public static AssemblerResult StaticAssembleInstructions(string program) { var memory = new MemoryStream(); var result = new AssemblerResult { Instructions = new StreamStructArrayWrapper <Instruction>(memory), }; var mipsAssembler = new MipsAssembler(memory); mipsAssembler.Assemble(program, result); return(result); }
/* Format codes * %d - Rd * %t - Rt * %s - Rs * %i - 16bit signed immediate * %I - 16bit unsigned immediate (always printed in hex) * %o - 16bit signed offset (rs base) * %O - 16bit signed offset (PC relative) * %j - 26bit absolute offset * %J - Register jump * %a - SA * %0 - Cop0 register * %1 - Cop1 register * %2? - Cop2 register (? is (s, d)) * %p - General cop (i.e. numbered) register * %n? - ins/ext size, ? (e, i) * %r - Debug register * %k - Cache function * %D - Fd * %T - Ft * %S - Fs * %x? - Vt (? is (s/scalar, p/pair, t/triple, q/quad, m/matrix pair, n/matrix triple, o/matrix quad) * %y? - Vs * %z? - Vd * %X? - Vo (? is (s, q)) * %Y - VFPU offset * %Z? - VFPU condition code/name (? is (c, n)) * %v? - VFPU immediate, ? (3, 5, 8, k, i, h, r, p? (? is (0, 1, 2, 3, 4, 5, 6, 7))) * %c - code (for break) * %C - code (for syscall) * %? - Indicates vmmul special exception */ 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('\n').Select(str => str.Trim()).Where(str => str.Length > 0)) { // Strip comments. var parts = line.Split(new[] { ";", "#" }, 2, StringSplitOptions.None); var realLine = parts[0].Trim(); // Directive if (line[0] == '.') { var lineTokens = line.Split(new[] { ' ', '\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 { var 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)) { throw new KeyNotFoundException($"Can't find label '{patch.LabelName}'"); } var labelAddress = labels[patch.LabelName]; OutputStream.Position = patch.Address; var instruction = (Instruction)BinaryReader.ReadUInt32(); { switch (patch.Type) { case AssemblerPatchType.Rel16: instruction.Imm = ((int)labelAddress - (int)patch.Address - 4) / 4; break; case AssemblerPatchType.Abs26: instruction.JumpBits = (labelAddress & PspMemory.MemoryMask) / 4; Console.Write("0x{0:X} : {1}", instruction.JumpBits, patch.LabelName); break; case AssemblerPatchType.Abs32: instruction.Value = labelAddress; break; } } OutputStream.Position = patch.Address; BinaryWriter.Write(instruction.Value); } }
/* Format codes * %d - Rd * %t - Rt * %s - Rs * %i - 16bit signed immediate * %I - 16bit unsigned immediate (always printed in hex) * %o - 16bit signed offset (rs base) * %O - 16bit signed offset (PC relative) * %j - 26bit absolute offset * %J - Register jump * %a - SA * %0 - Cop0 register * %1 - Cop1 register * %2? - Cop2 register (? is (s, d)) * %p - General cop (i.e. numbered) register * %n? - ins/ext size, ? (e, i) * %r - Debug register * %k - Cache function * %D - Fd * %T - Ft * %S - Fs * %x? - Vt (? is (s/scalar, p/pair, t/triple, q/quad, m/matrix pair, n/matrix triple, o/matrix quad) * %y? - Vs * %z? - Vd * %X? - Vo (? is (s, q)) * %Y - VFPU offset * %Z? - VFPU condition code/name (? is (c, n)) * %v? - VFPU immediate, ? (3, 5, 8, k, i, h, r, p? (? is (0, 1, 2, 3, 4, 5, 6, 7))) * %c - code (for break) * %C - code (for syscall) * %? - Indicates vmmul special exception */ 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 + "'")); } } }
public static AssemblerResult StaticAssembleInstructions(string Program) { var Memory = new MemoryStream(); var Result = new AssemblerResult() { Instructions = new StreamStructArrayWrapper<Instruction>(Memory), }; var MipsAssembler = new MipsAssembler(Memory); MipsAssembler.Assemble(Program, Result); return Result; }