mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-10 19:18:37 +02:00

from cpubase unit to a method in the tcg class. The reason for doing that is that this is now a standard part of the 16-bit and 8-bit code generators and moving to the tcg class allows doing extra checks (not done yet, but for example, in the future, we can keep track of whether there was an extra register allocated with getintregister and halt with an internalerror in case GetNextReg() is called for registers, which weren't allocated as a part of a sequence, therefore catching a certain class of 8-bit and 16-bit code generator bugs at compile time, instead of generating wrong code). - removed GetLastReg() from avr's cpubase unit, because it isn't used for anything. It might be added to the tcg class, in case it's ever needed, but for now I've left it out. * GetOffsetReg() and GetOffsetReg64() were also moved to the tcg unit. git-svn-id: trunk@37180 -
207 lines
6.7 KiB
ObjectPascal
207 lines
6.7 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2008 by Florian Klaempfl
|
|
|
|
This unit implements the avr specific class for the register
|
|
allocator
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
****************************************************************************
|
|
}
|
|
|
|
unit rgcpu;
|
|
|
|
{$i fpcdefs.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
aasmbase,aasmtai,aasmdata,aasmcpu,aasmsym,
|
|
cgbase,cgutils,
|
|
cpubase,
|
|
rgobj;
|
|
|
|
type
|
|
trgcpu = class(trgobj)
|
|
procedure add_constraints(reg:tregister);override;
|
|
procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
|
|
procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
|
|
function do_spill_replace(list : TAsmList;instr : tai_cpu_abstract_sym; orgreg : tsuperregister;const spilltemp : treference) : boolean; override;
|
|
end;
|
|
|
|
trgintcpu = class(trgcpu)
|
|
procedure add_cpu_interferences(p : tai);override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
verbose, cutils,
|
|
cgobj,
|
|
procinfo;
|
|
|
|
|
|
procedure trgcpu.add_constraints(reg:tregister);
|
|
var
|
|
supreg,i : Tsuperregister;
|
|
begin
|
|
case getsubreg(reg) of
|
|
{ Let 64bit floats conflict with all odd float regs }
|
|
R_SUBFD:
|
|
begin
|
|
{
|
|
supreg:=getsupreg(reg);
|
|
i:=RS_F1;
|
|
while (i<=RS_F31) do
|
|
begin
|
|
add_edge(supreg,i);
|
|
inc(i,2);
|
|
end;
|
|
}
|
|
end;
|
|
{ Let 64bit ints conflict with all odd int regs }
|
|
R_SUBQ:
|
|
begin
|
|
supreg:=getsupreg(reg);
|
|
{
|
|
i:=RS_G1;
|
|
while (i<=RS_I7) do
|
|
begin
|
|
add_edge(supreg,i);
|
|
inc(i,2);
|
|
end;
|
|
}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
|
|
var
|
|
helpins : tai;
|
|
tmpref : treference;
|
|
helplist : TAsmList;
|
|
hreg : tregister;
|
|
begin
|
|
if abs(spilltemp.offset)>63 then
|
|
begin
|
|
helplist:=TAsmList.create;
|
|
|
|
helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
|
|
helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
|
|
|
|
reference_reset_base(tmpref,NR_R26,0,1,[]);
|
|
helpins:=spilling_create_load(tmpref,tempreg);
|
|
helplist.concat(helpins);
|
|
list.insertlistafter(pos,helplist);
|
|
helplist.free;
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
|
|
|
|
procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
|
|
var
|
|
tmpref : treference;
|
|
helplist : TAsmList;
|
|
hreg : tregister;
|
|
begin
|
|
if abs(spilltemp.offset)>63 then
|
|
begin
|
|
helplist:=TAsmList.create;
|
|
|
|
helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
|
|
helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
|
|
|
|
reference_reset_base(tmpref,NR_R26,0,1,[]);
|
|
helplist.concat(spilling_create_store(tempreg,tmpref));
|
|
list.insertlistafter(pos,helplist);
|
|
helplist.free;
|
|
end
|
|
else
|
|
inherited;
|
|
end;
|
|
|
|
|
|
procedure trgintcpu.add_cpu_interferences(p : tai);
|
|
var
|
|
r : tsuperregister;
|
|
begin
|
|
if p.typ=ait_instruction then
|
|
begin
|
|
case taicpu(p).opcode of
|
|
A_CPI,
|
|
A_ANDI,
|
|
A_ORI,
|
|
A_SUBI,
|
|
A_SBCI,
|
|
A_LDI:
|
|
for r:=RS_R0 to RS_R15 do
|
|
add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
|
|
A_MULS:
|
|
begin
|
|
for r:=RS_R0 to RS_R15 do
|
|
add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
|
|
for r:=RS_R0 to RS_R15 do
|
|
add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean;
|
|
var
|
|
b : byte;
|
|
begin
|
|
result:=false;
|
|
if not(spilltemp.offset in [0..63]) then
|
|
exit;
|
|
|
|
{ Replace 'mov dst,orgreg' with 'ld dst,spilltemp'
|
|
and 'mov orgreg,src' with 'st dst,spilltemp' }
|
|
with instr do
|
|
begin
|
|
if (opcode=A_MOV) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
|
|
begin
|
|
if (getregtype(oper[0]^.reg)=regtype) and
|
|
(get_alias(getsupreg(oper[0]^.reg))=orgreg) and
|
|
(get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
|
|
begin
|
|
{ str expects the register in oper[0] }
|
|
instr.loadreg(0,oper[1]^.reg);
|
|
instr.loadref(1,spilltemp);
|
|
opcode:=A_ST;
|
|
result:=true;
|
|
end
|
|
else if (getregtype(oper[1]^.reg)=regtype) and
|
|
(get_alias(getsupreg(oper[1]^.reg))=orgreg) and
|
|
(get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
|
|
begin
|
|
instr.loadref(1,spilltemp);
|
|
opcode:=A_LD;
|
|
result:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|