Skip to content

Commit f54dea6

Browse files
committed
Added support for PLD instruction
1 parent e6f6d3a commit f54dea6

6 files changed

Lines changed: 232 additions & 0 deletions

File tree

src/decoder.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,9 @@ impl BasicInstructionDecoder {
373373
dec.insert::<instructions::orr::OrrImm>(version);
374374
dec.insert::<instructions::orr::OrrReg>(version);
375375
dec.insert::<instructions::pop::Pop>(version);
376+
dec.insert::<instructions::pld::PldImm>(version);
377+
dec.insert::<instructions::pld::PldLit>(version);
378+
dec.insert::<instructions::pld::PldReg>(version);
376379
dec.insert::<instructions::push::Push>(version);
377380
dec.insert::<instructions::pssbb::Pssbb>(version);
378381
dec.insert::<instructions::qadd16::Qadd16>(version);

src/instructions/ldrb.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ impl Instruction for LdrbReg {
166166
let rm = ins.reg4(0);
167167
let rt = ins.reg4(12);
168168
let rn = ins.reg4(16);
169+
other(rt.is_pc())?; // PLD
169170
other(rn.is_pc())?; // LDR (literal)
170171
unpredictable(rm.is_sp_or_pc())?;
171172
unpredictable(rt.is_pc() && state.in_it_block_not_last())?;

src/instructions/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub mod mvn;
7575
pub mod nop;
7676
pub mod orn;
7777
pub mod orr;
78+
pub mod pld;
7879
pub mod pop;
7980
pub mod pssbb;
8081
pub mod push;

src/instructions/pld.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//! Implements PLD (Preload Data) instructions.
2+
//!
3+
//! Emulation of this instruction has no effect and is similar to NOP instruction.
4+
5+
use super::{
6+
Encoding::{self, T1, T2},
7+
Pattern,
8+
};
9+
use crate::{
10+
arith::Shift,
11+
core::{
12+
ArmVersion::{V7EM, V7M, V8M},
13+
Effect, ItState, Processor, RunError,
14+
},
15+
decoder::DecodeError,
16+
helpers::BitAccess,
17+
instructions::{indexing_args, other, unpredictable, DecodeHelper, Instruction},
18+
registers::RegisterIndex,
19+
};
20+
21+
/// PLD (immediate) instruction.
22+
///
23+
/// Preload Data.
24+
pub struct PldImm {
25+
/// Base register.
26+
rn: RegisterIndex,
27+
/// True to add offset, false to subtract.
28+
add: bool,
29+
/// Immediate offset applied to Rn.
30+
imm32: u32,
31+
/// Encoding.
32+
encoding: Encoding,
33+
}
34+
35+
impl Instruction for PldImm {
36+
fn patterns() -> &'static [Pattern] {
37+
&[
38+
Pattern {
39+
encoding: T1,
40+
versions: &[V7M, V7EM, V8M],
41+
expression: "111110001001xxxx1111xxxxxxxxxxxx",
42+
},
43+
Pattern {
44+
encoding: T2,
45+
versions: &[V7M, V7EM, V8M],
46+
expression: "111110000001xxxx11111100xxxxxxxx",
47+
},
48+
]
49+
}
50+
51+
fn try_decode(encoding: Encoding, ins: u32, _state: ItState) -> Result<Self, DecodeError> {
52+
let rn = ins.reg4(16);
53+
other(rn.is_pc())?; // PLD (literal)
54+
Ok(match encoding {
55+
T1 => Self {
56+
rn,
57+
add: true,
58+
imm32: ins.imm12(0),
59+
encoding,
60+
},
61+
T2 => Self {
62+
rn,
63+
add: false,
64+
imm32: ins.imm8(0),
65+
encoding,
66+
},
67+
_ => panic!(),
68+
})
69+
}
70+
71+
fn execute(&self, _proc: &mut Processor) -> Result<Effect, RunError> {
72+
Ok(Effect::None)
73+
}
74+
75+
fn name(&self) -> String {
76+
"pld".into()
77+
}
78+
79+
fn args(&self, _pc: u32) -> String {
80+
// #0 and #-0 offsets generate different instructions. Therefore for encoding T2 we want
81+
// the sign to be explicit.
82+
indexing_args(
83+
self.rn,
84+
self.imm32,
85+
self.encoding == T2,
86+
true,
87+
self.add,
88+
false,
89+
)
90+
}
91+
}
92+
93+
/// PLD (literal) instruction.
94+
///
95+
/// Preload Data.
96+
pub struct PldLit {
97+
/// Label offset.
98+
imm32: u32,
99+
/// True to add offset, false to subtract.
100+
add: bool,
101+
}
102+
103+
impl Instruction for PldLit {
104+
fn patterns() -> &'static [Pattern] {
105+
&[Pattern {
106+
encoding: T1,
107+
versions: &[V7M, V7EM, V8M],
108+
expression: "11111000x00111111111xxxxxxxxxxxx",
109+
}]
110+
}
111+
112+
fn try_decode(encoding: Encoding, ins: u32, _state: ItState) -> Result<Self, DecodeError> {
113+
debug_assert_eq!(encoding, T1);
114+
Ok(Self {
115+
imm32: ins.imm12(0),
116+
add: ins.bit(23),
117+
})
118+
}
119+
120+
fn execute(&self, _proc: &mut Processor) -> Result<Effect, RunError> {
121+
Ok(Effect::None)
122+
}
123+
124+
fn name(&self) -> String {
125+
"pld".into()
126+
}
127+
128+
fn args(&self, _pc: u32) -> String {
129+
indexing_args(RegisterIndex::Pc, self.imm32, true, true, self.add, false)
130+
}
131+
}
132+
133+
/// PLD (register) instruction.
134+
///
135+
/// Preload Data.
136+
pub struct PldReg {
137+
/// Base register.
138+
rn: RegisterIndex,
139+
/// Offset register.
140+
rm: RegisterIndex,
141+
/// Shift to be applied to Rm.
142+
shift: Shift,
143+
}
144+
145+
impl Instruction for PldReg {
146+
fn patterns() -> &'static [Pattern] {
147+
&[Pattern {
148+
encoding: T1,
149+
versions: &[V7M, V7EM, V8M],
150+
expression: "111110000001xxxx1111000000xxxxxx",
151+
}]
152+
}
153+
154+
fn try_decode(encoding: Encoding, ins: u32, _state: ItState) -> Result<Self, DecodeError> {
155+
debug_assert_eq!(encoding, T1);
156+
let rn = ins.reg4(16);
157+
let rm = ins.reg4(0);
158+
other(rn.is_pc())?; // PLD (literal)
159+
unpredictable(rm.is_sp_or_pc())?;
160+
Ok(Self {
161+
rn,
162+
rm,
163+
shift: Shift::lsl(ins.imm2(4)),
164+
})
165+
}
166+
167+
fn execute(&self, _proc: &mut Processor) -> Result<Effect, RunError> {
168+
Ok(Effect::None)
169+
}
170+
171+
fn name(&self) -> String {
172+
"pld".into()
173+
}
174+
175+
fn args(&self, _pc: u32) -> String {
176+
format!("[{}, {}{}]", self.rn, self.rm, self.shift.arg_string())
177+
}
178+
}

src/test_decoder.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,26 @@ aff30080 nop.w
665665
4aeace77 orr.w r7, r10, lr, lsl #31
666666
40ead713 orr.w r3, r0, r7, lsr #7
667667
50eac703 orrs.w r3, r0, r7, lsl #3
668+
90f800f0 pld [r0]
669+
93f8aaf0 pld [r3, #170]
670+
97f8ffff pld [r7, #4095]
671+
9cf828f0 pld [r12, #40]
672+
9ef8c4f9 pld [lr, #2500]
673+
10f800fc pld [r0, #-0]
674+
13f8aafc pld [r3, #-170]
675+
17f8fffc pld [r7, #-255]
676+
1cf828fc pld [r12, #-40]
677+
1ef811fc pld [lr, #-17]
678+
9ff800f0 pld [pc, #0]
679+
1ff8ffff pld [pc, #-4095]
680+
9ff8ffff pld [pc, #4095]
681+
9ff8e3f9 pld [pc, #2531]
682+
1ff8f1f6 pld [pc, #-1777]
683+
10f801f0 pld [r0, r1]
684+
13f837f0 pld [r3, r7, lsl #3]
685+
1ef81cf0 pld [lr, r12, lsl #1]
686+
17f80ef0 pld [r7, lr]
687+
12f809f0 pld [r2, r9]
668688
01bc pop {r0}
669689
03bc pop {r0, r1}
670690
3abc pop {r1, r3, r4, r5}

tests/encode.s

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,35 @@ orr.w r7, r10, r14, lsl #31
10731073
orr.w r3, r0, r7, lsr #7
10741074
orrs.w r3, r0, r7, asl #3
10751075

1076+
// PLD (immediate)
1077+
// T1
1078+
pld [r0, #0]
1079+
pld [r3, #170]
1080+
pld [r7, #4095]
1081+
pld [r12, #40]
1082+
pld [r14, #2500]
1083+
// T2
1084+
pld [r0, #-0]
1085+
pld [r3, #-170]
1086+
pld [r7, #-255]
1087+
pld [r12, #-40]
1088+
pld [r14, #-17]
1089+
1090+
// PLD (literal)
1091+
// T1
1092+
pld [pc]
1093+
pld [pc, #-4095]
1094+
pld [pc, #4095]
1095+
pld [pc, #2531]
1096+
pld [pc, #-1777]
1097+
1098+
// PLD (register)
1099+
pld [r0, r1]
1100+
pld [r3, r7, lsl #3]
1101+
pld [r14, r12, lsl #1]
1102+
pld [r7, r14]
1103+
pld [r2, r9]
1104+
10761105
// POP
10771106
// T1
10781107
pop.n {r0}

0 commit comments

Comments
 (0)