public static void ReplaceAddressWithSymbolInProgramLine(ProgramLine instructionLine, int addressParameterIndexToReplace, bool addressIsRelative, string symbolName) { if (addressParameterIndexToReplace == 0 || addressParameterIndexToReplace == 1) { if (instructionLine.OpCodeParameters != null && instructionLine.OpCodeParameters.Count > 0) { InstructionLineParam paramToReplace = instructionLine.OpCodeParameters[addressParameterIndexToReplace]; // Find token to replace AsmToken tokenToReplace = paramToReplace.Tokens.FirstOrDefault <AsmToken>(t => t.Type == AsmTokenType.NUMBER); if (tokenToReplace != null) { // Generate new text for the line, replacing only the address token StringBuilder lineText = new StringBuilder(); foreach (AsmToken token in instructionLine.AllTokens) { if ((!addressIsRelative && token != tokenToReplace) || !paramToReplace.Tokens.Contains(token)) { lineText.Append(token.TextWithLeadingWhiteSpace); } else if (token == tokenToReplace) { if (tokenToReplace.LeadingWhiteSpace != null) { lineText.Append(tokenToReplace.LeadingWhiteSpace.Text); } else if (addressIsRelative && (paramToReplace.Tokens[0] != tokenToReplace)) { if (paramToReplace.Tokens[0].LeadingWhiteSpace != null) { lineText.Append(paramToReplace.Tokens[0].LeadingWhiteSpace.Text); } } lineText.Append(symbolName); } } // Parse new line from text ProgramLine newTextLine = Assembler.ParseProgramLine(lineText.ToString()); // Copy textual representation to the original program Line instructionLine.CopyTextualRepresentationFrom(newTextLine); } } } }
// Param type : Address | Bit | FlagCondition | Flags | IOPortRegister | // Indexed | InterruptMode | Number | Register | Register16 | RegisterIndirect // opcodeparam := *OPENINGPAR numexpr CLOSINGPAR | *BIT | *FLAGCONDITION | *FLAGS | *OPENINGPAR REGISTER CLOSINGPAR | // *OPENINGPAR REGISTER16 (PLUS|MINUS) numexpr CLOSINGPAR | *INTERRUPTMODE | *numexpr | *REGISTER | *REGISTER16 | *OPENINGPAR REGISTER16 CLOSINGPAR private void ParseOpcodeParam() { AsmToken nextToken = lexer.PeekNextToken(); if (nextToken.Type == AsmTokenType.BIT) { AsmToken bitToken = lexer.GetNextToken(); InstructionLineParam bitParam = new InstructionLineParam() { Type = InstructionLineParamType.Bit, Bit = AsmLexer.ParseBitToken(bitToken.Text) }; bitParam.Tokens.Add(bitToken); prgLine.OpCodeParameters.Add(bitParam); } else if (nextToken.Type == AsmTokenType.FLAGCONDITION) { AsmToken flagConditionToken = lexer.GetNextToken(); InstructionLineParam flagConditionParam = new InstructionLineParam() { Type = InstructionLineParamType.FlagCondition, FlagCondition = AsmLexer.ParseFlagConditionToken(flagConditionToken.Text) }; flagConditionParam.Tokens.Add(flagConditionToken); prgLine.OpCodeParameters.Add(flagConditionParam); } else if (nextToken.Type == AsmTokenType.FLAGS) { AsmToken flagsToken = lexer.GetNextToken(); InstructionLineParam flagsParam = new InstructionLineParam() { Type = InstructionLineParamType.Flags }; flagsParam.Tokens.Add(flagsToken); prgLine.OpCodeParameters.Add(flagsParam); } else if (nextToken.Type == AsmTokenType.INTERRUPTMODE) { AsmToken interruptModeToken = lexer.GetNextToken(); InstructionLineParam interruptModeParam = new InstructionLineParam() { Type = InstructionLineParamType.InterruptMode, InterruptMode = AsmLexer.ParseInterruptModeToken(interruptModeToken.Text) }; interruptModeParam.Tokens.Add(interruptModeToken); prgLine.OpCodeParameters.Add(interruptModeParam); } else if (nextToken.Type == AsmTokenType.REGISTER) { AsmToken registerToken = lexer.GetNextToken(); InstructionLineParam registerParam = new InstructionLineParam() { Type = InstructionLineParamType.Register, Register = AsmLexer.ParseRegisterToken(registerToken.Text) }; registerParam.Tokens.Add(registerToken); prgLine.OpCodeParameters.Add(registerParam); } else if (nextToken.Type == AsmTokenType.REGISTER16) { AsmToken register16Token = lexer.GetNextToken(); InstructionLineParam register16Param = new InstructionLineParam() { Type = InstructionLineParamType.Register16, Register16 = AsmLexer.ParseRegister16Token(register16Token.Text) }; register16Param.Tokens.Add(register16Token); prgLine.OpCodeParameters.Add(register16Param); } else if (nextToken.Type == AsmTokenType.OPENINGPAR) { lexer.StartTokenList(); InstructionLineParam resultLineParam = null; lexer.ConsumeToken(); nextToken = lexer.PeekNextToken(); if (nextToken.Type == AsmTokenType.REGISTER) { AsmToken registerToken = lexer.GetNextToken(); InstructionLineParam registerParam = new InstructionLineParam() { Type = InstructionLineParamType.IOPortRegister, Register = AsmLexer.ParseRegisterToken(registerToken.Text) }; resultLineParam = registerParam; prgLine.OpCodeParameters.Add(registerParam); } else if (nextToken.Type == AsmTokenType.REGISTER16) { AsmToken register16Token = lexer.GetNextToken(); Register16 register16 = AsmLexer.ParseRegister16Token(register16Token.Text); nextToken = lexer.PeekNextToken(); if (nextToken.Type == AsmTokenType.PLUS || nextToken.Type == AsmTokenType.MINUS) { AsmToken operatorToken = lexer.GetNextToken(); NumberExpression numberExpression = ParseNumberExpression(); NumberExpression displacementExpression = null; if (operatorToken.Type == AsmTokenType.PLUS) { displacementExpression = numberExpression; } else if (operatorToken.Type == AsmTokenType.MINUS) { displacementExpression = new NumberOperationExpression( new NumberOperand(0), NumberOperationType.Subtraction, numberExpression); } InstructionLineParam indexedParam = new InstructionLineParam() { Type = InstructionLineParamType.Indexed, Register16 = register16, NumberExpression = displacementExpression }; resultLineParam = indexedParam; prgLine.OpCodeParameters.Add(indexedParam); } else { InstructionLineParam register16Param = new InstructionLineParam() { Type = InstructionLineParamType.RegisterIndirect, Register16 = register16 }; resultLineParam = register16Param; prgLine.OpCodeParameters.Add(register16Param); } } else { NumberExpression numberExpression = ParseNumberExpression(); InstructionLineParam numberParam = new InstructionLineParam() { Type = InstructionLineParamType.Address, NumberExpression = numberExpression }; resultLineParam = numberParam; prgLine.OpCodeParameters.Add(numberParam); } nextToken = lexer.PeekNextToken(); if (nextToken.Type == AsmTokenType.CLOSINGPAR) { lexer.ConsumeToken(); } else { throw new Exception(String.Format("Line {0} : Expecting closing parenthesis ) at column {1} instead of {2} : {3}", lineNumber, nextToken.StartIndex, nextToken.Type.ToString(), nextToken.Text)); } ((List<AsmToken>)resultLineParam.Tokens).AddRange(lexer.EndTokenList()); } else { lexer.StartTokenList(); NumberExpression numberExpression = ParseNumberExpression(); InstructionLineParam numberParam = new InstructionLineParam() { Type = InstructionLineParamType.Number, NumberExpression = numberExpression }; prgLine.OpCodeParameters.Add(numberParam); ((List<AsmToken>)numberParam.Tokens).AddRange(lexer.EndTokenList()); } }
private static void AddOperandForLineParam(ref int address, IList<Operand> operands, ProgramLine programLine, AddressingMode? paramType, InstructionLineParam lineParam) { Operand operand = null; switch (paramType.Value) { // 8 bit unsigned operand case AddressingMode.Immediate: case AddressingMode.IOPortImmediate: operand = new Operand() { Type = OperandType.Unsigned8, Address = address, Expression = lineParam.NumberExpression, Line = programLine}; address += 1; break; // 8 bit signed operand case AddressingMode.Indexed: case AddressingMode.Relative: operand = new Operand() { Type = OperandType.Signed8, Address = address, Expression = lineParam.NumberExpression, Line = programLine }; address += 1; if (paramType.Value == AddressingMode.Relative && operand.Expression is SymbolOperand) { // If a label address is used where a relative address is expected, // we have to compute the relative displacement from the current addres to the label address operand.Expression = new RelativeDisplacementFromLabelAddressExpression((SymbolOperand)operand.Expression, NumberOperationType.Subtraction, new NumberOperand(address)); } else if (paramType.Value == AddressingMode.Relative && operand.Expression is NumberOperand) { // Relative adressing mode definition (DJNZ and JR instructions) : // The jump is measured from the address of the instruction OpCode and has a range of -126 to +129 bytes. // The assembler automatically adjusts for the twice incremented PC. operand.Expression = new NumberOperationExpression(operand.Expression, NumberOperationType.Subtraction, new NumberOperand(2)); } break; // 16 bit unsigned operand case AddressingMode.Immediate16: case AddressingMode.Extended: operand = new Operand() { Type = OperandType.Unsigned16, Address = address, Expression = lineParam.NumberExpression, Line = programLine}; address += 2; break; } if (operand != null) { operands.Add(operand); } }