From: Julian Seward Date: Tue, 7 Feb 2006 16:42:39 +0000 (+0000) Subject: ppc32/64: handle twi/tdi (conditional trap) instructions X-Git-Tag: svn/VALGRIND_3_2_3^2~90 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=18a3f264e1712f7c8e494af58f01719e346cf01a;p=thirdparty%2Fvalgrind.git ppc32/64: handle twi/tdi (conditional trap) instructions git-svn-id: svn://svn.valgrind.org/vex/trunk@1571 --- diff --git a/VEX/priv/guest-ppc/toIR.c b/VEX/priv/guest-ppc/toIR.c index 2310ee9108..d4dca35953 100644 --- a/VEX/priv/guest-ppc/toIR.c +++ b/VEX/priv/guest-ppc/toIR.c @@ -4483,6 +4483,130 @@ static Bool dis_cond_logic ( UInt theInstr ) } +/* + Trap instructions +*/ + +/* Do the code generation for a trap. Returned Bool is true iff + this is an unconditional trap. */ +static Bool do_trap ( IRType ty, UChar TO, + IRExpr* argL0, ULong argR0, Addr64 cia ) +{ + IRTemp argL, argR; + IRExpr *argLe, *argRe, *cond, *tmp; + + IROp opAND = ty==Ity_I32 ? Iop_And32 : Iop_And64; + IROp opOR = ty==Ity_I32 ? Iop_Or32 : Iop_Or64; + IROp opCMPORDS = ty==Ity_I32 ? Iop_CmpORD32S : Iop_CmpORD64S; + IROp opCMPORDU = ty==Ity_I32 ? Iop_CmpORD32U : Iop_CmpORD64U; + IROp opCMPNE = ty==Ity_I32 ? Iop_CmpNE32 : Iop_CmpNE64; + IROp opCMPEQ = ty==Ity_I32 ? Iop_CmpEQ32 : Iop_CmpEQ64; + IRExpr* const0 = ty==Ity_I32 ? mkU32(0) : mkU64(0); + IRExpr* const2 = ty==Ity_I32 ? mkU32(2) : mkU64(2); + IRExpr* const4 = ty==Ity_I32 ? mkU32(4) : mkU64(4); + IRExpr* const8 = ty==Ity_I32 ? mkU32(8) : mkU64(8); + + const UChar b11100 = 0x1C; + const UChar b00111 = 0x07; + + if ((TO & b11100) == b11100 || (TO & b00111) == b00111) { + /* Unconditional trap. Just do the exit without + testing the arguments. */ + stmt( IRStmt_Exit( + binop(opCMPEQ, const0, const0), + Ijk_Trap, + mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) + )); + return True; /* unconditional trap */ + } + + /* ty is the type at which the comparisons are done. This is not + the same as the 32/64-mode-ness. */ + vassert(ty == Ity_I32 || ty == Ity_I64); + argL = newTemp(ty); + argR = newTemp(ty); + if (ty == Ity_I32) { + assign( argL, mkSzNarrow32(Ity_I32, argL0) ); + assign( argR, mkU32( (UInt)argR0 )); + } else { + vassert(mode64); + assign( argL, argL0 ); + assign( argR, mkU64( argR0 )); + } + argLe = mkexpr(argL); + argRe = mkexpr(argR); + cond = const0; + if (TO & 16) { // L s R + tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const4); + cond = binop(opOR, tmp, cond); + } + if (TO & 4) { // L == R + tmp = binop(opAND, binop(opCMPORDS, argLe, argRe), const2); + cond = binop(opOR, tmp, cond); + } + if (TO & 2) { // L u R + tmp = binop(opAND, binop(opCMPORDU, argLe, argRe), const4); + cond = binop(opOR, tmp, cond); + } + stmt( IRStmt_Exit( + binop(opCMPNE, cond, const0), + Ijk_Trap, + mode64 ? IRConst_U64(cia) : IRConst_U32((UInt)cia) + )); + return False; /* not an unconditional trap */ +} + +static Bool dis_trapi ( UInt theInstr, + /*OUT*/DisResult* dres ) +{ + /* D-Form */ + UChar opc1 = ifieldOPC(theInstr); + UChar TO = ifieldRegDS(theInstr); + UChar rA_addr = ifieldRegA(theInstr); + UInt uimm16 = ifieldUIMM16(theInstr); + ULong simm16 = extend_s_16to64(uimm16); + Addr64 cia = guest_CIA_curr_instr; + IRType ty = mode64 ? Ity_I64 : Ity_I32; + Bool uncond = False; + + switch (opc1) { + case 0x03: // twi (Trap Word Immediate, PPC32 p548) + uncond = do_trap( Ity_I32, TO, getIReg(rA_addr), simm16, cia ); + if (TO == 4) { + DIP("tweqi r%u,%d\n", (UInt)rA_addr, (Int)simm16); + } else { + DIP("tw%di r%u,%d\n", (Int)TO, (UInt)rA_addr, (Int)simm16); + } + break; + case 0x02: // tdi + if (!mode64) + return False; + uncond = do_trap( Ity_I64, TO, getIReg(rA_addr), simm16, cia ); + break; + default: + return False; + } + + if (uncond) { + /* If the trap shows signs of being unconditional, don't + continue decoding past it. */ + irbb->next = mkSzImm( ty, nextInsnAddr() ); + irbb->jumpkind = Ijk_Boring; + dres->whatNext = Dis_StopHere; + } + + return True; +} + + /* System Linkage Instructions */ @@ -8725,13 +8849,10 @@ DisResult disInstr_PPC_WRK ( if (dis_syslink(theInstr, &dres)) goto decode_success; goto decode_failure; -//zz /* Trap Instructions */ -//zz case 0x02: // tdi -//zz DIP("trap op (tdi) => not implemented\n"); -//zz goto decode_failure; -//zz case 0x03: // twi -//zz DIP("trap op (twi) => not implemented\n"); -//zz goto decode_failure; + /* Trap Instructions */ + case 0x02: case 0x03: // tdi, twi + if (dis_trapi(theInstr, &dres)) goto decode_success; + goto decode_failure; /* Floating Point Load Instructions */ case 0x30: case 0x31: case 0x32: // lfs, lfsu, lfd diff --git a/VEX/priv/host-ppc/hdefs.c b/VEX/priv/host-ppc/hdefs.c index 3633fa7b9e..8d6098ca69 100644 --- a/VEX/priv/host-ppc/hdefs.c +++ b/VEX/priv/host-ppc/hdefs.c @@ -2941,6 +2941,7 @@ Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i, case Ijk_NoDecode: trc = VEX_TRC_JMP_NODECODE; break; case Ijk_TInval: trc = VEX_TRC_JMP_TINVAL; break; case Ijk_NoRedir: trc = VEX_TRC_JMP_NOREDIR; break; + case Ijk_Trap: trc = VEX_TRC_JMP_TRAP; break; case Ijk_Ret: case Ijk_Call: case Ijk_Boring: diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 4295597e88..bb48e71d57 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -703,6 +703,7 @@ void ppIRJumpKind ( IRJumpKind kind ) case Ijk_MapFail: vex_printf("MapFail"); break; case Ijk_TInval: vex_printf("Invalidate"); break; case Ijk_NoRedir: vex_printf("NoRedir"); break; + case Ijk_Trap: vex_printf("Trap"); break; case Ijk_Sys_syscall: vex_printf("Sys_syscall"); break; case Ijk_Sys_int32: vex_printf("Sys_int32"); break; case Ijk_Sys_int128: vex_printf("Sys_int128"); break; diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 27f92c599b..7634edd50e 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -912,6 +912,7 @@ typedef Ijk_MapFail, /* Vex-provided address translation failed */ Ijk_TInval, /* Invalidate translations before continuing. */ Ijk_NoRedir, /* Jump to un-redirected guest addr */ + Ijk_Trap, /* current instruction did a user trap */ /* Unfortunately, various guest-dependent syscall kinds. They all mean: do a syscall before continuing. */ Ijk_Sys_syscall, /* amd64 'syscall', ppc 'sc' */ diff --git a/VEX/pub/libvex_trc_values.h b/VEX/pub/libvex_trc_values.h index a82518e001..b89f5aee80 100644 --- a/VEX/pub/libvex_trc_values.h +++ b/VEX/pub/libvex_trc_values.h @@ -62,6 +62,8 @@ #define VEX_TRC_JMP_TINVAL 61 /* invalidate translations before continuing */ #define VEX_TRC_JMP_NOREDIR 81 /* jump to undirected guest addr */ +#define VEX_TRC_JMP_TRAP 85 /* deliver trap (SIGTRAP?) before + continuing */ #define VEX_TRC_JMP_EMWARN 63 /* deliver emulation warning before continuing */ #define VEX_TRC_JMP_EMFAIL 83 /* emulation fatal error; abort system */