x86 assembler improvements:

* Simplified REX handling: instead of useless adjusting instruction length on every REX change, adjust it just once, based on the final REX value.
* Similar for omitting REX.W in certain instructions: set a flag and consider it once the entire instruction has been processed. This removes the requirement for \335 to be the last opcode.
* maybewriterex also after $F2 prefix
* Fixed behavior of codes \310 and \311 (16- and 32-bit address respectively), this is needed for a few fancy instructions like LOOP and JCXZ, which honor address-size prefix instead of REX.
+ control code \361 for $66 prefix
+ IF_SSSE3, IF_SSE41, IF_SSE42 instruction flags (with dummy values)

x86/x86ins.dat:
* replaced literal $67 prefixes with \310 or \311
* marked encodings containing code \310 as NOX86_64
* replaced literal $48 prefixes with \326

git-svn-id: trunk@17433 -
This commit is contained in:
sergei 2011-05-12 13:09:51 +00:00
parent 428915a90b
commit de8ae0f873
5 changed files with 85 additions and 114 deletions

View File

@ -2517,15 +2517,15 @@
opcode : A_JCXZ;
ops : 1;
optypes : (ot_immediate,ot_none,ot_none);
code : #2#103#227#40;
code : #200#1#227#40;
flags : if_8086 or if_nox86_64
),
(
opcode : A_JECXZ;
ops : 1;
optypes : (ot_immediate,ot_none,ot_none);
code : #1#227#40;
flags : if_386 or if_nox86_64
code : #201#1#227#40;
flags : if_386
),
(
opcode : A_JMP;
@ -2791,7 +2791,7 @@
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#226#40;
flags : if_8086
flags : if_8086 or if_nox86_64
),
(
opcode : A_LOOP;
@ -2812,7 +2812,7 @@
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#225#40;
flags : if_8086
flags : if_8086 or if_nox86_64
),
(
opcode : A_LOOPE;
@ -2833,7 +2833,7 @@
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#224#40;
flags : if_8086
flags : if_8086 or if_nox86_64
),
(
opcode : A_LOOPNE;
@ -2854,7 +2854,7 @@
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#224#40;
flags : if_8086
flags : if_8086 or if_nox86_64
),
(
opcode : A_LOOPNZ;
@ -2875,7 +2875,7 @@
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#225#40;
flags : if_8086
flags : if_8086 or if_nox86_64
),
(
opcode : A_LOOPZ;

View File

@ -323,6 +323,11 @@ implementation
IF_SVM = $00100000;
{ SSE4 instructions }
IF_SSE4 = $00200000;
{ TODO: These flags were added to make x86ins.dat more readable.
Values must be reassigned to make any other use of them. }
IF_SSSE3 = $00200000;
IF_SSE41 = $00200000;
IF_SSE42 = $00200000;
IF_8086 = $00000000; { 8086 instruction }
IF_186 = $01000000; { 186+ instruction }
@ -906,7 +911,6 @@ implementation
modrm : byte;
sib : byte;
{$ifdef x86_64}
rex_present : boolean;
rex : byte;
{$endif x86_64}
end;
@ -1373,17 +1377,13 @@ implementation
((getregtype(input.reg)=R_MMREGISTER) and
(getsupreg(input.reg)>=RS_XMM8)) then
begin
output.rex_present:=true;
output.rex:=output.rex or $41;
inc(output.size,1);
end
else if (getregtype(input.reg)=R_INTREGISTER) and
(getsubreg(input.reg)=R_SUBL) and
(getsupreg(input.reg) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
begin
output.rex_present:=true;
output.rex:=output.rex or $40;
inc(output.size,1);
end;
process_ea:=true;
@ -1434,7 +1434,6 @@ implementation
((getregtype(br)=R_MMREGISTER) and
(getsupreg(br)>=RS_XMM8)) then
begin
output.rex_present:=true;
output.rex:=output.rex or $41;
end;
@ -1443,7 +1442,6 @@ implementation
((getregtype(ir)=R_MMREGISTER) and
(getsupreg(ir)>=RS_XMM8)) then
begin
output.rex_present:=true;
output.rex:=output.rex or $42;
end;
@ -1528,7 +1526,7 @@ implementation
output.sib:=(scalefactor shl 6) or (index shl 3) or base;
end;
end;
output.size:=1+ord(output.sib_present)+ord(output.rex_present)+output.bytes;
output.size:=1+ord(output.sib_present)+output.bytes;
process_ea:=true;
end;
@ -1683,11 +1681,13 @@ implementation
c : byte;
len : shortint;
ea_data : ea;
omit_rexw : boolean;
begin
len:=0;
codes:=@p^.code[0];
{$ifdef x86_64}
rex:=0;
omit_rexw:=false;
{$endif x86_64}
repeat
c:=ord(codes^);
@ -1708,17 +1708,12 @@ implementation
((getregtype(oper[c-8]^.reg)=R_MMREGISTER) and
(getsupreg(oper[c-8]^.reg)>=RS_XMM8)) then
begin
if rex=0 then
inc(len);
rex:=rex or $41;
end
else if (getregtype(oper[c-8]^.reg)=R_INTREGISTER) and
(getsubreg(oper[c-8]^.reg)=R_SUBL) and
(getsupreg(oper[c-8]^.reg) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
begin
if rex=0 then
inc(len);
rex:=rex or $40;
end;
{$endif x86_64}
@ -1737,7 +1732,6 @@ implementation
else
inc(len);
end;
15,
12,13,14,
16,17,18,
20,21,22,
@ -1769,42 +1763,41 @@ implementation
{$ifdef x86_64}
OT_BITS64:
begin
if rex=0 then
inc(len);
rex:=rex or $48;
end;
{$endif x86_64}
end;
end;
200,
200 :
{$ifndef x86_64}
inc(len);
{$else x86_64}
{ every insentry with code 0310 must be marked with NOX86_64 }
InternalError(2011051301);
{$endif x86_64}
201 :
{$ifdef x86_64}
inc(len)
{$endif x86_64}
;
212 :
inc(len);
214 :
begin
{$ifdef x86_64}
if rex=0 then
inc(len);
rex:=rex or $48;
{$endif x86_64}
end;
201,
202,
211,
213,
215,
217,218: ;
219,220 :
219,220,241 :
inc(len);
221:
{$ifdef x86_64}
{ remove rex competely? }
if rex=$48 then
begin
rex:=0;
dec(len);
end
else
rex:=rex and $f7
omit_rexw:=true
{$endif x86_64}
;
64..191 :
@ -1819,18 +1812,12 @@ implementation
((getregtype(oper[c and 7]^.reg)=R_MMREGISTER) and
(getsupreg(oper[c and 7]^.reg)>=RS_XMM8)) then
begin
if rex=0 then
inc(len);
rex:=rex or $44;
end
else if (getregtype(oper[c and 7]^.reg)=R_INTREGISTER) and
(getsubreg(oper[c and 7]^.reg)=R_SUBL) and
(getsupreg(oper[c and 7]^.reg) in [RS_RDI,RS_RSI,RS_RBP,RS_RSP]) then
begin
if rex=0 then
inc(len);
rex:=rex or $40;
end;
end;
@ -1842,9 +1829,6 @@ implementation
else
inc(len,ea_data.size);
{$ifdef x86_64}
{ did we already create include a rex into the length calculation? }
if (rex<>0) and (ea_data.rex<>0) then
dec(len);
rex:=rex or ea_data.rex;
{$endif x86_64}
@ -1853,6 +1837,17 @@ implementation
InternalError(200603141);
end;
until false;
{$ifdef x86_64}
if omit_rexw then
begin
if rex=$48 then { remove rex entirely? }
rex:=0
else
rex:=rex and $F7;
end;
if rex<>0 then
Inc(len);
{$endif}
calcsize:=len;
end;
@ -1894,7 +1889,7 @@ implementation
* the memory reference in operand x.
* \310 - indicates fixed 16-bit address size, i.e. optional 0x67.
* \311 - indicates fixed 32-bit address size, i.e. optional 0x67.
* \312 - indicates fixed 64-bit address size, i.e. optional 0x48.
* \312 - (disassembler only) invalid with non-default address size.
* \320,\321,\322 - might be an 0x66 or 0x48 byte, depending on the operand
* size of operand x.
* \323 - insert x86_64 REX at this position.
@ -1907,8 +1902,10 @@ implementation
* \331 - instruction not valid with REP prefix. Hint for
* disassembler only; for SSE instructions.
* \332 - disassemble a rep (0xF3 byte) prefix as repe not rep.
* \333 - REP prefix (0xF3 byte); for SSE instructions. Not encoded
* \333 - 0xF3 prefix optionally followed by REX; for SSE instructions
* \334 - 0xF2 prefix optionally followed by REX; for SSE instructions
* \335 - removes rex size prefix, i.e. rex.w must be the last opcode
* \361 - 0x66 prefix optionally followed by REX; for SSE instructions
}
var
@ -2091,11 +2088,6 @@ implementation
inc(codes);
objdata.writebytes(bytes,1);
end;
15 :
begin
bytes[0]:=0;
objdata.writebytes(bytes,1);
end;
12,13,14 :
begin
getvalsym(c-12);
@ -2196,11 +2188,24 @@ implementation
objdata.writebytes(bytes,1);
end;
end;
200 :
200 : { fixed 16-bit addr }
{$ifndef x86_64}
begin
bytes[0]:=$67;
objdata.writebytes(bytes,1);
end;
{$else x86_64}
{ every insentry having code 0310 must be marked with NOX86_64 }
InternalError(2011051302);
{$endif}
201 : { fixed 32-bit addr }
{$ifdef x86_64}
begin
bytes[0]:=$67;
objdata.writebytes(bytes,1);
end
{$endif x86_64}
;
208,209,210 :
begin
case oper[c-208]^.ot and OT_SIZE_MASK of
@ -2225,7 +2230,7 @@ implementation
maybewriterex;
{$endif x86_64}
end;
212 :
212, 241 :
begin
bytes[0]:=$66;
objdata.writebytes(bytes,1);
@ -2253,10 +2258,12 @@ implementation
begin
bytes[0]:=$f2;
objdata.writebytes(bytes,1);
{$ifdef x86_64}
maybewriterex;
{$endif x86_64}
end;
221:
;
201,
202,
215,
217,218 :

View File

@ -855,12 +855,11 @@ void \324\1\xCF 8086
[JCXZ]
(Ch_RECX, Ch_None, Ch_None)
imm \2\x67\xE3\50 8086,NOX86_64
imm \310\1\xE3\50 8086,NOX86_64
[JECXZ]
(Ch_RECX, Ch_None, Ch_None)
imm \1\xE3\50 386,NOX86_64
imm \2\x67\xE3\50 X86_64
imm \311\1\xE3\50 386
[JRCXZ]
(Ch_RECX, Ch_None, Ch_None)
@ -970,31 +969,31 @@ void \324\1\xAD 8086
[LOOP]
(Ch_RWECX, Ch_None, Ch_None)
imm \312\1\xE2\50 8086
imm,reg_cx \310\1\xE2\50 8086
imm,reg_cx \310\1\xE2\50 8086,NOX86_64
imm,reg_ecx|64 \311\1\xE2\50 386
[LOOPE]
(Ch_RWECX, Ch_RFlags, Ch_None)
imm \312\1\xE1\50 8086
imm,reg_cx \310\1\xE1\50 8086
imm,reg_cx \310\1\xE1\50 8086,NOX86_64
imm,reg_ecx|64 \311\1\xE1\50 386
[LOOPNE]
(Ch_RWECX, Ch_RFlags, Ch_None)
imm \312\1\xE0\50 8086
imm,reg_cx \310\1\xE0\50 8086
imm,reg_cx \310\1\xE0\50 8086,NOX86_64
imm,reg_ecx|64 \311\1\xE0\50 386
[LOOPNZ]
(Ch_RWECX, Ch_RFlags, Ch_None)
imm \312\1\xE0\50 8086
imm,reg_cx \310\1\xE0\50 8086
imm,reg_cx \310\1\xE0\50 8086,NOX86_64
imm,reg_ecx|64 \311\1\xE0\50 386
[LOOPZ]
(Ch_RWECX, Ch_RFlags, Ch_None)
imm \312\1\xE1\50 8086
imm,reg_cx \310\1\xE1\50 8086
imm,reg_cx \310\1\xE1\50 8086,NOX86_64
imm,reg_ecx|64 \311\1\xE1\50 386
[LSL,lslX]
@ -1482,7 +1481,7 @@ void \324\1\x61 186,NOX86_64
[POPF]
(Ch_RWESP, Ch_WFlags, Ch_None)
void \327\1\x9D 186,NOX86_64
void \2\x48\x9D X86_64
void \326\1\x9D X86_64
[POPFD,popfl]
(Ch_RWESP, Ch_WFlags, Ch_None)
@ -1495,7 +1494,7 @@ void \1\x9D X86_64
[POPFQ]
(Ch_RWESP, Ch_WFlags, Ch_None)
void \2\x48\x9D X86_64
void \326\1\x9D X86_64
[POR]
(Ch_All, Ch_None, Ch_None)
@ -1720,7 +1719,7 @@ void \324\1\x9C 186
[PUSHFQ]
(Ch_RWESP, Ch_RFlags, Ch_None)
void \2\x48\x9C X86_64
void \326\1\x9C X86_64
[PXOR]
(Ch_Mop2, Ch_Rop1, Ch_None)
@ -3715,12 +3714,12 @@ xmmreg,mem,imm \1\x66\301\331\3\x0F\x3A\xDF\110\26 SSE4
;*******************************************************************************
[STOSQ]
(Ch_RRAX, Ch_WMemEDI, Ch_RWRDI)
void \2\x48\xAB X86_64
void \326\1\xAB X86_64
[LODSQ]
(Ch_WRAX, Ch_RWRSI, Ch_None)
void \2\x48\xAD X86_64
void \326\1\xAD X86_64
[CMPSQ]
(Ch_All, Ch_None, Ch_None)
void \2\x48\xA7 X86_64
void \326\1\xA7 X86_64

View File

@ -1,2 +1,2 @@
{ don't edit, this file is generated from x86ins.dat }
1531;
1526;

View File

@ -2377,8 +2377,8 @@
opcode : A_JECXZ;
ops : 1;
optypes : (ot_immediate,ot_none,ot_none);
code : #2#103#227#40;
flags : if_x86_64
code : #201#1#227#40;
flags : if_386
),
(
opcode : A_JRCXZ;
@ -2604,13 +2604,6 @@
code : #202#1#226#40;
flags : if_8086
),
(
opcode : A_LOOP;
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#226#40;
flags : if_8086
),
(
opcode : A_LOOP;
ops : 2;
@ -2625,13 +2618,6 @@
code : #202#1#225#40;
flags : if_8086
),
(
opcode : A_LOOPE;
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#225#40;
flags : if_8086
),
(
opcode : A_LOOPE;
ops : 2;
@ -2646,13 +2632,6 @@
code : #202#1#224#40;
flags : if_8086
),
(
opcode : A_LOOPNE;
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#224#40;
flags : if_8086
),
(
opcode : A_LOOPNE;
ops : 2;
@ -2667,13 +2646,6 @@
code : #202#1#224#40;
flags : if_8086
),
(
opcode : A_LOOPNZ;
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#224#40;
flags : if_8086
),
(
opcode : A_LOOPNZ;
ops : 2;
@ -2688,13 +2660,6 @@
code : #202#1#225#40;
flags : if_8086
),
(
opcode : A_LOOPZ;
ops : 2;
optypes : (ot_immediate,ot_reg_cx,ot_none);
code : #200#1#225#40;
flags : if_8086
),
(
opcode : A_LOOPZ;
ops : 2;
@ -4309,7 +4274,7 @@
opcode : A_POPF;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#157;
code : #214#1#157;
flags : if_x86_64
),
(
@ -4323,7 +4288,7 @@
opcode : A_POPFQ;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#157;
code : #214#1#157;
flags : if_x86_64
),
(
@ -5142,7 +5107,7 @@
opcode : A_PUSHFQ;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#156;
code : #214#1#156;
flags : if_x86_64
),
(
@ -10700,21 +10665,21 @@
opcode : A_STOSQ;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#171;
code : #214#1#171;
flags : if_x86_64
),
(
opcode : A_LODSQ;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#173;
code : #214#1#173;
flags : if_x86_64
),
(
opcode : A_CMPSQ;
ops : 0;
optypes : (ot_none,ot_none,ot_none);
code : #2#72#167;
code : #214#1#167;
flags : if_x86_64
)
);