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; }); }
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 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())); }