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