private static Dictionary<int, Opcode> Assemble(List<Line> source) { Dictionary<int, Opcode> binary = new Dictionary<int, Opcode>(); Opcode op = null; RomItem[] ria = null; int address = 0; // 1st pass [Parse each command] foreach (Line line in source) { op = AssembleLine(line); if (op != null) { // regular instruction if (!op.Pseudo) { ria = new RomItem[1]; ria[0] = new RomItem(address, op); IncreaseAddress(ref address); } else // Handle Assembler pseudo instructions { ria = HandlePseudoInstruction(ref address, op); } // 2nd pass [Resolve each Pseudo command] foreach (RomItem ri in ria) { line.AddRomItem(ri); try { binary.Add(ri.Address, ri.Opcode); } catch { line.SetError("Address is overlapping with other code"); } } } } // 3rd pass [Resolve labels] ResolveLabels(binary); return binary; }
public void AddRomItem(RomItem ri) { ArrayList arl = new ArrayList(Opcodes); arl.Add(ri); Opcodes = (RomItem[])arl.ToArray(typeof(RomItem)); }
private static RomItem[] HandlePseudoInstruction(ref int address, Opcode op) { ArrayList arl = new ArrayList(); RomItem ri; if (op.Command == Command.org) // ORiGin { address = op.Imm16; if (!String.IsNullOrEmpty(op.Label)) op.SourceLine.SetError("ORG command is not allowed to have a label"); } else if (op.Command == Command.li) // Load Immediate { ri = new RomItem(address, OpcodeDictionary.Get("movl")); ri.Opcode.Register1 = op.Register1; if (op.Type == OpcodeType.TwoArg_RegImm16label) { ri.Opcode.Imm16label = op.Imm16label; ri.Opcode.Type = OpcodeType.TwoArg_RegImm16label_l; } else { ri.Opcode.Imm8 = op.Imm16 & 0xFF; ri.Opcode.Type = OpcodeType.TwoArg_RegImm8; } ri.Opcode.Label = op.Label; ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); ri = new RomItem(address, OpcodeDictionary.Get("movh")); ri.Opcode.Register1 = op.Register1; if (op.Type == OpcodeType.TwoArg_RegImm16label) { ri.Opcode.Imm16label = op.Imm16label; ri.Opcode.Type = OpcodeType.TwoArg_RegImm16label_h; } else { ri.Opcode.Imm8 = op.Imm16 >> 8; ri.Opcode.Type = OpcodeType.TwoArg_RegImm8; } ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); } else if (op.Command == Command.jrl) // JumpRegisterLabel { ri = new RomItem(address, OpcodeDictionary.Get("movl")); ri.Opcode.Register1 = op.Register1; //ri.Opcode.Imm8 = op.Imm16 & 0xFF; ri.Opcode.Imm16label = op.Imm16label; ri.Opcode.Type = OpcodeType.TwoArg_RegImm16label_l; ri.Opcode.Label = op.Label; ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); ri = new RomItem(address, OpcodeDictionary.Get("movh")); ri.Opcode.Register1 = op.Register1; //ri.Opcode.Imm8 = op.Imm16 >> 8; ri.Opcode.Imm16label = op.Imm16label; ri.Opcode.Type = OpcodeType.TwoArg_RegImm16label_h; ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); ri = new RomItem(address, OpcodeDictionary.Get("jr")); ri.Opcode.Register1 = op.Register1; ri.Opcode.Type = OpcodeType.OneArg_Reg; ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); } else if (op.Command == Command.dw) // DataWord { ri = new RomItem(address, OpcodeDictionary.Get("dw")); ri.Opcode.Data16 = op.Data16; ri.Opcode.Type = OpcodeType.OneArg_Data16; ri.Opcode.Label = op.Label; ri.Opcode.SetSourceLine(op.SourceLine); arl.Add(ri); IncreaseAddress(ref address); } return (RomItem[])arl.ToArray(typeof(RomItem)); }