Implement the extswsli instruction
authorPaul Mackerras <paulus@ozlabs.org>
Sat, 2 May 2020 03:28:19 +0000 (13:28 +1000)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 8 May 2020 02:12:01 +0000 (12:12 +1000)
This mainly required the addition of an entry to the opcode 31 decode
table and a 32-bit sign-extender in the rotator.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
decode1.vhdl
execute1.vhdl
rotator.vhdl
rotator_tb.vhdl

index 785b669591e6ba6a3acf377ccd375ef0c5cbc160..466a8ba1aab8737ddcf0022e436adf004264d8a9 100644 (file)
@@ -185,7 +185,8 @@ architecture behaviour of decode1 is
                2#1110111010#  =>       (ALU,    OP_EXTS,      NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is1B, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extsb
                2#1110011010#  =>       (ALU,    OP_EXTS,      NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is2B, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extsh
                2#1111011010#  =>       (ALU,    OP_EXTS,      NONE,       NONE,        RS,   RA,   '0', '0', '0', '0', ZERO, '0', is4B, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extsw
-               -- 2#110111101-# extswsli
+                2#1101111010#  =>       (ALU,    OP_EXTSWSLI,  NONE,       CONST_SH,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extswsli
+                2#1101111011#  =>       (ALU,    OP_EXTSWSLI,  NONE,       CONST_SH,    RS,   RA,   '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC,   '0', '0'), -- extswsli
                2#1111010110#  =>       (ALU,    OP_ICBI,      NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbi
                2#0000010110#  =>       (ALU,    OP_NOP,       NONE,       NONE,        NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- icbt
                2#0000001111#  =>       (ALU,    OP_ISEL,      RA_OR_ZERO, RB,          NONE, RT,   '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '1'), -- isel
index 8286d30db10a01069b6ae141b1faabe89f5c6902..694004988b8fca94bbdb31883d5bdac33704eedf 100644 (file)
@@ -63,6 +63,7 @@ architecture behaviour of execute1 is
     signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
     signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0'));
     signal right_shift, rot_clear_left, rot_clear_right: std_ulogic;
+    signal rot_sign_ext: std_ulogic;
     signal rotator_result: std_ulogic_vector(63 downto 0);
     signal rotator_carry: std_ulogic;
     signal logical_result: std_ulogic_vector(63 downto 0);
@@ -174,6 +175,7 @@ begin
            arith => e_in.is_signed,
            clear_left => rot_clear_left,
            clear_right => rot_clear_right,
+            sign_ext_rs => rot_sign_ext,
            result => rotator_result,
            carry_out => rotator_carry
            );
@@ -429,6 +431,7 @@ begin
        right_shift <= '1' when e_in.insn_type = OP_SHR else '0';
        rot_clear_left <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCL else '0';
        rot_clear_right <= '1' when e_in.insn_type = OP_RLC or e_in.insn_type = OP_RLCR else '0';
+        rot_sign_ext <= '1' when e_in.insn_type = OP_EXTSWSLI else '0';
 
        ctrl_tmp.irq_state <= WRITE_SRR0;
        exception := '0';
@@ -828,7 +831,7 @@ begin
            when OP_PRTY =>
                result := parity_result;
                result_en := '1';
-           when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR =>
+           when OP_RLC | OP_RLCL | OP_RLCR | OP_SHL | OP_SHR | OP_EXTSWSLI =>
                result := rotator_result;
                if e_in.output_carry = '1' then
                    set_carry(v.e, rotator_carry, rotator_carry);
index d8a8ee9422bb7b374dcb1b950411f9d8b1bb48cf..fef97884009ff26a0fe333ecabce14a3a5e36c5e 100644 (file)
@@ -15,6 +15,7 @@ entity rotator is
          arith: in std_ulogic;
          clear_left: in std_ulogic;
          clear_right: in std_ulogic;
+          sign_ext_rs: in std_ulogic;
          result: out std_ulogic_vector(63 downto 0);
          carry_out: out std_ulogic
       );
@@ -57,13 +58,18 @@ architecture behaviour of rotator is
 
 begin
     rotator_0: process(all)
+        variable hi32: std_ulogic_vector(31 downto 0);
     begin
        -- First replicate bottom 32 bits to both halves if 32-bit
        if is_32bit = '1' then
-           repl32 <= rs(31 downto 0) & rs(31 downto 0);
-       else
-           repl32 <= rs;
+            hi32 := rs(31 downto 0);
+       elsif sign_ext_rs = '1' then
+            -- sign extend bottom 32 bits
+            hi32 := (others => rs(31));
+        else
+           hi32 := rs(63 downto 32);
        end if;
+        repl32 <= hi32 & rs(31 downto 0);
 
        -- Negate shift count for right shifts
        if right_shift = '1' then
index 3cb46b0181b4607d50f92ff8b3f6abe15dbe444a..62a09ce6d272685dfdc4b7ca88caca214a7a63de 100644 (file)
@@ -19,6 +19,7 @@ architecture behave of rotator_tb is
     signal is_32bit, right_shift, arith, clear_left, clear_right: std_ulogic := '0';
     signal result: std_ulogic_vector(63 downto 0);
     signal carry_out: std_ulogic;
+    signal extsw: std_ulogic;
 
 begin
     rotator_0: entity work.rotator
@@ -32,6 +33,7 @@ begin
            arith => arith,
            clear_left => clear_left,
            clear_right => clear_right,
+            sign_ext_rs => extsw,
            result => result,
            carry_out => carry_out
        );
@@ -48,6 +50,7 @@ begin
        arith <= '0';
        clear_left <= '1';
        clear_right <= '1';
+        extsw <= '0';
         rlwnm_loop : for i in 0 to 1000 loop
            rs <= pseudorand(64);
            shift <= pseudorand(7);
@@ -263,6 +266,31 @@ begin
                report "bad srad expected " & to_hstring(behave_ca_ra) & " got " & to_hstring(carry_out & result);
         end loop;
 
+        -- extswsli
+        report "test extswsli";
+        ra <= (others => '0');
+       is_32bit <= '0';
+       right_shift <= '0';
+       arith <= '0';
+       clear_left <= '0';
+       clear_right <= '0';
+        extsw <= '1';
+        extswsli_loop : for i in 0 to 1000 loop
+           rs <= pseudorand(64);
+           shift <= '0' & pseudorand(6);
+           wait for clk_period;
+           behave_ra := rs;
+            behave_ra(63 downto 32) := (others => rs(31));
+            behave_ra := std_ulogic_vector(shift_left(unsigned(behave_ra),
+                                                      to_integer(unsigned(shift))));
+           --report "rs = " & to_hstring(rs);
+           --report "ra = " & to_hstring(ra);
+           --report "shift = " & to_hstring(shift);
+           --report "result = " & to_hstring(carry_out & result);
+           assert behave_ra = result
+               report "bad extswsli expected " & to_hstring(behave_ra) & " got " & to_hstring(result);
+        end loop;
+
         assert false report "end of test" severity failure;
         wait;
     end process;