1 {
2     Copyright (c) 1998-2002 by Florian Klaempfl
3 
4     Contains the base types 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 cpubase;
23 
24 {$i fpcdefs.inc}
25 
26 {$ModeSwitch advancedrecords}
27 
28 interface
29 
30 uses
31   globtype,strings,cutils,cclasses,aasmbase,cpuinfo,cgbase;
32 
33 
34 {*****************************************************************************
35                                 Assembler Opcodes
36 *****************************************************************************}
37 
38     type
39 { TODO: CPU32 opcodes do not fully include the Ultra SPRAC instruction set.}
40       { don't change the order of these opcodes! }
41       TAsmOp=({$i opcode.inc});
42 
43       {# This should define the array of instructions as string }
44       op2strtable=array[tasmop] of string[11];
45 
46     Const
47       {# First value of opcode enumeration }
48       firstop = low(tasmop);
49       {# Last value of opcode enumeration  }
50       lastop  = high(tasmop);
51 
52       std_op2str:op2strtable=({$i strinst.inc});
53 
54 {*****************************************************************************
55                                   Registers
56 *****************************************************************************}
57 
58 {$ifdef SPARC}
59     type
60       { Number of registers used for indexing in tables }
61       tregisterindex=0..{$i rspnor.inc}-1;
62       totherregisterset = set of tregisterindex;
63 
64     const
65       { Available Superregisters }
66       {$i rspsup.inc}
67 
68       { No Subregisters }
69       R_SUBWHOLE = R_SUBNONE;
70 
71       { Available Registers }
72       {$i rspcon.inc}
73 
74       first_int_imreg = $20;
75       first_fpu_imreg = $20;
76 
77       { MM Super register first and last }
78       first_mm_supreg    = 0;
79       first_mm_imreg     = 1;
80 
81 { TODO: Calculate bsstart}
82       regnumber_count_bsstart = 128;
83 
84       regnumber_table : array[tregisterindex] of tregister = (
85         {$i rspnum.inc}
86       );
87 
88       regstabs_table : array[tregisterindex] of ShortInt = (
89         {$i rspstab.inc}
90       );
91 
92       regdwarf_table : array[tregisterindex] of ShortInt = (
93         {$i rspdwrf.inc}
94       );
95 
96       { Aliases for full register LoadStore instructions }
97       A_ST_R = A_ST;
98       A_LD_R = A_LD;
99 {$endif SPARC}
100 
101 {$ifdef SPARC64}
102     type
103       { Number of registers used for indexing in tables }
104       tregisterindex=0..{$i rsp64nor.inc}-1;
105       totherregisterset = set of tregisterindex;
106 
107     const
108       { Available Superregisters }
109       {$i rsp64sup.inc}
110 
111       { No Subregisters }
112       R_SUBWHOLE = R_SUBNONE;
113 
114       { Available Registers }
115       {$i rsp64con.inc}
116 
117       first_int_imreg = $20;
118       first_fpu_imreg = $20;
119 
120       { MM Super register first and last }
121       first_mm_supreg    = 0;
122       first_mm_imreg     = 1;
123 
124 { TODO: Calculate bsstart}
125       regnumber_count_bsstart = 128;
126 
127       regnumber_table : array[tregisterindex] of tregister = (
128         {$i rsp64num.inc}
129       );
130 
131       regstabs_table : array[tregisterindex] of ShortInt = (
132         {$i rsp64stab.inc}
133       );
134 
135       regdwarf_table : array[tregisterindex] of ShortInt = (
136         {$i rsp64dwrf.inc}
137       );
138       { Aliases for full register LoadStore instructions }
139       A_ST_R = A_STX;
140       A_LD_R = A_LDX;
141 {$endif SPARC64}
142 
143 {*****************************************************************************
144                                 Conditions
145 *****************************************************************************}
146 
147     type
148       TAsmCond=(C_None,
149         C_A,C_AE,C_B,C_BE,
150         C_G,C_GE,C_L,C_LE,
151         C_E,C_NE,
152         C_POS,C_NEG,C_VC,C_VS,
153         C_FE,C_FG,C_FL,C_FGE,C_FLE,C_FNE,
154         C_FU,C_FUG,C_FUL,C_FUGE,C_FULE,C_FO,C_FUE,C_FLG
155       );
156 
157     const
158       firstIntCond=C_A;
159       lastIntCond=C_VS;
160       firstFloatCond=C_FE;
161       lastFloatCond=C_FNE;
162       floatAsmConds=[C_FE..C_FLG];
163 
164       cond2str:array[TAsmCond] of string[3]=('',
165         'gu','cc','cs','leu',
166         'g','ge','l','le',
167         'e','ne',
168         'pos','neg','vc','vs',
169         'e','g','l','ge','le','ne',
170         'u','ug','ul','uge','ule','o','ue','lg'
171       );
172 
173 
174 {*****************************************************************************
175                                    Flags
176 *****************************************************************************}
177 
178     type
179         TSparcFlags = (
180           { Integer results }
181           F_E,  {Equal}
182           F_NE, {Not Equal}
183           F_G,  {Greater}
184           F_L,  {Less}
185           F_GE, {Greater or Equal}
186           F_LE, {Less or Equal}
187           F_A,  {Above}
188           F_AE, {Above or Equal, synonym: Carry Clear}
189           F_B,  {Below, synonym: Carry Set}
190           F_BE, {Below or Equal}
191           { Floating point results }
192           F_FE,  {Equal}
193           F_FNE, {Not Equal}
194           F_FG,  {Greater}
195           F_FL,  {Less}
196           F_FGE, {Greater or Equal}
197           F_FLE  {Less or Equal}
198           );
199       TResFlags = record
200         { either icc or xcc (64 bit }
201         FlagReg : TRegister;
202         Flags : TSparcFlags;
203         procedure Init(r : TRegister;f : TSparcFlags);
204       end;
205 
206 {*****************************************************************************
207                                 Operand Sizes
208 *****************************************************************************}
209 
210 
211 {*****************************************************************************
212                                  Constants
213 *****************************************************************************}
214 
215     const
216       max_operands = 3;
217 
218       maxintregs = 8;
219       maxfpuregs = 8;
220       maxaddrregs = 0;
221 
222       maxvarregs = 8;
223       varregs : Array [1..maxvarregs] of Tsuperregister =
224                 (RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7);
225 
226       maxfpuvarregs = 1;
227       fpuvarregs : Array [1..maxfpuvarregs] of TsuperRegister =
228                 (RS_F2);
229 
230 {*****************************************************************************
231                           Default generic sizes
232 *****************************************************************************}
233 
234 {$ifdef SPARC64}
235       {# Defines the default address size for a processor, }
236       OS_ADDR = OS_64;
237       {# the natural int size for a processor,
238          has to match osuinttype/ossinttype as initialized in psystem }
239       OS_INT = OS_64;
240       OS_SINT = OS_S64;
241 {$else SPARC64}
242       {# Defines the default address size for a processor, }
243       OS_ADDR = OS_32;
244       {# the natural int size for a processor,
245          has to match osuinttype/ossinttype as initialized in psystem }
246       OS_INT = OS_32;
247       OS_SINT = OS_S32;
248 {$endif SPARC64}
249       {# the maximum float size for a processor,           }
250       OS_FLOAT = OS_F64;
251       {# the size of a vector register for a processor     }
252       OS_VECTOR = OS_M64;
253 
254 {*****************************************************************************
255                           Generic Register names
256 *****************************************************************************}
257 
258       {# Stack pointer register }
259       NR_STACK_POINTER_REG = NR_O6;
260       RS_STACK_POINTER_REG = RS_O6;
261       {# Frame pointer register }
262       NR_FRAME_POINTER_REG = NR_I6;
263       RS_FRAME_POINTER_REG = RS_I6;
264       {# Register for addressing absolute data in a position independant way,
265          such as in PIC code. The exact meaning is ABI specific. For
266          further information look at GCC source : PIC_OFFSET_TABLE_REGNUM
267 
268          Taken from GCC rs6000.h
269       }
270 { TODO: As indicated in rs6000.h, but can't find it anywhere else!}
271       {PIC_OFFSET_REG = R_30;}
272       { Return address for DWARF }
273       NR_RETURN_ADDRESS_REG = NR_I7;
274       { the return_result_reg, is used inside the called function to store its return
275       value when that is a scalar value otherwise a pointer to the address of the
276       result is placed inside it }
277       { Results are returned in this register (32-bit values) }
278       NR_FUNCTION_RETURN_REG = NR_I0;
279       RS_FUNCTION_RETURN_REG = RS_I0;
280       { Low part of 64bit return value }
281       NR_FUNCTION_RETURN64_LOW_REG = NR_I1;
282       RS_FUNCTION_RETURN64_LOW_REG = RS_I1;
283       { High part of 64bit return value }
284       NR_FUNCTION_RETURN64_HIGH_REG = NR_I0;
285       RS_FUNCTION_RETURN64_HIGH_REG = RS_I0;
286       { The value returned from a function is available in this register }
287       NR_FUNCTION_RESULT_REG = NR_O0;
288       RS_FUNCTION_RESULT_REG = RS_O0;
289       { The lowh part of 64bit value returned from a function }
290       NR_FUNCTION_RESULT64_LOW_REG = NR_O1;
291       RS_FUNCTION_RESULT64_LOW_REG = RS_O1;
292       { The high part of 64bit value returned from a function }
293       NR_FUNCTION_RESULT64_HIGH_REG = NR_O0;
294       RS_FUNCTION_RESULT64_HIGH_REG = RS_O0;
295 
296       NR_FPU_RESULT_REG = NR_F0;
297       NR_MM_RESULT_REG  = NR_NO;
298 
299       PARENT_FRAMEPOINTER_OFFSET = 68; { o0 }
300 
301       NR_DEFAULTFLAGS = NR_PSR;
302       RS_DEFAULTFLAGS = RS_PSR;
303 
304 {*****************************************************************************
305                        GCC /ABI linking information
306 *****************************************************************************}
307 
308       {# Required parameter alignment when calling a routine declared as
309          stdcall and cdecl. The alignment value should be the one defined
310          by GCC or the target ABI.
311 
312          The value of this constant is equal to the constant
313          PARM_BOUNDARY / BITS_PER_UNIT in the GCC source.
314       }
315       std_param_align = sizeof(AWord);
316 
317 {$ifdef SPARC64}
318       STACK_BIAS = 2047;
319 {$endif SPARC64}
320 
321 
322 {*****************************************************************************
323                             CPU Dependent Constants
324 *****************************************************************************}
325 
326     const
327       simm13lo=-4096;
328       simm13hi=4095;
329 
330 {*****************************************************************************
331                                   Helpers
332 *****************************************************************************}
333 
is_calljmpnull334     function  is_calljmp(o:tasmop):boolean;
335 
336     procedure inverse_flags(var f: TResFlags);
inverse_condnull337     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
conditions_equalnull338     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
339 
flags_to_condnull340     function  flags_to_cond(const f: TResFlags) : TAsmCond;
cgsize2subregnull341     function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
reg_cgsizenull342     function reg_cgsize(const reg: tregister): tcgsize;
std_regnamenull343     function std_regname(r:Tregister):string;
std_regnum_searchnull344     function std_regnum_search(const s:string):Tregister;
findreg_by_numbernull345     function findreg_by_number(r:Tregister):tregisterindex;
dwarf_regnull346     function dwarf_reg(r:tregister):shortint;
dwarf_reg_no_errornull347     function dwarf_reg_no_error(r:tregister):shortint;
348 
349 
350 implementation
351 
352     uses
353       rgBase,verbose;
354 
355 {$ifdef SPARC}
356     const
357       std_regname_table : TRegNameTAble = (
358         {$i rspstd.inc}
359       );
360 
361       regnumber_index : TRegisterIndexTable = (
362         {$i rsprni.inc}
363       );
364 
365       std_regname_index : TRegisterIndexTable = (
366         {$i rspsri.inc}
367       );
368 {$endif SPARC}
369 
370 {$ifdef SPARC64}
371     const
372       std_regname_table : TRegNameTAble = (
373         {$i rsp64std.inc}
374       );
375 
376       regnumber_index : TRegisterIndexTable = (
377         {$i rsp64rni.inc}
378       );
379 
380       std_regname_index : TRegisterIndexTable = (
381         {$i rsp64sri.inc}
382       );
383 {$endif SPARC64}
384 
385 {*****************************************************************************
386                                   Helpers
387 *****************************************************************************}
388 
is_calljmpnull389     function is_calljmp(o:tasmop):boolean;
390       const
391         CallJmpOp=[A_JMPL..A_CBccc];
392       begin
393         is_calljmp:=(o in CallJmpOp);
394       end;
395 
396 
397     procedure inverse_flags(var f: TResFlags);
398       const
399         inv_flags: array[TSparcFlags] of TSparcFlags =
400           (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_BE,F_B,F_AE,F_A,
401            F_FNE,F_FE,F_FLE,F_FGE,F_FL,F_FG);
402       begin
403         f.Flags:=inv_flags[f.Flags];
404       end;
405 
406 
flags_to_condnull407    function flags_to_cond(const f:TResFlags):TAsmCond;
408       const
409         flags_2_cond:array[TSparcFlags] of TAsmCond=
410           (C_E,C_NE,C_G,C_L,C_GE,C_LE,C_A,C_AE,C_B,C_BE,
411            C_FE,C_FNE,C_FG,C_FL,C_FGE,C_FLE);
412       begin
413         result:=flags_2_cond[f.Flags];
414       end;
415 
416 
cgsize2subregnull417     function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister;
418       begin
419         case regtype of
420           R_FPUREGISTER:
421             case s of
422               OS_F32:
423                 cgsize2subreg:=R_SUBFS;
424               OS_F64:
425                 cgsize2subreg:=R_SUBFD;
426               OS_F128:
427                 cgsize2subreg:=R_SUBFQ;
428               else
429                 internalerror(2009071903);
430             end;
431           else
432             begin
433 {$ifdef SPARC32}
434               if s in [OS_64,OS_S64] then
435                 cgsize2subreg:=R_SUBQ
436               else
437 {$endif SPARC32}
438                 cgsize2subreg:=R_SUBWHOLE;
439             end;
440         end;
441       end;
442 
443 
reg_cgsizenull444     function reg_cgsize(const reg: tregister): tcgsize;
445       begin
446         case getregtype(reg) of
447           R_INTREGISTER :
448             result:=OS_INT;
449           R_FPUREGISTER :
450             begin
451               if getsubreg(reg)=R_SUBFD then
452                 result:=OS_F64
453               else
454                 result:=OS_F32;
455             end;
456           else
457             internalerror(200303181);
458         end;
459       end;
460 
461 
findreg_by_numbernull462     function findreg_by_number(r:Tregister):tregisterindex;
463       begin
464         result:=findreg_by_number_table(r,regnumber_index);
465       end;
466 
467 
std_regnamenull468     function std_regname(r:Tregister):string;
469       var
470         p : tregisterindex;
471       begin
472         { For double floats show a pair like %f0:%f1 }
473         if (getsubreg(r)=R_SUBFD) and
474            (getsupreg(r)<first_fpu_imreg) then
475           begin
476             setsubreg(r,R_SUBFS);
477             p:=findreg_by_number(r);
478             if p<>0 then
479               result:=std_regname_table[p]
480             else
481               result:=generic_regname(r);
482             setsupreg(r,getsupreg(r)+1);
483             p:=findreg_by_number(r);
484             if p<>0 then
485               result:=result+':'+std_regname_table[p]
486             else
487               result:=result+':'+generic_regname(r);
488           end
489         else
490           begin
491             p:=findreg_by_number(r);
492             if p<>0 then
493               result:=std_regname_table[p]
494             else
495               result:=generic_regname(r);
496           end;
497       end;
498 
499 
std_regnum_searchnull500     function std_regnum_search(const s:string):Tregister;
501       begin
502         result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)];
503       end;
504 
505 
inverse_condnull506     function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE}
507       const
508         inverse: array[TAsmCond] of TAsmCond=(C_None,
509           C_BE,C_B,C_AE,C_A,
510           C_LE,C_L,C_GE,C_G,
511           C_NE,C_E,
512           C_NEG,C_POS,C_VS,C_VC,
513           C_FNE,C_FULE,C_FUGE,C_FUL,C_FUG,C_FE,
514           C_FO,C_FLE,C_FGE,C_FL,C_FG,C_FU,C_FLG,C_FUE
515         );
516       begin
517         result := inverse[c];
518       end;
519 
520 
conditions_equalnull521     function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE}
522       begin
523         result := c1 = c2;
524       end;
525 
526 
dwarf_regnull527     function dwarf_reg(r:tregister):shortint;
528       begin
529         result:=regdwarf_table[findreg_by_number(r)];
530         if result=-1 then
531           internalerror(200603251);
532       end;
533 
dwarf_reg_no_errornull534     function dwarf_reg_no_error(r:tregister):shortint;
535       begin
536         result:=regdwarf_table[findreg_by_number(r)];
537       end;
538 
539     procedure TResFlags.Init(r : TRegister; f : TSparcFlags);
540       begin
541         FlagReg:=r;
542         Flags:=f;
543       end;
544 
545 end.
546