1 /*---------------------------------------------------------------*/
2 /*--- begin host_NANOMIPS_defs.c ---*/
3 /*---------------------------------------------------------------*/
6 This file is part of Valgrind, a dynamic binary instrumentation
9 Copyright (C) 2017-2018 RT-RK
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 The GNU General Public License is contained in the file COPYING.
29 #include "libvex_basictypes.h"
31 #include "libvex_trc_values.h"
33 #include "main_util.h"
34 #include "host_generic_regs.h"
35 #include "host_nanomips_defs.h"
37 /* Register number for guest state pointer in host code. */
41 NANOMIPSInstr
*NANOMIPSInstr_Imm(NANOMIPSImmOp op
, HReg dst
, HReg src
,
44 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
47 i
->NMin
.Imm
.dst
= dst
;
48 i
->NMin
.Imm
.src
= src
;
49 i
->NMin
.Imm
.imm
= imm
;
53 NANOMIPSInstr
*NANOMIPSInstr_Alu(NANOMIPSAluOp op
, HReg dst
, HReg srcL
,
56 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
59 i
->NMin
.Alu
.dst
= dst
;
60 i
->NMin
.Alu
.srcL
= srcL
;
61 i
->NMin
.Alu
.srcR
= srcR
;
65 NANOMIPSInstr
*NANOMIPSInstr_Unary(NANOMIPSUnaryOp op
, HReg dst
, HReg src
)
67 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
69 i
->NMin
.Unary
.op
= op
;
70 i
->NMin
.Unary
.dst
= dst
;
71 i
->NMin
.Unary
.src
= src
;
75 NANOMIPSInstr
*NANOMIPSInstr_Cmp(NANOMIPSCondCode cond
, HReg dst
, HReg srcL
,
78 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
80 i
->NMin
.Cmp
.dst
= dst
;
81 i
->NMin
.Cmp
.srcL
= srcL
;
82 i
->NMin
.Cmp
.srcR
= srcR
;
83 i
->NMin
.Cmp
.cond
= cond
;
87 NANOMIPSInstr
*NANOMIPSInstr_Call(Addr target
,
88 UInt argiregs
, HReg guard
, RetLoc rloc
)
91 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
93 i
->NMin
.Call
.target
= target
;
94 i
->NMin
.Call
.argiregs
= argiregs
;
95 i
->NMin
.Call
.guard
= guard
;
96 i
->NMin
.Call
.rloc
= rloc
;
97 /* Only $4 ... $11 inclusive may be used as arg regs.*/
98 mask
= (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)
99 | (1 << 10) | (1 << 11);
100 vassert(0 == (argiregs
& ~mask
));
101 vassert(is_sane_RetLoc(rloc
));
105 NANOMIPSInstr
*NANOMIPSInstr_XDirect(Addr64 dstGA
, HReg address
, Int offset
,
106 HReg cond
, Bool toFastEP
)
108 NANOMIPSInstr
* i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
109 i
->tag
= NMin_XDirect
;
110 i
->NMin
.XDirect
.dstGA
= dstGA
;
111 i
->NMin
.XDirect
.addr
= address
;
112 i
->NMin
.XDirect
.addr_offset
= offset
;
113 i
->NMin
.XDirect
.cond
= cond
;
114 i
->NMin
.XDirect
.toFastEP
= toFastEP
;
118 NANOMIPSInstr
*NANOMIPSInstr_XIndir(HReg dstGA
, HReg address
, Int offset
,
121 NANOMIPSInstr
* i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
122 i
->tag
= NMin_XIndir
;
123 i
->NMin
.XIndir
.dstGA
= dstGA
;
124 i
->NMin
.XIndir
.addr
= address
;
125 i
->NMin
.XIndir
.addr_offset
= offset
;
126 i
->NMin
.XIndir
.cond
= cond
;
130 NANOMIPSInstr
*NANOMIPSInstr_XAssisted(HReg dstGA
, HReg address
, Int offset
,
131 HReg cond
, IRJumpKind jk
)
133 NANOMIPSInstr
* i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
134 i
->tag
= NMin_XAssisted
;
135 i
->NMin
.XAssisted
.dstGA
= dstGA
;
136 i
->NMin
.XAssisted
.addr
= address
;
137 i
->NMin
.XAssisted
.addr_offset
= offset
;
138 i
->NMin
.XAssisted
.cond
= cond
;
139 i
->NMin
.XAssisted
.jk
= jk
;
143 NANOMIPSInstr
*NANOMIPSInstr_Load(UChar sz
, HReg dst
,
144 HReg addr
, Int addr_offset
)
146 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
148 i
->NMin
.Load
.sz
= sz
;
149 i
->NMin
.Load
.addr
= addr
;
150 i
->NMin
.Load
.addr_offset
= addr_offset
;
151 i
->NMin
.Load
.dst
= dst
;
152 vassert(sz
== 1 || sz
== 2 || sz
== 4);
156 NANOMIPSInstr
*NANOMIPSInstr_Store(UChar sz
, HReg addr
, Int addr_offset
,
159 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
161 i
->NMin
.Store
.sz
= sz
;
162 i
->NMin
.Store
.src
= src
;
163 i
->NMin
.Store
.addr
= addr
;
164 i
->NMin
.Store
.addr_offset
= addr_offset
;
165 vassert(sz
== 1 || sz
== 2 || sz
== 4);
166 vassert(addr_offset
< 0x1000);
170 NANOMIPSInstr
*NANOMIPSInstr_LoadL(UChar sz
, HReg dst
,
171 HReg addr
, Int addr_offset
)
173 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
175 i
->NMin
.LoadL
.sz
= sz
;
176 i
->NMin
.LoadL
.addr
= addr
;
177 i
->NMin
.LoadL
.addr_offset
= addr_offset
;
182 NANOMIPSInstr
*NANOMIPSInstr_Cas(UChar sz
, HReg oldLo
, HReg oldHi
, HReg addr
,
183 HReg expdLo
, HReg expdHi
,
184 HReg dataLo
, HReg dataHi
)
186 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
189 i
->NMin
.Cas
.oldLo
= oldLo
;
190 i
->NMin
.Cas
.addr
= addr
;
191 i
->NMin
.Cas
.expdLo
= expdLo
;
192 i
->NMin
.Cas
.dataLo
= dataLo
;
194 vassert((sz
== 4) || (sz
== 8));
197 i
->NMin
.Cas
.oldHi
= oldHi
;
198 i
->NMin
.Cas
.expdHi
= expdHi
;
199 i
->NMin
.Cas
.dataHi
= dataHi
;
204 NANOMIPSInstr
*NANOMIPSInstr_StoreC(UChar sz
, HReg addr
, Int addr_offset
,
207 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
208 i
->tag
= NMin_StoreC
;
209 i
->NMin
.StoreC
.sz
= sz
;
210 i
->NMin
.StoreC
.src
= src
;
211 i
->NMin
.StoreC
.addr
= addr
;
212 i
->NMin
.StoreC
.addr_offset
= addr_offset
;
217 NANOMIPSInstr
*NANOMIPSInstr_MoveCond(NANOMIPSMoveCondOp op
, HReg dst
,
220 NANOMIPSInstr
*i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
221 i
->tag
= NMin_MoveCond
;
222 i
->NMin
.MoveCond
.op
= op
;
223 i
->NMin
.MoveCond
.dst
= dst
;
224 i
->NMin
.MoveCond
.src
= src
;
225 i
->NMin
.MoveCond
.cond
= cond
;
229 NANOMIPSInstr
*NANOMIPSInstr_EvCheck(HReg r_amCounter
,
230 Int offset_amCounter
,
232 Int offset_amFailAddr
)
234 NANOMIPSInstr
* i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
235 i
->tag
= NMin_EvCheck
;
236 i
->NMin
.EvCheck
.r_amCounter
= r_amCounter
;
237 i
->NMin
.EvCheck
.offset_amCounter
= offset_amCounter
;
238 i
->NMin
.EvCheck
.r_amFailAddr
= r_amFailAddr
;
239 i
->NMin
.EvCheck
.offset_amFailAddr
= offset_amFailAddr
;
243 NANOMIPSInstr
* NANOMIPSInstr_ProfInc ( void )
245 NANOMIPSInstr
* i
= LibVEX_Alloc_inline(sizeof(NANOMIPSInstr
));
246 i
->tag
= NMin_ProfInc
;
250 UInt
ppHRegNANOMIPS(HReg r
)
252 static const HChar
* regnames
[32] = {
253 "zero", "at", "t4", "t5", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
254 "t0", "t1", "t2", "t3", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
255 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
259 if (hregIsVirtual(r
)) {
263 vassert(hregClass(r
) == HRcInt32
);
264 r_no
= hregEncoding(r
);
267 return vex_printf("%s", regnames
[r_no
]);
270 void ppNANOMIPSInstr(const NANOMIPSInstr
* i
)
274 switch (i
->NMin
.Imm
.op
) {
314 ppHRegNANOMIPS(i
->NMin
.Imm
.dst
);
317 if (i
->NMin
.Imm
.op
!= NMimm_LI
) {
318 ppHRegNANOMIPS(i
->NMin
.Imm
.src
);
322 if (i
->NMin
.Imm
.op
== NMimm_ROTX
)
323 vex_printf("%u, %u, %u", (i
->NMin
.Imm
.imm
>> 7) & 0xF,
324 (i
->NMin
.Imm
.imm
>> 6) & 1, i
->NMin
.Imm
.imm
& 0x1F);
326 vex_printf("0x%X (%d)", i
->NMin
.Imm
.imm
, (Int
)i
->NMin
.Imm
.imm
);
331 switch (i
->NMin
.Alu
.op
) {
345 if (sameHReg(i
->NMin
.Alu
.srcL
, i
->NMin
.Alu
.srcR
))
412 ppHRegNANOMIPS(i
->NMin
.Alu
.dst
);
414 ppHRegNANOMIPS(i
->NMin
.Alu
.srcL
);
416 if ((i
->NMin
.Alu
.op
!= NMalu_OR
) ||
417 !sameHReg(i
->NMin
.Alu
.srcL
, i
->NMin
.Alu
.srcR
)) {
419 ppHRegNANOMIPS(i
->NMin
.Alu
.srcR
);
425 switch (i
->NMin
.Unary
.op
) {
441 if (i
->NMin
.Unary
.op
!= NMun_NOP
)
443 ppHRegNANOMIPS(i
->NMin
.Unary
.dst
);
445 ppHRegNANOMIPS(i
->NMin
.Unary
.src
);
450 switch (i
->NMin
.Cmp
.cond
) {
487 ppHRegNANOMIPS(i
->NMin
.Cmp
.dst
);
489 ppHRegNANOMIPS(i
->NMin
.Cmp
.srcL
);
491 ppHRegNANOMIPS(i
->NMin
.Cmp
.srcR
);
496 vex_printf("CALL 0x%lX, #%X, ", i
->NMin
.Call
.target
,
497 i
->NMin
.Call
.argiregs
);
498 ppHRegNANOMIPS(i
->NMin
.Call
.guard
);
502 vex_printf("(xDirect) ");
503 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
)) {
505 ppHRegNANOMIPS(i
->NMin
.XDirect
.cond
);
506 vex_printf(", zero, 12; ");
508 vex_printf("LI a5, 0x%08lX; ", i
->NMin
.XDirect
.dstGA
);
509 vex_printf("sw a5, %d(", i
->NMin
.XDirect
.addr_offset
);
510 ppHRegNANOMIPS(i
->NMin
.XDirect
.addr
);
511 vex_printf("); LI a5, <%s>; ", i
->NMin
.XDirect
.toFastEP
?
512 "disp_cp_chain_me_to_fastEP" : "disp_cp_chain_me_to_slowEP");
513 vex_printf("jalrc a5");
517 vex_printf("(xIndir) ");
518 if (!hregIsInvalid(i
->NMin
.XIndir
.cond
)) {
520 ppHRegNANOMIPS(i
->NMin
.XIndir
.cond
);
521 vex_printf(", zero, 16; ");
524 ppHRegNANOMIPS(i
->NMin
.XIndir
.dstGA
);
525 vex_printf(", %d(", i
->NMin
.XIndir
.addr_offset
);
526 ppHRegNANOMIPS(i
->NMin
.XIndir
.addr
);
527 vex_printf("); LI a5, <disp_cp_xindir>; ");
528 vex_printf("jalrc a5");
532 vex_printf("(xAssisted) ");
533 if (!hregIsInvalid(i
->NMin
.XAssisted
.cond
)) {
535 ppHRegNANOMIPS(i
->NMin
.XAssisted
.cond
);
536 vex_printf(", zero, 24; ");
539 ppHRegNANOMIPS(i
->NMin
.XAssisted
.dstGA
);
540 vex_printf(", %d(", i
->NMin
.XAssisted
.addr_offset
);
541 ppHRegNANOMIPS(i
->NMin
.XAssisted
.addr
);
542 vex_printf("); move a5, $IRJumpKind_to_TRCVAL(%d)",
543 (Int
)i
->NMin
.XAssisted
.jk
);
544 vex_printf("; LI a5, <disp_cp_xassisted>; ");
545 vex_printf("jalrc a5");
549 vex_printf("(evCheck) ");
550 vex_printf("lw a5, %d(", i
->NMin
.EvCheck
.offset_amCounter
);
551 ppHRegNANOMIPS(i
->NMin
.EvCheck
.r_amCounter
);
552 vex_printf("); addiu $9, $9, -1");
553 vex_printf("; sw a5, %d(", i
->NMin
.EvCheck
.offset_amCounter
);
554 ppHRegNANOMIPS(i
->NMin
.EvCheck
.r_amCounter
);
555 vex_printf("); begc a5, zero, nofail;");
556 vex_printf("lw a5, %d(", i
->NMin
.EvCheck
.offset_amFailAddr
);
557 ppHRegNANOMIPS(i
->NMin
.EvCheck
.r_amFailAddr
);
558 vex_printf("); jalrc a5; nofail:");
562 vex_printf("(profInc) li a5, ($NotKnownYet); "
573 switch (i
->NMin
.Load
.sz
) {
587 ppHRegNANOMIPS(i
->NMin
.Load
.dst
);
588 vex_printf(", (%d)", i
->NMin
.Load
.addr_offset
);
589 ppHRegNANOMIPS(i
->NMin
.Load
.addr
);
593 switch (i
->NMin
.Store
.sz
) {
607 ppHRegNANOMIPS(i
->NMin
.Store
.src
);
608 vex_printf(", (%d)", i
->NMin
.Store
.addr_offset
);
609 ppHRegNANOMIPS(i
->NMin
.Store
.addr
);
613 vex_printf("cas: \n");
614 if (i
->NMin
.Cas
.sz
== 4) {
616 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
618 ppHRegNANOMIPS(i
->NMin
.Cas
.addr
);
622 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
624 ppHRegNANOMIPS(i
->NMin
.Cas
.expdLo
);
625 vex_printf(", end; ");
627 vex_printf("addiu ");
628 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
630 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
634 ppHRegNANOMIPS(i
->NMin
.Cas
.dataLo
);
636 ppHRegNANOMIPS(i
->NMin
.Cas
.addr
);
640 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
642 ppHRegNANOMIPS(i
->NMin
.Cas
.expdLo
);
644 ppHRegNANOMIPS(i
->NMin
.Cas
.dataLo
);
645 vex_printf("; end:");
648 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
650 ppHRegNANOMIPS(i
->NMin
.Cas
.oldHi
);
652 ppHRegNANOMIPS(i
->NMin
.Cas
.addr
);
656 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
658 ppHRegNANOMIPS(i
->NMin
.Cas
.expdLo
);
659 vex_printf(", end; ");
662 ppHRegNANOMIPS(i
->NMin
.Cas
.oldHi
);
664 ppHRegNANOMIPS(i
->NMin
.Cas
.expdHi
);
665 vex_printf(", end; ");
667 vex_printf("addiu ");
668 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
670 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
673 vex_printf("addiu ");
674 ppHRegNANOMIPS(i
->NMin
.Cas
.oldHi
);
676 ppHRegNANOMIPS(i
->NMin
.Cas
.oldHi
);
680 ppHRegNANOMIPS(i
->NMin
.Cas
.dataLo
);
682 ppHRegNANOMIPS(i
->NMin
.Cas
.dataHi
);
684 ppHRegNANOMIPS(i
->NMin
.Cas
.addr
);
688 ppHRegNANOMIPS(i
->NMin
.Cas
.oldLo
);
690 ppHRegNANOMIPS(i
->NMin
.Cas
.expdLo
);
692 ppHRegNANOMIPS(i
->NMin
.Cas
.dataLo
);
695 ppHRegNANOMIPS(i
->NMin
.Cas
.oldHi
);
697 ppHRegNANOMIPS(i
->NMin
.Cas
.expdHi
);
699 ppHRegNANOMIPS(i
->NMin
.Cas
.dataHi
);
700 vex_printf("; end:");
706 ppHRegNANOMIPS(i
->NMin
.LoadL
.dst
);
707 vex_printf(", %d(", i
->NMin
.LoadL
.addr_offset
);
708 ppHRegNANOMIPS(i
->NMin
.LoadL
.addr
);
714 ppHRegNANOMIPS(i
->NMin
.StoreC
.src
);
715 vex_printf(", %d(", i
->NMin
.StoreC
.addr_offset
);
716 ppHRegNANOMIPS(i
->NMin
.StoreC
.addr
);
721 vassert(i
->NMin
.MoveCond
.op
== NMMoveCond_movn
);
723 ppHRegNANOMIPS(i
->NMin
.MoveCond
.dst
);
725 ppHRegNANOMIPS(i
->NMin
.MoveCond
.src
);
727 ppHRegNANOMIPS(i
->NMin
.MoveCond
.cond
);
732 /* --------- Helpers for register allocation. --------- */
734 void getRegUsage_NANOMIPSInstr(HRegUsage
* u
, const NANOMIPSInstr
* i
)
740 addHRegUse(u
, HRmWrite
, i
->NMin
.Imm
.dst
);
742 if (!hregIsInvalid(i
->NMin
.Imm
.src
))
743 addHRegUse(u
, HRmRead
, i
->NMin
.Imm
.src
);
748 addHRegUse(u
, HRmRead
, i
->NMin
.Alu
.srcL
);
749 addHRegUse(u
, HRmRead
, i
->NMin
.Alu
.srcR
);
750 addHRegUse(u
, HRmWrite
, i
->NMin
.Alu
.dst
);
752 /* or Rd,Rs,Rs == mr Rd,Rs */
753 if ((i
->NMin
.Alu
.op
== NMalu_OR
)
754 && sameHReg(i
->NMin
.Alu
.srcR
, i
->NMin
.Alu
.srcL
)) {
755 u
->isRegRegMove
= True
;
756 u
->regMoveSrc
= i
->NMin
.Alu
.srcL
;
757 u
->regMoveDst
= i
->NMin
.Alu
.dst
;
763 addHRegUse(u
, HRmRead
, i
->NMin
.Cmp
.srcL
);
764 addHRegUse(u
, HRmRead
, i
->NMin
.Cmp
.srcR
);
765 addHRegUse(u
, HRmWrite
, i
->NMin
.Cmp
.dst
);
769 addHRegUse(u
, HRmRead
, i
->NMin
.Unary
.src
);
770 addHRegUse(u
, HRmWrite
, i
->NMin
.Unary
.dst
);
774 UInt argir
= i
->NMin
.Call
.argiregs
;
776 if (!hregIsInvalid(i
->NMin
.Call
.guard
))
777 addHRegUse(u
, HRmRead
, i
->NMin
.Call
.guard
);
779 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR1());
780 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR2());
781 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR3());
782 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR4());
783 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR5());
784 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR6());
785 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR7());
786 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR8());
787 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR9());
788 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR10());
789 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR11());
790 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR12());
791 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR13());
792 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR14());
793 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR15());
794 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR24());
795 addHRegUse(u
, HRmWrite
, hregNANOMIPS_GPR25());
797 if (argir
& (1 << 11)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR11());
799 if (argir
& (1 << 10)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR10());
801 if (argir
& (1 << 9)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR9());
803 if (argir
& (1 << 8)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR8());
805 if (argir
& (1 << 7)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR7());
807 if (argir
& (1 << 6)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR6());
809 if (argir
& (1 << 5)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR5());
811 if (argir
& (1 << 4)) addHRegUse(u
, HRmRead
, hregNANOMIPS_GPR4());
813 vassert(0 == (argir
& ~((1 << 4) | (1 << 5) | (1 << 6)
814 | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
819 /* XDirect/XIndir/XAssisted are also a bit subtle. They
820 conditionally exit the block. Hence we only need to list (1)
821 the registers that they read, and (2) the registers that they
822 write in the case where the block is not exited. (2) is
823 empty, hence only (1) is relevant here. */
825 addHRegUse(u
, HRmRead
, i
->NMin
.XDirect
.addr
);
827 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
))
828 addHRegUse(u
, HRmRead
, i
->NMin
.XDirect
.cond
);
833 addHRegUse(u
, HRmRead
, i
->NMin
.XIndir
.dstGA
);
834 addHRegUse(u
, HRmRead
, i
->NMin
.XIndir
.addr
);
836 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
))
837 addHRegUse(u
, HRmRead
, i
->NMin
.XDirect
.cond
);
842 addHRegUse(u
, HRmRead
, i
->NMin
.XAssisted
.dstGA
);
843 addHRegUse(u
, HRmRead
, i
->NMin
.XAssisted
.addr
);
845 if (!hregIsInvalid(i
->NMin
.XAssisted
.cond
))
846 addHRegUse(u
, HRmRead
, i
->NMin
.XAssisted
.cond
);
851 addHRegUse(u
, HRmRead
, i
->NMin
.Load
.addr
);
852 addHRegUse(u
, HRmWrite
, i
->NMin
.Load
.dst
);
856 addHRegUse(u
, HRmRead
, i
->NMin
.Store
.addr
);
857 addHRegUse(u
, HRmRead
, i
->NMin
.Store
.src
);
861 addHRegUse(u
, HRmRead
, i
->NMin
.LoadL
.addr
);
862 addHRegUse(u
, HRmWrite
, i
->NMin
.LoadL
.dst
);
866 addHRegUse(u
, HRmWrite
, i
->NMin
.Cas
.oldLo
);
867 addHRegUse(u
, HRmRead
, i
->NMin
.Cas
.addr
);
868 addHRegUse(u
, HRmRead
, i
->NMin
.Cas
.expdLo
);
869 addHRegUse(u
, HRmModify
, i
->NMin
.Cas
.dataLo
);
870 if (i
->NMin
.Cas
.sz
== 8) {
871 addHRegUse(u
, HRmWrite
, i
->NMin
.Cas
.oldHi
);
872 addHRegUse(u
, HRmRead
, i
->NMin
.Cas
.expdHi
);
873 addHRegUse(u
, HRmModify
, i
->NMin
.Cas
.dataHi
);
878 addHRegUse(u
, HRmRead
, i
->NMin
.StoreC
.addr
);
879 addHRegUse(u
, HRmWrite
, i
->NMin
.StoreC
.src
);
880 addHRegUse(u
, HRmRead
, i
->NMin
.StoreC
.src
);
884 addHRegUse(u
, HRmWrite
, i
->NMin
.MoveCond
.dst
);
885 addHRegUse(u
, HRmRead
, i
->NMin
.MoveCond
.src
);
886 addHRegUse(u
, HRmRead
, i
->NMin
.MoveCond
.cond
);
890 addHRegUse(u
, HRmRead
, i
->NMin
.EvCheck
.r_amCounter
);
891 addHRegUse(u
, HRmRead
, i
->NMin
.EvCheck
.r_amFailAddr
);
895 /* does not use any registers. */
900 vpanic("getRegUsage_NANOMIPSInstr");
906 static void mapReg(HRegRemap
* m
, HReg
* r
)
908 *r
= lookupHRegRemap(m
, *r
);
911 void mapRegs_NANOMIPSInstr(HRegRemap
* m
, NANOMIPSInstr
* i
)
915 mapReg(m
, &i
->NMin
.Imm
.dst
);
917 if (!hregIsInvalid(i
->NMin
.Imm
.src
))
918 mapReg(m
, &i
->NMin
.Imm
.src
);
923 mapReg(m
, &i
->NMin
.Alu
.srcL
);
924 mapReg(m
, &i
->NMin
.Alu
.srcR
);
925 mapReg(m
, &i
->NMin
.Alu
.dst
);
929 mapReg(m
, &i
->NMin
.Cmp
.srcL
);
930 mapReg(m
, &i
->NMin
.Cmp
.srcR
);
931 mapReg(m
, &i
->NMin
.Cmp
.dst
);
935 mapReg(m
, &i
->NMin
.Unary
.src
);
936 mapReg(m
, &i
->NMin
.Unary
.dst
);
940 if (!hregIsInvalid(i
->NMin
.Call
.guard
))
941 mapReg(m
, &i
->NMin
.Call
.guard
);
947 mapReg(m
, &i
->NMin
.XDirect
.addr
);
949 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
))
950 mapReg(m
, &i
->NMin
.XDirect
.cond
);
955 mapReg(m
, &i
->NMin
.XIndir
.dstGA
);
956 mapReg(m
, &i
->NMin
.XIndir
.addr
);
958 if (!hregIsInvalid(i
->NMin
.XIndir
.cond
))
959 mapReg(m
, &i
->NMin
.XIndir
.cond
);
964 mapReg(m
, &i
->NMin
.XAssisted
.dstGA
);
965 mapReg(m
, &i
->NMin
.XAssisted
.addr
);
967 if (!hregIsInvalid(i
->NMin
.XAssisted
.cond
))
968 mapReg(m
, &i
->NMin
.XAssisted
.cond
);
973 mapReg(m
, &i
->NMin
.Load
.addr
);
974 mapReg(m
, &i
->NMin
.Load
.dst
);
978 mapReg(m
, &i
->NMin
.Store
.addr
);
979 mapReg(m
, &i
->NMin
.Store
.src
);
983 mapReg(m
, &i
->NMin
.LoadL
.addr
);
984 mapReg(m
, &i
->NMin
.LoadL
.dst
);
988 mapReg(m
, &i
->NMin
.Cas
.oldLo
);
989 mapReg(m
, &i
->NMin
.Cas
.addr
);
990 mapReg(m
, &i
->NMin
.Cas
.expdLo
);
991 mapReg(m
, &i
->NMin
.Cas
.dataLo
);
992 if (i
->NMin
.Cas
.sz
== 8) {
993 mapReg(m
, &i
->NMin
.Cas
.oldHi
);
994 mapReg(m
, &i
->NMin
.Cas
.expdHi
);
995 mapReg(m
, &i
->NMin
.Cas
.dataHi
);
1000 mapReg(m
, &i
->NMin
.StoreC
.addr
);
1001 mapReg(m
, &i
->NMin
.StoreC
.src
);
1005 mapReg(m
, &i
->NMin
.MoveCond
.dst
);
1006 mapReg(m
, &i
->NMin
.MoveCond
.src
);
1007 mapReg(m
, &i
->NMin
.MoveCond
.cond
);
1011 /* We expect both amodes only to mention %ebp, so this is in
1012 fact pointless, since %ebp isn't allocatable, but anyway.. */
1013 mapReg(m
, &i
->NMin
.EvCheck
.r_amCounter
);
1014 mapReg(m
, &i
->NMin
.EvCheck
.r_amFailAddr
);
1018 /* does not use any registers. */
1023 vpanic("mapRegs_NANOMIPSInstr");
1028 /* Generate NANOMIPS spill/reload instructions under the direction of the
1029 register allocator. */
1030 void genSpill_NANOMIPS( /*OUT*/ HInstr
** i1
, /*OUT*/ HInstr
** i2
, HReg rreg
,
1031 Int offsetB
, Bool mode64
)
1033 vassert(offsetB
>= 0);
1034 vassert(offsetB
< 0x1000);
1036 vassert(!hregIsVirtual(rreg
));
1037 vassert(hregClass(rreg
) == HRcInt32
);
1039 *i1
= NANOMIPSInstr_Store(4, GuestStatePointer
, offsetB
, rreg
);
1042 void genReload_NANOMIPS( /*OUT*/ HInstr
** i1
, /*OUT*/ HInstr
** i2
, HReg rreg
,
1043 Int offsetB
, Bool mode64
)
1045 vassert(offsetB
>= 0);
1046 vassert(offsetB
< 0x1000);
1048 vassert(!hregIsVirtual(rreg
));
1049 vassert(hregClass(rreg
) == HRcInt32
);
1051 *i1
= NANOMIPSInstr_Load(4, rreg
, GuestStatePointer
, offsetB
);
1054 NANOMIPSInstr
* genMove_NANOMIPS(HReg r_src
, HReg r_dst
)
1056 vassert(hregClass(r_dst
) == hregClass(r_src
));
1057 vassert(hregClass(r_src
) == HRcInt32
);
1058 return NANOMIPSInstr_Alu(NMalu_OR
, r_dst
, r_src
, r_src
);
1061 /* --------- The NANOMIPS assembler --------- */
1063 inline static UInt
iregNo(HReg r
)
1066 vassert(hregClass(r
) == (HRcInt32
));
1067 vassert(!hregIsVirtual(r
));
1068 n
= hregEncoding(r
);
1073 /* Emit 32bit instruction */
1074 static UChar
*emit32(UChar
* p
, UInt w32
)
1076 #if defined (_MIPSEB)
1077 *p
++ = toUChar((w32
>> 24) & 0x000000FF);
1078 *p
++ = toUChar((w32
>> 16) & 0x000000FF);
1079 *p
++ = toUChar((w32
>> 8) & 0x000000FF);
1080 *p
++ = toUChar(w32
& 0x000000FF);
1082 *p
++ = toUChar((w32
>> 16) & 0x000000FF);
1083 *p
++ = toUChar((w32
>> 24) & 0x000000FF);
1084 *p
++ = toUChar(w32
& 0x000000FF);
1085 *p
++ = toUChar((w32
>> 8) & 0x000000FF);
1090 static UChar
*mkFormNano2Regs12imm(UChar
* p
, UInt opc
, UInt rt
, UInt rs
,
1091 UInt opc2
, UInt imm
)
1094 vassert(opc
< 0x40);
1097 vassert(opc2
< 0x10);
1098 vassert(imm
< 0x1000);
1099 theInstr
= ((opc
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc2
<< 12) | (imm
));
1100 return emit32(p
, theInstr
);
1103 static UChar
*mkFormNano2Regs16imm(UChar
* p
, UInt opc
, UInt rt
, UInt rs
,
1107 vassert(opc
< 0x40);
1110 theInstr
= ((opc
<< 26) | (rt
<< 21) | (rs
<< 16) | (imm
));
1111 return emit32(p
, theInstr
);
1114 static UChar
*mkFormNano1Reg(UChar
* p
, UInt opc
, UInt rt
, UInt opc2
,
1118 vassert(opc
< 0x40);
1122 case 0x38: /* LUI */
1123 theInstr
= ((opc
<< 26) | (rt
<< 21) | (imm
& 0x1FF000) |
1124 ((imm
& 0x7FE00000) >> 19) | ((imm
& 0x80000000) >> 31));
1125 return emit32(p
, theInstr
);
1132 static UChar
* mkFormNanoPShift(UChar
* p
, UInt rt
, UInt rs
, UInt opc2
,
1138 vassert(opc2
< 0x10);
1139 vassert(imm
< 0x20);
1142 case PSLL
: /* SLL */
1143 case SRL32
: /* SRL */
1145 theInstr
= ((PU12
<< 26) | (rt
<< 21) | (rs
<< 16) |
1146 (PU12_PSHIFT
<< 12) | (opc2
<< 5) | (imm
));
1147 return emit32(p
, theInstr
);
1154 static UChar
*mkFormNanoP32A0(UChar
* p
, UInt rt
, UInt rs
, UInt rd
, UInt opc2
)
1160 vassert(opc2
< 0x80);
1163 case _POOL32A0_ADDU32
: /* ADDU */
1164 case _POOL32A0_AND32
: /* AND */
1165 case _POOL32A0_SUBU32
: /* SUBU */
1166 case _POOL32A0_SLLV
: /* SLLV */
1167 case _POOL32A0_SRLV
: /* SRLV */
1168 case _POOL32A0_SRAV
: /* SRAV */
1169 case _POOL32A0_XOR32
: /* XOR */
1170 case _POOL32A0_SLT
: /* SLT */
1171 case _POOL32A0_OR32
: /* OR */
1172 case _POOL32A0_NOR
: /* NOR */
1173 case _POOL32A0_PSLTU
: /* SLTU */
1174 case _POOL32A0_DIV
: /* DIV */
1175 case _POOL32A0_DIVU
: /* DIVU */
1176 case _POOL32A0_MOD
: /* MOD */
1177 case _POOL32A0_MODU
: /* MODU */
1178 case _POOL32A0_MUL32
: /* MUL */
1179 case _POOL32A0_MULU
: /* MULU */
1180 case _POOL32A0_MUH
: /* MUH */
1181 case _POOL32A0_MUHU
: /* MUHU */
1182 theInstr
= ((P32A
<< 26) | (rt
<< 21) | (rs
<< 16) | (rd
<< 11) |
1184 return emit32(p
, theInstr
);
1186 case _POOL32A0_PCMOVE
: /* MOVN */
1187 theInstr
= ((P32A
<< 26) | (rt
<< 21) | (rs
<< 16) | (rd
<< 11) |
1188 (1 << 10) | (opc2
<< 3));
1189 return emit32(p
, theInstr
);
1196 static UChar
*mkFormNanoPU12(UChar
* p
, UInt rt
, UInt rs
, UInt opc2
, UInt imm
)
1201 vassert(opc2
< 0x10);
1202 vassert(imm
< 0x1000);
1205 case PU12_ANDI
: /* ANDI */
1206 case PU12_ADDIU_NEG
: /* ADDIU_NEG */
1207 case PU12_ORI
: /* ORI */
1208 case PU12_SLTIU
: /* SLTIU */
1209 case PU12_XORI
: /* XORI */
1210 case PU12_PROTX
: /* ROTX */
1211 theInstr
= ((PU12
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc2
<< 12) |
1213 return emit32(p
, theInstr
);
1220 static UChar
*mkFormNanoPBR1(UChar
* p
, UInt rt
, UInt rs
, UInt opc2
, UInt imm
)
1225 vassert(opc2
< 0x04);
1226 vassert(imm
< 0x4000);
1228 theInstr
= ((PBR1
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc2
<< 14) |
1229 (imm
& 0x3FFE) | (imm
>> 14));
1230 return emit32(p
, theInstr
);
1233 static UChar
*mkFormNanoPBR2(UChar
* p
, UInt rt
, UInt rs
, UInt opc2
, UInt imm
)
1238 vassert(opc2
< 0x04);
1239 vassert(imm
< 0x4000);
1241 theInstr
= ((PBR2
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc2
<< 14) |
1242 (imm
& 0x3FFE) | (imm
>> 14));
1243 return emit32(p
, theInstr
);
1246 static UChar
*mkFormNanoPLSS9(UChar
* p
, UInt rt
, UInt rs
, nanoPLSS9 opc
,
1247 UInt opc1
, UInt opc2
, UInt imm_ru
)
1252 vassert(opc
< 0x04);
1253 vassert(opc1
< 0x10);
1254 vassert(opc2
< 0x02);
1257 case LL
: /* LL/SC */
1258 vassert(imm_ru
< 0x4000);
1259 theInstr
= ((PLSS9
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc
<< 8) |
1260 (opc1
<< 11) | opc2
| (imm_ru
& 0xFC) | ((imm_ru
& 0x100) << 7));
1262 case LLWP
: /* LLWP/SCWP */
1263 vassert(imm_ru
< 0x20);
1264 theInstr
= ((PLSS9
<< 26) | (rt
<< 21) | (rs
<< 16) | (opc
<< 8) |
1265 (opc1
<< 11) | ( imm_ru
<< 3 ) | opc2
);
1271 return emit32(p
, theInstr
);
1274 static UChar
*doMemAccess_IR(UChar
*p
, UChar sz
, UChar r_dst
,
1275 HReg addr
, Int addr_offset
, Bool isLoad
)
1278 vassert(((UInt
)addr_offset
) < 0x1000);
1280 opc2
= isLoad
? 0x00 : 0x01;
1298 p
= mkFormNano2Regs12imm(p
, 0x21, r_dst
, rA
, opc2
, addr_offset
);
1302 /* Load 32-bit immediate in exactely two 32-bit instructions even if it
1303 could generate fewer. This is needed for generating fixed sized patchable
1305 static inline UChar
* mkLoadImm32_EXACTLY2(UChar
* p
, UInt r_dst
, UInt imm
)
1307 vassert(r_dst
< 0x20);
1308 /* lui r_dst, (imm >> 20) */
1309 p
= mkFormNano1Reg(p
, 0x38, r_dst
, 0, imm
);
1310 /* ori r_dst, r_dst, (imm & 0xFFF) */
1311 p
= mkFormNanoPU12(p
, r_dst
, r_dst
, PU12_ORI
, imm
& 0xFFF);
1315 /* Load imm to r_dst */
1316 static UChar
*mkLoadImm(UChar
* p
, UInt r_dst
, UInt imm
)
1319 if (imm
<= 0xFFFF) {
1320 /* addiu[32] r_dst, 0, imm */
1321 p
= mkFormNano2Regs16imm(p
, 0x00, r_dst
, 0, imm
& 0xFFFF);
1322 } else if (imm
> 0xFFFFF000ULL
) {
1323 /* addiu[neg] r_dst, 0, imm */
1324 p
= mkFormNano2Regs12imm(p
, 0x20, r_dst
, 0, 0x08, (~imm
+ 1) & 0xFFF);
1326 /* lui r_dst, (imm >> 20) */
1327 p
= mkFormNano1Reg(p
, 0x38, r_dst
, 0, imm
);
1331 /* ori r_dst, r_dst, (imm & 0xFFF) */
1332 p
= mkFormNanoPU12(p
, r_dst
, r_dst
, PU12_ORI
, imm
& 0xFFF);
1339 /* Emit an instruction into buf and return the number of bytes used.
1340 Note that buf is not the insn's final place, and therefore it is
1341 imperative to emit position-independent code. If the emitted
1342 instruction was a profiler inc, set *is_profInc to True, else
1343 leave it unchanged. */
1344 Int
emit_NANOMIPSInstr ( /*MB_MOD*/Bool
* is_profInc
,
1345 UChar
* buf
, Int nbuf
,
1346 const NANOMIPSInstr
* i
,
1348 VexEndness endness_host
,
1349 const void* disp_cp_chain_me_to_slowEP
,
1350 const void* disp_cp_chain_me_to_fastEP
,
1351 const void* disp_cp_xindir
,
1352 const void* disp_cp_xassisted
)
1355 vassert(nbuf
>= 32);
1360 UInt r_dst
= iregNo(i
->NMin
.Imm
.dst
);
1361 UInt r_src
= hregIsInvalid(i
->NMin
.Imm
.src
) ?
1362 0 : iregNo(i
->NMin
.Imm
.src
);
1364 switch (i
->NMin
.Imm
.op
) {
1366 p
= mkLoadImm(p
, r_dst
, i
->NMin
.Imm
.imm
);
1372 p
= mkFormNanoPShift(p
, r_dst
, r_src
, i
->NMin
.Imm
.op
,
1377 p
= mkFormNanoPShift(p
, r_dst
, r_src
, NMimm_SLL
,
1378 32 - i
->NMin
.Imm
.imm
);
1379 p
= mkFormNanoPShift(p
, r_dst
, r_dst
, NMimm_SRA
,
1380 32 - i
->NMin
.Imm
.imm
);
1386 p
= mkFormNanoPU12(p
, r_dst
, r_src
, i
->NMin
.Imm
.op
- 0x6,
1390 p
= mkFormNanoPU12(p
, r_dst
, r_src
, PU12_PROTX
, i
->NMin
.Imm
.imm
);
1401 UInt r_dst
= iregNo(i
->NMin
.Alu
.dst
);
1402 UInt r_srcL
= iregNo(i
->NMin
.Alu
.srcL
);
1403 UInt r_srcR
= iregNo(i
->NMin
.Alu
.srcR
);
1405 switch (i
->NMin
.Alu
.op
) {
1406 /* NMalu_ADD, NMalu_SUB, NMalu_AND, NMalu_OR, NMalu_NOR,
1407 NMalu_XOR, NMalu_SLT */
1410 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_ADDU32
);
1415 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SUBU32
);
1420 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_AND32
);
1424 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_OR32
);
1429 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_NOR
);
1434 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_XOR32
);
1438 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SLT
);
1443 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SLLV
);
1448 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SRLV
);
1453 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SRAV
);
1458 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_DIV
);
1463 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_DIVU
);
1468 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MOD
);
1473 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MODU
);
1478 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MUL32
);
1483 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MULU
);
1488 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MUH
);
1493 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_MUHU
);
1504 UInt r_dst
= iregNo(i
->NMin
.Unary
.dst
);
1505 UInt r_src
= iregNo(i
->NMin
.Unary
.src
);
1507 switch (i
->NMin
.Unary
.op
) {
1508 /* NMun_CLO, NMun_CLZ, NMun_NOP */
1509 case NMun_CLO
: /* clo */
1510 p
= mkFormNano2Regs16imm(p
, 0x08, r_dst
, r_src
, 0x4B3F);
1513 case NMun_CLZ
: /* clz */
1514 p
= mkFormNano2Regs16imm(p
, 0x08, r_dst
, r_src
, 0x5B3F);
1517 case NMun_NOP
: /* nop (sll r0,r0,0) */
1518 p
= mkFormNano2Regs16imm(p
, 0x20, 0, 0, 0xC000);
1526 UInt r_srcL
= iregNo(i
->NMin
.Cmp
.srcL
);
1527 UInt r_srcR
= iregNo(i
->NMin
.Cmp
.srcR
);
1528 UInt r_dst
= iregNo(i
->NMin
.Cmp
.dst
);
1530 switch (i
->NMin
.Cmp
.cond
) {
1532 /* xor r_dst, r_srcL, r_srcR
1533 sltiu r_dst, r_dst, 1 */
1534 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_XOR32
);
1535 p
= mkFormNanoPU12(p
, r_dst
, r_dst
, PU12_SLTIU
, 1);
1539 /* xor r_dst, r_srcL, r_srcR
1540 sltu r_dst, zero, r_dst */
1541 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_XOR32
);
1542 p
= mkFormNanoP32A0(p
, r_dst
, 0, r_dst
, _POOL32A0_PSLTU
);
1546 /* slt r_dst, r_srcL, r_srcR */
1547 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_SLT
);
1551 /* sltu r_dst, r_srcL, r_srcR */
1552 p
= mkFormNanoP32A0(p
, r_srcR
, r_srcL
, r_dst
, _POOL32A0_PSLTU
);
1556 /* slt r_dst, r_srcR, r_srcL
1557 xori r_dst, r_dst, 1 */
1558 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_SLT
);
1559 p
= mkFormNanoPU12(p
, r_dst
, r_dst
, PU12_XORI
, 1);
1563 /* sltu r_dst, r_srcR, r_srcL
1564 xori r_dst, r_dst, 1 */
1565 p
= mkFormNanoP32A0(p
, r_srcL
, r_srcR
, r_dst
, _POOL32A0_PSLTU
);
1566 p
= mkFormNanoPU12(p
, r_dst
, r_dst
, PU12_XORI
, 1);
1577 /* If this is conditional, create a conditional
1578 jump over the rest of it. */
1579 if (!hregIsInvalid(i
->NMin
.Call
.guard
)) {
1580 switch (i
->NMin
.Call
.rloc
.pri
) {
1582 /* li $a0, 0x55555555 */
1583 p
= mkLoadImm(p
, 4, 0x55555555);
1585 p
= mkFormNanoP32A0(p
, 0, 4, 5, _POOL32A0_OR32
);
1589 /* li $a1, 0x55555555 */
1590 p
= mkLoadImm(p
, 4, 0x55555555);
1600 /* Skip 3 instructions
1601 beqc $[cond], $0, 12 */
1602 p
= mkFormNanoPBR1(p
, iregNo(i
->NMin
.Call
.guard
), 0,
1606 /* li $25, #target */
1607 p
= mkLoadImm32_EXACTLY2(p
, 25, i
->NMin
.Call
.target
);
1609 p
= mkFormNano2Regs16imm(p
, 0x12, 31, 25, 0);
1614 case NMin_XDirect
: {
1615 /* NB: what goes on here has to be very closely coordinated
1616 with the chainXDirect_NANOMIPS and
1617 unchainXDirect_NANOMIPS below. */
1618 /* We're generating chain-me requests here, so we need to be
1619 sure this is actually allowed -- no-redir translations
1620 can't use chain-me's. Hence: */
1621 vassert(disp_cp_chain_me_to_slowEP
!= NULL
);
1622 vassert(disp_cp_chain_me_to_fastEP
!= NULL
);
1624 /* Use ptmp for backpatching conditional jumps. */
1626 /* If this is conditional, create a conditional
1627 jump over the rest of it. */
1628 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
)) {
1629 /* Skip 6 instructions
1630 beqc $[cond], $0, 24 */
1631 p
= mkFormNanoPBR1(p
, iregNo(i
->NMin
.XDirect
.cond
), 0,
1635 /* Update the guest PC. */
1637 /* sw r9, (offset)addr */
1638 p
= mkLoadImm32_EXACTLY2(p
, 9, i
->NMin
.XDirect
.dstGA
);
1639 p
= doMemAccess_IR(p
, 4, 9, i
->NMin
.XDirect
.addr
,
1640 i
->NMin
.XDirect
.addr_offset
,
1642 /* --- FIRST PATCHABLE BYTE follows --- */
1643 /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
1644 calling to) backs up the return address, so as to find the
1645 address of the first patchable byte. So: don't change the
1646 number of instructions (3) below. */
1647 /* move r9, VG_(disp_cp_chain_me_to_{slowEP,fastEP}) */
1649 const void* disp_cp_chain_me
1650 = i
->NMin
.XDirect
.toFastEP
? disp_cp_chain_me_to_fastEP
1651 : disp_cp_chain_me_to_slowEP
;
1652 p
= mkLoadImm32_EXACTLY2(p
, /*r*/ 9,
1653 (Addr
)disp_cp_chain_me
);
1656 p
= mkFormNano2Regs16imm(p
, 0x12, 31, 9, 0); /* p += 4 */
1657 /* --- END of PATCHABLE BYTES --- */
1663 /* We're generating transfers that could lead indirectly to a
1664 chain-me, so we need to be sure this is actually allowed --
1665 no-redir translations are not allowed to reach normal
1666 translations without going through the scheduler. That means
1667 no XDirects or XIndirs out from no-redir translations.
1669 vassert(disp_cp_xindir
!= NULL
);
1671 /* If this is conditional, create a conditional
1672 jump over the rest of it. */
1673 if (!hregIsInvalid(i
->NMin
.XDirect
.cond
)) {
1674 /* Skip 4 instructions
1675 beqc $[cond], $0, 16 */
1676 p
= mkFormNanoPBR1(p
, iregNo(i
->NMin
.XIndir
.cond
), 0,
1680 /* sw r-dstGA, amPC */
1681 p
= doMemAccess_IR(p
, 4, iregNo(i
->NMin
.XIndir
.dstGA
),
1682 i
->NMin
.XIndir
.addr
,
1683 i
->NMin
.XIndir
.addr_offset
,
1686 /* move r9, VG_(disp_cp_xindir) */
1687 p
= mkLoadImm32_EXACTLY2(p
, /*r*/ 9,
1688 (Addr
)disp_cp_xindir
);
1690 p
= mkFormNano2Regs16imm(p
, 0x12, 31, 9, 0); /* p += 4 */
1695 case NMin_XAssisted
: {
1696 /* First off, if this is conditional, create a conditional jump
1697 over the rest of it. Or at least, leave a space for it that
1698 we will shortly fill in. */
1700 /* If this is conditional, create a conditional
1701 jump over the rest of it. */
1702 if (!hregIsInvalid(i
->NMin
.XAssisted
.cond
)) {
1703 /* Skip 4 instructions
1704 beqc $[cond], $0, 12 */
1705 p
= mkFormNanoPBR1(p
, iregNo(i
->NMin
.XAssisted
.cond
), 0,
1708 /* sw r-dstGA, amPC */
1709 p
= doMemAccess_IR(p
, 4, iregNo(i
->NMin
.XAssisted
.dstGA
),
1710 i
->NMin
.XAssisted
.addr
,
1711 i
->NMin
.XAssisted
.addr_offset
,
1716 switch (i
->NMin
.XAssisted
.jk
) {
1718 trcval
= VEX_TRC_JMP_CLIENTREQ
;
1721 case Ijk_Sys_syscall
:
1722 trcval
= VEX_TRC_JMP_SYS_SYSCALL
;
1725 /* case Ijk_Sys_int128:
1726 trcval = VEX_TRC_JMP_SYS_INT128;
1731 trcval
= VEX_TRC_JMP_YIELD
;
1735 trcval
= VEX_TRC_JMP_EMWARN
;
1739 trcval
= VEX_TRC_JMP_EMFAIL
;
1742 /* case Ijk_MapFail:
1743 trcval = VEX_TRC_JMP_MAPFAIL;
1748 trcval
= VEX_TRC_JMP_NODECODE
;
1751 case Ijk_InvalICache
:
1752 trcval
= VEX_TRC_JMP_INVALICACHE
;
1756 trcval
= VEX_TRC_JMP_NOREDIR
;
1760 trcval
= VEX_TRC_JMP_SIGILL
;
1764 trcval
= VEX_TRC_JMP_SIGTRAP
;
1767 /* case Ijk_SigSEGV:
1768 trcval = VEX_TRC_JMP_SIGSEGV;
1773 trcval
= VEX_TRC_JMP_SIGBUS
;
1776 case Ijk_SigFPE_IntDiv
:
1777 trcval
= VEX_TRC_JMP_SIGFPE_INTDIV
;
1780 case Ijk_SigFPE_IntOvf
:
1781 trcval
= VEX_TRC_JMP_SIGFPE_INTOVF
;
1785 trcval
= VEX_TRC_JMP_BORING
;
1788 /* We don't expect to see the following being assisted.
1793 ppIRJumpKind(i
->NMin
.XAssisted
.jk
);
1794 vpanic("emit_NANOMIPSInstr.NMin_XAssisted: unexpected jump"
1798 vassert(trcval
!= 0);
1799 p
= mkLoadImm32_EXACTLY2(p
, /*r*/ GuestSP
, trcval
);
1801 /* move r9, VG_(disp_cp_xassisted) */
1802 p
= mkLoadImm32_EXACTLY2(p
, /*r*/ 9,
1803 (ULong
)(Addr
)disp_cp_xassisted
);
1805 p
= mkFormNano2Regs16imm(p
, 0x12, 31, 9, 0); /* p += 4 */
1811 p
= doMemAccess_IR(p
, i
->NMin
.Load
.sz
, iregNo(i
->NMin
.Load
.dst
),
1813 i
->NMin
.Load
.addr_offset
,
1819 p
= doMemAccess_IR(p
, i
->NMin
.Store
.sz
, iregNo(i
->NMin
.Store
.src
),
1821 i
->NMin
.Store
.addr_offset
,
1827 p
= mkFormNanoPLSS9(p
, iregNo(i
->NMin
.LoadL
.dst
),
1828 iregNo(i
->NMin
.LoadL
.addr
),
1829 PLSS1
, PLL
, LL
, i
->NMin
.LoadL
.addr_offset
);
1835 p
= mkFormNanoPLSS9(p
, iregNo(i
->NMin
.StoreC
.src
),
1836 iregNo(i
->NMin
.StoreC
.addr
),
1837 PLSS1
, PSC
, PSC
, i
->NMin
.StoreC
.addr_offset
);
1843 vassert((i
->NMin
.Cas
.sz
== 4) || (i
->NMin
.Cas
.sz
== 8));
1844 UInt oldLo
= iregNo(i
->NMin
.Cas
.oldLo
);
1845 UInt addr
= iregNo(i
->NMin
.Cas
.addr
);
1846 UInt expdLo
= iregNo(i
->NMin
.Cas
.expdLo
);
1847 UInt dataLo
= iregNo(i
->NMin
.Cas
.dataLo
);
1848 UInt oldHi
= 0, expdHi
= 0, dataHi
= 0;
1849 if (i
->NMin
.Cas
.sz
== 8) {
1850 oldHi
= iregNo(i
->NMin
.Cas
.oldHi
);
1851 expdHi
= iregNo(i
->NMin
.Cas
.expdHi
);
1852 dataHi
= iregNo(i
->NMin
.Cas
.dataHi
);
1855 if (i
->NMin
.Cas
.sz
== 4) {
1858 * bnec old, expd, end
1861 * movn old, expd, data
1864 p
= mkFormNanoPLSS9(p
, oldLo
, addr
, PLSS1
, PLL
, LL
, 0);
1865 p
= mkFormNanoPBR2(p
, oldLo
, expdLo
, PBR2_BNEC32
, 12);
1866 p
= mkFormNano2Regs16imm(p
, 0x00, oldLo
, oldLo
, 1);
1867 p
= mkFormNanoPLSS9(p
, dataLo
, addr
, PLSS1
, PSC
, SC
, 0);
1868 p
= mkFormNanoP32A0(p
, dataLo
, expdLo
, oldLo
, _POOL32A0_PCMOVE
);
1871 * llwp oldLo, oldHi 0(addr)
1872 * bnec oldLo, expdLo, end
1873 * bnec oldHi, expdHi, end
1874 * addiu oldLo, oldLo, 1
1875 * addiu oldHi, oldHi, 1
1876 * scwp dataLo, dataHi, 0(addr)
1877 * movn oldLo, expdLo, dataLo
1878 * movn oldHi, expdHi, dataHi
1881 p
= mkFormNanoPLSS9(p
, oldLo
, addr
, PLSS1
, PLL
, LLWP
, oldHi
);
1882 p
= mkFormNanoPBR2(p
, oldLo
, expdLo
, PBR2_BNEC32
, 24);
1883 p
= mkFormNanoPBR2(p
, oldHi
, expdHi
, PBR2_BNEC32
, 20);
1884 p
= mkFormNano2Regs16imm(p
, 0x00, oldLo
, oldLo
, 1);
1885 p
= mkFormNano2Regs16imm(p
, 0x00, oldHi
, oldHi
, 1);
1886 p
= mkFormNanoPLSS9(p
, dataLo
, addr
, PLSS1
, PSC
, SCWP
, dataHi
);
1887 p
= mkFormNanoP32A0(p
, dataLo
, expdLo
, oldLo
, _POOL32A0_PCMOVE
);
1888 p
= mkFormNanoP32A0(p
, dataHi
, expdHi
, oldHi
, _POOL32A0_PCMOVE
);
1893 case NMin_MoveCond
: {
1894 UInt r_dst
= iregNo(i
->NMin
.MoveCond
.dst
);
1895 UInt r_src
= iregNo(i
->NMin
.MoveCond
.src
);
1896 UInt r_cond
= iregNo(i
->NMin
.MoveCond
.cond
);
1898 switch (i
->NMin
.MoveCond
.op
) {
1899 case NMMoveCond_movn
: {
1900 p
= mkFormNanoP32A0(p
, r_cond
, r_src
, r_dst
, _POOL32A0_PCMOVE
);
1911 case NMin_EvCheck
: {
1912 /* This requires a 32-bit dec/test in 32 mode. */
1917 bgec r9, zero, nofail
1923 /* lw r9, amCounter */
1924 p
= doMemAccess_IR(p
, 4, /*r*/ 9, i
->NMin
.EvCheck
.r_amCounter
,
1925 i
->NMin
.EvCheck
.offset_amCounter
,
1927 /* addiu r9,r9,-1 */
1928 p
= mkFormNanoPU12(p
, 9, 9, PU12_ADDIU_NEG
, 1);
1929 /* sw r9, amCounter */
1930 p
= doMemAccess_IR(p
, 4, /*r*/ 9, i
->NMin
.EvCheck
.r_amCounter
,
1931 i
->NMin
.EvCheck
.offset_amCounter
,
1933 /* bgec r9, zero, nofail */
1934 p
= emit32(p
, 0x88098008);
1935 /* lw r9, amFailAddr */
1936 p
= doMemAccess_IR(p
, sizeof(Addr
), /*r*/ 9,
1937 i
->NMin
.EvCheck
.r_amFailAddr
,
1938 i
->NMin
.EvCheck
.offset_amFailAddr
,
1941 p
= mkFormNano2Regs16imm(p
, 0x12, 31, 9, 0); /* p += 4 */
1944 vassert(evCheckSzB_NANOMIPS() == (UChar
*)p
- (UChar
*)p0
);
1948 case NMin_ProfInc
: {
1952 addiu r8, r8, 1 # add least significant word
1954 sltiu r1, r8, 1 # set carry-in bit
1959 /* li r9, 0x65556555 */
1960 p
= mkLoadImm32_EXACTLY2(p
, 9, 0x65556555);
1963 p
= mkFormNano2Regs12imm(p
, 0x21, 8, 9, 0x8, 0);
1965 /* addiu r8, r8, 1 */
1966 p
= mkFormNano2Regs16imm(p
, 0x00, 8, 8, 0x01);
1969 p
= mkFormNano2Regs12imm(p
, 0x21, 8, 9, 0x9, 0);
1971 /* sltiu r1, r8, 1 */
1972 p
= mkFormNanoPU12(p
, 1, 8, PU12_SLTIU
, 1);
1975 p
= mkFormNano2Regs12imm(p
, 0x21, 8, 9, 0x8, 4);
1977 /* addu r8, r8, r1 */
1978 p
= mkFormNanoP32A0(p
, 8, 1, 8, _POOL32A0_ADDU32
);
1981 p
= mkFormNano2Regs12imm(p
, 0x21, 8, 9, 0x9, 4);
1991 vex_printf("\n=> ");
1993 vpanic("emit_NANOMIPSInstr");
1994 /* NOTREACHED */ done
:
1995 vassert(p
- &buf
[0] <= 128);
1999 /* How big is an event check? See case for Min_EvCheck in
2000 emit_MIPSInstr just above. That crosschecks what this returns, so
2001 we can tell if we're inconsistent. */
2002 Int
evCheckSzB_NANOMIPS(void)
2007 VexInvalRange
chainXDirect_NANOMIPS(VexEndness endness_host
,
2008 void* place_to_chain
,
2009 const void* disp_cp_chain_me_EXPECTED
,
2010 const void* place_to_jump_to
)
2013 UInt
* p
= (UInt
*)place_to_chain
;
2014 /* li r9, disp_cp_chain_me_EXPECTED */
2015 mkLoadImm32_EXACTLY2((UChar
*)tmp
, 9, (Addr
)disp_cp_chain_me_EXPECTED
);
2017 mkFormNano2Regs16imm((UChar
*)(tmp
+ 2), 0x12, 31, 9, 0);
2018 vassert((tmp
[0] == p
[0]) && (tmp
[1] == p
[1]) && (tmp
[2] == p
[2]));
2019 /* li r9, place_to_jump_to */
2020 mkLoadImm32_EXACTLY2((UChar
*)place_to_chain
, 9, (Addr
)place_to_jump_to
);
2021 VexInvalRange vir
= {(HWord
)place_to_chain
, 8};
2025 /* NB: what goes on here has to be very closely coordinated with the
2026 emitInstr case for XDirect, above. */
2027 VexInvalRange
unchainXDirect_NANOMIPS ( VexEndness endness_host
,
2028 void* place_to_unchain
,
2029 const void* place_to_jump_to_EXPECTED
,
2030 const void* disp_cp_chain_me
)
2033 UInt
* p
= (UInt
*)place_to_unchain
;
2034 /* li r9, disp_cp_chain_me_EXPECTED */
2035 mkLoadImm32_EXACTLY2((UChar
*)tmp
, 9, (Addr
)place_to_jump_to_EXPECTED
);
2037 mkFormNano2Regs16imm((UChar
*)(tmp
+ 2), 0x12, 31, 9, 0);
2038 vassert((tmp
[0] == p
[0]) && (tmp
[1] == p
[1]) && (tmp
[2] == p
[2]));
2039 /* li r9, place_to_jump_to */
2040 mkLoadImm32_EXACTLY2((UChar
*)place_to_unchain
, 9, (Addr
)disp_cp_chain_me
);
2041 VexInvalRange vir
= {(HWord
)place_to_unchain
, 8};
2045 /* Patch the counter address into a profile inc point, as previously
2046 created by the Min_ProfInc case for emit_NANOMIPSInstr. */
2047 VexInvalRange
patchProfInc_NANOMIPS ( VexEndness endness_host
,
2048 void* place_to_patch
,
2049 const ULong
* location_of_counter
)
2052 UInt
* p
= (UInt
*)place_to_patch
;
2054 vassert(endness_host
== VexEndnessLE
|| endness_host
== VexEndnessBE
);
2055 vassert(sizeof(ULong
*) == 4);
2056 vassert(0 == (3 & (HWord
)p
));
2058 mkLoadImm32_EXACTLY2((UChar
*)tmp
, 9, 0x65556555);
2059 mkFormNano2Regs12imm((UChar
*)tmp
, 0x21, 8, 9, 0x8, 0);
2060 mkFormNano2Regs16imm((UChar
*)tmp
, 0x00, 8, 8, 0x01);
2061 mkFormNano2Regs12imm((UChar
*)tmp
, 0x21, 8, 9, 0x9, 0);
2062 mkFormNanoPU12((UChar
*)tmp
, 1, 8, PU12_SLTIU
, 1);
2063 mkFormNano2Regs12imm((UChar
*)tmp
, 0x21, 8, 9, 0x8, 4);
2064 mkFormNanoP32A0((UChar
*)tmp
, 8, 1, 8, _POOL32A0_ADDU32
);
2065 mkFormNano2Regs12imm((UChar
*)tmp
, 0x21, 8, 9, 0x9, 4);
2067 for(int i
= 0; i
< 9; i
++)
2068 vassert(tmp
[i
] == p
[i
]);
2070 /* li r9, place_to_jump_to */
2071 mkLoadImm32_EXACTLY2((UChar
*)place_to_patch
, 9, (Addr
)location_of_counter
);
2072 VexInvalRange vir
= {(HWord
)place_to_patch
, 8};
2076 const RRegUniverse
* getRRegUniverse_NANOMIPS ( Bool mode64
)
2078 /* The real-register universe is a big constant, so we just want to
2079 initialise it once. rRegUniverse_MIPS_initted values: 0=not initted,
2080 1=initted for 32-bit-mode, 2=initted for 64-bit-mode */
2081 static RRegUniverse rRegUniverse_MIPS
;
2082 static UInt rRegUniverse_MIPS_initted
= 0;
2085 RRegUniverse
* ru
= &rRegUniverse_MIPS
;
2087 if (LIKELY(rRegUniverse_MIPS_initted
== 1))
2092 RRegUniverse__init(ru
);
2094 /* Add the registers. The initial segment of this array must be
2095 those available for allocation by reg-alloc, and those that
2096 follow are not available for allocation. */
2097 ru
->allocable_start
[HRcInt32
] = ru
->size
;
2099 for (gpr
= 16; gpr
<= 22; gpr
++) {
2100 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, gpr
, ru
->size
);
2104 for (gpr
= 12; gpr
<= 15; gpr
++) {
2105 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, gpr
, ru
->size
);
2109 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, 24, ru
->size
);
2111 ru
->allocable_end
[HRcInt32
] = ru
->size
;
2113 ru
->allocable
= ++ru
->size
;
2115 for (gpr
= 0; gpr
<= 11; gpr
++) {
2116 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, gpr
, ru
->size
);
2120 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, 23, ru
->size
);
2122 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, 25, ru
->size
);
2124 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, 29, ru
->size
);
2126 ru
->regs
[ru
->size
] = mkHReg(False
, HRcInt32
, 31, ru
->size
);
2129 rRegUniverse_MIPS_initted
= 1;
2131 RRegUniverse__check_is_sane(ru
);
2135 /*---------------------------------------------------------------*/
2136 /*--- end host_NANOMIPS_defs.c ---*/
2137 /*---------------------------------------------------------------*/