aboutsummaryrefslogtreecommitdiff
path: root/src/armv8
diff options
context:
space:
mode:
Diffstat (limited to 'src/armv8')
-rw-r--r--src/armv8/a64.rs153
1 files changed, 152 insertions, 1 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index b901d21..662ea99 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -845,6 +845,56 @@ impl Display for Instruction {
Opcode::UMULH => {
write!(fmt, "umulh")?;
}
+ Opcode::UDIV => {
+ write!(fmt, "udiv")?;
+ }
+ Opcode::SDIV => {
+ write!(fmt, "sdiv")?;
+ }
+ Opcode::LSLV => {
+ // lslv == lsl (register) and, quoth the manual, `lsl is always the preferred
+ // disassembly`.
+ write!(fmt, "lsl")?;
+ }
+ Opcode::LSRV => {
+ // lsrv == lsr (register) and, quoth the manual, `lsr is always the preferred
+ // disassembly`.
+ write!(fmt, "lsr")?;
+ }
+ Opcode::ASRV => {
+ // asrv == asr (register) and, quoth the manual, `asr is always the preferred
+ // disassembly`.
+ write!(fmt, "asr")?;
+ }
+ Opcode::RORV => {
+ // rorv == ror (register) and, quoth the manual, `ror is always the preferred
+ // disassembly`.
+ write!(fmt, "ror")?;
+ }
+ Opcode::CRC32B => {
+ write!(fmt, "crc32b")?;
+ }
+ Opcode::CRC32H => {
+ write!(fmt, "crc32h")?;
+ }
+ Opcode::CRC32W => {
+ write!(fmt, "crc32w")?;
+ }
+ Opcode::CRC32X => {
+ write!(fmt, "crc32x")?;
+ }
+ Opcode::CRC32CB => {
+ write!(fmt, "crc32cb")?;
+ }
+ Opcode::CRC32CH => {
+ write!(fmt, "crc32ch")?;
+ }
+ Opcode::CRC32CW => {
+ write!(fmt, "crc32cw")?;
+ }
+ Opcode::CRC32CX => {
+ write!(fmt, "crc32cx")?;
+ }
};
if self.operands[0] != Operand::Nothing {
@@ -1028,6 +1078,20 @@ pub enum Opcode {
UMADDL,
UMSUBL,
UMULH,
+ UDIV,
+ SDIV,
+ LSLV,
+ LSRV,
+ ASRV,
+ RORV,
+ CRC32B,
+ CRC32H,
+ CRC32W,
+ CRC32X,
+ CRC32CB,
+ CRC32CH,
+ CRC32CW,
+ CRC32CX,
}
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -1520,7 +1584,94 @@ impl Decoder<ARMv8> for InstDecoder {
if ((word >> 30) & 1) == 0 {
// X0X11010_110XXXXX_XXXXXXXX_XXXXXXXX
// Data-processing (2 source)
- return Err(DecodeError::IncompleteDecoder);
+ let sf = ((word >> 31) & 0x01) as u8;
+ let S = ((word >> 29) & 0x01) as u8;
+
+ let Rd = (word & 0x1f) as u16;
+ let Rn = ((word >> 5) & 0x1f) as u16;
+ let opcode = ((word >> 10) & 0x3f) as u8;
+ let Rm = ((word >> 16) & 0x1f) as u16;
+
+ if S == 1 {
+ // unallocated
+ return Err(DecodeError::InvalidOpcode);
+ }
+
+ let combined_idx = (opcode << 1) | sf;
+
+ const OPCODES: &[Result<(Opcode, SizeCode), DecodeError>] = &[
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b00_0010
+ Ok((Opcode::UDIV, SizeCode::W)),
+ Ok((Opcode::UDIV, SizeCode::X)),
+ // opcode = 0b00_0011
+ Ok((Opcode::SDIV, SizeCode::W)),
+ Ok((Opcode::SDIV, SizeCode::X)),
+ // opcode = 0b00_01xx
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b00_1000
+ Ok((Opcode::LSLV, SizeCode::W)),
+ Ok((Opcode::LSLV, SizeCode::X)),
+ Ok((Opcode::LSRV, SizeCode::W)),
+ Ok((Opcode::LSRV, SizeCode::X)),
+ // opcode = 0b00_1010
+ Ok((Opcode::ASRV, SizeCode::W)),
+ Ok((Opcode::ASRV, SizeCode::X)),
+ // opcode = 0b00_1011
+ Ok((Opcode::RORV, SizeCode::W)),
+ Ok((Opcode::RORV, SizeCode::X)),
+ // opcode = 0b00_11xx
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0000
+ Ok((Opcode::CRC32B, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0001
+ Ok((Opcode::CRC32H, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0010
+ Ok((Opcode::CRC32W, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0011
+ Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::CRC32X, SizeCode::X)),
+ // opcode = 0b01_0100
+ Ok((Opcode::CRC32CB, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0101
+ Ok((Opcode::CRC32CH, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0110
+ Ok((Opcode::CRC32CW, SizeCode::X)),
+ Err(DecodeError::InvalidOpcode),
+ // opcode = 0b01_0111
+ Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::CRC32CX, SizeCode::X)),
+ ];
+ let (opcode, size) = OPCODES[combined_idx as usize]?;
+ inst.opcode = opcode;
+ inst.operands = [
+ Operand::Register(size, Rd),
+ Operand::Register(size, Rn),
+ Operand::Register(size, Rm),
+ Operand::Nothing,
+ ];
} else {
// X1X11010_110XXXXX_XXXXXXXX_XXXXXXXX
// Data-processing (1 source)