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