From 8a0a907e2faae2fb579260f64a40fffb00182638 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 2 May 2020 13:28:19 +1000 Subject: [PATCH] Implement the extswsli instruction This mainly required the addition of an entry to the opcode 31 decode table and a 32-bit sign-extender in the rotator. Signed-off-by: Paul Mackerras --- decode1.vhdl | 3 ++- execute1.vhdl | 5 ++++- rotator.vhdl | 12 +++++++++--- rotator_tb.vhdl | 28 ++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 785b669..466a8ba 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -185,7 +185,8 @@ architecture behaviour of decode1 is 2#1110111010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsb 2#1110011010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsh 2#1111011010# => (ALU, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extsw - -- 2#110111101-# extswsli + 2#1101111010# => (ALU, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extswsli + 2#1101111011# => (ALU, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- extswsli 2#1111010110# => (ALU, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbi 2#0000010110# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt 2#0000001111# => (ALU, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel diff --git a/execute1.vhdl b/execute1.vhdl index 8286d30..6940049 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -63,6 +63,7 @@ architecture behaviour of execute1 is signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0')); signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0')); signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; + signal rot_sign_ext: std_ulogic; signal rotator_result: std_ulogic_vector(63 downto 0); signal rotator_carry: std_ulogic; signal logical_result: std_ulogic_vector(63 downto 0); @@ -174,6 +175,7 @@ begin arith => e_in.is_signed, clear_left => rot_clear_left, clear_right => rot_clear_right, + sign_ext_rs => rot_sign_ext, result => rotator_result, carry_out => rotator_carry ); @@ -429,6 +431,7 @@ begin right_shift <= '1' when e_in.insn_type = OP_SHR else '0'; rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0'; rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0'; + rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0'; ctrl_tmp.irq_state <= WRITE_SRR0; exception := '0'; @@ -828,7 +831,7 @@ begin when OP_PRTY => result := parity_result; result_en := '1'; - when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR => + when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR | OP_EXTSWSLI => result := rotator_result; if e_in.output_carry = '1' then set_carry(v.e, rotator_carry, rotator_carry); diff --git a/rotator.vhdl b/rotator.vhdl index d8a8ee9..fef9788 100644 --- a/rotator.vhdl +++ b/rotator.vhdl @@ -15,6 +15,7 @@ entity rotator is arith: in std_ulogic; clear_left: in std_ulogic; clear_right: in std_ulogic; + sign_ext_rs: in std_ulogic; result: out std_ulogic_vector(63 downto 0); carry_out: out std_ulogic ); @@ -57,13 +58,18 @@ architecture behaviour of rotator is begin rotator_0: process(all) + variable hi32: std_ulogic_vector(31 downto 0); begin -- First replicate bottom 32 bits to both halves if 32-bit if is_32bit = '1' then - repl32 <= rs(31 downto 0) & rs(31 downto 0); - else - repl32 <= rs; + hi32 := rs(31 downto 0); + elsif sign_ext_rs = '1' then + -- sign extend bottom 32 bits + hi32 := (others => rs(31)); + else + hi32 := rs(63 downto 32); end if; + repl32 <= hi32 & rs(31 downto 0); -- Negate shift count for right shifts if right_shift = '1' then diff --git a/rotator_tb.vhdl b/rotator_tb.vhdl index 3cb46b0..62a09ce 100644 --- a/rotator_tb.vhdl +++ b/rotator_tb.vhdl @@ -19,6 +19,7 @@ architecture behave of rotator_tb is signal is_32bit, right_shift, arith, clear_left, clear_right: std_ulogic := '0'; signal result: std_ulogic_vector(63 downto 0); signal carry_out: std_ulogic; + signal extsw: std_ulogic; begin rotator_0: entity work.rotator @@ -32,6 +33,7 @@ begin arith => arith, clear_left => clear_left, clear_right => clear_right, + sign_ext_rs => extsw, result => result, carry_out => carry_out ); @@ -48,6 +50,7 @@ begin arith <= '0'; clear_left <= '1'; clear_right <= '1'; + extsw <= '0'; rlwnm_loop : for i in 0 to 1000 loop rs <= pseudorand(64); shift <= pseudorand(7); @@ -263,6 +266,31 @@ begin report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result); end loop; + -- extswsli + report "test extswsli"; + ra <= (others => '0'); + is_32bit <= '0'; + right_shift <= '0'; + arith <= '0'; + clear_left <= '0'; + clear_right <= '0'; + extsw <= '1'; + extswsli_loop : for i in 0 to 1000 loop + rs <= pseudorand(64); + shift <= '0' & pseudorand(6); + wait for clk_period; + behave_ra := rs; + behave_ra(63 downto 32) := (others => rs(31)); + behave_ra := std_ulogic_vector(shift_left(unsigned(behave_ra), + to_integer(unsigned(shift)))); + --report "rs = " & to_hstring(rs); + --report "ra = " & to_hstring(ra); + --report "shift = " & to_hstring(shift); + --report "result = " & to_hstring(carry_out & result); + assert behave_ra = result + report "bad extswsli expected " & to_hstring(behave_ra) & " got " & to_hstring(result); + end loop; + assert false report "end of test" severity failure; wait; end process;