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