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