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

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

unix.superglobalmegacorp.com

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