prefixed: std_ulogic;
prefix: std_ulogic_vector(25 downto 0);
illegal_suffix: std_ulogic;
+ misaligned_prefix: std_ulogic;
insn: std_ulogic_vector(31 downto 0);
decode: decode_rom_t;
br_pred: std_ulogic; -- Branch was predicted to be taken
constant Decode1ToDecode2Init : Decode1ToDecode2Type :=
(valid => '0', stop_mark => '0', nia => (others => '0'),
prefixed => '0', prefix => (others => '0'), insn => (others => '0'),
- illegal_suffix => '0',
+ illegal_suffix => '0', misaligned_prefix => '0',
decode => decode_rom_init, br_pred => '0', big_endian => '0',
spr_info => spr_id_init, ram_spr => ram_spr_info_init,
reg_a => (others => '0'), reg_b => (others => '0'), reg_c => (others => '0'));
ramspr_write_odd : std_ulogic;
dbg_spr_access : std_ulogic;
dec_ctr : std_ulogic;
+ prefixed : std_ulogic;
+ illegal_suffix : std_ulogic;
+ misaligned_prefix : std_ulogic;
end record;
constant Decode2ToExecute1Init : Decode2ToExecute1Type :=
(valid => '0', unit => ALU, fac => NONE, insn_type => OP_ILLEGAL, instr_tag => instr_tag_init,
ramspr_wraddr => (others => '0'), ramspr_write_even => '0', ramspr_write_odd => '0',
dbg_spr_access => '0',
dec_ctr => '0',
+ prefixed => '0', illegal_suffix => '0', misaligned_prefix => '0',
others => (others => '0'));
type MultiplyInputType is record
priv_mode : std_ulogic; -- privileged mode (MSR[PR] = 0)
mode_32bit : std_ulogic; -- trim addresses to 32 bits
is_32bit : std_ulogic;
+ prefixed : std_ulogic;
repeat : std_ulogic;
second : std_ulogic;
e2stall : std_ulogic;
addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'),
write_reg => (others => '0'),
length => (others => '0'),
- mode_32bit => '0', is_32bit => '0',
+ mode_32bit => '0', is_32bit => '0', prefixed => '0',
repeat => '0', second => '0', e2stall => '0',
msr => (others => '0'));
pv.prefixed := '1';
pv.pref_ia := f_in.nia(5 downto 2);
pv.prefix := f_in.insn(25 downto 0);
- v.valid := '0';
+ -- Check if the address of the prefix mod 64 is 60;
+ -- if so we need to arrange to generate an alignment interrupt
+ if f_in.nia(5 downto 2) = "1111" then
+ v.misaligned_prefix := '1';
+ else
+ v.valid := '0';
+ end if;
end if;
decode_rom_addr <= insn_code'val(to_integer(unsigned(icode_bits)));
c_out.read <= d_in.decode.input_cr;
decode2_addrs: process(all)
+ variable dec_a, dec_b, dec_c : decode_input_reg_t;
+ variable dec_o : decode_output_reg_t;
begin
- decoded_reg_a <= decode_input_reg_init;
- decoded_reg_b <= decode_input_reg_init;
- decoded_reg_c <= decode_input_reg_init;
- decoded_reg_o <= decode_output_reg_init;
- if d_in.valid = '1' then
- decoded_reg_a <= decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, d_in.prefix, d_in.nia);
- decoded_reg_b <= decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, d_in.prefix);
- decoded_reg_c <= decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn);
- decoded_reg_o <= decode_output_reg (d_in.decode.output_reg_a, d_in.insn);
+ dec_a := decode_input_reg_a (d_in.decode.input_reg_a, d_in.insn, d_in.prefix, d_in.nia);
+ dec_b := decode_input_reg_b (d_in.decode.input_reg_b, d_in.insn, d_in.prefix);
+ dec_c := decode_input_reg_c (d_in.decode.input_reg_c, d_in.insn);
+ dec_o := decode_output_reg (d_in.decode.output_reg_a, d_in.insn);
+ if d_in.valid = '0' or d_in.illegal_suffix = '1' then
+ dec_a.reg_valid := '0';
+ dec_b.reg_valid := '0';
+ dec_c.reg_valid := '0';
+ dec_o.reg_valid := '0';
end if;
- r_out.read1_enable <= decoded_reg_a.reg_valid;
- r_out.read2_enable <= decoded_reg_b.reg_valid;
- r_out.read3_enable <= decoded_reg_c.reg_valid;
+ decoded_reg_a <= dec_a;
+ decoded_reg_b <= dec_b;
+ decoded_reg_c <= dec_c;
+ decoded_reg_o <= dec_o;
+ r_out.read1_enable <= dec_a.reg_valid;
+ r_out.read2_enable <= dec_b.reg_valid;
+ r_out.read3_enable <= dec_c.reg_valid;
end process;
v.e.result_sel := "001"; -- logical_result
end if;
end if;
+ v.e.prefixed := d_in.prefixed;
+ v.e.illegal_suffix := d_in.illegal_suffix;
+ v.e.misaligned_prefix := d_in.misaligned_prefix;
elsif dc2.e.valid = '1' then
-- dc2.busy = 1 and dc2.e.valid = 1, thus this must be a repeated instruction.
fp_exception_next : std_ulogic;
trace_next : std_ulogic;
prev_op : insn_type_t;
+ prev_prefixed : std_ulogic;
oe : std_ulogic;
mul_select : std_ulogic_vector(1 downto 0);
res2_sel : std_ulogic_vector(1 downto 0);
(e => Execute1ToWritebackInit, se => side_effect_init,
busy => '0',
fp_exception_next => '0', trace_next => '0', prev_op => OP_ILLEGAL,
+ prev_prefixed => '0',
oe => '0', mul_select => "00", res2_sel => "00",
spr_select => spr_id_init, pmu_spr_num => 5x"0",
mul_in_progress => '0', mul_finish => '0', div_in_progress => '0',
variable bo, bi : std_ulogic_vector(4 downto 0);
variable illegal : std_ulogic;
variable privileged : std_ulogic;
+ variable misaligned : std_ulogic;
variable slow_op : std_ulogic;
variable owait : std_ulogic;
variable srr1 : std_ulogic_vector(63 downto 0);
illegal := '0';
privileged := '0';
+ misaligned := e_in.misaligned_prefix;
slow_op := '0';
owait := '0';
- if ex1.msr(MSR_PR) = '1' and instr_is_privileged(e_in.insn_type, e_in.insn) then
+ if e_in.illegal_suffix = '1' then
+ illegal := '1';
+ elsif ex1.msr(MSR_PR) = '1' and instr_is_privileged(e_in.insn_type, e_in.insn) then
privileged := '1';
end if;
end if;
end case;
- if privileged = '1' then
+ if misaligned = '1' then
+ -- generate an alignment interrupt
+ -- This is higher priority than illegal because a misaligned
+ -- prefix will come down as an OP_ILLEGAL instruction.
+ v.exception := '1';
+ v.e.intr_vec := 16#600#;
+ v.e.srr1(47 - 35) := '1';
+ v.e.srr1(47 - 34) := '1';
+ if e_in.valid = '1' then
+ report "misaligned prefixed instruction interrupt";
+ end if;
+
+ elsif privileged = '1' then
-- generate a program interrupt
v.exception := '1';
+ v.e.srr1(47 - 34) := e_in.prefixed;
-- set bit 45 to indicate privileged instruction type interrupt
v.e.srr1(47 - 45) := '1';
if e_in.valid = '1' then
elsif illegal = '1' then
v.exception := '1';
+ v.e.srr1(47 - 34) := e_in.prefixed;
-- Since we aren't doing Hypervisor emulation assist (0xe40) we
-- set bit 44 to indicate we have an illegal
v.e.srr1(47 - 44) := '1';
elsif HAS_FPU and ex1.msr(MSR_FP) = '0' and e_in.fac = FPU then
-- generate a floating-point unavailable interrupt
v.exception := '1';
+ v.e.srr1(47 - 34) := e_in.prefixed;
v.e.intr_vec := 16#800#;
if e_in.valid = '1' then
report "FP unavailable interrupt";
if valid_in = '1' then
v.prev_op := e_in.insn_type;
+ v.prev_prefixed := e_in.prefixed;
end if;
-- Determine if there is any interrupt to be taken
v.e.intr_vec := 16#d00#;
v.e.srr1 := (others => '0');
v.e.srr1(47 - 33) := '1';
+ v.e.srr1(47 - 34) := ex1.prev_prefixed;
if ex1.prev_op = OP_LOAD or ex1.prev_op = OP_ICBI or ex1.prev_op = OP_ICBT or
ex1.prev_op = OP_DCBT or ex1.prev_op = OP_DCBST or ex1.prev_op = OP_DCBF then
v.e.srr1(47 - 35) := '1';
lv.priv_mode := not ex1.msr(MSR_PR);
lv.mode_32bit := not ex1.msr(MSR_SF);
lv.is_32bit := e_in.is_32bit;
+ lv.prefixed := e_in.prefixed;
lv.repeat := e_in.repeat;
lv.second := e_in.second;
lv.e2stall := fp_in.f2stall;
instr_fault : std_ulogic;
do_update : std_ulogic;
mode_32bit : std_ulogic;
+ prefixed : std_ulogic;
addr : std_ulogic_vector(63 downto 0);
byte_sel : std_ulogic_vector(7 downto 0);
second_bytes : std_ulogic_vector(7 downto 0);
constant request_init : request_t := (valid => '0', dc_req => '0', load => '0', store => '0', tlbie => '0',
dcbz => '0', read_spr => '0', write_spr => '0', mmu_op => '0',
instr_fault => '0', do_update => '0',
- mode_32bit => '0', addr => (others => '0'),
+ mode_32bit => '0', prefixed => '0',
+ addr => (others => '0'),
byte_sel => x"00", second_bytes => x"00",
store_data => (others => '0'), instr_tag => instr_tag_init,
write_reg => 6x"00", length => x"0",
v.valid := l_in.valid;
v.instr_tag := l_in.instr_tag;
v.mode_32bit := l_in.mode_32bit;
+ v.prefixed := l_in.prefixed;
v.write_reg := l_in.write_reg;
v.length := l_in.length;
v.elt_length := l_in.length;
if exception = '1' then
if r2.req.align_intr = '1' then
v.intr_vec := 16#600#;
+ v.srr1(47 - 34) := r2.req.prefixed;
v.dar := r2.req.addr;
elsif r2.req.instr_fault = '0' then
+ v.srr1(47 - 34) := r2.req.prefixed;
v.dar := r2.req.addr;
if m_in.segerr = '0' then
v.intr_vec := 16#300#;