From: Ulrich Drepper Date: Fri, 19 Dec 2008 09:14:12 +0000 (-0800) Subject: Implement AMD 3DNOW disassembly. X-Git-Tag: elfutils-0.138~15^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5a04b9f38a416d43b3197c5d06ff6e75dd8490b7;p=thirdparty%2Felfutils.git Implement AMD 3DNOW disassembly. --- diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog index c63486592..db2a3f025 100644 --- a/libcpu/ChangeLog +++ b/libcpu/ChangeLog @@ -1,3 +1,8 @@ +2008-12-19 Ulrich Drepper + + * defs/i386: Add entry for AMD 3DNOW. + * i386_disasm.c: Implement AMD 3DNOW disassembly. + 2008-12-17 Ulrich Drepper * i386_disasm.c (i386_disasm): If instruction matches prefix, diff --git a/libcpu/defs/i386 b/libcpu/defs/i386 index 4abbc261b..3ae25ccb7 100644 --- a/libcpu/defs/i386 +++ b/libcpu/defs/i386 @@ -911,6 +911,7 @@ ifdef(`i386', 00001111,10101110,11110000:mfence 00001111,10101110,11111000:sfence 00001111,10101110,{mod}111{r_m}:clflush {mod}{r_m} +00001111,00001111,{MOD}{mmxreg}{R_M}:INVALID {MOD}{R_M},{mmxreg} # ORDER: dnl Many previous entries depend on this being last. 000{sreg2}111:pop {sreg2} diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index b676216a8..5da61705b 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -184,6 +184,73 @@ static const char *prefix_str[] = #endif +static const char amd3dnowstr[] = +#define MNE_3DNOW_PAVGUSB 1 + "pavgusb\0" +#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8) + "pfadd\0" +#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6) + "pfsub\0" +#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6) + "pfsubr\0" +#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7) + "pfacc\0" +#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6) + "pfcmpge\0" +#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8) + "pfcmpgt\0" +#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8) + "pfcmpeq\0" +#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8) + "pfmin\0" +#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6) + "pfmax\0" +#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6) + "pi2fd\0" +#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6) + "pf2id\0" +#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6) + "pfrcp\0" +#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6) + "pfrsqrt\0" +#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8) + "pfmul\0" +#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6) + "pfrcpit1\0" +#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9) + "pfrsqit1\0" +#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9) + "pfrcpit2\0" +#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9) + "pmulhrw"; + +#define AMD3DNOW_LOW_IDX 0x0d +#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1) +#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX) +static unsigned char amd3dnow[] = + { + [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB, + [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD, + [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB, + [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR, + [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC, + [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE, + [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT, + [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ, + [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN, + [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX, + [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD, + [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID, + [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP, + [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT, + [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL, + [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1, + [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1, + [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2, + [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW + }; + + struct output_data { GElf_Addr addr; @@ -623,6 +690,24 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, break; case 0x0f: + if (data[1] == 0x0f) + { + /* AMD 3DNOW. We need one more byte. */ + if (param_start >= end) + goto not; + if (*param_start < AMD3DNOW_LOW_IDX + || *param_start > AMD3DNOW_HIGH_IDX) + goto not; + unsigned int idx + = amd3dnow[AMD3DNOW_IDX (*param_start)]; + if (idx == 0) + goto not; + str = amd3dnowstr + idx - 1; + /* Eat the immediate byte indicating the + operation. */ + ++param_start; + break; + } #ifdef X86_64 if (data[1] == 0xc7) { diff --git a/tests/ChangeLog b/tests/ChangeLog index b1471c1b0..28667d673 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2008-12-19 Ulrich Drepper + + * testfile44.S.bz2: Add tests for AMD 3DNOW. + * testfile45.S.bz2: Likewise. + * testfile44.expect.bz2: Adjust accordingly. + * testfile45.expect.bz2: Likewise. + 2008-11-26 Roland McGrath * dwfl-bug-getmodules.c: New file. diff --git a/tests/testfile44.S.bz2 b/tests/testfile44.S.bz2 index cbd0da3d1..64bddea39 100644 Binary files a/tests/testfile44.S.bz2 and b/tests/testfile44.S.bz2 differ diff --git a/tests/testfile44.expect.bz2 b/tests/testfile44.expect.bz2 index 2347aea1c..598773151 100644 Binary files a/tests/testfile44.expect.bz2 and b/tests/testfile44.expect.bz2 differ diff --git a/tests/testfile45.S.bz2 b/tests/testfile45.S.bz2 index 91b479559..95bcf8649 100644 Binary files a/tests/testfile45.S.bz2 and b/tests/testfile45.S.bz2 differ diff --git a/tests/testfile45.expect.bz2 b/tests/testfile45.expect.bz2 index 06b4d9bd2..dcd7b9a9f 100644 Binary files a/tests/testfile45.expect.bz2 and b/tests/testfile45.expect.bz2 differ