symbian-qemu-0.9.1-12/qemu-symbian-svp/tcg/arm/tcg-target.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 }