Beispiel #1
0
        private Tlcs90Instruction DecodeOperands(byte b, Opcode opcode, string format)
        {
            int           op  = 0;
            var           ops = new MachineOperand[2];
            Constant      c;
            PrimitiveType size;

            for (int i = 0; i < format.Length; ++i)
            {
                switch (format[i])
                {
                case ',':
                    continue;

                case 'a':
                    this.dataWidth = PrimitiveType.Byte;
                    ops[op]        = new RegisterOperand(Registers.a);
                    break;

                case '@':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.af_);
                    break;

                case 'A':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.af);
                    break;

                case 'B':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.bc);
                    break;

                case 'c':
                    ops[op] = new ConditionOperand((CondCode)(b & 0xF));
                    break;

                case 'D':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.de);
                    break;

                case 'I':
                    // Immediate value
                    this.dataWidth = GetSize(format[++i]);
                    if (!rdr.TryReadLe(this.dataWidth, out c))
                    {
                        return(null);
                    }
                    ops[op] = new ImmediateOperand(c);
                    break;

                case 'i': // immediate value from opcode bits
                    ops[op] = ImmediateOperand.Byte((byte)(b & 0x7));
                    break;

                case 'g':
                    Debug.Assert(byteReg != null);
                    ops[op] = this.byteReg;
                    break;

                case 'G':
                    Debug.Assert(wordReg != null);
                    ops[op] = this.wordReg;
                    break;

                case 'H':
                    ops[op] = new RegisterOperand(Registers.hl);
                    break;

                case 'J':
                    // Absolute jump.
                    size = GetSize(format[++i]);
                    if (!rdr.TryReadLe(size, out c))
                    {
                        return(null);
                    }
                    ops[op] = AddressOperand.Ptr16(c.ToUInt16());
                    break;

                case 'j':
                    // relative jump
                    size = GetSize(format[++i]);
                    Address dest;
                    if (size.Size == 1)
                    {
                        if (!rdr.TryReadByte(out b))
                        {
                            return(null);
                        }
                        dest = rdr.Address + (sbyte)b;
                    }
                    else
                    {
                        if (!rdr.TryReadLeInt16(out short off))
                        {
                            return(null);
                        }
                        dest = rdr.Address + off;
                    }
                    ops[op] = AddressOperand.Create(dest);
                    break;

                case 'M':
                    this.dataWidth = GetSize(format[++i]);
                    ushort absAddr;
                    if (!rdr.TryReadLeUInt16(out absAddr))
                    {
                        return(null);
                    }
                    ops[op] = MemoryOperand.Absolute(this.dataWidth, absAddr);
                    break;

                case 'm':
                    size = GetSize(format[++i]);
                    byte pageAddr;
                    if (!rdr.TryReadByte(out pageAddr))
                    {
                        return(null);
                    }
                    ops[op] = MemoryOperand.Absolute(size, (ushort)(0xFF00 | pageAddr));
                    break;

                case 'S':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.sp);
                    break;

                case 'X':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.ix);
                    break;

                case 'Y':
                    this.dataWidth = PrimitiveType.Word16;
                    ops[op]        = new RegisterOperand(Registers.iy);
                    break;

                case 'r':
                    // Register encoded in low 3 bits of b.
                    ops[op]   = new RegisterOperand(Registers.byteRegs[b & 7]);
                    dataWidth = PrimitiveType.Byte;
                    break;

                case 'x':
                    this.backPatchOp = op;
                    break;

                default: throw new NotImplementedException(string.Format("Encoding '{0}' not implemented yet.", format[i]));
                }
                ++op;
            }
            return(new Tlcs90Instruction
            {
                Opcode = opcode,
                op1 = op > 0 ? ops[0] : null,
                op2 = op > 1 ? ops[1] : null,
            });
        }
Beispiel #2
0
            public override Tlcs90Instruction Decode(byte b, Tlcs90Disassembler dasm)
            {
                RegisterStorage baseReg = null;
                RegisterStorage idxReg  = null;
                ushort?         absAddr = null;
                Constant        offset  = null;

                switch (format[0])
                {
                case 'M':
                    ushort a;
                    if (!dasm.rdr.TryReadLeUInt16(out a))
                    {
                        return(null);
                    }
                    absAddr = a;
                    break;

                case 'm':
                    byte bb;
                    if (!dasm.rdr.TryReadByte(out bb))
                    {
                        return(null);
                    }
                    absAddr = (ushort)(0xFF00 | bb);
                    break;

                case 'B': baseReg = Registers.bc; break;

                case 'D': baseReg = Registers.de; break;

                case 'H': baseReg = Registers.hl; break;

                case 'X': baseReg = Registers.ix; break;

                case 'Y': baseReg = Registers.iy; break;

                case 'S': baseReg = Registers.sp; break;

                case 'E':
                    switch (format[1])
                    {
                    case 'S': baseReg = Registers.sp;  break;

                    case 'X': baseReg = Registers.ix;  break;

                    case 'Y': baseReg = Registers.ix;  break;

                    case 'H': baseReg = Registers.hl; idxReg = Registers.a;  break;

                    default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format));
                    }
                    if (idxReg == null)
                    {
                        if (!dasm.rdr.TryReadByte(out b))
                        {
                            return(null);
                        }
                        offset = Constant.SByte((sbyte)b);
                    }
                    break;

                default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format));
                }
                if (!dasm.rdr.TryReadByte(out b))
                {
                    return(null);
                }
                var instr = dstEncodings[b].Decode(b, dasm);

                if (instr == null)
                {
                    return(null);
                }

                var operand = new MemoryOperand(dasm.dataWidth)
                {
                    Base   = baseReg,
                    Offset = absAddr.HasValue
                        ? Constant.UInt16(absAddr.Value)
                        : offset,
                };

                if (dasm.backPatchOp == 0)
                {
                    instr.op1 = operand;
                    if (instr.op2 != null)
                    {
                        instr.op1.Width = instr.op2.Width;
                    }
                }
                else if (dasm.backPatchOp == 1)
                {
                    if ((instr.Opcode == Opcode.jp || instr.Opcode == Opcode.call)
                        &&
                        operand.Base == null &&
                        operand.Index == null &&
                        operand.Offset != null)
                    {
                        // JP cc,(XXXX) should be JP cc,XXXX
                        instr.op2       = AddressOperand.Ptr16(operand.Offset.ToUInt16());
                        instr.op2.Width = PrimitiveType.Ptr16;
                    }
                    else
                    {
                        instr.op2       = operand;
                        instr.op2.Width = instr.op1.Width;
                    }
                }
                else
                {
                    return(null);
                }
                return(instr);
            }
Beispiel #3
0
        public AvrInstruction Decode(ushort wInstr, Opcode opcode, string fmt)
        {
            var    ops = new List <MachineOperand>();
            int    offset;
            ushort w2;

            for (int i = 0; i < fmt.Length; ++i)
            {
                MachineOperand op;
                switch (fmt[i++])
                {
                case ',':
                    continue;

                case '+':
                    op = IncDec(true, fmt[i++]);
                    break;

                case '-':
                    op = IncDec(false, fmt[i++]);
                    break;

                case 'A': // I/O location
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 5) & 0x30) | (wInstr & 0xF)));
                    break;

                case 'B': // 8-bit immediate at bits 8..11 and 0..3
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0x0F)));
                    break;

                case 'g': // 4-bit field in sgis
                    op = ImmediateOperand.Byte((byte)((wInstr >> 3) & 0x0F));
                    break;

                case 'h': // 3-bit field in sgis, indicating bit nr.
                    op = ImmediateOperand.Byte((byte)(wInstr & 7));
                    break;

                case 'I': // 4-bit immediate at bit 0
                    op = ImmediateOperand.Byte((byte)(wInstr & 0x0F));
                    break;

                case 'i': // 4-bit immediate at bit 4
                    op = ImmediateOperand.Byte((byte)((wInstr >> 4) & 0x0F));
                    break;

                case 'J': // Relative jump
                    offset = (short)((wInstr & 0xFFF) << 4);
                    offset = offset >> 3;
                    op     = AddressOperand.Create(this.addr + 2 + offset);
                    break;

                case 'D': // Destination register
                    op = Register((wInstr >> 4) & 0x1F);
                    break;

                case 'd': // Destination register (r16-r31)
                    op = Register(0x10 | (wInstr >> 4) & 0x1F);
                    break;

                case 'R': // source register (5 bits)
                    op = Register((wInstr >> 5) & 0x10 | (wInstr) & 0x0F);
                    break;

                case 'r': // source register (4 bits)
                    op = Register((wInstr >> 4) & 0x10 | (wInstr >> 4) & 0x0F);
                    break;

                case 'K':
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 4) & 0xF0) | (wInstr & 0xF)));
                    break;

                case 'P': // register pair source
                    op = Register((wInstr << 1) & ~1);
                    break;

                case 'p': // register pair destination
                    op = Register((wInstr >> 3) & ~1);
                    break;

                case 'Q':   // absolute address used by jump and call.
                    if (!rdr.TryReadLeUInt16(out w2))
                    {
                        return(null);
                    }
                    op = AddressOperand.Ptr32(
                        (uint)(((wInstr >> 4) & 0x1F) << 18) |
                        (uint)((wInstr & 1) << 17) |
                        (uint)(w2 << 1));
                    break;

                case 'q':   // register pair used by adiw
                    op = Register(24 + ((wInstr >> 3) & 6));
                    break;

                case 's':   // immediate used by adiw/sbiw
                    op = ImmediateOperand.Byte((byte)(((wInstr >> 2) & 0x30) | (wInstr & 0xF)));
                    break;

                case 'w': // Trailing 16-bit absolute address
                    if (!rdr.TryReadLeUInt16(out w2))
                    {
                        return(null);
                    }
                    op = AddressOperand.Ptr16(w2);
                    break;

                case 'o':   // Branch offset
                    offset = (short)wInstr;
                    offset = (short)(offset << 6);
                    offset = (short)(offset >> 8);
                    offset = (short)(offset & ~1);
                    op     = AddressOperand.Create(this.addr + offset);
                    break;

                case 'X':
                    op = MemD(arch.x, 0);
                    break;

                case 'Y':
                    op = MemD(arch.y, 0);
                    break;

                case 'y':
                    op = MemD(arch.y, Displacement(wInstr));
                    break;

                case 'Z':
                    op = MemD(arch.z, 0);
                    break;

                case 'z':
                    op = MemD(arch.z, Displacement(wInstr));
                    break;

                default:
                    throw new NotImplementedException(string.Format("Unimplemented AVR8 format symbol '{0}'.'", fmt[i - 1]));
                }
                ops.Add(op);
            }
            return(new AvrInstruction
            {
                opcode = opcode,
                operands = ops.ToArray(),
            });
        }
Beispiel #4
0
            public override Tlcs90Instruction Decode(uint bPrev, Tlcs90Disassembler dasm)
            {
                RegisterStorage?baseReg = null;
                RegisterStorage?idxReg  = null;
                ushort?         absAddr = null;
                Constant?       offset  = null;

                switch (format[0])
                {
                case 'M':
                    if (!dasm.rdr.TryReadLeUInt16(out ushort a))
                    {
                        return(dasm.CreateInvalidInstruction());
                    }
                    absAddr = a;
                    break;

                case 'm':
                    if (!dasm.rdr.TryReadByte(out byte bb))
                    {
                        return(dasm.CreateInvalidInstruction());
                    }
                    absAddr = (ushort)(0xFF00 | bb);
                    break;

                case 'B': baseReg = Registers.bc; break;

                case 'D': baseReg = Registers.de; break;

                case 'H': baseReg = Registers.hl; break;

                case 'X': baseReg = Registers.ix; break;

                case 'Y': baseReg = Registers.iy; break;

                case 'S': baseReg = Registers.sp; break;

                case 'E':
                    switch (format[1])
                    {
                    case 'S': baseReg = Registers.sp;  break;

                    case 'X': baseReg = Registers.ix;  break;

                    case 'Y': baseReg = Registers.ix;  break;

                    case 'H': baseReg = Registers.hl; idxReg = Registers.a;  break;

                    default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format));
                    }
                    if (idxReg == null)
                    {
                        if (!dasm.rdr.TryReadByte(out byte bOff))
                        {
                            return(dasm.CreateInvalidInstruction());
                        }
                        offset = Constant.SByte((sbyte)bOff);
                    }
                    break;

                default: throw new NotImplementedException(string.Format("Tlcs-90: dst {0}", format));
                }
                if (!dasm.rdr.TryReadByte(out byte b))
                {
                    return(dasm.CreateInvalidInstruction());
                }
                var instr = dstEncodings[b].Decode(b, dasm);

                if (instr == null)
                {
                    return(dasm.CreateInvalidInstruction());
                }

                var operand = new MemoryOperand(dasm.dataWidth !)
                {
                    Base   = baseReg,
                    Offset = absAddr.HasValue
                        ? Constant.UInt16(absAddr.Value)
                        : offset,
                };

                if (dasm.backPatchOp == 0)
                {
                    if (instr.Operands.Length == 0)
                    {
                        instr.Operands = new MachineOperand[] { operand };
                    }
                    else
                    {
                        instr.Operands = new MachineOperand[] { operand, instr.Operands[0] };
                    }
                    if (instr.Operands.Length == 2)
                    {
                        instr.Operands[0].Width = instr.Operands[1].Width;
                    }
                }
                else if (dasm.backPatchOp == 1)
                {
                    if ((instr.Mnemonic == Mnemonic.jp || instr.Mnemonic == Mnemonic.call)
                        &&
                        operand.Base == null &&
                        operand.Index == null &&
                        operand.Offset != null)
                    {
                        // JP cc,(XXXX) should be JP cc,XXXX
                        var op = AddressOperand.Ptr16(operand.Offset.ToUInt16());
                        op.Width       = PrimitiveType.Ptr16;
                        instr.Operands = new MachineOperand[] { instr.Operands[0], op };
                    }
                    else
                    {
                        instr.Operands = new MachineOperand[] {
                            instr.Operands[0],
                            operand
                        };
                        instr.Operands[1].Width = instr.Operands[0].Width;
                    }
                }
                else
                {
                    return(dasm.CreateInvalidInstruction());
                }
                return(instr);
            }
Beispiel #5
0
        private i8051Instruction Decode(Opcode opcode, byte uInstr, string fmt)
        {
            byte b;
            var  ops = new List <MachineOperand>();

            foreach (var ch in fmt)
            {
                switch (ch)
                {
                case ',':
                    continue;

                case 'j': // An 11-bit address destination. This argument is used by ACALL and AJMP instructions. The target of the CALL or JMP must lie within the same 2K page as the first byte of the following instruction.
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(AddressOperand.Ptr16(
                                (ushort)(
                                    (rdr.Address.ToLinear() & ~0x7Ful) |
                                    (uInstr & 0xE0u) << 3 |
                                        b)));
                    break;

                case 'J':                                    // A 16-bit address destination. This argument is used by LCALL and LJMP instructions.
                    if (!rdr.TryReadBeUInt16(out var uAddr)) // Yes, big endian!
                    {
                        return(null);
                    }
                    ops.Add(AddressOperand.Ptr16(uAddr));
                    break;

                case 'o': // A signed (two's complement) 8-bit offset (-128 to 127) relative to the first byte of the following instruction.
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(AddressOperand.Create(rdr.Address + (sbyte)b));
                    break;

                case 'A': // The accumulator.
                    ops.Add(new RegisterOperand(Registers.A));
                    break;

                case 'd': // An internal data RAM location (0-127) or SFR (128-255).
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(MemoryOperand.Direct(Address.Ptr16(b)));
                    break;

                case 'r': // Register r0-r7
                    ops.Add(Reg(uInstr & 7));
                    break;

                case 'b': // A direct addressed bit in internal data RAM or SFR memory.
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(BitReg(b, false));
                    break;

                case 'B': // A direct addressed bit in internal data RAM or SFR memory.
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(BitReg(b, true));
                    break;

                case 'C':   // C flag of PSW
                    ops.Add(new FlagGroupOperand(arch.GetFlagGroup((uint)FlagM.C)));
                    break;

                case 'D':   // @DPTR
                    ops.Add(MemoryOperand.Indirect(Registers.DPTR));
                    break;

                case 'p':   // DPTR register pair
                    ops.Add(new SequenceOperand(Registers.DPTR));
                    break;

                case 'i': // A constant included in the instruction encoding.
                    if (!rdr.TryReadByte(out b))
                    {
                        return(null);
                    }
                    ops.Add(ImmediateOperand.Byte(b));
                    break;

                case 'I': // A constant included in the instruction encoding.
                    if (!rdr.TryReadUInt16(out var w))
                    {
                        return(null);
                    }
                    ops.Add(ImmediateOperand.Word16(w));
                    break;

                case '@': // @Ri	An internal data RAM location (0-255) addressed indirectly through R0 or R1.
                    ops.Add(MemoryOperand.Indirect(Registers.GetRegister(uInstr & 1)));
                    break;

                case '+': // @A + DPTR:
                    ops.Add(MemoryOperand.Indexed(Registers.DPTR, Registers.A));
                    break;

                case 'P': // @A + PC:
                    ops.Add(MemoryOperand.Indexed(Registers.PC, Registers.A));
                    break;

                case '*': // AB register pair
                    ops.Add(new SequenceOperand(Registers.AB));
                    break;

                default:
                    EmitUnitTest(opcode, uInstr);
                    break;
                }
            }

            return(new i8051Instruction
            {
                Opcode = opcode,
                Address = this.addr,
                Length = (int)(rdr.Address - this.addr),
                Operand1 = ops.Count >= 1 ? ops[0] : null,
                Operand2 = ops.Count >= 2 ? ops[1] : null,
                Operand3 = ops.Count >= 3 ? ops[2] : null,
            });
        }