diff options
| -rw-r--r-- | src/lib.rs | 613 | 
1 files changed, 261 insertions, 352 deletions
| @@ -797,38 +797,38 @@ pub enum OperandCode {      Yb_Xb,      Yv_AX,      Yv_Xv, -    Zb_Ib_R0, -    Zb_Ib_R1, -    Zb_Ib_R2, -    Zb_Ib_R3, -    Zb_Ib_R4, -    Zb_Ib_R5, -    Zb_Ib_R6, -    Zb_Ib_R7, -    Zv_R0, -    Zv_R1, -    Zv_R2, -    Zv_R3, -    Zv_R4, -    Zv_R5, -    Zv_R6, -    Zv_R7, -    Zv_AX_R0, -    Zv_AX_R1, -    Zv_AX_R2, -    Zv_AX_R3, -    Zv_AX_R4, -    Zv_AX_R5, -    Zv_AX_R6, -    Zv_AX_R7, -    Zv_Ivq_R0, -    Zv_Ivq_R1, -    Zv_Ivq_R2, -    Zv_Ivq_R3, -    Zv_Ivq_R4, -    Zv_Ivq_R5, -    Zv_Ivq_R6, -    Zv_Ivq_R7, +    Zb_Ib_R0 = 200, +    Zb_Ib_R1 = 201, +    Zb_Ib_R2 = 202, +    Zb_Ib_R3 = 203, +    Zb_Ib_R4 = 204, +    Zb_Ib_R5 = 205, +    Zb_Ib_R6 = 206, +    Zb_Ib_R7 = 207, +    Zv_R0 = 208, +    Zv_R1 = 209, +    Zv_R2 = 210, +    Zv_R3 = 211, +    Zv_R4 = 212, +    Zv_R5 = 213, +    Zv_R6 = 214, +    Zv_R7 = 215, +    Zv_AX_R0 = 216, +    Zv_AX_R1 = 217, +    Zv_AX_R2 = 218, +    Zv_AX_R3 = 219, +    Zv_AX_R4 = 220, +    Zv_AX_R5 = 221, +    Zv_AX_R6 = 222, +    Zv_AX_R7 = 223, +    Zv_Ivq_R0 = 224, +    Zv_Ivq_R1 = 225, +    Zv_Ivq_R2 = 226, +    Zv_Ivq_R3 = 227, +    Zv_Ivq_R4 = 228, +    Zv_Ivq_R5 = 229, +    Zv_Ivq_R6 = 230, +    Zv_Ivq_R7 = 231,      Nothing,      Implied,      Unsupported, @@ -1788,6 +1788,11 @@ enum Interpretation {  // this should be a 32-byte struct..  struct OpcodeRecord(Interpretation, OperandCode); +#[test] +fn opcode_record_size() { +    assert_eq!(std::mem::size_of::<OpcodeRecord>(), 2); +} +  const OPCODES: [OpcodeRecord; 256] = [      OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Eb_Gb),      OpcodeRecord(Interpretation::Instruction(Opcode::ADD), OperandCode::Ev_Gv), @@ -2084,141 +2089,164 @@ const OPCODES: [OpcodeRecord; 256] = [  ];  #[allow(non_snake_case)] -fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, result: usize) -> Option<()> { +fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize, width: u8) -> Option<()> {      let bank = width_to_gp_reg_bank(width, instr.prefixes.rex().present()); -    read_E_anybank(bytes_iter, instr, modrm, width, result, bank) +    if modrm >= 0b11000000 { +        read_modrm_reg(bytes_iter, instr, modrm, result, bank) +    } else { +        read_M(bytes_iter, instr, modrm, result) +    } +} +#[allow(non_snake_case)] +fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize) -> Option<()> { +    if modrm >= 0b11000000 { +        read_modrm_reg(bytes_iter, instr, modrm, result, RegisterBank::X) +    } else { +        read_M(bytes_iter, instr, modrm, result) +    }  } +  #[allow(non_snake_case)] -fn read_E_xmm<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, width: u8, result: usize) -> Option<()> { -    read_E_anybank(bytes_iter, instr, modrm, width, result, RegisterBank::X) +fn read_modrm_reg<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize, reg_bank: RegisterBank) -> Option<()> { +    instr.operands[result] = Operand::Register(RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank)); +    Some(())  }  #[allow(non_snake_case)] -fn read_E_anybank<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, _width: u8, result: usize, reg_bank: RegisterBank) -> Option<()> { +fn read_sib<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize) -> Option<()> {      let modbits = (modrm >> 6);      let addr_width = if instr.prefixes.address_size() { 4 } else { 8 }; -    if modbits == 0b11 { -        instr.operands[result] = Operand::Register(RegSpec::from_parts(modrm & 7, instr.prefixes.rex().b(), reg_bank)) -    } else if (modrm & 7) == 5 && modbits == 0b00 { -        let disp = read_num(bytes_iter, 4, &mut instr.length); -        instr.operands[result] = Operand::RegDisp( -            if addr_width == 8 { RegSpec::rip() } else { RegSpec::eip() }, -            disp as i32 -        ); -    } else if (modrm & 7) == 4 { -        let sibbyte = match bytes_iter.next() { -            Some(b) => b, -            None => { return None; } //Err("Out of bytes".to_string()) -        }; -        instr.length += 1; -//         let (ss, index, base) = octets_of(sibbyte); +    let sibbyte = match bytes_iter.next() { +        Some(b) => b, +        None => { return None; } //Err("Out of bytes".to_string()) +    }; +    instr.length += 1; -//            println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base); +    instr.operands[result] = if (sibbyte & 7) == 0b101 { +        let disp = if modbits == 0b00 { +            read_num(bytes_iter, 4, &mut instr.length) as i32 +        } else if modbits == 0b01 { +            read_num(bytes_iter, 1, &mut instr.length) as i8 as i32 +        } else { +            read_num(bytes_iter, 4, &mut instr.length) as i32 +        }; -        if (sibbyte & 7) == 0b101 { -            let disp = if modbits == 0b00 { -                read_num(bytes_iter, 4, &mut instr.length) as i32 -            } else if modbits == 0b01 { -                read_num(bytes_iter, 1, &mut instr.length) as i8 as i32 +        if ((sibbyte >> 3) & 7) == 0b100 { +            if modbits == 0b00 && !instr.prefixes.rex().x() { +                Operand::DisplacementU32(disp as u32)              } else { -                read_num(bytes_iter, 4, &mut instr.length) as i32 -            }; +                let reg = RegSpec::gp_from_parts(0b100, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); -            if ((sibbyte >> 3) & 7) == 0b100 { -                if modbits == 0b00 && !instr.prefixes.rex().x() { -                    instr.operands[result] = Operand::DisplacementU32(disp as u32); +                if disp == 0 { +                    Operand::RegDeref(reg)                  } else { -                    let reg = RegSpec::gp_from_parts(0b100, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +                    Operand::RegDisp(reg, disp as i32) +                } +            } +        } else { +            let base_reg = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); -                    if disp == 0 { -                        instr.operands[result] = Operand::RegDeref(reg); -                    } else { -                        instr.operands[result] = Operand::RegDisp(reg, disp as i32); -                    } +            let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +            let scale = 1u8 << (sibbyte >> 6); + +            match (scale, modbits, disp) { +                (0, 0b00, 0) => { +                    Operand::RegDeref(index_reg) +                }, +                (0, 0b00, _) => { +                    Operand::RegDisp(index_reg, disp as i32) +                }, +                (0, _, 0) => { +                    Operand::RegIndexBase(base_reg, index_reg) +                }, +                (0, _, _) => { +                    Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32) +                }, +                (_, 0b00, 0) => { +                    Operand::RegScale(index_reg, scale) +                }, +                (_, 0b00, _) => { +                    Operand::RegScaleDisp(index_reg, scale, disp as i32) +                }, +                (_, _, 0) => { +                    Operand::RegIndexBaseScale(base_reg, index_reg, scale) +                }, +                (_, _, _) => { +                    Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32)                  } -            } else { -                let base_reg = RegSpec::gp_from_parts(5, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); - -                let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); -                let scale = 1u8 << (sibbyte >> 6); - -                instr.operands[result] = match (scale, modbits, disp) { -                    (0, 0b00, 0) => { -                        Operand::RegDeref(index_reg) -                    }, -                    (0, 0b00, _) => { -                        Operand::RegDisp(index_reg, disp as i32) -                    }, -                    (0, _, 0) => { -                        Operand::RegIndexBase(base_reg, index_reg) -                    }, -                    (0, _, _) => { -                        Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32) -                    }, -                    (_, 0b00, 0) => { -                        Operand::RegScale(index_reg, scale) -                    }, -                    (_, 0b00, _) => { -                        Operand::RegScaleDisp(index_reg, scale, disp as i32) -                    }, -                    (_, _, 0) => { -                        Operand::RegIndexBaseScale(base_reg, index_reg, scale) -                    }, -                    (_, _, _) => { -                        Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32) -                    } -                };              } +        } +    } else { +        let base_reg = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); + +        let disp = if modbits == 0b00 { +            0 +        } else if modbits == 0b01 { +            read_num(bytes_iter, 1, &mut instr.length) as i8 as i32          } else { -            let base_reg = RegSpec::gp_from_parts((sibbyte & 7), instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); +            read_num(bytes_iter, 4, &mut instr.length) as i32 +        }; -            let disp = if modbits == 0b00 { -                0 -            } else if modbits == 0b01 { -                read_num(bytes_iter, 1, &mut instr.length) as i8 as i32 +        if ((sibbyte >> 3) & 7) == 0b100 { +            if disp == 0 { +                Operand::RegDeref(base_reg)              } else { -                read_num(bytes_iter, 4, &mut instr.length) as i32 -            }; - -            if ((sibbyte >> 3) & 7) == 0b100 { -                if disp == 0 { -                    instr.operands[result] = Operand::RegDeref(base_reg); +                Operand::RegDisp(base_reg, disp as i32) +            } +        } else { +            let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); +            let scale = 1u8 << (sibbyte >> 6); +            if disp == 0 { +                if scale == 0 { +                    Operand::RegIndexBase(base_reg, index_reg)                  } else { -                    instr.operands[result] = Operand::RegDisp(base_reg, disp as i32); +                    Operand::RegIndexBaseScale(base_reg, index_reg, scale)                  }              } else { -                let index_reg = RegSpec::gp_from_parts((sibbyte >> 3) & 7, instr.prefixes.rex().x(), addr_width, instr.prefixes.rex().present()); -                let scale = 1u8 << (sibbyte >> 6); -                if disp == 0 { -                    if scale == 0 { -                        instr.operands[result] = Operand::RegIndexBase(base_reg, index_reg) -                    } else { -                        instr.operands[result] = Operand::RegIndexBaseScale(base_reg, index_reg, scale); -                    } -                } else { -                    if scale == 0 { +                if scale == 0 { -                        instr.operands[result] = Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32); -                    } else { -                        instr.operands[result] = Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32); -                    } +                    Operand::RegIndexBaseDisp(base_reg, index_reg, disp as i32) +                } else { +                    Operand::RegIndexBaseScaleDisp(base_reg, index_reg, scale, disp as i32)                  }              }          } +    }; +    Some(()) +} + +#[allow(non_snake_case)] +fn read_M<T: Iterator<Item=u8>>(bytes_iter: &mut T, instr: &mut Instruction, modrm: u8, result: usize) -> Option<()> { +    let modbits = (modrm >> 6); +    let addr_width = if instr.prefixes.address_size() { 4 } else { 8 }; +    let mmm = modrm & 7; +    instr.operands[result] = if modbits == 0b11 { +        unsafe { unreachable_unchecked() } +    } else if mmm == 4 { +        return read_sib(bytes_iter, instr, modrm, result); +//         let (ss, index, base) = octets_of(sibbyte); + +//            println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base); +    } else if mmm == 5 && modbits == 0b00 { +        let disp = read_num(bytes_iter, 4, &mut instr.length); +        Operand::RegDisp( +            if addr_width == 8 { RegSpec::rip() } else { RegSpec::eip() }, +            disp as i32 +        )      } else { -        let reg = RegSpec::gp_from_parts(modrm & 7, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present()); +        let reg = RegSpec::gp_from_parts(mmm, instr.prefixes.rex().b(), addr_width, instr.prefixes.rex().present());          if modbits == 0b00 { -            instr.operands[result] = Operand::RegDeref(reg); +            Operand::RegDeref(reg)          } else {              let disp = if modbits == 0b01 {                  read_num(bytes_iter, 1, &mut instr.length) as i8 as i32              } else {                  read_num(bytes_iter, 4, &mut instr.length) as i32              }; -            instr.operands[result] = Operand::RegDisp(reg, disp); +            Operand::RegDisp(reg, disp)          } -    } +    };      Some(())  } @@ -2329,6 +2357,42 @@ pub fn read_instr<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Ins      read_operands(bytes_iter, instruction, record.1)  }  pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut Instruction, operand_code: OperandCode) -> Option<()> { +    if operand_code == OperandCode::Gv_Ev { +        let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); +        let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); + +//                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); +        read_E(&mut bytes_iter, instruction, modrm, 1, opwidth).unwrap(); +        instruction.operands[0] = +            Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +    } else if operand_code == OperandCode::Ev_Gv { +        let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); +        let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); + +        read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap(); +        instruction.operands[1] = +            Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +    } else if operand_code == OperandCode::Gb_Eb { +        let opwidth = 1; +        let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); + +        read_E(&mut bytes_iter, instruction, modrm, 1, opwidth).unwrap(); +        instruction.operands[0] = +            Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +    } else if operand_code == OperandCode::Eb_Gb { +        let opwidth = 1; +        let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); + +        read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap(); +        instruction.operands[1] = +            Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); +    } else if operand_code == OperandCode::Jbs { +        // TODO: arch width (8 in 64, 4 in 32, 2 in 16) +        instruction.operands = [ +            read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length).unwrap(), +            Operand::Nothing +        ]; +    } else {      match operand_code {          /*          Gv_Ev_Iv, @@ -2385,7 +2449,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  return None; // Err("Invalid modr/m for opcode 0xc6".to_owned());              } -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();          },          OperandCode::AL_Ob => {              let _addr_width = if instruction.prefixes.address_size() { 4 } else { 8 }; @@ -2451,7 +2515,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let num = read_num(&mut bytes_iter, 1, &mut instruction.length) as i8;              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = Operand::ImmediateI8(num); @@ -2460,7 +2524,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let imm = read_imm_signed(&mut bytes_iter, if opwidth == 8 { 4 } else { opwidth }, opwidth, &mut instruction.length).unwrap();              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = imm; @@ -2469,7 +2533,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let num = read_num(&mut bytes_iter, 1, &mut instruction.length) as i8;              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(num); @@ -2478,7 +2542,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let num = read_num(&mut bytes_iter, 1, &mut instruction.length) as i8;              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(num); @@ -2487,7 +2551,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let num = read_num(&mut bytes_iter, 1, &mut instruction.length) as i8;              if (modrm & 0b00111000) != 0 {                  instruction.opcode = Opcode::Invalid; @@ -2505,7 +2569,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  return None; // Err("Invalid modr/m for opcode 0xc7".to_string());              } -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.opcode = Opcode::MOV;              instruction.operands[1] = read_imm_unsigned(&mut bytes_iter, opwidth, &mut instruction.length).unwrap();          }, @@ -2513,7 +2577,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(1);          }, @@ -2521,7 +2585,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.opcode = BITWISE_OPCODE_MAP[((modrm >> 3) & 7) as usize].clone();              instruction.operands[1] = Operand::ImmediateI8(1);          }, @@ -2530,7 +2594,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();              let (mod_bits, r, m) = octets_of(modrm); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let opcode = BITWISE_OPCODE_MAP[r as usize].clone();              instruction.opcode = opcode;              instruction.operands[1] = Operand::Register(RegSpec::cl()); @@ -2538,7 +2602,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut          OperandCode::ModRM_0xf6 => {              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              match (modrm >> 3) & 7 {                  0 | 1 => {                      instruction.opcode = Opcode::TEST; @@ -2570,7 +2634,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut          OperandCode::ModRM_0xf7 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              match ((modrm >> 3) & 7) {                  0 | 1 => {                      instruction.opcode = Opcode::TEST; @@ -2604,7 +2668,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.opcode = [                  Opcode::INC,                  Opcode::DEC, @@ -2621,7 +2685,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              let opcode = [                  Opcode::INC,                  Opcode::DEC, @@ -2639,33 +2703,9 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.operands[1] = Operand::Nothing;          }, -        OperandCode::Eb_Gb => { -            let opwidth = 1; -            let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); - -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); -            instruction.operands[1] = -                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); -        }, -        OperandCode::Ev_Gv => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); - -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); -            instruction.operands[1] = -                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); -        }, -        OperandCode::Gb_Eb => { -            let opwidth = 1; -            let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); - -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 1).unwrap(); -            instruction.operands[0] = -                Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present())); -        },          OperandCode::Gb_Eb_Ib => {              let opwidth = 1;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); @@ -2687,7 +2727,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 1).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 1, opwidth).unwrap();              instruction.operands[0] =                  Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          }, @@ -2695,7 +2735,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap(); -            read_E(&mut bytes_iter, instruction, modrm, 2, 1).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 1, 2).unwrap();              instruction.operands[0] =                  Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          }, @@ -2716,7 +2756,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  instruction.operands[0] =                      Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});              } else { -                read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              }          },          OperandCode::Sw_Ew => { @@ -2736,7 +2776,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  instruction.operands[1] =                      Operand::Register(RegSpec { bank: RegisterBank::W, num: modrm & 7});              } else { -                read_E(&mut bytes_iter, instruction, modrm, opwidth, 1).unwrap(); +                read_E(&mut bytes_iter, instruction, modrm, 1, opwidth).unwrap();              }          },          OperandCode::Gdq_Ed => { @@ -2744,16 +2784,16 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E(&mut bytes_iter, instruction, modrm, 4 /* opwidth */, 1).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 1, 4 /* opwidth */).unwrap();              instruction.operands[0] =                  Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          }, -        OperandCode::Gv_Ev | OperandCode::Gv_M => { +        OperandCode::Gv_M => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 1).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 1, opwidth).unwrap();              instruction.operands[0] =                  Operand::Register(RegSpec::gp_from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), opwidth, instruction.prefixes.rex().present()));          }, @@ -2775,76 +2815,33 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              }).unwrap()          }          OperandCode::E_G_xmm => { -            let opwidth = 8;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E_xmm(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E_xmm(&mut bytes_iter, instruction, modrm, 0).unwrap();              instruction.operands[1] =                  Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X));          },          OperandCode::G_E_xmm => { -            let opwidth = 8;              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m); -            read_E_xmm(&mut bytes_iter, instruction, modrm, opwidth, 1).unwrap(); +            read_E_xmm(&mut bytes_iter, instruction, modrm, 1).unwrap();              instruction.operands[0] =                  Operand::Register(RegSpec::from_parts((modrm >> 3) & 7, instruction.prefixes.rex().r(), RegisterBank::X));          }, -        OperandCode::Zv_Ivq_R0 => { +        op @ OperandCode::Zv_Ivq_R0 | +        op @ OperandCode::Zv_Ivq_R1 | +        op @ OperandCode::Zv_Ivq_R2 | +        op @ OperandCode::Zv_Ivq_R3 | +        op @ OperandCode::Zv_Ivq_R4 | +        op @ OperandCode::Zv_Ivq_R5 | +        op @ OperandCode::Zv_Ivq_R6 | +        op @ OperandCode::Zv_Ivq_R7 => { +            let reg = (op as u8) - (OperandCode::Zv_Ivq_R0 as u8);              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R1 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(1, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R2 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(2, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R3 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(3, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R4 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(4, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R5 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(5, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R6 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(6, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), -                read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zv_Ivq_R7 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(7, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())), +                Operand::Register(RegSpec::gp_from_parts(reg, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present())),                  read_imm_ivq(&mut bytes_iter, opwidth, &mut instruction.length).unwrap()              ];          }, @@ -2864,51 +2861,17 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  read_imm_signed(&mut bytes_iter, numwidth, opwidth, &mut instruction.length).unwrap()              ];          } -        OperandCode::Zb_Ib_R0 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(0, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R1 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(1, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R2 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(2, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R3 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(3, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R4 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(4, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R5 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(5, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R6 => { +        op @ OperandCode::Zb_Ib_R0 | +        op @ OperandCode::Zb_Ib_R1 | +        op @ OperandCode::Zb_Ib_R2 | +        op @ OperandCode::Zb_Ib_R3 | +        op @ OperandCode::Zb_Ib_R4 | +        op @ OperandCode::Zb_Ib_R5 | +        op @ OperandCode::Zb_Ib_R6 | +        op @ OperandCode::Zb_Ib_R7 => { +            let reg = (op as u8) - (OperandCode::Zb_Ib_R0 as u8);              instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(6, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), -                read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap() -            ]; -        }, -        OperandCode::Zb_Ib_R7 => { -            instruction.operands = [ -                Operand::Register(RegSpec::gp_from_parts(7, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())), +                Operand::Register(RegSpec::gp_from_parts(reg, instruction.prefixes.rex().b(), 1, instruction.prefixes.rex().present())),                  read_imm_unsigned(&mut bytes_iter, 1, &mut instruction.length).unwrap()              ];          }, @@ -2918,13 +2881,6 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  Operand::Nothing              ];          } -        OperandCode::Jbs => { -            // TODO: arch width (8 in 64, 4 in 32, 2 in 16) -            instruction.operands = [ -                read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length).unwrap(), -                Operand::Nothing -            ]; -        },          OperandCode::Ibs => {              instruction.operands = [                  read_imm_signed(&mut bytes_iter, 1, 8, &mut instruction.length).unwrap(), @@ -2942,71 +2898,23 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              let modrm = read_modrm(&mut bytes_iter, &mut instruction.length).unwrap();              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.opcode = base_opcode_map((modrm >> 3) & 7);              instruction.operands[1] = read_imm_signed(&mut bytes_iter, 1, opwidth, &mut instruction.length).unwrap();          }, -        OperandCode::Zv_R0 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    0, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R1 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    1, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R2 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    2, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R3 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    3, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R4 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    4, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R5 => { +        op @ OperandCode::Zv_R0 | +        op @ OperandCode::Zv_R1 | +        op @ OperandCode::Zv_R2 | +        op @ OperandCode::Zv_R3 | +        op @ OperandCode::Zv_R4 | +        op @ OperandCode::Zv_R5 | +        op @ OperandCode::Zv_R6 | +        op @ OperandCode::Zv_R7 => { +            let reg = (op as u8) - (OperandCode::Zv_R0 as u8);              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes);              instruction.operands = [Operand::Register(                  RegSpec::gp_from_parts( -                    5, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R6 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    6, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() -                ) -            ), Operand::Nothing]; -        }, -        OperandCode::Zv_R7 => { -            let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); -            instruction.operands = [Operand::Register( -                RegSpec::gp_from_parts( -                    7, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present() +                    reg, instruction.prefixes.rex().b(), opwidth, instruction.prefixes.rex().present()                  )              ), Operand::Nothing];          }, @@ -3046,7 +2954,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut              } else {                  unreachable!("r <= 8");              } -            read_E(&mut bytes_iter, instruction, modrm, 2, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, 2).unwrap();          }          OperandCode::ModRM_0x0f01 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); @@ -3060,7 +2968,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  } else {                      instruction.opcode = Opcode::SGDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                    read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();                  }              } else if r == 1 {                  let mod_bits = modrm >> 6; @@ -3072,7 +2980,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  } else {                      instruction.opcode = Opcode::SIDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                    read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();                  }              } else if r == 2 {                  let mod_bits = modrm >> 6; @@ -3084,7 +2992,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  } else {                      instruction.opcode = Opcode::LGDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                    read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();                  }              } else if r == 3 {                  let mod_bits = modrm >> 6; @@ -3096,20 +3004,20 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  } else {                      instruction.opcode = Opcode::LIDT;                      instruction.operands[1] = Operand::Nothing; -                    read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                    read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();                  }              } else if r == 4 {                  // TODO: this permits storing only to word-size registers                  // spec suggets this might do something different for f.ex rdi.unwrap()                  instruction.opcode = Opcode::SMSW;                  instruction.operands[1] = Operand::Nothing; -                read_E(&mut bytes_iter, instruction, modrm, 2, 0).unwrap(); +                read_E(&mut bytes_iter, instruction, modrm, 0, 2).unwrap();              } else if r == 5 {                  panic!("Unsupported instruction: 0x0f01 with modrm: __ 101 ___");              } else if r == 6 {                  instruction.opcode = Opcode::LMSW;                  instruction.operands[1] = Operand::Nothing; -                read_E(&mut bytes_iter, instruction, modrm, 2, 0).unwrap(); +                read_E(&mut bytes_iter, instruction, modrm, 0, 2).unwrap();              } else if r == 7 {                  let mod_bits = modrm >> 6;                  let m = modrm & 7; @@ -3127,7 +3035,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  } else {                      instruction.opcode = Opcode::INVLPG;                      instruction.operands[1] = Operand::Nothing; -                    read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +                    read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();                  }              } else {                  unreachable!("r <= 8"); @@ -3211,7 +3119,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  }                  _ => { unreachable!("r < 6"); }              } -            read_E(&mut bytes_iter, instruction, modrm, 8, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, 8).unwrap();          }          OperandCode::ModRM_0x0fba => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vq, &instruction.prefixes); @@ -3239,7 +3147,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut                  }              } -            read_E(&mut bytes_iter, instruction, modrm, opwidth, 0).unwrap(); +            read_E(&mut bytes_iter, instruction, modrm, 0, opwidth).unwrap();              instruction.operands[1] = read_imm_signed(&mut bytes_iter, 1, 1, &mut instruction.length).unwrap();          } @@ -3323,6 +3231,7 @@ pub fn read_operands<T: Iterator<Item=u8>>(mut bytes_iter: T, instruction: &mut          //    unsafe { unreachable_unchecked(); }          }      }; +    }      Some(())  } | 
