File: r6502.cpp

package info (click to toggle)
higan 094-5
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,780 kB
  • ctags: 15,643
  • sloc: cpp: 103,963; ansic: 659; makefile: 531; sh: 25
file content (241 lines) | stat: -rwxr-xr-x 10,586 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include <processor/processor.hpp>
#include "r6502.hpp"

namespace Processor {

#define I
#define L last_cycle();
#define call(op) (this->*op)()

#include "memory.cpp"
#include "instructions.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"

uint8 R6502::mdr() const {
  return regs.mdr;
}

void R6502::power() {
  regs.a = 0x00;
  regs.x = 0x00;
  regs.y = 0x00;
  regs.s = 0x00;
  regs.p = 0x04;
}

void R6502::reset() {
  regs.mdr = 0x00;
  regs.s -= 3;
  regs.p.i = 1;
}

void R6502::interrupt() {
  op_readpc();
  op_readpc();
  op_writesp(regs.pc >> 8);
  op_writesp(regs.pc >> 0);
  op_writesp(regs.p | 0x20);
  uint16 vector = 0xfffe;  //IRQ
  nmi(vector);
  abs.l = op_read(vector++);
  regs.p.i = 1;
  regs.p.d = 0;
L abs.h = op_read(vector++);
  regs.pc = abs.w;
}

void R6502::exec() {
  uint8 opcode = op_readpci();
  switch(opcode) {
  case 0x00: return op_brk();
  case 0x01: return opi_read_indirect_zero_page_x<&R6502::opf_ora>();
I case 0x04: return opill_nop_zero_page();
  case 0x05: return opi_read_zero_page<&R6502::opf_ora>();
  case 0x06: return opi_rmw_zero_page<&R6502::opf_asl>();
  case 0x08: return op_php();
  case 0x09: return opi_read_immediate<&R6502::opf_ora>();
  case 0x0a: return opi_shift<&R6502::opf_sla>();
I case 0x0c: return opill_nop_absolute();
  case 0x0d: return opi_read_absolute<&R6502::opf_ora>();
  case 0x0e: return opi_rmw_absolute<&R6502::opf_asl>();
  case 0x10: return opi_branch(regs.p.n == 0);
  case 0x11: return opi_read_indirect_zero_page_y<&R6502::opf_ora>();
I case 0x14: return opill_nop_zero_page_x();
  case 0x15: return opi_read_zero_page_x<&R6502::opf_ora>();
  case 0x16: return opi_rmw_zero_page_x<&R6502::opf_asl>();
  case 0x18: return opi_clear_flag(regs.p.c);
  case 0x19: return opi_read_absolute_y<&R6502::opf_ora>();
I case 0x1a: return opill_nop_implied();
I case 0x1c: return opill_nop_absolute_x();
  case 0x1d: return opi_read_absolute_x<&R6502::opf_ora>();
  case 0x1e: return opi_rmw_absolute_x<&R6502::opf_asl>();
  case 0x20: return op_jsr_absolute();
  case 0x21: return opi_read_indirect_zero_page_x<&R6502::opf_and>();
  case 0x24: return opi_read_zero_page<&R6502::opf_bit>();
  case 0x25: return opi_read_zero_page<&R6502::opf_and>();
  case 0x26: return opi_rmw_zero_page<&R6502::opf_rol>();
  case 0x28: return op_plp();
  case 0x29: return opi_read_immediate<&R6502::opf_and>();
  case 0x2a: return opi_shift<&R6502::opf_rla>();
  case 0x2c: return opi_read_absolute<&R6502::opf_bit>();
  case 0x2d: return opi_read_absolute<&R6502::opf_and>();
  case 0x2e: return opi_rmw_absolute<&R6502::opf_rol>();
  case 0x30: return opi_branch(regs.p.n == 1);
  case 0x31: return opi_read_indirect_zero_page_y<&R6502::opf_and>();
I case 0x34: return opill_nop_zero_page_x();
  case 0x35: return opi_read_zero_page_x<&R6502::opf_and>();
  case 0x36: return opi_rmw_zero_page_x<&R6502::opf_rol>();
  case 0x38: return opi_set_flag(regs.p.c);
  case 0x39: return opi_read_absolute_y<&R6502::opf_and>();
I case 0x3a: return opill_nop_implied();
I case 0x3c: return opill_nop_absolute_x();
  case 0x3d: return opi_read_absolute_x<&R6502::opf_and>();
  case 0x3e: return opi_rmw_absolute_x<&R6502::opf_rol>();
  case 0x40: return op_rti();
  case 0x41: return opi_read_indirect_zero_page_x<&R6502::opf_eor>();
I case 0x44: return opill_nop_zero_page();
  case 0x45: return opi_read_zero_page<&R6502::opf_eor>();
  case 0x46: return opi_rmw_zero_page<&R6502::opf_lsr>();
  case 0x48: return opi_push(regs.a);
  case 0x49: return opi_read_immediate<&R6502::opf_eor>();
  case 0x4a: return opi_shift<&R6502::opf_sra>();
  case 0x4c: return op_jmp_absolute();
  case 0x4d: return opi_read_absolute<&R6502::opf_eor>();
  case 0x4e: return opi_rmw_absolute<&R6502::opf_lsr>();
  case 0x50: return opi_branch(regs.p.v == 0);
  case 0x51: return opi_read_indirect_zero_page_y<&R6502::opf_eor>();
I case 0x54: return opill_nop_zero_page_x();
  case 0x55: return opi_read_zero_page_x<&R6502::opf_eor>();
  case 0x56: return opi_rmw_zero_page_x<&R6502::opf_lsr>();
  case 0x58: return opi_clear_flag(regs.p.i);
  case 0x59: return opi_read_absolute_y<&R6502::opf_eor>();
I case 0x5a: return opill_nop_implied();
I case 0x5c: return opill_nop_absolute_x();
  case 0x5d: return opi_read_absolute_x<&R6502::opf_eor>();
  case 0x5e: return opi_rmw_absolute_x<&R6502::opf_lsr>();
  case 0x60: return op_rts();
  case 0x61: return opi_read_indirect_zero_page_x<&R6502::opf_adc>();
I case 0x64: return opill_nop_zero_page();
  case 0x65: return opi_read_zero_page<&R6502::opf_adc>();
  case 0x66: return opi_rmw_zero_page<&R6502::opf_ror>();
  case 0x68: return opi_pull(regs.a);
  case 0x69: return opi_read_immediate<&R6502::opf_adc>();
  case 0x6a: return opi_shift<&R6502::opf_rra>();
I case 0x6b: return opill_arr_immediate();
  case 0x6c: return op_jmp_indirect_absolute();
  case 0x6d: return opi_read_absolute<&R6502::opf_adc>();
  case 0x6e: return opi_rmw_absolute<&R6502::opf_ror>();
  case 0x70: return opi_branch(regs.p.v == 1);
I case 0x74: return opill_nop_zero_page_x();
  case 0x71: return opi_read_indirect_zero_page_y<&R6502::opf_adc>();
  case 0x75: return opi_read_zero_page_x<&R6502::opf_adc>();
  case 0x76: return opi_rmw_zero_page_x<&R6502::opf_ror>();
  case 0x78: return opi_set_flag(regs.p.i);
  case 0x79: return opi_read_absolute_y<&R6502::opf_adc>();
I case 0x7a: return opill_nop_implied();
I case 0x7c: return opill_nop_absolute_x();
  case 0x7d: return opi_read_absolute_x<&R6502::opf_adc>();
  case 0x7e: return opi_rmw_absolute_x<&R6502::opf_ror>();
I case 0x80: return opill_nop_absolute();
  case 0x81: return opi_store_indirect_zero_page_x(regs.a);
I case 0x82: return opill_nop_immediate();
  case 0x84: return opi_store_zero_page(regs.y);
  case 0x85: return opi_store_zero_page(regs.a);
  case 0x86: return opi_store_zero_page(regs.x);
  case 0x88: return opi_decrement(regs.y);
I case 0x89: return opill_nop_immediate();
  case 0x8a: return opi_transfer(regs.x, regs.a, 1);
  case 0x8c: return opi_store_absolute(regs.y);
  case 0x8d: return opi_store_absolute(regs.a);
  case 0x8e: return opi_store_absolute(regs.x);
  case 0x90: return opi_branch(regs.p.c == 0);
  case 0x91: return opi_store_indirect_zero_page_y(regs.a);
  case 0x94: return opi_store_zero_page_x(regs.y);
  case 0x95: return opi_store_zero_page_x(regs.a);
  case 0x96: return opi_store_zero_page_y(regs.x);
  case 0x98: return opi_transfer(regs.y, regs.a, 1);
  case 0x99: return opi_store_absolute_y(regs.a);
  case 0x9a: return opi_transfer(regs.x, regs.s, 0);
  case 0x9d: return opi_store_absolute_x(regs.a);
  case 0xa0: return opi_read_immediate<&R6502::opf_ldy>();
  case 0xa1: return opi_read_indirect_zero_page_x<&R6502::opf_lda>();
  case 0xa2: return opi_read_immediate<&R6502::opf_ldx>();
  case 0xa4: return opi_read_zero_page<&R6502::opf_ldy>();
  case 0xa5: return opi_read_zero_page<&R6502::opf_lda>();
  case 0xa6: return opi_read_zero_page<&R6502::opf_ldx>();
  case 0xa8: return opi_transfer(regs.a, regs.y, 1);
  case 0xa9: return opi_read_immediate<&R6502::opf_lda>();
  case 0xaa: return opi_transfer(regs.a, regs.x, 1);
  case 0xac: return opi_read_absolute<&R6502::opf_ldy>();
  case 0xad: return opi_read_absolute<&R6502::opf_lda>();
  case 0xae: return opi_read_absolute<&R6502::opf_ldx>();
  case 0xb0: return opi_branch(regs.p.c == 1);
  case 0xb1: return opi_read_indirect_zero_page_y<&R6502::opf_lda>();
  case 0xb4: return opi_read_zero_page_x<&R6502::opf_ldy>();
  case 0xb5: return opi_read_zero_page_x<&R6502::opf_lda>();
  case 0xb6: return opi_read_zero_page_y<&R6502::opf_ldx>();
  case 0xb8: return opi_clear_flag(regs.p.v);
  case 0xb9: return opi_read_absolute_y<&R6502::opf_lda>();
  case 0xba: return opi_transfer(regs.s, regs.x, 1);
  case 0xbc: return opi_read_absolute_x<&R6502::opf_ldy>();
  case 0xbd: return opi_read_absolute_x<&R6502::opf_lda>();
  case 0xbe: return opi_read_absolute_y<&R6502::opf_ldx>();
  case 0xc0: return opi_read_immediate<&R6502::opf_cpy>();
  case 0xc1: return opi_read_indirect_zero_page_x<&R6502::opf_cmp>();
I case 0xc2: return opill_nop_immediate();
  case 0xc4: return opi_read_zero_page<&R6502::opf_cpy>();
  case 0xc5: return opi_read_zero_page<&R6502::opf_cmp>();
  case 0xc6: return opi_rmw_zero_page<&R6502::opf_dec>();
  case 0xc8: return opi_increment(regs.y);
  case 0xc9: return opi_read_immediate<&R6502::opf_cmp>();
  case 0xca: return opi_decrement(regs.x);
  case 0xcc: return opi_read_absolute<&R6502::opf_cpy>();
  case 0xcd: return opi_read_absolute<&R6502::opf_cmp>();
  case 0xce: return opi_rmw_absolute<&R6502::opf_dec>();
  case 0xd0: return opi_branch(regs.p.z == 0);
  case 0xd1: return opi_read_indirect_zero_page_y<&R6502::opf_cmp>();
I case 0xd4: return opill_nop_zero_page_x();
  case 0xd5: return opi_read_zero_page_x<&R6502::opf_cmp>();
  case 0xd6: return opi_rmw_zero_page_x<&R6502::opf_dec>();
  case 0xd8: return opi_clear_flag(regs.p.d);
  case 0xd9: return opi_read_absolute_y<&R6502::opf_cmp>();
I case 0xda: return opill_nop_implied();
I case 0xdc: return opill_nop_absolute_x();
  case 0xdd: return opi_read_absolute_x<&R6502::opf_cmp>();
  case 0xde: return opi_rmw_absolute_x<&R6502::opf_dec>();
  case 0xe0: return opi_read_immediate<&R6502::opf_cpx>();
  case 0xe1: return opi_read_indirect_zero_page_x<&R6502::opf_sbc>();
I case 0xe2: return opill_nop_immediate();
  case 0xe4: return opi_read_zero_page<&R6502::opf_cpx>();
  case 0xe5: return opi_read_zero_page<&R6502::opf_sbc>();
  case 0xe6: return opi_rmw_zero_page<&R6502::opf_inc>();
  case 0xe8: return opi_increment(regs.x);
  case 0xe9: return opi_read_immediate<&R6502::opf_sbc>();
  case 0xea: return op_nop();
I case 0xeb: return opi_read_immediate<&R6502::opf_sbc>();
  case 0xec: return opi_read_absolute<&R6502::opf_cpx>();
  case 0xed: return opi_read_absolute<&R6502::opf_sbc>();
  case 0xee: return opi_rmw_absolute<&R6502::opf_inc>();
  case 0xf0: return opi_branch(regs.p.z == 1);
  case 0xf1: return opi_read_indirect_zero_page_y<&R6502::opf_sbc>();
I case 0xf4: return opill_nop_zero_page_x();
  case 0xf5: return opi_read_zero_page_x<&R6502::opf_sbc>();
  case 0xf6: return opi_rmw_zero_page_x<&R6502::opf_inc>();
  case 0xf8: return opi_set_flag(regs.p.d);
  case 0xf9: return opi_read_absolute_y<&R6502::opf_sbc>();
I case 0xfa: return opill_nop_implied();
I case 0xfc: return opill_nop_absolute_x();
  case 0xfd: return opi_read_absolute_x<&R6502::opf_sbc>();
  case 0xfe: return opi_rmw_absolute_x<&R6502::opf_inc>();
  }

  //unimplemented opcode
  return op_nop();
}

#undef I
#undef L
#undef call

}