Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/assembly label handling #6

Merged
merged 3 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/MimaSim/MimaSim/Core/Parsing/Emiting/ByteArrayBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,52 @@ public void Dispose()
_store.Dispose();
}

public void ReplaceAt(int index, byte value)
{
ValidateIndex(index);
var buffer = _store.GetBuffer();
buffer[index] = value;
}

public void ReplaceAt(int index, bool value)
{
ValidateIndex(index);
ReplaceAt(index, value ? streamTrue : streamFalse);
}

public void ReplaceAt(int index, char value)
{
ValidateIndex(index);
ReplaceAt(index, (byte)value);
}

public void ReplaceAt(int index, short value)
{
ValidateIndex(index);
var bytes = BitConverter.GetBytes(value);
Array.Copy(bytes, 0, _store.GetBuffer(), index, bytes.Length);
}

public void ReplaceAt(int index, int value)
{
ValidateIndex(index);
var bytes = BitConverter.GetBytes(value);
Array.Copy(bytes, 0, _store.GetBuffer(), index, bytes.Length);
}

public void ReplaceAt(int index, long value)
{
ValidateIndex(index);
var bytes = BitConverter.GetBytes(value);
Array.Copy(bytes, 0, _store.GetBuffer(), index, bytes.Length);
}

private void ValidateIndex(int index)
{
if (index < 0 || index >= Length)
throw new ArgumentOutOfRangeException(nameof(index), "Index is out of range.");
}

public bool GetBool()
{
return _store.ReadByte() == streamTrue;
Expand Down
37 changes: 27 additions & 10 deletions src/MimaSim/MimaSim/Core/Parsing/Emiting/ByteCodeEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ namespace MimaSim.Core.Parsing.Emiting;
public class ByteCodeEmitter
{
private readonly ByteArrayBuilder _builder = new();

private readonly Dictionary<string, byte> _labels = new();
private int _labelCount = 0;
private readonly Dictionary<string, short> _labels = new();
private readonly List<short> _labelReferences = new();
public int Position => _builder.Length;

public void Append(byte[] raw)
Expand All @@ -18,7 +17,7 @@ public void Append(byte[] raw)

public Label DefineLabel()
{
return new Label(_labelCount++);
return new Label(_labels.Count);
}

public void EmitInstruction(OpCodes opcode)
Expand Down Expand Up @@ -61,19 +60,37 @@ public void EmitRegister(Registers reg)
_builder.Append((byte)reg);
}

public byte GetLabel(string name)
public void AddLabelReference()
{
return _labels[name];
_labelReferences.Add((short)_builder.Length);
_builder.Append((short)0);
}

public void MarkLabel(Label label)
private void ReplaceLabelReferences()
{
_labels.Add("L" + label.LabelNum, (byte)_builder.Length);
foreach (var kvp in _labels)
{
int index = 0;
while (index < _labelReferences.Count)
{
if (_labelReferences[index] == kvp.Value)
{
_builder.ReplaceAt(index, kvp.Value);
}
index++;
}
}

_labelReferences.Clear();
}

public byte[] ToArray() => _builder.ToArray();
public byte[] ToArray()
{
ReplaceLabelReferences(); // Ensure labels are replaced before converting to array
return _builder.ToArray();
}

internal void CreateLabel(string name)
public void CreateLabel(string name)
{
_labels.Add(name, (byte)_builder.Length);
}
Expand Down
2 changes: 1 addition & 1 deletion src/MimaSim/MimaSim/MIMA/Instructions/LoadInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public bool Invoke(CPU cpu)

public void Dissassemble(StringBuilder builder, Disassembler disassembler)
{
builder.AppendLine($"load {disassembler.Fetch16()}");
builder.AppendLine($"load 0x{disassembler.Fetch16():X2}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public bool Invoke(CPU cpu)

public void Dissassemble(StringBuilder builder, Disassembler disassembler)
{
builder.AppendLine($"mov {disassembler.Fetch16()}, {disassembler.Fetch16()}");
builder.AppendLine($"mov 0x{disassembler.Fetch16():X2}, 0x{disassembler.Fetch16():X2}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ public bool Invoke(CPU cpu)

public void Dissassemble(StringBuilder builder, Disassembler disassembler)
{
builder.AppendLine($"mov {disassembler.Fetch16()}, {disassembler.FetchRegister()}");
builder.AppendLine($"mov 0x{disassembler.Fetch16():X2}, {disassembler.FetchRegister()}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public bool Invoke(CPU cpu)

public void Dissassemble(StringBuilder builder, Disassembler disassembler)
{
builder.AppendLine($"mov {disassembler.FetchRegister()}, {disassembler.Fetch16()}");
builder.AppendLine($"mov {disassembler.FetchRegister()}, 0x{disassembler.Fetch16():X2}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,25 @@ public AssemblyVisitor()
For<InstructionNode>(Visit);
For<LiteralNode>(VisitLiteral, node => node.Value is ulong);
For<LiteralNode>(VisitRegister, node => node.Value is Registers);
For<PrefixOperatorNode>(VisitAddress, op => op.Operator == "&");
For<PrefixOperatorNode>(VisitAddress, op => op.Tag == "address");
For<PrefixOperatorNode>(VisitLabelRef, op => op.Tag == "labelref");
For<PostfixOperatorNode>(VisitLabel, op => op.Tag == "label");
}

private void VisitLabel(PostfixOperatorNode labelDef)
{
if (labelDef.Expr is NameNode nameNode)
{
_emitter.CreateLabel(nameNode.Token.Text.ToString());
}
}

private void VisitLabelRef(PrefixOperatorNode labelRef)
{
if (labelRef.Expr is NameNode nameNode)
{
//todo: emit 0 address and adjust later in GetRaw()
}
}

private void VisitAddress(PrefixOperatorNode obj)
Expand Down
2 changes: 1 addition & 1 deletion src/MimaSim/MimaSim/MIMA/Visitors/HighParserVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private void VisitIfStatement(CallNode call)
private void VisitLoopStatement(CallNode call)
{
var label = _emitter.DefineLabel();
_emitter.MarkLabel(label);
// _emitter.MarkLabel(label);

Visit((CallNode)call.Args.First());

Expand Down
Loading