public static void RequireOpcodeFlag(OpcodeFlag flag, OpcodeFlag[] acceptable) { for (int i = 0; i < acceptable.Length; i++) if (flag.HasFlag(acceptable[i])) return; throw new Exception($"Opcode flag of '{flag}' is unsupported for this opcode"); }
private List <ushort> AssembleJSR(List <string> param, OpcodeFlag opcodeFlag, ParserState state) { if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { Guard.RequireParamCountMinMax(param, 1, 2); // allow two params for immediate far jump. return(state.Parser.AssembleJMI(0x01B9, param[0], param.Count == 2 ? param[1] : null, state)); } Guard.RequireParamCountExact(param, 1); return(state.Parser.AssembleJMI(0x00B9, param[0], null, state)); }
private List <ushort> AssembleJMP(List <string> param, OpcodeFlag opcodeFlag, ParserState state) { Guard.RequireOpcodeFlag(opcodeFlag, new[] { OpcodeFlag.BitWidth16 }); if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { Guard.RequireParamCountMinMax(param, 1, 2); return(state.Parser.AssembleJMI(0x01B8, param[0], param.Count == 2 ? param[1] : null, state)); } Guard.RequireParamCountExact(param, 1); return(state.Parser.AssembleJMI(0x00B8, param[0], null, state)); }
public static void RequireOpcodeFlag(OpcodeFlag flag, OpcodeFlag[] acceptable) { for (int i = 0; i < acceptable.Length; i++) { if (flag.HasFlag(acceptable[i])) { return; } } throw new Exception($"Opcode flag of '{flag}' is unsupported for this opcode"); }
private List <ushort> AssembleRTS(List <string> param, OpcodeFlag opcodeFlag, ParserState state) { if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { return(new List <ushort> { 0x01B4 }); // RTS.F } return(new List <ushort> { 0x00B4 }); // RTS }
private List<ushort> AssembleRTS(List<string> param, OpcodeFlag opcodeFlag, ParserState state) { if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { return new List<ushort> { 0x01B4 }; // RTS.F } return new List<ushort> { 0x00B4 }; // RTS }
private List<ushort> AssembleJSR(List<string> param, OpcodeFlag opcodeFlag, ParserState state) { if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { Guard.RequireParamCountMinMax(param, 1, 2); // allow two params for immediate far jump. return state.Parser.AssembleJMI(0x01B9, param[0], param.Count == 2 ? param[1] : null, state); } Guard.RequireParamCountExact(param, 1); return state.Parser.AssembleJMI(0x00B9, param[0], null, state); }
private List<ushort> AssembleJMP(List<string> param, OpcodeFlag opcodeFlag, ParserState state) { Guard.RequireOpcodeFlag(opcodeFlag, new[] { OpcodeFlag.BitWidth16 }); if (opcodeFlag.HasFlag(OpcodeFlag.FarJump)) { Guard.RequireParamCountMinMax(param, 1, 2); return state.Parser.AssembleJMI(0x01B8, param[0], param.Count == 2 ? param[1] : null, state); } Guard.RequireParamCountExact(param, 1); return state.Parser.AssembleJMI(0x00B8, param[0], null, state); }
private List<ushort> AssembleALU(ushort opcode, string param1, string param2, OpcodeFlag opcodeFlag, ParserState state) { Param p1 = ParseParam(param1); Param p2 = ParseParam(param2); if (p1.AddressingMode != AddressingMode.Register) { throw new Exception("ALU instruction first operand must be a general purpose register"); } ushort addressingmode = 0x0000; switch (p2.AddressingMode) { case AddressingMode.None: return null; case AddressingMode.Immediate: // .000 000e Immediate LOD R0, $1234 +1m // special case: alu.8 immediate with value greater than $FF should raise a warning... if (opcodeFlag == OpcodeFlag.BitWidth8 && p2.ImmediateWordShort >= 256) { throw new Exception("8-bit load operation with an immediate value of greater than 8 bits"); } addressingmode = 0x0000; if (p2.UsesExtraDataSegment) throw new Exception("Immediate addressing mode cannot use extra data segment"); break; case AddressingMode.Absolute: // s000 001e Absolute LOD R0, [$1234] +2m addressingmode = 0x0200; if (p2.UsesExtraDataSegment) addressingmode |= 0x8000; break; case AddressingMode.ControlRegister: // .000 1ppp Control register LOD R0, PS // can't use eightbit mode with proc regs... if (opcodeFlag.HasFlag(OpcodeFlag.BitWidth8)) throw new Exception("ALU instructions with status register operands do not support 8-bit mode"); if (p2.UsesExtraDataSegment) throw new Exception("Control register addressing mode cannot use extra data segment"); addressingmode = (ushort)(0x0800 | ((p2.RegisterIndex & 0x0007) << 8)); p2.RegisterIndex = 0; // must wipe out control register index, as it is used later in this subroutine. break; case AddressingMode.Register: // .001 rrre Register LOD R0, r1 addressingmode = 0x1000; if (p2.UsesExtraDataSegment) throw new Exception("Register addressing mode cannot use extra data segment"); break; case AddressingMode.Indirect: // s010 rrre Indirect LOD R0, [r1] +1m addressingmode = 0x2000; if (p2.UsesExtraDataSegment) addressingmode |= 0x8000; break; case AddressingMode.IndirectOffset: // s011 rrre Indirect Offset LOD R0, [r1,$1234] +2m addressingmode = 0x3000; if (p2.UsesExtraDataSegment) addressingmode |= 0x8000; break; case AddressingMode.IndirectIndexed: // s1ii rrre Indirect Indexed LOD R0, [r1,i2] +1m int index_register = (p2.RegisterIndex & 0x0300) << 4; addressingmode = (ushort)(0x4000 | index_register); if (p2.UsesExtraDataSegment) addressingmode |= 0x8000; break; default: throw new Exception("Unknown addressing mode"); } ushort bitwidth = 0x0000; if (opcodeFlag == OpcodeFlag.BitWidth8) bitwidth = 0x0100; // FEDC BA98 7654 3210 // AAAA rrrE OOOO ORRR m_Code.Clear(); m_Code.Add((ushort)(opcode | addressingmode | bitwidth | (p1.RegisterIndex & 0x0007) | ((p2.RegisterIndex & 0x0007) << 9))); if (p2.HasLabel) { state.Labels.Add((ushort)(state.Code.Count + m_Code.Count * c_InstructionSize), p2.Label); m_Code.Add(0xDEAD); } else if (p2.HasImmediateWord) { m_Code.Add(p2.ImmediateWordShort); } return m_Code; }
private List <ushort> AssembleALU(ushort opcode, string param1, string param2, OpcodeFlag opcodeFlag, ParserState state) { Param p1 = ParseParam(param1); Param p2 = ParseParam(param2); if (p1.AddressingMode != AddressingMode.Register) { throw new Exception("ALU instruction first operand must be a general purpose register"); } ushort addressingmode = 0x0000; switch (p2.AddressingMode) { case AddressingMode.None: return(null); case AddressingMode.Immediate: // .000 000e Immediate LOD R0, $1234 +1m // special case: alu.8 immediate with value greater than $FF should raise a warning... if (opcodeFlag == OpcodeFlag.BitWidth8 && p2.ImmediateWordShort >= 256) { throw new Exception("8-bit load operation with an immediate value of greater than 8 bits"); } addressingmode = 0x0000; if (p2.UsesExtraDataSegment) { throw new Exception("Immediate addressing mode cannot use extra data segment"); } break; case AddressingMode.Absolute: // s000 001e Absolute LOD R0, [$1234] +2m addressingmode = 0x0200; if (p2.UsesExtraDataSegment) { addressingmode |= 0x8000; } break; case AddressingMode.ControlRegister: // .000 1ppp Control register LOD R0, PS // can't use eightbit mode with proc regs... if (opcodeFlag.HasFlag(OpcodeFlag.BitWidth8)) { throw new Exception("ALU instructions with status register operands do not support 8-bit mode"); } if (p2.UsesExtraDataSegment) { throw new Exception("Control register addressing mode cannot use extra data segment"); } addressingmode = (ushort)(0x0800 | ((p2.RegisterIndex & 0x0007) << 8)); p2.RegisterIndex = 0; // must wipe out control register index, as it is used later in this subroutine. break; case AddressingMode.Register: // .001 rrre Register LOD R0, r1 addressingmode = 0x1000; if (p2.UsesExtraDataSegment) { throw new Exception("Register addressing mode cannot use extra data segment"); } break; case AddressingMode.Indirect: // s010 rrre Indirect LOD R0, [r1] +1m addressingmode = 0x2000; if (p2.UsesExtraDataSegment) { addressingmode |= 0x8000; } break; case AddressingMode.IndirectOffset: // s011 rrre Indirect Offset LOD R0, [r1,$1234] +2m addressingmode = 0x3000; if (p2.UsesExtraDataSegment) { addressingmode |= 0x8000; } break; case AddressingMode.IndirectIndexed: // s1ii rrre Indirect Indexed LOD R0, [r1,i2] +1m int index_register = (p2.RegisterIndex & 0x0300) << 4; addressingmode = (ushort)(0x4000 | index_register); if (p2.UsesExtraDataSegment) { addressingmode |= 0x8000; } break; default: throw new Exception("Unknown addressing mode"); } ushort bitwidth = 0x0000; if (opcodeFlag == OpcodeFlag.BitWidth8) { bitwidth = 0x0100; } // FEDC BA98 7654 3210 // AAAA rrrE OOOO ORRR m_Code.Clear(); m_Code.Add((ushort)(opcode | addressingmode | bitwidth | (p1.RegisterIndex & 0x0007) | ((p2.RegisterIndex & 0x0007) << 9))); if (p2.HasLabel) { state.Labels.Add((ushort)(state.Code.Count + m_Code.Count * c_InstructionSize), p2.Label); m_Code.Add(0xDEAD); } else if (p2.HasImmediateWord) { m_Code.Add(p2.ImmediateWordShort); } return(m_Code); }