insn: Implement isync instruction

The instruction works by redirecting fetch to nia+4 (hopefully using
the same adder used to generate LR) and doing a backflush. Along with
being single issue, this should guarantee that the next instruction
only gets fetched after the pipe's been emptied.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
pull/114/head
Benjamin Herrenschmidt 5 years ago
parent 6e0ee0b0db
commit a0d95e791e

@ -108,7 +108,7 @@ architecture behaviour of decode1 is
-- bclr, bcctr, bctar -- bclr, bcctr, bctar
2#100# => (ALU, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'), 2#100# => (ALU, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '1'),
-- isync -- isync
2#111# => (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), 2#111# => (ALU, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'),
others => illegal_inst others => illegal_inst
); );



@ -118,6 +118,7 @@ begin
variable bo, bi : std_ulogic_vector(4 downto 0); variable bo, bi : std_ulogic_vector(4 downto 0);
variable bf, bfa : std_ulogic_vector(2 downto 0); variable bf, bfa : std_ulogic_vector(2 downto 0);
variable l : std_ulogic; variable l : std_ulogic;
variable next_nia : std_ulogic_vector(63 downto 0);
begin begin
result := (others => '0'); result := (others => '0');
result_with_carry := (others => '0'); result_with_carry := (others => '0');
@ -135,6 +136,9 @@ begin
terminate_out <= '0'; terminate_out <= '0';
f_out <= Execute1ToFetch1TypeInit; f_out <= Execute1ToFetch1TypeInit;


-- Next insn adder used in a couple of places
next_nia := std_ulogic_vector(unsigned(e_in.nia) + 4);

-- rotator control signals -- rotator control signals
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';
@ -345,13 +349,17 @@ begin
-- Keep our test cases happy for now, ignore trap instructions -- Keep our test cases happy for now, ignore trap instructions
report "OP_TDI FIXME"; report "OP_TDI FIXME";


when OP_ISYNC =>
f_out.redirect <= '1';
f_out.redirect_nia <= next_nia;

when others => when others =>
terminate_out <= '1'; terminate_out <= '1';
report "illegal"; report "illegal";
end case; end case;


if e_in.lr = '1' then if e_in.lr = '1' then
ctrl_tmp.lr <= std_ulogic_vector(unsigned(e_in.nia) + 4); ctrl_tmp.lr <= next_nia;
end if; end if;


end if; end if;

Loading…
Cancel
Save