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

Subversion Repositories scarm

[/] [scarm/] [trunk/] [src/] [scALU.cpp] - Rev 8

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,I "stole" some codes from 
//       "swarm" , author Michael Dales (michael@dcs.gla.ac.uk)
//        
// scALU.cpp: implementation of the scALU class.
//
//////////////////////////////////////////////////////////////////////
 
#include "scALU.h"
#define DEBUG
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
#include "scALU.h"
#include"scARMInstruction.h"
#define CARRY_FROM(_a,_b,_r) ((_a >> 31) ? ((_b >> 31) | ((~_r) >> 31)) : ((_b >> 31) * ((~_r) >> 31)))
 
#define BORROWED_FROM(_a,_b,_r) ((_a >> 31) ? ((_b >> 31) & (_r >> 31)) : ((_b >> 31) | (_r >> 31)))
 
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
 
 
 
scALU::~scALU()
{
 
}
/******************************************************************************
 *
 */
uint32_t scALU::adc_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp;
  //int64_t result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int32_t)a;
  temp += (int32_t)b;
  if (c & C_FLAG)
    temp++;
 
  //result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags 
  *cond &= 0x0FFFFFFF;
 
  // N Flags = Rd[31] 
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (short_res == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = CarryFrom(Rn + shifter_operand + C Flag)
  if (CARRY_FROM((uint32_t)a, (uint32_t)b, short_res))
    (*cond) |= C_FLAG;
 
  // V Flag = OverflowFrom(Rn + shifter_operand + C Flag)
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return (uint32_t)short_res;
}
 
 
 
uint32_t scALU::add_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp;
  //int64_t result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int64_t)((int32_t)a);
  temp += (int64_t)((int32_t)b);
 
  //result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags 
  *cond &= 0x0FFFFFFF;
 
  // N Flags = Rd[31] 
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (short_res == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = CarryFrom(Rn + shifter_operand)
  if (CARRY_FROM((uint32_t)a, (uint32_t)b, short_res))
    (*cond) |= C_FLAG;
 
  // V Flag = OverflowFrom(Rn + shifter_operand)
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1)) {
    (*cond) |= V_FLAG;
  }
 
  return (uint32_t)short_res;
}
 
/******************************************************************************
 *
 */
uint32_t scALU::and_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  uint32_t temp;
 
  temp = a & b;
 
  // Clear flags - V flag uneffected
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (temp == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return temp;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::bic_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  uint32_t temp;
 
  temp = a & ~b;
 
  // Clear flags
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (temp == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return temp;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::cmn_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp;
  //int64_t result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int64_t)a;
  temp += (int64_t)b;
 
  //result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flags = Rd[31] 
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (short_res == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = CarryFrom(Rn + shifter_operand)
  if (CARRY_FROM((uint32_t)a, (uint32_t)b, short_res))
    (*cond) |= C_FLAG;
 
  temp = (int64_t)((int32_t)a);
  temp += (int32_t)b;
 
  // V Flag = OverflowFrom(Rn + shifter_operand)
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return 0;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::cmp_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp, result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int32_t)a;
  temp -= (int32_t)b;
 
  result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  uint64_t temp2 = (uint32_t)a;
  temp2 -= (uint32_t)b;
 
  uint64_t result2 = temp2 & 0x00000000FFFFFFFF;
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (short_res == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = NOT BorrowFrom(Rn - shifter_operand)
  //if (result2 == temp2)
  if (BORROWED_FROM((uint32_t)a, (uint32_t)b, short_res) == 0)
    (*cond) |= C_FLAG;
 
  // V Flag = OverFlowFrom (Rn - shifter_operand)
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return 0;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::eor_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  uint32_t temp;
 
  temp = a ^ b;
 
  // Clear flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (temp == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return temp;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::mov_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  // Clear flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((b >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (b == 0)
    (*cond) |= Z_FLAG;
 
  //cout<<"move"<<endl;
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return b;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::mvn_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  // Clear flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((b >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (~b == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return ~b;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::orr_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  uint32_t temp;
 
  temp = a | b;
 
  // Clear flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((b >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = if Rd == 0 then 1 else 0
  if (temp == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return temp;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::rsb_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp, result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int32_t)b;
  temp -= (int32_t)a;
 
  result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = NOT BorrowedFrom(shifter_operand - Rn)
  if (BORROWED_FROM((uint32_t)b, (uint32_t)a, short_res) == 0)
    (*cond) |= C_FLAG;
 
  // V Flag = OverflowFrom(shifter_operand - Rn)
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return (uint32_t)result;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::rsc_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp, result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int32_t)b;
  temp -= (int32_t)a;
  if (!(c & C_FLAG))
    temp--;
 
  result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = NOT BorrowedFrom(shifter_operand - Rn - NOT(C Flag))
  if (BORROWED_FROM((uint32_t)b, (uint32_t)a, short_res) == 0)
    (*cond) |= C_FLAG;
 
  // V Flag = OverflowFrom(shifter_operand - Rn - NOT(C Flag))
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return (uint32_t)result;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::sbc_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp, result;
  uint32_t short_res;
  uint32_t c = (*cond);
 
  temp = (int32_t)a;
  temp -= (int32_t)b;
  if (!(c & C_FLAG))
    temp--;
 
  result = temp & 0x00000000FFFFFFFFL;
  short_res = (uint32_t)((uint64_t)temp);
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = NOT BorrowedFrom(Rn - shifter_operand - NOT(C Flag))
  if (BORROWED_FROM((uint32_t)a, (uint32_t)b, short_res) == 0)
    (*cond) |= C_FLAG;
 
  // V Flag = OverflowFrom(Rn - shifter_operand - NOT(C Flag))
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return (uint32_t)result;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::sub_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int64_t temp, result, foo;
  uint32_t c = (*cond);
  //uint32_t res;
 
  temp = (int32_t)a;
  temp -= (int32_t)b;
 
  result = temp & 0x00000000FFFFFFFFL;
 
  // Clear flags
  *cond &= 0x0FFFFFFF;
 
  // N Flag = Rd[31]
  if (((temp >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
// C Flag = NOT BorrowedFrom(Rn - shifter_operand - NOT(C Flag))
#if 0
  if (result == temp)
    (*cond) |= C_FLAG;
#else
  foo = (uint32_t)((uint64_t)result);
  //cout.form("foo = 0x%08x\n", foo);
  if (BORROWED_FROM(a, b, foo) == 0)
    (*cond) |= C_FLAG;
 
#endif
 
  // V Flag = OverflowFrom(Rn - shifter_operand - NOT(C Flag))
  if (((temp >> 32) & 0x1) != ((temp >> 31) & 0x1))
    (*cond) |= V_FLAG;
 
  return (uint32_t)result;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::teq_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  uint32_t result;
 
  result = a ^ b;
 
  // Clear Flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((result >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return 0;
}
 
 
/******************************************************************************
 *
 */
uint32_t scALU::tst_op(uint32_t a, uint32_t b, uint32_t* cond)
{
  int32_t result;
 
  result = a & b;
 
  // Clear Flags (overflow unaffected)
  *cond &= (0x0FFFFFFF | V_FLAG);
 
  // N Flag = Rd[31]
  if (((result >> 31) & 0x1) == 1)
    (*cond) |= N_FLAG;
 
  // Z Flag = If Rd == 0 then 1 else 0
  if (result == 0)
    (*cond) |= Z_FLAG;
 
  // C Flag = shifter_carry_out 
  // Done otherwhere
 
  // V Flag = unaffected
 
  return 0;
}
void scALU::entry()
{
   OPCODE   op   =in_OP;
   uint32_t condition=inout_n_Flag;
   uint32_t a    =in_n_A;
   uint32_t b    =in_n_B;
 
   //sc_time local_time = sc_time_stamp();
 
   uint32_t result=0;
   switch (op)
   {
    case OP_AND: { 	result=and_op(a,b,&condition);/*cout<<"and_op";*/   break; }
    case OP_EOR: { 	result=eor_op(a,b,&condition);/*cout<<"eor_op";*/	break; }
    case OP_SUB: { 	result=sub_op(a,b,&condition);/*cout<<"sub_op";*/	break; }
    case OP_RSB: { 	result=rsb_op(a,b,&condition);/*cout<<"rsb_op";*/	break; }
    case OP_ADD: { 	result=add_op(a,b,&condition);/*cout<<"add_op";*/	break; }
    case OP_ADC: { 	result=adc_op(a,b,&condition);/*cout<<"adc_op";*/   break; }
    case OP_SBC: { 	result=sbc_op(a,b,&condition);/*cout<<"sbc_op";*/	break; }
    case OP_RSC: { 	result=rsc_op(a,b,&condition);/*cout<<"rsc_op";*/	break; }
    case OP_TST: { 	result=tst_op(a,b,&condition);/*cout<<"tst_op";*/	break; }
    case OP_ORR: { 	result=orr_op(a,b,&condition);/*cout<<"orr_op";*/	break; }
    case OP_TEQ: { 	result=teq_op(a,b,&condition);/*cout<<"teq_op";*/	break; }
    case OP_CMP: { 	result=cmp_op(a,b,&condition);/*cout<<"cmp_op";*/	break; }
    case OP_CMN: { 	result=cmn_op(a,b,&condition);/*cout<<"cmn_op";*/	break; }
    case OP_MOV: { 	result=mov_op(a,b,&condition);/*cout<<"mov_op";*/	break; }
    case OP_BIC: { 	result=bic_op(a,b,&condition);/*cout<<"bic_op";*/	break; }
    case OP_MVN: { 	result=mvn_op(a,b,&condition);/*cout<<"mvn_op";*/	break; }
    default:
		{
          cout<<"ALU: unknown op="<<op<<endl;
 
		}
   }//end of switch op
   inout_n_Flag=condition;
   //cout<<"flag="<<condition<<endl;
   out_n_Out=result;
 
#if defined(DEBUG)
   // cout<<" ALU: output="<<result<<endl;
#endif
}
 
void scALU::display()
{
   cout<<"A="<<in_n_A<<" B="<<in_n_B<<endl;
}
 

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.