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