+ -- Compute misc_result
+ case current.sub_select is
+ when "000" =>
+ misc_result <= (others => '0');
+ when "001" =>
+ -- addg6s
+ addg6s := (others => '0');
+ for i in 0 to 14 loop
+ lo := i * 4;
+ hi := (i + 1) * 4;
+ if (a_in(hi) xor b_in(hi) xor sum_with_carry(hi)) = '0' then
+ addg6s(lo + 3 downto lo) := "0110";
+ end if;
+ end loop;
+ if sum_with_carry(64) = '0' then
+ addg6s(63 downto 60) := "0110";
+ end if;
+ misc_result <= addg6s;
+ when "010" =>
+ -- isel
+ crbit := to_integer(unsigned(insn_bc(e_in.insn)));
+ if cr_in(31-crbit) = '1' then
+ isel_result := a_in;
+ else
+ isel_result := b_in;
+ end if;
+ misc_result <= isel_result;
+ when "011" =>
+ -- darn
+ darn := (others => '1');
+ if random_err = '0' then
+ case e_in.insn(17 downto 16) is
+ when "00" =>
+ darn := x"00000000" & random_cond(31 downto 0);
+ when "10" =>
+ darn := random_raw;
+ when others =>
+ darn := random_cond;
+ end case;
+ end if;
+ misc_result <= darn;
+ when "100" =>
+ -- mfmsr
+ misc_result <= ctrl.msr;
+ when "101" =>
+ if e_in.insn(20) = '0' then
+ -- mfcr
+ mfcr_result := x"00000000" & cr_in;
+ else
+ -- mfocrf
+ crnum := fxm_to_num(insn_fxm(e_in.insn));
+ mfcr_result := (others => '0');
+ for i in 0 to 7 loop
+ lo := (7-i)*4;
+ hi := lo + 3;
+ if crnum = i then
+ mfcr_result(hi downto lo) := cr_in(hi downto lo);
+ end if;
+ end loop;
+ end if;
+ misc_result <= mfcr_result;
+ when "110" =>
+ -- setb
+ bfa := insn_bfa(e_in.insn);
+ crbit := to_integer(unsigned(bfa)) * 4;
+ setb_result := (others => '0');
+ if cr_in(31 - crbit) = '1' then
+ setb_result := (others => '1');
+ elsif cr_in(30 - crbit) = '1' then
+ setb_result(0) := '1';
+ end if;
+ misc_result <= setb_result;
+ when others =>
+ misc_result <= (others => '0');
+ end case;
+
+ -- compute comparison results
+ -- Note, we have done RB - RA, not RA - RB
+ if e_in.insn_type = OP_CMP then
+ l := insn_l(e_in.insn);
+ else
+ l := not e_in.is_32bit;
+ end if;
+ zerolo := not (or (a_in(31 downto 0) xor b_in(31 downto 0)));
+ zerohi := not (or (a_in(63 downto 32) xor b_in(63 downto 32)));
+ if zerolo = '1' and (l = '0' or zerohi = '1') then
+ -- values are equal
+ trapval := "00100";
+ else
+ if l = '1' then
+ -- 64-bit comparison
+ msb_a := a_in(63);
+ msb_b := b_in(63);
+ else
+ -- 32-bit comparison
+ msb_a := a_in(31);
+ msb_b := b_in(31);
+ end if;
+ if msb_a /= msb_b then
+ -- Subtraction might overflow, but
+ -- comparison is clear from MSB difference.
+ -- for signed, 0 is greater; for unsigned, 1 is greater
+ trapval := msb_a & msb_b & '0' & msb_b & msb_a;
+ else
+ -- Subtraction cannot overflow since MSBs are equal.
+ -- carry = 1 indicates RA is smaller (signed or unsigned)
+ a_lt := (not l and carry_32) or (l and carry_64);
+ trapval := a_lt & not a_lt & '0' & a_lt & not a_lt;
+ end if;
+ end if;
+