~ubuntu-branches/ubuntu/dapper/fpc/dapper

« back to all changes in this revision

Viewing changes to compiler/x86/nx86add.pas

  • Committer: Bazaar Package Importer
  • Author(s): Carlos Laviola
  • Date: 2005-05-30 11:59:10 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050530115910-x5pbzm4qqta4i94h
Tags: 2.0.0-2
debian/fp-compiler.postinst.in: forgot to reapply the patch that
correctly creates the slave link to pc(1).  (Closes: #310907)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
{
2
 
    $Id: nx86add.pas,v 1.9 2004/02/22 16:30:37 florian Exp $
 
2
    $Id: nx86add.pas,v 1.17 2005/02/14 17:13:10 peter Exp $
3
3
    Copyright (c) 2000-2002 by Florian Klaempfl
4
4
 
5
5
    Common code generation for add nodes on the i386 and x86
20
20
 
21
21
 ****************************************************************************
22
22
}
23
 
{
24
 
Common code generation for add nodes on the i386 and x86
25
 
}
26
23
unit nx86add;
27
24
 
28
25
{$i fpcdefs.inc}
40
37
        function  getresflags(unsigned : boolean) : tresflags;
41
38
        procedure left_must_be_reg(opsize:TCGSize;noswap:boolean);
42
39
        procedure left_and_right_must_be_fpureg;
43
 
        procedure emit_op_right_left(op:TAsmOp;opsize:TOpSize);
 
40
        procedure emit_op_right_left(op:TAsmOp;opsize:TCgSize);
44
41
        procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean);
45
42
 
46
43
        procedure second_cmpfloatsse;
47
44
        procedure second_addfloatsse;
48
45
        procedure second_mul;virtual;abstract;
49
46
      public
50
 
        function  first_addstring : tnode; override;
51
 
        procedure second_addstring;override;
52
47
        procedure second_addfloat;override;
53
48
        procedure second_addsmallset;override;
54
49
        procedure second_add64bit;override;
64
59
 
65
60
    uses
66
61
      globtype,globals,
67
 
      verbose,
68
 
      cutils,
 
62
      verbose,cutils,
69
63
      cpuinfo,
70
64
      aasmbase,aasmtai,aasmcpu,
71
 
      symconst,symdef,
72
 
      cgobj,cgx86,cga,
73
 
      paramgr,
74
 
      htypechk,
75
 
      pass_2,ncgutil,
 
65
      symconst,
 
66
      cgobj,cgx86,cga,cgutils,
 
67
      paramgr,tgobj,ncgutil,
76
68
      ncon,nset,
77
69
      defutil;
78
70
 
116
108
           if (nodetype=subn) and (nf_swaped in flags) then
117
109
            begin
118
110
              if extra_not then
119
 
                emit_reg(A_NOT,TCGSize2Opsize[opsize],left.location.register);
120
 
              r:=cg.getintregister(exprasmlist,OS_INT);
121
 
              cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,r);
 
111
                cg.a_op_reg_reg(exprasmlist,OP_NOT,opsize,left.location.register,left.location.register);
 
112
              r:=cg.getintregister(exprasmlist,opsize);
 
113
              cg.a_load_loc_reg(exprasmlist,opsize,right.location,r);
122
114
              emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,r);
123
 
              emit_reg_reg(A_MOV,TCGSize2Opsize[opsize],r,left.location.register);
124
 
              cg.ungetregister(exprasmlist,r);
 
115
              cg.a_load_reg_reg(exprasmlist,opsize,opsize,r,left.location.register);
125
116
            end
126
117
           else
127
118
            begin
152
143
               else
153
144
                 if (op=A_IMUL) and
154
145
                    (right.location.loc=LOC_CONSTANT) and
155
 
                    (ispowerof2(right.location.value,power)) and
 
146
                    (ispowerof2(int64(right.location.value),power)) and
156
147
                    not(cs_check_overflow in aktlocalswitches) then
157
148
                  begin
158
149
                    emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
161
152
                 begin
162
153
                   if extra_not then
163
154
                     begin
164
 
                        r:=cg.getintregister(exprasmlist,OS_INT);
165
 
                        cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,r);
 
155
                        r:=cg.getintregister(exprasmlist,opsize);
 
156
                        cg.a_load_loc_reg(exprasmlist,opsize,right.location,r);
166
157
                        emit_reg(A_NOT,TCGSize2Opsize[opsize],r);
167
158
                        emit_reg_reg(A_AND,TCGSize2Opsize[opsize],r,left.location.register);
168
 
                        cg.ungetregister(exprasmlist,r);
169
159
                     end
170
160
                   else
171
161
                     begin
172
 
                        emit_op_right_left(op,TCGSize2Opsize[opsize]);
 
162
                        emit_op_right_left(op,opsize);
173
163
                     end;
174
164
                 end;
175
165
            end;
236
226
              { left was on the stack => swap }
237
227
              toggleflag(nf_swaped);
238
228
            end;
239
 
 
240
 
           { releases the right reference }
241
 
           location_release(exprasmlist,right.location);
242
229
         end
243
230
        { the nominator in st0 }
244
231
        else if (left.location.loc<>LOC_FPUREGISTER) then
255
242
      end;
256
243
 
257
244
 
258
 
    procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TOpsize);
 
245
    procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TCgsize);
 
246
{$ifdef x86_64}
 
247
      var
 
248
        tmpreg : tregister;
 
249
{$endif x86_64}
259
250
      begin
260
251
        { left must be a register }
261
252
        case right.location.loc of
262
253
          LOC_REGISTER,
263
254
          LOC_CREGISTER :
264
 
            exprasmlist.concat(taicpu.op_reg_reg(op,opsize,right.location.register,left.location.register));
 
255
            exprasmlist.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register));
265
256
          LOC_REFERENCE,
266
257
          LOC_CREFERENCE :
267
 
            exprasmlist.concat(taicpu.op_ref_reg(op,opsize,right.location.reference,left.location.register));
 
258
            begin
 
259
              tcgx86(cg).make_simple_ref(exprasmlist,right.location.reference);
 
260
              exprasmlist.concat(taicpu.op_ref_reg(op,TCGSize2Opsize[opsize],right.location.reference,left.location.register));
 
261
            end;
268
262
          LOC_CONSTANT :
269
 
            exprasmlist.concat(taicpu.op_const_reg(op,opsize,right.location.value,left.location.register));
 
263
            begin
 
264
{$ifdef x86_64}
 
265
              { x86_64 only supports signed 32 bits constants directly }
 
266
              if (opsize in [OS_S64,OS_64]) and
 
267
                 ((right.location.value<low(longint)) or (right.location.value>high(longint))) then
 
268
                begin
 
269
                  tmpreg:=cg.getintregister(exprasmlist,opsize);
 
270
                  cg.a_load_const_reg(exprasmlist,opsize,right.location.value,tmpreg);
 
271
                  exprasmlist.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],tmpreg,left.location.register));
 
272
                end
 
273
              else
 
274
{$endif x86_64}
 
275
                exprasmlist.concat(taicpu.op_const_reg(op,TCGSize2Opsize[opsize],right.location.value,left.location.register));
 
276
            end;
270
277
          else
271
278
            internalerror(200203232);
272
279
        end;
387
394
        left_must_be_reg(opsize,noswap);
388
395
        emit_generic_code(op,opsize,true,extra_not,false);
389
396
        location_freetemp(exprasmlist,right.location);
390
 
        location_release(exprasmlist,right.location);
391
397
 
392
398
        set_result_location_reg;
393
399
      end;
410
416
                 ((nf_swaped in flags) and (nodetype = gten)) then
411
417
                swapleftright;
412
418
              location_force_reg(exprasmlist,left.location,opsize,true);
413
 
              emit_op_right_left(A_AND,TCGSize2Opsize[opsize]);
 
419
              emit_op_right_left(A_AND,opsize);
414
420
              op:=A_CMP;
415
421
              { warning: ugly hack, we need a JE so change the node to equaln }
416
422
              nodetype:=equaln;
422
428
        left_must_be_reg(opsize,false);
423
429
        emit_generic_code(op,opsize,true,false,false);
424
430
        location_freetemp(exprasmlist,right.location);
425
 
        location_release(exprasmlist,right.location);
426
431
        location_freetemp(exprasmlist,left.location);
427
 
        location_release(exprasmlist,left.location);
428
432
 
429
433
        location_reset(location,LOC_FLAGS,OS_NO);
430
434
        location.resflags:=getresflags(true);
469
473
            if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
470
474
              location_force_mem(exprasmlist,left.location);
471
475
            cg.a_opmm_loc_reg(exprasmlist,op,location.size,left.location,location.register,mms_movescalar);
472
 
            location_release(exprasmlist,left.location);
473
476
          end
474
477
        else
475
478
          begin
483
486
            if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
484
487
              location_force_mem(exprasmlist,right.location);
485
488
            cg.a_opmm_loc_reg(exprasmlist,op,location.size,right.location,location.register,mms_movescalar);
486
 
            location_release(exprasmlist,right.location);
487
489
          end;
488
490
      end;
489
491
 
513
515
              location_force_mem(exprasmlist,left.location);
514
516
            case left.location.loc of
515
517
              LOC_REFERENCE,LOC_CREFERENCE:
516
 
                exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,left.location.reference,right.location.register));
 
518
                begin
 
519
                  tcgx86(cg).make_simple_ref(exprasmlist,left.location.reference);
 
520
                  exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,left.location.reference,right.location.register));
 
521
                end;
517
522
              LOC_MMREGISTER,LOC_CMMREGISTER:
518
523
                exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,left.location.register,right.location.register));
519
524
              else
536
541
              location_force_mem(exprasmlist,right.location);
537
542
            case right.location.loc of
538
543
              LOC_REFERENCE,LOC_CREFERENCE:
539
 
                exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,right.location.reference,left.location.register));
 
544
                begin
 
545
                  tcgx86(cg).make_simple_ref(exprasmlist,right.location.reference);
 
546
                  exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,right.location.reference,left.location.register));
 
547
                end;
540
548
              LOC_MMREGISTER,LOC_CMMREGISTER:
541
549
                exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,right.location.register,left.location.register));
542
550
              else
543
551
                internalerror(200402223);
544
552
            end;
545
553
          end;
546
 
        location_release(exprasmlist,right.location);
547
 
        location_release(exprasmlist,left.location);
548
554
        location.resflags:=getresflags(true);
549
555
      end;
550
556
 
576
582
 
577
583
        left_and_right_must_be_fpureg;
578
584
 
579
 
        { releases the left reference }
580
 
        if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
581
 
          location_release(exprasmlist,left.location);
582
 
 
583
585
        { if we swaped the tree nodes, then use the reverse operator }
584
586
        if nf_swaped in flags then
585
587
          begin
610
612
        pass_left_right;
611
613
        left_and_right_must_be_fpureg;
612
614
 
613
 
        { releases the left reference }
614
 
        if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
615
 
          location_release(exprasmlist,left.location);
616
 
 
617
615
{$ifndef x86_64}
618
616
        if aktspecificoptprocessor<ClassPentium2 then
619
617
          begin
622
620
            tcgx86(cg).dec_fpu_stack;
623
621
 
624
622
            { load fpu flags }
625
 
            cg.getexplicitregister(exprasmlist,NR_AX);
 
623
            cg.getcpuregister(exprasmlist,NR_AX);
626
624
            emit_reg(A_FNSTSW,S_NO,NR_AX);
627
625
            emit_none(A_SAHF,S_NO);
628
 
            cg.ungetregister(exprasmlist,NR_AX);
 
626
            cg.ungetcpuregister(exprasmlist,NR_AX);
629
627
            if nf_swaped in flags then
630
628
             begin
631
629
               case nodetype of
689
687
 
690
688
 
691
689
{*****************************************************************************
692
 
                                Addstring
693
 
*****************************************************************************}
694
 
 
695
 
    { note: if you implemented an fpc_shortstr_concat similar to the    }
696
 
    { one in i386.inc, you have to override first_addstring like in     }
697
 
    { ti386addnode.first_string and implement the shortstring concat    }
698
 
    { manually! The generic routine is different from the i386 one (JM) }
699
 
    function tx86addnode.first_addstring : tnode;
700
 
      begin
701
 
        { special cases for shortstrings, handled in pass_2 (JM) }
702
 
        { can't handle fpc_shortstr_compare with compilerproc either because it }
703
 
        { returns its results in the flags instead of in eax                    }
704
 
        if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) and
705
 
           is_shortstring(left.resulttype.def) and
706
 
           not(((left.nodetype=stringconstn) and (str_length(left)=0)) or
707
 
              ((right.nodetype=stringconstn) and (str_length(right)=0))) then
708
 
         begin
709
 
           expectloc:=LOC_FLAGS;
710
 
           calcregisters(self,0,0,0);
711
 
           result := nil;
712
 
           exit;
713
 
         end;
714
 
        { otherwise, use the generic code }
715
 
        result := inherited first_addstring;
716
 
      end;
717
 
 
718
 
 
719
 
    procedure tx86addnode.second_addstring;
720
 
      var
721
 
        paraloc1,
722
 
        paraloc2   : tparalocation;
723
 
        hregister1,
724
 
        hregister2 : tregister;
725
 
      begin
726
 
        { string operations are not commutative }
727
 
        if nf_swaped in flags then
728
 
          swapleftright;
729
 
        case tstringdef(left.resulttype.def).string_typ of
730
 
           st_shortstring:
731
 
             begin
732
 
                case nodetype of
733
 
                   ltn,lten,gtn,gten,equaln,unequaln :
734
 
                     begin
735
 
                       paraloc1:=paramanager.getintparaloc(pocall_default,1);
736
 
                       paraloc2:=paramanager.getintparaloc(pocall_default,2);
737
 
                       { process parameters }
738
 
                       secondpass(left);
739
 
                       location_release(exprasmlist,left.location);
740
 
                       if paraloc2.loc=LOC_REGISTER then
741
 
                         begin
742
 
                           hregister2:=cg.getaddressregister(exprasmlist);
743
 
                           cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister2);
744
 
                         end
745
 
                       else
746
 
                         begin
747
 
                           paramanager.allocparaloc(exprasmlist,paraloc2);
748
 
                           cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraloc2);
749
 
                         end;
750
 
                       secondpass(right);
751
 
                       location_release(exprasmlist,right.location);
752
 
                       if paraloc1.loc=LOC_REGISTER then
753
 
                         begin
754
 
                           hregister1:=cg.getaddressregister(exprasmlist);
755
 
                           cg.a_loadaddr_ref_reg(exprasmlist,right.location.reference,hregister1);
756
 
                         end
757
 
                       else
758
 
                         begin
759
 
                           paramanager.allocparaloc(exprasmlist,paraloc1);
760
 
                           cg.a_paramaddr_ref(exprasmlist,right.location.reference,paraloc1);
761
 
                         end;
762
 
                       { push parameters }
763
 
                       if paraloc1.loc=LOC_REGISTER then
764
 
                         begin
765
 
                           cg.ungetregister(exprasmlist,hregister2);
766
 
                           paramanager.allocparaloc(exprasmlist,paraloc2);
767
 
                           cg.a_param_reg(exprasmlist,OS_ADDR,hregister2,paraloc2);
768
 
                         end;
769
 
                       if paraloc2.loc=LOC_REGISTER then
770
 
                         begin
771
 
                           cg.ungetregister(exprasmlist,hregister1);
772
 
                           paramanager.allocparaloc(exprasmlist,paraloc1);
773
 
                           cg.a_param_reg(exprasmlist,OS_ADDR,hregister1,paraloc1);
774
 
                         end;
775
 
                       paramanager.freeparaloc(exprasmlist,paraloc1);
776
 
                       paramanager.freeparaloc(exprasmlist,paraloc2);
777
 
                       cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
778
 
                       cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
779
 
                       cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
780
 
                       location_freetemp(exprasmlist,left.location);
781
 
                       location_freetemp(exprasmlist,right.location);
782
 
                     end;
783
 
                end;
784
 
                location_reset(location,LOC_FLAGS,OS_NO);
785
 
                location.resflags:=getresflags(true);
786
 
             end;
787
 
           else
788
 
             { rest should be handled in first pass (JM) }
789
 
             internalerror(200108303);
790
 
       end;
791
 
     end;
792
 
 
793
 
{*****************************************************************************
794
690
                                  Add64bit
795
691
*****************************************************************************}
796
692
 
878
774
         left_must_be_reg(opsize,false);
879
775
         emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
880
776
         location_freetemp(exprasmlist,right.location);
881
 
         location_release(exprasmlist,right.location);
882
777
 
883
778
         set_result_location_reg;
884
779
      end;
898
793
         left_must_be_reg(opsize,false);
899
794
         emit_generic_code(A_CMP,opsize,unsigned,false,false);
900
795
         location_freetemp(exprasmlist,right.location);
901
 
         location_release(exprasmlist,right.location);
902
 
         if (left.location.loc<>LOC_CREGISTER) then
903
 
           begin
904
 
             location_freetemp(exprasmlist,left.location);
905
 
             location_release(exprasmlist,left.location);
906
 
           end;
 
796
         location_freetemp(exprasmlist,left.location);
 
797
 
907
798
         location_reset(location,LOC_FLAGS,OS_NO);
908
799
         location.resflags:=getresflags(unsigned);
909
800
      end;
913
804
end.
914
805
{
915
806
  $Log: nx86add.pas,v $
916
 
  Revision 1.9  2004/02/22 16:30:37  florian
917
 
    * fixed
918
 
    + second_cmpfloatsse
919
 
 
920
 
  Revision 1.8  2004/02/06 16:44:42  florian
921
 
    + improved floating point compares for x86-64 and Pentium2 and above
922
 
 
923
 
  Revision 1.7  2004/02/04 19:22:27  peter
924
 
  *** empty log message ***
925
 
 
926
 
  Revision 1.6  2004/01/20 12:59:37  florian
927
 
    * common addnode code for x86-64 and i386
928
 
 
929
 
  Revision 1.5  2003/12/26 13:19:16  florian
930
 
    * rtl and compiler compile with -Cfsse2
931
 
 
932
 
  Revision 1.4  2003/12/26 00:32:22  florian
933
 
    + fpu<->mm register conversion
934
 
 
935
 
  Revision 1.3  2003/12/25 01:07:09  florian
936
 
    + $fputype directive support
937
 
    + single data type operations with sse unit
938
 
    * fixed more x86-64 stuff
939
 
 
940
 
  Revision 1.2  2003/12/23 14:38:07  florian
941
 
    + second_floataddsse implemented
942
 
 
943
 
  Revision 1.1  2003/10/13 01:58:04  florian
944
 
    * some ideas for mm support implemented
 
807
  Revision 1.17  2005/02/14 17:13:10  peter
 
808
    * truncate log
 
809
 
 
810
  Revision 1.16  2005/02/06 00:05:56  florian
 
811
    + x86_64 pic draft
 
812
 
945
813
}