aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-12-29 03:10:43 -0800
committeriximeow <me@iximeow.net>2021-12-29 03:10:43 -0800
commit05b4c99e5c50e49aa79d6fcb0b28df6d300f4117 (patch)
tree0b3e048d6ec5c45d7db9f6e7c04875f8ce1fca72
parente378c361273869fcf8e0f99d7a6260c41dc435a3 (diff)
simd table lookup
-rw-r--r--src/armv8/a64.rs38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 30c80db..8b22e3a 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -1225,6 +1225,9 @@ pub enum Opcode {
CASH(u8),
CASB(u8),
CASP(u8),
+
+ TBL,
+ TBX,
}
impl Display for Opcode {
@@ -1983,6 +1986,8 @@ impl Display for Opcode {
Opcode::STLLRB => "stllrb",
Opcode::STLLRH => "stllrh",
Opcode::STLLR => "stllr",
+ Opcode::TBL => "tbl",
+ Opcode::TBX => "tbx",
Opcode::Bcc(cond) => {
return write!(fmt, "b.{}", Operand::ConditionCode(cond));
@@ -4253,7 +4258,7 @@ impl Decoder<ARMv8> for InstDecoder {
} else if op3 & 0b000100011 == 0b000000010 && op0 & 0b1011 == 0b0000 {
// `Advanced SIMD permute`
let Rd = (word >> 0) & 0b11111;
- let Rn = (word >> 6) & 0b11111;
+ let Rn = (word >> 5) & 0b11111;
let opcode = (word >> 12) & 0b111;
let Rm = (word >> 16) & 0b11111;
let size = (word >> 22) & 0b11;
@@ -4295,6 +4300,37 @@ impl Decoder<ARMv8> for InstDecoder {
Operand::SIMDRegisterElements(vec_size, Rm as u16, size),
Operand::Nothing,
];
+ } else if op3 & 0b000100011 == 0b000000000 && op0 & 0b1011 == 0b0000 {
+ // `Advanced SIMD table lookup`
+ let Rd = (word >> 0) & 0b11111;
+ let Rn = (word >> 5) & 0b11111;
+ let op = (word >> 12) & 0b1;
+ let len = ((word >> 13) & 0b11) as u8;
+ let Rm = (word >> 16) & 0b11111;
+ let op2 = (word >> 22) & 0b11;
+ let Q = (word >> 30) & 1;
+
+ if op2 != 0b00 {
+ return Err(DecodeError::InvalidOpcode);
+ }
+
+ let vec_size = if Q == 0 {
+ SIMDSizeCode::D
+ } else {
+ SIMDSizeCode::Q
+ };
+
+ inst.opcode = if op == 0 {
+ Opcode::TBL
+ } else {
+ Opcode::TBX
+ };
+ inst.operands = [
+ Operand::SIMDRegisterElements(vec_size, Rd as u16, SIMDSizeCode::B),
+ Operand::SIMDRegisterGroup(SIMDSizeCode::Q, Rn as u16, SIMDSizeCode::B, len + 1),
+ Operand::SIMDRegisterElements(vec_size, Rm as u16, SIMDSizeCode::B),
+ Operand::Nothing,
+ ];
} else {
return Err(DecodeError::InvalidOpcode);
}