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 <paulus@ozlabs.org>
pull/169/head
Paul Mackerras 5 years ago
parent 1ba29a407a
commit 8a0a907e2f

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

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

@ -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);
hi32 := rs(31 downto 0);
elsif sign_ext_rs = '1' then
-- sign extend bottom 32 bits
hi32 := (others => rs(31));
else
repl32 <= rs;
hi32 := rs(63 downto 32);
end if;
repl32 <= hi32 & rs(31 downto 0);

-- Negate shift count for right shifts
if right_shift = '1' then

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

Loading…
Cancel
Save