diff options
| author | iximeow <me@iximeow.net> | 2019-06-30 12:56:08 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 | 
| commit | 2f9867664191bcfe0b7f7209de7463df30f775de (patch) | |
| tree | 6f8e5f2265b201ece2712c1db321b09a4db2511d /src | |
| parent | 49d2e670b56d43d079775f01a02f31555bb9da73 (diff) | |
add more x86 instructions (bt, btr, bts, bsf, ...) and xadd
Diffstat (limited to 'src')
| -rw-r--r-- | src/display.rs | 26 | ||||
| -rw-r--r-- | src/lib.rs | 153 | 
2 files changed, 174 insertions, 5 deletions
| diff --git a/src/display.rs b/src/display.rs index ca2b2f7..cbf3e61 100644 --- a/src/display.rs +++ b/src/display.rs @@ -183,6 +183,13 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {  impl fmt::Display for Opcode {      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {          match self { +            &Opcode::XADD => write!(f, "{}", "xadd"), +            &Opcode::BT => write!(f, "{}", "bt"), +            &Opcode::BTS => write!(f, "{}", "bts"), +            &Opcode::BTR => write!(f, "{}", "btr"), +            &Opcode::BTC => write!(f, "{}", "btc"), +            &Opcode::BSF => write!(f, "{}", "bsf"), +            &Opcode::BSR => write!(f, "{}", "bsr"),              &Opcode::MOVSS => write!(f, "{}", "movss"),              &Opcode::SQRTSS => write!(f, "{}", "sqrtss"),              &Opcode::ADDSS => write!(f, "{}", "addss"), @@ -350,8 +357,11 @@ impl fmt::Display for Opcode {              &Opcode::DIV => write!(f, "{}", "div"),              &Opcode::IDIV => write!(f, "{}", "idiv"),              &Opcode::CMPXCHG => write!(f, "{}", "cmpxchg"), +            &Opcode::MOVSX_b => write!(f, "{}", "movsx"), +            &Opcode::MOVSX_w => write!(f, "{}", "movsx"),              &Opcode::MOVZX_b => write!(f, "{}", "movzx"),              &Opcode::MOVZX_w => write!(f, "{}", "movzx"), +            &Opcode::MOVSXD => write!(f, "{}", "movsxd"),              &Opcode::MOVSX => write!(f, "{}", "movsx"),              &Opcode::SETO => write!(f, "{}", "seto"),              &Opcode::SETNO => write!(f, "{}", "setno"), @@ -387,11 +397,10 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {              Opcode::SUBSS |              Opcode::MULSS |              Opcode::DIVSS | -            Opcode::MOVDDUP | -            Opcode::MOVSLDUP |              Opcode::HADDPS |              Opcode::HSUBPS |              Opcode::ADDSUBPS | +            Opcode::XADD|              Opcode::DIV |              Opcode::IDIV |              Opcode::MUL | @@ -415,6 +424,12 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {              Opcode::ADD |              Opcode::ADC |              Opcode::SUB | +            Opcode::BT | +            Opcode::BTS | +            Opcode::BTR | +            Opcode::BTC | +            Opcode::BSF | +            Opcode::BSR |              Opcode::IMUL => { write!(out, "{}", colors.arithmetic_op(self)) }              Opcode::POPF |              Opcode::PUSHF | @@ -471,6 +486,8 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {              Opcode::STC |              Opcode::STI |              Opcode::STD | +            Opcode::MOVDDUP | +            Opcode::MOVSLDUP |              Opcode::MOV |              Opcode::MOVSD |              Opcode::CBW | @@ -482,9 +499,12 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {              Opcode::MOVS |              Opcode::INS |              Opcode::OUTS | +            Opcode::MOVSX_b | +            Opcode::MOVSX_w |              Opcode::MOVZX_b |              Opcode::MOVZX_w |              Opcode::MOVSX | +            Opcode::MOVSXD |              Opcode::XCHG |              Opcode::CMOVA |              Opcode::CMOVB | @@ -627,6 +647,7 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi              }          };          match self.opcode { +            Opcode::MOVSX_b |              Opcode::MOVZX_b => {                  match context.and_then(|xs| xs[1].as_ref()) {                      Some(s) => { write!(out, ", {}", s) } @@ -653,6 +674,7 @@ impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instructi                      }                  }              }, +            Opcode::MOVSX_w |              Opcode::MOVZX_w => {                  match context.and_then(|xs| xs[1].as_ref()) {                      Some(s) => { write!(out, ", {}", s) } @@ -236,6 +236,13 @@ pub enum Segment {  #[allow(non_camel_case_types)]  #[derive(Copy, Clone, Debug, Eq, PartialEq)]  pub enum Opcode { +    XADD, +    BT, +    BTS, +    BTC, +    BTR, +    BSF, +    BSR,      MOVSS,      ADDSS,      SUBSS, @@ -266,9 +273,12 @@ pub enum Opcode {      CVTSS2SI,      CVTSS2SD,      LDDQU, +    MOVSX_b, +    MOVSX_w,      MOVZX_b,      MOVZX_w,      MOVSX, +    MOVSXD,      SAR,      SAL,      SHR, @@ -654,6 +664,7 @@ pub enum OperandCode {      ModRM_0x0f00,      ModRM_0x0f01,      ModRM_0x0fae, +    ModRM_0x0fba,      Rq_Cq_0,      Rq_Dq_0,      Cq_Rq_0, @@ -703,6 +714,7 @@ pub enum OperandCode {      Gb_Eb,      Gv_Eb,      Gv_Ew, +    Gv_Ed,      Gv_Ev,      G_E_xmm,      Gv_M, @@ -1013,6 +1025,11 @@ fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mu                      instruction.opcode = Opcode::UD2;                      Ok(OperandCode::Nothing)                  } +                0x0d => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::NOP; +                    Ok(OperandCode::Ev) +                }                  0x1f => {                      instruction.prefixes = prefixes;                      instruction.opcode = Opcode::NOP; @@ -1255,6 +1272,11 @@ fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mu                      instruction.opcode = Opcode::CPUID;                      Ok(OperandCode::Nothing)                  } +                0xa3 => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::BT; +                    Ok(OperandCode::Gv_Ev) +                }                  0xa8 => {                      instruction.prefixes = prefixes;                      instruction.opcode = Opcode::PUSH; @@ -1269,6 +1291,11 @@ fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mu                      instruction.prefixes = prefixes;                      Ok(OperandCode::ModRM_0x0fae)                  } +                0xaf => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::IMUL; +                    Ok(OperandCode::Gv_Ev) +                }                  0xb0 => {                      instruction.prefixes = prefixes;                      instruction.opcode = Opcode::CMPXCHG; @@ -1289,6 +1316,45 @@ fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mu                      instruction.opcode = Opcode::MOVZX_w;                      Ok(OperandCode::Gv_Ew)                  } +                0xba => { +                    instruction.prefixes = prefixes; +                    Ok(OperandCode::ModRM_0x0fba) +                } +                0xbb => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::BTC; +                    Ok(OperandCode::Gv_Ev) +                } +                0xbc => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::BSF; +                    Ok(OperandCode::Gv_Ev) +                } +                0xbd => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::BSR; +                    Ok(OperandCode::Gv_Ev) +                } +                0xbe => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::MOVSX_b; +                    Ok(OperandCode::Gv_Eb) +                } +                0xbf => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::MOVSX_w; +                    Ok(OperandCode::Gv_Ew) +                } +                0xc0 => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::XADD; +                    Ok(OperandCode::Eb_Gb) +                } +                0xc1 => { +                    instruction.prefixes = prefixes; +                    instruction.opcode = Opcode::XADD; +                    Ok(OperandCode::Ev_Gv) +                }                  _ => {                      Err(format!("Unknown opcode: 0f{:x}", b))                  } @@ -1391,6 +1457,11 @@ fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instr                          instruction.opcode = op;                          return Ok(OperandCode::Zv(x));                      }, +                    0x63 => { +                        instruction.prefixes = prefixes; +                        instruction.opcode = Opcode::MOVSXD; +                        return Ok(OperandCode::Gv_Ed); +                    },                      0x64 => {                          prefixes.set_fs();                          alternate_opcode_map = None; @@ -1577,12 +1648,12 @@ fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instr                      0x9c => {                          instruction.prefixes = prefixes;                          instruction.opcode = Opcode::PUSHF; -                        return Ok(OperandCode::Fw); +                        return Ok(OperandCode::Nothing);                      },                      0x9d => {                          instruction.prefixes = prefixes;                          instruction.opcode = Opcode::POPF; -                        return Ok(OperandCode::Fw); +                        return Ok(OperandCode::Nothing);                      },                      0x9e => {                          instruction.prefixes = prefixes; @@ -1768,6 +1839,20 @@ fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instr                          instruction.opcode = Opcode::Invalid;                          return Ok(operand);                      }, +                    0xdc => { +                        // TODO: WRONG +                        // x87 instructions +                        instruction.opcode = Opcode::NOP; +                        let _ = read_imm_unsigned(bytes_iter, 2, length)?; +                        return Ok(OperandCode::Nothing); +                    } +                    0xdd => { +                        // x87 instructions +                        // TODO: WRONG +                        instruction.opcode = Opcode::NOP; +                        let _ = read_imm_unsigned(bytes_iter, 2, length)?; +                        return Ok(OperandCode::Nothing); +                    }                      // TODO: GAP                      0xe8 => {                          instruction.prefixes = prefixes; @@ -2631,6 +2716,26 @@ fn read_operands<T: Iterator<Item=u8>>(              }          },          // TODO: verify M +        OperandCode::Gv_Ed => { +            let opwidth = 4; +            // TODO: ... +            let modrm = match bytes_iter.next() { +                Some(b) => b, +                None => return Err("Out of bytes".to_string()) +            }; +            *length += 1; +            let (mod_bits, r, m) = octets_of(modrm); + +//                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); +            match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1], length) { +                Ok(()) => { +                    instruction.operands[0] = +                        Operand::Register(RegSpec::gp_from_parts(r, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +                    Ok(()) +                }, +                Err(reason) => Err(reason) +            } +        },          OperandCode::Gv_Ev | OperandCode::Gv_M => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ... @@ -2947,7 +3052,8 @@ fn read_operands<T: Iterator<Item=u8>>(                          instruction.operands = [Operand::Nothing, Operand::Nothing];                          Ok(())                      } else { -                        panic!("Unsupported instruction: 0x0f01 with modrm: 11 110 r >= 2"); +                    //    panic!("Unsupported instruction: 0x0f01 with modrm: 11 110 r >= 2"); +                        Err("unsupported 0x0f01 variant".to_string())                      }                  } else {                      instruction.opcode = Opcode::INVLPG; @@ -3049,6 +3155,47 @@ fn read_operands<T: Iterator<Item=u8>>(                  _ => { unreachable!("r < 6"); }              }          } +        OperandCode::ModRM_0x0fba => { +            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); +            let modrm = match bytes_iter.next() { +                Some(b) => b, +                None => return Err("Out of bytes".to_string()) +            }; +            *length += 1; +            let (mod_bits, r, m) = octets_of(modrm); +            match r { +                0 | 1 | 2 | 3 => { +                    instruction.opcode = Opcode::Invalid; +                    return Err("invalid instruction".to_string()); +                }, +                4 => { +                    instruction.opcode = Opcode::BT; +                } +                5 => { +                    instruction.opcode = Opcode::BTS; +                } +                6 => { +                    instruction.opcode = Opcode::BTR; +                } +                7 => { +                    instruction.opcode = Opcode::BTC; +                } +                _ => { +                    unreachable!("r < 8"); +                } +            } + +            read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0], length)?; + +            match read_imm_signed(bytes_iter, 1, 1, length) { +                Ok(op) => { +                    instruction.operands[1] = op; +                    Ok(()) +                }, +                Err(reason) => Err(reason) +            } +        } +          OperandCode::Rq_Cq_0 => {              let modrm = match bytes_iter.next() {                  Some(b) => b, | 
