aboutsummaryrefslogtreecommitdiff
path: root/src/armv8/a64.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/armv8/a64.rs')
-rw-r--r--src/armv8/a64.rs153
1 files changed, 107 insertions, 46 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index cc86ea5..7fc1609 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -1696,6 +1696,11 @@ pub enum Opcode {
XPACI,
XPACD,
+ PACGA,
+ GMI,
+ IRG,
+ SUBP,
+ SUBPS,
}
impl Display for Opcode {
@@ -2520,6 +2525,12 @@ impl Display for Opcode {
Opcode::XPACI => "xpaci",
Opcode::XPACD => "xpacd",
+ Opcode::PACGA => "pacga",
+ Opcode::GMI => "gmi",
+ Opcode::IRG => "irg",
+ Opcode::SUBP => "subp",
+ Opcode::SUBPS => "subps",
+
Opcode::Bcc(cond) => {
return write!(fmt, "b.{}", Operand::ConditionCode(cond));
},
@@ -5409,10 +5420,9 @@ impl Decoder<ARMv8> for InstDecoder {
return Err(DecodeError::InvalidOpcode);
}
- if mode != 0b00 && opcode >= 0b100 && opcode != 0b110 {
+ if mode != 0b00 && opcode >= 0b100 && opcode < 0b110 {
return Err(DecodeError::InvalidOpcode);
}
-
let size = if sf == 0 {
SizeCode::W
} else {
@@ -5426,7 +5436,12 @@ impl Decoder<ARMv8> for InstDecoder {
} else if ty == 0b11 {
SIMDSizeCode::H
} else {
- return Err(DecodeError::InvalidOperand);
+ if (opcode == 0b110 || opcode == 0b111) && mode == 0b01 {
+ // this is fine, but it's not inferred..
+ SIMDSizeCode::B
+ } else {
+ return Err(DecodeError::InvalidOperand);
+ }
};
#[derive(Copy, Clone, Debug)]
@@ -5496,6 +5511,9 @@ impl Decoder<ARMv8> for InstDecoder {
(1, 0b10, 0b01, 0b111) => {
(Opcode::FMOV, ConvertOperands::gp_to_fp(GpSize::X, FpSize::Qh))
}
+ (1, 0b11, 0b00, 0b110) => {
+ (Opcode::FMOV, ConvertOperands::fp_to_gp(FpSize::H, GpSize::X))
+ }
(1, 0b11, 0b00, 0b111) => {
(Opcode::FMOV, ConvertOperands::gp_to_fp(GpSize::X, FpSize::H))
}
@@ -7227,46 +7245,57 @@ impl Decoder<ARMv8> for InstDecoder {
let Rm = ((word >> 16) & 0x1f) as u16;
if S == 1 {
- // unallocated
- return Err(DecodeError::InvalidOpcode);
+ if sf == 1 && opcode == 0b000000 {
+ inst.opcode = Opcode::SUBPS;
+ inst.operands = [
+ Operand::Register(SizeCode::X, Rd),
+ Operand::RegisterOrSP(SizeCode::X, Rn),
+ Operand::RegisterOrSP(SizeCode::X, Rm),
+ Operand::Nothing,
+ ];
+ return Ok(());
+ } else {
+ // unallocated
+ return Err(DecodeError::InvalidOpcode);
+ }
}
let combined_idx = (opcode << 1) | sf;
- const OPCODES: &[Result<(Opcode, SizeCode), DecodeError>] = &[
- Err(DecodeError::InvalidOpcode),
+ const OPCODES: &[Result<(Opcode, SizeCode, bool), DecodeError>] = &[
Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::SUBP, SizeCode::X, true)),
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
// opcode = 0b00_0010
- Ok((Opcode::UDIV, SizeCode::W)),
- Ok((Opcode::UDIV, SizeCode::X)),
+ Ok((Opcode::UDIV, SizeCode::W, false)),
+ Ok((Opcode::UDIV, SizeCode::X, false)),
// opcode = 0b00_0011
- Ok((Opcode::SDIV, SizeCode::W)),
- Ok((Opcode::SDIV, SizeCode::X)),
+ Ok((Opcode::SDIV, SizeCode::W, false)),
+ Ok((Opcode::SDIV, SizeCode::X, false)),
// opcode = 0b00_01xx
Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::IRG, SizeCode::X, true)),
Err(DecodeError::InvalidOpcode),
- Err(DecodeError::InvalidOpcode),
- Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::GMI, SizeCode::X, true)),
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)),
+ Ok((Opcode::LSLV, SizeCode::W, false)),
+ Ok((Opcode::LSLV, SizeCode::X, false)),
+ Ok((Opcode::LSRV, SizeCode::W, false)),
+ Ok((Opcode::LSRV, SizeCode::X, false)),
// opcode = 0b00_1010
- Ok((Opcode::ASRV, SizeCode::W)),
- Ok((Opcode::ASRV, SizeCode::X)),
+ Ok((Opcode::ASRV, SizeCode::W, false)),
+ Ok((Opcode::ASRV, SizeCode::X, false)),
// opcode = 0b00_1011
- Ok((Opcode::RORV, SizeCode::W)),
- Ok((Opcode::RORV, SizeCode::X)),
+ Ok((Opcode::RORV, SizeCode::W, false)),
+ Ok((Opcode::RORV, SizeCode::X, false)),
// opcode = 0b00_11xx
Err(DecodeError::InvalidOpcode),
- Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::PACGA, SizeCode::X, true)),
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
@@ -7274,47 +7303,79 @@ impl Decoder<ARMv8> for InstDecoder {
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0000
- Ok((Opcode::CRC32B, SizeCode::W)),
+ Ok((Opcode::CRC32B, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0001
- Ok((Opcode::CRC32H, SizeCode::W)),
+ Ok((Opcode::CRC32H, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0010
- Ok((Opcode::CRC32W, SizeCode::W)),
+ Ok((Opcode::CRC32W, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0011
Err(DecodeError::InvalidOpcode),
- Ok((Opcode::CRC32X, SizeCode::X)),
+ Ok((Opcode::CRC32X, SizeCode::X, false)),
// opcode = 0b01_0100
- Ok((Opcode::CRC32CB, SizeCode::W)),
+ Ok((Opcode::CRC32CB, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0101
- Ok((Opcode::CRC32CH, SizeCode::W)),
+ Ok((Opcode::CRC32CH, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0110
- Ok((Opcode::CRC32CW, SizeCode::W)),
+ Ok((Opcode::CRC32CW, SizeCode::W, false)),
Err(DecodeError::InvalidOpcode),
// opcode = 0b01_0111
Err(DecodeError::InvalidOpcode),
- Ok((Opcode::CRC32CX, SizeCode::X)),
+ Ok((Opcode::CRC32CX, SizeCode::X, false)),
];
- let (opcode, size) = OPCODES.get(combined_idx as usize).cloned().unwrap_or(Err(DecodeError::InvalidOpcode))?;
+ let (opcode, size, special) = OPCODES.get(combined_idx as usize).cloned().unwrap_or(Err(DecodeError::InvalidOpcode))?;
inst.opcode = opcode;
- inst.operands = [
- // `crc32` instructions always have w-reg dest/source1 operands
- if combined_idx > 0b01_0000_0 {
- Operand::Register(SizeCode::W, Rd)
- } else {
- Operand::Register(size, Rd)
- },
- if combined_idx > 0b01_0000_0 {
- Operand::Register(SizeCode::W, Rn)
- } else {
- Operand::Register(size, Rn)
- },
- Operand::Register(size, Rm),
- Operand::Nothing,
- ];
+ if !special {
+ inst.operands = [
+ // `crc32` instructions always have w-reg dest/source1 operands
+ if combined_idx > 0b01_0000_0 {
+ Operand::Register(SizeCode::W, Rd)
+ } else {
+ Operand::Register(size, Rd)
+ },
+ if combined_idx > 0b01_0000_0 {
+ Operand::Register(SizeCode::W, Rn)
+ } else {
+ Operand::Register(size, Rn)
+ },
+ Operand::Register(size, Rm),
+ Operand::Nothing,
+ ];
+ } else {
+ if opcode == Opcode::SUBP {
+ inst.operands = [
+ Operand::Register(SizeCode::X, Rd),
+ Operand::RegisterOrSP(SizeCode::X, Rn),
+ Operand::RegisterOrSP(SizeCode::X, Rm),
+ Operand::Nothing,
+ ];
+ } else if opcode == Opcode::IRG {
+ inst.operands = [
+ Operand::RegisterOrSP(SizeCode::X, Rd),
+ Operand::RegisterOrSP(SizeCode::X, Rn),
+ Operand::Register(SizeCode::X, Rm),
+ Operand::Nothing,
+ ];
+ } else if opcode == Opcode::GMI {
+ inst.operands = [
+ Operand::Register(SizeCode::X, Rd),
+ Operand::RegisterOrSP(SizeCode::X, Rn),
+ Operand::Register(SizeCode::X, Rm),
+ Operand::Nothing,
+ ];
+ } else if opcode == Opcode::PACGA {
+ inst.operands = [
+ Operand::Register(SizeCode::X, Rd),
+ Operand::Register(SizeCode::X, Rn),
+ Operand::RegisterOrSP(SizeCode::X, Rm),
+ Operand::Nothing,
+ ];
+ }
+ }
} else {
// X1X11010_110XXXXX_XXXXXXXX_XXXXXXXX
// Data-processing (1 source)