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()17static 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()59static 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()70static 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()81static 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()90static 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()99static 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()108static 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()116static 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()125static 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()134static 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()143static 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()154static 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()163static 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()172static void clc() { 173 clearcarry(); 174 } 175 cld()176static void cld() { 177 cleardecimal(); 178 } 179 cli()180static void cli() { 181 clearinterrupt(); 182 } 183 clv()184static void clv() { 185 clearoverflow(); 186 } 187 cmp()188static 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()200static 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()211static 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()222static void dec() { 223 value = getvalue(); 224 result = value - 1; 225 226 zerocalc(result); 227 signcalc(result); 228 229 putvalue(result); 230 } 231 dex()232static void dex() { 233 x--; 234 235 zerocalc(x); 236 signcalc(x); 237 } 238 dey()239static void dey() { 240 y--; 241 242 zerocalc(y); 243 signcalc(y); 244 } 245 eor()246static 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()257static void inc() { 258 value = getvalue(); 259 result = value + 1; 260 261 zerocalc(result); 262 signcalc(result); 263 264 putvalue(result); 265 } 266 inx()267static void inx() { 268 x++; 269 270 zerocalc(x); 271 signcalc(x); 272 } 273 iny()274static void iny() { 275 y++; 276 277 zerocalc(y); 278 signcalc(y); 279 } 280 jmp()281static void jmp() { 282 pc = ea; 283 } 284 jsr()285static void jsr() { 286 push16(pc - 1); 287 pc = ea; 288 } 289 lda()290static void lda() { 291 penaltyop = 1; 292 value = getvalue(); 293 a = (uint8_t)(value & 0x00FF); 294 295 zerocalc(a); 296 signcalc(a); 297 } 298 ldx()299static void ldx() { 300 penaltyop = 1; 301 value = getvalue(); 302 x = (uint8_t)(value & 0x00FF); 303 304 zerocalc(x); 305 signcalc(x); 306 } 307 ldy()308static void ldy() { 309 penaltyop = 1; 310 value = getvalue(); 311 y = (uint8_t)(value & 0x00FF); 312 313 zerocalc(y); 314 signcalc(y); 315 } 316 lsr()317static 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()329static 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()342static 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()353static void pha() { 354 push8(a); 355 } 356 php()357static void php() { 358 push8(status | FLAG_BREAK); 359 } 360 pla()361static void pla() { 362 a = pull8(); 363 364 zerocalc(a); 365 signcalc(a); 366 } 367 plp()368static void plp() { 369 status = pull8() | FLAG_CONSTANT; 370 } 371 rol()372static 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()383static 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()395static void rti() { 396 status = pull8(); 397 value = pull16(); 398 pc = value; 399 } 400 rts()401static void rts() { 402 value = pull16(); 403 pc = value + 1; 404 } 405 sbc()406static 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()446static void sec() { 447 setcarry(); 448 } 449 sed()450static void sed() { 451 setdecimal(); 452 } 453 sei()454static void sei() { 455 setinterrupt(); 456 } 457 sta()458static void sta() { 459 putvalue(a); 460 } 461 stx()462static void stx() { 463 putvalue(x); 464 } 465 sty()466static void sty() { 467 putvalue(y); 468 } 469 tax()470static void tax() { 471 x = a; 472 473 zerocalc(x); 474 signcalc(x); 475 } 476 tay()477static void tay() { 478 y = a; 479 480 zerocalc(y); 481 signcalc(y); 482 } 483 tsx()484static void tsx() { 485 x = sp; 486 487 zerocalc(x); 488 signcalc(x); 489 } 490 txa()491static void txa() { 492 a = x; 493 494 zerocalc(a); 495 signcalc(a); 496 } 497 txs()498static void txs() { 499 sp = x; 500 } 501 tya()502static void tya() { 503 a = y; 504 505 zerocalc(a); 506 signcalc(a); 507 } 508