use super::{
Encoding::{self, T1},
Instruction, Pattern,
};
use crate::{core::Effect, registers::RegisterIndex};
use crate::{
core::ItState,
core::{
ArmVersion::{V7EM, V7M, V8M},
Processor, RunError,
},
decoder::DecodeError,
instructions::{unpredictable, DecodeHelper},
};
pub struct Smull {
rdlo: RegisterIndex,
rdhi: RegisterIndex,
rn: RegisterIndex,
rm: RegisterIndex,
}
impl Instruction for Smull {
fn patterns() -> &'static [Pattern] {
&[Pattern {
encoding: T1,
versions: &[V7M, V7EM, V8M],
expression: "111110111000xxxxxxxxxxxx0000xxxx",
}]
}
fn try_decode(encoding: Encoding, ins: u32, _state: ItState) -> Result<Self, DecodeError> {
debug_assert_eq!(encoding, T1);
let rdlo = ins.reg4(12);
let rdhi = ins.reg4(8);
let rn = ins.reg4(16);
let rm = ins.reg4(0);
unpredictable(
rdlo.is_sp_or_pc() || rdhi.is_sp_or_pc() || rn.is_sp_or_pc() || rm.is_sp_or_pc(),
)?;
unpredictable(rdlo == rdhi)?;
Ok(Self { rdlo, rdhi, rn, rm })
}
fn execute(&self, proc: &mut Processor) -> Result<Effect, RunError> {
let result = (proc[self.rn] as i32 as i64) * (proc[self.rm] as i32 as i64);
proc.set(self.rdhi, (result >> 32) as u32);
proc.set(self.rdlo, result as u32);
Ok(Effect::None)
}
fn name(&self) -> String {
"smull".into()
}
fn args(&self, _pc: u32) -> String {
format!("{}, {}, {}, {}", self.rdlo, self.rdhi, self.rn, self.rm)
}
}
#[cfg(test)]
mod tests {
use super::Smull;
use crate::{
core::{Config, Processor},
instructions::Instruction,
registers::RegisterIndex,
};
#[test]
fn test_smlal() {
let vectors: [(i32, i32, i64); 5] = [
(10, 10, 100),
(36, -41, -1476),
(0x10101010, 0x78789696, 544681025927825760),
(-482331322, 1684641743, -812555478997574246),
(2127066525, -109506214, -232927002078886350),
];
for v in vectors {
let mut proc = Processor::new(Config::v7m());
let (rdlo, rdhi, rn, rm) = RegisterIndex::pick_four_general_distinct();
proc.set(rn, v.0 as u32);
proc.set(rm, v.1 as u32);
let mut expected = proc.registers.clone();
expected.set(rdhi, (v.2 >> 32) as u32);
expected.set(rdlo, v.2 as u32);
Smull { rdlo, rdhi, rn, rm }.execute(&mut proc).unwrap();
assert_eq!(proc.registers, expected)
}
}
}