Exemplo n.º 1
0
        private static OpcodeDescriptor Add(uint number, string name, uint argumentSize, params OperandKind[] operandKinds)
        {
            var descriptor = new OpcodeDescriptor(number, name, argumentSize, operandKinds.ToImmutableList());

            s_table.Add(number, descriptor);

            return(descriptor);
        }
Exemplo n.º 2
0
 public static bool TryGetOpcode(uint number, out OpcodeDescriptor opcode)
 {
     return(s_table.TryGetValue(number, out opcode));
 }
Exemplo n.º 3
0
        public void BindInstruction(
            OpcodeDescriptor opcode, ImmutableList <Operand> loadOperands, ImmutableList <Operand> storeOperands,
            int address, int length)
        {
            // We create a label at every address. Unused labels will be pruned by the AstBodyBuilder later.
            var label = GetOrCreateLabel(address);

            this.bodyBuilder.MarkLabel(label);

            var nextAddress = address + length;

            switch (opcode.Number)
            {
            case Opcodes.op_add:
                BindAdd(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_aload:
                BindRead(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    storeOp: storeOperands[0],
                    size: ValueSize.DWord);
                break;

            case Opcodes.op_aloadb:
                BindRead(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    storeOp: storeOperands[0],
                    size: ValueSize.Byte);
                break;

            case Opcodes.op_aloads:
                BindRead(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    storeOp: storeOperands[0],
                    size: ValueSize.Word);
                break;

            case Opcodes.op_astore:
                BindWrite(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    valueOp: loadOperands[2],
                    size: ValueSize.DWord);
                break;

            case Opcodes.op_astoreb:
                BindWrite(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    valueOp: loadOperands[2],
                    size: ValueSize.Byte);
                break;

            case Opcodes.op_astores:
                BindWrite(
                    baseAddressOp: loadOperands[0],
                    offsetOp: loadOperands[1],
                    valueOp: loadOperands[2],
                    size: ValueSize.Word);
                break;

            case Opcodes.op_call:
                BindCall(
                    addressOp: loadOperands[0],
                    argumentCountOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_callf:
                BindCall0(
                    addressOp: loadOperands[0],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_callfi:
                BindCall1(
                    addressOp: loadOperands[0],
                    arg1Op: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_callfii:
                BindCall2(
                    addressOp: loadOperands[0],
                    arg1Op: loadOperands[1],
                    arg2Op: loadOperands[2],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_callfiii:
                BindCall3(
                    addressOp: loadOperands[0],
                    arg1Op: loadOperands[1],
                    arg2Op: loadOperands[2],
                    arg3Op: loadOperands[3],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_copy:
                BindCopy(
                    targetOp: loadOperands[0],
                    storeOp: storeOperands[0],
                    size: ValueSize.DWord);
                break;

            case Opcodes.op_div:
                BindDivide(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_getmemsize:
                BindGetMemorySize(
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_glk:
                BindGlk(
                    identifierOp: loadOperands[0],
                    argumentCountOp: loadOperands[1],
                    storeOperands: storeOperands[0]);
                break;

            case Opcodes.op_jeq:
                BindJumpIfEqual(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jge:
                BindJumpIfGreaterThanOrEqual(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jgt:
                BindJumpIfGreaterThan(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jle:
                BindJumpIfLessThanOrEqual(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jlt:
                BindJumpIfLessThan(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jne:
                BindJumpIfNotEqual(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    jumpOffsetOp: loadOperands[2],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jnz:
                BindJumpIfNotEqualToZero(
                    leftOp: loadOperands[0],
                    jumpOffsetOp: loadOperands[1],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jump:
                BindJump(
                    jumpOffsetOp: loadOperands[0],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_jz:
                BindJumpIfEqualToZero(
                    leftOp: loadOperands[0],
                    jumpOffsetOp: loadOperands[1],
                    nextAddress: nextAddress);
                break;

            case Opcodes.op_mod:
                BindModulo(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_mul:
                BindMultiply(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            case Opcodes.op_quit:
                BindQuit();
                break;

            case Opcodes.op_restoreundo:
                BindRestoreUndo();
                break;

            case Opcodes.op_return:
                BindReturn(
                    expressionOp: loadOperands[0]);
                break;

            case Opcodes.op_stkcopy:
                BindStackCopy(
                    countOp: loadOperands[0]);
                break;

            case Opcodes.op_streamchar:
                BindStreamChar(
                    characterOp: loadOperands[0]);
                break;

            case Opcodes.op_streamnum:
                BindStreamNumber(
                    numberOp: loadOperands[0]);
                break;

            case Opcodes.op_streamstr:
                BindStreamString(
                    addressOp: loadOperands[0]);
                break;

            case Opcodes.op_sub:
                BindSubtract(
                    leftOp: loadOperands[0],
                    rightOp: loadOperands[1],
                    storeOp: storeOperands[0]);
                break;

            default: throw new NotSupportedException($"Unsupported opcode: {opcode}");
            }
        }
Exemplo n.º 4
0
        private static (ImmutableList <Operand> loadOps, ImmutableList <Operand> storeOps) ReadOperands(MemoryScanner scanner, OpcodeDescriptor opcode)
        {
            var loadOpsBuilder  = ImmutableList.CreateBuilder <Operand>();
            var storeOpsBuilder = ImmutableList.CreateBuilder <Operand>();

            var count = opcode.OperandCount;

            if (count > 0)
            {
                var typesLength = count / 2;
                if (count % 2 != 0)
                {
                    typesLength++;
                }

                var dataScanner = scanner.Memory.CreateScanner(scanner.Address + typesLength);

                for (int i = 0; i < count; i += 2)
                {
                    var opsBuilder = opcode.OperandKinds[i] == OperandKind.Load
                        ? loadOpsBuilder
                        : storeOpsBuilder;

                    var typeByte = scanner.NextByte();

                    var type    = (byte)(typeByte & 0x0f);
                    var operand = ReadOperand(dataScanner, type);
                    opsBuilder.Add(operand);

                    if (i + 1 < count)
                    {
                        opsBuilder = opcode.OperandKinds[i + 1] == OperandKind.Load
                            ? loadOpsBuilder
                            : storeOpsBuilder;

                        type    = (byte)(typeByte >> 4);
                        operand = ReadOperand(dataScanner, type);
                        opsBuilder.Add(operand);
                    }
                }

                scanner.SetAddress(dataScanner.Address);
            }

            return(loadOpsBuilder.ToImmutable(), storeOpsBuilder.ToImmutable());
        }