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 data = read(ea.address); if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); return data; } case AddressRegisterIndirectWithPreDecrement: { auto data = read(ea.address - bytes()); if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); 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: { write(ea.address, data); if(!Hold) write(AddressRegister{ea.reg}, ea.address += bytes()); return; } case AddressRegisterIndirectWithPreDecrement: { write(ea.address - bytes(), data); if(!Hold) write(AddressRegister{ea.reg}, ea.address -= bytes()); 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; } } } template auto M68K::flush(EffectiveAddress& ea, uint32 data) -> void { switch(ea.mode) { case AddressRegisterIndirectWithPostIncrement: { write(AddressRegister{ea.reg}, data); return; } case AddressRegisterIndirectWithPreDecrement: { write(AddressRegister{ea.reg}, data); return; } } }