fix(tests): Fix all arm tests
Former-commit-id: a3138584636cc34115207dc6a7b52cf175da187a
This commit is contained in:
parent
70c72bec2f
commit
9cc293fb02
|
@ -274,23 +274,31 @@ impl Core {
|
||||||
/// ------------------------------------------------------------------------------
|
/// ------------------------------------------------------------------------------
|
||||||
/// For LDR, add y=1S+1N if Rd=R15.
|
/// For LDR, add y=1S+1N if Rd=R15.
|
||||||
fn exec_ldr_str(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
fn exec_ldr_str(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
let mut writeback = insn.write_back_flag();
|
let load = insn.load_flag();
|
||||||
let mut addr = self.get_reg(insn.rn());
|
let pre_index = insn.pre_index_flag();
|
||||||
if insn.rn() == REG_PC {
|
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
|
addr = insn.pc + 8; // prefetching
|
||||||
}
|
}
|
||||||
let offset = self.get_barrel_shifted_value(insn.ldr_str_offset());
|
let offset = self.get_barrel_shifted_value(insn.ldr_str_offset());
|
||||||
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
|
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() {
|
addr = if insn.pre_index_flag() {
|
||||||
effective_addr
|
effective_addr
|
||||||
} else {
|
} else {
|
||||||
writeback = true;
|
|
||||||
addr
|
addr
|
||||||
};
|
};
|
||||||
if writeback && insn.rd() == insn.rn() {
|
|
||||||
writeback = false;
|
if load {
|
||||||
}
|
|
||||||
if insn.load_flag() {
|
|
||||||
self.S_cycle32(sb, self.pc);
|
self.S_cycle32(sb, self.pc);
|
||||||
let data = if insn.transfer_size() == 1 {
|
let data = if insn.transfer_size() == 1 {
|
||||||
self.N_cycle8(sb, addr);
|
self.N_cycle8(sb, addr);
|
||||||
|
@ -300,19 +308,19 @@ impl Core {
|
||||||
self.ldr_word(addr, sb)
|
self.ldr_word(addr, sb)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_reg(insn.rd(), data);
|
self.set_reg(dest_reg, data);
|
||||||
|
|
||||||
// +1I
|
// +1I
|
||||||
self.add_cycle();
|
self.add_cycle();
|
||||||
|
|
||||||
if insn.rd() == REG_PC {
|
if dest_reg == REG_PC {
|
||||||
self.flush_pipeline32(sb);
|
self.flush_pipeline32(sb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let value = if insn.rd() == REG_PC {
|
let value = if dest_reg == REG_PC {
|
||||||
insn.pc + 12
|
insn.pc + 12
|
||||||
} else {
|
} else {
|
||||||
self.get_reg(insn.rd())
|
self.get_reg(dest_reg)
|
||||||
};
|
};
|
||||||
if insn.transfer_size() == 1 {
|
if insn.transfer_size() == 1 {
|
||||||
self.N_cycle8(sb, addr);
|
self.N_cycle8(sb, addr);
|
||||||
|
@ -324,34 +332,49 @@ impl Core {
|
||||||
self.N_cycle32(sb, self.pc);
|
self.N_cycle32(sb, self.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if writeback {
|
if !load || base_reg != dest_reg {
|
||||||
self.set_reg(insn.rn(), effective_addr as u32)
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_ldr_str_hs(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
fn exec_ldr_str_hs(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
||||||
let mut writeback = insn.write_back_flag();
|
let load = insn.load_flag();
|
||||||
|
let pre_index = insn.pre_index_flag();
|
||||||
let mut addr = self.get_reg(insn.rn());
|
let writeback = insn.write_back_flag();
|
||||||
if insn.rn() == REG_PC {
|
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
|
addr = insn.pc + 8; // prefetching
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = self.get_barrel_shifted_value(insn.ldr_str_hs_offset().unwrap());
|
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;
|
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
|
||||||
addr = if insn.pre_index_flag() {
|
addr = if insn.pre_index_flag() {
|
||||||
effective_addr
|
effective_addr
|
||||||
} else {
|
} else {
|
||||||
writeback = true;
|
|
||||||
addr
|
addr
|
||||||
};
|
};
|
||||||
if writeback && insn.rd() == insn.rn() {
|
|
||||||
writeback = false;
|
if load {
|
||||||
}
|
|
||||||
if insn.load_flag() {
|
|
||||||
self.S_cycle32(sb, self.pc);
|
self.S_cycle32(sb, self.pc);
|
||||||
let data = match insn.halfword_data_transfer_type().unwrap() {
|
let data = match insn.halfword_data_transfer_type().unwrap() {
|
||||||
ArmHalfwordTransferType::SignedByte => {
|
ArmHalfwordTransferType::SignedByte => {
|
||||||
|
@ -368,19 +391,19 @@ impl Core {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.set_reg(insn.rd(), data);
|
self.set_reg(dest_reg, data);
|
||||||
|
|
||||||
// +1I
|
// +1I
|
||||||
self.add_cycle();
|
self.add_cycle();
|
||||||
|
|
||||||
if insn.rd() == REG_PC {
|
if dest_reg == REG_PC {
|
||||||
self.flush_pipeline32(sb);
|
self.flush_pipeline32(sb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let value = if insn.rd() == REG_PC {
|
let value = if dest_reg == REG_PC {
|
||||||
insn.pc + 12
|
insn.pc + 12
|
||||||
} else {
|
} else {
|
||||||
self.get_reg(insn.rd())
|
self.get_reg(dest_reg)
|
||||||
};
|
};
|
||||||
|
|
||||||
match insn.halfword_data_transfer_type().unwrap() {
|
match insn.halfword_data_transfer_type().unwrap() {
|
||||||
|
@ -393,26 +416,29 @@ impl Core {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if writeback {
|
if !load || base_reg != dest_reg {
|
||||||
self.set_reg(insn.rn(), effective_addr as u32)
|
if !pre_index {
|
||||||
|
self.set_reg(base_reg, effective_addr);
|
||||||
|
} else if insn.write_back_flag() {
|
||||||
|
self.set_reg(base_reg, effective_addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_ldm_stm(&mut self, sb: &mut SysBus, insn: ArmInstruction) -> CpuExecResult {
|
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 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 is_load = insn.load_flag();
|
||||||
let mut writeback = insn.write_back_flag();
|
let mut writeback = insn.write_back_flag();
|
||||||
let rn = insn.rn();
|
let base_reg = insn.rn();
|
||||||
let mut addr = self.gpr[rn] as i32;
|
let mut base_addr = self.get_reg(base_reg);
|
||||||
|
|
||||||
let step: i32 = if ascending { 4 } else { -4 };
|
|
||||||
let rlist = insn.register_list();
|
let rlist = insn.register_list();
|
||||||
|
|
||||||
if psr_user_flag {
|
if s_flag {
|
||||||
match self.cpsr.mode() {
|
match self.cpsr.mode() {
|
||||||
CpuMode::User | CpuMode::System => {
|
CpuMode::User | CpuMode::System => {
|
||||||
panic!("LDM/STM with S bit in unprivileged mode")
|
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 {
|
if is_load {
|
||||||
!rlist.bit(REG_PC)
|
!rlist.bit(REG_PC)
|
||||||
} else {
|
} else {
|
||||||
|
@ -431,29 +457,45 @@ impl Core {
|
||||||
false
|
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 rlist != 0 {
|
||||||
if is_load {
|
if is_load {
|
||||||
self.add_cycle();
|
self.add_cycle();
|
||||||
self.N_cycle32(sb, self.pc);
|
self.N_cycle32(sb, self.pc);
|
||||||
for r in 0..16 {
|
for r in 0..16 {
|
||||||
let r = if ascending { r } else { 15 - r };
|
|
||||||
if rlist.bit(r) {
|
if rlist.bit(r) {
|
||||||
if r == rn {
|
if r == base_reg {
|
||||||
writeback = false;
|
writeback = false;
|
||||||
}
|
}
|
||||||
if full {
|
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);
|
self.S_cycle32(sb, self.pc);
|
||||||
if user_bank_transfer {
|
|
||||||
self.set_reg_user(r, val);
|
self.set_reg(r, val);
|
||||||
} else {
|
|
||||||
self.set_reg(r, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if r == REG_PC {
|
if r == REG_PC {
|
||||||
if psr_transfer {
|
if psr_transfer {
|
||||||
|
@ -463,38 +505,47 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !full {
|
if !full {
|
||||||
addr = addr.wrapping_add(step);
|
addr = addr.wrapping_add(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for r in 0..16 {
|
for r in 0..16 {
|
||||||
let r = if ascending { r } else { 15 - r };
|
|
||||||
if rlist.bit(r) {
|
if rlist.bit(r) {
|
||||||
if full {
|
let val = if r != base_reg {
|
||||||
addr = addr.wrapping_add(step);
|
if r == REG_PC {
|
||||||
}
|
insn.pc + 12
|
||||||
|
|
||||||
let val = if r == REG_PC {
|
|
||||||
insn.pc + 12
|
|
||||||
} else {
|
|
||||||
if user_bank_transfer {
|
|
||||||
self.get_reg_user(r)
|
|
||||||
} else {
|
} else {
|
||||||
self.get_reg(r)
|
self.get_reg(r)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if first {
|
||||||
|
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 {
|
if first {
|
||||||
self.N_cycle32(sb, addr as u32);
|
self.N_cycle32(sb, addr);
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} 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 {
|
if !full {
|
||||||
addr = addr.wrapping_add(step);
|
addr = addr.wrapping_add(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -502,17 +553,21 @@ impl Core {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if is_load {
|
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.set_reg(REG_PC, val & !3);
|
||||||
self.flush_pipeline32(sb);
|
self.flush_pipeline32(sb);
|
||||||
} else {
|
} 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 {
|
if writeback {
|
||||||
self.set_reg(rn, addr as u32);
|
self.set_reg(base_reg, addr as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -614,9 +669,9 @@ impl Core {
|
||||||
self.S_cycle8(sb, base_addr);
|
self.S_cycle8(sb, base_addr);
|
||||||
self.set_reg(insn.rd(), t as u32);
|
self.set_reg(insn.rd(), t as u32);
|
||||||
} else {
|
} else {
|
||||||
let t = sb.read_32(base_addr);
|
let t = self.ldr_word(base_addr, sb);
|
||||||
self.N_cycle32(sb, base_addr);
|
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.S_cycle32(sb, base_addr);
|
||||||
self.set_reg(insn.rd(), t as u32);
|
self.set_reg(insn.rd(), t as u32);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue