~ubuntu-branches/debian/lenny/fpc/lenny

« back to all changes in this revision

Viewing changes to fpcsrc/compiler/ncgadd.pas

  • Committer: Bazaar Package Importer
  • Author(s): Mazen Neifer, Torsten Werner, Mazen Neifer
  • Date: 2008-05-17 17:12:11 UTC
  • mfrom: (3.1.9 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080517171211-9qi33xhd9evfa0kg
Tags: 2.2.0-dfsg1-9
[ Torsten Werner ]
* Add Mazen Neifer to Uploaders field.

[ Mazen Neifer ]
* Moved FPC sources into a version dependent directory from /usr/share/fpcsrc
  to /usr/share/fpcsrc/${FPCVERSION}. This allow installing more than on FPC
  release.
* Fixed far call issue in compiler preventing building huge binearies.
  (closes: #477743)
* Updated building dependencies, recomennded and suggested packages.
* Moved fppkg to fp-utils as it is just a helper tool and is not required by
  compiler.

Show diffs side-by-side

added added

removed removed

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