|
|
|
|
@ -85,7 +85,7 @@ bool CAssembler::buildSymbolTable()
|
|
|
|
|
{
|
|
|
|
|
list<CSourceLine*>::iterator it ;
|
|
|
|
|
unsigned int address = 0 ;
|
|
|
|
|
bool ret = TRUE ;
|
|
|
|
|
bool ret = true ;
|
|
|
|
|
|
|
|
|
|
for ( it = m_source.begin() ; it != m_source.end() ; it++ ) {
|
|
|
|
|
string name = toUpper( (*it)->getColumn( 0 ) ) ; // case insensitive
|
|
|
|
|
@ -93,17 +93,17 @@ bool CAssembler::buildSymbolTable()
|
|
|
|
|
if ( name == "NAMEREG" ) {
|
|
|
|
|
if ( !(*it)->isColumn( 3 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "'NAMEREG registername, newname' expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (*it)->isColumn( 4 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Rubbish found at end of line" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (*it)->getColumn( 2 ) != "," ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Comma expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -116,18 +116,18 @@ bool CAssembler::buildSymbolTable()
|
|
|
|
|
} else if ( name == "CONSTANT" ) {
|
|
|
|
|
if ( !(*it)->isColumn( 3 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "'CONSTANT name, valued' expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (*it)->isColumn( 4 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Rubbish found at end of line" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( (*it)->getColumn( 2 ) != "," ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Comma expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CConstant *nr = new CConstant ;
|
|
|
|
|
@ -138,17 +138,17 @@ bool CAssembler::buildSymbolTable()
|
|
|
|
|
} else if ( name == "ADDRESS" ) {
|
|
|
|
|
if ( !(*it)->isColumn( 1 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Value expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (*it)->isColumn( 4 ) ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Rubbish found at end of line" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( sscanf( (*it)->getColumn( 1 ).c_str(), "%X", &address ) != 1 ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Invalid address" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
(*it)->m_type = CSourceLine::stAddress ;
|
|
|
|
|
(*it)->m_address = address ;
|
|
|
|
|
@ -167,14 +167,14 @@ bool CAssembler::buildSymbolTable()
|
|
|
|
|
if ( (*it)->isColumn( 2 ) ) {
|
|
|
|
|
if ( getInstruction( (*it)->getColumn( 2 ) ) < 0 ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Instruction expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
} else {
|
|
|
|
|
address = address + 1 ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
error( (*it)->m_lineNr, "Label or Instruction expected" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
(*it)->m_address = address ;
|
|
|
|
|
@ -255,7 +255,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case DISABLE:
|
|
|
|
|
if ( toUpper( s1 ) != "INTERRUPT" ) {
|
|
|
|
|
error( line, "'INTERRUPT' expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
if ( instr == ENABLE )
|
|
|
|
|
code = instrENABLE_INTERRUPT ;
|
|
|
|
|
@ -281,44 +281,44 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case CALL:
|
|
|
|
|
case JUMP:
|
|
|
|
|
case RETURN:
|
|
|
|
|
b = TRUE ;
|
|
|
|
|
b = true ;
|
|
|
|
|
maxColumn= 2 ;
|
|
|
|
|
if ( toUpper( s1 ) == "C" ) {
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
case CALL : code = instrCALLC ; break ;
|
|
|
|
|
case JUMP : code = instrJUMPC ; break ;
|
|
|
|
|
case RETURN : code = instrRETURNC ; break ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
} else if ( toUpper( s1 ) == "NC" ) {
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
case CALL : code = instrCALLNC ; break ;
|
|
|
|
|
case JUMP : code = instrJUMPNC ; break ;
|
|
|
|
|
case RETURN : code = instrRETURNNC ; break ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
} else if ( toUpper( s1 ) == "NZ" ) {
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
case CALL : code = instrCALLNZ ; break ;
|
|
|
|
|
case JUMP : code = instrJUMPNZ ; break ;
|
|
|
|
|
case RETURN : code = instrRETURNNZ ; break ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
} else if ( toUpper( s1 ) == "Z" ) {
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
case CALL : code = instrCALLZ ; break ;
|
|
|
|
|
case JUMP : code = instrJUMPZ ; break ;
|
|
|
|
|
case RETURN : code = instrRETURNZ ; break ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
case CALL : code = instrCALL ; break ;
|
|
|
|
|
case JUMP : code = instrJUMP ; break ;
|
|
|
|
|
case RETURN : code = instrRETURN ; break ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'CALL', 'JUMP' or 'RETURN' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
b = FALSE ;
|
|
|
|
|
b = false ;
|
|
|
|
|
maxColumn = 1 ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -327,7 +327,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
if ( b ) {
|
|
|
|
|
if ( s2 != "," ) {
|
|
|
|
|
error( line, "Comma expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
s = s3 ;
|
|
|
|
|
} else
|
|
|
|
|
@ -340,7 +340,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
|
|
|
|
|
if ( sscanf( s.c_str(), "%d", &labelVal ) != 1 ) {
|
|
|
|
|
error( line, "Invalid label" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code |= labelVal ;
|
|
|
|
|
@ -352,7 +352,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
int reg = getRegister( translateRegister( s1 ) ) ;
|
|
|
|
|
if ( reg < 0 ) {
|
|
|
|
|
error( line, "Registername expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code = instrROTATE | (reg<<8) ;
|
|
|
|
|
@ -373,7 +373,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
default:
|
|
|
|
|
if ( s2 != "," ) {
|
|
|
|
|
error( line, "Comma expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
@ -385,13 +385,13 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
if ( sourceLine.getColumn( offset + 3 ) == "(" ) {
|
|
|
|
|
if ( !sourceLine.isColumn( offset + 5 ) || sourceLine.getColumn( offset + 5 ) != ")" ) {
|
|
|
|
|
error( line, "')' expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int reg2 = getRegister( translateRegister( sourceLine.getColumn( offset + 4 ) ) ) ;
|
|
|
|
|
if ( reg2 < 0 ) {
|
|
|
|
|
error( line, "Register expected" ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
code = (reg << 8) | (reg2 << 4) ;
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
@ -399,7 +399,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case OUTPUT: code |= instrOUTPUT_SX_SY ; break ;
|
|
|
|
|
case INPUT : code |= instrINPUT_SX_SY ; break ;
|
|
|
|
|
case FETCH : code |= instrFETCH_SX_SY ; break ;
|
|
|
|
|
default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
maxColumn = 6 ;
|
|
|
|
|
} else {
|
|
|
|
|
@ -408,7 +408,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
if ( sscanf( translateConstant( s3 ).c_str(), "%X", &value ) != 1 ) {
|
|
|
|
|
sprintf( err_desc, "Value or (regname) expected, but \"%s\" found.", s3.c_str() ) ;
|
|
|
|
|
error( line, err_desc ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
code = (reg << 8) | value ;
|
|
|
|
|
@ -417,7 +417,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case OUTPUT: code |= instrOUTPUT_SX_PP ; break ;
|
|
|
|
|
case INPUT : code |= instrINPUT_SX_PP ; break ;
|
|
|
|
|
case FETCH : code |= instrFETCH_SX_SS ; break ;
|
|
|
|
|
default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return FALSE ;
|
|
|
|
|
default: error( line, "'STORE', 'OUTPUT', 'INPUT' or 'FETCH' expected" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
maxColumn = 4 ;
|
|
|
|
|
}
|
|
|
|
|
@ -432,7 +432,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
if ( sscanf( translateConstant( s3 ).c_str(), "%X", &value ) != 1 ) {
|
|
|
|
|
sprintf( err_desc, "Value expected, but \"%s\" found.", s3.c_str() ) ;
|
|
|
|
|
error( line, err_desc ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
code = (reg << 8) | value ;
|
|
|
|
|
switch( instr ) {
|
|
|
|
|
@ -446,7 +446,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case SUBCY : code |= instrSUBCY_SX_KK ; break ;
|
|
|
|
|
case TEST : code |= instrTEST_SX_KK ; break ;
|
|
|
|
|
case XOR : code |= instrXOR_SX_KK ; break ;
|
|
|
|
|
default : error( line, "Unknown instruction" ) ; return FALSE ;
|
|
|
|
|
default : error( line, "Unknown instruction" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
code = ( reg << 8 ) | ( reg2 << 4 ) ;
|
|
|
|
|
@ -461,7 +461,7 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
case SUBCY : code |= instrSUBCY_SX_SY ; break ;
|
|
|
|
|
case TEST : code |= instrTEST_SX_SY ; break ;
|
|
|
|
|
case XOR : code |= instrXOR_SX_SY ; break ;
|
|
|
|
|
default : error( line, "Unknown instruction" ) ; return FALSE ;
|
|
|
|
|
default : error( line, "Unknown instruction" ) ; return false ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -472,13 +472,13 @@ bool CAssembler::addInstruction( instrNumber instr, CSourceLine sourceLine, int
|
|
|
|
|
if ( sourceLine.isColumn( maxColumn + offset ) ) {
|
|
|
|
|
sprintf( err_desc, "'%s' found at end of instruction", sourceLine.getColumn( maxColumn + offset ).c_str() ) ;
|
|
|
|
|
error( line, err_desc ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Finally
|
|
|
|
|
m_code->setInstruction( address, code, line ) ;
|
|
|
|
|
|
|
|
|
|
return TRUE ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -531,14 +531,14 @@ bool CAssembler::exportVHDL( string templateFile, string outputDir, string entit
|
|
|
|
|
FILE * infile = fopen( templateFile.c_str(), "r" ) ;
|
|
|
|
|
if ( infile == NULL ) {
|
|
|
|
|
error( NO_LINE_NR, string( "Unable to open VHDL template file '" + templateFile + "'" ).c_str() ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string exportFile = outputDir + "/" + entityName + ".vhd" ;
|
|
|
|
|
FILE * outfile = fopen( exportFile.c_str(), "w" ) ;
|
|
|
|
|
if ( outfile == NULL ) {
|
|
|
|
|
error( NO_LINE_NR , string( "Unable to open VHDL template file '%s'" + exportFile + ".vhd").c_str() ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool store = false, copy = false;
|
|
|
|
|
@ -585,7 +585,7 @@ bool CAssembler::exportVHDL( string templateFile, string outputDir, string entit
|
|
|
|
|
fclose( infile ) ;
|
|
|
|
|
fclose( outfile ) ;
|
|
|
|
|
|
|
|
|
|
return TRUE ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CAssembler::exportHEX( string filename, bool mem )
|
|
|
|
|
@ -593,7 +593,7 @@ bool CAssembler::exportHEX( string filename, bool mem )
|
|
|
|
|
FILE * file = fopen( filename.c_str(), "w" ) ;
|
|
|
|
|
if ( file == NULL ) {
|
|
|
|
|
error( NO_LINE_NR , string( "Unable to write to file '" + filename + "'").c_str() ) ;
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CInstruction * instr ;
|
|
|
|
|
@ -615,7 +615,7 @@ bool CAssembler::exportHEX( string filename, bool mem )
|
|
|
|
|
|
|
|
|
|
fclose( file ) ;
|
|
|
|
|
|
|
|
|
|
return TRUE ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -623,7 +623,7 @@ bool CAssembler::createOpcodes()
|
|
|
|
|
{
|
|
|
|
|
list<CSourceLine*>::iterator it ;
|
|
|
|
|
int columnOffset ;
|
|
|
|
|
bool ret = TRUE ;
|
|
|
|
|
bool ret = true ;
|
|
|
|
|
|
|
|
|
|
for ( it = m_source.begin() ; it != m_source.end() ; it++ ) {
|
|
|
|
|
if ( (*it)->m_type == CSourceLine::stNamereg ||
|
|
|
|
|
@ -643,11 +643,11 @@ bool CAssembler::createOpcodes()
|
|
|
|
|
|
|
|
|
|
if ( instr < 0 ) {
|
|
|
|
|
error( (*it)->m_lineNr, "Unknown instruction" ) ;
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
ret = false ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( addInstruction( (instrNumber) instr, **it, columnOffset ) == FALSE )
|
|
|
|
|
ret = FALSE ;
|
|
|
|
|
if ( addInstruction( (instrNumber) instr, **it, columnOffset ) == false )
|
|
|
|
|
ret = false ;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return ret ;
|
|
|
|
|
@ -656,8 +656,8 @@ bool CAssembler::createOpcodes()
|
|
|
|
|
bool CAssembler::assemble( )
|
|
|
|
|
{
|
|
|
|
|
bool r1, r2 ;
|
|
|
|
|
if ( loadFile() == FALSE )
|
|
|
|
|
return FALSE ;
|
|
|
|
|
if ( loadFile() == false )
|
|
|
|
|
return false ;
|
|
|
|
|
|
|
|
|
|
r1 = buildSymbolTable() ; // Even continue if symbol table failed..
|
|
|
|
|
r2 = createOpcodes() ; // .. this way we get the most errors/warnings in 1 compile cycle.
|
|
|
|
|
@ -727,7 +727,7 @@ bool CAssembler::loadFile()
|
|
|
|
|
if ( f == NULL ) {
|
|
|
|
|
string str = "Unable to load file '" + m_filename + "'";
|
|
|
|
|
error( NO_LINE_NR, str.c_str() ) ; // No linenumber information
|
|
|
|
|
return FALSE ;
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
char buf[ 256 ] ;
|
|
|
|
|
int linenr = 0 ;
|
|
|
|
|
@ -749,6 +749,6 @@ bool CAssembler::loadFile()
|
|
|
|
|
|
|
|
|
|
cout << "File " << m_filename << " succesfully loaded\r\n" ;
|
|
|
|
|
|
|
|
|
|
return TRUE ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|