1 /*
2 
3 						Extracted from original single fake6502.c file
4 
5 */
6 //
7 //          65C02 changes.
8 //
9 //          BRK                 now clears D
10 //          ADC/SBC             set N and Z in decimal mode. They also set V, but this is
11 //                              essentially meaningless so this has not been implemented.
12 //
13 //
14 //
15 //          instruction handler functions
16 //
adc()17 static void adc() {
18     penaltyop = 1;
19     #ifndef NES_CPU
20     if (status & FLAG_DECIMAL) {
21         uint16_t tmp, tmp2;
22         value = getvalue();
23         tmp = ((uint16_t)a & 0x0F) + (value & 0x0F) + (uint16_t)(status & FLAG_CARRY);
24         tmp2 = ((uint16_t)a & 0xF0) + (value & 0xF0);
25         if (tmp > 0x09) {
26             tmp2 += 0x10;
27             tmp += 0x06;
28         }
29         if (tmp2 > 0x90) {
30             tmp2 += 0x60;
31         }
32         if (tmp2 & 0xFF00) {
33             setcarry();
34         } else {
35             clearcarry();
36         }
37         result = (tmp & 0x0F) | (tmp2 & 0xF0);
38 
39         zerocalc(result);                /* 65C02 change, Decimal Arithmetic sets NZV */
40         signcalc(result);
41 
42         clockticks6502++;
43     } else {
44     #endif
45         value = getvalue();
46         result = (uint16_t)a + value + (uint16_t)(status & FLAG_CARRY);
47 
48         carrycalc(result);
49         zerocalc(result);
50         overflowcalc(result, a, value);
51         signcalc(result);
52     #ifndef NES_CPU
53     }
54     #endif
55 
56     saveaccum(result);
57 }
58 
and()59 static void and() {
60     penaltyop = 1;
61     value = getvalue();
62     result = (uint16_t)a & value;
63 
64     zerocalc(result);
65     signcalc(result);
66 
67     saveaccum(result);
68 }
69 
asl()70 static void asl() {
71     value = getvalue();
72     result = value << 1;
73 
74     carrycalc(result);
75     zerocalc(result);
76     signcalc(result);
77 
78     putvalue(result);
79 }
80 
bcc()81 static void bcc() {
82     if ((status & FLAG_CARRY) == 0) {
83         oldpc = pc;
84         pc += reladdr;
85         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
86             else clockticks6502++;
87     }
88 }
89 
bcs()90 static void bcs() {
91     if ((status & FLAG_CARRY) == FLAG_CARRY) {
92         oldpc = pc;
93         pc += reladdr;
94         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
95             else clockticks6502++;
96     }
97 }
98 
beq()99 static void beq() {
100     if ((status & FLAG_ZERO) == FLAG_ZERO) {
101         oldpc = pc;
102         pc += reladdr;
103         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
104             else clockticks6502++;
105     }
106 }
107 
bit()108 static void bit() {
109     value = getvalue();
110     result = (uint16_t)a & value;
111 
112     zerocalc(result);
113     status = (status & 0x3F) | (uint8_t)(value & 0xC0);
114 }
115 
bmi()116 static void bmi() {
117     if ((status & FLAG_SIGN) == FLAG_SIGN) {
118         oldpc = pc;
119         pc += reladdr;
120         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
121             else clockticks6502++;
122     }
123 }
124 
bne()125 static void bne() {
126     if ((status & FLAG_ZERO) == 0) {
127         oldpc = pc;
128         pc += reladdr;
129         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
130             else clockticks6502++;
131     }
132 }
133 
bpl()134 static void bpl() {
135     if ((status & FLAG_SIGN) == 0) {
136         oldpc = pc;
137         pc += reladdr;
138         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
139             else clockticks6502++;
140     }
141 }
142 
brk()143 static void brk() {
144     pc++;
145 
146 
147     push16(pc); //push next instruction address onto stack
148     push8(status | FLAG_BREAK); //push CPU status to stack
149     setinterrupt(); //set interrupt flag
150     cleardecimal();       // clear decimal flag (65C02 change)
151     pc = (uint16_t)read6502(0xFFFE) | ((uint16_t)read6502(0xFFFF) << 8);
152 }
153 
bvc()154 static void bvc() {
155     if ((status & FLAG_OVERFLOW) == 0) {
156         oldpc = pc;
157         pc += reladdr;
158         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
159             else clockticks6502++;
160     }
161 }
162 
bvs()163 static void bvs() {
164     if ((status & FLAG_OVERFLOW) == FLAG_OVERFLOW) {
165         oldpc = pc;
166         pc += reladdr;
167         if ((oldpc & 0xFF00) != (pc & 0xFF00)) clockticks6502 += 2; //check if jump crossed a page boundary
168             else clockticks6502++;
169     }
170 }
171 
clc()172 static void clc() {
173     clearcarry();
174 }
175 
cld()176 static void cld() {
177     cleardecimal();
178 }
179 
cli()180 static void cli() {
181     clearinterrupt();
182 }
183 
clv()184 static void clv() {
185     clearoverflow();
186 }
187 
cmp()188 static void cmp() {
189     penaltyop = 1;
190     value = getvalue();
191     result = (uint16_t)a - value;
192 
193     if (a >= (uint8_t)(value & 0x00FF)) setcarry();
194         else clearcarry();
195     if (a == (uint8_t)(value & 0x00FF)) setzero();
196         else clearzero();
197     signcalc(result);
198 }
199 
cpx()200 static void cpx() {
201     value = getvalue();
202     result = (uint16_t)x - value;
203 
204     if (x >= (uint8_t)(value & 0x00FF)) setcarry();
205         else clearcarry();
206     if (x == (uint8_t)(value & 0x00FF)) setzero();
207         else clearzero();
208     signcalc(result);
209 }
210 
cpy()211 static void cpy() {
212     value = getvalue();
213     result = (uint16_t)y - value;
214 
215     if (y >= (uint8_t)(value & 0x00FF)) setcarry();
216         else clearcarry();
217     if (y == (uint8_t)(value & 0x00FF)) setzero();
218         else clearzero();
219     signcalc(result);
220 }
221 
dec()222 static void dec() {
223     value = getvalue();
224     result = value - 1;
225 
226     zerocalc(result);
227     signcalc(result);
228 
229     putvalue(result);
230 }
231 
dex()232 static void dex() {
233     x--;
234 
235     zerocalc(x);
236     signcalc(x);
237 }
238 
dey()239 static void dey() {
240     y--;
241 
242     zerocalc(y);
243     signcalc(y);
244 }
245 
eor()246 static void eor() {
247     penaltyop = 1;
248     value = getvalue();
249     result = (uint16_t)a ^ value;
250 
251     zerocalc(result);
252     signcalc(result);
253 
254     saveaccum(result);
255 }
256 
inc()257 static void inc() {
258     value = getvalue();
259     result = value + 1;
260 
261     zerocalc(result);
262     signcalc(result);
263 
264     putvalue(result);
265 }
266 
inx()267 static void inx() {
268     x++;
269 
270     zerocalc(x);
271     signcalc(x);
272 }
273 
iny()274 static void iny() {
275     y++;
276 
277     zerocalc(y);
278     signcalc(y);
279 }
280 
jmp()281 static void jmp() {
282     pc = ea;
283 }
284 
jsr()285 static void jsr() {
286     push16(pc - 1);
287     pc = ea;
288 }
289 
lda()290 static void lda() {
291     penaltyop = 1;
292     value = getvalue();
293     a = (uint8_t)(value & 0x00FF);
294 
295     zerocalc(a);
296     signcalc(a);
297 }
298 
ldx()299 static void ldx() {
300     penaltyop = 1;
301     value = getvalue();
302     x = (uint8_t)(value & 0x00FF);
303 
304     zerocalc(x);
305     signcalc(x);
306 }
307 
ldy()308 static void ldy() {
309     penaltyop = 1;
310     value = getvalue();
311     y = (uint8_t)(value & 0x00FF);
312 
313     zerocalc(y);
314     signcalc(y);
315 }
316 
lsr()317 static void lsr() {
318     value = getvalue();
319     result = value >> 1;
320 
321     if (value & 1) setcarry();
322         else clearcarry();
323     zerocalc(result);
324     signcalc(result);
325 
326     putvalue(result);
327 }
328 
nop()329 static void nop() {
330     switch (opcode) {
331         case 0x1C:
332         case 0x3C:
333         case 0x5C:
334         case 0x7C:
335         case 0xDC:
336         case 0xFC:
337             penaltyop = 1;
338             break;
339     }
340 }
341 
ora()342 static void ora() {
343     penaltyop = 1;
344     value = getvalue();
345     result = (uint16_t)a | value;
346 
347     zerocalc(result);
348     signcalc(result);
349 
350     saveaccum(result);
351 }
352 
pha()353 static void pha() {
354     push8(a);
355 }
356 
php()357 static void php() {
358     push8(status | FLAG_BREAK);
359 }
360 
pla()361 static void pla() {
362     a = pull8();
363 
364     zerocalc(a);
365     signcalc(a);
366 }
367 
plp()368 static void plp() {
369     status = pull8() | FLAG_CONSTANT;
370 }
371 
rol()372 static void rol() {
373     value = getvalue();
374     result = (value << 1) | (status & FLAG_CARRY);
375 
376     carrycalc(result);
377     zerocalc(result);
378     signcalc(result);
379 
380     putvalue(result);
381 }
382 
ror()383 static void ror() {
384     value = getvalue();
385     result = (value >> 1) | ((status & FLAG_CARRY) << 7);
386 
387     if (value & 1) setcarry();
388         else clearcarry();
389     zerocalc(result);
390     signcalc(result);
391 
392     putvalue(result);
393 }
394 
rti()395 static void rti() {
396     status = pull8();
397     value = pull16();
398     pc = value;
399 }
400 
rts()401 static void rts() {
402     value = pull16();
403     pc = value + 1;
404 }
405 
sbc()406 static void sbc() {
407     penaltyop = 1;
408 
409     #ifndef NES_CPU
410     if (status & FLAG_DECIMAL) {
411         value = getvalue();
412         result = (uint16_t)a - (value & 0x0f) + (status & FLAG_CARRY) - 1;
413         if ((result & 0x0f) > (a & 0x0f)) {
414             result -= 6;
415         }
416         result -= (value & 0xf0);
417         if ((result & 0xfff0) > ((uint16_t)a & 0xf0)) {
418             result -= 0x60;
419         }
420         if (result <= (uint16_t)a) {
421             setcarry();
422         } else {
423             clearcarry();
424         }
425 
426         zerocalc(result);                /* 65C02 change, Decimal Arithmetic sets NZV */
427         signcalc(result);
428 
429         clockticks6502++;
430     } else {
431     #endif
432         value = getvalue() ^ 0x00FF;
433         result = (uint16_t)a + value + (uint16_t)(status & FLAG_CARRY);
434 
435         carrycalc(result);
436         zerocalc(result);
437         overflowcalc(result, a, value);
438         signcalc(result);
439     #ifndef NES_CPU
440     }
441     #endif
442 
443     saveaccum(result);
444 }
445 
sec()446 static void sec() {
447     setcarry();
448 }
449 
sed()450 static void sed() {
451     setdecimal();
452 }
453 
sei()454 static void sei() {
455     setinterrupt();
456 }
457 
sta()458 static void sta() {
459     putvalue(a);
460 }
461 
stx()462 static void stx() {
463     putvalue(x);
464 }
465 
sty()466 static void sty() {
467     putvalue(y);
468 }
469 
tax()470 static void tax() {
471     x = a;
472 
473     zerocalc(x);
474     signcalc(x);
475 }
476 
tay()477 static void tay() {
478     y = a;
479 
480     zerocalc(y);
481     signcalc(y);
482 }
483 
tsx()484 static void tsx() {
485     x = sp;
486 
487     zerocalc(x);
488     signcalc(x);
489 }
490 
txa()491 static void txa() {
492     a = x;
493 
494     zerocalc(a);
495     signcalc(a);
496 }
497 
txs()498 static void txs() {
499     sp = x;
500 }
501 
tya()502 static void tya() {
503     a = y;
504 
505     zerocalc(a);
506     signcalc(a);
507 }
508