mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-19 00:39:34 +02:00
* first x86-64 patches
This commit is contained in:
parent
95c6c8f430
commit
479a745096
1103
compiler/aasm.pas
Normal file
1103
compiler/aasm.pas
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ interface
|
||||
|
||||
type
|
||||
{ System independent float names }
|
||||
{$ifdef i386}
|
||||
{$ifdef x86}
|
||||
bestreal = extended;
|
||||
ts32real = single;
|
||||
ts64real = double;
|
||||
@ -255,7 +255,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.27 2002-07-01 18:46:22 peter
|
||||
Revision 1.28 2002-07-04 20:43:00 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.27 2002/07/01 18:46:22 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -299,4 +302,4 @@ end.
|
||||
* implicit result variable generation for assembler routines
|
||||
* removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
|
||||
|
||||
}
|
||||
}
|
791
compiler/i386/tgcpu.pas
Normal file
791
compiler/i386/tgcpu.pas
Normal file
@ -0,0 +1,791 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (C) 1998-2000 by Florian Klaempfl
|
||||
|
||||
This unit handles the temporary variables stuff for i386
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
unit tgcpu;
|
||||
|
||||
{$i defines.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
globals,
|
||||
cgbase,verbose,aasm,
|
||||
node,
|
||||
cpubase,cpuasm
|
||||
;
|
||||
|
||||
type
|
||||
tregisterset = set of tregister;
|
||||
|
||||
tpushed = array[R_EAX..R_MM6] of boolean;
|
||||
tsaved = array[R_EAX..R_MM6] of longint;
|
||||
|
||||
const
|
||||
usablereg32 : byte = 4;
|
||||
|
||||
{ this value is used in tsaved, if the register isn't saved }
|
||||
reg_not_saved = $7fffffff;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
usableregmmx : byte = 8;
|
||||
{$endif SUPPORT_MMX}
|
||||
|
||||
var
|
||||
{ tries to hold the amount of times which the current tree is processed }
|
||||
t_times : longint;
|
||||
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
procedure testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
function getregisterint : tregister;
|
||||
function getaddressregister: tregister;
|
||||
procedure ungetregister32(r : tregister);
|
||||
{ tries to allocate the passed register, if possible }
|
||||
function getexplicitregister32(r : tregister) : tregister;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
function getregistermmx : tregister;
|
||||
procedure ungetregistermmx(r : tregister);
|
||||
{$endif SUPPORT_MMX}
|
||||
|
||||
function isaddressregister(reg: tregister): boolean;
|
||||
|
||||
procedure ungetregister(r : tregister);
|
||||
|
||||
procedure cleartempgen;
|
||||
procedure del_reference(const ref : treference);
|
||||
procedure del_locref(const location : tlocation);
|
||||
procedure del_location(const l : tlocation);
|
||||
|
||||
{ pushs and restores registers }
|
||||
procedure pushusedregisters(var pushed : tpushed;b : tregisterset);
|
||||
procedure popusedregisters(const pushed : tpushed);
|
||||
|
||||
{ saves register variables (restoring happens automatically (JM) }
|
||||
procedure saveregvars(b : tregisterset);
|
||||
|
||||
{ saves and restores used registers to temp. values }
|
||||
procedure saveusedregisters(var saved : tsaved;b : tregisterset);
|
||||
procedure restoreusedregisters(const saved : tsaved);
|
||||
|
||||
{ increments the push count of all registers in b}
|
||||
procedure incrementregisterpushed(b : tregisterset);
|
||||
|
||||
procedure clearregistercount;
|
||||
procedure resetusableregisters;
|
||||
|
||||
{ corrects the fpu stack register by ofs }
|
||||
function correct_fpuregister(r : tregister;ofs : byte) : tregister;
|
||||
|
||||
type
|
||||
{$ifdef SUPPORT_MMX}
|
||||
regvar_longintarray = array[R_EAX..R_MM6] of longint;
|
||||
regvar_booleanarray = array[R_EAX..R_MM6] of boolean;
|
||||
regvar_ptreearray = array[R_EAX..R_MM6] of tnode;
|
||||
{$else SUPPORT_MMX}
|
||||
regvar_longintarray = array[R_EAX..R_EDI] of longint;
|
||||
regvar_booleanarray = array[R_EAX..R_EDI] of boolean;
|
||||
regvar_ptreearray = array[R_EAX..R_EDI] of tnode;
|
||||
{$endif SUPPORT_MMX}
|
||||
|
||||
var
|
||||
unused,usableregs : tregisterset;
|
||||
c_usableregs : longint;
|
||||
|
||||
{ uses only 1 byte while a set uses in FPC 32 bytes }
|
||||
usedinproc : tregisterset;
|
||||
|
||||
fpuvaroffset : byte;
|
||||
|
||||
{ count, how much a register must be pushed if it is used as register }
|
||||
{ variable }
|
||||
reg_pushes : regvar_longintarray;
|
||||
is_reg_var : regvar_booleanarray;
|
||||
regvar_loaded: regvar_booleanarray;
|
||||
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user : regvar_ptreearray;
|
||||
reg_releaser : regvar_ptreearray;
|
||||
{$endif TEMPREGDEBUG}
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
globtype,temp_gen,tainst,regvars;
|
||||
|
||||
procedure incrementregisterpushed(b : tregisterset);
|
||||
|
||||
var
|
||||
regi : tregister;
|
||||
|
||||
begin
|
||||
for regi:=R_EAX to R_EDI do
|
||||
begin
|
||||
if regi in b then
|
||||
inc(reg_pushes[regi],t_times*2);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure pushusedregisters(var pushed : tpushed;b : tregisterset);
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
hr : preference;
|
||||
{$endif}
|
||||
begin
|
||||
usedinproc:=usedinproc+b;
|
||||
for r:=R_EAX to R_EBX do
|
||||
begin
|
||||
pushed[r]:=false;
|
||||
{ if the register is used by the calling subroutine }
|
||||
if r in b then
|
||||
begin
|
||||
{ and is present in use }
|
||||
if not is_reg_var[r] then
|
||||
if not(r in unused) then
|
||||
begin
|
||||
{ then save it }
|
||||
exprasmlist.concat(Taicpu.Op_reg(A_PUSH,S_L,r));
|
||||
|
||||
{ here was a big problem !!!!!}
|
||||
{ you cannot do that for a register that is
|
||||
globally assigned to a var
|
||||
this also means that you must push it much more
|
||||
often, but there must be a better way
|
||||
maybe by putting the value back to the stack !! }
|
||||
if not(is_reg_var[r]) then
|
||||
begin
|
||||
unused:=unused+[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
inc(usablereg32);
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
pushed[r]:=true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
for r:=R_MM0 to R_MM6 do
|
||||
begin
|
||||
pushed[r]:=false;
|
||||
{ if the mmx register is in use, save it }
|
||||
if not(r in unused) then
|
||||
begin
|
||||
exprasmList.concat(Taicpu.Op_const_reg(A_SUB,S_L,8,R_ESP));
|
||||
new(hr);
|
||||
reset_reference(hr^);
|
||||
hr^.base:=R_ESP;
|
||||
exprasmList.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r,hr));
|
||||
if not(is_reg_var[r]) then
|
||||
begin
|
||||
unused:=unused+[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
inc(usableregmmx);
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
pushed[r]:=true;
|
||||
end;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
|
||||
procedure saveregvars(b : tregisterset);
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
|
||||
begin
|
||||
if not(cs_regalloc in aktglobalswitches) then
|
||||
exit;
|
||||
for r:=R_EAX to R_EBX do
|
||||
{ if the register is used by the calling subroutine }
|
||||
if (r in b) and is_reg_var[r] then
|
||||
store_regvar(exprasmlist,r)
|
||||
end;
|
||||
|
||||
|
||||
procedure saveusedregisters(var saved : tsaved;b : tregisterset);
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
hr : treference;
|
||||
|
||||
begin
|
||||
usedinproc:=usedinproc+b;
|
||||
for r:=R_EAX to R_EBX do
|
||||
begin
|
||||
saved[r]:=reg_not_saved;
|
||||
{ if the register is used by the calling subroutine }
|
||||
if r in b then
|
||||
begin
|
||||
{ and is present in use }
|
||||
if not(r in unused) then
|
||||
begin
|
||||
{ then save it }
|
||||
gettempofsizereference(4,hr);
|
||||
saved[r]:=hr.offset;
|
||||
exprasmList.concat(Taicpu.Op_reg_ref(A_MOV,S_L,r,newreference(hr)));
|
||||
{ here was a big problem !!!!!}
|
||||
{ you cannot do that for a register that is
|
||||
globally assigned to a var
|
||||
this also means that you must push it much more
|
||||
often, but there must be a better way
|
||||
maybe by putting the value back to the stack !! }
|
||||
if not(is_reg_var[r]) then
|
||||
begin
|
||||
unused:=unused+[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
inc(usablereg32);
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
for r:=R_MM0 to R_MM6 do
|
||||
begin
|
||||
saved[r]:=reg_not_saved;
|
||||
{ if the mmx register is in use, save it }
|
||||
if not(r in unused) then
|
||||
begin
|
||||
gettempofsizereference(8,hr);
|
||||
exprasmList.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r,newreference(hr)));
|
||||
if not(is_reg_var[r]) then
|
||||
begin
|
||||
unused:=unused+[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
inc(usableregmmx);
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
saved[r]:=hr.offset;
|
||||
end;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
procedure popusedregisters(const pushed : tpushed);
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
{$ifdef SUPPORT_MMX}
|
||||
hr : preference;
|
||||
{$endif SUPPORT_MMX}
|
||||
begin
|
||||
{ restore in reverse order: }
|
||||
{$ifdef SUPPORT_MMX}
|
||||
for r:=R_MM6 downto R_MM0 do
|
||||
begin
|
||||
if pushed[r] then
|
||||
begin
|
||||
new(hr);
|
||||
reset_reference(hr^);
|
||||
hr^.base:=R_ESP;
|
||||
exprasmList.concat(Taicpu.Op_ref_reg(
|
||||
A_MOVQ,S_NO,hr,r));
|
||||
exprasmList.concat(Taicpu.Op_const_reg(
|
||||
A_ADD,S_L,8,R_ESP));
|
||||
unused:=unused-[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
dec(usableregmmx);
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
for r:=R_EBX downto R_EAX do
|
||||
if pushed[r] then
|
||||
begin
|
||||
exprasmList.concat(Taicpu.Op_reg(A_POP,S_L,r));
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
if not (r in unused) then
|
||||
{ internalerror(10)
|
||||
in cg386cal we always restore regs
|
||||
that appear as used
|
||||
due to a unused tmep storage PM }
|
||||
else
|
||||
dec(usablereg32);
|
||||
{$endif TEMPREGDEBUG}
|
||||
unused:=unused-[r];
|
||||
end;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
procedure restoreusedregisters(const saved : tsaved);
|
||||
var
|
||||
r : tregister;
|
||||
hr : treference;
|
||||
|
||||
begin
|
||||
{ restore in reverse order: }
|
||||
{$ifdef SUPPORT_MMX}
|
||||
for r:=R_MM6 downto R_MM0 do
|
||||
begin
|
||||
if saved[r]<>reg_not_saved then
|
||||
begin
|
||||
reset_reference(hr);
|
||||
hr.base:=frame_pointer;
|
||||
hr.offset:=saved[r];
|
||||
exprasmList.concat(Taicpu.Op_ref_reg(
|
||||
A_MOVQ,S_NO,newreference(hr),r));
|
||||
unused:=unused-[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
dec(usableregmmx);
|
||||
{$endif TEMPREGDEBUG}
|
||||
ungetiftemp(hr);
|
||||
end;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
for r:=R_EBX downto R_EAX do
|
||||
if saved[r]<>reg_not_saved then
|
||||
begin
|
||||
reset_reference(hr);
|
||||
hr.base:=frame_pointer;
|
||||
hr.offset:=saved[r];
|
||||
exprasmList.concat(Taicpu.Op_ref_reg(A_MOV,S_L,newreference(hr),r));
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
if not (r in unused) then
|
||||
internalerror(10)
|
||||
else
|
||||
dec(usablereg32);
|
||||
{$endif TEMPREGDEBUG}
|
||||
unused:=unused-[r];
|
||||
ungetiftemp(hr);
|
||||
end;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
procedure ungetregister(r : tregister);
|
||||
|
||||
begin
|
||||
if r in [R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI] then
|
||||
ungetregister32(r)
|
||||
else if r in [R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI] then
|
||||
ungetregister32(reg16toreg32(r))
|
||||
else if r in [R_AL,R_BL,R_CL,R_DL] then
|
||||
ungetregister32(reg8toreg32(r))
|
||||
{$ifdef SUPPORT_MMX}
|
||||
else if r in [R_MM0..R_MM6] then
|
||||
ungetregistermmx(r)
|
||||
{$endif SUPPORT_MMX}
|
||||
else internalerror(200112021);
|
||||
end;
|
||||
|
||||
procedure ungetregister32(r : tregister);
|
||||
|
||||
begin
|
||||
if (r = R_EDI) or
|
||||
((not assigned(procinfo^._class)) and (r = R_ESI)) then
|
||||
begin
|
||||
exprasmList.concat(Tairegalloc.DeAlloc(r));
|
||||
exit;
|
||||
end;
|
||||
if cs_regalloc in aktglobalswitches then
|
||||
begin
|
||||
{ takes much time }
|
||||
if not(r in usableregs) then
|
||||
exit;
|
||||
unused:=unused+[r];
|
||||
inc(usablereg32);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if not(r in [R_EAX,R_EBX,R_ECX,R_EDX]) then
|
||||
exit;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
if (r in unused) then
|
||||
{$ifdef EXTTEMPREGDEBUG}
|
||||
begin
|
||||
Comment(V_Debug,'register freed twice '+reg2str(r));
|
||||
testregisters32;
|
||||
exit;
|
||||
end
|
||||
{$else EXTTEMPREGDEBUG}
|
||||
exit
|
||||
{$endif EXTTEMPREGDEBUG}
|
||||
else
|
||||
{$endif TEMPREGDEBUG}
|
||||
inc(usablereg32);
|
||||
unused:=unused+[r];
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_releaser[r]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
exprasmList.concat(Tairegalloc.DeAlloc(r));
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end;
|
||||
|
||||
{$ifdef SUPPORT_MMX}
|
||||
function getregistermmx : tregister;
|
||||
|
||||
var
|
||||
r : tregister;
|
||||
|
||||
begin
|
||||
dec(usableregmmx);
|
||||
for r:=R_MM0 to R_MM6 do
|
||||
if r in unused then
|
||||
begin
|
||||
unused:=unused-[r];
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EAX));
|
||||
getregistermmx:=r;
|
||||
exit;
|
||||
end;
|
||||
internalerror(10);
|
||||
end;
|
||||
|
||||
procedure ungetregistermmx(r : tregister);
|
||||
|
||||
begin
|
||||
if cs_regalloc in aktglobalswitches then
|
||||
begin
|
||||
{ takes much time }
|
||||
if not(r in usableregs) then
|
||||
exit;
|
||||
unused:=unused+[r];
|
||||
inc(usableregmmx);
|
||||
end
|
||||
else
|
||||
begin
|
||||
unused:=unused+[r];
|
||||
inc(usableregmmx);
|
||||
end;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
|
||||
function isaddressregister(reg: tregister): boolean;
|
||||
|
||||
begin
|
||||
isaddressregister := true;
|
||||
end;
|
||||
|
||||
procedure del_reference(const ref : treference);
|
||||
|
||||
begin
|
||||
if ref.is_immediate then
|
||||
exit;
|
||||
ungetregister32(ref.base);
|
||||
ungetregister32(ref.index);
|
||||
end;
|
||||
|
||||
|
||||
procedure del_locref(const location : tlocation);
|
||||
begin
|
||||
if (location.loc<>loc_mem) and (location.loc<>loc_reference) then
|
||||
exit;
|
||||
if location.reference.is_immediate then
|
||||
exit;
|
||||
ungetregister32(location.reference.base);
|
||||
ungetregister32(location.reference.index);
|
||||
end;
|
||||
|
||||
|
||||
procedure del_location(const l : tlocation);
|
||||
begin
|
||||
case l.loc of
|
||||
LOC_REGISTER :
|
||||
ungetregister(l.register);
|
||||
LOC_MEM,LOC_REFERENCE :
|
||||
del_reference(l.reference);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
procedure testregisters32;
|
||||
var test : byte;
|
||||
begin
|
||||
test:=0;
|
||||
if R_EAX in unused then
|
||||
inc(test);
|
||||
if R_EBX in unused then
|
||||
inc(test);
|
||||
if R_ECX in unused then
|
||||
inc(test);
|
||||
if R_EDX in unused then
|
||||
inc(test);
|
||||
if test<>usablereg32 then
|
||||
internalerror(10);
|
||||
end;
|
||||
{$endif TEMPREGDEBUG}
|
||||
|
||||
<<<<<<< tgcpu.pas
|
||||
function getregister32 : tregister;
|
||||
var
|
||||
r : tregister;
|
||||
=======
|
||||
function getregisterint : tregister;
|
||||
>>>>>>> 1.8
|
||||
begin
|
||||
if usablereg32=0 then
|
||||
internalerror(10);
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
if curptree^^.usableregs-usablereg32>curptree^^.registers32 then
|
||||
internalerror(10);
|
||||
{$endif TEMPREGDEBUG}
|
||||
{$ifdef EXTTEMPREGDEBUG}
|
||||
if curptree^^.usableregs-usablereg32>curptree^^.reallyusedregs then
|
||||
curptree^^.reallyusedregs:=curptree^^.usableregs-usablereg32;
|
||||
{$endif EXTTEMPREGDEBUG}
|
||||
dec(usablereg32);
|
||||
if R_EAX in unused then
|
||||
begin
|
||||
<<<<<<< tgcpu.pas
|
||||
r:=R_EAX;
|
||||
=======
|
||||
unused:=unused-[R_EAX];
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EAX));
|
||||
getregisterint:=R_EAX;
|
||||
>>>>>>> 1.8
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user[R_EAX]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
exprasmList.concat(Tairegalloc.Alloc(R_EAX));
|
||||
end
|
||||
else if R_EDX in unused then
|
||||
begin
|
||||
<<<<<<< tgcpu.pas
|
||||
r:=R_EDX;
|
||||
=======
|
||||
unused:=unused-[R_EDX];
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EDX));
|
||||
getregisterint:=R_EDX;
|
||||
>>>>>>> 1.8
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user[R_EDX]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
exprasmList.concat(Tairegalloc.Alloc(R_EDX));
|
||||
end
|
||||
else if R_EBX in unused then
|
||||
begin
|
||||
<<<<<<< tgcpu.pas
|
||||
r:=R_EBX;
|
||||
=======
|
||||
unused:=unused-[R_EBX];
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_EBX));
|
||||
getregisterint:=R_EBX;
|
||||
>>>>>>> 1.8
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user[R_EBX]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
exprasmList.concat(Tairegalloc.Alloc(R_EBX));
|
||||
end
|
||||
else if R_ECX in unused then
|
||||
begin
|
||||
<<<<<<< tgcpu.pas
|
||||
r:=R_ECX;
|
||||
=======
|
||||
unused:=unused-[R_ECX];
|
||||
usedinproc:=usedinproc or ($80 shr byte(R_ECX));
|
||||
getregisterint:=R_ECX;
|
||||
>>>>>>> 1.8
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
reg_user[R_ECX]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
exprasmList.concat(Tairegalloc.Alloc(R_ECX));
|
||||
end
|
||||
else internalerror(10);
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
exclude(unused,r);
|
||||
include(usedinproc,r);
|
||||
getregister32:=r;
|
||||
end;
|
||||
|
||||
|
||||
function getaddressregister: tregister;
|
||||
|
||||
begin
|
||||
getaddressregister := getregisterint;
|
||||
end;
|
||||
|
||||
function getexplicitregister32(r : tregister) : tregister;
|
||||
|
||||
begin
|
||||
if r in [R_ESI,R_EDI] then
|
||||
begin
|
||||
exprasmList.concat(Tairegalloc.Alloc(r));
|
||||
getexplicitregister32 := r;
|
||||
exit;
|
||||
end;
|
||||
if r in unused then
|
||||
begin
|
||||
dec(usablereg32);
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
if curptree^^.usableregs-usablereg32>curptree^^.registers32 then
|
||||
internalerror(10);
|
||||
reg_user[r]:=curptree^;
|
||||
{$endif TEMPREGDEBUG}
|
||||
include(unused,r);
|
||||
include(usedinproc,r);
|
||||
exprasmList.concat(Tairegalloc.Alloc(r));
|
||||
getexplicitregister32:=r;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
testregisters32;
|
||||
{$endif TEMPREGDEBUG}
|
||||
end
|
||||
else
|
||||
getexplicitregister32:=getregisterint;
|
||||
end;
|
||||
|
||||
procedure cleartempgen;
|
||||
|
||||
begin
|
||||
unused:=usableregs;
|
||||
usablereg32:=c_usableregs;
|
||||
{fpuvaroffset:=0;
|
||||
this must only be resetted at each procedure
|
||||
compilation start PM }
|
||||
end;
|
||||
|
||||
|
||||
procedure clearregistercount;
|
||||
var
|
||||
regi : tregister;
|
||||
begin
|
||||
{$ifdef SUPPORT_MMX}
|
||||
for regi:=R_EAX to R_MM6 do
|
||||
begin
|
||||
reg_pushes[regi]:=0;
|
||||
is_reg_var[regi]:=false;
|
||||
end;
|
||||
{$else SUPPORT_MMX}
|
||||
for regi:=R_EAX to R_EDI do
|
||||
begin
|
||||
reg_pushes[regi]:=0;
|
||||
is_reg_var[regi]:=false;
|
||||
end;
|
||||
{$endif SUPPORT_MMX}
|
||||
end;
|
||||
|
||||
function correct_fpuregister(r : tregister;ofs : byte) : tregister;
|
||||
|
||||
begin
|
||||
correct_fpuregister:=tregister(longint(r)+ofs);
|
||||
end;
|
||||
|
||||
procedure resetusableregisters;
|
||||
begin
|
||||
{$ifdef SUPPORT_MMX}
|
||||
usableregs:=[R_EAX,R_EBX,R_ECX,R_EDX,R_MM0..R_MM6];
|
||||
c_usableregs:=4;
|
||||
usableregmmx:=8;
|
||||
{$else}
|
||||
usableregs:=[R_EAX,R_EBX,R_ECX,R_EDX];
|
||||
c_usableregs:=4;
|
||||
{$endif SUPPORT_MMX}
|
||||
fillchar(regvar_loaded,sizeof(regvar_loaded),false);
|
||||
fillchar(is_reg_var,sizeof(is_reg_var),false);
|
||||
fpuvaroffset:=0;
|
||||
end;
|
||||
|
||||
begin
|
||||
resetusableregisters;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.10 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.9 2002/03/31 20:26:42 jonas
|
||||
+ a_loadfpu_* and a_loadmm_* methods in tcg
|
||||
* register allocation is now handled by a class and is mostly processor
|
||||
independent (+rgobj.pas and i386/rgcpu.pas)
|
||||
* temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
|
||||
* some small improvements and fixes to the optimizer
|
||||
* some register allocation fixes
|
||||
* some fpuvaroffset fixes in the unary minus node
|
||||
* push/popusedregisters is now called rg.save/restoreusedregisters and
|
||||
(for i386) uses temps instead of push/pop's when using -Op3 (that code is
|
||||
also better optimizable)
|
||||
* fixed and optimized register saving/restoring for new/dispose nodes
|
||||
* LOC_FPU locations now also require their "register" field to be set to
|
||||
R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
|
||||
- list field removed of the tnode class because it's not used currently
|
||||
and can cause hard-to-find bugs
|
||||
|
||||
Revision 1.8 2001/12/31 09:53:16 jonas
|
||||
* changed remaining "getregister32" calls to "getregisterint"
|
||||
|
||||
Revision 1.7 2001/12/29 15:29:59 jonas
|
||||
* powerpc/cgcpu.pas compiles :)
|
||||
* several powerpc-related fixes
|
||||
* cpuasm unit is now based on common tainst unit
|
||||
+ nppcmat unit for powerpc (almost complete)
|
||||
|
||||
Revision 1.5 2001/08/26 13:37:03 florian
|
||||
* some cg reorganisation
|
||||
* some PPC updates
|
||||
|
||||
Revision 1.4 2001/04/13 01:22:21 peter
|
||||
* symtable change to classes
|
||||
* range check generation and errors fixed, make cycle DEBUG=1 works
|
||||
* memory leaks fixed
|
||||
|
||||
Revision 1.3 2000/12/25 00:07:34 peter
|
||||
+ new tlinkedlist class (merge of old tstringqueue,tcontainer and
|
||||
tlinkedlist objects)
|
||||
|
||||
Revision 1.2 2000/12/05 11:44:34 jonas
|
||||
+ new integer regvar handling, should be much more efficient
|
||||
|
||||
Revision 1.1 2000/11/29 00:30:51 florian
|
||||
* unused units removed from uses clause
|
||||
* some changes for widestrings
|
||||
|
||||
Revision 1.9 2000/10/31 22:30:13 peter
|
||||
* merged asm result patch part 2
|
||||
|
||||
Revision 1.8 2000/10/14 10:14:56 peter
|
||||
* moehrendorf oct 2000 rewrite
|
||||
|
||||
Revision 1.7 2000/09/30 16:08:46 peter
|
||||
* more cg11 updates
|
||||
|
||||
Revision 1.6 2000/09/24 15:06:32 peter
|
||||
* use defines.inc
|
||||
|
||||
Revision 1.5 2000/08/27 16:11:55 peter
|
||||
* moved some util functions from globals,cobjects to cutils
|
||||
* splitted files into finput,fmodule
|
||||
|
||||
Revision 1.4 2000/08/05 13:32:39 peter
|
||||
* fixed build prob without support_mmx
|
||||
|
||||
Revision 1.3 2000/08/04 05:09:49 jonas
|
||||
* forgot to commit :( (part of regvar changes)
|
||||
|
||||
Revision 1.2 2000/07/13 11:32:52 michael
|
||||
+ removed logs
|
||||
}
|
@ -813,7 +813,6 @@ implementation
|
||||
;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
i : longint;
|
||||
found,
|
||||
@ -1631,9 +1630,9 @@ implementation
|
||||
procinfo^.flags:=procinfo^.flags or pi_do_call;
|
||||
end;
|
||||
|
||||
{ for the PowerPC standard calling conventions this information isn't necassary (FK) }
|
||||
{ It doesn't hurt to calculate it already though :) (JM) }
|
||||
rg.incrementregisterpushed(tprocdef(procdefinition).usedregisters);
|
||||
|
||||
end;
|
||||
|
||||
{ get a register for the return value }
|
||||
@ -1744,7 +1743,7 @@ implementation
|
||||
|
||||
registersfpu:=max(methodpointer.registersfpu,registersfpu);
|
||||
registers32:=max(methodpointer.registers32,registers32);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
{$ifdef SUPPORT_MMX }
|
||||
registersmmx:=max(methodpointer.registersmmx,registersmmx);
|
||||
{$endif SUPPORT_MMX}
|
||||
end;
|
||||
@ -1871,7 +1870,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.77 2002-07-01 16:23:52 peter
|
||||
Revision 1.78 2002-07-04 20:43:00 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.77 2002/07/01 16:23:52 peter
|
||||
* cg64 patch
|
||||
* basics for currency
|
||||
* asnode updates for class and interface (not finished)
|
||||
@ -1982,4 +1984,4 @@ end.
|
||||
Revision 1.62 2002/01/19 11:57:05 peter
|
||||
* fixed path appending for lib
|
||||
|
||||
}
|
||||
}
|
@ -490,7 +490,10 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.17 2002-07-01 18:46:22 peter
|
||||
Revision 1.18 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.17 2002/07/01 18:46:22 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -580,4 +583,4 @@ end.
|
||||
- list field removed of the tnode class because it's not used currently
|
||||
and can cause hard-to-find bugs
|
||||
|
||||
}
|
||||
}
|
@ -75,8 +75,9 @@ implementation
|
||||
cginfo,cgbase,pass_2,
|
||||
cpubase,cpuinfo,
|
||||
nld,ncon,
|
||||
tgobj,rgobj,
|
||||
ncgutil,
|
||||
cga,
|
||||
tgobj,rgobj,
|
||||
regvars,cgobj,cgcpu,cg64f32;
|
||||
|
||||
{*****************************************************************************
|
||||
@ -628,7 +629,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.21 2002-07-01 18:46:22 peter
|
||||
Revision 1.22 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.21 2002/07/01 18:46:22 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -718,5 +722,4 @@ end.
|
||||
Revision 1.8 2002/03/04 19:10:11 peter
|
||||
* removed compiler warnings
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1359,39 +1359,41 @@ begin
|
||||
def_symbol('VALUEFREEMEM');
|
||||
def_symbol('HASCURRENCY');
|
||||
|
||||
{ some stuff for TP compatibility }
|
||||
case target_info.cpu of
|
||||
cpu_i386:
|
||||
begin
|
||||
def_symbol('CPU86');
|
||||
def_symbol('CPU87');
|
||||
def_symbol('CPUI386');
|
||||
end;
|
||||
cpu_m68k:
|
||||
begin
|
||||
def_symbol('CPU68');
|
||||
def_symbol('CPU68K');
|
||||
end;
|
||||
cpu_alpha:
|
||||
begin
|
||||
def_symbol('CPUALPHA');
|
||||
end;
|
||||
cpu_powerpc:
|
||||
begin
|
||||
def_symbol('CPUPOWERPC');
|
||||
end;
|
||||
cpu_sparc:
|
||||
begin
|
||||
def_symbol('CPUSPARC');
|
||||
end;
|
||||
cpu_vm:
|
||||
begin
|
||||
def_symbol('CPUVIS');
|
||||
end;
|
||||
else
|
||||
internalerror(1295969);
|
||||
end;
|
||||
{ using a case is pretty useless here (FK) }
|
||||
{ some stuff for TP compatibility }
|
||||
{$ifdef i386}
|
||||
def_symbol('CPU86');
|
||||
def_symbol('CPU87');
|
||||
{$endif}
|
||||
{$ifdef m68k}
|
||||
def_symbol('CPU68');
|
||||
{$endif}
|
||||
|
||||
{ new processor stuff }
|
||||
{$ifdef i386}
|
||||
def_symbol('CPUI386');
|
||||
{$endif}
|
||||
{$ifdef m68k}
|
||||
def_symbol('CPU68K');
|
||||
{$endif}
|
||||
{$ifdef ALPHA}
|
||||
def_symbol('CPUALPHA');
|
||||
{$endif}
|
||||
{$ifdef powerpc}
|
||||
def_symbol('CPUPOWERPC');
|
||||
{$endif}
|
||||
{$ifdef iA64}
|
||||
def_symbol('CPUIA64');
|
||||
{$endif}
|
||||
{$ifdef x64_64}
|
||||
def_symbol('CPU 86_64');
|
||||
{$endif}
|
||||
{$ifdef sparc}
|
||||
def_symbol('CPUSPARC');
|
||||
{$endif}
|
||||
{$ifdef vis}
|
||||
def_symbol('CPUVIS');
|
||||
{$endif}
|
||||
|
||||
{ get default messagefile }
|
||||
{$ifdef Delphi}
|
||||
@ -1668,7 +1670,10 @@ finalization
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.75 2002-07-01 18:46:24 peter
|
||||
Revision 1.76 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.75 2002/07/01 18:46:24 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -1729,4 +1734,4 @@ end.
|
||||
Revision 1.65 2002/04/04 18:39:45 carl
|
||||
+ added wdosx support (patch from Pavel)
|
||||
|
||||
}
|
||||
}
|
@ -276,6 +276,10 @@ implementation
|
||||
On OS/2 the heap is also intialized by the RTL. We do
|
||||
not output a pointer }
|
||||
case target_info.target of
|
||||
{$ifdef x86_64}
|
||||
target_x86_64_linux:
|
||||
;
|
||||
{$endif x86_64}
|
||||
{$ifdef i386}
|
||||
target_i386_OS2:
|
||||
;
|
||||
@ -1384,7 +1388,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.67 2002-07-01 18:46:25 peter
|
||||
Revision 1.68 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.67 2002/07/01 18:46:25 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -1474,4 +1481,4 @@ end.
|
||||
* implicit result variable generation for assembler routines
|
||||
* removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
|
||||
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ program pp;
|
||||
-----------------------------------------------------------------
|
||||
GDB* support of the GNU Debugger
|
||||
I386 generate a compiler for the Intel i386+
|
||||
x86_64 generate a compiler for the AMD x86-64 architecture
|
||||
M68K generate a compiler for the M68000
|
||||
SPARC generate a compiler for SPARC
|
||||
POWERPC generate a compiler for the PowerPC
|
||||
@ -64,6 +65,12 @@ program pp;
|
||||
{$endif CPUDEFINED}
|
||||
{$define CPUDEFINED}
|
||||
{$endif I386}
|
||||
{$ifdef x86_64}
|
||||
{$ifdef CPUDEFINED}
|
||||
{$fatal ONLY one of the switches for the CPU type must be defined}
|
||||
{$endif CPUDEFINED}
|
||||
{$define CPUDEFINED}
|
||||
{$endif x86_64}
|
||||
{$ifdef M68K}
|
||||
{$ifdef CPUDEFINED}
|
||||
{$fatal ONLY one of the switches for the CPU type must be defined}
|
||||
@ -170,7 +177,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.14 2002-05-22 19:02:16 carl
|
||||
Revision 1.15 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.14 2002/05/22 19:02:16 carl
|
||||
+ generic FPC_HELP_FAIL
|
||||
+ generic FPC_HELP_DESTRUCTOR instated (original from Pierre)
|
||||
+ generic FPC_DISPOSE_CLASS
|
||||
|
@ -66,6 +66,11 @@ implementation
|
||||
,ra386dir
|
||||
{$endif NoRa386Dir}
|
||||
{$endif i386}
|
||||
{$ifdef x86_64}
|
||||
{$ifndef NoRax86Dir}
|
||||
,rax86dir
|
||||
{$endif NoRax86Dir}
|
||||
{$endif i386}
|
||||
{$ifdef m68k}
|
||||
{$ifndef NoRa68kMot}
|
||||
,ra68kmot
|
||||
@ -771,6 +776,24 @@ implementation
|
||||
end;
|
||||
{$endif NoRA386Dir}
|
||||
{$endif}
|
||||
|
||||
{$ifdef x86_64}
|
||||
{$ifndef NoRA386Dir}
|
||||
asmmode_i386_direct:
|
||||
begin
|
||||
if not target_asm.allowdirect then
|
||||
Message(parser_f_direct_assembler_not_allowed);
|
||||
if (aktprocdef.proccalloption=pocall_inline) then
|
||||
Begin
|
||||
Message1(parser_w_not_supported_for_inline,'direct asm');
|
||||
Message(parser_w_inlining_disabled);
|
||||
aktprocdef.proccalloption:=pocall_fpccall;
|
||||
End;
|
||||
asmstat:=tasmnode(rax86dir.assemble);
|
||||
end;
|
||||
{$endif NoRA386Dir}
|
||||
{$endif x86_64}
|
||||
|
||||
{$ifdef m68k}
|
||||
{$ifndef NoRA68kMot}
|
||||
asmmode_m68k_mot:
|
||||
@ -810,6 +833,23 @@ implementation
|
||||
else if pattern='EDI' then
|
||||
include(rg.usedinproc,R_EDI)
|
||||
{$endif i386}
|
||||
{$ifdef x86_64}
|
||||
if pattern='RAX' then
|
||||
include(usedinproc,R_RAX)
|
||||
else if pattern='RBX' then
|
||||
include(usedinproc,R_RBX)
|
||||
else if pattern='RCX' then
|
||||
include(usedinproc,R_RCX)
|
||||
else if pattern='RDX' then
|
||||
include(usedinproc,R_RDX)
|
||||
else if pattern='RSI' then
|
||||
begin
|
||||
include(usedinproc,R_RSI);
|
||||
exclude(asmstat.flags,nf_object_preserved);
|
||||
end
|
||||
else if pattern='RDI' then
|
||||
include(usedinproc,R_RDI)
|
||||
{$endif x86_64}
|
||||
{$ifdef m68k}
|
||||
if pattern='D0' then
|
||||
include(rg.usedinproc,R_D0)
|
||||
@ -1217,7 +1257,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.59 2002-07-01 18:46:25 peter
|
||||
Revision 1.60 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.59 2002/07/01 18:46:25 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -1290,4 +1333,4 @@ end.
|
||||
* implicit result variable generation for assembler routines
|
||||
* removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
|
||||
|
||||
}
|
||||
}
|
@ -23,9 +23,6 @@
|
||||
unit psub;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
{$ifdef powerpc}
|
||||
{$define newcg}
|
||||
{$endif powerpc}
|
||||
|
||||
interface
|
||||
|
||||
@ -47,7 +44,7 @@ implementation
|
||||
globtype,globals,tokens,verbose,comphook,
|
||||
systems,
|
||||
{ aasm }
|
||||
cpubase,cpuinfo,aasmbase,aasmtai,aasmcpu,
|
||||
cpubase,cpuinfo,aasmbase,aasmtai,
|
||||
{ symtable }
|
||||
symconst,symbase,symdef,symsym,symtype,symtable,types,
|
||||
ppu,fmodule,
|
||||
@ -281,8 +278,8 @@ implementation
|
||||
|
||||
{ reset the temporary memory }
|
||||
rg.cleartempgen;
|
||||
|
||||
rg.usedinproc:=[];
|
||||
|
||||
{ save entry info }
|
||||
entrypos:=aktfilepos;
|
||||
entryswitches:=aktlocalswitches;
|
||||
@ -819,7 +816,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.54 2002-07-01 18:46:25 peter
|
||||
Revision 1.55 2002-07-04 20:43:01 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.54 2002/07/01 18:46:25 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -901,4 +901,4 @@ end.
|
||||
Revision 1.42 2002/01/19 15:12:34 peter
|
||||
* check for unresolved forward classes in the interface
|
||||
|
||||
}
|
||||
}
|
@ -114,10 +114,10 @@ begin
|
||||
addtype('Double',s64floattype);
|
||||
addtype('Extended',s80floattype);
|
||||
addtype('Real',s64floattype);
|
||||
{$ifdef i386}
|
||||
{$ifdef x86}
|
||||
adddef('Comp',tfloatdef.create(s64comp));
|
||||
{$endif x86}
|
||||
addtype('Currency',s64currencytype);
|
||||
{$endif}
|
||||
addtype('Pointer',voidpointertype);
|
||||
addtype('FarPointer',voidfarpointertype);
|
||||
addtype('ShortString',cshortstringtype);
|
||||
@ -248,12 +248,12 @@ begin
|
||||
openshortstringtype.setdef(tstringdef.createshort(0));
|
||||
openchararraytype.setdef(tarraydef.create(0,-1,s32bittype));
|
||||
tarraydef(openchararraytype.def).elementtype:=cchartype;
|
||||
{$ifdef i386}
|
||||
{$ifdef x86}
|
||||
s32floattype.setdef(tfloatdef.create(s32real));
|
||||
s64floattype.setdef(tfloatdef.create(s64real));
|
||||
s80floattype.setdef(tfloatdef.create(s80real));
|
||||
{$endif x86}
|
||||
s64currencytype.setdef(tfloatdef.create(s64currency));
|
||||
{$endif}
|
||||
{$ifdef m68k}
|
||||
s32floattype.setdef(tfloatdef.create(s32real));
|
||||
if (cs_fp_emulation in aktmoduleswitches) then
|
||||
@ -280,7 +280,10 @@ end;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.27 2002-07-01 16:23:54 peter
|
||||
Revision 1.28 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.27 2002/07/01 16:23:54 peter
|
||||
* cg64 patch
|
||||
* basics for currency
|
||||
* asnode updates for class and interface (not finished)
|
||||
@ -326,4 +329,4 @@ end.
|
||||
instead of direct comparisons of low/high values of orddefs because
|
||||
qword is a special case
|
||||
|
||||
}
|
||||
}
|
@ -46,7 +46,11 @@ interface
|
||||
cpu_alpha, { 3 }
|
||||
cpu_powerpc, { 4 }
|
||||
cpu_sparc, { 5 }
|
||||
cpu_vm { 6 }
|
||||
cpu_vm, { 6 }
|
||||
cpu_iA64, { 7 }
|
||||
cpu_x86_64, { 8 }
|
||||
cpu_mips, { 9 }
|
||||
cpu_arm { 10 }
|
||||
);
|
||||
|
||||
tprocessors = (no_processor
|
||||
@ -100,7 +104,8 @@ interface
|
||||
target_i386_qnx, { 20 }
|
||||
target_i386_wdosx, { 21 }
|
||||
target_sparc_sunos, { 22 }
|
||||
target_sparc_linux { 23 }
|
||||
target_sparc_linux, { 23 }
|
||||
target_x86_64_linux { 24 }
|
||||
);
|
||||
|
||||
tasm = (as_none
|
||||
@ -120,11 +125,12 @@ interface
|
||||
ld_i386_GO32V1,ld_i386_GO32V2,ld_i386_linux,
|
||||
ld_i386_OS2,ld_i386_Win32,ld_i386_freebsd,
|
||||
ld_i386_Netware,ld_i386_sunos,ld_i386_beos,
|
||||
ld_i386_coff,ld_i386_pecoff,
|
||||
ld_i386_coff,ld_i386_pecoff,ld_i386_Wdosx,
|
||||
ld_m68k_Amiga,ld_m68k_Atari,ld_m68k_Mac,
|
||||
ld_m68k_linux,ld_m68k_PalmOS,ld_m68k_freebsd,
|
||||
ld_alpha_linux,
|
||||
ld_powerpc_linux,ld_powerpc_macos,ld_i386_Wdosx,
|
||||
ld_x86_64_linux,
|
||||
ld_powerpc_linux,ld_powerpc_macos,
|
||||
ld_SPARC_SunOs,ld_SPARC_linux
|
||||
);
|
||||
|
||||
@ -627,6 +633,9 @@ begin
|
||||
{$endif os2}
|
||||
{$endif go32v2}
|
||||
{$endif cpu86}
|
||||
{$ifdef cpu86_64}
|
||||
set_source(target_x86_64_linux);
|
||||
{$endif cpu86_64}
|
||||
{$ifdef cpu68}
|
||||
{$ifdef AMIGA}
|
||||
set_source(target_m68k_Amiga);
|
||||
@ -654,6 +663,13 @@ begin
|
||||
default_target(target_i386_linux);
|
||||
{$endif cpu86}
|
||||
{$endif i386}
|
||||
{$ifdef x86_64}
|
||||
{$ifdef cpu86_64}
|
||||
default_target(source_info.target);
|
||||
{$else cpu86_64}
|
||||
default_target(target_x86_64_linux);
|
||||
{$endif cpu86_64}
|
||||
{$endif x86_64}
|
||||
{$ifdef m68k}
|
||||
{$ifdef cpu68}
|
||||
default_target(source_info.target);
|
||||
@ -687,7 +703,10 @@ finalization
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.46 2002-07-01 18:46:29 peter
|
||||
Revision 1.47 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.46 2002/07/01 18:46:29 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -722,12 +741,4 @@ end.
|
||||
|
||||
Revision 1.38 2002/04/14 16:56:30 carl
|
||||
- remove duplicate comment
|
||||
|
||||
Revision 1.37 2002/04/07 10:20:15 carl
|
||||
+ added SPARC targets
|
||||
+ added VM target
|
||||
|
||||
Revision 1.36 2002/04/04 19:18:06 carl
|
||||
- removed cmnts
|
||||
|
||||
}
|
||||
}
|
332
compiler/tainst.pas
Normal file
332
compiler/tainst.pas
Normal file
@ -0,0 +1,332 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2002 by Michael Van Canneyt
|
||||
|
||||
Contains a generic assembler instruction object;
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
****************************************************************************
|
||||
}
|
||||
Unit tainst;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
Uses
|
||||
cpuinfo,cpubase,aasm,cclasses;
|
||||
|
||||
Type
|
||||
tairegalloc = class(tai)
|
||||
allocation : boolean;
|
||||
reg : tregister;
|
||||
constructor alloc(r : tregister);
|
||||
constructor dealloc(r : tregister);
|
||||
end;
|
||||
|
||||
taicpu_abstract = class(tai)
|
||||
condition : TAsmCond;
|
||||
ops : longint;
|
||||
oper : array[0..max_operands-1] of toper;
|
||||
opcode : tasmop;
|
||||
{$ifdef x86}
|
||||
segprefix : tregister;
|
||||
{$endif x86}
|
||||
is_jmp : boolean; { is this instruction a jump? (needed for optimizer) }
|
||||
Constructor Create(op : tasmop);
|
||||
Destructor Destroy;override;
|
||||
function getcopy:tlinkedlistitem;override;
|
||||
procedure loadconst(opidx:longint;l:aword);
|
||||
procedure loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
|
||||
procedure loadref(opidx:longint;const r:treference);
|
||||
procedure loadreg(opidx:longint;r:tregister);
|
||||
procedure loadoper(opidx:longint;o:toper);
|
||||
procedure SetCondition(const c:TAsmCond);
|
||||
end;
|
||||
|
||||
{ alignment for operator }
|
||||
tai_align_abstract = class(tai)
|
||||
buf : array[0..63] of char; { buf used for fill }
|
||||
aligntype : byte; { 1 = no align, 2 = word align, 4 = dword align }
|
||||
fillsize : byte; { real size to fill }
|
||||
fillop : byte; { value to fill with - optional }
|
||||
use_op : boolean;
|
||||
constructor Create(b:byte);
|
||||
constructor Create_op(b: byte; _op: byte);
|
||||
function getfillbuf:pchar;virtual;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
verbose;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TaiRegAlloc
|
||||
*****************************************************************************}
|
||||
|
||||
constructor tairegalloc.alloc(r : tregister);
|
||||
begin
|
||||
inherited create;
|
||||
typ:=ait_regalloc;
|
||||
allocation:=true;
|
||||
reg:=r;
|
||||
end;
|
||||
|
||||
|
||||
constructor tairegalloc.dealloc(r : tregister);
|
||||
begin
|
||||
inherited create;
|
||||
typ:=ait_regalloc;
|
||||
allocation:=false;
|
||||
reg:=r;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TaiInstruction
|
||||
*****************************************************************************}
|
||||
|
||||
constructor taicpu_abstract.Create(op : tasmop);
|
||||
|
||||
begin
|
||||
inherited create;
|
||||
typ:=ait_instruction;
|
||||
is_jmp:=false;
|
||||
opcode:=op;
|
||||
ops:=0;
|
||||
fillchar(condition,sizeof(condition),0);
|
||||
fillchar(oper,sizeof(oper),0);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
destructor taicpu_abstract.Destroy;
|
||||
|
||||
var
|
||||
i : longint;
|
||||
begin
|
||||
for i:=0 to ops-1 do
|
||||
case oper[i].typ of
|
||||
top_ref:
|
||||
dispose(oper[i].ref);
|
||||
top_symbol:
|
||||
dec(tasmsymbol(oper[i].sym).refs);
|
||||
end;
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
{ ---------------------------------------------------------------------
|
||||
Loading of operands.
|
||||
---------------------------------------------------------------------}
|
||||
|
||||
|
||||
|
||||
procedure taicpu_abstract.loadconst(opidx:longint;l:aword);
|
||||
begin
|
||||
if opidx>=ops then
|
||||
ops:=opidx+1;
|
||||
with oper[opidx] do
|
||||
begin
|
||||
if typ=top_ref then
|
||||
dispose(ref);
|
||||
val:=l;
|
||||
typ:=top_const;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure taicpu_abstract.loadsymbol(opidx:longint;s:tasmsymbol;sofs:longint);
|
||||
begin
|
||||
if not assigned(s) then
|
||||
internalerror(200204251);
|
||||
if opidx>=ops then
|
||||
ops:=opidx+1;
|
||||
with oper[opidx] do
|
||||
begin
|
||||
if typ=top_ref then
|
||||
dispose(ref);
|
||||
sym:=s;
|
||||
symofs:=sofs;
|
||||
typ:=top_symbol;
|
||||
end;
|
||||
inc(s.refs);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure taicpu_abstract.loadref(opidx:longint;const r:treference);
|
||||
begin
|
||||
if opidx>=ops then
|
||||
ops:=opidx+1;
|
||||
with oper[opidx] do
|
||||
begin
|
||||
if typ<>top_ref then
|
||||
new(ref);
|
||||
ref^:=r;
|
||||
{$ifdef x86}
|
||||
{ We allow this exception for i386, since overloading this would be
|
||||
too much of a a speed penalty}
|
||||
if not(ref^.segment in [R_DS,R_NO]) then
|
||||
segprefix:=ref^.segment;
|
||||
{$endif x86}
|
||||
typ:=top_ref;
|
||||
{ mark symbol as used }
|
||||
if assigned(ref^.symbol) then
|
||||
inc(ref^.symbol.refs);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure taicpu_abstract.loadreg(opidx:longint;r:tregister);
|
||||
begin
|
||||
if opidx>=ops then
|
||||
ops:=opidx+1;
|
||||
with oper[opidx] do
|
||||
begin
|
||||
if typ=top_ref then
|
||||
dispose(ref);
|
||||
reg:=r;
|
||||
typ:=top_reg;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure taicpu_abstract.loadoper(opidx:longint;o:toper);
|
||||
begin
|
||||
if opidx>=ops then
|
||||
ops:=opidx+1;
|
||||
if oper[opidx].typ=top_ref then
|
||||
dispose(oper[opidx].ref);
|
||||
oper[opidx]:=o;
|
||||
{ copy also the reference }
|
||||
if oper[opidx].typ=top_ref then
|
||||
begin
|
||||
new(oper[opidx].ref);
|
||||
oper[opidx].ref^:=o.ref^;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ ---------------------------------------------------------------------
|
||||
Miscellaneous methods.
|
||||
---------------------------------------------------------------------}
|
||||
|
||||
procedure taicpu_abstract.SetCondition(const c:TAsmCond);
|
||||
begin
|
||||
condition:=c;
|
||||
end;
|
||||
|
||||
|
||||
Function taicpu_abstract.getcopy:tlinkedlistitem;
|
||||
var
|
||||
i : longint;
|
||||
p : tlinkedlistitem;
|
||||
begin
|
||||
p:=inherited getcopy;
|
||||
{ make a copy of the references }
|
||||
for i:=1 to ops do
|
||||
if (taicpu_abstract(p).oper[i-1].typ=top_ref) then
|
||||
begin
|
||||
new(taicpu_abstract(p).oper[i-1].ref);
|
||||
taicpu_abstract(p).oper[i-1].ref^:=oper[i-1].ref^;
|
||||
end;
|
||||
getcopy:=p;
|
||||
end;
|
||||
|
||||
{****************************************************************************
|
||||
tai_align_abstract
|
||||
****************************************************************************}
|
||||
|
||||
constructor tai_align_abstract.Create(b: byte);
|
||||
begin
|
||||
inherited Create;
|
||||
typ:=ait_align;
|
||||
if b in [1,2,4,8,16,32] then
|
||||
aligntype := b
|
||||
else
|
||||
aligntype := 1;
|
||||
fillsize:=0;
|
||||
fillop:=0;
|
||||
use_op:=false;
|
||||
end;
|
||||
|
||||
|
||||
constructor tai_align_abstract.Create_op(b: byte; _op: byte);
|
||||
begin
|
||||
inherited Create;
|
||||
typ:=ait_align;
|
||||
if b in [1,2,4,8,16,32] then
|
||||
aligntype := b
|
||||
else
|
||||
aligntype := 1;
|
||||
fillsize:=0;
|
||||
fillop:=_op;
|
||||
use_op:=true;
|
||||
fillchar(buf,sizeof(buf),_op)
|
||||
end;
|
||||
|
||||
|
||||
function tai_align_abstract.getfillbuf:pchar;
|
||||
begin
|
||||
getfillbuf:=@buf;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.11 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.10 2002/07/01 18:46:29 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
Revision 1.9 2002/05/18 13:34:21 peter
|
||||
* readded missing revisions
|
||||
|
||||
Revision 1.7 2002/05/14 19:34:52 peter
|
||||
* removed old logs and updated copyright year
|
||||
|
||||
Revision 1.6 2002/05/14 17:28:09 peter
|
||||
* synchronized cpubase between powerpc and i386
|
||||
* moved more tables from cpubase to cpuasm
|
||||
* tai_align_abstract moved to tainst, cpuasm must define
|
||||
the tai_align class now, which may be empty
|
||||
|
||||
Revision 1.5 2002/04/25 20:16:39 peter
|
||||
* moved more routines from cga/n386util
|
||||
|
||||
Revision 1.4 2002/04/02 17:11:32 peter
|
||||
* tlocation,treference update
|
||||
* LOC_CONSTANT added for better constant handling
|
||||
* secondadd splitted in multiple routines
|
||||
* location_force_reg added for loading a location to a register
|
||||
of a specified size
|
||||
* secondassignment parses now first the right and then the left node
|
||||
(this is compatible with Kylix). This saves a lot of push/pop especially
|
||||
with string operations
|
||||
* adapted some routines to use the new cg methods
|
||||
|
||||
}
|
@ -748,6 +748,75 @@ end;
|
||||
use_function_relative_addresses : true
|
||||
);
|
||||
{$endif alpha}
|
||||
{$ifdef x86_64}
|
||||
const
|
||||
target_x86_64_linux_info : ttargetinfo =
|
||||
(
|
||||
target : target_i386_LINUX;
|
||||
name : 'Linux for x86-64';
|
||||
shortname : 'Linux64';
|
||||
flags : [];
|
||||
cpu : x86_64;
|
||||
unit_env : 'LINUXUNITS';
|
||||
extradefines : 'UNIX';
|
||||
sourceext : '.pp';
|
||||
pasext : '.pas';
|
||||
exeext : '';
|
||||
defext : '.def';
|
||||
scriptext : '.sh';
|
||||
smartext : '.sl';
|
||||
unitext : '.ppu';
|
||||
unitlibext : '.ppl';
|
||||
asmext : '.s';
|
||||
objext : '.o';
|
||||
resext : '.res';
|
||||
resobjext : '.or';
|
||||
sharedlibext : '.so';
|
||||
staticlibext : '.a';
|
||||
staticlibprefix : 'libp';
|
||||
sharedlibprefix : 'lib';
|
||||
sharedClibext : '.so';
|
||||
staticClibext : '.a';
|
||||
staticClibprefix : 'lib';
|
||||
sharedClibprefix : 'lib';
|
||||
Cprefix : '';
|
||||
newline : #10;
|
||||
dirsep : '/';
|
||||
files_case_relevent : true;
|
||||
assem : as_i386_elf32;
|
||||
assemextern : as_i386_as;
|
||||
link : ld_i386_linux;
|
||||
linkextern : ld_i386_linux;
|
||||
ar : ar_gnu_ar;
|
||||
res : res_none;
|
||||
script : script_unix;
|
||||
endian : endian_little;
|
||||
alignment :
|
||||
(
|
||||
procalign : 4;
|
||||
loopalign : 4;
|
||||
jumpalign : 0;
|
||||
constalignmin : 0;
|
||||
constalignmax : 1;
|
||||
varalignmin : 0;
|
||||
varalignmax : 1;
|
||||
localalignmin : 0;
|
||||
localalignmax : 1;
|
||||
paraalign : 4;
|
||||
recordalignmin : 0;
|
||||
recordalignmax : 2;
|
||||
maxCrecordalign : 4
|
||||
);
|
||||
size_of_pointer : 8;
|
||||
size_of_longint : 4;
|
||||
heapsize : 256*1024;
|
||||
maxheapsize : 65536*1024;
|
||||
stacksize : 16*1024;
|
||||
DllScanSupported:false;
|
||||
use_bound_instruction : false;
|
||||
use_function_relative_addresses : true
|
||||
);
|
||||
{$endif x86_64}
|
||||
{$IFDEF SPARC}
|
||||
CONST
|
||||
target_SPARC_linux_info : ttargetinfo =
|
||||
@ -815,6 +884,7 @@ end;
|
||||
);
|
||||
{$ENDIF SPARC}
|
||||
|
||||
|
||||
initialization
|
||||
{$ifdef i386}
|
||||
RegisterLinker(ld_i386_linux,TLinkerLinux);
|
||||
@ -840,6 +910,12 @@ initialization
|
||||
RegisterExport(target_alpha_linux,texportliblinux);
|
||||
RegisterTarget(target_alpha_linux_info);
|
||||
{$endif alpha}
|
||||
{$ifdef x86_64}
|
||||
RegisterLinker(ld_x86_64_linux,TLinkerLinux);
|
||||
RegisterImport(target_x86_64_linux,timportliblinux);
|
||||
RegisterExport(target_x86_64_linux,texportliblinux);
|
||||
RegisterTarget(target_x86_64_linux_info);
|
||||
{$endif x86_64}
|
||||
{$IFDEF SPARC}
|
||||
RegisterLinker(ld_SPARC_linux,TLinkerLinux);
|
||||
RegisterImport(target_SPARC_linux,timportliblinux);
|
||||
@ -847,9 +923,13 @@ initialization
|
||||
RegisterTarget(target_SPARC_linux_info);
|
||||
{$ENDIF SPARC}
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.27 2002-07-01 18:46:35 peter
|
||||
Revision 1.28 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.27 2002/07/01 18:46:35 peter
|
||||
* internal linker
|
||||
* reorganized aasm layer
|
||||
|
||||
@ -897,5 +977,4 @@ end.
|
||||
|
||||
Revision 1.15 2002/01/09 07:38:37 michael
|
||||
+ Patch from Peter for library imports
|
||||
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ interface
|
||||
{$ifdef i386}
|
||||
target_cpu_string = 'i386';
|
||||
{$endif}
|
||||
{$ifdef x86_64}
|
||||
target_cpu_string = 'x86_64';
|
||||
{$endif}
|
||||
{$ifdef sparc}
|
||||
target_cpu_string = 'sparc';
|
||||
{$endif}
|
||||
@ -66,6 +69,13 @@ interface
|
||||
{$ifdef ia64}
|
||||
target_cpu_string = 'ia64';
|
||||
{$endif}
|
||||
{$ifdef mips}
|
||||
target_cpu_string = 'mips';
|
||||
{$endif}
|
||||
{$ifdef arm}
|
||||
target_cpu_string = 'arm';
|
||||
{$endif}
|
||||
|
||||
|
||||
{ source cpu string }
|
||||
{$ifdef cpu86}
|
||||
@ -77,6 +87,9 @@ interface
|
||||
{$ifdef cpuia64}
|
||||
target_cpu_string = 'ia64';
|
||||
{$endif}
|
||||
{$ifdef cpu86_64}
|
||||
source_cpu_string = 'x86_64';
|
||||
{$endif}
|
||||
|
||||
function version_string:string;
|
||||
function full_version_string:string;
|
||||
@ -104,7 +117,10 @@ end;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.12 2002-05-18 13:34:21 peter
|
||||
Revision 1.13 2002-07-04 20:43:02 florian
|
||||
* first x86-64 patches
|
||||
|
||||
Revision 1.12 2002/05/18 13:34:21 peter
|
||||
* readded missing revisions
|
||||
|
||||
Revision 1.11 2002/05/16 19:46:47 carl
|
||||
@ -118,5 +134,4 @@ end.
|
||||
|
||||
Revision 1.8 2002/03/01 12:47:21 pierre
|
||||
* used shl 7 for release number
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user