-- generate DSI or DSegI for load/store exceptions
-- or ISI or ISegI for instruction fetch exceptions
if l_in.exception = '1' then
- if l_in.instr_fault = '0' then
+ if l_in.alignment = '1' then
+ v.f.redirect_nia := std_logic_vector(to_unsigned(16#600#, 64));
+ elsif l_in.instr_fault = '0' then
if l_in.segment_fault = '0' then
v.f.redirect_nia := std_logic_vector(to_unsigned(16#300#, 64));
else
dar : std_ulogic_vector(63 downto 0);
dsisr : std_ulogic_vector(31 downto 0);
instr_fault : std_ulogic;
+ align_intr : std_ulogic;
sprval : std_ulogic_vector(63 downto 0);
busy : std_ulogic;
wait_dcache : std_ulogic;
variable dsisr : std_ulogic_vector(31 downto 0);
variable mmu_mtspr : std_ulogic;
variable itlb_fault : std_ulogic;
+ variable misaligned : std_ulogic;
begin
v := r;
req := '0';
when TLBIE_WAIT =>
when COMPLETE =>
+ exception := r.align_intr;
end case;
v.dcbz := '0';
v.tlbie := '0';
v.instr_fault := '0';
+ v.align_intr := '0';
v.dwords_done := '0';
v.last_dword := '1';
v.write_reg := l_in.write_reg;
v.first_bytes := byte_sel;
v.second_bytes := long_sel(15 downto 8);
+ -- check alignment for larx/stcx
+ misaligned := or (std_ulogic_vector(unsigned(l_in.length(2 downto 0)) - 1) and addr(2 downto 0));
+ v.align_intr := l_in.reserve and misaligned;
+
case l_in.op is
when OP_STORE =>
req := '1';
-- Allow an extra cycle for RA update on loads
v.extra_cycle := l_in.update;
when OP_DCBZ =>
+ v.align_intr := v.nc;
req := '1';
v.dcbz := '1';
when OP_TLBIE =>
end case;
if req = '1' then
- if long_sel(15 downto 8) = "00000000" then
+ if v.align_intr = '1' then
+ v.state := COMPLETE;
+ elsif long_sel(15 downto 8) = "00000000" then
v.state := ACK_WAIT;
else
v.state := SECOND_REQ;
end if;
-- Update outputs to dcache
- d_out.valid <= req;
+ d_out.valid <= req and not v.align_intr;
d_out.load <= v.load;
d_out.dcbz <= v.dcbz;
d_out.nc <= v.nc;
-- update exception info back to execute1
e_out.busy <= busy;
e_out.exception <= exception;
+ e_out.alignment <= r.align_intr;
e_out.instr_fault <= r.instr_fault;
e_out.invalid <= m_in.invalid;
e_out.badtree <= m_in.badtree;
e_out.segment_fault <= m_in.segerr;
if exception = '1' and r.instr_fault = '0' then
v.dar := addr;
- if m_in.segerr = '0' then
+ if m_in.segerr = '0' and r.align_intr = '0' then
v.dsisr := dsisr;
end if;
end if;