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

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       root      378: static inline void tcg_out_dat_reg(TCGContext *s,
                    379:                 int cond, int opc, int rd, int rn, int rm, int shift)
                    380: {
                    381:     tcg_out32(s, (cond << 28) | (0 << 25) | (opc << 21) | TO_CPSR(opc) |
                    382:                     (rn << 16) | (rd << 12) | shift | rm);
                    383: }
                    384: 
                    385: static inline void tcg_out_dat_reg2(TCGContext *s,
                    386:                 int cond, int opc0, int opc1, int rd0, int rd1,
                    387:                 int rn0, int rn1, int rm0, int rm1, int shift)
                    388: {
                    389:     if (rd0 == rn1 || rd0 == rm1) {
                    390:         tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
                    391:                         (rn0 << 16) | (8 << 12) | shift | rm0);
                    392:         tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
                    393:                         (rn1 << 16) | (rd1 << 12) | shift | rm1);
                    394:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    395:                         rd0, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
                    396:     } else {
                    397:         tcg_out32(s, (cond << 28) | (0 << 25) | (opc0 << 21) | (1 << 20) |
                    398:                         (rn0 << 16) | (rd0 << 12) | shift | rm0);
                    399:         tcg_out32(s, (cond << 28) | (0 << 25) | (opc1 << 21) |
                    400:                         (rn1 << 16) | (rd1 << 12) | shift | rm1);
                    401:     }
                    402: }
                    403: 
                    404: static inline void tcg_out_dat_imm(TCGContext *s,
                    405:                 int cond, int opc, int rd, int rn, int im)
                    406: {
                    407:     tcg_out32(s, (cond << 28) | (1 << 25) | (opc << 21) | TO_CPSR(opc) |
                    408:                     (rn << 16) | (rd << 12) | im);
                    409: }
                    410: 
                    411: static inline void tcg_out_movi32(TCGContext *s,
1.1.1.6 ! root      412:                 int cond, int rd, uint32_t arg)
1.1       root      413: {
                    414:     /* TODO: This is very suboptimal, we can easily have a constant
                    415:      * pool somewhere after all the instructions.  */
1.1.1.6 ! root      416:     if ((int)arg < 0 && (int)arg >= -0x100) {
        !           417:         tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
        !           418:     } else if (use_armv7_instructions) {
1.1.1.5   root      419:         /* use movw/movt */
                    420:         /* movw */
                    421:         tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
                    422:                   | ((arg << 4) & 0x000f0000) | (arg & 0xfff));
1.1.1.6 ! root      423:         if (arg & 0xffff0000) {
1.1.1.5   root      424:             /* movt */
                    425:             tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
                    426:                       | ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
                    427:         }
1.1.1.6 ! root      428:     } else {
        !           429:         int opc = ARITH_MOV;
        !           430:         int rn = 0;
        !           431: 
        !           432:         do {
        !           433:             int i, rot;
        !           434: 
        !           435:             i = ctz32(arg) & ~1;
        !           436:             rot = ((32 - i) << 7) & 0xf00;
        !           437:             tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
        !           438:             arg &= ~(0xff << i);
        !           439: 
        !           440:             opc = ARITH_ORR;
        !           441:             rn = rd;
        !           442:         } while (arg);
        !           443:     }
1.1       root      444: }
                    445: 
                    446: static inline void tcg_out_mul32(TCGContext *s,
                    447:                 int cond, int rd, int rs, int rm)
                    448: {
                    449:     if (rd != rm)
                    450:         tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
                    451:                         (rs << 8) | 0x90 | rm);
                    452:     else if (rd != rs)
                    453:         tcg_out32(s, (cond << 28) | (rd << 16) | (0 << 12) |
                    454:                         (rm << 8) | 0x90 | rs);
                    455:     else {
                    456:         tcg_out32(s, (cond << 28) | ( 8 << 16) | (0 << 12) |
                    457:                         (rs << 8) | 0x90 | rm);
                    458:         tcg_out_dat_reg(s, cond, ARITH_MOV,
1.1.1.5   root      459:                         rd, 0, TCG_REG_R8, SHIFT_IMM_LSL(0));
1.1       root      460:     }
                    461: }
                    462: 
                    463: static inline void tcg_out_umull32(TCGContext *s,
                    464:                 int cond, int rd0, int rd1, int rs, int rm)
                    465: {
                    466:     if (rd0 != rm && rd1 != rm)
                    467:         tcg_out32(s, (cond << 28) | 0x800090 |
                    468:                         (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
                    469:     else if (rd0 != rs && rd1 != rs)
                    470:         tcg_out32(s, (cond << 28) | 0x800090 |
                    471:                         (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
                    472:     else {
                    473:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    474:                         TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
                    475:         tcg_out32(s, (cond << 28) | 0x800098 |
                    476:                         (rd1 << 16) | (rd0 << 12) | (rs << 8));
                    477:     }
                    478: }
                    479: 
                    480: static inline void tcg_out_smull32(TCGContext *s,
                    481:                 int cond, int rd0, int rd1, int rs, int rm)
                    482: {
                    483:     if (rd0 != rm && rd1 != rm)
                    484:         tcg_out32(s, (cond << 28) | 0xc00090 |
                    485:                         (rd1 << 16) | (rd0 << 12) | (rs << 8) | rm);
                    486:     else if (rd0 != rs && rd1 != rs)
                    487:         tcg_out32(s, (cond << 28) | 0xc00090 |
                    488:                         (rd1 << 16) | (rd0 << 12) | (rm << 8) | rs);
                    489:     else {
                    490:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    491:                         TCG_REG_R8, 0, rm, SHIFT_IMM_LSL(0));
                    492:         tcg_out32(s, (cond << 28) | 0xc00098 |
                    493:                         (rd1 << 16) | (rd0 << 12) | (rs << 8));
                    494:     }
                    495: }
                    496: 
1.1.1.5   root      497: static inline void tcg_out_ext8s(TCGContext *s, int cond,
                    498:                                  int rd, int rn)
                    499: {
                    500:     if (use_armv6_instructions) {
                    501:         /* sxtb */
                    502:         tcg_out32(s, 0x06af0070 | (cond << 28) | (rd << 12) | rn);
                    503:     } else {
                    504:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    505:                         rd, 0, rn, SHIFT_IMM_LSL(24));
                    506:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    507:                         rd, 0, rd, SHIFT_IMM_ASR(24));
                    508:     }
                    509: }
                    510: 
                    511: static inline void tcg_out_ext8u(TCGContext *s, int cond,
                    512:                                  int rd, int rn)
                    513: {
                    514:     tcg_out_dat_imm(s, cond, ARITH_AND, rd, rn, 0xff);
                    515: }
                    516: 
                    517: static inline void tcg_out_ext16s(TCGContext *s, int cond,
                    518:                                   int rd, int rn)
                    519: {
                    520:     if (use_armv6_instructions) {
                    521:         /* sxth */
                    522:         tcg_out32(s, 0x06bf0070 | (cond << 28) | (rd << 12) | rn);
                    523:     } else {
                    524:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    525:                         rd, 0, rn, SHIFT_IMM_LSL(16));
                    526:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    527:                         rd, 0, rd, SHIFT_IMM_ASR(16));
                    528:     }
                    529: }
                    530: 
                    531: static inline void tcg_out_ext16u(TCGContext *s, int cond,
                    532:                                   int rd, int rn)
                    533: {
                    534:     if (use_armv6_instructions) {
                    535:         /* uxth */
                    536:         tcg_out32(s, 0x06ff0070 | (cond << 28) | (rd << 12) | rn);
                    537:     } else {
                    538:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    539:                         rd, 0, rn, SHIFT_IMM_LSL(16));
                    540:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    541:                         rd, 0, rd, SHIFT_IMM_LSR(16));
                    542:     }
                    543: }
                    544: 
                    545: static inline void tcg_out_bswap16s(TCGContext *s, int cond, int rd, int rn)
                    546: {
                    547:     if (use_armv6_instructions) {
                    548:         /* revsh */
                    549:         tcg_out32(s, 0x06ff0fb0 | (cond << 28) | (rd << 12) | rn);
                    550:     } else {
                    551:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    552:                         TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
                    553:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    554:                         TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_ASR(16));
                    555:         tcg_out_dat_reg(s, cond, ARITH_ORR,
                    556:                         rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
                    557:     }
                    558: }
                    559: 
                    560: static inline void tcg_out_bswap16(TCGContext *s, int cond, int rd, int rn)
                    561: {
                    562:     if (use_armv6_instructions) {
                    563:         /* rev16 */
                    564:         tcg_out32(s, 0x06bf0fb0 | (cond << 28) | (rd << 12) | rn);
                    565:     } else {
                    566:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    567:                         TCG_REG_R8, 0, rn, SHIFT_IMM_LSL(24));
                    568:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    569:                         TCG_REG_R8, 0, TCG_REG_R8, SHIFT_IMM_LSR(16));
                    570:         tcg_out_dat_reg(s, cond, ARITH_ORR,
                    571:                         rd, TCG_REG_R8, rn, SHIFT_IMM_LSR(8));
                    572:     }
                    573: }
                    574: 
                    575: static inline void tcg_out_bswap32(TCGContext *s, int cond, int rd, int rn)
                    576: {
                    577:     if (use_armv6_instructions) {
                    578:         /* rev */
                    579:         tcg_out32(s, 0x06bf0f30 | (cond << 28) | (rd << 12) | rn);
                    580:     } else {
                    581:         tcg_out_dat_reg(s, cond, ARITH_EOR,
                    582:                         TCG_REG_R8, rn, rn, SHIFT_IMM_ROR(16));
                    583:         tcg_out_dat_imm(s, cond, ARITH_BIC,
                    584:                         TCG_REG_R8, TCG_REG_R8, 0xff | 0x800);
                    585:         tcg_out_dat_reg(s, cond, ARITH_MOV,
                    586:                         rd, 0, rn, SHIFT_IMM_ROR(8));
                    587:         tcg_out_dat_reg(s, cond, ARITH_EOR,
                    588:                         rd, rd, TCG_REG_R8, SHIFT_IMM_LSR(8));
                    589:     }
                    590: }
                    591: 
1.1       root      592: static inline void tcg_out_ld32_12(TCGContext *s, int cond,
                    593:                 int rd, int rn, tcg_target_long im)
                    594: {
                    595:     if (im >= 0)
                    596:         tcg_out32(s, (cond << 28) | 0x05900000 |
                    597:                         (rn << 16) | (rd << 12) | (im & 0xfff));
                    598:     else
                    599:         tcg_out32(s, (cond << 28) | 0x05100000 |
                    600:                         (rn << 16) | (rd << 12) | ((-im) & 0xfff));
                    601: }
                    602: 
                    603: static inline void tcg_out_st32_12(TCGContext *s, int cond,
                    604:                 int rd, int rn, tcg_target_long im)
                    605: {
                    606:     if (im >= 0)
                    607:         tcg_out32(s, (cond << 28) | 0x05800000 |
                    608:                         (rn << 16) | (rd << 12) | (im & 0xfff));
                    609:     else
                    610:         tcg_out32(s, (cond << 28) | 0x05000000 |
                    611:                         (rn << 16) | (rd << 12) | ((-im) & 0xfff));
                    612: }
                    613: 
                    614: static inline void tcg_out_ld32_r(TCGContext *s, int cond,
                    615:                 int rd, int rn, int rm)
                    616: {
                    617:     tcg_out32(s, (cond << 28) | 0x07900000 |
                    618:                     (rn << 16) | (rd << 12) | rm);
                    619: }
                    620: 
                    621: static inline void tcg_out_st32_r(TCGContext *s, int cond,
                    622:                 int rd, int rn, int rm)
                    623: {
                    624:     tcg_out32(s, (cond << 28) | 0x07800000 |
                    625:                     (rn << 16) | (rd << 12) | rm);
                    626: }
                    627: 
                    628: /* Register pre-increment with base writeback.  */
                    629: static inline void tcg_out_ld32_rwb(TCGContext *s, int cond,
                    630:                 int rd, int rn, int rm)
                    631: {
                    632:     tcg_out32(s, (cond << 28) | 0x07b00000 |
                    633:                     (rn << 16) | (rd << 12) | rm);
                    634: }
                    635: 
                    636: static inline void tcg_out_st32_rwb(TCGContext *s, int cond,
                    637:                 int rd, int rn, int rm)
                    638: {
                    639:     tcg_out32(s, (cond << 28) | 0x07a00000 |
                    640:                     (rn << 16) | (rd << 12) | rm);
                    641: }
                    642: 
                    643: static inline void tcg_out_ld16u_8(TCGContext *s, int cond,
                    644:                 int rd, int rn, tcg_target_long im)
                    645: {
                    646:     if (im >= 0)
                    647:         tcg_out32(s, (cond << 28) | 0x01d000b0 |
                    648:                         (rn << 16) | (rd << 12) |
                    649:                         ((im & 0xf0) << 4) | (im & 0xf));
                    650:     else
                    651:         tcg_out32(s, (cond << 28) | 0x015000b0 |
                    652:                         (rn << 16) | (rd << 12) |
                    653:                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
                    654: }
                    655: 
1.1.1.5   root      656: static inline void tcg_out_st16_8(TCGContext *s, int cond,
1.1       root      657:                 int rd, int rn, tcg_target_long im)
                    658: {
                    659:     if (im >= 0)
                    660:         tcg_out32(s, (cond << 28) | 0x01c000b0 |
                    661:                         (rn << 16) | (rd << 12) |
                    662:                         ((im & 0xf0) << 4) | (im & 0xf));
                    663:     else
                    664:         tcg_out32(s, (cond << 28) | 0x014000b0 |
                    665:                         (rn << 16) | (rd << 12) |
                    666:                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
                    667: }
                    668: 
                    669: static inline void tcg_out_ld16u_r(TCGContext *s, int cond,
                    670:                 int rd, int rn, int rm)
                    671: {
                    672:     tcg_out32(s, (cond << 28) | 0x019000b0 |
                    673:                     (rn << 16) | (rd << 12) | rm);
                    674: }
                    675: 
1.1.1.5   root      676: static inline void tcg_out_st16_r(TCGContext *s, int cond,
1.1       root      677:                 int rd, int rn, int rm)
                    678: {
                    679:     tcg_out32(s, (cond << 28) | 0x018000b0 |
                    680:                     (rn << 16) | (rd << 12) | rm);
                    681: }
                    682: 
                    683: static inline void tcg_out_ld16s_8(TCGContext *s, int cond,
                    684:                 int rd, int rn, tcg_target_long im)
                    685: {
                    686:     if (im >= 0)
                    687:         tcg_out32(s, (cond << 28) | 0x01d000f0 |
                    688:                         (rn << 16) | (rd << 12) |
                    689:                         ((im & 0xf0) << 4) | (im & 0xf));
                    690:     else
                    691:         tcg_out32(s, (cond << 28) | 0x015000f0 |
                    692:                         (rn << 16) | (rd << 12) |
                    693:                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
                    694: }
                    695: 
                    696: static inline void tcg_out_ld16s_r(TCGContext *s, int cond,
                    697:                 int rd, int rn, int rm)
                    698: {
                    699:     tcg_out32(s, (cond << 28) | 0x019000f0 |
                    700:                     (rn << 16) | (rd << 12) | rm);
                    701: }
                    702: 
                    703: static inline void tcg_out_ld8_12(TCGContext *s, int cond,
                    704:                 int rd, int rn, tcg_target_long im)
                    705: {
                    706:     if (im >= 0)
                    707:         tcg_out32(s, (cond << 28) | 0x05d00000 |
                    708:                         (rn << 16) | (rd << 12) | (im & 0xfff));
                    709:     else
                    710:         tcg_out32(s, (cond << 28) | 0x05500000 |
                    711:                         (rn << 16) | (rd << 12) | ((-im) & 0xfff));
                    712: }
                    713: 
                    714: static inline void tcg_out_st8_12(TCGContext *s, int cond,
                    715:                 int rd, int rn, tcg_target_long im)
                    716: {
                    717:     if (im >= 0)
                    718:         tcg_out32(s, (cond << 28) | 0x05c00000 |
                    719:                         (rn << 16) | (rd << 12) | (im & 0xfff));
                    720:     else
                    721:         tcg_out32(s, (cond << 28) | 0x05400000 |
                    722:                         (rn << 16) | (rd << 12) | ((-im) & 0xfff));
                    723: }
                    724: 
                    725: static inline void tcg_out_ld8_r(TCGContext *s, int cond,
                    726:                 int rd, int rn, int rm)
                    727: {
                    728:     tcg_out32(s, (cond << 28) | 0x07d00000 |
                    729:                     (rn << 16) | (rd << 12) | rm);
                    730: }
                    731: 
                    732: static inline void tcg_out_st8_r(TCGContext *s, int cond,
                    733:                 int rd, int rn, int rm)
                    734: {
                    735:     tcg_out32(s, (cond << 28) | 0x07c00000 |
                    736:                     (rn << 16) | (rd << 12) | rm);
                    737: }
                    738: 
                    739: static inline void tcg_out_ld8s_8(TCGContext *s, int cond,
                    740:                 int rd, int rn, tcg_target_long im)
                    741: {
                    742:     if (im >= 0)
                    743:         tcg_out32(s, (cond << 28) | 0x01d000d0 |
                    744:                         (rn << 16) | (rd << 12) |
                    745:                         ((im & 0xf0) << 4) | (im & 0xf));
                    746:     else
                    747:         tcg_out32(s, (cond << 28) | 0x015000d0 |
                    748:                         (rn << 16) | (rd << 12) |
                    749:                         (((-im) & 0xf0) << 4) | ((-im) & 0xf));
                    750: }
                    751: 
                    752: static inline void tcg_out_ld8s_r(TCGContext *s, int cond,
                    753:                 int rd, int rn, int rm)
                    754: {
                    755:     tcg_out32(s, (cond << 28) | 0x019000d0 |
                    756:                     (rn << 16) | (rd << 12) | rm);
                    757: }
                    758: 
                    759: static inline void tcg_out_ld32u(TCGContext *s, int cond,
                    760:                 int rd, int rn, int32_t offset)
                    761: {
                    762:     if (offset > 0xfff || offset < -0xfff) {
                    763:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    764:         tcg_out_ld32_r(s, cond, rd, rn, TCG_REG_R8);
                    765:     } else
                    766:         tcg_out_ld32_12(s, cond, rd, rn, offset);
                    767: }
                    768: 
                    769: static inline void tcg_out_st32(TCGContext *s, int cond,
                    770:                 int rd, int rn, int32_t offset)
                    771: {
                    772:     if (offset > 0xfff || offset < -0xfff) {
                    773:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    774:         tcg_out_st32_r(s, cond, rd, rn, TCG_REG_R8);
                    775:     } else
                    776:         tcg_out_st32_12(s, cond, rd, rn, offset);
                    777: }
                    778: 
                    779: static inline void tcg_out_ld16u(TCGContext *s, int cond,
                    780:                 int rd, int rn, int32_t offset)
                    781: {
                    782:     if (offset > 0xff || offset < -0xff) {
                    783:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    784:         tcg_out_ld16u_r(s, cond, rd, rn, TCG_REG_R8);
                    785:     } else
                    786:         tcg_out_ld16u_8(s, cond, rd, rn, offset);
                    787: }
                    788: 
                    789: static inline void tcg_out_ld16s(TCGContext *s, int cond,
                    790:                 int rd, int rn, int32_t offset)
                    791: {
                    792:     if (offset > 0xff || offset < -0xff) {
                    793:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    794:         tcg_out_ld16s_r(s, cond, rd, rn, TCG_REG_R8);
                    795:     } else
                    796:         tcg_out_ld16s_8(s, cond, rd, rn, offset);
                    797: }
                    798: 
1.1.1.5   root      799: static inline void tcg_out_st16(TCGContext *s, int cond,
1.1       root      800:                 int rd, int rn, int32_t offset)
                    801: {
                    802:     if (offset > 0xff || offset < -0xff) {
                    803:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
1.1.1.5   root      804:         tcg_out_st16_r(s, cond, rd, rn, TCG_REG_R8);
1.1       root      805:     } else
1.1.1.5   root      806:         tcg_out_st16_8(s, cond, rd, rn, offset);
1.1       root      807: }
                    808: 
                    809: static inline void tcg_out_ld8u(TCGContext *s, int cond,
                    810:                 int rd, int rn, int32_t offset)
                    811: {
                    812:     if (offset > 0xfff || offset < -0xfff) {
                    813:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    814:         tcg_out_ld8_r(s, cond, rd, rn, TCG_REG_R8);
                    815:     } else
                    816:         tcg_out_ld8_12(s, cond, rd, rn, offset);
                    817: }
                    818: 
                    819: static inline void tcg_out_ld8s(TCGContext *s, int cond,
                    820:                 int rd, int rn, int32_t offset)
                    821: {
                    822:     if (offset > 0xff || offset < -0xff) {
                    823:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    824:         tcg_out_ld8s_r(s, cond, rd, rn, TCG_REG_R8);
                    825:     } else
                    826:         tcg_out_ld8s_8(s, cond, rd, rn, offset);
                    827: }
                    828: 
1.1.1.5   root      829: static inline void tcg_out_st8(TCGContext *s, int cond,
1.1       root      830:                 int rd, int rn, int32_t offset)
                    831: {
                    832:     if (offset > 0xfff || offset < -0xfff) {
                    833:         tcg_out_movi32(s, cond, TCG_REG_R8, offset);
                    834:         tcg_out_st8_r(s, cond, rd, rn, TCG_REG_R8);
                    835:     } else
                    836:         tcg_out_st8_12(s, cond, rd, rn, offset);
                    837: }
                    838: 
                    839: static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
                    840: {
                    841:     int32_t val;
                    842: 
                    843:     val = addr - (tcg_target_long) s->code_ptr;
                    844:     if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
                    845:         tcg_out_b(s, cond, val);
                    846:     else {
                    847: #if 1
                    848:         tcg_abort();
                    849: #else
                    850:         if (cond == COND_AL) {
1.1.1.5   root      851:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      852:             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
                    853:         } else {
                    854:             tcg_out_movi32(s, cond, TCG_REG_R8, val - 8);
                    855:             tcg_out_dat_reg(s, cond, ARITH_ADD,
1.1.1.5   root      856:                             TCG_REG_PC, TCG_REG_PC,
                    857:                             TCG_REG_R8, SHIFT_IMM_LSL(0));
1.1       root      858:         }
                    859: #endif
                    860:     }
                    861: }
                    862: 
                    863: static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
                    864: {
                    865:     int32_t val;
                    866: 
                    867:     val = addr - (tcg_target_long) s->code_ptr;
                    868:     if (val < 0x01fffffd && val > -0x01fffffd)
                    869:         tcg_out_bl(s, cond, val);
                    870:     else {
                    871: #if 1
                    872:         tcg_abort();
                    873: #else
                    874:         if (cond == COND_AL) {
1.1.1.5   root      875:             tcg_out_dat_imm(s, cond, ARITH_ADD, TCG_REG_R14, TCG_REG_PC, 4);
                    876:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      877:             tcg_out32(s, addr); /* XXX: This is l->u.value, can we use it? */
                    878:         } else {
                    879:             tcg_out_movi32(s, cond, TCG_REG_R9, addr);
1.1.1.5   root      880:             tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
                    881:                             TCG_REG_PC, SHIFT_IMM_LSL(0));
1.1       root      882:             tcg_out_bx(s, cond, TCG_REG_R9);
                    883:         }
                    884: #endif
                    885:     }
                    886: }
                    887: 
                    888: static inline void tcg_out_callr(TCGContext *s, int cond, int arg)
                    889: {
1.1.1.5   root      890:     if (use_armv5_instructions) {
                    891:         tcg_out_blx(s, cond, arg);
                    892:     } else {
                    893:         tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0,
                    894:                         TCG_REG_PC, SHIFT_IMM_LSL(0));
                    895:         tcg_out_bx(s, cond, arg);
                    896:     }
1.1       root      897: }
                    898: 
                    899: static inline void tcg_out_goto_label(TCGContext *s, int cond, int label_index)
                    900: {
                    901:     TCGLabel *l = &s->labels[label_index];
                    902: 
                    903:     if (l->has_value)
                    904:         tcg_out_goto(s, cond, l->u.value);
                    905:     else if (cond == COND_AL) {
1.1.1.5   root      906:         tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root      907:         tcg_out_reloc(s, s->code_ptr, R_ARM_ABS32, label_index, 31337);
                    908:         s->code_ptr += 4;
                    909:     } else {
                    910:         /* Probably this should be preferred even for COND_AL... */
                    911:         tcg_out_reloc(s, s->code_ptr, R_ARM_PC24, label_index, 31337);
                    912:         tcg_out_b_noaddr(s, cond);
                    913:     }
                    914: }
                    915: 
                    916: #ifdef CONFIG_SOFTMMU
                    917: 
                    918: #include "../../softmmu_defs.h"
                    919: 
                    920: static void *qemu_ld_helpers[4] = {
                    921:     __ldb_mmu,
                    922:     __ldw_mmu,
                    923:     __ldl_mmu,
                    924:     __ldq_mmu,
                    925: };
                    926: 
                    927: static void *qemu_st_helpers[4] = {
                    928:     __stb_mmu,
                    929:     __stw_mmu,
                    930:     __stl_mmu,
                    931:     __stq_mmu,
                    932: };
                    933: #endif
                    934: 
                    935: #define TLB_SHIFT      (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS)
                    936: 
1.1.1.5   root      937: static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
1.1       root      938: {
1.1.1.5   root      939:     int addr_reg, data_reg, data_reg2, bswap;
1.1       root      940: #ifdef CONFIG_SOFTMMU
                    941:     int mem_index, s_bits;
                    942: # if TARGET_LONG_BITS == 64
                    943:     int addr_reg2;
                    944: # endif
                    945:     uint32_t *label_ptr;
                    946: #endif
                    947: 
1.1.1.5   root      948: #ifdef TARGET_WORDS_BIGENDIAN
                    949:     bswap = 1;
                    950: #else
                    951:     bswap = 0;
                    952: #endif
1.1       root      953:     data_reg = *args++;
                    954:     if (opc == 3)
                    955:         data_reg2 = *args++;
                    956:     else
1.1.1.3   root      957:         data_reg2 = 0; /* suppress warning */
1.1       root      958:     addr_reg = *args++;
                    959: #ifdef CONFIG_SOFTMMU
                    960: # if TARGET_LONG_BITS == 64
                    961:     addr_reg2 = *args++;
                    962: # endif
                    963:     mem_index = *args;
                    964:     s_bits = opc & 3;
                    965: 
                    966:     /* Should generate something like the following:
                    967:      *  shr r8, addr_reg, #TARGET_PAGE_BITS
                    968:      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
                    969:      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
                    970:      */
                    971: #  if CPU_TLB_BITS > 8
                    972: #   error
                    973: #  endif
1.1.1.5   root      974:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, TCG_REG_R8,
                    975:                     0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1.1       root      976:     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1.1.1.5   root      977:                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
                    978:     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_AREG0,
                    979:                     TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1.1       root      980:     /* In the
                    981:      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_read))]
                    982:      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
                    983:      * not exceed otherwise, so use an
                    984:      *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
                    985:      * before.
                    986:      */
                    987:     if (mem_index)
1.1.1.5   root      988:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1.1       root      989:                         (mem_index << (TLB_SHIFT & 1)) |
                    990:                         ((16 - (TLB_SHIFT >> 1)) << 8));
1.1.1.5   root      991:     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1.1       root      992:                     offsetof(CPUState, tlb_table[0][0].addr_read));
1.1.1.5   root      993:     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                    994:                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1.1       root      995:     /* Check alignment.  */
                    996:     if (s_bits)
                    997:         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                    998:                         0, addr_reg, (1 << s_bits) - 1);
                    999: #  if TARGET_LONG_BITS == 64
                   1000:     /* XXX: possibly we could use a block data load or writeback in
                   1001:      * the first access.  */
1.1.1.5   root     1002:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1003:                     offsetof(CPUState, tlb_table[0][0].addr_read) + 4);
1.1.1.5   root     1004:     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1005:                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1006: #  endif
1.1.1.5   root     1007:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1008:                     offsetof(CPUState, tlb_table[0][0].addend));
                   1009: 
                   1010:     switch (opc) {
                   1011:     case 0:
1.1.1.5   root     1012:         tcg_out_ld8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1013:         break;
                   1014:     case 0 | 4:
1.1.1.5   root     1015:         tcg_out_ld8s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1016:         break;
                   1017:     case 1:
1.1.1.5   root     1018:         tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1019:         if (bswap) {
                   1020:             tcg_out_bswap16(s, COND_EQ, data_reg, data_reg);
                   1021:         }
1.1       root     1022:         break;
                   1023:     case 1 | 4:
1.1.1.5   root     1024:         if (bswap) {
                   1025:             tcg_out_ld16u_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1026:             tcg_out_bswap16s(s, COND_EQ, data_reg, data_reg);
                   1027:         } else {
                   1028:             tcg_out_ld16s_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1029:         }
1.1       root     1030:         break;
                   1031:     case 2:
                   1032:     default:
1.1.1.5   root     1033:         tcg_out_ld32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1034:         if (bswap) {
                   1035:             tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
                   1036:         }
1.1       root     1037:         break;
                   1038:     case 3:
1.1.1.5   root     1039:         if (bswap) {
                   1040:             tcg_out_ld32_rwb(s, COND_EQ, data_reg2, TCG_REG_R1, addr_reg);
                   1041:             tcg_out_ld32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
                   1042:             tcg_out_bswap32(s, COND_EQ, data_reg2, data_reg2);
                   1043:             tcg_out_bswap32(s, COND_EQ, data_reg, data_reg);
                   1044:         } else {
                   1045:             tcg_out_ld32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
                   1046:             tcg_out_ld32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
                   1047:         }
1.1       root     1048:         break;
                   1049:     }
                   1050: 
                   1051:     label_ptr = (void *) s->code_ptr;
1.1.1.6 ! root     1052:     tcg_out_b_noaddr(s, COND_EQ);
1.1       root     1053: 
                   1054:     /* TODO: move this code to where the constants pool will be */
1.1.1.5   root     1055:     if (addr_reg != TCG_REG_R0) {
                   1056:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1057:                         TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
                   1058:     }
1.1       root     1059: # if TARGET_LONG_BITS == 32
1.1.1.5   root     1060:     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R1, 0, mem_index);
1.1       root     1061: # else
1.1.1.5   root     1062:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1063:                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
                   1064:     tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1065: # endif
1.1.1.5   root     1066:     tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_ld_helpers[s_bits] -
1.1       root     1067:                     (tcg_target_long) s->code_ptr);
                   1068: 
                   1069:     switch (opc) {
                   1070:     case 0 | 4:
1.1.1.5   root     1071:         tcg_out_ext8s(s, COND_AL, data_reg, TCG_REG_R0);
1.1       root     1072:         break;
                   1073:     case 1 | 4:
1.1.1.5   root     1074:         tcg_out_ext16s(s, COND_AL, data_reg, TCG_REG_R0);
1.1       root     1075:         break;
                   1076:     case 0:
                   1077:     case 1:
                   1078:     case 2:
                   1079:     default:
1.1.1.5   root     1080:         if (data_reg != TCG_REG_R0) {
                   1081:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1082:                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
                   1083:         }
1.1       root     1084:         break;
                   1085:     case 3:
1.1.1.5   root     1086:         if (data_reg != TCG_REG_R0) {
                   1087:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1088:                             data_reg, 0, TCG_REG_R0, SHIFT_IMM_LSL(0));
                   1089:         }
                   1090:         if (data_reg2 != TCG_REG_R1) {
                   1091:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1092:                             data_reg2, 0, TCG_REG_R1, SHIFT_IMM_LSL(0));
                   1093:         }
1.1       root     1094:         break;
                   1095:     }
                   1096: 
1.1.1.6 ! root     1097:     reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1.1.1.3   root     1098: #else /* !CONFIG_SOFTMMU */
                   1099:     if (GUEST_BASE) {
                   1100:         uint32_t offset = GUEST_BASE;
                   1101:         int i;
                   1102:         int rot;
                   1103: 
                   1104:         while (offset) {
                   1105:             i = ctz32(offset) & ~1;
                   1106:             rot = ((32 - i) << 7) & 0xf00;
                   1107: 
1.1.1.5   root     1108:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R8, addr_reg,
1.1.1.3   root     1109:                             ((offset >> i) & 0xff) | rot);
1.1.1.5   root     1110:             addr_reg = TCG_REG_R8;
1.1.1.3   root     1111:             offset &= ~(0xff << i);
                   1112:         }
                   1113:     }
1.1       root     1114:     switch (opc) {
                   1115:     case 0:
                   1116:         tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
                   1117:         break;
                   1118:     case 0 | 4:
                   1119:         tcg_out_ld8s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1120:         break;
                   1121:     case 1:
                   1122:         tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
1.1.1.5   root     1123:         if (bswap) {
                   1124:             tcg_out_bswap16(s, COND_AL, data_reg, data_reg);
                   1125:         }
1.1       root     1126:         break;
                   1127:     case 1 | 4:
1.1.1.5   root     1128:         if (bswap) {
                   1129:             tcg_out_ld16u_8(s, COND_AL, data_reg, addr_reg, 0);
                   1130:             tcg_out_bswap16s(s, COND_AL, data_reg, data_reg);
                   1131:         } else {
                   1132:             tcg_out_ld16s_8(s, COND_AL, data_reg, addr_reg, 0);
                   1133:         }
1.1       root     1134:         break;
                   1135:     case 2:
                   1136:     default:
                   1137:         tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, 0);
1.1.1.5   root     1138:         if (bswap) {
                   1139:             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
                   1140:         }
1.1       root     1141:         break;
                   1142:     case 3:
                   1143:         /* TODO: use block load -
                   1144:          * check that data_reg2 > data_reg or the other way */
1.1.1.2   root     1145:         if (data_reg == addr_reg) {
1.1.1.5   root     1146:             tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
                   1147:             tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
1.1.1.2   root     1148:         } else {
1.1.1.5   root     1149:             tcg_out_ld32_12(s, COND_AL, data_reg, addr_reg, bswap ? 4 : 0);
                   1150:             tcg_out_ld32_12(s, COND_AL, data_reg2, addr_reg, bswap ? 0 : 4);
                   1151:         }
                   1152:         if (bswap) {
                   1153:             tcg_out_bswap32(s, COND_AL, data_reg, data_reg);
                   1154:             tcg_out_bswap32(s, COND_AL, data_reg2, data_reg2);
1.1.1.2   root     1155:         }
1.1       root     1156:         break;
                   1157:     }
                   1158: #endif
                   1159: }
                   1160: 
1.1.1.5   root     1161: static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1.1       root     1162: {
1.1.1.5   root     1163:     int addr_reg, data_reg, data_reg2, bswap;
1.1       root     1164: #ifdef CONFIG_SOFTMMU
                   1165:     int mem_index, s_bits;
                   1166: # if TARGET_LONG_BITS == 64
                   1167:     int addr_reg2;
                   1168: # endif
                   1169:     uint32_t *label_ptr;
                   1170: #endif
                   1171: 
1.1.1.5   root     1172: #ifdef TARGET_WORDS_BIGENDIAN
                   1173:     bswap = 1;
                   1174: #else
                   1175:     bswap = 0;
                   1176: #endif
1.1       root     1177:     data_reg = *args++;
                   1178:     if (opc == 3)
                   1179:         data_reg2 = *args++;
                   1180:     else
1.1.1.3   root     1181:         data_reg2 = 0; /* suppress warning */
1.1       root     1182:     addr_reg = *args++;
                   1183: #ifdef CONFIG_SOFTMMU
                   1184: # if TARGET_LONG_BITS == 64
                   1185:     addr_reg2 = *args++;
                   1186: # endif
                   1187:     mem_index = *args;
                   1188:     s_bits = opc & 3;
                   1189: 
                   1190:     /* Should generate something like the following:
                   1191:      *  shr r8, addr_reg, #TARGET_PAGE_BITS
                   1192:      *  and r0, r8, #(CPU_TLB_SIZE - 1)   @ Assumption: CPU_TLB_BITS <= 8
                   1193:      *  add r0, env, r0 lsl #CPU_TLB_ENTRY_BITS
                   1194:      */
                   1195:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
1.1.1.5   root     1196:                     TCG_REG_R8, 0, addr_reg, SHIFT_IMM_LSR(TARGET_PAGE_BITS));
1.1       root     1197:     tcg_out_dat_imm(s, COND_AL, ARITH_AND,
1.1.1.5   root     1198:                     TCG_REG_R0, TCG_REG_R8, CPU_TLB_SIZE - 1);
                   1199:     tcg_out_dat_reg(s, COND_AL, ARITH_ADD, TCG_REG_R0,
                   1200:                     TCG_AREG0, TCG_REG_R0, SHIFT_IMM_LSL(CPU_TLB_ENTRY_BITS));
1.1       root     1201:     /* In the
                   1202:      *  ldr r1 [r0, #(offsetof(CPUState, tlb_table[mem_index][0].addr_write))]
                   1203:      * below, the offset is likely to exceed 12 bits if mem_index != 0 and
                   1204:      * not exceed otherwise, so use an
                   1205:      *  add r0, r0, #(mem_index * sizeof *CPUState.tlb_table)
                   1206:      * before.
                   1207:      */
                   1208:     if (mem_index)
1.1.1.5   root     1209:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R0, TCG_REG_R0,
1.1       root     1210:                         (mem_index << (TLB_SHIFT & 1)) |
                   1211:                         ((16 - (TLB_SHIFT >> 1)) << 8));
1.1.1.5   root     1212:     tcg_out_ld32_12(s, COND_AL, TCG_REG_R1, TCG_REG_R0,
1.1       root     1213:                     offsetof(CPUState, tlb_table[0][0].addr_write));
1.1.1.5   root     1214:     tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0, TCG_REG_R1,
                   1215:                     TCG_REG_R8, SHIFT_IMM_LSL(TARGET_PAGE_BITS));
1.1       root     1216:     /* Check alignment.  */
                   1217:     if (s_bits)
                   1218:         tcg_out_dat_imm(s, COND_EQ, ARITH_TST,
                   1219:                         0, addr_reg, (1 << s_bits) - 1);
                   1220: #  if TARGET_LONG_BITS == 64
                   1221:     /* XXX: possibly we could use a block data load or writeback in
                   1222:      * the first access.  */
1.1.1.5   root     1223:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
                   1224:                     offsetof(CPUState, tlb_table[0][0].addr_write) + 4);
                   1225:     tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1226:                     TCG_REG_R1, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1227: #  endif
1.1.1.5   root     1228:     tcg_out_ld32_12(s, COND_EQ, TCG_REG_R1, TCG_REG_R0,
1.1       root     1229:                     offsetof(CPUState, tlb_table[0][0].addend));
                   1230: 
                   1231:     switch (opc) {
                   1232:     case 0:
1.1.1.5   root     1233:         tcg_out_st8_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
1.1       root     1234:         break;
                   1235:     case 1:
1.1.1.5   root     1236:         if (bswap) {
                   1237:             tcg_out_bswap16(s, COND_EQ, TCG_REG_R0, data_reg);
                   1238:             tcg_out_st16_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
                   1239:         } else {
                   1240:             tcg_out_st16_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1241:         }
1.1       root     1242:         break;
                   1243:     case 2:
                   1244:     default:
1.1.1.5   root     1245:         if (bswap) {
                   1246:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
                   1247:             tcg_out_st32_r(s, COND_EQ, TCG_REG_R0, addr_reg, TCG_REG_R1);
                   1248:         } else {
                   1249:             tcg_out_st32_r(s, COND_EQ, data_reg, addr_reg, TCG_REG_R1);
                   1250:         }
1.1       root     1251:         break;
                   1252:     case 3:
1.1.1.5   root     1253:         if (bswap) {
                   1254:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
                   1255:             tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
                   1256:             tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
1.1.1.6 ! root     1257:             tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
1.1.1.5   root     1258:         } else {
                   1259:             tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
                   1260:             tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
                   1261:         }
1.1       root     1262:         break;
                   1263:     }
                   1264: 
                   1265:     label_ptr = (void *) s->code_ptr;
1.1.1.6 ! root     1266:     tcg_out_b_noaddr(s, COND_EQ);
1.1       root     1267: 
                   1268:     /* TODO: move this code to where the constants pool will be */
1.1.1.5   root     1269:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1270:                     TCG_REG_R0, 0, addr_reg, SHIFT_IMM_LSL(0));
1.1       root     1271: # if TARGET_LONG_BITS == 32
                   1272:     switch (opc) {
                   1273:     case 0:
1.1.1.5   root     1274:         tcg_out_ext8u(s, COND_AL, TCG_REG_R1, data_reg);
                   1275:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1276:         break;
                   1277:     case 1:
1.1.1.5   root     1278:         tcg_out_ext16u(s, COND_AL, TCG_REG_R1, data_reg);
                   1279:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1280:         break;
                   1281:     case 2:
1.1.1.5   root     1282:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1283:                         TCG_REG_R1, 0, data_reg, SHIFT_IMM_LSL(0));
                   1284:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
1.1       root     1285:         break;
                   1286:     case 3:
1.1.1.5   root     1287:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
                   1288:         tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
                   1289:         if (data_reg != TCG_REG_R2) {
                   1290:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1291:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1292:         }
                   1293:         if (data_reg2 != TCG_REG_R3) {
                   1294:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1295:                             TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1296:         }
1.1       root     1297:         break;
                   1298:     }
                   1299: # else
1.1.1.5   root     1300:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1301:                     TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
1.1       root     1302:     switch (opc) {
                   1303:     case 0:
1.1.1.5   root     1304:         tcg_out_ext8u(s, COND_AL, TCG_REG_R2, data_reg);
                   1305:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1306:         break;
                   1307:     case 1:
1.1.1.5   root     1308:         tcg_out_ext16u(s, COND_AL, TCG_REG_R2, data_reg);
                   1309:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1310:         break;
                   1311:     case 2:
1.1.1.5   root     1312:         if (data_reg != TCG_REG_R2) {
                   1313:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1314:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1315:         }
                   1316:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R3, 0, mem_index);
1.1       root     1317:         break;
                   1318:     case 3:
1.1.1.5   root     1319:         tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R8, 0, mem_index);
                   1320:         tcg_out32(s, (COND_AL << 28) | 0x052d8010); /* str r8, [sp, #-0x10]! */
                   1321:         if (data_reg != TCG_REG_R2) {
                   1322:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1323:                             TCG_REG_R2, 0, data_reg, SHIFT_IMM_LSL(0));
                   1324:         }
                   1325:         if (data_reg2 != TCG_REG_R3) {
                   1326:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1327:                             TCG_REG_R3, 0, data_reg2, SHIFT_IMM_LSL(0));
                   1328:         }
1.1       root     1329:         break;
                   1330:     }
                   1331: # endif
                   1332: 
1.1.1.5   root     1333:     tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits] -
1.1       root     1334:                     (tcg_target_long) s->code_ptr);
                   1335:     if (opc == 3)
1.1.1.5   root     1336:         tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
1.1       root     1337: 
1.1.1.6 ! root     1338:     reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
1.1.1.3   root     1339: #else /* !CONFIG_SOFTMMU */
                   1340:     if (GUEST_BASE) {
                   1341:         uint32_t offset = GUEST_BASE;
                   1342:         int i;
                   1343:         int rot;
                   1344: 
                   1345:         while (offset) {
                   1346:             i = ctz32(offset) & ~1;
                   1347:             rot = ((32 - i) << 7) & 0xf00;
                   1348: 
1.1.1.5   root     1349:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R1, addr_reg,
1.1.1.3   root     1350:                             ((offset >> i) & 0xff) | rot);
1.1.1.5   root     1351:             addr_reg = TCG_REG_R1;
1.1.1.3   root     1352:             offset &= ~(0xff << i);
                   1353:         }
                   1354:     }
1.1       root     1355:     switch (opc) {
                   1356:     case 0:
                   1357:         tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
                   1358:         break;
                   1359:     case 1:
1.1.1.5   root     1360:         if (bswap) {
                   1361:             tcg_out_bswap16(s, COND_AL, TCG_REG_R0, data_reg);
                   1362:             tcg_out_st16_8(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1363:         } else {
                   1364:             tcg_out_st16_8(s, COND_AL, data_reg, addr_reg, 0);
                   1365:         }
1.1       root     1366:         break;
                   1367:     case 2:
                   1368:     default:
1.1.1.5   root     1369:         if (bswap) {
                   1370:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
                   1371:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1372:         } else {
                   1373:             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1374:         }
1.1       root     1375:         break;
                   1376:     case 3:
                   1377:         /* TODO: use block store -
                   1378:          * check that data_reg2 > data_reg or the other way */
1.1.1.5   root     1379:         if (bswap) {
                   1380:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg2);
                   1381:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 0);
                   1382:             tcg_out_bswap32(s, COND_AL, TCG_REG_R0, data_reg);
                   1383:             tcg_out_st32_12(s, COND_AL, TCG_REG_R0, addr_reg, 4);
                   1384:         } else {
                   1385:             tcg_out_st32_12(s, COND_AL, data_reg, addr_reg, 0);
                   1386:             tcg_out_st32_12(s, COND_AL, data_reg2, addr_reg, 4);
                   1387:         }
1.1       root     1388:         break;
                   1389:     }
                   1390: #endif
                   1391: }
                   1392: 
                   1393: static uint8_t *tb_ret_addr;
                   1394: 
1.1.1.5   root     1395: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1       root     1396:                 const TCGArg *args, const int *const_args)
                   1397: {
                   1398:     int c;
                   1399: 
                   1400:     switch (opc) {
                   1401:     case INDEX_op_exit_tb:
                   1402:         {
                   1403:             uint8_t *ld_ptr = s->code_ptr;
                   1404:             if (args[0] >> 8)
1.1.1.5   root     1405:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
1.1       root     1406:             else
1.1.1.5   root     1407:                 tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R0, 0, args[0]);
1.1       root     1408:             tcg_out_goto(s, COND_AL, (tcg_target_ulong) tb_ret_addr);
                   1409:             if (args[0] >> 8) {
                   1410:                 *ld_ptr = (uint8_t) (s->code_ptr - ld_ptr) - 8;
                   1411:                 tcg_out32(s, args[0]);
                   1412:             }
                   1413:         }
                   1414:         break;
                   1415:     case INDEX_op_goto_tb:
                   1416:         if (s->tb_jmp_offset) {
                   1417:             /* Direct jump method */
                   1418: #if defined(USE_DIRECT_JUMP)
                   1419:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
1.1.1.6 ! root     1420:             tcg_out_b_noaddr(s, COND_AL);
1.1       root     1421: #else
1.1.1.5   root     1422:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
1.1       root     1423:             s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
                   1424:             tcg_out32(s, 0);
                   1425: #endif
                   1426:         } else {
                   1427:             /* Indirect jump method */
                   1428: #if 1
                   1429:             c = (int) (s->tb_next + args[0]) - ((int) s->code_ptr + 8);
                   1430:             if (c > 0xfff || c < -0xfff) {
                   1431:                 tcg_out_movi32(s, COND_AL, TCG_REG_R0,
                   1432:                                 (tcg_target_long) (s->tb_next + args[0]));
1.1.1.5   root     1433:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1.1       root     1434:             } else
1.1.1.5   root     1435:                 tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, c);
1.1       root     1436: #else
1.1.1.5   root     1437:             tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0);
                   1438:             tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, 0);
1.1       root     1439:             tcg_out32(s, (tcg_target_long) (s->tb_next + args[0]));
                   1440: #endif
                   1441:         }
                   1442:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                   1443:         break;
                   1444:     case INDEX_op_call:
                   1445:         if (const_args[0])
                   1446:             tcg_out_call(s, COND_AL, args[0]);
                   1447:         else
                   1448:             tcg_out_callr(s, COND_AL, args[0]);
                   1449:         break;
                   1450:     case INDEX_op_jmp:
                   1451:         if (const_args[0])
                   1452:             tcg_out_goto(s, COND_AL, args[0]);
                   1453:         else
                   1454:             tcg_out_bx(s, COND_AL, args[0]);
                   1455:         break;
                   1456:     case INDEX_op_br:
                   1457:         tcg_out_goto_label(s, COND_AL, args[0]);
                   1458:         break;
                   1459: 
                   1460:     case INDEX_op_ld8u_i32:
                   1461:         tcg_out_ld8u(s, COND_AL, args[0], args[1], args[2]);
                   1462:         break;
                   1463:     case INDEX_op_ld8s_i32:
                   1464:         tcg_out_ld8s(s, COND_AL, args[0], args[1], args[2]);
                   1465:         break;
                   1466:     case INDEX_op_ld16u_i32:
                   1467:         tcg_out_ld16u(s, COND_AL, args[0], args[1], args[2]);
                   1468:         break;
                   1469:     case INDEX_op_ld16s_i32:
                   1470:         tcg_out_ld16s(s, COND_AL, args[0], args[1], args[2]);
                   1471:         break;
                   1472:     case INDEX_op_ld_i32:
                   1473:         tcg_out_ld32u(s, COND_AL, args[0], args[1], args[2]);
                   1474:         break;
                   1475:     case INDEX_op_st8_i32:
1.1.1.5   root     1476:         tcg_out_st8(s, COND_AL, args[0], args[1], args[2]);
1.1       root     1477:         break;
                   1478:     case INDEX_op_st16_i32:
1.1.1.5   root     1479:         tcg_out_st16(s, COND_AL, args[0], args[1], args[2]);
1.1       root     1480:         break;
                   1481:     case INDEX_op_st_i32:
                   1482:         tcg_out_st32(s, COND_AL, args[0], args[1], args[2]);
                   1483:         break;
                   1484: 
                   1485:     case INDEX_op_mov_i32:
                   1486:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
                   1487:                         args[0], 0, args[1], SHIFT_IMM_LSL(0));
                   1488:         break;
                   1489:     case INDEX_op_movi_i32:
                   1490:         tcg_out_movi32(s, COND_AL, args[0], args[1]);
                   1491:         break;
                   1492:     case INDEX_op_add_i32:
                   1493:         c = ARITH_ADD;
                   1494:         goto gen_arith;
                   1495:     case INDEX_op_sub_i32:
                   1496:         c = ARITH_SUB;
                   1497:         goto gen_arith;
                   1498:     case INDEX_op_and_i32:
                   1499:         c = ARITH_AND;
                   1500:         goto gen_arith;
1.1.1.5   root     1501:     case INDEX_op_andc_i32:
                   1502:         c = ARITH_BIC;
                   1503:         goto gen_arith;
1.1       root     1504:     case INDEX_op_or_i32:
                   1505:         c = ARITH_ORR;
                   1506:         goto gen_arith;
                   1507:     case INDEX_op_xor_i32:
                   1508:         c = ARITH_EOR;
                   1509:         /* Fall through.  */
                   1510:     gen_arith:
1.1.1.3   root     1511:         if (const_args[2]) {
                   1512:             int rot;
                   1513:             rot = encode_imm(args[2]);
                   1514:             tcg_out_dat_imm(s, COND_AL, c,
                   1515:                             args[0], args[1], rotl(args[2], rot) | (rot << 7));
                   1516:         } else
                   1517:             tcg_out_dat_reg(s, COND_AL, c,
                   1518:                             args[0], args[1], args[2], SHIFT_IMM_LSL(0));
1.1       root     1519:         break;
                   1520:     case INDEX_op_add2_i32:
                   1521:         tcg_out_dat_reg2(s, COND_AL, ARITH_ADD, ARITH_ADC,
                   1522:                         args[0], args[1], args[2], args[3],
                   1523:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1524:         break;
                   1525:     case INDEX_op_sub2_i32:
                   1526:         tcg_out_dat_reg2(s, COND_AL, ARITH_SUB, ARITH_SBC,
                   1527:                         args[0], args[1], args[2], args[3],
                   1528:                         args[4], args[5], SHIFT_IMM_LSL(0));
                   1529:         break;
                   1530:     case INDEX_op_neg_i32:
                   1531:         tcg_out_dat_imm(s, COND_AL, ARITH_RSB, args[0], args[1], 0);
                   1532:         break;
1.1.1.3   root     1533:     case INDEX_op_not_i32:
                   1534:         tcg_out_dat_reg(s, COND_AL,
                   1535:                         ARITH_MVN, args[0], 0, args[1], SHIFT_IMM_LSL(0));
                   1536:         break;
1.1       root     1537:     case INDEX_op_mul_i32:
                   1538:         tcg_out_mul32(s, COND_AL, args[0], args[1], args[2]);
                   1539:         break;
                   1540:     case INDEX_op_mulu2_i32:
                   1541:         tcg_out_umull32(s, COND_AL, args[0], args[1], args[2], args[3]);
                   1542:         break;
                   1543:     /* XXX: Perhaps args[2] & 0x1f is wrong */
                   1544:     case INDEX_op_shl_i32:
                   1545:         c = const_args[2] ?
                   1546:                 SHIFT_IMM_LSL(args[2] & 0x1f) : SHIFT_REG_LSL(args[2]);
                   1547:         goto gen_shift32;
                   1548:     case INDEX_op_shr_i32:
                   1549:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_LSR(args[2] & 0x1f) :
                   1550:                 SHIFT_IMM_LSL(0) : SHIFT_REG_LSR(args[2]);
                   1551:         goto gen_shift32;
                   1552:     case INDEX_op_sar_i32:
                   1553:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ASR(args[2] & 0x1f) :
                   1554:                 SHIFT_IMM_LSL(0) : SHIFT_REG_ASR(args[2]);
1.1.1.5   root     1555:         goto gen_shift32;
                   1556:     case INDEX_op_rotr_i32:
                   1557:         c = const_args[2] ? (args[2] & 0x1f) ? SHIFT_IMM_ROR(args[2] & 0x1f) :
                   1558:                 SHIFT_IMM_LSL(0) : SHIFT_REG_ROR(args[2]);
1.1       root     1559:         /* Fall through.  */
                   1560:     gen_shift32:
                   1561:         tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1], c);
                   1562:         break;
                   1563: 
1.1.1.5   root     1564:     case INDEX_op_rotl_i32:
                   1565:         if (const_args[2]) {
                   1566:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
                   1567:                             ((0x20 - args[2]) & 0x1f) ?
                   1568:                             SHIFT_IMM_ROR((0x20 - args[2]) & 0x1f) :
                   1569:                             SHIFT_IMM_LSL(0));
                   1570:         } else {
                   1571:             tcg_out_dat_imm(s, COND_AL, ARITH_RSB, TCG_REG_R8, args[1], 0x20);
                   1572:             tcg_out_dat_reg(s, COND_AL, ARITH_MOV, args[0], 0, args[1],
                   1573:                             SHIFT_REG_ROR(TCG_REG_R8));
                   1574:         }
                   1575:         break;
                   1576: 
1.1       root     1577:     case INDEX_op_brcond_i32:
1.1.1.5   root     1578:         if (const_args[1]) {
                   1579:             int rot;
                   1580:             rot = encode_imm(args[1]);
                   1581:             tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
                   1582:                             args[0], rotl(args[1], rot) | (rot << 7));
                   1583:         } else {
                   1584:             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1585:                             args[0], args[1], SHIFT_IMM_LSL(0));
                   1586:         }
1.1       root     1587:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[2]], args[3]);
                   1588:         break;
                   1589:     case INDEX_op_brcond2_i32:
                   1590:         /* The resulting conditions are:
                   1591:          * TCG_COND_EQ    -->  a0 == a2 && a1 == a3,
                   1592:          * TCG_COND_NE    --> (a0 != a2 && a1 == a3) ||  a1 != a3,
                   1593:          * TCG_COND_LT(U) --> (a0 <  a2 && a1 == a3) ||  a1 <  a3,
                   1594:          * TCG_COND_GE(U) --> (a0 >= a2 && a1 == a3) || (a1 >= a3 && a1 != a3),
                   1595:          * TCG_COND_LE(U) --> (a0 <= a2 && a1 == a3) || (a1 <= a3 && a1 != a3),
                   1596:          * TCG_COND_GT(U) --> (a0 >  a2 && a1 == a3) ||  a1 >  a3,
                   1597:          */
                   1598:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1599:                         args[1], args[3], SHIFT_IMM_LSL(0));
                   1600:         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1601:                         args[0], args[2], SHIFT_IMM_LSL(0));
                   1602:         tcg_out_goto_label(s, tcg_cond_to_arm_cond[args[4]], args[5]);
                   1603:         break;
1.1.1.5   root     1604:     case INDEX_op_setcond_i32:
                   1605:         if (const_args[2]) {
                   1606:             int rot;
                   1607:             rot = encode_imm(args[2]);
                   1608:             tcg_out_dat_imm(s, COND_AL, ARITH_CMP, 0,
                   1609:                             args[1], rotl(args[2], rot) | (rot << 7));
                   1610:         } else {
                   1611:             tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1612:                             args[1], args[2], SHIFT_IMM_LSL(0));
                   1613:         }
                   1614:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[3]],
                   1615:                         ARITH_MOV, args[0], 0, 1);
                   1616:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[3])],
                   1617:                         ARITH_MOV, args[0], 0, 0);
                   1618:         break;
                   1619:     case INDEX_op_setcond2_i32:
                   1620:         /* See brcond2_i32 comment */
                   1621:         tcg_out_dat_reg(s, COND_AL, ARITH_CMP, 0,
                   1622:                         args[2], args[4], SHIFT_IMM_LSL(0));
                   1623:         tcg_out_dat_reg(s, COND_EQ, ARITH_CMP, 0,
                   1624:                         args[1], args[3], SHIFT_IMM_LSL(0));
                   1625:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[args[5]],
                   1626:                         ARITH_MOV, args[0], 0, 1);
                   1627:         tcg_out_dat_imm(s, tcg_cond_to_arm_cond[tcg_invert_cond(args[5])],
                   1628:                         ARITH_MOV, args[0], 0, 0);
                   1629:         break;
1.1       root     1630: 
                   1631:     case INDEX_op_qemu_ld8u:
1.1.1.5   root     1632:         tcg_out_qemu_ld(s, args, 0);
1.1       root     1633:         break;
                   1634:     case INDEX_op_qemu_ld8s:
1.1.1.5   root     1635:         tcg_out_qemu_ld(s, args, 0 | 4);
1.1       root     1636:         break;
                   1637:     case INDEX_op_qemu_ld16u:
1.1.1.5   root     1638:         tcg_out_qemu_ld(s, args, 1);
1.1       root     1639:         break;
                   1640:     case INDEX_op_qemu_ld16s:
1.1.1.5   root     1641:         tcg_out_qemu_ld(s, args, 1 | 4);
1.1       root     1642:         break;
1.1.1.5   root     1643:     case INDEX_op_qemu_ld32:
                   1644:         tcg_out_qemu_ld(s, args, 2);
1.1       root     1645:         break;
                   1646:     case INDEX_op_qemu_ld64:
1.1.1.5   root     1647:         tcg_out_qemu_ld(s, args, 3);
1.1       root     1648:         break;
                   1649: 
                   1650:     case INDEX_op_qemu_st8:
1.1.1.5   root     1651:         tcg_out_qemu_st(s, args, 0);
1.1       root     1652:         break;
                   1653:     case INDEX_op_qemu_st16:
1.1.1.5   root     1654:         tcg_out_qemu_st(s, args, 1);
1.1       root     1655:         break;
                   1656:     case INDEX_op_qemu_st32:
1.1.1.5   root     1657:         tcg_out_qemu_st(s, args, 2);
1.1       root     1658:         break;
                   1659:     case INDEX_op_qemu_st64:
1.1.1.5   root     1660:         tcg_out_qemu_st(s, args, 3);
                   1661:         break;
                   1662: 
                   1663:     case INDEX_op_bswap16_i32:
                   1664:         tcg_out_bswap16(s, COND_AL, args[0], args[1]);
                   1665:         break;
                   1666:     case INDEX_op_bswap32_i32:
                   1667:         tcg_out_bswap32(s, COND_AL, args[0], args[1]);
1.1       root     1668:         break;
                   1669: 
                   1670:     case INDEX_op_ext8s_i32:
1.1.1.5   root     1671:         tcg_out_ext8s(s, COND_AL, args[0], args[1]);
1.1       root     1672:         break;
                   1673:     case INDEX_op_ext16s_i32:
1.1.1.5   root     1674:         tcg_out_ext16s(s, COND_AL, args[0], args[1]);
                   1675:         break;
                   1676:     case INDEX_op_ext16u_i32:
                   1677:         tcg_out_ext16u(s, COND_AL, args[0], args[1]);
1.1       root     1678:         break;
                   1679: 
                   1680:     default:
                   1681:         tcg_abort();
                   1682:     }
                   1683: }
                   1684: 
                   1685: static const TCGTargetOpDef arm_op_defs[] = {
                   1686:     { INDEX_op_exit_tb, { } },
                   1687:     { INDEX_op_goto_tb, { } },
                   1688:     { INDEX_op_call, { "ri" } },
                   1689:     { INDEX_op_jmp, { "ri" } },
                   1690:     { INDEX_op_br, { } },
                   1691: 
                   1692:     { INDEX_op_mov_i32, { "r", "r" } },
                   1693:     { INDEX_op_movi_i32, { "r" } },
                   1694: 
                   1695:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1696:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1697:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1698:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1699:     { INDEX_op_ld_i32, { "r", "r" } },
                   1700:     { INDEX_op_st8_i32, { "r", "r" } },
                   1701:     { INDEX_op_st16_i32, { "r", "r" } },
                   1702:     { INDEX_op_st_i32, { "r", "r" } },
                   1703: 
                   1704:     /* TODO: "r", "r", "ri" */
1.1.1.3   root     1705:     { INDEX_op_add_i32, { "r", "r", "rI" } },
                   1706:     { INDEX_op_sub_i32, { "r", "r", "rI" } },
1.1       root     1707:     { INDEX_op_mul_i32, { "r", "r", "r" } },
                   1708:     { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
1.1.1.3   root     1709:     { INDEX_op_and_i32, { "r", "r", "rI" } },
1.1.1.5   root     1710:     { INDEX_op_andc_i32, { "r", "r", "rI" } },
1.1.1.3   root     1711:     { INDEX_op_or_i32, { "r", "r", "rI" } },
                   1712:     { INDEX_op_xor_i32, { "r", "r", "rI" } },
1.1       root     1713:     { INDEX_op_neg_i32, { "r", "r" } },
1.1.1.3   root     1714:     { INDEX_op_not_i32, { "r", "r" } },
1.1       root     1715: 
                   1716:     { INDEX_op_shl_i32, { "r", "r", "ri" } },
                   1717:     { INDEX_op_shr_i32, { "r", "r", "ri" } },
                   1718:     { INDEX_op_sar_i32, { "r", "r", "ri" } },
1.1.1.5   root     1719:     { INDEX_op_rotl_i32, { "r", "r", "ri" } },
                   1720:     { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1.1       root     1721: 
1.1.1.5   root     1722:     { INDEX_op_brcond_i32, { "r", "rI" } },
                   1723:     { INDEX_op_setcond_i32, { "r", "r", "rI" } },
1.1       root     1724: 
                   1725:     /* TODO: "r", "r", "r", "r", "ri", "ri" */
                   1726:     { INDEX_op_add2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1727:     { INDEX_op_sub2_i32, { "r", "r", "r", "r", "r", "r" } },
                   1728:     { INDEX_op_brcond2_i32, { "r", "r", "r", "r" } },
1.1.1.5   root     1729:     { INDEX_op_setcond2_i32, { "r", "r", "r", "r", "r" } },
                   1730: 
                   1731: #if TARGET_LONG_BITS == 32
                   1732:     { INDEX_op_qemu_ld8u, { "r", "l" } },
                   1733:     { INDEX_op_qemu_ld8s, { "r", "l" } },
                   1734:     { INDEX_op_qemu_ld16u, { "r", "l" } },
                   1735:     { INDEX_op_qemu_ld16s, { "r", "l" } },
                   1736:     { INDEX_op_qemu_ld32, { "r", "l" } },
                   1737:     { INDEX_op_qemu_ld64, { "L", "L", "l" } },
                   1738: 
                   1739:     { INDEX_op_qemu_st8, { "s", "s" } },
                   1740:     { INDEX_op_qemu_st16, { "s", "s" } },
                   1741:     { INDEX_op_qemu_st32, { "s", "s" } },
                   1742:     { INDEX_op_qemu_st64, { "S", "S", "s" } },
                   1743: #else
                   1744:     { INDEX_op_qemu_ld8u, { "r", "l", "l" } },
                   1745:     { INDEX_op_qemu_ld8s, { "r", "l", "l" } },
                   1746:     { INDEX_op_qemu_ld16u, { "r", "l", "l" } },
                   1747:     { INDEX_op_qemu_ld16s, { "r", "l", "l" } },
                   1748:     { INDEX_op_qemu_ld32, { "r", "l", "l" } },
                   1749:     { INDEX_op_qemu_ld64, { "L", "L", "l", "l" } },
                   1750: 
                   1751:     { INDEX_op_qemu_st8, { "s", "s", "s" } },
                   1752:     { INDEX_op_qemu_st16, { "s", "s", "s" } },
                   1753:     { INDEX_op_qemu_st32, { "s", "s", "s" } },
                   1754:     { INDEX_op_qemu_st64, { "S", "S", "s", "s" } },
                   1755: #endif
1.1       root     1756: 
1.1.1.5   root     1757:     { INDEX_op_bswap16_i32, { "r", "r" } },
                   1758:     { INDEX_op_bswap32_i32, { "r", "r" } },
1.1       root     1759: 
                   1760:     { INDEX_op_ext8s_i32, { "r", "r" } },
                   1761:     { INDEX_op_ext16s_i32, { "r", "r" } },
1.1.1.5   root     1762:     { INDEX_op_ext16u_i32, { "r", "r" } },
1.1       root     1763: 
                   1764:     { -1 },
                   1765: };
                   1766: 
1.1.1.5   root     1767: static void tcg_target_init(TCGContext *s)
1.1       root     1768: {
1.1.1.5   root     1769: #if !defined(CONFIG_USER_ONLY)
1.1       root     1770:     /* fail safe */
                   1771:     if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
                   1772:         tcg_abort();
1.1.1.5   root     1773: #endif
1.1       root     1774: 
1.1.1.5   root     1775:     tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
1.1       root     1776:     tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1.1.1.5   root     1777:                      (1 << TCG_REG_R0) |
                   1778:                      (1 << TCG_REG_R1) |
                   1779:                      (1 << TCG_REG_R2) |
                   1780:                      (1 << TCG_REG_R3) |
                   1781:                      (1 << TCG_REG_R12) |
                   1782:                      (1 << TCG_REG_R14));
1.1       root     1783: 
                   1784:     tcg_regset_clear(s->reserved_regs);
                   1785:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
                   1786:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_R8);
1.1.1.5   root     1787:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
1.1       root     1788: 
                   1789:     tcg_add_target_add_op_defs(arm_op_defs);
                   1790: }
                   1791: 
                   1792: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
                   1793:                 int arg1, tcg_target_long arg2)
                   1794: {
                   1795:     tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
                   1796: }
                   1797: 
                   1798: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                   1799:                 int arg1, tcg_target_long arg2)
                   1800: {
                   1801:     tcg_out_st32(s, COND_AL, arg, arg1, arg2);
                   1802: }
                   1803: 
1.1.1.2   root     1804: static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
1.1       root     1805: {
                   1806:     if (val > 0)
                   1807:         if (val < 0x100)
                   1808:             tcg_out_dat_imm(s, COND_AL, ARITH_ADD, reg, reg, val);
                   1809:         else
                   1810:             tcg_abort();
                   1811:     else if (val < 0) {
                   1812:         if (val > -0x100)
                   1813:             tcg_out_dat_imm(s, COND_AL, ARITH_SUB, reg, reg, -val);
                   1814:         else
                   1815:             tcg_abort();
                   1816:     }
                   1817: }
                   1818: 
1.1.1.5   root     1819: static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
1.1       root     1820: {
                   1821:     tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
                   1822: }
                   1823: 
                   1824: static inline void tcg_out_movi(TCGContext *s, TCGType type,
                   1825:                 int ret, tcg_target_long arg)
                   1826: {
                   1827:     tcg_out_movi32(s, COND_AL, ret, arg);
                   1828: }
                   1829: 
1.1.1.5   root     1830: static void tcg_target_qemu_prologue(TCGContext *s)
1.1       root     1831: {
1.1.1.5   root     1832:     /* There is no need to save r7, it is used to store the address
                   1833:        of the env structure and is not modified by GCC. */
1.1.1.4   root     1834: 
1.1.1.5   root     1835:     /* stmdb sp!, { r4 - r6, r8 - r11, lr } */
                   1836:     tcg_out32(s, (COND_AL << 28) | 0x092d4f70);
1.1       root     1837: 
                   1838:     tcg_out_bx(s, COND_AL, TCG_REG_R0);
                   1839:     tb_ret_addr = s->code_ptr;
                   1840: 
1.1.1.5   root     1841:     /* ldmia sp!, { r4 - r6, r8 - r11, pc } */
                   1842:     tcg_out32(s, (COND_AL << 28) | 0x08bd8f70);
1.1       root     1843: }

unix.superglobalmegacorp.com

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