Bladeren bron

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

git-svn-id: trunk@42525 -

florian 6 jaren geleden
bovenliggende
commit
b3ed34592f

+ 42 - 1
compiler/arm/cgcpu.pas

@@ -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;

+ 4 - 0
compiler/arm/narmadd.pas

@@ -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;

+ 16 - 3
compiler/arm/narminl.pas

@@ -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);

+ 2 - 0
compiler/arm/narmmat.pas

@@ -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

+ 9 - 2
compiler/cgobj.pas

@@ -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
 *****************************************************************************}
 *****************************************************************************}

+ 1 - 1
compiler/ncgcal.pas

@@ -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

+ 4 - 0
compiler/procinfo.pas

@@ -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;
 
 

+ 3 - 3
compiler/riscv/cgrv.pas

@@ -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;

+ 2 - 2
compiler/riscv/nrvadd.pas

@@ -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));

+ 6 - 6
compiler/riscv/nrvinl.pas

@@ -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);

+ 57 - 0
rtl/arm/arm.inc

@@ -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 }