Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module fc.cpu.r6502;
- import common.register16;
- // state
- struct Core {
- InternalState internal;
- ExternalState external;
- }
- struct InternalState {
- ubyte code;
- ubyte time;
- ubyte a;
- ubyte x;
- ubyte y;
- Register16 aa;
- Register16 pc;
- Register16 sp;
- Status p;
- bool interrupt = 1;
- bool irq;
- bool nmi, nmi_latch;
- bool res = 1;
- }
- struct Status {
- bool n;
- bool v;
- bool d;
- bool i;
- bool z;
- bool c;
- }
- struct ExternalState {
- ushort address;
- ubyte data;
- bool irq;
- bool nmi;
- bool res = 1;
- bool read;
- bool ready;
- }
- // logic
- alias Action = void function(Core*);
- Action[][][256] actions;
- void initialize(Core* core) {
- core.internal.sp.w = 0x0100;
- core.external.res = 1;
- core.internal.res = 1;
- core.internal.interrupt = 1;
- }
- void initialize_tables() {
- // todo: this will be a pain in the ass..
- actions[0x00] = [ // brk
- [ &req_irq_pc, &resp_nop ],
- [ &req_irq_push_pch, &resp_nop ],
- [ &req_irq_push_pcl, &resp_nop ],
- [ &req_irq_push_p, &resp_nop ],
- [ &req_vector_l, &resp_pcl ],
- [ &req_vector_h, &resp_pch ],
- [ &req_pc, &resp_code ]
- ];
- actions[0x78] = [ // sei
- [ &req_pc_sei, &resp_nop ],
- [ &req_pc, &resp_code ]
- ];
- }
- void rising_edge(Core* core) {
- auto code = core.internal.code;
- auto time = core.internal.time;
- actions[code][time][0](core);
- }
- void falling_edge(Core* core) {
- sample_interrupts(core);
- auto code = core.internal.code;
- auto time = core.internal.time;
- actions[code][time][1](core);
- }
- void sample_interrupts(Core* core) {
- if (core.internal.nmi_latch < core.external.nmi) {
- core.internal.nmi = 1;
- }
- core.internal.nmi_latch = core.external.nmi;
- core.internal.irq = core.external.irq & !core.internal.p.i;
- core.internal.res = core.external.res;
- core.internal.interrupt = ( core.internal.irq | core.internal.res | core.internal.nmi );
- }
- ubyte pack_flags(Core* core) {
- return
- ( core.internal.p.n << 7 ) |
- ( core.internal.p.v << 6 ) |
- ( core.internal.p.d << 3 ) |
- ( core.internal.p.i << 2 ) |
- ( core.internal.p.z << 1 ) |
- ( core.internal.p.c << 0 ) | 0x30;
- }
- // cycle actions
- void req_pc(Core* core) {
- core.external.address = core.internal.pc.w++;
- core.external.read = 1;
- }
- void req_irq_pc(Core* core) {
- core.external.address = core.internal.pc.w;
- core.external.read = 1;
- if (core.internal.interrupt) {
- core.internal.pc.w--;
- }
- else {
- core.internal.pc.w++;
- }
- }
- void req_irq_push_pch(Core* core) {
- core.external.address = core.internal.sp.w;
- core.external.read = core.internal.res;
- core.internal.sp.l--;
- // only push data on the bus if this is a write cycle
- if (core.external.read == 0) {
- core.external.data = core.internal.pc.h;
- }
- }
- void req_irq_push_pcl(Core* core) {
- core.external.address = core.internal.sp.w;
- core.external.read = core.internal.res;
- core.internal.sp.l--;
- // only push data on the bus if this is a write cycle
- if (core.external.read == 0) {
- core.external.data = core.internal.pc.l;
- }
- }
- void req_irq_push_p(Core* core) {
- core.external.address = core.internal.sp.w;
- core.external.read = core.internal.res;
- core.internal.sp.l--;
- // only push data on the bus if this is a write cycle
- if (core.external.read == 0) {
- core.external.data = pack_flags(core) & ~(core.internal.interrupt << 4);
- }
- core.internal.p.i = 1;
- }
- void req_vector_l(Core* core) {
- core.external.read = 1;
- if (core.internal.res) {
- core.external.address = 0xfffc;
- return;
- }
- if (core.internal.nmi) {
- core.external.address = 0xfffa;
- return;
- }
- core.external.address = 0xfffe;
- }
- void req_vector_h(Core* core) {
- core.external.read = 1;
- if (core.internal.res) {
- core.internal.res = 0;
- core.external.address = 0xfffd;
- return;
- }
- if (core.internal.nmi) {
- core.internal.nmi = 0;
- core.external.address = 0xfffb;
- return;
- }
- core.external.address = 0xffff;
- }
- void req_pc_sei(Core* core) {
- core.external.address = core.internal.pc.w;
- core.external.read = 1;
- core.internal.p.i = 1;
- }
- void resp_nop(Core* core) {
- core.internal.time++;
- }
- void resp_aal(Core* core) {
- core.internal.aa.l = core.external.data;
- core.internal.time++;
- }
- void resp_aah(Core* core) {
- core.internal.aa.h = core.external.data;
- core.internal.time++;
- }
- void resp_pcl(Core* core) {
- core.internal.pc.l = core.external.data;
- core.internal.time++;
- }
- void resp_pch(Core* core) {
- core.internal.pc.h = core.external.data;
- core.internal.time++;
- }
- void resp_code(Core* core) {
- core.internal.code = core.external.data;
- core.internal.time = 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement