From 0b881e21dc137b8ae7baf5ef71d61a4484ee225f Mon Sep 17 00:00:00 2001 From: Alexis Engelke Date: Sun, 12 Mar 2023 17:10:01 +0100 Subject: [PATCH] format: Fix 64-bit immediate on 32-bit platforms --- decode-test.c | 2 + encode-test.inc | 223 ++++++++++++++++++++++++++++++++++++++++++++++++ encode.c | 109 ++++++++++++----------- format.c | 2 +- 4 files changed, 279 insertions(+), 57 deletions(-) diff --git a/decode-test.c b/decode-test.c index 7307333..2089deb 100644 --- a/decode-test.c +++ b/decode-test.c @@ -1068,6 +1068,8 @@ main(int argc, char** argv) TEST("\x03\xc1", "add eax, ecx"); TEST("\x03\xd0", "add edx, eax"); TEST("\x03\xff", "add edi, edi"); + TEST("\x05\x01\x00\x00\x80", "add eax, 0x80000001"); + TEST64("\x48\x05\x01\x00\x00\x80", "add rax, 0xffffffff80000001"); TEST32("\x40", "inc eax"); TEST32("\x43", "inc ebx"); diff --git a/encode-test.inc b/encode-test.inc index 57ecf98..15d1525 100644 --- a/encode-test.inc +++ b/encode-test.inc @@ -737,6 +737,229 @@ TEST("\x66\x6b\x05\xf8\xff\xff\xff\x02", IMUL16rmi, 0, FE_AX, FE_MEM(FE_IP, 0, F TEST("\x69\x05\xf6\xff\xff\xff\x80\x00\x00\x00", IMUL32rmi, 0, FE_AX, FE_MEM(FE_IP, 0, FE_NOREG, 0), 0x80); TEST("\x66\x69\x05\xf7\xff\xff\xff\x80\x00", IMUL16rmi, 0, FE_AX, FE_MEM(FE_IP, 0, FE_NOREG, 0), 0x80); +TEST("\x01\x00", ADD32mr, 0, FE_MEM(FE_AX, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x01", ADD32mr, 0, FE_MEM(FE_CX, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x02", ADD32mr, 0, FE_MEM(FE_DX, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x03", ADD32mr, 0, FE_MEM(FE_BX, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x04\x80", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x81", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x82", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x83", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x84", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x85\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x04\x86", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x87", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_AX, 0), FE_AX); +TEST("\x01\x04\x88", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x89", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x8a", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x8b", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x8c", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x8d\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x04\x8e", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x8f", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_CX, 0), FE_AX); +TEST("\x01\x04\x90", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x91", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x92", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x93", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x94", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x95\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x04\x96", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x97", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DX, 0), FE_AX); +TEST("\x01\x04\x98", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x9a", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x9b", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x9c", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x9d\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x04\x9e", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BX, 0), FE_AX); +TEST("\x01\x04\x9f", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BX, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SP, 0), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SP, 0), FE_AX); +TEST("\x01\x04\xa8", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xa9", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xaa", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xab", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xac", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xad\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x04\xae", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xaf", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BP, 0), FE_AX); +TEST("\x01\x04\xb0", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb1", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb2", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb3", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb4", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb5\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x04\xb6", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb7", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SI, 0), FE_AX); +TEST("\x01\x04\xb8", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xb9", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xba", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xbb", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xbc", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xbd\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_NOREG, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x04\xbe", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DI, 0), FE_AX); +TEST("\x01\x04\xbf", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DI, 0), FE_AX); +TEST("\x01\x05\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_IP, 0, FE_NOREG, 0x44332217), FE_AX); +TEST("\x01\x06", ADD32mr, 0, FE_MEM(FE_SI, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x07", ADD32mr, 0, FE_MEM(FE_DI, 0, FE_NOREG, 0), FE_AX); +TEST("\x01\x40\x99", ADD32mr, 0, FE_MEM(FE_AX, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x41\x99", ADD32mr, 0, FE_MEM(FE_CX, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x42\x99", ADD32mr, 0, FE_MEM(FE_DX, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x43\x99", ADD32mr, 0, FE_MEM(FE_BX, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x44\x80\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x81\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x82\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x83\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x84\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x85\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x86\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x87\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_AX, -0x67), FE_AX); +TEST("\x01\x44\x88\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x89\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8a\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8b\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8c\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8d\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8e\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x8f\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_CX, -0x67), FE_AX); +TEST("\x01\x44\x90\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x91\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x92\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x93\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x94\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x95\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x96\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x97\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DX, -0x67), FE_AX); +TEST("\x01\x44\x98\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x99\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9a\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9b\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9c\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9d\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9e\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BX, -0x67), FE_AX); +TEST("\x01\x44\x9f\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BX, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SP, -0x67), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SP, -0x67), FE_AX); +TEST("\x01\x44\xa8\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xa9\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xaa\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xab\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xac\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xad\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xae\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xaf\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BP, -0x67), FE_AX); +TEST("\x01\x44\xb0\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb1\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb2\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb3\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb4\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb5\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb6\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb7\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SI, -0x67), FE_AX); +TEST("\x01\x44\xb8\x99", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xb9\x99", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xba\x99", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xbb\x99", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xbc\x99", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xbd\x99", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xbe\x99", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x44\xbf\x99", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DI, -0x67), FE_AX); +TEST("\x01\x45\x99", ADD32mr, 0, FE_MEM(FE_BP, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x46\x99", ADD32mr, 0, FE_MEM(FE_SI, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x47\x99", ADD32mr, 0, FE_MEM(FE_DI, 0, FE_NOREG, -0x67), FE_AX); +TEST("\x01\x80\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x81\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x82\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x83\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x84\x80\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x81\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x82\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x83\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x84\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x85\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x86\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x87\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_AX, 0x44332211), FE_AX); +TEST("\x01\x84\x88\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x89\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8a\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8b\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8c\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8d\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8e\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x8f\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_CX, 0x44332211), FE_AX); +TEST("\x01\x84\x90\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x91\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x92\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x93\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x94\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x95\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x96\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x97\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DX, 0x44332211), FE_AX); +TEST("\x01\x84\x98\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x99\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9a\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9b\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9c\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9d\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9e\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BX, 0x44332211), FE_AX); +TEST("\x01\x84\x9f\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BX, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SP, 0x44332211), FE_AX); +TEST("", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SP, 0x44332211), FE_AX); +TEST("\x01\x84\xa8\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xa9\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xaa\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xab\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xac\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xad\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xae\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xaf\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_BP, 0x44332211), FE_AX); +TEST("\x01\x84\xb0\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb1\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb2\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb3\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb4\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb5\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb6\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb7\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_SI, 0x44332211), FE_AX); +TEST("\x01\x84\xb8\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_AX, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xb9\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_CX, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xba\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DX, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xbb\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BX, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xbc\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SP, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xbd\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xbe\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x84\xbf\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 4, FE_DI, 0x44332211), FE_AX); +TEST("\x01\x85\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_BP, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x86\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_SI, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\x87\x11\x22\x33\x44", ADD32mr, 0, FE_MEM(FE_DI, 0, FE_NOREG, 0x44332211), FE_AX); +TEST("\x01\xc0", ADD32mr, 0, FE_AX, FE_AX); +TEST("\x01\xc1", ADD32mr, 0, FE_CX, FE_AX); +TEST("\x01\xc2", ADD32mr, 0, FE_DX, FE_AX); +TEST("\x01\xc3", ADD32mr, 0, FE_BX, FE_AX); +TEST("\x01\xc4", ADD32mr, 0, FE_SP, FE_AX); +TEST("\x01\xc5", ADD32mr, 0, FE_BP, FE_AX); +TEST("\x01\xc6", ADD32mr, 0, FE_SI, FE_AX); +TEST("\x01\xc7", ADD32mr, 0, FE_DI, FE_AX); + + // Test LOCK prefix TEST("\xf0\x87\x08", LOCK_XCHG32mr, 0, FE_MEM(FE_AX, 0, FE_NOREG, 0), FE_CX); TEST("\xf0\x0f\xc1\x01", LOCK_XADD32mr, 0, FE_MEM(FE_CX, 0, FE_NOREG, 0), FE_AX); diff --git a/encode.c b/encode.c index c00c031..81aefa2 100644 --- a/encode.c +++ b/encode.c @@ -176,80 +176,77 @@ enc_mr(uint8_t** restrict buf, uint64_t opc, uint64_t epfx, uint64_t op0, bool has_rex = opc & OPC_REXW || epfx & EPFX_REX_MSK; if (has_rex && (op_reg_gph(op0) || op_reg_gph(op1))) return -1; + + if (LIKELY(op_reg(op0))) { + if (enc_opc(buf, opc, epfx)) return -1; + *(*buf)++ = 0xc0 | ((op_reg_idx(op1) & 7) << 3) | (op_reg_idx(op0) & 7); + return 0; + } + unsigned opcsz = opc_size(opc, epfx); int mod = 0, reg = op1 & 7, rm; int scale = 0, idx = 4, base = 0; - int32_t off = 0; - bool withsib = false, mod0off = false; - if (op_reg(op0)) - { - mod = 3; - rm = op_reg_idx(op0) & 7; - } - else - { - off = op_mem_offset(op0); + int32_t off = op_mem_offset(op0); + bool withsib = false; - if (!!op_mem_idx(op0) != !!op_mem_scale(op0)) return -1; - if (!op_mem_idx(op0) && (opc & OPC_VSIB)) return -1; - if (op_mem_idx(op0)) + if (!!op_mem_idx(op0) != !!op_mem_scale(op0)) return -1; + if (!op_mem_idx(op0) && (opc & OPC_VSIB)) return -1; + if (op_mem_idx(op0)) + { + if (opc & OPC_VSIB) { - if (opc & OPC_VSIB) - { - if (!op_reg_xmm(op_mem_idx(op0))) return -1; - } - else - { - if (!op_reg_gpl(op_mem_idx(op0))) return -1; - if (op_reg_idx(op_mem_idx(op0)) == 4) return -1; - } - idx = op_mem_idx(op0) & 7; - int scalabs = op_mem_scale(op0); - if (scalabs & (scalabs - 1)) return -1; - scale = (scalabs & 0xA ? 1 : 0) | (scalabs & 0xC ? 2 : 0); - withsib = true; - } - - if (!op_mem_base(op0)) - { - rm = 5; - mod0off = true; - withsib = true; - } - else if (op_mem_base(op0) == FE_IP) - { - rm = 5; - mod0off = true; - // Adjust offset, caller doesn't know instruction length. - off -= opcsz + 5 + immsz; - if (withsib) return -1; + if (!op_reg_xmm(op_mem_idx(op0))) return -1; } else { - if (!op_reg_gpl(op_mem_base(op0))) return -1; - rm = op_reg_idx(op_mem_base(op0)) & 7; - if (rm == 5) mod = 1; + if (!op_reg_gpl(op_mem_idx(op0))) return -1; + if (op_reg_idx(op_mem_idx(op0)) == 4) return -1; } + idx = op_mem_idx(op0) & 7; + int scalabs = op_mem_scale(op0); + if (scalabs & (scalabs - 1)) return -1; + scale = (scalabs & 0xA ? 1 : 0) | (scalabs & 0xC ? 2 : 0); + withsib = true; + } - if (off && op_imm_n(off, 1) && !mod0off) - mod = 1; - else if (off && !mod0off) - mod = 2; - - if (withsib || rm == 4) - { + unsigned dispsz = 0; + if (!op_mem_base(op0)) + { + base = 5; + rm = 4; + dispsz = 4; + } + else if (op_mem_base(op0) == FE_IP) + { + rm = 5; + dispsz = 4; + // Adjust offset, caller doesn't know instruction length. + off -= opcsz + 5 + immsz; + if (withsib) return -1; + } + else + { + if (!op_reg_gpl(op_mem_base(op0))) return -1; + rm = op_reg_idx(op_mem_base(op0)) & 7; + if (withsib || rm == 4) { base = rm; rm = 4; } + if (off) { + mod = op_imm_n(off, 1) ? 0x40 : 0x80; + dispsz = op_imm_n(off, 1) ? 1 : 4; + } else if (rm == 5) { + mod = 0x40; + dispsz = 1; + } } - unsigned dispsz = mod == 1 ? 1 : (mod == 2 || mod0off) ? 4 : 0; - if (opcsz + 1 + (mod != 3 && rm == 4) + dispsz + immsz > 15) return -1; + if (opcsz + 1 + (rm == 4) + dispsz + immsz > 15) return -1; if (enc_opc(buf, opc, epfx)) return -1; - *(*buf)++ = (mod << 6) | (reg << 3) | rm; - if (mod != 3 && rm == 4) + *(*buf)++ = mod | (reg << 3) | rm; + if (UNLIKELY(rm == 4)) *(*buf)++ = (scale << 6) | (idx << 3) | base; return enc_imm(buf, off, dispsz); } diff --git a/format.c b/format.c index 774e83d..27ef820 100644 --- a/format.c +++ b/format.c @@ -468,7 +468,7 @@ fd_format_impl(char buf[DECLARE_RESTRICTED_ARRAY_SIZE(128)], const FdInstr* inst buf = fd_strpcat(buf, (struct FdStr) { bcstsize+1, *bcstsize }); } } else if (op_type == FD_OT_IMM || op_type == FD_OT_OFF) { - size_t immediate = FD_OP_IMM(instr, i); + uint64_t immediate = FD_OP_IMM(instr, i); // Some instructions have actually two immediate operands which are // decoded as a single operand. Split them here appropriately. switch (FD_TYPE(instr)) {