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