Add special case for MSR immediate
Former-commit-id: f9fabb3c0d7c05243866b712096c2c82cf41672d
This commit is contained in:
parent
a9bf2d25e0
commit
5f625b2209
|
@ -35,7 +35,7 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cycles 2S+1N
|
/// Cycles 2S+1N
|
||||||
fn exec_b_bl(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
fn exec_b_bl(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
if insn.link_flag() {
|
if insn.link_flag() {
|
||||||
self.set_reg(14, (insn.pc + (self.word_size() as u32)) & !0b1);
|
self.set_reg(14, (insn.pc + (self.word_size() as u32)) & !0b1);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ impl Core {
|
||||||
Ok(CpuPipelineAction::Flush)
|
Ok(CpuPipelineAction::Flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn branch_exchange(&mut self, mut addr: Addr) -> CpuResult<CpuPipelineAction> {
|
pub fn branch_exchange(&mut self, mut addr: Addr) -> CpuExecResult {
|
||||||
if addr.bit(0) {
|
if addr.bit(0) {
|
||||||
addr = addr & !0x1;
|
addr = addr & !0x1;
|
||||||
self.cpsr.set_state(CpuState::THUMB);
|
self.cpsr.set_state(CpuState::THUMB);
|
||||||
|
@ -60,21 +60,21 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cycles 2S+1N
|
/// Cycles 2S+1N
|
||||||
fn exec_bx(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
fn exec_bx(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
self.branch_exchange(self.get_reg(insn.rn()))
|
self.branch_exchange(self.get_reg(insn.rn()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_swi(&mut self, _bus: &mut Bus, _insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
fn exec_swi(&mut self, _bus: &mut Bus, _insn: ArmInstruction) -> CpuExecResult {
|
||||||
self.exception(Exception::SoftwareInterrupt);
|
self.exception(Exception::SoftwareInterrupt);
|
||||||
Ok(CpuPipelineAction::Flush)
|
Ok(CpuPipelineAction::Flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_msr_reg(
|
fn exec_msr_reg(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
&mut self,
|
self.exec_msr(insn, self.get_reg(insn.rm()))
|
||||||
_bus: &mut Bus,
|
}
|
||||||
insn: ArmInstruction,
|
|
||||||
) -> CpuResult<CpuPipelineAction> {
|
fn exec_msr(&mut self, insn: ArmInstruction, value: u32) -> CpuExecResult {
|
||||||
let new_psr = RegPSR::new(self.get_reg(insn.rm()));
|
let new_psr = RegPSR::new(value);
|
||||||
let old_mode = self.cpsr.mode();
|
let old_mode = self.cpsr.mode();
|
||||||
if insn.spsr_flag() {
|
if insn.spsr_flag() {
|
||||||
if let Some(index) = old_mode.spsr_index() {
|
if let Some(index) = old_mode.spsr_index() {
|
||||||
|
@ -91,13 +91,9 @@ impl Core {
|
||||||
Ok(CpuPipelineAction::IncPC)
|
Ok(CpuPipelineAction::IncPC)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_msr_flags(
|
fn exec_msr_flags(&mut self, _bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
&mut self,
|
|
||||||
_bus: &mut Bus,
|
|
||||||
insn: ArmInstruction,
|
|
||||||
) -> CpuResult<CpuPipelineAction> {
|
|
||||||
let op = insn.operand2()?;
|
let op = insn.operand2()?;
|
||||||
let op = self.decode_operand2(op)?;
|
let op = self.decode_operand2(op, false)?;
|
||||||
|
|
||||||
let old_mode = self.cpsr.mode();
|
let old_mode = self.cpsr.mode();
|
||||||
if insn.spsr_flag() {
|
if insn.spsr_flag() {
|
||||||
|
@ -112,9 +108,15 @@ impl Core {
|
||||||
Ok(CpuPipelineAction::IncPC)
|
Ok(CpuPipelineAction::IncPC)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_operand2(&mut self, op2: BarrelShifterValue) -> CpuResult<u32> {
|
fn decode_operand2(&mut self, op2: BarrelShifterValue, set_flags: bool) -> CpuResult<u32> {
|
||||||
match op2 {
|
match op2 {
|
||||||
BarrelShifterValue::RotatedImmediate(imm, r) => Ok(imm.rotate_right(r)),
|
BarrelShifterValue::RotatedImmediate(imm, r) => {
|
||||||
|
let result = imm.rotate_right(r);
|
||||||
|
if set_flags {
|
||||||
|
self.cpsr.set_C((result as u32).bit(31));
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
BarrelShifterValue::ShiftedRegister {
|
BarrelShifterValue::ShiftedRegister {
|
||||||
reg,
|
reg,
|
||||||
shift,
|
shift,
|
||||||
|
@ -143,13 +145,27 @@ impl Core {
|
||||||
} else {
|
} else {
|
||||||
self.get_reg(insn.rn()) as i32
|
self.get_reg(insn.rn()) as i32
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let opcode = insn.opcode().unwrap();
|
||||||
|
|
||||||
|
let set_flags = opcode.is_setting_flags() || insn.set_cond_flag();
|
||||||
let op2 = insn.operand2()?;
|
let op2 = insn.operand2()?;
|
||||||
let op2 = self.decode_operand2(op2)? as i32;
|
let op2 = self.decode_operand2(op2, set_flags)? as i32;
|
||||||
|
|
||||||
|
if !insn.set_cond_flag() {
|
||||||
|
match opcode {
|
||||||
|
AluOpCode::TEQ | AluOpCode::CMN => {
|
||||||
|
return self.exec_msr(insn, op2 as u32);
|
||||||
|
}
|
||||||
|
AluOpCode::TST | AluOpCode::CMP => {
|
||||||
|
unimplemented!("TODO implement MRS");
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let rd = insn.rd();
|
let rd = insn.rd();
|
||||||
|
|
||||||
let opcode = insn.opcode().unwrap();
|
|
||||||
let set_flags = opcode.is_setting_flags() || insn.set_cond_flag();
|
|
||||||
if let Some(result) = self.alu(opcode, op1, op2, set_flags) {
|
if let Some(result) = self.alu(opcode, op1, op2, set_flags) {
|
||||||
self.set_reg(rd, result as u32);
|
self.set_reg(rd, result as u32);
|
||||||
if rd == REG_PC {
|
if rd == REG_PC {
|
||||||
|
@ -167,11 +183,7 @@ impl Core {
|
||||||
/// STR{cond}{B}{T} Rd,<Address> | 2N | ---- | [Rn+/-<offset>]=Rd
|
/// STR{cond}{B}{T} Rd,<Address> | 2N | ---- | [Rn+/-<offset>]=Rd
|
||||||
/// ------------------------------------------------------------------------------
|
/// ------------------------------------------------------------------------------
|
||||||
/// For LDR, add y=1S+1N if Rd=R15.
|
/// For LDR, add y=1S+1N if Rd=R15.
|
||||||
fn exec_ldr_str(
|
fn exec_ldr_str(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
&mut self,
|
|
||||||
bus: &mut Bus,
|
|
||||||
insn: ArmInstruction,
|
|
||||||
) -> CpuResult<CpuPipelineAction> {
|
|
||||||
if insn.write_back_flag() && insn.rd() == insn.rn() {
|
if insn.write_back_flag() && insn.rd() == insn.rn() {
|
||||||
return Err(CpuError::IllegalInstruction);
|
return Err(CpuError::IllegalInstruction);
|
||||||
}
|
}
|
||||||
|
@ -227,11 +239,7 @@ impl Core {
|
||||||
Ok(pipeline_action)
|
Ok(pipeline_action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_ldr_str_hs(
|
fn exec_ldr_str_hs(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
&mut self,
|
|
||||||
bus: &mut Bus,
|
|
||||||
insn: ArmInstruction,
|
|
||||||
) -> CpuResult<CpuPipelineAction> {
|
|
||||||
if insn.write_back_flag() && insn.rd() == insn.rn() {
|
if insn.write_back_flag() && insn.rd() == insn.rn() {
|
||||||
return Err(CpuError::IllegalInstruction);
|
return Err(CpuError::IllegalInstruction);
|
||||||
}
|
}
|
||||||
|
@ -361,11 +369,7 @@ impl Core {
|
||||||
Ok(pipeline_action)
|
Ok(pipeline_action)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_mul_mla(
|
fn exec_mul_mla(&mut self, bus: &mut Bus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
&mut self,
|
|
||||||
bus: &mut Bus,
|
|
||||||
insn: ArmInstruction,
|
|
||||||
) -> CpuResult<CpuPipelineAction> {
|
|
||||||
let rd = insn.rd();
|
let rd = insn.rd();
|
||||||
let rn = insn.rn();
|
let rn = insn.rn();
|
||||||
let rs = insn.rs();
|
let rs = insn.rs();
|
||||||
|
|
Reference in a new issue