Example #1
0
 private void RewriteBinop(Func<Expression, Expression, BinaryExpression> fn, FlagM grf)
 {
     var dst = OpSrc(instr.Operands[0]);
     var src = OpSrc(instr.Operands[1]);
     m.Assign(dst, fn(dst, src));
     if (grf != 0)
     {
         var flg = arch.GetFlagGroup(Registers.PSW, (uint)grf);
         m.Assign(binder.EnsureFlagGroup(flg), m.Cond(dst));
     }
 }
Example #2
0
        public void RewriteAddcSubb(Func <Expression, Expression, Expression> opr)
        {
            // We do not take the trouble of widening the CF to the word size
            // to simplify code analysis in later stages.
            var c   = binder.EnsureFlagGroup(arch.GetFlagGroup(Registers.PSW, (uint)FlagM.C));
            var dst = OpSrc(instr.Operands[0], arch.DataMemory);
            var src = OpSrc(instr.Operands[1], arch.DataMemory);

            m.Assign(
                dst,
                opr(
                    opr(
                        dst,
                        src),
                    c));
            var grf = binder.EnsureFlagGroup(arch.GetFlagGroup(Registers.PSW, (uint)(FlagM.C | FlagM.AC | FlagM.OV | FlagM.P)));

            m.Assign(grf, m.Cond(dst));
        }
Example #3
0
        private i8051Instruction Decode(Mnemonic 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(Registers.PSW, (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
            {
                Mnemonic = opcode,
                Address = this.addr,
                Length = (int)(rdr.Address - this.addr),
                Operands = ops.ToArray()
            });
        }