Instruction.h 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Optional.h>
  8. #include <AK/StdLibExtras.h>
  9. #include <AK/String.h>
  10. #include <AK/Types.h>
  11. #include <stdio.h>
  12. namespace X86 {
  13. class Instruction;
  14. class Interpreter;
  15. typedef void (Interpreter::*InstructionHandler)(const Instruction&);
  16. class SymbolProvider {
  17. public:
  18. virtual String symbolicate(FlatPtr, u32* offset = nullptr) const = 0;
  19. protected:
  20. virtual ~SymbolProvider() = default;
  21. };
  22. template<typename T>
  23. struct TypeTrivia {
  24. static const size_t bits = sizeof(T) * 8;
  25. static const T sign_bit = 1 << (bits - 1);
  26. static const T mask = MakeUnsigned<T>(-1);
  27. };
  28. template<typename T, typename U>
  29. constexpr T sign_extended_to(U value)
  30. {
  31. if (!(value & TypeTrivia<U>::sign_bit))
  32. return value;
  33. return (TypeTrivia<T>::mask & ~TypeTrivia<U>::mask) | value;
  34. }
  35. enum IsLockPrefixAllowed {
  36. LockPrefixNotAllowed = 0,
  37. LockPrefixAllowed
  38. };
  39. enum InstructionFormat {
  40. InvalidFormat,
  41. MultibyteWithSlash,
  42. InstructionPrefix,
  43. __BeginFormatsWithRMByte,
  44. OP_RM16_reg16,
  45. OP_reg8_RM8,
  46. OP_reg16_RM16,
  47. OP_RM16_seg,
  48. OP_RM32_seg,
  49. OP_RM8_imm8,
  50. OP_RM16_imm16,
  51. OP_RM16_imm8,
  52. OP_RM32_imm8,
  53. OP_RM8,
  54. OP_RM16,
  55. OP_RM32,
  56. OP_FPU,
  57. OP_FPU_reg,
  58. OP_FPU_mem,
  59. OP_FPU_AX16,
  60. OP_FPU_RM16,
  61. OP_FPU_RM32,
  62. OP_FPU_RM64,
  63. OP_FPU_M80,
  64. OP_RM8_reg8,
  65. OP_RM32_reg32,
  66. OP_reg32_RM32,
  67. OP_RM32_imm32,
  68. OP_reg16_RM16_imm8,
  69. OP_reg32_RM32_imm8,
  70. OP_reg16_RM16_imm16,
  71. OP_reg32_RM32_imm32,
  72. OP_reg16_mem16,
  73. OP_reg32_mem32,
  74. OP_seg_RM16,
  75. OP_seg_RM32,
  76. OP_RM8_1,
  77. OP_RM16_1,
  78. OP_RM32_1,
  79. OP_FAR_mem16,
  80. OP_FAR_mem32,
  81. OP_RM8_CL,
  82. OP_RM16_CL,
  83. OP_RM32_CL,
  84. OP_reg32_CR,
  85. OP_CR_reg32,
  86. OP_reg32_DR,
  87. OP_DR_reg32,
  88. OP_reg16_RM8,
  89. OP_reg32_RM8,
  90. OP_reg32_RM16,
  91. OP_RM16_reg16_imm8,
  92. OP_RM32_reg32_imm8,
  93. OP_RM16_reg16_CL,
  94. OP_RM32_reg32_CL,
  95. OP_mm1_mm2m64,
  96. OP_mm1_mm2m32,
  97. OP_mm1_imm8,
  98. OP_mm1m64_mm2,
  99. __EndFormatsWithRMByte,
  100. OP_reg32_imm32,
  101. OP_AL_imm8,
  102. OP_AX_imm16,
  103. OP_EAX_imm32,
  104. OP_CS,
  105. OP_DS,
  106. OP_ES,
  107. OP_SS,
  108. OP_FS,
  109. OP_GS,
  110. OP,
  111. OP_reg16,
  112. OP_imm16,
  113. OP_relimm16,
  114. OP_relimm32,
  115. OP_imm8,
  116. OP_imm16_imm16,
  117. OP_imm16_imm32,
  118. OP_AX_reg16,
  119. OP_EAX_reg32,
  120. OP_AL_moff8,
  121. OP_AX_moff16,
  122. OP_EAX_moff32,
  123. OP_moff8_AL,
  124. OP_moff16_AX,
  125. OP_moff32_EAX,
  126. OP_reg8_imm8,
  127. OP_reg16_imm16,
  128. OP_3,
  129. OP_AX_imm8,
  130. OP_EAX_imm8,
  131. OP_short_imm8,
  132. OP_AL_DX,
  133. OP_AX_DX,
  134. OP_EAX_DX,
  135. OP_DX_AL,
  136. OP_DX_AX,
  137. OP_DX_EAX,
  138. OP_imm8_AL,
  139. OP_imm8_AX,
  140. OP_imm8_EAX,
  141. OP_reg8_CL,
  142. OP_reg32,
  143. OP_imm32,
  144. OP_imm16_imm8,
  145. OP_NEAR_imm,
  146. };
  147. static const unsigned CurrentAddressSize = 0xB33FBABE;
  148. struct InstructionDescriptor {
  149. InstructionHandler handler { nullptr };
  150. bool opcode_has_register_index { false };
  151. const char* mnemonic { nullptr };
  152. InstructionFormat format { InvalidFormat };
  153. bool has_rm { false };
  154. unsigned imm1_bytes { 0 };
  155. unsigned imm2_bytes { 0 };
  156. // Addressed by the 3 REG bits in the MOD-REG-R/M byte.
  157. // Some slash instructions have further subgroups when MOD is 11,
  158. // in that case the InstructionDescriptors in slashes have themselves
  159. // a non-null slashes member that's indexed by the three R/M bits.
  160. InstructionDescriptor* slashes { nullptr };
  161. unsigned imm1_bytes_for_address_size(bool a32)
  162. {
  163. if (imm1_bytes == CurrentAddressSize)
  164. return a32 ? 4 : 2;
  165. return imm1_bytes;
  166. }
  167. unsigned imm2_bytes_for_address_size(bool a32)
  168. {
  169. if (imm2_bytes == CurrentAddressSize)
  170. return a32 ? 4 : 2;
  171. return imm2_bytes;
  172. }
  173. IsLockPrefixAllowed lock_prefix_allowed { LockPrefixNotAllowed };
  174. };
  175. extern InstructionDescriptor s_table16[256];
  176. extern InstructionDescriptor s_table32[256];
  177. extern InstructionDescriptor s_0f_table16[256];
  178. extern InstructionDescriptor s_0f_table32[256];
  179. struct Prefix {
  180. enum Op {
  181. OperandSizeOverride = 0x66,
  182. AddressSizeOverride = 0x67,
  183. REP = 0xf3,
  184. REPZ = 0xf3,
  185. REPNZ = 0xf2,
  186. LOCK = 0xf0,
  187. };
  188. };
  189. enum class SegmentRegister {
  190. ES = 0,
  191. CS,
  192. SS,
  193. DS,
  194. FS,
  195. GS,
  196. SegR6,
  197. SegR7,
  198. };
  199. enum RegisterIndex8 {
  200. RegisterAL = 0,
  201. RegisterCL,
  202. RegisterDL,
  203. RegisterBL,
  204. RegisterAH,
  205. RegisterCH,
  206. RegisterDH,
  207. RegisterBH
  208. };
  209. enum RegisterIndex16 {
  210. RegisterAX = 0,
  211. RegisterCX,
  212. RegisterDX,
  213. RegisterBX,
  214. RegisterSP,
  215. RegisterBP,
  216. RegisterSI,
  217. RegisterDI
  218. };
  219. enum RegisterIndex32 {
  220. RegisterEAX = 0,
  221. RegisterECX,
  222. RegisterEDX,
  223. RegisterEBX,
  224. RegisterESP,
  225. RegisterEBP,
  226. RegisterESI,
  227. RegisterEDI
  228. };
  229. enum FpuRegisterIndex {
  230. ST0 = 0,
  231. ST1,
  232. ST2,
  233. ST3,
  234. ST4,
  235. ST5,
  236. ST6,
  237. ST7
  238. };
  239. enum MMXRegisterIndex {
  240. RegisterMM0 = 0,
  241. RegisterMM1,
  242. RegisterMM2,
  243. RegisterMM3,
  244. RegisterMM4,
  245. RegisterMM5,
  246. RegisterMM6,
  247. RegisterMM7
  248. };
  249. class LogicalAddress {
  250. public:
  251. LogicalAddress() { }
  252. LogicalAddress(u16 selector, FlatPtr offset)
  253. : m_selector(selector)
  254. , m_offset(offset)
  255. {
  256. }
  257. u16 selector() const { return m_selector; }
  258. FlatPtr offset() const { return m_offset; }
  259. void set_selector(u16 selector) { m_selector = selector; }
  260. void set_offset(FlatPtr offset) { m_offset = offset; }
  261. private:
  262. u16 m_selector { 0 };
  263. FlatPtr m_offset { 0 };
  264. };
  265. class InstructionStream {
  266. public:
  267. virtual bool can_read() = 0;
  268. virtual u8 read8() = 0;
  269. virtual u16 read16() = 0;
  270. virtual u32 read32() = 0;
  271. virtual u64 read64() = 0;
  272. protected:
  273. virtual ~InstructionStream() = default;
  274. };
  275. class SimpleInstructionStream final : public InstructionStream {
  276. public:
  277. SimpleInstructionStream(const u8* data, size_t size)
  278. : m_data(data)
  279. , m_size(size)
  280. {
  281. }
  282. virtual bool can_read() override { return m_offset < m_size; }
  283. virtual u8 read8() override
  284. {
  285. if (!can_read())
  286. return 0;
  287. return m_data[m_offset++];
  288. }
  289. virtual u16 read16() override
  290. {
  291. u8 lsb = read8();
  292. u8 msb = read8();
  293. return ((u16)msb << 8) | (u16)lsb;
  294. }
  295. virtual u32 read32() override
  296. {
  297. u16 lsw = read16();
  298. u16 msw = read16();
  299. return ((u32)msw << 16) | (u32)lsw;
  300. }
  301. virtual u64 read64() override
  302. {
  303. u32 lsw = read32();
  304. u32 msw = read32();
  305. return ((u64)msw << 32) | (u64)lsw;
  306. }
  307. size_t offset() const { return m_offset; }
  308. private:
  309. const u8* m_data { nullptr };
  310. size_t m_offset { 0 };
  311. size_t m_size { 0 };
  312. };
  313. class MemoryOrRegisterReference {
  314. friend class Instruction;
  315. public:
  316. String to_string_o8(const Instruction&) const;
  317. String to_string_o16(const Instruction&) const;
  318. String to_string_o32(const Instruction&) const;
  319. String to_string_fpu_reg() const;
  320. String to_string_fpu_mem(const Instruction&) const;
  321. String to_string_fpu_ax16() const;
  322. String to_string_fpu16(const Instruction&) const;
  323. String to_string_fpu32(const Instruction&) const;
  324. String to_string_fpu64(const Instruction&) const;
  325. String to_string_fpu80(const Instruction&) const;
  326. String to_string_mm(const Instruction&) const;
  327. bool is_register() const { return m_register_index != 0x7f; }
  328. unsigned register_index() const { return m_register_index; }
  329. RegisterIndex32 reg32() const { return static_cast<RegisterIndex32>(register_index()); }
  330. RegisterIndex16 reg16() const { return static_cast<RegisterIndex16>(register_index()); }
  331. RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
  332. FpuRegisterIndex reg_fpu() const { return static_cast<FpuRegisterIndex>(register_index()); }
  333. template<typename CPU, typename T>
  334. void write8(CPU&, const Instruction&, T);
  335. template<typename CPU, typename T>
  336. void write16(CPU&, const Instruction&, T);
  337. template<typename CPU, typename T>
  338. void write32(CPU&, const Instruction&, T);
  339. template<typename CPU, typename T>
  340. void write64(CPU&, const Instruction&, T);
  341. template<typename CPU, typename T>
  342. void write128(CPU&, const Instruction&, T);
  343. template<typename CPU, typename T>
  344. void write256(CPU&, const Instruction&, T);
  345. template<typename CPU>
  346. typename CPU::ValueWithShadowType8 read8(CPU&, const Instruction&);
  347. template<typename CPU>
  348. typename CPU::ValueWithShadowType16 read16(CPU&, const Instruction&);
  349. template<typename CPU>
  350. typename CPU::ValueWithShadowType32 read32(CPU&, const Instruction&);
  351. template<typename CPU>
  352. typename CPU::ValueWithShadowType64 read64(CPU&, const Instruction&);
  353. template<typename CPU>
  354. typename CPU::ValueWithShadowType128 read128(CPU&, const Instruction&);
  355. template<typename CPU>
  356. typename CPU::ValueWithShadowType256 read256(CPU&, const Instruction&);
  357. template<typename CPU>
  358. LogicalAddress resolve(const CPU&, const Instruction&);
  359. private:
  360. MemoryOrRegisterReference() { }
  361. String to_string(const Instruction&) const;
  362. String to_string_a16() const;
  363. String to_string_a32() const;
  364. template<typename InstructionStreamType>
  365. void decode(InstructionStreamType&, bool a32);
  366. template<typename InstructionStreamType>
  367. void decode16(InstructionStreamType&);
  368. template<typename InstructionStreamType>
  369. void decode32(InstructionStreamType&);
  370. template<typename CPU>
  371. LogicalAddress resolve16(const CPU&, Optional<SegmentRegister>);
  372. template<typename CPU>
  373. LogicalAddress resolve32(const CPU&, Optional<SegmentRegister>);
  374. template<typename CPU>
  375. u32 evaluate_sib(const CPU&, SegmentRegister& default_segment) const;
  376. union {
  377. u32 m_displacement32 { 0 };
  378. u16 m_displacement16;
  379. };
  380. u8 m_rm { 0 };
  381. u8 m_sib { 0 };
  382. u8 m_displacement_bytes { 0 };
  383. u8 m_register_index : 7 { 0x7f };
  384. bool m_has_sib : 1 { false };
  385. };
  386. class Instruction {
  387. public:
  388. template<typename InstructionStreamType>
  389. static Instruction from_stream(InstructionStreamType&, bool o32, bool a32);
  390. ~Instruction() { }
  391. ALWAYS_INLINE MemoryOrRegisterReference& modrm() const { return m_modrm; }
  392. ALWAYS_INLINE InstructionHandler handler() const { return m_descriptor->handler; }
  393. bool has_segment_prefix() const { return m_segment_prefix != 0xff; }
  394. ALWAYS_INLINE Optional<SegmentRegister> segment_prefix() const
  395. {
  396. if (has_segment_prefix())
  397. return static_cast<SegmentRegister>(m_segment_prefix);
  398. return {};
  399. }
  400. bool has_address_size_override_prefix() const { return m_has_address_size_override_prefix; }
  401. bool has_operand_size_override_prefix() const { return m_has_operand_size_override_prefix; }
  402. bool has_lock_prefix() const { return m_has_lock_prefix; }
  403. bool has_rep_prefix() const { return m_rep_prefix; }
  404. u8 rep_prefix() const { return m_rep_prefix; }
  405. bool is_valid() const { return m_descriptor; }
  406. unsigned length() const;
  407. String mnemonic() const;
  408. u8 op() const { return m_op; }
  409. u8 rm() const { return m_modrm.m_rm; }
  410. u8 slash() const { return (rm() >> 3) & 7; }
  411. u8 imm8() const { return m_imm1; }
  412. u16 imm16() const { return m_imm1; }
  413. u32 imm32() const { return m_imm1; }
  414. u8 imm8_1() const { return imm8(); }
  415. u8 imm8_2() const { return m_imm2; }
  416. u16 imm16_1() const { return imm16(); }
  417. u16 imm16_2() const { return m_imm2; }
  418. u32 imm32_1() const { return imm32(); }
  419. u32 imm32_2() const { return m_imm2; }
  420. u32 imm_address() const { return m_a32 ? imm32() : imm16(); }
  421. LogicalAddress imm_address16_16() const { return LogicalAddress(imm16_1(), imm16_2()); }
  422. LogicalAddress imm_address16_32() const { return LogicalAddress(imm16_1(), imm32_2()); }
  423. bool has_sub_op() const
  424. {
  425. return m_op == 0x0f;
  426. }
  427. unsigned register_index() const { return m_register_index; }
  428. RegisterIndex32 reg32() const { return static_cast<RegisterIndex32>(register_index()); }
  429. RegisterIndex16 reg16() const { return static_cast<RegisterIndex16>(register_index()); }
  430. RegisterIndex8 reg8() const { return static_cast<RegisterIndex8>(register_index()); }
  431. SegmentRegister segment_register() const { return static_cast<SegmentRegister>(register_index()); }
  432. u8 cc() const { return has_sub_op() ? m_sub_op & 0xf : m_op & 0xf; }
  433. bool a32() const { return m_a32; }
  434. String to_string(u32 origin, const SymbolProvider* = nullptr, bool x32 = true) const;
  435. private:
  436. template<typename InstructionStreamType>
  437. Instruction(InstructionStreamType&, bool o32, bool a32);
  438. void to_string_internal(StringBuilder&, u32 origin, const SymbolProvider*, bool x32) const;
  439. const char* reg8_name() const;
  440. const char* reg16_name() const;
  441. const char* reg32_name() const;
  442. InstructionDescriptor* m_descriptor { nullptr };
  443. mutable MemoryOrRegisterReference m_modrm;
  444. u32 m_imm1 { 0 };
  445. u32 m_imm2 { 0 };
  446. u8 m_segment_prefix { 0xff };
  447. u8 m_register_index { 0xff };
  448. u8 m_op { 0 };
  449. u8 m_sub_op { 0 };
  450. u8 m_extra_bytes { 0 };
  451. u8 m_rep_prefix { 0 };
  452. bool m_a32 : 1 { false };
  453. bool m_o32 : 1 { false };
  454. bool m_has_lock_prefix : 1 { false };
  455. bool m_has_operand_size_override_prefix : 1 { false };
  456. bool m_has_address_size_override_prefix : 1 { false };
  457. };
  458. template<typename CPU>
  459. ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve16(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
  460. {
  461. auto default_segment = SegmentRegister::DS;
  462. u16 offset = 0;
  463. switch (m_rm & 7) {
  464. case 0:
  465. offset = cpu.bx().value() + cpu.si().value() + m_displacement16;
  466. break;
  467. case 1:
  468. offset = cpu.bx().value() + cpu.di().value() + m_displacement16;
  469. break;
  470. case 2:
  471. default_segment = SegmentRegister::SS;
  472. offset = cpu.bp().value() + cpu.si().value() + m_displacement16;
  473. break;
  474. case 3:
  475. default_segment = SegmentRegister::SS;
  476. offset = cpu.bp().value() + cpu.di().value() + m_displacement16;
  477. break;
  478. case 4:
  479. offset = cpu.si().value() + m_displacement16;
  480. break;
  481. case 5:
  482. offset = cpu.di().value() + m_displacement16;
  483. break;
  484. case 6:
  485. if ((m_rm & 0xc0) == 0)
  486. offset = m_displacement16;
  487. else {
  488. default_segment = SegmentRegister::SS;
  489. offset = cpu.bp().value() + m_displacement16;
  490. }
  491. break;
  492. default:
  493. offset = cpu.bx().value() + m_displacement16;
  494. break;
  495. }
  496. u16 segment = cpu.segment(segment_prefix.value_or(default_segment));
  497. return { segment, offset };
  498. }
  499. template<typename CPU>
  500. ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve32(const CPU& cpu, Optional<SegmentRegister> segment_prefix)
  501. {
  502. auto default_segment = SegmentRegister::DS;
  503. u32 offset = 0;
  504. switch (m_rm & 0x07) {
  505. case 0 ... 3:
  506. case 6 ... 7:
  507. offset = cpu.const_gpr32((RegisterIndex32)(m_rm & 0x07)).value() + m_displacement32;
  508. break;
  509. case 4:
  510. offset = evaluate_sib(cpu, default_segment);
  511. break;
  512. default: // 5
  513. if ((m_rm & 0xc0) == 0x00) {
  514. offset = m_displacement32;
  515. break;
  516. } else {
  517. default_segment = SegmentRegister::SS;
  518. offset = cpu.ebp().value() + m_displacement32;
  519. break;
  520. }
  521. break;
  522. }
  523. u16 segment = cpu.segment(segment_prefix.value_or(default_segment));
  524. return { segment, offset };
  525. }
  526. template<typename CPU>
  527. ALWAYS_INLINE u32 MemoryOrRegisterReference::evaluate_sib(const CPU& cpu, SegmentRegister& default_segment) const
  528. {
  529. u32 scale_shift = m_sib >> 6;
  530. u32 index = 0;
  531. switch ((m_sib >> 3) & 0x07) {
  532. case 0 ... 3:
  533. case 5 ... 7:
  534. index = cpu.const_gpr32((RegisterIndex32)((m_sib >> 3) & 0x07)).value();
  535. break;
  536. case 4:
  537. index = 0;
  538. break;
  539. }
  540. u32 base = m_displacement32;
  541. switch (m_sib & 0x07) {
  542. case 0 ... 3:
  543. case 6 ... 7:
  544. base += cpu.const_gpr32((RegisterIndex32)(m_sib & 0x07)).value();
  545. break;
  546. case 4:
  547. default_segment = SegmentRegister::SS;
  548. base += cpu.esp().value();
  549. break;
  550. default: // 5
  551. switch ((m_rm >> 6) & 3) {
  552. case 0:
  553. break;
  554. case 1:
  555. case 2:
  556. default_segment = SegmentRegister::SS;
  557. base += cpu.ebp().value();
  558. break;
  559. default:
  560. VERIFY_NOT_REACHED();
  561. break;
  562. }
  563. break;
  564. }
  565. return (index << scale_shift) + base;
  566. }
  567. template<typename CPU, typename T>
  568. ALWAYS_INLINE void MemoryOrRegisterReference::write8(CPU& cpu, const Instruction& insn, T value)
  569. {
  570. if (is_register()) {
  571. cpu.gpr8(reg8()) = value;
  572. return;
  573. }
  574. auto address = resolve(cpu, insn);
  575. cpu.write_memory8(address, value);
  576. }
  577. template<typename CPU, typename T>
  578. ALWAYS_INLINE void MemoryOrRegisterReference::write16(CPU& cpu, const Instruction& insn, T value)
  579. {
  580. if (is_register()) {
  581. cpu.gpr16(reg16()) = value;
  582. return;
  583. }
  584. auto address = resolve(cpu, insn);
  585. cpu.write_memory16(address, value);
  586. }
  587. template<typename CPU, typename T>
  588. ALWAYS_INLINE void MemoryOrRegisterReference::write32(CPU& cpu, const Instruction& insn, T value)
  589. {
  590. if (is_register()) {
  591. cpu.gpr32(reg32()) = value;
  592. return;
  593. }
  594. auto address = resolve(cpu, insn);
  595. cpu.write_memory32(address, value);
  596. }
  597. template<typename CPU, typename T>
  598. ALWAYS_INLINE void MemoryOrRegisterReference::write64(CPU& cpu, const Instruction& insn, T value)
  599. {
  600. VERIFY(!is_register());
  601. auto address = resolve(cpu, insn);
  602. cpu.write_memory64(address, value);
  603. }
  604. template<typename CPU, typename T>
  605. ALWAYS_INLINE void MemoryOrRegisterReference::write128(CPU& cpu, const Instruction& insn, T value)
  606. {
  607. VERIFY(!is_register());
  608. auto address = resolve(cpu, insn);
  609. cpu.write_memory128(address, value);
  610. }
  611. template<typename CPU, typename T>
  612. ALWAYS_INLINE void MemoryOrRegisterReference::write256(CPU& cpu, const Instruction& insn, T value)
  613. {
  614. VERIFY(!is_register());
  615. auto address = resolve(cpu, insn);
  616. cpu.write_memory256(address, value);
  617. }
  618. template<typename CPU>
  619. ALWAYS_INLINE typename CPU::ValueWithShadowType8 MemoryOrRegisterReference::read8(CPU& cpu, const Instruction& insn)
  620. {
  621. if (is_register())
  622. return cpu.const_gpr8(reg8());
  623. auto address = resolve(cpu, insn);
  624. return cpu.read_memory8(address);
  625. }
  626. template<typename CPU>
  627. ALWAYS_INLINE typename CPU::ValueWithShadowType16 MemoryOrRegisterReference::read16(CPU& cpu, const Instruction& insn)
  628. {
  629. if (is_register())
  630. return cpu.const_gpr16(reg16());
  631. auto address = resolve(cpu, insn);
  632. return cpu.read_memory16(address);
  633. }
  634. template<typename CPU>
  635. ALWAYS_INLINE typename CPU::ValueWithShadowType32 MemoryOrRegisterReference::read32(CPU& cpu, const Instruction& insn)
  636. {
  637. if (is_register())
  638. return cpu.const_gpr32(reg32());
  639. auto address = resolve(cpu, insn);
  640. return cpu.read_memory32(address);
  641. }
  642. template<typename CPU>
  643. ALWAYS_INLINE typename CPU::ValueWithShadowType64 MemoryOrRegisterReference::read64(CPU& cpu, const Instruction& insn)
  644. {
  645. VERIFY(!is_register());
  646. auto address = resolve(cpu, insn);
  647. return cpu.read_memory64(address);
  648. }
  649. template<typename CPU>
  650. ALWAYS_INLINE typename CPU::ValueWithShadowType128 MemoryOrRegisterReference::read128(CPU& cpu, const Instruction& insn)
  651. {
  652. VERIFY(!is_register());
  653. auto address = resolve(cpu, insn);
  654. return cpu.read_memory128(address);
  655. }
  656. template<typename CPU>
  657. ALWAYS_INLINE typename CPU::ValueWithShadowType256 MemoryOrRegisterReference::read256(CPU& cpu, const Instruction& insn)
  658. {
  659. VERIFY(!is_register());
  660. auto address = resolve(cpu, insn);
  661. return cpu.read_memory256(address);
  662. }
  663. template<typename InstructionStreamType>
  664. ALWAYS_INLINE Instruction Instruction::from_stream(InstructionStreamType& stream, bool o32, bool a32)
  665. {
  666. return Instruction(stream, o32, a32);
  667. }
  668. ALWAYS_INLINE unsigned Instruction::length() const
  669. {
  670. unsigned len = 1;
  671. if (has_sub_op())
  672. ++len;
  673. if (m_descriptor->has_rm) {
  674. ++len;
  675. if (m_modrm.m_has_sib)
  676. ++len;
  677. len += m_modrm.m_displacement_bytes;
  678. }
  679. len += m_extra_bytes;
  680. return len;
  681. }
  682. ALWAYS_INLINE Optional<SegmentRegister> to_segment_prefix(u8 op)
  683. {
  684. switch (op) {
  685. case 0x26:
  686. return SegmentRegister::ES;
  687. case 0x2e:
  688. return SegmentRegister::CS;
  689. case 0x36:
  690. return SegmentRegister::SS;
  691. case 0x3e:
  692. return SegmentRegister::DS;
  693. case 0x64:
  694. return SegmentRegister::FS;
  695. case 0x65:
  696. return SegmentRegister::GS;
  697. default:
  698. return {};
  699. }
  700. }
  701. template<typename InstructionStreamType>
  702. ALWAYS_INLINE Instruction::Instruction(InstructionStreamType& stream, bool o32, bool a32)
  703. : m_a32(a32)
  704. , m_o32(o32)
  705. {
  706. u8 prefix_bytes = 0;
  707. for (;; ++prefix_bytes) {
  708. u8 opbyte = stream.read8();
  709. if (opbyte == Prefix::OperandSizeOverride) {
  710. m_o32 = !o32;
  711. m_has_operand_size_override_prefix = true;
  712. continue;
  713. }
  714. if (opbyte == Prefix::AddressSizeOverride) {
  715. m_a32 = !a32;
  716. m_has_address_size_override_prefix = true;
  717. continue;
  718. }
  719. if (opbyte == Prefix::REPZ || opbyte == Prefix::REPNZ) {
  720. m_rep_prefix = opbyte;
  721. continue;
  722. }
  723. if (opbyte == Prefix::LOCK) {
  724. m_has_lock_prefix = true;
  725. continue;
  726. }
  727. auto segment_prefix = to_segment_prefix(opbyte);
  728. if (segment_prefix.has_value()) {
  729. m_segment_prefix = (u8)segment_prefix.value();
  730. continue;
  731. }
  732. m_op = opbyte;
  733. break;
  734. }
  735. if (m_op == 0x0f) {
  736. m_sub_op = stream.read8();
  737. m_descriptor = m_o32 ? &s_0f_table32[m_sub_op] : &s_0f_table16[m_sub_op];
  738. } else {
  739. m_descriptor = m_o32 ? &s_table32[m_op] : &s_table16[m_op];
  740. }
  741. if (m_descriptor->has_rm) {
  742. // Consume ModR/M (may include SIB and displacement.)
  743. m_modrm.decode(stream, m_a32);
  744. m_register_index = (m_modrm.m_rm >> 3) & 7;
  745. } else {
  746. if (has_sub_op())
  747. m_register_index = m_sub_op & 7;
  748. else
  749. m_register_index = m_op & 7;
  750. }
  751. bool has_slash = m_descriptor->format == MultibyteWithSlash;
  752. if (has_slash) {
  753. m_descriptor = &m_descriptor->slashes[slash()];
  754. if ((rm() & 0xc0) == 0xc0 && m_descriptor->slashes)
  755. m_descriptor = &m_descriptor->slashes[rm() & 7];
  756. }
  757. if (!m_descriptor->mnemonic) {
  758. if (has_sub_op()) {
  759. if (has_slash)
  760. warnln("Instruction {:02X} {:02X} /{} not understood", m_op, m_sub_op, slash());
  761. else
  762. warnln("Instruction {:02X} {:02X} not understood", m_op, m_sub_op);
  763. } else {
  764. if (has_slash)
  765. warnln("Instruction {:02X} /{} not understood", m_op, slash());
  766. else
  767. warnln("Instruction {:02X} not understood", m_op);
  768. }
  769. m_descriptor = nullptr;
  770. return;
  771. }
  772. auto imm1_bytes = m_descriptor->imm1_bytes_for_address_size(m_a32);
  773. auto imm2_bytes = m_descriptor->imm2_bytes_for_address_size(m_a32);
  774. // Consume immediates if present.
  775. switch (imm2_bytes) {
  776. case 1:
  777. m_imm2 = stream.read8();
  778. break;
  779. case 2:
  780. m_imm2 = stream.read16();
  781. break;
  782. case 4:
  783. m_imm2 = stream.read32();
  784. break;
  785. default:
  786. VERIFY(imm2_bytes == 0);
  787. break;
  788. }
  789. switch (imm1_bytes) {
  790. case 1:
  791. m_imm1 = stream.read8();
  792. break;
  793. case 2:
  794. m_imm1 = stream.read16();
  795. break;
  796. case 4:
  797. m_imm1 = stream.read32();
  798. break;
  799. default:
  800. VERIFY(imm1_bytes == 0);
  801. break;
  802. }
  803. m_extra_bytes = prefix_bytes + imm1_bytes + imm2_bytes;
  804. #ifdef DISALLOW_INVALID_LOCK_PREFIX
  805. if (m_has_lock_prefix && !m_descriptor->lock_prefix_allowed) {
  806. warnln("Instruction not allowed with LOCK prefix, this will raise #UD");
  807. m_descriptor = nullptr;
  808. }
  809. #endif
  810. }
  811. template<typename InstructionStreamType>
  812. ALWAYS_INLINE void MemoryOrRegisterReference::decode(InstructionStreamType& stream, bool a32)
  813. {
  814. m_rm = stream.read8();
  815. if (a32) {
  816. decode32(stream);
  817. switch (m_displacement_bytes) {
  818. case 0:
  819. break;
  820. case 1:
  821. m_displacement32 = sign_extended_to<u32>(stream.read8());
  822. break;
  823. case 4:
  824. m_displacement32 = stream.read32();
  825. break;
  826. default:
  827. VERIFY_NOT_REACHED();
  828. break;
  829. }
  830. } else {
  831. decode16(stream);
  832. switch (m_displacement_bytes) {
  833. case 0:
  834. break;
  835. case 1:
  836. m_displacement16 = sign_extended_to<u16>(stream.read8());
  837. break;
  838. case 2:
  839. m_displacement16 = stream.read16();
  840. break;
  841. default:
  842. VERIFY_NOT_REACHED();
  843. break;
  844. }
  845. }
  846. }
  847. template<typename InstructionStreamType>
  848. ALWAYS_INLINE void MemoryOrRegisterReference::decode16(InstructionStreamType&)
  849. {
  850. switch (m_rm & 0xc0) {
  851. case 0:
  852. if ((m_rm & 0x07) == 6)
  853. m_displacement_bytes = 2;
  854. else
  855. VERIFY(m_displacement_bytes == 0);
  856. break;
  857. case 0x40:
  858. m_displacement_bytes = 1;
  859. break;
  860. case 0x80:
  861. m_displacement_bytes = 2;
  862. break;
  863. case 0xc0:
  864. m_register_index = m_rm & 7;
  865. break;
  866. }
  867. }
  868. template<typename InstructionStreamType>
  869. ALWAYS_INLINE void MemoryOrRegisterReference::decode32(InstructionStreamType& stream)
  870. {
  871. switch (m_rm & 0xc0) {
  872. case 0:
  873. if ((m_rm & 0x07) == 5)
  874. m_displacement_bytes = 4;
  875. break;
  876. case 0x40:
  877. m_displacement_bytes = 1;
  878. break;
  879. case 0x80:
  880. m_displacement_bytes = 4;
  881. break;
  882. case 0xc0:
  883. m_register_index = m_rm & 7;
  884. return;
  885. }
  886. m_has_sib = (m_rm & 0x07) == 4;
  887. if (m_has_sib) {
  888. m_sib = stream.read8();
  889. if ((m_sib & 0x07) == 5) {
  890. switch ((m_rm >> 6) & 0x03) {
  891. case 0:
  892. m_displacement_bytes = 4;
  893. break;
  894. case 1:
  895. m_displacement_bytes = 1;
  896. break;
  897. case 2:
  898. m_displacement_bytes = 4;
  899. break;
  900. default:
  901. VERIFY_NOT_REACHED();
  902. break;
  903. }
  904. }
  905. }
  906. }
  907. template<typename CPU>
  908. ALWAYS_INLINE LogicalAddress MemoryOrRegisterReference::resolve(const CPU& cpu, const Instruction& insn)
  909. {
  910. if (insn.a32())
  911. return resolve32(cpu, insn.segment_prefix());
  912. return resolve16(cpu, insn.segment_prefix());
  913. }
  914. }