aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--src/armv7.rs2
-rw-r--r--src/armv7/display.rs1
-rw-r--r--src/armv7/thumb.rs7
-rw-r--r--tests/armv7/thumb.rs5
5 files changed, 16 insertions, 1 deletions
diff --git a/CHANGELOG b/CHANGELOG
index b0265a1..7b35eaa 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,6 +23,8 @@
* thumb2: unknown wide hints are decoded as `hint` like other cases in ARM,
rather than rejected as invalid
* thumb2: support ARMv8 hints PACBTI, BTI, ESB, PAC, and AUT
+* thumb2: fix `mrc`, `mrc2` use of register number "15", which means apsr_nzcv,
+ rather than pc
* ARMv8: support thumb2 encoding of `Test Target` instruction, `Opcode::TT`
(formatted as any of `tt`, `ttt`, `tta`, `ttat`)
* ARMv8: formerly-coprocessor instructions have been defined into SIMD extensions,
diff --git a/src/armv7.rs b/src/armv7.rs
index 6edb6c9..87b44f5 100644
--- a/src/armv7.rs
+++ b/src/armv7.rs
@@ -660,6 +660,8 @@ pub enum StatusRegMask {
SPSR_FSC = 0b11101,
SPSR_FSX = 0b11110,
SPSR_FSXC = 0b11111,
+ // not part of the above bitpacking, this is encoded by reg number 0b1111 in some instructions.
+ APSR_NZCV = 0b100000,
}
impl StatusRegMask {
diff --git a/src/armv7/display.rs b/src/armv7/display.rs
index 5a48362..1398ce6 100644
--- a/src/armv7/display.rs
+++ b/src/armv7/display.rs
@@ -1330,6 +1330,7 @@ impl StatusRegMask {
StatusRegMask::CPSR_SC => "cpsr_sc",
StatusRegMask::CPSR_SX => "cpsr_sx",
StatusRegMask::CPSR_SXC => "cpsr_sxc",
+ StatusRegMask::APSR_NZCV => "apsr_nzcv",
StatusRegMask::APSR_NZCVQ => "apsr_nzcvq",
StatusRegMask::CPSR_FC => "cpsr_fc",
StatusRegMask::CPSR_FX => "cpsr_fx",
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index d029221..4340e95 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -4418,8 +4418,13 @@ fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: Bit
} else {
// MRC, MRC2 (A8-493)
inst.opcode = Opcode::MRC(coproc, opc1, opc2, is_2);
+ let dest = if CRd == 0b1111 {
+ Operand::StatusRegMask(StatusRegMask::APSR_NZCV)
+ } else {
+ Operand::Reg(Reg::from_u8(CRd))
+ };
inst.operands = [
- Operand::Reg(Reg::from_u8(CRd)),
+ dest,
Operand::CReg(CReg::from_u8(CRn)),
Operand::CReg(CReg::from_u8(CRm)),
Operand::Nothing,
diff --git a/tests/armv7/thumb.rs b/tests/armv7/thumb.rs
index 0c017e9..1278bd6 100644
--- a/tests/armv7/thumb.rs
+++ b/tests/armv7/thumb.rs
@@ -4664,6 +4664,11 @@ fn mrc_mcr_cdp() {
&[0x54, 0xec, 0xa0, 0x91],
"mrrc p1, 10, sb, r4, c0"
);
+
+ test_display(
+ &[0x1a, 0xee, 0xff, 0xf4],
+ "mrc p4, 0, apsr_nzcv, c10, c15, 7",
+ );
}
#[test]