]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Make a start on x86 instruction emission.
authorJulian Seward <jseward@acm.org>
Thu, 22 Jul 2004 01:14:11 +0000 (01:14 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 22 Jul 2004 01:14:11 +0000 (01:14 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@101

VEX/priv/host-x86/x86host_defs.c
VEX/priv/main/vex_main.c
VEX/test_main.c

index c09459b3c2f3449d78a3d68d5bc6f58ee058adcc..b14e8179ef95d67c9a751904864b35ce018b45c4 100644 (file)
@@ -785,17 +785,178 @@ X86Instr* genReload_X86 ( HReg rreg, Int offset )
 
 /* --------- The x86 assembler (bleh.) --------- */
 
+static UInt iregNo ( HReg r )
+{
+   UInt n;
+   vassert(hregClass(r) == HRcInt);
+   vassert(!hregIsVirtual(r));
+   n = hregNumber(r);
+   vassert(n <= 7);
+   return n;
+}
+
+static UChar mkModRegRM ( UChar mod, UChar reg, UChar regmem )
+{
+   return ((mod & 3) << 6) | ((reg & 7) << 3) | (regmem & 7);
+}
+
+static UChar mkSIB ( Int shift, Int regindex, Int regbase )
+{
+   return ((shift & 3) << 6) | ((regindex & 7) << 3) | (regbase & 7);
+}
+
+static UChar* emit32 ( UChar* p, UInt w32 )
+{
+   *p++ = (w32)       & 0x000000FF;
+   *p++ = (w32 >>  8) & 0x000000FF;
+   *p++ = (w32 >> 16) & 0x000000FF;
+   *p++ = (w32 >> 24) & 0x000000FF;
+   return p;
+}
+
+static Bool fits8bits ( UInt w32 )
+{
+   w32 &= 0xFFFFFF00;
+   return (w32 == 0 || w32 == 0xFFFFFF00);
+}
+
+
+/* Forming mod-reg-rm bytes and scale-index-base bytes.
+
+     greg,  0(ereg)    |  ereg != ESP && ereg != EBP
+                       =  00 greg ereg
+
+     greg,  d8(ereg)   |  ereg != ESP
+                       =  01 greg ereg, d8
+
+     greg,  d32(ereg)  |  ereg != ESP
+                       =  10 greg ereg, d32
+
+     -----------------------------------------------
+
+     greg,  d8(base,index,scale)  
+               |  index != ESP
+               =  01 greg 100, scale index base, d8
+
+     greg,  d32(base,index,scale)
+               |  index != ESP
+               =  10 greg 100, scale index base, d32
+*/
+static UChar* doAMode_M ( UChar* p, HReg greg, X86AMode* am ) 
+{
+   if (am->tag == Xam_IR) {
+      if (am->Xam.IR.imm == 0 
+          && am->Xam.IR.reg != hregX86_ESP()
+          && am->Xam.IR.reg != hregX86_EBP() ) {
+         *p++ = mkModRegRM(0, iregNo(greg), iregNo(am->Xam.IR.reg));
+         return p;
+      }
+      if (fits8bits(am->Xam.IR.imm)
+          && am->Xam.IR.reg != hregX86_ESP()) {
+         *p++ = mkModRegRM(1, iregNo(greg), iregNo(am->Xam.IR.reg));
+         *p++ = am->Xam.IR.imm & 0xFF;
+         return p;
+      }
+      if (am->Xam.IR.reg != hregX86_ESP()) {
+         *p++ = mkModRegRM(2, iregNo(greg), iregNo(am->Xam.IR.reg));
+         p = emit32(p, am->Xam.IR.imm);
+         return p;
+      }
+      ppX86AMode(am);
+      vpanic("doAMode_M: can't emit amode IR");
+      /*NOTREACHED*/
+   }
+   if (am->tag == Xam_IRRS) {
+      if (fits8bits(am->Xam.IRRS.imm)
+          && am->Xam.IRRS.index != hregX86_ESP()) {
+         *p++ = mkModRegRM(1, iregNo(greg), 4);
+         *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index, 
+                                          am->Xam.IRRS.base);
+         *p++ = am->Xam.IRRS.imm & 0xFF;
+         return p;
+      }
+      if (am->Xam.IRRS.index != hregX86_ESP()) {
+         *p++ = mkModRegRM(2, iregNo(greg), 4);
+         *p++ = mkSIB(am->Xam.IRRS.shift, am->Xam.IRRS.index,
+                                          am->Xam.IRRS.base);
+         p = emit32(p, am->Xam.IRRS.imm);
+         return p;
+      }
+      ppX86AMode(am);
+      vpanic("doAMode_M: can't emit amode IRRS");
+      /*NOTREACHED*/
+   }
+   vpanic("doAMode_M: unknown amode");
+   /*NOTREACHED*/
+}
+
+
+/* Emit a mod-reg-rm byte when the rm bit denotes a reg. */
+static UChar* doAMode_R ( UChar* p, HReg greg, HReg ereg ) 
+{
+   *p++ = mkModRegRM(3, iregNo(greg), iregNo(ereg));
+   return p;
+}
+
+
+
 /* Emit an instruction into buf and return the number of bytes used.
    Note that buf is not the insn's final place, and therefore it is
    imperative to emit position-independent code. */
 
 Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i )
 {
+   UChar* p = &buf[0];
+   vassert(nbuf >= 32);
+
    switch (i->tag) {
-      default: 
-          ppX86Instr(i);
-         vpanic("emit_X86Instr");
+
+   case Xin_Alu32R:
+      if (i->Xin.Alu32R.op == Xalu_MOV) {
+         switch (i->Xin.Alu32R.src->tag) {
+         //       case Xrmi_Imm:
+         //*p++ = 0xB8 + iregNo(i->Xin.Alu32.dst);
+         //p = emit32(i->Xin.Alu32.src->Xrmi.Imm.imm32);
+         //return p;
+         //case Xrmi_Reg:
+         case Xrmi_Mem:
+            *p++ = 0x8B;
+            p = doAMode_M(p, i->Xin.Alu32R.dst, 
+                             i->Xin.Alu32R.src->Xrmi.Mem.am);
+            goto done;
+         default:
+            goto bad;
+         }
+      } else {
+         goto bad;
+      }
+      break;
+
+   case Xin_Alu32M:
+      if (i->Xin.Alu32M.op == Xalu_MOV) {
+       if (i->Xin.Alu32M.src->tag == Xri_Reg) {
+         *p++ = 0x89;
+         p = doAMode_M(p, i->Xin.Alu32M.src->Xri.Reg.reg,
+                           i->Xin.Alu32M.dst);
+         goto done;
+       } else {
+         goto bad;
+       }
+      } else {
+         goto bad;
+      }
+      break;
+
+
+    bad:
+     default: 
+        ppX86Instr(i);
+        vpanic("emit_X86Instr");
+       /*NOTREACHED*/
    }
+  done:
+   vassert(p - &buf[0] <= 32);
+   return p - &buf[0];
 }
 
 
index 1c44df89f692bdfcd7d7ff5d42449bee996d20a5..7b704554ffa8a8f361a513f1666a03bdf856979f 100644 (file)
@@ -185,7 +185,16 @@ TranslateResult LibVEX_Translate (
    UChar insn_bytes[32];
    out_used = 0; /* tracks along the host_bytes array */
    for (i = 0; i < rcode->arr_used; i++) {
+      if (vex_verbosity > 0) {
+         ppInstr(rcode->arr[i]);
+         vex_printf("\n");
+      }
       j = (*emit)( insn_bytes, 32, rcode->arr[i] );
+      if (vex_verbosity > 0) {
+         for (k = 0; k < j; k++)
+            vex_printf("0x%-2x ", (UInt)insn_bytes[k]);
+         vex_printf("\n\n");
+      }
       if (out_used + j > host_bytes_size) {
          LibVEX_ClearTemporary(False);
          return TransOutputFull;
index 5c4d8e1c3f9e112ee313f2170d8e8803699a2500..b08d8cdb2f6e6e3cd37293de7281d33c87e1d088 100644 (file)
@@ -66,8 +66,8 @@ int main ( int argc, char** argv )
    LibVEX_Init ( &failure_exit, &log_bytes, 
                  1,  /* debug_paranoia */ 
                  1,  /* verbosity */
-                 False, 
-                //True, 
+                 //False, 
+                True, 
                  100 );
 
    while (!feof(f)) {