implemented the INC and DEC family of instructions

This commit is contained in:
2026-08-09 11:06:08 -05:00
parent ce5e94277e
commit 16b51620a6
3 changed files with 268 additions and 3 deletions
+4 -3
View File
@@ -24,7 +24,8 @@
- Batch 1 done (subroutines + stack): JSR, RTS, PHA, PLA, PHP, PLP, RTI, BRK, plus NOP and SEC as quick wins. Verified SP:FD->FB across JSR (push high-then-low works) - Batch 1 done (subroutines + stack): JSR, RTS, PHA, PLA, PHP, PLP, RTI, BRK, plus NOP and SEC as quick wins. Verified SP:FD->FB across JSR (push high-then-low works)
- Batch 2 done (branches): all 8 branches (BEQ/BNE/BCC/BCS/BPL/BMI/BVC/BVS) via one shared branch() routine with condition param. Taken = +3 cycles, page-cross = +1 more. Verified both taken and not-taken paths in the log - Batch 2 done (branches): all 8 branches (BEQ/BNE/BCC/BCS/BPL/BMI/BVC/BVS) via one shared branch() routine with condition param. Taken = +3 cycles, page-cross = +1 more. Verified both taken and not-taken paths in the log
- Flag set/clear ops done (part of Batch 10): CLC, CLI, CLV, CLD, SEI, SED (SEC done in Batch 1). SEI/SED set, the rest clear. Fixed a real bug where SEI/SED were clearing instead of setting - Flag set/clear ops done (part of Batch 10): CLC, CLI, CLV, CLD, SEI, SED (SEC done in Batch 1). SEI/SED set, the rest clear. Fixed a real bug where SEI/SED were clearing instead of setting
- Trace now matches the nestest reference log through line 506 (CBB9 INY, CYC:1168), field-for-field (PC/A/X/Y/P/SP/CYC verified by label-comparison script). Next panic is on 0xC8 (INY) at line 506, top of Batch 8 - Trace now matches the nestest reference log through line 678 (CCBA TAY, CYC:1592), field-for-field (PC/A/X/Y/P/SP/CYC verified by label-comparison script). Next panic is on 0xA8 (TAY) at line 678, a Batch 10 transfer opcode
- Batch 8 done (inc/dec): INC (4 modes), DEC (4 modes), INX, INY, DEX, DEY. RMW cores (inc/dec) read-modify-write and correctly return base WITHOUT the page-cross extra (RMW cycles are fixed). Register ops are wrapping_add/sub with Z/N only. 124 of 151 official opcodes done. INY/INX carried the log from 506 to 678 lines
- Batch 3 done (loads): LDA (8 modes), LDX (5 modes), LDY (5 modes) via three shared cores (lda/ldx/ldy) + thin wrappers. Caught two real bugs in review: all 4 LDY wrappers called self.ldx (would write to X instead of Y), and 6 of 8 LDX/LDY wrappers had wrong base cycles (3 instead of 4). Both fixed - Batch 3 done (loads): LDA (8 modes), LDX (5 modes), LDY (5 modes) via three shared cores (lda/ldx/ldy) + thin wrappers. Caught two real bugs in review: all 4 LDY wrappers called self.ldx (would write to X instead of Y), and 6 of 8 LDX/LDY wrappers had wrong base cycles (3 instead of 4). Both fixed
- Batch 4 done (stores): STA (7 modes), STX (3 modes), STY (3 modes) via three shared cores (sta/stx/sty) + thin wrappers. No flag changes. Refactored stx_zp to use the shared stx core for consistency. Fixed a comment typo (sta_abx was labeled 0x95 instead of 0x9D) - Batch 4 done (stores): STA (7 modes), STX (3 modes), STY (3 modes) via three shared cores (sta/stx/sty) + thin wrappers. No flag changes. Refactored stx_zp to use the shared stx core for consistency. Fixed a comment typo (sta_abx was labeled 0x95 instead of 0x9D)
- Batch 5 done (compares): CMP (8 modes), CPX (3 modes), CPY (3 modes) via three shared cores (cmp/cpx/cpy) + wrappers + immediate variants. Sets C (reg >= mem), Z, N; no store. Uses wrapping_sub for the borrow math. 70 of 151 official opcodes done. No diff progress expected until the log reaches these opcodes - Batch 5 done (compares): CMP (8 modes), CPX (3 modes), CPY (3 modes) via three shared cores (cmp/cpx/cpy) + wrappers + immediate variants. Sets C (reg >= mem), Z, N; no store. Uses wrapping_sub for the borrow math. 70 of 151 official opcodes done. No diff progress expected until the log reaches these opcodes
@@ -46,9 +47,9 @@ CPU implementation batches (by family, ordered by nestest log frequency):
- Batch 5 - DONE (compares, see Done section) - Batch 5 - DONE (compares, see Done section)
- Batch 6 - DONE (arithmetic, see Done section) - Batch 6 - DONE (arithmetic, see Done section)
- Batch 7 - DONE (logic, see Done section) - Batch 7 - DONE (logic, see Done section)
- Batch 8 - Inc/Dec: INC/DEC 4 modes each (RMW), INX, INY, DEX, DEY. Next up - Batch 8 - DONE (inc/dec, see Done section)
- Batch 9 - Shifts: ASL, LSR, ROL, ROR (accumulator + 4 memory modes each, RMW) - Batch 9 - Shifts: ASL, LSR, ROL, ROR (accumulator + 4 memory modes each, RMW)
- Batch 10 - PARTIAL: flag ops done (CLC/CLI/CLV/CLD/SEI/SED, plus SEC/NOP). Remaining: JMP ind 6C, transfers TAX/TAY/TXA/TYA/TSX/TXS - Batch 10 - PARTIAL: flag ops done (CLC/CLI/CLV/CLD/SEI/SED, plus SEC/NOP). Remaining: JMP ind 6C, transfers TAX/TAY/TXA/TYA/TSX/TXS. Next in log: TAY (0xA8) at line 678
Rules for each batch: Rules for each batch:
- Add the opcode's length to opcode_len in the same edit (never let them drift) - Add the opcode's length to opcode_len in the same edit (never let them drift)
+172
View File
@@ -504,3 +504,175 @@ F93F C9 00 A:00 X:AA Y:71 P:27 SP:F9 CYC:1158
F941 D0 01 A:00 X:AA Y:71 P:27 SP:F9 CYC:1160 F941 D0 01 A:00 X:AA Y:71 P:27 SP:F9 CYC:1160
F943 60 A:00 X:AA Y:71 P:27 SP:F9 CYC:1162 F943 60 A:00 X:AA Y:71 P:27 SP:F9 CYC:1162
CBB9 C8 A:00 X:AA Y:71 P:27 SP:FB CYC:1168 CBB9 C8 A:00 X:AA Y:71 P:27 SP:FB CYC:1168
CBBA 20 47 F9 A:00 X:AA Y:72 P:25 SP:FB CYC:1170
F947 B8 A:00 X:AA Y:72 P:25 SP:F9 CYC:1176
F948 38 A:00 X:AA Y:72 P:25 SP:F9 CYC:1178
F949 A9 40 A:00 X:AA Y:72 P:25 SP:F9 CYC:1180
F94B 60 A:40 X:AA Y:72 P:25 SP:F9 CYC:1182
CBBD E9 3F A:40 X:AA Y:72 P:25 SP:FB CYC:1188
CBBF 20 4C F9 A:01 X:AA Y:72 P:25 SP:FB CYC:1190
F94C F0 0B A:01 X:AA Y:72 P:25 SP:F9 CYC:1196
F94E 30 09 A:01 X:AA Y:72 P:25 SP:F9 CYC:1198
F950 90 07 A:01 X:AA Y:72 P:25 SP:F9 CYC:1200
F952 70 05 A:01 X:AA Y:72 P:25 SP:F9 CYC:1202
F954 C9 01 A:01 X:AA Y:72 P:25 SP:F9 CYC:1204
F956 D0 01 A:01 X:AA Y:72 P:27 SP:F9 CYC:1206
F958 60 A:01 X:AA Y:72 P:27 SP:F9 CYC:1208
CBC2 C8 A:01 X:AA Y:72 P:27 SP:FB CYC:1214
CBC3 20 5C F9 A:01 X:AA Y:73 P:25 SP:FB CYC:1216
F95C A9 40 A:01 X:AA Y:73 P:25 SP:F9 CYC:1222
F95E 38 A:40 X:AA Y:73 P:25 SP:F9 CYC:1224
F95F 24 01 A:40 X:AA Y:73 P:25 SP:F9 CYC:1226
F961 60 A:40 X:AA Y:73 P:E5 SP:F9 CYC:1229
CBC6 E9 41 A:40 X:AA Y:73 P:E5 SP:FB CYC:1235
CBC8 20 62 F9 A:FF X:AA Y:73 P:A4 SP:FB CYC:1237
F962 B0 0B A:FF X:AA Y:73 P:A4 SP:F9 CYC:1243
F964 F0 09 A:FF X:AA Y:73 P:A4 SP:F9 CYC:1245
F966 10 07 A:FF X:AA Y:73 P:A4 SP:F9 CYC:1247
F968 70 05 A:FF X:AA Y:73 P:A4 SP:F9 CYC:1249
F96A C9 FF A:FF X:AA Y:73 P:A4 SP:F9 CYC:1251
F96C D0 01 A:FF X:AA Y:73 P:27 SP:F9 CYC:1253
F96E 60 A:FF X:AA Y:73 P:27 SP:F9 CYC:1255
CBCB C8 A:FF X:AA Y:73 P:27 SP:FB CYC:1261
CBCC 20 72 F9 A:FF X:AA Y:74 P:25 SP:FB CYC:1263
F972 18 A:FF X:AA Y:74 P:25 SP:F9 CYC:1269
F973 A9 80 A:FF X:AA Y:74 P:24 SP:F9 CYC:1271
F975 60 A:80 X:AA Y:74 P:A4 SP:F9 CYC:1273
CBCF E9 00 A:80 X:AA Y:74 P:A4 SP:FB CYC:1279
CBD1 20 76 F9 A:7F X:AA Y:74 P:65 SP:FB CYC:1281
F976 90 05 A:7F X:AA Y:74 P:65 SP:F9 CYC:1287
F978 C9 7F A:7F X:AA Y:74 P:65 SP:F9 CYC:1289
F97A D0 01 A:7F X:AA Y:74 P:67 SP:F9 CYC:1291
F97C 60 A:7F X:AA Y:74 P:67 SP:F9 CYC:1293
CBD4 C8 A:7F X:AA Y:74 P:67 SP:FB CYC:1299
CBD5 20 80 F9 A:7F X:AA Y:75 P:65 SP:FB CYC:1301
F980 38 A:7F X:AA Y:75 P:65 SP:F9 CYC:1307
F981 A9 81 A:7F X:AA Y:75 P:65 SP:F9 CYC:1309
F983 60 A:81 X:AA Y:75 P:E5 SP:F9 CYC:1311
CBD8 E9 7F A:81 X:AA Y:75 P:E5 SP:FB CYC:1317
CBDA 20 84 F9 A:02 X:AA Y:75 P:65 SP:FB CYC:1319
F984 50 07 A:02 X:AA Y:75 P:65 SP:F9 CYC:1325
F986 90 05 A:02 X:AA Y:75 P:65 SP:F9 CYC:1327
F988 C9 02 A:02 X:AA Y:75 P:65 SP:F9 CYC:1329
F98A D0 01 A:02 X:AA Y:75 P:67 SP:F9 CYC:1331
F98C 60 A:02 X:AA Y:75 P:67 SP:F9 CYC:1333
CBDD 60 A:02 X:AA Y:75 P:67 SP:FB CYC:1339
C606 20 DE CB A:02 X:AA Y:75 P:67 SP:FD CYC:1345
CBDE EA A:02 X:AA Y:75 P:67 SP:FB CYC:1351
CBDF A9 FF A:02 X:AA Y:75 P:67 SP:FB CYC:1353
CBE1 85 01 A:FF X:AA Y:75 P:E5 SP:FB CYC:1355
CBE3 A9 44 A:FF X:AA Y:75 P:E5 SP:FB CYC:1358
CBE5 A2 55 A:44 X:AA Y:75 P:65 SP:FB CYC:1360
CBE7 A0 66 A:44 X:55 Y:75 P:65 SP:FB CYC:1362
CBE9 E8 A:44 X:55 Y:66 P:65 SP:FB CYC:1364
CBEA 88 A:44 X:56 Y:66 P:65 SP:FB CYC:1366
CBEB E0 56 A:44 X:56 Y:65 P:65 SP:FB CYC:1368
CBED D0 21 A:44 X:56 Y:65 P:67 SP:FB CYC:1370
CBEF C0 65 A:44 X:56 Y:65 P:67 SP:FB CYC:1372
CBF1 D0 1D A:44 X:56 Y:65 P:67 SP:FB CYC:1374
CBF3 E8 A:44 X:56 Y:65 P:67 SP:FB CYC:1376
CBF4 E8 A:44 X:57 Y:65 P:65 SP:FB CYC:1378
CBF5 88 A:44 X:58 Y:65 P:65 SP:FB CYC:1380
CBF6 88 A:44 X:58 Y:64 P:65 SP:FB CYC:1382
CBF7 E0 58 A:44 X:58 Y:63 P:65 SP:FB CYC:1384
CBF9 D0 15 A:44 X:58 Y:63 P:67 SP:FB CYC:1386
CBFB C0 63 A:44 X:58 Y:63 P:67 SP:FB CYC:1388
CBFD D0 11 A:44 X:58 Y:63 P:67 SP:FB CYC:1390
CBFF CA A:44 X:58 Y:63 P:67 SP:FB CYC:1392
CC00 C8 A:44 X:57 Y:63 P:65 SP:FB CYC:1394
CC01 E0 57 A:44 X:57 Y:64 P:65 SP:FB CYC:1396
CC03 D0 0B A:44 X:57 Y:64 P:67 SP:FB CYC:1398
CC05 C0 64 A:44 X:57 Y:64 P:67 SP:FB CYC:1400
CC07 D0 07 A:44 X:57 Y:64 P:67 SP:FB CYC:1402
CC09 C9 44 A:44 X:57 Y:64 P:67 SP:FB CYC:1404
CC0B D0 03 A:44 X:57 Y:64 P:67 SP:FB CYC:1406
CC0D 4C 14 CC A:44 X:57 Y:64 P:67 SP:FB CYC:1408
CC14 EA A:44 X:57 Y:64 P:67 SP:FB CYC:1411
CC15 38 A:44 X:57 Y:64 P:67 SP:FB CYC:1413
CC16 A2 69 A:44 X:57 Y:64 P:67 SP:FB CYC:1415
CC18 A9 96 A:44 X:69 Y:64 P:65 SP:FB CYC:1417
CC1A 24 01 A:96 X:69 Y:64 P:E5 SP:FB CYC:1419
CC1C A0 FF A:96 X:69 Y:64 P:E5 SP:FB CYC:1422
CC1E C8 A:96 X:69 Y:FF P:E5 SP:FB CYC:1424
CC1F D0 3D A:96 X:69 Y:00 P:67 SP:FB CYC:1426
CC21 30 3B A:96 X:69 Y:00 P:67 SP:FB CYC:1428
CC23 90 39 A:96 X:69 Y:00 P:67 SP:FB CYC:1430
CC25 50 37 A:96 X:69 Y:00 P:67 SP:FB CYC:1432
CC27 C0 00 A:96 X:69 Y:00 P:67 SP:FB CYC:1434
CC29 D0 33 A:96 X:69 Y:00 P:67 SP:FB CYC:1436
CC2B C8 A:96 X:69 Y:00 P:67 SP:FB CYC:1438
CC2C F0 30 A:96 X:69 Y:01 P:65 SP:FB CYC:1440
CC2E 30 2E A:96 X:69 Y:01 P:65 SP:FB CYC:1442
CC30 90 2C A:96 X:69 Y:01 P:65 SP:FB CYC:1444
CC32 50 2A A:96 X:69 Y:01 P:65 SP:FB CYC:1446
CC34 18 A:96 X:69 Y:01 P:65 SP:FB CYC:1448
CC35 B8 A:96 X:69 Y:01 P:64 SP:FB CYC:1450
CC36 A0 00 A:96 X:69 Y:01 P:24 SP:FB CYC:1452
CC38 88 A:96 X:69 Y:00 P:26 SP:FB CYC:1454
CC39 F0 23 A:96 X:69 Y:FF P:A4 SP:FB CYC:1456
CC3B 10 21 A:96 X:69 Y:FF P:A4 SP:FB CYC:1458
CC3D B0 1F A:96 X:69 Y:FF P:A4 SP:FB CYC:1460
CC3F 70 1D A:96 X:69 Y:FF P:A4 SP:FB CYC:1462
CC41 C0 FF A:96 X:69 Y:FF P:A4 SP:FB CYC:1464
CC43 D0 19 A:96 X:69 Y:FF P:27 SP:FB CYC:1466
CC45 18 A:96 X:69 Y:FF P:27 SP:FB CYC:1468
CC46 88 A:96 X:69 Y:FF P:26 SP:FB CYC:1470
CC47 F0 15 A:96 X:69 Y:FE P:A4 SP:FB CYC:1472
CC49 10 13 A:96 X:69 Y:FE P:A4 SP:FB CYC:1474
CC4B B0 11 A:96 X:69 Y:FE P:A4 SP:FB CYC:1476
CC4D 70 0F A:96 X:69 Y:FE P:A4 SP:FB CYC:1478
CC4F C0 FE A:96 X:69 Y:FE P:A4 SP:FB CYC:1480
CC51 D0 0B A:96 X:69 Y:FE P:27 SP:FB CYC:1482
CC53 C9 96 A:96 X:69 Y:FE P:27 SP:FB CYC:1484
CC55 D0 07 A:96 X:69 Y:FE P:27 SP:FB CYC:1486
CC57 E0 69 A:96 X:69 Y:FE P:27 SP:FB CYC:1488
CC59 D0 03 A:96 X:69 Y:FE P:27 SP:FB CYC:1490
CC5B 4C 62 CC A:96 X:69 Y:FE P:27 SP:FB CYC:1492
CC62 EA A:96 X:69 Y:FE P:27 SP:FB CYC:1495
CC63 38 A:96 X:69 Y:FE P:27 SP:FB CYC:1497
CC64 A0 69 A:96 X:69 Y:FE P:27 SP:FB CYC:1499
CC66 A9 96 A:96 X:69 Y:69 P:25 SP:FB CYC:1501
CC68 24 01 A:96 X:69 Y:69 P:A5 SP:FB CYC:1503
CC6A A2 FF A:96 X:69 Y:69 P:E5 SP:FB CYC:1506
CC6C E8 A:96 X:FF Y:69 P:E5 SP:FB CYC:1508
CC6D D0 3D A:96 X:00 Y:69 P:67 SP:FB CYC:1510
CC6F 30 3B A:96 X:00 Y:69 P:67 SP:FB CYC:1512
CC71 90 39 A:96 X:00 Y:69 P:67 SP:FB CYC:1514
CC73 50 37 A:96 X:00 Y:69 P:67 SP:FB CYC:1516
CC75 E0 00 A:96 X:00 Y:69 P:67 SP:FB CYC:1518
CC77 D0 33 A:96 X:00 Y:69 P:67 SP:FB CYC:1520
CC79 E8 A:96 X:00 Y:69 P:67 SP:FB CYC:1522
CC7A F0 30 A:96 X:01 Y:69 P:65 SP:FB CYC:1524
CC7C 30 2E A:96 X:01 Y:69 P:65 SP:FB CYC:1526
CC7E 90 2C A:96 X:01 Y:69 P:65 SP:FB CYC:1528
CC80 50 2A A:96 X:01 Y:69 P:65 SP:FB CYC:1530
CC82 18 A:96 X:01 Y:69 P:65 SP:FB CYC:1532
CC83 B8 A:96 X:01 Y:69 P:64 SP:FB CYC:1534
CC84 A2 00 A:96 X:01 Y:69 P:24 SP:FB CYC:1536
CC86 CA A:96 X:00 Y:69 P:26 SP:FB CYC:1538
CC87 F0 23 A:96 X:FF Y:69 P:A4 SP:FB CYC:1540
CC89 10 21 A:96 X:FF Y:69 P:A4 SP:FB CYC:1542
CC8B B0 1F A:96 X:FF Y:69 P:A4 SP:FB CYC:1544
CC8D 70 1D A:96 X:FF Y:69 P:A4 SP:FB CYC:1546
CC8F E0 FF A:96 X:FF Y:69 P:A4 SP:FB CYC:1548
CC91 D0 19 A:96 X:FF Y:69 P:27 SP:FB CYC:1550
CC93 18 A:96 X:FF Y:69 P:27 SP:FB CYC:1552
CC94 CA A:96 X:FF Y:69 P:26 SP:FB CYC:1554
CC95 F0 15 A:96 X:FE Y:69 P:A4 SP:FB CYC:1556
CC97 10 13 A:96 X:FE Y:69 P:A4 SP:FB CYC:1558
CC99 B0 11 A:96 X:FE Y:69 P:A4 SP:FB CYC:1560
CC9B 70 0F A:96 X:FE Y:69 P:A4 SP:FB CYC:1562
CC9D E0 FE A:96 X:FE Y:69 P:A4 SP:FB CYC:1564
CC9F D0 0B A:96 X:FE Y:69 P:27 SP:FB CYC:1566
CCA1 C9 96 A:96 X:FE Y:69 P:27 SP:FB CYC:1568
CCA3 D0 07 A:96 X:FE Y:69 P:27 SP:FB CYC:1570
CCA5 C0 69 A:96 X:FE Y:69 P:27 SP:FB CYC:1572
CCA7 D0 03 A:96 X:FE Y:69 P:27 SP:FB CYC:1574
CCA9 4C B0 CC A:96 X:FE Y:69 P:27 SP:FB CYC:1576
CCB0 EA A:96 X:FE Y:69 P:27 SP:FB CYC:1579
CCB1 A9 85 A:96 X:FE Y:69 P:27 SP:FB CYC:1581
CCB3 A2 34 A:85 X:FE Y:69 P:A5 SP:FB CYC:1583
CCB5 A0 99 A:85 X:34 Y:69 P:25 SP:FB CYC:1585
CCB7 18 A:85 X:34 Y:99 P:A5 SP:FB CYC:1587
CCB8 24 01 A:85 X:34 Y:99 P:A4 SP:FB CYC:1589
CCBA A8 A:85 X:34 Y:99 P:E4 SP:FB CYC:1592
+92
View File
@@ -148,6 +148,12 @@ impl Cpu {
0x49 => self.eor_imm(bus), 0x45 => self.eor_zp(bus), 0x55 => self.eor_zpx(bus), 0x49 => self.eor_imm(bus), 0x45 => self.eor_zp(bus), 0x55 => self.eor_zpx(bus),
0x4D => self.eor_abs(bus), 0x5D => self.eor_abx(bus), 0x59 => self.eor_aby(bus), 0x4D => self.eor_abs(bus), 0x5D => self.eor_abx(bus), 0x59 => self.eor_aby(bus),
0x41 => self.eor_izx(bus), 0x51 => self.eor_izy(bus), 0x41 => self.eor_izx(bus), 0x51 => self.eor_izy(bus),
// Increments
0xE6 => self.inc_zp(bus), 0xF6 => self.inc_zpx(bus), 0xEE => self.inc_abs(bus),
0xFE => self.inc_abx(bus), 0xE8 => self.inx_imp(bus), 0xC8 => self.iny_imp(bus),
// Decrements
0xC6 => self.dec_zp(bus), 0xD6 => self.dec_zpx(bus), 0xCE => self.dec_abs(bus),
0xDE => self.dec_abx(bus), 0xCA => self.dex_imp(bus), 0x88 => self.dey_imp(bus),
_ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)), _ => panic!("illegal/unkown opcode {opcode:#04X} at {:#06X}", self.pc.wrapping_sub(1)),
}; };
self.cycles += cycles as u64; self.cycles += cycles as u64;
@@ -185,6 +191,9 @@ impl Cpu {
0x1D => 3, /* ORA abx */ 0x19 => 3, /* ORA aby */ 0x01 => 2, /* ORA izx */ 0x11 => 2, /* ORA izy */ 0x1D => 3, /* ORA abx */ 0x19 => 3, /* ORA aby */ 0x01 => 2, /* ORA izx */ 0x11 => 2, /* ORA izy */
0x49 => 2, /* EOR imm */ 0x45 => 2, /* EOR zp */ 0x55 => 2, /* EOR zpx */ 0x4D => 3, /* EOR abs */ 0x49 => 2, /* EOR imm */ 0x45 => 2, /* EOR zp */ 0x55 => 2, /* EOR zpx */ 0x4D => 3, /* EOR abs */
0x5D => 3, /* EOR abx */ 0x59 => 3, /* EOR aby */ 0x41 => 2, /* EOR izx */ 0x51 => 2, /* EOR izy */ 0x5D => 3, /* EOR abx */ 0x59 => 3, /* EOR aby */ 0x41 => 2, /* EOR izx */ 0x51 => 2, /* EOR izy */
0xE6 => 2, /* INC zp */ 0xF6 => 2, /* INC zpx */ 0xEE => 3, /* INC abs */ 0xFE => 3, /* INC abx */
0xE8 => 1, /* INX imp */ 0xC8 => 1, /* INY imp */ 0xC6 => 2, /* DEC zp */ 0xD6 => 2, /* DEC zpx */
0xCE => 3, /* DEC abs */ 0xDE => 3, /* DEC abx */ 0xCA => 1, /* DEX imp */ 0x88 => 1, /* DEY imp */
_ => 1, // fallback, would show the invalid/unknown opcode only not its parameters _ => 1, // fallback, would show the invalid/unknown opcode only not its parameters
} }
} }
@@ -405,6 +414,22 @@ impl Cpu {
base + extra base + extra
} }
// INC core
fn inc(&mut self, bus: &mut impl Bus, (address, _extra): (u16, u8), base: u8) -> u8 {
let value = self.read(bus, address).wrapping_add(1);
self.write(bus, address, value);
self.set_zp_flags(value);
base // NO + extra — RMW cycles are fixed
}
// DEC core
fn dec(&mut self, bus: &mut impl Bus, (address, _extra): (u16, u8), base: u8) -> u8 {
let value = self.read(bus, address).wrapping_sub(1);
self.write(bus, address, value);
self.set_zp_flags(value);
base // NO + extra — RMW cycles are fixed
}
// NES 6502 opcode -> functions // NES 6502 opcode -> functions
fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles fn jmp_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0x4C, 3 bytes, 3 cycles
self.pc = self.fetch16(bus); self.pc = self.fetch16(bus);
@@ -968,6 +993,73 @@ impl Cpu {
2 2
} }
// INC variants
fn inc_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xE6, 2 bytes, 5 cycles
let (address, extra) = self.address_zp(bus);
self.inc(bus, (address, extra), 5)
}
fn inc_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xF6, 2 bytes, 6 cycles
let (address, extra) = self.address_zpx(bus);
self.inc(bus, (address, extra), 6)
}
fn inc_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xEE, 3 bytes, 6 cycles
let (address, extra) = self.address_abs(bus);
self.inc(bus, (address, extra), 6)
}
fn inc_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xFE, 3 bytes, 7 cycles
let (address, extra) = self.address_abx(bus);
self.inc(bus, (address, extra), 7)
}
// DEC variants
fn dec_zp(&mut self, bus: &mut impl Bus) -> u8 { // 0xC6, 2 bytes, 5 cycles
let (address, extra) = self.address_zp(bus);
self.dec(bus, (address, extra), 5)
}
fn dec_zpx(&mut self, bus: &mut impl Bus) -> u8 { // 0xD6, 2 bytes, 6 cycles
let (address, extra) = self.address_zpx(bus);
self.dec(bus, (address, extra), 6)
}
fn dec_abs(&mut self, bus: &mut impl Bus) -> u8 { // 0xCE, 3 bytes, 6 cycles
let (address, extra) = self.address_abs(bus);
self.dec(bus, (address, extra), 6)
}
fn dec_abx(&mut self, bus: &mut impl Bus) -> u8 { // 0xDE, 3 bytes, 7 cycles
let (address, extra) = self.address_abx(bus);
self.dec(bus, (address, extra), 7)
}
// INC register variants
fn inx_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xE8, 1 byte, 2 cycles
self.x = self.x.wrapping_add(1);
self.set_zp_flags(self.x);
2
}
fn iny_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xC8, 1 byte, 2 cycles
self.y = self.y.wrapping_add(1);
self.set_zp_flags(self.y);
2
}
// DEC register variants
fn dex_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0xCA, 1 byte, 2 cycles
self.x = self.x.wrapping_sub(1);
self.set_zp_flags(self.x);
2
}
fn dey_imp(&mut self, _bus: &mut impl Bus) -> u8 { // 0x88, 1 byte, 2 cycles
self.y = self.y.wrapping_sub(1);
self.set_zp_flags(self.y);
2
}
// all branching alternatives here, all 1 bytes // all branching alternatives here, all 1 bytes
fn bcs_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, self.flag(FLAG_CARRY)) } // 0xB0 fn bcs_rel(&mut self, bus: &mut impl Bus) -> u8 { self.branch(bus, self.flag(FLAG_CARRY)) } // 0xB0