diff options
| author | iximeow <me@iximeow.net> | 2019-10-20 21:54:37 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 | 
| commit | 74fa418fa25e3a9416b0f11a7e67d3157ace3a5c (patch) | |
| tree | 18c444742e77cd6d562d9a1b9a5e2f2e13aa5035 /src | |
| parent | 69768de62afb8f87c5b2993518604dbe438b6a41 (diff) | |
normalize displacement-containing operands a little more
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 88 | 
1 files changed, 37 insertions, 51 deletions
| @@ -2226,7 +2226,7 @@ fn read_modrm_reg<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruct  #[allow(non_snake_case)]  fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, ()> {      let modbits = (modrm >> 6); -    let addr_width = if instr.prefixes.address_size() { 4 } else { 8 }; +    let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q };      let sibbyte = match bytes_iter.next() {          Some(b) => b,          None => { unsafe { unreachable_unchecked(); } } @@ -2247,9 +2247,9 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m              if modbits == 0b00 && !instr.prefixes.rex().x() {                  instr.disp = disp as u32 as u64; -                OperandSpec::RegDisp +                OperandSpec::DispU32              } else { -                let reg = RegSpec::gp_from_parts(0b100, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +                let reg = RegSpec::from_parts(0b100, instr.prefixes.rex().x(), addr_width);                  instr.modrm_mmm = reg;                  if disp == 0 { @@ -2260,42 +2260,29 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m                  }              }          } else { -            instr.modrm_mmm = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); +            instr.modrm_mmm = RegSpec::from_parts(5, instr.prefixes.rex().b(), addr_width); -            instr.sib_index = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); -            instr.disp = disp as i64 as u64; +            instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width);              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale; -            match (scale, modbits, disp) { -                (0, 0b00, 0) => { -                    OperandSpec::Deref -                }, -                (0, 0b00, _) => { -                    OperandSpec::RegDisp -                }, -                (0, _, 0) => { -                    OperandSpec::RegIndexBase -                }, -                (0, _, _) => { -                    OperandSpec::RegIndexBaseDisp -                }, -                (_, 0b00, 0) => { -                    OperandSpec::RegScale -                }, -                (_, 0b00, _) => { +            if disp == 0 { +                if modbits == 0 {                      OperandSpec::RegScaleDisp -                }, -                (_, _, 0) => { -                    OperandSpec::RegIndexBaseScale -                }, -                (_, _, _) => { +                } else {                      OperandSpec::RegIndexBaseScaleDisp                  } +            } else { +                instr.disp = disp as i64 as u64; +                if modbits == 0 { +                    OperandSpec::RegScale +                } else { +                    OperandSpec::RegIndexBaseScale +                }              }          }      } else { -        instr.modrm_mmm = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); +        instr.modrm_mmm = RegSpec::from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width);          let disp = if modbits == 0b00 {              0 @@ -2304,30 +2291,23 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m          } else {              read_num(bytes_iter, 4, &mut instr.length)? as i32          }; -        instr.disp = disp as i64 as u64;          if ((sibbyte >> 3) & 7) == 0b100 {              if disp == 0 {                  OperandSpec::Deref              } else { +                instr.disp = disp as i64 as u64;                  OperandSpec::RegDisp              }          } else { -            instr.sib_index = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +            instr.sib_index = RegSpec::from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width);              let scale = 1u8 << (sibbyte >> 6);              instr.scale = scale;              if disp == 0 { -                if scale == 0 { -                    OperandSpec::RegIndexBase -                } else { -                    OperandSpec::RegIndexBaseScale -                } +                OperandSpec::RegIndexBaseScale              } else { -                if scale == 0 { -                    OperandSpec::RegIndexBaseDisp -                } else { -                    OperandSpec::RegIndexBaseScaleDisp -                } +                instr.disp = disp as i64 as u64; +                OperandSpec::RegIndexBaseScaleDisp              }          }      }; @@ -2337,11 +2317,9 @@ fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, m  #[allow(non_snake_case)]  fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8) -> Result<OperandSpec, ()> {      let modbits = (modrm >> 6); -    let addr_width = if instr.prefixes.address_size() { 4 } else { 8 }; +    let addr_width = if instr.prefixes.address_size() { RegisterBank::D } else { RegisterBank::Q };      let mmm = modrm & 7; -    let op_spec = if modbits == 0b11 { -        unsafe { unreachable_unchecked() } -    } else if mmm == 4 { +    let op_spec = if mmm == 4 {          return read_sib(bytes_iter, instr, modrm);  //         let (ss, index, base) = octets_of(sibbyte); @@ -2349,11 +2327,15 @@ fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod      } else if mmm == 5 && modbits == 0b00 {          let disp = read_num(bytes_iter, 4, &mut instr.length)? as i32;          instr.modrm_mmm = -            if addr_width == 8 { RegSpec::rip() } else { RegSpec::eip() }; -        instr.disp = disp as i64 as u64; -        OperandSpec::RegDisp +            if addr_width == RegisterBank::Q { RegSpec::rip() } else { RegSpec::eip() }; +        if disp == 0 { +            OperandSpec::Deref +        } else { +            instr.disp = disp as i64 as u64; +            OperandSpec::RegDisp +        }      } else { -        instr.modrm_mmm = RegSpec::gp_from_parts(mmm, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); +        instr.modrm_mmm = RegSpec::from_parts(mmm, instr.prefixes.rex().b(), addr_width);          if modbits == 0b00 {              OperandSpec::Deref @@ -2363,8 +2345,12 @@ fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, mod              } else {                  read_num(bytes_iter, 4, &mut instr.length)? as i32              }; -            instr.disp = disp as i64 as u64; -            OperandSpec::RegDisp +            if disp == 0 { +                OperandSpec::Deref +            } else { +                instr.disp = disp as i64 as u64; +                OperandSpec::RegDisp +            }          }      };      Ok(op_spec) | 
