diff options
| author | iximeow <me@iximeow.net> | 2020-08-08 22:46:46 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-08-09 01:39:01 -0700 | 
| commit | 7b82d7ef21fea44c44eff9524f2dd5f31b979fda (patch) | |
| tree | cd3bd9cf53a73c811a9699746f6dc87278d1f235 /src/long_mode | |
| parent | 6e3a3f8323266871ed6e3fbfd161e0b766516cc2 (diff) | |
try to special case immediates a bit
Diffstat (limited to 'src/long_mode')
| -rw-r--r-- | src/long_mode/mod.rs | 104 | 
1 files changed, 55 insertions, 49 deletions
diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 6b0d51c..ea92211 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -3394,12 +3394,12 @@ impl OperandCodeBuilder {      #[allow(unused)]      fn special_case_handler_index(&self) -> u16 { -        self.bits & 0x1ff +        self.bits & 0xff      }      const fn special_case(mut self, case: u16) -> Self {          // leave 0x4000 unset -        self.bits |= case & 0x1ff; +        self.bits |= case & 0xff;          self      } @@ -3470,6 +3470,28 @@ impl OperandCodeBuilder {      const fn is_only_modrm_operands(&self) -> bool {          self.bits & 0x0200 != 0      } + +    // WHEN AN IMMEDIATE IS PRESENT, THERE ARE ONLY 0x1F ALLOWED SPECIAL CASES. +    // WHEN NO IMMEDIATE IS PRESENT, THERE ARE 0xFF ALLOWED SPECIAL CASES. +    // SIZE IS DECIDED BY THE FOLLOWING TABLE: +    // 0: 1 BYTE +    // 1: 2 BYTES +    // 2: 4 BYTES +    // 4: 8 BYTES +    const fn with_imm(mut self, only_imm: bool, size: u8) -> Self { +        self.bits |= 0x100; +        self.bits |= (size as u16) << 5; +        self.bits |= (only_imm as u16) << 7; +        self +    } + +    fn has_imm(&self) -> Option<(bool, u8)> { +        if self.bits & 0x100 != 0 { +            Some(((self.bits & 0x80) != 0, (self.bits as u8 >> 5) & 3)) +        } else { +            None +        } +    }  }  #[allow(non_camel_case_types)] @@ -3510,18 +3532,18 @@ pub enum OperandCode {      Fw,      I_1,      I_3, -    Ib, -    Ibs,      Ivs,      Iw,      Iw_Ib, -    Jvds,      Ob_AL,      Ov_AX,      Sw_Ew,      Yb_AL,      Yb_Xb,      Yv_AX, +    Ib = OperandCodeBuilder::new().with_imm(false, 0).special_case(0).bits(), +    Ibs = OperandCodeBuilder::new().with_imm(true, 0).special_case(1).bits(), +    Jvds = OperandCodeBuilder::new().with_imm(true, 2).special_case(0).bits(),      Yv_Xv = OperandCodeBuilder::new().special_case(50).bits(),      x87_d8 = OperandCodeBuilder::new().special_case(31).bits(), @@ -3540,10 +3562,10 @@ pub enum OperandCode {          .byte_operands()          .operand_case(20)          .bits(), -    AL_Ib = OperandCodeBuilder::new().special_case(40).bits(), -    AX_Ib = OperandCodeBuilder::new().special_case(41).bits(), -    Ib_AL = OperandCodeBuilder::new().special_case(42).bits(), -    Ib_AX = OperandCodeBuilder::new().special_case(43).bits(), +    AL_Ib = OperandCodeBuilder::new().special_case(2).with_imm(false, 0).bits(), +    AX_Ib = OperandCodeBuilder::new().special_case(3).with_imm(false, 0).bits(), +    Ib_AL = OperandCodeBuilder::new().special_case(4).with_imm(false, 0).bits(), +    Ib_AX = OperandCodeBuilder::new().special_case(5).with_imm(false, 0).bits(),      AX_DX = OperandCodeBuilder::new().special_case(44).bits(),      AL_DX = OperandCodeBuilder::new().special_case(45).bits(),      DX_AX = OperandCodeBuilder::new().special_case(46).bits(), @@ -3636,6 +3658,7 @@ pub enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() +        .with_imm(false, 0)          .byte_operands()          .operand_case(3)          .bits(), @@ -3643,6 +3666,7 @@ pub enum OperandCode {          .read_modrm()          .set_embedded_instructions()          .read_E() +        .with_imm(false, 0)          .operand_case(3)          .bits(),      // this would be Eb_Ivs, 0x8e @@ -3748,12 +3772,12 @@ pub enum OperandCode {      Gdq_Ed = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(6).bits(),      Gdq_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(10).bits(),      Mdq_Gdq = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(11).bits(), -    G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(2).bits(), +    G_E_mm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).reg_mem().operand_case(2).bits(),      G_E_xmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(8).bits(),      AL_Ob = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(0).bits(),      AL_Xb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(1).bits(),      AX_Ov = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(3).bits(), -    AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().byte_operands().operand_case(0).bits(), +    AL_Ibs = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().with_imm(false, 0).byte_operands().operand_case(0).bits(),      AX_Ivd = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().operand_case(9).bits(),      Eb_Gb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().mem_reg().bits(), @@ -3761,7 +3785,7 @@ pub enum OperandCode {      Gb_Eb = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().only_modrm_operands().reg_mem().bits(),      Gv_Ev = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().bits(),      Gv_M = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().only_modrm_operands().reg_mem().operand_case(25).bits(), -    Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().byte_operands().reg_mem().operand_case(1).bits(), +    Gb_Eb_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().with_imm(false, 0).byte_operands().reg_mem().operand_case(1).bits(),      Gv_Ev_Iv = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_E().reg_mem().operand_case(1).bits(),      Rv_Gmm_Ib = OperandCodeBuilder::new().op0_is_rrr_and_embedded_instructions().read_modrm().read_E().reg_mem().operand_case(25).bits(),      // gap, 0x9a @@ -5676,7 +5700,6 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,                          instruction.imm =                              read_imm_ivq(&mut bytes_iter, opwidth, length)?;                          instruction.operands[1] = match opwidth { -                            1 => OperandSpec::ImmI8,                              2 => OperandSpec::ImmI16,                              4 => OperandSpec::ImmI32,                              8 => OperandSpec::ImmI64, @@ -5734,16 +5757,25 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,          instruction.operands[1] = mem_oper;      } +    if let Some((only_imm, immsz)) = operand_code.has_imm() { +        instruction.imm = +            read_imm_signed(&mut bytes_iter, 1 << immsz, length)? as u64; +        if only_imm { +            if immsz == 0 { +                instruction.operands[0] = OperandSpec::ImmI8; +            } else { +                instruction.operands[0] = OperandSpec::ImmI32; +            } +            instruction.operand_count = 1; +            return Ok(()); +        } +    } +      if operand_code.is_only_modrm_operands() {          if !operand_code.has_reg_mem() {              instruction.operands[0] = mem_oper;              instruction.operands[1] = OperandSpec::RegRRR;          }; -    } else if operand_code.bits() == OperandCode::Ibs as u16 { -        instruction.imm = -            read_imm_signed(&mut bytes_iter, 1, length)? as u64; -        instruction.operands[0] = OperandSpec::ImmI8; -        instruction.operand_count = 1;      } else {          let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) };      match operand_code { @@ -5806,14 +5838,17 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;          } -        _op @ OperandCode::ModRM_0x80_Eb_Ib | +        _op @ OperandCode::ModRM_0x80_Eb_Ib => { +            instruction.operands[0] = mem_oper; +            instruction.operands[1] = OperandSpec::ImmI8; +            instruction.operand_count = 2; +        }          _op @ OperandCode::ModRM_0x81_Ev_Ivs => {              instruction.operands[0] = mem_oper;              let numwidth = if opwidth == 8 { 4 } else { opwidth };              instruction.imm = read_imm_signed(&mut bytes_iter, numwidth, length)? as u64;              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = match opwidth { -                1 => OperandSpec::ImmI8,                  2 => OperandSpec::ImmI16,                  4 => OperandSpec::ImmI32,                  8 => OperandSpec::ImmI64, @@ -6107,9 +6142,6 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,          },          OperandCode::G_E_mm_Ib => {              instruction.modrm_rrr = RegSpec { bank: RegisterBank::MM, num: (modrm >> 3) & 7 }; -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u8 as u64; -            *length += 1;              if instruction.operands[1] == OperandSpec::RegMMM {                  instruction.modrm_mmm.bank = RegisterBank::MM;              } @@ -6135,8 +6167,6 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,          OperandCode::AL_Ibs => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_imm_signed(&mut bytes_iter, 1, length)? as u64;              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          } @@ -6170,20 +6200,10 @@ fn read_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T,          OperandCode::ModRM_0x83_Ev_Ibs => {              instruction.operands[0] = mem_oper;              instruction.opcode = base_opcode_map((modrm >> 3) & 7); -            instruction.imm = read_imm_signed(&mut bytes_iter, 1, length)? as u64;              instruction.operands[1] = OperandSpec::ImmI8;              instruction.operand_count = 2;          }, -        OperandCode::Jvds => { -            let offset = read_num(&mut bytes_iter, 4)?; -            *length += 4; -            instruction.imm = offset; -            instruction.operand_count = 1; -            instruction.operands[0] = OperandSpec::ImmI32; -        }          OperandCode::Gb_Eb_Ib => { -            instruction.imm = -                read_imm_signed(&mut bytes_iter, 1, length)? as u64;              instruction.operands[2] = OperandSpec::ImmI8;              instruction.operand_count = 3;          } @@ -7423,8 +7443,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              }          }          OperandCode::Ib => { -            instruction.imm = -                read_imm_unsigned(&mut bytes_iter, 1, length)?;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operand_count = 1;          } @@ -7833,9 +7851,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::AL_Ib => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u64; -            *length += 1;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8;              instruction.operand_count = 2; @@ -7847,9 +7862,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              } else {                 RegSpec::ax()              }; -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u64; -            *length += 1;              instruction.operands[0] = OperandSpec::RegRRR;              instruction.operands[1] = OperandSpec::ImmU8;              instruction.operand_count = 2; @@ -7857,9 +7869,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter          OperandCode::Ib_AL => {              instruction.modrm_rrr =                  RegSpec::al(); -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u64; -            *length += 1;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2; @@ -7871,9 +7880,6 @@ fn unlikely_operands<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter              } else {                  RegSpec::ax()              }; -            instruction.imm = -                read_num(&mut bytes_iter, 1)? as u64; -            *length += 1;              instruction.operands[0] = OperandSpec::ImmU8;              instruction.operands[1] = OperandSpec::RegRRR;              instruction.operand_count = 2;  | 
