Implement thumb format 6 (PC-Relative Load) and test it.
Former-commit-id: ae161edb0c8968913d2ef72a14053c118c6f7692
This commit is contained in:
parent
58e1230e7a
commit
eaf972de93
|
@ -65,11 +65,7 @@ impl Core {
|
|||
}
|
||||
|
||||
/// Cycles 2S+1N
|
||||
fn exec_bx(
|
||||
&mut self,
|
||||
sysbus: &mut Bus,
|
||||
insn: ArmInstruction,
|
||||
) -> CpuResult<CpuPipelineAction> {
|
||||
fn exec_bx(&mut self, sysbus: &mut Bus, insn: ArmInstruction) -> CpuResult<CpuPipelineAction> {
|
||||
let rn = self.get_reg(insn.rn());
|
||||
if rn.bit(0) {
|
||||
self.cpsr.set_state(CpuState::THUMB);
|
||||
|
@ -162,7 +158,13 @@ impl Core {
|
|||
res
|
||||
}
|
||||
|
||||
pub fn alu(&mut self, opcode: ArmOpCode, op1: i32, op2: i32, set_cond_flags: bool) -> Option<i32> {
|
||||
pub fn alu(
|
||||
&mut self,
|
||||
opcode: ArmOpCode,
|
||||
op1: i32,
|
||||
op2: i32,
|
||||
set_cond_flags: bool,
|
||||
) -> Option<i32> {
|
||||
let C = self.cpsr.C() as i32;
|
||||
|
||||
let mut carry = self.cpsr.C();
|
||||
|
@ -314,11 +316,11 @@ impl Core {
|
|||
if insn.load_flag() {
|
||||
let data = if insn.transfer_size() == 1 {
|
||||
// +1N
|
||||
self.add_cycles(dest, sysbus, NonSeq + MemoryAccess8);
|
||||
self.add_cycles(addr, sysbus, NonSeq + MemoryAccess8);
|
||||
sysbus.read_8(addr) as u32
|
||||
} else {
|
||||
// +1N
|
||||
self.add_cycles(dest, sysbus, NonSeq + MemoryAccess32);
|
||||
self.add_cycles(addr, sysbus, NonSeq + MemoryAccess32);
|
||||
sysbus.read_32(addr)
|
||||
};
|
||||
// +1S
|
||||
|
|
|
@ -58,7 +58,7 @@ impl ThumbInstruction {
|
|||
"ldr\t{Rd}, [pc, #{Imm:#x}] ; = #{effective:#x}",
|
||||
Rd = reg_string(self.rd()),
|
||||
Imm = self.word8(),
|
||||
effective = self.pc + 2 + (self.word8() as Addr)
|
||||
effective = (self.pc + 4 & !0b10) + (self.word8() as Addr)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::arm7tdmi::arm::exec::*;
|
||||
use crate::arm7tdmi::arm::ArmOpCode;
|
||||
use crate::arm7tdmi::arm::*;
|
||||
use crate::arm7tdmi::bus::{Bus, MemoryAccessType::*, MemoryAccessWidth::*};
|
||||
use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction};
|
||||
use crate::arm7tdmi::{Addr, REG_PC};
|
||||
|
||||
use super::{ThumbFormat, ThumbInstruction};
|
||||
|
||||
impl Core {
|
||||
fn exec_thumb_data_process_imm(
|
||||
&mut self,
|
||||
sysbus: &mut Bus,
|
||||
bus: &mut Bus,
|
||||
insn: ThumbInstruction,
|
||||
) -> CpuExecResult {
|
||||
let arm_alu_op: ArmOpCode = insn.format3_op().into();
|
||||
|
@ -21,15 +21,34 @@ impl Core {
|
|||
// +1S
|
||||
self.add_cycles(
|
||||
self.pc + (self.word_size() as u32),
|
||||
sysbus,
|
||||
bus,
|
||||
Seq + MemoryAccess32,
|
||||
);
|
||||
Ok(CpuPipelineAction::IncPC)
|
||||
}
|
||||
|
||||
pub fn exec_thumb(&mut self, sysbus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
|
||||
fn exec_thumb_ldr_pc(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
|
||||
let addr = (insn.pc & !0b10) + 4 + (insn.word8() as Addr);
|
||||
let data = bus.read_32(addr);
|
||||
// +1N
|
||||
self.add_cycles(addr, bus, NonSeq + MemoryAccess32);
|
||||
// +1S
|
||||
self.add_cycles(
|
||||
self.pc + (self.word_size() as u32),
|
||||
bus,
|
||||
Seq + MemoryAccess32,
|
||||
);
|
||||
self.set_reg(insn.rd(), data);
|
||||
// +1I
|
||||
self.add_cycle();
|
||||
|
||||
Ok(CpuPipelineAction::IncPC)
|
||||
}
|
||||
|
||||
pub fn exec_thumb(&mut self, bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
|
||||
match insn.fmt {
|
||||
ThumbFormat::DataProcessImm => self.exec_thumb_data_process_imm(sysbus, insn),
|
||||
ThumbFormat::DataProcessImm => self.exec_thumb_data_process_imm(bus, insn),
|
||||
ThumbFormat::LdrPc => self.exec_thumb_ldr_pc(bus, insn),
|
||||
_ => unimplemented!("thumb not implemented {:#}", insn),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -293,4 +293,32 @@ mod tests {
|
|||
);
|
||||
assert_eq!(core.get_reg(0), 0x27);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ldr_pc() {
|
||||
use crate::arm7tdmi::cpu::{Core, CpuPipelineAction};
|
||||
use crate::sysbus::BoxedMemory;
|
||||
|
||||
// ldr r0, [pc, #4]
|
||||
let insn = ThumbInstruction::decode(0x4801, 0x6).unwrap();
|
||||
|
||||
let bytes = vec![
|
||||
/* 0: */ 0x00, 0x00,
|
||||
/* 2: */ 0x00, 0x00,
|
||||
/* 4: */ 0x00, 0x00,
|
||||
/* 6: <pc> */ 0x00, 0x00,
|
||||
/* 8: */ 0x00, 0x00, 0x00, 0x00,
|
||||
/* c: */ 0x78, 0x56, 0x34, 0x12,
|
||||
];
|
||||
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||
let mut core = Core::new();
|
||||
core.set_reg(0, 0);
|
||||
|
||||
assert_eq!(format!("{}", insn), "ldr\tr0, [pc, #0x4] ; = #0xc");
|
||||
assert_eq!(
|
||||
core.exec_thumb(&mut mem, insn),
|
||||
Ok(CpuPipelineAction::IncPC)
|
||||
);
|
||||
assert_eq!(core.get_reg(0), 0x12345678);
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue