1 {
2     Copyright (c) 1998-2008 by Florian Klaempfl
3 
4     This unit implements the avr 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 }
23 
24 unit rgcpu;
25 
26 {$i fpcdefs.inc}
27 
28   interface
29 
30      uses
31        aasmbase,aasmtai,aasmdata,aasmcpu,aasmsym,
32        cgbase,cgutils,
33        cpubase,
34        rgobj;
35 
36      type
37        trgcpu = class(trgobj)
38          procedure add_constraints(reg:tregister);override;
39          procedure do_spill_read(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
40          procedure do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister); override;
do_spill_replacenull41          function do_spill_replace(list : TAsmList;instr : tai_cpu_abstract_sym; orgreg : tsuperregister;const spilltemp : treference) : boolean; override;
42        end;
43 
44        trgintcpu = class(trgcpu)
45          procedure add_cpu_interferences(p : tai);override;
46        end;
47 
48   implementation
49 
50     uses
51       verbose, cutils,
52       cgobj,
53       procinfo;
54 
55 
56     procedure trgcpu.add_constraints(reg:tregister);
57       var
58         supreg,i : Tsuperregister;
59       begin
60         case getsubreg(reg) of
61           { Let 64bit floats conflict with all odd float regs }
62           R_SUBFD:
63             begin
64             {
65               supreg:=getsupreg(reg);
66               i:=RS_F1;
67               while (i<=RS_F31) do
68                 begin
69                   add_edge(supreg,i);
70                   inc(i,2);
71                 end;
72             }
73             end;
74           { Let 64bit ints conflict with all odd int regs }
75           R_SUBQ:
76             begin
77               supreg:=getsupreg(reg);
78               {
79               i:=RS_G1;
80               while (i<=RS_I7) do
81                 begin
82                   add_edge(supreg,i);
83                   inc(i,2);
84                 end;
85               }
86             end;
87         end;
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)>63 then
99           begin
100             helplist:=TAsmList.create;
101 
102             helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
103             helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
104             helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
105             helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
106 
107             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
108             helpins:=spilling_create_load(tmpref,tempreg);
109             helplist.concat(helpins);
110             list.insertlistafter(pos,helplist);
111             helplist.free;
112           end
113         else
114           inherited;
115       end;
116 
117 
118     procedure trgcpu.do_spill_written(list: TAsmList; pos: tai; const spilltemp: treference; tempreg: tregister; orgsupreg: tsuperregister);
119       var
120         tmpref   : treference;
121         helplist : TAsmList;
122         hreg     : tregister;
123       begin
124         if abs(spilltemp.offset)>63 then
125           begin
126             helplist:=TAsmList.create;
127 
128             helplist.concat(taicpu.op_reg_const(A_LDI,NR_R26,lo(word(spilltemp.offset))));
129             helplist.concat(taicpu.op_reg_const(A_LDI,NR_R27,hi(word(spilltemp.offset))));
130             helplist.concat(taicpu.op_reg_reg(A_ADD,NR_R26,spilltemp.base));
131             helplist.concat(taicpu.op_reg_reg(A_ADC,NR_R27,cg.GetNextReg(spilltemp.base)));
132 
133             reference_reset_base(tmpref,NR_R26,0,spilltemp.temppos,1,[]);
134             helplist.concat(spilling_create_store(tempreg,tmpref));
135             list.insertlistafter(pos,helplist);
136             helplist.free;
137           end
138         else
139           inherited;
140       end;
141 
142 
143     procedure trgintcpu.add_cpu_interferences(p : tai);
144       var
145         r : tsuperregister;
146       begin
147         if p.typ=ait_instruction then
148           begin
149             case taicpu(p).opcode of
150               A_CPI,
151               A_ANDI,
152               A_ORI,
153               A_SUBI,
154               A_SBCI,
155               A_LDI:
156                 for r:=RS_R0 to RS_R15 do
157                   add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
158               A_MULS:
159                 begin
160                   for r:=RS_R0 to RS_R15 do
161                     add_edge(r,GetSupReg(taicpu(p).oper[0]^.reg));
162                   for r:=RS_R0 to RS_R15 do
163                     add_edge(r,GetSupReg(taicpu(p).oper[1]^.reg));
164                 end;
165             end;
166           end;
167       end;
168 
169 
trgcpu.do_spill_replacenull170     function trgcpu.do_spill_replace(list:TAsmList;instr:tai_cpu_abstract_sym;orgreg:tsuperregister;const spilltemp:treference):boolean;
171       var
172         b : byte;
173       begin
174         result:=false;
175         if not(spilltemp.offset in [0..63]) then
176           exit;
177 
178         { Replace 'mov  dst,orgreg' with 'ld  dst,spilltemp'
179           and     'mov  orgreg,src' with 'st  dst,spilltemp' }
180         with instr do
181           begin
182             if (opcode=A_MOV) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
183               begin
184                 if (getregtype(oper[0]^.reg)=regtype) and
185                    (get_alias(getsupreg(oper[0]^.reg))=orgreg) and
186                    (get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
187                   begin
188                     { str expects the register in oper[0] }
189                     instr.loadreg(0,oper[1]^.reg);
190                     instr.loadref(1,spilltemp);
191                     opcode:=A_ST;
192                     result:=true;
193                   end
194                 else if (getregtype(oper[1]^.reg)=regtype) and
195                    (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
196                    (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
197                   begin
198                     instr.loadref(1,spilltemp);
199                     opcode:=A_LD;
200                     result:=true;
201                   end;
202               end;
203           end;
204       end;
205 
206 end.
207