* more x86_64 assembler support, rtl compilation works, executables don't work yet

git-svn-id: trunk@3038 -
This commit is contained in:
florian 2006-03-26 09:38:05 +00:00
parent 5519158dff
commit 4c9a08b12b
2 changed files with 135 additions and 63 deletions

View File

@ -1491,27 +1491,43 @@ implementation
{ base }
case br of
NR_R8,
NR_RAX : base:=0;
NR_R9,
NR_RCX : base:=1;
NR_R10,
NR_RDX : base:=2;
NR_R11,
NR_RBX : base:=3;
NR_R12,
NR_RSP : base:=4;
NR_R13,
NR_NO,
NR_RBP : base:=5;
NR_R14,
NR_RSI : base:=6;
NR_R15,
NR_RDI : base:=7;
else
exit;
end;
{ index }
case ir of
NR_R8,
NR_RAX : index:=0;
NR_R9,
NR_RCX : index:=1;
NR_R10,
NR_RDX : index:=2;
NR_R11,
NR_RBX : index:=3;
NR_R12,
NR_NO : index:=4;
NR_R13,
NR_RBP : index:=5;
NR_R14,
NR_RSI : index:=6;
NR_R15,
NR_RDI : index:=7;
else
exit;
@ -1709,6 +1725,9 @@ implementation
begin
len:=0;
codes:=@p^.code;
{$ifdef x86_64}
rex:=0;
{$endif x86_64}
repeat
c:=ord(codes^);
inc(codes);
@ -1727,7 +1746,11 @@ implementation
(getsupreg(oper[c-8]^.reg)>=RS_R8)) or
((getregtype(oper[c-8]^.reg)=R_MMREGISTER) and
(getsupreg(oper[c-8]^.reg)>=RS_XMM8)) then
rex:=rex or $41;
begin
if rex=0 then
inc(len);
rex:=rex or $41;
end;
{$endif x86_64}
inc(codes);
inc(len);
@ -1776,8 +1799,9 @@ implementation
{$ifdef x86_64}
OT_BITS64:
begin
if rex=0 then
inc(len);
rex:=rex or $48;
inc(len);
end;
{$endif x86_64}
end;
@ -1808,6 +1832,22 @@ implementation
64..191 :
begin
{$ifdef x86_64}
if (c<127) then
begin
if (oper[c and 7]^.typ=top_reg) then
begin
if ((getregtype(oper[c and 7]^.reg)=R_INTREGISTER) and
(getsupreg(oper[c and 7]^.reg)>=RS_R8)) or
((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;
end;
end;
ea_data.rex:=0;
ea_data.rex_present:=false;
{$endif x86_64}
@ -1924,7 +1964,7 @@ implementation
{$endif extdebug}
{ safety check }
if objdata.currobjsec.size<>insoffset then
internalerror(200130121);
internalerror(200130121);
{ load data to write }
codes:=insentry^.code;
{ Force word push/pop for registers }
@ -1942,6 +1982,16 @@ implementation
break;
1,2,3 :
begin
{$ifdef x86_64}
if rex<>0 then
begin
bytes[0]:=rex;
{$ifdef extdebug}
rexwritten:=true;
{$endif extdebug}
objdata.writebytes(bytes,1);
end;
{$endif x86_64}
objdata.writebytes(codes^,c);
inc(codes,c);
end;
@ -1981,11 +2031,23 @@ implementation
8,9,10 :
begin
{ rex should be written at this point }
{
{$ifdef x86_64}
{$ifdef extdebug}
if (rex<>0) and not(rexwritten) then
internalerror(200603192);
{$endif extdebug}
{$endif x86_64}
}
{$ifdef x86_64}
if rex<>0 then
begin
bytes[0]:=rex;
{$ifdef extdebug}
rexwritten:=true;
{$endif extdebug}
objdata.writebytes(bytes,1);
end;
{$endif x86_64}
bytes[0]:=ord(codes^)+regval(oper[c-8]^.reg);
inc(codes);
@ -2120,6 +2182,7 @@ implementation
Message(asmw_e_64bit_not_supported);
{$endif x86_64}
end;
{
{$ifdef x86_64}
if rex<>0 then
begin
@ -2130,6 +2193,7 @@ implementation
objdata.writebytes(bytes,1);
end;
{$endif x86_64}
}
end;
212 :
begin

View File

@ -242,65 +242,72 @@ begin
operands[i].SetCorrectSize(opcode);
if tx86operand(operands[i]).opsize=S_NO then
begin
case operands[i].Opr.Typ of
OPR_LOCAL,
OPR_REFERENCE :
begin
if i=2 then
operand2:=1
else
operand2:=2;
if operand2<ops then
begin
{ Only allow register as operand to take the size from }
if operands[operand2].opr.typ=OPR_REGISTER then
begin
if ((opcode<>A_MOVD) and
(opcode<>A_CVTSI2SS)) then
tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
end
else
begin
{ if no register then take the opsize (which is available with ATT),
if not availble then give an error }
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
else
begin
if (m_delphi in aktmodeswitches) then
Message(asmr_w_unable_to_determine_reference_size_using_dword)
else
Message(asmr_e_unable_to_determine_reference_size);
{ recovery }
tx86operand(operands[i]).opsize:=S_L;
end;
end;
end
else
begin
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
end;
end;
OPR_SYMBOL :
begin
{ Fix lea which need a reference }
if opcode=A_LEA then
begin
s:=operands[i].opr.symbol;
so:=operands[i].opr.symofs;
operands[i].opr.typ:=OPR_REFERENCE;
Fillchar(operands[i].opr.ref,sizeof(treference),0);
operands[i].opr.ref.symbol:=s;
operands[i].opr.ref.offset:=so;
end;
{$ifdef x86_64}
tx86operand(operands[i]).opsize:=S_Q;
{$else x86_64}
tx86operand(operands[i]).opsize:=S_L;
if (opcode=A_MOVQ) and
(ops=2) and
(operands[1].opr.typ=OPR_CONSTANT) then
opsize:=S_Q
else
{$endif x86_64}
end;
end;
case operands[i].Opr.Typ of
OPR_LOCAL,
OPR_REFERENCE :
begin
if i=2 then
operand2:=1
else
operand2:=2;
if operand2<ops then
begin
{ Only allow register as operand to take the size from }
if operands[operand2].opr.typ=OPR_REGISTER then
begin
if ((opcode<>A_MOVD) and
(opcode<>A_CVTSI2SS)) then
tx86operand(operands[i]).opsize:=tx86operand(operands[operand2]).opsize;
end
else
begin
{ if no register then take the opsize (which is available with ATT),
if not availble then give an error }
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
else
begin
if (m_delphi in aktmodeswitches) then
Message(asmr_w_unable_to_determine_reference_size_using_dword)
else
Message(asmr_e_unable_to_determine_reference_size);
{ recovery }
tx86operand(operands[i]).opsize:=S_L;
end;
end;
end
else
begin
if opsize<>S_NO then
tx86operand(operands[i]).opsize:=opsize
end;
end;
OPR_SYMBOL :
begin
{ Fix lea which need a reference }
if opcode=A_LEA then
begin
s:=operands[i].opr.symbol;
so:=operands[i].opr.symofs;
operands[i].opr.typ:=OPR_REFERENCE;
Fillchar(operands[i].opr.ref,sizeof(treference),0);
operands[i].opr.ref.symbol:=s;
operands[i].opr.ref.offset:=so;
end;
{$ifdef x86_64}
tx86operand(operands[i]).opsize:=S_Q;
{$else x86_64}
tx86operand(operands[i]).opsize:=S_L;
{$endif x86_64}
end;
end;
end;
end;
end;
@ -555,14 +562,15 @@ begin
end;
{$ifdef x86_64}
{ Convert movq with at least one general registers to mov instruction }
{ Convert movq with at least one general registers or constant to a mov instruction }
if (opcode=A_MOVQ) and
(ops=2) and
(
(operands[1].opr.typ=OPR_REGISTER) or
(operands[2].opr.typ=OPR_REGISTER)
(operands[2].opr.typ=OPR_REGISTER) or
(operands[1].opr.typ=OPR_CONSTANT)
) then
opcode:=A_MOV;
opcode:=A_MOV;
{$endif x86_64}
{ GNU AS interprets FDIV without operand differently