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