template auto M68K::fetch(EffectiveAddress& ea) -> uint32 { if(!ea.valid.raise()) return ea.address; switch(ea.mode) { case DataRegisterDirect: { return read(DataRegister{ea.reg}); } case AddressRegisterDirect: { return read(AddressRegister{ea.reg}); } case AddressRegisterIndirect: { return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithPostIncrement: { return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithPreDecrement: { return read(AddressRegister{ea.reg}); } case AddressRegisterIndirectWithDisplacement: { return read(AddressRegister{ea.reg}) + (int16)readPC(); } case AddressRegisterIndirectWithIndex: { auto extension = readPC(); auto index = extension & 0x8000 ? read(AddressRegister{extension >> 12}) : read(DataRegister{extension >> 12}); if(!(extension & 0x800)) index = (int16)index; return read(AddressRegister{ea.reg}) + index + (int8)extension; } case AbsoluteShortIndirect: { return (int16)readPC(); } case AbsoluteLongIndirect: { return readPC(); } case ProgramCounterIndirectWithDisplacement: { auto base = r.pc; return base + (int16)readPC(); } case ProgramCounterIndirectWithIndex: { auto base = r.pc; auto extension = readPC(); auto index = extension & 0x8000 ? read(AddressRegister{extension >> 12}) : read(DataRegister{extension >> 12}); if(!(extension & 0x800)) index = (int16)index; return base + index + (int8)extension; } case Immediate: { return readPC(); } } return 0; } template auto M68K::read(EffectiveAddress& ea) -> uint32 { ea.address = fetch(ea); switch(ea.mode) { case DataRegisterDirect: { return clip(ea.address); } case AddressRegisterDirect: { return sign(ea.address); } case AddressRegisterIndirect: { return read(ea.address); } case AddressRegisterIndirectWithPostIncrement: { auto address = ea.address + (ea.reg == 7 && Size == Byte ? bytes() : bytes()); auto data = read(ea.address); if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return data; } case AddressRegisterIndirectWithPreDecrement: { auto address = ea.address - (ea.reg == 7 && Size == Byte ? bytes() : bytes()); auto data = read(address); if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return data; } case AddressRegisterIndirectWithDisplacement: { return read(ea.address); } case AddressRegisterIndirectWithIndex: { return read(ea.address); } case AbsoluteShortIndirect: { return read(ea.address); } case AbsoluteLongIndirect: { return read(ea.address); } case ProgramCounterIndirectWithDisplacement: { return read(ea.address); } case ProgramCounterIndirectWithIndex: { return read(ea.address); } case Immediate: { return clip(ea.address); } } return 0; } template auto M68K::write(EffectiveAddress& ea, uint32 data) -> void { ea.address = fetch(ea); switch(ea.mode) { case DataRegisterDirect: { return write(DataRegister{ea.reg}, data); } case AddressRegisterDirect: { return write(AddressRegister{ea.reg}, data); } case AddressRegisterIndirect: { return write(ea.address, data); } case AddressRegisterIndirectWithPostIncrement: { auto address = ea.address + (ea.reg == 7 && Size == Byte ? bytes() : bytes()); write(ea.address, data); if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return; } case AddressRegisterIndirectWithPreDecrement: { auto address = ea.address - (ea.reg == 7 && Size == Byte ? bytes() : bytes()); write(address, data); if(!Hold) write(AddressRegister{ea.reg}, ea.address = address); return; } case AddressRegisterIndirectWithDisplacement: { return write(ea.address, data); } case AddressRegisterIndirectWithIndex: { return write(ea.address, data); } case AbsoluteShortIndirect: { return write(ea.address, data); } case AbsoluteLongIndirect: { return write(ea.address, data); } case ProgramCounterIndirectWithDisplacement: { return write(ea.address, data); } case ProgramCounterIndirectWithIndex: { return write(ea.address, data); } case Immediate: { return; } } }