virt_mode: std_ulogic;
priv_mode: std_ulogic;
big_endian: std_ulogic;
+ mode_32bit: std_ulogic;
redirect_nia: std_ulogic_vector(63 downto 0);
end record;
constant Execute1ToFetch1Init : Execute1ToFetch1Type := (redirect => '0', virt_mode => '0',
priv_mode => '0', big_endian => '0',
- others => (others => '0'));
+ mode_32bit => '0', others => (others => '0'));
type Execute1ToLoadstore1Type is record
valid : std_ulogic;
rc : std_ulogic; -- set for stcx.
virt_mode : std_ulogic; -- do translation through TLB
priv_mode : std_ulogic; -- privileged mode (MSR[PR] = 0)
+ mode_32bit : std_ulogic; -- trim addresses to 32 bits
end record;
constant Execute1ToLoadstore1Init : Execute1ToLoadstore1Type := (valid => '0', op => OP_ILLEGAL, ci => '0', byte_reverse => '0',
sign_extend => '0', update => '0', xerc => xerc_init,
reserve => '0', rc => '0', virt_mode => '0', priv_mode => '0',
nia => (others => '0'), insn => (others => '0'),
addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'), length => (others => '0'),
- others => (others => '0'));
+ mode_32bit => '0', others => (others => '0'));
type Loadstore1ToExecute1Type is record
busy : std_ulogic;
type Execute1ToWritebackType is record
valid: std_ulogic;
rc : std_ulogic;
+ mode_32bit : std_ulogic;
write_enable : std_ulogic;
write_reg: gspr_index_t;
write_data: std_ulogic_vector(63 downto 0);
exc_write_reg : gspr_index_t;
exc_write_data : std_ulogic_vector(63 downto 0);
end record;
- constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', write_enable => '0',
+ constant Execute1ToWritebackInit : Execute1ToWritebackType := (valid => '0', rc => '0', mode_32bit => '0', write_enable => '0',
write_cr_enable => '0', exc_write_enable => '0',
write_xerc_enable => '0', xerc => xerc_init,
write_data => (others => '0'), write_cr_mask => (others => '0'),
v.terminate := '0';
icache_inval <= '0';
v.busy := '0';
- -- send MSR[IR], ~MSR[PR] and ~MSR[LE] up to fetch1
+ -- send MSR[IR], ~MSR[PR], ~MSR[LE] and ~MSR[SF] up to fetch1
v.f.virt_mode := ctrl.msr(MSR_IR);
v.f.priv_mode := not ctrl.msr(MSR_PR);
v.f.big_endian := not ctrl.msr(MSR_LE);
+ v.f.mode_32bit := not ctrl.msr(MSR_SF);
-- Next insn adder used in a couple of places
next_nia := std_ulogic_vector(unsigned(e_in.nia) + 4);
v.last_nia := e_in.nia;
end if;
+ v.e.mode_32bit := not ctrl.msr(MSR_SF);
+
if ctrl.irq_state = WRITE_SRR1 then
v.e.exc_write_reg := fast_spr_num(SPR_SRR1);
v.e.exc_write_data := ctrl.srr1;
v.f.virt_mode := a_in(MSR_IR) or a_in(MSR_PR);
v.f.priv_mode := not a_in(MSR_PR);
v.f.big_endian := not a_in(MSR_LE);
+ v.f.mode_32bit := not a_in(MSR_SF);
-- Can't use msr_copy here because the partial function MSR
-- bits should be left unchanged, not zeroed.
ctrl_tmp.msr(63 downto 31) <= a_in(63 downto 31);
v.f.priv_mode := '1';
-- XXX need an interrupt LE bit here, e.g. from LPCR
v.f.big_endian := '0';
+ v.f.mode_32bit := '0';
end if;
if v.f.redirect = '1' then
end if;
lv.virt_mode := ctrl.msr(MSR_DR);
lv.priv_mode := not ctrl.msr(MSR_PR);
+ lv.mode_32bit := not ctrl.msr(MSR_SF);
-- Update registers
rin <= v;
type stop_state_t is (RUNNING, STOPPED, RESTARTING);
type reg_internal_t is record
stop_state: stop_state_t;
+ mode_32bit: std_ulogic;
end record;
signal r, r_next : Fetch1ToIcacheType;
signal r_int, r_next_int : reg_internal_t;
" IR:" & std_ulogic'image(r_next.virt_mode) &
" P:" & std_ulogic'image(r_next.priv_mode) &
" E:" & std_ulogic'image(r_next.big_endian) &
+ " 32:" & std_ulogic'image(r_next_int.mode_32bit) &
" R:" & std_ulogic'image(e_in.redirect) & std_ulogic'image(d_in.redirect) &
" S:" & std_ulogic'image(stall_in) &
" T:" & std_ulogic'image(stop_in) &
v.priv_mode := '1';
v.big_endian := '0';
v_int.stop_state := RUNNING;
+ v_int.mode_32bit := '0';
elsif e_in.redirect = '1' then
v.nia := e_in.redirect_nia(63 downto 2) & "00";
+ if e_in.mode_32bit = '1' then
+ v.nia(63 downto 32) := (others => '0');
+ end if;
v.virt_mode := e_in.virt_mode;
v.priv_mode := e_in.priv_mode;
v.big_endian := e_in.big_endian;
+ v_int.mode_32bit := e_in.mode_32bit;
elsif d_in.redirect = '1' then
v.nia := d_in.redirect_nia(63 downto 2) & "00";
+ if r_int.mode_32bit = '1' then
+ v.nia(63 downto 32) := (others => '0');
+ end if;
elsif stall_in = '0' then
-- For debug stop/step to work properly we need a little bit of
end case;
if increment then
- v.nia := std_logic_vector(unsigned(v.nia) + 4);
+ if r_int.mode_32bit = '0' then
+ v.nia := std_ulogic_vector(unsigned(r.nia) + 4);
+ else
+ v.nia := x"00000000" & std_ulogic_vector(unsigned(r.nia(31 downto 0)) + 4);
+ end if;
v.sequential := '1';
end if;
end if;
wait_mmu : std_ulogic;
do_update : std_ulogic;
extra_cycle : std_ulogic;
+ mode_32bit : std_ulogic;
end record;
type byte_sel_t is array(0 to 7) of std_ulogic;
exception := '0';
if r.dwords_done = '1' or r.state = SECOND_REQ then
- maddr := next_addr;
+ addr := next_addr;
byte_sel := r.second_bytes;
else
- maddr := r.addr;
+ addr := r.addr;
byte_sel := r.first_bytes;
end if;
- addr := maddr;
+ if r.mode_32bit = '1' then
+ addr(63 downto 32) := (others => '0');
+ end if;
+ maddr := addr;
case r.state is
when IDLE =>
-- Note that l_in.valid is gated with busy inside execute1
if l_in.valid = '1' then
v.addr := lsu_sum;
+ v.mode_32bit := l_in.mode_32bit;
v.load := '0';
v.dcbz := '0';
v.tlbie := '0';
v.extra_cycle := '0';
addr := lsu_sum;
+ if l_in.mode_32bit = '1' then
+ addr(63 downto 32) := (others => '0');
+ end if;
maddr := l_in.addr2; -- address from RB for tlbie
-- XXX Temporary hack. Mark the op as non-cachable if the address
-- Perform CR0 update for RC forms
-- Note that loads never have a form with an RC bit, therefore this can test e_in.write_data
if e_in.rc = '1' and e_in.write_enable = '1' then
- sign := e_in.write_data(63);
- zero := not (or e_in.write_data);
+ zero := not (or e_in.write_data(31 downto 0));
+ if e_in.mode_32bit = '0' then
+ sign := e_in.write_data(63);
+ zero := zero and not (or e_in.write_data(63 downto 32));
+ else
+ sign := e_in.write_data(31);
+ end if;
c_out.write_cr_enable <= '1';
c_out.write_cr_mask <= num_to_fxm(0);
cf(3) := sign;