mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-13 07:09:54 +00:00
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>
This commit is contained in:
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#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#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#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#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#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
|
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: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
|
||||||
signal ctrl_tmp: 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 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_result: std_ulogic_vector(63 downto 0);
|
||||||
signal rotator_carry: std_ulogic;
|
signal rotator_carry: std_ulogic;
|
||||||
signal logical_result: std_ulogic_vector(63 downto 0);
|
signal logical_result: std_ulogic_vector(63 downto 0);
|
||||||
@ -174,6 +175,7 @@ begin
|
|||||||
arith => e_in.is_signed,
|
arith => e_in.is_signed,
|
||||||
clear_left => rot_clear_left,
|
clear_left => rot_clear_left,
|
||||||
clear_right => rot_clear_right,
|
clear_right => rot_clear_right,
|
||||||
|
sign_ext_rs => rot_sign_ext,
|
||||||
result => rotator_result,
|
result => rotator_result,
|
||||||
carry_out => rotator_carry
|
carry_out => rotator_carry
|
||||||
);
|
);
|
||||||
@ -429,6 +431,7 @@ begin
|
|||||||
right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
|
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_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_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;
|
ctrl_tmp.irq_state <= WRITE_SRR0;
|
||||||
exception := '0';
|
exception := '0';
|
||||||
@ -828,7 +831,7 @@ begin
|
|||||||
when OP_PRTY =>
|
when OP_PRTY =>
|
||||||
result := parity_result;
|
result := parity_result;
|
||||||
result_en := '1';
|
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;
|
result := rotator_result;
|
||||||
if e_in.output_carry = '1' then
|
if e_in.output_carry = '1' then
|
||||||
set_carry(v.e, rotator_carry, rotator_carry);
|
set_carry(v.e, rotator_carry, rotator_carry);
|
||||||
|
|||||||
12
rotator.vhdl
12
rotator.vhdl
@ -15,6 +15,7 @@ entity rotator is
|
|||||||
arith: in std_ulogic;
|
arith: in std_ulogic;
|
||||||
clear_left: in std_ulogic;
|
clear_left: in std_ulogic;
|
||||||
clear_right: in std_ulogic;
|
clear_right: in std_ulogic;
|
||||||
|
sign_ext_rs: in std_ulogic;
|
||||||
result: out std_ulogic_vector(63 downto 0);
|
result: out std_ulogic_vector(63 downto 0);
|
||||||
carry_out: out std_ulogic
|
carry_out: out std_ulogic
|
||||||
);
|
);
|
||||||
@ -57,13 +58,18 @@ architecture behaviour of rotator is
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
rotator_0: process(all)
|
rotator_0: process(all)
|
||||||
|
variable hi32: std_ulogic_vector(31 downto 0);
|
||||||
begin
|
begin
|
||||||
-- First replicate bottom 32 bits to both halves if 32-bit
|
-- First replicate bottom 32 bits to both halves if 32-bit
|
||||||
if is_32bit = '1' then
|
if is_32bit = '1' then
|
||||||
repl32 <= rs(31 downto 0) & rs(31 downto 0);
|
hi32 := rs(31 downto 0);
|
||||||
else
|
elsif sign_ext_rs = '1' then
|
||||||
repl32 <= rs;
|
-- sign extend bottom 32 bits
|
||||||
|
hi32 := (others => rs(31));
|
||||||
|
else
|
||||||
|
hi32 := rs(63 downto 32);
|
||||||
end if;
|
end if;
|
||||||
|
repl32 <= hi32 & rs(31 downto 0);
|
||||||
|
|
||||||
-- Negate shift count for right shifts
|
-- Negate shift count for right shifts
|
||||||
if right_shift = '1' then
|
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 is_32bit, right_shift, arith, clear_left, clear_right: std_ulogic := '0';
|
||||||
signal result: std_ulogic_vector(63 downto 0);
|
signal result: std_ulogic_vector(63 downto 0);
|
||||||
signal carry_out: std_ulogic;
|
signal carry_out: std_ulogic;
|
||||||
|
signal extsw: std_ulogic;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
rotator_0: entity work.rotator
|
rotator_0: entity work.rotator
|
||||||
@ -32,6 +33,7 @@ begin
|
|||||||
arith => arith,
|
arith => arith,
|
||||||
clear_left => clear_left,
|
clear_left => clear_left,
|
||||||
clear_right => clear_right,
|
clear_right => clear_right,
|
||||||
|
sign_ext_rs => extsw,
|
||||||
result => result,
|
result => result,
|
||||||
carry_out => carry_out
|
carry_out => carry_out
|
||||||
);
|
);
|
||||||
@ -48,6 +50,7 @@ begin
|
|||||||
arith <= '0';
|
arith <= '0';
|
||||||
clear_left <= '1';
|
clear_left <= '1';
|
||||||
clear_right <= '1';
|
clear_right <= '1';
|
||||||
|
extsw <= '0';
|
||||||
rlwnm_loop : for i in 0 to 1000 loop
|
rlwnm_loop : for i in 0 to 1000 loop
|
||||||
rs <= pseudorand(64);
|
rs <= pseudorand(64);
|
||||||
shift <= pseudorand(7);
|
shift <= pseudorand(7);
|
||||||
@ -263,6 +266,31 @@ begin
|
|||||||
report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result);
|
report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result);
|
||||||
end loop;
|
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;
|
assert false report "end of test" severity failure;
|
||||||
wait;
|
wait;
|
||||||
end process;
|
end process;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user