Ejemplo n.º 1
0
        private Tms7000Instruction Decode(Opcode opcode, string format)
        {
            int iOp   = 0;
            var instr = new Tms7000Instruction
            {
                Opcode = opcode,
            };

            for (int i = 0; i < format.Length; ++i)
            {
                MachineOperand op;
                byte           b;
                ushort         w;
                switch (format[i])
                {
                case ',': continue;

                case 'A':
                    op = new RegisterOperand(arch.a);
                    break;

                case 'B':
                    op = new RegisterOperand(arch.b);
                    break;

                case 'R':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = new RegisterOperand(arch.GpRegs[b]);
                    break;

                case 'P':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = new RegisterOperand(arch.Ports[b]);
                    break;

                case 'S':
                    ;                   op = new RegisterOperand(arch.st);
                    break;

                case 'i':
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = ImmediateOperand.Byte(b);
                    break;

                case 'I':
                    if (!rdr.TryReadBeUInt16(out w))
                    {
                        return(Invalid());
                    }
                    op = ImmediateOperand.Word16(w);
                    break;

                case 'j':   // short PC-relative jump
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = AddressOperand.Create(rdr.Address + (sbyte)b);
                    break;

                case 'D':  // direct, absolute address
                    if (!rdr.TryReadBeUInt16(out w))
                    {
                        return(Invalid());
                    }
                    if (i < format.Length - 1 && format[i + 1] == 'B')
                    {
                        ++i;
                        op = MemoryOperand.Indexed(Address.Ptr16(w), arch.b);
                    }
                    else
                    {
                        op = MemoryOperand.Direct(Address.Ptr16(w));
                    }
                    break;

                case '*': // indirect
                    if (!rdr.TryReadByte(out b))
                    {
                        return(Invalid());
                    }
                    op = MemoryOperand.Indirect(arch.GpRegs[b]);
                    break;

                default: throw new NotImplementedException($"Addressing mode {format[i]}");
                }
                switch (iOp++)
                {
                case 0: instr.op1 = op; break;

                case 1: instr.op2 = op; break;

                case 2: instr.op3 = op; break;
                }
            }
            return(instr);
        }