Statistics
| Branch: | Revision:

root / tcg / arm / tcg-target.c @ e936243a

History | View | Annotate | Download (48.7 kB)

1
/*
2
 * Tiny Code Generator for QEMU
3
 *
4
 * Copyright (c) 2008 Andrzej Zaborowski
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
25
    "%r0",
26
    "%r1",
27
    "%r2",
28
    "%r3",
29
    "%r4",
30
    "%r5",
31
    "%r6",
32
    "%r7",
33
    "%r8",
34
    "%r9",
35
    "%r10",
36
    "%r11",
37
    "%r12",
38
    "%r13",
39
    "%r14",
40
};
41

    
42
int tcg_target_reg_alloc_order[] = {
43
    TCG_REG_R0,
44
    TCG_REG_R1,
45
    TCG_REG_R2,
46
    TCG_REG_R3,
47
    TCG_REG_R4,
48
    TCG_REG_R5,
49
    TCG_REG_R6,
50
    TCG_REG_R7,
51
    TCG_REG_R8,
52
    TCG_REG_R9,
53
    TCG_REG_R10,
54
    TCG_REG_R11,
55
    TCG_REG_R12,
56
    TCG_REG_R13,
57
    TCG_REG_R14,
58
};
59

    
60
const int tcg_target_call_iarg_regs[4] = {
61
    TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
62
};
63
const int tcg_target_call_oarg_regs[2] = {
64
    TCG_REG_R0, TCG_REG_R1
65
};
66

    
67
static void patch_reloc(uint8_t *code_ptr, int type,
68
                tcg_target_long value, tcg_target_long addend)
69
{
70
    switch (type) {
71
    case R_ARM_ABS32:
72
        *(uint32_t *) code_ptr = value;
73
        break;
74

    
75
    case R_ARM_CALL:
76
    case R_ARM_JUMP24:
77
    default:
78
        tcg_abort();
79

    
80
    case R_ARM_PC24:
81
        *(uint32_t *) code_ptr |= (*(uint32_t *) code_ptr & 0xff000000) |
82
                (((value - ((tcg_target_long) code_ptr + 8)) >> 2) & 0xffffff);
83
        break;
84
    }
85
}
86

    
87
/* maximum number of register used for input function arguments */
88
static inline int tcg_target_get_call_iarg_regs_count(int flags)
89
{
90
    return 4;
91
}
92

    
93
#define USE_TLB
94

    
95
/* parse target specific constraints */
96
int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
97
{
98
    const char *ct_str;
99

    
100
    ct_str = *pct_str;
101
    switch (ct_str[0]) {
102
    case 'r':
103
#ifndef CONFIG_SOFTMMU
104
    case 'd':
105
    case 'D':
106
    case 'x':
107
    case 'X':
108
#endif
109
        ct->ct |= TCG_CT_REG;
110
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
111
        break;
112

    
113
#ifdef CONFIG_SOFTMMU
114
    /* qemu_ld/st inputs (unless 'd', 'D' or 'X') */
115
    case 'x':
116
        ct->ct |= TCG_CT_REG;
117
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
118
# ifdef USE_TLB
119
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
120
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
121
# endif
122
        break;
123

    
124
    /* qemu_ld/st data_reg */
125
    case 'd':
126
        ct->ct |= TCG_CT_REG;
127
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
128
        /* r0 and optionally r1 will be overwritten by the address
129
         * so don't use these.  */
130
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
131
# if TARGET_LONG_BITS == 64 || defined(USE_TLB)
132
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
133
# endif
134
        break;
135

    
136
    /* qemu_ld/st64 data_reg2 */
137
    case 'D':
138
        ct->ct |= TCG_CT_REG;
139
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
140
        /* r0, r1 and optionally r2 will be overwritten by the address
141
         * and the low word of data, so don't use these.  */
142
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
143
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
144
# if TARGET_LONG_BITS == 64
145
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
146
# endif
147
        break;
148

    
149
# if TARGET_LONG_BITS == 64
150
    /* qemu_ld/st addr_reg2 */
151
    case 'X':
152
        ct->ct |= TCG_CT_REG;
153
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
154
        /* r0 will be overwritten by the low word of base, so don't use it.  */
155
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
156
#  ifdef USE_TLB
157
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
158
#  endif
159
        break;
160
# endif
161
#endif
162

    
163
    case '1':
164
        ct->ct |= TCG_CT_REG;
165
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
166
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
167
        break;
168

    
169
    case '2':
170
        ct->ct |= TCG_CT_REG;
171
        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
172
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
173
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
174
        break;
175

    
176
    default:
177
        return -1;
178
    }
179
    ct_str++;
180
    *pct_str = ct_str;
181

    
182
    return 0;
183
}
184

    
185
/* Test if a constant matches the constraint.
186
 * TODO: define constraints for:
187
 *
188
 * ldr/str offset:   between -0xfff and 0xfff
189
 * ldrh/strh offset: between -0xff and 0xff
190
 * mov operand2:     values represented with x << (2 * y), x < 0x100
191
 * add, sub, eor...: ditto
192
 */
193
static inline int tcg_target_const_match(tcg_target_long val,
194
                const TCGArgConstraint *arg_ct)
195
{
196
    int ct;
197
    ct = arg_ct->ct;
198
    if (ct & TCG_CT_CONST)
199
        return 1;
200
    else
201
        return 0;
202
}
203

    
204
enum arm_data_opc_e {
205
    ARITH_AND = 0x0,
206
    ARITH_EOR = 0x1,
207
    ARITH_SUB = 0x2,
208
    ARITH_RSB = 0x3,
209
    ARITH_ADD = 0x4,
210
    ARITH_ADC = 0x5,
211
    ARITH_SBC = 0x6,
212
    ARITH_RSC = 0x7,
213
    ARITH_CMP = 0xa,
214
    ARITH_CMN = 0xb,
215
    ARITH_ORR = 0xc,
216
    ARITH_MOV = 0xd,
217
    ARITH_BIC = 0xe,
218
    ARITH_MVN = 0xf,
219
};
220

    
221
#define TO_CPSR(opc)                ((opc == ARITH_CMP || opc == ARITH_CMN) << 20)
222

    
223
#define SHIFT_IMM_LSL(im)        (((im) << 7) | 0x00)
224
#define SHIFT_IMM_LSR(im)        (((im) << 7) | 0x20)
225
#define SHIFT_IMM_ASR(im)        (((im) << 7) | 0x40)
226
#define SHIFT_IMM_ROR(im)        (((im) << 7) | 0x60)
227
#define SHIFT_REG_LSL(rs)        (((rs) << 8) | 0x10)
228
#define SHIFT_REG_LSR(rs)        (((rs) << 8) | 0x30)
229
#define SHIFT_REG_ASR(rs)        (((rs) << 8) | 0x50)
230
#define SHIFT_REG_ROR(rs)        (((rs) << 8) | 0x70)
231

    
232
enum arm_cond_code_e {
233
    COND_EQ = 0x0,
234
    COND_NE = 0x1,
235
    COND_CS = 0x2,        /* Unsigned greater or equal */
236
    COND_CC = 0x3,        /* Unsigned less than */
237
    COND_MI = 0x4,        /* Negative */
238
    COND_PL = 0x5,        /* Zero or greater */
239
    COND_VS = 0x6,        /* Overflow */
240
    COND_VC = 0x7,        /* No overflow */
241
    COND_HI = 0x8,        /* Unsigned greater than */
242
    COND_LS = 0x9,        /* Unsigned less or equal */
243
    COND_GE = 0xa,
244
    COND_LT = 0xb,
245
    COND_GT = 0xc,
246
    COND_LE = 0xd,
247
    COND_AL = 0xe,
248
};
249

    
250
static const uint8_t tcg_cond_to_arm_cond[10] = {
251
    [TCG_COND_EQ] = COND_EQ,
252
    [TCG_COND_NE] = COND_NE,
253
    [TCG_COND_LT] = COND_LT,
254
    [TCG_COND_GE] = COND_GE,
255
    [TCG_COND_LE] = COND_LE,
256
    [TCG_COND_GT] = COND_GT,
257
    /* unsigned */
258
    [TCG_COND_LTU] = COND_CC,
259
    [TCG_COND_GEU] = COND_CS,
260
    [TCG_COND_LEU] = COND_LS,
261
    [TCG_COND_GTU] = COND_HI,
262
};
263

    
264
static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
265
{
266
    tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
267
}
268

    
269
static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
270
{
271
    tcg_out32(s, (cond << 28) | 0x0a000000 |
272
                    (((offset - 8) >> 2) & 0x00ffffff));
273
}
274

    
275
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
276
{
277
#ifdef WORDS_BIGENDIAN
278
    tcg_out8(s, (cond << 4) | 0x0a);
279
    s->code_ptr += 3;
280
#else
281
    s->code_ptr += 3;
282
    tcg_out8(s, (cond << 4) | 0x0a);
283
#endif
284
}
285

    
286
static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
287
{
288
    tcg_out32(s, (cond << 28) | 0x0b000000 |
289
                    (((offset - 8) >> 2) & 0x00ffffff));
290
}
291

    
292
static inline void tcg_out_dat_reg(TCGContext *s,
293
                int cond, int opc, int rd, int rn, int rm, int shift)
294
{
295
    tcg_out32(s, (cond << 28) | (0 << 25) | (opc << 21) | TO_CPSR(opc) |
296
                    (rn << 16) | (rd << 12) | shift | rm);
297
}
298

    
299
static inline void tcg_out_dat_reg2(TCGContext *s,
300
                int cond, int opc0, int opc1, int rd0, int rd1,
301
                int rn0, int rn1, int rm0, int rm1, int shift)
302
{
303
    tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
304
                    (rn0 << 16) | (rd0 << 12) | shift | rm0);
305
    tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
306
                    (rn1 << 16) | (rd1 << 12) | shift | rm1);
307
}
308

    
309
static inline void tcg_out_dat_imm(TCGContext *s,
310
                int cond, int opc, int rd, int rn, int im)
311
{
312
    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) |
313
                    (rn << 16) | (rd << 12) | im);
314
}
315

    
316
static inline void tcg_out_movi32(TCGContext *s,
317
                int cond, int rd, int32_t arg)
318
{
319
    int offset = (uint32_t) arg - ((uint32_t) s->code_ptr + 8);
320

    
321
    /* TODO: This is very suboptimal, we can easily have a constant
322
     * pool somewhere after all the instructions.  */
323

    
324
    if (arg < 0 && arg > -0x100)
325
        return tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
326

    
327
    if (offset < 0x100 && offset > -0x100)
328
        return offset >= 0 ?
329
                tcg_out_dat_imm(s, cond, ARITH_ADD, rd, 15, offset) :
330
                tcg_out_dat_imm(s, cond, ARITH_SUB, rd, 15, -offset);
331

    
332
    tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
333
    if (arg & 0x0000ff00)
334
        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
335
                        ((arg >>  8) & 0xff) | 0xc00);
336
    if (arg & 0x00ff0000)
337
        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
338
                        ((arg >> 16) & 0xff) | 0x800);
339
    if (arg & 0xff000000)
340
        tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
341
                        ((arg >> 24) & 0xff) | 0x400);
342
}
343

    
344
static inline void tcg_out_mul32(TCGContext *s,
345
                int cond, int rd, int rs, int rm)
346
{
347
    if (rd != rm)
348
        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
349
                        (rs << 8) | 0x90 | rm);
350
    else if (rd != rs)
351
        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
352
                        (rm << 8) | 0x90 | rs);
353
    else {
354
        tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
355
                        (rs << 8) | 0x90 | rm);
356
        tcg_out_dat_reg(s, cond, ARITH_MOV,
357
                        rd, 0, 8, SHIFT_IMM_LSL(0));
358
    }
359
}
360

    
361
static inline void tcg_out_umull32(TCGContext *s,
362
                int cond, int rd0, int rd1, int rs, int rm)
363
{
364
    if (rd0 != rm && rd1 != rm)
365
        tcg_out32(s, (cond << 28) | 0x800090 |
366
                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
367
    else if (rd0 != rs && rd1 != rs)
368
        tcg_out32(s, (cond << 28) | 0x800090 |
369
                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
370
    else {
371
        tcg_out_dat_reg(s, cond, ARITH_MOV,
372
                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
373
        tcg_out32(s, (cond << 28) | 0x800098 |
374
                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
375
    }
376
}
377

    
378
static inline void tcg_out_smull32(TCGContext *s,
379
                int cond, int rd0, int rd1, int rs, int rm)
380
{
381
    if (rd0 != rm && rd1 != rm)
382
        tcg_out32(s, (cond << 28) | 0xc00090 |
383
                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
384
    else if (rd0 != rs && rd1 != rs)
385
        tcg_out32(s, (cond << 28) | 0xc00090 |
386
                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
387
    else {
388
        tcg_out_dat_reg(s, cond, ARITH_MOV,
389
                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
390
        tcg_out32(s, (cond << 28) | 0xc00098 |
391
                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
392
    }
393
}
394

    
395
static inline void tcg_out_ld32_12(TCGContext *s, int cond,
396
                int rd, int rn, tcg_target_long im)
397
{
398
    if (im >= 0)
399
        tcg_out32(s, (cond << 28) | 0x05900000 |
400
                        (rn << 16) | (rd << 12) | (im & 0xfff));
401
    else
402
        tcg_out32(s, (cond << 28) | 0x05100000 |
403
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
404
}
405

    
406
static inline void tcg_out_st32_12(TCGContext *s, int cond,
407
                int rd, int rn, tcg_target_long im)
408
{
409
    if (im >= 0)
410
        tcg_out32(s, (cond << 28) | 0x05800000 |
411
                        (rn << 16) | (rd << 12) | (im & 0xfff));
412
    else
413
        tcg_out32(s, (cond << 28) | 0x05000000 |
414
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
415
}
416

    
417
static inline void tcg_out_ld32_r(TCGContext *s, int cond,
418
                int rd, int rn, int rm)
419
{
420
    tcg_out32(s, (cond << 28) | 0x07900000 |
421
                    (rn << 16) | (rd << 12) | rm);
422
}
423

    
424
static inline void tcg_out_st32_r(TCGContext *s, int cond,
425
                int rd, int rn, int rm)
426
{
427
    tcg_out32(s, (cond << 28) | 0x07800000 |
428
                    (rn << 16) | (rd << 12) | rm);
429
}
430

    
431
static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
432
                int rd, int rn, tcg_target_long im)
433
{
434
    if (im >= 0)
435
        tcg_out32(s, (cond << 28) | 0x01d000b0 |
436
                        (rn << 16) | (rd << 12) |
437
                        ((im & 0xf0) << 4) | (im & 0xf));
438
    else
439
        tcg_out32(s, (cond << 28) | 0x015000b0 |
440
                        (rn << 16) | (rd << 12) |
441
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
442
}
443

    
444
static inline void tcg_out_st16u_8(TCGContext *s, int cond,
445
                int rd, int rn, tcg_target_long im)
446
{
447
    if (im >= 0)
448
        tcg_out32(s, (cond << 28) | 0x01c000b0 |
449
                        (rn << 16) | (rd << 12) |
450
                        ((im & 0xf0) << 4) | (im & 0xf));
451
    else
452
        tcg_out32(s, (cond << 28) | 0x014000b0 |
453
                        (rn << 16) | (rd << 12) |
454
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
455
}
456

    
457
static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
458
                int rd, int rn, int rm)
459
{
460
    tcg_out32(s, (cond << 28) | 0x019000b0 |
461
                    (rn << 16) | (rd << 12) | rm);
462
}
463

    
464
static inline void tcg_out_st16u_r(TCGContext *s, int cond,
465
                int rd, int rn, int rm)
466
{
467
    tcg_out32(s, (cond << 28) | 0x018000b0 |
468
                    (rn << 16) | (rd << 12) | rm);
469
}
470

    
471
static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
472
                int rd, int rn, tcg_target_long im)
473
{
474
    if (im >= 0)
475
        tcg_out32(s, (cond << 28) | 0x01d000f0 |
476
                        (rn << 16) | (rd << 12) |
477
                        ((im & 0xf0) << 4) | (im & 0xf));
478
    else
479
        tcg_out32(s, (cond << 28) | 0x015000f0 |
480
                        (rn << 16) | (rd << 12) |
481
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
482
}
483

    
484
static inline void tcg_out_st16s_8(TCGContext *s, int cond,
485
                int rd, int rn, tcg_target_long im)
486
{
487
    if (im >= 0)
488
        tcg_out32(s, (cond << 28) | 0x01c000f0 |
489
                        (rn << 16) | (rd << 12) |
490
                        ((im & 0xf0) << 4) | (im & 0xf));
491
    else
492
        tcg_out32(s, (cond << 28) | 0x014000f0 |
493
                        (rn << 16) | (rd << 12) |
494
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
495
}
496

    
497
static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
498
                int rd, int rn, int rm)
499
{
500
    tcg_out32(s, (cond << 28) | 0x019000f0 |
501
                    (rn << 16) | (rd << 12) | rm);
502
}
503

    
504
static inline void tcg_out_st16s_r(TCGContext *s, int cond,
505
                int rd, int rn, int rm)
506
{
507
    tcg_out32(s, (cond << 28) | 0x018000f0 |
508
                    (rn << 16) | (rd << 12) | rm);
509
}
510

    
511
static inline void tcg_out_ld8_12(TCGContext *s, int cond,
512
                int rd, int rn, tcg_target_long im)
513
{
514
    if (im >= 0)
515
        tcg_out32(s, (cond << 28) | 0x05d00000 |
516
                        (rn << 16) | (rd << 12) | (im & 0xfff));
517
    else
518
        tcg_out32(s, (cond << 28) | 0x05500000 |
519
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
520
}
521

    
522
static inline void tcg_out_st8_12(TCGContext *s, int cond,
523
                int rd, int rn, tcg_target_long im)
524
{
525
    if (im >= 0)
526
        tcg_out32(s, (cond << 28) | 0x05c00000 |
527
                        (rn << 16) | (rd << 12) | (im & 0xfff));
528
    else
529
        tcg_out32(s, (cond << 28) | 0x05400000 |
530
                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
531
}
532

    
533
static inline void tcg_out_ld8_r(TCGContext *s, int cond,
534
                int rd, int rn, int rm)
535
{
536
    tcg_out32(s, (cond << 28) | 0x07d00000 |
537
                    (rn << 16) | (rd << 12) | rm);
538
}
539

    
540
static inline void tcg_out_st8_r(TCGContext *s, int cond,
541
                int rd, int rn, int rm)
542
{
543
    tcg_out32(s, (cond << 28) | 0x07c00000 |
544
                    (rn << 16) | (rd << 12) | rm);
545
}
546

    
547
static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
548
                int rd, int rn, tcg_target_long im)
549
{
550
    if (im >= 0)
551
        tcg_out32(s, (cond << 28) | 0x01d000d0 |
552
                        (rn << 16) | (rd << 12) |
553
                        ((im & 0xf0) << 4) | (im & 0xf));
554
    else
555
        tcg_out32(s, (cond << 28) | 0x015000d0 |
556
                        (rn << 16) | (rd << 12) |
557
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
558
}
559

    
560
static inline void tcg_out_st8s_8(TCGContext *s, int cond,
561
                int rd, int rn, tcg_target_long im)
562
{
563
    if (im >= 0)
564
        tcg_out32(s, (cond << 28) | 0x01c000d0 |
565
                        (rn << 16) | (rd << 12) |
566
                        ((im & 0xf0) << 4) | (im & 0xf));
567
    else
568
        tcg_out32(s, (cond << 28) | 0x014000d0 |
569
                        (rn << 16) | (rd << 12) |
570
                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
571
}
572

    
573
static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
574
                int rd, int rn, int rm)
575
{
576
    tcg_out32(s, (cond << 28) | 0x019000d0 |
577
                    (rn << 16) | (rd << 12) | rm);
578
}
579

    
580
static inline void tcg_out_st8s_r(TCGContext *s, int cond,
581
                int rd, int rn, int rm)
582
{
583
    tcg_out32(s, (cond << 28) | 0x018000d0 |
584
                    (rn << 16) | (rd << 12) | rm);
585
}
586

    
587
static inline void tcg_out_ld32u(TCGContext *s, int cond,
588
                int rd, int rn, int32_t offset)
589
{
590
    if (offset > 0xfff || offset < -0xfff) {
591
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
592
        tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
593
    } else
594
        tcg_out_ld32_12(s, cond, rd, rn, offset);
595
}
596

    
597
static inline void tcg_out_st32(TCGContext *s, int cond,
598
                int rd, int rn, int32_t offset)
599
{
600
    if (offset > 0xfff || offset < -0xfff) {
601
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
602
        tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
603
    } else
604
        tcg_out_st32_12(s, cond, rd, rn, offset);
605
}
606

    
607
static inline void tcg_out_ld16u(TCGContext *s, int cond,
608
                int rd, int rn, int32_t offset)
609
{
610
    if (offset > 0xff || offset < -0xff) {
611
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
612
        tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
613
    } else
614
        tcg_out_ld16u_8(s, cond, rd, rn, offset);
615
}
616

    
617
static inline void tcg_out_ld16s(TCGContext *s, int cond,
618
                int rd, int rn, int32_t offset)
619
{
620
    if (offset > 0xff || offset < -0xff) {
621
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
622
        tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
623
    } else
624
        tcg_out_ld16s_8(s, cond, rd, rn, offset);
625
}
626

    
627
static inline void tcg_out_st16u(TCGContext *s, int cond,
628
                int rd, int rn, int32_t offset)
629
{
630
    if (offset > 0xff || offset < -0xff) {
631
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
632
        tcg_out_st16u_r(s, cond, rd, rn, TCG_REG_R8);
633
    } else
634
        tcg_out_st16u_8(s, cond, rd, rn, offset);
635
}
636

    
637
static inline void tcg_out_ld8u(TCGContext *s, int cond,
638
                int rd, int rn, int32_t offset)
639
{
640
    if (offset > 0xfff || offset < -0xfff) {
641
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
642
        tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
643
    } else
644
        tcg_out_ld8_12(s, cond, rd, rn, offset);
645
}
646

    
647
static inline void tcg_out_ld8s(TCGContext *s, int cond,
648
                int rd, int rn, int32_t offset)
649
{
650
    if (offset > 0xff || offset < -0xff) {
651
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
652
        tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
653
    } else
654
        tcg_out_ld8s_8(s, cond, rd, rn, offset);
655
}
656

    
657
static inline void tcg_out_st8u(TCGContext *s, int cond,
658
                int rd, int rn, int32_t offset)
659
{
660
    if (offset > 0xfff || offset < -0xfff) {
661
        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
662
        tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
663
    } else
664
        tcg_out_st8_12(s, cond, rd, rn, offset);
665
}
666

    
667
static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
668
{
669
    int32_t val;
670

    
671
    val = addr - (tcg_target_long) s->code_ptr;
672
    if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
673
        tcg_out_b(s, cond, val);
674
    else {
675
#if 1
676
        tcg_abort();
677
#else
678
        if (cond == COND_AL) {
679
            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
680
            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
681
        } else {
682
            tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
683
            tcg_out_dat_reg(s, cond, ARITH_ADD,
684
                            15, 15, TCG_REG_R8, SHIFT_IMM_LSL(0));
685
        }
686
#endif
687
    }
688
}
689

    
690
static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
691
{
692
    int32_t val;
693

    
694
#ifdef SAVE_LR
695
    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R8, 0, 14, SHIFT_IMM_LSL(0));
696
#endif
697

    
698
    val = addr - (tcg_target_long) s->code_ptr;
699
    if (val < 0x01fffffd && val > -0x01fffffd)
700
        tcg_out_bl(s, cond, val);
701
    else {
702
#if 1
703
        tcg_abort();
704
#else
705
        if (cond == COND_AL) {
706
            tcg_out_dat_imm(s, cond, ARITH_ADD, 14, 15, 4);
707
            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
708
            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
709
        } else {
710
            tcg_out_movi32(s, cond, TCG_REG_R9, addr);
711
            tcg_out_dat_imm(s, cond, ARITH_MOV, 14, 0, 15);
712
            tcg_out_bx(s, cond, TCG_REG_R9);
713
        }
714
#endif
715
    }
716

    
717
#ifdef SAVE_LR
718
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
719
#endif
720
}
721

    
722
static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
723
{
724
#ifdef SAVE_LR
725
    tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R8, 0, 14, SHIFT_IMM_LSL(0));
726
#endif
727
    /* TODO: on ARMv5 and ARMv6 replace with tcg_out_blx(s, cond, arg);  */
728
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 15, SHIFT_IMM_LSL(0));
729
    tcg_out_bx(s, cond, arg);
730
#ifdef SAVE_LR
731
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
732
#endif
733
}
734

    
735
static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
736
{
737
    TCGLabel *l = &s->labels[label_index];
738

    
739
    if (l->has_value)
740
        tcg_out_goto(s, cond, l->u.value);
741
    else if (cond == COND_AL) {
742
        tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
743
        tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
744
        s->code_ptr += 4;
745
    } else {
746
        /* Probably this should be preferred even for COND_AL... */
747
        tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
748
        tcg_out_b_noaddr(s, cond);
749
    }
750
}
751

    
752
static void tcg_out_div_helper(TCGContext *s, int cond, const TCGArg *args,
753
                void *helper_div, void *helper_rem, int shift)
754
{
755
    int div_reg = args[0];
756
    int rem_reg = args[1];
757

    
758
    /* stmdb sp!, { r0 - r3, ip, lr } */
759
    /* (Note that we need an even number of registers as per EABI) */
760
    tcg_out32(s, (cond << 28) | 0x092d500f);
761

    
762
    tcg_out_dat_reg(s, cond, ARITH_MOV, 0, 0, args[2], SHIFT_IMM_LSL(0));
763
    tcg_out_dat_reg(s, cond, ARITH_MOV, 1, 0, args[3], SHIFT_IMM_LSL(0));
764
    tcg_out_dat_reg(s, cond, ARITH_MOV, 2, 0, args[4], SHIFT_IMM_LSL(0));
765
    tcg_out_dat_reg(s, cond, ARITH_MOV, 3, 0, 2, shift);
766

    
767
    tcg_out_call(s, cond, (uint32_t) helper_div);
768
    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 0, SHIFT_IMM_LSL(0));
769

    
770
    /* ldmia sp, { r0 - r3, fp, lr } */
771
    tcg_out32(s, (cond << 28) | 0x089d500f);
772

    
773
    tcg_out_dat_reg(s, cond, ARITH_MOV, 0, 0, args[2], SHIFT_IMM_LSL(0));
774
    tcg_out_dat_reg(s, cond, ARITH_MOV, 1, 0, args[3], SHIFT_IMM_LSL(0));
775
    tcg_out_dat_reg(s, cond, ARITH_MOV, 2, 0, args[4], SHIFT_IMM_LSL(0));
776
    tcg_out_dat_reg(s, cond, ARITH_MOV, 3, 0, 2, shift);
777

    
778
    tcg_out_call(s, cond, (uint32_t) helper_rem);
779

    
780
    tcg_out_dat_reg(s, cond, ARITH_MOV, rem_reg, 0, 0, SHIFT_IMM_LSL(0));
781
    tcg_out_dat_reg(s, cond, ARITH_MOV, div_reg, 0, 8, SHIFT_IMM_LSL(0));
782

    
783
    /* ldr r0, [sp], #4 */
784
    if (rem_reg != 0 && div_reg != 0)
785
        tcg_out32(s, (cond << 28) | 0x04bd0004);
786
    /* ldr r1, [sp], #4 */
787
    if (rem_reg != 1 && div_reg != 1)
788
        tcg_out32(s, (cond << 28) | 0x04bd1004);
789
    /* ldr r2, [sp], #4 */
790
    if (rem_reg != 2 && div_reg != 2)
791
        tcg_out32(s, (cond << 28) | 0x04bd2004);
792
    /* ldr r3, [sp], #4 */
793
    if (rem_reg != 3 && div_reg != 3)
794
        tcg_out32(s, (cond << 28) | 0x04bd3004);
795
    /* ldr ip, [sp], #4 */
796
    if (rem_reg != 12 && div_reg != 12)
797
        tcg_out32(s, (cond << 28) | 0x04bdc004);
798
    /* ldr lr, [sp], #4 */
799
    if (rem_reg != 14 && div_reg != 14)
800
        tcg_out32(s, (cond << 28) | 0x04bde004);
801
}
802

    
803
#ifdef CONFIG_SOFTMMU
804
extern void __ldb_mmu(void);
805
extern void __ldw_mmu(void);
806
extern void __ldl_mmu(void);
807
extern void __ldq_mmu(void);
808

    
809
extern void __stb_mmu(void);
810
extern void __stw_mmu(void);
811
extern void __stl_mmu(void);
812
extern void __stq_mmu(void);
813

    
814
static void *qemu_ld_helpers[4] = {
815
    __ldb_mmu,
816
    __ldw_mmu,
817
    __ldl_mmu,
818
    __ldq_mmu,
819
};
820

    
821
static void *qemu_st_helpers[4] = {
822
    __stb_mmu,
823
    __stw_mmu,
824
    __stl_mmu,
825
    __stq_mmu,
826
};
827
#endif
828

    
829
static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
830
                const TCGArg *args, int opc)
831
{
832
    int addr_reg, data_reg, data_reg2;
833
#ifdef CONFIG_SOFTMMU
834
    int mem_index, s_bits;
835
# if TARGET_LONG_BITS == 64
836
    int addr_reg2;
837
# endif
838
# ifdef USE_TLB
839
    uint32_t *label_ptr;
840
# endif
841
#endif
842

    
843
    data_reg = *args++;
844
    if (opc == 3)
845
        data_reg2 = *args++;
846
    else
847
        data_reg2 = 0; /* surpress warning */
848
    addr_reg = *args++;
849
#if TARGET_LONG_BITS == 64
850
    addr_reg2 = *args++;
851
#endif
852
#ifdef CONFIG_SOFTMMU
853
    mem_index = *args;
854
    s_bits = opc & 3;
855

    
856
# ifdef USE_TLB
857
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
858
                    8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS));
859
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
860
                    0, 8, CPU_TLB_SIZE - 1);
861
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
862
                    0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
863
#  define TLB_SHIFT        (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
864
    if (mem_index)
865
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
866
                        (mem_index << (TLB_SHIFT & 1)) |
867
                        ((16 - (TLB_SHIFT >> 1)) << 8));
868
    tcg_out_ld32_12(s, COND_AL, 1, 0,
869
                    offsetof(CPUState, tlb_table[0][0].addr_read));
870
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
871
                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
872
    /* TODO: alignment check?
873
     * if (s_bits)
874
     * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,
875
     *                  0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));
876
     */
877
#  if TARGET_LONG_BITS == 64
878
    /* XXX: possibly we could use a block data load or writeback in
879
     * the first access.  */
880
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
881
                    offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
882
    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
883
                    0, 1, addr_reg2, SHIFT_IMM_LSL(0));
884
#  endif
885
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
886
                    offsetof(CPUState, tlb_table[0][0].addend));
887

    
888
    switch (opc) {
889
    case 0:
890
        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, 1);
891
        break;
892
    case 0 | 4:
893
        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, 1);
894
        break;
895
    case 1:
896
        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, 1);
897
        break;
898
    case 1 | 4:
899
        tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, 1);
900
        break;
901
    case 2:
902
    default:
903
        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, 1);
904
        break;
905
    case 3:
906
        /* TODO: must write back */
907
        tcg_out_ld32_r(s, COND_EQ, data_reg, 1, addr_reg);
908
        tcg_out_ld32_12(s, COND_EQ, data_reg2, 1, 4);
909
        break;
910
    }
911

    
912
    label_ptr = (void *) s->code_ptr;
913
    tcg_out_b(s, COND_EQ, 8);
914
# endif
915

    
916
# ifdef SAVE_LR
917
    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
918
# endif
919

    
920
    /* TODO: move this code to where the constants pool will be */
921
    if (addr_reg)
922
        tcg_out_dat_reg(s, cond, ARITH_MOV,
923
                        0, 0, addr_reg, SHIFT_IMM_LSL(0));
924
# if TARGET_LONG_BITS == 32
925
    tcg_out_dat_imm(s, cond, ARITH_MOV, 1, 0, mem_index);
926
# else
927
    if (addr_reg2 != 1)
928
        tcg_out_dat_reg(s, cond, ARITH_MOV,
929
                        1, 0, addr_reg2, SHIFT_IMM_LSL(0));
930
    tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
931
# endif
932
    tcg_out_bl(s, cond, (tcg_target_long) qemu_ld_helpers[s_bits] -
933
                    (tcg_target_long) s->code_ptr);
934

    
935
    switch (opc) {
936
    case 0 | 4:
937
        tcg_out_dat_reg(s, cond, ARITH_MOV,
938
                        0, 0, 0, SHIFT_IMM_LSL(24));
939
        tcg_out_dat_reg(s, cond, ARITH_MOV,
940
                        data_reg, 0, 0, SHIFT_IMM_ASR(24));
941
        break;
942
    case 1 | 4:
943
        tcg_out_dat_reg(s, cond, ARITH_MOV,
944
                        0, 0, 0, SHIFT_IMM_LSL(16));
945
        tcg_out_dat_reg(s, cond, ARITH_MOV,
946
                        data_reg, 0, 0, SHIFT_IMM_ASR(16));
947
        break;
948
    case 0:
949
    case 1:
950
    case 2:
951
    default:
952
        if (data_reg)
953
            tcg_out_dat_reg(s, cond, ARITH_MOV,
954
                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
955
        break;
956
    case 3:
957
        if (data_reg2 != 1)
958
            tcg_out_dat_reg(s, cond, ARITH_MOV,
959
                            data_reg2, 0, 1, SHIFT_IMM_LSL(0));
960
        if (data_reg != 0)
961
            tcg_out_dat_reg(s, cond, ARITH_MOV,
962
                            data_reg, 0, 0, SHIFT_IMM_LSL(0));
963
        break;
964
    }
965

    
966
# ifdef SAVE_LR
967
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
968
# endif
969

    
970
# ifdef USE_TLB
971
    *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
972
# endif
973
#else
974
    switch (opc) {
975
    case 0:
976
        tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
977
        break;
978
    case 0 | 4:
979
        tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
980
        break;
981
    case 1:
982
        tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
983
        break;
984
    case 1 | 4:
985
        tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
986
        break;
987
    case 2:
988
    default:
989
        tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
990
        break;
991
    case 3:
992
        /* TODO: use block load */
993
        tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
994
        tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
995
        break;
996
    }
997
#endif
998
}
999

    
1000
static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1001
                const TCGArg *args, int opc)
1002
{
1003
    int addr_reg, data_reg, data_reg2;
1004
#ifdef CONFIG_SOFTMMU
1005
    int mem_index, s_bits;
1006
# if TARGET_LONG_BITS == 64
1007
    int addr_reg2;
1008
# endif
1009
# ifdef USE_TLB
1010
    uint32_t *label_ptr;
1011
# endif
1012
#endif
1013

    
1014
    data_reg = *args++;
1015
    if (opc == 3)
1016
        data_reg2 = *args++;
1017
    else
1018
        data_reg2 = 0; /* surpress warning */
1019
    addr_reg = *args++;
1020
#if TARGET_LONG_BITS == 64
1021
    addr_reg2 = *args++;
1022
#endif
1023
#ifdef CONFIG_SOFTMMU
1024
    mem_index = *args;
1025
    s_bits = opc & 3;
1026

    
1027
# ifdef USE_TLB
1028
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1029
                    8, 0, addr_reg, SHIFT_IMM_ROR(TARGET_PAGE_BITS));
1030
    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1031
                    0, 8, CPU_TLB_SIZE - 1);
1032
    tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
1033
                    0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1034
    if (mem_index)
1035
        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
1036
                        (mem_index << (TLB_SHIFT & 1)) |
1037
                        ((16 - (TLB_SHIFT >> 1)) << 8));
1038
    tcg_out_ld32_12(s, COND_AL, 1, 0,
1039
                    offsetof(CPUState, tlb_table[0][0].addr_write));
1040
    tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
1041
                    0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1042
    /* TODO: alignment check?
1043
     * if (s_bits)
1044
     * tcg_out_data_reg(s, COND_EQ, ARITH_EOR,
1045
     *                  0, 1, 8, SHIFT_IMM_LSR(32 - s_bits));
1046
     */
1047
#  if TARGET_LONG_BITS == 64
1048
    /* XXX: possibly we could use a block data load or writeback in
1049
     * the first access.  */
1050
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
1051
                    offsetof(CPUState, tlb_table[0][0].addr_write)
1052
                    + 4);
1053
    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
1054
                    0, 1, addr_reg2, SHIFT_IMM_LSL(0));
1055
#  endif
1056
    tcg_out_ld32_12(s, COND_EQ, 1, 0,
1057
                    offsetof(CPUState, tlb_table[0][0].addend));
1058

    
1059
    switch (opc) {
1060
    case 0:
1061
        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, 1);
1062
        break;
1063
    case 0 | 4:
1064
        tcg_out_st8s_r(s, COND_EQ, data_reg, addr_reg, 1);
1065
        break;
1066
    case 1:
1067
        tcg_out_st16u_r(s, COND_EQ, data_reg, addr_reg, 1);
1068
        break;
1069
    case 1 | 4:
1070
        tcg_out_st16s_r(s, COND_EQ, data_reg, addr_reg, 1);
1071
        break;
1072
    case 2:
1073
    default:
1074
        tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
1075
        break;
1076
    case 3:
1077
        /* TODO: must write back */
1078
        tcg_out_st32_r(s, COND_EQ, data_reg, 1, addr_reg);
1079
        tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
1080
        break;
1081
    }
1082

    
1083
    label_ptr = (void *) s->code_ptr;
1084
    tcg_out_b(s, COND_EQ, 8);
1085
# endif
1086

    
1087
# ifdef SAVE_LR
1088
    tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
1089
# endif
1090

    
1091
    /* TODO: move this code to where the constants pool will be */
1092
    if (addr_reg)
1093
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1094
                        0, 0, addr_reg, SHIFT_IMM_LSL(0));
1095
# if TARGET_LONG_BITS == 32
1096
    switch (opc) {
1097
    case 0:
1098
        tcg_out_dat_imm(s, cond, ARITH_AND, 1, data_reg, 0xff);
1099
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1100
        break;
1101
    case 1:
1102
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1103
                        1, 0, data_reg, SHIFT_IMM_LSL(16));
1104
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1105
                        1, 0, 1, SHIFT_IMM_LSR(16));
1106
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1107
        break;
1108
    case 2:
1109
        if (data_reg != 1)
1110
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1111
                            1, 0, data_reg, SHIFT_IMM_LSL(0));
1112
        tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
1113
        break;
1114
    case 3:
1115
        if (data_reg != 1)
1116
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1117
                            1, 0, data_reg, SHIFT_IMM_LSL(0));
1118
        if (data_reg2 != 2)
1119
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1120
                            2, 0, data_reg2, SHIFT_IMM_LSL(0));
1121
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1122
        break;
1123
    }
1124
# else
1125
    if (addr_reg2 != 1)
1126
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1127
                        1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1128
    switch (opc) {
1129
    case 0:
1130
        tcg_out_dat_imm(s, cond, ARITH_AND, 2, data_reg, 0xff);
1131
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1132
        break;
1133
    case 1:
1134
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1135
                        2, 0, data_reg, SHIFT_IMM_LSL(16));
1136
        tcg_out_dat_reg(s, cond, ARITH_MOV,
1137
                        2, 0, 2, SHIFT_IMM_LSR(16));
1138
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1139
        break;
1140
    case 2:
1141
        if (data_reg != 2)
1142
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1143
                            2, 0, data_reg, SHIFT_IMM_LSL(0));
1144
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1145
        break;
1146
    case 3:
1147
        tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
1148
        tcg_out32(s, (cond << 28) | 0x052d3010); /* str r3, [sp, #-0x10]! */
1149
        if (data_reg != 2)
1150
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1151
                            2, 0, data_reg, SHIFT_IMM_LSL(0));
1152
        if (data_reg2 != 3)
1153
            tcg_out_dat_reg(s, cond, ARITH_MOV,
1154
                            3, 0, data_reg2, SHIFT_IMM_LSL(0));
1155
        break;
1156
    }
1157
# endif
1158

    
1159
    tcg_out_bl(s, cond, (tcg_target_long) qemu_st_helpers[s_bits] -
1160
                    (tcg_target_long) s->code_ptr);
1161

    
1162
# if TARGET_LONG_BITS == 64
1163
    if (opc == 3)
1164
        tcg_out_dat_imm(s, cond, ARITH_ADD, 13, 13, 0x10);
1165
# endif
1166

    
1167
# ifdef SAVE_LR
1168
    tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
1169
# endif
1170

    
1171
# ifdef USE_TLB
1172
    *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
1173
# endif
1174
#else
1175
    switch (opc) {
1176
    case 0:
1177
        tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1178
        break;
1179
    case 0 | 4:
1180
        tcg_out_st8s_8(s, COND_AL, data_reg, addr_reg, 0);
1181
        break;
1182
    case 1:
1183
        tcg_out_st16u_8(s, COND_AL, data_reg, addr_reg, 0);
1184
        break;
1185
    case 1 | 4:
1186
        tcg_out_st16s_8(s, COND_AL, data_reg, addr_reg, 0);
1187
        break;
1188
    case 2:
1189
    default:
1190
        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1191
        break;
1192
    case 3:
1193
        /* TODO: use block store */
1194
        tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1195
        tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1196
        break;
1197
    }
1198
#endif
1199
}
1200

    
1201
static uint8_t *tb_ret_addr;
1202

    
1203
static inline void tcg_out_op(TCGContext *s, int opc,
1204
                const TCGArg *args, const int *const_args)
1205
{
1206
    int c;
1207

    
1208
    switch (opc) {
1209
    case INDEX_op_exit_tb:
1210
#ifdef SAVE_LR
1211
        if (args[0] >> 8)
1212
            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
1213
        else
1214
            tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1215
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 15, 0, 14, SHIFT_IMM_LSL(0));
1216
        if (args[0] >> 8)
1217
            tcg_out32(s, args[0]);
1218
#else
1219
        if (args[0] >> 8)
1220
            tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
1221
        else
1222
            tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
1223
        tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1224
        if (args[0] >> 8)
1225
            tcg_out32(s, args[0]);
1226
#endif
1227
        break;
1228
    case INDEX_op_goto_tb:
1229
        if (s->tb_jmp_offset) {
1230
            /* Direct jump method */
1231
#if 1
1232
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1233
            tcg_out_b(s, COND_AL, 8);
1234
#else
1235
            tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
1236
            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1237
            tcg_out32(s, 0);
1238
#endif
1239
        } else {
1240
            /* Indirect jump method */
1241
#if 1
1242
            c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1243
            if (c > 0xfff || c < -0xfff) {
1244
                tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1245
                                (tcg_target_long) (s->tb_next + args[0]));
1246
                tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
1247
            } else
1248
                tcg_out_ld32_12(s, COND_AL, 15, 15, c);
1249
#else
1250
            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
1251
            tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
1252
            tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1253
#endif
1254
        }
1255
        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1256
        break;
1257
    case INDEX_op_call:
1258
        if (const_args[0])
1259
            tcg_out_call(s, COND_AL, args[0]);
1260
        else
1261
            tcg_out_callr(s, COND_AL, args[0]);
1262
        break;
1263
    case INDEX_op_jmp:
1264
        if (const_args[0])
1265
            tcg_out_goto(s, COND_AL, args[0]);
1266
        else
1267
            tcg_out_bx(s, COND_AL, args[0]);
1268
        break;
1269
    case INDEX_op_br:
1270
        tcg_out_goto_label(s, COND_AL, args[0]);
1271
        break;
1272

    
1273
    case INDEX_op_ld8u_i32:
1274
        tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1275
        break;
1276
    case INDEX_op_ld8s_i32:
1277
        tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1278
        break;
1279
    case INDEX_op_ld16u_i32:
1280
        tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1281
        break;
1282
    case INDEX_op_ld16s_i32:
1283
        tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1284
        break;
1285
    case INDEX_op_ld_i32:
1286
        tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1287
        break;
1288
    case INDEX_op_st8_i32:
1289
        tcg_out_st8u(s, COND_AL, args[0], args[1], args[2]);
1290
        break;
1291
    case INDEX_op_st16_i32:
1292
        tcg_out_st16u(s, COND_AL, args[0], args[1], args[2]);
1293
        break;
1294
    case INDEX_op_st_i32:
1295
        tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1296
        break;
1297

    
1298
    case INDEX_op_mov_i32:
1299
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1300
                        args[0], 0, args[1], SHIFT_IMM_LSL(0));
1301
        break;
1302
    case INDEX_op_movi_i32:
1303
        tcg_out_movi32(s, COND_AL, args[0], args[1]);
1304
        break;
1305
    case INDEX_op_add_i32:
1306
        c = ARITH_ADD;
1307
        goto gen_arith;
1308
    case INDEX_op_sub_i32:
1309
        c = ARITH_SUB;
1310
        goto gen_arith;
1311
    case INDEX_op_and_i32:
1312
        c = ARITH_AND;
1313
        goto gen_arith;
1314
    case INDEX_op_or_i32:
1315
        c = ARITH_ORR;
1316
        goto gen_arith;
1317
    case INDEX_op_xor_i32:
1318
        c = ARITH_EOR;
1319
        /* Fall through.  */
1320
    gen_arith:
1321
        tcg_out_dat_reg(s, COND_AL, c,
1322
                        args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1323
        break;
1324
    case INDEX_op_add2_i32:
1325
        tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
1326
                        args[0], args[1], args[2], args[3],
1327
                        args[4], args[5], SHIFT_IMM_LSL(0));
1328
        break;
1329
    case INDEX_op_sub2_i32:
1330
        tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
1331
                        args[0], args[1], args[2], args[3],
1332
                        args[4], args[5], SHIFT_IMM_LSL(0));
1333
        break;
1334
    case INDEX_op_neg_i32:
1335
        tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1336
        break;
1337
    case INDEX_op_mul_i32:
1338
        tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1339
        break;
1340
    case INDEX_op_mulu2_i32:
1341
        tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1342
        break;
1343
    case INDEX_op_div2_i32:
1344
        tcg_out_div_helper(s, COND_AL, args,
1345
                        tcg_helper_div_i64, tcg_helper_rem_i64,
1346
                        SHIFT_IMM_ASR(31));
1347
        break;
1348
    case INDEX_op_divu2_i32:
1349
        tcg_out_div_helper(s, COND_AL, args,
1350
                        tcg_helper_divu_i64, tcg_helper_remu_i64,
1351
                        SHIFT_IMM_LSR(31));
1352
        break;
1353
    /* XXX: Perhaps args[2] & 0x1f is wrong */
1354
    case INDEX_op_shl_i32:
1355
        c = const_args[2] ?
1356
                SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1357
        goto gen_shift32;
1358
    case INDEX_op_shr_i32:
1359
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1360
                SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1361
        goto gen_shift32;
1362
    case INDEX_op_sar_i32:
1363
        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1364
                SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1365
        /* Fall through.  */
1366
    gen_shift32:
1367
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1368
        break;
1369

    
1370
    case INDEX_op_brcond_i32:
1371
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1372
                        args[0], args[1], SHIFT_IMM_LSL(0));
1373
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1374
        break;
1375
    case INDEX_op_brcond2_i32:
1376
        /* The resulting conditions are:
1377
         * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
1378
         * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
1379
         * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
1380
         * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1381
         * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1382
         * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
1383
         */
1384
        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1385
                        args[1], args[3], SHIFT_IMM_LSL(0));
1386
        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1387
                        args[0], args[2], SHIFT_IMM_LSL(0));
1388
        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1389
        break;
1390

    
1391
    case INDEX_op_qemu_ld8u:
1392
        tcg_out_qemu_ld(s, COND_AL, args, 0);
1393
        break;
1394
    case INDEX_op_qemu_ld8s:
1395
        tcg_out_qemu_ld(s, COND_AL, args, 0 | 4);
1396
        break;
1397
    case INDEX_op_qemu_ld16u:
1398
        tcg_out_qemu_ld(s, COND_AL, args, 1);
1399
        break;
1400
    case INDEX_op_qemu_ld16s:
1401
        tcg_out_qemu_ld(s, COND_AL, args, 1 | 4);
1402
        break;
1403
    case INDEX_op_qemu_ld32u:
1404
        tcg_out_qemu_ld(s, COND_AL, args, 2);
1405
        break;
1406
    case INDEX_op_qemu_ld64:
1407
        tcg_out_qemu_ld(s, COND_AL, args, 3);
1408
        break;
1409

    
1410
    case INDEX_op_qemu_st8:
1411
        tcg_out_qemu_st(s, COND_AL, args, 0);
1412
        break;
1413
    case INDEX_op_qemu_st16:
1414
        tcg_out_qemu_st(s, COND_AL, args, 1);
1415
        break;
1416
    case INDEX_op_qemu_st32:
1417
        tcg_out_qemu_st(s, COND_AL, args, 2);
1418
        break;
1419
    case INDEX_op_qemu_st64:
1420
        tcg_out_qemu_st(s, COND_AL, args, 3);
1421
        break;
1422

    
1423
    case INDEX_op_ext8s_i32:
1424
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1425
                        args[0], 0, args[1], SHIFT_IMM_LSL(24));
1426
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1427
                        args[0], 0, args[0], SHIFT_IMM_ASR(24));
1428
        break;
1429
    case INDEX_op_ext16s_i32:
1430
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1431
                        args[0], 0, args[1], SHIFT_IMM_LSL(16));
1432
        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1433
                        args[0], 0, args[0], SHIFT_IMM_ASR(16));
1434
        break;
1435

    
1436
    default:
1437
        tcg_abort();
1438
    }
1439
}
1440

    
1441
static const TCGTargetOpDef arm_op_defs[] = {
1442
    { INDEX_op_exit_tb, { } },
1443
    { INDEX_op_goto_tb, { } },
1444
    { INDEX_op_call, { "ri" } },
1445
    { INDEX_op_jmp, { "ri" } },
1446
    { INDEX_op_br, { } },
1447

    
1448
    { INDEX_op_mov_i32, { "r", "r" } },
1449
    { INDEX_op_movi_i32, { "r" } },
1450

    
1451
    { INDEX_op_ld8u_i32, { "r", "r" } },
1452
    { INDEX_op_ld8s_i32, { "r", "r" } },
1453
    { INDEX_op_ld16u_i32, { "r", "r" } },
1454
    { INDEX_op_ld16s_i32, { "r", "r" } },
1455
    { INDEX_op_ld_i32, { "r", "r" } },
1456
    { INDEX_op_st8_i32, { "r", "r" } },
1457
    { INDEX_op_st16_i32, { "r", "r" } },
1458
    { INDEX_op_st_i32, { "r", "r" } },
1459

    
1460
    /* TODO: "r", "r", "ri" */
1461
    { INDEX_op_add_i32, { "r", "r", "r" } },
1462
    { INDEX_op_sub_i32, { "r", "r", "r" } },
1463
    { INDEX_op_mul_i32, { "r", "r", "r" } },
1464
    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1465
    { INDEX_op_div2_i32, { "r", "r", "r", "1", "2" } },
1466
    { INDEX_op_divu2_i32, { "r", "r", "r", "1", "2" } },
1467
    { INDEX_op_and_i32, { "r", "r", "r" } },
1468
    { INDEX_op_or_i32, { "r", "r", "r" } },
1469
    { INDEX_op_xor_i32, { "r", "r", "r" } },
1470
    { INDEX_op_neg_i32, { "r", "r" } },
1471

    
1472
    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1473
    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1474
    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1475

    
1476
    { INDEX_op_brcond_i32, { "r", "r" } },
1477

    
1478
    /* TODO: "r", "r", "r", "r", "ri", "ri" */
1479
    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1480
    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1481
    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1482

    
1483
    { INDEX_op_qemu_ld8u, { "r", "x", "X" } },
1484
    { INDEX_op_qemu_ld8s, { "r", "x", "X" } },
1485
    { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
1486
    { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
1487
    { INDEX_op_qemu_ld32u, { "r", "x", "X" } },
1488
    { INDEX_op_qemu_ld64, { "r", "d", "x", "X" } },
1489

    
1490
    { INDEX_op_qemu_st8, { "d", "x", "X" } },
1491
    { INDEX_op_qemu_st16, { "d", "x", "X" } },
1492
    { INDEX_op_qemu_st32, { "d", "x", "X" } },
1493
    { INDEX_op_qemu_st64, { "d", "D", "x", "X" } },
1494

    
1495
    { INDEX_op_ext8s_i32, { "r", "r" } },
1496
    { INDEX_op_ext16s_i32, { "r", "r" } },
1497

    
1498
    { -1 },
1499
};
1500

    
1501
void tcg_target_init(TCGContext *s)
1502
{
1503
    /* fail safe */
1504
    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1505
        tcg_abort();
1506

    
1507
    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
1508
                    ((2 << TCG_REG_R14) - 1) & ~(1 << TCG_REG_R8));
1509
    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1510
                    ((2 << TCG_REG_R3) - 1) |
1511
                    (1 << TCG_REG_R12) | (1 << TCG_REG_R14));
1512

    
1513
    tcg_regset_clear(s->reserved_regs);
1514
#ifdef SAVE_LR
1515
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R14);
1516
#endif
1517
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1518
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1519

    
1520
    tcg_add_target_add_op_defs(arm_op_defs);
1521
}
1522

    
1523
static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
1524
                int arg1, tcg_target_long arg2)
1525
{
1526
    tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
1527
}
1528

    
1529
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
1530
                int arg1, tcg_target_long arg2)
1531
{
1532
    tcg_out_st32(s, COND_AL, arg, arg1, arg2);
1533
}
1534

    
1535
void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
1536
{
1537
    if (val > 0)
1538
        if (val < 0x100)
1539
            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
1540
        else
1541
            tcg_abort();
1542
    else if (val < 0) {
1543
        if (val > -0x100)
1544
            tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
1545
        else
1546
            tcg_abort();
1547
    }
1548
}
1549

    
1550
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
1551
{
1552
    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
1553
}
1554

    
1555
static inline void tcg_out_movi(TCGContext *s, TCGType type,
1556
                int ret, tcg_target_long arg)
1557
{
1558
    tcg_out_movi32(s, COND_AL, ret, arg);
1559
}
1560

    
1561
void tcg_target_qemu_prologue(TCGContext *s)
1562
{
1563
    /* stmdb sp!, { r9 - r11, lr } */
1564
    tcg_out32(s, (COND_AL << 28) | 0x092d4e00);
1565

    
1566
    tcg_out_bx(s, COND_AL, TCG_REG_R0);
1567
    tb_ret_addr = s->code_ptr;
1568

    
1569
    /* ldmia sp!, { r9 - r11, pc } */
1570
    tcg_out32(s, (COND_AL << 28) | 0x08bd8e00);
1571
}