aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2022-10-02 13:57:49 +0200
committerTristan Gingold <tgingold@free.fr>2022-10-02 13:57:49 +0200
commit298fa787da01ded60f2b9d02c9529760aabd2921 (patch)
treef8697578f8ac6011720f561d5ecc5074849ae142 /src
parent7d642ac4d912c4111769f124a2da97fa83828548 (diff)
downloadghdl-298fa787da01ded60f2b9d02c9529760aabd2921.tar.gz
ghdl-298fa787da01ded60f2b9d02c9529760aabd2921.tar.bz2
ghdl-298fa787da01ded60f2b9d02c9529760aabd2921.zip
translate, grt: add lib function for div and rem.
Do not rely on hardware exceptions to catch division by 0, they are caught in windows by the c handler and not propagated
Diffstat (limited to 'src')
-rw-r--r--src/ghdldrv/ghdlrun.adb8
-rw-r--r--src/grt/grt-lib.adb44
-rw-r--r--src/grt/grt-lib.ads12
-rw-r--r--src/vhdl/translate/trans-chap7.adb58
-rw-r--r--src/vhdl/translate/trans_decls.ads4
-rw-r--r--src/vhdl/translate/translation.adb30
6 files changed, 148 insertions, 8 deletions
diff --git a/src/ghdldrv/ghdlrun.adb b/src/ghdldrv/ghdlrun.adb
index bfa095307..3f96bf456 100644
--- a/src/ghdldrv/ghdlrun.adb
+++ b/src/ghdldrv/ghdlrun.adb
@@ -386,6 +386,14 @@ package body Ghdlrun is
Grt.Lib.Ghdl_I32_Exp'Address);
Def (Trans_Decls.Ghdl_I64_Exp,
Grt.Lib.Ghdl_I64_Exp'Address);
+ Def (Trans_Decls.Ghdl_I32_Div,
+ Grt.Lib.Ghdl_I32_Div'Address);
+ Def (Trans_Decls.Ghdl_I64_Div,
+ Grt.Lib.Ghdl_I64_Div'Address);
+ Def (Trans_Decls.Ghdl_I32_Mod,
+ Grt.Lib.Ghdl_I32_Mod'Address);
+ Def (Trans_Decls.Ghdl_I64_Mod,
+ Grt.Lib.Ghdl_I64_Mod'Address);
Def (Trans_Decls.Ghdl_Check_Stack_Allocation,
Grt.Lib.Ghdl_Check_Stack_Allocation'Address);
diff --git a/src/grt/grt-lib.adb b/src/grt/grt-lib.adb
index f69da860f..ec64f810f 100644
--- a/src/grt/grt-lib.adb
+++ b/src/grt/grt-lib.adb
@@ -271,6 +271,50 @@ package body Grt.Lib is
return Res;
end Ghdl_I64_Exp;
+ function Ghdl_I32_Div (L, R : Ghdl_I32) return Ghdl_I32
+ is
+ pragma Suppress (Overflow_Check);
+ begin
+ if R = 0 then
+ Error ("division by 0");
+ elsif R = -1 and L = Ghdl_I32'First then
+ Error ("overflow in division");
+ end if;
+ return L / R;
+ end Ghdl_I32_Div;
+
+ function Ghdl_I64_Div (L, R : Ghdl_I64) return Ghdl_I64
+ is
+ pragma Suppress (Overflow_Check);
+ begin
+ if R = 0 then
+ Error ("division by 0");
+ elsif R = -1 and L = Ghdl_I64'First then
+ Error ("overflow in division");
+ end if;
+ return L / R;
+ end Ghdl_I64_Div;
+
+ function Ghdl_I32_Mod (L, R : Ghdl_I32) return Ghdl_I32
+ is
+ pragma Suppress (Overflow_Check);
+ begin
+ if R = 0 then
+ Error ("division by 0");
+ end if;
+ return L mod R;
+ end Ghdl_I32_Mod;
+
+ function Ghdl_I64_Mod (L, R : Ghdl_I64) return Ghdl_I64
+ is
+ pragma Suppress (Overflow_Check);
+ begin
+ if R = 0 then
+ Error ("division by 0");
+ end if;
+ return L mod R;
+ end Ghdl_I64_Mod;
+
procedure Ghdl_Check_Stack_Allocation (Size : Ghdl_Index_Type)
is
Bt : Backtrace_Addrs;
diff --git a/src/grt/grt-lib.ads b/src/grt/grt-lib.ads
index f8e7f0a7a..0210057fa 100644
--- a/src/grt/grt-lib.ads
+++ b/src/grt/grt-lib.ads
@@ -69,6 +69,12 @@ package Grt.Lib is
function Ghdl_I32_Exp (V : Ghdl_I32; E : Std_Integer) return Ghdl_I32;
function Ghdl_I64_Exp (V : Ghdl_I64; E : Std_Integer) return Ghdl_I64;
+ function Ghdl_I32_Div (L, R : Ghdl_I32) return Ghdl_I32;
+ function Ghdl_I64_Div (L, R : Ghdl_I64) return Ghdl_I64;
+
+ function Ghdl_I32_Mod (L, R : Ghdl_I32) return Ghdl_I32;
+ function Ghdl_I64_Mod (L, R : Ghdl_I64) return Ghdl_I64;
+
-- Called before allocation of large (complex) objects.
procedure Ghdl_Check_Stack_Allocation (Size : Ghdl_Index_Type);
@@ -141,6 +147,12 @@ private
pragma Export (C, Ghdl_I64_Exp, "__ghdl_i64_exp");
pragma Export (C, Ghdl_Real_Exp, "__ghdl_real_exp");
+ pragma Export (C, Ghdl_I32_Div, "__ghdl_i32_div");
+ pragma Export (C, Ghdl_I64_Div, "__ghdl_i64_div");
+
+ pragma Export (C, Ghdl_I32_Mod, "__ghdl_i32_mod");
+ pragma Export (C, Ghdl_I64_Mod, "__ghdl_i64_mod");
+
pragma Export (C, Ghdl_Std_Ulogic_To_Boolean_Array,
"__ghdl_std_ulogic_to_boolean_array");
diff --git a/src/vhdl/translate/trans-chap7.adb b/src/vhdl/translate/trans-chap7.adb
index 0ecd59f34..b9be2c390 100644
--- a/src/vhdl/translate/trans-chap7.adb
+++ b/src/vhdl/translate/trans-chap7.adb
@@ -1130,8 +1130,8 @@ package body Trans.Chap7 is
Iir_Predefined_Integer_Minus => ON_Sub_Ov,
Iir_Predefined_Integer_Mul => ON_Mul_Ov,
Iir_Predefined_Integer_Rem => ON_Rem_Ov,
- Iir_Predefined_Integer_Mod => ON_Mod_Ov,
- Iir_Predefined_Integer_Div => ON_Div_Ov,
+ Iir_Predefined_Integer_Mod => ON_Nil,
+ Iir_Predefined_Integer_Div => ON_Nil,
Iir_Predefined_Integer_Absolute => ON_Abs_Ov,
Iir_Predefined_Integer_Negation => ON_Neg_Ov,
@@ -2334,6 +2334,31 @@ package body Trans.Chap7 is
return New_Convert_Ov (New_Obj_Value (Res), Res_Otype);
end Translate_Predefined_Std_Ulogic_Array_Match;
+ -- Div/mod/rem intrinsic (to handle 0 and overflow).
+ function Translate_Predefined_Div (Expr : Iir_Function_Declaration;
+ Div32 : O_Dnode;
+ Div64 : O_Dnode;
+ Left_Tree, Right_Tree : O_Enode;
+ Res_Otype : O_Tnode) return O_Enode
+ is
+ Expr_Tinfo : constant Type_Info_Acc := Get_Info (Get_Type (Expr));
+ Opr : O_Dnode;
+ Etype : O_Tnode;
+ Res : O_Enode;
+ begin
+ case Type_Mode_Integers (Expr_Tinfo.Type_Mode) is
+ when Type_Mode_I32 =>
+ Opr := Div32;
+ Etype := Ghdl_I32_Type;
+ when Type_Mode_I64 =>
+ Opr := Div64;
+ Etype := Ghdl_I64_Type;
+ end case;
+ Res := Translate_Lib_Operator (New_Convert_Ov (Left_Tree, Etype),
+ New_Convert_Ov (Right_Tree, Etype), Opr);
+ return New_Convert_Ov (Res, Res_Otype);
+ end Translate_Predefined_Div;
+
function Translate_Predefined_Operator
(Expr : Iir_Function_Declaration; Left, Right : Iir; Res_Type : Iir)
return O_Enode
@@ -2594,6 +2619,28 @@ package body Trans.Chap7 is
end if;
end if;
+ when Iir_Predefined_Integer_Div =>
+ if Get_Kind (Right) /= Iir_Kind_Integer_Literal
+ or else Get_Value (Right) in -1 .. 0
+ then
+ return Translate_Predefined_Div
+ (Expr, Ghdl_I32_Div, Ghdl_I64_Div,
+ Left_Tree, Right_Tree, Res_Otype);
+ else
+ return New_Dyadic_Op (ON_Div_Ov, Left_Tree, Right_Tree);
+ end if;
+
+ when Iir_Predefined_Integer_Mod =>
+ if Get_Kind (Right) /= Iir_Kind_Integer_Literal
+ or else Get_Value (Right) = 0
+ then
+ return Translate_Predefined_Div
+ (Expr, Ghdl_I32_Mod, Ghdl_I64_Mod,
+ Left_Tree, Right_Tree, Res_Otype);
+ else
+ return New_Dyadic_Op (ON_Mod_Ov, Left_Tree, Right_Tree);
+ end if;
+
when Iir_Predefined_Physical_Integer_Div =>
return New_Dyadic_Op (ON_Div_Ov, Left_Tree,
New_Convert_Ov (Right_Tree, Res_Otype));
@@ -6348,8 +6395,6 @@ package body Trans.Chap7 is
| Iir_Predefined_Integer_Plus
| Iir_Predefined_Integer_Minus
| Iir_Predefined_Integer_Mul
- | Iir_Predefined_Integer_Div
- | Iir_Predefined_Integer_Mod
| Iir_Predefined_Integer_Rem
| Iir_Predefined_Floating_Equality
| Iir_Predefined_Floating_Inequality
@@ -6378,6 +6423,11 @@ package body Trans.Chap7 is
pragma Assert (Predefined_To_Onop (Kind) /= ON_Nil);
return;
+ when Iir_Predefined_Integer_Div
+ | Iir_Predefined_Integer_Mod =>
+ -- Intrinsic
+ return;
+
when Iir_Predefined_Boolean_Nand
| Iir_Predefined_Boolean_Nor
| Iir_Predefined_Boolean_Xnor
diff --git a/src/vhdl/translate/trans_decls.ads b/src/vhdl/translate/trans_decls.ads
index 1aac95cff..5587a3339 100644
--- a/src/vhdl/translate/trans_decls.ads
+++ b/src/vhdl/translate/trans_decls.ads
@@ -182,6 +182,10 @@ package Trans_Decls is
Ghdl_Real_Exp : O_Dnode;
Ghdl_I32_Exp : O_Dnode;
Ghdl_I64_Exp : O_Dnode;
+ Ghdl_I32_Div : O_Dnode;
+ Ghdl_I64_Div : O_Dnode;
+ Ghdl_I32_Mod : O_Dnode;
+ Ghdl_I64_Mod : O_Dnode;
-- Procedure called in case of check failed.
Ghdl_Program_Error : O_Dnode;
diff --git a/src/vhdl/translate/translation.adb b/src/vhdl/translate/translation.adb
index 5325e6276..cbca05a6a 100644
--- a/src/vhdl/translate/translation.adb
+++ b/src/vhdl/translate/translation.adb
@@ -1200,10 +1200,8 @@ package body Translation is
Start_Function_Decl
(Interfaces, Get_Identifier ("__ghdl_real_exp"), O_Storage_External,
Std_Real_Otype);
- New_Interface_Decl (Interfaces, Param, Get_Identifier ("left"),
- Std_Real_Otype);
- New_Interface_Decl (Interfaces, Param, Get_Identifier ("right"),
- Std_Integer_Otype);
+ New_Interface_Decl (Interfaces, Param, Wki_Left, Std_Real_Otype);
+ New_Interface_Decl (Interfaces, Param, Wki_Right, Std_Integer_Otype);
Finish_Subprogram_Decl (Interfaces, Ghdl_Real_Exp);
-- function __ghdl_i32_exp (left : ghdl_i32;
@@ -1226,6 +1224,30 @@ package body Translation is
New_Interface_Decl (Interfaces, Param, Wki_Right, Std_Integer_Otype);
Finish_Subprogram_Decl (Interfaces, Ghdl_I64_Exp);
+ declare
+ procedure Create_Div_Subprogram
+ (Name : String; T : O_Tnode; Decl : out O_Dnode) is
+ begin
+ Start_Function_Decl
+ (Interfaces, Get_Identifier (Name), O_Storage_External, T);
+ New_Interface_Decl (Interfaces, Param, Wki_Left, T);
+ New_Interface_Decl (Interfaces, Param, Wki_Right, T);
+ Finish_Subprogram_Decl (Interfaces, Decl);
+ end Create_Div_Subprogram;
+ begin
+ -- function __ghdl_i32_div (left, right : ghdl_i32) return ghdl_i32;
+ Create_Div_Subprogram ("__ghdl_i32_div", Ghdl_I32_Type, Ghdl_I32_Div);
+
+ -- function __ghdl_i64_div (left, right : ghdl_i64) return ghdl_i64;
+ Create_Div_Subprogram ("__ghdl_i64_div", Ghdl_I64_Type, Ghdl_I64_Div);
+
+ -- function __ghdl_i32_mod (left, right : ghdl_i32) return ghdl_i32;
+ Create_Div_Subprogram ("__ghdl_i32_mod", Ghdl_I32_Type, Ghdl_I32_Mod);
+
+ -- function __ghdl_i64_mod (left, right : ghdl_i64) return ghdl_i64;
+ Create_Div_Subprogram ("__ghdl_i64_mod", Ghdl_I64_Type, Ghdl_I64_Mod);
+ end;
+
-- procedure __ghdl_image_b1 (res : std_string_ptr_node;
-- val : ghdl_bool_type;
-- rti : ghdl_rti_access);