mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 14:47:55 +02:00
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:
parent
918909c65d
commit
f97f223de6
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -201,8 +201,8 @@ attsufNONE,
|
||||
attsufNONE,
|
||||
attsufNONE,
|
||||
attsufNONE,
|
||||
attsufINT,
|
||||
attsufINT,
|
||||
attsufINTdual,
|
||||
attsufINTdual,
|
||||
attsufINT,
|
||||
attsufNONE,
|
||||
attsufINT,
|
||||
|
@ -280,6 +280,11 @@ begin
|
||||
dec(attopcode[0]);
|
||||
attsuffix:='attsufINT';
|
||||
end;
|
||||
'Y' :
|
||||
begin
|
||||
dec(attopcode[0]);
|
||||
attsuffix:='attsufINTdual';
|
||||
end;
|
||||
'F' :
|
||||
begin
|
||||
dec(attopcode[0]);
|
||||
|
@ -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}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -201,8 +201,8 @@ attsufNONE,
|
||||
attsufNONE,
|
||||
attsufNONE,
|
||||
attsufNONE,
|
||||
attsufINT,
|
||||
attsufINT,
|
||||
attsufINTdual,
|
||||
attsufINTdual,
|
||||
attsufINT,
|
||||
attsufNONE,
|
||||
attsufINT,
|
||||
|
36
tests/test/tcmov1.pp
Normal file
36
tests/test/tcmov1.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user