Exemplo n.º 1
0
        private void PushOperand(DebuggableEmitter il, ulong index, UrclInstruction inst)
        {
            bool  isImm;
            ulong value;

            switch (index)
            {
            case 0:
                isImm = inst.AType switch
                {
                    OperandType.Register => false,
                    OperandType.Immediate => true,
                    _ => throw new InvalidOperationException(),
                };
                value = inst.A;
                break;

            case 1:
                isImm = inst.BType switch
                {
                    OperandType.Register => false,
                    OperandType.Immediate => true,
                    _ => throw new InvalidOperationException(),
                };
                value = inst.B;
                break;

            case 2:
                isImm = inst.CType switch
                {
                    OperandType.Register => false,
                    OperandType.Immediate => true,
                    _ => throw new InvalidOperationException(),
                };
                value = inst.C;
                break;

            default:
                throw new InvalidOperationException();
            }

            if (isImm)
            {
                il.Emit(OpCodes.Ldc_I8, value);
            }
            else
            {
                if (value == 0)
                {
                    il.Emit(OpCodes.Ldc_I8, 0UL);
                }
                else
                {
                    il.Emit(OpCodes.Ldloc, Registers[value - 1]);
                }
            }
        }
Exemplo n.º 2
0
 private static Operand GetA(UrclInstruction instruction)
 {
     return(instruction.AType switch
     {
         OperandType.None => Operand.Imm("0"),
         OperandType.Register => instruction.A == 0 ? Operand.Imm("0") : Operand.Abs(((instruction.A - 1) * 2) + RegistersOffset),
         OperandType.Immediate => Operand.Imm(instruction.A.ToString()),
         OperandType.Label => Operand.Imm(LabelToString(instruction.ALabel)),
         _ => throw new ArgumentException($"Unsupported operand type {instruction.AType}.", "A"),
     });
Exemplo n.º 3
0
        private void PopOperand(DebuggableEmitter il, ulong index, UrclInstruction inst)
        {
            ulong reg;

            switch (index)
            {
            case 0:
                if (inst.AType == OperandType.Register)
                {
                    reg = inst.A;
                }
                else
                {
                    throw new InvalidOperationException();
                }
                break;

            case 1:
                if (inst.AType == OperandType.Register)
                {
                    reg = inst.B;
                }
                else
                {
                    throw new InvalidOperationException();
                }
                break;

            case 2:
                if (inst.AType == OperandType.Register)
                {
                    reg = inst.C;
                }
                else
                {
                    throw new InvalidOperationException();
                }
                break;

            default:
                throw new InvalidOperationException();
            }

            if (reg == 0)
            {
                il.Emit(OpCodes.Pop);
            }
            else
            {
                il.Emit(OpCodes.Stloc, Registers[reg - 1]);
            }
        }
Exemplo n.º 4
0
            private ResolvedInstruction Decode(UrclInstruction inst)
            {
                var argCount = 0;

                if (inst.AType != OperandType.None)
                {
                    argCount++;
                }
                if (inst.BType != OperandType.None)
                {
                    argCount++;
                }
                if (inst.CType != OperandType.None)
                {
                    argCount++;
                }

                var args = new object[argCount];

                if (argCount >= 1)
                {
                    args[0] = inst.AType switch
                    {
                        OperandType.Register => new Register(inst.A),
                        OperandType.Immediate => inst.A,
                        _ => ResolveValue(inst.ALabel),
                    };
                }

                if (argCount >= 2)
                {
                    args[1] = inst.BType switch
                    {
                        OperandType.Register => new Register(inst.B),
                        OperandType.Immediate => inst.B,
                        _ => ResolveValue(inst.BLabel),
                    };
                }

                if (argCount >= 3)
                {
                    args[2] = inst.CType switch
                    {
                        OperandType.Register => new Register(inst.C),
                        OperandType.Immediate => inst.C,
                        _ => ResolveValue(inst.CLabel),
                    };
                }

                return(new ResolvedInstruction(inst.Operation, args));
            }
Exemplo n.º 5
0
        public static IEnumerable <UrclInstruction> Parse(IEnumerable <string> lines)
        {
            var labels = new Dictionary <string, Label>();

            ulong ram    = 1024;
            ulong maxReg = 0;

            for (int parseIteration = 0; parseIteration < 3; parseIteration++)
            {
                int index = 0;
                foreach (var line in lines)
                {
                    var trimmed = line.Trim();

                    if (trimmed.Length != 0 && !line.StartsWith("//"))
                    {
                        UrclInstruction result = null;

                        try
                        {
                            result = ParseInstruction(trimmed, parseIteration == 0, parseIteration > 0, labels);

                            if (parseIteration == 1)
                            {
                                if (result.Operation == Operation.MINRAM && result.A > ram)
                                {
                                    ram = result.A;
                                }
                                else
                                {
                                    if (result.AType == OperandType.Register && result.A > maxReg)
                                    {
                                        maxReg = result.A;
                                    }
                                    if (result.BType == OperandType.Register && result.B > maxReg)
                                    {
                                        maxReg = result.B;
                                    }
                                    if (result.CType == OperandType.Register && result.C > maxReg)
                                    {
                                        maxReg = result.C;
                                    }
                                }

                                result = null;
                            }
                            else if (result != null && result.Operation == Operation.MINRAM)
                            {
                                result = null;
                            }
                        }
                        catch (ParserError ex)
                        {
                            throw new ParserError($"Error on line {index + 1}: \"{line}\" {ex.Message}");
                        }

                        if (result != null)
                        {
                            yield return(result);
                        }
                    }

                    index++;
                }

                if (parseIteration == 1)
                {
                    yield return(new UrclInstruction(Operation.COMPILER_MAXREG, OperandType.Immediate, maxReg));

                    yield return(new UrclInstruction(Operation.MINRAM, OperandType.Immediate, ram));
                }
            }
        }
Exemplo n.º 6
0
        private void Emit(Action <X86Inst> emit, UrclInstruction instruction)
        {
            switch (instruction.Operation)
            {
            case Operation.NOP:
                emit(new X86Inst("nop"));
                break;

            case Operation.BRK:
            case Operation.HLT:
                emit(new X86Inst("hlt"));
                break;

            case Operation.ADD:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("add", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.INC:
                Set(emit, AX, GetB(instruction));
                emit(new X86Inst("inc", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.SUB:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("sub", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.DEC:
                Set(emit, AX, GetB(instruction));
                emit(new X86Inst("dec", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.MLT:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("mul", BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.DIV:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("xor", DX, DX));
                emit(new X86Inst("div", BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.MOD:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("xor", DX, DX));
                emit(new X86Inst("div", BX));
                Set(emit, GetA(instruction), DX);
                break;

            case Operation.AND:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("and", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.OR:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("or", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.XOR:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("xor", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.NAND:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("and", AX, BX));
                emit(new X86Inst("not", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.NOR:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("or", AX, BX));
                emit(new X86Inst("not", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.XNOR:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("xor", AX, BX));
                emit(new X86Inst("not", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.NOT:
                Set(emit, AX, GetB(instruction));
                emit(new X86Inst("not", AX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.LSH:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, Operand.Imm("1"));
                emit(new X86Inst("shl", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.BSL:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("shl", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.RSH:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, Operand.Imm("1"));
                emit(new X86Inst("shr", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.BSR:
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetC(instruction));
                emit(new X86Inst("shr", AX, BX));
                Set(emit, GetA(instruction), AX);
                break;

            case Operation.MOV:
                if (instruction.BType == OperandType.Register && instruction.B == 0)
                {
                    Set(emit, GetA(instruction), Operand.Imm("0"));
                }
                else
                {
                    Set(emit, AX, GetB(instruction));
                    Set(emit, GetA(instruction), AX);
                }
                break;

            case Operation.IMM:
                Set(emit, GetA(instruction), GetB(instruction));
                break;

            case Operation.LOAD:
            {
                Set(emit, BX, GetB(instruction));
                emit(new X86Inst("shl", BX, Operand.Imm("1")));
                Set(emit, AX, Operand.Rel(BX, 0));
                Set(emit, GetA(instruction), AX);
            }
            break;

            case Operation.STORE:
            {
                Set(emit, AX, GetB(instruction));
                Set(emit, BX, GetA(instruction));
                emit(new X86Inst("shl", BX, Operand.Imm("1")));
                Set(emit, Operand.Rel(BX, 0), AX);
            }
            break;

            case Operation.IN:
            {
                var port = GetB(instruction).ToString();

                switch (port)
                {
                case "3":
                case "78":
                case "79":
                    emit(new X86Inst("xor", AX, AX));
                    emit(new X86Inst("int", Operand.Imm("0x16")));
                    emit(new X86Inst("and", AX, Operand.Imm("0xFF")));
                    Set(emit, GetA(instruction), AX);
                    break;

                default:
                    throw new ArgumentException($"Unsupported IO port \"{port}\"", "B");
                }
            }
            break;

            case Operation.OUT:
            {
                var port = GetA(instruction).ToString();

                switch (port)
                {
                case "3":
                case "78":
                case "79":
                    Set(emit, AX, Operand.Imm("0x0A00"));
                    Set(emit, BX, GetB(instruction));
                    Set(emit, CX, Operand.Imm("1"));
                    emit(new X86Inst("and", BX, Operand.Imm("0xFF")));
                    emit(new X86Inst("or", AX, BX));
                    emit(new X86Inst("xor", BX, BX));
                    emit(new X86Inst("int", Operand.Imm("0x10")));
                    break;

                default:
                    throw new ArgumentException($"Unsupported IO port \"{port}\"", "A");
                }
            }
            break;

            case Operation.PSH:
            {
                emit(new X86Inst("push", GetA(instruction)));
            }
            break;

            case Operation.POP:
            {
                if (instruction.AType == OperandType.Register && instruction.A != 0)
                {
                    emit(new X86Inst("pop", GetA(instruction)));
                }
                else
                {
                    emit(new X86Inst("pop", AX));
                }
            }
            break;

            case Operation.BRA:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jmp", target));
            }
            break;

            case Operation.BRZ:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jz", target));
            }
            break;

            case Operation.BNZ:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jnz", target));
            }
            break;

            case Operation.BRC:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jc", target));
            }
            break;

            case Operation.BNC:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jnc", target));
            }
            break;

            case Operation.BRP:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("jns", target));
            }
            break;

            case Operation.BRN:
            {
                var target = GetA(instruction);

                if (instruction.AType == OperandType.Register)
                {
                    Set(emit, AX, target);
                    target = AX;
                }

                emit(new X86Inst("js", target));
            }
            break;

            case Operation.CAL:
            {
                emit(new X86Inst("call", GetA(instruction)));
            }
            break;

            case Operation.RET:
                emit(new X86Inst("ret"));
                break;

            case Operation.COMPILER_MARKLABEL:
                emit(new X86Inst($"{LabelToString(instruction.ALabel)}:"));
                break;

            case Operation.MINRAM:
            case Operation.BENCHMARK:
            case Operation.COMPILER_CREATELABEL:
            case Operation.COMPILER_PRAGMA:
            case Operation.COMPILER_MAXREG:
                break;

            case Operation.COMPILER_COMMENT:
                if (CommentPrefix != null)
                {
                    foreach (var line in instruction.Arguments)
                    {
                        emit(new X86Inst($"{CommentPrefix}{line}"));
                    }
                }
                break;

            default:
                break;
            }
        }
Exemplo n.º 7
0
        public IEnumerable <UrclInstruction> Parse(IEnumerable <string> lines, Func <string, IEnumerable <string> > import, string sourceName = null)
        {
            var lineLabels = new Label[lines.Count()];
            var used       = new bool[lineLabels.Length];

            for (int parseIteration = 0; parseIteration < 3; parseIteration++)
            {
                string macroName   = null;
                var    macroBuffer = new List <UrclInstruction>();

                int index = 0;
                foreach (var line in lines)
                {
                    var trimmed = line.Trim();

                    if (!ParserIgnore(trimmed))
                    {
                        if (parseIteration == 0)
                        {
                            lineLabels[index] = new Label();
                        }

                        UrclInstruction result = null;
                        IEnumerable <UrclInstruction> block = null;

                        try
                        {
                            result = ParseInstruction(trimmed, parseIteration == 0, parseIteration > 0, Labels, ValueMacros, CodeMacros, (rel) =>
                            {
                                var target = rel + index;

                                if (target < 0 || target >= lineLabels.Length || lineLabels[target] is null)
                                {
                                    throw new ParserError("Relative address is out of bounds.");
                                }

                                used[target] = true;
                                return(lineLabels[target]);
                            });

                            if (parseIteration == 1 && result != null)
                            {
                                if (result.Operation == Operation.COMPILER_CODEMACRO_BEGIN)
                                {
                                    if (macroName != null)
                                    {
                                        throw new ParserError("Macro was not finished before starting another macro.");
                                    }
                                    macroName = result.Arguments[0];
                                    macroBuffer.Clear();
                                    result = null;
                                }
                                else if (result.Operation == Operation.COMPILER_CODEMACRO_END)
                                {
                                    if (macroName == null)
                                    {
                                        throw new ParserError("Missing beginning of macro.");
                                    }
                                    CodeMacros[macroName] = macroBuffer.ToArray();
                                    macroName             = null;
                                    macroBuffer.Clear();
                                    result = null;
                                }
                                else if (result.Operation == Operation.COMPILER_CODEMACRO_USE)
                                {
                                    if (macroName != null)
                                    {
                                        throw new ParserError("Nested macros are not supported.");
                                    }
                                    if (CodeMacros.TryGetValue(result.Arguments[0], out IEnumerable <UrclInstruction> insts))
                                    {
                                        block  = insts;
                                        result = null;
                                    }
                                    else
                                    {
                                        throw new ParserError($"Undefined macro \"{result.Arguments[0]}\"");
                                    }
                                }
                                else if (result.Operation == Operation.IMPORT)
                                {
                                    var name = result.Arguments[0];
                                    block  = Parse(import(string.Join(' ', result.Arguments)), import, sourceName).ToArray();
                                    result = null;
                                }
                                else if (macroName != null)
                                {
                                    macroBuffer.Add(result);
                                    result = null;
                                }

                                result = null;
                            }
                            else if (result != null)
                            {
                                if (result.Operation == Operation.MINRAM || result.Operation == Operation.IMPORT)
                                {
                                    result = null;
                                }
                            }
                        }
                        catch (TargetInvocationException ex)
                        {
                            throw new ParserError($"Error on line {index + 1}: \"{line}\" {ex.InnerException.Message}");
                        }
                        catch (ParserError ex)
                        {
                            throw new ParserError($"Error on line {index + 1}: \"{line}\" {ex.Message}");
                        }

                        if ((result != null || block != null) && used[index])
                        {
                            yield return(new UrclInstruction(Operation.COMPILER_MARKLABEL, lineLabels[Array.IndexOf(lineLabels, lineLabels[index])]));
                        }

                        if (result != null)
                        {
                            yield return(result);
                        }
                        if (block != null)
                        {
                            foreach (var inst in block)
                            {
                                yield return(inst);
                            }
                        }
                    }
                    else
                    {
                        if (parseIteration == 0)
                        {
                            if (index > 0)
                            {
                                lineLabels[index] = lineLabels[index - 1];
                            }
                            else
                            {
                                lineLabels[index] = null;
                            }
                        }
                    }

                    index++;
                }
            }
        }
Exemplo n.º 8
0
        public void Emit(Instruction inst)
        {
            var start = Urcl.Count;

            var result = new UrclInstruction(Operation.NOP)
            {
                A = inst.Destination.Value,
                B = inst.Source.Value,
                C = inst.Target.Value,

                AType = inst.Destination.Immediate ? OperandType.Immediate : OperandType.Register,
                BType = inst.Source.Immediate ? OperandType.Immediate : OperandType.Register,
                CType = inst.Target.Immediate ? OperandType.Immediate : OperandType.Register
            };

            if (result.AType == OperandType.Register)
            {
                result.A++;
            }
            if (result.BType == OperandType.Register)
            {
                result.B++;
            }
            if (result.CType == OperandType.Register)
            {
                result.C++;
            }

            switch (inst.Operation)
            {
            case global::SpeedAsm.Operation.Set:
                result.Operation = inst.Source.Immediate ? Operation.IMM : Operation.MOV;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.Add:
                result.Operation = Operation.ADD;
                break;

            case global::SpeedAsm.Operation.Inc:
                result.Operation = Operation.INC;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.Sub:
                result.Operation = Operation.SUB;
                break;

            case global::SpeedAsm.Operation.Dec:
                result.Operation = Operation.DEC;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.Mul:
                result.Operation = Operation.MLT;
                break;

            case global::SpeedAsm.Operation.Div:
                result.Operation = Operation.DIV;
                break;

            case global::SpeedAsm.Operation.Mod:
                result.Operation = Operation.MOD;
                break;

            case global::SpeedAsm.Operation.And:
                result.Operation = Operation.AND;
                break;

            case global::SpeedAsm.Operation.Or:
                result.Operation = Operation.OR;
                break;

            case global::SpeedAsm.Operation.Xor:
                result.Operation = Operation.XOR;
                break;

            case global::SpeedAsm.Operation.Not:
                result.Operation = Operation.NOT;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BAnd:
            {
                var skipB = new Label();
                var skipC = new Label();
                Urcl.AddRange(new[]
                    {
                        new UrclInstruction(Operation.OR, OperandType.Register, result.B, OperandType.Register, result.B, OperandType.Register, result.B),
                        new UrclInstruction(Operation.BRZ, skipB),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.B, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipB),
                        new UrclInstruction(Operation.OR, OperandType.Register, result.C, OperandType.Register, result.C, OperandType.Register, result.C),
                        new UrclInstruction(Operation.BRZ, skipC),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.C, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipC),
                        new UrclInstruction(Operation.AND, OperandType.Register, result.A, OperandType.Register, result.B, OperandType.Register, result.C)
                    });
            }
            break;

            case global::SpeedAsm.Operation.BOr:
            {
                var skipB = new Label();
                var skipC = new Label();
                Urcl.AddRange(new[]
                    {
                        new UrclInstruction(Operation.OR, OperandType.Register, result.B, OperandType.Register, result.B, OperandType.Register, result.B),
                        new UrclInstruction(Operation.BRZ, skipB),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.B, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipB),
                        new UrclInstruction(Operation.OR, OperandType.Register, result.C, OperandType.Register, result.C, OperandType.Register, result.C),
                        new UrclInstruction(Operation.BRZ, skipC),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.C, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipC),
                        new UrclInstruction(Operation.OR, OperandType.Register, result.A, OperandType.Register, result.B, OperandType.Register, result.C)
                    });
            }
            break;

            case global::SpeedAsm.Operation.BXor:
            {
                var skipB = new Label();
                var skipC = new Label();
                Urcl.AddRange(new[]
                    {
                        new UrclInstruction(Operation.OR, OperandType.Register, result.B, OperandType.Register, result.B, OperandType.Register, result.B),
                        new UrclInstruction(Operation.BRZ, skipB),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.B, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipB),
                        new UrclInstruction(Operation.OR, OperandType.Register, result.C, OperandType.Register, result.C, OperandType.Register, result.C),
                        new UrclInstruction(Operation.BRZ, skipC),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.C, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipC),
                        new UrclInstruction(Operation.XOR, OperandType.Register, result.A, OperandType.Register, result.B, OperandType.Register, result.C)
                    });
            }
            break;

            case global::SpeedAsm.Operation.BNot:
            {
                var skipB = new Label();
                var end   = new Label();
                Urcl.AddRange(new[]
                    {
                        new UrclInstruction(Operation.OR, OperandType.Register, result.B, OperandType.Register, result.B, OperandType.Register, result.B),
                        new UrclInstruction(Operation.BNZ, skipB),
                        new UrclInstruction(Operation.IMM, OperandType.Register, result.A, OperandType.Immediate, 1),
                        new UrclInstruction(Operation.BRA, end),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, skipB),
                        new UrclInstruction(Operation.MOV, OperandType.Register, result.A, OperandType.Register, 0),
                        new UrclInstruction(Operation.COMPILER_MARKLABEL, end),
                        new UrclInstruction(Operation.OR, OperandType.Register, result.A, OperandType.Register, result.A, OperandType.Register, result.A)
                    });
            }
            break;

            case global::SpeedAsm.Operation.Label:
                result.Operation = Operation.COMPILER_MARKLABEL;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.Branch:
                result.Operation = Operation.BRA;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfNotZero:
                result.Operation = Operation.BNZ;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfZero:
                result.Operation = Operation.BRZ;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfCarry:
                result.Operation = Operation.BRC;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfSign:
                result.Operation = Operation.BRN;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfNotCarry:
                result.Operation = Operation.BNC;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            case global::SpeedAsm.Operation.BranchIfNotSign:
                result.Operation = Operation.BRN;
                result.AType     = OperandType.Label;
                result.ALabel    = GetLabel(result.A);
                result.BType     = OperandType.None;
                result.CType     = OperandType.None;
                break;

            default:
                throw new CompileError($"Operation is not supported for URCL: {inst.Operation}");
            }

            if (result.Operation != Operation.NOP)
            {
                Urcl.Add(result);
            }

            if (Urcl.Count > start)
            {
                foreach (var urcl in Urcl.GetRange(start, Urcl.Count - start))
                {
                    Instructions.Enqueue(urcl);
                }
            }
        }
Exemplo n.º 9
0
 private void Emit(UrclInstruction instruction)
 {
     Instructions.Add(instruction);
 }