1 
2 /*---------------------------------------------------------------*/
3 /*--- begin                                  host_mips_defs.c ---*/
4 /*---------------------------------------------------------------*/
5 
6 /*
7    This file is part of Valgrind, a dynamic binary instrumentation
8    framework.
9 
10    Copyright (C) 2010-2015 RT-RK
11       mips-valgrind@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", (Int)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 = %u\n", rs);
2139    UInt theInstr;
2140    vassert(opc < 0x40);
2141    vassert(rs < 0x20);
2142    vassert(rt < 0x20);
2143    vassert(rd < 0x20);
2144    vassert(sa < 0x20);
2145    func = func & 0xFFFF;
2146    theInstr = ((opc << 26) | (rs << 21) | (rt << 16) | (rd << 11) | (sa << 6) |
2147                (func));
2148 
2149    return emit32(p, theInstr);
2150 }
2151 
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.syned);
2538                   /* addiu */
2539                   p = mkFormI(p, 9, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
2540                } else {
2541                   /* addu */
2542                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 33);
2543                }
2544                break;
2545             case Malu_SUB:
2546                if (immR) {
2547                   /* addiu , but with negated imm */
2548                   vassert(srcR->Mrh.Imm.syned);
2549                   vassert(srcR->Mrh.Imm.imm16 != 0x8000);
2550                   p = mkFormI(p, 9, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16));
2551                } else {
2552                   /* subu */
2553                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 35);
2554                }
2555                break;
2556             case Malu_AND:
2557                if (immR) {
2558                   /* andi */
2559                   vassert(!srcR->Mrh.Imm.syned);
2560                   p = mkFormI(p, 12, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
2561                } else {
2562                   /* and */
2563                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 36);
2564                }
2565                break;
2566             case Malu_OR:
2567                if (immR) {
2568                   /* ori */
2569                   vassert(!srcR->Mrh.Imm.syned);
2570                   p = mkFormI(p, 13, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
2571                } else {
2572                   /* or */
2573                   if (r_srcL == 33)
2574                      /* MFHI */
2575                      p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
2576                   else if (r_srcL == 34)
2577                      /* MFLO */
2578                      p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
2579                   else if (r_dst == 33)
2580                      /* MTHI */
2581                      p = mkFormR(p, 0, r_srcL, 0, 0, 0, 17);
2582                   else if (r_dst == 34)
2583                      /* MTLO */
2584                      p = mkFormR(p, 0, r_srcL, 0, 0, 0, 19);
2585                   else
2586                      p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 37);
2587                }
2588                break;
2589             case Malu_NOR:
2590                /* nor */
2591                vassert(!immR);
2592                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 39);
2593                break;
2594             case Malu_XOR:
2595                if (immR) {
2596                   /* xori */
2597                   vassert(!srcR->Mrh.Imm.syned);
2598                   p = mkFormI(p, 14, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
2599                } else {
2600                   /* xor */
2601                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
2602                }
2603                break;
2604             case Malu_DADD:
2605                if (immR) {
2606                   vassert(srcR->Mrh.Imm.syned);
2607                   vassert(srcR->Mrh.Imm.imm16 != 0x8000);
2608                   p = mkFormI(p, 25, r_srcL, r_dst, srcR->Mrh.Imm.imm16);
2609                } else {
2610                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 45);
2611                }
2612                break;
2613             case Malu_DSUB:
2614                if (immR) {
2615                   p = mkFormI(p, 25, r_srcL, r_dst, (-srcR->Mrh.Imm.imm16));
2616                } else {
2617                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 47);
2618                }
2619                break;
2620             case Malu_SLT:
2621                if (immR) {
2622                   goto bad;
2623                } else {
2624                   p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
2625                }
2626                break;
2627 
2628             default:
2629                goto bad;
2630          }
2631          goto done;
2632       }
2633 
2634       case Min_Shft: {
2635          MIPSRH *srcR = i->Min.Shft.srcR;
2636          Bool sz32 = i->Min.Shft.sz32;
2637          Bool immR = toBool(srcR->tag == Mrh_Imm);
2638          UInt r_dst = iregNo(i->Min.Shft.dst, mode64);
2639          UInt r_srcL = iregNo(i->Min.Shft.srcL, mode64);
2640          UInt r_srcR = immR ? (-1) /*bogus */ : iregNo(srcR->Mrh.Reg.reg,
2641                                                        mode64);
2642          if (!mode64)
2643             vassert(sz32);
2644          switch (i->Min.Shft.op) {
2645             case Mshft_SLL:
2646                if (sz32) {
2647                   if (immR) {
2648                      UInt n = srcR->Mrh.Imm.imm16;
2649                      vassert(n >= 0 && n <= 32);
2650                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 0);
2651                   } else {
2652                      /* shift variable */
2653                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 4);
2654                   }
2655                } else {
2656                   if (immR) {
2657                      UInt n = srcR->Mrh.Imm.imm16;
2658                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
2659                      if (n >= 0 && n < 32) {
2660                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 56);
2661                      } else {
2662                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 60);
2663                      }
2664                   } else {
2665                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 20);
2666                   }
2667                }
2668                break;
2669 
2670             case Mshft_SRL:
2671                if (sz32) {
2672                   /* SRL, SRLV */
2673                   if (immR) {
2674                      UInt n = srcR->Mrh.Imm.imm16;
2675                      vassert(n >= 0 && n < 32);
2676                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 2);
2677                   } else {
2678                      /* shift variable */
2679                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 6);
2680                   }
2681                } else {
2682                   /* DSRL, DSRL32, DSRLV */
2683                   if (immR) {
2684                      UInt n = srcR->Mrh.Imm.imm16;
2685                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
2686                      if (n >= 0 && n < 32) {
2687                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 58);
2688                      } else {
2689                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 62);
2690                      }
2691                   } else {
2692                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 22);
2693                   }
2694                }
2695                break;
2696 
2697             case Mshft_SRA:
2698                if (sz32) {
2699                   /* SRA, SRAV */
2700                   if (immR) {
2701                      UInt n = srcR->Mrh.Imm.imm16;
2702                      vassert(n >= 0 && n < 32);
2703                      p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 3);
2704                   } else {
2705                      /* shift variable */
2706                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 7);
2707                   }
2708                } else {
2709                   /* DSRA, DSRA32, DSRAV */
2710                   if (immR) {
2711                      UInt n = srcR->Mrh.Imm.imm16;
2712                      vassert((n >= 0 && n < 32) || (n > 31 && n < 64));
2713                      if (n >= 0 && n < 32) {
2714                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n, 59);
2715                      } else {
2716                         p = mkFormS(p, 0, r_dst, 0, r_srcL, n - 32, 63);
2717                      }
2718                   } else {
2719                      p = mkFormS(p, 0, r_dst, r_srcR, r_srcL, 0, 23);
2720                   }
2721                }
2722                break;
2723 
2724             default:
2725                goto bad;
2726          }
2727 
2728          goto done;
2729       }
2730 
2731       case Min_Unary: {
2732          UInt r_dst = iregNo(i->Min.Unary.dst, mode64);
2733          UInt r_src = iregNo(i->Min.Unary.src, mode64);
2734 
2735          switch (i->Min.Unary.op) {
2736             /* Mun_CLO, Mun_CLZ, Mun_NOP, Mun_DCLO, Mun_DCLZ */
2737             case Mun_CLO:  /* clo */
2738                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 33);
2739                break;
2740             case Mun_CLZ:  /* clz */
2741                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 32);
2742                break;
2743             case Mun_NOP:  /* nop (sll r0,r0,0) */
2744                p = mkFormR(p, 0, 0, 0, 0, 0, 0);
2745                break;
2746             case Mun_DCLO:  /* clo */
2747                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 37);
2748                break;
2749             case Mun_DCLZ:  /* clz */
2750                p = mkFormR(p, 28, r_src, r_dst , r_dst, 0, 36);
2751                break;
2752          }
2753          goto done;
2754       }
2755 
2756       case Min_Cmp: {
2757          UInt r_srcL = iregNo(i->Min.Cmp.srcL, mode64);
2758          UInt r_srcR = iregNo(i->Min.Cmp.srcR, mode64);
2759          UInt r_dst = iregNo(i->Min.Cmp.dst, mode64);
2760 
2761          switch (i->Min.Cmp.cond) {
2762             case MIPScc_EQ:
2763                /* xor r_dst, r_srcL, r_srcR
2764                   sltiu r_dst, r_dst, 1 */
2765                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
2766                p = mkFormI(p, 11, r_dst, r_dst, 1);
2767                break;
2768             case MIPScc_NE:
2769                /* xor r_dst, r_srcL, r_srcR
2770                   sltu r_dst, zero, r_dst */
2771                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 38);
2772                p = mkFormR(p, 0, 0, r_dst, r_dst, 0, 43);
2773                break;
2774             case MIPScc_LT:
2775                /* slt r_dst, r_srcL, r_srcR */
2776                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 42);
2777                break;
2778             case MIPScc_LO:
2779                /* sltu r_dst, r_srcL, r_srcR */
2780                p = mkFormR(p, 0, r_srcL, r_srcR, r_dst, 0, 43);
2781                break;
2782             case MIPScc_LE:
2783                /* slt r_dst, r_srcR, r_srcL
2784                   xori r_dst, r_dst, 1 */
2785                p = mkFormR(p, 0, r_srcR, r_srcL, r_dst, 0, 42);
2786                p = mkFormI(p, 14, r_dst, r_dst, 1);
2787                break;
2788             case MIPScc_LS:
2789                /* sltu r_dst, rsrcR, r_srcL
2790                   xori r_dsr, r_dst, 1 */
2791                p = mkFormR(p, 0, r_srcR, r_srcL, r_dst, 0, 43);
2792                p = mkFormI(p, 14, r_dst, r_dst, 1);
2793                break;
2794             default:
2795                goto bad;
2796          }
2797          goto done;
2798       }
2799 
2800       case Min_Mul: {
2801          Bool syned = i->Min.Mul.syned;
2802          Bool widening = i->Min.Mul.widening;
2803          Bool sz32 = i->Min.Mul.sz32;
2804          UInt r_srcL = iregNo(i->Min.Mul.srcL, mode64);
2805          UInt r_srcR = iregNo(i->Min.Mul.srcR, mode64);
2806          UInt r_dst = iregNo(i->Min.Mul.dst, mode64);
2807          if (widening) {
2808             if (sz32) {
2809                if (syned)
2810                   /* mult */
2811                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 24);
2812                else
2813                   /* multu */
2814                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 25);
2815             } else {
2816                if (syned)  /* DMULT  r_dst,r_srcL,r_srcR */
2817                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 28);
2818                else  /* DMULTU r_dst,r_srcL,r_srcR */
2819                   p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 29);
2820             }
2821          } else {
2822             if (sz32)
2823                /* mul */
2824                p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
2825             else if (mode64 && !sz32)
2826                p = mkFormR(p, 28, r_srcL, r_srcR, r_dst, 0, 2);
2827             else
2828                goto bad;
2829          }
2830          goto done;
2831       }
2832 
2833       case Min_Macc: {
2834          Bool syned = i->Min.Macc.syned;
2835          UInt r_srcL = iregNo(i->Min.Macc.srcL, mode64);
2836          UInt r_srcR = iregNo(i->Min.Macc.srcR, mode64);
2837 
2838          if (syned) {
2839             switch (i->Min.Macc.op) {
2840                case Macc_ADD:
2841                   /* madd */
2842                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0, 0);
2843                   break;
2844                case Macc_SUB:
2845                   /* msub */
2846                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
2847                          4);
2848                   break;
2849                default:
2850                   goto bad;
2851             }
2852          } else {
2853             switch (i->Min.Macc.op) {
2854                case Macc_ADD:
2855                   /* maddu */
2856                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
2857                          1);
2858                   break;
2859                case Macc_SUB:
2860                   /* msubu */
2861                   p = mkFormR(p, 28, r_srcL, r_srcR, 0, 0,
2862                          5);
2863                   break;
2864                default:
2865                   goto bad;
2866             }
2867          }
2868 
2869          goto done;
2870       }
2871 
2872       case Min_Div: {
2873          Bool syned = i->Min.Div.syned;
2874          Bool sz32 = i->Min.Div.sz32;
2875          UInt r_srcL = iregNo(i->Min.Div.srcL, mode64);
2876          UInt r_srcR = iregNo(i->Min.Div.srcR, mode64);
2877          if (sz32) {
2878             if (syned) {
2879                /* div */
2880                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 26);
2881             } else
2882                /* divu */
2883                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 27);
2884             goto done;
2885          } else {
2886             if (syned) {
2887                /* ddiv */
2888                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 30);
2889             } else
2890                /* ddivu */
2891                p = mkFormR(p, 0, r_srcL, r_srcR, 0, 0, 31);
2892             goto done;
2893          }
2894       }
2895 
2896       case Min_Mthi: {
2897          UInt r_src = iregNo(i->Min.MtHL.src, mode64);
2898          p = mkFormR(p, 0, r_src, 0, 0, 0, 17);
2899          goto done;
2900       }
2901 
2902       case Min_Mtlo: {
2903          UInt r_src = iregNo(i->Min.MtHL.src, mode64);
2904          p = mkFormR(p, 0, r_src, 0, 0, 0, 19);
2905          goto done;
2906       }
2907 
2908       case Min_Mfhi: {
2909          UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
2910          p = mkFormR(p, 0, 0, 0, r_dst, 0, 16);
2911          goto done;
2912       }
2913 
2914       case Min_Mflo: {
2915          UInt r_dst = iregNo(i->Min.MfHL.dst, mode64);
2916          p = mkFormR(p, 0, 0, 0, r_dst, 0, 18);
2917          goto done;
2918       }
2919 
2920       case Min_MtFCSR: {
2921          UInt r_src = iregNo(i->Min.MtFCSR.src, mode64);
2922          /* ctc1 */
2923          p = mkFormR(p, 17, 6, r_src, 31, 0, 0);
2924          goto done;
2925       }
2926 
2927       case Min_MfFCSR: {
2928          UInt r_dst = iregNo(i->Min.MfFCSR.dst, mode64);
2929          /* cfc1 */
2930          p = mkFormR(p, 17, 2, r_dst, 31, 0, 0);
2931          goto done;
2932       }
2933 
2934       case Min_Call: {
2935          if (i->Min.Call.cond != MIPScc_AL
2936              && i->Min.Call.rloc.pri != RLPri_None) {
2937             /* The call might not happen (it isn't unconditional) and
2938                it returns a result.  In this case we will need to
2939                generate a control flow diamond to put 0x555..555 in
2940                the return register(s) in the case where the call
2941                doesn't happen.  If this ever becomes necessary, maybe
2942                copy code from the ARM equivalent.  Until that day,
2943                just give up. */
2944             goto bad;
2945          }
2946          MIPSCondCode cond = i->Min.Call.cond;
2947          UInt r_dst = 25;  /* using %r25 as address temporary -
2948                               see getRegUsage_MIPSInstr */
2949 
2950          /* jump over the following insns if condition does not hold */
2951          if (cond != MIPScc_AL) {
2952             /* jmp fwds if !condition */
2953             /* don't know how many bytes to jump over yet...
2954                make space for a jump instruction + nop!!! and fill in later. */
2955             ptmp = p;  /* fill in this bit later */
2956             p += 8;    /* p += 8 */
2957          }
2958 
2959          if (!mode64) {
2960             /* addiu $29, $29, -16 */
2961             p = mkFormI(p, 9, 29, 29, 0xFFF0);
2962          }
2963 
2964          /* load target to r_dst; p += 4|8 */
2965          p = mkLoadImm(p, r_dst, i->Min.Call.target, mode64);
2966 
2967          /* jalr r_dst */
2968          p = mkFormR(p, 0, r_dst, 0, 31, 0, 9);  /* p += 4 */
2969          p = mkFormR(p, 0, 0, 0, 0, 0, 0);       /* p += 4 */
2970 
2971          if (!mode64) {
2972             /* addiu $29, $29, 16 */
2973             p = mkFormI(p, 9, 29, 29, 0x0010);
2974          }
2975 
2976          /* Fix up the conditional jump, if there was one. */
2977          if (cond != MIPScc_AL) {
2978             UInt r_src = iregNo(i->Min.Call.src, mode64);
2979             Int delta = p - ptmp;
2980 
2981             vassert(delta >= 20 && delta <= 32);
2982             /* blez r_src, delta/4-1
2983                nop */
2984             ptmp = mkFormI(ptmp, 6, r_src, 0, delta / 4 - 1);
2985             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
2986          }
2987          goto done;
2988       }
2989 
2990       case Min_XDirect: {
2991          /* NB: what goes on here has to be very closely coordinated
2992             with the chainXDirect_MIPS and unchainXDirect_MIPS below. */
2993          /* We're generating chain-me requests here, so we need to be
2994             sure this is actually allowed -- no-redir translations
2995             can't use chain-me's.  Hence: */
2996          vassert(disp_cp_chain_me_to_slowEP != NULL);
2997          vassert(disp_cp_chain_me_to_fastEP != NULL);
2998 
2999          /* Use ptmp for backpatching conditional jumps. */
3000          ptmp = NULL;
3001 
3002          /* First off, if this is conditional, create a conditional
3003             jump over the rest of it.  Or at least, leave a space for
3004             it that we will shortly fill in. */
3005          if (i->Min.XDirect.cond != MIPScc_AL) {
3006             vassert(i->Min.XDirect.cond != MIPScc_NV);
3007             ptmp = p;
3008             p += 12;
3009          }
3010 
3011          /* Update the guest PC. */
3012          /* move r9, dstGA */
3013          /* sw/sd r9, amPC */
3014          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, (ULong)i->Min.XDirect.dstGA,
3015                                    mode64);
3016          p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 9,
3017                                            i->Min.XDirect.amPC, mode64);
3018 
3019          /* --- FIRST PATCHABLE BYTE follows --- */
3020          /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
3021             calling to) backs up the return address, so as to find the
3022             address of the first patchable byte.  So: don't change the
3023             number of instructions (3) below. */
3024          /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */
3025          /* jr  r9  */
3026          const void* disp_cp_chain_me
3027                   = i->Min.XDirect.toFastEP ? disp_cp_chain_me_to_fastEP
3028                                               : disp_cp_chain_me_to_slowEP;
3029          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
3030                                    (Addr)disp_cp_chain_me, mode64);
3031          /* jalr $9 */
3032          /* nop */
3033          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
3034          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
3035          /* --- END of PATCHABLE BYTES --- */
3036 
3037          /* Fix up the conditional jump, if there was one. */
3038          if (i->Min.XDirect.cond != MIPScc_AL) {
3039             Int delta = p - ptmp;
3040             delta = delta / 4 - 3;
3041             vassert(delta > 0 && delta < 40);
3042 
3043             /* lw $9, COND_OFFSET(GuestSP)
3044                beq $9, $0, 2
3045                nop */
3046             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
3047             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
3048             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
3049          }
3050          goto done;
3051       }
3052 
3053       case Min_XIndir: {
3054          /* We're generating transfers that could lead indirectly to a
3055             chain-me, so we need to be sure this is actually allowed --
3056             no-redir translations are not allowed to reach normal
3057             translations without going through the scheduler.  That means
3058             no XDirects or XIndirs out from no-redir translations.
3059             Hence: */
3060          vassert(disp_cp_xindir != NULL);
3061 
3062          /* Use ptmp for backpatching conditional jumps. */
3063          ptmp = NULL;
3064 
3065          /* First off, if this is conditional, create a conditional
3066             jump over the rest of it. */
3067          if (i->Min.XIndir.cond != MIPScc_AL) {
3068             vassert(i->Min.XIndir.cond != MIPScc_NV);
3069             ptmp = p;
3070             p += 12;
3071          }
3072 
3073          /* Update the guest PC. */
3074          /* sw/sd r-dstGA, amPC */
3075          p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
3076                                            iregNo(i->Min.XIndir.dstGA, mode64),
3077                                            i->Min.XIndir.amPC, mode64);
3078 
3079          /* move r9, VG_(disp_cp_xindir) */
3080          /* jalr   r9 */
3081          /* nop */
3082          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
3083                                    (Addr)disp_cp_xindir, mode64);
3084          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
3085          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
3086 
3087          /* Fix up the conditional jump, if there was one. */
3088          if (i->Min.XIndir.cond != MIPScc_AL) {
3089             Int delta = p - ptmp;
3090             delta = delta / 4 - 3;
3091             vassert(delta > 0 && delta < 40);
3092 
3093             /* lw $9, COND_OFFSET($GuestSP)
3094                beq $9, $0, 2
3095                nop */
3096             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
3097             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
3098             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
3099          }
3100          goto done;
3101       }
3102 
3103       case Min_XAssisted: {
3104          /* First off, if this is conditional, create a conditional jump
3105             over the rest of it.  Or at least, leave a space for it that
3106             we will shortly fill in. */
3107          ptmp = NULL;
3108          if (i->Min.XAssisted.cond != MIPScc_AL) {
3109             vassert(i->Min.XAssisted.cond != MIPScc_NV);
3110             ptmp = p;
3111             p += 12;
3112          }
3113 
3114          /* Update the guest PC. */
3115          /* sw/sd r-dstGA, amPC */
3116          p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
3117                                            iregNo(i->Min.XIndir.dstGA, mode64),
3118                                            i->Min.XIndir.amPC, mode64);
3119 
3120          /* imm32/64 r31, $magic_number */
3121          UInt trcval = 0;
3122          switch (i->Min.XAssisted.jk) {
3123             case Ijk_ClientReq:     trcval = VEX_TRC_JMP_CLIENTREQ;     break;
3124             case Ijk_Sys_syscall:   trcval = VEX_TRC_JMP_SYS_SYSCALL;   break;
3125             /* case Ijk_Sys_int128: trcval = VEX_TRC_JMP_SYS_INT128;   break; */
3126             case Ijk_Yield:         trcval = VEX_TRC_JMP_YIELD;       break;
3127             case Ijk_EmWarn:        trcval = VEX_TRC_JMP_EMWARN;        break;
3128             case Ijk_EmFail:        trcval = VEX_TRC_JMP_EMFAIL;        break;
3129             /* case Ijk_MapFail:   trcval = VEX_TRC_JMP_MAPFAIL;       break; */
3130             case Ijk_NoDecode:      trcval = VEX_TRC_JMP_NODECODE;      break;
3131             case Ijk_InvalICache:   trcval = VEX_TRC_JMP_INVALICACHE;   break;
3132             case Ijk_NoRedir:       trcval = VEX_TRC_JMP_NOREDIR;       break;
3133             case Ijk_SigILL:        trcval = VEX_TRC_JMP_SIGILL;        break;
3134             case Ijk_SigTRAP:       trcval = VEX_TRC_JMP_SIGTRAP;       break;
3135             /* case Ijk_SigSEGV:   trcval = VEX_TRC_JMP_SIGSEGV;       break; */
3136             case Ijk_SigBUS:        trcval = VEX_TRC_JMP_SIGBUS;        break;
3137             case Ijk_SigFPE_IntDiv: trcval = VEX_TRC_JMP_SIGFPE_INTDIV; break;
3138             case Ijk_SigFPE_IntOvf: trcval = VEX_TRC_JMP_SIGFPE_INTOVF; break;
3139             case Ijk_Boring:        trcval = VEX_TRC_JMP_BORING;        break;
3140             /* We don't expect to see the following being assisted.
3141                case Ijk_Ret:
3142                case Ijk_Call:
3143                fallthrough */
3144             default:
3145                ppIRJumpKind(i->Min.XAssisted.jk);
3146                vpanic("emit_MIPSInstr.Min_XAssisted: unexpected jump kind");
3147          }
3148          vassert(trcval != 0);
3149          p = mkLoadImm_EXACTLY2or6(p, /*r*/ GuestSP, trcval, mode64);
3150 
3151          /* move r9, VG_(disp_cp_xassisted) */
3152          p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
3153                                    (ULong)(Addr)disp_cp_xassisted, mode64);
3154          /* jalr $9
3155              nop */
3156          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
3157          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
3158 
3159          /* Fix up the conditional jump, if there was one. */
3160          if (i->Min.XAssisted.cond != MIPScc_AL) {
3161             Int delta = p - ptmp;
3162             delta = delta / 4 - 3;
3163             vassert(delta > 0 && delta < 40);
3164 
3165             /* lw $9, COND_OFFSET($GuestSP)
3166                beq $9, $0, 2
3167                nop */
3168             ptmp = mkFormI(ptmp, 35, GuestSP, 9, COND_OFFSET(mode64));
3169             ptmp = mkFormI(ptmp, 4, 0, 9, (delta));
3170             mkFormR(ptmp, 0, 0, 0, 0, 0, 0);
3171          }
3172          goto done;
3173       }
3174 
3175       case Min_Load: {
3176          MIPSAMode *am_addr = i->Min.Load.src;
3177          if (am_addr->tag == Mam_IR) {
3178             UInt r_dst = iregNo(i->Min.Load.dst, mode64);
3179             UInt opc, sz = i->Min.Load.sz;
3180             if (mode64 && (sz == 4 || sz == 8)) {
3181                /* should be guaranteed to us by iselWordExpr_AMode */
3182                vassert(0 == (am_addr->Mam.IR.index & 3));
3183             }
3184             switch (sz) {
3185                case 1:
3186                   opc = 32;
3187                   break;
3188                case 2:
3189                   opc = 33;
3190                   break;
3191                case 4:
3192                   opc = 35;
3193                   break;
3194                case 8:
3195                   opc = 55;
3196                   vassert(mode64);
3197                   break;
3198                default:
3199                   goto bad;
3200             }
3201 
3202             p = doAMode_IR(p, opc, r_dst, am_addr, mode64);
3203             goto done;
3204          } else if (am_addr->tag == Mam_RR) {
3205             UInt r_dst = iregNo(i->Min.Load.dst, mode64);
3206             UInt opc, sz = i->Min.Load.sz;
3207 
3208             switch (sz) {
3209                case 1:
3210                   opc = 32;
3211                   break;
3212                case 2:
3213                   opc = 33;
3214                   break;
3215                case 4:
3216                   opc = 35;
3217                   break;
3218                case 8:
3219                   opc = 55;
3220                   vassert(mode64);
3221                   break;
3222                default:
3223                   goto bad;
3224             }
3225 
3226             p = doAMode_RR(p, opc, r_dst, am_addr, mode64);
3227             goto done;
3228          }
3229          break;
3230       }
3231 
3232       case Min_Store: {
3233          MIPSAMode *am_addr = i->Min.Store.dst;
3234          if (am_addr->tag == Mam_IR) {
3235             UInt r_src = iregNo(i->Min.Store.src, mode64);
3236             UInt opc, sz = i->Min.Store.sz;
3237             if (mode64 && (sz == 4 || sz == 8)) {
3238                /* should be guaranteed to us by iselWordExpr_AMode */
3239                vassert(0 == (am_addr->Mam.IR.index & 3));
3240             }
3241             switch (sz) {
3242                case 1:
3243                   opc = 40;
3244                   break;
3245                case 2:
3246                   opc = 41;
3247                   break;
3248                case 4:
3249                   opc = 43;
3250                   break;
3251                case 8:
3252                   vassert(mode64);
3253                   opc = 63;
3254                   break;
3255                default:
3256                   goto bad;
3257             }
3258 
3259             p = doAMode_IR(p, opc, r_src, am_addr, mode64);
3260             goto done;
3261          } else if (am_addr->tag == Mam_RR) {
3262             UInt r_src = iregNo(i->Min.Store.src, mode64);
3263             UInt opc, sz = i->Min.Store.sz;
3264 
3265             switch (sz) {
3266                case 1:
3267                   opc = 40;
3268                   break;
3269                case 2:
3270                   opc = 41;
3271                   break;
3272                case 4:
3273                   opc = 43;
3274                   break;
3275                case 8:
3276                   vassert(mode64);
3277                   opc = 63;
3278                   break;
3279                default:
3280                   goto bad;
3281             }
3282 
3283             p = doAMode_RR(p, opc, r_src, am_addr, mode64);
3284             goto done;
3285          }
3286          break;
3287       }
3288       case Min_LoadL: {
3289          MIPSAMode *am_addr = i->Min.LoadL.src;
3290          UInt r_src = iregNo(am_addr->Mam.IR.base, mode64);
3291          UInt idx = am_addr->Mam.IR.index;
3292          UInt r_dst = iregNo(i->Min.LoadL.dst, mode64);
3293 
3294          if (i->Min.LoadL.sz == 4)
3295             p = mkFormI(p, 0x30, r_src, r_dst, idx);
3296          else
3297             p = mkFormI(p, 0x34, r_src, r_dst, idx);
3298          goto done;
3299       }
3300       case Min_StoreC: {
3301          MIPSAMode *am_addr = i->Min.StoreC.dst;
3302          UInt r_src = iregNo(i->Min.StoreC.src, mode64);
3303          UInt idx = am_addr->Mam.IR.index;
3304          UInt r_dst = iregNo(am_addr->Mam.IR.base, mode64);
3305 
3306          if (i->Min.StoreC.sz == 4)
3307             p = mkFormI(p, 0x38, r_dst, r_src, idx);
3308          else
3309             p = mkFormI(p, 0x3C, r_dst, r_src, idx);
3310          goto done;
3311       }
3312       case Min_Cas: {
3313          if (i->Min.Cas.sz != 8 && i->Min.Cas.sz != 4)
3314             goto bad;
3315          UInt old  = iregNo(i->Min.Cas.old, mode64);
3316          UInt addr = iregNo(i->Min.Cas.addr, mode64);
3317          UInt expd = iregNo(i->Min.Cas.expd, mode64);
3318          UInt data = iregNo(i->Min.Cas.data, mode64);
3319          Bool sz8  = toBool(i->Min.Cas.sz == 8);
3320 
3321          /*
3322           * ll(d)    old,  0(addr)
3323           * bne      old,  expd, end
3324           * nop
3325           * (d)addiu old,  old,  1
3326           * sc(d)    data, 0(addr)
3327           * movn     old,  expd, data
3328           * end:
3329           */
3330          // ll(d) old, 0(addr)
3331          p = mkFormI(p, sz8 ? 0x34 : 0x30, addr, old, 0);
3332          // bne  old,  expd, end
3333          p = mkFormI(p, 5, old, expd, 4);
3334          // nop
3335          p = mkFormR(p, 0, 0, 0, 0, 0, 0);
3336          // (d)addiu old,  old,  1
3337          p = mkFormI(p, sz8 ? 25 : 9, old, old, 1);
3338          // sc(d)  data, 0(addr)
3339          p = mkFormI(p, sz8 ? 0x3C : 0x38, addr, data, 0);
3340          // movn old,  expd, data
3341          p = mkFormR(p, 0, expd, data, old, 0, 0xb);
3342 
3343          goto done;
3344       }
3345       case Min_RdWrLR: {
3346          UInt reg = iregNo(i->Min.RdWrLR.gpr, mode64);
3347          Bool wrLR = i->Min.RdWrLR.wrLR;
3348          if (wrLR)
3349             p = mkMoveReg(p, 31, reg);
3350          else
3351             p = mkMoveReg(p, reg, 31);
3352          goto done;
3353       }
3354 
3355       /* Floating point */
3356       case Min_FpLdSt: {
3357          MIPSAMode *am_addr = i->Min.FpLdSt.addr;
3358          UChar sz = i->Min.FpLdSt.sz;
3359          vassert(sz == 4 || sz == 8);
3360          if (sz == 4) {
3361             UInt f_reg = fregNo(i->Min.FpLdSt.reg, mode64);
3362             if (i->Min.FpLdSt.isLoad) {
3363                if (am_addr->tag == Mam_IR)
3364                   p = doAMode_IR(p, 0x31, f_reg, am_addr, mode64);
3365                else if (am_addr->tag == Mam_RR)
3366                   p = doAMode_RR(p, 0x31, f_reg, am_addr, mode64);
3367             } else {
3368                if (am_addr->tag == Mam_IR)
3369                   p = doAMode_IR(p, 0x39, f_reg, am_addr, mode64);
3370                else if (am_addr->tag == Mam_RR)
3371                   p = doAMode_RR(p, 0x39, f_reg, am_addr, mode64);
3372             }
3373          } else if (sz == 8) {
3374             UInt f_reg = dregNo(i->Min.FpLdSt.reg);
3375             if (i->Min.FpLdSt.isLoad) {
3376                if (am_addr->tag == Mam_IR) {
3377                   p = doAMode_IR(p, 0x35, f_reg, am_addr, mode64);
3378                } else if (am_addr->tag == Mam_RR) {
3379                   p = doAMode_RR(p, 0x35, f_reg, am_addr, mode64);
3380                }
3381             } else {
3382                if (am_addr->tag == Mam_IR) {
3383                   p = doAMode_IR(p, 0x3d, f_reg, am_addr, mode64);
3384                } else if (am_addr->tag == Mam_RR) {
3385                   p = doAMode_RR(p, 0x3d, f_reg, am_addr, mode64);
3386                }
3387             }
3388          }
3389          goto done;
3390       }
3391 
3392       case Min_FpUnary: {
3393          switch (i->Min.FpUnary.op) {
3394             case Mfp_MOVS: {  /* FP move */
3395                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
3396                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
3397                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x6);
3398                break;
3399             }
3400             case Mfp_MOVD: {  /* FP move */
3401                 UInt fr_dst = dregNo(i->Min.FpUnary.dst);
3402                 UInt fr_src = dregNo(i->Min.FpUnary.src);
3403                 p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x6);
3404                 break;
3405              }
3406             case Mfp_ABSS: {  /* ABS.S */
3407                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
3408                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
3409                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x5);
3410                break;
3411             }
3412             case Mfp_ABSD: {  /* ABS.D */
3413                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
3414                UInt fr_src = dregNo(i->Min.FpUnary.src);
3415                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x5);
3416                break;
3417             }
3418             case Mfp_NEGS: {  /* NEG.S */
3419                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
3420                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
3421                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x7);
3422                break;
3423             }
3424             case Mfp_NEGD: {  /* NEG.D */
3425                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
3426                UInt fr_src = dregNo(i->Min.FpUnary.src);
3427                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x7);
3428                break;
3429             }
3430             case Mfp_SQRTS: {  /* SQRT.S */
3431                UInt fr_dst = fregNo(i->Min.FpUnary.dst, mode64);
3432                UInt fr_src = fregNo(i->Min.FpUnary.src, mode64);
3433                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x04);
3434                break;
3435             }
3436             case Mfp_SQRTD: {  /* SQRT.D */
3437                UInt fr_dst = dregNo(i->Min.FpUnary.dst);
3438                UInt fr_src = dregNo(i->Min.FpUnary.src);
3439                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x04);
3440                break;
3441             }
3442             default:
3443                goto bad;
3444          }
3445          goto done;
3446       }
3447 
3448       case Min_FpBinary: {
3449          switch (i->Min.FpBinary.op) {
3450             case Mfp_ADDS: {
3451                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
3452                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
3453                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
3454                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 0);
3455                break;
3456             }
3457             case Mfp_SUBS: {
3458                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
3459                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
3460                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
3461                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 1);
3462                break;
3463             }
3464             case Mfp_MULS: {
3465                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
3466                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
3467                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
3468                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 2);
3469                break;
3470             }
3471             case Mfp_DIVS: {
3472                UInt fr_dst = fregNo(i->Min.FpBinary.dst, mode64);
3473                UInt fr_srcL = fregNo(i->Min.FpBinary.srcL, mode64);
3474                UInt fr_srcR = fregNo(i->Min.FpBinary.srcR, mode64);
3475                p = mkFormR(p, 0x11, 0x10, fr_srcR, fr_srcL, fr_dst, 3);
3476                break;
3477             }
3478             case Mfp_ADDD: {
3479                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
3480                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
3481                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
3482                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 0);
3483                break;
3484             }
3485             case Mfp_SUBD: {
3486                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
3487                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
3488                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
3489                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 1);
3490                break;
3491             }
3492             case Mfp_MULD: {
3493                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
3494                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
3495                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
3496                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 2);
3497                break;
3498             }
3499             case Mfp_DIVD: {
3500                UInt fr_dst = dregNo(i->Min.FpBinary.dst);
3501                UInt fr_srcL = dregNo(i->Min.FpBinary.srcL);
3502                UInt fr_srcR = dregNo(i->Min.FpBinary.srcR);
3503                p = mkFormR(p, 0x11, 0x11, fr_srcR, fr_srcL, fr_dst, 3);
3504                break;
3505             }
3506             default:
3507                goto bad;
3508          }
3509          goto done;
3510       }
3511 
3512       case Min_FpTernary: {
3513          switch (i->Min.FpTernary.op) {
3514             case Mfp_MADDS: {
3515                UInt fr_dst = fregNo(i->Min.FpTernary.dst, mode64);
3516                UInt fr_src1 = fregNo(i->Min.FpTernary.src1, mode64);
3517                UInt fr_src2 = fregNo(i->Min.FpTernary.src2, mode64);
3518                UInt fr_src3 = fregNo(i->Min.FpTernary.src3, mode64);
3519                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x20);
3520                break;
3521             }
3522             case Mfp_MADDD: {
3523                UInt fr_dst = dregNo(i->Min.FpTernary.dst);
3524                UInt fr_src1 = dregNo(i->Min.FpTernary.src1);
3525                UInt fr_src2 = dregNo(i->Min.FpTernary.src2);
3526                UInt fr_src3 = dregNo(i->Min.FpTernary.src3);
3527                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x21);
3528                break;
3529             }
3530             case Mfp_MSUBS: {
3531                UInt fr_dst = fregNo(i->Min.FpTernary.dst, mode64);
3532                UInt fr_src1 = fregNo(i->Min.FpTernary.src1, mode64);
3533                UInt fr_src2 = fregNo(i->Min.FpTernary.src2, mode64);
3534                UInt fr_src3 = fregNo(i->Min.FpTernary.src3, mode64);
3535                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x28);
3536                break;
3537             }
3538             case Mfp_MSUBD: {
3539                UInt fr_dst = dregNo(i->Min.FpTernary.dst);
3540                UInt fr_src1 = dregNo(i->Min.FpTernary.src1);
3541                UInt fr_src2 = dregNo(i->Min.FpTernary.src2);
3542                UInt fr_src3 = dregNo(i->Min.FpTernary.src3);
3543                p = mkFormR(p, 0x13, fr_src1, fr_src2, fr_src3, fr_dst, 0x29);
3544                break;
3545             }
3546             default:
3547                goto bad;
3548          }
3549          goto done;
3550       }
3551 
3552       case Min_FpConvert: {
3553          switch (i->Min.FpConvert.op) {
3554             UInt fr_dst, fr_src;
3555             case Mfp_CVTSD:
3556                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3557                fr_src = dregNo(i->Min.FpConvert.src);
3558                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x20);
3559                break;
3560             case Mfp_CVTSW:
3561                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3562                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3563                p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x20);
3564                break;
3565             case Mfp_CVTWD:
3566                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3567                fr_src = dregNo(i->Min.FpConvert.src);
3568                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x24);
3569                break;
3570             case Mfp_CVTWS:
3571                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3572                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3573                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x24);
3574                break;
3575             case Mfp_CVTDW:
3576                fr_dst = dregNo(i->Min.FpConvert.dst);
3577                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3578                p = mkFormR(p, 0x11, 0x14, 0, fr_src, fr_dst, 0x21);
3579                break;
3580             case Mfp_CVTDL:
3581                fr_dst = dregNo(i->Min.FpConvert.dst);
3582                fr_src = dregNo(i->Min.FpConvert.src);
3583                p = mkFormR(p, 0x11, 0x15, 0, fr_src, fr_dst, 0x21);
3584                break;
3585             case Mfp_CVTDS:
3586                fr_dst = dregNo(i->Min.FpConvert.dst);
3587                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3588                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x21);
3589                break;
3590             case Mfp_CVTSL:
3591                fr_dst = dregNo(i->Min.FpConvert.dst);
3592                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3593                p = mkFormR(p, 0x11, 0x15, 0, fr_src, fr_dst, 0x20);
3594                break;
3595             case Mfp_CVTLS:
3596                if (mode64) {
3597                   fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3598                   fr_src = dregNo(i->Min.FpConvert.src);
3599                } else {
3600                   fr_dst = dregNo(i->Min.FpConvert.dst);
3601                   fr_src = fregNo(i->Min.FpConvert.src, mode64);
3602                }
3603                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x25);
3604                break;
3605             case Mfp_CVTLD:
3606                fr_dst = dregNo(i->Min.FpConvert.dst);
3607                fr_src = dregNo(i->Min.FpConvert.src);
3608                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x25);
3609                break;
3610             case Mfp_TRUWS:
3611                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3612                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3613                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0D);
3614                break;
3615             case Mfp_TRUWD:
3616                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3617                fr_src = dregNo(i->Min.FpConvert.src);
3618                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0D);
3619                break;
3620             case Mfp_TRULS:
3621                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3622                fr_src = dregNo(i->Min.FpConvert.src);
3623                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x09);
3624                break;
3625             case Mfp_TRULD:
3626                fr_dst = dregNo(i->Min.FpConvert.dst);
3627                fr_src = dregNo(i->Min.FpConvert.src);
3628                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x09);
3629                break;
3630             case Mfp_CEILWS:
3631                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3632                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3633                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0E);
3634                break;
3635             case Mfp_CEILWD:
3636                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3637                fr_src = dregNo(i->Min.FpConvert.src);
3638                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0E);
3639                break;
3640             case Mfp_CEILLS:
3641                fr_dst = dregNo(i->Min.FpConvert.dst);
3642                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3643                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0A);
3644                break;
3645             case Mfp_CEILLD:
3646                fr_dst = dregNo(i->Min.FpConvert.dst);
3647                fr_src = dregNo(i->Min.FpConvert.src);
3648                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0A);
3649                break;
3650             case Mfp_ROUNDWS:
3651                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3652                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3653                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0C);
3654                break;
3655             case Mfp_ROUNDWD:
3656                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3657                fr_src = dregNo(i->Min.FpConvert.src);
3658                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0C);
3659                break;
3660             case Mfp_ROUNDLD:
3661                fr_dst = dregNo(i->Min.FpConvert.dst);
3662                fr_src = dregNo(i->Min.FpConvert.src);
3663                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x08);
3664                break;
3665             case Mfp_FLOORWS:
3666                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3667                fr_src = fregNo(i->Min.FpConvert.src, mode64);
3668                p = mkFormR(p, 0x11, 0x10, 0, fr_src, fr_dst, 0x0F);
3669                break;
3670             case Mfp_FLOORWD:
3671                fr_dst = fregNo(i->Min.FpConvert.dst, mode64);
3672                fr_src = dregNo(i->Min.FpConvert.src);
3673                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0F);
3674                break;
3675             case Mfp_FLOORLD:
3676                fr_dst = dregNo(i->Min.FpConvert.dst);
3677                fr_src = dregNo(i->Min.FpConvert.src);
3678                p = mkFormR(p, 0x11, 0x11, 0, fr_src, fr_dst, 0x0B);
3679                break;
3680 
3681             default:
3682                goto bad;
3683          }
3684          goto done;
3685       }
3686 
3687       case Min_FpCompare: {
3688          UInt r_dst   = iregNo(i->Min.FpCompare.dst, mode64);
3689          UInt fr_srcL = dregNo(i->Min.FpCompare.srcL);
3690          UInt fr_srcR = dregNo(i->Min.FpCompare.srcR);
3691 
3692          UInt op;
3693          switch (i->Min.FpConvert.op) {
3694             case Mfp_CMP_UN:
3695                op = 1;
3696                break;
3697             case Mfp_CMP_EQ:
3698                op = 2;
3699                break;
3700             case Mfp_CMP_LT:
3701                op = 12;
3702                break;
3703             case Mfp_CMP_NGT:
3704                op = 15;
3705                break;
3706             default:
3707                goto bad;
3708          }
3709          /* c.cond.d fr_srcL, fr_srcR
3710             cfc1     r_dst,   $31
3711             srl      r_dst,   r_dst, 23
3712             andi     r_dst,   r_dst, 1 */
3713          p = mkFormR(p, 0x11, 0x11, fr_srcL, fr_srcR, 0, op + 48);
3714          p = mkFormR(p, 0x11, 0x2, r_dst, 31, 0, 0);
3715          p = mkFormS(p, 0, r_dst, 0, r_dst, 23, 2);
3716          p = mkFormI(p, 12, r_dst, r_dst, 1);
3717          goto done;
3718       }
3719 
3720       case Min_FpGpMove: {
3721          switch (i->Min.FpGpMove.op) {
3722             UInt rt, fs;
3723             case MFpGpMove_mfc1: {
3724                rt = iregNo(i->Min.FpGpMove.dst, mode64);
3725                fs = fregNo(i->Min.FpGpMove.src, mode64);
3726                p = mkFormR(p, 0x11, 0x0, rt, fs, 0x0, 0x0);
3727                break;
3728             }
3729             case MFpGpMove_dmfc1: {
3730                vassert(mode64);
3731                rt = iregNo(i->Min.FpGpMove.dst, mode64);
3732                fs = fregNo(i->Min.FpGpMove.src, mode64);
3733                p = mkFormR(p, 0x11, 0x1, rt, fs, 0x0, 0x0);
3734                break;
3735             }
3736             case MFpGpMove_mtc1: {
3737                rt = iregNo(i->Min.FpGpMove.src, mode64);
3738                fs = fregNo(i->Min.FpGpMove.dst, mode64);
3739                p = mkFormR(p, 0x11, 0x4, rt, fs, 0x0, 0x0);
3740                break;
3741             }
3742             case MFpGpMove_dmtc1: {
3743                vassert(mode64);
3744                rt = iregNo(i->Min.FpGpMove.src, mode64);
3745                fs = fregNo(i->Min.FpGpMove.dst, mode64);
3746                p = mkFormR(p, 0x11, 0x5, rt, fs, 0x0, 0x0);
3747                break;
3748             }
3749             default:
3750                goto bad;
3751          }
3752          goto done;
3753       }
3754 
3755       case Min_MoveCond: {
3756          switch (i->Min.MoveCond.op) {
3757             UInt d, s, t;
3758             case MFpMoveCond_movns: {
3759                d = fregNo(i->Min.MoveCond.dst, mode64);
3760                s = fregNo(i->Min.MoveCond.src, mode64);
3761                t = iregNo(i->Min.MoveCond.cond, mode64);
3762                p = mkFormR(p, 0x11, 0x10, t, s, d, 0x13);
3763                break;
3764             }
3765             case MFpMoveCond_movnd: {
3766                d = dregNo(i->Min.MoveCond.dst);
3767                s = dregNo(i->Min.MoveCond.src);
3768                t = iregNo(i->Min.MoveCond.cond, mode64);
3769                p = mkFormR(p, 0x11, 0x11, t, s, d, 0x13);
3770                break;
3771             }
3772             case MMoveCond_movn: {
3773                d = iregNo(i->Min.MoveCond.dst, mode64);
3774                s = iregNo(i->Min.MoveCond.src, mode64);
3775                t = iregNo(i->Min.MoveCond.cond, mode64);
3776                p = mkFormR(p, 0, s, t, d, 0, 0xb);
3777                break;
3778             }
3779             default:
3780                goto bad;
3781          }
3782          goto done;
3783       }
3784 
3785       case Min_EvCheck: {
3786          /* This requires a 32-bit dec/test in 32 mode. */
3787          /* We generate:
3788                lw      r9, amCounter
3789                addiu   r9, r9, -1
3790                sw      r9, amCounter
3791                bgez    r9, nofail
3792                lw      r9, amFailAddr
3793                jalr    r9
3794                nop
3795               nofail:
3796          */
3797          UChar* p0 = p;
3798          /* lw  r9, amCounter */
3799          p = do_load_or_store_word32(p, True /*isLoad*/ , /*r*/ 9,
3800                                      i->Min.EvCheck.amCounter, mode64);
3801          /* addiu r9,r9,-1 */
3802          p = mkFormI(p, 9, 9, 9, 0xFFFF);
3803          /* sw r30, amCounter */
3804          p = do_load_or_store_word32(p, False /*!isLoad*/ , /*r*/ 9,
3805                                      i->Min.EvCheck.amCounter, mode64);
3806          /* bgez t9, nofail */
3807          p = mkFormI(p, 1, 9, 1, 3);
3808          /* lw/ld r9, amFailAddr */
3809          p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
3810                                            i->Min.EvCheck.amFailAddr, mode64);
3811          /* jalr $9 */
3812          p = mkFormR(p, 0, 9, 0, 31, 0, 9);  /* p += 4 */
3813          p = mkFormR(p, 0, 0, 0, 0, 0, 0);   /* p += 4 */
3814          /* nofail: */
3815 
3816          /* Crosscheck */
3817          vassert(evCheckSzB_MIPS() == (UChar*)p - (UChar*)p0);
3818          goto done;
3819       }
3820 
3821       case Min_ProfInc: {
3822          /* Generate a code template to increment a memory location whose
3823             address will be known later as an immediate value. This code
3824             template will be patched once the memory location is known.
3825             For now we do this with address == 0x65556555. */
3826          if (mode64) {
3827             /* 64-bit:
3828                move r9, 0x6555655565556555ULL
3829                ld r8, 0(r9)
3830                daddiu r8, r8, 1
3831                sd r8, 0(r9) */
3832 
3833             /* move r9, 0x6555655565556555ULL */
3834             p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, 0x6555655565556555ULL,
3835                                       True /*mode64*/);
3836             /* ld r8, 0(r9) */
3837             p = mkFormI(p, 55, 9, 8, 0);
3838 
3839             /* daddiu r8, r8, 1 */
3840             p = mkFormI(p, 25, 8, 8, 1);
3841 
3842             /* sd r8, 0(r9) */
3843             p = mkFormI(p, 63, 9, 8, 0);
3844          } else {
3845             /* 32-bit:
3846                move r9, 0x65556555
3847                lw r8, 0(r9)
3848                addiu r8, r8, 1         # add least significant word
3849                sw r8, 0(r9)
3850                sltiu r1, r8, 1         # set carry-in bit
3851                lw r8, 4(r9)
3852                addu r8, r8, r1
3853                sw r8, 4(r9) */
3854 
3855             /* move r9, 0x65556555 */
3856             p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9, 0x65556555ULL,
3857                                       False /*!mode64*/);
3858             /* lw r8, 0(r9) */
3859             p = mkFormI(p, 35, 9, 8, 0);
3860 
3861             /* addiu r8, r8, 1         # add least significant word */
3862             p = mkFormI(p, 9, 8, 8, 1);
3863 
3864             /* sw r8, 0(r9) */
3865             p = mkFormI(p, 43, 9, 8, 0);
3866 
3867             /* sltiu r1, r8, 1         # set carry-in bit */
3868             p = mkFormI(p, 11, 8, 1, 1);
3869 
3870             /* lw r8, 4(r9) */
3871             p = mkFormI(p, 35, 9, 8, 4);
3872 
3873             /* addu r8, r8, r1 */
3874             p = mkFormR(p, 0, 8, 1, 8, 0, 33);
3875 
3876             /*  sw r8, 4(r9) */
3877             p = mkFormI(p, 43, 9, 8, 4);
3878 
3879          }
3880          /* Tell the caller .. */
3881          vassert(!(*is_profInc));
3882          *is_profInc = True;
3883          goto done;
3884       }
3885 
3886       default:
3887          goto bad;
3888 
3889    }
3890 
3891    bad:
3892       vex_printf("\n=> ");
3893       ppMIPSInstr(i, mode64);
3894       vpanic("emit_MIPSInstr");
3895       /* NOTREACHED */ done:
3896       vassert(p - &buf[0] <= 128);
3897       return p - &buf[0];
3898 }
3899 
3900 /* How big is an event check?  See case for Min_EvCheck in
3901    emit_MIPSInstr just above.  That crosschecks what this returns, so
3902    we can tell if we're inconsistent. */
evCheckSzB_MIPS(void)3903 Int evCheckSzB_MIPS (void)
3904 {
3905   UInt kInstrSize = 4;
3906   return 7*kInstrSize;
3907 }
3908 
3909 /* NB: what goes on here has to be very closely coordinated with the
3910    emitInstr case for XDirect, above. */
chainXDirect_MIPS(VexEndness endness_host,void * place_to_chain,const void * disp_cp_chain_me_EXPECTED,const void * place_to_jump_to,Bool mode64)3911 VexInvalRange chainXDirect_MIPS ( VexEndness endness_host,
3912                                   void* place_to_chain,
3913                                   const void* disp_cp_chain_me_EXPECTED,
3914                                   const void* place_to_jump_to,
3915                                   Bool  mode64 )
3916 {
3917    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
3918    /* What we're expecting to see is:
3919         move r9, disp_cp_chain_me_to_EXPECTED
3920         jalr r9
3921         nop
3922       viz
3923         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
3924         0x120F809   # jalr r9
3925         0x00000000  # nop
3926    */
3927    UChar* p = (UChar*)place_to_chain;
3928    vassert(0 == (3 & (HWord)p));
3929    vassert(isLoadImm_EXACTLY2or6(p, /*r*/9,
3930                                  (UInt)(Addr)disp_cp_chain_me_EXPECTED,
3931                                  mode64));
3932    vassert(fetch32(p + (mode64 ? 24 : 8) + 0) == 0x120F809);
3933    vassert(fetch32(p + (mode64 ? 24 : 8) + 4) == 0x00000000);
3934    /* And what we want to change it to is either:
3935           move r9, place_to_jump_to
3936           jalr r9
3937           nop
3938         viz
3939           <8 bytes generated by mkLoadImm_EXACTLY2or6>
3940           0x120F809   # jalr r9
3941           0x00000000  # nop
3942 
3943       The replacement has the same length as the original.
3944    */
3945 
3946    p = mkLoadImm_EXACTLY2or6(p, /*r*/9,
3947                              (Addr)place_to_jump_to, mode64);
3948    p = emit32(p, 0x120F809);
3949    p = emit32(p, 0x00000000);
3950 
3951    Int len = p - (UChar*)place_to_chain;
3952    vassert(len == (mode64 ? 32 : 16)); /* stay sane */
3953    VexInvalRange vir = {(HWord)place_to_chain, len};
3954    return vir;
3955 }
3956 
3957 /* NB: what goes on here has to be very closely coordinated with the
3958    emitInstr case for XDirect, above. */
unchainXDirect_MIPS(VexEndness endness_host,void * place_to_unchain,const void * place_to_jump_to_EXPECTED,const void * disp_cp_chain_me,Bool mode64)3959 VexInvalRange unchainXDirect_MIPS ( VexEndness endness_host,
3960                                     void* place_to_unchain,
3961                                     const void* place_to_jump_to_EXPECTED,
3962                                     const void* disp_cp_chain_me,
3963                                     Bool  mode64 )
3964 {
3965    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
3966    /* What we're expecting to see is:
3967         move r9, place_to_jump_to_EXPECTED
3968         jalr r9
3969         nop
3970       viz
3971         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
3972         0x120F809   # jalr r9
3973         0x00000000  # nop
3974    */
3975    UChar* p = (UChar*)place_to_unchain;
3976    vassert(0 == (3 & (HWord)p));
3977    vassert(isLoadImm_EXACTLY2or6(p, /*r*/ 9,
3978                                  (Addr)place_to_jump_to_EXPECTED,
3979                                  mode64));
3980    vassert(fetch32(p + (mode64 ? 24 : 8) + 0) == 0x120F809);
3981    vassert(fetch32(p + (mode64 ? 24 : 8) + 4) == 0x00000000);
3982    /* And what we want to change it to is:
3983         move r9, disp_cp_chain_me
3984         jalr r9
3985         nop
3986       viz
3987         <8 or 24 bytes generated by mkLoadImm_EXACTLY2or6>
3988         0x120F809   # jalr r9
3989         0x00000000  # nop
3990       The replacement has the same length as the original.
3991    */
3992    p = mkLoadImm_EXACTLY2or6(p, /*r*/ 9,
3993                              (Addr)disp_cp_chain_me, mode64);
3994    p = emit32(p, 0x120F809);
3995    p = emit32(p, 0x00000000);
3996 
3997    Int len = p - (UChar*)place_to_unchain;
3998    vassert(len == (mode64 ? 32 : 16)); /* stay sane */
3999    VexInvalRange vir = {(HWord)place_to_unchain, len};
4000    return vir;
4001 }
4002 
4003 /* Patch the counter address into a profile inc point, as previously
4004    created by the Min_ProfInc case for emit_MIPSInstr. */
patchProfInc_MIPS(VexEndness endness_host,void * place_to_patch,const ULong * location_of_counter,Bool mode64)4005 VexInvalRange patchProfInc_MIPS ( VexEndness endness_host,
4006                                   void*  place_to_patch,
4007                                   const ULong* location_of_counter,
4008                                   Bool mode64 )
4009 {
4010    vassert(endness_host == VexEndnessLE || endness_host == VexEndnessBE);
4011    if (mode64) {
4012       vassert(sizeof(ULong*) == 8);
4013    } else {
4014       vassert(sizeof(ULong*) == 4);
4015    }
4016    UChar* p = (UChar*)place_to_patch;
4017    vassert(0 == (3 & (HWord)p));
4018    vassert(isLoadImm_EXACTLY2or6((UChar *)p, /*r*/9,
4019                                  mode64 ? 0x6555655565556555ULL : 0x65556555,
4020                                  mode64));
4021 
4022    if (mode64) {
4023       vassert(fetch32(p + 24 + 0) == 0xDD280000);
4024       vassert(fetch32(p + 24 + 4) == 0x65080001);
4025       vassert(fetch32(p + 24 + 8) == 0xFD280000);
4026    } else {
4027       vassert(fetch32(p + 8 + 0) == 0x8D280000);
4028       vassert(fetch32(p + 8 + 4) == 0x25080001);
4029       vassert(fetch32(p + 8 + 8) == 0xAD280000);
4030       vassert(fetch32(p + 8 + 12) == 0x2d010001);
4031       vassert(fetch32(p + 8 + 16) == 0x8d280004);
4032       vassert(fetch32(p + 8 + 20) == 0x01014021);
4033       vassert(fetch32(p + 8 + 24) == 0xad280004);
4034    }
4035 
4036    p = mkLoadImm_EXACTLY2or6(p, /*r*/9,
4037                              (Addr)location_of_counter, mode64);
4038 
4039    VexInvalRange vir = {(HWord)p, 8};
4040    return vir;
4041 }
4042 
4043 
4044 /*---------------------------------------------------------------*/
4045 /*--- end                                    host_mips_defs.c ---*/
4046 /*---------------------------------------------------------------*/
4047