You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
437 lines
14 KiB
437 lines
14 KiB
15 years ago
|
#include "cpicoblaze.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
|
||
|
using namespace std ;
|
||
|
|
||
|
CProgramCounter::CProgramCounter()
|
||
|
{
|
||
|
pc = 0 ;
|
||
|
}
|
||
|
|
||
|
CProgramCounter::~CProgramCounter()
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
void CProgramCounter::Next()
|
||
|
{
|
||
|
pc = ( pc + 1 ) % (MAX_ADDRESS);
|
||
|
}
|
||
|
|
||
|
void CProgramCounter::Set( uint16_t address )
|
||
|
{
|
||
|
pc = address % (MAX_ADDRESS) ;
|
||
|
}
|
||
|
|
||
|
uint16_t CProgramCounter::Get()
|
||
|
{
|
||
|
return pc ;
|
||
|
}
|
||
|
|
||
|
CScratchPad::CScratchPad()
|
||
|
{
|
||
|
int i ;
|
||
|
for ( i = 0 ; i < sizeof( ram ) ; i++ )
|
||
|
ram[ i ] = 0 ;
|
||
|
}
|
||
|
|
||
|
CScratchPad::~CScratchPad()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CStack::CStack()
|
||
|
{
|
||
|
int i ;
|
||
|
for ( i = 0 ; i < STACK_DEPTH ; i++ )
|
||
|
stack[ i ] = 0 ;
|
||
|
ptr = 0 ;
|
||
|
}
|
||
|
|
||
|
CStack::~CStack()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CStack::Push( uint16_t data )
|
||
|
{
|
||
|
data &= 0x3FF ;
|
||
|
if ( ptr == STACK_DEPTH - 1 )
|
||
|
cout << ">>>>Stack overflow!<<<<\r\n" ;
|
||
|
|
||
|
stack[ ptr ] = data ;
|
||
|
ptr = ( ptr + 1 ) % STACK_DEPTH ;
|
||
|
}
|
||
|
|
||
|
uint16_t CStack::Pop()
|
||
|
{
|
||
|
if ( ptr == 0 )
|
||
|
cout << ">>>>Stack underflow!<<<<\r\n" ;
|
||
|
|
||
|
ptr = ( ptr - 1 ) % STACK_DEPTH ;
|
||
|
return stack[ ptr ] ;
|
||
|
}
|
||
|
|
||
|
void CStack::Reset()
|
||
|
{
|
||
|
ptr = 0 ;
|
||
|
}
|
||
|
|
||
|
uint8_t CScratchPad::Get( uint8_t address )
|
||
|
{
|
||
|
return ram[ address % sizeof( ram ) ] ;
|
||
|
}
|
||
|
|
||
|
void CScratchPad::Set( uint8_t address, uint8_t data )
|
||
|
{
|
||
|
ram[ address % sizeof( ram ) ] = data ;
|
||
|
}
|
||
|
|
||
|
CPort::CPort()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
CPort::~CPort()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CPort::addPort( CIOPort * port )
|
||
|
{
|
||
|
portList.push_back( port ) ;
|
||
|
}
|
||
|
|
||
|
void CPort::deletePort( CIOPort * port )
|
||
|
{
|
||
|
portList.remove( port ) ;
|
||
|
}
|
||
|
|
||
|
uint8_t CPort::PortIn()
|
||
|
{
|
||
|
// find appropiate port
|
||
|
list<CIOPort*>::iterator i ;
|
||
|
|
||
|
for ( i = portList.begin() ; i != portList.end() ; i++ )
|
||
|
if ( (*i)->getID() == portid && (*i)->isReadable() )
|
||
|
return (*i)->In() ;
|
||
|
|
||
|
|
||
|
// Nothing found return zero
|
||
|
return 0 ;
|
||
|
}
|
||
|
|
||
|
void CPort::PortOut( uint8_t data )
|
||
|
{
|
||
|
// find appropiate port
|
||
|
list<CIOPort*>::iterator i ;
|
||
|
|
||
|
for ( i = portList.begin() ; i != portList.end() ; i++ )
|
||
|
if ( (*i)->getID() == portid && (*i)->isWriteable() )
|
||
|
(*i)->Out( data ) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
CCode::CCode( CPicoBlaze *cpu )
|
||
|
{
|
||
|
m_cpu = cpu ;
|
||
|
|
||
|
int i ;
|
||
|
for ( i = 0 ; i < MAX_ADDRESS ; i++ )
|
||
|
CodeMap[ i ] = NULL ;
|
||
|
}
|
||
|
|
||
|
CCode::~CCode()
|
||
|
{
|
||
|
ClearCode() ;
|
||
|
}
|
||
|
|
||
|
void CCode::ClearCode() {
|
||
|
int i ;
|
||
|
for ( i = 0 ; i < MAX_ADDRESS ; i++ )
|
||
|
if ( CodeMap[ i ] != NULL ) {
|
||
|
delete CodeMap[ i ] ;
|
||
|
CodeMap[ i ] = NULL ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CInstruction * CCode::Disassemble( uint32_t code )
|
||
|
{
|
||
|
uint32_t code_17_0 = (code & 0x3ffff) ;
|
||
|
uint32_t code_17_12 = (code & 0x3f000) ;
|
||
|
uint32_t code_17_10 = (code & 0x3fC00) ;
|
||
|
uint32_t code_7_0 = (code & 0x000ff) ;
|
||
|
|
||
|
/* The picoBlaze-3 instruction set */
|
||
|
if ( code_17_0 == instrRETURN ) return new RETURN( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNC ) return new RETURNC( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNNC ) return new RETURNNC( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNNZ ) return new RETURNNZ( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNZ ) return new RETURNZ( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNI_DISABLE ) return new RETURNI_DISABLE( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrRETURNI_ENABLE ) return new RETURNI_ENABLE( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrDISABLE_INTERRUPT ) return new DISABLE_INTERRUPT( m_cpu, code ) ;
|
||
|
if ( code_17_0 == instrENABLE_INTERRUPT ) return new ENABLE_INTERRUPT( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrCALL ) return new CALL( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrCALLC ) return new CALLC( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrCALLNC ) return new CALLNC( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrCALLNZ ) return new CALLNZ( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrCALLZ ) return new CALLZ( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrJUMP ) return new JUMP( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrJUMPC ) return new JUMPC( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrJUMPNC ) return new JUMPNC( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrJUMPNZ ) return new JUMPNZ( m_cpu, code ) ;
|
||
|
if ( code_17_10 == instrJUMPZ ) return new JUMPZ( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrADD_SX_KK ) return new ADD_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrADD_SX_SY ) return new ADD_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrADDCY_SX_KK ) return new ADDCY_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrADDCY_SX_SY ) return new ADDCY_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrAND_SX_KK ) return new AND_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrAND_SX_SY) return new AND_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrCOMPARE_SX_KK ) return new COMPARE_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrCOMPARE_SX_SY ) return new COMPARE_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrFETCH_SX_SS ) return new FETCH_SX_SS( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrFETCH_SX_SY ) return new FETCH_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrINPUT_SX_SY ) return new INPUT_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrINPUT_SX_PP ) return new INPUT_SX_PP( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrLOAD_SX_KK ) return new LOAD_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrLOAD_SX_SY ) return new LOAD_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrOR_SX_KK ) return new OR_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrOR_SX_SY ) return new OR_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrOUTPUT_SX_SY ) return new OUTPUT_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrOUTPUT_SX_PP ) return new OUTPUT_SX_PP( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSTORE_SX_SS ) return new STORE_SX_SS( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSTORE_SX_SY ) return new STORE_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSUB_SX_KK ) return new SUB_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSUB_SX_SY ) return new SUB_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSUBCY_SX_KK ) return new SUBCY_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrSUBCY_SX_SY ) return new SUBCY_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrTEST_SX_KK ) return new TEST_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrTEST_SX_SY ) return new TEST_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrXOR_SX_KK ) return new XOR_SX_KK( m_cpu, code ) ;
|
||
|
if ( code_17_12 == instrXOR_SX_SY ) return new XOR_SX_SY( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrRL_SX ) return new RL_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrRR_SX ) return new RR_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSL0_SX ) return new SL0_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSL1_SX ) return new SL1_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSLA_SX ) return new SLA_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSLX_SX ) return new SLX_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSR0_SX ) return new SR0_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSR1_SX ) return new SR1_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSRA_SX ) return new SRA_SX( m_cpu, code ) ;
|
||
|
if ( code_7_0 == instrSRX_SX ) return new SRX_SX( m_cpu, code ) ;
|
||
|
/* switch( code_17_0 ) {
|
||
|
case instrRETURN : return new RETURN( m_cpu, code ) ;
|
||
|
case instrRETURNC : return new RETURNC( m_cpu, code ) ;
|
||
|
case instrRETURNNC : return new RETURNNC( m_cpu, code ) ;
|
||
|
case instrRETURNNZ : return new RETURNNZ( m_cpu, code ) ;
|
||
|
case instrRETURNZ : return new RETURNZ( m_cpu, code ) ;
|
||
|
case instrRETURNI_DISABLE : return new RETURNI_DISABLE( m_cpu, code ) ;
|
||
|
case instrRETURNI_ENABLE : return new RETURNI_ENABLE( m_cpu, code ) ;
|
||
|
case instrDISABLE_INTERRUPT : return new DISABLE_INTERRUPT( m_cpu, code ) ;
|
||
|
case instrENABLE_INTERRUPT : return new ENABLE_INTERRUPT( m_cpu, code ) ;
|
||
|
default:
|
||
|
switch( code_17_10 ) {
|
||
|
case instrCALL : return new CALL( m_cpu, code ) ;
|
||
|
case instrCALLC : return new CALLC( m_cpu, code ) ;
|
||
|
case instrCALLNC : return new CALLNC( m_cpu, code ) ;
|
||
|
case instrCALLNZ : return new CALLNZ( m_cpu, code ) ;
|
||
|
case instrCALLZ : return new CALLZ( m_cpu, code ) ;
|
||
|
case instrJUMP : return new JUMP( m_cpu, code ) ;
|
||
|
case instrJUMPC : return new JUMPC( m_cpu, code ) ;
|
||
|
case instrJUMPNC : return new JUMPNC( m_cpu, code ) ;
|
||
|
case instrJUMPNZ : return new JUMPNZ( m_cpu, code ) ;
|
||
|
case instrJUMPZ : return new JUMPZ( m_cpu, code ) ;
|
||
|
default:
|
||
|
switch ( code_17_12 ) {
|
||
|
case instrADD_SX_KK : return new ADD_SX_KK( m_cpu, code ) ;
|
||
|
case instrADD_SX_SY : return new ADD_SX_SY( m_cpu, code ) ;
|
||
|
case instrADDCY_SX_KK : return new ADDCY_SX_KK( m_cpu, code ) ;
|
||
|
case instrADDCY_SX_SY : return new ADDCY_SX_SY( m_cpu, code ) ;
|
||
|
case instrAND_SX_KK : return new AND_SX_KK( m_cpu, code ) ;
|
||
|
case instrAND_SX_SY : return new AND_SX_SY( m_cpu, code ) ;
|
||
|
case instrCOMPARE_SX_KK : return new COMPARE_SX_KK( m_cpu, code ) ;
|
||
|
case instrCOMPARE_SX_SY : return new COMPARE_SX_SY( m_cpu, code ) ;
|
||
|
case instrFETCH_SX_SS : return new FETCH_SX_SS( m_cpu, code ) ;
|
||
|
case instrFETCH_SX_SY : return new FETCH_SX_SY( m_cpu, code ) ;
|
||
|
case instrINPUT_SX_SY : return new INPUT_SX_SY( m_cpu, code ) ;
|
||
|
case instrINPUT_SX_PP : return new INPUT_SX_PP( m_cpu, code ) ;
|
||
|
case instrLOAD_SX_KK : return new LOAD_SX_KK( m_cpu, code ) ;
|
||
|
case instrLOAD_SX_SY : return new LOAD_SX_SY( m_cpu, code ) ;
|
||
|
case instrOR_SX_KK : return new OR_SX_KK( m_cpu, code ) ;
|
||
|
case instrOR_SX_SY : return new OR_SX_SY( m_cpu, code ) ;
|
||
|
case instrOUTPUT_SX_SY : return new OUTPUT_SX_SY( m_cpu, code ) ;
|
||
|
case instrOUTPUT_SX_PP : return new OUTPUT_SX_PP( m_cpu, code ) ;
|
||
|
case instrSTORE_SX_SS : return new STORE_SX_SS( m_cpu, code ) ;
|
||
|
case instrSTORE_SX_SY : return new STORE_SX_SY( m_cpu, code ) ;
|
||
|
case instrSUB_SX_KK : return new SUB_SX_KK( m_cpu, code ) ;
|
||
|
case instrSUB_SX_SY : return new SUB_SX_SY( m_cpu, code ) ;
|
||
|
case instrSUBCY_SX_KK : return new SUBCY_SX_KK( m_cpu, code ) ;
|
||
|
case instrSUBCY_SX_SY : return new SUBCY_SX_SY( m_cpu, code ) ;
|
||
|
case instrTEST_SX_KK : return new TEST_SX_KK( m_cpu, code ) ;
|
||
|
case instrTEST_SX_SY : return new TEST_SX_SY( m_cpu, code ) ;
|
||
|
case instrXOR_SX_KK : return new XOR_SX_KK( m_cpu, code ) ;
|
||
|
case instrXOR_SX_SY : return new XOR_SX_SY( m_cpu, code ) ;
|
||
|
|
||
|
case instrROTATE:
|
||
|
switch( code_7_0 ) {
|
||
|
case instrRL_SX : return new RL_SX( m_cpu, code ) ;
|
||
|
case instrRR_SX : return new RR_SX( m_cpu, code ) ;
|
||
|
case instrSL0_SX : return new SL0_SX( m_cpu, code ) ;
|
||
|
case instrSL1_SX : return new SL1_SX( m_cpu, code ) ;
|
||
|
case instrSLA_SX : return new SLA_SX( m_cpu, code ) ;
|
||
|
case instrSLX_SX : return new SLX_SX( m_cpu, code ) ;
|
||
|
case instrSR0_SX : return new SR0_SX( m_cpu, code ) ;
|
||
|
case instrSR1_SX : return new SR1_SX( m_cpu, code ) ;
|
||
|
case instrSRA_SX : return new SRA_SX( m_cpu, code ) ;
|
||
|
case instrSRX_SX : return new SRX_SX( m_cpu, code ) ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
cout << "Invalid code (" << code << ")\r\n" ;
|
||
|
|
||
|
return NULL ;
|
||
|
}
|
||
|
|
||
|
bool CCode::setInstruction( uint16_t address, uint32_t code, unsigned int sourceLine )
|
||
|
{
|
||
|
CInstruction *instr = Disassemble( code ) ;
|
||
|
if ( instr == NULL ) {
|
||
|
cout << ">>>>Unknown code at address " << address << "<<<<\r\n" ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
if ( address >= MAX_ADDRESS ) {
|
||
|
cout << ">>>>Invalid address" << address << "<<<<\r\n" ;
|
||
|
delete instr ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
|
||
|
if ( CodeMap[ address ] != NULL ) {
|
||
|
cout << ">>>>Code is placed at same address (" << address << ")<<<<\r\n" ;
|
||
|
delete instr ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
instr->setSourceLine( sourceLine ) ;
|
||
|
CodeMap[ address ] = instr ;
|
||
|
|
||
|
return TRUE ;
|
||
|
}
|
||
|
|
||
|
CInstruction * CCode::getInstruction( uint16_t address )
|
||
|
{
|
||
|
if ( address >= MAX_ADDRESS )
|
||
|
return NULL ;
|
||
|
else
|
||
|
return CodeMap[ address ] ;
|
||
|
}
|
||
|
|
||
|
void CCode::Print()
|
||
|
{
|
||
|
int i ;
|
||
|
|
||
|
cout << "----listing----\r\n" ;
|
||
|
for ( i = 0 ; i < MAX_ADDRESS ; i++ ) {
|
||
|
if ( CodeMap[ i ] != NULL ) {
|
||
|
cout << i << " : " ;
|
||
|
CodeMap[ i ]->Print() ;
|
||
|
cout << "\r\n" ;
|
||
|
}
|
||
|
}
|
||
|
cout << "----end listing----\r\n" ;
|
||
|
|
||
|
}
|
||
|
|
||
|
CPicoBlaze::CPicoBlaze()
|
||
|
{
|
||
|
flags.zero = false ;
|
||
|
flags.carry = false ;
|
||
|
flags.interrupt_enable = false ;
|
||
|
|
||
|
scratch = new CScratchPad ;
|
||
|
pc = new CProgramCounter ;
|
||
|
stack = new CStack ;
|
||
|
port = new CPort ;
|
||
|
code = new CCode( this ) ;
|
||
|
}
|
||
|
|
||
|
CPicoBlaze::~CPicoBlaze()
|
||
|
{
|
||
|
delete scratch ;
|
||
|
delete pc ;
|
||
|
delete stack ;
|
||
|
delete port ;
|
||
|
delete code ;
|
||
|
}
|
||
|
|
||
|
void CPicoBlaze::Reset()
|
||
|
{
|
||
|
RESET_EVENT resetEvent( this, 0 ) ;
|
||
|
|
||
|
resetEvent.Print() ; cout << "\r\n" ;
|
||
|
resetEvent.Execute() ;
|
||
|
}
|
||
|
|
||
|
void CPicoBlaze::Interrupt()
|
||
|
{
|
||
|
INTERRUPT_EVENT interruptEvent( this, 0 ) ;
|
||
|
|
||
|
// interruptEvent.Print() ; cout << "\r\n" ;
|
||
|
interruptEvent.Execute() ;
|
||
|
}
|
||
|
|
||
|
void CPicoBlaze::Print()
|
||
|
{
|
||
|
int i ;
|
||
|
|
||
|
cout << "----CPU----\r\n" ;
|
||
|
cout << "regs|" ;
|
||
|
for ( i = 0 ; i < 15 ; i++ )
|
||
|
cout << "s" << i << "=" << (int) s[ i ] << "|" ;
|
||
|
cout << "\r\n" ;
|
||
|
|
||
|
cout << "flags|";
|
||
|
cout << "c=" << flags.carry ;
|
||
|
cout << "|z=" << flags.zero ;
|
||
|
cout << "|ie=" << flags.interrupt_enable << "|\r\n" ;
|
||
|
cout << "----end CPU----\r\n" ;
|
||
|
}
|
||
|
|
||
|
unsigned int CPicoBlaze::GetNextSourceLine()
|
||
|
{
|
||
|
CInstruction *instr = code->getInstruction( pc->Get() ) ;
|
||
|
if ( instr == NULL ) {
|
||
|
cout << ">>>>Error in simulation (No code found at " << pc->Get() << ")<<<<\r\n" ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
return instr->getSourceLine() ;
|
||
|
}
|
||
|
|
||
|
bool CPicoBlaze::Next()
|
||
|
{
|
||
|
CInstruction *instr = code->getInstruction( pc->Get() ) ;
|
||
|
if ( instr == NULL ) {
|
||
|
cout << ">>>>Error in simulation (No code found at " << pc->Get() << ")<<<<\r\n" ;
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
instr->Execute() ;
|
||
|
|
||
|
return TRUE ;
|
||
|
}
|
||
|
|
||
|
void CPicoBlaze::addPort( CIOPort * ioport )
|
||
|
{
|
||
|
port->addPort( ioport ) ;
|
||
|
}
|
||
|
|
||
|
void CPicoBlaze::deletePort( CIOPort * ioport )
|
||
|
{
|
||
|
port->deletePort( ioport ) ;
|
||
|
}
|
||
|
|
||
|
|