1 {
2     Copyright (c) 1998-2002 by Florian Klaempfl
3 
4     This unit implements the code generator for the SPARC
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20  ****************************************************************************
21 }
22 unit cgcpu;
23 
24 {$i fpcdefs.inc}
25 
26 interface
27 
28     uses
29        globtype,parabase,
30        cgbase,cgutils,cgobj,
31        aasmbase,aasmtai,aasmdata,aasmcpu,
32        cpubase,cpuinfo,
33        node,symconst,SymType,symdef,
34        rgcpu,
35        cgsparc;
36 
37     type
38       TCGSparc64=class(TCGSparcGen)
39        procedure a_load_reg_reg(list : TAsmList; fromsize,tosize : tcgsize; reg1,reg2 : tregister);override;
40        procedure a_load_ref_reg_unaligned(list : TAsmList; fromsize,tosize : tcgsize; const ref : treference; register : tregister);override;
41        procedure a_load_reg_ref_unaligned(list : TAsmList; fromsize,tosize : tcgsize; register : tregister; const ref : treference);override;
42        procedure a_load_const_reg(list : TAsmList; size : TCGSize; a : tcgint; reg : TRegister);override;
43       end;
44 
45     procedure create_codegen;
46 
47   implementation
48 
49     uses
50       verbose,
51       systems;
52 
53     procedure TCGSparc64.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
54       var
55         instr : taicpu;
56       begin
57          if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
58             ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
59              (fromsize <> tosize)) or
60             { needs to mask out the sign in the top 16 bits }
61             ((fromsize = OS_S8) and
62              (tosize = OS_16)) then
63            case tosize of
64              OS_8 :
65                list.concat(taicpu.op_reg_const_reg(A_AND,reg1,$ff,reg2));
66              OS_16 :
67                begin
68                  list.concat(taicpu.op_reg_const_reg(A_SLLX,reg1,48,reg2));
69                  list.concat(taicpu.op_reg_const_reg(A_SRLX,reg2,48,reg2));
70                end;
71              OS_32 :
72                begin
73                  list.concat(taicpu.op_reg_const_reg(A_SLLX,reg1,32,reg2));
74                  list.concat(taicpu.op_reg_const_reg(A_SRLX,reg2,32,reg2));
75                end;
76              OS_S32 :
77                list.concat(taicpu.op_reg_reg_reg(A_SRA,reg1,NR_G0,reg2));
78              OS_64,
79              OS_S64 :
80                begin
81                  instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
82                  list.Concat(instr);
83                  { Notify the register allocator that we have written a move instruction so
84                   it can try to eliminate it. }
85                  add_move_instruction(instr);
86                end;
87              OS_S8 :
88                begin
89                  list.concat(taicpu.op_reg_const_reg(A_SLLX,reg1,56,reg2));
90                  list.concat(taicpu.op_reg_const_reg(A_SRAX,reg2,56,reg2));
91                end;
92              OS_S16 :
93                begin
94                  list.concat(taicpu.op_reg_const_reg(A_SLLX,reg1,48,reg2));
95                  list.concat(taicpu.op_reg_const_reg(A_SRAX,reg2,48,reg2));
96                end;
97              else
98                internalerror(2017060501);
99            end
100          else
101            begin
102              instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
103              list.Concat(instr);
104              { Notify the register allocator that we have written a move instruction so
105               it can try to eliminate it. }
106              add_move_instruction(instr);
107            end;
108       end;
109 
110 
111     procedure TCGSparc64.a_load_ref_reg_unaligned(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; register: tregister);
112       var
113         href: treference;
114         hreg1, hreg2, tmpreg: tregister;
115       begin
116         if fromsize in [OS_64,OS_S64] then
117           begin
118             { split into two 32 bit loads }
119             hreg1:=getintregister(list,OS_32);
120             hreg2:=getintregister(list,OS_32);
121             a_load_ref_reg(list,OS_32,OS_32,ref,hreg1);
122             href:=ref;
123             inc(href.offset,4);
124             a_load_ref_reg(list,OS_32,OS_32,href,hreg2);
125             a_op_const_reg_reg(list,OP_SHL,OS_64,32,hreg1,register);
126             a_op_reg_reg_reg(list,OP_OR,OS_64,hreg2,register,register);
127           end
128        else
129          inherited;
130       end;
131 
132 
133     procedure TCGSparc64.a_load_reg_ref_unaligned(list : TAsmList;fromsize,tosize : tcgsize;register : tregister;const ref : treference);
134       var
135         href: treference;
136         hreg1: tregister;
137       begin
138         if fromsize in [OS_64,OS_S64] then
139           begin
140             { split into two 32 bit stores }
141             href:=ref;
142             if not(TCGSparc64(cg).IsSimpleRef(href)) then
143               begin
144                 hreg1:=getintregister(list,OS_ADDR);
145                 a_loadaddr_ref_reg(list,href,hreg1);
146                 reference_reset_base(href,hreg1,0,href.temppos,href.alignment,href.volatility);
147               end;
148             inc(href.offset,4);
149             a_load_reg_ref(list,OS_32,OS_32,register,href);
150             hreg1:=getintregister(list,OS_32);
151             a_op_const_reg_reg(list,OP_SHR,OS_64,32,register,hreg1);
152             dec(href.offset,4);
153             a_load_reg_ref(list,OS_32,OS_32,hreg1,href);
154           end
155        else
156          inherited;
157       end;
158 
159 
160     procedure TCGSparc64.a_load_const_reg(list : TAsmList;size : TCGSize;a : tcgint;reg : TRegister);
161       var
162         hreg : TRegister;
163       begin
164         { we don't use the set instruction here because it could be evalutated to two
165           instructions which would cause problems with the delay slot (FK) }
166         if a=0 then
167           list.concat(taicpu.op_reg(A_CLR,reg))
168         else if (a>=simm13lo) and (a<=simm13hi) then
169           list.concat(taicpu.op_const_reg(A_MOV,a,reg))
170         else if (a>=0) and (a<=$ffffffff) then
171           begin
172             list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg));
173             if (aint(a) and aint($3ff))<>0 then
174               list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
175           end
176         else if (a>=-4294967296) and (a<=-1) then
177           begin
178             list.concat(taicpu.op_const_reg(A_SETHI,(not(aint(a)) shr 10) and $3fffff,reg));
179             if (aint(a) and aint($3ff)) or aint($1c00)<>0 then
180               list.concat(taicpu.op_reg_const_reg(A_XOR,reg,(aint(a) and aint($3ff)) or aint($1c00),reg));
181           end
182         else
183           begin
184             hreg:=getintregister(list,OS_64);
185             list.concat(taicpu.op_const_reg(A_SETHI,(aint(a) shr 10) and $3fffff,reg));
186             list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 42,hreg));
187             if ((aint(a) shr 32) and aint($3ff))<>0 then
188               list.concat(taicpu.op_reg_const_reg(A_OR,hreg,(aint(a) shr 32) and aint($3ff),hreg));
189             if (aint(a) and aint($3ff))<>0 then
190               list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
191             a_op_const_reg_reg(list,OP_SHL,OS_64,32,hreg,hreg);
192             list.concat(taicpu.op_reg_reg_reg(A_OR,reg,hreg,reg));
193           end;
194       end;
195 
196 
197     procedure create_codegen;
198       begin
199         cg:=TCgSparc64.Create;
200         if target_info.system=system_sparc64_linux then
201           TCgSparc64(cg).use_unlimited_pic_mode:=true
202         else
203           TCgSparc64(cg).use_unlimited_pic_mode:=false;
204         cg128:=tcg128.create;
205       end;
206 
207 end.
208 
209