PageRenderTime 26ms CodeModel.GetById 20ms app.highlight 3ms RepoModel.GetById 0ms app.codeStats 1ms

/compiler/ncgadd.pas

https://github.com/slibre/freepascal
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.