Browse Source

* qword/int64 multiplication fixed
+ qword/int64 subtraction

florian 26 years ago
parent
commit
59c6d9f289
2 changed files with 99 additions and 60 deletions
  1. 40 12
      compiler/cg386add.pas
  2. 59 48
      compiler/cg386inl.pas

+ 40 - 12
compiler/cg386add.pas

@@ -583,6 +583,7 @@ implementation
          mmxbase : tmmxtype;
 {$endif SUPPORT_MMX}
          pushedreg : tpushed;
+         hloc : tlocation;
 
       begin
       { to make it more readable, string and set (not smallset!) have their
@@ -1451,7 +1452,9 @@ implementation
 
                    if p^.treetype=muln then
                      begin
-                        release_qword_loc(p^.left^.location);
+                        { save p^.lcoation, because we change it now }
+                        set_location(hloc,p^.location);
+                        release_qword_loc(p^.location);
                         release_qword_loc(p^.right^.location);
                         p^.location.registerlow:=getexplicitregister32(R_EAX);
                         p^.location.registerhigh:=getexplicitregister32(R_EDX);
@@ -1462,7 +1465,12 @@ implementation
                           push_int(1)
                         else
                           push_int(0);
-                        emit_pushq_loc(p^.left^.location);
+                        { the left operand is in hloc, because the
+                          location of left is p^.location but p^.location
+                          is already destroyed
+                        }
+                        emit_pushq_loc(hloc);
+                        clear_location(hloc);
                         emit_pushq_loc(p^.right^.location);
                         if porddef(p^.resulttype)^.typ=u64bit then
                           emitcall('FPC_MUL_QWORD',true)
@@ -1555,7 +1563,7 @@ implementation
                         { and p^.location.register should be a valid register   }
                         { containing the left result                            }
 
-                         if p^.right^.location.loc<>LOC_REGISTER then
+                        if p^.right^.location.loc<>LOC_REGISTER then
                           begin
                              if (p^.treetype=subn) and p^.swaped then
                                begin
@@ -1564,13 +1572,25 @@ implementation
                                        emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
                                        emit_reg_reg(op,opsize,p^.location.register,R_EDI);
                                        emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
+                                       emit_reg_reg(A_MOV,opsize,p^.right^.location.registerhigh,R_EDI);
+                                       { the carry flag is still ok }
+                                       emit_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI);
+                                       emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerhigh);
                                     end
                                   else
                                     begin
                                        exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
                                          newreference(p^.right^.location.reference),R_EDI)));
-                                       exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_EDI)));
-                                       exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,p^.location.register)));
+                                       exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.registerlow,R_EDI)));
+                                       exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,p^.location.registerlow)));
+                                       hr:=newreference(p^.right^.location.reference);
+                                       inc(hr^.offset,4);
+                                       exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
+                                         hr,R_EDI)));
+                                       { here the carry flag is still preserved }
+                                       exprasmlist^.concat(new(pai386,op_reg_reg(op2,opsize,p^.location.registerhigh,R_EDI)));
+                                       exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,
+                                         p^.location.registerhigh)));
                                        ungetiftemp(p^.right^.location.reference);
                                        del_reference(p^.right^.location.reference);
                                     end;
@@ -1653,12 +1673,16 @@ implementation
                              { when swapped another result register }
                              if (p^.treetype=subn) and p^.swaped then
                                begin
-                                  exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
-                                    p^.location.register,p^.right^.location.register)));
-                                    swap_location(p^.location,p^.right^.location);
-                                    { newly swapped also set swapped flag }
-                                    { just to maintain ordering           }
-                                    p^.swaped:=not(p^.swaped);
+                                  exprasmlist^.concat(new(pai386,op_reg_reg(op,S_L,
+                                    p^.location.registerlow,
+                                    p^.right^.location.registerlow)));
+                                 exprasmlist^.concat(new(pai386,op_reg_reg(op2,S_L,
+                                    p^.location.registerhigh,
+                                    p^.right^.location.registerhigh)));
+                                  swap_location(p^.location,p^.right^.location);
+                                  { newly swapped also set swapped flag }
+                                  { just to maintain ordering           }
+                                  p^.swaped:=not(p^.swaped);
                                end
                              else if cmpop then
                                begin
@@ -2029,7 +2053,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.59  1999-05-19 10:31:53  florian
+  Revision 1.60  1999-05-23 19:55:10  florian
+    * qword/int64 multiplication fixed
+    + qword/int64 subtraction
+
+  Revision 1.59  1999/05/19 10:31:53  florian
     * two bugs reported by Romio (bugs 13) are fixed:
         - empty array constructors are now handled correctly (e.g. for sysutils.format)
         - comparsion of ansistrings was sometimes coded wrong

+ 59 - 48
compiler/cg386inl.pas

@@ -92,53 +92,60 @@ implementation
             floatstore(PFloatDef(dest^.resulttype)^.typ,dest^.location.reference);
           orddef:
             begin
-              Case dest^.resulttype^.size of
-                1 : hreg:=regtoreg8(accumulator);
-                2 : hreg:=regtoreg16(accumulator);
-                4 : hreg:=accumulator;
-              End;
-              emit_mov_reg_loc(hreg,dest^.location);
-              If (cs_check_range in aktlocalswitches) and
-                 {no need to rangecheck longints or cardinals on 32bit processors}
-                  not((porddef(dest^.resulttype)^.typ = s32bit) and
-                      (porddef(dest^.resulttype)^.low = $80000000) and
-                      (porddef(dest^.resulttype)^.high = $7fffffff)) and
-                  not((porddef(dest^.resulttype)^.typ = u32bit) and
-                      (porddef(dest^.resulttype)^.low = 0) and
-                      (porddef(dest^.resulttype)^.high = $ffffffff)) then
-                Begin
-                  {do not register this temporary def}
-                  OldRegisterDef := RegisterDef;
-                  RegisterDef := False;
-                  hdef:=nil;
-                  Case PordDef(dest^.resulttype)^.typ of
-                    u8bit,u16bit,u32bit:
-                      begin
-                        new(hdef,init(u32bit,0,$ffffffff));
-                        hreg:=accumulator;
-                      end;
-                    s8bit,s16bit,s32bit:
-                      begin
-                        new(hdef,init(s32bit,$80000000,$7fffffff));
-                        hreg:=accumulator;
-                      end;
-                  end;
-                  { create a fake node }
-                  hp := genzeronode(nothingn);
-                  hp^.location.loc := LOC_REGISTER;
-                  hp^.location.register := hreg;
-                  if assigned(hdef) then
-                    hp^.resulttype:=hdef
-                  else
-                    hp^.resulttype:=dest^.resulttype;
-                  { emit the range check }
-                  emitrangecheck(hp,dest^.resulttype);
-                  hp^.right := nil;
-                  if assigned(hdef) then
-                    Dispose(hdef, Done);
-                  RegisterDef := OldRegisterDef;
-                  disposetree(hp);
-                End;
+              if porddef(dest^.resulttype)^.typ in [u64bit,s64bitint] then
+                begin
+                   emit_movq_reg_loc(R_EDX,R_EAX,dest^.location);
+                end
+              else
+                begin
+                   Case dest^.resulttype^.size of
+                     1 : hreg:=regtoreg8(accumulator);
+                     2 : hreg:=regtoreg16(accumulator);
+                     4 : hreg:=accumulator;
+                   End;
+                   emit_mov_reg_loc(hreg,dest^.location);
+                   If (cs_check_range in aktlocalswitches) and
+                      {no need to rangecheck longints or cardinals on 32bit processors}
+                       not((porddef(dest^.resulttype)^.typ = s32bit) and
+                           (porddef(dest^.resulttype)^.low = $80000000) and
+                           (porddef(dest^.resulttype)^.high = $7fffffff)) and
+                       not((porddef(dest^.resulttype)^.typ = u32bit) and
+                           (porddef(dest^.resulttype)^.low = 0) and
+                           (porddef(dest^.resulttype)^.high = $ffffffff)) then
+                     Begin
+                       {do not register this temporary def}
+                       OldRegisterDef := RegisterDef;
+                       RegisterDef := False;
+                       hdef:=nil;
+                       Case PordDef(dest^.resulttype)^.typ of
+                         u8bit,u16bit,u32bit:
+                           begin
+                             new(hdef,init(u32bit,0,$ffffffff));
+                             hreg:=accumulator;
+                           end;
+                         s8bit,s16bit,s32bit:
+                           begin
+                             new(hdef,init(s32bit,$80000000,$7fffffff));
+                             hreg:=accumulator;
+                           end;
+                       end;
+                       { create a fake node }
+                       hp := genzeronode(nothingn);
+                       hp^.location.loc := LOC_REGISTER;
+                       hp^.location.register := hreg;
+                       if assigned(hdef) then
+                         hp^.resulttype:=hdef
+                       else
+                         hp^.resulttype:=dest^.resulttype;
+                       { emit the range check }
+                       emitrangecheck(hp,dest^.resulttype);
+                       hp^.right := nil;
+                       if assigned(hdef) then
+                         Dispose(hdef, Done);
+                       RegisterDef := OldRegisterDef;
+                       disposetree(hp);
+                     End;
+                end;
             End;
           else
             internalerror(66766766);
@@ -1240,7 +1247,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.53  1999-05-23 18:42:01  florian
+  Revision 1.54  1999-05-23 19:55:11  florian
+    * qword/int64 multiplication fixed
+    + qword/int64 subtraction
+
+  Revision 1.53  1999/05/23 18:42:01  florian
     * better error recovering in typed constants
     * some problems with arrays of const fixed, some problems
       due my previous