diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-01-09 05:39:28 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2008-01-09 05:39:28 +0000 |
commit | ff99322e986f8400995b4371dc39ea59e1252d5c (patch) | |
tree | 3a288354395723dc0a375d38111c9fe4a03e3a53 | |
parent | 9e6925dd43d4e6572b69194232f6152f232e737d (diff) |
Add x86-64 disassembler support.
-rw-r--r-- | backends/ChangeLog | 10 | ||||
-rw-r--r-- | backends/Makefile.am | 5 | ||||
-rw-r--r-- | backends/x86_64_init.c | 5 | ||||
-rw-r--r-- | libcpu/ChangeLog | 9 | ||||
-rw-r--r-- | libcpu/Makefile.am | 16 | ||||
-rw-r--r-- | libcpu/defs/i386 | 147 | ||||
-rw-r--r-- | libcpu/defs/x86_64 | 341 | ||||
-rw-r--r-- | libcpu/i386_data.h | 466 | ||||
-rw-r--r-- | libcpu/i386_disasm.c | 118 | ||||
-rw-r--r-- | libcpu/i386_parse.y | 5 | ||||
-rw-r--r-- | tests/ChangeLog | 11 | ||||
-rw-r--r-- | tests/Makefile.am | 7 | ||||
-rwxr-xr-x | tests/run-disasm-x86-64.sh | 36 | ||||
-rwxr-xr-x | tests/run-disasm-x86.sh (renamed from tests/run-disasm.sh) | 0 | ||||
-rw-r--r-- | tests/testfile44.S.bz2 | bin | 16107 -> 16435 bytes | |||
-rw-r--r-- | tests/testfile44.expect.bz2 | bin | 53649 -> 54232 bytes | |||
-rw-r--r-- | tests/testfile45.S.bz2 | bin | 0 -> 22669 bytes | |||
-rw-r--r-- | tests/testfile45.expect.bz2 | bin | 0 -> 74090 bytes |
18 files changed, 694 insertions, 482 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog index 3e35ef26..25155db3 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,13 @@ +2008-01-08 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Add x86-64 disassembler. + * x86_64_init.c (x86_64_init): Hook up disassembler. + +2007-12-28 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Add x86 disassembler. + * i386_init.c (i386_init): Hook up disassembler. + 2007-12-15 Roland McGrath <roland@redhat.com> * ppc_regs.c (ppc_register_info): Return "spefscr", not "spr512". diff --git a/backends/Makefile.am b/backends/Makefile.am index ef21717c..79fccfdc 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 2000-2006, 2007 Red Hat, Inc. +## Copyright (C) 2000-2006, 2007, 2008 Red Hat, Inc. ## This file is part of Red Hat elfutils. ## ## Red Hat elfutils is free software; you can redistribute it and/or modify @@ -72,8 +72,7 @@ am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os) x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c \ x86_64_retval.c x86_64_regs.c i386_auxv.c -# XXX Not yet -# cpu_x86_64 = ../libcpu/libcpu_x86_64.a +cpu_x86_64 = ../libcpu/libcpu_x86_64.a libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS) am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os) diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c index 8524b771..4e9eb55c 100644 --- a/backends/x86_64_init.c +++ b/backends/x86_64_init.c @@ -1,5 +1,5 @@ /* Initialization of x86-64 specific backend library. - Copyright (C) 2002, 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 2002, 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -54,8 +54,7 @@ x86_64_init (elf, machine, eh, ehlen) HOOK (eh, return_value_location); HOOK (eh, register_info); HOOK (eh, auxv_info); - // XXX Not yet. - // HOOK (eh, disasm); + HOOK (eh, disasm); return MODVERSION; } diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog index 9ce29d29..9bb8175d 100644 --- a/libcpu/ChangeLog +++ b/libcpu/ChangeLog @@ -1,3 +1,12 @@ +2008-01-08 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am: Enable x86-64 again. + * defs/i386: Lots of changes for x86-64. + * i386_data.h: Add support for use in x86-64 disassembler. + * i386_disasm.c: Likewise. + * i386_parse.y: Likewise. + * defs/x86_64: Removed. + 2008-01-04 Ulrich Drepper <drepper@redhat.com> * defs/i386: Cleanups, remove masks which are not needed. diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am index a11f0209..c2e5b747 100644 --- a/libcpu/Makefile.am +++ b/libcpu/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 2002, 2004, 2005, 2007 Red Hat, Inc. +## Copyright (C) 2002, 2004, 2005, 2007, 2008 Red Hat, Inc. ## This file is part of Red Hat elfutils. ## ## Red Hat elfutils is free software; you can redistribute it and/or modify @@ -43,13 +43,11 @@ if MUDFLAP libmudflap = -lmudflap endif -# XXX x86-64 uncommented for now. -noinst_LIBRARIES = libcpu_i386.a# libcpu_x86_64.a +noinst_LIBRARIES = libcpu_i386.a libcpu_x86_64.a noinst_PROGRAMS = i386_gendis libcpu_i386_a_SOURCES = i386_disasm.c -# XXX Unused for now. -#libcpu_x86_64_a_SOURCES = x86_64_disasm.c +libcpu_x86_64_a_SOURCES = x86_64_disasm.c i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y @@ -58,11 +56,11 @@ x86_64_disasm.o: x86_64.mnemonics x86_64_dis.h i386_disasm.c i386_dis.h: i386_gendis $(srcdir)/defs/i386 m4 -Di386 -DDISASSEMBLER $(srcdir)/defs/i386 | ./i386_gendis - > $@ -x86_64_dis.h: i386_gendis $(srcdir)/defs/x86_64 - m4 -Dx86_64 -DDISASSEMBLER $(srcdir)/defs/x86_64 | ./i386_gendis - > $@ +x86_64_dis.h: i386_gendis $(srcdir)/defs/i386 + m4 -Dx86_64 -DDISASSEMBLER $(srcdir)/defs/i386 | ./i386_gendis - > $@ -i386.mnemonics x86_64.mnemonics: %.mnemonics: $(srcdir)/defs/% - m4 -D$(<F) -DDISASSEMBLER $^ \ +i386.mnemonics x86_64.mnemonics: %.mnemonics: $(srcdir)/defs/i386 + m4 -D$(@:.mnemonics=) -DDISASSEMBLER $^ \ | sed '1,/^%%/d;/^#/d;/^[[:space:]]*$$/d;s/[^:]*:\([^[:space:]]*\).*/MNE(\1)/;s/{[^}]*}//g;/INVALID/d' \ | sort -u > $@ diff --git a/libcpu/defs/i386 b/libcpu/defs/i386 index 8c6602e2..9c90d824 100644 --- a/libcpu/defs/i386 +++ b/libcpu/defs/i386 @@ -1,6 +1,8 @@ %mask {s} 1 %mask {w} 1 %mask {w1} 1 +%mask {W1} 1 +%mask {W2} 1 dnl floating point reg suffix %mask {D} 1 %mask {imm8} 8 @@ -8,6 +10,7 @@ dnl floating point reg suffix %mask {imm16} 16 %mask {reg} 3 %mask {reg16} 3 +%mask {reg64} 3 %mask {tttn} 4 %mask {mod} 2 %mask {moda} 2 @@ -17,6 +20,8 @@ dnl like {r_m} but referencing byte register %mask {8r_m} 3 dnl like {r_m} but referencing 16-bit register %mask {16r_m} 3 +dnl like {r_m} but referencing 32- or 64-bit register +%mask {64r_m} 3 %mask {disp8} 8 dnl imm really is 8/16/32 bit depending on the situation. %mask {imm} 8 @@ -62,18 +67,18 @@ ifdef(`i386', 0001010{w},{imm}:adc {imm}{w},{ax}{w} 1000000{w},{mod}010{r_m},{imm}:adc{w} {imm}{w},{mod}{r_m}{w} 1000001{w},{mod}010{r_m},{imms8}:adc{w} {imms8},{mod}{r_m} -0001000{w},{mod}{reg}{r_m}:adc {reg}{w},{mod}{r_m} -0001001{w},{mod}{reg}{r_m}:adc {mod}{r_m},{reg}{w} +0001000{w},{mod}{reg}{r_m}:adc {reg}{w},{mod}{r_m}{w} +0001001{w},{mod}{reg}{r_m}:adc {mod}{r_m}{w},{reg}{w} 0000010{w},{imm}:add {imm}{w},{ax}{w} 1000000{w},{mod}000{r_m},{imm}:add{w} {imm}{w},{mod}{r_m}{w} 10000011,{mod}000{r_m},{imms8}:add{w0} {imms8},{mod}{r_m} -0000000{w},{mod}{reg}{r_m}:add {reg}{w},{mod}{r_m} -0000001{w},{mod}{reg}{r_m}:add {mod}{r_m},{reg}{w} +0000000{w},{mod}{reg}{r_m}:add {reg}{w},{mod}{r_m}{w} +0000001{w},{mod}{reg}{r_m}:add {mod}{r_m}{w},{reg}{w} 01100110,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubpd {Mod}{R_m},{xmmreg} 11110010,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubps {Mod}{R_m},{xmmreg} 0010010{w},{imm}:and {imm}{w},{ax}{w} 1000000{w},{mod}100{r_m},{imm}:and{w} {imm}{w},{mod}{r_m}{w} -1000001{w},{mod}100{r_m},{imms}:and{w} {imms},{mod}{r_m} +1000001{w},{mod}100{r_m},{imms8}:and{w} {imms8},{mod}{r_m} 0010000{w},{mod}{reg}{r_m}:and {reg}{w},{mod}{r_m}{w} 0010001{w},{mod}{reg}{r_m}:and {mod}{r_m}{w},{reg}{w} 01100110,00001111,01010100,{Mod}{xmmreg}{R_m}:andpd {Mod}{R_m},{xmmreg} @@ -83,6 +88,8 @@ ifdef(`i386', ifdef(`i386', `01100011,{mod}{reg16}{r_m}:arpl {reg16},{mod}{r_m} 01100010,{moda}{reg}{r_m}:bound {reg},{moda}{r_m} +', +`01100011,{mod}{reg64}{r_m}:movslq {mod}{r_m},{reg64} ')dnl 00001111,10111100,{mod}{reg}{r_m}:bsf {mod}{r_m},{reg} 00001111,10111101,{mod}{reg}{r_m}:bsr {mod}{r_m},{reg} @@ -95,12 +102,12 @@ ifdef(`i386', 00001111,10111010,{mod}110{r_m},{imm8}:btr{w} {imm8},{mod}{r_m} 00001111,10101011,{mod}{reg}{r_m}:bts {reg},{mod}{r_m} 00001111,10111010,{mod}101{r_m},{imm8}:bts{w} {imm8},{mod}{r_m} -11101000,{rel}:call {rel} -11111111,{mod}010{r_m}:call *{mod}{r_m} +11101000,{rel}:call{W} {rel} +11111111,{mod}010{64r_m}:call{W} *{mod}{64r_m} ifdef(`i386', `10011010,{absval},{sel}:lcall {sel},{absval} ')dnl -11111111,{mod}011{r_m}:lcall *{mod}{r_m} +11111111,{mod}011{64r_m}:lcall{W} *{mod}{64r_m} # SPECIAL 10011000:[{rex.w}?cltq:{dpfx}?cbtw:cwtl] 10011000:INVALID # SPECIAL 10011001:[{rew.w}?cqto:{dpfx}?cltd:cwtd] @@ -120,10 +127,17 @@ ifdef(`i386', 10000011,{mod}111{r_m},{imms8}:cmp{w0} {imms8},{mod}{r_m} 0011100{w},{mod}{reg}{r_m}:cmp {reg}{w},{mod}{r_m}{w} 0011101{w},{mod}{reg}{r_m}:cmp {mod}{r_m}{w},{reg}{w} -11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpsd {imm8},{Mod}{R_m},{xmmreg} +ifdef(`ASSEMBLER', +`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpsd {imm8},{Mod}{R_m},{xmmreg} 11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpss {imm8},{Mod}{R_m},{xmmreg} 01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmppd {imm8},{Mod}{R_m},{xmmreg} 00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpps {imm8},{Mod}{R_m},{xmmreg} +', +`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg} +11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg} +01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg} +00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg} +')dnl 1010011{w}:{RE}cmps{w} {es_di},{ds_si} 00001111,1011000{w},{mod}{reg}{r_m}:cmpxchg {reg}{w},{mod}{r_m}{w} ifdef(`i386', @@ -146,7 +160,7 @@ ifdef(`i386', ')dnl 1111011{w},{mod}110{r_m}:div{w} {mod}{r_m}{w} 00001111,01110111:emms -11001000,{imm16},{imm8}:enter {imm16},{imm8} +11001000,{imm16},{imm8}:enter{W} {imm16},{imm8} 11011001,11010000:fnop 11011001,11100000:fchs 11011001,11100001:fabs @@ -342,33 +356,44 @@ ifdef(`ASSEMBLER', 0110110{w}:{R}ins{w} {dx},{es_di} 11001101,{imm8}:int {imm8} 11001100:int3 -11001110:into +ifdef(`i386', +`11001110:into +')dnl 00001111,00001000:invd # ORDER 00001111,00000001,11111000:swapgs 00001111,00000001,{mod}111{r_m}:invlpg {mod}{r_m} # ORDER END -11001111:iret{W} +11001111:iret{W1} 0111{tttn},{disp8}:j{tttn} {disp8} 00001111,1000{tttn},{rel}:j{tttn} {rel} 00001111,1001{tttn},{mod}000{8r_m}:set{tttn} {mod}{8r_m} # SPECIAL 11100011,{disp8}:[{dpfx}?jcxz:jecxz] {disp8} 11100011,{disp8}:INVALID {disp8} 11101011,{disp8}:jmp {disp8} -11101001,{rel}:jmp {rel} -11111111,{mod}100{r_m}:jmp *{mod}{r_m} +11101001,{rel}:jmp{W} {rel} +11111111,{mod}100{64r_m}:jmp{W} *{mod}{64r_m} 11101010,{absval},{sel}:ljmp {sel},{absval} -11111111,{mod}101{r_m}:ljmp *{mod}{r_m} +11111111,{mod}101{64r_m}:ljmp{W} *{mod}{64r_m} 10011111:lahf 00001111,00000010,{mod}{reg}{16r_m}:lar {mod}{16r_m},{reg} -11000101,{mod}{reg}{r_m}:lds {mod}{r_m},{reg} +ifdef(`i386', +`11000101,{mod}{reg}{r_m}:lds {mod}{r_m},{reg} +')dnl 10001101,{mod}{reg}{r_m}:lea {mod}{r_m},{reg} -11001001:leave -11000100,{mod}{reg}{r_m}:les {mod}{r_m},{reg} +11001001:leave{W} +ifdef(`i386', +`11000100,{mod}{reg}{r_m}:les {mod}{r_m},{reg} +')dnl 00001111,10110100,{mod}{reg}{r_m}:lfs {mod}{r_m},{reg} -00001111,00000001,{mod}010{r_m}:lgdt{w0} {mod}{r_m} 00001111,10110101,{mod}{reg}{r_m}:lgs {mod}{r_m},{reg} +ifdef(`i386', +`00001111,00000001,{mod}010{r_m}:lgdt{w0} {mod}{r_m} 00001111,00000001,{mod}011{r_m}:lidt{w0} {mod}{r_m} +', +`00001111,00000001,{mod}010{r_m}:lgdt {mod}{r_m} +00001111,00000001,{mod}011{r_m}:lidt {mod}{r_m} +')dnl 00001111,00000000,{mod}010{16r_m}:lldt {mod}{16r_m} 00001111,00000001,{mod}110{16r_m}:lmsw {mod}{16r_m} 11110000:lock @@ -385,10 +410,10 @@ ifdef(`ASSEMBLER', 1011{w}{reg},{imm}:mov {imm}{w},{reg}{w} 1010000{w},{abs}:mov {abs},{ax}{w} 1010001{w},{abs}:mov {ax}{w},{abs} -00001111,00100000,11{ccc}{reg}:mov {ccc},{reg} -00001111,00100010,11{ccc}{reg}:mov {reg},{ccc} -00001111,00100001,11{ddd}{reg}:mov {ddd},{reg} -00001111,00100011,11{ddd}{reg}:mov {reg},{ddd} +00001111,00100000,11{ccc}{reg64}:mov {ccc},{reg64} +00001111,00100010,11{ccc}{reg64}:mov {reg64},{ccc} +00001111,00100001,11{ddd}{reg64}:mov {ddd},{reg64} +00001111,00100011,11{ddd}{reg64}:mov {reg64},{ddd} 10001100,{mod}{sreg3}{r_m}:mov {sreg3},{mod}{r_m} 10001110,{mod}{sreg3}{r_m}:mov {mod}{r_m},{sreg3} 1010010{w}:{R}movs{w} {ds_si},{es_di} @@ -398,12 +423,8 @@ ifdef(`ASSEMBLER', 00001111,10110111,{mod}{reg}{16r_m}:movzwl {mod}{16r_m},{reg} 1111011{w},{mod}100{r_m}:mul{w} {mod}{r_m}{w} 1111011{w},{mod}011{r_m}:neg{w} {mod}{r_m}{w} -ifdef(`ASSEMBLER', -`10010000:nop 11110011,10010000:pause -', -`10010000:{R}INVALID -')dnl +10010000:nop 1111011{w},{mod}010{r_m}:not{w} {mod}{r_m}{w} 0000100{w},{mod}{reg}{r_m}:or {reg}{w},{mod}{r_m}{w} 0000101{w},{mod}{reg}{r_m}:or {mod}{r_m}{w},{reg}{w} @@ -413,17 +434,36 @@ ifdef(`ASSEMBLER', 1110011{w},{imm8}:out {ax}{w},{imm8} 1110111{w}:out {ax}{w},{dx} 0110111{w}:{R}outs{w} {ds_si},{dx} -10001111,{mod}000{r_m}:pop{w} {mod}{r_m} -01011{reg}:pop {reg} -00001111,10{sreg3}001:pop {sreg3} -01100001:popa{W} +ifdef(`i386', +`10001111,{mod}000{r_m}:pop{w} {mod}{r_m} +', +# XXX This is not the cleanest way... +`10001111,11000{reg64}:pop {reg64} +10001111,{mod}000{r_m}:pop{W} {mod}{r_m} +')dnl +00001111,10{sreg3}001:pop{W} {sreg3} 10011101:popf{W} -11111111,{mod}110{r_m}:push{w} {mod}{r_m} -01010{reg}:push {reg} -011010{s}0,{imm}:push {imm}{s} +# XXX This is not the cleanest way... +ifdef(`i386', +`11111111,{mod}110{r_m}:push{w} {mod}{r_m} +', +`11111111,11110{reg64}:push {reg64} +11111111,{mod}110{r_m}:pushq {mod}{r_m} +')dnl +ifdef(`i386', +`01010{reg}:push {reg} +01011{reg}:pop {reg} +', +`01010{reg64}:push {reg64} +01011{reg64}:pop {reg64} +')dnl +011010{s}0,{imm}:push{W} {imm}{s} 000{sreg2}110:push {sreg2} -00001111,10{sreg3}000:push {sreg3} -01100000:pusha{W} +00001111,10{sreg3}000:push{W} {sreg3} +ifdef(`i386', +`01100000:pusha{W} +01100001:popa{W} +')dnl 10011100:pushf{W} 1101000{w},{mod}010{r_m}:rcl{w} {mod}{r_m}{w} 1101001{w},{mod}010{r_m}:rcl{w} %cl,{mod}{r_m}{w} @@ -434,8 +474,8 @@ ifdef(`ASSEMBLER', 00001111,00110010:rdmsr 00001111,00110011:rdpmc 00001111,00110001:rdtsc -11000011:ret -11000010,{imm16}:ret {imm16} +11000011:ret{W} +11000010,{imm16}:ret{W} {imm16} 11001011:lret 11001010,{imm16}:lret {imm16} 1101000{w},{mod}000{r_m}:rol{w} {mod}{r_m}{w} @@ -453,7 +493,7 @@ ifdef(`ASSEMBLER', 0001101{w},{mod}{reg}{r_m}:sbb {mod}{r_m}{w},{reg}{w} 0001110{w},{imm}:sbb {imm}{w},{ax}{w} 1000000{w},{mod}011{r_m},{imm}:sbb{w} {imm}{w},{mod}{r_m}{w} -1000001{w},{mod}011{r_m},{imms}:sbb{w} {imms},{mod}{r_m} +1000001{w},{mod}011{r_m},{imms8}:sbb{w} {imms8},{mod}{r_m} 1010111{w}:{RE}scas {es_di},{ax}{w} 00001111,1001{tttn},{mod}000{r_m}:set{tttn} {mod}{r_m} 1101000{w},{mod}100{r_m}:shl{w} {mod}{r_m}{w} @@ -471,14 +511,27 @@ ifdef(`ASSEMBLER', 00001111,00000001,11000010:vmlaunch 00001111,00000001,11000011:vmresume 00001111,00000001,11000100:vmxoff -00001111,01111000,{mod}{reg}{r_m}:vmread {reg},{mod}{r_m} -00001111,01111001,{mod}{reg}{r_m}:vmwrite {mod}{r_m},{reg} -00001111,00000001,{mod}000{r_m}:sgdtl {mod}{r_m} +00001111,01111000,{mod}{reg64}{64r_m}:vmread {reg64},{mod}{64r_m} +00001111,01111001,{mod}{reg64}{64r_m}:vmwrite {mod}{64r_m},{reg64} +ifdef(`i386', +`00001111,00000001,{mod}000{r_m}:sgdtl {mod}{r_m} +', +`00001111,00000001,{mod}000{r_m}:sgdt {mod}{r_m} +')dnl # ORDER END # ORDER -00001111,00000001,11001000:monitor %eax,%ecx,%edx +ifdef(`i386', +`00001111,00000001,11001000:monitor %eax,%ecx,%edx 00001111,00000001,11001001:mwait %eax,%ecx -00001111,00000001,{mod}001{r_m}:sidtl {mod}{r_m} +', +`00001111,00000001,11001000:monitor %rax,%rcx,%rdx +00001111,00000001,11001001:mwait %rax,%rcx +')dnl +ifdef(`i386', +`00001111,00000001,{mod}001{r_m}:sidtl {mod}{r_m} +', +`00001111,00000001,{mod}001{r_m}:sidt {mod}{r_m} +')dnl # ORDER END 00001111,00000000,{mod}000{r_m}:sldt {mod}{r_m} 00001111,00000001,{mod}100{r_m}:smsw {mod}{r_m} @@ -491,7 +544,7 @@ ifdef(`ASSEMBLER', 0010101{w},{mod}{reg}{r_m}:sub {mod}{r_m}{w},{reg}{w} 0010110{w},{imm}:sub {imm}{w},{ax}{w} 1000000{w},{mod}101{r_m},{imm}:sub{w} {imm}{w},{mod}{r_m}{w} -1000001{w},{mod}101{r_m},{imms}:sub{w} {imms},{mod}{r_m} +1000001{w},{mod}101{r_m},{imms8}:sub{w} {imms8},{mod}{r_m} 1000010{w},{mod}{reg}{r_m}:test {reg}{w},{mod}{r_m}{w} 1010100{w},{imm}:test {imm}{w},{ax}{w} 1111011{w},{mod}000{r_m},{imm}:test{w} {imm}{w},{mod}{r_m}{w} @@ -515,7 +568,7 @@ ifdef(`ASSEMBLER', 0011001{w},{mod}{reg}{r_m}:xor {mod}{r_m}{w},{reg}{w} 0011010{w},{imm}:xor {imm}{w},{ax}{w} 1000000{w},{mod}110{r_m},{imm}:xor{w} {imm}{w},{mod}{r_m}{w} -1000001{w},{mod}110{r_m},{imms}:xor{w} {imms},{mod}{r_m} +1000001{w},{mod}110{r_m},{imms8}:xor{w} {imms8},{mod}{r_m} 00001111,01110111:emms 01100110,00001111,11011011,{Mod}{xmmreg}{R_m}:pand {Mod}{R_m},{xmmreg} 00001111,11011011,{MOD}{mmxreg}{R_M}:pand {MOD}{R_M},{mmxreg} diff --git a/libcpu/defs/x86_64 b/libcpu/defs/x86_64 deleted file mode 100644 index 090c4751..00000000 --- a/libcpu/defs/x86_64 +++ /dev/null @@ -1,341 +0,0 @@ -%mask {s} 1 -%mask {w} 1 -%mask {D} 1 -%mask {imm8} 8 -%mask {imm16} 16 -%mask {reg} 3 -%mask {tttn} 4 -%mask {gg} 2 -%mask {mod} 2 -%mask {MOD} 2 -%mask {r_m} 3 -%mask {disp8} 8 -# imm really is 8/16/32 bit depending on the situation. -%mask {imm} 8 -%mask {abs} 32 -%mask {sel} 16 -%mask {imm32} 32 -%mask {dispA} 32 -%mask {ccc} 3 -%mask {ddd} 3 -%mask {sreg3} 3 -%mask {sreg2} 2 -%mask {mmxreg} 3 -%mask {R_M} 3 -%mask {0g} 2 -%mask {GG} 2 -%mask {gG} 2 -%mask {Mod} 2 -%mask {xmmreg} 3 -%mask {R_m} 3 -%mask {xmmreg1} 3 -%mask {xmmreg2} 3 -%mask {mmreg} 3 -%prefix {R} -%prefix {RE} -%suffix {W} -%suffix {WW} -%synonym {xmmreg1} {xmmreg} -%synonym {xmmreg2} {xmmreg} - -%% -0001010{w},{imm}:adc {imm}{w},{ax}{w} -1000000{w},{mod}010{r_m},{imm}:adc{w} {imm},{mod}{r_m} -1000001{w},{mod}010{r_m},{imm8}:adc{w} {imm8},{mod}{r_m} -0001000{w},{mod}{reg}{r_m}:adc{w} {reg},{mod}{r_m} -0001001{w},{mod}{reg}{r_m}:adc{w} {mod}{r_m},{reg} -0000010{w},{imm}:add {imm}{w},{ax}{w} -1000000{w},{mod}000{r_m},{imm}:add{w} {imm},{mod}{r_m} -1000001{w},{mod}000{r_m},{imm8}:add{w} {imm8},{mod}{r_m} -0000000{w},{mod}{reg}{r_m}:add {reg}{w},{mod}{r_m} -0000001{w},{mod}{reg}{r_m}:add {mod}{r_m},{reg}{w} -01100110,00001111,01011000,{Mod}{xmmreg}{R_m}:addpd {Mod}{R_m},{xmmreg} -00001111,01011000,{Mod}{xmmreg}{R_m}:addps {Mod}{R_m},{xmmreg} -11110010,00001111,01011000,{Mod}{xmmreg}{R_m}:addsd {Mod}{R_m},{xmmreg} -11110011,00001111,01011000,{Mod}{xmmreg}{R_m}:addss {Mod}{R_m},{xmmreg} -01100110,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubpd {Mod}{R_m},{xmmreg} -11110010,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubps {Mod}{R_m},{xmmreg} -# -# -# -0010000{w},{mod}{reg}{r_m}:and{w} {reg},{mod}{r_m} -0010001{w},{mod}{reg}{r_m}:and{w} {mod}{r_m},{reg} -0010010{w},{imm}:and {imm}{w},{ax}{w} -100000{s}{w},{mod}100{r_m},{imm}:and{w} {imm}{s},{mod}{r_m} -01100011,{mod}{reg}{r_m}:arpl {reg},{mod}{r_m} -01100010,{mod}{reg}{r_m}:bound {reg},{mod}{r_m} -00001111,10111100,{mod}{reg}{r_m}:bsf {reg},{mod}{r_m} -00001111,10111101,{mod}{reg}{r_m}:bsr {reg},{mod}{r_m} -00001111,11001{reg}:bswap {reg} -00001111,10111010,{mod}100{r_m},{imm8}:bt {imm8},{mod}{r_m} -00001111,10100011,{mod}{reg}{r_m}:bt {reg},{mod}{r_m} -00001111,10111010,{mod}111{r_m},{imm8}:btc {imm8},{mod}{r_m} -00001111,10111011,{mod}{reg}{r_m}:btc {reg},{mod}{r_m} -00001111,10111010,{mod}110{r_m},{imm8}:btr {imm8},{mod}{r_m} -00001111,10110011,{mod}{reg}{r_m}:btr {reg},{mod}{r_m} -00001111,10111010,{mod}101{r_m},{imm8}:bts {imm8},{mod}{r_m} -00001111,10101011,{mod}{reg}{r_m}:bts {reg},{mod}{r_m} -11101000,{abs}:call {abs} -11111111,{mod}010{r_m}:call *{mod}{r_m} -10011010,{abs},{sel}:lcall {sel},{abs} -11111111,{mod}011{r_m}:lcall {mod}{r_m} -10011000:cbt{WW} -#SPECIAL 10011001:[{dpfx}?cltd:cwtd] -11111000:clc -11111100:cld -11111010:cli -00001111,00000110:clts -11110101:cmc -00001111,0100{tttn},{mod}{reg}{r_m}:cmov{tttn} {mod}{r_m},{reg} -0011100{w},{mod}{reg}{r_m}:cmp{w} {reg},{mod}{r_m} -0011101{w},{mod}{reg}{r_m}:cmp{w} {mod}{r_m},{reg} -0011110{w},{imm}:cmp {imm}{w},{ax}{w} -100000{s}{w},{mod}111{r_m},{imm}:cmp{w} {imm}{s},{mod}{r_m} -1010011{w}:{RE}cmps{w} -00001111,1011000{w},{mod}{reg}{r_m}:cmpxchg{w} {reg},{mod}{r_m} -00001111,11000111,{mod}{reg}{r_m}:cmpxchg8b {reg},{mod}{r_m} -00001111,10100010:cpuid -00100111:daa -00101111:das -1111111{w},{mod}001{r_m}:dec{w} {mod}{r_m} -01001{reg}:dec {reg} -1111011{w},{mod}110{r_m}:div{w} {mod}{r_m} -11001000,{imm16},{imm8}:enter {imm16},{imm8} -11110100:hlt -1111011{w},{mod}111{r_m}:idiv{w} {mod}{r_m} -1111011{w},{mod}101{r_m}:imul{w} {mod}{r_m} -00001111,10101111,{mod}{reg}{r_m}:imul {reg},{mod}{r_m} -011010{s}1,{mod}{reg}{r_m},{imm}:imul {imm}{s},{mod}{r_m},{reg} -1110010{w},{imm8}:in {imm8},{ax}{w} -1110110{w}:in {dx},{ax}{w} -1111111{w},{mod}000{r_m}:inc{w} {mod}{r_m} -01000{reg}:inc {reg} -0110110{w}:{R}ins{w} {dx},{es_di} -11001101,{imm8}:int {imm8} -11001100:int 3 -11001110:into -00001111,00001000:invd -00001111,00000001,{mod}111{r_m}:invlpg {mod}{r_m} -11001111:iret{W} -0111{tttn},{disp8}:j{tttn} {disp8} -00001111,1000{tttn},{dispA}:j{tttn} {dispA} -#SPECIAL 11100011,{disp8}:[{dpfx}?jcxz:jecxz] {disp8} -11101011,{disp8}:jmp {disp8} -11101001,{dispA}:jmp {dispA} -11111111,{mod}100{r_m}:jmp *{mod}{r_m} -11101010,{abs},{sel}:ljmp {sel},{abs} -11111111,{mod}101{r_m}:ljmp {mod}{r_m} -10011111:lahf -00001111,00000010,{mod}{reg}{r_m}:lar {mod}{r_m},{reg} -11000101,{mod}{reg}{r_m}:lds {mod}{r_m},{reg} -10001101,{mod}{reg}{r_m}:lea {mod}{r_m},{reg} -11001001:leave -11000100,{mod}{reg}{r_m}:les {mod}{r_m},{reg} -00001111,10110100,{mod}{reg}{r_m}:lfs {mod}{r_m},{reg} -00001111,00000001,{mod}010{r_m}:lgdt{WW} {mod}{r_m} -00001111,10110101,{mod}{reg}{r_m}:lgs {mod}{r_m},{reg} -00001111,00000001,{mod}011{r_m}:lidt{WW} {mod}{r_m} -00001111,00000000,{mod}010{r_m}:lldt{WW} {mod}{r_m} -00001111,00000001,{mod}110{r_m}:lmsw {mod}{r_m} -11110000:lock -1010110{w}:{R}lods {ds_si},{ax}{w} -11100010,{disp8}:loop {disp8} -11100001,{disp8}:loope {disp8} -11100000,{disp8}:loopne {disp8} -00001111,00000011,{mod}{reg}{r_m}:lsl {mod}{r_m},{reg} -00001111,10110010,{mod}{reg}{r_m}:lss {mod}{r_m},{reg} -00001111,00000000,{mod}011{r_m}:ltr {mod}{r_m} -1000100{w},{mod}{reg}{r_m}:mov{w} {reg},{mod}{r_m} -1000101{w},{mod}{reg}{r_m}:mov{w} {mod}{r_m},{reg} -1100011{w},{mod}000{r_m},{imm}:mov{w} {imm},{mod}{r_m} -1011{w}{reg},{imm}:mov{w} {imm},{reg} -1010000{w},{abs}:mov {ax}{w},{abs} -1010001{w},{abs}:mov {abs},{ax}{w} -00001111,00100000,11{ccc}{reg}:mov {reg},{ccc} -00001111,00100010,11{ccc}{reg}:mov {ccc},{reg} -00001111,00100001,11{ddd}{reg}:mov {reg},{ddd} -00001111,00100011,11{ddd}{reg}:mov {ddd},{reg} -10001100,{mod}{sreg3}{r_m}:mov {sreg3},{mod}{r_m} -10001110,{mod}{sreg3}{r_m}:mov {mod}{r_m},{sreg3} -1010010{w}:{R}movs{w} {ds_si},{es_di} -00001111,1011111{w},{mod}{reg}{r_m}:movsx{w} {mod}{r_m},{reg} -00001111,1011011{w},{mod}{reg}{r_m}:movzx{w} {mod}{r_m},{reg} -1111011{w},{mod}100{r_m}:mul{w} {mod}{r_m} -1111011{w},{mod}011{r_m}:neg{w} {mod}{r_m} -10010000:nop -11110011,10010000:pause -1111011{w},{mod}010{r_m}:not{w} {mod}{r_m} -0000100{w},{mod}{reg}{r_m}:or{w} {reg},{mod}{r_m} -0000101{w},{mod}{reg}{r_m}:or{w} {mod}{r_m},{reg} -100000{s}{w},{mod}001{r_m},{imm}:or{w} {imm}{s},{mod}{r_m} -0000110{w},{imm}:mov {imm}{w},{ax}{w} -1110011{w},{imm8}:out {ax}{w},{imm8} -1110111{w}:out {ax}{w},{dx} -0110111{w}:{R}outs{w} {ds_si},{dx} -10001111,{mod}000{r_m}:pop {mod}{r_m} -01011{reg}:pop {reg} -000{sreg2}111:pop {sreg2} -00001111,10{sreg3}001:pop {sreg3} -01100001:popa{W} -10011101:popf{W} -11111111,{mod}110{r_m}:push {mod}{r_m} -01010{reg}:push {reg} -011010{s}0,{imm}:push {imm}{s} -000{sreg2}110:push {sreg2} -00001111,10{sreg3}000:push {sreg3} -01100000:pusha{W} -10011100:pushf{W} -1101000{w},{mod}010{r_m}:rcl{w} {mod}{r_m} -1101001{w},{mod}010{r_m}:rcl{w} %cl,{mod}{r_m} -1100000{w},{mod}010{r_m},{imm8}:rcl{w} {imm8},{mod}{r_m} -1101000{w},{mod}011{r_m}:rcr{w} {mod}{r_m} -1101001{w},{mod}011{r_m}:rcr{w} %cl,{mod}{r_m} -1100000{w},{mod}011{r_m},{imm8}:rcr{w} {imm8},{mod}{r_m} -00001111,00110010:rdmsr -00001111,00110011:rdpmc -00001111,00110001:rdtsc -11000011:ret -11000010,{imm16}:ret {imm16} -11001011:lret -11001010,{imm16}:lret {imm16} -1101000{w},{mod}000{r_m}:rol{w} {mod}{r_m} -1101001{w},{mod}000{r_m}:rol{w} %cl,{mod}{r_m} -1100000{w},{mod}000{r_m},{imm8}:rol{w} {imm8},{mod}{r_m} -1101000{w},{mod}001{r_m}:ror{w} {mod}{r_m} -1101001{w},{mod}001{r_m}:ror{w} %cl,{mod}{r_m} -1100000{w},{mod}001{r_m},{imm8}:ror{w} {imm8},{mod}{r_m} -00001111,10101010:rsm -10011110:sahf -1101000{w},{mod}111{r_m}:sar{w} {mod}{r_m} -1101001{w},{mod}111{r_m}:sar{w} %cl,{mod}{r_m} -1100000{w},{mod}111{r_m},{imm8}:sar{w} {imm8},{mod}{r_m} -0001100{w},{mod}{reg}{r_m}:sbb{w} {reg},{mod}{r_m} -0001101{w},{mod}{reg}{r_m}:sbb{w} {mod}{r_m},{reg} -0001110{w},{imm}:sbb {imm}{w},{ax}{w} -100000{s}{w},{mod}011{r_m},{imm}:sbb{w} {imm}{s},{mod}{r_m} -1010111{w}:{RE}scas {es_di},{ax}{w} -00001111,1001{tttn},{mod}000{r_m}:set{tttn} {mod}{r_m} -00001111,00000001,{mod}000{r_m}:sgdt {mod}{r_m} -1101000{w},{mod}100{r_m}:shl{w} {mod}{r_m} -1101001{w},{mod}100{r_m}:shl{w} %cl,{mod}{r_m} -1100000{w},{mod}100{r_m},{imm8}:shl{w} {imm8},{mod}{r_m} -1101000{w},{mod}101{r_m}:shr{w} {mod}{r_m} -00001111,10100100,{mod}{reg}{r_m},{imm8}:shld {imm8},{reg},{mod}{r_m} -00001111,10100101,{mod}{reg}{r_m}:shld %cl,{reg},{mod}{r_m} -1101001{w},{mod}101{r_m}:shr{w} %cl,{mod}{r_m} -1100000{w},{mod}101{r_m},{imm8}:shr{w} {imm8},{mod}{r_m} -00001111,10101100,{mod}{reg}{r_m},{imm8}:shrd {imm8},{reg},{mod}{r_m} -00001111,10101101,{mod}{reg}{r_m}:shrd %cl,{reg},{mod}{r_m} -00001111,00000001,{mod}001{r_m}:sidt {mod}{r_m} -00001111,00000000,{mod}000{r_m}:sldt {mod}{r_m} -00001111,00000001,{mod}100{r_m}:smsw {mod}{r_m} -11111001:stc -11111101:std -11111011:sti -1010101{w}:{R}stos {ax}{w},{es_di} -00001111,00000000,{mod}001{r_m}:str {mod}{r_m} -0010100{w},{mod}{reg}{r_m}:sub{w} {reg},{mod}{r_m} -0010101{w},{mod}{reg}{r_m}:sub{w} {mod}{r_m},{reg} -0010110{w},{imm}:sub {imm}{w},{ax}{w} -100000{s}{w},{mod}101{r_m},{imm}:sub{w} {imm}{s},{mod}{r_m} -1000010{w},{mod}{reg}{r_m}:test{w} {reg},{mod}{r_m}{w} -1000011{w},{mod}{reg}{r_m}:test{w} {mod}{r_m}{w},{reg} -0010100{w},{imm}:test {imm}{w},{ax}{w} -1111011{w},{mod}000{r_m},{imm}:test{w} {imm},{mod}{r_m} -00001111,00001011:ud2a -00001111,00000000,{mod}100{r_m}:verr {mod}{r_m} -00001111,00000000,{mod}101{r_m}:verw {mod}{r_m} -10011011:wait -00001111,00001001:wbinvd -00001111,00110000:wrmsr -00001111,1100000{w},{mod}{reg}{r_m}:xadd{w} {reg},{mod}{r_m} -1000011{w},{mod}{reg}{r_m}:xchg{w} {reg},{mod}{r_m} -11010111:xlat -0011000{w},{mod}{reg}{r_m}:xor{w} {reg},{mod}{r_m} -0011001{w},{mod}{reg}{r_m}:xor{w} {mod}{r_m},{reg} -0011010{w},{imm}:xor {imm}{w},{ax}{w} -100000{s}{w},{mod}110{r_m},{imm}:xor{w} {imm}{s},{mod}{r_m} -00001111,01110111:emms -00001111,01101110,{mod}{mmxreg}{r_m}:movd {mod}{r_m},{mmxreg} -00001111,01111110,{mod}{mmxreg}{r_m}:movd {mmxreg},{mod}{r_m} -00001111,01101111,{MOD}{mmxreg}{R_M}:movq {MOD}{R_M},{mmxreg} -00001111,01111111,{MOD}{mmxreg}{R_M}:movq {mmxreg},{MOD}{R_M} -00001111,01101011,{MOD}{mmxreg}{R_M}:packssdw {MOD}{R_M},{mmxreg} -00001111,01100011,{MOD}{mmxreg}{R_M}:packsswb {MOD}{R_M},{mmxreg} -00001111,01100111,{MOD}{mmxreg}{R_M}:packuswb {MOD}{R_M},{mmxreg} -00001111,111111{gg},{MOD}{mmxreg}{R_M}:padd{gg} {MOD}{R_M},{mmxreg} -00001111,111111{0g},{MOD}{mmxreg}{R_M}:padds{0g} {MOD}{R_M},{mmxreg} -00001111,110111{0g},{MOD}{mmxreg}{R_M}:paddus{0g} {MOD}{R_M},{mmxreg} -00001111,11011011,{MOD}{mmxreg}{R_M}:pand {MOD}{R_M},{mmxreg} -00001111,11011111,{MOD}{mmxreg}{R_M}:pandn {MOD}{R_M},{mmxreg} -00001111,011101{gg},{MOD}{mmxreg}{R_M}:pcmpeq{gg} {MOD}{R_M},{mmxreg} -00001111,011001{gg},{MOD}{mmxreg}{R_M}:pcmpgt{gg} {MOD}{R_M},{mmxreg} -00001111,11110101,{MOD}{mmxreg}{R_M}:pmaddwd {MOD}{R_M},{mmxreg} -00001111,11100101,{MOD}{mmxreg}{R_M}:pmulhw {MOD}{R_M},{mmxreg} -00001111,11010101,{MOD}{mmxreg}{R_M}:pmullw {MOD}{R_M},{mmxreg} -00001111,11101011,{MOD}{mmxreg}{R_M}:por {MOD}{R_M},{mmxreg} -00001111,111100{GG},{MOD}{mmxreg}{R_M}:psll{GG} {MOD}{R_M},{mmxreg} -00001111,011100{GG},11110{mmxreg},{imm8}:psll{GG} {imm8},{mmxreg} -00001111,111000{gG},{MOD}{mmxreg}{R_M}:psra{gG} {MOD}{R_M},{mmxreg} -00001111,011100{gG},11100{mmxreg},{imm8}:psra{gG} {imm8},{mmxreg} -00001111,110100{GG},{MOD}{mmxreg}{R_M}:psrl{GG} {MOD}{R_M},{mmxreg} -00001111,011100{GG},11010{mmxreg},{imm8}:psrl{GG} {imm8},{mmxreg} -00001111,111110{gg},{MOD}{mmxreg}{R_M}:psub{gg} {MOD}{R_M},{mmxreg} -00001111,111010{0g},{MOD}{mmxreg}{R_M}:psubs{0g} {MOD}{R_M},{mmxreg} -00001111,110110{0g},{MOD}{mmxreg}{R_M}:psubus{0g} {MOD}{R_M},{mmxreg} -00001111,011010{gg},{MOD}{mmxreg}{R_M}:punpckh{gg} {MOD}{R_M},{mmxreg} -00001111,011000{gg},{MOD}{mmxreg}{R_M}:punpckl{gg} {MOD}{R_M},{mmxreg} -00001111,11101111,{MOD}{mmxreg}{R_M}:pxor {MOD}{R_M},{mmxreg} -00001111,01011000,{Mod}{xmmreg}{R_m}:addps {Mod}{R_m},{xmmreg} -11110011,00001111,01011000,{Mod}{xmmreg}{R_m}:addss {Mod}{R_m},{xmmreg} -00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg} -00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpleps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnleps {Mod}{R_m},{xmmreg} -00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordps {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqss {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltss {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpless {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordss {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqss {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltss {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnless {Mod}{R_m},{xmmreg} -11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordss {Mod}{R_m},{xmmreg} -00001111,00101111,{Mod}{xmmreg}{R_m}:comiss {Mod}{R_m},{xmmreg} -00001111,00101010,{MOD}{xmmreg}{R_M}:cvtpi2ps {MOD}{R_M},{xmmreg} -00001111,00101101,{MOD}{mmreg}{R_M}:cvtps2pi {MOD}{R_M},{mmreg} -11110011,00001111,00101010,{mod}{xmmreg}{r_m}:cvtsi2ss {mod}{r_m},{xmmreg} -11110011,00001111,00101101,{Mod}{reg}{R_m}:cvtss2si {Mod}{R_m},{reg} -00001111,00101100,{Mod}{mmreg}{R_m}:cvttps2pi {Mod}{R_m},{mmreg} -11110011,00001111,00101100,{Mod}{reg}{R_m}:cvttss2si {Mod}{R_m},{reg} -00001111,01011110,{Mod}{xmmreg}{R_m}:divps {Mod}{R_m},{xmmreg} -11110011,00001111,01011110,{Mod}{xmmreg}{R_m}:divss {Mod}{R_m},{xmmreg} -00001111,10101110,{mod}001{r_m}:fxrstor {mod}{r_m} -00001111,10101110,{mod}000{r_m}:fxsave {mod}{r_m} -00001111,10101110,{mod}010{r_m}:ldmxcsr {mod}{r_m} -00001111,01011111,{Mod}{xmmreg}{R_m}:maxps {Mod}{R_m},{xmmreg} -11110011,00001111,01011111,{Mod}{xmmreg}{R_m}:maxss {Mod}{R_m},{xmmreg} -00001111,01011101,{Mod}{xmmreg}{R_m}:minps {Mod}{R_m},{xmmreg} -11110011,00001111,01011101,{Mod}{xmmreg}{R_m}:minss {Mod}{R_m},{xmmreg} -00001111,00101000,{Mod}{xmmreg}{R_m}:movaps {Mod}{R_m},{xmmreg} -00001111,00101001,{Mod}{xmmreg}{R_m}:movaps {xmmreg},{Mod}{R_m} -# ORDER: -00001111,00010010,11{xmmreg1}{xmmreg2}:movhlps {xmmreg1},{xmmreg2} -00001111,00010011,11{xmmreg1}{xmmreg2}:movhlps {xmmreg2},{xmmreg1} -00001111,00010010,{Mod}{xmmreg}{R_m}:movlps {Mod}{R_m},{xmmreg} -00001111,00010011,{Mod}{xmmreg}{R_m}:movlps {xmmreg},{Mod}{R_m} -# ORDER END: -# ORDER: -00001111,00010110,11{xmmreg1}{xmmreg2}:movlhps {xmmreg1},{xmmreg2} -00001111,00010111,11{xmmreg1}{xmmreg2}:movlhps {xmmreg2},{xmmreg1} -00001111,00010110,{Mod}{xmmreg}{R_m}:movhps {Mod}{R_m},{xmmreg} -00001111,00010111,{Mod}{xmmreg}{R_m}:movhps {xmmreg},{Mod}{R_m} -# ORDER END: -# BOGUS -00000000,11{reg}111:fadd {reg} -00001111,00000001,11000001:vmcall diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h index 5148fa06..398c672b 100644 --- a/libcpu/i386_data.h +++ b/libcpu/i386_data.h @@ -101,7 +101,7 @@ data_prefix (int *prefixes, char *bufp, size_t *bufcntp, size_t bufsize) else if (*prefixes & has_es) { ch = 'e'; - *prefixes &= has_es; + *prefixes &= ~has_es; } else if (*prefixes & has_fs) { @@ -132,10 +132,26 @@ data_prefix (int *prefixes, char *bufp, size_t *bufcntp, size_t bufsize) return 0; } -static const char regs[8][4] = +#ifdef X86_64 +static const char hiregs[8][4] = + { + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" + }; +static const char aregs[8][4] = + { + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi" + }; +static const char dregs[8][4] = + { + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" + }; +#else +static const char aregs[8][4] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; +# define dregs aregs +#endif static int general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), @@ -158,7 +174,48 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), return r; uint_fast8_t modrm = data[opoff1 / 8]; - if ((*prefixes & has_addr16) == 0) +#ifndef X86_64 + if (unlikely ((*prefixes & has_addr16) != 0)) + { + int16_t disp = 0; + bool nodisp = false; + + if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) + /* 16 bit displacement. */ + disp = read_2sbyte_unaligned (&data[opoff1 / 8 + 1]); + else if ((modrm & 0xc0) == 0x40) + /* 8 bit displacement. */ + disp = *(const int8_t *) &data[opoff1 / 8 + 1]; + else if ((modrm & 0xc0) == 0) + nodisp = true; + + char tmpbuf[sizeof ("-0x1234(%rr,%rr)")]; + int n; + if ((modrm & 0xc7) == 6) + n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp); + else + { + n = 0; + if (!nodisp) + n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16, + disp < 0 ? "-" : "", disp < 0 ? -disp : disp); + + if ((modrm & 0x4) == 0) + n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)", + "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]); + else + n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)", + ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]); + } + + if (*bufcntp + n + 1 > bufsize) + return *bufcntp + n + 1 - bufsize; + + memcpy (&bufp[*bufcntp], tmpbuf, n + 1); + *bufcntp += n; + } + else +#endif { if ((modrm & 7) != 4) { @@ -174,16 +231,53 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), else if ((modrm & 0xc0) == 0) nodisp = true; - char tmpbuf[sizeof ("-0x12345678(%rrr)")]; + char tmpbuf[sizeof ("-0x12345678(%rrrr)")]; int n; if (nodisp) - n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", regs[modrm & 7]); + { + n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)", +#ifdef X86_64 + (*prefixes & has_rex_b) ? hiregs[modrm & 7] : +#endif + aregs[modrm & 7]); +#ifdef X86_64 + if (*prefixes & has_addr16) + { + if (*prefixes & has_rex_b) + tmpbuf[n++] = 'd'; + else + tmpbuf[2] = 'e'; + } +#endif + } else if ((modrm & 0xc7) != 5) - n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%s)", - disp < 0 ? "-" : "", disp < 0 ? -disp : disp, - regs[modrm & 7]); + { + int p; + n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)", + disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p, +#ifdef X86_64 + (*prefixes & has_rex_b) ? hiregs[modrm & 7] : +#endif + aregs[modrm & 7]); +#ifdef X86_64 + if (*prefixes & has_addr16) + { + if (*prefixes & has_rex_b) + tmpbuf[n++] = 'd'; + else + tmpbuf[p] = 'e'; + } +#endif + } else - n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); + { +#ifdef X86_64 + n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)", + disp < 0 ? "-" : "", disp < 0 ? -disp : disp); +#else + n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp); +#endif + } if (*bufcntp + n + 1 > bufsize) return *bufcntp + n + 1 - bufsize; @@ -208,10 +302,14 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), else nodisp = true; - char tmpbuf[sizeof ("-0x12345678(%rrr,%rrr,N)")]; + char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")]; char *cp = tmpbuf; int n; - if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25) + if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25 +#ifdef X86_64 + || (*prefixes & has_rex_x) != 0 +#endif + ) { if (!nodisp) { @@ -225,14 +323,40 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5) { *cp++ = '%'; - cp = mempcpy (cp, regs[sib & 7], 3); + cp = stpcpy (cp, +#ifdef X86_64 + (*prefixes & has_rex_b) ? hiregs[sib & 7] : + (*prefixes & has_addr16) ? dregs[sib & 7] : +#endif + aregs[sib & 7]); +#ifdef X86_64 + if ((*prefixes & (has_rex_b | has_addr16)) + == (has_rex_b | has_addr16)) + *cp++ = 'd'; +#endif } - if ((sib & 0x38) != 0x20) + if ((sib & 0x38) != 0x20 +#ifdef X86_64 + || (*prefixes & has_rex_x) != 0 +#endif + ) { *cp++ = ','; *cp++ = '%'; - cp = mempcpy (cp, regs[(sib >> 3) & 7], 3); + cp = stpcpy (cp, +#ifdef X86_64 + (*prefixes & has_rex_x) + ? hiregs[(sib >> 3) & 7] : + (*prefixes & has_addr16) + ? dregs[(sib >> 3) & 7] : +#endif + aregs[(sib >> 3) & 7]); +#ifdef X86_64 + if ((*prefixes & (has_rex_b | has_addr16)) + == (has_rex_b | has_addr16)) + *cp++ = 'd'; +#endif *cp++ = ','; *cp++ = '0' + (1 << (sib >> 6)); @@ -243,7 +367,13 @@ general_mod$r_m (GElf_Addr addr __attribute__ ((unused)), else { assert (! nodisp); - n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp); +#ifdef X86_64 + if ((*prefixes & has_addr16) == 0) + n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64, + (int64_t) disp); + else +#endif + n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp); cp += n; } @@ -283,7 +413,7 @@ FCT_MOD$R_M (GElf_Addr addr __attribute__ ((unused)), size_t avail = bufsize - *bufcntp; int needed; if (*prefixes & (has_rep | has_repne)) - needed = snprintf (&bufp[*bufcntp], avail, "%%%s", regs[byte]); + needed = snprintf (&bufp[*bufcntp], avail, "%%%s", dregs[byte]); else needed = snprintf (&bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte); if ((size_t) needed > avail) @@ -344,7 +474,13 @@ generic_abs (int *prefixes __attribute__ ((unused)), const uint8_t *end __attribute__ ((unused)), DisasmGetSymCB_t symcb __attribute__ ((unused)), void *symcbarg __attribute__ ((unused)), - const char *absstring) + const char *absstring +#ifdef X86_64 + , int abslen +#else +# define abslen 4 +#endif + ) { int r = data_prefix (prefixes, bufp, bufcntp, bufsize); if (r != 0) @@ -352,12 +488,22 @@ generic_abs (int *prefixes __attribute__ ((unused)), assert (opoff1 % 8 == 0); assert (opoff1 / 8 == 1); - if (*param_start + 4 > end) + if (*param_start + abslen > end) return -1; - *param_start += 4; - uint32_t absval = read_4ubyte_unaligned (&data[1]); + *param_start += abslen; +#ifndef X86_64 + uint32_t absval; +# define ABSPRIFMT PRIx32 +#else + uint64_t absval; +# define ABSPRIFMT PRIx64 + if (abslen == 8) + absval = read_8ubyte_unaligned (&data[1]); + else +#endif + absval = read_4ubyte_unaligned (&data[1]); size_t avail = bufsize - *bufcntp; - int needed = snprintf (&bufp[*bufcntp], avail, "%s0x%" PRIx32, + int needed = snprintf (&bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT, absstring, absval); if ((size_t) needed > avail) return needed - avail; @@ -383,7 +529,11 @@ FCT_absval (GElf_Addr addr __attribute__ ((unused)), { return generic_abs (prefixes, opoff1, bufp, bufcntp, bufsize, data, param_start, end, symcb, - symcbarg, "$"); + symcbarg, "$" +#ifdef X86_64 + , 4 +#endif + ); } static int @@ -404,7 +554,11 @@ FCT_abs (GElf_Addr addr __attribute__ ((unused)), { return generic_abs (prefixes, opoff1, bufp, bufcntp, bufsize, data, param_start, end, symcb, - symcbarg, ""); + symcbarg, "" +#ifdef X86_64 + , 8 +#endif + ); } static int @@ -576,7 +730,12 @@ FCT_ds_xx (const char *reg, size_t avail = bufsize - *bufcntp; int needed = snprintf (&bufp[*bufcntp], avail, "(%%%s%s)", - *prefixes & idx_addr16 ? "" : "e", reg); +#ifdef X86_64 + *prefixes & idx_addr16 ? "e" : "r", +#else + *prefixes & idx_addr16 ? "" : "e", +#endif + reg); if ((size_t) needed > avail) return (size_t) needed - avail; *bufcntp += needed; @@ -665,7 +824,12 @@ FCT_es_di (GElf_Addr addr __attribute__ ((unused)), { size_t avail = bufsize - *bufcntp; int needed = snprintf (&bufp[*bufcntp], avail, "%%es:(%%%sdi)", - *prefixes & idx_addr16 ? "" : "e"); +#ifdef X86_64 + *prefixes & idx_addr16 ? "e" : "r" +#else + *prefixes & idx_addr16 ? "" : "e" +#endif + ); if ((size_t) needed > avail) return (size_t) needed - avail; *bufcntp += needed; @@ -757,9 +921,14 @@ FCT_imms (GElf_Addr addr __attribute__ ((unused)), void *symcbarg __attribute__ ((unused))) { size_t avail = bufsize - *bufcntp; - int_fast8_t byte = *(*param_start)++; + int8_t byte = *(*param_start)++; +#ifdef X86_64 + int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx64, + (int64_t) byte); +#else int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32, (int32_t) byte); +#endif if ((size_t) needed > avail) return (size_t) needed - avail; *bufcntp += needed; @@ -793,8 +962,13 @@ FCT_imm$s (GElf_Addr addr __attribute__ ((unused)), { if (*param_start + 4 > end) return -1; - uint32_t word = read_4ubyte_unaligned_inc (*param_start); + int32_t word = read_4sbyte_unaligned_inc (*param_start); +#ifdef X86_64 + int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx64, + (int64_t) word); +#else int needed = snprintf (&bufp[*bufcntp], avail, "$0x%" PRIx32, word); +#endif if ((size_t) needed > avail) return (size_t) needed - avail; *bufcntp += needed; @@ -893,7 +1067,6 @@ FCT_imm8 (GElf_Addr addr __attribute__ ((unused)), return 0; } -#ifndef X86_64 static int FCT_rel (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), @@ -913,15 +1086,19 @@ FCT_rel (GElf_Addr addr __attribute__ ((unused)), size_t avail = bufsize - *bufcntp; if (*param_start + 4 > end) return -1; - uint32_t rel = read_4ubyte_unaligned_inc (*param_start); + int32_t rel = read_4sbyte_unaligned_inc (*param_start); +#ifdef X86_64 + int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx64, + (uint64_t) (addr + rel + (*param_start - data))); +#else int needed = snprintf (&bufp[*bufcntp], avail, "0x%" PRIx32, (uint32_t) (addr + rel + (*param_start - data))); +#endif if ((size_t) needed > avail) return (size_t) needed - avail; *bufcntp += needed; return 0; } -#endif static int FCT_mmxreg (GElf_Addr addr __attribute__ ((unused)), @@ -971,14 +1148,33 @@ FCT_mod$r_m (GElf_Addr addr __attribute__ ((unused)), uint_fast8_t modrm = data[opoff1 / 8]; if ((modrm & 0xc0) == 0xc0) { + if (*prefixes & has_addr16) + return -1; + int is_16bit = (*prefixes & has_data16) != 0; if (*bufcntp + 5 - is_16bit > bufsize) return *bufcntp + 5 - is_16bit - bufsize; bufp[(*bufcntp)++] = '%'; - memcpy (&bufp[*bufcntp], regs[modrm & 7] + is_16bit, - sizeof (regs[0]) - is_16bit); - *bufcntp += 3 - is_16bit; + + char *cp; +#ifdef X86_64 + if ((*prefixes & has_rex_b) != 0 && !is_16bit) + { + cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); + if ((*prefixes & has_rex_w) == 0) + *cp++ = 'd'; + } + else +#endif + { + cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); +#ifdef X86_64 + if ((*prefixes & has_rex_w) != 0) + bufp[*bufcntp] = 'r'; +#endif + } + *bufcntp = cp - bufp; return 0; } @@ -1013,6 +1209,9 @@ FCT_moda$r_m (GElf_Addr addr __attribute__ ((unused)), uint_fast8_t modrm = data[opoff1 / 8]; if ((modrm & 0xc0) == 0xc0) { + if (*prefixes & has_addr16) + return -1; + if (*bufcntp + 3 > bufsize) return *bufcntp + 3 - bufsize; @@ -1029,6 +1228,14 @@ FCT_moda$r_m (GElf_Addr addr __attribute__ ((unused)), #endif +#ifdef X86_64 +static const char rex_8bit[8][3] = + { + [0] = "a", [1] = "c", [2] = "d", [3] = "b", + [4] = "sp", [5] = "bp", [6] = "si", [7] = "di" + }; +#endif + static int FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), @@ -1053,24 +1260,60 @@ FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)), uint_fast8_t modrm = data[opoff1 / 8]; if ((modrm & 0xc0) == 0xc0) { + if (*prefixes & has_addr16) + return -1; + + if (*bufcntp + 5 > bufsize) + return *bufcntp + 5 - bufsize; + if ((data[opoff3 / 8] & (1 << (7 - (opoff3 & 7)))) == 0) { - if (*bufcntp + 3 > bufsize) - return *bufcntp + 3 - bufsize; bufp[(*bufcntp)++] = '%'; - bufp[(*bufcntp)++] = "acdb"[modrm & 3]; - bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; + +#ifdef X86_64 + if (*prefixes & has_rex) + { + if (*prefixes & has_rex_r) + *bufcntp += snprintf (bufp + *bufcntp, bufsize - *bufcntp, + "r%db", 8 + (modrm & 7)); + else + { + char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]); + *cp++ = 'l'; + *bufcntp = cp - bufp; + } + } + else +#endif + { + bufp[(*bufcntp)++] = "acdb"[modrm & 3]; + bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2]; + } } else { int is_16bit = (*prefixes & has_data16) != 0; - if (*bufcntp + 5 - is_16bit > bufsize) - return *bufcntp + 5 - is_16bit - bufsize; bufp[(*bufcntp)++] = '%'; - memcpy (&bufp[*bufcntp], regs[modrm & 7] + is_16bit, - sizeof (regs[0]) - is_16bit); - *bufcntp += 3 - is_16bit; + + char *cp; +#ifdef X86_64 + if ((*prefixes & has_rex_b) != 0 && !is_16bit) + { + cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]); + if ((*prefixes & has_rex_w) == 0) + *cp++ = 'd'; + } + else +#endif + { + cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit); +#ifdef X86_64 + if ((*prefixes & has_rex_w) != 0) + bufp[*bufcntp] = 'r'; +#endif + } + *bufcntp = cp - bufp; } return 0; } @@ -1081,7 +1324,6 @@ FCT_mod$r_m$w (GElf_Addr addr __attribute__ ((unused)), } -#ifndef X86_64 static int FCT_mod$8r_m (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), @@ -1114,7 +1356,6 @@ FCT_mod$8r_m (GElf_Addr addr __attribute__ ((unused)), bufcntp, bufsize, data, param_start, end, symcb, symcbarg); } -#endif static int FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)), @@ -1140,7 +1381,7 @@ FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)), if (*bufcntp + 3 > bufsize) return *bufcntp + 3 - bufsize; bufp[(*bufcntp)++] = '%'; - memcpy (&bufp[*bufcntp], regs[byte] + 1, sizeof (regs[0]) - 1); + memcpy (&bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1); *bufcntp += 2; return 0; } @@ -1150,6 +1391,45 @@ FCT_mod$16r_m (GElf_Addr addr __attribute__ ((unused)), symcb, symcbarg); } +#ifdef X86_64 +static int +FCT_mod$64r_m (GElf_Addr addr __attribute__ ((unused)), + int *prefixes __attribute__ ((unused)), + const char *op1str __attribute__ ((unused)), + size_t opoff1 __attribute__ ((unused)), + size_t opoff2 __attribute__ ((unused)), + size_t opoff3 __attribute__ ((unused)), + char *bufp __attribute__ ((unused)), + size_t *bufcntp __attribute__ ((unused)), + size_t bufsize __attribute__ ((unused)), + const uint8_t *data __attribute__ ((unused)), + const uint8_t **param_start __attribute__ ((unused)), + const uint8_t *end __attribute__ ((unused)), + DisasmGetSymCB_t symcb __attribute__ ((unused)), + void *symcbarg __attribute__ ((unused))) +{ + assert (opoff1 % 8 == 0); + uint_fast8_t modrm = data[opoff1 / 8]; + if ((modrm & 0xc0) == 0xc0) + { + uint_fast8_t byte = data[opoff1 / 8] & 7; + if (*bufcntp + 4 > bufsize) + return *bufcntp + 4 - bufsize; + char *cp = &bufp[*bufcntp]; + *cp++ = '%'; + cp = stpcpy (cp, (*prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]); + *bufcntp = cp - bufp; + return 0; + } + + return general_mod$r_m (addr, prefixes, op1str, opoff1, opoff2, opoff3, bufp, + bufcntp, bufsize, data, param_start, end, + symcb, symcbarg); +} +#else +static typeof (FCT_mod$r_m) FCT_mod$64r_m __attribute__ ((alias ("FCT_mod$r_m"))); +#endif + static int FCT_reg (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), @@ -1171,11 +1451,69 @@ FCT_reg (GElf_Addr addr __attribute__ ((unused)), byte >>= 8 - (opoff1 % 8 + 3); byte &= 7; int is_16bit = (*prefixes & has_data16) != 0; - if (*bufcntp + 4 > bufsize) - return *bufcntp + 4 - bufsize; + if (*bufcntp + 5 > bufsize) + return *bufcntp + 5 - bufsize; + bufp[(*bufcntp)++] = '%'; +#ifdef X86_64 + if ((*prefixes & has_rex_r) != 0 && !is_16bit) + { + *bufcntp += snprintf (&bufp[*bufcntp], bufsize - *bufcntp, "r%d", + 8 + byte); + if ((*prefixes & has_rex_w) == 0) + bufp[(*bufcntp)++] = 'd'; + } + else +#endif + { + memcpy (&bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit); +#ifdef X86_64 + if ((*prefixes & has_rex_w) != 0 && !is_16bit) + bufp[*bufcntp] = 'r'; +#endif + *bufcntp += 3 - is_16bit; + } + return 0; +} + +static int +FCT_reg64 (GElf_Addr addr __attribute__ ((unused)), + int *prefixes __attribute__ ((unused)), + const char *op1str __attribute__ ((unused)), + size_t opoff1 __attribute__ ((unused)), + size_t opoff2 __attribute__ ((unused)), + size_t opoff3 __attribute__ ((unused)), + char *bufp __attribute__ ((unused)), + size_t *bufcntp __attribute__ ((unused)), + size_t bufsize __attribute__ ((unused)), + const uint8_t *data __attribute__ ((unused)), + const uint8_t **param_start __attribute__ ((unused)), + const uint8_t *end __attribute__ ((unused)), + DisasmGetSymCB_t symcb __attribute__ ((unused)), + void *symcbarg __attribute__ ((unused))) +{ + uint_fast8_t byte = data[opoff1 / 8]; + assert (opoff1 % 8 + 3 <= 8); + byte >>= 8 - (opoff1 % 8 + 3); + byte &= 7; + if ((*prefixes & has_data16) != 0) + return -1; + if (*bufcntp + 5 > bufsize) + return *bufcntp + 5 - bufsize; bufp[(*bufcntp)++] = '%'; - memcpy (&bufp[*bufcntp], regs[byte] + is_16bit, sizeof (regs[0]) - is_16bit); - *bufcntp += 3 - is_16bit; +#ifdef X86_64 + if ((*prefixes & has_rex_r) != 0) + { + *bufcntp += snprintf (&bufp[*bufcntp], bufsize - *bufcntp, "r%d", + 8 + byte); + if ((*prefixes & has_rex_w) == 0) + bufp[(*bufcntp)++] = 'd'; + } + else +#endif + { + memcpy (&bufp[*bufcntp], aregs[byte], 3); + *bufcntp += 3; + } return 0; } @@ -1202,15 +1540,34 @@ FCT_reg$w (GElf_Addr addr __attribute__ ((unused)), assert (opoff1 % 8 + 3 <= 8); byte >>= 8 - (opoff1 % 8 + 3); byte &= 7; - if (*bufcntp + 3 > bufsize) - return *bufcntp + 3 - bufsize; + + if (*bufcntp + 4 > bufsize) + return *bufcntp + 4 - bufsize; + bufp[(*bufcntp)++] = '%'; - bufp[(*bufcntp)++] = "acdb"[byte & 3]; - bufp[(*bufcntp)++] = "lh"[byte >> 2]; + +#ifdef X86_64 + if (*prefixes & has_rex) + { + if (*prefixes & has_rex_r) + *bufcntp += snprintf (bufp + *bufcntp, bufsize - *bufcntp, + "r%db", 8 + byte); + else + { + char* cp = stpcpy (bufp + *bufcntp, rex_8bit[byte]); + *cp++ = 'l'; + *bufcntp = cp - bufp; + } + } + else +#endif + { + bufp[(*bufcntp)++] = "acdb"[byte & 3]; + bufp[(*bufcntp)++] = "lh"[byte >> 2]; + } return 0; } -#ifndef X86_64 static int FCT_freg (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), @@ -1238,6 +1595,7 @@ FCT_freg (GElf_Addr addr __attribute__ ((unused)), return 0; } +#ifndef X86_64 static int FCT_reg16 (GElf_Addr addr __attribute__ ((unused)), int *prefixes __attribute__ ((unused)), diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index a9edcffd..ecdbfb65 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -90,7 +90,12 @@ static const unsigned short int mneidx[] = enum { - idx_cs = 0, + idx_rex_b = 0, + idx_rex_x, + idx_rex_r, + idx_rex_w, + idx_rex, + idx_cs, idx_ds, idx_es, idx_fs, @@ -106,6 +111,11 @@ enum enum { #define prefbit(pref) has_##pref = 1 << idx_##pref + prefbit (rex_b), + prefbit (rex_x), + prefbit (rex_r), + prefbit (rex_w), + prefbit (rex), prefbit (cs), prefbit (ds), prefbit (es), @@ -226,7 +236,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, while (data < end) { unsigned int i; - for (i = 0; i < nknown_prefixes; ++i) + for (i = idx_cs; i < nknown_prefixes; ++i) if (known_prefixes[i] == *data) break; if (i == nknown_prefixes) @@ -237,6 +247,11 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, ++data; } +#ifdef X86_64 + if (data < end && (*data & 0xf0) == 0x40) + prefixes |= ((*data++) & 0xf) | has_rex; +#endif + assert (data <= end); if (data == end) { @@ -407,19 +422,29 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, { uint_fast8_t modrm = codep[-1]; - if ((prefixes & has_addr16) == 0) +#ifndef X86_64 + if (likely ((prefixes & has_addr16) != 0)) + { + /* Account for displacement. */ + if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80) + param_start += 2; + else if ((modrm & 0xc0) == 0x40) + param_start += 1; + } + else +#endif { /* Account for SIB. */ if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4) param_start += 1; - } - /* Account for displacement. */ - if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 - || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5)) - param_start += 4; - else if ((modrm & 0xc0) == 0x40) - param_start += 1; + /* Account for displacement. */ + if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80 + || ((modrm & 0xc7) == 0x4 && (codep[0] & 0x7) == 0x5)) + param_start += 4; + else if ((modrm & 0xc0) == 0x40) + param_start += 1; + } if (unlikely (param_start > end)) goto not; @@ -484,6 +509,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, size_t start_idx = bufcnt; switch (*fmt++) { + char mnebuf[16]; const char *str; case 'm': @@ -493,15 +519,6 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, { switch (*data) { - case 0x90: - if (prefixes & ~has_rep) - goto print_prefix; - /* Discard the 'rep' prefix string possibly - already in the buffer. */ - bufcnt = 0; - str = prefixes & has_rep ? "pause" : "nop"; - break; - case 0x98: if (prefixes & ~has_data16) goto print_prefix; @@ -517,9 +534,56 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, case 0xe3: if (prefixes & ~has_addr16) goto print_prefix; +#ifdef X86_64 + str = prefixes & has_addr16 ? "jecxz" : "jrcxz"; +#else str = prefixes & has_addr16 ? "jcxz" : "jecxz"; +#endif break; + case 0x0f: +#ifdef X86_64 + if (data[1] == 0xc7) + { + str = ((prefixes & has_rex_w) + ? "cmpxchg16b" : "cmpxchg8b"); + break; + } +#endif + if (data[1] == 0xc2) + { + if (param_start >= end) + goto not; + if (*param_start > 7) + goto not; + static const char cmpops[][9] = + { + [0] = "cmpeq", + [1] = "cmplt", + [2] = "cmple", + [3] = "cmpunord", + [4] = "cmpneq", + [5] = "cmpnlt", + [6] = "cmpnle", + [7] = "cmpord" + }; + char *cp = stpcpy (mnebuf, cmpops[*param_start]); + if (correct_prefix & (has_rep | has_repne)) + *cp++ = 's'; + else + *cp++ = 'p'; + if (correct_prefix & (has_data16 | has_repne)) + *cp++ = 'd'; + else + *cp++ = 's'; + *cp = '\0'; + str = mnebuf; + /* Eat the immediate byte indicating the + operation. */ + ++param_start; + break; + } + default: assert (! "INVALID not handled"); } @@ -565,11 +629,23 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, ADD_CHAR ('w'); prefixes &= ~has_data16; } -#ifdef x86_64 +#ifdef X86_64 else - abort (); + ADD_CHAR ('q'); #endif break; + case suffix_W1: + if (prefixes & has_data16) + { + ADD_CHAR ('w'); + prefixes &= ~has_data16; + } +#ifdef X86_64 + else if (prefixes & has_rex_w) + ADD_CHAR ('q'); +#endif + break; + case suffix_tttn:; static const char tttn[16][3] = { diff --git a/libcpu/i386_parse.y b/libcpu/i386_parse.y index 5cfd3df2..896b11d0 100644 --- a/libcpu/i386_parse.y +++ b/libcpu/i386_parse.y @@ -108,7 +108,7 @@ struct instruction /* Suffix. */ enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn, - suffix_w1, suffix_D } suffix; + suffix_w1, suffix_W1, suffix_D } suffix; /* Flag set if modr/m is used. */ int modrm; @@ -324,6 +324,8 @@ instr: bytes ':' bitfieldopt kID bitfieldopt optargs newp->suffix = suffix_w1; else if (strcmp ($5->name, "W") == 0) newp->suffix = suffix_W; + else if (strcmp ($5->name, "W1") == 0) + newp->suffix = suffix_W1; else if (strcmp ($5->name, "D") == 0) newp->suffix = suffix_D; else @@ -1130,6 +1132,7 @@ instrtable_out (void) EMIT_SUFFIX (tttn); EMIT_SUFFIX (D); EMIT_SUFFIX (w1); + EMIT_SUFFIX (W1); fputc_unlocked ('\n', outfile); diff --git a/tests/ChangeLog b/tests/ChangeLog index 7ad6942a..4a76f034 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2008-01-08 Ulrich Drepper <drepper@redhat.com> + + * Makefile.am (TESTS): Add run-disasm-x86-64.sh. + (EXTRA): Add testfile45.S.bz2, testfile45.expect.bz2, + run-disasm-x86-64.sh. + * run-disasm-x86-64.sh: New file. + * testfile45.S.bz2: New file. + * testfile45.expect.bz2: New file. + * testfile44.S.bz2: New tests. + * testfile44.expect.bz2: Adjust. + 2008-01-04 Ulrich Drepper <drepper@redhat.com> * testfile44.S.bz2: New tests. diff --git a/tests/Makefile.am b/tests/Makefile.am index 25631e3c..42f71ce4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 1996-2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. +## Copyright (C) 1996-2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. ## This file is part of Red Hat elfutils. ## ## Red Hat elfutils is free software; you can redistribute it and/or modify @@ -84,7 +84,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ dwfl-bug-addr-overflow run-addrname-test.sh \ dwfl-bug-fd-leak dwfl-bug-report \ run-dwfl-bug-offline-rel.sh run-dwfl-addr-sect.sh \ - run-disasm.sh + run-disasm-x86.sh run-disasm-x86-64.sh # run-show-ciefde.sh if !STANDALONE @@ -135,7 +135,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile37.bz2 testfile37.debug.bz2 \ testfile38.bz2 testfile39.bz2 testfile40.bz2 testfile40.debug.bz2 \ testfile41.bz2 testfile42.bz2 testfile43.bz2 \ - testfile44.S.bz2 testfile44.expect.bz2 run-disasm.sh + testfile44.S.bz2 testfile44.expect.bz2 run-disasm-x86.sh \ + testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \ bindir=$(DESTDIR)$(bindir) \ diff --git a/tests/run-disasm-x86-64.sh b/tests/run-disasm-x86-64.sh new file mode 100755 index 00000000..2d9ed631 --- /dev/null +++ b/tests/run-disasm-x86-64.sh @@ -0,0 +1,36 @@ +#! /bin/sh +# Copyright (C) 2007, 2008 Red Hat, Inc. +# This file is part of Red Hat elfutils. +# +# Red Hat elfutils is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; version 2 of the License. +# +# Red Hat elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Red Hat elfutils; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +# +# Red Hat elfutils is an included package of the Open Invention Network. +# An included package of the Open Invention Network is a package for which +# Open Invention Network licensees cross-license their patents. No patent +# license is granted, either expressly or impliedly, by designation as an +# included package. Should you wish to participate in the Open Invention +# Network licensing program, please visit www.openinventionnetwork.com +# <http://www.openinventionnetwork.com>. + +. $srcdir/test-subr.sh + +# Run x86-64 test. +case "$(arch)" in + x86_64) + tempfiles testfile45.o + testfiles testfile45.S testfile45.expect + gcc -m64 -c -o testfile45.o testfile45.S + testrun_compare ../src/objdump -d testfile45.o < testfile45.expect + ;; +esac diff --git a/tests/run-disasm.sh b/tests/run-disasm-x86.sh index efbb81f8..efbb81f8 100755 --- a/tests/run-disasm.sh +++ b/tests/run-disasm-x86.sh diff --git a/tests/testfile44.S.bz2 b/tests/testfile44.S.bz2 Binary files differindex c3af5262..cbd0da3d 100644 --- a/tests/testfile44.S.bz2 +++ b/tests/testfile44.S.bz2 diff --git a/tests/testfile44.expect.bz2 b/tests/testfile44.expect.bz2 Binary files differindex c4a267e7..2347aea1 100644 --- a/tests/testfile44.expect.bz2 +++ b/tests/testfile44.expect.bz2 diff --git a/tests/testfile45.S.bz2 b/tests/testfile45.S.bz2 Binary files differnew file mode 100644 index 00000000..a2012edb --- /dev/null +++ b/tests/testfile45.S.bz2 diff --git a/tests/testfile45.expect.bz2 b/tests/testfile45.expect.bz2 Binary files differnew file mode 100644 index 00000000..ac814e31 --- /dev/null +++ b/tests/testfile45.expect.bz2 |