1 {
2     Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman
3 
4     Contains the base types for MIPS
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 {# Base unit for processor information. This unit contains
23    enumerations of registers, opcodes, sizes, and other
24    such things which are processor specific.
25 }
26 unit cpubase;
27 
28 {$i fpcdefs.inc}
29 
30   interface
31 
32     uses
33       cutils,cclasses,
34       globtype,globals,
35       cpuinfo,
36       aasmbase,
37       cgbase
38       ;
39 
40 
41 {*****************************************************************************
42                                 Assembler Opcodes
43 *****************************************************************************}
44 
45     type
46       TAsmOp=({$i opcode.inc});
47 
48       { This should define the array of instructions as string }
49       op2strtable=array[tasmop] of string[11];
50 
51     const
52       { First value of opcode enumeration }
53       firstop = low(tasmop);
54       { Last value of opcode enumeration  }
55       lastop  = high(tasmop);
56 
57 {*****************************************************************************
58                                   Registers
59 *****************************************************************************}
60 
61     type
62       { Number of registers used for indexing in tables }
63       tregisterindex=0..{$i rmipsnor.inc}-1;
64 
65     const
66       { Available Superregisters }
67       {$i rmipssup.inc}
68 
69       { No Subregisters }
70       R_SUBWHOLE = R_SUBD;
71 
72       { Available Registers }
73       {$i rmipscon.inc}
74 
75       { Integer Super registers first and last }
76       first_int_supreg = RS_R0;
77       first_int_imreg = $20;
78 
79       { Float Super register first and last }
80       first_fpu_supreg    = RS_F0;
81       first_fpu_imreg     = $20;
82 
83       { MM Super register first and last }
84       first_mm_supreg    = 0;
85       first_mm_imreg     = 1;
86 
87 { TODO: Calculate bsstart}
88       regnumber_count_bsstart = 64;
89 
90       regnumber_table : array[tregisterindex] of tregister = (
91         {$i rmipsnum.inc}
92       );
93 
94       regstabs_table : array[tregisterindex] of shortint = (
95         {$i rmipssta.inc}
96       );
97 
98       regdwarf_table : array[tregisterindex] of shortint = (
99         {$i rmipsdwf.inc}
100       );
101       { registers which may be destroyed by calls }
102       VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R15];
103       VOLATILE_FPUREGISTERS = [RS_F0..RS_F3];
104 
105     type
106       totherregisterset = set of tregisterindex;
107 
108 {*****************************************************************************
109                                 Conditions
110 *****************************************************************************}
111 
112     type
113       TAsmCond=(C_None,
114         C_EQ, C_NE, C_LT, C_LE, C_GT, C_GE, C_LTU, C_LEU, C_GTU, C_GEU,
115         C_LTZ, C_LEZ, C_GTZ, C_GEZ,
116         C_COP1TRUE,
117         C_COP1FALSE
118       );
119 
120     const
121       cond2str : array[TAsmCond] of string[3]=('',
122         'eq','ne','lt','le','gt','ge','ltu','leu','gtu','geu',
123         'ltz','lez','gtz','gez',
124         'c1t','c1f'
125       );
126 
127     type
128       TResFlags=record
129         reg1: TRegister;
130         cond: TOpCmp;
131       case use_const: boolean of
132         False: (reg2: TRegister);
133         True: (value: aint);
134       end;
135 
136 {*****************************************************************************
137                                  Constants
138 *****************************************************************************}
139 
140     const
141       max_operands = 4;
142 
143       maxintregs = 31;
144       maxfpuregs = 8;
145       maxaddrregs = 0;
146 
147 {*****************************************************************************
148                                  Constants
149 *****************************************************************************}
150 
151     const
152       maxvarregs = 7;
153       varregs : Array [1..maxvarregs] of tsuperregister =
154                 (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10);
155 
156       maxfpuvarregs = 4;
157       fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister =
158                 (RS_F4,RS_F5,RS_F6,RS_F7);
159 
160 {*****************************************************************************
161                           Default generic sizes
162 *****************************************************************************}
163 
164       { Defines the default address size for a processor, }
165       OS_ADDR = OS_32;
166       {# the natural int size for a processor,
167          has to match osuinttype/ossinttype as initialized in psystem }
168       OS_INT = OS_32;
169       OS_SINT = OS_S32;
170       { the maximum float size for a processor,           }
171       OS_FLOAT = OS_F64;
172       { the size of a vector register for a processor     }
173       OS_VECTOR = OS_M32;
174 
175 {*****************************************************************************
176                           Generic Register names
177 *****************************************************************************}
178 
179 
180       { PIC Code }
181       NR_GP = NR_R28;
182       NR_PIC_FUNC = NR_R25;
183       RS_GP = RS_R28;
184       RS_PIC_FUNC = RS_R25;
185 
186       { VMT code }
187       NR_VMT = NR_R24;
188       RS_VMT = RS_R24;
189 
190       NR_SP = NR_R29;
191       NR_S8 = NR_R30;
192       NR_FP = NR_R30;
193       NR_RA = NR_R31;
194 
195       RS_SP = RS_R29;
196       RS_S8 = RS_R30;
197       RS_FP = RS_R30;
198       RS_RA = RS_R31;
199 
200       {# Stack pointer register }
201       NR_STACK_POINTER_REG = NR_SP;
202       RS_STACK_POINTER_REG = RS_SP;
203       {# Frame pointer register }
204       NR_FRAME_POINTER_REG = NR_FP;
205       RS_FRAME_POINTER_REG = RS_FP;
206 
207       NR_RETURN_ADDRESS_REG = NR_R7;
208       { the return_result_reg, is used inside the called function to store its return
209       value when that is a scalar value otherwise a pointer to the address of the
210       result is placed inside it }
211 
212       { Results are returned in this register (32-bit values) }
213       NR_FUNCTION_RETURN_REG = NR_R2;
214       RS_FUNCTION_RETURN_REG = RS_R2;
215       { Low part of 64bit return value }
216       NR_FUNCTION_RETURN64_LOW_REG = NR_R2;
217       RS_FUNCTION_RETURN64_LOW_REG = RS_R2;
218       { High part of 64bit return value }
219       NR_FUNCTION_RETURN64_HIGH_REG = NR_R3;
220       RS_FUNCTION_RETURN64_HIGH_REG = RS_R3;
221       { The value returned from a function is available in this register }
222       NR_FUNCTION_RESULT_REG = NR_R2;
223       RS_FUNCTION_RESULT_REG = RS_R2;
224       { The lowh part of 64bit value returned from a function }
225       NR_FUNCTION_RESULT64_LOW_REG = NR_R2;
226       RS_FUNCTION_RESULT64_LOW_REG = RS_R2;
227       { The high part of 64bit value returned from a function }
228       NR_FUNCTION_RESULT64_HIGH_REG = NR_R3;
229       RS_FUNCTION_RESULT64_HIGH_REG = RS_R3;
230 
231       NR_FPU_RESULT_REG = NR_F0;
232       NR_MM_RESULT_REG  = NR_NO;
233 
234       NR_DEFAULTFLAGS = NR_NO;
235 
236 {*****************************************************************************
237                        GCC /ABI linking information
238 *****************************************************************************}
239 
240     const
241       { Required parameter alignment when calling a routine declared as
242         stdcall and cdecl. The alignment value should be the one defined
243         by GCC or the target ABI.
244 
245         The value of this constant is equal to the constant
246         PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
247       }
248       std_param_align = 4;
249 
250 {*****************************************************************************
251                             CPU Dependent Constants
252 *****************************************************************************}
253 
254     const
255       simm16lo =  -32768;
256       simm16hi =   32767;
257 
258 {*****************************************************************************
259                                   Helpers
260 *****************************************************************************}
261 
inverse_condnull262     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
conditions_equalnull263     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
264 
265     { Returns the tcgsize corresponding with the size of reg.}
reg_cgsizenull266     function reg_cgsize(const reg: tregister) : tcgsize;
cgsize2subregnull267     function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
is_calljmpnull268     function is_calljmp(o:tasmop):boolean;
findreg_by_numbernull269     function findreg_by_number(r:Tregister):tregisterindex;
std_regnum_searchnull270     function std_regnum_search(const s:string):Tregister;
std_regnamenull271     function std_regname(r:Tregister):string;
dwarf_regnull272     function dwarf_reg(r:tregister):shortint;
dwarf_reg_no_errornull273     function dwarf_reg_no_error(r:tregister):shortint;
274 
275   implementation
276 
277     uses
278       rgBase,verbose;
279 
280 
281     const
282       std_regname_table : TRegNameTable = (
283         {$i rmipsstd.inc}
284       );
285 
286       regnumber_index : array[tregisterindex] of tregisterindex = (
287         {$i rmipsrni.inc}
288       );
289 
290       std_regname_index : array[tregisterindex] of tregisterindex = (
291         {$i rmipssri.inc}
292       );
293 
294 
cgsize2subregnull295     function cgsize2subreg(regtype: tregistertype; s:tcgsize):tsubregister;
296       begin
297         case regtype of
298           R_FPUREGISTER:
299             if s=OS_F32 then
300               result:=R_SUBFS
301             else if s=OS_F64 then
302               result:=R_SUBFD
303             else
304               internalerror(2013021301);
305         else
306           result:=R_SUBWHOLE;
307         end;
308       end;
309 
310 
reg_cgsizenull311     function reg_cgsize(const reg: tregister): tcgsize;
312       begin
313         case getregtype(reg) of
314           R_INTREGISTER :
315             reg_cgsize:=OS_32;
316           R_FPUREGISTER :
317             begin
318               if getsubreg(reg)=R_SUBFD then
319                 result:=OS_F64
320               else
321                 result:=OS_F32;
322             end;
323           else
324             internalerror(200303181);
325           end;
326         end;
327 
328 
is_calljmpnull329     function is_calljmp(o:tasmop):boolean;
330       begin
331         is_calljmp:= o in [A_J,A_JAL,A_JALR,{ A_JALX, }A_JR, A_BA, A_BC];
332       end;
333 
334 
inverse_condnull335     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
336       const
337         inverse: array[TAsmCond] of TAsmCond=(C_None,
338         C_NE, C_EQ, C_GE, C_GT, C_LE, C_LT, C_GEU, C_GTU, C_LEU, C_LTU,
339         C_GEZ, C_GTZ, C_LEZ, C_LTZ,
340         C_COP1FALSE,
341         C_COP1TRUE
342         );
343       begin
344         result := inverse[c];
345       end;
findreg_by_numbernull346       function findreg_by_number(r:Tregister):tregisterindex;
347       begin
348         { the register table for MIPS cpu only contains
349           R_SUBFS and R_SUBD register types.
350           This function is called by dbgstabs unit,
351           here were are only interested in register,
352           not its subtype, thus we change subreg to
353           R_SUBFS or R_SUBD.  }
354         case getsubreg(r) of
355           R_SUBFD:
356             setsubreg(r, R_SUBFS);
357           R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
358             setsubreg(r, R_SUBD);
359         end;
360         result:=rgBase.findreg_by_number_table(r,regnumber_index);
361       end;
362 
363 
conditions_equalnull364     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
365       begin
366         result := c1 = c2;
367       end;
368 
369 
std_regnum_searchnull370     function std_regnum_search(const s:string):Tregister;
371       begin
372         result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
373       end;
374 
375 
std_regnamenull376     function std_regname(r:Tregister):string;
377       var
378         p : tregisterindex;
379         hr : tregister;
380       begin
381         hr:=r;
382         case getsubreg(hr) of
383           R_SUBFD:
384             setsubreg(hr, R_SUBFS);
385           R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
386             setsubreg(hr, R_SUBD);
387         end;
388         p:=findreg_by_number_table(hr,regnumber_index);
389         if p<>0 then
390           result:=std_regname_table[p]
391         else if getregtype(r)=R_SPECIALREGISTER then
392           result:=tostr(getsupreg(r))
393         else
394           result:=generic_regname(r);
395       end;
396 
dwarf_regnull397     function dwarf_reg(r:tregister):shortint;
398       begin
399         case getsubreg(r) of
400           R_SUBFD:
401             setsubreg(r, R_SUBFS);
402           R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
403             setsubreg(r, R_SUBD);
404         end;
405         result:=regdwarf_table[findreg_by_number(r)];
406         if result=-1 then
407           internalerror(200603251);
408       end;
409 
dwarf_reg_no_errornull410     function dwarf_reg_no_error(r:tregister):shortint;
411       begin
412         case getsubreg(r) of
413           R_SUBFD:
414             setsubreg(r, R_SUBFS);
415           R_SUBL, R_SUBW, R_SUBD, R_SUBQ:
416             setsubreg(r, R_SUBD);
417         end;
418         result:=regdwarf_table[findreg_by_number(r)];
419       end;
420 begin
421 end.
422