mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-04 10:24:39 +00:00
core: Implement 32-bit mode
In 32-bit mode, effective addresses are truncated to 32 bits, both for instruction fetches and data accesses, and CR0 is set for Rc=1 (record form) instructions based on the lower 32 bits of the result rather than all 64 bits. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
@@ -247,11 +247,12 @@ package common is
|
||||
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;
|
||||
@@ -273,13 +274,14 @@ package common is
|
||||
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;
|
||||
@@ -376,6 +378,7 @@ package common is
|
||||
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);
|
||||
@@ -388,7 +391,7 @@ package common is
|
||||
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'),
|
||||
|
||||
@@ -496,10 +496,11 @@ begin
|
||||
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);
|
||||
@@ -522,6 +523,8 @@ begin
|
||||
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;
|
||||
@@ -742,6 +745,7 @@ begin
|
||||
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);
|
||||
@@ -1165,6 +1169,7 @@ begin
|
||||
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
|
||||
@@ -1195,6 +1200,7 @@ begin
|
||||
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;
|
||||
|
||||
16
fetch1.vhdl
16
fetch1.vhdl
@@ -38,6 +38,7 @@ architecture behaviour of fetch1 is
|
||||
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;
|
||||
@@ -53,6 +54,7 @@ begin
|
||||
" 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) &
|
||||
@@ -84,13 +86,21 @@ begin
|
||||
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
|
||||
@@ -136,7 +146,11 @@ begin
|
||||
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;
|
||||
|
||||
@@ -84,6 +84,7 @@ architecture behave of loadstore1 is
|
||||
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;
|
||||
@@ -272,13 +273,16 @@ begin
|
||||
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 =>
|
||||
@@ -365,6 +369,7 @@ begin
|
||||
-- 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';
|
||||
@@ -389,6 +394,9 @@ begin
|
||||
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
|
||||
|
||||
@@ -99,8 +99,13 @@ begin
|
||||
-- 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;
|
||||
|
||||
Reference in New Issue
Block a user