Browse Source

* a_loadfpu_* gets two size parameters: fromsize and tosize
* fixed downsizing the precision of floating point values
* floating point constants are now treated using only the minimal
precision required (e.g. 2.0 is now a single, 1.1 extended etc)
(Delphi compatible)

git-svn-id: trunk@5927 -

Jonas Maebe 18 years ago
parent
commit
e815b923d5

+ 11 - 11
compiler/arm/cgcpu.pas

@@ -69,9 +69,9 @@ unit cgcpu;
         function a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
         function a_internal_load_ref_reg(list : TAsmList; fromsize, tosize : tcgsize;const Ref : treference;reg : tregister):treference;
 
 
         { fpu move instructions }
         { fpu move instructions }
-        procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); override;
-        procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister); override;
-        procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference); override;
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
 
 
         procedure a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
         procedure a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
         {  comparison operations }
         {  comparison operations }
@@ -231,7 +231,7 @@ unit cgcpu;
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
                 case location^.size of
                 case location^.size of
                    OS_F32, OS_F64:
                    OS_F32, OS_F64:
-                     a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
+                     a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
                    else
                    else
                      internalerror(2002072801);
                      internalerror(2002072801);
                 end;
                 end;
@@ -1009,7 +1009,7 @@ unit cgcpu;
           begin
           begin
             case hloc^.loc of
             case hloc^.loc of
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
-                a_loadfpu_ref_reg(list,size,ref,hloc^.register);
+                a_loadfpu_ref_reg(list,size,size,ref,hloc^.register);
               LOC_REGISTER :
               LOC_REGISTER :
                 case hloc^.size of
                 case hloc^.size of
                   OS_F32:
                   OS_F32:
@@ -1035,17 +1035,17 @@ unit cgcpu;
       end;
       end;
 
 
 
 
-     procedure tcgarm.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister);
+     procedure tcgarm.a_loadfpu_reg_reg(list: TAsmList; fromsize,tosize: tcgsize; reg1, reg2: tregister);
        begin
        begin
-         list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[size]));
+         list.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,reg2,reg1),cgsize2fpuoppostfix[tosize]));
        end;
        end;
 
 
 
 
-     procedure tcgarm.a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister);
+     procedure tcgarm.a_loadfpu_ref_reg(list: TAsmList; fromsize,tosize: tcgsize; const ref: treference; reg: tregister);
        var
        var
          oppostfix:toppostfix;
          oppostfix:toppostfix;
        begin
        begin
-         case size of
+         case tosize of
            OS_32,
            OS_32,
            OS_F32:
            OS_F32:
              oppostfix:=PF_S;
              oppostfix:=PF_S;
@@ -1061,11 +1061,11 @@ unit cgcpu;
        end;
        end;
 
 
 
 
-     procedure tcgarm.a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference);
+     procedure tcgarm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
        var
        var
          oppostfix:toppostfix;
          oppostfix:toppostfix;
        begin
        begin
-         case size of
+         case tosize of
            OS_F32:
            OS_F32:
              oppostfix:=PF_S;
              oppostfix:=PF_S;
            OS_F64:
            OS_F64:

+ 15 - 15
compiler/cgobj.pas

@@ -236,11 +236,11 @@ unit cgobj;
           procedure a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference); virtual;
           procedure a_load_subsetreg_subsetref(list: TAsmlist; fromsubsetsize, tosubsetsize : tcgsize; const fromsreg: tsubsetregister; const tosref: tsubsetreference); virtual;
 
 
           { fpu move instructions }
           { fpu move instructions }
-          procedure a_loadfpu_reg_reg(list: TAsmList; size:tcgsize; reg1, reg2: tregister); virtual; abstract;
-          procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister); virtual; abstract;
-          procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference); virtual; abstract;
-          procedure a_loadfpu_loc_reg(list: TAsmList; const loc: tlocation; const reg: tregister);
-          procedure a_loadfpu_reg_loc(list: TAsmList; size: tcgsize; const reg: tregister; const loc: tlocation);
+          procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize:tcgsize; reg1, reg2: tregister); virtual; abstract;
+          procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); virtual; abstract;
+          procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); virtual; abstract;
+          procedure a_loadfpu_loc_reg(list: TAsmList; tosize: tcgsize; const loc: tlocation; const reg: tregister);
+          procedure a_loadfpu_reg_loc(list: TAsmList; fromsize: tcgsize; const reg: tregister; const loc: tlocation);
           procedure a_paramfpu_reg(list : TAsmList;size : tcgsize;const r : tregister;const cgpara : TCGPara);virtual;
           procedure a_paramfpu_reg(list : TAsmList;size : tcgsize;const r : tregister;const cgpara : TCGPara);virtual;
           procedure a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
           procedure a_paramfpu_ref(list : TAsmList;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
 
 
@@ -1928,26 +1928,26 @@ implementation
       end;
       end;
 
 
 
 
-    procedure tcg.a_loadfpu_loc_reg(list: TAsmList; const loc: tlocation; const reg: tregister);
+    procedure tcg.a_loadfpu_loc_reg(list: TAsmList; tosize: tcgsize; const loc: tlocation; const reg: tregister);
       begin
       begin
         case loc.loc of
         case loc.loc of
           LOC_REFERENCE, LOC_CREFERENCE:
           LOC_REFERENCE, LOC_CREFERENCE:
-            a_loadfpu_ref_reg(list,loc.size,loc.reference,reg);
+            a_loadfpu_ref_reg(list,loc.size,tosize,loc.reference,reg);
           LOC_FPUREGISTER, LOC_CFPUREGISTER:
           LOC_FPUREGISTER, LOC_CFPUREGISTER:
-            a_loadfpu_reg_reg(list,loc.size,loc.register,reg);
+            a_loadfpu_reg_reg(list,loc.size,tosize,loc.register,reg);
           else
           else
             internalerror(200203301);
             internalerror(200203301);
         end;
         end;
       end;
       end;
 
 
 
 
-    procedure tcg.a_loadfpu_reg_loc(list: TAsmList; size: tcgsize; const reg: tregister; const loc: tlocation);
+    procedure tcg.a_loadfpu_reg_loc(list: TAsmList; fromsize: tcgsize; const reg: tregister; const loc: tlocation);
       begin
       begin
         case loc.loc of
         case loc.loc of
           LOC_REFERENCE, LOC_CREFERENCE:
           LOC_REFERENCE, LOC_CREFERENCE:
-            a_loadfpu_reg_ref(list,size,reg,loc.reference);
+            a_loadfpu_reg_ref(list,fromsize,loc.size,reg,loc.reference);
           LOC_FPUREGISTER, LOC_CFPUREGISTER:
           LOC_FPUREGISTER, LOC_CFPUREGISTER:
-            a_loadfpu_reg_reg(list,size,reg,loc.register);
+            a_loadfpu_reg_reg(list,fromsize,loc.size,reg,loc.register);
           else
           else
             internalerror(48991);
             internalerror(48991);
          end;
          end;
@@ -1962,19 +1962,19 @@ implementation
             LOC_FPUREGISTER,LOC_CFPUREGISTER:
             LOC_FPUREGISTER,LOC_CFPUREGISTER:
               begin
               begin
                 cgpara.check_simple_location;
                 cgpara.check_simple_location;
-                a_loadfpu_reg_reg(list,size,r,cgpara.location^.register);
+                a_loadfpu_reg_reg(list,size,size,r,cgpara.location^.register);
               end;
               end;
             LOC_REFERENCE,LOC_CREFERENCE:
             LOC_REFERENCE,LOC_CREFERENCE:
               begin
               begin
                 cgpara.check_simple_location;
                 cgpara.check_simple_location;
                 reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
                 reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
-                a_loadfpu_reg_ref(list,size,r,ref);
+                a_loadfpu_reg_ref(list,size,size,r,ref);
               end;
               end;
             LOC_REGISTER,LOC_CREGISTER:
             LOC_REGISTER,LOC_CREGISTER:
               begin
               begin
                 { paramfpu_ref does the check_simpe_location check here if necessary }
                 { paramfpu_ref does the check_simpe_location check here if necessary }
                 tg.GetTemp(list,TCGSize2Size[size],tt_normal,ref);
                 tg.GetTemp(list,TCGSize2Size[size],tt_normal,ref);
-                a_loadfpu_reg_ref(list,size,r,ref);
+                a_loadfpu_reg_ref(list,size,size,r,ref);
                 a_paramfpu_ref(list,size,ref,cgpara);
                 a_paramfpu_ref(list,size,ref,cgpara);
                 tg.Ungettemp(list,ref);
                 tg.Ungettemp(list,ref);
               end;
               end;
@@ -1991,7 +1991,7 @@ implementation
          cgpara.check_simple_location;
          cgpara.check_simple_location;
          case cgpara.location^.loc of
          case cgpara.location^.loc of
           LOC_FPUREGISTER,LOC_CFPUREGISTER:
           LOC_FPUREGISTER,LOC_CFPUREGISTER:
-            a_loadfpu_ref_reg(list,size,ref,cgpara.location^.register);
+            a_loadfpu_ref_reg(list,size,size,ref,cgpara.location^.register);
           LOC_REFERENCE,LOC_CREFERENCE:
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
             begin
               reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);
               reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);

+ 15 - 10
compiler/m68k/cgcpu.pas

@@ -56,9 +56,9 @@ unit cgcpu;
         procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
         procedure a_load_ref_ref(list : TAsmList;fromsize,tosize : tcgsize;const sref : treference;const dref : treference);override;
 
 
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
-        procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); override;
-        procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister); override;
-        procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference); override;
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
 
 
         procedure a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle); override;
         procedure a_loadmm_reg_reg(list: TAsmList;fromsize,tosize : tcgsize; reg1, reg2: tregister;shuffle : pmmshuffle); override;
         procedure a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
         procedure a_loadmm_ref_reg(list: TAsmList;fromsize,tosize : tcgsize; const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
@@ -550,22 +550,23 @@ unit cgcpu;
       end;
       end;
 
 
 
 
-    procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister);
+    procedure tcg68k.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
       begin
       begin
         { in emulation mode, only 32-bit single is supported }
         { in emulation mode, only 32-bit single is supported }
         if cs_fp_emulation in current_settings.moduleswitches then
         if cs_fp_emulation in current_settings.moduleswitches then
           list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
           list.concat(taicpu.op_reg_reg(A_MOVE,S_L,reg1,reg2))
         else
         else
-          list.concat(taicpu.op_reg_reg(A_FMOVE,S_FD,reg1,reg2));
+          list.concat(taicpu.op_reg_reg(A_FMOVE,tcgsize2opsize[tosize],reg1,reg2));
       end;
       end;
 
 
 
 
-    procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister);
+    procedure tcg68k.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
      var
      var
       opsize : topsize;
       opsize : topsize;
       href : treference;
       href : treference;
+      tmpreg : tregister;
       begin
       begin
-        opsize := tcgsize2opsize[size];
+        opsize := tcgsize2opsize[fromsize];
         { extended is not supported, since it is not available on Coldfire }
         { extended is not supported, since it is not available on Coldfire }
         if opsize = S_FX then
         if opsize = S_FX then
           internalerror(20020729);
           internalerror(20020729);
@@ -575,14 +576,18 @@ unit cgcpu;
         if cs_fp_emulation in current_settings.moduleswitches then
         if cs_fp_emulation in current_settings.moduleswitches then
            list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
            list.concat(taicpu.op_ref_reg(A_MOVE,S_L,href,reg))
         else
         else
-           list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
+           begin
+             list.concat(taicpu.op_ref_reg(A_FMOVE,opsize,href,reg));
+             if (tosize < fromsize) then
+               a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+           end;
       end;
       end;
 
 
-    procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference);
+    procedure tcg68k.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
       var
       var
        opsize : topsize;
        opsize : topsize;
       begin
       begin
-        opsize := tcgsize2opsize[size];
+        opsize := tcgsize2opsize[tosize];
         { extended is not supported, since it is not available on Coldfire }
         { extended is not supported, since it is not available on Coldfire }
         if opsize = S_FX then
         if opsize = S_FX then
           internalerror(20020729);
           internalerror(20020729);

+ 1 - 1
compiler/ncgadd.pas

@@ -137,7 +137,7 @@ interface
         if pushedfpu then
         if pushedfpu then
           begin
           begin
             tmpreg := cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
             tmpreg := cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
-            cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location,tmpreg);
+            cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location,tmpreg);
             location_reset(left.location,LOC_FPUREGISTER,left.location.size);
             location_reset(left.location,LOC_FPUREGISTER,left.location.size);
             left.location.register := tmpreg;
             left.location.register := tmpreg;
 {$ifdef x86}
 {$ifdef x86}

+ 4 - 4
compiler/ncgcal.pas

@@ -152,7 +152,7 @@ implementation
                    end
                    end
                  else
                  else
                    reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
                    reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
-                 cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,left.location.size,left.location.register,href);
+                 cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,left.location.size,left.location.size,left.location.register,href);
                end;
                end;
              LOC_MMREGISTER,
              LOC_MMREGISTER,
              LOC_CMMREGISTER:
              LOC_CMMREGISTER:
@@ -574,7 +574,7 @@ implementation
                        if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
                        if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
                          cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
                          cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
                        hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
                        hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
-                       cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.register,hregister);
+                       cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
                        location.register:=hregister;
                        location.register:=hregister;
 {$endif x86}
 {$endif x86}
                      end;
                      end;
@@ -745,7 +745,7 @@ implementation
                              internalerror(200408222);
                              internalerror(200408222);
                            if getsupreg(callerparaloc^.register)<first_fpu_imreg then
                            if getsupreg(callerparaloc^.register)<first_fpu_imreg then
                              cg.getcpuregister(current_asmdata.CurrAsmList,callerparaloc^.register);
                              cg.getcpuregister(current_asmdata.CurrAsmList,callerparaloc^.register);
-                           cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,ppn.tempcgpara.size,tmpparaloc^.register,callerparaloc^.register);
+                           cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,tmpparaloc^.size,ppn.tempcgpara.size,tmpparaloc^.register,callerparaloc^.register);
                          end;
                          end;
                        LOC_MMREGISTER:
                        LOC_MMREGISTER:
                          begin
                          begin
@@ -783,7 +783,7 @@ implementation
                                 LOC_REGISTER:
                                 LOC_REGISTER:
                                   cg.a_load_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
                                   cg.a_load_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
                                 LOC_FPUREGISTER:
                                 LOC_FPUREGISTER:
-                                  cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.register,href);
+                                  cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href);
                                 LOC_MMREGISTER:
                                 LOC_MMREGISTER:
                                   cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
                                   cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,tmpparaloc^.size,tmpparaloc^.size,tmpparaloc^.register,href,mms_movescalar);
                                 else
                                 else

+ 8 - 2
compiler/ncgcnv.pas

@@ -290,7 +290,13 @@ interface
                 location.size:=def_cgsize(resultdef);
                 location.size:=def_cgsize(resultdef);
                 case expectloc of
                 case expectloc of
                   LOC_FPUREGISTER:
                   LOC_FPUREGISTER:
-                    ;
+                    begin
+                      { on sparc a move from double -> single means from two to one register. }
+                      { On all other platforms it also needs rounding to avoid that           }
+                      { single(double_regvar) = double_regvar is true in all cases            }
+                      location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+                      cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
+                    end;
                   LOC_MMREGISTER:
                   LOC_MMREGISTER:
                     location_force_mmregscalar(current_asmdata.CurrAsmList,location,false);
                     location_force_mmregscalar(current_asmdata.CurrAsmList,location,false);
                   else
                   else
@@ -310,7 +316,7 @@ interface
                   else
                   else
                     begin
                     begin
                       location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
                       location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
-                      cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location,location.register);
+                      cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,location.size,left.location,location.register);
                     end;
                     end;
                  location_freetemp(current_asmdata.CurrAsmList,left.location);
                  location_freetemp(current_asmdata.CurrAsmList,left.location);
               end;
               end;

+ 4 - 16
compiler/ncgld.pas

@@ -362,7 +362,6 @@ implementation
     procedure tcgassignmentnode.pass_generate_code;
     procedure tcgassignmentnode.pass_generate_code;
       var
       var
          otlabel,hlabel,oflabel : tasmlabel;
          otlabel,hlabel,oflabel : tasmlabel;
-         fputyp : tfloattype;
          href : treference;
          href : treference;
          releaseright : boolean;
          releaseright : boolean;
          len : aint;
          len : aint;
@@ -560,7 +559,7 @@ implementation
                     LOC_CFPUREGISTER :
                     LOC_CFPUREGISTER :
                       begin
                       begin
                         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
                         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-                            right.location.size,
+                            right.location.size,left.location.size,
                             right.location.reference,
                             right.location.reference,
                             left.location.register);
                             left.location.register);
                       end;
                       end;
@@ -637,28 +636,17 @@ implementation
               LOC_FPUREGISTER,
               LOC_FPUREGISTER,
               LOC_CFPUREGISTER :
               LOC_CFPUREGISTER :
                 begin
                 begin
-                  if (left.resultdef.typ=floatdef) then
-                   fputyp:=tfloatdef(left.resultdef).floattype
-                  else
-                   if (right.resultdef.typ=floatdef) then
-                    fputyp:=tfloatdef(right.resultdef).floattype
-                  else
-                   if (right.nodetype=typeconvn) and
-                      (ttypeconvnode(right).left.resultdef.typ=floatdef) then
-                    fputyp:=tfloatdef(ttypeconvnode(right).left.resultdef).floattype
-                  else
-                    fputyp:=s32real;
                   { we can't do direct moves between fpu and mm registers }
                   { we can't do direct moves between fpu and mm registers }
                   if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
                   if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
                     begin
                     begin
                       location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
                       location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
                       cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
                       cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
-                          tfloat2tcgsize[fputyp],tfloat2tcgsize[fputyp],
+                          right.location.size,left.location.size,
                           right.location.register,left.location.register,mms_movescalar);
                           right.location.register,left.location.register,mms_movescalar);
                     end
                     end
                   else
                   else
                     cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
                     cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
-                        tfloat2tcgsize[fputyp],
+                        right.location.size,
                         right.location.register,left.location);
                         right.location.register,left.location);
                 end;
                 end;
               LOC_SUBSETREG,
               LOC_SUBSETREG,
@@ -915,7 +903,7 @@ implementation
                        hp.left.location.register,href,mms_movescalar);
                        hp.left.location.register,href,mms_movescalar);
                    LOC_FPUREGISTER,
                    LOC_FPUREGISTER,
                    LOC_CFPUREGISTER :
                    LOC_CFPUREGISTER :
-                     cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.register,href);
+                     cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
                    LOC_REFERENCE,
                    LOC_REFERENCE,
                    LOC_CREFERENCE :
                    LOC_CREFERENCE :
                      begin
                      begin

+ 4 - 4
compiler/ncgmat.pas

@@ -151,7 +151,7 @@ implementation
         }
         }
         tg.gettemp(current_asmdata.CurrAsmList,tcgsize2size[_size],tt_normal,href);
         tg.gettemp(current_asmdata.CurrAsmList,tcgsize2size[_size],tt_normal,href);
         { store the floating point value in the temporary memory area }
         { store the floating point value in the temporary memory area }
-        cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,_size,r,href);
+        cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,_size,_size,r,href);
         { only single and double ieee are supported, for little endian
         { only single and double ieee are supported, for little endian
           the signed bit is in the second dword }
           the signed bit is in the second dword }
         href2:=href;
         href2:=href;
@@ -166,7 +166,7 @@ implementation
         end;
         end;
         { flip sign-bit (bit 31/63) of single/double }
         { flip sign-bit (bit 31/63) of single/double }
         cg.a_op_const_ref(current_asmdata.CurrAsmList,OP_XOR,OS_32,aint($80000000),href2);
         cg.a_op_const_ref(current_asmdata.CurrAsmList,OP_XOR,OS_32,aint($80000000),href2);
-        cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,_size,href,r);
+        cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,_size,_size,href,r);
         tg.ungetiftemp(current_asmdata.CurrAsmList,href);
         tg.ungetiftemp(current_asmdata.CurrAsmList,href);
       end;
       end;
 
 
@@ -193,7 +193,7 @@ implementation
             begin
             begin
               location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
               location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
               cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
               cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-                 def_cgsize(left.resultdef),
+                 left.location.size,location.size,
                  left.location.reference,location.register);
                  left.location.reference,location.register);
               emit_float_sign_change(location.register,def_cgsize(left.resultdef));
               emit_float_sign_change(location.register,def_cgsize(left.resultdef));
             end;
             end;
@@ -205,7 +205,7 @@ implementation
           LOC_CFPUREGISTER:
           LOC_CFPUREGISTER:
             begin
             begin
                location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
                location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
-               cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,left.location.register,location.register);
+               cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,location.register);
                emit_float_sign_change(location.register,def_cgsize(left.resultdef));
                emit_float_sign_change(location.register,def_cgsize(left.resultdef));
             end;
             end;
           else
           else

+ 9 - 9
compiler/ncgutil.pas

@@ -691,7 +691,7 @@ implementation
                 l.reference:=href;
                 l.reference:=href;
               end;
               end;
             reg:=cg.getfpuregister(list,l.size);
             reg:=cg.getfpuregister(list,l.size);
-            cg.a_loadfpu_loc_reg(list,l,reg);
+            cg.a_loadfpu_loc_reg(list,l.size,l,reg);
             location_freetemp(list,l);
             location_freetemp(list,l);
             location_reset(l,LOC_FPUREGISTER,l.size);
             location_reset(l,LOC_FPUREGISTER,l.size);
             l.register:=reg;
             l.register:=reg;
@@ -711,7 +711,7 @@ implementation
             if (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
             if (l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
               begin
               begin
                 tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
                 tg.GetTemp(list,tcgsize2size[l.size],tt_normal,href);
-                cg.a_loadfpu_reg_ref(list,l.size,l.register,href);
+                cg.a_loadfpu_reg_ref(list,l.size,l.size,l.register,href);
                 location_reset(l,LOC_REFERENCE,l.size);
                 location_reset(l,LOC_REFERENCE,l.size);
                 l.reference:=href;
                 l.reference:=href;
               end;
               end;
@@ -749,7 +749,7 @@ implementation
           LOC_CFPUREGISTER :
           LOC_CFPUREGISTER :
             begin
             begin
               tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
               tg.GetTemp(list,TCGSize2Size[l.size],tt_normal,r);
-              cg.a_loadfpu_reg_ref(list,l.size,l.register,r);
+              cg.a_loadfpu_reg_ref(list,l.size,l.size,l.register,r);
               location_reset(l,LOC_REFERENCE,l.size);
               location_reset(l,LOC_REFERENCE,l.size);
               l.reference:=r;
               l.reference:=r;
             end;
             end;
@@ -1393,7 +1393,7 @@ implementation
                   { we can't do direct moves between fpu and mm registers }
                   { we can't do direct moves between fpu and mm registers }
                   if restmploc.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
                   if restmploc.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
                     location_force_fpureg(list,restmploc,false);
                     location_force_fpureg(list,restmploc,false);
-                  cg.a_loadfpu_loc_reg(list,restmploc,funcretloc.register);
+                  cg.a_loadfpu_loc_reg(list,reg_cgsize(funcretloc.register),restmploc,funcretloc.register);
                 end;
                 end;
               LOC_MMREGISTER:
               LOC_MMREGISTER:
                 begin
                 begin
@@ -1526,7 +1526,7 @@ implementation
               LOC_MMREGISTER :
               LOC_MMREGISTER :
                 cg.a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
                 cg.a_loadmm_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref,mms_movescalar);
               LOC_FPUREGISTER :
               LOC_FPUREGISTER :
-                cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.register,ref);
+                cg.a_loadfpu_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
               LOC_REFERENCE :
               LOC_REFERENCE :
                 begin
                 begin
                   reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
                   reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
@@ -1551,7 +1551,7 @@ implementation
               LOC_MMREGISTER :
               LOC_MMREGISTER :
                 cg.a_loadmm_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg,mms_movescalar);
                 cg.a_loadmm_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg,mms_movescalar);
               LOC_FPUREGISTER :
               LOC_FPUREGISTER :
-                cg.a_loadfpu_reg_reg(list,paraloc.size,paraloc.register,reg);
+                cg.a_loadfpu_reg_reg(list,paraloc.size,paraloc.size,paraloc.register,reg);
               LOC_REFERENCE :
               LOC_REFERENCE :
                 begin
                 begin
                   reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
                   reference_reset_base(href,paraloc.reference.index,paraloc.reference.offset);
@@ -1559,7 +1559,7 @@ implementation
                     R_INTREGISTER :
                     R_INTREGISTER :
                       cg.a_load_ref_reg(list,paraloc.size,paraloc.size,href,reg);
                       cg.a_load_ref_reg(list,paraloc.size,paraloc.size,href,reg);
                     R_FPUREGISTER :
                     R_FPUREGISTER :
-                      cg.a_loadfpu_ref_reg(list,paraloc.size,href,reg);
+                      cg.a_loadfpu_ref_reg(list,paraloc.size,paraloc.size,href,reg);
                     R_MMREGISTER :
                     R_MMREGISTER :
                       cg.a_loadmm_ref_reg(list,paraloc.size,paraloc.size,href,reg,mms_movescalar);
                       cg.a_loadmm_ref_reg(list,paraloc.size,paraloc.size,href,reg,mms_movescalar);
                     else
                     else
@@ -1710,7 +1710,7 @@ implementation
                       paraloc:=paraloc^.next;
                       paraloc:=paraloc^.next;
                     end;
                     end;
                   gen_alloc_regvar(list,currpara);
                   gen_alloc_regvar(list,currpara);
-                  cg.a_loadfpu_ref_reg(list,currpara.initialloc.size,tempref,currpara.initialloc.register);
+                  cg.a_loadfpu_ref_reg(list,currpara.initialloc.size,currpara.initialloc.size,tempref,currpara.initialloc.register);
                   tg.UnGetTemp(list,tempref);
                   tg.UnGetTemp(list,tempref);
 {$else sparc}
 {$else sparc}
                   unget_para(paraloc^);
                   unget_para(paraloc^);
@@ -2533,7 +2533,7 @@ implementation
                   cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
                   cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
               end;
               end;
             LOC_CFPUREGISTER:
             LOC_CFPUREGISTER:
-              cg.a_loadfpu_reg_reg(list,n.location.size,n.location.register,rr.new);
+              cg.a_loadfpu_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
       {$ifdef SUPPORT_MMX}
       {$ifdef SUPPORT_MMX}
             LOC_CMMXREGISTER:
             LOC_CMMXREGISTER:
               cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
               cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);

+ 1 - 0
compiler/options.pas

@@ -1915,6 +1915,7 @@ begin
   def_system_macro('FPC_HAS_VARSETS');
   def_system_macro('FPC_HAS_VARSETS');
   def_system_macro('FPC_HAS_VALGRINDBOOL');
   def_system_macro('FPC_HAS_VALGRINDBOOL');
   def_system_macro('FPC_HAS_STR_CURRENCY');
   def_system_macro('FPC_HAS_STR_CURRENCY');
+  def_system_macro('FPC_REAL2REAL_FIXED');
 {$ifdef x86}
 {$ifdef x86}
   def_system_macro('INTERNAL_BACKTRACE');
   def_system_macro('INTERNAL_BACKTRACE');
 {$endif}
 {$endif}

+ 8 - 1
compiler/pexpr.pas

@@ -2438,7 +2438,14 @@ implementation
                   d:=1.0;
                   d:=1.0;
                 end;
                 end;
                consume(_REALNUMBER);
                consume(_REALNUMBER);
-               p1:=crealconstnode.create(d,pbestrealtype^);
+{$ifdef FPC_REAL2REAL_FIXED}
+               if (d = single(d)) then
+                 p1:=crealconstnode.create(d,s32floattype)
+               else if (d = double(d)) then
+                 p1:=crealconstnode.create(d,s64floattype)
+               else
+{$endif FPC_REAL2REAL_FIXED}
+                 p1:=crealconstnode.create(d,pbestrealtype^);
              end;
              end;
 
 
            _STRING :
            _STRING :

+ 7 - 73
compiler/powerpc/cgcpu.pas

@@ -65,11 +65,6 @@ unit cgcpu;
           tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
           tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
        procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tcgsize; const fromsreg, tosreg: tsubsetregister); override;
        procedure a_load_subsetreg_subsetreg(list: TAsmlist; fromsubsetsize, tosubsetsize: tcgsize; const fromsreg, tosreg: tsubsetregister); override;
 
 
-        { fpu move instructions }
-        procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); override;
-        procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister); override;
-        procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference); override;
-
         {  comparison operations }
         {  comparison operations }
         procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
         procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : aint;reg : tregister;
           l : tasmlabel);override;
           l : tasmlabel);override;
@@ -261,7 +256,7 @@ const
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
               LOC_FPUREGISTER,LOC_CFPUREGISTER:
                 case location^.size of
                 case location^.size of
                    OS_F32, OS_F64:
                    OS_F32, OS_F64:
-                     a_loadfpu_ref_reg(list,location^.size,tmpref,location^.register);
+                     a_loadfpu_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
                    else
                    else
                      internalerror(2002072801);
                      internalerror(2002072801);
                 end;
                 end;
@@ -469,67 +464,6 @@ const
          end;
          end;
 
 
 
 
-     procedure tcgppc.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister);
-
-       var
-         instr: taicpu;
-       begin
-         instr :=  taicpu.op_reg_reg(A_FMR,reg2,reg1);
-         list.concat(instr);
-         rg[R_FPUREGISTER].add_move_instruction(instr);
-       end;
-
-
-     procedure tcgppc.a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister);
-
-       const
-         FpuLoadInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
-                          { indexed? updating?}
-                    (((A_LFS,A_LFSU),(A_LFSX,A_LFSUX)),
-                     ((A_LFD,A_LFDU),(A_LFDX,A_LFDUX)));
-       var
-         op: tasmop;
-         ref2: treference;
-
-       begin
-          { several functions call this procedure with OS_32 or OS_64 }
-          { so this makes life easier (FK)                            }
-          case size of
-             OS_32,OS_F32:
-               size:=OS_F32;
-             OS_64,OS_F64,OS_C64:
-               size:=OS_F64;
-             else
-               internalerror(200201121);
-          end;
-         ref2 := ref;
-         fixref(list,ref2);
-         op := fpuloadinstr[size,ref2.index <> NR_NO,false];
-         a_load_store(list,op,reg,ref2);
-       end;
-
-
-     procedure tcgppc.a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference);
-
-       const
-         FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
-                            { indexed? updating?}
-                    (((A_STFS,A_STFSU),(A_STFSX,A_STFSUX)),
-                     ((A_STFD,A_STFDU),(A_STFDX,A_STFDUX)));
-       var
-         op: tasmop;
-         ref2: treference;
-
-       begin
-         if not(size in [OS_F32,OS_F64]) then
-           internalerror(200201122);
-         ref2 := ref;
-         fixref(list,ref2);
-         op := fpustoreinstr[size,ref2.index <> NR_NO,false];
-         a_load_store(list,op,reg,ref2);
-       end;
-
-
      procedure tcgppc.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
      procedure tcgppc.a_op_const_reg(list : TAsmList; Op: TOpCG; size: TCGSize; a: aint; reg: TRegister);
 
 
        begin
        begin
@@ -1064,7 +998,7 @@ const
              reference_reset_base(href,NR_R1,-8);
              reference_reset_base(href,NR_R1,-8);
              for regcounter:=firstregfpu to RS_F31 do
              for regcounter:=firstregfpu to RS_F31 do
                begin
                begin
-                 a_loadfpu_reg_ref(list,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
+                 a_loadfpu_reg_ref(list,OS_F64,OS_F64,newreg(R_FPUREGISTER,regcounter,R_SUBNONE),href);
                  dec(href.offset,8);
                  dec(href.offset,8);
                end;
                end;
              { compute start of gpr save area }
              { compute start of gpr save area }
@@ -1209,7 +1143,7 @@ const
             reference_reset_base(href,NR_R1,-8);
             reference_reset_base(href,NR_R1,-8);
             for regcounter := firstregfpu to RS_F31 do
             for regcounter := firstregfpu to RS_F31 do
               begin
               begin
-                a_loadfpu_ref_reg(list,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
+                a_loadfpu_ref_reg(list,OS_F64,OS_F64,href,newreg(R_FPUREGISTER,regcounter,R_SUBNONE));
                 dec(href.offset,8);
                 dec(href.offset,8);
               end;
               end;
             inc(href.offset,4);
             inc(href.offset,4);
@@ -1707,8 +1641,8 @@ const
             else
             else
               begin
               begin
                 copyreg := getfpuregister(list,OS_F64);
                 copyreg := getfpuregister(list,OS_F64);
-                a_loadfpu_ref_reg(list,OS_F64,source,copyreg);
-                a_loadfpu_reg_ref(list,OS_F64,copyreg,dest);
+                a_loadfpu_ref_reg(list,OS_F64,OS_F64,source,copyreg);
+                a_loadfpu_reg_ref(list,OS_F64,OS_F64,copyreg,dest);
               end;
               end;
             exit;
             exit;
           end;
           end;
@@ -1777,8 +1711,8 @@ const
             copyreg := getfpuregister(list,OS_F64);
             copyreg := getfpuregister(list,OS_F64);
             for count2 := 1 to count do
             for count2 := 1 to count do
               begin
               begin
-                a_loadfpu_ref_reg(list,OS_F64,src,copyreg);
-                a_loadfpu_reg_ref(list,OS_F64,copyreg,dst);
+                a_loadfpu_ref_reg(list,OS_F64,OS_F64,src,copyreg);
+                a_loadfpu_reg_ref(list,OS_F64,OS_F64,copyreg,dst);
                 inc(src.offset,8);
                 inc(src.offset,8);
                 inc(dst.offset,8);
                 inc(dst.offset,8);
               end;
               end;

+ 10 - 2
compiler/powerpc/cpupara.pas

@@ -503,7 +503,15 @@ unit cpupara;
                   else { LOC_REFERENCE }
                   else { LOC_REFERENCE }
                     begin
                     begin
                        paraloc^.loc:=LOC_REFERENCE;
                        paraloc^.loc:=LOC_REFERENCE;
-                       paraloc^.size:=int_cgsize(paralen);
+                       case loc of
+                         LOC_FPUREGISTER:
+                           paraloc^.size:=int_float_cgsize(paralen);
+                         LOC_REGISTER,
+                         LOC_REFERENCE:
+                           paraloc^.size:=int_cgsize(paralen);
+                         else
+                           internalerror(2006011101);
+                       end;
                        if (side = callerside) then
                        if (side = callerside) then
                          paraloc^.reference.index:=NR_STACK_POINTER_REG
                          paraloc^.reference.index:=NR_STACK_POINTER_REG
                        else
                        else
@@ -511,7 +519,7 @@ unit cpupara;
                            paraloc^.reference.index:=NR_R12;
                            paraloc^.reference.index:=NR_R12;
                            tppcprocinfo(current_procinfo).needs_frame_pointer := true;
                            tppcprocinfo(current_procinfo).needs_frame_pointer := true;
                          end;
                          end;
-                       
+
                        if (target_info.abi = abi_powerpc_aix) and
                        if (target_info.abi = abi_powerpc_aix) and
                           (hp.paraloc[side].intsize < 3) then
                           (hp.paraloc[side].intsize < 3) then
                            paraloc^.reference.offset:=stack_offset+(4-paralen)
                            paraloc^.reference.offset:=stack_offset+(4-paralen)

+ 5 - 18
compiler/powerpc/nppccnv.pas

@@ -41,7 +41,7 @@ interface
          { procedure second_chararray_to_string;override; }
          { procedure second_chararray_to_string;override; }
          { procedure second_char_to_string;override; }
          { procedure second_char_to_string;override; }
           procedure second_int_to_real;override;
           procedure second_int_to_real;override;
-          procedure second_real_to_real;override;
+         { procedure second_real_to_real;override; }
          { procedure second_cord_to_pointer;override; }
          { procedure second_cord_to_pointer;override; }
          { procedure second_proc_to_procvar;override; }
          { procedure second_proc_to_procvar;override; }
          { procedure second_bool_to_int;override; }
          { procedure second_bool_to_int;override; }
@@ -210,37 +210,24 @@ implementation
          dec(ref.offset,4);
          dec(ref.offset,4);
 
 
          tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
          tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,tempconst.location.reference,
+         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,tempconst.location.reference,
            tmpfpureg);
            tmpfpureg);
          tempconst.free;
          tempconst.free;
 
 
          location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
          location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,ref,location.register);
+         cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,ref,location.register);
 
 
          tg.ungetiftemp(current_asmdata.CurrAsmList,ref);
          tg.ungetiftemp(current_asmdata.CurrAsmList,ref);
 
 
          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FSUB,location.register,
          current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FSUB,location.register,
            location.register,tmpfpureg));
            location.register,tmpfpureg));
 
 
-         { work around bug in some PowerPC processors }
-         if (tfloatdef(resultdef).floattype = s32real) then
+        { make sure the precision is correct }
+        if (tfloatdef(resultdef).floattype = s32real) then
            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
              location.register));
              location.register));
        end;
        end;
 
 
-
-     procedure tppctypeconvnode.second_real_to_real;
-       begin
-          inherited second_real_to_real;
-          { work around bug in some powerpc processors where doubles aren't }
-          { properly converted to singles                                   }
-          if (tfloatdef(left.resultdef).floattype = s64real) and
-             (tfloatdef(resultdef).floattype = s32real) then
-            current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
-              location.register));
-       end;
-
-
 begin
 begin
    ctypeconvnode:=tppctypeconvnode;
    ctypeconvnode:=tppctypeconvnode;
 end.
 end.

+ 1 - 1
compiler/powerpc/nppcmat.pas

@@ -599,7 +599,7 @@ end;
                           src1 := cg.getfpuregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
                           src1 := cg.getfpuregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
                           location.register := src1;
                           location.register := src1;
                           cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
                           cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-                            def_cgsize(left.resultdef),
+                            left.location.size,left.location.size,
                             left.location.reference,src1);
                             left.location.reference,src1);
                        end
                        end
                      else
                      else

+ 8 - 73
compiler/powerpc64/cgcpu.pas

@@ -70,15 +70,6 @@ type
     procedure a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
     procedure a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister); override;
     procedure a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize; a: aint; const sreg: tsubsetregister); override;
     procedure a_load_const_subsetreg(list: TAsmlist; subsetsize: tcgsize; a: aint; const sreg: tsubsetregister); override;
 
 
-    { fpu move instructions }
-    procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2:
-      tregister); override;
-
-    procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref:
-      treference; reg: tregister); override;
-    procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg:
-      tregister; const ref: treference); override;
-
     {  comparison operations }
     {  comparison operations }
     procedure a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op:
     procedure a_cmp_const_reg_label(list: TAsmList; size: tcgsize; cmp_op:
       topcmp; a: aint; reg: tregister;
       topcmp; a: aint; reg: tregister;
@@ -538,7 +529,7 @@ begin
       LOC_FPUREGISTER, LOC_CFPUREGISTER:
       LOC_FPUREGISTER, LOC_CFPUREGISTER:
         case location^.size of
         case location^.size of
           OS_F32, OS_F64:
           OS_F32, OS_F64:
-            a_loadfpu_ref_reg(list, location^.size, tmpref, location^.register);
+            a_loadfpu_ref_reg(list, location^.size, location^.size, tmpref, location^.register);
         else
         else
           internalerror(2002072801);
           internalerror(2002072801);
         end;
         end;
@@ -871,64 +862,6 @@ begin
   a_load_reg_subsetreg(list, subsetsize, subsetsize, tmpreg, sreg);
   a_load_reg_subsetreg(list, subsetsize, subsetsize, tmpreg, sreg);
 end;
 end;
 
 
-procedure tcgppc.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize;
-  reg1, reg2: tregister);
-var
-  instr: taicpu;
-begin
-  instr := taicpu.op_reg_reg(A_FMR, reg2, reg1);
-  list.concat(instr);
-  rg[R_FPUREGISTER].add_move_instruction(instr);
-end;
-
-procedure tcgppc.a_loadfpu_ref_reg(list: TAsmList; size: tcgsize;
-  const ref: treference; reg: tregister);
-const
-  FpuLoadInstr: array[OS_F32..OS_F64, boolean, boolean] of TAsmOp =
-  { indexed? updating?}
-  (((A_LFS, A_LFSU), (A_LFSX, A_LFSUX)),
-   ((A_LFD, A_LFDU), (A_LFDX, A_LFDUX)));
-var
-  op: tasmop;
-  ref2: treference;
-
-begin
-  { several functions call this procedure with OS_32 or OS_64
-   so this makes life easier (FK) }
-  case size of
-    OS_32, OS_F32:
-      size := OS_F32;
-    OS_64, OS_F64, OS_C64:
-      size := OS_F64;
-  else
-    internalerror(200201121);
-  end;
-  ref2 := ref;
-  fixref(list, ref2);
-  op := fpuloadinstr[size, ref2.index <> NR_NO, false];
-  a_load_store(list, op, reg, ref2);
-end;
-
-procedure tcgppc.a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg:
-  tregister; const ref: treference);
-const
-  FpuStoreInstr: array[OS_F32..OS_F64, boolean, boolean] of TAsmOp =
-  { indexed? updating? }
-  (((A_STFS, A_STFSU), (A_STFSX, A_STFSUX)),
-   ((A_STFD, A_STFDU), (A_STFDX, A_STFDUX)));
-var
-  op: tasmop;
-  ref2: treference;
-
-begin
-  if not (size in [OS_F32, OS_F64]) then
-    internalerror(200201122);
-  ref2 := ref;
-  fixref(list, ref2);
-  op := fpustoreinstr[size, ref2.index <> NR_NO, false];
-  a_load_store(list, op, reg, ref2);
-end;
-
 procedure tcgppc.a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize; a:
 procedure tcgppc.a_op_const_reg(list: TAsmList; Op: TOpCG; size: TCGSize; a:
   aint; reg: TRegister);
   aint; reg: TRegister);
 begin
 begin
@@ -1392,6 +1325,7 @@ begin
         para.paraloc[calleeside].Location^.register, para.localloc.reference);
         para.paraloc[calleeside].Location^.register, para.localloc.reference);
     LOC_FPUREGISTER, LOC_CFPUREGISTER:
     LOC_FPUREGISTER, LOC_CFPUREGISTER:
       a_loadfpu_reg_ref(list, para.paraloc[calleeside].Location^.size,
       a_loadfpu_reg_ref(list, para.paraloc[calleeside].Location^.size,
+        para.paraloc[calleeside].Location^.size,
         para.paraloc[calleeside].Location^.register, para.localloc.reference);
         para.paraloc[calleeside].Location^.register, para.localloc.reference);
     LOC_MMREGISTER, LOC_CMMREGISTER:
     LOC_MMREGISTER, LOC_CMMREGISTER:
       { not supported }
       { not supported }
@@ -1407,6 +1341,7 @@ begin
         para.localloc.reference, para.paraloc[calleeside].Location^.register);
         para.localloc.reference, para.paraloc[calleeside].Location^.register);
     LOC_FPUREGISTER, LOC_CFPUREGISTER:
     LOC_FPUREGISTER, LOC_CFPUREGISTER:
       a_loadfpu_ref_reg(list, para.paraloc[calleeside].Location^.size,
       a_loadfpu_ref_reg(list, para.paraloc[calleeside].Location^.size,
+        para.paraloc[calleeside].Location^.size,
         para.localloc.reference, para.paraloc[calleeside].Location^.register);
         para.localloc.reference, para.paraloc[calleeside].Location^.register);
     LOC_MMREGISTER, LOC_CMMREGISTER:
     LOC_MMREGISTER, LOC_CMMREGISTER:
       { not supported }
       { not supported }
@@ -1469,8 +1404,8 @@ var
       reference_reset_base(href, NR_STACK_POINTER_REG, -8);
       reference_reset_base(href, NR_STACK_POINTER_REG, -8);
       if (fprcount > 0) then
       if (fprcount > 0) then
         for regcount := RS_F31 downto firstregfpu do begin
         for regcount := RS_F31 downto firstregfpu do begin
-          a_loadfpu_reg_ref(list, OS_FLOAT, newreg(R_FPUREGISTER, regcount,
-            R_SUBNONE), href);
+          a_loadfpu_reg_ref(list, OS_FLOAT, OS_FLOAT, newreg(R_FPUREGISTER,
+            regcount, R_SUBNONE), href);
           dec(href.offset, tcgsize2size[OS_FLOAT]);
           dec(href.offset, tcgsize2size[OS_FLOAT]);
         end;
         end;
       if (gprcount > 0) then
       if (gprcount > 0) then
@@ -1605,7 +1540,7 @@ var
       reference_reset_base(href, NR_STACK_POINTER_REG, -tcgsize2size[OS_FLOAT]);
       reference_reset_base(href, NR_STACK_POINTER_REG, -tcgsize2size[OS_FLOAT]);
       if (fprcount > 0) then
       if (fprcount > 0) then
         for regcount := RS_F31 downto firstregfpu do begin
         for regcount := RS_F31 downto firstregfpu do begin
-          a_loadfpu_ref_reg(list, OS_FLOAT, href, newreg(R_FPUREGISTER, regcount,
+          a_loadfpu_ref_reg(list, OS_FLOAT, OS_FLOAT, href, newreg(R_FPUREGISTER, regcount,
             R_SUBNONE));
             R_SUBNONE));
           dec(href.offset, tcgsize2size[OS_FLOAT]);
           dec(href.offset, tcgsize2size[OS_FLOAT]);
         end;
         end;
@@ -1880,8 +1815,8 @@ begin
   if count > 0 then begin
   if count > 0 then begin
     a_reg_alloc(list, NR_F0);
     a_reg_alloc(list, NR_F0);
     for count2 := 1 to count do begin
     for count2 := 1 to count do begin
-      a_loadfpu_ref_reg(list, OS_F64, src, NR_F0);
-      a_loadfpu_reg_ref(list, OS_F64, NR_F0, dst);
+      a_loadfpu_ref_reg(list, OS_F64, OS_F64, src, NR_F0);
+      a_loadfpu_reg_ref(list, OS_F64, OS_F64, NR_F0, dst);
       inc(src.offset, 8);
       inc(src.offset, 8);
       inc(dst.offset, 8);
       inc(dst.offset, 8);
     end;
     end;

+ 9 - 1
compiler/powerpc64/cpupara.pas

@@ -412,7 +412,15 @@ begin
         { either LOC_REFERENCE, or one of the above which must be passed on the
         { either LOC_REFERENCE, or one of the above which must be passed on the
         stack because of insufficient registers }
         stack because of insufficient registers }
         paraloc^.loc := LOC_REFERENCE;
         paraloc^.loc := LOC_REFERENCE;
-        paraloc^.size := int_cgsize(paralen);
+        case loc of
+          LOC_FPUREGISTER:
+            paraloc^.size:=int_float_cgsize(paralen);
+          LOC_REGISTER,
+          LOC_REFERENCE:
+            paraloc^.size:=int_cgsize(paralen);
+          else
+            internalerror(2006011101);
+        end;
         if (side = callerside) then
         if (side = callerside) then
           paraloc^.reference.index := NR_STACK_POINTER_REG
           paraloc^.reference.index := NR_STACK_POINTER_REG
         else begin
         else begin

+ 8 - 4
compiler/powerpc64/nppccnv.pas

@@ -178,7 +178,7 @@ begin
     cg.a_load_reg_ref(current_asmdata.CurrAsmList, OS_S64, OS_S64, valuereg, disp);
     cg.a_load_reg_ref(current_asmdata.CurrAsmList, OS_S64, OS_S64, valuereg, disp);
     // lfd frD, disp(r1)
     // lfd frD, disp(r1)
     location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
     location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, disp, location.register);
+    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp, location.register);
     // fcfid frD, frD
     // fcfid frD, frD
     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, location.register,
     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, location.register,
       location.register));
       location.register));
@@ -186,7 +186,7 @@ begin
     { ts:todo use TOC for this constant or at least schedule better }
     { ts:todo use TOC for this constant or at least schedule better }
     // lfd frC, const
     // lfd frC, const
     tmpfpuconst := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
     tmpfpuconst := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,tempconst.location.reference,
+    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,tempconst.location.reference,
       tmpfpuconst);
       tmpfpuconst);
     tempconst.free;
     tempconst.free;
 
 
@@ -204,10 +204,10 @@ begin
 
 
     // lfd frT1, disp(R1)
     // lfd frT1, disp(R1)
     tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
     tmpfpureg := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, disp, tmpfpureg);
+    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp, tmpfpureg);
     // lfd frD, disp+8(R1)
     // lfd frD, disp+8(R1)
     location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
     location.register := cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
-    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, disp2, location.register);
+    cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64, OS_F64, disp2, location.register);
 
 
     // fcfid frT1, frT1
     // fcfid frT1, frT1
     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, tmpfpureg,
     current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FCFID, tmpfpureg,
@@ -225,6 +225,10 @@ begin
   // free reference
   // free reference
   tg.ungetiftemp(current_asmdata.CurrAsmList, disp);
   tg.ungetiftemp(current_asmdata.CurrAsmList, disp);
 
 
+  // make sure the precision is correct
+  if (tfloatdef(resultdef).floattype = s32real) then
+    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FRSP,location.register,
+      location.register));
 end;
 end;
 
 
 begin
 begin

+ 2 - 2
compiler/powerpc64/nppcmat.pas

@@ -336,10 +336,10 @@ begin
         begin
         begin
           if (left.resultdef.typ = floatdef) then begin
           if (left.resultdef.typ = floatdef) then begin
             src1 := cg.getfpuregister(current_asmdata.CurrAsmList,
             src1 := cg.getfpuregister(current_asmdata.CurrAsmList,
-              def_cgsize(left.resultdef));
+              left.location.size);
             location.register := src1;
             location.register := src1;
             cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
             cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-              def_cgsize(left.resultdef),
+              left.location.size,left.location.size,
               left.location.reference, src1);
               left.location.reference, src1);
           end else begin
           end else begin
             src1 := cg.getintregister(current_asmdata.CurrAsmList, OS_64);
             src1 := cg.getintregister(current_asmdata.CurrAsmList, OS_64);

+ 86 - 0
compiler/ppcgen/cgppc.pas

@@ -45,6 +45,11 @@ unit cgppc;
         procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
         procedure a_load_reg_ref(list: TAsmList; fromsize, tosize: TCGSize;
           reg: tregister; const ref: treference); override;
           reg: tregister; const ref: treference); override;
 
 
+        { fpu move instructions }
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
+
        protected
        protected
         function  get_darwin_call_stub(const s: string): tasmsymbol;
         function  get_darwin_call_stub(const s: string): tasmsymbol;
         procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
         procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
@@ -203,6 +208,87 @@ unit cgppc;
     end;
     end;
 
 
 
 
+
+     procedure tcgppcgen.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
+
+       var
+         op: tasmop;
+         instr: taicpu;
+       begin
+         if not(fromsize in [OS_F32,OS_F64]) or
+            not(tosize in [OS_F32,OS_F64]) then
+           internalerror(2006123110);
+         if (tosize < fromsize) then
+           op:=A_FRSP
+         else
+           op:=A_FMR;
+         instr := taicpu.op_reg_reg(op,reg2,reg1);
+         list.concat(instr);
+         if (op = A_FMR) then
+           rg[R_FPUREGISTER].add_move_instruction(instr);
+       end;
+
+
+     procedure tcgppcgen.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
+
+       const
+         FpuLoadInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+                          { indexed? updating?}
+                    (((A_LFS,A_LFSU),(A_LFSX,A_LFSUX)),
+                     ((A_LFD,A_LFDU),(A_LFDX,A_LFDUX)));
+       var
+         op: tasmop;
+         ref2: treference;
+
+       begin
+         if not(fromsize in [OS_F32,OS_F64]) or
+            not(tosize in [OS_F32,OS_F64]) then
+           internalerror(200201121);
+         ref2 := ref;
+         fixref(list,ref2);
+         op := fpuloadinstr[fromsize,ref2.index <> NR_NO,false];
+         a_load_store(list,op,reg,ref2);
+         if (fromsize > tosize) then
+           a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg);
+       end;
+
+
+     procedure tcgppcgen.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference);
+
+       const
+         FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
+                            { indexed? updating?}
+                    (((A_STFS,A_STFSU),(A_STFSX,A_STFSUX)),
+                     ((A_STFD,A_STFDU),(A_STFDX,A_STFDUX)));
+       var
+         op: tasmop;
+         ref2: treference;
+{$ifndef cpu64bit}
+         reg2: tregister;
+{$endif cpu64bit}
+
+       begin
+         if not(fromsize in [OS_F32,OS_F64]) or
+            not(tosize in [OS_F32,OS_F64]) then
+           internalerror(200201122);
+         ref2 := ref;
+         fixref(list,ref2);
+         op := fpustoreinstr[tosize,ref2.index <> NR_NO,false];
+{$ifndef cpu64bit}
+         { some ppc's have a bug whereby storing a double to memory }
+         { as single corrupts the value -> convert double to single }
+         { first                                                    }
+         if (tosize < fromsize) then
+           begin
+             reg2:=getfpuregister(list,tosize);
+             a_loadfpu_reg_reg(list,fromsize,tosize,reg,reg2);
+             reg:=reg2;
+           end;
+{$endif not cpu64bit}
+         a_load_store(list,op,reg,ref2);
+       end;
+
+
   procedure tcgppcgen.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
   procedure tcgppcgen.a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tcgsize; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister);
     var
     var
       fromsreg, tosreg: tsubsetregister;
       fromsreg, tosreg: tsubsetregister;

+ 37 - 19
compiler/sparc/cgcpu.pas

@@ -68,9 +68,9 @@ interface
         procedure a_load_reg_reg(list:TAsmList;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
         procedure a_load_reg_reg(list:TAsmList;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
         procedure a_loadaddr_ref_reg(list:TAsmList;const ref:TReference;r:tregister);override;
         procedure a_loadaddr_ref_reg(list:TAsmList;const ref:TReference;r:tregister);override;
         { fpu move instructions }
         { fpu move instructions }
-        procedure a_loadfpu_reg_reg(list:TAsmList;size:tcgsize;reg1, reg2:tregister);override;
-        procedure a_loadfpu_ref_reg(list:TAsmList;size:tcgsize;const ref:TReference;reg:tregister);override;
-        procedure a_loadfpu_reg_ref(list:TAsmList;size:tcgsize;reg:tregister;const ref:TReference);override;
+        procedure a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);override;
+        procedure a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);override;
+        procedure a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);override;
         { comparison operations }
         { comparison operations }
         procedure a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:aint;reg:tregister;l:tasmlabel);override;
         procedure a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:aint;reg:tregister;l:tasmlabel);override;
         procedure a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
         procedure a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
@@ -423,7 +423,7 @@ implementation
         href : treference;
         href : treference;
       begin
       begin
         tg.GetTemp(list,TCGSize2Size[size],tt_normal,href);
         tg.GetTemp(list,TCGSize2Size[size],tt_normal,href);
-        a_loadfpu_reg_ref(list,size,r,href);
+        a_loadfpu_reg_ref(list,size,size,r,href);
         a_paramfpu_ref(list,size,href,paraloc);
         a_paramfpu_ref(list,size,href,paraloc);
         tg.Ungettemp(list,href);
         tg.Ungettemp(list,href);
       end;
       end;
@@ -678,39 +678,57 @@ implementation
       end;
       end;
 
 
 
 
-    procedure TCgSparc.a_loadfpu_reg_reg(list:TAsmList;size:tcgsize;reg1, reg2:tregister);
+    procedure TCgSparc.a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);
       const
       const
-         FpuMovInstr : Array[OS_F32..OS_F64] of TAsmOp =
-           (A_FMOVS,A_FMOVD);
+         FpuMovInstr : Array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
+           ((A_FMOVS,A_FSTOD),(A_FDTOS,A_FMOVD));
       var
       var
+        op: TAsmOp;
         instr : taicpu;
         instr : taicpu;
       begin
       begin
-        if reg1<>reg2 then
-          begin
-            instr:=taicpu.op_reg_reg(fpumovinstr[size],reg1,reg2);
-            list.Concat(instr);
-            { Notify the register allocator that we have written a move instruction so
-              it can try to eliminate it. }
-            add_move_instruction(instr);
-          end;
+        op:=fpumovinstr[fromsize,tosize];
+        instr:=taicpu.op_reg_reg(op,reg1,reg2);
+        list.Concat(instr);
+        { Notify the register allocator that we have written a move instruction so
+        it can try to eliminate it. }
+        if (op = A_FMOVS) or
+           (op = A_FMOVD) then
+          add_move_instruction(instr);
       end;
       end;
 
 
 
 
-    procedure TCgSparc.a_loadfpu_ref_reg(list:TAsmList;size:tcgsize;const ref:TReference;reg:tregister);
+    procedure TCgSparc.a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);
        const
        const
          FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
          FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
            (A_LDF,A_LDDF);
            (A_LDF,A_LDDF);
+       var
+         tmpreg: tregister;
        begin
        begin
-         handle_load_store(list,false,fpuloadinstr[size],reg,ref);
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=reg;
+             reg:=getfpuregister(list,fromsize);
+           end;
+         handle_load_store(list,false,fpuloadinstr[fromsize],reg,ref);
+         if (fromsize<>tosize) then
+           a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
        end;
        end;
 
 
 
 
-     procedure TCgSparc.a_loadfpu_reg_ref(list:TAsmList;size:tcgsize;reg:tregister;const ref:TReference);
+     procedure TCgSparc.a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);
        const
        const
          FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
          FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
            (A_STF,A_STDF);
            (A_STF,A_STDF);
+       var
+         tmpreg: tregister;
        begin
        begin
-         handle_load_store(list,true,fpuloadinstr[size],reg,ref);
+         if (fromsize<>tosize) then
+           begin
+             tmpreg:=getfpuregister(list,tosize);
+             a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
+             reg:=tmpreg;
+           end;
+         handle_load_store(list,true,fpuloadinstr[tosize],reg,ref);
        end;
        end;
 
 
 
 

+ 6 - 5
compiler/sparc/ncpucnv.pas

@@ -40,7 +40,7 @@ interface
          { procedure second_chararray_to_string;override; }
          { procedure second_chararray_to_string;override; }
          { procedure second_char_to_string;override; }
          { procedure second_char_to_string;override; }
           procedure second_int_to_real;override;
           procedure second_int_to_real;override;
-          procedure second_real_to_real;override;
+         { procedure second_real_to_real;override; }
          { procedure second_cord_to_pointer;override; }
          { procedure second_cord_to_pointer;override; }
          { procedure second_proc_to_procvar;override; }
          { procedure second_proc_to_procvar;override; }
          { procedure second_bool_to_int;override; }
          { procedure second_bool_to_int;override; }
@@ -117,7 +117,7 @@ implementation
         begin
         begin
           location_force_mem(current_asmdata.CurrAsmList,left.location);
           location_force_mem(current_asmdata.CurrAsmList,left.location);
           { Load memory in fpu register }
           { Load memory in fpu register }
-          cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,left.location.reference,location.register);
+          cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,OS_F32,left.location.reference,location.register);
           tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
           tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
           { Convert value in fpu register from integer to float }
           { Convert value in fpu register from integer to float }
           case tfloatdef(resultdef).floattype of
           case tfloatdef(resultdef).floattype of
@@ -156,7 +156,7 @@ implementation
             location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
             location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
             location_force_mem(current_asmdata.CurrAsmList,left.location);
             location_force_mem(current_asmdata.CurrAsmList,left.location);
             { Load memory in fpu register }
             { Load memory in fpu register }
-            cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,left.location.reference,location.register);
+            cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F32,OS_F32,left.location.reference,location.register);
             tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
             tg.ungetiftemp(current_asmdata.CurrAsmList,left.location.reference);
             current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
             current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FiTOd,location.register,location.register));
 
 
@@ -175,7 +175,7 @@ implementation
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
                    current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
 
 
-                   cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,href,hregister);
+                   cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,href,hregister);
                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FADDD,location.register,hregister,location.register));
                    current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(A_FADDD,location.register,hregister,location.register));
                    cg.a_label(current_asmdata.CurrAsmList,l2);
                    cg.a_label(current_asmdata.CurrAsmList,l2);
 
 
@@ -194,6 +194,7 @@ implementation
        end;
        end;
 
 
 
 
+(*
     procedure tsparctypeconvnode.second_real_to_real;
     procedure tsparctypeconvnode.second_real_to_real;
       const
       const
         conv_op : array[tfloattype,tfloattype] of tasmop = (
         conv_op : array[tfloattype,tfloattype] of tasmop = (
@@ -217,7 +218,7 @@ implementation
         location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
         location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,left.location.register,location.register));
         current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,left.location.register,location.register));
       end;
       end;
-
+*)
 
 
     procedure tsparctypeconvnode.second_int_to_bool;
     procedure tsparctypeconvnode.second_int_to_bool;
       var
       var

+ 31 - 14
compiler/x86/cgx86.pas

@@ -72,9 +72,9 @@ unit cgx86;
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
 
 
         { fpu move instructions }
         { fpu move instructions }
-        procedure a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister); override;
-        procedure a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister); override;
-        procedure a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference); override;
+        procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
+        procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
+        procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
 
 
         { vector register move instructions }
         { vector register move instructions }
         procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
         procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
@@ -152,6 +152,7 @@ unit cgx86;
     uses
     uses
        globals,verbose,systems,cutils,
        globals,verbose,systems,cutils,
        symdef,defutil,paramgr,procinfo,
        symdef,defutil,paramgr,procinfo,
+       tgobj,
        fmodule;
        fmodule;
 
 
     const
     const
@@ -490,7 +491,7 @@ unit cgx86;
               end;
               end;
             OS_F80 :
             OS_F80 :
               begin
               begin
-                  op:=A_FSTP;
+                  op:=A_FSTP; 
                   s:=S_FX;
                   s:=S_FX;
                end;
                end;
             OS_C64 :
             OS_C64 :
@@ -847,35 +848,51 @@ unit cgx86;
 
 
     { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
     { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
     { R_ST means "the current value at the top of the fpu stack" (JM)     }
     { R_ST means "the current value at the top of the fpu stack" (JM)     }
-    procedure tcgx86.a_loadfpu_reg_reg(list: TAsmList; size: tcgsize; reg1, reg2: tregister);
+    procedure tcgx86.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister);
 
 
+       var
+         href: treference;
+         op: tasmop;
+         s: topsize;
        begin
        begin
          if (reg1<>NR_ST) then
          if (reg1<>NR_ST) then
            begin
            begin
-             list.concat(taicpu.op_reg(A_FLD,S_NO,rgfpu.correct_fpuregister(reg1,rgfpu.fpuvaroffset)));
+             floatloadops(tosize,op,s);
+             list.concat(taicpu.op_reg(op,s,rgfpu.correct_fpuregister(reg1,rgfpu.fpuvaroffset)));
              inc_fpu_stack;
              inc_fpu_stack;
            end;
            end;
          if (reg2<>NR_ST) then
          if (reg2<>NR_ST) then
            begin
            begin
-             list.concat(taicpu.op_reg(A_FSTP,S_NO,rgfpu.correct_fpuregister(reg2,rgfpu.fpuvaroffset)));
+             floatstoreops(tosize,op,s);
+             list.concat(taicpu.op_reg(op,s,rgfpu.correct_fpuregister(reg2,rgfpu.fpuvaroffset)));
              dec_fpu_stack;
              dec_fpu_stack;
            end;
            end;
+         { OS_F80 < OS_C64, but OS_C64 fits perfectly in OS_F80 }
+         if (reg1=NR_ST) and
+            (reg2=NR_ST) and
+            (tosize<>OS_F80) and
+            (tosize<fromsize) then
+           begin
+             { can't round down to lower precision in x87 :/ }
+             tg.gettemp(list,tcgsize2size[tosize],tt_persistent,href);
+             a_loadfpu_reg_ref(list,fromsize,tosize,NR_ST,href);
+             a_loadfpu_ref_reg(list,tosize,tosize,href,NR_ST);
+           end;
        end;
        end;
 
 
 
 
-    procedure tcgx86.a_loadfpu_ref_reg(list: TAsmList; size: tcgsize; const ref: treference; reg: tregister);
+    procedure tcgx86.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister);
        begin
        begin
-         floatload(list,size,ref);
-         if (reg<>NR_ST) then
-           a_loadfpu_reg_reg(list,size,NR_ST,reg);
+         floatload(list,fromsize,ref);
+         a_loadfpu_reg_reg(list,fromsize,tosize,NR_ST,reg);
        end;
        end;
 
 
 
 
-    procedure tcgx86.a_loadfpu_reg_ref(list: TAsmList; size: tcgsize; reg: tregister; const ref: treference);
+    procedure tcgx86.a_loadfpu_reg_ref(list: TAsmList; fromsize,tosize: tcgsize; reg: tregister; const ref: treference);
        begin
        begin
          if reg<>NR_ST then
          if reg<>NR_ST then
-           a_loadfpu_reg_reg(list,size,reg,NR_ST);
-         floatstore(list,size,ref);
+           a_loadfpu_reg_reg(list,fromsize,tosize,reg,NR_ST);
+         floatstore(list,tosize,ref);
        end;
        end;
 
 
 
 

+ 2 - 2
compiler/x86/nx86inl.pas

@@ -192,12 +192,12 @@ implementation
            LOC_CFPUREGISTER:
            LOC_CFPUREGISTER:
              begin
              begin
                cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,
                cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,
-                 left.location.register,location.register);
+                 left.location.size,left.location.register,location.register);
              end;
              end;
            LOC_REFERENCE,LOC_CREFERENCE:
            LOC_REFERENCE,LOC_CREFERENCE:
              begin
              begin
                cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
                cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-                  def_cgsize(left.resultdef),
+                  left.location.size,left.location.size,
                   left.location.reference,location.register);
                   left.location.reference,location.register);
              end;
              end;
            LOC_MMREGISTER,LOC_CMMREGISTER:
            LOC_MMREGISTER,LOC_CMMREGISTER:

+ 2 - 2
compiler/x86/nx86mat.pas

@@ -204,7 +204,7 @@ interface
                 begin
                 begin
                   location.register:=NR_ST;
                   location.register:=NR_ST;
                   cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
                   cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
-                     def_cgsize(left.resultdef),
+                     left.location.size,location.size,
                      left.location.reference,location.register);
                      left.location.reference,location.register);
                   emit_none(A_FCHS,S_NO);
                   emit_none(A_FCHS,S_NO);
                 end;
                 end;
@@ -212,7 +212,7 @@ interface
               LOC_CFPUREGISTER:
               LOC_CFPUREGISTER:
                 begin
                 begin
                    { "load st,st" is ignored by the code generator }
                    { "load st,st" is ignored by the code generator }
-                   cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,left.location.register,NR_ST);
+                   cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,left.location.size,location.size,left.location.register,NR_ST);
                    location.register:=NR_ST;
                    location.register:=NR_ST;
                    emit_none(A_FCHS,S_NO);
                    emit_none(A_FCHS,S_NO);
                 end;
                 end;

+ 2 - 2
compiler/x86/rgx86.pas

@@ -295,7 +295,7 @@ implementation
                   { then save it }
                   { then save it }
                   tg.GetTemp(list,extended_size,tt_persistent,hr);
                   tg.GetTemp(list,extended_size,tt_persistent,hr);
                   saved[r.enum].ofs:=hr.offset;
                   saved[r.enum].ofs:=hr.offset;
-                  cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
+                  cg.a_loadfpu_reg_ref(list,OS_FLOAT,OS_FLOAT,r,hr);
                   cg.a_reg_dealloc(list,r);
                   cg.a_reg_dealloc(list,r);
                   include(unusedregsfpu,r.enum);
                   include(unusedregsfpu,r.enum);
                   inc(countunusedregsfpu);
                   inc(countunusedregsfpu);
@@ -324,7 +324,7 @@ implementation
                   r2.number:=NR_FRAME_POINTER_REG;
                   r2.number:=NR_FRAME_POINTER_REG;
                   reference_reset_base(hr,r2,saved[r.enum].ofs);
                   reference_reset_base(hr,r2,saved[r.enum].ofs);
                   cg.a_reg_alloc(list,r);
                   cg.a_reg_alloc(list,r);
-                  cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
+                  cg.a_loadfpu_ref_reg(list,OS_FLOAT,OS_FLOAT,hr,r);
                   if not (r.enum in unusedregsfpu) then
                   if not (r.enum in unusedregsfpu) then
                     { internalerror(10)
                     { internalerror(10)
                       in n386cal we always save/restore the reg *state*
                       in n386cal we always save/restore the reg *state*