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

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: #if defined(CONFIG_SOFTMMU)
                    226:         tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
                    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_SPECIAL  = 0x00 << 26,
                    274:     OPC_BEQ      = 0x04 << 26,
                    275:     OPC_BNE      = 0x05 << 26,
                    276:     OPC_ADDIU    = 0x09 << 26,
                    277:     OPC_ANDI     = 0x0C << 26,
                    278:     OPC_ORI      = 0x0D << 26,
                    279:     OPC_XORI     = 0x0E << 26,
                    280:     OPC_LUI      = 0x0F << 26,
                    281:     OPC_LB       = 0x20 << 26,
                    282:     OPC_LH       = 0x21 << 26,
                    283:     OPC_LW       = 0x23 << 26,
                    284:     OPC_LBU      = 0x24 << 26,
                    285:     OPC_LHU      = 0x25 << 26,
                    286:     OPC_LWU      = 0x27 << 26,
                    287:     OPC_SB       = 0x28 << 26,
                    288:     OPC_SH       = 0x29 << 26,
                    289:     OPC_SW       = 0x2B << 26,
                    290:     OPC_SLL      = OPC_SPECIAL | 0x00,
                    291:     OPC_SRL      = OPC_SPECIAL | 0x02,
                    292:     OPC_SRA      = OPC_SPECIAL | 0x03,
                    293:     OPC_SLLV     = OPC_SPECIAL | 0x04,
                    294:     OPC_SRLV     = OPC_SPECIAL | 0x06,
                    295:     OPC_SRAV     = OPC_SPECIAL | 0x07,
                    296:     OPC_JR       = OPC_SPECIAL | 0x08,
                    297:     OPC_JALR     = OPC_SPECIAL | 0x09,
                    298:     OPC_MFHI     = OPC_SPECIAL | 0x10,
                    299:     OPC_MFLO     = OPC_SPECIAL | 0x12,
                    300:     OPC_MULT     = OPC_SPECIAL | 0x18,
                    301:     OPC_MULTU    = OPC_SPECIAL | 0x19,
                    302:     OPC_DIV      = OPC_SPECIAL | 0x1A,
                    303:     OPC_DIVU     = OPC_SPECIAL | 0x1B,
                    304:     OPC_ADDU     = OPC_SPECIAL | 0x21,
                    305:     OPC_SUBU     = OPC_SPECIAL | 0x23,
                    306:     OPC_AND      = OPC_SPECIAL | 0x24,
                    307:     OPC_OR       = OPC_SPECIAL | 0x25,
                    308:     OPC_XOR      = OPC_SPECIAL | 0x26,
                    309:     OPC_NOR      = OPC_SPECIAL | 0x27,
                    310:     OPC_SLT      = OPC_SPECIAL | 0x2A,
                    311:     OPC_SLTU     = OPC_SPECIAL | 0x2B,
                    312: };
                    313: 
                    314: /*
                    315:  * Type reg
                    316:  */
                    317: static inline void tcg_out_opc_reg(TCGContext *s, int opc, int rd, int rs, int rt)
                    318: {
                    319:     int32_t inst;
                    320: 
                    321:     inst = opc;
                    322:     inst |= (rs & 0x1F) << 21;
                    323:     inst |= (rt & 0x1F) << 16;
                    324:     inst |= (rd & 0x1F) << 11;
                    325:     tcg_out32(s, inst);
                    326: }
                    327: 
                    328: /*
                    329:  * Type immediate
                    330:  */
                    331: static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int imm)
                    332: {
                    333:     int32_t inst;
                    334: 
                    335:     inst = opc;
                    336:     inst |= (rs & 0x1F) << 21;
                    337:     inst |= (rt & 0x1F) << 16;
                    338:     inst |= (imm & 0xffff);
                    339:     tcg_out32(s, inst);
                    340: }
                    341: 
                    342: /*
1.1.1.3 ! root      343:  * Type branch
        !           344:  */
        !           345: static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
        !           346: {
        !           347:     /* We need to keep the offset unchanged for retranslation */
        !           348:     uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
        !           349: 
        !           350:     tcg_out_opc_imm(s, opc, rt, rs, offset);
        !           351: }
        !           352: 
        !           353: /*
1.1       root      354:  * Type sa
                    355:  */
                    356: static inline void tcg_out_opc_sa(TCGContext *s, int opc, int rd, int rt, int sa)
                    357: {
                    358:     int32_t inst;
                    359: 
                    360:     inst = opc;
                    361:     inst |= (rt & 0x1F) << 16;
                    362:     inst |= (rd & 0x1F) << 11;
                    363:     inst |= (sa & 0x1F) <<  6;
                    364:     tcg_out32(s, inst);
                    365: 
                    366: }
                    367: 
                    368: static inline void tcg_out_nop(TCGContext *s)
                    369: {
                    370:     tcg_out32(s, 0);
                    371: }
                    372: 
                    373: static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
                    374: {
                    375:     tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
                    376: }
                    377: 
                    378: static inline void tcg_out_movi(TCGContext *s, TCGType type,
                    379:                                 int reg, int32_t arg)
                    380: {
                    381:     if (arg == (int16_t)arg) {
                    382:         tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
                    383:     } else if (arg == (uint16_t)arg) {
                    384:         tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
                    385:     } else {
                    386:         tcg_out_opc_imm(s, OPC_LUI, reg, 0, arg >> 16);
                    387:         tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
                    388:     }
                    389: }
                    390: 
                    391: static inline void tcg_out_bswap16(TCGContext *s, int ret, int arg)
                    392: {
                    393:     /* ret and arg can't be register at */
                    394:     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    395:         tcg_abort();
                    396:     }
                    397: 
                    398:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    399:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0x00ff);
                    400: 
                    401:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
                    402:     tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
                    403:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    404: }
                    405: 
                    406: static inline void tcg_out_bswap16s(TCGContext *s, int ret, int arg)
                    407: {
                    408:     /* ret and arg can't be register at */
                    409:     if (ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    410:         tcg_abort();
                    411:     }
                    412: 
                    413:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    414:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff);
                    415: 
                    416:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
                    417:     tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
                    418:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    419: }
                    420: 
                    421: static inline void tcg_out_bswap32(TCGContext *s, int ret, int arg)
                    422: {
                    423:     /* ret and arg must be different and can't be register at */
                    424:     if (ret == arg || ret == TCG_REG_AT || arg == TCG_REG_AT) {
                    425:         tcg_abort();
                    426:     }
                    427: 
                    428:     tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
                    429: 
                    430:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 24);
                    431:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    432: 
                    433:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, arg, 0xff00);
                    434:     tcg_out_opc_sa(s, OPC_SLL, TCG_REG_AT, TCG_REG_AT, 8);
                    435:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    436: 
                    437:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_AT, arg, 8);
                    438:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_AT, TCG_REG_AT, 0xff00);
                    439:     tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_REG_AT);
                    440: }
                    441: 
                    442: static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
                    443:                               int arg1, tcg_target_long arg2)
                    444: {
                    445:     if (arg2 == (int16_t) arg2) {
                    446:         tcg_out_opc_imm(s, opc, arg, arg1, arg2);
                    447:     } else {
                    448:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, arg2);
                    449:         tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, TCG_REG_AT, arg1);
                    450:         tcg_out_opc_imm(s, opc, arg, TCG_REG_AT, 0);
                    451:     }
                    452: }
                    453: 
                    454: static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
                    455:                               int arg1, tcg_target_long arg2)
                    456: {
                    457:     tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
                    458: }
                    459: 
                    460: static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
                    461:                               int arg1, tcg_target_long arg2)
                    462: {
                    463:     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
                    464: }
                    465: 
                    466: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
                    467: {
                    468:     if (val == (int16_t)val) {
                    469:         tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
                    470:     } else {
                    471:         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, val);
                    472:         tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_REG_AT);
                    473:     }
                    474: }
                    475: 
                    476: static void tcg_out_brcond(TCGContext *s, int cond, int arg1,
                    477:                            int arg2, int label_index)
                    478: {
                    479:     TCGLabel *l = &s->labels[label_index];
                    480: 
                    481:     switch (cond) {
                    482:     case TCG_COND_EQ:
1.1.1.3 ! root      483:         tcg_out_opc_br(s, OPC_BEQ, arg1, arg2);
1.1       root      484:         break;
                    485:     case TCG_COND_NE:
1.1.1.3 ! root      486:         tcg_out_opc_br(s, OPC_BNE, arg1, arg2);
1.1       root      487:         break;
                    488:     case TCG_COND_LT:
                    489:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 ! root      490:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      491:         break;
                    492:     case TCG_COND_LTU:
                    493:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 ! root      494:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      495:         break;
                    496:     case TCG_COND_GE:
                    497:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg1, arg2);
1.1.1.3 ! root      498:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      499:         break;
                    500:     case TCG_COND_GEU:
                    501:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg1, arg2);
1.1.1.3 ! root      502:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      503:         break;
                    504:     case TCG_COND_LE:
                    505:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 ! root      506:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      507:         break;
                    508:     case TCG_COND_LEU:
                    509:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 ! root      510:         tcg_out_opc_br(s, OPC_BEQ, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      511:         break;
                    512:     case TCG_COND_GT:
                    513:         tcg_out_opc_reg(s, OPC_SLT, TCG_REG_AT, arg2, arg1);
1.1.1.3 ! root      514:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      515:         break;
                    516:     case TCG_COND_GTU:
                    517:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_AT, arg2, arg1);
1.1.1.3 ! root      518:         tcg_out_opc_br(s, OPC_BNE, TCG_REG_AT, TCG_REG_ZERO);
1.1       root      519:         break;
                    520:     default:
                    521:         tcg_abort();
                    522:         break;
                    523:     }
                    524:     if (l->has_value) {
                    525:         reloc_pc16(s->code_ptr - 4, l->u.value);
                    526:     } else {
                    527:         tcg_out_reloc(s, s->code_ptr - 4, R_MIPS_PC16, label_index, 0);
                    528:     }
                    529:     tcg_out_nop(s);
                    530: }
                    531: 
                    532: /* XXX: we implement it at the target level to avoid having to
                    533:    handle cross basic blocks temporaries */
                    534: static void tcg_out_brcond2(TCGContext *s, int cond, int arg1,
                    535:                             int arg2, int arg3, int arg4, int label_index)
                    536: {
                    537:     void *label_ptr;
                    538: 
                    539:     switch(cond) {
                    540:     case TCG_COND_NE:
                    541:         tcg_out_brcond(s, TCG_COND_NE, arg2, arg4, label_index);
                    542:         tcg_out_brcond(s, TCG_COND_NE, arg1, arg3, label_index);
                    543:         return;
                    544:     case TCG_COND_EQ:
                    545:         break;
                    546:     case TCG_COND_LT:
                    547:     case TCG_COND_LE:
                    548:         tcg_out_brcond(s, TCG_COND_LT, arg2, arg4, label_index);
                    549:         break;
                    550:     case TCG_COND_GT:
                    551:     case TCG_COND_GE:
                    552:         tcg_out_brcond(s, TCG_COND_GT, arg2, arg4, label_index);
                    553:         break;
                    554:     case TCG_COND_LTU:
                    555:     case TCG_COND_LEU:
                    556:         tcg_out_brcond(s, TCG_COND_LTU, arg2, arg4, label_index);
                    557:         break;
                    558:     case TCG_COND_GTU:
                    559:     case TCG_COND_GEU:
                    560:         tcg_out_brcond(s, TCG_COND_GTU, arg2, arg4, label_index);
                    561:         break;
                    562:     default:
                    563:         tcg_abort();
                    564:     }
                    565: 
                    566:     label_ptr = s->code_ptr;
1.1.1.3 ! root      567:     tcg_out_opc_br(s, OPC_BNE, arg2, arg4);
1.1       root      568:     tcg_out_nop(s);
                    569: 
                    570:     switch(cond) {
                    571:     case TCG_COND_EQ:
                    572:         tcg_out_brcond(s, TCG_COND_EQ, arg1, arg3, label_index);
                    573:         break;
                    574:     case TCG_COND_LT:
                    575:     case TCG_COND_LTU:
                    576:         tcg_out_brcond(s, TCG_COND_LTU, arg1, arg3, label_index);
                    577:         break;
                    578:     case TCG_COND_LE:
                    579:     case TCG_COND_LEU:
                    580:         tcg_out_brcond(s, TCG_COND_LEU, arg1, arg3, label_index);
                    581:         break;
                    582:     case TCG_COND_GT:
                    583:     case TCG_COND_GTU:
                    584:         tcg_out_brcond(s, TCG_COND_GTU, arg1, arg3, label_index);
                    585:         break;
                    586:     case TCG_COND_GE:
                    587:     case TCG_COND_GEU:
                    588:         tcg_out_brcond(s, TCG_COND_GEU, arg1, arg3, label_index);
                    589:         break;
                    590:     default:
                    591:         tcg_abort();
                    592:     }
                    593: 
                    594:     reloc_pc16(label_ptr, (tcg_target_long) s->code_ptr);
                    595: }
                    596: 
                    597: #if defined(CONFIG_SOFTMMU)
                    598: 
                    599: #include "../../softmmu_defs.h"
                    600: 
                    601: static void *qemu_ld_helpers[4] = {
                    602:     __ldb_mmu,
                    603:     __ldw_mmu,
                    604:     __ldl_mmu,
                    605:     __ldq_mmu,
                    606: };
                    607: 
                    608: static void *qemu_st_helpers[4] = {
                    609:     __stb_mmu,
                    610:     __stw_mmu,
                    611:     __stl_mmu,
                    612:     __stq_mmu,
                    613: };
                    614: #endif
                    615: 
                    616: static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
                    617:                             int opc)
                    618: {
                    619:     int addr_regl, addr_reg1, addr_meml;
                    620:     int data_regl, data_regh, data_reg1, data_reg2;
                    621:     int mem_index, s_bits;
                    622: #if defined(CONFIG_SOFTMMU)
                    623:     void *label1_ptr, *label2_ptr;
                    624:     int sp_args;
                    625: #endif
                    626: #if TARGET_LONG_BITS == 64
                    627: # if defined(CONFIG_SOFTMMU)
                    628:     uint8_t *label3_ptr;
                    629: # endif
                    630:     int addr_regh, addr_reg2, addr_memh;
                    631: #endif
                    632:     data_regl = *args++;
                    633:     if (opc == 3)
                    634:         data_regh = *args++;
                    635:     else
                    636:         data_regh = 0;
                    637:     addr_regl = *args++;
                    638: #if TARGET_LONG_BITS == 64
                    639:     addr_regh = *args++;
                    640: #endif
                    641:     mem_index = *args;
                    642:     s_bits = opc & 3;
                    643: 
                    644:     if (opc == 3) {
                    645: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    646:         data_reg1 = data_regh;
                    647:         data_reg2 = data_regl;
                    648: #else
                    649:         data_reg1 = data_regl;
                    650:         data_reg2 = data_regh;
                    651: #endif
                    652:     } else {
                    653:         data_reg1 = data_regl;
                    654:         data_reg2 = 0;
                    655:     }
                    656: #if TARGET_LONG_BITS == 64
                    657: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    658:     addr_reg1 = addr_regh;
                    659:     addr_reg2 = addr_regl;
                    660:     addr_memh = 0;
                    661:     addr_meml = 4;
                    662: # else
                    663:     addr_reg1 = addr_regl;
                    664:     addr_reg2 = addr_regh;
                    665:     addr_memh = 4;
                    666:     addr_meml = 0;
                    667: # endif
                    668: #else
                    669:     addr_reg1 = addr_regl;
                    670:     addr_meml = 0;
                    671: #endif
                    672: 
                    673: #if defined(CONFIG_SOFTMMU)
                    674:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
                    675:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    676:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
                    677:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    678:                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_meml);
                    679:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    680:     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
                    681: 
                    682: # if TARGET_LONG_BITS == 64
                    683:     label3_ptr = s->code_ptr;
1.1.1.3 ! root      684:     tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1       root      685:     tcg_out_nop(s);
                    686: 
                    687:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    688:                     offsetof(CPUState, tlb_table[mem_index][0].addr_read) + addr_memh);
                    689: 
                    690:     label1_ptr = s->code_ptr;
1.1.1.3 ! root      691:     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1       root      692:     tcg_out_nop(s);
                    693: 
                    694:     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
                    695: # else
                    696:     label1_ptr = s->code_ptr;
1.1.1.3 ! root      697:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1       root      698:     tcg_out_nop(s);
                    699: # endif
                    700: 
                    701:     /* slow path */
                    702:     sp_args = TCG_REG_A0;
                    703:     tcg_out_mov(s, sp_args++, addr_reg1);
                    704: # if TARGET_LONG_BITS == 64
                    705:     tcg_out_mov(s, sp_args++, addr_reg2);
                    706: # endif
                    707:     tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
                    708:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
                    709:     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
                    710:     tcg_out_nop(s);
                    711: 
                    712:     switch(opc) {
                    713:     case 0:
                    714:         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xff);
                    715:         break;
                    716:     case 0 | 4:
                    717:         tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 24);
                    718:         tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 24);
                    719:         break;
                    720:     case 1:
                    721:         tcg_out_opc_imm(s, OPC_ANDI, data_reg1, TCG_REG_V0, 0xffff);
                    722:         break;
                    723:     case 1 | 4:
                    724:         tcg_out_opc_sa(s, OPC_SLL, TCG_REG_V0, TCG_REG_V0, 16);
                    725:         tcg_out_opc_sa(s, OPC_SRA, data_reg1, TCG_REG_V0, 16);
                    726:         break;
                    727:     case 2:
                    728:         tcg_out_mov(s, data_reg1, TCG_REG_V0);
                    729:         break;
                    730:     case 3:
                    731:         tcg_out_mov(s, data_reg2, TCG_REG_V1);
                    732:         tcg_out_mov(s, data_reg1, TCG_REG_V0);
                    733:         break;
                    734:     default:
                    735:         tcg_abort();
                    736:     }
                    737: 
                    738:     label2_ptr = s->code_ptr;
1.1.1.3 ! root      739:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1       root      740:     tcg_out_nop(s);
                    741: 
                    742:     /* label1: fast path */
                    743:     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
                    744: 
1.1.1.2   root      745:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
1.1       root      746:                     offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
1.1.1.2   root      747:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_V0, TCG_REG_A0, addr_regl);
1.1       root      748: 
                    749:     addr_reg1 = TCG_REG_V0;
                    750: #endif
                    751: 
                    752:     switch(opc) {
                    753:     case 0:
                    754:         tcg_out_opc_imm(s, OPC_LBU, data_reg1, addr_reg1, 0);
                    755:         break;
                    756:     case 0 | 4:
                    757:         tcg_out_opc_imm(s, OPC_LB, data_reg1, addr_reg1, 0);
                    758:         break;
                    759:     case 1:
                    760:         if (TCG_NEED_BSWAP) {
                    761:             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
                    762:             tcg_out_bswap16(s, data_reg1, TCG_REG_T0);
                    763:         } else {
                    764:             tcg_out_opc_imm(s, OPC_LHU, data_reg1, addr_reg1, 0);
                    765:         }
                    766:         break;
                    767:     case 1 | 4:
                    768:         if (TCG_NEED_BSWAP) {
                    769:             tcg_out_opc_imm(s, OPC_LHU, TCG_REG_T0, addr_reg1, 0);
                    770:             tcg_out_bswap16s(s, data_reg1, TCG_REG_T0);
                    771:         } else {
                    772:             tcg_out_opc_imm(s, OPC_LH, data_reg1, addr_reg1, 0);
                    773:         }
                    774:         break;
                    775:     case 2:
                    776:         if (TCG_NEED_BSWAP) {
                    777:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
                    778:             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
                    779:         } else {
                    780:             tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
                    781:         }
                    782:         break;
                    783:     case 3:
                    784: #if !defined(CONFIG_SOFTMMU)
                    785:         tcg_out_mov(s, TCG_REG_V0, addr_reg1);
                    786:         addr_reg1 = TCG_REG_V0;
                    787: #endif
                    788:         if (TCG_NEED_BSWAP) {
                    789:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 4);
                    790:             tcg_out_bswap32(s, data_reg1, TCG_REG_T0);
                    791:             tcg_out_opc_imm(s, OPC_LW, TCG_REG_T0, addr_reg1, 0);
                    792:             tcg_out_bswap32(s, data_reg2, TCG_REG_T0);
                    793:         } else {
                    794:             tcg_out_opc_imm(s, OPC_LW, data_reg1, addr_reg1, 0);
                    795:             tcg_out_opc_imm(s, OPC_LW, data_reg2, addr_reg1, 4);
                    796:         }
                    797:         break;
                    798:     default:
                    799:         tcg_abort();
                    800:     }
                    801: 
                    802: #if defined(CONFIG_SOFTMMU)
                    803:     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
                    804: #endif
                    805: }
                    806: 
                    807: static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
                    808:                             int opc)
                    809: {
                    810:     int addr_regl, addr_reg1, addr_meml;
                    811:     int data_regl, data_regh, data_reg1, data_reg2;
                    812:     int mem_index, s_bits;
                    813: #if defined(CONFIG_SOFTMMU)
                    814:     uint8_t *label1_ptr, *label2_ptr;
                    815:     int sp_args;
                    816: #endif
                    817: #if TARGET_LONG_BITS == 64
                    818: # if defined(CONFIG_SOFTMMU)
                    819:     uint8_t *label3_ptr;
                    820: # endif
                    821:     int addr_regh, addr_reg2, addr_memh;
                    822: #endif
                    823: 
                    824:     data_regl = *args++;
                    825:     if (opc == 3) {
                    826:         data_regh = *args++;
                    827: #if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    828:         data_reg1 = data_regh;
                    829:         data_reg2 = data_regl;
                    830: #else
                    831:         data_reg1 = data_regl;
                    832:         data_reg2 = data_regh;
                    833: #endif
                    834:     } else {
                    835:         data_reg1 = data_regl;
                    836:         data_reg2 = 0;
                    837:         data_regh = 0;
                    838:     }
                    839:     addr_regl = *args++;
                    840: #if TARGET_LONG_BITS == 64
                    841:     addr_regh = *args++;
                    842: # if defined(TCG_TARGET_WORDS_BIGENDIAN)
                    843:     addr_reg1 = addr_regh;
                    844:     addr_reg2 = addr_regl;
                    845:     addr_memh = 0;
                    846:     addr_meml = 4;
                    847: # else
                    848:     addr_reg1 = addr_regl;
                    849:     addr_reg2 = addr_regh;
                    850:     addr_memh = 4;
                    851:     addr_meml = 0;
                    852: # endif
                    853: #else
                    854:     addr_reg1 = addr_regl;
                    855:     addr_meml = 0;
                    856: #endif
                    857:     mem_index = *args;
                    858:     s_bits = opc;
                    859: 
                    860: #if defined(CONFIG_SOFTMMU)
                    861:     tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addr_regl, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
                    862:     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
                    863:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
                    864:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    865:                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_meml);
                    866:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
                    867:     tcg_out_opc_reg(s, OPC_AND, TCG_REG_T0, TCG_REG_T0, addr_regl);
                    868: 
                    869: # if TARGET_LONG_BITS == 64
                    870:     label3_ptr = s->code_ptr;
1.1.1.3 ! root      871:     tcg_out_opc_br(s, OPC_BNE, TCG_REG_T0, TCG_REG_AT);
1.1       root      872:     tcg_out_nop(s);
                    873: 
                    874:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_AT, TCG_REG_A0,
                    875:                     offsetof(CPUState, tlb_table[mem_index][0].addr_write) + addr_memh);
                    876: 
                    877:     label1_ptr = s->code_ptr;
1.1.1.3 ! root      878:     tcg_out_opc_br(s, OPC_BEQ, addr_regh, TCG_REG_AT);
1.1       root      879:     tcg_out_nop(s);
                    880: 
                    881:     reloc_pc16(label3_ptr, (tcg_target_long) s->code_ptr);
                    882: # else
                    883:     label1_ptr = s->code_ptr;
1.1.1.3 ! root      884:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_T0, TCG_REG_AT);
1.1       root      885:     tcg_out_nop(s);
                    886: # endif
                    887: 
                    888:     /* slow path */
                    889:     sp_args = TCG_REG_A0;
                    890:     tcg_out_mov(s, sp_args++, addr_reg1);
                    891: # if TARGET_LONG_BITS == 64
                    892:     tcg_out_mov(s, sp_args++, addr_reg2);
                    893: # endif
                    894:     switch(opc) {
                    895:     case 0:
                    896:         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xff);
                    897:         break;
                    898:     case 1:
                    899:         tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
                    900:         break;
                    901:     case 2:
                    902:         tcg_out_mov(s, sp_args++, data_reg1);
                    903:         break;
                    904:     case 3:
                    905:         sp_args = (sp_args + 1) & ~1;
                    906:         tcg_out_mov(s, sp_args++, data_reg1);
                    907:         tcg_out_mov(s, sp_args++, data_reg2);
                    908:         break;
                    909:     default:
                    910:         tcg_abort();
                    911:     }
                    912:     if (sp_args > TCG_REG_A3) {
                    913:         /* Push mem_index on the stack */
                    914:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, mem_index);
                    915:         tcg_out_st(s, TCG_TYPE_I32, TCG_REG_AT, TCG_REG_SP, 16);
                    916:     } else {
                    917:         tcg_out_movi(s, TCG_TYPE_I32, sp_args, mem_index);
                    918:     }
                    919: 
                    920:     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_st_helpers[s_bits]);
                    921:     tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
                    922:     tcg_out_nop(s);
                    923: 
                    924:     label2_ptr = s->code_ptr;
1.1.1.3 ! root      925:     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1.1       root      926:     tcg_out_nop(s);
                    927: 
                    928:     /* label1: fast path */
                    929:     reloc_pc16(label1_ptr, (tcg_target_long) s->code_ptr);
                    930: 
                    931:     tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0,
                    932:                     offsetof(CPUState, tlb_table[mem_index][0].addend) + addr_meml);
                    933:     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, addr_regl);
                    934: 
                    935:     addr_reg1 = TCG_REG_A0;
                    936: #endif
                    937: 
                    938:     switch(opc) {
                    939:     case 0:
                    940:         tcg_out_opc_imm(s, OPC_SB, data_reg1, addr_reg1, 0);
                    941:         break;
                    942:     case 1:
                    943:         if (TCG_NEED_BSWAP) {
                    944:             tcg_out_bswap16(s, TCG_REG_T0, data_reg1);
                    945:             tcg_out_opc_imm(s, OPC_SH, TCG_REG_T0, addr_reg1, 0);
                    946:         } else {
                    947:             tcg_out_opc_imm(s, OPC_SH, data_reg1, addr_reg1, 0);
                    948:         }
                    949:         break;
                    950:     case 2:
                    951:         if (TCG_NEED_BSWAP) {
                    952:             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
                    953:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
                    954:         } else {
                    955:             tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
                    956:         }
                    957:         break;
                    958:     case 3:
                    959:         if (TCG_NEED_BSWAP) {
                    960:             tcg_out_bswap32(s, TCG_REG_T0, data_reg2);
                    961:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 0);
                    962:             tcg_out_bswap32(s, TCG_REG_T0, data_reg1);
                    963:             tcg_out_opc_imm(s, OPC_SW, TCG_REG_T0, addr_reg1, 4);
                    964:         } else {
                    965:             tcg_out_opc_imm(s, OPC_SW, data_reg1, addr_reg1, 0);
                    966:             tcg_out_opc_imm(s, OPC_SW, data_reg2, addr_reg1, 4);
                    967:         }
                    968:         break;
                    969:     default:
                    970:         tcg_abort();
                    971:     }
                    972: 
                    973: #if defined(CONFIG_SOFTMMU)
                    974:     reloc_pc16(label2_ptr, (tcg_target_long) s->code_ptr);
                    975: #endif
                    976: }
                    977: 
                    978: static inline void tcg_out_op(TCGContext *s, int opc,
                    979:                               const TCGArg *args, const int *const_args)
                    980: {
                    981:     switch(opc) {
                    982:     case INDEX_op_exit_tb:
                    983:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_V0, args[0]);
                    984:         tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, (tcg_target_long)tb_ret_addr);
                    985:         tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
                    986:         tcg_out_nop(s);
                    987:         break;
                    988:     case INDEX_op_goto_tb:
                    989:         if (s->tb_jmp_offset) {
                    990:             /* direct jump method */
                    991:             tcg_abort();
                    992:         } else {
                    993:             /* indirect jump method */
                    994:             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_AT, (tcg_target_long)(s->tb_next + args[0]));
                    995:             tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_AT, TCG_REG_AT, 0);
                    996:             tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_AT, 0);
                    997:         }
                    998:         tcg_out_nop(s);
                    999:         s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
                   1000:         break;
                   1001:     case INDEX_op_call:
                   1002:         tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, args[0], 0);
                   1003:         tcg_out_nop(s);
                   1004:         break;
                   1005:     case INDEX_op_jmp:
                   1006:         tcg_out_opc_reg(s, OPC_JR, 0, args[0], 0);
                   1007:         tcg_out_nop(s);
                   1008:         break;
                   1009:     case INDEX_op_br:
                   1010:         tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, args[0]);
                   1011:         break;
                   1012: 
                   1013:     case INDEX_op_mov_i32:
                   1014:         tcg_out_mov(s, args[0], args[1]);
                   1015:         break;
                   1016:     case INDEX_op_movi_i32:
                   1017:         tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
                   1018:         break;
                   1019: 
                   1020:     case INDEX_op_ld8u_i32:
                   1021:        tcg_out_ldst(s, OPC_LBU, args[0], args[1], args[2]);
                   1022:         break;
                   1023:     case INDEX_op_ld8s_i32:
                   1024:         tcg_out_ldst(s, OPC_LB, args[0], args[1], args[2]);
                   1025:         break;
                   1026:     case INDEX_op_ld16u_i32:
                   1027:         tcg_out_ldst(s, OPC_LHU, args[0], args[1], args[2]);
                   1028:         break;
                   1029:     case INDEX_op_ld16s_i32:
                   1030:         tcg_out_ldst(s, OPC_LH, args[0], args[1], args[2]);
                   1031:         break;
                   1032:     case INDEX_op_ld_i32:
                   1033:         tcg_out_ldst(s, OPC_LW, args[0], args[1], args[2]);
                   1034:         break;
                   1035:     case INDEX_op_st8_i32:
                   1036:         tcg_out_ldst(s, OPC_SB, args[0], args[1], args[2]);
                   1037:         break;
                   1038:     case INDEX_op_st16_i32:
                   1039:         tcg_out_ldst(s, OPC_SH, args[0], args[1], args[2]);
                   1040:         break;
                   1041:     case INDEX_op_st_i32:
                   1042:         tcg_out_ldst(s, OPC_SW, args[0], args[1], args[2]);
                   1043:         break;
                   1044: 
                   1045:     case INDEX_op_add_i32:
                   1046:         if (const_args[2]) {
                   1047:             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], args[2]);
                   1048:         } else {
                   1049:             tcg_out_opc_reg(s, OPC_ADDU, args[0], args[1], args[2]);
                   1050:         }
                   1051:         break;
                   1052:     case INDEX_op_add2_i32:
                   1053:         if (const_args[4]) {
                   1054:             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], args[4]);
                   1055:         } else {
                   1056:             tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_AT, args[2], args[4]);
                   1057:         }
                   1058:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, TCG_REG_AT, args[2]);
                   1059:         if (const_args[5]) {
                   1060:             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], args[5]);
                   1061:         } else {
                   1062:              tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
                   1063:         }
                   1064:         tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
                   1065:         tcg_out_mov(s, args[0], TCG_REG_AT);
                   1066:         break;
                   1067:     case INDEX_op_sub_i32:
                   1068:         if (const_args[2]) {
                   1069:             tcg_out_opc_imm(s, OPC_ADDIU, args[0], args[1], -args[2]);
                   1070:         } else {
                   1071:             tcg_out_opc_reg(s, OPC_SUBU, args[0], args[1], args[2]);
                   1072:         }
                   1073:         break;
                   1074:     case INDEX_op_sub2_i32:
                   1075:         if (const_args[4]) {
                   1076:             tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_AT, args[2], -args[4]);
                   1077:         } else {
                   1078:             tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, args[2], args[4]);
                   1079:         }
                   1080:         tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_T0, args[2], TCG_REG_AT);
                   1081:         if (const_args[5]) {
                   1082:             tcg_out_opc_imm(s, OPC_ADDIU, args[1], args[3], -args[5]);
                   1083:         } else {
                   1084:              tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
                   1085:         }
                   1086:         tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
                   1087:         tcg_out_mov(s, args[0], TCG_REG_AT);
                   1088:         break;
                   1089:     case INDEX_op_mul_i32:
                   1090:         tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
                   1091:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1092:         break;
                   1093:     case INDEX_op_mulu2_i32:
                   1094:         tcg_out_opc_reg(s, OPC_MULTU, 0, args[2], args[3]);
                   1095:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1096:         tcg_out_opc_reg(s, OPC_MFHI, args[1], 0, 0);
                   1097:         break;
                   1098:     case INDEX_op_div_i32:
                   1099:         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
                   1100:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1101:         break;
                   1102:     case INDEX_op_divu_i32:
                   1103:         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
                   1104:         tcg_out_opc_reg(s, OPC_MFLO, args[0], 0, 0);
                   1105:         break;
                   1106:     case INDEX_op_rem_i32:
                   1107:         tcg_out_opc_reg(s, OPC_DIV, 0, args[1], args[2]);
                   1108:         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
                   1109:         break;
                   1110:     case INDEX_op_remu_i32:
                   1111:         tcg_out_opc_reg(s, OPC_DIVU, 0, args[1], args[2]);
                   1112:         tcg_out_opc_reg(s, OPC_MFHI, args[0], 0, 0);
                   1113:         break;
                   1114: 
                   1115:     case INDEX_op_and_i32:
                   1116:         if (const_args[2]) {
                   1117:             tcg_out_opc_imm(s, OPC_ANDI, args[0], args[1], args[2]);
                   1118:         } else {
                   1119:             tcg_out_opc_reg(s, OPC_AND, args[0], args[1], args[2]);
                   1120:         }
                   1121:         break;
                   1122:     case INDEX_op_or_i32:
                   1123:         if (const_args[2]) {
                   1124:             tcg_out_opc_imm(s, OPC_ORI, args[0], args[1], args[2]);
                   1125:         } else {
                   1126:             tcg_out_opc_reg(s, OPC_OR, args[0], args[1], args[2]);
                   1127:         }
                   1128:         break;
                   1129:     case INDEX_op_not_i32:
                   1130:         tcg_out_opc_reg(s, OPC_NOR, args[0], args[1], args[1]);
                   1131:         break;
                   1132:     case INDEX_op_xor_i32:
                   1133:         if (const_args[2]) {
                   1134:             tcg_out_opc_imm(s, OPC_XORI, args[0], args[1], args[2]);
                   1135:         } else {
                   1136:             tcg_out_opc_reg(s, OPC_XOR, args[0], args[1], args[2]);
                   1137:         }
                   1138:         break;
                   1139: 
                   1140:     case INDEX_op_sar_i32:
                   1141:         if (const_args[2]) {
                   1142:             tcg_out_opc_sa(s, OPC_SRA, args[0], args[1], args[2]);
                   1143:         } else {
                   1144:             tcg_out_opc_reg(s, OPC_SRAV, args[0], args[2], args[1]);
                   1145:         }
                   1146:         break;
                   1147:     case INDEX_op_shl_i32:
                   1148:         if (const_args[2]) {
                   1149:             tcg_out_opc_sa(s, OPC_SLL, args[0], args[1], args[2]);
                   1150:         } else {
                   1151:             tcg_out_opc_reg(s, OPC_SLLV, args[0], args[2], args[1]);
                   1152:         }
                   1153:         break;
                   1154:     case INDEX_op_shr_i32:
                   1155:         if (const_args[2]) {
                   1156:             tcg_out_opc_sa(s, OPC_SRL, args[0], args[1], args[2]);
                   1157:         } else {
                   1158:             tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
                   1159:         }
                   1160:         break;
                   1161: 
                   1162:     case INDEX_op_brcond_i32:
                   1163:         tcg_out_brcond(s, args[2], args[0], args[1], args[3]);
                   1164:         break;
                   1165:     case INDEX_op_brcond2_i32:
                   1166:         tcg_out_brcond2(s, args[4], args[0], args[1], args[2], args[3], args[5]);
                   1167:         break;
                   1168: 
                   1169:     case INDEX_op_qemu_ld8u:
                   1170:         tcg_out_qemu_ld(s, args, 0);
                   1171:         break;
                   1172:     case INDEX_op_qemu_ld8s:
                   1173:         tcg_out_qemu_ld(s, args, 0 | 4);
                   1174:         break;
                   1175:     case INDEX_op_qemu_ld16u:
                   1176:         tcg_out_qemu_ld(s, args, 1);
                   1177:         break;
                   1178:     case INDEX_op_qemu_ld16s:
                   1179:         tcg_out_qemu_ld(s, args, 1 | 4);
                   1180:         break;
                   1181:     case INDEX_op_qemu_ld32u:
                   1182:         tcg_out_qemu_ld(s, args, 2);
                   1183:         break;
                   1184:     case INDEX_op_qemu_ld64:
                   1185:         tcg_out_qemu_ld(s, args, 3);
                   1186:         break;
                   1187:     case INDEX_op_qemu_st8:
                   1188:         tcg_out_qemu_st(s, args, 0);
                   1189:         break;
                   1190:     case INDEX_op_qemu_st16:
                   1191:         tcg_out_qemu_st(s, args, 1);
                   1192:         break;
                   1193:     case INDEX_op_qemu_st32:
                   1194:         tcg_out_qemu_st(s, args, 2);
                   1195:         break;
                   1196:     case INDEX_op_qemu_st64:
                   1197:         tcg_out_qemu_st(s, args, 3);
                   1198:         break;
                   1199: 
                   1200:     default:
                   1201:         tcg_abort();
                   1202:     }
                   1203: }
                   1204: 
                   1205: static const TCGTargetOpDef mips_op_defs[] = {
                   1206:     { INDEX_op_exit_tb, { } },
                   1207:     { INDEX_op_goto_tb, { } },
                   1208:     { INDEX_op_call, { "C" } },
                   1209:     { INDEX_op_jmp, { "r" } },
                   1210:     { INDEX_op_br, { } },
                   1211: 
                   1212:     { INDEX_op_mov_i32, { "r", "r" } },
                   1213:     { INDEX_op_movi_i32, { "r" } },
                   1214:     { INDEX_op_ld8u_i32, { "r", "r" } },
                   1215:     { INDEX_op_ld8s_i32, { "r", "r" } },
                   1216:     { INDEX_op_ld16u_i32, { "r", "r" } },
                   1217:     { INDEX_op_ld16s_i32, { "r", "r" } },
                   1218:     { INDEX_op_ld_i32, { "r", "r" } },
                   1219:     { INDEX_op_st8_i32, { "rZ", "r" } },
                   1220:     { INDEX_op_st16_i32, { "rZ", "r" } },
                   1221:     { INDEX_op_st_i32, { "rZ", "r" } },
                   1222: 
                   1223:     { INDEX_op_add_i32, { "r", "rZ", "rJZ" } },
                   1224:     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
                   1225:     { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
                   1226:     { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
                   1227:     { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
                   1228:     { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
                   1229:     { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
                   1230:     { INDEX_op_sub_i32, { "r", "rZ", "rJZ" } },
                   1231: 
                   1232:     { INDEX_op_and_i32, { "r", "rZ", "rIZ" } },
                   1233:     { INDEX_op_not_i32, { "r", "rZ" } },
                   1234:     { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
                   1235:     { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
                   1236: 
                   1237:     { INDEX_op_shl_i32, { "r", "rZ", "riZ" } },
                   1238:     { INDEX_op_shr_i32, { "r", "rZ", "riZ" } },
                   1239:     { INDEX_op_sar_i32, { "r", "rZ", "riZ" } },
                   1240: 
                   1241:     { INDEX_op_brcond_i32, { "rZ", "rZ" } },
                   1242: 
                   1243:     { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
                   1244:     { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rJZ", "rJZ" } },
                   1245:     { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
                   1246: 
                   1247: #if TARGET_LONG_BITS == 32
                   1248:     { INDEX_op_qemu_ld8u, { "L", "lZ" } },
                   1249:     { INDEX_op_qemu_ld8s, { "L", "lZ" } },
                   1250:     { INDEX_op_qemu_ld16u, { "L", "lZ" } },
                   1251:     { INDEX_op_qemu_ld16s, { "L", "lZ" } },
                   1252:     { INDEX_op_qemu_ld32u, { "L", "lZ" } },
                   1253:     { INDEX_op_qemu_ld64, { "L", "L", "lZ" } },
                   1254: 
                   1255:     { INDEX_op_qemu_st8, { "SZ", "SZ" } },
                   1256:     { INDEX_op_qemu_st16, { "SZ", "SZ" } },
                   1257:     { INDEX_op_qemu_st32, { "SZ", "SZ" } },
                   1258:     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ" } },
                   1259: #else
                   1260:     { INDEX_op_qemu_ld8u, { "L", "lZ", "lZ" } },
                   1261:     { INDEX_op_qemu_ld8s, { "L", "lZ", "lZ" } },
                   1262:     { INDEX_op_qemu_ld16u, { "L", "lZ", "lZ" } },
                   1263:     { INDEX_op_qemu_ld16s, { "L", "lZ", "lZ" } },
                   1264:     { INDEX_op_qemu_ld32u, { "L", "lZ", "lZ" } },
                   1265:     { INDEX_op_qemu_ld64, { "L", "L", "lZ", "lZ" } },
                   1266: 
                   1267:     { INDEX_op_qemu_st8, { "SZ", "SZ", "SZ" } },
                   1268:     { INDEX_op_qemu_st16, { "SZ", "SZ", "SZ" } },
                   1269:     { INDEX_op_qemu_st32, { "SZ", "SZ", "SZ" } },
                   1270:     { INDEX_op_qemu_st64, { "SZ", "SZ", "SZ", "SZ" } },
                   1271: #endif
                   1272:     { -1 },
                   1273: };
                   1274: 
                   1275: static int tcg_target_callee_save_regs[] = {
1.1.1.3 ! root     1276: #if 0 /* used for the global env (TCG_AREG0), so no need to save */
1.1       root     1277:     TCG_REG_S0,
1.1.1.3 ! root     1278: #endif
1.1       root     1279:     TCG_REG_S1,
                   1280:     TCG_REG_S2,
                   1281:     TCG_REG_S3,
                   1282:     TCG_REG_S4,
                   1283:     TCG_REG_S5,
                   1284:     TCG_REG_S6,
                   1285:     TCG_REG_S7,
                   1286:     TCG_REG_GP,
1.1.1.3 ! root     1287:     TCG_REG_FP,
1.1       root     1288:     TCG_REG_RA,       /* should be last for ABI compliance */
                   1289: };
                   1290: 
                   1291: /* Generate global QEMU prologue and epilogue code */
                   1292: void tcg_target_qemu_prologue(TCGContext *s)
                   1293: {
                   1294:     int i, frame_size;
                   1295: 
                   1296:     /* reserve some stack space */
                   1297:     frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
                   1298:                  + TCG_STATIC_CALL_ARGS_SIZE;
                   1299:     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
                   1300:                  ~(TCG_TARGET_STACK_ALIGN - 1);
                   1301: 
                   1302:     /* TB prologue */
                   1303:     tcg_out_addi(s, TCG_REG_SP, -frame_size);
                   1304:     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
                   1305:         tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
                   1306:                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
                   1307:     }
                   1308: 
                   1309:     /* Call generated code */
                   1310:     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_A0, 0);
                   1311:     tcg_out_nop(s);
                   1312:     tb_ret_addr = s->code_ptr;
                   1313: 
                   1314:     /* TB epilogue */
                   1315:     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
                   1316:         tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
                   1317:                    TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
                   1318:     }
                   1319: 
                   1320:     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
                   1321:     tcg_out_addi(s, TCG_REG_SP, frame_size);
                   1322: }
                   1323: 
                   1324: void tcg_target_init(TCGContext *s)
                   1325: {
                   1326:     tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
                   1327:     tcg_regset_set(tcg_target_call_clobber_regs,
                   1328:                    (1 << TCG_REG_V0) |
                   1329:                    (1 << TCG_REG_V1) |
                   1330:                    (1 << TCG_REG_A0) |
                   1331:                    (1 << TCG_REG_A1) |
                   1332:                    (1 << TCG_REG_A2) |
                   1333:                    (1 << TCG_REG_A3) |
                   1334:                    (1 << TCG_REG_T1) |
                   1335:                    (1 << TCG_REG_T2) |
                   1336:                    (1 << TCG_REG_T3) |
                   1337:                    (1 << TCG_REG_T4) |
                   1338:                    (1 << TCG_REG_T5) |
                   1339:                    (1 << TCG_REG_T6) |
                   1340:                    (1 << TCG_REG_T7) |
                   1341:                    (1 << TCG_REG_T8) |
                   1342:                    (1 << TCG_REG_T9));
                   1343: 
                   1344:     tcg_regset_clear(s->reserved_regs);
                   1345:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
                   1346:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
                   1347:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
                   1348:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_AT);   /* internal use */
                   1349:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_T0);   /* internal use */
                   1350:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
                   1351:     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
                   1352: 
                   1353:     tcg_add_target_add_op_defs(mips_op_defs);
                   1354: }

unix.superglobalmegacorp.com

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