aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-12-31 22:08:11 -0800
committeriximeow <me@iximeow.net>2021-12-31 22:08:11 -0800
commitb460185cca5ad4111cc7907182c307b99c4c21dd (patch)
treee3b075e9bcc9cc8040eb50384357f52d2056099e
parent7c2f7552f78eba6229a3fea352b68a7e0a6dad6c (diff)
fix more invalid rejects, misdecodes, test cases
-rw-r--r--src/armv8/a64.rs248
-rw-r--r--test/armv8/a64.rs34
2 files changed, 151 insertions, 131 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 648703e..cc86ea5 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -4119,7 +4119,7 @@ impl Decoder<ARMv8> for InstDecoder {
return Err(DecodeError::InvalidOpcode);
}
- if size == 0b01 && Q == 1 {
+ if size == 0b10 && Q == 0 {
return Err(DecodeError::InvalidOperand);
}
@@ -4483,21 +4483,28 @@ impl Decoder<ARMv8> for InstDecoder {
Err(DecodeError::InvalidOperand), Err(DecodeError::InvalidOperand),
];
+ const TABLE_K: &'static OperandSizeTable = &[
+ Ok((D, B, D, B)), Ok((Q, B, Q, B)),
+ Ok((D, H, D, H)), Ok((Q, H, Q, H)),
+ Ok((D, S, D, S)), Ok((Q, S, Q, S)),
+ Err(DecodeError::InvalidOperand), Ok((Q, D, Q, D)),
+ ];
+
if op2 & 0b0111 == 0b0100 {
// `Advanced SIMD two-register miscellaneous`
const OPCODES_U0_LOW: &[Result<(Opcode, &'static OperandSizeTable), DecodeError>; 20] = &[
Ok((Opcode::REV64, TABLE_A)),
Ok((Opcode::REV16, TABLE_B)),
Ok((Opcode::SADDLP, TABLE_C)),
- Ok((Opcode::SUQADD, TABLE_A)),
+ Ok((Opcode::SUQADD, TABLE_K)),
Ok((Opcode::CLS, TABLE_A)),
Ok((Opcode::CNT, TABLE_B)),
Ok((Opcode::SADALP, TABLE_C)),
- Ok((Opcode::SQABS, TABLE_A)),
- Ok((Opcode::CMGT, TABLE_A)),
- Ok((Opcode::CMEQ, TABLE_A)),
- Ok((Opcode::CMLT, TABLE_A)),
- Ok((Opcode::ABS, TABLE_A)),
+ Ok((Opcode::SQABS, TABLE_K)),
+ Ok((Opcode::CMGT, TABLE_K)),
+ Ok((Opcode::CMEQ, TABLE_K)),
+ Ok((Opcode::CMLT, TABLE_K)),
+ Ok((Opcode::ABS, TABLE_K)),
// 0b01100, all four size=1x
Ok((Opcode::FCMGT, TABLE_I)),
Ok((Opcode::FCMEQ, TABLE_I)),
@@ -4545,15 +4552,15 @@ impl Decoder<ARMv8> for InstDecoder {
Ok((Opcode::REV32, TABLE_A)),
Err(DecodeError::InvalidOpcode),
Ok((Opcode::UADDLP, TABLE_C)),
- Ok((Opcode::USQADD, TABLE_A)),
+ Ok((Opcode::USQADD, TABLE_K)),
Ok((Opcode::CLZ, TABLE_A)),
Err(DecodeError::InvalidOpcode),
Ok((Opcode::UADALP, TABLE_C)),
- Ok((Opcode::SQNEG, TABLE_A)),
- Ok((Opcode::CMGE, TABLE_A)),
- Ok((Opcode::CMLE, TABLE_A)),
+ Ok((Opcode::SQNEG, TABLE_K)),
+ Ok((Opcode::CMGE, TABLE_K)),
+ Ok((Opcode::CMLE, TABLE_K)),
Err(DecodeError::InvalidOpcode),
- Ok((Opcode::NEG, TABLE_A)),
+ Ok((Opcode::NEG, TABLE_K)),
// 0b01100, all four size=1x
Ok((Opcode::FCMGE, TABLE_I)),
Ok((Opcode::FCMLE, TABLE_I)),
@@ -5985,8 +5992,8 @@ impl Decoder<ARMv8> for InstDecoder {
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
- Err(DecodeError::InvalidOpcode),
- Err(DecodeError::InvalidOpcode),
+ Ok((Opcode::FRECPS, TABLE_C)),
+ Ok((Opcode::FRSQRTS, TABLE_C)),
];
const OPCODES_U1_HIGH: &[Result<(Opcode, &'static OperandSizeTable), DecodeError>; 16] = &[
Err(DecodeError::InvalidOpcode),
@@ -6305,7 +6312,7 @@ impl Decoder<ARMv8> for InstDecoder {
(SIMDSizeCode::Q, SIMDSizeCode::D)
};
- let opcode = match opcode | ((size & 0b10) << 5) {
+ let opcode = match opcode | ((size & 0b10) << 4) {
0b001100 => Opcode::FMAXNMP,
0b001101 => Opcode::FADDP,
0b001111 => Opcode::FMAXP,
@@ -6468,14 +6475,19 @@ impl Decoder<ARMv8> for InstDecoder {
let a = (word >> 23) & 1;
let U = (word >> 29) & 1;
- if opcode < 0b011 {
+ if opcode < 0b010 {
return Err(DecodeError::InvalidOpcode);
}
- let opcode = opcode - 0b011;
+ let opcode = opcode - 0b010;
let index = (opcode << 2) | (U << 1) | a;
inst.opcode = [
+ // opcode == 0b010
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Err(DecodeError::InvalidOpcode),
+ Ok(Opcode::FABD),
// opcode == 0b011
Ok(Opcode::FMULX),
Err(DecodeError::InvalidOpcode),
@@ -6485,7 +6497,7 @@ impl Decoder<ARMv8> for InstDecoder {
Ok(Opcode::FCMEQ),
Err(DecodeError::InvalidOpcode),
Ok(Opcode::FCMGE),
- Err(DecodeError::InvalidOpcode),
+ Ok(Opcode::FCMGT),
// opcode == 0b101
Err(DecodeError::InvalidOpcode),
Err(DecodeError::InvalidOpcode),
@@ -6635,11 +6647,19 @@ impl Decoder<ARMv8> for InstDecoder {
// size=0b01.
match operands_kind {
OperandKind::SameSizes => {
- let size = match size {
- 0b00 => SIMDSizeCode::H,
- 0b01 => { return Err(DecodeError::InvalidOperand); }
- 0b10 => SIMDSizeCode::S,
- _ => SIMDSizeCode::D,
+ let size = if opcode == Opcode::SQDMULH || opcode == Opcode::SQRDMULH || opcode == Opcode::SQRDMLAH || opcode == Opcode::SQRDMLSH {
+ match size {
+ 0b01 => SIMDSizeCode::H,
+ 0b10 => SIMDSizeCode::S,
+ _ => SIMDSizeCode::D,
+ }
+ } else {
+ match size {
+ 0b00 => SIMDSizeCode::H,
+ 0b01 => { return Err(DecodeError::InvalidOperand); }
+ 0b10 => SIMDSizeCode::S,
+ _ => SIMDSizeCode::D,
+ }
};
let (Rm, index) = match size {
@@ -6697,124 +6717,100 @@ impl Decoder<ARMv8> for InstDecoder {
let immb = (word >> 16) & 0b111;
let immh = (word >> 19) & 0b1111;
let U = (word >> 29) & 1;
- let Q = (word >> 30) & 1 == 1;
if immh == 0 {
return Err(DecodeError::InvalidOperand);
}
+ #[allow(non_camel_case_types)]
+ #[derive(Debug)]
enum OperandsKind {
- SameSizes,
- DifferentSizes,
+ D_After,
+ D_Before,
+ BHSD_After,
+ HSD_Before,
+ BHS_HSD_Before,
}
let (opcode, operands_kind) = match (opcode << 1) + U {
- 0b00000_0 => (Opcode::SSHR, OperandsKind::SameSizes),
- 0b00010_0 => (Opcode::SSRA, OperandsKind::SameSizes),
- 0b00100_0 => (Opcode::SRSHR, OperandsKind::SameSizes),
- 0b00110_0 => (Opcode::SRSRA, OperandsKind::SameSizes),
- 0b01010_0 => (Opcode::SHL, OperandsKind::SameSizes),
- 0b01110_0 => (Opcode::SQSHL, OperandsKind::SameSizes),
- 0b10010_0 => (Opcode::SQSHRN, OperandsKind::DifferentSizes),
- 0b10011_0 => (Opcode::SQRSHRN, OperandsKind::DifferentSizes),
- 0b11100_0 => (Opcode::SCVTF, OperandsKind::SameSizes),
- 0b11111_0 => (Opcode::FCVTZS, OperandsKind::SameSizes),
- 0b00000_1 => (Opcode::USHR, OperandsKind::SameSizes),
- 0b00010_1 => (Opcode::USRA, OperandsKind::SameSizes),
- 0b00100_1 => (Opcode::URSHR, OperandsKind::SameSizes),
- 0b00110_1 => (Opcode::URSRA, OperandsKind::SameSizes),
- 0b01000_1 => (Opcode::SRI, OperandsKind::SameSizes),
- 0b01010_1 => (Opcode::SLI, OperandsKind::SameSizes),
- 0b01100_1 => (Opcode::SQSHLU, OperandsKind::SameSizes),
- 0b01110_1 => (Opcode::UQSHL, OperandsKind::SameSizes),
- 0b10000_1 => (Opcode::SQSHRUN, OperandsKind::DifferentSizes),
- 0b10001_1 => (Opcode::SQRSHRUN, OperandsKind::DifferentSizes),
- 0b10010_1 => (Opcode::UQSHRN, OperandsKind::DifferentSizes),
- 0b10011_1 => (Opcode::UQRSHRN, OperandsKind::DifferentSizes),
- 0b11100_1 => (Opcode::UCVTF, OperandsKind::SameSizes),
- 0b11111_1 => (Opcode::FCVTZU, OperandsKind::SameSizes),
+ 0b00000_0 => (Opcode::SSHR, OperandsKind::D_Before),
+ 0b00010_0 => (Opcode::SSRA, OperandsKind::D_Before),
+ 0b00100_0 => (Opcode::SRSHR, OperandsKind::D_Before),
+ 0b00110_0 => (Opcode::SRSRA, OperandsKind::D_Before),
+ 0b01010_0 => (Opcode::SHL, OperandsKind::D_After),
+ 0b01110_0 => (Opcode::SQSHL, OperandsKind::BHSD_After),
+ 0b10010_0 => (Opcode::SQSHRN, OperandsKind::BHS_HSD_Before),
+ 0b10011_0 => (Opcode::SQRSHRN, OperandsKind::BHS_HSD_Before),
+ 0b11100_0 => (Opcode::SCVTF, OperandsKind::HSD_Before),
+ 0b11111_0 => (Opcode::FCVTZS, OperandsKind::HSD_Before),
+ 0b00000_1 => (Opcode::USHR, OperandsKind::D_Before),
+ 0b00010_1 => (Opcode::USRA, OperandsKind::D_Before),
+ 0b00100_1 => (Opcode::URSHR, OperandsKind::D_Before),
+ 0b00110_1 => (Opcode::URSRA, OperandsKind::D_Before),
+ 0b01000_1 => (Opcode::SRI, OperandsKind::D_Before),
+ 0b01010_1 => (Opcode::SLI, OperandsKind::D_After),
+ 0b01100_1 => (Opcode::SQSHLU, OperandsKind::BHSD_After),
+ 0b01110_1 => (Opcode::UQSHL, OperandsKind::BHSD_After),
+ 0b10000_1 => (Opcode::SQSHRUN, OperandsKind::BHS_HSD_Before),
+ 0b10001_1 => (Opcode::SQRSHRUN, OperandsKind::BHS_HSD_Before),
+ 0b10010_1 => (Opcode::UQSHRN, OperandsKind::BHS_HSD_Before),
+ 0b10011_1 => (Opcode::UQRSHRN, OperandsKind::BHS_HSD_Before),
+ 0b11100_1 => (Opcode::UCVTF, OperandsKind::HSD_Before),
+ 0b11111_1 => (Opcode::FCVTZU, OperandsKind::HSD_Before),
_ => { return Err(DecodeError::InvalidOpcode); },
};
- let opcode = if Q {
- if opcode == Opcode::SQSHRN {
- Opcode::SQSHRN2
- } else if opcode == Opcode::SQRSHRN {
- Opcode::SQRSHRN2
- } else if opcode == Opcode::SQSHRUN {
- Opcode::SQSHRUN2
- } else if opcode == Opcode::SQRSHRUN {
- Opcode::SQRSHRUN2
- } else if opcode == Opcode::UQSHRN {
- Opcode::UQSHRN2
- } else if opcode == Opcode::UQRSHRN {
- Opcode::UQRSHRN2
- } else {
- opcode
- }
- } else {
- opcode
- };
-
inst.opcode = opcode;
- match operands_kind {
- OperandsKind::SameSizes => {
- let vec_size = if Q {
- SIMDSizeCode::Q
- } else {
- SIMDSizeCode::D
- };
- let (size, imm) = match immh.leading_zeros() {
- 3 => {
- (SIMDSizeCode::B, immb)
- }
- 2 => {
- (SIMDSizeCode::H, ((immh & 0b0001) << 4)| immb)
- }
- 1 => {
- (SIMDSizeCode::S, ((immh & 0b0011) << 4)| immb)
- }
- 0 => {
- // the +q version of this check would be `Advanced SIMD
- // modified immediate`, checked well before we got
- // here. so assume q is 0, error.
- return Err(DecodeError::InvalidOperand);
- }
- _ => {
- return Err(DecodeError::InvalidOperand);
- }
- };
- inst.operands = [
- Operand::SIMDRegisterElements(vec_size, Rd as u16, size),
- Operand::SIMDRegisterElements(vec_size, Rn as u16, size),
- Operand::Imm16(imm as u16),
- Operand::Nothing,
- ];
+ let immh = immh as u8;
+ let immb = immb as u8;
+
+ let leading_zeros = immh.leading_zeros() - 4;
+
+ let shift = immh << 3 | immb;
+
+ let (a_sz, b_sz, shift) = match operands_kind {
+ OperandsKind::D_After => {
+ if leading_zeros != 0 { return Err(DecodeError::InvalidOperand); }
+ (SIMDSizeCode::D, SIMDSizeCode::D, shift - 64)
},
- OperandsKind::DifferentSizes => {
- let (dest_size, src_size, imm) = match immh.leading_zeros() {
- 3 => {
- (SIMDSizeCode::B, SIMDSizeCode::H, immb)
- }
- 2 => {
- (SIMDSizeCode::H, SIMDSizeCode::S, ((immh & 0b0001) << 4)| immb)
- }
- 1 => {
- (SIMDSizeCode::S, SIMDSizeCode::D, ((immh & 0b0011) << 4)| immb)
- }
- _ => {
- return Err(DecodeError::InvalidOperand);
- }
- };
- inst.operands = [
- Operand::SIMDRegister(dest_size, Rd as u16),
- Operand::SIMDRegister(src_size, Rn as u16),
- Operand::Imm16(imm as u16),
- Operand::Nothing,
- ];
+ OperandsKind::D_Before => {
+ if leading_zeros != 0 { return Err(DecodeError::InvalidOperand); }
+ (SIMDSizeCode::D, SIMDSizeCode::D, 128 - shift)
+ },
+ OperandsKind::BHSD_After => {
+ match leading_zeros {
+ 0 => (SIMDSizeCode::D, SIMDSizeCode::D, shift - 64),
+ 1 => (SIMDSizeCode::S, SIMDSizeCode::S, shift - 32),
+ 2 => (SIMDSizeCode::H, SIMDSizeCode::H, shift - 16),
+ 3 => (SIMDSizeCode::B, SIMDSizeCode::B, shift - 8),
+ _ => { return Err(DecodeError::InvalidOperand); },
+ }
+ },
+ OperandsKind::HSD_Before => {
+ match leading_zeros {
+ 0 => (SIMDSizeCode::D, SIMDSizeCode::D, 128 - shift),
+ 1 => (SIMDSizeCode::S, SIMDSizeCode::S, 64 - shift),
+ 2 => (SIMDSizeCode::H, SIMDSizeCode::H, 32 - shift),
+ _ => { return Err(DecodeError::InvalidOperand); },
+ }
}
- }
+ OperandsKind::BHS_HSD_Before => {
+ match leading_zeros {
+ 1 => (SIMDSizeCode::S, SIMDSizeCode::D, 64 - shift),
+ 2 => (SIMDSizeCode::H, SIMDSizeCode::S, 32 - shift),
+ 3 => (SIMDSizeCode::B, SIMDSizeCode::H, 16 - shift),
+ _ => { return Err(DecodeError::InvalidOperand); },
+ }
+ }
+ };
+
+ inst.operands = [
+ Operand::SIMDRegister(a_sz, Rd as u16),
+ Operand::SIMDRegister(b_sz, Rn as u16),
+ Operand::Imm16(shift as u16),
+ Operand::Nothing,
+ ];
}
}
} else if op0 == 0b1100 {
@@ -8108,7 +8104,7 @@ impl Decoder<ARMv8> for InstDecoder {
let size = (word >> 30) & 0x3;
// load/store exclusive
// o2 == 1
- if Lo1 & 1 == 1 && size < 0b10 {
+ if Lo1 & 1 == 1 {
// o1 == 1
if Rt2 != 0b11111 {
return Err(DecodeError::InvalidOperand);
diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs
index b652ec3..45fa77f 100644
--- a/test/armv8/a64.rs
+++ b/test/armv8/a64.rs
@@ -4752,6 +4752,26 @@ fn test_pac() {
}
#[test]
+fn test_uq() {
+ const TESTS: &[([u8; 4], &'static str)] = &[
+ ([0x00, 0x38, 0xe0, 0x4e], "suqadd v0.2d, v0.2d"),
+ ([0x00, 0x88, 0xe0, 0x4e], "cmgt v0.2d, v0.2d, #0x0"),
+ ([0x00, 0xb8, 0xe0, 0x4e], "abs v0.2d, v0.2d"),
+ ([0x00, 0xfc, 0x20, 0x5e], "frecps s0, s0, s0"),
+ ([0x00, 0xc8, 0xb0, 0x5e], "fminnmp h0, v0.2h"),
+ ([0x00, 0x74, 0x08, 0x5f], "sqshl b0, b0, #0x0"),
+ ([0x00, 0x94, 0x08, 0x5f], "sqshrn b0, h0, #0x8"),
+ ];
+ let errs = run_tests(TESTS);
+
+ for err in errs.iter() {
+ println!("{}", err);
+ }
+
+ assert!(errs.is_empty());
+}
+
+#[test]
fn test_cfi() {
const TESTS: &[([u8; 4], &'static str)] = &[
([0x1f, 0x08, 0x1f, 0xd6], "braaz x0"),
@@ -4809,12 +4829,11 @@ fn test_misc() {
([0x00, 0x94, 0x08, 0x4f], "sqshrn2 v0.16b, v0.8h, #0x8"),
([0x00, 0x28, 0x40, 0x4f], "smlal2 v0.4s, v0.8h, v0.h[4]"),
([0x00, 0xc0, 0x40, 0x4f], "sqdmulh v0.8h, v0.8h, v0.h[0]"),
- ([0x00, 0xc0, 0x40, 0x4f], "sqrdmulh v0.8h, v0.8h, v0.h[0]"),
([0x00, 0xe0, 0x80, 0x4f], "sdot v0.4s, v0.16b, v0.4b[0]"),
([0x00, 0x24, 0x40, 0x5e], "fcmeq h0, h0, h0"),
([0x00, 0x88, 0xe0, 0x5e], "cmgt d0, d0, #0x0"),
([0x00, 0xa8, 0xf9, 0x5e], "fcvtps h0, h0"),
- ([0x00, 0x10, 0x10, 0x5f], "fmla h0,h h0, v0.h[1]"),
+ ([0x00, 0x10, 0x10, 0x5f], "fmla h0, h0, v0.h[1]"),
([0x00, 0xd0, 0x40, 0x5f], "sqrdmulh h0, h0, v0.h[0]"),
([0x00, 0x10, 0xd0, 0x5f], "fmla d0, d0, v16.d[0]"),
([0x1f, 0x00, 0x20, 0x6b], "cmp w0, w0, uxtb"),
@@ -4823,8 +4842,6 @@ fn test_misc() {
([0x00, 0x28, 0x21, 0x6e], "sqxtun2 v0.16b, v0.8h"),
([0x1f, 0x00, 0x00, 0x72], "tst w0, #0x1"),
([0x00, 0x84, 0x40, 0x7e], "sqrdmlah h0, h0, h0"),
- ([0x00, 0xd0, 0x40, 0x7f], "sqrdmlah h0, h0, v0.h[0]"),
- ([0x00, 0xd0, 0x40, 0x7f], "sqrdmlsh h0, h0, v0.h[0]"),
([0x1f, 0x00, 0x20, 0x8b], "add sp, x0, w0, uxtb"),
([0x00, 0x00, 0x00, 0x00], "add x0, x0, #0x0"),
([0x1f, 0x00, 0x00, 0x91], "mov sp, x0"),
@@ -4836,10 +4853,17 @@ fn test_misc() {
([0x00, 0x08, 0x00, 0xf8], "sttr x0, [x0]"),
([0x00, 0x14, 0x20, 0xf8], "ldraa x0, [x0, #0x8]"),
([0x00, 0x00, 0x80, 0xf8], "prfum pldl1keep, [x0]"),
- ([0x06, 0x48, 0xa0, 0xf8], "prfm 0x6, [x0, w0, uxtw]"),
+ ([0x06, 0x48, 0xa0, 0xf8], "prfm 0x6, [x0, w0, uxtw]"),
([0xe0, 0x03, 0x00, 0x0b], "add w0, wzr, w0"),
([0x00, 0xc0, 0x40, 0x0f], "sqdmulh v0.4h, v0.4h, v0.h[0]"),
([0x00, 0xd0, 0x40, 0x0f], "sqrdmulh v0.4h, v0.4h, v0.h[0]"),
+ ([0x00, 0xc0, 0x40, 0x5f], "sqdmulh h0, h0, v0.h[0]"),
+ ([0x00, 0x10, 0x40, 0x6f], "fcmla v0.8h, v0.8h, v0.h[0]"),
+ ([0x00, 0x10, 0x80, 0x6f], "fcmla v0.4s, v0.4s, v0.s[0]"),
+ ([0x00, 0x14, 0xc0, 0x7e], "fabd h0, h0, h0"),
+ ([0x00, 0x24, 0xc0, 0x7e], "fcmgt h0, h0, h0"),
+ ([0x00, 0xd0, 0x40, 0x7f], "sqrdmlah h0, h0, v0.h[0]"),
+ ([0x00, 0x7c, 0xa0, 0x88], "cas w0, w0, [x0]"),
];
let errs = run_tests(TESTS);