mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 05:49:12 +02:00
+ Implemented the actual register allocator
+ Scratch registers unavailable when new register allocator used + maybe_save/maybe_restore unavailable when new register allocator used
This commit is contained in:
parent
4aec360876
commit
25059e21b6
@ -435,6 +435,7 @@ interface
|
|||||||
procedure loadref(opidx:longint;const r:treference);
|
procedure loadref(opidx:longint;const r:treference);
|
||||||
procedure loadreg(opidx:longint;r:tregister);
|
procedure loadreg(opidx:longint;r:tregister);
|
||||||
procedure loadoper(opidx:longint;o:toper);
|
procedure loadoper(opidx:longint;o:toper);
|
||||||
|
function is_nop:boolean;virtual;abstract;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ alignment for operator }
|
{ alignment for operator }
|
||||||
@ -450,9 +451,12 @@ interface
|
|||||||
function calculatefillbuf(var buf : tfillbuffer):pchar;virtual;
|
function calculatefillbuf(var buf : tfillbuffer):pchar;virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Ttranstable=array[Tsuperregister] of Tsuperregister;
|
||||||
|
|
||||||
taasmoutput = class(tlinkedlist)
|
taasmoutput = class(tlinkedlist)
|
||||||
function getlasttaifilepos : pfileposinfo;
|
function getlasttaifilepos : pfileposinfo;
|
||||||
procedure convert_registers;
|
procedure convert_registers;
|
||||||
|
procedure translate_registers(const table:Ttranstable);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1767,10 +1771,56 @@ uses
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure Taasmoutput.translate_registers(const table:Ttranstable);
|
||||||
|
|
||||||
|
var p,q:Tai;
|
||||||
|
i:shortint;
|
||||||
|
r:Preference;
|
||||||
|
|
||||||
|
begin
|
||||||
|
p:=Tai(first);
|
||||||
|
while assigned(p) do
|
||||||
|
begin
|
||||||
|
case p.typ of
|
||||||
|
ait_regalloc:
|
||||||
|
Tai_regalloc(p).reg.number:=(Tai_regalloc(p).reg.number and $ff) or
|
||||||
|
(table[Tai_regalloc(p).reg.number shr 8] shl 8);
|
||||||
|
ait_instruction:
|
||||||
|
begin
|
||||||
|
for i:=0 to Taicpu_abstract(p).ops-1 do
|
||||||
|
if Taicpu_abstract(p).oper[i].typ=Top_reg then
|
||||||
|
Taicpu_abstract(p).oper[i].reg.number:=(Taicpu_abstract(p).oper[i].reg.number and $ff) or
|
||||||
|
(table[Taicpu_abstract(p).oper[i].reg.number shr 8] shl 8)
|
||||||
|
else if Taicpu_abstract(p).oper[i].typ=Top_ref then
|
||||||
|
begin
|
||||||
|
r:=Taicpu_abstract(p).oper[i].ref;
|
||||||
|
r^.base.number:=(r^.base.number and $ff) or
|
||||||
|
(table[r^.base.number shr 8] shl 8);
|
||||||
|
r^.index.number:=(r^.index.number and $ff) or
|
||||||
|
(table[r^.index.number shr 8] shl 8);
|
||||||
|
end;
|
||||||
|
if Taicpu_abstract(p).is_nop then
|
||||||
|
begin
|
||||||
|
q:=p;
|
||||||
|
p:=Tai(p.next);
|
||||||
|
remove(q);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
p:=Tai(p.next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.21 2003-02-19 22:00:14 daniel
|
Revision 1.22 2003-04-22 10:09:34 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.21 2003/02/19 22:00:14 daniel
|
||||||
* Code generator converted to new register notation
|
* Code generator converted to new register notation
|
||||||
- Horribily outdated todo.txt removed
|
- Horribily outdated todo.txt removed
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ unit cg64f32;
|
|||||||
globtype,globals,systems,
|
globtype,globals,systems,
|
||||||
cgbase,
|
cgbase,
|
||||||
verbose,
|
verbose,
|
||||||
symbase,symconst,symdef,defutil;
|
symbase,symconst,symdef,defutil,rgobj;
|
||||||
|
|
||||||
|
|
||||||
function joinreg64(reglo,reghi : tregister) : tregister64;
|
function joinreg64(reglo,reghi : tregister) : tregister64;
|
||||||
@ -170,7 +170,11 @@ unit cg64f32;
|
|||||||
internalerror(200302035);
|
internalerror(200302035);
|
||||||
if (tmpref.base.number=reg.reglo.number) then
|
if (tmpref.base.number=reg.reglo.number) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else}
|
||||||
tmpreg := cg.get_scratch_reg_address(list);
|
tmpreg := cg.get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
got_scratch:=true;
|
got_scratch:=true;
|
||||||
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
|
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.base,tmpreg);
|
||||||
tmpref.base:=tmpreg;
|
tmpref.base:=tmpreg;
|
||||||
@ -181,7 +185,11 @@ unit cg64f32;
|
|||||||
{ implementation FK }
|
{ implementation FK }
|
||||||
if (tmpref.index.number=reg.reglo.number) then
|
if (tmpref.index.number=reg.reglo.number) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(list);
|
tmpreg:=cg.get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
got_scratch:=true;
|
got_scratch:=true;
|
||||||
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
|
cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpref.index,tmpreg);
|
||||||
tmpref.index:=tmpreg;
|
tmpref.index:=tmpreg;
|
||||||
@ -189,8 +197,13 @@ unit cg64f32;
|
|||||||
cg.a_load_ref_reg(list,OS_32,tmpref,reg.reglo);
|
cg.a_load_ref_reg(list,OS_32,tmpref,reg.reglo);
|
||||||
inc(tmpref.offset,4);
|
inc(tmpref.offset,4);
|
||||||
cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
|
cg.a_load_ref_reg(list,OS_32,tmpref,reg.reghi);
|
||||||
|
{$ifdef newra}
|
||||||
|
if got_scratch then
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
if got_scratch then
|
if got_scratch then
|
||||||
cg.free_scratch_reg(list,tmpreg);
|
cg.free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -399,12 +412,22 @@ unit cg64f32;
|
|||||||
var
|
var
|
||||||
tempreg: tregister64;
|
tempreg: tregister64;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tempreg.reghi:=rg.getregisterint(list,OS_INT);
|
||||||
|
tempreg.reglo:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
a_load64_ref_reg(list,ref,tempreg);
|
a_load64_ref_reg(list,ref,tempreg);
|
||||||
a_op64_reg_reg(list,op,tempreg,reg);
|
a_op64_reg_reg(list,op,tempreg,reg);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tempreg.reglo);
|
||||||
|
rg.ungetregisterint(list,tempreg.reghi);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tempreg.reglo);
|
cg.free_scratch_reg(list,tempreg.reglo);
|
||||||
cg.free_scratch_reg(list,tempreg.reghi);
|
cg.free_scratch_reg(list,tempreg.reghi);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -412,13 +435,23 @@ unit cg64f32;
|
|||||||
var
|
var
|
||||||
tempreg: tregister64;
|
tempreg: tregister64;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tempreg.reghi:=rg.getregisterint(list,OS_INT);
|
||||||
|
tempreg.reglo:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
a_load64_ref_reg(list,ref,tempreg);
|
a_load64_ref_reg(list,ref,tempreg);
|
||||||
a_op64_reg_reg(list,op,reg,tempreg);
|
a_op64_reg_reg(list,op,reg,tempreg);
|
||||||
a_load64_reg_ref(list,tempreg,ref);
|
a_load64_reg_ref(list,tempreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tempreg.reglo);
|
||||||
|
rg.ungetregisterint(list,tempreg.reghi);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tempreg.reglo);
|
cg.free_scratch_reg(list,tempreg.reglo);
|
||||||
cg.free_scratch_reg(list,tempreg.reghi);
|
cg.free_scratch_reg(list,tempreg.reghi);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -426,13 +459,23 @@ unit cg64f32;
|
|||||||
var
|
var
|
||||||
tempreg: tregister64;
|
tempreg: tregister64;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tempreg.reghi:=rg.getregisterint(list,OS_INT);
|
||||||
|
tempreg.reglo:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reghi := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
tempreg.reglo := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
a_load64_ref_reg(list,ref,tempreg);
|
a_load64_ref_reg(list,ref,tempreg);
|
||||||
a_op64_const_reg(list,op,value,tempreg);
|
a_op64_const_reg(list,op,value,tempreg);
|
||||||
a_load64_reg_ref(list,tempreg,ref);
|
a_load64_reg_ref(list,tempreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tempreg.reglo);
|
||||||
|
rg.ungetregisterint(list,tempreg.reghi);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tempreg.reglo);
|
cg.free_scratch_reg(list,tempreg.reglo);
|
||||||
cg.free_scratch_reg(list,tempreg.reghi);
|
cg.free_scratch_reg(list,tempreg.reghi);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
|
procedure tcg64f32.a_param64_reg(list : taasmoutput;reg : tregister64;const locpara : tparalocation);
|
||||||
@ -539,7 +582,11 @@ unit cg64f32;
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
got_scratch := true;
|
got_scratch := true;
|
||||||
a_load64high_ref_reg(list,p.location.reference,hreg);
|
a_load64high_ref_reg(list,p.location.reference,hreg);
|
||||||
end;
|
end;
|
||||||
@ -555,8 +602,13 @@ unit cg64f32;
|
|||||||
cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
|
cg.a_cmp_const_reg_label(list,OS_32,OC_EQ,aword(-1),hreg,neglabel);
|
||||||
end;
|
end;
|
||||||
{ !!! freeing of register should happen directly after compare! (JM) }
|
{ !!! freeing of register should happen directly after compare! (JM) }
|
||||||
|
{$ifdef newra}
|
||||||
|
if got_scratch then
|
||||||
|
rg.ungetregisterint(list,hreg);
|
||||||
|
{$else}
|
||||||
if got_scratch then
|
if got_scratch then
|
||||||
cg.free_scratch_reg(list,hreg);
|
cg.free_scratch_reg(list,hreg);
|
||||||
|
{$endif}
|
||||||
{ For all other values we have a range check error }
|
{ For all other values we have a range check error }
|
||||||
cg.a_call_name(list,'FPC_RANGEERROR');
|
cg.a_call_name(list,'FPC_RANGEERROR');
|
||||||
|
|
||||||
@ -587,7 +639,11 @@ unit cg64f32;
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
got_scratch := true;
|
got_scratch := true;
|
||||||
a_load64low_ref_reg(list,p.location.reference,hreg);
|
a_load64low_ref_reg(list,p.location.reference,hreg);
|
||||||
end;
|
end;
|
||||||
@ -595,8 +651,13 @@ unit cg64f32;
|
|||||||
objectlibrary.getlabel(neglabel);
|
objectlibrary.getlabel(neglabel);
|
||||||
cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
|
cg.a_cmp_const_reg_label(list,OS_32,OC_LT,0,hreg,neglabel);
|
||||||
{ !!! freeing of register should happen directly after compare! (JM) }
|
{ !!! freeing of register should happen directly after compare! (JM) }
|
||||||
|
{$ifdef newra}
|
||||||
|
if got_scratch then
|
||||||
|
rg.ungetregisterint(list,hreg);
|
||||||
|
{$else}
|
||||||
if got_scratch then
|
if got_scratch then
|
||||||
cg.free_scratch_reg(list,hreg);
|
cg.free_scratch_reg(list,hreg);
|
||||||
|
{$endif}
|
||||||
|
|
||||||
cg.a_call_name(list,'FPC_RANGEERROR');
|
cg.a_call_name(list,'FPC_RANGEERROR');
|
||||||
|
|
||||||
@ -641,7 +702,11 @@ unit cg64f32;
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
hreg := cg.get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
got_scratch := true;
|
got_scratch := true;
|
||||||
|
|
||||||
opsize := def_cgsize(p.resulttype.def);
|
opsize := def_cgsize(p.resulttype.def);
|
||||||
@ -654,8 +719,13 @@ unit cg64f32;
|
|||||||
cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
|
cg.a_cmp_const_reg_label(list,opsize,OC_GTE,0,hreg,poslabel);
|
||||||
|
|
||||||
{ !!! freeing of register should happen directly after compare! (JM) }
|
{ !!! freeing of register should happen directly after compare! (JM) }
|
||||||
|
{$ifdef newra}
|
||||||
|
if got_scratch then
|
||||||
|
rg.ungetregisterint(list,hreg);
|
||||||
|
{$else}
|
||||||
if got_scratch then
|
if got_scratch then
|
||||||
cg.free_scratch_reg(list,hreg);
|
cg.free_scratch_reg(list,hreg);
|
||||||
|
{$endif}
|
||||||
cg.a_call_name(list,'FPC_RANGEERROR');
|
cg.a_call_name(list,'FPC_RANGEERROR');
|
||||||
cg.a_label(list,poslabel);
|
cg.a_label(list,poslabel);
|
||||||
end;
|
end;
|
||||||
@ -766,7 +836,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.38 2003-04-07 08:52:58 jonas
|
Revision 1.39 2003-04-22 10:09:34 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.38 2003/04/07 08:52:58 jonas
|
||||||
* fixed compiling error
|
* fixed compiling error
|
||||||
|
|
||||||
Revision 1.37 2003/04/07 08:45:09 jonas
|
Revision 1.37 2003/04/07 08:45:09 jonas
|
||||||
|
@ -59,9 +59,11 @@ unit cgobj;
|
|||||||
sould be @link(tcg64f32) and not @var(tcg).
|
sould be @link(tcg64f32) and not @var(tcg).
|
||||||
}
|
}
|
||||||
tcg = class
|
tcg = class
|
||||||
|
{$ifndef newra}
|
||||||
scratch_register_array_pointer : aword;
|
scratch_register_array_pointer : aword;
|
||||||
{# List of currently unused scratch registers }
|
{# List of currently unused scratch registers }
|
||||||
unusedscratchregisters:Tsupregset;
|
unusedscratchregisters:Tsupregset;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
alignment : talignment;
|
alignment : talignment;
|
||||||
{************************************************}
|
{************************************************}
|
||||||
@ -79,6 +81,7 @@ unit cgobj;
|
|||||||
{# Deallocates register r by inserting a pa_regdealloc record}
|
{# Deallocates register r by inserting a pa_regdealloc record}
|
||||||
procedure a_reg_dealloc(list : taasmoutput;r : tregister);
|
procedure a_reg_dealloc(list : taasmoutput;r : tregister);
|
||||||
|
|
||||||
|
{$ifndef newra}
|
||||||
{# @abstract(Returns an int register for use as scratch register)
|
{# @abstract(Returns an int register for use as scratch register)
|
||||||
This routine returns a register which can be used by
|
This routine returns a register which can be used by
|
||||||
the code generator as a general purpose scratch register.
|
the code generator as a general purpose scratch register.
|
||||||
@ -102,6 +105,7 @@ unit cgobj;
|
|||||||
was previously allocated using @link(get_scratch_reg).
|
was previously allocated using @link(get_scratch_reg).
|
||||||
}
|
}
|
||||||
procedure free_scratch_reg(list : taasmoutput;r : tregister);
|
procedure free_scratch_reg(list : taasmoutput;r : tregister);
|
||||||
|
{$endif newra}
|
||||||
{# Pass a parameter, which is located in a register, to a routine.
|
{# Pass a parameter, which is located in a register, to a routine.
|
||||||
|
|
||||||
This routine should push/send the parameter to the routine, as
|
This routine should push/send the parameter to the routine, as
|
||||||
@ -503,7 +507,9 @@ unit cgobj;
|
|||||||
rgobj,cutils;
|
rgobj,cutils;
|
||||||
|
|
||||||
const
|
const
|
||||||
|
{$ifndef newra}
|
||||||
max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
|
max_scratch_regs = high(scratch_regs) - low(scratch_regs) + 1;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
{ Please leave this here, this module should NOT use
|
{ Please leave this here, this module should NOT use
|
||||||
exprasmlist, the lists are always passed as arguments.
|
exprasmlist, the lists are always passed as arguments.
|
||||||
@ -520,9 +526,11 @@ unit cgobj;
|
|||||||
i : longint;
|
i : longint;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifndef newra}
|
||||||
scratch_register_array_pointer:=1;
|
scratch_register_array_pointer:=1;
|
||||||
for i:=low(scratch_regs) to high(scratch_regs) do
|
for i:=low(scratch_regs) to high(scratch_regs) do
|
||||||
include(unusedscratchregisters,scratch_regs[i]);
|
include(unusedscratchregisters,scratch_regs[i]);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
|
procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
|
||||||
@ -543,6 +551,7 @@ unit cgobj;
|
|||||||
list.concat(tai_label.create(l));
|
list.concat(tai_label.create(l));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifndef newra}
|
||||||
function tcg.get_scratch_reg_int(list:taasmoutput;size:Tcgsize):tregister;
|
function tcg.get_scratch_reg_int(list:taasmoutput;size:Tcgsize):tregister;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -587,6 +596,7 @@ unit cgobj;
|
|||||||
include(unusedscratchregisters,r.number shr 8);
|
include(unusedscratchregisters,r.number shr 8);
|
||||||
a_reg_dealloc(list,r);
|
a_reg_dealloc(list,r);
|
||||||
end;
|
end;
|
||||||
|
{$endif newra}
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
for better code generation these methods should be overridden
|
for better code generation these methods should be overridden
|
||||||
@ -626,20 +636,36 @@ unit cgobj;
|
|||||||
hr : tregister;
|
hr : tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
hr:=get_scratch_reg_int(list,size);
|
hr:=get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_const_reg(list,size,a,hr);
|
a_load_const_reg(list,size,a,hr);
|
||||||
a_param_reg(list,size,hr,locpara);
|
a_param_reg(list,size,hr,locpara);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,hr);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,hr);
|
free_scratch_reg(list,hr);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
|
procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
|
||||||
var
|
var
|
||||||
hr : tregister;
|
hr : tregister;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
hr:=get_scratch_reg_int(list,size);
|
hr:=get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,r,hr);
|
a_load_ref_reg(list,size,r,hr);
|
||||||
a_param_reg(list,size,hr,locpara);
|
a_param_reg(list,size,hr,locpara);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,hr);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,hr);
|
free_scratch_reg(list,hr);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -664,10 +690,18 @@ unit cgobj;
|
|||||||
var
|
var
|
||||||
hr : tregister;
|
hr : tregister;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getaddressregister(list);
|
||||||
|
{$else newra}
|
||||||
hr:=get_scratch_reg_address(list);
|
hr:=get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
a_loadaddr_ref_reg(list,r,hr);
|
a_loadaddr_ref_reg(list,r,hr);
|
||||||
a_param_reg(list,OS_ADDR,hr,locpara);
|
a_param_reg(list,OS_ADDR,hr,locpara);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,hr);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,hr);
|
free_scratch_reg(list,hr);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -732,7 +766,11 @@ unit cgobj;
|
|||||||
tmpreg := rg.getregisterint(list,size)
|
tmpreg := rg.getregisterint(list,size)
|
||||||
else
|
else
|
||||||
{$endif i386}
|
{$endif i386}
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,sref,tmpreg);
|
a_load_ref_reg(list,size,sref,tmpreg);
|
||||||
a_load_reg_ref(list,size,tmpreg,dref);
|
a_load_reg_ref(list,size,tmpreg,dref);
|
||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
@ -745,7 +783,11 @@ unit cgobj;
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
{$endif i386}
|
{$endif i386}
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -755,10 +797,18 @@ unit cgobj;
|
|||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_const_reg(list,size,a,tmpreg);
|
a_load_const_reg(list,size,a,tmpreg);
|
||||||
a_load_reg_ref(list,size,tmpreg,ref);
|
a_load_reg_ref(list,size,tmpreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -949,11 +999,19 @@ unit cgobj;
|
|||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,ref,tmpreg);
|
a_load_ref_reg(list,size,ref,tmpreg);
|
||||||
a_op_const_reg(list,op,a,tmpreg);
|
a_op_const_reg(list,op,a,tmpreg);
|
||||||
a_load_reg_ref(list,size,tmpreg,ref);
|
a_load_reg_ref(list,size,tmpreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -977,11 +1035,19 @@ unit cgobj;
|
|||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,ref,tmpreg);
|
a_load_ref_reg(list,size,ref,tmpreg);
|
||||||
a_op_reg_reg(list,op,size,reg,tmpreg);
|
a_op_reg_reg(list,op,size,reg,tmpreg);
|
||||||
a_load_reg_ref(list,size,tmpreg,ref);
|
a_load_reg_ref(list,size,tmpreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1000,10 +1066,18 @@ unit cgobj;
|
|||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,ref,tmpreg);
|
a_load_ref_reg(list,size,ref,tmpreg);
|
||||||
a_op_reg_reg(list,op,size,tmpreg,reg);
|
a_op_reg_reg(list,op,size,tmpreg,reg);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1034,10 +1108,18 @@ unit cgobj;
|
|||||||
a_op_ref_reg(list,op,loc.size,ref,loc.register);
|
a_op_ref_reg(list,op,loc.size,ref,loc.register);
|
||||||
LOC_REFERENCE,LOC_CREFERENCE:
|
LOC_REFERENCE,LOC_CREFERENCE:
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,loc.size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,loc.size);
|
tmpreg := get_scratch_reg_int(list,loc.size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,loc.size,ref,tmpreg);
|
a_load_ref_reg(list,loc.size,ref,tmpreg);
|
||||||
a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
|
a_op_reg_ref(list,op,loc.size,tmpreg,loc.reference);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
internalerror(200109061);
|
internalerror(200109061);
|
||||||
@ -1067,10 +1149,18 @@ unit cgobj;
|
|||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,ref,tmpreg);
|
a_load_ref_reg(list,size,ref,tmpreg);
|
||||||
a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
|
a_cmp_const_reg_label(list,size,cmp_op,a,tmpreg,l);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const loc : tlocation;
|
procedure tcg.a_cmp_const_loc_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const loc : tlocation;
|
||||||
@ -1093,10 +1183,18 @@ unit cgobj;
|
|||||||
tmpreg: tregister;
|
tmpreg: tregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,ref,tmpreg);
|
a_load_ref_reg(list,size,ref,tmpreg);
|
||||||
a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
|
a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
|
procedure tcg.a_cmp_loc_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp; const loc: tlocation; reg : tregister; l : tasmlabel);
|
||||||
@ -1128,6 +1226,12 @@ unit cgobj;
|
|||||||
a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
|
a_cmp_ref_reg_label(list,size,cmp_op,ref,loc.register,l);
|
||||||
LOC_REFERENCE,LOC_CREFERENCE:
|
LOC_REFERENCE,LOC_CREFERENCE:
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg := rg.getregisterint(list,size);
|
||||||
|
a_load_ref_reg(list,size,loc.reference,tmpreg);
|
||||||
|
a_cmp_ref_reg_label(list,size,cmp_op,ref,tmpreg,l);
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else newra}
|
||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
{ the following is done with defines to avoid a speed penalty, }
|
{ the following is done with defines to avoid a speed penalty, }
|
||||||
{ since all this is only necessary for the 80x86 (because EDI }
|
{ since all this is only necessary for the 80x86 (because EDI }
|
||||||
@ -1145,7 +1249,8 @@ unit cgobj;
|
|||||||
rg.ungetregisterint(list,tmpreg)
|
rg.ungetregisterint(list,tmpreg)
|
||||||
else
|
else
|
||||||
{$endif i386}
|
{$endif i386}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif newra}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
internalerror(200109061);
|
internalerror(200109061);
|
||||||
@ -1392,8 +1497,11 @@ unit cgobj;
|
|||||||
if lto < 0 then
|
if lto < 0 then
|
||||||
lto := 0;
|
lto := 0;
|
||||||
end;
|
end;
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(list,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg := get_scratch_reg_int(list,OS_INT);
|
hreg := get_scratch_reg_int(list,OS_INT);
|
||||||
|
{$endif}
|
||||||
if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
if (p.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
|
||||||
a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
|
a_op_const_reg_reg(list,OP_SUB,def_cgsize(p.resulttype.def),
|
||||||
aword(lto),p.location.register,hreg)
|
aword(lto),p.location.register,hreg)
|
||||||
@ -1406,7 +1514,11 @@ unit cgobj;
|
|||||||
objectlibrary.getlabel(neglabel);
|
objectlibrary.getlabel(neglabel);
|
||||||
a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(hto-lto),hreg,neglabel);
|
a_cmp_const_reg_label(list,OS_INT,OC_BE,aword(hto-lto),hreg,neglabel);
|
||||||
{ !!! should happen right after the compare (JM) }
|
{ !!! should happen right after the compare (JM) }
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,hreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,hreg);
|
free_scratch_reg(list,hreg);
|
||||||
|
{$endif}
|
||||||
a_call_name(list,'FPC_RANGEERROR');
|
a_call_name(list,'FPC_RANGEERROR');
|
||||||
a_label(list,neglabel);
|
a_label(list,neglabel);
|
||||||
end;
|
end;
|
||||||
@ -1425,10 +1537,18 @@ unit cgobj;
|
|||||||
var
|
var
|
||||||
tmpreg : tregister;
|
tmpreg : tregister;
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(list,size);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_int(list,size);
|
tmpreg := get_scratch_reg_int(list,size);
|
||||||
|
{$endif}
|
||||||
g_flags2reg(list,size,f,tmpreg);
|
g_flags2reg(list,size,f,tmpreg);
|
||||||
a_load_reg_ref(list,size,tmpreg,ref);
|
a_load_reg_ref(list,size,tmpreg,ref);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1719,7 +1839,12 @@ finalization
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.81 2003-04-06 21:11:23 olle
|
Revision 1.82 2003-04-22 10:09:34 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.81 2003/04/06 21:11:23 olle
|
||||||
* changed newasmsymbol to newasmsymboldata for data symbols
|
* changed newasmsymbol to newasmsymboldata for data symbols
|
||||||
|
|
||||||
Revision 1.80 2003/03/28 19:16:56 peter
|
Revision 1.80 2003/03/28 19:16:56 peter
|
||||||
|
@ -199,6 +199,7 @@ interface
|
|||||||
function NeedAddrPrefix(opidx:byte):boolean;
|
function NeedAddrPrefix(opidx:byte):boolean;
|
||||||
procedure Swapoperands;
|
procedure Swapoperands;
|
||||||
{$endif NOAG386BIN}
|
{$endif NOAG386BIN}
|
||||||
|
function is_nop:boolean;override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1898,6 +1899,17 @@ implementation
|
|||||||
end;
|
end;
|
||||||
{$endif NOAG386BIN}
|
{$endif NOAG386BIN}
|
||||||
|
|
||||||
|
function Taicpu.is_nop:boolean;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{We do not check the number of operands; we assume that nobody constructs
|
||||||
|
a mov or xchg instruction with less than 2 operands.}
|
||||||
|
is_nop:=(opcode=A_NOP) or
|
||||||
|
(opcode=A_MOV) and (oper[0].typ=top_reg) and (oper[1].typ=top_reg) and (oper[0].reg.number=oper[1].reg.number) or
|
||||||
|
(opcode=A_XCHG) and (oper[0].typ=top_reg) and (oper[1].typ=top_reg) and (oper[0].reg.number=oper[1].reg.number);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
Instruction table
|
Instruction table
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
@ -1947,7 +1959,12 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.15 2003-03-26 12:50:54 armin
|
Revision 1.16 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.15 2003/03/26 12:50:54 armin
|
||||||
* avoid problems with the ide in init/dome
|
* avoid problems with the ide in init/dome
|
||||||
|
|
||||||
Revision 1.14 2003/03/08 08:59:07 daniel
|
Revision 1.14 2003/03/08 08:59:07 daniel
|
||||||
|
@ -460,7 +460,7 @@ interface
|
|||||||
else
|
else
|
||||||
regstr:=std_reg2str[tai_regalloc(hp).reg.enum];
|
regstr:=std_reg2str[tai_regalloc(hp).reg.enum];
|
||||||
if (cs_asm_regalloc in aktglobalswitches) then
|
if (cs_asm_regalloc in aktglobalswitches) then
|
||||||
AsmWriteLn(target_asm.comment+'Register '+regstr+
|
AsmWriteLn(#9#9+target_asm.comment+'Register '+regstr+
|
||||||
allocstr[tai_regalloc(hp).allocation]);
|
allocstr[tai_regalloc(hp).allocation]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -921,7 +921,12 @@ initialization
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.32 2003-03-08 13:59:17 daniel
|
Revision 1.33 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.32 2003/03/08 13:59:17 daniel
|
||||||
* Work to handle new register notation in ag386nsm
|
* Work to handle new register notation in ag386nsm
|
||||||
+ Added newra version of Ti386moddivnode
|
+ Added newra version of Ti386moddivnode
|
||||||
|
|
||||||
|
@ -552,8 +552,10 @@ uses
|
|||||||
{# Registers which are defined as scratch and no need to save across
|
{# Registers which are defined as scratch and no need to save across
|
||||||
routine calls or in assembler blocks.
|
routine calls or in assembler blocks.
|
||||||
}
|
}
|
||||||
|
{$ifndef newra}
|
||||||
max_scratch_regs = 1;
|
max_scratch_regs = 1;
|
||||||
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
|
scratch_regs : array[1..max_scratch_regs] of Tsuperregister = (RS_EDI);
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
@ -814,7 +816,12 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.46 2003-04-21 19:16:50 peter
|
Revision 1.47 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.46 2003/04/21 19:16:50 peter
|
||||||
* count address regs separate
|
* count address regs separate
|
||||||
|
|
||||||
Revision 1.45 2003/03/28 19:16:57 peter
|
Revision 1.45 2003/03/28 19:16:57 peter
|
||||||
|
@ -84,13 +84,17 @@ interface
|
|||||||
secondpass(left);
|
secondpass(left);
|
||||||
|
|
||||||
{ are too few registers free? }
|
{ are too few registers free? }
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if location.loc=LOC_FPUREGISTER then
|
if location.loc=LOC_FPUREGISTER then
|
||||||
pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
|
pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
|
||||||
else
|
else
|
||||||
pushedfpu:=false;
|
pushedfpu:=false;
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -476,7 +480,9 @@ interface
|
|||||||
falselabel:=ofl;
|
falselabel:=ofl;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
isjump:=(right.location.loc=LOC_JUMP);
|
isjump:=(right.location.loc=LOC_JUMP);
|
||||||
if isjump then
|
if isjump then
|
||||||
begin
|
begin
|
||||||
@ -486,7 +492,9 @@ interface
|
|||||||
objectlibrary.getlabel(falselabel);
|
objectlibrary.getlabel(falselabel);
|
||||||
end;
|
end;
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
|
||||||
location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
|
location_force_reg(exprasmlist,right.location,opsize_2_cgsize[opsize],false);
|
||||||
if isjump then
|
if isjump then
|
||||||
@ -1642,7 +1650,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.61 2003-04-17 10:02:48 daniel
|
Revision 1.62 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.61 2003/04/17 10:02:48 daniel
|
||||||
* Tweaked register allocate/deallocate positition to less interferences
|
* Tweaked register allocate/deallocate positition to less interferences
|
||||||
are generated.
|
are generated.
|
||||||
|
|
||||||
|
@ -146,9 +146,17 @@ implementation
|
|||||||
{ better than an add on all processors }
|
{ better than an add on all processors }
|
||||||
if pop_size=4 then
|
if pop_size=4 then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hreg);
|
cg.free_scratch_reg(exprasmlist,hreg);
|
||||||
|
{$endif newra}
|
||||||
end
|
end
|
||||||
{ the pentium has two pipes and pop reg is pairable }
|
{ the pentium has two pipes and pop reg is pairable }
|
||||||
{ but the registers must be different! }
|
{ but the registers must be different! }
|
||||||
@ -158,9 +166,17 @@ implementation
|
|||||||
(aktoptprocessor=ClassP5) and
|
(aktoptprocessor=ClassP5) and
|
||||||
(rg.countunusedregsint>0) then
|
(rg.countunusedregsint>0) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hreg);
|
cg.free_scratch_reg(exprasmlist,hreg);
|
||||||
|
{$endif}
|
||||||
hreg:=rg.getregisterint(exprasmlist,OS_INT);
|
hreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
exprasmlist.concat(taicpu.op_reg(A_POP,S_L,hreg));
|
||||||
rg.ungetregisterint(exprasmlist,hreg);
|
rg.ungetregisterint(exprasmlist,hreg);
|
||||||
@ -185,7 +201,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.87 2003-04-04 15:38:56 peter
|
Revision 1.88 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.87 2003/04/04 15:38:56 peter
|
||||||
* moved generic code from n386cal to ncgcal, i386 now also
|
* moved generic code from n386cal to ncgcal, i386 now also
|
||||||
uses the generic ncgcal
|
uses the generic ncgcal
|
||||||
|
|
||||||
|
@ -117,7 +117,11 @@ implementation
|
|||||||
hregister:=left.location.register;
|
hregister:=left.location.register;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getregisterint(exprasmlist,OS_32);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
|
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
|
||||||
|
{$endif}
|
||||||
freereg:=true;
|
freereg:=true;
|
||||||
cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hregister);
|
cg.a_load_reg_reg(exprasmlist,left.location.size,OS_32,left.location.register,hregister);
|
||||||
end;
|
end;
|
||||||
@ -126,7 +130,11 @@ implementation
|
|||||||
LOC_REFERENCE,
|
LOC_REFERENCE,
|
||||||
LOC_CREFERENCE :
|
LOC_CREFERENCE :
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif newra}
|
||||||
freereg:=true;
|
freereg:=true;
|
||||||
if left.location.size in [OS_64,OS_S64] then
|
if left.location.size in [OS_64,OS_S64] then
|
||||||
begin
|
begin
|
||||||
@ -147,8 +155,13 @@ implementation
|
|||||||
|
|
||||||
{ for 64 bit integers, the high dword is already pushed }
|
{ for 64 bit integers, the high dword is already pushed }
|
||||||
exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
|
exprasmlist.concat(taicpu.op_reg(A_PUSH,S_L,hregister));
|
||||||
|
{$ifdef newra}
|
||||||
|
if freereg then
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else}
|
||||||
if freereg then
|
if freereg then
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif}
|
||||||
r.enum:=R_INTREGISTER;
|
r.enum:=R_INTREGISTER;
|
||||||
r.number:=NR_ESP;
|
r.number:=NR_ESP;
|
||||||
reference_reset_base(href,r,0);
|
reference_reset_base(href,r,0);
|
||||||
@ -268,10 +281,18 @@ implementation
|
|||||||
begin
|
begin
|
||||||
if left.location.size in [OS_64,OS_S64] then
|
if left.location.size in [OS_64,OS_S64] then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getregisterint(exprasmlist,OS_32);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
|
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_32);
|
||||||
|
{$endif}
|
||||||
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.registerlow,hregister);
|
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,left.location.registerlow,hregister);
|
||||||
cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.registerhigh,hregister);
|
cg.a_op_reg_reg(exprasmlist,OP_OR,OS_32,left.location.registerhigh,hregister);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
|
cg.a_op_reg_reg(exprasmlist,OP_OR,left.location.size,left.location.register,left.location.register);
|
||||||
@ -432,7 +453,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.57 2003-03-13 19:52:23 jonas
|
Revision 1.58 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.57 2003/03/13 19:52:23 jonas
|
||||||
* and more new register allocator fixes (in the i386 code generator this
|
* and more new register allocator fixes (in the i386 code generator this
|
||||||
time). At least now the ppc cross compiler can compile the linux
|
time). At least now the ppc cross compiler can compile the linux
|
||||||
system unit again, but I haven't tested it.
|
system unit again, but I haven't tested it.
|
||||||
|
@ -288,10 +288,14 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ generate code for the element to set }
|
{ generate code for the element to set }
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||||
tcallparanode(left).left.location,pushedregs);
|
tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
{ determine asm operator }
|
{ determine asm operator }
|
||||||
if inlinenumber=in_include_x_y then
|
if inlinenumber=in_include_x_y then
|
||||||
asmop:=A_BTS
|
asmop:=A_BTS
|
||||||
@ -316,15 +320,24 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
scratch_reg := TRUE;
|
scratch_reg := TRUE;
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hregister:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
|
cg.a_load_loc_reg(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,hregister);
|
||||||
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
if (tcallparanode(left).left.location.loc=LOC_REFERENCE) then
|
||||||
emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
|
emit_reg_ref(asmop,S_L,hregister,tcallparanode(left).left.location.reference)
|
||||||
else
|
else
|
||||||
emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
|
emit_reg_reg(asmop,S_L,hregister,tcallparanode(left).left.location.register);
|
||||||
|
{$ifdef newra}
|
||||||
|
if scratch_reg then
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else}
|
||||||
if scratch_reg then
|
if scratch_reg then
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -334,7 +347,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.56 2003-02-19 22:00:15 daniel
|
Revision 1.57 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.56 2003/02/19 22:00:15 daniel
|
||||||
* Code generator converted to new register notation
|
* Code generator converted to new register notation
|
||||||
- Horribily outdated todo.txt removed
|
- Horribily outdated todo.txt removed
|
||||||
|
|
||||||
|
@ -77,9 +77,7 @@ implementation
|
|||||||
secondpass(left);
|
secondpass(left);
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
@ -154,15 +152,22 @@ implementation
|
|||||||
emit_none(A_CDQ,S_NO);
|
emit_none(A_CDQ,S_NO);
|
||||||
|
|
||||||
{Division depends on the right type.}
|
{Division depends on the right type.}
|
||||||
if torddef(right.resulttype.def).typ=u32bit then
|
if Torddef(right.resulttype.def).typ=u32bit then
|
||||||
op:=A_DIV
|
op:=A_DIV
|
||||||
else
|
else
|
||||||
op:=A_IDIV;
|
op:=A_IDIV;
|
||||||
|
|
||||||
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
|
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
|
||||||
emit_ref(op,S_L,right.location.reference)
|
emit_ref(op,S_L,right.location.reference)
|
||||||
|
else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
||||||
|
emit_reg(op,S_L,right.location.register)
|
||||||
else
|
else
|
||||||
emit_reg(op,S_L,right.location.register);
|
begin
|
||||||
|
hreg1:=rg.getregisterint(exprasmlist,right.location.size);
|
||||||
|
cg.a_load_loc_reg(exprasmlist,right.location,hreg1);
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg1);
|
||||||
|
emit_reg(op,S_L,hreg1);
|
||||||
|
end;
|
||||||
location_release(exprasmlist,right.location);
|
location_release(exprasmlist,right.location);
|
||||||
|
|
||||||
{Copy the result into a new register. Release EAX & EDX.}
|
{Copy the result into a new register. Release EAX & EDX.}
|
||||||
@ -425,9 +430,13 @@ implementation
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
|
|
||||||
{ determine operator }
|
{ determine operator }
|
||||||
if nodetype=shln then
|
if nodetype=shln then
|
||||||
@ -1172,7 +1181,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.50 2003-04-21 19:15:26 peter
|
Revision 1.51 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.50 2003/04/21 19:15:26 peter
|
||||||
* when ecx is not available allocated another register
|
* when ecx is not available allocated another register
|
||||||
|
|
||||||
Revision 1.49 2003/04/17 10:02:48 daniel
|
Revision 1.49 2003/04/17 10:02:48 daniel
|
||||||
|
@ -200,9 +200,13 @@ implementation
|
|||||||
{ Only process the right if we are not generating jumps }
|
{ Only process the right if we are not generating jumps }
|
||||||
if not genjumps then
|
if not genjumps then
|
||||||
begin
|
begin
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
@ -720,7 +724,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.51 2003-03-13 19:52:23 jonas
|
Revision 1.52 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.51 2003/03/13 19:52:23 jonas
|
||||||
* and more new register allocator fixes (in the i386 code generator this
|
* and more new register allocator fixes (in the i386 code generator this
|
||||||
time). At least now the ppc cross compiler can compile the linux
|
time). At least now the ppc cross compiler can compile the linux
|
||||||
system unit again, but I haven't tested it.
|
system unit again, but I haven't tested it.
|
||||||
|
@ -329,9 +329,9 @@ unit rgcpu;
|
|||||||
procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
|
procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if ref.base.number<>NR_NO then
|
if (ref.base.number<>NR_NO) and (ref.base.number<>NR_FRAME_POINTER_REG) then
|
||||||
ungetregisterint(list,ref.base);
|
ungetregisterint(list,ref.base);
|
||||||
if ref.index.number<>NR_NO then
|
if (ref.index.number<>NR_NO) and (ref.index.number<>NR_FRAME_POINTER_REG) then
|
||||||
ungetregisterint(list,ref.index);
|
ungetregisterint(list,ref.index);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -557,12 +557,17 @@ unit rgcpu;
|
|||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
rg := trgcpu.create;
|
rg := trgcpu.create(7); {We use 7 int registers on i386.}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.18 2003-04-21 19:16:50 peter
|
Revision 1.19 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.18 2003/04/21 19:16:50 peter
|
||||||
* count address regs separate
|
* count address regs separate
|
||||||
|
|
||||||
Revision 1.17 2003/03/28 19:16:57 peter
|
Revision 1.17 2003/03/28 19:16:57 peter
|
||||||
|
@ -210,12 +210,17 @@ unit rgcpu;
|
|||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
rg := trgcpu.create;
|
rg := trgcpu.create(16);
|
||||||
end.
|
end.
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.7 2003-02-19 22:00:16 daniel
|
Revision 1.8 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.7 2003/02/19 22:00:16 daniel
|
||||||
* Code generator converted to new register notation
|
* Code generator converted to new register notation
|
||||||
- Horribily outdated todo.txt removed
|
- Horribily outdated todo.txt removed
|
||||||
|
|
||||||
|
@ -171,11 +171,19 @@ implementation
|
|||||||
begin
|
begin
|
||||||
if calloption=pocall_inline then
|
if calloption=pocall_inline then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif newra}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
||||||
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
||||||
@ -202,11 +210,19 @@ implementation
|
|||||||
inc(pushedparasize,POINTER_SIZE);
|
inc(pushedparasize,POINTER_SIZE);
|
||||||
if calloption=pocall_inline then
|
if calloption=pocall_inline then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
||||||
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
||||||
@ -250,11 +266,19 @@ implementation
|
|||||||
inc(pushedparasize,POINTER_SIZE);
|
inc(pushedparasize,POINTER_SIZE);
|
||||||
if calloption=pocall_inline then
|
if calloption=pocall_inline then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,tmpreg);
|
||||||
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
reference_reset_base(href,procinfo.framepointer,para_offset-pushedparasize);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraitem.paraloc);
|
||||||
@ -719,6 +743,14 @@ implementation
|
|||||||
r.number:=NR_ACCUMULATOR;
|
r.number:=NR_ACCUMULATOR;
|
||||||
hregister.enum:=R_INTREGISTER;
|
hregister.enum:=R_INTREGISTER;
|
||||||
hregister.number:=NR_ACCUMULATORHIGH;
|
hregister.number:=NR_ACCUMULATORHIGH;
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
|
||||||
|
rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH);
|
||||||
|
rg.ungetregisterint(exprasmlist,r);
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else newra}
|
||||||
cg.a_reg_alloc(exprasmlist,r);
|
cg.a_reg_alloc(exprasmlist,r);
|
||||||
cg.a_reg_alloc(exprasmlist,hregister);
|
cg.a_reg_alloc(exprasmlist,hregister);
|
||||||
if RS_ACCUMULATOR in rg.unusedregsint then
|
if RS_ACCUMULATOR in rg.unusedregsint then
|
||||||
@ -729,6 +761,7 @@ implementation
|
|||||||
location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
|
location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
|
||||||
else
|
else
|
||||||
location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
|
location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$endif newra}
|
||||||
cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
|
cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
|
||||||
location.register64);
|
location.register64);
|
||||||
end
|
end
|
||||||
@ -740,11 +773,17 @@ implementation
|
|||||||
nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
|
nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
|
||||||
r.enum:=R_INTREGISTER;
|
r.enum:=R_INTREGISTER;
|
||||||
r.number:=nr;
|
r.number:=nr;
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.getexplicitregisterint(exprasmlist,nr);
|
||||||
|
rg.ungetregisterint(exprasmlist,r);
|
||||||
|
location.register:=rg.getregisterint(exprasmlist,cgsize);
|
||||||
|
{$else newra}
|
||||||
cg.a_reg_alloc(exprasmlist,r);
|
cg.a_reg_alloc(exprasmlist,r);
|
||||||
if RS_ACCUMULATOR in rg.unusedregsint then
|
if RS_ACCUMULATOR in rg.unusedregsint then
|
||||||
location.register:=rg.getexplicitregisterint(exprasmlist,nr)
|
location.register:=rg.getexplicitregisterint(exprasmlist,nr)
|
||||||
else
|
else
|
||||||
location.register:=rg.getregisterint(exprasmlist,cgsize);
|
location.register:=rg.getregisterint(exprasmlist,cgsize);
|
||||||
|
{$endif newra}
|
||||||
cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
|
cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -783,12 +822,18 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_REGISTER,OS_INT);
|
location_reset(location,LOC_REGISTER,OS_INT);
|
||||||
|
r.enum:=R_INTREGISTER;
|
||||||
|
r.number:=NR_ACCUMULATOR;
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
|
||||||
|
rg.ungetregisterint(exprasmlist,r);
|
||||||
|
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else newra}
|
||||||
if RS_ACCUMULATOR in rg.unusedregsint then
|
if RS_ACCUMULATOR in rg.unusedregsint then
|
||||||
location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
|
location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
|
||||||
else
|
else
|
||||||
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
r.enum:=R_INTREGISTER;
|
{$endif newra}
|
||||||
r.number:=NR_ACCUMULATOR;
|
|
||||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
|
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -999,11 +1044,19 @@ implementation
|
|||||||
by function itself ! }
|
by function itself ! }
|
||||||
if inlined then
|
if inlined then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_address(exprasmlist);
|
hregister:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,funcretref,hregister);
|
cg.a_loadaddr_ref_reg(exprasmlist,funcretref,hregister);
|
||||||
reference_reset_base(href,procinfo.framepointer,inlinecode.retoffset);
|
reference_reset_base(href,procinfo.framepointer,inlinecode.retoffset);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
cg.a_paramaddr_ref(exprasmlist,funcretref,paramanager.getfuncretparaloc(procdefinition));
|
cg.a_paramaddr_ref(exprasmlist,funcretref,paramanager.getfuncretparaloc(procdefinition));
|
||||||
@ -1423,7 +1476,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.47 2003-04-22 09:49:44 peter
|
Revision 1.48 2003-04-22 10:09:34 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.47 2003/04/22 09:49:44 peter
|
||||||
* do not load self when calling a non-inherited class constructor
|
* do not load self when calling a non-inherited class constructor
|
||||||
|
|
||||||
Revision 1.46 2003/04/21 20:03:32 peter
|
Revision 1.46 2003/04/21 20:03:32 peter
|
||||||
|
@ -390,10 +390,14 @@ implementation
|
|||||||
{ second_ argument specified?, must be a s32bit in register }
|
{ second_ argument specified?, must be a s32bit in register }
|
||||||
if assigned(tcallparanode(left).right) then
|
if assigned(tcallparanode(left).right) then
|
||||||
begin
|
begin
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||||
tcallparanode(left).left.location,pushedregs);
|
tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
{ when constant, just multiply the addvalue }
|
{ when constant, just multiply the addvalue }
|
||||||
if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
|
if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
|
||||||
addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
|
addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
|
||||||
@ -504,13 +508,21 @@ implementation
|
|||||||
(tenumdef(tcallparanode(tcallparanode(left).right).left.resulttype.def).max<=32));
|
(tenumdef(tcallparanode(tcallparanode(left).right).left.resulttype.def).max<=32));
|
||||||
|
|
||||||
{ generate code for the element to set }
|
{ generate code for the element to set }
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
maybe_save(exprasmlist,tcallparanode(tcallparanode(left).right).left.registers32,
|
||||||
tcallparanode(left).left.location,pushedregs);
|
tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
maybe_restore(exprasmlist,tcallparanode(left).left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
|
|
||||||
{ bitnumber - which must be loaded into register }
|
{ bitnumber - which must be loaded into register }
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hregister := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hregister := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
hregister2 := rg.getregisterint(exprasmlist,OS_INT);
|
hregister2 := rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
|
||||||
case tcallparanode(tcallparanode(left).right).left.location.loc of
|
case tcallparanode(tcallparanode(left).right).left.location.loc of
|
||||||
@ -568,7 +580,11 @@ implementation
|
|||||||
}
|
}
|
||||||
{ hregister contains the bitnumber (div 32 to get the correct offset) }
|
{ hregister contains the bitnumber (div 32 to get the correct offset) }
|
||||||
cg.a_op_const_reg(exprasmlist, OP_SHR, 5, hregister);
|
cg.a_op_const_reg(exprasmlist, OP_SHR, 5, hregister);
|
||||||
|
{$ifdef newra}
|
||||||
|
addrreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
addrreg := cg.get_scratch_reg_address(exprasmlist);
|
addrreg := cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
{ calculate the correct address of the operand }
|
{ calculate the correct address of the operand }
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist, tcallparanode(left).left.location.reference,addrreg);
|
cg.a_loadaddr_ref_reg(exprasmlist, tcallparanode(left).left.location.reference,addrreg);
|
||||||
cg.a_op_reg_reg(exprasmlist, OP_ADD, OS_INT, hregister, addrreg);
|
cg.a_op_reg_reg(exprasmlist, OP_ADD, OS_INT, hregister, addrreg);
|
||||||
@ -583,10 +599,17 @@ implementation
|
|||||||
cg.a_op_reg_reg(exprasmlist, OP_NOT, OS_32, hregister2, hregister2);
|
cg.a_op_reg_reg(exprasmlist, OP_NOT, OS_32, hregister2, hregister2);
|
||||||
cg.a_op_reg_ref(exprasmlist, OP_AND, OS_32, hregister2, href);
|
cg.a_op_reg_ref(exprasmlist, OP_AND, OS_32, hregister2, href);
|
||||||
end;
|
end;
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,addrreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist, addrreg);
|
cg.free_scratch_reg(exprasmlist, addrreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif}
|
||||||
rg.ungetregisterint(exprasmlist,hregister2);
|
rg.ungetregisterint(exprasmlist,hregister2);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -646,7 +669,12 @@ end.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.23 2003-04-06 21:11:23 olle
|
Revision 1.24 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.23 2003/04/06 21:11:23 olle
|
||||||
* changed newasmsymbol to newasmsymboldata for data symbols
|
* changed newasmsymbol to newasmsymboldata for data symbols
|
||||||
|
|
||||||
Revision 1.22 2003/03/28 19:16:56 peter
|
Revision 1.22 2003/03/28 19:16:56 peter
|
||||||
|
@ -363,10 +363,18 @@ implementation
|
|||||||
rg.ungetregisterint(exprasmlist,hregister);
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
{ load address of the function }
|
{ load address of the function }
|
||||||
reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
|
reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
|
||||||
|
{$ifdef newra}
|
||||||
|
hregister:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
hregister:=cg.get_scratch_reg_address(exprasmlist);
|
hregister:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
|
cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister);
|
||||||
|
{$else newra}
|
||||||
cg.free_scratch_reg(exprasmlist,hregister);
|
cg.free_scratch_reg(exprasmlist,hregister);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -443,12 +451,16 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
||||||
{ can be false }
|
{ can be false }
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
{ decrement destination reference counter }
|
{ decrement destination reference counter }
|
||||||
if (left.resulttype.def.needs_inittable) then
|
if (left.resulttype.def.needs_inittable) then
|
||||||
cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
|
cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,right.location,pushedregs);
|
maybe_restore(exprasmlist,right.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -469,14 +481,18 @@ implementation
|
|||||||
|
|
||||||
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
||||||
{ can be false }
|
{ can be false }
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
{ increment source reference counter, this is
|
{ increment source reference counter, this is
|
||||||
useless for string constants}
|
useless for string constants}
|
||||||
if (right.resulttype.def.needs_inittable) and
|
if (right.resulttype.def.needs_inittable) and
|
||||||
(right.nodetype<>stringconstn) then
|
(right.nodetype<>stringconstn) then
|
||||||
cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
|
cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
|
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
@ -633,9 +649,13 @@ implementation
|
|||||||
{ generate the leftnode for the true case, and
|
{ generate the leftnode for the true case, and
|
||||||
release the location }
|
release the location }
|
||||||
cg.a_label(exprasmlist,truelabel);
|
cg.a_label(exprasmlist,truelabel);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,right.location,pushedregs);
|
maybe_restore(exprasmlist,right.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
cg.a_load_const_loc(exprasmlist,1,left.location);
|
cg.a_load_const_loc(exprasmlist,1,left.location);
|
||||||
@ -643,9 +663,13 @@ implementation
|
|||||||
cg.a_jmp_always(exprasmlist,hlabel);
|
cg.a_jmp_always(exprasmlist,hlabel);
|
||||||
{ generate the leftnode for the false case }
|
{ generate the leftnode for the false case }
|
||||||
cg.a_label(exprasmlist,falselabel);
|
cg.a_label(exprasmlist,falselabel);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,right.location,pushedregs);
|
maybe_restore(exprasmlist,right.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
cg.a_load_const_loc(exprasmlist,0,left.location);
|
cg.a_load_const_loc(exprasmlist,0,left.location);
|
||||||
@ -910,10 +934,18 @@ implementation
|
|||||||
if vaddr then
|
if vaddr then
|
||||||
begin
|
begin
|
||||||
location_force_mem(exprasmlist,hp.left.location);
|
location_force_mem(exprasmlist,hp.left.location);
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
tmpreg:=cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
|
cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||||
|
{$endif}
|
||||||
location_release(exprasmlist,hp.left.location);
|
location_release(exprasmlist,hp.left.location);
|
||||||
if freetemp then
|
if freetemp then
|
||||||
location_freetemp(exprasmlist,hp.left.location);
|
location_freetemp(exprasmlist,hp.left.location);
|
||||||
@ -970,7 +1002,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.47 2003-04-06 21:11:23 olle
|
Revision 1.48 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.47 2003/04/06 21:11:23 olle
|
||||||
* changed newasmsymbol to newasmsymboldata for data symbols
|
* changed newasmsymbol to newasmsymboldata for data symbols
|
||||||
|
|
||||||
Revision 1.46 2003/03/28 19:16:56 peter
|
Revision 1.46 2003/03/28 19:16:56 peter
|
||||||
|
@ -257,9 +257,13 @@ implementation
|
|||||||
secondpass(left);
|
secondpass(left);
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
location_copy(location,left.location);
|
location_copy(location,left.location);
|
||||||
@ -350,9 +354,13 @@ implementation
|
|||||||
begin
|
begin
|
||||||
freescratch:=false;
|
freescratch:=false;
|
||||||
secondpass(left);
|
secondpass(left);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
{ determine operator }
|
{ determine operator }
|
||||||
case nodetype of
|
case nodetype of
|
||||||
shln: op:=OP_SHL;
|
shln: op:=OP_SHL;
|
||||||
@ -428,15 +436,24 @@ implementation
|
|||||||
begin
|
begin
|
||||||
if right.location.loc<>LOC_CREGISTER then
|
if right.location.loc<>LOC_CREGISTER then
|
||||||
location_release(exprasmlist,right.location);
|
location_release(exprasmlist,right.location);
|
||||||
|
{$ifdef newra}
|
||||||
|
hcountreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hcountreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hcountreg:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
freescratch := true;
|
freescratch := true;
|
||||||
cg.a_load_loc_reg(exprasmlist,right.location,hcountreg);
|
cg.a_load_loc_reg(exprasmlist,right.location,hcountreg);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
hcountreg:=right.location.register;
|
hcountreg:=right.location.register;
|
||||||
cg.a_op_reg_reg(exprasmlist,op,OS_INT,hcountreg,location.register);
|
cg.a_op_reg_reg(exprasmlist,op,OS_INT,hcountreg,location.register);
|
||||||
|
{$ifdef newra}
|
||||||
|
if freescratch then
|
||||||
|
rg.ungetregisterint(exprasmlist,hcountreg);
|
||||||
|
{$else}
|
||||||
if freescratch then
|
if freescratch then
|
||||||
cg.free_scratch_reg(exprasmlist,hcountreg);
|
cg.free_scratch_reg(exprasmlist,hcountreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -450,7 +467,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.7 2003-03-28 19:16:56 peter
|
Revision 1.8 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.7 2003/03/28 19:16:56 peter
|
||||||
* generic constructor working for i386
|
* generic constructor working for i386
|
||||||
* remove fixed self register
|
* remove fixed self register
|
||||||
* esi added as address register for i386
|
* esi added as address register for i386
|
||||||
|
@ -406,12 +406,20 @@ implementation
|
|||||||
usetemp:=true;
|
usetemp:=true;
|
||||||
if is_class_or_interface(left.resulttype.def) then
|
if is_class_or_interface(left.resulttype.def) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
|
cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(exprasmlist);
|
||||||
|
{$else}
|
||||||
tmpreg := cg.get_scratch_reg_address(exprasmlist);
|
tmpreg := cg.get_scratch_reg_address(exprasmlist);
|
||||||
|
{$endif newra}
|
||||||
cg.a_loadaddr_ref_reg(exprasmlist,
|
cg.a_loadaddr_ref_reg(exprasmlist,
|
||||||
left.location.reference,tmpreg);
|
left.location.reference,tmpreg);
|
||||||
end;
|
end;
|
||||||
@ -444,7 +452,11 @@ implementation
|
|||||||
tg.GetTemp(exprasmlist,pointer_size,tt_persistant,withreference);
|
tg.GetTemp(exprasmlist,pointer_size,tt_persistant,withreference);
|
||||||
{ move to temp reference }
|
{ move to temp reference }
|
||||||
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
|
cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,tmpreg);
|
cg.free_scratch_reg(exprasmlist,tmpreg);
|
||||||
|
{$endif}
|
||||||
{$ifdef GDB}
|
{$ifdef GDB}
|
||||||
if (cs_debuginfo in aktmoduleswitches) then
|
if (cs_debuginfo in aktmoduleswitches) then
|
||||||
begin
|
begin
|
||||||
@ -580,7 +592,11 @@ implementation
|
|||||||
hreg:=right.location.register
|
hreg:=right.location.register
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
freereg:=true;
|
freereg:=true;
|
||||||
cg.a_load_loc_reg(exprasmlist,right.location,hreg);
|
cg.a_load_loc_reg(exprasmlist,right.location,hreg);
|
||||||
end;
|
end;
|
||||||
@ -588,8 +604,13 @@ implementation
|
|||||||
objectlibrary.getlabel(poslabel);
|
objectlibrary.getlabel(poslabel);
|
||||||
cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
|
cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
|
||||||
cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
|
cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
|
||||||
|
{$ifdef newra}
|
||||||
|
if freereg then
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg);
|
||||||
|
{$else}
|
||||||
if freereg then
|
if freereg then
|
||||||
cg.free_scratch_reg(exprasmlist,hreg);
|
cg.free_scratch_reg(exprasmlist,hreg);
|
||||||
|
{$endif}
|
||||||
cg.a_label(exprasmlist,poslabel);
|
cg.a_label(exprasmlist,poslabel);
|
||||||
cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
|
cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
|
||||||
cg.a_label(exprasmlist,neglabel);
|
cg.a_label(exprasmlist,neglabel);
|
||||||
@ -843,9 +864,13 @@ implementation
|
|||||||
ofl:=falselabel;
|
ofl:=falselabel;
|
||||||
objectlibrary.getlabel(falselabel);
|
objectlibrary.getlabel(falselabel);
|
||||||
end;
|
end;
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,location,pushedregs);
|
maybe_restore(exprasmlist,location,pushedregs);
|
||||||
|
{$endif}
|
||||||
|
|
||||||
if cs_check_range in aktlocalswitches then
|
if cs_check_range in aktlocalswitches then
|
||||||
begin
|
begin
|
||||||
@ -919,7 +944,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.45 2003-04-06 21:11:23 olle
|
Revision 1.46 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.45 2003/04/06 21:11:23 olle
|
||||||
* changed newasmsymbol to newasmsymboldata for data symbols
|
* changed newasmsymbol to newasmsymboldata for data symbols
|
||||||
|
|
||||||
Revision 1.44 2003/03/28 19:16:56 peter
|
Revision 1.44 2003/03/28 19:16:56 peter
|
||||||
|
@ -110,11 +110,15 @@ implementation
|
|||||||
{ also a second value ? }
|
{ also a second value ? }
|
||||||
if assigned(right) then
|
if assigned(right) then
|
||||||
begin
|
begin
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif newra}
|
||||||
if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
|
||||||
location_force_reg(exprasmlist,right.location,OS_32,false);
|
location_force_reg(exprasmlist,right.location,OS_32,false);
|
||||||
end;
|
end;
|
||||||
@ -264,9 +268,13 @@ implementation
|
|||||||
{ Only process the right if we are not generating jumps }
|
{ Only process the right if we are not generating jumps }
|
||||||
if not genjumps then
|
if not genjumps then
|
||||||
begin
|
begin
|
||||||
|
{$ifndef newra}
|
||||||
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
secondpass(right);
|
secondpass(right);
|
||||||
|
{$ifndef newra}
|
||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
@ -312,7 +320,11 @@ implementation
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ load the value in a register }
|
{ load the value in a register }
|
||||||
|
{$ifdef newra}
|
||||||
|
pleftreg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
pleftreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
pleftreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
opsize := OS_INT;
|
opsize := OS_INT;
|
||||||
cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,pleftreg);
|
cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),left.location.reference,pleftreg);
|
||||||
end;
|
end;
|
||||||
@ -340,7 +352,11 @@ implementation
|
|||||||
if (left.location.loc = LOC_CREGISTER) and
|
if (left.location.loc = LOC_CREGISTER) and
|
||||||
(hr.enum <> pleftreg.enum) then
|
(hr.enum <> pleftreg.enum) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg,hr);
|
cg.a_op_const_reg_reg(exprasmlist,OP_SUB,opsize,setparts[i].start,pleftreg,hr);
|
||||||
pleftreg:=hr;
|
pleftreg:=hr;
|
||||||
opsize := OS_INT;
|
opsize := OS_INT;
|
||||||
@ -388,13 +404,21 @@ implementation
|
|||||||
cg.a_label(exprasmlist,l3);
|
cg.a_label(exprasmlist,l3);
|
||||||
case left.location.loc of
|
case left.location.loc of
|
||||||
LOC_CREGISTER :
|
LOC_CREGISTER :
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,pleftreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,pleftreg);
|
cg.free_scratch_reg(exprasmlist,pleftreg);
|
||||||
|
{$endif}
|
||||||
LOC_REGISTER :
|
LOC_REGISTER :
|
||||||
rg.ungetregister(exprasmlist,pleftreg);
|
rg.ungetregister(exprasmlist,pleftreg);
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
reference_release(exprasmlist,left.location.reference);
|
reference_release(exprasmlist,left.location.reference);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,pleftreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,pleftreg);
|
cg.free_scratch_reg(exprasmlist,pleftreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
@ -412,7 +436,11 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{ clear the register value, indicating result is FALSE }
|
{ clear the register value, indicating result is FALSE }
|
||||||
cg.a_load_const_reg(exprasmlist,OS_INT,0,location.register);
|
cg.a_load_const_reg(exprasmlist,OS_INT,0,location.register);
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
case right.location.loc of
|
case right.location.loc of
|
||||||
LOC_REGISTER,
|
LOC_REGISTER,
|
||||||
LOC_CREGISTER:
|
LOC_CREGISTER:
|
||||||
@ -444,14 +472,23 @@ implementation
|
|||||||
LOC_REGISTER,
|
LOC_REGISTER,
|
||||||
LOC_CREGISTER:
|
LOC_CREGISTER:
|
||||||
begin
|
begin
|
||||||
hr3:=rg.makeregsize(left.location.register,OS_INT);
|
hr3.enum:=R_INTREGISTER;
|
||||||
|
hr3.number:=(left.location.register.number and not $ff) or R_SUBWHOLE;
|
||||||
cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,hr3);
|
cg.a_load_reg_reg(exprasmlist,left.location.size,OS_INT,left.location.register,hr3);
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,hr3,hr);
|
cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,hr3,hr);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
hr:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
hr:=cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),
|
cg.a_load_ref_reg(exprasmlist,def_cgsize(left.resulttype.def),
|
||||||
left.location.reference,hr);
|
left.location.reference,hr);
|
||||||
location_release(exprasmlist,left.location);
|
location_release(exprasmlist,left.location);
|
||||||
@ -496,7 +533,11 @@ implementation
|
|||||||
internalerror(2002032210);
|
internalerror(2002032210);
|
||||||
end;
|
end;
|
||||||
{ free bitnumber register }
|
{ free bitnumber register }
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,hr);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,hr);
|
cg.free_scratch_reg(exprasmlist,hr);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -683,9 +724,17 @@ implementation
|
|||||||
begin
|
begin
|
||||||
last:=0;
|
last:=0;
|
||||||
first:=true;
|
first:=true;
|
||||||
|
{$ifdef newra}
|
||||||
|
scratch_reg:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else newra}
|
||||||
scratch_reg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
scratch_reg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
|
||||||
|
{$endif}
|
||||||
genitem(hp);
|
genitem(hp);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(exprasmlist,scratch_reg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(exprasmlist,scratch_reg);
|
cg.free_scratch_reg(exprasmlist,scratch_reg);
|
||||||
|
{$endif}
|
||||||
cg.a_jmp_always(exprasmlist,elselabel);
|
cg.a_jmp_always(exprasmlist,elselabel);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1063,7 +1112,12 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.26 2003-02-19 22:00:14 daniel
|
Revision 1.27 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.26 2003/02/19 22:00:14 daniel
|
||||||
* Code generator converted to new register notation
|
* Code generator converted to new register notation
|
||||||
- Horribily outdated todo.txt removed
|
- Horribily outdated todo.txt removed
|
||||||
|
|
||||||
|
@ -52,8 +52,10 @@ interface
|
|||||||
procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
|
procedure location_force_reg(list: TAAsmoutput;var l:tlocation;dst_size:TCGSize;maybeconst:boolean);
|
||||||
procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
|
procedure location_force_mem(list: TAAsmoutput;var l:tlocation);
|
||||||
|
|
||||||
|
{$ifndef newra}
|
||||||
procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
|
procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
|
||||||
procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
|
procedure maybe_restore(list:taasmoutput;var l:tlocation;const s:tmaybesave);
|
||||||
|
{$endif}
|
||||||
function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
|
function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
|
||||||
|
|
||||||
procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
|
procedure push_value_para(list:taasmoutput;p:tnode;calloption:tproccalloption;
|
||||||
@ -607,6 +609,7 @@ implementation
|
|||||||
Maybe_Save
|
Maybe_Save
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
|
{$ifndef newra}
|
||||||
procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
|
procedure maybe_save(list:taasmoutput;needed:integer;var l:tlocation;var s:tmaybesave);
|
||||||
begin
|
begin
|
||||||
s.saved:=false;
|
s.saved:=false;
|
||||||
@ -707,6 +710,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
tg.ungetiftemp(list,s.ref);
|
tg.ungetiftemp(list,s.ref);
|
||||||
end;
|
end;
|
||||||
|
{$endif newra}
|
||||||
|
|
||||||
|
|
||||||
function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
|
function maybe_pushfpu(list:taasmoutput;needed : byte;var l:tlocation) : boolean;
|
||||||
@ -1064,11 +1068,19 @@ implementation
|
|||||||
vs_out :
|
vs_out :
|
||||||
begin
|
begin
|
||||||
reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
|
reference_reset_base(href,procinfo.framepointer,tvarsym(p).address+procinfo.para_offset);
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(list);
|
tmpreg:=cg.get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
||||||
reference_reset_base(href,tmpreg,0);
|
reference_reset_base(href,tmpreg,0);
|
||||||
cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
|
cg.g_initialize(list,tvarsym(p).vartype.def,href,false);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tmpreg);
|
cg.free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1518,14 +1530,22 @@ function returns in a register and the caller receives it in an other one}
|
|||||||
reference_reset_base(href,procinfo.framepointer,procinfo.inheritedflag_offset);
|
reference_reset_base(href,procinfo.framepointer,procinfo.inheritedflag_offset);
|
||||||
cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,inheriteddesctructorlabel);
|
cg.a_cmp_const_ref_label(list,OS_ADDR,OC_EQ,0,href,inheriteddesctructorlabel);
|
||||||
reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
|
reference_reset_base(href,procinfo.framepointer,procinfo.selfpointer_offset);
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else}
|
||||||
tmpreg:=cg.get_scratch_reg_address(list);
|
tmpreg:=cg.get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
||||||
cg.a_param_reg(list,OS_ADDR,tmpreg,paramanager.getintparaloc(1));
|
cg.a_param_reg(list,OS_ADDR,tmpreg,paramanager.getintparaloc(1));
|
||||||
reference_reset_base(href,tmpreg,0);
|
reference_reset_base(href,tmpreg,0);
|
||||||
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
||||||
reference_reset_base(href,tmpreg,72);
|
reference_reset_base(href,tmpreg,72);
|
||||||
cg.a_call_ref(list,href);
|
cg.a_call_ref(list,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tmpreg);
|
cg.free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
cg.a_label(list,inheriteddesctructorlabel);
|
cg.a_label(list,inheriteddesctructorlabel);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1801,11 +1821,19 @@ function returns in a register and the caller receives it in an other one}
|
|||||||
cg.a_load_ref_reg(list,OS_ADDR,href,r);
|
cg.a_load_ref_reg(list,OS_ADDR,href,r);
|
||||||
cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
|
cg.a_param_reg(list,OS_ADDR,r,paramanager.getintparaloc(1));
|
||||||
reference_reset_base(href,r,0);
|
reference_reset_base(href,r,0);
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else newra}
|
||||||
tmpreg:=cg.get_scratch_reg_address(list);
|
tmpreg:=cg.get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
cg.a_load_ref_reg(list,OS_ADDR,href,tmpreg);
|
||||||
reference_reset_base(href,tmpreg,68);
|
reference_reset_base(href,tmpreg,68);
|
||||||
cg.a_call_ref(list,href);
|
cg.a_call_ref(list,href);
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
cg.free_scratch_reg(list,tmpreg);
|
cg.free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
{ return the self pointer }
|
{ return the self pointer }
|
||||||
cg.a_label(list,inheritedconstructorlabel);
|
cg.a_label(list,inheritedconstructorlabel);
|
||||||
@ -2018,7 +2046,12 @@ function returns in a register and the caller receives it in an other one}
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.84 2003-04-16 09:26:55 jonas
|
Revision 1.85 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.84 2003/04/16 09:26:55 jonas
|
||||||
* assembler procedures now again get a stackframe if they have local
|
* assembler procedures now again get a stackframe if they have local
|
||||||
variables. No space is reserved for a function result however.
|
variables. No space is reserved for a function result however.
|
||||||
Also, the register parameters aren't automatically saved on the stack
|
Also, the register parameters aren't automatically saved on the stack
|
||||||
|
@ -70,12 +70,17 @@ unit rgcpu;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
rg := trgcpu.create;
|
rg := trgcpu.create(32); {PPC has 32 registers.}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.5 2003-02-19 22:00:16 daniel
|
Revision 1.6 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.5 2003/02/19 22:00:16 daniel
|
||||||
* Code generator converted to new register notation
|
* Code generator converted to new register notation
|
||||||
- Horribily outdated todo.txt removed
|
- Horribily outdated todo.txt removed
|
||||||
|
|
||||||
|
@ -373,10 +373,26 @@ implementation
|
|||||||
procinfo.aktproccode.insertlist(procinfo.aktentrycode);
|
procinfo.aktproccode.insertlist(procinfo.aktentrycode);
|
||||||
procinfo.aktproccode.concatlist(procinfo.aktexitcode);
|
procinfo.aktproccode.concatlist(procinfo.aktexitcode);
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
rg.writegraph;
|
{ rg.writegraph;}
|
||||||
{$endif}
|
{$endif}
|
||||||
if not(cs_no_regalloc in aktglobalswitches) then
|
if not(cs_no_regalloc in aktglobalswitches) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
{Do register allocation.}
|
||||||
|
repeat
|
||||||
|
rg.prepare_colouring;
|
||||||
|
rg.colour_registers;
|
||||||
|
rg.epilogue_colouring;
|
||||||
|
{Are there spilled registers? We cannot do that yet.}
|
||||||
|
if rg.spillednodes<>'' then
|
||||||
|
internalerror(200304221);
|
||||||
|
{if not try_fast_spill(rg) then
|
||||||
|
slow_spill(rg);
|
||||||
|
}
|
||||||
|
until rg.spillednodes='';
|
||||||
|
procinfo.aktproccode.translate_registers(rg.colour);
|
||||||
|
procinfo.aktproccode.convert_registers;
|
||||||
|
{$else newra}
|
||||||
procinfo.aktproccode.convert_registers;
|
procinfo.aktproccode.convert_registers;
|
||||||
{$ifndef NoOpt}
|
{$ifndef NoOpt}
|
||||||
if (cs_optimize in aktglobalswitches) and
|
if (cs_optimize in aktglobalswitches) and
|
||||||
@ -384,6 +400,7 @@ implementation
|
|||||||
((procinfo.flags and pi_is_assembler)=0) then
|
((procinfo.flags and pi_is_assembler)=0) then
|
||||||
optimize(procinfo.aktproccode);
|
optimize(procinfo.aktproccode);
|
||||||
{$endif NoOpt}
|
{$endif NoOpt}
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
{ save local data (casetable) also in the same file }
|
{ save local data (casetable) also in the same file }
|
||||||
if assigned(procinfo.aktlocaldata) and
|
if assigned(procinfo.aktlocaldata) and
|
||||||
@ -867,7 +884,12 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.98 2003-04-17 07:50:24 daniel
|
Revision 1.99 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.98 2003/04/17 07:50:24 daniel
|
||||||
* Some work on interference graph construction
|
* Some work on interference graph construction
|
||||||
|
|
||||||
Revision 1.97 2003/04/16 09:26:55 jonas
|
Revision 1.97 2003/04/16 09:26:55 jonas
|
||||||
|
@ -42,8 +42,7 @@ published by Cambridge University Press.
|
|||||||
Reading this book is recommended for a complete understanding. Here is a small
|
Reading this book is recommended for a complete understanding. Here is a small
|
||||||
introduction.
|
introduction.
|
||||||
|
|
||||||
The code generator thinks it has an infinite amount of registers. Our processor
|
The code generator thinks it has an infinite amount of registers. Our processorhas a limited amount of registers. Therefore we must reduce the amount of
|
||||||
has a limited amount of registers. Therefore we must reduce the amount of
|
|
||||||
registers until there are less enough to fit into the processors registers.
|
registers until there are less enough to fit into the processors registers.
|
||||||
|
|
||||||
Registers can interfere or not interfere. If two imaginary registers interfere
|
Registers can interfere or not interfere. If two imaginary registers interfere
|
||||||
@ -61,7 +60,7 @@ if two registers interfere there is a connection between them in the graph.
|
|||||||
In addition to the imaginary registers in the code generator, the psysical
|
In addition to the imaginary registers in the code generator, the psysical
|
||||||
CPU registers are also present in this graph. This allows us to make
|
CPU registers are also present in this graph. This allows us to make
|
||||||
interferences between imaginary registers and cpu registers. This is very
|
interferences between imaginary registers and cpu registers. This is very
|
||||||
usefull for describing archtectural constrains, like for example that
|
usefull for describing archtectural constraints, like for example that
|
||||||
the div instruction modifies edx, so variables that are in use at that time
|
the div instruction modifies edx, so variables that are in use at that time
|
||||||
cannot be stored into edx. This can be modelled by making edx interfere
|
cannot be stored into edx. This can be modelled by making edx interfere
|
||||||
with those variables.
|
with those variables.
|
||||||
@ -108,8 +107,21 @@ unit rgobj;
|
|||||||
end;
|
end;
|
||||||
Pinterferencegraph=^Tinterferencegraph;
|
Pinterferencegraph=^Tinterferencegraph;
|
||||||
|
|
||||||
|
Tmovelist=record
|
||||||
|
count:cardinal;
|
||||||
|
data:array[0..$ffff] of Tlinkedlistitem;
|
||||||
|
end;
|
||||||
|
Pmovelist=^Tmovelist;
|
||||||
|
|
||||||
|
{In the register allocator we keep track of move instructions.
|
||||||
|
These instructions are moved between five linked lists. There
|
||||||
|
is also a linked list per register to keep track about the moves
|
||||||
|
it is associated with. Because we need to determine quickly in
|
||||||
|
which of the five lists it is we add anu enumeradtion to each
|
||||||
|
move instruction.}
|
||||||
|
|
||||||
Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
|
Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
|
||||||
ms_worklist_moves,ms_activemoves);
|
ms_worklist_moves,ms_active_moves);
|
||||||
Tmoveins=class(Tlinkedlistitem)
|
Tmoveins=class(Tlinkedlistitem)
|
||||||
moveset:Tmoveset;
|
moveset:Tmoveset;
|
||||||
instruction:Taicpu;
|
instruction:Taicpu;
|
||||||
@ -129,7 +141,7 @@ unit rgobj;
|
|||||||
{ aren't currently allocated to a regvar. The "unusedregsxxx" }
|
{ aren't currently allocated to a regvar. The "unusedregsxxx" }
|
||||||
{ contain all registers of type "xxx" that aren't currenly }
|
{ contain all registers of type "xxx" that aren't currenly }
|
||||||
{ allocated }
|
{ allocated }
|
||||||
lastintreg:Tsuperregister;
|
lastintreg,maxintreg:Tsuperregister;
|
||||||
unusedregsint,usableregsint:Tsupregset;
|
unusedregsint,usableregsint:Tsupregset;
|
||||||
unusedregsaddr,usableregsaddr:Tsupregset;
|
unusedregsaddr,usableregsaddr:Tsupregset;
|
||||||
unusedregsfpu,usableregsfpu : tregisterset;
|
unusedregsfpu,usableregsfpu : tregisterset;
|
||||||
@ -161,12 +173,15 @@ unit rgobj;
|
|||||||
is_reg_var_int:Tsupregset;
|
is_reg_var_int:Tsupregset;
|
||||||
regvar_loaded: regvar_booleanarray;
|
regvar_loaded: regvar_booleanarray;
|
||||||
regvar_loaded_int: Tsupregset;
|
regvar_loaded_int: Tsupregset;
|
||||||
|
{$ifdef newra}
|
||||||
|
colour:array[Tsuperregister] of Tsuperregister;
|
||||||
|
spillednodes:string;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
{ tries to hold the amount of times which the current tree is processed }
|
{ tries to hold the amount of times which the current tree is processed }
|
||||||
t_times: longint;
|
t_times: longint;
|
||||||
|
|
||||||
constructor create;
|
constructor create(Acpu_registers:byte);
|
||||||
|
|
||||||
{# Allocate a general purpose register
|
{# Allocate a general purpose register
|
||||||
|
|
||||||
@ -245,7 +260,12 @@ unit rgobj;
|
|||||||
}
|
}
|
||||||
procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
|
procedure ungetreference(list: taasmoutput; const ref : treference); virtual;
|
||||||
|
|
||||||
{# Reset the register allocator information (usable registers etc) }
|
{# Reset the register allocator information (usable registers etc).
|
||||||
|
Please note that it is mortal sins to call cleartempgen during
|
||||||
|
graph colouring (that is between prepare_colouring and
|
||||||
|
epilogue_colouring).
|
||||||
|
}
|
||||||
|
|
||||||
procedure cleartempgen;virtual;
|
procedure cleartempgen;virtual;
|
||||||
|
|
||||||
{# Convert a register to a specified register size, and return that register size }
|
{# Convert a register to a specified register size, and return that register size }
|
||||||
@ -299,13 +319,26 @@ unit rgobj;
|
|||||||
procedure saveUnusedState(var state: pointer);virtual;
|
procedure saveUnusedState(var state: pointer);virtual;
|
||||||
procedure restoreUnusedState(var state: pointer);virtual;
|
procedure restoreUnusedState(var state: pointer);virtual;
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
|
{$ifdef ra_debug}
|
||||||
procedure writegraph;
|
procedure writegraph;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
procedure add_move_instruction(instr:Taicpu);
|
||||||
|
procedure prepare_colouring;
|
||||||
|
procedure epilogue_colouring;
|
||||||
|
procedure colour_registers;
|
||||||
|
{$endif newra}
|
||||||
protected
|
protected
|
||||||
|
cpu_registers:byte;
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
igraph:Tinterferencegraph;
|
igraph:Tinterferencegraph;
|
||||||
movelist:array[Tsuperregister] of Tlinkedlist;
|
degree:array[0..255] of byte;
|
||||||
worklistmoves:Tlinkedlist;
|
alias:array[Tsuperregister] of Tsuperregister;
|
||||||
|
simplifyworklist,freezeworklist,spillworklist:string;
|
||||||
|
coalescednodes:string;
|
||||||
|
selectstack:string;
|
||||||
|
movelist:array[Tsuperregister] of Pmovelist;
|
||||||
|
worklist_moves,active_moves,frozen_moves,
|
||||||
|
coalesced_moves,constrained_moves:Tlinkedlist;
|
||||||
{$endif}
|
{$endif}
|
||||||
{ the following two contain the common (generic) code for all }
|
{ the following two contain the common (generic) code for all }
|
||||||
{ get- and ungetregisterxxx functions/procedures }
|
{ get- and ungetregisterxxx functions/procedures }
|
||||||
@ -332,6 +365,23 @@ unit rgobj;
|
|||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
procedure add_edge(u,v:Tsuperregister);
|
procedure add_edge(u,v:Tsuperregister);
|
||||||
procedure add_edges_used(u:Tsuperregister);
|
procedure add_edges_used(u:Tsuperregister);
|
||||||
|
procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
|
||||||
|
function move_related(n:Tsuperregister):boolean;
|
||||||
|
procedure make_work_list;
|
||||||
|
procedure enable_moves(n:Tsuperregister);
|
||||||
|
procedure decrement_degree(m:Tsuperregister);
|
||||||
|
procedure simplify;
|
||||||
|
|
||||||
|
function get_alias(n:Tsuperregister):Tsuperregister;
|
||||||
|
procedure add_worklist(u:Tsuperregister);
|
||||||
|
function adjacent_ok(u,v:Tsuperregister):boolean;
|
||||||
|
function conservative(u,v:Tsuperregister):boolean;
|
||||||
|
procedure combine(u,v:Tsuperregister);
|
||||||
|
procedure coalesce;
|
||||||
|
procedure freeze_moves(u:Tsuperregister);
|
||||||
|
procedure freeze;
|
||||||
|
procedure select_spill;
|
||||||
|
procedure assign_colours;
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -415,7 +465,7 @@ unit rgobj;
|
|||||||
globals,verbose,
|
globals,verbose,
|
||||||
cgobj,tgobj,regvars;
|
cgobj,tgobj,regvars;
|
||||||
|
|
||||||
constructor trgobj.create;
|
constructor Trgobj.create(Acpu_registers:byte);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
usedinproc := [];
|
usedinproc := [];
|
||||||
@ -423,14 +473,17 @@ unit rgobj;
|
|||||||
t_times := 0;
|
t_times := 0;
|
||||||
resetusableregisters;
|
resetusableregisters;
|
||||||
lastintreg:=0;
|
lastintreg:=0;
|
||||||
|
maxintreg:=first_imreg;
|
||||||
|
cpu_registers:=Acpu_registers;
|
||||||
{$ifdef TEMPREGDEBUG}
|
{$ifdef TEMPREGDEBUG}
|
||||||
fillchar(reg_user,sizeof(reg_user),0);
|
fillchar(reg_user,sizeof(reg_user),0);
|
||||||
fillchar(reg_releaser,sizeof(reg_releaser),0);
|
fillchar(reg_releaser,sizeof(reg_releaser),0);
|
||||||
{$endif TEMPREGDEBUG}
|
{$endif TEMPREGDEBUG}
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
fillchar(igraph,sizeof(igraph),0);
|
fillchar(igraph,sizeof(igraph),0);
|
||||||
|
fillchar(degree,sizeof(degree),0);
|
||||||
fillchar(movelist,sizeof(movelist),0);
|
fillchar(movelist,sizeof(movelist),0);
|
||||||
worklistmoves.create;
|
worklist_moves:=Tlinkedlist.create;
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -487,6 +540,8 @@ unit rgobj;
|
|||||||
list.concat(Tai_regalloc.alloc(r));
|
list.concat(Tai_regalloc.alloc(r));
|
||||||
result:=r;
|
result:=r;
|
||||||
lastintreg:=i;
|
lastintreg:=i;
|
||||||
|
if i>maxintreg then
|
||||||
|
maxintreg:=i;
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
add_edges_used(i);
|
add_edges_used(i);
|
||||||
{$endif}
|
{$endif}
|
||||||
@ -749,6 +804,8 @@ unit rgobj;
|
|||||||
countunusedregsint:=countusableregsint;
|
countunusedregsint:=countusableregsint;
|
||||||
countunusedregsfpu:=countusableregsfpu;
|
countunusedregsfpu:=countusableregsfpu;
|
||||||
countunusedregsmm:=countusableregsmm;
|
countunusedregsmm:=countusableregsmm;
|
||||||
|
lastintreg:=0;
|
||||||
|
maxintreg:=first_imreg;
|
||||||
{$ifdef newra}
|
{$ifdef newra}
|
||||||
unusedregsint:=[0..255];
|
unusedregsint:=[0..255];
|
||||||
{$else}
|
{$else}
|
||||||
@ -762,10 +819,12 @@ unit rgobj;
|
|||||||
if igraph.adjlist[i]<>nil then
|
if igraph.adjlist[i]<>nil then
|
||||||
dispose(igraph.adjlist[i]);
|
dispose(igraph.adjlist[i]);
|
||||||
if movelist[i]<>nil then
|
if movelist[i]<>nil then
|
||||||
movelist[i].destroy;
|
dispose(movelist[i]);
|
||||||
end;
|
end;
|
||||||
|
fillchar(movelist,sizeof(movelist),0);
|
||||||
fillchar(igraph,sizeof(igraph),0);
|
fillchar(igraph,sizeof(igraph),0);
|
||||||
worklistmoves.destroy;
|
fillchar(degree,sizeof(degree),0);
|
||||||
|
worklist_moves.clear;
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1224,9 +1283,15 @@ unit rgobj;
|
|||||||
include(igraph.bitmap[v],u);
|
include(igraph.bitmap[v],u);
|
||||||
{Precoloured nodes are not stored in the interference graph.}
|
{Precoloured nodes are not stored in the interference graph.}
|
||||||
if not(u in [first_supreg..last_supreg]) then
|
if not(u in [first_supreg..last_supreg]) then
|
||||||
addadj(u,v);
|
begin
|
||||||
|
addadj(u,v);
|
||||||
|
inc(degree[u]);
|
||||||
|
end;
|
||||||
if not(v in [first_supreg..last_supreg]) then
|
if not(v in [first_supreg..last_supreg]) then
|
||||||
addadj(v,u);
|
begin
|
||||||
|
addadj(v,u);
|
||||||
|
inc(degree[v]);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1240,13 +1305,18 @@ unit rgobj;
|
|||||||
add_edge(u,i);
|
add_edge(u,i);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef ra_debug}
|
||||||
procedure Trgobj.writegraph;
|
procedure Trgobj.writegraph;
|
||||||
|
|
||||||
|
{This procedure writes out the current interference graph in the
|
||||||
|
register allocator.}
|
||||||
|
|
||||||
|
|
||||||
var f:text;
|
var f:text;
|
||||||
i,j:Tsuperregister;
|
i,j:Tsuperregister;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
assign(f,'igraph');
|
assign(f,'igraph'+char(48+random(10))+char(48+random(10)));
|
||||||
rewrite(f);
|
rewrite(f);
|
||||||
writeln(f,'Interference graph');
|
writeln(f,'Interference graph');
|
||||||
writeln(f);
|
writeln(f);
|
||||||
@ -1273,6 +1343,502 @@ unit rgobj;
|
|||||||
end;
|
end;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
procedure Trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if movelist[u]=nil then
|
||||||
|
begin
|
||||||
|
getmem(movelist[u],64);
|
||||||
|
movelist[u]^.count:=0;
|
||||||
|
end
|
||||||
|
else if (movelist[u]^.count and 15)=15 then
|
||||||
|
reallocmem(movelist[u],(movelist[u]^.count+1)*4+64);
|
||||||
|
movelist[u]^.data[movelist[u]^.count]:=data;
|
||||||
|
inc(movelist[u]^.count);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.add_move_instruction(instr:Taicpu);
|
||||||
|
|
||||||
|
{This procedure notifies a certain as a move instruction so the
|
||||||
|
register allocator can try to eliminate it.}
|
||||||
|
|
||||||
|
var i:Tmoveins;
|
||||||
|
ssupreg,dsupreg:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
i:=Tmoveins.create;
|
||||||
|
i.moveset:=ms_worklist_moves;
|
||||||
|
i.instruction:=instr;
|
||||||
|
worklist_moves.insert(i);
|
||||||
|
ssupreg:=instr.oper[0].reg.number shr 8;
|
||||||
|
add_to_movelist(ssupreg,i);
|
||||||
|
dsupreg:=instr.oper[1].reg.number shr 8;
|
||||||
|
add_to_movelist(dsupreg,i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Trgobj.move_related(n:Tsuperregister):boolean;
|
||||||
|
|
||||||
|
var i:cardinal;
|
||||||
|
|
||||||
|
begin
|
||||||
|
move_related:=false;
|
||||||
|
if movelist[n]<>nil then
|
||||||
|
begin
|
||||||
|
for i:=0 to movelist[n]^.count-1 do
|
||||||
|
if Tmoveins(movelist[n]^.data[i]).moveset in
|
||||||
|
[ms_worklist_moves,ms_active_moves] then
|
||||||
|
begin
|
||||||
|
move_related:=true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.make_work_list;
|
||||||
|
|
||||||
|
var n:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for n:=first_imreg to maxintreg do
|
||||||
|
if degree[n]>cpu_registers then
|
||||||
|
spillworklist:=spillworklist+char(n)
|
||||||
|
else if move_related(n) then
|
||||||
|
freezeworklist:=freezeworklist+char(n)
|
||||||
|
else
|
||||||
|
simplifyworklist:=simplifyworklist+char(n);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.prepare_colouring;
|
||||||
|
|
||||||
|
begin
|
||||||
|
make_work_list;
|
||||||
|
active_moves:=Tlinkedlist.create;
|
||||||
|
frozen_moves:=Tlinkedlist.create;
|
||||||
|
coalesced_moves:=Tlinkedlist.create;
|
||||||
|
constrained_moves:=Tlinkedlist.create;
|
||||||
|
fillchar(alias,sizeof(alias),0);
|
||||||
|
coalescednodes:='';
|
||||||
|
selectstack:='';
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.enable_moves(n:Tsuperregister);
|
||||||
|
|
||||||
|
var m:Tlinkedlistitem;
|
||||||
|
i:cardinal;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if movelist[n]<>nil then
|
||||||
|
for i:=0 to movelist[n]^.count-1 do
|
||||||
|
begin
|
||||||
|
m:=movelist[n]^.data[i];
|
||||||
|
if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
|
||||||
|
begin
|
||||||
|
if Tmoveins(m).moveset=ms_active_moves then
|
||||||
|
begin
|
||||||
|
{Move m from the set active_moves to the set worklist_moves.}
|
||||||
|
active_moves.remove(m);
|
||||||
|
Tmoveins(m).moveset:=ms_worklist_moves;
|
||||||
|
worklist_moves.concat(m);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.decrement_degree(m:Tsuperregister);
|
||||||
|
|
||||||
|
var adj:Pstring;
|
||||||
|
d:byte;
|
||||||
|
i:byte;
|
||||||
|
n:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
d:=degree[m];
|
||||||
|
dec(degree[m]);
|
||||||
|
if d=cpu_registers then
|
||||||
|
begin
|
||||||
|
{Enable moves for m.}
|
||||||
|
enable_moves(m);
|
||||||
|
{Enable moves for adjacent.}
|
||||||
|
adj:=igraph.adjlist[m];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
n:=adj^[i];
|
||||||
|
if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
|
||||||
|
enable_moves(Tsuperregister(n));
|
||||||
|
end;
|
||||||
|
{In case the node is in the spillworklist, delete it.}
|
||||||
|
delete(spillworklist,pos(char(m),spillworklist),1);
|
||||||
|
if move_related(m) then
|
||||||
|
freezeworklist:=freezeworklist+char(m)
|
||||||
|
else
|
||||||
|
simplifyworklist:=simplifyworklist+char(m);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.simplify;
|
||||||
|
|
||||||
|
var adj:Pstring;
|
||||||
|
i:byte;
|
||||||
|
m:char;
|
||||||
|
n:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{We need to take a random element out of the simplifyworklist. We take
|
||||||
|
the last element. Dirty code!}
|
||||||
|
n:=Tsuperregister(simplifyworklist[byte(simplifyworklist[0])]);
|
||||||
|
dec(simplifyworklist[0]);
|
||||||
|
{Push it on the selectstack.}
|
||||||
|
selectstack:=selectstack+char(n);
|
||||||
|
adj:=igraph.adjlist[n];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
m:=adj^[i];
|
||||||
|
if (pos(m,selectstack) or pos(m,coalescednodes))=0 then
|
||||||
|
decrement_degree(Tsuperregister(m));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Trgobj.get_alias(n:Tsuperregister):Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
while pos(char(n),coalescednodes)<>0 do
|
||||||
|
n:=alias[n];
|
||||||
|
get_alias:=n;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.add_worklist(u:Tsuperregister);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if not(u in [first_supreg..last_supreg]) and not move_related(u) and
|
||||||
|
(degree[u]<cpu_registers) then
|
||||||
|
begin
|
||||||
|
delete(freezeworklist,pos(char(u),freezeworklist),1);
|
||||||
|
simplifyworklist:=simplifyworklist+char(u);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
|
||||||
|
|
||||||
|
{Check wether u and v should be coalesced. u is precoloured.}
|
||||||
|
|
||||||
|
function ok(t,r:Tsuperregister):boolean;
|
||||||
|
|
||||||
|
begin
|
||||||
|
ok:=(degree[t]<cpu_registers) or
|
||||||
|
(t in [first_supreg..last_supreg]) or
|
||||||
|
(r in igraph.bitmap[t]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var adj:Pstring;
|
||||||
|
i:byte;
|
||||||
|
t:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
adjacent_ok:=true;
|
||||||
|
adj:=igraph.adjlist[v];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
t:=adj^[i];
|
||||||
|
if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
|
||||||
|
if not ok(Tsuperregister(t),u) then
|
||||||
|
begin
|
||||||
|
adjacent_ok:=false;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Trgobj.conservative(u,v:Tsuperregister):boolean;
|
||||||
|
|
||||||
|
var adj:Pstring;
|
||||||
|
done:set of char; {To prevent that we count nodes twice.}
|
||||||
|
i,k:byte;
|
||||||
|
n:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
k:=0;
|
||||||
|
done:=[];
|
||||||
|
adj:=igraph.adjlist[u];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
n:=adj^[i];
|
||||||
|
if (pos(n,selectstack) or pos(n,coalescednodes))=0 then
|
||||||
|
begin
|
||||||
|
include(done,n);
|
||||||
|
if degree[Tsuperregister(n)]>=cpu_registers then
|
||||||
|
inc(k);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
adj:=igraph.adjlist[v];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
n:=adj^[i];
|
||||||
|
if ((pos(n,selectstack) or pos(n,coalescednodes))=0) and
|
||||||
|
not (n in done) and
|
||||||
|
(degree[Tsuperregister(n)]>=cpu_registers) then
|
||||||
|
inc(k);
|
||||||
|
end;
|
||||||
|
conservative:=(k<cpu_registers);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.combine(u,v:Tsuperregister);
|
||||||
|
|
||||||
|
var add:boolean;
|
||||||
|
adj:Pstring;
|
||||||
|
i,p:byte;
|
||||||
|
n,o:cardinal;
|
||||||
|
t:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
p:=pos(char(v),freezeworklist);
|
||||||
|
if p<>0 then
|
||||||
|
delete(freezeworklist,p,1)
|
||||||
|
else
|
||||||
|
delete(spillworklist,pos(char(v),spillworklist),1);
|
||||||
|
coalescednodes:=coalescednodes+char(v);
|
||||||
|
alias[v]:=u;
|
||||||
|
|
||||||
|
{Combine both movelists. Since the movelists are sets, only add
|
||||||
|
elements that are not already present.}
|
||||||
|
for n:=0 to movelist[v]^.count-1 do
|
||||||
|
begin
|
||||||
|
add:=true;
|
||||||
|
for o:=0 to movelist[u]^.count-1 do
|
||||||
|
if movelist[u]^.data[o]=movelist[v]^.data[n] then
|
||||||
|
begin
|
||||||
|
add:=false;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
if add then
|
||||||
|
add_to_movelist(u,movelist[v]^.data[n]);
|
||||||
|
end;
|
||||||
|
enable_moves(v);
|
||||||
|
|
||||||
|
adj:=igraph.adjlist[v];
|
||||||
|
if adj<>nil then
|
||||||
|
for i:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
t:=adj^[i];
|
||||||
|
if (pos(t,selectstack) or pos(t,coalescednodes))=0 then
|
||||||
|
begin
|
||||||
|
add_edge(Tsuperregister(t),u);
|
||||||
|
decrement_degree(Tsuperregister(t));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
p:=pos(char(u),freezeworklist);
|
||||||
|
if (degree[u]>=cpu_registers) and (p<>0) then
|
||||||
|
begin
|
||||||
|
delete(freezeworklist,p,1);
|
||||||
|
spillworklist:=spillworklist+char(u);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.coalesce;
|
||||||
|
|
||||||
|
var m:Tmoveins;
|
||||||
|
x,y,u,v:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
m:=Tmoveins(worklist_moves.getfirst);
|
||||||
|
x:=get_alias(m.instruction.oper[0].reg.number shr 8);
|
||||||
|
y:=get_alias(m.instruction.oper[1].reg.number shr 8);
|
||||||
|
if y in [first_supreg..last_supreg] then
|
||||||
|
begin
|
||||||
|
u:=y;
|
||||||
|
v:=x;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
u:=x;
|
||||||
|
v:=y;
|
||||||
|
end;
|
||||||
|
if (u=v) then
|
||||||
|
begin
|
||||||
|
m.moveset:=ms_coalesced_moves; {Already coalesced.}
|
||||||
|
coalesced_moves.insert(m);
|
||||||
|
add_worklist(u);
|
||||||
|
end
|
||||||
|
{Do u and v interfere? In that case the move is constrained. Two
|
||||||
|
precoloured nodes interfere allways. If v is precoloured, by the above
|
||||||
|
code u is precoloured, thus interference...}
|
||||||
|
else if (v in [first_supreg..last_supreg]) or (u in igraph.bitmap[v]) then
|
||||||
|
begin
|
||||||
|
m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
|
||||||
|
constrained_moves.insert(m);
|
||||||
|
add_worklist(u);
|
||||||
|
add_worklist(v);
|
||||||
|
end
|
||||||
|
{Next test: is it possible and a good idea to coalesce??}
|
||||||
|
else if ((u in [first_supreg..last_supreg]) and adjacent_ok(u,v)) or
|
||||||
|
(not(u in [first_supreg..last_supreg]) and conservative(u,v)) then
|
||||||
|
begin
|
||||||
|
m.moveset:=ms_coalesced_moves; {Move coalesced!}
|
||||||
|
coalesced_moves.insert(m);
|
||||||
|
combine(u,v);
|
||||||
|
add_worklist(u);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
m.moveset:=ms_active_moves;
|
||||||
|
active_moves.insert(m);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.freeze_moves(u:Tsuperregister);
|
||||||
|
|
||||||
|
var i:cardinal;
|
||||||
|
m:Tlinkedlistitem;
|
||||||
|
v,x,y:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for i:=0 to movelist[u]^.count-1 do
|
||||||
|
begin
|
||||||
|
m:=movelist[u]^.data[i];
|
||||||
|
if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
|
||||||
|
begin
|
||||||
|
x:=Tmoveins(m).instruction.oper[0].reg.number shr 8;
|
||||||
|
y:=Tmoveins(m).instruction.oper[1].reg.number shr 8;
|
||||||
|
if get_alias(y)=get_alias(u) then
|
||||||
|
v:=get_alias(x)
|
||||||
|
else
|
||||||
|
v:=get_alias(y);
|
||||||
|
{Move m from active_moves/worklist_moves to frozen_moves.}
|
||||||
|
if Tmoveins(m).moveset=ms_active_moves then
|
||||||
|
active_moves.remove(m)
|
||||||
|
else
|
||||||
|
worklist_moves.remove(m);
|
||||||
|
Tmoveins(m).moveset:=ms_frozen_moves;
|
||||||
|
frozen_moves.insert(m);
|
||||||
|
|
||||||
|
if not(move_related(v)) and (degree[v]<cpu_registers) then
|
||||||
|
begin
|
||||||
|
delete(freezeworklist,pos(char(v),freezeworklist),1);
|
||||||
|
simplifyworklist:=simplifyworklist+char(v);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.freeze;
|
||||||
|
|
||||||
|
var n:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{We need to take a random element out of the freezeworklist. We take
|
||||||
|
the last element. Dirty code!}
|
||||||
|
n:=Tsuperregister(freezeworklist[byte(freezeworklist[0])]);
|
||||||
|
dec(freezeworklist[0]);
|
||||||
|
{Add it to the simplifyworklist.}
|
||||||
|
simplifyworklist:=simplifyworklist+char(n);
|
||||||
|
freeze_moves(n);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.select_spill;
|
||||||
|
|
||||||
|
var n:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
{This code is WAY too naive. We need not to select just a register, but
|
||||||
|
the register that is used the least...}
|
||||||
|
n:=spillworklist[byte(spillworklist[0])];
|
||||||
|
dec(spillworklist[0]);
|
||||||
|
simplifyworklist:=simplifyworklist+n;
|
||||||
|
freeze_moves(Tsuperregister(n));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.assign_colours;
|
||||||
|
|
||||||
|
{Assign_colours assigns the actual colours to the registers.}
|
||||||
|
|
||||||
|
var adj:Pstring;
|
||||||
|
i,j,k:byte;
|
||||||
|
n,a:Tsuperregister;
|
||||||
|
adj_colours,colourednodes:set of Tsuperregister;
|
||||||
|
w:char;
|
||||||
|
|
||||||
|
begin
|
||||||
|
spillednodes:='';
|
||||||
|
{Colour the cpu registers...}
|
||||||
|
colourednodes:=[first_supreg..last_supreg];
|
||||||
|
for i:=first_supreg to last_supreg do
|
||||||
|
colour[i]:=i;
|
||||||
|
{Now colour the imaginary registers on the select-stack.}
|
||||||
|
for i:=length(selectstack) downto 1 do
|
||||||
|
begin
|
||||||
|
n:=Tsuperregister(selectstack[i]);
|
||||||
|
{Create a list of colours that we cannot assign to n.}
|
||||||
|
adj_colours:=[];
|
||||||
|
adj:=igraph.adjlist[n];
|
||||||
|
if adj<>nil then
|
||||||
|
for j:=1 to length(adj^) do
|
||||||
|
begin
|
||||||
|
w:=adj^[j];
|
||||||
|
a:=get_alias(Tsuperregister(w));
|
||||||
|
if a in colourednodes then
|
||||||
|
include(adj_colours,colour[a]);
|
||||||
|
end;
|
||||||
|
{Assume a spill by default...}
|
||||||
|
spillednodes:=spillednodes+char(n);
|
||||||
|
{Search for a colour not in this list.}
|
||||||
|
for k:=1 to cpu_registers do
|
||||||
|
if not(k in adj_colours) then
|
||||||
|
begin
|
||||||
|
colour[n]:=k;
|
||||||
|
dec(spillednodes[0]); {Colour found: no spill.}
|
||||||
|
include(colourednodes,n);
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{Finally colour the nodes that were coalesced.}
|
||||||
|
for i:=1 to length(coalescednodes) do
|
||||||
|
begin
|
||||||
|
n:=Tsuperregister(coalescednodes[i]);
|
||||||
|
colour[n]:=colour[get_alias(n)];
|
||||||
|
end;
|
||||||
|
for i:=first_imreg to maxintreg do
|
||||||
|
writeln(i:4,' ',colour[i]:4)
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.colour_registers;
|
||||||
|
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
if length(simplifyworklist)<>0 then
|
||||||
|
simplify
|
||||||
|
else if not(worklist_moves.empty) then
|
||||||
|
coalesce
|
||||||
|
else if length(freezeworklist)<>0 then
|
||||||
|
freeze
|
||||||
|
else if length(spillworklist)<>0 then
|
||||||
|
select_spill;
|
||||||
|
until (length(simplifyworklist) or
|
||||||
|
byte(not(worklist_moves.empty)) or
|
||||||
|
length(freezeworklist) or
|
||||||
|
length(spillworklist)
|
||||||
|
)=0;
|
||||||
|
assign_colours;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.epilogue_colouring;
|
||||||
|
|
||||||
|
begin
|
||||||
|
active_moves.destroy;
|
||||||
|
active_moves:=nil;
|
||||||
|
frozen_moves.destroy;
|
||||||
|
frozen_moves:=nil;
|
||||||
|
coalesced_moves.destroy;
|
||||||
|
coalesced_moves:=nil;
|
||||||
|
constrained_moves.destroy;
|
||||||
|
constrained_moves:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$endif newra}
|
||||||
|
|
||||||
|
|
||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
TReference
|
TReference
|
||||||
@ -1403,7 +1969,12 @@ end.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.35 2003-04-21 19:16:49 peter
|
Revision 1.36 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.35 2003/04/21 19:16:49 peter
|
||||||
* count address regs separate
|
* count address regs separate
|
||||||
|
|
||||||
Revision 1.34 2003/04/17 16:48:21 daniel
|
Revision 1.34 2003/04/17 16:48:21 daniel
|
||||||
|
@ -66,11 +66,16 @@ procedure trgcpu.UngetRegisterInt(list:taasmoutput;reg:tregister);
|
|||||||
inherited ungetregisterint(list,reg);
|
inherited ungetregisterint(list,reg);
|
||||||
end;
|
end;
|
||||||
begin
|
begin
|
||||||
rg := trgcpu.create;
|
rg := trgcpu.create(24); {24 registers.}
|
||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.8 2003-03-15 22:51:58 mazen
|
Revision 1.9 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.8 2003/03/15 22:51:58 mazen
|
||||||
* remaking sparc rtl compile
|
* remaking sparc rtl compile
|
||||||
|
|
||||||
Revision 1.7 2003/03/10 21:59:54 mazen
|
Revision 1.7 2003/03/10 21:59:54 mazen
|
||||||
|
@ -363,13 +363,24 @@ unit cgx86;
|
|||||||
OS_8,OS_S8,
|
OS_8,OS_S8,
|
||||||
OS_16,OS_S16:
|
OS_16,OS_S16:
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
if target_info.alignment.paraalign = 2 then
|
||||||
|
tmpreg:=rg.getregisterint(list,OS_16)
|
||||||
|
else
|
||||||
|
tmpreg:=rg.getregisterint(list,OS_32);
|
||||||
|
{$else}
|
||||||
if target_info.alignment.paraalign = 2 then
|
if target_info.alignment.paraalign = 2 then
|
||||||
tmpreg:=get_scratch_reg_int(list,OS_16)
|
tmpreg:=get_scratch_reg_int(list,OS_16)
|
||||||
else
|
else
|
||||||
tmpreg:=get_scratch_reg_int(list,OS_32);
|
tmpreg:=get_scratch_reg_int(list,OS_32);
|
||||||
|
{$endif}
|
||||||
a_load_ref_reg(list,size,r,tmpreg);
|
a_load_ref_reg(list,size,r,tmpreg);
|
||||||
list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
|
list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
OS_32,OS_S32:
|
OS_32,OS_S32:
|
||||||
list.concat(taicpu.op_ref(A_PUSH,S_L,r));
|
list.concat(taicpu.op_ref(A_PUSH,S_L,r));
|
||||||
@ -405,10 +416,18 @@ unit cgx86;
|
|||||||
list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
|
list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getaddressregister(list);
|
||||||
|
{$else}
|
||||||
tmpreg := get_scratch_reg_address(list);
|
tmpreg := get_scratch_reg_address(list);
|
||||||
|
{$endif}
|
||||||
a_loadaddr_ref_reg(list,r,tmpreg);
|
a_loadaddr_ref_reg(list,r,tmpreg);
|
||||||
list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
|
list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
|
||||||
|
{$ifdef newra}
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else}
|
||||||
free_scratch_reg(list,tmpreg);
|
free_scratch_reg(list,tmpreg);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -780,7 +799,9 @@ unit cgx86;
|
|||||||
regloadsize: tcgsize;
|
regloadsize: tcgsize;
|
||||||
dstsize: topsize;
|
dstsize: topsize;
|
||||||
tmpreg : tregister;
|
tmpreg : tregister;
|
||||||
|
{$ifndef newra}
|
||||||
popecx : boolean;
|
popecx : boolean;
|
||||||
|
{$endif}
|
||||||
r:Tregister;
|
r:Tregister;
|
||||||
instr:Taicpu;
|
instr:Taicpu;
|
||||||
|
|
||||||
@ -805,6 +826,13 @@ unit cgx86;
|
|||||||
internalerror(200109233);
|
internalerror(200109233);
|
||||||
OP_SHR,OP_SHL,OP_SAR:
|
OP_SHR,OP_SHL,OP_SAR:
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
tmpreg:=rg.getexplicitregisterint(list,NR_CL);
|
||||||
|
a_load_reg_reg(list,size,OS_8,dst,tmpreg);
|
||||||
|
list.concat(taicpu.op_reg_reg(Topcg2asmop[op],S_B,src,
|
||||||
|
tmpreg));
|
||||||
|
rg.ungetregisterint(list,tmpreg);
|
||||||
|
{$else newra}
|
||||||
tmpreg.enum:=R_INTREGISTER;
|
tmpreg.enum:=R_INTREGISTER;
|
||||||
tmpreg.number:=NR_NO;
|
tmpreg.number:=NR_NO;
|
||||||
popecx := false;
|
popecx := false;
|
||||||
@ -821,8 +849,6 @@ unit cgx86;
|
|||||||
regloadsize:=OS_32;
|
regloadsize:=OS_32;
|
||||||
end;
|
end;
|
||||||
tmpreg := get_scratch_reg_int(list,OS_INT);
|
tmpreg := get_scratch_reg_int(list,OS_INT);
|
||||||
tmpreg.enum:=R_INTREGISTER;
|
|
||||||
tmpreg.number:=NR_EDI;
|
|
||||||
a_load_reg_reg(list,regloadsize,regloadsize,src,tmpreg);
|
a_load_reg_reg(list,regloadsize,regloadsize,src,tmpreg);
|
||||||
end;
|
end;
|
||||||
if src.number shr 8<>RS_ECX then
|
if src.number shr 8<>RS_ECX then
|
||||||
@ -862,16 +888,13 @@ unit cgx86;
|
|||||||
list.concat(taicpu.op_reg(A_POP,S_L,r))
|
list.concat(taicpu.op_reg(A_POP,S_L,r))
|
||||||
else if not (dst.number shr 8=RS_ECX) then
|
else if not (dst.number shr 8=RS_ECX) then
|
||||||
rg.ungetregisterint(list,r);
|
rg.ungetregisterint(list,r);
|
||||||
|
{$endif newra}
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
if reg2opsize(src) <> dstsize then
|
if reg2opsize(src) <> dstsize then
|
||||||
internalerror(200109226);
|
internalerror(200109226);
|
||||||
instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
|
instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
|
||||||
{$ifdef newra}
|
|
||||||
if op in [_MOV,_XCHG] then
|
|
||||||
rg.add_move_instruction(instr);
|
|
||||||
{$endif newra}
|
|
||||||
list.concat(instr);
|
list.concat(instr);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1839,7 +1862,12 @@ unit cgx86;
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.38 2003-04-17 16:48:21 daniel
|
Revision 1.39 2003-04-22 10:09:35 daniel
|
||||||
|
+ Implemented the actual register allocator
|
||||||
|
+ Scratch registers unavailable when new register allocator used
|
||||||
|
+ maybe_save/maybe_restore unavailable when new register allocator used
|
||||||
|
|
||||||
|
Revision 1.38 2003/04/17 16:48:21 daniel
|
||||||
* Added some code to keep track of move instructions in register
|
* Added some code to keep track of move instructions in register
|
||||||
allocator
|
allocator
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user