* first x86-64 patches

This commit is contained in:
florian 2002-07-04 20:43:00 +00:00
parent 95c6c8f430
commit 479a745096
16 changed files with 2495 additions and 85 deletions

1103
compiler/aasm.pas Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
View 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
}

View File

@ -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
}

View File

@ -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
}
}