mos6510 0.1.1 → 0.1.3

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,893 @@
1
+ # This file is a pretty raw conversion of js/jssid.mos6510.js from
2
+ # https://github.com/jhohertz/jsSID
3
+
4
+ module Mos6510
5
+ class Mos6510
6
+ attr_accessor :cycles, :bval, :wval, :mem, :sid, :a, :x, :y, :s, :p, :pc
7
+
8
+ def initialize(mem, sid: nil)
9
+ # other internal values
10
+ self.cycles = 0
11
+ self.bval = 0
12
+ self.wval = 0
13
+
14
+ self.mem = mem
15
+ self.sid = sid
16
+
17
+ self.reset
18
+ end
19
+
20
+ def getmem(addr)
21
+ #if (addr < 0 || addr > 65536) puts "jsSID.MOS6510.getmem: out of range addr: " + addr + " (caller: " + arguments.caller + ")"
22
+ #if addr == 0xdd0d
23
+ # self.mem[addr] = 0;
24
+ #}
25
+ return self.mem[addr]
26
+ end
27
+
28
+ def setmem(addr, value)
29
+ #if (addr < 0 || addr > 65535) puts "jsSID.MOS6510.getmem: out of range addr: " + addr + " (caller: " + arguments.caller + ")"
30
+ #if (value < 0 || value > 255 ) puts "jsSID.MOS6510.getmem: out of range value: " + value + " (caller: " + arguments.caller + ")"
31
+ if (addr & 0xfc00) == 0xd400 && self.sid
32
+ self.sid.poke(addr & 0x1f, value)
33
+ if addr > 0xd418
34
+ puts "attempted digi poke:", addr, value
35
+ self.sid.pokeDigi(addr, value)
36
+ end
37
+ else
38
+ self.mem[addr] = value
39
+ end
40
+ end
41
+
42
+ # just like pc++, but with bound check on pc after
43
+ def pcinc
44
+ pc = self.pc
45
+ self.pc = (self.pc + 1) & 0xffff
46
+ return pc
47
+ end
48
+
49
+ def getaddr(mode)
50
+ case mode
51
+ when Mode::IMP
52
+ self.cycles += 2
53
+ return 0
54
+ when Mode::IMM
55
+ self.cycles += 2
56
+ return self.getmem(self.pcinc())
57
+ when Mode::ABS
58
+ self.cycles += 4
59
+ ad = self.getmem(self.pcinc())
60
+ ad |= self.getmem(self.pcinc()) << 8
61
+ return self.getmem(ad)
62
+ when Mode::ABSX
63
+ self.cycles += 4
64
+ ad = self.getmem(self.pcinc())
65
+ ad |= 256 * self.getmem(self.pcinc())
66
+ ad2 = ad + self.x
67
+ ad2 &= 0xffff
68
+ if (ad2 & 0xff00) != (ad & 0xff00)
69
+ self.cycles += 1
70
+ end
71
+ return self.getmem(ad2)
72
+ when Mode::ABSY
73
+ self.cycles += 4
74
+ ad = self.getmem(self.pcinc())
75
+ ad |= 256 * self.getmem(self.pcinc())
76
+ ad2 = ad + self.y
77
+ ad2 &= 0xffff
78
+ if (ad2 & 0xff00) != (ad & 0xff00)
79
+ self.cycles += 1
80
+ end
81
+ return self.getmem(ad2)
82
+ when Mode::ZP
83
+ self.cycles += 3
84
+ ad = self.getmem(self.pcinc())
85
+ return self.getmem(ad)
86
+ when Mode::ZPX
87
+ self.cycles += 4
88
+ ad = self.getmem(self.pcinc())
89
+ ad += self.x
90
+ return self.getmem(ad & 0xff)
91
+ when Mode::ZPY
92
+ self.cycles += 4
93
+ ad = self.getmem(self.pcinc())
94
+ ad += self.y
95
+ return self.getmem(ad & 0xff)
96
+ when Mode::INDX
97
+ self.cycles += 6
98
+ ad = self.getmem(self.pcinc())
99
+ ad += self.x
100
+ ad2 = self.getmem(ad & 0xff)
101
+ ad += 1
102
+ ad2 |= self.getmem(ad & 0xff) << 8
103
+ return self.getmem(ad2)
104
+ when Mode::INDY
105
+ self.cycles += 5
106
+ ad = self.getmem(self.pcinc())
107
+ ad2 = self.getmem(ad)
108
+ ad2 |= self.getmem((ad + 1) & 0xff) << 8
109
+ ad = ad2 + self.y
110
+ ad &= 0xffff
111
+ if (ad2 & 0xff00) != (ad & 0xff00)
112
+ self.cycles += 1
113
+ end
114
+ return self.getmem(ad)
115
+ when Mode::ACC
116
+ self.cycles += 2
117
+ return self.a
118
+ end
119
+ puts "getaddr: attempted unhandled mode"
120
+ return 0
121
+ end
122
+
123
+ def setaddr(mode, val)
124
+ # FIXME: not checking pc addresses as all should be relative to a valid instruction
125
+ case mode
126
+ when Mode::ABS
127
+ self.cycles += 2
128
+ ad = self.getmem(self.pc - 2)
129
+ ad |= 256 * self.getmem(self.pc - 1)
130
+ self.setmem(ad, val)
131
+ return
132
+ when Mode::ABSX
133
+ self.cycles += 3
134
+ ad = self.getmem(self.pc - 2)
135
+ ad |= 256 * self.getmem(self.pc - 1)
136
+ ad2 = ad + self.x
137
+ ad2 &= 0xffff
138
+ if (ad2 & 0xff00) != (ad & 0xff00)
139
+ self.cycles -= 1
140
+ end
141
+ self.setmem(ad2, val)
142
+ return
143
+ when Mode::ZP
144
+ self.cycles += 2
145
+ ad = self.getmem(self.pc - 1)
146
+ self.setmem(ad, val)
147
+ return
148
+ when Mode::ZPX
149
+ self.cycles += 2
150
+ ad = self.getmem(self.pc - 1)
151
+ ad += self.x
152
+ self.setmem(ad & 0xff, val)
153
+ return
154
+ when Mode::ACC
155
+ self.a = val
156
+ return
157
+ end
158
+ puts "setaddr: attempted unhandled mode"
159
+ end
160
+
161
+ def putaddr(mode, val)
162
+ case mode
163
+ when Mode::ABS
164
+ self.cycles += 4
165
+ ad = self.getmem(self.pcinc())
166
+ ad |= self.getmem(self.pcinc()) << 8
167
+ self.setmem(ad, val)
168
+ return
169
+ when Mode::ABSX
170
+ self.cycles += 4
171
+ ad = self.getmem(self.pcinc())
172
+ ad |= self.getmem(self.pcinc()) << 8
173
+ ad2 = ad + self.x
174
+ ad2 &= 0xffff
175
+ self.setmem(ad2, val)
176
+ return
177
+ when Mode::ABSY
178
+ self.cycles += 4
179
+ ad = self.getmem(self.pcinc())
180
+ ad |= self.getmem(self.pcinc()) << 8
181
+ ad2 = ad + self.y
182
+ ad2 &= 0xffff
183
+ if (ad2 & 0xff00) != (ad & 0xff00)
184
+ self.cycles += 1
185
+ end
186
+ self.setmem(ad2, val)
187
+ return
188
+ when Mode::ZP
189
+ self.cycles += 3
190
+ ad = self.getmem(self.pcinc())
191
+ self.setmem(ad, val)
192
+ return
193
+ when Mode::ZPX
194
+ self.cycles += 4
195
+ ad = self.getmem(self.pcinc())
196
+ ad += self.x
197
+ self.setmem(ad & 0xff, val)
198
+ return
199
+ when Mode::ZPY
200
+ self.cycles += 4
201
+ ad = self.getmem(self.pcinc())
202
+ ad += self.y
203
+ self.setmem(ad & 0xff,val)
204
+ return
205
+ when Mode::INDX
206
+ self.cycles += 6
207
+ ad = self.getmem(self.pcinc())
208
+ ad += self.x
209
+ ad2 = self.getmem(ad & 0xff)
210
+ ad += 1
211
+ ad2 |= self.getmem(ad & 0xff) << 8
212
+ self.setmem(ad2, val)
213
+ return
214
+ when Mode::INDY
215
+ self.cycles += 5
216
+ ad = self.getmem(self.pcinc())
217
+ ad2 = self.getmem(ad)
218
+ ad2 |= self.getmem((ad + 1) & 0xff) << 8
219
+ ad = ad2 + self.y
220
+ ad &= 0xffff
221
+ self.setmem(ad, val)
222
+ return
223
+ when Mode::ACC
224
+ self.cycles += 2
225
+ self.a = val
226
+ return
227
+ end
228
+ puts "putaddr: attempted unhandled mode"
229
+ end
230
+
231
+ def setflags(flag, cond)
232
+ if cond && cond != 0
233
+ self.p |= flag
234
+ else
235
+ self.p &= ~flag & 0xff
236
+ end
237
+ end
238
+
239
+ def push(val)
240
+ self.setmem(0x100 + self.s, val)
241
+ if self.s > 0
242
+ self.s -= 1
243
+ end
244
+ end
245
+
246
+ def pop
247
+ if self.s < 0xff
248
+ self.s += 1
249
+ end
250
+ self.getmem(0x100 + self.s)
251
+ end
252
+
253
+ def branch(flag)
254
+ dist = self.getaddr(Mode::IMM)
255
+ # FIXME: while this was checked out, it still seems too complicated
256
+ # make signed
257
+ if dist & 0x80 != 0
258
+ dist = 0 - ((~dist & 0xff) + 1)
259
+ end
260
+
261
+ # this here needs to be extracted for general 16-bit rounding needs
262
+ self.wval = self.pc + dist
263
+ # FIXME: added boundary checks to wrap around. Not sure this is whats needed
264
+ if self.wval < 0
265
+ self.wval += 65536
266
+ end
267
+ self.wval &= 0xffff
268
+ if flag
269
+ self.cycles += ((self.pc & 0x100) != (self.wval & 0x100)) ? 2 : 1
270
+ self.pc = self.wval
271
+ end
272
+ end
273
+
274
+ def reset
275
+ self.a = 0
276
+ self.x = 0
277
+ self.y = 0
278
+ self.p = 0
279
+ self.s = 255
280
+ self.pc = self.getmem(0xfffc)
281
+ self.pc |= 256 * self.getmem(0xfffd)
282
+ end
283
+
284
+ def step
285
+ c = nil # Is this ever used?
286
+ self.cycles = 0
287
+
288
+ opc = self.getmem(self.pcinc())
289
+ cmd = OPCODES[opc][0]
290
+ addr = OPCODES[opc][1]
291
+
292
+ case cmd
293
+ when Inst::ADC
294
+ self.wval = self.a + self.getaddr(addr) + ((self.p & Flag::C) != 0 ? 1 : 0)
295
+ self.setflags(Flag::C, self.wval & 0x100)
296
+ self.a = self.wval & 0xff
297
+ self.setflags(Flag::Z, self.a == 0)
298
+ self.setflags(Flag::N, self.a & 0x80)
299
+ self.setflags(Flag::V, ((self.p & Flag::C) != 0 ? 1 : 0) ^ ((self.p & Flag::N) != 0 ? 1 : 0))
300
+ when Inst::AND
301
+ self.bval = self.getaddr(addr)
302
+ self.a &= self.bval
303
+ self.setflags(Flag::Z, self.a == 0)
304
+ self.setflags(Flag::N, self.a & 0x80)
305
+ when Inst::ASL
306
+ self.wval = self.getaddr(addr)
307
+ self.wval <<= 1
308
+ self.setaddr(addr, self.wval & 0xff)
309
+ self.setflags(Flag::Z, self.wval == 0)
310
+ self.setflags(Flag::N, self.wval & 0x80)
311
+ self.setflags(Flag::C, self.wval & 0x100)
312
+ when Inst::BCC
313
+ self.branch(!(self.p & Flag::C != 0))
314
+ when Inst::BCS
315
+ self.branch(self.p & Flag::C != 0)
316
+ when Inst::BNE
317
+ self.branch(!(self.p & Flag::Z != 0))
318
+ when Inst::BEQ
319
+ self.branch(self.p & Flag::Z != 0)
320
+ when Inst::BPL
321
+ self.branch(!(self.p & Flag::N != 0))
322
+ when Inst::BMI
323
+ self.branch(self.p & Flag::N != 0)
324
+ when Inst::BVC
325
+ self.branch(!(self.p & Flag::V != 0))
326
+ when Inst::BVS
327
+ self.branch(self.p & Flag::V != 0)
328
+ when Inst::BIT
329
+ self.bval = self.getaddr(addr)
330
+ self.setflags(Flag::Z, (self.a & self.bval) == 0)
331
+ self.setflags(Flag::N, self.bval & 0x80)
332
+ self.setflags(Flag::V, self.bval & 0x40)
333
+ when Inst::BRK
334
+ pc = 0 # just quit per rockbox
335
+ #self.push(self.pc & 0xff);
336
+ #self.push(self.pc >> 8);
337
+ #self.push(self.p);
338
+ #self.setflags(jsSID.MOS6510.Flag::B, 1);
339
+ # FIXME: should Z be set as well?
340
+ #self.pc = self.getmem(0xfffe);
341
+ #self.cycles += 7;
342
+ when Inst::CLC
343
+ self.cycles += 2
344
+ self.setflags(Flag::C, 0)
345
+ when Inst::CLD
346
+ self.cycles += 2
347
+ self.setflags(Flag::D, 0)
348
+ when Inst::CLI
349
+ self.cycles += 2
350
+ self.setflags(Flag::I, 0)
351
+ when Inst::CLV
352
+ self.cycles += 2
353
+ self.setflags(Flag::V, 0)
354
+ when Inst::CMP
355
+ self.bval = self.getaddr(addr)
356
+ self.wval = self.a - self.bval
357
+ # FIXME: may not actually be needed (yay 2's complement)
358
+ if self.wval < 0
359
+ self.wval += 256
360
+ end
361
+ self.setflags(Flag::Z, self.wval == 0)
362
+ self.setflags(Flag::N, self.wval & 0x80)
363
+ self.setflags(Flag::C, self.a >= self.bval)
364
+ when Inst::CPX
365
+ self.bval = self.getaddr(addr)
366
+ self.wval = self.x - self.bval
367
+ # FIXME: may not actually be needed (yay 2's complement)
368
+ if self.wval < 0
369
+ self.wval += 256
370
+ end
371
+ self.setflags(Flag::Z, self.wval == 0)
372
+ self.setflags(Flag::N, self.wval & 0x80)
373
+ self.setflags(Flag::C, self.x >= self.bval)
374
+ when Inst::CPY
375
+ self.bval = self.getaddr(addr)
376
+ self.wval = self.y - self.bval
377
+ # FIXME: may not actually be needed (yay 2's complement)
378
+ if self.wval < 0
379
+ self.wval += 256
380
+ end
381
+ self.setflags(Flag::Z, self.wval == 0)
382
+ self.setflags(Flag::N, self.wval & 0x80)
383
+ self.setflags(Flag::C, self.y >= self.bval)
384
+ when Inst::DEC
385
+ self.bval = self.getaddr(addr)
386
+ self.bval -= 1
387
+ # FIXME: may be able to just mask this (yay 2's complement)
388
+ if self.bval < 0
389
+ self.bval += 256
390
+ end
391
+ self.setaddr(addr, self.bval)
392
+ self.setflags(Flag::Z, self.bval == 0)
393
+ self.setflags(Flag::N, self.bval & 0x80)
394
+ when Inst::DEX
395
+ self.cycles += 2
396
+ self.x -= 1
397
+ # FIXME: may be able to just mask this (yay 2's complement)
398
+ if self.x < 0
399
+ self.x += 256
400
+ end
401
+ self.setflags(Flag::Z, self.x == 0)
402
+ self.setflags(Flag::N, self.x & 0x80)
403
+ when Inst::DEY
404
+ self.cycles += 2
405
+ self.y -= 1
406
+ # FIXME: may be able to just mask this (yay 2's complement)
407
+ if self.y < 0
408
+ self.y += 256
409
+ end
410
+ self.setflags(Flag::Z, self.y == 0)
411
+ self.setflags(Flag::N, self.y & 0x80)
412
+ when Inst::EOR
413
+ self.bval = self.getaddr(addr)
414
+ self.a ^= self.bval
415
+ self.setflags(Flag::Z, self.a == 0)
416
+ self.setflags(Flag::N, self.a & 0x80)
417
+ when Inst::INC
418
+ self.bval = self.getaddr(addr)
419
+ self.bval += 1
420
+ self.bval &= 0xff
421
+ self.setaddr(addr, self.bval)
422
+ self.setflags(Flag::Z, self.bval == 0)
423
+ self.setflags(Flag::N, self.bval & 0x80)
424
+ when Inst::INX
425
+ self.cycles += 2
426
+ self.x += 1
427
+ self.x &= 0xff
428
+ self.setflags(Flag::Z, self.x == 0)
429
+ self.setflags(Flag::N, self.x & 0x80)
430
+ when Inst::INY
431
+ self.cycles += 2
432
+ self.y += 1
433
+ self.y &= 0xff
434
+ self.setflags(Flag::Z, self.y == 0)
435
+ self.setflags(Flag::N, self.y & 0x80)
436
+ when Inst::JMP
437
+ self.cycles += 3
438
+ self.wval = self.getmem(self.pcinc())
439
+ self.wval |= 256 * self.getmem(self.pcinc())
440
+ case addr
441
+ when Mode::ABS
442
+ self.pc = self.wval
443
+ when Mode::IND
444
+ self.pc = self.getmem(self.wval)
445
+ self.pc |= 256 * self.getmem((self.wval + 1) & 0xffff)
446
+ self.cycles += 2
447
+ end
448
+ when Inst::JSR
449
+ self.cycles += 6
450
+ self.push(((self.pc + 1) & 0xffff) >> 8)
451
+ self.push((self.pc + 1) & 0xff)
452
+ self.wval = self.getmem(self.pcinc())
453
+ self.wval |= 256 * self.getmem(self.pcinc())
454
+ self.pc = self.wval
455
+ when Inst::LDA
456
+ self.a = self.getaddr(addr)
457
+ self.setflags(Flag::Z, self.a == 0)
458
+ self.setflags(Flag::N, self.a & 0x80)
459
+ when Inst::LDX
460
+ self.x = self.getaddr(addr)
461
+ self.setflags(Flag::Z, self.x == 0)
462
+ self.setflags(Flag::N, self.x & 0x80)
463
+ when Inst::LDY
464
+ self.y = self.getaddr(addr)
465
+ self.setflags(Flag::Z, self.y == 0)
466
+ self.setflags(Flag::N, self.y & 0x80)
467
+ when Inst::LSR
468
+ self.bval = self.getaddr(addr)
469
+ self.wval = self.bval
470
+ self.wval >>= 1
471
+ self.setaddr(addr, self.wval & 0xff)
472
+ self.setflags(Flag::Z, self.wval == 0)
473
+ self.setflags(Flag::N, self.wval & 0x80)
474
+ self.setflags(Flag::C, self.bval & 1)
475
+ when Inst::NOP
476
+ self.cycles += 2
477
+ when Inst::ORA
478
+ self.bval = self.getaddr(addr)
479
+ self.a |= self.bval
480
+ self.setflags(Flag::Z, self.a == 0)
481
+ self.setflags(Flag::N, self.a & 0x80)
482
+ when Inst::PHA
483
+ self.push(self.a)
484
+ self.cycles += 3
485
+ when Inst::PHP
486
+ self.push(self.p)
487
+ self.cycles += 3
488
+ when Inst::PLA
489
+ self.a = self.pop
490
+ self.setflags(Flag::Z, self.a == 0)
491
+ self.setflags(Flag::N, self.a & 0x80)
492
+ self.cycles += 4
493
+ when Inst::PLP
494
+ self.p = self.pop
495
+ self.cycles += 4
496
+ when Inst::ROL
497
+ self.bval = self.getaddr(addr)
498
+ c = (self.p & Flag::C) != 0 ? 1 : 0
499
+ self.setflags(Flag::C, self.bval & 0x80)
500
+ self.bval <<= 1
501
+ self.bval |= c
502
+ self.bval &= 0xff
503
+ self.setaddr(addr, self.bval)
504
+ self.setflags(Flag::N, self.bval & 0x80)
505
+ self.setflags(Flag::Z, self.bval == 0)
506
+ when Inst::ROR
507
+ self.bval = self.getaddr(addr)
508
+ c = (self.p & Flag::C) != 0 ? 128 : 0
509
+ self.setflags(Flag::C, self.bval & 1)
510
+ self.bval >>= 1
511
+ self.bval |= c
512
+ self.setaddr(addr, self.bval)
513
+ self.setflags(Flag::N, self.bval & 0x80)
514
+ self.setflags(Flag::Z, self.bval == 0)
515
+ when Inst::RTI
516
+ # treat like RTS
517
+ when Inst::RTS
518
+ self.wval = self.pop
519
+ self.wval |= 256 * self.pop
520
+ self.pc = self.wval + 1
521
+ self.cycles += 6
522
+ when Inst::SBC
523
+ self.bval = self.getaddr(addr) ^ 0xff
524
+ self.wval = self.a + self.bval + ((self.p & Flag::C) != 0 ? 1 : 0)
525
+ self.setflags(Flag::C, self.wval & 0x100)
526
+ self.a = self.wval & 0xff
527
+ self.setflags(Flag::Z, self.a == 0)
528
+ self.setflags(Flag::N, self.a > 127)
529
+ self.setflags(Flag::V, ((self.p & Flag::C) != 0 ? 1 : 0) ^ ((self.p & Flag::N) != 0 ? 1 : 0))
530
+ when Inst::SEC
531
+ self.cycles += 2
532
+ self.setflags(Flag::C, 1)
533
+ when Inst::SED
534
+ self.cycles += 2
535
+ self.setflags(Flag::D, 1)
536
+ when Inst::SEI
537
+ self.cycles += 2
538
+ self.setflags(Flag::I, 1)
539
+ when Inst::STA
540
+ self.putaddr(addr, self.a)
541
+ when Inst::STX
542
+ self.putaddr(addr, self.x)
543
+ when Inst::STY
544
+ self.putaddr(addr, self.y)
545
+ when Inst::TAX
546
+ self.cycles += 2
547
+ self.x = self.a
548
+ self.setflags(Flag::Z, self.x == 0)
549
+ self.setflags(Flag::N, self.x & 0x80)
550
+ when Inst::TAY
551
+ self.cycles += 2
552
+ self.y = self.a
553
+ self.setflags(Flag::Z, self.y == 0)
554
+ self.setflags(Flag::N, self.y & 0x80)
555
+ when Inst::TSX
556
+ self.cycles += 2
557
+ self.x = self.s
558
+ self.setflags(Flag::Z, self.x == 0)
559
+ self.setflags(Flag::N, self.x & 0x80)
560
+ when Inst::TXA
561
+ self.cycles += 2
562
+ self.a = self.x
563
+ self.setflags(Flag::Z, self.a == 0)
564
+ self.setflags(Flag::N, self.a & 0x80)
565
+ when Inst::TXS
566
+ self.cycles += 2
567
+ self.s = self.x
568
+ when Inst::TYA
569
+ self.cycles += 2
570
+ self.a = self.y
571
+ self.setflags(Flag::Z, self.a == 0)
572
+ self.setflags(Flag::N, self.a & 0x80)
573
+ else
574
+ puts "step: attempted unhandled instruction, opcode: #{opc}"
575
+ end
576
+
577
+ self.cycles
578
+ end
579
+
580
+ def jsr(npc, na)
581
+ ccl = 0
582
+
583
+ self.a = na
584
+ self.x = 0
585
+ self.y = 0
586
+ self.p = 0
587
+ self.s = 255
588
+ self.pc = npc
589
+ self.push(0)
590
+ self.push(0)
591
+
592
+ while self.pc > 1
593
+ ccl += self.step
594
+ end
595
+
596
+ ccl
597
+ end
598
+
599
+ # Flags Enum
600
+ module Flag
601
+ N = 128; V = 64; B = 16; D = 8; I = 4; Z = 2; C = 1
602
+ end
603
+
604
+ # Opcodes Enum
605
+ module Inst
606
+ ADC = 'adc'; AND = 'and'; ASL = 'asl'; BCC = 'bcc'; BCS = 'bcs'; BEQ = 'beq'; BIT = 'bit'; BMI = 'bmi'; BNE = 'bne'; BPL = 'bpl'; BRK = 'brk'; BVC = 'bvc'; BVS = 'bvs'; CLC = 'clc';
607
+ CLD = 'cld'; CLI = 'cli'; CLV = 'clv'; CMP = 'cmp'; CPX = 'cpx'; CPY = 'cpy'; DEC = 'dec'; DEX = 'dex'; DEY = 'dey'; EOR = 'eor'; INC = 'inc'; INX = 'inx'; INY = 'iny'; JMP = 'jmp';
608
+ JSR = 'jsr'; LDA = 'lda'; LDX = 'ldx'; LDY = 'ldy'; LSR = 'lsr'; NOP = 'nop'; ORA = 'ora'; PHA = 'pha'; PHP = 'php'; PLA = 'pla'; PLP = 'plp'; ROL = 'rol'; ROR = 'ror'; RTI = 'rti';
609
+ RTS = 'rts'; SBC = 'sbc'; SEC = 'sec'; SED = 'sed'; SEI = 'sei'; STA = 'sta'; STX = 'stx'; STY = 'sty'; TAX = 'tax'; TAY = 'tay'; TSX = 'tsx'; TXA = 'txa'; TXS = 'txs'; TYA = 'tya';
610
+ XXX = 'xxx'
611
+ end
612
+
613
+ # Modes Enum
614
+ module Mode
615
+ IMP = 'imp'; IMM = 'imm'; ABS = 'abs'; ABSX = 'absx'; ABSY = 'absy'; ZP = 'zp'; ZPX = 'zpx'; ZPY = 'zpy'; IND = 'ind'; INDX = 'indx'; INDY = 'indy'; ACC = 'acc'; REL = 'rel'; XXX = 'xxx'
616
+ end
617
+
618
+ # 256 entries, each entry array pair of [inst, mode]
619
+ OPCODES = [
620
+ [Inst::BRK, Mode::IMP], # 0x00
621
+ [Inst::ORA, Mode::INDX], # 0x01
622
+ [Inst::XXX, Mode::XXX], # 0x02
623
+ [Inst::XXX, Mode::XXX], # 0x03
624
+ [Inst::XXX, Mode::ZP], # 0x04
625
+ [Inst::ORA, Mode::ZP], # 0x05
626
+ [Inst::ASL, Mode::ZP], # 0x06
627
+ [Inst::XXX, Mode::XXX], # 0x07
628
+ [Inst::PHP, Mode::IMP], # 0x08
629
+ [Inst::ORA, Mode::IMM], # 0x09
630
+ [Inst::ASL, Mode::ACC], # 0x0a
631
+ [Inst::XXX, Mode::XXX], # 0x0b
632
+ [Inst::XXX, Mode::ABS], # 0x0c
633
+ [Inst::ORA, Mode::ABS], # 0x0d
634
+ [Inst::ASL, Mode::ABS], # 0x0e
635
+ [Inst::XXX, Mode::XXX], # 0x0f
636
+
637
+ [Inst::BPL, Mode::REL], # 0x10
638
+ [Inst::ORA, Mode::INDY], # 0x11
639
+ [Inst::XXX, Mode::XXX], # 0x12
640
+ [Inst::XXX, Mode::XXX], # 0x13
641
+ [Inst::XXX, Mode::XXX], # 0x14
642
+ [Inst::ORA, Mode::ZPX], # 0x15
643
+ [Inst::ASL, Mode::ZPX], # 0x16
644
+ [Inst::XXX, Mode::XXX], # 0x17
645
+ [Inst::CLC, Mode::IMP], # 0x18
646
+ [Inst::ORA, Mode::ABSY], # 0x19
647
+ [Inst::XXX, Mode::XXX], # 0x1a
648
+ [Inst::XXX, Mode::XXX], # 0x1b
649
+ [Inst::XXX, Mode::XXX], # 0x1c
650
+ [Inst::ORA, Mode::ABSX], # 0x1d
651
+ [Inst::ASL, Mode::ABSX], # 0x1e
652
+ [Inst::XXX, Mode::XXX], # 0x1f
653
+
654
+ [Inst::JSR, Mode::ABS], # 0x20
655
+ [Inst::AND, Mode::INDX], # 0x21
656
+ [Inst::XXX, Mode::XXX], # 0x22
657
+ [Inst::XXX, Mode::XXX], # 0x23
658
+ [Inst::BIT, Mode::ZP], # 0x24
659
+ [Inst::AND, Mode::ZP], # 0x25
660
+ [Inst::ROL, Mode::ZP], # 0x26
661
+ [Inst::XXX, Mode::XXX], # 0x27
662
+ [Inst::PLP, Mode::IMP], # 0x28
663
+ [Inst::AND, Mode::IMM], # 0x29
664
+ [Inst::ROL, Mode::ACC], # 0x2a
665
+ [Inst::XXX, Mode::XXX], # 0x2b
666
+ [Inst::BIT, Mode::ABS], # 0x2c
667
+ [Inst::AND, Mode::ABS], # 0x2d
668
+ [Inst::ROL, Mode::ABS], # 0x2e
669
+ [Inst::XXX, Mode::XXX], # 0x2f
670
+
671
+ [Inst::BMI, Mode::REL], # 0x30
672
+ [Inst::AND, Mode::INDY], # 0x31
673
+ [Inst::XXX, Mode::XXX], # 0x32
674
+ [Inst::XXX, Mode::XXX], # 0x33
675
+ [Inst::XXX, Mode::XXX], # 0x34
676
+ [Inst::AND, Mode::ZPX], # 0x35
677
+ [Inst::ROL, Mode::ZPX], # 0x36
678
+ [Inst::XXX, Mode::XXX], # 0x37
679
+ [Inst::SEC, Mode::IMP], # 0x38
680
+ [Inst::AND, Mode::ABSY], # 0x39
681
+ [Inst::XXX, Mode::XXX], # 0x3a
682
+ [Inst::XXX, Mode::XXX], # 0x3b
683
+ [Inst::XXX, Mode::XXX], # 0x3c
684
+ [Inst::AND, Mode::ABSX], # 0x3d
685
+ [Inst::ROL, Mode::ABSX], # 0x3e
686
+ [Inst::XXX, Mode::XXX], # 0x3f
687
+
688
+ [Inst::RTI, Mode::IMP], # 0x40
689
+ [Inst::EOR, Mode::INDX], # 0x41
690
+ [Inst::XXX, Mode::XXX], # 0x42
691
+ [Inst::XXX, Mode::XXX], # 0x43
692
+ [Inst::XXX, Mode::ZP], # 0x44
693
+ [Inst::EOR, Mode::ZP], # 0x45
694
+ [Inst::LSR, Mode::ZP], # 0x46
695
+ [Inst::XXX, Mode::XXX], # 0x47
696
+ [Inst::PHA, Mode::IMP], # 0x48
697
+ [Inst::EOR, Mode::IMM], # 0x49
698
+ [Inst::LSR, Mode::ACC], # 0x4a
699
+ [Inst::XXX, Mode::XXX], # 0x4b
700
+ [Inst::JMP, Mode::ABS], # 0x4c
701
+ [Inst::EOR, Mode::ABS], # 0x4d
702
+ [Inst::LSR, Mode::ABS], # 0x4e
703
+ [Inst::XXX, Mode::XXX], # 0x4f
704
+
705
+ [Inst::BVC, Mode::REL], # 0x50
706
+ [Inst::EOR, Mode::INDY], # 0x51
707
+ [Inst::XXX, Mode::XXX], # 0x52
708
+ [Inst::XXX, Mode::XXX], # 0x53
709
+ [Inst::XXX, Mode::XXX], # 0x54
710
+ [Inst::EOR, Mode::ZPX], # 0x55
711
+ [Inst::LSR, Mode::ZPX], # 0x56
712
+ [Inst::XXX, Mode::XXX], # 0x57
713
+ [Inst::CLI, Mode::IMP], # 0x58
714
+ [Inst::EOR, Mode::ABSY], # 0x59
715
+ [Inst::XXX, Mode::XXX], # 0x5a
716
+ [Inst::XXX, Mode::XXX], # 0x5b
717
+ [Inst::XXX, Mode::XXX], # 0x5c
718
+ [Inst::EOR, Mode::ABSX], # 0x5d
719
+ [Inst::LSR, Mode::ABSX], # 0x5e
720
+ [Inst::XXX, Mode::XXX], # 0x5f
721
+
722
+ [Inst::RTS, Mode::IMP], # 0x60
723
+ [Inst::ADC, Mode::INDX], # 0x61
724
+ [Inst::XXX, Mode::XXX], # 0x62
725
+ [Inst::XXX, Mode::XXX], # 0x63
726
+ [Inst::XXX, Mode::ZP], # 0x64
727
+ [Inst::ADC, Mode::ZP], # 0x65
728
+ [Inst::ROR, Mode::ZP], # 0x66
729
+ [Inst::XXX, Mode::XXX], # 0x67
730
+ [Inst::PLA, Mode::IMP], # 0x68
731
+ [Inst::ADC, Mode::IMM], # 0x69
732
+ [Inst::ROR, Mode::ACC], # 0x6a
733
+ [Inst::XXX, Mode::XXX], # 0x6b
734
+ [Inst::JMP, Mode::IND], # 0x6c
735
+ [Inst::ADC, Mode::ABS], # 0x6d
736
+ [Inst::ROR, Mode::ABS], # 0x6e
737
+ [Inst::XXX, Mode::XXX], # 0x6f
738
+
739
+ [Inst::BVS, Mode::REL], # 0x70
740
+ [Inst::ADC, Mode::INDY], # 0x71
741
+ [Inst::XXX, Mode::XXX], # 0x72
742
+ [Inst::XXX, Mode::XXX], # 0x73
743
+ [Inst::XXX, Mode::XXX], # 0x74
744
+ [Inst::ADC, Mode::ZPX], # 0x75
745
+ [Inst::ROR, Mode::ZPX], # 0x76
746
+ [Inst::XXX, Mode::XXX], # 0x77
747
+ [Inst::SEI, Mode::IMP], # 0x78
748
+ [Inst::ADC, Mode::ABSY], # 0x79
749
+ [Inst::XXX, Mode::XXX], # 0x7a
750
+ [Inst::XXX, Mode::XXX], # 0x7b
751
+ [Inst::XXX, Mode::XXX], # 0x7c
752
+ [Inst::ADC, Mode::ABSX], # 0x7d
753
+ [Inst::ROR, Mode::ABSX], # 0x7e
754
+ [Inst::XXX, Mode::XXX], # 0x7f
755
+
756
+ [Inst::XXX, Mode::IMM], # 0x80
757
+ [Inst::STA, Mode::INDX], # 0x81
758
+ [Inst::XXX, Mode::XXX], # 0x82
759
+ [Inst::XXX, Mode::XXX], # 0x83
760
+ [Inst::STY, Mode::ZP], # 0x84
761
+ [Inst::STA, Mode::ZP], # 0x85
762
+ [Inst::STX, Mode::ZP], # 0x86
763
+ [Inst::XXX, Mode::XXX], # 0x87
764
+ [Inst::DEY, Mode::IMP], # 0x88
765
+ [Inst::XXX, Mode::IMM], # 0x89
766
+ [Inst::TXA, Mode::ACC], # 0x8a
767
+ [Inst::XXX, Mode::XXX], # 0x8b
768
+ [Inst::STY, Mode::ABS], # 0x8c
769
+ [Inst::STA, Mode::ABS], # 0x8d
770
+ [Inst::STX, Mode::ABS], # 0x8e
771
+ [Inst::XXX, Mode::XXX], # 0x8f
772
+
773
+ [Inst::BCC, Mode::REL], # 0x90
774
+ [Inst::STA, Mode::INDY], # 0x91
775
+ [Inst::XXX, Mode::XXX], # 0x92
776
+ [Inst::XXX, Mode::XXX], # 0x93
777
+ [Inst::STY, Mode::ZPX], # 0x94
778
+ [Inst::STA, Mode::ZPX], # 0x95
779
+ [Inst::STX, Mode::ZPY], # 0x96
780
+ [Inst::XXX, Mode::XXX], # 0x97
781
+ [Inst::TYA, Mode::IMP], # 0x98
782
+ [Inst::STA, Mode::ABSY], # 0x99
783
+ [Inst::TXS, Mode::ACC], # 0x9a
784
+ [Inst::XXX, Mode::XXX], # 0x9b
785
+ [Inst::XXX, Mode::XXX], # 0x9c
786
+ [Inst::STA, Mode::ABSX], # 0x9d
787
+ [Inst::XXX, Mode::ABSX], # 0x9e
788
+ [Inst::XXX, Mode::XXX], # 0x9f
789
+
790
+ [Inst::LDY, Mode::IMM], # 0xa0
791
+ [Inst::LDA, Mode::INDX], # 0xa1
792
+ [Inst::LDX, Mode::IMM], # 0xa2
793
+ [Inst::XXX, Mode::XXX], # 0xa3
794
+ [Inst::LDY, Mode::ZP], # 0xa4
795
+ [Inst::LDA, Mode::ZP], # 0xa5
796
+ [Inst::LDX, Mode::ZP], # 0xa6
797
+ [Inst::XXX, Mode::XXX], # 0xa7
798
+ [Inst::TAY, Mode::IMP], # 0xa8
799
+ [Inst::LDA, Mode::IMM], # 0xa9
800
+ [Inst::TAX, Mode::ACC], # 0xaa
801
+ [Inst::XXX, Mode::XXX], # 0xab
802
+ [Inst::LDY, Mode::ABS], # 0xac
803
+ [Inst::LDA, Mode::ABS], # 0xad
804
+ [Inst::LDX, Mode::ABS], # 0xae
805
+ [Inst::XXX, Mode::XXX], # 0xaf
806
+
807
+ [Inst::BCS, Mode::REL], # 0xb0
808
+ [Inst::LDA, Mode::INDY], # 0xb1
809
+ [Inst::XXX, Mode::XXX], # 0xb2
810
+ [Inst::XXX, Mode::XXX], # 0xb3
811
+ [Inst::LDY, Mode::ZPX], # 0xb4
812
+ [Inst::LDA, Mode::ZPX], # 0xb5
813
+ [Inst::LDX, Mode::ZPY], # 0xb6
814
+ [Inst::XXX, Mode::XXX], # 0xb7
815
+ [Inst::CLV, Mode::IMP], # 0xb8
816
+ [Inst::LDA, Mode::ABSY], # 0xb9
817
+ [Inst::TSX, Mode::ACC], # 0xba
818
+ [Inst::XXX, Mode::XXX], # 0xbb
819
+ [Inst::LDY, Mode::ABSX], # 0xbc
820
+ [Inst::LDA, Mode::ABSX], # 0xbd
821
+ [Inst::LDX, Mode::ABSY], # 0xbe
822
+ [Inst::XXX, Mode::XXX], # 0xbf
823
+
824
+ [Inst::CPY, Mode::IMM], # 0xc0
825
+ [Inst::CMP, Mode::INDX], # 0xc1
826
+ [Inst::XXX, Mode::XXX], # 0xc2
827
+ [Inst::XXX, Mode::XXX], # 0xc3
828
+ [Inst::CPY, Mode::ZP], # 0xc4
829
+ [Inst::CMP, Mode::ZP], # 0xc5
830
+ [Inst::DEC, Mode::ZP], # 0xc6
831
+ [Inst::XXX, Mode::XXX], # 0xc7
832
+ [Inst::INY, Mode::IMP], # 0xc8
833
+ [Inst::CMP, Mode::IMM], # 0xc9
834
+ [Inst::DEX, Mode::ACC], # 0xca
835
+ [Inst::XXX, Mode::XXX], # 0xcb
836
+ [Inst::CPY, Mode::ABS], # 0xcc
837
+ [Inst::CMP, Mode::ABS], # 0xcd
838
+ [Inst::DEC, Mode::ABS], # 0xce
839
+ [Inst::XXX, Mode::XXX], # 0xcf
840
+
841
+ [Inst::BNE, Mode::REL], # 0xd0
842
+ [Inst::CMP, Mode::INDY], # 0xd1
843
+ [Inst::XXX, Mode::XXX], # 0xd2
844
+ [Inst::XXX, Mode::XXX], # 0xd3
845
+ [Inst::XXX, Mode::ZPX], # 0xd4
846
+ [Inst::CMP, Mode::ZPX], # 0xd5
847
+ [Inst::DEC, Mode::ZPX], # 0xd6
848
+ [Inst::XXX, Mode::XXX], # 0xd7
849
+ [Inst::CLD, Mode::IMP], # 0xd8
850
+ [Inst::CMP, Mode::ABSY], # 0xd9
851
+ [Inst::XXX, Mode::ACC], # 0xda
852
+ [Inst::XXX, Mode::XXX], # 0xdb
853
+ [Inst::XXX, Mode::XXX], # 0xdc
854
+ [Inst::CMP, Mode::ABSX], # 0xdd
855
+ [Inst::DEC, Mode::ABSX], # 0xde
856
+ [Inst::XXX, Mode::XXX], # 0xdf
857
+
858
+ [Inst::CPX, Mode::IMM], # 0xe0
859
+ [Inst::SBC, Mode::INDX], # 0xe1
860
+ [Inst::XXX, Mode::XXX], # 0xe2
861
+ [Inst::XXX, Mode::XXX], # 0xe3
862
+ [Inst::CPX, Mode::ZP], # 0xe4
863
+ [Inst::SBC, Mode::ZP], # 0xe5
864
+ [Inst::INC, Mode::ZP], # 0xe6
865
+ [Inst::XXX, Mode::XXX], # 0xe7
866
+ [Inst::INX, Mode::IMP], # 0xe8
867
+ [Inst::SBC, Mode::IMM], # 0xe9
868
+ [Inst::NOP, Mode::ACC], # 0xea
869
+ [Inst::XXX, Mode::XXX], # 0xeb
870
+ [Inst::CPX, Mode::ABS], # 0xec
871
+ [Inst::SBC, Mode::ABS], # 0xed
872
+ [Inst::INC, Mode::ABS], # 0xee
873
+ [Inst::XXX, Mode::XXX], # 0xef
874
+
875
+ [Inst::BEQ, Mode::REL], # 0xf0
876
+ [Inst::SBC, Mode::INDY], # 0xf1
877
+ [Inst::XXX, Mode::XXX], # 0xf2
878
+ [Inst::XXX, Mode::XXX], # 0xf3
879
+ [Inst::XXX, Mode::ZPX], # 0xf4
880
+ [Inst::SBC, Mode::ZPX], # 0xf5
881
+ [Inst::INC, Mode::ZPX], # 0xf6
882
+ [Inst::XXX, Mode::XXX], # 0xf7
883
+ [Inst::SED, Mode::IMP], # 0xf8
884
+ [Inst::SBC, Mode::ABSY], # 0xf9
885
+ [Inst::XXX, Mode::ACC], # 0xfa
886
+ [Inst::XXX, Mode::XXX], # 0xfb
887
+ [Inst::XXX, Mode::XXX], # 0xfc
888
+ [Inst::SBC, Mode::ABSX], # 0xfd
889
+ [Inst::INC, Mode::ABSX], # 0xfe
890
+ [Inst::XXX, Mode::XXX] # 0xff
891
+ ].freeze
892
+ end
893
+ end