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