qemu/tcg/mips/tcg-target.inc.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#ifdef CONFIG_DEBUG_TCG
  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 int 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    tcg_debug_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    tcg_debug_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    tcg_debug_assert(type == R_MIPS_PC16);
 154    tcg_debug_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_R5    = OPC_SPECIAL | 0x08,
 292    OPC_JALR     = OPC_SPECIAL | 0x09,
 293    OPC_MOVZ     = OPC_SPECIAL | 0x0A,
 294    OPC_MOVN     = OPC_SPECIAL | 0x0B,
 295    OPC_SYNC     = OPC_SPECIAL | 0x0F,
 296    OPC_MFHI     = OPC_SPECIAL | 0x10,
 297    OPC_MFLO     = OPC_SPECIAL | 0x12,
 298    OPC_MULT     = OPC_SPECIAL | 0x18,
 299    OPC_MUL_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x18,
 300    OPC_MUH      = OPC_SPECIAL | (0x03 <<  6) | 0x18,
 301    OPC_MULTU    = OPC_SPECIAL | 0x19,
 302    OPC_MULU     = OPC_SPECIAL | (0x02 <<  6) | 0x19,
 303    OPC_MUHU     = OPC_SPECIAL | (0x03 <<  6) | 0x19,
 304    OPC_DIV      = OPC_SPECIAL | 0x1A,
 305    OPC_DIV_R6   = OPC_SPECIAL | (0x02 <<  6) | 0x1A,
 306    OPC_MOD      = OPC_SPECIAL | (0x03 <<  6) | 0x1A,
 307    OPC_DIVU     = OPC_SPECIAL | 0x1B,
 308    OPC_DIVU_R6  = OPC_SPECIAL | (0x02 <<  6) | 0x1B,
 309    OPC_MODU     = OPC_SPECIAL | (0x03 <<  6) | 0x1B,
 310    OPC_ADDU     = OPC_SPECIAL | 0x21,
 311    OPC_SUBU     = OPC_SPECIAL | 0x23,
 312    OPC_AND      = OPC_SPECIAL | 0x24,
 313    OPC_OR       = OPC_SPECIAL | 0x25,
 314    OPC_XOR      = OPC_SPECIAL | 0x26,
 315    OPC_NOR      = OPC_SPECIAL | 0x27,
 316    OPC_SLT      = OPC_SPECIAL | 0x2A,
 317    OPC_SLTU     = OPC_SPECIAL | 0x2B,
 318    OPC_SELEQZ   = OPC_SPECIAL | 0x35,
 319    OPC_SELNEZ   = OPC_SPECIAL | 0x37,
 320
 321    OPC_REGIMM   = 0x01 << 26,
 322    OPC_BLTZ     = OPC_REGIMM | (0x00 << 16),
 323    OPC_BGEZ     = OPC_REGIMM | (0x01 << 16),
 324
 325    OPC_SPECIAL2 = 0x1c << 26,
 326    OPC_MUL_R5   = OPC_SPECIAL2 | 0x002,
 327
 328    OPC_SPECIAL3 = 0x1f << 26,
 329    OPC_EXT      = OPC_SPECIAL3 | 0x000,
 330    OPC_INS      = OPC_SPECIAL3 | 0x004,
 331    OPC_WSBH     = OPC_SPECIAL3 | 0x0a0,
 332    OPC_SEB      = OPC_SPECIAL3 | 0x420,
 333    OPC_SEH      = OPC_SPECIAL3 | 0x620,
 334
 335    /* MIPS r6 doesn't have JR, JALR should be used instead */
 336    OPC_JR       = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
 337
 338    /*
 339     * MIPS r6 replaces MUL with an alternative encoding which is
 340     * backwards-compatible at the assembly level.
 341     */
 342    OPC_MUL      = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
 343
 344    /* MIPS r6 introduced names for weaker variants of SYNC.  These are
 345       backward compatible to previous architecture revisions.  */
 346    OPC_SYNC_WMB     = OPC_SYNC | 0x04 << 5,
 347    OPC_SYNC_MB      = OPC_SYNC | 0x10 << 5,
 348    OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 5,
 349    OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 5,
 350    OPC_SYNC_RMB     = OPC_SYNC | 0x13 << 5,
 351} MIPSInsn;
 352
 353/*
 354 * Type reg
 355 */
 356static inline void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
 357                                   TCGReg rd, TCGReg rs, TCGReg rt)
 358{
 359    int32_t inst;
 360
 361    inst = opc;
 362    inst |= (rs & 0x1F) << 21;
 363    inst |= (rt & 0x1F) << 16;
 364    inst |= (rd & 0x1F) << 11;
 365    tcg_out32(s, inst);
 366}
 367
 368/*
 369 * Type immediate
 370 */
 371static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
 372                                   TCGReg rt, TCGReg rs, TCGArg imm)
 373{
 374    int32_t inst;
 375
 376    inst = opc;
 377    inst |= (rs & 0x1F) << 21;
 378    inst |= (rt & 0x1F) << 16;
 379    inst |= (imm & 0xffff);
 380    tcg_out32(s, inst);
 381}
 382
 383/*
 384 * Type bitfield
 385 */
 386static inline void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
 387                                  TCGReg rs, int msb, int lsb)
 388{
 389    int32_t inst;
 390
 391    inst = opc;
 392    inst |= (rs & 0x1F) << 21;
 393    inst |= (rt & 0x1F) << 16;
 394    inst |= (msb & 0x1F) << 11;
 395    inst |= (lsb & 0x1F) << 6;
 396    tcg_out32(s, inst);
 397}
 398
 399/*
 400 * Type branch
 401 */
 402static inline void tcg_out_opc_br(TCGContext *s, MIPSInsn opc,
 403                                  TCGReg rt, TCGReg rs)
 404{
 405    /* We pay attention here to not modify the branch target by reading
 406       the existing value and using it again. This ensure that caches and
 407       memory are kept coherent during retranslation. */
 408    uint16_t offset = (uint16_t)*s->code_ptr;
 409
 410    tcg_out_opc_imm(s, opc, rt, rs, offset);
 411}
 412
 413/*
 414 * Type sa
 415 */
 416static inline void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
 417                                  TCGReg rd, TCGReg rt, TCGArg sa)
 418{
 419    int32_t inst;
 420
 421    inst = opc;
 422    inst |= (rt & 0x1F) << 16;
 423    inst |= (rd & 0x1F) << 11;
 424    inst |= (sa & 0x1F) <<  6;
 425    tcg_out32(s, inst);
 426
 427}
 428
 429/*
 430 * Type jump.
 431 * Returns true if the branch was in range and the insn was emitted.
 432 */
 433static bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, void *target)
 434{
 435    uintptr_t dest = (uintptr_t)target;
 436    uintptr_t from = (uintptr_t)s->code_ptr + 4;
 437    int32_t inst;
 438
 439    /* The pc-region branch happens within the 256MB region of
 440       the delay slot (thus the +4).  */
 441    if ((from ^ dest) & -(1 << 28)) {
 442        return false;
 443    }
 444    tcg_debug_assert((dest & 3) == 0);
 445
 446    inst = opc;
 447    inst |= (dest >> 2) & 0x3ffffff;
 448    tcg_out32(s, inst);
 449    return true;
 450}
 451
 452static inline void tcg_out_nop(TCGContext *s)
 453{
 454    tcg_out32(s, 0);
 455}
 456
 457static inline void tcg_out_mov(TCGContext *s, TCGType type,
 458                               TCGReg ret, TCGReg arg)
 459{
 460    /* Simple reg-reg move, optimising out the 'do nothing' case */
 461    if (ret != arg) {
 462        tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
 463    }
 464}
 465
 466static inline void tcg_out_movi(TCGContext *s, TCGType type,
 467                                TCGReg reg, tcg_target_long arg)
 468{
 469    if (arg == (int16_t)arg) {
 470        tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
 471    } else if (arg == (uint16_t)arg) {
 472        tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
 473    } else {
 474        tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
 475        if (arg & 0xffff) {
 476            tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
 477        }
 478    }
 479}
 480
 481static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
 482{
 483    if (use_mips32r2_instructions) {
 484        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 485    } else {
 486        /* ret and arg can't be register at */
 487        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
 488            tcg_abort();
 489        }
 490
 491        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 492        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);
 493        tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);
 494        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 495    }
 496}
 497
 498static inline void tcg_out_bswap16s(TCGContext *s, TCGReg ret, TCGReg arg)
 499{
 500    if (use_mips32r2_instructions) {
 501        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 502        tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);
 503    } else {
 504        /* ret and arg can't be register at */
 505        if (ret == TCG_TMP0 || arg == TCG_TMP0) {
 506            tcg_abort();
 507        }
 508
 509        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 510        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 511        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
 512        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 513    }
 514}
 515
 516static inline void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg)
 517{
 518    if (use_mips32r2_instructions) {
 519        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
 520        tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
 521    } else {
 522        /* ret and arg must be different and can't be register at */
 523        if (ret == arg || ret == TCG_TMP0 || arg == TCG_TMP0) {
 524            tcg_abort();
 525        }
 526
 527        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 528
 529        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 24);
 530        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 531
 532        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, arg, 0xff00);
 533        tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
 534        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 535
 536        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);
 537        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0xff00);
 538        tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);
 539    }
 540}
 541
 542static inline void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
 543{
 544    if (use_mips32r2_instructions) {
 545        tcg_out_opc_reg(s, OPC_SEB, ret, 0, arg);
 546    } else {
 547        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);
 548        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 24);
 549    }
 550}
 551
 552static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
 553{
 554    if (use_mips32r2_instructions) {
 555        tcg_out_opc_reg(s, OPC_SEH, ret, 0, arg);
 556    } else {
 557        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 16);
 558        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);
 559    }
 560}
 561
 562static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
 563                         TCGReg addr, intptr_t ofs)
 564{
 565    int16_t lo = ofs;
 566    if (ofs != lo) {
 567        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
 568        if (addr != TCG_REG_ZERO) {
 569            tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
 570        }
 571        addr = TCG_TMP0;
 572    }
 573    tcg_out_opc_imm(s, opc, data, addr, lo);
 574}
 575
 576static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
 577                              TCGReg arg1, intptr_t arg2)
 578{
 579    tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
 580}
 581
 582static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
 583                              TCGReg arg1, intptr_t arg2)
 584{
 585    tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
 586}
 587
 588static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
 589                               TCGReg base, intptr_t ofs)
 590{
 591    if (val == 0) {
 592        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
 593        return true;
 594    }
 595    return false;
 596}
 597
 598static inline void tcg_out_addi(TCGContext *s, TCGReg reg, TCGArg val)
 599{
 600    if (val == (int16_t)val) {
 601        tcg_out_opc_imm(s, OPC_ADDIU, reg, reg, val);
 602    } else {
 603        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
 604        tcg_out_opc_reg(s, OPC_ADDU, reg, reg, TCG_TMP0);
 605    }
 606}
 607
 608static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
 609                            TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
 610                            bool cbh, bool is_sub)
 611{
 612    TCGReg th = TCG_TMP1;
 613
 614    /* If we have a negative constant such that negating it would
 615       make the high part zero, we can (usually) eliminate one insn.  */
 616    if (cbl && cbh && bh == -1 && bl != 0) {
 617        bl = -bl;
 618        bh = 0;
 619        is_sub = !is_sub;
 620    }
 621
 622    /* By operating on the high part first, we get to use the final
 623       carry operation to move back from the temporary.  */
 624    if (!cbh) {
 625        tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
 626    } else if (bh != 0 || ah == rl) {
 627        tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
 628    } else {
 629        th = ah;
 630    }
 631
 632    /* Note that tcg optimization should eliminate the bl == 0 case.  */
 633    if (is_sub) {
 634        if (cbl) {
 635            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
 636            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
 637        } else {
 638            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
 639            tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
 640        }
 641        tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
 642    } else {
 643        if (cbl) {
 644            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
 645            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
 646        } else if (rl == al && rl == bl) {
 647            tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, 31);
 648            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
 649        } else {
 650            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
 651            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
 652        }
 653        tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
 654    }
 655}
 656
 657/* Bit 0 set if inversion required; bit 1 set if swapping required.  */
 658#define MIPS_CMP_INV  1
 659#define MIPS_CMP_SWAP 2
 660
 661static const uint8_t mips_cmp_map[16] = {
 662    [TCG_COND_LT]  = 0,
 663    [TCG_COND_LTU] = 0,
 664    [TCG_COND_GE]  = MIPS_CMP_INV,
 665    [TCG_COND_GEU] = MIPS_CMP_INV,
 666    [TCG_COND_LE]  = MIPS_CMP_INV | MIPS_CMP_SWAP,
 667    [TCG_COND_LEU] = MIPS_CMP_INV | MIPS_CMP_SWAP,
 668    [TCG_COND_GT]  = MIPS_CMP_SWAP,
 669    [TCG_COND_GTU] = MIPS_CMP_SWAP,
 670};
 671
 672static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
 673                            TCGReg arg1, TCGReg arg2)
 674{
 675    MIPSInsn s_opc = OPC_SLTU;
 676    int cmp_map;
 677
 678    switch (cond) {
 679    case TCG_COND_EQ:
 680        if (arg2 != 0) {
 681            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
 682            arg1 = ret;
 683        }
 684        tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, 1);
 685        break;
 686
 687    case TCG_COND_NE:
 688        if (arg2 != 0) {
 689            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
 690            arg1 = ret;
 691        }
 692        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, arg1);
 693        break;
 694
 695    case TCG_COND_LT:
 696    case TCG_COND_GE:
 697    case TCG_COND_LE:
 698    case TCG_COND_GT:
 699        s_opc = OPC_SLT;
 700        /* FALLTHRU */
 701
 702    case TCG_COND_LTU:
 703    case TCG_COND_GEU:
 704    case TCG_COND_LEU:
 705    case TCG_COND_GTU:
 706        cmp_map = mips_cmp_map[cond];
 707        if (cmp_map & MIPS_CMP_SWAP) {
 708            TCGReg t = arg1;
 709            arg1 = arg2;
 710            arg2 = t;
 711        }
 712        tcg_out_opc_reg(s, s_opc, ret, arg1, arg2);
 713        if (cmp_map & MIPS_CMP_INV) {
 714            tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
 715        }
 716        break;
 717
 718     default:
 719         tcg_abort();
 720         break;
 721     }
 722}
 723
 724static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
 725                           TCGReg arg2, TCGLabel *l)
 726{
 727    static const MIPSInsn b_zero[16] = {
 728        [TCG_COND_LT] = OPC_BLTZ,
 729        [TCG_COND_GT] = OPC_BGTZ,
 730        [TCG_COND_LE] = OPC_BLEZ,
 731        [TCG_COND_GE] = OPC_BGEZ,
 732    };
 733
 734    MIPSInsn s_opc = OPC_SLTU;
 735    MIPSInsn b_opc;
 736    int cmp_map;
 737
 738    switch (cond) {
 739    case TCG_COND_EQ:
 740        b_opc = OPC_BEQ;
 741        break;
 742    case TCG_COND_NE:
 743        b_opc = OPC_BNE;
 744        break;
 745
 746    case TCG_COND_LT:
 747    case TCG_COND_GT:
 748    case TCG_COND_LE:
 749    case TCG_COND_GE:
 750        if (arg2 == 0) {
 751            b_opc = b_zero[cond];
 752            arg2 = arg1;
 753            arg1 = 0;
 754            break;
 755        }
 756        s_opc = OPC_SLT;
 757        /* FALLTHRU */
 758
 759    case TCG_COND_LTU:
 760    case TCG_COND_GTU:
 761    case TCG_COND_LEU:
 762    case TCG_COND_GEU:
 763        cmp_map = mips_cmp_map[cond];
 764        if (cmp_map & MIPS_CMP_SWAP) {
 765            TCGReg t = arg1;
 766            arg1 = arg2;
 767            arg2 = t;
 768        }
 769        tcg_out_opc_reg(s, s_opc, TCG_TMP0, arg1, arg2);
 770        b_opc = (cmp_map & MIPS_CMP_INV ? OPC_BEQ : OPC_BNE);
 771        arg1 = TCG_TMP0;
 772        arg2 = TCG_REG_ZERO;
 773        break;
 774
 775    default:
 776        tcg_abort();
 777        break;
 778    }
 779
 780    tcg_out_opc_br(s, b_opc, arg1, arg2);
 781    if (l->has_value) {
 782        reloc_pc16(s->code_ptr - 1, l->u.value_ptr);
 783    } else {
 784        tcg_out_reloc(s, s->code_ptr - 1, R_MIPS_PC16, l, 0);
 785    }
 786    tcg_out_nop(s);
 787}
 788
 789static TCGReg tcg_out_reduce_eq2(TCGContext *s, TCGReg tmp0, TCGReg tmp1,
 790                                 TCGReg al, TCGReg ah,
 791                                 TCGReg bl, TCGReg bh)
 792{
 793    /* Merge highpart comparison into AH.  */
 794    if (bh != 0) {
 795        if (ah != 0) {
 796            tcg_out_opc_reg(s, OPC_XOR, tmp0, ah, bh);
 797            ah = tmp0;
 798        } else {
 799            ah = bh;
 800        }
 801    }
 802    /* Merge lowpart comparison into AL.  */
 803    if (bl != 0) {
 804        if (al != 0) {
 805            tcg_out_opc_reg(s, OPC_XOR, tmp1, al, bl);
 806            al = tmp1;
 807        } else {
 808            al = bl;
 809        }
 810    }
 811    /* Merge high and low part comparisons into AL.  */
 812    if (ah != 0) {
 813        if (al != 0) {
 814            tcg_out_opc_reg(s, OPC_OR, tmp0, ah, al);
 815            al = tmp0;
 816        } else {
 817            al = ah;
 818        }
 819    }
 820    return al;
 821}
 822
 823static void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
 824                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
 825{
 826    TCGReg tmp0 = TCG_TMP0;
 827    TCGReg tmp1 = ret;
 828
 829    tcg_debug_assert(ret != TCG_TMP0);
 830    if (ret == ah || ret == bh) {
 831        tcg_debug_assert(ret != TCG_TMP1);
 832        tmp1 = TCG_TMP1;
 833    }
 834
 835    switch (cond) {
 836    case TCG_COND_EQ:
 837    case TCG_COND_NE:
 838        tmp1 = tcg_out_reduce_eq2(s, tmp0, tmp1, al, ah, bl, bh);
 839        tcg_out_setcond(s, cond, ret, tmp1, TCG_REG_ZERO);
 840        break;
 841
 842    default:
 843        tcg_out_setcond(s, TCG_COND_EQ, tmp0, ah, bh);
 844        tcg_out_setcond(s, tcg_unsigned_cond(cond), tmp1, al, bl);
 845        tcg_out_opc_reg(s, OPC_AND, tmp1, tmp1, tmp0);
 846        tcg_out_setcond(s, tcg_high_cond(cond), tmp0, ah, bh);
 847        tcg_out_opc_reg(s, OPC_OR, ret, tmp1, tmp0);
 848        break;
 849    }
 850}
 851
 852static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
 853                            TCGReg bl, TCGReg bh, TCGLabel *l)
 854{
 855    TCGCond b_cond = TCG_COND_NE;
 856    TCGReg tmp = TCG_TMP1;
 857
 858    /* With branches, we emit between 4 and 9 insns with 2 or 3 branches.
 859       With setcond, we emit between 3 and 10 insns and only 1 branch,
 860       which ought to get better branch prediction.  */
 861     switch (cond) {
 862     case TCG_COND_EQ:
 863     case TCG_COND_NE:
 864        b_cond = cond;
 865        tmp = tcg_out_reduce_eq2(s, TCG_TMP0, TCG_TMP1, al, ah, bl, bh);
 866        break;
 867
 868    default:
 869        /* Minimize code size by preferring a compare not requiring INV.  */
 870        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
 871            cond = tcg_invert_cond(cond);
 872            b_cond = TCG_COND_EQ;
 873        }
 874        tcg_out_setcond2(s, cond, tmp, al, ah, bl, bh);
 875        break;
 876    }
 877
 878    tcg_out_brcond(s, b_cond, tmp, TCG_REG_ZERO, l);
 879}
 880
 881static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
 882                            TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
 883{
 884    bool eqz = false;
 885
 886    /* If one of the values is zero, put it last to match SEL*Z instructions */
 887    if (use_mips32r6_instructions && v1 == 0) {
 888        v1 = v2;
 889        v2 = 0;
 890        cond = tcg_invert_cond(cond);
 891    }
 892
 893    switch (cond) {
 894    case TCG_COND_EQ:
 895        eqz = true;
 896        /* FALLTHRU */
 897    case TCG_COND_NE:
 898        if (c2 != 0) {
 899            tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, c1, c2);
 900            c1 = TCG_TMP0;
 901        }
 902        break;
 903
 904    default:
 905        /* Minimize code size by preferring a compare not requiring INV.  */
 906        if (mips_cmp_map[cond] & MIPS_CMP_INV) {
 907            cond = tcg_invert_cond(cond);
 908            eqz = true;
 909        }
 910        tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
 911        c1 = TCG_TMP0;
 912        break;
 913    }
 914
 915    if (use_mips32r6_instructions) {
 916        MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
 917        MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
 918
 919        if (v2 != 0) {
 920            tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
 921        }
 922        tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
 923        if (v2 != 0) {
 924            tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
 925        }
 926    } else {
 927        MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
 928
 929        tcg_out_opc_reg(s, m_opc, ret, v1, c1);
 930
 931        /* This should be guaranteed via constraints */
 932        tcg_debug_assert(v2 == ret);
 933    }
 934}
 935
 936static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
 937{
 938    /* Note that the ABI requires the called function's address to be
 939       loaded into T9, even if a direct branch is in range.  */
 940    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
 941
 942    /* But do try a direct branch, allowing the cpu better insn prefetch.  */
 943    if (tail) {
 944        if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
 945            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
 946        }
 947    } else {
 948        if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
 949            tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
 950        }
 951    }
 952}
 953
 954static void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
 955{
 956    tcg_out_call_int(s, arg, false);
 957    tcg_out_nop(s);
 958}
 959
 960#if defined(CONFIG_SOFTMMU)
 961static void * const qemu_ld_helpers[16] = {
 962    [MO_UB]   = helper_ret_ldub_mmu,
 963    [MO_SB]   = helper_ret_ldsb_mmu,
 964    [MO_LEUW] = helper_le_lduw_mmu,
 965    [MO_LESW] = helper_le_ldsw_mmu,
 966    [MO_LEUL] = helper_le_ldul_mmu,
 967    [MO_LEQ]  = helper_le_ldq_mmu,
 968    [MO_BEUW] = helper_be_lduw_mmu,
 969    [MO_BESW] = helper_be_ldsw_mmu,
 970    [MO_BEUL] = helper_be_ldul_mmu,
 971    [MO_BEQ]  = helper_be_ldq_mmu,
 972};
 973
 974static void * const qemu_st_helpers[16] = {
 975    [MO_UB]   = helper_ret_stb_mmu,
 976    [MO_LEUW] = helper_le_stw_mmu,
 977    [MO_LEUL] = helper_le_stl_mmu,
 978    [MO_LEQ]  = helper_le_stq_mmu,
 979    [MO_BEUW] = helper_be_stw_mmu,
 980    [MO_BEUL] = helper_be_stl_mmu,
 981    [MO_BEQ]  = helper_be_stq_mmu,
 982};
 983
 984/* Helper routines for marshalling helper function arguments into
 985 * the correct registers and stack.
 986 * I is where we want to put this argument, and is updated and returned
 987 * for the next call. ARG is the argument itself.
 988 *
 989 * We provide routines for arguments which are: immediate, 32 bit
 990 * value in register, 16 and 8 bit values in register (which must be zero
 991 * extended before use) and 64 bit value in a lo:hi register pair.
 992 */
 993
 994static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg)
 995{
 996    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
 997        tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg);
 998    } else {
 999        tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i);
1000    }
1001    return i + 1;
1002}
1003
1004static int tcg_out_call_iarg_reg8(TCGContext *s, int i, TCGReg arg)
1005{
1006    TCGReg tmp = TCG_TMP0;
1007    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1008        tmp = tcg_target_call_iarg_regs[i];
1009    }
1010    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xff);
1011    return tcg_out_call_iarg_reg(s, i, tmp);
1012}
1013
1014static int tcg_out_call_iarg_reg16(TCGContext *s, int i, TCGReg arg)
1015{
1016    TCGReg tmp = TCG_TMP0;
1017    if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1018        tmp = tcg_target_call_iarg_regs[i];
1019    }
1020    tcg_out_opc_imm(s, OPC_ANDI, tmp, arg, 0xffff);
1021    return tcg_out_call_iarg_reg(s, i, tmp);
1022}
1023
1024static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg)
1025{
1026    TCGReg tmp = TCG_TMP0;
1027    if (arg == 0) {
1028        tmp = TCG_REG_ZERO;
1029    } else {
1030        if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) {
1031            tmp = tcg_target_call_iarg_regs[i];
1032        }
1033        tcg_out_movi(s, TCG_TYPE_REG, tmp, arg);
1034    }
1035    return tcg_out_call_iarg_reg(s, i, tmp);
1036}
1037
1038static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah)
1039{
1040    i = (i + 1) & ~1;
1041    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al));
1042    i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah));
1043    return i;
1044}
1045
1046/* Perform the tlb comparison operation.  The complete host address is
1047   placed in BASE.  Clobbers AT, T0, A0.  */
1048static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl,
1049                             TCGReg addrh, TCGMemOpIdx oi,
1050                             tcg_insn_unit *label_ptr[2], bool is_load)
1051{
1052    TCGMemOp opc = get_memop(oi);
1053    unsigned s_bits = opc & MO_SIZE;
1054    unsigned a_bits = get_alignment_bits(opc);
1055    int mem_index = get_mmuidx(oi);
1056    int cmp_off
1057        = (is_load
1058           ? offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1059           : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write));
1060    int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend);
1061
1062    tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl,
1063                   TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1064    tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
1065                    (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
1066    tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
1067
1068    /* Compensate for very large offsets.  */
1069    if (add_off >= 0x8000) {
1070        /* Most target env are smaller than 32k; none are larger than 64k.
1071           Simplify the logic here merely to offset by 0x7ff0, giving us a
1072           range just shy of 64k.  Check this assumption.  */
1073        QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
1074                                   tlb_table[NB_MMU_MODES - 1][1])
1075                          > 0x7ff0 + 0x7fff);
1076        tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
1077        cmp_off -= 0x7ff0;
1078        add_off -= 0x7ff0;
1079    }
1080
1081    /* Load the (low half) tlb comparator.  */
1082    tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0,
1083                    cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
1084
1085    /* We don't currently support unaligned accesses.
1086       We could do so with mips32r6.  */
1087    if (a_bits < s_bits) {
1088        a_bits = s_bits;
1089    }
1090    /* Mask the page bits, keeping the alignment bits to compare against.
1091       In between on 32-bit targets, load the tlb addend for the fast path.  */
1092    tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
1093                 TARGET_PAGE_MASK | ((1 << a_bits) - 1));
1094    if (TARGET_LONG_BITS == 32) {
1095        tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
1096    }
1097    tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
1098
1099    label_ptr[0] = s->code_ptr;
1100    tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
1101
1102    /* Load and test the high half tlb comparator.  */
1103    if (TARGET_LONG_BITS == 64) {
1104        /* delay slot */
1105        tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF);
1106
1107        /* Load the tlb addend for the fast path. We can't do it earlier with
1108           64-bit targets or we'll clobber a0 before reading the high half tlb
1109           comparator.  */
1110        tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
1111
1112        label_ptr[1] = s->code_ptr;
1113        tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0);
1114    }
1115
1116    /* delay slot */
1117    tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl);
1118}
1119
1120static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
1121                                TCGReg datalo, TCGReg datahi,
1122                                TCGReg addrlo, TCGReg addrhi,
1123                                void *raddr, tcg_insn_unit *label_ptr[2])
1124{
1125    TCGLabelQemuLdst *label = new_ldst_label(s);
1126
1127    label->is_ld = is_ld;
1128    label->oi = oi;
1129    label->datalo_reg = datalo;
1130    label->datahi_reg = datahi;
1131    label->addrlo_reg = addrlo;
1132    label->addrhi_reg = addrhi;
1133    label->raddr = raddr;
1134    label->label_ptr[0] = label_ptr[0];
1135    if (TARGET_LONG_BITS == 64) {
1136        label->label_ptr[1] = label_ptr[1];
1137    }
1138}
1139
1140static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1141{
1142    TCGMemOpIdx oi = l->oi;
1143    TCGMemOp opc = get_memop(oi);
1144    TCGReg v0;
1145    int i;
1146
1147    /* resolve label address */
1148    reloc_pc16(l->label_ptr[0], s->code_ptr);
1149    if (TARGET_LONG_BITS == 64) {
1150        reloc_pc16(l->label_ptr[1], s->code_ptr);
1151    }
1152
1153    i = 1;
1154    if (TARGET_LONG_BITS == 64) {
1155        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1156    } else {
1157        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1158    }
1159    i = tcg_out_call_iarg_imm(s, i, oi);
1160    i = tcg_out_call_iarg_imm(s, i, (intptr_t)l->raddr);
1161    tcg_out_call_int(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)], false);
1162    /* delay slot */
1163    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1164
1165    v0 = l->datalo_reg;
1166    if ((opc & MO_SIZE) == MO_64) {
1167        /* We eliminated V0 from the possible output registers, so it
1168           cannot be clobbered here.  So we must move V1 first.  */
1169        if (MIPS_BE) {
1170            tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V1);
1171            v0 = l->datahi_reg;
1172        } else {
1173            tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
1174        }
1175    }
1176
1177    reloc_pc16(s->code_ptr, l->raddr);
1178    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1179    /* delay slot */
1180    tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
1181}
1182
1183static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1184{
1185    TCGMemOpIdx oi = l->oi;
1186    TCGMemOp opc = get_memop(oi);
1187    TCGMemOp s_bits = opc & MO_SIZE;
1188    int i;
1189
1190    /* resolve label address */
1191    reloc_pc16(l->label_ptr[0], s->code_ptr);
1192    if (TARGET_LONG_BITS == 64) {
1193        reloc_pc16(l->label_ptr[1], s->code_ptr);
1194    }
1195
1196    i = 1;
1197    if (TARGET_LONG_BITS == 64) {
1198        i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg);
1199    } else {
1200        i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg);
1201    }
1202    switch (s_bits) {
1203    case MO_8:
1204        i = tcg_out_call_iarg_reg8(s, i, l->datalo_reg);
1205        break;
1206    case MO_16:
1207        i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg);
1208        break;
1209    case MO_32:
1210        i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
1211        break;
1212    case MO_64:
1213        i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
1214        break;
1215    default:
1216        tcg_abort();
1217    }
1218    i = tcg_out_call_iarg_imm(s, i, oi);
1219
1220    /* Tail call to the store helper.  Thus force the return address
1221       computation to take place in the return address register.  */
1222    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RA, (intptr_t)l->raddr);
1223    i = tcg_out_call_iarg_reg(s, i, TCG_REG_RA);
1224    tcg_out_call_int(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)], true);
1225    /* delay slot */
1226    tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
1227}
1228#endif
1229
1230static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1231                                   TCGReg base, TCGMemOp opc)
1232{
1233    switch (opc & (MO_SSIZE | MO_BSWAP)) {
1234    case MO_UB:
1235        tcg_out_opc_imm(s, OPC_LBU, datalo, base, 0);
1236        break;
1237    case MO_SB:
1238        tcg_out_opc_imm(s, OPC_LB, datalo, base, 0);
1239        break;
1240    case MO_UW | MO_BSWAP:
1241        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1242        tcg_out_bswap16(s, datalo, TCG_TMP1);
1243        break;
1244    case MO_UW:
1245        tcg_out_opc_imm(s, OPC_LHU, datalo, base, 0);
1246        break;
1247    case MO_SW | MO_BSWAP:
1248        tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0);
1249        tcg_out_bswap16s(s, datalo, TCG_TMP1);
1250        break;
1251    case MO_SW:
1252        tcg_out_opc_imm(s, OPC_LH, datalo, base, 0);
1253        break;
1254    case MO_UL | MO_BSWAP:
1255        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 0);
1256        tcg_out_bswap32(s, datalo, TCG_TMP1);
1257        break;
1258    case MO_UL:
1259        tcg_out_opc_imm(s, OPC_LW, datalo, base, 0);
1260        break;
1261    case MO_Q | MO_BSWAP:
1262        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, HI_OFF);
1263        tcg_out_bswap32(s, datalo, TCG_TMP1);
1264        tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, LO_OFF);
1265        tcg_out_bswap32(s, datahi, TCG_TMP1);
1266        break;
1267    case MO_Q:
1268        tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF);
1269        tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF);
1270        break;
1271    default:
1272        tcg_abort();
1273    }
1274}
1275
1276static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1277{
1278    TCGReg addr_regl, addr_regh __attribute__((unused));
1279    TCGReg data_regl, data_regh;
1280    TCGMemOpIdx oi;
1281    TCGMemOp opc;
1282#if defined(CONFIG_SOFTMMU)
1283    tcg_insn_unit *label_ptr[2];
1284#endif
1285    /* Note that we've eliminated V0 from the output registers,
1286       so we won't overwrite the base register during loading.  */
1287    TCGReg base = TCG_REG_V0;
1288
1289    data_regl = *args++;
1290    data_regh = (is_64 ? *args++ : 0);
1291    addr_regl = *args++;
1292    addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1293    oi = *args++;
1294    opc = get_memop(oi);
1295
1296#if defined(CONFIG_SOFTMMU)
1297    tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
1298    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1299    add_qemu_ldst_label(s, 1, oi, data_regl, data_regh, addr_regl, addr_regh,
1300                        s->code_ptr, label_ptr);
1301#else
1302    if (guest_base == 0 && data_regl != addr_regl) {
1303        base = addr_regl;
1304    } else if (guest_base == (int16_t)guest_base) {
1305        tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base);
1306    } else {
1307        tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
1308        tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
1309    }
1310    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc);
1311#endif
1312}
1313
1314static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi,
1315                                   TCGReg base, TCGMemOp opc)
1316{
1317    switch (opc & (MO_SIZE | MO_BSWAP)) {
1318    case MO_8:
1319        tcg_out_opc_imm(s, OPC_SB, datalo, base, 0);
1320        break;
1321
1322    case MO_16 | MO_BSWAP:
1323        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, datalo, 0xffff);
1324        tcg_out_bswap16(s, TCG_TMP1, TCG_TMP1);
1325        datalo = TCG_TMP1;
1326        /* FALLTHRU */
1327    case MO_16:
1328        tcg_out_opc_imm(s, OPC_SH, datalo, base, 0);
1329        break;
1330
1331    case MO_32 | MO_BSWAP:
1332        tcg_out_bswap32(s, TCG_TMP1, datalo);
1333        datalo = TCG_TMP1;
1334        /* FALLTHRU */
1335    case MO_32:
1336        tcg_out_opc_imm(s, OPC_SW, datalo, base, 0);
1337        break;
1338
1339    case MO_64 | MO_BSWAP:
1340        tcg_out_bswap32(s, TCG_TMP1, datalo);
1341        tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, HI_OFF);
1342        tcg_out_bswap32(s, TCG_TMP1, datahi);
1343        tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, LO_OFF);
1344        break;
1345    case MO_64:
1346        tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF);
1347        tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF);
1348        break;
1349
1350    default:
1351        tcg_abort();
1352    }
1353}
1354
1355static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1356{
1357    TCGReg addr_regl, addr_regh __attribute__((unused));
1358    TCGReg data_regl, data_regh, base;
1359    TCGMemOpIdx oi;
1360    TCGMemOp opc;
1361#if defined(CONFIG_SOFTMMU)
1362    tcg_insn_unit *label_ptr[2];
1363#endif
1364
1365    data_regl = *args++;
1366    data_regh = (is_64 ? *args++ : 0);
1367    addr_regl = *args++;
1368    addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
1369    oi = *args++;
1370    opc = get_memop(oi);
1371
1372#if defined(CONFIG_SOFTMMU)
1373    /* Note that we eliminated the helper's address argument,
1374       so we can reuse that for the base.  */
1375    base = (TARGET_LONG_BITS == 32 ? TCG_REG_A1 : TCG_REG_A2);
1376    tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
1377    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1378    add_qemu_ldst_label(s, 0, oi, data_regl, data_regh, addr_regl, addr_regh,
1379                        s->code_ptr, label_ptr);
1380#else
1381    if (guest_base == 0) {
1382        base = addr_regl;
1383    } else {
1384        base = TCG_REG_A0;
1385        if (guest_base == (int16_t)guest_base) {
1386            tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base);
1387        } else {
1388            tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
1389            tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl);
1390        }
1391    }
1392    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1393#endif
1394}
1395
1396static void tcg_out_mb(TCGContext *s, TCGArg a0)
1397{
1398    static const MIPSInsn sync[] = {
1399        /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1400           as the former is an ordering barrier and the latter
1401           is a completion barrier.  */
1402        [0 ... TCG_MO_ALL]            = OPC_SYNC_MB,
1403        [TCG_MO_LD_LD]                = OPC_SYNC_RMB,
1404        [TCG_MO_ST_ST]                = OPC_SYNC_WMB,
1405        [TCG_MO_LD_ST]                = OPC_SYNC_RELEASE,
1406        [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1407        [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1408    };
1409    tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1410}
1411
1412static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1413                              const TCGArg *args, const int *const_args)
1414{
1415    MIPSInsn i1, i2;
1416    TCGArg a0, a1, a2;
1417    int c2;
1418
1419    a0 = args[0];
1420    a1 = args[1];
1421    a2 = args[2];
1422    c2 = const_args[2];
1423
1424    switch (opc) {
1425    case INDEX_op_exit_tb:
1426        {
1427            TCGReg b0 = TCG_REG_ZERO;
1428
1429            if (a0 & ~0xffff) {
1430                tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff);
1431                b0 = TCG_REG_V0;
1432            }
1433            if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1434                tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0,
1435                             (uintptr_t)tb_ret_addr);
1436                tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1437            }
1438            tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff);
1439        }
1440        break;
1441    case INDEX_op_goto_tb:
1442        if (s->tb_jmp_insn_offset) {
1443            /* direct jump method */
1444            s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
1445            /* Avoid clobbering the address during retranslation.  */
1446            tcg_out32(s, OPC_J | (*(uint32_t *)s->code_ptr & 0x3ffffff));
1447        } else {
1448            /* indirect jump method */
1449            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO,
1450                       (uintptr_t)(s->tb_jmp_target_addr + a0));
1451            tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1452        }
1453        tcg_out_nop(s);
1454        s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
1455        break;
1456    case INDEX_op_br:
1457        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
1458                       arg_label(a0));
1459        break;
1460
1461    case INDEX_op_ld8u_i32:
1462        i1 = OPC_LBU;
1463        goto do_ldst;
1464    case INDEX_op_ld8s_i32:
1465        i1 = OPC_LB;
1466        goto do_ldst;
1467    case INDEX_op_ld16u_i32:
1468        i1 = OPC_LHU;
1469        goto do_ldst;
1470    case INDEX_op_ld16s_i32:
1471        i1 = OPC_LH;
1472        goto do_ldst;
1473    case INDEX_op_ld_i32:
1474        i1 = OPC_LW;
1475        goto do_ldst;
1476    case INDEX_op_st8_i32:
1477        i1 = OPC_SB;
1478        goto do_ldst;
1479    case INDEX_op_st16_i32:
1480        i1 = OPC_SH;
1481        goto do_ldst;
1482    case INDEX_op_st_i32:
1483        i1 = OPC_SW;
1484    do_ldst:
1485        tcg_out_ldst(s, i1, a0, a1, a2);
1486        break;
1487
1488    case INDEX_op_add_i32:
1489        i1 = OPC_ADDU, i2 = OPC_ADDIU;
1490        goto do_binary;
1491    case INDEX_op_or_i32:
1492        i1 = OPC_OR, i2 = OPC_ORI;
1493        goto do_binary;
1494    case INDEX_op_xor_i32:
1495        i1 = OPC_XOR, i2 = OPC_XORI;
1496    do_binary:
1497        if (c2) {
1498            tcg_out_opc_imm(s, i2, a0, a1, a2);
1499            break;
1500        }
1501    do_binaryv:
1502        tcg_out_opc_reg(s, i1, a0, a1, a2);
1503        break;
1504
1505    case INDEX_op_sub_i32:
1506        if (c2) {
1507            tcg_out_opc_imm(s, OPC_ADDIU, a0, a1, -a2);
1508            break;
1509        }
1510        i1 = OPC_SUBU;
1511        goto do_binary;
1512    case INDEX_op_and_i32:
1513        if (c2 && a2 != (uint16_t)a2) {
1514            int msb = ctz32(~a2) - 1;
1515            tcg_debug_assert(use_mips32r2_instructions);
1516            tcg_debug_assert(is_p2m1(a2));
1517            tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1518            break;
1519        }
1520        i1 = OPC_AND, i2 = OPC_ANDI;
1521        goto do_binary;
1522    case INDEX_op_nor_i32:
1523        i1 = OPC_NOR;
1524        goto do_binaryv;
1525
1526    case INDEX_op_mul_i32:
1527        if (use_mips32_instructions) {
1528            tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1529            break;
1530        }
1531        i1 = OPC_MULT, i2 = OPC_MFLO;
1532        goto do_hilo1;
1533    case INDEX_op_mulsh_i32:
1534        if (use_mips32r6_instructions) {
1535            tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
1536            break;
1537        }
1538        i1 = OPC_MULT, i2 = OPC_MFHI;
1539        goto do_hilo1;
1540    case INDEX_op_muluh_i32:
1541        if (use_mips32r6_instructions) {
1542            tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
1543            break;
1544        }
1545        i1 = OPC_MULTU, i2 = OPC_MFHI;
1546        goto do_hilo1;
1547    case INDEX_op_div_i32:
1548        if (use_mips32r6_instructions) {
1549            tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
1550            break;
1551        }
1552        i1 = OPC_DIV, i2 = OPC_MFLO;
1553        goto do_hilo1;
1554    case INDEX_op_divu_i32:
1555        if (use_mips32r6_instructions) {
1556            tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
1557            break;
1558        }
1559        i1 = OPC_DIVU, i2 = OPC_MFLO;
1560        goto do_hilo1;
1561    case INDEX_op_rem_i32:
1562        if (use_mips32r6_instructions) {
1563            tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
1564            break;
1565        }
1566        i1 = OPC_DIV, i2 = OPC_MFHI;
1567        goto do_hilo1;
1568    case INDEX_op_remu_i32:
1569        if (use_mips32r6_instructions) {
1570            tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
1571            break;
1572        }
1573        i1 = OPC_DIVU, i2 = OPC_MFHI;
1574    do_hilo1:
1575        tcg_out_opc_reg(s, i1, 0, a1, a2);
1576        tcg_out_opc_reg(s, i2, a0, 0, 0);
1577        break;
1578
1579    case INDEX_op_muls2_i32:
1580        i1 = OPC_MULT;
1581        goto do_hilo2;
1582    case INDEX_op_mulu2_i32:
1583        i1 = OPC_MULTU;
1584    do_hilo2:
1585        tcg_out_opc_reg(s, i1, 0, a2, args[3]);
1586        tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1587        tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1588        break;
1589
1590    case INDEX_op_not_i32:
1591        i1 = OPC_NOR;
1592        goto do_unary;
1593    case INDEX_op_bswap16_i32:
1594        i1 = OPC_WSBH;
1595        goto do_unary;
1596    case INDEX_op_ext8s_i32:
1597        i1 = OPC_SEB;
1598        goto do_unary;
1599    case INDEX_op_ext16s_i32:
1600        i1 = OPC_SEH;
1601    do_unary:
1602        tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
1603        break;
1604
1605    case INDEX_op_sar_i32:
1606        i1 = OPC_SRAV, i2 = OPC_SRA;
1607        goto do_shift;
1608    case INDEX_op_shl_i32:
1609        i1 = OPC_SLLV, i2 = OPC_SLL;
1610        goto do_shift;
1611    case INDEX_op_shr_i32:
1612        i1 = OPC_SRLV, i2 = OPC_SRL;
1613        goto do_shift;
1614    case INDEX_op_rotr_i32:
1615        i1 = OPC_ROTRV, i2 = OPC_ROTR;
1616    do_shift:
1617        if (c2) {
1618            tcg_out_opc_sa(s, i2, a0, a1, a2);
1619        } else {
1620            tcg_out_opc_reg(s, i1, a0, a2, a1);
1621        }
1622        break;
1623    case INDEX_op_rotl_i32:
1624        if (c2) {
1625            tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
1626        } else {
1627            tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
1628            tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
1629        }
1630        break;
1631
1632    case INDEX_op_bswap32_i32:
1633        tcg_out_opc_reg(s, OPC_WSBH, a0, 0, a1);
1634        tcg_out_opc_sa(s, OPC_ROTR, a0, a0, 16);
1635        break;
1636
1637    case INDEX_op_deposit_i32:
1638        tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
1639        break;
1640
1641    case INDEX_op_brcond_i32:
1642        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
1643        break;
1644    case INDEX_op_brcond2_i32:
1645        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
1646        break;
1647
1648    case INDEX_op_movcond_i32:
1649        tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
1650        break;
1651
1652    case INDEX_op_setcond_i32:
1653        tcg_out_setcond(s, args[3], a0, a1, a2);
1654        break;
1655    case INDEX_op_setcond2_i32:
1656        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
1657        break;
1658
1659    case INDEX_op_qemu_ld_i32:
1660        tcg_out_qemu_ld(s, args, false);
1661        break;
1662    case INDEX_op_qemu_ld_i64:
1663        tcg_out_qemu_ld(s, args, true);
1664        break;
1665    case INDEX_op_qemu_st_i32:
1666        tcg_out_qemu_st(s, args, false);
1667        break;
1668    case INDEX_op_qemu_st_i64:
1669        tcg_out_qemu_st(s, args, true);
1670        break;
1671
1672    case INDEX_op_add2_i32:
1673        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1674                        const_args[4], const_args[5], false);
1675        break;
1676    case INDEX_op_sub2_i32:
1677        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1678                        const_args[4], const_args[5], true);
1679        break;
1680
1681    case INDEX_op_mb:
1682        tcg_out_mb(s, a0);
1683        break;
1684    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
1685    case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
1686    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
1687    default:
1688        tcg_abort();
1689    }
1690}
1691
1692static const TCGTargetOpDef mips_op_defs[] = {
1693    { INDEX_op_exit_tb, { } },
1694    { INDEX_op_goto_tb, { } },
1695    { INDEX_op_br, { } },
1696
1697    { INDEX_op_ld8u_i32, { "r", "r" } },
1698    { INDEX_op_ld8s_i32, { "r", "r" } },
1699    { INDEX_op_ld16u_i32, { "r", "r" } },
1700    { INDEX_op_ld16s_i32, { "r", "r" } },
1701    { INDEX_op_ld_i32, { "r", "r" } },
1702    { INDEX_op_st8_i32, { "rZ", "r" } },
1703    { INDEX_op_st16_i32, { "rZ", "r" } },
1704    { INDEX_op_st_i32, { "rZ", "r" } },
1705
1706    { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
1707    { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
1708#if !use_mips32r6_instructions
1709    { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
1710    { INDEX_op_mulu2_i32, { "r", "r", "rZ", "rZ" } },
1711#endif
1712    { INDEX_op_mulsh_i32, { "r", "rZ", "rZ" } },
1713    { INDEX_op_muluh_i32, { "r", "rZ", "rZ" } },
1714    { INDEX_op_div_i32, { "r", "rZ", "rZ" } },
1715    { INDEX_op_divu_i32, { "r", "rZ", "rZ" } },
1716    { INDEX_op_rem_i32, { "r", "rZ", "rZ" } },
1717    { INDEX_op_remu_i32, { "r", "rZ", "rZ" } },
1718    { INDEX_op_sub_i32, { "r", "rZ", "rN" } },
1719
1720    { INDEX_op_and_i32, { "r", "rZ", "rIK" } },
1721    { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
1722    { INDEX_op_not_i32, { "r", "rZ" } },
1723    { INDEX_op_or_i32, { "r", "rZ", "rIZ" } },
1724    { INDEX_op_xor_i32, { "r", "rZ", "rIZ" } },
1725
1726    { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
1727    { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
1728    { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
1729    { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
1730    { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
1731
1732    { INDEX_op_bswap16_i32, { "r", "r" } },
1733    { INDEX_op_bswap32_i32, { "r", "r" } },
1734
1735    { INDEX_op_ext8s_i32, { "r", "rZ" } },
1736    { INDEX_op_ext16s_i32, { "r", "rZ" } },
1737
1738    { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1739
1740    { INDEX_op_brcond_i32, { "rZ", "rZ" } },
1741#if use_mips32r6_instructions
1742    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1743#else
1744    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
1745#endif
1746    { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
1747    { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
1748
1749    { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1750    { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rN", "rN" } },
1751    { INDEX_op_brcond2_i32, { "rZ", "rZ", "rZ", "rZ" } },
1752
1753#if TARGET_LONG_BITS == 32
1754    { INDEX_op_qemu_ld_i32, { "L", "lZ" } },
1755    { INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
1756    { INDEX_op_qemu_ld_i64, { "L", "L", "lZ" } },
1757    { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
1758#else
1759    { INDEX_op_qemu_ld_i32, { "L", "lZ", "lZ" } },
1760    { INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
1761    { INDEX_op_qemu_ld_i64, { "L", "L", "lZ", "lZ" } },
1762    { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ", "SZ" } },
1763#endif
1764
1765    { INDEX_op_mb, { } },
1766    { -1 },
1767};
1768
1769static int tcg_target_callee_save_regs[] = {
1770    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
1771    TCG_REG_S1,
1772    TCG_REG_S2,
1773    TCG_REG_S3,
1774    TCG_REG_S4,
1775    TCG_REG_S5,
1776    TCG_REG_S6,
1777    TCG_REG_S7,
1778    TCG_REG_S8,
1779    TCG_REG_RA,       /* should be last for ABI compliance */
1780};
1781
1782/* The Linux kernel doesn't provide any information about the available
1783   instruction set. Probe it using a signal handler. */
1784
1785
1786#ifndef use_movnz_instructions
1787bool use_movnz_instructions = false;
1788#endif
1789
1790#ifndef use_mips32_instructions
1791bool use_mips32_instructions = false;
1792#endif
1793
1794#ifndef use_mips32r2_instructions
1795bool use_mips32r2_instructions = false;
1796#endif
1797
1798static volatile sig_atomic_t got_sigill;
1799
1800static void sigill_handler(int signo, siginfo_t *si, void *data)
1801{
1802    /* Skip the faulty instruction */
1803    ucontext_t *uc = (ucontext_t *)data;
1804    uc->uc_mcontext.pc += 4;
1805
1806    got_sigill = 1;
1807}
1808
1809static void tcg_target_detect_isa(void)
1810{
1811    struct sigaction sa_old, sa_new;
1812
1813    memset(&sa_new, 0, sizeof(sa_new));
1814    sa_new.sa_flags = SA_SIGINFO;
1815    sa_new.sa_sigaction = sigill_handler;
1816    sigaction(SIGILL, &sa_new, &sa_old);
1817
1818    /* Probe for movn/movz, necessary to implement movcond. */
1819#ifndef use_movnz_instructions
1820    got_sigill = 0;
1821    asm volatile(".set push\n"
1822                 ".set mips32\n"
1823                 "movn $zero, $zero, $zero\n"
1824                 "movz $zero, $zero, $zero\n"
1825                 ".set pop\n"
1826                 : : : );
1827    use_movnz_instructions = !got_sigill;
1828#endif
1829
1830    /* Probe for MIPS32 instructions. As no subsetting is allowed
1831       by the specification, it is only necessary to probe for one
1832       of the instructions. */
1833#ifndef use_mips32_instructions
1834    got_sigill = 0;
1835    asm volatile(".set push\n"
1836                 ".set mips32\n"
1837                 "mul $zero, $zero\n"
1838                 ".set pop\n"
1839                 : : : );
1840    use_mips32_instructions = !got_sigill;
1841#endif
1842
1843    /* Probe for MIPS32r2 instructions if MIPS32 instructions are
1844       available. As no subsetting is allowed by the specification,
1845       it is only necessary to probe for one of the instructions. */
1846#ifndef use_mips32r2_instructions
1847    if (use_mips32_instructions) {
1848        got_sigill = 0;
1849        asm volatile(".set push\n"
1850                     ".set mips32r2\n"
1851                     "seb $zero, $zero\n"
1852                     ".set pop\n"
1853                     : : : );
1854        use_mips32r2_instructions = !got_sigill;
1855    }
1856#endif
1857
1858    sigaction(SIGILL, &sa_old, NULL);
1859}
1860
1861/* Generate global QEMU prologue and epilogue code */
1862static void tcg_target_qemu_prologue(TCGContext *s)
1863{
1864    int i, frame_size;
1865
1866    /* reserve some stack space, also for TCG temps. */
1867    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1868                 + TCG_STATIC_CALL_ARGS_SIZE
1869                 + CPU_TEMP_BUF_NLONGS * sizeof(long);
1870    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
1871                 ~(TCG_TARGET_STACK_ALIGN - 1);
1872    tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
1873                  + TCG_STATIC_CALL_ARGS_SIZE,
1874                  CPU_TEMP_BUF_NLONGS * sizeof(long));
1875
1876    /* TB prologue */
1877    tcg_out_addi(s, TCG_REG_SP, -frame_size);
1878    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1879        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1880                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1881    }
1882
1883    /* Call generated code */
1884    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
1885    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1886    tb_ret_addr = s->code_ptr;
1887
1888    /* TB epilogue */
1889    for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
1890        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
1891                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
1892    }
1893
1894    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
1895    tcg_out_addi(s, TCG_REG_SP, frame_size);
1896}
1897
1898static void tcg_target_init(TCGContext *s)
1899{
1900    tcg_target_detect_isa();
1901    tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
1902    tcg_regset_set(tcg_target_call_clobber_regs,
1903                   (1 << TCG_REG_V0) |
1904                   (1 << TCG_REG_V1) |
1905                   (1 << TCG_REG_A0) |
1906                   (1 << TCG_REG_A1) |
1907                   (1 << TCG_REG_A2) |
1908                   (1 << TCG_REG_A3) |
1909                   (1 << TCG_REG_T0) |
1910                   (1 << TCG_REG_T1) |
1911                   (1 << TCG_REG_T2) |
1912                   (1 << TCG_REG_T3) |
1913                   (1 << TCG_REG_T4) |
1914                   (1 << TCG_REG_T5) |
1915                   (1 << TCG_REG_T6) |
1916                   (1 << TCG_REG_T7) |
1917                   (1 << TCG_REG_T8) |
1918                   (1 << TCG_REG_T9));
1919
1920    tcg_regset_clear(s->reserved_regs);
1921    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
1922    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
1923    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
1924    tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);     /* internal use */
1925    tcg_regset_set_reg(s->reserved_regs, TCG_TMP1);     /* internal use */
1926    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
1927    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
1928    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);   /* global pointer */
1929
1930    tcg_add_target_add_op_defs(mips_op_defs);
1931}
1932
1933void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
1934{
1935    atomic_set((uint32_t *)jmp_addr, deposit32(OPC_J, 0, 26, addr >> 2));
1936    flush_icache_range(jmp_addr, jmp_addr + 4);
1937}
1938