From 986c99873d0ebe9b02f233ce52ec607834417310 Mon Sep 17 00:00:00 2001 From: Marco Thomas Date: Wed, 14 May 2025 12:12:57 +0900 Subject: [PATCH] ft: implement Group 2 instructions --- src/disasm.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++ src/instructions.rs | 15 +++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/disasm.rs b/src/disasm.rs index b6844aa..cd6c6c5 100644 --- a/src/disasm.rs +++ b/src/disasm.rs @@ -234,6 +234,42 @@ impl Disassembler { } } + /// Match the modrm reg bits to the GPR2 mnemonics. + /// Group 2 only has a single operand, the other one is either a constant + /// 1 (not present in the binary) or the CL register. + /// This function assumes the operand to be 1 + pub fn modrm_reg_to_grp2_1(reg: u8, target: ModRmTarget) -> Mnemonic { + match reg { + 0b000 => Mnemonic::ROL_b(target, 1), + 0b001 => Mnemonic::ROR_b(target, 1), + 0b010 => Mnemonic::RCL_b(target, 1), + 0b011 => Mnemonic::RCR_b(target, 1), + 0b100 => Mnemonic::SHL_b(target, 1), + 0b101 => Mnemonic::SHR_b(target, 1), + 0b110 => Mnemonic::SAR_b(target, 1), + 0b111 => Mnemonic::SAR_b(target, 1), + _ => panic!("Illegal Group 2 mnemonic"), + } + } + + /// Match the modrm reg bits to the GPR2 mnemonics. + /// Group 2 only has a single operand, the other one is either a constant + /// 1 (not present in the binary) or the CL register. + /// This function assumes the operand to be CL register. + pub fn modrm_reg_to_grp2_cl(reg: u8, target: ModRmTarget) -> Mnemonic { + match reg { + 0b000 => Mnemonic::ROL_fromReg(target, Register::CL), + 0b001 => Mnemonic::ROR_fromReg(target, Register::CL), + 0b010 => Mnemonic::RCL_fromReg(target, Register::CL), + 0b011 => Mnemonic::RCR_fromReg(target, Register::CL), + 0b100 => Mnemonic::SHL_fromReg(target, Register::CL), + 0b101 => Mnemonic::SHR_fromReg(target, Register::CL), + 0b110 => Mnemonic::SAR_fromReg(target, Register::CL), + 0b111 => Mnemonic::SAR_fromReg(target, Register::CL), + _ => panic!("Illegal Group 2 mnemonic"), + } + } + /// Match the modrm reg bits to the GPR3a/b mnemonics. /// Group 3 only has a single operand, which is the ModRmTarget selected /// by modrm bits. @@ -523,6 +559,24 @@ impl Disassembler { 0xCD => Mnemonic::INT(self.parse_byte()), + // Group 2 + 0xD0 => { + let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); + Self::modrm_reg_to_grp2_1(reg, target) + } + 0xD1 => { + let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); + Self::modrm_reg_to_grp2_1(reg, target) + } + 0xD2 => { + let (target, reg) = self.parse_modrm_byte(Operand::Byte(0)); + Self::modrm_reg_to_grp2_cl(reg, target) + } + 0xD3 => { + let (target, reg) = self.parse_modrm_byte(Operand::Word(0)); + Self::modrm_reg_to_grp2_cl(reg, target) + } + 0xE8 => Mnemonic::CALL_v(self.parse_word()), 0xE9 => Mnemonic::JMP_v(self.parse_word()), diff --git a/src/instructions.rs b/src/instructions.rs index d69c534..ac30ebb 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -241,6 +241,21 @@ pub enum Mnemonic { IDIV(ModRmTarget), // HALT HLT, + // Shift and Rotate + ROL_b(ModRmTarget, Byte), + ROR_b(ModRmTarget, Byte), + RCL_b(ModRmTarget, Byte), + RCR_b(ModRmTarget, Byte), + SHL_b(ModRmTarget, Byte), + SHR_b(ModRmTarget, Byte), + SAR_b(ModRmTarget, Byte), + ROL_fromReg(ModRmTarget, Register), + ROR_fromReg(ModRmTarget, Register), + RCL_fromReg(ModRmTarget, Register), + RCR_fromReg(ModRmTarget, Register), + SHL_fromReg(ModRmTarget, Register), + SHR_fromReg(ModRmTarget, Register), + SAR_fromReg(ModRmTarget, Register), // INT INT(Byte), }