summaryrefslogtreecommitdiff
path: root/rtl/core/alu/shifter.sv
diff options
context:
space:
mode:
Diffstat (limited to 'rtl/core/alu/shifter.sv')
-rw-r--r--rtl/core/alu/shifter.sv33
1 files changed, 28 insertions, 5 deletions
diff --git a/rtl/core/alu/shifter.sv b/rtl/core/alu/shifter.sv
index 3effb2c..4385b41 100644
--- a/rtl/core/alu/shifter.sv
+++ b/rtl/core/alu/shifter.sv
@@ -1,12 +1,35 @@
-module alu_shl
+`include "core/uarch.sv"
+
+module core_alu_shifter
#(parameter W=16)
(
- input logic[W - 1:0] a,
- b,
- output logic[W - 1:0] q,
+ input alu_control ctrl,
+ input logic[W - 1:0] base,
+ input logic[7:0] shift,
+ input logic c_in,
+
+ output logic[W - 1:0] b,
output logic c
);
- assign {c, q} = {1'b0, a} << b;
+ logic [W - 1:0] b_no_c, b_shl, b_shr, b_ror;
+ logic [W:0] sign_mask;
+ logic c_shl, c_shr;
+
+ assign sign_mask = {(W + 1){ctrl.sign_extend & base[W - 1]}};
+ assign {c_shl, b_shl} = {c_in, base} << shift;
+ assign {b_shr, c_shr} = {base, c_in} >> shift | ~(sign_mask >> shift);
+ assign b_ror = b_shr | base << (W - shift);
+
+ assign b = {b_no_c[W - 1] | (ctrl.put_carry & c_in), b_no_c[W - 2:0]};
+ assign c = ctrl.shr | ctrl.ror ? c_shr : c_shl;
+
+ always_comb
+ if(ctrl.ror)
+ b = b_ror;
+ else if(ctrl.shr)
+ b = {b_shr[W - 1] | (ctrl.put_carry & c_in), b_shr[W - 2:0]};
+ else
+ b = b_shl;
endmodule