1 { 2 Copyright (c) 1998-2002 by Florian Klaempfl 3 4 Generate generic mathematical nodes 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 ncgmat; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 symtype, 30 node,nmat,cpubase,cgbase; 31 32 type 33 tcgunaryminusnode = class(tunaryminusnode) 34 protected 35 { This routine is called to change the sign of the 36 floating point value in the floating point 37 register r. 38 39 This routine should be overridden, since 40 the generic version is not optimal at all. The 41 generic version assumes that floating 42 point values are stored in the register 43 in IEEE-754 format. 44 } 45 procedure emit_float_sign_change(r: tregister; _size : tdef);virtual; 46 {$ifdef SUPPORT_MMX} 47 procedure second_mmx;virtual;abstract; 48 {$endif SUPPORT_MMX} 49 {$ifndef cpu64bitalu} 50 procedure second_64bit;virtual; 51 {$endif not cpu64bitalu} 52 procedure second_integer;virtual; 53 procedure second_float;virtual; 54 procedure second_float_emulated;virtual; 55 public 56 procedure pass_generate_code;override; 57 end; 58 59 tcgmoddivnode = class(tmoddivnode) 60 procedure pass_generate_code;override; 61 protected 62 { This routine must do an actual 32-bit division, be it 63 signed or unsigned. The result must set into the the 64 @var(num) register. 65 66 @param(signed Indicates if the division must be signed) 67 @param(denum Register containing the denominator 68 @param(num Register containing the numerator, will also receive result) 69 70 The actual optimizations regarding shifts have already 71 been done and emitted, so this should really a do a divide. 72 } 73 procedure emit_div_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract; 74 { This routine must do an actual 32-bit modulo, be it 75 signed or unsigned. The result must set into the the 76 @var(num) register. 77 78 @param(signed Indicates if the modulo must be signed) 79 @param(denum Register containing the denominator 80 @param(num Register containing the numerator, will also receive result) 81 82 The actual optimizations regarding shifts have already 83 been done and emitted, so this should really a do a modulo. 84 } 85 procedure emit_mod_reg_reg(signed: boolean;denum,num : tregister);virtual;abstract; 86 {$ifndef cpu64bitalu} 87 { This routine must do an actual 64-bit division, be it 88 signed or unsigned. The result must set into the the 89 @var(num) register. 90 91 @param(signed Indicates if the division must be signed) 92 @param(denum Register containing the denominator 93 @param(num Register containing the numerator, will also receive result) 94 95 The actual optimizations regarding shifts have already 96 been done and emitted, so this should really a do a divide. 97 Currently, this routine should only be implemented on 98 64-bit systems, otherwise a helper is called in 1st pass. 99 } 100 procedure emit64_div_reg_reg(signed: boolean;denum,num : tregister64);virtual; 101 {$endif not cpu64bitalu} 102 end; 103 104 tcgshlshrnode = class(tshlshrnode) 105 {$ifdef SUPPORT_MMX} 106 procedure second_mmx;virtual;abstract; 107 {$endif SUPPORT_MMX} 108 {$ifndef cpu64bitalu} 109 procedure second_64bit;virtual; 110 {$endif not cpu64bitalu} 111 procedure second_integer;virtual; 112 procedure pass_generate_code;override; 113 end; 114 115 tcgnotnode = class(tnotnode) 116 protected handle_locjumpnull117 function handle_locjump: boolean; 118 procedure second_boolean;virtual;abstract; 119 {$ifdef SUPPORT_MMX} 120 procedure second_mmx;virtual;abstract; 121 {$endif SUPPORT_MMX} 122 {$ifndef cpu64bitalu} 123 procedure second_64bit;virtual; 124 {$endif not cpu64bitalu} 125 procedure second_integer;virtual; 126 public 127 procedure pass_generate_code;override; 128 end; 129 130 131 implementation 132 133 uses 134 globtype,systems, 135 cutils,verbose,globals, 136 symtable,symconst,symdef,aasmbase,aasmdata,aasmcpu,defutil, 137 parabase, 138 pass_2, 139 ncon, 140 tgobj,cgobj,cgutils,paramgr,hlcgobj; 141 142 {***************************************************************************** 143 TCGUNARYMINUSNODE 144 *****************************************************************************} 145 146 procedure tcgunaryminusnode.emit_float_sign_change(r: tregister; _size : tdef); 147 var 148 href, 149 href2 : treference; 150 begin 151 { get a temporary memory reference to store the floating 152 point value 153 } 154 tg.gethltemp(current_asmdata.CurrAsmList,_size,_size.size,tt_normal,href); 155 { store the floating point value in the temporary memory area } 156 case getregtype(r) of 157 R_FPUREGISTER: 158 hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href); 159 R_MMREGISTER: 160 hlcg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href,mms_movescalar); 161 else 162 internalerror(2015091005); 163 end; 164 { only single and double ieee are supported, for little endian 165 the signed bit is in the second dword } 166 href2:=href; 167 if _size.typ<>floatdef then 168 internalerror(2014012211); 169 case tfloatdef(_size).floattype of 170 s64real, 171 s64comp, 172 s64currency: 173 if target_info.endian = endian_little then 174 inc(href2.offset,4); 175 s32real : 176 ; 177 else 178 internalerror(200406021); 179 end; 180 { flip sign-bit (bit 31/63) of single/double } 181 hlcg.a_op_const_ref(current_asmdata.CurrAsmList,OP_XOR,u32inttype, 182 {$ifdef cpu64bitalu} 183 aint($80000000), 184 {$else cpu64bitalu} 185 longint($80000000), 186 {$endif cpu64bitalu} 187 href2); 188 case getregtype(r) of 189 R_FPUREGISTER: 190 hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r); 191 R_MMREGISTER: 192 hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r,mms_movescalar); 193 else 194 internalerror(2015091006); 195 end; 196 tg.ungetiftemp(current_asmdata.CurrAsmList,href); 197 end; 198 199 200 {$ifndef cpu64bitalu} 201 procedure tcgunaryminusnode.second_64bit; 202 var 203 tr: tregister; 204 hl: tasmlabel; 205 begin 206 secondpass(left); 207 location_reset(location,LOC_REGISTER,left.location.size); 208 location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); 209 location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); 210 cg64.a_op64_loc_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64, 211 left.location,joinreg64(location.register64.reglo,location.register64.reghi)); 212 { there's only overflow in case left was low(int64) -> -left = left } 213 if (cs_check_overflow in current_settings.localswitches) then 214 begin 215 tr:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); 216 cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32, 217 longint($80000000),location.register64.reghi,tr); 218 cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_OR,OS_32, 219 location.register64.reglo,tr); 220 current_asmdata.getjumplabel(hl); 221 cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_32,OC_NE,0,tr,hl); 222 cg.a_call_name(current_asmdata.CurrAsmList,'FPC_OVERFLOW',false); 223 cg.a_label(current_asmdata.CurrAsmList,hl); 224 end; 225 end; 226 {$endif not cpu64bitalu} 227 228 229 procedure tcgunaryminusnode.second_float_emulated; 230 begin 231 secondpass(left); 232 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); 233 location:=left.location; 234 case location.size of 235 OS_32: 236 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.register); 237 OS_64: 238 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_XOR,OS_32,tcgint($80000000),location.registerhi); 239 else 240 internalerror(2014033101); 241 end; 242 end; 243 244 245 procedure tcgunaryminusnode.second_float; 246 begin 247 secondpass(left); 248 location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef)); 249 case left.location.loc of 250 LOC_REFERENCE, 251 LOC_CREFERENCE : 252 begin 253 location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef); 254 case getregtype(location.register) of 255 R_FPUREGISTER: 256 hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList, 257 left.resultdef,resultdef, 258 left.location.reference,location.register); 259 R_MMREGISTER: 260 hlcg.a_loadmm_ref_reg(current_asmdata.CurrAsmList, 261 left.resultdef,resultdef, 262 left.location.reference,location.register,mms_movescalar); 263 else 264 internalerror(2015091004); 265 end; 266 emit_float_sign_change(location.register,left.resultdef); 267 end; 268 LOC_FPUREGISTER, 269 LOC_CFPUREGISTER: 270 begin 271 location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef); 272 hlcg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register); 273 emit_float_sign_change(location.register,left.resultdef); 274 end; 275 LOC_MMREGISTER, 276 LOC_CMMREGISTER: 277 begin 278 location.register:=hlcg.getmmregister(current_asmdata.CurrAsmList,resultdef); 279 hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,left.resultdef,resultdef,left.location.register,location.register,mms_movescalar); 280 emit_float_sign_change(location.register,left.resultdef); 281 end 282 else 283 internalerror(200306021); 284 end; 285 end; 286 287 288 procedure tcgunaryminusnode.second_integer; 289 var 290 hl: tasmlabel; 291 opsize: tdef; 292 begin 293 secondpass(left); 294 295 {$ifdef cpunodefaultint} 296 opsize:=left.resultdef; 297 {$else cpunodefaultint} 298 { in case of a 32 bit system that can natively execute 64 bit operations } 299 if (left.resultdef.size<=sinttype.size) then 300 opsize:=sinttype 301 else 302 opsize:={$ifdef cpu16bitalu}s32inttype{$else}s64inttype{$endif}; 303 {$endif cpunodefaultint} 304 if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then 305 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opsize,false); 306 location_reset(location,LOC_REGISTER,def_cgsize(opsize)); 307 location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size); 308 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,opsize,left.location.register,location.register); 309 310 if (cs_check_overflow in current_settings.localswitches) then 311 begin 312 current_asmdata.getjumplabel(hl); 313 hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_NE,torddef(opsize).low.svalue,location.register,hl); 314 hlcg.g_call_system_proc(current_asmdata.CurrAsmList,'fpc_overflow',[],nil); 315 hlcg.a_label(current_asmdata.CurrAsmList,hl); 316 end; 317 end; 318 319 320 procedure tcgunaryminusnode.pass_generate_code; 321 begin 322 {$ifndef cpu64bitalu} 323 if is_64bit(left.resultdef) then 324 second_64bit 325 else 326 {$endif not cpu64bitalu} 327 {$ifdef SUPPORT_MMX} 328 if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then 329 second_mmx 330 else 331 {$endif SUPPORT_MMX} 332 if (left.resultdef.typ=floatdef) then 333 begin 334 if (cs_fp_emulation in current_settings.moduleswitches) then 335 second_float_emulated 336 else 337 second_float; 338 end 339 else 340 second_integer; 341 end; 342 343 344 {***************************************************************************** 345 TCGMODDIVNODE 346 *****************************************************************************} 347 348 {$ifndef cpu64bitalu} 349 procedure tcgmoddivnode.emit64_div_reg_reg(signed: boolean; denum,num:tregister64); 350 begin 351 { handled in pass_1 already, unless pass_1 is 352 overridden 353 } 354 { should be handled in pass_1 (JM) } 355 internalerror(200109052); 356 end; 357 {$endif not cpu64bitalu} 358 359 360 procedure tcgmoddivnode.pass_generate_code; 361 var 362 hreg1 : tregister; 363 hdenom : tregister; 364 power : longint; 365 hl : tasmlabel; 366 paraloc1 : tcgpara; 367 opsize : tcgsize; 368 opdef : tdef; 369 pd: tprocdef; 370 begin 371 secondpass(left); 372 if codegenerror then 373 exit; 374 secondpass(right); 375 if codegenerror then 376 exit; 377 location_copy(location,left.location); 378 379 {$ifndef cpu64bitalu} 380 if is_64bit(resultdef) then 381 begin 382 if is_signed(left.resultdef) then 383 opdef:=s64inttype 384 else 385 opdef:=u64inttype; 386 387 { this code valid for 64-bit cpu's only , 388 otherwise helpers are called in pass_1 389 } 390 hlcg.location_force_reg(current_asmdata.CurrAsmList,location,left.resultdef,opdef,false); 391 location_copy(location,left.location); 392 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,opdef,false); 393 emit64_div_reg_reg(is_signed(left.resultdef), 394 joinreg64(right.location.register64.reglo,right.location.register64.reghi), 395 joinreg64(location.register64.reglo,location.register64.reghi)); 396 end 397 else 398 {$endif not cpu64bitalu} 399 begin 400 if is_signed(left.resultdef) then 401 begin 402 opsize:=OS_SINT; 403 opdef:=ossinttype; 404 end 405 else 406 begin 407 opsize:=OS_INT; 408 opdef:=osuinttype; 409 end; 410 411 { put numerator in register } 412 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,false); 413 hreg1:=left.location.register; 414 415 if (nodetype=divn) and 416 (right.nodetype=ordconstn) and 417 ispowerof2(tordconstnode(right).value.svalue,power) then 418 Begin 419 { for signed numbers, the numerator must be adjusted before the 420 shift instruction, but not wih unsigned numbers! Otherwise, 421 "Cardinal($ffffffff) div 16" overflows! (JM) } 422 If is_signed(left.resultdef) Then 423 Begin 424 current_asmdata.getjumplabel(hl); 425 cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_GT,0,hreg1,hl); 426 if power=1 then 427 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,1,hreg1) 428 else 429 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,Tordconstnode(right).value.svalue-1,hreg1); 430 cg.a_label(current_asmdata.CurrAsmList,hl); 431 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,OS_INT,power,hreg1); 432 End 433 Else { not signed } 434 cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,power,hreg1); 435 End 436 else 437 begin 438 { bring denominator to hdenom } 439 { hdenom is always free, it's } 440 { only used for temporary } 441 { purposes } 442 hdenom := cg.getintregister(current_asmdata.CurrAsmList,OS_INT); 443 hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,osuinttype,right.location,hdenom); 444 { verify if the divisor is zero, if so return an error immediately, 445 except if we have a const node, where we don't need this, because 446 then zero check was done earlier. 447 } 448 if (right.nodetype <> ordconstn) then 449 begin 450 current_asmdata.getjumplabel(hl); 451 cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_NE,0,hdenom,hl); 452 paraloc1.init; 453 pd:=search_system_proc('fpc_handleerror'); 454 paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1); 455 cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_S32,aint(200),paraloc1); 456 paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1); 457 cg.a_call_name(current_asmdata.CurrAsmList,'FPC_HANDLEERROR',false); 458 paraloc1.done; 459 cg.a_label(current_asmdata.CurrAsmList,hl); 460 end; 461 if nodetype = modn then 462 emit_mod_reg_reg(is_signed(left.resultdef),hdenom,hreg1) 463 else 464 emit_div_reg_reg(is_signed(left.resultdef),hdenom,hreg1); 465 end; 466 location_reset(location,LOC_REGISTER,opsize); 467 location.register:=hreg1; 468 end; 469 cg.g_overflowcheck(current_asmdata.CurrAsmList,location,resultdef); 470 end; 471 472 473 {***************************************************************************** 474 TCGSHLRSHRNODE 475 *****************************************************************************} 476 477 478 {$ifndef cpu64bitalu} 479 procedure tcgshlshrnode.second_64bit; 480 begin 481 { already hanled in 1st pass } 482 internalerror(2002081501); 483 end; 484 {$endif not cpu64bitalu} 485 486 487 procedure tcgshlshrnode.second_integer; 488 var 489 op : topcg; 490 opdef,shiftcountdef: tdef; 491 hcountreg : tregister; 492 opsize : tcgsize; 493 shiftval : longint; 494 begin 495 { determine operator } 496 case nodetype of 497 shln: op:=OP_SHL; 498 shrn: op:=OP_SHR; 499 else 500 internalerror(2013120102); 501 end; 502 {$ifdef cpunodefaultint} 503 opsize:=left.location.size; 504 opdef:=left.resultdef; 505 shiftcountdef:=opdef; 506 {$else cpunodefaultint} 507 if left.resultdef.size<=4 then 508 begin 509 if is_signed(left.resultdef) then 510 begin 511 if (sizeof(aint)<4) and 512 (left.resultdef.size<=sizeof(aint)) then 513 begin 514 opsize:=OS_SINT; 515 opdef:=sinttype; 516 end 517 else 518 begin 519 opdef:=s32inttype; 520 opsize:=OS_S32; 521 end; 522 {$ifdef cpu16bitalu} 523 shiftcountdef:=s16inttype; 524 {$else cpu16bitalu} 525 shiftcountdef:=opdef; 526 {$endif cpu16bitalu} 527 end 528 else 529 begin 530 if (sizeof(aint)<4) and 531 (left.resultdef.size<=sizeof(aint)) then 532 begin 533 opsize:=OS_INT; 534 opdef:=uinttype; 535 end 536 else 537 begin 538 opdef:=u32inttype; 539 opsize:=OS_32; 540 end; 541 {$ifdef cpu16bitalu} 542 shiftcountdef:=u16inttype; 543 {$else cpu16bitalu} 544 shiftcountdef:=opdef; 545 {$endif cpu16bitalu} 546 end 547 end 548 else 549 begin 550 if is_signed(left.resultdef) then 551 begin 552 opdef:=s64inttype; 553 opsize:=OS_S64; 554 end 555 else 556 begin 557 opdef:=u64inttype; 558 opsize:=OS_64; 559 end; 560 shiftcountdef:=opdef; 561 end; 562 {$endif cpunodefaultint} 563 564 if not(left.location.loc in [LOC_CREGISTER,LOC_REGISTER]) or 565 { location_force_reg can be also used to change the size of a register } 566 (left.location.size<>opsize) then 567 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,opdef,true); 568 location_reset(location,LOC_REGISTER,opsize); 569 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 570 571 { shifting by a constant directly coded: } 572 if (right.nodetype=ordconstn) then 573 begin 574 { shl/shr must "wrap around", so use ... and 31 } 575 { In TP, "byte/word shl 16 = 0", so no "and 15" in case of 576 a 16 bit ALU } 577 if tcgsize2size[opsize]<=4 then 578 shiftval:=tordconstnode(right).value.uvalue and 31 579 else 580 shiftval:=tordconstnode(right).value.uvalue and 63; 581 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,opdef, 582 shiftval,left.location.register,location.register); 583 end 584 else 585 begin 586 { load right operators in a register - this 587 is done since most target cpu which will use this 588 node do not support a shift count in a mem. location (cec) 589 } 590 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,shiftcountdef,true); 591 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,opdef,right.location.register,left.location.register,location.register); 592 end; 593 { shl/shr nodes return the same type as left, which can be different 594 from opdef } 595 if opdef<>resultdef then 596 begin 597 hcountreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 598 hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,opdef,resultdef,location.register,hcountreg); 599 location.register:=hcountreg; 600 end; 601 end; 602 603 604 procedure tcgshlshrnode.pass_generate_code; 605 begin 606 secondpass(left); 607 secondpass(right); 608 {$ifdef SUPPORT_MMX} 609 if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then 610 second_mmx 611 else 612 {$endif SUPPORT_MMX} 613 {$ifndef cpu64bitalu} 614 if is_64bit(left.resultdef) then 615 second_64bit 616 else 617 {$endif not cpu64bitalu} 618 second_integer; 619 end; 620 621 622 {***************************************************************************** 623 TCGNOTNODE 624 *****************************************************************************} 625 626 {$ifndef cpu64bitalu} 627 procedure tcgnotnode.second_64bit; 628 begin 629 secondpass(left); 630 if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then 631 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); 632 location_reset(location,LOC_REGISTER,left.location.size); 633 location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); 634 location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32); 635 { perform the NOT operation } 636 cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NOT,location.size,left.location.register64,location.register64); 637 end; 638 {$endif not cpu64bitalu} 639 640 641 procedure tcgnotnode.second_integer; 642 begin 643 secondpass(left); 644 if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then 645 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); 646 location_reset(location,LOC_REGISTER,left.location.size); 647 location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size); 648 { perform the NOT operation } 649 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,location.register); 650 end; 651 652 tcgnotnode.handle_locjumpnull653 function tcgnotnode.handle_locjump: boolean; 654 begin 655 result:=(left.expectloc=LOC_JUMP); 656 if result then 657 begin 658 secondpass(left); 659 660 if is_constboolnode(left) then 661 internalerror(2014010101); 662 if left.location.loc<>LOC_JUMP then 663 internalerror(2012081306); 664 665 { switch true and false labels to invert result } 666 location_reset_jump(location,left.location.falselabel,left.location.truelabel); 667 end; 668 end; 669 670 671 procedure tcgnotnode.pass_generate_code; 672 begin 673 if is_boolean(resultdef) then 674 second_boolean 675 {$ifdef SUPPORT_MMX} 676 else if (cs_mmx in current_settings.localswitches) and is_mmx_able_array(left.resultdef) then 677 second_mmx 678 {$endif SUPPORT_MMX} 679 {$ifndef cpu64bitalu} 680 else if is_64bit(left.resultdef) then 681 second_64bit 682 {$endif not cpu64bitalu} 683 else 684 second_integer; 685 end; 686 687 begin 688 cmoddivnode:=tcgmoddivnode; 689 cunaryminusnode:=tcgunaryminusnode; 690 cshlshrnode:=tcgshlshrnode; 691 cnotnode:=tcgnotnode; 692 end. 693