public void Assemble(String Lines, AssemblerResult AssemblerResult = null)
{
if (AssemblerResult == null) AssemblerResult = new AssemblerResult();
var Labels = AssemblerResult.Labels;
var Patches = AssemblerResult.Patches;
foreach (var Line in Lines.Split(new char[] { '\n' }).Select(Str => Str.Trim()).Where(Str => Str.Length > 0))
{
// Strip comments.
var Parts = Line.Split(new string[] { ";", "#" }, 2, StringSplitOptions.None);
var RealLine = Parts[0].Trim();
// Directive
if (Line[0] == '.')
{
var LineTokens = Line.Split(new char[] { ' ', '\t' }, 2);
switch (LineTokens[0])
{
case ".code":
OutputStream.Position = ParseIntegerConstant(LineTokens[1]);
break;
default:
throw (new NotImplementedException("Unsupported directive '" + LineTokens[0] + "'"));
}
}
else
{
// Label
if (RealLine.EndsWith(":"))
{
Labels[RealLine.Substr(0, -1).Trim()] = (uint)OutputStream.Position;
}
// Instruction
else
{
uint PC = (uint)OutputStream.Position;
var Instructions = AssembleInstructions(ref PC, RealLine, Patches);
foreach (var Instruction in Instructions)
{
BinaryWriter.Write(Instruction.Value);
}
}
}
}
foreach (var Patch in Patches)
{
if (Labels.ContainsKey(Patch.LabelName))
{
var LabelAddress = Labels[Patch.LabelName];
Instruction Instruction;
OutputStream.Position = Patch.Address;
Instruction = (Instruction)BinaryReader.ReadUInt32();
{
switch (Patch.Type)
{
case AssemblerPatchType.REL_16:
Instruction.IMM = ((int)LabelAddress - (int)Patch.Address - 4) / 4;
break;
case AssemblerPatchType.ABS_26:
Instruction.JUMP_Bits = (LabelAddress & PspMemory.MemoryMask) / 4;
Console.Write("0x{0:X} : {1}", Instruction.JUMP_Bits, Patch.LabelName);
break;
case AssemblerPatchType.ABS_32:
Instruction.Value = LabelAddress;
break;
}
}
OutputStream.Position = Patch.Address; BinaryWriter.Write(Instruction.Value);
}
else
{
throw(new KeyNotFoundException("Can't find label '" + Patch.LabelName + "'"));
}
}
}