private bool TryDecodeOperand(PrimitiveType width, out MachineOperand op) { op = null; byte b; byte bSpecifier; ushort w; uint dw; if (!rdr.TryReadByte(out bSpecifier)) { return(false); } var reg = arch.GetRegister(bSpecifier & 0xF); switch (bSpecifier >> 4) { case 0: // Literal mode case 1: case 2: case 3: op = LiteralOperand(width, bSpecifier); break; case 4: // Index mode op = IndexOperand(width, reg); break; case 5: // Register mode op = new RegisterOperand(reg); break; case 6: // Register deferred op = new MemoryOperand(width) { Base = reg }; break; case 7: // Autodecrement mode op = new MemoryOperand(width) { Base = reg, AutoDecrement = true, }; break; case 8: // Autoincrement mode if (reg.Number == 0x0F) { op = ImmediateOperand(width); } else { op = new MemoryOperand(width) { Base = reg, AutoIncrement = true, }; } break; case 9: // Deferred Autoincrement mode op = new MemoryOperand(width) { Base = reg, AutoIncrement = true, Deferred = true, }; break; case 0xA: // Displacement mode case 0xD: if (!rdr.TryReadByte(out b)) { return(false); } op = DisplacementOperand(width, reg, Constant.SByte((sbyte)b), bSpecifier); break; case 0xB: case 0xE: if (!rdr.TryReadUInt16(out w)) { return(false); } op = DisplacementOperand(width, reg, Constant.Int16((short)w), bSpecifier); break; case 0xC: case 0xF: if (!rdr.TryReadUInt32(out dw)) { return(false); } op = DisplacementOperand(width, reg, Constant.Word32(dw), bSpecifier); break; default: throw new InvalidCastException("Impossiburu!"); } return(true); }
private bool CompareOp(MachineOperand opA, MachineOperand opB) { if (opA == null && opB == null) { return(true); } if (opA == null || opB == null) { return(false); } if (opA.GetType() != opB.GetType()) { return(false); } var regOpA = opA as RegisterOperand; if (regOpA != null) { if (NormalizeRegisters) { return(true); } var regOpB = (RegisterOperand)opB; return(regOpA.Register == regOpB.Register); } var immOpA = opA as ImmediateOperand; if (immOpA != null) { if (NormalizeConstants) { return(true); } var immOpB = (ImmediateOperand)opB; return(CompareValues(immOpA.Value, immOpB.Value)); } var addrOpA = opA as AddressOperand; if (addrOpA != null) { if (NormalizeConstants) { return(true); } var addrOpB = (AddressOperand)opB; return(addrOpA.Address.ToLinear() == addrOpB.Address.ToLinear()); } var condOpA = opA as ConditionOperand; if (condOpA != null) { return(condOpA.Code == ((ConditionOperand)opB).Code); } var memOpA = opA as MemoryOperand; if (memOpA != null) { var memOpB = (MemoryOperand)opB; if (NormalizeRegisters && !CompareRegisters(memOpA.Base, memOpB.Base)) { return(false); } if (NormalizeConstants && !CompareValues(memOpA.Offset, memOpB.Offset)) { return(false); } return(true); } throw new NotImplementedException(); }
private bool TryParseOperandInner(ushort uInstr, byte addressMode, byte operandBits, PrimitiveType dataWidth, EndianImageReader rdr, out MachineOperand op) { Constant offset; switch (addressMode) { case 0: // Data register direct. op = DataRegisterOperand(operandBits, 0); return(true); case 1: // Address register direct op = new RegisterOperand(AddressRegister(operandBits, 0)); return(true); case 2: // Address register indirect op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0)); return(true); case 3: // Address register indirect with postincrement. op = MemoryOperand.PostIncrement(dataWidth, AddressRegister(operandBits, 0)); return(true); case 4: // Address register indirect with predecrement. op = MemoryOperand.PreDecrement(dataWidth, AddressRegister(operandBits, 0)); return(true); case 5: // Address register indirect with displacement. if (!rdr.TryReadBe(PrimitiveType.Int16, out offset)) { op = default !; return(false); } op = MemoryOperand.Indirect(dataWidth, AddressRegister(operandBits, 0), offset); return(true);
private Expression SrcOp(MachineOperand opSrc) { return(orw.Transform(instrCur, opSrc, opSrc.Width, state)); }
private Expression DstOp(MachineOperand op, Expression src, Func <Expression, Expression> fn) { var regOp = op as RegisterOperand; if (regOp != null) { var id = binder.EnsureRegister(regOp.Register); m.Assign(id, fn(src)); return(id); } var mem = op as MemoryOperand; if (mem != null) { Identifier r0; Identifier gbr; Identifier reg; var tmp = binder.CreateTemporary(op.Width); switch (mem.mode) { case AddressingMode.Indirect: reg = binder.EnsureRegister(mem.reg); m.Assign( m.Load(mem.Width, reg), fn(src)); return(null); case AddressingMode.IndirectDisplacement: reg = binder.EnsureRegister(mem.reg); m.Assign( m.Load(mem.Width, m.IAdd(reg, Constant.Int32(mem.disp))), fn(src)); return(null); case AddressingMode.IndirectPreDecr: reg = binder.EnsureRegister(mem.reg); m.Assign(reg, m.ISub(reg, Constant.Int32(mem.Width.Size))); m.Assign( m.Load(tmp.DataType, reg), fn(src)); return(null); case AddressingMode.IndexedIndirect: m.Assign( m.Load(mem.Width, m.IAdd( binder.EnsureRegister(Registers.r0), binder.EnsureRegister(mem.reg))), fn(src)); return(null); case AddressingMode.GbrIndexedIndirect: r0 = binder.EnsureRegister(Registers.r0); gbr = binder.EnsureRegister(Registers.gbr); m.Assign(tmp, m.Load(tmp.DataType, m.IAdd(r0, gbr))); m.Assign( m.Load(tmp.DataType, m.IAdd(r0, gbr)), fn(src)); return(tmp); default: throw new NotImplementedException(mem.mode.ToString()); } } throw new NotImplementedException(op.GetType().Name); }
private bool Compare(MachineOperand a, MachineOperand b) { if (a == null && b == null) { return(true); } if (a == null || b == null) { return(false); } if (a.GetType() != b.GetType()) { return(false); } var rA = a as RegisterOperand; if (rA != null) { if (NormalizeRegisters) { return(true); } var rB = (RegisterOperand)b; return(rA.Register == rB.Register); } var iA = a as ImmediateOperand; if (iA != null) { if (NormalizeConstants) { return(true); } var iB = (ImmediateOperand)b; return(CompareValues(iA.Value, iB.Value)); } var aA = a as AddressOperand; if (aA != null) { if (NormalizeConstants) { return(true); } var aB = (AddressOperand)b; return(aA.Address.ToLinear() == aB.Address.ToLinear()); } var mA = a as IndirectOperand; if (mA != null) { var mB = (IndirectOperand)b; if (!NormalizeRegisters && mA.Base != mB.Base) { return(false); } if (!NormalizeConstants && mA.Offset != mB.Offset) { return(false); } return(true); } throw new NotImplementedException(); }
private bool Compare(MachineOperand opA, MachineOperand opB) { if (opA == null && opB == null) { return(true); } if (opA == null || opB == null) { return(false); } if (opA.GetType() != opB.GetType()) { return(false); } if (opA is RegisterOperand regA) { var regB = (RegisterOperand)opB; return(NormalizeRegisters || regA.Register == regB.Register); } if (opA is M68kImmediateOperand immA) { var immB = (M68kImmediateOperand)opB; return(CompareValues(immA.Constant, immB.Constant)); } if (opA is PredecrementMemoryOperand preA) { var preB = (PredecrementMemoryOperand)opB; return(CompareRegisters(preA.Register, preB.Register)); } if (opA is PostIncrementMemoryOperand postA) { var postB = (PostIncrementMemoryOperand)opB; return(CompareRegisters(postA.Register, postB.Register)); } if (opA is RegisterSetOperand regsetA) { var regsetB = (RegisterSetOperand)opB; return(NormalizeRegisters || regsetA.BitSet == regsetB.BitSet); } if (opA is MemoryOperand memA) { var memB = (MemoryOperand)opB; if (!NormalizeRegisters && !CompareRegisters(memA.Base, memB.Base)) { return(false); } return(NormalizeConstants || CompareValues(memA.Offset, memB.Offset)); } if (opA is M68kAddressOperand addrA) { var addrB = (M68kAddressOperand)opB; return(NormalizeConstants || addrA.Address == addrB.Address); } if (opA is IndirectIndexedOperand idxA) { var idxB = (IndirectIndexedOperand)opB; if (!NormalizeRegisters) { if (!CompareRegisters(idxA.ARegister, idxB.ARegister)) { return(false); } if (!CompareRegisters(idxA.XRegister, idxB.XRegister)) { return(false); } } if (!NormalizeConstants) { if (idxA.Imm8 != idxB.Imm8) { return(false); } if (idxA.Scale != idxB.Scale) { return(false); } } return(true); } throw new NotImplementedException(opA.GetType().FullName); }
private void Branch(ConditionCode code, MachineOperand op) { this.iclass = InstrClass.ConditionalTransfer; m.Branch(m.Test(code, orw.AluRegister(Registers.FPUF)), OperandAsCodeAddress(op)!, InstrClass.ConditionalTransfer); }
private Identifier Reg(MachineOperand op) { return(binder.EnsureRegister(((RegisterOperand)op).Register)); }
private int OperandHash(MachineOperand op) { if (op == null) { return(0); } if (op is RegisterOperand rop) { if (NormalizeRegisters) { return(0); } else { return(rop.Register.GetHashCode()); } } if (op is M68kImmediateOperand immop) { if (NormalizeConstants) { return(0); } else { return(immop.Constant.GetHashCode()); } } if (op is M68kAddressOperand addrOp) { if (NormalizeConstants) { return(0); } else { return(addrOp.Address.GetHashCode()); } } if (op is MemoryOperand memOp) { int h = 0; if (!NormalizeConstants && memOp.Offset != null) { h = memOp.Offset.GetHashCode(); } if (!NormalizeRegisters) { h = h * 9 ^ memOp.Base.GetHashCode(); } return(h); } if (op is IndirectIndexedOperand ind) { int h = 0; if (!NormalizeConstants) { h = ind.Imm8.GetHashCode(); h = h * 11 ^ ind.Scale.GetHashCode(); h = h * 13 ^ ind.Imm8.GetHashCode(); } if (!NormalizeRegisters) { h = h * 5 ^ ind.ARegister.GetHashCode(); h = h * 17 ^ ind.XRegister.GetHashCode(); } return(h); } if (op is PredecrementMemoryOperand pre) { int h = 43; if (!NormalizeRegisters) { h = h * 5 ^ base.GetRegisterHash(pre.Register); } return(h); } if (op is PostIncrementMemoryOperand post) { int h = 47; if (!NormalizeRegisters) { h = h * 7 ^ base.GetRegisterHash(post.Register); } return(h); } if (op is RegisterSetOperand regset) { int h = 29; if (!NormalizeRegisters) { h = h ^ regset.BitSet.GetHashCode(); } return(h); } if (op is IndexedOperand indexOp) { int h = 53; if (!NormalizeRegisters) { if (indexOp.Base != null) { h = h * 7 ^ GetRegisterHash(indexOp.Base); } if (indexOp.Index != null) { h = h * 11 ^ GetRegisterHash(indexOp.Index); h = h * 13 ^ indexOp.index_reg_width !.GetHashCode(); } } if (!NormalizeConstants) { if (indexOp.BaseDisplacement != null) { h = h * 17 ^ indexOp.BaseDisplacement.GetHashCode(); } if (indexOp.IndexScale != 0) { h = h * 19 ^ indexOp.IndexScale; } } return(h); } throw new NotImplementedException(); }
private Constant Imm(MachineOperand op) { return(((ImmediateOperand)op).Value); }
private Address Addr(MachineOperand op) { return(((AddressOperand)op).Address); }
private RegisterStorage GetRegister(MachineOperand op) { var rOp = op as RegisterOperand; return(rOp?.Register); }
// Zero-extend an operand known to be unsigned immediate. private Constant RewriteUimm(MachineOperand op) { var iOp = (ImmediateOperand)op; return(Constant.UInt32(iOp.Value.ToUInt32())); }
private bool ImplicitWidth(MachineOperand op) { return(op is RegisterOperand || op is X86AddressOperand); }
public DecoratorOperand(DataType width, MachineOperand op) : base(width) { this.Operand = op; }
protected virtual (FSRIndexedMode indMode, Expression memPtr) GetMemFileAccess(MachineOperand opernd) { switch (opernd) { case PICOperandBankedMemory bnkmem: var offset = bnkmem.Offset; if (PICRegisters.TryGetAlwaysAccessibleRegister(offset, out var regsrc)) { var srciopr = PICRegisters.IndirectOpMode(regsrc, out PICRegisterStorage indsrcreg); if (srciopr != FSRIndexedMode.None) { return(srciopr, binder.EnsureRegister(indsrcreg)); } return(FSRIndexedMode.None, binder.EnsureRegister(regsrc)); } return(FSRIndexedMode.None, DataBankMem8(Bsr, Constant.Byte(offset))); case PICOperandRegister reg: var iopr = PICRegisters.IndirectOpMode(reg.Register, out PICRegisterStorage indreg); if (iopr != FSRIndexedMode.None) { return(iopr, binder.EnsureRegister(indreg)); } return(iopr, binder.EnsureRegister(reg.Register)); default: throw new InvalidOperationException($"Invalid PIC instruction's memory operand: {opernd}"); } }
private Expression SrcOp(MachineOperand op, Func <int, int> immediateFn = null) { var regOp = op as RegisterOperand; if (regOp != null) { var id = binder.EnsureRegister(regOp.Register); return(id); } var immOp = op as ImmediateOperand; if (immOp != null) { return(Constant.Word32(immediateFn(immOp.Value.ToInt32()))); } var addrOp = op as AddressOperand; if (addrOp != null) { return(addrOp.Address); } var mem = op as MemoryOperand; if (mem != null) { Identifier reg; switch (mem.mode) { default: throw new NotImplementedException(mem.mode.ToString()); case AddressingMode.Indirect: return(m.Load(mem.Width, binder.EnsureRegister(mem.reg))); case AddressingMode.IndirectPreDecr: reg = binder.EnsureRegister(mem.reg); m.Assign(reg, m.IAdd(reg, Constant.Int32(mem.Width.Size))); return(m.Load(mem.Width, reg)); case AddressingMode.IndirectPostIncr: var t = binder.CreateTemporary(mem.Width); reg = binder.EnsureRegister(mem.reg); m.Assign(t, m.Load(mem.Width, reg)); m.Assign(reg, m.IAdd(reg, Constant.Int32(t.DataType.Size))); return(t); case AddressingMode.IndirectDisplacement: reg = binder.EnsureRegister(mem.reg); return(m.Load( mem.Width, m.IAdd(reg, Constant.Int32(mem.disp)))); case AddressingMode.IndexedIndirect: return(m.Load(mem.Width, m.IAdd( binder.EnsureRegister(Registers.r0), binder.EnsureRegister(mem.reg)))); case AddressingMode.PcRelativeDisplacement: var addr = instr.Address.ToUInt32(); if (mem.Width.Size == 4) { addr &= ~3u; } addr += (uint)(mem.disp + 4); return(m.Load(mem.Width, Address.Ptr32(addr))); } } throw new NotImplementedException(op.GetType().Name); }
protected override (FSRIndexedMode indMode, Expression memPtr) GetMemFileAccess(MachineOperand opernd) { if (opernd is PICOperandBankedMemory bankmemop && bankmemop.IsAccess) { var bankmem = PICMemoryDescriptor.CreateBankedAddr(bankmemop); if (PICMemoryDescriptor.CanBeFSR2IndexAddress(bankmem)) { return(FSRIndexedMode.None, DataMem8(m.IAdd(Fsr2, bankmem.BankOffset))); // Address is in the form [FSR2]+offset ("à la" Extended Execution mode). } if (PICMemoryDescriptor.TryGetAbsDataAddress(bankmem, out var absAddr)) { if (PICRegisters.TryGetRegister(absAddr, out var sfr)) { var iop = PICRegisters.IndirectOpMode(sfr, out PICRegisterStorage fsrreg); if (iop != FSRIndexedMode.None) { return(iop, binder.EnsureRegister(fsrreg)); } return(iop, binder.EnsureRegister(sfr)); } return(FSRIndexedMode.None, DataMem8(absAddr)); } } return(base.GetMemFileAccess(opernd)); }
private int GetHashCode(MachineOperand op) { if (op == null) { return(0); } var r = op as RegisterOperand; if (r != null) { if (NormalizeRegisters) { return(0); } else { return(GetRegisterHash(r.Register)); } } var i = op as ImmediateOperand; if (i != null) { if (NormalizeConstants) { return(0); } else { return(GetConstantHash(i.Value)); } } var a = op as AddressOperand; if (a != null) { if (NormalizeConstants) { return(0); } else { return(a.Address.GetHashCode()); } } var m = op as IndirectOperand; if (m != null) { int h = 0; if (!NormalizeRegisters) { h = GetRegisterHash(m.Base); } if (!NormalizeConstants) { h ^= m.Offset.GetHashCode(); } return(h); } return(42); }
private Expression?RewriteJmpSrc(MachineOperand op) { if (!(op is MemoryOperand memOp)) { // PDP-11 always has a memory reference // for the destination of a transfer instruction. return(null); } var r = memOp.Register != null ? binder.EnsureRegister(memOp.Register) : null; var tmp = binder.CreateTemporary(op.Width); switch (memOp.Mode) { default: throw new AddressCorrelatedException( dasm.Current.Address, "Not implemented: addressing mode {0}.", memOp.Mode); case AddressMode.RegDef: return(r !); case AddressMode.Absolute: return(Address.Ptr16(memOp.EffectiveAddress)); case AddressMode.AutoIncr: m.Assign(tmp, m.Mem(PrimitiveType.Ptr16, r !)); m.Assign(r !, m.IAdd(r !, memOp.Width.Size)); break; case AddressMode.AutoIncrDef: m.Assign(tmp, m.Mem(op.Width, r !)); m.Assign(r !, m.IAdd(r !, memOp.Width.Size)); break; case AddressMode.AutoDecr: m.Assign(r !, m.ISub(r !, memOp.Width.Size)); return(m.Mem(op.Width, r !)); case AddressMode.AutoDecrDef: m.Assign(r !, m.ISub(r !, memOp.Width.Size)); m.Assign(tmp, m.Mem(op.Width, m.Mem(PrimitiveType.Ptr16, r !))); return(tmp); case AddressMode.Indexed: if (memOp.Register == Registers.pc) { var offset = (short)memOp.EffectiveAddress; var addrBase = (long)instr.Address.ToLinear(); var addr = Address.Ptr16((ushort)(instr.Length + addrBase + offset)); return(addr); } else { return(m.Mem( this.dasm.Current.DataWidth !, m.IAdd(r !, Constant.Word16(memOp.EffectiveAddress)))); } case AddressMode.IndexedDef: if (memOp.Register == Registers.pc) { var offset = (short)memOp.EffectiveAddress; var addrBase = (long)instr.Address.ToLinear() + instr.Length; var addr = m.Ptr16((ushort)(addrBase + offset)); return(m.Mem( PrimitiveType.Word16, addr)); } else { return(m.Mem( PrimitiveType.Ptr16, m.IAdd(r !, Constant.Word16(memOp.EffectiveAddress)))); } } return(tmp); /* * var immOp = op as ImmediateOperand; * if (immOp != null) * { * return immOp.Value; * } * var addrOp = op as AddressOperand; * if (addrOp != null) * { * return addrOp.Address; * } * throw new NotImplementedException(); */ }
public bool TryParseOperand(ushort opcode, int bitOffset, PrimitiveType dataWidth, EndianImageReader rdr, out MachineOperand op) { opcode >>= bitOffset; byte operandBits = (byte)(opcode & 7); byte addressMode = (byte)((opcode >> 3) & 7); return(TryParseOperandInner(opcode, addressMode, operandBits, dataWidth, rdr, out op)); }
private Expression OpSrc(MachineOperand op) { switch (op) { case RegisterOperand reg: return(binder.EnsureRegister(reg.Register)); case FlagGroupOperand flg: return(binder.EnsureFlagGroup(flg.FlagGroup)); case ImmediateOperand imm: return(imm.Value); case AddressOperand addr: return(addr.Address); case MemoryOperand mem: Expression ea; if (mem.DirectAddress != null) { if (mem.Index != null) { ea = m.IAdd(mem.DirectAddress, binder.EnsureRegister(mem.Index)); } else { ea = mem.DirectAddress; } } else if (mem.Register != null) { if (mem.Index != null) { var idx = binder.EnsureRegister(mem.Index); if (mem.Register == Registers.PC) { ea = m.IAdd( instr.Address + instr.Length, idx); } else { ea = binder.EnsureIdentifier(mem.Register); ea = m.IAdd(ea, idx); } } else { ea = binder.EnsureIdentifier(mem.Register); } } else { throw new NotImplementedException(); } return(m.Mem(mem.Width, ea)); case BitOperand bit: Expression e = binder.EnsureRegister(bit.Register); if (bit.Bit > 0) { e = m.Shr(e, (byte)bit.Bit); } e = m.And(e, 1); if (bit.Negated) { e = m.Not(e); } return(e); case SequenceOperand seq: return(binder.EnsureSequence(seq.Sequence.DataType, seq.Sequence.Name, seq.Sequence.Elements)); default: throw new NotImplementedException($"Not implemented {op.GetType().Name}."); } }
private void RewriteConditionalGoto(ConditionCode cc, MachineOperand op1) { iclass = InstrClass.ConditionalTransfer; m.Branch(CreateTestCondition(cc, instrCur.Mnemonic), OperandAsCodeAddress(op1) !, InstrClass.ConditionalTransfer); }
private void WriteDst(MachineOperand op, Expression src) { switch (op) { case RegisterOperand reg: m.Assign(binder.EnsureRegister(reg.Register), src); break; case FlagGroupOperand flg: m.Assign(binder.EnsureFlagGroup(flg.FlagGroup), src); break; case MemoryOperand mem: Expression ea; if (mem.DirectAddress != null) { if (mem.Index != null) { ea = m.IAdd(mem.DirectAddress, binder.EnsureRegister(mem.Index)); } else { ea = mem.DirectAddress; } } else if (mem.Register != null) { if (mem.Index != null) { var idx = binder.EnsureRegister(mem.Index); if (mem.Register == Registers.PC) { ea = m.IAdd( instr.Address + instr.Length, idx); } else { ea = binder.EnsureIdentifier(mem.Register); ea = m.IAdd(ea, idx); } } else { ea = binder.EnsureIdentifier(mem.Register); } } else { throw new NotImplementedException(); } m.Assign(m.Mem(mem.Width, ea), src); break; case BitOperand bit: if (bit.Bit > 0) { src = m.Shl(src, (byte)bit.Bit); } var mask = (byte)~(1 << bit.Bit); var e = binder.EnsureRegister(bit.Register); m.Assign(e, m.Or(m.And(e, mask), src)); break; default: throw new NotImplementedException($"Not implemented {op.GetType().Name}."); } }
private Expression SrcOp(MachineOperand opSrc, PrimitiveType dstWidth) { return(orw.Transform(instrCur, opSrc, dstWidth, state)); }
private bool HasImplicitWidth(MachineOperand op) { return(op is RegisterOperand || op is AddressOperand || op is FpuOperand); }
private Expression RewriteOp(MachineOperand op) { return(RewriteOp(op, false)); }
private int HashOp(MachineOperand op) { if (op == null) { return(0); } int h = op.GetType().GetHashCode(); var regOp = op as RegisterOperand; if (regOp != null) { if (NormalizeRegisters) { return(h); } else { return(h * 29 ^ regOp.Register.GetHashCode()); } } var immOp = op as ImmediateOperand; if (immOp != null) { if (NormalizeConstants) { return(h); } else { return(h * 13 ^ GetConstantHash(immOp.Value)); } } var addrOp = op as AddressOperand; if (addrOp != null) { if (NormalizeConstants) { return(h); } else { return(h * 29 ^ addrOp.Address.GetHashCode()); } } var condOp = op as ConditionOperand; if (condOp != null) { return(h * 19 ^ condOp.Code.GetHashCode()); } var memOp = op as MemoryOperand; if (memOp != null) { if (!NormalizeRegisters && memOp.Base != null) { h = h * 23 ^ memOp.Base.GetHashCode(); } if (!NormalizeConstants && memOp.Offset != null) { h = h * 17 ^ GetConstantHash(memOp.Offset); } return(h); } throw new NotImplementedException(string.Format("{0} ({1})", op, op.GetType().Name)); }