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

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

unix.superglobalmegacorp.com

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