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

Subversion Repositories scarm

[/] [scarm/] [trunk/] [src/] [scBarrelShifter.cpp] - Rev 10

Go to most recent revision | Compare with Previous | Blame | View Log

///////////////////////////////////////////////////////////////////////////////
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////              
//          
//  Original Author: Allen Tao Zhong,
//  University of Electronic Science and Technology in China
//  email: zhong@opencores.org
//  info   This is a SystemC ARM model 
//   
//
///////////////////////////////////////////////////////////////////////////////
 
/*****************************************************************************
 
  scBarrelShifter.cpp -- a barrel shifter
 
  Original Author: Allen Tao Zhong, University of Electronic Science and 
                   Technology in China
 
 *****************************************************************************/
 
// scBarrelShifter.cpp: implementation of the scBarrelShifter class.
//
//////////////////////////////////////////////////////////////////////
 
#include "scBarrelShifter.h"
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
#define SHIFT_LEFT(_x,_y)  ((_y >= 32) ? 0 : _x << _y)
#define SHIFT_RIGHT(_x,_y) ((_y >= 32) ? 0 : _x >> _y)
#define SIGNED_SHIFT_RIGHT(_x,_y) ((_y >= 32) ? ((_x >> 31) * 0xFFFFFFFF) : ((int32_t)_x) >> _y)
 
///////////////////////////////////////////////////////////////////////////////
//
//
uint32_t scBarrelShifter::Shift(uint32_t nVal,SHIFT type, int nDist)
{
	//out_b_RW=0;
    out_CPSR=R_CPSR;
	uint32_t nCPSR=inout_n_Flag;
  switch (type)
    {
      ////////////////////////////////////////////////////////////////
      case S_LSL: case S_ASL:
      {
		 if (nDist == 0)
		 {
			m_nShiftCarryBit = (nCPSR & C_FLAG) ? 1 : 0;
			return nVal;
		 }
		 else if (nDist == 32)
		 {
			m_nShiftCarryBit = nVal & 0x1;
			return 0;
		 }
	     else if (nDist > 32)
		 {
			m_nShiftCarryBit = 0;
			return 0;
		 }
		 else
		 {
			m_nShiftCarryBit = SHIFT_RIGHT(nVal, (32 - nDist)) & 0x1;
			return (nVal << nDist); break;
		 }
      }
      break;
      ////////////////////////////////////////////////////////////////
    case S_LSR:
      {
	if (nDist == 0)
	  {
	    m_nShiftCarryBit = (nCPSR & C_FLAG) ? 1 : 0;
	    return nVal;
	  }
	else if (nDist == 32)
	  {
	    m_nShiftCarryBit = (nVal >> 31);
	    return 0;
	  }
	else if (nDist > 32)
	  {
	    m_nShiftCarryBit = 0;
	    return 0;
	  }
	else
	  {
	    m_nShiftCarryBit = (nVal >> (nDist - 1)) & 0x1;
	    return (nVal >> nDist); 
	  }
      }
      break;
      ////////////////////////////////////////////////////////////////
    case S_ASR:
      {
	if (nDist == 0)
	  {
	    m_nShiftCarryBit = (nCPSR & C_FLAG) ? 1 : 0;
	    return nVal;
	  }
	else if (nDist >= 32)
	  {
	    if (nVal & 0x80000000)
	      {
		m_nShiftCarryBit = 1;
		return 0xFFFFFFFF;
	      }
	    else
	      {
		m_nShiftCarryBit = 0;
		return 0;
	      }
	  }
	else
	  {
	    uint32_t temp = 0xFFFFFFFF;	
	    m_nShiftCarryBit = (nVal >> (nDist - 1)) & 0x1;		
	    if ((nVal & 0x80000000) != 0)
	      nVal = (nVal >> nDist) | (~(temp >> (nDist /* - 1 */)));
	    else
	      nVal = (nVal >> nDist);
 
	    return nVal;
	  }
      }
      break;
      ////////////////////////////////////////////////////////////////
    case S_ROR:
      {
	if (nDist == 0)
	  {
	    m_nShiftCarryBit = (nCPSR & C_FLAG) ? 1 : 0;
	    return nVal;
	  }
	else if ((nDist & 0x1F) == 0)
	  {
	    m_nShiftCarryBit = nVal >> 31;
	    return nVal;
	  }
	else
	  {
	    nDist &= 0x1F;
	    m_nShiftCarryBit = SHIFT_RIGHT(nVal, (nDist - 1)) & 0x1;
	    return (nVal >> nDist) | (nVal << (32 - nDist));
	  }
      }
      break;
      ////////////////////////////////////////////////////////////////
    case S_RRX:
      {
	    m_nShiftCarryBit = nVal & 0x1;
 
        uint32_t temp = nVal & 0x1;
        nVal = nVal >> 1;
        if (nCPSR & C_FLAG)
          nVal |= 0x80000000;
 
        return nVal;
      }
      break;
    default :
	{
          cout<<"error in scBarrelShifter.Shift\n";
		  return 0;
 
	}
   }//end of switch(type)
   	out_b_RW=1;
    out_CPSR=R_CPSR;
	inout_n_Flag=nCPSR&(m_nShiftCarryBit<<29);
}
 
void scBarrelShifter::entry()
{  
 
   uint32_t val,dist,new_val;
   val=in_n_Val;
   dist=in_n_Dist;
   new_val=Shift(val, in_SHIFT_TYPE, dist);
   out_n_NewVal=new_val;
   out_b_Carry=m_nShiftCarryBit?1:0;
 
   //cout<<" Shifter: Value="<<hex<<in_n_Val<<"  ShitfDist="<<in_n_Dist<<" shifted_value="<<hex<<new_val<<endl;
}
 
 

Go to most recent revision | 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.