diff options
author | iximeow <me@iximeow.net> | 2024-03-17 02:34:27 +0000 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2024-03-17 02:34:27 +0000 |
commit | 79d220ce177833f7dd80e15e1094bbfbf4c6f8b1 (patch) | |
tree | 5624ca330ce94299791bab1e44421bbe596a38c1 | |
parent | 2b0930355d87d7f195a7ff05d18b09b61a5ea490 (diff) |
system instruction and register improvements
* cN instead of crN for control registers
* # for immediates in sys/sysl instructions
* write out ARM system register names in the way the ARM reference manual says
-rw-r--r-- | src/armv8/a64.rs | 30 | ||||
-rw-r--r-- | tests/armv8/a64.rs | 20 |
2 files changed, 40 insertions, 10 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index de7a743..19440ba 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -600,20 +600,20 @@ impl Display for Instruction { } }, Opcode::SYS(ops) => { - return write!(fmt, "sys {:#x}, {}, {}, {:#x}, {}", + return write!(fmt, "sys #{:#x}, {}, {}, #{:#x}, {}", ops.op1(), - self.operands[0], self.operands[1], - ops.op2(), self.operands[2], + ops.op2(), + self.operands[0], ); } Opcode::SYSL(ops) => { - return write!(fmt, "sysl {}, {:#x}, {}, {}, {:#x}", - self.operands[0], + return write!(fmt, "sysl {}, #{:#x}, {}, {}, #{:#x}", + self.operands[2], ops.op1(), + self.operands[0], self.operands[1], - self.operands[2], ops.op2(), ); } @@ -2910,7 +2910,7 @@ impl Display for Operand { write!(fmt, "{}, {}", Operand::Register(*size, *reg), Operand::Register(*size, *reg + 1)) }, Operand::ControlReg(reg) => { - write!(fmt, "cr{}", reg) + write!(fmt, "c{}", reg) }, Operand::PrefetchOp(op) => { let ty = (op >> 3) & 0b11; @@ -2933,7 +2933,17 @@ impl Display for Operand { 0x4000 => fmt.write_str("midr_el1"), 0x5e82 => fmt.write_str("tpidr_el0"), 0x5f02 => fmt.write_str("cntvct_el0"), - _ => write!(fmt, "sysreg:{:x}", reg), + _ => { + // syntax for otherwise-undescribed system register names is described in + // MRS or similar, S<op0>_<op1>_<Cn>_<Cm>_<op2> + // ... but that "op0" is `o0` + 2. + let op2 = reg & 0b111; + let CRm = (reg >> 3) & 0b1111; + let CRn = (reg >> 7) & 0b1111; + let op1 = (reg >> 11) & 0b111; + let op0 = ((reg >> 14) & 0b1) + 2; + write!(fmt, "s{op0}_{op1}_c{CRn}_c{CRm}_{op2}") + }, } } Operand::PstateField(reg) => { @@ -10418,7 +10428,7 @@ impl Decoder<ARMv8> for InstDecoder { } } 0b001 => { - let Rt = word & 0b1111; + let Rt = word & 0b11111; let op2 = (word >> 5) & 0b111; let CRm = (word >> 8) & 0b1111; let CRn = (word >> 12) & 0b1111; @@ -10447,7 +10457,7 @@ impl Decoder<ARMv8> for InstDecoder { inst.opcode = Opcode::Invalid; } 0b101 => { - let Rt = word & 0b1111; + let Rt = word & 0b11111; let op2 = (word >> 5) & 0b111; let CRm = (word >> 8) & 0b1111; let CRn = (word >> 12) & 0b1111; diff --git a/tests/armv8/a64.rs b/tests/armv8/a64.rs index 1d04a76..a3ec96e 100644 --- a/tests/armv8/a64.rs +++ b/tests/armv8/a64.rs @@ -4753,6 +4753,26 @@ fn test_vec_shift() { } #[test] +fn test_system() { + const TESTS: &[([u8; 4], &'static str)] = &[ + ([0x00, 0x00, 0x08, 0xd5], "sys #0x0, c0, c0, #0x0, x0"), + ([0x00, 0x00, 0x28, 0xd5], "sysl x0, #0x0, c0, c0, #0x0"), + ([0x10, 0x00, 0x08, 0xd5], "sys #0x0, c0, c0, #0x0, x16"), + ([0x10, 0x00, 0x28, 0xd5], "sysl x16, #0x0, c0, c0, #0x0"), + ([0xab, 0x03, 0x08, 0xd5], "sys #0x0, c0, c3, #0x5, x11"), + ([0xab, 0x03, 0x28, 0xd5], "sysl x11, #0x0, c0, c3, #0x5"), + ([0x00, 0x00, 0x30, 0xd5], "mrs x0, s2_0_c0_c0_0"), + ]; + let errs = run_tests(TESTS); + + for err in errs.iter() { + println!("{}", err); + } + + assert!(errs.is_empty()); +} + +#[test] fn test_pac() { const TESTS: &[([u8; 4], &'static str)] = &[ ([0x00, 0x04, 0xc1, 0xda], "pacib x0, x0"), |