diff options
author | iximeow <me@iximeow.net> | 2023-07-24 06:41:02 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2023-07-24 06:41:02 -0700 |
commit | ab51fd1b2c7cf1b7bb6f84c5b07e06245f6b3d99 (patch) | |
tree | 80b2a81dfb805c49a5c3a43296835bd5195e422a | |
parent | 855fa08f1d2f4bc405a1cfc205b5e9321dd4ebf5 (diff) |
fix handling of lar/lsl source register
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | src/long_mode/mod.rs | 33 | ||||
-rw-r--r-- | src/protected_mode/mod.rs | 37 | ||||
-rw-r--r-- | src/real_mode/mod.rs | 37 | ||||
-rw-r--r-- | test/long_mode/mod.rs | 18 | ||||
-rw-r--r-- | test/protected_mode/mod.rs | 10 | ||||
-rw-r--r-- | test/real_mode/mod.rs | 10 | ||||
-rw-r--r-- | todo_notes | 1 |
8 files changed, 119 insertions, 32 deletions
@@ -25,6 +25,11 @@ encodings and bitness * in some cases, instructions loading a single-precision float reported 8-byte loads * in some cases, instructions loading a double-precision float reported 4-byte loads +* fix register sizes for lar/lsl + * 16 bits are read from the source register, but x86 docs state that the + source register is written as 16-bit, 32-bit, or 64-bit, as prefixes dictate. + memory is always written as `word [addr]`, which was correct before and + remains the case. ## 1.1.5 * fix several typos across crate docs - thank you Bruce! (aka github user waywardmonkeys) diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 71b2373..14f782c 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -5037,6 +5037,7 @@ enum OperandCase { AX_Ib, Ib_AL, Ib_AX, + Gv_Ew_LAR, Gv_Ew_LSL, Gdq_Ev, Gv_Ev_Ib, @@ -5374,6 +5375,7 @@ enum OperandCode { Zv_Ivq_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Ivq_R, 7).bits(), Gv_Eb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Eb).bits(), Gv_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew).bits(), + Gv_Ew_LAR = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LAR).bits(), Gv_Ew_LSL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(), Gdq_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ed).bits(), Gd_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ed).bits(), @@ -8009,11 +8011,30 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; }, + OperandCase::Gv_Ew_LAR => { + instruction.operands[1] = mem_oper; + // lar is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword/qword for + // larger modes even though the upper 16 bits would be ignored. + // + // so the registers are correct by the time we're here, we might just need to override + // mem size as well. + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = 2; + } + instruction.regs[0].bank = self.vqp_size(); + }, OperandCase::Gv_Ew_LSL => { instruction.operands[1] = mem_oper; - // lsl is weird. the full register width is written, but only the low 16 bits are used. + // lsl is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword for larger + // modes even though the upper 16 bits would be ignored. if instruction.operands[1] == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::D; + if instruction.regs[1].bank == RegisterBank::Q { + instruction.regs[1].bank = RegisterBank::D; + } } else { instruction.mem_size = 2; } @@ -10869,7 +10890,7 @@ fn read_modrm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11145,7 +11166,7 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ const REP_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11421,7 +11442,7 @@ const REP_0F_CODES: [OpcodeRecord; 256] = [ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11694,7 +11715,7 @@ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ const NORMAL_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index f4e355f..200e12f 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -4936,6 +4936,7 @@ enum OperandCase { AX_Ib, Ib_AL, Ib_AX, + Gv_Ew_LAR, Gv_Ew_LSL, // Gdq_Ev, Gd_Ev, @@ -5266,6 +5267,7 @@ enum OperandCode { Zv_Iv_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 7).bits(), Gv_Eb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Eb).bits(), Gv_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew).bits(), + Gv_Ew_LAR = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LAR).bits(), Gv_Ew_LSL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(), // Gdq_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ed).bits(), Gd_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ed).bits(), @@ -7940,12 +7942,31 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; }, - OperandCase::Gv_Ew_LSL => { + OperandCase::Gv_Ew_LAR => { instruction.operands[1] = mem_oper; - // lsl is weird. the full register width is written, but only the low 16 bits are used. - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::D; + // lar is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword/qword for + // larger modes even though the upper 16 bits would be ignored. + // + // so the registers are correct by the time we're here, we might just need to override + // mem size as well. + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = 2; + } + instruction.regs[0].bank = if instruction.prefixes.operand_size() { + RegisterBank::W } else { + RegisterBank::D + }; + }, + OperandCase::Gv_Ew_LSL => { + instruction.operands[1] = mem_oper; + // lsl is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword for larger + // modes even though the upper 16 bits would be ignored. + if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 2; } instruction.regs[0].bank = if instruction.prefixes.operand_size() { @@ -10743,7 +10764,7 @@ fn read_modrm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11019,7 +11040,7 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ const REP_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11295,7 +11316,7 @@ const REP_0F_CODES: [OpcodeRecord; 256] = [ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11568,7 +11589,7 @@ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ const NORMAL_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 924f46c..6765c1e 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -4936,6 +4936,7 @@ enum OperandCase { AX_Ib, Ib_AL, Ib_AX, + Gv_Ew_LAR, Gv_Ew_LSL, // Gdq_Ev, Gd_Ev, @@ -5266,6 +5267,7 @@ enum OperandCode { Zv_Iv_R7 = OperandCodeBuilder::new().op0_is_rrr_and_Z_operand(ZOperandCategory::Zv_Iv_R, 7).bits(), Gv_Eb = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Eb).bits(), Gv_Ew = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew).bits(), + Gv_Ew_LAR = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LAR).bits(), Gv_Ew_LSL = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gv_Ew_LSL).bits(), // Gdq_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gdq_Ed).bits(), Gd_Ed = OperandCodeBuilder::new().read_E().operand_case(OperandCase::Gd_Ed).bits(), @@ -7946,12 +7948,31 @@ fn read_operands< instruction.regs[1].bank = RegisterBank::MM; instruction.regs[1].num &= 0b111; }, - OperandCase::Gv_Ew_LSL => { + OperandCase::Gv_Ew_LAR => { instruction.operands[1] = mem_oper; - // lsl is weird. the full register width is written, but only the low 16 bits are used. - if instruction.operands[1] == OperandSpec::RegMMM { - instruction.regs[1].bank = RegisterBank::W; + // lar is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword/qword for + // larger modes even though the upper 16 bits would be ignored. + // + // so the registers are correct by the time we're here, we might just need to override + // mem size as well. + if instruction.operands[1] != OperandSpec::RegMMM { + instruction.mem_size = 2; + } + instruction.regs[0].bank = if !instruction.prefixes.operand_size() { + RegisterBank::W } else { + RegisterBank::D + }; + }, + OperandCase::Gv_Ew_LSL => { + instruction.operands[1] = mem_oper; + // lsl is weird. a segment selector is taken from the source register, which means + // either we read the low 16-bits of a register or read 16 bits from a memory operand. + // for whatever reason, the intel manual writes a source register as a dword for larger + // modes even though the upper 16 bits would be ignored. + if instruction.operands[1] != OperandSpec::RegMMM { instruction.mem_size = 2; } instruction.regs[0].bank = if !instruction.prefixes.operand_size() { @@ -10755,7 +10776,7 @@ fn read_modrm<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11031,7 +11052,7 @@ const REPNZ_0F_CODES: [OpcodeRecord; 256] = [ const REP_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11307,7 +11328,7 @@ const REP_0F_CODES: [OpcodeRecord; 256] = [ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), @@ -11580,7 +11601,7 @@ const OPERAND_SIZE_0F_CODES: [OpcodeRecord; 256] = [ const NORMAL_0F_CODES: [OpcodeRecord; 256] = [ OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f00), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::ModRM_0x0f01), - OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew), + OpcodeRecord::new(Interpretation::Instruction(Opcode::LAR), OperandCode::Gv_Ew_LAR), OpcodeRecord::new(Interpretation::Instruction(Opcode::LSL), OperandCode::Gv_Ew_LSL), OpcodeRecord::new(Interpretation::Instruction(Opcode::Invalid), OperandCode::Nothing), OpcodeRecord::new(Interpretation::Instruction(Opcode::SYSCALL), OperandCode::Nothing), diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs index 9144dbe..3e6b700 100644 --- a/test/long_mode/mod.rs +++ b/test/long_mode/mod.rs @@ -2567,12 +2567,20 @@ fn strange_prefixing() { #[test] fn prefixed_0f() { - test_display(&[0x0f, 0x02, 0xc0], "lar eax, ax"); - test_display(&[0x48, 0x0f, 0x02, 0xc0], "lar rax, ax"); - test_display(&[0x0f, 0x03, 0xc0], "lsl eax, eax"); - // capstone says `lsl rax, rax`, but xed says `rax, eax`. intel docs also say second reg should + test_display(&[0x0f, 0x02, 0x01], "lar eax, word [rcx]"); + test_display(&[0x0f, 0x02, 0xc1], "lar eax, ecx"); + test_display(&[0x4f, 0x0f, 0x02, 0x01], "lar r8, word [r9]"); + test_display(&[0x4f, 0x0f, 0x02, 0xc1], "lar r8, r9"); + test_display(&[0x66, 0x0f, 0x02, 0x01], "lar ax, word [rcx]"); + test_display(&[0x66, 0x0f, 0x02, 0xc1], "lar ax, cx"); + test_display(&[0x0f, 0x03, 0x01], "lsl eax, word [rcx]"); + test_display(&[0x0f, 0x03, 0xc1], "lsl eax, ecx"); + test_display(&[0x48, 0x0f, 0x03, 0x01], "lsl rax, word [rcx]"); + // capstone says `lsl rax, rcx`, but xed says `rax, ecx`. intel docs also say second reg should // be dword. - test_display(&[0x48, 0x0f, 0x03, 0xc0], "lsl rax, eax"); + test_display(&[0x48, 0x0f, 0x03, 0xc1], "lsl rax, ecx"); + test_display(&[0x66, 0x0f, 0x03, 0x01], "lsl ax, word [rcx]"); + test_display(&[0x66, 0x0f, 0x03, 0xc1], "lsl ax, cx"); test_display(&[0x0f, 0x05], "syscall"); test_display(&[0x48, 0x0f, 0x05], "syscall"); test_display(&[0x66, 0x0f, 0x05], "syscall"); diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs index 5229617..85d92ce 100644 --- a/test/protected_mode/mod.rs +++ b/test/protected_mode/mod.rs @@ -2270,8 +2270,14 @@ fn strange_prefixing() { #[test] fn prefixed_0f() { - test_display(&[0x0f, 0x02, 0xc0], "lar eax, ax"); - test_display(&[0x0f, 0x03, 0xc0], "lsl eax, eax"); + test_display(&[0x0f, 0x02, 0x01], "lar eax, word [ecx]"); + test_display(&[0x0f, 0x02, 0xc1], "lar eax, ecx"); + test_display(&[0x66, 0x0f, 0x02, 0x01], "lar ax, word [ecx]"); + test_display(&[0x66, 0x0f, 0x02, 0xc1], "lar ax, cx"); + test_display(&[0x0f, 0x03, 0x01], "lsl eax, word [ecx]"); + test_display(&[0x0f, 0x03, 0xc1], "lsl eax, ecx"); + test_display(&[0x66, 0x0f, 0x03, 0x01], "lsl ax, word [ecx]"); + test_display(&[0x66, 0x0f, 0x03, 0xc1], "lsl ax, cx"); test_display(&[0x0f, 0x05], "syscall"); test_display(&[0x66, 0x0f, 0x05], "syscall"); test_display(&[0x0f, 0x06], "clts"); diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs index 7cf5fc2..2ae52d8 100644 --- a/test/real_mode/mod.rs +++ b/test/real_mode/mod.rs @@ -162,8 +162,10 @@ fn test_real_mode() { test_display(&[0x0f, 0x01, 0xfb], "mwaitx"); test_display(&[0x0f, 0x01, 0xfc], "clzero"); test_display(&[0x0f, 0x01, 0xfd], "rdpru ecx"); - test_display(&[0x0f, 0x02, 0xc0], "lar ax, ax"); - test_display(&[0x0f, 0x03, 0xc0], "lsl ax, ax"); + test_display(&[0x0f, 0x02, 0x01], "lar ax, word [bx + di * 1]"); + test_display(&[0x0f, 0x02, 0xc1], "lar ax, cx"); + test_display(&[0x0f, 0x03, 0x01], "lsl ax, word [bx + di * 1]"); + test_display(&[0x0f, 0x03, 0xc1], "lsl ax, cx"); test_display(&[0x0f, 0x05], "syscall"); test_display(&[0x0f, 0x06], "clts"); test_display(&[0x0f, 0x07], "sysret"); @@ -16715,6 +16717,10 @@ fn test_real_mode() { test_display(&[0x65, 0x89, 0x04], "mov word gs:[si], ax"); test_display(&[0x65, 0xf0, 0x87, 0x0f], "lock xchg word gs:[bx], cx"); test_display(&[0x66, 0x0f, 0x01, 0xd8], "vmrun ax"); + test_display(&[0x66, 0x0f, 0x02, 0x01], "lar eax, word [bx + di * 1]"); + test_display(&[0x66, 0x0f, 0x02, 0xc1], "lar eax, ecx"); + test_display(&[0x66, 0x0f, 0x03, 0x01], "lsl eax, word [bx + di * 1]"); + test_display(&[0x66, 0x0f, 0x03, 0xc1], "lsl eax, ecx"); test_display(&[0x66, 0x0f, 0x05], "syscall"); test_display(&[0x66, 0x0f, 0x0f, 0xc6, 0xb7], "pmulhrw mm0, mm6"); test_display(&[0x66, 0x0f, 0x10, 0xc0], "movupd xmm0, xmm0"); diff --git a/todo_notes b/todo_notes deleted file mode 100644 index f0785d7..0000000 --- a/todo_notes +++ /dev/null @@ -1 +0,0 @@ -lsl seems just... wrong. check alternate prefixes in 32-/61-bit |