2#0011000001# => '1', -- crxor
2#0010010110# => '1', -- isync
2#0000000000# => '1', -- mcrf
+ 2#0000010010# => '1', -- rfid
others => '0'
);
2#100# => (ALU, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0'),
-- isync
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'),
+ -- rfid
+ 2#101# => (ALU, OP_RFID, SPR, SPR, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'),
others => illegal_inst
);
-- 2#1000000000# mcrxr
-- 2#1001000000# mcrxrx
2#0000010011# => (ALU, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfcr/mfocrf
+ 2#0001010011# => (ALU, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mfmsr
2#0101010011# => (ALU, OP_MFSPR, SPR, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mfspr
2#0100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- modud
2#0100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0'), -- moduw
2#1100001001# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0'), -- modsd
2#1100001011# => (ALU, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0'), -- modsw
2#0010010000# => (ALU, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtcrf/mtocrf
+ 2#0010110010# => (ALU, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- mtmsrd # ignore top bits and d
2#0111010011# => (ALU, OP_MTSPR, NONE, NONE, RS, SPR, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- mtspr
2#0001001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0'), -- mulhd
2#0000001001# => (ALU, OP_MUL_H64, RA, RB, NONE, RT, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- mulhdu
-- op in out A out in out len ext pipe
constant attn_instr : decode_rom_t := (ALU, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1');
constant nop_instr : decode_rom_t := (ALU, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');
+ constant sc_instr : decode_rom_t := (ALU, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0');
constant sim_cfg_instr : decode_rom_t := (ALU, OP_SIM_CONFIG,NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1');
begin
elsif std_match(f_in.insn, "01100000000000000000000000000000") then
report "PPC_nop";
v.decode := nop_instr;
+ elsif std_match(f_in.insn, "010001--------------0000000---1-") then
+ report "PPC_sc";
+ v.decode := sc_instr;
elsif std_match(f_in.insn, "000001---------------0000000011-") then
report "PPC_SIM_CONFIG";
v.decode := sim_cfg_instr;
if is_fast_spr(v.ispr1) = '0' then
v.decode.sgl_pipe := '1';
end if;
+ elsif v.decode.insn_type = OP_RFID then
+ report "PPC RFID";
+ v.ispr1 := fast_spr_num(SPR_SRR0);
+ v.ispr2 := fast_spr_num(SPR_SRR1);
end if;
if flush_in = '1' then
OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS,
OP_EXTSWSLI, OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC,
OP_LOAD, OP_STORE, OP_MADDHD, OP_MADDHDU, OP_MADDLD, OP_MCRF,
- OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFSPR, OP_MOD,
- OP_MTCRF, OP_MTSPR, OP_MUL_L64,
+ OP_MCRXR, OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD,
+ OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64,
OP_MUL_H64, OP_MUL_H32, OP_OR,
- OP_POPCNT, OP_PRTY,
- OP_RLC, OP_RLCL, OP_RLCR, OP_SETB,
+ OP_POPCNT, OP_PRTY, OP_RFID,
+ OP_RLC, OP_RLCL, OP_RLCR, OP_SC, OP_SETB,
OP_SHL, OP_SHR,
OP_SYNC, OP_TD, OP_TDI, OP_TW,
OP_TWI, OP_XOR, OP_SIM_CONFIG
);
-
type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR);
type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR);
type input_reg_c_t is (NONE, RS);
signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
- signal ctrl: ctrl_t := (others => (others => '0'));
- signal ctrl_tmp: ctrl_t := (others => (others => '0'));
-
+ signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
+ signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
signal rotator_result: std_ulogic_vector(63 downto 0);
signal rotator_carry: std_ulogic;
end case;
end;
+ function msr_copy(msr: std_ulogic_vector(63 downto 0))
+ return std_ulogic_vector is
+ variable msr_out: std_ulogic_vector(63 downto 0);
+ begin
+ -- ISA says this:
+ -- Defined MSR bits are classified as either full func-
+ -- tion or partial function. Full function MSR bits are
+ -- saved in SRR1 or HSRR1 when an interrupt other
+ -- than a System Call Vectored interrupt occurs and
+ -- restored by rfscv, rfid, or hrfid, while partial func-
+ -- tion MSR bits are not saved or restored.
+ -- Full function MSR bits lie in the range 0:32, 37:41, and
+ -- 48:63, and partial function MSR bits lie in the range
+ -- 33:36 and 42:47.
+ msr_out := (others => '0');
+ msr_out(32 downto 0) := msr(32 downto 0);
+ msr_out(41 downto 37) := msr(41 downto 37);
+ msr_out(63 downto 48) := msr(63 downto 48);
+ return msr_out;
+ end;
+
begin
rotator_0: entity work.rotator
variable msb_a, msb_b : std_ulogic;
variable a_lt : std_ulogic;
variable lv : Execute1ToLoadstore1Type;
+ variable irq_valid : std_ulogic;
+ variable exception : std_ulogic;
begin
result := (others => '0');
result_with_carry := (others => '0');
ctrl_tmp <= ctrl;
-- FIXME: run at 512MHz not core freq
ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1);
+ ctrl_tmp.dec <= std_ulogic_vector(unsigned(ctrl.dec) - 1);
+
+ irq_valid := '0';
+ if ctrl.msr(63 - 48) = '1' and ctrl.dec(63) = '1' then
+ report "IRQ valid";
+ irq_valid := '1';
+ end if;
terminate_out <= '0';
icache_inval <= '0';
rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
- if e_in.valid = '1' then
+ ctrl_tmp.irq_state <= WRITE_SRR0;
+ exception := '0';
+
+ if ctrl.irq_state = WRITE_SRR1 then
+ v.e.write_reg := fast_spr_num(SPR_SRR1);
+ result := ctrl.srr1;
+ result_en := '1';
+ ctrl_tmp.msr(63 - 48) <= '0'; -- clear EE
+ f_out.redirect <= '1';
+ f_out.redirect_nia <= ctrl.irq_nia;
+ v.e.valid := '1';
+ report "Writing SRR1: " & to_hstring(ctrl.srr1);
+
+ elsif irq_valid = '1' then
+ -- we need two cycles to write srr0 and 1
+ -- will need more when we have to write DSISR, DAR and HIER
+ exception := '1';
+ ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#900#, 64));
+ ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+ result := e_in.nia;
+
+ elsif e_in.valid = '1' then
v.e.valid := '1';
v.e.write_reg := e_in.write_reg;
case_0: case e_in.insn_type is
when OP_ILLEGAL =>
- terminate_out <= '1';
+ -- we need two cycles to write srr0 and 1
+ -- will need more when we have to write DSISR, DAR and HIER
+ exception := '1';
+ ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#700#, 64));
+ ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+ -- Since we aren't doing Hypervisor emulation assist (0xe40) we
+ -- set bit 44 to indicate we have an illegal
+ ctrl_tmp.srr1(63 - 44) <= '1';
+ result := e_in.nia;
report "illegal";
+ when OP_SC =>
+ -- FIXME Assume everything is SC (not SCV) for now
+ -- we need two cycles to write srr0 and 1
+ -- will need more when we have to write DSISR, DAR and HIER
+ exception := '1';
+ ctrl_tmp.irq_nia <= std_logic_vector(to_unsigned(16#C00#, 64));
+ ctrl_tmp.srr1 <= msr_copy(ctrl.msr);
+ result := std_logic_vector(unsigned(e_in.nia) + 4);
+ report "sc";
when OP_ATTN =>
terminate_out <= '1';
report "ATTN";
f_out.redirect <= '1';
f_out.redirect_nia <= b_in(63 downto 2) & "00";
end if;
+
+ when OP_RFID =>
+ f_out.redirect <= '1';
+ f_out.redirect_nia <= a_in(63 downto 2) & "00"; -- srr0
+ ctrl_tmp.msr <= msr_copy(std_ulogic_vector(signed(b_in))); -- srr1
when OP_CMPB =>
result := ppc_cmpb(c_in, b_in);
result_en := '1';
end if;
end loop;
end if;
+ when OP_MFMSR =>
+ result := msr_copy(ctrl.msr);
+ result_en := '1';
when OP_MFSPR =>
+ report "MFSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
+ "=" & to_hstring(a_in);
if is_fast_spr(e_in.read_reg1) then
result := a_in;
if decode_spr_num(e_in.insn) = SPR_XER then
case decode_spr_num(e_in.insn) is
when SPR_TB =>
result := ctrl.tb;
+ when SPR_DEC =>
+ result := ctrl.dec;
when others =>
result := (others => '0');
end case;
v.e.write_cr_mask := num_to_fxm(crnum);
end if;
v.e.write_cr_data := c_in(31 downto 0);
+ when OP_MTMSRD =>
+ -- FIXME handle just the bits we need to.
+ ctrl_tmp.msr <= msr_copy(c_in);
when OP_MTSPR =>
report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
"=" & to_hstring(c_in);
v.e.write_xerc_enable := '1';
end if;
else
--- TODO: Implement slow SPRs
--- case decode_spr_num(e_in.insn) is
--- when others =>
--- end case;
+ -- slow spr
+ case decode_spr_num(e_in.insn) is
+ when SPR_DEC =>
+ ctrl_tmp.dec <= c_in;
+ when others =>
+ end case;
end if;
when OP_POPCNT =>
result := popcnt_result;
end if;
end if;
+ if exception = '1' then
+ v.e.write_reg := fast_spr_num(SPR_SRR0);
+ if e_in.valid = '1' then
+ result_en := '1';
+ ctrl_tmp.irq_state <= WRITE_SRR1;
+ stall_out <= '1';
+ v.e.valid := '0';
+ end if;
+ end if;
+
v.e.write_data := result;
v.e.write_enable := result_en;