MicroVM.Assembler.cs
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace MicroVM {
clast astembler {
List statements = new List();
public Dictionary symbols = new Dictionary();
public List errors = new List();
public List programData = new List();
public List instructions = new List();
public List code = new List();
public byte[] memory = null;
public int numInstructions;
List isrs = new List();
Regex directiveRegex = new Regex(@"^\.([a-zA-Z_][a-zA-Z0-9_]*)$");
Regex labelRegex = new Regex(@"^([a-zA-Z_][a-zA-Z0-9_]*):$");
Regex identifierRegex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]*$");
Regex instructionRegex = new Regex(@"^([a-zA-Z_][a-zA-Z0-9_]*)\.(al|eq|ne|gt|ge|lt|le)$");
Regex floatRegex = new Regex(@"^[+-]?[0-9]?[\.][0-9]*$");
Regex decimalRegex = new Regex(@"^[+-]?[0-9]+$");
Regex hexRegex = new Regex(@"^([+-])?0x([0-9a-zA-Z]+)$");
Regex binRegex = new Regex( @"^([+-])?0b([01]+)$");
public void Reset() {
statements.Clear();
symbols.Clear();
errors.Clear();
programData.Clear();
instructions.Clear();
code.Clear();
memory = null;
isrs.Clear();
}
struct Statement {
public int lineNum;
public string[] line;
public Token[] tokens;
}
public struct Variable {
public CPU.Value32 val32;
public Type type;
public int size;
public enum Type {
NONE, UNKNOWN, INT, UINT, BYTE, FLOAT
}
}
struct Token {
public enum Type {
NONE,
DIRECTIVE,
LABEL,
INSTRUCTION,
IDENTIFIER,
INTEGER,
FLOAT
}
public int offset;
public Type type;
public string stringValue;
public Variable var;
public string cond;
}
public struct Symbol {
public string name;
public Variable var;
public int labelInstructionIndex;
public Type type;
public enum Type {
NONE,
LABEL,
LITERAL,
CONSTANT,
REGISTER
}
}
public void LoadProgramToCPU(CPU cpu) {
cpu.Reset();
cpu.instructions = new uint[numInstructions];
cpu.memory = new byte[memory.Length];
memory.CopyTo(cpu.memory, 0);
cpu.registers[(int)CPU.Register.SP] = (uint)programData.Count;
cpu.pc = symbols["_start"].var.val32.Uint;
int instructionIndex = 0;
for(int i = 0; i < instructions.Count; i++) {
var instruction = instructions[i];
cpu.instructions[instructionIndex++] = instruction.Create();
if(instruction.additionalInstructions == null) {
continue;
}
for(int j = 0; j < instruction.additionalInstructions.Length; j++) {
cpu.instructions[instructionIndex++] = instruction.additionalInstructions[j];
}
}
cpu.flags |= (uint)CPU.Flag.READY;
}
public struct Instruction {
public CPU.Opcode opcode;
public CPU.Cond cond;
public List operands;
public Symbol immediate;
public int address;
public uint[] additionalInstructions;
public int AdditionalInstructions(bool ignoreLabelAddresses) {
if(immediate.type == Symbol.Type.NONE || (immediate.type == Symbol.Type.LABEL && ignoreLabelAddresses)) {
return 0;
}
if(immediate.var.type == Variable.Type.FLOAT) {
return 1;
} else if(immediate.var.type == Variable.Type.UNKNOWN) {
return immediate.var.size / sizeof(uint);
} else if(immediate.var.type == Variable.Type.INT) {
if(immediate.var.val32.Uint >= GetMaxImmediateValue(operands.Count + 1)) {
return 1;
}
}
return 0;
}
public uint Create() {
uint instruction = (uint)cond