diff options
author | Tristan Gingold <tgingold@free.fr> | 2020-04-13 07:08:14 +0200 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2020-04-13 07:08:14 +0200 |
commit | 5ed51a3a905c0096930c2b1c66932df24468dba9 (patch) | |
tree | 555bf7f1461896b5066f1640c97af998a8f369c7 | |
parent | d0e80a90cd97e60164eaa0d97e0d17676880e4bf (diff) | |
download | ghdl-5ed51a3a905c0096930c2b1c66932df24468dba9.tar.gz ghdl-5ed51a3a905c0096930c2b1c66932df24468dba9.tar.bz2 ghdl-5ed51a3a905c0096930c2b1c66932df24468dba9.zip |
synth-oper: also handle negative values for shift. Fix #1218
-rw-r--r-- | src/synth/synth-oper.adb | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/src/synth/synth-oper.adb b/src/synth/synth-oper.adb index 11b6c4396..c4e44f274 100644 --- a/src/synth/synth-oper.adb +++ b/src/synth/synth-oper.adb @@ -575,24 +575,35 @@ package body Synth.Oper is return Create_Value_Net (N, Res_Typ); end Synth_Sdivmod; - function Synth_Shift (Id_Pos : Module_Id; Id_Neg : Module_Id) + function Synth_Shift (Sh_Pos : Module_Id; Sh_Neg : Module_Id) return Valtyp is - pragma Unreferenced (Id_Neg); L1, R1 : Net; - N : Net; - Is_Pos : Boolean; + N, Nn, Nr1, Cond : Net; begin - Is_Pos := Is_Positive (Right); - L1 := Get_Net (Left); R1 := Get_Net (Right); - if Is_Pos then - N := Build_Shift_Rotate (Ctxt, Id_Pos, L1, R1); - else - raise Internal_Error; - end if; + + -- Handle the case when the RHS is positive. + N := Build_Shift_Rotate (Ctxt, Sh_Pos, L1, R1); Set_Location (N, Expr); + + if not Is_Positive (Right) then + -- If we cannot trivially prove that the RHS is positive, also + -- handle the case when it could be negative. + -- At worst, the optimizer will remove that part. + Nr1 := Build_Monadic (Ctxt, Id_Neg, R1); + Set_Location (Nr1, Expr); + Nn := Build_Shift_Rotate (Ctxt, Sh_Neg, L1, Nr1); + + -- Extract the sign bit. + Cond := Build_Extract (Ctxt, R1, Get_Width (R1) - 1, 1); + Set_Location (Cond, Expr); + + N := Build_Mux2 (Ctxt, Cond, N, Nn); + Set_Location (N, Expr); + end if; + return Create_Value_Net (N, Create_Res_Bound (Left)); end Synth_Shift; @@ -1306,7 +1317,7 @@ package body Synth.Oper is return No_Valtyp; when Iir_Predefined_Ieee_Numeric_Std_Sra_Sgn_Int => - return Synth_Shift (Id_Asr, Id_None); + return Synth_Shift (Id_Asr, Id_Lsl); when Iir_Predefined_Ieee_Numeric_Std_Sll_Uns_Int => return Synth_Shift (Id_Lsl, Id_Lsr); |