|
|
/**********************************************************************************
|
/**********************************************************************************
|
Theia, Ray Cast Programable graphic Processing Unit.
|
Theia, Ray Cast Programable graphic Processing Unit.
|
Copyright (C) 2012 Diego Valverde (diego.valverde.g@gmail.com)
|
Copyright (C) 2012 Diego Valverde (diego.valverde.g@gmail.com)
|
|
|
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
as published by the Free Software Foundation; either version 2
|
as published by the Free Software Foundation; either version 2
|
of the License, or (at your option) any later version.
|
of the License, or (at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
***********************************************************************************/
|
***********************************************************************************/
|
|
|
|
|
%require "2.4.1"
|
%require "2.4.1"
|
%skeleton "lalr1.cc"
|
%skeleton "lalr1.cc"
|
%defines
|
%defines
|
%error-verbose
|
%error-verbose
|
%locations
|
%locations
|
%define namespace "Theia"
|
%define namespace "Theia"
|
%define parser_class_name "Parser"
|
%define parser_class_name "Parser"
|
%parse-param { Theia::Scanner &scanner }
|
%parse-param { Theia::Scanner &scanner }
|
%parse-param { std::map & mSymbolMap }
|
%parse-param { std::map & mSymbolMap }
|
%parse-param { std::vector< CControlInstruction > &mInstructions }
|
%parse-param { std::vector< CControlInstruction > &mInstructions }
|
%parse-param { bool &mGenerateFixedPointArithmetic }
|
%parse-param { bool &mGenerateFixedPointArithmetic }
|
%lex-param { Theia::Scanner &scanner }
|
%lex-param { Theia::Scanner &scanner }
|
|
|
%code requires {
|
%code requires {
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include
|
#include "Instruction.h"
|
#include "Instruction.h"
|
#include
|
#include
|
|
|
|
|
// We want to return a string
|
// We want to return a string
|
#define YYSTYPE std::string
|
#define YYSTYPE std::string
|
|
|
|
|
namespace Theia
|
namespace Theia
|
{
|
{
|
// Forward-declare the Scanner class; the Parser needs to be assigned a
|
// Forward-declare the Scanner class; the Parser needs to be assigned a
|
// Scanner, but the Scanner can't be declared without the Parser
|
// Scanner, but the Scanner can't be declared without the Parser
|
class Scanner;
|
class Scanner;
|
|
|
// We use a map to store the INI data
|
// We use a map to store the INI data
|
typedef std::map > mapData;
|
typedef std::map > mapData;
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|
|
|
}
|
}
|
|
|
%code
|
%code
|
{
|
{
|
#include "Instruction.h"
|
#include "Instruction.h"
|
#include
|
#include
|
CControlInstruction I;
|
CControlInstruction I;
|
std::vector< unsigned int > gBranchStack;
|
std::vector< unsigned int > gBranchStack;
|
static int gInsertedInstructions = 0;
|
static int gInsertedInstructions = 0;
|
static int gWhileLoopAddress = 0;
|
static int gWhileLoopAddress = 0;
|
#define FUNCTION_PARAM_START_REGION 4
|
#define FUNCTION_PARAM_START_REGION 4
|
#define FUNCTION_PARAM_LAST_REGION 7
|
#define FUNCTION_PARAM_LAST_REGION 7
|
std::map gVaribleMap;
|
std::map gVaribleMap;
|
|
|
#define AUTOVAR_START_REGION 9
|
#define AUTOVAR_START_REGION 9
|
#define TEMP_VAR_START_OFFSET 128
|
#define TEMP_VAR_START_OFFSET 128
|
unsigned int gAutoVarIndex = AUTOVAR_START_REGION;
|
unsigned int gAutoVarIndex = AUTOVAR_START_REGION;
|
|
|
unsigned int gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
|
unsigned int gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
int GetCurrentLineNumber( const Theia::Parser::location_type &loc )
|
int GetCurrentLineNumber( const Theia::Parser::location_type &loc )
|
{
|
{
|
int ret = -1;
|
int ret = -1;
|
std::stringstream ss2;
|
std::stringstream ss2;
|
std::string where;
|
std::string where;
|
ss2 << loc;
|
ss2 << loc;
|
ss2 >> where;
|
ss2 >> where;
|
where.erase(where.find_first_of("."));
|
where.erase(where.find_first_of("."));
|
std::stringstream ss3;
|
std::stringstream ss3;
|
ss3 << where;
|
ss3 << where;
|
ss3 >> ret;
|
ss3 >> ret;
|
return ret;
|
return ret;
|
}
|
}
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
unsigned int GetAddressFromIdentifier( std::string aIdentifier, Theia::Parser::location_type yylloc )
|
unsigned int GetAddressFromIdentifier( std::string aIdentifier, Theia::Parser::location_type yylloc )
|
{
|
{
|
if (aIdentifier.find("R") != std::string::npos)
|
if (aIdentifier.find("R") != std::string::npos)
|
{
|
{
|
return atoi(aIdentifier.c_str()+1);
|
return atoi(aIdentifier.c_str()+1);
|
}
|
}
|
if (gVaribleMap.find(aIdentifier) == gVaribleMap.end())
|
if (gVaribleMap.find(aIdentifier) == gVaribleMap.end())
|
{
|
{
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "Undefined variable '" << aIdentifier << "' at line " << yylloc << " \n";
|
ret << "Undefined variable '" << aIdentifier << "' at line " << yylloc << " \n";
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
|
|
return gVaribleMap[ aIdentifier ];
|
return gVaribleMap[ aIdentifier ];
|
|
|
}
|
}
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
unsigned int gTempRegisterIndex = TEMP_VAR_START_OFFSET;
|
unsigned int gTempRegisterIndex = TEMP_VAR_START_OFFSET;
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
unsigned int GetFreeTempRegister( void )
|
unsigned int GetFreeTempRegister( void )
|
{
|
{
|
|
|
return gTempRegisterIndex++;
|
return gTempRegisterIndex++;
|
|
|
}
|
}
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
void ResetTempRegisterIndex( void )
|
void ResetTempRegisterIndex( void )
|
{
|
{
|
|
|
gTempRegisterIndex = TEMP_VAR_START_OFFSET;
|
gTempRegisterIndex = TEMP_VAR_START_OFFSET;
|
}
|
}
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
unsigned int AllocateVariable( )
|
unsigned int AllocateVariable( )
|
{
|
{
|
gAutoVarIndex++;
|
gAutoVarIndex++;
|
return gAutoVarIndex;
|
return gAutoVarIndex;
|
|
|
}
|
}
|
//----------------------------------------------------------
|
//----------------------------------------------------------
|
// Prototype for the yylex function
|
// Prototype for the yylex function
|
static int yylex(Theia::Parser::semantic_type * yylval,
|
static int yylex(Theia::Parser::semantic_type * yylval,
|
Theia::Parser::location_type * yylloc,
|
Theia::Parser::location_type * yylloc,
|
Theia::Scanner &scanner);
|
Theia::Scanner &scanner);
|
}
|
}
|
|
|
%token SHL SHR SCALAR RETURN EXIT EQUAL NOT_EQUAL GREATER_THAN LESS_THAN LESS_OR_EQUAL_THAN GREATER_OR_EQUAL_THAN IF ELSE OPEN_ROUND_BRACE CLOSE_ROUND_BRACE OPEN_BRACE CLOSE_BRACE ASSIGN ADD DECCONST HEXCONST BINCONST EOS MINUS
|
%token SHL SHR SCALAR RETURN EXIT EQUAL NOT_EQUAL GREATER_THAN LESS_THAN LESS_OR_EQUAL_THAN GREATER_OR_EQUAL_THAN IF ELSE OPEN_ROUND_BRACE CLOSE_ROUND_BRACE OPEN_BRACE CLOSE_BRACE ASSIGN ADD DECCONST HEXCONST BINCONST EOS MINUS
|
%token IDENTIFIER COMMA OPEN_SQUARE_BRACE CLOSE_SQUARE_BRACE WHILE START BITWISE_AND BITWISE_OR COPY_DATA_BLOCK COPY_CODE_BLOCK BLOCK_TRANSFER_IN_PROGRESS
|
%token IDENTIFIER COMMA OPEN_SQUARE_BRACE CLOSE_SQUARE_BRACE WHILE START BITWISE_AND BITWISE_OR COPY_DATA_BLOCK COPY_CODE_BLOCK BLOCK_TRANSFER_IN_PROGRESS
|
%%
|
%%
|
|
|
statement_list: //empty
|
statement_list: //empty
|
|
|
|
|
statement_list statement
|
statement_list statement
|
|
|
|
|
statement
|
statement
|
;
|
;
|
|
|
statement
|
statement
|
:
|
:
|
START LESS_THAN constant GREATER_THAN EOS
|
START LESS_THAN constant GREATER_THAN EOS
|
{
|
{
|
|
|
unsigned int ImmediateValue;
|
unsigned int ImmediateValue;
|
std::string StringHex = $3;
|
std::string StringHex = $3;
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << std::hex << StringHex;
|
ss << std::hex << StringHex;
|
ss >> ImmediateValue;
|
ss >> ImmediateValue;
|
|
|
|
|
I.mComment = "Start";
|
I.mComment = "Start";
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation(EOPERATION_DELIVERCOMMAND);
|
I.SetOperation(EOPERATION_DELIVERCOMMAND);
|
I.SetDestinationAddress( ImmediateValue+1 );
|
I.SetDestinationAddress( ImmediateValue+1 );
|
I.SetSrc1Address( VP_COMMAND_START_MAIN_THREAD );
|
I.SetSrc1Address( VP_COMMAND_START_MAIN_THREAD );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
}
|
}
|
|
|
|
|
SCALAR scalar_list EOS
|
SCALAR scalar_list EOS
|
|
|
|
|
COPY_DATA_BLOCK LESS_THAN expression COMMA expression COMMA expression GREATER_THAN EOS
|
COPY_DATA_BLOCK LESS_THAN expression COMMA expression COMMA expression GREATER_THAN EOS
|
{
|
{
|
|
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.mComment = "Setting destination ID SPR for Copy data block";
|
I.mComment = "Setting destination ID SPR for Copy data block";
|
I.SetDestinationAddress( BLOCK_DST_REG );
|
I.SetDestinationAddress( BLOCK_DST_REG );
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(0);
|
I.SetSrc0Address(0);
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
|
|
std::cout << "COPY_DATA_BLOCK I(" << GetAddressFromIdentifier($3,yylloc) << ") " << GetAddressFromIdentifier($5,yylloc) << " " << GetAddressFromIdentifier($7,yylloc) << "\n";
|
std::cout << "COPY_DATA_BLOCK I(" << GetAddressFromIdentifier($3,yylloc) << ") " << GetAddressFromIdentifier($5,yylloc) << " " << GetAddressFromIdentifier($7,yylloc) << "\n";
|
I.mComment = "Copy data block";
|
I.mComment = "Copy data block";
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation(EOPERATION_COPYBLOCK);
|
I.SetOperation(EOPERATION_COPYBLOCK);
|
//I.SetCopyDestinationId(ImmediateValue);
|
//I.SetCopyDestinationId(ImmediateValue);
|
I.SetCopyDestinationId(0);
|
I.SetCopyDestinationId(0);
|
I.SetCopyDestinationAddress(GetAddressFromIdentifier($5,yylloc));
|
I.SetCopyDestinationAddress(GetAddressFromIdentifier($5,yylloc));
|
I.SetCopySourceAddress(GetAddressFromIdentifier($7,yylloc));
|
I.SetCopySourceAddress(GetAddressFromIdentifier($7,yylloc));
|
I.SetCopySize(GetAddressFromIdentifier($9,yylloc));
|
I.SetCopySize(GetAddressFromIdentifier($9,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
}
|
}
|
|
|
|
|
EXIT EOS
|
EXIT EOS
|
{
|
{
|
//Insert a stupid NOP before the exit... is a bug but easier to just patch like this...
|
//Insert a stupid NOP before the exit... is a bug but easier to just patch like this...
|
|
|
I.mComment = "Exit";
|
I.mComment = "Exit";
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation(EOPERATION_EXIT);
|
I.SetOperation(EOPERATION_EXIT);
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
}
|
}
|
|
|
|
|
|
|
IDENTIFIER MINUS MINUS EOS
|
IDENTIFIER MINUS MINUS EOS
|
{
|
{
|
|
|
I.mComment = "Storing constant '1'";
|
I.mComment = "Storing constant '1'";
|
I.SetOperation( EOPERATION_SUB );
|
I.SetOperation( EOPERATION_SUB );
|
unsigned int TmpReg = GetFreeTempRegister();
|
unsigned int TmpReg = GetFreeTempRegister();
|
I.SetDestinationAddress( TmpReg );
|
I.SetDestinationAddress( TmpReg );
|
I.SetLiteral(1);
|
I.SetLiteral(1);
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
|
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address( TmpReg );
|
I.SetSrc0Address( TmpReg );
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
gInsertedInstructions = 0;
|
gInsertedInstructions = 0;
|
ResetTempRegisterIndex();
|
ResetTempRegisterIndex();
|
}
|
}
|
|
|
|
|
IDENTIFIER ADD ADD EOS
|
IDENTIFIER ADD ADD EOS
|
{
|
{
|
|
|
I.mComment = "Storing constant '1'";
|
I.mComment = "Storing constant '1'";
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
unsigned int TmpReg = GetFreeTempRegister();
|
unsigned int TmpReg = GetFreeTempRegister();
|
I.SetDestinationAddress( TmpReg );
|
I.SetDestinationAddress( TmpReg );
|
I.SetLiteral(1);
|
I.SetLiteral(1);
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
|
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address( TmpReg );
|
I.SetSrc0Address( TmpReg );
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
gInsertedInstructions = 0;
|
gInsertedInstructions = 0;
|
ResetTempRegisterIndex();
|
ResetTempRegisterIndex();
|
|
|
}
|
}
|
|
|
|
|
IDENTIFIER ASSIGN expression EOS
|
IDENTIFIER ASSIGN expression EOS
|
{
|
{
|
mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
|
mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(0);
|
I.SetSrc0Address(0);
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
gInsertedInstructions = 0;
|
gInsertedInstructions = 0;
|
ResetTempRegisterIndex();
|
ResetTempRegisterIndex();
|
}
|
}
|
|
|
|
|
IDENTIFIER ADD ASSIGN expression EOS
|
IDENTIFIER ADD ASSIGN expression EOS
|
{
|
{
|
mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
|
mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($4,yylloc));
|
I.SetSrc1Address( GetAddressFromIdentifier($4,yylloc));
|
I.SetSrc0Address( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc0Address( GetAddressFromIdentifier($1,yylloc) );
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
gInsertedInstructions = 0;
|
gInsertedInstructions = 0;
|
}
|
}
|
|
|
|
|
WHILE {gWhileLoopAddress = (mInstructions.size());} OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE OPEN_BRACE statement_list CLOSE_BRACE
|
WHILE {gWhileLoopAddress = (mInstructions.size());} OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE OPEN_BRACE statement_list CLOSE_BRACE
|
{
|
{
|
mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size()+1);
|
mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size()+1);
|
gBranchStack.pop_back();
|
gBranchStack.pop_back();
|
//Now I need to put a GOTO so that the while gets evaluated again...
|
//Now I need to put a GOTO so that the while gets evaluated again...
|
//jump out of the if
|
//jump out of the if
|
I.Clear();
|
I.Clear();
|
I.SetOperation( EOPERATION_BRANCH );
|
I.SetOperation( EOPERATION_BRANCH );
|
I.mComment = "while loop goto re-eval boolean";
|
I.mComment = "while loop goto re-eval boolean";
|
I.SetDestinationAddress( gWhileLoopAddress );
|
I.SetDestinationAddress( gWhileLoopAddress );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
|
|
I.SetOperation( EOPERATION_NOP );
|
I.SetOperation( EOPERATION_NOP );
|
I.mComment = "branch delay";
|
I.mComment = "branch delay";
|
I.SetDestinationAddress( gWhileLoopAddress );
|
I.SetDestinationAddress( gWhileLoopAddress );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
gInsertedInstructions = 0;
|
gInsertedInstructions = 0;
|
}
|
}
|
|
|
|
|
START IDENTIFIER EOS
|
START IDENTIFIER EOS
|
{
|
{
|
|
|
}
|
}
|
;
|
;
|
|
|
|
|
|
|
expression
|
expression
|
:
|
:
|
expression ADD term
|
expression ADD term
|
{
|
{
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_ADD );
|
I.SetOperation( EOPERATION_ADD );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
|
|
//$$ = ss.str();
|
//$$ = ss.str();
|
|
|
}
|
}
|
|
|
|
|
expression BITWISE_OR term
|
expression BITWISE_OR term
|
{
|
{
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_OR );
|
I.SetOperation( EOPERATION_OR );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
expression MINUS term
|
expression MINUS term
|
{
|
{
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_SUB );
|
I.SetOperation( EOPERATION_SUB );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
term
|
term
|
{
|
{
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
term
|
term
|
:
|
:
|
factor SHL factor
|
factor SHL factor
|
{
|
{
|
|
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_SHL );
|
I.SetOperation( EOPERATION_SHL );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
factor SHR factor
|
factor SHR factor
|
{
|
{
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_SHR );
|
I.SetOperation( EOPERATION_SHR );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
factor BITWISE_AND factor
|
factor BITWISE_AND factor
|
{
|
{
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_AND );
|
I.SetOperation( EOPERATION_AND );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << "R" << TempRegIndex;
|
ss << "R" << TempRegIndex;
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
factor
|
factor
|
{
|
{
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
;
|
;
|
|
|
factor
|
factor
|
:
|
:
|
IDENTIFIER
|
IDENTIFIER
|
{
|
{
|
$$ = $1;
|
$$ = $1;
|
}
|
}
|
|
|
|
|
OPEN_ROUND_BRACE expression CLOSE_ROUND_BRACE
|
OPEN_ROUND_BRACE expression CLOSE_ROUND_BRACE
|
{
|
{
|
$$ = $2;
|
$$ = $2;
|
}
|
}
|
|
|
|
|
constant
|
constant
|
{
|
{
|
unsigned int ImmediateValue;
|
unsigned int ImmediateValue;
|
std::string StringHex = $1;
|
std::string StringHex = $1;
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << std::hex << StringHex;
|
ss << std::hex << StringHex;
|
ss >> ImmediateValue;
|
ss >> ImmediateValue;
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
unsigned int TempRegIndex = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetOperation( EOPERATION_ASSIGN );
|
// I.mSourceLine = GetCurrentLineNumber( yylloc );
|
// I.mSourceLine = GetCurrentLineNumber( yylloc );
|
|
|
I.SetDestinationAddress( TempRegIndex );
|
I.SetDestinationAddress( TempRegIndex );
|
|
|
I.SetLiteral(ImmediateValue);
|
I.SetLiteral(ImmediateValue);
|
|
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
|
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
I.Clear();
|
I.Clear();
|
std::stringstream ss2;
|
std::stringstream ss2;
|
ss2 << "R" << TempRegIndex;
|
ss2 << "R" << TempRegIndex;
|
$$ = ss2.str();
|
$$ = ss2.str();
|
}
|
}
|
;
|
;
|
|
|
|
|
|
|
constant
|
constant
|
:
|
:
|
DECCONST
|
DECCONST
|
{
|
{
|
// Transform to HEX string
|
// Transform to HEX string
|
unsigned int Val;
|
unsigned int Val;
|
std::string StringDec = $1;
|
std::string StringDec = $1;
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << StringDec;
|
ss << StringDec;
|
ss >> Val;
|
ss >> Val;
|
std::stringstream ss2;
|
std::stringstream ss2;
|
ss2 << std::hex << Val;
|
ss2 << std::hex << Val;
|
$$ = ss2.str();
|
$$ = ss2.str();
|
}
|
}
|
|
|
|
|
HEXCONST
|
HEXCONST
|
{
|
{
|
std::string StringHex = $1;
|
std::string StringHex = $1;
|
// Get rid of the 0x
|
// Get rid of the 0x
|
StringHex.erase(StringHex.begin(),StringHex.begin()+2);
|
StringHex.erase(StringHex.begin(),StringHex.begin()+2);
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << std::hex << StringHex;
|
ss << std::hex << StringHex;
|
|
|
$$ = ss.str();
|
$$ = ss.str();
|
}
|
}
|
|
|
|
|
BINCONST
|
BINCONST
|
{
|
{
|
// Transform to HEX string
|
// Transform to HEX string
|
std::string StringBin = $1;
|
std::string StringBin = $1;
|
// Get rid of the 0b
|
// Get rid of the 0b
|
StringBin.erase(StringBin.begin(),StringBin.begin()+2);
|
StringBin.erase(StringBin.begin(),StringBin.begin()+2);
|
std::bitset<32> Bitset( StringBin );
|
std::bitset<32> Bitset( StringBin );
|
std::stringstream ss2;
|
std::stringstream ss2;
|
ss2 << std::hex << Bitset;
|
ss2 << std::hex << Bitset;
|
$$ = ss2.str();
|
$$ = ss2.str();
|
}
|
}
|
;
|
;
|
|
|
boolean_expression
|
boolean_expression
|
:
|
:
|
BLOCK_TRANSFER_IN_PROGRESS
|
BLOCK_TRANSFER_IN_PROGRESS
|
{
|
{
|
|
|
unsigned int ImmediateValue = 0x1;
|
unsigned int ImmediateValue = 0x1;
|
unsigned int TempRegIndex0 = GetFreeTempRegister();
|
unsigned int TempRegIndex0 = GetFreeTempRegister();
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetDestinationAddress( TempRegIndex0 );
|
I.SetDestinationAddress( TempRegIndex0 );
|
I.SetLiteral(ImmediateValue);
|
I.SetLiteral(ImmediateValue);
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
|
|
|
|
I.SetOperation( EOPERATION_BEQ );
|
I.SetOperation( EOPERATION_BEQ );
|
I.SetDestinationAddress( 0 );
|
I.SetDestinationAddress( 0 );
|
I.SetSrc1Address( STATUS_REG );
|
I.SetSrc1Address( STATUS_REG );
|
I.SetSrc0Address(TempRegIndex0);
|
I.SetSrc0Address(TempRegIndex0);
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
gBranchStack.push_back(mInstructions.size() - 1);
|
gBranchStack.push_back(mInstructions.size() - 1);
|
I.Clear();
|
I.Clear();
|
|
|
I.SetOperation( EOPERATION_NOP );
|
I.SetOperation( EOPERATION_NOP );
|
I.mComment = "branch delay";
|
I.mComment = "branch delay";
|
I.SetDestinationAddress( gWhileLoopAddress );
|
I.SetDestinationAddress( gWhileLoopAddress );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
|
|
|
|
|
|
}
|
}
|
|
|
|
|
expression EQUAL expression
|
expression EQUAL expression
|
{
|
{
|
|
|
I.SetOperation( EOPERATION_BNE );
|
I.SetOperation( EOPERATION_BNE );
|
I.SetDestinationAddress( 0 );
|
I.SetDestinationAddress( 0 );
|
I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
gBranchStack.push_back(mInstructions.size() - 1);
|
gBranchStack.push_back(mInstructions.size() - 1);
|
I.Clear();
|
I.Clear();
|
|
|
I.SetOperation( EOPERATION_NOP );
|
I.SetOperation( EOPERATION_NOP );
|
I.mComment = "branch delay";
|
I.mComment = "branch delay";
|
I.SetDestinationAddress( gWhileLoopAddress );
|
I.SetDestinationAddress( gWhileLoopAddress );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
|
|
}
|
}
|
|
|
|
|
expression LESS_OR_EQUAL_THAN expression
|
expression LESS_OR_EQUAL_THAN expression
|
{
|
{
|
|
|
I.SetOperation( EOPERATION_BLE );
|
I.SetOperation( EOPERATION_BLE );
|
I.SetDestinationAddress( 0 );
|
I.SetDestinationAddress( 0 );
|
I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
|
I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
|
I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
gInsertedInstructions++;
|
gInsertedInstructions++;
|
gBranchStack.push_back(mInstructions.size() - 1);
|
gBranchStack.push_back(mInstructions.size() - 1);
|
I.Clear();
|
I.Clear();
|
|
|
I.SetOperation( EOPERATION_NOP );
|
I.SetOperation( EOPERATION_NOP );
|
I.mComment = "branch delay";
|
I.mComment = "branch delay";
|
I.SetDestinationAddress( gWhileLoopAddress );
|
I.SetDestinationAddress( gWhileLoopAddress );
|
mInstructions.push_back(I);
|
mInstructions.push_back(I);
|
I.Clear();
|
I.Clear();
|
|
|
}
|
}
|
|
|
|
|
constant
|
|
{
|
|
unsigned int ImmediateValue;
|
|
std::string StringHex = $1;
|
|
std::stringstream ss;
|
|
ss << std::hex << StringHex;
|
|
ss >> ImmediateValue;
|
|
unsigned int TempRegIndex0 = GetFreeTempRegister();
|
|
I.SetOperation( EOPERATION_ASSIGN );
|
|
I.SetDestinationAddress( TempRegIndex0 );
|
|
I.SetLiteral(ImmediateValue);
|
|
mInstructions.push_back(I);
|
|
gInsertedInstructions++;
|
|
|
|
|
|
I.SetOperation( EOPERATION_BEQ );
|
|
I.SetDestinationAddress( 0 );
|
|
I.SetSrc1Address( 0 ); //Compare againts zero
|
|
I.SetSrc0Address(TempRegIndex0);
|
|
mInstructions.push_back(I);
|
|
gInsertedInstructions++;
|
|
gBranchStack.push_back(mInstructions.size() - 1);
|
|
I.Clear();
|
|
|
|
I.SetOperation( EOPERATION_NOP );
|
|
I.mComment = "branch delay";
|
|
I.SetDestinationAddress( gWhileLoopAddress );
|
|
mInstructions.push_back(I);
|
|
I.Clear();
|
|
}
|
;
|
;
|
scalar_list
|
scalar_list
|
:
|
:
|
IDENTIFIER COMMA scalar_list
|
IDENTIFIER COMMA scalar_list
|
{
|
{
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
{
|
{
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
|
|
gVaribleMap[ $1 ] = AllocateVariable();
|
gVaribleMap[ $1 ] = AllocateVariable();
|
}
|
}
|
|
|
|
|
IDENTIFIER ASSIGN constant COMMA scalar_list
|
IDENTIFIER ASSIGN constant COMMA scalar_list
|
{
|
{
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
{
|
{
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
|
|
gVaribleMap[ $1 ] = AllocateVariable();
|
gVaribleMap[ $1 ] = AllocateVariable();
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetDestinationAddress( gVaribleMap[ $1 ] );
|
I.SetDestinationAddress( gVaribleMap[ $1 ] );
|
I.SetLiteral( atoi($3.c_str() ) );
|
I.SetLiteral( atoi($3.c_str() ) );
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
|
|
}
|
}
|
|
|
|
|
IDENTIFIER ASSIGN constant
|
IDENTIFIER ASSIGN constant
|
{
|
{
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
{
|
{
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
unsigned int ImmediateValue;
|
unsigned int ImmediateValue;
|
std::string StringHex = $3;
|
std::string StringHex = $3;
|
std::stringstream ss;
|
std::stringstream ss;
|
ss << std::hex << StringHex;
|
ss << std::hex << StringHex;
|
ss >> ImmediateValue;
|
ss >> ImmediateValue;
|
gVaribleMap[ $1 ] = AllocateVariable();
|
gVaribleMap[ $1 ] = AllocateVariable();
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.mSourceLine = GetCurrentLineNumber( yylloc );
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetOperation( EOPERATION_ASSIGN );
|
I.SetDestinationAddress( gVaribleMap[ $1 ] );
|
I.SetDestinationAddress( gVaribleMap[ $1 ] );
|
I.SetLiteral( ImmediateValue );
|
I.SetLiteral( ImmediateValue );
|
mInstructions.push_back( I );
|
mInstructions.push_back( I );
|
I.Clear();
|
I.Clear();
|
}
|
}
|
|
|
|
|
IDENTIFIER
|
IDENTIFIER
|
{
|
{
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
if (gVaribleMap.find($1) != gVaribleMap.end())
|
{
|
{
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
ret << "Duplicated symbol '" << $1 << "'\n";
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
|
|
gVaribleMap[ $1 ] = AllocateVariable();
|
gVaribleMap[ $1 ] = AllocateVariable();
|
}
|
}
|
;
|
;
|
|
|
|
|
%%
|
%%
|
|
|
|
|
|
|
// Error function throws an exception (std::string) with the location and error message
|
// Error function throws an exception (std::string) with the location and error message
|
void Theia::Parser::error(const Theia::Parser::location_type &loc,
|
void Theia::Parser::error(const Theia::Parser::location_type &loc,
|
const std::string &msg) {
|
const std::string &msg) {
|
std::ostringstream ret;
|
std::ostringstream ret;
|
ret << "\ncp_compile -- Parser Error at " << loc << ": " << msg;
|
ret << "\ncp_compile -- Parser Error at " << loc << ": " << msg;
|
throw ret.str();
|
throw ret.str();
|
}
|
}
|
|
|
// Now that we have the Parser declared, we can declare the Scanner and implement
|
// Now that we have the Parser declared, we can declare the Scanner and implement
|
// the yylex function
|
// the yylex function
|
#include "Scanner.h"
|
#include "Scanner.h"
|
static int yylex(Theia::Parser::semantic_type * yylval,
|
static int yylex(Theia::Parser::semantic_type * yylval,
|
Theia::Parser::location_type * yylloc,
|
Theia::Parser::location_type * yylloc,
|
Theia::Scanner &scanner) {
|
Theia::Scanner &scanner) {
|
return scanner.yylex(yylval, yylloc);
|
return scanner.yylex(yylval, yylloc);
|
}
|
}
|
|
|
|
|