fix(tests): Fix all arm tests

Former-commit-id: a3138584636cc34115207dc6a7b52cf175da187a
This commit is contained in:
Michel Heily 2020-01-17 13:10:26 +02:00
parent 70c72bec2f
commit 9cc293fb02

View file

@ -274,23 +274,31 @@ impl Core {
/// ------------------------------------------------------------------------------
/// For LDR, add y=1S+1N if Rd=R15.
fn exec_ldr_str(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let mut writeback = insn.write_back_flag();
let mut addr = self.get_reg(insn.rn());
if insn.rn() == REG_PC {
let load = insn.load_flag();
let pre_index = insn.pre_index_flag();
let writeback = insn.write_back_flag();
let base_reg = insn.rn();
let dest_reg = insn.rd();
let mut addr = self.get_reg(base_reg);
if base_reg == REG_PC {
addr = insn.pc + 8; // prefetching
}
let offset = self.get_barrel_shifted_value(insn.ldr_str_offset());
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
// TODO - confirm this
let old_mode = self.cpsr.mode();
if !pre_index && writeback {
self.change_mode(old_mode, CpuMode::User);
}
addr = if insn.pre_index_flag() {
effective_addr
} else {
writeback = true;
addr
};
if writeback && insn.rd() == insn.rn() {
writeback = false;
}
if insn.load_flag() {
if load {
self.S_cycle32(sb, self.pc);
let data = if insn.transfer_size() == 1 {
self.N_cycle8(sb, addr);
@ -300,19 +308,19 @@ impl Core {
self.ldr_word(addr, sb)
};
self.set_reg(insn.rd(), data);
self.set_reg(dest_reg, data);
// +1I
self.add_cycle();
if insn.rd() == REG_PC {
if dest_reg == REG_PC {
self.flush_pipeline32(sb);
}
} else {
let value = if insn.rd() == REG_PC {
let value = if dest_reg == REG_PC {
insn.pc + 12
} else {
self.get_reg(insn.rd())
self.get_reg(dest_reg)
};
if insn.transfer_size() == 1 {
self.N_cycle8(sb, addr);
@ -324,34 +332,49 @@ impl Core {
self.N_cycle32(sb, self.pc);
}
if writeback {
self.set_reg(insn.rn(), effective_addr as u32)
if !load || base_reg != dest_reg {
if !pre_index {
self.set_reg(base_reg, effective_addr);
} else if insn.write_back_flag() {
self.set_reg(base_reg, effective_addr);
}
}
if !pre_index && insn.write_back_flag() {
self.change_mode(self.cpsr.mode(), old_mode);
}
Ok(())
}
fn exec_ldr_str_hs(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let mut writeback = insn.write_back_flag();
let mut addr = self.get_reg(insn.rn());
if insn.rn() == REG_PC {
let load = insn.load_flag();
let pre_index = insn.pre_index_flag();
let writeback = insn.write_back_flag();
let base_reg = insn.rn();
let dest_reg = insn.rd();
let mut addr = self.get_reg(base_reg);
if base_reg == REG_PC {
addr = insn.pc + 8; // prefetching
}
let offset = self.get_barrel_shifted_value(insn.ldr_str_hs_offset().unwrap());
// TODO - confirm this
let old_mode = self.cpsr.mode();
if !pre_index && writeback {
println!("SPECIAL CHANGE MODE");
self.change_mode(old_mode, CpuMode::User);
}
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
addr = if insn.pre_index_flag() {
effective_addr
} else {
writeback = true;
addr
};
if writeback && insn.rd() == insn.rn() {
writeback = false;
}
if insn.load_flag() {
if load {
self.S_cycle32(sb, self.pc);
let data = match insn.halfword_data_transfer_type().unwrap() {
ArmHalfwordTransferType::SignedByte => {
@ -368,19 +391,19 @@ impl Core {
}
};
self.set_reg(insn.rd(), data);
self.set_reg(dest_reg, data);
// +1I
self.add_cycle();
if insn.rd() == REG_PC {
if dest_reg == REG_PC {
self.flush_pipeline32(sb);
}
} else {
let value = if insn.rd() == REG_PC {
let value = if dest_reg == REG_PC {
insn.pc + 12
} else {
self.get_reg(insn.rd())
self.get_reg(dest_reg)
};
match insn.halfword_data_transfer_type().unwrap() {
@ -393,26 +416,29 @@ impl Core {
};
}
if writeback {
self.set_reg(insn.rn(), effective_addr as u32)
if !load || base_reg != dest_reg {
if !pre_index {
self.set_reg(base_reg, effective_addr);
} else if insn.write_back_flag() {
self.set_reg(base_reg, effective_addr);
}
}
Ok(())
}
fn exec_ldm_stm(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
let full = insn.pre_index_flag();
let mut full = insn.pre_index_flag();
let ascending = insn.add_offset_flag();
let psr_user_flag = insn.psr_and_force_user_flag();
let s_flag = insn.raw.bit(22);
let is_load = insn.load_flag();
let mut writeback = insn.write_back_flag();
let rn = insn.rn();
let mut addr = self.gpr[rn] as i32;
let base_reg = insn.rn();
let mut base_addr = self.get_reg(base_reg);
let step: i32 = if ascending { 4 } else { -4 };
let rlist = insn.register_list();
if psr_user_flag {
if s_flag {
match self.cpsr.mode() {
CpuMode::User | CpuMode::System => {
panic!("LDM/STM with S bit in unprivileged mode")
@ -421,7 +447,7 @@ impl Core {
};
}
let user_bank_transfer = if psr_user_flag {
let user_bank_transfer = if s_flag {
if is_load {
!rlist.bit(REG_PC)
} else {
@ -431,29 +457,45 @@ impl Core {
false
};
let psr_transfer = psr_user_flag & is_load & rlist.bit(REG_PC);
let old_mode = self.cpsr.mode();
if user_bank_transfer {
self.change_mode(old_mode, CpuMode::User);
}
let psr_transfer = s_flag & is_load & rlist.bit(REG_PC);
let rlist_count = rlist.count_ones();
let old_base = base_addr;
if rlist != 0 && !ascending {
base_addr = base_addr.wrapping_sub(rlist_count * 4);
if writeback {
self.set_reg(base_reg, base_addr);
writeback = false;
}
full = !full;
}
let mut addr = base_addr;
if rlist != 0 {
if is_load {
self.add_cycle();
self.N_cycle32(sb, self.pc);
for r in 0..16 {
let r = if ascending { r } else { 15 - r };
if rlist.bit(r) {
if r == rn {
if r == base_reg {
writeback = false;
}
if full {
addr = addr.wrapping_add(step);
addr = addr.wrapping_add(4);
}
let val = sb.read_32(addr as Addr);
let val = sb.read_32(addr);
self.S_cycle32(sb, self.pc);
if user_bank_transfer {
self.set_reg_user(r, val);
} else {
self.set_reg(r, val);
}
if r == REG_PC {
if psr_transfer {
@ -463,38 +505,47 @@ impl Core {
}
if !full {
addr = addr.wrapping_add(step);
addr = addr.wrapping_add(4);
}
}
}
} else {
let mut first = true;
for r in 0..16 {
let r = if ascending { r } else { 15 - r };
if rlist.bit(r) {
if full {
addr = addr.wrapping_add(step);
}
let val = if r == REG_PC {
let val = if r != base_reg {
if r == REG_PC {
insn.pc + 12
} else {
if user_bank_transfer {
self.get_reg_user(r)
} else {
self.get_reg(r)
}
};
} else {
if first {
self.N_cycle32(sb, addr as u32);
old_base
} else {
let x = rlist_count * 4;
if ascending {
old_base + x
} else {
old_base - x
}
}
};
if full {
addr = addr.wrapping_add(4);
}
if first {
self.N_cycle32(sb, addr);
first = false;
} else {
self.S_cycle32(sb, addr as u32);
self.S_cycle32(sb, addr);
}
self.write_32(addr as Addr, val, sb);
self.write_32(addr, val, sb);
if !full {
addr = addr.wrapping_add(step);
addr = addr.wrapping_add(4);
}
}
}
@ -502,17 +553,21 @@ impl Core {
}
} else {
if is_load {
let val = self.ldr_word(addr as u32, sb);
let val = self.ldr_word(addr, sb);
self.set_reg(REG_PC, val & !3);
self.flush_pipeline32(sb);
} else {
self.write_32(addr as u32, self.pc + 4, sb);
self.write_32(addr, self.pc + 4, sb);
}
addr = addr.wrapping_add(step * 0x10);
addr = addr.wrapping_add(0x40);
}
if user_bank_transfer {
self.change_mode(self.cpsr.mode(), old_mode);
}
if writeback {
self.set_reg(rn, addr as u32);
self.set_reg(base_reg, addr as u32);
}
Ok(())
@ -614,9 +669,9 @@ impl Core {
self.S_cycle8(sb, base_addr);
self.set_reg(insn.rd(), t as u32);
} else {
let t = sb.read_32(base_addr);
let t = self.ldr_word(base_addr, sb);
self.N_cycle32(sb, base_addr);
sb.write_32(base_addr, self.get_reg(insn.rm()));
self.write_32(base_addr, self.get_reg(insn.rm()), sb);
self.S_cycle32(sb, base_addr);
self.set_reg(insn.rd(), t as u32);
}