mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 05:49:23 +02:00
+ 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:
parent
847ac91d1d
commit
b3ed34592f
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
|
@ -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 }
|
||||||
|
Loading…
Reference in New Issue
Block a user