@ -11,6 +11,9 @@ use work.insn_helpers.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					use work.ppc_fx_insns.all;
 
					 
					 
					 
					use work.ppc_fx_insns.all;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					entity execute1 is
 
					 
					 
					 
					entity execute1 is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    generic (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        EX1_BYPASS : boolean := true
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					        );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    port (
 
					 
					 
					 
					    port (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						clk   : in std_ulogic;
 
					 
					 
					 
						clk   : in std_ulogic;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        rst   : in std_ulogic;
 
					 
					 
					 
					        rst   : in std_ulogic;
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -46,6 +49,8 @@ architecture behaviour of execute1 is
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    signal r, rin : reg_type;
 
					 
					 
					 
					    signal r, rin : reg_type;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    signal ctrl: ctrl_t := (others => (others => '0'));
 
					 
					 
					 
					    signal ctrl: ctrl_t := (others => (others => '0'));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    signal ctrl_tmp: ctrl_t := (others => (others => '0'));
 
					 
					 
					 
					    signal ctrl_tmp: ctrl_t := (others => (others => '0'));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -109,9 +114,9 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    rotator_0: entity work.rotator
 
					 
					 
					 
					    rotator_0: entity work.rotator
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						port map (
 
					 
					 
					 
						port map (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    rs => e_in.read_data3,
 
					 
					 
					 
						    rs => c_in,
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    ra => e_in.read_data1,
 
					 
					 
					 
						    ra => a_in,
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    shift => e_in.read_data2(6 downto 0),
 
					 
					 
					 
						    shift => b_in(6 downto 0),
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    insn => e_in.insn,
 
					 
					 
					 
						    insn => e_in.insn,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    is_32bit => e_in.is_32bit,
 
					 
					 
					 
						    is_32bit => e_in.is_32bit,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    right_shift => right_shift,
 
					 
					 
					 
						    right_shift => right_shift,
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -124,8 +129,8 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    logical_0: entity work.logical
 
					 
					 
					 
					    logical_0: entity work.logical
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						port map (
 
					 
					 
					 
						port map (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    rs => e_in.read_data3,
 
					 
					 
					 
						    rs => c_in,
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
						    rb => e_in.read_data2,
 
					 
					 
					 
						    rb => b_in,
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    op => e_in.insn_type,
 
					 
					 
					 
						    op => e_in.insn_type,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    invert_in => e_in.invert_a,
 
					 
					 
					 
						    invert_in => e_in.invert_a,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    invert_out => e_in.invert_out,
 
					 
					 
					 
						    invert_out => e_in.invert_out,
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -137,7 +142,7 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    countzero_0: entity work.zero_counter
 
					 
					 
					 
					    countzero_0: entity work.zero_counter
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						port map (
 
					 
					 
					 
						port map (
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    rs => e_in.read_data3,
 
					 
					 
					 
						    rs => c_in,
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    count_right => e_in.insn(10),
 
					 
					 
					 
						    count_right => e_in.insn(10),
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    is_32bit => e_in.is_32bit,
 
					 
					 
					 
						    is_32bit => e_in.is_32bit,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    result => countzero_result
 
					 
					 
					 
						    result => countzero_result
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -158,6 +163,10 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            d_out => divider_to_x
 
					 
					 
					 
					            d_out => divider_to_x
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            );
 
					 
					 
					 
					            );
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    a_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data1 = '1' else e_in.read_data1;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					    c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    execute1_0: process(clk)
 
					 
					 
					 
					    execute1_0: process(clk)
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					    begin
 
					 
					 
					 
					    begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if rising_edge(clk) then
 
					 
					 
					 
						if rising_edge(clk) then
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -256,21 +265,21 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						if e_in.is_32bit = '1' then
 
					 
					 
					 
						if e_in.is_32bit = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    if e_in.is_signed = '1' then
 
					 
					 
					 
						    if e_in.is_signed = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data1 <= (others => e_in.read_data1(31));
 
					 
					 
					 
							x_to_multiply.data1 <= (others => a_in(31));
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data1(31 downto 0) <= e_in.read_data1(31 downto 0);
 
					 
					 
					 
							x_to_multiply.data1(31 downto 0) <= a_in(31 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data2 <= (others => e_in.read_data2(31));
 
					 
					 
					 
							x_to_multiply.data2 <= (others => b_in(31));
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data2(31 downto 0) <= e_in.read_data2(31 downto 0);
 
					 
					 
					 
							x_to_multiply.data2(31 downto 0) <= b_in(31 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    else
 
					 
					 
					 
						    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data1 <= '0' & x"00000000" & e_in.read_data1(31 downto 0);
 
					 
					 
					 
							x_to_multiply.data1 <= '0' & x"00000000" & a_in(31 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data2 <= '0' & x"00000000" & e_in.read_data2(31 downto 0);
 
					 
					 
					 
							x_to_multiply.data2 <= '0' & x"00000000" & b_in(31 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    end if;
 
					 
					 
					 
						    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						else
 
					 
					 
					 
						else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    if e_in.is_signed = '1' then
 
					 
					 
					 
						    if e_in.is_signed = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data1 <= e_in.read_data1(63) & e_in.read_data1;
 
					 
					 
					 
							x_to_multiply.data1 <= a_in(63) & a_in;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data2 <= e_in.read_data2(63) & e_in.read_data2;
 
					 
					 
					 
							x_to_multiply.data2 <= b_in(63) & b_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    else
 
					 
					 
					 
						    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data1 <= '0' & e_in.read_data1;
 
					 
					 
					 
							x_to_multiply.data1 <= '0' & a_in;
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
							x_to_multiply.data2 <= '0' & e_in.read_data2;
 
					 
					 
					 
							x_to_multiply.data2 <= '0' & b_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    end if;
 
					 
					 
					 
						    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						end if;
 
					 
					 
					 
						end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -279,23 +288,23 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        sign2 := '0';
 
					 
					 
					 
					        sign2 := '0';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        if e_in.is_signed = '1' then
 
					 
					 
					 
					        if e_in.is_signed = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            if e_in.is_32bit = '1' then
 
					 
					 
					 
					            if e_in.is_32bit = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                sign1 := e_in.read_data1(31);
 
					 
					 
					 
					                sign1 := a_in(31);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                sign2 := e_in.read_data2(31);
 
					 
					 
					 
					                sign2 := b_in(31);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					            else
 
					 
					 
					 
					            else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                sign1 := e_in.read_data1(63);
 
					 
					 
					 
					                sign1 := a_in(63);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                sign2 := e_in.read_data2(63);
 
					 
					 
					 
					                sign2 := b_in(63);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					            end if;
 
					 
					 
					 
					            end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        -- take absolute values
 
					 
					 
					 
					        -- take absolute values
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        if sign1 = '0' then
 
					 
					 
					 
					        if sign1 = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            abs1 := signed(e_in.read_data1);
 
					 
					 
					 
					            abs1 := signed(a_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        else
 
					 
					 
					 
					        else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            abs1 := - signed(e_in.read_data1);
 
					 
					 
					 
					            abs1 := - signed(a_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        if sign2 = '0' then
 
					 
					 
					 
					        if sign2 = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            abs2 := signed(e_in.read_data2);
 
					 
					 
					 
					            abs2 := signed(b_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        else
 
					 
					 
					 
					        else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            abs2 := - signed(e_in.read_data2);
 
					 
					 
					 
					            abs2 := - signed(b_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					        end if;
 
					 
					 
					 
					        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					
 
					 
					 
					 
					
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					        x_to_divider <= Execute1ToDividerInit;
 
					 
					 
					 
					        x_to_divider <= Execute1ToDividerInit;
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -358,14 +367,14 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							-- Do nothing
 
					 
					 
					 
							-- Do nothing
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_ADD | OP_CMP =>
 
					 
					 
					 
						    when OP_ADD | OP_CMP =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if e_in.invert_a = '0' then
 
					 
					 
					 
							if e_in.invert_a = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    a_inv := e_in.read_data1;
 
					 
					 
					 
							    a_inv := a_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							else
 
					 
					 
					 
							else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    a_inv := not e_in.read_data1;
 
					 
					 
					 
							    a_inv := not a_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result_with_carry := ppc_adde(a_inv, e_in.read_data2,
 
					 
					 
					 
							result_with_carry := ppc_adde(a_inv, b_in,
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
										      decode_input_carry(e_in.input_carry, v.e.xerc));
 
					 
					 
					 
										      decode_input_carry(e_in.input_carry, v.e.xerc));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result := result_with_carry(63 downto 0);
 
					 
					 
					 
							result := result_with_carry(63 downto 0);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                carry_32 := result(32) xor a_inv(32) xor e_in.read_data2(32);
 
					 
					 
					 
					                carry_32 := result(32) xor a_inv(32) xor b_in(32);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                carry_64 := result_with_carry(64);
 
					 
					 
					 
					                carry_64 := result_with_carry(64);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                if e_in.insn_type = OP_ADD then
 
					 
					 
					 
					                if e_in.insn_type = OP_ADD then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    if e_in.output_carry = '1' then
 
					 
					 
					 
					                    if e_in.output_carry = '1' then
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -373,8 +382,8 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    end if;
 
					 
					 
					 
					                    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    if e_in.oe = '1' then
 
					 
					 
					 
					                    if e_in.oe = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        set_ov(v.e,
 
					 
					 
					 
					                        set_ov(v.e,
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                               calc_ov(a_inv(63), e_in.read_data2(63), carry_64, result_with_carry(63)),
 
					 
					 
					 
					                               calc_ov(a_inv(63), b_in(63), carry_64, result_with_carry(63)),
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                               calc_ov(a_inv(31), e_in.read_data2(31), carry_32, result_with_carry(31)));
 
					 
					 
					 
					                               calc_ov(a_inv(31), b_in(31), carry_32, result_with_carry(31)));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                    end if;
 
					 
					 
					 
					                    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    result_en := '1';
 
					 
					 
					 
					                    result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                else
 
					 
					 
					 
					                else
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -385,20 +394,20 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.e.write_cr_enable := '1';
 
					 
					 
					 
					                    v.e.write_cr_enable := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    crnum := to_integer(unsigned(bf));
 
					 
					 
					 
					                    crnum := to_integer(unsigned(bf));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    v.e.write_cr_mask := num_to_fxm(crnum);
 
					 
					 
					 
					                    v.e.write_cr_mask := num_to_fxm(crnum);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    zerolo := not (or (e_in.read_data1(31 downto 0) xor e_in.read_data2(31 downto 0)));
 
					 
					 
					 
					                    zerolo := not (or (a_in(31 downto 0) xor b_in(31 downto 0)));
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                    zerohi := not (or (e_in.read_data1(63 downto 32) xor e_in.read_data2(63 downto 32)));
 
					 
					 
					 
					                    zerohi := not (or (a_in(63 downto 32) xor b_in(63 downto 32)));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                    if zerolo = '1' and (l = '0' or zerohi = '1') then
 
					 
					 
					 
					                    if zerolo = '1' and (l = '0' or zerohi = '1') then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        -- values are equal
 
					 
					 
					 
					                        -- values are equal
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        newcrf := "001" & v.e.xerc.so;
 
					 
					 
					 
					                        newcrf := "001" & v.e.xerc.so;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                    else
 
					 
					 
					 
					                    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        if l = '1' then
 
					 
					 
					 
					                        if l = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            -- 64-bit comparison
 
					 
					 
					 
					                            -- 64-bit comparison
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            msb_a := e_in.read_data1(63);
 
					 
					 
					 
					                            msb_a := a_in(63);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                            msb_b := e_in.read_data2(63);
 
					 
					 
					 
					                            msb_b := b_in(63);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                        else
 
					 
					 
					 
					                        else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            -- 32-bit comparison
 
					 
					 
					 
					                            -- 32-bit comparison
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            msb_a := e_in.read_data1(31);
 
					 
					 
					 
					                            msb_a := a_in(31);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
					                            msb_b := e_in.read_data2(31);
 
					 
					 
					 
					                            msb_b := b_in(31);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
					                        end if;
 
					 
					 
					 
					                        end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                        if msb_a /= msb_b then
 
					 
					 
					 
					                        if msb_a /= msb_b then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                            -- Subtraction might overflow, but
 
					 
					 
					 
					                            -- Subtraction might overflow, but
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -424,25 +433,25 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_B =>
 
					 
					 
					 
						    when OP_B =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							f_out.redirect <= '1';
 
					 
					 
					 
							f_out.redirect <= '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if (insn_aa(e_in.insn)) then
 
					 
					 
					 
							if (insn_aa(e_in.insn)) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
 
					 
					 
					 
							    f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							else
 
					 
					 
					 
							else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
 
					 
					 
					 
							    f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_BC =>
 
					 
					 
					 
						    when OP_BC =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							-- read_data1 is CTR
 
					 
					 
					 
							-- read_data1 is CTR
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							bo := insn_bo(e_in.insn);
 
					 
					 
					 
							bo := insn_bo(e_in.insn);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							bi := insn_bi(e_in.insn);
 
					 
					 
					 
							bi := insn_bi(e_in.insn);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if bo(4-2) = '0' then
 
					 
					 
					 
							if bo(4-2) = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := std_ulogic_vector(unsigned(e_in.read_data1) - 1);
 
					 
					 
					 
							    result := std_ulogic_vector(unsigned(a_in) - 1);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    result_en := '1';
 
					 
					 
					 
							    result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.e.write_reg := fast_spr_num(SPR_CTR);
 
					 
					 
					 
							    v.e.write_reg := fast_spr_num(SPR_CTR);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if ppc_bc_taken(bo, bi, e_in.cr, e_in.read_data1) = 1 then
 
					 
					 
					 
							if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    f_out.redirect <= '1';
 
					 
					 
					 
							    f_out.redirect <= '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    if (insn_aa(e_in.insn)) then
 
					 
					 
					 
							    if (insn_aa(e_in.insn)) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								f_out.redirect_nia <= std_ulogic_vector(signed(e_in.read_data2));
 
					 
					 
					 
								f_out.redirect_nia <= std_ulogic_vector(signed(b_in));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    else
 
					 
					 
					 
							    else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(e_in.read_data2));
 
					 
					 
					 
								f_out.redirect_nia <= std_ulogic_vector(signed(e_in.nia) + signed(b_in));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    end if;
 
					 
					 
					 
							    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_BCREG =>
 
					 
					 
					 
						    when OP_BCREG =>
 
				
			 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
							 
						
					 
					 
					@ -451,40 +460,40 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							bo := insn_bo(e_in.insn);
 
					 
					 
					 
							bo := insn_bo(e_in.insn);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							bi := insn_bi(e_in.insn);
 
					 
					 
					 
							bi := insn_bi(e_in.insn);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if bo(4-2) = '0' and e_in.insn(10) = '0' then
 
					 
					 
					 
							if bo(4-2) = '0' and e_in.insn(10) = '0' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := std_ulogic_vector(unsigned(e_in.read_data1) - 1);
 
					 
					 
					 
							    result := std_ulogic_vector(unsigned(a_in) - 1);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    result_en := '1';
 
					 
					 
					 
							    result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.e.write_reg := fast_spr_num(SPR_CTR);
 
					 
					 
					 
							    v.e.write_reg := fast_spr_num(SPR_CTR);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if ppc_bc_taken(bo, bi, e_in.cr, e_in.read_data1) = 1 then
 
					 
					 
					 
							if ppc_bc_taken(bo, bi, e_in.cr, a_in) = 1 then
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    f_out.redirect <= '1';
 
					 
					 
					 
							    f_out.redirect <= '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    f_out.redirect_nia <= e_in.read_data2(63 downto 2) & "00";
 
					 
					 
					 
							    f_out.redirect_nia <= b_in(63 downto 2) & "00";
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_CMPB =>
 
					 
					 
					 
						    when OP_CMPB =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result := ppc_cmpb(e_in.read_data3, e_in.read_data2);
 
					 
					 
					 
							result := ppc_cmpb(c_in, b_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							result_en := '1';
 
					 
					 
					 
							result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_CNTZ =>
 
					 
					 
					 
						    when OP_CNTZ =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result := countzero_result;
 
					 
					 
					 
							result := countzero_result;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result_en := '1';
 
					 
					 
					 
							result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					            when OP_EXTS =>
 
					 
					 
					 
					            when OP_EXTS =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
					                -- note data_len is a 1-hot encoding
 
					 
					 
					 
					                -- note data_len is a 1-hot encoding
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							negative := (e_in.data_len(0) and e_in.read_data3(7)) or
 
					 
					 
					 
							negative := (e_in.data_len(0) and c_in(7)) or
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								    (e_in.data_len(1) and e_in.read_data3(15)) or
 
					 
					 
					 
								    (e_in.data_len(1) and c_in(15)) or
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								    (e_in.data_len(2) and e_in.read_data3(31));
 
					 
					 
					 
								    (e_in.data_len(2) and c_in(31));
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							result := (others => negative);
 
					 
					 
					 
							result := (others => negative);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if e_in.data_len(2) = '1' then
 
					 
					 
					 
							if e_in.data_len(2) = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result(31 downto 16) := e_in.read_data3(31 downto 16);
 
					 
					 
					 
							    result(31 downto 16) := c_in(31 downto 16);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if e_in.data_len(2) = '1' or e_in.data_len(1) = '1' then
 
					 
					 
					 
							if e_in.data_len(2) = '1' or e_in.data_len(1) = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result(15 downto 8) := e_in.read_data3(15 downto 8);
 
					 
					 
					 
							    result(15 downto 8) := c_in(15 downto 8);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result(7 downto 0) := e_in.read_data3(7 downto 0);
 
					 
					 
					 
							result(7 downto 0) := c_in(7 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							result_en := '1';
 
					 
					 
					 
							result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_ISEL =>
 
					 
					 
					 
						    when OP_ISEL =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							crbit := to_integer(unsigned(insn_bc(e_in.insn)));
 
					 
					 
					 
							crbit := to_integer(unsigned(insn_bc(e_in.insn)));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if e_in.cr(31-crbit) = '1' then
 
					 
					 
					 
							if e_in.cr(31-crbit) = '1' then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := e_in.read_data1;
 
					 
					 
					 
							    result := a_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							else
 
					 
					 
					 
							else
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := e_in.read_data2;
 
					 
					 
					 
							    result := b_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							result_en := '1';
 
					 
					 
					 
							result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_MCRF =>
 
					 
					 
					 
						    when OP_MCRF =>
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -549,7 +558,7 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_MFSPR =>
 
					 
					 
					 
						    when OP_MFSPR =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							if is_fast_spr(e_in.read_reg1) then
 
					 
					 
					 
							if is_fast_spr(e_in.read_reg1) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := e_in.read_data1;
 
					 
					 
					 
							    result := a_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    if decode_spr_num(e_in.insn) = SPR_XER then
 
					 
					 
					 
							    if decode_spr_num(e_in.insn) = SPR_XER then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								-- bits 0:31 and 35:43 are treated as reserved and return 0s when read using mfxer
 
					 
					 
					 
								-- bits 0:31 and 35:43 are treated as reserved and return 0s when read using mfxer
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								result(63 downto 32) := (others => '0');
 
					 
					 
					 
								result(63 downto 32) := (others => '0');
 
				
			 
			
		
	
	
		
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
					 
					@ -596,19 +605,19 @@ begin
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    crnum := fxm_to_num(insn_fxm(e_in.insn));
 
					 
					 
					 
							    crnum := fxm_to_num(insn_fxm(e_in.insn));
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    v.e.write_cr_mask := num_to_fxm(crnum);
 
					 
					 
					 
							    v.e.write_cr_mask := num_to_fxm(crnum);
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							end if;
 
					 
					 
					 
							end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							v.e.write_cr_data := e_in.read_data3(31 downto 0);
 
					 
					 
					 
							v.e.write_cr_data := c_in(31 downto 0);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
						    when OP_MTSPR =>
 
					 
					 
					 
						    when OP_MTSPR =>
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
 
					 
					 
					 
							report "MTSPR to SPR " & integer'image(decode_spr_num(e_in.insn)) &
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    "=" & to_hstring(e_in.read_data3);
 
					 
					 
					 
							    "=" & to_hstring(c_in);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							if is_fast_spr(e_in.write_reg) then
 
					 
					 
					 
							if is_fast_spr(e_in.write_reg) then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    result := e_in.read_data3;
 
					 
					 
					 
							    result := c_in;
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
							    result_en := '1';
 
					 
					 
					 
							    result_en := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    if decode_spr_num(e_in.insn) = SPR_XER then
 
					 
					 
					 
							    if decode_spr_num(e_in.insn) = SPR_XER then
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
								v.e.xerc.so := e_in.read_data3(63-32);
 
					 
					 
					 
								v.e.xerc.so := c_in(63-32);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								v.e.xerc.ov := e_in.read_data3(63-33);
 
					 
					 
					 
								v.e.xerc.ov := c_in(63-33);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								v.e.xerc.ca := e_in.read_data3(63-34);
 
					 
					 
					 
								v.e.xerc.ca := c_in(63-34);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								v.e.xerc.ov32 := e_in.read_data3(63-44);
 
					 
					 
					 
								v.e.xerc.ov32 := c_in(63-44);
 
				
			 
			
				
				
			
		
	
		
		
			
				
					
					 
					 
					 
								v.e.xerc.ca32 := e_in.read_data3(63-45);
 
					 
					 
					 
								v.e.xerc.ca32 := c_in(63-45);
 
				
			 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 
					 
					 
								v.e.write_xerc_enable := '1';
 
					 
					 
					 
								v.e.write_xerc_enable := '1';
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							    end if;
 
					 
					 
					 
							    end if;
 
				
			 
			
		
	
		
		
			
				
					
					 
					 
					 
							else
 
					 
					 
					 
							else