Add x86-64 disassembler support.

This commit is contained in:
Ulrich Drepper
2008-01-09 05:39:28 +00:00
parent 9e6925dd43
commit ff99322e98
18 changed files with 694 additions and 482 deletions
+10
View File
@@ -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".
+2 -3
View File
@@ -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)
+2 -3
View File
@@ -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;
}
+9
View File
@@ -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.
+7 -9
View File
@@ -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 > $@
+100 -47
View File
@@ -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}
-341
View File
@@ -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
+412 -54
View File
@@ -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)++] = '%';
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 && !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)++] = '%';
#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)),
+97 -21
View File
@@ -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] =
{
+4 -1
View File
@@ -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);
+11
View File
@@ -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.
+4 -3
View File
@@ -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) \
+36
View File
@@ -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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.