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

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: 
                    845: static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
                    846: {
                    847:     int32_t val;
                    848: 
1.1.1.7   root      849:     if (addr & 1) {
                    850:         /* goto to a Thumb destination isn't supported */
                    851:         tcg_abort();
                    852:     }
                    853: 
1.1       root      854:     val = addr - (tcg_target_long) s->code_ptr;
                    855:     if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
                    856:         tcg_out_b(s, cond, val);
                    857:     else {
                    858: #if 1
                    859:         tcg_abort();
                    860: #else
                    861:         if (cond == COND_AL) {
1.1.1.5   root      862:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      863:             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
                    864:         } else {
                    865:             tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
                    866:             tcg_out_dat_reg(s, cond, ARITH_ADD,
1.1.1.5   root      867:                             TCG_REG_PC, TCG_REG_PC,
                    868:                             TCG_REG_R8, SHIFT_IMM_LSL(0));
1.1       root      869:         }
                    870: #endif
                    871:     }
                    872: }
                    873: 
1.1.1.7   root      874: static inline void tcg_out_call(TCGContext *s, uint32_t addr)
1.1       root      875: {
                    876:     int32_t val;
                    877: 
                    878:     val = addr - (tcg_target_long) s->code_ptr;
1.1.1.7   root      879:     if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
                    880:         if (addr & 1) {
                    881:             /* Use BLX if the target is in Thumb mode */
                    882:             if (!use_armv5_instructions) {
                    883:                 tcg_abort();
                    884:             }
                    885:             tcg_out_blx_imm(s, val);
                    886:         } else {
                    887:             tcg_out_bl(s, COND_AL, val);
                    888:         }
                    889:     } else {
1.1       root      890: #if 1
                    891:         tcg_abort();
                    892: #else
                    893:         if (cond == COND_AL) {
1.1.1.5   root      894:             tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
                    895:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      896:             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
                    897:         } else {
                    898:             tcg_out_movi32(s, cond, TCG_REG_R9, addr);
1.1.1.5   root      899:             tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
                    900:                             TCG_REG_PC, SHIFT_IMM_LSL(0));
1.1       root      901:             tcg_out_bx(s, cond, TCG_REG_R9);
                    902:         }
                    903: #endif
                    904:     }
                    905: }
                    906: 
                    907: static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
                    908: {
1.1.1.5   root      909:     if (use_armv5_instructions) {
                    910:         tcg_out_blx(s, cond, arg);
                    911:     } else {
                    912:         tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
                    913:                         TCG_REG_PC, SHIFT_IMM_LSL(0));
                    914:         tcg_out_bx(s, cond, arg);
                    915:     }
1.1       root      916: }
                    917: 
                    918: static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
                    919: {
                    920:     TCGLabel *l = &s->labels[label_index];
                    921: 
                    922:     if (l->has_value)
                    923:         tcg_out_goto(s, cond, l->u.value);
                    924:     else if (cond == COND_AL) {
1.1.1.5   root      925:         tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      926:         tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
                    927:         s->code_ptr += 4;
                    928:     } else {
                    929:         /* Probably this should be preferred even for COND_AL... */
                    930:         tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
                    931:         tcg_out_b_noaddr(s, cond);
                    932:     }
                    933: }
                    934: 
                    935: #ifdef CONFIG_SOFTMMU
                    936: 
                    937: #include "../../softmmu_defs.h"
                    938: 
                    939: static void *qemu_ld_helpers[4] = {
                    940:     __ldb_mmu,
                    941:     __ldw_mmu,
                    942:     __ldl_mmu,
                    943:     __ldq_mmu,
                    944: };
                    945: 
                    946: static void *qemu_st_helpers[4] = {
                    947:     __stb_mmu,
                    948:     __stw_mmu,
                    949:     __stl_mmu,
                    950:     __stq_mmu,
                    951: };
                    952: #endif
                    953: 
                    954: #define TLB_SHIFT      (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
                    955: 
1.1.1.5   root      956: static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
1.1       root      957: {
1.1.1.5   root      958:     int addr_reg, data_reg, data_reg2, bswap;
1.1       root      959: #ifdef CONFIG_SOFTMMU
                    960:     int mem_index, s_bits;
                    961: # if TARGET_LONG_BITS == 64
                    962:     int addr_reg2;
                    963: # endif
                    964:     uint32_t *label_ptr;
                    965: #endif
                    966: 
1.1.1.5   root      967: #ifdef TARGET_WORDS_BIGENDIAN
                    968:     bswap = 1;
                    969: #else
                    970:     bswap = 0;
                    971: #endif
1.1       root      972:     data_reg = *args++;
                    973:     if (opc == 3)
                    974:         data_reg2 = *args++;
                    975:     else
1.1.1.3   root      976:         data_reg2 = 0; /* suppress warning */
1.1       root      977:     addr_reg = *args++;
                    978: #ifdef CONFIG_SOFTMMU
                    979: # if TARGET_LONG_BITS == 64
                    980:     addr_reg2 = *args++;
                    981: # endif
                    982:     mem_index = *args;
                    983:     s_bits = opc & 3;
                    984: 
                    985:     /* Should generate something like the following:
                    986:      *  shr r8, addr_reg, #TARGET_PAGE_BITS
                    987:      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
                    988:      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
                    989:      */
                    990: #  if CPU_TLB_BITS > 8
                    991: #   error
                    992: #  endif
1.1.1.5   root      993:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
                    994:                     0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1.1       root      995:     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1.1.1.5   root      996:                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
                    997:     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                    998:                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1.1       root      999:     /* In the
                   1000:      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
                   1001:      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
                   1002:      * not exceed otherwise, so use an
                   1003:      *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
                   1004:      * before.
                   1005:      */
                   1006:     if (mem_index)
1.1.1.5   root     1007:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1.1       root     1008:                         (mem_index << (TLB_SHIFT & 1)) |
                   1009:                         ((16 - (TLB_SHIFT >> 1)) << 8));
1.1.1.5   root     1010:     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1.1       root     1011:                     offsetof(CPUState, tlb_table[0][0].addr_read));
1.1.1.5   root     1012:     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                   1013:                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1.1       root     1014:     /* Check alignment.  */
                   1015:     if (s_bits)
                   1016:         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                   1017:                         0, addr_reg, (1 << s_bits) - 1);
                   1018: #  if TARGET_LONG_BITS == 64
                   1019:     /* XXX: possibly we could use a block data load or writeback in
                   1020:      * the first access.  */
1.1.1.5   root     1021:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1022:                     offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
1.1.1.5   root     1023:     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1024:                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1025: #  endif
1.1.1.5   root     1026:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1027:                     offsetof(CPUState, tlb_table[0][0].addend));
                   1028: 
                   1029:     switch (opc) {
                   1030:     case 0:
1.1.1.5   root     1031:         tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1032:         break;
                   1033:     case 0 | 4:
1.1.1.5   root     1034:         tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1035:         break;
                   1036:     case 1:
1.1.1.5   root     1037:         tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1038:         if (bswap) {
                   1039:             tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
                   1040:         }
1.1       root     1041:         break;
                   1042:     case 1 | 4:
1.1.1.5   root     1043:         if (bswap) {
                   1044:             tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1045:             tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
                   1046:         } else {
                   1047:             tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1048:         }
1.1       root     1049:         break;
                   1050:     case 2:
                   1051:     default:
1.1.1.5   root     1052:         tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1053:         if (bswap) {
                   1054:             tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
                   1055:         }
1.1       root     1056:         break;
                   1057:     case 3:
1.1.1.5   root     1058:         if (bswap) {
                   1059:             tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
                   1060:             tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
                   1061:             tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
                   1062:             tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
                   1063:         } else {
                   1064:             tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
                   1065:             tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
                   1066:         }
1.1       root     1067:         break;
                   1068:     }
                   1069: 
                   1070:     label_ptr = (void *) s->code_ptr;
1.1.1.6   root     1071:     tcg_out_b_noaddr(s, COND_EQ);
1.1       root     1072: 
                   1073:     /* TODO: move this code to where the constants pool will be */
1.1.1.5   root     1074:     if (addr_reg != TCG_REG_R0) {
                   1075:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1076:                         TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
                   1077:     }
1.1       root     1078: # if TARGET_LONG_BITS == 32
1.1.1.5   root     1079:     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
1.1       root     1080: # else
1.1.1.5   root     1081:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1082:                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
                   1083:     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1084: # endif
1.1.1.7   root     1085:     tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
1.1       root     1086: 
                   1087:     switch (opc) {
                   1088:     case 0 | 4:
1.1.1.5   root     1089:         tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1.1       root     1090:         break;
                   1091:     case 1 | 4:
1.1.1.5   root     1092:         tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1.1       root     1093:         break;
                   1094:     case 0:
                   1095:     case 1:
                   1096:     case 2:
                   1097:     default:
1.1.1.5   root     1098:         if (data_reg != TCG_REG_R0) {
                   1099:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1100:                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
                   1101:         }
1.1       root     1102:         break;
                   1103:     case 3:
1.1.1.5   root     1104:         if (data_reg != TCG_REG_R0) {
                   1105:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1106:                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
                   1107:         }
                   1108:         if (data_reg2 != TCG_REG_R1) {
                   1109:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1110:                             data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
                   1111:         }
1.1       root     1112:         break;
                   1113:     }
                   1114: 
1.1.1.6   root     1115:     reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1.1.1.3   root     1116: #else /* !CONFIG_SOFTMMU */
                   1117:     if (GUEST_BASE) {
                   1118:         uint32_t offset = GUEST_BASE;
                   1119:         int i;
                   1120:         int rot;
                   1121: 
                   1122:         while (offset) {
                   1123:             i = ctz32(offset) & ~1;
                   1124:             rot = ((32 - i) << 7) & 0xf00;
                   1125: 
1.1.1.5   root     1126:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
1.1.1.3   root     1127:                             ((offset >> i) & 0xff) | rot);
1.1.1.5   root     1128:             addr_reg = TCG_REG_R8;
1.1.1.3   root     1129:             offset &= ~(0xff << i);
                   1130:         }
                   1131:     }
1.1       root     1132:     switch (opc) {
                   1133:     case 0:
                   1134:         tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
                   1135:         break;
                   1136:     case 0 | 4:
                   1137:         tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1138:         break;
                   1139:     case 1:
                   1140:         tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1.1.1.5   root     1141:         if (bswap) {
                   1142:             tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
                   1143:         }
1.1       root     1144:         break;
                   1145:     case 1 | 4:
1.1.1.5   root     1146:         if (bswap) {
                   1147:             tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
                   1148:             tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
                   1149:         } else {
                   1150:             tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1151:         }
1.1       root     1152:         break;
                   1153:     case 2:
                   1154:     default:
                   1155:         tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1.1.1.5   root     1156:         if (bswap) {
                   1157:             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
                   1158:         }
1.1       root     1159:         break;
                   1160:     case 3:
                   1161:         /* TODO: use block load -
                   1162:          * check that data_reg2 > data_reg or the other way */
1.1.1.2   root     1163:         if (data_reg == addr_reg) {
1.1.1.5   root     1164:             tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
                   1165:             tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1.1.1.2   root     1166:         } else {
1.1.1.5   root     1167:             tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
                   1168:             tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
                   1169:         }
                   1170:         if (bswap) {
                   1171:             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
                   1172:             tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1.1.1.2   root     1173:         }
1.1       root     1174:         break;
                   1175:     }
                   1176: #endif
                   1177: }
                   1178: 
1.1.1.5   root     1179: static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1.1       root     1180: {
1.1.1.5   root     1181:     int addr_reg, data_reg, data_reg2, bswap;
1.1       root     1182: #ifdef CONFIG_SOFTMMU
                   1183:     int mem_index, s_bits;
                   1184: # if TARGET_LONG_BITS == 64
                   1185:     int addr_reg2;
                   1186: # endif
                   1187:     uint32_t *label_ptr;
                   1188: #endif
                   1189: 
1.1.1.5   root     1190: #ifdef TARGET_WORDS_BIGENDIAN
                   1191:     bswap = 1;
                   1192: #else
                   1193:     bswap = 0;
                   1194: #endif
1.1       root     1195:     data_reg = *args++;
                   1196:     if (opc == 3)
                   1197:         data_reg2 = *args++;
                   1198:     else
1.1.1.3   root     1199:         data_reg2 = 0; /* suppress warning */
1.1       root     1200:     addr_reg = *args++;
                   1201: #ifdef CONFIG_SOFTMMU
                   1202: # if TARGET_LONG_BITS == 64
                   1203:     addr_reg2 = *args++;
                   1204: # endif
                   1205:     mem_index = *args;
                   1206:     s_bits = opc & 3;
                   1207: 
                   1208:     /* Should generate something like the following:
                   1209:      *  shr r8, addr_reg, #TARGET_PAGE_BITS
                   1210:      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
                   1211:      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
                   1212:      */
                   1213:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1.1.1.5   root     1214:                     TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1.1       root     1215:     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1.1.1.5   root     1216:                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
                   1217:     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
                   1218:                     TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1.1       root     1219:     /* In the
                   1220:      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
                   1221:      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
                   1222:      * not exceed otherwise, so use an
                   1223:      *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
                   1224:      * before.
                   1225:      */
                   1226:     if (mem_index)
1.1.1.5   root     1227:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1.1       root     1228:                         (mem_index << (TLB_SHIFT & 1)) |
                   1229:                         ((16 - (TLB_SHIFT >> 1)) << 8));
1.1.1.5   root     1230:     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1.1       root     1231:                     offsetof(CPUState, tlb_table[0][0].addr_write));
1.1.1.5   root     1232:     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                   1233:                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1.1       root     1234:     /* Check alignment.  */
                   1235:     if (s_bits)
                   1236:         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                   1237:                         0, addr_reg, (1 << s_bits) - 1);
                   1238: #  if TARGET_LONG_BITS == 64
                   1239:     /* XXX: possibly we could use a block data load or writeback in
                   1240:      * the first access.  */
1.1.1.5   root     1241:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                   1242:                     offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
                   1243:     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1244:                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1245: #  endif
1.1.1.5   root     1246:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1247:                     offsetof(CPUState, tlb_table[0][0].addend));
                   1248: 
                   1249:     switch (opc) {
                   1250:     case 0:
1.1.1.5   root     1251:         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1252:         break;
                   1253:     case 1:
1.1.1.5   root     1254:         if (bswap) {
                   1255:             tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
                   1256:             tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
                   1257:         } else {
                   1258:             tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1259:         }
1.1       root     1260:         break;
                   1261:     case 2:
                   1262:     default:
1.1.1.5   root     1263:         if (bswap) {
                   1264:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
                   1265:             tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
                   1266:         } else {
                   1267:             tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1268:         }
1.1       root     1269:         break;
                   1270:     case 3:
1.1.1.5   root     1271:         if (bswap) {
                   1272:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
                   1273:             tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
                   1274:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1.1.1.6   root     1275:             tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
1.1.1.5   root     1276:         } else {
                   1277:             tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
                   1278:             tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
                   1279:         }
1.1       root     1280:         break;
                   1281:     }
                   1282: 
                   1283:     label_ptr = (void *) s->code_ptr;
1.1.1.6   root     1284:     tcg_out_b_noaddr(s, COND_EQ);
1.1       root     1285: 
                   1286:     /* TODO: move this code to where the constants pool will be */
1.1.1.5   root     1287:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1288:                     TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1.1       root     1289: # if TARGET_LONG_BITS == 32
                   1290:     switch (opc) {
                   1291:     case 0:
1.1.1.5   root     1292:         tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
                   1293:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1294:         break;
                   1295:     case 1:
1.1.1.5   root     1296:         tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
                   1297:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1298:         break;
                   1299:     case 2:
1.1.1.5   root     1300:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1301:                         TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
                   1302:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1303:         break;
                   1304:     case 3:
1.1.1.5   root     1305:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
                   1306:         tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
                   1307:         if (data_reg != TCG_REG_R2) {
                   1308:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1309:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1310:         }
                   1311:         if (data_reg2 != TCG_REG_R3) {
                   1312:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1313:                             TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1314:         }
1.1       root     1315:         break;
                   1316:     }
                   1317: # else
1.1.1.5   root     1318:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1319:                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1320:     switch (opc) {
                   1321:     case 0:
1.1.1.5   root     1322:         tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
                   1323:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1324:         break;
                   1325:     case 1:
1.1.1.5   root     1326:         tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
                   1327:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1328:         break;
                   1329:     case 2:
1.1.1.5   root     1330:         if (data_reg != TCG_REG_R2) {
                   1331:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1332:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1333:         }
                   1334:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1335:         break;
                   1336:     case 3:
1.1.1.5   root     1337:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
                   1338:         tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
                   1339:         if (data_reg != TCG_REG_R2) {
                   1340:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1341:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1342:         }
                   1343:         if (data_reg2 != TCG_REG_R3) {
                   1344:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1345:                             TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1346:         }
1.1       root     1347:         break;
                   1348:     }
                   1349: # endif
                   1350: 
1.1.1.7   root     1351:     tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
1.1       root     1352:     if (opc == 3)
1.1.1.5   root     1353:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
1.1       root     1354: 
1.1.1.6   root     1355:     reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1.1.1.3   root     1356: #else /* !CONFIG_SOFTMMU */
                   1357:     if (GUEST_BASE) {
                   1358:         uint32_t offset = GUEST_BASE;
                   1359:         int i;
                   1360:         int rot;
                   1361: 
                   1362:         while (offset) {
                   1363:             i = ctz32(offset) & ~1;
                   1364:             rot = ((32 - i) << 7) & 0xf00;
                   1365: 
1.1.1.5   root     1366:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1.1.1.3   root     1367:                             ((offset >> i) & 0xff) | rot);
1.1.1.5   root     1368:             addr_reg = TCG_REG_R1;
1.1.1.3   root     1369:             offset &= ~(0xff << i);
                   1370:         }
                   1371:     }
1.1       root     1372:     switch (opc) {
                   1373:     case 0:
                   1374:         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
                   1375:         break;
                   1376:     case 1:
1.1.1.5   root     1377:         if (bswap) {
                   1378:             tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
                   1379:             tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1380:         } else {
                   1381:             tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
                   1382:         }
1.1       root     1383:         break;
                   1384:     case 2:
                   1385:     default:
1.1.1.5   root     1386:         if (bswap) {
                   1387:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
                   1388:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1389:         } else {
                   1390:             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1391:         }
1.1       root     1392:         break;
                   1393:     case 3:
                   1394:         /* TODO: use block store -
                   1395:          * check that data_reg2 > data_reg or the other way */
1.1.1.5   root     1396:         if (bswap) {
                   1397:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
                   1398:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1399:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
                   1400:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
                   1401:         } else {
                   1402:             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1403:             tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
                   1404:         }
1.1       root     1405:         break;
                   1406:     }
                   1407: #endif
                   1408: }
                   1409: 
                   1410: static uint8_t *tb_ret_addr;
                   1411: 
1.1.1.5   root     1412: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1       root     1413:                 const TCGArg *args, const int *const_args)
                   1414: {
                   1415:     int c;
                   1416: 
                   1417:     switch (opc) {
                   1418:     case INDEX_op_exit_tb:
                   1419:         {
                   1420:             uint8_t *ld_ptr = s->code_ptr;
                   1421:             if (args[0] >> 8)
1.1.1.5   root     1422:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1.1       root     1423:             else
1.1.1.5   root     1424:                 tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1.1       root     1425:             tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
                   1426:             if (args[0] >> 8) {
                   1427:                 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
                   1428:                 tcg_out32(s, args[0]);
                   1429:             }
                   1430:         }
                   1431:         break;
                   1432:     case INDEX_op_goto_tb:
                   1433:         if (s->tb_jmp_offset) {
                   1434:             /* Direct jump method */
                   1435: #if defined(USE_DIRECT_JUMP)
                   1436:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1.1.1.6   root     1437:             tcg_out_b_noaddr(s, COND_AL);
1.1       root     1438: #else
1.1.1.5   root     1439:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root     1440:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                   1441:             tcg_out32(s, 0);
                   1442: #endif
                   1443:         } else {
                   1444:             /* Indirect jump method */
                   1445: #if 1
                   1446:             c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
                   1447:             if (c > 0xfff || c < -0xfff) {
                   1448:                 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
                   1449:                                 (tcg_target_long) (s->tb_next + args[0]));
1.1.1.5   root     1450:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1.1       root     1451:             } else
1.1.1.5   root     1452:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1.1       root     1453: #else
1.1.1.5   root     1454:             tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
                   1455:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1.1       root     1456:             tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
                   1457: #endif
                   1458:         }
                   1459:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                   1460:         break;
                   1461:     case INDEX_op_call:
                   1462:         if (const_args[0])
1.1.1.7   root     1463:             tcg_out_call(s, args[0]);
1.1       root     1464:         else
                   1465:             tcg_out_callr(s, COND_AL, args[0]);
                   1466:         break;
                   1467:     case INDEX_op_jmp:
                   1468:         if (const_args[0])
                   1469:             tcg_out_goto(s, COND_AL, args[0]);
                   1470:         else
                   1471:             tcg_out_bx(s, COND_AL, args[0]);
                   1472:         break;
                   1473:     case INDEX_op_br:
                   1474:         tcg_out_goto_label(s, COND_AL, args[0]);
                   1475:         break;
                   1476: 
                   1477:     case INDEX_op_ld8u_i32:
                   1478:         tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
                   1479:         break;
                   1480:     case INDEX_op_ld8s_i32:
                   1481:         tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
                   1482:         break;
                   1483:     case INDEX_op_ld16u_i32:
                   1484:         tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
                   1485:         break;
                   1486:     case INDEX_op_ld16s_i32:
                   1487:         tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
                   1488:         break;
                   1489:     case INDEX_op_ld_i32:
                   1490:         tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
                   1491:         break;
                   1492:     case INDEX_op_st8_i32:
1.1.1.5   root     1493:         tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1.1       root     1494:         break;
                   1495:     case INDEX_op_st16_i32:
1.1.1.5   root     1496:         tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1.1       root     1497:         break;
                   1498:     case INDEX_op_st_i32:
                   1499:         tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
                   1500:         break;
                   1501: 
                   1502:     case INDEX_op_mov_i32:
                   1503:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1504:                         args[0], 0, args[1], SHIFT_IMM_LSL(0));
                   1505:         break;
                   1506:     case INDEX_op_movi_i32:
                   1507:         tcg_out_movi32(s, COND_AL, args[0], args[1]);
                   1508:         break;
                   1509:     case INDEX_op_add_i32:
                   1510:         c = ARITH_ADD;
                   1511:         goto gen_arith;
                   1512:     case INDEX_op_sub_i32:
                   1513:         c = ARITH_SUB;
                   1514:         goto gen_arith;
                   1515:     case INDEX_op_and_i32:
                   1516:         c = ARITH_AND;
                   1517:         goto gen_arith;
1.1.1.5   root     1518:     case INDEX_op_andc_i32:
                   1519:         c = ARITH_BIC;
                   1520:         goto gen_arith;
1.1       root     1521:     case INDEX_op_or_i32:
                   1522:         c = ARITH_ORR;
                   1523:         goto gen_arith;
                   1524:     case INDEX_op_xor_i32:
                   1525:         c = ARITH_EOR;
                   1526:         /* Fall through.  */
                   1527:     gen_arith:
1.1.1.3   root     1528:         if (const_args[2]) {
                   1529:             int rot;
                   1530:             rot = encode_imm(args[2]);
                   1531:             tcg_out_dat_imm(s, COND_AL, c,
                   1532:                             args[0], args[1], rotl(args[2], rot) | (rot << 7));
                   1533:         } else
                   1534:             tcg_out_dat_reg(s, COND_AL, c,
                   1535:                             args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1.1       root     1536:         break;
                   1537:     case INDEX_op_add2_i32:
                   1538:         tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
                   1539:                         args[0], args[1], args[2], args[3],
                   1540:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1541:         break;
                   1542:     case INDEX_op_sub2_i32:
                   1543:         tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
                   1544:                         args[0], args[1], args[2], args[3],
                   1545:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1546:         break;
                   1547:     case INDEX_op_neg_i32:
                   1548:         tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
                   1549:         break;
1.1.1.3   root     1550:     case INDEX_op_not_i32:
                   1551:         tcg_out_dat_reg(s, COND_AL,
                   1552:                         ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
                   1553:         break;
1.1       root     1554:     case INDEX_op_mul_i32:
                   1555:         tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
                   1556:         break;
                   1557:     case INDEX_op_mulu2_i32:
                   1558:         tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
                   1559:         break;
                   1560:     /* XXX: Perhaps args[2] & 0x1f is wrong */
                   1561:     case INDEX_op_shl_i32:
                   1562:         c = const_args[2] ?
                   1563:                 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
                   1564:         goto gen_shift32;
                   1565:     case INDEX_op_shr_i32:
                   1566:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
                   1567:                 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
                   1568:         goto gen_shift32;
                   1569:     case INDEX_op_sar_i32:
                   1570:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
                   1571:                 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1.1.1.5   root     1572:         goto gen_shift32;
                   1573:     case INDEX_op_rotr_i32:
                   1574:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
                   1575:                 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1.1       root     1576:         /* Fall through.  */
                   1577:     gen_shift32:
                   1578:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
                   1579:         break;
                   1580: 
1.1.1.5   root     1581:     case INDEX_op_rotl_i32:
                   1582:         if (const_args[2]) {
                   1583:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
                   1584:                             ((0x20 - args[2]) & 0x1f) ?
                   1585:                             SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
                   1586:                             SHIFT_IMM_LSL(0));
                   1587:         } else {
                   1588:             tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
                   1589:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
                   1590:                             SHIFT_REG_ROR(TCG_REG_R8));
                   1591:         }
                   1592:         break;
                   1593: 
1.1       root     1594:     case INDEX_op_brcond_i32:
1.1.1.5   root     1595:         if (const_args[1]) {
                   1596:             int rot;
                   1597:             rot = encode_imm(args[1]);
                   1598:             tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
                   1599:                             args[0], rotl(args[1], rot) | (rot << 7));
                   1600:         } else {
                   1601:             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1602:                             args[0], args[1], SHIFT_IMM_LSL(0));
                   1603:         }
1.1       root     1604:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
                   1605:         break;
                   1606:     case INDEX_op_brcond2_i32:
                   1607:         /* The resulting conditions are:
                   1608:          * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
                   1609:          * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
                   1610:          * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
                   1611:          * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
                   1612:          * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
                   1613:          * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
                   1614:          */
                   1615:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1616:                         args[1], args[3], SHIFT_IMM_LSL(0));
                   1617:         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1618:                         args[0], args[2], SHIFT_IMM_LSL(0));
                   1619:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
                   1620:         break;
1.1.1.5   root     1621:     case INDEX_op_setcond_i32:
                   1622:         if (const_args[2]) {
                   1623:             int rot;
                   1624:             rot = encode_imm(args[2]);
                   1625:             tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
                   1626:                             args[1], rotl(args[2], rot) | (rot << 7));
                   1627:         } else {
                   1628:             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1629:                             args[1], args[2], SHIFT_IMM_LSL(0));
                   1630:         }
                   1631:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
                   1632:                         ARITH_MOV, args[0], 0, 1);
                   1633:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
                   1634:                         ARITH_MOV, args[0], 0, 0);
                   1635:         break;
                   1636:     case INDEX_op_setcond2_i32:
                   1637:         /* See brcond2_i32 comment */
                   1638:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1639:                         args[2], args[4], SHIFT_IMM_LSL(0));
                   1640:         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1641:                         args[1], args[3], SHIFT_IMM_LSL(0));
                   1642:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
                   1643:                         ARITH_MOV, args[0], 0, 1);
                   1644:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
                   1645:                         ARITH_MOV, args[0], 0, 0);
                   1646:         break;
1.1       root     1647: 
                   1648:     case INDEX_op_qemu_ld8u:
1.1.1.5   root     1649:         tcg_out_qemu_ld(s, args, 0);
1.1       root     1650:         break;
                   1651:     case INDEX_op_qemu_ld8s:
1.1.1.5   root     1652:         tcg_out_qemu_ld(s, args, 0 | 4);
1.1       root     1653:         break;
                   1654:     case INDEX_op_qemu_ld16u:
1.1.1.5   root     1655:         tcg_out_qemu_ld(s, args, 1);
1.1       root     1656:         break;
                   1657:     case INDEX_op_qemu_ld16s:
1.1.1.5   root     1658:         tcg_out_qemu_ld(s, args, 1 | 4);
1.1       root     1659:         break;
1.1.1.5   root     1660:     case INDEX_op_qemu_ld32:
                   1661:         tcg_out_qemu_ld(s, args, 2);
1.1       root     1662:         break;
                   1663:     case INDEX_op_qemu_ld64:
1.1.1.5   root     1664:         tcg_out_qemu_ld(s, args, 3);
1.1       root     1665:         break;
                   1666: 
                   1667:     case INDEX_op_qemu_st8:
1.1.1.5   root     1668:         tcg_out_qemu_st(s, args, 0);
1.1       root     1669:         break;
                   1670:     case INDEX_op_qemu_st16:
1.1.1.5   root     1671:         tcg_out_qemu_st(s, args, 1);
1.1       root     1672:         break;
                   1673:     case INDEX_op_qemu_st32:
1.1.1.5   root     1674:         tcg_out_qemu_st(s, args, 2);
1.1       root     1675:         break;
                   1676:     case INDEX_op_qemu_st64:
1.1.1.5   root     1677:         tcg_out_qemu_st(s, args, 3);
                   1678:         break;
                   1679: 
                   1680:     case INDEX_op_bswap16_i32:
                   1681:         tcg_out_bswap16(s, COND_AL, args[0], args[1]);
                   1682:         break;
                   1683:     case INDEX_op_bswap32_i32:
                   1684:         tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1.1       root     1685:         break;
                   1686: 
                   1687:     case INDEX_op_ext8s_i32:
1.1.1.5   root     1688:         tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1.1       root     1689:         break;
                   1690:     case INDEX_op_ext16s_i32:
1.1.1.5   root     1691:         tcg_out_ext16s(s, COND_AL, args[0], args[1]);
                   1692:         break;
                   1693:     case INDEX_op_ext16u_i32:
                   1694:         tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1.1       root     1695:         break;
                   1696: 
                   1697:     default:
                   1698:         tcg_abort();
                   1699:     }
                   1700: }
                   1701: 
                   1702: static const TCGTargetOpDef arm_op_defs[] = {
                   1703:     { INDEX_op_exit_tb, { } },
                   1704:     { INDEX_op_goto_tb, { } },
                   1705:     { INDEX_op_call, { "ri" } },
                   1706:     { INDEX_op_jmp, { "ri" } },
                   1707:     { INDEX_op_br, { } },
                   1708: 
                   1709:     { INDEX_op_mov_i32, { "r", "r" } },
                   1710:     { INDEX_op_movi_i32, { "r" } },
                   1711: 
                   1712:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1713:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1714:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1715:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1716:     { INDEX_op_ld_i32, { "r", "r" } },
                   1717:     { INDEX_op_st8_i32, { "r", "r" } },
                   1718:     { INDEX_op_st16_i32, { "r", "r" } },
                   1719:     { INDEX_op_st_i32, { "r", "r" } },
                   1720: 
                   1721:     /* TODO: "r", "r", "ri" */
1.1.1.3   root     1722:     { INDEX_op_add_i32, { "r", "r", "rI" } },
                   1723:     { INDEX_op_sub_i32, { "r", "r", "rI" } },
1.1       root     1724:     { INDEX_op_mul_i32, { "r", "r", "r" } },
                   1725:     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1.1.1.3   root     1726:     { INDEX_op_and_i32, { "r", "r", "rI" } },
1.1.1.5   root     1727:     { INDEX_op_andc_i32, { "r", "r", "rI" } },
1.1.1.3   root     1728:     { INDEX_op_or_i32, { "r", "r", "rI" } },
                   1729:     { INDEX_op_xor_i32, { "r", "r", "rI" } },
1.1       root     1730:     { INDEX_op_neg_i32, { "r", "r" } },
1.1.1.3   root     1731:     { INDEX_op_not_i32, { "r", "r" } },
1.1       root     1732: 
                   1733:     { INDEX_op_shl_i32, { "r", "r", "ri" } },
                   1734:     { INDEX_op_shr_i32, { "r", "r", "ri" } },
                   1735:     { INDEX_op_sar_i32, { "r", "r", "ri" } },
1.1.1.5   root     1736:     { INDEX_op_rotl_i32, { "r", "r", "ri" } },
                   1737:     { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1.1       root     1738: 
1.1.1.5   root     1739:     { INDEX_op_brcond_i32, { "r", "rI" } },
                   1740:     { INDEX_op_setcond_i32, { "r", "r", "rI" } },
1.1       root     1741: 
                   1742:     /* TODO: "r", "r", "r", "r", "ri", "ri" */
                   1743:     { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1744:     { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1745:     { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1.1.1.5   root     1746:     { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
                   1747: 
                   1748: #if TARGET_LONG_BITS == 32
                   1749:     { INDEX_op_qemu_ld8u, { "r", "l" } },
                   1750:     { INDEX_op_qemu_ld8s, { "r", "l" } },
                   1751:     { INDEX_op_qemu_ld16u, { "r", "l" } },
                   1752:     { INDEX_op_qemu_ld16s, { "r", "l" } },
                   1753:     { INDEX_op_qemu_ld32, { "r", "l" } },
                   1754:     { INDEX_op_qemu_ld64, { "L", "L", "l" } },
                   1755: 
                   1756:     { INDEX_op_qemu_st8, { "s", "s" } },
                   1757:     { INDEX_op_qemu_st16, { "s", "s" } },
                   1758:     { INDEX_op_qemu_st32, { "s", "s" } },
                   1759:     { INDEX_op_qemu_st64, { "S", "S", "s" } },
                   1760: #else
                   1761:     { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
                   1762:     { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
                   1763:     { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
                   1764:     { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
                   1765:     { INDEX_op_qemu_ld32, { "r", "l", "l" } },
                   1766:     { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
                   1767: 
                   1768:     { INDEX_op_qemu_st8, { "s", "s", "s" } },
                   1769:     { INDEX_op_qemu_st16, { "s", "s", "s" } },
                   1770:     { INDEX_op_qemu_st32, { "s", "s", "s" } },
                   1771:     { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
                   1772: #endif
1.1       root     1773: 
1.1.1.5   root     1774:     { INDEX_op_bswap16_i32, { "r", "r" } },
                   1775:     { INDEX_op_bswap32_i32, { "r", "r" } },
1.1       root     1776: 
                   1777:     { INDEX_op_ext8s_i32, { "r", "r" } },
                   1778:     { INDEX_op_ext16s_i32, { "r", "r" } },
1.1.1.5   root     1779:     { INDEX_op_ext16u_i32, { "r", "r" } },
1.1       root     1780: 
                   1781:     { -1 },
                   1782: };
                   1783: 
1.1.1.5   root     1784: static void tcg_target_init(TCGContext *s)
1.1       root     1785: {
1.1.1.5   root     1786: #if !defined(CONFIG_USER_ONLY)
1.1       root     1787:     /* fail safe */
                   1788:     if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
                   1789:         tcg_abort();
1.1.1.5   root     1790: #endif
1.1       root     1791: 
1.1.1.5   root     1792:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1.1       root     1793:     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1.1.1.5   root     1794:                      (1 << TCG_REG_R0) |
                   1795:                      (1 << TCG_REG_R1) |
                   1796:                      (1 << TCG_REG_R2) |
                   1797:                      (1 << TCG_REG_R3) |
                   1798:                      (1 << TCG_REG_R12) |
                   1799:                      (1 << TCG_REG_R14));
1.1       root     1800: 
                   1801:     tcg_regset_clear(s->reserved_regs);
                   1802:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
                   1803:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1.1.1.5   root     1804:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
1.1       root     1805: 
                   1806:     tcg_add_target_add_op_defs(arm_op_defs);
1.1.1.7   root     1807:     tcg_set_frame(s, TCG_AREG0, offsetof(CPUState, temp_buf),
                   1808:                   CPU_TEMP_BUF_NLONGS * sizeof(long));
1.1       root     1809: }
                   1810: 
1.1.1.8 ! root     1811: static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
        !          1812:                               TCGReg arg1, tcg_target_long arg2)
1.1       root     1813: {
                   1814:     tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
                   1815: }
                   1816: 
1.1.1.8 ! root     1817: static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
        !          1818:                               TCGReg arg1, tcg_target_long arg2)
1.1       root     1819: {
                   1820:     tcg_out_st32(s, COND_AL, arg, arg1, arg2);
                   1821: }
                   1822: 
1.1.1.8 ! root     1823: static inline void tcg_out_mov(TCGContext *s, TCGType type,
        !          1824:                                TCGReg ret, TCGReg arg)
1.1       root     1825: {
                   1826:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
                   1827: }
                   1828: 
                   1829: static inline void tcg_out_movi(TCGContext *s, TCGType type,
1.1.1.8 ! root     1830:                                 TCGReg ret, tcg_target_long arg)
1.1       root     1831: {
                   1832:     tcg_out_movi32(s, COND_AL, ret, arg);
                   1833: }
                   1834: 
1.1.1.5   root     1835: static void tcg_target_qemu_prologue(TCGContext *s)
1.1       root     1836: {
1.1.1.7   root     1837:     /* Calling convention requires us to save r4-r11 and lr;
                   1838:      * save also r12 to maintain stack 8-alignment.
                   1839:      */
                   1840: 
                   1841:     /* stmdb sp!, { r4 - r12, lr } */
                   1842:     tcg_out32(s, (COND_AL << 28) | 0x092d5ff0);
1.1.1.4   root     1843: 
1.1.1.7   root     1844:     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1.1       root     1845: 
1.1.1.7   root     1846:     tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]);
1.1       root     1847:     tb_ret_addr = s->code_ptr;
                   1848: 
1.1.1.7   root     1849:     /* ldmia sp!, { r4 - r12, pc } */
                   1850:     tcg_out32(s, (COND_AL << 28) | 0x08bd9ff0);
1.1       root     1851: }

unix.superglobalmegacorp.com

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