qemu/tcg/mips/tcg-target.c
<<
>>
Prefs
   1/*
   2 * Tiny Code Generator for QEMU
   3 *
   4 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
   5 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
   6 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a copy
   9 * of this software and associated documentation files (the "Software"), to deal
  10 * in the Software without restriction, including without limitation the rights
  11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12 * copies of the Software, and to permit persons to whom the Software is
  13 * furnished to do so, subject to the following conditions:
  14 *
  15 * The above copyright notice and this permission notice shall be included in
  16 * all copies or substantial portions of the Software.
  17 *
  18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24 * THE SOFTWARE.
  25 */
  26
  27#include "tcg-be-ldst.h"
  28
  29#ifdef HOST_WORDS_BIGENDIAN
  30# define MIPS_BE  1
  31#else
  32# define MIPS_BE  0
  33#endif
  34
  35#define LO_OFF    (MIPS_BE * 4)
  36#define HI_OFF    (4 - LO_OFF)
  37
  38#ifndef NDEBUG
  39static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
  40    "zero",
  41    "at",
  42    "v0",
  43    "v1",
  44    "a0",
  45    "a1",
  46    "a2",
  47    "a3",
  48    "t0",
  49    "t1",
  50    "t2",
  51    "t3",
  52    "t4",
  53    "t5",
  54    "t6",
  55    "t7",
  56    "s0",
  57    "s1",
  58    "s2",
  59    "s3",
  60    "s4",
  61    "s5",
  62    "s6",
  63    "s7",
  64    "t8",
  65    "t9",
  66    "k0",
  67    "k1",
  68    "gp",
  69    "sp",
  70    "s8",
  71    "ra",
  72};
  73#endif
  74
  75#define TCG_TMP0  TCG_REG_AT
  76#define TCG_TMP1  TCG_REG_T9
  77
  78/* check if we really need so many registers :P */
  79static const TCGReg tcg_target_reg_alloc_order[] = {
  80    /* Call saved registers.  */
  81    TCG_REG_S0,
  82    TCG_REG_S1,
  83    TCG_REG_S2,
  84    TCG_REG_S3,
  85    TCG_REG_S4,
  86    TCG_REG_S5,
  87    TCG_REG_S6,
  88    TCG_REG_S7,
  89    TCG_REG_S8,
  90
  91    /* Call clobbered registers.  */
  92    TCG_REG_T0,
  93    TCG_REG_T1,
  94    TCG_REG_T2,
  95    TCG_REG_T3,
  96    TCG_REG_T4,
  97    TCG_REG_T5,
  98    TCG_REG_T6,
  99    TCG_REG_T7,
 100    TCG_REG_T8,
 101    TCG_REG_T9,
 102    TCG_REG_V1,
 103    TCG_REG_V0,
 104
 105    /* Argument registers, opposite order of allocation.  */
 106    TCG_REG_A3,
 107    TCG_REG_A2,
 108    TCG_REG_A1,
 109    TCG_REG_A0,
 110};
 111
 112static const TCGReg tcg_target_call_iarg_regs[4] = {
 113    TCG_REG_A0,
 114    TCG_REG_A1,
 115    TCG_REG_A2,
 116    TCG_REG_A3
 117};
 118
 119static const TCGReg tcg_target_call_oarg_regs[2] = {
 120    TCG_REG_V0,
 121    TCG_REG_V1
 122};
 123
 124static tcg_insn_unit *tb_ret_addr;
 125
 126static inline uint32_t reloc_pc16_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 127{
 128    /* Let the compiler perform the right-shift as part of the arithmetic.  */
 129    ptrdiff_t disp = target - (pc + 1);
 130    assert(disp == (int16_t)disp);
 131    return disp & 0xffff;
 132}
 133
 134static inline void reloc_pc16(tcg_insn_unit *pc, tcg_insn_unit *target)
 135{
 136    *pc = deposit32(*pc, 0, 16, reloc_pc16_val(pc, target));
 137}
 138
 139static inline uint32_t reloc_26_val(tcg_insn_unit *pc, tcg_insn_unit *target)
 140{
 141    assert((((uintptr_t)pc ^ (uintptr_t)target) & 0xf0000000) == 0);
 142    return ((uintptr_t)target >> 2) & 0x3ffffff;
 143}
 144
 145static inline void reloc_26(tcg_insn_unit *pc, tcg_insn_unit *target)
 146{
 147    *pc = deposit32(*pc, 0, 26, reloc_26_val(pc, target));
 148}
 149
 150static void patch_reloc(tcg_insn_unit *code_ptr, int type,
 151                        intptr_t value, intptr_t addend)
 152{
 153    assert(type == R_MIPS_PC16);
 154    assert(addend == 0);
 155    reloc_pc16(code_ptr, (tcg_insn_unit *)value);
 156}
 157
 158#define TCG_CT_CONST_ZERO 0x100
 159#define TCG_CT_CONST_U16  0x200    /* Unsigned 16-bit: 0 - 0xffff.  */
 160#define TCG_CT_CONST_S16  0x400    /* Signed 16-bit: -32768 - 32767 */
 161#define TCG_CT_CONST_P2M1 0x800    /* Power of 2 minus 1.  */
 162#define TCG_CT_CONST_N16  0x1000   /* "Negatable" 16-bit: -32767 - 32767 */
 163
 164static inline bool is_p2m1(tcg_target_long val)
 165{
 166    return val && ((val + 1) & val) == 0;
 167}
 168
 169/* parse target specific constraints */
 170static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 171{
 172    const char *ct_str;
 173
 174    ct_str = *pct_str;
 175    switch(ct_str[0]) {
 176    case 'r':
 177        ct->ct |= TCG_CT_REG;
 178        tcg_regset_set(ct->u.regs, 0xffffffff);
 179        break;
 180    case 'L': /* qemu_ld output arg constraint */
 181        ct->ct |= TCG_CT_REG;
 182        tcg_regset_set(ct->u.regs, 0xffffffff);
 183        tcg_regset_reset_reg(ct->u.regs, TCG_REG_V0);
 184        break;
 185    case 'l': /* qemu_ld input arg constraint */
 186        ct->ct |= TCG_CT_REG;
 187        tcg_regset_set(ct->u.regs, 0xffffffff);
 188        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 189#if defined(CONFIG_SOFTMMU)
 190        if (TARGET_LONG_BITS == 64) {
 191            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 192        }
 193#endif
 194        break;
 195    case 'S': /* qemu_st constraint */
 196        ct->ct |= TCG_CT_REG;
 197        tcg_regset_set(ct->u.regs, 0xffffffff);
 198        tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
 199#if defined(CONFIG_SOFTMMU)
 200        if (TARGET_LONG_BITS == 32) {
 201            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
 202        } else {
 203            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
 204            tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
 205        }
 206#endif
 207        break;
 208    case 'I':
 209        ct->ct |= TCG_CT_CONST_U16;
 210        break;
 211    case 'J':
 212        ct->ct |= TCG_CT_CONST_S16;
 213        break;
 214    case 'K':
 215        ct->ct |= TCG_CT_CONST_P2M1;
 216        break;
 217    case 'N':
 218        ct->ct |= TCG_CT_CONST_N16;
 219        break;
 220    case 'Z':
 221        /* We are cheating a bit here, using the fact that the register
 222           ZERO is also the register number 0. Hence there is no need
 223           to check for const_args in each instruction. */
 224        ct->ct |= TCG_CT_CONST_ZERO;
 225        break;
 226    default:
 227        return -1;
 228    }
 229    ct_str++;
 230    *pct_str = ct_str;
 231    return 0;
 232}
 233
 234/* test if a constant matches the constraint */
 235static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
 236                                         const TCGArgConstraint *arg_ct)
 237{
 238    int ct;
 239    ct = arg_ct->ct;
 240    if (ct & TCG_CT_CONST) {
 241        return 1;
 242    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
 243        return 1;
 244    } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
 245        return 1;
 246    } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
 247        return 1;
 248    } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
 249        return 1;
 250    } else if ((ct & TCG_CT_CONST_P2M1)
 251               && use_mips32r2_instructions && is_p2m1(val)) {
 252        return 1;
 253    }
 254    return 0;
 255}
 256
 257/* instruction opcodes */
 258typedef enum {
 259    OPC_J        = 0x02 << 26,
 260    OPC_JAL      = 0x03 << 26,
 261    OPC_BEQ      = 0x04 << 26,
 262    OPC_BNE      = 0x05 << 26,
 263    OPC_BLEZ     = 0x06 << 26,
 264    OPC_BGTZ     = 0x07 << 26,
 265    OPC_ADDIU    = 0x09 << 26,
 266    OPC_SLTI     = 0x0A << 26,
 267    OPC_SLTIU    = 0x0B << 26,
 268    OPC_ANDI     = 0x0C << 26,
 269    OPC_ORI      = 0x0D << 26,
 270    OPC_XORI     = 0x0E << 26,
 271    OPC_LUI      = 0x0F << 26,
 272    OPC_LB       = 0x20 << 26,
 273    OPC_LH       = 0x21 << 26,
 274    OPC_LW       = 0x23 << 26,
 275    OPC_LBU      = 0x24 << 26,
 276    OPC_LHU      = 0x25 << 26,
 277    OPC_LWU      = 0x27 << 26,
 278    OPC_SB       = 0x28 << 26,
 279    OPC_SH       = 0x29 << 26,
 280    OPC_SW       = 0x2B << 26,
 281
 282    OPC_SPECIAL  = 0x00 << 26,
 283    OPC_SLL      = OPC_SPECIAL | 0x00,
 284    OPC_SRL      = OPC_SPECIAL | 0x02,
 285    OPC_ROTR     = OPC_SPECIAL | (0x01 << 21) | 0x02,
 286    OPC_SRA      = OPC_SPECIAL | 0x03,
 287    OPC_SLLV     = OPC_SPECIAL | 0x04,
 288    OPC_SRLV     = OPC_SPECIAL | 0x06,
 289    OPC_ROTRV    = OPC_SPECIAL | (0x01 <<  6) | 0x06,
 290    OPC_SRAV     = OPC_SPECIAL | 0x07,
 291    OPC_JR       = OPC_SPECIAL | 0x08,
 292    OPC_JALR     = OPC_SPECIAL | 0x09,
 293    OPC_MOVZ     = OPC_SPECIAL | 0x0A,
 294    OPC_MOVN     = OPC_SPECIAL | 0x0B,
 295    OPC_MFHI     = OPC_SPECIAL | 0x10,
 296    OPC_MFLO     = OPC_SPECIAL | 0x12,
 297    OPC_MULT     = OPC_SPECIAL | 0x18,
 298    OPC_MULTU    = OPC_SPECIAL | 0x19,
 299    OPC_DIV      = OPC_SPECIAL | 0x1A,
 300    OPC_DIVU     = OPC_SPECIAL | 0x1B,
 301    OPC_ADDU     = OPC_SPECIAL | 0x21,
 302    OPC_SUBU     = OPC_SPECIAL | 0x23,
 303    OPC_AND      = OPC_SPECIAL | 0x24,
 304    OPC_OR       = OPC_SPECIAL | 0x25,
 305    OPC_XOR      = OPC_SPECIAL | 0x26,
 306    OPC_NOR      = OPC_SPECIAL | 0x27,
 307    OPC_SLT      = OPC_SPECIAL | 0x2A,
 308    OPC_SLTU     = OPC_SPECIAL | 0x2B,
 309
 310    OPC_REGIMM   = 0x01 << 26,
 311    OPC_BLTZ     = OPC_REGIMM | (0x00 << 16),
 312    OPC_BGEZ     = OPC_REGIMM | (0x01 << 16),
 313
 314    OPC_SPECIAL2 = 0x1c << 26,
 315    OPC_MUL      = OPC_SPECIAL2 | 0x002,
 316
 317    OPC_SPECIAL3 = 0x1f << 26,
 318    OPC_EXT      = OPC_SPECIAL3 | 0x000,
 319    OPC_INS      = OPC_SPECIAL3 | 0x004,
 320    OPC_WSBH     = OPC_SPECIAL3 | 0x0a0,
 321    OPC_SEB      = OPC_SPECIAL3 | 0x420,
 322    OPC_SEH      = OPC_SPECIAL3 | 0x620,
 323} MIPSInsn;
 324
 325/*
 326 * Type reg
 327 */
 328static inline void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
 329                                   TCGReg rd, TCGReg rs, TCGReg rt)
 330{
 331    int32_t inst;
 332
 333    inst = opc;
 334    inst |= (rs & 0x1F) << 21;
 335    inst |= (rt & 0x1F) << 16;
 336    inst |= (rd & 0x1F) << 11;
 337    tcg_out32(s, inst);
 338}
 339
 340/*
 341 * Type immediate
 342 */
 343static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
 344                                   TCGReg rt, TCGReg rs, TCGArg imm)
 345{
 346    int32_t inst;
 347
 348    inst = opc;
 349    inst |= (rs & 0x1F) << 21;
 350    inst |= (rt & 0x1F) << 16;
 351    inst |= (imm & 0xffff);
 352    tcg_out32(s, inst);
 353}
 354
 355/*
 356 * Type bitfield
 357 */
 358static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
 359                                  TCGReg rs, int msb, int lsb)
 360{
 361    int32_t inst;
 362
 363    inst = opc;
 364    inst |= (rs & 0x1F) << 21;
 365    inst |= (rt & 0x1F) << 16;
 366    inst |= (msb & 0x1F) << 11;
 367    inst |= (lsb & 0x1F) << 6;
 368    tcg_out32(s, inst);
 369}
 370
 371/*
 372 * Type branch
 373 */
 374static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
 375                                  TCGReg rt, TCGReg rs)
 376{
 377    /* We pay attention here to not modify the branch target by reading
 378       the existing value and using it again. This ensure that caches and
 379       memory are kept coherent during retranslation. */
 380    uint16_t offset = (uint16_t)*s->code_ptr;
 381
 382    tcg_out_opc_imm(s, opc, rt, rs, offset);
 383}
 384
 385/*
 386 * Type sa
 387 */
 388static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
 389                                  TCGReg rd, TCGReg rt, TCGArg sa)
 390{
 391    int32_t inst;
 392
 393    inst = opc;
 394    inst |= (rt & 0x1F) << 16;
 395    inst |= (rd & 0x1F) << 11;
 396    inst |= (sa & 0x1F) <<  6;
 397    tcg_out32(s, inst);
 398
 399}
 400
 401/*
 402 * Type jump.
 403 * Returns true if the branch was in range and the insn was emitted.
 404 */
 405static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
 406{
 407    uintptr_t dest = (uintptr_t)target;
 408    uintptr_t from = (uintptr_t)s->code_ptr + 4;
 409    int32_t inst;
 410
 411    /* The pc-region branch happens within the 256MB region of
 412       the delay slot (thus the +4).  */
 413    if ((from ^ dest) & -(1 << 28)) {
 414        return false;
 415    }
 416    assert((dest & 3) == 0);
 417
 418    inst = opc;
 419    inst |= (dest >> 2) & 0x3ffffff;
 420    tcg_out32(s, inst);
 421    return true;
 422}
 423
 424static inline void tcg_out_nop(TCGContext *s)
 425{
 426    tcg_out32(s, 0);
 427}
 428
 429static inline void tcg_out_mov(TCGContext *s, TCGType type,
 430                               TCGReg ret, TCGReg arg)
 431{
 432    /* Simple reg-reg move, optimising out the 'do nothing' case */
 433    if (ret != arg) {
 434        tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
 435    }
 436}
 437
 438static inline void tcg_out_movi(TCGContext *s, TCGType type,
 439                                TCGReg reg, tcg_target_long arg)
 440{
 441    if (arg == (int16_t)arg) {
 442        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
 443    } else if (arg == (uint16_t)arg) {
 444        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
 445    } else {
 446        tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
 447        if (arg & 0xffff) {
 448            tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
 449        }
 450    }
 451}
 452
 453static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
 454{
 455    if (use_mips32r2_instructions) {
 456        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 457    } else {
 458        /* ret and arg can't be register at */
 459        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
 460            tcg_abort();
 461        }
 462
 463        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 464        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
 465        tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
 466        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 467    }
 468}
 469
 470static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
 471{
 472    if (use_mips32r2_instructions) {
 473        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 474        tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
 475    } else {
 476        /* ret and arg can't be register at */
 477        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
 478            tcg_abort();
 479        }
 480
 481        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 482        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 483        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
 484        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 485    }
 486}
 487
 488static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
 489{
 490    if (use_mips32r2_instructions) {
 491        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 492        tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
 493    } else {
 494        /* ret and arg must be different and can't be register at */
 495        if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) {
 496            tcg_abort();
 497        }
 498
 499        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 500
 501        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 24);
 502        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 503
 504        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00);
 505        tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
 506        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 507
 508        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 509        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00);
 510        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 511    }
 512}
 513
 514static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
 515{
 516    if (use_mips32r2_instructions) {
 517        tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
 518    } else {
 519        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 520        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
 521    }
 522}
 523
 524static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
 525{
 526    if (use_mips32r2_instructions) {
 527        tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
 528    } else {
 529        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
 530        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
 531    }
 532}
 533
 534static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
 535                         TCGReg addr, intptr_t ofs)
 536{
 537    int16_t lo = ofs;
 538    if (ofs != lo) {
 539        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
 540        if (addr != TCG_REG_ZERO) {
 541            tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
 542        }
 543        addr = TCG_TMP0;
 544    }
 545    tcg_out_opc_imm(s, opc, data, addr, lo);
 546}
 547
 548static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
 549                              TCGReg arg1, intptr_t arg2)
 550{
 551    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
 552}
 553
 554static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
 555                              TCGReg arg1, intptr_t arg2)
 556{
 557    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
 558}
 559
 560static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
 561{
 562    if (val == (int16_t)val) {
 563        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
 564    } else {
 565        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
 566        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0);
 567    }
 568}
 569
 570/* Bit 0 set if inversion required; bit 1 set if swapping required.  */
 571#define MIPS_CMP_INV  1
 572#define MIPS_CMP_SWAP 2
 573
 574static const uint8_t mips_cmp_map[16] = {
 575    [TCG_COND_LT]  = 0,
 576    [TCG_COND_LTU] = 0,
 577    [TCG_COND_GE]  = MIPS_CMP_INV,
 578    [TCG_COND_GEU] = MIPS_CMP_INV,
 579    [TCG_COND_LE]  = MIPS_CMP_INV | MIPS_CMP_SWAP,
 580    [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
 581    [TCG_COND_GT]  = MIPS_CMP_SWAP,
 582    [TCG_COND_GTU] = MIPS_CMP_SWAP,
 583};
 584
 585static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
 586                            TCGReg arg1, TCGReg arg2)
 587{
 588    MIPSInsn s_opc = OPC_SLTU;
 589    int cmp_map;
 590
 591    switch (cond) {
 592    case TCG_COND_EQ:
 593        if (arg2 != 0) {
 594            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
 595            arg1 = ret;
 596        }
 597        tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
 598        break;
 599
 600    case TCG_COND_NE:
 601        if (arg2 != 0) {
 602            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
 603            arg1 = ret;
 604        }
 605        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
 606        break;
 607
 608    case TCG_COND_LT:
 609    case TCG_COND_GE:
 610    case TCG_COND_LE:
 611    case TCG_COND_GT:
 612        s_opc = OPC_SLT;
 613        /* FALLTHRU */
 614
 615    case TCG_COND_LTU:
 616    case TCG_COND_GEU:
 617    case TCG_COND_LEU:
 618    case TCG_COND_GTU:
 619        cmp_map = mips_cmp_map[cond];
 620        if (cmp_map & MIPS_CMP_SWAP) {
 621            TCGReg t = arg1;
 622            arg1 = arg2;
 623            arg2 = t;
 624        }
 625        tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
 626        if (cmp_map & MIPS_CMP_INV) {
 627            tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
 628        }
 629        break;
 630
 631     default:
 632         tcg_abort();
 633         break;
 634     }
 635}
 636
 637static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
 638                           TCGReg arg2, TCGLabel *l)
 639{
 640    static const MIPSInsn b_zero[16] = {
 641        [TCG_COND_LT] = OPC_BLTZ,
 642        [TCG_COND_GT] = OPC_BGTZ,
 643        [TCG_COND_LE] = OPC_BLEZ,
 644        [TCG_COND_GE] = OPC_BGEZ,
 645    };
 646
 647    MIPSInsn s_opc = OPC_SLTU;
 648    MIPSInsn b_opc;
 649    int cmp_map;
 650
 651    switch (cond) {
 652    case TCG_COND_EQ:
 653        b_opc = OPC_BEQ;
 654        break;
 655    case TCG_COND_NE:
 656        b_opc = OPC_BNE;
 657        break;
 658
 659    case TCG_COND_LT:
 660    case TCG_COND_GT:
 661    case TCG_COND_LE:
 662    case TCG_COND_GE:
 663        if (arg2 == 0) {
 664            b_opc = b_zero[cond];
 665            arg2 = arg1;
 666            arg1 = 0;
 667            break;
 668        }
 669        s_opc = OPC_SLT;
 670        /* FALLTHRU */
 671
 672    case TCG_COND_LTU:
 673    case TCG_COND_GTU:
 674    case TCG_COND_LEU:
 675    case TCG_COND_GEU:
 676        cmp_map = mips_cmp_map[cond];
 677        if (cmp_map & MIPS_CMP_SWAP) {
 678            TCGReg t = arg1;
 679            arg1 = arg2;
 680            arg2 = t;
 681        }
 682        tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
 683        b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
 684        arg1 = TCG_TMP0;
 685        arg2 = TCG_REG_ZERO;
 686        break;
 687
 688    default:
 689        tcg_abort();
 690        break;
 691    }
 692
 693    tcg_out_opc_br(s, b_opc, arg1, arg2);
 694    if (l->has_value) {
 695        reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
 696    } else {
 697        tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
 698    }
 699    tcg_out_nop(s);
 700}
 701
 702static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
 703                                 TCGReg al, TCGReg ah,
 704                                 TCGReg bl, TCGReg bh)
 705{
 706    /* Merge highpart comparison into AH.  */
 707    if (bh != 0) {
 708        if (ah != 0) {
 709            tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
 710            ah = tmp0;
 711        } else {
 712            ah = bh;
 713        }
 714    }
 715    /* Merge lowpart comparison into AL.  */
 716    if (bl != 0) {
 717        if (al != 0) {
 718            tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
 719            al = tmp1;
 720        } else {
 721            al = bl;
 722        }
 723    }
 724    /* Merge high and low part comparisons into AL.  */
 725    if (ah != 0) {
 726        if (al != 0) {
 727            tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
 728            al = tmp0;
 729        } else {
 730            al = ah;
 731        }
 732    }
 733    return al;
 734}
 735
 736static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
 737                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
 738{
 739    TCGReg tmp0 = TCG_TMP0;
 740    TCGReg tmp1 = ret;
 741
 742    assert(ret != TCG_TMP0);
 743    if (ret == ah || ret == bh) {
 744        assert(ret != TCG_TMP1);
 745        tmp1 = TCG_TMP1;
 746    }
 747
 748    switch (cond) {
 749    case TCG_COND_EQ:
 750    case TCG_COND_NE:
 751        tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
 752        tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
 753        break;
 754
 755    default:
 756        tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
 757        tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
 758        tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
 759        tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
 760        tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
 761        break;
 762    }
 763}
 764
 765static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
 766                            TCGReg bl, TCGReg bh, TCGLabel *l)
 767{
 768    TCGCond b_cond = TCG_COND_NE;
 769    TCGReg tmp = TCG_TMP1;
 770
 771    /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
 772       With setcond, we emit between 3 and 10 insns and only 1 branch,
 773       which ought to get better branch prediction.  */
 774     switch (cond) {
 775     case TCG_COND_EQ:
 776     case TCG_COND_NE:
 777        b_cond = cond;
 778        tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
 779        break;
 780
 781    default:
 782        /* Minimize code size by preferring a compare not requiring INV.  */
 783        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
 784            cond = tcg_invert_cond(cond);
 785            b_cond = TCG_COND_EQ;
 786        }
 787        tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
 788        break;
 789    }
 790
 791    tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
 792}
 793
 794static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
 795                            TCGReg c1, TCGReg c2, TCGReg v)
 796{
 797    MIPSInsn m_opc = OPC_MOVN;
 798
 799    switch (cond) {
 800    case TCG_COND_EQ:
 801        m_opc = OPC_MOVZ;
 802        /* FALLTHRU */
 803    case TCG_COND_NE:
 804        if (c2 != 0) {
 805            tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
 806            c1 = TCG_TMP0;
 807        }
 808        break;
 809
 810    default:
 811        /* Minimize code size by preferring a compare not requiring INV.  */
 812        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
 813            cond = tcg_invert_cond(cond);
 814            m_opc = OPC_MOVZ;
 815        }
 816        tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
 817        c1 = TCG_TMP0;
 818        break;
 819    }
 820
 821    tcg_out_opc_reg(s, m_opc, ret, v, c1);
 822}
 823
 824static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
 825{
 826    /* Note that the ABI requires the called function's address to be
 827       loaded into T9, even if a direct branch is in range.  */
 828    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
 829
 830    /* But do try a direct branch, allowing the cpu better insn prefetch.  */
 831    if (tail) {
 832        if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
 833            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
 834        }
 835    } else {
 836        if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
 837            tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
 838        }
 839    }
 840}
 841
 842static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
 843{
 844    tcg_out_call_int(s, arg, false);
 845    tcg_out_nop(s);
 846}
 847
 848#if defined(CONFIG_SOFTMMU)
 849static void * const qemu_ld_helpers[16] = {
 850    [MO_UB]   = helper_ret_ldub_mmu,
 851    [MO_SB]   = helper_ret_ldsb_mmu,
 852    [MO_LEUW] = helper_le_lduw_mmu,
 853    [MO_LESW] = helper_le_ldsw_mmu,
 854    [MO_LEUL] = helper_le_ldul_mmu,
 855    [MO_LEQ]  = helper_le_ldq_mmu,
 856    [MO_BEUW] = helper_be_lduw_mmu,
 857    [MO_BESW] = helper_be_ldsw_mmu,
 858    [MO_BEUL] = helper_be_ldul_mmu,
 859    [MO_BEQ]  = helper_be_ldq_mmu,
 860};
 861
 862static void * const qemu_st_helpers[16] = {
 863    [MO_UB]   = helper_ret_stb_mmu,
 864    [MO_LEUW] = helper_le_stw_mmu,
 865    [MO_LEUL] = helper_le_stl_mmu,
 866    [MO_LEQ]  = helper_le_stq_mmu,
 867    [MO_BEUW] = helper_be_stw_mmu,
 868    [MO_BEUL] = helper_be_stl_mmu,
 869    [MO_BEQ]  = helper_be_stq_mmu,
 870};
 871
 872/* Helper routines for marshalling helper function arguments into
 873 * the correct registers and stack.
 874 * I is where we want to put this argument, and is updated and returned
 875 * for the next call. ARG is the argument itself.
 876 *
 877 * We provide routines for arguments which are: immediate, 32 bit
 878 * value in register, 16 and 8 bit values in register (which must be zero
 879 * extended before use) and 64 bit value in a lo:hi register pair.
 880 */
 881
 882static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
 883{
 884    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 885        tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
 886    } else {
 887        tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
 888    }
 889    return i + 1;
 890}
 891
 892static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
 893{
 894    TCGReg tmp = TCG_TMP0;
 895    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 896        tmp = tcg_target_call_iarg_regs[i];
 897    }
 898    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
 899    return tcg_out_call_iarg_reg(s, i, tmp);
 900}
 901
 902static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
 903{
 904    TCGReg tmp = TCG_TMP0;
 905    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 906        tmp = tcg_target_call_iarg_regs[i];
 907    }
 908    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
 909    return tcg_out_call_iarg_reg(s, i, tmp);
 910}
 911
 912static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
 913{
 914    TCGReg tmp = TCG_TMP0;
 915    if (arg == 0) {
 916        tmp = TCG_REG_ZERO;
 917    } else {
 918        if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 919            tmp = tcg_target_call_iarg_regs[i];
 920        }
 921        tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
 922    }
 923    return tcg_out_call_iarg_reg(s, i, tmp);
 924}
 925
 926static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
 927{
 928    i = (i + 1) & ~1;
 929    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
 930    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
 931    return i;
 932}
 933
 934/* Perform the tlb comparison operation.  The complete host address is
 935   placed in BASE.  Clobbers AT, T0, A0.  */
 936static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
 937                             TCGReg addrh, int mem_index, TCGMemOp s_bits,
 938                             tcg_insn_unit *label_ptr[2], bool is_load)
 939{
 940    int cmp_off
 941        = (is_load
 942           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
 943           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
 944    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
 945
 946    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
 947                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 948    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
 949                    (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
 950    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
 951
 952    /* Compensate for very large offsets.  */
 953    if (add_off >= 0x8000) {
 954        /* Most target env are smaller than 32k; none are larger than 64k.
 955           Simplify the logic here merely to offset by 0x7ff0, giving us a
 956           range just shy of 64k.  Check this assumption.  */
 957        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
 958                                   tlb_table[NB_MMU_MODES - 1][1])
 959                          > 0x7ff0 + 0x7fff);
 960        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
 961        cmp_off -= 0x7ff0;
 962        add_off -= 0x7ff0;
 963    }
 964
 965    /* Load the tlb comparator.  */
 966    if (TARGET_LONG_BITS == 64) {
 967        tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF);
 968        tcg_out_opc_imm(s, OPC_LW, base, TCG_REG_A0, cmp_off + HI_OFF);
 969    } else {
 970        tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off);
 971    }
 972
 973    /* Mask the page bits, keeping the alignment bits to compare against.
 974       In between, load the tlb addend for the fast path.  */
 975    tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
 976                 TARGET_PAGE_MASK | ((1 << s_bits) - 1));
 977    tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
 978    tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
 979
 980    label_ptr[0] = s->code_ptr;
 981    tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
 982
 983    if (TARGET_LONG_BITS == 64) {
 984        /* delay slot */
 985        tcg_out_nop(s);
 986
 987        label_ptr[1] = s->code_ptr;
 988        tcg_out_opc_br(s, OPC_BNE, addrh, base);
 989    }
 990
 991    /* delay slot */
 992    tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl);
 993}
 994
 995static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
 996                                TCGReg datalo, TCGReg datahi,
 997                                TCGReg addrlo, TCGReg addrhi,
 998                                void *raddr, tcg_insn_unit *label_ptr[2])
 999{
1000    TCGLabelQemuLdst *label = new_ldst_label(s);
1001
1002    label->is_ld = is_ld;
1003    label->oi = oi;
1004    label->datalo_reg = datalo;
1005    label->datahi_reg = datahi;
1006    label->addrlo_reg = addrlo;
1007    label->addrhi_reg = addrhi;
1008    label->raddr = raddr;
1009    label->label_ptr[0] = label_ptr[0];
1010    if (TARGET_LONG_BITS == 64) {
1011        label->label_ptr[1] = label_ptr[1];
1012    }
1013}
1014
1015static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1016{
1017    TCGMemOpIdx oi = l->oi;
1018    TCGMemOp opc = get_memop(oi);
1019    TCGReg v0;
1020    int i;
1021
1022    /* resolve label address */
1023    reloc_pc16(l->label_ptr[0], s->code_ptr);
1024    if (TARGET_LONG_BITS == 64) {
1025        reloc_pc16(l->label_ptr[1], s->code_ptr);
1026    }
1027
1028    i = 1;
1029    if (TARGET_LONG_BITS == 64) {
1030        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1031    } else {
1032        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1033    }
1034    i = tcg_out_call_iarg_imm(s, i, oi);
1035    i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
1036    tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
1037    /* delay slot */
1038    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1039
1040    v0 = l->datalo_reg;
1041    if ((opc & MO_SIZE) == MO_64) {
1042        /* We eliminated V0 from the possible output registers, so it
1043           cannot be clobbered here.  So we must move V1 first.  */
1044        if (MIPS_BE) {
1045            tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1046            v0 = l->datahi_reg;
1047        } else {
1048            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1049        }
1050    }
1051
1052    reloc_pc16(s->code_ptr, l->raddr);
1053    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1054    /* delay slot */
1055    tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
1056}
1057
1058static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1059{
1060    TCGMemOpIdx oi = l->oi;
1061    TCGMemOp opc = get_memop(oi);
1062    TCGMemOp s_bits = opc & MO_SIZE;
1063    int i;
1064
1065    /* resolve label address */
1066    reloc_pc16(l->label_ptr[0], s->code_ptr);
1067    if (TARGET_LONG_BITS == 64) {
1068        reloc_pc16(l->label_ptr[1], s->code_ptr);
1069    }
1070
1071    i = 1;
1072    if (TARGET_LONG_BITS == 64) {
1073        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1074    } else {
1075        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1076    }
1077    switch (s_bits) {
1078    case MO_8:
1079        i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1080        break;
1081    case MO_16:
1082        i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1083        break;
1084    case MO_32:
1085        i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1086        break;
1087    case MO_64:
1088        i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1089        break;
1090    default:
1091        tcg_abort();
1092    }
1093    i = tcg_out_call_iarg_imm(s, i, oi);
1094
1095    /* Tail call to the store helper.  Thus force the return address
1096       computation to take place in the return address register.  */
1097    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1098    i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
1099    tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
1100    /* delay slot */
1101    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1102}
1103#endif
1104
1105static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1106                                   TCGReg base, TCGMemOp opc)
1107{
1108    switch (opc & (MO_SSIZE | MO_BSWAP)) {
1109    case MO_UB:
1110        tcg_out_opc_imm(s, OPC_LBU, datalo, base, 0);
1111        break;
1112    case MO_SB:
1113        tcg_out_opc_imm(s, OPC_LB, datalo, base, 0);
1114        break;
1115    case MO_UW | MO_BSWAP:
1116        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1117        tcg_out_bswap16(s, datalo, TCG_TMP1);
1118        break;
1119    case MO_UW:
1120        tcg_out_opc_imm(s, OPC_LHU, datalo, base, 0);
1121        break;
1122    case MO_SW | MO_BSWAP:
1123        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1124        tcg_out_bswap16s(s, datalo, TCG_TMP1);
1125        break;
1126    case MO_SW:
1127        tcg_out_opc_imm(s, OPC_LH, datalo, base, 0);
1128        break;
1129    case MO_UL | MO_BSWAP:
1130        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 0);
1131        tcg_out_bswap32(s, datalo, TCG_TMP1);
1132        break;
1133    case MO_UL:
1134        tcg_out_opc_imm(s, OPC_LW, datalo, base, 0);
1135        break;
1136    case MO_Q | MO_BSWAP:
1137        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, HI_OFF);
1138        tcg_out_bswap32(s, datalo, TCG_TMP1);
1139        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, LO_OFF);
1140        tcg_out_bswap32(s, datahi, TCG_TMP1);
1141        break;
1142    case MO_Q:
1143        tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF);
1144        tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF);
1145        break;
1146    default:
1147        tcg_abort();
1148    }
1149}
1150
1151static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1152{
1153    TCGReg addr_regl, addr_regh __attribute__((unused));
1154    TCGReg data_regl, data_regh;
1155    TCGMemOpIdx oi;
1156    TCGMemOp opc;
1157#if defined(CONFIG_SOFTMMU)
1158    tcg_insn_unit *label_ptr[2];
1159    int mem_index;
1160    TCGMemOp s_bits;
1161#endif
1162    /* Note that we've eliminated V0 from the output registers,
1163       so we won't overwrite the base register during loading.  */
1164    TCGReg base = TCG_REG_V0;
1165
1166    data_regl = *args++;
1167    data_regh = (is_64 ? *args++ : 0);
1168    addr_regl = *args++;
1169    addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1170    oi = *args++;
1171    opc = get_memop(oi);
1172
1173#if defined(CONFIG_SOFTMMU)
1174    mem_index = get_mmuidx(oi);
1175    s_bits = opc & MO_SIZE;
1176
1177    tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
1178                     s_bits, label_ptr, 1);
1179    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1180    add_qemu_ldst_label(s, 1, oi, data_regl, data_regh, addr_regl, addr_regh,
1181                        s->code_ptr, label_ptr);
1182#else
1183    if (GUEST_BASE == 0 && data_regl != addr_regl) {
1184        base = addr_regl;
1185    } else if (GUEST_BASE == (int16_t)GUEST_BASE) {
1186        tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, GUEST_BASE);
1187    } else {
1188        tcg_out_movi(s, TCG_TYPE_PTR, base, GUEST_BASE);
1189        tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
1190    }
1191    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1192#endif
1193}
1194
1195static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1196                                   TCGReg base, TCGMemOp opc)
1197{
1198    switch (opc & (MO_SIZE | MO_BSWAP)) {
1199    case MO_8:
1200        tcg_out_opc_imm(s, OPC_SB, datalo, base, 0);
1201        break;
1202
1203    case MO_16 | MO_BSWAP:
1204        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, datalo, 0xffff);
1205        tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
1206        datalo = TCG_TMP1;
1207        /* FALLTHRU */
1208    case MO_16:
1209        tcg_out_opc_imm(s, OPC_SH, datalo, base, 0);
1210        break;
1211
1212    case MO_32 | MO_BSWAP:
1213        tcg_out_bswap32(s, TCG_TMP1, datalo);
1214        datalo = TCG_TMP1;
1215        /* FALLTHRU */
1216    case MO_32:
1217        tcg_out_opc_imm(s, OPC_SW, datalo, base, 0);
1218        break;
1219
1220    case MO_64 | MO_BSWAP:
1221        tcg_out_bswap32(s, TCG_TMP1, datalo);
1222        tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, HI_OFF);
1223        tcg_out_bswap32(s, TCG_TMP1, datahi);
1224        tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, LO_OFF);
1225        break;
1226    case MO_64:
1227        tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF);
1228        tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF);
1229        break;
1230
1231    default:
1232        tcg_abort();
1233    }
1234}
1235
1236static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
1237                            TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
1238                            bool cbh, bool is_sub)
1239{
1240    TCGReg th = TCG_TMP1;
1241
1242    /* If we have a negative constant such that negating it would
1243       make the high part zero, we can (usually) eliminate one insn.  */
1244    if (cbl && cbh && bh == -1 && bl != 0) {
1245        bl = -bl;
1246        bh = 0;
1247        is_sub = !is_sub;
1248    }
1249
1250    /* By operating on the high part first, we get to use the final
1251       carry operation to move back from the temporary.  */
1252    if (!cbh) {
1253        tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
1254    } else if (bh != 0 || ah == rl) {
1255        tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
1256    } else {
1257        th = ah;
1258    }
1259
1260    /* Note that tcg optimization should eliminate the bl == 0 case.  */
1261    if (is_sub) {
1262        if (cbl) {
1263            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
1264            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
1265        } else {
1266            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
1267            tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
1268        }
1269        tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
1270    } else {
1271        if (cbl) {
1272            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
1273            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
1274        } else if (rl == al && rl == bl) {
1275            tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
1276            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
1277        } else {
1278            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
1279            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
1280        }
1281        tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
1282    }
1283}
1284
1285static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1286{
1287    TCGReg addr_regl, addr_regh __attribute__((unused));
1288    TCGReg data_regl, data_regh, base;
1289    TCGMemOpIdx oi;
1290    TCGMemOp opc;
1291#if defined(CONFIG_SOFTMMU)
1292    tcg_insn_unit *label_ptr[2];
1293    int mem_index;
1294    TCGMemOp s_bits;
1295#endif
1296
1297    data_regl = *args++;
1298    data_regh = (is_64 ? *args++ : 0);
1299    addr_regl = *args++;
1300    addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1301    oi = *args++;
1302    opc = get_memop(oi);
1303
1304#if defined(CONFIG_SOFTMMU)
1305    mem_index = get_mmuidx(oi);
1306    s_bits = opc & 3;
1307
1308    /* Note that we eliminated the helper's address argument,
1309       so we can reuse that for the base.  */
1310    base = (TARGET_LONG_BITS == 32 ? TCG_REG_A1 : TCG_REG_A2);
1311    tcg_out_tlb_load(s, base, addr_regl, addr_regh, mem_index,
1312                     s_bits, label_ptr, 0);
1313    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1314    add_qemu_ldst_label(s, 0, oi, data_regl, data_regh, addr_regl, addr_regh,
1315                        s->code_ptr, label_ptr);
1316#else
1317    if (GUEST_BASE == 0) {
1318        base = addr_regl;
1319    } else {
1320        base = TCG_REG_A0;
1321        if (GUEST_BASE == (int16_t)GUEST_BASE) {
1322            tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, GUEST_BASE);
1323        } else {
1324            tcg_out_movi(s, TCG_TYPE_PTR, base, GUEST_BASE);
1325            tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
1326        }
1327    }
1328    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1329#endif
1330}
1331
1332static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1333                              const TCGArg *args, const int *const_args)
1334{
1335    MIPSInsn i1, i2;
1336    TCGArg a0, a1, a2;
1337    int c2;
1338
1339    a0 = args[0];
1340    a1 = args[1];
1341    a2 = args[2];
1342    c2 = const_args[2];
1343
1344    switch (opc) {
1345    case INDEX_op_exit_tb:
1346        {
1347            TCGReg b0 = TCG_REG_ZERO;
1348
1349            if (a0 & ~0xffff) {
1350                tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1351                b0 = TCG_REG_V0;
1352            }
1353            if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1354                tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
1355                             (uintptr_t)tb_ret_addr);
1356                tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1357            }
1358            tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
1359        }
1360        break;
1361    case INDEX_op_goto_tb:
1362        if (s->tb_jmp_offset) {
1363            /* direct jump method */
1364            s->tb_jmp_offset[a0] = tcg_current_code_size(s);
1365            /* Avoid clobbering the address during retranslation.  */
1366            tcg_out32(s, OPC_J | (*(uint32_t *)s->code_ptr & 0x3ffffff));
1367        } else {
1368            /* indirect jump method */
1369            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
1370                       (uintptr_t)(s->tb_next + a0));
1371            tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1372        }
1373        tcg_out_nop(s);
1374        s->tb_next_offset[a0] = tcg_current_code_size(s);
1375        break;
1376    case INDEX_op_br:
1377        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
1378                       arg_label(a0));
1379        break;
1380
1381    case INDEX_op_ld8u_i32:
1382        i1 = OPC_LBU;
1383        goto do_ldst;
1384    case INDEX_op_ld8s_i32:
1385        i1 = OPC_LB;
1386        goto do_ldst;
1387    case INDEX_op_ld16u_i32:
1388        i1 = OPC_LHU;
1389        goto do_ldst;
1390    case INDEX_op_ld16s_i32:
1391        i1 = OPC_LH;
1392        goto do_ldst;
1393    case INDEX_op_ld_i32:
1394        i1 = OPC_LW;
1395        goto do_ldst;
1396    case INDEX_op_st8_i32:
1397        i1 = OPC_SB;
1398        goto do_ldst;
1399    case INDEX_op_st16_i32:
1400        i1 = OPC_SH;
1401        goto do_ldst;
1402    case INDEX_op_st_i32:
1403        i1 = OPC_SW;
1404    do_ldst:
1405        tcg_out_ldst(s, i1, a0, a1, a2);
1406        break;
1407
1408    case INDEX_op_add_i32:
1409        i1 = OPC_ADDU, i2 = OPC_ADDIU;
1410        goto do_binary;
1411    case INDEX_op_or_i32:
1412        i1 = OPC_OR, i2 = OPC_ORI;
1413        goto do_binary;
1414    case INDEX_op_xor_i32:
1415        i1 = OPC_XOR, i2 = OPC_XORI;
1416    do_binary:
1417        if (c2) {
1418            tcg_out_opc_imm(s, i2, a0, a1, a2);
1419            break;
1420        }
1421    do_binaryv:
1422        tcg_out_opc_reg(s, i1, a0, a1, a2);
1423        break;
1424
1425    case INDEX_op_sub_i32:
1426        if (c2) {
1427            tcg_out_opc_imm(s, OPC_ADDIU, a0, a1, -a2);
1428            break;
1429        }
1430        i1 = OPC_SUBU;
1431        goto do_binary;
1432    case INDEX_op_and_i32:
1433        if (c2 && a2 != (uint16_t)a2) {
1434            int msb = ctz32(~a2) - 1;
1435            assert(use_mips32r2_instructions);
1436            assert(is_p2m1(a2));
1437            tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1438            break;
1439        }
1440        i1 = OPC_AND, i2 = OPC_ANDI;
1441        goto do_binary;
1442    case INDEX_op_nor_i32:
1443        i1 = OPC_NOR;
1444        goto do_binaryv;
1445
1446    case INDEX_op_mul_i32:
1447        if (use_mips32_instructions) {
1448            tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1449            break;
1450        }
1451        i1 = OPC_MULT, i2 = OPC_MFLO;
1452        goto do_hilo1;
1453    case INDEX_op_mulsh_i32:
1454        i1 = OPC_MULT, i2 = OPC_MFHI;
1455        goto do_hilo1;
1456    case INDEX_op_muluh_i32:
1457        i1 = OPC_MULTU, i2 = OPC_MFHI;
1458        goto do_hilo1;
1459    case INDEX_op_div_i32:
1460        i1 = OPC_DIV, i2 = OPC_MFLO;
1461        goto do_hilo1;
1462    case INDEX_op_divu_i32:
1463        i1 = OPC_DIVU, i2 = OPC_MFLO;
1464        goto do_hilo1;
1465    case INDEX_op_rem_i32:
1466        i1 = OPC_DIV, i2 = OPC_MFHI;
1467        goto do_hilo1;
1468    case INDEX_op_remu_i32:
1469        i1 = OPC_DIVU, i2 = OPC_MFHI;
1470    do_hilo1:
1471        tcg_out_opc_reg(s, i1, 0, a1, a2);
1472        tcg_out_opc_reg(s, i2, a0, 0, 0);
1473        break;
1474
1475    case INDEX_op_muls2_i32:
1476        i1 = OPC_MULT;
1477        goto do_hilo2;
1478    case INDEX_op_mulu2_i32:
1479        i1 = OPC_MULTU;
1480    do_hilo2:
1481        tcg_out_opc_reg(s, i1, 0, a2, args[3]);
1482        tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1483        tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1484        break;
1485
1486    case INDEX_op_not_i32:
1487        i1 = OPC_NOR;
1488        goto do_unary;
1489    case INDEX_op_bswap16_i32:
1490        i1 = OPC_WSBH;
1491        goto do_unary;
1492    case INDEX_op_ext8s_i32:
1493        i1 = OPC_SEB;
1494        goto do_unary;
1495    case INDEX_op_ext16s_i32:
1496        i1 = OPC_SEH;
1497    do_unary:
1498        tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
1499        break;
1500
1501    case INDEX_op_sar_i32:
1502        i1 = OPC_SRAV, i2 = OPC_SRA;
1503        goto do_shift;
1504    case INDEX_op_shl_i32:
1505        i1 = OPC_SLLV, i2 = OPC_SLL;
1506        goto do_shift;
1507    case INDEX_op_shr_i32:
1508        i1 = OPC_SRLV, i2 = OPC_SRL;
1509        goto do_shift;
1510    case INDEX_op_rotr_i32:
1511        i1 = OPC_ROTRV, i2 = OPC_ROTR;
1512    do_shift:
1513        if (c2) {
1514            tcg_out_opc_sa(s, i2, a0, a1, a2);
1515        } else {
1516            tcg_out_opc_reg(s, i1, a0, a2, a1);
1517        }
1518        break;
1519    case INDEX_op_rotl_i32:
1520        if (c2) {
1521            tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
1522        } else {
1523            tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
1524            tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
1525        }
1526        break;
1527
1528    case INDEX_op_bswap32_i32:
1529        tcg_out_opc_reg(s, OPC_WSBH, a0, 0, a1);
1530        tcg_out_opc_sa(s, OPC_ROTR, a0, a0, 16);
1531        break;
1532
1533    case INDEX_op_deposit_i32:
1534        tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
1535        break;
1536
1537    case INDEX_op_brcond_i32:
1538        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
1539        break;
1540    case INDEX_op_brcond2_i32:
1541        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
1542        break;
1543
1544    case INDEX_op_movcond_i32:
1545        tcg_out_movcond(s, args[5], a0, a1, a2, args[3]);
1546        break;
1547
1548    case INDEX_op_setcond_i32:
1549        tcg_out_setcond(s, args[3], a0, a1, a2);
1550        break;
1551    case INDEX_op_setcond2_i32:
1552        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
1553        break;
1554
1555    case INDEX_op_qemu_ld_i32:
1556        tcg_out_qemu_ld(s, args, false);
1557        break;
1558    case INDEX_op_qemu_ld_i64:
1559        tcg_out_qemu_ld(s, args, true);
1560        break;
1561    case INDEX_op_qemu_st_i32:
1562        tcg_out_qemu_st(s, args, false);
1563        break;
1564    case INDEX_op_qemu_st_i64:
1565        tcg_out_qemu_st(s, args, true);
1566        break;
1567
1568    case INDEX_op_add2_i32:
1569        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1570                        const_args[4], const_args[5], false);
1571        break;
1572    case INDEX_op_sub2_i32:
1573        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1574                        const_args[4], const_args[5], true);
1575        break;
1576
1577    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
1578    case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
1579    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
1580    default:
1581        tcg_abort();
1582    }
1583}
1584
1585static const TCGTargetOpDef mips_op_defs[] = {
1586    { INDEX_op_exit_tb, { } },
1587    { INDEX_op_goto_tb, { } },
1588    { INDEX_op_br, { } },
1589
1590    { INDEX_op_ld8u_i32, { "r", "r" } },
1591    { INDEX_op_ld8s_i32, { "r", "r" } },
1592    { INDEX_op_ld16u_i32, { "r", "r" } },
1593    { INDEX_op_ld16s_i32, { "r", "r" } },
1594    { INDEX_op_ld_i32, { "r", "r" } },
1595    { INDEX_op_st8_i32, { "rZ", "r" } },
1596    { INDEX_op_st16_i32, { "rZ", "r" } },
1597    { INDEX_op_st_i32, { "rZ", "r" } },
1598
1599    { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1600    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1601    { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
1602    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1603    { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1604    { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
1605    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1606    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1607    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1608    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1609    { INDEX_op_sub_i32, { "r", "rZ", "rN" } },
1610
1611    { INDEX_op_and_i32, { "r", "rZ", "rIK" } },
1612    { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1613    { INDEX_op_not_i32, { "r", "rZ" } },
1614    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1615    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1616
1617    { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1618    { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1619    { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
1620    { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1621    { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
1622
1623    { INDEX_op_bswap16_i32, { "r", "r" } },
1624    { INDEX_op_bswap32_i32, { "r", "r" } },
1625
1626    { INDEX_op_ext8s_i32, { "r", "rZ" } },
1627    { INDEX_op_ext16s_i32, { "r", "rZ" } },
1628
1629    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1630
1631    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1632    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
1633    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1634    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1635
1636    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1637    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1638    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1639
1640#if TARGET_LONG_BITS == 32
1641    { INDEX_op_qemu_ld_i32, { "L", "lZ" } },
1642    { INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
1643    { INDEX_op_qemu_ld_i64, { "L", "L", "lZ" } },
1644    { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
1645#else
1646    { INDEX_op_qemu_ld_i32, { "L", "lZ", "lZ" } },
1647    { INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
1648    { INDEX_op_qemu_ld_i64, { "L", "L", "lZ", "lZ" } },
1649    { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ", "SZ" } },
1650#endif
1651    { -1 },
1652};
1653
1654static int tcg_target_callee_save_regs[] = {
1655    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
1656    TCG_REG_S1,
1657    TCG_REG_S2,
1658    TCG_REG_S3,
1659    TCG_REG_S4,
1660    TCG_REG_S5,
1661    TCG_REG_S6,
1662    TCG_REG_S7,
1663    TCG_REG_S8,
1664    TCG_REG_RA,       /* should be last for ABI compliance */
1665};
1666
1667/* The Linux kernel doesn't provide any information about the available
1668   instruction set. Probe it using a signal handler. */
1669
1670#include <signal.h>
1671
1672#ifndef use_movnz_instructions
1673bool use_movnz_instructions = false;
1674#endif
1675
1676#ifndef use_mips32_instructions
1677bool use_mips32_instructions = false;
1678#endif
1679
1680#ifndef use_mips32r2_instructions
1681bool use_mips32r2_instructions = false;
1682#endif
1683
1684static volatile sig_atomic_t got_sigill;
1685
1686static void sigill_handler(int signo, siginfo_t *si, void *data)
1687{
1688    /* Skip the faulty instruction */
1689    ucontext_t *uc = (ucontext_t *)data;
1690    uc->uc_mcontext.pc += 4;
1691
1692    got_sigill = 1;
1693}
1694
1695static void tcg_target_detect_isa(void)
1696{
1697    struct sigaction sa_old, sa_new;
1698
1699    memset(&sa_new, 0, sizeof(sa_new));
1700    sa_new.sa_flags = SA_SIGINFO;
1701    sa_new.sa_sigaction = sigill_handler;
1702    sigaction(SIGILL, &sa_new, &sa_old);
1703
1704    /* Probe for movn/movz, necessary to implement movcond. */
1705#ifndef use_movnz_instructions
1706    got_sigill = 0;
1707    asm volatile(".set push\n"
1708                 ".set mips32\n"
1709                 "movn $zero, $zero, $zero\n"
1710                 "movz $zero, $zero, $zero\n"
1711                 ".set pop\n"
1712                 : : : );
1713    use_movnz_instructions = !got_sigill;
1714#endif
1715
1716    /* Probe for MIPS32 instructions. As no subsetting is allowed
1717       by the specification, it is only necessary to probe for one
1718       of the instructions. */
1719#ifndef use_mips32_instructions
1720    got_sigill = 0;
1721    asm volatile(".set push\n"
1722                 ".set mips32\n"
1723                 "mul $zero, $zero\n"
1724                 ".set pop\n"
1725                 : : : );
1726    use_mips32_instructions = !got_sigill;
1727#endif
1728
1729    /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1730       available. As no subsetting is allowed by the specification,
1731       it is only necessary to probe for one of the instructions. */
1732#ifndef use_mips32r2_instructions
1733    if (use_mips32_instructions) {
1734        got_sigill = 0;
1735        asm volatile(".set push\n"
1736                     ".set mips32r2\n"
1737                     "seb $zero, $zero\n"
1738                     ".set pop\n"
1739                     : : : );
1740        use_mips32r2_instructions = !got_sigill;
1741    }
1742#endif
1743
1744    sigaction(SIGILL, &sa_old, NULL);
1745}
1746
1747/* Generate global QEMU prologue and epilogue code */
1748static void tcg_target_qemu_prologue(TCGContext *s)
1749{
1750    int i, frame_size;
1751
1752    /* reserve some stack space, also for TCG temps. */
1753    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1754                 + TCG_STATIC_CALL_ARGS_SIZE
1755                 + CPU_TEMP_BUF_NLONGS * sizeof(long);
1756    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1757                 ~(TCG_TARGET_STACK_ALIGN - 1);
1758    tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1759                  + TCG_STATIC_CALL_ARGS_SIZE,
1760                  CPU_TEMP_BUF_NLONGS * sizeof(long));
1761
1762    /* TB prologue */
1763    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1764    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1765        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1766                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1767    }
1768
1769    /* Call generated code */
1770    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1771    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1772    tb_ret_addr = s->code_ptr;
1773
1774    /* TB epilogue */
1775    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1776        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1777                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1778    }
1779
1780    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1781    tcg_out_addi(s, TCG_REG_SP, frame_size);
1782}
1783
1784static void tcg_target_init(TCGContext *s)
1785{
1786    tcg_target_detect_isa();
1787    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1788    tcg_regset_set(tcg_target_call_clobber_regs,
1789                   (1 << TCG_REG_V0) |
1790                   (1 << TCG_REG_V1) |
1791                   (1 << TCG_REG_A0) |
1792                   (1 << TCG_REG_A1) |
1793                   (1 << TCG_REG_A2) |
1794                   (1 << TCG_REG_A3) |
1795                   (1 << TCG_REG_T0) |
1796                   (1 << TCG_REG_T1) |
1797                   (1 << TCG_REG_T2) |
1798                   (1 << TCG_REG_T3) |
1799                   (1 << TCG_REG_T4) |
1800                   (1 << TCG_REG_T5) |
1801                   (1 << TCG_REG_T6) |
1802                   (1 << TCG_REG_T7) |
1803                   (1 << TCG_REG_T8) |
1804                   (1 << TCG_REG_T9));
1805
1806    tcg_regset_clear(s->reserved_regs);
1807    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1808    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1809    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1810    tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);     /* internal use */
1811    tcg_regset_set_reg(s->reserved_regs, TCG_TMP1);     /* internal use */
1812    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1813    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1814    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);   /* global pointer */
1815
1816    tcg_add_target_add_op_defs(mips_op_defs);
1817}
1818
1819void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1820{
1821    uint32_t *ptr = (uint32_t *)jmp_addr;
1822    *ptr = deposit32(*ptr, 0, 26, addr >> 2);
1823    flush_icache_range(jmp_addr, jmp_addr + 4);
1824}
1825