* rg[tregistertype] added in tcg

This commit is contained in:
peter 2003-12-12 17:16:17 +00:00
parent 8b4a122d49
commit bce5a1e252
4 changed files with 289 additions and 351 deletions

View File

@ -59,7 +59,9 @@ unit cgobj;
sould be @link(tcg64f32) and not @var(tcg).
}
tcg = class
public
alignment : talignment;
rg : array[tregistertype] of trgobj;
t_times:cardinal;
{************************************************}
{ basic routines }
@ -71,28 +73,28 @@ unit cgobj;
procedure done_register_allocators;virtual;abstract;
{# Gets a register suitable to do integer operations on.}
function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;abstract;
function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
{# Gets a register suitable to do integer operations on.}
function getaddressregister(list:Taasmoutput):Tregister;virtual;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;abstract;
function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;abstract;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;
function getflagregister(list:Taasmoutput;size:Tcgsize):Tregister;virtual;abstract;
{Does the generic cg need SIMD registers, like getmmxregister? Or should
the cpu specific child cg object have such a method?}
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;abstract;
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
procedure ungetreference(list:Taasmoutput;const r:Treference);virtual;
procedure add_move_instruction(instr:Taicpu);virtual;abstract;
procedure add_move_instruction(instr:Taicpu);virtual;
function uses_registers(rt:Tregistertype):boolean;virtual;abstract;
function uses_registers(rt:Tregistertype):boolean;virtual;
{# Get a specific register.}
procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;abstract;
procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;
{# Get multiple registers specified.}
procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;abstract;
procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;
{# Free multiple registers specified.}
procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;abstract;
procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);virtual;
procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;abstract;
procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
function makeregsize(reg:Tregister;size:Tcgsize):Tregister;
@ -550,24 +552,74 @@ implementation
******************************************************************************}
constructor tcg.create;
begin
end;
begin
end;
function Tcg.makeregsize(reg:Tregister;size:Tcgsize):Tregister;
var
subreg:Tsubregister;
begin
subreg:=cgsize2subreg(size);
result:=reg;
setsubreg(result,subreg);
end;
var subreg:Tsubregister;
begin
subreg:=cgsize2subreg(size);
result:=reg;
setsubreg(result,subreg);
end;
{*****************************************************************************
register allocation
******************************************************************************}
function tcg.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
if not assigned(rg[R_INTREGISTER]) then
internalerror(200312122);
result:=rg[R_INTREGISTER].getregister(list,cgsize2subreg(size));
end;
function tcg.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
if not assigned(rg[R_FPUREGISTER]) then
internalerror(200312123);
result:=rg[R_FPUREGISTER].getregister(list,cgsize2subreg(size));
end;
function tcg.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
if not assigned(rg[R_MMREGISTER]) then
internalerror(200312124);
result:=rg[R_MMREGISTER].getregister(list,cgsize2subreg(size));
end;
function tcg.getaddressregister(list:Taasmoutput):Tregister;
begin
result:=getintregister(list,OS_ADDR);
if assigned(rg[R_ADDRESSREGISTER]) then
result:=rg[R_ADDRESSREGISTER].getregister(list,R_SUBWHOLE)
else
begin
if not assigned(rg[R_INTREGISTER]) then
internalerror(200312121);
result:=rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
end;
end;
procedure tcg.getexplicitregister(list:Taasmoutput;r:Tregister);
begin
if not assigned(rg[getregtype(r)]) then
internalerror(200312125);
rg[getregtype(r)].getexplicitregister(list,r);
end;
procedure tcg.ungetregister(list:Taasmoutput;r:Tregister);
begin
if not assigned(rg[getregtype(r)]) then
internalerror(200312126);
rg[getregtype(r)].ungetregister(list,r);
end;
@ -578,6 +630,61 @@ implementation
end;
procedure tcg.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
if assigned(rg[rt]) then
rg[rt].allocexplicitregisters(list,r)
else
internalerror(200310092);
end;
procedure tcg.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
if assigned(rg[rt]) then
rg[rt].deallocexplicitregisters(list,r)
else
internalerror(200310093);
end;
function tcg.uses_registers(rt:Tregistertype):boolean;
begin
if assigned(rg[rt]) then
result:=rg[rt].uses_registers
else
internalerror(200310094);
end;
procedure tcg.add_move_instruction(instr:Taicpu);
var
rt : tregistertype;
begin
rt:=getregtype(instr.oper[O_MOV_SOURCE]^.reg);
if assigned(rg[rt]) then
rg[rt].add_move_instruction(instr)
else
internalerror(200310095);
end;
procedure tcg.do_register_allocation(list:Taasmoutput;headertai:tai);
var
rt : tregistertype;
begin
for rt:=low(tregistertype) to high(tregistertype) do
begin
if assigned(rg[rt]) then
begin
rg[rt].check_unreleasedregs;
rg[rt].do_register_allocation(list,headertai);
rg[rt].translate_registers(list);
end;
end;
end;
procedure tcg.a_reg_alloc(list : taasmoutput;r : tregister);
begin
list.concat(tai_regalloc.alloc(r));
@ -619,11 +726,10 @@ implementation
end;
end;
procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
var
hr : tregister;
begin
hr:=getintregister(list,size);
a_load_const_reg(list,size,a,hr);
@ -1835,7 +1941,10 @@ finalization
end.
{
$Log$
Revision 1.137 2003-12-06 22:11:47 jonas
Revision 1.138 2003-12-12 17:16:17 peter
* rg[tregistertype] added in tcg
Revision 1.137 2003/12/06 22:11:47 jonas
+ allocate volatile registers around calls to procedures declared with
"saveregisters" on non-x86 processors

View File

@ -34,24 +34,10 @@ unit cgcpu;
type
tcgppc = class(tcg)
rgint,
rgflags,
rgmm,
rgfpu : trgcpu;
procedure init_register_allocators;override;
procedure done_register_allocators;override;
function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
procedure ungetregister(list:Taasmoutput;r:Tregister);override;
procedure ungetreference(list:Taasmoutput;const r:Treference);override;
procedure add_move_instruction(instr:Taicpu);override;
procedure do_register_allocation(list:Taasmoutput;headertai:tai);override;
procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
function uses_registers(rt:Tregistertype):boolean;override;
{ passing parameters, per default the parameter is pushed }
{ nr gives the number of the parameter (enumerated from }
@ -180,155 +166,37 @@ const
procedure tcgppc.init_register_allocators;
begin
rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
[RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,
RS_R9,RS_R10,RS_R11,RS_R12,RS_R31,RS_R30,RS_R29,
RS_R28,RS_R27,RS_R26,RS_R25,RS_R24,RS_R23,RS_R22,
RS_R21,RS_R20,RS_R19,RS_R18,RS_R17,RS_R16,RS_R15,
RS_R14,RS_R13],first_int_imreg,[]);
rgfpu:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
[RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,RS_F8,RS_F9,
RS_F10,RS_F11,RS_F12,RS_F13,RS_F31,RS_F30,RS_F29,RS_F28,RS_F27,
RS_F26,RS_F25,RS_F24,RS_F23,RS_F22,RS_F21,RS_F20,RS_F19,RS_F18,
RS_F17,RS_F16,RS_F15,RS_F14],first_fpu_imreg,[]);
{$warning FIX ME}
rgmm:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
[RS_M0,RS_M1,RS_M2],first_mm_imreg,[]);
end;
procedure tcgppc.done_register_allocators;
begin
rgint.free;
rgmm.free;
rgfpu.free;
end;
function tcgppc.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=rgint.getregister(list,cgsize2subreg(size));
end;
function tcgppc.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=rgfpu.getregister(list,R_SUBWHOLE);
end;
function tcgppc.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=rgmm.getregister(list,R_SUBNONE);
end;
procedure tcgppc.getexplicitregister(list:Taasmoutput;r:Tregister);
begin
case getregtype(r) of
R_INTREGISTER :
rgint.getexplicitregister(list,r);
R_MMREGISTER :
rgmm.getexplicitregister(list,r);
R_FPUREGISTER :
rgfpu.getexplicitregister(list,r);
else
internalerror(200310091);
end;
end;
procedure tcgppc.ungetregister(list:Taasmoutput;r:Tregister);
begin
case getregtype(r) of
R_INTREGISTER :
rgint.ungetregister(list,r);
R_FPUREGISTER :
rgfpu.ungetregister(list,r);
R_MMREGISTER :
rgmm.ungetregister(list,r);
else
internalerror(200310091);
end;
rg[R_INTREGISTER].free;
rg[R_FPUREGISTER].free;
rg[R_MMREGISTER].free;
end;
procedure tcgppc.ungetreference(list:Taasmoutput;const r:Treference);
begin
if r.base<>NR_NO then
rgint.ungetregister(list,r.base);
ungetregister(list,r.base);
if r.index<>NR_NO then
rgint.ungetregister(list,r.index);
end;
procedure tcgppc.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
case rt of
R_INTREGISTER :
rgint.allocexplicitregisters(list,r);
R_FPUREGISTER :
rgfpu.allocexplicitregisters(list,r);
R_MMREGISTER :
rgmm.allocexplicitregisters(list,r);
else
internalerror(200310092);
end;
end;
procedure tcgppc.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
case rt of
R_INTREGISTER :
rgint.deallocexplicitregisters(list,r);
R_FPUREGISTER :
rgfpu.deallocexplicitregisters(list,r);
R_MMREGISTER :
rgmm.deallocexplicitregisters(list,r);
else
internalerror(200310093);
end;
end;
function tcgppc.uses_registers(rt:Tregistertype):boolean;
begin
case rt of
R_INTREGISTER :
result:=rgint.uses_registers;
R_MMREGISTER :
result:=rgmm.uses_registers;
R_FPUREGISTER :
result:=rgfpu.uses_registers;
else
internalerror(200310094);
end;
end;
procedure tcgppc.add_move_instruction(instr:Taicpu);
begin
rgint.add_move_instruction(instr);
end;
procedure tcgppc.do_register_allocation(list:Taasmoutput;headertai:tai);
begin
{ Int }
rgint.check_unreleasedregs;
rgint.do_register_allocation(list,headertai);
rgint.translate_registers(list);
{ FPU }
rgfpu.check_unreleasedregs;
rgfpu.do_register_allocation(list,headertai);
rgfpu.translate_registers(list);
{ MM }
rgmm.check_unreleasedregs;
rgmm.do_register_allocation(list,headertai);
rgmm.translate_registers(list);
ungetregister(list,r.index);
end;
@ -367,10 +235,10 @@ const
reference_reset(ref);
ref.base:=locpara.reference.index;
ref.offset:=locpara.reference.offset;
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_ref_reg(list,size,size,r,tmpreg);
a_load_reg_ref(list,size,size,tmpreg,ref);
rgint.ungetregister(list,tmpreg);
rg[R_INTREGISTER].ungetregister(list,tmpreg);
end;
LOC_FPUREGISTER,LOC_CFPUREGISTER:
case size of
@ -399,10 +267,10 @@ const
reference_reset(ref);
ref.base := locpara.reference.index;
ref.offset := locpara.reference.offset;
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_loadaddr_ref_reg(list,r,tmpreg);
a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
rgint.ungetregister(list,tmpreg);
rg[R_INTREGISTER].ungetregister(list,tmpreg);
end;
else
internalerror(2002080701);
@ -438,14 +306,14 @@ const
{Generate instruction to load the procedure address from
the transition vector.}
//TODO: Support cross-TOC calls.
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
reference_reset(tmpref);
tmpref.offset := 0;
//tmpref.symaddr := refs_full;
tmpref.base:= reg;
list.concat(taicpu.op_reg_ref(A_LWZ,tmpreg,tmpref));
list.concat(taicpu.op_reg(A_MTCTR,tmpreg));
rgint.ungetregister(list,tmpreg);
rg[R_INTREGISTER].ungetregister(list,tmpreg);
end
else
list.concat(taicpu.op_reg(A_MTCTR,reg));
@ -506,7 +374,7 @@ const
op := storeinstr[tcgsize2unsigned[tosize],ref2.index<>NR_NO,false];
a_load_store(list,op,reg,ref2);
if freereg then
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
End;
@ -544,7 +412,7 @@ const
op := loadinstr[fromsize,ref2.index<>NR_NO,false];
a_load_store(list,op,reg,ref2);
if freereg then
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
{ sign extend shortint if necessary, since there is no }
{ load instruction that does that automatically (JM) }
if fromsize = OS_S8 then
@ -579,7 +447,7 @@ const
else internalerror(2002090901);
end;
list.concat(instr);
rgint.add_move_instruction(instr);
rg[R_INTREGISTER].add_move_instruction(instr);
end;
end;
@ -619,7 +487,7 @@ const
op := fpuloadinstr[size,ref2.index <> NR_NO,false];
a_load_store(list,op,reg,ref2);
if freereg then
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
end;
@ -643,7 +511,7 @@ const
op := fpustoreinstr[size,ref2.index <> NR_NO,false];
a_load_store(list,op,reg,ref2);
if freereg then
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
end;
@ -799,11 +667,11 @@ const
if gotrlwi and
(src = dst) then
begin
scratchreg := rgint.getregister(list,R_SUBWHOLE);
scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
list.concat(taicpu.op_reg_const(A_LI,scratchreg,-1));
list.concat(taicpu.op_reg_reg_const_const_const(A_RLWIMI,dst,
scratchreg,0,l1,l2));
rgint.ungetregister(list,scratchreg);
rg[R_INTREGISTER].ungetregister(list,scratchreg);
end
else
do_lo_hi;
@ -833,10 +701,10 @@ const
{ perform the operation }
if useReg then
begin
scratchreg := rgint.getregister(list,R_SUBWHOLE);
scratchreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_const_reg(list,OS_32,a,scratchreg);
a_op_reg_reg_reg(list,op,OS_32,scratchreg,src,dst);
rgint.ungetregister(list,scratchreg);
rg[R_INTREGISTER].ungetregister(list,scratchreg);
end;
end;
@ -881,20 +749,20 @@ const
list.concat(taicpu.op_reg_reg_const(A_CMPWI,NR_CR0,reg,longint(a)))
else
begin
scratch_register := rgint.getregister(list,R_SUBWHOLE);
scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_const_reg(list,OS_32,a,scratch_register);
list.concat(taicpu.op_reg_reg_reg(A_CMPW,NR_CR0,reg,scratch_register));
rgint.ungetregister(list,scratch_register);
rg[R_INTREGISTER].ungetregister(list,scratch_register);
end
else
if (a <= $ffff) then
list.concat(taicpu.op_reg_reg_const(A_CMPLWI,NR_CR0,reg,a))
else
begin
scratch_register := rgint.getregister(list,R_SUBWHOLE);
scratch_register := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_const_reg(list,OS_32,a,scratch_register);
list.concat(taicpu.op_reg_reg_reg(A_CMPLW,NR_CR0,reg,scratch_register));
rgint.ungetregister(list,scratch_register);
rg[R_INTREGISTER].ungetregister(list,scratch_register);
end;
a_jmp(list,A_BC,TOpCmp2AsmCond[cmp_op],0,l);
end;
@ -1088,7 +956,7 @@ const
{ FIXME: has to be R_F8 instad of R_F14 for SYSV abi }
for regcounter:=RS_F14 to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:= true;
firstregfpu:=regcounter;
@ -1100,7 +968,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
firstreggpr:=regcounter2;
@ -1183,7 +1051,7 @@ const
reference_reset_base(href,NR_R12,-8);
for regcounter:=firstregfpu to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
a_loadfpu_reg_ref(list,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
dec(href.offset,8);
@ -1209,7 +1077,7 @@ const
reference_reset_base(href,NR_R12,-4);
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
a_load_reg_ref(list,OS_INT,OS_INT,newreg(R_INTREGISTER,regcounter2,R_SUBNONE),href);
@ -1242,7 +1110,7 @@ const
cg.a_load_ref_ref(list,hp.paraloc[calleeside].size,hp.paraloc[calleeside].size,href2,href);
}
cg.a_load_ref_reg(list,hp.paraloc[calleeside].size,hp.paraloc[calleeside].size,href2,NR_R0);
cg.a_load_reg_ref(list,hp.paraloc[calleeside].size,hp.paraloc[calleeside].size,NR_R0,href);
cg.a_load_reg_ref(list,hp.paraloc[calleeside].size,hp.paraloc[calleeside].size,NR_R0,href);
end
{$ifdef dummy}
else if (hp.calleeparaloc.loc in [LOC_REGISTER,LOC_CREGISTER]) then
@ -1306,7 +1174,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter:=RS_F14 to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:=true;
firstregfpu:=regcounter;
@ -1318,7 +1186,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
firstreggpr:=regcounter2;
@ -1339,7 +1207,7 @@ const
reference_reset_base(href,NR_R12,-8);
for regcounter := firstregfpu to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
a_loadfpu_ref_reg(list,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
dec(href.offset,8);
@ -1352,7 +1220,7 @@ const
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
a_load_ref_reg(list,OS_INT,OS_INT,href,newreg(R_INTREGISTER,regcounter2,R_SUBNONE));
@ -1437,7 +1305,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter:=RS_F14 to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:=true;
firstregfpu:=regcounter;
@ -1448,7 +1316,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
firstreggpr:=regcounter2;
@ -1506,7 +1374,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter:=RS_F14 to RS_F31 do
begin
if regcounter in rgfpu.used_in_proc then
if regcounter in rg[R_FPUREGISTER].used_in_proc then
begin
usesfpr:=true;
firstregfpu:=regcounter;
@ -1518,7 +1386,7 @@ const
if not (po_assembler in current_procinfo.procdef.procoptions) then
for regcounter2:=RS_R13 to RS_R31 do
begin
if regcounter2 in rgint.used_in_proc then
if regcounter2 in rg[R_INTREGISTER].used_in_proc then
begin
usesgpr:=true;
firstreggpr:=regcounter2;
@ -1761,7 +1629,7 @@ const
ref2.base,tmpref));
if freereg then
begin
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
freereg := false;
end;
end
@ -1787,7 +1655,7 @@ const
(r <> ref2.base) then
list.concat(taicpu.op_reg_reg(A_MR,r,ref2.base));
if freereg then
rgint.ungetregister(list,ref2.base);
rg[R_INTREGISTER].ungetregister(list,ref2.base);
end;
{ ************* concatcopy ************ }
@ -1853,7 +1721,7 @@ const
{ load the address of source into src.base }
if loadref then
begin
src.base := rgint.getregister(list,R_SUBWHOLE);
src.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_ref_reg(list,OS_32,OS_32,source,src.base);
orgsrc := false;
end
@ -1862,7 +1730,7 @@ const
((source.index <> NR_NO) and
((source.offset + longint(len)) > high(smallint))) then
begin
src.base := rgint.getregister(list,R_SUBWHOLE);
src.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_loadaddr_ref_reg(list,source,src.base);
orgsrc := false;
end
@ -1879,7 +1747,7 @@ const
((dest.index <> NR_NO) and
((dest.offset + longint(len)) > high(smallint))) then
begin
dst.base := rgint.getregister(list,R_SUBWHOLE);
dst.base := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_loadaddr_ref_reg(list,dest,dst.base);
orgdst := false;
end
@ -1901,7 +1769,7 @@ const
inc(src.offset,8);
list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,8));
list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,8));
countreg := rgint.getregister(list,R_SUBWHOLE);
countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_const_reg(list,OS_32,count,countreg);
{ explicitely allocate R_0 since it can be used safely here }
{ (for holding date that's being copied) }
@ -1912,7 +1780,7 @@ const
list.concat(taicpu.op_reg_ref(A_LFDU,NR_F0,src));
list.concat(taicpu.op_reg_ref(A_STFDU,NR_F0,dst));
a_jmp(list,A_BC,C_NE,0,lab);
rgint.ungetregister(list,countreg);
rg[R_INTREGISTER].ungetregister(list,countreg);
a_reg_dealloc(list,NR_F0);
len := len mod 8;
end;
@ -1954,7 +1822,7 @@ const
inc(src.offset,4);
list.concat(taicpu.op_reg_reg_const(A_SUBI,src.base,src.base,4));
list.concat(taicpu.op_reg_reg_const(A_SUBI,dst.base,dst.base,4));
countreg := rgint.getregister(list,R_SUBWHOLE);
countreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load_const_reg(list,OS_32,count,countreg);
{ explicitely allocate R_0 since it can be used safely here }
{ (for holding date that's being copied) }
@ -1965,7 +1833,7 @@ const
list.concat(taicpu.op_reg_ref(A_LWZU,NR_R0,src));
list.concat(taicpu.op_reg_ref(A_STWU,NR_R0,dst));
a_jmp(list,A_BC,C_NE,0,lab);
rgint.ungetregister(list,countreg);
rg[R_INTREGISTER].ungetregister(list,countreg);
a_reg_dealloc(list,NR_R0);
len := len mod 4;
end;
@ -2009,9 +1877,9 @@ const
reference_release(list,source);
end
else
rgint.ungetregister(list,src.base);
rg[R_INTREGISTER].ungetregister(list,src.base);
if not orgdst then
rgint.ungetregister(list,dst.base);
rg[R_INTREGISTER].ungetregister(list,dst.base);
if delsource then
tg.ungetiftemp(list,source);
end;
@ -2153,13 +2021,13 @@ const
{ otherwise it may be overwritten (and it's still used afterwards) }
freeindex := false;
if (ref.index >= first_int_imreg) and
(supregset_in(rgint.unusedregs,getsupreg(ref.index))) then
(supregset_in(rg[R_INTREGISTER].unusedregs,getsupreg(ref.index))) then
begin
rgint.getexplicitregister(list,ref.index);
rg[R_INTREGISTER].getexplicitregister(list,ref.index);
orgindex := ref.index;
freeindex := true;
end;
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
if not assigned(ref.symbol) and
(cardinal(ref.offset-low(smallint)) <=
high(smallint)-low(smallint)) then
@ -2176,7 +2044,7 @@ const
end;
ref.base := tmpreg;
if freeindex then
rgint.ungetregister(list,orgindex);
rg[R_INTREGISTER].ungetregister(list,orgindex);
end
end
else
@ -2270,7 +2138,7 @@ const
largeOffset:= (cardinal(ref.offset-low(smallint)) >
high(smallint)-low(smallint));
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
tmpregUsed:= false;
if assigned(ref.symbol) then
@ -2321,7 +2189,7 @@ const
(cardinal(ref.offset-low(smallint)) >
high(smallint)-low(smallint)) then
begin
tmpreg := rgint.getregister(list,R_SUBWHOLE);
tmpreg := rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
reference_reset(tmpref);
tmpref.symbol := ref.symbol;
tmpref.offset := ref.offset;
@ -2340,7 +2208,7 @@ const
end;
if (tmpreg <> NR_NO) then
rgint.ungetregister(list,tmpreg);
rg[R_INTREGISTER].ungetregister(list,tmpreg);
end;
@ -2434,22 +2302,22 @@ const
end
else if ((value shr 32) = 0) then
begin
tmpreg := tcgppc(cg).rgint.getregister(list,R_SUBWHOLE);
tmpreg := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
cg.a_load_const_reg(list,OS_32,cardinal(value),tmpreg);
list.concat(taicpu.op_reg_reg_reg(ops[issub,2],
regdst.reglo,regsrc.reglo,tmpreg));
tcgppc(cg).rgint.ungetregister(list,tmpreg);
tcgppc(cg).rg[R_INTREGISTER].ungetregister(list,tmpreg);
list.concat(taicpu.op_reg_reg(ops[issub,3],
regdst.reghi,regsrc.reghi));
end
else
begin
tmpreg64.reglo := tcgppc(cg).rgint.getregister(list,R_SUBWHOLE);
tmpreg64.reghi := tcgppc(cg).rgint.getregister(list,R_SUBWHOLE);
tmpreg64.reglo := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
tmpreg64.reghi := tcgppc(cg).rg[R_INTREGISTER].getregister(list,R_SUBWHOLE);
a_load64_const_reg(list,value,tmpreg64);
a_op64_reg_reg_reg(list,op,tmpreg64,regsrc,regdst);
tcgppc(cg).rgint.ungetregister(list,tmpreg64.reglo);
tcgppc(cg).rgint.ungetregister(list,tmpreg64.reghi);
tcgppc(cg).rg[R_INTREGISTER].ungetregister(list,tmpreg64.reglo);
tcgppc(cg).rg[R_INTREGISTER].ungetregister(list,tmpreg64.reghi);
end
end
else
@ -2471,7 +2339,10 @@ begin
end.
{
$Log$
Revision 1.145 2003-12-10 00:09:57 karoly
Revision 1.146 2003-12-12 17:16:18 peter
* rg[tregistertype] added in tcg
Revision 1.145 2003/12/10 00:09:57 karoly
* fixed compilation with -dppc603
Revision 1.144 2003/12/09 20:39:43 jonas

View File

@ -176,17 +176,32 @@ unit rgobj;
end;
Preginfo=^TReginfo;
{ This is the base class used for a register allocator. }
trgbase=class
function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;abstract;
{# Get the register specified.}
procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;abstract;
{# Get multiple registers specified.}
procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
{# Free multiple registers specified.}
procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
function uses_registers:boolean;virtual;abstract;
{# Deallocate any kind of register }
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;abstract;
end;
{#------------------------------------------------------------------
This class implements the abstract register allocator. It is used by the
code generator to allocate and free registers which might be valid across
nodes. It also contains utility routines related to registers.
This class implements the default register allocator. It is used by the
code generator to allocate and free registers which might be valid
across nodes. It also contains utility routines related to registers.
Some of the methods in this class should be overriden
by cpu-specific implementations.
--------------------------------------------------------------------}
trgobj=class
trgobj=class(trgbase)
preserved_by_proc : tcpuregisterset;
used_in_proc : tcpuregisterset;
// is_reg_var : Tsuperregisterset; {old regvars}
@ -201,20 +216,20 @@ unit rgobj;
{# Allocate a register. An internalerror will be generated if there is
no more free registers which can be allocated.}
function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
procedure add_constraints(reg:Tregister);virtual;
function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;
{# Get the register specified.}
procedure getexplicitregister(list:Taasmoutput;r:Tregister);
procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;
{# Get multiple registers specified.}
procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
{# Free multiple registers specified.}
procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
function uses_registers:boolean;
procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
function uses_registers:boolean;virtual;
{# Deallocate any kind of register }
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
procedure add_constraints(reg:Tregister);virtual;
{# Do the register allocation.}
procedure do_register_allocation(list:Taasmoutput;headertai:tai);
procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
{ procedure resetusableregisters;virtual;}
@ -615,17 +630,21 @@ implementation
function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
var p:Tsuperregister;
r:Tregister;
begin
p:=getnewreg;
supregset_exclude(unusedregs,p);
r:=newreg(regtype,p,subreg);
list.concat(Tai_regalloc.alloc(r));
add_edges_used(p);
add_constraints(r);
result:=r;
end;
var
p : Tsuperregister;
r : Tregister;
begin
p:=getnewreg;
supregset_exclude(unusedregs,p);
if defaultsub=R_SUBNONE then
r:=newreg(regtype,p,R_SUBNONE)
else
r:=newreg(regtype,p,subreg);
list.concat(Tai_regalloc.alloc(r));
add_edges_used(p);
add_constraints(r);
result:=r;
end;
function trgobj.uses_registers:boolean;
@ -1818,7 +1837,10 @@ implementation
end.
{
$Log$
Revision 1.98 2003-12-04 23:27:32 peter
Revision 1.99 2003-12-12 17:16:17 peter
* rg[tregistertype] added in tcg
Revision 1.98 2003/12/04 23:27:32 peter
* remove redundant calls to add_edge_used
Revision 1.97 2003/11/29 17:36:41 peter

View File

@ -36,27 +36,20 @@ unit cgx86;
type
tcgx86 = class(tcg)
rgint,
rgmm : trgcpu;
rgfpu : Trgx86fpu;
procedure init_register_allocators;override;
procedure done_register_allocators;override;
function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
procedure ungetregister(list:Taasmoutput;r:Tregister);override;
procedure ungetreference(list:Taasmoutput;const r:Treference);override;
procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
function uses_registers(rt:Tregistertype):boolean;override;
procedure add_move_instruction(instr:Taicpu);override;
procedure dec_fpu_stack;
procedure inc_fpu_stack;
procedure do_register_allocation(list:Taasmoutput;headertai:tai);override;
{ passing parameters, per default the parameter is pushed }
{ nr gives the number of the parameter (enumerated from }
{ left to right), this allows to move the parameter to }
@ -176,123 +169,77 @@ unit cgx86;
procedure Tcgx86.init_register_allocators;
begin
if cs_create_pic in aktmoduleswitches then
rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
else
rgint:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
rgmm:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
rgfpu:=Trgx86fpu.create;
end;
procedure Tcgx86.done_register_allocators;
begin
rgint.free;
rgmm.free;
rg[R_INTREGISTER].free;
rg[R_INTREGISTER]:=nil;
rg[R_MMREGISTER].free;
rg[R_MMREGISTER]:=nil;
rgfpu.free;
end;
function Tcgx86.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=rgint.getregister(list,cgsize2subreg(size));
end;
function Tcgx86.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=trgx86fpu(rgfpu).getregisterfpu(list);
end;
function Tcgx86.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
begin
result:=rgmm.getregister(list,R_SUBNONE);
result:=rgfpu.getregisterfpu(list);
end;
procedure Tcgx86.getexplicitregister(list:Taasmoutput;r:Tregister);
begin
case getregtype(r) of
R_INTREGISTER :
rgint.getexplicitregister(list,r);
R_SSEREGISTER :
rgmm.getexplicitregister(list,r);
else
internalerror(200310091);
end;
if getregtype(r)=R_FPUREGISTER then
internalerror(2003121210)
else
inherited getexplicitregister(list,r);
end;
procedure tcgx86.ungetregister(list:Taasmoutput;r:Tregister);
begin
case getregtype(r) of
R_INTREGISTER :
rgint.ungetregister(list,r);
R_FPUREGISTER :
rgfpu.ungetregisterfpu(list,r);
R_SSEREGISTER :
rgmm.ungetregister(list,r);
else
internalerror(200310091);
end;
if getregtype(r)=R_FPUREGISTER then
rgfpu.ungetregisterfpu(list,r)
else
inherited ungetregister(list,r);
end;
procedure tcgx86.ungetreference(list:Taasmoutput;const r:Treference);
begin
if r.base<>NR_NO then
rgint.ungetregister(list,r.base);
ungetregister(list,r.base);
if r.index<>NR_NO then
rgint.ungetregister(list,r.index);
ungetregister(list,r.index);
end;
procedure Tcgx86.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
case rt of
R_INTREGISTER :
rgint.allocexplicitregisters(list,r);
R_SSEREGISTER :
rgmm.allocexplicitregisters(list,r);
R_FPUREGISTER :
else
internalerror(200310092);
end;
if rt<>R_FPUREGISTER then
inherited allocexplicitregisters(list,rt,r);
end;
procedure Tcgx86.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
case rt of
R_INTREGISTER :
rgint.deallocexplicitregisters(list,r);
R_SSEREGISTER :
rgmm.deallocexplicitregisters(list,r);
R_FPUREGISTER :
else
internalerror(200310093);
end;
if rt<>R_FPUREGISTER then
inherited deallocexplicitregisters(list,rt,r);
end;
function Tcgx86.uses_registers(rt:Tregistertype):boolean;
begin
case rt of
R_INTREGISTER :
result:=rgint.uses_registers;
R_SSEREGISTER :
result:=rgmm.uses_registers;
R_FPUREGISTER :
result:=false;
else
internalerror(200310094);
end;
end;
procedure Tcgx86.add_move_instruction(instr:Taicpu);
begin
rgint.add_move_instruction(instr);
if rt=R_FPUREGISTER then
result:=false
else
result:=inherited uses_registers(rt);
end;
@ -308,20 +255,6 @@ unit cgx86;
end;
procedure Tcgx86.do_register_allocation(list:Taasmoutput;headertai:tai);
begin
{ Int }
rgint.check_unreleasedregs;
rgint.do_register_allocation(list,headertai);
rgint.translate_registers(list);
{ SSE }
rgmm.check_unreleasedregs;
rgmm.do_register_allocation(list,headertai);
rgmm.translate_registers(list);
end;
{****************************************************************************
This is private property, keep out! :)
****************************************************************************}
@ -706,7 +639,7 @@ unit cgx86;
instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
{Notify the register allocator that we have written a move instruction so
it can try to eliminate it.}
Tcgx86(cg).rgint.add_move_instruction(instr);
add_move_instruction(instr);
list.concat(instr);
end;
@ -1513,7 +1446,7 @@ unit cgx86;
list.concat(Tai_section.Create(sec_code));
list.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,pl,0,NR_EDX));
a_call_name(list,target_info.Cprefix+mcountprefix+'mcount');
include(rgint.used_in_proc,RS_EDX);
include(rg[R_INTREGISTER].used_in_proc,RS_EDX);
end;
system_i386_go32v2,system_i386_watcom:
@ -1575,7 +1508,7 @@ unit cgx86;
begin
list.concat(tai_regalloc.alloc(NR_EBP));
include(rgint.preserved_by_proc,RS_EBP);
include(rg[R_INTREGISTER].preserved_by_proc,RS_EBP);
list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EBP));
list.concat(Taicpu.op_reg_reg(A_MOV,S_L,NR_ESP,NR_EBP));
if localsize>0 then
@ -1633,36 +1566,36 @@ unit cgx86;
begin
{ Get temp }
size:=0;
if RS_EBX in rgint.used_in_proc then
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if RS_ESI in rgint.used_in_proc then
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if RS_EDI in rgint.used_in_proc then
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
inc(size,POINTER_SIZE);
if size>0 then
begin
tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
{ Copy registers to temp }
href:=current_procinfo.save_regs_ref;
if RS_EBX in rgint.used_in_proc then
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EBX,href);
inc(href.offset,POINTER_SIZE);
end;
if RS_ESI in rgint.used_in_proc then
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_ESI,href);
inc(href.offset,POINTER_SIZE);
end;
if RS_EDI in rgint.used_in_proc then
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EDI,href);
inc(href.offset,POINTER_SIZE);
end;
end;
include(rgint.preserved_by_proc,RS_EBX);
include(rgint.preserved_by_proc,RS_ESI);
include(rgint.preserved_by_proc,RS_EDI);
include(rg[R_INTREGISTER].preserved_by_proc,RS_EBX);
include(rg[R_INTREGISTER].preserved_by_proc,RS_ESI);
include(rg[R_INTREGISTER].preserved_by_proc,RS_EDI);
end;
@ -1672,17 +1605,17 @@ unit cgx86;
begin
{ Copy registers from temp }
href:=current_procinfo.save_regs_ref;
if RS_EBX in rgint.used_in_proc then
if RS_EBX in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EBX);
inc(href.offset,POINTER_SIZE);
end;
if RS_ESI in rgint.used_in_proc then
if RS_ESI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_ESI);
inc(href.offset,POINTER_SIZE);
end;
if RS_EDI in rgint.used_in_proc then
if RS_EDI in rg[R_INTREGISTER].used_in_proc then
begin
a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EDI);
inc(href.offset,POINTER_SIZE);
@ -1751,7 +1684,10 @@ unit cgx86;
end.
{
$Log$
Revision 1.89 2003-12-06 01:15:23 florian
Revision 1.90 2003-12-12 17:16:18 peter
* rg[tregistertype] added in tcg
Revision 1.89 2003/12/06 01:15:23 florian
* reverted Peter's alloctemp patch; hopefully properly
Revision 1.88 2003/12/03 23:13:20 peter