Quellcode durchsuchen

* fixed dword -> double in fpa mode

git-svn-id: trunk@6153 -
florian vor 18 Jahren
Ursprung
Commit
df44f7c231
1 geänderte Dateien mit 40 neuen und 1 gelöschten Zeilen
  1. 40 1
      compiler/arm/narmcnv.pas

+ 40 - 1
compiler/arm/narmcnv.pas

@@ -118,13 +118,52 @@ implementation
     procedure tarmtypeconvnode.second_int_to_real;
       var
         instr : taicpu;
+        href : treference;
+        l1,l2 : tasmlabel;
+        hregister : tregister;
       begin
+        current_asmdata.getdatalabel(l1);
+        current_asmdata.getjumplabel(l2);
+        reference_reset_symbol(href,l1,0);
+
+        { convert first to double to avoid precision loss }
         location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
         location_force_reg(current_asmdata.CurrAsmList,left.location,OS_32,true);
         location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
         instr:=taicpu.op_reg_reg(A_FLT,location.register,left.location.register);
-        instr.oppostfix:=cgsize2fpuoppostfix[def_cgsize(resultdef)];
+        instr.oppostfix:=PF_D;
         current_asmdata.CurrAsmList.concat(instr);
+
+        current_asmdata.CurrAsmList.concat(Taicpu.op_reg_const(A_CMP,left.location.register,0));
+        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_GE,l2);
+
+        case tfloatdef(resultdef).floattype of
+          { converting dword to s64real first and cut off at the end avoids precision loss }
+          s32real,
+          s64real:
+            begin
+              hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,OS_F64);
+              current_asmdata.asmlists[al_typedconsts].concat(tai_align.create(const_align(8)));
+              current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l1));
+              { I got this constant from a test program (FK) }
+              current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit($41f00000));
+              current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_32bit(0));
+
+              cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,OS_F64,OS_F64,href,hregister);
+              current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_ADF,location.register,hregister,location.register),PF_D));
+              cg.a_label(current_asmdata.CurrAsmList,l2);
+
+              { cut off if we should convert to single }
+              if tfloatdef(resultdef).floattype=s32real then
+                begin
+                  hregister:=location.register;
+                  location.register:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
+                  current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_MVF,hregister,location.register),PF_S));
+                end;
+            end;
+          else
+            internalerror(200410031);
+        end;
       end;