Advertisement
Guest User

Untitled

a guest
Oct 17th, 2015
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 5.11 KB | None | 0 0
  1. module fc.cpu.r6502;
  2.  
  3. import common.register16;
  4.  
  5. // state
  6.  
  7. struct Core {
  8.     InternalState internal;
  9.     ExternalState external;
  10. }
  11.  
  12. struct InternalState {
  13.     ubyte code;
  14.     ubyte time;
  15.     ubyte a;
  16.     ubyte x;
  17.     ubyte y;
  18.     Register16 aa;
  19.     Register16 pc;
  20.     Register16 sp;
  21.     Status p;
  22.     bool interrupt = 1;
  23.     bool irq;
  24.     bool nmi, nmi_latch;
  25.     bool res = 1;
  26. }
  27.  
  28. struct Status {
  29.     bool n;
  30.     bool v;
  31.     bool d;
  32.     bool i;
  33.     bool z;
  34.     bool c;
  35. }
  36.  
  37. struct ExternalState {
  38.     ushort address;
  39.     ubyte data;
  40.     bool irq;
  41.     bool nmi;
  42.     bool res = 1;
  43.     bool read;
  44.     bool ready;
  45. }
  46.  
  47. // logic
  48.  
  49. alias Action = void function(Core*);
  50.  
  51. Action[][][256] actions;
  52.  
  53. void initialize(Core* core) {
  54.     core.internal.sp.w = 0x0100;
  55.     core.external.res = 1;
  56.     core.internal.res = 1;
  57.     core.internal.interrupt = 1;
  58. }
  59.  
  60. void initialize_tables() {
  61.     // todo: this will be a pain in the ass..
  62.  
  63.     actions[0x00] = [ // brk
  64.         [ &req_irq_pc,       &resp_nop  ],
  65.         [ &req_irq_push_pch, &resp_nop  ],
  66.         [ &req_irq_push_pcl, &resp_nop  ],
  67.         [ &req_irq_push_p,   &resp_nop  ],
  68.         [ &req_vector_l,     &resp_pcl  ],
  69.         [ &req_vector_h,     &resp_pch  ],
  70.         [ &req_pc,           &resp_code ]
  71.     ];
  72.  
  73.     actions[0x78] = [ // sei
  74.         [ &req_pc_sei, &resp_nop  ],
  75.         [ &req_pc,     &resp_code ]
  76.     ];
  77. }
  78.  
  79. void rising_edge(Core* core) {
  80.     auto code = core.internal.code;
  81.     auto time = core.internal.time;
  82.  
  83.     actions[code][time][0](core);
  84. }
  85.  
  86. void falling_edge(Core* core) {
  87.     sample_interrupts(core);
  88.  
  89.     auto code = core.internal.code;
  90.     auto time = core.internal.time;
  91.  
  92.     actions[code][time][1](core);
  93. }
  94.  
  95. void sample_interrupts(Core* core) {
  96.     if (core.internal.nmi_latch < core.external.nmi) {
  97.         core.internal.nmi = 1;
  98.     }
  99.  
  100.     core.internal.nmi_latch = core.external.nmi;
  101.     core.internal.irq = core.external.irq & !core.internal.p.i;
  102.     core.internal.res = core.external.res;
  103.  
  104.     core.internal.interrupt = ( core.internal.irq | core.internal.res | core.internal.nmi );
  105. }
  106.  
  107. ubyte pack_flags(Core* core) {
  108.     return
  109.         ( core.internal.p.n << 7 ) |
  110.         ( core.internal.p.v << 6 ) |
  111.         ( core.internal.p.d << 3 ) |
  112.         ( core.internal.p.i << 2 ) |
  113.         ( core.internal.p.z << 1 ) |
  114.         ( core.internal.p.c << 0 ) | 0x30;
  115. }
  116.  
  117. // cycle actions
  118.  
  119. void req_pc(Core* core) {
  120.     core.external.address = core.internal.pc.w++;
  121.     core.external.read = 1;
  122. }
  123.  
  124. void req_irq_pc(Core* core) {
  125.     core.external.address = core.internal.pc.w;
  126.     core.external.read = 1;
  127.  
  128.     if (core.internal.interrupt) {
  129.         core.internal.pc.w--;
  130.     }
  131.     else {
  132.         core.internal.pc.w++;
  133.     }
  134. }
  135.  
  136. void req_irq_push_pch(Core* core) {
  137.     core.external.address = core.internal.sp.w;
  138.     core.external.read = core.internal.res;
  139.     core.internal.sp.l--;
  140.  
  141.     // only push data on the bus if this is a write cycle
  142.     if (core.external.read == 0) {
  143.         core.external.data = core.internal.pc.h;
  144.     }
  145. }
  146.  
  147. void req_irq_push_pcl(Core* core) {
  148.     core.external.address = core.internal.sp.w;
  149.     core.external.read = core.internal.res;
  150.     core.internal.sp.l--;
  151.  
  152.     // only push data on the bus if this is a write cycle
  153.     if (core.external.read == 0) {
  154.         core.external.data = core.internal.pc.l;
  155.     }
  156. }
  157.  
  158. void req_irq_push_p(Core* core) {
  159.     core.external.address = core.internal.sp.w;
  160.     core.external.read = core.internal.res;
  161.     core.internal.sp.l--;
  162.  
  163.     // only push data on the bus if this is a write cycle
  164.     if (core.external.read == 0) {
  165.         core.external.data = pack_flags(core) & ~(core.internal.interrupt << 4);
  166.     }
  167.  
  168.     core.internal.p.i = 1;
  169. }
  170.  
  171. void req_vector_l(Core* core) {
  172.     core.external.read = 1;
  173.  
  174.     if (core.internal.res) {
  175.         core.external.address = 0xfffc;
  176.         return;
  177.     }
  178.  
  179.     if (core.internal.nmi) {
  180.         core.external.address = 0xfffa;
  181.         return;
  182.     }
  183.  
  184.     core.external.address = 0xfffe;
  185. }
  186.  
  187. void req_vector_h(Core* core) {
  188.     core.external.read = 1;
  189.  
  190.     if (core.internal.res) {
  191.         core.internal.res = 0;
  192.         core.external.address = 0xfffd;
  193.         return;
  194.     }
  195.  
  196.     if (core.internal.nmi) {
  197.         core.internal.nmi = 0;
  198.         core.external.address = 0xfffb;
  199.         return;
  200.     }
  201.  
  202.     core.external.address = 0xffff;
  203. }
  204.  
  205. void req_pc_sei(Core* core) {
  206.     core.external.address = core.internal.pc.w;
  207.     core.external.read = 1;
  208.     core.internal.p.i = 1;
  209. }
  210.  
  211. void resp_nop(Core* core) {
  212.     core.internal.time++;
  213. }
  214.  
  215. void resp_aal(Core* core) {
  216.     core.internal.aa.l = core.external.data;
  217.     core.internal.time++;
  218. }
  219.  
  220. void resp_aah(Core* core) {
  221.     core.internal.aa.h = core.external.data;
  222.     core.internal.time++;
  223. }
  224.  
  225. void resp_pcl(Core* core) {
  226.     core.internal.pc.l = core.external.data;
  227.     core.internal.time++;
  228. }
  229.  
  230. void resp_pch(Core* core) {
  231.     core.internal.pc.h = core.external.data;
  232.     core.internal.time++;
  233. }
  234.  
  235. void resp_code(Core* core) {
  236.     core.internal.code = core.external.data;
  237.     core.internal.time = 0;
  238. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement