]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
ppc32/64: handle twi/tdi (conditional trap) instructions
authorJulian Seward <jseward@acm.org>
Tue, 7 Feb 2006 16:42:39 +0000 (16:42 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 7 Feb 2006 16:42:39 +0000 (16:42 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@1571

VEX/priv/guest-ppc/toIR.c
VEX/priv/host-ppc/hdefs.c
VEX/priv/ir/irdefs.c
VEX/pub/libvex_ir.h
VEX/pub/libvex_trc_values.h

index 2310ee9108239da4f6b464d03168686af96f4ac0..d4dca35953e3b1ca5b559333c443ccd1c7adfbce 100644 (file)
@@ -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), const8);
+      cond = binop(opOR, tmp, cond);
+   }
+   if (TO & 8) { // 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), const8);
+      cond = binop(opOR, tmp, cond);
+   }
+   if (TO & 1) { // 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
index 3633fa7b9ea8f0e5d30453ddf7aff2d3e299c30f..8d6098ca697c1456b14604ef8f215403b361d965 100644 (file)
@@ -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:
index 4295597e881a2e0f42878ad1e16c87054201f5ad..bb48e71d57acb5bde7ac91b86adeca0b285fdd6d 100644 (file)
@@ -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;
index 27f92c599b4b571e479a05d3b88c03482ebd3337..7634edd50e43d90b683ae3b0c13d292c8aaae291 100644 (file)
@@ -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' */
index a82518e001814472a550e3a86e71387f827d2230..b89f5aee80a35a9f1651db8eb43441fa92f985ec 100644 (file)
@@ -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 */