Difference between revisions of "Mano pdp8 AssemblerMano.cc"
(Created page with " AssemblerMano.cc -- The assembler interpreter. <PRE> // Mano Assembler #ifndef ASSEMBLERMANO_CC #define ASSEMBLERMANO_CC #ifndef MANO_H #include "mano.h" #endif #ifnde...") |
(No difference)
|
Latest revision as of 16:56, 13 June 2016
AssemblerMano.cc -- The assembler interpreter.
// Mano Assembler #ifndef ASSEMBLERMANO_CC #define ASSEMBLERMANO_CC #ifndef MANO_H #include "mano.h" #endif #ifndef INSTRUCTIONWORD_CC #include "InstructionWord.cc" #endif #ifndef SYMBOLTABLE_CC #include "SymbolTable.cc" #endif #ifndef PROGRAMLINE_CC #include "ProgramLine.cc" #endif #ifndef QUEUE_CC #include "queue.cc" #endif #ifndef CHARSTRING_CC #include "charString.cc" #endif class AssemblerMano { SymbolTable Mano_SymbolTable; queue<ProgramLine> queue_Program; queue<ProgramLine> queue_SecondPass; queue<InstructionWord> queue_AssemblyCode; int i_mHLT; // machine is halted int i_mORG; // there is only one ORG short LocationCounter_short_m; // LC counter void FirstPass( queue<ProgramLine> queue_Program ) { LocationCounter_short_m = 0; // LC <- 0 int i_test = 0; while( !queue_Program.isempty() ) // scan next line of code { i_test++; if( DEBUG ) cout << " AssemblerMano: FirstPass 1" << endl; ProgramLine PL; queue_Program.dequeue( PL ) ; // Check for Label if( IsLabel( PL ) ) { Mano_SymbolTable.LoadSymbol( PL.GetLabel(), PL.GetLineNumber(), LocationCounter_short_m ); IncrementLC(); queue_SecondPass.enqueue( PL ); continue; } if( IsORG( PL ) == VALID_ORG_INSTRUCTION ) { queue_SecondPass.enqueue( PL ); continue; } if( IsEND( PL ) == VALID_END_INSTRUCTION ) { queue_SecondPass.enqueue( PL ); continue; } queue_SecondPass.enqueue( PL ); IncrementLC(); } // end while if( DEBUG ) cout << " AssemblerMano: FirstPass " << i_test << " line processed." << endl; } // FirstPass // Second Pass Methods void SecondPass() // do this { // Set LC to zero. SetLC( 0 ); // Scan the next line of code. while( !queue_SecondPass.isempty() ) { if( DEBUG ) cout << " AssemblerMano: SecondPass 1" << endl; ProgramLine PL; queue_SecondPass.dequeue( PL ); // Check for Pseudo instruction if( IsPseudoInstruction( PL ) ) { // If true decode and scan next line. if( PseudoInstructionTable( PL ) == VALID_END_INSTRUCTION ) break; LoadAssemblyCodeQueue( PL ); IncrementLC(); continue; } if( IsMemoryReferenceInstruction( PL ) ) { MemoryReferenceInstructionTable( PL ); LoadAssemblyCodeQueue( PL ); IncrementLC(); continue; } if( IsNONMemoryReferenceInstruction( PL ) ) { NonMemoryReferenceInstructionTable( PL ); IncrementLC(); continue; } // If the SecondPass gets to here there is an error. // Increment LC. // Scan the next code line. cout << " AssemblerMano: SecondPass: ERROR Line " << LocationCounter_short_m << endl; IncrementLC(); } // while LoadAssemblyCodeQueue } // SecondPass void LoadAssemblyCodeQueue( ProgramLine &PL ) { InstructionWord InstructionWord_Temp; // set LocationCounter InstructionWord_Temp.setlocation( LocationCounter_short_m ); // set Instruction Word InstructionWord_Temp.setdata( PL.GetInstWord() ); // load address at the right memory address queue_AssemblyCode.enqueue( InstructionWord_Temp ); } int IsAddress( int i_Number ) { if( DEBUG ) cout << " AssemblerMano: IsAddress 0" << endl; if( i_Number > MAX_ADDRESS ) { if( DEBUG ) cout << " AssemblerMano: IsAddress 1" << endl; return 0; } if( i_Number < MIN_ADDRESS ) { if( DEBUG ) cout << " AssemblerMano: IsAddress 2" << endl; return 0; } if( DEBUG ) cout << " AssemblerMano: IsAddress 3" << endl; return 1; } // IsAddress( unsigned short sl_Number ) int IsNumber( int ul_Number ) { if( DEBUG ) cout << " AssemblerMano: IsNumber 0" << endl; if( ul_Number > MAX_PLUS ) return NUMBER_OVER_MAX; if( ul_Number < MAX_MINUS ) return NUMBER_UNDER_MINUS_MIN; return VALID_NUMBER; } // IsNumber( int ul_Number ) // Label Methods int IsLabel( ProgramLine &PL ) { // The first character must be a letter. // The label can be one, two or three // characters long. charString charString_Temp = PL.GetLabel(); if( charString_Temp.IsAlphaNum( 1 ) && ( charString_Temp.length() <= LABEL_LENGTH ) ) return true; else return false; } // int IsLabel( ProgramLine &PL ) // Memory Methods int IsMemoryReferenceInstruction( ProgramLine &PL ) { // Valid Memory Reference Instructions from // chapter 5, table 5-4 on page 145. if( PL.GetInstruction() == "AND" ) return true; if( PL.GetInstruction() == "ADD" ) return true; if( PL.GetInstruction() == "LDA" ) return true; if( PL.GetInstruction() == "STA" ) return true; if( PL.GetInstruction() == "BUN" ) return true; if( PL.GetInstruction() == "BSA" ) return true; if( PL.GetInstruction() == "ISZ" ) return true; return false; } // IsMemoryReferenceInstruction( ProgramLine &PL ) int IsNONMemoryReferenceInstruction( ProgramLine &PL ) { // Register Reference Instructions if( PL.GetInstruction() == "CIL" ) return 1; if( PL.GetInstruction() == "CIR" ) return 1; if( PL.GetInstruction() == "CLA" ) return 1; if( PL.GetInstruction() == "CLE" ) return 1; if( PL.GetInstruction() == "CMA" ) return 1; if( PL.GetInstruction() == "CME" ) return 1; if( PL.GetInstruction() == "HLT" ) return 1; if( PL.GetInstruction() == "INC" ) return 1; if( PL.GetInstruction() == "SNA" ) return 1; if( PL.GetInstruction() == "SPA" ) return 1; if( PL.GetInstruction() == "SZA" ) return 1; if( PL.GetInstruction() == "SZE" ) return 1; // Input-Output Instructions if( PL.GetInstruction() == "INP" ) return 1; if( PL.GetInstruction() == "OUT" ) return 1; if( PL.GetInstruction() == "SKI" ) return 1; if( PL.GetInstruction() == "SKO" ) return 1; if( PL.GetInstruction() == "IOF" ) return 1; if( PL.GetInstruction() == "ION" ) return 1; return 0; } // IsNONMemoryReferenceInstruction( ProgramLine &PL ) void MemoryReferenceInstructionTable( ProgramLine &PL ) { if( DEBUG ) cout << " AssemblerMano: Memory_Reference_Instruction_Table 0" << endl; short us_data = 0; short s_Idicator = 0; // determine Indirection if( PL.GetIndirection() == "I" ) { us_data += def_I; } // add indirection s_Idicator = Mano_SymbolTable.Search( PL.GetLabel() ); if( s_Idicator > -1 ) { us_data += s_Idicator; } if( PL.GetInstruction() == "AND" ) { us_data += def_AND; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "ADD" ) { us_data += def_ADD; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "LDA" ) { us_data += def_LDA; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "STA" ) { us_data += def_STA; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "BUN" ) { us_data += def_BUN; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "BSA" ) { us_data += def_BSA; PL.SetInstWord( us_data ); } if( PL.GetInstruction() == "ISZ" ) { us_data += def_ISZ; PL.SetInstWord( us_data ); } } // void Memory_Reference_Instruction_Table void NonMemoryReferenceInstructionTable( ProgramLine PL ) { if( DEBUG ) cout << " AssemblerMano: Non_Memory_Reference_Instruction_Table 0" << endl; // Register Reference Instructions if( PL.GetInstruction() == "CIL" ) PL.SetInstWord( def_CIL ); if( PL.GetInstruction() == "CIR" ) PL.SetInstWord( def_CIR ); if( PL.GetInstruction() == "CLA" ) PL.SetInstWord( def_CLA ); if( PL.GetInstruction() == "CLE" ) PL.SetInstWord( def_CLE ); if( PL.GetInstruction() == "CMA" ) PL.SetInstWord( def_CMA ); if( PL.GetInstruction() == "CME" ) PL.SetInstWord( def_CME ); if( PL.GetInstruction() == "HLT" ) { i_mHLT = VALID_HLT_INSTRUCTION; PL.SetInstWord( def_HLT ); } if( PL.GetInstruction() == "INC" ) PL.SetInstWord( def_INC ); if( PL.GetInstruction() == "SNA" ) PL.SetInstWord( def_SNA ); if( PL.GetInstruction() == "SPA" ) PL.SetInstWord( def_SPA ); if( PL.GetInstruction() == "SZA" ) PL.SetInstWord( def_SZA ); if( PL.GetInstruction() == "SZE" ) PL.SetInstWord( def_SZE ); // Input-Output Instructions if( PL.GetInstruction() == "INP" ) PL.SetInstWord( def_INP ); if( PL.GetInstruction() == "OUT" ) PL.SetInstWord( def_OUT ); if( PL.GetInstruction() == "SKI" ) PL.SetInstWord( def_SKI ); if( PL.GetInstruction() == "SKO" ) PL.SetInstWord( def_SKO ); if( PL.GetInstruction() == "IOF" ) PL.SetInstWord( def_IOF ); if( PL.GetInstruction() == "ION" ) PL.SetInstWord( def_ION ); } // NonMemoryReferenceInstructionTable // Pseudo Instruction Methods int IsPseudoInstruction( ProgramLine PL ) { // Valid Pseudo Instructions are. // ORG Origin Address // END End program // HEX Hexadecimal Number // DEC Decimal Number // OCT Octal Number if( PL.GetInstruction() == "ORG" ) return true; if( PL.GetInstruction() == "HEX" ) return true; if( PL.GetInstruction() == "DEC" ) return true; if( PL.GetInstruction() == "OCT" ) return true; if( PL.GetInstruction() == "END" ) return true; return false; } // IsPseudoInstruction( ProgramLine PL ) int PseudoInstructionTable( ProgramLine &PL ) { // charString charString_Instruction, charString charString_Command, short s_Location // Decode Pseudo Instruction // Carry out appropriate action // Instruction Action // ORG Decode number and set LocationCounter_short_m to it. // END set i_mEND to VALID_END_INSTRUCTION // HEX Decode hexadcimal number and place in location pointed to by LocationCounter_short_m // DEC Decode decimal number and place in location pointed to by LocationCounter_short_m // OCT Decode octal number and place in location pointed to by LocationCounter_short_m // Default return value is NON_PSEUDO_INSTRUCTION // Success return value is VALID_PSEUDO_INSTRCTION if( DEBUG ) cout << " AssemblerMano: PseudoInstructionTable 0" << endl; int i_ReturnValue = 0; if( IsORG( PL ) == VALID_ORG_INSTRUCTION) return VALID_ORG_INSTRUCTION; if( IsEND( PL ) == VALID_END_INSTRUCTION ) return VALID_END_INSTRUCTION; // Check for DEC, HEX if( PL.GetInstruction() == "HEX" ) { DecodeNumber( PL, 16 ); return VALID_PSEUDO_INSTRUCTION; } if( PL.GetInstruction() == "DEC" ) { DecodeNumber( PL, 10 ); return VALID_PSEUDO_INSTRUCTION; } if( PL.GetInstruction() == "OCT" ) { DecodeNumber( PL, 8 ); return VALID_PSEUDO_INSTRUCTION; } return NON_PSEUDO_INSTRUCTION; } // PseudoInstructionTable int IsEND( ProgramLine &PL ) { // Check for END if( PL.GetInstruction() == "END" ) { PL.SetInstWord( VALID_END_INSTRUCTION ); return VALID_END_INSTRUCTION; } return INVALID_END_INSTRUCTION; } // IsEND( ProgramLine PL ) int IsORG( ProgramLine &PL ) { // Check for ORG if( DEBUG ) cout << " AssemblerMano: IsORG 0" << endl; if( PL.GetInstruction() == "ORG" ) { // ORG is always a hexadecimal number DecodeNumber( PL, 16 ); int i_ReturnValue = PL.GetInstWord(); if( IsAddress( i_ReturnValue ) ) { SetLC( i_ReturnValue ); return VALID_ORG_INSTRUCTION; } else return INVALID_ORG_INSTRUCTION; } return INVALID_ORG_INSTRUCTION; } // IsORG( ProgramLine PL ) void DecodeNumber( ProgramLine &PL, int Base_int ) { // Convert string to valid number and return // Assume number without a pseudoinstruction is hexadecimal. // Assume strings are trimmed front and back long l_ReturnValue = 0; l_ReturnValue = PL.GetOperand().toLong( Base_int ); PL.SetInstWord( l_ReturnValue ); } // DecodeNumber // LocationCounter Utilities void SetLC( short s ) { LocationCounter_short_m = s; } void IncrementLC() { LocationCounter_short_m++; } public: AssemblerMano() { LocationCounter_short_m = 0; i_mHLT = 0; i_mORG = 0; } ~AssemblerMano(){} SymbolTable GetSymbolTable() { return Mano_SymbolTable; } queue<InstructionWord> GetAssemblyCode() { return queue_AssemblyCode; } // Error check and assemble the program short AssembleProgram( queue<ProgramLine> queue_Program ) { if( DEBUG ) cout << " AssemblerMano: AssembleProgram 0" << endl; // check for more than MAX_ADDRESS if( !IsAddress( queue_Program.census() ) ) { if( DEBUG ) cout << " AssemblerMano: Assembler 1" << endl; return 0; } // First Pass if( DEBUG ) cout << " AssemblerMano: Assembler 2" << endl; FirstPass( queue_Program ); // Second Pass if( DEBUG ) cout << " AssemblerMano: Assembler 3" << endl; SecondPass(); if( DEBUG ) cout << " AssemblerMano: Assembler 4" << endl; return 1; } // Assembler( queue) }; #endif // AssemblerMano_CC
Internal Links
Parent Article: Mano PDP-8 Simulation Project Source Code