From 6232e8b1daf7067cb2e8065687530d5f88ecb46d Mon Sep 17 00:00:00 2001 From: iximeow Date: Fri, 15 Jan 2021 18:40:31 -0800 Subject: support xchg AX/reg --- CHANGELOG | 1 + src/long_mode/mod.rs | 14 ++++++++++++++ src/protected_mode/mod.rs | 11 +++++++++++ test/long_mode/mod.rs | 8 ++++++++ test/protected_mode/mod.rs | 7 +++++++ 5 files changed, 41 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index c608941..0a707eb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ - `rdpkru` and `wrpkru` were incorrectly decoded when modrm bits were not `11` * small performance tweaks. read_imm_signed is now inline(always) and some pre-decode initialization is a bit better-packed +* `xchg {r,e,}ax, reg` was not supported! it's supported now. ## 0.1.4 * [long mode only]: fix decoding of rex-prefixed modrm+sib operands selecting index 0b100 and base 0b101 diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index f9be9ab..909157b 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -6079,6 +6079,20 @@ fn read_operands>(decoder: &InstDecoder, mut bytes_iter: T, } 1 => { // Zv_AX + let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, instruction.prefixes); + let bank = if opwidth == 4 { + RegisterBank::D + } else if opwidth == 2 { + RegisterBank::W + } else { + RegisterBank::Q + }; + instruction.modrm_rrr = + RegSpec::from_parts(0, instruction.prefixes.rex().b(), bank); + instruction.operands[1] = OperandSpec::RegMMM; + instruction.modrm_mmm = + RegSpec::from_parts(reg, instruction.prefixes.rex().b(), bank); + instruction.operand_count = 2; } 2 => { // these are Zb_Ib_R diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 9327f64..6394de0 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -5933,6 +5933,17 @@ fn read_operands>(decoder: &InstDecoder, mut bytes_iter: T, } 1 => { // Zv_AX + let bank = if !instruction.prefixes.operand_size() { + RegisterBank::D + } else { + RegisterBank::W + }; + instruction.modrm_rrr = + RegSpec::from_parts(0, bank); + instruction.operands[1] = OperandSpec::RegMMM; + instruction.modrm_mmm = + RegSpec::from_parts(reg, bank); + instruction.operand_count = 2; } 2 => { // these are Zb_Ib_R diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index 0830c2d..c3933ab 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -1137,6 +1137,14 @@ fn test_mov() { } #[test] +fn test_xchg() { + test_display(&[0x90], "nop"); + test_display(&[0x91], "xchg eax, ecx"); + test_display(&[0x4f, 0x91], "xchg r8, r9"); + test_display(&[0x66, 0x91], "xchg ax, cx"); +} + +#[test] fn test_stack() { test_display(&[0x66, 0x41, 0x50], "push r8w"); } diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index e3c7975..88cf7ea 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -1030,6 +1030,13 @@ fn test_mov() { } #[test] +fn test_xchg() { + test_display(&[0x90], "nop"); + test_display(&[0x91], "xchg eax, ecx"); + test_display(&[0x66, 0x91], "xchg ax, cx"); +} + +#[test] fn test_stack() { test_display(&[0x66, 0x50], "push ax"); } -- cgit v1.1