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

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

unix.superglobalmegacorp.com

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