use crate::cpu::Cpu;
use crate::memory::Memory;
pub fn indexed(cpu: &mut Cpu, mem: &mut impl Memory) -> (u16, u8) {
let post = cpu.fetch_byte(mem);
if post & 0x80 == 0 {
let reg = index_reg(cpu, post);
let offset = if post & 0x10 != 0 {
(post | 0xE0) as i8 as i16 as u16
} else {
(post & 0x1F) as u16
};
let ea = reg.wrapping_add(offset);
return (ea, 1);
}
let indirect = post & 0x10 != 0;
let mode = post & 0x0F;
let (ea, extra) = match mode {
0x00 => {
let reg = index_reg(cpu, post);
let ea = reg;
set_index_reg(cpu, post, reg.wrapping_add(1));
(ea, 2)
}
0x01 => {
let reg = index_reg(cpu, post);
let ea = reg;
set_index_reg(cpu, post, reg.wrapping_add(2));
(ea, 3)
}
0x02 => {
let reg = index_reg(cpu, post).wrapping_sub(1);
set_index_reg(cpu, post, reg);
(reg, 2)
}
0x03 => {
let reg = index_reg(cpu, post).wrapping_sub(2);
set_index_reg(cpu, post, reg);
(reg, 3)
}
0x04 => {
let ea = index_reg(cpu, post);
(ea, 0)
}
0x05 => {
let reg = index_reg(cpu, post);
let offset = cpu.registers().b() as i8 as i16 as u16;
(reg.wrapping_add(offset), 1)
}
0x06 => {
let reg = index_reg(cpu, post);
let offset = cpu.registers().a() as i8 as i16 as u16;
(reg.wrapping_add(offset), 1)
}
0x08 => {
let reg = index_reg(cpu, post);
let offset = cpu.fetch_byte(mem) as i8 as i16 as u16;
(reg.wrapping_add(offset), 1)
}
0x09 => {
let reg = index_reg(cpu, post);
let offset = cpu.fetch_word(mem);
(reg.wrapping_add(offset), 4)
}
0x0B => {
let reg = index_reg(cpu, post);
let offset = cpu.registers().d;
(reg.wrapping_add(offset), 4)
}
0x0C => {
let offset = cpu.fetch_byte(mem) as i8 as i16 as u16;
let ea = cpu.registers().pc.wrapping_add(offset);
(ea, 1)
}
0x0D => {
let offset = cpu.fetch_word(mem);
let ea = cpu.registers().pc.wrapping_add(offset);
(ea, 5)
}
0x0F if indirect => {
let ea = cpu.fetch_word(mem);
let ptr = mem.read_word(ea);
return (ptr, 5);
}
_ => {
(0, 0)
}
};
if indirect {
let ptr = mem.read_word(ea);
(ptr, extra + 3)
} else {
(ea, extra)
}
}
fn index_reg(cpu: &Cpu, post: u8) -> u16 {
match (post >> 5) & 0x03 {
0 => cpu.registers().x,
1 => cpu.registers().y,
2 => cpu.registers().u,
3 => cpu.registers().s,
_ => unreachable!(),
}
}
fn set_index_reg(cpu: &mut Cpu, post: u8, val: u16) {
match (post >> 5) & 0x03 {
0 => cpu.registers_mut().x = val,
1 => cpu.registers_mut().y = val,
2 => cpu.registers_mut().u = val,
3 => {
cpu.registers_mut().s = val;
cpu.arm_nmi();
}
_ => unreachable!(),
}
}