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