2 /*--------------------------------------------------------------------*/
3 /*--- begin guest_nanomips_toIR.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2017-2018 RT-RK
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 The GNU General Public License is contained in the file COPYING.
30 /* Translates nanoMIPS code to IR. */
32 #include "libvex_basictypes.h"
33 #include "libvex_ir.h"
35 #include "libvex_guest_mips32.h"
37 #include "main_util.h"
38 #include "main_globals.h"
39 #include "guest_generic_bb_to_IR.h"
40 #include "guest_nanomips_defs.h"
44 #define DIP(format, args...) \
45 if (vex_traceflags & VEX_TRACE_FE) \
46 vex_printf(format, ## args)
48 #define OFFB_PC offsetof(VexGuestMIPS32State, guest_PC)
50 #define ILLEGAL_INSTRUCTON \
51 dres->jk_StopHere = Ijk_SigILL; \
52 dres->whatNext = Dis_StopHere;
54 #define LLADDR_INVALID (mkU32(0xFFFFFFFF))
56 /* MOD: The IRSB* into which we're generating code. */
59 /* CONST: The guest address for the instruction currently being
61 static Addr32 guest_PC_curr_instr
;
63 /* Do a endian load of a 16-bit word, regardless of the endianness of the
65 static inline UShort
getUShort(const UChar
* p
)
71 #elif defined (_MIPSEB)
78 /* Do a endian load of a 32-bit code word. */
79 static inline UInt
getUInt(const UChar
* p
)
81 return (getUShort(p
) << 16) | getUShort(p
+ 2);
84 const UChar GPR3_list
[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
85 const UChar GPR4_list
[] = { 8, 9, 10, 11, 4, 5, 6, 7, 16, 17, 18, 19,
88 const UChar GPR4_zero_list
[] = { 8, 9, 10, 0, 4, 5, 6, 7, 16, 17, 18,
91 const UChar GPR3_src_store_list
[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
92 const UChar GPR2_reg1_list
[] = { 4, 5, 6, 7 };
93 const UChar GPR2_reg2_list
[] = { 5, 6, 7, 8 };
95 static UInt
integerGuestRegOffset(UInt iregNo
)
97 /* Maybe we should use formula ??? */
100 return offsetof(VexGuestMIPS32State
, guest_r0
);
103 return offsetof(VexGuestMIPS32State
, guest_r1
);
106 return offsetof(VexGuestMIPS32State
, guest_r2
);
109 return offsetof(VexGuestMIPS32State
, guest_r3
);
112 return offsetof(VexGuestMIPS32State
, guest_r4
);
115 return offsetof(VexGuestMIPS32State
, guest_r5
);
118 return offsetof(VexGuestMIPS32State
, guest_r6
);
121 return offsetof(VexGuestMIPS32State
, guest_r7
);
124 return offsetof(VexGuestMIPS32State
, guest_r8
);
127 return offsetof(VexGuestMIPS32State
, guest_r9
);
130 return offsetof(VexGuestMIPS32State
, guest_r10
);
133 return offsetof(VexGuestMIPS32State
, guest_r11
);
136 return offsetof(VexGuestMIPS32State
, guest_r12
);
139 return offsetof(VexGuestMIPS32State
, guest_r13
);
142 return offsetof(VexGuestMIPS32State
, guest_r14
);
145 return offsetof(VexGuestMIPS32State
, guest_r15
);
148 return offsetof(VexGuestMIPS32State
, guest_r16
);
151 return offsetof(VexGuestMIPS32State
, guest_r17
);
154 return offsetof(VexGuestMIPS32State
, guest_r18
);
157 return offsetof(VexGuestMIPS32State
, guest_r19
);
160 return offsetof(VexGuestMIPS32State
, guest_r20
);
163 return offsetof(VexGuestMIPS32State
, guest_r21
);
166 return offsetof(VexGuestMIPS32State
, guest_r22
);
169 return offsetof(VexGuestMIPS32State
, guest_r23
);
172 return offsetof(VexGuestMIPS32State
, guest_r24
);
175 return offsetof(VexGuestMIPS32State
, guest_r25
);
178 return offsetof(VexGuestMIPS32State
, guest_r26
);
181 return offsetof(VexGuestMIPS32State
, guest_r27
);
184 return offsetof(VexGuestMIPS32State
, guest_r28
);
187 return offsetof(VexGuestMIPS32State
, guest_r29
);
190 return offsetof(VexGuestMIPS32State
, guest_r30
);
193 return offsetof(VexGuestMIPS32State
, guest_r31
);
200 /* Add a statement to the list held by "irsb". */
201 static void stmt(IRStmt
* st
)
203 addStmtToIRSB(irsb
, st
);
206 static IRExpr
*mkU8(UInt i
)
209 return IRExpr_Const(IRConst_U8((UChar
) i
));
212 /* Create an expression node for a 32-bit integer constant. */
213 static IRExpr
*mkU32(UInt i
)
215 return IRExpr_Const(IRConst_U32(i
));
218 static void putPC(IRExpr
* e
)
220 stmt(IRStmt_Put(OFFB_PC
, e
));
223 static void putIReg(UInt archreg
, IRExpr
* e
)
225 vassert(archreg
< 32);
228 stmt(IRStmt_Put(integerGuestRegOffset(archreg
), e
));
231 static IRExpr
*getIReg(UInt iregNo
)
237 vassert(iregNo
< 32);
238 return IRExpr_Get(integerGuestRegOffset(iregNo
), ty
);
242 static void putLLaddr(IRExpr
* e
)
244 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State
, guest_LLaddr
), e
));
247 static IRExpr
*getLLaddr(void)
249 return IRExpr_Get(offsetof(VexGuestMIPS32State
, guest_LLaddr
), Ity_I32
);
252 static void putLLdata(IRExpr
* e
)
254 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State
, guest_LLdata
), e
));
257 static IRExpr
*getLLdata(void)
259 return IRExpr_Get(offsetof(VexGuestMIPS32State
, guest_LLdata
), Ity_I32
);
262 static void putLLdata64(IRExpr
* e
)
264 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State
, guest_LLdata64
), e
));
267 static IRExpr
*getLLdata64(void)
269 return IRExpr_Get(offsetof(VexGuestMIPS32State
, guest_LLdata64
), Ity_I64
);
272 static IRExpr
*unop(IROp op
, IRExpr
* a
)
274 return IRExpr_Unop(op
, a
);
277 static IRExpr
*binop(IROp op
, IRExpr
* a1
, IRExpr
* a2
)
279 return IRExpr_Binop(op
, a1
, a2
);
282 static IRExpr
*qop(IROp op
, IRExpr
* a1
, IRExpr
* a2
, IRExpr
* a3
, IRExpr
* a4
)
284 return IRExpr_Qop(op
, a1
, a2
, a3
, a4
);
287 /* Generate a new temporary of the given type. */
288 static IRTemp
newTemp(IRType ty
)
290 vassert(isPlausibleIRType(ty
));
291 return newIRTemp(irsb
->tyenv
, ty
);
294 static void assign(IRTemp dst
, IRExpr
* e
)
296 stmt(IRStmt_WrTmp(dst
, e
));
299 static void store(IRExpr
* addr
, IRExpr
* data
)
301 #if defined (_MIPSEL)
302 stmt(IRStmt_Store(Iend_LE
, addr
, data
));
303 #elif defined (_MIPSEB)
304 stmt(IRStmt_Store(Iend_BE
, addr
, data
));
308 static IRExpr
*load(IRType ty
, IRExpr
* addr
)
310 IRExpr
*load1
= NULL
;
311 #if defined (_MIPSEL)
312 load1
= IRExpr_Load(Iend_LE
, ty
, addr
);
313 #elif defined (_MIPSEB)
314 load1
= IRExpr_Load(Iend_BE
, ty
, addr
);
319 static IRExpr
*mkexpr(IRTemp tmp
)
321 return IRExpr_RdTmp(tmp
);
324 static UInt
extend_sign(UInt value
, UChar from_nbits
)
326 UChar shift
= 32 - from_nbits
;
327 return (UInt
)((((Int
) value
) << shift
) >> shift
);
330 static void ir_for_branch(DisResult
*dres
, IRExpr
*guard
, UChar length
,
333 dres
->whatNext
= Dis_StopHere
;
334 dres
->jk_StopHere
= Ijk_Boring
;
335 stmt(IRStmt_Exit(guard
, Ijk_Boring
,
336 IRConst_U32(guest_PC_curr_instr
+ length
+ offset
),
338 putPC(mkU32(guest_PC_curr_instr
+ length
));
341 static void nano_plsu12(DisResult
*dres
, UInt cins
)
343 UChar rs
= (cins
>> 16) & 0x1F;
344 UChar rt
= (cins
>> 21) & 0x1F;
345 UShort u
= cins
& 0x0FFF;
347 switch ((cins
>> 12) & 0x0F) {
348 case PLSU12_LB
: { /* lb[u12] */
349 DIP("lb[u12] r%u %u(r%u)", rt
, u
, rs
);
350 putIReg(rt
, unop(Iop_8Sto32
,
351 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)))));
355 case PLSU12_LH
: { /* lh[u12] */
356 DIP("lh[u12] r%u %u(r%u)", rt
, u
, rs
);
357 putIReg(rt
, unop(Iop_16Sto32
,
358 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)))));
362 case PLSU12_LW
: { /* lw[u12] */
363 DIP("lw[u12] r%u %u(r%u)", rt
, u
, rs
);
364 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
368 case PLSU12_LD
: { /* ld[u12] */
369 DIP("ld[u12] r%u %u(r%u)", rt
, u
, rs
);
374 case PLSU12_SB
: { /* sb[u12] */
375 DIP("sb[12] r%u %u(r%u)", rt
, u
, rs
);
376 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), unop(Iop_32to8
, getIReg(rt
)));
380 case PLSU12_SH
: { /* sh[u12] */
381 DIP("sh[u12] r%u %u(r%u)", rt
, u
, rs
);
382 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), unop(Iop_32to16
, getIReg(rt
)));
386 case PLSU12_SW
: { /* sw[u12] */
387 DIP("sw[u12] r%u, %u(r%u)", rt
, u
, rs
);
388 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
392 case PLSU12_SD
: { /* sd[u12] */
393 DIP("sd[u12] r%u, %u(r%u)", rt
, u
, rs
);
397 case PLSU12_LBU
: { /* lbu[u12] */
398 DIP("lbu r%u, %u(r%u)", rt
, u
, rs
);
399 putIReg(rt
, unop(Iop_8Uto32
,
400 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)))));
404 case PLSU12_LHU
: { /* lhu[u12] */
405 DIP("lhu[u12] r%u %u(r%u)", rt
, u
, rs
);
406 putIReg(rt
, unop(Iop_16Uto32
,
407 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)))));
411 case PLSU12_LWC1
: { /* lwc1[u12] */
412 DIP("lwc1[u12] r%u %u(r%u)", rt
, u
, rs
);
417 case PLSU12_LDC1
: { /* ldc1[u12] */
418 DIP("ldc1[u12] r%u %u(r%u)", rt
, u
, rs
);
423 case PLSU12_PREF
: { /* pref[u12] */
424 DIP("pref[u12] r%u %u(r%u)", rt
, u
, rs
);
428 case PLSU12_LWU
: { /* lwu[u12] */
429 DIP("lwu[u12] r%u %u(r%u)", rt
, u
, rs
);
434 case PLSU12_SWC1
: { /* swc1[u12] */
435 DIP("swc1[u12] r%u %u(r%u)", rt
, u
, rs
);
440 case PLSU12_SDC1
: { /* sdc1[u12] */
441 DIP("sdc1[u12] r%u %u(r%u)", rt
, u
, rs
);
451 static void nano_pl32a0(DisResult
*dres
, UInt cins
)
453 UChar rd
= (cins
>> 11) & 0x1F;
454 UChar rs
= (cins
>> 16) & 0x1F;
455 UChar rt
= (cins
>> 21) & 0x1F;
456 IRTemp t1
= newTemp(Ity_I32
);
457 IRTemp t2
= newTemp(Ity_I64
);
459 switch ((cins
>> 3) & 0x07F) {
460 case _POOL32A0_PTRAP
: {
461 if ((cins
>> 10) & 0x01) { /* tne */
462 DIP("tne r%u, r%u", rs
, rt
);
463 stmt(IRStmt_Exit(binop(Iop_CmpNE32
, getIReg(rs
),
464 getIReg(rt
)), Ijk_SigTRAP
,
465 IRConst_U32(guest_PC_curr_instr
+ 4),
468 UChar trap_code
= (cins
>> 11) & 0x1F;
469 DIP("teq r%u, r%u %u", rs
, rt
, trap_code
);
471 stmt(IRStmt_Exit(binop(Iop_CmpEQ32
, getIReg(rs
),
472 getIReg(rt
)), Ijk_SigFPE_IntDiv
,
473 IRConst_U32(guest_PC_curr_instr
+ 4),
475 else if (trap_code
== 6)
476 stmt(IRStmt_Exit(binop(Iop_CmpEQ32
, getIReg(rs
),
477 getIReg(rt
)), Ijk_SigFPE_IntOvf
,
478 IRConst_U32(guest_PC_curr_instr
+ 4),
481 stmt(IRStmt_Exit(binop(Iop_CmpEQ32
, getIReg(rs
),
482 getIReg(rt
)), Ijk_SigTRAP
,
483 IRConst_U32(guest_PC_curr_instr
+ 4),
490 case _POOL32A0_SEB
: { /* seb */
491 DIP("seb r%u, r%u", rs
, rt
);
492 putIReg(rt
, unop(Iop_8Sto32
, unop(Iop_32to8
, getIReg(rs
))));
496 case _POOL32A0_SEH
: { /* seh */
497 DIP("seh r%u, r%u", rs
, rt
);
498 putIReg(rt
, unop(Iop_16Sto32
, unop(Iop_32to16
, getIReg(rs
))));
502 case _POOL32A0_SLLV
: { /* sllv */
503 DIP("sllv r%u, r%u, r%u", rd
, rs
, rt
);
504 assign(t1
, binop(Iop_And32
, getIReg(rt
), mkU32(0x1f)));
505 putIReg(rd
, binop(Iop_Shl32
, getIReg(rs
), unop(Iop_32to8
,
510 case _POOL32A0_MUL32
: { /* mul */
511 DIP("mul[32] r%u, r%u, r%u", rd
, rs
, rt
);
512 putIReg(rd
, unop(Iop_64to32
, binop(Iop_MullS32
, getIReg(rt
),
517 case _POOL32A0_MUH
: { /* muh */
518 DIP("muh r%u, r%u, r%u", rd
, rs
, rt
);
519 putIReg(rd
, unop(Iop_64HIto32
, binop(Iop_MullS32
, getIReg(rt
),
524 case _POOL32A0_MULU
: { /* mulu */
525 DIP("mulu r%u, r%u, r%u", rd
, rs
, rt
);
526 putIReg(rd
, unop(Iop_64to32
, binop(Iop_MullU32
, getIReg(rt
),
531 case _POOL32A0_MUHU
: { /* muhu */
532 DIP("muhu r%u, r%u, r%u", rd
, rs
, rt
);
533 putIReg(rd
, unop(Iop_64HIto32
, binop(Iop_MullU32
, getIReg(rt
),
538 case _POOL32A0_DIV
: { /* div */
539 DIP("div r%u, r%u, r%u", rd
, rs
, rt
);
540 putIReg(rd
, binop(Iop_DivS32
, getIReg(rs
), getIReg(rt
)));
544 case _POOL32A0_MOD
: { /* mod */
545 DIP("mod r%u, r%u, r%u", rd
, rs
, rt
);
546 putIReg(rd
, unop(Iop_64HIto32
, binop(Iop_DivModS32to32
, getIReg(rs
),
551 case _POOL32A0_DIVU
: { /* divu */
552 DIP("divu r%u, r%u, r%u", rd
, rs
, rt
);
553 putIReg(rd
, binop(Iop_DivU32
, getIReg(rs
), getIReg(rt
)));
557 case _POOL32A0_MODU
: { /* modu */
558 DIP("modu r%u, r%u, r%u", rd
, rs
, rt
);
559 putIReg(rd
, unop(Iop_64HIto32
, binop(Iop_DivModU32to32
, getIReg(rs
),
564 case _POOL32A0_SRLV
: { /* srlv */
565 DIP("srlv r%u, r%u, r%u", rd
, rs
, rt
);
566 assign(t1
, binop(Iop_And32
, getIReg(rt
), mkU32(0x1f)));
567 putIReg(rd
, binop(Iop_Shr32
,
568 getIReg(rs
), unop(Iop_32to8
, mkexpr(t1
))));
572 case _POOL32A0_SRAV
: { /* srav */
573 DIP("srav r%u, r%u, r%u", rd
, rs
, rt
);
574 assign(t1
, binop(Iop_And32
, getIReg(rt
), mkU32(0x1f)));
575 putIReg(rd
, binop(Iop_Sar32
,
576 getIReg(rs
), unop(Iop_32to8
, mkexpr(t1
))));
580 case _POOL32A0_ROTRV
: { /* rotrv */
581 DIP("rotv r%u, r%u, r%u", rd
, rs
, rt
);
582 assign(t1
, binop(Iop_And32
, getIReg(rt
), mkU32(0x1f)));
583 assign(t2
, binop(Iop_32HLto64
, getIReg(rs
), getIReg(rs
)));
584 putIReg(rd
, unop(Iop_64to32
,
586 mkexpr(t2
), unop(Iop_32to8
, mkexpr(t1
)))));
590 case _POOL32A0_AND32
: { /* and[32] */
591 DIP("and[32] r%u, r%u, r%u", rd
, rs
, rt
);
592 putIReg(rd
, binop(Iop_And32
, getIReg(rs
), getIReg(rt
)));
596 case _POOL32A0_ADD
: { /* add */
597 DIP("add r%u, r%u, r%u", rd
, rs
, rt
);
598 // if overflows(sum, nbits=32): raise exception('OV')
599 putIReg(rd
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)));
603 case _POOL32A0_ADDU32
: { /* addu[32] */
604 DIP("addu[32] r%u, r%u, r%u", rd
, rs
, rt
);
605 putIReg(rd
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)));
609 case _POOL32A0_SUB
: { /* sub */
610 DIP("sub r%u, r%u, r%u", rd
, rs
, rt
);
611 // if overflows(result, nbits=32): raise exception('OV')
612 putIReg(rd
, binop(Iop_Sub32
, getIReg(rs
), getIReg(rt
)));
616 case _POOL32A0_SUBU32
: { /* subu[32] */
617 DIP("subu[32] r%u, r%u, r%u", rd
, rs
, rt
);
618 putIReg(rd
, binop(Iop_Sub32
, getIReg(rs
), getIReg(rt
)));
622 case _POOL32A0_OR32
: { /* or[32] */
623 DIP("or[32] r%u, r%u, r%u", rd
, rs
, rt
);
624 putIReg(rd
, binop(Iop_Or32
, getIReg(rs
), getIReg(rt
)));
628 case _POOL32A0_NOR
: { /* nor */
629 DIP("nor r%u, r%u, r%u", rd
, rs
, rt
);
630 putIReg(rd
, unop(Iop_Not32
, binop(Iop_Or32
, getIReg(rs
),
635 case _POOL32A0_XOR32
: { /* xor[32] */
636 DIP("xor[32] r%u, r%u, r%u", rd
, rs
, rt
);
637 putIReg(rd
, binop(Iop_Xor32
, getIReg(rs
), getIReg(rt
)));
641 case _POOL32A0_SLT
: { /* slt */
642 DIP("slt r%u, r%u, r%u", rd
, rs
, rt
);
643 putIReg(rd
, unop(Iop_1Uto32
, binop(Iop_CmpLT32S
, getIReg(rs
),
648 case _POOL32A0_PSLTU
: { /* p.sltu */
652 DIP("sltu r%u, r%u, r%u", rd
, rs
, rt
);
653 putIReg(rd
, unop(Iop_1Uto32
, binop(Iop_CmpLT32U
, getIReg(rs
),
660 case _POOL32A0_SOV
: { /* sov */
661 IRTemp t33
= newTemp(Ity_I32
);
662 IRTemp t0
= newTemp(Ity_I32
);
663 DIP("sov r%u, r%u, r%u", rd
, rs
, rt
);
664 assign(t1
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)));
665 assign(t33
, binop(Iop_Add32
,
666 binop(Iop_Sar32
, getIReg(rs
), mkU8(1)),
667 binop(Iop_Sar32
, getIReg(rt
), mkU8(1))));
668 assign(t0
, binop(Iop_And32
,
670 getIReg(rs
), getIReg(rt
)), mkU32(1)));
671 putIReg(rd
, unop(Iop_1Uto32
,
673 binop(Iop_Sar32
, mkexpr(t1
), mkU8(1)),
674 binop(Iop_Add32
, mkexpr(t33
), mkexpr(t0
)))));
675 // GPR[rd] = 1 if overflows(sum, nbits=32) else 0
679 case _POOL32A0_PCMOVE
: { /* p.cmove */
680 if (cins
& 0x400) { /* movn */
681 DIP("movn r%u, r%u, r%u", rd
, rs
, rt
);
682 putIReg(rd
, IRExpr_ITE(binop(Iop_CmpNE32
, getIReg(rt
), mkU32(0x00)),
683 getIReg(rs
), getIReg(rd
)));
685 DIP("movz r%u, r%u, r%u", rd
, rs
, rt
);
686 putIReg(rd
, IRExpr_ITE(binop(Iop_CmpEQ32
, getIReg(rt
), mkU32(0x00)),
687 getIReg(rs
), getIReg(rd
)));
693 case _POOL32A0_RDHWR
: /* RDHWR */
694 DIP("rdhwr r%u, r%u", rt
, rs
);
697 putIReg(rt
, IRExpr_Get(offsetof(VexGuestMIPS32State
, guest_ULR
),
700 } else if (rs
<= 3) {
701 IRExpr
** arg
= mkIRExprVec_1(mkU32(rs
));
702 IRTemp val
= newTemp(Ity_I32
);
703 IRDirty
*d
= unsafeIRDirty_1_N(val
,
705 "nanomips_dirtyhelper_rdhwr",
706 &nanomips_dirtyhelper_rdhwr
,
708 stmt(IRStmt_Dirty(d
));
709 putIReg(rt
, mkexpr(val
));
712 vex_printf("Unsupported RDHWR variant");
717 vex_printf("Unrecognized _POOL32A0 instruction %08X",
718 (cins
>> 3) & 0x07F);
723 static void nano_pplsx(DisResult
*dres
, UInt cins
)
725 UChar rd
= (cins
>> 11) & 0x1F;
726 UChar rs
= (cins
>> 16) & 0x1F;
727 UChar rt
= (cins
>> 21) & 0x1F;
729 switch ((cins
>> 7) & 0x0F) {
730 case LBX
: { /* lbx */
731 DIP("lbx r%u, %u(r%u)", rd
, rs
, rt
);
732 putIReg(rd
, unop(Iop_8Sto32
,
734 binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)))));
738 case SBX
: { /* sbx */
739 DIP("sbx r%u %u(r%u)", rd
, rs
, rt
);
740 store(binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)),
741 unop(Iop_32to8
, getIReg(rd
)));
745 case LBUX
: { /* lbux */
746 DIP("lbux r%u, %u(r%u)", rd
, rs
, rt
);
747 putIReg(rd
, unop(Iop_8Uto32
,
749 binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)))));
754 DIP("lhx r%u, %u(r%u)", rd
, rs
, rt
);
755 putIReg(rd
, unop(Iop_16Sto32
,
757 binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)))));
762 DIP("shx r%u %u(r%u)", rd
, rs
, rt
);
763 store(binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)), unop(Iop_32to16
,
769 DIP("lbux r%u, %u(r%u)", rd
, rs
, rt
);
770 putIReg(rd
, unop(Iop_16Uto32
,
772 binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)))));
777 DIP("lwx r%u, %u(r%u)", rd
, rs
, rt
);
778 putIReg(rd
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
))));
783 DIP("swx r%u %u(r%u)", rd
, rs
, rt
);
784 store(binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)), getIReg(rd
));
794 static void nano_pplsxs(DisResult
*dres
, UInt cins
)
796 UChar rd
= (cins
>> 11) & 0x1F;
797 UChar rs
= (cins
>> 16) & 0x1F;
798 UChar rt
= (cins
>> 21) & 0x1F;
800 switch ((cins
>> 7) & 0x0F) {
802 DIP("lhxs r%u, %u(r%u)", rd
, rs
, rt
);
803 putIReg(rd
, unop(Iop_16Sto32
,
806 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x01)),
812 DIP("shxs r%u %u(r%u)", rd
, rs
, rt
);
813 store(binop(Iop_Add32
,
814 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x01)),
816 unop(Iop_32to16
, getIReg(rd
)));
821 DIP("lbuxs r%u, %u(r%u)", rd
, rs
, rt
);
822 putIReg(rd
, unop(Iop_16Uto32
,
825 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x01)),
831 DIP("lwxs[32] r%u, r%u(r%u)", rd
, rs
, rt
);
832 putIReg(rd
, load(Ity_I32
,
834 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x02)),
840 DIP("swxs r%u %u(r%u)", rd
, rs
, rt
);
841 store(binop(Iop_Add32
,
842 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x02)),
854 static void nano_plsx(DisResult
*dres
, UInt cins
)
856 if ((cins
>> 6) & 0x01) {
857 nano_pplsxs(dres
, cins
);
859 nano_pplsx(dres
, cins
);
863 static void nano_pool32Axf_4(DisResult
*dres
, UInt cins
)
865 UChar rs
= (cins
>> 16) & 0x1F;
866 UChar rt
= (cins
>> 21) & 0x1F;
869 switch ((cins
>> 9) & 0x7F) {
870 case nano_POOL32Axf4_CLO
: { /* clo */
871 DIP("clo r%u, r%u", rt
, rs
);
872 t1
= newTemp(Ity_I1
);
873 assign(t1
, binop(Iop_CmpEQ32
, getIReg(rs
), mkU32(0xffffffff)));
874 putIReg(rt
, IRExpr_ITE(mkexpr(t1
),
877 unop(Iop_Not32
, getIReg(rs
)))));
881 case nano_POOL32Axf4_CLZ
: { /* clz */
882 DIP("clz r%u, r%u", rt
, rs
);
883 putIReg(rt
, unop(Iop_Clz32
, getIReg(rs
)));
889 static void nano_p32Axf(DisResult
*dres
, UInt cins
)
891 switch ((cins
>> 6) & 0x7) {
893 nano_pool32Axf_4(dres
, cins
);
901 vex_printf("Unrecognized pool32Axf instruction %08X\n", cins
);
907 static void nano_pool32a7(DisResult
*dres
, UInt cins
)
909 UChar rd
= (cins
>> 11) & 0x1F;
910 UChar rs
= (cins
>> 16) & 0x1F;
911 UChar rt
= (cins
>> 21) & 0x1F;
912 UChar u2
= (cins
>> 9) & 0x03;
913 UChar shift
= (cins
>> 6) & 0x1F;
915 switch ((cins
>> 3) & 7) {
917 nano_plsx(dres
, cins
);
920 case _POOL32A7_LSA
: { /* lsa */
921 DIP("lsa r%u r%u, r%u", rd
, rs
, rt
);
922 putIReg(rd
, binop(Iop_Add32
, binop(Iop_Shl32
, getIReg(rs
), mkU8(u2
)),
927 case _POOL32A7_EXTW
: { /*extw*/
928 DIP("extw r%u r%u, r%u, %u", rd
, rs
, rt
, shift
);
929 IRTemp t1
= newTemp(Ity_I64
);
930 assign(t1
, binop(Iop_32HLto64
, getIReg(rt
), getIReg(rs
)));
931 putIReg(rd
, unop(Iop_64to32
, binop(Iop_Shr64
, mkexpr(t1
),
936 case _POOL32A7_P32Axf
: {
937 nano_p32Axf(dres
, cins
);
942 vex_printf("Unrecognized _POOL32A7 instruction %08X", cins
);
947 static void nano_p32a(DisResult
*dres
, UInt cins
)
949 switch (cins
& 0x7) {
951 nano_pl32a0(dres
, cins
);
955 nano_pool32a7(dres
, cins
);
959 vex_printf("Unrecognized P32A instruction %08X", cins
);
964 static void nano_pbal(DisResult
*dres
, UInt cins
)
966 Int s
= extend_sign((cins
& 0x1FFFFFE) | ((cins
& 1) << 25), 26);
968 if (cins
& 0x2000000) { /* BALC[32] */
969 DIP("balc %0X", guest_PC_curr_instr
+ 4 + s
);
970 putIReg(31, mkU32(guest_PC_curr_instr
+ 4));
971 dres
->jk_StopHere
= Ijk_Call
;
972 } else { /* BC[32] */
973 DIP("bc %0X", guest_PC_curr_instr
+ 4 + s
);
974 dres
->jk_StopHere
= Ijk_Boring
;
977 putPC(mkU32(guest_PC_curr_instr
+ 4 + s
));
978 dres
->whatNext
= Dis_StopHere
;
981 static void nano_ppsr(DisResult
*dres
, UInt cins
)
983 UInt u
= cins
& 0xFF8;
984 UChar count
= (cins
>> 16) & 0x0F;
985 UChar rt
= (cins
>> 21) & 0x1F;
989 switch (cins
& 0x03) {
990 case 0x00: { /* save[32] */
991 DIP("save %u, r%u-r%u", u
, (rt
& 0x1fu
) | (rt
& 0x10u
),
992 ((rt
+ count
- 1) & 0x1fu
) | (rt
& 0x10u
));
994 IRTemp t1
= newTemp(Ity_I32
);
995 assign(t1
, getIReg(29));
997 putIReg(29, binop(Iop_Sub32
, mkexpr(t1
), mkU32(u
)));
999 while (counter
!= count
) {
1000 Bool use_gp
= (cins
& 0x04) && (counter
+ 1 == count
);
1001 UChar this_rt
= use_gp
? 28 : (UChar
)((rt
+ counter
) & 0x1f)
1003 Int offset
= -((counter
+ 1) << 2);
1004 store(binop(Iop_Add32
, mkexpr(t1
), mkU32(offset
)),
1012 case 0x02: /* restore[32] */
1013 jr
= False
; //falls through common restore(.jrc) implementation
1015 case 0x03: { /* restore.jrc[32] */
1016 DIP("restore%s %u, r%u-r%u", jr
? ".jrc" : "", u
,
1017 ((rt
+ count
- 1) & 0x1fu
) | (rt
& 0x10u
),
1018 (rt
& 0x1fu
) | (rt
& 0x10u
));
1020 while (counter
!= count
) {
1021 Bool use_gp
= (cins
& 0x04) && (counter
+ 1 == count
);
1022 UChar this_rt
= use_gp
? 28 : ((rt
+ counter
) & 0x1F) | (rt
& 0x10);
1023 Int offset
= u
- ((counter
+ 1) << 2);
1024 putIReg(this_rt
,load(Ity_I32
, binop(Iop_Add32
,
1025 getIReg(29), mkU32(offset
))));
1026 // if this_rt == 29: raise UNPREDICTABLE()
1030 putIReg(29, binop(Iop_Add32
, getIReg(29), mkU32(u
)));
1034 dres
->whatNext
= Dis_StopHere
;
1035 dres
->jk_StopHere
= Ijk_Ret
;
1046 static void nano_psrf(UInt cins
)
1048 switch (cins
& 0x03) {
1049 case 0x00: { /* savef */
1050 vex_printf("Instruction savef is missing documentation.\n");
1055 case 0x02: { /* restoref */
1056 vex_printf("Instruction restoref is missing documentation.\n");
1066 static void nano_psr(DisResult
*dres
, UInt cins
)
1068 switch ((cins
>> 20) & 0x1) {
1069 case 0x00: /* pp.sr */
1070 nano_ppsr(dres
, cins
);
1073 case 0x01: /* p.sr.f */
1083 static void nano_pri(DisResult
*dres
, UInt cins
)
1085 switch ((cins
>> 19) & 3) {
1091 if (cins
& 0x40000) { /* HYPCALL */
1092 vex_printf("Instruction HYPCALL is missing documentation.\n");
1094 } else { /* SYSCALL[32] */
1095 DIP("syscall %u", cins
& 0x3FFFF);
1096 dres
->jk_StopHere
= Ijk_Sys_syscall
;
1097 dres
->whatNext
= Dis_StopHere
;
1102 case PRI_BREAK
: /* BREAK[32] */
1103 DIP("break %u", cins
& 0x7FFFF);
1104 dres
->jk_StopHere
= Ijk_SigTRAP
;
1105 dres
->whatNext
= Dis_StopHere
;
1109 vex_printf("Instruction SDBBP is not supported.\n");
1118 static void nano_psll(UInt cins
)
1120 UChar rt
= (cins
>> 21) & 0x1F;
1121 UChar rs
= (cins
>> 16) & 0x1F;
1122 UChar shift
= cins
& 0x1F;
1124 if (rt
== 0 && shift
== 0) { /* nop[32] */
1129 if (rt
== 0 && shift
== 3) { /* ehb */
1135 if (rt
== 0 && shift
== 5) { /* pause */
1138 // pause_until_llbit_clears();
1142 if (rt
== 0 && shift
== 6) { /* sync */
1143 DIP("sync 0x%x", rs
);
1144 /* Just ignore it. */
1148 DIP("sll r%u, r%u, %u", rt
, rs
, shift
);
1149 putIReg(rt
, binop(Iop_Shl32
, getIReg(rs
), mkU8(shift
)));
1153 static void nano_pshift(UInt cins
)
1155 UChar rt
= (cins
>> 21) & 0x1F;
1156 UChar rs
= (cins
>> 16) & 0x1F;
1157 UChar shift
= cins
& 0x1F;
1159 switch ((cins
>> 5) & 0xF) {
1160 case PSLL
: { /* p.sll */
1165 case SRL32
: /* srl[32] */
1166 DIP("srl[32] r%u, r%u, %u", rt
, rs
, shift
);
1167 putIReg(rt
, binop(Iop_Shr32
, getIReg(rs
), mkU8(shift
)));
1171 DIP("sra r%u, r%u, %u", rt
, rs
, shift
);
1172 putIReg(rt
, binop(Iop_Sar32
, getIReg(rs
), mkU8(shift
)));
1175 case ROTR
: /* rotr */
1176 DIP("rotr r%u, r%u, %u", rt
, rs
, shift
);
1177 IRTemp t1
= newTemp(Ity_I64
);
1178 assign(t1
, binop(Iop_32HLto64
, getIReg(rs
), getIReg(rs
)));
1179 putIReg(rt
, unop(Iop_64to32
, binop(Iop_Shr64
, mkexpr(t1
),
1183 case DSLL
: { /* dsll */
1184 DIP("dsll r%u, r%u, %u", rt
, rs
, shift
);
1189 case DSLL32
: { /* dsll32 */
1190 DIP("dsll32 r%u, r%u, %u", rt
, rs
, shift
);
1195 case DSRL
: { /* dsrl */
1196 DIP("dsrl r%u, r%u, %u", rt
, rs
, shift
);
1201 case DSRL32
: { /* dsrl32 */
1202 DIP("dsrl32 r%u, r%u, %u", rt
, rs
, shift
);
1207 case DSRA
: { /* dsra */
1208 DIP("dsra r%u, r%u, %u", rt
, rs
, shift
);
1213 case DSRA32
: { /* dsra32 */
1214 DIP("dsra32 r%u, r%u, %u", rt
, rs
, shift
);
1219 case DROTR
: { /* drotr */
1220 DIP("drotr r%u, r%u, %u", rt
, rs
, shift
);
1225 case DROTR32
: { /* drotr32 */
1226 DIP("drotr32 r%u, r%u, %u", rt
, rs
, shift
);
1236 static void nano_protx(UInt cins
)
1238 UChar rt
= (cins
>> 21) & 0x1F;
1239 UChar rs
= (cins
>> 16) & 0x1F;
1240 UChar shift
= cins
& 0x1F;
1241 UChar shiftx
= ((cins
>> 7) & 0xF) << 1;
1242 UChar stripe
= (cins
& 0x40) ? 1 : 0;
1244 switch ((cins
>> 5) & 0x41) {
1245 case 0x00: { /* rotx */
1246 DIP("rotx r%u, r%u, %u, %u, %u", rt
, rs
, shift
, shiftx
, stripe
);
1247 putIReg(rt
, qop(Iop_Rotx32
, getIReg(rs
), mkU8(shift
),
1248 mkU8(shiftx
), mkU8(stripe
)));
1259 static void nano_pins(UInt cins
)
1261 UChar rt
= (cins
>> 21) & 0x1F;
1262 UChar rs
= (cins
>> 16) & 0x1F;
1263 UChar lsb
= cins
& 0x1F;
1264 UChar msbd
= (cins
>> 6) & 0x1F;
1266 switch ((cins
>> 5) & 0x41) {
1267 case 0x00: { /* ins */
1268 UChar size
= 1 + msbd
- lsb
;
1269 DIP("ins r%u, r%u, %u, %u", rt
, rs
, lsb
, size
);
1270 UInt mask
= ((1 << size
) - 1) << lsb
;
1271 putIReg(rt
, binop(Iop_Or32
, binop(Iop_And32
, getIReg(rt
),
1275 getIReg(rs
), mkU8(lsb
)),
1280 case 0x01: { /* dins */
1285 case 0x40: { /* dinsm */
1290 case 0x41: { /* dins */
1300 static void nano_pext(UInt cins
)
1302 UChar rt
= (cins
>> 21) & 0x1F;
1303 UChar rs
= (cins
>> 16) & 0x1F;
1304 UChar lsb
= cins
& 0x1F;
1305 UChar msbd
= (cins
>> 6) & 0x1F;
1307 switch ((cins
>> 5) & 0x41) {
1308 case 0x00: { /* ext */
1309 DIP("ext r%u, r%u, %u, %u", rt
, rs
, lsb
, msbd
+ 1u);
1311 if (msbd
+ 1 + lsb
> 32) vassert(0);
1313 putIReg(rt
, binop(Iop_And32
, binop(Iop_Shr32
, getIReg(rs
), mkU8(lsb
)),
1314 mkU32((1 << (msbd
+ 1)) - 1)));
1318 case 0x01: { /* dextu */
1323 case 0x40: { /* dextm */
1328 case 0x41: { /* dext */
1338 static void nano_pool16c00(UInt cins
)
1340 UChar rs
= GPR3_list
[(cins
>> 4) & 0x07];
1341 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
1343 switch (cins
& 0x0C) {
1344 case POOL16C00_NOT
: { /* not[16] */
1345 DIP("not[16] r%u, r%u", rt
, rs
);
1346 putIReg(rt
, unop(Iop_Not32
, getIReg(rs
)));
1350 case POOL16C00_XOR
: { /* xor[16] */
1351 DIP("xor[16] r%u, r%u", rt
, rs
);
1352 putIReg(rt
, binop(Iop_Xor32
, getIReg(rs
), getIReg(rt
)));
1356 case POOL16C00_AND
: { /* and[16] */
1357 DIP("and[16] r%u, r%u", rt
, rs
);
1358 putIReg(rt
, binop(Iop_And32
, getIReg(rs
), getIReg(rt
)));
1362 case POOL16C00_OR
: { /* or[16] */
1363 DIP("or[16] r%u, r%u", rt
, rs
);
1364 putIReg(rt
, binop(Iop_Or32
, getIReg(rs
), getIReg(rt
)));
1370 static void nano_pu12(DisResult
*dres
, UInt cins
)
1372 UChar rs
= (cins
>> 16) & 0x1F;
1373 UChar rt
= (cins
>> 21) & 0x1F;
1374 UShort u
= cins
& 0x0FFF;
1376 switch ((cins
>> 12) & 0x0F) {
1377 case PU12_ORI
: { /* ori */
1378 DIP("ori r%u, r%u, %u", rt
, rs
, u
);
1379 putIReg(rt
, binop(Iop_Or32
, getIReg(rs
), mkU32(u
)));
1383 case PU12_XORI
: { /* xori */
1384 DIP("xori r%u, r%u, %u", rt
, rs
, u
);
1385 putIReg(rt
, binop(Iop_Xor32
, getIReg(rs
), mkU32(u
)));
1389 case PU12_ANDI
: { /* andi */
1390 DIP("andi r%u, r%u, %u", rt
, rs
, u
);
1391 putIReg(rt
, binop(Iop_And32
, getIReg(rs
), mkU32(u
)));
1395 case PU12_PSR
: /* p.sr */
1396 nano_psr(dres
, cins
);
1399 case PU12_SLTI
: { /* slti */
1400 DIP("slti r%u, r%u, %u", rt
, rs
, u
);
1401 putIReg(rt
, unop(Iop_1Uto32
, binop(Iop_CmpLT32S
, getIReg(rs
),
1406 case PU12_SLTIU
: { /* sltiu */
1407 DIP("sltiu r%u, r%u, %u", rt
, rs
, u
);
1408 putIReg(rt
, unop(Iop_1Uto32
, binop(Iop_CmpLT32U
, getIReg(rs
),
1413 case PU12_SEQI
: { /* seqi */
1414 DIP("seqi r%u, r%u, %u", rt
, rs
, u
);
1415 putIReg(rt
, unop(Iop_1Uto32
, binop(Iop_CmpEQ32
, getIReg(rs
),
1420 case PU12_ADDIU_NEG
: { /* addiu[neg] */
1421 DIP("addiu[neg] r%u, r%u, %u", rt
, rs
, u
);
1422 putIReg(rt
, binop(Iop_Sub32
, getIReg(rs
), mkU32(u
)));
1426 case PU12_PSHIFT
: /* p.shift */
1430 case PU12_PROTX
: /* p.rotx */
1434 case PU12_PINS
: /* p.ins */
1438 case PU12_PEXT
: /* p.ext */
1447 static void nano_pbr1(DisResult
*dres
, UInt cins
)
1449 UChar rs
= (cins
>> 16) & 0x1F;
1450 UChar rt
= (cins
>> 21) & 0x1F;
1451 Short s
= (Short
)((cins
& 0x3FFE) |
1452 ((cins
& 1) << 14) | ((cins
& 1) << 15));
1454 switch ((cins
>> 14) & 0x3) {
1455 case PBR1_BEQC32
: { /* BEQC[32] */
1456 DIP("beqc[32] r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1457 ir_for_branch(dres
, binop(Iop_CmpEQ32
, getIReg(rt
), getIReg(rs
)),
1462 case PBR1_PBR3A
: { /* P.BR3A */
1467 case PBR1_BGEC
: { /* BGEC */
1468 DIP("bgec r%u, r%u, %X", rs
, rt
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1469 ir_for_branch(dres
, binop(Iop_CmpLE32S
, getIReg(rt
), getIReg(rs
)),
1474 case PBR1_BGEUC
: { /* bgeuc */
1475 DIP("bgeuc r%u, r%u, %X", rs
, rt
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1476 ir_for_branch(dres
, binop(Iop_CmpLE32U
, getIReg(rt
), getIReg(rs
)),
1482 vex_printf("Unsupported p.br1 instruction %08X", cins
);
1487 static void nano_pbr2(DisResult
*dres
, UInt cins
)
1489 UChar rs
= (cins
>> 16) & 0x1F;
1490 UChar rt
= (cins
>> 21) & 0x1F;
1491 Short s
= (Short
)((cins
& 0x3FFE) |
1492 ((cins
& 1) << 14) | ((cins
& 1) << 15));
1494 switch ((cins
>> 14) & 0x3) {
1495 case PBR2_BNEC32
: { /* BNEC[32] */
1496 DIP("bnec r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1497 ir_for_branch(dres
, binop(Iop_CmpNE32
, getIReg(rt
), getIReg(rs
)),
1502 case PBR2_BLTC
: { /* BLTC */
1503 DIP("bltc r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1504 ir_for_branch(dres
, binop(Iop_CmpLT32S
, getIReg(rs
), getIReg(rt
)),
1509 case PBR2_BLTUC
: { /* BLTUC */
1510 DIP("bltuc r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 4 + (Int
)s
);
1511 ir_for_branch(dres
, binop(Iop_CmpLT32U
, getIReg(rs
), getIReg(rt
)),
1517 vex_printf("Unsupported p.br2 instruction %08X", cins
);
1522 static void nano_pbri(DisResult
*dres
, UInt cins
)
1524 UChar rt
= (cins
>> 21) & 0x1F;
1525 Int s
= extend_sign((cins
& 0x7FE) | ((cins
& 0x01) << 11), 12);
1526 UChar bit
= (cins
>> 11) & 0x3F;
1527 UInt u
= (cins
>> 11) & 0x7F;
1529 switch ((cins
>> 18) & 0x07) {
1531 DIP("beqic r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1532 ir_for_branch(dres
, binop(Iop_CmpEQ32
, getIReg(rt
), mkU32(u
)),
1538 DIP("bbeqzc r%u, %u, %0X", rt
, bit
, guest_PC_curr_instr
+ 4 + s
);
1548 binop(Iop_Shr32
, getIReg(rt
), mkU8(bit
)),
1554 case PBRI_BGEIC
: { /* bgeic */
1555 DIP("bgeic r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1556 ir_for_branch(dres
, binop(Iop_CmpLE32S
, mkU32(u
), getIReg(rt
)),
1561 case PBRI_BGEIUC
: { /* bgeiuc */
1562 DIP("bgeiuc r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1563 ir_for_branch(dres
, binop(Iop_CmpLE32U
, mkU32(u
), getIReg(rt
)),
1569 DIP("bneic r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1571 binop(Iop_CmpNE32
, getIReg(rt
), mkU32(u
)), 4, s
);
1576 DIP("bbnezc r%u, %u, %0X", rt
, bit
, guest_PC_curr_instr
+ 4 + s
);
1586 binop(Iop_Shr32
, getIReg(rt
), mkU8(bit
)),
1593 DIP("bltic r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1594 ir_for_branch(dres
, binop(Iop_CmpLT32S
, getIReg(rt
), mkU32(u
)),
1600 DIP("bltiuc r%u, %u, %0X", rt
, u
, guest_PC_curr_instr
+ 4 + s
);
1601 ir_for_branch(dres
, binop(Iop_CmpLT32U
, getIReg(rt
), mkU32(u
)),
1607 vex_printf("Unsupported p.bri instruction %08X", cins
);
1612 static void nano_pprefs9(DisResult
*dres
, UInt cins
)
1614 UChar hint
= (cins
>> 21) & 0x1F;
1615 UChar rs
= (cins
>> 16) & 0x1F;
1616 UChar s
= extend_sign((cins
& 0xFF) | ((cins
>> 7) & 0x100), 9);
1618 if (hint
== 31) { /* synci */
1619 DIP("synci %u(r%u)", s
, rs
);
1621 } else { /* pref[s9] */
1622 DIP("pref[s9] %u, %u(r%u)", hint
, s
, rs
);
1627 static void nano_plss0(DisResult
*dres
, UInt cins
)
1629 UChar rs
= (cins
>> 16) & 0x1F;
1630 UChar rt
= (cins
>> 21) & 0x1F;
1631 Int s
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFF), 9);
1633 switch ((cins
>> 11) & 0xf) {
1634 case LBS9
: { /* lb[s9] */
1635 DIP("lb[s9] r%u %d(r%u)", rt
, s
, rs
);
1636 putIReg(rt
, unop(Iop_8Sto32
,
1637 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
1642 case LHS9
: { /* lh[s9] */
1643 DIP("lh[s9] r%u %d(r%u)", rt
, s
, rs
);
1644 putIReg(rt
, unop(Iop_16Sto32
,
1645 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
1650 case LWS9
: { /* lw[s9] */
1651 DIP("lw[s9] r%u %d(r%u)", rt
, s
, rs
);
1652 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(s
))));
1656 case LDS9
: { /* ld[s9] */
1657 DIP("ld[s9] r%u %d(r%u)", rt
, s
, rs
);
1662 case SBS9
: { /* sb[s9] */
1663 DIP("sb[s9] r%u %d(r%u)", rt
, s
, rs
);
1664 store(binop(Iop_Add32
, getIReg(rs
), mkU32(s
)), unop(Iop_32to8
,
1669 case SHS9
: { /* sh[s9] */
1670 DIP("sh[s9] r%u %d(r%u)", rt
, s
, rs
);
1671 store(binop(Iop_Add32
, getIReg(rs
), mkU32(s
)), unop(Iop_32to16
,
1676 case SWS9
: { /* sw[s9] */
1677 DIP("sw[s9] r%u %d(r%u)", rt
, s
, rs
);
1678 store(binop(Iop_Add32
, getIReg(rs
), mkU32(s
)), getIReg(rt
));
1682 case SDS9
: { /* sd[s9] */
1683 DIP("sd[s9] r%u %d(r%u)", rt
, s
, rs
);
1688 case LBUS9
: { /* lbu[s9] */
1689 DIP("lbu[s9] r%u %d(r%u)", rt
, s
, rs
);
1690 putIReg(rt
, unop(Iop_8Uto32
,
1691 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
1696 case LHUS9
: { /* lhu[s9] */
1697 DIP("lhu[s9] r%u %d(r%u)", rt
, s
, rs
);
1698 putIReg(rt
, unop(Iop_16Uto32
,
1699 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
1704 case LWC1S9
: { /* lwc1[s9] */
1705 DIP("lwc1[s9] r%u %d(r%u)", rt
, s
, rs
);
1710 case LDC1S9
: { /* ldc1[s9] */
1711 DIP("ldc1[s9] r%u %d(r%u)", rt
, s
, rs
);
1716 case PPREFS9
: { /* p.pref[s9] pool */
1717 nano_pprefs9(dres
, cins
);
1721 case LWUS9
: { /* lwu[s9] */
1722 DIP("lwu[s9] r%u %d(r%u)", rt
, s
, rs
);
1727 case SWC1S9
: { /* swc1[s9] */
1728 DIP("swc1[s9] r%u %d(r%u)", rt
, s
, rs
);
1733 case SDC1S9
: { /* sdc1[s9] */
1734 DIP("sdc1[s9] r%u %d(r%u)", rt
, s
, rs
);
1741 static void nano_pll(DisResult
*dres
, UInt cins
)
1744 UChar rs
= (cins
>> 16) & 0x1F;
1745 UChar rt
= (cins
>> 21) & 0x1F;
1746 UInt s
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFC), 9);
1748 switch (cins
& 0x03) {
1750 DIP("ll r%u %u(r%u)", rt
, s
, rs
);
1751 t1
= newTemp(Ity_I32
);
1752 t2
= newTemp(Ity_I32
);
1753 assign(t1
, binop(Iop_Add32
, getIReg(rs
), mkU32(s
)));
1754 assign(t2
, load(Ity_I32
, mkexpr(t1
)));
1755 putLLaddr(mkexpr(t1
));
1756 putLLdata(mkexpr(t2
));
1757 putIReg(rt
, mkexpr(t2
));
1762 UChar ru
= (cins
>> 3) & 0x1F;
1763 DIP("llwp r%u %u(r%u)", rt
, s
, rs
);
1764 if (rt
== ru
) vassert(0);
1765 t1
= newTemp(Ity_I32
);
1766 t2
= newTemp(Ity_I64
);
1767 assign(t1
, getIReg(rs
));
1768 assign(t2
, load(Ity_I64
, mkexpr(t1
)));
1769 putLLaddr(mkexpr(t1
));
1770 putLLdata64(mkexpr(t2
));
1771 putIReg(rt
, unop(Iop_64to32
, mkexpr(t2
)));
1772 putIReg(ru
, unop(Iop_64HIto32
, mkexpr(t2
)));
1781 static void nano_psc(DisResult
*dres
, UInt cins
)
1783 IRTemp t1
, t2
, t3
, t4
, t5
;
1784 UChar rs
= (cins
>> 16) & 0x1F;
1785 UChar rt
= (cins
>> 21) & 0x1F;
1786 UInt s
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFC), 9);
1788 switch (cins
& 0x03) {
1790 DIP("sc r%u %u(r%u)", rt
, s
, rs
);
1792 t1
= newTemp(Ity_I32
);
1793 t2
= newTemp(Ity_I1
);
1794 t3
= newTemp(Ity_I32
);
1796 assign(t1
, binop(Iop_Add32
, getIReg(rs
), mkU32(s
)));
1798 assign(t2
, binop(Iop_CmpNE32
,
1799 mkexpr(t1
), getLLaddr()));
1800 assign(t3
, getIReg(rt
));
1801 putLLaddr(LLADDR_INVALID
);
1802 putIReg(rt
, getIReg(0));
1804 stmt(IRStmt_Exit(mkexpr(t2
), Ijk_Boring
,
1805 IRConst_U32(guest_PC_curr_instr
+ 4),
1808 t4
= newTemp(Ity_I32
);
1809 t5
= newTemp(Ity_I32
);
1811 assign(t5
, getLLdata());
1813 stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID
, t4
, /* old_mem */
1814 MIPS_IEND
, mkexpr(t1
), /* addr */
1815 NULL
, mkexpr(t5
), /* expected value */
1816 NULL
, mkexpr(t3
) /* new value */)));
1818 putIReg(rt
, unop(Iop_1Uto32
,
1819 binop(Iop_CmpEQ32
, mkexpr(t4
), mkexpr(t5
))));
1824 UChar ru
= (cins
>> 3) & 0x1F;
1825 DIP("scwp r%u %u(r%u)", rt
, s
, rs
);
1826 t1
= newTemp(Ity_I32
);
1827 t2
= newTemp(Ity_I1
);
1829 IRTemp oldHi
, oldLo
, expHi
, expLo
;
1830 oldHi
= newTemp(Ity_I32
);
1831 oldLo
= newTemp(Ity_I32
);
1832 expHi
= newTemp(Ity_I32
);
1833 expLo
= newTemp(Ity_I32
);
1835 assign(t2
, binop(Iop_CmpNE32
,
1836 getIReg(rs
), getLLaddr()));
1838 putLLaddr(LLADDR_INVALID
);
1839 putIReg(rt
, getIReg(0));
1841 stmt(IRStmt_Exit(mkexpr(t2
), Ijk_Boring
,
1842 IRConst_U32(guest_PC_curr_instr
+ 4),
1845 assign(expHi
, unop(Iop_64HIto32
, getLLdata64()));
1846 assign(expLo
, unop(Iop_64to32
, getLLdata64()));
1849 stmt(IRStmt_CAS(mkIRCAS(oldHi
, oldLo
, /* old_mem */
1850 MIPS_IEND
, getIReg(rs
), /* addr */
1851 mkexpr(expHi
), mkexpr(expLo
), /* expected value */
1852 getIReg(ru
), getIReg(rt
) /* new value */)));
1854 putIReg(rt
, binop(Iop_And32
,
1856 binop(Iop_CmpEQ32
, mkexpr(oldHi
), mkexpr(expHi
))),
1858 binop(Iop_CmpEQ32
, mkexpr(oldLo
), mkexpr(expLo
)))));
1867 static void nano_plss1(DisResult
*dres
, UInt cins
)
1869 UChar rs
= (cins
>> 16) & 0x1F;
1870 UChar rt
= (cins
>> 21) & 0x1F;
1871 UInt s
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFF), 9);
1873 switch ((cins
>> 11) & 0x0F) {
1879 case UALH
: { /* ualh */
1880 DIP("ualh r%u %u(r%u)", rt
, s
, rs
);
1881 putIReg(rt
, unop(Iop_16Sto32
,
1882 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
), mkU32(s
)))));
1886 case UASH
: { /* uash */
1887 DIP("uash r%u %u(r%u)", rt
, s
, rs
);
1888 store(binop(Iop_Add32
, getIReg(rs
), mkU32(s
)), unop(Iop_32to16
, getIReg(rt
)));
1892 case CACHE
: { /* cache */
1918 nano_pll(dres
, cins
);
1923 nano_psc(dres
, cins
);
1938 vex_printf("Unrecognized P.LS.S1 instruction %08X", cins
);
1943 static void nano_plswm(DisResult
*dres
, UInt cins
)
1945 UChar rs
= (cins
>> 16) & 0x1F;
1946 UChar rt
= (cins
>> 21) & 0x1F;
1947 Int offset
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFF), 9);
1948 UChar count3
= (cins
>> 12) & 0x07;
1949 UChar count
= count3
? count3
: 8;
1954 if ((cins
>> 11) & 0x01) { /* swm */
1955 DIP("swm r%u, %d(r%u), %u", rt
, offset
, rs
, count
);
1957 while (counter
!= count
) {
1958 rt_tmp
= rt
? (rt
& 0x10) | ((rt
+ counter
) & 0x1F) : 0;
1959 offset_tmp
= offset
+ (counter
<< 2);
1960 store(binop(Iop_Add32
, getIReg(rs
), mkU32(offset_tmp
)),
1965 DIP("lwm r%u, %d(r%u), %u", rt
, offset
, rs
, count
);
1967 while (counter
!= count
) {
1968 rt_tmp
= (rt
& 0x10) | ((rt
+ counter
) & 0x1F);
1969 offset_tmp
= offset
+ (counter
<< 2);
1970 putIReg(rt_tmp
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
),
1971 mkU32(offset_tmp
))));
1973 if ((rt_tmp
== rs
) && (counter
!= count
- 1)) {
1974 // raise UNPREDICTABLE()
1983 static void nano_plsuawm(DisResult
*dres
, UInt cins
)
1985 UChar rs
= (cins
>> 16) & 0x1F;
1986 UChar rt
= (cins
>> 21) & 0x1F;
1987 UInt s
= extend_sign(((cins
>> 7) & 0x100) | (cins
& 0xFF), 9);
1988 UChar count3
= (cins
>> 12) & 0x07;
1989 UChar count
= count3
? count3
: 8;
1992 UChar rt_tmp
, offset_tmp
;
1994 if ((cins
>> 11) & 0x01) { /* uaswm */
1996 DIP("uaswm r%u, %d(r%u), %u", rt
, (int)offset
, rs
, count
);
1998 while (counter
!= count
) {
1999 rt_tmp
= rt
? (rt
& 0x10) | ((rt
+ counter
) & 0x1F) : 0;
2000 offset_tmp
= offset
+ (counter
<< 2);
2001 store(binop(Iop_Add32
, getIReg(rs
), mkU32(offset_tmp
)),
2006 } else { /* ualwm */
2008 DIP("ualwm r%u, %d(r%u), %u", rt
, (int)offset
, rs
, count
);
2010 while (counter
!= count
) {
2011 rt_tmp
= (rt
& 0x10) | ((rt
+ counter
) & 0x1F);
2012 offset_tmp
= offset
+ (counter
<< 2);
2013 putIReg(rt_tmp
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
),
2014 mkU32(offset_tmp
))));
2016 if ((rt_tmp
== rs
) && (counter
!= count
- 1)) {
2018 // raise UNPREDICTABLE()
2026 static void nano_plss9(DisResult
*dres
, UInt cins
)
2028 switch ((cins
>> 8) & 0x7) {
2029 case PLSS0
: { /* p.ls.s0 */
2030 nano_plss0(dres
, cins
);
2035 nano_plss1(dres
, cins
);
2045 nano_plswm(dres
, cins
);
2050 nano_plsuawm(dres
, cins
);
2066 static void nano_p16a1(DisResult
*dres
, UShort cins
)
2068 if (cins
& 0x40) { /* ADDIU[R1.SP] */
2070 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2071 UChar u
= (cins
& 0x3F) << 2;
2072 DIP("ADDIU[R1.SP] r%u, %u", rt
, u
);
2073 putIReg(rt
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)));
2079 static void nano_p16a2(DisResult
*dres
, UShort cins
)
2081 if (cins
& 0x08) { /* P.ADDIU[RS5] */
2082 UChar rt
= (cins
>> 5) & 0x1F;
2084 if (rt
!= 0) { /* ADDIU[RS5] */
2085 Int s
= extend_sign((cins
& 0x07) | ((cins
>> 1) & 0x08), 4);
2086 DIP("addiu r%u, r%u, %d", rt
, rt
, s
);
2087 putIReg(rt
, binop(Iop_Add32
, getIReg(rt
), mkU32(s
)));
2091 } else { /* ADDIU[R2] */
2092 UChar rs
= GPR3_list
[(cins
>> 4) & 0x07];
2093 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2094 UChar u
= (cins
& 0x07) << 2;
2095 DIP("addiu r%u, r%u, 0x%X", rt
, rs
, u
);
2096 putIReg(rt
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)));
2100 static void nano_p16ri(DisResult
*dres
, UShort cins
)
2102 switch ((cins
>> 3) & 0x03) {
2104 if (cins
& 0x4) { /* HYPCALL[16] */
2105 vex_printf("Instruction HYPCALL is missing documentation.\n");
2107 } else { /* SYSCALL[16] */
2108 DIP("syscall %u", cins
& 0x3u
);
2109 dres
->jk_StopHere
= Ijk_Sys_syscall
;
2110 dres
->whatNext
= Dis_StopHere
;
2116 case RI_BREAK
: { /* BREAK[16] */
2117 DIP("break %u", cins
& 0x7u
);
2118 dres
->jk_StopHere
= Ijk_SigTRAP
;
2119 dres
->whatNext
= Dis_StopHere
;
2124 vex_printf("Instruction SDBBP is not supported.\n");
2130 static void nano_p16mv(DisResult
*dres
, UShort cins
)
2132 UChar rs
= cins
& 0x1F;
2133 UChar rt
= (cins
>> 5) & 0x1f;
2136 DIP("move r%u, r%u", rt
, rs
);
2137 putIReg(rt
, getIReg(rs
));
2139 nano_p16ri(dres
, cins
);
2143 static void nano_p16shift(DisResult
*dres
, UShort cins
)
2145 UChar rs
= GPR3_list
[(cins
>> 4) & 0x07];
2146 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2147 UChar shift
= cins
& 0x07;
2149 if (cins
& 0x08) { /* slr[16] */
2150 DIP("slr r%u, r%u, %u ", rt
, rs
, shift
);
2151 putIReg(rt
, binop(Iop_Shr32
, getIReg(rs
), mkU8(shift
!= 0 ? shift
: 8)));
2152 } else { /* sll[16] */
2153 DIP("sll r%u, r%u, %u ", rt
, rs
, shift
);
2154 putIReg(rt
, binop(Iop_Shl32
, getIReg(rs
), mkU8(shift
!= 0 ? shift
: 8)));
2158 static void nano_p16c(DisResult
*dres
, UShort cins
)
2160 switch (cins
& 0x03) {
2161 case 0x00: { /* POOL16C_0 */
2162 nano_pool16c00(cins
);
2167 case 0x03: { /* LWXS[16] */
2168 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2169 UChar rs
= GPR3_list
[(cins
>> 4) & 0x07];
2170 UChar rd
= GPR3_list
[(cins
>> 1) & 0x07];
2171 DIP("lwxs[32] r%u, %u(r%u)", rd
, rs
, rt
);
2172 putIReg(rd
, load(Ity_I32
,
2173 binop(Iop_Add32
, binop(Iop_Shl32
, getIReg(rs
),
2184 static void nano_p16br(DisResult
*dres
, UShort cins
)
2186 UChar u
= (cins
& 0x0f) << 1;
2189 UChar rt
= (cins
>> 5) & 0x1F;
2191 if (cins
& 0x10) { /* JALRC[16] */
2192 DIP("jalrc r%u", rt
);
2193 putIReg(31, mkU32(guest_PC_curr_instr
+ 2));
2194 dres
->jk_StopHere
= Ijk_Call
;
2197 dres
->jk_StopHere
= rt
!= 31 ? Ijk_Boring
: Ijk_Ret
;
2201 dres
->whatNext
= Dis_StopHere
;
2203 UChar rt3
= (cins
>> 7) & 0x07;
2204 UChar rs3
= (cins
>> 4) & 0x07;
2205 UChar rt
= GPR3_list
[rt3
];
2206 UChar rs
= GPR3_list
[rs3
];
2208 if (rs3
< rt3
) { /* beqc[16] */
2209 DIP("beqc r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 2 + u
);
2210 ir_for_branch(dres
, binop(Iop_CmpEQ32
, getIReg(rt
), getIReg(rs
)),
2212 } else { /* bnec[16] */
2213 DIP("bnec r%u, r%u, %X", rt
, rs
, guest_PC_curr_instr
+ 2 + u
);
2214 ir_for_branch(dres
, binop(Iop_CmpNE32
, getIReg(rt
), getIReg(rs
)),
2220 static void nano_p16sr(DisResult
*dres
, UShort cins
)
2222 UChar u
= cins
& 0xF0;
2223 UChar count
= cins
& 0x0F;
2225 UChar rt
= cins
& 0x200 ? 31 : 30;
2227 if (cins
& 0x100) { /* RESTORE.JRC[16] */
2228 DIP("restore.jrc %u, r%u-r%u", u
, (rt
& 0x1fu
) | (rt
& 0x10u
),
2229 ((rt
+ count
- 1) & 0x1fu
) | (rt
& 0x10u
));
2231 while (counter
!= count
) {
2232 UChar this_rt
= ((rt
+ counter
) & 0x1F) | (rt
& 0x10);
2233 Int offset
= u
- ((counter
+ 1) << 2);
2234 putIReg(this_rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(29),
2236 // if this_rt == 29: raise UNPREDICTABLE()
2240 putIReg(29, binop(Iop_Add32
, getIReg(29), mkU32(u
)));
2242 dres
->whatNext
= Dis_StopHere
;
2243 dres
->jk_StopHere
= Ijk_Ret
;
2244 } else { /* SAVE[16] */
2245 DIP("save %u, r%u-r%u", u
, (rt
& 0x1fu
) | (rt
& 0x10u
),
2246 ((rt
+ count
- 1) & 0x1fu
) | (rt
& 0x10u
));
2248 IRTemp t1
= newTemp(Ity_I32
);
2249 assign(t1
, getIReg(29));
2251 putIReg(29, binop(Iop_Sub32
, mkexpr(t1
), mkU32(u
)));
2253 while (counter
!= count
) {
2254 UChar this_rt
= ((rt
+ counter
) & 0x1f) | (rt
& 0x10);
2255 Int offset
= -((counter
+ 1) << 2);
2256 store(binop(Iop_Add32
, mkexpr(t1
), mkU32(offset
)), getIReg(this_rt
));
2262 static void nano_p16lb(DisResult
*dres
, UShort cins
)
2264 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2265 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2266 UChar u
= cins
& 0x3;
2268 switch ((cins
>> 2) & 0x3) {
2269 case 0x0: /* LB[16] */
2270 DIP("lb[16] r%u %u(r%u)", rt
, u
, rs
);
2271 putIReg(rt
, unop(Iop_8Sto32
,
2272 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
2276 case 0x1: /* SB[16] */
2277 rt
= GPR3_src_store_list
[(cins
>> 7) & 0x7];
2278 DIP("sb[16] r%u %u(r%u)", rt
, u
, rs
);
2279 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), unop(Iop_32to8
,
2283 case 0x2: /* LBU[16] */
2284 DIP("lbu[16] r%u %u(r%u)", rt
, u
, rs
);
2285 putIReg(rt
, unop(Iop_8Uto32
,
2286 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
2291 vex_printf("Unrecognized bytes %04x\n", cins
);
2296 static void nano_p16lh(DisResult
*dres
, UShort cins
)
2298 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2299 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2300 UChar u
= cins
& 0x06;
2302 switch (cins
& 0x09) {
2303 case 0x0: /* LH[16] */
2304 DIP("lh[16] r%u %u(r%u)", rt
, u
, rs
);
2305 putIReg(rt
, unop(Iop_16Sto32
,
2306 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
2310 case 0x1: /* SH[16] */
2311 rt
= GPR3_src_store_list
[(cins
>> 7) & 0x7];
2312 DIP("sh[16] r%u %u(r%u)", rt
, u
, rs
);
2313 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), unop(Iop_32to16
,
2317 case 0x8: /* LHU[16] */
2318 DIP("lhu[16] r%u %u(r%u)", rt
, u
, rs
);
2319 putIReg(rt
, unop(Iop_16Uto32
,
2320 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
2325 vex_printf("Unrecognized bytes %04x\n", cins
);
2330 static void nano_p164x4(DisResult
*dres
, UShort cins
)
2332 UChar rt
= GPR4_list
[((cins
>> 6) & 0x08) | ((cins
>> 5) & 0x07)];
2333 UChar rs
= GPR4_list
[((cins
>> 1) & 0x08) | (cins
& 0x07)];
2336 switch (cins
& 0x108) {
2337 case 0x00: { /* ADDU[4x4] */
2338 DIP("addu[4x4] r%u, r%u, r%u", rd
, rs
, rt
);
2339 putIReg(rd
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)));
2343 case 0x08: { /* MUL[4x4] */
2344 DIP("mul[4x4] r%u, r%u, r%u", rd
, rs
, rt
);
2345 putIReg(rd
, binop(Iop_Mul32
, getIReg(rs
), getIReg(rt
)));
2354 static void nano_pgpbh(DisResult
*dres
, UInt cins
)
2356 UChar rt
= (cins
>> 21) & 0x1F;
2358 UInt u
= cins
& 0x3FFFF;
2360 switch ((cins
>> 18) & 7) {
2361 case LBGP
: { /* lb[gp] */
2362 DIP("lb[gp] r%u %u(r%u)", rt
, u
, rs
);
2363 putIReg(rt
, unop(Iop_8Sto32
,
2364 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
2369 case SBGP
: { /* sb[gp] */
2370 DIP("sb[gp] r%u %u(r%u)", rt
, u
, rs
);
2371 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), unop(Iop_32to8
,
2376 case LBUGP
: { /* lbu[gp] */
2377 DIP("lbu[gp] r%u %u(r%u)", rt
, u
, rs
);
2378 putIReg(rt
, unop(Iop_8Uto32
,
2379 load(Ity_I8
, binop(Iop_Add32
, getIReg(rs
),
2384 case ADDIUGPB
: { /* addiu[gp.b] */
2385 DIP("addiu r%u, r%u, 0x%X", rt
, rs
, u
);
2386 putIReg(rt
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)));
2391 if (cins
& 0x01) { /* lhu[gp] */
2392 DIP("lhu[gp] r%u %u(r%u)", rt
, u
, rs
);
2393 putIReg(rt
, unop(Iop_16Uto32
,
2394 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
2395 mkU32(u
& 0x3FFFE)))));
2396 } else { /* lh[gp] */
2397 DIP("lh[gp] r%u %u(r%u)", rt
, u
, rs
);
2398 putIReg(rt
, unop(Iop_16Sto32
,
2399 load(Ity_I16
, binop(Iop_Add32
, getIReg(rs
),
2400 mkU32(u
& 0x3FFFE)))));
2409 } else { /* sh[gp] */
2410 DIP("sh[gp] r%u %u(r%u)", rt
, u
, rs
);
2411 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
& 0x3FFFE)),
2412 unop(Iop_32to16
, getIReg(rt
)));
2430 static void nano_pj(DisResult
*dres
, UInt cins
)
2432 UChar rt
= (cins
>> 21) & 0x1F;
2433 UChar rs
= (cins
>> 16) & 0x1F;
2435 switch ((cins
>> 12) & 0x0F) {
2436 case JALRC32
: { /* JARLC[32] */
2437 DIP("jalrc[32] r%u, r%u", rt
, rs
);
2438 putIReg(rt
, mkU32(guest_PC_curr_instr
+ 4));
2440 dres
->jk_StopHere
= Ijk_Call
;
2441 dres
->whatNext
= Dis_StopHere
;
2446 DIP("jalrc.hb r%u r%u", rt
, rs
);
2447 putIReg(rt
, mkU32(guest_PC_curr_instr
+ 4));
2449 dres
->jk_StopHere
= Ijk_Call
;
2450 dres
->whatNext
= Dis_StopHere
;
2456 if (rt
== 0) { /* brsc */
2457 DIP("brsc r%u", rs
);
2458 IRTemp t1
= newTemp(Ity_I32
);
2459 assign(t1
, binop(Iop_Add32
, mkU32(guest_PC_curr_instr
+ 4),
2460 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x01))));
2462 } else { /* balrsc */
2463 DIP("balrsc r%u, r%u", rs
, rt
);
2464 IRTemp t1
= newTemp(Ity_I32
);
2465 assign(t1
, binop(Iop_Add32
, mkU32(guest_PC_curr_instr
+ 4),
2466 binop(Iop_Shl32
, getIReg(rs
), mkU8(0x01))));
2467 putIReg(rt
, mkU32(guest_PC_curr_instr
+ 4));
2470 dres
->jk_StopHere
= Ijk_Boring
;
2471 dres
->whatNext
= Dis_StopHere
;
2477 static void nano_pgpw(DisResult
*dres
, UInt cins
)
2479 UChar rt
= (cins
>> 21) & 0x1F;
2481 UInt u
= cins
& 0x1FFFFC;
2483 switch (cins
& 0x03) {
2484 case PGPW_ADDIU
: { /* addiu[gp.w] */
2485 DIP("addiu[gp.w] r%u, r%u, %u", rt
, rs
, u
);
2486 putIReg(rt
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)));
2490 case PGPW_LW
: { /* lw[gp] */
2491 DIP("lw[gp] r%u, %u(r%u)", rt
, u
, rs
);
2492 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
2496 case PGPW_SW
: { /* sw[gp] */
2497 DIP("sw[gp] r%u, %u(r%u)", rt
, u
, rs
);
2498 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
2504 static void dis_nanoMIPS16(DisResult
*dres
, UShort cins
)
2506 switch (cins
>> 10) {
2508 nano_p16a2(dres
, cins
);
2512 Int s
= extend_sign((cins
& 0x3FE) | ((cins
& 1) << 10), 11);
2513 DIP("bc %0X", guest_PC_curr_instr
+ 2 + s
);
2514 putPC(mkU32(guest_PC_curr_instr
+ 2 + s
));
2515 dres
->jk_StopHere
= Ijk_Boring
;
2516 dres
->whatNext
= Dis_StopHere
;
2521 nano_p16mv(dres
, cins
);
2525 nano_p16shift(dres
, cins
);
2529 nano_p16c(dres
, cins
);
2533 nano_p16br(dres
, cins
);
2538 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2539 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2540 UChar rd
= GPR3_list
[(cins
>> 1) & 0x7];
2542 if (cins
& 1) { /* SUBU[16] */
2543 DIP("subu r%u, r%u, r%u", rd
, rs
, rt
);
2544 putIReg(rd
, binop(Iop_Sub32
, getIReg(rs
), getIReg(rt
)));
2545 } else { /* ADDU[16] */
2546 DIP("addu r%u, r%u, r%u", rd
, rs
, rt
);
2547 putIReg(rd
, binop(Iop_Add32
, getIReg(rs
), getIReg(rt
)));
2554 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2555 UChar eu
= cins
& 0x7F;
2558 if (eu
== 127) s
= -1;
2561 DIP("li r%u, %d", rt
, s
);
2562 putIReg(rt
, mkU32(s
));
2567 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2568 Int s
= (Char
)((cins
& 0x7E) | (cins
<< 7));
2569 DIP("bnezc r%u, %X", rt
, guest_PC_curr_instr
+ 2 + s
);
2570 ir_for_branch(dres
, binop(Iop_CmpNE32
, getIReg(rt
), mkU32(0)), 2, s
);
2575 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2576 Int s
= (Char
)((cins
& 0x7E) | (cins
<< 7));
2577 DIP("beqzc r%u, %X", rt
, guest_PC_curr_instr
+ 2 + s
);
2578 ir_for_branch(dres
, binop(Iop_CmpEQ32
, getIReg(rt
), mkU32(0)), 2, s
);
2583 nano_p16lb(dres
, cins
);
2587 nano_p16lh(dres
, cins
);
2591 nano_p16sr(dres
, cins
);
2595 nano_p16a1(dres
, cins
);
2598 case ANDI16
: { /* ANDI[16] */
2599 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2600 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2601 UChar eu
= cins
& 0xF;
2604 if (eu
== 12) u
= 0x00FF;
2605 else if (eu
== 13) u
= 0xFFFF;
2608 DIP("andi[16] r%u, r%u, %u", rt
, rs
, u
);
2609 putIReg(rt
, binop(Iop_And32
, getIReg(rs
), mkU32(u
)));
2613 case LW16
: { /* LW[16] */
2614 UChar rt
= GPR3_list
[(cins
>> 7) & 0x7];
2615 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2616 UChar u
= (cins
& 0x0F) << 2;
2617 DIP("lw[16] r%u, %u(r%u)", rt
, u
, rs
);
2618 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
2622 case LWSP
: { /* LW[SP] */
2623 UChar rt
= (cins
>> 5) & 0x1F;
2625 UChar u
= (cins
& 0x1F) << 2;
2626 DIP("lw[SP] r%u, %u(r%u)", rt
, u
, rs
);
2627 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
2631 case LWGP16
: { /* LW[GP16] */
2632 UChar rt
= GPR3_list
[(cins
>> 7) & 0x07];
2634 UInt u
= (cins
& 0x7F) << 2;
2635 DIP("lw[GP16] r%u, %u(r%u)", rt
, u
, rs
);
2636 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
2640 case LW4X4
: { /* LW[4x4] */
2641 UChar rt
= GPR4_list
[((cins
>> 6) & 0x08) | ((cins
>> 5) & 0x07)];
2642 UChar rs
= GPR4_list
[((cins
>> 1) & 0x08) | (cins
& 0x07)];
2643 UChar u
= (cins
& 0x08) | ((cins
>> 6) & 0x04);
2644 DIP("lw[4x4] r%u, %u(r%u)", rt
, u
, rs
);
2645 putIReg(rt
, load(Ity_I32
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
))));
2649 case SW16
: { /* SW[16] */
2650 UChar rt
= GPR3_src_store_list
[(cins
>> 7) & 0x7];
2651 UChar rs
= GPR3_list
[(cins
>> 4) & 0x7];
2652 UChar u
= (cins
& 0x0F) << 2;
2653 DIP("sw[16] r%u, %u(r%u)", rt
, u
, rs
);
2654 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
2658 case SWSP
: { /* SW[SP] */
2659 UChar rt
= (cins
>> 5) & 0x1F;
2661 UChar u
= (cins
& 0x1F) << 2;
2662 DIP("sw[SP] r%u, %u(r%u)", rt
, u
, rs
);
2663 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
2667 case SWGP16
: { /* SW[GP16] */
2668 UChar rt
= GPR3_src_store_list
[(cins
>> 7) & 0x07];
2670 UInt u
= (cins
& 0x7F) << 2;
2671 DIP("sw[GP16] r%u, %u(r%u)", rt
, u
, rs
);
2672 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
2676 case SW4X4
: { /* SW[4x4] */
2677 UChar rt
= GPR4_zero_list
[((cins
>> 6) & 0x08) | ((cins
>> 5) & 0x07)];
2678 UChar rs
= GPR4_list
[((cins
>> 1) & 0x08) | (cins
& 0x07)];
2679 UChar u
= (cins
& 0x08) | ((cins
>> 6) & 0x04);
2680 DIP("sw[4x4] r%u, %u(r%u)", rt
, u
, rs
);
2681 store(binop(Iop_Add32
, getIReg(rs
), mkU32(u
)), getIReg(rt
));
2685 case P164X4
: { /* P16.4X4 pool */
2686 nano_p164x4(dres
, cins
);
2690 case MOVEP
: { /* MOVEP */
2691 UChar rd1
= GPR2_reg1_list
[((cins
>> 2) & 0x02) | ((cins
>> 8) & 0x01)];
2692 UChar rd2
= GPR2_reg2_list
[((cins
>> 2) & 0x02) | ((cins
>> 8) & 0x01)];
2693 UChar rs1
= GPR4_zero_list
[((cins
>> 1) & 0x08) | (cins
& 0x07)];
2694 UChar rs2
= GPR4_zero_list
[((cins
>> 6) & 0x08) | ((cins
>> 5) & 0x07)];
2695 DIP("MOVEP r%u, r%u, r%u, r%u", rd1
, rd2
, rs1
, rs2
);
2696 putIReg(rd1
, getIReg(rs1
));
2697 putIReg(rd2
, getIReg(rs2
));
2701 case MOVEPREV
: { /* MOVEP[REV] */
2702 UChar rd1
= GPR4_list
[((cins
>> 1) & 0x08) | (cins
& 0x07)];
2703 UChar rd2
= GPR4_list
[((cins
>> 6) & 0x08) | ((cins
>> 5) & 0x07)];
2704 UChar rs1
= GPR2_reg1_list
[((cins
>> 2) & 0x02) | ((cins
>> 8) & 0x01)];
2705 UChar rs2
= GPR2_reg2_list
[((cins
>> 2) & 0x02) | ((cins
>> 8) & 0x01)];
2706 DIP("MOVEP r%u, r%u, r%u, r%u", rd1
, rd2
, rs1
, rs2
);
2707 putIReg(rd1
, getIReg(rs1
));
2708 putIReg(rd2
, getIReg(rs2
));
2713 Int s
= extend_sign((cins
& 0x3FE) | ((cins
& 0x1) << 10), 11);
2714 DIP("balc %0X", guest_PC_curr_instr
+ 2 + s
);
2715 putIReg(31, mkU32(guest_PC_curr_instr
+ 2));
2716 putPC(mkU32(guest_PC_curr_instr
+ 2 + s
));
2717 dres
->whatNext
= Dis_StopHere
;
2718 dres
->jk_StopHere
= Ijk_Call
;
2723 vex_printf("Unsupported 16bit: %04X\n", cins
);
2731 static void dis_nanoMIPS32(DisResult
*dres
, UInt cins
)
2734 switch (cins
>> 26) {
2736 UChar rt
= (cins
>> 21) & 0x1F;
2739 UChar rs
= (cins
>> 16) & 0x1F;
2740 UInt u
= cins
& 0xFFFF;
2741 DIP("addiu r%u, r%u, %u", rt
, rs
, u
);
2742 putIReg(rt
, binop(Iop_Add32
, getIReg(rs
), mkU32(u
)));
2744 nano_pri(dres
, cins
);
2751 UChar rt
= (cins
>> 21) & 0x1F;
2752 Int s
= extend_sign((cins
& 0x1FFFFE) | ((cins
& 1) << 21), 22);
2753 DIP("addiupc r%u, 0x%X", rt
, guest_PC_curr_instr
+ 4 + s
);
2754 putIReg(rt
, mkU32(guest_PC_curr_instr
+ 4 + s
));
2759 Int s
= extend_sign((cins
& 0x1FFFFE) | ((cins
& 1) << 21), 22);
2760 UChar rt
= GPR4_zero_list
[((cins
>> 21) & 0x07)
2761 | ((cins
>> 22) & 0x08)];
2762 UChar rd
= (cins
& 0x1000000) ? 5 : 4; /* GPR1_list */
2763 DIP("move.balc r%u, r%u, %0X", rd
, rt
, guest_PC_curr_instr
+ 4 + s
);
2764 putIReg(rd
, getIReg(rt
));
2765 putIReg(31, mkU32(guest_PC_curr_instr
+ 4));
2766 putPC(mkU32(guest_PC_curr_instr
+ 4 + s
));
2767 dres
->jk_StopHere
= Ijk_Call
;
2768 dres
->whatNext
= Dis_StopHere
;
2773 nano_plsu12(dres
, cins
);
2777 nano_pgpw(dres
, cins
);
2781 nano_pu12(dres
, cins
);
2785 nano_p32a(dres
, cins
);
2789 nano_pgpbh(dres
, cins
);
2793 nano_pbal(dres
, cins
);
2797 nano_pbr1(dres
, cins
);
2801 nano_pbr2(dres
, cins
);
2805 nano_pbri(dres
, cins
);
2809 nano_plss9(dres
, cins
);
2813 if (cins
& 0x02) { /* ALUIPC */
2814 UChar rt
= (cins
>> 21) & 0x1F;
2815 UInt s
= (cins
& 0x1FF000) | ((cins
& 0xFFC) << 19) | (cins
<< 31);
2816 DIP("aluipc r%u %08X", rt
, s
);
2817 putIReg(rt
, binop(Iop_And32
, mkU32(guest_PC_curr_instr
+ s
+ 4),
2818 unop(Iop_Not32
, mkU32(0xFFF))));
2820 UChar rt
= (cins
>> 21) & 0x1F;
2821 UInt s
= (cins
& 0x1FF000) | ((cins
& 0xFFC) << 19) | (cins
<< 31);
2822 DIP("lui r%u %08X", rt
, s
);
2823 putIReg(rt
, mkU32(s
));
2829 nano_pj(dres
, cins
);
2834 vex_printf("Unsupported 32bit: %08X\n", cins
);
2842 static void dis_nanoMIPS48(DisResult
*dres
, ULong cins
)
2845 UChar rt
= (cins
>> 37) & 0x1F;
2846 UInt x
= (UInt
)cins
;
2848 switch ((cins
>> 32) & 0x1F) {
2850 DIP("li r%u, 0x%X", rt
, x
);
2851 putIReg(rt
, mkU32(x
));
2855 DIP("addiu r%u, r%u, 0x%X", rt
, rt
, x
);
2856 putIReg(rt
, binop(Iop_Add32
, getIReg(rt
), mkU32(x
)));
2860 DIP("addiu r%u, r28, 0x%X", rt
, x
);
2861 putIReg(rt
, binop(Iop_Add32
, getIReg(28), mkU32(x
)));
2865 DIP("addiupc r%u, 0x%X", rt
, x
);
2866 putIReg(rt
, mkU32(guest_PC_curr_instr
+ x
+ 6));
2870 DIP("lwpc r%u, 0x%X", rt
, x
);
2871 putIReg(rt
, load(Ity_I32
, mkU32(guest_PC_curr_instr
+ 6 + x
)));
2875 DIP("swpc r%u, 0x%X", rt
, x
);
2876 store(mkU32(guest_PC_curr_instr
+ 6 + x
), getIReg(rt
));
2880 vex_printf("Unsupported 48bit: %012llX\n", cins
);
2888 static Bool
check_for_special_requests_nanoMIPS(DisResult
*dres
,
2891 /* 8000 c04d srl zero, zero, 13
2892 8000 c05d srl zero, zero, 29
2893 8000 c043 srl zero, zero, 3
2894 8000 c053 srl zero, zero, 19 */
2895 const UInt word1
= 0x8000C04D;
2896 const UInt word2
= 0x8000C05D;
2897 const UInt word3
= 0x8000C043;
2898 const UInt word4
= 0x8000C053;
2899 if (getUInt(code
+ 0) == word1
&& getUInt(code
+ 4) == word2
&&
2900 getUInt(code
+ 8) == word3
&& getUInt(code
+ 12) == word4
) {
2901 /* Got a "Special" instruction preamble. Which one is it? */
2902 if (getUInt(code
+ 16) == 0x218C6290 /* or t0, t0, t0 */ ) {
2903 /* $a7 = client_request ( $t0 ) */
2904 DIP("a7 = client_request(t0)");
2905 dres
->jk_StopHere
= Ijk_ClientReq
;
2906 dres
->whatNext
= Dis_StopHere
;
2909 } else if (getUInt(code
+ 16) == 0x21AD6A90 /* or t1, t1, t1 */ ) {
2910 /* $a7 = guest_NRADDR */
2911 DIP("a7 = guest_NRADDR");
2912 putIReg(11, IRExpr_Get(offsetof(VexGuestMIPS32State
, guest_NRADDR
),
2916 } else if (getUInt(code
+ 16) == 0x21CE7290 /* or t2, t2, t2 */ ) {
2917 /* branch-and-link-to-noredir $25 */
2918 DIP("branch-and-link-to-noredir t9");
2919 putIReg(31, mkU32(guest_PC_curr_instr
+ 20));
2921 dres
->jk_StopHere
= Ijk_NoRedir
;
2922 dres
->whatNext
= Dis_StopHere
;
2925 } else if (getUInt(code
+ 16) == 0x21EF7A90 /* or t3, t3, t3 */ ) {
2927 DIP("IR injection");
2928 #if defined (_MIPSEL)
2929 vex_inject_ir(irsb
, Iend_LE
);
2930 #elif defined (_MIPSEB)
2931 vex_inject_ir(irsb
, Iend_BE
);
2934 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State
, guest_CMSTART
),
2935 mkU32(guest_PC_curr_instr
)));
2936 stmt(IRStmt_Put(offsetof(VexGuestMIPS32State
, guest_CMLEN
),
2939 dres
->whatNext
= Dis_StopHere
;
2940 dres
->jk_StopHere
= Ijk_InvalICache
;
2949 /*------------------------------------------------------------*/
2950 /*--- Disassemble a single instruction ---*/
2951 /*------------------------------------------------------------*/
2953 /* Disassemble a single instruction into IR. The instruction is
2954 located in host memory at guest_instr, and has guest IP of
2955 guest_PC_curr_instr, which will have been set before the call
2959 /* Disassemble a single instruction into IR. The instruction
2960 is located in host memory at &guest_code[delta]. */
2961 DisResult
disInstr_nanoMIPS( IRSB
* irsb_IN
,
2962 const UChar
* guest_code_IN
,
2966 const VexArchInfo
* archinfo
,
2967 const VexAbiInfo
* abiinfo
,
2968 VexEndness host_endness_IN
,
2969 Bool sigill_diag_IN
)
2973 vassert(guest_arch
== VexArchNANOMIPS
);
2975 /* Set result defaults. */
2976 dres
.whatNext
= Dis_Continue
;
2978 dres
.jk_StopHere
= Ijk_INVALID
;
2979 dres
.hint
= Dis_HintNone
;
2982 guest_PC_curr_instr
= (Addr32
)guest_IP
;
2984 code
= guest_code_IN
+ delta
;
2986 if (!check_for_special_requests_nanoMIPS(&dres
, code
)) {
2987 UShort cins
= getUShort(code
);
2988 nanoMIPSopcodes opcode
= cins
>> 10;
2990 if (opcode
& P16
) dis_nanoMIPS16(&dres
, cins
);
2991 else if (opcode
== P48I
) {
2992 ULong cinsl
= (((ULong
) cins
) << 32) |
2993 (((ULong
) getUShort(code
+ 4)) << 16) |
2994 getUShort(code
+ 2);
2995 dis_nanoMIPS48(&dres
, cinsl
);
2997 UInt cinsi
= (((UInt
) cins
) << 16) | getUShort(code
+ 2);
2998 dis_nanoMIPS32(&dres
, cinsi
);
3002 if ((dres
.whatNext
== Dis_Continue
) ||
3003 (dres
.jk_StopHere
== Ijk_Sys_syscall
) ||
3004 (dres
.jk_StopHere
== Ijk_SigTRAP
) ||
3005 (dres
.jk_StopHere
== Ijk_SigILL
) ||
3006 (dres
.jk_StopHere
== Ijk_ClientReq
) ||
3007 (dres
.jk_StopHere
== Ijk_NoRedir
) ||
3008 (dres
.jk_StopHere
== Ijk_InvalICache
)) {
3009 putPC(mkU32(guest_PC_curr_instr
+ dres
.len
));
3016 /*--------------------------------------------------------------------*/
3017 /*--- end guest_nanomips_toIR.c ---*/
3018 /*--------------------------------------------------------------------*/