aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2024-03-17 02:34:27 +0000
committeriximeow <me@iximeow.net>2024-03-17 02:34:27 +0000
commit79d220ce177833f7dd80e15e1094bbfbf4c6f8b1 (patch)
tree5624ca330ce94299791bab1e44421bbe596a38c1
parent2b0930355d87d7f195a7ff05d18b09b61a5ea490 (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.rs30
-rw-r--r--tests/armv8/a64.rs20
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"),