mips: Add some missing syscalls for mips32
[valgrind.git] / VEX / priv / host_nanomips_defs.c
blobb356d09d817ee7ac7cc7b4f602f466868bc1865e
1 /*---------------------------------------------------------------*/
2 /*--- begin host_NANOMIPS_defs.c ---*/
3 /*---------------------------------------------------------------*/
5 /*
6 This file is part of Valgrind, a dynamic binary instrumentation
7 framework.
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
24 02111-1307, USA.
26 The GNU General Public License is contained in the file COPYING.
29 #include "libvex_basictypes.h"
30 #include "libvex.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. */
38 #define GuestSP 23
41 NANOMIPSInstr *NANOMIPSInstr_Imm(NANOMIPSImmOp op, HReg dst, HReg src,
42 UInt imm)
44 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
45 i->tag = NMin_Imm;
46 i->NMin.Imm.op = op;
47 i->NMin.Imm.dst = dst;
48 i->NMin.Imm.src = src;
49 i->NMin.Imm.imm = imm;
50 return i;
53 NANOMIPSInstr *NANOMIPSInstr_Alu(NANOMIPSAluOp op, HReg dst, HReg srcL,
54 HReg srcR)
56 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
57 i->tag = NMin_Alu;
58 i->NMin.Alu.op = op;
59 i->NMin.Alu.dst = dst;
60 i->NMin.Alu.srcL = srcL;
61 i->NMin.Alu.srcR = srcR;
62 return i;
65 NANOMIPSInstr *NANOMIPSInstr_Unary(NANOMIPSUnaryOp op, HReg dst, HReg src)
67 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
68 i->tag = NMin_Unary;
69 i->NMin.Unary.op = op;
70 i->NMin.Unary.dst = dst;
71 i->NMin.Unary.src = src;
72 return i;
75 NANOMIPSInstr *NANOMIPSInstr_Cmp(NANOMIPSCondCode cond, HReg dst, HReg srcL,
76 HReg srcR)
78 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
79 i->tag = NMin_Cmp;
80 i->NMin.Cmp.dst = dst;
81 i->NMin.Cmp.srcL = srcL;
82 i->NMin.Cmp.srcR = srcR;
83 i->NMin.Cmp.cond = cond;
84 return i;
87 NANOMIPSInstr *NANOMIPSInstr_Call(Addr target,
88 UInt argiregs, HReg guard, RetLoc rloc)
90 UInt mask;
91 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
92 i->tag = NMin_Call;
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));
102 return i;
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;
115 return i;
118 NANOMIPSInstr *NANOMIPSInstr_XIndir(HReg dstGA, HReg address, Int offset,
119 HReg cond)
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;
127 return i;
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;
140 return i;
143 NANOMIPSInstr *NANOMIPSInstr_Load(UChar sz, HReg dst,
144 HReg addr, Int addr_offset)
146 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
147 i->tag = NMin_Load;
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);
153 return i;
156 NANOMIPSInstr *NANOMIPSInstr_Store(UChar sz, HReg addr, Int addr_offset,
157 HReg src)
159 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
160 i->tag = NMin_Store;
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);
167 return i;
170 NANOMIPSInstr *NANOMIPSInstr_LoadL(UChar sz, HReg dst,
171 HReg addr, Int addr_offset)
173 NANOMIPSInstr *i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
174 i->tag = NMin_LoadL;
175 i->NMin.LoadL.sz = sz;
176 i->NMin.LoadL.addr = addr;
177 i->NMin.LoadL.addr_offset = addr_offset;
178 vassert(sz == 4);
179 return i;
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));
187 i->tag = NMin_Cas;
188 i->NMin.Cas.sz = sz;
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));
196 if (sz == 8) {
197 i->NMin.Cas.oldHi = oldHi;
198 i->NMin.Cas.expdHi = expdHi;
199 i->NMin.Cas.dataHi = dataHi;
201 return i;
204 NANOMIPSInstr *NANOMIPSInstr_StoreC(UChar sz, HReg addr, Int addr_offset,
205 HReg src)
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;
213 vassert(sz == 4);
214 return i;
217 NANOMIPSInstr *NANOMIPSInstr_MoveCond(NANOMIPSMoveCondOp op, HReg dst,
218 HReg src, HReg cond)
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;
226 return i;
229 NANOMIPSInstr *NANOMIPSInstr_EvCheck(HReg r_amCounter,
230 Int offset_amCounter,
231 HReg r_amFailAddr,
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;
240 return i;
243 NANOMIPSInstr* NANOMIPSInstr_ProfInc ( void )
245 NANOMIPSInstr* i = LibVEX_Alloc_inline(sizeof(NANOMIPSInstr));
246 i->tag = NMin_ProfInc;
247 return i;
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"
257 UChar r_no;
259 if (hregIsVirtual(r)) {
260 return ppHReg(r);
263 vassert(hregClass(r) == HRcInt32);
264 r_no = hregEncoding(r);
265 vassert(r_no < 32);
267 return vex_printf("%s", regnames[r_no]);
270 void ppNANOMIPSInstr(const NANOMIPSInstr* i)
272 switch (i->tag) {
273 case NMin_Imm:
274 switch (i->NMin.Imm.op) {
275 case NMimm_SLL:
276 vex_printf("sll ");
277 break;
279 case NMimm_SRL:
280 vex_printf("srl ");
281 break;
283 case NMimm_LI:
284 vex_printf("LI ");
285 break;
287 case NMimm_SRA:
288 vex_printf("sra ");
289 break;
291 case NMimm_SGN:
292 vex_printf("SGN ");
293 break;
295 case NMimm_ORI:
296 vex_printf("ori ");
297 break;
299 case NMimm_XORI:
300 vex_printf("xori ");
301 break;
303 case NMimm_ANDI:
304 vex_printf("andi ");
305 break;
306 case NMimm_ROTX:
307 vex_printf("rotx ");
308 break;
310 default:
311 vassert(0);
314 ppHRegNANOMIPS(i->NMin.Imm.dst);
315 vex_printf(", ");
317 if (i->NMin.Imm.op != NMimm_LI) {
318 ppHRegNANOMIPS(i->NMin.Imm.src);
319 vex_printf(", ");
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);
325 else
326 vex_printf("0x%X (%d)", i->NMin.Imm.imm, (Int)i->NMin.Imm.imm);
327 break;
329 case NMin_Alu:
331 switch (i->NMin.Alu.op) {
332 case NMalu_SLL:
333 vex_printf("sllv ");
334 break;
336 case NMalu_SRL:
337 vex_printf("srlv ");
338 break;
340 case NMalu_SRA:
341 vex_printf("srav ");
342 break;
344 case NMalu_OR:
345 if (sameHReg(i->NMin.Alu.srcL, i->NMin.Alu.srcR))
346 vex_printf("move ");
347 else
348 vex_printf("or ");
350 break;
352 case NMalu_XOR:
353 vex_printf("xor ");
354 break;
356 case NMalu_AND:
357 vex_printf("and ");
358 break;
360 case NMalu_ADD:
361 vex_printf("add ");
362 break;
364 case NMalu_SUB:
365 vex_printf("sub ");
366 break;
368 case NMalu_SLT:
369 vex_printf("slt ");
370 break;
372 case NMalu_NOR:
373 vex_printf("nor ");
374 break;
376 case NMalu_MUL:
377 vex_printf("mul ");
378 break;
380 case NMalu_MULU:
381 vex_printf("mulu ");
382 break;
384 case NMalu_MUH:
385 vex_printf("muh ");
386 break;
388 case NMalu_MUHU:
389 vex_printf("muhu ");
390 break;
392 case NMalu_DIV:
393 vex_printf("div ");
394 break;
396 case NMalu_DIVU:
397 vex_printf("divu ");
398 break;
400 case NMalu_MOD:
401 vex_printf("mod ");
402 break;
404 case NMalu_MODU:
405 vex_printf("modu ");
406 break;
408 default:
409 vassert(0);
412 ppHRegNANOMIPS(i->NMin.Alu.dst);
413 vex_printf(", ");
414 ppHRegNANOMIPS(i->NMin.Alu.srcL);
416 if ((i->NMin.Alu.op != NMalu_OR) ||
417 !sameHReg(i->NMin.Alu.srcL, i->NMin.Alu.srcR)) {
418 vex_printf(", ");
419 ppHRegNANOMIPS(i->NMin.Alu.srcR);
422 break;
424 case NMin_Unary:
425 switch (i->NMin.Unary.op) {
426 case NMun_CLO:
427 vex_printf("clo");
428 break;
430 case NMun_CLZ:
431 vex_printf("clz");
432 break;
434 case NMun_NOP:
435 vex_printf("nop");
436 break;
438 default:
439 vassert(0);
441 if (i->NMin.Unary.op != NMun_NOP)
443 ppHRegNANOMIPS(i->NMin.Unary.dst);
444 vex_printf(",");
445 ppHRegNANOMIPS(i->NMin.Unary.src);
447 break;
448 case NMin_Cmp:
450 switch (i->NMin.Cmp.cond) {
451 case NMcc_EQ:
452 vex_printf("EQ ");
453 break;
455 case NMcc_NE:
456 vex_printf("NE ");
457 break;
459 case NMcc_LTS:
460 vex_printf("LTS ");
461 break;
463 case NMcc_LTU:
464 vex_printf("LTU ");
465 break;
467 case NMcc_LES:
468 vex_printf("LES ");
469 break;
471 case NMcc_LEU:
472 vex_printf("LEU ");
473 break;
475 case NMcc_AL:
476 vex_printf("AL ");
477 break;
479 case NMcc_NV:
480 vex_printf("NV ");
481 break;
483 default:
484 vassert(0);
487 ppHRegNANOMIPS(i->NMin.Cmp.dst);
488 vex_printf(", ");
489 ppHRegNANOMIPS(i->NMin.Cmp.srcL);
490 vex_printf(", ");
491 ppHRegNANOMIPS(i->NMin.Cmp.srcR);
493 break;
495 case NMin_Call:
496 vex_printf("CALL 0x%lX, #%X, ", i->NMin.Call.target,
497 i->NMin.Call.argiregs);
498 ppHRegNANOMIPS(i->NMin.Call.guard);
499 break;
501 case NMin_XDirect:
502 vex_printf("(xDirect) ");
503 if (!hregIsInvalid(i->NMin.XDirect.cond)) {
504 vex_printf("beqc ");
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");
514 break;
516 case NMin_XIndir:
517 vex_printf("(xIndir) ");
518 if (!hregIsInvalid(i->NMin.XIndir.cond)) {
519 vex_printf("beqc ");
520 ppHRegNANOMIPS(i->NMin.XIndir.cond);
521 vex_printf(", zero, 16; ");
523 vex_printf("sw ");
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");
529 break;
531 case NMin_XAssisted:
532 vex_printf("(xAssisted) ");
533 if (!hregIsInvalid(i->NMin.XAssisted.cond)) {
534 vex_printf("beqc ");
535 ppHRegNANOMIPS(i->NMin.XAssisted.cond);
536 vex_printf(", zero, 24; ");
538 vex_printf("sw ");
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");
546 break;
548 case NMin_EvCheck:
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:");
559 break;
561 case NMin_ProfInc:
562 vex_printf("(profInc) li a5, ($NotKnownYet); "
563 "lw a4, 0(a5); "
564 "addiu $a4, a4, 1; "
565 "sw $a4, 0(a5); "
566 "sltiu at, a4, 1; "
567 "lw a4, 4(a5); "
568 "addu a4, a4, at; "
569 "sw a4, 4(a5); " );
570 break;
572 case NMin_Load:
573 switch (i->NMin.Load.sz) {
574 case 1:
575 vex_printf("lb ");
576 break;
578 case 2:
579 vex_printf("lh ");
580 break;
582 case 4:
583 vex_printf("lw ");
584 break;
587 ppHRegNANOMIPS(i->NMin.Load.dst);
588 vex_printf(", (%d)", i->NMin.Load.addr_offset);
589 ppHRegNANOMIPS(i->NMin.Load.addr);
590 break;
592 case NMin_Store:
593 switch (i->NMin.Store.sz) {
594 case 1:
595 vex_printf("sb ");
596 break;
598 case 2:
599 vex_printf("sh ");
600 break;
602 case 4:
603 vex_printf("sw ");
604 break;
607 ppHRegNANOMIPS(i->NMin.Store.src);
608 vex_printf(", (%d)", i->NMin.Store.addr_offset);
609 ppHRegNANOMIPS(i->NMin.Store.addr);
610 break;
612 case NMin_Cas:
613 vex_printf("cas: \n");
614 if (i->NMin.Cas.sz == 4) {
615 vex_printf("ll ");
616 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
617 vex_printf(", 0(");
618 ppHRegNANOMIPS(i->NMin.Cas.addr);
619 vex_printf("); ");
621 vex_printf("bnec ");
622 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
623 vex_printf(", ");
624 ppHRegNANOMIPS(i->NMin.Cas.expdLo);
625 vex_printf(", end; ");
627 vex_printf("addiu ");
628 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
629 vex_printf(", ");
630 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
631 vex_printf(", 1; ");
633 vex_printf("sc ");
634 ppHRegNANOMIPS(i->NMin.Cas.dataLo);
635 vex_printf(", 0(");
636 ppHRegNANOMIPS(i->NMin.Cas.addr);
637 vex_printf("); ");
639 vex_printf("movn ");
640 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
641 vex_printf(", ");
642 ppHRegNANOMIPS(i->NMin.Cas.expdLo);
643 vex_printf(", ");
644 ppHRegNANOMIPS(i->NMin.Cas.dataLo);
645 vex_printf("; end:");
646 } else {
647 vex_printf("llwp ");
648 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
649 vex_printf(", ");
650 ppHRegNANOMIPS(i->NMin.Cas.oldHi);
651 vex_printf(", 0(");
652 ppHRegNANOMIPS(i->NMin.Cas.addr);
653 vex_printf("); ");
655 vex_printf("bnec ");
656 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
657 vex_printf(", ");
658 ppHRegNANOMIPS(i->NMin.Cas.expdLo);
659 vex_printf(", end; ");
661 vex_printf("bnec ");
662 ppHRegNANOMIPS(i->NMin.Cas.oldHi);
663 vex_printf(", ");
664 ppHRegNANOMIPS(i->NMin.Cas.expdHi);
665 vex_printf(", end; ");
667 vex_printf("addiu ");
668 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
669 vex_printf(", ");
670 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
671 vex_printf(", 1; ");
673 vex_printf("addiu ");
674 ppHRegNANOMIPS(i->NMin.Cas.oldHi);
675 vex_printf(", ");
676 ppHRegNANOMIPS(i->NMin.Cas.oldHi);
677 vex_printf(", 1; ");
679 vex_printf("scwp ");
680 ppHRegNANOMIPS(i->NMin.Cas.dataLo);
681 vex_printf(", ");
682 ppHRegNANOMIPS(i->NMin.Cas.dataHi);
683 vex_printf(", 0(");
684 ppHRegNANOMIPS(i->NMin.Cas.addr);
685 vex_printf("); ");
687 vex_printf("movn ");
688 ppHRegNANOMIPS(i->NMin.Cas.oldLo);
689 vex_printf(", ");
690 ppHRegNANOMIPS(i->NMin.Cas.expdLo);
691 vex_printf(", ");
692 ppHRegNANOMIPS(i->NMin.Cas.dataLo);
694 vex_printf("movn ");
695 ppHRegNANOMIPS(i->NMin.Cas.oldHi);
696 vex_printf(", ");
697 ppHRegNANOMIPS(i->NMin.Cas.expdHi);
698 vex_printf(", ");
699 ppHRegNANOMIPS(i->NMin.Cas.dataHi);
700 vex_printf("; end:");
702 break;
704 case NMin_LoadL:
705 vex_printf("ll ");
706 ppHRegNANOMIPS(i->NMin.LoadL.dst);
707 vex_printf(", %d(", i->NMin.LoadL.addr_offset);
708 ppHRegNANOMIPS(i->NMin.LoadL.addr);
709 vex_printf("); ");
710 break;
712 case NMin_StoreC:
713 vex_printf("sc ");
714 ppHRegNANOMIPS(i->NMin.StoreC.src);
715 vex_printf(", %d(", i->NMin.StoreC.addr_offset);
716 ppHRegNANOMIPS(i->NMin.StoreC.addr);
717 vex_printf("); ");
718 break;
720 case NMin_MoveCond:
721 vassert(i->NMin.MoveCond.op == NMMoveCond_movn);
722 vex_printf("movn ");
723 ppHRegNANOMIPS(i->NMin.MoveCond.dst);
724 vex_printf(", ");
725 ppHRegNANOMIPS(i->NMin.MoveCond.src);
726 vex_printf(", ");
727 ppHRegNANOMIPS(i->NMin.MoveCond.cond);
728 break;
732 /* --------- Helpers for register allocation. --------- */
734 void getRegUsage_NANOMIPSInstr(HRegUsage* u, const NANOMIPSInstr* i)
736 initHRegUsage(u);
738 switch (i->tag) {
739 case NMin_Imm:
740 addHRegUse(u, HRmWrite, i->NMin.Imm.dst);
742 if (!hregIsInvalid(i->NMin.Imm.src))
743 addHRegUse(u, HRmRead, i->NMin.Imm.src);
745 return;
747 case NMin_Alu:
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;
760 return;
762 case NMin_Cmp:
763 addHRegUse(u, HRmRead, i->NMin.Cmp.srcL);
764 addHRegUse(u, HRmRead, i->NMin.Cmp.srcR);
765 addHRegUse(u, HRmWrite, i->NMin.Cmp.dst);
766 return;
768 case NMin_Unary:
769 addHRegUse(u, HRmRead, i->NMin.Unary.src);
770 addHRegUse(u, HRmWrite, i->NMin.Unary.dst);
771 return;
773 case NMin_Call: {
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)
815 | (1 << 11))));
816 return;
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. */
824 case NMin_XDirect:
825 addHRegUse(u, HRmRead, i->NMin.XDirect.addr);
827 if (!hregIsInvalid(i->NMin.XDirect.cond))
828 addHRegUse(u, HRmRead, i->NMin.XDirect.cond);
830 return;
832 case NMin_XIndir:
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);
839 return;
841 case NMin_XAssisted:
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);
848 return;
850 case NMin_Load:
851 addHRegUse(u, HRmRead, i->NMin.Load.addr);
852 addHRegUse(u, HRmWrite, i->NMin.Load.dst);
853 return;
855 case NMin_Store:
856 addHRegUse(u, HRmRead, i->NMin.Store.addr);
857 addHRegUse(u, HRmRead, i->NMin.Store.src);
858 return;
860 case NMin_LoadL:
861 addHRegUse(u, HRmRead, i->NMin.LoadL.addr);
862 addHRegUse(u, HRmWrite, i->NMin.LoadL.dst);
863 return;
865 case NMin_Cas:
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);
875 return;
877 case NMin_StoreC:
878 addHRegUse(u, HRmRead, i->NMin.StoreC.addr);
879 addHRegUse(u, HRmWrite, i->NMin.StoreC.src);
880 addHRegUse(u, HRmRead, i->NMin.StoreC.src);
881 return;
883 case NMin_MoveCond:
884 addHRegUse(u, HRmWrite, i->NMin.MoveCond.dst);
885 addHRegUse(u, HRmRead, i->NMin.MoveCond.src);
886 addHRegUse(u, HRmRead, i->NMin.MoveCond.cond);
887 return;
889 case NMin_EvCheck:
890 addHRegUse(u, HRmRead, i->NMin.EvCheck.r_amCounter);
891 addHRegUse(u, HRmRead, i->NMin.EvCheck.r_amFailAddr);
892 return;
894 case NMin_ProfInc:
895 /* does not use any registers. */
896 return;
898 default:
899 ppNANOMIPSInstr(i);
900 vpanic("getRegUsage_NANOMIPSInstr");
901 break;
905 /* local helper */
906 static void mapReg(HRegRemap * m, HReg * r)
908 *r = lookupHRegRemap(m, *r);
911 void mapRegs_NANOMIPSInstr(HRegRemap * m, NANOMIPSInstr * i)
913 switch (i->tag) {
914 case NMin_Imm:
915 mapReg(m, &i->NMin.Imm.dst);
917 if (!hregIsInvalid(i->NMin.Imm.src))
918 mapReg(m, &i->NMin.Imm.src);
920 break;
922 case NMin_Alu:
923 mapReg(m, &i->NMin.Alu.srcL);
924 mapReg(m, &i->NMin.Alu.srcR);
925 mapReg(m, &i->NMin.Alu.dst);
926 return;
928 case NMin_Cmp:
929 mapReg(m, &i->NMin.Cmp.srcL);
930 mapReg(m, &i->NMin.Cmp.srcR);
931 mapReg(m, &i->NMin.Cmp.dst);
932 return;
934 case NMin_Unary:
935 mapReg(m, &i->NMin.Unary.src);
936 mapReg(m, &i->NMin.Unary.dst);
937 return;
939 case NMin_Call: {
940 if (!hregIsInvalid(i->NMin.Call.guard))
941 mapReg(m, &i->NMin.Call.guard);
943 return;
946 case NMin_XDirect:
947 mapReg(m, &i->NMin.XDirect.addr);
949 if (!hregIsInvalid(i->NMin.XDirect.cond))
950 mapReg(m, &i->NMin.XDirect.cond);
952 return;
954 case NMin_XIndir:
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);
961 return;
963 case NMin_XAssisted:
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);
970 return;
972 case NMin_Load:
973 mapReg(m, &i->NMin.Load.addr);
974 mapReg(m, &i->NMin.Load.dst);
975 return;
977 case NMin_Store:
978 mapReg(m, &i->NMin.Store.addr);
979 mapReg(m, &i->NMin.Store.src);
980 return;
982 case NMin_LoadL:
983 mapReg(m, &i->NMin.LoadL.addr);
984 mapReg(m, &i->NMin.LoadL.dst);
985 return;
987 case NMin_Cas:
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);
997 return;
999 case NMin_StoreC:
1000 mapReg(m, &i->NMin.StoreC.addr);
1001 mapReg(m, &i->NMin.StoreC.src);
1002 return;
1004 case NMin_MoveCond:
1005 mapReg(m, &i->NMin.MoveCond.dst);
1006 mapReg(m, &i->NMin.MoveCond.src);
1007 mapReg(m, &i->NMin.MoveCond.cond);
1008 return;
1010 case NMin_EvCheck:
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);
1015 return;
1017 case NMin_ProfInc:
1018 /* does not use any registers. */
1019 return;
1021 default:
1022 ppNANOMIPSInstr(i);
1023 vpanic("mapRegs_NANOMIPSInstr");
1024 break;
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);
1035 vassert(!mode64);
1036 vassert(!hregIsVirtual(rreg));
1037 vassert(hregClass(rreg) == HRcInt32);
1038 *i2 = NULL;
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);
1047 vassert(!mode64);
1048 vassert(!hregIsVirtual(rreg));
1049 vassert(hregClass(rreg) == HRcInt32);
1050 *i2 = NULL;
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)
1065 UInt n;
1066 vassert(hregClass(r) == (HRcInt32));
1067 vassert(!hregIsVirtual(r));
1068 n = hregEncoding(r);
1069 vassert(n <= 32);
1070 return n;
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);
1081 #else
1082 *p++ = toUChar((w32 >> 16) & 0x000000FF);
1083 *p++ = toUChar((w32 >> 24) & 0x000000FF);
1084 *p++ = toUChar(w32 & 0x000000FF);
1085 *p++ = toUChar((w32 >> 8) & 0x000000FF);
1086 #endif
1087 return p;
1090 static UChar *mkFormNano2Regs12imm(UChar * p, UInt opc, UInt rt, UInt rs,
1091 UInt opc2, UInt imm)
1093 UInt theInstr;
1094 vassert(opc < 0x40);
1095 vassert(rs < 0x20);
1096 vassert(rt < 0x20);
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,
1104 UShort imm)
1106 UInt theInstr;
1107 vassert(opc < 0x40);
1108 vassert(rs < 0x20);
1109 vassert(rt < 0x20);
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,
1115 UInt imm)
1117 UInt theInstr;
1118 vassert(opc < 0x40);
1119 vassert(rt < 0x20);
1121 switch (opc) {
1122 case 0x38: /* LUI */
1123 theInstr = ((opc << 26) | (rt << 21) | (imm & 0x1FF000) |
1124 ((imm & 0x7FE00000) >> 19) | ((imm & 0x80000000) >> 31));
1125 return emit32(p, theInstr);
1127 default:
1128 vassert(0);
1132 static UChar* mkFormNanoPShift(UChar * p, UInt rt, UInt rs, UInt opc2,
1133 UInt imm)
1135 UInt theInstr;
1136 vassert(rt < 0x20);
1137 vassert(rs < 0x20);
1138 vassert(opc2 < 0x10);
1139 vassert(imm < 0x20);
1141 switch (opc2) {
1142 case PSLL: /* SLL */
1143 case SRL32: /* SRL */
1144 case SRA: /* SRA */
1145 theInstr = ((PU12 << 26) | (rt << 21) | (rs << 16) |
1146 (PU12_PSHIFT << 12) | (opc2 << 5) | (imm));
1147 return emit32(p, theInstr);
1149 default:
1150 vassert(0);
1154 static UChar *mkFormNanoP32A0(UChar * p, UInt rt, UInt rs, UInt rd, UInt opc2)
1156 UInt theInstr;
1157 vassert(rt < 0x20);
1158 vassert(rs < 0x20);
1159 vassert(rd < 0x20);
1160 vassert(opc2 < 0x80);
1162 switch (opc2) {
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) |
1183 (opc2 << 3));
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);
1191 default:
1192 vassert(0);
1196 static UChar *mkFormNanoPU12(UChar * p, UInt rt, UInt rs, UInt opc2, UInt imm)
1198 UInt theInstr;
1199 vassert(rt < 0x20);
1200 vassert(rs < 0x20);
1201 vassert(opc2 < 0x10);
1202 vassert(imm < 0x1000);
1204 switch (opc2) {
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) |
1212 (imm));
1213 return emit32(p, theInstr);
1215 default:
1216 vassert(0);
1220 static UChar *mkFormNanoPBR1(UChar * p, UInt rt, UInt rs, UInt opc2, UInt imm)
1222 UInt theInstr;
1223 vassert(rt < 0x20);
1224 vassert(rs < 0x20);
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)
1235 UInt theInstr;
1236 vassert(rt < 0x20);
1237 vassert(rs < 0x20);
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)
1249 UInt theInstr;
1250 vassert(rt < 0x20);
1251 vassert(rs < 0x20);
1252 vassert(opc < 0x04);
1253 vassert(opc1 < 0x10);
1254 vassert(opc2 < 0x02);
1256 switch (opc2){
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));
1261 break;
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);
1266 break;
1267 default:
1268 vassert(0);
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)
1277 UInt rA, opc2;
1278 vassert(((UInt)addr_offset) < 0x1000);
1279 rA = iregNo(addr);
1280 opc2 = isLoad ? 0x00 : 0x01;
1282 switch (sz) {
1283 case 1:
1284 break;
1286 case 2:
1287 opc2 = opc2 | 0x04;
1288 break;
1290 case 4:
1291 opc2 = opc2 | 0x08;
1292 break;
1294 default:
1295 vassert(0);
1298 p = mkFormNano2Regs12imm(p, 0x21, r_dst, rA, opc2, addr_offset);
1299 return p;
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
1304 sequences. */
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);
1312 return p;
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);
1325 } else {
1326 /* lui r_dst, (imm >> 20) */
1327 p = mkFormNano1Reg(p, 0x38, r_dst, 0, imm);
1328 imm &= 0xFFF;
1330 if (imm != 0) {
1331 /* ori r_dst, r_dst, (imm & 0xFFF) */
1332 p = mkFormNanoPU12(p, r_dst, r_dst, PU12_ORI, imm & 0xFFF);
1336 return p;
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,
1347 Bool mode64,
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 )
1354 UChar *p = &buf[0];
1355 vassert(nbuf >= 32);
1356 vassert(!mode64);
1358 switch (i->tag) {
1359 case NMin_Imm: {
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) {
1365 case NMimm_LI:
1366 p = mkLoadImm(p, r_dst, i->NMin.Imm.imm);
1367 break;
1369 case NMimm_SLL:
1370 case NMimm_SRL:
1371 case NMimm_SRA:
1372 p = mkFormNanoPShift(p, r_dst, r_src, i->NMin.Imm.op,
1373 i->NMin.Imm.imm);
1374 break;
1376 case NMimm_SGN:
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);
1381 break;
1383 case NMimm_ANDI:
1384 case NMimm_ORI:
1385 case NMimm_XORI:
1386 p = mkFormNanoPU12(p, r_dst, r_src, i->NMin.Imm.op - 0x6,
1387 i->NMin.Imm.imm);
1388 break;
1389 case NMimm_ROTX:
1390 p = mkFormNanoPU12(p, r_dst, r_src, PU12_PROTX, i->NMin.Imm.imm);
1391 break;
1393 default:
1394 goto bad;
1397 goto done;
1400 case NMin_Alu: {
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 */
1408 case NMalu_ADD:
1409 /* addu[32] */
1410 p = mkFormNanoP32A0(p, r_srcL, r_srcR, r_dst, _POOL32A0_ADDU32);
1411 break;
1413 case NMalu_SUB:
1414 /* subu[32] */
1415 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SUBU32);
1416 break;
1418 case NMalu_AND:
1419 /* and */
1420 p = mkFormNanoP32A0(p, r_srcL, r_srcR, r_dst, _POOL32A0_AND32);
1421 break;
1423 case NMalu_OR:
1424 p = mkFormNanoP32A0(p, r_srcL, r_srcR, r_dst, _POOL32A0_OR32);
1425 break;
1427 case NMalu_NOR:
1428 /* nor */
1429 p = mkFormNanoP32A0(p, r_srcL, r_srcR, r_dst, _POOL32A0_NOR);
1430 break;
1432 case NMalu_XOR:
1433 /* xor */
1434 p = mkFormNanoP32A0(p, r_srcL, r_srcR, r_dst, _POOL32A0_XOR32);
1435 break;
1437 case NMalu_SLT:
1438 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SLT);
1439 break;
1441 case NMalu_SLL:
1442 /* sllv */
1443 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SLLV);
1444 break;
1446 case NMalu_SRL:
1447 /* srlv */
1448 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SRLV);
1449 break;
1451 case NMalu_SRA:
1452 /* srav */
1453 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SRAV);
1454 break;
1456 case NMalu_DIV:
1457 /* div */
1458 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_DIV);
1459 break;
1461 case NMalu_DIVU:
1462 /* divu */
1463 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_DIVU);
1464 break;
1466 case NMalu_MOD:
1467 /* mod */
1468 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MOD);
1469 break;
1471 case NMalu_MODU:
1472 /* modu */
1473 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MODU);
1474 break;
1476 case NMalu_MUL:
1477 /* mul */
1478 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MUL32);
1479 break;
1481 case NMalu_MULU:
1482 /* mulu */
1483 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MULU);
1484 break;
1486 case NMalu_MUH:
1487 /* muh */
1488 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MUH);
1489 break;
1491 case NMalu_MUHU:
1492 /* muhu */
1493 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_MUHU);
1494 break;
1496 default:
1497 goto bad;
1500 goto done;
1503 case NMin_Unary: {
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);
1511 break;
1513 case NMun_CLZ: /* clz */
1514 p = mkFormNano2Regs16imm(p, 0x08, r_dst, r_src, 0x5B3F);
1515 break;
1517 case NMun_NOP: /* nop (sll r0,r0,0) */
1518 p = mkFormNano2Regs16imm(p, 0x20, 0, 0, 0xC000);
1519 break;
1522 goto done;
1525 case NMin_Cmp: {
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) {
1531 case NMcc_EQ:
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);
1536 break;
1538 case NMcc_NE:
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);
1543 break;
1545 case NMcc_LTS:
1546 /* slt r_dst, r_srcL, r_srcR */
1547 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_SLT);
1548 break;
1550 case NMcc_LTU:
1551 /* sltu r_dst, r_srcL, r_srcR */
1552 p = mkFormNanoP32A0(p, r_srcR, r_srcL, r_dst, _POOL32A0_PSLTU);
1553 break;
1555 case NMcc_LES:
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);
1560 break;
1562 case NMcc_LEU:
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);
1567 break;
1569 default:
1570 goto bad;
1573 goto done;
1576 case NMin_Call: {
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) {
1581 case RLPri_2Int:
1582 /* li $a0, 0x55555555 */
1583 p = mkLoadImm(p, 4, 0x55555555);
1584 /* move $a1, $a0 */
1585 p = mkFormNanoP32A0(p, 0, 4, 5, _POOL32A0_OR32);
1586 break;
1588 case RLPri_Int:
1589 /* li $a1, 0x55555555 */
1590 p = mkLoadImm(p, 4, 0x55555555);
1591 break;
1593 case RLPri_None:
1594 break;
1596 default:
1597 vassert(0);
1600 /* Skip 3 instructions
1601 beqc $[cond], $0, 12 */
1602 p = mkFormNanoPBR1(p, iregNo(i->NMin.Call.guard), 0,
1603 PBR1_BEQC32, 12);
1606 /* li $25, #target */
1607 p = mkLoadImm32_EXACTLY2(p, 25, i->NMin.Call.target);
1608 /* jalrc $25 */
1609 p = mkFormNano2Regs16imm(p, 0x12, 31, 25, 0);
1611 goto done;
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,
1632 PBR1_BEQC32, 24);
1635 /* Update the guest PC. */
1636 /* li r9, dstGA */
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,
1641 False /* Store */);
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}) */
1648 /* jr r9 */
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);
1655 /* jalrc r9 */
1656 p = mkFormNano2Regs16imm(p, 0x12, 31, 9, 0); /* p += 4 */
1657 /* --- END of PATCHABLE BYTES --- */
1659 goto done;
1662 case NMin_XIndir: {
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.
1668 Hence: */
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,
1677 PBR1_BEQC32, 16);
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,
1684 False /* Store */);
1686 /* move r9, VG_(disp_cp_xindir) */
1687 p = mkLoadImm32_EXACTLY2(p, /*r*/ 9,
1688 (Addr)disp_cp_xindir);
1689 /* jalrc r9 */
1690 p = mkFormNano2Regs16imm(p, 0x12, 31, 9, 0); /* p += 4 */
1692 goto done;
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,
1706 PBR1_BEQC32, 24);
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,
1712 False /* Store */);
1714 UInt trcval = 0;
1716 switch (i->NMin.XAssisted.jk) {
1717 case Ijk_ClientReq:
1718 trcval = VEX_TRC_JMP_CLIENTREQ;
1719 break;
1721 case Ijk_Sys_syscall:
1722 trcval = VEX_TRC_JMP_SYS_SYSCALL;
1723 break;
1725 /* case Ijk_Sys_int128:
1726 trcval = VEX_TRC_JMP_SYS_INT128;
1727 break;
1730 case Ijk_Yield:
1731 trcval = VEX_TRC_JMP_YIELD;
1732 break;
1734 case Ijk_EmWarn:
1735 trcval = VEX_TRC_JMP_EMWARN;
1736 break;
1738 case Ijk_EmFail:
1739 trcval = VEX_TRC_JMP_EMFAIL;
1740 break;
1742 /* case Ijk_MapFail:
1743 trcval = VEX_TRC_JMP_MAPFAIL;
1744 break;
1747 case Ijk_NoDecode:
1748 trcval = VEX_TRC_JMP_NODECODE;
1749 break;
1751 case Ijk_InvalICache:
1752 trcval = VEX_TRC_JMP_INVALICACHE;
1753 break;
1755 case Ijk_NoRedir:
1756 trcval = VEX_TRC_JMP_NOREDIR;
1757 break;
1759 case Ijk_SigILL:
1760 trcval = VEX_TRC_JMP_SIGILL;
1761 break;
1763 case Ijk_SigTRAP:
1764 trcval = VEX_TRC_JMP_SIGTRAP;
1765 break;
1767 /* case Ijk_SigSEGV:
1768 trcval = VEX_TRC_JMP_SIGSEGV;
1769 break;
1772 case Ijk_SigBUS:
1773 trcval = VEX_TRC_JMP_SIGBUS;
1774 break;
1776 case Ijk_SigFPE_IntDiv:
1777 trcval = VEX_TRC_JMP_SIGFPE_INTDIV;
1778 break;
1780 case Ijk_SigFPE_IntOvf:
1781 trcval = VEX_TRC_JMP_SIGFPE_INTOVF;
1782 break;
1784 case Ijk_Boring:
1785 trcval = VEX_TRC_JMP_BORING;
1786 break;
1788 /* We don't expect to see the following being assisted.
1789 case Ijk_Ret:
1790 case Ijk_Call:
1791 fallthrough */
1792 default:
1793 ppIRJumpKind(i->NMin.XAssisted.jk);
1794 vpanic("emit_NANOMIPSInstr.NMin_XAssisted: unexpected jump"
1795 "kind");
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);
1804 /* jalrc r9 */
1805 p = mkFormNano2Regs16imm(p, 0x12, 31, 9, 0); /* p += 4 */
1807 goto done;
1810 case NMin_Load:
1811 p = doMemAccess_IR(p, i->NMin.Load.sz, iregNo(i->NMin.Load.dst),
1812 i->NMin.Load.addr,
1813 i->NMin.Load.addr_offset,
1814 True /* Load */);
1815 goto done;
1816 break;
1818 case NMin_Store:
1819 p = doMemAccess_IR(p, i->NMin.Store.sz, iregNo(i->NMin.Store.src),
1820 i->NMin.Store.addr,
1821 i->NMin.Store.addr_offset,
1822 False /* Store */);
1823 goto done;
1824 break;
1826 case NMin_LoadL: {
1827 p = mkFormNanoPLSS9(p, iregNo(i->NMin.LoadL.dst),
1828 iregNo(i->NMin.LoadL.addr),
1829 PLSS1, PLL, LL, i->NMin.LoadL.addr_offset);
1830 goto done;
1831 break;
1834 case NMin_StoreC: {
1835 p = mkFormNanoPLSS9(p, iregNo(i->NMin.StoreC.src),
1836 iregNo(i->NMin.StoreC.addr),
1837 PLSS1, PSC, PSC, i->NMin.StoreC.addr_offset);
1838 goto done;
1839 break;
1842 case NMin_Cas: {
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) {
1857 * ll old, 0(addr)
1858 * bnec old, expd, end
1859 * addiu old, old, 1
1860 * sc data, 0(addr)
1861 * movn old, expd, data
1862 * end:
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);
1869 } else {
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
1879 * end:
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);
1890 goto done;
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);
1901 break;
1904 default:
1905 vassert(0);
1908 goto done;
1911 case NMin_EvCheck: {
1912 /* This requires a 32-bit dec/test in 32 mode. */
1913 /* We generate:
1914 lw r9, amCounter
1915 addiu r9, r9, -1
1916 sw r9, amCounter
1917 bgec r9, zero, nofail
1918 lw r9, amFailAddr
1919 jalrc r9
1920 nofail:
1922 UChar* p0 = p;
1923 /* lw r9, amCounter */
1924 p = doMemAccess_IR(p, 4, /*r*/ 9, i->NMin.EvCheck.r_amCounter,
1925 i->NMin.EvCheck.offset_amCounter,
1926 True /* Load */);
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,
1932 False /* Store */);
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,
1939 True /* Load */);
1940 /* jalrc[32] r9 */
1941 p = mkFormNano2Regs16imm(p, 0x12, 31, 9, 0); /* p += 4 */
1942 /* nofail: */
1943 /* Crosscheck */
1944 vassert(evCheckSzB_NANOMIPS() == (UChar*)p - (UChar*)p0);
1945 goto done;
1948 case NMin_ProfInc: {
1949 /* 32-bit:
1950 li r9, 0x65556555
1951 lw r8, 0(r9)
1952 addiu r8, r8, 1 # add least significant word
1953 sw r8, 0(r9)
1954 sltiu r1, r8, 1 # set carry-in bit
1955 lw r8, 4(r9)
1956 addu r8, r8, r1
1957 sw r8, 4(r9) */
1959 /* li r9, 0x65556555 */
1960 p = mkLoadImm32_EXACTLY2(p, 9, 0x65556555);
1962 /* lw r8, 0(r9) */
1963 p = mkFormNano2Regs12imm(p, 0x21, 8, 9, 0x8, 0);
1965 /* addiu r8, r8, 1 */
1966 p = mkFormNano2Regs16imm(p, 0x00, 8, 8, 0x01);
1968 /* sw r8, 0(r9) */
1969 p = mkFormNano2Regs12imm(p, 0x21, 8, 9, 0x9, 0);
1971 /* sltiu r1, r8, 1 */
1972 p = mkFormNanoPU12(p, 1, 8, PU12_SLTIU, 1);
1974 /* lw r8, 4(r9) */
1975 p = mkFormNano2Regs12imm(p, 0x21, 8, 9, 0x8, 4);
1977 /* addu r8, r8, r1 */
1978 p = mkFormNanoP32A0(p, 8, 1, 8, _POOL32A0_ADDU32);
1980 /* sw r8, 0(r9) */
1981 p = mkFormNano2Regs12imm(p, 0x21, 8, 9, 0x9, 4);
1983 break;
1986 default:
1987 goto bad;
1990 bad:
1991 vex_printf("\n=> ");
1992 ppNANOMIPSInstr(i);
1993 vpanic("emit_NANOMIPSInstr");
1994 /* NOTREACHED */ done:
1995 vassert(p - &buf[0] <= 128);
1996 return p - &buf[0];
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)
2004 return 6 * 4;
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)
2012 UInt tmp[3];
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);
2016 /* jalrc r9 */
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};
2022 return vir;
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)
2032 UInt tmp[3];
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);
2036 /* jalrc r9 */
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};
2042 return vir;
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)
2051 UInt tmp[9];
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};
2073 return vir;
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;
2083 UInt gpr;
2085 RRegUniverse* ru = &rRegUniverse_MIPS;
2087 if (LIKELY(rRegUniverse_MIPS_initted == 1))
2088 return ru;
2090 vassert(!mode64);
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);
2101 ru->size++;
2104 for (gpr = 12; gpr <= 15; gpr++) {
2105 ru->regs[ru->size] = mkHReg(False, HRcInt32, gpr, ru->size);
2106 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);
2117 ru->size++;
2120 ru->regs[ru->size] = mkHReg(False, HRcInt32, 23, ru->size);
2121 ru->size++;
2122 ru->regs[ru->size] = mkHReg(False, HRcInt32, 25, ru->size);
2123 ru->size++;
2124 ru->regs[ru->size] = mkHReg(False, HRcInt32, 29, ru->size);
2125 ru->size++;
2126 ru->regs[ru->size] = mkHReg(False, HRcInt32, 31, ru->size);
2127 ru->size++;
2129 rRegUniverse_MIPS_initted = 1;
2131 RRegUniverse__check_is_sane(ru);
2132 return ru;
2135 /*---------------------------------------------------------------*/
2136 /*--- end host_NANOMIPS_defs.c ---*/
2137 /*---------------------------------------------------------------*/