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

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

unix.superglobalmegacorp.com

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