/// <summary> /// only for instructions that use labels /// </summary> /// <param name="Assembly.AddressingMethod"></param> /// <param name="pc"></param> void setValue(Assembly.AddressingMethod AddressingMethod, ushort pc) { int nval = 0; try { nval = ComputedValue.GetNumeral(); } catch (FormatException ex) { throw new SyntaxErrorException("Invalid label or literal", ex); } int fnval = nval; if (AddressingMethod == Assembly.AddressingMethod.relative) { nval -= ((ushort)pc + 2); } int onval = nval; if (nval < 0) { nval = Assembly.TwosComplement8bit(nval); } if (nval > ushort.MaxValue) { throw new SyntaxErrorException("Value out of range: " + nval + ", it first was " + fnval + ", after possible relative subtraction is was " + onval + ", then if so it was complemented to " + nval); } setValue(nval); return; }
/// <summary> /// Populate the ComputedValue object with the results determined from the earlier-set ValueLeft, ValueMiddle, ValueRight, and OpCode /// For use on the second pass for opcodes that use a label /// </summary> /// <param name="opcode"></param> /// <param name="Assembly.AddressingMethod"></param> /// <param name="pc"></param> public void ParseValue(Assembly.OpCode opcode, Assembly.AddressingMethod AddressingMethod, ushort pc) { if (!(labelUsers.Contains(opcode))) { return; } parseValue(); setValue(AddressingMethod, pc); return; }
/// <summary> /// Determines addressing method of a line /// </summary> /// <param name="assembler"></param> public void DetermineAddressingMethod(AssemblerConfig config) { if (this.OpCode == null) { throw new InvalidOperationException("Attempt to determine addressing method of non-statement"); } if (this.RValue == null) { this.AddressingMethod = Assembly.AddressingMethod.implied; return; } //will include branches, jmp, implied, accumulator (shown as implied if (Assembly.OpcodeTable[OpCode.Value].Keys.Count == 1) { AddressingMethod = Assembly.OpcodeTable[OpCode.Value].Keys.First(); return; } //branches and jumps were already detected before this point this.RValue.ParseValue(this.OpCode.Value); var result = this.RValue.ComputedValue; var choices = RValue.LineEndingToOptions[this.RValue.ValueRight].Where( choice => Assembly.OpcodeTable[this.OpCode.Value].Keys.Contains(choice) ).ToList(); if (choices.Count == 0) { throw new SyntaxErrorException("Illegal addressing method for opcode"); } if (choices.Count == 1) { this.AddressingMethod = choices.First(); return; } if (result.Literal) { this.AddressingMethod = Assembly.AddressingMethod.immediate; return; } choices.Remove(Assembly.AddressingMethod.immediate); if (choices.Count == 0) { throw new SyntaxErrorException("Illegal addressing method for opcode"); } if (choices.Count == 1) { this.AddressingMethod = choices.First(); return; } Assembly.AddressingMethod lo = choices.Where(choice => Assembly.AddressingMethodLength[choice] == 1).First(); Assembly.AddressingMethod hi = choices.Where(choice => Assembly.AddressingMethodLength[choice] == 2).First(); switch (config.OperandLength) { case AssemblerConfig.OperandLengthOption.Longest: this.AddressingMethod = hi; return; case AssemblerConfig.OperandLengthOption.Smallest: if (result.Result > byte.MaxValue) { this.AddressingMethod = hi; return; } this.AddressingMethod = lo; return; case AssemblerConfig.OperandLengthOption.AsWritten: //Only works in binary and hex because they're the ones where one extra digit is the point where it goes from one byte to two if (result.Base == 2 || result.Base == 16) { //maximum characters before there are more characters than necessary to represent 256 int bumpLimit = result.Base == 2 ? 8 : 2; if (result.ValueString.Length > bumpLimit) { this.AddressingMethod = hi; return; } this.AddressingMethod = lo; return; } if (result.Result > byte.MaxValue) { this.AddressingMethod = hi; return; } this.AddressingMethod = lo; return; } throw new SyntaxErrorException("Unable to determine addressing method"); }