From d2a9308181e64e03d65fa69ad5b8773b02bb6ebb Mon Sep 17 00:00:00 2001 From: sergei Date: Fri, 3 Jan 2014 08:14:43 +0000 Subject: [PATCH] + SPARC: implemented register spill replacement. git-svn-id: trunk@26364 - --- compiler/rgobj.pas | 4 ++-- compiler/sparc/rgcpu.pas | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/compiler/rgobj.pas b/compiler/rgobj.pas index 4921a0b2ea..14e83e3727 100644 --- a/compiler/rgobj.pas +++ b/compiler/rgobj.pas @@ -2134,7 +2134,7 @@ unit rgobj; if not spilled then exit; -{$if defined(x86) or defined(mips)} +{$if defined(x86) or defined(mips) or defined(sparc)} { Try replacing the register with the spilltemp. This is useful only for the i386,x86_64 that support memory locations for several instructions @@ -2149,7 +2149,7 @@ unit rgobj; mustbespilled:=false; end; end; -{$endif defined(x86) or defined(mips)} +{$endif defined(x86) or defined(mips) or defined(sparc)} { There are registers that need are spilled. We generate the diff --git a/compiler/sparc/rgcpu.pas b/compiler/sparc/rgcpu.pas index 5297337ecf..fabbd3dd78 100644 --- a/compiler/sparc/rgcpu.pas +++ b/compiler/sparc/rgcpu.pas @@ -37,6 +37,7 @@ unit rgcpu; function get_spill_subreg(r : tregister) : tsubregister;override; procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override; procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override; + function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override; end; @@ -161,4 +162,53 @@ implementation inherited do_spill_written(list,pos,spilltemp,tempreg); end; + + function trgcpu.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean; + var + opidx: longint; + begin + result:=false; + { Replace 'mov src,orgreg' with 'st src,spilltemp' + and 'mov orgreg,dst' with 'ld spilltemp,dst' } + if (abs(spilltemp.offset)>4095) then + exit; + if ((regtype=R_INTREGISTER) and (instr.opcode<>A_MOV)) or + ((regtype=R_FPUREGISTER) and (instr.opcode<>A_FMOVs) and (instr.opcode<>A_FMOVd)) then + exit; + { Ignore mis-encoded stuff like 'mov %something,%y' } + if (instr.ops<>2) or + (instr.oper[0]^.typ<>top_reg) or + (instr.oper[1]^.typ<>top_reg) or + (getregtype(instr.oper[0]^.reg)<>regtype) or + (getregtype(instr.oper[1]^.reg)<>regtype) then + exit; + opidx:=-1; + if get_alias(getsupreg(instr.oper[0]^.reg))=orgreg then + begin + if (regtype=R_INTREGISTER) then + instr.opcode:=A_LD + else if (getsubreg(instr.oper[0]^.reg)=R_SUBFS) then + instr.opcode:=A_LDF + else + instr.opcode:=A_LDDF; + opidx:=0; + end + else if get_alias(getsupreg(instr.oper[1]^.reg))=orgreg then + begin + if (regtype=R_INTREGISTER) then + instr.opcode:=A_ST + else if (getsubreg(instr.oper[1]^.reg)=R_SUBFS) then + instr.opcode:=A_STF + else + instr.opcode:=A_STDF; + opidx:=1; + end + else + InternalError(2013061002); + instr.oper[opidx]^.typ:=top_ref; + new(instr.oper[opidx]^.ref); + instr.oper[opidx]^.ref^:=spilltemp; + result:=true; + end; + end.