tcg-target.inc.c 83.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*
 * Tiny Code Generator for QEMU
 *
 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

27 28
#ifdef HOST_WORDS_BIGENDIAN
# define MIPS_BE  1
29
#else
30
# define MIPS_BE  0
31 32
#endif

33 34 35 36 37 38
#if TCG_TARGET_REG_BITS == 32
# define LO_OFF  (MIPS_BE * 4)
# define HI_OFF  (4 - LO_OFF)
#else
/* To assert at compile-time that these values are never used
   for TCG_TARGET_REG_BITS == 64.  */
39
int link_error(void);
40 41 42
# define LO_OFF  link_error()
# define HI_OFF  link_error()
#endif
43

44
#ifdef CONFIG_DEBUG_TCG
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
    "zero",
    "at",
    "v0",
    "v1",
    "a0",
    "a1",
    "a2",
    "a3",
    "t0",
    "t1",
    "t2",
    "t3",
    "t4",
    "t5",
    "t6",
    "t7",
    "s0",
    "s1",
    "s2",
    "s3",
    "s4",
    "s5",
    "s6",
    "s7",
    "t8",
    "t9",
    "k0",
    "k1",
    "gp",
    "sp",
76
    "s8",
77 78 79 80
    "ra",
};
#endif

81
#define TCG_TMP0  TCG_REG_AT
82
#define TCG_TMP1  TCG_REG_T9
83 84
#define TCG_TMP2  TCG_REG_T8
#define TCG_TMP3  TCG_REG_T7
85

86 87 88 89
#ifndef CONFIG_SOFTMMU
#define TCG_GUEST_BASE_REG TCG_REG_S1
#endif

90
/* check if we really need so many registers :P */
91
static const int tcg_target_reg_alloc_order[] = {
92
    /* Call saved registers.  */
93 94 95 96 97 98 99 100
    TCG_REG_S0,
    TCG_REG_S1,
    TCG_REG_S2,
    TCG_REG_S3,
    TCG_REG_S4,
    TCG_REG_S5,
    TCG_REG_S6,
    TCG_REG_S7,
101 102 103
    TCG_REG_S8,

    /* Call clobbered registers.  */
104 105 106 107 108 109
    TCG_REG_T4,
    TCG_REG_T5,
    TCG_REG_T6,
    TCG_REG_T7,
    TCG_REG_T8,
    TCG_REG_T9,
110
    TCG_REG_V1,
111
    TCG_REG_V0,
112 113

    /* Argument registers, opposite order of allocation.  */
114 115 116 117
    TCG_REG_T3,
    TCG_REG_T2,
    TCG_REG_T1,
    TCG_REG_T0,
118 119 120 121
    TCG_REG_A3,
    TCG_REG_A2,
    TCG_REG_A1,
    TCG_REG_A0,
122 123
};

124
static const TCGReg tcg_target_call_iarg_regs[] = {
125 126 127
    TCG_REG_A0,
    TCG_REG_A1,
    TCG_REG_A2,
128 129 130 131 132 133 134
    TCG_REG_A3,
#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
    TCG_REG_T0,
    TCG_REG_T1,
    TCG_REG_T2,
    TCG_REG_T3,
#endif
135 136
};

137
static const TCGReg tcg_target_call_oarg_regs[2] = {
138 139 140 141
    TCG_REG_V0,
    TCG_REG_V1
};

142
static tcg_insn_unit *tb_ret_addr;
143
static tcg_insn_unit *bswap32_addr;
144 145
static tcg_insn_unit *bswap32u_addr;
static tcg_insn_unit *bswap64_addr;
146

147
static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
148
{
149 150
    /* Let the compiler perform the right-shift as part of the arithmetic.  */
    ptrdiff_t disp = target - (pc + 1);
151
    tcg_debug_assert(disp == (int16_t)disp);
152
    return disp & 0xffff;
153 154
}

155
static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
156
{
157
    *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
158 159
}

160
static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
161
{
162
    tcg_debug_assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0);
163
    return ((uintptr_t)target >> 2) & 0x3ffffff;
164 165
}

166
static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
167
{
168
    *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
169 170
}

171
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
172
                        intptr_t value, intptr_t addend)
173
{
174 175
    tcg_debug_assert(type == R_MIPS_PC16);
    tcg_debug_assert(addend == 0);
176
    reloc_pc16(code_ptr, (tcg_insn_unit *)value);
177
    return true;
178 179
}

180
#define TCG_CT_CONST_ZERO 0x100
181 182 183 184
#define TCG_CT_CONST_U16  0x200    /* Unsigned 16-bit: 0 - 0xffff.  */
#define TCG_CT_CONST_S16  0x400    /* Signed 16-bit: -32768 - 32767 */
#define TCG_CT_CONST_P2M1 0x800    /* Power of 2 minus 1.  */
#define TCG_CT_CONST_N16  0x1000   /* "Negatable" 16-bit: -32767 - 32767 */
185
#define TCG_CT_CONST_WSZ  0x2000   /* word size */
186 187 188 189 190 191

static inline bool is_p2m1(tcg_target_long val)
{
    return val && ((val + 1) & val) == 0;
}

192
/* parse target specific constraints */
193 194
static const char *target_parse_constraint(TCGArgConstraint *ct,
                                           const char *ct_str, TCGType type)
195
{
196
    switch(*ct_str++) {
197 198
    case 'r':
        ct->ct |= TCG_CT_REG;
199
        ct->u.regs = 0xffffffff;
200
        break;
201
    case 'L': /* qemu_ld input arg constraint */
202
        ct->ct |= TCG_CT_REG;
203
        ct->u.regs = 0xffffffff;
204
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
205
#if defined(CONFIG_SOFTMMU)
206
        if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
207 208
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
        }
209 210 211 212
#endif
        break;
    case 'S': /* qemu_st constraint */
        ct->ct |= TCG_CT_REG;
213
        ct->u.regs = 0xffffffff;
214
        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
215
#if defined(CONFIG_SOFTMMU)
216
        if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
217 218
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
219 220
        } else {
            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
221
        }
222 223 224 225 226 227 228 229
#endif
        break;
    case 'I':
        ct->ct |= TCG_CT_CONST_U16;
        break;
    case 'J':
        ct->ct |= TCG_CT_CONST_S16;
        break;
230 231 232
    case 'K':
        ct->ct |= TCG_CT_CONST_P2M1;
        break;
233 234 235
    case 'N':
        ct->ct |= TCG_CT_CONST_N16;
        break;
236 237 238
    case 'W':
        ct->ct |= TCG_CT_CONST_WSZ;
        break;
239 240 241 242 243 244 245
    case 'Z':
        /* We are cheating a bit here, using the fact that the register
           ZERO is also the register number 0. Hence there is no need
           to check for const_args in each instruction. */
        ct->ct |= TCG_CT_CONST_ZERO;
        break;
    default:
246
        return NULL;
247
    }
248
    return ct_str;
249 250 251
}

/* test if a constant matches the constraint */
252
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
253 254 255 256
                                         const TCGArgConstraint *arg_ct)
{
    int ct;
    ct = arg_ct->ct;
257
    if (ct & TCG_CT_CONST) {
258
        return 1;
259
    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
260
        return 1;
261
    } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
262
        return 1;
263
    } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
264
        return 1;
265 266
    } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
        return 1;
267 268 269
    } else if ((ct & TCG_CT_CONST_P2M1)
               && use_mips32r2_instructions && is_p2m1(val)) {
        return 1;
270 271 272
    } else if ((ct & TCG_CT_CONST_WSZ)
               && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
        return 1;
273 274
    }
    return 0;
275 276 277
}

/* instruction opcodes */
278
typedef enum {
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
    OPC_J        = 002 << 26,
    OPC_JAL      = 003 << 26,
    OPC_BEQ      = 004 << 26,
    OPC_BNE      = 005 << 26,
    OPC_BLEZ     = 006 << 26,
    OPC_BGTZ     = 007 << 26,
    OPC_ADDIU    = 011 << 26,
    OPC_SLTI     = 012 << 26,
    OPC_SLTIU    = 013 << 26,
    OPC_ANDI     = 014 << 26,
    OPC_ORI      = 015 << 26,
    OPC_XORI     = 016 << 26,
    OPC_LUI      = 017 << 26,
    OPC_DADDIU   = 031 << 26,
    OPC_LB       = 040 << 26,
    OPC_LH       = 041 << 26,
    OPC_LW       = 043 << 26,
    OPC_LBU      = 044 << 26,
    OPC_LHU      = 045 << 26,
    OPC_LWU      = 047 << 26,
    OPC_SB       = 050 << 26,
    OPC_SH       = 051 << 26,
    OPC_SW       = 053 << 26,
    OPC_LD       = 067 << 26,
    OPC_SD       = 077 << 26,

    OPC_SPECIAL  = 000 << 26,
    OPC_SLL      = OPC_SPECIAL | 000,
    OPC_SRL      = OPC_SPECIAL | 002,
    OPC_ROTR     = OPC_SPECIAL | 002 | (1 << 21),
    OPC_SRA      = OPC_SPECIAL | 003,
    OPC_SLLV     = OPC_SPECIAL | 004,
    OPC_SRLV     = OPC_SPECIAL | 006,
    OPC_ROTRV    = OPC_SPECIAL | 006 | 0100,
    OPC_SRAV     = OPC_SPECIAL | 007,
    OPC_JR_R5    = OPC_SPECIAL | 010,
    OPC_JALR     = OPC_SPECIAL | 011,
    OPC_MOVZ     = OPC_SPECIAL | 012,
    OPC_MOVN     = OPC_SPECIAL | 013,
    OPC_SYNC     = OPC_SPECIAL | 017,
    OPC_MFHI     = OPC_SPECIAL | 020,
    OPC_MFLO     = OPC_SPECIAL | 022,
    OPC_DSLLV    = OPC_SPECIAL | 024,
    OPC_DSRLV    = OPC_SPECIAL | 026,
    OPC_DROTRV   = OPC_SPECIAL | 026 | 0100,
    OPC_DSRAV    = OPC_SPECIAL | 027,
    OPC_MULT     = OPC_SPECIAL | 030,
    OPC_MUL_R6   = OPC_SPECIAL | 030 | 0200,
    OPC_MUH      = OPC_SPECIAL | 030 | 0300,
    OPC_MULTU    = OPC_SPECIAL | 031,
    OPC_MULU     = OPC_SPECIAL | 031 | 0200,
    OPC_MUHU     = OPC_SPECIAL | 031 | 0300,
    OPC_DIV      = OPC_SPECIAL | 032,
    OPC_DIV_R6   = OPC_SPECIAL | 032 | 0200,
    OPC_MOD      = OPC_SPECIAL | 032 | 0300,
    OPC_DIVU     = OPC_SPECIAL | 033,
    OPC_DIVU_R6  = OPC_SPECIAL | 033 | 0200,
    OPC_MODU     = OPC_SPECIAL | 033 | 0300,
    OPC_DMULT    = OPC_SPECIAL | 034,
    OPC_DMUL     = OPC_SPECIAL | 034 | 0200,
    OPC_DMUH     = OPC_SPECIAL | 034 | 0300,
    OPC_DMULTU   = OPC_SPECIAL | 035,
    OPC_DMULU    = OPC_SPECIAL | 035 | 0200,
    OPC_DMUHU    = OPC_SPECIAL | 035 | 0300,
    OPC_DDIV     = OPC_SPECIAL | 036,
    OPC_DDIV_R6  = OPC_SPECIAL | 036 | 0200,
    OPC_DMOD     = OPC_SPECIAL | 036 | 0300,
    OPC_DDIVU    = OPC_SPECIAL | 037,
    OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
    OPC_DMODU    = OPC_SPECIAL | 037 | 0300,
    OPC_ADDU     = OPC_SPECIAL | 041,
    OPC_SUBU     = OPC_SPECIAL | 043,
    OPC_AND      = OPC_SPECIAL | 044,
    OPC_OR       = OPC_SPECIAL | 045,
    OPC_XOR      = OPC_SPECIAL | 046,
    OPC_NOR      = OPC_SPECIAL | 047,
    OPC_SLT      = OPC_SPECIAL | 052,
    OPC_SLTU     = OPC_SPECIAL | 053,
    OPC_DADDU    = OPC_SPECIAL | 055,
    OPC_DSUBU    = OPC_SPECIAL | 057,
    OPC_SELEQZ   = OPC_SPECIAL | 065,
    OPC_SELNEZ   = OPC_SPECIAL | 067,
    OPC_DSLL     = OPC_SPECIAL | 070,
    OPC_DSRL     = OPC_SPECIAL | 072,
    OPC_DROTR    = OPC_SPECIAL | 072 | (1 << 21),
    OPC_DSRA     = OPC_SPECIAL | 073,
    OPC_DSLL32   = OPC_SPECIAL | 074,
    OPC_DSRL32   = OPC_SPECIAL | 076,
    OPC_DROTR32  = OPC_SPECIAL | 076 | (1 << 21),
    OPC_DSRA32   = OPC_SPECIAL | 077,
369 370
    OPC_CLZ_R6   = OPC_SPECIAL | 0120,
    OPC_DCLZ_R6  = OPC_SPECIAL | 0122,
371 372 373 374 375 376 377

    OPC_REGIMM   = 001 << 26,
    OPC_BLTZ     = OPC_REGIMM | (000 << 16),
    OPC_BGEZ     = OPC_REGIMM | (001 << 16),

    OPC_SPECIAL2 = 034 << 26,
    OPC_MUL_R5   = OPC_SPECIAL2 | 002,
378 379
    OPC_CLZ      = OPC_SPECIAL2 | 040,
    OPC_DCLZ     = OPC_SPECIAL2 | 044,
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394

    OPC_SPECIAL3 = 037 << 26,
    OPC_EXT      = OPC_SPECIAL3 | 000,
    OPC_DEXTM    = OPC_SPECIAL3 | 001,
    OPC_DEXTU    = OPC_SPECIAL3 | 002,
    OPC_DEXT     = OPC_SPECIAL3 | 003,
    OPC_INS      = OPC_SPECIAL3 | 004,
    OPC_DINSM    = OPC_SPECIAL3 | 005,
    OPC_DINSU    = OPC_SPECIAL3 | 006,
    OPC_DINS     = OPC_SPECIAL3 | 007,
    OPC_WSBH     = OPC_SPECIAL3 | 00240,
    OPC_DSBH     = OPC_SPECIAL3 | 00244,
    OPC_DSHD     = OPC_SPECIAL3 | 00544,
    OPC_SEB      = OPC_SPECIAL3 | 02040,
    OPC_SEH      = OPC_SPECIAL3 | 03040,
395 396 397

    /* MIPS r6 doesn't have JR, JALR should be used instead */
    OPC_JR       = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
398 399 400 401 402 403

    /*
     * MIPS r6 replaces MUL with an alternative encoding which is
     * backwards-compatible at the assembly level.
     */
    OPC_MUL      = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
404 405 406 407 408 409 410 411

    /* MIPS r6 introduced names for weaker variants of SYNC.  These are
       backward compatible to previous architecture revisions.  */
    OPC_SYNC_WMB     = OPC_SYNC | 0x04 << 5,
    OPC_SYNC_MB      = OPC_SYNC | 0x10 << 5,
    OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 5,
    OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 5,
    OPC_SYNC_RMB     = OPC_SYNC | 0x13 << 5,
412 413 414 415 416 417

    /* Aliases for convenience.  */
    ALIAS_PADD     = sizeof(void *) == 4 ? OPC_ADDU : OPC_DADDU,
    ALIAS_PADDI    = sizeof(void *) == 4 ? OPC_ADDIU : OPC_DADDIU,
    ALIAS_TSRL     = TARGET_LONG_BITS == 32 || TCG_TARGET_REG_BITS == 32
                     ? OPC_SRL : OPC_DSRL,
418
} MIPSInsn;
419 420 421 422

/*
 * Type reg
 */
423
static inline void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
424
                                   TCGReg rd, TCGReg rs, TCGReg rt)
425 426 427 428 429 430 431 432 433 434 435 436 437
{
    int32_t inst;

    inst = opc;
    inst |= (rs & 0x1F) << 21;
    inst |= (rt & 0x1F) << 16;
    inst |= (rd & 0x1F) << 11;
    tcg_out32(s, inst);
}

/*
 * Type immediate
 */
438
static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
439
                                   TCGReg rt, TCGReg rs, TCGArg imm)
440 441 442 443 444 445 446 447 448 449
{
    int32_t inst;

    inst = opc;
    inst |= (rs & 0x1F) << 21;
    inst |= (rt & 0x1F) << 16;
    inst |= (imm & 0xffff);
    tcg_out32(s, inst);
}

450 451 452
/*
 * Type bitfield
 */
453
static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
454 455 456 457 458 459 460 461 462 463 464 465
                                  TCGReg rs, int msb, int lsb)
{
    int32_t inst;

    inst = opc;
    inst |= (rs & 0x1F) << 21;
    inst |= (rt & 0x1F) << 16;
    inst |= (msb & 0x1F) << 11;
    inst |= (lsb & 0x1F) << 6;
    tcg_out32(s, inst);
}

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
static inline void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
                                    MIPSInsn oph, TCGReg rt, TCGReg rs,
                                    int msb, int lsb)
{
    if (lsb >= 32) {
        opc = oph;
        msb -= 32;
        lsb -= 32;
    } else if (msb >= 32) {
        opc = opm;
        msb -= 32;
    }
    tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
}

481 482 483
/*
 * Type branch
 */
484
static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
485
                                  TCGReg rt, TCGReg rs)
486
{
487
    tcg_out_opc_imm(s, opc, rt, rs, 0);
488 489
}

490 491 492
/*
 * Type sa
 */
493
static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
494
                                  TCGReg rd, TCGReg rt, TCGArg sa)
495 496 497 498 499 500 501 502 503 504 505
{
    int32_t inst;

    inst = opc;
    inst |= (rt & 0x1F) << 16;
    inst |= (rd & 0x1F) << 11;
    inst |= (sa & 0x1F) <<  6;
    tcg_out32(s, inst);

}

506 507 508 509 510 511 512 513 514 515 516 517
static void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
                             TCGReg rd, TCGReg rt, TCGArg sa)
{
    int32_t inst;

    inst = (sa & 32 ? opc2 : opc1);
    inst |= (rt & 0x1F) << 16;
    inst |= (rd & 0x1F) << 11;
    inst |= (sa & 0x1F) <<  6;
    tcg_out32(s, inst);
}

518 519 520 521
/*
 * Type jump.
 * Returns true if the branch was in range and the insn was emitted.
 */
522
static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
523 524 525 526 527 528 529 530 531 532
{
    uintptr_t dest = (uintptr_t)target;
    uintptr_t from = (uintptr_t)s->code_ptr + 4;
    int32_t inst;

    /* The pc-region branch happens within the 256MB region of
       the delay slot (thus the +4).  */
    if ((from ^ dest) & -(1 << 28)) {
        return false;
    }
533
    tcg_debug_assert((dest & 3) == 0);
534 535 536 537 538 539 540

    inst = opc;
    inst |= (dest >> 2) & 0x3ffffff;
    tcg_out32(s, inst);
    return true;
}

541 542 543 544 545
static inline void tcg_out_nop(TCGContext *s)
{
    tcg_out32(s, 0);
}

546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
static inline void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
{
    tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
}

static inline void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
{
    tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
}

static inline void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
{
    tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
}

561 562
static inline void tcg_out_mov(TCGContext *s, TCGType type,
                               TCGReg ret, TCGReg arg)
563
{
564 565
    /* Simple reg-reg move, optimising out the 'do nothing' case */
    if (ret != arg) {
566
        tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
567
    }
568 569
}

570 571
static void tcg_out_movi(TCGContext *s, TCGType type,
                         TCGReg ret, tcg_target_long arg)
572
{
573 574 575
    if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
        arg = (int32_t)arg;
    }
576
    if (arg == (int16_t)arg) {
577 578 579 580 581 582 583 584 585
        tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
        return;
    }
    if (arg == (uint16_t)arg) {
        tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
        return;
    }
    if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
        tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
586
    } else {
587 588 589 590 591 592 593
        tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1);
        if (arg & 0xffff0000ull) {
            tcg_out_dsll(s, ret, ret, 16);
            tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16);
            tcg_out_dsll(s, ret, ret, 16);
        } else {
            tcg_out_dsll(s, ret, ret, 32);
594
        }
595
    }
596 597 598
    if (arg & 0xffff) {
        tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
    }
599 600
}

601
static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
602
{
603 604 605 606
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
    } else {
        /* ret and arg can't be register at */
607
        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
608 609
            tcg_abort();
        }
610

611
        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
612 613
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
        tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
614
        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
615
    }
616 617
}

618
static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
619
{
620 621 622 623 624
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
        tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
    } else {
        /* ret and arg can't be register at */
625
        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
626 627
            tcg_abort();
        }
628

629
        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
630 631
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
632
        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
633
    }
634 635
}

636 637 638 639 640 641 642
static void tcg_out_bswap_subr(TCGContext *s, tcg_insn_unit *sub)
{
    bool ok = tcg_out_opc_jmp(s, OPC_JAL, sub);
    tcg_debug_assert(ok);
}

static void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
643
{
644 645 646 647
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
        tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
    } else {
648 649 650 651
        tcg_out_bswap_subr(s, bswap32_addr);
        /* delay slot -- never omit the insn, like tcg_out_mov might.  */
        tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
        tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
652
    }
653 654
}

655 656 657 658 659 660 661
static void tcg_out_bswap32u(TCGContext *s, TCGReg ret, TCGReg arg)
{
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
        tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
        tcg_out_dsrl(s, ret, ret, 32);
    } else {
662 663 664 665
        tcg_out_bswap_subr(s, bswap32u_addr);
        /* delay slot -- never omit the insn, like tcg_out_mov might.  */
        tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
        tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
666 667 668 669 670 671 672 673 674
    }
}

static void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
{
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
        tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
    } else {
675 676 677 678
        tcg_out_bswap_subr(s, bswap64_addr);
        /* delay slot -- never omit the insn, like tcg_out_mov might.  */
        tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
        tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
679 680 681
    }
}

682
static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
683
{
684 685 686 687 688 689
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
    } else {
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
    }
690 691
}

692
static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
693
{
694 695 696 697 698 699
    if (use_mips32r2_instructions) {
        tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
    } else {
        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
    }
700 701
}

702 703 704 705 706 707 708 709 710 711
static inline void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
{
    if (use_mips32r2_instructions) {
        tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
    } else {
        tcg_out_dsll(s, ret, arg, 32);
        tcg_out_dsrl(s, ret, ret, 32);
    }
}

712
static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
713
                         TCGReg addr, intptr_t ofs)
714
{
715 716
    int16_t lo = ofs;
    if (ofs != lo) {
717
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
718
        if (addr != TCG_REG_ZERO) {
719
            tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
720
        }
721
        addr = TCG_TMP0;
722
    }
723
    tcg_out_opc_imm(s, opc, data, addr, lo);
724 725
}

726
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
727
                              TCGReg arg1, intptr_t arg2)
728
{
729 730 731 732 733
    MIPSInsn opc = OPC_LD;
    if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
        opc = OPC_LW;
    }
    tcg_out_ldst(s, opc, arg, arg1, arg2);
734 735
}

736
static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
737
                              TCGReg arg1, intptr_t arg2)
738
{
739 740 741 742 743
    MIPSInsn opc = OPC_SD;
    if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
        opc = OPC_SW;
    }
    tcg_out_ldst(s, opc, arg, arg1, arg2);
744 745
}

746 747 748 749 750 751 752 753 754 755
static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
                               TCGReg base, intptr_t ofs)
{
    if (val == 0) {
        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
        return true;
    }
    return false;
}

756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
                            TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
                            bool cbh, bool is_sub)
{
    TCGReg th = TCG_TMP1;

    /* If we have a negative constant such that negating it would
       make the high part zero, we can (usually) eliminate one insn.  */
    if (cbl && cbh && bh == -1 && bl != 0) {
        bl = -bl;
        bh = 0;
        is_sub = !is_sub;
    }

    /* By operating on the high part first, we get to use the final
       carry operation to move back from the temporary.  */
    if (!cbh) {
        tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
    } else if (bh != 0 || ah == rl) {
        tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
    } else {
        th = ah;
    }

    /* Note that tcg optimization should eliminate the bl == 0 case.  */
    if (is_sub) {
        if (cbl) {
            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
        } else {
            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
            tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
        }
        tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
    } else {
        if (cbl) {
            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
        } else if (rl == al && rl == bl) {
795
            tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, TCG_TARGET_REG_BITS - 1);
796 797 798 799 800 801 802 803 804
            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
        } else {
            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
        }
        tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
    }
}

805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
/* Bit 0 set if inversion required; bit 1 set if swapping required.  */
#define MIPS_CMP_INV  1
#define MIPS_CMP_SWAP 2

static const uint8_t mips_cmp_map[16] = {
    [TCG_COND_LT]  = 0,
    [TCG_COND_LTU] = 0,
    [TCG_COND_GE]  = MIPS_CMP_INV,
    [TCG_COND_GEU] = MIPS_CMP_INV,
    [TCG_COND_LE]  = MIPS_CMP_INV | MIPS_CMP_SWAP,
    [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
    [TCG_COND_GT]  = MIPS_CMP_SWAP,
    [TCG_COND_GTU] = MIPS_CMP_SWAP,
};

static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
                            TCGReg arg1, TCGReg arg2)
{
    MIPSInsn s_opc = OPC_SLTU;
    int cmp_map;

    switch (cond) {
    case TCG_COND_EQ:
        if (arg2 != 0) {
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
            arg1 = ret;
        }
        tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
        break;

    case TCG_COND_NE:
        if (arg2 != 0) {
            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
            arg1 = ret;
        }
        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
        break;

    case TCG_COND_LT:
    case TCG_COND_GE:
    case TCG_COND_LE:
    case TCG_COND_GT:
        s_opc = OPC_SLT;
        /* FALLTHRU */

    case TCG_COND_LTU:
    case TCG_COND_GEU:
    case TCG_COND_LEU:
    case TCG_COND_GTU:
        cmp_map = mips_cmp_map[cond];
        if (cmp_map & MIPS_CMP_SWAP) {
            TCGReg t = arg1;
            arg1 = arg2;
            arg2 = t;
        }
        tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
        if (cmp_map & MIPS_CMP_INV) {
            tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
        }
        break;

     default:
         tcg_abort();
         break;
     }
}

872
static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
873
                           TCGReg arg2, TCGLabel *l)
874
{
875 876 877 878 879 880 881 882 883 884
    static const MIPSInsn b_zero[16] = {
        [TCG_COND_LT] = OPC_BLTZ,
        [TCG_COND_GT] = OPC_BGTZ,
        [TCG_COND_LE] = OPC_BLEZ,
        [TCG_COND_GE] = OPC_BGEZ,
    };

    MIPSInsn s_opc = OPC_SLTU;
    MIPSInsn b_opc;
    int cmp_map;
885 886 887

    switch (cond) {
    case TCG_COND_EQ:
888
        b_opc = OPC_BEQ;
889 890
        break;
    case TCG_COND_NE:
891
        b_opc = OPC_BNE;
892
        break;
893

894
    case TCG_COND_LT:
895
    case TCG_COND_GT:
896
    case TCG_COND_LE:
897
    case TCG_COND_GE:
898
        if (arg2 == 0) {
899 900 901 902
            b_opc = b_zero[cond];
            arg2 = arg1;
            arg1 = 0;
            break;
903
        }
904 905 906 907 908
        s_opc = OPC_SLT;
        /* FALLTHRU */

    case TCG_COND_LTU:
    case TCG_COND_GTU:
909
    case TCG_COND_LEU:
910 911 912 913 914 915
    case TCG_COND_GEU:
        cmp_map = mips_cmp_map[cond];
        if (cmp_map & MIPS_CMP_SWAP) {
            TCGReg t = arg1;
            arg1 = arg2;
            arg2 = t;
916
        }
917 918 919 920
        tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
        b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
        arg1 = TCG_TMP0;
        arg2 = TCG_REG_ZERO;
921
        break;
922

923 924 925 926
    default:
        tcg_abort();
        break;
    }
927 928

    tcg_out_opc_br(s, b_opc, arg1, arg2);
929
    if (l->has_value) {
930
        reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
931
    } else {
932
        tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
933 934 935 936
    }
    tcg_out_nop(s);
}

937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
                                 TCGReg al, TCGReg ah,
                                 TCGReg bl, TCGReg bh)
{
    /* Merge highpart comparison into AH.  */
    if (bh != 0) {
        if (ah != 0) {
            tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
            ah = tmp0;
        } else {
            ah = bh;
        }
    }
    /* Merge lowpart comparison into AL.  */
    if (bl != 0) {
        if (al != 0) {
            tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
            al = tmp1;
        } else {
            al = bl;
        }
    }
    /* Merge high and low part comparisons into AL.  */
    if (ah != 0) {
        if (al != 0) {
            tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
            al = tmp0;
        } else {
            al = ah;
        }
    }
    return al;
}

971 972 973 974 975 976
static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
{
    TCGReg tmp0 = TCG_TMP0;
    TCGReg tmp1 = ret;

977
    tcg_debug_assert(ret != TCG_TMP0);
978
    if (ret == ah || ret == bh) {
979
        tcg_debug_assert(ret != TCG_TMP1);
980 981 982 983 984 985
        tmp1 = TCG_TMP1;
    }

    switch (cond) {
    case TCG_COND_EQ:
    case TCG_COND_NE:
986 987
        tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
        tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
988 989 990 991 992 993 994 995 996 997 998 999
        break;

    default:
        tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
        tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
        tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
        tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
        tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
        break;
    }
}

1000
static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
1001
                            TCGReg bl, TCGReg bh, TCGLabel *l)
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
{
    TCGCond b_cond = TCG_COND_NE;
    TCGReg tmp = TCG_TMP1;

    /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
       With setcond, we emit between 3 and 10 insns and only 1 branch,
       which ought to get better branch prediction.  */
     switch (cond) {
     case TCG_COND_EQ:
     case TCG_COND_NE:
        b_cond = cond;
        tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
1014 1015 1016
        break;

    default:
1017
        /* Minimize code size by preferring a compare not requiring INV.  */
1018 1019 1020 1021 1022 1023
        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
            cond = tcg_invert_cond(cond);
            b_cond = TCG_COND_EQ;
        }
        tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
        break;
1024 1025
    }

1026
    tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
1027 1028
}

1029
static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1030
                            TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
1031
{
1032 1033 1034 1035 1036 1037 1038 1039
    bool eqz = false;

    /* If one of the values is zero, put it last to match SEL*Z instructions */
    if (use_mips32r6_instructions && v1 == 0) {
        v1 = v2;
        v2 = 0;
        cond = tcg_invert_cond(cond);
    }
1040

1041 1042
    switch (cond) {
    case TCG_COND_EQ:
1043
        eqz = true;
1044
        /* FALLTHRU */
1045
    case TCG_COND_NE:
1046
        if (c2 != 0) {
1047
            tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
1048
            c1 = TCG_TMP0;
1049 1050
        }
        break;
1051

1052
    default:
1053
        /* Minimize code size by preferring a compare not requiring INV.  */
1054 1055
        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
            cond = tcg_invert_cond(cond);
1056
            eqz = true;
1057 1058 1059
        }
        tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
        c1 = TCG_TMP0;
1060 1061
        break;
    }
1062

1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
    if (use_mips32r6_instructions) {
        MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
        MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;

        if (v2 != 0) {
            tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
        }
        tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
        if (v2 != 0) {
            tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
        }
    } else {
        MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;

        tcg_out_opc_reg(s, m_opc, ret, v1, c1);

        /* This should be guaranteed via constraints */
        tcg_debug_assert(v2 == ret);
    }
1082 1083
}

1084
static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
1085 1086 1087 1088 1089 1090
{
    /* Note that the ABI requires the called function's address to be
       loaded into T9, even if a direct branch is in range.  */
    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);

    /* But do try a direct branch, allowing the cpu better insn prefetch.  */
1091 1092 1093 1094 1095 1096 1097 1098
    if (tail) {
        if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
        }
    } else {
        if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
            tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
        }
1099
    }
1100
}
1101

1102 1103 1104
static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
{
    tcg_out_call_int(s, arg, false);
1105 1106 1107
    tcg_out_nop(s);
}

1108
#if defined(CONFIG_SOFTMMU)
1109 1110
#include "tcg-ldst.inc.c"

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
static void * const qemu_ld_helpers[16] = {
    [MO_UB]   = helper_ret_ldub_mmu,
    [MO_SB]   = helper_ret_ldsb_mmu,
    [MO_LEUW] = helper_le_lduw_mmu,
    [MO_LESW] = helper_le_ldsw_mmu,
    [MO_LEUL] = helper_le_ldul_mmu,
    [MO_LEQ]  = helper_le_ldq_mmu,
    [MO_BEUW] = helper_be_lduw_mmu,
    [MO_BESW] = helper_be_ldsw_mmu,
    [MO_BEUL] = helper_be_ldul_mmu,
    [MO_BEQ]  = helper_be_ldq_mmu,
1122 1123 1124 1125
#if TCG_TARGET_REG_BITS == 64
    [MO_LESL] = helper_le_ldsl_mmu,
    [MO_BESL] = helper_be_ldsl_mmu,
#endif
1126 1127
};

1128 1129 1130 1131 1132 1133 1134 1135
static void * const qemu_st_helpers[16] = {
    [MO_UB]   = helper_ret_stb_mmu,
    [MO_LEUW] = helper_le_stw_mmu,
    [MO_LEUL] = helper_le_stl_mmu,
    [MO_LEQ]  = helper_le_stq_mmu,
    [MO_BEUW] = helper_be_stw_mmu,
    [MO_BEUL] = helper_be_stl_mmu,
    [MO_BEQ]  = helper_be_stq_mmu,
1136
};
1137

1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
/* Helper routines for marshalling helper function arguments into
 * the correct registers and stack.
 * I is where we want to put this argument, and is updated and returned
 * for the next call. ARG is the argument itself.
 *
 * We provide routines for arguments which are: immediate, 32 bit
 * value in register, 16 and 8 bit values in register (which must be zero
 * extended before use) and 64 bit value in a lo:hi register pair.
 */

static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
1149
{
1150 1151 1152
    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
        tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
    } else {
1153 1154 1155
        /* For N32 and N64, the initial offset is different.  But there
           we also have 8 argument register so we don't run out here.  */
        tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
1156 1157 1158 1159
        tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
    }
    return i + 1;
}
1160

1161 1162
static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
{
1163
    TCGReg tmp = TCG_TMP0;
1164 1165 1166 1167 1168 1169 1170 1171 1172
    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
        tmp = tcg_target_call_iarg_regs[i];
    }
    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
    return tcg_out_call_iarg_reg(s, i, tmp);
}

static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
{
1173
    TCGReg tmp = TCG_TMP0;
1174 1175 1176 1177 1178 1179 1180 1181 1182
    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
        tmp = tcg_target_call_iarg_regs[i];
    }
    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
    return tcg_out_call_iarg_reg(s, i, tmp);
}

static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
{
1183
    TCGReg tmp = TCG_TMP0;
1184 1185
    if (arg == 0) {
        tmp = TCG_REG_ZERO;
1186
    } else {
1187 1188 1189 1190
        if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
            tmp = tcg_target_call_iarg_regs[i];
        }
        tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
1191
    }
1192 1193 1194 1195 1196
    return tcg_out_call_iarg_reg(s, i, tmp);
}

static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
{
1197
    tcg_debug_assert(TCG_TARGET_REG_BITS == 32);
1198 1199 1200 1201 1202 1203 1204
    i = (i + 1) & ~1;
    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
    return i;
}

/* Perform the tlb comparison operation.  The complete host address is
1205
   placed in BASE.  Clobbers TMP0, TMP1, TMP2, A0.  */
1206
static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
1207
                             TCGReg addrh, TCGMemOpIdx oi,
1208 1209
                             tcg_insn_unit *label_ptr[2], bool is_load)
{
1210 1211 1212
    TCGMemOp opc = get_memop(oi);
    unsigned s_bits = opc & MO_SIZE;
    unsigned a_bits = get_alignment_bits(opc);
1213
    target_ulong mask;
1214
    int mem_index = get_mmuidx(oi);
1215 1216 1217 1218 1219 1220
    int cmp_off
        = (is_load
           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);

1221
    tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl,
1222 1223 1224
                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
                    (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1225
    tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1226

1227
    /* Compensate for very large offsets.  */
1228 1229 1230 1231
    while (add_off >= 0x8000) {
        /* Most target env are smaller than 32k, but a few are larger than 64k,
         * so handle an arbitrarily large offset.
         */
1232
        tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
1233 1234 1235 1236
        cmp_off -= 0x7ff0;
        add_off -= 0x7ff0;
    }

1237 1238 1239 1240 1241
    /* We don't currently support unaligned accesses.
       We could do so with mips32r6.  */
    if (a_bits < s_bits) {
        a_bits = s_bits;
    }
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258

    mask = (target_ulong)TARGET_PAGE_MASK | ((1 << a_bits) - 1);

    /* Load the (low half) tlb comparator.  Mask the page bits, keeping the
       alignment bits to compare against.  */
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
        tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
        tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, mask);
    } else {
        tcg_out_ldst(s,
                    (TARGET_LONG_BITS == 64 ? OPC_LD
                    : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW),
                    TCG_TMP0, TCG_REG_A0, cmp_off);
        tcg_out_movi(s, TCG_TYPE_TL, TCG_TMP1, mask);
        /* No second compare is required here;
           load the tlb addend for the fast path.  */
        tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_REG_A0, add_off);
1259
    }
1260
    tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
1261

1262 1263 1264 1265 1266 1267
    /* Zero extend a 32-bit guest address for a 64-bit host. */
    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
        tcg_out_ext32u(s, base, addrl);
        addrl = base;
    }

1268
    label_ptr[0] = s->code_ptr;
1269
    tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
1270

1271
    /* Load and test the high half tlb comparator.  */
1272
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1273
        /* delay slot */
1274
        tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF);
1275

1276 1277
        /* Load the tlb addend for the fast path.  */
        tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_REG_A0, add_off);
1278

1279
        label_ptr[1] = s->code_ptr;
1280
        tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
1281
    }
1282

1283
    /* delay slot */
1284
    tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP2, addrl);
1285
}
1286

1287
static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
1288
                                TCGType ext,
1289 1290
                                TCGReg datalo, TCGReg datahi,
                                TCGReg addrlo, TCGReg addrhi,
1291
                                void *raddr, tcg_insn_unit *label_ptr[2])
1292 1293 1294 1295
{
    TCGLabelQemuLdst *label = new_ldst_label(s);

    label->is_ld = is_ld;
1296
    label->oi = oi;
1297
    label->type = ext;
1298 1299 1300 1301 1302 1303
    label->datalo_reg = datalo;
    label->datahi_reg = datahi;
    label->addrlo_reg = addrlo;
    label->addrhi_reg = addrhi;
    label->raddr = raddr;
    label->label_ptr[0] = label_ptr[0];
1304
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1305 1306 1307 1308 1309 1310
        label->label_ptr[1] = label_ptr[1];
    }
}

static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
1311
    TCGMemOpIdx oi = l->oi;
1312
    TCGMemOp opc = get_memop(oi);
1313
    TCGReg v0;
1314 1315 1316 1317
    int i;

    /* resolve label address */
    reloc_pc16(l->label_ptr[0], s->code_ptr);
1318
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1319 1320 1321
        reloc_pc16(l->label_ptr[1], s->code_ptr);
    }

1322
    i = 1;
1323
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1324 1325 1326 1327
        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
    } else {
        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
    }
1328
    i = tcg_out_call_iarg_imm(s, i, oi);
1329
    i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
1330
    tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
1331 1332
    /* delay slot */
    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1333

1334
    v0 = l->datalo_reg;
1335
    if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
1336 1337
        /* We eliminated V0 from the possible output registers, so it
           cannot be clobbered here.  So we must move V1 first.  */
1338 1339 1340 1341 1342 1343
        if (MIPS_BE) {
            tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
            v0 = l->datahi_reg;
        } else {
            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
        }
1344 1345
    }

1346
    reloc_pc16(s->code_ptr, l->raddr);
1347
    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1348
    /* delay slot */
1349 1350 1351 1352 1353 1354
    if (TCG_TARGET_REG_BITS == 64 && l->type == TCG_TYPE_I32) {
        /* we always sign-extend 32-bit loads */
        tcg_out_opc_sa(s, OPC_SLL, v0, TCG_REG_V0, 0);
    } else {
        tcg_out_opc_reg(s, OPC_OR, v0, TCG_REG_V0, TCG_REG_ZERO);
    }
1355
}
1356

1357 1358
static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
{
1359
    TCGMemOpIdx oi = l->oi;
1360
    TCGMemOp opc = get_memop(oi);
1361 1362 1363 1364 1365
    TCGMemOp s_bits = opc & MO_SIZE;
    int i;

    /* resolve label address */
    reloc_pc16(l->label_ptr[0], s->code_ptr);
1366
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1367 1368
        reloc_pc16(l->label_ptr[1], s->code_ptr);
    }
1369

1370
    i = 1;
1371
    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1372
        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1373
    } else {
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
    }
    switch (s_bits) {
    case MO_8:
        i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
        break;
    case MO_16:
        i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
        break;
    case MO_32:
        i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
        break;
    case MO_64:
1387 1388 1389 1390 1391
        if (TCG_TARGET_REG_BITS == 32) {
            i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
        } else {
            i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
        }
1392 1393 1394
        break;
    default:
        tcg_abort();
1395
    }
1396
    i = tcg_out_call_iarg_imm(s, i, oi);
1397

1398 1399 1400 1401
    /* Tail call to the store helper.  Thus force the return address
       computation to take place in the return address register.  */
    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
    i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
1402
    tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
1403 1404
    /* delay slot */
    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1405
}
1406 1407
#endif

1408
static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1409
                                   TCGReg base, TCGMemOp opc, bool is_64)
1410
{
1411
    switch (opc & (MO_SSIZE | MO_BSWAP)) {
1412
    case MO_UB:
1413
        tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1414
        break;
1415
    case MO_SB:
1416
        tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1417
        break;
1418
    case MO_UW | MO_BSWAP:
1419
        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1420
        tcg_out_bswap16(s, lo, TCG_TMP1);
1421
        break;
1422
    case MO_UW:
1423
        tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1424
        break;
1425
    case MO_SW | MO_BSWAP:
1426
        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1427
        tcg_out_bswap16s(s, lo, TCG_TMP1);
1428
        break;
1429
    case MO_SW:
1430
        tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1431 1432
        break;
    case MO_UL | MO_BSWAP:
1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
        if (TCG_TARGET_REG_BITS == 64 && is_64) {
            if (use_mips32r2_instructions) {
                tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
                tcg_out_bswap32u(s, lo, lo);
            } else {
                tcg_out_bswap_subr(s, bswap32u_addr);
                /* delay slot */
                tcg_out_opc_imm(s, OPC_LWU, TCG_TMP0, base, 0);
                tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
            }
            break;
        }
        /* FALLTHRU */
    case MO_SL | MO_BSWAP:
1447 1448 1449 1450 1451 1452 1453 1454 1455
        if (use_mips32r2_instructions) {
            tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
            tcg_out_bswap32(s, lo, lo);
        } else {
            tcg_out_bswap_subr(s, bswap32_addr);
            /* delay slot */
            tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
            tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_TMP3);
        }
1456 1457
        break;
    case MO_UL:
1458 1459 1460 1461 1462 1463
        if (TCG_TARGET_REG_BITS == 64 && is_64) {
            tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
            break;
        }
        /* FALLTHRU */
    case MO_SL:
1464
        tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1465 1466
        break;
    case MO_Q | MO_BSWAP:
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
        if (TCG_TARGET_REG_BITS == 64) {
            if (use_mips32r2_instructions) {
                tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
                tcg_out_bswap64(s, lo, lo);
            } else {
                tcg_out_bswap_subr(s, bswap64_addr);
                /* delay slot */
                tcg_out_opc_imm(s, OPC_LD, TCG_TMP0, base, 0);
                tcg_out_mov(s, TCG_TYPE_I64, lo, TCG_TMP3);
            }
        } else if (use_mips32r2_instructions) {
1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
            tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
            tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 4);
            tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, TCG_TMP0);
            tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, TCG_TMP1);
            tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? lo : hi, TCG_TMP0, 16);
            tcg_out_opc_sa(s, OPC_ROTR, MIPS_BE ? hi : lo, TCG_TMP1, 16);
        } else {
            tcg_out_bswap_subr(s, bswap32_addr);
            /* delay slot */
            tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 0);
            tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, base, 4);
            tcg_out_bswap_subr(s, bswap32_addr);
            /* delay slot */
            tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? lo : hi, TCG_TMP3);
            tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3);
        }
1494 1495
        break;
    case MO_Q:
1496
        /* Prefer to load from offset 0 first, but allow for overlap.  */
1497 1498 1499
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
        } else if (MIPS_BE ? hi != base : lo == base) {
1500 1501 1502 1503 1504 1505
            tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
            tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
        } else {
            tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
            tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
        }
1506 1507 1508 1509 1510 1511
        break;
    default:
        tcg_abort();
    }
}

1512
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1513
{
1514 1515
    TCGReg addr_regl, addr_regh __attribute__((unused));
    TCGReg data_regl, data_regh;
1516
    TCGMemOpIdx oi;
1517
    TCGMemOp opc;
1518
#if defined(CONFIG_SOFTMMU)
1519
    tcg_insn_unit *label_ptr[2];
1520
#endif
1521
    TCGReg base = TCG_REG_A0;
1522

1523
    data_regl = *args++;
1524
    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1525
    addr_regl = *args++;
1526
    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1527 1528
    oi = *args++;
    opc = get_memop(oi);
1529

1530
#if defined(CONFIG_SOFTMMU)
1531
    tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
1532 1533 1534 1535
    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
    add_qemu_ldst_label(s, 1, oi,
                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
                        data_regl, data_regh, addr_regl, addr_regh,
1536
                        s->code_ptr, label_ptr);
1537
#else
1538 1539 1540 1541
    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
        tcg_out_ext32u(s, base, addr_regl);
        addr_regl = base;
    }
1542
    if (guest_base == 0 && data_regl != addr_regl) {
1543
        base = addr_regl;
1544
    } else if (guest_base == (int16_t)guest_base) {
1545
        tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
1546
    } else {
1547
        tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
1548
    }
1549
    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1550 1551
#endif
}
1552

1553
static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1554 1555
                                   TCGReg base, TCGMemOp opc)
{
1556 1557 1558 1559 1560
    /* Don't clutter the code below with checks to avoid bswapping ZERO.  */
    if ((lo | hi) == 0) {
        opc &= ~MO_BSWAP;
    }

1561
    switch (opc & (MO_SIZE | MO_BSWAP)) {
1562
    case MO_8:
1563
        tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
1564
        break;
1565

1566
    case MO_16 | MO_BSWAP:
1567
        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, lo, 0xffff);
1568
        tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
1569
        lo = TCG_TMP1;
1570 1571
        /* FALLTHRU */
    case MO_16:
1572
        tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
1573
        break;
1574 1575

    case MO_32 | MO_BSWAP:
1576 1577
        tcg_out_bswap32(s, TCG_TMP3, lo);
        lo = TCG_TMP3;
1578 1579
        /* FALLTHRU */
    case MO_32:
1580
        tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
1581
        break;
1582 1583

    case MO_64 | MO_BSWAP:
1584 1585 1586 1587
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_out_bswap64(s, TCG_TMP3, lo);
            tcg_out_opc_imm(s, OPC_SD, TCG_TMP3, base, 0);
        } else if (use_mips32r2_instructions) {
1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
            tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP0, 0, MIPS_BE ? lo : hi);
            tcg_out_opc_reg(s, OPC_WSBH, TCG_TMP1, 0, MIPS_BE ? hi : lo);
            tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP0, TCG_TMP0, 16);
            tcg_out_opc_sa(s, OPC_ROTR, TCG_TMP1, TCG_TMP1, 16);
            tcg_out_opc_imm(s, OPC_SW, TCG_TMP0, base, 0);
            tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, 4);
        } else {
            tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? lo : hi);
            tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 0);
            tcg_out_bswap32(s, TCG_TMP3, MIPS_BE ? hi : lo);
            tcg_out_opc_imm(s, OPC_SW, TCG_TMP3, base, 4);
        }
1600
        break;
1601
    case MO_64:
1602 1603 1604 1605 1606 1607
        if (TCG_TARGET_REG_BITS == 64) {
            tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
        } else {
            tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? hi : lo, base, 0);
            tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? lo : hi, base, 4);
        }
1608
        break;
1609

1610 1611 1612
    default:
        tcg_abort();
    }
1613
}
1614

1615
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1616 1617
{
    TCGReg addr_regl, addr_regh __attribute__((unused));
1618
    TCGReg data_regl, data_regh;
1619
    TCGMemOpIdx oi;
1620
    TCGMemOp opc;
1621 1622 1623
#if defined(CONFIG_SOFTMMU)
    tcg_insn_unit *label_ptr[2];
#endif
1624
    TCGReg base = TCG_REG_A0;
1625 1626

    data_regl = *args++;
1627
    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1628
    addr_regl = *args++;
1629
    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1630 1631
    oi = *args++;
    opc = get_memop(oi);
1632

1633
#if defined(CONFIG_SOFTMMU)
1634
    tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
1635
    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1636 1637 1638
    add_qemu_ldst_label(s, 0, oi,
                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
                        data_regl, data_regh, addr_regl, addr_regh,
1639
                        s->code_ptr, label_ptr);
1640
#else
1641 1642 1643 1644 1645
    base = TCG_REG_A0;
    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
        tcg_out_ext32u(s, base, addr_regl);
        addr_regl = base;
    }
1646
    if (guest_base == 0) {
1647
        base = addr_regl;
1648 1649
    } else if (guest_base == (int16_t)guest_base) {
        tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
1650
    } else {
1651
        tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG, addr_regl);
1652
    }
1653
    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1654 1655 1656
#endif
}

1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672
static void tcg_out_mb(TCGContext *s, TCGArg a0)
{
    static const MIPSInsn sync[] = {
        /* Note that SYNC_MB is a slightly weaker than SYNC 0,
           as the former is an ordering barrier and the latter
           is a completion barrier.  */
        [0 ... TCG_MO_ALL]            = OPC_SYNC_MB,
        [TCG_MO_LD_LD]                = OPC_SYNC_RMB,
        [TCG_MO_ST_ST]                = OPC_SYNC_WMB,
        [TCG_MO_LD_ST]                = OPC_SYNC_RELEASE,
        [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
        [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
    };
    tcg_out32(s, sync[a0 & TCG_MO_ALL]);
}

1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6,
                        int width, TCGReg a0, TCGReg a1, TCGArg a2)
{
    if (use_mips32r6_instructions) {
        if (a2 == width) {
            tcg_out_opc_reg(s, opcv6, a0, a1, 0);
        } else {
            tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
            tcg_out_movcond(s, TCG_COND_EQ, a0, a1, 0, a2, TCG_TMP0);
        }
    } else {
        if (a2 == width) {
            tcg_out_opc_reg(s, opcv2, a0, a1, a1);
        } else if (a0 == a2) {
            tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
            tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
        } else if (a0 != a1) {
            tcg_out_opc_reg(s, opcv2, a0, a1, a1);
            tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
        } else {
            tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
            tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
            tcg_out_mov(s, TCG_TYPE_REG, a0, TCG_TMP0);
        }
    }
}

1700
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1701 1702
                              const TCGArg *args, const int *const_args)
{
1703
    MIPSInsn i1, i2;
1704 1705 1706 1707 1708 1709 1710 1711 1712
    TCGArg a0, a1, a2;
    int c2;

    a0 = args[0];
    a1 = args[1];
    a2 = args[2];
    c2 = const_args[2];

    switch (opc) {
1713
    case INDEX_op_exit_tb:
1714 1715 1716
        {
            TCGReg b0 = TCG_REG_ZERO;

1717
            a0 = (intptr_t)a0;
1718 1719 1720 1721 1722
            if (a0 & ~0xffff) {
                tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
                b0 = TCG_REG_V0;
            }
            if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1723
                tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
1724
                             (uintptr_t)tb_ret_addr);
1725
                tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1726 1727
            }
            tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
1728
        }
1729 1730
        break;
    case INDEX_op_goto_tb:
1731
        if (s->tb_jmp_insn_offset) {
1732
            /* direct jump method */
1733
            s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
1734 1735
            /* Avoid clobbering the address during retranslation.  */
            tcg_out32(s, OPC_J | (*(uint32_t *)s->code_ptr & 0x3ffffff));
1736 1737
        } else {
            /* indirect jump method */
1738
            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
1739
                       (uintptr_t)(s->tb_jmp_target_addr + a0));
1740
            tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1741 1742
        }
        tcg_out_nop(s);
1743
        set_jmp_reset_offset(s, a0);
1744
        break;
1745 1746 1747 1748 1749
    case INDEX_op_goto_ptr:
        /* jmp to the given host address (could be epilogue) */
        tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
        tcg_out_nop(s);
        break;
1750
    case INDEX_op_br:
1751 1752
        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
                       arg_label(a0));
1753 1754 1755
        break;

    case INDEX_op_ld8u_i32:
1756
    case INDEX_op_ld8u_i64:
1757 1758
        i1 = OPC_LBU;
        goto do_ldst;
1759
    case INDEX_op_ld8s_i32:
1760
    case INDEX_op_ld8s_i64:
1761 1762
        i1 = OPC_LB;
        goto do_ldst;
1763
    case INDEX_op_ld16u_i32:
1764
    case INDEX_op_ld16u_i64:
1765 1766
        i1 = OPC_LHU;
        goto do_ldst;
1767
    case INDEX_op_ld16s_i32:
1768
    case INDEX_op_ld16s_i64:
1769 1770
        i1 = OPC_LH;
        goto do_ldst;
1771
    case INDEX_op_ld_i32:
1772
    case INDEX_op_ld32s_i64:
1773 1774
        i1 = OPC_LW;
        goto do_ldst;
1775 1776 1777 1778 1779 1780
    case INDEX_op_ld32u_i64:
        i1 = OPC_LWU;
        goto do_ldst;
    case INDEX_op_ld_i64:
        i1 = OPC_LD;
        goto do_ldst;
1781
    case INDEX_op_st8_i32:
1782
    case INDEX_op_st8_i64:
1783 1784
        i1 = OPC_SB;
        goto do_ldst;
1785
    case INDEX_op_st16_i32:
1786
    case INDEX_op_st16_i64:
1787 1788
        i1 = OPC_SH;
        goto do_ldst;
1789
    case INDEX_op_st_i32:
1790
    case INDEX_op_st32_i64:
1791
        i1 = OPC_SW;
1792 1793 1794
        goto do_ldst;
    case INDEX_op_st_i64:
        i1 = OPC_SD;
1795 1796
    do_ldst:
        tcg_out_ldst(s, i1, a0, a1, a2);
1797 1798 1799
        break;

    case INDEX_op_add_i32:
1800 1801
        i1 = OPC_ADDU, i2 = OPC_ADDIU;
        goto do_binary;
1802 1803 1804
    case INDEX_op_add_i64:
        i1 = OPC_DADDU, i2 = OPC_DADDIU;
        goto do_binary;
1805
    case INDEX_op_or_i32:
1806
    case INDEX_op_or_i64:
1807 1808 1809
        i1 = OPC_OR, i2 = OPC_ORI;
        goto do_binary;
    case INDEX_op_xor_i32:
1810
    case INDEX_op_xor_i64:
1811 1812
        i1 = OPC_XOR, i2 = OPC_XORI;
    do_binary:
1813
        if (c2) {
1814 1815
            tcg_out_opc_imm(s, i2, a0, a1, a2);
            break;
1816
        }
1817 1818
    do_binaryv:
        tcg_out_opc_reg(s, i1, a0, a1, a2);
1819
        break;
1820

1821
    case INDEX_op_sub_i32:
1822 1823 1824 1825 1826
        i1 = OPC_SUBU, i2 = OPC_ADDIU;
        goto do_subtract;
    case INDEX_op_sub_i64:
        i1 = OPC_DSUBU, i2 = OPC_DADDIU;
    do_subtract:
1827
        if (c2) {
1828
            tcg_out_opc_imm(s, i2, a0, a1, -a2);
1829
            break;
1830
        }
1831
        goto do_binaryv;
1832 1833 1834
    case INDEX_op_and_i32:
        if (c2 && a2 != (uint16_t)a2) {
            int msb = ctz32(~a2) - 1;
1835 1836
            tcg_debug_assert(use_mips32r2_instructions);
            tcg_debug_assert(is_p2m1(a2));
1837 1838 1839 1840 1841
            tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
            break;
        }
        i1 = OPC_AND, i2 = OPC_ANDI;
        goto do_binary;
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
    case INDEX_op_and_i64:
        if (c2 && a2 != (uint16_t)a2) {
            int msb = ctz64(~a2) - 1;
            tcg_debug_assert(use_mips32r2_instructions);
            tcg_debug_assert(is_p2m1(a2));
            tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
            break;
        }
        i1 = OPC_AND, i2 = OPC_ANDI;
        goto do_binary;
1852
    case INDEX_op_nor_i32:
1853
    case INDEX_op_nor_i64:
1854 1855 1856
        i1 = OPC_NOR;
        goto do_binaryv;

1857
    case INDEX_op_mul_i32:
1858
        if (use_mips32_instructions) {
1859
            tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1860
            break;
1861
        }
1862 1863
        i1 = OPC_MULT, i2 = OPC_MFLO;
        goto do_hilo1;
1864
    case INDEX_op_mulsh_i32:
1865 1866 1867 1868
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
            break;
        }
1869 1870
        i1 = OPC_MULT, i2 = OPC_MFHI;
        goto do_hilo1;
1871
    case INDEX_op_muluh_i32:
1872 1873 1874 1875
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
            break;
        }
1876 1877
        i1 = OPC_MULTU, i2 = OPC_MFHI;
        goto do_hilo1;
1878
    case INDEX_op_div_i32:
1879 1880 1881 1882
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
            break;
        }
1883 1884
        i1 = OPC_DIV, i2 = OPC_MFLO;
        goto do_hilo1;
1885
    case INDEX_op_divu_i32:
1886 1887 1888 1889
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
            break;
        }
1890 1891
        i1 = OPC_DIVU, i2 = OPC_MFLO;
        goto do_hilo1;
1892
    case INDEX_op_rem_i32:
1893 1894 1895 1896
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
            break;
        }
1897 1898
        i1 = OPC_DIV, i2 = OPC_MFHI;
        goto do_hilo1;
1899
    case INDEX_op_remu_i32:
1900 1901 1902 1903
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
            break;
        }
1904
        i1 = OPC_DIVU, i2 = OPC_MFHI;
1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
        goto do_hilo1;
    case INDEX_op_mul_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
            break;
        }
        i1 = OPC_DMULT, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_mulsh_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DMUH, a0, a1, a2);
            break;
        }
        i1 = OPC_DMULT, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_muluh_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DMUHU, a0, a1, a2);
            break;
        }
        i1 = OPC_DMULTU, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_div_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
            break;
        }
        i1 = OPC_DDIV, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_divu_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
            break;
        }
        i1 = OPC_DDIVU, i2 = OPC_MFLO;
        goto do_hilo1;
    case INDEX_op_rem_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
            break;
        }
        i1 = OPC_DDIV, i2 = OPC_MFHI;
        goto do_hilo1;
    case INDEX_op_remu_i64:
        if (use_mips32r6_instructions) {
            tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
            break;
        }
        i1 = OPC_DDIVU, i2 = OPC_MFHI;
1954 1955 1956
    do_hilo1:
        tcg_out_opc_reg(s, i1, 0, a1, a2);
        tcg_out_opc_reg(s, i2, a0, 0, 0);
1957 1958
        break;

1959 1960 1961 1962 1963
    case INDEX_op_muls2_i32:
        i1 = OPC_MULT;
        goto do_hilo2;
    case INDEX_op_mulu2_i32:
        i1 = OPC_MULTU;
1964 1965 1966 1967 1968 1969
        goto do_hilo2;
    case INDEX_op_muls2_i64:
        i1 = OPC_DMULT;
        goto do_hilo2;
    case INDEX_op_mulu2_i64:
        i1 = OPC_DMULTU;
1970 1971 1972 1973
    do_hilo2:
        tcg_out_opc_reg(s, i1, 0, a2, args[3]);
        tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
        tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
A
Aurelien Jarno 已提交
1974
        break;
1975

1976
    case INDEX_op_not_i32:
1977
    case INDEX_op_not_i64:
1978 1979 1980
        i1 = OPC_NOR;
        goto do_unary;
    case INDEX_op_bswap16_i32:
1981
    case INDEX_op_bswap16_i64:
1982 1983 1984
        i1 = OPC_WSBH;
        goto do_unary;
    case INDEX_op_ext8s_i32:
1985
    case INDEX_op_ext8s_i64:
1986 1987 1988
        i1 = OPC_SEB;
        goto do_unary;
    case INDEX_op_ext16s_i32:
1989
    case INDEX_op_ext16s_i64:
1990 1991 1992
        i1 = OPC_SEH;
    do_unary:
        tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
1993 1994
        break;

1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016
    case INDEX_op_bswap32_i32:
        tcg_out_bswap32(s, a0, a1);
        break;
    case INDEX_op_bswap32_i64:
        tcg_out_bswap32u(s, a0, a1);
        break;
    case INDEX_op_bswap64_i64:
        tcg_out_bswap64(s, a0, a1);
        break;
    case INDEX_op_extrh_i64_i32:
        tcg_out_dsra(s, a0, a1, 32);
        break;
    case INDEX_op_ext32s_i64:
    case INDEX_op_ext_i32_i64:
    case INDEX_op_extrl_i64_i32:
        tcg_out_opc_sa(s, OPC_SLL, a0, a1, 0);
        break;
    case INDEX_op_ext32u_i64:
    case INDEX_op_extu_i32_i64:
        tcg_out_ext32u(s, a0, a1);
        break;

2017
    case INDEX_op_sar_i32:
2018 2019
        i1 = OPC_SRAV, i2 = OPC_SRA;
        goto do_shift;
2020
    case INDEX_op_shl_i32:
2021 2022
        i1 = OPC_SLLV, i2 = OPC_SLL;
        goto do_shift;
2023
    case INDEX_op_shr_i32:
2024 2025 2026 2027 2028
        i1 = OPC_SRLV, i2 = OPC_SRL;
        goto do_shift;
    case INDEX_op_rotr_i32:
        i1 = OPC_ROTRV, i2 = OPC_ROTR;
    do_shift:
2029
        if (c2) {
2030
            tcg_out_opc_sa(s, i2, a0, a1, a2);
2031
            break;
2032
        }
2033 2034
    do_shiftv:
        tcg_out_opc_reg(s, i1, a0, a2, a1);
2035
        break;
2036
    case INDEX_op_rotl_i32:
2037 2038
        if (c2) {
            tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
2039
        } else {
2040 2041
            tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
            tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
2042 2043
        }
        break;
2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078
    case INDEX_op_sar_i64:
        if (c2) {
            tcg_out_dsra(s, a0, a1, a2);
            break;
        }
        i1 = OPC_DSRAV;
        goto do_shiftv;
    case INDEX_op_shl_i64:
        if (c2) {
            tcg_out_dsll(s, a0, a1, a2);
            break;
        }
        i1 = OPC_DSLLV;
        goto do_shiftv;
    case INDEX_op_shr_i64:
        if (c2) {
            tcg_out_dsrl(s, a0, a1, a2);
            break;
        }
        i1 = OPC_DSRLV;
        goto do_shiftv;
    case INDEX_op_rotr_i64:
        if (c2) {
            tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
            break;
        }
        i1 = OPC_DROTRV;
        goto do_shiftv;
    case INDEX_op_rotl_i64:
        if (c2) {
            tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, 64 - a2);
        } else {
            tcg_out_opc_reg(s, OPC_DSUBU, TCG_TMP0, TCG_REG_ZERO, a2);
            tcg_out_opc_reg(s, OPC_DROTRV, a0, TCG_TMP0, a1);
        }
2079 2080
        break;

2081 2082 2083 2084 2085 2086 2087
    case INDEX_op_clz_i32:
        tcg_out_clz(s, OPC_CLZ, OPC_CLZ_R6, 32, a0, a1, a2);
        break;
    case INDEX_op_clz_i64:
        tcg_out_clz(s, OPC_DCLZ, OPC_DCLZ_R6, 64, a0, a1, a2);
        break;

2088
    case INDEX_op_deposit_i32:
2089
        tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
2090
        break;
2091 2092 2093 2094
    case INDEX_op_deposit_i64:
        tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
                         args[3] + args[4] - 1, args[3]);
        break;
2095
    case INDEX_op_extract_i32:
2096
        tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2);
2097 2098 2099
        break;
    case INDEX_op_extract_i64:
        tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1,
2100
                         args[3] - 1, a2);
2101
        break;
2102

2103
    case INDEX_op_brcond_i32:
2104
    case INDEX_op_brcond_i64:
2105
        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2106 2107
        break;
    case INDEX_op_brcond2_i32:
2108
        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
2109 2110
        break;

2111
    case INDEX_op_movcond_i32:
2112
    case INDEX_op_movcond_i64:
2113
        tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
2114 2115
        break;

2116
    case INDEX_op_setcond_i32:
2117
    case INDEX_op_setcond_i64:
2118
        tcg_out_setcond(s, args[3], a0, a1, a2);
2119
        break;
2120
    case INDEX_op_setcond2_i32:
2121
        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
2122
        break;
2123

2124 2125
    case INDEX_op_qemu_ld_i32:
        tcg_out_qemu_ld(s, args, false);
2126
        break;
2127 2128
    case INDEX_op_qemu_ld_i64:
        tcg_out_qemu_ld(s, args, true);
2129
        break;
2130 2131
    case INDEX_op_qemu_st_i32:
        tcg_out_qemu_st(s, args, false);
2132
        break;
2133 2134
    case INDEX_op_qemu_st_i64:
        tcg_out_qemu_st(s, args, true);
2135 2136
        break;

2137 2138 2139 2140 2141 2142 2143 2144 2145
    case INDEX_op_add2_i32:
        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                        const_args[4], const_args[5], false);
        break;
    case INDEX_op_sub2_i32:
        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
                        const_args[4], const_args[5], true);
        break;

2146 2147 2148
    case INDEX_op_mb:
        tcg_out_mb(s, a0);
        break;
2149
    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2150
    case INDEX_op_mov_i64:
2151
    case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
2152
    case INDEX_op_movi_i64:
2153
    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2154 2155 2156 2157 2158
    default:
        tcg_abort();
    }
}

2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
{
    static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
    static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
    static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
    static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
    static const TCGTargetOpDef SZ_S = { .args_ct_str = { "SZ", "S" } };
    static const TCGTargetOpDef rZ_rZ = { .args_ct_str = { "rZ", "rZ" } };
    static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
    static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
    static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
    static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
    static const TCGTargetOpDef r_r_rJ = { .args_ct_str = { "r", "r", "rJ" } };
    static const TCGTargetOpDef SZ_S_S = { .args_ct_str = { "SZ", "S", "S" } };
    static const TCGTargetOpDef SZ_SZ_S
        = { .args_ct_str = { "SZ", "SZ", "S" } };
    static const TCGTargetOpDef SZ_SZ_S_S
        = { .args_ct_str = { "SZ", "SZ", "S", "S" } };
    static const TCGTargetOpDef r_rZ_rN
        = { .args_ct_str = { "r", "rZ", "rN" } };
    static const TCGTargetOpDef r_rZ_rZ
        = { .args_ct_str = { "r", "rZ", "rZ" } };
    static const TCGTargetOpDef r_r_rIK
        = { .args_ct_str = { "r", "r", "rIK" } };
    static const TCGTargetOpDef r_r_rWZ
        = { .args_ct_str = { "r", "r", "rWZ" } };
    static const TCGTargetOpDef r_r_r_r
        = { .args_ct_str = { "r", "r", "r", "r" } };
    static const TCGTargetOpDef r_r_L_L
        = { .args_ct_str = { "r", "r", "L", "L" } };
    static const TCGTargetOpDef dep
        = { .args_ct_str = { "r", "0", "rZ" } };
    static const TCGTargetOpDef movc
        = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "0" } };
    static const TCGTargetOpDef movc_r6
        = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
    static const TCGTargetOpDef add2
        = { .args_ct_str = { "r", "r", "rZ", "rZ", "rN", "rN" } };
    static const TCGTargetOpDef br2
        = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
    static const TCGTargetOpDef setc2
        = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };

    switch (op) {
    case INDEX_op_goto_ptr:
        return &r;
2205

2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237
    case INDEX_op_ld8u_i32:
    case INDEX_op_ld8s_i32:
    case INDEX_op_ld16u_i32:
    case INDEX_op_ld16s_i32:
    case INDEX_op_ld_i32:
    case INDEX_op_not_i32:
    case INDEX_op_bswap16_i32:
    case INDEX_op_bswap32_i32:
    case INDEX_op_ext8s_i32:
    case INDEX_op_ext16s_i32:
    case INDEX_op_extract_i32:
    case INDEX_op_ld8u_i64:
    case INDEX_op_ld8s_i64:
    case INDEX_op_ld16u_i64:
    case INDEX_op_ld16s_i64:
    case INDEX_op_ld32s_i64:
    case INDEX_op_ld32u_i64:
    case INDEX_op_ld_i64:
    case INDEX_op_not_i64:
    case INDEX_op_bswap16_i64:
    case INDEX_op_bswap32_i64:
    case INDEX_op_bswap64_i64:
    case INDEX_op_ext8s_i64:
    case INDEX_op_ext16s_i64:
    case INDEX_op_ext32s_i64:
    case INDEX_op_ext32u_i64:
    case INDEX_op_ext_i32_i64:
    case INDEX_op_extu_i32_i64:
    case INDEX_op_extrl_i64_i32:
    case INDEX_op_extrh_i64_i32:
    case INDEX_op_extract_i64:
        return &r_r;
2238

2239 2240 2241 2242 2243 2244 2245 2246
    case INDEX_op_st8_i32:
    case INDEX_op_st16_i32:
    case INDEX_op_st_i32:
    case INDEX_op_st8_i64:
    case INDEX_op_st16_i64:
    case INDEX_op_st32_i64:
    case INDEX_op_st_i64:
        return &rZ_r;
2247

2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
    case INDEX_op_add_i32:
    case INDEX_op_add_i64:
        return &r_r_rJ;
    case INDEX_op_sub_i32:
    case INDEX_op_sub_i64:
        return &r_rZ_rN;
    case INDEX_op_mul_i32:
    case INDEX_op_mulsh_i32:
    case INDEX_op_muluh_i32:
    case INDEX_op_div_i32:
    case INDEX_op_divu_i32:
    case INDEX_op_rem_i32:
    case INDEX_op_remu_i32:
    case INDEX_op_nor_i32:
    case INDEX_op_setcond_i32:
    case INDEX_op_mul_i64:
    case INDEX_op_mulsh_i64:
    case INDEX_op_muluh_i64:
    case INDEX_op_div_i64:
    case INDEX_op_divu_i64:
    case INDEX_op_rem_i64:
    case INDEX_op_remu_i64:
    case INDEX_op_nor_i64:
    case INDEX_op_setcond_i64:
        return &r_rZ_rZ;
    case INDEX_op_muls2_i32:
    case INDEX_op_mulu2_i32:
    case INDEX_op_muls2_i64:
    case INDEX_op_mulu2_i64:
        return &r_r_r_r;
    case INDEX_op_and_i32:
    case INDEX_op_and_i64:
        return &r_r_rIK;
    case INDEX_op_or_i32:
    case INDEX_op_xor_i32:
    case INDEX_op_or_i64:
    case INDEX_op_xor_i64:
        return &r_r_rI;
    case INDEX_op_shl_i32:
    case INDEX_op_shr_i32:
    case INDEX_op_sar_i32:
    case INDEX_op_rotr_i32:
    case INDEX_op_rotl_i32:
    case INDEX_op_shl_i64:
    case INDEX_op_shr_i64:
    case INDEX_op_sar_i64:
    case INDEX_op_rotr_i64:
    case INDEX_op_rotl_i64:
        return &r_r_ri;
    case INDEX_op_clz_i32:
    case INDEX_op_clz_i64:
        return &r_r_rWZ;
2300

2301 2302 2303 2304 2305 2306 2307 2308 2309
    case INDEX_op_deposit_i32:
    case INDEX_op_deposit_i64:
        return &dep;
    case INDEX_op_brcond_i32:
    case INDEX_op_brcond_i64:
        return &rZ_rZ;
    case INDEX_op_movcond_i32:
    case INDEX_op_movcond_i64:
        return use_mips32r6_instructions ? &movc_r6 : &movc;
2310

2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333
    case INDEX_op_add2_i32:
    case INDEX_op_sub2_i32:
        return &add2;
    case INDEX_op_setcond2_i32:
        return &setc2;
    case INDEX_op_brcond2_i32:
        return &br2;

    case INDEX_op_qemu_ld_i32:
        return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
                ? &r_L : &r_L_L);
    case INDEX_op_qemu_st_i32:
        return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
                ? &SZ_S : &SZ_S_S);
    case INDEX_op_qemu_ld_i64:
        return (TCG_TARGET_REG_BITS == 64 ? &r_L
                : TARGET_LONG_BITS == 32 ? &r_r_L : &r_r_L_L);
    case INDEX_op_qemu_st_i64:
        return (TCG_TARGET_REG_BITS == 64 ? &SZ_S
                : TARGET_LONG_BITS == 32 ? &SZ_SZ_S : &SZ_SZ_S_S);

    default:
        return NULL;
2334 2335 2336
    }
}

2337
static const int tcg_target_callee_save_regs[] = {
B
Blue Swirl 已提交
2338
    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2339 2340 2341 2342 2343 2344 2345
    TCG_REG_S1,
    TCG_REG_S2,
    TCG_REG_S3,
    TCG_REG_S4,
    TCG_REG_S5,
    TCG_REG_S6,
    TCG_REG_S7,
2346
    TCG_REG_S8,
2347 2348 2349
    TCG_REG_RA,       /* should be last for ABI compliance */
};

2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428
/* The Linux kernel doesn't provide any information about the available
   instruction set. Probe it using a signal handler. */


#ifndef use_movnz_instructions
bool use_movnz_instructions = false;
#endif

#ifndef use_mips32_instructions
bool use_mips32_instructions = false;
#endif

#ifndef use_mips32r2_instructions
bool use_mips32r2_instructions = false;
#endif

static volatile sig_atomic_t got_sigill;

static void sigill_handler(int signo, siginfo_t *si, void *data)
{
    /* Skip the faulty instruction */
    ucontext_t *uc = (ucontext_t *)data;
    uc->uc_mcontext.pc += 4;

    got_sigill = 1;
}

static void tcg_target_detect_isa(void)
{
    struct sigaction sa_old, sa_new;

    memset(&sa_new, 0, sizeof(sa_new));
    sa_new.sa_flags = SA_SIGINFO;
    sa_new.sa_sigaction = sigill_handler;
    sigaction(SIGILL, &sa_new, &sa_old);

    /* Probe for movn/movz, necessary to implement movcond. */
#ifndef use_movnz_instructions
    got_sigill = 0;
    asm volatile(".set push\n"
                 ".set mips32\n"
                 "movn $zero, $zero, $zero\n"
                 "movz $zero, $zero, $zero\n"
                 ".set pop\n"
                 : : : );
    use_movnz_instructions = !got_sigill;
#endif

    /* Probe for MIPS32 instructions. As no subsetting is allowed
       by the specification, it is only necessary to probe for one
       of the instructions. */
#ifndef use_mips32_instructions
    got_sigill = 0;
    asm volatile(".set push\n"
                 ".set mips32\n"
                 "mul $zero, $zero\n"
                 ".set pop\n"
                 : : : );
    use_mips32_instructions = !got_sigill;
#endif

    /* Probe for MIPS32r2 instructions if MIPS32 instructions are
       available. As no subsetting is allowed by the specification,
       it is only necessary to probe for one of the instructions. */
#ifndef use_mips32r2_instructions
    if (use_mips32_instructions) {
        got_sigill = 0;
        asm volatile(".set push\n"
                     ".set mips32r2\n"
                     "seb $zero, $zero\n"
                     ".set pop\n"
                     : : : );
        use_mips32r2_instructions = !got_sigill;
    }
#endif

    sigaction(SIGILL, &sa_old, NULL);
}

2429 2430 2431 2432 2433 2434 2435 2436 2437 2438
static tcg_insn_unit *align_code_ptr(TCGContext *s)
{
    uintptr_t p = (uintptr_t)s->code_ptr;
    if (p & 15) {
        p = (p + 15) & -16;
        s->code_ptr = (void *)p;
    }
    return s->code_ptr;
}

2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451
/* Stack frame parameters.  */
#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))

#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
                     + TCG_TARGET_STACK_ALIGN - 1) \
                    & -TCG_TARGET_STACK_ALIGN)
#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)

/* We're expecting to be able to use an immediate for frame allocation.  */
QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);

2452
/* Generate global QEMU prologue and epilogue code */
2453
static void tcg_target_qemu_prologue(TCGContext *s)
2454
{
2455 2456 2457
    int i;

    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2458 2459

    /* TB prologue */
2460 2461 2462 2463
    tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2464 2465
    }

2466 2467 2468 2469 2470 2471 2472
#ifndef CONFIG_SOFTMMU
    if (guest_base) {
        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
    }
#endif

2473
    /* Call generated code */
2474
    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
2475
    /* delay slot */
B
Blue Swirl 已提交
2476
    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2477

2478 2479 2480 2481 2482 2483 2484
    /*
     * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
     * and fall through to the rest of the epilogue.
     */
    s->code_gen_epilogue = s->code_ptr;
    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);

2485
    /* TB epilogue */
2486 2487 2488 2489
    tb_ret_addr = s->code_ptr;
    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2490 2491 2492
    }

    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2493
    /* delay slot */
2494
    tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2495 2496 2497 2498 2499

    if (use_mips32r2_instructions) {
        return;
    }

2500
    /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525
       clobbers TCG_TMP1, TCG_TMP2.  */

    /*
     * bswap32 -- 32-bit swap (signed result for mips64).  a0 = abcd.
     */
    bswap32_addr = align_code_ptr(s);
    /* t3 = (ssss)d000 */
    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
    /* t1 = 000a */
    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
    /* t2 = 00c0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
    /* t3 = d00a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
    /* t1 = 0abc */
    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
    /* t2 = 0c00 */
    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
    /* t1 = 00b0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
    /* t3 = dc0a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
    /* t3 = dcba -- delay slot */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613

    if (TCG_TARGET_REG_BITS == 32) {
        return;
    }

    /*
     * bswap32u -- unsigned 32-bit swap.  a0 = ....abcd.
     */
    bswap32u_addr = align_code_ptr(s);
    /* t1 = (0000)000d */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
    /* t3 = 000a */
    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
    /* t1 = (0000)d000 */
    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
    /* t2 = 00c0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
    /* t3 = d00a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
    /* t1 = 0abc */
    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
    /* t2 = 0c00 */
    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
    /* t1 = 00b0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
    /* t3 = dc0a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
    /* t3 = dcba -- delay slot */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);

    /*
     * bswap64 -- 64-bit swap.  a0 = abcdefgh
     */
    bswap64_addr = align_code_ptr(s);
    /* t3 = h0000000 */
    tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
    /* t1 = 0000000a */
    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);

    /* t2 = 000000g0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
    /* t3 = h000000a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
    /* t1 = 00000abc */
    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
    /* t2 = 0g000000 */
    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
    /* t1 = 000000b0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);

    /* t3 = hg00000a */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
    /* t2 = 0000abcd */
    tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
    /* t3 = hg0000ba */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);

    /* t1 = 000000c0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
    /* t2 = 0000000d */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
    /* t1 = 00000c00 */
    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
    /* t2 = 0000d000 */
    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);

    /* t3 = hg000cba */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
    /* t1 = 00abcdef */
    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
    /* t3 = hg00dcba */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);

    /* t2 = 0000000f */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
    /* t1 = 000000e0 */
    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
    /* t2 = 00f00000 */
    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
    /* t1 = 000e0000 */
    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);

    /* t3 = hgf0dcba */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
    /* t3 = hgfedcba -- delay slot */
    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2614 2615
}

2616
static void tcg_target_init(TCGContext *s)
2617
{
2618
    tcg_target_detect_isa();
2619
    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2620
    if (TCG_TARGET_REG_BITS == 64) {
2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640
        tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
    }

    tcg_target_call_clobber_regs = 0;
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
2641

2642
    s->reserved_regs = 0;
2643 2644 2645
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
2646 2647
    tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);     /* internal use */
    tcg_regset_set_reg(s->reserved_regs, TCG_TMP1);     /* internal use */
2648 2649
    tcg_regset_set_reg(s->reserved_regs, TCG_TMP2);     /* internal use */
    tcg_regset_set_reg(s->reserved_regs, TCG_TMP3);     /* internal use */
2650 2651
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
2652
    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);   /* global pointer */
2653
}
2654

2655 2656
void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_addr,
                              uintptr_t addr)
2657
{
2658
    atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
2659 2660
    flush_icache_range(jmp_addr, jmp_addr + 4);
}
2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704

typedef struct {
    DebugFrameHeader h;
    uint8_t fde_def_cfa[4];
    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
} DebugFrame;

#define ELF_HOST_MACHINE EM_MIPS
/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
   which is good because they're really quite complicated for MIPS.  */

static const DebugFrame debug_frame = {
    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
    .h.cie.id = -1,
    .h.cie.version = 1,
    .h.cie.code_align = 1,
    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
    .h.cie.return_column = TCG_REG_RA,

    /* Total FDE size does not include the "len" member.  */
    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),

    .fde_def_cfa = {
        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
        (FRAME_SIZE >> 7)
    },
    .fde_reg_ofs = {
        0x80 + 16, 9,                   /* DW_CFA_offset, s0, -72 */
        0x80 + 17, 8,                   /* DW_CFA_offset, s2, -64 */
        0x80 + 18, 7,                   /* DW_CFA_offset, s3, -56 */
        0x80 + 19, 6,                   /* DW_CFA_offset, s4, -48 */
        0x80 + 20, 5,                   /* DW_CFA_offset, s5, -40 */
        0x80 + 21, 4,                   /* DW_CFA_offset, s6, -32 */
        0x80 + 22, 3,                   /* DW_CFA_offset, s7, -24 */
        0x80 + 30, 2,                   /* DW_CFA_offset, s8, -16 */
        0x80 + 31, 1,                   /* DW_CFA_offset, ra,  -8 */
    }
};

void tcg_register_jit(void *buf, size_t buf_size)
{
    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
}
反馈
建议
客服 返回
顶部