aboutsummaryrefslogtreecommitdiff
path: root/src/armv7
diff options
context:
space:
mode:
authorrva3 <rva333@protonmail.com>2026-02-20 03:45:01 +0200
committeriximeow <me@iximeow.net>2026-02-22 03:08:10 +0000
commitfa24eedf78fb9fe2d87ac3f59763e25d3ba4462f (patch)
treef626db67bb33d750be7304c58dca3da260257f77 /src/armv7
parent256c8128d82a5c5d99c1a114f3fb488b28d6b925 (diff)
support A1 encoding of several coprocessor instructions + SVC
initially was "implement MCR/MRC decoding", but expanded to include the whole coprocessor space for completeness, and then SVC is right there too. Neon instructions in this space are still rejected, as neon support is not really there yet. Co-authored-by: iximeow <me@iximeow.net>
Diffstat (limited to 'src/armv7')
-rw-r--r--src/armv7/display.rs83
-rw-r--r--src/armv7/thumb.rs40
2 files changed, 54 insertions, 69 deletions
diff --git a/src/armv7/display.rs b/src/armv7/display.rs
index f81e2cc..5ceedd6 100644
--- a/src/armv7/display.rs
+++ b/src/armv7/display.rs
@@ -462,18 +462,20 @@ pub(crate) fn visit_inst<T: DisplaySink>(instr: &Instruction, out: &mut T) -> fm
_ => {}
}
}
- Opcode::STCL(coproc) |
- Opcode::STC(coproc) |
- Opcode::STC2L(coproc) |
- Opcode::STC2(coproc) |
- Opcode::LDC(coproc) |
- Opcode::LDCL(coproc) |
- Opcode::LDC2(coproc) |
- Opcode::LDC2L(coproc) => {
+ Opcode::STCL(coproc, _) |
+ Opcode::STC(coproc, _) |
+ Opcode::LDC(coproc, _) |
+ Opcode::LDCL(coproc, _) => {
out.span_start_opcode();
unsafe {
out.write_lt_8(instr.opcode.name())?;
}
+ if instr.condition != ConditionCode::AL {
+ let name = instr.condition.name();
+ // all condition codes are two characters long
+ out.write_char(name[0] as char)?;
+ out.write_char(name[1] as char)?;
+ }
out.span_end_opcode();
out.write_fixed_size(" p")?;
if coproc >= 10 {
@@ -497,12 +499,18 @@ pub(crate) fn visit_inst<T: DisplaySink>(instr: &Instruction, out: &mut T) -> fm
return Ok(());
}
- Opcode::MRRC2(coproc, opc) |
- Opcode::MCRR2(coproc, opc) => {
+ Opcode::MRRC(coproc, opc, _) |
+ Opcode::MCRR(coproc, opc, _) => {
out.span_start_opcode();
unsafe {
out.write_lt_8(instr.opcode.name())?;
}
+ if instr.condition != ConditionCode::AL {
+ let name = instr.condition.name();
+ // all condition codes are two characters long
+ out.write_char(name[0] as char)?;
+ out.write_char(name[1] as char)?;
+ }
out.span_end_opcode();
out.write_char(' ')?;
@@ -527,11 +535,17 @@ pub(crate) fn visit_inst<T: DisplaySink>(instr: &Instruction, out: &mut T) -> fm
}
Opcode::MRC(coproc, opc1, opc2, _) |
Opcode::MCR(coproc, opc1, opc2, _) |
- Opcode::CDP2(coproc, opc1, opc2) => {
+ Opcode::CDP(coproc, opc1, opc2, _) => {
out.span_start_opcode();
unsafe {
out.write_lt_8(instr.opcode.name())?;
}
+ if instr.condition != ConditionCode::AL {
+ let name = instr.condition.name();
+ // all condition codes are two characters long
+ out.write_char(name[0] as char)?;
+ out.write_char(name[1] as char)?;
+ }
out.span_end_opcode();
out.write_char(' ')?;
@@ -911,21 +925,15 @@ impl <T: fmt::Write, Y: YaxColors> Colorize<T, Y> for ConditionedOpcode {
Opcode::HVC |
Opcode::SVC |
Opcode::SMC |
- Opcode::LDC(_) |
- Opcode::LDCL(_) |
- Opcode::LDC2(_) |
- Opcode::LDC2L(_) |
- Opcode::STC(_) |
- Opcode::STCL(_) |
- Opcode::STC2(_) |
- Opcode::STC2L(_) |
- Opcode::MCRR2(_, _) |
+ Opcode::LDC(_, _) |
+ Opcode::LDCL(_, _) |
+ Opcode::STC(_, _) |
+ Opcode::STCL(_, _) |
+ Opcode::MCRR(_, _, _) |
Opcode::MCR(_, _, _, _) |
- Opcode::MRRC2(_, _) |
+ Opcode::MRRC(_, _, _) |
Opcode::MRC(_, _, _, _) |
- Opcode::MCRR(_, _) |
- Opcode::MRRC(_, _) |
- Opcode::CDP2(_, _, _) => { write!(out, "{}", colors.platform_op(self)) },
+ Opcode::CDP(_, _, _, _) => { write!(out, "{}", colors.platform_op(self)) },
}
}
}
@@ -950,23 +958,24 @@ impl Opcode {
Opcode::LDRSBT => { "ldrsbt" },
Opcode::STRD => { "strd" },
Opcode::LDRD => { "ldrd" },
- Opcode::LDC(_) => { "ldc" },
- Opcode::LDCL(_) => { "ldcl" },
- Opcode::LDC2(_) => { "ldc2" },
- Opcode::LDC2L(_) => { "ldc2l" },
- Opcode::STC(_) => { "stc" },
- Opcode::STCL(_) => { "stcl" },
- Opcode::STC2(_) => { "stc2" },
- Opcode::STC2L(_) => { "stc2l" },
- Opcode::MCRR2(_, _) => { "mcrr2" },
+ Opcode::LDC(_, false) => { "ldc" },
+ Opcode::LDC(_, true) => { "ldc2" },
+ Opcode::LDCL(_, false) => { "ldcl" },
+ Opcode::LDCL(_, true) => { "ldc2l" },
+ Opcode::STC(_, false) => { "stc" },
+ Opcode::STC(_, true) => { "stc2" },
+ Opcode::STCL(_, false) => { "stcl" },
+ Opcode::STCL(_, true) => { "stc2l" },
Opcode::MCR(_, _, _, false) => { "mcr" },
Opcode::MCR(_, _, _, true) => { "mcr2" },
- Opcode::MRRC2(_, _) => { "mrrc2" },
Opcode::MRC(_, _, _, false) => { "mrc" },
Opcode::MRC(_, _, _, true) => { "mrc2" },
- Opcode::MCRR(_, _) => { "mcrr" },
- Opcode::MRRC(_, _) => { "mrrc" },
- Opcode::CDP2(_, _, _) => { "cdp2" },
+ Opcode::MCRR(_, _, false) => { "mcrr" },
+ Opcode::MCRR(_, _, true) => { "mcrr2" },
+ Opcode::MRRC(_, _, false) => { "mrrc" },
+ Opcode::MRRC(_, _, true) => { "mrrc2" },
+ Opcode::CDP(_, _, _, false) => { "cdp" },
+ Opcode::CDP(_, _, _, true) => { "cdp2" },
Opcode::SRS(true, true) => { "srsib" },
Opcode::SRS(false, true) => { "srsia" },
Opcode::SRS(true, false) => { "srsdb" },
diff --git a/src/armv7/thumb.rs b/src/armv7/thumb.rs
index e18cb38..a2809eb 100644
--- a/src/armv7/thumb.rs
+++ b/src/armv7/thumb.rs
@@ -4253,11 +4253,7 @@ fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: Bit
let opc1 = lower2[4..8].load::<u8>();
let rt = lower2[12..16].load::<u8>();
let rt2 = instr2[0..4].load::<u8>();
- if instr2[12] {
- inst.opcode = Opcode::MCRR2(coproc, opc1);
- } else {
- inst.opcode = Opcode::MCRR(coproc, opc1);
- }
+ inst.opcode = Opcode::MCRR(coproc, opc1, instr2[12]);
inst.operands = [
Operand::Reg(Reg::from_u8(rt)),
Operand::Reg(Reg::from_u8(rt2)),
@@ -4275,11 +4271,7 @@ fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: Bit
// but the operand name is `opc1`!
//
// this is a very uninteresting typo, but fun to spot nonetheless
- if instr2[12] {
- inst.opcode = Opcode::MRRC2(coproc, opc1);
- } else {
- inst.opcode = Opcode::MRRC(coproc, opc1);
- }
+ inst.opcode = Opcode::MRRC(coproc, opc1, instr2[12]);
inst.operands = [
Operand::Reg(Reg::from_u8(rt)),
Operand::Reg(Reg::from_u8(rt2)),
@@ -4296,18 +4288,10 @@ fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: Bit
let crd = lower2[12..16].load::<u8>();
let imm8 = lower2[0..8].load::<u16>();
- if instr2[12] {
- if instr2[6] {
- inst.opcode = Opcode::STC2L(coproc);
- } else {
- inst.opcode = Opcode::STC2(coproc);
- }
+ if instr2[6] {
+ inst.opcode = Opcode::STCL(coproc, instr2[12]);
} else {
- if instr2[6] {
- inst.opcode = Opcode::STCL(coproc);
- } else {
- inst.opcode = Opcode::STC(coproc);
- }
+ inst.opcode = Opcode::STC(coproc, instr2[12]);
}
inst.operands = [
Operand::CReg(CReg::from_u8(crd)),
@@ -4356,18 +4340,10 @@ fn decode_table_a6_30(decoder: &InstDecoder, inst: &mut Instruction, instr2: Bit
// `LDC, LDC2 (immediate) on A8-393`
}
- if instr2[12] {
- if instr2[6] {
- inst.opcode = Opcode::LDC2L(coproc);
- } else {
- inst.opcode = Opcode::LDC2(coproc);
- }
+ if instr2[6] {
+ inst.opcode = Opcode::LDCL(coproc, instr2[12]);
} else {
- if instr2[6] {
- inst.opcode = Opcode::LDCL(coproc);
- } else {
- inst.opcode = Opcode::LDC(coproc);
- }
+ inst.opcode = Opcode::LDC(coproc, instr2[12]);
}
inst.operands = [
Operand::CReg(CReg::from_u8(crd)),