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