1 { 2 Copyright (c) 2000-2002 by the FPC development team 3 4 Code generation for add nodes (generic version) 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 ncgadd; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 node,nadd,cpubase,cgbase; 30 31 type 32 tcgaddnode = class(taddnode) 33 { function pass_1: tnode; override;} 34 procedure pass_generate_code;override; 35 protected 36 { call secondpass for both left and right } 37 procedure pass_left_right; virtual; 38 { set the register of the result location } 39 procedure set_result_location_reg; 40 { load left and right nodes into registers } 41 procedure force_reg_left_right(allow_swap,allow_constant:boolean); virtual; 42 cmpnode2topcmpnull43 function cmpnode2topcmp(unsigned: boolean): TOpCmp; 44 45 procedure second_opfloat; 46 procedure second_opboolean; 47 procedure second_opsmallset; 48 procedure second_op64bit; 49 procedure second_opordinal; 50 51 procedure second_addstring;virtual; 52 procedure second_addfloat;virtual;abstract; 53 procedure second_addboolean;virtual; 54 procedure second_addsmallset;virtual; 55 procedure second_addsmallsetelement;virtual; 56 {$ifdef x86} 57 {$ifdef SUPPORT_MMX} 58 procedure second_opmmx;virtual;abstract; 59 {$endif SUPPORT_MMX} 60 {$endif x86} 61 procedure second_opvector;virtual;abstract; 62 procedure second_add64bit;virtual; 63 procedure second_addordinal;virtual; 64 procedure second_cmpfloat;virtual;abstract; 65 procedure second_cmpboolean;virtual; 66 procedure second_cmpsmallset;virtual;abstract; 67 procedure second_cmp64bit;virtual;abstract; 68 procedure second_cmpordinal;virtual;abstract; 69 end; 70 71 implementation 72 73 uses 74 globtype,systems, 75 verbose,globals, 76 symconst,symdef, 77 aasmbase,aasmdata,defutil, 78 pass_2,tgobj, 79 nutils,nset,ncgutil,cgobj,cgutils, 80 hlcgobj 81 ; 82 83 84 {***************************************************************************** 85 Helpers 86 *****************************************************************************} 87 88 procedure tcgaddnode.pass_left_right; 89 {$if defined(x86) and not defined(llvm)} 90 var 91 tmpreg : tregister; 92 pushedfpu : boolean; 93 {$endif x86 and not llvm} 94 begin 95 { calculate the operator which is more difficult } 96 firstcomplex(self); 97 98 { in case of constant put it to the left } 99 if (left.nodetype=ordconstn) then 100 swapleftright; 101 102 secondpass(left); 103 if left.location.loc in [LOC_FLAGS,LOC_JUMP] then 104 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false); 105 {$if defined(x86) and not defined(llvm)} 106 { are too few registers free? } 107 pushedfpu:=false; 108 if (left.location.loc=LOC_FPUREGISTER) and 109 (node_resources_fpu(right)>=maxfpuregs) then 110 begin 111 hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef); 112 pushedfpu:=true; 113 end; 114 {$endif x86 and not llvm} 115 116 secondpass(right); 117 if right.location.loc in [LOC_FLAGS,LOC_JUMP] then 118 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,false); 119 {$if defined(x86) and not defined(llvm)} 120 if pushedfpu then 121 begin 122 if use_vectorfpu(left.resultdef) then 123 begin 124 tmpreg := cg.getmmregister(current_asmdata.CurrAsmList,left.location.size); 125 hlcg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,left.location,tmpreg,mms_movescalar); 126 location_freetemp(current_asmdata.CurrAsmList,left.location); 127 location_reset(left.location,LOC_MMREGISTER,left.location.size); 128 left.location.register:=tmpreg; 129 end 130 else 131 begin 132 tmpreg := cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size); 133 cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location,tmpreg); 134 location_freetemp(current_asmdata.CurrAsmList,left.location); 135 location_reset(left.location,LOC_FPUREGISTER,left.location.size); 136 left.location.register := tmpreg; 137 { left operand is now on top of the stack, instead of the right one! } 138 if (right.location.loc=LOC_FPUREGISTER) then 139 toggleflag(nf_swapped); 140 end; 141 end; 142 {$endif x86 and not llvm} 143 end; 144 145 146 procedure tcgaddnode.set_result_location_reg; 147 begin 148 location_reset(location,LOC_REGISTER,def_cgsize(resultdef)); 149 {$ifndef cpu64bitalu} 150 if location.size in [OS_64,OS_S64] then 151 begin 152 location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32); 153 location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32); 154 end 155 else 156 {$endif} 157 location.register := hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 158 end; 159 160 161 procedure tcgaddnode.force_reg_left_right(allow_swap,allow_constant:boolean); 162 begin 163 if (left.location.loc<>LOC_REGISTER) and 164 not( 165 allow_constant and 166 (left.location.loc in [LOC_CONSTANT,LOC_CREGISTER]) 167 ) then 168 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); 169 if (right.location.loc<>LOC_REGISTER) and 170 not( 171 allow_constant and 172 (right.location.loc in [LOC_CONSTANT,LOC_CREGISTER]) and 173 (left.location.loc<>LOC_CONSTANT) 174 ) then 175 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false); 176 177 { Left is always a register, right can be register or constant } 178 if left.location.loc=LOC_CONSTANT then 179 begin 180 { when it is not allowed to swap we have a constant on 181 left, that will give problems } 182 if not allow_swap then 183 internalerror(200307043); 184 swapleftright; 185 end; 186 end; 187 188 tcgaddnode.cmpnode2topcmpnull189 function tcgaddnode.cmpnode2topcmp(unsigned: boolean): TOpCmp; 190 begin 191 if unsigned then 192 case nodetype of 193 gtn: result:=OC_A; 194 gten: result:=OC_AE; 195 ltn: result:=OC_B; 196 lten: result:=OC_BE; 197 equaln: result:=OC_EQ; 198 unequaln: result:=OC_NE; 199 else 200 internalerror(2011010412); 201 end 202 else 203 case nodetype of 204 gtn: result:=OC_GT; 205 gten: result:=OC_GTE; 206 ltn: result:=OC_LT; 207 lten: result:=OC_LTE; 208 equaln: result:=OC_EQ; 209 unequaln: result:=OC_NE; 210 else 211 internalerror(2011010412); 212 end 213 end; 214 215 {***************************************************************************** 216 Smallsets 217 *****************************************************************************} 218 219 procedure tcgaddnode.second_opsmallset; 220 begin 221 { when a setdef is passed, it has to be a smallset } 222 if not( 223 ((left.nodetype=setelementn) or is_smallset(left.resultdef)) and 224 ((right.nodetype=setelementn) or is_smallset(right.resultdef)) 225 ) then 226 internalerror(200203302); 227 if (left.nodetype=setelementn) or (right.nodetype=setelementn) then 228 second_addsmallsetelement 229 else if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then 230 second_cmpsmallset 231 else 232 second_addsmallset; 233 end; 234 235 236 procedure tcgaddnode.second_addsmallset; 237 var 238 cgop : TOpCg; 239 opdone : boolean; 240 begin 241 opdone := false; 242 pass_left_right; 243 force_reg_left_right(true,true); 244 set_result_location_reg; 245 case nodetype of 246 addn : 247 cgop:=OP_OR; 248 symdifn : 249 cgop:=OP_XOR; 250 muln : 251 cgop:=OP_AND; 252 subn : 253 begin 254 cgop:=OP_AND; 255 if (not(nf_swapped in flags)) then 256 if (right.location.loc=LOC_CONSTANT) then 257 right.location.value := not(right.location.value) 258 else 259 opdone := true 260 else if (left.location.loc=LOC_CONSTANT) then 261 left.location.value := not(left.location.value) 262 else 263 begin 264 swapleftright; 265 opdone := true; 266 end; 267 if opdone then 268 begin 269 if (right.location.size<>left.location.size) or 270 (location.size<>left.location.size) then 271 internalerror(2010123001); 272 { make sure that location.register is different from 273 left.location.register, since right will overwrite it 274 and we'll use left afterwards } 275 if (right.location.loc=LOC_REGISTER) then 276 location.register:=right.location.register 277 else 278 location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size); 279 { make sure we don't modify left/right.location, because we told 280 force_reg_left_right above that they can be constant } 281 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,resultdef,right.location.register,location.register); 282 if left.location.loc = LOC_CONSTANT then 283 hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.value,location.register) 284 else 285 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.register,location.register); 286 end; 287 end; 288 else 289 internalerror(2002072701); 290 end; 291 292 if not opdone then 293 begin 294 // these are all commutative operations 295 if (left.location.loc = LOC_CONSTANT) then 296 swapleftright; 297 if (right.location.loc = LOC_CONSTANT) then 298 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef, 299 right.location.value,left.location.register, 300 location.register) 301 else 302 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef, 303 right.location.register,left.location.register, 304 location.register); 305 end; 306 end; 307 308 309 procedure tcgaddnode.second_addsmallsetelement; 310 var 311 tmpreg : tregister; 312 mask, 313 setbase : aint; 314 cgop : TOpCg; 315 begin 316 if nodetype<>addn then 317 internalerror(20080302); 318 { no range support for smallsets } 319 if assigned(tsetelementnode(right).right) then 320 internalerror(20080303); 321 pass_left_right; 322 { setelementn is a special case, it must be on right } 323 if (nf_swapped in flags) and 324 (left.nodetype=setelementn) then 325 swapleftright; 326 force_reg_left_right(false,false); 327 set_result_location_reg; 328 setbase:=tsetdef(left.resultdef).setbase; 329 if (right.location.loc = LOC_CONSTANT) then 330 begin 331 if (target_info.endian=endian_big) then 332 mask:=aint((aword(1) shl (resultdef.size*8-1)) shr aword(right.location.value-setbase)) 333 else 334 mask:=aint(1 shl (right.location.value-setbase)); 335 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef, 336 mask,left.location.register,location.register); 337 end 338 else 339 begin 340 if (target_info.endian=endian_big) then 341 begin 342 mask:=aint((aword(1) shl (resultdef.size*8-1))); 343 cgop:=OP_SHR 344 end 345 else 346 begin 347 mask:=1; 348 cgop:=OP_SHL 349 end; 350 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 351 hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,mask,tmpreg); 352 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true); 353 register_maybe_adjust_setbase(current_asmdata.CurrAsmList,resultdef,right.location,setbase); 354 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef, 355 right.location.register,tmpreg); 356 if left.location.loc <> LOC_CONSTANT then 357 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef,tmpreg, 358 left.location.register,location.register) 359 else 360 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef, 361 left.location.value,tmpreg,location.register); 362 end; 363 end; 364 365 366 {***************************************************************************** 367 Boolean 368 *****************************************************************************} 369 370 procedure tcgaddnode.second_opboolean; 371 begin 372 if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then 373 second_cmpboolean 374 else 375 second_addboolean; 376 end; 377 378 379 procedure tcgaddnode.second_addboolean; 380 var 381 cgop : TOpCg; 382 truelabel, falselabel : tasmlabel; 383 oldflowcontrol : tflowcontrol; 384 begin 385 { And,Or will only evaluate from left to right only the 386 needed nodes unless full boolean evaluation is enabled } 387 if (nodetype in [orn,andn]) and 388 (not(cs_full_boolean_eval in current_settings.localswitches) or 389 (nf_short_bool in flags)) then 390 begin 391 case nodetype of 392 andn : 393 begin 394 secondpass(left); 395 hlcg.maketojumpbool(current_asmdata.CurrAsmList,left); 396 hlcg.a_label(current_asmdata.CurrAsmList,left.location.truelabel); 397 current_asmdata.getjumplabel(truelabel); 398 location_reset_jump(location,truelabel,left.location.falselabel); 399 end; 400 orn : 401 begin 402 secondpass(left); 403 hlcg.maketojumpbool(current_asmdata.CurrAsmList,left); 404 hlcg.a_label(current_asmdata.CurrAsmList,left.location.falselabel); 405 current_asmdata.getjumplabel(falselabel); 406 location_reset_jump(location,left.location.truelabel,falselabel); 407 end; 408 else 409 internalerror(200307044); 410 end; 411 { these jumps mean we're now in a flow control construct } 412 oldflowcontrol:=flowcontrol; 413 include(flowcontrol,fc_inflowcontrol); 414 415 secondpass(right); 416 { jump to the same labels as the left side, since the andn/orn 417 merges the results of left and right } 418 hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,right,location.truelabel,location.falselabel); 419 420 flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]); 421 end 422 else 423 begin 424 pass_left_right; 425 force_reg_left_right(false,true); 426 set_result_location_reg; 427 428 case nodetype of 429 xorn : 430 cgop:=OP_XOR; 431 orn : 432 cgop:=OP_OR; 433 andn : 434 cgop:=OP_AND; 435 else 436 internalerror(200203247); 437 end; 438 {$ifndef cpu64bitalu} 439 if right.location.size in [OS_64,OS_S64] then 440 begin 441 if right.location.loc <> LOC_CONSTANT then 442 cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,cgop,location.size, 443 left.location.register64,right.location.register64, 444 location.register64) 445 else 446 cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,cgop,location.size, 447 right.location.value,left.location.register64, 448 location.register64); 449 end 450 else 451 {$endif cpu64bitalu} 452 begin 453 if right.location.loc <> LOC_CONSTANT then 454 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef, 455 left.location.register,right.location.register, 456 location.register) 457 else 458 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef, 459 right.location.value,left.location.register, 460 location.register); 461 end; 462 end; 463 end; 464 465 466 {***************************************************************************** 467 64-bit 468 *****************************************************************************} 469 470 procedure tcgaddnode.second_op64bit; 471 begin 472 if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then 473 second_cmp64bit 474 else 475 second_add64bit; 476 end; 477 478 479 procedure tcgaddnode.second_add64bit; 480 var 481 op : TOpCG; 482 checkoverflow : boolean; 483 ovloc : tlocation; 484 begin 485 ovloc.loc:=LOC_VOID; 486 487 pass_left_right; 488 force_reg_left_right(false,true); 489 set_result_location_reg; 490 491 { assume no overflow checking is required } 492 checkoverflow := false; 493 case nodetype of 494 addn : 495 begin 496 op:=OP_ADD; 497 checkoverflow:=true; 498 end; 499 subn : 500 begin 501 op:=OP_SUB; 502 checkoverflow:=true; 503 end; 504 xorn: 505 op:=OP_XOR; 506 orn: 507 op:=OP_OR; 508 andn: 509 op:=OP_AND; 510 muln: 511 begin 512 { should be handled in pass_1 (JM) } 513 internalerror(200109051); 514 end; 515 else 516 internalerror(2002072705); 517 end; 518 519 checkoverflow:= 520 checkoverflow and 521 (left.resultdef.typ<>pointerdef) and 522 (right.resultdef.typ<>pointerdef) and 523 (cs_check_overflow in current_settings.localswitches) and not(nf_internal in flags); 524 525 {$ifdef cpu64bitalu} 526 case nodetype of 527 xorn,orn,andn,addn: 528 begin 529 if (right.location.loc = LOC_CONSTANT) then 530 hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,right.location.value, 531 left.location.register,location.register) 532 else 533 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,resultdef,right.location.register, 534 left.location.register,location.register); 535 end; 536 subn: 537 begin 538 if (nf_swapped in flags) then 539 swapleftright; 540 541 if left.location.loc <> LOC_CONSTANT then 542 begin 543 if right.location.loc <> LOC_CONSTANT then 544 // reg64 - reg64 545 hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 546 right.location.register,left.location.register,location.register, 547 checkoverflow,ovloc) 548 else 549 // reg64 - const64 550 hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 551 right.location.value,left.location.register,location.register, 552 checkoverflow,ovloc); 553 end 554 else 555 begin 556 // const64 - reg64 557 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); 558 hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 559 right.location.register,left.location.register,location.register, 560 checkoverflow,ovloc); 561 end; 562 end; 563 else 564 internalerror(2002072803); 565 end; 566 {$else cpu64bitalu} 567 case nodetype of 568 xorn,orn,andn,addn: 569 begin 570 if (right.location.loc = LOC_CONSTANT) then 571 cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.value64, 572 left.location.register64,location.register64, 573 checkoverflow,ovloc) 574 else 575 cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.register64, 576 left.location.register64,location.register64, 577 checkoverflow,ovloc); 578 end; 579 subn: 580 begin 581 if (nf_swapped in flags) then 582 swapleftright; 583 584 if left.location.loc <> LOC_CONSTANT then 585 begin 586 if right.location.loc <> LOC_CONSTANT then 587 // reg64 - reg64 588 cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size, 589 right.location.register64,left.location.register64, 590 location.register64, 591 checkoverflow,ovloc) 592 else 593 // reg64 - const64 594 cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size, 595 right.location.value64,left.location.register64, 596 location.register64, 597 checkoverflow,ovloc) 598 end 599 else 600 begin 601 // const64 - reg64 602 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true); 603 cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size, 604 right.location.register64,left.location.register64, 605 location.register64, 606 checkoverflow,ovloc); 607 end; 608 end; 609 else 610 internalerror(2002072803); 611 end; 612 {$endif cpu64bitalu} 613 614 { emit overflow check if enabled } 615 if checkoverflow then 616 hlcg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc); 617 end; 618 619 620 {***************************************************************************** 621 Strings 622 *****************************************************************************} 623 624 procedure tcgaddnode.second_addstring; 625 begin 626 { this should already be handled in pass1 } 627 internalerror(2002072402); 628 end; 629 630 631 {***************************************************************************** 632 Floats 633 *****************************************************************************} 634 635 procedure tcgaddnode.second_opfloat; 636 begin 637 if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then 638 second_cmpfloat 639 else 640 second_addfloat; 641 end; 642 643 644 {***************************************************************************** 645 Ordinals 646 *****************************************************************************} 647 648 procedure tcgaddnode.second_opordinal; 649 begin 650 if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) then 651 second_cmpordinal 652 else 653 second_addordinal; 654 end; 655 656 657 procedure tcgaddnode.second_addordinal; 658 var 659 unsigned, 660 checkoverflow : boolean; 661 cgop : topcg; 662 tmpreg : tregister; 663 ovloc : tlocation; 664 begin 665 ovloc.loc:=LOC_VOID; 666 667 pass_left_right; 668 force_reg_left_right(false,true); 669 set_result_location_reg; 670 671 { determine if the comparison will be unsigned } 672 unsigned:=not(is_signed(left.resultdef)) or 673 not(is_signed(right.resultdef)); 674 675 { assume no overflow checking is require } 676 checkoverflow := false; 677 678 case nodetype of 679 addn: 680 begin 681 cgop:=OP_ADD; 682 checkoverflow:=true; 683 end; 684 xorn : 685 begin 686 cgop:=OP_XOR; 687 end; 688 orn : 689 begin 690 cgop:=OP_OR; 691 end; 692 andn: 693 begin 694 cgop:=OP_AND; 695 end; 696 muln: 697 begin 698 checkoverflow:=true; 699 if unsigned then 700 cgop:=OP_MUL 701 else 702 cgop:=OP_IMUL; 703 end; 704 subn : 705 begin 706 checkoverflow:=true; 707 cgop:=OP_SUB; 708 end; 709 else 710 internalerror(2013120104); 711 end; 712 713 checkoverflow:= 714 checkoverflow and 715 (left.resultdef.typ<>pointerdef) and 716 (right.resultdef.typ<>pointerdef) and 717 (cs_check_overflow in current_settings.localswitches) and not(nf_internal in flags); 718 719 if nodetype<>subn then 720 begin 721 if (right.location.loc<>LOC_CONSTANT) then 722 hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,resultdef, 723 left.location.register,right.location.register, 724 location.register,checkoverflow,ovloc) 725 else 726 hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,resultdef, 727 right.location.value,left.location.register, 728 location.register,checkoverflow,ovloc); 729 end 730 else { subtract is a special case since its not commutative } 731 begin 732 if (nf_swapped in flags) then 733 swapleftright; 734 if left.location.loc<>LOC_CONSTANT then 735 begin 736 if right.location.loc<>LOC_CONSTANT then 737 hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 738 right.location.register,left.location.register, 739 location.register,checkoverflow,ovloc) 740 else 741 hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 742 right.location.value,left.location.register, 743 location.register,checkoverflow,ovloc); 744 end 745 else 746 begin 747 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 748 hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef, 749 left.location.value,tmpreg); 750 hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef, 751 right.location.register,tmpreg,location.register,checkoverflow,ovloc); 752 end; 753 end; 754 755 { emit overflow check if required } 756 if checkoverflow then 757 hlcg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc); 758 end; 759 760 761 procedure tcgaddnode.second_cmpboolean; 762 begin 763 second_cmpordinal; 764 end; 765 766 767 {***************************************************************************** 768 pass_generate_code; 769 *****************************************************************************} 770 771 procedure tcgaddnode.pass_generate_code; 772 begin 773 case left.resultdef.typ of 774 orddef : 775 begin 776 { handling boolean expressions } 777 if is_boolean(left.resultdef) and 778 is_boolean(right.resultdef) then 779 second_opboolean 780 { 64bit operations } 781 else if is_64bit(left.resultdef) then 782 second_op64bit 783 else 784 second_opordinal; 785 end; 786 stringdef : 787 begin 788 second_addstring; 789 end; 790 setdef : 791 begin 792 if is_smallset(tsetdef(left.resultdef)) then 793 second_opsmallset 794 else 795 internalerror(200109041); 796 end; 797 arraydef : 798 begin 799 { support dynarr=nil } 800 if is_dynamic_array(left.resultdef) then 801 second_opordinal 802 else 803 if (cs_support_vectors in current_settings.globalswitches) and 804 is_vector(left.resultdef) then 805 second_opvector 806 {$ifdef SUPPORT_MMX} 807 else 808 if is_mmx_able_array(left.resultdef) then 809 second_opmmx 810 {$endif SUPPORT_MMX} 811 else 812 internalerror(200306016); 813 end; 814 floatdef : 815 second_opfloat; 816 else 817 second_opordinal; 818 end; 819 end; 820 821 begin 822 caddnode:=tcgaddnode; 823 end. 824