From: Julian Seward Date: Wed, 22 Jan 2020 08:26:43 +0000 (+0100) Subject: Bug 415757 - vex x86->IR: unhandled instruction bytes: 0x66 0xF 0xCE (bswapw). X-Git-Tag: VALGRIND_3_16_0~127 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e0573777c487e83d5fbd2fd764b041e59784766;p=thirdparty%2Fvalgrind.git Bug 415757 - vex x86->IR: unhandled instruction bytes: 0x66 0xF 0xCE (bswapw). Implement bswapw, even though the instruction does not officially exist. Patch from Alex Henrie (alexhenrie24@gmail.com). --- diff --git a/VEX/priv/guest_x86_toIR.c b/VEX/priv/guest_x86_toIR.c index 01bcc8a952..5d6e6dc64f 100644 --- a/VEX/priv/guest_x86_toIR.c +++ b/VEX/priv/guest_x86_toIR.c @@ -14676,15 +14676,21 @@ DisResult disInstr_X86_WRK ( case 0xCD: case 0xCE: case 0xCF: /* BSWAP %edi */ - /* AFAICS from the Intel docs, this only exists at size 4. */ - if (sz != 4) goto decode_failure; - - t1 = newTemp(Ity_I32); - assign( t1, getIReg(4, opc-0xC8) ); - t2 = math_BSWAP(t1, Ity_I32); - - putIReg(4, opc-0xC8, mkexpr(t2)); - DIP("bswapl %s\n", nameIReg(4, opc-0xC8)); + /* According to the Intel and AMD docs, 16-bit BSWAP is undefined. + * However, the result of a 16-bit BSWAP is always zero in every Intel + * and AMD CPU, and some software depends on this behavior. */ + if (sz == 2) { + putIReg(2, opc-0xC8, mkU16(0)); + DIP("bswapw %s\n", nameIReg(2, opc-0xC8)); + } else if (sz == 4) { + t1 = newTemp(Ity_I32); + assign( t1, getIReg(4, opc-0xC8) ); + t2 = math_BSWAP(t1, Ity_I32); + putIReg(4, opc-0xC8, mkexpr(t2)); + DIP("bswapl %s\n", nameIReg(4, opc-0xC8)); + } else { + goto decode_failure; + } break; /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */ diff --git a/none/tests/x86/Makefile.am b/none/tests/x86/Makefile.am index bc9615ec14..4086cd8348 100644 --- a/none/tests/x86/Makefile.am +++ b/none/tests/x86/Makefile.am @@ -35,6 +35,7 @@ EXTRA_DIST = \ aad_aam.stdout.exp aad_aam.stderr.exp aad_aam.vgtest \ badseg.stderr.exp badseg.stdout.exp badseg.stdout.exp-solaris \ badseg.vgtest \ + bswapw.stderr.exp bswapw.stdout.exp bswapw.vgtest \ bt_everything.stderr.exp bt_everything.stdout.exp bt_everything.vgtest \ bt_literal.stderr.exp bt_literal.stdout.exp bt_literal.vgtest \ bug125959-x86.stderr.exp bug125959-x86.stdout.exp bug125959-x86.vgtest \ @@ -85,6 +86,7 @@ check_PROGRAMS = \ aad_aam \ allexec \ badseg \ + bswapw \ bt_everything \ bt_literal \ bug125959-x86 \ diff --git a/none/tests/x86/bswapw.c b/none/tests/x86/bswapw.c new file mode 100644 index 0000000000..adb0bf617c --- /dev/null +++ b/none/tests/x86/bswapw.c @@ -0,0 +1,31 @@ + +#include + +typedef unsigned int UInt; + +int main ( void ) +{ + +#define GO16(REG,VALUE) \ + value = VALUE; \ + __asm__ __volatile__( \ + "pushl %%" REG " \n\t" \ + "movl 0(" "%0" "), %%" REG " \n\t" \ + ".byte 0x66 \n\t" "bswapl %%" REG "\n\t" \ + "movl %%" REG ", 0(" "%0" ") \n\t" \ + "popl %%" REG "\n" \ + : : "r" (&value) : REG, "memory", "cc" \ + ); \ + printf("0x%08x\n", value) + + UInt value; + GO16("eax", 0x12345678); + GO16("ebx", 0x23456789); + GO16("ecx", 0x3456789a); + GO16("edx", 0x456789ab); + GO16("esi", 0x56789abc); + GO16("edi", 0x6789abcd); + //GO16("ebp", 0x789abcde); // The compiler complains + + return 0; +} diff --git a/none/tests/x86/bswapw.stderr.exp b/none/tests/x86/bswapw.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/none/tests/x86/bswapw.stdout.exp b/none/tests/x86/bswapw.stdout.exp new file mode 100644 index 0000000000..a59b9a0c24 --- /dev/null +++ b/none/tests/x86/bswapw.stdout.exp @@ -0,0 +1,6 @@ +0x12340000 +0x23450000 +0x34560000 +0x45670000 +0x56780000 +0x67890000 diff --git a/none/tests/x86/bswapw.vgtest b/none/tests/x86/bswapw.vgtest new file mode 100644 index 0000000000..0d2d920702 --- /dev/null +++ b/none/tests/x86/bswapw.vgtest @@ -0,0 +1,2 @@ +prog: bswapw +vgopts: -q