private AddressOperand RelativeBranch(uint wInstr) { int off = (short)wInstr; off <<= 2; return(AddressOperand.Ptr32((uint)(off + rdr.Address.ToUInt32()))); }
private VaxInstruction DecodeOperands(Opcode opcode, string format) { var ops = new List <MachineOperand>(); MachineOperand op; PrimitiveType width; int i = 0; while (i != format.Length) { switch (format[i++]) { case ',': continue; case 'a': if (!TryDecodeOperand(Width(format[i++]), out op)) { return(null); } break; case 'r': case 'w': case 'm': case 'v': if (!TryDecodeOperand(Width(format[i++]), out op)) { return(null); } break; case 'b': width = Width(format[i++]); long jOffset = rdr.ReadLeSigned(width); ulong uAddr = (uint)((long)rdr.Address.Offset + jOffset); op = AddressOperand.Ptr32((uint)uAddr); break; default: throw new NotImplementedException( string.Format( "Access type {0} not implemented.", format[i - 1])); } if (op == null) { return(new VaxInstruction { Opcode = Opcode.Invalid, Operands = new MachineOperand[0], }); } ops.Add(op); } return(new VaxInstruction { Opcode = opcode, Operands = ops.ToArray() }); }
private MachineOperand NegativePcRelativeAddress() { var nAddr = ((0xFFFF0000 | state.imm16) << 2) + (int)(rdr.Address.ToUInt32() & ~3); return(AddressOperand.Ptr32((uint)nAddr)); }
private static Mutator b(PrimitiveType width) { return(d => { long jOffset = d.rdr.ReadLeSigned(width); uint uAddr = (uint)((long)d.rdr.Address.Offset + jOffset); d.ops.Add(AddressOperand.Ptr32(uAddr)); return true; }); }
internal static bool Jijkm(uint uInstr, YmpDisassembler dasm) { if (!dasm.rdr.TryReadBeUInt16(out ushort n)) { return(false); } var uAddr = ((uInstr & 0x1FF) << 16) | n; dasm.ops.Add(AddressOperand.Ptr32(uAddr)); return(true); }
// absolute address used by jump and call. private static bool Q(uint wInstr, Avr8Disassembler dasm) { if (!dasm.rdr.TryReadLeUInt16(out ushort w2)) { return(false); } dasm.ops.Add(AddressOperand.Ptr32( (uint)(((wInstr >> 4) & 0x1F) << 18) | (uint)((wInstr & 1) << 17) | (uint)(w2 << 1))); return(true); }
private static Mutator b(PrimitiveType width) { return((u, d) => { if (!d.rdr.TryReadLeSigned(width, out long jOffset)) { return false; } uint uAddr = (uint)((long)d.rdr.Address.Offset + jOffset); d.ops.Add(AddressOperand.Ptr32(uAddr)); return true; }); }
private MachineOperand DisplacementOperand(PrimitiveType width, RegisterStorage reg, Constant c, byte bSpecifier) { if (reg.Number == 15) { return(AddressOperand.Ptr32( (uint)((int)rdr.Address.ToLinear() + c.ToInt32()))); } return(new MemoryOperand(width) { Base = reg, Offset = c, Deferred = (bSpecifier >> 4) > 0xC }); }
private MachineOperand CreateAccess( RegisterStorage baseReg, int offset) { if (baseReg == null || baseReg.Number == 0) { return(AddressOperand.Ptr32((uint)offset)); } return(new MemoryOperand(PrimitiveType.Word32) { Base = baseReg, Offset = offset }); }
private static Mutator <OpenRISCDisassembler> Page(int bitLen) { var offsetField = new Bitfield(0, bitLen); return((u, d) => { long pageOffset = offsetField.ReadSigned(u) << 13; long lAddr = (long)(d.addr.ToLinear() & ~8192ul) + pageOffset; ulong uAddr = (ulong)lAddr; var aOp = d.arch.WordWidth.BitSize == 64 ? AddressOperand.Ptr64(uAddr) : AddressOperand.Ptr32((uint)uAddr); d.ops.Add(aOp); return true; }); }
internal static bool Jnm(uint uInstr, YmpDisassembler dasm) { if (!dasm.rdr.TryReadBeUInt16(out ushort m)) { return(false); } if (!dasm.rdr.TryReadBeUInt16(out ushort n)) { return(false); } uint nm = n; nm = nm << 16 | m; dasm.ops.Add(AddressOperand.Ptr32(nm)); return(true); }
private MachineOperand AbsoluteDestination(int addrBytes) { uint uAddr = 0; int sh = 0; while (--addrBytes >= 0) { if (!rdr.TryReadByte(out byte b)) { return(null); } uAddr |= (uint)b << sh; sh += 8; } return(AddressOperand.Ptr32(uAddr)); }
private MachineOperand CreateAccess( RegisterStorage baseReg, RegisterStorage idxReg, int offset) { if ((baseReg == null || baseReg.Number == 0) && (idxReg == null || idxReg.Number == 0)) { return AddressOperand.Ptr32((uint)offset); } return new MemoryOperand(PrimitiveType.Word32) { Base = baseReg, Index = idxReg, Offset = offset }; }
public override XtensaInstruction Decode(XtensaDisassembler dasm) { int shoff = dasm.state.imm12; if (shoff > 0x7FF) { shoff |= ~0x7FF; } var dst = AddressOperand.Ptr32((uint) ((int)dasm.state.addr.ToUInt32() + 4 + shoff)); return(new XtensaInstruction { Opcode = opcode, Operands = new MachineOperand[] { dasm.GetAluRegister(dasm.state.s), dst, } }); }
private Msp430Instruction Decode(ushort uInstr, Opcode opcode, string fmt) { PrimitiveType dataWidth = null; int i = 0; if (i < fmt.Length) { switch (fmt[i++]) { case 'w': // use width bit dataWidth = (uInstr & 0x40) != 0 ? PrimitiveType.Byte : PrimitiveType.Word16; break; case 'a': // a/w bit 4. dataWidth = (uInstr & 0x04) != 0 ? PrimitiveType.Word16 : Msp430Architecture.Word20; break; case 'x': dataWidth = (uExtension != 0) && (uExtension & 0x40) == 0 ? Msp430Architecture.Word20 : PrimitiveType.Word16; break; case 'p': dataWidth = Msp430Architecture.Word20; break; case 'W': // b/w/a combined from the op and the extension var w = ((this.uExtension & 0x40) >> 5) | (uInstr & 0x040) >> 6; switch (w) { case 0: return(Invalid()); case 1: dataWidth = Msp430Architecture.Word20; break; case 2: dataWidth = PrimitiveType.Word16; break; case 3: dataWidth = PrimitiveType.Byte; break; } break; default: --i; break; } } MachineOperand op1 = null; MachineOperand op2 = null; int aS; int iReg; if (i < fmt.Length) { switch (fmt[i++]) { case 'J': int offset = (short)(uInstr << 6) >> 5; op1 = AddressOperand.Create(rdr.Address + offset); break; case 'r': op1 = SourceOperand(0, uInstr & 0x0F, dataWidth); break; case 'S': aS = (uInstr >> 4) & 0x03; iReg = (uInstr >> 8) & 0x0F; op1 = SourceOperand(aS, iReg, dataWidth); if (op1 == null) { return(null); } break; case 's': aS = (uInstr >> 4) & 0x03; iReg = uInstr & 0x0F; op1 = SourceOperand(aS, iReg, dataWidth); if (op1 == null) { return(null); } break; case 'n': int n = 1 + ((uInstr >> 4) & 0x0F); op1 = ImmediateOperand.Byte((byte)n); break; case 'N': n = 1 + ((uInstr >> 10) & 3); op1 = ImmediateOperand.Byte((byte)n); break; case '@': iReg = (uInstr >> 8) & 0x0F; var reg = Registers.GpRegisters[iReg]; op1 = new MemoryOperand(Msp430Architecture.Word20) { Base = reg, }; break; case '+': iReg = (uInstr >> 8) & 0x0F; reg = Registers.GpRegisters[iReg]; op1 = PostInc(reg, Msp430Architecture.Word20); break; case '&': if (!rdr.TryReadLeUInt16(out var lo16)) { return(Invalid()); } var hi4 = (uint)(uInstr >> 8) & 0x0F; //$TODO: 20-bit address? op1 = AddressOperand.Ptr32((hi4 << 16) | lo16); break; case 'x': if (!rdr.TryReadLeInt16(out var idxOffset)) { return(Invalid()); } iReg = (uInstr >> 8) & 0x0F; reg = Registers.GpRegisters[iReg]; op1 = new MemoryOperand(Msp430Architecture.Word20) { Base = reg, Offset = idxOffset }; break; default: --i; break; } } if (i < fmt.Length) { switch (fmt[i]) { case 'D': var aD = (uInstr >> 7) & 0x01; iReg = uInstr & 0x0F; if (iReg == 3) { return(Invalid()); } var reg = Registers.GpRegisters[iReg]; if (aD == 0) { if (iReg == 3) { return(Invalid()); } op2 = new RegisterOperand(reg); } else { op2 = Indexed(reg, dataWidth); if (op2 == null) { return(null); } } break; case 'r': op2 = SourceOperand(0, uInstr & 0x0F, dataWidth); break; } } int rep = (uExtension & 0x0F); var instr = new Msp430Instruction { opcode = opcode, dataWidth = dataWidth, op1 = op1, op2 = op2, repeatImm = (uExtension & 0x80) != 0 ? 0 : rep + 1, repeatReg = (uExtension & 0x80) != 0 ? Registers.GpRegisters[rep] : null, }; instr = SpecialCase(instr); return(instr); }
public IEnumerator <MachineInstruction> GetEnumerator() { Address addr = rdr.Address; while (rdr.TryReadByte(out byte opcode)) { MachineInstruction instr; switch ((opcode >> 4) & 0xF) { case 0: // nop instr = new TestMachineInstruction(InstrClass.Padding | InstrClass.Linear, Mnemonic.nop); break; case 1: // ALU instr = new TestMachineInstruction(InstrClass.Linear, Mnemonic.alu); break; case 2: // a jump if (!rdr.TryReadBeUInt16(out ushort uAddr)) { instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid); } else if ((opcode & 0xF) != 0) { instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Conditional, Mnemonic.bra); } else { instr = new TestMachineInstruction(InstrClass.Transfer, Mnemonic.jmp); } instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) }; break; case 3: // a call. if (!rdr.TryReadBeUInt16(out uAddr)) { instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid); } else { instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Call, Mnemonic.call); } instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) }; break; case 4: // a jump with delay slot if (!rdr.TryReadBeUInt16(out uAddr)) { instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid); } else if ((opcode & 0xF) != 0) { instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Conditional | InstrClass.Delay, Mnemonic.braD); } else { instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Delay, Mnemonic.jmpD); } instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) }; break; case 5: // a call with delay slot. if (!rdr.TryReadBeUInt16(out uAddr)) { instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid); } else { instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Call | InstrClass.Delay, Mnemonic.callD); } instr.Operands = new MachineOperand[] { AddressOperand.Ptr32(uAddr) }; break; case 6: // return instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Return, Mnemonic.ret); break; case 7: // return with delay slot. instr = new TestMachineInstruction(InstrClass.Transfer | InstrClass.Return | InstrClass.Delay, Mnemonic.ret); break; default: instr = new TestMachineInstruction(InstrClass.Invalid, Mnemonic.Invalid); break; } var addrNew = rdr.Address; instr.Address = addr; instr.Length = (int)(addrNew - addr); yield return(instr); addr = addrNew; } }
public AvrInstruction Decode(ushort wInstr, Opcode opcode, InstrClass iclass, 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) & 0x0F); break; case 'R': // source register (5 bits) op = Register((wInstr >> 5) & 0x10 | (wInstr) & 0x0F); break; case 'r': if (i < fmt.Length && fmt[i] == '4') { ++i; // source register (r16-r31) op = Register(0x10 | wInstr & 0x0F); } else { // source register (5 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 + 2); 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, iclass = iclass, operands = ops.ToArray(), }); }
private X86Instruction DecodeOperands(Opcode opcode, byte op, string strFormat, InstrClass iclass) { if (strFormat == null) { return(null); } MachineOperand pOperand; PrimitiveType width = null; PrimitiveType iWidth = dataWidth; byte modRm; List <MachineOperand> ops = new List <MachineOperand>(); int i = 0; while (i != strFormat.Length) { if (strFormat[i] == ',') { ++i; } pOperand = null; MemoryOperand memOp; char chFmt = strFormat[i++]; switch (chFmt) { case '1': pOperand = new ImmediateOperand(Constant.Byte(1)); break; case '3': pOperand = new ImmediateOperand(Constant.Byte(3)); break; case 'A': // Absolute memory address. ++i; if (!rdr.TryReadLeUInt16(out ushort off)) { return(null); } if (!rdr.TryReadLeUInt16(out ushort seg)) { return(null); } var addr = mode.CreateSegmentedAddress(seg, off); if (addr == null) { return(null); } pOperand = new X86AddressOperand(addr); break; case 'C': // control register encoded in the reg field. ++i; if (!TryEnsureModRM(out modRm)) { return(null); } var creg = mode.GetControlRegister((modRm >> 3) & 7); if (creg == null) { return(null); } pOperand = new RegisterOperand(creg); break; case 'D': // debug register encoded in the reg field. ++i; if (!TryEnsureModRM(out modRm)) { return(null); } var dreg = mode.GetDebugRegister((modRm >> 3) & 7); if (dreg == null) { return(null); } pOperand = new RegisterOperand(dreg); break; case 'E': // memory or register operand specified by mod & r/m fields. width = OperandWidth(strFormat, ref i); ++i; pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, GpRegFromBits); if (pOperand == null) { return(null); } break; case 'Q': // memory or register MMX operand specified by mod & r/m fields. width = SseOperandWidth(strFormat, ref i); pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, MmxRegFromBits); if (pOperand == null) { return(null); } break; case 'G': // register operand specified by the reg field of the modRM byte. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits)); break; case 'H': // If VEX encoding, use vvvv register. if (currentDecodingContext.IsVex) { width = SseOperandWidth(strFormat, ref i); pOperand = new RegisterOperand(XmmRegFromBits(currentDecodingContext.VexRegister, width)); } else { i = strFormat.IndexOf(',', i); } break; case 'N': // MMX register operand specified by the r/m field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, MmxRegFromBits)); break; case 'P': // MMX register operand specified by the reg field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits)); break; case 'I': // Immediate operand. if (strFormat[i] == 'x') { iWidth = width; // Use width of the previous operand. } else { width = OperandWidth(strFormat, ref i); // Don't use the width of the previous operand. } ++i; pOperand = CreateImmediateOperand(width, dataWidth); if (pOperand == null) { return(null); } break; case 'L': // The upper 4 bits of the 8-bit immediate selects a 128-bit XMM register or a 256-bit YMM register, determined // by operand type. if (!rdr.TryReadByte(out var lReg)) { return(null); } if (strFormat[i] == 'x') { iWidth = width; // Use width of the previous operand. } else { width = OperandWidth(strFormat, ref i); // Don't use the width of the previous operand. } ++i; pOperand = new RegisterOperand(XmmRegFromBits((lReg >> 4) & 0xF, width)); break; case 'J': // Relative ("near") jump. width = OperandWidth(strFormat, ref i); ++i; Constant cOffset; if (!rdr.TryRead(width, out cOffset)) { return(null); } long jOffset = cOffset.ToInt64(); ulong uAddr = (ulong)((long)rdr.Address.Offset + jOffset); if (defaultAddressWidth.BitSize == 64) //$REVIEW: not too keen on the switch statement here. { pOperand = AddressOperand.Ptr64(uAddr); } else if (defaultAddressWidth.BitSize == 32) { pOperand = AddressOperand.Ptr32((uint)uAddr); } else { pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr)); } break; case 'M': // modRM may only refer to memory. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } if ((modRm & 0xC0) == 0xC0) { return(null); } pOperand = DecodeModRM(dataWidth, this.currentDecodingContext.SegmentOverride, GpRegFromBits) as MemoryOperand; if (pOperand == null) { return(null); } break; case 'O': // Offset of the operand is encoded directly after the opcode. width = OperandWidth(strFormat, ref i); ++i; if (!rdr.TryReadLe(addressWidth, out var offset)) { return(null); } pOperand = memOp = new MemoryOperand(width, offset); memOp.SegOverride = this.currentDecodingContext.SegmentOverride; break; case 'R': // register operand specified by the mod field of the modRM byte. width = OperandWidth(strFormat, ref i); ++i; if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, GpRegFromBits)); break; case 'S': // Segment register encoded by reg field of modRM byte. ++i; // Skip over the 'w'. if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(SegFromBits(modRm >> 3)); break; case 'U': // XMM operand specified by the modRm field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm, width, XmmRegFromBits)); break; case 'V': // XMM operand specified by the reg field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits)); break; case 'W': // memory or XMM operand specified by mod & r/m fields. width = SseOperandWidth(strFormat, ref i); pOperand = DecodeModRM(width, this.currentDecodingContext.SegmentOverride, XmmRegFromBits); break; case 'a': // Implicit use of accumulator. pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat, ref i))); ++i; break; case 'b': iWidth = PrimitiveType.Byte; pOperand = null; break; case 'c': // Implicit use of CL. pOperand = new RegisterOperand(Registers.cl); break; case 'd': // Implicit use of DX or EDX. width = OperandWidth(strFormat, ref i); ++i; pOperand = new RegisterOperand(RegFromBitsRexW(2, width)); break; case 'r': // Register encoded as last 3 bits of instruction. iWidth = width = OperandWidth(strFormat, ref i); ++i; pOperand = new RegisterOperand(RegFromBitsRexB(op, width)); break; case 's': // Segment encoded as next byte of the format string. pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0')); break; case 'F': // Floating-point ST(x) if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new FpuOperand(modRm & 0x07); break; case 'f': // ST(0) pOperand = new FpuOperand(0); break; default: throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat)); } if (pOperand != null) { ops.Add(pOperand); } } return(new X86Instruction(opcode, iclass, iWidth, addressWidth, ops.ToArray()) { repPrefix = this.currentDecodingContext.F2Prefix ? 2 : this.currentDecodingContext.F3Prefix ? 3 : 0 }); }
private MachineOperand JumpOffset(byte offset) { int dst = (int)state.addr.ToUInt32() + (sbyte)offset + 4; return(AddressOperand.Ptr32((uint)dst)); }
private AddressOperand LongJumpOffset() { return(AddressOperand.Ptr32((uint)((int)state.addr.ToLinear() + (state.offset + 4)))); }
private MachineOperand CallOffset(int offset) { return(AddressOperand.Ptr32((uint)((state.addr.ToUInt32() & ~3) + (offset << 2) + 4))); }
private IntelInstruction DecodeOperands(Opcode opcode, byte op, string strFormat) { MachineOperand pOperand; PrimitiveType width = null; PrimitiveType iWidth = dataWidth; byte modRm; List <MachineOperand> ops = new List <MachineOperand>(); int i = 0; while (i != strFormat.Length) { if (strFormat[i] == ',') { ++i; } pOperand = null; ImmediateOperand immOp; MemoryOperand memOp; X86AddressOperand addrOp; int offset; char chFmt = strFormat[i++]; switch (chFmt) { case '1': pOperand = immOp = new ImmediateOperand(Constant.Byte(1)); break; case '3': pOperand = immOp = new ImmediateOperand(Constant.Byte(3)); break; case 'A': // Absolute memory address. ++i; ushort off = rdr.ReadLeUInt16(); ushort seg = rdr.ReadLeUInt16(); pOperand = addrOp = new X86AddressOperand(Address.SegPtr(seg, off)); break; case 'E': // memory or register operand specified by mod & r/m fields. width = OperandWidth(strFormat[i++]); pOperand = DecodeModRM(width, segmentOverride, GpRegFromBits); break; case 'Q': // memory or register MMX operand specified by mod & r/m fields. width = OperandWidth(strFormat[i++]); pOperand = DecodeModRM(width, segmentOverride, MmxRegFromBits); break; case 'G': // register operand specified by the reg field of the modRM byte. width = OperandWidth(strFormat[i++]); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, GpRegFromBits)); break; case 'P': // MMX register operand specified by the reg field of the modRM byte. width = OperandWidth(strFormat[i++]); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, MmxRegFromBits)); break; case 'I': // Immediate operand. if (strFormat[i] == 'x') { iWidth = width; // Use width of the previous operand. } else { width = OperandWidth(strFormat[i]); // Don't use the width of the previous operand. } ++i; pOperand = CreateImmediateOperand(width, dataWidth); break; case 'J': // Relative ("near") jump. width = OperandWidth(strFormat[i++]); offset = rdr.ReadLeSigned(width); ulong uAddr = (ulong)((long)rdr.Address.Offset + (long)offset); if (defaultAddressWidth.BitSize == 64) //$REVIEW: not too keen on the switch statement here. { pOperand = AddressOperand.Ptr64(uAddr); } else if (defaultAddressWidth.BitSize == 32) { pOperand = AddressOperand.Ptr32((uint)uAddr); } else { pOperand = new ImmediateOperand(Constant.Create(defaultDataWidth, uAddr)); } break; case 'M': // modRM may only refer to memory. width = OperandWidth(strFormat[i++]); pOperand = DecodeModRM(dataWidth, segmentOverride, GpRegFromBits); break; case 'O': // Offset of the operand is encoded directly after the opcode. width = OperandWidth(strFormat[i++]); pOperand = memOp = new MemoryOperand(width, rdr.ReadLe(addressWidth)); memOp.SegOverride = segmentOverride; break; case 'S': // Segment register encoded by reg field of modRM byte. ++i; // Skip over the 'w'. if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(SegFromBits(modRm >> 3)); break; case 'V': // XMM operand specified by the reg field of the modRM byte. width = SseOperandWidth(strFormat, ref i); if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new RegisterOperand(RegFromBitsRexR(modRm >> 3, width, XmmRegFromBits)); break; case 'W': // memory or XMM operand specified by mod & r/m fields. width = SseOperandWidth(strFormat, ref i); pOperand = DecodeModRM(width, segmentOverride, XmmRegFromBits); break; case 'a': // Implicit use of accumulator. pOperand = new RegisterOperand(RegFromBitsRexW(0, OperandWidth(strFormat[i++]))); break; case 'b': iWidth = PrimitiveType.Byte; pOperand = null; break; case 'c': // Implicit use of CL. pOperand = new RegisterOperand(Registers.cl); break; case 'd': // Implicit use of DX or EDX. width = OperandWidth(strFormat[i++]); pOperand = new RegisterOperand(RegFromBitsRexW(2, width)); break; case 'r': // Register encoded as last 3 bits of instruction. width = OperandWidth(strFormat[i++]); pOperand = new RegisterOperand(RegFromBitsRexW(op, width)); break; case 's': // Segment encoded as next byte of the format string. pOperand = new RegisterOperand(SegFromBits(strFormat[i++] - '0')); break; case 'F': // Floating-point ST(x) if (!TryEnsureModRM(out modRm)) { return(null); } pOperand = new FpuOperand(modRm & 0x07); break; case 'f': // ST(0) pOperand = new FpuOperand(0); break; default: throw new ArgumentOutOfRangeException(string.Format("Unknown format specifier '{0}' at position {1} of format string '{2}'.", chFmt, i, strFormat)); } if (pOperand != null) { ops.Add(pOperand); } } return(new IntelInstruction(opcode, iWidth, addressWidth, ops.ToArray())); }
private AddressOperand LargeBranch(uint wInstr) { var off = (wInstr & 0x03FFFFFF) << 2; return(AddressOperand.Ptr32((rdr.Address.ToUInt32() & 0xF0000000u) | off)); }