Home | History | Annotate | Download | only in priv
      1 
      2 /*---------------------------------------------------------------*/
      3 /*--- begin                                  host_mips_defs.c ---*/
      4 /*---------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2010-2015 RT-RK
     11       mips-valgrind (at) rt-rk.com
     12 
     13    This program is free software; you can redistribute it and/or
     14    modify it under the terms of the GNU General Public License as
     15    published by the Free Software Foundation; either version 2 of the
     16    License, or (at your option) any later version.
     17 
     18    This program is distributed in the hope that it will be useful, but
     19    WITHOUT ANY WARRANTY; without even the implied warranty of
     20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21    General Public License for more details.
     22 
     23    You should have received a copy of the GNU General Public License
     24    along with this program; if not, write to the Free Software
     25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26    02111-1307, USA.
     27 
     28    The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 #include "libvex_basictypes.h"
     32 #include "libvex.h"
     33 #include "libvex_trc_values.h"
     34 
     35 #include "main_util.h"
     36 #include "host_generic_regs.h"
     37 #include "host_mips_defs.h"
     38 
     39 /* guest_COND offset. */
     40 #define COND_OFFSET(__mode64) (__mode64 ? 612 : 448)
     41 
     42 /* Register number for guest state pointer in host code. */
     43 #define GuestSP 23
     44 
     45 
     46 /*---------------- Registers ----------------*/
     47 
     48 const RRegUniverse* getRRegUniverse_MIPS ( Bool mode64 )
     49 {
     50    /* The real-register universe is a big constant, so we just want to
     51       initialise it once.  rRegUniverse_MIPS_initted values: 0=not initted,
     52       1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
     53    static RRegUniverse rRegUniverse_MIPS;
     54    static UInt         rRegUniverse_MIPS_initted = 0;
     55 
     56    /* Handy shorthand, nothing more */
     57    RRegUniverse* ru = &rRegUniverse_MIPS;
     58 
     59    /* This isn't thread-safe.  Sigh. */
     60    UInt howNeeded = mode64 ? 2 : 1;
     61    if (LIKELY(rRegUniverse_MIPS_initted == howNeeded))
     62       return ru;
     63 
     64    RRegUniverse__init(ru);
     65 
     66    /* Add the registers.  The initial segment of this array must be
     67       those available for allocation by reg-alloc, and those that
     68       follow are not available for allocation. */
     69    ru->regs[ru->size++] = hregMIPS_GPR16(mode64);
     70    ru->regs[ru->size++] = hregMIPS_GPR17(mode64);
     71    ru->regs[ru->size++] = hregMIPS_GPR18(mode64);
     72    ru->regs[ru->size++] = hregMIPS_GPR19(mode64);
     73    ru->regs[ru->size++] = hregMIPS_GPR20(mode64);
     74    ru->regs[ru->size++] = hregMIPS_GPR21(mode64);
     75    ru->regs[ru->size++] = hregMIPS_GPR22(mode64);
     76 
     77    ru->regs[ru->size++] = hregMIPS_GPR12(mode64);
     78    ru->regs[ru->size++] = hregMIPS_GPR13(mode64);
     79    ru->regs[ru->size++] = hregMIPS_GPR14(mode64);
     80    ru->regs[ru->size++] = hregMIPS_GPR15(mode64);
     81    ru->regs[ru->size++] = hregMIPS_GPR24(mode64);
     82    /* s7  (=guest_state) */
     83    ru->regs[ru->size++] = hregMIPS_F16(mode64);
     84    ru->regs[ru->size++] = hregMIPS_F18(mode64);
     85    ru->regs[ru->size++] = hregMIPS_F20(mode64);
     86    ru->regs[ru->size++] = hregMIPS_F22(mode64);
     87    ru->regs[ru->size++] = hregMIPS_F24(mode64);
     88    ru->regs[ru->size++] = hregMIPS_F26(mode64);
     89    ru->regs[ru->size++] = hregMIPS_F28(mode64);
     90    ru->regs[ru->size++] = hregMIPS_F30(mode64);
     91    if (!mode64) {
     92       /* Fake double floating point */
     93       ru->regs[ru->size++] = hregMIPS_D0(mode64);
     94       ru->regs[ru->size++] = hregMIPS_D1(mode64);
     95       ru->regs[ru->size++] = hregMIPS_D2(mode64);
     96       ru->regs[ru->size++] = hregMIPS_D3(mode64);
     97       ru->regs[ru->size++] = hregMIPS_D4(mode64);
     98       ru->regs[ru->size++] = hregMIPS_D5(mode64);
     99       ru->regs[ru->size++] = hregMIPS_D6(mode64);
    100       ru->regs[ru->size++] = hregMIPS_D7(mode64);
    101    }
    102 
    103    ru->allocable = ru->size;
    104    /* And other regs, not available to the allocator. */
    105 
    106    ru->regs[ru->size++] = hregMIPS_HI(mode64);
    107    ru->regs[ru->size++] = hregMIPS_LO(mode64);
    108    ru->regs[ru->size++] = hregMIPS_GPR0(mode64);
    109    ru->regs[ru->size++] = hregMIPS_GPR1(mode64);
    110    ru->regs[ru->size++] = hregMIPS_GPR2(mode64);
    111    ru->regs[ru->size++] = hregMIPS_GPR3(mode64);
    112    ru->regs[ru->size++] = hregMIPS_GPR4(mode64);
    113    ru->regs[ru->size++] = hregMIPS_GPR5(mode64);
    114    ru->regs[ru->size++] = hregMIPS_GPR6(mode64);
    115    ru->regs[ru->size++] = hregMIPS_GPR7(mode64);
    116    ru->regs[ru->size++] = hregMIPS_GPR8(mode64);
    117    ru->regs[ru->size++] = hregMIPS_GPR9(mode64);
    118    ru->regs[ru->size++] = hregMIPS_GPR10(mode64);
    119    ru->regs[ru->size++] = hregMIPS_GPR11(mode64);
    120    ru->regs[ru->size++] = hregMIPS_GPR23(mode64);
    121    ru->regs[ru->size++] = hregMIPS_GPR25(mode64);
    122    ru->regs[ru->size++] = hregMIPS_GPR29(mode64);
    123    ru->regs[ru->size++] = hregMIPS_GPR31(mode64);
    124 
    125    rRegUniverse_MIPS_initted = howNeeded;
    126 
    127    RRegUniverse__check_is_sane(ru);
    128    return ru;
    129 }
    130 
    131 
    132 void ppHRegMIPS(HReg reg, Bool mode64)
    133 {
    134    Int r;
    135    static const HChar *ireg32_names[35]
    136        = { "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
    137       "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
    138       "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
    139       "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31",
    140       "%32", "%33", "%34",
    141    };
    142 
    143    static const HChar *freg32_names[32]
    144        = { "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
    145       "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
    146       "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
    147       "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "f30", "$f31"
    148    };
    149 
    150    static const HChar *freg64_names[32]
    151        = { "$d0", "$d1", "$d2", "$d3", "$d4", "$d5", "$d6", "$d7",
    152       "$d8", "$d9", "$d10", "$d11", "$d12", "$d13", "$d14", "$d15",
    153    };
    154 
    155    /* Be generic for all virtual regs. */
    156    if (hregIsVirtual(reg)) {
    157       ppHReg(reg);
    158       return;
    159    }
    160 
    161    /* But specific for real regs. */
    162    vassert(hregClass(reg) == HRcInt32 || hregClass(reg) == HRcInt64 ||
    163            hregClass(reg) == HRcFlt32 || hregClass(reg) == HRcFlt64);
    164 
    165    /* But specific for real regs. */
    166    switch (hregClass(reg)) {
    167       case HRcInt32:
    168          r = hregEncoding(reg);
    169          vassert(r >= 0 && r < 32);
    170          vex_printf("%s", ireg32_names[r]);
    171          return;
    172       case HRcInt64:
    173          r = hregEncoding (reg);
    174          vassert (r >= 0 && r < 32);
    175          vex_printf ("%s", ireg32_names[r]);
    176          return;
    177       case HRcFlt32:
    178          r = hregEncoding(reg);
    179          vassert(r >= 0 && r < 32);
    180          vex_printf("%s", freg32_names[r]);
    181          return;
    182       case HRcFlt64:
    183          r = hregEncoding(reg);
    184          vassert(r >= 0 && r < 32);
    185          vex_printf("%s", freg64_names[r]);
    186          return;
    187       default:
    188          vpanic("ppHRegMIPS");
    189          break;
    190    }
    191 
    192    return;
    193 }
    194 
    195 
    196 /*----------------- Condition Codes ----------------------*/
    197 
    198 const HChar *showMIPSCondCode(MIPSCondCode cond)
    199 {
    200    const HChar* ret;
    201    switch (cond) {
    202       case MIPScc_EQ:
    203          ret = "EQ";  /* equal */
    204          break;
    205       case MIPScc_NE:
    206          ret = "NEQ";  /* not equal */
    207          break;
    208       case MIPScc_HS:
    209          ret = "GE";  /* >=u (Greater Than or Equal) */
    210          break;
    211       case MIPScc_LO:
    212          ret = "LT";  /* <u  (lower) */
    213          break;
    214       case MIPScc_MI:
    215          ret = "MI";  /* minus (negative) */
    216          break;
    217       case MIPScc_PL:
    218          ret = "PL";  /* plus (zero or +ve) */
    219          break;
    220       case MIPScc_VS:
    221          ret = "VS";  /* overflow */
    222          break;
    223       case MIPScc_VC:
    224          ret = "VC";  /* no overflow */
    225          break;
    226       case MIPScc_HI:
    227          ret = "HI";  /* >u   (higher) */
    228          break;
    229       case MIPScc_LS:
    230          ret = "LS";  /* <=u  (lower or same) */
    231          break;
    232       case MIPScc_GE:
    233          ret = "GE";  /* >=s (signed greater or equal) */
    234          break;
    235       case MIPScc_LT:
    236          ret = "LT";  /* <s  (signed less than) */
    237          break;
    238       case MIPScc_GT:
    239          ret = "GT";  /* >s  (signed greater) */
    240          break;
    241       case MIPScc_LE:
    242          ret = "LE";  /* <=s (signed less or equal) */
    243          break;
    244       case MIPScc_AL:
    245          ret = "AL";  /* always (unconditional) */
    246          break;
    247       case MIPScc_NV:
    248          ret = "NV";  /* never (unconditional): */
    249          break;
    250       default:
    251          vpanic("showMIPSCondCode");
    252          break;
    253    }
    254    return ret;
    255 }
    256 
    257 const HChar *showMIPSFpOp(MIPSFpOp op)
    258 {
    259    const HChar *ret;
    260    switch (op) {
    261       case Mfp_ADDD:
    262          ret = "add.d";
    263          break;
    264       case Mfp_SUBD:
    265          ret = "sub.d";
    266          break;
    267       case Mfp_MULD:
    268          ret = "mul.d";
    269          break;
    270       case Mfp_DIVD:
    271          ret = "div.d";
    272          break;
    273       case Mfp_MADDD:
    274          ret = "madd.d";
    275          break;
    276       case Mfp_MSUBD:
    277          ret = "msub.d";
    278          break;
    279       case Mfp_MADDS:
    280          ret = "madd.s";
    281          break;
    282       case Mfp_MSUBS:
    283          ret = "msub.s";
    284          break;
    285       case Mfp_ADDS:
    286          ret = "add.s";
    287          break;
    288       case Mfp_SUBS:
    289          ret = "sub.s";
    290          break;
    291       case Mfp_MULS:
    292          ret = "mul.s";
    293          break;
    294       case Mfp_DIVS:
    295          ret = "div.s";
    296          break;
    297       case Mfp_SQRTS:
    298          ret = "sqrt.s";
    299          break;
    300       case Mfp_SQRTD:
    301          ret = "sqrt.d";
    302          break;
    303       case Mfp_ABSS:
    304          ret = "abs.s";
    305          break;
    306       case Mfp_ABSD:
    307          ret = "abs.d";
    308          break;
    309       case Mfp_NEGS:
    310          ret = "neg.s";
    311          break;
    312       case Mfp_NEGD:
    313          ret = "neg.d";
    314          break;
    315       case Mfp_MOVS:
    316          ret = "mov.s";
    317          break;
    318       case Mfp_MOVD:
    319          ret = "mov.d";
    320          break;
    321       case Mfp_ROUNDWS:
    322          ret = "round.w.s";
    323          break;
    324       case Mfp_ROUNDWD:
    325          ret = "round.w.d";
    326          break;
    327       case Mfp_ROUNDLD:
    328          ret = "round.l.d";
    329          break;
    330       case Mfp_FLOORWS:
    331          ret = "floor.w.s";
    332          break;
    333       case Mfp_FLOORWD:
    334          ret = "floor.w.d";
    335          break;
    336       case Mfp_CVTDW:
    337          ret = "cvt.d.w";
    338          break;
    339       case Mfp_CVTDL:
    340          ret = "cvt.d.l";
    341          break;
    342       case Mfp_CVTDS:
    343          ret = "cvt.d.s";
    344          break;
    345       case Mfp_CVTSD:
    346          ret = "cvt.s.d";
    347          break;
    348       case Mfp_CVTSW:
    349          ret = "cvt.s.w";
    350          break;
    351       case Mfp_CVTWS:
    352          ret = "cvt.w.s";
    353          break;
    354       case Mfp_CVTWD:
    355          ret = "cvt.w.d";
    356          break;
    357       case Mfp_CVTLD:
    358          ret = "cvt.l.d";
    359          break;
    360       case Mfp_CVTLS:
    361          ret = "cvt.l.s";
    362          break;
    363       case Mfp_TRUWD:
    364          ret = "trunc.w.d";
    365          break;
    366       case Mfp_TRUWS:
    367          ret = "trunc.w.s";
    368          break;
    369       case Mfp_TRULD:
    370          ret = "trunc.l.d";
    371          break;
    372       case Mfp_TRULS:
    373          ret = "trunc.l.s";
    374          break;
    375       case Mfp_CEILWS:
    376          ret = "ceil.w.s";
    377          break;
    378       case Mfp_CEILWD:
    379          ret = "ceil.w.d";
    380          break;
    381       case Mfp_CEILLS:
    382          ret = "ceil.l.s";
    383          break;
    384       case Mfp_CEILLD:
    385          ret = "ceil.l.d";
    386          break;
    387       case Mfp_CMP_UN:
    388          ret = "c.un.d";
    389          break;
    390       case Mfp_CMP_EQ:
    391          ret = "c.eq.d";
    392          break;
    393       case Mfp_CMP_LT:
    394          ret = "c.lt.d";
    395          break;
    396       case Mfp_CMP_NGT:
    397          ret = "c.ngt.d";
    398          break;
    399       default:
    400          vex_printf("Unknown op: %d", (Int)op);
    401          vpanic("showMIPSFpOp");
    402          break;
    403    }
    404    return ret;
    405 }
    406 
    407 /* Show move from/to fpr to/from gpr */
    408 const HChar* showMIPSFpGpMoveOp ( MIPSFpGpMoveOp op )
    409 {
    410    const HChar *ret;
    411    switch (op) {
    412       case MFpGpMove_mfc1:
    413          ret = "mfc1";
    414          break;
    415       case MFpGpMove_dmfc1:
    416          ret = "dmfc1";
    417          break;
    418       case MFpGpMove_mtc1:
    419          ret = "mtc1";
    420          break;
    421       case MFpGpMove_dmtc1:
    422          ret = "dmtc1";
    423          break;
    424       default:
    425          vpanic("showMIPSFpGpMoveOp");
    426          break;
    427    }
    428    return ret;
    429 }
    430 
    431 /* Show floating point move conditional */
    432 const HChar* showMIPSMoveCondOp ( MIPSMoveCondOp op )
    433 {
    434    const HChar *ret;
    435    switch (op) {
    436       case MFpMoveCond_movns:
    437          ret = "movn.s";
    438          break;
    439       case MFpMoveCond_movnd:
    440          ret = "movn.d";
    441          break;
    442       case MMoveCond_movn:
    443          ret = "movn";
    444          break;
    445       default:
    446          vpanic("showMIPSFpMoveCondOp");
    447          break;
    448    }
    449    return ret;
    450 }
    451 
    452 /* --------- MIPSAMode: memory address expressions. --------- */
    453 
    454 MIPSAMode *MIPSAMode_IR(Int idx, HReg base)
    455 {
    456    MIPSAMode *am = LibVEX_Alloc_inline(sizeof(MIPSAMode));
    457    am->tag = Mam_IR;
    458    am->Mam.IR.base = base;
    459    am->Mam.IR.index = idx;
    460 
    461    return am;
    462 }
    463 
    464 MIPSAMode *MIPSAMode_RR(HReg idx, HReg base)
    465 {
    466    MIPSAMode *am = LibVEX_Alloc_inline(sizeof(MIPSAMode));
    467    am->tag = Mam_RR;
    468    am->Mam.RR.base = base;
    469    am->Mam.RR.index = idx;
    470 
    471    return am;
    472 }
    473 
    474 MIPSAMode *dopyMIPSAMode(MIPSAMode * am)
    475 {
    476    MIPSAMode* ret;
    477    switch (am->tag) {
    478       case Mam_IR:
    479          ret = MIPSAMode_IR(am->Mam.IR.index, am->Mam.IR.base);
    480          break;
    481       case Mam_RR:
    482          ret = MIPSAMode_RR(am->Mam.RR.index, am->Mam.RR.base);
    483          break;
    484       default:
    485          vpanic("dopyMIPSAMode");
    486          break;
    487    }
    488    return ret;
    489 }
    490 
    491 MIPSAMode *nextMIPSAModeFloat(MIPSAMode * am)
    492 {
    493    MIPSAMode* ret;
    494    switch (am->tag) {
    495       case Mam_IR:
    496          ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
    497          break;
    498       case Mam_RR:
    499          /* We can't do anything with the RR case, so if it appears
    500             we simply have to give up. */
    501          /* fallthrough */
    502       default:
    503          vpanic("nextMIPSAModeFloat");
    504          break;
    505    }
    506    return ret;
    507 }
    508 
    509 MIPSAMode *nextMIPSAModeInt(MIPSAMode * am)
    510 {
    511    MIPSAMode* ret;
    512    switch (am->tag) {
    513       case Mam_IR:
    514          ret = MIPSAMode_IR(am->Mam.IR.index + 4, am->Mam.IR.base);
    515          break;
    516       case Mam_RR:
    517          /* We can't do anything with the RR case, so if it appears
    518             we simply have to give up. */
    519          /* fallthrough */
    520       default:
    521          vpanic("nextMIPSAModeInt");
    522          break;
    523    }
    524    return ret;
    525 }
    526 
    527 void ppMIPSAMode(MIPSAMode * am, Bool mode64)
    528 {
    529    switch (am->tag) {
    530       case Mam_IR:
    531          if (am->Mam.IR.index == 0)
    532             vex_printf("0(");
    533          else
    534             vex_printf("%d(", (Int) am->Mam.IR.index);
    535          ppHRegMIPS(am->Mam.IR.base, mode64);
    536          vex_printf(")");
    537          return;
    538       case Mam_RR:
    539          ppHRegMIPS(am->Mam.RR.base, mode64);
    540          vex_printf(", ");
    541          ppHRegMIPS(am->Mam.RR.index, mode64);
    542          return;
    543       default:
    544          vpanic("ppMIPSAMode");
    545          break;
    546    }
    547 }
    548 
    549 static void addRegUsage_MIPSAMode(HRegUsage * u, MIPSAMode * am)
    550 {
    551    switch (am->tag) {
    552       case Mam_IR:
    553          addHRegUse(u, HRmRead, am->Mam.IR.base);
    554          return;
    555       case Mam_RR:
    556          addHRegUse(u, HRmRead, am->Mam.RR.base);
    557          addHRegUse(u, HRmRead, am->Mam.RR.index);
    558          return;
    559       default:
    560          vpanic("addRegUsage_MIPSAMode");
    561          break;
    562    }
    563 }
    564 
    565 static void mapRegs_MIPSAMode(HRegRemap * m, MIPSAMode * am)
    566 {
    567    switch (am->tag) {
    568       case Mam_IR:
    569          am->Mam.IR.base = lookupHRegRemap(m, am->Mam.IR.base);
    570          return;
    571       case Mam_RR:
    572          am->Mam.RR.base = lookupHRegRemap(m, am->Mam.RR.base);
    573          am->Mam.RR.index = lookupHRegRemap(m, am->Mam.RR.index);
    574          return;
    575       default:
    576          vpanic("mapRegs_MIPSAMode");
    577          break;
    578    }
    579 }
    580 
    581 /* --------- Operand, which can be a reg or a u16/s16. --------- */
    582 
    583 MIPSRH *MIPSRH_Imm(Bool syned, UShort imm16)
    584 {
    585    MIPSRH *op = LibVEX_Alloc_inline(sizeof(MIPSRH));
    586    op->tag = Mrh_Imm;
    587    op->Mrh.Imm.syned = syned;
    588    op->Mrh.Imm.imm16 = imm16;
    589    /* If this is a signed value, ensure it's not -32768, so that we
    590       are guaranteed always to be able to negate if needed. */
    591    if (syned)
    592       vassert(imm16 != 0x8000);
    593    vassert(syned == True || syned == False);
    594    return op;
    595 }
    596 
    597 MIPSRH *MIPSRH_Reg(HReg reg)
    598 {
    599    MIPSRH *op = LibVEX_Alloc_inline(sizeof(MIPSRH));
    600    op->tag = Mrh_Reg;
    601    op->Mrh.Reg.reg = reg;
    602    return op;
    603 }
    604 
    605 void ppMIPSRH(MIPSRH * op, Bool mode64)
    606 {
    607    MIPSRHTag tag = op->tag;
    608    switch (tag) {
    609       case Mrh_Imm:
    610          if (op->Mrh.Imm.syned)
    611             vex_printf("%d", (Int) (Short) op->Mrh.Imm.imm16);
    612          else
    613             vex_printf("%u", (UInt) (UShort) op->Mrh.Imm.imm16);
    614          return;
    615       case Mrh_Reg:
    616          ppHRegMIPS(op->Mrh.Reg.reg, mode64);
    617          return;
    618       default:
    619          vpanic("ppMIPSRH");
    620          break;
    621    }
    622 }
    623 
    624 /* An MIPSRH can only be used in a "read" context (what would it mean
    625    to write or modify a literal?) and so we enumerate its registers
    626    accordingly. */
    627 static void addRegUsage_MIPSRH(HRegUsage * u, MIPSRH * op)
    628 {
    629    switch (op->tag) {
    630       case Mrh_Imm:
    631          return;
    632       case Mrh_Reg:
    633          addHRegUse(u, HRmRead, op->Mrh.Reg.reg);
    634          return;
    635       default:
    636          vpanic("addRegUsage_MIPSRH");
    637          break;
    638    }
    639 }
    640 
    641 static void mapRegs_MIPSRH(HRegRemap * m, MIPSRH * op)
    642 {
    643    switch (op->tag) {
    644       case Mrh_Imm:
    645          return;
    646       case Mrh_Reg:
    647          op->Mrh.Reg.reg = lookupHRegRemap(m, op->Mrh.Reg.reg);
    648          return;
    649       default:
    650          vpanic("mapRegs_MIPSRH");
    651          break;
    652    }
    653 }
    654 
    655 /* --------- Instructions. --------- */
    656 
    657 const HChar *showMIPSUnaryOp(MIPSUnaryOp op)
    658 {
    659    const HChar* ret;
    660    switch (op) {
    661       case Mun_CLO:
    662          ret = "clo";
    663          break;
    664       case Mun_CLZ:
    665          ret = "clz";
    666          break;
    667       case Mun_NOP:
    668          ret = "nop";
    669          break;
    670       case Mun_DCLO:
    671          ret = "dclo";
    672          break;
    673       case Mun_DCLZ:
    674          ret = "dclz";
    675          break;
    676       default:
    677          vpanic("showMIPSUnaryOp");
    678          break;
    679    }
    680    return ret;
    681 }
    682 
    683 const HChar *showMIPSAluOp(MIPSAluOp op, Bool immR)
    684 {
    685    const HChar* ret;
    686    switch (op) {
    687       case Malu_ADD:
    688          ret = immR ? "addiu" : "addu";
    689          break;
    690       case Malu_SUB:
    691          ret = "subu";
    692          break;
    693       case Malu_AND:
    694          ret = immR ? "andi" : "and";
    695          break;
    696       case Malu_OR:
    697          ret = immR ? "ori" : "or";
    698          break;
    699       case Malu_NOR:
    700          vassert(immR == False); /*there's no nor with an immediate operand!? */
    701          ret = "nor";
    702          break;
    703       case Malu_XOR:
    704          ret = immR ? "xori" : "xor";
    705          break;
    706       case Malu_DADD:
    707          ret = immR ? "daddi" : "dadd";
    708          break;
    709       case Malu_DSUB:
    710          ret = immR ? "dsubi" : "dsub";
    711          break;
    712       case Malu_SLT:
    713          ret = immR ? "slti" : "slt";
    714          break;
    715       default:
    716          vpanic("showMIPSAluOp");
    717          break;
    718    }
    719    return ret;
    720 }
    721 
    722 const HChar *showMIPSShftOp(MIPSShftOp op, Bool immR, Bool sz32)
    723 {
    724    const HChar *ret;
    725    switch (op) {
    726       case Mshft_SRA:
    727          ret = immR ? (sz32 ? "sra" : "dsra") : (sz32 ? "srav" : "dsrav");
    728          break;
    729       case Mshft_SLL:
    730          ret = immR ? (sz32 ? "sll" : "dsll") : (sz32 ? "sllv" : "dsllv");
    731          break;
    732       case Mshft_SRL:
    733          ret = immR ? (sz32 ? "srl" : "dsrl") : (sz32 ? "srlv" : "dsrlv");
    734          break;
    735       default:
    736          vpanic("showMIPSShftOp");
    737          break;
    738    }
    739    return ret;
    740 }
    741 
    742 const HChar *showMIPSMaccOp(MIPSMaccOp op, Bool variable)
    743 {
    744    const HChar *ret;
    745    switch (op) {
    746       case Macc_ADD:
    747          ret = variable ? "madd" : "maddu";
    748          break;
    749       case Macc_SUB:
    750          ret = variable ? "msub" : "msubu";
    751          break;
    752       default:
    753          vpanic("showMIPSAccOp");
    754          break;
    755    }
    756    return ret;
    757 }
    758 
    759 MIPSInstr *MIPSInstr_LI(HReg dst, ULong imm)
    760 {
    761    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    762    i->tag = Min_LI;
    763    i->Min.LI.dst = dst;
    764    i->Min.LI.imm = imm;
    765    return i;
    766 }
    767 
    768 MIPSInstr *MIPSInstr_Alu(MIPSAluOp op, HReg dst, HReg srcL, MIPSRH * srcR)
    769 {
    770    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    771    i->tag = Min_Alu;
    772    i->Min.Alu.op = op;
    773    i->Min.Alu.dst = dst;
    774    i->Min.Alu.srcL = srcL;
    775    i->Min.Alu.srcR = srcR;
    776    return i;
    777 }
    778 
    779 MIPSInstr *MIPSInstr_Shft(MIPSShftOp op, Bool sz32, HReg dst, HReg srcL,
    780                           MIPSRH * srcR)
    781 {
    782    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    783    i->tag = Min_Shft;
    784    i->Min.Shft.op = op;
    785    i->Min.Shft.sz32 = sz32;
    786    i->Min.Shft.dst = dst;
    787    i->Min.Shft.srcL = srcL;
    788    i->Min.Shft.srcR = srcR;
    789    return i;
    790 }
    791 
    792 MIPSInstr *MIPSInstr_Unary(MIPSUnaryOp op, HReg dst, HReg src)
    793 {
    794    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    795    i->tag = Min_Unary;
    796    i->Min.Unary.op = op;
    797    i->Min.Unary.dst = dst;
    798    i->Min.Unary.src = src;
    799    return i;
    800 }
    801 
    802 MIPSInstr *MIPSInstr_Cmp(Bool syned, Bool sz32, HReg dst, HReg srcL, HReg srcR,
    803                          MIPSCondCode cond)
    804 {
    805    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    806    i->tag = Min_Cmp;
    807    i->Min.Cmp.syned = syned;
    808    i->Min.Cmp.sz32 = sz32;
    809    i->Min.Cmp.dst = dst;
    810    i->Min.Cmp.srcL = srcL;
    811    i->Min.Cmp.srcR = srcR;
    812    i->Min.Cmp.cond = cond;
    813    return i;
    814 }
    815 
    816 /* multiply */
    817 MIPSInstr *MIPSInstr_Mul(Bool syned, Bool wid, Bool sz32, HReg dst, HReg srcL,
    818                          HReg srcR)
    819 {
    820    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    821    i->tag = Min_Mul;
    822    i->Min.Mul.syned = syned;
    823    i->Min.Mul.widening = wid; /* widen=True else False */
    824    i->Min.Mul.sz32 = sz32; /* True = 32 bits */
    825    i->Min.Mul.dst = dst;
    826    i->Min.Mul.srcL = srcL;
    827    i->Min.Mul.srcR = srcR;
    828    return i;
    829 }
    830 
    831 /* msub */
    832 MIPSInstr *MIPSInstr_Msub(Bool syned, HReg srcL, HReg srcR)
    833 {
    834    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    835    i->tag = Min_Macc;
    836 
    837    i->Min.Macc.op = Macc_SUB;
    838    i->Min.Macc.syned = syned;
    839    i->Min.Macc.srcL = srcL;
    840    i->Min.Macc.srcR = srcR;
    841    return i;
    842 }
    843 
    844 /* madd */
    845 MIPSInstr *MIPSInstr_Madd(Bool syned, HReg srcL, HReg srcR)
    846 {
    847    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    848    i->tag = Min_Macc;
    849 
    850    i->Min.Macc.op = Macc_ADD;
    851    i->Min.Macc.syned = syned;
    852    i->Min.Macc.srcL = srcL;
    853    i->Min.Macc.srcR = srcR;
    854    return i;
    855 }
    856 
    857 /* div */
    858 MIPSInstr *MIPSInstr_Div(Bool syned, Bool sz32, HReg srcL, HReg srcR)
    859 {
    860    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    861    i->tag = Min_Div;
    862    i->Min.Div.syned = syned;
    863    i->Min.Div.sz32 = sz32; /* True = 32 bits */
    864    i->Min.Div.srcL = srcL;
    865    i->Min.Div.srcR = srcR;
    866    return i;
    867 }
    868 
    869 MIPSInstr *MIPSInstr_Call ( MIPSCondCode cond, Addr64 target, UInt argiregs,
    870                             HReg src, RetLoc rloc )
    871 {
    872    UInt mask;
    873    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    874    i->tag = Min_Call;
    875    i->Min.Call.cond = cond;
    876    i->Min.Call.target = target;
    877    i->Min.Call.argiregs = argiregs;
    878    i->Min.Call.src = src;
    879    i->Min.Call.rloc = rloc;
    880    /* Only $4 .. $7/$11 inclusive may be used as arg regs. */
    881    mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)
    882           | (1 << 10) | (1 << 11);
    883    vassert(0 == (argiregs & ~mask));
    884    vassert(is_sane_RetLoc(rloc));
    885    return i;
    886 }
    887 
    888 MIPSInstr *MIPSInstr_CallAlways ( MIPSCondCode cond, Addr64 target,
    889                                   UInt argiregs, RetLoc rloc )
    890 {
    891    UInt mask;
    892    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    893    i->tag = Min_Call;
    894    i->Min.Call.cond = cond;
    895    i->Min.Call.target = target;
    896    i->Min.Call.argiregs = argiregs;
    897    i->Min.Call.rloc = rloc;
    898    /* Only $4 .. $7/$11 inclusive may be used as arg regs. */
    899    mask = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)
    900           | (1 << 10) | (1 << 11);
    901    vassert(0 == (argiregs & ~mask));
    902    vassert(is_sane_RetLoc(rloc));
    903    return i;
    904 }
    905 
    906 MIPSInstr *MIPSInstr_XDirect ( Addr64 dstGA, MIPSAMode* amPC,
    907                                MIPSCondCode cond, Bool toFastEP ) {
    908    MIPSInstr* i               = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    909    i->tag                     = Min_XDirect;
    910    i->Min.XDirect.dstGA       = dstGA;
    911    i->Min.XDirect.amPC        = amPC;
    912    i->Min.XDirect.cond        = cond;
    913    i->Min.XDirect.toFastEP    = toFastEP;
    914    return i;
    915 }
    916 
    917 MIPSInstr *MIPSInstr_XIndir ( HReg dstGA, MIPSAMode* amPC,
    918                               MIPSCondCode cond ) {
    919    MIPSInstr* i            = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    920    i->tag                  = Min_XIndir;
    921    i->Min.XIndir.dstGA     = dstGA;
    922    i->Min.XIndir.amPC      = amPC;
    923    i->Min.XIndir.cond      = cond;
    924    return i;
    925 }
    926 
    927 MIPSInstr *MIPSInstr_XAssisted ( HReg dstGA, MIPSAMode* amPC,
    928                                  MIPSCondCode cond, IRJumpKind jk ) {
    929    MIPSInstr* i               = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    930    i->tag                     = Min_XAssisted;
    931    i->Min.XAssisted.dstGA     = dstGA;
    932    i->Min.XAssisted.amPC      = amPC;
    933    i->Min.XAssisted.cond      = cond;
    934    i->Min.XAssisted.jk        = jk;
    935    return i;
    936 }
    937 
    938 MIPSInstr *MIPSInstr_Load(UChar sz, HReg dst, MIPSAMode * src, Bool mode64)
    939 {
    940    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    941    i->tag = Min_Load;
    942    i->Min.Load.sz = sz;
    943    i->Min.Load.src = src;
    944    i->Min.Load.dst = dst;
    945    vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    946 
    947    if (sz == 8)
    948       vassert(mode64);
    949    return i;
    950 }
    951 
    952 MIPSInstr *MIPSInstr_Store(UChar sz, MIPSAMode * dst, HReg src, Bool mode64)
    953 {
    954    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    955    i->tag = Min_Store;
    956    i->Min.Store.sz = sz;
    957    i->Min.Store.src = src;
    958    i->Min.Store.dst = dst;
    959    vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    960 
    961    if (sz == 8)
    962       vassert(mode64);
    963    return i;
    964 }
    965 
    966 MIPSInstr *MIPSInstr_LoadL(UChar sz, HReg dst, MIPSAMode * src, Bool mode64)
    967 {
    968    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    969    i->tag = Min_LoadL;
    970    i->Min.LoadL.sz  = sz;
    971    i->Min.LoadL.src = src;
    972    i->Min.LoadL.dst = dst;
    973    vassert(sz == 4 || sz == 8);
    974 
    975    if (sz == 8)
    976       vassert(mode64);
    977    return i;
    978 }
    979 
    980 MIPSInstr *MIPSInstr_Cas(UChar sz, HReg old, HReg addr,
    981                          HReg expd, HReg data, Bool mode64)
    982 {
    983    MIPSInstr *i    = LibVEX_Alloc_inline(sizeof(MIPSInstr));
    984    i->tag          = Min_Cas;
    985    i->Min.Cas.sz   = sz;
    986    i->Min.Cas.old  = old;
    987    i->Min.Cas.addr = addr;
    988    i->Min.Cas.expd = expd;
    989    i->Min.Cas.data = data;
    990    vassert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
    991 
    992    if (sz == 8)
    993       vassert(mode64);
    994    return i;
    995 }
    996 
    997 MIPSInstr *MIPSInstr_StoreC(UChar sz, MIPSAMode * dst, HReg src, Bool mode64)
    998 {
    999    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1000    i->tag = Min_StoreC;
   1001    i->Min.StoreC.sz  = sz;
   1002    i->Min.StoreC.src = src;
   1003    i->Min.StoreC.dst = dst;
   1004    vassert(sz == 4 || sz == 8);
   1005 
   1006    if (sz == 8)
   1007       vassert(mode64);
   1008    return i;
   1009 }
   1010 
   1011 MIPSInstr *MIPSInstr_Mthi(HReg src)
   1012 {
   1013    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1014    i->tag = Min_Mthi;
   1015    i->Min.MtHL.src = src;
   1016    return i;
   1017 }
   1018 
   1019 MIPSInstr *MIPSInstr_Mtlo(HReg src)
   1020 {
   1021    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1022    i->tag = Min_Mtlo;
   1023    i->Min.MtHL.src = src;
   1024    return i;
   1025 }
   1026 
   1027 MIPSInstr *MIPSInstr_Mfhi(HReg dst)
   1028 {
   1029    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1030    i->tag = Min_Mfhi;
   1031    i->Min.MfHL.dst = dst;
   1032    return i;
   1033 }
   1034 
   1035 MIPSInstr *MIPSInstr_Mflo(HReg dst)
   1036 {
   1037    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1038    i->tag = Min_Mflo;
   1039    i->Min.MfHL.dst = dst;
   1040    return i;
   1041 }
   1042 
   1043 /* Read/Write Link Register */
   1044 MIPSInstr *MIPSInstr_RdWrLR(Bool wrLR, HReg gpr)
   1045 {
   1046    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1047    i->tag = Min_RdWrLR;
   1048    i->Min.RdWrLR.wrLR = wrLR;
   1049    i->Min.RdWrLR.gpr = gpr;
   1050    return i;
   1051 }
   1052 
   1053 MIPSInstr *MIPSInstr_FpLdSt(Bool isLoad, UChar sz, HReg reg, MIPSAMode * addr)
   1054 {
   1055    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1056    i->tag = Min_FpLdSt;
   1057    i->Min.FpLdSt.isLoad = isLoad;
   1058    i->Min.FpLdSt.sz = sz;
   1059    i->Min.FpLdSt.reg = reg;
   1060    i->Min.FpLdSt.addr = addr;
   1061    vassert(sz == 4 || sz == 8);
   1062    return i;
   1063 }
   1064 
   1065 MIPSInstr *MIPSInstr_FpUnary(MIPSFpOp op, HReg dst, HReg src)
   1066 {
   1067    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1068    i->tag = Min_FpUnary;
   1069    i->Min.FpUnary.op = op;
   1070    i->Min.FpUnary.dst = dst;
   1071    i->Min.FpUnary.src = src;
   1072    return i;
   1073 }
   1074 
   1075 MIPSInstr *MIPSInstr_FpBinary(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR)
   1076 {
   1077    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1078    i->tag = Min_FpBinary;
   1079    i->Min.FpBinary.op = op;
   1080    i->Min.FpBinary.dst = dst;
   1081    i->Min.FpBinary.srcL = srcL;
   1082    i->Min.FpBinary.srcR = srcR;
   1083    return i;
   1084 }
   1085 
   1086 MIPSInstr *MIPSInstr_FpTernary ( MIPSFpOp op, HReg dst, HReg src1, HReg src2,
   1087                                  HReg src3 )
   1088 {
   1089    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1090    i->tag = Min_FpTernary;
   1091    i->Min.FpTernary.op = op;
   1092    i->Min.FpTernary.dst = dst;
   1093    i->Min.FpTernary.src1 = src1;
   1094    i->Min.FpTernary.src2 = src2;
   1095    i->Min.FpTernary.src3 = src3;
   1096    return i;
   1097 }
   1098 
   1099 MIPSInstr *MIPSInstr_FpConvert(MIPSFpOp op, HReg dst, HReg src)
   1100 {
   1101    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1102    i->tag = Min_FpConvert;
   1103    i->Min.FpConvert.op = op;
   1104    i->Min.FpConvert.dst = dst;
   1105    i->Min.FpConvert.src = src;
   1106    return i;
   1107 
   1108 }
   1109 
   1110 MIPSInstr *MIPSInstr_FpCompare(MIPSFpOp op, HReg dst, HReg srcL, HReg srcR)
   1111 {
   1112    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1113    i->tag = Min_FpCompare;
   1114    i->Min.FpCompare.op = op;
   1115    i->Min.FpCompare.dst = dst;
   1116    i->Min.FpCompare.srcL = srcL;
   1117    i->Min.FpCompare.srcR = srcR;
   1118    return i;
   1119 }
   1120 
   1121 MIPSInstr *MIPSInstr_MtFCSR(HReg src)
   1122 {
   1123    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1124    i->tag = Min_MtFCSR;
   1125    i->Min.MtFCSR.src = src;
   1126    return i;
   1127 }
   1128 
   1129 MIPSInstr *MIPSInstr_MfFCSR(HReg dst)
   1130 {
   1131    MIPSInstr *i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1132    i->tag = Min_MfFCSR;
   1133    i->Min.MfFCSR.dst = dst;
   1134    return i;
   1135 }
   1136 
   1137 MIPSInstr *MIPSInstr_FpGpMove ( MIPSFpGpMoveOp op, HReg dst, HReg src )
   1138 {
   1139    MIPSInstr *i        = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1140    i->tag              = Min_FpGpMove;
   1141    i->Min.FpGpMove.op  = op;
   1142    i->Min.FpGpMove.dst = dst;
   1143    i->Min.FpGpMove.src = src;
   1144    return i;
   1145 }
   1146 
   1147 MIPSInstr *MIPSInstr_MoveCond ( MIPSMoveCondOp op, HReg dst, HReg src,
   1148                                 HReg cond )
   1149 {
   1150    MIPSInstr *i        = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1151    i->tag              = Min_MoveCond;
   1152    i->Min.MoveCond.op  = op;
   1153    i->Min.MoveCond.dst = dst;
   1154    i->Min.MoveCond.src = src;
   1155    i->Min.MoveCond.cond = cond;
   1156    return i;
   1157 }
   1158 
   1159 MIPSInstr *MIPSInstr_EvCheck ( MIPSAMode* amCounter,
   1160                             MIPSAMode* amFailAddr ) {
   1161    MIPSInstr* i                 = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1162    i->tag                       = Min_EvCheck;
   1163    i->Min.EvCheck.amCounter     = amCounter;
   1164    i->Min.EvCheck.amFailAddr    = amFailAddr;
   1165    return i;
   1166 }
   1167 
   1168 MIPSInstr* MIPSInstr_ProfInc ( void ) {
   1169    MIPSInstr* i = LibVEX_Alloc_inline(sizeof(MIPSInstr));
   1170    i->tag       = Min_ProfInc;
   1171    return i;
   1172 }
   1173 
   1174 /* -------- Pretty Print instructions ------------- */
   1175 static void ppLoadImm(HReg dst, ULong imm, Bool mode64)
   1176 {
   1177    vex_printf("li ");
   1178    ppHRegMIPS(dst, mode64);
   1179    vex_printf(",0x%016llx", imm);
   1180 }
   1181 
   1182 void ppMIPSInstr(const MIPSInstr * i, Bool mode64)
   1183 {
   1184    switch (i->tag) {
   1185       case Min_LI:
   1186          ppLoadImm(i->Min.LI.dst, i->Min.LI.imm, mode64);
   1187          break;
   1188       case Min_Alu: {
   1189          HReg r_srcL = i->Min.Alu.srcL;
   1190          MIPSRH *rh_srcR = i->Min.Alu.srcR;
   1191          /* generic */
   1192          vex_printf("%s ", showMIPSAluOp(i->Min.Alu.op,
   1193                                          toBool(rh_srcR->tag == Mrh_Imm)));
   1194          ppHRegMIPS(i->Min.Alu.dst, mode64);
   1195          vex_printf(",");
   1196          ppHRegMIPS(r_srcL, mode64);
   1197          vex_printf(",");
   1198          ppMIPSRH(rh_srcR, mode64);
   1199          return;
   1200       }
   1201       case Min_Shft: {
   1202          HReg r_srcL = i->Min.Shft.srcL;
   1203          MIPSRH *rh_srcR = i->Min.Shft.srcR;
   1204          vex_printf("%s ", showMIPSShftOp(i->Min.Shft.op,
   1205                                           toBool(rh_srcR->tag == Mrh_Imm),
   1206                                           i->Min.Shft.sz32));
   1207          ppHRegMIPS(i->Min.Shft.dst, mode64);
   1208          vex_printf(",");
   1209          ppHRegMIPS(r_srcL, mode64);
   1210          vex_printf(",");
   1211          ppMIPSRH(rh_srcR, mode64);
   1212          return;
   1213       }
   1214       case Min_Unary: {
   1215          vex_printf("%s ", showMIPSUnaryOp(i->Min.Unary.op));
   1216          ppHRegMIPS(i->Min.Unary.dst, mode64);
   1217          vex_printf(",");
   1218          ppHRegMIPS(i->Min.Unary.src, mode64);
   1219          return;
   1220       }
   1221       case Min_Cmp: {
   1222          vex_printf("word_compare ");
   1223          ppHRegMIPS(i->Min.Cmp.dst, mode64);
   1224          vex_printf(" = %s ( ", showMIPSCondCode(i->Min.Cmp.cond));
   1225          ppHRegMIPS(i->Min.Cmp.srcL, mode64);
   1226          vex_printf(", ");
   1227          ppHRegMIPS(i->Min.Cmp.srcR, mode64);
   1228          vex_printf(" )");
   1229 
   1230          return;
   1231       }
   1232       case Min_Mul: {
   1233          switch (i->Min.Mul.widening) {
   1234             case False:
   1235                vex_printf("mul ");
   1236                ppHRegMIPS(i->Min.Mul.dst, mode64);
   1237                vex_printf(", ");
   1238                ppHRegMIPS(i->Min.Mul.srcL, mode64);
   1239                vex_printf(", ");
   1240                ppHRegMIPS(i->Min.Mul.srcR, mode64);
   1241                return;
   1242             case True:
   1243                vex_printf("%s%s ", i->Min.Mul.sz32 ? "mult" : "dmult",
   1244                                    i->Min.Mul.syned ? "" : "u");
   1245                ppHRegMIPS(i->Min.Mul.dst, mode64);
   1246                vex_printf(", ");
   1247                ppHRegMIPS(i->Min.Mul.srcL, mode64);
   1248                vex_printf(", ");
   1249                ppHRegMIPS(i->Min.Mul.srcR, mode64);
   1250                return;
   1251             }
   1252          break;
   1253       }
   1254       case Min_Mthi: {
   1255          vex_printf("mthi ");
   1256          ppHRegMIPS(i->Min.MtHL.src, mode64);
   1257          return;
   1258       }
   1259       case Min_Mtlo: {
   1260          vex_printf("mtlo ");
   1261          ppHRegMIPS(i->Min.MtHL.src, mode64);
   1262          return;
   1263       }
   1264       case Min_Mfhi: {
   1265          vex_printf("mfhi ");
   1266          ppHRegMIPS(i->Min.MfHL.dst, mode64);
   1267          return;
   1268       }
   1269       case Min_Mflo: {
   1270          vex_printf("mflo ");
   1271          ppHRegMIPS(i->Min.MfHL.dst, mode64);
   1272          return;
   1273       }
   1274       case Min_Macc: {
   1275          vex_printf("%s ", showMIPSMaccOp(i->Min.Macc.op, i->Min.Macc.syned));
   1276          ppHRegMIPS(i->Min.Macc.srcL, mode64);
   1277          vex_printf(", ");
   1278          ppHRegMIPS(i->Min.Macc.srcR, mode64);
   1279          return;
   1280       }
   1281       case Min_Div: {
   1282          if (!i->Min.Div.sz32)
   1283             vex_printf("d");
   1284          vex_printf("div");
   1285          vex_printf("%s ", i->Min.Div.syned ? "s" : "u");
   1286          ppHRegMIPS(i->Min.Div.srcL, mode64);
   1287          vex_printf(", ");
   1288          ppHRegMIPS(i->Min.Div.srcR, mode64);
   1289          return;
   1290       }
   1291       case Min_Call: {
   1292          Int n;
   1293          vex_printf("call: ");
   1294          if (i->Min.Call.cond != MIPScc_AL) {
   1295             vex_printf("if (%s) ", showMIPSCondCode(i->Min.Call.cond));
   1296          }
   1297          vex_printf(" {");
   1298          if (!mode64)
   1299             vex_printf(" addiu $29, $29, -16");
   1300 
   1301          ppLoadImm(hregMIPS_GPR25(mode64), i->Min.Call.target, mode64);
   1302 
   1303          vex_printf(" ; jarl $31, $25; # args [");
   1304          for (n = 0; n < 32; n++) {
   1305             if (i->Min.Call.argiregs & (1 << n)) {
   1306                vex_printf("$%d", n);
   1307                if ((i->Min.Call.argiregs >> n) > 1)
   1308                   vex_printf(",");
   1309             }
   1310          }
   1311          vex_printf("] nop; ");
   1312          if (!mode64)
   1313             vex_printf("addiu $29, $29, 16; ]");
   1314 
   1315          break;
   1316       }
   1317       case Min_XDirect:
   1318          vex_printf("(xDirect) ");
   1319          vex_printf("if (guest_COND.%s) { ",
   1320                     showMIPSCondCode(i->Min.XDirect.cond));
   1321          vex_printf("move $9, 0x%x,", (UInt)i->Min.XDirect.dstGA);
   1322          vex_printf("; sw $9, ");
   1323          ppMIPSAMode(i->Min.XDirect.amPC, mode64);
   1324          vex_printf("; move $9, $disp_cp_chain_me_to_%sEP; jalr $9; nop}",
   1325                     i->Min.XDirect.toFastEP ? "fast" : "slow");
   1326          return;
   1327       case Min_XIndir:
   1328          vex_printf("(xIndir) ");
   1329          vex_printf("if (guest_COND.%s) { sw ",
   1330                     showMIPSCondCode(i->Min.XIndir.cond));
   1331          ppHRegMIPS(i->Min.XIndir.dstGA, mode64);
   1332          vex_printf(", ");
   1333          ppMIPSAMode(i->Min.XIndir.amPC, mode64);
   1334          vex_printf("; move $9, $disp_indir; jalr $9; nop}");
   1335          return;
   1336       case Min_XAssisted:
   1337          vex_printf("(xAssisted) ");
   1338          vex_printf("if (guest_COND.%s) { ",
   1339                     showMIPSCondCode(i->Min.XAssisted.cond));
   1340          vex_printf("sw ");
   1341          ppHRegMIPS(i->Min.XAssisted.dstGA, mode64);
   1342          vex_printf(", ");
   1343          ppMIPSAMode(i->Min.XAssisted.amPC, mode64);
   1344          vex_printf("; move $9, $IRJumpKind_to_TRCVAL(%d)",
   1345                     (Int)i->Min.XAssisted.jk);
   1346          vex_printf("; move $9, $disp_assisted; jalr $9; nop; }");
   1347          return;
   1348       case Min_Load: {
   1349          Bool idxd = toBool(i->Min.Load.src->tag == Mam_RR);
   1350          UChar sz = i->Min.Load.sz;
   1351          HChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd';
   1352          vex_printf("l%c%s ", c_sz, idxd ? "x" : "");
   1353          ppHRegMIPS(i->Min.Load.dst, mode64);
   1354          vex_printf(",");
   1355          ppMIPSAMode(i->Min.Load.src, mode64);
   1356          return;
   1357       }
   1358       case Min_Store: {
   1359          UChar sz = i->Min.Store.sz;
   1360          Bool idxd = toBool(i->Min.Store.dst->tag == Mam_RR);
   1361          HChar c_sz = sz == 1 ? 'b' : sz == 2 ? 'h' : sz == 4 ? 'w' : 'd';
   1362          vex_printf("s%c%s ", c_sz, idxd ? "x" : "");
   1363          ppHRegMIPS(i->Min.Store.src, mode64);
   1364          vex_printf(",");
   1365          ppMIPSAMode(i->Min.Store.dst, mode64);
   1366          return;
   1367       }
   1368       case Min_LoadL: {
   1369          vex_printf("ll ");
   1370          ppHRegMIPS(i->Min.LoadL.dst, mode64);
   1371          vex_printf(",");
   1372          ppMIPSAMode(i->Min.LoadL.src, mode64);
   1373          return;
   1374       }
   1375       case Min_Cas: {
   1376           Bool sz8  = toBool(i->Min.Cas.sz == 8);
   1377           /*
   1378            * ll(d)    old,  0(addr)
   1379            * bne      old,  expd, end
   1380            * nop
   1381            * (d)addiu old,  old,  1
   1382            * sc(d)    data, 0(addr)
   1383            * movn     old,  expd, data
   1384            * end:
   1385            */
   1386           // ll(d) old, 0(addr)
   1387          vex_printf("cas: ");
   1388 
   1389          vex_printf("%s ", sz8 ? "lld" : "ll");
   1390          ppHRegMIPS(i->Min.Cas.old , mode64);
   1391          vex_printf(", 0(");
   1392          ppHRegMIPS(i->Min.Cas.addr , mode64);
   1393          vex_printf(")\n");
   1394 
   1395          vex_printf("bne ");
   1396          ppHRegMIPS(i->Min.Cas.old , mode64);
   1397          vex_printf(", ");
   1398          ppHRegMIPS(i->Min.Cas.expd , mode64);
   1399          vex_printf(", end\n");
   1400 
   1401          vex_printf("nop\n");
   1402 
   1403          vex_printf("%s ", sz8 ? "daddiu" : "addiu");
   1404          ppHRegMIPS(i->Min.Cas.old , mode64);
   1405          vex_printf(", ");
   1406          ppHRegMIPS(i->Min.Cas.old , mode64);
   1407          vex_printf(", 1\n");
   1408 
   1409          vex_printf("%s ", sz8 ? "scd" : "sc");
   1410          ppHRegMIPS(i->Min.Cas.data , mode64);
   1411          vex_printf(", 0(");
   1412          ppHRegMIPS(i->Min.Cas.addr , mode64);
   1413          vex_printf(")\n");
   1414 
   1415          vex_printf("movn ");
   1416          ppHRegMIPS(i->Min.Cas.old , mode64);
   1417          vex_printf(", ");
   1418          ppHRegMIPS(i->Min.Cas.expd , mode64);
   1419          vex_printf(", ");
   1420          ppHRegMIPS(i->Min.Cas.data , mode64);
   1421          vex_printf("\nend:");
   1422          return;
   1423       }
   1424       case Min_StoreC: {
   1425          vex_printf("sc ");
   1426          ppHRegMIPS(i->Min.StoreC.src, mode64);
   1427          vex_printf(",");
   1428          ppMIPSAMode(i->Min.StoreC.dst, mode64);
   1429          return;
   1430       }
   1431       case Min_RdWrLR: {
   1432          vex_printf("%s ", i->Min.RdWrLR.wrLR ? "mtlr" : "mflr");
   1433          ppHRegMIPS(i->Min.RdWrLR.gpr, mode64);
   1434          return;
   1435       }
   1436       case Min_FpUnary:
   1437          vex_printf("%s ", showMIPSFpOp(i->Min.FpUnary.op));
   1438          ppHRegMIPS(i->Min.FpUnary.dst, mode64);
   1439          vex_printf(",");
   1440          ppHRegMIPS(i->Min.FpUnary.src, mode64);
   1441          return;
   1442       case Min_FpBinary:
   1443          vex_printf("%s", showMIPSFpOp(i->Min.FpBinary.op));
   1444          ppHRegMIPS(i->Min.FpBinary.dst, mode64);
   1445          vex_printf(",");
   1446          ppHRegMIPS(i->Min.FpBinary.srcL, mode64);
   1447          vex_printf(",");
   1448          ppHRegMIPS(i->Min.FpBinary.srcR, mode64);
   1449          return;
   1450       case Min_FpTernary:
   1451          vex_printf("%s", showMIPSFpOp(i->Min.FpTernary.op));
   1452          ppHRegMIPS(i->Min.FpTernary.dst, mode64);
   1453          vex_printf(",");
   1454          ppHRegMIPS(i->Min.FpTernary.src1, mode64);
   1455          vex_printf(",");
   1456          ppHRegMIPS(i->Min.FpTernary.src2, mode64);
   1457          vex_printf(",");
   1458          ppHRegMIPS(i->Min.FpTernary.src3, mode64);
   1459          return;
   1460       case Min_FpConvert:
   1461          vex_printf("%s", showMIPSFpOp(i->Min.FpConvert.op));
   1462          ppHRegMIPS(i->Min.FpConvert.dst, mode64);
   1463          vex_printf(",");
   1464          ppHRegMIPS(i->Min.FpConvert.src, mode64);
   1465          return;
   1466       case Min_FpCompare:
   1467          vex_printf("%s ", showMIPSFpOp(i->Min.FpCompare.op));
   1468          ppHRegMIPS(i->Min.FpCompare.srcL, mode64);
   1469          vex_printf(",");
   1470          ppHRegMIPS(i->Min.FpCompare.srcR, mode64);
   1471          return;
   1472       case Min_FpMulAcc:
   1473          vex_printf("%s ", showMIPSFpOp(i->Min.FpMulAcc.op));
   1474          ppHRegMIPS(i->Min.FpMulAcc.dst, mode64);
   1475          vex_printf(",");
   1476          ppHRegMIPS(i->Min.FpMulAcc.srcML, mode64);
   1477          vex_printf(",");
   1478          ppHRegMIPS(i->Min.FpMulAcc.srcMR, mode64);
   1479          vex_printf(",");
   1480          ppHRegMIPS(i->Min.FpMulAcc.srcAcc, mode64);
   1481          return;
   1482       case Min_FpLdSt: {
   1483          if (i->Min.FpLdSt.sz == 4) {
   1484             if (i->Min.FpLdSt.isLoad) {
   1485                vex_printf("lwc1 ");
   1486                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
   1487                vex_printf(",");
   1488                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
   1489             } else {
   1490                vex_printf("swc1 ");
   1491                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
   1492                vex_printf(",");
   1493                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
   1494             }
   1495          } else if (i->Min.FpLdSt.sz == 8) {
   1496             if (i->Min.FpLdSt.isLoad) {
   1497                vex_printf("ldc1 ");
   1498                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
   1499                vex_printf(",");
   1500                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
   1501             } else {
   1502                vex_printf("sdc1 ");
   1503                ppHRegMIPS(i->Min.FpLdSt.reg, mode64);
   1504                vex_printf(",");
   1505                ppMIPSAMode(i->Min.FpLdSt.addr, mode64);
   1506             }
   1507          }
   1508          return;
   1509       }
   1510       case Min_MtFCSR: {
   1511          vex_printf("ctc1 ");
   1512          ppHRegMIPS(i->Min.MtFCSR.src, mode64);
   1513          vex_printf(", $31");
   1514          return;
   1515       }
   1516       case Min_MfFCSR: {
   1517          vex_printf("ctc1 ");
   1518          ppHRegMIPS(i->Min.MfFCSR.dst, mode64);
   1519          vex_printf(", $31");
   1520          return;
   1521       }
   1522       case Min_FpGpMove: {
   1523          vex_printf("%s ", showMIPSFpGpMoveOp(i->Min.FpGpMove.op));
   1524          ppHRegMIPS(i->Min.FpGpMove.dst, mode64);
   1525          vex_printf(", ");
   1526          ppHRegMIPS(i->Min.FpGpMove.src, mode64);
   1527          return;
   1528       }
   1529       case Min_MoveCond: {
   1530          vex_printf("%s", showMIPSMoveCondOp(i->Min.MoveCond.op));
   1531          ppHRegMIPS(i->Min.MoveCond.dst, mode64);
   1532          vex_printf(", ");
   1533          ppHRegMIPS(i->Min.MoveCond.src, mode64);
   1534          vex_printf(", ");
   1535          ppHRegMIPS(i->Min.MoveCond.cond, mode64);
   1536          return;
   1537       }
   1538       case Min_EvCheck:
   1539          vex_printf("(evCheck) lw $9, ");
   1540          ppMIPSAMode(i->Min.EvCheck.amCounter, mode64);
   1541          vex_printf("; addiu $9, $9, -1");
   1542          vex_printf("; sw $9, ");
   1543          ppMIPSAMode(i->Min.EvCheck.amCounter, mode64);
   1544          vex_printf("; bgez $t9, nofail; jalr *");
   1545          ppMIPSAMode(i->Min.EvCheck.amFailAddr, mode64);
   1546          vex_printf("; nofail:");
   1547          return;
   1548       case Min_ProfInc:
   1549          if (mode64)
   1550             vex_printf("(profInc) move $9, ($NotKnownYet); "
   1551                        "ld $8, 0($9); "
   1552                        "daddiu $8, $8, 1; "
   1553                        "sd $8, 0($9); " );
   1554          else
   1555             vex_printf("(profInc) move $9, ($NotKnownYet); "
   1556                        "lw $8, 0($9); "
   1557                        "addiu $8, $8, 1; "
   1558                        "sw $8, 0($9); "
   1559                        "sltiu $1, $8, 1; "
   1560                        "lw $8, 4($9); "
   1561                        "addu $8, $8, $1; "
   1562                        "sw $8, 4($9); " );
   1563          return;
   1564       default:
   1565          vpanic("ppMIPSInstr");
   1566          break;
   1567    }
   1568 }
   1569 
   1570 /* --------- Helpers for register allocation. --------- */
   1571 
   1572 void getRegUsage_MIPSInstr(HRegUsage * u, const MIPSInstr * i, Bool mode64)
   1573 {
   1574    initHRegUsage(u);
   1575    switch (i->tag) {
   1576       case Min_LI:
   1577          addHRegUse(u, HRmWrite, i->Min.LI.dst);
   1578          break;
   1579       case Min_Alu:
   1580          addHRegUse(u, HRmRead, i->Min.Alu.srcL);
   1581          addRegUsage_MIPSRH(u, i->Min.Alu.srcR);
   1582          addHRegUse(u, HRmWrite, i->Min.Alu.dst);
   1583          return;
   1584       case Min_Shft:
   1585          addHRegUse(u, HRmRead, i->Min.Shft.srcL);
   1586          addRegUsage_MIPSRH(u, i->Min.Shft.srcR);
   1587          addHRegUse(u, HRmWrite, i->Min.Shft.dst);
   1588          return;
   1589       case Min_Cmp:
   1590          addHRegUse(u, HRmRead, i->Min.Cmp.srcL);
   1591          addHRegUse(u, HRmRead, i->Min.Cmp.srcR);
   1592          addHRegUse(u, HRmWrite, i->Min.Cmp.dst);
   1593          return;
   1594       case Min_Unary:
   1595          addHRegUse(u, HRmRead, i->Min.Unary.src);
   1596          addHRegUse(u, HRmWrite, i->Min.Unary.dst);
   1597          return;
   1598       case Min_Mul:
   1599          addHRegUse(u, HRmWrite, i->Min.Mul.dst);
   1600          addHRegUse(u, HRmRead, i->Min.Mul.srcL);
   1601          addHRegUse(u, HRmRead, i->Min.Mul.srcR);
   1602          return;
   1603       case Min_Mthi:
   1604       case Min_Mtlo:
   1605          addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
   1606          addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
   1607          addHRegUse(u, HRmRead, i->Min.MtHL.src);
   1608          return;
   1609       case Min_Mfhi:
   1610       case Min_Mflo:
   1611          addHRegUse(u, HRmRead, hregMIPS_HI(mode64));
   1612          addHRegUse(u, HRmRead, hregMIPS_LO(mode64));
   1613          addHRegUse(u, HRmWrite, i->Min.MfHL.dst);
   1614          return;
   1615       case Min_MtFCSR:
   1616          addHRegUse(u, HRmRead, i->Min.MtFCSR.src);
   1617          return;
   1618       case Min_MfFCSR:
   1619          addHRegUse(u, HRmWrite, i->Min.MfFCSR.dst);
   1620          return;
   1621       case Min_Macc:
   1622          addHRegUse(u, HRmModify, hregMIPS_HI(mode64));
   1623          addHRegUse(u, HRmModify, hregMIPS_LO(mode64));
   1624          addHRegUse(u, HRmRead, i->Min.Macc.srcL);
   1625          addHRegUse(u, HRmRead, i->Min.Macc.srcR);
   1626          return;
   1627       case Min_Div:
   1628          addHRegUse(u, HRmWrite, hregMIPS_HI(mode64));
   1629          addHRegUse(u, HRmWrite, hregMIPS_LO(mode64));
   1630          addHRegUse(u, HRmRead, i->Min.Div.srcL);
   1631          addHRegUse(u, HRmRead, i->Min.Div.srcR);
   1632          return;
   1633       case Min_Call: {
   1634          /* Logic and comments copied/modified from x86, ppc and arm back end.
   1635             First off, claim it trashes all the caller-saved regs
   1636             which fall within the register allocator's jurisdiction. */
   1637          if (i->Min.Call.cond != MIPScc_AL)
   1638             addHRegUse(u, HRmRead, i->Min.Call.src);
   1639          UInt argir;
   1640          addHRegUse(u, HRmWrite, hregMIPS_GPR1(mode64));
   1641 
   1642          addHRegUse(u, HRmWrite, hregMIPS_GPR2(mode64));
   1643          addHRegUse(u, HRmWrite, hregMIPS_GPR3(mode64));
   1644 
   1645          addHRegUse(u, HRmWrite, hregMIPS_GPR4(mode64));
   1646          addHRegUse(u, HRmWrite, hregMIPS_GPR5(mode64));
   1647          addHRegUse(u, HRmWrite, hregMIPS_GPR6(mode64));
   1648          addHRegUse(u, HRmWrite, hregMIPS_GPR7(mode64));
   1649 
   1650          addHRegUse(u, HRmWrite, hregMIPS_GPR8(mode64));
   1651          addHRegUse(u, HRmWrite, hregMIPS_GPR9(mode64));
   1652          addHRegUse(u, HRmWrite, hregMIPS_GPR10(mode64));
   1653          addHRegUse(u, HRmWrite, hregMIPS_GPR11(mode64));
   1654          addHRegUse(u, HRmWrite, hregMIPS_GPR12(mode64));
   1655          addHRegUse(u, HRmWrite, hregMIPS_GPR13(mode64));
   1656          addHRegUse(u, HRmWrite, hregMIPS_GPR14(mode64));
   1657          addHRegUse(u, HRmWrite, hregMIPS_GPR15(mode64));
   1658 
   1659          addHRegUse(u, HRmWrite, hregMIPS_GPR24(mode64));
   1660          addHRegUse(u, HRmWrite, hregMIPS_GPR25(mode64));
   1661          addHRegUse(u, HRmWrite, hregMIPS_GPR31(mode64));
   1662 
   1663          /* Now we have to state any parameter-carrying registers
   1664             which might be read. This depends on the argiregs field. */
   1665          argir = i->Min.Call.argiregs;
   1666          if (argir & (1<<11)) addHRegUse(u, HRmRead, hregMIPS_GPR11(mode64));
   1667          if (argir & (1<<10)) addHRegUse(u, HRmRead, hregMIPS_GPR10(mode64));
   1668          if (argir & (1<<9)) addHRegUse(u, HRmRead, hregMIPS_GPR9(mode64));
   1669          if (argir & (1<<8)) addHRegUse(u, HRmRead, hregMIPS_GPR8(mode64));
   1670          if (argir & (1<<7)) addHRegUse(u, HRmRead, hregMIPS_GPR7(mode64));
   1671          if (argir & (1<<6)) addHRegUse(u, HRmRead, hregMIPS_GPR6(mode64));
   1672          if (argir & (1<<5)) addHRegUse(u, HRmRead, hregMIPS_GPR5(mode64));
   1673          if (argir & (1<<4)) addHRegUse(u, HRmRead, hregMIPS_GPR4(mode64));
   1674 
   1675          vassert(0 == (argir & ~((1 << 4) | (1 << 5) | (1 << 6)
   1676                                  | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
   1677                                  | (1 << 11))));
   1678 
   1679          return;
   1680       }
   1681       /* XDirect/XIndir/XAssisted are also a bit subtle.  They
   1682          conditionally exit the block.  Hence we only need to list (1)
   1683          the registers that they read, and (2) the registers that they
   1684          write in the case where the block is not exited.  (2) is
   1685          empty, hence only (1) is relevant here. */
   1686       case Min_XDirect:
   1687          addRegUsage_MIPSAMode(u, i->Min.XDirect.amPC);
   1688          return;
   1689       case Min_XIndir:
   1690          addHRegUse(u, HRmRead, i->Min.XIndir.dstGA);
   1691          addRegUsage_MIPSAMode(u, i->Min.XIndir.amPC);
   1692          return;
   1693       case Min_XAssisted:
   1694          addHRegUse(u, HRmRead, i->Min.XAssisted.dstGA);
   1695          addRegUsage_MIPSAMode(u, i->Min.XAssisted.amPC);
   1696          return;
   1697       case Min_Load:
   1698          addRegUsage_MIPSAMode(u, i->Min.Load.src);
   1699          addHRegUse(u, HRmWrite, i->Min.Load.dst);
   1700          return;
   1701       case Min_Store:
   1702          addHRegUse(u, HRmRead, i->Min.Store.src);
   1703          addRegUsage_MIPSAMode(u, i->Min.Store.dst);
   1704          return;
   1705       case Min_LoadL:
   1706          addRegUsage_MIPSAMode(u, i->Min.LoadL.src);
   1707          addHRegUse(u, HRmWrite, i->Min.LoadL.dst);
   1708          return;
   1709       case Min_Cas:
   1710          addHRegUse(u, HRmWrite, i->Min.Cas.old);
   1711          addHRegUse(u, HRmRead, i->Min.Cas.addr);
   1712          addHRegUse(u, HRmRead, i->Min.Cas.expd);
   1713          addHRegUse(u, HRmModify, i->Min.Cas.data);
   1714          return;
   1715       case Min_StoreC:
   1716          addHRegUse(u, HRmWrite, i->Min.StoreC.src);
   1717          addHRegUse(u, HRmRead, i->Min.StoreC.src);
   1718          addRegUsage_MIPSAMode(u, i->Min.StoreC.dst);
   1719          return;
   1720       case Min_RdWrLR:
   1721          addHRegUse(u, (i->Min.RdWrLR.wrLR ? HRmRead : HRmWrite),
   1722                         i->Min.RdWrLR.gpr);
   1723          return;
   1724       case Min_FpLdSt:
   1725          if (i->Min.FpLdSt.sz == 4) {
   1726             addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
   1727                            i->Min.FpLdSt.reg);
   1728             addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
   1729             return;
   1730          } else if (i->Min.FpLdSt.sz == 8) {
   1731             addHRegUse(u, (i->Min.FpLdSt.isLoad ? HRmWrite : HRmRead),
   1732                            i->Min.FpLdSt.reg);
   1733             addRegUsage_MIPSAMode(u, i->Min.FpLdSt.addr);
   1734             return;
   1735          }
   1736          break;
   1737       case Min_FpUnary:
   1738          addHRegUse(u, HRmWrite, i->Min.FpUnary.dst);
   1739          addHRegUse(u, HRmRead, i->Min.FpUnary.src);
   1740          return;
   1741       case Min_FpBinary:
   1742          addHRegUse(u, HRmWrite, i->Min.FpBinary.dst);
   1743          addHRegUse(u, HRmRead, i->Min.FpBinary.srcL);
   1744          addHRegUse(u, HRmRead, i->Min.FpBinary.srcR);
   1745          return;
   1746       case Min_FpTernary:
   1747          addHRegUse(u, HRmWrite, i->Min.FpTernary.dst);
   1748          addHRegUse(u, HRmRead, i->Min.FpTernary.src1);
   1749          addHRegUse(u, HRmRead, i->Min.FpTernary.src2);
   1750          addHRegUse(u, HRmRead, i->Min.FpTernary.src3);
   1751          return;
   1752       case Min_FpConvert:
   1753          addHRegUse(u, HRmWrite, i->Min.FpConvert.dst);
   1754          addHRegUse(u, HRmRead, i->Min.FpConvert.src);
   1755          return;
   1756       case Min_FpCompare:
   1757          addHRegUse(u, HRmWrite, i->Min.FpCompare.dst);
   1758          addHRegUse(u, HRmRead, i->Min.FpCompare.srcL);
   1759          addHRegUse(u, HRmRead, i->Min.FpCompare.srcR);
   1760          return;
   1761       case Min_FpGpMove:
   1762          addHRegUse(u, HRmWrite, i->Min.FpGpMove.dst);
   1763          addHRegUse(u, HRmRead, i->Min.FpGpMove.src);
   1764          return;
   1765       case Min_MoveCond:
   1766          addHRegUse(u, HRmModify, i->Min.MoveCond.dst);
   1767          addHRegUse(u, HRmRead, i->Min.MoveCond.src);
   1768          addHRegUse(u, HRmRead, i->Min.MoveCond.cond);
   1769          return;
   1770       case Min_EvCheck:
   1771          /* We expect both amodes only to mention %ebp, so this is in
   1772             fact pointless, since %ebp isn't allocatable, but anyway.. */
   1773          addRegUsage_MIPSAMode(u, i->Min.EvCheck.amCounter);
   1774          addRegUsage_MIPSAMode(u, i->Min.EvCheck.amFailAddr);
   1775          return;
   1776       case Min_ProfInc:
   1777          /* does not use any registers. */
   1778          return;
   1779       default:
   1780          ppMIPSInstr(i, mode64);
   1781          vpanic("getRegUsage_MIPSInstr");
   1782          break;
   1783    }
   1784 }
   1785 
   1786 /* local helper */
   1787 static void mapReg(HRegRemap * m, HReg * r)
   1788 {
   1789    *r = lookupHRegRemap(m, *r);
   1790 }
   1791 
   1792 void mapRegs_MIPSInstr(HRegRemap * m, MIPSInstr * i, Bool mode64)
   1793 {
   1794    switch (i->tag) {
   1795       case Min_LI:
   1796          mapReg(m, &i->Min.LI.dst);
   1797          break;
   1798       case Min_Alu:
   1799          mapReg(m, &i->Min.Alu.srcL);
   1800          mapRegs_MIPSRH(m, i->Min.Alu.srcR);
   1801          mapReg(m, &i->Min.Alu.dst);
   1802          return;
   1803       case Min_Shft:
   1804          mapReg(m, &i->Min.Shft.srcL);
   1805          mapRegs_MIPSRH(m, i->Min.Shft.srcR);
   1806          mapReg(m, &i->Min.Shft.dst);
   1807          return;
   1808       case Min_Cmp:
   1809          mapReg(m, &i->Min.Cmp.srcL);
   1810          mapReg(m, &i->Min.Cmp.srcR);
   1811          mapReg(m, &i->Min.Cmp.dst);
   1812          return;
   1813       case Min_Unary:
   1814          mapReg(m, &i->Min.Unary.src);
   1815          mapReg(m, &i->Min.Unary.dst);
   1816          return;
   1817       case Min_Mul:
   1818          mapReg(m, &i->Min.Mul.dst);
   1819          mapReg(m, &i->Min.Mul.srcL);
   1820          mapReg(m, &i->Min.Mul.srcR);
   1821          return;
   1822       case Min_Mthi:
   1823       case Min_Mtlo:
   1824          mapReg(m, &i->Min.MtHL.src);
   1825          return;
   1826       case Min_Mfhi:
   1827       case Min_Mflo:
   1828          mapReg(m, &i->Min.MfHL.dst);
   1829          return;
   1830       case Min_Macc:
   1831          mapReg(m, &i->Min.Macc.srcL);
   1832          mapReg(m, &i->Min.Macc.srcR);
   1833          return;
   1834       case Min_Div:
   1835          mapReg(m, &i->Min.Div.srcL);
   1836          mapReg(m, &i->Min.Div.srcR);
   1837          return;
   1838       case Min_Call:
   1839          {
   1840             if (i->Min.Call.cond != MIPScc_AL)
   1841                mapReg(m, &i->Min.Call.src);
   1842             return;
   1843          }
   1844       case Min_XDirect:
   1845          mapRegs_MIPSAMode(m, i->Min.XDirect.amPC);
   1846          return;
   1847       case Min_XIndir:
   1848          mapReg(m, &i->Min.XIndir.dstGA);
   1849          mapRegs_MIPSAMode(m, i->Min.XIndir.amPC);
   1850          return;
   1851       case Min_XAssisted:
   1852          mapReg(m, &i->Min.XAssisted.dstGA);
   1853          mapRegs_MIPSAMode(m, i->Min.XAssisted.amPC);
   1854          return;
   1855       case Min_Load:
   1856          mapRegs_MIPSAMode(m, i->Min.Load.src);
   1857          mapReg(m, &i->Min.Load.dst);
   1858          return;
   1859       case Min_Store:
   1860          mapReg(m, &i->Min.Store.src);
   1861          mapRegs_MIPSAMode(m, i->Min.Store.dst);
   1862          return;
   1863       case Min_LoadL:
   1864          mapRegs_MIPSAMode(m, i->Min.LoadL.src);
   1865          mapReg(m, &i->Min.LoadL.dst);
   1866          return;
   1867       case Min_Cas:
   1868          mapReg(m, &i->Min.Cas.old);
   1869          mapReg(m, &i->Min.Cas.addr);
   1870          mapReg(m, &i->Min.Cas.expd);
   1871          mapReg(m, &i->Min.Cas.data);
   1872          return;
   1873       case Min_StoreC:
   1874          mapReg(m, &i->Min.StoreC.src);
   1875          mapRegs_MIPSAMode(m, i->Min.StoreC.dst);
   1876          return;
   1877       case Min_RdWrLR:
   1878          mapReg(m, &i->Min.RdWrLR.gpr);
   1879          return;
   1880       case Min_FpLdSt:
   1881          if (i->Min.FpLdSt.sz == 4) {
   1882             mapReg(m, &i->Min.FpLdSt.reg);
   1883             mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
   1884             return;
   1885          } else if (i->Min.FpLdSt.sz == 8) {
   1886             mapReg(m, &i->Min.FpLdSt.reg);
   1887             mapRegs_MIPSAMode(m, i->Min.FpLdSt.addr);
   1888             return;
   1889          }
   1890          break;
   1891       case Min_FpUnary:
   1892          mapReg(m, &i->Min.FpUnary.dst);
   1893          mapReg(m, &i->Min.FpUnary.src);
   1894          return;
   1895       case Min_FpBinary:
   1896          mapReg(m, &i->Min.FpBinary.dst);
   1897          mapReg(m, &i->Min.FpBinary.srcL);
   1898          mapReg(m, &i->Min.FpBinary.srcR);
   1899          return;
   1900       case Min_FpTernary:
   1901          mapReg(m, &i->Min.FpTernary.dst);
   1902          mapReg(m, &i->Min.FpTernary.src1);
   1903          mapReg(m, &i->Min.FpTernary.src2);
   1904          mapReg(m, &i->Min.FpTernary.src3);
   1905          return;
   1906       case Min_FpConvert:
   1907          mapReg(m, &i->Min.FpConvert.dst);
   1908          mapReg(m, &i->Min.FpConvert.src);
   1909          return;
   1910       case Min_FpCompare:
   1911          mapReg(m, &i->Min.FpCompare.dst);
   1912          mapReg(m, &i->Min.FpCompare.srcL);
   1913          mapReg(m, &i->Min.FpCompare.srcR);
   1914          return;
   1915       case Min_MtFCSR:
   1916          mapReg(m, &i->Min.MtFCSR.src);
   1917          return;
   1918       case Min_MfFCSR:
   1919          mapReg(m, &i->Min.MfFCSR.dst);
   1920          return;
   1921       case Min_FpGpMove:
   1922          mapReg(m, &i->Min.FpGpMove.dst);
   1923          mapReg(m, &i->Min.FpGpMove.src);
   1924          return;
   1925       case Min_MoveCond:
   1926          mapReg(m, &i->Min.MoveCond.dst);
   1927          mapReg(m, &i->Min.MoveCond.src);
   1928          mapReg(m, &i->Min.MoveCond.cond);
   1929          return;
   1930       case Min_EvCheck:
   1931          /* We expect both amodes only to mention %ebp, so this is in
   1932             fact pointless, since %ebp isn't allocatable, but anyway.. */
   1933          mapRegs_MIPSAMode(m, i->Min.EvCheck.amCounter);
   1934          mapRegs_MIPSAMode(m, i->Min.EvCheck.amFailAddr);
   1935          return;
   1936       case Min_ProfInc:
   1937          /* does not use any registers. */
   1938          return;
   1939       default:
   1940          ppMIPSInstr(i, mode64);
   1941          vpanic("mapRegs_MIPSInstr");
   1942          break;
   1943    }
   1944 
   1945 }
   1946 
   1947 /* Figure out if i represents a reg-reg move, and if so assign the
   1948    source and destination to *src and *dst.  If in doubt say No.  Used
   1949    by the register allocator to do move coalescing.
   1950 */
   1951 Bool isMove_MIPSInstr(const MIPSInstr * i, HReg * src, HReg * dst)
   1952 {
   1953    /* Moves between integer regs */
   1954    if (i->tag == Min_Alu) {
   1955       /* or Rd,Rs,Rs == mr Rd,Rs */
   1956       if (i->Min.Alu.op != Malu_OR)
   1957          return False;
   1958       if (i->Min.Alu.srcR->tag != Mrh_Reg)
   1959          return False;
   1960       if (!sameHReg(i->Min.Alu.srcR->Mrh.Reg.reg, i->Min.Alu.srcL))
   1961          return False;
   1962       *src = i->Min.Alu.srcL;
   1963       *dst = i->Min.Alu.dst;
   1964       return True;
   1965    }
   1966    return False;
   1967 }
   1968 
   1969 /* Generate mips spill/reload instructions under the direction of the
   1970    register allocator. */
   1971 void genSpill_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
   1972                     Int offsetB, Bool mode64)
   1973 {
   1974    MIPSAMode *am;
   1975    vassert(offsetB >= 0);
   1976    vassert(!hregIsVirtual(rreg));
   1977    *i1 = *i2 = NULL;
   1978    am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64));
   1979 
   1980    switch (hregClass(rreg)) {
   1981       case HRcInt64:
   1982          vassert(mode64);
   1983          *i1 = MIPSInstr_Store(8, am, rreg, mode64);
   1984          break;
   1985       case HRcInt32:
   1986          vassert(!mode64);
   1987          *i1 = MIPSInstr_Store(4, am, rreg, mode64);
   1988          break;
   1989       case HRcFlt32:
   1990          vassert(!mode64);
   1991          *i1 = MIPSInstr_FpLdSt(False /*Store */ , 4, rreg, am);
   1992          break;
   1993       case HRcFlt64:
   1994          *i1 = MIPSInstr_FpLdSt(False /*Store */ , 8, rreg, am);
   1995          break;
   1996       default:
   1997          ppHRegClass(hregClass(rreg));
   1998          vpanic("genSpill_MIPS: unimplemented regclass");
   1999          break;
   2000    }
   2001 }
   2002 
   2003 void genReload_MIPS( /*OUT*/ HInstr ** i1, /*OUT*/ HInstr ** i2, HReg rreg,
   2004                      Int offsetB, Bool mode64)
   2005 {
   2006    MIPSAMode *am;
   2007    vassert(!hregIsVirtual(rreg));
   2008    am = MIPSAMode_IR(offsetB, GuestStatePointer(mode64));
   2009 
   2010    switch (hregClass(rreg)) {
   2011       case HRcInt64:
   2012          vassert(mode64);
   2013          *i1 = MIPSInstr_Load(8, rreg, am, mode64);
   2014          break;
   2015       case HRcInt32:
   2016          vassert(!mode64);
   2017          *i1 = MIPSInstr_Load(4, rreg, am, mode64);
   2018          break;
   2019       case HRcFlt32:
   2020          if (mode64)
   2021             *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am);
   2022          else
   2023             *i1 = MIPSInstr_FpLdSt(True /*Load */ , 4, rreg, am);
   2024          break;
   2025       case HRcFlt64:
   2026          *i1 = MIPSInstr_FpLdSt(True /*Load */ , 8, rreg, am);
   2027          break;
   2028       default:
   2029          ppHRegClass(hregClass(rreg));
   2030          vpanic("genReload_MIPS: unimplemented regclass");
   2031          break;
   2032    }
   2033 }
   2034 
   2035 /* --------- The mips assembler --------- */
   2036 
   2037 inline static UInt iregNo(HReg r, Bool mode64)
   2038 {
   2039    UInt n;
   2040    vassert(hregClass(r) == (mode64 ? HRcInt64 : HRcInt32));
   2041    vassert(!hregIsVirtual(r));
   2042    n = hregEncoding(r);
   2043    vassert(n <= 32);
   2044    return n;
   2045 }
   2046 
   2047 inline static UInt fregNo(HReg r, Bool mode64)
   2048 {
   2049    UInt n;
   2050    vassert(!hregIsVirtual(r));
   2051    n = hregEncoding(r);
   2052    vassert(n <= 31);
   2053    return n;
   2054 }
   2055 
   2056 inline static UInt dregNo(HReg r)
   2057 {
   2058    UInt n;
   2059    vassert(!hregIsVirtual(r));
   2060    n = hregEncoding(r);
   2061    vassert(n <= 31);
   2062    return n;
   2063 }
   2064 
   2065 /* Emit 32bit instruction */
   2066 static UChar *emit32(UChar * p, UInt w32)
   2067 {
   2068 #if defined (_MIPSEL)
   2069    *p++ = toUChar(w32 & 0x000000FF);
   2070    *p++ = toUChar((w32 >> 8) & 0x000000FF);
   2071    *p++ = toUChar((w32 >> 16) & 0x000000FF);
   2072    *p++ = toUChar((w32 >> 24) & 0x000000FF);
   2073 /* HACK !!!!
   2074    MIPS endianess is decided at compile time using gcc defined
   2075    symbols _MIPSEL or _MIPSEB. When compiling libvex in a cross-arch
   2076    setup, then none of these is defined. We just choose here by default
   2077    mips Big Endian to allow libvexmultiarch_test to work when using
   2078    a mips host architecture.
   2079    A cleaner way would be to either have mips using 'dynamic endness'
   2080    (like ppc64be or le, decided at runtime) or at least defining
   2081    by default _MIPSEB when compiling on a non mips system.
   2082 #elif defined (_MIPSEB).
   2083 */
   2084 #else
   2085    *p++ = toUChar((w32 >> 24) & 0x000000FF);
   2086    *p++ = toUChar((w32 >> 16) & 0x000000FF);
   2087    *p++ = toUChar((w32 >> 8) & 0x000000FF);
   2088    *p++ = toUChar(w32 & 0x000000FF);
   2089 #endif
   2090    return p;
   2091 }
   2092 /* Fetch an instruction */
   2093 static UInt fetch32 ( UChar* p )
   2094 {
   2095    UInt w32 = 0;
   2096 #if defined (_MIPSEL)
   2097    w32 |= ((0xFF & (UInt)p[0]) << 0);
   2098    w32 |= ((0xFF & (UInt)p[1]) << 8);
   2099    w32 |= ((0xFF & (UInt)p[2]) << 16);
   2100    w32 |= ((0xFF & (UInt)p[3]) << 24);
   2101 #elif defined (_MIPSEB)
   2102    w32 |= ((0xFF & (UInt)p[0]) << 24);
   2103    w32 |= ((0xFF & (UInt)p[1]) << 16);
   2104    w32 |= ((0xFF & (UInt)p[2]) <<  8);
   2105    w32 |= ((0xFF & (UInt)p[3]) <<  0);
   2106 #endif
   2107    return w32;
   2108 }
   2109 
   2110 /* physical structure of mips instructions */
   2111 /* type I : opcode    - 6 bits
   2112          rs         - 5 bits
   2113          rt         - 5 bits
   2114          immediate - 16 bits
   2115 */
   2116 static UChar *mkFormI(UChar * p, UInt opc, UInt rs, UInt rt, UInt imm)
   2117 {
   2118    UInt theInstr;
   2119    vassert(opc < 0x40);
   2120    vassert(rs < 0x20);
   2121    vassert(rt < 0x20);
   2122    imm = imm & 0xFFFF;
   2123    theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (imm));
   2124    return emit32(p, theInstr);
   2125 }
   2126 
   2127 /* type R: opcode    - 6 bits
   2128          rs    - 5 bits
   2129          rt    - 5 bits
   2130          rd    - 5 bits
   2131          sa    - 5 bits
   2132          func  - 6 bits
   2133 */
   2134 static UChar *mkFormR(UChar * p, UInt opc, UInt rs, UInt rt, UInt rd, UInt sa,
   2135             UInt func)
   2136 {
   2137    if (rs >= 0x20)
   2138       vex_printf("rs = %u\n", rs);
   2139    UInt theInstr;
   2140    vassert(opc < 0x40);
   2141    vassert(rs < 0x20);
   2142    vassert(rt < 0x20);
   2143    vassert(rd < 0x20);
   2144    vassert(sa < 0x20);
   2145    func = func & 0xFFFF;
   2146    theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (rd << 11) | (sa << 6) |
   2147                (func));
   2148 
   2149    return emit32(p, theInstr);
   2150 }
   2151 
   2152 static UChar *mkFormS(UChar * p, UInt opc1, UInt rRD, UInt rRS, UInt rRT,
   2153                       UInt sa, UInt opc2)
   2154 {
   2155    UInt theInstr;
   2156    vassert(opc1 <= 0x3F);
   2157    vassert(rRD < 0x20);
   2158    vassert(rRS < 0x20);
   2159    vassert(rRT < 0x20);
   2160    vassert(opc2 <= 0x3F);
   2161    vassert(sa >= 0 && sa <= 0x3F);
   2162 
   2163    theInstr = ((opc1 << 26) | (rRS << 21) | (rRT << 16) | (rRD << 11) |
   2164               ((sa & 0x1F) << 6) | (opc2));
   2165 
   2166    return emit32(p, theInstr);
   2167 }
   2168 
   2169 static UChar *doAMode_IR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am,
   2170                          Bool mode64)
   2171 {
   2172    UInt rA, idx, r_dst;
   2173    vassert(am->tag == Mam_IR);
   2174    vassert(am->Mam.IR.index < 0x10000);
   2175 
   2176    rA = iregNo(am->Mam.IR.base, mode64);
   2177    idx = am->Mam.IR.index;
   2178 
   2179    if (rSD == 33 || rSD == 34)
   2180       r_dst = 24;
   2181    else
   2182       r_dst = rSD;
   2183 
   2184    if (opc1 < 40) {
   2185       /* load */
   2186       if (rSD == 33)
   2187          /* mfhi */
   2188          p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
   2189       else if (rSD == 34)
   2190          /* mflo */
   2191          p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
   2192    }
   2193 
   2194    p = mkFormI(p, opc1, rA, r_dst, idx);
   2195 
   2196    if (opc1 >= 40) {
   2197       /* store */
   2198       if (rSD == 33)
   2199          /* mthi */
   2200          p = mkFormR(p, 0, r_dst, 0, 0, 0, 17);
   2201       else if (rSD == 34)
   2202          /* mtlo */
   2203          p = mkFormR(p, 0, r_dst, 0, 0, 0, 19);
   2204    }
   2205 
   2206    return p;
   2207 }
   2208 
   2209 static UChar *doAMode_RR(UChar * p, UInt opc1, UInt rSD, MIPSAMode * am,
   2210                          Bool mode64)
   2211 {
   2212    UInt rA, rB, r_dst;
   2213    vassert(am->tag == Mam_RR);
   2214 
   2215    rA = iregNo(am->Mam.RR.base, mode64);
   2216    rB = iregNo(am->Mam.RR.index, mode64);
   2217 
   2218    if (rSD == 33 || rSD == 34)
   2219       r_dst = 24;
   2220    else
   2221       r_dst = rSD;
   2222 
   2223    if (opc1 < 40) {
   2224       /* load */
   2225       if (rSD == 33)
   2226          /* mfhi */
   2227          p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
   2228       else if (rSD == 34)
   2229          /* mflo */
   2230          p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
   2231    }
   2232 
   2233    if (mode64) {
   2234       /* daddu rA, rA, rB$
   2235          sd/ld r_dst, 0(rA)$
   2236          dsubu rA, rA, rB */
   2237       p = mkFormR(p, 0, rA, rB, rA, 0, 45);
   2238       p = mkFormI(p, opc1, rA, r_dst, 0);
   2239       p = mkFormR(p, 0, rA, rB, rA, 0, 47);
   2240    } else {
   2241       /* addu rA, rA, rB
   2242          sw/lw r_dst, 0(rA)
   2243          subu rA, rA, rB */
   2244       p = mkFormR(p, 0, rA, rB, rA, 0, 33);
   2245       p = mkFormI(p, opc1, rA, r_dst, 0);
   2246       p = mkFormR(p, 0, rA, rB, rA, 0, 35);
   2247    }
   2248    if (opc1 >= 40) {
   2249       /* store */
   2250       if (rSD == 33)
   2251          /* mthi */
   2252          p = mkFormR(p, 0, r_dst, 0, 0, 0, 17);
   2253       else if (rSD == 34)
   2254          /* mtlo */
   2255          p = mkFormR(p, 0, r_dst, 0, 0, 0, 19);
   2256    }
   2257 
   2258    return p;
   2259 }
   2260 
   2261 /* Load imm to r_dst */
   2262 static UChar *mkLoadImm(UChar * p, UInt r_dst, ULong imm, Bool mode64)
   2263 {
   2264    if (!mode64) {
   2265       vassert(r_dst < 0x20);
   2266       UInt u32 = (UInt) imm;
   2267       Int s32 = (Int) u32;
   2268       Long s64 = (Long) s32;
   2269       imm = (ULong) s64;
   2270    }
   2271 
   2272    if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) {
   2273       /* sign-extendable from 16 bits
   2274          addiu r_dst, 0, imm  => li r_dst, imm */
   2275       p = mkFormI(p, 9, 0, r_dst, imm & 0xFFFF);
   2276    } else {
   2277       if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) {
   2278          /* sign-extendable from 32 bits
   2279             addiu r_dst, r0, (imm >> 16) => lis r_dst, (imm >> 16)
   2280             lui r_dst, (imm >> 16) */
   2281          p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
   2282          /* ori r_dst, r_dst, (imm & 0xFFFF) */
   2283          p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2284       } else {
   2285          vassert(mode64);
   2286          /* lui load in upper half of low word */
   2287          p = mkFormI(p, 15, 0, r_dst, (imm >> 48) & 0xFFFF);
   2288          /* ori */
   2289          p = mkFormI(p, 13, r_dst, r_dst, (imm >> 32) & 0xFFFF);
   2290          /* shift */
   2291          p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2292          /* ori */
   2293          p = mkFormI(p, 13, r_dst, r_dst, (imm >> 16) & 0xFFFF);
   2294          /* shift */
   2295          p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2296          /* ori */
   2297          p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2298       }
   2299    }
   2300    return p;
   2301 }
   2302 
   2303 /* A simplified version of mkLoadImm that always generates 2 or 6
   2304    instructions (32 or 64 bits respectively) even if it could generate
   2305    fewer.  This is needed for generating fixed sized patchable
   2306    sequences. */
   2307 static UChar* mkLoadImm_EXACTLY2or6 ( UChar* p,
   2308                                       UInt r_dst, ULong imm, Bool mode64)
   2309 {
   2310    vassert(r_dst < 0x20);
   2311 
   2312    if (!mode64) {
   2313       /* In 32-bit mode, make sure the top 32 bits of imm are a sign
   2314          extension of the bottom 32 bits. (Probably unnecessary.) */
   2315       UInt u32 = (UInt)imm;
   2316       Int  s32 = (Int)u32;
   2317       Long s64 = (Long)s32;
   2318       imm = (ULong)s64;
   2319    }
   2320 
   2321    if (!mode64) {
   2322       /* sign-extendable from 32 bits
   2323          addiu r_dst, r0, (imm >> 16) => lis r_dst, (imm >> 16)
   2324          lui r_dst, (imm >> 16) */
   2325       p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
   2326       /* ori r_dst, r_dst, (imm & 0xFFFF) */
   2327       p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2328    } else {
   2329       /* full 64bit immediate load: 6 (six!) insns. */
   2330       vassert(mode64);
   2331       /* lui load in upper half of low word */
   2332       p = mkFormI(p, 15, 0, r_dst, (imm >> 48) & 0xFFFF);
   2333       /* ori */
   2334       p = mkFormI(p, 13, r_dst, r_dst, (imm >> 32) & 0xFFFF);
   2335       /* shift */
   2336       p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2337       /* ori */
   2338       p = mkFormI(p, 13, r_dst, r_dst, (imm >> 16) & 0xFFFF);
   2339       /* shift */
   2340       p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2341       /* ori */
   2342       p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2343    }
   2344    return p;
   2345 }
   2346 
   2347 /* Checks whether the sequence of bytes at p was indeed created
   2348    by mkLoadImm_EXACTLY2or6 with the given parameters. */
   2349 static Bool isLoadImm_EXACTLY2or6 ( UChar* p_to_check,
   2350                                     UInt r_dst, ULong imm, Bool mode64 )
   2351 {
   2352    vassert(r_dst < 0x20);
   2353    Bool ret;
   2354    if (!mode64) {
   2355       /* In 32-bit mode, make sure the top 32 bits of imm are a sign
   2356          extension of the bottom 32 bits.  (Probably unnecessary.) */
   2357       UInt u32 = (UInt)imm;
   2358       Int  s32 = (Int)u32;
   2359       Long s64 = (Long)s32;
   2360       imm = (ULong)s64;
   2361    }
   2362 
   2363    if (!mode64) {
   2364       UInt   expect[2] = { 0, 0 };
   2365       UChar* p         = (UChar*)&expect[0];
   2366       /* lui r_dst, (immi >> 16) */
   2367       p = mkFormI(p, 15, 0, r_dst, (imm >> 16) & 0xFFFF);
   2368       /* ori r_dst, r_dst, (imm & 0xFFFF) */
   2369       p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2370       vassert(p == (UChar*)&expect[2]);
   2371 
   2372       ret = fetch32(p_to_check + 0) == expect[0]
   2373             && fetch32(p_to_check + 4) == expect[1];
   2374    } else {
   2375       UInt   expect[6] = { 0, 0, 0, 0, 0, 0};
   2376       UChar* p         = (UChar*)&expect[0];
   2377       /* lui load in upper half of low word */
   2378       p = mkFormI(p, 15, 0, r_dst, (imm >> 48) & 0xFFFF);
   2379       /* ori */
   2380       p = mkFormI(p, 13, r_dst, r_dst, (imm >> 32) & 0xFFFF);
   2381       /* shift */
   2382       p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2383       /* ori */
   2384       p = mkFormI(p, 13, r_dst, r_dst, (imm >> 16) & 0xFFFF);
   2385       /* shift */
   2386       p = mkFormS(p, 0, r_dst, 0, r_dst, 16, 56);
   2387       /* ori */
   2388       p = mkFormI(p, 13, r_dst, r_dst, imm & 0xFFFF);
   2389       vassert(p == (UChar*)&expect[6]);
   2390 
   2391       ret = fetch32(p_to_check + 0) == expect[0]
   2392             && fetch32(p_to_check + 4) == expect[1]
   2393             && fetch32(p_to_check + 8) == expect[2]
   2394             && fetch32(p_to_check + 12) == expect[3]
   2395             && fetch32(p_to_check + 16) == expect[4]
   2396             && fetch32(p_to_check + 20) == expect[5];
   2397    }
   2398    return ret;
   2399 }
   2400 
   2401 /* Generate a machine-word sized load or store. Simplified version of
   2402    the Min_Load and Min_Store cases below.
   2403    This will generate 32-bit load/store on MIPS32, and 64-bit load/store on
   2404    MIPS64 platforms.
   2405 */
   2406 static UChar* do_load_or_store_machine_word ( UChar* p, Bool isLoad, UInt reg,
   2407                                               MIPSAMode* am, Bool mode64 )
   2408 {
   2409    if (isLoad) { /* load */
   2410       switch (am->tag) {
   2411          case Mam_IR:
   2412             if (mode64) {
   2413                vassert(0 == (am->Mam.IR.index & 3));
   2414             }
   2415             p = doAMode_IR(p, mode64 ? 55 : 35, reg, am, mode64);
   2416             break;
   2417          case Mam_RR:
   2418             /* we could handle this case, but we don't expect to ever
   2419                need to. */
   2420             vassert(0);
   2421             break;
   2422          default:
   2423             vassert(0);
   2424             break;
   2425       }
   2426    } else /* store */ {
   2427       switch (am->tag) {
   2428          case Mam_IR:
   2429             if (mode64) {
   2430                vassert(0 == (am->Mam.IR.index & 3));
   2431             }
   2432             p = doAMode_IR(p, mode64 ? 63 : 43, reg, am, mode64);
   2433             break;
   2434          case Mam_RR:
   2435             /* we could handle this case, but we don't expect to ever
   2436                need to. */
   2437             vassert(0);
   2438             break;
   2439          default:
   2440             vassert(0);
   2441             break;
   2442       }
   2443    }
   2444    return p;
   2445 }
   2446 
   2447 /* Generate a 32-bit sized load or store. Simplified version of
   2448    do_load_or_store_machine_word above. */
   2449 static UChar* do_load_or_store_word32 ( UChar* p, Bool isLoad, UInt reg,
   2450                                         MIPSAMode* am, Bool mode64 )
   2451 {
   2452    if (isLoad) { /* load */
   2453       switch (am->tag) {
   2454          case Mam_IR:
   2455             if (mode64) {
   2456                vassert(0 == (am->Mam.IR.index & 3));
   2457             }
   2458             p = doAMode_IR(p, 35, reg, am, mode64);
   2459             break;
   2460          case Mam_RR:
   2461             /* we could handle this case, but we don't expect to ever
   2462                need to. */
   2463             vassert(0);
   2464             break;
   2465          default:
   2466             vassert(0);
   2467             break;
   2468       }
   2469    } else /* store */ {
   2470       switch (am->tag) {
   2471          case Mam_IR:
   2472             if (mode64) {
   2473                vassert(0 == (am->Mam.IR.index & 3));
   2474             }
   2475             p = doAMode_IR(p, 43, reg, am, mode64);
   2476             break;
   2477          case Mam_RR:
   2478             /* we could handle this case, but we don't expect to ever
   2479                need to. */
   2480             vassert(0);
   2481             break;
   2482          default:
   2483             vassert(0);
   2484             break;
   2485       }
   2486    }
   2487    return p;
   2488 }
   2489 
   2490 /* Move r_dst to r_src */
   2491 static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src)
   2492 {
   2493    vassert(r_dst < 0x20);
   2494    vassert(r_src < 0x20);
   2495 
   2496    if (r_dst != r_src) {
   2497       /* or r_dst, r_src, r_src */
   2498       p = mkFormR(p, 0, r_src, r_src, r_dst, 0, 37);
   2499    }
   2500    return p;
   2501 }
   2502 
   2503 /* Emit an instruction into buf and return the number of bytes used.
   2504    Note that buf is not the insn's final place, and therefore it is
   2505    imperative to emit position-independent code.  If the emitted
   2506    instruction was a profiler inc, set *is_profInc to True, else
   2507    leave it unchanged. */
   2508 Int emit_MIPSInstr ( /*MB_MOD*/Bool* is_profInc,
   2509                      UChar* buf, Int nbuf, const MIPSInstr* i,
   2510                      Bool mode64,
   2511                      VexEndness endness_host,
   2512                      const void* disp_cp_chain_me_to_slowEP,
   2513                      const void* disp_cp_chain_me_to_fastEP,
   2514                      const void* disp_cp_xindir,
   2515                      const void* disp_cp_xassisted )
   2516 {
   2517    UChar *p = &buf[0];
   2518    UChar *ptmp = p;
   2519    vassert(nbuf >= 32);
   2520 
   2521    switch (i->tag) {
   2522       case Min_LI:
   2523          p = mkLoadImm(p, iregNo(i->Min.LI.dst, mode64), i->Min.LI.imm, mode64);
   2524          goto done;
   2525 
   2526       case Min_Alu: {
   2527          MIPSRH *srcR = i->Min.Alu.srcR;
   2528          Bool immR = toBool(srcR->tag == Mrh_Imm);
   2529          UInt r_dst = iregNo(i->Min.Alu.dst, mode64);
   2530          UInt r_srcL = iregNo(i->Min.Alu.srcL, mode64);
   2531          UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg,
   2532                                                        mode64);
   2533          switch (i->Min.Alu.op) {
   2534             /* Malu_ADD, Malu_SUB, Malu_AND, Malu_OR, Malu_NOR, Malu_XOR, Malu_SLT */
   2535             case Malu_ADD:
   2536                if (immR) {
   2537                   vassert(srcR->Mrh.Imm.syned);
   2538                   /* addiu */
   2539                   p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
   2540                } else {
   2541                   /* addu */
   2542                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 33);
   2543                }
   2544                break;
   2545             case Malu_SUB:
   2546                if (immR) {
   2547                   /* addiu , but with negated imm */
   2548                   vassert(srcR->Mrh.Imm.syned);
   2549                   vassert(srcR->Mrh.Imm.imm16 != 0x8000);
   2550                   p = mkFormI(p, 9, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16));
   2551                } else {
   2552                   /* subu */
   2553                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 35);
   2554                }
   2555                break;
   2556             case Malu_AND:
   2557                if (immR) {
   2558                   /* andi */
   2559                   vassert(!srcR->Mrh.Imm.syned);
   2560                   p = mkFormI(p, 12, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
   2561                } else {
   2562                   /* and */
   2563                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 36);
   2564                }
   2565                break;
   2566             case Malu_OR:
   2567                if (immR) {
   2568                   /* ori */
   2569                   vassert(!srcR->Mrh.Imm.syned);
   2570                   p = mkFormI(p, 13, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
   2571                } else {
   2572                   /* or */
   2573                   if (r_srcL == 33)
   2574                      /* MFHI */
   2575                      p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
   2576                   else if (r_srcL == 34)
   2577                      /* MFLO */
   2578                      p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
   2579                   else if (r_dst == 33)
   2580                      /* MTHI */
   2581                      p = mkFormR(p, 0, r_srcL, 0, 0, 0, 17);
   2582                   else if (r_dst == 34)
   2583                      /* MTLO */
   2584                      p = mkFormR(p, 0, r_srcL, 0, 0, 0, 19);
   2585                   else
   2586                      p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 37);
   2587                }
   2588                break;
   2589             case Malu_NOR:
   2590                /* nor */
   2591                vassert(!immR);
   2592                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 39);
   2593                break;
   2594             case Malu_XOR:
   2595                if (immR) {
   2596                   /* xori */
   2597                   vassert(!srcR->Mrh.Imm.syned);
   2598                   p = mkFormI(p, 14, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
   2599                } else {
   2600                   /* xor */
   2601                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
   2602                }
   2603                break;
   2604             case Malu_DADD:
   2605                if (immR) {
   2606                   vassert(srcR->Mrh.Imm.syned);
   2607                   vassert(srcR->Mrh.Imm.imm16 != 0x8000);
   2608                   p = mkFormI(p, 25, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
   2609                } else {
   2610                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 45);
   2611                }
   2612                break;
   2613             case Malu_DSUB:
   2614                if (immR) {
   2615                   p = mkFormI(p, 25, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16));
   2616                } else {
   2617                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 47);
   2618                }
   2619                break;
   2620             case Malu_SLT:
   2621                if (immR) {
   2622                   goto bad;
   2623                } else {
   2624                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
   2625                }
   2626                break;
   2627 
   2628             default:
   2629                goto bad;
   2630          }
   2631          goto done;
   2632       }
   2633 
   2634       case Min_Shft: {
   2635          MIPSRH *srcR = i->Min.Shft.srcR;
   2636          Bool sz32 = i->Min.Shft.sz32;
   2637          Bool immR = toBool(srcR->tag == Mrh_Imm);
   2638          UInt r_dst = iregNo(i->Min.Shft.dst, mode64);
   2639          UInt r_srcL = iregNo(i->Min.Shft.srcL, mode64);
   2640          UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg,
   2641                                                        mode64);
   2642          if (!mode64)
   2643             vassert(sz32);
   2644          switch (i->Min.Shft.op) {
   2645             case Mshft_SLL:
   2646                if (sz32) {
   2647                   if (immR) {
   2648                      UInt n = srcR->Mrh.Imm.imm16;
   2649                      vassert(n >= 0 && n <= 32);
   2650                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 0);
   2651                   } else {
   2652                      /* shift variable */
   2653                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 4);
   2654                   }
   2655                } else {
   2656                   if (immR) {
   2657                      UInt n = srcR->Mrh.Imm.imm16;
   2658                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
   2659                      if (n >= 0 && n < 32) {
   2660                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 56);
   2661                      } else {
   2662                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 60);
   2663                      }
   2664                   } else {
   2665                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 20);
   2666                   }
   2667                }
   2668                break;
   2669 
   2670             case Mshft_SRL:
   2671                if (sz32) {
   2672                   /* SRL, SRLV */
   2673                   if (immR) {
   2674                      UInt n = srcR->Mrh.Imm.imm16;
   2675                      vassert(n >= 0 && n < 32);
   2676                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 2);
   2677                   } else {
   2678                      /* shift variable */
   2679                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 6);
   2680                   }
   2681                } else {
   2682                   /* DSRL, DSRL32, DSRLV */
   2683                   if (immR) {
   2684                      UInt n = srcR->Mrh.Imm.imm16;
   2685                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
   2686                      if (n >= 0 && n < 32) {
   2687                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 58);
   2688                      } else {
   2689                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 62);
   2690                      }
   2691                   } else {
   2692                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 22);
   2693                   }
   2694                }
   2695                break;
   2696 
   2697             case Mshft_SRA:
   2698                if (sz32) {
   2699                   /* SRA, SRAV */
   2700                   if (immR) {
   2701                      UInt n = srcR->Mrh.Imm.imm16;
   2702                      vassert(n >= 0 && n < 32);
   2703                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 3);
   2704                   } else {
   2705                      /* shift variable */
   2706                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 7);
   2707                   }
   2708                } else {
   2709                   /* DSRA, DSRA32, DSRAV */
   2710                   if (immR) {
   2711                      UInt n = srcR->Mrh.Imm.imm16;
   2712                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
   2713                      if (n >= 0 && n < 32) {
   2714                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 59);
   2715                      } else {
   2716                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 63);
   2717                      }
   2718                   } else {
   2719                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 23);
   2720                   }
   2721                }
   2722                break;
   2723 
   2724             default:
   2725                goto bad;
   2726          }
   2727 
   2728          goto done;
   2729       }
   2730 
   2731       case Min_Unary: {
   2732          UInt r_dst = iregNo(i->Min.Unary.dst, mode64);
   2733          UInt r_src = iregNo(i->Min.Unary.src, mode64);
   2734 
   2735          switch (i->Min.Unary.op) {
   2736             /* Mun_CLO, Mun_CLZ, Mun_NOP, Mun_DCLO, Mun_DCLZ */
   2737             case Mun_CLO:  /* clo */
   2738                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 33);
   2739                break;
   2740             case Mun_CLZ:  /* clz */
   2741                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 32);
   2742                break;
   2743             case Mun_NOP:  /* nop (sll r0,r0,0) */
   2744                p = mkFormR(p, 0, 0, 0, 0, 0, 0);
   2745                break;
   2746             case Mun_DCLO:  /* clo */
   2747                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 37);
   2748                break;
   2749             case Mun_DCLZ:  /* clz */
   2750                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 36);
   2751                break;
   2752          }
   2753          goto done;
   2754       }
   2755 
   2756       case Min_Cmp: {
   2757          UInt r_srcL = iregNo(i->Min.Cmp.srcL, mode64);
   2758          UInt r_srcR = iregNo(i->Min.Cmp.srcR, mode64);
   2759          UInt r_dst = iregNo(i->Min.Cmp.dst, mode64);
   2760 
   2761          switch (i->Min.Cmp.cond) {
   2762             case MIPScc_EQ:
   2763                /* xor r_dst, r_srcL, r_srcR
   2764                   sltiu r_dst, r_dst, 1 */
   2765                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
   2766                p = mkFormI(p, 11, r_dst, r_dst, 1);
   2767                break;
   2768             case MIPScc_NE:
   2769                /* xor r_dst, r_srcL, r_srcR
   2770                   sltu r_dst, zero, r_dst */
   2771                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
   2772                p = mkFormR(p, 0, 0, r_dst, r_dst, 0, 43);
   2773                break;
   2774             case MIPScc_LT:
   2775                /* slt r_dst, r_srcL, r_srcR */
   2776                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
   2777                break;
   2778             case MIPScc_LO:
   2779                /* sltu r_dst, r_srcL, r_srcR */
   2780                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43);
   2781                break;
   2782             case MIPScc_LE:
   2783                /* slt r_dst, r_srcR, r_srcL
   2784                   xori r_dst, r_dst, 1 */
   2785                p = mkFormR(p, 0, r_srcR, r_srcL, r_dst, 0, 42);
   2786                p = mkFormI(p, 14, r_dst, r_dst, 1);
   2787                break;
   2788             case MIPScc_LS:
   2789                /* sltu r_dst, rsrcR, r_srcL
   2790                   xori r_dsr, r_dst, 1 */
   2791                p = mkFormR(p, 0, r_srcR, r_srcL, r_dst, 0, 43);
   2792                p = mkFormI(p, 14, r_dst, r_dst, 1);
   2793                break;
   2794             default:
   2795                goto bad;
   2796          }
   2797          goto done;
   2798       }
   2799 
   2800       case Min_Mul: {
   2801          Bool syned = i->Min.Mul.syned;
   2802          Bool widening = i->Min.Mul.widening;
   2803          Bool sz32 = i->Min.Mul.sz32;
   2804          UInt r_srcL = iregNo(i->Min.Mul.srcL, mode64);
   2805          UInt r_srcR = iregNo(i->Min.Mul.srcR, mode64);
   2806          UInt r_dst = iregNo(i->Min.Mul.dst, mode64);
   2807          if (widening) {
   2808             if (sz32) {
   2809                if (syned)
   2810                   /* mult */
   2811                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24);
   2812                else
   2813                   /* multu */
   2814                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25);
   2815             } else {
   2816                if (syned)  /* DMULT  r_dst,r_srcL,r_srcR */
   2817                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28);
   2818                else  /* DMULTU r_dst,r_srcL,r_srcR */
   2819                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29);
   2820             }
   2821          } else {
   2822             if (sz32)
   2823                /* mul */
   2824                p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
   2825             else if (mode64 && !sz32)
   2826                p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
   2827             else
   2828                goto bad;
   2829          }
   2830          goto done;
   2831       }
   2832 
   2833       case Min_Macc: {
   2834          Bool syned = i->Min.Macc.syned;
   2835          UInt r_srcL = iregNo(i->Min.Macc.srcL, mode64);
   2836          UInt r_srcR = iregNo(i->Min.Macc.srcR, mode64);
   2837 
   2838          if (syned) {
   2839             switch (i->Min.Macc.op) {
   2840                case Macc_ADD:
   2841                   /* madd */
   2842                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 0);
   2843                   break;
   2844                case Macc_SUB:
   2845                   /* msub */
   2846                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
   2847                          4);
   2848                   break;
   2849                default:
   2850                   goto bad;
   2851             }
   2852          } else {
   2853             switch (i->Min.Macc.op) {
   2854                case Macc_ADD:
   2855                   /* maddu */
   2856                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
   2857                          1);
   2858                   break;
   2859                case Macc_SUB:
   2860                   /* msubu */
   2861                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
   2862                          5);
   2863                   break;
   2864                default:
   2865                   goto bad;
   2866             }
   2867          }
   2868 
   2869          goto done;
   2870       }
   2871 
   2872       case Min_Div: {
   2873          Bool syned = i->Min.Div.syned;
   2874          Bool sz32 = i->Min.Div.sz32;
   2875          UInt r_srcL = iregNo(i->Min.Div.srcL, mode64);
   2876          UInt r_srcR = iregNo(i->Min.Div.srcR, mode64);
   2877          if (sz32) {
   2878             if (syned) {
   2879                /* div */
   2880                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 26);
   2881             } else
   2882                /* divu */
   2883                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 27);
   2884             goto done;
   2885          } else {
   2886             if (syned) {
   2887                /* ddiv */
   2888                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 30);
   2889             } else
   2890                /* ddivu */
   2891                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 31);
   2892             goto done;
   2893          }
   2894       }
   2895 
   2896       case Min_Mthi: {
   2897          UInt r_src = iregNo(i->Min.MtHL.src, mode64);
   2898          p = mkFormR(p, 0, r_src, 0, 0, 0, 17);
   2899          goto done;
   2900       }
   2901 
   2902       case Min_Mtlo: {
   2903          UInt r_src = iregNo(i->Min.MtHL.src, mode64);
   2904          p = mkFormR(p, 0, r_src, 0, 0, 0, 19);
   2905          goto done;
   2906       }
   2907 
   2908       case Min_Mfhi: {
   2909          UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
   2910          p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
   2911          goto done;
   2912       }
   2913 
   2914       case Min_Mflo: {
   2915          UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
   2916          p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
   2917          goto done;
   2918       }
   2919 
   2920       case Min_MtFCSR: {
   2921          UInt r_src = iregNo(i->Min.MtFCSR.src, mode64);
   2922          /* ctc1 */
   2923          p = mkFormR(p, 17, 6, r_src, 31, 0, 0);
   2924          goto done;
   2925       }
   2926 
   2927       case Min_MfFCSR: {
   2928          UInt r_dst = iregNo(i->Min.MfFCSR.dst, mode64);
   2929          /* cfc1 */
   2930          p = mkFormR(p, 17, 2, r_dst, 31, 0, 0);
   2931          goto done;
   2932       }
   2933 
   2934       case Min_Call: {
   2935          if (i->Min.Call.cond != MIPScc_AL
   2936              && i->Min.Call.rloc.pri != RLPri_None) {
   2937             /* The call might not happen (it isn't unconditional) and
   2938                it returns a result.  In this case we will need to
   2939                generate a control flow diamond to put 0x555..555 in
   2940                the return register(s) in the case where the call
   2941                doesn't happen.  If this ever becomes necessary, maybe
   2942                copy code from the ARM equivalent.  Until that day,
   2943                just give up. */
   2944             goto bad;
   2945          }
   2946          MIPSCondCode cond = i->Min.Call.cond;
   2947          UInt r_dst = 25;  /* using %r25 as address temporary -
   2948                               see getRegUsage_MIPSInstr */
   2949 
   2950          /* jump over the following insns if condition does not hold */
   2951          if (cond != MIPScc_AL) {
   2952             /* jmp fwds if !condition */
   2953             /* don't know how many bytes to jump over yet...
   2954                make space for a jump instruction + nop!!! and fill in later. */
   2955             ptmp = p;  /* fill in this bit later */
   2956             p += 8;    /* p += 8 */
   2957          }
   2958 
   2959          if (!mode64) {
   2960             /* addiu $29, $29, -16 */
   2961             p = mkFormI(p, 9, 29, 29, 0xFFF0);
   2962          }
   2963 
   2964          /* load target to r_dst; p += 4|8 */
   2965          p = mkLoadImm(p, r_dst, i->Min.Call.target, mode64);
   2966 
   2967          /* jalr r_dst */
   2968          p = mkFormR(p, 0, r_dst, 0, 31, 0, 9);  /* p += 4 */
   2969          p = mkFormR(p, 0, 0, 0, 0, 0, 0);       /* p += 4 */
   2970 
   2971          if (!mode64) {
   2972             /* addiu $29, $29, 16 */
   2973             p = mkFormI(p, 9, 29, 29, 0x0010);
   2974          }
   2975 
   2976          /* Fix up the conditional jump, if there was one. */
   2977          if (cond != MIPScc_AL) {
   2978             UInt r_src = iregNo(i->Min.Call.src, mode64);
   2979             Int delta = p - ptmp;
   2980 
   2981             vassert(delta >= 20 && delta <= 32);
   2982             /* blez r_src, delta/4-1
   2983                nop */
   2984             ptmp = mkFormI(ptmp, 6, r_src, 0, delta / 4 - 1);
   2985             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
   2986          }
   2987          goto done;
   2988       }
   2989 
   2990       case Min_XDirect: {
   2991          /* NB: what goes on here has to be very closely coordinated
   2992             with the chainXDirect_MIPS and unchainXDirect_MIPS below. */
   2993          /* We're generating chain-me requests here, so we need to be
   2994             sure this is actually allowed -- no-redir translations
   2995             can't use chain-me's.  Hence: */
   2996          vassert(disp_cp_chain_me_to_slowEP != NULL);
   2997          vassert(disp_cp_chain_me_to_fastEP != NULL);
   2998 
   2999          /* Use ptmp for backpatching conditional jumps. */
   3000          ptmp = NULL;
   3001 
   3002          /* First off, if this is conditional, create a conditional
   3003             jump over the rest of it.  Or at least, leave a space for
   3004             it that we will shortly fill in. */
   3005          if (i->Min.XDirect.cond != MIPScc_AL) {
   3006             vassert(i->Min.XDirect.cond != MIPScc_NV);
   3007             ptmp = p;
   3008             p += 12;
   3009          }
   3010 
   3011          /* Update the guest PC. */
   3012          /* move r9, dstGA */
   3013          /* sw/sd r9, amPC */
   3014          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, (ULong)i->Min.XDirect.dstGA,
   3015                                    mode64);
   3016          p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 9,
   3017                                            i->Min.XDirect.amPC, mode64);
   3018 
   3019          /* --- FIRST PATCHABLE BYTE follows --- */
   3020          /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
   3021             calling to) backs up the return address, so as to find the
   3022             address of the first patchable byte.  So: don't change the
   3023             number of instructions (3) below. */
   3024          /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */
   3025          /* jr  r9  */
   3026          const void* disp_cp_chain_me
   3027                   = i->Min.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
   3028                                               : disp_cp_chain_me_to_slowEP;
   3029          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
   3030                                    (Addr)disp_cp_chain_me, mode64);
   3031          /* jalr $9 */
   3032          /* nop */
   3033          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
   3034          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
   3035          /* --- END of PATCHABLE BYTES --- */
   3036 
   3037          /* Fix up the conditional jump, if there was one. */
   3038          if (i->Min.XDirect.cond != MIPScc_AL) {
   3039             Int delta = p - ptmp;
   3040             delta = delta / 4 - 3;
   3041             vassert(delta > 0 && delta < 40);
   3042 
   3043             /* lw $9, COND_OFFSET(GuestSP)
   3044                beq $9, $0, 2
   3045                nop */
   3046             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
   3047             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
   3048             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
   3049          }
   3050          goto done;
   3051       }
   3052 
   3053       case Min_XIndir: {
   3054          /* We're generating transfers that could lead indirectly to a
   3055             chain-me, so we need to be sure this is actually allowed --
   3056             no-redir translations are not allowed to reach normal
   3057             translations without going through the scheduler.  That means
   3058             no XDirects or XIndirs out from no-redir translations.
   3059             Hence: */
   3060          vassert(disp_cp_xindir != NULL);
   3061 
   3062          /* Use ptmp for backpatching conditional jumps. */
   3063          ptmp = NULL;
   3064 
   3065          /* First off, if this is conditional, create a conditional
   3066             jump over the rest of it. */
   3067          if (i->Min.XIndir.cond != MIPScc_AL) {
   3068             vassert(i->Min.XIndir.cond != MIPScc_NV);
   3069             ptmp = p;
   3070             p += 12;
   3071          }
   3072 
   3073          /* Update the guest PC. */
   3074          /* sw/sd r-dstGA, amPC */
   3075          p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
   3076                                            iregNo(i->Min.XIndir.dstGA, mode64),
   3077                                            i->Min.XIndir.amPC, mode64);
   3078 
   3079          /* move r9, VG_(disp_cp_xindir) */
   3080          /* jalr   r9 */
   3081          /* nop */
   3082          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
   3083                                    (Addr)disp_cp_xindir, mode64);
   3084          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
   3085          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
   3086 
   3087          /* Fix up the conditional jump, if there was one. */
   3088          if (i->Min.XIndir.cond != MIPScc_AL) {
   3089             Int delta = p - ptmp;
   3090             delta = delta / 4 - 3;
   3091             vassert(delta > 0 && delta < 40);
   3092 
   3093             /* lw $9, COND_OFFSET($GuestSP)
   3094                beq $9, $0, 2
   3095                nop */
   3096             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
   3097             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
   3098             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
   3099          }
   3100          goto done;
   3101       }
   3102 
   3103       case Min_XAssisted: {
   3104          /* First off, if this is conditional, create a conditional jump
   3105             over the rest of it.  Or at least, leave a space for it that
   3106             we will shortly fill in. */
   3107          ptmp = NULL;
   3108          if (i->Min.XAssisted.cond != MIPScc_AL) {
   3109             vassert(i->Min.XAssisted.cond != MIPScc_NV);
   3110             ptmp = p;
   3111             p += 12;
   3112          }
   3113 
   3114          /* Update the guest PC. */
   3115          /* sw/sd r-dstGA, amPC */
   3116          p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
   3117                                            iregNo(i->Min.XIndir.dstGA, mode64),
   3118                                            i->Min.XIndir.amPC, mode64);
   3119 
   3120          /* imm32/64 r31, $magic_number */
   3121          UInt trcval = 0;
   3122          switch (i->Min.XAssisted.jk) {
   3123             case Ijk_ClientReq:     trcval = VEX_TRC_JMP_CLIENTREQ;     break;
   3124             case Ijk_Sys_syscall:   trcval = VEX_TRC_JMP_SYS_SYSCALL;   break;
   3125             /* case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128;   break; */
   3126             case Ijk_Yield:         trcval = VEX_TRC_JMP_YIELD;       break;
   3127             case Ijk_EmWarn:        trcval = VEX_TRC_JMP_EMWARN;        break;
   3128             case Ijk_EmFail:        trcval = VEX_TRC_JMP_EMFAIL;        break;
   3129             /* case Ijk_MapFail:   trcval = VEX_TRC_JMP_MAPFAIL;       break; */
   3130             case Ijk_NoDecode:      trcval = VEX_TRC_JMP_NODECODE;      break;
   3131             case Ijk_InvalICache:   trcval = VEX_TRC_JMP_INVALICACHE;   break;
   3132             case Ijk_NoRedir:       trcval = VEX_TRC_JMP_NOREDIR;       break;
   3133             case Ijk_SigILL:        trcval = VEX_TRC_JMP_SIGILL;        break;
   3134             case Ijk_SigTRAP:       trcval = VEX_TRC_JMP_SIGTRAP;       break;
   3135             /* case Ijk_SigSEGV:   trcval = VEX_TRC_JMP_SIGSEGV;       break; */
   3136             case Ijk_SigBUS:        trcval = VEX_TRC_JMP_SIGBUS;        break;
   3137             case Ijk_SigFPE_IntDiv: trcval = VEX_TRC_JMP_SIGFPE_INTDIV; break;
   3138             case Ijk_SigFPE_IntOvf: trcval = VEX_TRC_JMP_SIGFPE_INTOVF; break;
   3139             case Ijk_Boring:        trcval = VEX_TRC_JMP_BORING;        break;
   3140             /* We don't expect to see the following being assisted.
   3141                case Ijk_Ret:
   3142                case Ijk_Call:
   3143                fallthrough */
   3144             default:
   3145                ppIRJumpKind(i->Min.XAssisted.jk);
   3146                vpanic("emit_MIPSInstr.Min_XAssisted: unexpected jump kind");
   3147          }
   3148          vassert(trcval != 0);
   3149          p = mkLoadImm_EXACTLY2or6(p, /*r*/ GuestSP, trcval, mode64);
   3150 
   3151          /* move r9, VG_(disp_cp_xassisted) */
   3152          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
   3153                                    (ULong)(Addr)disp_cp_xassisted, mode64);
   3154          /* jalr $9
   3155              nop */
   3156          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
   3157          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
   3158 
   3159          /* Fix up the conditional jump, if there was one. */
   3160          if (i->Min.XAssisted.cond != MIPScc_AL) {
   3161             Int delta = p - ptmp;
   3162             delta = delta / 4 - 3;
   3163             vassert(delta > 0 && delta < 40);
   3164 
   3165             /* lw $9, COND_OFFSET($GuestSP)
   3166                beq $9, $0, 2
   3167                nop */
   3168             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
   3169             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
   3170             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
   3171          }
   3172          goto done;
   3173       }
   3174 
   3175       case Min_Load: {
   3176          MIPSAMode *am_addr = i->Min.Load.src;
   3177          if (am_addr->tag == Mam_IR) {
   3178             UInt r_dst = iregNo(i->Min.Load.dst, mode64);
   3179             UInt opc, sz = i->Min.Load.sz;
   3180             if (mode64 && (sz == 4 || sz == 8)) {
   3181                /* should be guaranteed to us by iselWordExpr_AMode */
   3182                vassert(0 == (am_addr->Mam.IR.index & 3));
   3183             }
   3184             switch (sz) {
   3185                case 1:
   3186                   opc = 32;
   3187                   break;
   3188                case 2:
   3189                   opc = 33;
   3190                   break;
   3191                case 4:
   3192                   opc = 35;
   3193                   break;
   3194                case 8:
   3195                   opc = 55;
   3196                   vassert(mode64);
   3197                   break;
   3198                default:
   3199                   goto bad;
   3200             }
   3201 
   3202             p = doAMode_IR(p, opc, r_dst, am_addr, mode64);
   3203             goto done;
   3204          } else if (am_addr->tag == Mam_RR) {
   3205             UInt r_dst = iregNo(i->Min.Load.dst, mode64);
   3206             UInt opc, sz = i->Min.Load.sz;
   3207 
   3208             switch (sz) {
   3209                case 1:
   3210                   opc = 32;
   3211                   break;
   3212                case 2:
   3213                   opc = 33;
   3214                   break;
   3215                case 4:
   3216                   opc = 35;
   3217                   break;
   3218                case 8:
   3219                   opc = 55;
   3220                   vassert(mode64);
   3221                   break;
   3222                default:
   3223                   goto bad;
   3224             }
   3225 
   3226             p = doAMode_RR(p, opc, r_dst, am_addr, mode64);
   3227             goto done;
   3228          }
   3229          break;
   3230       }
   3231 
   3232       case Min_Store: {
   3233          MIPSAMode *am_addr = i->Min.Store.dst;
   3234          if (am_addr->tag == Mam_IR) {
   3235             UInt r_src = iregNo(i->Min.Store.src, mode64);
   3236             UInt opc, sz = i->Min.Store.sz;
   3237             if (mode64 && (sz == 4 || sz == 8)) {
   3238                /* should be guaranteed to us by iselWordExpr_AMode */
   3239                vassert(0 == (am_addr->Mam.IR.index & 3));
   3240             }
   3241             switch (sz) {
   3242                case 1:
   3243                   opc = 40;
   3244                   break;
   3245                case 2:
   3246                   opc = 41;
   3247                   break;
   3248                case 4:
   3249                   opc = 43;
   3250                   break;
   3251                case 8:
   3252                   vassert(mode64);
   3253                   opc = 63;
   3254                   break;
   3255                default:
   3256                   goto bad;
   3257             }
   3258 
   3259             p = doAMode_IR(p, opc, r_src, am_addr, mode64);
   3260             goto done;
   3261          } else if (am_addr->tag == Mam_RR) {
   3262             UInt r_src = iregNo(i->Min.Store.src, mode64);
   3263             UInt opc, sz = i->Min.Store.sz;
   3264 
   3265             switch (sz) {
   3266                case 1:
   3267                   opc = 40;
   3268                   break;
   3269                case 2:
   3270                   opc = 41;
   3271                   break;
   3272                case 4:
   3273                   opc = 43;
   3274                   break;
   3275                case 8:
   3276                   vassert(mode64);
   3277                   opc = 63;
   3278                   break;
   3279                default:
   3280                   goto bad;
   3281             }
   3282 
   3283             p = doAMode_RR(p, opc, r_src, am_addr, mode64);
   3284             goto done;
   3285          }
   3286          break;
   3287       }
   3288       case Min_LoadL: {
   3289          MIPSAMode *am_addr = i->Min.LoadL.src;
   3290          UInt r_src = iregNo(am_addr->Mam.IR.base, mode64);
   3291          UInt idx = am_addr->Mam.IR.index;
   3292          UInt r_dst = iregNo(i->Min.LoadL.dst, mode64);
   3293 
   3294          if (i->Min.LoadL.sz == 4)
   3295             p = mkFormI(p, 0x30, r_src, r_dst, idx);
   3296          else
   3297             p = mkFormI(p, 0x34, r_src, r_dst, idx);
   3298          goto done;
   3299       }
   3300       case Min_StoreC: {
   3301          MIPSAMode *am_addr = i->Min.StoreC.dst;
   3302          UInt r_src = iregNo(i->Min.StoreC.src, mode64);
   3303          UInt idx = am_addr->Mam.IR.index;
   3304          UInt r_dst = iregNo(am_addr->Mam.IR.base, mode64);
   3305 
   3306          if (i->Min.StoreC.sz == 4)
   3307             p = mkFormI(p, 0x38, r_dst, r_src, idx);
   3308          else
   3309             p = mkFormI(p, 0x3C, r_dst, r_src, idx);
   3310          goto done;
   3311       }
   3312       case Min_Cas: {
   3313          if (i->Min.Cas.sz != 8 && i->Min.Cas.sz != 4)
   3314             goto bad;
   3315          UInt old  = iregNo(i->Min.Cas.old, mode64);
   3316          UInt addr = iregNo(i->Min.Cas.addr, mode64);
   3317          UInt expd = iregNo(i->Min.Cas.expd, mode64);
   3318          UInt data = iregNo(i->Min.Cas.data, mode64);
   3319          Bool sz8  = toBool(i->Min.Cas.sz == 8);
   3320 
   3321          /*
   3322           * ll(d)    old,  0(addr)
   3323           * bne      old,  expd, end
   3324           * nop
   3325           * (d)addiu old,  old,  1
   3326           * sc(d)    data, 0(addr)
   3327           * movn     old,  expd, data
   3328           * end:
   3329           */
   3330          // ll(d) old, 0(addr)
   3331          p = mkFormI(p, sz8 ? 0x34 : 0x30, addr, old, 0);
   3332          // bne  old,  expd, end
   3333          p = mkFormI(p, 5, old, expd, 4);
   3334          // nop
   3335          p = mkFormR(p, 0, 0, 0, 0, 0, 0);
   3336          // (d)addiu old,  old,  1
   3337          p = mkFormI(p, sz8 ? 25 : 9, old, old, 1);
   3338          // sc(d)  data, 0(addr)
   3339          p = mkFormI(p, sz8 ? 0x3C : 0x38, addr, data, 0);
   3340          // movn old,  expd, data
   3341          p = mkFormR(p, 0, expd, data, old, 0, 0xb);
   3342 
   3343          goto done;
   3344       }
   3345       case Min_RdWrLR: {
   3346          UInt reg = iregNo(i->Min.RdWrLR.gpr, mode64);
   3347          Bool wrLR = i->Min.RdWrLR.wrLR;
   3348          if (wrLR)
   3349             p = mkMoveReg(p, 31, reg);
   3350          else
   3351             p = mkMoveReg(p, reg, 31);
   3352          goto done;
   3353       }
   3354 
   3355       /* Floating point */
   3356       case Min_FpLdSt: {
   3357          MIPSAMode *am_addr = i->Min.FpLdSt.addr;
   3358          UChar sz = i->Min.FpLdSt.sz;
   3359          vassert(sz == 4 || sz == 8);
   3360          if (sz == 4) {
   3361             UInt f_reg = fregNo(i->Min.FpLdSt.reg, mode64);
   3362             if (i->Min.FpLdSt.isLoad) {
   3363                if (am_addr->tag == Mam_IR)
   3364                   p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64);
   3365                else if (am_addr->tag == Mam_RR)
   3366                   p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64);
   3367             } else {
   3368                if (am_addr->tag == Mam_IR)
   3369                   p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64);
   3370                else if (am_addr->tag == Mam_RR)
   3371                   p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64);
   3372             }
   3373          } else if (sz == 8) {
   3374             UInt f_reg = dregNo(i->Min.FpLdSt.reg);
   3375             if (i->Min.FpLdSt.isLoad) {
   3376                if (am_addr->tag == Mam_IR) {
   3377                   p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64);
   3378                } else if (am_addr->tag == Mam_RR) {
   3379                   p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64);
   3380                }
   3381             } else {
   3382                if (am_addr->tag == Mam_IR) {
   3383                   p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64);
   3384                } else if (am_addr->tag == Mam_RR) {
   3385                   p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64);
   3386                }
   3387             }
   3388          }
   3389          goto done;
   3390       }
   3391 
   3392       case Min_FpUnary: {
   3393          switch (i->Min.FpUnary.op) {
   3394             case Mfp_MOVS: {  /* FP move */
   3395                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
   3396                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
   3397                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x6);
   3398                break;
   3399             }
   3400             case Mfp_MOVD: {  /* FP move */
   3401                 UInt fr_dst = dregNo(i->Min.FpUnary.dst);
   3402                 UInt fr_src = dregNo(i->Min.FpUnary.src);
   3403                 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x6);
   3404                 break;
   3405              }
   3406             case Mfp_ABSS: {  /* ABS.S */
   3407                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
   3408                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
   3409                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x5);
   3410                break;
   3411             }
   3412             case Mfp_ABSD: {  /* ABS.D */
   3413                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
   3414                UInt fr_src = dregNo(i->Min.FpUnary.src);
   3415                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x5);
   3416                break;
   3417             }
   3418             case Mfp_NEGS: {  /* NEG.S */
   3419                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
   3420                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
   3421                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x7);
   3422                break;
   3423             }
   3424             case Mfp_NEGD: {  /* NEG.D */
   3425                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
   3426                UInt fr_src = dregNo(i->Min.FpUnary.src);
   3427                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x7);
   3428                break;
   3429             }
   3430             case Mfp_SQRTS: {  /* SQRT.S */
   3431                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
   3432                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
   3433                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x04);
   3434                break;
   3435             }
   3436             case Mfp_SQRTD: {  /* SQRT.D */
   3437                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
   3438                UInt fr_src = dregNo(i->Min.FpUnary.src);
   3439                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x04);
   3440                break;
   3441             }
   3442             default:
   3443                goto bad;
   3444          }
   3445          goto done;
   3446       }
   3447 
   3448       case Min_FpBinary: {
   3449          switch (i->Min.FpBinary.op) {
   3450             case Mfp_ADDS: {
   3451                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
   3452                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
   3453                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
   3454                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 0);
   3455                break;
   3456             }
   3457             case Mfp_SUBS: {
   3458                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
   3459                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
   3460                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
   3461                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 1);
   3462                break;
   3463             }
   3464             case Mfp_MULS: {
   3465                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
   3466                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
   3467                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
   3468                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 2);
   3469                break;
   3470             }
   3471             case Mfp_DIVS: {
   3472                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
   3473                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
   3474                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
   3475                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 3);
   3476                break;
   3477             }
   3478             case Mfp_ADDD: {
   3479                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
   3480                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
   3481                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
   3482                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 0);
   3483                break;
   3484             }
   3485             case Mfp_SUBD: {
   3486                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
   3487                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
   3488                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
   3489                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 1);
   3490                break;
   3491             }
   3492             case Mfp_MULD: {
   3493                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
   3494                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
   3495                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
   3496                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 2);
   3497                break;
   3498             }
   3499             case Mfp_DIVD: {
   3500                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
   3501                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
   3502                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
   3503                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 3);
   3504                break;
   3505             }
   3506             default:
   3507                goto bad;
   3508          }
   3509          goto done;
   3510       }
   3511 
   3512       case Min_FpTernary: {
   3513          switch (i->Min.FpTernary.op) {
   3514             case Mfp_MADDS: {
   3515                UInt fr_dst = fregNo(i->Min.FpTernary.dst, mode64);
   3516                UInt fr_src1 = fregNo(i->Min.FpTernary.src1, mode64);
   3517                UInt fr_src2 = fregNo(i->Min.FpTernary.src2, mode64);
   3518                UInt fr_src3 = fregNo(i->Min.FpTernary.src3, mode64);
   3519                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x20);
   3520                break;
   3521             }
   3522             case Mfp_MADDD: {
   3523                UInt fr_dst = dregNo(i->Min.FpTernary.dst);
   3524                UInt fr_src1 = dregNo(i->Min.FpTernary.src1);
   3525                UInt fr_src2 = dregNo(i->Min.FpTernary.src2);
   3526                UInt fr_src3 = dregNo(i->Min.FpTernary.src3);
   3527                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x21);
   3528                break;
   3529             }
   3530             case Mfp_MSUBS: {
   3531                UInt fr_dst = fregNo(i->Min.FpTernary.dst, mode64);
   3532                UInt fr_src1 = fregNo(i->Min.FpTernary.src1, mode64);
   3533                UInt fr_src2 = fregNo(i->Min.FpTernary.src2, mode64);
   3534                UInt fr_src3 = fregNo(i->Min.FpTernary.src3, mode64);
   3535                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x28);
   3536                break;
   3537             }
   3538             case Mfp_MSUBD: {
   3539                UInt fr_dst = dregNo(i->Min.FpTernary.dst);
   3540                UInt fr_src1 = dregNo(i->Min.FpTernary.src1);
   3541                UInt fr_src2 = dregNo(i->Min.FpTernary.src2);
   3542                UInt fr_src3 = dregNo(i->Min.FpTernary.src3);
   3543                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x29);
   3544                break;
   3545             }
   3546             default:
   3547                goto bad;
   3548          }
   3549          goto done;
   3550       }
   3551 
   3552       case Min_FpConvert: {
   3553          switch (i->Min.FpConvert.op) {
   3554             UInt fr_dst, fr_src;
   3555             case Mfp_CVTSD:
   3556                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3557                fr_src = dregNo(i->Min.FpConvert.src);
   3558                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x20);
   3559                break;
   3560             case Mfp_CVTSW:
   3561                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3562                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3563                p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x20);
   3564                break;
   3565             case Mfp_CVTWD:
   3566                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3567                fr_src = dregNo(i->Min.FpConvert.src);
   3568                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x24);
   3569                break;
   3570             case Mfp_CVTWS:
   3571                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3572                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3573                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x24);
   3574                break;
   3575             case Mfp_CVTDW:
   3576                fr_dst = dregNo(i->Min.FpConvert.dst);
   3577                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3578                p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x21);
   3579                break;
   3580             case Mfp_CVTDL:
   3581                fr_dst = dregNo(i->Min.FpConvert.dst);
   3582                fr_src = dregNo(i->Min.FpConvert.src);
   3583                p = mkFormR(p, 0x11, 0x15, 0, fr_src, fr_dst, 0x21);
   3584                break;
   3585             case Mfp_CVTDS:
   3586                fr_dst = dregNo(i->Min.FpConvert.dst);
   3587                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3588                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x21);
   3589                break;
   3590             case Mfp_CVTSL:
   3591                fr_dst = dregNo(i->Min.FpConvert.dst);
   3592                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3593                p = mkFormR(p, 0x11, 0x15, 0, fr_src, fr_dst, 0x20);
   3594                break;
   3595             case Mfp_CVTLS:
   3596                if (mode64) {
   3597                   fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3598                   fr_src = dregNo(i->Min.FpConvert.src);
   3599                } else {
   3600                   fr_dst = dregNo(i->Min.FpConvert.dst);
   3601                   fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3602                }
   3603                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x25);
   3604                break;
   3605             case Mfp_CVTLD:
   3606                fr_dst = dregNo(i->Min.FpConvert.dst);
   3607                fr_src = dregNo(i->Min.FpConvert.src);
   3608                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x25);
   3609                break;
   3610             case Mfp_TRUWS:
   3611                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3612                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3613                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0D);
   3614                break;
   3615             case Mfp_TRUWD:
   3616                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3617                fr_src = dregNo(i->Min.FpConvert.src);
   3618                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0D);
   3619                break;
   3620             case Mfp_TRULS:
   3621                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3622                fr_src = dregNo(i->Min.FpConvert.src);
   3623                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x09);
   3624                break;
   3625             case Mfp_TRULD:
   3626                fr_dst = dregNo(i->Min.FpConvert.dst);
   3627                fr_src = dregNo(i->Min.FpConvert.src);
   3628                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x09);
   3629                break;
   3630             case Mfp_CEILWS:
   3631                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3632                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3633                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0E);
   3634                break;
   3635             case Mfp_CEILWD:
   3636                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3637                fr_src = dregNo(i->Min.FpConvert.src);
   3638                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0E);
   3639                break;
   3640             case Mfp_CEILLS:
   3641                fr_dst = dregNo(i->Min.FpConvert.dst);
   3642                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3643                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0A);
   3644                break;
   3645             case Mfp_CEILLD:
   3646                fr_dst = dregNo(i->Min.FpConvert.dst);
   3647                fr_src = dregNo(i->Min.FpConvert.src);
   3648                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0A);
   3649                break;
   3650             case Mfp_ROUNDWS:
   3651                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3652                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3653                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0C);
   3654                break;
   3655             case Mfp_ROUNDWD:
   3656                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3657                fr_src = dregNo(i->Min.FpConvert.src);
   3658                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0C);
   3659                break;
   3660             case Mfp_ROUNDLD:
   3661                fr_dst = dregNo(i->Min.FpConvert.dst);
   3662                fr_src = dregNo(i->Min.FpConvert.src);
   3663                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x08);
   3664                break;
   3665             case Mfp_FLOORWS:
   3666                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3667                fr_src = fregNo(i->Min.FpConvert.src, mode64);
   3668                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0F);
   3669                break;
   3670             case Mfp_FLOORWD:
   3671                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
   3672                fr_src = dregNo(i->Min.FpConvert.src);
   3673                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0F);
   3674                break;
   3675             case Mfp_FLOORLD:
   3676                fr_dst = dregNo(i->Min.FpConvert.dst);
   3677                fr_src = dregNo(i->Min.FpConvert.src);
   3678                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0B);
   3679                break;
   3680 
   3681             default:
   3682                goto bad;
   3683          }
   3684          goto done;
   3685       }
   3686 
   3687       case Min_FpCompare: {
   3688          UInt r_dst   = iregNo(i->Min.FpCompare.dst, mode64);
   3689          UInt fr_srcL = dregNo(i->Min.FpCompare.srcL);
   3690          UInt fr_srcR = dregNo(i->Min.FpCompare.srcR);
   3691 
   3692          UInt op;
   3693          switch (i->Min.FpConvert.op) {
   3694             case Mfp_CMP_UN:
   3695                op = 1;
   3696                break;
   3697             case Mfp_CMP_EQ:
   3698                op = 2;
   3699                break;
   3700             case Mfp_CMP_LT:
   3701                op = 12;
   3702                break;
   3703             case Mfp_CMP_NGT:
   3704                op = 15;
   3705                break;
   3706             default:
   3707                goto bad;
   3708          }
   3709          /* c.cond.d fr_srcL, fr_srcR
   3710             cfc1     r_dst,   $31
   3711             srl      r_dst,   r_dst, 23
   3712             andi     r_dst,   r_dst, 1 */
   3713          p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0, op + 48);
   3714          p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0);
   3715          p = mkFormS(p, 0, r_dst, 0, r_dst, 23, 2);
   3716          p = mkFormI(p, 12, r_dst, r_dst, 1);
   3717          goto done;
   3718       }
   3719 
   3720       case Min_FpGpMove: {
   3721          switch (i->Min.FpGpMove.op) {
   3722             UInt rt, fs;
   3723             case MFpGpMove_mfc1: {
   3724                rt = iregNo(i->Min.FpGpMove.dst, mode64);
   3725                fs = fregNo(i->Min.FpGpMove.src, mode64);
   3726                p = mkFormR(p, 0x11, 0x0, rt, fs, 0x0, 0x0);
   3727                break;
   3728             }
   3729             case MFpGpMove_dmfc1: {
   3730                vassert(mode64);
   3731                rt = iregNo(i->Min.FpGpMove.dst, mode64);
   3732                fs = fregNo(i->Min.FpGpMove.src, mode64);
   3733                p = mkFormR(p, 0x11, 0x1, rt, fs, 0x0, 0x0);
   3734                break;
   3735             }
   3736             case MFpGpMove_mtc1: {
   3737                rt = iregNo(i->Min.FpGpMove.src, mode64);
   3738                fs = fregNo(i->Min.FpGpMove.dst, mode64);
   3739                p = mkFormR(p, 0x11, 0x4, rt, fs, 0x0, 0x0);
   3740                break;
   3741             }
   3742             case MFpGpMove_dmtc1: {
   3743                vassert(mode64);
   3744                rt = iregNo(i->Min.FpGpMove.src, mode64);
   3745                fs = fregNo(i->Min.FpGpMove.dst, mode64);
   3746                p = mkFormR(p, 0x11, 0x5, rt, fs, 0x0, 0x0);
   3747                break;
   3748             }
   3749             default:
   3750                goto bad;
   3751          }
   3752          goto done;
   3753       }
   3754 
   3755       case Min_MoveCond: {
   3756          switch (i->Min.MoveCond.op) {
   3757             UInt d, s, t;
   3758             case MFpMoveCond_movns: {
   3759                d = fregNo(i->Min.MoveCond.dst, mode64);
   3760                s = fregNo(i->Min.MoveCond.src, mode64);
   3761                t = iregNo(i->Min.MoveCond.cond, mode64);
   3762                p = mkFormR(p, 0x11, 0x10, t, s, d, 0x13);
   3763                break;
   3764             }
   3765             case MFpMoveCond_movnd: {
   3766                d = dregNo(i->Min.MoveCond.dst);
   3767                s = dregNo(i->Min.MoveCond.src);
   3768                t = iregNo(i->Min.MoveCond.cond, mode64);
   3769                p = mkFormR(p, 0x11, 0x11, t, s, d, 0x13);
   3770                break;
   3771             }
   3772             case MMoveCond_movn: {
   3773                d = iregNo(i->Min.MoveCond.dst, mode64);
   3774                s = iregNo(i->Min.MoveCond.src, mode64);
   3775                t = iregNo(i->Min.MoveCond.cond, mode64);
   3776                p = mkFormR(p, 0, s, t, d, 0, 0xb);
   3777                break;
   3778             }
   3779             default:
   3780                goto bad;
   3781          }
   3782          goto done;
   3783       }
   3784 
   3785       case Min_EvCheck: {
   3786          /* This requires a 32-bit dec/test in 32 mode. */
   3787          /* We generate:
   3788                lw      r9, amCounter
   3789                addiu   r9, r9, -1
   3790                sw      r9, amCounter
   3791                bgez    r9, nofail
   3792                lw      r9, amFailAddr
   3793                jalr    r9
   3794                nop
   3795               nofail:
   3796          */
   3797          UChar* p0 = p;
   3798          /* lw  r9, amCounter */
   3799          p = do_load_or_store_word32(p, True /*isLoad*/ , /*r*/ 9,
   3800                                      i->Min.EvCheck.amCounter, mode64);
   3801          /* addiu r9,r9,-1 */
   3802          p = mkFormI(p, 9, 9, 9, 0xFFFF);
   3803          /* sw r30, amCounter */
   3804          p = do_load_or_store_word32(p, False /*!isLoad*/ , /*r*/ 9,
   3805                                      i->Min.EvCheck.amCounter, mode64);
   3806          /* bgez t9, nofail */
   3807          p = mkFormI(p, 1, 9, 1, 3);
   3808          /* lw/ld r9, amFailAddr */
   3809          p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
   3810                                            i->Min.EvCheck.amFailAddr, mode64);
   3811          /* jalr $9 */
   3812          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
   3813          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
   3814          /* nofail: */
   3815 
   3816          /* Crosscheck */
   3817          vassert(evCheckSzB_MIPS() == (UChar*)p - (UChar*)p0);
   3818          goto done;
   3819       }
   3820 
   3821       case Min_ProfInc: {
   3822          /* Generate a code template to increment a memory location whose
   3823             address will be known later as an immediate value. This code
   3824             template will be patched once the memory location is known.
   3825             For now we do this with address == 0x65556555. */
   3826          if (mode64) {
   3827             /* 64-bit:
   3828                move r9, 0x6555655565556555ULL
   3829                ld r8, 0(r9)
   3830                daddiu r8, r8, 1
   3831                sd r8, 0(r9) */
   3832 
   3833             /* move r9, 0x6555655565556555ULL */
   3834             p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, 0x6555655565556555ULL,
   3835                                       True /*mode64*/);
   3836             /* ld r8, 0(r9) */
   3837             p = mkFormI(p, 55, 9, 8, 0);
   3838 
   3839             /* daddiu r8, r8, 1 */
   3840             p = mkFormI(p, 25, 8, 8, 1);
   3841 
   3842             /* sd r8, 0(r9) */
   3843             p = mkFormI(p, 63, 9, 8, 0);
   3844          } else {
   3845             /* 32-bit:
   3846                move r9, 0x65556555
   3847                lw r8, 0(r9)
   3848                addiu r8, r8, 1         # add least significant word
   3849                sw r8, 0(r9)
   3850                sltiu r1, r8, 1         # set carry-in bit
   3851                lw r8, 4(r9)
   3852                addu r8, r8, r1
   3853                sw r8, 4(r9) */
   3854 
   3855             /* move r9, 0x65556555 */
   3856             p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, 0x65556555ULL,
   3857                                       False /*!mode64*/);
   3858             /* lw r8, 0(r9) */
   3859             p = mkFormI(p, 35, 9, 8, 0);
   3860 
   3861             /* addiu r8, r8, 1         # add least significant word */
   3862             p = mkFormI(p, 9, 8, 8, 1);
   3863 
   3864             /* sw r8, 0(r9) */
   3865             p = mkFormI(p, 43, 9, 8, 0);
   3866 
   3867             /* sltiu r1, r8, 1         # set carry-in bit */
   3868             p = mkFormI(p, 11, 8, 1, 1);
   3869 
   3870             /* lw r8, 4(r9) */
   3871             p = mkFormI(p, 35, 9, 8, 4);
   3872 
   3873             /* addu r8, r8, r1 */
   3874             p = mkFormR(p, 0, 8, 1, 8, 0, 33);
   3875 
   3876             /*  sw r8, 4(r9) */
   3877             p = mkFormI(p, 43, 9, 8, 4);
   3878 
   3879          }
   3880          /* Tell the caller .. */
   3881          vassert(!(*is_profInc));
   3882          *is_profInc = True;
   3883          goto done;
   3884       }
   3885 
   3886       default:
   3887          goto bad;
   3888 
   3889    }
   3890 
   3891    bad:
   3892       vex_printf("\n=> ");
   3893       ppMIPSInstr(i, mode64);
   3894       vpanic("emit_MIPSInstr");
   3895       /* NOTREACHED */ done:
   3896       vassert(p - &buf[0] <= 128);
   3897       return p - &buf[0];
   3898 }
   3899 
   3900 /* How big is an event check?  See case for Min_EvCheck in
   3901    emit_MIPSInstr just above.  That crosschecks what this returns, so
   3902    we can tell if we're inconsistent. */
   3903 Int evCheckSzB_MIPS (void)
   3904 {
   3905   UInt kInstrSize = 4;
   3906   return 7*kInstrSize;
   3907 }
   3908 
   3909 /* NB: what goes on here has to be very closely coordinated with the
   3910    emitInstr case for XDirect, above. */
   3911 VexInvalRange chainXDirect_MIPS ( VexEndness endness_host,
   3912                                   void* place_to_chain,
   3913                                   const void* disp_cp_chain_me_EXPECTED,
   3914                                   const void* place_to_jump_to,
   3915                                   Bool  mode64 )
   3916 {
   3917    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
   3918    /* What we're expecting to see is:
   3919         move r9, disp_cp_chain_me_to_EXPECTED
   3920         jalr r9
   3921         nop
   3922       viz
   3923         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
   3924         0x120F809   # jalr r9
   3925         0x00000000  # nop
   3926    */
   3927    UChar* p = (UChar*)place_to_chain;
   3928    vassert(0 == (3 & (HWord)p));
   3929    vassert(isLoadImm_EXACTLY2or6(p, /*r*/9,
   3930                                  (UInt)(Addr)disp_cp_chain_me_EXPECTED,
   3931                                  mode64));
   3932    vassert(fetch32(p + (mode64 ? 24 : 8) + 0) == 0x120F809);
   3933    vassert(fetch32(p + (mode64 ? 24 : 8) + 4) == 0x00000000);
   3934    /* And what we want to change it to is either:
   3935           move r9, place_to_jump_to
   3936           jalr r9
   3937           nop
   3938         viz
   3939           <8 bytes generated by mkLoadImm_EXACTLY2or6>
   3940           0x120F809   # jalr r9
   3941           0x00000000  # nop
   3942 
   3943       The replacement has the same length as the original.
   3944    */
   3945 
   3946    p = mkLoadImm_EXACTLY2or6(p, /*r*/9,
   3947                              (Addr)place_to_jump_to, mode64);
   3948    p = emit32(p, 0x120F809);
   3949    p = emit32(p, 0x00000000);
   3950 
   3951    Int len = p - (UChar*)place_to_chain;
   3952    vassert(len == (mode64 ? 32 : 16)); /* stay sane */
   3953    VexInvalRange vir = {(HWord)place_to_chain, len};
   3954    return vir;
   3955 }
   3956 
   3957 /* NB: what goes on here has to be very closely coordinated with the
   3958    emitInstr case for XDirect, above. */
   3959 VexInvalRange unchainXDirect_MIPS ( VexEndness endness_host,
   3960                                     void* place_to_unchain,
   3961                                     const void* place_to_jump_to_EXPECTED,
   3962                                     const void* disp_cp_chain_me,
   3963                                     Bool  mode64 )
   3964 {
   3965    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
   3966    /* What we're expecting to see is:
   3967         move r9, place_to_jump_to_EXPECTED
   3968         jalr r9
   3969         nop
   3970       viz
   3971         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
   3972         0x120F809   # jalr r9
   3973         0x00000000  # nop
   3974    */
   3975    UChar* p = (UChar*)place_to_unchain;
   3976    vassert(0 == (3 & (HWord)p));
   3977    vassert(isLoadImm_EXACTLY2or6(p, /*r*/ 9,
   3978                                  (Addr)place_to_jump_to_EXPECTED,
   3979                                  mode64));
   3980    vassert(fetch32(p + (mode64 ? 24 : 8) + 0) == 0x120F809);
   3981    vassert(fetch32(p + (mode64 ? 24 : 8) + 4) == 0x00000000);
   3982    /* And what we want to change it to is:
   3983         move r9, disp_cp_chain_me
   3984         jalr r9
   3985         nop
   3986       viz
   3987         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
   3988         0x120F809   # jalr r9
   3989         0x00000000  # nop
   3990       The replacement has the same length as the original.
   3991    */
   3992    p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
   3993                              (Addr)disp_cp_chain_me, mode64);
   3994    p = emit32(p, 0x120F809);
   3995    p = emit32(p, 0x00000000);
   3996 
   3997    Int len = p - (UChar*)place_to_unchain;
   3998    vassert(len == (mode64 ? 32 : 16)); /* stay sane */
   3999    VexInvalRange vir = {(HWord)place_to_unchain, len};
   4000    return vir;
   4001 }
   4002 
   4003 /* Patch the counter address into a profile inc point, as previously
   4004    created by the Min_ProfInc case for emit_MIPSInstr. */
   4005 VexInvalRange patchProfInc_MIPS ( VexEndness endness_host,
   4006                                   void*  place_to_patch,
   4007                                   const ULong* location_of_counter,
   4008                                   Bool mode64 )
   4009 {
   4010    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
   4011    if (mode64) {
   4012       vassert(sizeof(ULong*) == 8);
   4013    } else {
   4014       vassert(sizeof(ULong*) == 4);
   4015    }
   4016    UChar* p = (UChar*)place_to_patch;
   4017    vassert(0 == (3 & (HWord)p));
   4018    vassert(isLoadImm_EXACTLY2or6((UChar *)p, /*r*/9,
   4019                                  mode64 ? 0x6555655565556555ULL : 0x65556555,
   4020                                  mode64));
   4021 
   4022    if (mode64) {
   4023       vassert(fetch32(p + 24 + 0) == 0xDD280000);
   4024       vassert(fetch32(p + 24 + 4) == 0x65080001);
   4025       vassert(fetch32(p + 24 + 8) == 0xFD280000);
   4026    } else {
   4027       vassert(fetch32(p + 8 + 0) == 0x8D280000);
   4028       vassert(fetch32(p + 8 + 4) == 0x25080001);
   4029       vassert(fetch32(p + 8 + 8) == 0xAD280000);
   4030       vassert(fetch32(p + 8 + 12) == 0x2d010001);
   4031       vassert(fetch32(p + 8 + 16) == 0x8d280004);
   4032       vassert(fetch32(p + 8 + 20) == 0x01014021);
   4033       vassert(fetch32(p + 8 + 24) == 0xad280004);
   4034    }
   4035 
   4036    p = mkLoadImm_EXACTLY2or6(p, /*r*/9,
   4037                              (Addr)location_of_counter, mode64);
   4038 
   4039    VexInvalRange vir = {(HWord)p, 8};
   4040    return vir;
   4041 }
   4042 
   4043 
   4044 /*---------------------------------------------------------------*/
   4045 /*--- end                                    host_mips_defs.c ---*/
   4046 /*---------------------------------------------------------------*/
   4047