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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [beta_2.0/] [compiler/] [src/] [vp_compiler/] [parser.y] - Rev 227

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


/**********************************************************************************
Theia, Ray Cast Programable graphic Processing Unit.
Copyright (C) 2012  Diego Valverde (diego.valverde.g@gmail.com)

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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

***********************************************************************************/

 
%require "2.4.1"
%skeleton "lalr1.cc"
%defines
%error-verbose
%locations
%define namespace "Theia"
%define parser_class_name "Parser"
%parse-param { Theia::Scanner &scanner }
%parse-param { std::map<std::string,unsigned int>  & mSymbolMap }
%parse-param { std::vector< Instruction > &mInstructions }
%parse-param { bool &mGenerateFixedPointArithmetic }
%lex-param   { Theia::Scanner &scanner }

%code requires {
        #include <string>
        #include <sstream>
        #include <iomanip>
        #include <bitset>
        #include <map>
        #include "Instruction.h"
        #include <vector>
        

        // We want to return a string
        #define YYSTYPE std::string

        
                namespace Theia
                {
                        // Forward-declare the Scanner class; the Parser needs to be assigned a 
                        // Scanner, but the Scanner can't be declared without the Parser
                        class Scanner;
                
                        // We use a map to store the INI data
                        typedef std::map<std::string, std::map<std::string, std::string> > mapData;
                        
                        
                        


                }
        
}

%code 
{
        #include "Instruction.h"
        #include <vector>
        Instruction I,tmpI;
        
        std::vector< unsigned int > gBranchStack;
        static int gInsertedInstructions = 0;
        static int gWhileLoopAddress = 0;
#define FUNCTION_PARAM_START_REGION 4
#define FUNCTION_PARAM_LAST_REGION  10
        std::map<std::string, unsigned int> gFunctionParameters;
        std::map<std::string, unsigned int> gAutoVarMap;
        std::map<std::string, unsigned int> gThreadMap; //Key: Symbol, value: start code addr
        bool gThreadScope = false;
#define AUTOVAR_START_REGION 9
#define THREAD_OFFSET 128
unsigned int gExtraDestModifications = 0;
unsigned int gAutoVarIndex = AUTOVAR_START_REGION;
unsigned int gThreadAutoVarIndex = THREAD_OFFSET;
unsigned int gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
//----------------------------------------------------------
unsigned int GetNextFunctionParamRegister()
{
        unsigned Ret = gFunctionParameterIndex++;
        return Ret;
}

//----------------------------------------------------------
void AddFunctionParameter( std::string aVar, Theia::Parser::location_type  yylloc)
{
        ////std::cout << "Adding " << aVar << "\n";
        if (gFunctionParameterIndex+1 > FUNCTION_PARAM_LAST_REGION)
        {
                        std::ostringstream ret;
                        ret << "Cannot allocate more parameters '" << aVar << "' at line " << yylloc << " \n";
                        throw ret.str();
        }
        if (gFunctionParameters.find(aVar) != gFunctionParameters.end())
        {
                        std::ostringstream ret;
                        ret << "Parameter '" << aVar << "' at line " << yylloc << " is already defined\n";
                        throw ret.str();
        }
        
        gFunctionParameters[ aVar ] = gFunctionParameterIndex++;
        
}
//----------------------------------------------------------
std::string  GetRegisterFromFunctionParameter( std::string aVar )
{
        ////std::cout << "Looking for " << aVar << "\n";
        if (gFunctionParameters.find(aVar) == gFunctionParameters.end())
                return "NULL";
        
        std::ostringstream ss;
        ss << gFunctionParameters[ aVar ];
        return  ("R" + ss.str());
}
//----------------------------------------------------------
unsigned int GetCurretAutoVarFrameSize()
{
        
        return gAutoVarMap.size();
        
}
//----------------------------------------------------------
std::string GetRegisterFromAutoVar( std::string aVar, Theia::Parser::location_type  yylloc )
{
        if (gAutoVarMap.find(aVar) == gAutoVarMap.end())
        {
                        std::ostringstream ret;
                        ret << "Undefined variable '" << aVar << "' at line " << yylloc << " \n";
                        throw ret.str();
        }
                        
                std::ostringstream ss;
                ss << gAutoVarMap[ aVar ];
                return  ("R" + ss.str());
}
//----------------------------------------------------------
int GetCurrentLineNumber( const Theia::Parser::location_type &loc )
{
                int ret = -1;
                std::stringstream ss2;
                std::string where;
                ss2 << loc;
                ss2 >> where;
                where.erase(where.find_first_of("."));
                std::stringstream ss3;
                ss3 << where;
                ss3 >> ret;
                return ret;
}
//----------------------------------------------------------
unsigned int AllocAutoVar( unsigned int aSize = 1)
{
                
        if (!gThreadScope)
        {
                gAutoVarIndex += aSize;
                return gAutoVarIndex - (aSize-1);
        }else{
                gThreadAutoVarIndex += aSize;
                return (gThreadAutoVarIndex - (aSize-1));
        }
}
//----------------------------------------------------------
void ClearFunctionParameterMap()
{       
        gFunctionParameters.clear();
        gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
}
//----------------------------------------------------------
void ClearAutoVarMap()
{
        gAutoVarMap.clear();
        gAutoVarIndex = AUTOVAR_START_REGION;
}
//----------------------------------------------------------
unsigned int gTempRegisterIndex = 1;
unsigned int GetFreeTempRegister( )
{
        if (!gThreadScope)
                return gAutoVarIndex + (gTempRegisterIndex++);
        else
                return gThreadAutoVarIndex + (gTempRegisterIndex++);
        
}
//----------------------------------------------------------                    
void ResetTempRegisterIndex( void )
{
        
        gTempRegisterIndex = 1;
}       
//----------------------------------------------------------
bool IsSwizzled( std::string aSource)
{
        if (aSource.find(".") != std::string::npos)
                return true;
        else
                return false;
}

//----------------------------------------------------------
void SetSwizzleAndSign( unsigned int aSourceIndex, std::string aSwizzle, Instruction & I )
{
        std::string Reg,X,Y,Z, junk;
        std::stringstream ss( aSwizzle );
        ss >> Reg >> junk >> X >> Y >> Z;
        
        
        if (aSourceIndex == 1)
        {
                if (X == "X") { I.SetSrc1SwizzleX(SWX_X);       }
                if (X == "Y") { I.SetSrc1SwizzleX(SWX_Y);       }
                if (X == "Z") { I.SetSrc1SwizzleX(SWX_Z);       }
                if (X == "-X") { I.SetSrc1SignX( true ); I.SetSrc1SwizzleX(SWX_X);      }
                if (X == "-Y") { I.SetSrc1SignX( true ); I.SetSrc1SwizzleX(SWX_Y);      }
                if (X == "-Z") { I.SetSrc1SignX( true ); I.SetSrc1SwizzleX(SWX_Z);      }
                
                if (Y == "X") { I.SetSrc1SwizzleY(SWY_X);       }
                if (Y == "Y") { I.SetSrc1SwizzleY(SWY_Y);       }
                if (Y == "Z") { I.SetSrc1SwizzleY(SWY_Z);       }
                if (Y == "-X") { I.SetSrc1SignY( true ); I.SetSrc1SwizzleY(SWY_X);      }
                if (Y == "-Y") { I.SetSrc1SignY( true ); I.SetSrc1SwizzleY(SWY_Y);      }
                if (Y == "-Z") { I.SetSrc1SignY( true ); I.SetSrc1SwizzleY(SWY_Z);      }
                
                if (Z == "X") { I.SetSrc1SwizzleZ(SWZ_X);       }
                if (Z == "Y") { I.SetSrc1SwizzleZ(SWZ_Y);       }
                if (Z == "Z") { I.SetSrc1SwizzleZ(SWZ_Z);       }
                if (Z == "-X") { I.SetSrc1SignZ( true ); I.SetSrc1SwizzleZ(SWZ_X);      }
                if (Z == "-Y") { I.SetSrc1SignZ( true ); I.SetSrc1SwizzleZ(SWZ_Y);      }
                if (Z == "-Z") { I.SetSrc1SignZ( true ); I.SetSrc1SwizzleZ(SWZ_Z);      }
        } else {
                if (X == "X") { I.SetSrc0SwizzleX(SWX_X);       }
                if (X == "Y") { I.SetSrc0SwizzleX(SWX_Y);       }
                if (X == "Z") { I.SetSrc0SwizzleX(SWX_Z);       }
                if (X == "-X") { I.SetSrc0SignX( true ); I.SetSrc0SwizzleX(SWX_X);      }
                if (X == "-Y") { I.SetSrc0SignX( true ); I.SetSrc0SwizzleX(SWX_Y);      }
                if (X == "-Z") { I.SetSrc0SignX( true ); I.SetSrc0SwizzleX(SWX_Z);      }
                
                if (Y == "X") { I.SetSrc0SwizzleY(SWY_X);       }
                if (Y == "Y") { I.SetSrc0SwizzleY(SWY_Y);       }
                if (Y == "Z") { I.SetSrc0SwizzleY(SWY_Z);       }
                if (Y == "-X") { I.SetSrc0SignY( true ); I.SetSrc0SwizzleY(SWY_X);      }
                if (Y == "-Y") { I.SetSrc0SignY( true ); I.SetSrc0SwizzleY(SWY_Y);      }
                if (Y == "-Z") { I.SetSrc0SignY( true ); I.SetSrc0SwizzleY(SWY_Z);      }
                
                if (Z == "X") { I.SetSrc0SwizzleZ(SWZ_X);       }
                if (Z == "Y") { I.SetSrc0SwizzleZ(SWZ_Y);       }
                if (Z == "Z") { I.SetSrc0SwizzleZ(SWZ_Z);       }
                if (Z == "-X") { I.SetSrc0SignZ( true ); I.SetSrc0SwizzleZ(SWZ_X);      }
                if (Z == "-Y") { I.SetSrc0SignZ( true ); I.SetSrc0SwizzleZ(SWZ_Y);      }
                if (Z == "-Z") { I.SetSrc0SignZ( true ); I.SetSrc0SwizzleZ(SWZ_Z);      }
        }
}
//----------------------------------------------------------
void StoreReturnAddress( std::vector<Instruction> & aInstructions, Theia::Parser::location_type & yylloc )
{
                I.SetCode( EOPERATION_ADD );
                I.mComment = "store return address**";
                I.SetImm( aInstructions.size()+4 );
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( RETURN_ADDRESS_REGISTER );
                I.SetDestZero( true );
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                aInstructions.push_back( I );
                I.Clear();
}
//----------------------------------------------------------
void SavePreviousFramePointer( std::vector<Instruction> & aInstructions )
{
                I.SetCode( EOPERATION_ADD );
                I.mComment = "store current frame offset";
                I.SetWriteChannel(ECHANNEL_Y);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetSrc1Address(SPR_CONTROL_REGISTER);
                I.SetSrc1SwizzleX(SWX_X);
                I.SetSrc1SwizzleY(SWY_X);
                I.SetSrc1SwizzleZ(SWZ_X);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                aInstructions.push_back( I );
                I.Clear();
}
//----------------------------------------------------------
void SetIndexRegister( unsigned int aIndex, std::vector<Instruction> & aInstructions  )
{
                Instruction Tmp;
                Tmp.SetCode( EOPERATION_ADD );
                Tmp.mComment = "store array index register";
                Tmp.SetWriteChannel(ECHANNEL_Z);
                Tmp.SetDestinationAddress( SPR_CONTROL_REGISTER );
                Tmp.SetSrc1Address( aIndex );
                Tmp.SetSrc1Displace( true );
                Tmp.SetSrc1SwizzleX(SWX_X);
                Tmp.SetSrc1SwizzleY(SWY_X);
                Tmp.SetSrc1SwizzleZ(SWZ_X);
                Tmp.SetSrc0Address(0);
                Tmp.SetSrc0SwizzleX(SWX_X);
                Tmp.SetSrc0SwizzleY(SWY_X);
                Tmp.SetSrc0SwizzleZ(SWZ_X);
                //Tmp.SetImm( aIndex );
                //Tmp.SetDestZero( true );
                aInstructions.push_back( Tmp );
                
}
//----------------------------------------------------------
void UpdateFramePointer( std::vector<Instruction> & aInstructions )
{
                I.SetCode( EOPERATION_ADD );
                I.mComment = "displace next frame offset by the number of auto variables in current frame";
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetImm( GetCurretAutoVarFrameSize() );
                I.SetDestZero( false );
                aInstructions.push_back( I );
                I.Clear();
}
//----------------------------------------------------------
void CallFunction( std::string aFunctionName,  std::vector<Instruction> & aInstructions, std::map<std::string,unsigned int>  &  aSymbolMap)
{
                I.SetCode( EOPERATION_ADD );
                I.mComment = "call the function";
                I.SetBranchFlag( true );
                I.SetBranchType( EBRANCH_ALWAYS );
                //Now do the branch
                if (aSymbolMap.find(aFunctionName) == aSymbolMap.end())
                        I.SetDestinationSymbol( "@"+aFunctionName );
                else 
                        I.SetDestinationAddress( aSymbolMap[ aFunctionName ] );
                
                aInstructions.push_back( I );
                I.Clear();
}
//----------------------------------------------------------
void SetDestinationFromRegister( std::string aDestination, Instruction & aInst, bool Imm  )
{
                //Look for displament addressing mode
                                
                if (aDestination.find("OFFSET") != std::string::npos)
                {
                        aDestination.erase(aDestination.find("OFFSET"));
                        ////std::cout << "^_^ left_hand_side " << Destination << "\n";
                        if (Imm == true)
                                aInst.SetSrc0Displace( true ); //When Imm == 0, then setting this makes offset
                        else
                                aInst.SetDestZero( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
                }
                if (aDestination.find(".") != std::string::npos)
                {
                        aInst.ClearWriteChannel();
                        if (aDestination.find("x") != std::string::npos)
                                aInst.SetWriteChannel(ECHANNEL_X);
                        if (aDestination.find("y") != std::string::npos)
                                aInst.SetWriteChannel(ECHANNEL_Y);
                        if (aDestination.find("z") != std::string::npos)
                                aInst.SetWriteChannel(ECHANNEL_Z);

                        aDestination.erase(aDestination.find("."));
                        
                }
                aInst.SetDestinationAddress( atoi(aDestination.c_str()+1) );
}
//----------------------------------------------------------
void PopulateSourceRegisters( std::string a1, std::string a2, Instruction & I, std::vector<Instruction> & aInstructions )
{


                        if ( a1.find("R") == std::string::npos )
                        {
                                //This is for constants
                                unsigned int ImmediateValue;
                                std::string StringHex = a1;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                        } else {
                        
                        
                        
                                if (a1.find("array_element") != std::string::npos)
                                {
                                        
                        
                                        std::string Index = a1.substr(a1.find("array_element"));
                                        ////std::cout << "XXXXX " << Index << "\n\n\n";
                                        Index = Index.substr(Index.find_first_not_of("array_element R"));
                                        ////std::cout << "XXXXX " << Index << "\n\n\n";
                                        SetIndexRegister( atoi(Index.c_str()), aInstructions );
                                        a1.erase(a1.find("array_element"));
                                        I.SetSrc0Displace( true ); 
                                        I.SetSrc1Displace( true ); 
                                        I.SetImmBit( true );
                                }
                                        //Look for displament addressing mode
                                else if (a1.find("OFFSET") != std::string::npos)
                                {
                                        a1.erase(a1.find("OFFSET"));
                                        ////std::cout << "^_^ a1" << a1 << "\n";
                                        I.SetSrc1Displace( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
                                }
                                
                                std::string Src1 = a1;
                                if (IsSwizzled( Src1 ))
                                {
                                        SetSwizzleAndSign( 1, Src1,  I );
                                        Src1.erase(Src1.find("."));
                                }
                                I.SetSrc1Address( atoi( Src1.c_str()+1 ) );
                        }
                        
                        if ( a2.find("R") == std::string::npos)
                        {
                        } else {
                        
                                
                        
                                //Look for displament addressing mode
                                if (a2.find("OFFSET") != std::string::npos)
                                {
                                        a2.erase(a2.find("OFFSET"));
                                        ////std::cout << "^_^ a2 " << a2 << "\n";
                                        I.SetSrc0Displace( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
                                }
                        
                                std::string Src0 = a2;
                                if (IsSwizzled( Src0 ))
                                {
                                        SetSwizzleAndSign( 0, Src0,  I );
                                        Src0.erase(Src0.find("."));
                                }
                                I.SetSrc0Address( atoi( Src0.c_str()+1 ) );
                        }       
}
//----------------------------------------------------------
void ClearNextFunctionParamRegister()
{
        gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
}
//----------------------------------------------------------
void AddFunctionInputList( std::string aVar, std::vector<Instruction> & aInstructions,Theia::Parser::location_type  yylloc)
{
        //Get the value from the variable
        DCOUT << "Calling AddFunctionInputList input arg: " << aVar << " \n";
        //Copy the value into function parameter register
        unsigned FunctionParamReg = GetNextFunctionParamRegister();
        I.Clear();
        I.SetCode( EOPERATION_ADD );
        I.mComment = "copy the value into function parameter register";
        I.SetWriteChannel(ECHANNEL_XYZ);
        //I.SetDestZero( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
        I.SetDestinationAddress( FunctionParamReg );
        
        if (aVar.find("R") != std::string::npos)
        {
                if (aVar.find("OFFSET") != std::string::npos)
                {
                        I.SetSrc1Displace( true );
                        aVar.erase(aVar.find("OFFSET"));
                }
                I.SetSrc1Address(atoi(aVar.c_str()+1));
                I.SetSrc1SwizzleX(SWX_X);
                I.SetSrc1SwizzleY(SWY_Y);
                I.SetSrc1SwizzleZ(SWZ_Z);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                aInstructions.push_back( I );
                I.Clear();
                return;
        }
        std::string Reg = GetRegisterFromFunctionParameter( aVar );
        if (Reg == "NULL")
        {
                Reg = GetRegisterFromAutoVar( aVar, yylloc );
                I.SetSrc1Address(atoi(Reg.c_str()+1));
                I.SetSrc1Displace( true );
        } else {
                I.SetSrc1Address(atoi(Reg.c_str()+1));
                I.SetSrc1Displace( false );
        }
        
        
        
        I.SetSrc1SwizzleX(SWX_X);
        I.SetSrc1SwizzleY(SWY_Y);
        I.SetSrc1SwizzleZ(SWZ_Z);
        I.SetSrc0Address(0);
        I.SetSrc0SwizzleX(SWX_X);
        I.SetSrc0SwizzleY(SWY_X);
        I.SetSrc0SwizzleZ(SWZ_X);
        aInstructions.push_back( I );
        I.Clear();
}
//----------------------------------------------------------
void SetExpressionDestination( std::string aStringDestination, Instruction & I )
{
                std::string Destination = aStringDestination;
                
                //Look for indirect addressing
                if (Destination.find("INDEX") != std::string::npos)
                {
                        
                        std::string IndexRegister = Destination.substr(Destination.find("INDEX")+5);
                        Destination.erase(Destination.find("INDEX"));
                        I.SetImm( 0 );
                        I.SetCode( EOPERATION_ADD );
                        
                        if (Destination.find(".") != std::string::npos)
                        {
                                I.ClearWriteChannel();
                                if (Destination.find("x") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_X);
                                if (Destination.find("y") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Y);
                                if (Destination.find("z") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Z);
                                Destination.erase(Destination.find("."));
                
                        }
                                                
                        I.SetDestinationAddress( atoi(Destination.c_str()+1) );
                        
                } else {
                
                        //Look for displament addressing mode
                        if (Destination.find("OFFSET") != std::string::npos)
                        {
                                Destination.erase(Destination.find("OFFSET"));
                                I.SetDestZero( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
                        }
                        if (Destination.find(".") != std::string::npos)
                        {
                                I.ClearWriteChannel();
                                if (Destination.find("x") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_X);
                                if (Destination.find("y") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Y);
                                if (Destination.find("z") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Z);

                                Destination.erase(Destination.find("."));
                                
                        }
                        I.SetDestinationAddress( atoi(Destination.c_str()+1) );
                        
                        
                        
                }
}               

//----------------------------------------------------------
bool SourceNull( std::string aSource )
{
        if (aSource == "NULL")
                return true;
                
        return false;
}
//----------------------------------------------------------

void PopulateInstruction( std::string aDestination, std::string aSource1, std::string aSource0, Instruction & I, Theia::Parser::location_type  yylloc, bool aHasLiteral = false, unsigned int aLiteral = 0)
{


        bool DestinationHasOffset  = false;
        bool DetinationHasIndex    = false;
        bool Source0HasOffset      = false;
        bool Source1HasOffset      = false;
        bool Source1HasIndex       = false;
        bool Source0HasIndex       = false;
        
        
        if (aDestination.find("INDEX") != std::string::npos)
        {
                std::string ArrayIndex = aDestination.substr(aDestination.find("INDEX")+5);
                aSource1 = ArrayIndex;
                DetinationHasIndex      = true;
                
        }
                
        if (aSource1.find("INDEX") != std::string::npos)
                Source1HasIndex = true;
                
        if (aSource0.find("INDEX") != std::string::npos)
                Source0HasIndex = true; 
                
        if (aDestination.find("OFFSET") != std::string::npos)
                DestinationHasOffset = true;
                
        if      (aSource0.find("OFFSET") != std::string::npos)
                Source0HasOffset = true;
                
        if      (aSource1.find("OFFSET") != std::string::npos)
                Source1HasOffset = true;        
        
        if (IsSwizzled( aSource1 ))
                SetSwizzleAndSign( 1, aSource1,  I );
        I.SetSrc1Address( atoi( aSource1.c_str()+1 ) );
        
        if (IsSwizzled( aSource0 ))
                SetSwizzleAndSign( 0, aSource0,  I );
        I.SetSrc0Address( atoi( aSource0.c_str()+1 ) );
        
        
        
        //Fisrt take care of the destination write channel
        if (aDestination.find(".") != std::string::npos)
                {
                        I.ClearWriteChannel();
                        if (aDestination.find("x") != std::string::npos)
                                I.SetWriteChannel(ECHANNEL_X);
                        if (aDestination.find("y") != std::string::npos)
                                I.SetWriteChannel(ECHANNEL_Y);
                        if (aDestination.find("z") != std::string::npos)
                                I.SetWriteChannel(ECHANNEL_Z);
                        aDestination.erase(aDestination.find("."));
        } else {
                I.SetWriteChannel(ECHANNEL_XYZ);
        }
        //Now set the destination Index
        I.SetDestinationAddress( atoi(aDestination.c_str()+1) );
        
                
        //Now determine the addressing mode
        //Simple addressing modes
        if (!aHasLiteral &&     !DetinationHasIndex && !Source0HasIndex && !Source1HasIndex)
        {
                
                I.SetAddressingMode( DestinationHasOffset,Source1HasOffset,Source0HasOffset);
                return;
        }
        
        
        I.SetImmBit( true ); //This is to set the IMM bit = 1, may be overwritten latter
        //Complex addressing modes
        if 
        ( 
        aHasLiteral &&
        !SourceNull( aSource0 ) &&
        !Source0HasOffset &&
        !Source1HasOffset &&
        !DestinationHasOffset 
        )
        {
                I.SetAddressingMode( false,false,false);
                I.SetImm( aLiteral );
                
        }
        else    
        if 
        ( 
        aHasLiteral &&
        !SourceNull( aSource0 ) &&
        Source0HasOffset &&
        !Source0HasIndex &&
        DestinationHasOffset 
        
        )
        {
                
                I.SetAddressingMode( false,false,true);
                I.SetImm( aLiteral );
                
                
        }       
        else
        if 
        ( 
        !aHasLiteral &&
        !SourceNull( aSource1 ) &&
        !Source1HasOffset &&
        !SourceNull( aSource0 ) &&
        Source0HasOffset &&
        Source0HasIndex &&
        DestinationHasOffset 
        
        )
        {
                I.SetAddressingMode( false,true,false);
                
        }
        else
        if 
        ( 
        !aHasLiteral &&
        !Source1HasOffset &&
        !SourceNull( aSource0 ) &&
        Source0HasOffset &&
        !Source0HasIndex &&
        DestinationHasOffset &&
        DetinationHasIndex
        
        )
        {
                I.SetAddressingMode( false,true,true);
                
        }
        else
        if 
        ( 
        aHasLiteral &&
        SourceNull( aSource0 ) &&
        !DestinationHasOffset &&
        !DetinationHasIndex
        
        )
        {
        
                
                I.SetAddressingMode( true,false,false);
                I.SetImm( aLiteral );
        }
        else
        if 
        ( 
        aHasLiteral &&
        SourceNull( aSource0 ) &&
        DestinationHasOffset &&
        !DetinationHasIndex
        
        )
        {
                
                I.SetAddressingMode( true,false,true);
                I.SetImm( aLiteral );
        }
        else
        if 
        ( 
        !aHasLiteral &&
        Source1HasOffset &&
        Source1HasIndex &&
        SourceNull( aSource0 ) &&
        DestinationHasOffset &&
        !DetinationHasIndex
        
        )
        {
                
                I.SetAddressingMode( true,true,false);
        }
        else
        if 
        ( 
        !aHasLiteral &&
        Source1HasOffset &&
        Source1HasIndex &&
        Source0HasOffset &&
        !Source0HasIndex &&
        DestinationHasOffset &&
        !DetinationHasIndex
        
        )
        {
                
                I.SetAddressingMode( true,true,true);
        } else {
                        std::ostringstream ret;
                        ret << "Could not determine addressing mode  at line " << yylloc << " \n";
                        throw ret.str();
        }
        
        
}

//-------------------------------------------------------------
void PopulateBoolean(EBRANCHTYPE aBranchType, std::string Source1, std::string Source0, Instruction & I, std::vector<Instruction> & aInstructions, Theia::Parser::location_type & yylloc )
{

                                        if (Source0.find("R") == std::string::npos)
                                        {
                                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                                I.SetCode( EOPERATION_ADD );
                                                unsigned int TempRegIndex  = GetFreeTempRegister();
                                                I.SetDestinationAddress( TempRegIndex );
                                                unsigned int ImmediateValue;
                                                std::string StringHex = Source0;
                                                std::stringstream ss;
                                                ss << std::hex << StringHex;
                                                ss >> ImmediateValue;
                                                I.SetImm( ImmediateValue );
                                                I.SetDestZero( true );
                                                I.SetSrc0Displace( true );
                                                I.SetWriteChannel(ECHANNEL_X);
                                                I.SetWriteChannel(ECHANNEL_Y);
                                                I.SetWriteChannel(ECHANNEL_Z);
                                                aInstructions.push_back(I);
                                                I.Clear();
                                                
                                                std::stringstream ss2;
                                                ss2 << "R" << TempRegIndex; 
                                                ss2 >> Source0;
                                                Source0 += " OFFSET ";
                                                
                                        }
                                        else
                                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                                
                                        I.SetCode( EOPERATION_ADD );
                                        I.SetSrc0SignX( true );
                                        I.SetSrc0SignY( true );
                                        I.SetSrc0SignZ( true );
                                        I.SetBranchFlag( true );
                                        I.ClearWriteChannel();
                                        I.SetBranchType( aBranchType );
                                        
                                        PopulateSourceRegisters( Source1, Source0, I, aInstructions);
                                        aInstructions.push_back(I);
                                        I.Clear();
                                        ////std::cout << "pushing code at position " << (mInstructions.size() - 1) << "\n";
                                        gBranchStack.push_back(aInstructions.size() - 1);
                                        ResetTempRegisterIndex();
}

//-------------------------------------------------------------
        // Prototype for the yylex function
        static int yylex(Theia::Parser::semantic_type * yylval,
                         Theia::Parser::location_type * yylloc,
                         Theia::Scanner &scanner);
}

%token AUTO RETURN FUNCTION JMP 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 DIV MUL ADD DECCONST HEXCONST BINCONST EOS DOT MINUS TK_X TK_Y TK_Z TK_N REG
%token IDENTIFIER SQRT SCALE UNSCALE USING FIXED_POINT COMMA OPEN_SQUARE_BRACE CLOSE_SQUARE_BRACE WHILE ADD_EQ THREAD START BITWISE_AND BITWISE_OR OUT
%%

statement_list: //empty
        |
        statement_list statement
        |
        statement
        ;

statement
        :
        AUTO auto_var_list EOS
        |
        USING FIXED_POINT EOS
        {
                mGenerateFixedPointArithmetic = true;
        }
        |
        EXIT EOS
        {
                //Insert a stupid NOP before the exit... is a bug but easier to just patch like this...
                
                I.Clear();
                I.mComment = "NOP";
                I.SetCode( EOPERATION_NOP );
                mInstructions.push_back(I);
                I.Clear();
                
                I.SetEofFlag(true);
                I.mComment = "Set the Exit bit";
                I.SetCode( EOPERATION_ADD );
                mInstructions.push_back(I);
                I.Clear();
        }
        |
        RETURN expression EOS
        {
        
                //////////////////////////////////////////////////////////////////////////////
                // This means this that the expression was just a constant.
                // No operations were inserted
                //////////////////////////////////////////////////////////////////////////////
                if (gInsertedInstructions == 0)
                {
                        I.Clear();
                        I.SetCode(EOPERATION_ADD);
                        I.mComment ="Set the return value";
                        if ($3.find("R") != std::string::npos)
                        {
                                PopulateInstruction( "R1", $2,"R0 . X X X",I,yylloc);
                        }
                        else
                        {
                                unsigned int ImmediateValue = 0;
                                std::string StringHex = $3;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                PopulateInstruction( "R1", $3,"NULL",I, yylloc, true, ImmediateValue);
                        }
                        mInstructions.push_back(I);     
                        I.Clear();
                } else {
                
                        mInstructions[ mInstructions.size() - gInsertedInstructions].mSourceLine = GetCurrentLineNumber(yylloc);
                        gInsertedInstructions = 0;      
                        mInstructions.back().mComment ="Assigning return value";
                        mInstructions.back().SetDestinationAddress( RETURN_VALUE_REGISTER );
                        
                }
                ResetTempRegisterIndex();
                
                I.SetCode( EOPERATION_ADD );
                I.mComment = "Restore previous function frame offset";
                I.ClearWriteChannel();
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetSrc1Address(SPR_CONTROL_REGISTER);
                I.SetSrc1SwizzleX(SWX_Y);
                I.SetSrc1SwizzleY(SWY_Y);
                I.SetSrc1SwizzleZ(SWZ_Y);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                mInstructions.push_back( I );
                I.Clear();
                
                //Now return
                I.SetImm( 0 );
                I.SetCode( EOPERATION_ADD );
                I.mComment = "return from function";
                I.SetBranchFlag( true );
                I.SetBranchType( EBRANCH_ALWAYS );
                I.SetDestinationAddress( RETURN_ADDRESS_REGISTER );
                mInstructions.push_back(I);
                I.Clear();
                
        
                
        }
        |
        RETURN EOS
        {
                I.SetCode( EOPERATION_ADD );
                I.mComment = "Restore previous function frame offset";
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetSrc1Address(SPR_CONTROL_REGISTER);
                I.SetSrc1SwizzleX(SWX_Y);
                I.SetSrc1SwizzleY(SWY_Y);
                I.SetSrc1SwizzleZ(SWZ_Y);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                mInstructions.push_back( I );
                I.Clear();
        
                I.SetImm( 0 );
                I.SetCode( EOPERATION_ADD );
                I.mComment = "return from function";
                I.SetBranchFlag( true );
                I.SetBranchType( EBRANCH_ALWAYS );
                I.SetDestinationAddress( RETURN_ADDRESS_REGISTER );
                mInstructions.push_back(I);
                I.Clear();
        }
        
         |
         left_hand_side ADD_EQ constant EOS
          {
                
                 I.mSourceLine = GetCurrentLineNumber( yylloc );
                 I.SetCode( EOPERATION_ADD );
                 SetDestinationFromRegister( $1, I , true);
                 unsigned int ImmediateValue;
                 std::string StringHex = $3;
                 std::stringstream ss;
                 ss << std::hex << StringHex;
                 ss >> ImmediateValue;
                 I.SetImm( ImmediateValue );
                 I.SetDestZero( false );
                 
                 mInstructions.push_back( I );
                 I.Clear();
         }
         |
         left_hand_side MINUS MINUS EOS
         {
                
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetCode( EOPERATION_ADD );
                SetDestinationFromRegister( $1, I, false );
                I.SetSrc0SignX( true );
                I.SetSrc0SignY( true );
                I.SetSrc0SignZ( true );
                std::string Destination = $1;
                if (Destination.find("OFFSET") != std::string::npos)
                {
                        I.SetSrc1Displace( true );
                        Destination.erase(Destination.find("OFFSET"));
                }
                        
                if (Destination.find(".") != std::string::npos)
                        Destination.erase(Destination.find("."));
                
                
                I.SetSrc1Address(atoi(Destination.c_str()+1));
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_Y);
                I.SetSrc0SwizzleY(SWY_Y);
                I.SetSrc0SwizzleZ(SWZ_Y);
                mInstructions.push_back( I );
                I.Clear();
         }
         |
         left_hand_side ADD ADD EOS
         {
                
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetCode( EOPERATION_ADD );
                SetDestinationFromRegister( $1, I, false );
                std::string Destination = $1;
                if (Destination.find("OFFSET") != std::string::npos)
                {
                        I.SetSrc1Displace( true );
                        Destination.erase(Destination.find("OFFSET"));
                }
                        
                if (Destination.find(".") != std::string::npos)
                        Destination.erase(Destination.find("."));
                
                I.SetSrc1Address(atoi(Destination.c_str()+1));
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_Y);
                I.SetSrc0SwizzleY(SWY_Y);
                I.SetSrc0SwizzleZ(SWZ_Y);
                mInstructions.push_back( I );
                I.Clear();
         }
         |
         left_hand_side ASSIGN expression  EOS
        {
                
                //////////////////////////////////////////////////////////////////////////////
                // This means this that the expression will write into the output memory
                // constant index
                //////////////////////////////////////////////////////////////////////////////
        
                if ($1.find("OUT") != std::string::npos && $1.find("INDEX") == std::string::npos )
                {
                        //PopulateInstruction( "R0", "R0 . X X X",$3,I,yylloc);
                        
                        I.SetCode(EOPERATION_OUT); 
                        $1.erase($1.find("OUT"),3);
                        
                        unsigned int ImmediateValue;
                        std::stringstream ss;
                        ss << std::hex << $1;
                        ss >> ImmediateValue;
                        PopulateInstruction( $3, "R0 OFFSET", "R0 OFFSET", I, yylloc, true, ImmediateValue );
                        #ifdef DEBUG
                        I.PrintFields();
                        #endif
                        mInstructions.push_back(I);
                        I.Clear();
                        ResetTempRegisterIndex();
                        goto LABEL_EXPRESSION_DONE;
                }
                //////////////////////////////////////////////////////////////////////////////
                // This means this that the expression will write into the output memory
                // variable index
                //////////////////////////////////////////////////////////////////////////////
        
                if ($1.find("OUT") != std::string::npos && $1.find("INDEX") != std::string::npos )
                {
                        std::string Destination = $1;
                        DCOUT << "!!!!!!!!!!!!!!!!!Destination " << Destination << "\n";
                        std::string IndexRegister = Destination.substr(Destination.find("INDEX")+5);
                        Destination.erase(Destination.find("INDEX"));
                        
                        
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                                
                //      PopulateSourceRegisters( IndexRegister + " OFFSET ", $3, I, mInstructions );
                        PopulateSourceRegisters( IndexRegister, $3, I, mInstructions );
                        
                        
                        //I.SetImm( 0 );
                        I.SetCode( EOPERATION_OUT );
                        std::string Source0 = $3;
                        DCOUT << "!!!!!!!!!!!!!!!!!Source0 '" << Source0 << "'\n";
                /*      if (Source0.find("OFFSET") != std::string::npos)
                        {
                                        Source0.erase(Source0.find("OFFSET"));
                                        I.SetSrc0Displace(1);
                        }
                        I.SetSrc1Address(atoi(IndexRegister.c_str()+1));
                        I.SetSrc0Address(atoi(Source0.c_str()+1));*/
                        
                /*      if (Destination.find(".") != std::string::npos)
                        {
                                I.ClearWriteChannel();
                                if (Destination.find("x") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_X);
                                if (Destination.find("y") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Y);
                                if (Destination.find("z") != std::string::npos)
                                        I.SetWriteChannel(ECHANNEL_Z);

                                Destination.erase(Destination.find("."));
                                                
                        }
                                
                        std::string Source0 = $3;
                        if (Source0.find("OFFSET") != std::string::npos)
                        {
                                        Source0.erase(Source0.find("OFFSET"));
                                        I.SetSrc0Displace(1);
                        }
                        I.SetSrc1Address(atoi(IndexRegister.c_str()+1));
                        I.SetSrc0Address(atoi(Source0.c_str()+1));
                                        
                                        
                                //      I.SetSrc0Address(mInstructions.back().GetDestinationAddress());
                        I.SetDestZero(0);
                        I.SetSrc1Displace(1);
                        I.SetSrc0Displace(1);
                        I.SetDestinationAddress( atoi(Destination.c_str()+1) );*/
                        mInstructions.push_back( I );
                        I.Clear();
                        ResetTempRegisterIndex();
                        goto LABEL_EXPRESSION_DONE;
                }
                //////////////////////////////////////////////////////////////////////////////
                // This means this that the expression was just a constant.
                // No operations were inserted
                //////////////////////////////////////////////////////////////////////////////
                if (gInsertedInstructions == 0)
                {
                        
                        I.Clear();
                        
                        I.SetCode(EOPERATION_ADD);
                        I.mSourceLine = GetCurrentLineNumber(yylloc);
                        if ($3.find("R") != std::string::npos)
                        {
                        // case 1:
                        // foo = 0;        //$$ = R0 . X X X
                        /*      SetDestinationFromRegister( $1, I, false );
                                PopulateSourceRegisters( $3, "R0 . X X X", I, mInstructions);*/
                                
                                PopulateInstruction( $1, "R0 . X X X",$3,I,yylloc);
                        
                        } else {
                        // case 2:
                        // foo = 0xcafe;  //$$ = 0xcafe
                                SetDestinationFromRegister( $1, I, true );
                                unsigned int ImmediateValue = 0;
                                std::string StringHex = $3;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                                        
                                PopulateInstruction( $1, $3,"NULL",I, yylloc, true, ImmediateValue);
                        }
                        std::string strConstant = $3;
                        
                        mInstructions.push_back(I);
                        I.Clear();
                        ResetTempRegisterIndex();
                        goto LABEL_EXPRESSION_DONE;
                }
                
                //////////////////////////////////////////////////////////////////////////////
                // This means that the last instruction which was inserted was a tripple 
                // constant assignement, like foo = (1,2,3)
                //////////////////////////////////////////////////////////////////////////////
                if (mInstructions.back().mBisonFlagTrippleConstAssign)
                {
                        unsigned int LastIndex = mInstructions.size() - 1;
                        mInstructions[LastIndex].SetDestinationAddress(atoi($1.c_str()+1));
                        mInstructions[LastIndex-1].SetDestinationAddress(atoi($1.c_str()+1));
                        mInstructions[LastIndex-2].SetDestinationAddress(atoi($1.c_str()+1));
                        mInstructions[LastIndex-2].mSourceLine = GetCurrentLineNumber( yylloc );
                        if($1.find("OFFSET") == std::string::npos)
                        {
                                mInstructions[LastIndex].SetAddressingMode(true,false,false);
                                mInstructions[LastIndex-1].SetAddressingMode(true,false,false);
                                mInstructions[LastIndex-2].SetAddressingMode(true,false,false);
                        }
                        
                        ResetTempRegisterIndex();
                        goto LABEL_EXPRESSION_DONE;
                }
                //////////////////////////////////////////////////////////////////////////////
                // Handle the case where the destination is an array of vector
                // ej: R = v1[ i ]  + V2
                //////////////////////////////////////////////////////////////////////////////
                if (I.GetOperation() == 0 && $3.find("array_element") != std::string::npos)
                {
                        //No operation meaning the the expression only has a single variable
                        //See if the expression returned is an array_element 
                        if ($3.find("array_element") != std::string::npos)
                        {
                                ////std::cout << "expression is an array element\n\n";
                                std::string Index = $3.substr($3.find("array_element"));
                                Index = Index.substr(Index.find_first_not_of("array_element R"));
                                SetIndexRegister( atoi(Index.c_str()), mInstructions );
                                $3.erase($3.find("array_element"));
                                SetExpressionDestination( $1, I );
                                I.SetCode(EOPERATION_ADD);
                                I.SetImmBit( true );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( true ); 
                                I.SetSrc0Displace( false ); 
                                I.mSourceLine = GetCurrentLineNumber(yylloc);
                                
                                if ($3.find("OFFSET") != std::string::npos)
                                        $3.erase($3.find("OFFSET"));
                                        
                                I.SetSrc1Address(atoi($3.c_str()+1));
                                I.SetSrc0Address(0);
                                mInstructions.push_back(I);
                                I.Clear();
                        }
                } 
                else 
                {
                
                                mInstructions[ mInstructions.size() - gInsertedInstructions].mSourceLine = GetCurrentLineNumber(yylloc);
                                gInsertedInstructions = 0;              
                                std::string Destination = $1;
                                //std::cout << "DST " << Destination << " \n";
                                //Look for indirect addressing
                                if (Destination.find("INDEX") != std::string::npos)
                                {
                                        
                                        std::string IndexRegister = Destination.substr(Destination.find("INDEX")+5);
                                        
                                        Destination.erase(Destination.find("INDEX"));
                                        
                                        I.SetImm( 0 );
                                        I.SetCode( EOPERATION_ADD );
                                        
                                        if (Destination.find(".") != std::string::npos)
                                        {
                                                I.ClearWriteChannel();
                                                if (Destination.find("x") != std::string::npos)
                                                        I.SetWriteChannel(ECHANNEL_X);
                                                if (Destination.find("y") != std::string::npos)
                                                        I.SetWriteChannel(ECHANNEL_Y);
                                                if (Destination.find("z") != std::string::npos)
                                                        I.SetWriteChannel(ECHANNEL_Z);

                                                Destination.erase(Destination.find("."));
                                                
                                        }
                                
                                        std::string Source0 = $3;
                                        if (Source0.find("OFFSET") != std::string::npos)
                                        {
                                                Source0.erase(Source0.find("OFFSET"));
                                                I.SetSrc0Displace(1);
                                        }
                                        I.SetSrc1Address(atoi(IndexRegister.c_str()+1));
                                        I.SetSrc0Address(atoi(Source0.c_str()+1));
                                        
                                        
                                //      I.SetSrc0Address(mInstructions.back().GetDestinationAddress());
                                        I.SetDestZero(0);
                                        I.SetSrc1Displace(1);
                                        I.SetSrc0Displace(1);
                                        I.SetDestinationAddress( atoi(Destination.c_str()+1) );
                                        mInstructions.push_back( I );
                                        I.Clear();
                                } else {
                                        
                                        if (mInstructions.back().GetImm())
                                        {
                                                //Look for displament addressing mode
                                                unsigned int AddressingMode = mInstructions.back().GetAddressingMode();
                                                if (Destination.find("OFFSET") != std::string::npos)
                                                {
                                                        //This means AddressMode is '101', so leave the way it is
                                                        mInstructions.back().ClearWriteChannel();
                                                        mInstructions.back().SetWriteChannel(ECHANNEL_Z);
                                                        Destination.erase(Destination.find("OFFSET"));
                                                } else {
                                                        //This is not supposed to have index, so change addressing mode to '100'
                                                        
                                                        mInstructions.back().SetDestZero( true );
                                                        mInstructions.back().SetSrc1Displace( false );
                                                        mInstructions.back().SetSrc0Displace( false );
                                                        mInstructions.back().ClearWriteChannel();
                                                        mInstructions.back().SetWriteChannel(ECHANNEL_Z);
                                                }
                                                
                                        } else {
                                                mInstructions.back().SetDestZero( false ); //First assume no offset was used
                                                
                                                
                                                
                                                //Look for displament addressing mode
                                                if (Destination.find("OFFSET") != std::string::npos)
                                                {
                                                        Destination.erase(Destination.find("OFFSET"));
                                                        mInstructions.back().SetDestZero( true ); //When Imm != 0, DestZero means DST = DSTINDEX + offset
                                                }
                                        }       
                                                if (Destination.find(".") != std::string::npos)
                                                {
                                                        mInstructions.back().ClearWriteChannel();
                                                        if (Destination.find("x") != std::string::npos)
                                                                mInstructions.back().SetWriteChannel(ECHANNEL_X);
                                                        if (Destination.find("y") != std::string::npos)
                                                                mInstructions.back().SetWriteChannel(ECHANNEL_Y);
                                                        if (Destination.find("z") != std::string::npos)
                                                                mInstructions.back().SetWriteChannel(ECHANNEL_Z);

                                                        Destination.erase(Destination.find("."));
                                                        
                                                }
                                                mInstructions.back().SetDestinationAddress( atoi($1.c_str()+1) );
                                                for (int i = 1; i <= gExtraDestModifications; i++ )
                                                {
                                                        int idx = (mInstructions.size()-1)-i;
                                                        mInstructions[idx].SetDestinationAddress( atoi($1.c_str()+1) );
                                                        if (mInstructions[idx].GetImm())
                                                        {
                                                                        
                                                                //This is not supposed to have index, so change addressing mode to '100'
                                                                mInstructions[idx].SetDestZero( true );
                                                                mInstructions[idx].SetSrc1Displace( false );
                                                                mInstructions[idx].SetSrc0Displace( false );
                                                                                
                                                                                
                                                        }
                                                        
                                                }
                                                gExtraDestModifications = 0;
                                        
                                        
                                        
                                }
                                ResetTempRegisterIndex();
                }
                
                LABEL_EXPRESSION_DONE:
                gInsertedInstructions = 0;
                while(0);
                
        }
        |
        WHILE { /*Middle rule here, get me the loop address*/ ;gWhileLoopAddress = (mInstructions.size());}OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE OPEN_BRACE statement_list CLOSE_BRACE
        {
                mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size()+1);
                gBranchStack.pop_back();
                //Now I need to put a GOTO so that the while gets evaluated again...
                //jump out of the if
           I.Clear();
           I.SetCode( EOPERATION_ADD );
           I.mComment = "while loop goto re-eval boolean";
           I.SetDestinationAddress( gWhileLoopAddress );
           I.SetBranchFlag( true );
           I.SetBranchType( EBRANCH_ALWAYS );
           mInstructions.push_back(I);
           I.Clear();
        
        }
        | IF 
          OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE 
          OPEN_BRACE statement_list CLOSE_BRACE
      ELSE 
        { 
         
           //jump out of the if
           I.Clear();
           I.SetCode( EOPERATION_ADD );
           I.SetBranchFlag( true );
           I.SetBranchType( EBRANCH_ALWAYS );
           mInstructions.push_back(I);
           I.Clear();
           //Take care of the destination addr of the if statement.
           mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size());
          gBranchStack.pop_back();
          //push the inconditional jump into the stack
          gBranchStack.push_back(mInstructions.size() - 1);
          ////std::cout << "else\n";
          
        } 
          OPEN_BRACE  statement_list CLOSE_BRACE
        {
           
           mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size());
           gBranchStack.pop_back();
           //Now push the JMP
           
                ////std::cout << "END elseif\n";
        }
        |
        //NOW the if statement
        IF OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE OPEN_BRACE statement_list CLOSE_BRACE  
        {
                mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size());
                //mInstructions[gBranchStack.back()].mSourceLine = GetCurrentLineNumber(yylloc);
                
                gBranchStack.pop_back();
                ////std::cout << "if closing at " << mInstructions.size() << "\n";
                
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////                                                                                                                                                                                                             /////
        /////   Function declaration                                                                                                                                                              /////
        /////                                                                                                                                                                                                             /////
        /////   function <function-name> ( [ <arg1>, ... ,<arg6> ])                                                                                                       /////
        /////   {                                                                                                                                                                                                         /////
        /////    <statement-list>                                                                                                                                                                         /////
        /////                                                                                                                                                                                                             /////
        /////   }                                                                                                                                                                                                         /////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        |
        FUNCTION IDENTIFIER OPEN_ROUND_BRACE function_argument_list CLOSE_ROUND_BRACE
        {
          DCOUT << "Function declaration for " << $2 << " at " << mInstructions.size() << "\n" ;
          mSymbolMap[ $2 ] = mInstructions.size();
        } OPEN_BRACE statement_list CLOSE_BRACE
        {
                //Clear the auto var index now that we leave the function scope
                ClearAutoVarMap();
                ClearFunctionParameterMap();
                
                //Now uddate the current SPR_CONTROL_REGISTER.x = SPR_CONTROL_REGISTER.y
                I.SetCode( EOPERATION_ADD );
                I.mComment = "Restore previous function frame offset";
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetSrc1Address(SPR_CONTROL_REGISTER);
                I.SetSrc1SwizzleX(SWX_Y);
                I.SetSrc1SwizzleY(SWY_Y);
                I.SetSrc1SwizzleZ(SWZ_Y);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                
                mInstructions.push_back( I );
                I.Clear();
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////                                                                                                                                                                                                             /////
        /////   Thread declaration                                                                                                                                                                        /////
        /////                                                                                                                                                                                                             /////
        /////   thread <thread-name> ( )                                                                                                                                                          /////
        /////   {                                                                                                                                                                                                         /////
        /////    <statement-list>                                                                                                                                                                         /////
        /////                                                                                                                                                                                                             /////
        /////   }                                                                                                                                                                                                         /////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        |
        //Thread declaration
        THREAD IDENTIFIER OPEN_ROUND_BRACE CLOSE_ROUND_BRACE
        {
                gThreadMap[ $2 ] = mInstructions.size();
                gThreadScope = true;
        }
        OPEN_BRACE statement_list CLOSE_BRACE
        {
                ////std::cout << "Defining thread" << "\n";
                gThreadScope = false;
                ClearAutoVarMap();
                //Since the thread is done, then disable threading
                I.SetCode( EOPERATION_ADD );
                I.mComment = "Disable multi-threading";
                I.SetDestinationAddress( SPR_CONTROL_REGISTER0 );
                unsigned int Value = 0;
                I.SetImm( Value );
                I.SetDestZero( true );
                I.SetWriteChannel(ECHANNEL_Z);
                mInstructions.push_back( I );
                I.Clear();
        
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////                                                                                                                                                                                                             /////
        /////   Start thread                                                                                                                                                                              /////
        /////                                                                                                                                                                                                             /////
        /////   start <thread-name> ( );                                                                                                                                                          /////
        /////                                                                                                                                                                                                             /////
        /////                                                                                                                                                                                                             /////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        |
        START IDENTIFIER OPEN_ROUND_BRACE CLOSE_ROUND_BRACE EOS
        {
                unsigned int ThreadCodeOffset = 0;
                ////std::cout << "Starting thread" << "\n";
                if (gThreadMap.find($2) == gThreadMap.end())
                {
                        
                        std::ostringstream ret;
                        ret << "Undefined thread '" << $2 << "' at line " << yylloc << " \n";
                        ret << "Current version of the compiler needs thread defintion prior of thread instantiation\n";
                        throw ret.str();
                } else {
                        ThreadCodeOffset = gThreadMap[$2];
                        //Now enable the multithreading and set instruction offset
                        I.SetCode( EOPERATION_ADD );
                        std::ostringstream ss;
                        ss << "Set thread instruction offset to 8'd" << ThreadCodeOffset;
                        I.mComment = ss.str();
                        I.SetDestinationAddress( SPR_CONTROL_REGISTER0 );
                        unsigned int Value = (ThreadCodeOffset << 1);
                        I.SetImm( Value );
                        I.SetDestZero( true );
                        I.SetWriteChannel(ECHANNEL_Z);
                        mInstructions.push_back( I );
                        I.Clear();
                        
                         
                        I.SetCode( EOPERATION_ADD );
                        I.mComment = "Enable multi-threading";
                        I.SetDestinationAddress( SPR_CONTROL_REGISTER0 );
                        Value = (ThreadCodeOffset << 1 | 1);
                        I.SetImm( Value );
                        I.SetDestZero( true );
                        I.SetWriteChannel(ECHANNEL_Z);
                        mInstructions.push_back( I );
                        I.Clear();
                        
                }
                
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////                                                                                                                                                                                                             /////
        /////   Function call and assign return value to variable                                                                                                         /////
        /////                                                                                                                                                                                                             /////
        /////   <variable> = <function-name> ( [ <arg1>, ... ,<arg6> ]);                                                                                          /////
        /////                                                                                                                                                                                                             /////
        /////                                                                                                                                                                                                             /////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        |
        left_hand_side ASSIGN IDENTIFIER OPEN_ROUND_BRACE function_input_list CLOSE_ROUND_BRACE EOS
        {
                ////std::cout << "Function call returning to var\n";
                StoreReturnAddress( mInstructions, yylloc );
                SavePreviousFramePointer( mInstructions );
                UpdateFramePointer( mInstructions );
                CallFunction( $3, mInstructions, mSymbolMap );
                
                
                //Return value comes in R1, so let's store this in our variable
                I.SetCode( EOPERATION_ADD );
                SetDestinationFromRegister( $1, I, false );
                I.mComment = "grab the return value from the function";
                I.SetSrc1Address( RETURN_VALUE_REGISTER);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                mInstructions.push_back( I );
                I.Clear();
                ClearNextFunctionParamRegister();
        }
        |
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /////                                                                                                                                                                                                             /////
        /////   Function call (return value is ignored)                                                                                                                           /////
        /////                                                                                                                                                                                                             /////
        /////   <function-name> ( [ <arg1>, ... ,<arg6> ]);                                                                                                                       /////
        /////                                                                                                                                                                                                             /////
        /////                                                                                                                                                                                                             /////
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        IDENTIFIER  OPEN_ROUND_BRACE function_input_list CLOSE_ROUND_BRACE EOS
        {
        
                //Store the return address      
                StoreReturnAddress( mInstructions, yylloc );
        
        
                //Store the current SPR_CONTROL_REGISTER.x into the previous SPR_CONTROL_REGISTER.y
                //SPR_CONTROL_REGISTER.y = SPR_CONTROL_REGISTER.xxx + 0;
                I.SetCode( EOPERATION_ADD );
                I.mComment = "store current frame offset";
                I.SetWriteChannel(ECHANNEL_Y);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetSrc1Address(SPR_CONTROL_REGISTER);
                I.SetSrc1SwizzleX(SWX_X);
                I.SetSrc1SwizzleY(SWY_X);
                I.SetSrc1SwizzleZ(SWZ_X);
                I.SetSrc0Address(0);
                I.SetSrc0SwizzleX(SWX_X);
                I.SetSrc0SwizzleY(SWY_X);
                I.SetSrc0SwizzleZ(SWZ_X);
                mInstructions.push_back( I );
                I.Clear();
                //Now uddate the current SPR_CONTROL_REGISTER.x += number of auto variables
                I.SetCode( EOPERATION_ADD );
                I.mComment = "displace next frame offset by the number of auto variables in current frame";
                I.SetWriteChannel(ECHANNEL_X);
                I.SetDestinationAddress( SPR_CONTROL_REGISTER );
                I.SetImm( GetCurretAutoVarFrameSize() );
                I.SetDestZero( false );
                mInstructions.push_back( I );
                I.Clear();
                //Call the function with a JMP
                I.SetCode( EOPERATION_ADD );
                I.mComment = "call the function";
                I.SetBranchFlag( true );
                I.SetBranchType( EBRANCH_ALWAYS );
                
                //Now assign the destination of the branch (our function virtual address)
                if (mSymbolMap.find($1) == mSymbolMap.end())
                {
                        //The destination is not yet declared
                        //so leave it as a symbol so that it can latter
                        //resolved by the linker
                        I.SetDestinationSymbol( "@"+$1 );
                } else {
                        //The destination symbol has already been declared
                        //so assign it right away
                        I.SetDestinationAddress( mSymbolMap[ $1 ] );
                }
                
                //Push the last instruction in the sequence and clean up        
                mInstructions.push_back( I );
                I.Clear();
                
        }
        ;
        
        
        
        function_input_list
                                          :
                                          |//empty
                                          expression COMMA function_input_list
                                          {
                                                AddFunctionInputList( $1, mInstructions,yylloc );
                                          }
                                          |
                                          expression
                                          {
                                                AddFunctionInputList( $1,mInstructions, yylloc );
                                          }
                                          ;

        function_argument_list
                                                :
                                                | //empty
                                                IDENTIFIER COMMA function_argument_list
                                                {
                                                        AddFunctionParameter( $1, yylloc );
                                                }
                                                |
                                                IDENTIFIER
                                                {
                                                        AddFunctionParameter( $1, yylloc );
                                                }
                                                ;
        
// <Exp> ::= <Exp> + <Term> |
          // <Exp> - <Term> |
          // <Term>

// <Term> ::= <Term> * <Factor> |
           // <Term> / <Factor> |
           // <Factor>

// <Factor> ::= x | y | ... |
             // ( <Exp> ) |
             // - <Factor> |
             // <Number>
                         
expression
                :
                expression ADD term
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        gExtraDestModifications = 0;
                        
                        I.SetCode( EOPERATION_ADD );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                                
                        PopulateSourceRegisters( $1, $3, I, mInstructions );
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                        
                }
                |
                expression MINUS term
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetCode( EOPERATION_ADD );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetSrc0SignX( true );
                        I.SetSrc0SignY( true );
                        I.SetSrc0SignZ( true );
                                
                        PopulateSourceRegisters( $1, $3, I, mInstructions);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                expression BITWISE_OR term
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetCode( EOPERATION_LOGIC );
                        I.SetLogicOperation( ELOGIC_OR );
                        PopulateSourceRegisters( $1, $3, I, mInstructions);
                        
                                                
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                term
                {
                        $$ = $1;
                }
                ;
                
                term
                :
                term MUL factor
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetCode( EOPERATION_MUL );
                        
                        PopulateSourceRegisters( $1, $3, I, mInstructions);
                        
                        //If we are using fixed point aritmethic then we need to apply the scale
                        //R = A * ( B >> SCALE)
                        if (mGenerateFixedPointArithmetic)
                                I.SetSrc0Rotation( EROT_RESULT_RIGHT );
                        
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                term DIV factor
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetCode( EOPERATION_DIV );
                        
                        PopulateSourceRegisters( $1, $3, I, mInstructions);
                        
                        //If we are using fixed point aritmethic then we need to apply the scale
                        // R = (A << N) / B
                        if (mGenerateFixedPointArithmetic)
                                I.SetSrc1Rotation( EROT_SRC1_LEFT );
                        
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                term BITWISE_AND factor
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetCode( EOPERATION_LOGIC );
                        I.SetLogicOperation( ELOGIC_AND );
                        PopulateSourceRegisters( $1, $3, I, mInstructions);
                        
                                                
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                factor
                {
                        $$ = $1;
                }
                ;
                
                factor
                :
                source
                {
                        $$ = $1;
                }
                |
                SQRT OPEN_ROUND_BRACE expression CLOSE_ROUND_BRACE
                {
                        gExtraDestModifications = 0;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetDestZero( true ); //Use indexing for DST
                        I.SetWriteChannel(ECHANNEL_XYZ);
                        I.SetCode( EOPERATION_SQRT );
                        I.SetSrc0Address( 0 );       
                        PopulateSourceRegisters( $3 ,"R0 . X X X", I, mInstructions);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        
                        std::stringstream ss;
                        ss << "R" << TempRegIndex << " OFFSET ";
                        $$ = ss.str();
                }
                |
                OPEN_ROUND_BRACE expression CLOSE_ROUND_BRACE
                {
                        $$ = $2;
                }
                ;
                
        
        
        source
        :
        constant
        {
        
                unsigned int ImmediateValue;
                std::string StringHex = $1;
                std::stringstream ss;
                ss << std::hex << StringHex;
                ss >> ImmediateValue;
                
                switch (ImmediateValue)
                {
                case 0:
                        $$ = "R0 . X X X";
                break;
                case 1:
                        $$ = "R0 . Y Y Y";
                break;
                case 2:
                        $$ = "R0 . Z Z Z";
                break;
                default:
                        std::string StringHex = $1;
                        std::stringstream ss;
                        ss << std::hex << StringHex;
                        ss >> ImmediateValue;
                        $$ = ss.str();
                        break;
                }
        }
        |
        OPEN_ROUND_BRACE constant COMMA constant COMMA constant CLOSE_ROUND_BRACE
        {
                unsigned int TempRegIndex  = GetFreeTempRegister();
                unsigned int ImmediateValue;
                
                {
                
                std::string StringHex = $2;
                std::stringstream ss;
                ss << std::hex << StringHex;
                ss >> ImmediateValue;
                
                
                I.SetDestinationAddress( TempRegIndex );
                I.SetImm( ImmediateValue );
                I.SetDestZero(true);
                I.SetSrc0Displace(true);
                I.SetWriteChannel(ECHANNEL_X);
                I.SetCode( EOPERATION_ADD );
                mInstructions.push_back(I);
                gInsertedInstructions++;
                I.Clear();
                }
                
                {
                std::string StringHex = $4;
                std::stringstream ss;
                ss << std::hex << StringHex;
                ss >> ImmediateValue;
                
                I.SetDestinationAddress( TempRegIndex );
                I.SetImm( ImmediateValue );
                I.SetDestZero(true);
                I.SetSrc0Displace(true);
                I.SetWriteChannel(ECHANNEL_Y);
                I.SetCode( EOPERATION_ADD );
                mInstructions.push_back(I);
                gInsertedInstructions++;
                I.Clear();
                }
                
                {
                std::string StringHex = $6;
                std::stringstream ss;
                ss << std::hex << StringHex;
                ss >> ImmediateValue;
                
                I.SetDestinationAddress( TempRegIndex );
                I.SetImm( ImmediateValue );
                I.SetDestZero(true);
                I.SetSrc0Displace(true);
                I.SetWriteChannel(ECHANNEL_Z);
                I.SetCode( EOPERATION_ADD );
                I.mBisonFlagTrippleConstAssign = true;
                mInstructions.push_back(I);
                gInsertedInstructions++;
                I.Clear();
                }
                
                gExtraDestModifications = 2;
                std::stringstream ss2;
                ss2 << "R" << TempRegIndex << " OFFSET ";
                $$ = ss2.str();
        }
        |
        IDENTIFIER array_index
        {
                
                
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = Register;
                 else
                        $$ = GetRegisterFromAutoVar( $1, yylloc) + " OFFSET ";
                        
                if ($2 != "NULL")
                {
                                        
                        $$ += " array_element " + $2;
                        
                }
        }
        |
        IDENTIFIER DOT coordinate coordinate coordinate
        {
        
                std::string X = $3,Y = $4,Z = $5;
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = (Register + " . " + " " + X + " " + Y  + " " + Z/* + " OFFSET "*/);
                else
                        $$ = (GetRegisterFromAutoVar( $1, yylloc) + " . " + " " + X + " " + Y  + " " + Z + " OFFSET ");
        }
        |
        REG
        {
                
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R;
                
        }
        |
        SCALE OPEN_ROUND_BRACE REG CLOSE_ROUND_BRACE
        {
        
                std::string R = $1;
                R.erase(0,1);
                $$ = "<<R" + R;
        }
        |
        UNSCALE OPEN_ROUND_BRACE REG CLOSE_ROUND_BRACE
        {
        
                std::string R = $1;
                R.erase(0,1);
                $$ = ">>R" + R;
        }
        |
        REG DOT coordinate coordinate coordinate
        {
                std::string R = $1;
                std::string X = $3,Y = $4,Z = $5;
                R.erase(0,1);
                $$ = "R" + R + " . " + " " + X + " " + Y  + " " + Z;
        
        }
        ;
        
        
        coordinate
        :
        TK_X 
        {
                $$ = "X";
        }
        |
        MINUS TK_X
        {
                $$ = "-X";
        }
        |
        TK_Y
        {
                $$ = "Y";
        }
        |
        MINUS TK_Y
        {
                $$ = "-Y";
        }
        |
        TK_Z
        {
                $$ = "Z";
        }
        |
        MINUS TK_Z
        {
                $$ = "-Z";
        }
        ;       
        
        
array_index
        :
        {
                $$ = "NULL";
        }
        |
        OPEN_SQUARE_BRACE IDENTIFIER CLOSE_SQUARE_BRACE
        {
                /*std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($2)) != "NULL")
                        $$ = Register;
                else*/
                //Indexes into arrays can only be auto variables!
                $$ = GetRegisterFromAutoVar( $2, yylloc );
        }
        ;
        
left_hand_side
        :
        OUT OPEN_SQUARE_BRACE constant CLOSE_SQUARE_BRACE
        {
                
                $$ = "OUT " + $3;
        }
        |
        OUT OPEN_SQUARE_BRACE IDENTIFIER CLOSE_SQUARE_BRACE
        {
        /*
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($3)) == "NULL")
                        Register = GetRegisterFromAutoVar( $3, yylloc );
                
                $$ = "OUT INDEX" + Register;
                */
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($3)) != "NULL")
                        $$ = "OUT INDEX" + Register;
                else    
                        $$ = "OUT INDEX" + GetRegisterFromAutoVar( $3, yylloc ) + " OFFSET ";
                
                
                
        }
        |
        IDENTIFIER array_index
        {
                
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = Register + ".xyz";
                else
                        $$ = GetRegisterFromAutoVar( $1, yylloc ) + ".xyz" + " OFFSET " + (($2 != "NULL")?" INDEX"+$2:"");
                
        } 
        |
        IDENTIFIER DOT TK_X
        {
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = Register + ".x";
                else
                $$ = GetRegisterFromAutoVar( $1, yylloc ) + ".x" + " OFFSET ";
        }
        |
        IDENTIFIER DOT TK_Y
        {
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = Register + ".y";
                else
                        $$ = GetRegisterFromAutoVar( $1, yylloc ) + ".y" + " OFFSET ";
        }
        |
        IDENTIFIER DOT TK_Z
        {
                std::string Register;
                if ((Register = GetRegisterFromFunctionParameter($1)) != "NULL")
                        $$ = Register + ".z";
                else
                        $$ = GetRegisterFromAutoVar( $1, yylloc ) + ".z" + " OFFSET ";
        }
        |
        REG 
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".xyz";
        }
        |
        REG DOT TK_X
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".x";
        }
        |
        REG DOT TK_Y
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".y";
        }
        |
        REG DOT TK_Z
        {
                
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".z";
        }
        |
        REG DOT TK_X TK_Y TK_N
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".xy";
        }
        |
        REG DOT TK_X TK_N TK_Z
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".xz";
        }
        |
        REG DOT TK_N TK_Y TK_Z
        {
                std::string R = $1;
                R.erase(0,1);
                $$ = "R" + R + ".yz";
        }
        ;

        
boolean_expression
                                :
                                expression NOT_EQUAL expression
                                {
                                        PopulateBoolean(EBRANCH_IF_ZERO, $1, $3, I, mInstructions, yylloc );
                                        
                                }
                                |
                                expression EQUAL expression 
                                {
                                        PopulateBoolean(EBRANCH_IF_NOT_ZERO, $1, $3, I, mInstructions, yylloc );
                                        
                                }
                                |
                                expression GREATER_THAN expression
                                {
                                        PopulateBoolean(EBRANCH_IF_ZERO_OR_SIGN, $1, $3, I, mInstructions, yylloc );
                                        
                                }
                                        
                                |
                                expression LESS_THAN expression
                                {
                                        PopulateBoolean(EBRANCH_IF_ZERO_OR_NOT_SIGN, $1, $3, I, mInstructions, yylloc );
                                
                                }
                                |
                                expression LESS_OR_EQUAL_THAN expression
                                {
                                        PopulateBoolean(EBRANCH_IF_NOT_SIGN, $1, $3, I, mInstructions, yylloc );
                                        
                                }                               
                                |
                                expression GREATER_OR_EQUAL_THAN expression
                                {
                                        PopulateBoolean(EBRANCH_IF_SIGN, $1, $3, I, mInstructions, yylloc );
                                        
                                }
                                ;       
        
constant
        :
                DECCONST
                {
                        // Transform to HEX string
                        unsigned int Val;
                        std::string StringDec = $1;
                        std::stringstream ss;
                        ss << StringDec;
                        ss >> Val;
                        std::stringstream ss2;
                        ss2 << std::hex << Val;
                        $$ = ss2.str();
                }
                |
                HEXCONST
                {
                        std::string StringHex = $1;
                        // Get rid of the 0x
                        StringHex.erase(StringHex.begin(),StringHex.begin()+2);
                        std::stringstream ss;
                        ss << std::hex << StringHex;
                        
                        $$ = ss.str();
                }
                |
                BINCONST
                {
                        // Transform to HEX string
                        std::string StringBin = $1;
                        // Get rid of the 0b
                        StringBin.erase(StringBin.begin(),StringBin.begin()+2);
                        std::bitset<32> Bitset( StringBin );
                        std::stringstream ss2;
                        ss2 << std::hex <<  Bitset.to_ulong();
                        $$ = ss2.str();
                }
        ;
auto_var_list
                        :
                        IDENTIFIER array_size COMMA auto_var_list
                        {
                                if (gAutoVarMap.find($1) != gAutoVarMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol '" << $1 << "'\n";
                                        throw ret.str();
                                }
                                
                                std::stringstream ss;
                                ss << $2;
                                unsigned int Size;
                                ss >> Size;
                                gAutoVarMap[ $1 ] = AllocAutoVar(Size);
                        }
                        |
                        IDENTIFIER ASSIGN OPEN_ROUND_BRACE constant COMMA constant COMMA constant CLOSE_ROUND_BRACE COMMA auto_var_list
                        {
                                if (gAutoVarMap.find($1) != gAutoVarMap.end())
                                {
                                std::ostringstream ret;
                                ret << "Duplicated symbol " << $1 << "'\n";
                                throw ret.str();
                                }
                                gAutoVarMap[ $1 ] = AllocAutoVar();
                                
                                unsigned int Destination = gAutoVarMap[ $1 ];
                
                                        
                
                                I.ClearWriteChannel();
                                unsigned int ImmediateValue;
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_X);
                                std::string StringHex = $4;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_Y);
                                std::string StringHex = $6;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_Z);
                                std::string StringHex = $8;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                        }
                        |
                        IDENTIFIER ASSIGN OPEN_ROUND_BRACE constant COMMA constant COMMA constant CLOSE_ROUND_BRACE
                        {
                                if (gAutoVarMap.find($1) != gAutoVarMap.end())
                                {
                                std::ostringstream ret;
                                ret << "Duplicated symbol " << $1 << "'\n";
                                throw ret.str();
                                }
                                gAutoVarMap[ $1 ] = AllocAutoVar();
                                
                                unsigned int Destination = gAutoVarMap[ $1 ];
                
                        
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                
                
                                I.ClearWriteChannel();
                                unsigned int ImmediateValue;
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_X);
                                std::string StringHex = $4;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_Y);
                                std::string StringHex = $6;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                                {
                                I.SetDestinationAddress( Destination );
                                I.SetWriteChannel(ECHANNEL_Z);
                                std::string StringHex = $8;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                I.SetImm( ImmediateValue );
                                I.SetDestZero( true );
                                I.SetSrc1Displace( false );
                                I.SetSrc0Displace( true );
                                I.SetCode( EOPERATION_ADD );
                                mInstructions.push_back(I);
                                I.Clear();
                                }
                        }
                        |
                        IDENTIFIER array_size
                        {
                                
                                if (gAutoVarMap.find($1) != gAutoVarMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol " << $1 << "'\n";
                                        throw ret.str();
                                }
                                std::stringstream ss;
                                ss << std::hex << $2;
                                unsigned int Size;
                                ss >> Size;
                                ////std::cout  << "Array Size is " << Size << " " << $2 << "\n";
                                gAutoVarMap[ $1 ] = AllocAutoVar(Size);
                        }
                        ;

array_size
                 :
                 {
                 $$ = "1";
                 }
                 |
                 OPEN_SQUARE_BRACE constant CLOSE_SQUARE_BRACE
                 {
                
                 $$ = $2;
                 }
                 ;
%%



// Error function throws an exception (std::string) with the location and error message
void Theia::Parser::error(const Theia::Parser::location_type &loc,
                                          const std::string &msg) {
        std::ostringstream ret;
        ret << "Parser Error at " << loc << ": "  << msg;
        throw ret.str();
}

// Now that we have the Parser declared, we can declare the Scanner and implement
// the yylex function
#include "Scanner.h"
static int yylex(Theia::Parser::semantic_type * yylval,
                 Theia::Parser::location_type * yylloc,
                 Theia::Scanner &scanner) {
        return scanner.yylex(yylval, yylloc);
}

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.