/rust/registry/src/index.crates.io-1949cf8c6b5b557f/iced-x86-1.21.0/src/decoder.rs
Line | Count | Source |
1 | | // SPDX-License-Identifier: MIT |
2 | | // Copyright (C) 2018-present iced project and contributors |
3 | | |
4 | | macro_rules! mk_read_xx { |
5 | | ($slf:ident, $mem_ty:ty, $from_le:path, $ret_ty:ty, $err_expr:expr) => { |
6 | | const SIZE: usize = mem::size_of::<$mem_ty>(); |
7 | | const _: () = assert!(SIZE >= 1); |
8 | | const _: () = assert!(SIZE <= Decoder::MAX_READ_SIZE); |
9 | | let data_ptr = $slf.data_ptr; |
10 | | #[allow(trivial_numeric_casts)] |
11 | | { |
12 | | // This doesn't overflow data_ptr (verified in ctor since SIZE <= MAX_READ_SIZE) |
13 | | if data_ptr + SIZE - 1 < $slf.max_data_ptr { |
14 | | // SAFETY: |
15 | | // - cast: It's OK to cast to an unaligned `*const uXX` since we call read_unaligned() |
16 | | // - ptr::read_unaligned: ptr is readable and data (u8 slice) is initialized |
17 | | let result = $from_le(unsafe { ptr::read_unaligned(data_ptr as *const $mem_ty) }) as $ret_ty; |
18 | | // - data_ptr + SIZE doesn't overflow (verified in ctor since SIZE <= MAX_READ_SIZE) |
19 | | // - data_ptr + SIZE <= self.max_data_ptr (see `if` check above) |
20 | | $slf.data_ptr = data_ptr + SIZE; |
21 | | result |
22 | | } else { |
23 | | $err_expr |
24 | | } |
25 | | } |
26 | | }; |
27 | | } |
28 | | macro_rules! mk_read_xx_fn_body { |
29 | | ($slf:ident, $mem_ty:ty, $from_le:path, $ret_ty:ty) => { |
30 | | mk_read_xx!($slf, $mem_ty, $from_le, $ret_ty, { |
31 | | $slf.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
32 | | 0 |
33 | | }) |
34 | | }; |
35 | | } |
36 | | macro_rules! read_u8_break { |
37 | | ($slf:ident) => {{ |
38 | | mk_read_xx! {$slf, u8, u8::from_le, usize, break} |
39 | | }}; |
40 | | } |
41 | | #[cfg(not(feature = "__internal_flip"))] |
42 | | macro_rules! read_u16_break { |
43 | | ($slf:ident) => {{ |
44 | | mk_read_xx! {$slf, u16, u16::from_le, usize, break} |
45 | | }}; |
46 | | } |
47 | | macro_rules! read_u32_break { |
48 | | ($slf:ident) => {{ |
49 | | mk_read_xx! {$slf, u32, u32::from_le, usize, break} |
50 | | }}; |
51 | | } |
52 | | #[cfg(not(feature = "__internal_flip"))] |
53 | | macro_rules! read_op_mem_stmt_ret { |
54 | | ($decoder:ident, $instruction:ident, $stmts:block) => {{ |
55 | | debug_assert!($decoder.state.encoding() != EncodingKind::EVEX as u32 && $decoder.state.encoding() != EncodingKind::MVEX as u32); |
56 | | let index = $decoder.state.mem_index as usize; |
57 | | debug_assert!(index < $decoder.read_op_mem_fns.len()); |
58 | | // SAFETY: index is valid because modrm.mod = 0-2 (never 3 if we're here) so index will always be 0-10_111 (17h) |
59 | | let handler = unsafe { *$decoder.read_op_mem_fns.get_unchecked(index) }; |
60 | | |
61 | | $stmts |
62 | | |
63 | | if $decoder.state.address_size != OpSize::Size16 { |
64 | | (handler)($instruction, $decoder) |
65 | | } else { |
66 | | $decoder.read_op_mem_16($instruction, TupleType::N1); |
67 | | false |
68 | | } |
69 | | }}; |
70 | | } |
71 | | #[cfg(not(feature = "__internal_flip"))] |
72 | | macro_rules! read_op_mem_stmt { |
73 | | ($decoder:ident, $instruction:ident, $stmts:block) => { |
74 | | let _ = read_op_mem_stmt_ret!($decoder, $instruction, $stmts); |
75 | | }; |
76 | | } |
77 | | #[cfg(feature = "__internal_flip")] |
78 | | macro_rules! read_op_mem_stmt { |
79 | | ($decoder:ident, $instruction:ident, $stmts:block) => { |
80 | | debug_assert!($decoder.state.encoding() != EncodingKind::EVEX as u32 && $decoder.state.encoding() != EncodingKind::MVEX as u32); |
81 | | $stmts |
82 | | if $decoder.state.address_size != OpSize::Size16 { |
83 | | let _ = $decoder.read_op_mem_32_or_64($instruction); |
84 | | } else { |
85 | | $decoder.read_op_mem_16($instruction, TupleType::N1); |
86 | | } |
87 | | }; |
88 | | } |
89 | | |
90 | | mod enums; |
91 | | mod handlers; |
92 | | mod table_de; |
93 | | #[cfg(test)] |
94 | | pub(crate) mod tests; |
95 | | |
96 | | use crate::decoder::handlers::tables::TABLES; |
97 | | use crate::decoder::handlers::{OpCodeHandler, OpCodeHandlerDecodeFn}; |
98 | | use crate::iced_constants::IcedConstants; |
99 | | use crate::iced_error::IcedError; |
100 | | use crate::instruction_internal; |
101 | | use crate::tuple_type_tbl::get_disp8n; |
102 | | use crate::*; |
103 | | use core::iter::FusedIterator; |
104 | | use core::{cmp, fmt, mem, ptr}; |
105 | | |
106 | | #[rustfmt::skip] |
107 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
108 | | static READ_OP_MEM_VSIB_FNS: [fn(&mut Decoder<'_>, &mut Instruction, Register, TupleType, bool) -> bool; 0x18] = [ |
109 | | decoder_read_op_mem_vsib_0, |
110 | | decoder_read_op_mem_vsib_0, |
111 | | decoder_read_op_mem_vsib_0, |
112 | | decoder_read_op_mem_vsib_0, |
113 | | decoder_read_op_mem_vsib_0_4, |
114 | | decoder_read_op_mem_vsib_0_5, |
115 | | decoder_read_op_mem_vsib_0, |
116 | | decoder_read_op_mem_vsib_0, |
117 | | |
118 | | decoder_read_op_mem_vsib_1, |
119 | | decoder_read_op_mem_vsib_1, |
120 | | decoder_read_op_mem_vsib_1, |
121 | | decoder_read_op_mem_vsib_1, |
122 | | decoder_read_op_mem_vsib_1_4, |
123 | | decoder_read_op_mem_vsib_1, |
124 | | decoder_read_op_mem_vsib_1, |
125 | | decoder_read_op_mem_vsib_1, |
126 | | |
127 | | decoder_read_op_mem_vsib_2, |
128 | | decoder_read_op_mem_vsib_2, |
129 | | decoder_read_op_mem_vsib_2, |
130 | | decoder_read_op_mem_vsib_2, |
131 | | decoder_read_op_mem_vsib_2_4, |
132 | | decoder_read_op_mem_vsib_2, |
133 | | decoder_read_op_mem_vsib_2, |
134 | | decoder_read_op_mem_vsib_2, |
135 | | ]; |
136 | | |
137 | | static MEM_REGS_16: [(Register, Register); 8] = [ |
138 | | (Register::BX, Register::SI), |
139 | | (Register::BX, Register::DI), |
140 | | (Register::BP, Register::SI), |
141 | | (Register::BP, Register::DI), |
142 | | (Register::SI, Register::None), |
143 | | (Register::DI, Register::None), |
144 | | (Register::BP, Register::None), |
145 | | (Register::BX, Register::None), |
146 | | ]; |
147 | | |
148 | | // GENERATOR-BEGIN: OpSize |
149 | | // ⚠️This was generated by GENERATOR!🦹♂️ |
150 | | #[derive(Copy, Clone, Eq, PartialEq)] |
151 | | #[allow(dead_code)] |
152 | | pub(crate) enum OpSize { |
153 | | Size16, |
154 | | Size32, |
155 | | Size64, |
156 | | } |
157 | | #[rustfmt::skip] |
158 | | static GEN_DEBUG_OP_SIZE: [&str; 3] = [ |
159 | | "Size16", |
160 | | "Size32", |
161 | | "Size64", |
162 | | ]; |
163 | | impl fmt::Debug for OpSize { |
164 | | #[inline] |
165 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
166 | 0 | write!(f, "{}", GEN_DEBUG_OP_SIZE[*self as usize]) |
167 | 0 | } |
168 | | } |
169 | | impl Default for OpSize { |
170 | | #[must_use] |
171 | | #[inline] |
172 | 4.02k | fn default() -> Self { |
173 | 4.02k | OpSize::Size16 |
174 | 4.02k | } |
175 | | } |
176 | | // GENERATOR-END: OpSize |
177 | | |
178 | | // GENERATOR-BEGIN: DecoderError |
179 | | // ⚠️This was generated by GENERATOR!🦹♂️ |
180 | | /// Decoder error |
181 | | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
182 | | #[cfg_attr(not(feature = "exhaustive_enums"), non_exhaustive)] |
183 | | pub enum DecoderError { |
184 | | /// No error. The last decoded instruction is a valid instruction |
185 | | None = 0, |
186 | | /// It's an invalid instruction or an invalid encoding of an existing instruction (eg. some reserved bit is set/cleared) |
187 | | InvalidInstruction = 1, |
188 | | /// There's not enough bytes left to decode the instruction |
189 | | NoMoreBytes = 2, |
190 | | } |
191 | | #[rustfmt::skip] |
192 | | static GEN_DEBUG_DECODER_ERROR: [&str; 3] = [ |
193 | | "None", |
194 | | "InvalidInstruction", |
195 | | "NoMoreBytes", |
196 | | ]; |
197 | | impl fmt::Debug for DecoderError { |
198 | | #[inline] |
199 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
200 | 0 | write!(f, "{}", GEN_DEBUG_DECODER_ERROR[*self as usize]) |
201 | 0 | } |
202 | | } |
203 | | impl Default for DecoderError { |
204 | | #[must_use] |
205 | | #[inline] |
206 | 0 | fn default() -> Self { |
207 | 0 | DecoderError::None |
208 | 0 | } |
209 | | } |
210 | | #[allow(non_camel_case_types)] |
211 | | #[allow(dead_code)] |
212 | | pub(crate) type DecoderErrorUnderlyingType = u8; |
213 | | #[rustfmt::skip] |
214 | | impl DecoderError { |
215 | | /// Iterates over all `DecoderError` enum values |
216 | | #[inline] |
217 | 0 | pub fn values() -> impl Iterator<Item = DecoderError> + DoubleEndedIterator + ExactSizeIterator + FusedIterator { |
218 | | // SAFETY: all values 0-max are valid enum values |
219 | 0 | (0..IcedConstants::DECODER_ERROR_ENUM_COUNT).map(|x| unsafe { mem::transmute::<u8, DecoderError>(x as u8) }) |
220 | 0 | } |
221 | | } |
222 | | #[test] |
223 | | #[rustfmt::skip] |
224 | | fn test_decodererror_values() { |
225 | | let mut iter = DecoderError::values(); |
226 | | assert_eq!(iter.size_hint(), (IcedConstants::DECODER_ERROR_ENUM_COUNT, Some(IcedConstants::DECODER_ERROR_ENUM_COUNT))); |
227 | | assert_eq!(iter.len(), IcedConstants::DECODER_ERROR_ENUM_COUNT); |
228 | | assert!(iter.next().is_some()); |
229 | | assert_eq!(iter.size_hint(), (IcedConstants::DECODER_ERROR_ENUM_COUNT - 1, Some(IcedConstants::DECODER_ERROR_ENUM_COUNT - 1))); |
230 | | assert_eq!(iter.len(), IcedConstants::DECODER_ERROR_ENUM_COUNT - 1); |
231 | | |
232 | | let values: Vec<DecoderError> = DecoderError::values().collect(); |
233 | | assert_eq!(values.len(), IcedConstants::DECODER_ERROR_ENUM_COUNT); |
234 | | for (i, value) in values.into_iter().enumerate() { |
235 | | assert_eq!(i, value as usize); |
236 | | } |
237 | | |
238 | | let values1: Vec<DecoderError> = DecoderError::values().collect(); |
239 | | let mut values2: Vec<DecoderError> = DecoderError::values().rev().collect(); |
240 | | values2.reverse(); |
241 | | assert_eq!(values1, values2); |
242 | | } |
243 | | #[rustfmt::skip] |
244 | | impl TryFrom<usize> for DecoderError { |
245 | | type Error = IcedError; |
246 | | #[inline] |
247 | 0 | fn try_from(value: usize) -> Result<Self, Self::Error> { |
248 | 0 | if value < IcedConstants::DECODER_ERROR_ENUM_COUNT { |
249 | | // SAFETY: all values 0-max are valid enum values |
250 | 0 | Ok(unsafe { mem::transmute(value as u8) }) |
251 | | } else { |
252 | 0 | Err(IcedError::new("Invalid DecoderError value")) |
253 | | } |
254 | 0 | } |
255 | | } |
256 | | #[test] |
257 | | #[rustfmt::skip] |
258 | | fn test_decodererror_try_from_usize() { |
259 | | for value in DecoderError::values() { |
260 | | let converted = <DecoderError as TryFrom<usize>>::try_from(value as usize).unwrap(); |
261 | | assert_eq!(converted, value); |
262 | | } |
263 | | assert!(<DecoderError as TryFrom<usize>>::try_from(IcedConstants::DECODER_ERROR_ENUM_COUNT).is_err()); |
264 | | assert!(<DecoderError as TryFrom<usize>>::try_from(core::usize::MAX).is_err()); |
265 | | } |
266 | | #[cfg(feature = "serde")] |
267 | | #[rustfmt::skip] |
268 | | #[allow(clippy::zero_sized_map_values)] |
269 | | const _: () = { |
270 | | use core::marker::PhantomData; |
271 | | use serde::de; |
272 | | use serde::{Deserialize, Deserializer, Serialize, Serializer}; |
273 | | type EnumType = DecoderError; |
274 | | impl Serialize for EnumType { |
275 | | #[inline] |
276 | | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
277 | | where |
278 | | S: Serializer, |
279 | | { |
280 | | serializer.serialize_u8(*self as u8) |
281 | | } |
282 | | } |
283 | | impl<'de> Deserialize<'de> for EnumType { |
284 | | #[inline] |
285 | | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
286 | | where |
287 | | D: Deserializer<'de>, |
288 | | { |
289 | | struct Visitor<'de> { |
290 | | marker: PhantomData<EnumType>, |
291 | | lifetime: PhantomData<&'de ()>, |
292 | | } |
293 | | impl<'de> de::Visitor<'de> for Visitor<'de> { |
294 | | type Value = EnumType; |
295 | | #[inline] |
296 | | fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { |
297 | | formatter.write_str("enum DecoderError") |
298 | | } |
299 | | #[inline] |
300 | | fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> |
301 | | where |
302 | | E: de::Error, |
303 | | { |
304 | | if let Ok(v) = <usize as TryFrom<_>>::try_from(v) { |
305 | | if let Ok(value) = <EnumType as TryFrom<_>>::try_from(v) { |
306 | | return Ok(value); |
307 | | } |
308 | | } |
309 | | Err(de::Error::invalid_value(de::Unexpected::Unsigned(v), &"a valid DecoderError variant value")) |
310 | | } |
311 | | } |
312 | | deserializer.deserialize_u8(Visitor { marker: PhantomData::<EnumType>, lifetime: PhantomData }) |
313 | | } |
314 | | } |
315 | | }; |
316 | | // GENERATOR-END: DecoderError |
317 | | |
318 | | // GENERATOR-BEGIN: DecoderOptions |
319 | | // ⚠️This was generated by GENERATOR!🦹♂️ |
320 | | /// Decoder options |
321 | | #[allow(missing_copy_implementations)] |
322 | | #[allow(missing_debug_implementations)] |
323 | | pub struct DecoderOptions; |
324 | | impl DecoderOptions { |
325 | | /// No option is enabled |
326 | | pub const NONE: u32 = 0x0000_0000; |
327 | | /// Disable some checks for invalid encodings of instructions, eg. most instructions can't use a `LOCK` prefix so if one is found, they're decoded as [`Code::INVALID`] unless this option is enabled. |
328 | | /// |
329 | | /// [`Code::INVALID`]: enum.Code.html#variant.INVALID |
330 | | pub const NO_INVALID_CHECK: u32 = 0x0000_0001; |
331 | | /// AMD decoder: allow 16-bit branch/ret instructions in 64-bit mode, no `o64 CALL/JMP FAR [mem], o64 LSS/LFS/LGS`, `UD0` has no modr/m byte, decode `LOCK MOV CR`. The AMD decoder can still decode Intel instructions. |
332 | | pub const AMD: u32 = 0x0000_0002; |
333 | | /// Decode opcodes `0F0D` and `0F18-0F1F` as reserved-nop instructions (eg. [`Code::Reservednop_rm32_r32_0F1D`]) |
334 | | /// |
335 | | /// [`Code::Reservednop_rm32_r32_0F1D`]: enum.Code.html#variant.Reservednop_rm32_r32_0F1D |
336 | | pub const FORCE_RESERVED_NOP: u32 = 0x0000_0004; |
337 | | /// Decode `UMOV` instructions |
338 | | pub const UMOV: u32 = 0x0000_0008; |
339 | | /// Decode `XBTS`/`IBTS` |
340 | | pub const XBTS: u32 = 0x0000_0010; |
341 | | /// Decode `0FA6`/`0FA7` as `CMPXCHG` |
342 | | pub const CMPXCHG486A: u32 = 0x0000_0020; |
343 | | /// Decode some old removed FPU instructions (eg. `FRSTPM`) |
344 | | pub const OLD_FPU: u32 = 0x0000_0040; |
345 | | /// Decode `PCOMMIT` |
346 | | pub const PCOMMIT: u32 = 0x0000_0080; |
347 | | /// Decode 286 `STOREALL`/`LOADALL` (`0F04` and `0F05`) |
348 | | pub const LOADALL286: u32 = 0x0000_0100; |
349 | | /// Decode 386 `LOADALL` |
350 | | pub const LOADALL386: u32 = 0x0000_0200; |
351 | | /// Decode `CL1INVMB` |
352 | | pub const CL1INVMB: u32 = 0x0000_0400; |
353 | | /// Decode `MOV r32,tr` and `MOV tr,r32` |
354 | | pub const MOV_TR: u32 = 0x0000_0800; |
355 | | /// Decode `JMPE` instructions |
356 | | pub const JMPE: u32 = 0x0000_1000; |
357 | | /// Don't decode `PAUSE`, decode `NOP` instead |
358 | | pub const NO_PAUSE: u32 = 0x0000_2000; |
359 | | /// Don't decode `WBNOINVD`, decode `WBINVD` instead |
360 | | pub const NO_WBNOINVD: u32 = 0x0000_4000; |
361 | | /// Decode undocumented Intel `RDUDBG` and `WRUDBG` instructions |
362 | | pub const UDBG: u32 = 0x0000_8000; |
363 | | /// Don't decode `TZCNT`, decode `BSF` instead |
364 | | pub const NO_MPFX_0FBC: u32 = 0x0001_0000; |
365 | | /// Don't decode `LZCNT`, decode `BSR` instead |
366 | | pub const NO_MPFX_0FBD: u32 = 0x0002_0000; |
367 | | /// Don't decode `LAHF` and `SAHF` in 64-bit mode |
368 | | pub const NO_LAHF_SAHF_64: u32 = 0x0004_0000; |
369 | | /// Decode `MPX` instructions |
370 | | pub const MPX: u32 = 0x0008_0000; |
371 | | /// Decode most Cyrix instructions: `FPU`, `EMMI`, `SMM`, `DDI` |
372 | | pub const CYRIX: u32 = 0x0010_0000; |
373 | | /// Decode Cyrix `SMINT 0F7E` (Cyrix 6x86 or earlier) |
374 | | pub const CYRIX_SMINT_0F7E: u32 = 0x0020_0000; |
375 | | /// Decode Cyrix `DMI` instructions (AMD Geode GX/LX) |
376 | | pub const CYRIX_DMI: u32 = 0x0040_0000; |
377 | | /// Decode Centaur `ALTINST` |
378 | | pub const ALTINST: u32 = 0x0080_0000; |
379 | | /// Decode Intel Knights Corner instructions (requires the `mvex` feature) |
380 | | pub const KNC: u32 = 0x0100_0000; |
381 | | } |
382 | | // GENERATOR-END: DecoderOptions |
383 | | |
384 | | // GENERATOR-BEGIN: HandlerFlags |
385 | | // ⚠️This was generated by GENERATOR!🦹♂️ |
386 | | pub(crate) struct HandlerFlags; |
387 | | #[allow(dead_code)] |
388 | | impl HandlerFlags { |
389 | | pub(crate) const NONE: u32 = 0x0000_0000; |
390 | | pub(crate) const XACQUIRE: u32 = 0x0000_0001; |
391 | | pub(crate) const XRELEASE: u32 = 0x0000_0002; |
392 | | pub(crate) const XACQUIRE_XRELEASE_NO_LOCK: u32 = 0x0000_0004; |
393 | | pub(crate) const LOCK: u32 = 0x0000_0008; |
394 | | } |
395 | | // GENERATOR-END: HandlerFlags |
396 | | |
397 | | // GENERATOR-BEGIN: StateFlags |
398 | | // ⚠️This was generated by GENERATOR!🦹♂️ |
399 | | pub(crate) struct StateFlags; |
400 | | #[allow(dead_code)] |
401 | | impl StateFlags { |
402 | | pub(crate) const IP_REL64: u32 = 0x0000_0001; |
403 | | pub(crate) const IP_REL32: u32 = 0x0000_0002; |
404 | | pub(crate) const HAS_REX: u32 = 0x0000_0008; |
405 | | pub(crate) const B: u32 = 0x0000_0010; |
406 | | pub(crate) const Z: u32 = 0x0000_0020; |
407 | | pub(crate) const IS_INVALID: u32 = 0x0000_0040; |
408 | | pub(crate) const W: u32 = 0x0000_0080; |
409 | | pub(crate) const NO_IMM: u32 = 0x0000_0100; |
410 | | pub(crate) const ADDR64: u32 = 0x0000_0200; |
411 | | pub(crate) const BRANCH_IMM8: u32 = 0x0000_0400; |
412 | | pub(crate) const XBEGIN: u32 = 0x0000_0800; |
413 | | pub(crate) const LOCK: u32 = 0x0000_1000; |
414 | | pub(crate) const ALLOW_LOCK: u32 = 0x0000_2000; |
415 | | pub(crate) const NO_MORE_BYTES: u32 = 0x0000_4000; |
416 | | pub(crate) const HAS66: u32 = 0x0000_8000; |
417 | | pub(crate) const MVEX_SSS_MASK: u32 = 0x0000_0007; |
418 | | pub(crate) const MVEX_SSS_SHIFT: u32 = 0x0000_0010; |
419 | | pub(crate) const MVEX_EH: u32 = 0x0008_0000; |
420 | | pub(crate) const ENCODING_MASK: u32 = 0x0000_0007; |
421 | | pub(crate) const ENCODING_SHIFT: u32 = 0x0000_001D; |
422 | | } |
423 | | // GENERATOR-END: StateFlags |
424 | | |
425 | | // This is `repr(u32)` since we need the decoder field near other fields that also get cleared in `decode()`. |
426 | | // It could fit in a `u8` but then it wouldn't be cleared at the same time as the other fields since the |
427 | | // compiler would move other `u32` fields above it to align the fields. |
428 | | #[repr(u32)] |
429 | | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
430 | | enum DecoderMandatoryPrefix { |
431 | | PNP = 0, |
432 | | P66 = 1, |
433 | | PF3 = 2, |
434 | | PF2 = 3, |
435 | | } |
436 | | impl Default for DecoderMandatoryPrefix { |
437 | 4.02k | fn default() -> Self { |
438 | 4.02k | DecoderMandatoryPrefix::PNP |
439 | 4.02k | } |
440 | | } |
441 | | |
442 | | #[derive(Default)] |
443 | | #[allow(dead_code)] |
444 | | struct State { |
445 | | modrm: u32, // 0-0xFF |
446 | | mod_: u32, // 0-3 |
447 | | reg: u32, // 0-7 |
448 | | rm: u32, // 0-7 |
449 | | |
450 | | // *************************** |
451 | | // These fields are cleared in decode_out() and should be close so the compiler can optimize clearing them. |
452 | | extra_register_base: u32, // R << 3 |
453 | | extra_index_register_base: u32, // X << 3 |
454 | | extra_base_register_base: u32, // B << 3 |
455 | | extra_index_register_base_vsib: u32, |
456 | | flags: u32, // StateFlags |
457 | | mandatory_prefix: DecoderMandatoryPrefix, |
458 | | |
459 | | vvvv: u32, // V`vvvv. Not stored in inverted form. If 16/32-bit mode, bits [4:3] are cleared |
460 | | vvvv_invalid_check: u32, // vvvv bits, even in 16/32-bit mode. |
461 | | // *************************** |
462 | | mem_index: u32, // (mod << 3 | rm) and an index into the mem handler tables if mod <= 2 |
463 | | vector_length: VectorLength, |
464 | | aaa: u32, |
465 | | extra_register_base_evex: u32, // EVEX/MVEX.R' << 4 |
466 | | extra_base_register_base_evex: u32, // EVEX/MVEX.XB << 3 |
467 | | // The order of these 4 fields is important. They're accessed as a u32 (decode_out_ptr()) by the compiler so should be 4 byte aligned. |
468 | | address_size: OpSize, |
469 | | operand_size: OpSize, |
470 | | segment_prio: u8, // 0=ES/CS/SS/DS, 1=FS/GS |
471 | | dummy: u8, |
472 | | // ================= |
473 | | } |
474 | | |
475 | | impl State { |
476 | | #[must_use] |
477 | | #[inline(always)] |
478 | | #[cfg(debug_assertions)] |
479 | | const fn encoding(&self) -> u32 { |
480 | | (self.flags >> StateFlags::ENCODING_SHIFT) & StateFlags::ENCODING_MASK |
481 | | } |
482 | | |
483 | | #[must_use] |
484 | | #[inline(always)] |
485 | | #[cfg(not(debug_assertions))] |
486 | | #[allow(clippy::unused_self)] |
487 | 0 | fn encoding(&self) -> u32 { |
488 | 0 | EncodingKind::Legacy as u32 |
489 | 0 | } |
490 | | |
491 | | #[must_use] |
492 | | #[inline] |
493 | | #[cfg(feature = "mvex")] |
494 | | fn sss(&self) -> u32 { |
495 | | (self.flags >> StateFlags::MVEX_SSS_SHIFT) & StateFlags::MVEX_SSS_MASK |
496 | | } |
497 | | } |
498 | | |
499 | | /// Decodes 16/32/64-bit x86 instructions |
500 | | #[allow(missing_debug_implementations)] |
501 | | #[allow(dead_code)] |
502 | | pub struct Decoder<'a> |
503 | | where |
504 | | Self: Send + Sync, |
505 | | { |
506 | | // Current RIP value |
507 | | ip: u64, |
508 | | |
509 | | // Next bytes to read if there's enough bytes left to read. |
510 | | // This can be 1 byte past the last byte of `data`. |
511 | | // Invariant: data.as_ptr() <= data_ptr <= max_data_ptr <= data.as_ptr() + data.len() == data_ptr_end |
512 | | // Invariant: {data_ptr,max_data_ptr,data_ptr_end}.add(max(MAX_READ_SIZE, MAX_INSTRUCTION_LENGTH)) doesn't overflow |
513 | | data_ptr: usize, |
514 | | // This is `data.as_ptr() + data.len()` (1 byte past the last valid byte). |
515 | | // This is guaranteed to be >= data_ptr (see the ctor), in other words, it can't overflow to 0 |
516 | | // Invariant: data.as_ptr() <= data_ptr <= max_data_ptr <= data.as_ptr() + data.len() == data_ptr_end |
517 | | // Invariant: {data_ptr,max_data_ptr,data_ptr_end}.add(max(MAX_READ_SIZE, MAX_INSTRUCTION_LENGTH)) doesn't overflow |
518 | | data_ptr_end: usize, |
519 | | // Set to cmp::min(self.data_ptr + IcedConstants::MAX_INSTRUCTION_LENGTH, self.data_ptr_end) |
520 | | // and is guaranteed to not overflow |
521 | | // Initialized in decode() to at most 15 bytes after data_ptr so read_uXX() fails quickly after at most 15 read bytes |
522 | | // (1MB prefixes won't cause it to read 1MB prefixes, it will stop after at most 15). |
523 | | // Invariant: data.as_ptr() <= data_ptr <= max_data_ptr <= data.as_ptr() + data.len() == data_ptr_end |
524 | | // Invariant: {data_ptr,max_data_ptr,data_ptr_end}.add(max(MAX_READ_SIZE, MAX_INSTRUCTION_LENGTH)) doesn't overflow |
525 | | max_data_ptr: usize, |
526 | | // Initialized to start of data (data_ptr) when decode() is called. Used to calculate current IP/offset (when decoding) if needed. |
527 | | instr_start_data_ptr: usize, |
528 | | |
529 | | handlers_map0: &'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100], |
530 | | // MAP0 is only used by MVEX. Don't allocate an extra array element if mvex feature is disabled (common case) |
531 | | #[cfg(all(not(feature = "no_vex"), feature = "mvex"))] |
532 | | handlers_vex_map0: &'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100], |
533 | | #[cfg(not(feature = "no_vex"))] |
534 | | handlers_vex: [&'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100]; 3], |
535 | | #[cfg(not(feature = "no_evex"))] |
536 | | handlers_evex: [&'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100]; 6], |
537 | | #[cfg(not(feature = "no_xop"))] |
538 | | handlers_xop: [&'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100]; 3], |
539 | | #[cfg(feature = "mvex")] |
540 | | handlers_mvex: [&'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100]; 3], |
541 | | |
542 | | #[cfg(not(all(not(feature = "no_vex"), feature = "mvex")))] |
543 | | handlers_vex_map0: (), |
544 | | #[cfg(feature = "no_vex")] |
545 | | handlers_vex: [(); 3], |
546 | | #[cfg(feature = "no_evex")] |
547 | | handlers_evex: [(); 6], |
548 | | #[cfg(feature = "no_xop")] |
549 | | handlers_xop: [(); 3], |
550 | | #[cfg(not(feature = "mvex"))] |
551 | | handlers_mvex: [(); 3], |
552 | | |
553 | | #[cfg(not(feature = "__internal_flip"))] |
554 | | read_op_mem_fns: [fn(&mut Instruction, &mut Decoder<'a>) -> bool; 0x18], |
555 | | #[cfg(feature = "__internal_flip")] |
556 | | read_op_mem_fns: (), |
557 | | |
558 | | state: State, |
559 | | // DecoderOptions |
560 | | options: u32, |
561 | | // All 1s if we should check for invalid instructions, else 0 |
562 | | invalid_check_mask: u32, |
563 | | // StateFlags::W if 64-bit mode, 0 if 16/32-bit mode |
564 | | is64b_mode_and_w: u32, |
565 | | // 7 in 16/32-bit mode, 15 in 64-bit mode |
566 | | reg15_mask: u32, |
567 | | // 0 in 16/32-bit mode, 0E0h in 64-bit mode |
568 | | mask_e0: u32, |
569 | | rex_mask: u32, |
570 | | bitness: u32, |
571 | | // The order of these 4 fields is important. They're accessed as a u32 (decode_out_ptr()) by the compiler so should be 4 byte aligned. |
572 | | default_address_size: OpSize, |
573 | | default_operand_size: OpSize, |
574 | | segment_prio: u8, // Always 0 |
575 | | dummy: u8, // Padding so the compiler can read 4 bytes, see decode_out_ptr() |
576 | | // ================= |
577 | | default_inverted_address_size: OpSize, |
578 | | default_inverted_operand_size: OpSize, |
579 | | // true if 64-bit mode, false if 16/32-bit mode |
580 | | is64b_mode: bool, |
581 | | default_code_size: CodeSize, |
582 | | // Offset of displacement in the instruction. Only used by get_constant_offsets() to return the offset of the displ |
583 | | displ_index: u8, |
584 | | |
585 | | // Input data provided by the user. When there's no more bytes left to read we'll return a NoMoreBytes error |
586 | | data: &'a [u8], |
587 | | } |
588 | | |
589 | | macro_rules! write_base_reg { |
590 | | ($instruction:ident, $expr:expr) => { |
591 | | debug_assert!($expr < IcedConstants::REGISTER_ENUM_COUNT as u32); |
592 | | $instruction.set_memory_base(unsafe { mem::transmute($expr as RegisterUnderlyingType) }); |
593 | | }; |
594 | | } |
595 | | |
596 | | macro_rules! write_index_reg { |
597 | | ($instruction:ident, $expr:expr) => { |
598 | | debug_assert!($expr < IcedConstants::REGISTER_ENUM_COUNT as u32); |
599 | | $instruction.set_memory_index(unsafe { mem::transmute($expr as RegisterUnderlyingType) }); |
600 | | }; |
601 | | } |
602 | | |
603 | | impl<'a> Decoder<'a> { |
604 | | const MAX_READ_SIZE: usize = 8; |
605 | | |
606 | | /// Creates a decoder |
607 | | /// |
608 | | /// # Panics |
609 | | /// |
610 | | /// Panics if `bitness` is not one of 16, 32, 64. |
611 | | /// |
612 | | /// # Arguments |
613 | | /// |
614 | | /// * `bitness`: 16, 32 or 64 |
615 | | /// * `data`: Data to decode |
616 | | /// * `options`: Decoder options, `0` or eg. `DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD` |
617 | | /// |
618 | | /// # Examples |
619 | | /// |
620 | | /// ``` |
621 | | /// use iced_x86::*; |
622 | | /// |
623 | | /// // xchg ah,[rdx+rsi+16h] |
624 | | /// // xacquire lock add dword ptr [rax],5Ah |
625 | | /// // vmovdqu64 zmm18{k3}{z},zmm11 |
626 | | /// let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3"; |
627 | | /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE); |
628 | | /// decoder.set_ip(0x1234_5678); |
629 | | /// |
630 | | /// let instr1 = decoder.decode(); |
631 | | /// assert_eq!(instr1.code(), Code::Xchg_rm8_r8); |
632 | | /// assert_eq!(instr1.mnemonic(), Mnemonic::Xchg); |
633 | | /// assert_eq!(instr1.len(), 4); |
634 | | /// |
635 | | /// let instr2 = decoder.decode(); |
636 | | /// assert_eq!(instr2.code(), Code::Add_rm32_imm8); |
637 | | /// assert_eq!(instr2.mnemonic(), Mnemonic::Add); |
638 | | /// assert_eq!(instr2.len(), 5); |
639 | | /// |
640 | | /// let instr3 = decoder.decode(); |
641 | | /// assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512); |
642 | | /// assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64); |
643 | | /// assert_eq!(instr3.len(), 6); |
644 | | /// ``` |
645 | | /// |
646 | | /// It's sometimes useful to decode some invalid instructions, eg. `lock add esi,ecx`. |
647 | | /// Pass in [`DecoderOptions::NO_INVALID_CHECK`] to the constructor and the decoder |
648 | | /// will decode some invalid encodings. |
649 | | /// |
650 | | /// [`DecoderOptions::NO_INVALID_CHECK`]: struct.DecoderOptions.html#associatedconstant.NO_INVALID_CHECK |
651 | | /// |
652 | | /// ``` |
653 | | /// use iced_x86::*; |
654 | | /// |
655 | | /// // lock add esi,ecx ; lock not allowed |
656 | | /// let bytes = b"\xF0\x01\xCE"; |
657 | | /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE); |
658 | | /// decoder.set_ip(0x1234_5678); |
659 | | /// let instr = decoder.decode(); |
660 | | /// assert_eq!(instr.code(), Code::INVALID); |
661 | | /// |
662 | | /// // We want to decode some instructions with invalid encodings |
663 | | /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NO_INVALID_CHECK); |
664 | | /// decoder.set_ip(0x1234_5678); |
665 | | /// let instr = decoder.decode(); |
666 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
667 | | /// assert!(instr.has_lock_prefix()); |
668 | | /// ``` |
669 | | #[must_use] |
670 | | #[inline] |
671 | | #[allow(clippy::unwrap_used)] |
672 | 2.01k | pub fn new(bitness: u32, data: &'a [u8], options: u32) -> Decoder<'a> { |
673 | 2.01k | Decoder::try_new(bitness, data, options).unwrap() |
674 | 2.01k | } <iced_x86::decoder::Decoder>::new Line | Count | Source | 672 | 2.01k | pub fn new(bitness: u32, data: &'a [u8], options: u32) -> Decoder<'a> { | 673 | 2.01k | Decoder::try_new(bitness, data, options).unwrap() | 674 | 2.01k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::new |
675 | | |
676 | | /// Creates a decoder |
677 | | /// |
678 | | /// # Panics |
679 | | /// |
680 | | /// Panics if `bitness` is not one of 16, 32, 64. |
681 | | /// |
682 | | /// # Arguments |
683 | | /// |
684 | | /// * `bitness`: 16, 32 or 64 |
685 | | /// * `data`: Data to decode |
686 | | /// * `ip`: `RIP` value |
687 | | /// * `options`: Decoder options, `0` or eg. `DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD` |
688 | | /// |
689 | | /// # Examples |
690 | | /// |
691 | | /// ``` |
692 | | /// use iced_x86::*; |
693 | | /// |
694 | | /// // xchg ah,[rdx+rsi+16h] |
695 | | /// // xacquire lock add dword ptr [rax],5Ah |
696 | | /// // vmovdqu64 zmm18{k3}{z},zmm11 |
697 | | /// let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3"; |
698 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
699 | | /// |
700 | | /// let instr1 = decoder.decode(); |
701 | | /// assert_eq!(instr1.code(), Code::Xchg_rm8_r8); |
702 | | /// assert_eq!(instr1.mnemonic(), Mnemonic::Xchg); |
703 | | /// assert_eq!(instr1.len(), 4); |
704 | | /// |
705 | | /// let instr2 = decoder.decode(); |
706 | | /// assert_eq!(instr2.code(), Code::Add_rm32_imm8); |
707 | | /// assert_eq!(instr2.mnemonic(), Mnemonic::Add); |
708 | | /// assert_eq!(instr2.len(), 5); |
709 | | /// |
710 | | /// let instr3 = decoder.decode(); |
711 | | /// assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512); |
712 | | /// assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64); |
713 | | /// assert_eq!(instr3.len(), 6); |
714 | | /// ``` |
715 | | /// |
716 | | /// It's sometimes useful to decode some invalid instructions, eg. `lock add esi,ecx`. |
717 | | /// Pass in [`DecoderOptions::NO_INVALID_CHECK`] to the constructor and the decoder |
718 | | /// will decode some invalid encodings. |
719 | | /// |
720 | | /// [`DecoderOptions::NO_INVALID_CHECK`]: struct.DecoderOptions.html#associatedconstant.NO_INVALID_CHECK |
721 | | /// |
722 | | /// ``` |
723 | | /// use iced_x86::*; |
724 | | /// |
725 | | /// // lock add esi,ecx ; lock not allowed |
726 | | /// let bytes = b"\xF0\x01\xCE"; |
727 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
728 | | /// let instr = decoder.decode(); |
729 | | /// assert_eq!(instr.code(), Code::INVALID); |
730 | | /// |
731 | | /// // We want to decode some instructions with invalid encodings |
732 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NO_INVALID_CHECK); |
733 | | /// let instr = decoder.decode(); |
734 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
735 | | /// assert!(instr.has_lock_prefix()); |
736 | | /// ``` |
737 | | #[must_use] |
738 | | #[inline] |
739 | | #[allow(clippy::unwrap_used)] |
740 | 0 | pub fn with_ip(bitness: u32, data: &'a [u8], ip: u64, options: u32) -> Decoder<'a> { |
741 | 0 | Decoder::try_with_ip(bitness, data, ip, options).unwrap() |
742 | 0 | } |
743 | | |
744 | | /// Creates a decoder |
745 | | /// |
746 | | /// # Errors |
747 | | /// |
748 | | /// Fails if `bitness` is not one of 16, 32, 64. |
749 | | /// |
750 | | /// # Arguments |
751 | | /// |
752 | | /// * `bitness`: 16, 32 or 64 |
753 | | /// * `data`: Data to decode |
754 | | /// * `options`: Decoder options, `0` or eg. `DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD` |
755 | | /// |
756 | | /// # Examples |
757 | | /// |
758 | | /// ``` |
759 | | /// use iced_x86::*; |
760 | | /// |
761 | | /// // xchg ah,[rdx+rsi+16h] |
762 | | /// // xacquire lock add dword ptr [rax],5Ah |
763 | | /// // vmovdqu64 zmm18{k3}{z},zmm11 |
764 | | /// let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3"; |
765 | | /// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap(); |
766 | | /// decoder.set_ip(0x1234_5678); |
767 | | /// |
768 | | /// let instr1 = decoder.decode(); |
769 | | /// assert_eq!(instr1.code(), Code::Xchg_rm8_r8); |
770 | | /// assert_eq!(instr1.mnemonic(), Mnemonic::Xchg); |
771 | | /// assert_eq!(instr1.len(), 4); |
772 | | /// |
773 | | /// let instr2 = decoder.decode(); |
774 | | /// assert_eq!(instr2.code(), Code::Add_rm32_imm8); |
775 | | /// assert_eq!(instr2.mnemonic(), Mnemonic::Add); |
776 | | /// assert_eq!(instr2.len(), 5); |
777 | | /// |
778 | | /// let instr3 = decoder.decode(); |
779 | | /// assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512); |
780 | | /// assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64); |
781 | | /// assert_eq!(instr3.len(), 6); |
782 | | /// ``` |
783 | | /// |
784 | | /// It's sometimes useful to decode some invalid instructions, eg. `lock add esi,ecx`. |
785 | | /// Pass in [`DecoderOptions::NO_INVALID_CHECK`] to the constructor and the decoder |
786 | | /// will decode some invalid encodings. |
787 | | /// |
788 | | /// [`DecoderOptions::NO_INVALID_CHECK`]: struct.DecoderOptions.html#associatedconstant.NO_INVALID_CHECK |
789 | | /// |
790 | | /// ``` |
791 | | /// use iced_x86::*; |
792 | | /// |
793 | | /// // lock add esi,ecx ; lock not allowed |
794 | | /// let bytes = b"\xF0\x01\xCE"; |
795 | | /// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NONE).unwrap(); |
796 | | /// decoder.set_ip(0x1234_5678); |
797 | | /// let instr = decoder.decode(); |
798 | | /// assert_eq!(instr.code(), Code::INVALID); |
799 | | /// |
800 | | /// // We want to decode some instructions with invalid encodings |
801 | | /// let mut decoder = Decoder::try_new(64, bytes, DecoderOptions::NO_INVALID_CHECK).unwrap(); |
802 | | /// decoder.set_ip(0x1234_5678); |
803 | | /// let instr = decoder.decode(); |
804 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
805 | | /// assert!(instr.has_lock_prefix()); |
806 | | /// ``` |
807 | | #[inline] |
808 | 2.01k | pub fn try_new(bitness: u32, data: &'a [u8], options: u32) -> Result<Decoder<'a>, IcedError> { |
809 | 2.01k | Decoder::try_with_ip(bitness, data, 0, options) |
810 | 2.01k | } <iced_x86::decoder::Decoder>::try_new Line | Count | Source | 808 | 2.01k | pub fn try_new(bitness: u32, data: &'a [u8], options: u32) -> Result<Decoder<'a>, IcedError> { | 809 | 2.01k | Decoder::try_with_ip(bitness, data, 0, options) | 810 | 2.01k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::try_new |
811 | | |
812 | | /// Creates a decoder |
813 | | /// |
814 | | /// # Errors |
815 | | /// |
816 | | /// Fails if `bitness` is not one of 16, 32, 64. |
817 | | /// |
818 | | /// # Arguments |
819 | | /// |
820 | | /// * `bitness`: 16, 32 or 64 |
821 | | /// * `data`: Data to decode |
822 | | /// * `ip`: `RIP` value |
823 | | /// * `options`: Decoder options, `0` or eg. `DecoderOptions::NO_INVALID_CHECK | DecoderOptions::AMD` |
824 | | /// |
825 | | /// # Examples |
826 | | /// |
827 | | /// ``` |
828 | | /// use iced_x86::*; |
829 | | /// |
830 | | /// // xchg ah,[rdx+rsi+16h] |
831 | | /// // xacquire lock add dword ptr [rax],5Ah |
832 | | /// // vmovdqu64 zmm18{k3}{z},zmm11 |
833 | | /// let bytes = b"\x86\x64\x32\x16\xF0\xF2\x83\x00\x5A\x62\xC1\xFE\xCB\x6F\xD3"; |
834 | | /// let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE).unwrap(); |
835 | | /// |
836 | | /// let instr1 = decoder.decode(); |
837 | | /// assert_eq!(instr1.code(), Code::Xchg_rm8_r8); |
838 | | /// assert_eq!(instr1.mnemonic(), Mnemonic::Xchg); |
839 | | /// assert_eq!(instr1.len(), 4); |
840 | | /// |
841 | | /// let instr2 = decoder.decode(); |
842 | | /// assert_eq!(instr2.code(), Code::Add_rm32_imm8); |
843 | | /// assert_eq!(instr2.mnemonic(), Mnemonic::Add); |
844 | | /// assert_eq!(instr2.len(), 5); |
845 | | /// |
846 | | /// let instr3 = decoder.decode(); |
847 | | /// assert_eq!(instr3.code(), Code::EVEX_Vmovdqu64_zmm_k1z_zmmm512); |
848 | | /// assert_eq!(instr3.mnemonic(), Mnemonic::Vmovdqu64); |
849 | | /// assert_eq!(instr3.len(), 6); |
850 | | /// ``` |
851 | | /// |
852 | | /// It's sometimes useful to decode some invalid instructions, eg. `lock add esi,ecx`. |
853 | | /// Pass in [`DecoderOptions::NO_INVALID_CHECK`] to the constructor and the decoder |
854 | | /// will decode some invalid encodings. |
855 | | /// |
856 | | /// [`DecoderOptions::NO_INVALID_CHECK`]: struct.DecoderOptions.html#associatedconstant.NO_INVALID_CHECK |
857 | | /// |
858 | | /// ``` |
859 | | /// use iced_x86::*; |
860 | | /// |
861 | | /// // lock add esi,ecx ; lock not allowed |
862 | | /// let bytes = b"\xF0\x01\xCE"; |
863 | | /// let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE).unwrap(); |
864 | | /// let instr = decoder.decode(); |
865 | | /// assert_eq!(instr.code(), Code::INVALID); |
866 | | /// |
867 | | /// // We want to decode some instructions with invalid encodings |
868 | | /// let mut decoder = Decoder::try_with_ip(64, bytes, 0x1234_5678, DecoderOptions::NO_INVALID_CHECK).unwrap(); |
869 | | /// let instr = decoder.decode(); |
870 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
871 | | /// assert!(instr.has_lock_prefix()); |
872 | | /// ``` |
873 | | #[allow(clippy::missing_inline_in_public_items)] |
874 | | #[allow(clippy::let_unit_value)] |
875 | | #[allow(trivial_casts)] |
876 | 2.01k | pub fn try_with_ip(bitness: u32, data: &'a [u8], ip: u64, options: u32) -> Result<Decoder<'a>, IcedError> { |
877 | | let is64b_mode; |
878 | | let default_code_size; |
879 | | let default_operand_size; |
880 | | let default_inverted_operand_size; |
881 | | let default_address_size; |
882 | | let default_inverted_address_size; |
883 | 2.01k | match bitness { |
884 | 2.01k | 64 => { |
885 | 2.01k | is64b_mode = true; |
886 | 2.01k | default_code_size = CodeSize::Code64; |
887 | 2.01k | default_operand_size = OpSize::Size32; |
888 | 2.01k | default_inverted_operand_size = OpSize::Size16; |
889 | 2.01k | default_address_size = OpSize::Size64; |
890 | 2.01k | default_inverted_address_size = OpSize::Size32; |
891 | 2.01k | } |
892 | 0 | 32 => { |
893 | 0 | is64b_mode = false; |
894 | 0 | default_code_size = CodeSize::Code32; |
895 | 0 | default_operand_size = OpSize::Size32; |
896 | 0 | default_inverted_operand_size = OpSize::Size16; |
897 | 0 | default_address_size = OpSize::Size32; |
898 | 0 | default_inverted_address_size = OpSize::Size16; |
899 | 0 | } |
900 | 0 | 16 => { |
901 | 0 | is64b_mode = false; |
902 | 0 | default_code_size = CodeSize::Code16; |
903 | 0 | default_operand_size = OpSize::Size16; |
904 | 0 | default_inverted_operand_size = OpSize::Size32; |
905 | 0 | default_address_size = OpSize::Size16; |
906 | 0 | default_inverted_address_size = OpSize::Size32; |
907 | 0 | } |
908 | 0 | _ => return Err(IcedError::new("Invalid bitness")), |
909 | | } |
910 | 2.01k | let data_ptr_end = data.as_ptr() as usize + data.len(); |
911 | 2.01k | if data_ptr_end < data.as_ptr() as usize || { |
912 | | // Verify that max_data_ptr can never overflow and that data_ptr.add(N) can't overflow. |
913 | | // Both of them can equal data_ptr_end (1 byte past the last valid byte). |
914 | | // When reading a u8/u16/u32..., we calculate data_ptr.add({1,2,4,...MAX_READ_SIZE}) so it must not overflow. |
915 | | // In decode(), we calculate data_ptr.add(MAX_INSTRUCTION_LENGTH) so it must not overflow. |
916 | 2.01k | data_ptr_end.wrapping_add(cmp::max(IcedConstants::MAX_INSTRUCTION_LENGTH, Decoder::MAX_READ_SIZE)) < data.as_ptr() as usize |
917 | | } { |
918 | 0 | return Err(IcedError::new("Invalid slice")); |
919 | 2.01k | } |
920 | | |
921 | 2.01k | let tables = &*TABLES; |
922 | | |
923 | | #[allow(clippy::unwrap_used)] |
924 | 2.01k | fn get_handlers( |
925 | 2.01k | handlers: &'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler)], |
926 | 2.01k | ) -> &'static [(OpCodeHandlerDecodeFn, &'static OpCodeHandler); 0x100] { |
927 | 2.01k | debug_assert_eq!(handlers.len(), 0x100); |
928 | 2.01k | TryFrom::try_from(handlers).unwrap() |
929 | 2.01k | } |
930 | | macro_rules! mk_handlers_local { |
931 | | ($name:ident, $feature:literal) => { |
932 | | mk_handlers_local!($name, $name, $feature); |
933 | | }; |
934 | | ($name:ident, $field_name:ident, $feature:literal) => { |
935 | | #[cfg(not(feature = $feature))] |
936 | | let $name = get_handlers(&tables.$field_name); |
937 | | #[cfg(feature = $feature)] |
938 | | let $name = (); |
939 | | }; |
940 | | ($name:ident ; $feature:literal) => { |
941 | | mk_handlers_local!($name, $name ; $feature); |
942 | | }; |
943 | | ($name:ident, $field_name:ident ; $feature:literal) => { |
944 | | #[cfg(feature = $feature)] |
945 | | let $name = get_handlers(&tables.$field_name); |
946 | | #[cfg(not(feature = $feature))] |
947 | | let $name = (); |
948 | | }; |
949 | | } |
950 | | #[cfg(all(not(feature = "no_vex"), feature = "mvex"))] |
951 | | let handlers_vex_map0 = get_handlers(&tables.handlers_vex_map0); |
952 | | #[cfg(not(all(not(feature = "no_vex"), feature = "mvex")))] |
953 | 2.01k | let handlers_vex_map0 = (); |
954 | 2.01k | mk_handlers_local!(handlers_vex_0f, "no_vex"); |
955 | 2.01k | mk_handlers_local!(handlers_vex_0f38, "no_vex"); |
956 | 2.01k | mk_handlers_local!(handlers_vex_0f3a, "no_vex"); |
957 | 2.01k | mk_handlers_local!(handlers_evex_0f, "no_evex"); |
958 | 2.01k | mk_handlers_local!(handlers_evex_0f38, "no_evex"); |
959 | 2.01k | mk_handlers_local!(handlers_evex_0f3a, "no_evex"); |
960 | 2.01k | mk_handlers_local!(handlers_evex_map4, invalid_map, "no_evex"); |
961 | 2.01k | mk_handlers_local!(handlers_evex_map5, "no_evex"); |
962 | 2.01k | mk_handlers_local!(handlers_evex_map6, "no_evex"); |
963 | 2.01k | mk_handlers_local!(handlers_xop_map8, "no_xop"); |
964 | 2.01k | mk_handlers_local!(handlers_xop_map9, "no_xop"); |
965 | 2.01k | mk_handlers_local!(handlers_xop_map10, "no_xop"); |
966 | 2.01k | mk_handlers_local!(handlers_mvex_0f ; "mvex"); |
967 | 2.01k | mk_handlers_local!(handlers_mvex_0f38 ; "mvex"); |
968 | 2.01k | mk_handlers_local!(handlers_mvex_0f3a ; "mvex"); |
969 | | |
970 | | #[rustfmt::skip] |
971 | | #[cfg(not(feature = "__internal_flip"))] |
972 | 2.01k | let read_op_mem_fns = [ |
973 | 2.01k | Decoder::read_op_mem_0, |
974 | 2.01k | Decoder::read_op_mem_0, |
975 | 2.01k | Decoder::read_op_mem_0, |
976 | 2.01k | Decoder::read_op_mem_0, |
977 | 2.01k | Decoder::read_op_mem_0_4, |
978 | 2.01k | Decoder::read_op_mem_0_5, |
979 | 2.01k | Decoder::read_op_mem_0, |
980 | 2.01k | Decoder::read_op_mem_0, |
981 | 2.01k | |
982 | 2.01k | Decoder::read_op_mem_1, |
983 | 2.01k | Decoder::read_op_mem_1, |
984 | 2.01k | Decoder::read_op_mem_1, |
985 | 2.01k | Decoder::read_op_mem_1, |
986 | 2.01k | Decoder::read_op_mem_1_4, |
987 | 2.01k | Decoder::read_op_mem_1, |
988 | 2.01k | Decoder::read_op_mem_1, |
989 | 2.01k | Decoder::read_op_mem_1, |
990 | 2.01k | |
991 | 2.01k | Decoder::read_op_mem_2, |
992 | 2.01k | Decoder::read_op_mem_2, |
993 | 2.01k | Decoder::read_op_mem_2, |
994 | 2.01k | Decoder::read_op_mem_2, |
995 | 2.01k | Decoder::read_op_mem_2_4, |
996 | 2.01k | Decoder::read_op_mem_2, |
997 | 2.01k | Decoder::read_op_mem_2, |
998 | 2.01k | Decoder::read_op_mem_2, |
999 | 2.01k | ]; |
1000 | | #[cfg(feature = "__internal_flip")] |
1001 | | let read_op_mem_fns = (); |
1002 | | |
1003 | | Ok(Decoder { |
1004 | 2.01k | ip, |
1005 | 2.01k | data_ptr: data.as_ptr() as usize, |
1006 | 2.01k | data_ptr_end, |
1007 | 2.01k | max_data_ptr: data.as_ptr() as usize, |
1008 | 2.01k | instr_start_data_ptr: data.as_ptr() as usize, |
1009 | 2.01k | handlers_map0: get_handlers(&tables.handlers_map0), |
1010 | 2.01k | handlers_vex_map0, |
1011 | 2.01k | handlers_vex: [handlers_vex_0f, handlers_vex_0f38, handlers_vex_0f3a], |
1012 | 2.01k | handlers_evex: [handlers_evex_0f, handlers_evex_0f38, handlers_evex_0f3a, handlers_evex_map4, handlers_evex_map5, handlers_evex_map6], |
1013 | 2.01k | handlers_xop: [handlers_xop_map8, handlers_xop_map9, handlers_xop_map10], |
1014 | 2.01k | handlers_mvex: [handlers_mvex_0f, handlers_mvex_0f38, handlers_mvex_0f3a], |
1015 | 2.01k | read_op_mem_fns, |
1016 | 2.01k | state: State::default(), |
1017 | 2.01k | options, |
1018 | 2.01k | invalid_check_mask: if (options & DecoderOptions::NO_INVALID_CHECK) == 0 { u32::MAX } else { 0 }, |
1019 | 2.01k | is64b_mode_and_w: if is64b_mode { StateFlags::W } else { 0 }, |
1020 | 2.01k | reg15_mask: if is64b_mode { 0xF } else { 0x7 }, |
1021 | 2.01k | mask_e0: if is64b_mode { 0xE0 } else { 0 }, |
1022 | 2.01k | rex_mask: if is64b_mode { 0xF0 } else { 0 }, |
1023 | 2.01k | bitness, |
1024 | 2.01k | default_address_size, |
1025 | 2.01k | default_operand_size, |
1026 | | segment_prio: 0, |
1027 | | dummy: 0, |
1028 | 2.01k | default_inverted_address_size, |
1029 | 2.01k | default_inverted_operand_size, |
1030 | 2.01k | is64b_mode, |
1031 | 2.01k | default_code_size, |
1032 | | displ_index: 0, |
1033 | 2.01k | data, |
1034 | | }) |
1035 | 2.01k | } |
1036 | | |
1037 | | /// Gets the current `IP`/`EIP`/`RIP` value, see also [`position()`] |
1038 | | /// |
1039 | | /// [`position()`]: #method.position |
1040 | | #[must_use] |
1041 | | #[inline] |
1042 | 1.86k | pub const fn ip(&self) -> u64 { |
1043 | 1.86k | self.ip |
1044 | 1.86k | } <iced_x86::decoder::Decoder>::ip Line | Count | Source | 1042 | 1.86k | pub const fn ip(&self) -> u64 { | 1043 | 1.86k | self.ip | 1044 | 1.86k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::ip |
1045 | | |
1046 | | /// Sets the current `IP`/`EIP`/`RIP` value, see also [`try_set_position()`] |
1047 | | /// |
1048 | | /// This method only updates the IP value, it does not change the data position, use [`try_set_position()`] to change the position. |
1049 | | /// |
1050 | | /// [`try_set_position()`]: #method.try_set_position |
1051 | | /// |
1052 | | /// # Arguments |
1053 | | /// |
1054 | | /// * `new_value`: New IP |
1055 | | #[inline] |
1056 | 2.01k | pub fn set_ip(&mut self, new_value: u64) { |
1057 | 2.01k | self.ip = new_value; |
1058 | 2.01k | } <iced_x86::decoder::Decoder>::set_ip Line | Count | Source | 1056 | 2.01k | pub fn set_ip(&mut self, new_value: u64) { | 1057 | 2.01k | self.ip = new_value; | 1058 | 2.01k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::set_ip |
1059 | | |
1060 | | /// Gets the bitness (16, 32 or 64) |
1061 | | #[must_use] |
1062 | | #[inline] |
1063 | 0 | pub const fn bitness(&self) -> u32 { |
1064 | 0 | self.bitness |
1065 | 0 | } |
1066 | | |
1067 | | /// Gets the max value that can be passed to [`try_set_position()`]. This is the size of the data that gets |
1068 | | /// decoded to instructions and it's the length of the slice that was passed to the constructor. |
1069 | | /// |
1070 | | /// [`try_set_position()`]: #method.try_set_position |
1071 | | #[must_use] |
1072 | | #[inline] |
1073 | 0 | pub const fn max_position(&self) -> usize { |
1074 | 0 | self.data.len() |
1075 | 0 | } |
1076 | | |
1077 | | /// Gets the current data position. This value is always <= [`max_position()`]. |
1078 | | /// When [`position()`] == [`max_position()`], it's not possible to decode more |
1079 | | /// instructions and [`can_decode()`] returns `false`. |
1080 | | /// |
1081 | | /// [`max_position()`]: #method.max_position |
1082 | | /// [`position()`]: #method.position |
1083 | | /// [`can_decode()`]: #method.can_decode |
1084 | | #[must_use] |
1085 | | #[inline] |
1086 | 0 | pub fn position(&self) -> usize { |
1087 | 0 | self.data_ptr - self.data.as_ptr() as usize |
1088 | 0 | } |
1089 | | |
1090 | | /// Sets the current data position, which is the index into the data passed to the constructor. |
1091 | | /// This value is always <= [`max_position()`] |
1092 | | /// |
1093 | | /// [`max_position()`]: #method.max_position |
1094 | | /// |
1095 | | /// # Errors |
1096 | | /// |
1097 | | /// Fails if the new position is invalid. |
1098 | | /// |
1099 | | /// # Arguments |
1100 | | /// |
1101 | | /// * `new_pos`: New position and must be <= [`max_position()`] |
1102 | | /// |
1103 | | /// # Examples |
1104 | | /// |
1105 | | /// ``` |
1106 | | /// use iced_x86::*; |
1107 | | /// |
1108 | | /// // nop and pause |
1109 | | /// let bytes = b"\x90\xF3\x90"; |
1110 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1111 | | /// |
1112 | | /// assert_eq!(decoder.position(), 0); |
1113 | | /// assert_eq!(decoder.max_position(), 3); |
1114 | | /// let instr = decoder.decode(); |
1115 | | /// assert_eq!(decoder.position(), 1); |
1116 | | /// assert_eq!(instr.code(), Code::Nopd); |
1117 | | /// |
1118 | | /// let instr = decoder.decode(); |
1119 | | /// assert_eq!(decoder.position(), 3); |
1120 | | /// assert_eq!(instr.code(), Code::Pause); |
1121 | | /// |
1122 | | /// // Start all over again |
1123 | | /// decoder.set_position(0).unwrap(); |
1124 | | /// decoder.set_ip(0x1234_5678); |
1125 | | /// assert_eq!(decoder.position(), 0); |
1126 | | /// assert_eq!(decoder.decode().code(), Code::Nopd); |
1127 | | /// assert_eq!(decoder.decode().code(), Code::Pause); |
1128 | | /// assert_eq!(decoder.position(), 3); |
1129 | | /// ``` |
1130 | | #[inline] |
1131 | | #[allow(clippy::missing_inline_in_public_items)] |
1132 | 0 | pub fn set_position(&mut self, new_pos: usize) -> Result<(), IcedError> { |
1133 | 0 | if new_pos > self.data.len() { |
1134 | 0 | Err(IcedError::new("Invalid position")) |
1135 | | } else { |
1136 | | // - We verified the new offset above. |
1137 | | // - Referencing 1 byte past the last valid byte is safe as long as we don't dereference it. |
1138 | 0 | self.data_ptr = self.data.as_ptr() as usize + new_pos; |
1139 | 0 | Ok(()) |
1140 | | } |
1141 | 0 | } |
1142 | | |
1143 | | #[doc(hidden)] |
1144 | | #[inline] |
1145 | 0 | pub fn try_set_position(&mut self, new_pos: usize) -> Result<(), IcedError> { |
1146 | 0 | self.set_position(new_pos) |
1147 | 0 | } |
1148 | | |
1149 | | /// Returns `true` if there's at least one more byte to decode. It doesn't verify that the |
1150 | | /// next instruction is valid, it only checks if there's at least one more byte to read. |
1151 | | /// See also [`position()`] and [`max_position()`] |
1152 | | /// |
1153 | | /// It's not required to call this method. If this method returns `false`, then [`decode_out()`] |
1154 | | /// and [`decode()`] will return an instruction whose [`code()`] == [`Code::INVALID`]. |
1155 | | /// |
1156 | | /// [`position()`]: #method.position |
1157 | | /// [`max_position()`]: #method.max_position |
1158 | | /// [`decode_out()`]: #method.decode_out |
1159 | | /// [`decode()`]: #method.decode |
1160 | | /// [`code()`]: struct.Instruction.html#method.code |
1161 | | /// [`Code::INVALID`]: enum.Code.html#variant.INVALID |
1162 | | /// |
1163 | | /// # Examples |
1164 | | /// |
1165 | | /// ``` |
1166 | | /// use iced_x86::*; |
1167 | | /// |
1168 | | /// // nop and an incomplete instruction |
1169 | | /// let bytes = b"\x90\xF3\x0F"; |
1170 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1171 | | /// |
1172 | | /// // 3 bytes left to read |
1173 | | /// assert!(decoder.can_decode()); |
1174 | | /// let instr = decoder.decode(); |
1175 | | /// assert_eq!(instr.code(), Code::Nopd); |
1176 | | /// |
1177 | | /// // 2 bytes left to read |
1178 | | /// assert!(decoder.can_decode()); |
1179 | | /// let instr = decoder.decode(); |
1180 | | /// // Not enough bytes left to decode a full instruction |
1181 | | /// assert_eq!(instr.code(), Code::INVALID); |
1182 | | /// |
1183 | | /// // 0 bytes left to read |
1184 | | /// assert!(!decoder.can_decode()); |
1185 | | /// ``` |
1186 | | #[must_use] |
1187 | | #[inline] |
1188 | | #[allow(clippy::missing_const_for_fn)] |
1189 | 0 | pub fn can_decode(&self) -> bool { |
1190 | 0 | self.data_ptr != self.data_ptr_end |
1191 | 0 | } |
1192 | | |
1193 | | /// Returns an iterator that borrows this instance to decode instructions until there's |
1194 | | /// no more data to decode, i.e., until [`can_decode()`] returns `false`. |
1195 | | /// |
1196 | | /// [`can_decode()`]: #method.can_decode |
1197 | | /// |
1198 | | /// # Examples |
1199 | | /// |
1200 | | /// ``` |
1201 | | /// use iced_x86::*; |
1202 | | /// |
1203 | | /// // nop and pause |
1204 | | /// let bytes = b"\x90\xF3\x90"; |
1205 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1206 | | /// |
1207 | | /// let mut iter = decoder.iter(); |
1208 | | /// assert_eq!(iter.next().unwrap().code(), Code::Nopd); |
1209 | | /// assert_eq!(iter.next().unwrap().code(), Code::Pause); |
1210 | | /// assert!(iter.next().is_none()); |
1211 | | /// ``` |
1212 | | /// |
1213 | | /// `for` loop: |
1214 | | /// |
1215 | | /// ``` |
1216 | | /// use iced_x86::*; |
1217 | | /// |
1218 | | /// let bytes = b"\x90\xF3\x90"; |
1219 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1220 | | /// |
1221 | | /// for instr in &mut decoder { // or decoder.iter() |
1222 | | /// println!("code: {:?}", instr.code()); |
1223 | | /// } |
1224 | | /// ``` |
1225 | | #[inline] |
1226 | 0 | pub fn iter<'b>(&'b mut self) -> DecoderIter<'a, 'b> { |
1227 | 0 | DecoderIter { decoder: self } |
1228 | 0 | } |
1229 | | |
1230 | | #[must_use] |
1231 | | #[inline(always)] |
1232 | 6.55k | fn read_u8(&mut self) -> usize { |
1233 | 6.55k | mk_read_xx_fn_body! {self, u8, u8::from_le, usize} |
1234 | 6.55k | } |
1235 | | |
1236 | | #[must_use] |
1237 | | #[inline(always)] |
1238 | 58 | fn read_u16(&mut self) -> usize { |
1239 | 58 | mk_read_xx_fn_body! {self, u16, u16::from_le, usize} |
1240 | 58 | } |
1241 | | |
1242 | | #[must_use] |
1243 | | #[inline(always)] |
1244 | 119 | fn read_u32(&mut self) -> usize { |
1245 | 119 | mk_read_xx_fn_body! {self, u32, u32::from_le, usize} |
1246 | 119 | } |
1247 | | |
1248 | | #[must_use] |
1249 | | #[inline(always)] |
1250 | 76 | fn read_u64(&mut self) -> u64 { |
1251 | 76 | mk_read_xx_fn_body! {self, u64, u64::from_le, u64} |
1252 | 76 | } |
1253 | | |
1254 | | /// Gets the last decoder error. Unless you need to know the reason it failed, |
1255 | | /// it's better to check [`instruction.is_invalid()`]. |
1256 | | /// |
1257 | | /// [`instruction.is_invalid()`]: struct.Instruction.html#method.is_invalid |
1258 | | #[must_use] |
1259 | | #[inline] |
1260 | 2.01k | pub const fn last_error(&self) -> DecoderError { |
1261 | | // NoMoreBytes error has highest priority |
1262 | 2.01k | if (self.state.flags & StateFlags::NO_MORE_BYTES) != 0 { |
1263 | 0 | DecoderError::NoMoreBytes |
1264 | 2.01k | } else if (self.state.flags & StateFlags::IS_INVALID) != 0 { |
1265 | 215 | DecoderError::InvalidInstruction |
1266 | | } else { |
1267 | 1.79k | DecoderError::None |
1268 | | } |
1269 | 2.01k | } <iced_x86::decoder::Decoder>::last_error Line | Count | Source | 1260 | 2.01k | pub const fn last_error(&self) -> DecoderError { | 1261 | | // NoMoreBytes error has highest priority | 1262 | 2.01k | if (self.state.flags & StateFlags::NO_MORE_BYTES) != 0 { | 1263 | 0 | DecoderError::NoMoreBytes | 1264 | 2.01k | } else if (self.state.flags & StateFlags::IS_INVALID) != 0 { | 1265 | 215 | DecoderError::InvalidInstruction | 1266 | | } else { | 1267 | 1.79k | DecoderError::None | 1268 | | } | 1269 | 2.01k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::last_error |
1270 | | |
1271 | | /// Decodes and returns the next instruction, see also [`decode_out(&mut Instruction)`] |
1272 | | /// which avoids copying the decoded instruction to the caller's return variable. |
1273 | | /// See also [`last_error()`]. |
1274 | | /// |
1275 | | /// [`decode_out(&mut Instruction)`]: #method.decode_out |
1276 | | /// [`last_error()`]: #method.last_error |
1277 | | /// |
1278 | | /// # Examples |
1279 | | /// |
1280 | | /// ``` |
1281 | | /// use iced_x86::*; |
1282 | | /// |
1283 | | /// // xrelease lock add [rax],ebx |
1284 | | /// let bytes = b"\xF0\xF3\x01\x18"; |
1285 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1286 | | /// let instr = decoder.decode(); |
1287 | | /// |
1288 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
1289 | | /// assert_eq!(instr.mnemonic(), Mnemonic::Add); |
1290 | | /// assert_eq!(instr.len(), 4); |
1291 | | /// assert_eq!(instr.op_count(), 2); |
1292 | | /// |
1293 | | /// assert_eq!(instr.op0_kind(), OpKind::Memory); |
1294 | | /// assert_eq!(instr.memory_base(), Register::RAX); |
1295 | | /// assert_eq!(instr.memory_index(), Register::None); |
1296 | | /// assert_eq!(instr.memory_index_scale(), 1); |
1297 | | /// assert_eq!(instr.memory_displacement64(), 0); |
1298 | | /// assert_eq!(instr.memory_segment(), Register::DS); |
1299 | | /// assert_eq!(instr.segment_prefix(), Register::None); |
1300 | | /// assert_eq!(instr.memory_size(), MemorySize::UInt32); |
1301 | | /// |
1302 | | /// assert_eq!(instr.op1_kind(), OpKind::Register); |
1303 | | /// assert_eq!(instr.op1_register(), Register::EBX); |
1304 | | /// |
1305 | | /// assert!(instr.has_lock_prefix()); |
1306 | | /// assert!(instr.has_xrelease_prefix()); |
1307 | | /// ``` |
1308 | | #[must_use] |
1309 | | #[inline] |
1310 | 0 | pub fn decode(&mut self) -> Instruction { |
1311 | 0 | let mut instruction = mem::MaybeUninit::uninit(); |
1312 | | // SAFETY: decode_out_ptr() initializes the whole instruction (all fields) with valid values |
1313 | | unsafe { |
1314 | 0 | self.decode_out_ptr(instruction.as_mut_ptr()); |
1315 | 0 | instruction.assume_init() |
1316 | | } |
1317 | 0 | } |
1318 | | |
1319 | | /// Decodes the next instruction. The difference between this method and [`decode()`] is that this |
1320 | | /// method doesn't need to copy the result to the caller's return variable (saves 40 bytes of copying). |
1321 | | /// See also [`last_error()`]. |
1322 | | /// |
1323 | | /// [`decode()`]: #method.decode |
1324 | | /// [`last_error()`]: #method.last_error |
1325 | | /// |
1326 | | /// # Arguments |
1327 | | /// |
1328 | | /// * `instruction`: Updated with the decoded instruction. All fields are initialized (it's an `out` argument) |
1329 | | /// |
1330 | | /// # Examples |
1331 | | /// |
1332 | | /// ``` |
1333 | | /// use iced_x86::*; |
1334 | | /// |
1335 | | /// // xrelease lock add [rax],ebx |
1336 | | /// let bytes = b"\xF0\xF3\x01\x18"; |
1337 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
1338 | | /// let mut instr = Instruction::default(); |
1339 | | /// decoder.decode_out(&mut instr); |
1340 | | /// |
1341 | | /// assert_eq!(instr.code(), Code::Add_rm32_r32); |
1342 | | /// assert_eq!(instr.mnemonic(), Mnemonic::Add); |
1343 | | /// assert_eq!(instr.len(), 4); |
1344 | | /// assert_eq!(instr.op_count(), 2); |
1345 | | /// |
1346 | | /// assert_eq!(instr.op0_kind(), OpKind::Memory); |
1347 | | /// assert_eq!(instr.memory_base(), Register::RAX); |
1348 | | /// assert_eq!(instr.memory_index(), Register::None); |
1349 | | /// assert_eq!(instr.memory_index_scale(), 1); |
1350 | | /// assert_eq!(instr.memory_displacement64(), 0); |
1351 | | /// assert_eq!(instr.memory_segment(), Register::DS); |
1352 | | /// assert_eq!(instr.segment_prefix(), Register::None); |
1353 | | /// assert_eq!(instr.memory_size(), MemorySize::UInt32); |
1354 | | /// |
1355 | | /// assert_eq!(instr.op1_kind(), OpKind::Register); |
1356 | | /// assert_eq!(instr.op1_register(), Register::EBX); |
1357 | | /// |
1358 | | /// assert!(instr.has_lock_prefix()); |
1359 | | /// assert!(instr.has_xrelease_prefix()); |
1360 | | /// ``` |
1361 | | #[inline] |
1362 | 2.01k | pub fn decode_out(&mut self, instruction: &mut Instruction) { |
1363 | 2.01k | unsafe { |
1364 | 2.01k | self.decode_out_ptr(instruction); |
1365 | 2.01k | } |
1366 | 2.01k | } <iced_x86::decoder::Decoder>::decode_out Line | Count | Source | 1362 | 2.01k | pub fn decode_out(&mut self, instruction: &mut Instruction) { | 1363 | 2.01k | unsafe { | 1364 | 2.01k | self.decode_out_ptr(instruction); | 1365 | 2.01k | } | 1366 | 2.01k | } |
Unexecuted instantiation: <iced_x86::decoder::Decoder>::decode_out |
1367 | | |
1368 | | // SAFETY: `instruction` must be non-null, writable and aligned (`ptr::write()`) and not aliased |
1369 | | #[allow(clippy::useless_let_if_seq)] |
1370 | 2.01k | unsafe fn decode_out_ptr(&mut self, instruction: *mut Instruction) { |
1371 | | // SAFETY: |
1372 | | // - the instruction has only primitive integer types, nothing needs to be dropped |
1373 | | // - private method: no caller passes in a null ptr, a non-writable ptr or an unaligned ptr |
1374 | 2.01k | unsafe { ptr::write(instruction, Instruction::default()) }; |
1375 | | // SAFETY: private method: the only callers pass in their `&mut arg` or their own stack-allocated `MaybeUninit` instruction |
1376 | 2.01k | let instruction = unsafe { &mut *instruction }; |
1377 | | |
1378 | 2.01k | self.state.extra_register_base = 0; |
1379 | 2.01k | self.state.extra_index_register_base = 0; |
1380 | 2.01k | self.state.extra_base_register_base = 0; |
1381 | 2.01k | self.state.extra_index_register_base_vsib = 0; |
1382 | 2.01k | self.state.flags = 0; |
1383 | 2.01k | self.state.mandatory_prefix = DecoderMandatoryPrefix::default(); |
1384 | | // These don't need to be cleared, but they're here so the compiler can re-use the |
1385 | | // same XMM reg to clear the previous 2 u32s (including these 2 u32s). |
1386 | 2.01k | self.state.vvvv = 0; |
1387 | 2.01k | self.state.vvvv_invalid_check = 0; |
1388 | | |
1389 | | // We only need to write addr/op size fields and init segment_prio to 0. |
1390 | | // The fields are consecutive so the compiler can read all 4 fields (including dummy) |
1391 | | // and write all 4 fields at the same time. |
1392 | 2.01k | self.state.address_size = self.default_address_size; |
1393 | 2.01k | self.state.operand_size = self.default_operand_size; |
1394 | 2.01k | self.state.segment_prio = self.segment_prio; |
1395 | 2.01k | self.state.dummy = self.dummy; |
1396 | | |
1397 | 2.01k | let data_ptr = self.data_ptr; |
1398 | 2.01k | self.instr_start_data_ptr = data_ptr; |
1399 | | // The ctor has verified that the two expressions used in min() don't overflow and are >= data_ptr. |
1400 | | // The calculated usize is a valid pointer in `self.data` slice or at most 1 byte past the last valid byte. |
1401 | 2.01k | self.max_data_ptr = cmp::min(data_ptr + IcedConstants::MAX_INSTRUCTION_LENGTH, self.data_ptr_end); |
1402 | | |
1403 | 2.01k | let b = self.read_u8(); |
1404 | 2.01k | let mut handler = self.handlers_map0[b]; |
1405 | 2.01k | if ((b as u32) & self.rex_mask) == 0x40 { |
1406 | 389 | debug_assert!(self.is64b_mode); |
1407 | 389 | handler = self.handlers_map0[self.read_u8()]; |
1408 | 389 | let mut flags = self.state.flags | StateFlags::HAS_REX; |
1409 | 389 | if (b & 8) != 0 { |
1410 | 275 | flags |= StateFlags::W; |
1411 | 275 | self.state.operand_size = OpSize::Size64; |
1412 | 275 | } |
1413 | 389 | self.state.flags = flags; |
1414 | 389 | self.state.extra_register_base = (b as u32 & 4) << 1; |
1415 | 389 | self.state.extra_index_register_base = (b as u32 & 2) << 2; |
1416 | 389 | self.state.extra_base_register_base = (b as u32 & 1) << 3; |
1417 | 1.62k | } |
1418 | 2.01k | self.decode_table2(handler, instruction); |
1419 | | |
1420 | 2.01k | debug_assert_eq!(data_ptr, self.instr_start_data_ptr); |
1421 | 2.01k | let instr_len = self.data_ptr as u32 - data_ptr as u32; |
1422 | 2.01k | debug_assert!(instr_len <= IcedConstants::MAX_INSTRUCTION_LENGTH as u32); // Could be 0 if there were no bytes available |
1423 | 2.01k | instruction_internal::internal_set_len(instruction, instr_len); |
1424 | 2.01k | let orig_ip = self.ip; |
1425 | 2.01k | let ip = orig_ip.wrapping_add(instr_len as u64); |
1426 | 2.01k | self.ip = ip; |
1427 | 2.01k | instruction.set_next_ip(ip); |
1428 | 2.01k | instruction_internal::internal_set_code_size(instruction, self.default_code_size); |
1429 | | |
1430 | 2.01k | let mut flags = self.state.flags; |
1431 | 2.01k | if (flags & (StateFlags::IS_INVALID | StateFlags::LOCK | StateFlags::IP_REL64 | StateFlags::IP_REL32)) != 0 { |
1432 | 278 | let addr = ip.wrapping_add(instruction.memory_displacement64()); |
1433 | | // Assume it's IP_REL64 (very common if we're here). We'll undo this if it's not. |
1434 | 278 | instruction.set_memory_displacement64(addr); |
1435 | | // RIP rel ops are common, but invalid/lock bits are usually never set, so exit early if possible |
1436 | 278 | if (flags & (StateFlags::IP_REL64 | StateFlags::IS_INVALID | StateFlags::LOCK)) == StateFlags::IP_REL64 { |
1437 | 38 | return; |
1438 | 240 | } |
1439 | 240 | if (flags & StateFlags::IP_REL64) == 0 { |
1440 | 239 | // Undo what we did above |
1441 | 239 | instruction.set_memory_displacement64(addr.wrapping_sub(ip)); |
1442 | 239 | } |
1443 | 240 | if (flags & StateFlags::IP_REL32) != 0 { |
1444 | 3 | let addr = ip.wrapping_add(instruction.memory_displacement64()); |
1445 | 3 | instruction.set_memory_displacement64(addr as u32 as u64); |
1446 | 237 | } |
1447 | | |
1448 | 240 | if (flags & StateFlags::IS_INVALID) != 0 |
1449 | 56 | || (((flags & (StateFlags::LOCK | StateFlags::ALLOW_LOCK)) & self.invalid_check_mask) == StateFlags::LOCK) |
1450 | | { |
1451 | 215 | *instruction = Instruction::default(); |
1452 | | const _: () = assert!(Code::INVALID as u32 == 0); |
1453 | | //instruction.set_code(Code::INVALID); |
1454 | | |
1455 | 215 | if (flags & StateFlags::NO_MORE_BYTES) != 0 { |
1456 | 123 | debug_assert_eq!(data_ptr, self.instr_start_data_ptr); |
1457 | 123 | let max_len = self.data_ptr_end - data_ptr; |
1458 | | // If max-instr-len bytes is available, it's never no-more-bytes, and always invalid-instr |
1459 | 123 | if max_len >= IcedConstants::MAX_INSTRUCTION_LENGTH { |
1460 | 123 | flags &= !StateFlags::NO_MORE_BYTES; |
1461 | 123 | } |
1462 | | // max_data_ptr is in self.data slice or at most 1 byte past the last valid byte |
1463 | 123 | self.data_ptr = self.max_data_ptr; |
1464 | 92 | } |
1465 | | |
1466 | 215 | self.state.flags = flags | StateFlags::IS_INVALID; |
1467 | | |
1468 | 215 | let instr_len = self.data_ptr as u32 - data_ptr as u32; |
1469 | 215 | instruction_internal::internal_set_len(instruction, instr_len); |
1470 | 215 | let ip = orig_ip.wrapping_add(instr_len as u64); |
1471 | 215 | self.ip = ip; |
1472 | 215 | instruction.set_next_ip(ip); |
1473 | 215 | instruction_internal::internal_set_code_size(instruction, self.default_code_size); |
1474 | 25 | } |
1475 | 1.73k | } |
1476 | 2.01k | } |
1477 | | |
1478 | | #[inline(always)] |
1479 | 2.09k | fn reset_rex_prefix_state(&mut self) { |
1480 | 2.09k | self.state.flags &= !(StateFlags::HAS_REX | StateFlags::W); |
1481 | 2.09k | if (self.state.flags & StateFlags::HAS66) == 0 { |
1482 | 1.55k | self.state.operand_size = self.default_operand_size; |
1483 | 1.55k | } else { |
1484 | 546 | self.state.operand_size = self.default_inverted_operand_size; |
1485 | 546 | } |
1486 | 2.09k | self.state.extra_register_base = 0; |
1487 | 2.09k | self.state.extra_index_register_base = 0; |
1488 | 2.09k | self.state.extra_base_register_base = 0; |
1489 | 2.09k | } |
1490 | | |
1491 | | #[inline(always)] |
1492 | 2.89k | fn call_opcode_handlers_map0_table(&mut self, instruction: &mut Instruction) { |
1493 | 2.89k | let b = self.read_u8(); |
1494 | 2.89k | self.decode_table2(self.handlers_map0[b], instruction); |
1495 | 2.89k | } |
1496 | | |
1497 | | #[must_use] |
1498 | | #[inline] |
1499 | 0 | fn current_ip32(&self) -> u32 { |
1500 | 0 | debug_assert!(self.instr_start_data_ptr <= self.data_ptr); |
1501 | 0 | debug_assert!(self.data_ptr - self.instr_start_data_ptr <= IcedConstants::MAX_INSTRUCTION_LENGTH); |
1502 | 0 | ((self.data_ptr - self.instr_start_data_ptr) as u32).wrapping_add(self.ip as u32) |
1503 | 0 | } |
1504 | | |
1505 | | #[must_use] |
1506 | | #[inline] |
1507 | 29 | fn current_ip64(&self) -> u64 { |
1508 | 29 | debug_assert!(self.instr_start_data_ptr <= self.data_ptr); |
1509 | 29 | debug_assert!(self.data_ptr - self.instr_start_data_ptr <= IcedConstants::MAX_INSTRUCTION_LENGTH); |
1510 | 29 | ((self.data_ptr - self.instr_start_data_ptr) as u64).wrapping_add(self.ip) |
1511 | 29 | } |
1512 | | |
1513 | | #[inline] |
1514 | 98 | fn clear_mandatory_prefix(&mut self, instruction: &mut Instruction) { |
1515 | 98 | debug_assert_eq!(self.state.encoding(), EncodingKind::Legacy as u32); |
1516 | 98 | instruction_internal::internal_clear_has_repe_repne_prefix(instruction); |
1517 | 98 | } |
1518 | | |
1519 | | #[inline(always)] |
1520 | 2 | fn set_xacquire_xrelease(&mut self, instruction: &mut Instruction, flags: u32) { |
1521 | 2 | if instruction.has_lock_prefix() { |
1522 | 0 | self.set_xacquire_xrelease_core(instruction, flags); |
1523 | 2 | } |
1524 | 2 | } |
1525 | | |
1526 | | #[allow(clippy::nonminimal_bool)] |
1527 | 0 | fn set_xacquire_xrelease_core(&mut self, instruction: &mut Instruction, flags: u32) { |
1528 | 0 | debug_assert!(!((flags & HandlerFlags::XACQUIRE_XRELEASE_NO_LOCK) == 0 && !instruction.has_lock_prefix())); |
1529 | 0 | match self.state.mandatory_prefix { |
1530 | 0 | DecoderMandatoryPrefix::PF2 => { |
1531 | 0 | self.clear_mandatory_prefix_f2(instruction); |
1532 | 0 | instruction.set_has_xacquire_prefix(true); |
1533 | 0 | } |
1534 | 0 | DecoderMandatoryPrefix::PF3 => { |
1535 | 0 | self.clear_mandatory_prefix_f3(instruction); |
1536 | 0 | instruction.set_has_xrelease_prefix(true); |
1537 | 0 | } |
1538 | 0 | _ => {} |
1539 | | } |
1540 | 0 | } |
1541 | | |
1542 | | #[inline] |
1543 | 1 | fn clear_mandatory_prefix_f3(&self, instruction: &mut Instruction) { |
1544 | 1 | debug_assert_eq!(self.state.encoding(), EncodingKind::Legacy as u32); |
1545 | 1 | debug_assert_eq!(self.state.mandatory_prefix, DecoderMandatoryPrefix::PF3); |
1546 | 1 | instruction.set_has_repe_prefix(false); |
1547 | 1 | } |
1548 | | |
1549 | | #[inline] |
1550 | 0 | fn clear_mandatory_prefix_f2(&self, instruction: &mut Instruction) { |
1551 | 0 | debug_assert_eq!(self.state.encoding(), EncodingKind::Legacy as u32); |
1552 | 0 | debug_assert_eq!(self.state.mandatory_prefix, DecoderMandatoryPrefix::PF2); |
1553 | 0 | instruction.set_has_repne_prefix(false); |
1554 | 0 | } |
1555 | | |
1556 | | #[inline] |
1557 | 63 | fn set_invalid_instruction(&mut self) { |
1558 | 63 | self.state.flags |= StateFlags::IS_INVALID; |
1559 | 63 | } |
1560 | | |
1561 | | #[inline(always)] |
1562 | 4.90k | fn decode_table2(&mut self, (decode, handler): (OpCodeHandlerDecodeFn, &OpCodeHandler), instruction: &mut Instruction) { |
1563 | 4.90k | if handler.has_modrm { |
1564 | 980 | let m = self.read_u8() as u32; |
1565 | 980 | self.state.modrm = m; |
1566 | 980 | self.state.reg = (m >> 3) & 7; |
1567 | 980 | self.state.mod_ = m >> 6; |
1568 | 980 | self.state.rm = m & 7; |
1569 | 980 | self.state.mem_index = (self.state.mod_ << 3) | self.state.rm; |
1570 | 3.92k | } |
1571 | 4.90k | (decode)(handler, self, instruction); |
1572 | 4.90k | } |
1573 | | |
1574 | | #[inline(always)] |
1575 | 49 | fn read_modrm(&mut self) { |
1576 | 49 | let m = self.read_u8() as u32; |
1577 | 49 | self.state.modrm = m; |
1578 | 49 | self.state.reg = (m >> 3) & 7; |
1579 | 49 | self.state.mod_ = m >> 6; |
1580 | 49 | self.state.rm = m & 7; |
1581 | 49 | self.state.mem_index = (self.state.mod_ << 3) | self.state.rm; |
1582 | 49 | } |
1583 | | |
1584 | | #[cfg(feature = "no_vex")] |
1585 | 3 | fn vex2(&mut self, _instruction: &mut Instruction) { |
1586 | 3 | self.set_invalid_instruction(); |
1587 | 3 | } |
1588 | | |
1589 | | #[cfg(not(feature = "no_vex"))] |
1590 | | fn vex2(&mut self, instruction: &mut Instruction) { |
1591 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1592 | | if (((self.state.flags & StateFlags::HAS_REX) | (self.state.mandatory_prefix as u32)) & self.invalid_check_mask) != 0 { |
1593 | | self.set_invalid_instruction(); |
1594 | | } |
1595 | | // Undo what decode_out() did if it got a REX prefix |
1596 | | self.state.flags &= !StateFlags::W; |
1597 | | self.state.extra_index_register_base = 0; |
1598 | | self.state.extra_base_register_base = 0; |
1599 | | |
1600 | | if cfg!(debug_assertions) { |
1601 | | self.state.flags |= (EncodingKind::VEX as u32) << StateFlags::ENCODING_SHIFT; |
1602 | | } |
1603 | | |
1604 | | let b = self.read_u8(); |
1605 | | let (decode, handler) = self.handlers_vex[0][b]; |
1606 | | |
1607 | | let mut b = self.state.modrm; |
1608 | | |
1609 | | const _: () = assert!(VectorLength::L128 as u32 == 0); |
1610 | | const _: () = assert!(VectorLength::L256 as u32 == 1); |
1611 | | // SAFETY: 0<=(n&1)<=1 and those are valid enum variants, see const assert!() above |
1612 | | self.state.vector_length = unsafe { mem::transmute((b >> 2) & 1) }; |
1613 | | |
1614 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1615 | | const _: () = assert!(DecoderMandatoryPrefix::P66 as u32 == 1); |
1616 | | const _: () = assert!(DecoderMandatoryPrefix::PF3 as u32 == 2); |
1617 | | const _: () = assert!(DecoderMandatoryPrefix::PF2 as u32 == 3); |
1618 | | // SAFETY: 0<=(b&3)<=3 and those are valid enum variants, see const assert!() above |
1619 | | self.state.mandatory_prefix = unsafe { mem::transmute(b & 3) }; |
1620 | | |
1621 | | b = !b; |
1622 | | self.state.extra_register_base = (b >> 4) & 8; |
1623 | | |
1624 | | // Bit 6 can only be 0 if it's 16/32-bit mode, so we don't need to change the mask |
1625 | | b = (b >> 3) & 0x0F; |
1626 | | self.state.vvvv = b; |
1627 | | self.state.vvvv_invalid_check = b; |
1628 | | |
1629 | | self.decode_table2((decode, handler), instruction); |
1630 | | } |
1631 | | |
1632 | | #[cfg(feature = "no_vex")] |
1633 | 0 | fn vex3(&mut self, _instruction: &mut Instruction) { |
1634 | 0 | self.set_invalid_instruction(); |
1635 | 0 | } |
1636 | | |
1637 | | #[cfg(not(feature = "no_vex"))] |
1638 | | fn vex3(&mut self, instruction: &mut Instruction) { |
1639 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1640 | | if (((self.state.flags & StateFlags::HAS_REX) | (self.state.mandatory_prefix as u32)) & self.invalid_check_mask) != 0 { |
1641 | | self.set_invalid_instruction(); |
1642 | | } |
1643 | | // Undo what decode_out() did if it got a REX prefix |
1644 | | self.state.flags &= !StateFlags::W; |
1645 | | |
1646 | | if cfg!(debug_assertions) { |
1647 | | self.state.flags |= (EncodingKind::VEX as u32) << StateFlags::ENCODING_SHIFT; |
1648 | | } |
1649 | | |
1650 | | let b2 = self.read_u16() as u32; |
1651 | | |
1652 | | const _: () = assert!(StateFlags::W == 0x80); |
1653 | | self.state.flags |= b2 & 0x80; |
1654 | | |
1655 | | const _: () = assert!(VectorLength::L128 as u32 == 0); |
1656 | | const _: () = assert!(VectorLength::L256 as u32 == 1); |
1657 | | // SAFETY: 0<=(n&1)<=1 and those are valid enum variants, see const assert!() above |
1658 | | self.state.vector_length = unsafe { mem::transmute((b2 >> 2) & 1) }; |
1659 | | |
1660 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1661 | | const _: () = assert!(DecoderMandatoryPrefix::P66 as u32 == 1); |
1662 | | const _: () = assert!(DecoderMandatoryPrefix::PF3 as u32 == 2); |
1663 | | const _: () = assert!(DecoderMandatoryPrefix::PF2 as u32 == 3); |
1664 | | // SAFETY: 0<=(b2&3)<=3 and those are valid enum variants, see const assert!() above |
1665 | | self.state.mandatory_prefix = unsafe { mem::transmute(b2 & 3) }; |
1666 | | |
1667 | | let b = (!b2 >> 3) & 0x0F; |
1668 | | self.state.vvvv_invalid_check = b; |
1669 | | self.state.vvvv = b & self.reg15_mask; |
1670 | | let b1 = self.state.modrm; |
1671 | | let b1x = !b1 & self.mask_e0; |
1672 | | self.state.extra_register_base = (b1x >> 4) & 8; |
1673 | | self.state.extra_index_register_base = (b1x >> 3) & 8; |
1674 | | self.state.extra_base_register_base = (b1x >> 2) & 8; |
1675 | | |
1676 | | if let Some(&table) = self.handlers_vex.get(((b1 & 0x1F) as usize).wrapping_sub(1)) { |
1677 | | self.decode_table2(table[(b2 >> 8) as usize], instruction); |
1678 | | } else { |
1679 | | #[cfg(feature = "mvex")] |
1680 | | if (b1 & 0x1F) == 0 { |
1681 | | self.decode_table2(self.handlers_vex_map0[(b2 >> 8) as usize], instruction); |
1682 | | return; |
1683 | | } |
1684 | | self.set_invalid_instruction(); |
1685 | | } |
1686 | | } |
1687 | | |
1688 | | #[cfg(feature = "no_xop")] |
1689 | 6 | fn xop(&mut self, _instruction: &mut Instruction) { |
1690 | 6 | self.set_invalid_instruction(); |
1691 | 6 | } |
1692 | | |
1693 | | #[cfg(not(feature = "no_xop"))] |
1694 | | fn xop(&mut self, instruction: &mut Instruction) { |
1695 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1696 | | if (((self.state.flags & StateFlags::HAS_REX) | (self.state.mandatory_prefix as u32)) & self.invalid_check_mask) != 0 { |
1697 | | self.set_invalid_instruction(); |
1698 | | } |
1699 | | // Undo what decode_out() did if it got a REX prefix |
1700 | | self.state.flags &= !StateFlags::W; |
1701 | | |
1702 | | if cfg!(debug_assertions) { |
1703 | | self.state.flags |= (EncodingKind::XOP as u32) << StateFlags::ENCODING_SHIFT; |
1704 | | } |
1705 | | |
1706 | | let b2 = self.read_u16() as u32; |
1707 | | |
1708 | | const _: () = assert!(StateFlags::W == 0x80); |
1709 | | self.state.flags |= b2 & 0x80; |
1710 | | |
1711 | | const _: () = assert!(VectorLength::L128 as u32 == 0); |
1712 | | const _: () = assert!(VectorLength::L256 as u32 == 1); |
1713 | | // SAFETY: 0<=(n&1)<=1 and those are valid enum variants, see const assert!() above |
1714 | | self.state.vector_length = unsafe { mem::transmute((b2 >> 2) & 1) }; |
1715 | | |
1716 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1717 | | const _: () = assert!(DecoderMandatoryPrefix::P66 as u32 == 1); |
1718 | | const _: () = assert!(DecoderMandatoryPrefix::PF3 as u32 == 2); |
1719 | | const _: () = assert!(DecoderMandatoryPrefix::PF2 as u32 == 3); |
1720 | | // SAFETY: 0<=(b2&3)<=3 and those are valid enum variants, see const assert!() above |
1721 | | self.state.mandatory_prefix = unsafe { mem::transmute(b2 & 3) }; |
1722 | | |
1723 | | let b = (!b2 >> 3) & 0x0F; |
1724 | | self.state.vvvv_invalid_check = b; |
1725 | | self.state.vvvv = b & self.reg15_mask; |
1726 | | let b1 = self.state.modrm; |
1727 | | let b1x = !b1 & self.mask_e0; |
1728 | | self.state.extra_register_base = (b1x >> 4) & 8; |
1729 | | self.state.extra_index_register_base = (b1x >> 3) & 8; |
1730 | | self.state.extra_base_register_base = (b1x >> 2) & 8; |
1731 | | |
1732 | | if let Some(&table) = self.handlers_xop.get(((b1 & 0x1F) as usize).wrapping_sub(8)) { |
1733 | | self.decode_table2(table[(b2 >> 8) as usize], instruction); |
1734 | | } else { |
1735 | | self.set_invalid_instruction(); |
1736 | | } |
1737 | | } |
1738 | | |
1739 | | #[cfg(not(any(not(feature = "no_evex"), feature = "mvex")))] |
1740 | 0 | fn evex_mvex(&mut self, _instruction: &mut Instruction) { |
1741 | 0 | self.set_invalid_instruction(); |
1742 | 0 | } |
1743 | | |
1744 | | #[cfg(any(not(feature = "no_evex"), feature = "mvex"))] |
1745 | | fn evex_mvex(&mut self, instruction: &mut Instruction) { |
1746 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1747 | | if (((self.state.flags & StateFlags::HAS_REX) | (self.state.mandatory_prefix as u32)) & self.invalid_check_mask) != 0 { |
1748 | | self.set_invalid_instruction(); |
1749 | | } |
1750 | | // Undo what decode_out() did if it got a REX prefix |
1751 | | self.state.flags &= !StateFlags::W; |
1752 | | |
1753 | | let d = self.read_u32() as u32; |
1754 | | if (d & 4) != 0 { |
1755 | | #[cfg(feature = "no_evex")] |
1756 | | self.set_invalid_instruction(); |
1757 | | #[cfg(not(feature = "no_evex"))] |
1758 | | { |
1759 | | let p0 = self.state.modrm; |
1760 | | if (p0 & 8) == 0 { |
1761 | | if cfg!(debug_assertions) { |
1762 | | self.state.flags |= (EncodingKind::EVEX as u32) << StateFlags::ENCODING_SHIFT; |
1763 | | } |
1764 | | |
1765 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1766 | | const _: () = assert!(DecoderMandatoryPrefix::P66 as u32 == 1); |
1767 | | const _: () = assert!(DecoderMandatoryPrefix::PF3 as u32 == 2); |
1768 | | const _: () = assert!(DecoderMandatoryPrefix::PF2 as u32 == 3); |
1769 | | // SAFETY: 0<=(d&3)<=3 and those are valid enum variants, see const assert!() above |
1770 | | self.state.mandatory_prefix = unsafe { mem::transmute(d & 3) }; |
1771 | | |
1772 | | const _: () = assert!(StateFlags::W == 0x80); |
1773 | | self.state.flags |= d & 0x80; |
1774 | | |
1775 | | let p2 = d >> 8; |
1776 | | let aaa = p2 & 7; |
1777 | | self.state.aaa = aaa; |
1778 | | instruction_internal::internal_set_op_mask(instruction, aaa); |
1779 | | if (p2 & 0x80) != 0 { |
1780 | | // invalid if aaa == 0 and if we check for invalid instructions (it's all 1s) |
1781 | | if (aaa ^ self.invalid_check_mask) == u32::MAX { |
1782 | | self.set_invalid_instruction(); |
1783 | | } |
1784 | | self.state.flags |= StateFlags::Z; |
1785 | | instruction.set_zeroing_masking(true); |
1786 | | } |
1787 | | |
1788 | | const _: () = assert!(StateFlags::B == 0x10); |
1789 | | self.state.flags |= p2 & 0x10; |
1790 | | |
1791 | | const _: () = assert!(VectorLength::L128 as u32 == 0); |
1792 | | const _: () = assert!(VectorLength::L256 as u32 == 1); |
1793 | | const _: () = assert!(VectorLength::L512 as u32 == 2); |
1794 | | const _: () = assert!(VectorLength::Unknown as u32 == 3); |
1795 | | // SAFETY: 0<=(n&3)<=3 and those are valid enum variants, see const assert!() above |
1796 | | self.state.vector_length = unsafe { mem::transmute((p2 >> 5) & 3) }; |
1797 | | |
1798 | | let p1 = (!d >> 3) & 0x0F; |
1799 | | if self.is64b_mode { |
1800 | | let mut tmp = (!p2 & 8) << 1; |
1801 | | self.state.extra_index_register_base_vsib = tmp; |
1802 | | tmp += p1; |
1803 | | self.state.vvvv = tmp; |
1804 | | self.state.vvvv_invalid_check = tmp; |
1805 | | let mut p0x = !p0; |
1806 | | self.state.extra_register_base = (p0x >> 4) & 8; |
1807 | | self.state.extra_index_register_base = (p0x >> 3) & 8; |
1808 | | self.state.extra_register_base_evex = p0x & 0x10; |
1809 | | p0x >>= 2; |
1810 | | self.state.extra_base_register_base_evex = p0x & 0x18; |
1811 | | self.state.extra_base_register_base = p0x & 8; |
1812 | | } else { |
1813 | | self.state.vvvv_invalid_check = p1; |
1814 | | self.state.vvvv = p1 & 0x07; |
1815 | | const _: () = assert!(StateFlags::IS_INVALID == 0x40); |
1816 | | self.state.flags |= (!p2 & 8) << 3; |
1817 | | } |
1818 | | |
1819 | | if let Some(&table) = self.handlers_evex.get(((p0 & 7) as usize).wrapping_sub(1)) { |
1820 | | let (decode, handler) = table[(d >> 16) as u8 as usize]; |
1821 | | debug_assert!(handler.has_modrm); |
1822 | | let m = d >> 24; |
1823 | | self.state.modrm = m; |
1824 | | self.state.reg = (m >> 3) & 7; |
1825 | | self.state.mod_ = m >> 6; |
1826 | | self.state.rm = m & 7; |
1827 | | self.state.mem_index = (self.state.mod_ << 3) | self.state.rm; |
1828 | | // Invalid if LL=3 and no rc |
1829 | | const _: () = assert!(StateFlags::B > 3); |
1830 | | debug_assert!(self.state.vector_length as u32 <= 3); |
1831 | | if (((self.state.flags & StateFlags::B) | (self.state.vector_length as u32)) & self.invalid_check_mask) == 3 { |
1832 | | self.set_invalid_instruction(); |
1833 | | } |
1834 | | (decode)(handler, self, instruction); |
1835 | | } else { |
1836 | | self.set_invalid_instruction(); |
1837 | | } |
1838 | | } else { |
1839 | | self.set_invalid_instruction(); |
1840 | | } |
1841 | | } |
1842 | | } else { |
1843 | | #[cfg(not(feature = "mvex"))] |
1844 | | self.set_invalid_instruction(); |
1845 | | #[cfg(feature = "mvex")] |
1846 | | { |
1847 | | if (self.options & DecoderOptions::KNC) == 0 || !self.is64b_mode { |
1848 | | self.set_invalid_instruction(); |
1849 | | } else { |
1850 | | let p0 = self.state.modrm; |
1851 | | if cfg!(debug_assertions) { |
1852 | | self.state.flags |= (EncodingKind::MVEX as u32) << StateFlags::ENCODING_SHIFT; |
1853 | | } |
1854 | | |
1855 | | const _: () = assert!(DecoderMandatoryPrefix::PNP as u32 == 0); |
1856 | | const _: () = assert!(DecoderMandatoryPrefix::P66 as u32 == 1); |
1857 | | const _: () = assert!(DecoderMandatoryPrefix::PF3 as u32 == 2); |
1858 | | const _: () = assert!(DecoderMandatoryPrefix::PF2 as u32 == 3); |
1859 | | // SAFETY: 0<=(d&3)<=3 and those are valid enum variants, see const assert!() above |
1860 | | self.state.mandatory_prefix = unsafe { mem::transmute(d & 3) }; |
1861 | | |
1862 | | const _: () = assert!(StateFlags::W == 0x80); |
1863 | | self.state.flags |= d & 0x80; |
1864 | | |
1865 | | let p2 = d >> 8; |
1866 | | let aaa = p2 & 7; |
1867 | | self.state.aaa = aaa; |
1868 | | instruction_internal::internal_set_op_mask(instruction, aaa); |
1869 | | |
1870 | | const _: () = assert!(StateFlags::MVEX_SSS_SHIFT == 16); |
1871 | | const _: () = assert!(StateFlags::MVEX_SSS_MASK == 7); |
1872 | | const _: () = assert!(StateFlags::MVEX_EH == 1 << (StateFlags::MVEX_SSS_SHIFT + 3)); |
1873 | | self.state.flags |= (p2 & 0xF0) << (StateFlags::MVEX_SSS_SHIFT - 4); |
1874 | | |
1875 | | let p1 = (!d >> 3) & 0x0F; |
1876 | | let mut tmp = (!p2 & 8) << 1; |
1877 | | self.state.extra_index_register_base_vsib = tmp; |
1878 | | tmp += p1; |
1879 | | self.state.vvvv = tmp; |
1880 | | self.state.vvvv_invalid_check = tmp; |
1881 | | let mut p0x = !p0; |
1882 | | self.state.extra_register_base = (p0x >> 4) & 8; |
1883 | | self.state.extra_index_register_base = (p0x >> 3) & 8; |
1884 | | self.state.extra_register_base_evex = p0x & 0x10; |
1885 | | p0x >>= 2; |
1886 | | self.state.extra_base_register_base_evex = p0x & 0x18; |
1887 | | self.state.extra_base_register_base = p0x & 8; |
1888 | | |
1889 | | if let Some(&table) = self.handlers_mvex.get(((p0 & 0xF) as usize).wrapping_sub(1)) { |
1890 | | let (decode, handler) = table[(d >> 16) as u8 as usize]; |
1891 | | debug_assert!(handler.has_modrm); |
1892 | | let m = d >> 24; |
1893 | | self.state.modrm = m; |
1894 | | self.state.reg = (m >> 3) & 7; |
1895 | | self.state.mod_ = m >> 6; |
1896 | | self.state.rm = m & 7; |
1897 | | self.state.mem_index = (self.state.mod_ << 3) | self.state.rm; |
1898 | | (decode)(handler, self, instruction); |
1899 | | } else { |
1900 | | self.set_invalid_instruction(); |
1901 | | } |
1902 | | } |
1903 | | } |
1904 | | } |
1905 | | } |
1906 | | |
1907 | | #[must_use] |
1908 | | #[inline(always)] |
1909 | 30 | fn read_op_seg_reg(&mut self) -> u32 { |
1910 | 30 | let reg = self.state.reg; |
1911 | | const _: () = assert!(Register::ES as u32 + 1 == Register::CS as u32); |
1912 | | const _: () = assert!(Register::ES as u32 + 2 == Register::SS as u32); |
1913 | | const _: () = assert!(Register::ES as u32 + 3 == Register::DS as u32); |
1914 | | const _: () = assert!(Register::ES as u32 + 4 == Register::FS as u32); |
1915 | | const _: () = assert!(Register::ES as u32 + 5 == Register::GS as u32); |
1916 | 30 | if reg < 6 { |
1917 | 22 | Register::ES as u32 + reg |
1918 | | } else { |
1919 | 8 | self.set_invalid_instruction(); |
1920 | 8 | Register::None as u32 |
1921 | | } |
1922 | 30 | } |
1923 | | |
1924 | | #[inline(always)] |
1925 | | #[cfg(any(not(feature = "no_vex"), not(feature = "no_xop")))] |
1926 | | fn read_op_mem_sib(&mut self, instruction: &mut Instruction) { |
1927 | | debug_assert!(self.state.encoding() != EncodingKind::EVEX as u32 && self.state.encoding() != EncodingKind::MVEX as u32); |
1928 | | let is_valid = if self.state.address_size != OpSize::Size16 { |
1929 | | self.read_op_mem_32_or_64(instruction) |
1930 | | } else { |
1931 | | self.read_op_mem_16(instruction, TupleType::N1); |
1932 | | false |
1933 | | }; |
1934 | | if self.invalid_check_mask != 0 && !is_valid { |
1935 | | self.set_invalid_instruction(); |
1936 | | } |
1937 | | } |
1938 | | |
1939 | | // All MPX instructions in 64-bit mode force 64-bit addressing, and |
1940 | | // all MPX instructions in 16/32-bit mode require 32-bit addressing |
1941 | | // (see SDM Vol 1, 17.5.1 Intel MPX and Operating Modes) |
1942 | | #[inline(always)] |
1943 | 0 | fn read_op_mem_mpx(&mut self, instruction: &mut Instruction) { |
1944 | 0 | debug_assert!(self.state.encoding() != EncodingKind::EVEX as u32 && self.state.encoding() != EncodingKind::MVEX as u32); |
1945 | 0 | if self.is64b_mode { |
1946 | 0 | self.state.address_size = OpSize::Size64; |
1947 | 0 | let _ = self.read_op_mem_32_or_64(instruction); |
1948 | 0 | } else if self.state.address_size != OpSize::Size16 { |
1949 | 0 | let _ = self.read_op_mem_32_or_64(instruction); |
1950 | 0 | } else { |
1951 | 0 | self.read_op_mem_16(instruction, TupleType::N1); |
1952 | 0 | if self.invalid_check_mask != 0 { |
1953 | 0 | self.set_invalid_instruction(); |
1954 | 0 | } |
1955 | | } |
1956 | 0 | } |
1957 | | |
1958 | | #[inline(always)] |
1959 | | #[cfg(any(not(feature = "no_evex"), feature = "mvex"))] |
1960 | | fn read_op_mem_tuple_type(&mut self, instruction: &mut Instruction, tuple_type: TupleType) { |
1961 | | debug_assert!(self.state.encoding() == EncodingKind::EVEX as u32 || self.state.encoding() == EncodingKind::MVEX as u32); |
1962 | | if self.state.address_size != OpSize::Size16 { |
1963 | | let index_reg = if self.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
1964 | | let _ = decoder_read_op_mem_32_or_64_vsib(self, instruction, index_reg, tuple_type, false); |
1965 | | } else { |
1966 | | self.read_op_mem_16(instruction, tuple_type); |
1967 | | } |
1968 | | } |
1969 | | |
1970 | | #[inline(always)] |
1971 | | #[cfg(any(not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
1972 | | fn read_op_mem_vsib(&mut self, instruction: &mut Instruction, vsib_index: Register, tuple_type: TupleType) { |
1973 | | let is_valid = if self.state.address_size != OpSize::Size16 { |
1974 | | decoder_read_op_mem_32_or_64_vsib(self, instruction, vsib_index, tuple_type, true) |
1975 | | } else { |
1976 | | self.read_op_mem_16(instruction, tuple_type); |
1977 | | false |
1978 | | }; |
1979 | | if self.invalid_check_mask != 0 && !is_valid { |
1980 | | self.set_invalid_instruction(); |
1981 | | } |
1982 | | } |
1983 | | |
1984 | | // It's small enough that the compiler wants to inline it but almost no-one will |
1985 | | // disassemble code with 16-bit addressing. |
1986 | | #[inline(never)] |
1987 | | #[cold] |
1988 | 0 | fn read_op_mem_16(&mut self, instruction: &mut Instruction, tuple_type: TupleType) { |
1989 | 0 | debug_assert!(self.state.address_size == OpSize::Size16); |
1990 | 0 | debug_assert!(self.state.rm <= 7); |
1991 | | // SAFETY: `MEM_REGS_16.len() == 8` and `0<=self.state.rm<=7` |
1992 | 0 | let (mut base_reg, index_reg) = unsafe { *MEM_REGS_16.get_unchecked(self.state.rm as usize) }; |
1993 | 0 | match self.state.mod_ { |
1994 | | 0 => { |
1995 | 0 | if self.state.rm == 6 { |
1996 | 0 | instruction_internal::internal_set_memory_displ_size(instruction, 2); |
1997 | 0 | self.displ_index = self.data_ptr as u8; |
1998 | 0 | instruction.set_memory_displacement64(self.read_u16() as u64); |
1999 | 0 | base_reg = Register::None; |
2000 | 0 | debug_assert_eq!(index_reg, Register::None); |
2001 | 0 | } |
2002 | | } |
2003 | 0 | 1 => { |
2004 | 0 | instruction_internal::internal_set_memory_displ_size(instruction, 1); |
2005 | 0 | self.displ_index = self.data_ptr as u8; |
2006 | 0 | let b = self.read_u8(); |
2007 | 0 | instruction.set_memory_displacement64(self.disp8n(tuple_type).wrapping_mul(b as i8 as u32) as u16 as u64); |
2008 | 0 | } |
2009 | | _ => { |
2010 | 0 | debug_assert_eq!(self.state.mod_, 2); |
2011 | 0 | instruction_internal::internal_set_memory_displ_size(instruction, 2); |
2012 | 0 | self.displ_index = self.data_ptr as u8; |
2013 | 0 | instruction.set_memory_displacement64(self.read_u16() as u64); |
2014 | | } |
2015 | | } |
2016 | 0 | instruction.set_memory_base(base_reg); |
2017 | 0 | instruction.set_memory_index(index_reg); |
2018 | 0 | } |
2019 | | |
2020 | | #[must_use] |
2021 | | #[cfg(feature = "__internal_flip")] |
2022 | | fn read_op_mem_32_or_64(&mut self, instruction: &mut Instruction) -> bool { |
2023 | | let base_reg = if self.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2024 | | decoder_read_op_mem_32_or_64_vsib(self, instruction, base_reg, TupleType::N1, false) |
2025 | | } |
2026 | | |
2027 | | // Returns `true` if the SIB byte was read |
2028 | | // This is a specialized version of read_op_mem_32_or_64_vsib() which takes less arguments. Keep them in sync. |
2029 | | #[must_use] |
2030 | | #[cfg(not(feature = "__internal_flip"))] |
2031 | | #[inline(always)] |
2032 | 0 | fn read_op_mem_32_or_64(&mut self, instruction: &mut Instruction) -> bool { |
2033 | 0 | read_op_mem_stmt_ret!(self, instruction, {}) |
2034 | 0 | } |
2035 | | |
2036 | | #[cfg(not(feature = "__internal_flip"))] |
2037 | | #[allow(clippy::never_loop)] |
2038 | 68 | fn read_op_mem_1(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2039 | | loop { |
2040 | 68 | instruction_internal::internal_set_memory_displ_size(instruction, 1); |
2041 | 68 | this.displ_index = this.data_ptr as u8; |
2042 | 68 | let displ = read_u8_break!(this) as i8 as u64; |
2043 | 67 | if this.state.address_size == OpSize::Size64 { |
2044 | 64 | instruction.set_memory_displacement64(displ); |
2045 | 64 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::RAX as u32); |
2046 | | } else { |
2047 | 3 | instruction.set_memory_displacement64(displ as u32 as u64); |
2048 | 3 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::EAX as u32); |
2049 | | } |
2050 | | |
2051 | 67 | return false; |
2052 | | } |
2053 | 1 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2054 | 1 | false |
2055 | 68 | } |
2056 | | |
2057 | | #[cfg(not(feature = "__internal_flip"))] |
2058 | | #[allow(clippy::never_loop)] |
2059 | 56 | fn read_op_mem_1_4(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2060 | | loop { |
2061 | 56 | instruction_internal::internal_set_memory_displ_size(instruction, 1); |
2062 | | |
2063 | 56 | this.displ_index = this.data_ptr.wrapping_add(1) as u8; |
2064 | 56 | let w = read_u16_break!(this) as u32; |
2065 | | |
2066 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2067 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2068 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2069 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2070 | | // SAFETY: 0-3 are valid variants |
2071 | 55 | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute(((w >> 6) & 3) as InstrScaleUnderlyingType) }); |
2072 | 55 | let index = ((w >> 3) & 7) + this.state.extra_index_register_base; |
2073 | 55 | if this.state.address_size == OpSize::Size64 { |
2074 | | const BASE_REG: Register = Register::RAX; |
2075 | 44 | if index != 4 { |
2076 | 40 | write_index_reg!(instruction, index + BASE_REG as u32); |
2077 | 4 | } |
2078 | | |
2079 | 44 | write_base_reg!(instruction, (w & 7) + this.state.extra_base_register_base + BASE_REG as u32); |
2080 | 44 | let displ = (w >> 8) as i8 as u64; |
2081 | 44 | instruction.set_memory_displacement64(displ); |
2082 | | } else { |
2083 | | const BASE_REG: Register = Register::EAX; |
2084 | 11 | if index != 4 { |
2085 | 10 | write_index_reg!(instruction, index + BASE_REG as u32); |
2086 | 1 | } |
2087 | | |
2088 | 11 | write_base_reg!(instruction, (w & 7) + this.state.extra_base_register_base + BASE_REG as u32); |
2089 | 11 | let displ = (w >> 8) as i8 as u32 as u64; |
2090 | 11 | instruction.set_memory_displacement64(displ); |
2091 | | } |
2092 | | |
2093 | 55 | return true; |
2094 | | } |
2095 | 1 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2096 | 1 | true |
2097 | 56 | } |
2098 | | |
2099 | | #[cfg(not(feature = "__internal_flip"))] |
2100 | 579 | fn read_op_mem_0(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2101 | 579 | if this.state.address_size == OpSize::Size64 { |
2102 | 557 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::RAX as u32); |
2103 | | } else { |
2104 | 22 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::EAX as u32); |
2105 | | }; |
2106 | | |
2107 | 579 | false |
2108 | 579 | } |
2109 | | |
2110 | | #[cfg(not(feature = "__internal_flip"))] |
2111 | | #[allow(clippy::never_loop)] |
2112 | 44 | fn read_op_mem_0_5(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2113 | | loop { |
2114 | 44 | this.displ_index = this.data_ptr as u8; |
2115 | 44 | let displ = read_u32_break!(this) as i32 as u64; |
2116 | 42 | if this.state.address_size == OpSize::Size64 { |
2117 | 39 | debug_assert!(this.is64b_mode); |
2118 | 39 | this.state.flags |= StateFlags::IP_REL64; |
2119 | 39 | instruction.set_memory_displacement64(displ); |
2120 | 39 | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2121 | 39 | instruction.set_memory_base(Register::RIP); |
2122 | 3 | } else if this.is64b_mode { |
2123 | 3 | this.state.flags |= StateFlags::IP_REL32; |
2124 | 3 | instruction.set_memory_displacement64(displ as u32 as u64); |
2125 | 3 | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2126 | 3 | instruction.set_memory_base(Register::EIP); |
2127 | 3 | } else { |
2128 | 0 | instruction.set_memory_displacement64(displ as u32 as u64); |
2129 | 0 | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2130 | 0 | } |
2131 | | |
2132 | 42 | return false; |
2133 | | } |
2134 | 2 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2135 | 2 | false |
2136 | 44 | } |
2137 | | |
2138 | | #[cfg(not(feature = "__internal_flip"))] |
2139 | | #[allow(clippy::never_loop)] |
2140 | 78 | fn read_op_mem_2_4(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2141 | | loop { |
2142 | 78 | let sib = read_u8_break!(this) as u32; |
2143 | 77 | this.displ_index = this.data_ptr as u8; |
2144 | 77 | let displ = read_u32_break!(this) as i32 as u64; |
2145 | | |
2146 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2147 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2148 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2149 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2150 | | // SAFETY: 0-3 are valid variants |
2151 | 74 | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute((sib >> 6) as InstrScaleUnderlyingType) }); |
2152 | 74 | let index = ((sib >> 3) & 7) + this.state.extra_index_register_base; |
2153 | 74 | if this.state.address_size == OpSize::Size64 { |
2154 | | const BASE_REG: Register = Register::RAX; |
2155 | 55 | if index != 4 { |
2156 | 51 | write_index_reg!(instruction, index + BASE_REG as u32); |
2157 | 4 | } |
2158 | | |
2159 | 55 | write_base_reg!(instruction, (sib & 7) + this.state.extra_base_register_base + BASE_REG as u32); |
2160 | 55 | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2161 | 55 | instruction.set_memory_displacement64(displ); |
2162 | | } else { |
2163 | | const BASE_REG: Register = Register::EAX; |
2164 | 19 | if index != 4 { |
2165 | 18 | write_index_reg!(instruction, index + BASE_REG as u32); |
2166 | 1 | } |
2167 | | |
2168 | 19 | write_base_reg!(instruction, (sib & 7) + this.state.extra_base_register_base + BASE_REG as u32); |
2169 | 19 | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2170 | 19 | instruction.set_memory_displacement64(displ as u32 as u64); |
2171 | | } |
2172 | | |
2173 | 74 | return true; |
2174 | | } |
2175 | 4 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2176 | 4 | true |
2177 | 78 | } |
2178 | | |
2179 | | #[cfg(not(feature = "__internal_flip"))] |
2180 | | #[allow(clippy::never_loop)] |
2181 | 99 | fn read_op_mem_2(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2182 | | loop { |
2183 | 99 | this.displ_index = this.data_ptr as u8; |
2184 | 99 | let displ = read_u32_break!(this) as i32 as u64; |
2185 | 96 | if this.state.address_size == OpSize::Size64 { |
2186 | 92 | instruction.set_memory_displacement64(displ); |
2187 | 92 | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2188 | 92 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::RAX as u32); |
2189 | | } else { |
2190 | 4 | instruction.set_memory_displacement64(displ as u32 as u64); |
2191 | 4 | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2192 | 4 | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::EAX as u32); |
2193 | | } |
2194 | | |
2195 | 96 | return false; |
2196 | | } |
2197 | 3 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2198 | 3 | false |
2199 | 99 | } |
2200 | | |
2201 | | #[cfg(not(feature = "__internal_flip"))] |
2202 | | #[allow(clippy::never_loop)] |
2203 | 59 | fn read_op_mem_0_4(instruction: &mut Instruction, this: &mut Decoder<'_>) -> bool { |
2204 | | loop { |
2205 | 59 | let sib = read_u8_break!(this) as u32; |
2206 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2207 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2208 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2209 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2210 | | // SAFETY: 0-3 are valid variants |
2211 | 58 | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute((sib >> 6) as InstrScaleUnderlyingType) }); |
2212 | 58 | let index = ((sib >> 3) & 7) + this.state.extra_index_register_base; |
2213 | 58 | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2214 | 58 | if index != 4 { |
2215 | 49 | write_index_reg!(instruction, index + base_reg as u32); |
2216 | 9 | } |
2217 | | |
2218 | 58 | let base = sib & 7; |
2219 | 58 | if base == 5 { |
2220 | 9 | this.displ_index = this.data_ptr as u8; |
2221 | 9 | let displ = read_u32_break!(this) as i32 as u64; |
2222 | 6 | if this.state.address_size == OpSize::Size64 { |
2223 | 5 | instruction.set_memory_displacement64(displ); |
2224 | 5 | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2225 | 5 | } else { |
2226 | 1 | instruction.set_memory_displacement64(displ as u32 as u64); |
2227 | 1 | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2228 | 1 | } |
2229 | | } else { |
2230 | 49 | write_base_reg!(instruction, base + this.state.extra_base_register_base + base_reg as u32); |
2231 | 49 | instruction_internal::internal_set_memory_displ_size(instruction, 0); |
2232 | 49 | instruction.set_memory_displacement64(0); |
2233 | | } |
2234 | | |
2235 | 55 | return true; |
2236 | | } |
2237 | 4 | this.state.flags |= StateFlags::IS_INVALID | StateFlags::NO_MORE_BYTES; |
2238 | 4 | true |
2239 | 59 | } |
2240 | | |
2241 | | #[must_use] |
2242 | | #[inline(always)] |
2243 | 0 | fn disp8n(&self, tuple_type: TupleType) -> u32 { |
2244 | 0 | get_disp8n(tuple_type, (self.state.flags & StateFlags::B) != 0) |
2245 | 0 | } |
2246 | | |
2247 | | /// Gets the offsets of the constants (memory displacement and immediate) in the decoded instruction. |
2248 | | /// The caller can check if there are any relocations at those addresses. |
2249 | | /// |
2250 | | /// # Arguments |
2251 | | /// |
2252 | | /// * `instruction`: The latest instruction that was decoded by this decoder |
2253 | | /// |
2254 | | /// # Examples |
2255 | | /// |
2256 | | /// ``` |
2257 | | /// use iced_x86::*; |
2258 | | /// |
2259 | | /// // nop |
2260 | | /// // xor dword ptr [rax-5AA5EDCCh],5Ah |
2261 | | /// // 00 01 02 03 04 05 06 |
2262 | | /// // \opc\mrm\displacement___\imm |
2263 | | /// let bytes = b"\x90\x83\xB3\x34\x12\x5A\xA5\x5A"; |
2264 | | /// let mut decoder = Decoder::with_ip(64, bytes, 0x1234_5678, DecoderOptions::NONE); |
2265 | | /// assert_eq!(decoder.decode().code(), Code::Nopd); |
2266 | | /// let instr = decoder.decode(); |
2267 | | /// let co = decoder.get_constant_offsets(&instr); |
2268 | | /// |
2269 | | /// assert!(co.has_displacement()); |
2270 | | /// assert_eq!(co.displacement_offset(), 2); |
2271 | | /// assert_eq!(co.displacement_size(), 4); |
2272 | | /// assert!(co.has_immediate()); |
2273 | | /// assert_eq!(co.immediate_offset(), 6); |
2274 | | /// assert_eq!(co.immediate_size(), 1); |
2275 | | /// // It's not an instruction with two immediates (e.g. enter) |
2276 | | /// assert!(!co.has_immediate2()); |
2277 | | /// assert_eq!(co.immediate_offset2(), 0); |
2278 | | /// assert_eq!(co.immediate_size2(), 0); |
2279 | | /// ``` |
2280 | | #[must_use] |
2281 | | #[allow(clippy::missing_inline_in_public_items)] |
2282 | 0 | pub fn get_constant_offsets(&self, instruction: &Instruction) -> ConstantOffsets { |
2283 | 0 | let mut constant_offsets = ConstantOffsets::default(); |
2284 | | |
2285 | 0 | let displ_size = instruction.memory_displ_size(); |
2286 | 0 | if displ_size != 0 { |
2287 | 0 | constant_offsets.displacement_offset = self.displ_index.wrapping_sub(self.instr_start_data_ptr as u8); |
2288 | 0 | if displ_size == 8 && (self.state.flags & StateFlags::ADDR64) == 0 { |
2289 | 0 | constant_offsets.displacement_size = 4; |
2290 | 0 | } else { |
2291 | 0 | constant_offsets.displacement_size = displ_size as u8; |
2292 | 0 | } |
2293 | 0 | } |
2294 | | |
2295 | 0 | if (self.state.flags & StateFlags::NO_IMM) == 0 { |
2296 | 0 | let mut extra_imm_sub = 0; |
2297 | 0 | for i in (0..instruction.op_count()).rev() { |
2298 | 0 | match instruction.op_kind(i) { |
2299 | | OpKind::Immediate8 | OpKind::Immediate8to16 | OpKind::Immediate8to32 | OpKind::Immediate8to64 => { |
2300 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(extra_imm_sub).wrapping_sub(1) as u8; |
2301 | 0 | constant_offsets.immediate_size = 1; |
2302 | 0 | break; |
2303 | | } |
2304 | | |
2305 | | OpKind::Immediate16 => { |
2306 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(extra_imm_sub).wrapping_sub(2) as u8; |
2307 | 0 | constant_offsets.immediate_size = 2; |
2308 | 0 | break; |
2309 | | } |
2310 | | |
2311 | | OpKind::Immediate32 | OpKind::Immediate32to64 => { |
2312 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(extra_imm_sub).wrapping_sub(4) as u8; |
2313 | 0 | constant_offsets.immediate_size = 4; |
2314 | 0 | break; |
2315 | | } |
2316 | | |
2317 | | OpKind::Immediate64 => { |
2318 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(extra_imm_sub).wrapping_sub(8) as u8; |
2319 | 0 | constant_offsets.immediate_size = 8; |
2320 | 0 | break; |
2321 | | } |
2322 | | |
2323 | 0 | OpKind::Immediate8_2nd => { |
2324 | 0 | constant_offsets.immediate_offset2 = instruction.len().wrapping_sub(1) as u8; |
2325 | 0 | constant_offsets.immediate_size2 = 1; |
2326 | 0 | extra_imm_sub = 1; |
2327 | 0 | } |
2328 | | |
2329 | | OpKind::NearBranch16 => { |
2330 | 0 | if (self.state.flags & StateFlags::BRANCH_IMM8) != 0 { |
2331 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(1) as u8; |
2332 | 0 | constant_offsets.immediate_size = 1; |
2333 | 0 | } else if (self.state.flags & StateFlags::XBEGIN) == 0 { |
2334 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(2) as u8; |
2335 | 0 | constant_offsets.immediate_size = 2; |
2336 | 0 | } else { |
2337 | 0 | debug_assert!((self.state.flags & StateFlags::XBEGIN) != 0); |
2338 | 0 | if self.state.operand_size != OpSize::Size16 { |
2339 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(4) as u8; |
2340 | 0 | constant_offsets.immediate_size = 4; |
2341 | 0 | } else { |
2342 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(2) as u8; |
2343 | 0 | constant_offsets.immediate_size = 2; |
2344 | 0 | } |
2345 | | } |
2346 | | } |
2347 | | |
2348 | | OpKind::NearBranch32 | OpKind::NearBranch64 => { |
2349 | 0 | if (self.state.flags & StateFlags::BRANCH_IMM8) != 0 { |
2350 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(1) as u8; |
2351 | 0 | constant_offsets.immediate_size = 1; |
2352 | 0 | } else if (self.state.flags & StateFlags::XBEGIN) == 0 { |
2353 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(4) as u8; |
2354 | 0 | constant_offsets.immediate_size = 4; |
2355 | 0 | } else { |
2356 | 0 | debug_assert!((self.state.flags & StateFlags::XBEGIN) != 0); |
2357 | 0 | if self.state.operand_size != OpSize::Size16 { |
2358 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(4) as u8; |
2359 | 0 | constant_offsets.immediate_size = 4; |
2360 | 0 | } else { |
2361 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(2) as u8; |
2362 | 0 | constant_offsets.immediate_size = 2; |
2363 | 0 | } |
2364 | | } |
2365 | | } |
2366 | | |
2367 | 0 | OpKind::FarBranch16 => { |
2368 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(2 + 2) as u8; |
2369 | 0 | constant_offsets.immediate_size = 2; |
2370 | 0 | constant_offsets.immediate_offset2 = instruction.len().wrapping_sub(2) as u8; |
2371 | 0 | constant_offsets.immediate_size2 = 2; |
2372 | 0 | } |
2373 | | |
2374 | 0 | OpKind::FarBranch32 => { |
2375 | 0 | constant_offsets.immediate_offset = instruction.len().wrapping_sub(4 + 2) as u8; |
2376 | 0 | constant_offsets.immediate_size = 4; |
2377 | 0 | constant_offsets.immediate_offset2 = instruction.len().wrapping_sub(2) as u8; |
2378 | 0 | constant_offsets.immediate_size2 = 2; |
2379 | 0 | } |
2380 | | |
2381 | 0 | _ => {} |
2382 | | } |
2383 | | } |
2384 | 0 | } |
2385 | | |
2386 | 0 | constant_offsets |
2387 | 0 | } |
2388 | | } |
2389 | | |
2390 | | // These are referenced from a static and I couldn't get it to work when they were inside an `impl` block |
2391 | | // so they're here instead of where they really belong. |
2392 | | |
2393 | | // Returns `true` if the SIB byte was read |
2394 | | // Same as read_op_mem_32_or_64() except it works with vsib memory operands. Keep them in sync. |
2395 | | #[must_use] |
2396 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2397 | | #[inline(always)] |
2398 | | fn decoder_read_op_mem_32_or_64_vsib( |
2399 | | this: &mut Decoder<'_>, instruction: &mut Instruction, index_reg: Register, tuple_type: TupleType, is_vsib: bool, |
2400 | | ) -> bool { |
2401 | | debug_assert!(this.state.address_size == OpSize::Size32 || this.state.address_size == OpSize::Size64); |
2402 | | |
2403 | | let index = this.state.mem_index as usize; |
2404 | | debug_assert!(index < READ_OP_MEM_VSIB_FNS.len()); |
2405 | | // SAFETY: index is valid because modrm.mod = 0-2 (never 3 if we're here) so index will always be 0-10_111 (17h) |
2406 | | unsafe { (READ_OP_MEM_VSIB_FNS.get_unchecked(index))(this, instruction, index_reg, tuple_type, is_vsib) } |
2407 | | } |
2408 | | |
2409 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2410 | | fn decoder_read_op_mem_vsib_1( |
2411 | | this: &mut Decoder<'_>, instruction: &mut Instruction, _index_reg: Register, tuple_type: TupleType, _is_vsib: bool, |
2412 | | ) -> bool { |
2413 | | instruction_internal::internal_set_memory_displ_size(instruction, 1); |
2414 | | this.displ_index = this.data_ptr as u8; |
2415 | | let b = this.read_u8(); |
2416 | | if this.state.address_size == OpSize::Size64 { |
2417 | | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::RAX as u32); |
2418 | | instruction.set_memory_displacement64((this.disp8n(tuple_type) as u64).wrapping_mul(b as i8 as u64)); |
2419 | | } else { |
2420 | | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + Register::EAX as u32); |
2421 | | instruction.set_memory_displacement64(this.disp8n(tuple_type).wrapping_mul(b as i8 as u32) as u64); |
2422 | | } |
2423 | | |
2424 | | false |
2425 | | } |
2426 | | |
2427 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2428 | | fn decoder_read_op_mem_vsib_1_4( |
2429 | | this: &mut Decoder<'_>, instruction: &mut Instruction, index_reg: Register, tuple_type: TupleType, is_vsib: bool, |
2430 | | ) -> bool { |
2431 | | instruction_internal::internal_set_memory_displ_size(instruction, 1); |
2432 | | |
2433 | | this.displ_index = this.data_ptr.wrapping_add(1) as u8; |
2434 | | let sib = this.read_u16() as u32; |
2435 | | let index = ((sib >> 3) & 7) + this.state.extra_index_register_base; |
2436 | | if !is_vsib { |
2437 | | if index != 4 { |
2438 | | write_index_reg!(instruction, index + index_reg as u32); |
2439 | | } |
2440 | | } else { |
2441 | | write_index_reg!(instruction, index + this.state.extra_index_register_base_vsib + index_reg as u32); |
2442 | | } |
2443 | | |
2444 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2445 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2446 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2447 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2448 | | // SAFETY: 0-3 are valid variants |
2449 | | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute(((sib >> 6) & 3) as InstrScaleUnderlyingType) }); |
2450 | | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2451 | | write_base_reg!(instruction, (sib & 7) + this.state.extra_base_register_base + base_reg as u32); |
2452 | | |
2453 | | let b = (sib >> 8) as i8 as u32; |
2454 | | let displ = this.disp8n(tuple_type).wrapping_mul(b); |
2455 | | if this.state.address_size == OpSize::Size64 { |
2456 | | instruction.set_memory_displacement64(displ as i32 as u64); |
2457 | | } else { |
2458 | | instruction.set_memory_displacement64(displ as u64); |
2459 | | } |
2460 | | |
2461 | | true |
2462 | | } |
2463 | | |
2464 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2465 | | fn decoder_read_op_mem_vsib_0( |
2466 | | this: &mut Decoder<'_>, instruction: &mut Instruction, _index_reg: Register, _tuple_type: TupleType, _is_vsib: bool, |
2467 | | ) -> bool { |
2468 | | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2469 | | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + base_reg as u32); |
2470 | | |
2471 | | false |
2472 | | } |
2473 | | |
2474 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2475 | | fn decoder_read_op_mem_vsib_0_5( |
2476 | | this: &mut Decoder<'_>, instruction: &mut Instruction, _index_reg: Register, _tuple_type: TupleType, _is_vsib: bool, |
2477 | | ) -> bool { |
2478 | | this.displ_index = this.data_ptr as u8; |
2479 | | let d = this.read_u32(); |
2480 | | if this.state.address_size == OpSize::Size64 { |
2481 | | debug_assert!(this.is64b_mode); |
2482 | | this.state.flags |= StateFlags::IP_REL64; |
2483 | | instruction.set_memory_displacement64(d as i32 as u64); |
2484 | | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2485 | | instruction.set_memory_base(Register::RIP); |
2486 | | } else if this.is64b_mode { |
2487 | | this.state.flags |= StateFlags::IP_REL32; |
2488 | | instruction.set_memory_displacement64(d as u64); |
2489 | | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2490 | | instruction.set_memory_base(Register::EIP); |
2491 | | } else { |
2492 | | instruction.set_memory_displacement64(d as u64); |
2493 | | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2494 | | } |
2495 | | |
2496 | | false |
2497 | | } |
2498 | | |
2499 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2500 | | fn decoder_read_op_mem_vsib_2_4( |
2501 | | this: &mut Decoder<'_>, instruction: &mut Instruction, index_reg: Register, _tuple_type: TupleType, is_vsib: bool, |
2502 | | ) -> bool { |
2503 | | let sib = this.read_u8() as u32; |
2504 | | this.displ_index = this.data_ptr as u8; |
2505 | | |
2506 | | let index = ((sib >> 3) & 7) + this.state.extra_index_register_base; |
2507 | | if !is_vsib { |
2508 | | if index != 4 { |
2509 | | write_index_reg!(instruction, index + index_reg as u32); |
2510 | | } |
2511 | | } else { |
2512 | | write_index_reg!(instruction, index + this.state.extra_index_register_base_vsib + index_reg as u32); |
2513 | | } |
2514 | | |
2515 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2516 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2517 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2518 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2519 | | // SAFETY: 0-3 are valid variants |
2520 | | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute((sib >> 6) as InstrScaleUnderlyingType) }); |
2521 | | |
2522 | | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2523 | | write_base_reg!(instruction, (sib & 7) + this.state.extra_base_register_base + base_reg as u32); |
2524 | | let displ = this.read_u32() as u32; |
2525 | | if this.state.address_size == OpSize::Size64 { |
2526 | | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2527 | | instruction.set_memory_displacement64(displ as i32 as u64); |
2528 | | } else { |
2529 | | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2530 | | instruction.set_memory_displacement64(displ as u64); |
2531 | | } |
2532 | | |
2533 | | true |
2534 | | } |
2535 | | |
2536 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2537 | | fn decoder_read_op_mem_vsib_2( |
2538 | | this: &mut Decoder<'_>, instruction: &mut Instruction, _index_reg: Register, _tuple_type: TupleType, _is_vsib: bool, |
2539 | | ) -> bool { |
2540 | | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2541 | | write_base_reg!(instruction, this.state.extra_base_register_base + this.state.rm + base_reg as u32); |
2542 | | this.displ_index = this.data_ptr as u8; |
2543 | | let d = this.read_u32(); |
2544 | | if this.state.address_size == OpSize::Size64 { |
2545 | | instruction.set_memory_displacement64(d as i32 as u64); |
2546 | | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2547 | | } else { |
2548 | | instruction.set_memory_displacement64(d as u64); |
2549 | | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2550 | | } |
2551 | | |
2552 | | false |
2553 | | } |
2554 | | |
2555 | | #[cfg(any(feature = "__internal_flip", not(feature = "no_evex"), not(feature = "no_vex"), not(feature = "no_xop"), feature = "mvex"))] |
2556 | | fn decoder_read_op_mem_vsib_0_4( |
2557 | | this: &mut Decoder<'_>, instruction: &mut Instruction, index_reg: Register, _tuple_type: TupleType, is_vsib: bool, |
2558 | | ) -> bool { |
2559 | | let sib = this.read_u8() as u32; |
2560 | | const _: () = assert!(InstrScale::Scale1 as u32 == 0); |
2561 | | const _: () = assert!(InstrScale::Scale2 as u32 == 1); |
2562 | | const _: () = assert!(InstrScale::Scale4 as u32 == 2); |
2563 | | const _: () = assert!(InstrScale::Scale8 as u32 == 3); |
2564 | | // SAFETY: 0-3 are valid variants |
2565 | | instruction_internal::internal_set_memory_index_scale(instruction, unsafe { mem::transmute((sib >> 6) as InstrScaleUnderlyingType) }); |
2566 | | let index = ((sib >> 3) & 7) + this.state.extra_index_register_base; |
2567 | | if !is_vsib { |
2568 | | if index != 4 { |
2569 | | write_index_reg!(instruction, index + index_reg as u32); |
2570 | | } |
2571 | | } else { |
2572 | | write_index_reg!(instruction, index + this.state.extra_index_register_base_vsib + index_reg as u32); |
2573 | | } |
2574 | | |
2575 | | let base = sib & 7; |
2576 | | if base == 5 { |
2577 | | this.displ_index = this.data_ptr as u8; |
2578 | | let d = this.read_u32(); |
2579 | | if this.state.address_size == OpSize::Size64 { |
2580 | | instruction.set_memory_displacement64(d as i32 as u64); |
2581 | | instruction_internal::internal_set_memory_displ_size(instruction, 4); |
2582 | | } else { |
2583 | | instruction.set_memory_displacement64(d as u64); |
2584 | | instruction_internal::internal_set_memory_displ_size(instruction, 3); |
2585 | | } |
2586 | | } else { |
2587 | | let base_reg = if this.state.address_size == OpSize::Size64 { Register::RAX } else { Register::EAX }; |
2588 | | write_base_reg!(instruction, base + this.state.extra_base_register_base + base_reg as u32); |
2589 | | instruction_internal::internal_set_memory_displ_size(instruction, 0); |
2590 | | instruction.set_memory_displacement64(0); |
2591 | | } |
2592 | | |
2593 | | true |
2594 | | } |
2595 | | |
2596 | | #[doc(hidden)] |
2597 | | #[allow(missing_debug_implementations)] |
2598 | | pub struct DecoderIter<'a, 'b> { |
2599 | | decoder: &'b mut Decoder<'a>, |
2600 | | } |
2601 | | |
2602 | | impl Iterator for DecoderIter<'_, '_> { |
2603 | | type Item = Instruction; |
2604 | | |
2605 | | #[inline] |
2606 | 0 | fn next(&mut self) -> Option<Self::Item> { |
2607 | 0 | if self.decoder.can_decode() { |
2608 | 0 | Some(self.decoder.decode()) |
2609 | | } else { |
2610 | 0 | None |
2611 | | } |
2612 | 0 | } |
2613 | | } |
2614 | | |
2615 | | impl FusedIterator for DecoderIter<'_, '_> {} |
2616 | | |
2617 | | #[doc(hidden)] |
2618 | | #[allow(missing_debug_implementations)] |
2619 | | pub struct DecoderIntoIter<'a> { |
2620 | | decoder: Decoder<'a>, |
2621 | | } |
2622 | | |
2623 | | impl Iterator for DecoderIntoIter<'_> { |
2624 | | type Item = Instruction; |
2625 | | |
2626 | | #[inline] |
2627 | 0 | fn next(&mut self) -> Option<Self::Item> { |
2628 | 0 | if self.decoder.can_decode() { |
2629 | 0 | Some(self.decoder.decode()) |
2630 | | } else { |
2631 | 0 | None |
2632 | | } |
2633 | 0 | } |
2634 | | } |
2635 | | |
2636 | | impl FusedIterator for DecoderIntoIter<'_> {} |
2637 | | |
2638 | | impl<'a> IntoIterator for Decoder<'a> { |
2639 | | type Item = Instruction; |
2640 | | type IntoIter = DecoderIntoIter<'a>; |
2641 | | |
2642 | | #[must_use] |
2643 | | #[inline] |
2644 | 0 | fn into_iter(self) -> Self::IntoIter { |
2645 | 0 | DecoderIntoIter { decoder: self } |
2646 | 0 | } |
2647 | | } |
2648 | | |
2649 | | impl<'a, 'b> IntoIterator for &'b mut Decoder<'a> { |
2650 | | type Item = Instruction; |
2651 | | type IntoIter = DecoderIter<'a, 'b>; |
2652 | | |
2653 | | #[must_use] |
2654 | | #[inline] |
2655 | 0 | fn into_iter(self) -> Self::IntoIter { |
2656 | 0 | DecoderIter { decoder: self } |
2657 | 0 | } |
2658 | | } |