mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-05 05:58:02 +02:00
257 lines
9.9 KiB
ObjectPascal
257 lines
9.9 KiB
ObjectPascal
{
|
|
Copyright (c) 1998-2008 by Florian Klaempfl
|
|
|
|
This unit implements the Z80 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
|
|
R_SUBL,R_SUBH:
|
|
begin
|
|
{ Some registers have no 8-bit subregister }
|
|
supreg:=getsupreg(reg);
|
|
add_edge(supreg,RS_IX);
|
|
add_edge(supreg,RS_IY);
|
|
add_edge(supreg,RS_SP);
|
|
end;
|
|
else
|
|
;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
|
|
var
|
|
tmpref : treference;
|
|
helplist : TAsmList;
|
|
begin
|
|
if (spilltemp.base=NR_IX) and ((spilltemp.offset<-128) or (spilltemp.offset>127)) then
|
|
begin
|
|
helplist:=TAsmList.create;
|
|
|
|
helplist.concat(taicpu.op_reg(A_PUSH,NR_BC));
|
|
helplist.concat(taicpu.op_reg(A_PUSH,NR_IX));
|
|
helplist.concat(taicpu.op_reg(A_POP,NR_BC));
|
|
helplist.concat(taicpu.op_reg_const(A_LD,NR_IY,spilltemp.offset));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADD,NR_IY,NR_BC));
|
|
helplist.concat(taicpu.op_reg(A_POP,NR_BC));
|
|
reference_reset_base(tmpref,NR_IY,0,ctempposinvalid,1,[]);
|
|
helplist.concat(spilling_create_load(tmpref,tempreg));
|
|
|
|
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;
|
|
begin
|
|
if (spilltemp.base=NR_IX) and ((spilltemp.offset<-128) or (spilltemp.offset>127)) then
|
|
begin
|
|
helplist:=TAsmList.create;
|
|
|
|
helplist.concat(taicpu.op_reg(A_PUSH,NR_BC));
|
|
helplist.concat(taicpu.op_reg(A_PUSH,NR_IX));
|
|
helplist.concat(taicpu.op_reg(A_POP,NR_BC));
|
|
helplist.concat(taicpu.op_reg_const(A_LD,NR_IY,spilltemp.offset));
|
|
helplist.concat(taicpu.op_reg_reg(A_ADD,NR_IY,NR_BC));
|
|
helplist.concat(taicpu.op_reg(A_POP,NR_BC));
|
|
reference_reset_base(tmpref,NR_IY,0,ctempposinvalid,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 (spilltemp.offset<-128) or (spilltemp.offset>127) then
|
|
exit;
|
|
|
|
{ Replace 'ld orgreg,src' with 'ld spilltemp,src'
|
|
and 'ld dst,orgreg' with 'ld dst,spilltemp' }
|
|
with instr do
|
|
begin
|
|
if (opcode=A_LD) 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
|
|
instr.loadref(0,spilltemp);
|
|
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);
|
|
result:=true;
|
|
end;
|
|
end
|
|
{ Replace 'ld orgreg,const' with 'ld spilltemp,const' }
|
|
else if (opcode=A_LD) and (ops=2) and (oper[1]^.typ=top_const) and (oper[0]^.typ=top_reg) then
|
|
begin
|
|
if (getregtype(oper[0]^.reg)=regtype) and
|
|
(get_alias(getsupreg(oper[0]^.reg))=orgreg) then
|
|
begin
|
|
instr.loadref(0,spilltemp);
|
|
result:=true;
|
|
end;
|
|
end
|
|
{ Replace 'add A,orgreg' with 'add A,spilltemp'
|
|
and 'adc A,orgreg' with 'adc A,spilltemp'
|
|
and 'sub A,orgreg' with 'sub A,spilltemp'
|
|
and 'sbc A,orgreg' with 'sbc A,spilltemp'
|
|
and 'and A,orgreg' with 'and A,spilltemp'
|
|
and 'or A,orgreg' with 'or A,spilltemp'
|
|
and 'xor A,orgreg' with 'xor A,spilltemp'
|
|
and 'cp A,orgreg' with 'cp A,spilltemp' }
|
|
else if (opcode in [A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP]) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
|
|
begin
|
|
{ we don't really need to check whether the first register is 'A',
|
|
because that's the only register allowed as a destination for
|
|
these instructions }
|
|
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);
|
|
result:=true;
|
|
end;
|
|
end
|
|
{ Replace 'bit const,orgreg' with 'bit const,spilltemp'
|
|
and 'set const,orgreg' with 'set const,spilltemp'
|
|
and 'res const,orgreg' with 'res const,spilltemp' }
|
|
else if (opcode in [A_BIT,A_SET,A_RES]) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_const) then
|
|
begin
|
|
if (getregtype(oper[1]^.reg)=regtype) and
|
|
(get_alias(getsupreg(oper[1]^.reg))=orgreg) then
|
|
begin
|
|
instr.loadref(1,spilltemp);
|
|
result:=true;
|
|
end;
|
|
end
|
|
{ Replace 'inc orgreg' with 'inc spilltemp'
|
|
and 'dec orgreg' with 'dec spilltemp'
|
|
and 'add orgreg' with 'add spilltemp'
|
|
and 'adc orgreg' with 'adc spilltemp'
|
|
and 'sub orgreg' with 'sub spilltemp'
|
|
and 'sbc orgreg' with 'sbc spilltemp'
|
|
and 'and orgreg' with 'and spilltemp'
|
|
and 'or orgreg' with 'or spilltemp'
|
|
and 'xor orgreg' with 'xor spilltemp'
|
|
and 'cp orgreg' with 'cp spilltemp'
|
|
and 'rlc orgreg' with 'rlc spilltemp'
|
|
and 'rl orgreg' with 'rl spilltemp'
|
|
and 'rrc orgreg' with 'rrc spilltemp'
|
|
and 'rr orgreg' with 'rr spilltemp'
|
|
and 'sla orgreg' with 'sla spilltemp'
|
|
and 'sra orgreg' with 'sra spilltemp'
|
|
and 'srl orgreg' with 'srl spilltemp' }
|
|
else if (opcode in [A_INC,A_DEC,A_ADD,A_ADC,A_SUB,A_SBC,A_AND,A_OR,A_XOR,A_CP,
|
|
A_RLC,A_RL,A_RRC,A_RR,A_SLA,A_SRA,A_SRL]) and (ops=1) and (oper[0]^.typ=top_reg) then
|
|
begin
|
|
if (getregtype(oper[0]^.reg)=regtype) and
|
|
(get_alias(getsupreg(oper[0]^.reg))=orgreg) then
|
|
begin
|
|
instr.loadref(0,spilltemp);
|
|
result:=true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|