]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
implement IN and OUT opcodes.
authorDirk Mueller <daywalker@users.sourceforge.net>
Sat, 27 Sep 2003 20:15:01 +0000 (20:15 +0000)
committerDirk Mueller <daywalker@users.sourceforge.net>
Sat, 27 Sep 2003 20:15:01 +0000 (20:15 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1839

NEWS
coregrind/vg_helpers.S
coregrind/vg_include.h
coregrind/vg_main.c
coregrind/vg_to_ucode.c
coregrind/vg_translate.c
include/vg_skin.h

diff --git a/NEWS b/NEWS
index 2911a9f34794fef6b7e4a1b210896907196bab24..cde37943e7a9e40d9bf223d45f08adb1787c14f8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,8 @@ Snapshot 2003XXXX (XX XXXX 2003)
     - pavgb
     - ucomiss
     - enter
+    - mov imm32, %esp
+    - all "in" and "out" opcodes
 
 - Memcheck: Implemented handling of more SSE(2) constructs
 
index 2edfeed828e6857e8e57a99031e46da52aaa2387..80d866291b80fd6c200cc7b155e9c8c736064f44 100644 (file)
@@ -103,6 +103,68 @@ VG_(helper_RDTSC):
        popl    %eax
        ret
 
+/* 
+   Fetch a byte/word/dword from given port
+   On entry:
+         size     1, 2 or 4
+         port, replaced by result
+         RA
+*/
+.global VG_(helper_IN)
+VG_(helper_IN):
+       pushl   %eax
+       pushl   %edx
+       movl    16(%esp), %eax
+       movl    12(%esp), %edx
+       cmpl    $4, %eax
+       je      in_dword
+       cmpl    $2, %eax
+       je      in_word
+in_byte:
+       inb     (%dx), %al
+       jmp     in_done
+in_word:
+       in      (%dx), %ax
+       jmp     in_done
+in_dword:
+       inl     (%dx),%eax
+in_done:
+       movl    %eax,12(%esp)
+       popl    %edx
+       popl    %eax
+       ret
+
+/* 
+   Write a byte/word/dword to given port
+   On entry:
+         size     1, 2 or 4
+         port
+         value
+         RA
+*/
+.global VG_(helper_OUT)
+VG_(helper_OUT):
+       pushl   %eax
+       pushl   %edx
+       movl    16(%esp), %edx
+       movl    12(%esp), %eax
+       cmpl    $4, 20(%esp)
+       je      out_dword
+       cmpl    $2, 20(%esp)
+       je      out_word
+out_byte:
+       outb    %al,(%dx)
+       jmp     out_done
+out_word:
+       out     %ax,(%dx)
+       jmp     out_done
+out_dword:
+       outl    %eax,(%dx)
+out_done:
+       popl    %edx
+       popl    %eax
+       ret
+
 
 /* Do the CPUID instruction.
    On entry:
index 5425e3e5cfe800c985a84e4cb2a5d032eea632d4..e097cffdb9f9793d5e2bf33ad7e9513d012ba96f 100644 (file)
@@ -1570,6 +1570,9 @@ extern void VG_(helper_shldw);
 extern void VG_(helper_shrdl);
 extern void VG_(helper_shrdw);
 
+extern void VG_(helper_IN);
+extern void VG_(helper_OUT);
+
 extern void VG_(helper_RDTSC);
 extern void VG_(helper_CPUID);
 
index a8a8b60656a7a7bac079720907d6a410c12748a1..b6ec7af1992eda8cae718efa739bf38af1f949cf 100644 (file)
@@ -90,6 +90,8 @@ Int VGOFF_(helper_shldl) = INVALID_OFFSET;
 Int VGOFF_(helper_shldw) = INVALID_OFFSET;
 Int VGOFF_(helper_shrdl) = INVALID_OFFSET;
 Int VGOFF_(helper_shrdw) = INVALID_OFFSET;
+Int VGOFF_(helper_IN) = INVALID_OFFSET;
+Int VGOFF_(helper_OUT) = INVALID_OFFSET;
 Int VGOFF_(helper_RDTSC) = INVALID_OFFSET;
 Int VGOFF_(helper_CPUID) = INVALID_OFFSET;
 Int VGOFF_(helper_BSWAP) = INVALID_OFFSET;
@@ -142,10 +144,12 @@ static void align_BaB ( UInt align )
 }
 
 /* Allocate 1 word in baseBlock and set it to the given value. */
-static Int alloc_BaB_1_set ( Addr a )
+static Int alloc_BaB_1_set ( Addr a, const Char* what )
 {
    Int off = alloc_BaB(1);
    VG_(baseBlock)[off] = (UInt)a;
+   if ( VG_( clo_verbosity ) > 1 )
+     VG_(printf)( "Allocated %d for %s\n", off*4, what );
    return off;
 }
 
@@ -183,7 +187,7 @@ void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
 {
    UInt i;
    for (i = 0; i < n; i++) 
-      offsets[i] = alloc_BaB_1_set( addrs[i] );
+      offsets[i] = alloc_BaB_1_set( addrs[i], "helper" );
 }
 
 Bool VG_(need_to_handle_esp_assignment)(void)
@@ -309,75 +313,79 @@ static void vg_init_baseBlock ( void )
 
    /* Helper functions. */
    VGOFF_(helper_idiv_64_32)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_64_32), "idiv_64_32" );
    VGOFF_(helper_div_64_32)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_div_64_32), "div_64_32" );
    VGOFF_(helper_idiv_32_16)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_32_16), "idiv_32_16" );
    VGOFF_(helper_div_32_16)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_div_32_16), "div_32_16" );
    VGOFF_(helper_idiv_16_8)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_idiv_16_8), "idiv_16_8" );
    VGOFF_(helper_div_16_8)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_div_16_8), "div_16_8" );
 
    VGOFF_(helper_imul_32_64)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_32_64), "imul_32_64" );
    VGOFF_(helper_mul_32_64)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_32_64), "mul_32_64" );
    VGOFF_(helper_imul_16_32)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_16_32), "imul_16_32" );
    VGOFF_(helper_mul_16_32)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_16_32), "mul_16_32" );
    VGOFF_(helper_imul_8_16)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_imul_8_16), "imul_8_16" );
    VGOFF_(helper_mul_8_16)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_mul_8_16), "mul_8_16" );
 
    VGOFF_(helper_CLD)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_CLD) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_CLD), "helper_CLD" );
    VGOFF_(helper_STD)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_STD) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_STD), "helper_STD" );
    VGOFF_(helper_get_dirflag)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_get_dirflag), "get_dirflag" );
 
    VGOFF_(helper_CLC)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_CLC) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_CLC), "helper_CLC" );
    VGOFF_(helper_STC)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_STC) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_STC), "helper_STC" );
 
    VGOFF_(helper_shldl)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_shldl) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_shldl), "helper_shldl" );
    VGOFF_(helper_shldw)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_shldw) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_shldw), "helper_shldw" );
    VGOFF_(helper_shrdl)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_shrdl), "helper_shrdl" );
    VGOFF_(helper_shrdw)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_shrdw), "helper_shrdw" );
 
    VGOFF_(helper_RDTSC)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_RDTSC), "helper_RDTSC" );
    VGOFF_(helper_CPUID)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_CPUID), "helper_CPUID" );
 
    VGOFF_(helper_bsf)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_bsf) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_bsf), "helper_bsf" );
    VGOFF_(helper_bsr)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_bsr) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_bsr), "helper_bsr" );
 
    VGOFF_(helper_fstsw_AX)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_fstsw_AX), "fstsw_AX" );
    VGOFF_(helper_SAHF)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_SAHF), "SAHF" );
    VGOFF_(helper_LAHF)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_LAHF), "LAHF" );
    VGOFF_(helper_DAS)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_DAS) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_DAS), "DAS" );
    VGOFF_(helper_DAA)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_DAA) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_DAA), "DAA" );
+   VGOFF_(helper_IN)
+      = alloc_BaB_1_set( (Addr) & VG_(helper_IN), "IN" );
+   VGOFF_(helper_OUT)
+      = alloc_BaB_1_set( (Addr) & VG_(helper_OUT), "OUT" );
 
    VGOFF_(helper_undefined_instruction)
-      = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction) );
+      = alloc_BaB_1_set( (Addr) & VG_(helper_undefined_instruction), "undefined" );
 
    /* Allocate slots for noncompact helpers */
    assign_helpers_in_baseBlock(VG_(n_noncompact_helpers), 
index 8ccbbea09ed7d907f3b3f750acdb65f40aedd0a8..3c617fd4aa101e6a77d5d7a4882ff36f6036d923 100644 (file)
@@ -700,7 +700,6 @@ void codegen_XOR_reg_with_itself ( UCodeBlock* cb, Int size,
    uInstr2(cb, PUT, size, TempReg, tmp, ArchReg, ge_reg);
 }
 
-
 /* Handle binary integer instructions of the form
       op E, G  meaning
       op reg-or-mem, reg
@@ -5637,6 +5636,80 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
          VG_(printf)("xlat%c [ebx]\n", nameISize(sz));
       break;
 
+   /* ------------------------ IN / OUT ----------------------- */
+
+   case 0xE4: /* IN ib, %al        */
+   case 0xE5: /* IN ib, %{e}ax     */
+   case 0xEC: /* IN (%dx),%al      */
+   case 0xED: /* IN (%dx),%{e}ax   */
+      t1 = newTemp(cb);
+      t2 = newTemp(cb);
+      t3 = newTemp(cb);
+
+      uInstr0(cb, CALLM_S, 0);
+      /* operand size? */
+      uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
+      uLiteral(cb, ( opc == 0xE4 || opc == 0xEC ) ? 1 : sz);
+      uInstr1(cb, PUSH,  4, TempReg, t1);
+      /* port number ? */
+      if ( opc == 0xE4 || opc == 0xE5 ) {
+         abyte = getUChar(eip); eip++;
+         uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+         uLiteral(cb, abyte);
+      }
+      else
+         uInstr2(cb, GET,   4, ArchReg, R_EDX, TempReg, t2);
+
+      uInstr1(cb, PUSH,  4, TempReg, t2);
+      uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_IN));
+      uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+      uInstr1(cb, POP,   4, TempReg, t2);
+      uInstr1(cb, CLEAR, 0, Lit16,   4);
+      uInstr0(cb, CALLM_E, 0);
+      uInstr2(cb, PUT,   4, TempReg, t2, ArchReg, R_EAX);
+      if (dis) {
+         if ( opc == 0xE4 || opc == 0xE5 )
+            VG_(printf)("in 0x%x, %%eax/%%ax/%%al\n", getUChar(eip-1) );
+         else
+            VG_(printf)("in (%%dx), %%eax/%%ax/%%al\n");
+      }
+      break;
+   case 0xE6: /* OUT %al,ib       */
+   case 0xE7: /* OUT %{e}ax,ib    */
+   case 0xEE: /* OUT %al,(%dx)    */
+   case 0xEF: /* OUT %{e}ax,(%dx) */
+      t1 = newTemp(cb);
+      t2 = newTemp(cb);
+      t3 = newTemp(cb);
+
+      uInstr0(cb, CALLM_S, 0);
+      /* operand size? */
+      uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
+      uLiteral(cb, ( opc == 0xE6 || opc == 0xEE ) ? 1 : sz);
+      uInstr1(cb, PUSH,  4, TempReg, t1);
+      /* port number ? */
+      if ( opc == 0xE6 || opc == 0xE7 ) {
+         abyte = getUChar(eip); eip++;
+         uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
+         uLiteral(cb, abyte);
+      }
+      else
+         uInstr2(cb, GET,   4, ArchReg, R_EDX, TempReg, t2);
+      uInstr1(cb, PUSH,  4, TempReg, t2);
+      uInstr2(cb, GET,   4, ArchReg, R_EAX, TempReg, t3);
+      uInstr1(cb, PUSH,  4, TempReg, t3);
+      uInstr1(cb, CALLM, 0, Lit16,   VGOFF_(helper_OUT));
+      uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
+      uInstr1(cb, CLEAR,  0, Lit16,  12);
+      uInstr0(cb, CALLM_E, 0);
+      if (dis) {
+         if ( opc == 0xE4 || opc == 0xE5 )
+            VG_(printf)("out %%eax/%%ax/%%al, 0x%x\n", getUChar(eip-1) );
+         else
+            VG_(printf)("out %%eax/%%ax/%%al, (%%dx)\n");
+      }
+      break;
+
    /* ------------------------ (Grp1 extensions) ---------- */
 
    case 0x80: /* Grp1 Ib,Eb */
index efc5b3bc2e303af4effa5d94e2165ab077d13df5..fc0cbe9e1aef751991703c7f484f8e779c062485 100644 (file)
@@ -70,7 +70,7 @@ void VG_(free_UCodeBlock) ( UCodeBlock* cb )
 
 
 /* Ensure there's enough space in a block to add one uinstr. */
-static __inline__
+static
 void ensureUInstr ( UCodeBlock* cb )
 {
    if (cb->used == cb->size) {
index 574041013b7400700be0aab62bf803542e8da9bb..34370a9c000417c97a075ff64ff1e8e20c42b520 100644 (file)
@@ -1079,6 +1079,9 @@ extern Int VGOFF_(helper_shrdw);
 extern Int VGOFF_(helper_RDTSC);
 extern Int VGOFF_(helper_CPUID);
 
+extern Int VGOFF_(helper_IN);
+extern Int VGOFF_(helper_OUT);
+
 extern Int VGOFF_(helper_bsf);
 extern Int VGOFF_(helper_bsr);