+ software handling of exceptions on arm

* reworked software handling of exceptions so they can be check lazily

git-svn-id: trunk@42525 -
This commit is contained in:
florian 2019-07-28 21:06:36 +00:00
parent 847ac91d1d
commit b3ed34592f
11 changed files with 146 additions and 18 deletions

View File

@ -61,6 +61,8 @@ unit cgcpu;
procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: 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_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
procedure g_check_for_fpu_exception(list : TAsmList; force,clear : boolean); override;
procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override; procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
{ comparison operations } { comparison operations }
procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister; procedure a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
@ -1720,6 +1722,33 @@ unit cgcpu;
end; end;
procedure tbasecgarm.g_check_for_fpu_exception(list: TAsmList;force,clear : boolean);
var
r : TRegister;
ai: taicpu;
l: TAsmLabel;
begin
if ((cs_check_fpu_exceptions in current_settings.localswitches) and
(force or current_procinfo.FPUExceptionCheckNeeded)) then
begin
r:=getintregister(list,OS_INT);
list.concat(taicpu.op_reg_reg(A_FMRX,r,NR_FPSCR));
list.concat(setoppostfix(taicpu.op_reg_reg_const(A_AND,r,r,$9f),PF_S));
current_asmdata.getjumplabel(l);
ai:=taicpu.op_sym(A_B,l);
ai.is_jmp:=true;
ai.condition:=C_EQ;
list.concat(ai);
alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_THROWFPUEXCEPTION',false);
dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
a_label(list,l);
if clear then
current_procinfo.FPUExceptionCheckNeeded:=false;
end;
end;
{ comparison operations } { comparison operations }
procedure tbasecgarm.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister; procedure tbasecgarm.a_cmp_const_reg_label(list : TAsmList;size : tcgsize;cmp_op : topcmp;a : tcgint;reg : tregister;
l : tasmlabel); l : tasmlabel);
@ -3069,6 +3098,7 @@ unit cgcpu;
else else
; ;
end; end;
maybe_check_for_fpu_exception(list);
end; end;
@ -3134,6 +3164,7 @@ unit cgcpu;
if (tmpmmreg<>reg) then if (tmpmmreg<>reg) then
a_loadmm_reg_reg(list,fromsize,tosize,tmpmmreg,reg,shuffle); a_loadmm_reg_reg(list,fromsize,tosize,tmpmmreg,reg,shuffle);
maybe_check_for_fpu_exception(list);
end; end;
@ -3199,6 +3230,7 @@ unit cgcpu;
begin begin
handle_load_store(list,A_VSTR,PF_None,tmpmmreg,ref); handle_load_store(list,A_VSTR,PF_None,tmpmmreg,ref);
end; end;
maybe_check_for_fpu_exception(list);
end; end;
@ -3214,6 +3246,7 @@ unit cgcpu;
not shufflescalar(shuffle) then not shufflescalar(shuffle) then
internalerror(2009112516); internalerror(2009112516);
list.concat(taicpu.op_reg_reg(A_VMOV,mmreg,intreg)); list.concat(taicpu.op_reg_reg(A_VMOV,mmreg,intreg));
maybe_check_for_fpu_exception(list);
end; end;
@ -3229,6 +3262,7 @@ unit cgcpu;
not shufflescalar(shuffle) then not shufflescalar(shuffle) then
internalerror(2009112514); internalerror(2009112514);
list.concat(taicpu.op_reg_reg(A_VMOV,intreg,mmreg)); list.concat(taicpu.op_reg_reg(A_VMOV,intreg,mmreg));
maybe_check_for_fpu_exception(list);
end; end;
@ -3356,6 +3390,7 @@ unit cgcpu;
if (mmsize<>OS_F64) then if (mmsize<>OS_F64) then
internalerror(2009112405); internalerror(2009112405);
list.concat(taicpu.op_reg_reg_reg(A_VMOV,mmreg,intreg.reglo,intreg.reghi)); list.concat(taicpu.op_reg_reg_reg(A_VMOV,mmreg,intreg.reglo,intreg.reghi));
cg.maybe_check_for_fpu_exception(list);
end; end;
@ -3366,6 +3401,7 @@ unit cgcpu;
if (mmsize<>OS_F64) then if (mmsize<>OS_F64) then
internalerror(2009112406); internalerror(2009112406);
list.concat(taicpu.op_reg_reg_reg(A_VMOV,intreg.reglo,intreg.reghi,mmreg)); list.concat(taicpu.op_reg_reg_reg(A_VMOV,intreg.reglo,intreg.reghi,mmreg));
cg.maybe_check_for_fpu_exception(list);
end; end;
@ -5196,6 +5232,7 @@ unit cgcpu;
instr:=setoppostfix(taicpu.op_reg_reg(A_VMOV,reg2,reg1), PF_F32); instr:=setoppostfix(taicpu.op_reg_reg(A_VMOV,reg2,reg1), PF_F32);
list.Concat(instr); list.Concat(instr);
add_move_instruction(instr); add_move_instruction(instr);
maybe_check_for_fpu_exception(list);
end end
else if (fromsize=OS_F64) and else if (fromsize=OS_F64) and
(tosize=OS_F64) then (tosize=OS_F64) then
@ -5221,6 +5258,7 @@ unit cgcpu;
procedure tthumb2cgarm.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle); procedure tthumb2cgarm.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference; shuffle: pmmshuffle);
begin begin
handle_load_store(list,A_VSTR,PF_None,reg,ref); handle_load_store(list,A_VSTR,PF_None,reg,ref);
maybe_check_for_fpu_exception(list);
end; end;
@ -5238,7 +5276,10 @@ unit cgcpu;
begin begin
if //(shuffle=nil) and if //(shuffle=nil) and
(fromsize=OS_F32) then (fromsize=OS_F32) then
list.Concat(taicpu.op_reg_reg(A_VMOV,intreg,mmreg)) begin
list.Concat(taicpu.op_reg_reg(A_VMOV,intreg,mmreg));
maybe_check_for_fpu_exception(list);
end
else else
internalerror(2012100814); internalerror(2012100814);
end; end;

View File

@ -238,6 +238,7 @@ interface
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op, current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op,
location.register,left.location.register,right.location.register),pf)); location.register,left.location.register,right.location.register),pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_fpv4_s16: fpu_fpv4_s16:
begin begin
@ -263,6 +264,7 @@ interface
end; end;
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op, location.register,left.location.register,right.location.register), PF_F32)); current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op, location.register,left.location.register,right.location.register), PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_soft: fpu_soft:
{ this case should be handled already by pass1 } { this case should be handled already by pass1 }
@ -325,6 +327,7 @@ interface
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op, current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op,
left.location.register,right.location.register), pf)); left.location.register,right.location.register), pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VMRS,NR_APSR_nzcv,NR_FPSCR)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_VMRS,NR_APSR_nzcv,NR_FPSCR));
location.resflags:=GetFpuResFlags; location.resflags:=GetFpuResFlags;
@ -341,6 +344,7 @@ interface
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op, current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(op,
left.location.register,right.location.register),PF_F32)); left.location.register,right.location.register),PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS); cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_VMRS, NR_APSR_nzcv, NR_FPSCR)); current_asmdata.CurrAsmList.Concat(taicpu.op_reg_reg(A_VMRS, NR_APSR_nzcv, NR_FPSCR));
end; end;

View File

@ -272,9 +272,13 @@ implementation
else else
pf:=PF_F64; pf:=PF_F64;
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register),pf)); current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register),pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_fpv4_s16: fpu_fpv4_s16:
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32)); begin
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg(A_VABS,location.register,left.location.register), PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end;
fpu_soft: fpu_soft:
begin begin
if singleprec then if singleprec then
@ -309,9 +313,13 @@ implementation
else else
pf:=PF_F64; pf:=PF_F64;
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register),pf)); current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register),pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_fpv4_s16: fpu_fpv4_s16:
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32)); begin
current_asmdata.CurrAsmList.Concat(setoppostfix(taicpu.op_reg_reg_reg(A_VMUL,location.register,left.location.register,left.location.register), PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end;
else else
internalerror(2009111403); internalerror(2009111403);
end; end;
@ -339,9 +347,13 @@ implementation
else else
pf:=PF_F64; pf:=PF_F64;
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register),pf)); current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register),pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_fpv4_s16: fpu_fpv4_s16:
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register), PF_F32)); begin
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VSQRT,location.register,left.location.register), PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end;
else else
internalerror(2009111402); internalerror(2009111402);
end; end;
@ -515,6 +527,7 @@ implementation
oppostfix:=PF_F32; oppostfix:=PF_F32;
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op[negproduct,negop3], current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg_reg(op[negproduct,negop3],
location.register,paraarray[1].location.register,paraarray[2].location.register),oppostfix)); location.register,paraarray[1].location.register,paraarray[2].location.register),oppostfix));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end end
else else
internalerror(2014032301); internalerror(2014032301);

View File

@ -435,6 +435,7 @@ implementation
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG, current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG,
location.register,left.location.register), pf)); location.register,left.location.register), pf));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_fpv4_s16: fpu_fpv4_s16:
begin begin
@ -444,6 +445,7 @@ implementation
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size); location.register:=cg.getmmregister(current_asmdata.CurrAsmList,location.size);
current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG, current_asmdata.CurrAsmList.concat(setoppostfix(taicpu.op_reg_reg(A_VNEG,
location.register,left.location.register), PF_F32)); location.register,left.location.register), PF_F32));
cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
fpu_soft: fpu_soft:
begin begin

View File

@ -453,7 +453,8 @@ unit cgobj;
{ some CPUs do not support hardware fpu exceptions, this procedure is called after instructions which { some CPUs do not support hardware fpu exceptions, this procedure is called after instructions which
might set FPU exception related flags, so it has to check these flags if needed and throw an exeception } might set FPU exception related flags, so it has to check these flags if needed and throw an exeception }
procedure g_check_for_fpu_exception(list: TAsmList); virtual; procedure g_check_for_fpu_exception(list : TAsmList; force,clear : boolean); virtual;
procedure maybe_check_for_fpu_exception(list: TAsmList);
protected protected
function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual; function g_indirect_sym_load(list:TAsmList;const symname: string; const flags: tindsymflags): tregister;virtual;
@ -2930,12 +2931,18 @@ implementation
end; end;
procedure tcg.g_check_for_fpu_exception(list: TAsmList); procedure tcg.g_check_for_fpu_exception(list: TAsmList;force,clear : boolean);
begin begin
{ empty by default } { empty by default }
end; end;
procedure tcg.maybe_check_for_fpu_exception(list: TAsmList);
begin
current_procinfo.FPUExceptionCheckNeeded:=true;
g_check_for_fpu_exception(list,false,true);
end;
{***************************************************************************** {*****************************************************************************
TCG64 TCG64
*****************************************************************************} *****************************************************************************}

View File

@ -1280,7 +1280,7 @@ implementation
{ check for fpu exceptions } { check for fpu exceptions }
if cnf_check_fpu_exceptions in callnodeflags then if cnf_check_fpu_exceptions in callnodeflags then
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
{ perhaps i/o check ? } { perhaps i/o check ? }
if (cs_check_io in current_settings.localswitches) and if (cs_check_io in current_settings.localswitches) and

View File

@ -136,6 +136,10 @@ unit procinfo;
Requires different entry code for some targets. } Requires different entry code for some targets. }
ConstructorCallingConstructor: boolean; ConstructorCallingConstructor: boolean;
{ true, if an FPU instruction has been generated which could raise an exception and where the flags
need to be checked explicitly like on RISC-V or certain ARM architectures }
FPUExceptionCheckNeeded : Boolean;
constructor create(aparent:tprocinfo);virtual; constructor create(aparent:tprocinfo);virtual;
destructor destroy;override; destructor destroy;override;

View File

@ -72,7 +72,7 @@ unit cgrv;
procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: 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_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tcgsize; reg: tregister; const ref: treference); override;
procedure g_check_for_fpu_exception(list: TAsmList); override; procedure g_check_for_fpu_exception(list: TAsmList;force,clear : boolean); override;
protected protected
function fixref(list: TAsmList; var ref: treference): boolean; function fixref(list: TAsmList; var ref: treference): boolean;
procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister); procedure maybeadjustresult(list: TAsmList; op: topcg; size: tcgsize; dst: tregister);
@ -614,7 +614,7 @@ unit cgrv;
if fromsize<>tosize then if fromsize<>tosize then
begin begin
list.concat(taicpu.op_reg_reg(convOp[fromsize,tosize],reg2,reg1)); list.concat(taicpu.op_reg_reg(convOp[fromsize,tosize],reg2,reg1));
g_check_for_fpu_exception(list); maybe_check_for_fpu_exception(list);
end end
else else
begin begin
@ -786,7 +786,7 @@ unit cgrv;
end; end;
procedure tcgrv.g_check_for_fpu_exception(list: TAsmList); procedure tcgrv.g_check_for_fpu_exception(list: TAsmList;force,clear : boolean);
var var
r : TRegister; r : TRegister;
ai: taicpu; ai: taicpu;

View File

@ -423,12 +423,12 @@ implementation
if not cmpop then if not cmpop then
begin begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end end
else else
begin begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,right.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
if inv then if inv then
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_XORI,location.register,location.register,1)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_const(A_XORI,location.register,location.register,1));

View File

@ -160,13 +160,13 @@ implementation
begin begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_S,location.register, current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_S,location.register,
left.location.register)); left.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
OS_F64: OS_F64:
begin begin
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_D,location.register, current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(A_FSQRT_D,location.register,
left.location.register)); left.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end end
else else
inherited; inherited;
@ -199,7 +199,7 @@ implementation
else else
op := A_FMUL_D; op := A_FMUL_D;
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg(op,location.register,left.location.register,left.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
@ -237,7 +237,7 @@ implementation
{$endif} {$endif}
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg(op,location.register,left.location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
@ -275,7 +275,7 @@ implementation
{$endif} {$endif}
current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_roundingmode(op,location.register,left.location.register,RM_RTZ)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_roundingmode(op,location.register,left.location.register,RM_RTZ));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end; end;
@ -349,7 +349,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_reg_reg(op[def_cgsize(resultdef), negproduct,negop3],location.register,paraarray[1].location.register,paraarray[2].location.register,paraarray[2].location.register)); current_asmdata.CurrAsmList.concat(taicpu.op_reg_reg_reg_reg(op[def_cgsize(resultdef), negproduct,negop3],location.register,paraarray[1].location.register,paraarray[2].location.register,paraarray[2].location.register));
cg.g_check_for_fpu_exception(current_asmdata.CurrAsmList); cg.maybe_check_for_fpu_exception(current_asmdata.CurrAsmList);
end end
else else
internalerror(2014032301); internalerror(2014032301);

View File

@ -47,6 +47,63 @@ begin
end; end;
end; end;
{$else} {$else}
const
fpu_nx = 1 shl 0;
fpu_uf = 1 shl 1;
fpu_of = 1 shl 2;
fpu_dz = 1 shl 3;
fpu_nv = 1 shl 4;
function getfpscr: sizeuint; nostackframe; assembler;
asm
fmrx r0,fpscr
end;
procedure setfpscr(flags : sizeuint); nostackframe; assembler;
asm
fmxr fpscr,r0
end;
const
FPSCR_IOC = 1;
FPSCR_DZC = 1 shl 1;
FPSCR_OFC = 1 shl 2;
FPSCR_UFC = 1 shl 3;
FPSCR_IXC = 1 shl 4;
FPSCR_IDC = 1 shl 7;
procedure fpc_throwfpuexception;[public,alias:'FPC_THROWFPUEXCEPTION'];
var
fpscr : longint;
f: TFPUException;
begin
{ at this point, we know already, that an exception will be risen }
fpscr:=getfpscr;
if (fpscr and FPSCR_DZC) <> 0 then
float_raise(exZeroDivide);
if (fpscr and FPSCR_OFC) <> 0 then
float_raise(exOverflow);
if (fpscr and FPSCR_UFC) <> 0 then
float_raise(exUnderflow);
if (fpscr and FPSCR_IOC) <> 0 then
float_raise(exInvalidOp);
if (fpscr and FPSCR_IXC) <> 0 then
float_raise(exPrecision);
if (fpscr and FPSCR_IDC) <> 0 then
float_raise(exDenormalized);
{ now the soft float exceptions }
for f in softfloat_exception_flags do
float_raise(f);
end;
Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif} Procedure SysInitFPU;{$ifdef SYSTEMINLINE}inline;{$endif}
begin begin
{ Enable FPU exceptions, but disable INEXACT, UNDERFLOW, DENORMAL } { Enable FPU exceptions, but disable INEXACT, UNDERFLOW, DENORMAL }