private void SkipWhiteSpace(Assembly6809TokenParser parser) { var pt = parser.Peek(); while (pt?.TokenPeek != null && pt.TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Whitespace) { parser.GetToken(); pt = parser.Peek(); } }
private void IgnoreLine(Assembly6809TokenParser parser) { var pt = parser.Peek(); while (pt?.TokenPeek != null && pt.TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Newline) { parser.GetToken(); pt = parser.Peek(); } }
private void LdxImmediate(Assembly6809TokenParser parser, List<byte> byteList, bool labelScan) { parser.GetToken(); string expression = GetExpression(parser); ushort parsedExpression = ParseExpression(expression, labelScan); byte lsb = (byte)(parsedExpression & 0xFFu); byte msb = (byte)((parsedExpression >> 8) & 0xFFu); byteList.Add(0x8E); byteList.Add(msb); byteList.Add(lsb); _numberOfBytes += 3; }
private void LdaImmediate(Assembly6809TokenParser parser, List<byte> byteList, bool labelScan) { parser.GetToken(); string expression = GetExpression(parser); ushort parsedExpression = ParseExpression(expression, labelScan); if (parsedExpression > 255) { throw new Exceptions.OverflowException($"Overflow error at line {_lineNumber}"); } byte lsb = (byte)(parsedExpression & 0xFFu); byteList.Add(0x86); byteList.Add(lsb); _numberOfBytes += 2; }
public byte[] Assemble(string program) { _labelTable.Clear(); _lineNumberTable.Clear(); _equateTable.Clear(); _lineNumber = 1; _numberOfBytes = 0; var byteList = new List<byte>(); var parser = new Assembly6809TokenParser { InputString = program }; var token = parser.GetToken(); // Phase 1 - Scan for labels and build up our label table while (token != null) { string line = ""; while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Newline) { line += token.TokenValue; token = parser.GetToken(); } line += '\n'; ParseLine(line, true); _lineNumber++; token = parser.GetToken(); } _lineNumber = 1; parser = new Assembly6809TokenParser { InputString = program }; token = parser.GetToken(); // Phase 2 - Actually assemble the program while (token != null) { string line = ""; while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Newline) { line += token.TokenValue; token = parser.GetToken(); } line += '\n'; byteList.AddRange(ParseLine(line, false)); _lineNumber++; token = parser.GetToken(); } return byteList.ToArray(); }
private string GetExpression(Assembly6809TokenParser parser) { string exp = ""; SkipWhiteSpace(parser); var token = parser.GetToken(); while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Newline) { exp = exp + token.TokenValue; SkipWhiteSpace(parser); token = parser.GetToken(); } return exp; }
private ushort ParseExpression(Assembly6809TokenParser parser, Assembly6809TokenParser.Tokens delimiter, bool labelScan) { SkipWhiteSpace(parser); if (parser.Peek() == null || parser.Peek().TokenPeek == null) { throw new Exceptions.UnexpectedEndOfLineException($"Unexpected End of Line on line {_lineNumber}"); } var token = parser.Peek()?.TokenPeek; string exp = ""; while (token != null && token.TokenName != delimiter) { token = parser.GetToken(); exp += token.TokenValue; if (parser.Peek() == null || parser.Peek().TokenPeek == null) break; token = parser.Peek()?.TokenPeek; } return ParseExpression(exp, labelScan); }
private List<byte> ParseLine(string line, bool labelScan) { var byteList = new List<byte>(); var parser = new Assembly6809TokenParser { InputString = line }; var token = parser.GetToken(); string lastLabel = ""; while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Newline) { if (token.TokenName == Assembly6809TokenParser.Tokens.Identifier && labelScan) { if (_labelTable.ContainsKey(token.TokenValue.Trim().ToUpper())) { throw new Exceptions.LabelDefinedMoreThanOnceException( $"The label {token.TokenValue.Trim().ToUpper()} has been defined more than once, on lines {_lineNumberTable[token.TokenValue.Trim().ToUpper()]} and {_lineNumber}"); } if (_equateTable.ContainsKey(token.TokenValue.Trim().ToUpper())) { throw new Exceptions.LabelDefinedMoreThanOnceException( $"The label {token.TokenValue.Trim().ToUpper()} has been defined more than once, on lines {_lineNumberTable[token.TokenValue.Trim().ToUpper()]} and {_lineNumber}"); } _labelTable.Add(token.TokenValue.Trim().ToUpper(), _numberOfBytes); lastLabel = token.TokenValue.Trim().ToUpper(); _lineNumberTable.Add(token.TokenValue.Trim().ToUpper(), _lineNumber); token = parser.GetToken(); continue; } else if (token.TokenName == Assembly6809TokenParser.Tokens.Identifier && !labelScan) { token = parser.GetToken(); continue; } string expression; ushort parsedExpression; byte msb; byte lsb; switch (token.TokenName) { case Assembly6809TokenParser.Tokens.End: SkipWhiteSpace(parser); if (parser.Peek() == null || parser.Peek().TokenPeek == null || parser.Peek().TokenPeek.TokenName != Assembly6809TokenParser.Tokens.Identifier) { throw new Exceptions.InvalidLabelException($"Invalid label on line {_lineNumber}"); } token = parser.GetToken(); if (!_labelTable.ContainsKey(token.TokenValue.Trim().ToUpper()) && !labelScan) { throw new Exceptions.UndefinedLabelException($"The label {token.TokenValue.Trim().ToUpper()} is not defined in line {_lineNumber}"); } ExecutionAddress = (ushort)(_labelTable[token.TokenValue.Trim().ToUpper()] + _origination); break; case Assembly6809TokenParser.Tokens.Equ: if (string.IsNullOrWhiteSpace(lastLabel) || !_labelTable.ContainsKey(lastLabel)) { throw new Exceptions.LabelRequiredException( $"An EQU instruction requires a label to precede it, on line {_lineNumber}!"); } _labelTable.Remove(lastLabel); SkipWhiteSpace(parser); token = parser.GetToken(); string exp = ""; while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Newline) { exp = exp + token.TokenValue; SkipWhiteSpace(parser); token = parser.GetToken(); } _equateTable.Add(lastLabel, ParseExpression(exp, labelScan)); lastLabel = ""; break; case Assembly6809TokenParser.Tokens.Org: SkipWhiteSpace(parser); expression = GetExpression(parser); _origination = ParseExpression(expression, labelScan); break; case Assembly6809TokenParser.Tokens.Lda: SkipWhiteSpace(parser); if (parser.Peek() != null && parser.Peek().TokenPeek != null && parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.PoundSign) // LDA Immediate { LdaImmediate(parser, byteList, labelScan); } break; case Assembly6809TokenParser.Tokens.Ldx: SkipWhiteSpace(parser); if (parser.Peek() != null && parser.Peek().TokenPeek != null && parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.PoundSign) // LDX Immediate { LdxImmediate(parser, byteList, labelScan); } break; case Assembly6809TokenParser.Tokens.Rts: SkipWhiteSpace(parser); Rts(parser, byteList); IgnoreLine(parser); break; case Assembly6809TokenParser.Tokens.Sta: SkipWhiteSpace(parser); if (parser.Peek() != null && parser.Peek().TokenPeek != null && (parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Comma || parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Decrement1 || parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Integer || parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.BinaryNumber || parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.HexNumber || parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Identifier)) // STA Indexed { StaIndexed(parser, byteList, labelScan); } break; } token = parser.GetToken(); } return byteList; }
private void StaIndexed(Assembly6809TokenParser parser, List<byte> byteList, bool labelScan) { ushort indexValue = 0; bool negate = false; if (parser.Peek() != null && parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Comma) { parser.GetToken(); } else { var token = parser.GetToken(); if (token.TokenName == Assembly6809TokenParser.Tokens.Decrement1) { negate = true; token = parser.GetToken(); } indexValue = ParseExpression(parser, Assembly6809TokenParser.Tokens.Comma, labelScan); } SkipWhiteSpace(parser); string register = ParseRegister(parser); //if (parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Comma) //{ // parser.GetToken(); //} //else //{ // string expression = ""; // var token = parser.GetToken(); // if (token.TokenName == Assembly6809TokenParser.Tokens.Decrement1) // { // negate = true; // token = parser.GetToken(); // } // while (token != null && token.TokenName != Assembly6809TokenParser.Tokens.Comma) // { // expression += token.TokenValue; // token = parser.GetToken(); // } // ushort parsedExpression = ParseExpression(expression, labelScan); // indexValue = parsedExpression; //} //byte operand = 128; //bool hasByteOperand = false; //bool hasWordOperand = false; //ushort wordOperand = 0; //byte byteOperand = 0; //if (indexValue == 0) //{ // operand = 132; //} //else if (indexValue > 0 && indexValue <= 16) //{ // operand = (byte)indexValue; // if (negate) // { // //operand = (byte) (operand | 16); // operand = ConvertToTwosCompliment(operand); // operand = (byte)(operand & 0x1f); // } //} //else if (indexValue >= 17 && indexValue <= 128) //{ // operand = (byte)(operand | 8); // byteOperand = (byte)(negate ? ConvertToTwosCompliment((byte)indexValue) : indexValue); // hasByteOperand = true; //} //else if (indexValue >= 129) //{ // operand = (byte)(operand | 9); // wordOperand = negate ? ConvertToTwosCompliment(indexValue) : indexValue; // hasWordOperand = true; //} //SkipWhiteSpace(parser); //var registerToken = parser.GetToken(); //if (registerToken.TokenName != Assembly6809TokenParser.Tokens.Register && // registerToken.TokenValue.ToUpper() != "X" && registerToken.TokenValue.ToUpper() != "Y" && // registerToken.TokenValue.ToUpper() != "U" && registerToken.TokenValue.ToUpper() != "S") //{ // throw new Exceptions.InvalidRegisterNameException($"Register is invalid at line {_lineNumber}"); //} //string register = registerToken.TokenValue.ToUpper(); //switch (register) //{ // case "X": // operand = (byte)(operand & 0x9f); // break; // case "Y": // operand = (byte)(operand & 0xbf); // break; // case "U": // operand = (byte)(operand & 0xdf); // break; // case "S": // operand = (byte)(operand & 0xff); // break; //} //SkipWhiteSpace(parser); //if (parser.Peek() != null && parser.Peek().TokenPeek != null && // parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Increment1) //{ // if (indexValue > 0) // { // throw new Exceptions.InvalidOperandException($"Invalid Operand: Cannot increment with an offset at line {_lineNumber}"); // } // operand = (byte)(operand & 0xe0); // parser.GetToken(); //} //if (parser.Peek() != null && parser.Peek().TokenPeek != null && parser.Peek().TokenPeek.TokenName == Assembly6809TokenParser.Tokens.Increment2) { if (indexValue > 0) { throw new Exceptions.InvalidOperandException($"Invalid Operand: Cannot increment with an offset at line {_lineNumber}"); } operand = (byte)(operand & 0xe0); operand = (byte)(operand | 0x01); parser.GetToken(); } byteList.Add(0xA7); byteList.Add(operand); _numberOfBytes += 2; if (hasByteOperand) { byteList.Add(byteOperand); _numberOfBytes += 1; } else if (hasWordOperand) { byteList.Add((byte)((wordOperand >> 8) & 0xFFu)); byteList.Add((byte)(wordOperand & 0xFFu)); _numberOfBytes += 2; } }
private void Rts(Assembly6809TokenParser parser, List<byte> byteList) { byteList.Add(0x39); _numberOfBytes += 1; }