1 { 2 Copyright (c) 1998-2002 by Florian Klaempfl and Peter Vreman 3 4 Contains the base types for the ARM 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 {$define USEINLINE} 29 30 {$i fpcdefs.inc} 31 32 interface 33 34 uses 35 globtype,globals, 36 cpuinfo, 37 cgbase 38 ; 39 40 41 {***************************************************************************** 42 Assembler Opcodes 43 *****************************************************************************} 44 45 type 46 TAsmOp= {$i armop.inc} 47 {This is a bit of a hack, because there are more than 256 ARM Assembly Ops 48 But FPC currently can't handle more than 256 elements in a set.} 49 TCommonAsmOps = Set of A_None .. A_UADD16; 50 51 { This should define the array of instructions as string } 52 op2strtable=array[tasmop] of string[11]; 53 54 const 55 { First value of opcode enumeration } 56 firstop = low(tasmop); 57 { Last value of opcode enumeration } 58 lastop = high(tasmop); 59 60 {***************************************************************************** 61 Registers 62 *****************************************************************************} 63 64 type 65 { Number of registers used for indexing in tables } 66 tregisterindex=0..{$i rarmnor.inc}-1; 67 68 const 69 { Available Superregisters } 70 {$i rarmsup.inc} 71 72 RS_PC = RS_R15; 73 74 { No Subregisters } 75 R_SUBWHOLE = R_SUBNONE; 76 77 { Available Registers } 78 {$i rarmcon.inc} 79 80 { aliases } 81 NR_PC = NR_R15; 82 83 { Integer Super registers first and last } 84 first_int_supreg = RS_R0; 85 first_int_imreg = $10; 86 87 { Float Super register first and last } 88 first_fpu_supreg = RS_F0; 89 first_fpu_imreg = $08; 90 91 { MM Super register first and last } 92 first_mm_supreg = RS_S0; 93 first_mm_imreg = $30; 94 95 { TODO: Calculate bsstart} 96 regnumber_count_bsstart = 128; 97 98 regnumber_table : array[tregisterindex] of tregister = ( 99 {$i rarmnum.inc} 100 ); 101 102 regstabs_table : array[tregisterindex] of shortint = ( 103 {$i rarmsta.inc} 104 ); 105 106 regdwarf_table : array[tregisterindex] of shortint = ( 107 {$i rarmdwa.inc} 108 ); 109 { registers which may be destroyed by calls } 110 VOLATILE_INTREGISTERS = [RS_R0..RS_R3,RS_R12..RS_R14]; 111 VOLATILE_FPUREGISTERS = [RS_F0..RS_F3]; 112 VOLATILE_MMREGISTERS = [RS_D0..RS_D7,RS_D16..RS_D31]; 113 114 VOLATILE_INTREGISTERS_DARWIN = [RS_R0..RS_R3,RS_R9,RS_R12..RS_R14]; 115 116 type 117 totherregisterset = set of tregisterindex; 118 119 {***************************************************************************** 120 Instruction post fixes 121 *****************************************************************************} 122 type 123 { ARM instructions load/store and arithmetic instructions 124 can have several instruction post fixes which are collected 125 in this enumeration 126 } 127 TOpPostfix = (PF_None, 128 { update condition flags 129 or floating point single } 130 PF_S, 131 { floating point size } 132 PF_D,PF_E,PF_P,PF_EP, 133 { exchange } 134 PF_X, 135 { rounding } 136 PF_R, 137 { load/store } 138 PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T, 139 { multiple load/store address modes } 140 PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA, 141 { multiple load/store vfp address modes } 142 PF_IAD,PF_DBD,PF_FDD,PF_EAD, 143 PF_IAS,PF_DBS,PF_FDS,PF_EAS, 144 PF_IAX,PF_DBX,PF_FDX,PF_EAX, 145 { VFP postfixes } 146 PF_8,PF_16,PF_32,PF_64, 147 PF_I8,PF_I16,PF_I32,PF_I64, 148 PF_S8,PF_S16,PF_S32,PF_S64, 149 PF_U8,PF_U16,PF_U32,PF_U64, 150 PF_P8, // polynomial 151 PF_F32,PF_F64, 152 PF_F32F64,PF_F64F32, 153 PF_F32S16,PF_F32U16,PF_S16F32,PF_U16F32, 154 PF_F64S16,PF_F64U16,PF_S16F64,PF_U16F64, 155 PF_F32S32,PF_F32U32,PF_S32F32,PF_U32F32, 156 PF_F64S32,PF_F64U32,PF_S32F64,PF_U32F64 157 ); 158 159 TOpPostfixes = set of TOpPostfix; 160 161 TRoundingMode = (RM_None,RM_P,RM_M,RM_Z); 162 163 const 164 cgsize2fpuoppostfix : array[OS_NO..OS_F128] of toppostfix = ( 165 PF_None, 166 PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None,PF_None, 167 PF_S,PF_D,PF_E,PF_None,PF_None); 168 169 oppostfix2str : array[TOpPostfix] of string[8] = ('', 170 's', 171 'd','e','p','ep', 172 'x', 173 'r', 174 'b','sb','bt','h','sh','t', 175 'ia','ib','da','db','fd','fa','ed','ea', 176 'iad','dbd','fdd','ead', 177 'ias','dbs','fds','eas', 178 'iax','dbx','fdx','eax', 179 '.8','.16','.32','.64', 180 '.i8','.i16','.i32','.i64', 181 '.s8','.s16','.s32','.s64', 182 '.u8','.u16','.u32','.u64', 183 '.p8', 184 '.f32','.f64', 185 '.f32.f64','.f64.f32', 186 '.f32.s16','.f32.u16','.s16.f32','.u16.f32', 187 '.f64.s16','.f64.u16','.s16.f64','.u16.f64', 188 '.f32.s32','.f32.u32','.s32.f32','.u32.f32', 189 '.f64.s32','.f64.u32','.s32.f64','.u32.f64'); 190 191 roundingmode2str : array[TRoundingMode] of string[1] = ('', 192 'p','m','z'); 193 194 {***************************************************************************** 195 Conditions 196 *****************************************************************************} 197 198 type 199 TAsmCond=(C_None, 200 C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS, 201 C_GE,C_LT,C_GT,C_LE,C_AL,C_NV 202 ); 203 204 TAsmConds = set of TAsmCond; 205 206 const 207 cond2str : array[TAsmCond] of string[2]=('', 208 'eq','ne','cs','cc','mi','pl','vs','vc','hi','ls', 209 'ge','lt','gt','le','al','nv' 210 ); 211 212 uppercond2str : array[TAsmCond] of string[2]=('', 213 'EQ','NE','CS','CC','MI','PL','VS','VC','HI','LS', 214 'GE','LT','GT','LE','AL','NV' 215 ); 216 217 {***************************************************************************** 218 Flags 219 *****************************************************************************} 220 221 type 222 TResFlags = (F_EQ,F_NE,F_CS,F_CC,F_MI,F_PL,F_VS,F_VC,F_HI,F_LS, 223 F_GE,F_LT,F_GT,F_LE); 224 225 {***************************************************************************** 226 Operands 227 *****************************************************************************} 228 229 taddressmode = (AM_OFFSET,AM_PREINDEXED,AM_POSTINDEXED); 230 tshiftmode = (SM_None,SM_LSL,SM_LSR,SM_ASR,SM_ROR,SM_RRX); 231 232 tupdatereg = (UR_None,UR_Update); 233 234 pshifterop = ^tshifterop; 235 236 tshifterop = record 237 shiftmode : tshiftmode; 238 rs : tregister; 239 shiftimm : byte; 240 end; 241 242 tcpumodeflag = (mfA, mfI, mfF); 243 tcpumodeflags = set of tcpumodeflag; 244 245 tspecialregflag = (srC, srX, srS, srF); 246 tspecialregflags = set of tspecialregflag; 247 248 {***************************************************************************** 249 Constants 250 *****************************************************************************} 251 252 const 253 max_operands = 6; 254 255 maxintregs = 15; 256 maxfpuregs = 8; 257 maxaddrregs = 0; 258 259 {***************************************************************************** 260 Operand Sizes 261 *****************************************************************************} 262 263 type 264 topsize = (S_NO, 265 S_B,S_W,S_L,S_BW,S_BL,S_WL, 266 S_IS,S_IL,S_IQ, 267 S_FS,S_FL,S_FX,S_D,S_Q,S_FV,S_FXX 268 ); 269 270 {***************************************************************************** 271 Constants 272 *****************************************************************************} 273 274 const 275 maxvarregs = 7; 276 varregs : Array [1..maxvarregs] of tsuperregister = 277 (RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,RS_R10); 278 279 maxfpuvarregs = 4; 280 fpuvarregs : Array [1..maxfpuvarregs] of tsuperregister = 281 (RS_F4,RS_F5,RS_F6,RS_F7); 282 283 {***************************************************************************** 284 Default generic sizes 285 *****************************************************************************} 286 287 { Defines the default address size for a processor, } 288 OS_ADDR = OS_32; 289 { the natural int size for a processor, 290 has to match osuinttype/ossinttype as initialized in psystem } 291 OS_INT = OS_32; 292 OS_SINT = OS_S32; 293 { the maximum float size for a processor, } 294 OS_FLOAT = OS_F64; 295 { the size of a vector register for a processor } 296 OS_VECTOR = OS_M32; 297 298 {***************************************************************************** 299 Generic Register names 300 *****************************************************************************} 301 302 { Stack pointer register } 303 NR_STACK_POINTER_REG = NR_R13; 304 RS_STACK_POINTER_REG = RS_R13; 305 { Frame pointer register (initialized in tcpuprocinfo.init_framepointer) } 306 RS_FRAME_POINTER_REG: tsuperregister = RS_NO; 307 NR_FRAME_POINTER_REG: tregister = NR_NO; 308 { Register for addressing absolute data in a position independant way, 309 such as in PIC code. The exact meaning is ABI specific. For 310 further information look at GCC source : PIC_OFFSET_TABLE_REGNUM 311 } 312 NR_PIC_OFFSET_REG = NR_R9; 313 { Results are returned in this register (32-bit values) } 314 NR_FUNCTION_RETURN_REG = NR_R0; 315 RS_FUNCTION_RETURN_REG = RS_R0; 316 { The value returned from a function is available in this register } 317 NR_FUNCTION_RESULT_REG = NR_FUNCTION_RETURN_REG; 318 RS_FUNCTION_RESULT_REG = RS_FUNCTION_RETURN_REG; 319 320 NR_FPU_RESULT_REG = NR_F0; 321 322 NR_MM_RESULT_REG = NR_D0; 323 324 NR_RETURN_ADDRESS_REG = NR_FUNCTION_RETURN_REG; 325 326 { Offset where the parent framepointer is pushed } 327 PARENT_FRAMEPOINTER_OFFSET = 0; 328 329 NR_DEFAULTFLAGS = NR_CPSR; 330 RS_DEFAULTFLAGS = RS_CPSR; 331 332 { Low part of 64bit return value } NR_FUNCTION_RESULT64_LOW_REGnull333 function NR_FUNCTION_RESULT64_LOW_REG: tregister;{$ifdef USEINLINE}inline;{$endif USEINLINE} RS_FUNCTION_RESULT64_LOW_REGnull334 function RS_FUNCTION_RESULT64_LOW_REG: shortint;{$ifdef USEINLINE}inline;{$endif USEINLINE} 335 { High part of 64bit return value } NR_FUNCTION_RESULT64_HIGH_REGnull336 function NR_FUNCTION_RESULT64_HIGH_REG: tregister;{$ifdef USEINLINE}inline;{$endif USEINLINE} RS_FUNCTION_RESULT64_HIGH_REGnull337 function RS_FUNCTION_RESULT64_HIGH_REG: shortint;{$ifdef USEINLINE}inline;{$endif USEINLINE} 338 339 {***************************************************************************** 340 GCC /ABI linking information 341 *****************************************************************************} 342 343 const 344 { Required parameter alignment when calling a routine declared as 345 stdcall and cdecl. The alignment value should be the one defined 346 by GCC or the target ABI. 347 348 The value of this constant is equal to the constant 349 PARM_BOUNDARY / BITS_PER_UNIT in the GCC source. 350 } 351 std_param_align = 4; 352 353 354 {***************************************************************************** 355 Helpers 356 *****************************************************************************} 357 358 { Returns the tcgsize corresponding with the size of reg.} reg_cgsizenull359 function reg_cgsize(const reg: tregister) : tcgsize; cgsize2subregnull360 function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister; is_calljmpnull361 function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE} 362 procedure inverse_flags(var f: TResFlags); flags_to_condnull363 function flags_to_cond(const f: TResFlags) : TAsmCond; findreg_by_numbernull364 function findreg_by_number(r:Tregister):tregisterindex; std_regnum_searchnull365 function std_regnum_search(const s:string):Tregister; std_regnamenull366 function std_regname(r:Tregister):string; 367 inverse_condnull368 function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE} conditions_equalnull369 function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} 370 371 procedure shifterop_reset(var so : tshifterop); {$ifdef USEINLINE}inline;{$endif USEINLINE} is_pcnull372 function is_pc(const r : tregister) : boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} 373 is_shifter_constnull374 function is_shifter_const(d : aint;var imm_shift : byte) : boolean; is_thumb_immnull375 function is_thumb_imm(d: aint): boolean; 376 { Returns true if d is a valid constant for thumb 32 bit, 377 doesn't handle ROR_C detection } is_thumb32_immnull378 function is_thumb32_imm(d : aint) : boolean; split_into_shifter_constnull379 function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword):boolean; is_continuous_masknull380 function is_continuous_mask(d : aword;var lsb, width: byte) : boolean; dwarf_regnull381 function dwarf_reg(r:tregister):shortint; dwarf_reg_no_errornull382 function dwarf_reg_no_error(r:tregister):shortint; 383 IsITnull384 function IsIT(op: TAsmOp) : boolean; GetITLevelsnull385 function GetITLevels(op: TAsmOp) : longint; 386 GenerateARMCodenull387 function GenerateARMCode : boolean; GenerateThumbCodenull388 function GenerateThumbCode : boolean; GenerateThumb2Codenull389 function GenerateThumb2Code : boolean; 390 IsVFPFloatImmediatenull391 function IsVFPFloatImmediate(ft : tfloattype;value : bestreal) : boolean; 392 393 implementation 394 395 uses 396 systems,rgBase,verbose; 397 398 399 const 400 std_regname_table : TRegNameTable = ( 401 {$i rarmstd.inc} 402 ); 403 404 regnumber_index : array[tregisterindex] of tregisterindex = ( 405 {$i rarmrni.inc} 406 ); 407 408 std_regname_index : array[tregisterindex] of tregisterindex = ( 409 {$i rarmsri.inc} 410 ); 411 412 cgsize2subregnull413 function cgsize2subreg(regtype: tregistertype; s:Tcgsize):Tsubregister; 414 begin 415 case regtype of 416 R_MMREGISTER: 417 begin 418 case s of 419 OS_F32: 420 cgsize2subreg:=R_SUBFS; 421 OS_F64: 422 cgsize2subreg:=R_SUBFD; 423 else 424 internalerror(2009112701); 425 end; 426 end; 427 else 428 cgsize2subreg:=R_SUBWHOLE; 429 end; 430 end; 431 432 reg_cgsizenull433 function reg_cgsize(const reg: tregister): tcgsize; 434 begin 435 case getregtype(reg) of 436 R_INTREGISTER : 437 reg_cgsize:=OS_32; 438 R_FPUREGISTER : 439 reg_cgsize:=OS_F80; 440 R_MMREGISTER : 441 begin 442 case getsubreg(reg) of 443 R_SUBFD, 444 R_SUBWHOLE: 445 result:=OS_F64; 446 R_SUBFS: 447 result:=OS_F32; 448 else 449 internalerror(2009112903); 450 end; 451 end; 452 else 453 internalerror(200303181); 454 end; 455 end; 456 457 is_calljmpnull458 function is_calljmp(o:tasmop):boolean;{$ifdef USEINLINE}inline;{$endif USEINLINE} 459 begin 460 { This isn't 100% perfect because the arm allows jumps also by writing to PC=R15. 461 To overcome this problem we simply forbid that FPC generates jumps by loading R15 } 462 is_calljmp:= o in [A_B,A_BL,A_BX,A_BLX]; 463 end; 464 465 466 procedure inverse_flags(var f: TResFlags); 467 const 468 inv_flags: array[TResFlags] of TResFlags = 469 (F_NE,F_EQ,F_CC,F_CS,F_PL,F_MI,F_VC,F_VS,F_LS,F_HI, 470 F_LT,F_GE,F_LE,F_GT); 471 begin 472 f:=inv_flags[f]; 473 end; 474 475 flags_to_condnull476 function flags_to_cond(const f: TResFlags) : TAsmCond; 477 const 478 flag_2_cond: array[F_EQ..F_LE] of TAsmCond = 479 (C_EQ,C_NE,C_CS,C_CC,C_MI,C_PL,C_VS,C_VC,C_HI,C_LS, 480 C_GE,C_LT,C_GT,C_LE); 481 begin 482 if f>high(flag_2_cond) then 483 internalerror(200112301); 484 result:=flag_2_cond[f]; 485 end; 486 487 findreg_by_numbernull488 function findreg_by_number(r:Tregister):tregisterindex; 489 begin 490 result:=rgBase.findreg_by_number_table(r,regnumber_index); 491 end; 492 493 std_regnum_searchnull494 function std_regnum_search(const s:string):Tregister; 495 begin 496 result:=regnumber_table[findreg_by_name_table(s,std_regname_table,std_regname_index)]; 497 end; 498 499 std_regnamenull500 function std_regname(r:Tregister):string; 501 var 502 p : tregisterindex; 503 begin 504 p:=findreg_by_number_table(r,regnumber_index); 505 if p<>0 then 506 result:=std_regname_table[p] 507 else 508 result:=generic_regname(r); 509 end; 510 511 512 procedure shifterop_reset(var so : tshifterop);{$ifdef USEINLINE}inline;{$endif USEINLINE} 513 begin 514 FillChar(so,sizeof(so),0); 515 end; 516 517 is_pcnull518 function is_pc(const r : tregister) : boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} 519 begin 520 is_pc:=(r=NR_R15); 521 end; 522 523 inverse_condnull524 function inverse_cond(const c: TAsmCond): TAsmCond; {$ifdef USEINLINE}inline;{$endif USEINLINE} 525 const 526 inverse: array[TAsmCond] of TAsmCond=(C_None, 527 C_NE,C_EQ,C_CC,C_CS,C_PL,C_MI,C_VC,C_VS,C_LS,C_HI, 528 C_LT,C_GE,C_LE,C_GT,C_None,C_None 529 ); 530 begin 531 result := inverse[c]; 532 end; 533 534 conditions_equalnull535 function conditions_equal(const c1, c2: TAsmCond): boolean; {$ifdef USEINLINE}inline;{$endif USEINLINE} 536 begin 537 result := c1 = c2; 538 end; 539 540 is_shifter_constnull541 function is_shifter_const(d : aint;var imm_shift : byte) : boolean; 542 var 543 i : longint; 544 begin 545 if GenerateThumb2Code then 546 begin 547 for i:=0 to 24 do 548 begin 549 if (dword(d) and not($ff shl i))=0 then 550 begin 551 imm_shift:=i; 552 result:=true; 553 exit; 554 end; 555 end; 556 end 557 else 558 begin 559 for i:=0 to 15 do 560 begin 561 if (dword(d) and not(roldword($ff,i*2)))=0 then 562 begin 563 imm_shift:=i*2; 564 result:=true; 565 exit; 566 end; 567 end; 568 end; 569 result:=false; 570 end; 571 572 is_thumb_immnull573 function is_thumb_imm(d: aint): boolean; 574 begin 575 result:=(d and $FF) = d; 576 end; 577 578 is_thumb32_immnull579 function is_thumb32_imm(d: aint): boolean; 580 var 581 t : aint; 582 i : longint; 583 begin 584 {Loading 0-255 is simple} 585 if (d and $FF) = d then 586 result:=true 587 { If top and bottom are equal, check if either all 4 bytes are equal 588 or byte 0 and 2 or byte 1 and 3 are equal } 589 else if ((d shr 16)=(d and $FFFF)) and 590 ( 591 ((d and $FF00FF00) = 0) or 592 ((d and $00FF00FF) = 0) or 593 ((d shr 8)=(d and $FF)) 594 ) then 595 result:=true 596 {Can an 8-bit value be shifted accordingly?} 597 else 598 begin 599 result:=false; 600 for i:=8 to 31 do 601 begin 602 t:=RolDWord(d,i); 603 if ((t and $FF)=t) and 604 ((t and $80)=$80) then 605 begin 606 result:=true; 607 exit; 608 end; 609 end; 610 end; 611 end; 612 is_continuous_masknull613 function is_continuous_mask(d : aword;var lsb, width: byte) : boolean; 614 var 615 msb : byte; 616 begin 617 lsb:=BsfDword(d); 618 msb:=BsrDword(d); 619 620 width:=msb-lsb+1; 621 622 result:=(lsb<>255) and (msb<>255) and (aword(((1 shl (msb-lsb+1))-1) shl lsb) = d); 623 end; 624 625 split_into_shifter_constnull626 function split_into_shifter_const(value : aint;var imm1: dword; var imm2: dword) : boolean; 627 var 628 d, i, i2: Dword; 629 begin 630 Result:=false; 631 {Thumb2 is not supported (YET?)} 632 if GenerateThumb2Code then exit; 633 d:=DWord(value); 634 for i:=0 to 15 do 635 begin 636 imm1:=d and rordword($FF, I*2); 637 imm2:=d and not (imm1); {remove already found bits} 638 {is the remainder a shifterconst? YAY! we've done it!} 639 {Could we start from i instead of 0?} 640 for i2:=0 to 15 do 641 begin 642 if (imm2 and not(rordword($FF,i2*2)))=0 then 643 begin 644 result:=true; 645 exit; 646 end; 647 end; 648 end; 649 end; 650 dwarf_regnull651 function dwarf_reg(r:tregister):shortint; 652 begin 653 result:=regdwarf_table[findreg_by_number(r)]; 654 if result=-1 then 655 internalerror(200603251); 656 end; 657 dwarf_reg_no_errornull658 function dwarf_reg_no_error(r:tregister):shortint; 659 begin 660 result:=regdwarf_table[findreg_by_number(r)]; 661 end; 662 663 { Low part of 64bit return value } NR_FUNCTION_RESULT64_LOW_REGnull664 function NR_FUNCTION_RESULT64_LOW_REG: tregister; {$ifdef USEINLINE}inline;{$endif USEINLINE} 665 begin 666 if target_info.endian=endian_little then 667 result:=NR_R0 668 else 669 result:=NR_R1; 670 end; 671 RS_FUNCTION_RESULT64_LOW_REGnull672 function RS_FUNCTION_RESULT64_LOW_REG: shortint; {$ifdef USEINLINE}inline;{$endif USEINLINE} 673 begin 674 if target_info.endian=endian_little then 675 result:=RS_R0 676 else 677 result:=RS_R1; 678 end; 679 680 { High part of 64bit return value } NR_FUNCTION_RESULT64_HIGH_REGnull681 function NR_FUNCTION_RESULT64_HIGH_REG: tregister; {$ifdef USEINLINE}inline;{$endif USEINLINE} 682 begin 683 if target_info.endian=endian_little then 684 result:=NR_R1 685 else 686 result:=NR_R0; 687 end; 688 RS_FUNCTION_RESULT64_HIGH_REGnull689 function RS_FUNCTION_RESULT64_HIGH_REG: shortint; {$ifdef USEINLINE}inline;{$endif USEINLINE} 690 begin 691 if target_info.endian=endian_little then 692 result:=RS_R1 693 else 694 result:=RS_R0; 695 end; 696 IsITnull697 function IsIT(op: TAsmOp) : boolean; 698 begin 699 case op of 700 A_IT, 701 A_ITE, A_ITT, 702 A_ITEE, A_ITTE, A_ITET, A_ITTT, 703 A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE, 704 A_ITEET, A_ITTET, A_ITETT, A_ITTTT: 705 result:=true; 706 else 707 result:=false; 708 end; 709 end; 710 GetITLevelsnull711 function GetITLevels(op: TAsmOp) : longint; 712 begin 713 case op of 714 A_IT: 715 result:=1; 716 A_ITE, A_ITT: 717 result:=2; 718 A_ITEE, A_ITTE, A_ITET, A_ITTT: 719 result:=3; 720 A_ITEEE, A_ITTEE, A_ITETE, A_ITTTE, 721 A_ITEET, A_ITTET, A_ITETT, A_ITTTT: 722 result:=4; 723 else 724 result:=0; 725 end; 726 end; 727 728 GenerateARMCodenull729 function GenerateARMCode : boolean; 730 begin 731 Result:=current_settings.instructionset=is_arm; 732 end; 733 734 GenerateThumbCodenull735 function GenerateThumbCode : boolean; 736 begin 737 Result:=(current_settings.instructionset=is_thumb) and not(CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype]); 738 end; 739 740 GenerateThumb2Codenull741 function GenerateThumb2Code : boolean; 742 begin 743 Result:=(current_settings.instructionset=is_thumb) and (CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype]); 744 end; 745 746 IsVFPFloatImmediatenull747 function IsVFPFloatImmediate(ft : tfloattype;value : bestreal) : boolean; 748 var 749 singlerec : tcompsinglerec; 750 doublerec : tcompdoublerec; 751 begin 752 Result:=false; 753 case ft of 754 s32real: 755 begin 756 singlerec.value:=value; 757 singlerec:=tcompsinglerec(NtoLE(DWord(singlerec))); 758 Result:=(singlerec.bytes[0]=0) and (singlerec.bytes[1]=0) and ((singlerec.bytes[2] and 7)=0) and 759 (((singlerec.bytes[3] and $7e)=$40) or ((singlerec.bytes[3] and $7e)=$3e)); 760 end; 761 s64real: 762 begin 763 doublerec.value:=value; 764 doublerec:=tcompdoublerec(NtoLE(QWord(doublerec))); 765 Result:=(doublerec.bytes[0]=0) and (doublerec.bytes[1]=0) and (doublerec.bytes[2]=0) and 766 (doublerec.bytes[3]=0) and (doublerec.bytes[4]=0) and (doublerec.bytes[5]=0) and 767 ((((doublerec.bytes[6] and $7f)=$40) and ((doublerec.bytes[7] and $c0)=0)) or 768 (((doublerec.bytes[6] and $7f)=$3f) and ((doublerec.bytes[7] and $c0)=$c0))); 769 end; 770 end; 771 end; 772 773 774 end. 775 776