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
25#if defined(__ARM_ARCH_7__) ||  \
26    defined(__ARM_ARCH_7A__) || \
27    defined(__ARM_ARCH_7EM__) || \
28    defined(__ARM_ARCH_7M__) || \
29    defined(__ARM_ARCH_7R__)
30#define USE_ARMV7_INSTRUCTIONS
31#endif
32
33#if defined(USE_ARMV7_INSTRUCTIONS) || \
34    defined(__ARM_ARCH_6J__) || \
35    defined(__ARM_ARCH_6K__) || \
36    defined(__ARM_ARCH_6T2__) || \
37    defined(__ARM_ARCH_6Z__) || \
38    defined(__ARM_ARCH_6ZK__)
39#define USE_ARMV6_INSTRUCTIONS
40#endif
41
42#if defined(USE_ARMV6_INSTRUCTIONS) || \
43    defined(__ARM_ARCH_5T__) || \
44    defined(__ARM_ARCH_5TE__) || \
45    defined(__ARM_ARCH_5TEJ__)
46#define USE_ARMV5_INSTRUCTIONS
47#endif
48
49#ifdef USE_ARMV5_INSTRUCTIONS
50static const int use_armv5_instructions = 1;
51#else
52static const int use_armv5_instructions = 0;
53#endif
54#undef USE_ARMV5_INSTRUCTIONS
55
56#ifdef USE_ARMV6_INSTRUCTIONS
57static const int use_armv6_instructions = 1;
58#else
59static const int use_armv6_instructions = 0;
60#endif
61#undef USE_ARMV6_INSTRUCTIONS
62
63#ifdef USE_ARMV7_INSTRUCTIONS
64static const int use_armv7_instructions = 1;
65#else
66static const int use_armv7_instructions = 0;
67#endif
68#undef USE_ARMV7_INSTRUCTIONS
69
70#ifndef NDEBUG
71static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
72    "%r0",
73    "%r1",
74    "%r2",
75    "%r3",
76    "%r4",
77    "%r5",
78    "%r6",
79    "%r7",
80    "%r8",
81    "%r9",
82    "%r10",
83    "%r11",
84    "%r12",
85    "%r13",
86    "%r14",
87    "%pc",
88};
89#endif
90
91static const int tcg_target_reg_alloc_order[] = {
92    TCG_REG_R4,
93    TCG_REG_R5,
94    TCG_REG_R6,
95    TCG_REG_R7,
96    TCG_REG_R8,
97    TCG_REG_R9,
98    TCG_REG_R10,
99    TCG_REG_R11,
100    TCG_REG_R13,
101    TCG_REG_R0,
102    TCG_REG_R1,
103    TCG_REG_R2,
104    TCG_REG_R3,
105    TCG_REG_R12,
106    TCG_REG_R14,
107};
108
109static const int tcg_target_call_iarg_regs[4] = {
110    TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
111};
112static const int tcg_target_call_oarg_regs[2] = {
113    TCG_REG_R0, TCG_REG_R1
114};
115
116static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
117{
118    *(uint32_t *) code_ptr = target;
119}
120
121static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
122{
123    uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
124
125    *(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
126                             | (offset & 0xffffff);
127}
128
129static void patch_reloc(uint8_t *code_ptr, int type,
130                tcg_target_long value, tcg_target_long addend)
131{
132    switch (type) {
133    case R_ARM_ABS32:
134        reloc_abs32(code_ptr, value);
135        break;
136
137    case R_ARM_CALL:
138    case R_ARM_JUMP24:
139    default:
140        tcg_abort();
141
142    case R_ARM_PC24:
143        reloc_pc24(code_ptr, value);
144        break;
145    }
146}
147
148/* maximum number of register used for input function arguments */
149static inline int tcg_target_get_call_iarg_regs_count(int flags)
150{
151    return 4;
152}
153
154/* parse target specific constraints */
155static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
156{
157    const char *ct_str;
158
159    ct_str = *pct_str;
160    switch (ct_str[0]) {
161    case 'I':
162         ct->ct |= TCG_CT_CONST_ARM;
163         break;
164
165    case 'r':
166        ct->ct |= TCG_CT_REG;
167        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
168        break;
169
170    /* qemu_ld address */
171    case 'l':
172        ct->ct |= TCG_CT_REG;
173        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
174#ifdef CONFIG_SOFTMMU
175        /* r0 and r1 will be overwritten when reading the tlb entry,
176           so don't use these. */
177        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
178        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
179#endif
180        break;
181    case 'L':
182        ct->ct |= TCG_CT_REG;
183        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
184#ifdef CONFIG_SOFTMMU
185        /* r1 is still needed to load data_reg or data_reg2,
186           so don't use it. */
187        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
188#endif
189        break;
190
191    /* qemu_st address & data_reg */
192    case 's':
193        ct->ct |= TCG_CT_REG;
194        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
195        /* r0 and r1 will be overwritten when reading the tlb entry
196           (softmmu only) and doing the byte swapping, so don't
197           use these. */
198        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
199        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
200        break;
201    /* qemu_st64 data_reg2 */
202    case 'S':
203        ct->ct |= TCG_CT_REG;
204        tcg_regset_set32(ct->u.regs, 0, (1 << TCG_TARGET_NB_REGS) - 1);
205        /* r0 and r1 will be overwritten when reading the tlb entry
206            (softmmu only) and doing the byte swapping, so don't
207            use these. */
208        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
209        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
210#ifdef CONFIG_SOFTMMU
211        /* r2 is still needed to load data_reg, so don't use it. */
212        tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
213#endif
214        break;
215
216    default:
217        return -1;
218    }
219    ct_str++;
220    *pct_str = ct_str;
221
222    return 0;
223}
224
225static inline uint32_t rotl(uint32_t val, int n)
226{
227  return (val << n) | (val >> (32 - n));
228}
229
230/* ARM immediates for ALU instructions are made of an unsigned 8-bit
231   right-rotated by an even amount between 0 and 30. */
232static inline int encode_imm(uint32_t imm)
233{
234    int shift;
235
236    /* simple case, only lower bits */
237    if ((imm & ~0xff) == 0)
238        return 0;
239    /* then try a simple even shift */
240    shift = ctz32(imm) & ~1;
241    if (((imm >> shift) & ~0xff) == 0)
242        return 32 - shift;
243    /* now try harder with rotations */
244    if ((rotl(imm, 2) & ~0xff) == 0)
245        return 2;
246    if ((rotl(imm, 4) & ~0xff) == 0)
247        return 4;
248    if ((rotl(imm, 6) & ~0xff) == 0)
249        return 6;
250    /* imm can't be encoded */
251    return -1;
252}
253
254static inline int check_fit_imm(uint32_t imm)
255{
256    return encode_imm(imm) >= 0;
257}
258
259/* Test if a constant matches the constraint.
260 * TODO: define constraints for:
261 *
262 * ldr/str offset:   between -0xfff and 0xfff
263 * ldrh/strh offset: between -0xff and 0xff
264 * mov operand2:     values represented with x << (2 * y), x < 0x100
265 * add, sub, eor...: ditto
266 */
267static inline int tcg_target_const_match(tcg_target_long val,
268                const TCGArgConstraint *arg_ct)
269{
270    int ct;
271    ct = arg_ct->ct;
272    if (ct & TCG_CT_CONST)
273        return 1;
274    else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val))
275        return 1;
276    else
277        return 0;
278}
279
280enum arm_data_opc_e {
281    ARITH_AND = 0x0,
282    ARITH_EOR = 0x1,
283    ARITH_SUB = 0x2,
284    ARITH_RSB = 0x3,
285    ARITH_ADD = 0x4,
286    ARITH_ADC = 0x5,
287    ARITH_SBC = 0x6,
288    ARITH_RSC = 0x7,
289    ARITH_TST = 0x8,
290    ARITH_CMP = 0xa,
291    ARITH_CMN = 0xb,
292    ARITH_ORR = 0xc,
293    ARITH_MOV = 0xd,
294    ARITH_BIC = 0xe,
295    ARITH_MVN = 0xf,
296};
297
298#define TO_CPSR(opc) \
299  ((opc == ARITH_CMP || opc == ARITH_CMN || opc == ARITH_TST) << 20)
300
301#define SHIFT_IMM_LSL(im)	(((im) << 7) | 0x00)
302#define SHIFT_IMM_LSR(im)	(((im) << 7) | 0x20)
303#define SHIFT_IMM_ASR(im)	(((im) << 7) | 0x40)
304#define SHIFT_IMM_ROR(im)	(((im) << 7) | 0x60)
305#define SHIFT_REG_LSL(rs)	(((rs) << 8) | 0x10)
306#define SHIFT_REG_LSR(rs)	(((rs) << 8) | 0x30)
307#define SHIFT_REG_ASR(rs)	(((rs) << 8) | 0x50)
308#define SHIFT_REG_ROR(rs)	(((rs) << 8) | 0x70)
309
310enum arm_cond_code_e {
311    COND_EQ = 0x0,
312    COND_NE = 0x1,
313    COND_CS = 0x2,	/* Unsigned greater or equal */
314    COND_CC = 0x3,	/* Unsigned less than */
315    COND_MI = 0x4,	/* Negative */
316    COND_PL = 0x5,	/* Zero or greater */
317    COND_VS = 0x6,	/* Overflow */
318    COND_VC = 0x7,	/* No overflow */
319    COND_HI = 0x8,	/* Unsigned greater than */
320    COND_LS = 0x9,	/* Unsigned less or equal */
321    COND_GE = 0xa,
322    COND_LT = 0xb,
323    COND_GT = 0xc,
324    COND_LE = 0xd,
325    COND_AL = 0xe,
326};
327
328static const uint8_t tcg_cond_to_arm_cond[10] = {
329    [TCG_COND_EQ] = COND_EQ,
330    [TCG_COND_NE] = COND_NE,
331    [TCG_COND_LT] = COND_LT,
332    [TCG_COND_GE] = COND_GE,
333    [TCG_COND_LE] = COND_LE,
334    [TCG_COND_GT] = COND_GT,
335    /* unsigned */
336    [TCG_COND_LTU] = COND_CC,
337    [TCG_COND_GEU] = COND_CS,
338    [TCG_COND_LEU] = COND_LS,
339    [TCG_COND_GTU] = COND_HI,
340};
341
342static inline void tcg_out_bx(TCGContext *s, int cond, int rn)
343{
344    tcg_out32(s, (cond << 28) | 0x012fff10 | rn);
345}
346
347static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
348{
349    tcg_out32(s, (cond << 28) | 0x0a000000 |
350                    (((offset - 8) >> 2) & 0x00ffffff));
351}
352
353static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
354{
355    /* We pay attention here to not modify the branch target by skipping
356       the corresponding bytes. This ensure that caches and memory are
357       kept coherent during retranslation. */
358#ifdef HOST_WORDS_BIGENDIAN
359    tcg_out8(s, (cond << 4) | 0x0a);
360    s->code_ptr += 3;
361#else
362    s->code_ptr += 3;
363    tcg_out8(s, (cond << 4) | 0x0a);
364#endif
365}
366
367static inline void tcg_out_bl(TCGContext *s, int cond, int32_t offset)
368{
369    tcg_out32(s, (cond << 28) | 0x0b000000 |
370                    (((offset - 8) >> 2) & 0x00ffffff));
371}
372
373static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
374{
375    tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
376}
377
378static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
379{
380    tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
381                (((offset - 8) >> 2) & 0x00ffffff));
382}
383
384static inline void tcg_out_dat_reg(TCGContext *s,
385                int cond, int opc, int rd, int rn, int rm, int shift)
386{
387    tcg_out32(s, (cond << 28) | (0 << 25) | (opc << 21) | TO_CPSR(opc) |
388                    (rn << 16) | (rd << 12) | shift | rm);
389}
390
391static inline void tcg_out_dat_reg2(TCGContext *s,
392                int cond, int opc0, int opc1, int rd0, int rd1,
393                int rn0, int rn1, int rm0, int rm1, int shift)
394{
395    if (rd0 == rn1 || rd0 == rm1) {
396        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
397                        (rn0 << 16) | (8 << 12) | shift | rm0);
398        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
399                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
400        tcg_out_dat_reg(s, cond, ARITH_MOV,
401                        rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
402    } else {
403        tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
404                        (rn0 << 16) | (rd0 << 12) | shift | rm0);
405        tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
406                        (rn1 << 16) | (rd1 << 12) | shift | rm1);
407    }
408}
409
410static inline void tcg_out_dat_imm(TCGContext *s,
411                int cond, int opc, int rd, int rn, int im)
412{
413    tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
414                    (rn << 16) | (rd << 12) | im);
415}
416
417static inline void tcg_out_movi32(TCGContext *s,
418                int cond, int rd, uint32_t arg)
419{
420    /* TODO: This is very suboptimal, we can easily have a constant
421     * pool somewhere after all the instructions.  */
422    if ((int)arg < 0 && (int)arg >= -0x100) {
423        tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
424    } else if (use_armv7_instructions) {
425        /* use movw/movt */
426        /* movw */
427        tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
428                  | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
429        if (arg & 0xffff0000) {
430            /* movt */
431            tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
432                      | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
433        }
434    } else {
435        int opc = ARITH_MOV;
436        int rn = 0;
437
438        do {
439            int i, rot;
440
441            i = ctz32(arg) & ~1;
442            rot = ((32 - i) << 7) & 0xf00;
443            tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
444            arg &= ~(0xff << i);
445
446            opc = ARITH_ORR;
447            rn = rd;
448        } while (arg);
449    }
450}
451
452static inline void tcg_out_mul32(TCGContext *s,
453                int cond, int rd, int rs, int rm)
454{
455    if (rd != rm)
456        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
457                        (rs << 8) | 0x90 | rm);
458    else if (rd != rs)
459        tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
460                        (rm << 8) | 0x90 | rs);
461    else {
462        tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
463                        (rs << 8) | 0x90 | rm);
464        tcg_out_dat_reg(s, cond, ARITH_MOV,
465                        rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
466    }
467}
468
469static inline void tcg_out_umull32(TCGContext *s,
470                int cond, int rd0, int rd1, int rs, int rm)
471{
472    if (rd0 != rm && rd1 != rm)
473        tcg_out32(s, (cond << 28) | 0x800090 |
474                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
475    else if (rd0 != rs && rd1 != rs)
476        tcg_out32(s, (cond << 28) | 0x800090 |
477                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
478    else {
479        tcg_out_dat_reg(s, cond, ARITH_MOV,
480                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
481        tcg_out32(s, (cond << 28) | 0x800098 |
482                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
483    }
484}
485
486static inline void tcg_out_smull32(TCGContext *s,
487                int cond, int rd0, int rd1, int rs, int rm)
488{
489    if (rd0 != rm && rd1 != rm)
490        tcg_out32(s, (cond << 28) | 0xc00090 |
491                        (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
492    else if (rd0 != rs && rd1 != rs)
493        tcg_out32(s, (cond << 28) | 0xc00090 |
494                        (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
495    else {
496        tcg_out_dat_reg(s, cond, ARITH_MOV,
497                        TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
498        tcg_out32(s, (cond << 28) | 0xc00098 |
499                        (rd1 << 16) | (rd0 << 12) | (rs << 8));
500    }
501}
502
503static inline void tcg_out_ext8s(TCGContext *s, int cond,
504                                 int rd, int rn)
505{
506    if (use_armv6_instructions) {
507        /* sxtb */
508        tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
509    } else {
510        tcg_out_dat_reg(s, cond, ARITH_MOV,
511                        rd, 0, rn, SHIFT_IMM_LSL(24));
512        tcg_out_dat_reg(s, cond, ARITH_MOV,
513                        rd, 0, rd, SHIFT_IMM_ASR(24));
514    }
515}
516
517static inline void tcg_out_ext8u(TCGContext *s, int cond,
518                                 int rd, int rn)
519{
520    tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
521}
522
523static inline void tcg_out_ext16s(TCGContext *s, int cond,
524                                  int rd, int rn)
525{
526    if (use_armv6_instructions) {
527        /* sxth */
528        tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
529    } else {
530        tcg_out_dat_reg(s, cond, ARITH_MOV,
531                        rd, 0, rn, SHIFT_IMM_LSL(16));
532        tcg_out_dat_reg(s, cond, ARITH_MOV,
533                        rd, 0, rd, SHIFT_IMM_ASR(16));
534    }
535}
536
537static inline void tcg_out_ext16u(TCGContext *s, int cond,
538                                  int rd, int rn)
539{
540    if (use_armv6_instructions) {
541        /* uxth */
542        tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
543    } else {
544        tcg_out_dat_reg(s, cond, ARITH_MOV,
545                        rd, 0, rn, SHIFT_IMM_LSL(16));
546        tcg_out_dat_reg(s, cond, ARITH_MOV,
547                        rd, 0, rd, SHIFT_IMM_LSR(16));
548    }
549}
550
551static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
552{
553    if (use_armv6_instructions) {
554        /* revsh */
555        tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
556    } else {
557        tcg_out_dat_reg(s, cond, ARITH_MOV,
558                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
559        tcg_out_dat_reg(s, cond, ARITH_MOV,
560                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
561        tcg_out_dat_reg(s, cond, ARITH_ORR,
562                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
563    }
564}
565
566static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
567{
568    if (use_armv6_instructions) {
569        /* rev16 */
570        tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
571    } else {
572        tcg_out_dat_reg(s, cond, ARITH_MOV,
573                        TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
574        tcg_out_dat_reg(s, cond, ARITH_MOV,
575                        TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
576        tcg_out_dat_reg(s, cond, ARITH_ORR,
577                        rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
578    }
579}
580
581static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
582{
583    if (use_armv6_instructions) {
584        /* rev */
585        tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
586    } else {
587        tcg_out_dat_reg(s, cond, ARITH_EOR,
588                        TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
589        tcg_out_dat_imm(s, cond, ARITH_BIC,
590                        TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
591        tcg_out_dat_reg(s, cond, ARITH_MOV,
592                        rd, 0, rn, SHIFT_IMM_ROR(8));
593        tcg_out_dat_reg(s, cond, ARITH_EOR,
594                        rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
595    }
596}
597
598static inline void tcg_out_ld32_12(TCGContext *s, int cond,
599                int rd, int rn, tcg_target_long im)
600{
601    if (im >= 0)
602        tcg_out32(s, (cond << 28) | 0x05900000 |
603                        (rn << 16) | (rd << 12) | (im & 0xfff));
604    else
605        tcg_out32(s, (cond << 28) | 0x05100000 |
606                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
607}
608
609static inline void tcg_out_st32_12(TCGContext *s, int cond,
610                int rd, int rn, tcg_target_long im)
611{
612    if (im >= 0)
613        tcg_out32(s, (cond << 28) | 0x05800000 |
614                        (rn << 16) | (rd << 12) | (im & 0xfff));
615    else
616        tcg_out32(s, (cond << 28) | 0x05000000 |
617                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
618}
619
620static inline void tcg_out_ld32_r(TCGContext *s, int cond,
621                int rd, int rn, int rm)
622{
623    tcg_out32(s, (cond << 28) | 0x07900000 |
624                    (rn << 16) | (rd << 12) | rm);
625}
626
627static inline void tcg_out_st32_r(TCGContext *s, int cond,
628                int rd, int rn, int rm)
629{
630    tcg_out32(s, (cond << 28) | 0x07800000 |
631                    (rn << 16) | (rd << 12) | rm);
632}
633
634/* Register pre-increment with base writeback.  */
635static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
636                int rd, int rn, int rm)
637{
638    tcg_out32(s, (cond << 28) | 0x07b00000 |
639                    (rn << 16) | (rd << 12) | rm);
640}
641
642static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
643                int rd, int rn, int rm)
644{
645    tcg_out32(s, (cond << 28) | 0x07a00000 |
646                    (rn << 16) | (rd << 12) | rm);
647}
648
649static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
650                int rd, int rn, tcg_target_long im)
651{
652    if (im >= 0)
653        tcg_out32(s, (cond << 28) | 0x01d000b0 |
654                        (rn << 16) | (rd << 12) |
655                        ((im & 0xf0) << 4) | (im & 0xf));
656    else
657        tcg_out32(s, (cond << 28) | 0x015000b0 |
658                        (rn << 16) | (rd << 12) |
659                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
660}
661
662static inline void tcg_out_st16_8(TCGContext *s, int cond,
663                int rd, int rn, tcg_target_long im)
664{
665    if (im >= 0)
666        tcg_out32(s, (cond << 28) | 0x01c000b0 |
667                        (rn << 16) | (rd << 12) |
668                        ((im & 0xf0) << 4) | (im & 0xf));
669    else
670        tcg_out32(s, (cond << 28) | 0x014000b0 |
671                        (rn << 16) | (rd << 12) |
672                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
673}
674
675static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
676                int rd, int rn, int rm)
677{
678    tcg_out32(s, (cond << 28) | 0x019000b0 |
679                    (rn << 16) | (rd << 12) | rm);
680}
681
682static inline void tcg_out_st16_r(TCGContext *s, int cond,
683                int rd, int rn, int rm)
684{
685    tcg_out32(s, (cond << 28) | 0x018000b0 |
686                    (rn << 16) | (rd << 12) | rm);
687}
688
689static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
690                int rd, int rn, tcg_target_long im)
691{
692    if (im >= 0)
693        tcg_out32(s, (cond << 28) | 0x01d000f0 |
694                        (rn << 16) | (rd << 12) |
695                        ((im & 0xf0) << 4) | (im & 0xf));
696    else
697        tcg_out32(s, (cond << 28) | 0x015000f0 |
698                        (rn << 16) | (rd << 12) |
699                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
700}
701
702static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
703                int rd, int rn, int rm)
704{
705    tcg_out32(s, (cond << 28) | 0x019000f0 |
706                    (rn << 16) | (rd << 12) | rm);
707}
708
709static inline void tcg_out_ld8_12(TCGContext *s, int cond,
710                int rd, int rn, tcg_target_long im)
711{
712    if (im >= 0)
713        tcg_out32(s, (cond << 28) | 0x05d00000 |
714                        (rn << 16) | (rd << 12) | (im & 0xfff));
715    else
716        tcg_out32(s, (cond << 28) | 0x05500000 |
717                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
718}
719
720static inline void tcg_out_st8_12(TCGContext *s, int cond,
721                int rd, int rn, tcg_target_long im)
722{
723    if (im >= 0)
724        tcg_out32(s, (cond << 28) | 0x05c00000 |
725                        (rn << 16) | (rd << 12) | (im & 0xfff));
726    else
727        tcg_out32(s, (cond << 28) | 0x05400000 |
728                        (rn << 16) | (rd << 12) | ((-im) & 0xfff));
729}
730
731static inline void tcg_out_ld8_r(TCGContext *s, int cond,
732                int rd, int rn, int rm)
733{
734    tcg_out32(s, (cond << 28) | 0x07d00000 |
735                    (rn << 16) | (rd << 12) | rm);
736}
737
738static inline void tcg_out_st8_r(TCGContext *s, int cond,
739                int rd, int rn, int rm)
740{
741    tcg_out32(s, (cond << 28) | 0x07c00000 |
742                    (rn << 16) | (rd << 12) | rm);
743}
744
745static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
746                int rd, int rn, tcg_target_long im)
747{
748    if (im >= 0)
749        tcg_out32(s, (cond << 28) | 0x01d000d0 |
750                        (rn << 16) | (rd << 12) |
751                        ((im & 0xf0) << 4) | (im & 0xf));
752    else
753        tcg_out32(s, (cond << 28) | 0x015000d0 |
754                        (rn << 16) | (rd << 12) |
755                        (((-im) & 0xf0) << 4) | ((-im) & 0xf));
756}
757
758static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
759                int rd, int rn, int rm)
760{
761    tcg_out32(s, (cond << 28) | 0x019000d0 |
762                    (rn << 16) | (rd << 12) | rm);
763}
764
765static inline void tcg_out_ld32u(TCGContext *s, int cond,
766                int rd, int rn, int32_t offset)
767{
768    if (offset > 0xfff || offset < -0xfff) {
769        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
770        tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
771    } else
772        tcg_out_ld32_12(s, cond, rd, rn, offset);
773}
774
775static inline void tcg_out_st32(TCGContext *s, int cond,
776                int rd, int rn, int32_t offset)
777{
778    if (offset > 0xfff || offset < -0xfff) {
779        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
780        tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
781    } else
782        tcg_out_st32_12(s, cond, rd, rn, offset);
783}
784
785static inline void tcg_out_ld16u(TCGContext *s, int cond,
786                int rd, int rn, int32_t offset)
787{
788    if (offset > 0xff || offset < -0xff) {
789        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
790        tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
791    } else
792        tcg_out_ld16u_8(s, cond, rd, rn, offset);
793}
794
795static inline void tcg_out_ld16s(TCGContext *s, int cond,
796                int rd, int rn, int32_t offset)
797{
798    if (offset > 0xff || offset < -0xff) {
799        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
800        tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
801    } else
802        tcg_out_ld16s_8(s, cond, rd, rn, offset);
803}
804
805static inline void tcg_out_st16(TCGContext *s, int cond,
806                int rd, int rn, int32_t offset)
807{
808    if (offset > 0xff || offset < -0xff) {
809        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
810        tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
811    } else
812        tcg_out_st16_8(s, cond, rd, rn, offset);
813}
814
815static inline void tcg_out_ld8u(TCGContext *s, int cond,
816                int rd, int rn, int32_t offset)
817{
818    if (offset > 0xfff || offset < -0xfff) {
819        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
820        tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
821    } else
822        tcg_out_ld8_12(s, cond, rd, rn, offset);
823}
824
825static inline void tcg_out_ld8s(TCGContext *s, int cond,
826                int rd, int rn, int32_t offset)
827{
828    if (offset > 0xff || offset < -0xff) {
829        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
830        tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
831    } else
832        tcg_out_ld8s_8(s, cond, rd, rn, offset);
833}
834
835static inline void tcg_out_st8(TCGContext *s, int cond,
836                int rd, int rn, int32_t offset)
837{
838    if (offset > 0xfff || offset < -0xfff) {
839        tcg_out_movi32(s, cond, TCG_REG_R8, offset);
840        tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
841    } else
842        tcg_out_st8_12(s, cond, rd, rn, offset);
843}
844
845static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
846{
847    int32_t val;
848
849    if (addr & 1) {
850        /* goto to a Thumb destination isn't supported */
851        tcg_abort();
852    }
853
854    val = addr - (tcg_target_long) s->code_ptr;
855    if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
856        tcg_out_b(s, cond, val);
857    else {
858#if 1
859        tcg_abort();
860#else
861        if (cond == COND_AL) {
862            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
863            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
864        } else {
865            tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
866            tcg_out_dat_reg(s, cond, ARITH_ADD,
867                            TCG_REG_PC, TCG_REG_PC,
868                            TCG_REG_R8, SHIFT_IMM_LSL(0));
869        }
870#endif
871    }
872}
873
874static inline void tcg_out_call(TCGContext *s, uint32_t addr)
875{
876    int32_t val;
877
878    val = addr - (tcg_target_long) s->code_ptr;
879    if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
880        if (addr & 1) {
881            /* Use BLX if the target is in Thumb mode */
882            if (!use_armv5_instructions) {
883                tcg_abort();
884            }
885            tcg_out_blx_imm(s, val);
886        } else {
887            tcg_out_bl(s, COND_AL, val);
888        }
889    } else {
890#if 1
891        tcg_abort();
892#else
893        if (cond == COND_AL) {
894            tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
895            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
896            tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
897        } else {
898            tcg_out_movi32(s, cond, TCG_REG_R9, addr);
899            tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
900                            TCG_REG_PC, SHIFT_IMM_LSL(0));
901            tcg_out_bx(s, cond, TCG_REG_R9);
902        }
903#endif
904    }
905}
906
907static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
908{
909    if (use_armv5_instructions) {
910        tcg_out_blx(s, cond, arg);
911    } else {
912        tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
913                        TCG_REG_PC, SHIFT_IMM_LSL(0));
914        tcg_out_bx(s, cond, arg);
915    }
916}
917
918static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
919{
920    TCGLabel *l = &s->labels[label_index];
921
922    if (l->has_value)
923        tcg_out_goto(s, cond, l->u.value);
924    else if (cond == COND_AL) {
925        tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
926        tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
927        s->code_ptr += 4;
928    } else {
929        /* Probably this should be preferred even for COND_AL... */
930        tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
931        tcg_out_b_noaddr(s, cond);
932    }
933}
934
935#ifdef CONFIG_SOFTMMU
936
937#include "../../softmmu_defs.h"
938
939static void *qemu_ld_helpers[4] = {
940    __ldb_mmu,
941    __ldw_mmu,
942    __ldl_mmu,
943    __ldq_mmu,
944};
945
946static void *qemu_st_helpers[4] = {
947    __stb_mmu,
948    __stw_mmu,
949    __stl_mmu,
950    __stq_mmu,
951};
952#endif
953
954#define TLB_SHIFT	(CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
955
956static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
957{
958    int addr_reg, data_reg, data_reg2, bswap;
959#ifdef CONFIG_SOFTMMU
960    int mem_index, s_bits;
961# if TARGET_LONG_BITS == 64
962    int addr_reg2;
963# endif
964    uint32_t *label_ptr;
965#endif
966
967#ifdef TARGET_WORDS_BIGENDIAN
968    bswap = 1;
969#else
970    bswap = 0;
971#endif
972    data_reg = *args++;
973    if (opc == 3)
974        data_reg2 = *args++;
975    else
976        data_reg2 = 0; /* suppress warning */
977    addr_reg = *args++;
978#ifdef CONFIG_SOFTMMU
979# if TARGET_LONG_BITS == 64
980    addr_reg2 = *args++;
981# endif
982    mem_index = *args;
983    s_bits = opc & 3;
984
985    /* Should generate something like the following:
986     *  shr r8, addr_reg, #TARGET_PAGE_BITS
987     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
988     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
989     */
990#  if CPU_TLB_BITS > 8
991#   error
992#  endif
993    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
994                    0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
995    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
996                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
997    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
998                    TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
999    /* In the
1000     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
1001     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
1002     * not exceed otherwise, so use an
1003     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
1004     * before.
1005     */
1006    if (mem_index)
1007        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1008                        (mem_index << (TLB_SHIFT & 1)) |
1009                        ((16 - (TLB_SHIFT >> 1)) << 8));
1010    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1011                    offsetof(CPUState, tlb_table[0][0].addr_read));
1012    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1013                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1014    /* Check alignment.  */
1015    if (s_bits)
1016        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1017                        0, addr_reg, (1 << s_bits) - 1);
1018#  if TARGET_LONG_BITS == 64
1019    /* XXX: possibly we could use a block data load or writeback in
1020     * the first access.  */
1021    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1022                    offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
1023    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1024                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1025#  endif
1026    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1027                    offsetof(CPUState, tlb_table[0][0].addend));
1028
1029    switch (opc) {
1030    case 0:
1031        tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1032        break;
1033    case 0 | 4:
1034        tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1035        break;
1036    case 1:
1037        tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1038        if (bswap) {
1039            tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
1040        }
1041        break;
1042    case 1 | 4:
1043        if (bswap) {
1044            tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1045            tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
1046        } else {
1047            tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1048        }
1049        break;
1050    case 2:
1051    default:
1052        tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1053        if (bswap) {
1054            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1055        }
1056        break;
1057    case 3:
1058        if (bswap) {
1059            tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
1060            tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
1061            tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
1062            tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
1063        } else {
1064            tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1065            tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1066        }
1067        break;
1068    }
1069
1070    label_ptr = (void *) s->code_ptr;
1071    tcg_out_b_noaddr(s, COND_EQ);
1072
1073    /* TODO: move this code to where the constants pool will be */
1074    if (addr_reg != TCG_REG_R0) {
1075        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1076                        TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1077    }
1078# if TARGET_LONG_BITS == 32
1079    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
1080# else
1081    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1082                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1083    tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1084# endif
1085    tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
1086
1087    switch (opc) {
1088    case 0 | 4:
1089        tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1090        break;
1091    case 1 | 4:
1092        tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1093        break;
1094    case 0:
1095    case 1:
1096    case 2:
1097    default:
1098        if (data_reg != TCG_REG_R0) {
1099            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1100                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
1101        }
1102        break;
1103    case 3:
1104        if (data_reg != TCG_REG_R0) {
1105            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1106                            data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
1107        }
1108        if (data_reg2 != TCG_REG_R1) {
1109            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1110                            data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
1111        }
1112        break;
1113    }
1114
1115    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1116#else /* !CONFIG_SOFTMMU */
1117    if (GUEST_BASE) {
1118        uint32_t offset = GUEST_BASE;
1119        int i;
1120        int rot;
1121
1122        while (offset) {
1123            i = ctz32(offset) & ~1;
1124            rot = ((32 - i) << 7) & 0xf00;
1125
1126            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
1127                            ((offset >> i) & 0xff) | rot);
1128            addr_reg = TCG_REG_R8;
1129            offset &= ~(0xff << i);
1130        }
1131    }
1132    switch (opc) {
1133    case 0:
1134        tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
1135        break;
1136    case 0 | 4:
1137        tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
1138        break;
1139    case 1:
1140        tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1141        if (bswap) {
1142            tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
1143        }
1144        break;
1145    case 1 | 4:
1146        if (bswap) {
1147            tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1148            tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
1149        } else {
1150            tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
1151        }
1152        break;
1153    case 2:
1154    default:
1155        tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1156        if (bswap) {
1157            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1158        }
1159        break;
1160    case 3:
1161        /* TODO: use block load -
1162         * check that data_reg2 > data_reg or the other way */
1163        if (data_reg == addr_reg) {
1164            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1165            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1166        } else {
1167            tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1168            tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
1169        }
1170        if (bswap) {
1171            tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
1172            tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1173        }
1174        break;
1175    }
1176#endif
1177}
1178
1179static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1180{
1181    int addr_reg, data_reg, data_reg2, bswap;
1182#ifdef CONFIG_SOFTMMU
1183    int mem_index, s_bits;
1184# if TARGET_LONG_BITS == 64
1185    int addr_reg2;
1186# endif
1187    uint32_t *label_ptr;
1188#endif
1189
1190#ifdef TARGET_WORDS_BIGENDIAN
1191    bswap = 1;
1192#else
1193    bswap = 0;
1194#endif
1195    data_reg = *args++;
1196    if (opc == 3)
1197        data_reg2 = *args++;
1198    else
1199        data_reg2 = 0; /* suppress warning */
1200    addr_reg = *args++;
1201#ifdef CONFIG_SOFTMMU
1202# if TARGET_LONG_BITS == 64
1203    addr_reg2 = *args++;
1204# endif
1205    mem_index = *args;
1206    s_bits = opc & 3;
1207
1208    /* Should generate something like the following:
1209     *  shr r8, addr_reg, #TARGET_PAGE_BITS
1210     *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
1211     *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
1212     */
1213    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1214                    TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1215    tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1216                    TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
1217    tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
1218                    TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1219    /* In the
1220     *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
1221     * below, the offset is likely to exceed 12 bits if mem_index != 0 and
1222     * not exceed otherwise, so use an
1223     *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
1224     * before.
1225     */
1226    if (mem_index)
1227        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1228                        (mem_index << (TLB_SHIFT & 1)) |
1229                        ((16 - (TLB_SHIFT >> 1)) << 8));
1230    tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1231                    offsetof(CPUState, tlb_table[0][0].addr_write));
1232    tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
1233                    TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1234    /* Check alignment.  */
1235    if (s_bits)
1236        tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
1237                        0, addr_reg, (1 << s_bits) - 1);
1238#  if TARGET_LONG_BITS == 64
1239    /* XXX: possibly we could use a block data load or writeback in
1240     * the first access.  */
1241    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1242                    offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
1243    tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1244                    TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1245#  endif
1246    tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1247                    offsetof(CPUState, tlb_table[0][0].addend));
1248
1249    switch (opc) {
1250    case 0:
1251        tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1252        break;
1253    case 1:
1254        if (bswap) {
1255            tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
1256            tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1257        } else {
1258            tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1259        }
1260        break;
1261    case 2:
1262    default:
1263        if (bswap) {
1264            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1265            tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
1266        } else {
1267            tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1268        }
1269        break;
1270    case 3:
1271        if (bswap) {
1272            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
1273            tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
1274            tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1275            tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
1276        } else {
1277            tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
1278            tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
1279        }
1280        break;
1281    }
1282
1283    label_ptr = (void *) s->code_ptr;
1284    tcg_out_b_noaddr(s, COND_EQ);
1285
1286    /* TODO: move this code to where the constants pool will be */
1287    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1288                    TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1289# if TARGET_LONG_BITS == 32
1290    switch (opc) {
1291    case 0:
1292        tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
1293        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1294        break;
1295    case 1:
1296        tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
1297        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1298        break;
1299    case 2:
1300        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1301                        TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
1302        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1303        break;
1304    case 3:
1305        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
1306        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
1307        if (data_reg != TCG_REG_R2) {
1308            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1309                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1310        }
1311        if (data_reg2 != TCG_REG_R3) {
1312            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1313                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
1314        }
1315        break;
1316    }
1317# else
1318    tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1319                    TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1320    switch (opc) {
1321    case 0:
1322        tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
1323        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1324        break;
1325    case 1:
1326        tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
1327        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1328        break;
1329    case 2:
1330        if (data_reg != TCG_REG_R2) {
1331            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1332                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1333        }
1334        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1335        break;
1336    case 3:
1337        tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
1338        tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
1339        if (data_reg != TCG_REG_R2) {
1340            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1341                            TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
1342        }
1343        if (data_reg2 != TCG_REG_R3) {
1344            tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1345                            TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
1346        }
1347        break;
1348    }
1349# endif
1350
1351    tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
1352    if (opc == 3)
1353        tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
1354
1355    reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1356#else /* !CONFIG_SOFTMMU */
1357    if (GUEST_BASE) {
1358        uint32_t offset = GUEST_BASE;
1359        int i;
1360        int rot;
1361
1362        while (offset) {
1363            i = ctz32(offset) & ~1;
1364            rot = ((32 - i) << 7) & 0xf00;
1365
1366            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1367                            ((offset >> i) & 0xff) | rot);
1368            addr_reg = TCG_REG_R1;
1369            offset &= ~(0xff << i);
1370        }
1371    }
1372    switch (opc) {
1373    case 0:
1374        tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
1375        break;
1376    case 1:
1377        if (bswap) {
1378            tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
1379            tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1380        } else {
1381            tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
1382        }
1383        break;
1384    case 2:
1385    default:
1386        if (bswap) {
1387            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1388            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1389        } else {
1390            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1391        }
1392        break;
1393    case 3:
1394        /* TODO: use block store -
1395         * check that data_reg2 > data_reg or the other way */
1396        if (bswap) {
1397            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
1398            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
1399            tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
1400            tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
1401        } else {
1402            tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
1403            tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
1404        }
1405        break;
1406    }
1407#endif
1408}
1409
1410static uint8_t *tb_ret_addr;
1411
1412static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1413                const TCGArg *args, const int *const_args)
1414{
1415    int c;
1416
1417    switch (opc) {
1418    case INDEX_op_exit_tb:
1419        {
1420            uint8_t *ld_ptr = s->code_ptr;
1421            if (args[0] >> 8)
1422                tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1423            else
1424                tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1425            tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
1426            if (args[0] >> 8) {
1427                *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
1428                tcg_out32(s, args[0]);
1429            }
1430        }
1431        break;
1432    case INDEX_op_goto_tb:
1433        if (s->tb_jmp_offset) {
1434            /* Direct jump method */
1435#if defined(USE_DIRECT_JUMP)
1436            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1437            tcg_out_b_noaddr(s, COND_AL);
1438#else
1439            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1440            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1441            tcg_out32(s, 0);
1442#endif
1443        } else {
1444            /* Indirect jump method */
1445#if 1
1446            c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
1447            if (c > 0xfff || c < -0xfff) {
1448                tcg_out_movi32(s, COND_AL, TCG_REG_R0,
1449                                (tcg_target_long) (s->tb_next + args[0]));
1450                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1451            } else
1452                tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1453#else
1454            tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1455            tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1456            tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
1457#endif
1458        }
1459        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
1460        break;
1461    case INDEX_op_call:
1462        if (const_args[0])
1463            tcg_out_call(s, args[0]);
1464        else
1465            tcg_out_callr(s, COND_AL, args[0]);
1466        break;
1467    case INDEX_op_jmp:
1468        if (const_args[0])
1469            tcg_out_goto(s, COND_AL, args[0]);
1470        else
1471            tcg_out_bx(s, COND_AL, args[0]);
1472        break;
1473    case INDEX_op_br:
1474        tcg_out_goto_label(s, COND_AL, args[0]);
1475        break;
1476
1477    case INDEX_op_ld8u_i32:
1478        tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
1479        break;
1480    case INDEX_op_ld8s_i32:
1481        tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
1482        break;
1483    case INDEX_op_ld16u_i32:
1484        tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
1485        break;
1486    case INDEX_op_ld16s_i32:
1487        tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
1488        break;
1489    case INDEX_op_ld_i32:
1490        tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
1491        break;
1492    case INDEX_op_st8_i32:
1493        tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1494        break;
1495    case INDEX_op_st16_i32:
1496        tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1497        break;
1498    case INDEX_op_st_i32:
1499        tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
1500        break;
1501
1502    case INDEX_op_mov_i32:
1503        tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1504                        args[0], 0, args[1], SHIFT_IMM_LSL(0));
1505        break;
1506    case INDEX_op_movi_i32:
1507        tcg_out_movi32(s, COND_AL, args[0], args[1]);
1508        break;
1509    case INDEX_op_add_i32:
1510        c = ARITH_ADD;
1511        goto gen_arith;
1512    case INDEX_op_sub_i32:
1513        c = ARITH_SUB;
1514        goto gen_arith;
1515    case INDEX_op_and_i32:
1516        c = ARITH_AND;
1517        goto gen_arith;
1518    case INDEX_op_andc_i32:
1519        c = ARITH_BIC;
1520        goto gen_arith;
1521    case INDEX_op_or_i32:
1522        c = ARITH_ORR;
1523        goto gen_arith;
1524    case INDEX_op_xor_i32:
1525        c = ARITH_EOR;
1526        /* Fall through.  */
1527    gen_arith:
1528        if (const_args[2]) {
1529            int rot;
1530            rot = encode_imm(args[2]);
1531            tcg_out_dat_imm(s, COND_AL, c,
1532                            args[0], args[1], rotl(args[2], rot) | (rot << 7));
1533        } else
1534            tcg_out_dat_reg(s, COND_AL, c,
1535                            args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1536        break;
1537    case INDEX_op_add2_i32:
1538        tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
1539                        args[0], args[1], args[2], args[3],
1540                        args[4], args[5], SHIFT_IMM_LSL(0));
1541        break;
1542    case INDEX_op_sub2_i32:
1543        tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
1544                        args[0], args[1], args[2], args[3],
1545                        args[4], args[5], SHIFT_IMM_LSL(0));
1546        break;
1547    case INDEX_op_neg_i32:
1548        tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
1549        break;
1550    case INDEX_op_not_i32:
1551        tcg_out_dat_reg(s, COND_AL,
1552                        ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
1553        break;
1554    case INDEX_op_mul_i32:
1555        tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
1556        break;
1557    case INDEX_op_mulu2_i32:
1558        tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
1559        break;
1560    /* XXX: Perhaps args[2] & 0x1f is wrong */
1561    case INDEX_op_shl_i32:
1562        c = const_args[2] ?
1563                SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
1564        goto gen_shift32;
1565    case INDEX_op_shr_i32:
1566        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
1567                SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
1568        goto gen_shift32;
1569    case INDEX_op_sar_i32:
1570        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
1571                SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1572        goto gen_shift32;
1573    case INDEX_op_rotr_i32:
1574        c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
1575                SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1576        /* Fall through.  */
1577    gen_shift32:
1578        tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
1579        break;
1580
1581    case INDEX_op_rotl_i32:
1582        if (const_args[2]) {
1583            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1584                            ((0x20 - args[2]) & 0x1f) ?
1585                            SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
1586                            SHIFT_IMM_LSL(0));
1587        } else {
1588            tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
1589            tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
1590                            SHIFT_REG_ROR(TCG_REG_R8));
1591        }
1592        break;
1593
1594    case INDEX_op_brcond_i32:
1595        if (const_args[1]) {
1596            int rot;
1597            rot = encode_imm(args[1]);
1598            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
1599                            args[0], rotl(args[1], rot) | (rot << 7));
1600        } else {
1601            tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1602                            args[0], args[1], SHIFT_IMM_LSL(0));
1603        }
1604        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
1605        break;
1606    case INDEX_op_brcond2_i32:
1607        /* The resulting conditions are:
1608         * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
1609         * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
1610         * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
1611         * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
1612         * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
1613         * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
1614         */
1615        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1616                        args[1], args[3], SHIFT_IMM_LSL(0));
1617        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1618                        args[0], args[2], SHIFT_IMM_LSL(0));
1619        tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
1620        break;
1621    case INDEX_op_setcond_i32:
1622        if (const_args[2]) {
1623            int rot;
1624            rot = encode_imm(args[2]);
1625            tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
1626                            args[1], rotl(args[2], rot) | (rot << 7));
1627        } else {
1628            tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1629                            args[1], args[2], SHIFT_IMM_LSL(0));
1630        }
1631        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
1632                        ARITH_MOV, args[0], 0, 1);
1633        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
1634                        ARITH_MOV, args[0], 0, 0);
1635        break;
1636    case INDEX_op_setcond2_i32:
1637        /* See brcond2_i32 comment */
1638        tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
1639                        args[2], args[4], SHIFT_IMM_LSL(0));
1640        tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
1641                        args[1], args[3], SHIFT_IMM_LSL(0));
1642        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
1643                        ARITH_MOV, args[0], 0, 1);
1644        tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
1645                        ARITH_MOV, args[0], 0, 0);
1646        break;
1647
1648    case INDEX_op_qemu_ld8u:
1649        tcg_out_qemu_ld(s, args, 0);
1650        break;
1651    case INDEX_op_qemu_ld8s:
1652        tcg_out_qemu_ld(s, args, 0 | 4);
1653        break;
1654    case INDEX_op_qemu_ld16u:
1655        tcg_out_qemu_ld(s, args, 1);
1656        break;
1657    case INDEX_op_qemu_ld16s:
1658        tcg_out_qemu_ld(s, args, 1 | 4);
1659        break;
1660    case INDEX_op_qemu_ld32:
1661        tcg_out_qemu_ld(s, args, 2);
1662        break;
1663    case INDEX_op_qemu_ld64:
1664        tcg_out_qemu_ld(s, args, 3);
1665        break;
1666
1667    case INDEX_op_qemu_st8:
1668        tcg_out_qemu_st(s, args, 0);
1669        break;
1670    case INDEX_op_qemu_st16:
1671        tcg_out_qemu_st(s, args, 1);
1672        break;
1673    case INDEX_op_qemu_st32:
1674        tcg_out_qemu_st(s, args, 2);
1675        break;
1676    case INDEX_op_qemu_st64:
1677        tcg_out_qemu_st(s, args, 3);
1678        break;
1679
1680    case INDEX_op_bswap16_i32:
1681        tcg_out_bswap16(s, COND_AL, args[0], args[1]);
1682        break;
1683    case INDEX_op_bswap32_i32:
1684        tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1685        break;
1686
1687    case INDEX_op_ext8s_i32:
1688        tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1689        break;
1690    case INDEX_op_ext16s_i32:
1691        tcg_out_ext16s(s, COND_AL, args[0], args[1]);
1692        break;
1693    case INDEX_op_ext16u_i32:
1694        tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1695        break;
1696
1697    default:
1698        tcg_abort();
1699    }
1700}
1701
1702static const TCGTargetOpDef arm_op_defs[] = {
1703    { INDEX_op_exit_tb, { } },
1704    { INDEX_op_goto_tb, { } },
1705    { INDEX_op_call, { "ri" } },
1706    { INDEX_op_jmp, { "ri" } },
1707    { INDEX_op_br, { } },
1708
1709    { INDEX_op_mov_i32, { "r", "r" } },
1710    { INDEX_op_movi_i32, { "r" } },
1711
1712    { INDEX_op_ld8u_i32, { "r", "r" } },
1713    { INDEX_op_ld8s_i32, { "r", "r" } },
1714    { INDEX_op_ld16u_i32, { "r", "r" } },
1715    { INDEX_op_ld16s_i32, { "r", "r" } },
1716    { INDEX_op_ld_i32, { "r", "r" } },
1717    { INDEX_op_st8_i32, { "r", "r" } },
1718    { INDEX_op_st16_i32, { "r", "r" } },
1719    { INDEX_op_st_i32, { "r", "r" } },
1720
1721    /* TODO: "r", "r", "ri" */
1722    { INDEX_op_add_i32, { "r", "r", "rI" } },
1723    { INDEX_op_sub_i32, { "r", "r", "rI" } },
1724    { INDEX_op_mul_i32, { "r", "r", "r" } },
1725    { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1726    { INDEX_op_and_i32, { "r", "r", "rI" } },
1727    { INDEX_op_andc_i32, { "r", "r", "rI" } },
1728    { INDEX_op_or_i32, { "r", "r", "rI" } },
1729    { INDEX_op_xor_i32, { "r", "r", "rI" } },
1730    { INDEX_op_neg_i32, { "r", "r" } },
1731    { INDEX_op_not_i32, { "r", "r" } },
1732
1733    { INDEX_op_shl_i32, { "r", "r", "ri" } },
1734    { INDEX_op_shr_i32, { "r", "r", "ri" } },
1735    { INDEX_op_sar_i32, { "r", "r", "ri" } },
1736    { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1737    { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1738
1739    { INDEX_op_brcond_i32, { "r", "rI" } },
1740    { INDEX_op_setcond_i32, { "r", "r", "rI" } },
1741
1742    /* TODO: "r", "r", "r", "r", "ri", "ri" */
1743    { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
1744    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
1745    { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1746    { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
1747
1748#if TARGET_LONG_BITS == 32
1749    { INDEX_op_qemu_ld8u, { "r", "l" } },
1750    { INDEX_op_qemu_ld8s, { "r", "l" } },
1751    { INDEX_op_qemu_ld16u, { "r", "l" } },
1752    { INDEX_op_qemu_ld16s, { "r", "l" } },
1753    { INDEX_op_qemu_ld32, { "r", "l" } },
1754    { INDEX_op_qemu_ld64, { "L", "L", "l" } },
1755
1756    { INDEX_op_qemu_st8, { "s", "s" } },
1757    { INDEX_op_qemu_st16, { "s", "s" } },
1758    { INDEX_op_qemu_st32, { "s", "s" } },
1759    { INDEX_op_qemu_st64, { "S", "S", "s" } },
1760#else
1761    { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
1762    { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
1763    { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
1764    { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
1765    { INDEX_op_qemu_ld32, { "r", "l", "l" } },
1766    { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
1767
1768    { INDEX_op_qemu_st8, { "s", "s", "s" } },
1769    { INDEX_op_qemu_st16, { "s", "s", "s" } },
1770    { INDEX_op_qemu_st32, { "s", "s", "s" } },
1771    { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
1772#endif
1773
1774    { INDEX_op_bswap16_i32, { "r", "r" } },
1775    { INDEX_op_bswap32_i32, { "r", "r" } },
1776
1777    { INDEX_op_ext8s_i32, { "r", "r" } },
1778    { INDEX_op_ext16s_i32, { "r", "r" } },
1779    { INDEX_op_ext16u_i32, { "r", "r" } },
1780
1781    { -1 },
1782};
1783
1784static void tcg_target_init(TCGContext *s)
1785{
1786#if !defined(CONFIG_USER_ONLY)
1787    /* fail safe */
1788    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
1789        tcg_abort();
1790#endif
1791
1792    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1793    tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1794                     (1 << TCG_REG_R0) |
1795                     (1 << TCG_REG_R1) |
1796                     (1 << TCG_REG_R2) |
1797                     (1 << TCG_REG_R3) |
1798                     (1 << TCG_REG_R12) |
1799                     (1 << TCG_REG_R14));
1800
1801    tcg_regset_clear(s->reserved_regs);
1802    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
1803    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1804    tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
1805
1806    tcg_add_target_add_op_defs(arm_op_defs);
1807}
1808
1809static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
1810                int arg1, tcg_target_long arg2)
1811{
1812    tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
1813}
1814
1815static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
1816                int arg1, tcg_target_long arg2)
1817{
1818    tcg_out_st32(s, COND_AL, arg, arg1, arg2);
1819}
1820
1821static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
1822{
1823    if (val > 0)
1824        if (val < 0x100)
1825            tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
1826        else
1827            tcg_abort();
1828    else if (val < 0) {
1829        if (val > -0x100)
1830            tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
1831        else
1832            tcg_abort();
1833    }
1834}
1835
1836static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
1837{
1838    tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
1839}
1840
1841static inline void tcg_out_movi(TCGContext *s, TCGType type,
1842                int ret, tcg_target_long arg)
1843{
1844    tcg_out_movi32(s, COND_AL, ret, arg);
1845}
1846
1847static void tcg_target_qemu_prologue(TCGContext *s)
1848{
1849    /* There is no need to save r7, it is used to store the address
1850       of the env structure and is not modified by GCC. */
1851
1852    /* stmdb sp!, { r4 - r6, r8 - r11, lr } */
1853    tcg_out32(s, (COND_AL << 28) | 0x092d4f70);
1854
1855    tcg_out_bx(s, COND_AL, TCG_REG_R0);
1856    tb_ret_addr = s->code_ptr;
1857
1858    /* ldmia sp!, { r4 - r6, r8 - r11, pc } */
1859    tcg_out32(s, (COND_AL << 28) | 0x08bd8f70);
1860}
1861