x86_64 assembler reader improvements:

+ Added new value TAttSuffix.attsufINTdual, assigned it to movsX and movzX instructions
* Moved suffix-to-size translation tables from rax86att.pas to itcpugas.pas
+ Added x86_64 specific suffix-to-size translation, enabling BQ and WQ suffixes (LQ seems unnecessary at the moment)
* Fixed logic of tx86attreader.is_asmopcode so it only assigns dual suffix to instructions that explicitly allow it. This disambiguates cases like movsbq=movs+bq vs. cmovbq=cmovb+q
* As a net result: movz[bw]q and movs[bw]q now compile for x86_64; cmovbw and cmovbl which were incorrectly handled for i386 are now fixed.
+ Test for correct assembling of cmov.

git-svn-id: trunk@17353 -
This commit is contained in:
sergei 2011-04-20 11:18:13 +00:00
parent 918909c65d
commit f97f223de6
8 changed files with 90 additions and 26 deletions

1
.gitattributes vendored
View File

@ -9674,6 +9674,7 @@ tests/test/tclass8.pp svneol=native#text/plain
tests/test/tclass9.pp svneol=native#text/pascal
tests/test/tclassinfo1.pp svneol=native#text/pascal
tests/test/tclrprop.pp svneol=native#text/plain
tests/test/tcmov1.pp svneol=native#text/plain
tests/test/tcmp.pp svneol=native#text/plain
tests/test/tcmp0.pp svneol=native#text/plain
tests/test/tconstref1.pp svneol=native#text/pascal

View File

@ -201,8 +201,8 @@ attsufNONE,
attsufNONE,
attsufNONE,
attsufNONE,
attsufINT,
attsufINT,
attsufINTdual,
attsufINTdual,
attsufINT,
attsufNONE,
attsufINT,

View File

@ -280,6 +280,11 @@ begin
dec(attopcode[0]);
attsuffix:='attsufINT';
end;
'Y' :
begin
dec(attopcode[0]);
attsuffix:='attsufINTdual';
end;
'F' :
begin
dec(attopcode[0]);

View File

@ -29,7 +29,7 @@ interface
cgbase,cpubase;
type
TAttSuffix = (AttSufNONE,AttSufINT,AttSufFPU,AttSufFPUint);
TAttSuffix = (AttSufNONE,AttSufINT,AttSufFPU,AttSufFPUint,AttSufINTdual);
const
{$ifdef x86_64}
@ -52,6 +52,22 @@ interface
't',
''
);
{ suffix-to-opsize conversion tables, used in asmreadrer }
{ !! S_LQ excluded: movzlq does not exist, movslq is processed
as a separate instruction w/o suffix (aka movsxd), and there are
no more instructions needing it. }
att_sizesuffixstr : array[0..11] of string[2] = (
'','BW','BL','WL','BQ','WQ',{'LQ',}'B','W','L','S','Q','T'
);
att_sizesuffix : array[0..11] of topsize = (
S_NO,S_BW,S_BL,S_WL,S_BQ,S_WQ,{S_LQ,}S_B,S_W,S_L,S_FS,S_IQ,S_FX
);
att_sizefpusuffix : array[0..11] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,{S_NO,}S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
);
att_sizefpuintsuffix : array[0..11] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,{S_NO,}S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
);
{$else x86_64}
gas_opsize2str : array[topsize] of string[2] = ('',
'b','w','l','q','bw','bl','wl',
@ -62,6 +78,19 @@ interface
't',
''
);
{ suffix-to-opsize conversion tables, used in asmreadrer }
att_sizesuffixstr : array[0..9] of string[2] = (
'','BW','BL','WL','B','W','L','S','Q','T'
);
att_sizesuffix : array[0..9] of topsize = (
S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
);
att_sizefpusuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
);
att_sizefpuintsuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
);
{$endif x86_64}

View File

@ -759,27 +759,13 @@ Implementation
function tx86attreader.is_asmopcode(const s: string):boolean;
const
{ We need first to check the long prefixes, else we get probs
with things like movsbl }
att_sizesuffixstr : array[0..9] of string[2] = (
'','BW','BL','WL','B','W','L','S','Q','T'
);
att_sizesuffix : array[0..9] of topsize = (
S_NO,S_BW,S_BL,S_WL,S_B,S_W,S_L,S_FS,S_IQ,S_FX
);
att_sizefpusuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_FL,S_FS,S_IQ,S_FX
);
att_sizefpuintsuffix : array[0..9] of topsize = (
S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_IL,S_IS,S_IQ,S_NO
);
var
cond : string[4];
cnd : tasmcond;
len,
j,
sufidx : longint;
sufidx,
suflen : longint;
Begin
is_asmopcode:=FALSE;
@ -790,13 +776,20 @@ Implementation
{ search for all possible suffixes }
for sufidx:=low(att_sizesuffixstr) to high(att_sizesuffixstr) do
begin
len:=length(s)-length(att_sizesuffixstr[sufidx]);
if copy(s,len+1,length(att_sizesuffixstr[sufidx]))=att_sizesuffixstr[sufidx] then
suflen:=length(att_sizesuffixstr[sufidx]);
len:=length(s)-suflen;
if copy(s,len+1,suflen)=att_sizesuffixstr[sufidx] then
begin
{ Search opcodes }
if len>0 then
begin
actopcode:=tasmop(PtrUInt(iasmops.Find(copy(s,1,len))));
{ two-letter suffix is allowed by just a few instructions (movsx,movzx),
and it is always required whenever allowed }
if (gas_needsuffix[actopcode]=attsufINTdual) xor (suflen=2) then
continue;
if actopcode<>A_NONE then
begin
if gas_needsuffix[actopcode]=attsufFPU then

View File

@ -1097,12 +1097,12 @@ void \326\1\xA5 X86_64
(Ch_All, Ch_None, Ch_None)
void \324\1\xA5 8086
[MOVSX,movsX]
[MOVSX,movsY]
(Ch_Wop2, Ch_Rop1, Ch_None)
reg32|64,rm16 \301\320\2\x0F\xBF\110 386
reg16|32|64,rm8 \301\320\2\x0F\xBE\110 386
[MOVZX,movzX]
[MOVZX,movzY]
(Ch_Wop2, Ch_Rop1, Ch_None)
reg32|64,rm16 \301\320\2\x0F\xB7\110 386
reg16|32|64,rm8 \301\320\2\x0F\xB6\110 386
@ -3717,4 +3717,4 @@ void \2\x48\xAD X86_64
[CMPSQ]
(Ch_All, Ch_None, Ch_None)
void \2\x48\xA7 X86_64
void \2\x48\xA7 X86_64

View File

@ -201,8 +201,8 @@ attsufNONE,
attsufNONE,
attsufNONE,
attsufNONE,
attsufINT,
attsufINT,
attsufINTdual,
attsufINTdual,
attsufINT,
attsufNONE,
attsufINT,

36
tests/test/tcmov1.pp Normal file
View File

@ -0,0 +1,36 @@
{ %CPU=x86_64 }
{$mode objfpc}{$asmmode att}
// Test correct assembling of cmov instructions
// they should receive condition and size separately,
// iow cmovbq should not be processed as cmov+bq
function test: Pointer; assembler; nostackframe;
asm
jmp .L3
.L1:
cmovbq %rcx,%rax // 48 0f 42 c1
cmovbl %ecx,%eax // 0f 42 c1
cmovbw %cx,%ax // 66 0f 42 c1
cmovlq %rcx,%rax // 48 0f 4c c1
.L3:
lea .L1(%rip), %rax
end;
var
x: PByte;
begin
x := test;
if (x[0]<>$48) or (x[1]<>$0F) or (x[2]<>$42) or (x[3]<>$C1) then
Halt(1);
Inc(x,4);
if (x[0]<>$0F) or (x[1]<>$42) or (x[2]<>$C1) then
Halt(2);
Inc(x,3);
if (x[0]<>$66) or (x[1]<>$0F) or (x[2]<>$42) or (x[3]<>$C1) then
Halt(3);
Inc(x,4);
if (x[0]<>$48) or (x[1]<>$0F) or (x[2]<>$4C) or (x[3]<>$C1) then
Halt(4);
end.