From 8d8ec2ca642353fa7f4cbedc233bd0930831a2eb Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Sat, 27 Sep 2003 20:15:01 +0000 Subject: [PATCH] implement IN and OUT opcodes. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1839 --- NEWS | 2 ++ coregrind/vg_helpers.S | 62 +++++++++++++++++++++++++++++++++ coregrind/vg_include.h | 3 ++ coregrind/vg_main.c | 74 +++++++++++++++++++++------------------ coregrind/vg_to_ucode.c | 75 +++++++++++++++++++++++++++++++++++++++- coregrind/vg_translate.c | 2 +- include/vg_skin.h | 3 ++ 7 files changed, 186 insertions(+), 35 deletions(-) diff --git a/NEWS b/NEWS index 2911a9f34..cde37943e 100644 --- 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 diff --git a/coregrind/vg_helpers.S b/coregrind/vg_helpers.S index 2edfeed82..80d866291 100644 --- a/coregrind/vg_helpers.S +++ b/coregrind/vg_helpers.S @@ -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: diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 5425e3e5c..e097cffdb 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -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); diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index a8a8b6065..b6ec7af19 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -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), diff --git a/coregrind/vg_to_ucode.c b/coregrind/vg_to_ucode.c index 8ccbbea09..3c617fd4a 100644 --- a/coregrind/vg_to_ucode.c +++ b/coregrind/vg_to_ucode.c @@ -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 */ diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c index efc5b3bc2..fc0cbe9e1 100644 --- a/coregrind/vg_translate.c +++ b/coregrind/vg_translate.c @@ -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) { diff --git a/include/vg_skin.h b/include/vg_skin.h index 574041013..34370a9c0 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -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);