Annotation of qemu/tcg/arm/tcg-target.c, revision 1.1.1.1

1.1       root        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:         tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1015:         tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, 4);
                   1016:         break;
                   1017:     }
                   1018: #endif
                   1019: }
                   1020: 
                   1021: static inline void tcg_out_qemu_st(TCGContext *s, int cond,
                   1022:                 const TCGArg *args, int opc)
                   1023: {
                   1024:     int addr_reg, data_reg, data_reg2;
                   1025: #ifdef CONFIG_SOFTMMU
                   1026:     int mem_index, s_bits;
                   1027: # if TARGET_LONG_BITS == 64
                   1028:     int addr_reg2;
                   1029: # endif
                   1030:     uint32_t *label_ptr;
                   1031: #endif
                   1032: 
                   1033:     data_reg = *args++;
                   1034:     if (opc == 3)
                   1035:         data_reg2 = *args++;
                   1036:     else
                   1037:         data_reg2 = 0; /* surpress warning */
                   1038:     addr_reg = *args++;
                   1039: #ifdef CONFIG_SOFTMMU
                   1040: # if TARGET_LONG_BITS == 64
                   1041:     addr_reg2 = *args++;
                   1042: # endif
                   1043:     mem_index = *args;
                   1044:     s_bits = opc & 3;
                   1045: 
                   1046:     /* Should generate something like the following:
                   1047:      *  shr r8, addr_reg, #TARGET_PAGE_BITS
                   1048:      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
                   1049:      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
                   1050:      */
                   1051:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1052:                     8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
                   1053:     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
                   1054:                     0, 8, CPU_TLB_SIZE - 1);
                   1055:     tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
                   1056:                     0, TCG_AREG0, 0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
                   1057:     /* In the
                   1058:      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
                   1059:      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
                   1060:      * not exceed otherwise, so use an
                   1061:      *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
                   1062:      * before.
                   1063:      */
                   1064:     if (mem_index)
                   1065:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 0, 0,
                   1066:                         (mem_index << (TLB_SHIFT & 1)) |
                   1067:                         ((16 - (TLB_SHIFT >> 1)) << 8));
                   1068:     tcg_out_ld32_12(s, COND_AL, 1, 0,
                   1069:                     offsetof(CPUState, tlb_table[0][0].addr_write));
                   1070:     tcg_out_dat_reg(s, COND_AL, ARITH_CMP,
                   1071:                     0, 1, 8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
                   1072:     /* Check alignment.  */
                   1073:     if (s_bits)
                   1074:         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                   1075:                         0, addr_reg, (1 << s_bits) - 1);
                   1076: #  if TARGET_LONG_BITS == 64
                   1077:     /* XXX: possibly we could use a block data load or writeback in
                   1078:      * the first access.  */
                   1079:     tcg_out_ld32_12(s, COND_EQ, 1, 0,
                   1080:                     offsetof(CPUState, tlb_table[0][0].addr_write)
                   1081:                     + 4);
                   1082:     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP,
                   1083:                     0, 1, addr_reg2, SHIFT_IMM_LSL(0));
                   1084: #  endif
                   1085:     tcg_out_ld32_12(s, COND_EQ, 1, 0,
                   1086:                     offsetof(CPUState, tlb_table[0][0].addend));
                   1087: 
                   1088:     switch (opc) {
                   1089:     case 0:
                   1090:         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, 1);
                   1091:         break;
                   1092:     case 0 | 4:
                   1093:         tcg_out_st8s_r(s, COND_EQ, data_reg, addr_reg, 1);
                   1094:         break;
                   1095:     case 1:
                   1096:         tcg_out_st16u_r(s, COND_EQ, data_reg, addr_reg, 1);
                   1097:         break;
                   1098:     case 1 | 4:
                   1099:         tcg_out_st16s_r(s, COND_EQ, data_reg, addr_reg, 1);
                   1100:         break;
                   1101:     case 2:
                   1102:     default:
                   1103:         tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, 1);
                   1104:         break;
                   1105:     case 3:
                   1106:         tcg_out_st32_rwb(s, COND_EQ, data_reg, 1, addr_reg);
                   1107:         tcg_out_st32_12(s, COND_EQ, data_reg2, 1, 4);
                   1108:         break;
                   1109:     }
                   1110: 
                   1111:     label_ptr = (void *) s->code_ptr;
                   1112:     tcg_out_b(s, COND_EQ, 8);
                   1113: 
                   1114:     /* TODO: move this code to where the constants pool will be */
                   1115:     if (addr_reg)
                   1116:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1117:                         0, 0, addr_reg, SHIFT_IMM_LSL(0));
                   1118: # if TARGET_LONG_BITS == 32
                   1119:     switch (opc) {
                   1120:     case 0:
                   1121:         tcg_out_dat_imm(s, cond, ARITH_AND, 1, data_reg, 0xff);
                   1122:         tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
                   1123:         break;
                   1124:     case 1:
                   1125:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1126:                         1, 0, data_reg, SHIFT_IMM_LSL(16));
                   1127:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1128:                         1, 0, 1, SHIFT_IMM_LSR(16));
                   1129:         tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
                   1130:         break;
                   1131:     case 2:
                   1132:         if (data_reg != 1)
                   1133:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1134:                             1, 0, data_reg, SHIFT_IMM_LSL(0));
                   1135:         tcg_out_dat_imm(s, cond, ARITH_MOV, 2, 0, mem_index);
                   1136:         break;
                   1137:     case 3:
                   1138:         if (data_reg != 1)
                   1139:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1140:                             1, 0, data_reg, SHIFT_IMM_LSL(0));
                   1141:         if (data_reg2 != 2)
                   1142:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1143:                             2, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1144:         tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
                   1145:         break;
                   1146:     }
                   1147: # else
                   1148:     if (addr_reg2 != 1)
                   1149:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1150:                         1, 0, addr_reg2, SHIFT_IMM_LSL(0));
                   1151:     switch (opc) {
                   1152:     case 0:
                   1153:         tcg_out_dat_imm(s, cond, ARITH_AND, 2, data_reg, 0xff);
                   1154:         tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
                   1155:         break;
                   1156:     case 1:
                   1157:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1158:                         2, 0, data_reg, SHIFT_IMM_LSL(16));
                   1159:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1160:                         2, 0, 2, SHIFT_IMM_LSR(16));
                   1161:         tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
                   1162:         break;
                   1163:     case 2:
                   1164:         if (data_reg != 2)
                   1165:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1166:                             2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1167:         tcg_out_dat_imm(s, cond, ARITH_MOV, 3, 0, mem_index);
                   1168:         break;
                   1169:     case 3:
                   1170:         tcg_out_dat_imm(s, cond, ARITH_MOV, 8, 0, mem_index);
                   1171:         tcg_out32(s, (cond << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
                   1172:         if (data_reg != 2)
                   1173:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1174:                             2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1175:         if (data_reg2 != 3)
                   1176:             tcg_out_dat_reg(s, cond, ARITH_MOV,
                   1177:                             3, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1178:         break;
                   1179:     }
                   1180: # endif
                   1181: 
                   1182: # ifdef SAVE_LR
                   1183:     tcg_out_dat_reg(s, cond, ARITH_MOV, 8, 0, 14, SHIFT_IMM_LSL(0));
                   1184: # endif
                   1185: 
                   1186:     tcg_out_bl(s, cond, (tcg_target_long) qemu_st_helpers[s_bits] -
                   1187:                     (tcg_target_long) s->code_ptr);
                   1188: # if TARGET_LONG_BITS == 64
                   1189:     if (opc == 3)
                   1190:         tcg_out_dat_imm(s, cond, ARITH_ADD, 13, 13, 0x10);
                   1191: # endif
                   1192: 
                   1193: # ifdef SAVE_LR
                   1194:     tcg_out_dat_reg(s, cond, ARITH_MOV, 14, 0, 8, SHIFT_IMM_LSL(0));
                   1195: # endif
                   1196: 
                   1197:     *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
                   1198: #else
                   1199:     switch (opc) {
                   1200:     case 0:
                   1201:         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
                   1202:         break;
                   1203:     case 0 | 4:
                   1204:         tcg_out_st8s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1205:         break;
                   1206:     case 1:
                   1207:         tcg_out_st16u_8(s, COND_AL, data_reg, addr_reg, 0);
                   1208:         break;
                   1209:     case 1 | 4:
                   1210:         tcg_out_st16s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1211:         break;
                   1212:     case 2:
                   1213:     default:
                   1214:         tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1215:         break;
                   1216:     case 3:
                   1217:         /* TODO: use block store -
                   1218:          * check that data_reg2 > data_reg or the other way */
                   1219:         tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1220:         tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
                   1221:         break;
                   1222:     }
                   1223: #endif
                   1224: }
                   1225: 
                   1226: static uint8_t *tb_ret_addr;
                   1227: 
                   1228: static inline void tcg_out_op(TCGContext *s, int opc,
                   1229:                 const TCGArg *args, const int *const_args)
                   1230: {
                   1231:     int c;
                   1232: 
                   1233:     switch (opc) {
                   1234:     case INDEX_op_exit_tb:
                   1235: #ifdef SAVE_LR
                   1236:         if (args[0] >> 8)
                   1237:             tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
                   1238:         else
                   1239:             tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
                   1240:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV, 15, 0, 14, SHIFT_IMM_LSL(0));
                   1241:         if (args[0] >> 8)
                   1242:             tcg_out32(s, args[0]);
                   1243: #else
                   1244:         {
                   1245:             uint8_t *ld_ptr = s->code_ptr;
                   1246:             if (args[0] >> 8)
                   1247:                 tcg_out_ld32_12(s, COND_AL, 0, 15, 0);
                   1248:             else
                   1249:                 tcg_out_dat_imm(s, COND_AL, ARITH_MOV, 0, 0, args[0]);
                   1250:             tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
                   1251:             if (args[0] >> 8) {
                   1252:                 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
                   1253:                 tcg_out32(s, args[0]);
                   1254:             }
                   1255:         }
                   1256: #endif
                   1257:         break;
                   1258:     case INDEX_op_goto_tb:
                   1259:         if (s->tb_jmp_offset) {
                   1260:             /* Direct jump method */
                   1261: #if defined(USE_DIRECT_JUMP)
                   1262:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                   1263:             tcg_out_b(s, COND_AL, 8);
                   1264: #else
                   1265:             tcg_out_ld32_12(s, COND_AL, 15, 15, -4);
                   1266:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                   1267:             tcg_out32(s, 0);
                   1268: #endif
                   1269:         } else {
                   1270:             /* Indirect jump method */
                   1271: #if 1
                   1272:             c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
                   1273:             if (c > 0xfff || c < -0xfff) {
                   1274:                 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
                   1275:                                 (tcg_target_long) (s->tb_next + args[0]));
                   1276:                 tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
                   1277:             } else
                   1278:                 tcg_out_ld32_12(s, COND_AL, 15, 15, c);
                   1279: #else
                   1280:             tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, 15, 0);
                   1281:             tcg_out_ld32_12(s, COND_AL, 15, TCG_REG_R0, 0);
                   1282:             tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
                   1283: #endif
                   1284:         }
                   1285:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                   1286:         break;
                   1287:     case INDEX_op_call:
                   1288:         if (const_args[0])
                   1289:             tcg_out_call(s, COND_AL, args[0]);
                   1290:         else
                   1291:             tcg_out_callr(s, COND_AL, args[0]);
                   1292:         break;
                   1293:     case INDEX_op_jmp:
                   1294:         if (const_args[0])
                   1295:             tcg_out_goto(s, COND_AL, args[0]);
                   1296:         else
                   1297:             tcg_out_bx(s, COND_AL, args[0]);
                   1298:         break;
                   1299:     case INDEX_op_br:
                   1300:         tcg_out_goto_label(s, COND_AL, args[0]);
                   1301:         break;
                   1302: 
                   1303:     case INDEX_op_ld8u_i32:
                   1304:         tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
                   1305:         break;
                   1306:     case INDEX_op_ld8s_i32:
                   1307:         tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
                   1308:         break;
                   1309:     case INDEX_op_ld16u_i32:
                   1310:         tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
                   1311:         break;
                   1312:     case INDEX_op_ld16s_i32:
                   1313:         tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
                   1314:         break;
                   1315:     case INDEX_op_ld_i32:
                   1316:         tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
                   1317:         break;
                   1318:     case INDEX_op_st8_i32:
                   1319:         tcg_out_st8u(s, COND_AL, args[0], args[1], args[2]);
                   1320:         break;
                   1321:     case INDEX_op_st16_i32:
                   1322:         tcg_out_st16u(s, COND_AL, args[0], args[1], args[2]);
                   1323:         break;
                   1324:     case INDEX_op_st_i32:
                   1325:         tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
                   1326:         break;
                   1327: 
                   1328:     case INDEX_op_mov_i32:
                   1329:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1330:                         args[0], 0, args[1], SHIFT_IMM_LSL(0));
                   1331:         break;
                   1332:     case INDEX_op_movi_i32:
                   1333:         tcg_out_movi32(s, COND_AL, args[0], args[1]);
                   1334:         break;
                   1335:     case INDEX_op_add_i32:
                   1336:         c = ARITH_ADD;
                   1337:         goto gen_arith;
                   1338:     case INDEX_op_sub_i32:
                   1339:         c = ARITH_SUB;
                   1340:         goto gen_arith;
                   1341:     case INDEX_op_and_i32:
                   1342:         c = ARITH_AND;
                   1343:         goto gen_arith;
                   1344:     case INDEX_op_or_i32:
                   1345:         c = ARITH_ORR;
                   1346:         goto gen_arith;
                   1347:     case INDEX_op_xor_i32:
                   1348:         c = ARITH_EOR;
                   1349:         /* Fall through.  */
                   1350:     gen_arith:
                   1351:         tcg_out_dat_reg(s, COND_AL, c,
                   1352:                         args[0], args[1], args[2], SHIFT_IMM_LSL(0));
                   1353:         break;
                   1354:     case INDEX_op_add2_i32:
                   1355:         tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
                   1356:                         args[0], args[1], args[2], args[3],
                   1357:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1358:         break;
                   1359:     case INDEX_op_sub2_i32:
                   1360:         tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
                   1361:                         args[0], args[1], args[2], args[3],
                   1362:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1363:         break;
                   1364:     case INDEX_op_neg_i32:
                   1365:         tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
                   1366:         break;
                   1367:     case INDEX_op_mul_i32:
                   1368:         tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
                   1369:         break;
                   1370:     case INDEX_op_mulu2_i32:
                   1371:         tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
                   1372:         break;
                   1373:     case INDEX_op_div2_i32:
                   1374:         tcg_out_div_helper(s, COND_AL, args,
                   1375:                         tcg_helper_div_i64, tcg_helper_rem_i64,
                   1376:                         SHIFT_IMM_ASR(31));
                   1377:         break;
                   1378:     case INDEX_op_divu2_i32:
                   1379:         tcg_out_div_helper(s, COND_AL, args,
                   1380:                         tcg_helper_divu_i64, tcg_helper_remu_i64,
                   1381:                         SHIFT_IMM_LSR(31));
                   1382:         break;
                   1383:     /* XXX: Perhaps args[2] & 0x1f is wrong */
                   1384:     case INDEX_op_shl_i32:
                   1385:         c = const_args[2] ?
                   1386:                 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
                   1387:         goto gen_shift32;
                   1388:     case INDEX_op_shr_i32:
                   1389:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
                   1390:                 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
                   1391:         goto gen_shift32;
                   1392:     case INDEX_op_sar_i32:
                   1393:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
                   1394:                 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
                   1395:         /* Fall through.  */
                   1396:     gen_shift32:
                   1397:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
                   1398:         break;
                   1399: 
                   1400:     case INDEX_op_brcond_i32:
                   1401:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1402:                         args[0], args[1], SHIFT_IMM_LSL(0));
                   1403:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
                   1404:         break;
                   1405:     case INDEX_op_brcond2_i32:
                   1406:         /* The resulting conditions are:
                   1407:          * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
                   1408:          * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
                   1409:          * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
                   1410:          * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
                   1411:          * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
                   1412:          * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
                   1413:          */
                   1414:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1415:                         args[1], args[3], SHIFT_IMM_LSL(0));
                   1416:         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1417:                         args[0], args[2], SHIFT_IMM_LSL(0));
                   1418:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
                   1419:         break;
                   1420: 
                   1421:     case INDEX_op_qemu_ld8u:
                   1422:         tcg_out_qemu_ld(s, COND_AL, args, 0);
                   1423:         break;
                   1424:     case INDEX_op_qemu_ld8s:
                   1425:         tcg_out_qemu_ld(s, COND_AL, args, 0 | 4);
                   1426:         break;
                   1427:     case INDEX_op_qemu_ld16u:
                   1428:         tcg_out_qemu_ld(s, COND_AL, args, 1);
                   1429:         break;
                   1430:     case INDEX_op_qemu_ld16s:
                   1431:         tcg_out_qemu_ld(s, COND_AL, args, 1 | 4);
                   1432:         break;
                   1433:     case INDEX_op_qemu_ld32u:
                   1434:         tcg_out_qemu_ld(s, COND_AL, args, 2);
                   1435:         break;
                   1436:     case INDEX_op_qemu_ld64:
                   1437:         tcg_out_qemu_ld(s, COND_AL, args, 3);
                   1438:         break;
                   1439: 
                   1440:     case INDEX_op_qemu_st8:
                   1441:         tcg_out_qemu_st(s, COND_AL, args, 0);
                   1442:         break;
                   1443:     case INDEX_op_qemu_st16:
                   1444:         tcg_out_qemu_st(s, COND_AL, args, 1);
                   1445:         break;
                   1446:     case INDEX_op_qemu_st32:
                   1447:         tcg_out_qemu_st(s, COND_AL, args, 2);
                   1448:         break;
                   1449:     case INDEX_op_qemu_st64:
                   1450:         tcg_out_qemu_st(s, COND_AL, args, 3);
                   1451:         break;
                   1452: 
                   1453:     case INDEX_op_ext8s_i32:
                   1454:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1455:                         args[0], 0, args[1], SHIFT_IMM_LSL(24));
                   1456:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1457:                         args[0], 0, args[0], SHIFT_IMM_ASR(24));
                   1458:         break;
                   1459:     case INDEX_op_ext16s_i32:
                   1460:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1461:                         args[0], 0, args[1], SHIFT_IMM_LSL(16));
                   1462:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1463:                         args[0], 0, args[0], SHIFT_IMM_ASR(16));
                   1464:         break;
                   1465: 
                   1466:     default:
                   1467:         tcg_abort();
                   1468:     }
                   1469: }
                   1470: 
                   1471: static const TCGTargetOpDef arm_op_defs[] = {
                   1472:     { INDEX_op_exit_tb, { } },
                   1473:     { INDEX_op_goto_tb, { } },
                   1474:     { INDEX_op_call, { "ri" } },
                   1475:     { INDEX_op_jmp, { "ri" } },
                   1476:     { INDEX_op_br, { } },
                   1477: 
                   1478:     { INDEX_op_mov_i32, { "r", "r" } },
                   1479:     { INDEX_op_movi_i32, { "r" } },
                   1480: 
                   1481:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1482:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1483:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1484:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1485:     { INDEX_op_ld_i32, { "r", "r" } },
                   1486:     { INDEX_op_st8_i32, { "r", "r" } },
                   1487:     { INDEX_op_st16_i32, { "r", "r" } },
                   1488:     { INDEX_op_st_i32, { "r", "r" } },
                   1489: 
                   1490:     /* TODO: "r", "r", "ri" */
                   1491:     { INDEX_op_add_i32, { "r", "r", "r" } },
                   1492:     { INDEX_op_sub_i32, { "r", "r", "r" } },
                   1493:     { INDEX_op_mul_i32, { "r", "r", "r" } },
                   1494:     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
                   1495:     { INDEX_op_div2_i32, { "r", "r", "r", "1", "2" } },
                   1496:     { INDEX_op_divu2_i32, { "r", "r", "r", "1", "2" } },
                   1497:     { INDEX_op_and_i32, { "r", "r", "r" } },
                   1498:     { INDEX_op_or_i32, { "r", "r", "r" } },
                   1499:     { INDEX_op_xor_i32, { "r", "r", "r" } },
                   1500:     { INDEX_op_neg_i32, { "r", "r" } },
                   1501: 
                   1502:     { INDEX_op_shl_i32, { "r", "r", "ri" } },
                   1503:     { INDEX_op_shr_i32, { "r", "r", "ri" } },
                   1504:     { INDEX_op_sar_i32, { "r", "r", "ri" } },
                   1505: 
                   1506:     { INDEX_op_brcond_i32, { "r", "r" } },
                   1507: 
                   1508:     /* TODO: "r", "r", "r", "r", "ri", "ri" */
                   1509:     { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1510:     { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1511:     { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
                   1512: 
                   1513:     { INDEX_op_qemu_ld8u, { "r", "x", "X" } },
                   1514:     { INDEX_op_qemu_ld8s, { "r", "x", "X" } },
                   1515:     { INDEX_op_qemu_ld16u, { "r", "x", "X" } },
                   1516:     { INDEX_op_qemu_ld16s, { "r", "x", "X" } },
                   1517:     { INDEX_op_qemu_ld32u, { "r", "x", "X" } },
                   1518:     { INDEX_op_qemu_ld64, { "d", "r", "x", "X" } },
                   1519: 
                   1520:     { INDEX_op_qemu_st8, { "x", "x", "X" } },
                   1521:     { INDEX_op_qemu_st16, { "x", "x", "X" } },
                   1522:     { INDEX_op_qemu_st32, { "x", "x", "X" } },
                   1523:     { INDEX_op_qemu_st64, { "x", "D", "x", "X" } },
                   1524: 
                   1525:     { INDEX_op_ext8s_i32, { "r", "r" } },
                   1526:     { INDEX_op_ext16s_i32, { "r", "r" } },
                   1527: 
                   1528:     { -1 },
                   1529: };
                   1530: 
                   1531: void tcg_target_init(TCGContext *s)
                   1532: {
                   1533:     /* fail safe */
                   1534:     if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
                   1535:         tcg_abort();
                   1536: 
                   1537:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0,
                   1538:                     ((2 << TCG_REG_R14) - 1) & ~(1 << TCG_REG_R8));
                   1539:     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
                   1540:                     ((2 << TCG_REG_R3) - 1) |
                   1541:                     (1 << TCG_REG_R12) | (1 << TCG_REG_R14));
                   1542: 
                   1543:     tcg_regset_clear(s->reserved_regs);
                   1544: #ifdef SAVE_LR
                   1545:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R14);
                   1546: #endif
                   1547:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
                   1548:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
                   1549: 
                   1550:     tcg_add_target_add_op_defs(arm_op_defs);
                   1551: }
                   1552: 
                   1553: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
                   1554:                 int arg1, tcg_target_long arg2)
                   1555: {
                   1556:     tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
                   1557: }
                   1558: 
                   1559: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                   1560:                 int arg1, tcg_target_long arg2)
                   1561: {
                   1562:     tcg_out_st32(s, COND_AL, arg, arg1, arg2);
                   1563: }
                   1564: 
                   1565: void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
                   1566: {
                   1567:     if (val > 0)
                   1568:         if (val < 0x100)
                   1569:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
                   1570:         else
                   1571:             tcg_abort();
                   1572:     else if (val < 0) {
                   1573:         if (val > -0x100)
                   1574:             tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
                   1575:         else
                   1576:             tcg_abort();
                   1577:     }
                   1578: }
                   1579: 
                   1580: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
                   1581: {
                   1582:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
                   1583: }
                   1584: 
                   1585: static inline void tcg_out_movi(TCGContext *s, TCGType type,
                   1586:                 int ret, tcg_target_long arg)
                   1587: {
                   1588:     tcg_out_movi32(s, COND_AL, ret, arg);
                   1589: }
                   1590: 
                   1591: void tcg_target_qemu_prologue(TCGContext *s)
                   1592: {
                   1593:     /* stmdb sp!, { r9 - r11, lr } */
                   1594:     tcg_out32(s, (COND_AL << 28) | 0x092d4e00);
                   1595: 
                   1596:     tcg_out_bx(s, COND_AL, TCG_REG_R0);
                   1597:     tb_ret_addr = s->code_ptr;
                   1598: 
                   1599:     /* ldmia sp!, { r9 - r11, pc } */
                   1600:     tcg_out32(s, (COND_AL << 28) | 0x08bd8e00);
                   1601: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.