Skip to content

Commit ecaa985

Browse files
committed
Added support for MCRR instruction
1 parent 33c6870 commit ecaa985

6 files changed

Lines changed: 130 additions & 5 deletions

File tree

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ Here is a list of instructions that are not implemented yet for ArmV7-M archiect
4848
- LDREXH: Load Register Exclusive Halfword
4949
- LDRSBT: Load Register Signed Byte Unprivileged
5050
- LDRSHT: Load Register Signed Halfword Unprivileged
51-
- MCRR, MCRR2: Move to Compressor from two ARM Registers
5251
- MRC, MRC2: Move to Register from Coprocessor
5352
- MRRC, MRRC2: Move to two Registers from Compressor
5453
- PLD: Preload Data
@@ -149,7 +148,6 @@ Here is the list of instructions that are not implemented yet for ArmV8-M archit
149148
- LDRSHT: Load Register Signed Halfword Unprivileged
150149
- LSLS: Logical Shift Left, Setting flags
151150
- LSRS: Logical Shift Right, Setting flags
152-
- MCRR, MCRR2: Move to Compressor from two ARM Registers
153151
- MRC, MRC2: Move to ARM Register from Coprocessor
154152
- MRRC, MRRC2: Move to two ARM Registers from Coprocessor
155153
- PLD: Preload Data

src/decoder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ impl BasicInstructionDecoder {
345345
dec.insert::<instructions::lsr::LsrImm>(version);
346346
dec.insert::<instructions::lsr::LsrReg>(version);
347347
dec.insert::<instructions::mcr::Mcr>(version);
348+
dec.insert::<instructions::mcrr::Mcrr>(version);
348349
dec.insert::<instructions::mla::Mla>(version);
349350
dec.insert::<instructions::mls::Mls>(version);
350351
dec.insert::<instructions::mov::MovImm>(version);

src/instructions/mcrr.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! Implements MCRR and MCRR2 (Move to Coprocessor from two Arm Registers) instructions.
2+
3+
use super::{
4+
Encoding::{self, T1, T2},
5+
Instruction, Pattern,
6+
};
7+
use crate::{
8+
arm::{
9+
ArmProcessor,
10+
ArmVersion::{V7EM, V7M, V8M},
11+
Effect, RunError,
12+
},
13+
decoder::DecodeError,
14+
instructions::{unpredictable, DecodeHelper},
15+
it_state::ItState,
16+
registers::RegisterIndex,
17+
};
18+
19+
/// MCRR or MCRR2 instruction.
20+
///
21+
/// Move to Coprocessor from two Arm Registers.
22+
pub struct Mcrr {
23+
/// Coprocessor index, from 0 to 15.
24+
coproc: u8,
25+
/// Coprocessor-specific opcode, from 0 to 15.
26+
opc1: u8,
27+
/// First Arm source register.
28+
rt: RegisterIndex,
29+
/// Second Arm source register.
30+
rt2: RegisterIndex,
31+
/// Additional coprocessor destination register, from 0 to 15.
32+
crm: u8,
33+
/// Encoding.
34+
encoding: Encoding,
35+
/// Raw encoding.
36+
/// Required since transmitted directly to the coprocessor.
37+
ins: u32,
38+
}
39+
40+
impl Instruction for Mcrr {
41+
fn patterns() -> &'static [Pattern] {
42+
&[
43+
Pattern {
44+
encoding: T1,
45+
versions: &[V7M, V7EM, V8M],
46+
expression: "111011000100xxxxxxxxxxxxxxxxxxxx",
47+
},
48+
Pattern {
49+
encoding: T2,
50+
versions: &[V7M, V7EM, V8M],
51+
expression: "111111000100xxxxxxxxxxxxxxxxxxxx",
52+
},
53+
]
54+
}
55+
56+
fn try_decode(encoding: Encoding, ins: u32, _state: ItState) -> Result<Self, DecodeError> {
57+
debug_assert!((encoding == T1) || (encoding == T2));
58+
let rt = ins.reg4(12);
59+
let rt2 = ins.reg4(16);
60+
unpredictable(rt.is_sp_or_pc() || rt2.is_sp_or_pc())?;
61+
Ok(Self {
62+
coproc: ins.imm4(8) as u8,
63+
opc1: ins.imm4(4) as u8,
64+
rt: ins.reg4(12),
65+
rt2: ins.reg4(16),
66+
crm: ins.imm4(0) as u8,
67+
encoding,
68+
ins,
69+
})
70+
}
71+
72+
fn execute(&self, proc: &mut ArmProcessor) -> Result<Effect, RunError> {
73+
let Some(coprocessor) = proc.coproc_accepted(self.coproc, self.ins) else {
74+
proc.generate_coprocessor_exception();
75+
return Ok(Effect::None);
76+
};
77+
78+
coprocessor
79+
.borrow_mut()
80+
.send_two_words(proc[self.rt2], proc[self.rt], self.ins);
81+
Ok(Effect::None)
82+
}
83+
84+
fn name(&self) -> String {
85+
match self.encoding {
86+
Encoding::T1 => "mcrr",
87+
Encoding::T2 => "mcrr2",
88+
_ => panic!(),
89+
}
90+
.into()
91+
}
92+
93+
fn args(&self, _pc: u32) -> String {
94+
format!(
95+
"p{}, #{}, {}, {}, c{}",
96+
self.coproc, self.opc1, self.rt, self.rt2, self.crm
97+
)
98+
}
99+
}

src/instructions/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub mod ldrt;
5353
pub mod lsl;
5454
pub mod lsr;
5555
pub mod mcr;
56+
pub mod mcrr;
5657
pub mod mla;
5758
pub mod mls;
5859
pub mod mov;

src/test_decoder.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,16 @@ efee777f mcr p15, #7, r7, c15, c7, #3
491491
87fef1e3 mcr2 p3, #4, lr, c7, c1, #7
492492
effe777f mcr2 p15, #7, r7, c15, c7, #3
493493
22fe1f62 mcr2 p2, #1, r6, c2, c15, #0
494+
4eec0010 mcrr p0, #0, r1, lr, c0
495+
41ec3975 mcrr p5, #3, r7, r1, c9
496+
40ec73e7 mcrr p7, #7, lr, r0, c3
497+
47ecf1ae mcrr p14, #15, r10, r7, c1
498+
49ec6f72 mcrr p2, #6, r7, r9, c15
499+
4efc0010 mcrr2 p0, #0, r1, lr, c0
500+
41fc3975 mcrr2 p5, #3, r7, r1, c9
501+
40fc73e7 mcrr2 p7, #7, lr, r0, c3
502+
47fcf1ae mcrr2 p14, #15, r10, r7, c1
503+
49fc6f72 mcrr2 p2, #6, r7, r9, c15
494504
01fb0230 mla r0, r1, r2, r3
495505
05fb0074 mla r4, r5, r0, r7
496506
07fb0809 mla r9, r7, r8, r0
@@ -584,6 +594,7 @@ aff30080 nop.w
584594
66eac372 orn r2, r6, r3, lsl #31
585595
70ea9e27 orns r7, r0, lr, lsr #10
586596
7eea6810 orns r0, lr, r8, asr #5
597+
0000 movs r0, r0
587598
41f00000 orr r0, r1, #0
588599
42f0aa21 orr r1, r2, #2852170240
589600
43f4ff72 orr r2, r3, #510
@@ -1017,3 +1028,4 @@ aff30180 yield.w
10171028
aff30280 wfe.w
10181029
30bf wfi
10191030
aff30380 wfi.w
1031+
0000 movs r0, r0

tests/encode.s

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,20 @@ mcr2 p3, #4, r14, c7, c1, #7
803803
mcr2 p15, #7, r7, c15, c7, #3
804804
mcr2 p2, #1, r6, c2, c15
805805

806+
// MCRR
807+
// T1
808+
mcrr p0, #0, r1, r14, c0
809+
mcrr p5, #3, r7, r1, c9
810+
mcrr p7, #7, r14, r0, c3
811+
mcrr p14, #15, r10, r7, c1
812+
mcrr p2, #6, r7, r9, c15
813+
// T2
814+
mcrr2 p0, #0, r1, r14, c0
815+
mcrr2 p5, #3, r7, r1, c9
816+
mcrr2 p7, #7, r14, r0, c3
817+
mcrr2 p14, #15, r10, r7, c1
818+
mcrr2 p2, #6, r7, r9, c15
819+
806820
// MLA
807821
// T1
808822
mla r0, r1, r2, r3
@@ -950,6 +964,9 @@ orn r2, r6, r3, lsl #31
950964
orns r7, r0, r14, lsr #10
951965
orns r0, r14, r8, asr #5
952966

967+
.org 0x1830
968+
label_far_s12:
969+
953970
// ORR (immediate)
954971
// T1
955972
orr r0, r1, #0
@@ -973,9 +990,6 @@ orr.w r7, r10, r14, lsl #31
973990
orr.w r3, r0, r7, lsr #7
974991
orrs.w r3, r0, r7, asl #3
975992

976-
.org 0x1830
977-
label_far_s12:
978-
979993
// POP
980994
// T1
981995
pop.n {r0}

0 commit comments

Comments
 (0)