From fc58559ee82178ba3fa1a82530bd381fa9eb55ba Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 9 Aug 2022 19:48:30 +1000 Subject: [PATCH 01/22] writeback: Eliminate unintentional inferred latch By not assigning to interrupt_out.srr1 in some circumstances, the writeback_1 process creates an inferred latch, which is not desirable. Eliminate it by restructuring the code so interrupt_out.srr1 is always set, to zeroes if nothing else. Fixes: bc4d02cb0dcc ("Start removing SPRs from register file", 2022-07-12) Signed-off-by: Paul Mackerras --- writeback.vhdl | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/writeback.vhdl b/writeback.vhdl index 2f6af2c..7fef5c3 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -92,21 +92,20 @@ begin intr := e_in.interrupt or l_in.interrupt or fp_in.interrupt; interrupt_out.intr <= intr; - if intr = '1' then - srr1 := (others => '0'); - if e_in.interrupt = '1' then - vec := e_in.intr_vec; - srr1 := e_in.srr1; - elsif l_in.interrupt = '1' then - vec := l_in.intr_vec; - srr1 := l_in.srr1; - elsif fp_in.interrupt = '1' then - vec := fp_in.intr_vec; - srr1 := fp_in.srr1; - end if; - interrupt_out.srr1 <= srr1; + srr1 := (others => '0'); + if e_in.interrupt = '1' then + vec := e_in.intr_vec; + srr1 := e_in.srr1; + elsif l_in.interrupt = '1' then + vec := l_in.intr_vec; + srr1 := l_in.srr1; + elsif fp_in.interrupt = '1' then + vec := fp_in.intr_vec; + srr1 := fp_in.srr1; + end if; + interrupt_out.srr1 <= srr1; - else + if intr = '0' then if e_in.write_enable = '1' then w_out.write_reg <= e_in.write_reg; w_out.write_data <= e_in.write_data; From 795b6e2a6b022b4a9c72c51da5d83505d94f5ee1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 28 Jul 2022 20:46:59 +1000 Subject: [PATCH 02/22] Remove leftover logic for 16-byte loads and stores This removes some logic that was previously added for the 16-byte loads and stores (lq, lqarx, stq, stqcx.) and not completely removed in commit c9e838b6560f ("Remove support for lq, stq, lqarx and stqcx.", 2022-06-04). Signed-off-by: Paul Mackerras --- common.vhdl | 2 -- dcache.vhdl | 4 ++-- loadstore1.vhdl | 26 ++++++-------------------- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/common.vhdl b/common.vhdl index 4f8191e..f6cb939 100644 --- a/common.vhdl +++ b/common.vhdl @@ -525,8 +525,6 @@ package common is dcbz : std_ulogic; nc : std_ulogic; reserve : std_ulogic; - atomic : std_ulogic; -- part of a multi-transfer atomic op - atomic_last : std_ulogic; virt_mode : std_ulogic; priv_mode : std_ulogic; addr : std_ulogic_vector(63 downto 0); diff --git a/dcache.vhdl b/dcache.vhdl index 2d5ebe3..1e9fbcc 100644 --- a/dcache.vhdl +++ b/dcache.vhdl @@ -1004,10 +1004,10 @@ begin -- XXX or if r0.req.nc = '1' if r0.req.load = '1' then -- load with reservation - set_rsrv <= r0.req.atomic_last; + set_rsrv <= '1'; else -- store conditional - clear_rsrv <= r0.req.atomic_last; + clear_rsrv <= '1'; if reservation.valid = '0' or r0.req.addr(63 downto LINE_OFF_BITS) /= reservation.addr then cancel_store <= '1'; diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 439f124..726f57a 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -83,8 +83,6 @@ architecture behave of loadstore1 is update : std_ulogic; xerc : xer_common_t; reserve : std_ulogic; - atomic : std_ulogic; - atomic_last : std_ulogic; rc : std_ulogic; nc : std_ulogic; -- non-cacheable access virt_mode : std_ulogic; @@ -108,7 +106,7 @@ architecture behave of loadstore1 is elt_length => x"0", byte_reverse => '0', brev_mask => "000", sign_extend => '0', update => '0', xerc => xerc_init, reserve => '0', - atomic => '0', atomic_last => '0', rc => '0', nc => '0', + rc => '0', nc => '0', virt_mode => '0', priv_mode => '0', load_sp => '0', sprsel => "00", ric => "00", is_slbia => '0', align_intr => '0', dword_index => '0', two_dwords => '0', incomplete => '0'); @@ -439,15 +437,9 @@ begin addr := lsu_sum; if l_in.second = '1' then - if l_in.update = '0' then - -- for the second half of a 16-byte transfer, - -- use the previous address plus 8. - addr := std_ulogic_vector(unsigned(r1.addr0(63 downto 3)) + 1) & r1.addr0(2 downto 0); - else - -- for an update-form load, use the previous address - -- as the value to write back to RA. - addr := r1.addr0; - end if; + -- for an update-form load, use the previous address + -- as the value to write back to RA. + addr := r1.addr0; end if; if l_in.mode_32bit = '1' then addr(63 downto 32) := (others => '0'); @@ -474,14 +466,12 @@ begin misaligned := or (addr_mask and addr(2 downto 0)); v.align_intr := l_in.reserve and misaligned; - v.atomic := not misaligned; - v.atomic_last := not misaligned and (l_in.second or not l_in.repeat); - case l_in.op is when OP_STORE => v.store := '1'; when OP_LOAD => - if l_in.update = '0' or l_in.second = '0' then + -- Note: only RA updates have l_in.second = 1 + if l_in.second = '0' then v.load := '1'; if HAS_FPU and l_in.is_32bit = '1' then -- Allow an extra cycle for SP->DP precision conversion @@ -953,8 +943,6 @@ begin d_out.dcbz <= stage1_req.dcbz; d_out.nc <= stage1_req.nc; d_out.reserve <= stage1_req.reserve; - d_out.atomic <= stage1_req.atomic; - d_out.atomic_last <= stage1_req.atomic_last; d_out.addr <= stage1_req.addr; d_out.byte_sel <= stage1_req.byte_sel; d_out.virt_mode <= stage1_req.virt_mode; @@ -965,8 +953,6 @@ begin d_out.dcbz <= r2.req.dcbz; d_out.nc <= r2.req.nc; d_out.reserve <= r2.req.reserve; - d_out.atomic <= r2.req.atomic; - d_out.atomic_last <= r2.req.atomic_last; d_out.addr <= r2.req.addr; d_out.byte_sel <= r2.req.byte_sel; d_out.virt_mode <= r2.req.virt_mode; From 7a60c118ed6d8901012da13caff8aeded64f6cdc Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 29 Jul 2022 08:27:10 +1000 Subject: [PATCH 03/22] loadstore1: Simplify address generation in OP_FETCH_FAILED case Instead of having a multiplexer in loadstore1 in order to be able to put the instruction address into v.addr, we now set decode.input_reg_a to CIA in the decode table entry for OP_FETCH_FAILED. That means that the operand selection machinery in decode2 will supply the instruction address to loadstore1 on the lv.addr1 input and no special case is needed in loadstore1. This saves a few LUTs (~40 on the Artix-7). Signed-off-by: Paul Mackerras --- common.vhdl | 3 +-- decode1.vhdl | 2 +- execute1.vhdl | 1 - loadstore1.vhdl | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/common.vhdl b/common.vhdl index f6cb939..685d0c3 100644 --- a/common.vhdl +++ b/common.vhdl @@ -476,7 +476,6 @@ package common is type Execute1ToLoadstore1Type is record valid : std_ulogic; op : insn_type_t; -- what ld/st or m[tf]spr or TLB op to do - nia : std_ulogic_vector(63 downto 0); insn : std_ulogic_vector(31 downto 0); instr_tag : instr_tag_t; addr1 : std_ulogic_vector(63 downto 0); @@ -504,7 +503,7 @@ package common is (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'), + insn => (others => '0'), instr_tag => instr_tag_init, addr1 => (others => '0'), addr2 => (others => '0'), data => (others => '0'), write_reg => (others => '0'), diff --git a/decode1.vhdl b/decode1.vhdl index b2c6059..fda2ce2 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -527,7 +527,7 @@ architecture behaviour of decode1 is -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt -- op in out A out in out len ext pipe constant nop_instr : decode_rom_t := (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); - constant fetch_fail_inst: decode_rom_t := (LDST, NONE, OP_FETCH_FAILED, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); + constant fetch_fail_inst: decode_rom_t := (LDST, NONE, OP_FETCH_FAILED, CIA, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is variable ret : ram_spr_info; diff --git a/execute1.vhdl b/execute1.vhdl index fd20c01..0eb0b7f 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -1554,7 +1554,6 @@ begin -- Outputs to loadstore1 (async) lv.op := e_in.insn_type; - lv.nia := e_in.nia; lv.instr_tag := e_in.instr_tag; lv.addr1 := a_in; lv.addr2 := b_in; diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 726f57a..7071582 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -497,7 +497,6 @@ begin when OP_FETCH_FAILED => -- send it to the MMU to do the radix walk v.instr_fault := '1'; - v.addr := l_in.nia; v.mmu_op := '1'; when others => end case; From 03ca9b5dd5ef466f0a263ac2e9caaeb4310a0d76 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 May 2022 11:59:14 +1000 Subject: [PATCH 04/22] FPU: Minor fix and simplifications In preparation for an explicit exponent data path. The fix is that fre[s] needs to negate the exponent after renomalization rather than before, otherwise the exponent adjustment done by the renormalization is in the wrong direction. Signed-off-by: Paul Mackerras --- fpu.vhdl | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/fpu.vhdl b/fpu.vhdl index c06c4bd..d838872 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -56,7 +56,7 @@ architecture behaviour of fpu is ADD_1, ADD_SHIFT, ADD_2, ADD_3, CMP_1, CMP_2, MULT_1, - FMADD_1, FMADD_2, FMADD_3, + FMADD_0, FMADD_1, FMADD_2, FMADD_3, FMADD_4, FMADD_5, FMADD_6, LOOKUP, DIV_2, DIV_3, DIV_4, DIV_5, DIV_6, @@ -1538,9 +1538,9 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_b := '1'; + v.result_exp := r.b.exponent; case r.b.class is when FINITE => - v.result_exp := - r.b.exponent; if r.b.mantissa(UNIT_BIT) = '0' then v.state := RENORM_B; else @@ -1600,7 +1600,7 @@ begin -- else AIN_B v.result_sign := r.a.negative; v.result_class := r.a.class; - v.result_exp := r.a.exponent; + v.result_exp := r.a.exponent + r.c.exponent; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_a := '1'; @@ -1610,8 +1610,6 @@ begin if r.a.class = FINITE and r.c.class = FINITE and (r.b.class = FINITE or r.b.class = ZERO) then v.is_subtract := not is_add; - mulexp := r.a.exponent + r.c.exponent; - v.result_exp := mulexp; -- Make sure A and C are normalized if r.a.mantissa(UNIT_BIT) = '0' then v.state := RENORM_A; @@ -1627,15 +1625,10 @@ begin -- addend is bigger, do multiply first v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2)); f_to_multiply.valid <= '1'; - v.state := FMADD_1; + v.state := FMADD_0; else - -- product is bigger, shift B right and use it as the - -- addend to the multiplier - v.shift := r.b.exponent - mulexp + to_signed(64, EXP_BITS); - -- for subtract, multiplier does B - A * C - v.result_sign := not (r.a.negative xor r.c.negative xor r.insn(2) xor is_add); - v.result_exp := r.b.exponent; - v.state := FMADD_2; + -- product is bigger, shift B first + v.state := FMADD_1; end if; else if r.a.class = NAN or r.b.class = NAN or r.c.class = NAN then @@ -1715,11 +1708,7 @@ begin when RENORM_B2 => set_b := '1'; - if r.is_sqrt = '0' then - v.result_exp := r.result_exp + r.shift; - else - v.result_exp := new_exp; - end if; + v.result_exp := new_exp; v.opsel_a := AIN_B; v.state := LOOKUP; @@ -1830,7 +1819,7 @@ begin v.state := FINISH; end if; - when FMADD_1 => + when FMADD_0 => -- Addend is bigger here v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2)); -- note v.shift is at most -2 here @@ -1844,6 +1833,15 @@ begin v.state := ADD_SHIFT; end if; + when FMADD_1 => + -- product is bigger here + -- shift B right and use it as the addend to the multiplier + v.shift := r.b.exponent - r.result_exp + to_signed(64, EXP_BITS); + -- for subtract, multiplier does B - A * C + v.result_sign := r.a.negative xor r.c.negative xor r.insn(2) xor r.is_subtract; + v.result_exp := r.b.exponent; + v.state := FMADD_2; + when FMADD_2 => -- Product is potentially bigger here -- r.shift = addend exp - product exp + 64, r.r = r.b.mantissa @@ -1993,6 +1991,7 @@ begin v.state := FINISH; when FRE_1 => + v.result_exp := - r.result_exp; opsel_r <= RES_MISC; misc_sel <= "0111"; v.shift := to_signed(1, EXP_BITS); From 8da05e5331914674bd3e66a5728d435228d3ebf7 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 14 May 2022 21:46:40 +1000 Subject: [PATCH 05/22] FPU: Make an explicit exponent data path With this, the large case statement sets values for a set of control signals, which then control multiplexers and adders that generate values for v.result_exp and v.shift. The plan is for the case statement to turn into a microcode ROM eventually. The value of v.result_exp is the sum of two values, either of which can be negated (but not both). The first value can be chosen from the result exponent, A exponent, B exponent arithmetically shifted right one bit, or 0. The second value can be chosen from new_exp (which is r.result_exp - r.shift), B exponent, C exponent or a constant. The choices for the constant are 0, 56, the maximum exponent (max_exp) or the exponent bias for trap-enabled overflow conditions (bias_exp). These choices are controlled by the signals re_sel1, re_neg1, re_sel2 and re_neg2, and the sum is written into v.result_exp if re_set_result is 1. For v.shift we also compute the sum of two values, either of which can be negated (but not both). The first value can be chosen from new_exp, B exponent, r.shift, or 0. The second value can be chosen from the A exponent or a constant. The possible constants are 0, 1, 4, 8, 32, 52, 56, 63, 64, or the minimum exponent (min_exp). These choices are controlled by the signals rs_sel1, rs_neg1, rs_sel2 and rs_neg2. After the adder there is a multiplexer which selects either the sum or a shift count for normalization (derived from a count leading zeroes operation on R) to be written into v.shift. The count-leading-zeroes result does not go through the adder for timing reasons. In order to simplify the logic and help improve timing, settings of the control signals have been made unconditional in a state in many places, even if those settings are only required when some condition is met. Signed-off-by: Paul Mackerras --- fpu.vhdl | 490 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 395 insertions(+), 95 deletions(-) diff --git a/fpu.vhdl b/fpu.vhdl index d838872..44ab9aa 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -232,6 +232,55 @@ architecture behaviour of fpu is constant MULADD_A : std_ulogic_vector(1 downto 0) := "10"; constant MULADD_RS : std_ulogic_vector(1 downto 0) := "11"; + -- control signals and values for exponent data path + constant REXP1_ZERO : std_ulogic_vector(1 downto 0) := "00"; + constant REXP1_R : std_ulogic_vector(1 downto 0) := "01"; + constant REXP1_A : std_ulogic_vector(1 downto 0) := "10"; + constant REXP1_BHALF : std_ulogic_vector(1 downto 0) := "11"; + + constant REXP2_CON : std_ulogic_vector(1 downto 0) := "00"; + constant REXP2_NE : std_ulogic_vector(1 downto 0) := "01"; + constant REXP2_C : std_ulogic_vector(1 downto 0) := "10"; + constant REXP2_B : std_ulogic_vector(1 downto 0) := "11"; + + constant RECON2_ZERO : std_ulogic_vector(1 downto 0) := "00"; + constant RECON2_UNIT : std_ulogic_vector(1 downto 0) := "01"; + constant RECON2_BIAS : std_ulogic_vector(1 downto 0) := "10"; + constant RECON2_MAX : std_ulogic_vector(1 downto 0) := "11"; + + signal re_sel1 : std_ulogic_vector(1 downto 0); + signal re_sel2 : std_ulogic_vector(1 downto 0); + signal re_con2 : std_ulogic_vector(1 downto 0); + signal re_neg1 : std_ulogic; + signal re_neg2 : std_ulogic; + signal re_set_result : std_ulogic; + + constant RSH1_ZERO : std_ulogic_vector(1 downto 0) := "00"; + constant RSH1_B : std_ulogic_vector(1 downto 0) := "01"; + constant RSH1_NE : std_ulogic_vector(1 downto 0) := "10"; + constant RSH1_S : std_ulogic_vector(1 downto 0) := "11"; + + constant RSH2_CON : std_ulogic := '0'; + constant RSH2_A : std_ulogic := '1'; + + constant RSCON2_ZERO : std_ulogic_vector(3 downto 0) := "0000"; + constant RSCON2_1 : std_ulogic_vector(3 downto 0) := "0001"; + constant RSCON2_UNIT_52 : std_ulogic_vector(3 downto 0) := "0010"; + constant RSCON2_64_UNIT : std_ulogic_vector(3 downto 0) := "0011"; + constant RSCON2_32 : std_ulogic_vector(3 downto 0) := "0100"; + constant RSCON2_52 : std_ulogic_vector(3 downto 0) := "0101"; + constant RSCON2_UNIT : std_ulogic_vector(3 downto 0) := "0110"; + constant RSCON2_63 : std_ulogic_vector(3 downto 0) := "0111"; + constant RSCON2_64 : std_ulogic_vector(3 downto 0) := "1000"; + constant RSCON2_MINEXP : std_ulogic_vector(3 downto 0) := "1001"; + + signal rs_sel1 : std_ulogic_vector(1 downto 0); + signal rs_sel2 : std_ulogic; + signal rs_con2 : std_ulogic_vector(3 downto 0); + signal rs_neg1 : std_ulogic; + signal rs_neg2 : std_ulogic; + signal rs_norm : std_ulogic; + -- Inverse lookup table, indexed by the top 8 fraction bits -- The first 256 entries are the reciprocal (1/x) lookup table, -- and the remaining 768 entries are the reciprocal square root table. @@ -705,7 +754,6 @@ begin variable new_exp : signed(EXP_BITS-1 downto 0); variable exp_tiny : std_ulogic; variable exp_huge : std_ulogic; - variable renormalize : std_ulogic; variable clz : std_ulogic_vector(5 downto 0); variable set_x : std_ulogic; variable mshift : signed(EXP_BITS-1 downto 0); @@ -741,6 +789,12 @@ begin variable mult_mask : std_ulogic; variable sign_bit : std_ulogic; variable rnd_b32 : std_ulogic; + variable rexp_in1 : signed(EXP_BITS-1 downto 0); + variable rexp_in2 : signed(EXP_BITS-1 downto 0); + variable rexp_cin : std_ulogic; + variable rexp_sum : signed(EXP_BITS-1 downto 0); + variable rsh_in1 : signed(EXP_BITS-1 downto 0); + variable rsh_in2 : signed(EXP_BITS-1 downto 0); variable int_result : std_ulogic; variable illegal : std_ulogic; begin @@ -884,7 +938,6 @@ begin end if; v.update_fprf := '0'; - v.shift := to_signed(0, EXP_BITS); v.first := '0'; v.opsel_a := AIN_R; opsel_ainv <= '0'; @@ -900,7 +953,6 @@ begin arith_done := '0'; invalid := '0'; zero_divide := '0'; - renormalize := '0'; set_x := '0'; qnan_result := '0'; set_a := '0'; @@ -928,6 +980,20 @@ begin rnd_b32 := '0'; int_result := '0'; illegal := '0'; + + re_sel1 <= REXP1_ZERO; + re_sel2 <= REXP2_CON; + re_con2 <= RECON2_ZERO; + re_neg1 <= '0'; + re_neg2 <= '0'; + re_set_result <= '0'; + rs_sel1 <= RSH1_ZERO; + rs_sel2 <= RSH2_CON; + rs_con2 <= RSCON2_ZERO; + rs_neg1 <= '0'; + rs_neg2 <= '0'; + rs_norm <= '0'; + case r.state is when IDLE => v.use_a := '0'; @@ -1090,7 +1156,8 @@ begin -- r.opsel_a = AIN_B v.instr_done := '1'; update_fx := '1'; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; if (r.a.class = NAN and r.a.mantissa(QNAN_BIT) = '0') or (r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0') then -- Signalling NAN @@ -1221,7 +1288,8 @@ begin when DO_FMR => -- r.opsel_a = AIN_B v.result_class := r.b.class; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; v.quieten_nan := '0'; if r.insn(9) = '1' then v.result_sign := '0'; -- fabs @@ -1241,7 +1309,12 @@ begin -- r.opsel_a = AIN_B v.result_class := r.b.class; v.result_sign := r.b.negative; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; + -- set shift to exponent - 52 + rs_sel1 <= RSH1_B; + rs_con2 <= RSCON2_52; + rs_neg2 <= '1'; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; if r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0' then @@ -1254,7 +1327,6 @@ begin -- integer already, no rounding required arith_done := '1'; else - v.shift := r.b.exponent - to_signed(52, EXP_BITS); v.state := FRI_1; v.round_mode := '1' & r.insn(7 downto 6); end if; @@ -1266,7 +1338,12 @@ begin -- r.opsel_a = AIN_B, r.shift = 0 v.result_class := r.b.class; v.result_sign := r.b.negative; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; + -- set shift to exponent - -126 + rs_sel1 <= RSH1_B; + rs_con2 <= RSCON2_MINEXP; + rs_neg2 <= '1'; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; if r.b.class = NAN and r.b.mantissa(53) = '0' then @@ -1277,7 +1354,6 @@ begin set_x := '1'; if r.b.class = FINITE then if r.b.exponent < to_signed(-126, EXP_BITS) then - v.shift := r.b.exponent - to_signed(-126, EXP_BITS); v.state := ROUND_UFLOW; elsif r.b.exponent > to_signed(127, EXP_BITS) then v.state := ROUND_OFLOW; @@ -1295,7 +1371,10 @@ begin -- r.opsel_a = AIN_B v.result_class := r.b.class; v.result_sign := r.b.negative; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; + rs_sel1 <= RSH1_B; + rs_neg2 <= '1'; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; if r.b.class = NAN and r.b.mantissa(53) = '0' then @@ -1305,6 +1384,7 @@ begin end if; int_result := '1'; + case r.b.class is when ZERO => arith_done := '1'; @@ -1315,14 +1395,16 @@ begin elsif r.b.exponent >= to_signed(52, EXP_BITS) then -- integer already, no rounding required, -- shift into final position - v.shift := r.b.exponent - to_signed(UNIT_BIT, EXP_BITS); + -- set shift to exponent - 56 + rs_con2 <= RSCON2_UNIT; if r.insn(8) = '1' and r.b.negative = '1' then v.state := INT_OFLOW; else v.state := INT_ISHIFT; end if; else - v.shift := r.b.exponent - to_signed(52, EXP_BITS); + -- set shift to exponent - 52 + rs_con2 <= RSCON2_52; v.state := INT_SHIFT; end if; when INFINITY | NAN => @@ -1339,7 +1421,8 @@ begin v.result_sign := '1'; end if; v.result_class := r.b.class; - v.result_exp := to_signed(UNIT_BIT, EXP_BITS); + re_con2 <= RECON2_UNIT; + re_set_result <= '1'; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; if r.b.class = ZERO then @@ -1353,7 +1436,12 @@ begin -- r.opsel_a = AIN_A v.result_sign := r.a.negative; v.result_class := r.a.class; - v.result_exp := r.a.exponent; + re_sel1 <= REXP1_A; + re_set_result <= '1'; + -- set shift to a.exp - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; + rs_sel2 <= RSH2_A; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_a := '1'; @@ -1364,7 +1452,6 @@ begin v.add_bsmall := r.exp_cmp; v.opsel_a := AIN_B; if r.exp_cmp = '0' then - v.shift := r.a.exponent - r.b.exponent; v.result_sign := r.b.negative xnor r.insn(1); if r.a.exponent = r.b.exponent then v.state := ADD_2; @@ -1408,8 +1495,10 @@ begin v.fpscr(FPSCR_FI) := '0'; v.use_a := '1'; v.use_c := '1'; + re_sel1 <= REXP1_A; + re_sel2 <= REXP2_C; + re_set_result <= '1'; if r.a.class = FINITE and r.c.class = FINITE then - v.result_exp := r.a.exponent + r.c.exponent; -- Renormalize denorm operands if r.a.mantissa(UNIT_BIT) = '0' then v.state := RENORM_A; @@ -1446,7 +1535,10 @@ begin v.use_a := '1'; v.use_b := '1'; v.result_sign := r.a.negative xor r.b.negative; - v.result_exp := r.a.exponent - r.b.exponent; + re_sel1 <= REXP1_A; + re_sel2 <= REXP2_B; + re_neg2 <= '1'; + re_set_result <= '1'; v.count := "00"; if r.a.class = FINITE and r.b.class = FINITE then -- Renormalize denorm operands @@ -1503,9 +1595,10 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_b := '1'; + re_sel2 <= REXP2_B; + re_set_result <= '1'; case r.b.class is when FINITE => - v.result_exp := r.b.exponent; if r.b.negative = '1' then v.fpscr(FPSCR_VXSQRT) := '1'; qnan_result := '1'; @@ -1514,7 +1607,8 @@ begin elsif r.b.exponent(0) = '0' then v.state := SQRT_1; else - v.shift := to_signed(1, EXP_BITS); + -- set shift to 1 + rs_con2 <= RSCON2_1; v.state := RENORM_B2; end if; when NAN => @@ -1538,7 +1632,8 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_b := '1'; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; case r.b.class is when FINITE => if r.b.mantissa(UNIT_BIT) = '0' then @@ -1564,10 +1659,12 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_b := '1'; - v.shift := to_signed(1, EXP_BITS); + re_sel2 <= REXP2_B; + re_set_result <= '1'; + -- set shift to 1 + rs_con2 <= RSCON2_1; case r.b.class is when FINITE => - v.result_exp := r.b.exponent; if r.b.negative = '1' then v.fpscr(FPSCR_VXSQRT) := '1'; qnan_result := '1'; @@ -1600,7 +1697,12 @@ begin -- else AIN_B v.result_sign := r.a.negative; v.result_class := r.a.class; - v.result_exp := r.a.exponent + r.c.exponent; + -- put a.exp + c.exp into result_exp + re_sel1 <= REXP1_A; + re_sel2 <= REXP2_C; + re_set_result <= '1'; + -- put b.exp into shift + rs_sel1 <= RSH1_B; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; v.use_a := '1'; @@ -1625,6 +1727,7 @@ begin -- addend is bigger, do multiply first v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2)); f_to_multiply.valid <= '1'; + v.first := '1'; v.state := FMADD_0; else -- product is bigger, shift B first @@ -1664,7 +1767,7 @@ begin end if; when RENORM_A => - renormalize := '1'; + rs_norm <= '1'; v.state := RENORM_A2; if r.insn(4) = '1' then v.opsel_a := AIN_C; @@ -1675,7 +1778,8 @@ begin when RENORM_A2 => -- r.opsel_a = AIN_C for fmul/fmadd, AIN_B for fdiv set_a := '1'; - v.result_exp := new_exp; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; if r.insn(4) = '1' then if r.c.mantissa(UNIT_BIT) = '1' then if r.insn(3) = '0' or r.b.class = ZERO then @@ -1702,23 +1806,25 @@ begin end if; when RENORM_B => - renormalize := '1'; + rs_norm <= '1'; renorm_sqrt := r.is_sqrt; v.state := RENORM_B2; when RENORM_B2 => set_b := '1'; - v.result_exp := new_exp; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.opsel_a := AIN_B; v.state := LOOKUP; when RENORM_C => - renormalize := '1'; + rs_norm <= '1'; v.state := RENORM_C2; when RENORM_C2 => set_c := '1'; - v.result_exp := new_exp; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; if r.insn(3) = '0' or r.b.class = ZERO then v.first := '1'; v.state := MULT_1; @@ -1733,14 +1839,20 @@ begin when ADD_1 => -- transferring B to R - v.shift := r.b.exponent - r.a.exponent; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; + -- set shift to b.exp - a.exp + rs_sel1 <= RSH1_B; + rs_sel2 <= RSH2_A; + rs_neg2 <= '1'; v.longmask := '0'; v.state := ADD_SHIFT; when ADD_SHIFT => -- r.shift = - exponent difference, r.longmask = 0 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.x := s_nz; set_x := '1'; v.longmask := r.single_prec; @@ -1756,12 +1868,15 @@ begin opsel_b <= BIN_R; opsel_binv <= r.is_subtract; carry_in <= r.is_subtract and not r.x; - v.shift := to_signed(-1, EXP_BITS); + -- set shift to -1 + rs_con2 <= RSCON2_1; + rs_neg2 <= '1'; v.state := ADD_3; when ADD_3 => -- check for overflow or negative result (can't get both) -- r.shift = -1 + re_sel2 <= REXP2_NE; if r.r(63) = '1' then -- result is opposite sign to expected v.result_sign := not r.result_sign; @@ -1771,6 +1886,7 @@ begin elsif r.r(UNIT_BIT + 1) = '1' then -- sum overflowed, shift right opsel_r <= RES_SHIFT; + re_set_result <= '1'; set_x := '1'; if exp_huge = '1' then v.state := ROUND_OFLOW; @@ -1789,7 +1905,7 @@ begin end if; arith_done := '1'; else - renormalize := '1'; + rs_norm <= '1'; v.state := NORMALIZE; end if; @@ -1820,26 +1936,36 @@ begin end if; when FMADD_0 => + -- r.shift is b.exp, so new_exp is a.exp + c.exp - b.exp + -- (first time through; subsequent times we preserve v.shift) -- Addend is bigger here - v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2)); + -- set shift to a.exp + c.exp - b.exp -- note v.shift is at most -2 here - v.shift := r.result_exp - r.b.exponent; + if r.first = '1' then + rs_sel1 <= RSH1_NE; + else + rs_sel1 <= RSH1_S; + end if; opsel_r <= RES_MULT; opsel_s <= S_MULT; set_s := '1'; - f_to_multiply.valid <= r.first; if multiply_to_f.valid = '1' then v.longmask := '0'; v.state := ADD_SHIFT; end if; when FMADD_1 => + -- shift is b.exp, so new_exp is a.exp + c.exp - b.exp -- product is bigger here -- shift B right and use it as the addend to the multiplier - v.shift := r.b.exponent - r.result_exp + to_signed(64, EXP_BITS); -- for subtract, multiplier does B - A * C v.result_sign := r.a.negative xor r.c.negative xor r.insn(2) xor r.is_subtract; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; + re_set_result <= '1'; + -- set shift to b.exp - result_exp + 64 + rs_sel1 <= RSH1_NE; + rs_neg1 <= '1'; + rs_con2 <= RSCON2_64; v.state := FMADD_2; when FMADD_2 => @@ -1847,12 +1973,17 @@ begin -- r.shift = addend exp - product exp + 64, r.r = r.b.mantissa set_s := '1'; opsel_s <= S_SHIFT; - v.shift := r.shift - to_signed(64, EXP_BITS); + -- set shift to r.shift - 64 + rs_sel1 <= RSH1_S; + rs_con2 <= RSCON2_64; + rs_neg2 <= '1'; v.state := FMADD_3; when FMADD_3 => -- r.shift = addend exp - product exp opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.first := '1'; v.state := FMADD_4; @@ -1876,11 +2007,14 @@ begin opsel_s <= S_NEG; set_s := '1'; end if; - v.shift := to_signed(UNIT_BIT, EXP_BITS); + -- set shift to UNIT_BIT + rs_con2 <= RSCON2_UNIT; v.state := FMADD_6; when FMADD_6 => -- r.shift = UNIT_BIT (or 0, but only if r is now nonzero) + re_sel2 <= REXP2_NE; + rs_norm <= '1'; if (r.r(UNIT_BIT + 2) or r_hi_nz or r_lo_nz or (or (r.r(DP_LSB - 1 downto 0)))) = '0' then if s_nz = '0' then -- must be a subtraction, and r.x must be zero @@ -1891,13 +2025,13 @@ begin -- R is all zeroes but there are non-zero bits in S -- so shift them into R and set S to 0 opsel_r <= RES_SHIFT; + re_set_result <= '1'; set_s := '1'; - -- stay in state FMADD_6 + v.state := FINISH; end if; elsif r.r(UNIT_BIT + 2 downto UNIT_BIT) = "001" then v.state := FINISH; else - renormalize := '1'; v.state := NORMALIZE; end if; @@ -1991,27 +2125,33 @@ begin v.state := FINISH; when FRE_1 => - v.result_exp := - r.result_exp; + re_sel1 <= REXP1_R; + re_neg1 <= '1'; + re_set_result <= '1'; opsel_r <= RES_MISC; misc_sel <= "0111"; - v.shift := to_signed(1, EXP_BITS); + -- set shift to 1 + rs_con2 <= RSCON2_1; v.state := NORMALIZE; when FTDIV_1 => v.cr_result(1) := exp_tiny or exp_huge; + -- set shift to a.exp + rs_sel2 <= RSH2_A; if exp_tiny = '1' or exp_huge = '1' or r.a.class = ZERO or r.first = '0' then v.instr_done := '1'; else - v.shift := r.a.exponent; v.doing_ftdiv := "10"; end if; when RSQRT_1 => opsel_r <= RES_MISC; misc_sel <= "0111"; - sqrt_exp := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1); - v.result_exp := - sqrt_exp; - v.shift := to_signed(1, EXP_BITS); + re_sel1 <= REXP1_BHALF; + re_neg1 <= '1'; + re_set_result <= '1'; + -- set shift to 1 + rs_con2 <= RSCON2_1; v.state := NORMALIZE; when SQRT_1 => @@ -2023,7 +2163,9 @@ begin msel_1 <= MUL1_B; msel_2 <= MUL2_LUT; f_to_multiply.valid <= '1'; - v.shift := to_signed(-1, EXP_BITS); + -- set shift to -1 + rs_con2 <= RSCON2_1; + rs_neg2 <= '1'; v.count := "00"; v.state := SQRT_2; @@ -2032,6 +2174,8 @@ begin -- not expecting multiplier result yet -- r.shift = -1 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.first := '1'; v.state := SQRT_3; @@ -2132,9 +2276,10 @@ begin when SQRT_10 => -- Add the bottom 8 bits of P, sign-extended, onto R. opsel_b <= BIN_PS8; - sqrt_exp := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1); - v.result_exp := sqrt_exp; - v.shift := to_signed(1, EXP_BITS); + re_sel1 <= REXP1_BHALF; + re_set_result <= '1'; + -- set shift to 1 + rs_con2 <= RSCON2_1; v.first := '1'; v.state := SQRT_11; @@ -2167,13 +2312,19 @@ begin when INT_SHIFT => -- r.shift = b.exponent - 52 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; set_x := '1'; v.state := INT_ROUND; - v.shift := to_signed(52 - UNIT_BIT, EXP_BITS); + -- set shift to -4 (== 52 - UNIT_BIT) + rs_con2 <= RSCON2_UNIT_52; + rs_neg2 <= '1'; when INT_ROUND => -- r.shift = -4 (== 52 - UNIT_BIT) opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; round := fp_rounding(r.r, r.x, '0', r.round_mode, r.result_sign); v.fpscr(FPSCR_FR downto FPSCR_FI) := round; -- Check for negative values that don't round to 0 for fcti*u* @@ -2187,6 +2338,8 @@ begin when INT_ISHIFT => -- r.shift = b.exponent - UNIT_BIT; opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.state := INT_FINAL; when INT_FINAL => @@ -2248,6 +2401,8 @@ begin when FRI_1 => -- r.shift = b.exponent - 52 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; set_x := '1'; v.state := ROUNDING; @@ -2255,13 +2410,16 @@ begin if r.is_multiply = '1' and px_nz = '1' then v.x := '1'; end if; + -- set shift to new_exp - min_exp (N.B. rs_norm overrides this) + rs_sel1 <= RSH1_NE; + rs_con2 <= RSCON2_MINEXP; + rs_neg2 <= '1'; if r.r(63 downto UNIT_BIT) /= std_ulogic_vector(to_unsigned(1, 64 - UNIT_BIT)) then - renormalize := '1'; + rs_norm <= '1'; v.state := NORMALIZE; else set_x := '1'; if exp_tiny = '1' then - v.shift := new_exp - min_exp; v.state := ROUND_UFLOW; elsif exp_huge = '1' then v.state := ROUND_OFLOW; @@ -2272,11 +2430,16 @@ begin when NORMALIZE => -- Shift so we have 9 leading zeroes (we know R is non-zero) - -- r.shift = clz(r.r) - 9 + -- r.shift = clz(r.r) - 7 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; + -- set shift to new_exp - min_exp + rs_sel1 <= RSH1_NE; + rs_con2 <= RSCON2_MINEXP; + rs_neg2 <= '1'; set_x := '1'; if exp_tiny = '1' then - v.shift := new_exp - min_exp; v.state := ROUND_UFLOW; elsif exp_huge = '1' then v.state := ROUND_OFLOW; @@ -2291,15 +2454,19 @@ begin -- disabled underflow exception case -- have to denormalize before rounding opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; set_x := '1'; v.state := ROUNDING; else -- enabled underflow exception case -- if denormalized, have to normalize before rounding v.fpscr(FPSCR_UX) := '1'; - v.result_exp := r.result_exp + bias_exp; + re_sel1 <= REXP1_R; + re_con2 <= RECON2_BIAS; + re_set_result <= '1'; if r.r(UNIT_BIT) = '0' then - renormalize := '1'; + rs_norm <= '1'; v.state := NORMALIZE; else v.state := ROUNDING; @@ -2321,13 +2488,17 @@ begin v.fpscr(FPSCR_FR) := '0'; end if; -- construct largest representable number - v.result_exp := max_exp; + re_con2 <= RECON2_MAX; + re_set_result <= '1'; opsel_r <= RES_MISC; misc_sel <= "001" & r.single_prec; arith_done := '1'; else -- enabled overflow exception - v.result_exp := r.result_exp - bias_exp; + re_sel1 <= REXP1_R; + re_con2 <= RECON2_BIAS; + re_neg2 <= '1'; + re_set_result <= '1'; v.state := ROUNDING; end if; @@ -2338,13 +2509,15 @@ begin if round(1) = '1' then -- increment the LSB for the precision opsel_b <= BIN_RND; - v.shift := to_signed(-1, EXP_BITS); + -- set shift to -1 + rs_con2 <= RSCON2_1; + rs_neg2 <= '1'; v.state := ROUNDING_2; else if r.r(UNIT_BIT) = '0' then -- result after masking could be zero, or could be a -- denormalized result that needs to be renormalized - renormalize := '1'; + rs_norm <= '1'; v.state := ROUNDING_3; else arith_done := '1'; @@ -2361,8 +2534,10 @@ begin -- Check for overflow during rounding -- r.shift = -1 v.x := '0'; + re_sel2 <= REXP2_NE; if r.r(UNIT_BIT + 1) = '1' then opsel_r <= RES_SHIFT; + re_set_result <= '1'; if exp_huge = '1' then v.state := ROUND_OFLOW; else @@ -2370,7 +2545,7 @@ begin end if; elsif r.r(UNIT_BIT) = '0' then -- Do CLZ so we can renormalize the result - renormalize := '1'; + rs_norm <= '1'; v.state := ROUNDING_3; else arith_done := '1'; @@ -2379,6 +2554,11 @@ begin when ROUNDING_3 => -- r.shift = clz(r.r) - 9 mant_nz := r_hi_nz or (r_lo_nz and not r.single_prec); + re_sel2 <= REXP2_NE; + -- set shift to new_exp - min_exp (== -1022) + rs_sel1 <= RSH1_NE; + rs_con2 <= RSCON2_MINEXP; + rs_neg2 <= '1'; if mant_nz = '0' then v.result_class := ZERO; if r.is_subtract = '1' then @@ -2389,8 +2569,8 @@ begin else -- Renormalize result after rounding opsel_r <= RES_SHIFT; + re_set_result <= '1'; v.denorm := exp_tiny; - v.shift := new_exp - to_signed(-1022, EXP_BITS); if new_exp < to_signed(-1022, EXP_BITS) then v.state := DENORM; else @@ -2401,6 +2581,8 @@ begin when DENORM => -- r.shift = result_exp - -1022 opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; arith_done := '1'; when NAN_RESULT => @@ -2425,17 +2607,18 @@ begin case r.opsel_a is when AIN_B => v.result_sign := r.b.negative xor r.negate; - v.result_exp := r.b.exponent; + re_sel2 <= REXP2_B; v.result_class := r.b.class; when AIN_C => v.result_sign := r.c.negative xor r.negate; - v.result_exp := r.c.exponent; + re_sel2 <= REXP2_C; v.result_class := r.c.class; when others => v.result_sign := r.a.negative xor r.negate; - v.result_exp := r.a.exponent; + re_sel1 <= REXP1_A; v.result_class := r.a.class; end case; + re_set_result <= '1'; arith_done := '1'; when DO_IDIVMOD => @@ -2456,12 +2639,13 @@ begin carry_in <= '1'; end if; v.result_class := FINITE; - v.result_exp := to_signed(UNIT_BIT, EXP_BITS); + re_con2 <= RECON2_UNIT; + re_set_result <= '1'; v.state := IDIV_NORMB; end if; when IDIV_NORMB => -- do count-leading-zeroes on B (now in R) - renormalize := '1'; + rs_norm <= '1'; -- save the original value of B or |B| in C set_c := '1'; v.state := IDIV_NORMB2; @@ -2469,6 +2653,8 @@ begin -- get B into the range [1, 2) in 8.56 format set_x := '1'; -- record if any 1 bits shifted out opsel_r <= RES_SHIFT; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.state := IDIV_NORMB3; when IDIV_NORMB3 => -- add the X bit onto R to round up B @@ -2483,12 +2669,13 @@ begin opsel_ainv <= '1'; carry_in <= '1'; end if; - v.result_exp := to_signed(UNIT_BIT, EXP_BITS); + re_con2 <= RECON2_UNIT; + re_set_result <= '1'; v.opsel_a := AIN_C; v.state := IDIV_CLZA2; when IDIV_CLZA2 => -- r.opsel_a = AIN_C - renormalize := '1'; + rs_norm <= '1'; -- write the dividend back into A in case we negated it set_a_mant := '1'; -- while doing the count-leading-zeroes on A, @@ -2500,7 +2687,9 @@ begin v.state := IDIV_CLZA3; when IDIV_CLZA3 => -- save the exponent of A (but don't overwrite the mantissa) - v.a.exponent := new_exp; + set_a_exp := '1'; + re_sel2 <= REXP2_NE; + re_set_result <= '1'; v.div_close := '0'; if new_exp = r.b.exponent then v.div_close := '1'; @@ -2521,9 +2710,9 @@ begin end if; when IDIV_NR0 => -- reduce number of Newton-Raphson iterations for small A - if r.divext = '1' or new_exp >= to_signed(32, EXP_BITS) then + if r.divext = '1' or r.result_exp >= to_signed(32, EXP_BITS) then v.count := "00"; - elsif new_exp >= to_signed(16, EXP_BITS) then + elsif r.result_exp >= to_signed(16, EXP_BITS) then v.count := "01"; else v.count := "10"; @@ -2567,7 +2756,8 @@ begin f_to_multiply.valid <= r.first; pshift := '1'; v.opsel_a := AIN_A; - v.shift := to_signed(64, EXP_BITS); + -- set shift to 64 + rs_con2 <= RSCON2_64; -- Get 0.5 into R in case the inverse estimate turns out to be -- less than 0.5, in which case we want to use 0.5, to avoid -- infinite loops in some cases. @@ -2587,7 +2777,8 @@ begin opsel_r <= RES_MISC; misc_sel <= "0001"; v.opsel_a := AIN_A; - v.shift := to_signed(64, EXP_BITS); + -- set shift to 64 + rs_con2 <= RSCON2_64; v.state := IDIV_DODIV; when IDIV_DODIV => -- r.opsel_a = AIN_A @@ -2604,15 +2795,19 @@ begin -- put that into B, which now holds the quotient set_b_mant := '1'; if r.divext = '0' then - v.shift := to_signed(-UNIT_BIT, EXP_BITS); + -- set shift to -56 + rs_con2 <= RSCON2_UNIT; + rs_neg2 <= '1'; v.first := '1'; v.state := IDIV_DIV; elsif r.single_prec = '1' then -- divwe[u][o], shift A left 32 bits - v.shift := to_signed(32, EXP_BITS); + -- set shift to 32 + rs_con2 <= RSCON2_32; v.state := IDIV_SH32; elsif r.div_close = '0' then - v.shift := to_signed(64 - UNIT_BIT, EXP_BITS); + -- set shift to 64 - UNIT_BIT (== 8) + rs_con2 <= RSCON2_64_UNIT; v.state := IDIV_EXTDIV; else -- handle top bit of quotient specially @@ -2623,7 +2818,9 @@ begin when IDIV_SH32 => -- r.shift = 32, R contains the dividend opsel_r <= RES_SHIFT; - v.shift := to_signed(-UNIT_BIT, EXP_BITS); + -- set shift to -UNIT_BIT (== -56) + rs_con2 <= RSCON2_UNIT; + rs_neg2 <= '1'; v.first := '1'; v.state := IDIV_DIV; when IDIV_DIV => @@ -2637,7 +2834,9 @@ begin f_to_multiply.valid <= r.first; pshift := '1'; opsel_r <= RES_MULT; - v.shift := - r.b.exponent; + -- set shift to - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; if multiply_to_f.valid = '1' then v.state := IDIV_DIV2; end if; @@ -2670,7 +2869,8 @@ begin if r.divmod = '0' then v.opsel_a := AIN_B; end if; - v.shift := to_signed(UNIT_BIT, EXP_BITS); + -- set shift to UNIT_BIT (== 56) + rs_con2 <= RSCON2_UNIT; if pcmpc_lt = '1' or pcmpc_eq = '1' then if r.divmod = '0' then v.state := IDIV_DIVADJ; @@ -2687,7 +2887,9 @@ begin when IDIV_DIV5 => pshift := '1'; opsel_r <= RES_MULT; - v.shift := - r.b.exponent; + -- set shift to - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; if multiply_to_f.valid = '1' then v.state := IDIV_DIV6; end if; @@ -2727,7 +2929,8 @@ begin if r.divmod = '0' then v.opsel_a := AIN_B; end if; - v.shift := to_signed(UNIT_BIT, EXP_BITS); + -- set shift to UNIT_BIT (== 56) + rs_con2 <= RSCON2_UNIT; if r.divmod = '0' then v.state := IDIV_DIVADJ; elsif pcmpc_eq = '1' then @@ -2737,14 +2940,18 @@ begin end if; when IDIV_EXT_TBH => -- r.opsel_a = AIN_C; get divisor into R and prepare to shift left - v.shift := to_signed(63, EXP_BITS) - r.b.exponent; + -- set shift to 63 - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; + rs_con2 <= RSCON2_63; v.opsel_a := AIN_A; v.state := IDIV_EXT_TBH2; when IDIV_EXT_TBH2 => -- r.opsel_a = AIN_A; divisor is in R -- r.shift = 63 - b.exponent; shift and put into B set_b_mant := '1'; - v.shift := to_signed(64 - UNIT_BIT, EXP_BITS); + -- set shift to 64 - UNIT_BIT (== 8) + rs_con2 <= RSCON2_64_UNIT; v.state := IDIV_EXT_TBH3; when IDIV_EXT_TBH3 => -- Dividing (A << 64) by C @@ -2752,7 +2959,10 @@ begin -- Put A in the top 64 bits of Ahi/A/Alo set_a_hi := '1'; set_a_mant := '1'; - v.shift := to_signed(64, EXP_BITS) - r.b.exponent; + -- set shift to 64 - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; + rs_con2 <= RSCON2_64; v.state := IDIV_EXT_TBH4; when IDIV_EXT_TBH4 => -- dividend (A) is in R @@ -2760,7 +2970,8 @@ begin opsel_r <= RES_SHIFT; -- top bit of A gets lost in the shift, so handle it specially v.opsel_a := AIN_B; - v.shift := to_signed(63, EXP_BITS); + -- set shift to 63 + rs_con2 <= RSCON2_63; v.state := IDIV_EXT_TBH5; when IDIV_EXT_TBH5 => -- r.opsel_a = AIN_B, r.shift = 63 @@ -2779,7 +2990,10 @@ begin -- Put A in the top 64 bits of Ahi/A/Alo set_a_hi := '1'; set_a_mant := '1'; - v.shift := to_signed(64, EXP_BITS) - r.b.exponent; + -- set shift to 64 - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; + rs_con2 <= RSCON2_64; v.state := IDIV_EXTDIV1; when IDIV_EXTDIV1 => -- dividend is in R @@ -2816,7 +3030,10 @@ begin opsel_r <= RES_MULT; opsel_s <= S_MULT; set_s := '1'; - v.shift := to_signed(UNIT_BIT, EXP_BITS) - r.b.exponent; + -- set shift to UNIT_BIT - b.exp + rs_sel1 <= RSH1_B; + rs_neg1 <= '1'; + rs_con2 <= RSCON2_UNIT; if multiply_to_f.valid = '1' then v.state := IDIV_EXTDIV5; end if; @@ -3200,17 +3417,100 @@ begin v.c.mantissa := shift_res; end if; - if opsel_r = RES_SHIFT then - v.result_exp := new_exp; + -- exponent data path + case re_sel1 is + when REXP1_R => + rexp_in1 := r.result_exp; + when REXP1_A => + rexp_in1 := r.a.exponent; + when REXP1_BHALF => + rexp_in1 := r.b.exponent(EXP_BITS-1) & r.b.exponent(EXP_BITS-1 downto 1); + when others => + rexp_in1 := to_signed(0, EXP_BITS); + end case; + if re_neg1 = '1' then + rexp_in1 := not rexp_in1; end if; - - if renormalize = '1' then + case re_sel2 is + when REXP2_NE => + rexp_in2 := new_exp; + when REXP2_C => + rexp_in2 := r.c.exponent; + when REXP2_B => + rexp_in2 := r.b.exponent; + when others => + case re_con2 is + when RECON2_UNIT => + rexp_in2 := to_signed(UNIT_BIT, EXP_BITS); + when RECON2_MAX => + rexp_in2 := max_exp; + when RECON2_BIAS => + rexp_in2 := bias_exp; + when others => + rexp_in2 := to_signed(0, EXP_BITS); + end case; + end case; + if re_neg2 = '1' then + rexp_in2 := not rexp_in2; + end if; + rexp_cin := re_neg1 or re_neg2; + rexp_sum := rexp_in1 + rexp_in2 + rexp_cin; + if re_set_result = '1' then + v.result_exp := rexp_sum; + end if; + case rs_sel1 is + when RSH1_B => + rsh_in1 := r.b.exponent; + when RSH1_NE => + rsh_in1 := new_exp; + when RSH1_S => + rsh_in1 := r.shift; + when others => + rsh_in1 := to_signed(0, EXP_BITS); + end case; + if rs_neg1 = '1' then + rsh_in1 := not rsh_in1; + end if; + case rs_sel2 is + when RSH2_A => + rsh_in2 := r.a.exponent; + when others => + case rs_con2 is + when RSCON2_1 => + rsh_in2 := to_signed(1, EXP_BITS); + when RSCON2_UNIT_52 => + rsh_in2 := to_signed(UNIT_BIT - 52, EXP_BITS); + when RSCON2_64_UNIT => + rsh_in2 := to_signed(64 - UNIT_BIT, EXP_BITS); + when RSCON2_32 => + rsh_in2 := to_signed(32, EXP_BITS); + when RSCON2_52 => + rsh_in2 := to_signed(52, EXP_BITS); + when RSCON2_UNIT => + rsh_in2 := to_signed(UNIT_BIT, EXP_BITS); + when RSCON2_63 => + rsh_in2 := to_signed(63, EXP_BITS); + when RSCON2_64 => + rsh_in2 := to_signed(64, EXP_BITS); + when RSCON2_MINEXP => + rsh_in2 := min_exp; + when others => + rsh_in2 := to_signed(0, EXP_BITS); + end case; + end case; + if rs_neg2 = '1' then + rsh_in2 := not rsh_in2; + end if; + if rs_norm = '1' then clz := count_left_zeroes(r.r); if renorm_sqrt = '1' then -- make denormalized value end up with even exponent clz(0) := '1'; end if; + -- do this as a separate dedicated 7-bit adder for timing reasons v.shift := resize(signed('0' & clz) - (63 - UNIT_BIT), EXP_BITS); + else + v.shift := rsh_in1 + rsh_in2 + (rs_neg1 or rs_neg2); end if; if r.update_fprf = '1' then From 932da4c114b518504ea9863415159af01bd412b4 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 21 May 2022 19:36:17 +1000 Subject: [PATCH 06/22] FPU: Simplify IDLE state code Do more decoding of the instruction ahead of the IDLE state processing so that the IDLE state code becomes much simpler. To make the decoding easier, we now use four insn_type_t codes for floating-point operations rather than two. This also rearranges the insn_type_t values a little to get the 4 FP opcode values to differ only in the bottom 2 bits, and put OP_DIV, OP_DIVE and OP_MOD next to them. Signed-off-by: Paul Mackerras --- common.vhdl | 8 ++ decode1.vhdl | 112 +++++++-------- decode2.vhdl | 20 +-- decode_types.vhdl | 14 +- execute1.vhdl | 3 + fpu.vhdl | 283 ++++++++++++++++++++------------------ scripts/fmt_log/fmt_log.c | 14 +- 7 files changed, 236 insertions(+), 218 deletions(-) diff --git a/common.vhdl b/common.vhdl index 685d0c3..51cbc02 100644 --- a/common.vhdl +++ b/common.vhdl @@ -317,6 +317,9 @@ package common is read_data1: std_ulogic_vector(63 downto 0); read_data2: std_ulogic_vector(63 downto 0); read_data3: std_ulogic_vector(63 downto 0); + reg_valid1: std_ulogic; + reg_valid2: std_ulogic; + reg_valid3: std_ulogic; cr: std_ulogic_vector(31 downto 0); xerc: xer_common_t; lr: std_ulogic; @@ -363,6 +366,7 @@ package common is is_32bit => '0', is_signed => '0', xerc => xerc_init, reserve => '0', br_pred => '0', byte_reverse => '0', sign_extend => '0', update => '0', nia => (others => '0'), read_data1 => (others => '0'), read_data2 => (others => '0'), read_data3 => (others => '0'), + reg_valid1 => '0', reg_valid2 => '0', reg_valid3 => '0', cr => (others => '0'), insn => (others => '0'), data_len => (others => '0'), result_sel => "000", sub_select => "000", repeat => '0', second => '0', spr_select => spr_id_init, @@ -671,6 +675,9 @@ package common is fra : std_ulogic_vector(63 downto 0); frb : std_ulogic_vector(63 downto 0); frc : std_ulogic_vector(63 downto 0); + valid_a : std_ulogic; + valid_b : std_ulogic; + valid_c : std_ulogic; frt : gspr_index_t; rc : std_ulogic; m32b : std_ulogic; @@ -684,6 +691,7 @@ package common is insn => (others => '0'), fe_mode => "00", rc => '0', fra => (others => '0'), frb => (others => '0'), frc => (others => '0'), frt => (others => '0'), + valid_a => '0', valid_b => '0', valid_c => '0', single => '0', is_signed => '0', out_cr => '0', m32b => '0', oe => '0', xerc => xerc_init, stall => '0'); diff --git a/decode1.vhdl b/decode1.vhdl index fda2ce2..8bea225 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -443,18 +443,18 @@ architecture behaviour of decode1 is constant decode_op_59_array : op_59_subop_array_t := ( -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt -- op in out A out in out len ext pipe - 2#01110# => (FPU, FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfid[u]s - 2#10010# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fdivs - 2#10100# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsubs - 2#10101# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fadds - 2#10110# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsqrts - 2#11000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fres - 2#11001# => (FPU, FPU, OP_FPOP, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmuls - 2#11010# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- frsqrtes - 2#11100# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmsubs - 2#11101# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmadds - 2#11110# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmsubs - 2#11111# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmadds + 2#01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfid[u]s + 2#10010# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fdivs + 2#10100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsubs + 2#10101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fadds + 2#10110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsqrts + 2#11000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fres + 2#11001# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmuls + 2#11010# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- frsqrtes + 2#11100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmsubs + 2#11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmadds + 2#11110# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmsubs + 2#11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmadds others => illegal_inst ); @@ -470,38 +470,38 @@ architecture behaviour of decode1 is constant decode_op_63l_array : op_63_subop_array_0_t := ( -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt -- op in out A out in out len ext pipe - 2#000000000# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 0/0=fcmpu - 2#000000001# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 1/0=fcmpo - 2#000000010# => (FPU, FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 2/0=mcrfs - 2#000000100# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 4/0=ftdiv - 2#000000101# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 5/0=ftsqrt - 2#011000001# => (FPU, FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/6=mtfsb1 - 2#011000010# => (FPU, FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/6=mtfsb0 - 2#011000100# => (FPU, FPU, OP_FPOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/6=mtfsfi - 2#011011010# => (FPU, FPU, OP_FPOP_I, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 26/6=fmrgow - 2#011011110# => (FPU, FPU, OP_FPOP_I, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 30/6=fmrgew - 2#011110010# => (FPU, FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 18/7=mffs family - 2#011110110# => (FPU, FPU, OP_FPOP_I, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 22/7=mtfsf - 2#100000000# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/8=fcpsgn - 2#100000001# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/8=fneg - 2#100000010# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/8=fmr - 2#100000100# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/8=fnabs - 2#100001000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 8/8=fabs - 2#100001100# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 12/8=frin - 2#100001101# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 13/8=friz - 2#100001110# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 14/8=frip - 2#100001111# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 15/8=frim - 2#110000000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- 0/12=frsp - 2#111000000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/14=fctiw - 2#111000100# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/14=fctiwu - 2#111011001# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/14=fctid - 2#111011010# => (FPU, FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 26/14=fcfid - 2#111011101# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/14=fctidu - 2#111011110# => (FPU, FPU, OP_FPOP_I, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 30/14=fcfidu - 2#111100000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/15=fctiwz - 2#111100100# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/15=fctiwuz - 2#111111001# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/15=fctidz - 2#111111101# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/15=fctiduz + 2#000000000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 0/0=fcmpu + 2#000000001# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 1/0=fcmpo + 2#000000010# => (FPU, FPU, OP_FP_CMP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 2/0=mcrfs + 2#000000100# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 4/0=ftdiv + 2#000000101# => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 5/0=ftsqrt + 2#011000001# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/6=mtfsb1 + 2#011000010# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/6=mtfsb0 + 2#011000100# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/6=mtfsfi + 2#011011010# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 26/6=fmrgow + 2#011011110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 30/6=fmrgew + 2#011110010# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 18/7=mffs family + 2#011110110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 22/7=mtfsf + 2#100000000# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/8=fcpsgn + 2#100000001# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/8=fneg + 2#100000010# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/8=fmr + 2#100000100# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/8=fnabs + 2#100001000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 8/8=fabs + 2#100001100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 12/8=frin + 2#100001101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 13/8=friz + 2#100001110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 14/8=frip + 2#100001111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 15/8=frim + 2#110000000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- 0/12=frsp + 2#111000000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/14=fctiw + 2#111000100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/14=fctiwu + 2#111011001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/14=fctid + 2#111011010# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 26/14=fcfid + 2#111011101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/14=fctidu + 2#111011110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 30/14=fcfidu + 2#111100000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/15=fctiwz + 2#111100100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/15=fctiwuz + 2#111111001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/15=fctidz + 2#111111101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/15=fctiduz others => illegal_inst ); @@ -509,18 +509,18 @@ architecture behaviour of decode1 is constant decode_op_63h_array : op_63_subop_array_1_t := ( -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt -- op in out A out in out len ext pipe - 2#0010# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fdiv - 2#0100# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsub - 2#0101# => (FPU, FPU, OP_FPOP, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fadd - 2#0110# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsqrt - 2#0111# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsel - 2#1000# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fre - 2#1001# => (FPU, FPU, OP_FPOP, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmul - 2#1010# => (FPU, FPU, OP_FPOP, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- frsqrte - 2#1100# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmsub - 2#1101# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmadd - 2#1110# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmsub - 2#1111# => (FPU, FPU, OP_FPOP, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmadd + 2#0010# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fdiv + 2#0100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsub + 2#0101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fadd + 2#0110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsqrt + 2#0111# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsel + 2#1000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fre + 2#1001# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmul + 2#1010# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- frsqrte + 2#1100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmsub + 2#1101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmadd + 2#1110# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmsub + 2#1111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmadd others => illegal_inst ); diff --git a/decode2.vhdl b/decode2.vhdl index 1392aae..0592fe4 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -58,10 +58,6 @@ architecture behaviour of decode2 is busy : std_ulogic; sgl_pipe : std_ulogic; prev_sgl : std_ulogic; - reg_a_valid : std_ulogic; - reg_b_valid : std_ulogic; - reg_c_valid : std_ulogic; - reg_o_valid : std_ulogic; input_ov : std_ulogic; output_ov : std_ulogic; read_rspr : std_ulogic; @@ -450,11 +446,6 @@ begin when others => end case; - v.reg_a_valid := decoded_reg_a.reg_valid; - v.reg_b_valid := decoded_reg_b.reg_valid; - v.reg_c_valid := decoded_reg_c.reg_valid; - v.reg_o_valid := decoded_reg_o.reg_valid; - if d_in.decode.lr = '1' then v.e.lr := insn_lk(d_in.insn); -- b and bc have even major opcodes; bcreg is considered absolute @@ -542,6 +533,9 @@ begin v.e.read_reg1 := d_in.reg_a; v.e.read_reg2 := d_in.reg_b; v.e.read_reg3 := d_in.reg_c; + v.e.reg_valid1 := decoded_reg_a.reg_valid; + v.e.reg_valid2 := decoded_reg_b.reg_valid; + v.e.reg_valid3 := decoded_reg_c.reg_valid; v.e.write_reg := decoded_reg_o.reg; v.e.write_reg_enable := decoded_reg_o.reg_valid; v.e.invert_a := d_in.decode.invert_a; @@ -583,16 +577,16 @@ begin control_valid_in <= valid_in; control_serialize <= v.sgl_pipe or v.prev_sgl; - gpr_write_valid <= v.reg_o_valid; + gpr_write_valid <= v.e.write_reg_enable; gpr_write <= v.e.write_reg; - gpr_a_read_valid <= v.reg_a_valid; + gpr_a_read_valid <= v.e.reg_valid1; gpr_a_read <= v.e.read_reg1; - gpr_b_read_valid <= v.reg_b_valid; + gpr_b_read_valid <= v.e.reg_valid2; gpr_b_read <= v.e.read_reg2; - gpr_c_read_valid <= v.reg_c_valid; + gpr_c_read_valid <= v.e.reg_valid3; gpr_c_read <= v.e.read_reg3; cr_write_valid <= v.e.output_cr or v.e.rc; diff --git a/decode_types.vhdl b/decode_types.vhdl index 9ee329d..d5e51bf 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -4,14 +4,16 @@ use ieee.std_logic_1164.all; package decode_types is type insn_type_t is (OP_ILLEGAL, OP_NOP, OP_ADD, OP_AND, OP_ATTN, OP_B, OP_BC, OP_BCREG, - OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPRB, + OP_BCD, OP_BPERM, OP_CMP, OP_CMPB, OP_CMPEQB, OP_CMPRB, OP_CNTZ, OP_CROP, OP_DARN, OP_DCBF, OP_DCBST, OP_DCBT, OP_DCBTST, - OP_DCBZ, OP_DIV, OP_DIVE, OP_EXTS, OP_EXTSWSLI, - OP_FPOP, OP_FPOP_I, - OP_ICBI, OP_ICBT, OP_ISEL, OP_ISYNC, + OP_DCBZ, OP_ICBI, OP_ICBT, + OP_FP_CMP, OP_FP_ARITH, OP_FP_MOVE, OP_FP_MISC, + OP_DIV, OP_DIVE, OP_MOD, + OP_EXTS, OP_EXTSWSLI, + OP_ISEL, OP_ISYNC, OP_LOAD, OP_STORE, - OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MOD, + OP_MCRXRX, OP_MFCR, OP_MFMSR, OP_MFSPR, OP_MTCRF, OP_MTMSRD, OP_MTSPR, OP_MUL_L64, OP_MUL_H64, OP_MUL_H32, OP_OR, OP_POPCNT, OP_PRTY, OP_RFID, @@ -19,7 +21,7 @@ package decode_types is OP_SHL, OP_SHR, OP_SYNC, OP_TLBIE, OP_TRAP, OP_XOR, - OP_BCD, OP_ADDG6S, + OP_ADDG6S, OP_FETCH_FAILED ); type input_reg_a_t is (NONE, RA, RA_OR_ZERO, CIA, FRA); diff --git a/execute1.vhdl b/execute1.vhdl index 0eb0b7f..556dc41 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -1590,6 +1590,9 @@ begin fv.fra := a_in; fv.frb := b_in; fv.frc := c_in; + fv.valid_a := e_in.reg_valid1; + fv.valid_b := e_in.reg_valid2; + fv.valid_c := e_in.reg_valid3; fv.frt := e_in.write_reg; fv.rc := e_in.rc; fv.out_cr := e_in.output_cr; diff --git a/fpu.vhdl b/fpu.vhdl index 44ab9aa..3ea51b9 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -40,6 +40,7 @@ architecture behaviour of fpu is type fpu_reg_type is record class : fp_number_class; negative : std_ulogic; + denorm : std_ulogic; exponent : signed(EXP_BITS-1 downto 0); -- unbiased mantissa : std_ulogic_vector(63 downto 0); -- 8.56 format end record; @@ -52,6 +53,7 @@ architecture behaviour of fpu is DO_FADD, DO_FMUL, DO_FDIV, DO_FSQRT, DO_FMADD, DO_FRE, DO_FRSQRTE, DO_FSEL, + DO_IDIVMOD, FRI_1, ADD_1, ADD_SHIFT, ADD_2, ADD_3, CMP_1, CMP_2, @@ -76,7 +78,6 @@ architecture behaviour of fpu is RENORM_B, RENORM_B2, RENORM_C, RENORM_C2, NAN_RESULT, EXC_RESULT, - DO_IDIVMOD, IDIV_NORMB, IDIV_NORMB2, IDIV_NORMB3, IDIV_CLZA, IDIV_CLZA2, IDIV_CLZA3, IDIV_NR0, IDIV_NR1, IDIV_NR2, IDIV_USE0_5, @@ -89,6 +90,9 @@ architecture behaviour of fpu is IDIV_EXTDIV4, IDIV_EXTDIV5, IDIV_EXTDIV6, IDIV_MODADJ, IDIV_MODSUB, IDIV_DIVADJ, IDIV_OVFCHK, IDIV_DONE, IDIV_ZERO); + type decode32 is array(0 to 31) of state_t; + type decode8 is array(0 to 7) of state_t; + type reg_type is record state : state_t; busy : std_ulogic; @@ -103,6 +107,7 @@ architecture behaviour of fpu is dest_fpr : gspr_index_t; fe_mode : std_ulogic; rc : std_ulogic; + fp_rc : std_ulogic; is_cmp : std_ulogic; single_prec : std_ulogic; sp_result : std_ulogic; @@ -281,6 +286,48 @@ architecture behaviour of fpu is signal rs_neg2 : std_ulogic; signal rs_norm : std_ulogic; + constant arith_decode : decode32 := ( + -- indexed by bits 5..1 of opcode + 2#01000# => DO_FRI, + 2#01100# => DO_FRSP, + 2#01110# => DO_FCTI, + 2#01111# => DO_FCTI, + 2#10010# => DO_FDIV, + 2#10100# => DO_FADD, + 2#10101# => DO_FADD, + 2#10110# => DO_FSQRT, + 2#11000# => DO_FRE, + 2#11001# => DO_FMUL, + 2#11010# => DO_FRSQRTE, + 2#11100# => DO_FMADD, + 2#11101# => DO_FMADD, + 2#11110# => DO_FMADD, + 2#11111# => DO_FMADD, + others => DO_ILLEGAL + ); + + constant cmp_decode : decode8 := ( + 2#000# => DO_FCMP, + 2#001# => DO_FCMP, + 2#010# => DO_MCRFS, + 2#100# => DO_FTDIV, + 2#101# => DO_FTSQRT, + others => DO_ILLEGAL + ); + + constant misc_decode : decode32 := ( + -- indexed by bits 10, 8, 4, 2, 1 of opcode + 2#00010# => DO_MTFSB, + 2#01010# => DO_MTFSFI, + 2#10010# => DO_FMRG, + 2#11010# => DO_FMRG, + 2#10011# => DO_MFFS, + 2#11011# => DO_MTFSF, + 2#10110# => DO_FCFID, + 2#11110# => DO_FCFID, + others => DO_ILLEGAL + ); + -- Inverse lookup table, indexed by the top 8 fraction bits -- The first 256 entries are the reciprocal (1/x) lookup table, -- and the remaining 768 entries are the reciprocal square root table. @@ -503,7 +550,7 @@ architecture behaviour of fpu is -- Split a DP floating-point number into components and work out its class. -- If is_int = 1, the input is considered an integer - function decode_dp(fpr: std_ulogic_vector(63 downto 0); is_int: std_ulogic; + function decode_dp(fpr: std_ulogic_vector(63 downto 0); is_fp: std_ulogic; is_32bint: std_ulogic; is_signed: std_ulogic) return fpu_reg_type is variable reg : fpu_reg_type; variable exp_nz : std_ulogic; @@ -513,11 +560,13 @@ architecture behaviour of fpu is variable cls : std_ulogic_vector(2 downto 0); begin reg.negative := fpr(63); + reg.denorm := '0'; exp_nz := or (fpr(62 downto 52)); exp_ao := and (fpr(62 downto 52)); frac_nz := or (fpr(51 downto 0)); low_nz := or (fpr(31 downto 0)); - if is_int = '0' then + if is_fp = '1' then + reg.denorm := frac_nz and not exp_nz; reg.exponent := signed(resize(unsigned(fpr(62 downto 52)), EXP_BITS)) - to_signed(1023, EXP_BITS); if exp_nz = '0' then reg.exponent := to_signed(-1022, EXP_BITS); @@ -735,7 +784,9 @@ begin variable fpscr_mask : std_ulogic_vector(31 downto 0); variable j, k : integer; variable flm : std_ulogic_vector(7 downto 0); - variable int_input : std_ulogic; + variable fpin_a : std_ulogic; + variable fpin_b : std_ulogic; + variable fpin_c : std_ulogic; variable is_32bint : std_ulogic; variable mask : std_ulogic_vector(63 downto 0); variable in_a0 : std_ulogic_vector(63 downto 0); @@ -795,14 +846,16 @@ begin variable rexp_sum : signed(EXP_BITS-1 downto 0); variable rsh_in1 : signed(EXP_BITS-1 downto 0); variable rsh_in2 : signed(EXP_BITS-1 downto 0); + variable exec_state : state_t; + variable opcbits : std_ulogic_vector(4 downto 0); variable int_result : std_ulogic; variable illegal : std_ulogic; begin v := r; v.complete := '0'; v.do_intr := '0'; - int_input := '0'; is_32bint := '0'; + exec_state := IDLE; if r.complete = '1' or r.do_intr = '1' then v.instr_done := '0'; @@ -823,6 +876,7 @@ begin v.single_prec := e_in.single; v.is_signed := e_in.is_signed; v.rc := e_in.rc; + v.fp_rc := '0'; v.is_cmp := e_in.out_cr; v.oe := e_in.oe; v.m32b := e_in.m32b; @@ -831,36 +885,79 @@ begin v.integer_op := '0'; v.divext := '0'; v.divmod := '0'; - if e_in.op = OP_FPOP or e_in.op = OP_FPOP_I then - v.longmask := e_in.single; - if e_in.op = OP_FPOP_I then - int_input := '1'; - end if; - else -- OP_DIV, OP_DIVE, OP_MOD - v.integer_op := '1'; - int_input := '1'; - is_32bint := e_in.single; - if e_in.op = OP_DIVE then + v.is_sqrt := '0'; + v.is_multiply := '0'; + fpin_a := '0'; + fpin_b := '0'; + fpin_c := '0'; + v.use_a := e_in.valid_a; + v.use_b := e_in.valid_b; + v.use_c := e_in.valid_c; + v.round_mode := '0' & r.fpscr(FPSCR_RN+1 downto FPSCR_RN); + case e_in.op is + when OP_FP_ARITH => + fpin_a := e_in.valid_a; + fpin_b := e_in.valid_b; + fpin_c := e_in.valid_c; + v.longmask := e_in.single; + v.fp_rc := e_in.rc; + exec_state := arith_decode(to_integer(unsigned(e_in.insn(5 downto 1)))); + if e_in.insn(5 downto 1) = "11001" or e_in.insn(5 downto 3) = "111" then + v.is_multiply := '1'; + end if; + if e_in.insn(5 downto 1) = "10110" or e_in.insn(5 downto 1) = "11010" then + v.is_sqrt := '1'; + end if; + if e_in.insn(5 downto 1) = "01111" then + v.round_mode := "001"; + end if; + when OP_FP_CMP => + fpin_a := e_in.valid_a; + fpin_b := e_in.valid_b; + exec_state := cmp_decode(to_integer(unsigned(e_in.insn(8 downto 6)))); + when OP_FP_MISC => + v.fp_rc := e_in.rc; + opcbits := e_in.insn(10) & e_in.insn(8) & e_in.insn(4) & e_in.insn(2) & e_in.insn(1); + exec_state := misc_decode(to_integer(unsigned(opcbits))); + when OP_FP_MOVE => + v.fp_rc := e_in.rc; + fpin_a := e_in.valid_a; + fpin_b := e_in.valid_b; + fpin_c := e_in.valid_c; + if e_in.insn(5) = '0' then + exec_state := DO_FMR; + else + exec_state := DO_FSEL; + end if; + when OP_DIV => + v.integer_op := '1'; + is_32bint := e_in.single; + exec_state := DO_IDIVMOD; + when OP_DIVE => + v.integer_op := '1'; v.divext := '1'; - elsif e_in.op = OP_MOD then + is_32bint := e_in.single; + exec_state := DO_IDIVMOD; + when OP_MOD => + v.integer_op := '1'; v.divmod := '1'; - end if; - end if; + is_32bint := e_in.single; + exec_state := DO_IDIVMOD; + when others => + exec_state := DO_ILLEGAL; + end case; v.quieten_nan := '1'; v.tiny := '0'; v.denorm := '0'; - v.round_mode := '0' & r.fpscr(FPSCR_RN+1 downto FPSCR_RN); v.is_subtract := '0'; - v.is_multiply := '0'; - v.is_sqrt := '0'; v.add_bsmall := '0'; v.doing_ftdiv := "00"; v.int_ovf := '0'; v.div_close := '0'; - adec := decode_dp(e_in.fra, int_input, is_32bint, e_in.is_signed); - bdec := decode_dp(e_in.frb, int_input, is_32bint, e_in.is_signed); - cdec := decode_dp(e_in.frc, int_input, '0', '0'); + adec := decode_dp(e_in.fra, fpin_a, is_32bint, e_in.is_signed); + bdec := decode_dp(e_in.frb, fpin_b, is_32bint, e_in.is_signed); + cdec := decode_dp(e_in.frc, fpin_c, '0', '0'); v.a := adec; v.b := bdec; v.c := cdec; @@ -996,110 +1093,36 @@ begin case r.state is when IDLE => - v.use_a := '0'; - v.use_b := '0'; - v.use_c := '0'; v.invalid := '0'; v.negate := '0'; if e_in.valid = '1' then + v.opsel_a := AIN_B; v.busy := '1'; - case e_in.insn(5 downto 1) is - when "00000" => - if e_in.insn(8) = '1' then - if e_in.insn(6) = '0' then - v.state := DO_FTDIV; - else - v.state := DO_FTSQRT; + if e_in.op = OP_FP_ARITH and e_in.valid_a = '1' and + (e_in.valid_b = '0' or e_in.valid_c = '0') then + v.opsel_a := AIN_A; + end if; + if e_in.op = OP_FP_ARITH then + -- input selection for denorm cases + case e_in.insn(5 downto 1) is + when "10010" => -- fdiv + if v.b.mantissa(UNIT_BIT) = '0' and v.a.mantissa(UNIT_BIT) = '1' then + v.opsel_a := AIN_B; end if; - elsif e_in.insn(7) = '1' then - v.state := DO_MCRFS; - else - v.opsel_a := AIN_B; - v.state := DO_FCMP; - end if; - when "00110" => - if e_in.insn(10) = '0' then - if e_in.insn(8) = '0' then - v.state := DO_MTFSB; - else - v.state := DO_MTFSFI; + when "11001" => -- fmul + if v.c.mantissa(UNIT_BIT) = '0' and v.a.mantissa(UNIT_BIT) = '1' then + v.opsel_a := AIN_C; end if; - else - v.state := DO_FMRG; - end if; - when "00111" => - if e_in.insn(8) = '0' then - v.state := DO_MFFS; - else - v.state := DO_MTFSF; - end if; - when "01000" => - v.opsel_a := AIN_B; - if e_in.insn(9 downto 8) /= "11" then - v.state := DO_FMR; - else - v.state := DO_FRI; - end if; - when "01001" | "01011" => - -- integer divides and mods, major opcode 31 - v.opsel_a := AIN_B; - v.state := DO_IDIVMOD; - when "01100" => - v.opsel_a := AIN_B; - v.state := DO_FRSP; - when "01110" => - v.opsel_a := AIN_B; - if int_input = '1' then - -- fcfid[u][s] - v.state := DO_FCFID; - else - v.state := DO_FCTI; - end if; - when "01111" => - v.round_mode := "001"; - v.opsel_a := AIN_B; - v.state := DO_FCTI; - when "10010" => - v.opsel_a := AIN_A; - if v.b.mantissa(UNIT_BIT) = '0' and v.a.mantissa(UNIT_BIT) = '1' then - v.opsel_a := AIN_B; - end if; - v.state := DO_FDIV; - when "10100" | "10101" => - v.opsel_a := AIN_A; - v.state := DO_FADD; - when "10110" => - v.is_sqrt := '1'; - v.opsel_a := AIN_B; - v.state := DO_FSQRT; - when "10111" => - v.state := DO_FSEL; - when "11000" => - v.opsel_a := AIN_B; - v.state := DO_FRE; - when "11001" => - v.is_multiply := '1'; - v.opsel_a := AIN_A; - if v.c.mantissa(UNIT_BIT) = '0' and v.a.mantissa(UNIT_BIT) = '1' then - v.opsel_a := AIN_C; - end if; - v.state := DO_FMUL; - when "11010" => - v.is_sqrt := '1'; - v.opsel_a := AIN_B; - v.state := DO_FRSQRTE; - when "11100" | "11101" | "11110" | "11111" => - if v.a.mantissa(UNIT_BIT) = '0' then - v.opsel_a := AIN_A; - elsif v.c.mantissa(UNIT_BIT) = '0' then - v.opsel_a := AIN_C; - else - v.opsel_a := AIN_B; - end if; - v.state := DO_FMADD; - when others => - v.state := DO_ILLEGAL; - end case; + when "11100" | "11101" | "11110" | "11111" => -- fmadd etc. + if v.a.mantissa(UNIT_BIT) = '0' then + v.opsel_a := AIN_A; + elsif v.c.mantissa(UNIT_BIT) = '0' then + v.opsel_a := AIN_C; + end if; + when others => + end case; + end if; + v.state := exec_state; end if; v.x := '0'; v.old_exc := r.fpscr(FPSCR_VX downto FPSCR_XX); @@ -1444,8 +1467,6 @@ begin rs_sel2 <= RSH2_A; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_a := '1'; - v.use_b := '1'; is_add := r.a.negative xor r.b.negative xor r.insn(1); if r.a.class = FINITE and r.b.class = FINITE then v.is_subtract := not is_add; @@ -1493,8 +1514,6 @@ begin v.result_class := r.a.class; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_a := '1'; - v.use_c := '1'; re_sel1 <= REXP1_A; re_sel2 <= REXP2_C; re_set_result <= '1'; @@ -1532,8 +1551,6 @@ begin v.result_class := r.a.class; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_a := '1'; - v.use_b := '1'; v.result_sign := r.a.negative xor r.b.negative; re_sel1 <= REXP1_A; re_sel2 <= REXP2_B; @@ -1594,7 +1611,6 @@ begin v.result_sign := r.b.negative; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_b := '1'; re_sel2 <= REXP2_B; re_set_result <= '1'; case r.b.class is @@ -1631,7 +1647,6 @@ begin v.result_sign := r.b.negative; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_b := '1'; re_sel2 <= REXP2_B; re_set_result <= '1'; case r.b.class is @@ -1658,7 +1673,6 @@ begin v.result_sign := r.b.negative; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_b := '1'; re_sel2 <= REXP2_B; re_set_result <= '1'; -- set shift to 1 @@ -1705,9 +1719,6 @@ begin rs_sel1 <= RSH1_B; v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; - v.use_a := '1'; - v.use_b := '1'; - v.use_c := '1'; is_add := r.a.negative xor r.c.negative xor r.b.negative xor r.insn(1); if r.a.class = FINITE and r.c.class = FINITE and (r.b.class = FINITE or r.b.class = ZERO) then @@ -1769,7 +1780,7 @@ begin when RENORM_A => rs_norm <= '1'; v.state := RENORM_A2; - if r.insn(4) = '1' then + if r.use_c = '1' and r.c.denorm = '1' then v.opsel_a := AIN_C; else v.opsel_a := AIN_B; @@ -3532,7 +3543,7 @@ begin v.state := IDLE; v.busy := '0'; v.f2stall := '0'; - if r.rc = '1' and (r.op = OP_FPOP or r.op = OP_FPOP_I) then + if r.fp_rc = '1' then v.cr_result := v.fpscr(FPSCR_FX downto FPSCR_OX); end if; v.sp_result := r.single_prec; diff --git a/scripts/fmt_log/fmt_log.c b/scripts/fmt_log/fmt_log.c index 3646087..09d41ad 100644 --- a/scripts/fmt_log/fmt_log.c +++ b/scripts/fmt_log/fmt_log.c @@ -88,13 +88,13 @@ const char *units[4] = { "--", "al", "ls", "fp" }; const char *ops[64] = { "illegal", "nop ", "add ", "and ", "attn ", "b ", "bc ", "bcreg ", - "bperm ", "cmp ", "cmpb ", "cmpeqb ", "cmprb ", "cntz ", "crop ", "darn ", - "dcbf ", "dcbst ", "dcbt ", "dcbtst ", "dcbz ", "div ", "dive ", "exts ", - "extswsl", "fpop ", "fpopi ", "icbi ", "icbt ", "isel ", "isync ", "ld ", - "st ", "mcrxrx ", "mfcr ", "mfmsr ", "mfspr ", "mod ", "mtcrf ", "mtmsr ", - "mtspr ", "mull64 ", "mulh64 ", "mulh32 ", "or ", "popcnt ", "prty ", "rfid ", - "rlc ", "rlcl ", "rlcr ", "sc ", "setb ", "shl ", "shr ", "sync ", - "tlbie ", "trap ", "xor ", "bcd ", "addg6s ", "ffail ", "?62 ", "?63 " + "bcd ", "bperm ", "cmp ", "cmpb ", "cmpeqb ", "cmprb ", "cntz ", "crop ", + "darn ", "dcbf ", "dcbst ", "dcbt ", "dcbtst ", "dcbz ", "icbi ", "icbt ", + "fpcmp ", "fparith", "fpmove ", "fpmisc ", "div ", "dive ", "mod ", "exts ", + "extswsl", "isel ", "isync ", "ld ", "st ", "mcrxrx ", "mfcr ", "mfmsr ", + "mfspr ", "mtcrf ", "mtmsr ", "mtspr ", "mull64 ", "mulh64 ", "mulh32 ", "or ", + "popcnt ", "prty ", "rfid ", "rlc ", "rlcl ", "rlcr ", "sc ", "setb ", + "shl ", "shr ", "sync ", "tlbie ", "trap ", "xor ", "addg6s ", "ffail ", }; const char *spr_names[13] = From 09965b91024faceab13446ab6801fdb2614da71e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 27 May 2022 22:23:50 +1000 Subject: [PATCH 07/22] FPU: Set sign of 0 result of subtraction in pack_dp When a floating-point subtraction results in a zero result, the sign of the result is required to be positive in all rounding modes except the round to minus infinity mode, when it is negative. Consolidate the logic for doing this in one place, in the pack_dp function, instead of having it at each place where a zero result is generated. Since fnmadd[s] and fnmsub[s] negate the result after this rule has been applied, we use the r.negate signal to indicate a negation which is now done in pack_dp. Thus the EXC_RESULT state no longer uses r.negate, and in fact doesn't set v.result_sign at all; that is now done in the states that lead into EXC_RESULT. Signed-off-by: Paul Mackerras --- fpu.vhdl | 73 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/fpu.vhdl b/fpu.vhdl index 3ea51b9..417a318 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -169,6 +169,9 @@ architecture behaviour of fpu is oe : std_ulogic; xerc : xer_common_t; xerc_result : xer_common_t; + res_negate : std_ulogic; + res_subtract : std_ulogic; + res_rmode : std_ulogic_vector(2 downto 0); end record; type lookup_table is array(0 to 1023) of std_ulogic_vector(17 downto 0); @@ -605,15 +608,21 @@ architecture behaviour of fpu is end; -- Construct a DP floating-point result from components - function pack_dp(sign: std_ulogic; class: fp_number_class; exp: signed(EXP_BITS-1 downto 0); - mantissa: std_ulogic_vector; single_prec: std_ulogic; quieten_nan: std_ulogic) + function pack_dp(negative: std_ulogic; class: fp_number_class; exp: signed(EXP_BITS-1 downto 0); + mantissa: std_ulogic_vector; single_prec: std_ulogic; quieten_nan: std_ulogic; + negate: std_ulogic; is_subtract: std_ulogic; round_mode: std_ulogic_vector) return std_ulogic_vector is variable dp_result : std_ulogic_vector(63 downto 0); + variable sign : std_ulogic; begin dp_result := (others => '0'); - dp_result(63) := sign; + sign := negative; case class is when ZERO => + if is_subtract = '1' then + -- set result sign depending on rounding mode + sign := round_mode(0) and round_mode(1); + end if; when FINITE => if mantissa(UNIT_BIT) = '1' then -- normalized number @@ -633,6 +642,7 @@ architecture behaviour of fpu is dp_result(28 downto 0) := mantissa(SP_LSB - 1 downto DP_LSB); end if; end case; + dp_result(63) := sign xor negate; return dp_result; end; @@ -1468,8 +1478,8 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; is_add := r.a.negative xor r.b.negative xor r.insn(1); + v.is_subtract := not is_add; if r.a.class = FINITE and r.b.class = FINITE then - v.is_subtract := not is_add; v.add_bsmall := r.exp_cmp; v.opsel_a := AIN_B; if r.exp_cmp = '0' then @@ -1491,18 +1501,13 @@ begin v.fpscr(FPSCR_VXISI) := '1'; qnan_result := '1'; arith_done := '1'; - elsif r.a.class = ZERO and r.b.class = ZERO and is_add = '0' then - -- return -0 for rounding to -infinity - v.result_sign := r.round_mode(1) and r.round_mode(0); - arith_done := '1'; elsif r.a.class = INFINITY or r.b.class = ZERO then - -- result is A - v.opsel_a := AIN_A; - v.state := EXC_RESULT; + -- result is A; we're already set up to put A into R + arith_done := '1'; else -- result is +/- B v.opsel_a := AIN_B; - v.negate := not r.insn(1); + v.result_sign := r.b.negative xnor r.insn(1); v.state := EXC_RESULT; end if; end if; @@ -1541,7 +1546,6 @@ begin else -- r.c.class is ZERO or INFINITY v.opsel_a := AIN_C; - v.negate := r.a.negative; v.state := EXC_RESULT; end if; end if; @@ -1599,8 +1603,10 @@ begin v.fpscr(FPSCR_FI) := '0'; if r.a.class = ZERO or (r.a.negative = '0' and r.a.class /= NAN) then v.opsel_a := AIN_C; + v.result_sign := r.c.negative; else v.opsel_a := AIN_B; + v.result_sign := r.b.negative; end if; v.quieten_nan := '0'; v.state := EXC_RESULT; @@ -1720,9 +1726,10 @@ begin v.fpscr(FPSCR_FR) := '0'; v.fpscr(FPSCR_FI) := '0'; is_add := r.a.negative xor r.c.negative xor r.b.negative xor r.insn(1); + v.negate := r.insn(2); + v.is_subtract := not is_add; if r.a.class = FINITE and r.c.class = FINITE and (r.b.class = FINITE or r.b.class = ZERO) then - v.is_subtract := not is_add; -- Make sure A and C are normalized if r.a.mantissa(UNIT_BIT) = '0' then v.state := RENORM_A; @@ -1730,13 +1737,13 @@ begin v.state := RENORM_C; elsif r.b.class = ZERO then -- no addend, degenerates to multiply - v.result_sign := r.a.negative xor r.c.negative xor r.insn(2); + v.result_sign := r.a.negative xor r.c.negative; f_to_multiply.valid <= '1'; v.is_multiply := '1'; v.state := MULT_1; elsif r.madd_cmp = '0' then -- addend is bigger, do multiply first - v.result_sign := not (r.b.negative xor r.insn(1) xor r.insn(2)); + v.result_sign := r.b.negative xnor r.insn(1); f_to_multiply.valid <= '1'; v.first := '1'; v.state := FMADD_0; @@ -1760,19 +1767,14 @@ begin else -- result is infinity v.result_class := INFINITY; - v.result_sign := r.a.negative xor r.c.negative xor r.insn(2); + v.result_sign := r.a.negative xor r.c.negative; arith_done := '1'; end if; else -- Here A is zero, C is zero, or B is infinity -- Result is +/-B in all of those cases v.opsel_a := AIN_B; - if r.b.class /= ZERO or is_add = '1' then - v.negate := not (r.insn(1) xor r.insn(2)); - else - -- have to be careful about rule for 0 - 0 result sign - v.negate := r.b.negative xor (r.round_mode(1) and r.round_mode(0)) xor r.insn(2); - end if; + v.result_sign := r.b.negative xnor r.insn(1); v.state := EXC_RESULT; end if; end if; @@ -1910,10 +1912,6 @@ begin elsif (r_hi_nz or r_lo_nz or (or (r.r(DP_LSB - 1 downto 0)))) = '0' then -- r.x must be zero at this point v.result_class := ZERO; - if r.is_subtract = '1' then - -- set result sign depending on rounding mode - v.result_sign := r.round_mode(1) and r.round_mode(0); - end if; arith_done := '1'; else rs_norm <= '1'; @@ -1970,7 +1968,7 @@ begin -- product is bigger here -- shift B right and use it as the addend to the multiplier -- for subtract, multiplier does B - A * C - v.result_sign := r.a.negative xor r.c.negative xor r.insn(2) xor r.is_subtract; + v.result_sign := r.a.negative xor r.c.negative xor r.is_subtract; re_sel2 <= REXP2_B; re_set_result <= '1'; -- set shift to b.exp - result_exp + 64 @@ -2030,7 +2028,6 @@ begin if s_nz = '0' then -- must be a subtraction, and r.x must be zero v.result_class := ZERO; - v.result_sign := r.round_mode(1) and r.round_mode(0); arith_done := '1'; else -- R is all zeroes but there are non-zero bits in S @@ -2572,10 +2569,6 @@ begin rs_neg2 <= '1'; if mant_nz = '0' then v.result_class := ZERO; - if r.is_subtract = '1' then - -- set result sign depending on rounding mode - v.result_sign := r.round_mode(1) and r.round_mode(0); - end if; arith_done := '1'; else -- Renormalize result after rounding @@ -2597,6 +2590,7 @@ begin arith_done := '1'; when NAN_RESULT => + v.negate := '0'; if (r.use_a = '1' and r.a.class = NAN and r.a.mantissa(QNAN_BIT) = '0') or (r.use_b = '1' and r.b.class = NAN and r.b.mantissa(QNAN_BIT) = '0') or (r.use_c = '1' and r.c.class = NAN and r.c.mantissa(QNAN_BIT) = '0') then @@ -2606,10 +2600,13 @@ begin end if; if r.use_a = '1' and r.a.class = NAN then v.opsel_a := AIN_A; + v.result_sign := r.a.negative; elsif r.use_b = '1' and r.b.class = NAN then v.opsel_a := AIN_B; + v.result_sign := r.b.negative; elsif r.use_c = '1' and r.c.class = NAN then v.opsel_a := AIN_C; + v.result_sign := r.c.negative; end if; v.state := EXC_RESULT; @@ -2617,15 +2614,12 @@ begin -- r.opsel_a = AIN_A, AIN_B or AIN_C according to which input is the result case r.opsel_a is when AIN_B => - v.result_sign := r.b.negative xor r.negate; re_sel2 <= REXP2_B; v.result_class := r.b.class; when AIN_C => - v.result_sign := r.c.negative xor r.negate; re_sel2 <= REXP2_C; v.result_class := r.c.class; when others => - v.result_sign := r.a.negative xor r.negate; re_sel1 <= REXP1_A; v.result_class := r.a.class; end case; @@ -3171,6 +3165,7 @@ begin invalid := '1'; v.result_class := NAN; v.result_sign := '0'; + v.negate := '0'; misc_sel <= "0001"; opsel_r <= RES_MISC; arith_done := '1'; @@ -3550,6 +3545,9 @@ begin v.int_result := int_result; v.illegal := illegal; v.nsnan_result := v.quieten_nan; + v.res_negate := v.negate; + v.res_subtract := v.is_subtract; + v.res_rmode := r.round_mode; if r.integer_op = '1' then v.cr_mask := num_to_fxm(0); elsif r.is_cmp = '0' then @@ -3581,7 +3579,8 @@ begin fp_result <= r.r; else fp_result <= pack_dp(r.result_sign, r.result_class, r.result_exp, r.r, - r.sp_result, r.nsnan_result); + r.sp_result, r.nsnan_result, + r.res_negate, r.res_subtract, r.res_rmode); end if; rin <= v; From 47895f8aff5f8ff0d1a3f86509e22c4e5290b181 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 30 Jul 2022 09:42:19 +1000 Subject: [PATCH 08/22] decode2: Decode unit and single-pipe attributes for mfspr/mtspr in decode2 Instead of doing that in decode1. That lets us get rid of the force_single and override_unit fields of reg_internal_t in decode1, which will simplify following changes to decode1. Signed-off-by: Paul Mackerras --- decode1.vhdl | 34 +--------------------------------- decode2.vhdl | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 40 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 8bea225..f50b82e 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -54,11 +54,9 @@ architecture behaviour of decode1 is type reg_internal_t is record override : std_ulogic; override_decode: decode_rom_t; - override_unit: std_ulogic; - force_single: std_ulogic; end record; constant reg_internal_t_init : reg_internal_t := - (override => '0', override_decode => illegal_inst, override_unit => '0', force_single => '0'); + (override => '0', override_decode => illegal_inst); signal ri, ri_in : reg_internal_t; @@ -703,31 +701,6 @@ begin end if; may_read_rb := '1'; - if std_match(f_in.insn(10 downto 1), "01-1010011") then - -- mfspr or mtspr - -- Make mtspr to slow SPRs single issue - if v.spr_info.valid = '1' then - vi.force_single := f_in.insn(8); - end if; - -- send MMU-related SPRs to loadstore1 - case sprn is - when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR => - vi.override_decode.unit := LDST; - vi.override_unit := '1'; - -- make mtspr to loadstore SPRs single-issue - if f_in.insn(8) = '1' then - vi.force_single := '1'; - end if; - when others => - end case; - -- FIXME: This is a bit fragile doing this here but sprn depends - -- on f_in.insn - if is_X(f_in.insn) then - vi.override_decode.unit := NONE; - vi.override_unit := 'X'; - vi.force_single := 'X'; - end if; - end if; if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then -- lower half of column 23 has FP loads and stores fprs := '1'; @@ -880,11 +853,6 @@ begin d_out <= r; if ri.override = '1' then d_out.decode <= ri.override_decode; - elsif ri.override_unit = '1' then - d_out.decode.unit <= ri.override_decode.unit; - end if; - if ri.force_single = '1' then - d_out.decode.sgl_pipe <= '1'; end if; f_out.redirect <= br.predict; f_out.redirect_nia <= br_target & "00"; diff --git a/decode2.vhdl b/decode2.vhdl index 0592fe4..6cac985 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -389,6 +389,7 @@ begin variable v : reg_type; variable length : std_ulogic_vector(3 downto 0); variable op : insn_type_t; + variable unit : unit_t; variable valid_in : std_ulogic; variable decctr : std_ulogic; variable sprs_busy : std_ulogic; @@ -401,6 +402,7 @@ begin v.e := Decode2ToExecute1Init; sprs_busy := '0'; + unit := d_in.decode.unit; if d_in.valid = '1' then v.prev_sgl := dc2.sgl_pipe; @@ -433,13 +435,27 @@ begin v.input_ov := '1'; -- need SO state if setting OV to 0 end if; when OP_MFSPR => - if decode_spr_num(d_in.insn) = SPR_XER then - v.input_ov := '1'; - end if; + case decode_spr_num(d_in.insn) is + when SPR_XER => + v.input_ov := '1'; + when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR => + unit := LDST; + when others => + end case; when OP_MTSPR => - if decode_spr_num(d_in.insn) = SPR_XER then - v.e.output_xer := '1'; - v.output_ov := '1'; + case decode_spr_num(d_in.insn) is + when SPR_XER => + v.e.output_xer := '1'; + v.output_ov := '1'; + when SPR_DAR | SPR_DSISR | SPR_PID | SPR_PTCR => + unit := LDST; + if d_in.valid = '1' then + v.sgl_pipe := '1'; + end if; + when others => + end case; + if d_in.spr_info.valid = '1' and d_in.valid = '1' then + v.sgl_pipe := '1'; end if; when OP_CMP | OP_MCRXRX => v.input_ov := '1'; @@ -528,7 +544,7 @@ begin -- execute unit v.e.nia := d_in.nia; - v.e.unit := d_in.decode.unit; + v.e.unit := unit; v.e.fac := d_in.decode.facility; v.e.read_reg1 := d_in.reg_a; v.e.read_reg2 := d_in.reg_b; From 5380d800399e8fddd6c25281617f97eeea8f7ff3 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 26 Jul 2022 14:55:29 +1000 Subject: [PATCH 09/22] decode1: Use block RAMs in decode This combines the various decode arrays in decode1 into two, one indexed by the major opcode (bits 31--26 of the instruction) together with bits 4--0 of the instruction, and the other indexed mostly by the minor opcode (bits 10--1), with some swizzles to accommodate the relevant parts of the minor opcode space for opcodes 19, 31, 59 and 63 within a 2k entry ROM (11 address bits). These are called the "major" and the "row" decode ROMs respectively. (Bits 10--6 of the instruction are called the "row index", and bits 5--1, or 5--0 for some opcodes, are called the "column index", because of the way the opcode maps in the ISA are laid out.) Both ROMs are looked up each cycle and the result from one or other, or from an override in ri.override_decode, are selected after a clock edge. This uses quite a lot of BRAM resources. In future a predecode step will reduce the BRAM usage substantially. Signed-off-by: Paul Mackerras --- decode1.vhdl | 975 +++++++++++++++++++++++++-------------------------- 1 file changed, 468 insertions(+), 507 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index f50b82e..54754ab 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -52,11 +52,15 @@ architecture behaviour of decode1 is constant DVU : unit_t := divider_unit(HAS_FPU); type reg_internal_t is record + maj_decode : decode_rom_t; + row_decode : decode_rom_t; + use_row : std_ulogic; override : std_ulogic; override_decode: decode_rom_t; end record; constant reg_internal_t_init : reg_internal_t := - (override => '0', override_decode => illegal_inst); + (maj_decode => illegal_inst, row_decode => illegal_inst, use_row => '0', + override => '0', override_decode => illegal_inst); signal ri, ri_in : reg_internal_t; @@ -68,457 +72,431 @@ architecture behaviour of decode1 is signal br, br_in : br_predictor_t; - subtype major_opcode_t is unsigned(5 downto 0); - type major_rom_array_t is array(0 to 63) of decode_rom_t; - type minor_valid_array_t is array(0 to 1023) of std_ulogic; - type minor_valid_array_2t is array(0 to 2047) of std_ulogic; - type op_4_subop_array_t is array(0 to 63) of decode_rom_t; - type op_19_subop_array_t is array(0 to 7) of decode_rom_t; - type op_30_subop_array_t is array(0 to 15) of decode_rom_t; - type op_31_subop_array_t is array(0 to 1023) of decode_rom_t; - type op_59_subop_array_t is array(0 to 31) of decode_rom_t; - type minor_rom_array_2_t is array(0 to 3) of decode_rom_t; - type op_63_subop_array_0_t is array(0 to 511) of decode_rom_t; - type op_63_subop_array_1_t is array(0 to 16) of decode_rom_t; - - constant major_decode_rom_array : major_rom_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 12 => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addic - 13 => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- addic. - 14 => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addi - 15 => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addis - 28 => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andi. - 29 => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andis. - 0 => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn - 18 => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b - 16 => (ALU, NONE, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc - 11 => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi - 10 => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli - 34 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz - 35 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzu - 50 => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfd - 51 => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdu - 48 => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfs - 49 => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsu - 42 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lha - 43 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhau - 40 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhz - 41 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzu - 32 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwz - 33 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzu - 7 => (ALU, NONE, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- mulli - 24 => (ALU, NONE, OP_OR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ori - 25 => (ALU, NONE, OP_OR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- oris - 20 => (ALU, NONE, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwimi - 21 => (ALU, NONE, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwinm - 23 => (ALU, NONE, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwnm - 17 => (ALU, NONE, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sc - 38 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stb - 39 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbu - 54 => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfd - 55 => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdu - 52 => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfs - 53 => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsu - 44 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sth - 45 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthu - 36 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stw - 37 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwu - 8 => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- subfic - 2 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tdi - 3 => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- twi - 26 => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xori - 27 => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xoris + type decoder_rom_t is array(0 to 2047) of decode_rom_t; + + -- Indexed by bits 31-26 (major opcode) and 4-0 of instruction word + constant major_decode_rom : decoder_rom_t := ( + -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt + -- op in out A out in out len ext pipe + 2#001100_00000# to 2#001100_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addic + 2#001101_00000# to 2#001101_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- addic. + 2#001110_00000# to 2#001110_11111# => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addi + 2#001111_00000# to 2#001111_11111# => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addis + 2#010011_00100# to 2#010011_00101# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addpcis + 2#011100_00000# to 2#011100_11111# => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andi. + 2#011101_00000# to 2#011101_11111# => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andis. + 2#000000_00000# to 2#000000_11111# => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn + 2#010010_00000# to 2#010010_11111# => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b + 2#010000_00000# to 2#010000_11111# => (ALU, NONE, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc + 2#001011_00000# to 2#001011_11111# => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi + 2#001010_00000# to 2#001010_11111# => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli + 2#100010_00000# to 2#100010_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz + 2#100011_00000# to 2#100011_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzu + 2#110010_00000# to 2#110010_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfd + 2#110011_00000# to 2#110011_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdu + 2#110000_00000# to 2#110000_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfs + 2#110001_00000# to 2#110001_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsu + 2#101010_00000# to 2#101010_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lha + 2#101011_00000# to 2#101011_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhau + 2#101000_00000# to 2#101000_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhz + 2#101001_00000# to 2#101001_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzu + 2#100000_00000# to 2#100000_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwz + 2#100001_00000# to 2#100001_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzu + 2#000111_00000# to 2#000111_11111# => (ALU, NONE, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- mulli + 2#011000_00000# to 2#011000_11111# => (ALU, NONE, OP_OR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ori + 2#011001_00000# to 2#011001_11111# => (ALU, NONE, OP_OR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- oris + 2#010100_00000# to 2#010100_11111# => (ALU, NONE, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwimi + 2#010101_00000# to 2#010101_11111# => (ALU, NONE, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwinm + 2#010111_00000# to 2#010111_11111# => (ALU, NONE, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwnm + 2#010001_00000# to 2#010001_11111# => (ALU, NONE, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sc + 2#100110_00000# to 2#100110_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stb + 2#100111_00000# to 2#100111_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbu + 2#110110_00000# to 2#110110_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfd + 2#110111_00000# to 2#110111_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdu + 2#110100_00000# to 2#110100_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfs + 2#110101_00000# to 2#110101_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsu + 2#101100_00000# to 2#101100_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sth + 2#101101_00000# to 2#101101_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthu + 2#100100_00000# to 2#100100_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stw + 2#100101_00000# to 2#100101_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwu + 2#001000_00000# to 2#001000_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- subfic + 2#000010_00000# to 2#000010_11111# => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tdi + 2#000011_00000# to 2#000011_11111# => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- twi + 2#011010_00000# to 2#011010_11111# => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xori + 2#011011_00000# to 2#011011_11111# => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xoris + -- major opcode 4 + 2#000100_10000# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddhd + 2#000100_10001# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- maddhdu + 2#000100_10011# => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddld + -- major opcode 30 + 2#011110_01000# to 2#011110_01001# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic + 2#011110_01010# to 2#011110_01011# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic + 2#011110_00000# to 2#011110_00001# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl + 2#011110_00010# to 2#011110_00011# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl + 2#011110_00100# to 2#011110_00101# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr + 2#011110_00110# to 2#011110_00111# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr + 2#011110_01100# to 2#011110_01101# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi + 2#011110_01110# to 2#011110_01111# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi + 2#011110_10000# to 2#011110_10001# => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcl + 2#011110_10010# to 2#011110_10011# => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcr + -- major opcode 58 + 2#111010_00000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_00001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_00010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_00100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_00101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_00110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_01000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_01001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_01010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_01100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_01101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_01110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_10000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_10001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_10010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_11000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_11001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_11010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_11100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld + 2#111010_11101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu + 2#111010_11110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + -- major opcode 59 + 2#111011_00100# to 2#111011_00101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fdivs + 2#111011_01000# to 2#111011_01001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsubs + 2#111011_01010# to 2#111011_01011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fadds + 2#111011_01100# to 2#111011_01101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsqrts + 2#111011_10000# to 2#111011_10001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fres + 2#111011_10010# to 2#111011_10011# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmuls + 2#111011_10100# to 2#111011_10101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- frsqrtes + 2#111011_11000# to 2#111011_11001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmsubs + 2#111011_11010# to 2#111011_11011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmadds + 2#111011_11100# to 2#111011_11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmsubs + 2#111011_11110# to 2#111011_11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmadds + -- major opcode 62 + 2#111110_00000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_00001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_00100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_00101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_01000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_01001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_01100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_01101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_10000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_10001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_10100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_11000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_11001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_11100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std + 2#111110_11101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + -- major opcode 63 + 2#111111_00100# to 2#111111_00101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fdiv + 2#111111_01000# to 2#111111_01001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsub + 2#111111_01010# to 2#111111_01011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fadd + 2#111111_01100# to 2#111111_01101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsqrt + 2#111111_01110# to 2#111111_01111# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsel + 2#111111_10000# to 2#111111_10001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fre + 2#111111_10010# to 2#111111_10011# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmul + 2#111111_10100# to 2#111111_10101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- frsqrte + 2#111111_11000# to 2#111111_11001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmsub + 2#111111_11010# to 2#111111_11011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmadd + 2#111111_11100# to 2#111111_11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmsub + 2#111111_11110# to 2#111111_11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmadd others => illegal_inst ); - -- indexed by bits 5..0 and 10..6 of instruction word - constant decode_op_4_valid : minor_valid_array_2t := ( - 2#11000000000# to 2#11000011111# => '1', -- maddhd - 2#11000100000# to 2#11000111111# => '1', -- maddhdu - 2#11001100000# to 2#11001111111# => '1', -- maddld - others => '0' - ); - - -- indexed by bits 5..0 of instruction word - constant decode_op_4_array : op_4_subop_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#110000# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddhd - 2#110001# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- maddhdu - 2#110011# => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddld - others => decode_rom_init - ); - - -- indexed by bits 10..1 of instruction word - constant decode_op_19_valid : minor_valid_array_t := ( - 2#0001000000# to 2#0001011111# => '1', -- addpcis, 5 upper bits are part of constant - 2#1000010000# => '1', -- bcctr - 2#1000000000# => '1', -- bclr - 2#1000010001# => '1', -- bctar - 2#0000101000# => '1', -- crand - 2#0000100100# => '1', -- crandc - 2#0000101001# => '1', -- creqv - 2#0000100111# => '1', -- crnand - 2#0000100001# => '1', -- crnor - 2#0000101110# => '1', -- cror - 2#0000101101# => '1', -- crorc - 2#0000100110# => '1', -- crxor - 2#1011000100# => '1', -- isync - 2#0000000000# => '1', -- mcrf - 2#1001000000# => '1', -- rfid - others => '0' - ); - - -- indexed by bits 5, 3, 2 of instruction word - constant decode_op_19_array : op_19_subop_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - -- mcrf; and cr logical ops - 2#000# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - -- addpcis - 2#001# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - -- bclr, bcctr, bctar - 2#100# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), - -- isync - 2#111# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - -- rfid - 2#101# => (ALU, NONE, OP_RFID, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - others => illegal_inst - ); - - constant decode_op_30_array : op_30_subop_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#0100# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic - 2#0101# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic - 2#0000# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl - 2#0001# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl - 2#0010# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr - 2#0011# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr - 2#0110# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi - 2#0111# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi - 2#1000# => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcl - 2#1001# => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcr - others => illegal_inst - ); - - -- Note: reformat with column -t -o ' ' - constant decode_op_31_array : op_31_subop_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#0100001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- add - 2#1100001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addo - 2#0000001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addc - 2#1000001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addco - 2#0010001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- adde - 2#1010001010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addeo - 2#0010101010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addex - 2#0001001010# => (ALU, NONE, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addg6s - 2#0011101010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addme - 2#1011101010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addmeo - 2#0011001010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addze - 2#1011001010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addzeo - 2#0000011100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- and - 2#0000111100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- andc - 2#0011111100# => (ALU, NONE, OP_BPERM, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- bperm - 2#0100111010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cbcdtd - 2#0100011010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cdtbcd - 2#0000000000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmp - 2#0111111100# => (ALU, NONE, OP_CMPB, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpb - 2#0011100000# => (ALU, NONE, OP_CMPEQB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpeqb - 2#0000100000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpl - 2#0011000000# => (ALU, NONE, OP_CMPRB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmprb - 2#0000111010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cntlzd - 2#0000011010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cntlzw - 2#1000111010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cnttzd - 2#1000011010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cnttzw - 2#1011110011# => (ALU, NONE, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- darn - 2#0001010110# => (ALU, NONE, OP_DCBF, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbf - 2#0000110110# => (ALU, NONE, OP_DCBST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbst - 2#0100010110# => (ALU, NONE, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbt - 2#0011110110# => (ALU, NONE, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbtst - 2#1111110110# => (LDST, NONE, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbz - 2#0110001001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeu - 2#1110001001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeuo - 2#0110001011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweu - 2#1110001011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweuo - 2#0110101001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divde - 2#1110101001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdeo - 2#0110101011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwe - 2#1110101011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divweo - 2#0111001001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdu - 2#1111001001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divduo - 2#0111001011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwu - 2#1111001011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwuo - 2#0111101001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divd - 2#1111101001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdo - 2#0111101011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divw - 2#1111101011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwo - 2#1100110110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dss - 2#0101010110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dst - 2#0101110110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dstst - 2#1101010110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- eieio - 2#0100011100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- eqv - 2#1110111010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsb - 2#1110011010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsh - 2#1111011010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsw - 2#1101111010# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli - 2#1101111011# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli - 2#1111010110# => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbi - 2#0000010110# => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbt - 2#0000001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0000101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0001001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0001101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0010001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0010101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0011001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0011101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0100001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0100101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0101001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0101101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0110001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0110101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0111001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0111101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1000001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1000101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1001001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1001101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1010001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1010101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1011001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1011101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1100001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1100101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1101001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1101101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1110001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1110101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1111001111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#1111101111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0000110100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lbarx - 2#1101010101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzcix - 2#0001110111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzux - 2#0001010111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzx - 2#0001010100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- ldarx - 2#1000010100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldbrx - 2#1101110101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldcix - 2#0000110101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldux - 2#0000010101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldx - 2#1001010111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfdx - 2#1001110111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdux - 2#1101010111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwax - 2#1101110111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwzx - 2#1000010111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfsx - 2#1000110111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsux - 2#0001110100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lharx - 2#0101110111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhaux - 2#0101010111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhax - 2#1100010110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhbrx - 2#1100110101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzcix - 2#0100110111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzux - 2#0100010111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzx - 2#0000010100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lwarx - 2#0101110101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwaux - 2#0101010101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwax - 2#1000010110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwbrx - 2#1100010101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzcix - 2#0000110111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzux - 2#0000010111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzx - 2#1001000000# => (ALU, NONE, OP_MCRXRX, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mcrxrx - 2#0000010011# => (ALU, NONE, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfcr/mfocrf - 2#0001010011# => (ALU, NONE, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- mfmsr - 2#0101010011# => (ALU, NONE, OP_MFSPR, NONE, NONE, RS, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfspr - 2#0100001001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- modud - 2#0100001011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- moduw - 2#1100001001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- modsd - 2#1100001011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0', NONE), -- modsw - 2#0010010000# => (ALU, NONE, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtcrf/mtocrf - 2#0010010010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- mtmsr - 2#0010110010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtmsrd # ignore top bits and d - 2#0111010011# => (ALU, NONE, OP_MTSPR, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtspr - 2#0001001001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd - 2#0000001001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu - 2#0001001011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw - 2#0000001011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu + constant row_decode_rom : decoder_rom_t := ( + -- Major opcode 31 + -- Address bits are 0, insn(10:1) + -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt + -- op in out A out in out len ext pipe + 2#0_01000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- add + 2#0_11000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addo + 2#0_00000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addc + 2#0_10000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addco + 2#0_00100_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- adde + 2#0_10100_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addeo + 2#0_00101_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addex + 2#0_00010_01010# => (ALU, NONE, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addg6s + 2#0_00111_01010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addme + 2#0_10111_01010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addmeo + 2#0_00110_01010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addze + 2#0_10110_01010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addzeo + 2#0_00000_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- and + 2#0_00001_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- andc + 2#0_00111_11100# => (ALU, NONE, OP_BPERM, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- bperm + 2#0_01001_11010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cbcdtd + 2#0_01000_11010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cdtbcd + 2#0_00000_00000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmp + 2#0_01111_11100# => (ALU, NONE, OP_CMPB, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpb + 2#0_00111_00000# => (ALU, NONE, OP_CMPEQB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpeqb + 2#0_00001_00000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpl + 2#0_00110_00000# => (ALU, NONE, OP_CMPRB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmprb + 2#0_00001_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cntlzd + 2#0_00000_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cntlzw + 2#0_10001_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cnttzd + 2#0_10000_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cnttzw + 2#0_10111_10011# => (ALU, NONE, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- darn + 2#0_00010_10110# => (ALU, NONE, OP_DCBF, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbf + 2#0_00001_10110# => (ALU, NONE, OP_DCBST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbst + 2#0_01000_10110# => (ALU, NONE, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbt + 2#0_00111_10110# => (ALU, NONE, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbtst + 2#0_11111_10110# => (LDST, NONE, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbz + 2#0_01100_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeu + 2#0_11100_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeuo + 2#0_01100_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweu + 2#0_11100_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweuo + 2#0_01101_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divde + 2#0_11101_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdeo + 2#0_01101_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwe + 2#0_11101_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divweo + 2#0_01110_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdu + 2#0_11110_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divduo + 2#0_01110_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwu + 2#0_11110_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwuo + 2#0_01111_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divd + 2#0_11111_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdo + 2#0_01111_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divw + 2#0_11111_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwo + 2#0_11001_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dss + 2#0_01010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dst + 2#0_01011_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dstst + 2#0_11010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- eieio + 2#0_01000_11100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- eqv + 2#0_11101_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsb + 2#0_11100_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsh + 2#0_11110_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsw + 2#0_11011_11010# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli + 2#0_11011_11011# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli + 2#0_11110_10110# => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbi + 2#0_00000_10110# => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbt + 2#0_00000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_01111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_10111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_11111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel + 2#0_00001_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lbarx + 2#0_11010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzcix + 2#0_00011_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzux + 2#0_00010_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzx + 2#0_00010_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- ldarx + 2#0_10000_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldbrx + 2#0_11011_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldcix + 2#0_00001_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldux + 2#0_00000_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldx + 2#0_10010_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfdx + 2#0_10011_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdux + 2#0_11010_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwax + 2#0_11011_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwzx + 2#0_10000_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfsx + 2#0_10001_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsux + 2#0_00011_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lharx + 2#0_01011_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhaux + 2#0_01010_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhax + 2#0_11000_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhbrx + 2#0_11001_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzcix + 2#0_01001_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzux + 2#0_01000_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzx + 2#0_00000_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lwarx + 2#0_01011_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwaux + 2#0_01010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwax + 2#0_10000_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwbrx + 2#0_11000_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzcix + 2#0_00001_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzux + 2#0_00000_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzx + 2#0_10010_00000# => (ALU, NONE, OP_MCRXRX, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mcrxrx + 2#0_00000_10011# => (ALU, NONE, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfcr/mfocrf + 2#0_00010_10011# => (ALU, NONE, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- mfmsr + 2#0_01010_10011# => (ALU, NONE, OP_MFSPR, NONE, NONE, RS, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfspr + 2#0_01000_01001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- modud + 2#0_01000_01011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- moduw + 2#0_11000_01001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- modsd + 2#0_11000_01011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0', NONE), -- modsw + 2#0_00100_10000# => (ALU, NONE, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtcrf/mtocrf + 2#0_00100_10010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- mtmsr + 2#0_00101_10010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtmsrd # ignore top bits and d + 2#0_01110_10011# => (ALU, NONE, OP_MTSPR, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtspr + 2#0_00010_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd + 2#0_00000_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu + 2#0_00010_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw + 2#0_00000_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu -- next 4 have reserved bit set - 2#1001001001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd - 2#1000001001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu - 2#1001001011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw - 2#1000001011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu - 2#0011101001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulld - 2#1011101001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulldo - 2#0011101011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullw - 2#1011101011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullwo - 2#0111011100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nand - 2#0001101000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- neg - 2#1001101000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nego + 2#0_10010_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd + 2#0_10000_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu + 2#0_10010_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw + 2#0_10000_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu + 2#0_00111_01001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulld + 2#0_10111_01001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulldo + 2#0_00111_01011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullw + 2#0_10111_01011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullwo + 2#0_01110_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nand + 2#0_00011_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- neg + 2#0_10011_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nego -- next 8 are reserved no-op instructions - 2#1000010010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1000110010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1001010010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1001110010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1010010010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1010110010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1011010010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#1011110010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0001111100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nor - 2#0110111100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- or - 2#0110011100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- orc - 2#0001111010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntb - 2#0111111010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntd - 2#0101111010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntw - 2#0010111010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyd - 2#0010011010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyw - 2#0010000000# => (ALU, NONE, OP_SETB, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- setb - 2#0111110010# => (LDST, NONE, OP_TLBIE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- slbia - 2#0000011011# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- sld - 2#0000011000# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- slw - 2#1100011010# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- srad - 2#1100111010# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi - 2#1100111011# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi - 2#1100011000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- sraw - 2#1100111000# => (ALU, NONE, OP_SHR, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- srawi - 2#1000011011# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- srd - 2#1000011000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- srw - 2#1111010101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbcix - 2#1010110110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stbcx - 2#0011110111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbux - 2#0011010111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbx - 2#1010010100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdbrx - 2#1111110101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdcix - 2#0011010110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stdcx - 2#0010110101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdux - 2#0010010101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdx - 2#1011010111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfdx - 2#1011110111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdux - 2#1111010111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfiwx - 2#1010010111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfsx - 2#1010110111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsux - 2#1110010110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthbrx - 2#1110110101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthcix - 2#1011010110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- sthcx - 2#0110110111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthux - 2#0110010111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthx - 2#1010010110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwbrx - 2#1110010101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwcix - 2#0010010110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stwcx - 2#0010110111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwux - 2#0010010111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwx - 2#0000101000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subf - 2#1000101000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfo - 2#0000001000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfc - 2#1000001000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfco - 2#0010001000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfe - 2#1010001000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfeo - 2#0011101000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfme - 2#1011101000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfmeo - 2#0011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfze - 2#1011001000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfzeo - 2#1001010110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sync - 2#0001000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- td - 2#0000000100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- tw - 2#0100110010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbie - 2#0100010010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbiel - 2#1000110110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbsync - 2#0000011110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- wait - 2#0100111100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- xor - others => illegal_inst - ); - - constant decode_op_58_array : minor_rom_array_2_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 0 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 1 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2 => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - others => decode_rom_init - ); - - constant decode_op_59_array : op_59_subop_array_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfid[u]s - 2#10010# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fdivs - 2#10100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsubs - 2#10101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fadds - 2#10110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsqrts - 2#11000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fres - 2#11001# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmuls - 2#11010# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- frsqrtes - 2#11100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmsubs - 2#11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmadds - 2#11110# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmsubs - 2#11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmadds - others => illegal_inst - ); - - constant decode_op_62_array : minor_rom_array_2_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 0 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 1 => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - others => decode_rom_init - ); + 2#0_10000_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10001_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10010_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10011_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10100_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10101_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10110_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_10111_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop + 2#0_00011_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nor + 2#0_01101_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- or + 2#0_01100_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- orc + 2#0_00011_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntb + 2#0_01111_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntd + 2#0_01011_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntw + 2#0_00101_11010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyd + 2#0_00100_11010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyw + 2#0_00100_00000# => (ALU, NONE, OP_SETB, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- setb + 2#0_01111_10010# => (LDST, NONE, OP_TLBIE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- slbia + 2#0_00000_11011# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- sld + 2#0_00000_11000# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- slw + 2#0_11000_11010# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- srad + 2#0_11001_11010# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi + 2#0_11001_11011# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi + 2#0_11000_11000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- sraw + 2#0_11001_11000# => (ALU, NONE, OP_SHR, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- srawi + 2#0_10000_11011# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- srd + 2#0_10000_11000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- srw + 2#0_11110_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbcix + 2#0_10101_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stbcx + 2#0_00111_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbux + 2#0_00110_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbx + 2#0_10100_10100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdbrx + 2#0_11111_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdcix + 2#0_00110_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stdcx + 2#0_00101_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdux + 2#0_00100_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdx + 2#0_10110_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfdx + 2#0_10111_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdux + 2#0_11110_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfiwx + 2#0_10100_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfsx + 2#0_10101_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsux + 2#0_11100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthbrx + 2#0_11101_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthcix + 2#0_10110_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- sthcx + 2#0_01101_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthux + 2#0_01100_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthx + 2#0_10100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwbrx + 2#0_11100_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwcix + 2#0_00100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stwcx + 2#0_00101_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwux + 2#0_00100_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwx + 2#0_00001_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subf + 2#0_10001_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfo + 2#0_00000_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfc + 2#0_10000_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfco + 2#0_00100_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfe + 2#0_10100_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfeo + 2#0_00111_01000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfme + 2#0_10111_01000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfmeo + 2#0_00110_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfze + 2#0_10110_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfzeo + 2#0_10010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sync + 2#0_00010_00100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- td + 2#0_00000_00100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- tw + 2#0_01001_10010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbie + 2#0_01000_10010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbiel + 2#0_10001_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbsync + 2#0_00000_11110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- wait + 2#0_01001_11100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- xor + + -- Major opcode 19 + -- Columns with insn(4) = '1' are all illegal and not mapped here; to + -- fit into 2048 entries, the columns are remapped so that 16-24 are + -- stored here as 8-15; in other words the address bits are + -- 1, insn(10..6), 1, insn(5), insn(3..1) + 2#1_10000_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bcctr + 2#1_00000_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bclr + 2#1_10001_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bctar + 2#1_01000_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crand + 2#1_00100_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crandc + 2#1_01001_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- creqv + 2#1_00111_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crnand + 2#1_00001_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crnor + 2#1_01110_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cror + 2#1_01101_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crorc + 2#1_00110_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crxor + 2#1_00100_11110# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isync + 2#1_00000_10000# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mcrf + 2#1_00000_11010# => (ALU, NONE, OP_RFID, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- rfid + + -- Major opcode 59 + -- Only column 14 is valid here; columns 16-31 are handled in the major table + -- Column 14 is mapped to column 6 of the space which is + -- mostly used for opcode 19. + 2#1_11010_10110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfids + 2#1_11110_10110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfidus + + -- Major opcode 63 + -- Columns 0-15 are mapped here; columns 16-31 are in the major table. + -- Address bits are 1, insn(10:6), 0, insn(4:1) + 2#1_00000_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 0/0=fcmpu + 2#1_00001_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 1/0=fcmpo + 2#1_00010_00000# => (FPU, FPU, OP_FP_CMP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 2/0=mcrfs + 2#1_00100_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 4/0=ftdiv + 2#1_00101_00000# => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 5/0=ftsqrt + 2#1_00001_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/6=mtfsb1 + 2#1_00010_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/6=mtfsb0 + 2#1_00100_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/6=mtfsfi + 2#1_11010_00110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 26/6=fmrgow + 2#1_11110_00110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 30/6=fmrgew + 2#1_10010_00111# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 18/7=mffs family + 2#1_10110_00111# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 22/7=mtfsf + 2#1_00000_01000# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/8=fcpsgn + 2#1_00001_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/8=fneg + 2#1_00010_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/8=fmr + 2#1_00100_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/8=fnabs + 2#1_01000_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 8/8=fabs + 2#1_01100_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 12/8=frin + 2#1_01101_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 13/8=friz + 2#1_01110_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 14/8=frip + 2#1_01111_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 15/8=frim + 2#1_00000_01100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- 0/12=frsp + 2#1_00000_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/14=fctiw + 2#1_00100_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/14=fctiwu + 2#1_11001_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/14=fctid + 2#1_11010_01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 26/14=fcfid + 2#1_11101_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/14=fctidu + 2#1_11110_01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 30/14=fcfidu + 2#1_00000_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/15=fctiwz + 2#1_00100_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/15=fctiwuz + 2#1_11001_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/15=fctidz + 2#1_11101_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/15=fctiduz - -- indexed by bits 4..1 and 10..6 of instruction word - constant decode_op_63l_array : op_63_subop_array_0_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#000000000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 0/0=fcmpu - 2#000000001# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 1/0=fcmpo - 2#000000010# => (FPU, FPU, OP_FP_CMP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 2/0=mcrfs - 2#000000100# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 4/0=ftdiv - 2#000000101# => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 5/0=ftsqrt - 2#011000001# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/6=mtfsb1 - 2#011000010# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/6=mtfsb0 - 2#011000100# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/6=mtfsfi - 2#011011010# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 26/6=fmrgow - 2#011011110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 30/6=fmrgew - 2#011110010# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 18/7=mffs family - 2#011110110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 22/7=mtfsf - 2#100000000# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/8=fcpsgn - 2#100000001# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/8=fneg - 2#100000010# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/8=fmr - 2#100000100# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/8=fnabs - 2#100001000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 8/8=fabs - 2#100001100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 12/8=frin - 2#100001101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 13/8=friz - 2#100001110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 14/8=frip - 2#100001111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 15/8=frim - 2#110000000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- 0/12=frsp - 2#111000000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/14=fctiw - 2#111000100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/14=fctiwu - 2#111011001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/14=fctid - 2#111011010# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 26/14=fcfid - 2#111011101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/14=fctidu - 2#111011110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 30/14=fcfidu - 2#111100000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/15=fctiwz - 2#111100100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/15=fctiwuz - 2#111111001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/15=fctidz - 2#111111101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/15=fctiduz - others => illegal_inst - ); - - -- indexed by bits 4..1 of instruction word - constant decode_op_63h_array : op_63_subop_array_1_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#0010# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fdiv - 2#0100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsub - 2#0101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fadd - 2#0110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsqrt - 2#0111# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsel - 2#1000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fre - 2#1001# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmul - 2#1010# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- frsqrte - 2#1100# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmsub - 2#1101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmadd - 2#1110# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmsub - 2#1111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmadd others => illegal_inst ); @@ -632,9 +610,9 @@ begin variable v : Decode1ToDecode2Type; variable vr : Decode1ToRegisterFileType; variable vi : reg_internal_t; - variable majorop : major_opcode_t; - variable minor4op : std_ulogic_vector(10 downto 0); - variable op_19_bits: std_ulogic_vector(2 downto 0); + variable majorop : std_ulogic_vector(5 downto 0); + variable majaddr : std_ulogic_vector(10 downto 0); + variable rowaddr : std_ulogic_vector(10 downto 0); variable sprn : spr_num_t; variable br_target : std_ulogic_vector(61 downto 0); variable br_offset : signed(23 downto 0); @@ -663,11 +641,30 @@ begin br_offset := (others => '0'); - majorop := unsigned(f_in.insn(31 downto 26)); - if is_X(majorop) then + majorop := f_in.insn(31 downto 26); + majaddr := majorop & f_in.insn(4 downto 0); + if is_X(majaddr) then v.decode := x_inst; else - v.decode := major_decode_rom_array(to_integer(majorop)); + vi.maj_decode := major_decode_rom(to_integer(unsigned(majaddr))); + end if; + + -- row_decode_rom is used for op 19, 31, 59, 63 + -- addr bit 10 is 0 for op 31, 1 for 19, 59, 63 + rowaddr(10) := f_in.insn(31) or not f_in.insn(29); + rowaddr(9 downto 5) := f_in.insn(10 downto 6); + if f_in.insn(28) = '0' then + -- op 19 and op 59 + rowaddr(4 downto 3) := '1' & f_in.insn(5); + else + -- op 31 and 63; for 63 we only use this when f_in.insn(5) = '0' + rowaddr(4 downto 3) := f_in.insn(5 downto 4); + end if; + rowaddr(2 downto 0) := f_in.insn(3 downto 1); + if is_X(rowaddr) then + vi.row_decode := x_inst; + else + vi.row_decode := row_decode_rom(to_integer(unsigned(rowaddr))); end if; if is_X(f_in.insn) then @@ -682,9 +679,7 @@ begin case unsigned(majorop) is when "000100" => -- 4 -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) - minor4op := f_in.insn(5 downto 0) & f_in.insn(10 downto 6); - vi.override := not decode_op_4_valid(to_integer(unsigned(minor4op))); - v.decode := decode_op_4_array(to_integer(unsigned(f_in.insn(5 downto 0)))); + vi.override := not f_in.insn(5); in3rc := '1'; may_read_rb := '1'; @@ -694,11 +689,7 @@ begin when "011111" => -- 31 -- major opcode 31, lots of things - if is_X(f_in.insn) then - v.decode := x_inst; - else - v.decode := decode_op_31_array(to_integer(unsigned(f_in.insn(10 downto 1)))); - end if; + vi.use_row := '1'; may_read_rb := '1'; if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then @@ -717,17 +708,13 @@ begin br_offset := signed(f_in.insn(25 downto 2)); when "010011" => -- 19 - if is_X(f_in.insn) then - vi.override := 'X'; - else - vi.override := not decode_op_19_valid(to_integer(unsigned(f_in.insn(5 downto 1) & f_in.insn(10 downto 6)))); - end if; - op_19_bits := f_in.insn(5) & f_in.insn(3) & f_in.insn(2); - if is_X(op_19_bits) then - v.decode := x_inst; - else - v.decode := decode_op_19_array(to_integer(unsigned(op_19_bits))); - end if; + -- Columns 8-15 and 24-31 don't have any valid instructions + -- (where insn(5..1) is the column number). + -- addpcis (column 2) is in the major table + -- Use the row table for columns 0-1 and 16-23 (mapped to 8-15) + -- Columns 4-7 in the row table are used for op 59 cols 12-15 + vi.override := f_in.insn(4); + vi.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2)); when "011000" => -- 24 -- ori, special-case the standard NOP @@ -738,11 +725,6 @@ begin end if; when "011110" => -- 30 - if is_X(f_in.insn) then - v.decode := x_inst; - else - v.decode := decode_op_30_array(to_integer(unsigned(f_in.insn(4 downto 1)))); - end if; may_read_rb := f_in.insn(4); when "110100" | "110101" | "110110" | "110111" => -- 52, 53, 54, 55 @@ -751,47 +733,22 @@ begin fprs := '1'; end if; - when "111010" => -- 58 - if is_X(f_in.insn) then - v.decode := x_inst; - else - v.decode := decode_op_58_array(to_integer(unsigned(f_in.insn(1 downto 0)))); - end if; - when "111011" => -- 59 if HAS_FPU then -- floating point operations, mostly single-precision - if is_X(f_in.insn) then - v.decode := x_inst; - else - v.decode := decode_op_59_array(to_integer(unsigned(f_in.insn(5 downto 1)))); - end if; - if f_in.insn(5) = '0' and not std_match(f_in.insn(10 downto 1), "11-1001110") then - vi.override := '1'; - end if; + -- Use row table for columns 12-15, major table for 16-31 + vi.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3)); + vi.use_row := not f_in.insn(5); in3rc := '1'; fprabc := '1'; fprs := '1'; may_read_rb := '1'; end if; - when "111110" => -- 62 - if is_X(f_in.insn) then - v.decode := x_inst; - else - v.decode := decode_op_62_array(to_integer(unsigned(f_in.insn(1 downto 0)))); - end if; - when "111111" => -- 63 if HAS_FPU then -- floating point operations, general and double-precision - if is_X(f_in.insn) then - v.decode := x_inst; - elsif f_in.insn(5) = '0' then - v.decode := decode_op_63l_array(to_integer(unsigned(f_in.insn(4 downto 1) & f_in.insn(10 downto 6)))); - else - v.decode := decode_op_63h_array(to_integer(unsigned(f_in.insn(4 downto 1)))); - end if; + vi.use_row := not f_in.insn(5); in3rc := '1'; fprabc := '1'; fprs := '1'; @@ -853,6 +810,10 @@ begin d_out <= r; if ri.override = '1' then d_out.decode <= ri.override_decode; + elsif ri.use_row = '1' then + d_out.decode <= ri.row_decode; + else + d_out.decode <= ri.maj_decode; end if; f_out.redirect <= br.predict; f_out.redirect_nia <= br_target & "00"; @@ -867,9 +828,9 @@ begin dec1_log : process(clk) begin if rising_edge(clk) then - log_data <= std_ulogic_vector(to_unsigned(insn_type_t'pos(r.decode.insn_type), 6)) & + log_data <= std_ulogic_vector(to_unsigned(insn_type_t'pos(d_out.decode.insn_type), 6)) & r.nia(5 downto 2) & - std_ulogic_vector(to_unsigned(unit_t'pos(r.decode.unit), 2)) & + std_ulogic_vector(to_unsigned(unit_t'pos(d_out.decode.unit), 2)) & r.valid; end if; end process; From c3ee10f013fe35b66ac285d15dfece21cc44ac35 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 26 Jul 2022 18:21:19 +1000 Subject: [PATCH 10/22] decode1: Split instruction decoding into two steps This reduces the block RAM requirements for instruction decoding by splitting it into two steps. The first, in a new pipeline stage called decode0 (implemented by code in decode1.vhdl) maps the instruction to a 9-bit instruction code using major and row decode ROMs. The second maps the 9-bit code to the final decode_rom_t (about 44 bits wide). Branch prediction done in decode is now done in decode0 rather than decode1. Signed-off-by: Paul Mackerras --- common.vhdl | 2 + decode1.vhdl | 1390 ++++++++++++++++++++++++++++----------------- decode_types.vhdl | 285 ++++++++++ 3 files changed, 1145 insertions(+), 532 deletions(-) diff --git a/common.vhdl b/common.vhdl index 51cbc02..a698ba9 100644 --- a/common.vhdl +++ b/common.vhdl @@ -250,6 +250,8 @@ package common is next_predicted: std_ulogic; next_pred_ntaken: std_ulogic; end record; + constant IcacheToDecode1Init : IcacheToDecode1Type := + (nia => (others => '0'), insn => (others => '0'), others => '0'); type IcacheEventType is record icache_miss : std_ulogic; diff --git a/decode1.vhdl b/decode1.vhdl index 54754ab..9dd57d9 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -31,38 +31,28 @@ entity decode1 is end entity decode1; architecture behaviour of decode1 is - signal r, rin : Decode1ToDecode2Type; - signal f, fin : Decode1ToFetch1Type; - - constant illegal_inst : decode_rom_t := - (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); - constant x_inst : decode_rom_t := - (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, 'X', 'X', 'X', 'X', ZERO, 'X', NONE, 'X', 'X', 'X', 'X', 'X', 'X', NONE, 'X', 'X', NONE); - - -- If we have an FPU, then it is used for integer divisions, - -- otherwise a dedicated divider in the ALU is used. - function divider_unit(hf : boolean) return unit_t is - begin - if hf then - return FPU; - else - return ALU; - end if; - end; - constant DVU : unit_t := divider_unit(HAS_FPU); - - type reg_internal_t is record - maj_decode : decode_rom_t; - row_decode : decode_rom_t; + type dc0_t is record + f_in : IcacheToDecode1Type; use_row : std_ulogic; + br_pred : std_ulogic; override : std_ulogic; - override_decode: decode_rom_t; + ov_insn : insn_code; + spr_info : spr_id; + ram_spr : ram_spr_info; + fprs : std_ulogic; + fprabc : std_ulogic; + in3rc : std_ulogic; + maybe_rb : std_ulogic; end record; - constant reg_internal_t_init : reg_internal_t := - (maj_decode => illegal_inst, row_decode => illegal_inst, use_row => '0', - override => '0', override_decode => illegal_inst); + constant dc0_t_init : dc0_t := + (f_in => IcacheToDecode1Init, ov_insn => INSN_illegal, + spr_info => spr_id_init, ram_spr => ram_spr_info_init, + others => '0'); - signal ri, ri_in : reg_internal_t; + signal dc0, dc0in : dc0_t; + + signal r, rin : Decode1ToDecode2Type; + signal f, fin : Decode1ToFetch1Type; type br_predictor_t is record br_nia : std_ulogic_vector(61 downto 0); @@ -72,438 +62,738 @@ architecture behaviour of decode1 is signal br, br_in : br_predictor_t; - type decoder_rom_t is array(0 to 2047) of decode_rom_t; - - -- Indexed by bits 31-26 (major opcode) and 4-0 of instruction word - constant major_decode_rom : decoder_rom_t := ( - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#001100_00000# to 2#001100_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addic - 2#001101_00000# to 2#001101_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- addic. - 2#001110_00000# to 2#001110_11111# => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addi - 2#001111_00000# to 2#001111_11111# => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addis - 2#010011_00100# to 2#010011_00101# => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addpcis - 2#011100_00000# to 2#011100_11111# => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andi. - 2#011101_00000# to 2#011101_11111# => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), -- andis. - 2#000000_00000# to 2#000000_11111# => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- attn - 2#010010_00000# to 2#010010_11111# => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- b - 2#010000_00000# to 2#010000_11111# => (ALU, NONE, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bc - 2#001011_00000# to 2#001011_11111# => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmpi - 2#001010_00000# to 2#001010_11111# => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpli - 2#100010_00000# to 2#100010_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbz - 2#100011_00000# to 2#100011_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzu - 2#110010_00000# to 2#110010_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfd - 2#110011_00000# to 2#110011_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdu - 2#110000_00000# to 2#110000_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfs - 2#110001_00000# to 2#110001_11111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsu - 2#101010_00000# to 2#101010_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lha - 2#101011_00000# to 2#101011_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhau - 2#101000_00000# to 2#101000_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhz - 2#101001_00000# to 2#101001_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzu - 2#100000_00000# to 2#100000_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwz - 2#100001_00000# to 2#100001_11111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzu - 2#000111_00000# to 2#000111_11111# => (ALU, NONE, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- mulli - 2#011000_00000# to 2#011000_11111# => (ALU, NONE, OP_OR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ori - 2#011001_00000# to 2#011001_11111# => (ALU, NONE, OP_OR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- oris - 2#010100_00000# to 2#010100_11111# => (ALU, NONE, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwimi - 2#010101_00000# to 2#010101_11111# => (ALU, NONE, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwinm - 2#010111_00000# to 2#010111_11111# => (ALU, NONE, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- rlwnm - 2#010001_00000# to 2#010001_11111# => (ALU, NONE, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sc - 2#100110_00000# to 2#100110_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stb - 2#100111_00000# to 2#100111_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbu - 2#110110_00000# to 2#110110_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfd - 2#110111_00000# to 2#110111_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdu - 2#110100_00000# to 2#110100_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfs - 2#110101_00000# to 2#110101_11111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsu - 2#101100_00000# to 2#101100_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sth - 2#101101_00000# to 2#101101_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthu - 2#100100_00000# to 2#100100_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stw - 2#100101_00000# to 2#100101_11111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwu - 2#001000_00000# to 2#001000_11111# => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- subfic - 2#000010_00000# to 2#000010_11111# => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tdi - 2#000011_00000# to 2#000011_11111# => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- twi - 2#011010_00000# to 2#011010_11111# => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xori - 2#011011_00000# to 2#011011_11111# => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- xoris + signal maj_rom_addr : std_ulogic_vector(10 downto 0); + signal row_rom_addr : std_ulogic_vector(10 downto 0); + signal major_predecode : insn_code; + signal row_predecode : insn_code; + + signal decode_rom_addr : insn_code; + signal decode : decode_rom_t; + signal rom_ce : std_ulogic; + + type predecoder_rom_t is array(0 to 2047) of insn_code; + + constant major_predecode_rom : predecoder_rom_t := ( + 2#001100_00000# to 2#001100_11111# => INSN_addic, + 2#001101_00000# to 2#001101_11111# => INSN_addic_dot, + 2#001110_00000# to 2#001110_11111# => INSN_addi, + 2#001111_00000# to 2#001111_11111# => INSN_addis, + 2#010011_00100# to 2#010011_00101# => INSN_addpcis, + 2#011100_00000# to 2#011100_11111# => INSN_andi_dot, + 2#011101_00000# to 2#011101_11111# => INSN_andis_dot, + 2#000000_00000# => INSN_attn, + 2#010010_00000# to 2#010010_11111# => INSN_b, + 2#010000_00000# to 2#010000_11111# => INSN_bc, + 2#001011_00000# to 2#001011_11111# => INSN_cmpi, + 2#001010_00000# to 2#001010_11111# => INSN_cmpli, + 2#100010_00000# to 2#100010_11111# => INSN_lbz, + 2#100011_00000# to 2#100011_11111# => INSN_lbzu, + 2#110010_00000# to 2#110010_11111# => INSN_lfd, + 2#110011_00000# to 2#110011_11111# => INSN_lfdu, + 2#110000_00000# to 2#110000_11111# => INSN_lfs, + 2#110001_00000# to 2#110001_11111# => INSN_lfsu, + 2#101010_00000# to 2#101010_11111# => INSN_lha, + 2#101011_00000# to 2#101011_11111# => INSN_lhau, + 2#101000_00000# to 2#101000_11111# => INSN_lhz, + 2#101001_00000# to 2#101001_11111# => INSN_lhzu, + 2#100000_00000# to 2#100000_11111# => INSN_lwz, + 2#100001_00000# to 2#100001_11111# => INSN_lwzu, + 2#000111_00000# to 2#000111_11111# => INSN_mulli, + 2#011000_00000# to 2#011000_11111# => INSN_ori, + 2#011001_00000# to 2#011001_11111# => INSN_oris, + 2#010100_00000# to 2#010100_11111# => INSN_rlwimi, + 2#010101_00000# to 2#010101_11111# => INSN_rlwinm, + 2#010111_00000# to 2#010111_11111# => INSN_rlwnm, + 2#010001_00000# to 2#010001_11111# => INSN_sc, + 2#100110_00000# to 2#100110_11111# => INSN_stb, + 2#100111_00000# to 2#100111_11111# => INSN_stbu, + 2#110110_00000# to 2#110110_11111# => INSN_stfd, + 2#110111_00000# to 2#110111_11111# => INSN_stfdu, + 2#110100_00000# to 2#110100_11111# => INSN_stfs, + 2#110101_00000# to 2#110101_11111# => INSN_stfsu, + 2#101100_00000# to 2#101100_11111# => INSN_sth, + 2#101101_00000# to 2#101101_11111# => INSN_sthu, + 2#100100_00000# to 2#100100_11111# => INSN_stw, + 2#100101_00000# to 2#100101_11111# => INSN_stwu, + 2#001000_00000# to 2#001000_11111# => INSN_subfic, + 2#000010_00000# to 2#000010_11111# => INSN_tdi, + 2#000011_00000# to 2#000011_11111# => INSN_twi, + 2#011010_00000# to 2#011010_11111# => INSN_xori, + 2#011011_00000# to 2#011011_11111# => INSN_xoris, -- major opcode 4 - 2#000100_10000# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddhd - 2#000100_10001# => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- maddhdu - 2#000100_10011# => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- maddld + 2#000100_10000# => INSN_maddhd, + 2#000100_10001# => INSN_maddhdu, + 2#000100_10011# => INSN_maddld, -- major opcode 30 - 2#011110_01000# to 2#011110_01001# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic - 2#011110_01010# to 2#011110_01011# => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldic - 2#011110_00000# to 2#011110_00001# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl - 2#011110_00010# to 2#011110_00011# => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicl - 2#011110_00100# to 2#011110_00101# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr - 2#011110_00110# to 2#011110_00111# => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldicr - 2#011110_01100# to 2#011110_01101# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi - 2#011110_01110# to 2#011110_01111# => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldimi - 2#011110_10000# to 2#011110_10001# => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcl - 2#011110_10010# to 2#011110_10011# => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- rldcr + 2#011110_01000# to 2#011110_01001# => INSN_rldic, + 2#011110_01010# to 2#011110_01011# => INSN_rldic, + 2#011110_00000# to 2#011110_00001# => INSN_rldicl, + 2#011110_00010# to 2#011110_00011# => INSN_rldicl, + 2#011110_00100# to 2#011110_00101# => INSN_rldicr, + 2#011110_00110# to 2#011110_00111# => INSN_rldicr, + 2#011110_01100# to 2#011110_01101# => INSN_rldimi, + 2#011110_01110# to 2#011110_01111# => INSN_rldimi, + 2#011110_10000# to 2#011110_10001# => INSN_rldcl, + 2#011110_10010# to 2#011110_10011# => INSN_rldcr, -- major opcode 58 - 2#111010_00000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_00001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_00010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_00100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_00101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_00110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_01000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_01001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_01010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_01100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_01101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_01110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_10000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_10001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_10010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_11000# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_11001# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_11010# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa - 2#111010_11100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ld - 2#111010_11101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldu - 2#111010_11110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwa + 2#111010_00000# => INSN_ld, + 2#111010_00001# => INSN_ldu, + 2#111010_00010# => INSN_lwa, + 2#111010_00100# => INSN_ld, + 2#111010_00101# => INSN_ldu, + 2#111010_00110# => INSN_lwa, + 2#111010_01000# => INSN_ld, + 2#111010_01001# => INSN_ldu, + 2#111010_01010# => INSN_lwa, + 2#111010_01100# => INSN_ld, + 2#111010_01101# => INSN_ldu, + 2#111010_01110# => INSN_lwa, + 2#111010_10000# => INSN_ld, + 2#111010_10001# => INSN_ldu, + 2#111010_10010# => INSN_lwa, + 2#111010_10100# => INSN_ld, + 2#111010_10101# => INSN_ldu, + 2#111010_10110# => INSN_lwa, + 2#111010_11000# => INSN_ld, + 2#111010_11001# => INSN_ldu, + 2#111010_11010# => INSN_lwa, + 2#111010_11100# => INSN_ld, + 2#111010_11101# => INSN_ldu, + 2#111010_11110# => INSN_lwa, -- major opcode 59 - 2#111011_00100# to 2#111011_00101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fdivs - 2#111011_01000# to 2#111011_01001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsubs - 2#111011_01010# to 2#111011_01011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fadds - 2#111011_01100# to 2#111011_01101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fsqrts - 2#111011_10000# to 2#111011_10001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fres - 2#111011_10010# to 2#111011_10011# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmuls - 2#111011_10100# to 2#111011_10101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- frsqrtes - 2#111011_11000# to 2#111011_11001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmsubs - 2#111011_11010# to 2#111011_11011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fmadds - 2#111011_11100# to 2#111011_11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmsubs - 2#111011_11110# to 2#111011_11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fnmadds + 2#111011_00100# to 2#111011_00101# => INSN_fdivs, + 2#111011_01000# to 2#111011_01001# => INSN_fsubs, + 2#111011_01010# to 2#111011_01011# => INSN_fadds, + 2#111011_01100# to 2#111011_01101# => INSN_fsqrts, + 2#111011_10000# to 2#111011_10001# => INSN_fres, + 2#111011_10010# to 2#111011_10011# => INSN_fmuls, + 2#111011_10100# to 2#111011_10101# => INSN_frsqrtes, + 2#111011_11000# to 2#111011_11001# => INSN_fmsubs, + 2#111011_11010# to 2#111011_11011# => INSN_fmadds, + 2#111011_11100# to 2#111011_11101# => INSN_fnmsubs, + 2#111011_11110# to 2#111011_11111# => INSN_fnmadds, -- major opcode 62 - 2#111110_00000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_00001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_00100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_00101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_01000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_01001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_01100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_01101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_10000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_10001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_10100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_11000# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_11001# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu - 2#111110_11100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- std - 2#111110_11101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdu + 2#111110_00000# => INSN_std, + 2#111110_00001# => INSN_stdu, + 2#111110_00100# => INSN_std, + 2#111110_00101# => INSN_stdu, + 2#111110_01000# => INSN_std, + 2#111110_01001# => INSN_stdu, + 2#111110_01100# => INSN_std, + 2#111110_01101# => INSN_stdu, + 2#111110_10000# => INSN_std, + 2#111110_10001# => INSN_stdu, + 2#111110_10100# => INSN_std, + 2#111110_10101# => INSN_stdu, + 2#111110_11000# => INSN_std, + 2#111110_11001# => INSN_stdu, + 2#111110_11100# => INSN_std, + 2#111110_11101# => INSN_stdu, -- major opcode 63 - 2#111111_00100# to 2#111111_00101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fdiv - 2#111111_01000# to 2#111111_01001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsub - 2#111111_01010# to 2#111111_01011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fadd - 2#111111_01100# to 2#111111_01101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsqrt - 2#111111_01110# to 2#111111_01111# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fsel - 2#111111_10000# to 2#111111_10001# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fre - 2#111111_10010# to 2#111111_10011# => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmul - 2#111111_10100# to 2#111111_10101# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- frsqrte - 2#111111_11000# to 2#111111_11001# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmsub - 2#111111_11010# to 2#111111_11011# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fmadd - 2#111111_11100# to 2#111111_11101# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmsub - 2#111111_11110# to 2#111111_11111# => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- fnmadd - others => illegal_inst + 2#111111_00100# to 2#111111_00101# => INSN_fdiv, + 2#111111_01000# to 2#111111_01001# => INSN_fsub, + 2#111111_01010# to 2#111111_01011# => INSN_fadd, + 2#111111_01100# to 2#111111_01101# => INSN_fsqrt, + 2#111111_01110# to 2#111111_01111# => INSN_fsel, + 2#111111_10000# to 2#111111_10001# => INSN_fre, + 2#111111_10010# to 2#111111_10011# => INSN_fmul, + 2#111111_10100# to 2#111111_10101# => INSN_frsqrte, + 2#111111_11000# to 2#111111_11001# => INSN_fmsub, + 2#111111_11010# to 2#111111_11011# => INSN_fmadd, + 2#111111_11100# to 2#111111_11101# => INSN_fnmsub, + 2#111111_11110# to 2#111111_11111# => INSN_fnmadd, + others => INSN_illegal ); - constant row_decode_rom : decoder_rom_t := ( + constant row_predecode_rom : predecoder_rom_t := ( -- Major opcode 31 -- Address bits are 0, insn(10:1) - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - 2#0_01000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- add - 2#0_11000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addo - 2#0_00000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addc - 2#0_10000_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addco - 2#0_00100_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- adde - 2#0_10100_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addeo - 2#0_00101_01010# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addex - 2#0_00010_01010# => (ALU, NONE, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- addg6s - 2#0_00111_01010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addme - 2#0_10111_01010# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addmeo - 2#0_00110_01010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addze - 2#0_10110_01010# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- addzeo - 2#0_00000_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- and - 2#0_00001_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- andc - 2#0_00111_11100# => (ALU, NONE, OP_BPERM, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- bperm - 2#0_01001_11010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cbcdtd - 2#0_01000_11010# => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cdtbcd - 2#0_00000_00000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- cmp - 2#0_01111_11100# => (ALU, NONE, OP_CMPB, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpb - 2#0_00111_00000# => (ALU, NONE, OP_CMPEQB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpeqb - 2#0_00001_00000# => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmpl - 2#0_00110_00000# => (ALU, NONE, OP_CMPRB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cmprb - 2#0_00001_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cntlzd - 2#0_00000_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cntlzw - 2#0_10001_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- cnttzd - 2#0_10000_11010# => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- cnttzw - 2#0_10111_10011# => (ALU, NONE, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- darn - 2#0_00010_10110# => (ALU, NONE, OP_DCBF, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbf - 2#0_00001_10110# => (ALU, NONE, OP_DCBST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbst - 2#0_01000_10110# => (ALU, NONE, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbt - 2#0_00111_10110# => (ALU, NONE, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbtst - 2#0_11111_10110# => (LDST, NONE, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dcbz - 2#0_01100_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeu - 2#0_11100_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdeuo - 2#0_01100_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweu - 2#0_11100_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divweuo - 2#0_01101_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divde - 2#0_11101_01001# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdeo - 2#0_01101_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwe - 2#0_11101_01011# => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divweo - 2#0_01110_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divdu - 2#0_11110_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- divduo - 2#0_01110_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwu - 2#0_11110_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- divwuo - 2#0_01111_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divd - 2#0_11111_01001# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- divdo - 2#0_01111_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divw - 2#0_11111_01011# => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- divwo - 2#0_11001_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dss - 2#0_01010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dst - 2#0_01011_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- dstst - 2#0_11010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- eieio - 2#0_01000_11100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- eqv - 2#0_11101_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsb - 2#0_11100_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsh - 2#0_11110_11010# => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extsw - 2#0_11011_11010# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli - 2#0_11011_11011# => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- extswsli - 2#0_11110_10110# => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbi - 2#0_00000_10110# => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- icbt - 2#0_00000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_01111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_10111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11000_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11001_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11010_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11011_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11100_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11101_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11110_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_11111_01111# => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isel - 2#0_00001_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lbarx - 2#0_11010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzcix - 2#0_00011_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lbzux - 2#0_00010_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lbzx - 2#0_00010_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- ldarx - 2#0_10000_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldbrx - 2#0_11011_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldcix - 2#0_00001_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- ldux - 2#0_00000_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- ldx - 2#0_10010_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfdx - 2#0_10011_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lfdux - 2#0_11010_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwax - 2#0_11011_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lfiwzx - 2#0_10000_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- lfsx - 2#0_10001_10111# => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), -- lfsux - 2#0_00011_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lharx - 2#0_01011_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhaux - 2#0_01010_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhax - 2#0_11000_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhbrx - 2#0_11001_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzcix - 2#0_01001_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lhzux - 2#0_01000_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lhzx - 2#0_00000_10100# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), -- lwarx - 2#0_01011_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwaux - 2#0_01010_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwax - 2#0_10000_10110# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwbrx - 2#0_11000_10101# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzcix - 2#0_00001_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), -- lwzux - 2#0_00000_10111# => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- lwzx - 2#0_10010_00000# => (ALU, NONE, OP_MCRXRX, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mcrxrx - 2#0_00000_10011# => (ALU, NONE, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfcr/mfocrf - 2#0_00010_10011# => (ALU, NONE, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), -- mfmsr - 2#0_01010_10011# => (ALU, NONE, OP_MFSPR, NONE, NONE, RS, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mfspr - 2#0_01000_01001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- modud - 2#0_01000_01011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- moduw - 2#0_11000_01001# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), -- modsd - 2#0_11000_01011# => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0', NONE), -- modsw - 2#0_00100_10000# => (ALU, NONE, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtcrf/mtocrf - 2#0_00100_10010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- mtmsr - 2#0_00101_10010# => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtmsrd # ignore top bits and d - 2#0_01110_10011# => (ALU, NONE, OP_MTSPR, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mtspr - 2#0_00010_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd - 2#0_00000_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu - 2#0_00010_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw - 2#0_00000_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu + 2#0_01000_01010# => INSN_add, + 2#0_11000_01010# => INSN_add, -- addo + 2#0_00000_01010# => INSN_addc, + 2#0_10000_01010# => INSN_addc, -- addco + 2#0_00100_01010# => INSN_adde, + 2#0_10100_01010# => INSN_adde, -- addeo + 2#0_00101_01010# => INSN_addex, + 2#0_00010_01010# => INSN_addg6s, + 2#0_00111_01010# => INSN_addme, + 2#0_10111_01010# => INSN_addme, -- addmeo + 2#0_00110_01010# => INSN_addze, + 2#0_10110_01010# => INSN_addze, -- addzeo + 2#0_00000_11100# => INSN_and, + 2#0_00001_11100# => INSN_andc, + 2#0_00111_11100# => INSN_bperm, + 2#0_01001_11010# => INSN_cbcdtd, + 2#0_01000_11010# => INSN_cdtbcd, + 2#0_00000_00000# => INSN_cmp, + 2#0_01111_11100# => INSN_cmpb, + 2#0_00111_00000# => INSN_cmpeqb, + 2#0_00001_00000# => INSN_cmpl, + 2#0_00110_00000# => INSN_cmprb, + 2#0_00001_11010# => INSN_cntlzd, + 2#0_00000_11010# => INSN_cntlzw, + 2#0_10001_11010# => INSN_cnttzd, + 2#0_10000_11010# => INSN_cnttzw, + 2#0_10111_10011# => INSN_darn, + 2#0_00010_10110# => INSN_dcbf, + 2#0_00001_10110# => INSN_dcbst, + 2#0_01000_10110# => INSN_dcbt, + 2#0_00111_10110# => INSN_dcbtst, + 2#0_11111_10110# => INSN_dcbz, + 2#0_01100_01001# => INSN_divdeu, + 2#0_11100_01001# => INSN_divdeu, -- divdeuo + 2#0_01100_01011# => INSN_divweu, + 2#0_11100_01011# => INSN_divweu, -- divweuo + 2#0_01101_01001# => INSN_divde, + 2#0_11101_01001# => INSN_divde, -- divdeo + 2#0_01101_01011# => INSN_divwe, + 2#0_11101_01011# => INSN_divwe, -- divweo + 2#0_01110_01001# => INSN_divdu, + 2#0_11110_01001# => INSN_divdu, -- divduo + 2#0_01110_01011# => INSN_divwu, + 2#0_11110_01011# => INSN_divwu, -- divwuo + 2#0_01111_01001# => INSN_divd, + 2#0_11111_01001# => INSN_divd, -- divdo + 2#0_01111_01011# => INSN_divw, + 2#0_11111_01011# => INSN_divw, -- divwo + 2#0_11001_10110# => INSN_nop, -- dss + 2#0_01010_10110# => INSN_nop, -- dst + 2#0_01011_10110# => INSN_nop, -- dstst + 2#0_11010_10110# => INSN_eieio, + 2#0_01000_11100# => INSN_eqv, + 2#0_11101_11010# => INSN_extsb, + 2#0_11100_11010# => INSN_extsh, + 2#0_11110_11010# => INSN_extsw, + 2#0_11011_11010# => INSN_extswsli, + 2#0_11011_11011# => INSN_extswsli, + 2#0_11110_10110# => INSN_icbi, + 2#0_00000_10110# => INSN_icbt, + 2#0_00000_01111# => INSN_isel, + 2#0_00001_01111# => INSN_isel, + 2#0_00010_01111# => INSN_isel, + 2#0_00011_01111# => INSN_isel, + 2#0_00100_01111# => INSN_isel, + 2#0_00101_01111# => INSN_isel, + 2#0_00110_01111# => INSN_isel, + 2#0_00111_01111# => INSN_isel, + 2#0_01000_01111# => INSN_isel, + 2#0_01001_01111# => INSN_isel, + 2#0_01010_01111# => INSN_isel, + 2#0_01011_01111# => INSN_isel, + 2#0_01100_01111# => INSN_isel, + 2#0_01101_01111# => INSN_isel, + 2#0_01110_01111# => INSN_isel, + 2#0_01111_01111# => INSN_isel, + 2#0_10000_01111# => INSN_isel, + 2#0_10001_01111# => INSN_isel, + 2#0_10010_01111# => INSN_isel, + 2#0_10011_01111# => INSN_isel, + 2#0_10100_01111# => INSN_isel, + 2#0_10101_01111# => INSN_isel, + 2#0_10110_01111# => INSN_isel, + 2#0_10111_01111# => INSN_isel, + 2#0_11000_01111# => INSN_isel, + 2#0_11001_01111# => INSN_isel, + 2#0_11010_01111# => INSN_isel, + 2#0_11011_01111# => INSN_isel, + 2#0_11100_01111# => INSN_isel, + 2#0_11101_01111# => INSN_isel, + 2#0_11110_01111# => INSN_isel, + 2#0_11111_01111# => INSN_isel, + 2#0_00001_10100# => INSN_lbarx, + 2#0_11010_10101# => INSN_lbzcix, + 2#0_00011_10111# => INSN_lbzux, + 2#0_00010_10111# => INSN_lbzx, + 2#0_00010_10100# => INSN_ldarx, + 2#0_10000_10100# => INSN_ldbrx, + 2#0_11011_10101# => INSN_ldcix, + 2#0_00001_10101# => INSN_ldux, + 2#0_00000_10101# => INSN_ldx, + 2#0_10010_10111# => INSN_lfdx, + 2#0_10011_10111# => INSN_lfdux, + 2#0_11010_10111# => INSN_lfiwax, + 2#0_11011_10111# => INSN_lfiwzx, + 2#0_10000_10111# => INSN_lfsx, + 2#0_10001_10111# => INSN_lfsux, + 2#0_00011_10100# => INSN_lharx, + 2#0_01011_10111# => INSN_lhaux, + 2#0_01010_10111# => INSN_lhax, + 2#0_11000_10110# => INSN_lhbrx, + 2#0_11001_10101# => INSN_lhzcix, + 2#0_01001_10111# => INSN_lhzux, + 2#0_01000_10111# => INSN_lhzx, + 2#0_00000_10100# => INSN_lwarx, + 2#0_01011_10101# => INSN_lwaux, + 2#0_01010_10101# => INSN_lwax, + 2#0_10000_10110# => INSN_lwbrx, + 2#0_11000_10101# => INSN_lwzcix, + 2#0_00001_10111# => INSN_lwzux, + 2#0_00000_10111# => INSN_lwzx, + 2#0_10010_00000# => INSN_mcrxrx, + 2#0_00000_10011# => INSN_mfcr, + 2#0_00010_10011# => INSN_mfmsr, + 2#0_01010_10011# => INSN_mfspr, + 2#0_01000_01001# => INSN_modud, + 2#0_01000_01011# => INSN_moduw, + 2#0_11000_01001# => INSN_modsd, + 2#0_11000_01011# => INSN_modsw, + 2#0_00100_10000# => INSN_mtcrf, + 2#0_00100_10010# => INSN_mtmsr, + 2#0_00101_10010# => INSN_mtmsrd, + 2#0_01110_10011# => INSN_mtspr, + 2#0_00010_01001# => INSN_mulhd, + 2#0_00000_01001# => INSN_mulhdu, + 2#0_00010_01011# => INSN_mulhw, + 2#0_00000_01011# => INSN_mulhwu, -- next 4 have reserved bit set - 2#0_10010_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulhd - 2#0_10000_01001# => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- mulhdu - 2#0_10010_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mulhw - 2#0_10000_01011# => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- mulhwu - 2#0_00111_01001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulld - 2#0_10111_01001# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- mulldo - 2#0_00111_01011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullw - 2#0_10111_01011# => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- mullwo - 2#0_01110_11100# => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nand - 2#0_00011_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- neg - 2#0_10011_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nego + 2#0_10010_01001# => INSN_mulhd, + 2#0_10000_01001# => INSN_mulhdu, + 2#0_10010_01011# => INSN_mulhw, + 2#0_10000_01011# => INSN_mulhwu, + 2#0_00111_01001# => INSN_mulld, + 2#0_10111_01001# => INSN_mulld, -- mulldo + 2#0_00111_01011# => INSN_mullw, + 2#0_10111_01011# => INSN_mullw, -- mullwo + 2#0_01110_11100# => INSN_nand, + 2#0_00011_01000# => INSN_neg, + 2#0_10011_01000# => INSN_neg, -- nego -- next 8 are reserved no-op instructions - 2#0_10000_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10001_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10010_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10011_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10100_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10101_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10110_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_10111_10010# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- nop - 2#0_00011_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- nor - 2#0_01101_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- or - 2#0_01100_11100# => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- orc - 2#0_00011_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntb - 2#0_01111_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntd - 2#0_01011_11010# => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- popcntw - 2#0_00101_11010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyd - 2#0_00100_11010# => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- prtyw - 2#0_00100_00000# => (ALU, NONE, OP_SETB, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- setb - 2#0_01111_10010# => (LDST, NONE, OP_TLBIE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- slbia - 2#0_00000_11011# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- sld - 2#0_00000_11000# => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- slw - 2#0_11000_11010# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- srad - 2#0_11001_11010# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi - 2#0_11001_11011# => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), -- sradi - 2#0_11000_11000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- sraw - 2#0_11001_11000# => (ALU, NONE, OP_SHR, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), -- srawi - 2#0_10000_11011# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- srd - 2#0_10000_11000# => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- srw - 2#0_11110_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbcix - 2#0_10101_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stbcx - 2#0_00111_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stbux - 2#0_00110_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stbx - 2#0_10100_10100# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdbrx - 2#0_11111_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdcix - 2#0_00110_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stdcx - 2#0_00101_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stdux - 2#0_00100_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stdx - 2#0_10110_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfdx - 2#0_10111_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stfdux - 2#0_11110_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stfiwx - 2#0_10100_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- stfsx - 2#0_10101_10111# => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), -- stfsux - 2#0_11100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthbrx - 2#0_11101_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthcix - 2#0_10110_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- sthcx - 2#0_01101_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- sthux - 2#0_01100_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sthx - 2#0_10100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwbrx - 2#0_11100_10101# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwcix - 2#0_00100_10110# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), -- stwcx - 2#0_00101_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), -- stwux - 2#0_00100_10111# => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- stwx - 2#0_00001_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subf - 2#0_10001_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfo - 2#0_00000_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfc - 2#0_10000_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfco - 2#0_00100_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfe - 2#0_10100_01000# => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfeo - 2#0_00111_01000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfme - 2#0_10111_01000# => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfmeo - 2#0_00110_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfze - 2#0_10110_01000# => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- subfzeo - 2#0_10010_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- sync - 2#0_00010_00100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- td - 2#0_00000_00100# => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), -- tw - 2#0_01001_10010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbie - 2#0_01000_10010# => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbiel - 2#0_10001_10110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- tlbsync - 2#0_00000_11110# => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- wait - 2#0_01001_11100# => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- xor + 2#0_10000_10010# => INSN_nop, + 2#0_10001_10010# => INSN_nop, + 2#0_10010_10010# => INSN_nop, + 2#0_10011_10010# => INSN_nop, + 2#0_10100_10010# => INSN_nop, + 2#0_10101_10010# => INSN_nop, + 2#0_10110_10010# => INSN_nop, + 2#0_10111_10010# => INSN_nop, + 2#0_00011_11100# => INSN_nor, + 2#0_01101_11100# => INSN_or, + 2#0_01100_11100# => INSN_orc, + 2#0_00011_11010# => INSN_popcntb, + 2#0_01111_11010# => INSN_popcntd, + 2#0_01011_11010# => INSN_popcntw, + 2#0_00101_11010# => INSN_prtyd, + 2#0_00100_11010# => INSN_prtyw, + 2#0_00100_00000# => INSN_setb, + 2#0_01111_10010# => INSN_slbia, + 2#0_00000_11011# => INSN_sld, + 2#0_00000_11000# => INSN_slw, + 2#0_11000_11010# => INSN_srad, + 2#0_11001_11010# => INSN_sradi, + 2#0_11001_11011# => INSN_sradi, + 2#0_11000_11000# => INSN_sraw, + 2#0_11001_11000# => INSN_srawi, + 2#0_10000_11011# => INSN_srd, + 2#0_10000_11000# => INSN_srw, + 2#0_11110_10101# => INSN_stbcix, + 2#0_10101_10110# => INSN_stbcx, + 2#0_00111_10111# => INSN_stbux, + 2#0_00110_10111# => INSN_stbx, + 2#0_10100_10100# => INSN_stdbrx, + 2#0_11111_10101# => INSN_stdcix, + 2#0_00110_10110# => INSN_stdcx, + 2#0_00101_10101# => INSN_stdux, + 2#0_00100_10101# => INSN_stdx, + 2#0_10110_10111# => INSN_stfdx, + 2#0_10111_10111# => INSN_stfdux, + 2#0_11110_10111# => INSN_stfiwx, + 2#0_10100_10111# => INSN_stfsx, + 2#0_10101_10111# => INSN_stfsux, + 2#0_11100_10110# => INSN_sthbrx, + 2#0_11101_10101# => INSN_sthcix, + 2#0_10110_10110# => INSN_sthcx, + 2#0_01101_10111# => INSN_sthux, + 2#0_01100_10111# => INSN_sthx, + 2#0_10100_10110# => INSN_stwbrx, + 2#0_11100_10101# => INSN_stwcix, + 2#0_00100_10110# => INSN_stwcx, + 2#0_00101_10111# => INSN_stwux, + 2#0_00100_10111# => INSN_stwx, + 2#0_00001_01000# => INSN_subf, + 2#0_10001_01000# => INSN_subf, -- subfo + 2#0_00000_01000# => INSN_subfc, + 2#0_10000_01000# => INSN_subfc, -- subfco + 2#0_00100_01000# => INSN_subfe, + 2#0_10100_01000# => INSN_subfe, -- subfeo + 2#0_00111_01000# => INSN_subfme, + 2#0_10111_01000# => INSN_subfme, -- subfmeo + 2#0_00110_01000# => INSN_subfze, + 2#0_10110_01000# => INSN_subfze, -- subfzeo + 2#0_10010_10110# => INSN_sync, + 2#0_00010_00100# => INSN_td, + 2#0_00000_00100# => INSN_tw, + 2#0_01001_10010# => INSN_tlbie, + 2#0_01000_10010# => INSN_tlbiel, + 2#0_10001_10110# => INSN_tlbsync, + 2#0_00000_11110# => INSN_wait, + 2#0_01001_11100# => INSN_xor, -- Major opcode 19 -- Columns with insn(4) = '1' are all illegal and not mapped here; to -- fit into 2048 entries, the columns are remapped so that 16-24 are -- stored here as 8-15; in other words the address bits are -- 1, insn(10..6), 1, insn(5), insn(3..1) - 2#1_10000_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bcctr - 2#1_00000_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bclr - 2#1_10001_11000# => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), -- bctar - 2#1_01000_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crand - 2#1_00100_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crandc - 2#1_01001_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- creqv - 2#1_00111_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crnand - 2#1_00001_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crnor - 2#1_01110_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- cror - 2#1_01101_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crorc - 2#1_00110_10001# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- crxor - 2#1_00100_11110# => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- isync - 2#1_00000_10000# => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- mcrf - 2#1_00000_11010# => (ALU, NONE, OP_RFID, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- rfid + 2#1_10000_11000# => INSN_bcctr, + 2#1_00000_11000# => INSN_bclr, + 2#1_10001_11000# => INSN_bctar, + 2#1_01000_10001# => INSN_crand, + 2#1_00100_10001# => INSN_crandc, + 2#1_01001_10001# => INSN_creqv, + 2#1_00111_10001# => INSN_crnand, + 2#1_00001_10001# => INSN_crnor, + 2#1_01110_10001# => INSN_cror, + 2#1_01101_10001# => INSN_crorc, + 2#1_00110_10001# => INSN_crxor, + 2#1_00100_11110# => INSN_isync, + 2#1_00000_10000# => INSN_mcrf, + 2#1_00000_11010# => INSN_rfid, -- Major opcode 59 -- Only column 14 is valid here; columns 16-31 are handled in the major table -- Column 14 is mapped to column 6 of the space which is -- mostly used for opcode 19. - 2#1_11010_10110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfids - 2#1_11110_10110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- fcfidus + 2#1_11010_10110# => INSN_fcfids, + 2#1_11110_10110# => INSN_fcfidus, -- Major opcode 63 -- Columns 0-15 are mapped here; columns 16-31 are in the major table. -- Address bits are 1, insn(10:6), 0, insn(4:1) - 2#1_00000_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 0/0=fcmpu - 2#1_00001_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 1/0=fcmpo - 2#1_00010_00000# => (FPU, FPU, OP_FP_CMP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 2/0=mcrfs - 2#1_00100_00000# => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 4/0=ftdiv - 2#1_00101_00000# => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 5/0=ftsqrt - 2#1_00001_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/6=mtfsb1 - 2#1_00010_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/6=mtfsb0 - 2#1_00100_00110# => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/6=mtfsfi - 2#1_11010_00110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 26/6=fmrgow - 2#1_11110_00110# => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), -- 30/6=fmrgew - 2#1_10010_00111# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 18/7=mffs family - 2#1_10110_00111# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 22/7=mtfsf - 2#1_00000_01000# => (FPU, FPU, OP_FP_MOVE, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/8=fcpsgn - 2#1_00001_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 1/8=fneg - 2#1_00010_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 2/8=fmr - 2#1_00100_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/8=fnabs - 2#1_01000_01000# => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 8/8=fabs - 2#1_01100_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 12/8=frin - 2#1_01101_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 13/8=friz - 2#1_01110_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 14/8=frip - 2#1_01111_01000# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 15/8=frim - 2#1_00000_01100# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), -- 0/12=frsp - 2#1_00000_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/14=fctiw - 2#1_00100_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/14=fctiwu - 2#1_11001_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/14=fctid - 2#1_11010_01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 26/14=fcfid - 2#1_11101_01110# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/14=fctidu - 2#1_11110_01110# => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 30/14=fcfidu - 2#1_00000_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 0/15=fctiwz - 2#1_00100_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 4/15=fctiwuz - 2#1_11001_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 25/15=fctidz - 2#1_11101_01111# => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), -- 29/15=fctiduz - - others => illegal_inst + 2#1_00000_00000# => INSN_fcmpu, + 2#1_00001_00000# => INSN_fcmpo, + 2#1_00010_00000# => INSN_mcrfs, + 2#1_00100_00000# => INSN_ftdiv, + 2#1_00101_00000# => INSN_ftsqrt, + 2#1_00001_00110# => INSN_mtfsb, + 2#1_00010_00110# => INSN_mtfsb, + 2#1_00100_00110# => INSN_mtfsfi, + 2#1_11010_00110# => INSN_fmrgow, + 2#1_11110_00110# => INSN_fmrgew, + 2#1_10010_00111# => INSN_mffs, + 2#1_10110_00111# => INSN_mtfsf, + 2#1_00000_01000# => INSN_fcpsgn, + 2#1_00001_01000# => INSN_fneg, + 2#1_00010_01000# => INSN_fmr, + 2#1_00100_01000# => INSN_fnabs, + 2#1_01000_01000# => INSN_fabs, + 2#1_01100_01000# => INSN_frin, + 2#1_01101_01000# => INSN_friz, + 2#1_01110_01000# => INSN_frip, + 2#1_01111_01000# => INSN_frim, + 2#1_00000_01100# => INSN_frsp, + 2#1_00000_01110# => INSN_fctiw, + 2#1_00100_01110# => INSN_fctiwu, + 2#1_11001_01110# => INSN_fctid, + 2#1_11010_01110# => INSN_fcfid, + 2#1_11101_01110# => INSN_fctidu, + 2#1_11110_01110# => INSN_fcfidu, + 2#1_00000_01111# => INSN_fctiwz, + 2#1_00100_01111# => INSN_fctiwuz, + 2#1_11001_01111# => INSN_fctidz, + 2#1_11101_01111# => INSN_fctiduz, + + others => INSN_illegal ); - -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt - -- op in out A out in out len ext pipe - constant nop_instr : decode_rom_t := (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); - constant fetch_fail_inst: decode_rom_t := (LDST, NONE, OP_FETCH_FAILED, CIA, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE); + -- If we have an FPU, then it is used for integer divisions, + -- otherwise a dedicated divider in the ALU is used. + function divider_unit(hf : boolean) return unit_t is + begin + if hf then + return FPU; + else + return ALU; + end if; + end; + constant DVU : unit_t := divider_unit(HAS_FPU); + + type decoder_rom_t is array(insn_code) of decode_rom_t; + + constant decode_rom : decoder_rom_t := ( + -- unit fac internal in1 in2 in3 out CR CR inv inv cry cry ldst BR sgn upd rsrv 32b sgn rc lk sgl rpt + -- op in out A out in out len ext pipe + INSN_illegal => (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_fetch_fail => (LDST, NONE, OP_FETCH_FAILED, CIA, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + + INSN_add => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_adde => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addex => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addg6s => (ALU, NONE, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_addi => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_addic => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_addic_dot => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), + INSN_addis => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_addme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addpcis => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_addze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_and => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_andc => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_andi_dot => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), + INSN_andis_dot => (ALU, NONE, OP_AND, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), + INSN_attn => (ALU, NONE, OP_ATTN, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), + INSN_b => (ALU, NONE, OP_B, NONE, CONST_LI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), + INSN_bc => (ALU, NONE, OP_BC, NONE, CONST_BD, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), + INSN_bcctr => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), + INSN_bclr => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), + INSN_bctar => (ALU, NONE, OP_BCREG, NONE, NONE, NONE, NONE, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0', NONE), + INSN_bperm => (ALU, NONE, OP_BPERM, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cbcdtd => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cdtbcd => (ALU, NONE, OP_BCD, NONE, NONE, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cmp => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_cmpb => (ALU, NONE, OP_CMPB, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cmpeqb => (ALU, NONE, OP_CMPEQB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cmpi => (ALU, NONE, OP_CMP, RA, CONST_SI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_cmpl => (ALU, NONE, OP_CMP, RA, RB, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cmpli => (ALU, NONE, OP_CMP, RA, CONST_UI, NONE, NONE, '0', '1', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cmprb => (ALU, NONE, OP_CMPRB, RA, RB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cntlzd => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_cntlzw => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_cnttzd => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_cnttzw => (ALU, NONE, OP_CNTZ, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_crand => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_crandc => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_creqv => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_crnand => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_crnor => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_cror => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_crorc => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_crxor => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_darn => (ALU, NONE, OP_DARN, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_dcbf => (ALU, NONE, OP_DCBF, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_dcbst => (ALU, NONE, OP_DCBST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_dcbt => (ALU, NONE, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_dcbtst => (ALU, NONE, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_dcbz => (LDST, NONE, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_divd => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_divde => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_divdeu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_divdu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_divw => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_divwe => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_divweu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_divwu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_eieio => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_eqv => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_extsb => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_extsh => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_extsw => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_extswsli => (ALU, NONE, OP_EXTSWSLI, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fabs => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fadd => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fadds => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fcfid => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fcfids => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fcfidu => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fcfidus => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fcmpo => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_fcmpu => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_fcpsgn => (FPU, FPU, OP_FP_MOVE, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctid => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctidu => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctiduz => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctidz => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctiw => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctiwu => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctiwuz => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fctiwz => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fdiv => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fdivs => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fmadd => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fmadds => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fmr => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fmrgew => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_fmrgow => (FPU, FPU, OP_FP_MISC, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_fmsub => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fmsubs => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fmul => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fmuls => (FPU, FPU, OP_FP_ARITH, FRA, NONE, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fnabs => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fneg => (FPU, FPU, OP_FP_MOVE, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fnmadd => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fnmadds => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fnmsub => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fnmsubs => (FPU, FPU, OP_FP_ARITH, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fre => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fres => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_frim => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_frin => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_frip => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_friz => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_frsp => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_frsqrte => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_frsqrtes => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fsel => (FPU, FPU, OP_FP_MOVE, FRA, FRB, FRC, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fsqrt => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fsqrts => (FPU, FPU, OP_FP_ARITH, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_fsub => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_fsubs => (FPU, FPU, OP_FP_ARITH, FRA, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_ftdiv => (FPU, FPU, OP_FP_CMP, FRA, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ftsqrt => (FPU, FPU, OP_FP_CMP, NONE, FRB, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_icbi => (ALU, NONE, OP_ICBI, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), + INSN_icbt => (ALU, NONE, OP_ICBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), + INSN_isel => (ALU, NONE, OP_ISEL, RA_OR_ZERO, RB, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_isync => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lbarx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), + INSN_lbz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lbzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lbzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lbzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lbzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ld => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ldarx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), + INSN_ldbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ldcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ldu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_ldux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_ldx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lfd => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lfdu => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lfdux => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lfdx => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lfiwax => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lfiwzx => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lfs => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_lfsu => (LDST, FPU, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), + INSN_lfsux => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', DUPD), + INSN_lfsx => (LDST, FPU, OP_LOAD, RA_OR_ZERO, RB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_lha => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lharx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), + INSN_lhau => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lhaux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lhax => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lhbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lhz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lhzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lhzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lhzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lhzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwa => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwarx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), + INSN_lwaux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lwax => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lwzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), + INSN_lwzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_maddhd => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_maddhdu => (ALU, NONE, OP_MUL_H64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_maddld => (ALU, NONE, OP_MUL_L64, RA, RB, RCR, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_mcrf => (ALU, NONE, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mcrfs => (FPU, FPU, OP_FP_CMP, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mcrxrx => (ALU, NONE, OP_MCRXRX, NONE, NONE, NONE, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mfcr => (ALU, NONE, OP_MFCR, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mffs => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, FRT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_mfmsr => (ALU, NONE, OP_MFMSR, NONE, NONE, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1', NONE), + INSN_mfspr => (ALU, NONE, OP_MFSPR, NONE, NONE, RS, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_modsd => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_modsw => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', NONE, '0', '0', NONE), + INSN_modud => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_moduw => (DVU, NONE, OP_MOD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_mtcrf => (ALU, NONE, OP_MTCRF, NONE, NONE, RS, NONE, '0', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mtfsb => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_mtfsf => (FPU, FPU, OP_FP_MISC, NONE, FRB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_mtfsfi => (FPU, FPU, OP_FP_MISC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_mtmsr => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_mtmsrd => (ALU, NONE, OP_MTMSRD, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mtspr => (ALU, NONE, OP_MTSPR, NONE, NONE, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_mulhd => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_mulhdu => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_mulhw => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_mulhwu => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_mulld => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_mulli => (ALU, NONE, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), + INSN_mullw => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_nand => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_neg => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_nop => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_nor => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_or => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_orc => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_ori => (ALU, NONE, OP_OR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_oris => (ALU, NONE, OP_OR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_popcntb => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_popcntd => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_popcntw => (ALU, NONE, OP_POPCNT, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_prtyd => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_prtyw => (ALU, NONE, OP_PRTY, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_rfid => (ALU, NONE, OP_RFID, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_rldcl => (ALU, NONE, OP_RLCL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rldcr => (ALU, NONE, OP_RLCR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rldic => (ALU, NONE, OP_RLC, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rldicl => (ALU, NONE, OP_RLCL, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rldicr => (ALU, NONE, OP_RLCR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rldimi => (ALU, NONE, OP_RLC, RA, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_rlwimi => (ALU, NONE, OP_RLC, RA, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_rlwinm => (ALU, NONE, OP_RLC, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_rlwnm => (ALU, NONE, OP_RLC, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_sc => (ALU, NONE, OP_SC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_setb => (ALU, NONE, OP_SETB, NONE, NONE, NONE, RT, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_slbia => (LDST, NONE, OP_TLBIE, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sld => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_slw => (ALU, NONE, OP_SHL, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_srad => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_sradi => (ALU, NONE, OP_SHR, NONE, CONST_SH, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_sraw => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_srawi => (ALU, NONE, OP_SHR, NONE, CONST_SH32, RS, RA, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_srd => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_srw => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_stb => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stbcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stbcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), + INSN_stbu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stbux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stbx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_std => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), + INSN_stdu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfd => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfdu => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfdux => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfdx => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfiwx => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stfs => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_stfsu => (LDST, FPU, OP_STORE, RA_OR_ZERO, CONST_SI, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), + INSN_stfsux => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '1', '0', NONE, '0', '0', NONE), + INSN_stfsx => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_sth => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), + INSN_sthu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stw => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), + INSN_stwu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_subf => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subfc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subfe => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subfic => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_subfme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subfze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_sync => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_td => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_tdi => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_tlbie => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_tlbiel => (LDST, NONE, OP_TLBIE, NONE, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_tlbsync => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_tw => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_twi => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), + INSN_wait => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_xor => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_xori => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_xoris => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE) + ); function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is variable ret : ram_spr_info; @@ -583,17 +873,16 @@ architecture behaviour of decode1 is end; begin - decode1_0: process(clk) + decode0_0: process(clk) begin if rising_edge(clk) then if rst = '1' then - r <= Decode1ToDecode2Init; - ri <= reg_internal_t_init; + dc0 <= dc0_t_init; elsif flush_in = '1' then - r.valid <= '0'; + dc0.f_in.valid <= '0'; + dc0.f_in.fetch_failed <= '0'; elsif stall_in = '0' then - r <= rin; - ri <= ri_in; + dc0 <= dc0in; end if; if rst = '1' then br.br_nia <= (others => '0'); @@ -604,12 +893,27 @@ begin end if; end if; end process; - busy_out <= stall_in; - decode1_1: process(all) - variable v : Decode1ToDecode2Type; - variable vr : Decode1ToRegisterFileType; - variable vi : reg_internal_t; + decode0_roms: process(clk) + begin + if rising_edge(clk) then + if stall_in = '0' then + if is_X(maj_rom_addr) then + major_predecode <= INSN_illegal; + else + major_predecode <= major_predecode_rom(to_integer(unsigned(maj_rom_addr))); + end if; + if is_X(row_rom_addr) then + row_predecode <= INSN_illegal; + else + row_predecode <= row_predecode_rom(to_integer(unsigned(row_rom_addr))); + end if; + end if; + end if; + end process; + + decode0_1: process(all) + variable v : dc0_t; variable majorop : std_ulogic_vector(5 downto 0); variable majaddr : std_ulogic_vector(10 downto 0); variable rowaddr : std_ulogic_vector(10 downto 0); @@ -617,39 +921,16 @@ begin variable br_target : std_ulogic_vector(61 downto 0); variable br_offset : signed(23 downto 0); variable bv : br_predictor_t; - variable fprs, fprabc : std_ulogic; - variable in3rc : std_ulogic; - variable may_read_rb : std_ulogic; begin - v := Decode1ToDecode2Init; - vi := reg_internal_t_init; - - v.valid := f_in.valid; - v.nia := f_in.nia; - v.insn := f_in.insn; - v.stop_mark := f_in.stop_mark; - v.big_endian := f_in.big_endian; - - fprs := '0'; - fprabc := '0'; - in3rc := '0'; - may_read_rb := '0'; - - if f_in.valid = '1' then - report "Decode insn " & to_hstring(f_in.insn) & " at " & to_hstring(f_in.nia); - end if; + v := dc0_t_init; + v.f_in := f_in; br_offset := (others => '0'); majorop := f_in.insn(31 downto 26); majaddr := majorop & f_in.insn(4 downto 0); - if is_X(majaddr) then - v.decode := x_inst; - else - vi.maj_decode := major_decode_rom(to_integer(unsigned(majaddr))); - end if; - -- row_decode_rom is used for op 19, 31, 59, 63 + -- row_predecode_rom is used for op 19, 31, 59, 63 -- addr bit 10 is 0 for op 31, 1 for 19, 59, 63 rowaddr(10) := f_in.insn(31) or not f_in.insn(29); rowaddr(9 downto 5) := f_in.insn(10 downto 6); @@ -661,11 +942,9 @@ begin rowaddr(4 downto 3) := f_in.insn(5 downto 4); end if; rowaddr(2 downto 0) := f_in.insn(3 downto 1); - if is_X(rowaddr) then - vi.row_decode := x_inst; - else - vi.row_decode := row_decode_rom(to_integer(unsigned(rowaddr))); - end if; + + maj_rom_addr <= majaddr; + row_rom_addr <= rowaddr; if is_X(f_in.insn) then v.spr_info := (sel => "XXX", others => 'X'); @@ -679,22 +958,22 @@ begin case unsigned(majorop) is when "000100" => -- 4 -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) - vi.override := not f_in.insn(5); - in3rc := '1'; - may_read_rb := '1'; + v.override := not f_in.insn(5); + v.in3rc := '1'; + v.maybe_rb := '1'; when "010111" => -- 23 -- rlwnm[.] - may_read_rb := '1'; + v.maybe_rb := '1'; when "011111" => -- 31 -- major opcode 31, lots of things - vi.use_row := '1'; - may_read_rb := '1'; + v.use_row := '1'; + v.maybe_rb := '1'; if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then -- lower half of column 23 has FP loads and stores - fprs := '1'; + v.fprs := '1'; end if; when "010000" => -- 16 @@ -713,75 +992,55 @@ begin -- addpcis (column 2) is in the major table -- Use the row table for columns 0-1 and 16-23 (mapped to 8-15) -- Columns 4-7 in the row table are used for op 59 cols 12-15 - vi.override := f_in.insn(4); - vi.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2)); + v.override := f_in.insn(4); + v.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2)); when "011000" => -- 24 -- ori, special-case the standard NOP if std_match(f_in.insn, "01100000000000000000000000000000") then - report "PPC_nop"; - vi.override := '1'; - vi.override_decode := nop_instr; + v.override := '1'; + v.ov_insn := INSN_nop; end if; when "011110" => -- 30 - may_read_rb := f_in.insn(4); + v.maybe_rb := f_in.insn(4); when "110100" | "110101" | "110110" | "110111" => -- 52, 53, 54, 55 -- stfd[u] and stfs[u] if HAS_FPU then - fprs := '1'; + v.fprs := '1'; end if; when "111011" => -- 59 if HAS_FPU then -- floating point operations, mostly single-precision -- Use row table for columns 12-15, major table for 16-31 - vi.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3)); - vi.use_row := not f_in.insn(5); - in3rc := '1'; - fprabc := '1'; - fprs := '1'; - may_read_rb := '1'; + v.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3)); + v.use_row := not f_in.insn(5); + v.in3rc := '1'; + v.fprabc := '1'; + v.fprs := '1'; + v.maybe_rb := '1'; end if; when "111111" => -- 63 if HAS_FPU then -- floating point operations, general and double-precision - vi.use_row := not f_in.insn(5); - in3rc := '1'; - fprabc := '1'; - fprs := '1'; - may_read_rb := '1'; + v.use_row := not f_in.insn(5); + v.in3rc := '1'; + v.fprabc := '1'; + v.fprs := '1'; + v.maybe_rb := '1'; end if; when others => end case; - -- Work out GPR/FPR read addresses - vr.reg_1_addr := fprabc & insn_ra(f_in.insn); - vr.reg_2_addr := fprabc & insn_rb(f_in.insn); - if in3rc = '1' then - vr.reg_3_addr := fprabc & insn_rcreg(f_in.insn); - else - vr.reg_3_addr := fprs & insn_rs(f_in.insn); - end if; - vr.read_1_enable := f_in.valid and not f_in.fetch_failed; - vr.read_2_enable := f_in.valid and not f_in.fetch_failed and may_read_rb; - vr.read_3_enable := f_in.valid and not f_in.fetch_failed; - - v.reg_a := vr.reg_1_addr; - v.reg_b := vr.reg_2_addr; - v.reg_c := vr.reg_3_addr; - if f_in.fetch_failed = '1' then - v.valid := '1'; - vi.override := '1'; - vi.override_decode := fetch_fail_inst; + v.override := '1'; + v.ov_insn := INSN_fetch_fail; -- Only send down a single OP_FETCH_FAILED - if ri.override = '1' and ri.override_decode.insn_type = OP_FETCH_FAILED then - v.valid := '0'; - end if; + v.f_in.valid := not dc0.f_in.fetch_failed; end if; -- Branch predictor @@ -801,24 +1060,91 @@ begin -- after a clock edge... br_target := std_ulogic_vector(signed(br.br_nia) + br.br_offset); - -- Update registers - rin <= v; - ri_in <= vi; + dc0in <= v; br_in <= bv; - -- Update outputs - d_out <= r; - if ri.override = '1' then - d_out.decode <= ri.override_decode; - elsif ri.use_row = '1' then - d_out.decode <= ri.row_decode; - else - d_out.decode <= ri.maj_decode; - end if; f_out.redirect <= br.predict; f_out.redirect_nia <= br_target & "00"; flush_out <= bv.predict or br.predict; + end process; + + decode1_0: process(clk) + begin + if rising_edge(clk) then + if rst = '1' then + r <= Decode1ToDecode2Init; + elsif flush_in = '1' then + r.valid <= '0'; + elsif stall_in = '0' then + r <= rin; + end if; + end if; + end process; + + busy_out <= stall_in; + + decode1_rom: process(clk) + begin + if rising_edge(clk) then + if stall_in = '0' then + decode <= decode_rom(decode_rom_addr); + end if; + end if; + end process; + + decode1_1: process(all) + variable v : Decode1ToDecode2Type; + variable vr : Decode1ToRegisterFileType; + variable icode : insn_code; + variable sprn : spr_num_t; + begin + v := Decode1ToDecode2Init; + + v.valid := dc0.f_in.valid; + v.nia := dc0.f_in.nia; + v.insn := dc0.f_in.insn; + v.stop_mark := dc0.f_in.stop_mark; + v.big_endian := dc0.f_in.big_endian; + v.br_pred := dc0.br_pred; + v.spr_info := dc0.spr_info; + v.ram_spr := dc0.ram_spr; + + if dc0.override = '1' then + icode := dc0.ov_insn; + elsif dc0.use_row = '0' then + icode := major_predecode; + else + icode := row_predecode; + end if; + decode_rom_addr <= icode; + if dc0.f_in.valid = '1' then + report "Decode insn " & to_hstring(dc0.f_in.insn) & " at " & to_hstring(dc0.f_in.nia) & + " code " & insn_code'image(icode); + end if; + + -- Work out GPR/FPR read addresses + vr.reg_1_addr := dc0.fprabc & insn_ra(dc0.f_in.insn); + vr.reg_2_addr := dc0.fprabc & insn_rb(dc0.f_in.insn); + if dc0.in3rc = '1' then + vr.reg_3_addr := dc0.fprabc & insn_rcreg(dc0.f_in.insn); + else + vr.reg_3_addr := dc0.fprs & insn_rs(dc0.f_in.insn); + end if; + vr.read_1_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; + vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and dc0.maybe_rb; + vr.read_3_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; + + v.reg_a := vr.reg_1_addr; + v.reg_b := vr.reg_2_addr; + v.reg_c := vr.reg_3_addr; + + -- Update registers + rin <= v; + + -- Update outputs + d_out <= r; + d_out.decode <= decode; r_out <= vr; end process; diff --git a/decode_types.vhdl b/decode_types.vhdl index d5e51bf..443d093 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -24,6 +24,291 @@ package decode_types is OP_ADDG6S, OP_FETCH_FAILED ); + + type insn_code is ( + INSN_illegal, + INSN_fetch_fail, + INSN_add, + INSN_addc, + INSN_adde, + INSN_addex, + INSN_addg6s, + INSN_addi, + INSN_addic, + INSN_addic_dot, + INSN_addis, + INSN_addme, + INSN_addpcis, + INSN_addze, + INSN_and, + INSN_andc, + INSN_andi_dot, + INSN_andis_dot, + INSN_attn, + INSN_b, + INSN_bc, + INSN_bcctr, + INSN_bclr, + INSN_bctar, + INSN_bperm, + INSN_cbcdtd, + INSN_cdtbcd, + INSN_cmp, + INSN_cmpb, + INSN_cmpeqb, + INSN_cmpi, + INSN_cmpl, + INSN_cmpli, + INSN_cmprb, + INSN_cntlzd, + INSN_cntlzw, + INSN_cnttzd, + INSN_cnttzw, + INSN_crand, + INSN_crandc, + INSN_creqv, + INSN_crnand, + INSN_crnor, + INSN_cror, + INSN_crorc, + INSN_crxor, + INSN_darn, + INSN_dcbf, + INSN_dcbst, + INSN_dcbt, + INSN_dcbtst, + INSN_dcbz, + INSN_divd, + INSN_divde, + INSN_divdeu, + INSN_divdu, + INSN_divw, + INSN_divwe, + INSN_divweu, + INSN_divwu, + INSN_eieio, + INSN_eqv, + INSN_extsb, + INSN_extsh, + INSN_extsw, + INSN_extswsli, + INSN_fabs, + INSN_fadd, + INSN_fadds, + INSN_fcfid, + INSN_fcfids, + INSN_fcfidu, + INSN_fcfidus, + INSN_fcmpo, + INSN_fcmpu, + INSN_fcpsgn, + INSN_fctid, + INSN_fctidu, + INSN_fctiduz, + INSN_fctidz, + INSN_fctiw, + INSN_fctiwu, + INSN_fctiwuz, + INSN_fctiwz, + INSN_fdiv, + INSN_fdivs, + INSN_fmadd, + INSN_fmadds, + INSN_fmr, + INSN_fmrgew, + INSN_fmrgow, + INSN_fmsub, + INSN_fmsubs, + INSN_fmul, + INSN_fmuls, + INSN_fnabs, + INSN_fneg, + INSN_fnmadd, + INSN_fnmadds, + INSN_fnmsub, + INSN_fnmsubs, + INSN_fre, + INSN_fres, + INSN_frim, + INSN_frin, + INSN_frip, + INSN_friz, + INSN_frsp, + INSN_frsqrte, + INSN_frsqrtes, + INSN_fsel, + INSN_fsqrt, + INSN_fsqrts, + INSN_fsub, + INSN_fsubs, + INSN_ftdiv, + INSN_ftsqrt, + INSN_icbi, + INSN_icbt, + INSN_isel, + INSN_isync, + INSN_lbarx, + INSN_lbz, + INSN_lbzcix, + INSN_lbzu, + INSN_lbzux, + INSN_lbzx, + INSN_ld, + INSN_ldarx, + INSN_ldbrx, + INSN_ldcix, + INSN_ldu, + INSN_ldux, + INSN_ldx, + INSN_lfd, + INSN_lfdu, + INSN_lfdux, + INSN_lfdx, + INSN_lfiwax, + INSN_lfiwzx, + INSN_lfs, + INSN_lfsu, + INSN_lfsux, + INSN_lfsx, + INSN_lha, + INSN_lharx, + INSN_lhau, + INSN_lhaux, + INSN_lhax, + INSN_lhbrx, + INSN_lhz, + INSN_lhzcix, + INSN_lhzu, + INSN_lhzux, + INSN_lhzx, + INSN_lwa, + INSN_lwarx, + INSN_lwaux, + INSN_lwax, + INSN_lwbrx, + INSN_lwz, + INSN_lwzcix, + INSN_lwzu, + INSN_lwzux, + INSN_lwzx, + INSN_maddhd, + INSN_maddhdu, + INSN_maddld, + INSN_mcrf, + INSN_mcrfs, + INSN_mcrxrx, + INSN_mfcr, + INSN_mffs, + INSN_mfmsr, + INSN_mfspr, + INSN_modsd, + INSN_modsw, + INSN_modud, + INSN_moduw, + INSN_mtcrf, + INSN_mtfsb, + INSN_mtfsf, + INSN_mtfsfi, + INSN_mtmsr, + INSN_mtmsrd, + INSN_mtspr, + INSN_mulhd, + INSN_mulhdu, + INSN_mulhw, + INSN_mulhwu, + INSN_mulld, + INSN_mulli, + INSN_mullw, + INSN_nand, + INSN_neg, + INSN_nop, + INSN_nor, + INSN_or, + INSN_orc, + INSN_ori, + INSN_oris, + INSN_popcntb, + INSN_popcntd, + INSN_popcntw, + INSN_prtyd, + INSN_prtyw, + INSN_rfid, + INSN_rldcl, + INSN_rldcr, + INSN_rldic, + INSN_rldicl, + INSN_rldicr, + INSN_rldimi, + INSN_rlwimi, + INSN_rlwinm, + INSN_rlwnm, + INSN_sc, + INSN_setb, + INSN_slbia, + INSN_sld, + INSN_slw, + INSN_srad, + INSN_sradi, + INSN_sraw, + INSN_srawi, + INSN_srd, + INSN_srw, + INSN_stb, + INSN_stbcix, + INSN_stbcx, + INSN_stbu, + INSN_stbux, + INSN_stbx, + INSN_std, + INSN_stdbrx, + INSN_stdcix, + INSN_stdcx, + INSN_stdu, + INSN_stdux, + INSN_stdx, + INSN_stfd, + INSN_stfdu, + INSN_stfdux, + INSN_stfdx, + INSN_stfiwx, + INSN_stfs, + INSN_stfsu, + INSN_stfsux, + INSN_stfsx, + INSN_sth, + INSN_sthbrx, + INSN_sthcix, + INSN_sthcx, + INSN_sthu, + INSN_sthux, + INSN_sthx, + INSN_stw, + INSN_stwbrx, + INSN_stwcix, + INSN_stwcx, + INSN_stwu, + INSN_stwux, + INSN_stwx, + INSN_subf, + INSN_subfc, + INSN_subfe, + INSN_subfic, + INSN_subfme, + INSN_subfze, + INSN_sync, + INSN_td, + INSN_tdi, + INSN_tlbie, + INSN_tlbiel, + INSN_tlbsync, + INSN_tw, + INSN_twi, + INSN_wait, + INSN_xor, + INSN_xori, + INSN_xoris + ); + type input_reg_a_t is (NONE, RA, RA_OR_ZERO, CIA, FRA); type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, FRB); From c9aea45ffe8188579fd1f4686a3d80bba29fa827 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 28 Jul 2022 19:00:04 +1000 Subject: [PATCH 11/22] decode1: Divide insn_code values into ranges to indicate register usage This lets us compute r_out.reg_*_addr and r_out.read_2_enable values without needing access to the primary opcode value. We also have that non-FP instructions are < 256. Signed-off-by: Paul Mackerras --- decode1.vhdl | 85 +++++----- decode_types.vhdl | 401 ++++++++++++++++++++++++++-------------------- 2 files changed, 266 insertions(+), 220 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 9dd57d9..98c5b80 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -39,10 +39,6 @@ architecture behaviour of decode1 is ov_insn : insn_code; spr_info : spr_id; ram_spr : ram_spr_info; - fprs : std_ulogic; - fprabc : std_ulogic; - in3rc : std_ulogic; - maybe_rb : std_ulogic; end record; constant dc0_t_init : dc0_t := (f_in => IcacheToDecode1Init, ov_insn => INSN_illegal, @@ -792,7 +788,9 @@ architecture behaviour of decode1 is INSN_wait => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_xor => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_xori => (ALU, NONE, OP_XOR, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_xoris => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE) + INSN_xoris => (ALU, NONE, OP_XOR, NONE, CONST_UI_HI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + + others => (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE) ); function decode_ram_spr(sprn : spr_num_t) return ram_spr_info is @@ -959,22 +957,11 @@ begin when "000100" => -- 4 -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) v.override := not f_in.insn(5); - v.in3rc := '1'; - v.maybe_rb := '1'; - - when "010111" => -- 23 - -- rlwnm[.] - v.maybe_rb := '1'; when "011111" => -- 31 -- major opcode 31, lots of things + -- Use the first half of the row table for all columns v.use_row := '1'; - v.maybe_rb := '1'; - - if HAS_FPU and std_match(f_in.insn(10 downto 1), "1----10111") then - -- lower half of column 23 has FP loads and stores - v.fprs := '1'; - end if; when "010000" => -- 16 -- Predict backward branches as taken, forward as untaken @@ -990,8 +977,9 @@ begin -- Columns 8-15 and 24-31 don't have any valid instructions -- (where insn(5..1) is the column number). -- addpcis (column 2) is in the major table - -- Use the row table for columns 0-1 and 16-23 (mapped to 8-15) - -- Columns 4-7 in the row table are used for op 59 cols 12-15 + -- Other valid columns are mapped to columns in the second + -- half of the row table: columns 0-1 are mapped to 16-17 + -- and 16-23 are mapped to 24-31. v.override := f_in.insn(4); v.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2)); @@ -1002,35 +990,26 @@ begin v.ov_insn := INSN_nop; end if; - when "011110" => -- 30 - v.maybe_rb := f_in.insn(4); - - when "110100" | "110101" | "110110" | "110111" => -- 52, 53, 54, 55 - -- stfd[u] and stfs[u] - if HAS_FPU then - v.fprs := '1'; - end if; - when "111011" => -- 59 if HAS_FPU then -- floating point operations, mostly single-precision - -- Use row table for columns 12-15, major table for 16-31 + -- Columns 0-11 are illegal; columns 12-15 are mapped + -- to columns 20-23 in the second half of the row table, + -- and columns 16-31 are in the major table. v.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3)); v.use_row := not f_in.insn(5); - v.in3rc := '1'; - v.fprabc := '1'; - v.fprs := '1'; - v.maybe_rb := '1'; + else + v.override := '1'; end if; when "111111" => -- 63 if HAS_FPU then -- floating point operations, general and double-precision + -- Use columns 0-15 of the second half of the row table + -- for columns 0-15, and the major table for columns 16-31. v.use_row := not f_in.insn(5); - v.in3rc := '1'; - v.fprabc := '1'; - v.fprs := '1'; - v.maybe_rb := '1'; + else + v.override := '1'; end if; when others => @@ -1097,6 +1076,7 @@ begin variable vr : Decode1ToRegisterFileType; variable icode : insn_code; variable sprn : spr_num_t; + variable maybe_rb : std_ulogic; begin v := Decode1ToDecode2Init; @@ -1124,15 +1104,32 @@ begin end if; -- Work out GPR/FPR read addresses - vr.reg_1_addr := dc0.fprabc & insn_ra(dc0.f_in.insn); - vr.reg_2_addr := dc0.fprabc & insn_rb(dc0.f_in.insn); - if dc0.in3rc = '1' then - vr.reg_3_addr := dc0.fprabc & insn_rcreg(dc0.f_in.insn); - else - vr.reg_3_addr := dc0.fprs & insn_rs(dc0.f_in.insn); + maybe_rb := '0'; + vr.reg_1_addr := '0' & insn_ra(dc0.f_in.insn); + vr.reg_2_addr := '0' & insn_rb(dc0.f_in.insn); + vr.reg_3_addr := '0' & insn_rs(dc0.f_in.insn); + if icode >= INSN_first_rb then + maybe_rb := '1'; + if icode < INSN_first_frs then + if icode >= INSN_first_rc then + vr.reg_3_addr := '0' & insn_rcreg(dc0.f_in.insn); + end if; + else + -- access FRS operand + vr.reg_3_addr(5) := '1'; + if icode >= INSN_first_frab then + -- access FRA and/or FRB operands + vr.reg_1_addr(5) := '1'; + vr.reg_2_addr(5) := '1'; + end if; + if icode >= INSN_first_frabc then + -- access FRC operand + vr.reg_3_addr := '1' & insn_rcreg(dc0.f_in.insn); + end if; + end if; end if; vr.read_1_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; - vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and dc0.maybe_rb; + vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and maybe_rb; vr.read_3_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; v.reg_a := vr.reg_1_addr; diff --git a/decode_types.vhdl b/decode_types.vhdl index 443d093..dd2781e 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -25,14 +25,15 @@ package decode_types is OP_FETCH_FAILED ); + -- The following list is ordered in such a way that we can know some + -- things about which registers are accessed by an instruction by its place + -- in the list. In other words we can decide whether an instruction + -- accesses FPRs and whether it has an RB operand by doing simple + -- comparisons of the insn_code for the instruction with a few constants. type insn_code is ( + -- The following instructions don't have an RB operand or access FPRs INSN_illegal, INSN_fetch_fail, - INSN_add, - INSN_addc, - INSN_adde, - INSN_addex, - INSN_addg6s, INSN_addi, INSN_addic, INSN_addic_dot, @@ -40,8 +41,6 @@ package decode_types is INSN_addme, INSN_addpcis, INSN_addze, - INSN_and, - INSN_andc, INSN_andi_dot, INSN_andis_dot, INSN_attn, @@ -50,20 +49,14 @@ package decode_types is INSN_bcctr, INSN_bclr, INSN_bctar, - INSN_bperm, INSN_cbcdtd, INSN_cdtbcd, - INSN_cmp, - INSN_cmpb, - INSN_cmpeqb, INSN_cmpi, - INSN_cmpl, INSN_cmpli, - INSN_cmprb, - INSN_cntlzd, INSN_cntlzw, - INSN_cnttzd, + INSN_cntlzd, INSN_cnttzw, + INSN_cnttzd, INSN_crand, INSN_crandc, INSN_creqv, @@ -73,242 +66,298 @@ package decode_types is INSN_crorc, INSN_crxor, INSN_darn, - INSN_dcbf, - INSN_dcbst, - INSN_dcbt, - INSN_dcbtst, - INSN_dcbz, - INSN_divd, - INSN_divde, - INSN_divdeu, - INSN_divdu, - INSN_divw, - INSN_divwe, - INSN_divweu, - INSN_divwu, INSN_eieio, - INSN_eqv, INSN_extsb, INSN_extsh, INSN_extsw, INSN_extswsli, - INSN_fabs, - INSN_fadd, - INSN_fadds, - INSN_fcfid, - INSN_fcfids, - INSN_fcfidu, - INSN_fcfidus, - INSN_fcmpo, - INSN_fcmpu, - INSN_fcpsgn, - INSN_fctid, - INSN_fctidu, - INSN_fctiduz, - INSN_fctidz, - INSN_fctiw, - INSN_fctiwu, - INSN_fctiwuz, - INSN_fctiwz, - INSN_fdiv, - INSN_fdivs, - INSN_fmadd, - INSN_fmadds, - INSN_fmr, - INSN_fmrgew, - INSN_fmrgow, - INSN_fmsub, - INSN_fmsubs, - INSN_fmul, - INSN_fmuls, - INSN_fnabs, - INSN_fneg, - INSN_fnmadd, - INSN_fnmadds, - INSN_fnmsub, - INSN_fnmsubs, - INSN_fre, - INSN_fres, - INSN_frim, - INSN_frin, - INSN_frip, - INSN_friz, - INSN_frsp, - INSN_frsqrte, - INSN_frsqrtes, - INSN_fsel, - INSN_fsqrt, - INSN_fsqrts, - INSN_fsub, - INSN_fsubs, - INSN_ftdiv, - INSN_ftsqrt, - INSN_icbi, - INSN_icbt, - INSN_isel, INSN_isync, - INSN_lbarx, INSN_lbz, - INSN_lbzcix, INSN_lbzu, - INSN_lbzux, - INSN_lbzx, INSN_ld, - INSN_ldarx, - INSN_ldbrx, - INSN_ldcix, INSN_ldu, - INSN_ldux, - INSN_ldx, - INSN_lfd, - INSN_lfdu, - INSN_lfdux, - INSN_lfdx, - INSN_lfiwax, - INSN_lfiwzx, - INSN_lfs, - INSN_lfsu, - INSN_lfsux, - INSN_lfsx, INSN_lha, - INSN_lharx, INSN_lhau, - INSN_lhaux, - INSN_lhax, - INSN_lhbrx, INSN_lhz, - INSN_lhzcix, INSN_lhzu, - INSN_lhzux, - INSN_lhzx, INSN_lwa, - INSN_lwarx, - INSN_lwaux, - INSN_lwax, - INSN_lwbrx, INSN_lwz, - INSN_lwzcix, INSN_lwzu, - INSN_lwzux, - INSN_lwzx, - INSN_maddhd, - INSN_maddhdu, - INSN_maddld, INSN_mcrf, INSN_mcrfs, INSN_mcrxrx, INSN_mfcr, - INSN_mffs, INSN_mfmsr, INSN_mfspr, - INSN_modsd, - INSN_modsw, - INSN_modud, - INSN_moduw, INSN_mtcrf, INSN_mtfsb, - INSN_mtfsf, INSN_mtfsfi, INSN_mtmsr, INSN_mtmsrd, INSN_mtspr, - INSN_mulhd, - INSN_mulhdu, - INSN_mulhw, - INSN_mulhwu, - INSN_mulld, INSN_mulli, - INSN_mullw, - INSN_nand, INSN_neg, INSN_nop, - INSN_nor, - INSN_or, - INSN_orc, INSN_ori, INSN_oris, INSN_popcntb, - INSN_popcntd, INSN_popcntw, - INSN_prtyd, + INSN_popcntd, INSN_prtyw, + INSN_prtyd, INSN_rfid, - INSN_rldcl, - INSN_rldcr, INSN_rldic, INSN_rldicl, INSN_rldicr, INSN_rldimi, INSN_rlwimi, INSN_rlwinm, - INSN_rlwnm, INSN_sc, INSN_setb, INSN_slbia, - INSN_sld, - INSN_slw, - INSN_srad, INSN_sradi, - INSN_sraw, INSN_srawi, - INSN_srd, - INSN_srw, INSN_stb, + INSN_stbu, + INSN_std, + INSN_stdu, + INSN_sth, + INSN_sthu, + INSN_stw, + INSN_stwu, + INSN_subfic, + INSN_subfme, + INSN_subfze, + INSN_sync, + INSN_tdi, + INSN_tlbsync, + INSN_twi, + INSN_wait, + INSN_xori, + INSN_xoris, + + -- pad to 112 to simplify comparison logic + INSN_103, + INSN_104, INSN_105, INSN_106, INSN_107, + INSN_108, INSN_109, INSN_110, INSN_111, + + -- The following instructions have an RB operand but don't access FPRs + INSN_add, + INSN_addc, + INSN_adde, + INSN_addex, + INSN_addg6s, + INSN_and, + INSN_andc, + INSN_bperm, + INSN_cmp, + INSN_cmpb, + INSN_cmpeqb, + INSN_cmpl, + INSN_cmprb, + INSN_dcbf, + INSN_dcbst, + INSN_dcbt, + INSN_dcbtst, + INSN_dcbz, + INSN_divd, + INSN_divdu, + INSN_divde, + INSN_divdeu, + INSN_divw, + INSN_divwu, + INSN_divwe, + INSN_divweu, + INSN_eqv, + INSN_icbi, + INSN_icbt, + INSN_isel, + INSN_lbarx, + INSN_lbzcix, + INSN_lbzux, + INSN_lbzx, + INSN_ldarx, + INSN_ldbrx, + INSN_ldcix, + INSN_ldx, + INSN_ldux, + INSN_lharx, + INSN_lhax, + INSN_lhaux, + INSN_lhbrx, + INSN_lhzcix, + INSN_lhzx, + INSN_lhzux, + INSN_lwarx, + INSN_lwax, + INSN_lwaux, + INSN_lwbrx, + INSN_lwzcix, + INSN_lwzx, + INSN_lwzux, + INSN_modsd, + INSN_modsw, + INSN_moduw, + INSN_modud, + INSN_mulhw, + INSN_mulhwu, + INSN_mulhd, + INSN_mulhdu, + INSN_mullw, + INSN_mulld, + INSN_nand, + INSN_nor, + INSN_or, + INSN_orc, + INSN_rldcl, + INSN_rldcr, + INSN_rlwnm, + INSN_slw, + INSN_sld, + INSN_sraw, + INSN_srad, + INSN_srw, + INSN_srd, INSN_stbcix, INSN_stbcx, - INSN_stbu, - INSN_stbux, INSN_stbx, - INSN_std, + INSN_stbux, INSN_stdbrx, INSN_stdcix, INSN_stdcx, - INSN_stdu, - INSN_stdux, INSN_stdx, - INSN_stfd, - INSN_stfdu, - INSN_stfdux, - INSN_stfdx, - INSN_stfiwx, - INSN_stfs, - INSN_stfsu, - INSN_stfsux, - INSN_stfsx, - INSN_sth, + INSN_stdux, INSN_sthbrx, INSN_sthcix, INSN_sthcx, - INSN_sthu, - INSN_sthux, INSN_sthx, - INSN_stw, + INSN_sthux, INSN_stwbrx, INSN_stwcix, INSN_stwcx, - INSN_stwu, - INSN_stwux, INSN_stwx, + INSN_stwux, INSN_subf, INSN_subfc, INSN_subfe, - INSN_subfic, - INSN_subfme, - INSN_subfze, - INSN_sync, INSN_td, - INSN_tdi, INSN_tlbie, INSN_tlbiel, - INSN_tlbsync, INSN_tw, - INSN_twi, - INSN_wait, INSN_xor, - INSN_xori, - INSN_xoris + + -- pad to 224 to simplify comparison logic + INSN_215, + INSN_216, INSN_217, INSN_218, INSN_219, + INSN_220, INSN_221, INSN_222, INSN_223, + + -- The following instructions have a third input addressed by RC + INSN_maddld, + INSN_maddhd, + INSN_maddhdu, + + -- pad to 256 to simplify comparison logic + INSN_227, + INSN_228, INSN_229, INSN_230, INSN_231, + INSN_232, INSN_233, INSN_234, INSN_235, + INSN_236, INSN_237, INSN_238, INSN_239, + INSN_240, INSN_241, INSN_242, INSN_243, + INSN_244, INSN_245, INSN_246, INSN_247, + INSN_248, INSN_249, INSN_250, INSN_251, + INSN_252, INSN_253, INSN_254, INSN_255, + + -- The following instructions access floating-point registers + -- These ones have an FRS operand, but RA/RB are GPRs + INSN_stfd, + INSN_stfdu, + INSN_stfs, + INSN_stfsu, + INSN_stfdux, + INSN_stfdx, + INSN_stfiwx, + INSN_stfsux, + INSN_stfsx, + -- These ones don't actually have an FRS operand (rather an FRT destination) + -- but are here so that all FP instructions are >= INST_first_frs. + INSN_lfd, + INSN_lfdu, + INSN_lfs, + INSN_lfsu, + INSN_lfdx, + INSN_lfdux, + INSN_lfiwax, + INSN_lfiwzx, + INSN_lfsx, + INSN_lfsux, + INSN_275, -- padding + + -- The following instructions access FRA and/or FRB operands + INSN_fabs, + INSN_fadd, + INSN_fadds, + INSN_fcfid, + INSN_fcfids, + INSN_fcfidu, + INSN_fcfidus, + INSN_fcmpo, + INSN_fcmpu, + INSN_fcpsgn, + INSN_fctid, + INSN_fctidz, + INSN_fctidu, + INSN_fctiduz, + INSN_fctiw, + INSN_fctiwz, + INSN_fctiwu, + INSN_fctiwuz, + INSN_fdiv, + INSN_fdivs, + INSN_fmr, + INSN_fmrgew, + INSN_fmrgow, + INSN_fnabs, + INSN_fneg, + INSN_fre, + INSN_fres, + INSN_frim, + INSN_frin, + INSN_frip, + INSN_friz, + INSN_frsp, + INSN_frsqrte, + INSN_frsqrtes, + INSN_fsqrt, + INSN_fsqrts, + INSN_fsub, + INSN_fsubs, + INSN_ftdiv, + INSN_ftsqrt, + INSN_mffs, + INSN_mtfsf, + + -- pad to 320 + INSN_318, INSN_319, + + -- The following instructions access FRA, FRB (possibly) and FRC operands + INSN_fmul, + INSN_fmuls, + INSN_fmadd, + INSN_fmadds, + INSN_fmsub, + INSN_fmsubs, + INSN_fnmadd, + INSN_fnmadds, + INSN_fnmsub, + INSN_fnmsubs, + INSN_fsel ); + constant INSN_first_rb : insn_code := INSN_add; + constant INSN_first_rc : insn_code := INSN_maddld; + constant INSN_first_frs : insn_code := INSN_stfd; + constant INSN_first_frab : insn_code := INSN_fabs; + constant INSN_first_frabc : insn_code := INSN_fmul; + type input_reg_a_t is (NONE, RA, RA_OR_ZERO, CIA, FRA); type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, FRB); From 26dc1e879c0999c201657dee44ea40c0760e4517 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 28 Jul 2022 20:28:41 +1000 Subject: [PATCH 12/22] Eliminate use of primary opcode outside of decode1 This changes code that previously looked at the primary opcode (bits 26 to 31) of the instruction to use other methods, in places other than in stage0 of decode1. * Extend rc_t to have a new value, RCOE, indicating that the instruction has both Rc and OE bits. * Decode2 now tells execute1 whether the instruction has a third operand, used for distinguishing between multiply and multiply-add instructions. * The invert_a field of the decode ROM is overloaded for load/store instructions to indicate cache-inhibited loads and stores. Signed-off-by: Paul Mackerras --- decode1.vhdl | 58 +++++++++++++++++++++++------------------------ decode2.vhdl | 5 ++-- decode_types.vhdl | 2 +- execute1.vhdl | 12 ++++------ 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/decode1.vhdl b/decode1.vhdl index 98c5b80..d017912 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -510,18 +510,18 @@ architecture behaviour of decode1 is INSN_illegal => (NONE, NONE, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_fetch_fail => (LDST, NONE, OP_FETCH_FAILED, CIA, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_add => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_addc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_adde => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_add => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_addc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_adde => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_addex => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '0', '0', OV, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_addg6s => (ALU, NONE, OP_ADDG6S, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_addi => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_addic => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_addic_dot => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '1', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), INSN_addis => (ALU, NONE, OP_ADD, RA_OR_ZERO, CONST_SI_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_addme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_addpcis => (ALU, NONE, OP_ADD, CIA, CONST_DXHI4, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_addze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_addze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '0', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_and => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_andc => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '1', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_andi_dot => (ALU, NONE, OP_AND, NONE, CONST_UI, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', ONE, '0', '0', NONE), @@ -560,14 +560,14 @@ architecture behaviour of decode1 is INSN_dcbt => (ALU, NONE, OP_DCBT, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_dcbtst => (ALU, NONE, OP_DCBTST, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_dcbz => (LDST, NONE, OP_DCBZ, RA_OR_ZERO, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_divd => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), - INSN_divde => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), - INSN_divdeu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_divdu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_divw => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), - INSN_divwe => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), - INSN_divweu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), - INSN_divwu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), + INSN_divd => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RCOE, '0', '0', NONE), + INSN_divde => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RCOE, '0', '0', NONE), + INSN_divdeu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_divdu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_divw => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RCOE, '0', '0', NONE), + INSN_divwe => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RCOE, '0', '0', NONE), + INSN_divweu => (DVU, NONE, OP_DIVE, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RCOE, '0', '0', NONE), + INSN_divwu => (DVU, NONE, OP_DIV, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RCOE, '0', '0', NONE), INSN_eieio => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_eqv => (ALU, NONE, OP_XOR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_extsb => (ALU, NONE, OP_EXTS, NONE, NONE, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), @@ -631,14 +631,14 @@ architecture behaviour of decode1 is INSN_isync => (ALU, NONE, OP_ISYNC, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lbarx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), INSN_lbz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_lbzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lbzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '1', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lbzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lbzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lbzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_ld => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_ldarx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', NONE, '0', '0', NONE), INSN_ldbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_ldcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_ldcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '1', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_ldu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_DS, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_ldux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_ldx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), @@ -659,7 +659,7 @@ architecture behaviour of decode1 is INSN_lhax => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lhbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lhz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_lhzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lhzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '1', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lhzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lhzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lhzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), @@ -669,7 +669,7 @@ architecture behaviour of decode1 is INSN_lwax => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '1', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lwbrx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lwz => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_lwzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_lwzcix => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '1', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_lwzu => (LDST, NONE, OP_LOAD, RA_OR_ZERO, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lwzux => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', DUPD), INSN_lwzx => (LDST, NONE, OP_LOAD, RA_OR_ZERO, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), @@ -698,11 +698,11 @@ architecture behaviour of decode1 is INSN_mulhdu => (ALU, NONE, OP_MUL_H64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_mulhw => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), INSN_mulhwu => (ALU, NONE, OP_MUL_H32, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), - INSN_mulld => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RC, '0', '0', NONE), + INSN_mulld => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', RCOE, '0', '0', NONE), INSN_mulli => (ALU, NONE, OP_MUL_L64, RA, CONST_SI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '1', NONE, '0', '0', NONE), - INSN_mullw => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RC, '0', '0', NONE), + INSN_mullw => (ALU, NONE, OP_MUL_L64, RA, RB, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '1', RCOE, '0', '0', NONE), INSN_nand => (ALU, NONE, OP_AND, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_neg => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_neg => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_nop => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_nor => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '1', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_or => (ALU, NONE, OP_OR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), @@ -736,14 +736,14 @@ architecture behaviour of decode1 is INSN_srd => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), INSN_srw => (ALU, NONE, OP_SHR, NONE, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '1', '0', RC, '0', '0', NONE), INSN_stb => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_stbcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stbcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '1', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stbcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), INSN_stbu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_stbux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_stbx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_std => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stdbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_stdcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stdcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '1', '0', ZERO, '0', is8B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stdcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), INSN_stdu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_DS, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_stdux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is8B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), @@ -759,24 +759,24 @@ architecture behaviour of decode1 is INSN_stfsx => (LDST, FPU, OP_STORE, RA_OR_ZERO, RB, FRS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '1', '0', NONE, '0', '0', NONE), INSN_sth => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_sthbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_sthcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_sthcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '1', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_sthcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), INSN_sthu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_sthux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_sthx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stw => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stwbrx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '1', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_stwcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), + INSN_stwcix => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '1', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_stwcx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '1', '0', '0', ONE, '0', '0', NONE), INSN_stwu => (LDST, NONE, OP_STORE, RA_OR_ZERO, CONST_SI, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_stwux => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, RA, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '1', '0', '0', '0', NONE, '0', '0', NONE), INSN_stwx => (LDST, NONE, OP_STORE, RA_OR_ZERO, RB, RS, NONE, '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_subf => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_subfc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_subfe => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subf => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '0', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_subfc => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_subfe => (ALU, NONE, OP_ADD, RA, RB, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_subfic => (ALU, NONE, OP_ADD, RA, CONST_SI, NONE, RT, '0', '0', '1', '0', ONE, '1', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), - INSN_subfme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), - INSN_subfze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0', NONE), + INSN_subfme => (ALU, NONE, OP_ADD, RA, CONST_M1, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), + INSN_subfze => (ALU, NONE, OP_ADD, RA, NONE, NONE, RT, '0', '0', '1', '0', CA, '1', NONE, '0', '0', '0', '0', '0', '0', RCOE, '0', '0', NONE), INSN_sync => (ALU, NONE, OP_NOP, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_td => (ALU, NONE, OP_TRAP, RA, RB, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), INSN_tdi => (ALU, NONE, OP_TRAP, RA, CONST_SI, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0', NONE), diff --git a/decode2.vhdl b/decode2.vhdl index 6cac985..98557f9 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -188,7 +188,7 @@ architecture behaviour of decode2 is function decode_rc (t : rc_t; insn_in : std_ulogic_vector(31 downto 0)) return std_ulogic is begin case t is - when RC => + when RC | RCOE => return insn_rc(insn_in); when ONE => return '1'; @@ -427,8 +427,7 @@ begin end if; case d_in.decode.insn_type is when OP_ADD | OP_MUL_L64 | OP_DIV | OP_DIVE => - -- OE field is valid in OP_ADD/OP_MUL_L64 with major opcode 31 only - if d_in.insn(31 downto 26) = "011111" and insn_oe(d_in.insn) = '1' then + if d_in.decode.rc = RCOE and insn_oe(d_in.insn) = '1' then v.e.oe := '1'; v.e.output_xer := '1'; v.output_ov := '1'; diff --git a/decode_types.vhdl b/decode_types.vhdl index dd2781e..9f19530 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -363,7 +363,7 @@ package decode_types is CONST_DXHI4, CONST_DS, CONST_DQ, CONST_M1, CONST_SH, CONST_SH32, FRB); type input_reg_c_t is (NONE, RS, RCR, FRC, FRS); type output_reg_a_t is (NONE, RT, RA, FRT); - type rc_t is (NONE, ONE, RC); + type rc_t is (NONE, ONE, RC, RCOE); type carry_in_t is (ZERO, CA, OV, ONE); constant SH_OFFSET : integer := 0; diff --git a/execute1.vhdl b/execute1.vhdl index 556dc41..024f5c2 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -719,7 +719,7 @@ begin x_to_divider.flush <= flush_in; addend := (others => '0'); - if e_in.insn(26) = '0' then + if e_in.reg_valid3 = '1' then -- integer multiply-add, major op 4 (if it is a multiply) addend(63 downto 0) := c_in; if e_in.is_signed = '1' then @@ -1271,7 +1271,7 @@ begin v.se.icache_inval := '1'; when OP_MUL_L64 => - if HAS_SHORT_MULT and e_in.insn(26) = '1' and + if HAS_SHORT_MULT and e_in.reg_valid3 = '0' and fits_in_n_bits(a_in, 16) and fits_in_n_bits(b_in, 16) then -- Operands fit into 16 bits, so use short multiplier if e_in.oe = '1' then @@ -1567,11 +1567,9 @@ begin lv.reserve := e_in.reserve; lv.rc := e_in.rc; lv.insn := e_in.insn; - -- decode l*cix and st*cix instructions here - if e_in.insn(31 downto 26) = "011111" and e_in.insn(10 downto 9) = "11" and - e_in.insn(5 downto 1) = "10101" then - lv.ci := '1'; - end if; + -- invert_a field is overloaded for load/store instructions + -- to mark l*cix and st*cix + lv.ci := e_in.invert_a; lv.virt_mode := ex1.msr(MSR_DR); lv.priv_mode := not ex1.msr(MSR_PR); lv.mode_32bit := not ex1.msr(MSR_SF); From 21ab36a0c0cc05501d036a160f3002d21b7cd9cd Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 29 Jul 2022 20:29:26 +1000 Subject: [PATCH 13/22] Pre-decode instructions when writing them to icache This splits out the decoding done in the decode0 step into a separate predecoder, used when writing instructions into the icache. The icache now holds 36 bits per instruction rather than 32. For valid instructions, those 36 bits comprise the bottom 26 bits of the instruction word, a 9-bit insn_code value (which uniquely identifies the instruction), and a zero in the MSB. For illegal instructions, the MSB is one and the full instruction word is in the bottom 32 bits. Having the full instruction word available for illegal instructions means that it can be printed in the log when simulating, or in future could be placed in the HEIR register. If we don't have an FPU, then the floating-point instructions are regarded as illegal. In that case, the insn_code values would fit into 8 bits, which could be used in future to reduce the size of decode_rom from 512 to 256 entries. Signed-off-by: Paul Mackerras --- Makefile | 2 +- cache_ram.vhdl | 11 +- common.vhdl | 3 +- core.vhdl | 1 + decode1.vhdl | 691 +++++-------------------------------------------- icache.vhdl | 127 ++++++--- microwatt.core | 1 + predecode.vhdl | 582 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 745 insertions(+), 673 deletions(-) create mode 100644 predecode.vhdl diff --git a/Makefile b/Makefile index 85a0fee..ebb1b79 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ all = core_tb icache_tb dcache_tb dmi_dtm_tb \ all: $(all) core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ - utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl \ + utils.vhdl plru.vhdl cache_ram.vhdl icache.vhdl predecode.vhdl \ decode1.vhdl helpers.vhdl insn_helpers.vhdl \ control.vhdl decode2.vhdl register_file.vhdl \ cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \ diff --git a/cache_ram.vhdl b/cache_ram.vhdl index 8c8c495..641917f 100644 --- a/cache_ram.vhdl +++ b/cache_ram.vhdl @@ -7,6 +7,7 @@ entity cache_ram is generic( ROW_BITS : integer := 16; WIDTH : integer := 64; + BYTEWID : integer := 8; TRACE : boolean := false; ADD_BUF : boolean := false ); @@ -16,7 +17,7 @@ entity cache_ram is rd_en : in std_logic; rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0); rd_data : out std_logic_vector(WIDTH - 1 downto 0); - wr_sel : in std_logic_vector(WIDTH/8 - 1 downto 0); + wr_sel : in std_logic_vector(WIDTH/BYTEWID - 1 downto 0); wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0); wr_data : in std_logic_vector(WIDTH - 1 downto 0) ); @@ -38,7 +39,7 @@ begin variable lbit : integer range 0 to WIDTH - 1; variable mbit : integer range 0 to WIDTH - 1; variable widx : integer range 0 to SIZE - 1; - constant sel0 : std_logic_vector(WIDTH/8 - 1 downto 0) + constant sel0 : std_logic_vector(WIDTH/BYTEWID - 1 downto 0) := (others => '0'); begin if rising_edge(clk) then @@ -49,9 +50,9 @@ begin " dat:" & to_hstring(wr_data); end if; end if; - for i in 0 to WIDTH/8-1 loop - lbit := i * 8; - mbit := lbit + 7; + for i in 0 to WIDTH/BYTEWID-1 loop + lbit := i * BYTEWID; + mbit := lbit + BYTEWID - 1; widx := to_integer(unsigned(wr_addr)); if wr_sel(i) = '1' then ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit); diff --git a/common.vhdl b/common.vhdl index a698ba9..6287be5 100644 --- a/common.vhdl +++ b/common.vhdl @@ -246,12 +246,13 @@ package common is fetch_failed: std_ulogic; nia: std_ulogic_vector(63 downto 0); insn: std_ulogic_vector(31 downto 0); + icode: insn_code; big_endian: std_ulogic; next_predicted: std_ulogic; next_pred_ntaken: std_ulogic; end record; constant IcacheToDecode1Init : IcacheToDecode1Type := - (nia => (others => '0'), insn => (others => '0'), others => '0'); + (nia => (others => '0'), insn => (others => '0'), icode => INSN_illegal, others => '0'); type IcacheEventType is record icache_miss : std_ulogic; diff --git a/core.vhdl b/core.vhdl index 764141a..0624000 100644 --- a/core.vhdl +++ b/core.vhdl @@ -246,6 +246,7 @@ begin icache_0: entity work.icache generic map( SIM => SIM, + HAS_FPU => HAS_FPU, LINE_SIZE => 64, NUM_LINES => ICACHE_NUM_LINES, NUM_WAYS => ICACHE_NUM_WAYS, diff --git a/decode1.vhdl b/decode1.vhdl index d017912..559a505 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -31,22 +31,6 @@ entity decode1 is end entity decode1; architecture behaviour of decode1 is - type dc0_t is record - f_in : IcacheToDecode1Type; - use_row : std_ulogic; - br_pred : std_ulogic; - override : std_ulogic; - ov_insn : insn_code; - spr_info : spr_id; - ram_spr : ram_spr_info; - end record; - constant dc0_t_init : dc0_t := - (f_in => IcacheToDecode1Init, ov_insn => INSN_illegal, - spr_info => spr_id_init, ram_spr => ram_spr_info_init, - others => '0'); - - signal dc0, dc0in : dc0_t; - signal r, rin : Decode1ToDecode2Type; signal f, fin : Decode1ToFetch1Type; @@ -58,437 +42,10 @@ architecture behaviour of decode1 is signal br, br_in : br_predictor_t; - signal maj_rom_addr : std_ulogic_vector(10 downto 0); - signal row_rom_addr : std_ulogic_vector(10 downto 0); - signal major_predecode : insn_code; - signal row_predecode : insn_code; - signal decode_rom_addr : insn_code; signal decode : decode_rom_t; - signal rom_ce : std_ulogic; - - type predecoder_rom_t is array(0 to 2047) of insn_code; - - constant major_predecode_rom : predecoder_rom_t := ( - 2#001100_00000# to 2#001100_11111# => INSN_addic, - 2#001101_00000# to 2#001101_11111# => INSN_addic_dot, - 2#001110_00000# to 2#001110_11111# => INSN_addi, - 2#001111_00000# to 2#001111_11111# => INSN_addis, - 2#010011_00100# to 2#010011_00101# => INSN_addpcis, - 2#011100_00000# to 2#011100_11111# => INSN_andi_dot, - 2#011101_00000# to 2#011101_11111# => INSN_andis_dot, - 2#000000_00000# => INSN_attn, - 2#010010_00000# to 2#010010_11111# => INSN_b, - 2#010000_00000# to 2#010000_11111# => INSN_bc, - 2#001011_00000# to 2#001011_11111# => INSN_cmpi, - 2#001010_00000# to 2#001010_11111# => INSN_cmpli, - 2#100010_00000# to 2#100010_11111# => INSN_lbz, - 2#100011_00000# to 2#100011_11111# => INSN_lbzu, - 2#110010_00000# to 2#110010_11111# => INSN_lfd, - 2#110011_00000# to 2#110011_11111# => INSN_lfdu, - 2#110000_00000# to 2#110000_11111# => INSN_lfs, - 2#110001_00000# to 2#110001_11111# => INSN_lfsu, - 2#101010_00000# to 2#101010_11111# => INSN_lha, - 2#101011_00000# to 2#101011_11111# => INSN_lhau, - 2#101000_00000# to 2#101000_11111# => INSN_lhz, - 2#101001_00000# to 2#101001_11111# => INSN_lhzu, - 2#100000_00000# to 2#100000_11111# => INSN_lwz, - 2#100001_00000# to 2#100001_11111# => INSN_lwzu, - 2#000111_00000# to 2#000111_11111# => INSN_mulli, - 2#011000_00000# to 2#011000_11111# => INSN_ori, - 2#011001_00000# to 2#011001_11111# => INSN_oris, - 2#010100_00000# to 2#010100_11111# => INSN_rlwimi, - 2#010101_00000# to 2#010101_11111# => INSN_rlwinm, - 2#010111_00000# to 2#010111_11111# => INSN_rlwnm, - 2#010001_00000# to 2#010001_11111# => INSN_sc, - 2#100110_00000# to 2#100110_11111# => INSN_stb, - 2#100111_00000# to 2#100111_11111# => INSN_stbu, - 2#110110_00000# to 2#110110_11111# => INSN_stfd, - 2#110111_00000# to 2#110111_11111# => INSN_stfdu, - 2#110100_00000# to 2#110100_11111# => INSN_stfs, - 2#110101_00000# to 2#110101_11111# => INSN_stfsu, - 2#101100_00000# to 2#101100_11111# => INSN_sth, - 2#101101_00000# to 2#101101_11111# => INSN_sthu, - 2#100100_00000# to 2#100100_11111# => INSN_stw, - 2#100101_00000# to 2#100101_11111# => INSN_stwu, - 2#001000_00000# to 2#001000_11111# => INSN_subfic, - 2#000010_00000# to 2#000010_11111# => INSN_tdi, - 2#000011_00000# to 2#000011_11111# => INSN_twi, - 2#011010_00000# to 2#011010_11111# => INSN_xori, - 2#011011_00000# to 2#011011_11111# => INSN_xoris, - -- major opcode 4 - 2#000100_10000# => INSN_maddhd, - 2#000100_10001# => INSN_maddhdu, - 2#000100_10011# => INSN_maddld, - -- major opcode 30 - 2#011110_01000# to 2#011110_01001# => INSN_rldic, - 2#011110_01010# to 2#011110_01011# => INSN_rldic, - 2#011110_00000# to 2#011110_00001# => INSN_rldicl, - 2#011110_00010# to 2#011110_00011# => INSN_rldicl, - 2#011110_00100# to 2#011110_00101# => INSN_rldicr, - 2#011110_00110# to 2#011110_00111# => INSN_rldicr, - 2#011110_01100# to 2#011110_01101# => INSN_rldimi, - 2#011110_01110# to 2#011110_01111# => INSN_rldimi, - 2#011110_10000# to 2#011110_10001# => INSN_rldcl, - 2#011110_10010# to 2#011110_10011# => INSN_rldcr, - -- major opcode 58 - 2#111010_00000# => INSN_ld, - 2#111010_00001# => INSN_ldu, - 2#111010_00010# => INSN_lwa, - 2#111010_00100# => INSN_ld, - 2#111010_00101# => INSN_ldu, - 2#111010_00110# => INSN_lwa, - 2#111010_01000# => INSN_ld, - 2#111010_01001# => INSN_ldu, - 2#111010_01010# => INSN_lwa, - 2#111010_01100# => INSN_ld, - 2#111010_01101# => INSN_ldu, - 2#111010_01110# => INSN_lwa, - 2#111010_10000# => INSN_ld, - 2#111010_10001# => INSN_ldu, - 2#111010_10010# => INSN_lwa, - 2#111010_10100# => INSN_ld, - 2#111010_10101# => INSN_ldu, - 2#111010_10110# => INSN_lwa, - 2#111010_11000# => INSN_ld, - 2#111010_11001# => INSN_ldu, - 2#111010_11010# => INSN_lwa, - 2#111010_11100# => INSN_ld, - 2#111010_11101# => INSN_ldu, - 2#111010_11110# => INSN_lwa, - -- major opcode 59 - 2#111011_00100# to 2#111011_00101# => INSN_fdivs, - 2#111011_01000# to 2#111011_01001# => INSN_fsubs, - 2#111011_01010# to 2#111011_01011# => INSN_fadds, - 2#111011_01100# to 2#111011_01101# => INSN_fsqrts, - 2#111011_10000# to 2#111011_10001# => INSN_fres, - 2#111011_10010# to 2#111011_10011# => INSN_fmuls, - 2#111011_10100# to 2#111011_10101# => INSN_frsqrtes, - 2#111011_11000# to 2#111011_11001# => INSN_fmsubs, - 2#111011_11010# to 2#111011_11011# => INSN_fmadds, - 2#111011_11100# to 2#111011_11101# => INSN_fnmsubs, - 2#111011_11110# to 2#111011_11111# => INSN_fnmadds, - -- major opcode 62 - 2#111110_00000# => INSN_std, - 2#111110_00001# => INSN_stdu, - 2#111110_00100# => INSN_std, - 2#111110_00101# => INSN_stdu, - 2#111110_01000# => INSN_std, - 2#111110_01001# => INSN_stdu, - 2#111110_01100# => INSN_std, - 2#111110_01101# => INSN_stdu, - 2#111110_10000# => INSN_std, - 2#111110_10001# => INSN_stdu, - 2#111110_10100# => INSN_std, - 2#111110_10101# => INSN_stdu, - 2#111110_11000# => INSN_std, - 2#111110_11001# => INSN_stdu, - 2#111110_11100# => INSN_std, - 2#111110_11101# => INSN_stdu, - -- major opcode 63 - 2#111111_00100# to 2#111111_00101# => INSN_fdiv, - 2#111111_01000# to 2#111111_01001# => INSN_fsub, - 2#111111_01010# to 2#111111_01011# => INSN_fadd, - 2#111111_01100# to 2#111111_01101# => INSN_fsqrt, - 2#111111_01110# to 2#111111_01111# => INSN_fsel, - 2#111111_10000# to 2#111111_10001# => INSN_fre, - 2#111111_10010# to 2#111111_10011# => INSN_fmul, - 2#111111_10100# to 2#111111_10101# => INSN_frsqrte, - 2#111111_11000# to 2#111111_11001# => INSN_fmsub, - 2#111111_11010# to 2#111111_11011# => INSN_fmadd, - 2#111111_11100# to 2#111111_11101# => INSN_fnmsub, - 2#111111_11110# to 2#111111_11111# => INSN_fnmadd, - others => INSN_illegal - ); - constant row_predecode_rom : predecoder_rom_t := ( - -- Major opcode 31 - -- Address bits are 0, insn(10:1) - 2#0_01000_01010# => INSN_add, - 2#0_11000_01010# => INSN_add, -- addo - 2#0_00000_01010# => INSN_addc, - 2#0_10000_01010# => INSN_addc, -- addco - 2#0_00100_01010# => INSN_adde, - 2#0_10100_01010# => INSN_adde, -- addeo - 2#0_00101_01010# => INSN_addex, - 2#0_00010_01010# => INSN_addg6s, - 2#0_00111_01010# => INSN_addme, - 2#0_10111_01010# => INSN_addme, -- addmeo - 2#0_00110_01010# => INSN_addze, - 2#0_10110_01010# => INSN_addze, -- addzeo - 2#0_00000_11100# => INSN_and, - 2#0_00001_11100# => INSN_andc, - 2#0_00111_11100# => INSN_bperm, - 2#0_01001_11010# => INSN_cbcdtd, - 2#0_01000_11010# => INSN_cdtbcd, - 2#0_00000_00000# => INSN_cmp, - 2#0_01111_11100# => INSN_cmpb, - 2#0_00111_00000# => INSN_cmpeqb, - 2#0_00001_00000# => INSN_cmpl, - 2#0_00110_00000# => INSN_cmprb, - 2#0_00001_11010# => INSN_cntlzd, - 2#0_00000_11010# => INSN_cntlzw, - 2#0_10001_11010# => INSN_cnttzd, - 2#0_10000_11010# => INSN_cnttzw, - 2#0_10111_10011# => INSN_darn, - 2#0_00010_10110# => INSN_dcbf, - 2#0_00001_10110# => INSN_dcbst, - 2#0_01000_10110# => INSN_dcbt, - 2#0_00111_10110# => INSN_dcbtst, - 2#0_11111_10110# => INSN_dcbz, - 2#0_01100_01001# => INSN_divdeu, - 2#0_11100_01001# => INSN_divdeu, -- divdeuo - 2#0_01100_01011# => INSN_divweu, - 2#0_11100_01011# => INSN_divweu, -- divweuo - 2#0_01101_01001# => INSN_divde, - 2#0_11101_01001# => INSN_divde, -- divdeo - 2#0_01101_01011# => INSN_divwe, - 2#0_11101_01011# => INSN_divwe, -- divweo - 2#0_01110_01001# => INSN_divdu, - 2#0_11110_01001# => INSN_divdu, -- divduo - 2#0_01110_01011# => INSN_divwu, - 2#0_11110_01011# => INSN_divwu, -- divwuo - 2#0_01111_01001# => INSN_divd, - 2#0_11111_01001# => INSN_divd, -- divdo - 2#0_01111_01011# => INSN_divw, - 2#0_11111_01011# => INSN_divw, -- divwo - 2#0_11001_10110# => INSN_nop, -- dss - 2#0_01010_10110# => INSN_nop, -- dst - 2#0_01011_10110# => INSN_nop, -- dstst - 2#0_11010_10110# => INSN_eieio, - 2#0_01000_11100# => INSN_eqv, - 2#0_11101_11010# => INSN_extsb, - 2#0_11100_11010# => INSN_extsh, - 2#0_11110_11010# => INSN_extsw, - 2#0_11011_11010# => INSN_extswsli, - 2#0_11011_11011# => INSN_extswsli, - 2#0_11110_10110# => INSN_icbi, - 2#0_00000_10110# => INSN_icbt, - 2#0_00000_01111# => INSN_isel, - 2#0_00001_01111# => INSN_isel, - 2#0_00010_01111# => INSN_isel, - 2#0_00011_01111# => INSN_isel, - 2#0_00100_01111# => INSN_isel, - 2#0_00101_01111# => INSN_isel, - 2#0_00110_01111# => INSN_isel, - 2#0_00111_01111# => INSN_isel, - 2#0_01000_01111# => INSN_isel, - 2#0_01001_01111# => INSN_isel, - 2#0_01010_01111# => INSN_isel, - 2#0_01011_01111# => INSN_isel, - 2#0_01100_01111# => INSN_isel, - 2#0_01101_01111# => INSN_isel, - 2#0_01110_01111# => INSN_isel, - 2#0_01111_01111# => INSN_isel, - 2#0_10000_01111# => INSN_isel, - 2#0_10001_01111# => INSN_isel, - 2#0_10010_01111# => INSN_isel, - 2#0_10011_01111# => INSN_isel, - 2#0_10100_01111# => INSN_isel, - 2#0_10101_01111# => INSN_isel, - 2#0_10110_01111# => INSN_isel, - 2#0_10111_01111# => INSN_isel, - 2#0_11000_01111# => INSN_isel, - 2#0_11001_01111# => INSN_isel, - 2#0_11010_01111# => INSN_isel, - 2#0_11011_01111# => INSN_isel, - 2#0_11100_01111# => INSN_isel, - 2#0_11101_01111# => INSN_isel, - 2#0_11110_01111# => INSN_isel, - 2#0_11111_01111# => INSN_isel, - 2#0_00001_10100# => INSN_lbarx, - 2#0_11010_10101# => INSN_lbzcix, - 2#0_00011_10111# => INSN_lbzux, - 2#0_00010_10111# => INSN_lbzx, - 2#0_00010_10100# => INSN_ldarx, - 2#0_10000_10100# => INSN_ldbrx, - 2#0_11011_10101# => INSN_ldcix, - 2#0_00001_10101# => INSN_ldux, - 2#0_00000_10101# => INSN_ldx, - 2#0_10010_10111# => INSN_lfdx, - 2#0_10011_10111# => INSN_lfdux, - 2#0_11010_10111# => INSN_lfiwax, - 2#0_11011_10111# => INSN_lfiwzx, - 2#0_10000_10111# => INSN_lfsx, - 2#0_10001_10111# => INSN_lfsux, - 2#0_00011_10100# => INSN_lharx, - 2#0_01011_10111# => INSN_lhaux, - 2#0_01010_10111# => INSN_lhax, - 2#0_11000_10110# => INSN_lhbrx, - 2#0_11001_10101# => INSN_lhzcix, - 2#0_01001_10111# => INSN_lhzux, - 2#0_01000_10111# => INSN_lhzx, - 2#0_00000_10100# => INSN_lwarx, - 2#0_01011_10101# => INSN_lwaux, - 2#0_01010_10101# => INSN_lwax, - 2#0_10000_10110# => INSN_lwbrx, - 2#0_11000_10101# => INSN_lwzcix, - 2#0_00001_10111# => INSN_lwzux, - 2#0_00000_10111# => INSN_lwzx, - 2#0_10010_00000# => INSN_mcrxrx, - 2#0_00000_10011# => INSN_mfcr, - 2#0_00010_10011# => INSN_mfmsr, - 2#0_01010_10011# => INSN_mfspr, - 2#0_01000_01001# => INSN_modud, - 2#0_01000_01011# => INSN_moduw, - 2#0_11000_01001# => INSN_modsd, - 2#0_11000_01011# => INSN_modsw, - 2#0_00100_10000# => INSN_mtcrf, - 2#0_00100_10010# => INSN_mtmsr, - 2#0_00101_10010# => INSN_mtmsrd, - 2#0_01110_10011# => INSN_mtspr, - 2#0_00010_01001# => INSN_mulhd, - 2#0_00000_01001# => INSN_mulhdu, - 2#0_00010_01011# => INSN_mulhw, - 2#0_00000_01011# => INSN_mulhwu, - -- next 4 have reserved bit set - 2#0_10010_01001# => INSN_mulhd, - 2#0_10000_01001# => INSN_mulhdu, - 2#0_10010_01011# => INSN_mulhw, - 2#0_10000_01011# => INSN_mulhwu, - 2#0_00111_01001# => INSN_mulld, - 2#0_10111_01001# => INSN_mulld, -- mulldo - 2#0_00111_01011# => INSN_mullw, - 2#0_10111_01011# => INSN_mullw, -- mullwo - 2#0_01110_11100# => INSN_nand, - 2#0_00011_01000# => INSN_neg, - 2#0_10011_01000# => INSN_neg, -- nego - -- next 8 are reserved no-op instructions - 2#0_10000_10010# => INSN_nop, - 2#0_10001_10010# => INSN_nop, - 2#0_10010_10010# => INSN_nop, - 2#0_10011_10010# => INSN_nop, - 2#0_10100_10010# => INSN_nop, - 2#0_10101_10010# => INSN_nop, - 2#0_10110_10010# => INSN_nop, - 2#0_10111_10010# => INSN_nop, - 2#0_00011_11100# => INSN_nor, - 2#0_01101_11100# => INSN_or, - 2#0_01100_11100# => INSN_orc, - 2#0_00011_11010# => INSN_popcntb, - 2#0_01111_11010# => INSN_popcntd, - 2#0_01011_11010# => INSN_popcntw, - 2#0_00101_11010# => INSN_prtyd, - 2#0_00100_11010# => INSN_prtyw, - 2#0_00100_00000# => INSN_setb, - 2#0_01111_10010# => INSN_slbia, - 2#0_00000_11011# => INSN_sld, - 2#0_00000_11000# => INSN_slw, - 2#0_11000_11010# => INSN_srad, - 2#0_11001_11010# => INSN_sradi, - 2#0_11001_11011# => INSN_sradi, - 2#0_11000_11000# => INSN_sraw, - 2#0_11001_11000# => INSN_srawi, - 2#0_10000_11011# => INSN_srd, - 2#0_10000_11000# => INSN_srw, - 2#0_11110_10101# => INSN_stbcix, - 2#0_10101_10110# => INSN_stbcx, - 2#0_00111_10111# => INSN_stbux, - 2#0_00110_10111# => INSN_stbx, - 2#0_10100_10100# => INSN_stdbrx, - 2#0_11111_10101# => INSN_stdcix, - 2#0_00110_10110# => INSN_stdcx, - 2#0_00101_10101# => INSN_stdux, - 2#0_00100_10101# => INSN_stdx, - 2#0_10110_10111# => INSN_stfdx, - 2#0_10111_10111# => INSN_stfdux, - 2#0_11110_10111# => INSN_stfiwx, - 2#0_10100_10111# => INSN_stfsx, - 2#0_10101_10111# => INSN_stfsux, - 2#0_11100_10110# => INSN_sthbrx, - 2#0_11101_10101# => INSN_sthcix, - 2#0_10110_10110# => INSN_sthcx, - 2#0_01101_10111# => INSN_sthux, - 2#0_01100_10111# => INSN_sthx, - 2#0_10100_10110# => INSN_stwbrx, - 2#0_11100_10101# => INSN_stwcix, - 2#0_00100_10110# => INSN_stwcx, - 2#0_00101_10111# => INSN_stwux, - 2#0_00100_10111# => INSN_stwx, - 2#0_00001_01000# => INSN_subf, - 2#0_10001_01000# => INSN_subf, -- subfo - 2#0_00000_01000# => INSN_subfc, - 2#0_10000_01000# => INSN_subfc, -- subfco - 2#0_00100_01000# => INSN_subfe, - 2#0_10100_01000# => INSN_subfe, -- subfeo - 2#0_00111_01000# => INSN_subfme, - 2#0_10111_01000# => INSN_subfme, -- subfmeo - 2#0_00110_01000# => INSN_subfze, - 2#0_10110_01000# => INSN_subfze, -- subfzeo - 2#0_10010_10110# => INSN_sync, - 2#0_00010_00100# => INSN_td, - 2#0_00000_00100# => INSN_tw, - 2#0_01001_10010# => INSN_tlbie, - 2#0_01000_10010# => INSN_tlbiel, - 2#0_10001_10110# => INSN_tlbsync, - 2#0_00000_11110# => INSN_wait, - 2#0_01001_11100# => INSN_xor, - - -- Major opcode 19 - -- Columns with insn(4) = '1' are all illegal and not mapped here; to - -- fit into 2048 entries, the columns are remapped so that 16-24 are - -- stored here as 8-15; in other words the address bits are - -- 1, insn(10..6), 1, insn(5), insn(3..1) - 2#1_10000_11000# => INSN_bcctr, - 2#1_00000_11000# => INSN_bclr, - 2#1_10001_11000# => INSN_bctar, - 2#1_01000_10001# => INSN_crand, - 2#1_00100_10001# => INSN_crandc, - 2#1_01001_10001# => INSN_creqv, - 2#1_00111_10001# => INSN_crnand, - 2#1_00001_10001# => INSN_crnor, - 2#1_01110_10001# => INSN_cror, - 2#1_01101_10001# => INSN_crorc, - 2#1_00110_10001# => INSN_crxor, - 2#1_00100_11110# => INSN_isync, - 2#1_00000_10000# => INSN_mcrf, - 2#1_00000_11010# => INSN_rfid, - - -- Major opcode 59 - -- Only column 14 is valid here; columns 16-31 are handled in the major table - -- Column 14 is mapped to column 6 of the space which is - -- mostly used for opcode 19. - 2#1_11010_10110# => INSN_fcfids, - 2#1_11110_10110# => INSN_fcfidus, - - -- Major opcode 63 - -- Columns 0-15 are mapped here; columns 16-31 are in the major table. - -- Address bits are 1, insn(10:6), 0, insn(4:1) - 2#1_00000_00000# => INSN_fcmpu, - 2#1_00001_00000# => INSN_fcmpo, - 2#1_00010_00000# => INSN_mcrfs, - 2#1_00100_00000# => INSN_ftdiv, - 2#1_00101_00000# => INSN_ftsqrt, - 2#1_00001_00110# => INSN_mtfsb, - 2#1_00010_00110# => INSN_mtfsb, - 2#1_00100_00110# => INSN_mtfsfi, - 2#1_11010_00110# => INSN_fmrgow, - 2#1_11110_00110# => INSN_fmrgew, - 2#1_10010_00111# => INSN_mffs, - 2#1_10110_00111# => INSN_mtfsf, - 2#1_00000_01000# => INSN_fcpsgn, - 2#1_00001_01000# => INSN_fneg, - 2#1_00010_01000# => INSN_fmr, - 2#1_00100_01000# => INSN_fnabs, - 2#1_01000_01000# => INSN_fabs, - 2#1_01100_01000# => INSN_frin, - 2#1_01101_01000# => INSN_friz, - 2#1_01110_01000# => INSN_frip, - 2#1_01111_01000# => INSN_frim, - 2#1_00000_01100# => INSN_frsp, - 2#1_00000_01110# => INSN_fctiw, - 2#1_00100_01110# => INSN_fctiwu, - 2#1_11001_01110# => INSN_fctid, - 2#1_11010_01110# => INSN_fcfid, - 2#1_11101_01110# => INSN_fctidu, - 2#1_11110_01110# => INSN_fcfidu, - 2#1_00000_01111# => INSN_fctiwz, - 2#1_00100_01111# => INSN_fctiwuz, - 2#1_11001_01111# => INSN_fctidz, - 2#1_11101_01111# => INSN_fctiduz, - - others => INSN_illegal - ); + signal fetch_failed : std_ulogic; -- If we have an FPU, then it is used for integer divisions, -- otherwise a dedicated divider in the ALU is used. @@ -871,16 +428,18 @@ architecture behaviour of decode1 is end; begin - decode0_0: process(clk) + decode1_0: process(clk) begin if rising_edge(clk) then if rst = '1' then - dc0 <= dc0_t_init; + r <= Decode1ToDecode2Init; + fetch_failed <= '0'; elsif flush_in = '1' then - dc0.f_in.valid <= '0'; - dc0.f_in.fetch_failed <= '0'; + r.valid <= '0'; + fetch_failed <= '0'; elsif stall_in = '0' then - dc0 <= dc0in; + r <= rin; + fetch_failed <= f_in.fetch_failed; end if; if rst = '1' then br.br_nia <= (others => '0'); @@ -892,139 +451,73 @@ begin end if; end process; - decode0_roms: process(clk) + busy_out <= stall_in; + + decode1_rom: process(clk) begin if rising_edge(clk) then if stall_in = '0' then - if is_X(maj_rom_addr) then - major_predecode <= INSN_illegal; - else - major_predecode <= major_predecode_rom(to_integer(unsigned(maj_rom_addr))); - end if; - if is_X(row_rom_addr) then - row_predecode <= INSN_illegal; - else - row_predecode <= row_predecode_rom(to_integer(unsigned(row_rom_addr))); - end if; + decode <= decode_rom(decode_rom_addr); end if; end if; end process; - decode0_1: process(all) - variable v : dc0_t; - variable majorop : std_ulogic_vector(5 downto 0); - variable majaddr : std_ulogic_vector(10 downto 0); - variable rowaddr : std_ulogic_vector(10 downto 0); - variable sprn : spr_num_t; + decode1_1: process(all) + variable v : Decode1ToDecode2Type; + variable vr : Decode1ToRegisterFileType; variable br_target : std_ulogic_vector(61 downto 0); variable br_offset : signed(23 downto 0); variable bv : br_predictor_t; + variable icode : insn_code; + variable sprn : spr_num_t; + variable maybe_rb : std_ulogic; begin - v := dc0_t_init; - v.f_in := f_in; - - br_offset := (others => '0'); - - majorop := f_in.insn(31 downto 26); - majaddr := majorop & f_in.insn(4 downto 0); - - -- row_predecode_rom is used for op 19, 31, 59, 63 - -- addr bit 10 is 0 for op 31, 1 for 19, 59, 63 - rowaddr(10) := f_in.insn(31) or not f_in.insn(29); - rowaddr(9 downto 5) := f_in.insn(10 downto 6); - if f_in.insn(28) = '0' then - -- op 19 and op 59 - rowaddr(4 downto 3) := '1' & f_in.insn(5); - else - -- op 31 and 63; for 63 we only use this when f_in.insn(5) = '0' - rowaddr(4 downto 3) := f_in.insn(5 downto 4); - end if; - rowaddr(2 downto 0) := f_in.insn(3 downto 1); + v := Decode1ToDecode2Init; - maj_rom_addr <= majaddr; - row_rom_addr <= rowaddr; + v.valid := f_in.valid; + v.nia := f_in.nia; + v.insn := f_in.insn; + v.stop_mark := f_in.stop_mark; + v.big_endian := f_in.big_endian; if is_X(f_in.insn) then v.spr_info := (sel => "XXX", others => 'X'); v.ram_spr := (index => (others => 'X'), others => 'X'); else - sprn := decode_spr_num(f_in.insn); - v.spr_info := map_spr(sprn); - v.ram_spr := decode_ram_spr(sprn); - end if; - - case unsigned(majorop) is - when "000100" => -- 4 - -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) - v.override := not f_in.insn(5); - - when "011111" => -- 31 - -- major opcode 31, lots of things - -- Use the first half of the row table for all columns - v.use_row := '1'; - - when "010000" => -- 16 - -- Predict backward branches as taken, forward as untaken - v.br_pred := f_in.insn(15); - br_offset := resize(signed(f_in.insn(15 downto 2)), 24); - - when "010010" => -- 18 - -- Unconditional branches are always taken - v.br_pred := '1'; - br_offset := signed(f_in.insn(25 downto 2)); - - when "010011" => -- 19 - -- Columns 8-15 and 24-31 don't have any valid instructions - -- (where insn(5..1) is the column number). - -- addpcis (column 2) is in the major table - -- Other valid columns are mapped to columns in the second - -- half of the row table: columns 0-1 are mapped to 16-17 - -- and 16-23 are mapped to 24-31. - v.override := f_in.insn(4); - v.use_row := f_in.insn(5) or (not f_in.insn(3) and not f_in.insn(2)); - - when "011000" => -- 24 - -- ori, special-case the standard NOP - if std_match(f_in.insn, "01100000000000000000000000000000") then - v.override := '1'; - v.ov_insn := INSN_nop; - end if; - - when "111011" => -- 59 - if HAS_FPU then - -- floating point operations, mostly single-precision - -- Columns 0-11 are illegal; columns 12-15 are mapped - -- to columns 20-23 in the second half of the row table, - -- and columns 16-31 are in the major table. - v.override := not f_in.insn(5) and (not f_in.insn(4) or not f_in.insn(3)); - v.use_row := not f_in.insn(5); - else - v.override := '1'; - end if; - - when "111111" => -- 63 - if HAS_FPU then - -- floating point operations, general and double-precision - -- Use columns 0-15 of the second half of the row table - -- for columns 0-15, and the major table for columns 16-31. - v.use_row := not f_in.insn(5); - else - v.override := '1'; - end if; + sprn := decode_spr_num(f_in.insn); + v.spr_info := map_spr(sprn); + v.ram_spr := decode_ram_spr(sprn); + end if; - when others => - end case; + icode := f_in.icode; if f_in.fetch_failed = '1' then - v.override := '1'; - v.ov_insn := INSN_fetch_fail; + icode := INSN_fetch_fail; -- Only send down a single OP_FETCH_FAILED - v.f_in.valid := not dc0.f_in.fetch_failed; + v.valid := not fetch_failed; + end if; + decode_rom_addr <= icode; + + if f_in.valid = '1' then + report "Decode " & insn_code'image(icode) & " " & to_hstring(f_in.insn) & + " at " & to_hstring(f_in.nia); end if; -- Branch predictor - -- Note bclr, bcctr and bctar are predicted not taken as we have no + -- Note bclr, bcctr and bctar not predicted as we have no -- count cache or link stack. + br_offset := (others => '0'); + case icode is + when INSN_b => + -- Unconditional branches are always taken + v.br_pred := '1'; + br_offset := signed(f_in.insn(25 downto 2)); + when INSN_bc => + -- Predict backward branches as taken, forward as untaken + v.br_pred := f_in.insn(15); + br_offset := resize(signed(f_in.insn(15 downto 2)), 24); + when others => + end case; bv.br_nia := f_in.nia(63 downto 2); if f_in.insn(1) = '1' then bv.br_nia := (others => '0'); @@ -1039,80 +532,16 @@ begin -- after a clock edge... br_target := std_ulogic_vector(signed(br.br_nia) + br.br_offset); - dc0in <= v; - br_in <= bv; - - f_out.redirect <= br.predict; - f_out.redirect_nia <= br_target & "00"; - flush_out <= bv.predict or br.predict; - end process; - - decode1_0: process(clk) - begin - if rising_edge(clk) then - if rst = '1' then - r <= Decode1ToDecode2Init; - elsif flush_in = '1' then - r.valid <= '0'; - elsif stall_in = '0' then - r <= rin; - end if; - end if; - end process; - - busy_out <= stall_in; - - decode1_rom: process(clk) - begin - if rising_edge(clk) then - if stall_in = '0' then - decode <= decode_rom(decode_rom_addr); - end if; - end if; - end process; - - decode1_1: process(all) - variable v : Decode1ToDecode2Type; - variable vr : Decode1ToRegisterFileType; - variable icode : insn_code; - variable sprn : spr_num_t; - variable maybe_rb : std_ulogic; - begin - v := Decode1ToDecode2Init; - - v.valid := dc0.f_in.valid; - v.nia := dc0.f_in.nia; - v.insn := dc0.f_in.insn; - v.stop_mark := dc0.f_in.stop_mark; - v.big_endian := dc0.f_in.big_endian; - v.br_pred := dc0.br_pred; - v.spr_info := dc0.spr_info; - v.ram_spr := dc0.ram_spr; - - if dc0.override = '1' then - icode := dc0.ov_insn; - elsif dc0.use_row = '0' then - icode := major_predecode; - else - icode := row_predecode; - end if; - decode_rom_addr <= icode; - - if dc0.f_in.valid = '1' then - report "Decode insn " & to_hstring(dc0.f_in.insn) & " at " & to_hstring(dc0.f_in.nia) & - " code " & insn_code'image(icode); - end if; - -- Work out GPR/FPR read addresses maybe_rb := '0'; - vr.reg_1_addr := '0' & insn_ra(dc0.f_in.insn); - vr.reg_2_addr := '0' & insn_rb(dc0.f_in.insn); - vr.reg_3_addr := '0' & insn_rs(dc0.f_in.insn); + vr.reg_1_addr := '0' & insn_ra(f_in.insn); + vr.reg_2_addr := '0' & insn_rb(f_in.insn); + vr.reg_3_addr := '0' & insn_rs(f_in.insn); if icode >= INSN_first_rb then maybe_rb := '1'; if icode < INSN_first_frs then if icode >= INSN_first_rc then - vr.reg_3_addr := '0' & insn_rcreg(dc0.f_in.insn); + vr.reg_3_addr := '0' & insn_rcreg(f_in.insn); end if; else -- access FRS operand @@ -1124,13 +553,13 @@ begin end if; if icode >= INSN_first_frabc then -- access FRC operand - vr.reg_3_addr := '1' & insn_rcreg(dc0.f_in.insn); + vr.reg_3_addr := '1' & insn_rcreg(f_in.insn); end if; end if; end if; - vr.read_1_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; - vr.read_2_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed and maybe_rb; - vr.read_3_enable := dc0.f_in.valid and not dc0.f_in.fetch_failed; + vr.read_1_enable := f_in.valid; + vr.read_2_enable := f_in.valid and maybe_rb; + vr.read_3_enable := f_in.valid; v.reg_a := vr.reg_1_addr; v.reg_b := vr.reg_2_addr; @@ -1138,11 +567,15 @@ begin -- Update registers rin <= v; + br_in <= bv; -- Update outputs d_out <= r; d_out.decode <= decode; r_out <= vr; + f_out.redirect <= br.predict; + f_out.redirect_nia <= br_target & "00"; + flush_out <= bv.predict or br.predict; end process; d1_log: if LOG_LENGTH > 0 generate diff --git a/icache.vhdl b/icache.vhdl index 9eb08c1..63de229 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -23,6 +23,7 @@ use ieee.numeric_std.all; library work; use work.utils.all; use work.common.all; +use work.decode_types.all; use work.wishbone_types.all; -- 64 bit direct mapped icache. All instructions are 4B aligned. @@ -30,6 +31,7 @@ use work.wishbone_types.all; entity icache is generic ( SIM : boolean := false; + HAS_FPU : boolean := true; -- Line size in bytes LINE_SIZE : positive := 64; -- BRAM organisation: We never access more than wishbone_data_bits at @@ -122,8 +124,20 @@ architecture rtl of icache is subtype way_t is integer range 0 to NUM_WAYS-1; subtype row_in_line_t is unsigned(ROW_LINEBITS-1 downto 0); + -- We store a pre-decoded 10-bit insn_code along with the bottom 26 bits of + -- each instruction, giving a total of 36 bits per instruction, which + -- fits neatly into the block RAMs available on FPGAs. + -- For illegal instructions, the top 4 bits are ones and the bottom 6 bits + -- are the instruction's primary opcode, so we have the whole instruction + -- word available (e.g. to put in HEIR). For other instructions, the + -- primary opcode is not stored but could be determined from the insn_code. + constant PREDECODE_BITS : natural := 10; + constant INSN_IMAGE_BITS : natural := 26; + constant ICWORDLEN : natural := PREDECODE_BITS + INSN_IMAGE_BITS; + constant ROW_WIDTH : natural := INSN_PER_ROW * ICWORDLEN; + -- The cache data BRAM organized as described above for each way - subtype cache_row_t is std_ulogic_vector(ROW_SIZE_BITS-1 downto 0); + subtype cache_row_t is std_ulogic_vector(ROW_WIDTH-1 downto 0); -- The cache tags LUTRAM has a row per set. Vivado is a pain and will -- not handle a clean (commented) definition of the cache tags as a 3d @@ -184,6 +198,8 @@ architecture rtl of icache is wb : wishbone_master_out; store_way : way_t; store_index : index_t; + recv_row : row_t; + recv_valid : std_ulogic; store_row : row_t; store_tag : cache_tag_t; store_valid : std_ulogic; @@ -214,7 +230,9 @@ architecture rtl of icache is -- Cache RAM interface type cache_ram_out_t is array(way_t) of cache_row_t; - signal cache_out : cache_ram_out_t; + signal cache_out : cache_ram_out_t; + signal cache_wr_data : std_ulogic_vector(ROW_WIDTH - 1 downto 0); + signal wb_rd_data : std_ulogic_vector(ROW_SIZE_BITS - 1 downto 0); -- PLRU output interface type plru_out_t is array(index_t) of std_ulogic_vector(WAY_BITS-1 downto 0); @@ -293,7 +311,7 @@ architecture rtl of icache is variable word: integer range 0 to INSN_PER_ROW-1; begin word := to_integer(unsigned(addr(INSN_BITS+2-1 downto 2))); - return data(31+word*32 downto word*32); + return data(word * ICWORDLEN + ICWORDLEN - 1 downto word * ICWORDLEN); end; -- Get the tag value from the address @@ -327,6 +345,34 @@ architecture rtl of icache is begin + -- byte-swap read data if big endian + process(all) + variable j: integer; + begin + if r.store_tag(TAG_BITS - 1) = '0' then + wb_rd_data <= wishbone_in.dat; + else + for ii in 0 to (wishbone_in.dat'length / 8) - 1 loop + j := ((ii / 4) * 4) + (3 - (ii mod 4)); + wb_rd_data(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8); + end loop; + end if; + end process; + + predecoder_0: entity work.predecoder + generic map ( + HAS_FPU => HAS_FPU, + WIDTH => INSN_PER_ROW, + ICODE_LEN => PREDECODE_BITS, + IMAGE_LEN => INSN_IMAGE_BITS + ) + port map ( + clk => clk, + valid_in => wishbone_in.ack, + insns_in => wb_rd_data, + icodes_out => cache_wr_data + ); + assert LINE_SIZE mod ROW_SIZE = 0; assert ispow2(LINE_SIZE) report "LINE_SIZE not power of 2" severity FAILURE; assert ispow2(NUM_LINES) report "NUM_LINES not power of 2" severity FAILURE; @@ -367,13 +413,13 @@ begin signal rd_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal wr_addr : std_ulogic_vector(ROW_BITS-1 downto 0); signal dout : cache_row_t; - signal wr_sel : std_ulogic_vector(ROW_SIZE-1 downto 0); - signal wr_dat : std_ulogic_vector(wishbone_in.dat'left downto 0); + signal wr_sel : std_ulogic_vector(0 downto 0); begin way: entity work.cache_ram generic map ( ROW_BITS => ROW_BITS, - WIDTH => ROW_SIZE_BITS + WIDTH => ROW_WIDTH, + BYTEWID => ROW_WIDTH ) port map ( clk => clk, @@ -382,31 +428,19 @@ begin rd_data => dout, wr_sel => wr_sel, wr_addr => wr_addr, - wr_data => wr_dat + wr_data => cache_wr_data ); process(all) - variable j: integer; begin - -- byte-swap read data if big endian - if r.store_tag(TAG_BITS - 1) = '0' then - wr_dat <= wishbone_in.dat; - else - for ii in 0 to (wishbone_in.dat'length / 8) - 1 loop - j := ((ii / 4) * 4) + (3 - (ii mod 4)); - wr_dat(ii * 8 + 7 downto ii * 8) <= wishbone_in.dat(j * 8 + 7 downto j * 8); - end loop; - end if; do_read <= not stall_in; do_write <= '0'; - if wishbone_in.ack = '1' and replace_way = i then + if r.recv_valid = '1' and r.store_way = i then do_write <= '1'; end if; cache_out(i) <= dout; rd_addr <= std_ulogic_vector(to_unsigned(req_row, ROW_BITS)); wr_addr <= std_ulogic_vector(to_unsigned(r.store_row, ROW_BITS)); - for ii in 0 to ROW_SIZE-1 loop - wr_sel(ii) <= do_write; - end loop; + wr_sel(0) <= do_write; end process; end generate; @@ -515,6 +549,8 @@ begin icache_comb : process(all) variable is_hit : std_ulogic; variable hit_way : way_t; + variable insn : std_ulogic_vector(ICWORDLEN - 1 downto 0); + variable icode : insn_code; begin -- Extract line, row and tag from request if not is_X(i_in.nia) then @@ -575,11 +611,18 @@ begin -- I prefer not to do just yet as it would force fetch2 to know about -- some of the cache geometry information. -- + insn := (others => '0'); + icode := INSN_illegal; if r.hit_valid = '1' then - i_out.insn <= read_insn_word(r.hit_nia, cache_out(r.hit_way)); - else - i_out.insn <= (others => '0'); + insn := read_insn_word(r.hit_nia, cache_out(r.hit_way)); + -- Currently we use only the top bit for indicating illegal + -- instructions because we know that insn_codes fit into 9 bits. + if insn(ICWORDLEN - 1) = '0' then + icode := insn_code'val(to_integer(unsigned(insn(ICWORDLEN-1 downto INSN_IMAGE_BITS)))); + end if; end if; + i_out.insn <= insn(31 downto 0); + i_out.icode <= icode; i_out.valid <= r.hit_valid; i_out.nia <= r.hit_nia; i_out.stop_mark <= r.hit_smark; @@ -640,9 +683,11 @@ begin variable snoop_addr : real_addr_t; variable snoop_tag : cache_tag_t; variable snoop_cache_tags : cache_tags_set_t; + variable replace_way : way_t; begin if rising_edge(clk) then ev.icache_miss <= '0'; + r.recv_valid <= '0'; -- On reset, clear all valid bits to force misses if rst = '1' then for i in index_t loop @@ -714,13 +759,13 @@ begin " IR:" & std_ulogic'image(i_in.virt_mode) & " SM:" & std_ulogic'image(i_in.stop_mark) & " idx:" & integer'image(req_index) & - " way:" & integer'image(replace_way) & " tag:" & to_hstring(req_tag) & " RA:" & to_hstring(real_addr); ev.icache_miss <= '1'; -- Keep track of our index and way for subsequent stores r.store_index <= req_index; + r.recv_row <= get_row(req_raddr); r.store_row <= get_row(req_raddr); r.store_tag <= req_tag; r.store_valid <= '1'; @@ -740,6 +785,7 @@ begin when CLR_TAG | WAIT_ACK => if r.state = CLR_TAG then -- Get victim way from plru + replace_way := to_integer(unsigned(plru_victim(r.store_index))); r.store_way <= replace_way; -- Force misses on that way while reloading that line @@ -757,6 +803,19 @@ begin r.state <= WAIT_ACK; end if; + -- If we are writing in this cycle, mark row valid and see if we are done + if r.recv_valid = '1' then + r.rows_valid(r.store_row mod ROW_PER_LINE) <= not inval_in; + if is_last_row(r.store_row, r.end_row_ix) then + -- Cache line is now valid + cache_valids(r.store_index)(r.store_way) <= r.store_valid and not inval_in; + -- We are done + r.state <= IDLE; + end if; + -- Increment store row counter + r.store_row <= r.recv_row; + end if; + -- If we are still sending requests, was one accepted ? if wishbone_in.stall = '0' and r.wb.stb = '1' then -- That was the last word ? We are done sending. Clear stb. @@ -777,33 +836,27 @@ begin -- Incoming acks processing if wishbone_in.ack = '1' then - r.rows_valid(r.store_row mod ROW_PER_LINE) <= not inval_in; -- Check for completion - if is_last_row(r.store_row, r.end_row_ix) then + if is_last_row(r.recv_row, r.end_row_ix) then -- Complete wishbone cycle r.wb.cyc <= '0'; - - -- Cache line is now valid - cache_valids(r.store_index)(replace_way) <= r.store_valid and not inval_in; - - -- We are done - r.state <= IDLE; end if; + r.recv_valid <= '1'; - -- Increment store row counter - r.store_row <= next_row(r.store_row); + -- Increment receive row counter + r.recv_row <= next_row(r.recv_row); end if; when STOP_RELOAD => -- Wait for all outstanding requests to be satisfied, then -- go to IDLE state. - if get_row_of_line(r.store_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then + if get_row_of_line(r.recv_row) = get_row_of_line(get_row(wb_to_addr(r.wb.adr))) then r.wb.cyc <= '0'; r.state <= IDLE; end if; if wishbone_in.ack = '1' then -- Increment store row counter - r.store_row <= next_row(r.store_row); + r.recv_row <= next_row(r.recv_row); end if; end case; end if; diff --git a/microwatt.core b/microwatt.core index 46e114e..4c8695e 100644 --- a/microwatt.core +++ b/microwatt.core @@ -9,6 +9,7 @@ filesets: - wishbone_types.vhdl - common.vhdl - fetch1.vhdl + - predecode.vhdl - decode1.vhdl - helpers.vhdl - decode2.vhdl diff --git a/predecode.vhdl b/predecode.vhdl new file mode 100644 index 0000000..1e1d85b --- /dev/null +++ b/predecode.vhdl @@ -0,0 +1,582 @@ +-- Instruction pre-decoder for microwatt +-- One cycle latency. Does 'WIDTH' instructions in parallel. + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; +use work.decode_types.all; +use work.insn_helpers.all; + +entity predecoder is + generic ( + HAS_FPU : boolean := true; + WIDTH : natural := 2; + ICODE_LEN : natural := 10; + IMAGE_LEN : natural := 26 + ); + port ( + clk : in std_ulogic; + valid_in : in std_ulogic; + insns_in : in std_ulogic_vector(WIDTH * 32 - 1 downto 0); + icodes_out : out std_ulogic_vector(WIDTH * (ICODE_LEN + IMAGE_LEN) - 1 downto 0) + ); +end entity predecoder; + +architecture behaviour of predecoder is + + type predecoder_rom_t is array(0 to 2047) of insn_code; + + constant major_predecode_rom : predecoder_rom_t := ( + 2#001100_00000# to 2#001100_11111# => INSN_addic, + 2#001101_00000# to 2#001101_11111# => INSN_addic_dot, + 2#001110_00000# to 2#001110_11111# => INSN_addi, + 2#001111_00000# to 2#001111_11111# => INSN_addis, + 2#010011_00100# to 2#010011_00101# => INSN_addpcis, + 2#011100_00000# to 2#011100_11111# => INSN_andi_dot, + 2#011101_00000# to 2#011101_11111# => INSN_andis_dot, + 2#000000_00000# => INSN_attn, + 2#010010_00000# to 2#010010_11111# => INSN_b, + 2#010000_00000# to 2#010000_11111# => INSN_bc, + 2#001011_00000# to 2#001011_11111# => INSN_cmpi, + 2#001010_00000# to 2#001010_11111# => INSN_cmpli, + 2#100010_00000# to 2#100010_11111# => INSN_lbz, + 2#100011_00000# to 2#100011_11111# => INSN_lbzu, + 2#110010_00000# to 2#110010_11111# => INSN_lfd, + 2#110011_00000# to 2#110011_11111# => INSN_lfdu, + 2#110000_00000# to 2#110000_11111# => INSN_lfs, + 2#110001_00000# to 2#110001_11111# => INSN_lfsu, + 2#101010_00000# to 2#101010_11111# => INSN_lha, + 2#101011_00000# to 2#101011_11111# => INSN_lhau, + 2#101000_00000# to 2#101000_11111# => INSN_lhz, + 2#101001_00000# to 2#101001_11111# => INSN_lhzu, + 2#100000_00000# to 2#100000_11111# => INSN_lwz, + 2#100001_00000# to 2#100001_11111# => INSN_lwzu, + 2#000111_00000# to 2#000111_11111# => INSN_mulli, + 2#011000_00000# to 2#011000_11111# => INSN_ori, + 2#011001_00000# to 2#011001_11111# => INSN_oris, + 2#010100_00000# to 2#010100_11111# => INSN_rlwimi, + 2#010101_00000# to 2#010101_11111# => INSN_rlwinm, + 2#010111_00000# to 2#010111_11111# => INSN_rlwnm, + 2#010001_00000# to 2#010001_11111# => INSN_sc, + 2#100110_00000# to 2#100110_11111# => INSN_stb, + 2#100111_00000# to 2#100111_11111# => INSN_stbu, + 2#110110_00000# to 2#110110_11111# => INSN_stfd, + 2#110111_00000# to 2#110111_11111# => INSN_stfdu, + 2#110100_00000# to 2#110100_11111# => INSN_stfs, + 2#110101_00000# to 2#110101_11111# => INSN_stfsu, + 2#101100_00000# to 2#101100_11111# => INSN_sth, + 2#101101_00000# to 2#101101_11111# => INSN_sthu, + 2#100100_00000# to 2#100100_11111# => INSN_stw, + 2#100101_00000# to 2#100101_11111# => INSN_stwu, + 2#001000_00000# to 2#001000_11111# => INSN_subfic, + 2#000010_00000# to 2#000010_11111# => INSN_tdi, + 2#000011_00000# to 2#000011_11111# => INSN_twi, + 2#011010_00000# to 2#011010_11111# => INSN_xori, + 2#011011_00000# to 2#011011_11111# => INSN_xoris, + -- major opcode 4 + 2#000100_10000# => INSN_maddhd, + 2#000100_10001# => INSN_maddhdu, + 2#000100_10011# => INSN_maddld, + -- major opcode 30 + 2#011110_01000# to 2#011110_01001# => INSN_rldic, + 2#011110_01010# to 2#011110_01011# => INSN_rldic, + 2#011110_00000# to 2#011110_00001# => INSN_rldicl, + 2#011110_00010# to 2#011110_00011# => INSN_rldicl, + 2#011110_00100# to 2#011110_00101# => INSN_rldicr, + 2#011110_00110# to 2#011110_00111# => INSN_rldicr, + 2#011110_01100# to 2#011110_01101# => INSN_rldimi, + 2#011110_01110# to 2#011110_01111# => INSN_rldimi, + 2#011110_10000# to 2#011110_10001# => INSN_rldcl, + 2#011110_10010# to 2#011110_10011# => INSN_rldcr, + -- major opcode 58 + 2#111010_00000# => INSN_ld, + 2#111010_00001# => INSN_ldu, + 2#111010_00010# => INSN_lwa, + 2#111010_00100# => INSN_ld, + 2#111010_00101# => INSN_ldu, + 2#111010_00110# => INSN_lwa, + 2#111010_01000# => INSN_ld, + 2#111010_01001# => INSN_ldu, + 2#111010_01010# => INSN_lwa, + 2#111010_01100# => INSN_ld, + 2#111010_01101# => INSN_ldu, + 2#111010_01110# => INSN_lwa, + 2#111010_10000# => INSN_ld, + 2#111010_10001# => INSN_ldu, + 2#111010_10010# => INSN_lwa, + 2#111010_10100# => INSN_ld, + 2#111010_10101# => INSN_ldu, + 2#111010_10110# => INSN_lwa, + 2#111010_11000# => INSN_ld, + 2#111010_11001# => INSN_ldu, + 2#111010_11010# => INSN_lwa, + 2#111010_11100# => INSN_ld, + 2#111010_11101# => INSN_ldu, + 2#111010_11110# => INSN_lwa, + -- major opcode 59 + 2#111011_00100# to 2#111011_00101# => INSN_fdivs, + 2#111011_01000# to 2#111011_01001# => INSN_fsubs, + 2#111011_01010# to 2#111011_01011# => INSN_fadds, + 2#111011_01100# to 2#111011_01101# => INSN_fsqrts, + 2#111011_10000# to 2#111011_10001# => INSN_fres, + 2#111011_10010# to 2#111011_10011# => INSN_fmuls, + 2#111011_10100# to 2#111011_10101# => INSN_frsqrtes, + 2#111011_11000# to 2#111011_11001# => INSN_fmsubs, + 2#111011_11010# to 2#111011_11011# => INSN_fmadds, + 2#111011_11100# to 2#111011_11101# => INSN_fnmsubs, + 2#111011_11110# to 2#111011_11111# => INSN_fnmadds, + -- major opcode 62 + 2#111110_00000# => INSN_std, + 2#111110_00001# => INSN_stdu, + 2#111110_00100# => INSN_std, + 2#111110_00101# => INSN_stdu, + 2#111110_01000# => INSN_std, + 2#111110_01001# => INSN_stdu, + 2#111110_01100# => INSN_std, + 2#111110_01101# => INSN_stdu, + 2#111110_10000# => INSN_std, + 2#111110_10001# => INSN_stdu, + 2#111110_10100# => INSN_std, + 2#111110_10101# => INSN_stdu, + 2#111110_11000# => INSN_std, + 2#111110_11001# => INSN_stdu, + 2#111110_11100# => INSN_std, + 2#111110_11101# => INSN_stdu, + -- major opcode 63 + 2#111111_00100# to 2#111111_00101# => INSN_fdiv, + 2#111111_01000# to 2#111111_01001# => INSN_fsub, + 2#111111_01010# to 2#111111_01011# => INSN_fadd, + 2#111111_01100# to 2#111111_01101# => INSN_fsqrt, + 2#111111_01110# to 2#111111_01111# => INSN_fsel, + 2#111111_10000# to 2#111111_10001# => INSN_fre, + 2#111111_10010# to 2#111111_10011# => INSN_fmul, + 2#111111_10100# to 2#111111_10101# => INSN_frsqrte, + 2#111111_11000# to 2#111111_11001# => INSN_fmsub, + 2#111111_11010# to 2#111111_11011# => INSN_fmadd, + 2#111111_11100# to 2#111111_11101# => INSN_fnmsub, + 2#111111_11110# to 2#111111_11111# => INSN_fnmadd, + others => INSN_illegal + ); + + constant row_predecode_rom : predecoder_rom_t := ( + -- Major opcode 31 + -- Address bits are 0, insn(10:1) + 2#0_01000_01010# => INSN_add, + 2#0_11000_01010# => INSN_add, -- addo + 2#0_00000_01010# => INSN_addc, + 2#0_10000_01010# => INSN_addc, -- addco + 2#0_00100_01010# => INSN_adde, + 2#0_10100_01010# => INSN_adde, -- addeo + 2#0_00101_01010# => INSN_addex, + 2#0_00010_01010# => INSN_addg6s, + 2#0_00111_01010# => INSN_addme, + 2#0_10111_01010# => INSN_addme, -- addmeo + 2#0_00110_01010# => INSN_addze, + 2#0_10110_01010# => INSN_addze, -- addzeo + 2#0_00000_11100# => INSN_and, + 2#0_00001_11100# => INSN_andc, + 2#0_00111_11100# => INSN_bperm, + 2#0_01001_11010# => INSN_cbcdtd, + 2#0_01000_11010# => INSN_cdtbcd, + 2#0_00000_00000# => INSN_cmp, + 2#0_01111_11100# => INSN_cmpb, + 2#0_00111_00000# => INSN_cmpeqb, + 2#0_00001_00000# => INSN_cmpl, + 2#0_00110_00000# => INSN_cmprb, + 2#0_00001_11010# => INSN_cntlzd, + 2#0_00000_11010# => INSN_cntlzw, + 2#0_10001_11010# => INSN_cnttzd, + 2#0_10000_11010# => INSN_cnttzw, + 2#0_10111_10011# => INSN_darn, + 2#0_00010_10110# => INSN_dcbf, + 2#0_00001_10110# => INSN_dcbst, + 2#0_01000_10110# => INSN_dcbt, + 2#0_00111_10110# => INSN_dcbtst, + 2#0_11111_10110# => INSN_dcbz, + 2#0_01100_01001# => INSN_divdeu, + 2#0_11100_01001# => INSN_divdeu, -- divdeuo + 2#0_01100_01011# => INSN_divweu, + 2#0_11100_01011# => INSN_divweu, -- divweuo + 2#0_01101_01001# => INSN_divde, + 2#0_11101_01001# => INSN_divde, -- divdeo + 2#0_01101_01011# => INSN_divwe, + 2#0_11101_01011# => INSN_divwe, -- divweo + 2#0_01110_01001# => INSN_divdu, + 2#0_11110_01001# => INSN_divdu, -- divduo + 2#0_01110_01011# => INSN_divwu, + 2#0_11110_01011# => INSN_divwu, -- divwuo + 2#0_01111_01001# => INSN_divd, + 2#0_11111_01001# => INSN_divd, -- divdo + 2#0_01111_01011# => INSN_divw, + 2#0_11111_01011# => INSN_divw, -- divwo + 2#0_11001_10110# => INSN_nop, -- dss + 2#0_01010_10110# => INSN_nop, -- dst + 2#0_01011_10110# => INSN_nop, -- dstst + 2#0_11010_10110# => INSN_eieio, + 2#0_01000_11100# => INSN_eqv, + 2#0_11101_11010# => INSN_extsb, + 2#0_11100_11010# => INSN_extsh, + 2#0_11110_11010# => INSN_extsw, + 2#0_11011_11010# => INSN_extswsli, + 2#0_11011_11011# => INSN_extswsli, + 2#0_11110_10110# => INSN_icbi, + 2#0_00000_10110# => INSN_icbt, + 2#0_00000_01111# => INSN_isel, + 2#0_00001_01111# => INSN_isel, + 2#0_00010_01111# => INSN_isel, + 2#0_00011_01111# => INSN_isel, + 2#0_00100_01111# => INSN_isel, + 2#0_00101_01111# => INSN_isel, + 2#0_00110_01111# => INSN_isel, + 2#0_00111_01111# => INSN_isel, + 2#0_01000_01111# => INSN_isel, + 2#0_01001_01111# => INSN_isel, + 2#0_01010_01111# => INSN_isel, + 2#0_01011_01111# => INSN_isel, + 2#0_01100_01111# => INSN_isel, + 2#0_01101_01111# => INSN_isel, + 2#0_01110_01111# => INSN_isel, + 2#0_01111_01111# => INSN_isel, + 2#0_10000_01111# => INSN_isel, + 2#0_10001_01111# => INSN_isel, + 2#0_10010_01111# => INSN_isel, + 2#0_10011_01111# => INSN_isel, + 2#0_10100_01111# => INSN_isel, + 2#0_10101_01111# => INSN_isel, + 2#0_10110_01111# => INSN_isel, + 2#0_10111_01111# => INSN_isel, + 2#0_11000_01111# => INSN_isel, + 2#0_11001_01111# => INSN_isel, + 2#0_11010_01111# => INSN_isel, + 2#0_11011_01111# => INSN_isel, + 2#0_11100_01111# => INSN_isel, + 2#0_11101_01111# => INSN_isel, + 2#0_11110_01111# => INSN_isel, + 2#0_11111_01111# => INSN_isel, + 2#0_00001_10100# => INSN_lbarx, + 2#0_11010_10101# => INSN_lbzcix, + 2#0_00011_10111# => INSN_lbzux, + 2#0_00010_10111# => INSN_lbzx, + 2#0_00010_10100# => INSN_ldarx, + 2#0_10000_10100# => INSN_ldbrx, + 2#0_11011_10101# => INSN_ldcix, + 2#0_00001_10101# => INSN_ldux, + 2#0_00000_10101# => INSN_ldx, + 2#0_10010_10111# => INSN_lfdx, + 2#0_10011_10111# => INSN_lfdux, + 2#0_11010_10111# => INSN_lfiwax, + 2#0_11011_10111# => INSN_lfiwzx, + 2#0_10000_10111# => INSN_lfsx, + 2#0_10001_10111# => INSN_lfsux, + 2#0_00011_10100# => INSN_lharx, + 2#0_01011_10111# => INSN_lhaux, + 2#0_01010_10111# => INSN_lhax, + 2#0_11000_10110# => INSN_lhbrx, + 2#0_11001_10101# => INSN_lhzcix, + 2#0_01001_10111# => INSN_lhzux, + 2#0_01000_10111# => INSN_lhzx, + 2#0_00000_10100# => INSN_lwarx, + 2#0_01011_10101# => INSN_lwaux, + 2#0_01010_10101# => INSN_lwax, + 2#0_10000_10110# => INSN_lwbrx, + 2#0_11000_10101# => INSN_lwzcix, + 2#0_00001_10111# => INSN_lwzux, + 2#0_00000_10111# => INSN_lwzx, + 2#0_10010_00000# => INSN_mcrxrx, + 2#0_00000_10011# => INSN_mfcr, + 2#0_00010_10011# => INSN_mfmsr, + 2#0_01010_10011# => INSN_mfspr, + 2#0_01000_01001# => INSN_modud, + 2#0_01000_01011# => INSN_moduw, + 2#0_11000_01001# => INSN_modsd, + 2#0_11000_01011# => INSN_modsw, + 2#0_00100_10000# => INSN_mtcrf, + 2#0_00100_10010# => INSN_mtmsr, + 2#0_00101_10010# => INSN_mtmsrd, + 2#0_01110_10011# => INSN_mtspr, + 2#0_00010_01001# => INSN_mulhd, + 2#0_00000_01001# => INSN_mulhdu, + 2#0_00010_01011# => INSN_mulhw, + 2#0_00000_01011# => INSN_mulhwu, + -- next 4 have reserved bit set + 2#0_10010_01001# => INSN_mulhd, + 2#0_10000_01001# => INSN_mulhdu, + 2#0_10010_01011# => INSN_mulhw, + 2#0_10000_01011# => INSN_mulhwu, + 2#0_00111_01001# => INSN_mulld, + 2#0_10111_01001# => INSN_mulld, -- mulldo + 2#0_00111_01011# => INSN_mullw, + 2#0_10111_01011# => INSN_mullw, -- mullwo + 2#0_01110_11100# => INSN_nand, + 2#0_00011_01000# => INSN_neg, + 2#0_10011_01000# => INSN_neg, -- nego + -- next 8 are reserved no-op instructions + 2#0_10000_10010# => INSN_nop, + 2#0_10001_10010# => INSN_nop, + 2#0_10010_10010# => INSN_nop, + 2#0_10011_10010# => INSN_nop, + 2#0_10100_10010# => INSN_nop, + 2#0_10101_10010# => INSN_nop, + 2#0_10110_10010# => INSN_nop, + 2#0_10111_10010# => INSN_nop, + 2#0_00011_11100# => INSN_nor, + 2#0_01101_11100# => INSN_or, + 2#0_01100_11100# => INSN_orc, + 2#0_00011_11010# => INSN_popcntb, + 2#0_01111_11010# => INSN_popcntd, + 2#0_01011_11010# => INSN_popcntw, + 2#0_00101_11010# => INSN_prtyd, + 2#0_00100_11010# => INSN_prtyw, + 2#0_00100_00000# => INSN_setb, + 2#0_01111_10010# => INSN_slbia, + 2#0_00000_11011# => INSN_sld, + 2#0_00000_11000# => INSN_slw, + 2#0_11000_11010# => INSN_srad, + 2#0_11001_11010# => INSN_sradi, + 2#0_11001_11011# => INSN_sradi, + 2#0_11000_11000# => INSN_sraw, + 2#0_11001_11000# => INSN_srawi, + 2#0_10000_11011# => INSN_srd, + 2#0_10000_11000# => INSN_srw, + 2#0_11110_10101# => INSN_stbcix, + 2#0_10101_10110# => INSN_stbcx, + 2#0_00111_10111# => INSN_stbux, + 2#0_00110_10111# => INSN_stbx, + 2#0_10100_10100# => INSN_stdbrx, + 2#0_11111_10101# => INSN_stdcix, + 2#0_00110_10110# => INSN_stdcx, + 2#0_00101_10101# => INSN_stdux, + 2#0_00100_10101# => INSN_stdx, + 2#0_10110_10111# => INSN_stfdx, + 2#0_10111_10111# => INSN_stfdux, + 2#0_11110_10111# => INSN_stfiwx, + 2#0_10100_10111# => INSN_stfsx, + 2#0_10101_10111# => INSN_stfsux, + 2#0_11100_10110# => INSN_sthbrx, + 2#0_11101_10101# => INSN_sthcix, + 2#0_10110_10110# => INSN_sthcx, + 2#0_01101_10111# => INSN_sthux, + 2#0_01100_10111# => INSN_sthx, + 2#0_10100_10110# => INSN_stwbrx, + 2#0_11100_10101# => INSN_stwcix, + 2#0_00100_10110# => INSN_stwcx, + 2#0_00101_10111# => INSN_stwux, + 2#0_00100_10111# => INSN_stwx, + 2#0_00001_01000# => INSN_subf, + 2#0_10001_01000# => INSN_subf, -- subfo + 2#0_00000_01000# => INSN_subfc, + 2#0_10000_01000# => INSN_subfc, -- subfco + 2#0_00100_01000# => INSN_subfe, + 2#0_10100_01000# => INSN_subfe, -- subfeo + 2#0_00111_01000# => INSN_subfme, + 2#0_10111_01000# => INSN_subfme, -- subfmeo + 2#0_00110_01000# => INSN_subfze, + 2#0_10110_01000# => INSN_subfze, -- subfzeo + 2#0_10010_10110# => INSN_sync, + 2#0_00010_00100# => INSN_td, + 2#0_00000_00100# => INSN_tw, + 2#0_01001_10010# => INSN_tlbie, + 2#0_01000_10010# => INSN_tlbiel, + 2#0_10001_10110# => INSN_tlbsync, + 2#0_00000_11110# => INSN_wait, + 2#0_01001_11100# => INSN_xor, + + -- Major opcode 19 + -- Columns with insn(4) = '1' are all illegal and not mapped here; to + -- fit into 2048 entries, the columns are remapped so that 16-24 are + -- stored here as 8-15; in other words the address bits are + -- 1, insn(10..6), 1, insn(5), insn(3..1) + 2#1_10000_11000# => INSN_bcctr, + 2#1_00000_11000# => INSN_bclr, + 2#1_10001_11000# => INSN_bctar, + 2#1_01000_10001# => INSN_crand, + 2#1_00100_10001# => INSN_crandc, + 2#1_01001_10001# => INSN_creqv, + 2#1_00111_10001# => INSN_crnand, + 2#1_00001_10001# => INSN_crnor, + 2#1_01110_10001# => INSN_cror, + 2#1_01101_10001# => INSN_crorc, + 2#1_00110_10001# => INSN_crxor, + 2#1_00100_11110# => INSN_isync, + 2#1_00000_10000# => INSN_mcrf, + 2#1_00000_11010# => INSN_rfid, + + -- Major opcode 59 + -- Only column 14 is valid here; columns 16-31 are handled in the major table + -- Column 14 is mapped to column 6 of the space which is + -- mostly used for opcode 19. + 2#1_11010_10110# => INSN_fcfids, + 2#1_11110_10110# => INSN_fcfidus, + + -- Major opcode 63 + -- Columns 0-15 are mapped here; columns 16-31 are in the major table. + -- Address bits are 1, insn(10:6), 0, insn(4:1) + 2#1_00000_00000# => INSN_fcmpu, + 2#1_00001_00000# => INSN_fcmpo, + 2#1_00010_00000# => INSN_mcrfs, + 2#1_00100_00000# => INSN_ftdiv, + 2#1_00101_00000# => INSN_ftsqrt, + 2#1_00001_00110# => INSN_mtfsb, + 2#1_00010_00110# => INSN_mtfsb, + 2#1_00100_00110# => INSN_mtfsfi, + 2#1_11010_00110# => INSN_fmrgow, + 2#1_11110_00110# => INSN_fmrgew, + 2#1_10010_00111# => INSN_mffs, + 2#1_10110_00111# => INSN_mtfsf, + 2#1_00000_01000# => INSN_fcpsgn, + 2#1_00001_01000# => INSN_fneg, + 2#1_00010_01000# => INSN_fmr, + 2#1_00100_01000# => INSN_fnabs, + 2#1_01000_01000# => INSN_fabs, + 2#1_01100_01000# => INSN_frin, + 2#1_01101_01000# => INSN_friz, + 2#1_01110_01000# => INSN_frip, + 2#1_01111_01000# => INSN_frim, + 2#1_00000_01100# => INSN_frsp, + 2#1_00000_01110# => INSN_fctiw, + 2#1_00100_01110# => INSN_fctiwu, + 2#1_11001_01110# => INSN_fctid, + 2#1_11010_01110# => INSN_fcfid, + 2#1_11101_01110# => INSN_fctidu, + 2#1_11110_01110# => INSN_fcfidu, + 2#1_00000_01111# => INSN_fctiwz, + 2#1_00100_01111# => INSN_fctiwuz, + 2#1_11001_01111# => INSN_fctidz, + 2#1_11101_01111# => INSN_fctiduz, + + others => INSN_illegal + ); + + constant IOUT_LEN : natural := ICODE_LEN + IMAGE_LEN; + + type predec_t is record + image : std_ulogic_vector(31 downto 0); + maj_predecode : insn_code; + row_predecode : insn_code; + end record; + + subtype index_t is integer range 0 to WIDTH-1; + type predec_array is array(index_t) of predec_t; + + signal pred : predec_array; + +begin + predecode_0: process(clk) + variable majaddr : std_ulogic_vector(10 downto 0); + variable rowaddr : std_ulogic_vector(10 downto 0); + variable iword : std_ulogic_vector(31 downto 0); + begin + if rising_edge(clk) then + for i in index_t loop + if valid_in = '1' then + iword := insns_in(i * 32 + 31 downto i * 32); + + majaddr := iword(31 downto 26) & iword(4 downto 0); + + -- row_predecode_rom is used for op 19, 31, 59, 63 + -- addr bit 10 is 0 for op 31, 1 for 19, 59, 63 + rowaddr(10) := iword(31) or not iword(29); + rowaddr(9 downto 5) := iword(10 downto 6); + if iword(28) = '0' then + -- op 19 and op 59 + rowaddr(4 downto 3) := '1' & iword(5); + else + -- op 31 and 63; for 63 we only use this when iword(5) = '0' + rowaddr(4 downto 3) := iword(5 downto 4); + end if; + rowaddr(2 downto 0) := iword(3 downto 1); + + pred(i).image <= iword; + pred(i).maj_predecode <= major_predecode_rom(to_integer(unsigned(majaddr))); + pred(i).row_predecode <= row_predecode_rom(to_integer(unsigned(rowaddr))); + else + pred(i).image <= (others => '0'); + pred(i).maj_predecode <= INSN_illegal; + pred(i).row_predecode <= INSN_illegal; + end if; + end loop; + end if; + end process; + + predecode_1: process(all) + variable iword : std_ulogic_vector(31 downto 0); + variable use_row : std_ulogic; + variable illegal : std_ulogic; + variable ici : std_ulogic_vector(IOUT_LEN - 1 downto 0); + variable icode : insn_code; + begin + for i in index_t loop + iword := pred(i).image; + icode := pred(i).maj_predecode; + use_row := '0'; + illegal := '0'; + + case iword(31 downto 26) is + when "000100" => -- 4 + -- major opcode 4, mostly VMX/VSX stuff but also some integer ops (madd*) + illegal := not iword(5); + + when "010011" => -- 19 + -- Columns 8-15 and 24-31 don't have any valid instructions + -- (where insn(5..1) is the column number). + -- addpcis (column 2) is in the major table + -- Other valid columns are mapped to columns in the second + -- half of the row table: columns 0-1 are mapped to 16-17 + -- and 16-23 are mapped to 24-31. + illegal := iword(4); + use_row := iword(5) or (not iword(3) and not iword(2)); + + when "011000" => -- 24 + -- ori, special-case the standard NOP + if std_match(iword, "01100000000000000000000000000000") then + icode := INSN_nop; + end if; + + when "011111" => -- 31 + -- major opcode 31, lots of things + -- Use the first half of the row table for all columns + use_row := '1'; + + when "111011" => -- 59 + -- floating point operations, mostly single-precision + -- Columns 0-11 are illegal; columns 12-15 are mapped + -- to columns 20-23 in the second half of the row table, + -- and columns 16-31 are in the major table. + illegal := not iword(5) and (not iword(4) or not iword(3)); + use_row := not iword(5); + + when "111111" => -- 63 + -- floating point operations, general and double-precision + -- Use columns 0-15 of the second half of the row table + -- for columns 0-15, and the major table for columns 16-31. + use_row := not iword(5); + + when others => + end case; + if use_row = '1' then + icode := pred(i).row_predecode; + end if; + + -- Mark FP instructions as illegal if we don't have an FPU + if not HAS_FPU and icode >= INSN_first_frs then + illegal := '1'; + end if; + + ici(31 downto 0) := iword; + ici(IOUT_LEN - 1 downto 32) := (others => '0'); + if illegal = '1' or icode = INSN_illegal then + -- Since an insn_code currently fits in 9 bits, use just + -- the most significant bit of ici to indicate illegal insns. + ici(IOUT_LEN - 1) := '1'; + else + ici(IOUT_LEN - 1 downto IMAGE_LEN) := + std_ulogic_vector(to_unsigned(insn_code'pos(icode), ICODE_LEN)); + end if; + icodes_out(i * IOUT_LEN + IOUT_LEN - 1 downto i * IOUT_LEN) <= ici; + end loop; + end process; + +end architecture behaviour; From 30f65741350630b88a25fa43a3ee5ecfe5cdeb39 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Aug 2022 14:57:12 +1000 Subject: [PATCH 14/22] predecode: Work around apparent yosys/nextpnr bug This rearranges the synchronous process here to avoid setting fields of pred(i) to zero or INSN_illegal when valid_in is '0'. Experimentally, on ECP5 this acts like an asynchronous reset rather than a synchronous reset. Instead, handle possible indeterminate input for simulation by making the maj_predecode and row_predecode fields of predec_t be unsigned rather than insn_code (an enumerated type), and setting them to X when the input word is indeterminate. Signed-off-by: Paul Mackerras --- predecode.vhdl | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/predecode.vhdl b/predecode.vhdl index 1e1d85b..3bbd224 100644 --- a/predecode.vhdl +++ b/predecode.vhdl @@ -454,26 +454,34 @@ architecture behaviour of predecoder is type predec_t is record image : std_ulogic_vector(31 downto 0); - maj_predecode : insn_code; - row_predecode : insn_code; + maj_predecode : unsigned(ICODE_LEN - 1 downto 0); + row_predecode : unsigned(ICODE_LEN - 1 downto 0); end record; subtype index_t is integer range 0 to WIDTH-1; type predec_array is array(index_t) of predec_t; signal pred : predec_array; + signal valid : std_ulogic; begin predecode_0: process(clk) variable majaddr : std_ulogic_vector(10 downto 0); variable rowaddr : std_ulogic_vector(10 downto 0); variable iword : std_ulogic_vector(31 downto 0); + variable majcode : insn_code; + variable rowcode : insn_code; begin if rising_edge(clk) then + valid <= valid_in; for i in index_t loop - if valid_in = '1' then - iword := insns_in(i * 32 + 31 downto i * 32); + iword := insns_in(i * 32 + 31 downto i * 32); + pred(i).image <= iword; + if is_X(iword) then + pred(i).maj_predecode <= (others => 'X'); + pred(i).row_predecode <= (others => 'X'); + else majaddr := iword(31 downto 26) & iword(4 downto 0); -- row_predecode_rom is used for op 19, 31, 59, 63 @@ -489,13 +497,10 @@ begin end if; rowaddr(2 downto 0) := iword(3 downto 1); - pred(i).image <= iword; - pred(i).maj_predecode <= major_predecode_rom(to_integer(unsigned(majaddr))); - pred(i).row_predecode <= row_predecode_rom(to_integer(unsigned(rowaddr))); - else - pred(i).image <= (others => '0'); - pred(i).maj_predecode <= INSN_illegal; - pred(i).row_predecode <= INSN_illegal; + majcode := major_predecode_rom(to_integer(unsigned(majaddr))); + pred(i).maj_predecode <= to_unsigned(insn_code'pos(majcode), ICODE_LEN); + rowcode := row_predecode_rom(to_integer(unsigned(rowaddr))); + pred(i).row_predecode <= to_unsigned(insn_code'pos(rowcode), ICODE_LEN); end if; end loop; end if; @@ -506,7 +511,7 @@ begin variable use_row : std_ulogic; variable illegal : std_ulogic; variable ici : std_ulogic_vector(IOUT_LEN - 1 downto 0); - variable icode : insn_code; + variable icode : unsigned(ICODE_LEN - 1 downto 0); begin for i in index_t loop iword := pred(i).image; @@ -532,7 +537,7 @@ begin when "011000" => -- 24 -- ori, special-case the standard NOP if std_match(iword, "01100000000000000000000000000000") then - icode := INSN_nop; + icode := to_unsigned(insn_code'pos(INSN_nop), ICODE_LEN); end if; when "011111" => -- 31 @@ -561,19 +566,20 @@ begin end if; -- Mark FP instructions as illegal if we don't have an FPU - if not HAS_FPU and icode >= INSN_first_frs then + if not HAS_FPU and not is_X(icode) and + to_integer(icode) >= insn_code'pos(INSN_first_frs) then illegal := '1'; end if; ici(31 downto 0) := iword; ici(IOUT_LEN - 1 downto 32) := (others => '0'); - if illegal = '1' or icode = INSN_illegal then + if valid = '0' or illegal = '1' or is_X(icode) or + icode = to_unsigned(insn_code'pos(INSN_illegal), ICODE_LEN) then -- Since an insn_code currently fits in 9 bits, use just -- the most significant bit of ici to indicate illegal insns. ici(IOUT_LEN - 1) := '1'; else - ici(IOUT_LEN - 1 downto IMAGE_LEN) := - std_ulogic_vector(to_unsigned(insn_code'pos(icode), ICODE_LEN)); + ici(IOUT_LEN - 1 downto IMAGE_LEN) := std_ulogic_vector(icode); end if; icodes_out(i * IOUT_LEN + IOUT_LEN - 1 downto i * IOUT_LEN) <= ici; end loop; From 6db626d24547b96bce576c8c3fdf2790c7d6c7ce Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Aug 2022 15:17:25 +1000 Subject: [PATCH 15/22] icache: Log 36 bits of instruction rather than 32 This expands the field in the log buffer that stores the instruction fetched from the icache to 36 bits, so that we get the insn_code and illegal instruction indication. To do this, we reclaim 3 unused bits from execute1's portion and one other unused bit (previously just set to 0 in core.vhdl). This also alters the trigger behaviour to stop after one quarter of the log buffer has been filled with samples after the trigger, or 256 entries, whichever is less. This is to ensure that the trigger event doesn't get overwritten when the log buffer is small. This updates fmt_log to the new log format. Valid instructions are printed as a decimal insn_code value followed by the bottom 26 bits of the instruction. Illegal instructions are printed as "ill" followed by the full 32 bits of the instruction. Signed-off-by: Paul Mackerras --- core.vhdl | 10 +++++----- core_debug.vhdl | 3 ++- execute1.vhdl | 5 ++--- icache.vhdl | 9 ++++++--- scripts/fmt_log/fmt_log.c | 27 +++++++++++++++------------ 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/core.vhdl b/core.vhdl index 0624000..d7036f1 100644 --- a/core.vhdl +++ b/core.vhdl @@ -267,7 +267,7 @@ begin wishbone_in => wishbone_insn_in, wb_snoop_in => wb_snoop_in, events => icache_events, - log_out => log_data(96 downto 43) + log_out => log_data(100 downto 43) ); icache_stall_in <= decode1_busy; @@ -288,7 +288,7 @@ begin d_out => decode1_to_decode2, f_out => decode1_to_fetch1, r_out => decode1_to_register_file, - log_out => log_data(109 downto 97) + log_out => log_data(113 downto 101) ); decode1_stall_in <= decode2_stall_out; @@ -320,7 +320,7 @@ begin writeback_bypass => writeback_bypass, dbg_spr_req => dbg_spr_req, dbg_spr_addr => dbg_spr_addr, - log_out => log_data(119 downto 110) + log_out => log_data(123 downto 114) ); decode2_busy_in <= ex1_busy_out; @@ -399,7 +399,7 @@ begin dbg_spr_data => dbg_spr_data, sim_dump => sim_ex_dump, sim_dump_done => sim_cr_dump, - log_out => log_data(134 downto 120), + log_out => log_data(135 downto 124), log_rd_addr => log_rd_addr, log_rd_data => log_rd_data, log_wr_addr => log_wr_addr @@ -501,7 +501,7 @@ begin ); log_data(150) <= '0'; - log_data(139 downto 135) <= "00000"; + log_data(139 downto 136) <= "0000"; debug_0: entity work.core_debug generic map ( diff --git a/core_debug.vhdl b/core_debug.vhdl index c9c3f40..592cf85 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -175,7 +175,8 @@ begin gspr_index <= (others => '0'); else if do_log_trigger = '1' or log_trigger_delay /= 0 then - if log_trigger_delay = 255 then + if log_trigger_delay = 255 or + (LOG_LENGTH < 1024 and log_trigger_delay = LOG_LENGTH / 4) then log_dmi_trigger(1) <= '1'; log_trigger_delay <= 0; else diff --git a/execute1.vhdl b/execute1.vhdl index 024f5c2..92da2ee 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -65,7 +65,7 @@ entity execute1 is sim_dump : in std_ulogic; sim_dump_done : out std_ulogic; - log_out : out std_ulogic_vector(14 downto 0); + log_out : out std_ulogic_vector(11 downto 0); log_rd_addr : out std_ulogic_vector(31 downto 0); log_rd_data : in std_ulogic_vector(63 downto 0); log_wr_addr : in std_ulogic_vector(31 downto 0) @@ -1802,7 +1802,7 @@ begin end generate; e1_log: if LOG_LENGTH > 0 generate - signal log_data : std_ulogic_vector(14 downto 0); + signal log_data : std_ulogic_vector(11 downto 0); begin ex1_log : process(clk) begin @@ -1812,7 +1812,6 @@ begin exception_log & irq_valid_log & interrupt_in.intr & - "000" & ex2.e.write_enable & ex2.e.valid & (ex2.e.redirect or ex2.e.interrupt) & diff --git a/icache.vhdl b/icache.vhdl index 63de229..58e2b5c 100644 --- a/icache.vhdl +++ b/icache.vhdl @@ -71,7 +71,7 @@ entity icache is wb_snoop_in : in wishbone_master_out := wishbone_master_out_init; events : out IcacheEventType; - log_out : out std_ulogic_vector(53 downto 0) + log_out : out std_ulogic_vector(57 downto 0) ); end entity icache; @@ -244,6 +244,8 @@ architecture rtl of icache is signal snoop_index : index_t; signal snoop_hits : cache_way_valids_t; + signal log_insn : std_ulogic_vector(35 downto 0); + -- Return the cache line index (tag index) for an address function get_index(addr: std_ulogic_vector) return index_t is begin @@ -623,6 +625,7 @@ begin end if; i_out.insn <= insn(31 downto 0); i_out.icode <= icode; + log_insn <= cache_wr_data(35 downto 0); i_out.valid <= r.hit_valid; i_out.nia <= r.hit_nia; i_out.stop_mark <= r.hit_smark; @@ -872,7 +875,7 @@ begin icache_log: if LOG_LENGTH > 0 generate -- Output data to logger - signal log_data : std_ulogic_vector(53 downto 0); + signal log_data : std_ulogic_vector(57 downto 0); begin data_log: process(clk) variable lway: way_t; @@ -885,7 +888,7 @@ begin wstate := '1'; end if; log_data <= i_out.valid & - i_out.insn & + log_insn & wishbone_in.ack & r.wb.adr(2 downto 0) & r.wb.stb & r.wb.cyc & diff --git a/scripts/fmt_log/fmt_log.c b/scripts/fmt_log/fmt_log.c index 09d41ad..e92ecba 100644 --- a/scripts/fmt_log/fmt_log.c +++ b/scripts/fmt_log/fmt_log.c @@ -22,7 +22,7 @@ struct log_entry { u64 ic_wb_adr: 3; u64 ic_wb_ack: 1; - u64 ic_insn: 32; + u64 ic_insn: 36; u64 ic_valid: 1; u64 d1_valid: 1; u64 d1_unit: 2; @@ -39,9 +39,8 @@ struct log_entry { u64 e1_stall_out: 1; u64 e1_redirect: 1; u64 e1_valid: 1; - u64 e1_write_enable: 1; - u64 e1_unused: 3; + u64 e1_write_enable: 1; u64 e1_irq_state: 1; u64 e1_irq: 1; u64 e1_exception: 1; @@ -49,7 +48,7 @@ struct log_entry { u64 e1_msr_ir: 1; u64 e1_msr_pr: 1; u64 e1_msr_ee: 1; - u64 pad1: 5; + u64 pad1: 4; u64 ls_state: 3; u64 ls_dw_done: 1; u64 ls_min_done: 1; @@ -134,9 +133,9 @@ int main(int ac, char **av) full_nia[log.nia_lo & 0xf] = (log.nia_hi? 0xc000000000000000: 0) | (log.nia_lo << 2); if (lineno % 20 == 1) { - printf(" fetch1 NIA icache decode1 decode2 execute1 loadstore dcache CR GSPR\n"); - printf(" ---------------- TAHW S -WB-- pN --insn-- pN un op pN byp FR IIE MSR WC SD MM CE SRTO DE -WB-- c ms reg val\n"); - printf(" LdMy t csnSa IA IA it IA abc le srx EPID em tw rd mx tAwp vr csnSa 0 k\n"); + printf(" fetch1 NIA icache decode1 decode2 execute1 loadstore dcache CR GSPR\n"); + printf(" ---------------- TAHW S -WB-- pN ic --insn-- pN un op pN byp FR IIE MSR WC SD MM CE SRTO DE -WB-- c ms reg val\n"); + printf(" LdMy t csnSa IA IA it IA abc le srx EPID em tw rd mx tAwp vr csnSa 0 k\n"); } printf("%4ld %c0000%.11llx %c ", lineno, (log.nia_hi? 'c': '0'), @@ -154,12 +153,16 @@ int main(int ac, char **av) FLAG(ic_wb_stall, 'S'), FLAG(ic_wb_ack, 'a'), PNIA(ic_part_nia)); - if (log.ic_valid) - printf("%.8x", log.ic_insn); - else if (log.ic_fetch_failed) - printf("!!!!!!!!"); + if (log.ic_valid) { + if (log.ic_insn & (1ul << 35)) + printf("ill %.8lx", log.ic_insn & 0xfffffffful); + else + printf("%3lu x%.7lx", (long)(log.ic_insn >> 26), + (unsigned long)(log.ic_insn & 0x3ffffff)); + } else if (log.ic_fetch_failed) + printf(" !!!!!!!!"); else - printf("--------"); + printf("--- --------"); printf(" %c%c %.2llx ", FLAG(ic_valid, '>'), FLAG(d2_stall_out, '|'), From 58e799b3504090451d5ffb32352d665ec187a0b8 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 4 Aug 2022 15:25:06 +1000 Subject: [PATCH 16/22] predecode: Add more comments to row_predecode_rom and insn_code values This adds comments to row_predecode_rom to aid understanding how the columns in the second half of the table are allocated to different primary opcodes, and to the insn_code values to assist in locating the code with a given numeric value. No code change. Signed-off-by: Paul Mackerras --- decode_types.vhdl | 58 +++++++++++++++++++++++------------------------ predecode.vhdl | 8 +++++-- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/decode_types.vhdl b/decode_types.vhdl index 9f19530..7ceb2ae 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -32,7 +32,7 @@ package decode_types is -- comparisons of the insn_code for the instruction with a few constants. type insn_code is ( -- The following instructions don't have an RB operand or access FPRs - INSN_illegal, + INSN_illegal, -- 0 INSN_fetch_fail, INSN_addi, INSN_addic, @@ -42,7 +42,7 @@ package decode_types is INSN_addpcis, INSN_addze, INSN_andi_dot, - INSN_andis_dot, + INSN_andis_dot, -- 10 INSN_attn, INSN_b, INSN_bc, @@ -52,7 +52,7 @@ package decode_types is INSN_cbcdtd, INSN_cdtbcd, INSN_cmpi, - INSN_cmpli, + INSN_cmpli, -- 20 INSN_cntlzw, INSN_cntlzd, INSN_cnttzw, @@ -62,7 +62,7 @@ package decode_types is INSN_creqv, INSN_crnand, INSN_crnor, - INSN_cror, + INSN_cror, -- 30 INSN_crorc, INSN_crxor, INSN_darn, @@ -72,7 +72,7 @@ package decode_types is INSN_extsw, INSN_extswsli, INSN_isync, - INSN_lbz, + INSN_lbz, -- 40 INSN_lbzu, INSN_ld, INSN_ldu, @@ -82,7 +82,7 @@ package decode_types is INSN_lhzu, INSN_lwa, INSN_lwz, - INSN_lwzu, + INSN_lwzu, -- 50 INSN_mcrf, INSN_mcrfs, INSN_mcrxrx, @@ -92,7 +92,7 @@ package decode_types is INSN_mtcrf, INSN_mtfsb, INSN_mtfsfi, - INSN_mtmsr, + INSN_mtmsr, -- 60 INSN_mtmsrd, INSN_mtspr, INSN_mulli, @@ -102,7 +102,7 @@ package decode_types is INSN_oris, INSN_popcntb, INSN_popcntw, - INSN_popcntd, + INSN_popcntd, -- 70 INSN_prtyw, INSN_prtyd, INSN_rfid, @@ -112,7 +112,7 @@ package decode_types is INSN_rldimi, INSN_rlwimi, INSN_rlwinm, - INSN_sc, + INSN_sc, -- 80 INSN_setb, INSN_slbia, INSN_sradi, @@ -122,7 +122,7 @@ package decode_types is INSN_std, INSN_stdu, INSN_sth, - INSN_sthu, + INSN_sthu, -- 90 INSN_stw, INSN_stwu, INSN_subfic, @@ -132,7 +132,7 @@ package decode_types is INSN_tdi, INSN_tlbsync, INSN_twi, - INSN_wait, + INSN_wait, -- 100 INSN_xori, INSN_xoris, @@ -150,7 +150,7 @@ package decode_types is INSN_and, INSN_andc, INSN_bperm, - INSN_cmp, + INSN_cmp, -- 120 INSN_cmpb, INSN_cmpeqb, INSN_cmpl, @@ -160,7 +160,7 @@ package decode_types is INSN_dcbt, INSN_dcbtst, INSN_dcbz, - INSN_divd, + INSN_divd, -- 130 INSN_divdu, INSN_divde, INSN_divdeu, @@ -170,7 +170,7 @@ package decode_types is INSN_divweu, INSN_eqv, INSN_icbi, - INSN_icbt, + INSN_icbt, -- 140 INSN_isel, INSN_lbarx, INSN_lbzcix, @@ -180,7 +180,7 @@ package decode_types is INSN_ldbrx, INSN_ldcix, INSN_ldx, - INSN_ldux, + INSN_ldux, -- 150 INSN_lharx, INSN_lhax, INSN_lhaux, @@ -190,7 +190,7 @@ package decode_types is INSN_lhzux, INSN_lwarx, INSN_lwax, - INSN_lwaux, + INSN_lwaux, -- 160 INSN_lwbrx, INSN_lwzcix, INSN_lwzx, @@ -200,7 +200,7 @@ package decode_types is INSN_moduw, INSN_modud, INSN_mulhw, - INSN_mulhwu, + INSN_mulhwu, -- 170 INSN_mulhd, INSN_mulhdu, INSN_mullw, @@ -210,7 +210,7 @@ package decode_types is INSN_or, INSN_orc, INSN_rldcl, - INSN_rldcr, + INSN_rldcr, -- 180 INSN_rlwnm, INSN_slw, INSN_sld, @@ -220,7 +220,7 @@ package decode_types is INSN_srd, INSN_stbcix, INSN_stbcx, - INSN_stbx, + INSN_stbx, -- 190 INSN_stbux, INSN_stdbrx, INSN_stdcix, @@ -230,7 +230,7 @@ package decode_types is INSN_sthbrx, INSN_sthcix, INSN_sthcx, - INSN_sthx, + INSN_sthx, -- 200 INSN_sthux, INSN_stwbrx, INSN_stwcix, @@ -240,7 +240,7 @@ package decode_types is INSN_subf, INSN_subfc, INSN_subfe, - INSN_td, + INSN_td, -- 210 INSN_tlbie, INSN_tlbiel, INSN_tw, @@ -272,7 +272,7 @@ package decode_types is INSN_stfdu, INSN_stfs, INSN_stfsu, - INSN_stfdux, + INSN_stfdux, -- 260 INSN_stfdx, INSN_stfiwx, INSN_stfsux, @@ -284,7 +284,7 @@ package decode_types is INSN_lfs, INSN_lfsu, INSN_lfdx, - INSN_lfdux, + INSN_lfdux, -- 270 INSN_lfiwax, INSN_lfiwzx, INSN_lfsx, @@ -296,7 +296,7 @@ package decode_types is INSN_fadd, INSN_fadds, INSN_fcfid, - INSN_fcfids, + INSN_fcfids, -- 280 INSN_fcfidu, INSN_fcfidus, INSN_fcmpo, @@ -306,7 +306,7 @@ package decode_types is INSN_fctidz, INSN_fctidu, INSN_fctiduz, - INSN_fctiw, + INSN_fctiw, -- 290 INSN_fctiwz, INSN_fctiwu, INSN_fctiwuz, @@ -316,7 +316,7 @@ package decode_types is INSN_fmrgew, INSN_fmrgow, INSN_fnabs, - INSN_fneg, + INSN_fneg, -- 300 INSN_fre, INSN_fres, INSN_frim, @@ -326,7 +326,7 @@ package decode_types is INSN_frsp, INSN_frsqrte, INSN_frsqrtes, - INSN_fsqrt, + INSN_fsqrt, -- 310 INSN_fsqrts, INSN_fsub, INSN_fsubs, @@ -339,7 +339,7 @@ package decode_types is INSN_318, INSN_319, -- The following instructions access FRA, FRB (possibly) and FRC operands - INSN_fmul, + INSN_fmul, -- 320 INSN_fmuls, INSN_fmadd, INSN_fmadds, @@ -349,7 +349,7 @@ package decode_types is INSN_fnmadds, INSN_fnmsub, INSN_fnmsubs, - INSN_fsel + INSN_fsel -- 330 ); constant INSN_first_rb : insn_code := INSN_add; diff --git a/predecode.vhdl b/predecode.vhdl index 3bbd224..7e1149b 100644 --- a/predecode.vhdl +++ b/predecode.vhdl @@ -389,6 +389,8 @@ architecture behaviour of predecoder is -- fit into 2048 entries, the columns are remapped so that 16-24 are -- stored here as 8-15; in other words the address bits are -- 1, insn(10..6), 1, insn(5), insn(3..1) + -- Columns 16-17 here are opcode 19 columns 0-1 + -- Columns 24-31 here are opcode 19 columns 16-23 2#1_10000_11000# => INSN_bcctr, 2#1_00000_11000# => INSN_bclr, 2#1_10001_11000# => INSN_bctar, @@ -405,15 +407,17 @@ architecture behaviour of predecoder is 2#1_00000_11010# => INSN_rfid, -- Major opcode 59 + -- Address bits are 1, insn(10..6), 1, 0, insn(3..1) -- Only column 14 is valid here; columns 16-31 are handled in the major table - -- Column 14 is mapped to column 6 of the space which is - -- mostly used for opcode 19. + -- Column 14 is mapped to column 22. + -- Columns 20-23 here are opcode 59 columns 12-15 2#1_11010_10110# => INSN_fcfids, 2#1_11110_10110# => INSN_fcfidus, -- Major opcode 63 -- Columns 0-15 are mapped here; columns 16-31 are in the major table. -- Address bits are 1, insn(10:6), 0, insn(4:1) + -- Columns 0-15 here are opcode 63 columns 0-15 2#1_00000_00000# => INSN_fcmpu, 2#1_00001_00000# => INSN_fcmpo, 2#1_00010_00000# => INSN_mcrfs, From 595a7584008057a5be3b9a4a9bb1035ecccb23f9 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 16 Jul 2022 11:49:28 +1000 Subject: [PATCH 17/22] execute1: Add a pipelined 33-bit signed multiplier This adds a pipelined 33-bit by 33-bit signed multiplier with one cycle latency to the execute pipeline, and uses it for the mullw, mulhw and mulhwu instructions. Because it has one cycle of latency we can assume that its result is available in the second execute stage without needing to add busy logic to the second stage. This adds both a generic version of the multiplier and a Xilinx-specific version using four DSP slices of the Artix-7. Signed-off-by: Paul Mackerras --- Makefile | 6 +- execute1.vhdl | 71 ++++++++--- microwatt.core | 1 + multiply-32s.vhdl | 55 ++++++++ xilinx-mult-32s.vhdl | 293 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 408 insertions(+), 18 deletions(-) create mode 100644 multiply-32s.vhdl create mode 100644 xilinx-mult-32s.vhdl diff --git a/Makefile b/Makefile index ebb1b79..794cbc1 100644 --- a/Makefile +++ b/Makefile @@ -60,9 +60,9 @@ core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ decode1.vhdl helpers.vhdl insn_helpers.vhdl \ control.vhdl decode2.vhdl register_file.vhdl \ cr_file.vhdl crhelpers.vhdl ppc_fx_insns.vhdl rotator.vhdl \ - logical.vhdl countbits.vhdl multiply.vhdl divider.vhdl execute1.vhdl \ - loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl core_debug.vhdl \ - core.vhdl fpu.vhdl pmu.vhdl + logical.vhdl countbits.vhdl multiply.vhdl multiply-32s.vhdl divider.vhdl \ + execute1.vhdl loadstore1.vhdl mmu.vhdl dcache.vhdl writeback.vhdl \ + core_debug.vhdl core.vhdl fpu.vhdl pmu.vhdl soc_files = wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \ wishbone_debug_master.vhdl xics.vhdl syscon.vhdl gpio.vhdl soc.vhdl \ diff --git a/execute1.vhdl b/execute1.vhdl index 92da2ee..948bdd6 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -85,6 +85,7 @@ architecture behaviour of execute1 is write_pmuspr : std_ulogic; ramspr_write_even : std_ulogic; ramspr_write_odd : std_ulogic; + mult_32s : std_ulogic; end record; constant side_effect_init : side_effect_type := (others => '0'); @@ -203,6 +204,8 @@ architecture behaviour of execute1 is -- multiply signals signal x_to_multiply: MultiplyInputType; signal multiply_to_x: MultiplyOutputType; + signal x_to_mult_32s: MultiplyInputType; + signal mult_32s_to_x: MultiplyOutputType; -- divider signals signal x_to_divider: Execute1ToDividerType; @@ -411,6 +414,14 @@ begin m_out => multiply_to_x ); + mult_32s_0: entity work.multiply_32s + port map ( + clk => clk, + stall => stage2_stall, + m_in => x_to_mult_32s, + m_out => mult_32s_to_x + ); + divider_0: if not HAS_FPU generate div_0: entity work.divider port map ( @@ -730,14 +741,14 @@ begin addend := not addend; end if; + x_to_multiply.data1 <= std_ulogic_vector(abs1); + x_to_multiply.data2 <= std_ulogic_vector(abs2); x_to_multiply.is_32bit <= e_in.is_32bit; x_to_multiply.not_result <= sign1 xor sign2; x_to_multiply.addend <= addend; x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus); if e_in.is_32bit = '0' then -- 64-bit forms - x_to_multiply.data1 <= std_ulogic_vector(abs1); - x_to_multiply.data2 <= std_ulogic_vector(abs2); if e_in.insn_type = OP_DIVE then x_to_divider.is_extended <= '1'; end if; @@ -745,8 +756,6 @@ begin x_to_divider.divisor <= std_ulogic_vector(abs2); else -- 32-bit forms - x_to_multiply.data1 <= x"00000000" & std_ulogic_vector(abs1(31 downto 0)); - x_to_multiply.data2 <= x"00000000" & std_ulogic_vector(abs2(31 downto 0)); x_to_divider.is_extended <= '0'; if e_in.insn_type = OP_DIVE then -- extended forms x_to_divider.dividend <= std_ulogic_vector(abs1(31 downto 0)) & x"00000000"; @@ -756,6 +765,14 @@ begin x_to_divider.divisor <= x"00000000" & std_ulogic_vector(abs2(31 downto 0)); end if; + -- signals to 32-bit multiplier + x_to_mult_32s.data1 <= 31x"0" & (a_in(31) and e_in.is_signed) & a_in(31 downto 0); + x_to_mult_32s.data2 <= 31x"0" & (b_in(31) and e_in.is_signed) & b_in(31 downto 0); + -- The following are unused, but set here to avoid X states + x_to_mult_32s.is_32bit <= '1'; + x_to_mult_32s.not_result <= '0'; + x_to_mult_32s.addend <= (others => '0'); + shortmul_result <= std_ulogic_vector(resize(signed(mshort_p), 64)); case ex1.mul_select is when "00" => @@ -1271,7 +1288,11 @@ begin v.se.icache_inval := '1'; when OP_MUL_L64 => - if HAS_SHORT_MULT and e_in.reg_valid3 = '0' and + if e_in.is_32bit = '1' then + v.se.mult_32s := '1'; + v.res2_sel := "00"; + slow_op := '1'; + elsif HAS_SHORT_MULT and e_in.reg_valid3 = '0' and fits_in_n_bits(a_in, 16) and fits_in_n_bits(b_in, 16) then -- Operands fit into 16 bits, so use short multiplier if e_in.oe = '1' then @@ -1285,11 +1306,16 @@ begin owait := '1'; end if; - when OP_MUL_H64 | OP_MUL_H32 => + when OP_MUL_H64 => v.start_mul := '1'; slow_op := '1'; owait := '1'; + when OP_MUL_H32 => + v.se.mult_32s := '1'; + v.res2_sel := "01"; + slow_op := '1'; + when OP_DIV | OP_DIVE | OP_MOD => if not HAS_FPU then v.start_div := '1'; @@ -1370,6 +1396,7 @@ begin fv := Execute1ToFPUInit; x_to_multiply.valid <= '0'; + x_to_mult_32s.valid <= '0'; x_to_divider.valid <= '0'; v.ext_interrupt := '0'; v.taken_branch_event := '0'; @@ -1456,6 +1483,7 @@ begin v.res2_sel := actions.res2_sel; v.msr := actions.new_msr; x_to_multiply.valid <= actions.start_mul; + x_to_mult_32s.valid <= actions.se.mult_32s; v.mul_in_progress := actions.start_mul; x_to_divider.valid <= actions.start_div; v.div_in_progress := actions.start_div; @@ -1624,11 +1652,6 @@ begin -- Second execute stage control execute2_1: process(all) variable v : reg_stage2_type; - variable overflow : std_ulogic; - variable lv : Execute1ToLoadstore1Type; - variable fv : Execute1ToFPUType; - variable k : integer; - variable go : std_ulogic; variable bypass_valid : std_ulogic; variable rcresult : std_ulogic_vector(63 downto 0); variable sprres : std_ulogic_vector(63 downto 0); @@ -1647,6 +1670,14 @@ begin v.br_mispredict := ex1.br_mispredict; end if; + if ex1.se.mult_32s = '1' and ex1.oe = '1' then + v.e.xerc.ov := mult_32s_to_x.overflow; + v.e.xerc.ov32 := mult_32s_to_x.overflow; + if mult_32s_to_x.overflow = '1' then + v.e.xerc.so := '1'; + end if; + end if; + ctrl_tmp <= ctrl; -- FIXME: run at 512MHz not core freq ctrl_tmp.tb <= std_ulogic_vector(unsigned(ctrl.tb) + 1); @@ -1667,24 +1698,34 @@ begin v.e.write_xerc_enable := '0'; v.e.redirect := '0'; v.e.br_last := '0'; - v.se := side_effect_init; v.taken_branch_event := '0'; v.br_mispredict := '0'; end if; if flush_in = '1' then v.e.valid := '0'; v.e.interrupt := '0'; + v.se := side_effect_init; v.ext_interrupt := '0'; end if; -- This is split like this because mfspr doesn't have an Rc bit, -- and we don't want the zero-detect logic to be after the -- SPR mux for timing reasons. - if ex1.res2_sel(0) = '0' then + if ex1.se.mult_32s = '1' then + if ex1.res2_sel(0) = '0' then + rcresult := mult_32s_to_x.result(63 downto 0); + else + rcresult := mult_32s_to_x.result(63 downto 32) & + mult_32s_to_x.result(63 downto 32); + end if; + elsif ex1.res2_sel(0) = '0' then rcresult := ex1.e.write_data; - sprres := spr_result; else rcresult := countbits_result; + end if; + if ex1.res2_sel(0) = '0' then + sprres := spr_result; + else sprres := pmu_to_x.spr_val; end if; if ex1.res2_sel(1) = '0' then @@ -1708,7 +1749,7 @@ begin cr_res(31) := sign; cr_res(30) := not (sign or zero); cr_res(29) := zero; - cr_res(28) := ex1.e.xerc.so; + cr_res(28) := v.e.xerc.so; cr_mask(7) := '1'; end if; diff --git a/microwatt.core b/microwatt.core index 4c8695e..b817901 100644 --- a/microwatt.core +++ b/microwatt.core @@ -66,6 +66,7 @@ filesets: xilinx_specific: files: - xilinx-mult.vhdl : {file_type : vhdlSource-2008} + - xilinx-mult-32s.vhdl : {file_type : vhdlSource-2008} - fpga/fpga-random.vhdl : {file_type : vhdlSource-2008} - fpga/fpga-random.xdc : {file_type : xdc} diff --git a/multiply-32s.vhdl b/multiply-32s.vhdl new file mode 100644 index 0000000..0639dbf --- /dev/null +++ b/multiply-32s.vhdl @@ -0,0 +1,55 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; + +-- Signed 33b x 33b multiplier giving 64-bit product, with no addend, +-- with fixed 1-cycle latency. + +entity multiply_32s is + port ( + clk : in std_logic; + stall : in std_ulogic; + + m_in : in MultiplyInputType; + m_out : out MultiplyOutputType + ); +end entity multiply_32s; + +architecture behaviour of multiply_32s is + type reg_type is record + valid : std_ulogic; + data : signed(65 downto 0); + end record; + constant reg_type_init : reg_type := (valid => '0', data => (others => '0')); + + signal r, rin : reg_type := reg_type_init; +begin + multiply_0: process(clk) + begin + if rising_edge(clk) and stall = '0' then + r <= rin; + end if; + end process; + + multiply_1: process(all) + variable v : reg_type; + variable d : std_ulogic_vector(63 downto 0); + variable ov : std_ulogic; + begin + v.valid := m_in.valid; + v.data := signed(m_in.data1(32 downto 0)) * signed(m_in.data2(32 downto 0)); + + d := std_ulogic_vector(r.data(63 downto 0)); + + ov := (or d(63 downto 31)) and not (and d(63 downto 31)); + + m_out.result <= 64x"0" & d; + m_out.overflow <= ov; + m_out.valid <= r.valid; + + rin <= v; + end process; +end architecture behaviour; diff --git a/xilinx-mult-32s.vhdl b/xilinx-mult-32s.vhdl new file mode 100644 index 0000000..fde19ae --- /dev/null +++ b/xilinx-mult-32s.vhdl @@ -0,0 +1,293 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; + +library unisim; +use unisim.vcomponents.all; + +-- Signed 33b x 33b multiplier giving 64-bit product, with no addend. + +entity multiply_32s is + port ( + clk : in std_logic; + stall : in std_ulogic; + + m_in : in MultiplyInputType; + m_out : out MultiplyOutputType + ); +end entity multiply_32s; + +architecture behaviour of multiply_32s is + signal clocken : std_ulogic; + signal data1 : std_ulogic_vector(52 downto 0); + signal data2 : std_ulogic_vector(34 downto 0); + signal m00_p, m01_p : std_ulogic_vector(47 downto 0); + signal m00_pc : std_ulogic_vector(47 downto 0); + signal m10_p, m11_p : std_ulogic_vector(47 downto 0); + signal m10_pc : std_ulogic_vector(47 downto 0); + signal p0_pat, p0_patb : std_ulogic; + signal p1_pat, p1_patb : std_ulogic; + signal product_lo : std_ulogic_vector(22 downto 0); + +begin + -- sign extend + data1 <= std_ulogic_vector(resize(signed(m_in.data1(32 downto 0)), 53)); + data2 <= std_ulogic_vector(resize(signed(m_in.data2(32 downto 0)), 35)); + + clocken <= m_in.valid and not stall; + + m00: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + MREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & data2(16 downto 0), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m00_p, + PCIN => (others => '0'), + PCOUT => m00_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m01: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + MREG => 0, + OPMODEREG => 0, + PREG => 0 + ) + port map ( + A => "0000000" & data1(22 downto 0), + ACIN => (others => '0'), + ALUMODE => "0000", + B => data2(34 downto 17), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => '0', + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "1010101", + P => m01_p, + PCIN => m00_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m10: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 1, + INMODEREG => 0, + MASK => x"fffffffe00ff", + OPMODEREG => 0, + PREG => 0, + USE_PATTERN_DETECT => "PATDET" + ) + port map ( + A => data1(52 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => '0' & data2(16 downto 0), + BCIN => (others => '0'), + C => std_ulogic_vector(resize(signed(m01_p(38 downto 6)), 48)), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => clocken, + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => clocken, + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "0110101", + P => m10_p, + PATTERNDETECT => p0_pat, + PATTERNBDETECT => p0_patb, + PCIN => (others => '0'), + PCOUT => m10_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m11: DSP48E1 + generic map ( + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, + CARRYINREG => 0, + CARRYINSELREG => 0, + CREG => 0, + INMODEREG => 0, + MASK => x"fffffc000000", + OPMODEREG => 0, + PREG => 0, + USE_PATTERN_DETECT => "PATDET" + ) + port map ( + A => data1(52 downto 23), + ACIN => (others => '0'), + ALUMODE => "0000", + B => data2(34 downto 17), + BCIN => (others => '0'), + C => (others => '0'), + CARRYCASCIN => '0', + CARRYIN => '0', + CARRYINSEL => "000", + CEA1 => '0', + CEA2 => '0', + CEAD => '0', + CEALUMODE => '0', + CEB1 => '0', + CEB2 => '0', + CEC => '0', + CECARRYIN => '0', + CECTRL => '0', + CED => '0', + CEINMODE => '0', + CEM => clocken, + CEP => '0', + CLK => clk, + D => (others => '0'), + INMODE => "00000", + MULTSIGNIN => '0', + OPMODE => "1010101", + P => m11_p, + PATTERNDETECT => p1_pat, + PATTERNBDETECT => p1_patb, + PCIN => m10_pc, + RSTA => '0', + RSTALLCARRYIN => '0', + RSTALUMODE => '0', + RSTB => '0', + RSTC => '0', + RSTCTRL => '0', + RSTD => '0', + RSTINMODE => '0', + RSTM => '0', + RSTP => '0' + ); + + m_out.result(127 downto 64) <= (others => '0'); + m_out.result(63 downto 40) <= m11_p(23 downto 0); + m_out.result(39 downto 23) <= m10_p(16 downto 0); + m_out.result(22 downto 0) <= product_lo; + + m_out.overflow <= not ((p0_pat and p1_pat) or (p0_patb and p1_patb)); + + process(clk) + begin + if rising_edge(clk) and stall = '0' then + m_out.valid <= m_in.valid; + product_lo <= m01_p(5 downto 0) & m00_p(16 downto 0); + end if; + end process; + +end architecture behaviour; From af9fe3467c91b46c053bdc81fcef45044ef09578 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 8 Aug 2022 17:06:46 +1000 Subject: [PATCH 18/22] xilinx_mult: Prepare for doing signed multiplication This rearranges the way that partial products are generated and summed so that the partial products that could be negative in a signed multiplier are now sign-extended. The inputs are still zero-extended, however. The overflow detection logic now only detects 64-bit overflow, since 32-bit multiplications are handled in a separate multiplier. Signed-off-by: Paul Mackerras --- xilinx-mult.vhdl | 275 +++++++++++++++++++++++++---------------------- 1 file changed, 144 insertions(+), 131 deletions(-) diff --git a/xilinx-mult.vhdl b/xilinx-mult.vhdl index 97259b4..608810e 100644 --- a/xilinx-mult.vhdl +++ b/xilinx-mult.vhdl @@ -19,22 +19,24 @@ end entity multiply; architecture behaviour of multiply is signal m00_p, m01_p, m02_p, m03_p : std_ulogic_vector(47 downto 0); - signal m00_pc : std_ulogic_vector(47 downto 0); + signal m00_pc, m02_pc : std_ulogic_vector(47 downto 0); signal m10_p, m11_p, m12_p, m13_p : std_ulogic_vector(47 downto 0); - signal m11_pc, m12_pc, m13_pc : std_ulogic_vector(47 downto 0); + signal m10_pc, m12_pc : std_ulogic_vector(47 downto 0); signal m20_p, m21_p, m22_p, m23_p : std_ulogic_vector(47 downto 0); + signal m20_pc, m22_pc : std_ulogic_vector(47 downto 0); + signal pp0, pp1 : std_ulogic_vector(127 downto 0); + signal pp23 : std_ulogic_vector(127 downto 0); + signal sumlo : std_ulogic_vector(8 downto 0); signal s0_pc, s1_pc : std_ulogic_vector(47 downto 0); + signal s0_carry, p0_carry : std_ulogic_vector(3 downto 0); signal product : std_ulogic_vector(127 downto 0); signal addend : std_ulogic_vector(127 downto 0); - signal s0_carry, p0_carry : std_ulogic_vector(3 downto 0); - signal p0_mask : std_ulogic_vector(47 downto 0); signal p0_pat, p0_patb : std_ulogic; signal p1_pat, p1_patb : std_ulogic; - signal req_32bit, r32_1 : std_ulogic; signal rnot_1 : std_ulogic; signal valid_1 : std_ulogic; - signal overflow, ovf_in : std_ulogic; + signal overflow : std_ulogic; begin addend <= m_in.addend; @@ -55,12 +57,12 @@ begin PREG => 1 ) port map ( - A => "0000000" & m_in.data1(22 downto 0), + A => 6x"0" & m_in.data1(23 downto 0), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(16 downto 0), BCIN => (others => '0'), - C => "00000000000000" & addend(33 downto 0), + C => 14x"0" & addend(33 downto 0), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -106,12 +108,14 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 1, OPMODEREG => 0, PREG => 0 ) port map ( - A => "0000000" & m_in.data1(22 downto 0), + A => 6x"0" & m_in.data1(23 downto 0), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(33 downto 17), @@ -126,7 +130,7 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', @@ -168,12 +172,12 @@ begin PREG => 1 ) port map ( - A => "0000000" & m_in.data1(22 downto 0), + A => 6x"0" & m_in.data1(23 downto 0), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(50 downto 34), BCIN => (others => '0'), - C => x"0000000" & "000" & addend(50 downto 34), + C => 24x"0" & addend(57 downto 34), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -197,6 +201,7 @@ begin OPMODE => "0110101", P => m02_p, PCIN => (others => '0'), + PCOUT => m02_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -220,17 +225,17 @@ begin CARRYINSELREG => 0, CREG => 0, INMODEREG => 0, - MREG => 0, + MREG => 1, OPMODEREG => 0, - PREG => 1 + PREG => 0 ) port map ( - A => "0000000" & m_in.data1(22 downto 0), + A => 6x"0" & m_in.data1(23 downto 0), ACIN => (others => '0'), ALUMODE => "0000", B => "00000" & m_in.data2(63 downto 51), BCIN => (others => '0'), - C => x"000000" & '0' & addend(73 downto 51), + C => (others => '0'), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -245,15 +250,15 @@ begin CECTRL => '0', CED => '0', CEINMODE => '0', - CEM => '0', - CEP => m_in.valid, + CEM => m_in.valid, + CEP => '0', CLK => clk, D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0110101", + OPMODE => "1010101", P => m03_p, - PCIN => (others => '0'), + PCIN => m02_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -277,16 +282,17 @@ begin CARRYINSELREG => 0, CREG => 0, INMODEREG => 0, + MREG => 0, OPMODEREG => 0, - PREG => 0 + PREG => 1 ) port map ( - A => "0000000000000" & m_in.data1(39 downto 23), + A => 6x"0" & m_in.data1(47 downto 24), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(16 downto 0), BCIN => (others => '0'), - C => x"000" & "00" & m01_p(39 downto 6), + C => (others => '0'), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -301,15 +307,16 @@ begin CECTRL => '0', CED => '0', CEINMODE => '0', - CEM => m_in.valid, - CEP => '0', + CEM => '0', + CEP => m_in.valid, CLK => clk, D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0110101", + OPMODE => "0000101", P => m10_p, PCIN => (others => '0'), + PCOUT => m10_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -333,16 +340,17 @@ begin CARRYINSELREG => 0, CREG => 0, INMODEREG => 0, + MREG => 1, OPMODEREG => 0, PREG => 0 ) port map ( - A => "0000000000000" & m_in.data1(39 downto 23), + A => 6x"0" & m_in.data1(47 downto 24), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(33 downto 17), BCIN => (others => '0'), - C => x"000" & "00" & m02_p(39 downto 6), + C => (others => '0'), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -363,10 +371,9 @@ begin D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0110101", + OPMODE => "1010101", P => m11_p, - PCIN => (others => '0'), - PCOUT => m11_pc, + PCIN => m10_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -390,16 +397,17 @@ begin CARRYINSELREG => 0, CREG => 0, INMODEREG => 0, + MREG => 0, OPMODEREG => 0, - PREG => 0 + PREG => 1 ) port map ( - A => "0000000000000" & m_in.data1(39 downto 23), + A => 6x"0" & m_in.data1(47 downto 24), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(50 downto 34), BCIN => (others => '0'), - C => x"0000" & '0' & m03_p(36 downto 6), + C => 24x"0" & addend(81 downto 58), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -414,8 +422,8 @@ begin CECTRL => '0', CED => '0', CEINMODE => '0', - CEM => m_in.valid, - CEP => '0', + CEM => '0', + CEP => m_in.valid, CLK => clk, D => (others => '0'), INMODE => "00000", @@ -445,17 +453,19 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 1, OPMODEREG => 0, PREG => 0 ) port map ( - A => "0000000000000" & m_in.data1(39 downto 23), + A => 6x"0" & m_in.data1(47 downto 24), ACIN => (others => '0'), ALUMODE => "0000", B => "00000" & m_in.data2(63 downto 51), BCIN => (others => '0'), - C => x"0000000" & "000" & addend(90 downto 74), + C => (others => '0'), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -465,7 +475,7 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', @@ -476,10 +486,9 @@ begin D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0110101", + OPMODE => "1010101", P => m13_p, - PCIN => (others => '0'), - PCOUT => m13_pc, + PCIN => m12_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -501,12 +510,14 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 0, OPMODEREG => 0, - PREG => 0 + PREG => 1 ) port map ( - A => "000000" & m_in.data1(63 downto 40), + A => 14x"0" & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(16 downto 0), @@ -521,20 +532,21 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', CEINMODE => '0', - CEM => m_in.valid, - CEP => '0', + CEM => '0', + CEP => m_in.valid, CLK => clk, D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0010101", + OPMODE => "0000101", P => m20_p, - PCIN => m11_pc, + PCIN => (others => '0'), + PCOUT => m20_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -556,12 +568,14 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 1, OPMODEREG => 0, PREG => 0 ) port map ( - A => "000000" & m_in.data1(63 downto 40), + A => 14x"0" & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(33 downto 17), @@ -576,7 +590,7 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', @@ -587,9 +601,9 @@ begin D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0010101", + OPMODE => "1010101", P => m21_p, - PCIN => m12_pc, + PCIN => m20_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -611,17 +625,19 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 0, OPMODEREG => 0, - PREG => 0 + PREG => 1 ) port map ( - A => "000000" & m_in.data1(63 downto 40), + A => 14x"0" & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(50 downto 34), BCIN => (others => '0'), - C => (others => '0'), + C => "00" & addend(127 downto 82), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -631,20 +647,21 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', CEINMODE => '0', - CEM => m_in.valid, - CEP => '0', + CEM => '0', + CEP => m_in.valid, CLK => clk, D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0010101", + OPMODE => "0110101", P => m22_p, - PCIN => m13_pc, + PCIN => (others => '0'), + PCOUT => m22_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -666,17 +683,19 @@ begin BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, + CREG => 0, INMODEREG => 0, + MREG => 1, OPMODEREG => 0, PREG => 0 ) port map ( - A => "000000" & m_in.data1(63 downto 40), + A => 14x"0" & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => "00000" & m_in.data2(63 downto 51), BCIN => (others => '0'), - C => x"00" & "000" & addend(127 downto 91), + C => (others => '0'), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -686,7 +705,7 @@ begin CEALUMODE => '0', CEB1 => '0', CEB2 => '0', - CEC => '1', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', @@ -697,9 +716,9 @@ begin D => (others => '0'), INMODE => "00000", MULTSIGNIN => '0', - OPMODE => "0110101", + OPMODE => "1010101", P => m23_p, - PCIN => (others => '0'), + PCIN => m22_pc, RSTA => '0', RSTALLCARRYIN => '0', RSTALUMODE => '0', @@ -712,6 +731,17 @@ begin RSTP => '0' ); + pp0 <= std_ulogic_vector(resize(signed(m13_p(37 downto 0) & m12_p(16 downto 0) & + m01_p(40 downto 0) & m00_p(16 downto 0)), 128)); + pp1 <= m23_p(28 downto 0) & m22_p(16 downto 0) & m11_p(40 downto 0) & m10_p(16 downto 0) & 24x"0"; + -- pp2 <= std_ulogic_vector(resize(signed(m03_p(37 downto 0) & m02_p(16 downto 0) & 34x"0"), 128)); + -- pp3 <= std_ulogic_vector(resize(signed(m21_p(34 downto 0) & m20_p(16 downto 0) & 48x"0"), 128)); + + pp23 <= std_ulogic_vector(resize(resize(signed(m03_p(37 downto 0) & m02_p(16 downto 0) & 34x"0"), 100) + + signed(m21_p(34 downto 0) & m20_p(16 downto 0) & 48x"0"), 128)); + + sumlo <= std_ulogic_vector(unsigned('0' & pp0(31 downto 24)) + unsigned('0' & pp1(31 downto 24))); + s0: DSP48E1 generic map ( ACASCREG => 0, @@ -725,16 +755,16 @@ begin INMODEREG => 0, MREG => 0, OPMODEREG => 0, - PREG => 1, + PREG => 0, USE_MULT => "none" ) port map ( - A => m22_p(5 downto 0) & x"0000" & m10_p(34 downto 27), + A => pp0(79 downto 50), ACIN => (others => '0'), ALUMODE => "0000", - B => m10_p(26 downto 9), + B => pp0(49 downto 32), BCIN => (others => '0'), - C => m20_p(39 downto 0) & m02_p(5 downto 0) & "00", + C => pp1(79 downto 32), CARRYCASCIN => '0', CARRYIN => '0', CARRYINSEL => "000", @@ -751,7 +781,7 @@ begin CED => '0', CEINMODE => '0', CEM => '0', - CEP => valid_1, + CEP => '0', CLK => clk, D => (others => '0'), INMODE => "00000", @@ -773,43 +803,43 @@ begin s1: DSP48E1 generic map ( - ACASCREG => 1, + ACASCREG => 0, ALUMODEREG => 0, - AREG => 1, - BCASCREG => 1, - BREG => 1, + AREG => 0, + BCASCREG => 0, + BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, - CREG => 1, + CREG => 0, INMODEREG => 0, MREG => 0, OPMODEREG => 0, - PREG => 0, + PREG => 1, USE_MULT => "none" ) port map ( - A => x"000" & m22_p(41 downto 24), + A => pp0(127 downto 98), ACIN => (others => '0'), ALUMODE => "0000", - B => m22_p(23 downto 6), + B => pp0(97 downto 80), BCIN => (others => '0'), - C => m23_p(36 downto 0) & x"00" & "0" & m20_p(41 downto 40), + C => pp1(127 downto 80), CARRYCASCIN => '0', CARRYIN => s0_carry(3), CARRYINSEL => "000", CEA1 => '0', - CEA2 => valid_1, + CEA2 => '0', CEAD => '0', CEALUMODE => '0', CEB1 => '0', - CEB2 => valid_1, - CEC => valid_1, + CEB2 => '0', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', CEINMODE => '0', CEM => '0', - CEP => '0', + CEP => valid_1, CLK => clk, D => (others => '0'), INMODE => "00000", @@ -829,52 +859,48 @@ begin RSTP => '0' ); - -- mask is 0 for 32-bit ops, 0x0000ffffffff for 64-bit - p0_mask(47 downto 31) <= (others => '0'); - p0_mask(30 downto 0) <= (others => not r32_1); - p0: DSP48E1 generic map ( - ACASCREG => 1, - ALUMODEREG => 1, - AREG => 1, - BCASCREG => 1, - BREG => 1, + ACASCREG => 0, + ALUMODEREG => 0, + AREG => 0, + BCASCREG => 0, + BREG => 0, CARRYINREG => 0, CARRYINSELREG => 0, - CREG => 1, + CREG => 0, INMODEREG => 0, + MASK => x"00007fffffff", MREG => 0, OPMODEREG => 0, - PREG => 0, - SEL_MASK => "C", + PREG => 1, USE_MULT => "none", USE_PATTERN_DETECT => "PATDET" ) port map ( - A => m21_p(22 downto 0) & m03_p(5 downto 0) & '0', + A => pp23(79 downto 50), ACIN => (others => '0'), ALUMODE => "00" & rnot_1 & '0', - B => (others => '0'), + B => pp23(49 downto 32), BCIN => (others => '0'), - C => p0_mask, + C => (others => '0'), CARRYCASCIN => '0', - CARRYIN => '0', + CARRYIN => sumlo(8), CARRYINSEL => "000", CARRYOUT => p0_carry, CEA1 => '0', - CEA2 => valid_1, + CEA2 => '0', CEAD => '0', - CEALUMODE => valid_1, + CEALUMODE => '0', CEB1 => '0', - CEB2 => valid_1, - CEC => valid_1, + CEB2 => '0', + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0', CEINMODE => '0', CEM => '0', - CEP => '0', + CEP => valid_1, CLK => clk, D => (others => '0'), INMODE => "00000", @@ -915,10 +941,10 @@ begin USE_PATTERN_DETECT => "PATDET" ) port map ( - A => x"0000000" & '0' & m21_p(41), + A => pp23(127 downto 98), ACIN => (others => '0'), ALUMODE => "00" & rnot_1 & '0', - B => m21_p(40 downto 23), + B => pp23(97 downto 80), BCIN => (others => '0'), C => (others => '0'), CARRYCASCIN => '0', @@ -930,7 +956,7 @@ begin CEALUMODE => valid_1, CEB1 => '0', CEB2 => valid_1, - CEC => '0', + CEC => valid_1, CECARRYIN => '0', CECTRL => '0', CED => '0', @@ -958,39 +984,26 @@ begin RSTP => '0' ); - mult_out: process(all) - variable ov : std_ulogic; - begin - -- set overflow if the high bits are neither all zeroes nor all ones - if req_32bit = '0' then - ov := not ((p1_pat and p0_pat) or (p1_patb and p0_patb)); - else - ov := not ((p1_pat and p0_pat and not product(31)) or - (p1_patb and p0_patb and product(31))); - end if; - ovf_in <= ov; - - m_out.result <= product; - m_out.overflow <= overflow; - end process; - process(clk) begin if rising_edge(clk) then - if rnot_1 = '0' then - product(31 downto 0) <= m10_p(8 downto 0) & m01_p(5 downto 0) & m00_p(16 downto 0); - else - product(31 downto 0) <= not (m10_p(8 downto 0) & m01_p(5 downto 0) & m00_p(16 downto 0)); + if valid_1 = '1' then + if rnot_1 = '0' then + product(31 downto 0) <= sumlo(7 downto 0) & pp0(23 downto 0); + else + product(31 downto 0) <= not (sumlo(7 downto 0) & pp0(23 downto 0)); + end if; end if; m_out.valid <= valid_1; valid_1 <= m_in.valid; - req_32bit <= r32_1; - r32_1 <= m_in.is_32bit; rnot_1 <= m_in.not_result; - overflow <= ovf_in; + overflow <= not ((p1_pat and p0_pat) or (p1_patb and p0_patb)); end if; end process; + m_out.result <= product; + m_out.overflow <= overflow; + end architecture behaviour; library ieee; From e02d8060edaa0300f14a695895f4a0b622e0351a Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Mon, 8 Aug 2022 22:26:39 +1000 Subject: [PATCH 19/22] Change the multiplier interface to support signed multipliers This adds an 'is_signed' signal to MultiplyInputType to indicate whether the data1 and data2 fields are to be interpreted as signed or unsigned numbers. The 'not_result' field is replaced by a 'subtract' field which provides a more intuitive interface for requesting that the product be subtracted from the addend rather than added, i.e. subtract = 1 gives C - A * B, vs. subtract = 0 giving C + A * B. (Previously the users of the multipliers got the same effect by complementing the addend and setting not_result = 1.) The is_32bit field is removed because it is no longer used now that we have a separate 32-bit multiplier. Signed-off-by: Paul Mackerras --- common.vhdl | 9 ++++----- execute1.vhdl | 44 ++++++++++++++++++++------------------------ fpu.vhdl | 10 +++------- multiply-32s.vhdl | 3 ++- multiply.vhdl | 29 ++++++++++++----------------- xilinx-mult-32s.vhdl | 8 +++++--- xilinx-mult.vhdl | 22 +++++++++++++--------- 7 files changed, 59 insertions(+), 66 deletions(-) diff --git a/common.vhdl b/common.vhdl index 6287be5..7c7a8d5 100644 --- a/common.vhdl +++ b/common.vhdl @@ -385,12 +385,11 @@ package common is data1: std_ulogic_vector(63 downto 0); data2: std_ulogic_vector(63 downto 0); addend: std_ulogic_vector(127 downto 0); - is_32bit: std_ulogic; - not_result: std_ulogic; + is_signed: std_ulogic; + subtract: std_ulogic; -- 0 => addend + data1 * data2, 1 => addend - data1 * data2 end record; - constant MultiplyInputInit : MultiplyInputType := (valid => '0', - is_32bit => '0', not_result => '0', - others => (others => '0')); + constant MultiplyInputInit : MultiplyInputType := (data1 => 64x"0", data2 => 64x"0", + addend => 128x"0", others => '0'); type MultiplyOutputType is record valid: std_ulogic; diff --git a/execute1.vhdl b/execute1.vhdl index 948bdd6..721d493 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -695,7 +695,22 @@ begin overflow_32 <= calc_ov(a_inv(31), b_in(31), carry_32, sum_with_carry(31)); overflow_64 <= calc_ov(a_inv(63), b_in(63), carry_64, sum_with_carry(63)); - -- signals to multiply and divide units + -- signals to multiplier + addend := (others => '0'); + if e_in.reg_valid3 = '1' then + -- integer multiply-add, major op 4 (if it is a multiply) + addend(63 downto 0) := c_in; + if e_in.is_signed = '1' then + addend(127 downto 64) := (others => c_in(63)); + end if; + end if; + x_to_multiply.data1 <= std_ulogic_vector(a_in); + x_to_multiply.data2 <= std_ulogic_vector(b_in); + x_to_multiply.is_signed <= e_in.is_signed; + x_to_multiply.subtract <= '0'; + x_to_multiply.addend <= addend; + + -- Interface to divide unit sign1 := '0'; sign2 := '0'; if e_in.is_signed = '1' then @@ -719,7 +734,6 @@ begin abs2 := - signed(b_in); end if; - -- Interface to multiply and divide units x_to_divider.is_signed <= e_in.is_signed; x_to_divider.is_32bit <= e_in.is_32bit; x_to_divider.is_extended <= '0'; @@ -728,24 +742,6 @@ begin x_to_divider.is_modulus <= '1'; end if; x_to_divider.flush <= flush_in; - - addend := (others => '0'); - if e_in.reg_valid3 = '1' then - -- integer multiply-add, major op 4 (if it is a multiply) - addend(63 downto 0) := c_in; - if e_in.is_signed = '1' then - addend(127 downto 64) := (others => c_in(63)); - end if; - end if; - if (sign1 xor sign2) = '1' then - addend := not addend; - end if; - - x_to_multiply.data1 <= std_ulogic_vector(abs1); - x_to_multiply.data2 <= std_ulogic_vector(abs2); - x_to_multiply.is_32bit <= e_in.is_32bit; - x_to_multiply.not_result <= sign1 xor sign2; - x_to_multiply.addend <= addend; x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus); if e_in.is_32bit = '0' then -- 64-bit forms @@ -766,11 +762,11 @@ begin end if; -- signals to 32-bit multiplier - x_to_mult_32s.data1 <= 31x"0" & (a_in(31) and e_in.is_signed) & a_in(31 downto 0); - x_to_mult_32s.data2 <= 31x"0" & (b_in(31) and e_in.is_signed) & b_in(31 downto 0); + x_to_mult_32s.data1 <= 32x"0" & a_in(31 downto 0); + x_to_mult_32s.data2 <= 32x"0" & b_in(31 downto 0); + x_to_mult_32s.is_signed <= e_in.is_signed; -- The following are unused, but set here to avoid X states - x_to_mult_32s.is_32bit <= '1'; - x_to_mult_32s.not_result <= '0'; + x_to_mult_32s.subtract <= '0'; x_to_mult_32s.addend <= (others => '0'); shortmul_result <= std_ulogic_vector(resize(signed(mshort_p), 64)); diff --git a/fpu.vhdl b/fpu.vhdl index 417a318..eaa4cf2 100644 --- a/fpu.vhdl +++ b/fpu.vhdl @@ -1071,7 +1071,7 @@ begin set_b_mant := '0'; set_c := '0'; set_s := '0'; - f_to_multiply.is_32bit <= '0'; + f_to_multiply.is_signed <= '0'; f_to_multiply.valid <= '0'; msel_1 <= MUL1_A; msel_2 <= MUL2_C; @@ -3227,12 +3227,8 @@ begin maddend(UNIT_BIT - 1 downto 0) := r.s; when others => end case; - if msel_inv = '1' then - f_to_multiply.addend <= not maddend; - else - f_to_multiply.addend <= maddend; - end if; - f_to_multiply.not_result <= msel_inv; + f_to_multiply.addend <= maddend; + f_to_multiply.subtract <= msel_inv; if set_y = '1' then v.y := f_to_multiply.data2; end if; diff --git a/multiply-32s.vhdl b/multiply-32s.vhdl index 0639dbf..ea3e2a8 100644 --- a/multiply-32s.vhdl +++ b/multiply-32s.vhdl @@ -40,7 +40,8 @@ begin variable ov : std_ulogic; begin v.valid := m_in.valid; - v.data := signed(m_in.data1(32 downto 0)) * signed(m_in.data2(32 downto 0)); + v.data := signed((m_in.is_signed and m_in.data1(31)) & m_in.data1(31 downto 0)) * + signed((m_in.is_signed and m_in.data2(31)) & m_in.data2(31 downto 0)); d := std_ulogic_vector(r.data(63 downto 0)); diff --git a/multiply.vhdl b/multiply.vhdl index c09fc22..615ceea 100644 --- a/multiply.vhdl +++ b/multiply.vhdl @@ -7,7 +7,7 @@ use work.common.all; entity multiply is generic ( - PIPELINE_DEPTH : natural := 4 + PIPELINE_DEPTH : natural := 3 ); port ( clk : in std_logic; @@ -23,11 +23,8 @@ architecture behaviour of multiply is type multiply_pipeline_stage is record valid : std_ulogic; data : unsigned(127 downto 0); - is_32bit : std_ulogic; - not_res : std_ulogic; end record; constant MultiplyPipelineStageInit : multiply_pipeline_stage := (valid => '0', - is_32bit => '0', not_res => '0', data => (others => '0')); type multiply_pipeline_type is array(0 to PIPELINE_DEPTH-1) of multiply_pipeline_stage; @@ -52,31 +49,29 @@ begin multiply_1: process(all) variable v : reg_type; + variable a, b : std_ulogic_vector(64 downto 0); + variable prod : std_ulogic_vector(129 downto 0); variable d : std_ulogic_vector(127 downto 0); variable d2 : std_ulogic_vector(63 downto 0); variable ov : std_ulogic; begin v := r; + a := (m.is_signed and m.data1(63)) & m.data1; + b := (m.is_signed and m.data2(63)) & m.data2; + prod := std_ulogic_vector(signed(a) * signed(b)); v.multiply_pipeline(0).valid := m.valid; - v.multiply_pipeline(0).data := (unsigned(m.data1) * unsigned(m.data2)) + unsigned(m.addend); - v.multiply_pipeline(0).is_32bit := m.is_32bit; - v.multiply_pipeline(0).not_res := m.not_result; + if m.subtract = '1' then + v.multiply_pipeline(0).data := unsigned(m.addend) - unsigned(prod(127 downto 0)); + else + v.multiply_pipeline(0).data := unsigned(m.addend) + unsigned(prod(127 downto 0)); + end if; loop_0: for i in 1 to PIPELINE_DEPTH-1 loop v.multiply_pipeline(i) := r.multiply_pipeline(i-1); end loop; d := std_ulogic_vector(v.multiply_pipeline(PIPELINE_DEPTH-1).data); - if v.multiply_pipeline(PIPELINE_DEPTH-1).not_res = '1' then - d := not d; - end if; - - ov := '0'; - if v.multiply_pipeline(PIPELINE_DEPTH-1).is_32bit = '1' then - ov := (or d(63 downto 31)) and not (and d(63 downto 31)); - else - ov := (or d(127 downto 63)) and not (and d(127 downto 63)); - end if; + ov := (or d(127 downto 63)) and not (and d(127 downto 63)); ovf_in <= ov; m_out.result <= d; diff --git a/xilinx-mult-32s.vhdl b/xilinx-mult-32s.vhdl index fde19ae..cacc22d 100644 --- a/xilinx-mult-32s.vhdl +++ b/xilinx-mult-32s.vhdl @@ -33,9 +33,11 @@ architecture behaviour of multiply_32s is signal product_lo : std_ulogic_vector(22 downto 0); begin - -- sign extend - data1 <= std_ulogic_vector(resize(signed(m_in.data1(32 downto 0)), 53)); - data2 <= std_ulogic_vector(resize(signed(m_in.data2(32 downto 0)), 35)); + -- sign extend if signed + data1(31 downto 0) <= m_in.data1(31 downto 0); + data1(52 downto 32) <= (others => m_in.is_signed and m_in.data1(31)); + data2(31 downto 0) <= m_in.data2(31 downto 0); + data2(34 downto 32) <= (others => m_in.is_signed and m_in.data2(31)); clocken <= m_in.valid and not stall; diff --git a/xilinx-mult.vhdl b/xilinx-mult.vhdl index 608810e..26ba5d7 100644 --- a/xilinx-mult.vhdl +++ b/xilinx-mult.vhdl @@ -18,6 +18,8 @@ entity multiply is end entity multiply; architecture behaviour of multiply is + signal d1sign : std_ulogic_vector(13 downto 0); + signal d2sign : std_ulogic_vector(4 downto 0); signal m00_p, m01_p, m02_p, m03_p : std_ulogic_vector(47 downto 0); signal m00_pc, m02_pc : std_ulogic_vector(47 downto 0); signal m10_p, m11_p, m12_p, m13_p : std_ulogic_vector(47 downto 0); @@ -39,7 +41,9 @@ architecture behaviour of multiply is signal overflow : std_ulogic; begin - addend <= m_in.addend; + addend <= m_in.addend when m_in.subtract = '0' else not m_in.addend; + d1sign <= (others => m_in.data1(63) and m_in.is_signed); + d2sign <= (others => m_in.data2(63) and m_in.is_signed); m00: DSP48E1 generic map ( @@ -233,7 +237,7 @@ begin A => 6x"0" & m_in.data1(23 downto 0), ACIN => (others => '0'), ALUMODE => "0000", - B => "00000" & m_in.data2(63 downto 51), + B => d2sign & m_in.data2(63 downto 51), BCIN => (others => '0'), C => (others => '0'), CARRYCASCIN => '0', @@ -463,7 +467,7 @@ begin A => 6x"0" & m_in.data1(47 downto 24), ACIN => (others => '0'), ALUMODE => "0000", - B => "00000" & m_in.data2(63 downto 51), + B => d2sign & m_in.data2(63 downto 51), BCIN => (others => '0'), C => (others => '0'), CARRYCASCIN => '0', @@ -517,7 +521,7 @@ begin PREG => 1 ) port map ( - A => 14x"0" & m_in.data1(63 downto 48), + A => d1sign & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(16 downto 0), @@ -575,7 +579,7 @@ begin PREG => 0 ) port map ( - A => 14x"0" & m_in.data1(63 downto 48), + A => d1sign & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(33 downto 17), @@ -632,7 +636,7 @@ begin PREG => 1 ) port map ( - A => 14x"0" & m_in.data1(63 downto 48), + A => d1sign & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", B => '0' & m_in.data2(50 downto 34), @@ -690,10 +694,10 @@ begin PREG => 0 ) port map ( - A => 14x"0" & m_in.data1(63 downto 48), + A => d1sign & m_in.data1(63 downto 48), ACIN => (others => '0'), ALUMODE => "0000", - B => "00000" & m_in.data2(63 downto 51), + B => d2sign & m_in.data2(63 downto 51), BCIN => (others => '0'), C => (others => '0'), CARRYCASCIN => '0', @@ -996,7 +1000,7 @@ begin end if; m_out.valid <= valid_1; valid_1 <= m_in.valid; - rnot_1 <= m_in.not_result; + rnot_1 <= m_in.subtract; overflow <= not ((p1_pat and p0_pat) or (p1_patb and p0_patb)); end if; end process; From d1e8e62feee3e2d2d01a69f1486e8099e8438b31 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 19 Jul 2022 12:29:47 +1000 Subject: [PATCH 20/22] Remove option for "short" 16x16 bit multiplier Now that we have a 33 bit x 33 bit signed multiplier in execute1, there is really no need for the 16 bit multiplier. The coremark results are just as good without it as with it. This removes the option for the sake of simplicity. Signed-off-by: Paul Mackerras --- core.vhdl | 2 -- execute1.vhdl | 19 ------------------- fpga/top-arty.vhdl | 2 -- fpga/top-generic.vhdl | 2 -- fpga/top-nexys-video.vhdl | 2 -- fpga/top-orangecrab0.2.vhdl | 1 - fpga/top-wukong-v2.vhdl | 2 -- microwatt.core | 14 -------------- soc.vhdl | 2 -- 9 files changed, 46 deletions(-) diff --git a/core.vhdl b/core.vhdl index d7036f1..aef2d7f 100644 --- a/core.vhdl +++ b/core.vhdl @@ -13,7 +13,6 @@ entity core is EX1_BYPASS : boolean := true; HAS_FPU : boolean := true; HAS_BTC : boolean := true; - HAS_SHORT_MULT : boolean := false; ALT_RESET_ADDRESS : std_ulogic_vector(63 downto 0) := (others => '0'); LOG_LENGTH : natural := 512; ICACHE_NUM_LINES : natural := 64; @@ -366,7 +365,6 @@ begin SIM => SIM, EX1_BYPASS => EX1_BYPASS, HAS_FPU => HAS_FPU, - HAS_SHORT_MULT => HAS_SHORT_MULT, LOG_LENGTH => LOG_LENGTH ) port map ( diff --git a/execute1.vhdl b/execute1.vhdl index 721d493..a8fd052 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -15,7 +15,6 @@ entity execute1 is SIM : boolean := false; EX1_BYPASS : boolean := true; HAS_FPU : boolean := true; - HAS_SHORT_MULT : boolean := false; -- Non-zero to enable log data collection LOG_LENGTH : natural := 0 ); @@ -448,17 +447,6 @@ begin p_out => pmu_to_x ); - short_mult_0: if HAS_SHORT_MULT generate - begin - short_mult: entity work.short_multiply - port map ( - clk => clk, - a_in => a_in(15 downto 0), - b_in => b_in(15 downto 0), - m_out => mshort_p - ); - end generate; - dbg_ctrl_out <= ctrl; log_rd_addr <= ex2.log_addr_spr; @@ -1288,13 +1276,6 @@ begin v.se.mult_32s := '1'; v.res2_sel := "00"; slow_op := '1'; - elsif HAS_SHORT_MULT and e_in.reg_valid3 = '0' and - fits_in_n_bits(a_in, 16) and fits_in_n_bits(b_in, 16) then - -- Operands fit into 16 bits, so use short multiplier - if e_in.oe = '1' then - -- Note 16x16 multiply can't overflow, even for mullwo - set_ov(v.e, '0', '0'); - end if; else -- Use standard multiplier v.start_mul := '1'; diff --git a/fpga/top-arty.vhdl b/fpga/top-arty.vhdl index 0c5822f..ecdd5d4 100644 --- a/fpga/top-arty.vhdl +++ b/fpga/top-arty.vhdl @@ -16,7 +16,6 @@ entity toplevel is CLK_FREQUENCY : positive := 100000000; HAS_FPU : boolean := true; HAS_BTC : boolean := true; - HAS_SHORT_MULT : boolean := false; USE_LITEDRAM : boolean := false; NO_BRAM : boolean := false; DISABLE_FLATTEN_CORE : boolean := false; @@ -199,7 +198,6 @@ begin CLK_FREQ => CLK_FREQUENCY, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, - HAS_SHORT_MULT => HAS_SHORT_MULT, HAS_DRAM => USE_LITEDRAM, DRAM_SIZE => 256 * 1024 * 1024, DRAM_INIT_SIZE => PAYLOAD_SIZE, diff --git a/fpga/top-generic.vhdl b/fpga/top-generic.vhdl index da42bb5..c75e465 100644 --- a/fpga/top-generic.vhdl +++ b/fpga/top-generic.vhdl @@ -13,7 +13,6 @@ entity toplevel is CLK_FREQUENCY : positive := 100000000; HAS_FPU : boolean := true; HAS_BTC : boolean := false; - HAS_SHORT_MULT: boolean := false; ICACHE_NUM_LINES : natural := 64; LOG_LENGTH : natural := 512; DISABLE_FLATTEN_CORE : boolean := false; @@ -75,7 +74,6 @@ begin CLK_FREQ => CLK_FREQUENCY, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, - HAS_SHORT_MULT => HAS_SHORT_MULT, ICACHE_NUM_LINES => ICACHE_NUM_LINES, LOG_LENGTH => LOG_LENGTH, DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE, diff --git a/fpga/top-nexys-video.vhdl b/fpga/top-nexys-video.vhdl index 3dd9998..beb4045 100644 --- a/fpga/top-nexys-video.vhdl +++ b/fpga/top-nexys-video.vhdl @@ -16,7 +16,6 @@ entity toplevel is CLK_FREQUENCY : positive := 100000000; HAS_FPU : boolean := true; HAS_BTC : boolean := true; - HAS_SHORT_MULT: boolean := false; USE_LITEDRAM : boolean := false; NO_BRAM : boolean := false; DISABLE_FLATTEN_CORE : boolean := false; @@ -175,7 +174,6 @@ begin CLK_FREQ => CLK_FREQUENCY, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, - HAS_SHORT_MULT=> HAS_SHORT_MULT, HAS_DRAM => USE_LITEDRAM, DRAM_SIZE => 512 * 1024 * 1024, DRAM_INIT_SIZE => PAYLOAD_SIZE, diff --git a/fpga/top-orangecrab0.2.vhdl b/fpga/top-orangecrab0.2.vhdl index e3e9c80..ada940c 100644 --- a/fpga/top-orangecrab0.2.vhdl +++ b/fpga/top-orangecrab0.2.vhdl @@ -188,7 +188,6 @@ begin HAS_UART1 => HAS_UART1, HAS_SD_CARD => USE_LITESDCARD, ICACHE_NUM_LINES => ICACHE_NUM_LINES, - HAS_SHORT_MULT => true, NGPIO => NGPIO ) port map ( diff --git a/fpga/top-wukong-v2.vhdl b/fpga/top-wukong-v2.vhdl index d2a23ab..d3f7bd8 100644 --- a/fpga/top-wukong-v2.vhdl +++ b/fpga/top-wukong-v2.vhdl @@ -16,7 +16,6 @@ entity toplevel is CLK_FREQUENCY : positive := 100000000; HAS_FPU : boolean := true; HAS_BTC : boolean := true; - HAS_SHORT_MULT : boolean := false; USE_LITEDRAM : boolean := false; NO_BRAM : boolean := false; DISABLE_FLATTEN_CORE : boolean := false; @@ -175,7 +174,6 @@ begin CLK_FREQ => CLK_FREQUENCY, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, - HAS_SHORT_MULT => HAS_SHORT_MULT, HAS_DRAM => USE_LITEDRAM, DRAM_SIZE => 256 * 1024 * 1024, DRAM_INIT_SIZE => PAYLOAD_SIZE, diff --git a/microwatt.core b/microwatt.core index b817901..07085b1 100644 --- a/microwatt.core +++ b/microwatt.core @@ -146,7 +146,6 @@ targets: - uart_is_16550 - has_fpu - has_btc - - has_short_mult tools: vivado: {part : xc7a100tcsg324-1} toplevel : toplevel @@ -252,7 +251,6 @@ targets: - uart_is_16550 - has_fpu - has_btc - - has_short_mult generate: [litedram_nexys_video, liteeth_nexys_video, litesdcard_nexys_video] tools: vivado: {part : xc7a200tsbg484-1} @@ -273,7 +271,6 @@ targets: - has_uart1 - has_fpu=false - has_btc=false - - has_short_mult - use_litesdcard tools: vivado: {part : xc7a35ticsg324-1L} @@ -296,7 +293,6 @@ targets: - has_uart1 - has_fpu=false - has_btc=false - - has_short_mult generate: [litedram_arty, liteeth_arty, litesdcard_arty] tools: vivado: {part : xc7a35ticsg324-1L} @@ -317,7 +313,6 @@ targets: - has_uart1 - has_fpu - has_btc - - has_short_mult - use_litesdcard tools: vivado: {part : xc7a100ticsg324-1L} @@ -340,7 +335,6 @@ targets: - has_uart1 - has_fpu - has_btc - - has_short_mult generate: [litedram_arty, liteeth_arty, litesdcard_arty] tools: vivado: {part : xc7a100ticsg324-1L} @@ -362,7 +356,6 @@ targets: - uart_is_16550 - has_fpu - has_btc - - has_short_mult generate: [litesdcard_wukong-v2] tools: vivado: {part : xc7a100tfgg676-1} @@ -384,7 +377,6 @@ targets: - uart_is_16550 - has_fpu - has_btc - - has_short_mult generate: [litedram_wukong-v2, liteeth_wukong-v2, litesdcard_wukong-v2] tools: vivado: {part : xc7a100tfgg676-1} @@ -500,12 +492,6 @@ parameters: paramtype : generic default : true - has_short_mult: - datatype : bool - description : Include a 16 bit x 16 bit single-cycle multiplier in the core - paramtype : generic - default : false - disable_flatten_core: datatype : bool description : Prevent Vivado from flattening the main core components diff --git a/soc.vhdl b/soc.vhdl index 6842473..7daca5f 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -59,7 +59,6 @@ entity soc is SIM : boolean; HAS_FPU : boolean := true; HAS_BTC : boolean := true; - HAS_SHORT_MULT : boolean := false; DISABLE_FLATTEN_CORE : boolean := false; ALT_RESET_ADDRESS : std_logic_vector(63 downto 0) := (23 downto 0 => '0', others => '1'); HAS_DRAM : boolean := false; @@ -335,7 +334,6 @@ begin SIM => SIM, HAS_FPU => HAS_FPU, HAS_BTC => HAS_BTC, - HAS_SHORT_MULT => HAS_SHORT_MULT, DISABLE_FLATTEN => DISABLE_FLATTEN_CORE, ALT_RESET_ADDRESS => ALT_RESET_ADDRESS, LOG_LENGTH => LOG_LENGTH, From b0aa5340b82a59d345db50b02b598e8da8add88e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 10 Aug 2022 11:33:10 +1000 Subject: [PATCH 21/22] execute1: Make it clear that divide logic is not included when HAS_FPU=true This adds a "not HAS_FPU" condition in a few places to make it obvious that logic to interface to the divide unit is not included when we have an FPU. Signed-off-by: Paul Mackerras --- execute1.vhdl | 88 ++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/execute1.vhdl b/execute1.vhdl index a8fd052..2d6af00 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -699,54 +699,56 @@ begin x_to_multiply.addend <= addend; -- Interface to divide unit - sign1 := '0'; - sign2 := '0'; - if e_in.is_signed = '1' then - if e_in.is_32bit = '1' then - sign1 := a_in(31); - sign2 := b_in(31); + if not HAS_FPU then + sign1 := '0'; + sign2 := '0'; + if e_in.is_signed = '1' then + if e_in.is_32bit = '1' then + sign1 := a_in(31); + sign2 := b_in(31); + else + sign1 := a_in(63); + sign2 := b_in(63); + end if; + end if; + -- take absolute values + if sign1 = '0' then + abs1 := signed(a_in); else - sign1 := a_in(63); - sign2 := b_in(63); + abs1 := - signed(a_in); end if; - end if; - -- take absolute values - if sign1 = '0' then - abs1 := signed(a_in); - else - abs1 := - signed(a_in); - end if; - if sign2 = '0' then - abs2 := signed(b_in); - else - abs2 := - signed(b_in); - end if; - - x_to_divider.is_signed <= e_in.is_signed; - x_to_divider.is_32bit <= e_in.is_32bit; - x_to_divider.is_extended <= '0'; - x_to_divider.is_modulus <= '0'; - if e_in.insn_type = OP_MOD then - x_to_divider.is_modulus <= '1'; - end if; - x_to_divider.flush <= flush_in; - x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus); - if e_in.is_32bit = '0' then - -- 64-bit forms - if e_in.insn_type = OP_DIVE then - x_to_divider.is_extended <= '1'; + if sign2 = '0' then + abs2 := signed(b_in); + else + abs2 := - signed(b_in); end if; - x_to_divider.dividend <= std_ulogic_vector(abs1); - x_to_divider.divisor <= std_ulogic_vector(abs2); - else - -- 32-bit forms + + x_to_divider.is_signed <= e_in.is_signed; + x_to_divider.is_32bit <= e_in.is_32bit; x_to_divider.is_extended <= '0'; - if e_in.insn_type = OP_DIVE then -- extended forms - x_to_divider.dividend <= std_ulogic_vector(abs1(31 downto 0)) & x"00000000"; + x_to_divider.is_modulus <= '0'; + if e_in.insn_type = OP_MOD then + x_to_divider.is_modulus <= '1'; + end if; + x_to_divider.flush <= flush_in; + x_to_divider.neg_result <= sign1 xor (sign2 and not x_to_divider.is_modulus); + if e_in.is_32bit = '0' then + -- 64-bit forms + if e_in.insn_type = OP_DIVE then + x_to_divider.is_extended <= '1'; + end if; + x_to_divider.dividend <= std_ulogic_vector(abs1); + x_to_divider.divisor <= std_ulogic_vector(abs2); else - x_to_divider.dividend <= x"00000000" & std_ulogic_vector(abs1(31 downto 0)); + -- 32-bit forms + x_to_divider.is_extended <= '0'; + if e_in.insn_type = OP_DIVE then -- extended forms + x_to_divider.dividend <= std_ulogic_vector(abs1(31 downto 0)) & x"00000000"; + else + x_to_divider.dividend <= x"00000000" & std_ulogic_vector(abs1(31 downto 0)); + end if; + x_to_divider.divisor <= x"00000000" & std_ulogic_vector(abs2(31 downto 0)); end if; - x_to_divider.divisor <= x"00000000" & std_ulogic_vector(abs2(31 downto 0)); end if; -- signals to 32-bit multiplier @@ -1486,7 +1488,7 @@ begin end if; end if; - if ex1.div_in_progress = '1' then + if not HAS_FPU and ex1.div_in_progress = '1' then v.div_in_progress := not divider_to_x.valid; v.busy := not divider_to_x.valid; if divider_to_x.valid = '1' and ex1.oe = '1' then From 20f49f06f8438761ca5ebe77ebbfe9244fea66e6 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 10 Aug 2022 12:03:36 +1000 Subject: [PATCH 22/22] multiply_tb: Fix multiply_tb.vhdl for the new multiplier interface Signed-off-by: Paul Mackerras --- multiply_tb.vhdl | 76 ++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 42 deletions(-) diff --git a/multiply_tb.vhdl b/multiply_tb.vhdl index 5b13e14..77955db 100644 --- a/multiply_tb.vhdl +++ b/multiply_tb.vhdl @@ -26,15 +26,6 @@ architecture behave of multiply_tb is signal m1 : MultiplyInputType := MultiplyInputInit; signal m2 : MultiplyOutputType; - function absval(x: std_ulogic_vector) return std_ulogic_vector is - begin - if x(x'left) = '1' then - return std_ulogic_vector(- signed(x)); - else - return x; - end if; - end; - begin multiply_0: entity work.multiply generic map (PIPELINE_DEPTH => pipeline_depth) @@ -51,7 +42,6 @@ begin stim_process: process variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0); variable si: std_ulogic_vector(15 downto 0); - variable sign: std_ulogic; variable rnd : RandomPType; begin rnd.InitSeed(stim_process'path_name); @@ -102,11 +92,11 @@ begin behave_rt := ppc_mulld(ra, rb); - m1.data1 <= absval(ra); - m1.data2 <= absval(rb); - sign := ra(63) xor rb(63); - m1.not_result <= sign; - m1.addend <= (others => sign); + m1.data1 <= ra; + m1.data2 <= rb; + m1.is_signed <= '1'; + m1.subtract <= '0'; + m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; @@ -128,7 +118,8 @@ begin m1.data1 <= ra; m1.data2 <= rb; - m1.not_result <= '0'; + m1.is_signed <= '0'; + m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; @@ -149,11 +140,11 @@ begin behave_rt := ppc_mulhd(ra, rb); - m1.data1 <= absval(ra); - m1.data2 <= absval(rb); - sign := ra(63) xor rb(63); - m1.not_result <= sign; - m1.addend <= (others => sign); + m1.data1 <= ra; + m1.data2 <= rb; + m1.is_signed <= '1'; + m1.subtract <= '0'; + m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; @@ -173,13 +164,13 @@ begin behave_rt := ppc_mullw(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= absval(ra(31 downto 0)); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= absval(rb(31 downto 0)); - sign := ra(31) xor rb(31); - m1.not_result <= sign; - m1.addend <= (others => sign); + m1.data1 <= (others => ra(31)); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => rb(31)); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.is_signed <= '1'; + m1.subtract <= '0'; + m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; @@ -199,13 +190,13 @@ begin behave_rt := ppc_mulhw(ra, rb); - m1.data1 <= (others => '0'); - m1.data1(31 downto 0) <= absval(ra(31 downto 0)); - m1.data2 <= (others => '0'); - m1.data2(31 downto 0) <= absval(rb(31 downto 0)); - sign := ra(31) xor rb(31); - m1.not_result <= sign; - m1.addend <= (others => sign); + m1.data1 <= (others => ra(31)); + m1.data1(31 downto 0) <= ra(31 downto 0); + m1.data2 <= (others => rb(31)); + m1.data2(31 downto 0) <= rb(31 downto 0); + m1.is_signed <= '1'; + m1.subtract <= '0'; + m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period; @@ -229,7 +220,8 @@ begin m1.data1(31 downto 0) <= ra(31 downto 0); m1.data2 <= (others => '0'); m1.data2(31 downto 0) <= rb(31 downto 0); - m1.not_result <= '0'; + m1.is_signed <= '0'; + m1.subtract <= '0'; m1.addend <= (others => '0'); m1.valid <= '1'; @@ -250,12 +242,12 @@ begin behave_rt := ppc_mulli(ra, si); - m1.data1 <= absval(ra); - m1.data2 <= (others => '0'); - m1.data2(15 downto 0) <= absval(si); - sign := ra(63) xor si(15); - m1.not_result <= sign; - m1.addend <= (others => sign); + m1.data1 <= ra; + m1.data2 <= (others => si(15)); + m1.data2(15 downto 0) <= si; + m1.is_signed <= '1'; + m1.subtract <= '0'; + m1.addend <= (others => '0'); m1.valid <= '1'; wait for clk_period;