OpenCores
URL https://opencores.org/ocsvn/core_arm/core_arm/trunk

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [arm/] [libs/] [armshiefter.vhd] - Rev 4

Compare with Previous | Blame | View Log

library ieee;
use ieee.std_logic_1164.all;
 
-- PREFIX: ash_xxx
package armshiefter is
 
-- Addressing modes:
-- DAta PRocessing Addressing Modes      : DAPRAM
-- LoaD/STore Addressing Modes           : LDSTAM
-- Load/Store misc (V4) Addressing Modes : LSV4AM
 
-- Share shiefter for DAPRAM  and LDSTAM addressing modes
-- operands:
--                               data1  data2   value   shieftval
-- ade_styp_immrot(DAPRAM):        -      -      imm      imm 
-- ade_styp_simm(DAPRAM+LDSTAM):   -     use    data2     imm
-- ade_styp_sreg(DAPRAM):         use    use    data1    data2
-- ade_styp_none:                  -     use    data2      0
 
type ash_styp is (
  ash_styp_none,  -- no shieft
  ash_styp_immrot,-- DAPRAM: OP2 immidiate rotated
  ash_styp_simm,  -- DAPRAM: OP2 shieft with imm, LDSTAM: addr v1 reg (adm_LDSTAM_reg) 
  ash_styp_sreg   -- DAPRAM: OP2 shieft with reg  
);       
 
type ash_sdir is (
  ash_sdir_snone,    -- no shieft
  ash_sdir_slsl,     -- LSL #: logical shieft left 
  ash_sdir_slsr,     -- LSR #: logical shieft righ
  ash_sdir_sasr,     -- ASR #: arithmetic shieft left
  ash_sdir_sror,     -- ROR #: rotate 
  ash_sdir_srrx      -- RRX #: rotate 1 with carry
);
 
-- Shiefter of rsstg
procedure aas_shieft(
  insn  : in std_logic_vector(31 downto 0);
  dir   : in ash_sdir;
  typ   : in ash_styp;
  data1 : in std_logic_vector(31 downto 0);
  data2 : in std_logic_vector(31 downto 0);
  carry : in std_logic;
  shieftout      : out std_logic_vector(31 downto 0);
  shieftcarryout : out std_logic
);
 
end armshiefter;
 
package body armshiefter is
 
constant ASH_DAPRAMxLDSTAM_IMMROT_U : integer := 11; -- imm rot amount
constant ASH_DAPRAMxLDSTAM_IMMROT_D : integer := 8;   
constant ASH_DAPRAMxLDSTAM_IMM_U    : integer := 7;  -- imm const
constant ASH_DAPRAMxLDSTAM_IMM_D    : integer := 0;   
constant ASH_DAPRAMxLDSTAM_SIMM_U   : integer := 11; -- shieft immidiate amount
constant ASH_DAPRAMxLDSTAM_SIMM_D   : integer := 7;
 
type shift_src is (shiftin_00,shiftin_32,shiftin_33,shiftin_prev);
 
procedure aas_shieft(
  insn  : in std_logic_vector(31 downto 0);
  dir   : in ash_sdir;
  typ   : in ash_styp;
  data1 : in std_logic_vector(31 downto 0);
  data2 : in std_logic_vector(31 downto 0);
  carry : in std_logic;
  shieftout      : out std_logic_vector(31 downto 0);
  shieftcarryout : out std_logic
) is  
variable op1 : std_logic_vector(31 downto 0);
variable op2 : std_logic_vector(4 downto 0);                        
variable shiftin : std_logic_vector(64 downto 0);
variable carryout : std_logic;
variable carryoutsrc : shift_src;
begin
 
  carryoutsrc := shiftin_prev;
  carryout := carry;
 
  op1 := data1;
  op2 := (others => '0');
  shiftin := (others => '0');
  shiftin(32 downto 1) := data1;
 
  --                                       data1  data2   value   shieftval
  -- adm_DAPRAMxLDSTAM_DAPRAM_immrot:        -      -      imm      imm 
  -- adm_DAPRAMxLDSTAM_DAPRAMxLDSTAM_simm:   -     use    data2     imm
  -- adm_DAPRAMxLDSTAM_DAPRAM_sreg:         use    use    data1    data2
  -- adm_DAPRAMxLDSTAM_DAPRAM_none:          -     use    data2      0
 
  case typ is
    when ash_styp_immrot  => -- (special msr case also)
 
      --  64  63               33  32 31          1  0
      -- +---+---+---------------+===+=============+---+
      -- |           op1         |       op1       | 0 |
      -- +---+---+---------------+ccc+=============+---+
      --         |    op1            |                   <<  1 (>>1) 
      --                      |       op1       |        << 31 (>>31)
 
      op1 := (others => '0');
      op1(7 downto 0) := insn(ASH_DAPRAMxLDSTAM_IMM_U downto ASH_DAPRAMxLDSTAM_IMM_D);
 
      shiftin := (others => '0');
      shiftin(32 downto 1) := op1;
      shiftin(64 downto 33) := op1;
      op2 := insn(ASH_DAPRAMxLDSTAM_IMMROT_U downto ASH_DAPRAMxLDSTAM_IMMROT_D) & "0";
 
      carryoutsrc := shiftin_32;
 
      if op2 = "00000" then -- == 0
        carryoutsrc := shiftin_prev;
        carryout := carry;
      end if;
 
    when ash_styp_simm =>
 
      shiftin := (others => '0');
      shiftin(32 downto 1) := data2;
 
      case dir  is 
        when ash_sdir_slsl =>
 
          --$(del)
          --if shift_imm == 0 then /* Register Operand */
          --  shifter_operand = Rm
          --  shifter_carry_out = C Flag
          --else /* shift_imm > 0 */
          --  shifter_operand = Rm Logical_Shift_Left shift_imm
          --  shifter_carry_out = Rm[32 - shift_imm]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | c |           op1         |    000      | 0 |
          -- +---+---+------------ccc+===+=============+---+
          --       c |    op1            |                   << 31 (>>0)
          --                       c |       op1       |     << 0 (>>31)
 
          shiftin := (others => '0');
          shiftin(64) := carry;
          shiftin(63 downto 32) := data2;
          op2 := not insn(ASH_DAPRAMxLDSTAM_SIMM_U downto ASH_DAPRAMxLDSTAM_SIMM_D);
 
          carryoutsrc := shiftin_33;
 
        when ash_sdir_slsr =>
 
          --$(del)
          --if shift_imm == 0 then
          --  shifter_operand = 0
          --  shifter_carry_out = Rm[31]
          --else /* shift_imm > 0 */
          --  shifter_operand = Rm Logical_Shift_Right shift_imm
          --  shifter_carry_out = Rm[shift_imm - 1]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | 0 | 0 |    000        |        op1      | c |
          -- +---+---+---------------+===+=============+ccc+
          --                         |     op1         |     >> 0
          --                                       |op1|     >> 31 
 
          shiftin := (others => '0');
          shiftin(0) := carry;
          shiftin(32 downto 1) := data2;
          op2 := insn(ASH_DAPRAMxLDSTAM_SIMM_U downto ASH_DAPRAMxLDSTAM_SIMM_D);
 
          carryoutsrc := shiftin_00;
 
        when ash_sdir_sasr =>
          --$(del)
          --if shift_imm == 0 then
          --  if Rm[31] == 0 then
          --    shifter_operand = 0
          --    shifter_carry_out = Rm[31]
          --  else /* Rm[31] == 1 */
          --    shifter_operand = 0xFFFFFFFF
          --    shifter_carry_out = Rm[31]
          --else /* shift_imm > 0 */
          --  shifter_operand = Rm Arithmetic_Shift_Right <shift_imm>
          --  shifter_carry_out = Rm[shift_imm - 1]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | s | s |    sss        |        op1      | c |
          -- +---+---+---------------+===+=============+ccc+
          --                           s |    op1      |     >> 1
          --                                  sss  |op1|     >> 31 
          --                                  000      | 0   >> 0 (s=0)
          --                                  111      | 1   >> 0 (s=1)
          if data2(31) = '1' then
            shiftin(64 downto 33) := (others => '1');
          else
            shiftin(64 downto 33) := (others => '0');
          end if;
          shiftin(0) := carry;
          shiftin(32 downto 1) := data2;
          op2 := insn(ASH_DAPRAMxLDSTAM_SIMM_U downto ASH_DAPRAMxLDSTAM_SIMM_D);
 
          if op2 = "00000" then
            if data2(31) = '1' then
              shiftin(32 downto 0) := (others => '1');
            else
              shiftin(32 downto 0) := (others => '0');
            end if;
          end if;
 
          carryoutsrc := shiftin_00;
 
        when ash_sdir_sror =>
 
          --$(del)
          --if shift_imm == 0 then
          --  ash_sdir_srrx case
          --else /* shift_imm > 0 */
          --  shifter_operand = Rm Rotate_Right shift_imm
          --  shifter_carry_out = Rm[shift_imm - 1]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- |           op1         |       op1       | 0 |
          -- +---+---+---------------+ccc+=============+---+
          --         |    op1            |                   <<  1 (>>1) 
          --                      |       op1       |        << 31 (>>31)
 
          shiftin := (others => '0');
          shiftin(64 downto 33) := data2;
          shiftin(32 downto 1) := data2;
          op2 := insn(ASH_DAPRAMxLDSTAM_SIMM_U downto ASH_DAPRAMxLDSTAM_SIMM_D);
 
          carryoutsrc := shiftin_32;
 
        when ash_sdir_srrx =>
 
          --$(del)
          --shifter_operand = (C Flag Logical_Shift_Left 31) OR (Rm Logical_Shift_Right 1)
          --shifter_carry_out = Rm[0]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- |           000         | c |    op1-1        |
          -- +---+---+---------------+===+=============+ccc+
          --                                                 : rrx 
 
          shiftin(31 downto 0) := data2;
          shiftin(32) := carry;
          op2 := (others => '0');
 
          carryoutsrc := shiftin_00;
 
        when ash_sdir_snone =>
          op2 := (others => '0');
        when others => null;
      end case;
 
 
 
    when ash_styp_sreg =>
 
      shiftin := (others => '0');
      shiftin(32 downto 1) := data1;
 
      case dir  is 
        when ash_sdir_slsl =>
 
          --$(del)
          --if Rs[7:0] == 0 then
          --  shifter_operand = Rm
          --  shifter_carry_out = C Flag
          --else if Rs[7:0] < 32 then
          --  shifter_operand = Rm Logical_Shift_Left Rs[7:0]
          --  shifter_carry_out = Rm[32 - Rs[7:0]]
          --else if Rs[7:0] == 32 then
          --  shifter_operand = 0
          --  shifter_carry_out = Rm[0]
          --else /* Rs[7:0] > 32 */
          --  shifter_operand = 0
          --  shifter_carry_out = 0
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | c |           op1         |    000      | 0 |
          -- +---+---+------------ccc+===+=============+---+
          --       c |    op1            |                   << 31 (>>0)
          --                       c |       op1       |     << 0 (>>31)
 
          shiftin := (others => '0');
          shiftin(64) := carry;
          shiftin(63 downto 32) := data1;
          op2 := not data2(4 downto 0);
 
          carryoutsrc := shiftin_33;
 
          if not (data2(7 downto 5) = "000") then -- >= 32
            shiftin := (others => '0');
            if data2(7 downto 0) = "00100000" then  -- == 32
              carryoutsrc := shiftin_prev;
              carryout := data1(0);
            end if;
          end if;
 
        when ash_sdir_slsr =>
 
          --$(del)
          --if Rs[7:0] == 0 then
          --  shifter_operand = Rm
          --  shifter_carry_out = C Flag
          --else if Rs[7:0] < 32 then
          --  shifter_operand = Rm Logical_Shift_Right Rs[7:0]
          --  shifter_carry_out = Rm[Rs[7:0] - 1]
          --else if Rs[7:0] == 32 then
          --  shifter_operand = 0
          --  shifter_carry_out = Rm[31]
          --else /* Rs[7:0] > 32 */
          --  shifter_operand = 0
          --  shifter_carry_out = 0
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | 0 | 0 |    000        |        op1      | c |
          -- +---+---+---------------+===+=============+ccc+
          --                         |     op1         |     >> 0
          --                                       |op1|     >> 31 
 
          shiftin := (others => '0');
          shiftin(0) := carry;
          shiftin(32 downto 1) := data1;
          op2 := data2(4 downto 0);
 
          carryoutsrc := shiftin_00;
 
          if not (data2(7 downto 5) = "000") then -- >= 32
            shiftin := (others => '0');
            if data2(7 downto 0) = "00100000" then  -- == 32
              carryoutsrc := shiftin_prev;
              carryout := data1(31);
            end if;
          end if;
 
        when ash_sdir_sasr =>
          --$(del)
          --if Rs[7:0] == 0 then
          --  shifter_operand = Rm
          --  shifter_carry_out = C Flag
          --else if Rs[7:0] < 32 then
          --  shifter_operand = Rm Arithmetic_Shift_Right Rs[7:0]
          --  shifter_carry_out = Rm[Rs[7:0] - 1]
          --else /* Rs[7:0] >= 32 */
          --  if Rm[31] == 0 then
          --    shifter_operand = 0
          --    shifter_carry_out = Rm[31]
          --  else /* Rm[31] == 1 */
          --    shifter_operand = 0xFFFFFFFF
          --    shifter_carry_out = Rm[31]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- | s | s |    sss        |        op1      | c |
          -- +---+---+---------------+===+=============+ccc+
          --                           s |    op1      |     >> 1
          --                                  sss  |op1|     >> 31 
          --                                  000      | 0   >> 0 (s=0)
          --                                  111      | 1   >> 0 (s=1)
          if data1(31) = '1' then
            shiftin(64 downto 33) := (others => '1');
          else
            shiftin(64 downto 33) := (others => '0');
          end if;
          shiftin(0) := carry;
          shiftin(32 downto 1) := data1;
          op2 := data2(4 downto 0);
 
          if not (data2(7 downto 5) = "000") then -- >= 32
            if data1(31) = '1' then
              shiftin(32 downto 0) := (others => '1');
            else
              shiftin(32 downto 0) := (others => '0');
            end if;
          end if;
 
          carryoutsrc := shiftin_00;
 
        when ash_sdir_sror =>
 
          --$(del)
          --if Rs[7:0] == 0 then
          --  shifter_operand = Rm
          --  shifter_carry_out = C Flag
          --else if Rs[4:0] == 0 then
          --  shifter_operand = Rm 
          --  shifter_carry_out = Rm[31]
          --else /* Rs[4:0] > 0 */
          --  shifter_operand = Rm Rotate_Right Rs[4:0]
          --  shifter_carry_out = Rm[Rs[4:0] - 1]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- |           op1         |       op1       | 0 |
          -- +---+---+---------------+ccc+=============+---+
          --         |    op1            |                   <<  1 (>>1) 
          --                      |       op1       |        << 31 (>>31)
 
          shiftin := (others => '0');
          shiftin(64 downto 33) := data1;
          shiftin(32 downto 1) := data1;
          op2 := data2(4 downto 0);
 
          carryoutsrc := shiftin_32;
 
          if data2(7 downto 0) = "00000000" then -- == 0
            carryoutsrc := shiftin_prev;
            carryout := carry;
          end if;
 
        when ash_sdir_srrx =>
 
          --$(del)
          --shifter_operand = (C Flag Logical_Shift_Left 31) OR (Rm Logical_Shift_Right 1)
          --shifter_carry_out = Rm[0]
          --$(/del)
 
          --  64  63               33  32 31          1  0
          -- +---+---+---------------+===+=============+---+
          -- |           000         | c |    op1-1        |
          -- +---+---+---------------+===+=============+ccc+
          --                                                 : rrx
 
          op2 := (others => '0');
          shiftin(31 downto 0) := carry & shiftin(31 downto 1);
 
        when ash_sdir_snone =>
        when others => null;
      end case;
 
    when ash_styp_none =>
 
      shiftin := (others => '0');
      shiftin(32 downto 1) := data2;
 
    when others => 
  end case;
 
  -- shifter
  if op2 (4) = '1' then
    shiftin(48 downto 0) := shiftin(64 downto 16);
  end if;
  if op2 (3) = '1' then
    shiftin(40 downto 0) := shiftin(48 downto 8);
  end if;
  if op2 (2) = '1' then
    shiftin(36 downto 0) := shiftin(40 downto 4);
  end if;
  if op2 (1) = '1' then
    shiftin(34 downto 0) := shiftin(36 downto 2);
  end if;
  if op2 (0) = '1' then
    shiftin(32 downto 0) := shiftin(33 downto 1);
  end if;
 
  -- carry out select
  case carryoutsrc is
    when shiftin_00   => carryout := shiftin(0);
    when shiftin_33   => carryout := shiftin(33);
    when shiftin_32   => carryout := shiftin(32);
    when shiftin_prev => 
    when others => null;
  end case;
 
  shieftout := shiftin(32 downto 1);
  shieftcarryout := carryout;
 
end;
 
end armshiefter;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.