diff --git a/decode1.vhdl b/decode1.vhdl index b4e7d26..51a2643 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -84,14 +84,14 @@ architecture behaviour of decode1 is 2#1000010000# => '1', -- bcctr 2#0000010000# => '1', -- bclr 2#1000110000# => '0', -- bctar - 2#0100000001# => '0', -- crand - 2#0010000001# => '0', -- crandc - 2#0100100001# => '0', -- creqv - 2#0011100001# => '0', -- crnand - 2#0000100001# => '0', -- crnor - 2#0111000001# => '0', -- cror - 2#0011000001# => '0', -- crorc - 2#0110100001# => '0', -- crxor + 2#0100000001# => '1', -- crand + 2#0010000001# => '1', -- crandc + 2#0100100001# => '1', -- creqv + 2#0011100001# => '1', -- crnand + 2#0000100001# => '1', -- crnor + 2#0111000001# => '1', -- cror + 2#0110100001# => '1', -- crorc + 2#0011000001# => '1', -- crxor 2#0010010110# => '1', -- isync 2#0000000000# => '1', -- mcrf others => '0' @@ -101,7 +101,7 @@ architecture behaviour of decode1 is constant decode_op_19_array : op_19_subop_array_t := ( -- unit internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl -- op in out A out in out len ext pipe - -- mcrf; cr logical ops not implemented yet + -- mcrf; and cr logical ops 2#000# => (ALU, OP_MCRF, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), -- addpcis not implemented yet 2#001# => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), diff --git a/execute1.vhdl b/execute1.vhdl index 9b14088..421bccb 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -152,6 +152,10 @@ begin variable sh32, mb32, me32 : std_ulogic_vector(4 downto 0); variable bo, bi : std_ulogic_vector(4 downto 0); variable bf, bfa : std_ulogic_vector(2 downto 0); + variable cr_op : std_ulogic_vector(9 downto 0); + variable bt, ba, bb : std_ulogic_vector(4 downto 0); + variable btnum, banum, bbnum : integer range 0 to 31; + variable crresult : std_ulogic; variable l : std_ulogic; variable next_nia : std_ulogic_vector(63 downto 0); variable carry_32, carry_64 : std_ulogic; @@ -335,24 +339,64 @@ begin end if; result_en := '1'; when OP_MCRF => - bf := insn_bf(e_in.insn); - bfa := insn_bfa(e_in.insn); - v.e.write_cr_enable := '1'; - crnum := to_integer(unsigned(bf)); - scrnum := to_integer(unsigned(bfa)); - v.e.write_cr_mask := num_to_fxm(crnum); - for i in 0 to 7 loop - lo := (7-i)*4; - hi := lo + 3; - if i = scrnum then - newcrf := e_in.cr(hi downto lo); - end if; - end loop; - for i in 0 to 7 loop - lo := i*4; - hi := lo + 3; - v.e.write_cr_data(hi downto lo) := newcrf; - end loop; + cr_op := insn_cr(e_in.insn); + report "CR OP " & to_hstring(cr_op); + if cr_op(0) = '0' then -- MCRF + bf := insn_bf(e_in.insn); + bfa := insn_bfa(e_in.insn); + v.e.write_cr_enable := '1'; + crnum := to_integer(unsigned(bf)); + scrnum := to_integer(unsigned(bfa)); + v.e.write_cr_mask := num_to_fxm(crnum); + for i in 0 to 7 loop + lo := (7-i)*4; + hi := lo + 3; + if i = scrnum then + newcrf := e_in.cr(hi downto lo); + end if; + end loop; + for i in 0 to 7 loop + lo := i*4; + hi := lo + 3; + v.e.write_cr_data(hi downto lo) := newcrf; + end loop; + else + v.e.write_cr_enable := '1'; + bt := insn_bt(e_in.insn); + ba := insn_ba(e_in.insn); + bb := insn_bb(e_in.insn); + btnum := 31 - to_integer(unsigned(bt)); + banum := 31 - to_integer(unsigned(ba)); + bbnum := 31 - to_integer(unsigned(bb)); + case cr_op(8 downto 5) is + when "1001" => -- CREQV + crresult := not(e_in.cr(banum) xor e_in.cr(bbnum)); + when "0111" => -- CRNAND + crresult := not(e_in.cr(banum) and e_in.cr(bbnum)); + when "0100" => -- CRANDC + crresult := (e_in.cr(banum) and not e_in.cr(bbnum)); + when "1000" => -- CRAND + crresult := (e_in.cr(banum) and e_in.cr(bbnum)); + when "0001" => -- CRNOR + crresult := not(e_in.cr(banum) or e_in.cr(bbnum)); + when "1101" => -- CRORC + crresult := (e_in.cr(banum) or not e_in.cr(bbnum)); + when "0110" => -- CRXOR + crresult := (e_in.cr(banum) xor e_in.cr(bbnum)); + when "1110" => -- CROR + crresult := (e_in.cr(banum) or e_in.cr(bbnum)); + when others => + report "BAD CR?"; + end case; + v.e.write_cr_mask := num_to_fxm((31-btnum) / 4); + for i in 0 to 31 loop + if i = btnum then + v.e.write_cr_data(i) := crresult; + else + v.e.write_cr_data(i) := e_in.cr(i); + end if; + end loop; + end if; when OP_MFSPR => if is_fast_spr(e_in.read_reg1) then result := e_in.read_data1; diff --git a/insn_helpers.vhdl b/insn_helpers.vhdl index f58dacd..8812044 100644 --- a/insn_helpers.vhdl +++ b/insn_helpers.vhdl @@ -20,6 +20,10 @@ package insn_helpers is function insn_bd (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bf (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bfa (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_cr (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_bt (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_ba (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_bb (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bo (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bi (insn_in : std_ulogic_vector) return std_ulogic_vector; @@ -124,6 +128,26 @@ package body insn_helpers is return insn_in(20 downto 18); end; + function insn_cr (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(10 downto 1); + end; + + function insn_bb (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(15 downto 11); + end; + + function insn_ba (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(20 downto 16); + end; + + function insn_bt (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(25 downto 21); + end; + function insn_fxm (insn_in : std_ulogic_vector) return std_ulogic_vector is begin return insn_in(19 downto 12);