Annotation of qemu/tcg/mips/tcg-target.c, revision 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.