mos6510 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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