mos6502 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020, Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ module Mos6502
8
+ class CpuFlags
9
+ def initialize
10
+ reset!
11
+ end
12
+
13
+ def carry=(flag)
14
+ @carry = set_flag(flag)
15
+ end
16
+
17
+ def carry?
18
+ @carry
19
+ end
20
+
21
+ def zero=(flag)
22
+ @zero = set_flag(flag)
23
+ end
24
+
25
+ def zero?
26
+ @zero
27
+ end
28
+
29
+ def interupt_disable=(flag)
30
+ @interupt_disable = set_flag(flag)
31
+ end
32
+
33
+ def interupt_disable?
34
+ @interupt_disable
35
+ end
36
+
37
+ def decimal_mode=(flag)
38
+ @decimal_mode = set_flag(flag)
39
+ end
40
+
41
+ def decimal_mode?
42
+ @decimal_mode
43
+ end
44
+
45
+ def break=(flag)
46
+ @break = set_flag(flag)
47
+ end
48
+
49
+ def break?
50
+ @break
51
+ end
52
+
53
+ def overflow=(flag)
54
+ @overflow = set_flag(flag)
55
+ end
56
+
57
+ def overflow?
58
+ @overflow
59
+ end
60
+
61
+ def negative=(flag)
62
+ @negative = set_flag(flag)
63
+ end
64
+
65
+ def negative?
66
+ @negative
67
+ end
68
+
69
+ def encode
70
+ [
71
+ @negative, @overflow, true, true, @decimal_mode,
72
+ @interupt_disable, @zero, @carry
73
+ ].reduce(0) { |acc, flag| (acc << 1) + get_flag(flag) }
74
+ end
75
+
76
+ def decode(bin)
77
+ self.carry = bin & 1
78
+ self.zero = (bin >> 1) & 1
79
+ self.interupt_disable = (bin >> 2) & 1
80
+ self.decimal_mode = (bin >> 3) & 1
81
+ self.break = (bin >> 4) & 1
82
+ self.overflow = (bin >> 6) & 1
83
+ self.negative = (bin >> 7) & 1
84
+ end
85
+
86
+ def reset!
87
+ @carry = false
88
+ @zero = false
89
+ @interupt_disable = false
90
+ @decimal_mode = false
91
+ @break = false
92
+ @overflow = false
93
+ @negative = false
94
+ end
95
+
96
+ private
97
+
98
+ def set_flag(flag) # rubocop:disable Naming/AccessorMethodName
99
+ flag == 0 ? false : !!flag # rubocop:disable Style/NumericPredicate
100
+ end
101
+
102
+ def get_flag(flag)
103
+ flag ? 1 : 0
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,861 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2020, Robert Haines.
4
+ #
5
+ # Licensed under the BSD License. See LICENCE for details.
6
+
7
+ require_relative 'cpu_ops'
8
+
9
+ module Mos6502
10
+ class Cpu
11
+ private
12
+
13
+ def instructions
14
+ {
15
+ # BRK
16
+ 0x00 => lambda {
17
+ @pc += 1
18
+ stack_push((@pc >> 8) & 0xff)
19
+ stack_push(@pc & 0xff)
20
+ stack_push(@status.encode)
21
+ @pc = @memory.get_word(0xfffe)
22
+ @status.break = true
23
+ @status.interupt_disable = true
24
+ },
25
+
26
+ # ORA (indexed indirect)
27
+ 0x01 => lambda {
28
+ @a |= @memory.get(indexed_indirect)
29
+ set_nz_flags(@a)
30
+ },
31
+
32
+ # ORA (zero page)
33
+ 0x05 => lambda {
34
+ @a |= @memory.get(zero_page)
35
+ set_nz_flags(@a)
36
+ },
37
+
38
+ # ASL (zero page)
39
+ 0x06 => lambda {
40
+ address = zero_page
41
+ @memory.set(address, asl(@memory.get(address)))
42
+ },
43
+
44
+ # PHP
45
+ 0x08 => lambda {
46
+ stack_push(@status.encode)
47
+ },
48
+
49
+ # ORA (immediate)
50
+ 0x09 => lambda {
51
+ @a |= next_byte
52
+ set_nz_flags(@a)
53
+ },
54
+
55
+ # ASL (accumulator)
56
+ 0x0a => lambda {
57
+ @a = asl(@a) & 0xff
58
+ },
59
+
60
+ # ORA (absolute)
61
+ 0x0d => lambda {
62
+ @a |= @memory.get(absolute)
63
+ set_nz_flags(@a)
64
+ },
65
+
66
+ # ASL (absolute)
67
+ 0x0e => lambda {
68
+ address = absolute
69
+ @memory.set(address, asl(@memory.get(address)))
70
+ },
71
+
72
+ # BPL
73
+ 0x10 => lambda {
74
+ offset = next_byte
75
+ @pc = branch(offset) unless @status.negative?
76
+ },
77
+
78
+ # ORA (indirect indexed)
79
+ 0x11 => lambda {
80
+ @a |= @memory.get(indirect_indexed)
81
+ set_nz_flags(@a)
82
+ },
83
+
84
+ # ORA (zero page, X)
85
+ 0x15 => lambda {
86
+ @a |= @memory.get(zero_page(@x))
87
+ set_nz_flags(@a)
88
+ },
89
+
90
+ # ASL (zero page, X)
91
+ 0x16 => lambda {
92
+ address = zero_page(@x)
93
+ @memory.set(address, asl(@memory.get(address)))
94
+ },
95
+
96
+ # CLC
97
+ 0x18 => lambda {
98
+ @status.carry = false
99
+ },
100
+
101
+ # ORA (absolute, Y)
102
+ 0x19 => lambda {
103
+ @a |= @memory.get(absolute(@y))
104
+ set_nz_flags(@a)
105
+ },
106
+
107
+ # ORA (absolute, X)
108
+ 0x1d => lambda {
109
+ @a |= @memory.get(absolute(@x))
110
+ set_nz_flags(@a)
111
+ },
112
+
113
+ # ASL (absolute, X)
114
+ 0x1e => lambda {
115
+ address = absolute(@x)
116
+ @memory.set(address, asl(@memory.get(address)))
117
+ },
118
+
119
+ # JSR
120
+ 0x20 => lambda {
121
+ jump_to = absolute
122
+ return_to = @pc - 1
123
+ stack_push((return_to >> 8) & 0xff)
124
+ stack_push(return_to & 0xff)
125
+ @pc = jump_to
126
+ },
127
+
128
+ # AND (indexed indirect)
129
+ 0x21 => lambda {
130
+ @a &= @memory.get(indexed_indirect)
131
+ set_nz_flags(@a)
132
+ },
133
+
134
+ # BIT (zero page)
135
+ 0x24 => lambda {
136
+ bit(@memory.get(zero_page))
137
+ },
138
+
139
+ # AND (zero page)
140
+ 0x25 => lambda {
141
+ @a &= @memory.get(zero_page)
142
+ set_nz_flags(@a)
143
+ },
144
+
145
+ # ROL (zero page)
146
+ 0x26 => lambda {
147
+ address = zero_page
148
+ @memory.set(address, rol(@memory.get(address)))
149
+ },
150
+
151
+ # PLP
152
+ 0x28 => lambda {
153
+ @status.decode(stack_pop)
154
+ },
155
+
156
+ # AND (immediate)
157
+ 0x29 => lambda {
158
+ @a &= next_byte
159
+ set_nz_flags(@a)
160
+ },
161
+
162
+ # ROL (accumulator)
163
+ 0x2a => lambda {
164
+ @a = rol(@a) & 0xff
165
+ },
166
+
167
+ # BIT (absolute)
168
+ 0x2c => lambda {
169
+ bit(@memory.get(absolute))
170
+ },
171
+
172
+ # AND (absolute)
173
+ 0x2d => lambda {
174
+ @a &= @memory.get(absolute)
175
+ set_nz_flags(@a)
176
+ },
177
+
178
+ # ROL (absolute)
179
+ 0x2e => lambda {
180
+ address = absolute
181
+ @memory.set(address, rol(@memory.get(address)))
182
+ },
183
+
184
+ # BMI
185
+ 0x30 => lambda {
186
+ offset = next_byte
187
+ @pc = branch(offset) if @status.negative?
188
+ },
189
+
190
+ # AND (indirect indexed)
191
+ 0x31 => lambda {
192
+ @a &= @memory.get(indirect_indexed)
193
+ set_nz_flags(@a)
194
+ },
195
+
196
+ # AND (zero page, X)
197
+ 0x35 => lambda {
198
+ @a &= @memory.get(zero_page(@x))
199
+ set_nz_flags(@a)
200
+ },
201
+
202
+ # ROL (zero page, X)
203
+ 0x36 => lambda {
204
+ address = zero_page(@x)
205
+ @memory.set(address, rol(@memory.get(address)))
206
+ },
207
+
208
+ # SEC
209
+ 0x38 => lambda {
210
+ @status.carry = true
211
+ },
212
+
213
+ # AND (absolute, Y)
214
+ 0x39 => lambda {
215
+ @a &= @memory.get(absolute(@y))
216
+ set_nz_flags(@a)
217
+ },
218
+
219
+ # AND (absolute, X)
220
+ 0x3d => lambda {
221
+ @a &= @memory.get(absolute(@x))
222
+ set_nz_flags(@a)
223
+ },
224
+
225
+ # ROL (absolute, X)
226
+ 0x3e => lambda {
227
+ address = absolute(@x)
228
+ @memory.set(address, rol(@memory.get(address)))
229
+ },
230
+
231
+ # RTI
232
+ 0x40 => lambda {
233
+ @status.decode(stack_pop)
234
+ @pc = (stack_pop | (stack_pop << 8))
235
+ },
236
+
237
+ # EOR (indexed indirect)
238
+ 0x41 => lambda {
239
+ @a ^= @memory.get(indexed_indirect)
240
+ set_nz_flags(@a)
241
+ },
242
+
243
+ # EOR (zero page)
244
+ 0x45 => lambda {
245
+ @a ^= @memory.get(zero_page)
246
+ set_nz_flags(@a)
247
+ },
248
+
249
+ # LSR (zero page)
250
+ 0x46 => lambda {
251
+ address = zero_page
252
+ @memory.set(address, lsr(@memory.get(address)))
253
+ },
254
+
255
+ # PHA
256
+ 0x48 => lambda {
257
+ stack_push(@a)
258
+ },
259
+
260
+ # EOR (immediate)
261
+ 0x49 => lambda {
262
+ @a ^= next_byte
263
+ set_nz_flags(@a)
264
+ },
265
+
266
+ # LSR (accumulator)
267
+ 0x4a => lambda {
268
+ @a = lsr(@a)
269
+ },
270
+
271
+ # JMP (absolute)
272
+ 0x4c => lambda {
273
+ @pc = absolute
274
+ },
275
+
276
+ # EOR (absolute)
277
+ 0x4d => lambda {
278
+ @a ^= @memory.get(absolute)
279
+ set_nz_flags(@a)
280
+ },
281
+
282
+ # LSR (absolute)
283
+ 0x4e => lambda {
284
+ address = absolute
285
+ @memory.set(address, lsr(@memory.get(address)))
286
+ },
287
+
288
+ # BVC
289
+ 0x50 => lambda {
290
+ offset = next_byte
291
+ @pc = branch(offset) unless @status.overflow?
292
+ },
293
+
294
+ # EOR (indirect indexed)
295
+ 0x51 => lambda {
296
+ @a ^= @memory.get(indirect_indexed)
297
+ set_nz_flags(@a)
298
+ },
299
+
300
+ # EOR (zero page, X)
301
+ 0x55 => lambda {
302
+ @a ^= @memory.get(zero_page(@x))
303
+ set_nz_flags(@a)
304
+ },
305
+
306
+ # LSR (zero page, X)
307
+ 0x56 => lambda {
308
+ address = zero_page(@x)
309
+ @memory.set(address, lsr(@memory.get(address)))
310
+ },
311
+
312
+ # CLI
313
+ 0x58 => lambda {
314
+ @status.interupt_disable = false
315
+ },
316
+
317
+ # EOR (absolute, Y)
318
+ 0x59 => lambda {
319
+ @a ^= @memory.get(absolute(@y))
320
+ set_nz_flags(@a)
321
+ },
322
+
323
+ # EOR (absolute, X)
324
+ 0x5d => lambda {
325
+ @a ^= @memory.get(absolute(@x))
326
+ set_nz_flags(@a)
327
+ },
328
+
329
+ # LSR (absolute, X)
330
+ 0x5e => lambda {
331
+ address = absolute(@x)
332
+ @memory.set(address, lsr(@memory.get(address)))
333
+ },
334
+
335
+ # RTS
336
+ 0x60 => lambda {
337
+ @pc = (stack_pop | (stack_pop << 8)) + 1
338
+ },
339
+
340
+ # ADC (indexed indirect)
341
+ 0x61 => lambda {
342
+ adc(@memory.get(indexed_indirect))
343
+ },
344
+
345
+ # ADC (zero page)
346
+ 0x65 => lambda {
347
+ adc(@memory.get(zero_page))
348
+ },
349
+
350
+ # ROR (zero page)
351
+ 0x66 => lambda {
352
+ address = zero_page
353
+ @memory.set(address, ror(@memory.get(address)))
354
+ },
355
+
356
+ # PLA
357
+ 0x68 => lambda {
358
+ @a = stack_pop
359
+ set_nz_flags(@a)
360
+ },
361
+
362
+ # ADC (immediate)
363
+ 0x69 => lambda {
364
+ adc(next_byte)
365
+ },
366
+
367
+ # ROR (accumulator)
368
+ 0x6a => lambda {
369
+ @a = ror(@a)
370
+ },
371
+
372
+ # JMP (indirect)
373
+ 0x6c => lambda {
374
+ @pc = indirect
375
+ },
376
+
377
+ # ADC (absolute)
378
+ 0x6d => lambda {
379
+ adc(@memory.get(absolute))
380
+ },
381
+
382
+ # ROR (absolute)
383
+ 0x6e => lambda {
384
+ address = absolute
385
+ @memory.set(address, ror(@memory.get(address)))
386
+ },
387
+
388
+ # BVS
389
+ 0x70 => lambda {
390
+ offset = next_byte
391
+ @pc = branch(offset) if @status.overflow?
392
+ },
393
+
394
+ # ADC (indirect indexed)
395
+ 0x71 => lambda {
396
+ adc(@memory.get(indirect_indexed))
397
+ },
398
+
399
+ # ADC (zero page, X)
400
+ 0x75 => lambda {
401
+ adc(@memory.get(zero_page(@x)))
402
+ },
403
+
404
+ # ROR (zero page, X)
405
+ 0x76 => lambda {
406
+ address = zero_page(@x)
407
+ @memory.set(address, ror(@memory.get(address)))
408
+ },
409
+
410
+ # SEI
411
+ 0x78 => lambda {
412
+ @status.interupt_disable = true
413
+ },
414
+
415
+ # ADC (absolute, Y)
416
+ 0x79 => lambda {
417
+ adc(@memory.get(absolute(@y)))
418
+ },
419
+
420
+ # ADC (absolute, X)
421
+ 0x7d => lambda {
422
+ adc(@memory.get(absolute(@x)))
423
+ },
424
+
425
+ # ROR (absolute, X)
426
+ 0x7e => lambda {
427
+ address = absolute(@x)
428
+ @memory.set(address, ror(@memory.get(address)))
429
+ },
430
+
431
+ # STA (indexed indirect)
432
+ 0x81 => lambda {
433
+ @memory.set(indexed_indirect, @a)
434
+ },
435
+
436
+ # STY (zero page)
437
+ 0x84 => lambda {
438
+ @memory.set(zero_page, @y)
439
+ },
440
+
441
+ # STA (zero page)
442
+ 0x85 => lambda {
443
+ @memory.set(zero_page, @a)
444
+ },
445
+
446
+ # STX (zero page)
447
+ 0x86 => lambda {
448
+ @memory.set(zero_page, @x)
449
+ },
450
+
451
+ # DEY
452
+ 0x88 => lambda {
453
+ @y = dec(@y) & 0xff
454
+ },
455
+
456
+ # TXA
457
+ 0x8a => lambda {
458
+ @a = @x & 0xff
459
+ set_nz_flags(@a)
460
+ },
461
+
462
+ # STY (absolute)
463
+ 0x8c => lambda {
464
+ @memory.set(absolute, @y)
465
+ },
466
+
467
+ # STA (absolute)
468
+ 0x8d => lambda {
469
+ @memory.set(absolute, @a)
470
+ },
471
+
472
+ # STX (absolute)
473
+ 0x8e => lambda {
474
+ @memory.set(absolute, @x)
475
+ },
476
+
477
+ # BCC
478
+ 0x90 => lambda {
479
+ offset = next_byte
480
+ @pc = branch(offset) unless @status.carry?
481
+ },
482
+
483
+ # STA (indirect indexed)
484
+ 0x91 => lambda {
485
+ @memory.set(indirect_indexed, @a)
486
+ },
487
+
488
+ # STY (zero page, X)
489
+ 0x94 => lambda {
490
+ @memory.set(zero_page(@x), @y)
491
+ },
492
+
493
+ # STA (zero page, X)
494
+ 0x95 => lambda {
495
+ @memory.set(zero_page(@x), @a)
496
+ },
497
+
498
+ # STX (zero page, Y)
499
+ 0x96 => lambda {
500
+ @memory.set(zero_page(@y), @x)
501
+ },
502
+
503
+ # TYA
504
+ 0x98 => lambda {
505
+ @a = @y & 0xff
506
+ set_nz_flags(@a)
507
+ },
508
+
509
+ # STA (absolute, Y)
510
+ 0x99 => lambda {
511
+ @memory.set(absolute(@y), @a)
512
+ },
513
+
514
+ # TXS
515
+ 0x9a => lambda {
516
+ @sp = @x & 0xff
517
+ },
518
+
519
+ # STA (absolute, X)
520
+ 0x9d => lambda {
521
+ @memory.set(absolute(@x), @a)
522
+ },
523
+
524
+ # LDY (immediate)
525
+ 0xa0 => lambda {
526
+ @y = next_byte
527
+ set_nz_flags(@y)
528
+ },
529
+
530
+ # LDA (indexed indirect)
531
+ 0xa1 => lambda {
532
+ @a = @memory.get(indexed_indirect)
533
+ set_nz_flags(@a)
534
+ },
535
+
536
+ # LDX (immediate)
537
+ 0xa2 => lambda {
538
+ @x = next_byte
539
+ set_nz_flags(@x)
540
+ },
541
+
542
+ # LDY (zero page)
543
+ 0xa4 => lambda {
544
+ @y = @memory.get(zero_page)
545
+ set_nz_flags(@y)
546
+ },
547
+
548
+ # LDA (zero page)
549
+ 0xa5 => lambda {
550
+ @a = @memory.get(zero_page)
551
+ set_nz_flags(@a)
552
+ },
553
+
554
+ # LDX (zero page)
555
+ 0xa6 => lambda {
556
+ @x = @memory.get(zero_page)
557
+ set_nz_flags(@x)
558
+ },
559
+
560
+ # TAY
561
+ 0xa8 => lambda {
562
+ @y = @a & 0xff
563
+ set_nz_flags(@y)
564
+ },
565
+
566
+ # LDA (immediate)
567
+ 0xa9 => lambda {
568
+ @a = next_byte
569
+ set_nz_flags(@a)
570
+ },
571
+
572
+ # TAX
573
+ 0xaa => lambda {
574
+ @x = @a & 0xff
575
+ set_nz_flags(@x)
576
+ },
577
+
578
+ # LDY (absolute)
579
+ 0xac => lambda {
580
+ @y = @memory.get(absolute)
581
+ set_nz_flags(@y)
582
+ },
583
+
584
+ # LDA (absolute)
585
+ 0xad => lambda {
586
+ @a = @memory.get(absolute)
587
+ set_nz_flags(@a)
588
+ },
589
+
590
+ # LDX (absolute)
591
+ 0xae => lambda {
592
+ @x = @memory.get(absolute)
593
+ set_nz_flags(@x)
594
+ },
595
+
596
+ # BCS
597
+ 0xb0 => lambda {
598
+ offset = next_byte
599
+ @pc = branch(offset) if @status.carry?
600
+ },
601
+
602
+ # LDA (indirect indexed)
603
+ 0xb1 => lambda {
604
+ @a = @memory.get(indirect_indexed)
605
+ set_nz_flags(@a)
606
+ },
607
+
608
+ # LDY (zero page, X)
609
+ 0xb4 => lambda {
610
+ @y = @memory.get(zero_page(@x))
611
+ set_nz_flags(@y)
612
+ },
613
+
614
+ # LDA (zero page, X)
615
+ 0xb5 => lambda {
616
+ @a = @memory.get(zero_page(@x))
617
+ set_nz_flags(@a)
618
+ },
619
+
620
+ # LDX (zero page, Y)
621
+ 0xb6 => lambda {
622
+ @x = @memory.get(zero_page(@y))
623
+ set_nz_flags(@x)
624
+ },
625
+
626
+ # CLV
627
+ 0xb8 => lambda {
628
+ @status.overflow = false
629
+ },
630
+
631
+ # LDA (absolute, Y)
632
+ 0xb9 => lambda {
633
+ @a = @memory.get(absolute(@y))
634
+ set_nz_flags(@a)
635
+ },
636
+
637
+ # TSX
638
+ 0xba => lambda {
639
+ @x = @sp & 0xff
640
+ set_nz_flags(@x)
641
+ },
642
+
643
+ # LDY (absolute, X)
644
+ 0xbc => lambda {
645
+ @y = @memory.get(absolute(@x))
646
+ set_nz_flags(@y)
647
+ },
648
+
649
+ # LDA (absolute, X)
650
+ 0xbd => lambda {
651
+ @a = @memory.get(absolute(@x))
652
+ set_nz_flags(@a)
653
+ },
654
+
655
+ # LDX (absolute, Y)
656
+ 0xbe => lambda {
657
+ @x = @memory.get(absolute(@y))
658
+ set_nz_flags(@x)
659
+ },
660
+
661
+ # CPY (immediate)
662
+ 0xc0 => lambda {
663
+ compare(@y, next_byte)
664
+ },
665
+
666
+ # CMP (indexed indirect)
667
+ 0xc1 => lambda {
668
+ compare(@a, @memory.get(indexed_indirect))
669
+ },
670
+
671
+ # CPY (zero page)
672
+ 0xc4 => lambda {
673
+ compare(@y, @memory.get(zero_page))
674
+ },
675
+
676
+ # CMP (zero page)
677
+ 0xc5 => lambda {
678
+ compare(@a, @memory.get(zero_page))
679
+ },
680
+
681
+ # DEC (zero page)
682
+ 0xc6 => lambda {
683
+ address = zero_page
684
+ @memory.set(address, dec(@memory.get(address)))
685
+ },
686
+
687
+ # INY
688
+ 0xc8 => lambda {
689
+ @y = inc(@y) & 0xff
690
+ },
691
+
692
+ # CMP (immediate)
693
+ 0xc9 => lambda {
694
+ compare(@a, next_byte)
695
+ },
696
+
697
+ # DEX
698
+ 0xca => lambda {
699
+ @x = dec(@x) & 0xff
700
+ },
701
+
702
+ # CPY (absolute)
703
+ 0xcc => lambda {
704
+ compare(@y, @memory.get(absolute))
705
+ },
706
+
707
+ # CMP (absolute)
708
+ 0xcd => lambda {
709
+ compare(@a, @memory.get(absolute))
710
+ },
711
+
712
+ # DEC (absolute)
713
+ 0xce => lambda {
714
+ address = absolute
715
+ @memory.set(address, dec(@memory.get(address)))
716
+ },
717
+
718
+ # BNE
719
+ 0xd0 => lambda {
720
+ offset = next_byte
721
+ @pc = branch(offset) unless @status.zero?
722
+ },
723
+
724
+ # CMP (indirect indexed)
725
+ 0xd1 => lambda {
726
+ compare(@a, @memory.get(indirect_indexed))
727
+ },
728
+
729
+ # CMP (zero page, X)
730
+ 0xd5 => lambda {
731
+ compare(@a, @memory.get(zero_page(@x)))
732
+ },
733
+
734
+ # DEC (zero page, X)
735
+ 0xd6 => lambda {
736
+ address = zero_page(@x)
737
+ @memory.set(address, dec(@memory.get(address)))
738
+ },
739
+
740
+ # CLD
741
+ 0xd8 => lambda {
742
+ @status.decimal_mode = false
743
+ },
744
+
745
+ # CMP (absolute, Y)
746
+ 0xd9 => lambda {
747
+ compare(@a, @memory.get(absolute(@y)))
748
+ },
749
+
750
+ # CMP (absolute, X)
751
+ 0xdd => lambda {
752
+ compare(@a, @memory.get(absolute(@x)))
753
+ },
754
+
755
+ # DEC (absolute, X)
756
+ 0xde => lambda {
757
+ address = absolute(@x)
758
+ @memory.set(address, dec(@memory.get(address)))
759
+ },
760
+
761
+ # CPX (immediate)
762
+ 0xe0 => lambda {
763
+ compare(@x, next_byte)
764
+ },
765
+
766
+ # SBC (indexed indirect)
767
+ 0xe1 => lambda {
768
+ sbc(@memory.get(indexed_indirect))
769
+ },
770
+
771
+ # CPX (zero page)
772
+ 0xe4 => lambda {
773
+ compare(@x, @memory.get(zero_page))
774
+ },
775
+
776
+ # SBC (zero page)
777
+ 0xe5 => lambda {
778
+ sbc(@memory.get(zero_page))
779
+ },
780
+
781
+ # INC (zero page)
782
+ 0xe6 => lambda {
783
+ address = zero_page
784
+ @memory.set(address, inc(@memory.get(address)))
785
+ },
786
+
787
+ # INX
788
+ 0xe8 => lambda {
789
+ @x = inc(@x) & 0xff
790
+ },
791
+
792
+ # SBC (immediate)
793
+ 0xe9 => lambda {
794
+ sbc(next_byte)
795
+ },
796
+
797
+ # NOP
798
+ 0xea => lambda {}, # rubocop:disable Style/Lambda
799
+
800
+ # CPX (absolute)
801
+ 0xec => lambda {
802
+ compare(@x, @memory.get(absolute))
803
+ },
804
+
805
+ # SBC (absolute)
806
+ 0xed => lambda {
807
+ sbc(@memory.get(absolute))
808
+ },
809
+
810
+ # INC (absolute)
811
+ 0xee => lambda {
812
+ address = absolute
813
+ @memory.set(address, inc(@memory.get(address)))
814
+ },
815
+
816
+ # BEQ
817
+ 0xf0 => lambda {
818
+ offset = next_byte
819
+ @pc = branch(offset) if @status.zero?
820
+ },
821
+
822
+ # SBC (indirect indexed)
823
+ 0xf1 => lambda {
824
+ sbc(@memory.get(indirect_indexed))
825
+ },
826
+
827
+ # SBC (zero page, X)
828
+ 0xf5 => lambda {
829
+ sbc(@memory.get(zero_page(@x)))
830
+ },
831
+
832
+ # INC (zero page, X)
833
+ 0xf6 => lambda {
834
+ address = zero_page(@x)
835
+ @memory.set(address, inc(@memory.get(address)))
836
+ },
837
+
838
+ # SED
839
+ 0xf8 => lambda {
840
+ @status.decimal_mode = true
841
+ },
842
+
843
+ # SBC (absolute, Y)
844
+ 0xf9 => lambda {
845
+ sbc(@memory.get(absolute(@y)))
846
+ },
847
+
848
+ # SBC (absolute, X)
849
+ 0xfd => lambda {
850
+ sbc(@memory.get(absolute(@x)))
851
+ },
852
+
853
+ # INC (absolute, X)
854
+ 0xfe => lambda {
855
+ address = absolute(@x)
856
+ @memory.set(address, inc(@memory.get(address)))
857
+ }
858
+ }
859
+ end
860
+ end
861
+ end