From 4c9a08b12b8d9ba38d41d22a009640792a583a32 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 26 Mar 2006 09:38:05 +0000 Subject: [PATCH] * more x86_64 assembler support, rtl compilation works, executables don't work yet git-svn-id: trunk@3038 - --- compiler/x86/aasmcpu.pas | 70 ++++++++++++++++++++- compiler/x86/rax86.pas | 128 +++++++++++++++++++++------------------ 2 files changed, 135 insertions(+), 63 deletions(-) diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index 3e8fe7a348..6fd4bc434e 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -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 diff --git a/compiler/x86/rax86.pas b/compiler/x86/rax86.pas index 482d0dca87..5dd43557c9 100644 --- a/compiler/x86/rax86.pas +++ b/compiler/x86/rax86.pas @@ -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 operand2A_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 operand2A_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