More fixes
Former-commit-id: 897cbc0fb9c12469606c48ee8a02d35bf82c2ae5
This commit is contained in:
parent
8dc169d25d
commit
36dba78c55
|
@ -446,16 +446,30 @@ mod tests {
|
||||||
use crate::sysbus::BoxedMemory;
|
use crate::sysbus::BoxedMemory;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_swi() {
|
fn swi() {
|
||||||
|
let mut core = Core::new();
|
||||||
|
|
||||||
|
let bytes = vec![];
|
||||||
|
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||||
|
|
||||||
|
|
||||||
// swi #0x1337
|
// swi #0x1337
|
||||||
let decoded = ArmInstruction::decode(0xef001337, 0).unwrap();
|
let decoded = ArmInstruction::decode(0xef001337, 0).unwrap();
|
||||||
assert_eq!(decoded.fmt, ArmFormat::SWI);
|
assert_eq!(decoded.fmt, ArmFormat::SWI);
|
||||||
assert_eq!(decoded.swi_comment(), 0x1337);
|
assert_eq!(decoded.swi_comment(), 0x1337);
|
||||||
assert_eq!(format!("{}", decoded), "swi\t#0x1337");
|
assert_eq!(format!("{}", decoded), "swi\t#0x1337");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
core.exec_arm(&mut mem, decoded),
|
||||||
|
Ok(CpuPipelineAction::Flush)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(core.cpsr.mode() , CpuMode::Supervisor);
|
||||||
|
assert_eq!(core.pc, Exception::SoftwareInterrupt as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_branch_forwards() {
|
fn branch_forwards() {
|
||||||
// 0x20: b 0x30
|
// 0x20: b 0x30
|
||||||
let decoded = ArmInstruction::decode(0xea_00_00_02, 0x20).unwrap();
|
let decoded = ArmInstruction::decode(0xea_00_00_02, 0x20).unwrap();
|
||||||
assert_eq!(decoded.fmt, ArmFormat::B_BL);
|
assert_eq!(decoded.fmt, ArmFormat::B_BL);
|
||||||
|
@ -465,10 +479,22 @@ mod tests {
|
||||||
0x30
|
0x30
|
||||||
);
|
);
|
||||||
assert_eq!(format!("{}", decoded), "b\t0x30");
|
assert_eq!(format!("{}", decoded), "b\t0x30");
|
||||||
|
|
||||||
|
let mut core = Core::new();
|
||||||
|
core.pc = 0x20 + 8;
|
||||||
|
|
||||||
|
let bytes = vec![];
|
||||||
|
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
core.exec_arm(&mut mem, decoded),
|
||||||
|
Ok(CpuPipelineAction::Flush)
|
||||||
|
);
|
||||||
|
assert_eq!(core.pc, 0x30);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_branch_link_backwards() {
|
fn branch_link_backwards() {
|
||||||
// 0x20: bl 0x10
|
// 0x20: bl 0x10
|
||||||
let decoded = ArmInstruction::decode(0xeb_ff_ff_fa, 0x20).unwrap();
|
let decoded = ArmInstruction::decode(0xeb_ff_ff_fa, 0x20).unwrap();
|
||||||
assert_eq!(decoded.fmt, ArmFormat::B_BL);
|
assert_eq!(decoded.fmt, ArmFormat::B_BL);
|
||||||
|
@ -478,10 +504,22 @@ mod tests {
|
||||||
0x10
|
0x10
|
||||||
);
|
);
|
||||||
assert_eq!(format!("{}", decoded), "bl\t0x10");
|
assert_eq!(format!("{}", decoded), "bl\t0x10");
|
||||||
|
|
||||||
|
let mut core = Core::new();
|
||||||
|
core.pc = 0x20 + 8;
|
||||||
|
|
||||||
|
let bytes = vec![];
|
||||||
|
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
core.exec_arm(&mut mem, decoded),
|
||||||
|
Ok(CpuPipelineAction::Flush)
|
||||||
|
);
|
||||||
|
assert_eq!(core.pc, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_ldr_pre_index() {
|
fn ldr_pre_index() {
|
||||||
// ldreq r2, [r5, -r6, lsl #5]
|
// ldreq r2, [r5, -r6, lsl #5]
|
||||||
let decoded = ArmInstruction::decode(0x07_15_22_86, 0).unwrap();
|
let decoded = ArmInstruction::decode(0x07_15_22_86, 0).unwrap();
|
||||||
assert_eq!(decoded.fmt, ArmFormat::LDR_STR);
|
assert_eq!(decoded.fmt, ArmFormat::LDR_STR);
|
||||||
|
@ -501,11 +539,31 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(format!("{}", decoded), "ldreq\tr2, [r5, -r6, lsl #5]");
|
assert_eq!(format!("{}", decoded), "ldreq\tr2, [r5, -r6, lsl #5]");
|
||||||
|
|
||||||
|
let mut core = Core::new();
|
||||||
|
core.cpsr.set_Z(true);
|
||||||
|
core.gpr[5] = 0x34;
|
||||||
|
core.gpr[6] = 1;
|
||||||
|
core.gpr[2] = 0;
|
||||||
|
|
||||||
|
let bytes = vec![
|
||||||
|
/* 00h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 10h: */ 0x00, 0x00, 0x00, 0x00, 0x37, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
];
|
||||||
|
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
core.exec_arm(&mut mem, decoded),
|
||||||
|
Ok(CpuPipelineAction::IncPC)
|
||||||
|
);
|
||||||
|
assert_eq!(core.gpr[2], 0x1337);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decode_str_post_index() {
|
fn str_post_index() {
|
||||||
// strteq r2, [r4], -r7, lsl #8
|
// strteq r2, [r4], -r7, asr #8
|
||||||
let decoded = ArmInstruction::decode(0x06_24_24_47, 0).unwrap();
|
let decoded = ArmInstruction::decode(0x06_24_24_47, 0).unwrap();
|
||||||
assert_eq!(decoded.fmt, ArmFormat::LDR_STR);
|
assert_eq!(decoded.fmt, ArmFormat::LDR_STR);
|
||||||
assert_eq!(decoded.cond, ArmCond::Equal);
|
assert_eq!(decoded.cond, ArmCond::Equal);
|
||||||
|
@ -524,6 +582,26 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(format!("{}", decoded), "strteq\tr2, [r4], -r7, asr #8");
|
assert_eq!(format!("{}", decoded), "strteq\tr2, [r4], -r7, asr #8");
|
||||||
|
|
||||||
|
let mut core = Core::new();
|
||||||
|
core.cpsr.set_Z(true);
|
||||||
|
core.gpr[4] = 0x0;
|
||||||
|
core.gpr[7] = 1;
|
||||||
|
core.gpr[2] = 0xabababab;
|
||||||
|
|
||||||
|
let bytes = vec![
|
||||||
|
/* 00h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 10h: */ 0x00, 0x00, 0x00, 0x00, 0x37, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 20h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
/* 30h: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
];
|
||||||
|
let mut mem = BoxedMemory::new(bytes.into_boxed_slice());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
core.exec_arm(&mut mem, decoded),
|
||||||
|
Ok(CpuPipelineAction::IncPC)
|
||||||
|
);
|
||||||
|
assert_eq!(mem.read_32(0), 0xabababab);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -41,20 +41,20 @@ where
|
||||||
D: InstructionDecoder,
|
D: InstructionDecoder,
|
||||||
N: Num,
|
N: Num,
|
||||||
{
|
{
|
||||||
fn flush(&mut self) {
|
pub fn flush(&mut self) {
|
||||||
self.fetched = None;
|
self.fetched = None;
|
||||||
self.decoded = None;
|
self.decoded = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_flushed(&self) -> bool {
|
pub fn is_flushed(&self) -> bool {
|
||||||
self.fetched.is_none() && self.decoded.is_none()
|
self.fetched.is_none() && self.decoded.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_only_fetched(&self) -> bool {
|
pub fn is_only_fetched(&self) -> bool {
|
||||||
self.fetched.is_some() && self.decoded.is_none()
|
self.fetched.is_some() && self.decoded.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ready_to_execute(&self) -> bool {
|
pub fn is_ready_to_execute(&self) -> bool {
|
||||||
self.fetched.is_some() && self.decoded.is_some()
|
self.fetched.is_some() && self.decoded.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,11 @@ impl ThumbInstruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_transferring_bytes(&self) -> bool {
|
pub fn is_transferring_bytes(&self) -> bool {
|
||||||
self.raw.bit(10)
|
match self.fmt {
|
||||||
|
ThumbFormat::LdrStrRegOffset => self.raw.bit(10),
|
||||||
|
ThumbFormat::LdrStrImmOffset => self.raw.bit(12),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_load(&self) -> bool {
|
pub fn is_load(&self) -> bool {
|
||||||
|
|
Reference in a new issue