Пример #1
0
 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");
 }
Пример #2
0
 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));
 }
Пример #3
0
 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));
 }
Пример #4
0
 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");
 }
Пример #5
0
 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
 }
Пример #6
0
 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
 }
Пример #7
0
 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);
 }
Пример #8
0
 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);
 }
Пример #9
0
        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;
        }
Пример #10
0
        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);
        }