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

« back to all changes in this revision

Viewing changes to compiler/powerpc/nppcadd.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
 
    $Id: nppcadd.pas,v 1.43 2004/03/18 16:19:03 peter Exp $
3
 
    Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
4
 
 
5
 
    Code generation for add nodes on the PowerPC
6
 
 
7
 
    This program is free software; you can redistribute it and/or modify
8
 
    it under the terms of the GNU General Public License as published by
9
 
    the Free Software Foundation; either version 2 of the License, or
10
 
    (at your option) any later version.
11
 
 
12
 
    This program is distributed in the hope that it will be useful,
13
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
    GNU General Public License for more details.
16
 
 
17
 
    You should have received a copy of the GNU General Public License
18
 
    along with this program; if not, write to the Free Software
19
 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
 
21
 
 ****************************************************************************
22
 
}
23
 
unit nppcadd;
24
 
 
25
 
{$i fpcdefs.inc}
26
 
 
27
 
interface
28
 
 
29
 
    uses
30
 
       node,nadd,ncgadd,cpubase;
31
 
 
32
 
    type
33
 
       tppcaddnode = class(tcgaddnode)
34
 
          function pass_1: tnode; override;
35
 
          procedure pass_2;override;
36
 
         private
37
 
          procedure pass_left_and_right;
38
 
          procedure load_left_right(cmpop, load_constants: boolean);
39
 
          function  getresflags : tresflags;
40
 
          procedure emit_compare(unsigned : boolean);
41
 
          procedure second_addfloat;override;
42
 
          procedure second_addboolean;override;
43
 
          procedure second_addsmallset;override;
44
 
{$ifdef SUPPORT_MMX}
45
 
          procedure second_addmmx;override;
46
 
{$endif SUPPORT_MMX}
47
 
          procedure second_add64bit;override;
48
 
       end;
49
 
 
50
 
  implementation
51
 
 
52
 
    uses
53
 
      globtype,systems,
54
 
      cutils,verbose,globals,
55
 
      symconst,symdef,paramgr,
56
 
      aasmbase,aasmtai,aasmcpu,defutil,htypechk,
57
 
      cgbase,cpuinfo,pass_1,pass_2,regvars,
58
 
      cpupara,cgcpu,
59
 
      ncon,nset,
60
 
      ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
61
 
 
62
 
 
63
 
{*****************************************************************************
64
 
                                  Pass 1
65
 
*****************************************************************************}
66
 
 
67
 
    function tppcaddnode.pass_1: tnode;
68
 
      begin
69
 
        if (nodetype in [equaln,unequaln]) and
70
 
           is_64bit(left.resulttype.def) then
71
 
          begin
72
 
            result := nil;
73
 
            firstpass(left);
74
 
            firstpass(right);
75
 
            expectloc := LOC_FLAGS;
76
 
            calcregisters(self,2,0,0);
77
 
            exit;
78
 
          end;
79
 
        result := inherited pass_1;
80
 
      end;
81
 
 
82
 
 
83
 
{*****************************************************************************
84
 
                                  Helpers
85
 
*****************************************************************************}
86
 
 
87
 
    procedure tppcaddnode.pass_left_and_right;
88
 
      var
89
 
        tmpreg     : tregister;
90
 
        pushedfpu  : boolean;
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
 
        secondpass(left);
100
 
 
101
 
        { are too few registers free? }
102
 
        if location.loc=LOC_FPUREGISTER then
103
 
          pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
104
 
        else
105
 
          pushedfpu:=false;
106
 
        secondpass(right);
107
 
        if pushedfpu then
108
 
          begin
109
 
            tmpreg := cg.getfpuregister(exprasmlist,left.location.size);
110
 
            cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
111
 
            location_reset(left.location,LOC_FPUREGISTER,left.location.size);
112
 
            left.location.register := tmpreg;
113
 
          end;
114
 
      end;
115
 
 
116
 
 
117
 
    procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
118
 
 
119
 
      procedure load_node(var n: tnode);
120
 
        begin
121
 
          case n.location.loc of
122
 
            LOC_REGISTER:
123
 
              if not cmpop then
124
 
                begin
125
 
                  location.register := n.location.register;
126
 
                  if is_64bit(n.resulttype.def) then
127
 
                    location.registerhigh := n.location.registerhigh;
128
 
                end;
129
 
            LOC_REFERENCE,LOC_CREFERENCE:
130
 
              begin
131
 
                location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
132
 
                if not cmpop then
133
 
                  begin
134
 
                    location.register := n.location.register;
135
 
                    if is_64bit(n.resulttype.def) then
136
 
                      location.registerhigh := n.location.registerhigh;
137
 
                  end;
138
 
              end;
139
 
            LOC_CONSTANT:
140
 
              begin
141
 
                if load_constants then
142
 
                  begin
143
 
                    location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
144
 
                    if not cmpop then
145
 
                      location.register := n.location.register;
146
 
                      if is_64bit(n.resulttype.def) then
147
 
                        location.registerhigh := n.location.registerhigh;
148
 
                  end;
149
 
              end;
150
 
          end;
151
 
        end;
152
 
 
153
 
      begin
154
 
        load_node(left);
155
 
        load_node(right);
156
 
        if not(cmpop) and
157
 
           (location.register = NR_NO) then
158
 
         begin
159
 
           location.register := cg.getintregister(exprasmlist,OS_INT);
160
 
           if is_64bit(resulttype.def) then
161
 
             location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
162
 
         end;
163
 
      end;
164
 
 
165
 
 
166
 
    function tppcaddnode.getresflags : tresflags;
167
 
      begin
168
 
        if (left.resulttype.def.deftype <> floatdef) then
169
 
          result.cr := RS_CR0
170
 
        else
171
 
          result.cr := RS_CR1;
172
 
        case nodetype of
173
 
          equaln : result.flag:=F_EQ;
174
 
          unequaln : result.flag:=F_NE;
175
 
        else
176
 
          if nf_swaped in flags then
177
 
            case nodetype of
178
 
              ltn : result.flag:=F_GT;
179
 
              lten : result.flag:=F_GE;
180
 
              gtn : result.flag:=F_LT;
181
 
              gten : result.flag:=F_LE;
182
 
            end
183
 
          else
184
 
            case nodetype of
185
 
              ltn : result.flag:=F_LT;
186
 
              lten : result.flag:=F_LE;
187
 
              gtn : result.flag:=F_GT;
188
 
              gten : result.flag:=F_GE;
189
 
            end;
190
 
        end
191
 
      end;
192
 
 
193
 
 
194
 
    procedure tppcaddnode.emit_compare(unsigned: boolean);
195
 
      var
196
 
        op : tasmop;
197
 
        tmpreg : tregister;
198
 
        useconst : boolean;
199
 
      begin
200
 
        // get the constant on the right if there is one
201
 
        if (left.location.loc = LOC_CONSTANT) then
202
 
          swapleftright;
203
 
        // can we use an immediate, or do we have to load the
204
 
        // constant in a register first?
205
 
        if (right.location.loc = LOC_CONSTANT) then
206
 
          begin
207
 
{$ifdef dummy}
208
 
            if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>$ffffffff) or unsigned) then
209
 
              internalerror(2002080301);
210
 
{$endif extdebug}
211
 
            if (nodetype in [equaln,unequaln]) then
212
 
              if (unsigned and
213
 
                  (right.location.value > high(word))) or
214
 
                 (not unsigned and
215
 
                  (longint(right.location.value) < low(smallint)) or
216
 
                   (longint(right.location.value) > high(smallint))) then
217
 
                { we can then maybe use a constant in the 'othersigned' case
218
 
                 (the sign doesn't matter for // equal/unequal)}
219
 
                unsigned := not unsigned;
220
 
 
221
 
            if (unsigned and
222
 
                ((right.location.value) <= high(word))) or
223
 
               (not(unsigned) and
224
 
                (longint(right.location.value) >= low(smallint)) and
225
 
                (longint(right.location.value) <= high(smallint))) then
226
 
               useconst := true
227
 
            else
228
 
              begin
229
 
                useconst := false;
230
 
                tmpreg := cg.getintregister(exprasmlist,OS_INT);
231
 
                cg.a_load_const_reg(exprasmlist,OS_INT,
232
 
                  aword(right.location.value),tmpreg);
233
 
               end
234
 
          end
235
 
        else
236
 
          useconst := false;
237
 
        location.loc := LOC_FLAGS;
238
 
        location.resflags := getresflags;
239
 
        if not unsigned then
240
 
          if useconst then
241
 
            op := A_CMPWI
242
 
          else
243
 
            op := A_CMPW
244
 
        else
245
 
          if useconst then
246
 
            op := A_CMPLWI
247
 
          else
248
 
            op := A_CMPLW;
249
 
 
250
 
        if (right.location.loc = LOC_CONSTANT) then
251
 
          if useconst then
252
 
            exprasmlist.concat(taicpu.op_reg_const(op,
253
 
              left.location.register,longint(right.location.value)))
254
 
          else
255
 
            begin
256
 
              exprasmlist.concat(taicpu.op_reg_reg(op,
257
 
                left.location.register,tmpreg));
258
 
              cg.ungetregister(exprasmlist,tmpreg);
259
 
            end
260
 
        else
261
 
          exprasmlist.concat(taicpu.op_reg_reg(op,
262
 
            left.location.register,right.location.register));
263
 
      end;
264
 
 
265
 
 
266
 
{*****************************************************************************
267
 
                                AddBoolean
268
 
*****************************************************************************}
269
 
 
270
 
    procedure tppcaddnode.second_addboolean;
271
 
      var
272
 
        cgop      : TOpCg;
273
 
        cgsize  : TCgSize;
274
 
        cmpop,
275
 
        isjump  : boolean;
276
 
        otl,ofl : tasmlabel;
277
 
      begin
278
 
        { calculate the operator which is more difficult }
279
 
        firstcomplex(self);
280
 
 
281
 
        cmpop:=false;
282
 
        if (torddef(left.resulttype.def).typ=bool8bit) or
283
 
           (torddef(right.resulttype.def).typ=bool8bit) then
284
 
         cgsize:=OS_8
285
 
        else
286
 
          if (torddef(left.resulttype.def).typ=bool16bit) or
287
 
             (torddef(right.resulttype.def).typ=bool16bit) then
288
 
           cgsize:=OS_16
289
 
        else
290
 
           cgsize:=OS_32;
291
 
 
292
 
        if (cs_full_boolean_eval in aktlocalswitches) or
293
 
           (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
294
 
          begin
295
 
            if left.nodetype in [ordconstn,realconstn] then
296
 
             swapleftright;
297
 
 
298
 
            isjump:=(left.expectloc=LOC_JUMP);
299
 
            if isjump then
300
 
              begin
301
 
                 otl:=truelabel;
302
 
                 objectlibrary.getlabel(truelabel);
303
 
                 ofl:=falselabel;
304
 
                 objectlibrary.getlabel(falselabel);
305
 
              end;
306
 
            secondpass(left);
307
 
            if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
308
 
             location_force_reg(exprasmlist,left.location,cgsize,false);
309
 
            if isjump then
310
 
             begin
311
 
               truelabel:=otl;
312
 
               falselabel:=ofl;
313
 
             end
314
 
            else if left.location.loc=LOC_JUMP then
315
 
              internalerror(2003122901);
316
 
 
317
 
            isjump:=(right.expectloc=LOC_JUMP);
318
 
            if isjump then
319
 
              begin
320
 
                 otl:=truelabel;
321
 
                 objectlibrary.getlabel(truelabel);
322
 
                 ofl:=falselabel;
323
 
                 objectlibrary.getlabel(falselabel);
324
 
              end;
325
 
            secondpass(right);
326
 
            if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
327
 
             location_force_reg(exprasmlist,right.location,cgsize,false);
328
 
            if isjump then
329
 
             begin
330
 
               truelabel:=otl;
331
 
               falselabel:=ofl;
332
 
             end
333
 
            else if right.location.loc=LOC_JUMP then
334
 
              internalerror(200312292);
335
 
 
336
 
            cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
337
 
 
338
 
            { set result location }
339
 
            if not cmpop then
340
 
              location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
341
 
             else
342
 
              location_reset(location,LOC_FLAGS,OS_NO);
343
 
 
344
 
            load_left_right(cmpop,false);
345
 
 
346
 
            if (left.location.loc = LOC_CONSTANT) then
347
 
              swapleftright;
348
 
 
349
 
            { compare the }
350
 
            case nodetype of
351
 
              ltn,lten,gtn,gten,
352
 
              equaln,unequaln :
353
 
                begin
354
 
                  if (right.location.loc <> LOC_CONSTANT) then
355
 
                    exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
356
 
                      left.location.register,right.location.register))
357
 
                  else
358
 
                    exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
359
 
                      left.location.register,longint(right.location.value)));
360
 
                  location.resflags := getresflags;
361
 
                end;
362
 
              else
363
 
                begin
364
 
                  case nodetype of
365
 
                    xorn :
366
 
                      cgop:=OP_XOR;
367
 
                    orn :
368
 
                      cgop:=OP_OR;
369
 
                    andn :
370
 
                      cgop:=OP_AND;
371
 
                    else
372
 
                      internalerror(200203247);
373
 
                  end;
374
 
 
375
 
                  if right.location.loc <> LOC_CONSTANT then
376
 
                    cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
377
 
                      left.location.register,right.location.register,
378
 
                      location.register)
379
 
                  else
380
 
                    cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
381
 
                      aword(right.location.value),left.location.register,
382
 
                      location.register);
383
 
                end;
384
 
            end;
385
 
         end
386
 
        else
387
 
         begin
388
 
           // just to make sure we free the right registers
389
 
           cmpop := true;
390
 
           case nodetype of
391
 
             andn,
392
 
             orn :
393
 
               begin
394
 
                 location_reset(location,LOC_JUMP,OS_NO);
395
 
                 case nodetype of
396
 
                   andn :
397
 
                     begin
398
 
                        otl:=truelabel;
399
 
                        objectlibrary.getlabel(truelabel);
400
 
                        secondpass(left);
401
 
                        maketojumpbool(exprasmlist,left,lr_load_regvars);
402
 
                        cg.a_label(exprasmlist,truelabel);
403
 
                        truelabel:=otl;
404
 
                     end;
405
 
                   orn :
406
 
                     begin
407
 
                        ofl:=falselabel;
408
 
                        objectlibrary.getlabel(falselabel);
409
 
                        secondpass(left);
410
 
                        maketojumpbool(exprasmlist,left,lr_load_regvars);
411
 
                        cg.a_label(exprasmlist,falselabel);
412
 
                        falselabel:=ofl;
413
 
                     end;
414
 
                   else
415
 
                     internalerror(200403181);
416
 
                 end;
417
 
                 secondpass(right);
418
 
                 maketojumpbool(exprasmlist,right,lr_load_regvars);
419
 
               end;
420
 
           end;
421
 
         end;
422
 
 
423
 
        release_reg_left_right;
424
 
      end;
425
 
 
426
 
 
427
 
{*****************************************************************************
428
 
                                AddFloat
429
 
*****************************************************************************}
430
 
 
431
 
    procedure tppcaddnode.second_addfloat;
432
 
      var
433
 
        op    : TAsmOp;
434
 
        cmpop : boolean;
435
 
      begin
436
 
        pass_left_and_right;
437
 
 
438
 
        cmpop:=false;
439
 
        case nodetype of
440
 
          addn :
441
 
            op:=A_FADD;
442
 
          muln :
443
 
            op:=A_FMUL;
444
 
          subn :
445
 
            op:=A_FSUB;
446
 
          slashn :
447
 
            op:=A_FDIV;
448
 
          ltn,lten,gtn,gten,
449
 
          equaln,unequaln :
450
 
            begin
451
 
              op:=A_FCMPO;
452
 
              cmpop:=true;
453
 
            end;
454
 
          else
455
 
            internalerror(200403182);
456
 
        end;
457
 
 
458
 
        // get the operands in the correct order, there are no special cases
459
 
        // here, everything is register-based
460
 
        if nf_swaped in flags then
461
 
          swapleftright;
462
 
 
463
 
        // put both operands in a register
464
 
        location_force_fpureg(exprasmlist,right.location,true);
465
 
        location_force_fpureg(exprasmlist,left.location,true);
466
 
 
467
 
        // initialize de result
468
 
        if not cmpop then
469
 
          begin
470
 
            location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
471
 
            if left.location.loc = LOC_FPUREGISTER then
472
 
              location.register := left.location.register
473
 
            else if right.location.loc = LOC_FPUREGISTER then
474
 
              location.register := right.location.register
475
 
            else
476
 
              location.register := cg.getfpuregister(exprasmlist,location.size);
477
 
          end
478
 
        else
479
 
         begin
480
 
           location_reset(location,LOC_FLAGS,OS_NO);
481
 
           location.resflags := getresflags;
482
 
         end;
483
 
 
484
 
        // emit the actual operation
485
 
        if not cmpop then
486
 
          begin
487
 
            exprasmlist.concat(taicpu.op_reg_reg_reg(op,
488
 
              location.register,left.location.register,
489
 
              right.location.register))
490
 
          end
491
 
        else
492
 
          begin
493
 
            exprasmlist.concat(taicpu.op_reg_reg_reg(op,
494
 
              newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
495
 
          end;
496
 
 
497
 
        release_reg_left_right;
498
 
      end;
499
 
 
500
 
{*****************************************************************************
501
 
                                AddSmallSet
502
 
*****************************************************************************}
503
 
 
504
 
    procedure tppcaddnode.second_addsmallset;
505
 
      var
506
 
        cgop   : TOpCg;
507
 
        tmpreg : tregister;
508
 
        opdone,
509
 
        cmpop  : boolean;
510
 
      begin
511
 
        pass_left_and_right;
512
 
 
513
 
        { when a setdef is passed, it has to be a smallset }
514
 
        if ((left.resulttype.def.deftype=setdef) and
515
 
            (tsetdef(left.resulttype.def).settype<>smallset)) or
516
 
           ((right.resulttype.def.deftype=setdef) and
517
 
            (tsetdef(right.resulttype.def).settype<>smallset)) then
518
 
         internalerror(200203301);
519
 
 
520
 
        opdone := false;
521
 
        cmpop:=nodetype in [equaln,unequaln,lten,gten];
522
 
 
523
 
        { set result location }
524
 
        if not cmpop then
525
 
          location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
526
 
         else
527
 
          location_reset(location,LOC_FLAGS,OS_NO);
528
 
 
529
 
        load_left_right(cmpop,false);
530
 
 
531
 
        if not(cmpop) and
532
 
           (location.register = NR_NO) then
533
 
          location.register := cg.getintregister(exprasmlist,OS_INT);
534
 
 
535
 
        case nodetype of
536
 
          addn :
537
 
            begin
538
 
              if (nf_swaped in flags) and (left.nodetype=setelementn) then
539
 
                swapleftright;
540
 
              { are we adding set elements ? }
541
 
              if right.nodetype=setelementn then
542
 
                begin
543
 
                  { no range support for smallsets! }
544
 
                  if assigned(tsetelementnode(right).right) then
545
 
                   internalerror(43244);
546
 
                  if (right.location.loc = LOC_CONSTANT) then
547
 
                    cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
548
 
                      aword(1 shl aword(right.location.value)),
549
 
                      left.location.register,location.register)
550
 
                  else
551
 
                    begin
552
 
                      tmpreg := cg.getintregister(exprasmlist,OS_INT);
553
 
                      cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
554
 
                      cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
555
 
                        right.location.register,tmpreg);
556
 
                      if left.location.loc <> LOC_CONSTANT then
557
 
                        cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
558
 
                          left.location.register,location.register)
559
 
                      else
560
 
                        cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
561
 
                          aword(left.location.value),tmpreg,location.register);
562
 
                      cg.ungetregister(exprasmlist,tmpreg);
563
 
                    end;
564
 
                  opdone := true;
565
 
                end
566
 
              else
567
 
                cgop := OP_OR;
568
 
            end;
569
 
          symdifn :
570
 
            cgop:=OP_XOR;
571
 
          muln :
572
 
            cgop:=OP_AND;
573
 
          subn :
574
 
            begin
575
 
              cgop:=OP_AND;
576
 
              if (not(nf_swaped in flags)) then
577
 
                if (right.location.loc=LOC_CONSTANT) then
578
 
                  right.location.value := not(right.location.value)
579
 
                else
580
 
                  opdone := true
581
 
              else if (left.location.loc=LOC_CONSTANT) then
582
 
                left.location.value := not(left.location.value)
583
 
              else
584
 
                 begin
585
 
                   swapleftright;
586
 
                   opdone := true;
587
 
                 end;
588
 
              if opdone then
589
 
                begin
590
 
                  if left.location.loc = LOC_CONSTANT then
591
 
                    begin
592
 
                      tmpreg := cg.getintregister(exprasmlist,OS_INT);
593
 
                      cg.a_load_const_reg(exprasmlist,OS_INT,
594
 
                        aword(left.location.value),tmpreg);
595
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
596
 
                        location.register,tmpreg,right.location.register));
597
 
                      cg.ungetregister(exprasmlist,tmpreg);
598
 
                    end
599
 
                  else
600
 
                    exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
601
 
                      location.register,left.location.register,
602
 
                      right.location.register));
603
 
                end;
604
 
            end;
605
 
          equaln,
606
 
          unequaln :
607
 
            begin
608
 
              emit_compare(true);
609
 
              opdone := true;
610
 
            end;
611
 
          lten,gten:
612
 
            begin
613
 
              If (not(nf_swaped in flags) and
614
 
                  (nodetype = lten)) or
615
 
                 ((nf_swaped in flags) and
616
 
                  (nodetype = gten)) then
617
 
                swapleftright;
618
 
              // now we have to check whether left >= right
619
 
              tmpreg := cg.getintregister(exprasmlist,OS_INT);
620
 
              if left.location.loc = LOC_CONSTANT then
621
 
                begin
622
 
                  cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
623
 
                    not(left.location.value),right.location.register,tmpreg);
624
 
                  exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
625
 
                  // the two instructions above should be folded together by
626
 
                  // the peepholeoptimizer
627
 
                end
628
 
              else
629
 
                begin
630
 
                  if right.location.loc = LOC_CONSTANT then
631
 
                    begin
632
 
                      cg.a_load_const_reg(exprasmlist,OS_INT,
633
 
                        aword(right.location.value),tmpreg);
634
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
635
 
                        tmpreg,left.location.register));
636
 
                    end
637
 
                  else
638
 
                    exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
639
 
                      right.location.register,left.location.register));
640
 
                end;
641
 
              cg.ungetregister(exprasmlist,tmpreg);
642
 
              location.resflags.cr := RS_CR0;
643
 
              location.resflags.flag := F_EQ;
644
 
              opdone := true;
645
 
            end;
646
 
          else
647
 
            internalerror(2002072701);
648
 
        end;
649
 
 
650
 
        if not opdone then
651
 
          begin
652
 
            // these are all commutative operations
653
 
            if (left.location.loc = LOC_CONSTANT) then
654
 
              swapleftright;
655
 
            if (right.location.loc = LOC_CONSTANT) then
656
 
              cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
657
 
                aword(right.location.value),left.location.register,
658
 
                location.register)
659
 
            else
660
 
              cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
661
 
                right.location.register,left.location.register,
662
 
                location.register);
663
 
          end;
664
 
 
665
 
        release_reg_left_right;
666
 
      end;
667
 
 
668
 
{*****************************************************************************
669
 
                                Add64bit
670
 
*****************************************************************************}
671
 
 
672
 
    procedure tppcaddnode.second_add64bit;
673
 
      var
674
 
        op         : TOpCG;
675
 
        op1,op2    : TAsmOp;
676
 
        hl4        : tasmlabel;
677
 
        cmpop,
678
 
        unsigned   : boolean;
679
 
        r          : Tregister;
680
 
 
681
 
 
682
 
      procedure emit_cmp64_hi;
683
 
 
684
 
        var
685
 
          oldleft, oldright: tlocation;
686
 
        begin
687
 
          // put the high part of the location in the low part
688
 
          location_copy(oldleft,left.location);
689
 
          location_copy(oldright,right.location);
690
 
          if left.location.loc = LOC_CONSTANT then
691
 
            left.location.valueqword := left.location.valueqword shr 32
692
 
          else
693
 
            left.location.registerlow := left.location.registerhigh;
694
 
          if right.location.loc = LOC_CONSTANT then
695
 
            right.location.valueqword := right.location.valueqword shr 32
696
 
          else
697
 
            right.location.registerlow := right.location.registerhigh;
698
 
 
699
 
          // and call the normal emit_compare
700
 
          emit_compare(unsigned);
701
 
          location_copy(left.location,oldleft);
702
 
          location_copy(right.location,oldright);
703
 
        end;
704
 
 
705
 
 
706
 
      procedure emit_cmp64_lo;
707
 
 
708
 
        begin
709
 
          emit_compare(true);
710
 
        end;
711
 
 
712
 
 
713
 
      procedure firstjmp64bitcmp;
714
 
 
715
 
        var
716
 
          oldnodetype: tnodetype;
717
 
        begin
718
 
{$ifdef OLDREGVARS}
719
 
           load_all_regvars(exprasmlist);
720
 
{$endif OLDREGVARS}
721
 
           { the jump the sequence is a little bit hairy }
722
 
           case nodetype of
723
 
              ltn,gtn:
724
 
                begin
725
 
                   cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
726
 
                   { cheat a little bit for the negative test }
727
 
                   toggleflag(nf_swaped);
728
 
                   cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
729
 
                   toggleflag(nf_swaped);
730
 
                end;
731
 
              lten,gten:
732
 
                begin
733
 
                   oldnodetype:=nodetype;
734
 
                   if nodetype=lten then
735
 
                     nodetype:=ltn
736
 
                   else
737
 
                     nodetype:=gtn;
738
 
                   cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
739
 
                   { cheat for the negative test }
740
 
                   if nodetype=ltn then
741
 
                     nodetype:=gtn
742
 
                   else
743
 
                     nodetype:=ltn;
744
 
                   cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
745
 
                   nodetype:=oldnodetype;
746
 
                end;
747
 
              equaln:
748
 
                begin
749
 
                  nodetype := unequaln;
750
 
                  cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
751
 
                  nodetype := equaln;
752
 
                end;
753
 
              unequaln:
754
 
                begin
755
 
                  cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
756
 
                end;
757
 
           end;
758
 
        end;
759
 
 
760
 
 
761
 
      procedure secondjmp64bitcmp;
762
 
 
763
 
        begin
764
 
           { the jump the sequence is a little bit hairy }
765
 
           case nodetype of
766
 
              ltn,gtn,lten,gten:
767
 
                begin
768
 
                   { the comparison of the low dword always has }
769
 
                   { to be always unsigned!                     }
770
 
                   cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
771
 
                   cg.a_jmp_always(exprasmlist,falselabel);
772
 
                end;
773
 
              equaln:
774
 
                begin
775
 
                   nodetype := unequaln;
776
 
                   cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
777
 
                   cg.a_jmp_always(exprasmlist,truelabel);
778
 
                   nodetype := equaln;
779
 
                end;
780
 
              unequaln:
781
 
                begin
782
 
                   cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
783
 
                   cg.a_jmp_always(exprasmlist,falselabel);
784
 
                end;
785
 
           end;
786
 
        end;
787
 
 
788
 
 
789
 
    var
790
 
      tempreg64: tregister64;
791
 
 
792
 
      begin
793
 
        firstcomplex(self);
794
 
 
795
 
        pass_left_and_right;
796
 
 
797
 
        cmpop:=false;
798
 
        unsigned:=((left.resulttype.def.deftype=orddef) and
799
 
                   (torddef(left.resulttype.def).typ=u64bit)) or
800
 
                  ((right.resulttype.def.deftype=orddef) and
801
 
                   (torddef(right.resulttype.def).typ=u64bit));
802
 
        case nodetype of
803
 
          addn :
804
 
            begin
805
 
              op:=OP_ADD;
806
 
            end;
807
 
          subn :
808
 
            begin
809
 
              op:=OP_SUB;
810
 
            end;
811
 
          ltn,lten,
812
 
          gtn,gten,
813
 
          equaln,unequaln:
814
 
            begin
815
 
              op:=OP_NONE;
816
 
              cmpop:=true;
817
 
            end;
818
 
          xorn:
819
 
            op:=OP_XOR;
820
 
          orn:
821
 
            op:=OP_OR;
822
 
          andn:
823
 
            op:=OP_AND;
824
 
          muln:
825
 
            begin
826
 
              { should be handled in pass_1 (JM) }
827
 
              internalerror(200109051);
828
 
            end;
829
 
          else
830
 
            internalerror(2002072705);
831
 
        end;
832
 
 
833
 
        if not cmpop then
834
 
          location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
835
 
 
836
 
        load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
837
 
            (nodetype in [addn,subn]));
838
 
 
839
 
        if not(cs_check_overflow in aktlocalswitches) or
840
 
           not(nodetype in [addn,subn]) then
841
 
          begin
842
 
            case nodetype of
843
 
              ltn,lten,
844
 
              gtn,gten:
845
 
                begin
846
 
                  emit_cmp64_hi;
847
 
                  firstjmp64bitcmp;
848
 
                  emit_cmp64_lo;
849
 
                  secondjmp64bitcmp;
850
 
                end;
851
 
              equaln,unequaln:
852
 
                begin
853
 
                  // instead of doing a complicated compare, do
854
 
                  // (left.hi xor right.hi) or (left.lo xor right.lo)
855
 
                  // (somewhate optimized so that no superfluous 'mr's are
856
 
                  //  generated)
857
 
                  if (left.location.loc = LOC_CONSTANT) then
858
 
                    swapleftright;
859
 
                  if (right.location.loc = LOC_CONSTANT) then
860
 
                    begin
861
 
                      if left.location.loc = LOC_REGISTER then
862
 
                        begin
863
 
                          tempreg64.reglo := left.location.registerlow;
864
 
                          tempreg64.reghi := left.location.registerhigh;
865
 
                        end
866
 
                      else
867
 
                        begin
868
 
                          if (aword(right.location.valueqword) <> 0) then
869
 
                            tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
870
 
                          else
871
 
                            tempreg64.reglo := left.location.registerlow;
872
 
                          if ((right.location.valueqword shr 32) <> 0) then
873
 
                            tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
874
 
                          else
875
 
                            tempreg64.reghi := left.location.registerhigh;
876
 
                        end;
877
 
 
878
 
                      if (aword(right.location.valueqword) <> 0) then
879
 
                        { negative values can be handled using SUB, }
880
 
                        { positive values < 65535 using XOR.        }
881
 
                        if (longint(right.location.valueqword) >= -32767) and
882
 
                           (longint(right.location.valueqword) < 0) then
883
 
                          cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
884
 
                            aword(right.location.valueqword),
885
 
                            left.location.registerlow,tempreg64.reglo)
886
 
                        else
887
 
                          cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
888
 
                            aword(right.location.valueqword),
889
 
                            left.location.registerlow,tempreg64.reglo);
890
 
 
891
 
                      if ((right.location.valueqword shr 32) <> 0) then
892
 
                        if (longint(right.location.valueqword shr 32) >= -32767) and
893
 
                           (longint(right.location.valueqword shr 32) < 0) then
894
 
                          cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
895
 
                            aword(right.location.valueqword shr 32),
896
 
                            left.location.registerhigh,tempreg64.reghi)
897
 
                        else
898
 
                          cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
899
 
                            aword(right.location.valueqword shr 32),
900
 
                            left.location.registerhigh,tempreg64.reghi);
901
 
                    end
902
 
                  else
903
 
                    begin
904
 
                       tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
905
 
                       tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
906
 
                       cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
907
 
                         left.location.register64,right.location.register64,
908
 
                         tempreg64);
909
 
                    end;
910
 
 
911
 
                  cg.a_reg_alloc(exprasmlist,NR_R0);
912
 
                  exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
913
 
                    tempreg64.reglo,tempreg64.reghi));
914
 
                  cg.a_reg_dealloc(exprasmlist,NR_R0);
915
 
                  if (tempreg64.reglo <> left.location.registerlow) then
916
 
                    cg.ungetregister(exprasmlist,tempreg64.reglo);
917
 
                  if (tempreg64.reghi <> left.location.registerhigh) then
918
 
                    cg.ungetregister(exprasmlist,tempreg64.reghi);
919
 
 
920
 
                  location_reset(location,LOC_FLAGS,OS_NO);
921
 
                  location.resflags := getresflags;
922
 
                end;
923
 
              xorn,orn,andn,addn:
924
 
                begin
925
 
                  if (location.registerlow = NR_NO) then
926
 
                    begin
927
 
                      location.registerlow := cg.getintregister(exprasmlist,OS_INT);
928
 
                      location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
929
 
                    end;
930
 
 
931
 
                  if (left.location.loc = LOC_CONSTANT) then
932
 
                    swapleftright;
933
 
                  if (right.location.loc = LOC_CONSTANT) then
934
 
                    cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
935
 
                      left.location.register64,location.register64)
936
 
                  else
937
 
                    cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
938
 
                      left.location.register64,location.register64);
939
 
                end;
940
 
              subn:
941
 
                begin
942
 
                  if (nf_swaped in flags) then
943
 
                    swapleftright;
944
 
 
945
 
                  if left.location.loc <> LOC_CONSTANT then
946
 
                    begin
947
 
                      if (location.registerlow = NR_NO) then
948
 
                        begin
949
 
                         location.registerlow := cg.getintregister(exprasmlist,OS_INT);
950
 
                         location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
951
 
                      end;
952
 
                      if right.location.loc <> LOC_CONSTANT then
953
 
                        // reg64 - reg64
954
 
                        cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
955
 
                          right.location.register64,left.location.register64,
956
 
                          location.register64)
957
 
                      else
958
 
                        // reg64 - const64
959
 
                        cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
960
 
                          right.location.valueqword,left.location.register64,
961
 
                          location.register64)
962
 
                    end
963
 
                  else if ((left.location.valueqword shr 32) = 0) then
964
 
                    begin
965
 
                      if (location.registerlow = NR_NO) then
966
 
                        begin
967
 
                         location.registerlow := cg.getintregister(exprasmlist,OS_INT);
968
 
                         location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
969
 
                      end;
970
 
                      if (int64(left.location.valueqword) >= low(smallint)) and
971
 
                         (int64(left.location.valueqword) <= high(smallint)) then
972
 
                        begin
973
 
                          // consts16 - reg64
974
 
                          exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
975
 
                            location.registerlow,right.location.registerlow,
976
 
                            aword(left.location.value)));
977
 
                        end
978
 
                      else
979
 
                        begin
980
 
                          // const32 - reg64
981
 
                          location_force_reg(exprasmlist,left.location,
982
 
                            OS_32,true);
983
 
                          exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
984
 
                            location.registerlow,left.location.registerlow,
985
 
                            right.location.registerlow));
986
 
                        end;
987
 
                      exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
988
 
                        location.registerhigh,right.location.registerhigh));
989
 
                    end
990
 
                  else if (aword(left.location.valueqword) = 0) then
991
 
                    begin
992
 
                      // (const32 shl 32) - reg64
993
 
                      if (location.registerlow = NR_NO) then
994
 
                        begin
995
 
                         location.registerlow := cg.getintregister(exprasmlist,OS_INT);
996
 
                         location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
997
 
                      end;
998
 
                      exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
999
 
                        location.registerlow,right.location.registerlow,0));
1000
 
                      left.location.valueqword := left.location.valueqword shr 32;
1001
 
                      location_force_reg(exprasmlist,left.location,OS_32,true);
1002
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
1003
 
                        location.registerhigh,right.location.registerhigh,
1004
 
                        left.location.register));
1005
 
                    end
1006
 
                  else
1007
 
                    begin
1008
 
                      // const64 - reg64
1009
 
                      location_force_reg(exprasmlist,left.location,
1010
 
                        def_cgsize(left.resulttype.def),false);
1011
 
                      if (left.location.loc = LOC_REGISTER) then
1012
 
                        location.register64 := left.location.register64
1013
 
                      else if (location.registerlow = NR_NO) then
1014
 
                        begin
1015
 
                         location.registerlow := cg.getintregister(exprasmlist,OS_INT);
1016
 
                         location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
1017
 
                        end;
1018
 
                      cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
1019
 
                        right.location.register64,left.location.register64,
1020
 
                        location.register64);
1021
 
                     end;
1022
 
                end;
1023
 
              else
1024
 
                internalerror(2002072803);
1025
 
            end;
1026
 
          end
1027
 
        else
1028
 
          begin
1029
 
            if is_signed(resulttype.def) then
1030
 
              begin
1031
 
                case nodetype of
1032
 
                  addn:
1033
 
                    begin
1034
 
                      op1 := A_ADDC;
1035
 
                      op2 := A_ADDEO;
1036
 
                    end;
1037
 
                  subn:
1038
 
                    begin
1039
 
                      op1 := A_SUBC;
1040
 
                      op2 := A_SUBFEO;
1041
 
                    end;
1042
 
                  else
1043
 
                    internalerror(2002072806);
1044
 
                end
1045
 
              end
1046
 
            else
1047
 
              begin
1048
 
                case nodetype of
1049
 
                  addn:
1050
 
                    begin
1051
 
                      op1 := A_ADDC;
1052
 
                      op2 := A_ADDE;
1053
 
                    end;
1054
 
                  subn:
1055
 
                    begin
1056
 
                      op1 := A_SUBC;
1057
 
                      op2 := A_SUBFE;
1058
 
                    end;
1059
 
                end;
1060
 
              end;
1061
 
            exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
1062
 
              left.location.registerlow,right.location.registerlow));
1063
 
            exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
1064
 
              right.location.registerhigh,left.location.registerhigh));
1065
 
            if not(is_signed(resulttype.def)) then
1066
 
              if nodetype = addn then
1067
 
                exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.registerhigh,left.location.registerhigh))
1068
 
              else
1069
 
                exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.registerhigh,location.registerhigh));
1070
 
            cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1071
 
          end;
1072
 
 
1073
 
        { set result location }
1074
 
        { (emit_compare sets it to LOC_FLAGS for compares, so set the }
1075
 
        {  real location only now) (JM)                               }
1076
 
        if cmpop and
1077
 
           not(nodetype in [equaln,unequaln]) then
1078
 
          location_reset(location,LOC_JUMP,OS_NO);
1079
 
 
1080
 
        release_reg_left_right;
1081
 
 
1082
 
      end;
1083
 
 
1084
 
 
1085
 
{*****************************************************************************
1086
 
                                AddMMX
1087
 
*****************************************************************************}
1088
 
 
1089
 
{$ifdef SUPPORT_MMX}
1090
 
    procedure ti386addnode.second_addmmx;
1091
 
      var
1092
 
        op         : TAsmOp;
1093
 
        cmpop      : boolean;
1094
 
        mmxbase    : tmmxtype;
1095
 
        hregister  : tregister;
1096
 
      begin
1097
 
        pass_left_and_right;
1098
 
 
1099
 
        cmpop:=false;
1100
 
        mmxbase:=mmx_type(left.resulttype.def);
1101
 
        case nodetype of
1102
 
          addn :
1103
 
            begin
1104
 
              if (cs_mmx_saturation in aktlocalswitches) then
1105
 
                begin
1106
 
                   case mmxbase of
1107
 
                      mmxs8bit:
1108
 
                        op:=A_PADDSB;
1109
 
                      mmxu8bit:
1110
 
                        op:=A_PADDUSB;
1111
 
                      mmxs16bit,mmxfixed16:
1112
 
                        op:=A_PADDSB;
1113
 
                      mmxu16bit:
1114
 
                        op:=A_PADDUSW;
1115
 
                   end;
1116
 
                end
1117
 
              else
1118
 
                begin
1119
 
                   case mmxbase of
1120
 
                      mmxs8bit,mmxu8bit:
1121
 
                        op:=A_PADDB;
1122
 
                      mmxs16bit,mmxu16bit,mmxfixed16:
1123
 
                        op:=A_PADDW;
1124
 
                      mmxs32bit,mmxu32bit:
1125
 
                        op:=A_PADDD;
1126
 
                   end;
1127
 
                end;
1128
 
            end;
1129
 
          muln :
1130
 
            begin
1131
 
               case mmxbase of
1132
 
                  mmxs16bit,mmxu16bit:
1133
 
                    op:=A_PMULLW;
1134
 
                  mmxfixed16:
1135
 
                    op:=A_PMULHW;
1136
 
               end;
1137
 
            end;
1138
 
          subn :
1139
 
            begin
1140
 
              if (cs_mmx_saturation in aktlocalswitches) then
1141
 
                begin
1142
 
                   case mmxbase of
1143
 
                      mmxs8bit:
1144
 
                        op:=A_PSUBSB;
1145
 
                      mmxu8bit:
1146
 
                        op:=A_PSUBUSB;
1147
 
                      mmxs16bit,mmxfixed16:
1148
 
                        op:=A_PSUBSB;
1149
 
                      mmxu16bit:
1150
 
                        op:=A_PSUBUSW;
1151
 
                   end;
1152
 
                end
1153
 
              else
1154
 
                begin
1155
 
                   case mmxbase of
1156
 
                      mmxs8bit,mmxu8bit:
1157
 
                        op:=A_PSUBB;
1158
 
                      mmxs16bit,mmxu16bit,mmxfixed16:
1159
 
                        op:=A_PSUBW;
1160
 
                      mmxs32bit,mmxu32bit:
1161
 
                        op:=A_PSUBD;
1162
 
                   end;
1163
 
                end;
1164
 
            end;
1165
 
          xorn:
1166
 
            op:=A_PXOR;
1167
 
          orn:
1168
 
            op:=A_POR;
1169
 
          andn:
1170
 
            op:=A_PAND;
1171
 
          else
1172
 
            internalerror(200403183);
1173
 
        end;
1174
 
 
1175
 
        { left and right no register?  }
1176
 
        { then one must be demanded    }
1177
 
        if (left.location.loc<>LOC_MMXREGISTER) then
1178
 
         begin
1179
 
           if (right.location.loc=LOC_MMXREGISTER) then
1180
 
            begin
1181
 
              location_swap(left.location,right.location);
1182
 
              toggleflag(nf_swaped);
1183
 
            end
1184
 
           else
1185
 
            begin
1186
 
              { register variable ? }
1187
 
              if (left.location.loc=LOC_CMMXREGISTER) then
1188
 
               begin
1189
 
                 hregister:=rg.getregistermm(exprasmlist);
1190
 
                 emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
1191
 
               end
1192
 
              else
1193
 
               begin
1194
 
                 if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1195
 
                  internalerror(200203245);
1196
 
 
1197
 
                 location_release(exprasmlist,left.location);
1198
 
 
1199
 
                 hregister:=rg.getregistermm(exprasmlist);
1200
 
                 emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
1201
 
               end;
1202
 
 
1203
 
              location_reset(left.location,LOC_MMXREGISTER,OS_NO);
1204
 
              left.location.register:=hregister;
1205
 
            end;
1206
 
         end;
1207
 
 
1208
 
        { at this point, left.location.loc should be LOC_MMXREGISTER }
1209
 
        if right.location.loc<>LOC_MMXREGISTER then
1210
 
         begin
1211
 
           if (nodetype=subn) and (nf_swaped in flags) then
1212
 
            begin
1213
 
              if right.location.loc=LOC_CMMXREGISTER then
1214
 
               begin
1215
 
                 emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
1216
 
                 emit_reg_reg(op,S_NO,left.location.register,R_MM7);
1217
 
                 emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
1218
 
               end
1219
 
              else
1220
 
               begin
1221
 
                 if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1222
 
                  internalerror(200203247);
1223
 
                 emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
1224
 
                 emit_reg_reg(op,S_NO,left.location.register,R_MM7);
1225
 
                 emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
1226
 
                 location_release(exprasmlist,right.location);
1227
 
               end;
1228
 
            end
1229
 
           else
1230
 
            begin
1231
 
              if (right.location.loc=LOC_CMMXREGISTER) then
1232
 
               begin
1233
 
                 emit_reg_reg(op,S_NO,right.location.register,left.location.register);
1234
 
               end
1235
 
              else
1236
 
               begin
1237
 
                 if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
1238
 
                  internalerror(200203246);
1239
 
                 emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
1240
 
                 location_release(exprasmlist,right.location);
1241
 
               end;
1242
 
            end;
1243
 
          end
1244
 
        else
1245
 
          begin
1246
 
            { right.location=LOC_MMXREGISTER }
1247
 
            if (nodetype=subn) and (nf_swaped in flags) then
1248
 
             begin
1249
 
               emit_reg_reg(op,S_NO,left.location.register,right.location.register);
1250
 
               location_swap(left.location,right.location);
1251
 
               toggleflag(nf_swaped);
1252
 
             end
1253
 
            else
1254
 
             begin
1255
 
               emit_reg_reg(op,S_NO,right.location.register,left.location.register);
1256
 
             end;
1257
 
          end;
1258
 
 
1259
 
        location_freetemp(exprasmlist,right.location);
1260
 
        location_release(exprasmlist,right.location);
1261
 
        if cmpop then
1262
 
         begin
1263
 
           location_freetemp(exprasmlist,left.location);
1264
 
           location_release(exprasmlist,left.location);
1265
 
         end;
1266
 
        set_result_location(cmpop,true);
1267
 
      end;
1268
 
{$endif SUPPORT_MMX}
1269
 
 
1270
 
 
1271
 
{*****************************************************************************
1272
 
                                pass_2
1273
 
*****************************************************************************}
1274
 
 
1275
 
    procedure tppcaddnode.pass_2;
1276
 
    { is also being used for xor, and "mul", "sub, or and comparative }
1277
 
    { operators                                                }
1278
 
      var
1279
 
         cgop       : topcg;
1280
 
         op         : tasmop;
1281
 
         tmpreg     : tregister;
1282
 
         hl         : tasmlabel;
1283
 
         cmpop      : boolean;
1284
 
 
1285
 
         { true, if unsigned types are compared }
1286
 
         unsigned : boolean;
1287
 
 
1288
 
      begin
1289
 
         { to make it more readable, string and set (not smallset!) have their
1290
 
           own procedures }
1291
 
         case left.resulttype.def.deftype of
1292
 
           orddef :
1293
 
             begin
1294
 
               { handling boolean expressions }
1295
 
               if is_boolean(left.resulttype.def) and
1296
 
                  is_boolean(right.resulttype.def) then
1297
 
                 begin
1298
 
                   second_addboolean;
1299
 
                   exit;
1300
 
                 end
1301
 
               { 64bit operations }
1302
 
               else if is_64bit(left.resulttype.def) then
1303
 
                 begin
1304
 
                   second_add64bit;
1305
 
                   exit;
1306
 
                 end;
1307
 
             end;
1308
 
           stringdef :
1309
 
             begin
1310
 
               internalerror(2002072402);
1311
 
               exit;
1312
 
             end;
1313
 
           setdef :
1314
 
             begin
1315
 
               { normalsets are already handled in pass1 }
1316
 
               if (tsetdef(left.resulttype.def).settype<>smallset) then
1317
 
                internalerror(200109041);
1318
 
               second_addsmallset;
1319
 
               exit;
1320
 
             end;
1321
 
           arraydef :
1322
 
             begin
1323
 
{$ifdef SUPPORT_MMX}
1324
 
               if is_mmx_able_array(left.resulttype.def) then
1325
 
                begin
1326
 
                  second_addmmx;
1327
 
                  exit;
1328
 
                end;
1329
 
{$endif SUPPORT_MMX}
1330
 
             end;
1331
 
           floatdef :
1332
 
             begin
1333
 
               second_addfloat;
1334
 
               exit;
1335
 
             end;
1336
 
         end;
1337
 
 
1338
 
         { defaults }
1339
 
         cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
1340
 
         unsigned:=not(is_signed(left.resulttype.def)) or
1341
 
                   not(is_signed(right.resulttype.def));
1342
 
 
1343
 
         pass_left_and_right;
1344
 
 
1345
 
         { Convert flags to register first }
1346
 
         { can any of these things be in the flags actually?? (JM) }
1347
 
 
1348
 
         if (left.location.loc = LOC_FLAGS) or
1349
 
            (right.location.loc = LOC_FLAGS) then
1350
 
           internalerror(2002072602);
1351
 
 
1352
 
         { set result location }
1353
 
         if not cmpop then
1354
 
           location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
1355
 
          else
1356
 
           location_reset(location,LOC_FLAGS,OS_NO);
1357
 
 
1358
 
         load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
1359
 
            (nodetype in [addn,subn,muln]));
1360
 
 
1361
 
         if (location.register = NR_NO) and
1362
 
            not(cmpop) then
1363
 
           location.register := cg.getintregister(exprasmlist,OS_INT);
1364
 
 
1365
 
         if not(cs_check_overflow in aktlocalswitches) or
1366
 
            (cmpop) or
1367
 
            (nodetype in [orn,andn,xorn]) then
1368
 
           begin
1369
 
             case nodetype of
1370
 
               addn, muln, xorn, orn, andn:
1371
 
                 begin
1372
 
                   case nodetype of
1373
 
                     addn:
1374
 
                       cgop := OP_ADD;
1375
 
                     muln:
1376
 
                       if unsigned then
1377
 
                         cgop := OP_MUL
1378
 
                       else
1379
 
                         cgop := OP_IMUL;
1380
 
                     xorn:
1381
 
                       cgop := OP_XOR;
1382
 
                     orn:
1383
 
                       cgop := OP_OR;
1384
 
                     andn:
1385
 
                       cgop := OP_AND;
1386
 
                   end;
1387
 
                   if (left.location.loc = LOC_CONSTANT) then
1388
 
                     swapleftright;
1389
 
                   if (right.location.loc <> LOC_CONSTANT) then
1390
 
                     cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
1391
 
                       left.location.register,right.location.register,
1392
 
                       location.register)
1393
 
                   else
1394
 
                     cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
1395
 
                       aword(right.location.value),left.location.register,
1396
 
                     location.register);
1397
 
                 end;
1398
 
               subn:
1399
 
                 begin
1400
 
                   if (nf_swaped in flags) then
1401
 
                     swapleftright;
1402
 
                   if left.location.loc <> LOC_CONSTANT then
1403
 
                     if right.location.loc <> LOC_CONSTANT then
1404
 
                       cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
1405
 
                         right.location.register,left.location.register,
1406
 
                         location.register)
1407
 
                     else
1408
 
                       cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
1409
 
                         aword(right.location.value),left.location.register,
1410
 
                         location.register)
1411
 
                   else
1412
 
                     if (longint(left.location.value) >= low(smallint)) and
1413
 
                        (longint(left.location.value) <= high(smallint)) then
1414
 
                       begin
1415
 
                         exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
1416
 
                           location.register,right.location.register,
1417
 
                           longint(left.location.value)));
1418
 
                       end
1419
 
                     else
1420
 
                       begin
1421
 
                         tmpreg := cg.getintregister(exprasmlist,OS_INT);
1422
 
                         cg.a_load_const_reg(exprasmlist,OS_INT,
1423
 
                           aword(left.location.value),tmpreg);
1424
 
                         cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
1425
 
                           right.location.register,tmpreg,location.register);
1426
 
                         cg.ungetregister(exprasmlist,tmpreg);
1427
 
                       end;
1428
 
                 end;
1429
 
               ltn,lten,gtn,gten,equaln,unequaln :
1430
 
                 begin
1431
 
                   emit_compare(unsigned);
1432
 
                 end;
1433
 
             end;
1434
 
           end
1435
 
         else
1436
 
           // overflow checking is on and we have an addn, subn or muln
1437
 
           begin
1438
 
             if is_signed(resulttype.def) then
1439
 
               begin
1440
 
                 case nodetype of
1441
 
                   addn:
1442
 
                     op := A_ADDO;
1443
 
                   subn:
1444
 
                     op := A_SUBO;
1445
 
                   muln:
1446
 
                     op := A_MULLWO;
1447
 
                   else
1448
 
                     internalerror(2002072601);
1449
 
                 end;
1450
 
                 exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
1451
 
                   left.location.register,right.location.register));
1452
 
                 cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1453
 
              end
1454
 
             else
1455
 
              begin
1456
 
                case nodetype of
1457
 
                  addn:
1458
 
                    begin
1459
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
1460
 
                        left.location.register,right.location.register));
1461
 
                      exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
1462
 
                      cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1463
 
                    end;
1464
 
                  subn:
1465
 
                    begin
1466
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
1467
 
                        left.location.register,right.location.register));
1468
 
                      exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
1469
 
                      cg.g_overflowcheck(exprasmlist,location,resulttype.def);
1470
 
                    end;
1471
 
                  muln:
1472
 
                    begin
1473
 
                      { calculate the upper 32 bits of the product, = 0 if no overflow }
1474
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,location.register,
1475
 
                        left.location.register,right.location.register));
1476
 
                      { calculate the real result }
1477
 
                      exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
1478
 
                        left.location.register,right.location.register));
1479
 
                      { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
1480
 
                      objectlibrary.getlabel(hl);
1481
 
                      tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
1482
 
                      cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
1483
 
                      cg.a_label(exprasmlist,hl);
1484
 
                    end;
1485
 
                end;
1486
 
              end;
1487
 
           end;
1488
 
 
1489
 
         release_reg_left_right;
1490
 
      end;
1491
 
 
1492
 
begin
1493
 
   caddnode:=tppcaddnode;
1494
 
end.
1495
 
{
1496
 
  $Log: nppcadd.pas,v $
1497
 
  Revision 1.43  2004/03/18 16:19:03  peter
1498
 
    * fixed operator overload allowing for pointer-string
1499
 
    * replaced some type_e_mismatch with more informational messages
1500
 
 
1501
 
  Revision 1.42  2004/01/06 21:37:41  peter
1502
 
    * fixed too long ie number
1503
 
 
1504
 
  Revision 1.41  2003/12/29 11:35:19  jonas
1505
 
    * hopefully fixed tb0454
1506
 
 
1507
 
  Revision 1.40  2003/12/09 20:39:43  jonas
1508
 
    * forgot call to cg.g_overflowcheck() in nppcadd
1509
 
    * fixed overflow flag definition
1510
 
    * fixed cg.g_overflowcheck() for signed numbers (jump over call to
1511
 
      FPC_OVERFLOW if *no* overflow instead of if overflow :)
1512
 
 
1513
 
  Revision 1.39  2003/12/08 21:18:44  jonas
1514
 
    * fixed usigned overflow checking
1515
 
 
1516
 
  Revision 1.38  2003/10/17 14:52:07  peter
1517
 
    * fixed ppc build
1518
 
 
1519
 
  Revision 1.37  2003/10/17 01:22:08  florian
1520
 
    * compilation of the powerpc compiler fixed
1521
 
 
1522
 
  Revision 1.36  2003/10/01 20:34:49  peter
1523
 
    * procinfo unit contains tprocinfo
1524
 
    * cginfo renamed to cgbase
1525
 
    * moved cgmessage to verbose
1526
 
    * fixed ppc and sparc compiles
1527
 
 
1528
 
  Revision 1.35  2003/09/03 19:39:16  peter
1529
 
    * removed empty cga unit
1530
 
 
1531
 
  Revision 1.34  2003/09/03 19:35:24  peter
1532
 
    * powerpc compiles again
1533
 
 
1534
 
  Revision 1.33  2003/06/14 22:32:43  jonas
1535
 
    * ppc compiles with -dnewra, haven't tried to compile anything with it
1536
 
      yet though
1537
 
 
1538
 
  Revision 1.32  2003/06/04 11:58:58  jonas
1539
 
    * calculate localsize also in g_return_from_proc since it's now called
1540
 
      before g_stackframe_entry (still have to fix macos)
1541
 
    * compilation fixes (cycle doesn't work yet though)
1542
 
 
1543
 
  Revision 1.31  2003/06/01 21:38:06  peter
1544
 
    * getregisterfpu size parameter added
1545
 
    * op_const_reg size parameter added
1546
 
    * sparc updates
1547
 
 
1548
 
  Revision 1.30  2003/05/30 18:49:14  jonas
1549
 
    * fixed problem where sometimes no register was allocated for the result
1550
 
      of an addnode when using regvars
1551
 
 
1552
 
  Revision 1.29  2003/04/27 11:55:34  jonas
1553
 
    * fixed overflow checking form of 64bit add instruction
1554
 
 
1555
 
  Revision 1.28  2003/04/27 11:06:06  jonas
1556
 
    * fixed 64bit "const - reg/ref" bugs
1557
 
 
1558
 
  Revision 1.27  2003/04/24 22:29:58  florian
1559
 
    * fixed a lot of PowerPC related stuff
1560
 
 
1561
 
  Revision 1.26  2003/04/23 22:18:01  peter
1562
 
    * fixes to get rtl compiled
1563
 
 
1564
 
  Revision 1.25  2003/04/23 12:35:35  florian
1565
 
    * fixed several issues with powerpc
1566
 
    + applied a patch from Jonas for nested function calls (PowerPC only)
1567
 
    * ...
1568
 
 
1569
 
  Revision 1.24  2003/03/11 21:46:24  jonas
1570
 
    * lots of new regallocator fixes, both in generic and ppc-specific code
1571
 
      (ppc compiler still can't compile the linux system unit though)
1572
 
 
1573
 
  Revision 1.23  2003/03/10 18:11:41  olle
1574
 
    * changed ungetregister to ungetregisterint in tppcaddnode.clear_left_right
1575
 
 
1576
 
  Revision 1.22  2003/02/19 22:00:16  daniel
1577
 
    * Code generator converted to new register notation
1578
 
    - Horribily outdated todo.txt removed
1579
 
 
1580
 
  Revision 1.21  2003/01/08 18:43:58  daniel
1581
 
   * Tregister changed into a record
1582
 
 
1583
 
  Revision 1.20  2002/11/25 17:43:27  peter
1584
 
    * splitted defbase in defutil,symutil,defcmp
1585
 
    * merged isconvertable and is_equal into compare_defs(_ext)
1586
 
    * made operator search faster by walking the list only once
1587
 
 
1588
 
  Revision 1.19  2002/10/21 18:08:05  jonas
1589
 
    * some range errors fixed
1590
 
 
1591
 
  Revision 1.18  2002/09/08 14:14:49  jonas
1592
 
    * more optimizations for 64bit compares
1593
 
 
1594
 
  Revision 1.17  2002/09/07 22:15:48  jonas
1595
 
    * fixed optimized 64 compares
1596
 
 
1597
 
  Revision 1.16  2002/09/04 19:42:45  jonas
1598
 
    * fixed bugs in 64bit operations (registers weren't always allocated for
1599
 
      the result)
1600
 
    * optimized 'const64 - reg64/mem64'
1601
 
    * optimized equaln/unequaln with 64bit values (change them to
1602
 
      '(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
1603
 
      branches and the result can be returned in the flags this way. Could
1604
 
      be done for the i386 too probably.
1605
 
 
1606
 
  Revision 1.15  2002/08/31 21:30:46  florian
1607
 
    * fixed several problems caused by Jonas' commit :)
1608
 
 
1609
 
  Revision 1.14  2002/08/31 19:26:20  jonas
1610
 
    * fixed 64bit comparisons
1611
 
 
1612
 
  Revision 1.13  2002/08/17 22:09:47  florian
1613
 
    * result type handling in tcgcal.pass_2 overhauled
1614
 
    * better tnode.dowrite
1615
 
    * some ppc stuff fixed
1616
 
 
1617
 
  Revision 1.12  2002/08/14 18:41:48  jonas
1618
 
    - remove valuelow/valuehigh fields from tlocation, because they depend
1619
 
      on the endianess of the host operating system -> difficult to get
1620
 
      right. Use lo/hi(location.valueqword) instead (remember to use
1621
 
      valueqword and not value!!)
1622
 
 
1623
 
  Revision 1.11  2002/08/11 14:32:32  peter
1624
 
    * renamed current_library to objectlibrary
1625
 
 
1626
 
  Revision 1.10  2002/08/11 13:24:18  peter
1627
 
    * saving of asmsymbols in ppu supported
1628
 
    * asmsymbollist global is removed and moved into a new class
1629
 
      tasmlibrarydata that will hold the info of a .a file which
1630
 
      corresponds with a single module. Added librarydata to tmodule
1631
 
      to keep the library info stored for the module. In the future the
1632
 
      objectfiles will also be stored to the tasmlibrarydata class
1633
 
    * all getlabel/newasmsymbol and friends are moved to the new class
1634
 
 
1635
 
  Revision 1.9  2002/08/11 11:40:16  jonas
1636
 
    * some overflow checking fixes
1637
 
 
1638
 
  Revision 1.8  2002/08/11 06:14:40  florian
1639
 
    * fixed powerpc compilation problems
1640
 
 
1641
 
  Revision 1.7  2002/08/10 17:15:31  jonas
1642
 
    * various fixes and optimizations
1643
 
 
1644
 
  Revision 1.6  2002/08/06 20:55:24  florian
1645
 
    * first part of ppc calling conventions fix
1646
 
 
1647
 
  Revision 1.5  2002/08/05 08:58:54  jonas
1648
 
    * fixed compilation problems
1649
 
 
1650
 
  Revision 1.4  2002/08/04 12:57:56  jonas
1651
 
    * more misc. fixes, mostly constant-related
1652
 
 
1653
 
  Revision 1.3  2002/07/28 16:02:49  jonas
1654
 
    + 64 bit operations (badly tested), everything is implemented now!
1655
 
    * some small fixes
1656
 
 
1657
 
  Revision 1.2  2002/07/27 20:00:59  jonas
1658
 
    + second_addboolean(), second_addfloat() and second_addsmallset()
1659
 
      (64bit stuff is all that's left to do)
1660
 
 
1661
 
  Revision 1.1  2002/07/26 12:31:57  jonas
1662
 
    + intial implementation of add nodes, only integer/enumeration/pointer/...
1663
 
      handling is finished
1664
 
}