From df44f7c2317fb68abb4fa1f58692a15343541045 Mon Sep 17 00:00:00 2001 From: florian Date: Tue, 23 Jan 2007 21:07:09 +0000 Subject: [PATCH] * fixed dword -> double in fpa mode git-svn-id: trunk@6153 - --- compiler/arm/narmcnv.pas | 41 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/compiler/arm/narmcnv.pas b/compiler/arm/narmcnv.pas index 26d099a141..df89707d96 100644 --- a/compiler/arm/narmcnv.pas +++ b/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;