Annotation of qemu/tcg/mips/tcg-target.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * Tiny Code Generator for QEMU
                      3:  *
                      4:  * Copyright (c) 2008-2009 Arnaud Patard <[email protected]>
                      5:  * Copyright (c) 2009 Aurelien Jarno <[email protected]>
                      6:  * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
                      7:  *
                      8:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      9:  * of this software and associated documentation files (the "Software"), to deal
                     10:  * in the Software without restriction, including without limitation the rights
                     11:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     12:  * copies of the Software, and to permit persons to whom the Software is
                     13:  * furnished to do so, subject to the following conditions:
                     14:  *
                     15:  * The above copyright notice and this permission notice shall be included in
                     16:  * all copies or substantial portions of the Software.
                     17:  *
                     18:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     19:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     20:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     21:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     22:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     23:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     24:  * THE SOFTWARE.
                     25:  */
                     26: 
                     27: #if defined(TCG_TARGET_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
                     28: # define TCG_NEED_BSWAP 0
                     29: #else
                     30: # define TCG_NEED_BSWAP 1
                     31: #endif
                     32: 
                     33: #ifndef NDEBUG
                     34: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
                     35:     "zero",
                     36:     "at",
                     37:     "v0",
                     38:     "v1",
                     39:     "a0",
                     40:     "a1",
                     41:     "a2",
                     42:     "a3",
                     43:     "t0",
                     44:     "t1",
                     45:     "t2",
                     46:     "t3",
                     47:     "t4",
                     48:     "t5",
                     49:     "t6",
                     50:     "t7",
                     51:     "s0",
                     52:     "s1",
                     53:     "s2",
                     54:     "s3",
                     55:     "s4",
                     56:     "s5",
                     57:     "s6",
                     58:     "s7",
                     59:     "t8",
                     60:     "t9",
                     61:     "k0",
                     62:     "k1",
                     63:     "gp",
                     64:     "sp",
                     65:     "fp",
                     66:     "ra",
                     67: };
                     68: #endif
                     69: 
                     70: /* check if we really need so many registers :P */
                     71: static const int tcg_target_reg_alloc_order[] = {
                     72:     TCG_REG_S0,
                     73:     TCG_REG_S1,
                     74:     TCG_REG_S2,
                     75:     TCG_REG_S3,
                     76:     TCG_REG_S4,
                     77:     TCG_REG_S5,
                     78:     TCG_REG_S6,
                     79:     TCG_REG_S7,
                     80:     TCG_REG_T1,
                     81:     TCG_REG_T2,
                     82:     TCG_REG_T3,
                     83:     TCG_REG_T4,
                     84:     TCG_REG_T5,
                     85:     TCG_REG_T6,
                     86:     TCG_REG_T7,
                     87:     TCG_REG_T8,
                     88:     TCG_REG_T9,
                     89:     TCG_REG_A0,
                     90:     TCG_REG_A1,
                     91:     TCG_REG_A2,
                     92:     TCG_REG_A3,
                     93:     TCG_REG_V0,
                     94:     TCG_REG_V1
                     95: };
                     96: 
                     97: static const int tcg_target_call_iarg_regs[4] = {
                     98:     TCG_REG_A0,
                     99:     TCG_REG_A1,
                    100:     TCG_REG_A2,
                    101:     TCG_REG_A3
                    102: };
                    103: 
                    104: static const int tcg_target_call_oarg_regs[2] = {
                    105:     TCG_REG_V0,
                    106:     TCG_REG_V1
                    107: };
                    108: 
                    109: static uint8_t *tb_ret_addr;
                    110: 
                    111: static inline uint32_t reloc_lo16_val (void *pc, tcg_target_long target)
                    112: {
                    113:     return target & 0xffff;
                    114: }
                    115: 
                    116: static inline void reloc_lo16 (void *pc, tcg_target_long target)
                    117: {
                    118:     *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
                    119:                        | reloc_lo16_val(pc, target);
                    120: }
                    121: 
                    122: static inline uint32_t reloc_hi16_val (void *pc, tcg_target_long target)
                    123: {
                    124:     return (target >> 16) & 0xffff;
                    125: }
                    126: 
                    127: static inline void reloc_hi16 (void *pc, tcg_target_long target)
                    128: {
                    129:     *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
                    130:                        | reloc_hi16_val(pc, target);
                    131: }
                    132: 
                    133: static inline uint32_t reloc_pc16_val (void *pc, tcg_target_long target)
                    134: {
                    135:     int32_t disp;
                    136: 
                    137:     disp = target - (tcg_target_long) pc - 4;
                    138:     if (disp != (disp << 14) >> 14) {
                    139:         tcg_abort ();
                    140:     }
                    141: 
                    142:     return (disp >> 2) & 0xffff;
                    143: }
                    144: 
                    145: static inline void reloc_pc16 (void *pc, tcg_target_long target)
                    146: {
                    147:     *(uint32_t *) pc = (*(uint32_t *) pc & ~0xffff)
                    148:                        | reloc_pc16_val(pc, target);
                    149: }
                    150: 
                    151: static inline uint32_t reloc_26_val (void *pc, tcg_target_long target)
                    152: {
                    153:     if ((((tcg_target_long)pc + 4) & 0xf0000000) != (target & 0xf0000000)) {
                    154:         tcg_abort ();
                    155:     }
                    156: 
                    157:     return (target >> 2) & 0x3ffffff;
                    158: }
                    159: 
                    160: static inline void reloc_pc26 (void *pc, tcg_target_long target)
                    161: {
                    162:     *(uint32_t *) pc = (*(uint32_t *) pc & ~0x3ffffff)
                    163:                        | reloc_26_val(pc, target);
                    164: }
                    165: 
                    166: static void patch_reloc(uint8_t *code_ptr, int type,
                    167:                         tcg_target_long value, tcg_target_long addend)
                    168: {
                    169:     value += addend;
                    170:     switch(type) {
                    171:     case R_MIPS_LO16:
                    172:         reloc_lo16(code_ptr, value);
                    173:         break;
                    174:     case R_MIPS_HI16:
                    175:         reloc_hi16(code_ptr, value);
                    176:         break;
                    177:     case R_MIPS_PC16:
                    178:         reloc_pc16(code_ptr, value);
                    179:         break;
                    180:     case R_MIPS_26:
                    181:         reloc_pc26(code_ptr, value);
                    182:         break;
                    183:     default:
                    184:         tcg_abort();
                    185:     }
                    186: }
                    187: 
                    188: /* maximum number of register used for input function arguments */
                    189: static inline int tcg_target_get_call_iarg_regs_count(int flags)
                    190: {
                    191:     return 4;
                    192: }
                    193: 
                    194: /* parse target specific constraints */
                    195: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
                    196: {
                    197:     const char *ct_str;
                    198: 
                    199:     ct_str = *pct_str;
                    200:     switch(ct_str[0]) {
                    201:     case 'r':
                    202:         ct->ct |= TCG_CT_REG;
                    203:         tcg_regset_set(ct->u.regs, 0xffffffff);
                    204:         break;
                    205:     case 'C':
                    206:         ct->ct |= TCG_CT_REG;
                    207:         tcg_regset_clear(ct->u.regs);
                    208:         tcg_regset_set_reg(ct->u.regs, TCG_REG_T9);
                    209:         break;
                    210:     case 'L': /* qemu_ld output arg constraint */
                    211:         ct->ct |= TCG_CT_REG;
                    212:         tcg_regset_set(ct->u.regs, 0xffffffff);
                    213:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
                    214:         break;
                    215:     case 'l': /* qemu_ld input arg constraint */
                    216:         ct->ct |= TCG_CT_REG;
                    217:         tcg_regset_set(ct->u.regs, 0xffffffff);
                    218: #if defined(CONFIG_SOFTMMU)
                    219:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
                    220: #endif
                    221:         break;
                    222:     case 'S': /* qemu_st constraint */
                    223:         ct->ct |= TCG_CT_REG;
                    224:         tcg_regset_set(ct->u.regs, 0xffffffff);
                    225:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
1.1.1.4   root      226: #if defined(CONFIG_SOFTMMU)
1.1       root      227: # if TARGET_LONG_BITS == 64
                    228:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
                    229: # endif
                    230:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
                    231: #endif
                    232:         break;
                    233:     case 'I':
                    234:         ct->ct |= TCG_CT_CONST_U16;
                    235:         break;
                    236:     case 'J':
                    237:         ct->ct |= TCG_CT_CONST_S16;
                    238:         break;
                    239:     case 'Z':
                    240:         /* We are cheating a bit here, using the fact that the register
                    241:            ZERO is also the register number 0. Hence there is no need
                    242:            to check for const_args in each instruction. */
                    243:         ct->ct |= TCG_CT_CONST_ZERO;
                    244:         break;
                    245:     default:
                    246:         return -1;
                    247:     }
                    248:     ct_str++;
                    249:     *pct_str = ct_str;
                    250:     return 0;
                    251: }
                    252: 
                    253: /* test if a constant matches the constraint */
                    254: static inline int tcg_target_const_match(tcg_target_long val,
                    255:                                          const TCGArgConstraint *arg_ct)
                    256: {
                    257:     int ct;
                    258:     ct = arg_ct->ct;
                    259:     if (ct & TCG_CT_CONST)
                    260:         return 1;
                    261:     else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
                    262:         return 1;
                    263:     else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val)
                    264:         return 1;
                    265:     else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val)
                    266:         return 1;
                    267:     else
                    268:         return 0;
                    269: }
                    270: 
                    271: /* instruction opcodes */
                    272: enum {
                    273:     OPC_BEQ      = 0x04 << 26,
                    274:     OPC_BNE      = 0x05 << 26,
                    275:     OPC_ADDIU    = 0x09 << 26,
1.1.1.4   root      276:     OPC_SLTI     = 0x0A << 26,
                    277:     OPC_SLTIU    = 0x0B << 26,
1.1       root      278:     OPC_ANDI     = 0x0C << 26,
                    279:     OPC_ORI      = 0x0D << 26,
                    280:     OPC_XORI     = 0x0E << 26,
                    281:     OPC_LUI      = 0x0F << 26,
                    282:     OPC_LB       = 0x20 << 26,
                    283:     OPC_LH       = 0x21 << 26,
                    284:     OPC_LW       = 0x23 << 26,
                    285:     OPC_LBU      = 0x24 << 26,
                    286:     OPC_LHU      = 0x25 << 26,
                    287:     OPC_LWU      = 0x27 << 26,
                    288:     OPC_SB       = 0x28 << 26,
                    289:     OPC_SH       = 0x29 << 26,
                    290:     OPC_SW       = 0x2B << 26,
1.1.1.4   root      291: 
                    292:     OPC_SPECIAL  = 0x00 << 26,
1.1       root      293:     OPC_SLL      = OPC_SPECIAL | 0x00,
                    294:     OPC_SRL      = OPC_SPECIAL | 0x02,
                    295:     OPC_SRA      = OPC_SPECIAL | 0x03,
                    296:     OPC_SLLV     = OPC_SPECIAL | 0x04,
                    297:     OPC_SRLV     = OPC_SPECIAL | 0x06,
                    298:     OPC_SRAV     = OPC_SPECIAL | 0x07,
                    299:     OPC_JR       = OPC_SPECIAL | 0x08,
                    300:     OPC_JALR     = OPC_SPECIAL | 0x09,
                    301:     OPC_MFHI     = OPC_SPECIAL | 0x10,
                    302:     OPC_MFLO     = OPC_SPECIAL | 0x12,
                    303:     OPC_MULT     = OPC_SPECIAL | 0x18,
                    304:     OPC_MULTU    = OPC_SPECIAL | 0x19,
                    305:     OPC_DIV      = OPC_SPECIAL | 0x1A,
                    306:     OPC_DIVU     = OPC_SPECIAL | 0x1B,
                    307:     OPC_ADDU     = OPC_SPECIAL | 0x21,
                    308:     OPC_SUBU     = OPC_SPECIAL | 0x23,
                    309:     OPC_AND      = OPC_SPECIAL | 0x24,
                    310:     OPC_OR       = OPC_SPECIAL | 0x25,
                    311:     OPC_XOR      = OPC_SPECIAL | 0x26,
                    312:     OPC_NOR      = OPC_SPECIAL | 0x27,
                    313:     OPC_SLT      = OPC_SPECIAL | 0x2A,
                    314:     OPC_SLTU     = OPC_SPECIAL | 0x2B,
1.1.1.4   root      315: 
                    316:     OPC_SPECIAL3 = 0x1f << 26,
                    317:     OPC_SEB      = OPC_SPECIAL3 | 0x420,
                    318:     OPC_SEH      = OPC_SPECIAL3 | 0x620,
1.1       root      319: };
                    320: 
                    321: /*
                    322:  * Type reg
                    323:  */
                    324: static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
                    325: {
                    326:     int32_t inst;
                    327: 
                    328:     inst = opc;
                    329:     inst |= (rs & 0x1F) << 21;
                    330:     inst |= (rt & 0x1F) << 16;
                    331:     inst |= (rd & 0x1F) << 11;
                    332:     tcg_out32(s, inst);
                    333: }
                    334: 
                    335: /*
                    336:  * Type immediate
                    337:  */
                    338: static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
                    339: {
                    340:     int32_t inst;
                    341: 
                    342:     inst = opc;
                    343:     inst |= (rs & 0x1F) << 21;
                    344:     inst |= (rt & 0x1F) << 16;
                    345:     inst |= (imm & 0xffff);
                    346:     tcg_out32(s, inst);
                    347: }
                    348: 
                    349: /*
1.1.1.3   root      350:  * Type branch
                    351:  */
                    352: static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
                    353: {
1.1.1.5 ! root      354:     /* We pay attention here to not modify the branch target by reading
        !           355:        the existing value and using it again. This ensure that caches and
        !           356:        memory are kept coherent during retranslation. */
        !           357:     uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
1.1.1.3   root      358: 
                    359:     tcg_out_opc_imm(s, opc, rt, rs, offset);
                    360: }
                    361: 
                    362: /*
1.1       root      363:  * Type sa
                    364:  */
                    365: static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
                    366: {
                    367:     int32_t inst;
                    368: 
                    369:     inst = opc;
                    370:     inst |= (rt & 0x1F) << 16;
                    371:     inst |= (rd & 0x1F) << 11;
                    372:     inst |= (sa & 0x1F) <<  6;
                    373:     tcg_out32(s, inst);
                    374: 
                    375: }
                    376: 
                    377: static inline void tcg_out_nop(TCGContext *s)
                    378: {
                    379:     tcg_out32(s, 0);
                    380: }
                    381: 
1.1.1.4   root      382: static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
1.1       root      383: {
                    384:     tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
                    385: }
                    386: 
                    387: static inline void tcg_out_movi(TCGContext *s, TCGType type,
                    388:                                 int reg, int32_t arg)
                    389: {
                    390:     if (arg == (int16_t)arg) {
                    391:         tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
                    392:     } else if (arg == (uint16_t)arg) {
                    393:         tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
                    394:     } else {
                    395:         tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
                    396:         tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
                    397:     }
                    398: }
                    399: 
                    400: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
                    401: {
                    402:     /* ret and arg can't be register at */
                    403:     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    404:         tcg_abort();
                    405:     }
                    406: 
                    407:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    408:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
                    409: 
                    410:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
                    411:     tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
                    412:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    413: }
                    414: 
                    415: static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
                    416: {
                    417:     /* ret and arg can't be register at */
                    418:     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    419:         tcg_abort();
                    420:     }
                    421: 
                    422:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    423:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
                    424: 
                    425:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
                    426:     tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
                    427:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    428: }
                    429: 
                    430: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
                    431: {
                    432:     /* ret and arg must be different and can't be register at */
                    433:     if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    434:         tcg_abort();
                    435:     }
                    436: 
                    437:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
                    438: 
                    439:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
                    440:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    441: 
                    442:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
                    443:     tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
                    444:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    445: 
                    446:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    447:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
                    448:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    449: }
                    450: 
1.1.1.4   root      451: static inline void tcg_out_ext8s(TCGContext *s, int ret, int arg)
                    452: {
                    453: #ifdef _MIPS_ARCH_MIPS32R2
                    454:     tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
                    455: #else
                    456:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
                    457:     tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
                    458: #endif
                    459: }
                    460: 
                    461: static inline void tcg_out_ext16s(TCGContext *s, int ret, int arg)
                    462: {
                    463: #ifdef _MIPS_ARCH_MIPS32R2
                    464:     tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
                    465: #else
                    466:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
                    467:     tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
                    468: #endif
                    469: }
                    470: 
1.1       root      471: static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
                    472:                               int arg1, tcg_target_long arg2)
                    473: {
                    474:     if (arg2 == (int16_t) arg2) {
                    475:         tcg_out_opc_imm(s, opc, arg, arg1, arg2);
                    476:     } else {
                    477:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
                    478:         tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
                    479:         tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
                    480:     }
                    481: }
                    482: 
                    483: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
                    484:                               int arg1, tcg_target_long arg2)
                    485: {
                    486:     tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
                    487: }
                    488: 
                    489: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                    490:                               int arg1, tcg_target_long arg2)
                    491: {
                    492:     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
                    493: }
                    494: 
                    495: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
                    496: {
                    497:     if (val == (int16_t)val) {
                    498:         tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
                    499:     } else {
                    500:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
                    501:         tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
                    502:     }
                    503: }
                    504: 
1.1.1.4   root      505: static void tcg_out_brcond(TCGContext *s, TCGCond cond, int arg1,
1.1       root      506:                            int arg2, int label_index)
                    507: {
                    508:     TCGLabel *l = &s->labels[label_index];
                    509: 
                    510:     switch (cond) {
                    511:     case TCG_COND_EQ:
1.1.1.3   root      512:         tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
1.1       root      513:         break;
                    514:     case TCG_COND_NE:
1.1.1.3   root      515:         tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
1.1       root      516:         break;
                    517:     case TCG_COND_LT:
                    518:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3   root      519:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      520:         break;
                    521:     case TCG_COND_LTU:
                    522:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3   root      523:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      524:         break;
                    525:     case TCG_COND_GE:
                    526:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3   root      527:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      528:         break;
                    529:     case TCG_COND_GEU:
                    530:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3   root      531:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      532:         break;
                    533:     case TCG_COND_LE:
                    534:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3   root      535:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      536:         break;
                    537:     case TCG_COND_LEU:
                    538:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3   root      539:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      540:         break;
                    541:     case TCG_COND_GT:
                    542:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3   root      543:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      544:         break;
                    545:     case TCG_COND_GTU:
                    546:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3   root      547:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      548:         break;
                    549:     default:
                    550:         tcg_abort();
                    551:         break;
                    552:     }
                    553:     if (l->has_value) {
                    554:         reloc_pc16(s->code_ptr - 4, l->u.value);
                    555:     } else {
                    556:         tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
                    557:     }
                    558:     tcg_out_nop(s);
                    559: }
                    560: 
                    561: /* XXX: we implement it at the target level to avoid having to
                    562:    handle cross basic blocks temporaries */
1.1.1.4   root      563: static void tcg_out_brcond2(TCGContext *s, TCGCond cond, int arg1,
1.1       root      564:                             int arg2, int arg3, int arg4, int label_index)
                    565: {
                    566:     void *label_ptr;
                    567: 
                    568:     switch(cond) {
                    569:     case TCG_COND_NE:
                    570:         tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
                    571:         tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
                    572:         return;
                    573:     case TCG_COND_EQ:
                    574:         break;
                    575:     case TCG_COND_LT:
                    576:     case TCG_COND_LE:
                    577:         tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
                    578:         break;
                    579:     case TCG_COND_GT:
                    580:     case TCG_COND_GE:
                    581:         tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
                    582:         break;
                    583:     case TCG_COND_LTU:
                    584:     case TCG_COND_LEU:
                    585:         tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
                    586:         break;
                    587:     case TCG_COND_GTU:
                    588:     case TCG_COND_GEU:
                    589:         tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
                    590:         break;
                    591:     default:
                    592:         tcg_abort();
                    593:     }
                    594: 
                    595:     label_ptr = s->code_ptr;
1.1.1.3   root      596:     tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
1.1       root      597:     tcg_out_nop(s);
                    598: 
                    599:     switch(cond) {
                    600:     case TCG_COND_EQ:
                    601:         tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
                    602:         break;
                    603:     case TCG_COND_LT:
                    604:     case TCG_COND_LTU:
                    605:         tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
                    606:         break;
                    607:     case TCG_COND_LE:
                    608:     case TCG_COND_LEU:
                    609:         tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
                    610:         break;
                    611:     case TCG_COND_GT:
                    612:     case TCG_COND_GTU:
                    613:         tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
                    614:         break;
                    615:     case TCG_COND_GE:
                    616:     case TCG_COND_GEU:
                    617:         tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
                    618:         break;
                    619:     default:
                    620:         tcg_abort();
                    621:     }
                    622: 
                    623:     reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
                    624: }
                    625: 
1.1.1.4   root      626: static void tcg_out_setcond(TCGContext *s, TCGCond cond, int ret,
                    627:                             int arg1, int arg2)
                    628: {
                    629:     switch (cond) {
                    630:     case TCG_COND_EQ:
                    631:         if (arg1 == 0) {
                    632:             tcg_out_opc_imm(s, OPC_SLTIU, ret, arg2, 1);
                    633:         } else if (arg2 == 0) {
                    634:             tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
                    635:         } else {
                    636:             tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
                    637:             tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
                    638:         }
                    639:         break;
                    640:     case TCG_COND_NE:
                    641:         if (arg1 == 0) {
                    642:             tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg2);
                    643:         } else if (arg2 == 0) {
                    644:             tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
                    645:         } else {
                    646:             tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
                    647:             tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
                    648:         }
                    649:         break;
                    650:     case TCG_COND_LT:
                    651:         tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
                    652:         break;
                    653:     case TCG_COND_LTU:
                    654:         tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
                    655:         break;
                    656:     case TCG_COND_GE:
                    657:         tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
                    658:         tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
                    659:         break;
                    660:     case TCG_COND_GEU:
                    661:         tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
                    662:         tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
                    663:         break;
                    664:     case TCG_COND_LE:
                    665:         tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
                    666:         tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
                    667:         break;
                    668:     case TCG_COND_LEU:
                    669:         tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
                    670:         tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
                    671:         break;
                    672:     case TCG_COND_GT:
                    673:         tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
                    674:         break;
                    675:     case TCG_COND_GTU:
                    676:         tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
                    677:         break;
                    678:     default:
                    679:         tcg_abort();
                    680:         break;
                    681:     }
                    682: }
                    683: 
                    684: /* XXX: we implement it at the target level to avoid having to
                    685:    handle cross basic blocks temporaries */
                    686: static void tcg_out_setcond2(TCGContext *s, TCGCond cond, int ret,
                    687:                              int arg1, int arg2, int arg3, int arg4)
                    688: {
                    689:     switch (cond) {
                    690:     case TCG_COND_EQ:
                    691:         tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_AT, arg2, arg4);
                    692:         tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg1, arg3);
                    693:         tcg_out_opc_reg(s, OPC_AND, ret, TCG_REG_AT, TCG_REG_T0);
                    694:         return;
                    695:     case TCG_COND_NE:
                    696:         tcg_out_setcond(s, TCG_COND_NE, TCG_REG_AT, arg2, arg4);
                    697:         tcg_out_setcond(s, TCG_COND_NE, TCG_REG_T0, arg1, arg3);
                    698:         tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_AT, TCG_REG_T0);
                    699:         return;
                    700:     case TCG_COND_LT:
                    701:     case TCG_COND_LE:
                    702:         tcg_out_setcond(s, TCG_COND_LT, TCG_REG_AT, arg2, arg4);
                    703:         break;
                    704:     case TCG_COND_GT:
                    705:     case TCG_COND_GE:
                    706:         tcg_out_setcond(s, TCG_COND_GT, TCG_REG_AT, arg2, arg4);
                    707:         break;
                    708:     case TCG_COND_LTU:
                    709:     case TCG_COND_LEU:
                    710:         tcg_out_setcond(s, TCG_COND_LTU, TCG_REG_AT, arg2, arg4);
                    711:         break;
                    712:     case TCG_COND_GTU:
                    713:     case TCG_COND_GEU:
                    714:         tcg_out_setcond(s, TCG_COND_GTU, TCG_REG_AT, arg2, arg4);
                    715:         break;
                    716:     default:
                    717:         tcg_abort();
                    718:         break;
                    719:     }
                    720: 
                    721:     tcg_out_setcond(s, TCG_COND_EQ, TCG_REG_T0, arg2, arg4);
                    722: 
                    723:     switch(cond) {
                    724:     case TCG_COND_LT:
                    725:     case TCG_COND_LTU:
                    726:         tcg_out_setcond(s, TCG_COND_LTU, ret, arg1, arg3);
                    727:         break;
                    728:     case TCG_COND_LE:
                    729:     case TCG_COND_LEU:
                    730:         tcg_out_setcond(s, TCG_COND_LEU, ret, arg1, arg3);
                    731:         break;
                    732:     case TCG_COND_GT:
                    733:     case TCG_COND_GTU:
                    734:         tcg_out_setcond(s, TCG_COND_GTU, ret, arg1, arg3);
                    735:         break;
                    736:     case TCG_COND_GE:
                    737:     case TCG_COND_GEU:
                    738:         tcg_out_setcond(s, TCG_COND_GEU, ret, arg1, arg3);
                    739:         break;
                    740:     default:
                    741:         tcg_abort();
                    742:     }
                    743: 
                    744:     tcg_out_opc_reg(s, OPC_AND, ret, ret, TCG_REG_T0);
                    745:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    746: }
                    747: 
1.1       root      748: #if defined(CONFIG_SOFTMMU)
                    749: 
                    750: #include "../../softmmu_defs.h"
                    751: 
                    752: static void *qemu_ld_helpers[4] = {
                    753:     __ldb_mmu,
                    754:     __ldw_mmu,
                    755:     __ldl_mmu,
                    756:     __ldq_mmu,
                    757: };
                    758: 
                    759: static void *qemu_st_helpers[4] = {
                    760:     __stb_mmu,
                    761:     __stw_mmu,
                    762:     __stl_mmu,
                    763:     __stq_mmu,
                    764: };
                    765: #endif
                    766: 
                    767: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                    768:                             int opc)
                    769: {
                    770:     int addr_regl, addr_reg1, addr_meml;
                    771:     int data_regl, data_regh, data_reg1, data_reg2;
                    772:     int mem_index, s_bits;
                    773: #if defined(CONFIG_SOFTMMU)
                    774:     void *label1_ptr, *label2_ptr;
                    775:     int sp_args;
                    776: #endif
                    777: #if TARGET_LONG_BITS == 64
                    778: # if defined(CONFIG_SOFTMMU)
                    779:     uint8_t *label3_ptr;
                    780: # endif
                    781:     int addr_regh, addr_reg2, addr_memh;
                    782: #endif
                    783:     data_regl = *args++;
                    784:     if (opc == 3)
                    785:         data_regh = *args++;
                    786:     else
                    787:         data_regh = 0;
                    788:     addr_regl = *args++;
                    789: #if TARGET_LONG_BITS == 64
                    790:     addr_regh = *args++;
                    791: #endif
                    792:     mem_index = *args;
                    793:     s_bits = opc & 3;
                    794: 
                    795:     if (opc == 3) {
                    796: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    797:         data_reg1 = data_regh;
                    798:         data_reg2 = data_regl;
                    799: #else
                    800:         data_reg1 = data_regl;
                    801:         data_reg2 = data_regh;
                    802: #endif
                    803:     } else {
                    804:         data_reg1 = data_regl;
                    805:         data_reg2 = 0;
                    806:     }
                    807: #if TARGET_LONG_BITS == 64
                    808: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    809:     addr_reg1 = addr_regh;
                    810:     addr_reg2 = addr_regl;
                    811:     addr_memh = 0;
                    812:     addr_meml = 4;
                    813: # else
                    814:     addr_reg1 = addr_regl;
                    815:     addr_reg2 = addr_regh;
                    816:     addr_memh = 4;
                    817:     addr_meml = 0;
                    818: # endif
                    819: #else
                    820:     addr_reg1 = addr_regl;
                    821:     addr_meml = 0;
                    822: #endif
                    823: 
                    824: #if defined(CONFIG_SOFTMMU)
                    825:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
                    826:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    827:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
                    828:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    829:                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
                    830:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    831:     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
                    832: 
                    833: # if TARGET_LONG_BITS == 64
                    834:     label3_ptr = s->code_ptr;
1.1.1.3   root      835:     tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1       root      836:     tcg_out_nop(s);
                    837: 
                    838:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    839:                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
                    840: 
                    841:     label1_ptr = s->code_ptr;
1.1.1.3   root      842:     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1       root      843:     tcg_out_nop(s);
                    844: 
                    845:     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
                    846: # else
                    847:     label1_ptr = s->code_ptr;
1.1.1.3   root      848:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1       root      849:     tcg_out_nop(s);
                    850: # endif
                    851: 
                    852:     /* slow path */
                    853:     sp_args = TCG_REG_A0;
1.1.1.4   root      854:     tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1       root      855: # if TARGET_LONG_BITS == 64
1.1.1.4   root      856:     tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1       root      857: # endif
                    858:     tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
                    859:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
                    860:     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
                    861:     tcg_out_nop(s);
                    862: 
                    863:     switch(opc) {
                    864:     case 0:
                    865:         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
                    866:         break;
                    867:     case 0 | 4:
1.1.1.4   root      868:         tcg_out_ext8s(s, data_reg1, TCG_REG_V0);
1.1       root      869:         break;
                    870:     case 1:
                    871:         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
                    872:         break;
                    873:     case 1 | 4:
1.1.1.4   root      874:         tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
1.1       root      875:         break;
                    876:     case 2:
1.1.1.4   root      877:         tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1       root      878:         break;
                    879:     case 3:
1.1.1.4   root      880:         tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
                    881:         tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
1.1       root      882:         break;
                    883:     default:
                    884:         tcg_abort();
                    885:     }
                    886: 
                    887:     label2_ptr = s->code_ptr;
1.1.1.3   root      888:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1       root      889:     tcg_out_nop(s);
                    890: 
                    891:     /* label1: fast path */
                    892:     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
                    893: 
1.1.1.2   root      894:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4   root      895:                     offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1.1.2   root      896:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1.1.4   root      897: #else
                    898:     if (GUEST_BASE == (int16_t)GUEST_BASE) {
                    899:         tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_V0, addr_regl, GUEST_BASE);
                    900:     } else {
                    901:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, GUEST_BASE);
                    902:         tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_V0, addr_regl);
                    903:     }
1.1       root      904: #endif
                    905: 
                    906:     switch(opc) {
                    907:     case 0:
1.1.1.4   root      908:         tcg_out_opc_imm(s, OPC_LBU, data_reg1, TCG_REG_V0, 0);
1.1       root      909:         break;
                    910:     case 0 | 4:
1.1.1.4   root      911:         tcg_out_opc_imm(s, OPC_LB, data_reg1, TCG_REG_V0, 0);
1.1       root      912:         break;
                    913:     case 1:
                    914:         if (TCG_NEED_BSWAP) {
1.1.1.4   root      915:             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1       root      916:             tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
                    917:         } else {
1.1.1.4   root      918:             tcg_out_opc_imm(s, OPC_LHU, data_reg1, TCG_REG_V0, 0);
1.1       root      919:         }
                    920:         break;
                    921:     case 1 | 4:
                    922:         if (TCG_NEED_BSWAP) {
1.1.1.4   root      923:             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, TCG_REG_V0, 0);
1.1       root      924:             tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
                    925:         } else {
1.1.1.4   root      926:             tcg_out_opc_imm(s, OPC_LH, data_reg1, TCG_REG_V0, 0);
1.1       root      927:         }
                    928:         break;
                    929:     case 2:
                    930:         if (TCG_NEED_BSWAP) {
1.1.1.4   root      931:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1       root      932:             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
                    933:         } else {
1.1.1.4   root      934:             tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
1.1       root      935:         }
                    936:         break;
                    937:     case 3:
                    938:         if (TCG_NEED_BSWAP) {
1.1.1.4   root      939:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 4);
1.1       root      940:             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
1.1.1.4   root      941:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, TCG_REG_V0, 0);
1.1       root      942:             tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
                    943:         } else {
1.1.1.4   root      944:             tcg_out_opc_imm(s, OPC_LW, data_reg1, TCG_REG_V0, 0);
                    945:             tcg_out_opc_imm(s, OPC_LW, data_reg2, TCG_REG_V0, 4);
1.1       root      946:         }
                    947:         break;
                    948:     default:
                    949:         tcg_abort();
                    950:     }
                    951: 
                    952: #if defined(CONFIG_SOFTMMU)
                    953:     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
                    954: #endif
                    955: }
                    956: 
                    957: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                    958:                             int opc)
                    959: {
                    960:     int addr_regl, addr_reg1, addr_meml;
                    961:     int data_regl, data_regh, data_reg1, data_reg2;
                    962:     int mem_index, s_bits;
                    963: #if defined(CONFIG_SOFTMMU)
                    964:     uint8_t *label1_ptr, *label2_ptr;
                    965:     int sp_args;
                    966: #endif
                    967: #if TARGET_LONG_BITS == 64
                    968: # if defined(CONFIG_SOFTMMU)
                    969:     uint8_t *label3_ptr;
                    970: # endif
                    971:     int addr_regh, addr_reg2, addr_memh;
                    972: #endif
                    973: 
                    974:     data_regl = *args++;
                    975:     if (opc == 3) {
                    976:         data_regh = *args++;
                    977: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    978:         data_reg1 = data_regh;
                    979:         data_reg2 = data_regl;
                    980: #else
                    981:         data_reg1 = data_regl;
                    982:         data_reg2 = data_regh;
                    983: #endif
                    984:     } else {
                    985:         data_reg1 = data_regl;
                    986:         data_reg2 = 0;
                    987:         data_regh = 0;
                    988:     }
                    989:     addr_regl = *args++;
                    990: #if TARGET_LONG_BITS == 64
                    991:     addr_regh = *args++;
                    992: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    993:     addr_reg1 = addr_regh;
                    994:     addr_reg2 = addr_regl;
                    995:     addr_memh = 0;
                    996:     addr_meml = 4;
                    997: # else
                    998:     addr_reg1 = addr_regl;
                    999:     addr_reg2 = addr_regh;
                   1000:     addr_memh = 4;
                   1001:     addr_meml = 0;
                   1002: # endif
                   1003: #else
                   1004:     addr_reg1 = addr_regl;
                   1005:     addr_meml = 0;
                   1006: #endif
                   1007:     mem_index = *args;
                   1008:     s_bits = opc;
                   1009: 
                   1010: #if defined(CONFIG_SOFTMMU)
                   1011:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
                   1012:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                   1013:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
                   1014:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                   1015:                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
                   1016:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                   1017:     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
                   1018: 
                   1019: # if TARGET_LONG_BITS == 64
                   1020:     label3_ptr = s->code_ptr;
1.1.1.3   root     1021:     tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1       root     1022:     tcg_out_nop(s);
                   1023: 
                   1024:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                   1025:                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
                   1026: 
                   1027:     label1_ptr = s->code_ptr;
1.1.1.3   root     1028:     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1       root     1029:     tcg_out_nop(s);
                   1030: 
                   1031:     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
                   1032: # else
                   1033:     label1_ptr = s->code_ptr;
1.1.1.3   root     1034:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1       root     1035:     tcg_out_nop(s);
                   1036: # endif
                   1037: 
                   1038:     /* slow path */
                   1039:     sp_args = TCG_REG_A0;
1.1.1.4   root     1040:     tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
1.1       root     1041: # if TARGET_LONG_BITS == 64
1.1.1.4   root     1042:     tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
1.1       root     1043: # endif
                   1044:     switch(opc) {
                   1045:     case 0:
                   1046:         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
                   1047:         break;
                   1048:     case 1:
                   1049:         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
                   1050:         break;
                   1051:     case 2:
1.1.1.4   root     1052:         tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
1.1       root     1053:         break;
                   1054:     case 3:
                   1055:         sp_args = (sp_args + 1) & ~1;
1.1.1.4   root     1056:         tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
                   1057:         tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
1.1       root     1058:         break;
                   1059:     default:
                   1060:         tcg_abort();
                   1061:     }
                   1062:     if (sp_args > TCG_REG_A3) {
                   1063:         /* Push mem_index on the stack */
                   1064:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
                   1065:         tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
                   1066:     } else {
                   1067:         tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
                   1068:     }
                   1069: 
                   1070:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
                   1071:     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
                   1072:     tcg_out_nop(s);
                   1073: 
                   1074:     label2_ptr = s->code_ptr;
1.1.1.3   root     1075:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1       root     1076:     tcg_out_nop(s);
                   1077: 
                   1078:     /* label1: fast path */
                   1079:     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
                   1080: 
                   1081:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1.1.4   root     1082:                     offsetof(CPUState, tlb_table[mem_index][0].addend));
1.1       root     1083:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
1.1.1.4   root     1084: #else
                   1085:     if (GUEST_BASE == (int16_t)GUEST_BASE) {
                   1086:         tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, addr_regl, GUEST_BASE);
                   1087:     } else {
                   1088:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, GUEST_BASE);
                   1089:         tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
                   1090:     }
1.1       root     1091: 
                   1092: #endif
                   1093: 
                   1094:     switch(opc) {
                   1095:     case 0:
1.1.1.4   root     1096:         tcg_out_opc_imm(s, OPC_SB, data_reg1, TCG_REG_A0, 0);
1.1       root     1097:         break;
                   1098:     case 1:
                   1099:         if (TCG_NEED_BSWAP) {
                   1100:             tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
1.1.1.4   root     1101:             tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, TCG_REG_A0, 0);
1.1       root     1102:         } else {
1.1.1.4   root     1103:             tcg_out_opc_imm(s, OPC_SH, data_reg1, TCG_REG_A0, 0);
1.1       root     1104:         }
                   1105:         break;
                   1106:     case 2:
                   1107:         if (TCG_NEED_BSWAP) {
                   1108:             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4   root     1109:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1       root     1110:         } else {
1.1.1.4   root     1111:             tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
1.1       root     1112:         }
                   1113:         break;
                   1114:     case 3:
                   1115:         if (TCG_NEED_BSWAP) {
                   1116:             tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
1.1.1.4   root     1117:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 0);
1.1       root     1118:             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
1.1.1.4   root     1119:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, TCG_REG_A0, 4);
1.1       root     1120:         } else {
1.1.1.4   root     1121:             tcg_out_opc_imm(s, OPC_SW, data_reg1, TCG_REG_A0, 0);
                   1122:             tcg_out_opc_imm(s, OPC_SW, data_reg2, TCG_REG_A0, 4);
1.1       root     1123:         }
                   1124:         break;
                   1125:     default:
                   1126:         tcg_abort();
                   1127:     }
                   1128: 
                   1129: #if defined(CONFIG_SOFTMMU)
                   1130:     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
                   1131: #endif
                   1132: }
                   1133: 
1.1.1.4   root     1134: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1       root     1135:                               const TCGArg *args, const int *const_args)
                   1136: {
                   1137:     switch(opc) {
                   1138:     case INDEX_op_exit_tb:
                   1139:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
                   1140:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
                   1141:         tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
                   1142:         tcg_out_nop(s);
                   1143:         break;
                   1144:     case INDEX_op_goto_tb:
                   1145:         if (s->tb_jmp_offset) {
                   1146:             /* direct jump method */
                   1147:             tcg_abort();
                   1148:         } else {
                   1149:             /* indirect jump method */
                   1150:             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
                   1151:             tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
                   1152:             tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
                   1153:         }
                   1154:         tcg_out_nop(s);
                   1155:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                   1156:         break;
                   1157:     case INDEX_op_call:
                   1158:         tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
                   1159:         tcg_out_nop(s);
                   1160:         break;
                   1161:     case INDEX_op_jmp:
                   1162:         tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
                   1163:         tcg_out_nop(s);
                   1164:         break;
                   1165:     case INDEX_op_br:
                   1166:         tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
                   1167:         break;
                   1168: 
                   1169:     case INDEX_op_mov_i32:
1.1.1.4   root     1170:         tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
1.1       root     1171:         break;
                   1172:     case INDEX_op_movi_i32:
                   1173:         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
                   1174:         break;
                   1175: 
                   1176:     case INDEX_op_ld8u_i32:
1.1.1.4   root     1177:         tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
1.1       root     1178:         break;
                   1179:     case INDEX_op_ld8s_i32:
                   1180:         tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
                   1181:         break;
                   1182:     case INDEX_op_ld16u_i32:
                   1183:         tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
                   1184:         break;
                   1185:     case INDEX_op_ld16s_i32:
                   1186:         tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
                   1187:         break;
                   1188:     case INDEX_op_ld_i32:
                   1189:         tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
                   1190:         break;
                   1191:     case INDEX_op_st8_i32:
                   1192:         tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
                   1193:         break;
                   1194:     case INDEX_op_st16_i32:
                   1195:         tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
                   1196:         break;
                   1197:     case INDEX_op_st_i32:
                   1198:         tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
                   1199:         break;
                   1200: 
                   1201:     case INDEX_op_add_i32:
                   1202:         if (const_args[2]) {
                   1203:             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
                   1204:         } else {
                   1205:             tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
                   1206:         }
                   1207:         break;
                   1208:     case INDEX_op_add2_i32:
                   1209:         if (const_args[4]) {
                   1210:             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
                   1211:         } else {
                   1212:             tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
                   1213:         }
                   1214:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
                   1215:         if (const_args[5]) {
                   1216:             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
                   1217:         } else {
                   1218:              tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
                   1219:         }
                   1220:         tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
1.1.1.4   root     1221:         tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1       root     1222:         break;
                   1223:     case INDEX_op_sub_i32:
                   1224:         if (const_args[2]) {
                   1225:             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
                   1226:         } else {
                   1227:             tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
                   1228:         }
                   1229:         break;
                   1230:     case INDEX_op_sub2_i32:
                   1231:         if (const_args[4]) {
                   1232:             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
                   1233:         } else {
                   1234:             tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
                   1235:         }
                   1236:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
                   1237:         if (const_args[5]) {
                   1238:             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
                   1239:         } else {
                   1240:              tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
                   1241:         }
                   1242:         tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
1.1.1.4   root     1243:         tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
1.1       root     1244:         break;
                   1245:     case INDEX_op_mul_i32:
                   1246:         tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
                   1247:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1248:         break;
                   1249:     case INDEX_op_mulu2_i32:
                   1250:         tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
                   1251:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1252:         tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
                   1253:         break;
                   1254:     case INDEX_op_div_i32:
                   1255:         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
                   1256:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1257:         break;
                   1258:     case INDEX_op_divu_i32:
                   1259:         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
                   1260:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1261:         break;
                   1262:     case INDEX_op_rem_i32:
                   1263:         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
                   1264:         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
                   1265:         break;
                   1266:     case INDEX_op_remu_i32:
                   1267:         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
                   1268:         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
                   1269:         break;
                   1270: 
                   1271:     case INDEX_op_and_i32:
                   1272:         if (const_args[2]) {
                   1273:             tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
                   1274:         } else {
                   1275:             tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
                   1276:         }
                   1277:         break;
                   1278:     case INDEX_op_or_i32:
                   1279:         if (const_args[2]) {
                   1280:             tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
                   1281:         } else {
                   1282:             tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
                   1283:         }
                   1284:         break;
1.1.1.4   root     1285:     case INDEX_op_nor_i32:
                   1286:         tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[2]);
                   1287:         break;
1.1       root     1288:     case INDEX_op_not_i32:
1.1.1.4   root     1289:         tcg_out_opc_reg(s, OPC_NOR, args[0], TCG_REG_ZERO, args[1]);
1.1       root     1290:         break;
                   1291:     case INDEX_op_xor_i32:
                   1292:         if (const_args[2]) {
                   1293:             tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
                   1294:         } else {
                   1295:             tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
                   1296:         }
                   1297:         break;
                   1298: 
                   1299:     case INDEX_op_sar_i32:
                   1300:         if (const_args[2]) {
                   1301:             tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
                   1302:         } else {
                   1303:             tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
                   1304:         }
                   1305:         break;
                   1306:     case INDEX_op_shl_i32:
                   1307:         if (const_args[2]) {
                   1308:             tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
                   1309:         } else {
                   1310:             tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
                   1311:         }
                   1312:         break;
                   1313:     case INDEX_op_shr_i32:
                   1314:         if (const_args[2]) {
                   1315:             tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
                   1316:         } else {
                   1317:             tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
                   1318:         }
                   1319:         break;
                   1320: 
1.1.1.4   root     1321:     case INDEX_op_ext8s_i32:
                   1322:         tcg_out_ext8s(s, args[0], args[1]);
                   1323:         break;
                   1324:     case INDEX_op_ext16s_i32:
                   1325:         tcg_out_ext16s(s, args[0], args[1]);
                   1326:         break;
                   1327: 
1.1       root     1328:     case INDEX_op_brcond_i32:
                   1329:         tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
                   1330:         break;
                   1331:     case INDEX_op_brcond2_i32:
                   1332:         tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
                   1333:         break;
                   1334: 
1.1.1.4   root     1335:     case INDEX_op_setcond_i32:
                   1336:         tcg_out_setcond(s, args[3], args[0], args[1], args[2]);
                   1337:         break;
                   1338:     case INDEX_op_setcond2_i32:
                   1339:         tcg_out_setcond2(s, args[5], args[0], args[1], args[2], args[3], args[4]);
                   1340:         break;
                   1341: 
1.1       root     1342:     case INDEX_op_qemu_ld8u:
                   1343:         tcg_out_qemu_ld(s, args, 0);
                   1344:         break;
                   1345:     case INDEX_op_qemu_ld8s:
                   1346:         tcg_out_qemu_ld(s, args, 0 | 4);
                   1347:         break;
                   1348:     case INDEX_op_qemu_ld16u:
                   1349:         tcg_out_qemu_ld(s, args, 1);
                   1350:         break;
                   1351:     case INDEX_op_qemu_ld16s:
                   1352:         tcg_out_qemu_ld(s, args, 1 | 4);
                   1353:         break;
1.1.1.4   root     1354:     case INDEX_op_qemu_ld32:
1.1       root     1355:         tcg_out_qemu_ld(s, args, 2);
                   1356:         break;
                   1357:     case INDEX_op_qemu_ld64:
                   1358:         tcg_out_qemu_ld(s, args, 3);
                   1359:         break;
                   1360:     case INDEX_op_qemu_st8:
                   1361:         tcg_out_qemu_st(s, args, 0);
                   1362:         break;
                   1363:     case INDEX_op_qemu_st16:
                   1364:         tcg_out_qemu_st(s, args, 1);
                   1365:         break;
                   1366:     case INDEX_op_qemu_st32:
                   1367:         tcg_out_qemu_st(s, args, 2);
                   1368:         break;
                   1369:     case INDEX_op_qemu_st64:
                   1370:         tcg_out_qemu_st(s, args, 3);
                   1371:         break;
                   1372: 
                   1373:     default:
                   1374:         tcg_abort();
                   1375:     }
                   1376: }
                   1377: 
                   1378: static const TCGTargetOpDef mips_op_defs[] = {
                   1379:     { INDEX_op_exit_tb, { } },
                   1380:     { INDEX_op_goto_tb, { } },
                   1381:     { INDEX_op_call, { "C" } },
                   1382:     { INDEX_op_jmp, { "r" } },
                   1383:     { INDEX_op_br, { } },
                   1384: 
                   1385:     { INDEX_op_mov_i32, { "r", "r" } },
                   1386:     { INDEX_op_movi_i32, { "r" } },
                   1387:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1388:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1389:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1390:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1391:     { INDEX_op_ld_i32, { "r", "r" } },
                   1392:     { INDEX_op_st8_i32, { "rZ", "r" } },
                   1393:     { INDEX_op_st16_i32, { "rZ", "r" } },
                   1394:     { INDEX_op_st_i32, { "rZ", "r" } },
                   1395: 
                   1396:     { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
                   1397:     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
                   1398:     { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
                   1399:     { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
                   1400:     { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
                   1401:     { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
                   1402:     { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
                   1403:     { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
                   1404: 
                   1405:     { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
1.1.1.4   root     1406:     { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1.1       root     1407:     { INDEX_op_not_i32, { "r", "rZ" } },
                   1408:     { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
                   1409:     { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
                   1410: 
                   1411:     { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
                   1412:     { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
                   1413:     { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
                   1414: 
1.1.1.4   root     1415:     { INDEX_op_ext8s_i32, { "r", "rZ" } },
                   1416:     { INDEX_op_ext16s_i32, { "r", "rZ" } },
                   1417: 
1.1       root     1418:     { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1.1.1.4   root     1419:     { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
                   1420:     { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1.1       root     1421: 
                   1422:     { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
                   1423:     { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
                   1424:     { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
                   1425: 
                   1426: #if TARGET_LONG_BITS == 32
                   1427:     { INDEX_op_qemu_ld8u, { "L", "lZ" } },
                   1428:     { INDEX_op_qemu_ld8s, { "L", "lZ" } },
                   1429:     { INDEX_op_qemu_ld16u, { "L", "lZ" } },
                   1430:     { INDEX_op_qemu_ld16s, { "L", "lZ" } },
1.1.1.4   root     1431:     { INDEX_op_qemu_ld32, { "L", "lZ" } },
1.1       root     1432:     { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
                   1433: 
                   1434:     { INDEX_op_qemu_st8, { "SZ", "SZ" } },
                   1435:     { INDEX_op_qemu_st16, { "SZ", "SZ" } },
                   1436:     { INDEX_op_qemu_st32, { "SZ", "SZ" } },
                   1437:     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
                   1438: #else
                   1439:     { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
                   1440:     { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
                   1441:     { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
                   1442:     { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
1.1.1.4   root     1443:     { INDEX_op_qemu_ld32, { "L", "lZ", "lZ" } },
1.1       root     1444:     { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
                   1445: 
                   1446:     { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
                   1447:     { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
                   1448:     { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
                   1449:     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
                   1450: #endif
                   1451:     { -1 },
                   1452: };
                   1453: 
                   1454: static int tcg_target_callee_save_regs[] = {
1.1.1.3   root     1455: #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1.1       root     1456:     TCG_REG_S0,
1.1.1.3   root     1457: #endif
1.1       root     1458:     TCG_REG_S1,
                   1459:     TCG_REG_S2,
                   1460:     TCG_REG_S3,
                   1461:     TCG_REG_S4,
                   1462:     TCG_REG_S5,
                   1463:     TCG_REG_S6,
                   1464:     TCG_REG_S7,
                   1465:     TCG_REG_GP,
1.1.1.3   root     1466:     TCG_REG_FP,
1.1       root     1467:     TCG_REG_RA,       /* should be last for ABI compliance */
                   1468: };
                   1469: 
                   1470: /* Generate global QEMU prologue and epilogue code */
1.1.1.4   root     1471: static void tcg_target_qemu_prologue(TCGContext *s)
1.1       root     1472: {
                   1473:     int i, frame_size;
                   1474: 
                   1475:     /* reserve some stack space */
                   1476:     frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
                   1477:                  + TCG_STATIC_CALL_ARGS_SIZE;
                   1478:     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
                   1479:                  ~(TCG_TARGET_STACK_ALIGN - 1);
                   1480: 
                   1481:     /* TB prologue */
                   1482:     tcg_out_addi(s, TCG_REG_SP, -frame_size);
                   1483:     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
                   1484:         tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
                   1485:                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
                   1486:     }
                   1487: 
                   1488:     /* Call generated code */
                   1489:     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
                   1490:     tcg_out_nop(s);
                   1491:     tb_ret_addr = s->code_ptr;
                   1492: 
                   1493:     /* TB epilogue */
                   1494:     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
                   1495:         tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
                   1496:                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
                   1497:     }
                   1498: 
                   1499:     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
                   1500:     tcg_out_addi(s, TCG_REG_SP, frame_size);
                   1501: }
                   1502: 
1.1.1.4   root     1503: static void tcg_target_init(TCGContext *s)
1.1       root     1504: {
                   1505:     tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
                   1506:     tcg_regset_set(tcg_target_call_clobber_regs,
                   1507:                    (1 << TCG_REG_V0) |
                   1508:                    (1 << TCG_REG_V1) |
                   1509:                    (1 << TCG_REG_A0) |
                   1510:                    (1 << TCG_REG_A1) |
                   1511:                    (1 << TCG_REG_A2) |
                   1512:                    (1 << TCG_REG_A3) |
                   1513:                    (1 << TCG_REG_T1) |
                   1514:                    (1 << TCG_REG_T2) |
                   1515:                    (1 << TCG_REG_T3) |
                   1516:                    (1 << TCG_REG_T4) |
                   1517:                    (1 << TCG_REG_T5) |
                   1518:                    (1 << TCG_REG_T6) |
                   1519:                    (1 << TCG_REG_T7) |
                   1520:                    (1 << TCG_REG_T8) |
                   1521:                    (1 << TCG_REG_T9));
                   1522: 
                   1523:     tcg_regset_clear(s->reserved_regs);
                   1524:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
                   1525:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
                   1526:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
                   1527:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
                   1528:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
                   1529:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
                   1530:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
                   1531: 
                   1532:     tcg_add_target_add_op_defs(mips_op_defs);
                   1533: }

unix.superglobalmegacorp.com

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