1 { 2 Copyright (c) 1998-2002 by Florian Klaempfl 3 4 This unit implements the SPARC specific class for the register 5 allocator 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21 ****************************************************************************} 22 unit rgcpu; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 aasmbase,aasmcpu,aasmtai,aasmsym,aasmdata, 30 cgbase,cgutils, 31 cpubase, 32 rgobj; 33 34 type 35 trgcpu=class(trgobj) 36 procedure add_constraints(reg:tregister);override; get_spill_subregnull37 function get_spill_subreg(r : tregister) : tsubregister;override; 38 procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override; 39 procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override; do_spill_replacenull40 function do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean; override; 41 end; 42 43 44 implementation 45 46 uses 47 verbose,cutils, 48 globtype, 49 cgobj; 50 51 procedure trgcpu.add_constraints(reg:tregister); 52 var 53 supreg,i : Tsuperregister; 54 begin 55 case getsubreg(reg) of 56 { Let 64bit floats conflict with all odd float regs } 57 R_SUBFD: 58 begin 59 supreg:=getsupreg(reg); 60 i:=RS_F1; 61 while (i<=RS_F31) do 62 begin 63 add_edge(supreg,i); 64 inc(i,2); 65 end; 66 end; 67 { Let 64bit ints conflict with all odd int regs } 68 R_SUBQ: 69 begin 70 supreg:=getsupreg(reg); 71 i:=RS_G1; 72 while (i<=RS_I7) do 73 begin 74 add_edge(supreg,i); 75 inc(i,2); 76 end; 77 end; 78 end; 79 end; 80 81 trgcpu.get_spill_subregnull82 function trgcpu.get_spill_subreg(r : tregister) : tsubregister; 83 begin 84 if getregtype(r)=R_FPUREGISTER then 85 result:=getsubreg(r) 86 else 87 result:=defaultsub; 88 end; 89 90 91 procedure trgcpu.do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); 92 var 93 helpins : tai; 94 tmpref : treference; 95 helplist : TAsmList; 96 hreg : tregister; 97 begin 98 if abs(spilltemp.offset)>4095 then 99 begin 100 helplist:=TAsmList.create; 101 102 if getregtype(tempreg)=R_INTREGISTER then 103 hreg:=tempreg 104 else 105 hreg:=cg.getintregister(helplist,OS_ADDR); 106 107 {$ifdef SPARC} 108 reference_reset(tmpref,sizeof(pint),[]); 109 tmpref.offset:=spilltemp.offset; 110 tmpref.refaddr:=addr_high; 111 helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg)); 112 113 tmpref.refaddr:=addr_low; 114 helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg)); 115 {$else SPARC} 116 if (spilltemp.offset>=-4294967296) and (spilltemp.offset<=-1) then 117 begin 118 helplist.concat(taicpu.op_const_reg(A_SETHI,(not(aint(spilltemp.offset)) shr 10) and $3fffff,hreg)); 119 if (aint(spilltemp.offset) and aint($3ff)) or aint($1c00)<>0 then 120 helplist.concat(taicpu.op_reg_const_reg(A_XOR,hreg,(aint(spilltemp.offset) and aint($3ff)) or aint($1c00),hreg)); 121 end 122 else 123 Internalerror(2017090901); 124 {$endif SPARC} 125 126 reference_reset_base(tmpref,hreg,0,spilltemp.temppos,sizeof(aint),[]); 127 tmpref.index:=spilltemp.base; 128 129 helpins:=spilling_create_load(tmpref,tempreg); 130 helplist.concat(helpins); 131 list.insertlistafter(pos,helplist); 132 helplist.free; 133 end 134 else 135 inherited; 136 end; 137 138 139 procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); 140 var 141 tmpref : treference; 142 helplist : TAsmList; 143 hreg : tregister; 144 begin 145 if abs(spilltemp.offset)>4095 then 146 begin 147 helplist:=TAsmList.create; 148 149 if getregtype(tempreg)=R_INTREGISTER then 150 hreg:=getregisterinline(helplist,[R_SUBWHOLE]) 151 else 152 hreg:=cg.getintregister(helplist,OS_ADDR); 153 154 {$ifdef SPARC} 155 reference_reset(tmpref,sizeof(aint),[]); 156 tmpref.offset:=spilltemp.offset; 157 tmpref.refaddr:=addr_high; 158 helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg)); 159 160 tmpref.refaddr:=addr_low; 161 helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg)); 162 {$else SPARC} 163 if (spilltemp.offset>=-4294967296) and (spilltemp.offset<=-1) then 164 begin 165 helplist.concat(taicpu.op_const_reg(A_SETHI,(not(aint(spilltemp.offset)) shr 10) and $3fffff,hreg)); 166 if (aint(spilltemp.offset) and aint($3ff)) or aint($1c00)<>0 then 167 helplist.concat(taicpu.op_reg_const_reg(A_XOR,hreg,(aint(spilltemp.offset) and aint($3ff)) or aint($1c00),hreg)); 168 end 169 else 170 Internalerror(2017090901); 171 {$endif SPARC} 172 173 reference_reset_base(tmpref,hreg,0,spilltemp.temppos,sizeof(aint),[]); 174 tmpref.index:=spilltemp.base; 175 176 helplist.concat(spilling_create_store(tempreg,tmpref)); 177 if getregtype(tempreg)=R_INTREGISTER then 178 ungetregisterinline(helplist,hreg); 179 180 list.insertlistafter(pos,helplist); 181 helplist.free; 182 end 183 else 184 inherited; 185 end; 186 187 trgcpu.do_spill_replacenull188 function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean; 189 var 190 opidx: longint; 191 begin 192 result:=false; 193 { Replace 'mov src,orgreg' with 'st src,spilltemp' 194 and 'mov orgreg,dst' with 'ld spilltemp,dst' } 195 if (abs(spilltemp.offset)>4095) then 196 exit; 197 if ((regtype=R_INTREGISTER) and (instr.opcode<>A_MOV)) or 198 ((regtype=R_FPUREGISTER) and (instr.opcode<>A_FMOVs) and (instr.opcode<>A_FMOVd)) then 199 exit; 200 { Ignore mis-encoded stuff like 'mov %something,%y' } 201 if (instr.ops<>2) or 202 (instr.oper[0]^.typ<>top_reg) or 203 (instr.oper[1]^.typ<>top_reg) or 204 (getregtype(instr.oper[0]^.reg)<>regtype) or 205 (getregtype(instr.oper[1]^.reg)<>regtype) then 206 exit; 207 opidx:=-1; 208 if get_alias(getsupreg(instr.oper[0]^.reg))=orgreg then 209 begin 210 if (regtype=R_INTREGISTER) then 211 instr.opcode:=A_LD_R 212 else if (getsubreg(instr.oper[0]^.reg)=R_SUBFS) then 213 instr.opcode:=A_LDF 214 else 215 instr.opcode:=A_LDDF; 216 opidx:=0; 217 end 218 else if get_alias(getsupreg(instr.oper[1]^.reg))=orgreg then 219 begin 220 if (regtype=R_INTREGISTER) then 221 instr.opcode:=A_ST_R 222 else if (getsubreg(instr.oper[1]^.reg)=R_SUBFS) then 223 instr.opcode:=A_STF 224 else 225 instr.opcode:=A_STDF; 226 opidx:=1; 227 end 228 else 229 InternalError(2013061002); 230 instr.oper[opidx]^.typ:=top_ref; 231 new(instr.oper[opidx]^.ref); 232 instr.oper[opidx]^.ref^:=spilltemp; 233 result:=true; 234 end; 235 236 end. 237