Skip to content

Instantly share code, notes, and snippets.

@nico-abram
Created June 22, 2019 22:43
Show Gist options
  • Save nico-abram/7939e22d69760a145c14835a1a973b67 to your computer and use it in GitHub Desktop.
Save nico-abram/7939e22d69760a145c14835a1a973b67 to your computer and use it in GitHub Desktop.
// Data Processing or PSR transfer
pub fn PSR(cpu: &mut Cpu, opcode: u32) {
let immediate = as_extra_flag(opcode);
let set_condition_flags = (opcode & 0x0010_0000) != 0;
let (rn, rd, _, _, _) = as_usizes(opcode);
let (_, _, third_byte, second_byte, lowest_byte) = as_bytes(opcode);
let rn = *cpu.reg_mut(rn);
let psr_opcode = ((opcode & 0x01E0_0000) >> 25) as u8;
let op2: u32 = if immediate {
let ror_shift = second_byte & 0x0007;
(lowest_byte as u32).rotate_right(ror_shift as u32) // TODO: Im fairly sure this is wrong
} else {
let register_value: u32 = cpu.regs[lowest_byte as usize];
let shift_by_register = (opcode & 0x0000_0010) != 0;
let shift_amount = if (shift_by_register) {
cpu.regs[third_byte as usize]
} else {
((third_byte as u32) * 2 + ((second_byte & 0x80) as u32))
};
let shift_type = ((opcode & 0x0000_0060) >> 6) as u8;
match shift_type {
0 => register_value.overflowing_shl(shift_amount).0,
1 => register_value.overflowing_shr(shift_amount).0,
1 => register_value.overflowing_shr(shift_amount).0,
2 => (register_value as i32).overflowing_shr(shift_amount).0 as u32,
3 => register_value.rotate_right(shift_amount),
_ => unimplemented!("Impossible"),
}
};
let mut res = &mut cpu.regs[rd];
let mut void = 0u32; // For use by tst and teq
match psr_opcode as u8 {
0 => {
*res = rn & op2;
}
1 => {
*res = rn ^ op2;
}
2 => {
*res = rn - op2;
}
3 => {
*res = op2 - rn;
}
4 => {
*res = rn + op2;
}
5 => {
*res = rn + op2 + (cpu.cpsr.C() as u32);
}
6 => {
*res = rn - op2 + (cpu.cpsr.C() as u32) - 1;
}
7 => {
*res = op2 - rn + (cpu.cpsr.C() as u32) - 1;
}
8 => {
res = &mut void;
//tst
unimplemented!();
}
9 => {
res = &mut void;
//teq
unimplemented!();
}
10 => {
//cmp
unimplemented!();
}
11 => {
//cmn
unimplemented!();
}
12 => {
*res = rn | op2;
}
13 => {
*res = op2;
}
14 => {
*res = rn & (!op2);
}
15 => {
*res = !op2;
}
_ => unimplemented!("Impossible"),
}
if set_condition_flags {
unimplemented!();
// TODO: conditions
}
cpu.clocks += 0; // todo:clocks
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment