rubyboy 0.4.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rubyboy/cpu.rb CHANGED
@@ -1,96 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require_relative 'register'
3
+ require_relative 'registers'
4
+ require_relative 'operand'
5
5
 
6
6
  module Rubyboy
7
7
  class Cpu
8
- def initialize(bus)
9
- @a = Register.new(name: 'a', value: 0x01)
10
- @b = Register.new(name: 'b', value: 0x00)
11
- @c = Register.new(name: 'c', value: 0x13)
12
- @d = Register.new(name: 'd', value: 0x00)
13
- @e = Register.new(name: 'e', value: 0xd8)
14
- @h = Register.new(name: 'h', value: 0x01)
15
- @l = Register.new(name: 'l', value: 0x4d)
16
- @f = Register.new(name: 'f', value: 0xb0)
8
+ def initialize(bus, interrupt)
9
+ @bus = bus
10
+ @interrupt = interrupt
11
+ @registers = Registers.new
17
12
 
18
13
  @pc = 0x0100
19
14
  @sp = 0xfffe
20
15
  @ime = false
21
16
  @ime_delay = false
22
- @bus = bus
23
- @opcodes = File.open('lib/opcodes.json', 'r') { |file| JSON.parse(file.read) }
24
17
  @halted = false
25
-
26
- @cnt = 0
27
- end
28
-
29
- def af
30
- (@a.value << 8) + @f.value
31
- end
32
-
33
- def af=(value)
34
- value &= 0xffff
35
- @a.value = value >> 8
36
- @f.value = value & 0xf0
37
- end
38
-
39
- def bc
40
- (@b.value << 8) + @c.value
41
- end
42
-
43
- def bc=(value)
44
- value &= 0xffff
45
- @b.value = value >> 8
46
- @c.value = value & 0xff
47
- end
48
-
49
- def de
50
- (@d.value << 8) + @e.value
51
- end
52
-
53
- def de=(value)
54
- value &= 0xffff
55
- @d.value = value >> 8
56
- @e.value = value & 0xff
57
- end
58
-
59
- def hl
60
- (@h.value << 8) + @l.value
61
- end
62
-
63
- def hl=(value)
64
- value &= 0xffff
65
- @h.value = value >> 8
66
- @l.value = value & 0xff
67
18
  end
68
19
 
69
20
  def exec
70
21
  opcode = read_byte(@pc)
71
22
  # print_log(opcode)
72
23
 
73
- in_interrupt = false
24
+ @halted &= @interrupt.interrupts == 0
74
25
 
75
- if @ime && @bus.interrupt.interrupts.positive?
76
- in_interrupt = true
77
- else
78
- increment_pc
79
- end
26
+ return 16 if @halted
80
27
 
81
- if in_interrupt
28
+ if @ime && @interrupt.interrupts > 0
82
29
  pcs = [0x0040, 0x0048, 0x0050, 0x0058, 0x0060]
83
30
  5.times do |i|
84
- next if @bus.interrupt.interrupts[i].zero?
31
+ next if @interrupt.interrupts[i] == 0
85
32
 
86
- @bus.interrupt.if &= (~(1 << i)) & 0xff
33
+ @interrupt.reset_flag(i)
87
34
  @ime = false
88
35
  @sp -= 2
89
36
  @bus.write_word(@sp, @pc)
90
37
  @pc = pcs[i]
38
+
91
39
  break
92
40
  end
41
+
93
42
  return 20
43
+ else
44
+ increment_pc
94
45
  end
95
46
 
96
47
  if @ime_delay
@@ -98,1386 +49,517 @@ module Rubyboy
98
49
  @ime = true
99
50
  end
100
51
 
101
- cbprefixed = false
102
- branched = false
103
-
104
52
  case opcode
105
- when 0x00 # NOP
106
- when 0x01 # LD BC, nn
107
- self.bc = read_word_and_advance_pc
108
- when 0x02 # LD (BC), A
109
- write_byte(bc, @a.value)
110
- when 0x03 # INC BC
111
- self.bc = bc + 1
112
- when 0x04 # INC B
113
- @b.increment
114
- update_flags(
115
- z: @b.value.zero?,
116
- n: false,
117
- h: (@b.value & 0x0f).zero?
118
- )
119
- when 0x05 # DEC B
120
- @b.decrement
121
- update_flags(
122
- z: @b.value.zero?,
123
- n: true,
124
- h: (@b.value & 0x0f) == 0x0f
125
- )
126
- when 0x06 # LD B, d8
127
- @b.value = read_byte_and_advance_pc
128
- when 0x07 # RLCA
129
- @a.value = (@a.value << 1) | (@a.value >> 7)
130
- update_flags(
131
- z: false,
132
- n: false,
133
- h: false,
134
- c: @a.value[0] == 1
135
- )
136
- when 0x08 # LD (nn), SP
137
- word = read_word_and_advance_pc
138
- write_word(word, @sp)
139
- when 0x09 # ADD HL, BC
140
- hflag = (hl & 0x0fff) + (bc & 0x0fff) > 0x0fff
141
- cflag = hl + bc > 0xffff
142
- self.hl = hl + bc
143
- update_flags(
144
- n: false,
145
- h: hflag,
146
- c: cflag
147
- )
148
- when 0x0a # LD A, (BC)
149
- @a.value = read_byte(bc)
150
- when 0x0b # DEC BC
151
- self.bc = bc - 1
152
- when 0x0c # INC C
153
- @c.increment
154
- update_flags(
155
- z: @c.value.zero?,
156
- n: false,
157
- h: (@c.value & 0x0f).zero?
158
- )
159
- when 0x0d # DEC C
160
- @c.decrement
161
- update_flags(
162
- z: @c.value.zero?,
163
- n: true,
164
- h: (@c.value & 0x0f) == 0x0f
165
- )
166
- when 0x0e # LD C, d8
167
- @c.value = read_byte_and_advance_pc
168
- when 0x0f # RRCA
169
- @a.value = (@a.value >> 1) | (@a.value << 7)
170
- update_flags(
171
- z: false,
172
- n: false,
173
- h: false,
174
- c: @a.value[7] == 1
175
- )
176
- when 0x10 # STOP
177
- when 0x11 # LD DE, nn
178
- self.de = read_word_and_advance_pc
179
- when 0x12 # LD (DE), A
180
- write_byte(de, @a.value)
181
- when 0x13 # INC DE
182
- self.de = de + 1
183
- when 0x14 # INC D
184
- @d.increment
185
- update_flags(
186
- z: @d.value.zero?,
187
- n: false,
188
- h: (@d.value & 0x0f).zero?
189
- )
190
- when 0x15 # DEC D
191
- @d.decrement
192
- update_flags(
193
- z: @d.value.zero?,
194
- n: true,
195
- h: (@d.value & 0x0f) == 0x0f
196
- )
197
- when 0x16 # LD D, d8
198
- @d.value = read_byte_and_advance_pc
199
- when 0x17 # RLA
200
- cflag = @a.value[7] == 1
201
- @a.value = (@a.value << 1) | bool_to_integer(flags[:c])
202
- update_flags(
203
- z: false,
204
- n: false,
205
- h: false,
206
- c: cflag
207
- )
208
- when 0x18 # JR r8
209
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
210
- @pc += byte
211
- when 0x19 # ADD HL, DE
212
- hflag = (hl & 0x0fff) + (de & 0x0fff) > 0x0fff
213
- cflag = hl + de > 0xffff
214
- self.hl = hl + de
215
- update_flags(
216
- n: false,
217
- h: hflag,
218
- c: cflag
219
- )
220
- when 0x1a # LD A, (DE)
221
- @a.value = read_byte(de)
222
- when 0x1b # DEC DE
223
- self.de = de - 1
224
- when 0x1c # INC E
225
- @e.increment
226
- update_flags(
227
- z: @e.value.zero?,
228
- n: false,
229
- h: (@e.value & 0x0f).zero?
230
- )
231
- when 0x1d # DEC E
232
- @e.decrement
233
- update_flags(
234
- z: @e.value.zero?,
235
- n: true,
236
- h: (@e.value & 0x0f) == 0x0f
237
- )
238
- when 0x1e # LD E, d8
239
- @e.value = read_byte_and_advance_pc
240
- when 0x1f # RRA
241
- cflag = @a.value[0] == 1
242
- @a.value = (@a.value >> 1) | (bool_to_integer(flags[:c]) << 7)
243
- update_flags(
244
- z: false,
245
- n: false,
246
- h: false,
247
- c: cflag
248
- )
249
- when 0x20 # JR NZ, r8
250
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
251
- unless flags[:z]
252
- @pc += byte
253
- branched = true
254
- end
255
- when 0x21 # LD HL, nn
256
- self.hl = read_word_and_advance_pc
257
- when 0x22 # LD (HL+), A
258
- write_byte(hl, @a.value)
259
- self.hl = hl + 1
260
- when 0x23 # INC HL
261
- self.hl = hl + 1
262
- when 0x24 # INC H
263
- @h.increment
264
- update_flags(
265
- z: @h.value.zero?,
266
- n: false,
267
- h: (@h.value & 0x0f).zero?
268
- )
269
- when 0x25 # DEC H
270
- @h.decrement
271
- update_flags(
272
- z: @h.value.zero?,
273
- n: true,
274
- h: (@h.value & 0x0f) == 0x0f
275
- )
276
- when 0x26 # LD H, d8
277
- @h.value = read_byte_and_advance_pc
278
- when 0x27 # DAA
279
- if flags[:n]
280
- @a.value -= 0x06 if flags[:h]
281
- @a.value -= 0x60 if flags[:c]
282
- else
283
- if flags[:c] || @a.value > 0x99
284
- @a.value += 0x60
285
- update_flags(c: true)
286
- end
287
- @a.value += 0x06 if flags[:h] || (@a.value & 0x0f) > 0x09
288
- end
289
- update_flags(
290
- z: @a.value.zero?,
291
- h: false
292
- )
293
- when 0x28 # JR Z, r8
294
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
295
- if flags[:z]
296
- @pc += byte
297
- branched = true
298
- end
299
- when 0x29 # ADD HL, HL
300
- hflag = (hl & 0x0fff) + (hl & 0x0fff) > 0x0fff
301
- cflag = hl + hl > 0xffff
302
- self.hl = hl + hl
303
- update_flags(
304
- n: false,
305
- h: hflag,
306
- c: cflag
307
- )
308
- when 0x2a # LD A, (HL+)
309
- @a.value = read_byte(hl)
310
- self.hl = hl + 1
311
- when 0x2b # DEC HL
312
- self.hl = hl - 1
313
- when 0x2c # INC L
314
- @l.increment
315
- update_flags(
316
- z: @l.value.zero?,
317
- n: false,
318
- h: (@l.value & 0x0f).zero?
319
- )
320
- when 0x2d # DEC L
321
- @l.decrement
322
- update_flags(
323
- z: @l.value.zero?,
324
- n: true,
325
- h: (@l.value & 0x0f) == 0x0f
326
- )
327
- when 0x2e # LD L, d8
328
- @l.value = read_byte_and_advance_pc
329
- when 0x2f # CPL
330
- @a.value = ~@a.value
331
- update_flags(
332
- n: true,
333
- h: true
334
- )
335
- when 0x30 # JR NC, r8
336
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
337
- unless flags[:c]
338
- @pc += byte
339
- branched = true
340
- end
341
- when 0x31 # LD SP, nn
342
- @sp = read_word_and_advance_pc
343
- when 0x32 # LD (HL-), A
344
- write_byte(hl, @a.value)
345
- self.hl = hl - 1
346
- when 0x33 # INC SP
347
- @sp = (@sp + 1) & 0xffff
348
- when 0x34 # INC (HL)
349
- byte = read_byte(hl)
350
- byte = (byte + 1) & 0xff
351
- write_byte(hl, byte)
352
- update_flags(
353
- z: byte.zero?,
354
- n: false,
355
- h: (byte & 0x0f).zero?
356
- )
357
- when 0x35 # DEC (HL)
358
- byte = read_byte(hl)
359
- byte = (byte - 1) & 0xff
360
- write_byte(hl, byte)
361
- update_flags(
362
- z: byte.zero?,
363
- n: true,
364
- h: (byte & 0x0f) == 0x0f
365
- )
366
- when 0x36 # LD (HL), d8
367
- byte = read_byte_and_advance_pc
368
- write_byte(hl, byte)
369
- when 0x37 # SCF
370
- update_flags(
371
- n: false,
372
- h: false,
373
- c: true
374
- )
375
- when 0x38 # JR C, r8
376
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
377
- if flags[:c]
378
- @pc += byte
379
- branched = true
380
- end
381
- when 0x39 # ADD HL, SP
382
- hflag = (hl & 0x0fff) + (@sp & 0x0fff) > 0x0fff
383
- cflag = hl + @sp > 0xffff
384
- self.hl = hl + @sp
385
- update_flags(
386
- n: false,
387
- h: hflag,
388
- c: cflag
389
- )
390
- when 0x3a # LD A, (HL-)
391
- @a.value = read_byte(hl)
392
- self.hl = hl - 1
393
- when 0x3b # DEC SP
394
- @sp = (@sp - 1) & 0xffff
395
- when 0x3c # INC A
396
- @a.increment
397
- update_flags(
398
- z: @a.value.zero?,
399
- n: false,
400
- h: (@a.value & 0x0f).zero?
401
- )
402
- when 0x3d # DEC A
403
- @a.decrement
404
- update_flags(
405
- z: @a.value.zero?,
406
- n: true,
407
- h: (@a.value & 0x0f) == 0x0f
408
- )
409
- when 0x3e # LD A, d8
410
- @a.value = read_byte_and_advance_pc
411
- when 0x3f # CCF
412
- update_flags(
413
- n: false,
414
- h: false,
415
- c: !flags[:c]
416
- )
417
- when 0x40 # LD B, B
418
- @b.value = @b.value
419
- when 0x41 # LD B, C
420
- @b.value = @c.value
421
- when 0x42 # LD B, D
422
- @b.value = @d.value
423
- when 0x43 # LD B, E
424
- @b.value = @e.value
425
- when 0x44 # LD B, H
426
- @b.value = @h.value
427
- when 0x45 # LD B, L
428
- @b.value = @l.value
429
- when 0x46 # LD B, (HL)
430
- @b.value = read_byte(hl)
431
- when 0x47 # LD B, A
432
- @b.value = @a.value
433
- when 0x48 # LD C, B
434
- @c.value = @b.value
435
- when 0x49 # LD C, C
436
- @c.value = @c.value
437
- when 0x4a # LD C, D
438
- @c.value = @d.value
439
- when 0x4b # LD C, E
440
- @c.value = @e.value
441
- when 0x4c # LD C, H
442
- @c.value = @h.value
443
- when 0x4d # LD C, L
444
- @c.value = @l.value
445
- when 0x4e # LD C, (HL)
446
- @c.value = read_byte(hl)
447
- when 0x4f # LD C, A
448
- @c.value = @a.value
449
- when 0x50 # LD D, B
450
- @d.value = @b.value
451
- when 0x51 # LD D, C
452
- @d.value = @c.value
453
- when 0x52 # LD D, D
454
- @d.value = @d.value
455
- when 0x53 # LD D, E
456
- @d.value = @e.value
457
- when 0x54 # LD D, H
458
- @d.value = @h.value
459
- when 0x55 # LD D, L
460
- @d.value = @l.value
461
- when 0x56 # LD D, (HL)
462
- @d.value = read_byte(hl)
463
- when 0x57 # LD D, A
464
- @d.value = @a.value
465
- when 0x58 # LD E, B
466
- @e.value = @b.value
467
- when 0x59 # LD E, C
468
- @e.value = @c.value
469
- when 0x5a # LD E, D
470
- @e.value = @d.value
471
- when 0x5b # LD E, E
472
- @e.value = @e.value
473
- when 0x5c # LD E, H
474
- @e.value = @h.value
475
- when 0x5d # LD E, L
476
- @e.value = @l.value
477
- when 0x5e # LD E, (HL)
478
- @e.value = read_byte(hl)
479
- when 0x5f # LD E, A
480
- @e.value = @a.value
481
- when 0x60 # LD H, B
482
- @h.value = @b.value
483
- when 0x61 # LD H, C
484
- @h.value = @c.value
485
- when 0x62 # LD H, D
486
- @h.value = @d.value
487
- when 0x63 # LD H, E
488
- @h.value = @e.value
489
- when 0x64 # LD H, H
490
- @h.value = @h.value
491
- when 0x65 # LD H, L
492
- @h.value = @l.value
493
- when 0x66 # LD H, (HL)
494
- @h.value = read_byte(hl)
495
- when 0x67 # LD H, A
496
- @h.value = @a.value
497
- when 0x68 # LD L, B
498
- @l.value = @b.value
499
- when 0x69 # LD L, C
500
- @l.value = @c.value
501
- when 0x6a # LD L, D
502
- @l.value = @d.value
503
- when 0x6b # LD L, E
504
- @l.value = @e.value
505
- when 0x6c # LD L, H
506
- @l.value = @h.value
507
- when 0x6d # LD L, L
508
- @l.value = @l.value
509
- when 0x6e # LD L, (HL)
510
- @l.value = read_byte(hl)
511
- when 0x6f # LD L, A
512
- @l.value = @a.value
513
- when 0x70 # LD (HL), B
514
- write_byte(hl, @b.value)
515
- when 0x71 # LD (HL), C
516
- write_byte(hl, @c.value)
517
- when 0x72 # LD (HL), D
518
- write_byte(hl, @d.value)
519
- when 0x73 # LD (HL), E
520
- write_byte(hl, @e.value)
521
- when 0x74 # LD (HL), H
522
- write_byte(hl, @h.value)
523
- when 0x75 # LD (HL), L
524
- write_byte(hl, @l.value)
525
- when 0x76 # HALT
526
- @pc -= 1 unless @bus.interrupt.interrupts.positive?
527
- when 0x77 # LD (HL), A
528
- write_byte(hl, @a.value)
529
- when 0x78 # LD A, B
530
- @a.value = @b.value
531
- when 0x79 # LD A, C
532
- @a.value = @c.value
533
- when 0x7a # LD A, D
534
- @a.value = @d.value
535
- when 0x7b # LD A, E
536
- @a.value = @e.value
537
- when 0x7c # LD A, H
538
- @a.value = @h.value
539
- when 0x7d # LD A, L
540
- @a.value = @l.value
541
- when 0x7e # LD A, (HL)
542
- @a.value = read_byte(hl)
543
- when 0x7f # LD A, A
544
- @a.value = @a.value
545
- when 0x80 # ADD A, B
546
- add8(@a, @b)
547
- when 0x81 # ADD A, C
548
- add8(@a, @c)
549
- when 0x82 # ADD A, D
550
- add8(@a, @d)
551
- when 0x83 # ADD A, E
552
- add8(@a, @e)
553
- when 0x84 # ADD A, H
554
- add8(@a, @h)
555
- when 0x85 # ADD A, L
556
- add8(@a, @l)
557
- when 0x86 # ADD A, (HL)
558
- add8(@a, Register.new(name: 'HL', value: read_byte(hl)))
559
- when 0x87 # ADD A, A
560
- add8(@a, @a)
561
- when 0x88 # ADC A, B
562
- adc8(@a, @b)
563
- when 0x89 # ADC A, C
564
- adc8(@a, @c)
565
- when 0x8a # ADC A, D
566
- adc8(@a, @d)
567
- when 0x8b # ADC A, E
568
- adc8(@a, @e)
569
- when 0x8c # ADC A, H
570
- adc8(@a, @h)
571
- when 0x8d # ADC A, L
572
- adc8(@a, @l)
573
- when 0x8e # ADC A, (HL)
574
- adc8(@a, Register.new(name: 'HL', value: read_byte(hl)))
575
- when 0x8f # ADC A, A
576
- adc8(@a, @a)
577
- when 0x90 # SUB B
578
- sub8(@b)
579
- when 0x91 # SUB C
580
- sub8(@c)
581
- when 0x92 # SUB D
582
- sub8(@d)
583
- when 0x93 # SUB E
584
- sub8(@e)
585
- when 0x94 # SUB H
586
- sub8(@h)
587
- when 0x95 # SUB L
588
- sub8(@l)
589
- when 0x96 # SUB (HL)
590
- sub8(Register.new(name: 'HL', value: read_byte(hl)))
591
- when 0x97 # SUB A
592
- sub8(@a)
593
- when 0x98 # SBC A, B
594
- sbc8(@b)
595
- when 0x99 # SBC A, C
596
- sbc8(@c)
597
- when 0x9a # SBC A, D
598
- sbc8(@d)
599
- when 0x9b # SBC A, E
600
- sbc8(@e)
601
- when 0x9c # SBC A, H
602
- sbc8(@h)
603
- when 0x9d # SBC A, L
604
- sbc8(@l)
605
- when 0x9e # SBC A, (HL)
606
- sbc8(Register.new(name: 'HL', value: read_byte(hl)))
607
- when 0x9f # SBC A, A
608
- sbc8(@a)
609
- when 0xa0 # AND B
610
- and8(@b)
611
- when 0xa1 # AND C
612
- and8(@c)
613
- when 0xa2 # AND D
614
- and8(@d)
615
- when 0xa3 # AND E
616
- and8(@e)
617
- when 0xa4 # AND H
618
- and8(@h)
619
- when 0xa5 # AND L
620
- and8(@l)
621
- when 0xa6 # AND (HL)
622
- and8(Register.new(name: 'HL', value: read_byte(hl)))
623
- when 0xa7 # AND A
624
- and8(@a)
625
- when 0xa8 # XOR B
626
- xor8(@b)
627
- when 0xa9 # XOR C
628
- xor8(@c)
629
- when 0xaa # XOR D
630
- xor8(@d)
631
- when 0xab # XOR E
632
- xor8(@e)
633
- when 0xac # XOR H
634
- xor8(@h)
635
- when 0xad # XOR L
636
- xor8(@l)
637
- when 0xae # XOR (HL)
638
- xor8(Register.new(name: 'HL', value: read_byte(hl)))
639
- when 0xaf # XOR A
640
- xor8(@a)
641
- when 0xb0 # OR B
642
- or8(@b)
643
- when 0xb1 # OR C
644
- or8(@c)
645
- when 0xb2 # OR D
646
- or8(@d)
647
- when 0xb3 # OR E
648
- or8(@e)
649
- when 0xb4 # OR H
650
- or8(@h)
651
- when 0xb5 # OR L
652
- or8(@l)
653
- when 0xb6 # OR (HL)
654
- or8(Register.new(name: 'HL', value: read_byte(hl)))
655
- when 0xb7 # OR A
656
- or8(@a)
657
- when 0xb8 # CP B
658
- cp8(@b)
659
- when 0xb9 # CP C
660
- cp8(@c)
661
- when 0xba # CP D
662
- cp8(@d)
663
- when 0xbb # CP E
664
- cp8(@e)
665
- when 0xbc # CP H
666
- cp8(@h)
667
- when 0xbd # CP L
668
- cp8(@l)
669
- when 0xbe # CP (HL)
670
- cp8(Register.new(name: 'HL', value: read_byte(hl)))
671
- when 0xbf # CP A
672
- cp8(@a)
673
- when 0xc0 # RET NZ
674
- unless flags[:z]
675
- @pc = read_word(@sp)
676
- @sp += 2
677
- branched = true
678
- end
679
- when 0xc1 # POP BC
680
- self.bc = read_word(@sp)
681
- @sp += 2
682
- when 0xc2 # JP NZ, nn
683
- word = read_word_and_advance_pc
684
- unless flags[:z]
685
- @pc = word
686
- branched = true
687
- end
688
- when 0xc3 # JP nn
689
- @pc = read_word_and_advance_pc
690
- when 0xc4 # CALL NZ, nn
691
- word = read_word_and_advance_pc
692
- unless flags[:z]
693
- @sp -= 2
694
- write_word(@sp, @pc)
695
- @pc = word
696
- branched = true
697
- end
698
- when 0xc5 # PUSH BC
699
- @sp -= 2
700
- write_word(@sp, bc)
701
- when 0xc6 # ADD A, d8
702
- byte = read_byte_and_advance_pc
703
- add8(@a, Register.new(name: 'd8', value: byte))
704
- when 0xc7 # RST 00H
705
- @sp -= 2
706
- write_word(@sp, @pc)
707
- @pc = 0x00
708
- when 0xc8 # RET Z
709
- if flags[:z]
710
- @pc = read_word(@sp)
711
- @sp += 2
712
- branched = true
713
- end
714
- when 0xc9 # RET
715
- @pc = read_word(@sp)
716
- @sp += 2
717
- when 0xca # JP Z, nn
718
- word = read_word_and_advance_pc
719
- if flags[:z]
720
- @pc = word
721
- branched = true
722
- end
723
- when 0xcc # CALL Z, nn
724
- word = read_word_and_advance_pc
725
- if flags[:z]
726
- @sp -= 2
727
- write_word(@sp, @pc)
728
- @pc = word
729
- branched = true
730
- end
731
- when 0xcd # CALL nn
732
- word = read_word_and_advance_pc
733
- @sp -= 2
734
- write_word(@sp, @pc)
735
- @pc = word
736
- when 0xce # ADC A, d8
737
- byte = read_byte_and_advance_pc
738
- adc8(@a, Register.new(name: 'd8', value: byte))
739
- when 0xcf # RST 08H
740
- @sp -= 2
741
- write_word(@sp, @pc)
742
- @pc = 0x08
743
- when 0xd0 # RET NC
744
- unless flags[:c]
745
- @pc = read_word(@sp)
746
- @sp += 2
747
- branched = true
748
- end
749
- when 0xd1 # POP DE
750
- self.de = read_word(@sp)
751
- @sp += 2
752
- when 0xd2 # JP NC, nn
753
- word = read_word_and_advance_pc
754
- unless flags[:c]
755
- @pc = word
756
- branched = true
757
- end
758
- when 0xd4 # CALL NC, nn
759
- word = read_word_and_advance_pc
760
- unless flags[:c]
761
- @sp -= 2
762
- write_word(@sp, @pc)
763
- @pc = word
764
- branched = true
765
- end
766
- when 0xd5 # PUSH DE
767
- @sp -= 2
768
- write_word(@sp, de)
769
- when 0xd6 # SUB d8
770
- byte = read_byte_and_advance_pc
771
- sub8(Register.new(name: 'd8', value: byte))
772
- when 0xd7 # RST 10H
773
- @sp -= 2
774
- write_word(@sp, @pc)
775
- @pc = 0x10
776
- when 0xd8 # RET C
777
- if flags[:c]
778
- @pc = read_word(@sp)
779
- @sp += 2
780
- branched = true
781
- end
782
- when 0xd9 # RETI
783
- @pc = read_word(@sp)
784
- @sp += 2
785
- @ime = true
786
- when 0xda # JP C, nn
787
- word = read_word_and_advance_pc
788
- if flags[:c]
789
- @pc = word
790
- branched = true
791
- end
792
- when 0xdc # CALL C, nn
793
- word = read_word_and_advance_pc
794
- if flags[:c]
795
- @sp -= 2
796
- write_word(@sp, @pc)
797
- @pc = word
798
- branched = true
799
- end
800
- when 0xde # SBC A, d8
801
- byte = read_byte_and_advance_pc
802
- sbc8(Register.new(name: 'd8', value: byte))
803
- when 0xdf # RST 18H
804
- @sp -= 2
805
- write_word(@sp, @pc)
806
- @pc = 0x18
807
- when 0xe0 # LDH (a8), A
808
- byte = read_byte_and_advance_pc
809
- write_byte(0xff00 + byte, @a.value)
810
- when 0xe1 # POP HL
811
- self.hl = read_word(@sp)
812
- @sp += 2
813
- when 0xe2 # LD (C), A
814
- write_byte(0xff00 + @c.value, @a.value)
815
- when 0xe5 # PUSH HL
816
- @sp -= 2
817
- write_word(@sp, hl)
818
- when 0xe6 # AND d8
819
- byte = read_byte_and_advance_pc
820
- and8(Register.new(name: 'd8', value: byte))
821
- when 0xe7 # RST 20H
822
- @sp -= 2
823
- write_word(@sp, @pc)
824
- @pc = 0x20
825
- when 0xe8 # ADD SP, r8
826
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
827
-
828
- hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
829
- cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
830
-
831
- @sp += byte
832
- @sp &= 0xffff
833
- update_flags(
834
- z: false,
835
- n: false,
836
- h: hflag,
837
- c: cflag
838
- )
839
- when 0xe9 # JP (HL)
840
- @pc = hl
841
- when 0xea # LD (nn), A
842
- word = read_word_and_advance_pc
843
- write_byte(word, @a.value)
844
- when 0xee # XOR d8
845
- byte = read_byte_and_advance_pc
846
- xor8(Register.new(name: 'd8', value: byte))
847
- when 0xef # RST 28H
848
- @sp -= 2
849
- write_word(@sp, @pc)
850
- @pc = 0x28
851
- when 0xf0 # LDH A, (a8)
852
- byte = read_byte_and_advance_pc
853
- @a.value = read_byte(0xff00 + byte)
854
- when 0xf1 # POP AF
855
- self.af = read_word(@sp)
856
- @sp += 2
857
- when 0xf2 # LD A, (C)
858
- @a.value = read_byte(0xff00 + @c.value)
859
- when 0xf3 # DI
860
- @ime_delay = false
861
- @ime = false
862
- when 0xf5 # PUSH AF
863
- @sp -= 2
864
- write_word(@sp, af)
865
- when 0xf6 # OR d8
866
- byte = read_byte_and_advance_pc
867
- or8(Register.new(name: 'd8', value: byte))
868
- when 0xf7 # RST 30H
869
- @sp -= 2
870
- write_word(@sp, @pc)
871
- @pc = 0x30
872
- when 0xf8 # LD HL, SP+r8
873
- byte = convert_to_twos_complement(read_byte_and_advance_pc)
874
-
875
- hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
876
- cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
877
- self.hl = @sp + byte
878
- update_flags(
879
- z: false,
880
- n: false,
881
- h: hflag,
882
- c: cflag
883
- )
884
- when 0xf9 # LD SP, HL
885
- @sp = hl
886
- when 0xfa # LD A, (nn)
887
- word = read_word_and_advance_pc
888
- @a.value = read_byte(word)
889
- when 0xfb # EI
890
- @ime_delay = true
891
- when 0xfe # CP d8
892
- byte = read_byte_and_advance_pc
893
- update_flags(
894
- z: @a.value == byte,
895
- n: true,
896
- h: (@a.value & 0x0f) < (byte & 0x0f),
897
- c: @a.value < byte
898
- )
899
- when 0xff # RST 38H
900
- @sp -= 2
901
- write_word(@sp, @pc)
902
- @pc = 0x38
53
+ when 0x00 then 4 # NOP
54
+ when 0x01 then ld16({ type: :register16, value: :bc }, { type: :immediate16 })
55
+ when 0x02 then ld8({ type: :indirect, value: :bc }, { type: :register8, value: :a })
56
+ when 0x03 then inc16({ type: :register16, value: :bc })
57
+ when 0x04 then inc8({ type: :register8, value: :b })
58
+ when 0x05 then dec8({ type: :register8, value: :b })
59
+ when 0x06 then ld8({ type: :register8, value: :b }, { type: :immediate8 })
60
+ when 0x07 then rlca
61
+ when 0x08 then ld16({ type: :direct16 }, { type: :sp })
62
+ when 0x09 then add16({ type: :register16, value: :hl }, { type: :register16, value: :bc })
63
+ when 0x0a then ld8({ type: :register8, value: :a }, { type: :indirect, value: :bc })
64
+ when 0x0b then dec16({ type: :register16, value: :bc })
65
+ when 0x0c then inc8({ type: :register8, value: :c })
66
+ when 0x0d then dec8({ type: :register8, value: :c })
67
+ when 0x0e then ld8({ type: :register8, value: :c }, { type: :immediate8 })
68
+ when 0x0f then rrca
69
+ when 0x10 then 4 # STOP
70
+ when 0x11 then ld16({ type: :register16, value: :de }, { type: :immediate16 })
71
+ when 0x12 then ld8({ type: :indirect, value: :de }, { type: :register8, value: :a })
72
+ when 0x13 then inc16({ type: :register16, value: :de })
73
+ when 0x14 then inc8({ type: :register8, value: :d })
74
+ when 0x15 then dec8({ type: :register8, value: :d })
75
+ when 0x16 then ld8({ type: :register8, value: :d }, { type: :immediate8 })
76
+ when 0x17 then rla
77
+ when 0x18 then jr
78
+ when 0x19 then add16({ type: :register16, value: :hl }, { type: :register16, value: :de })
79
+ when 0x1a then ld8({ type: :register8, value: :a }, { type: :indirect, value: :de })
80
+ when 0x1b then dec16({ type: :register16, value: :de })
81
+ when 0x1c then inc8({ type: :register8, value: :e })
82
+ when 0x1d then dec8({ type: :register8, value: :e })
83
+ when 0x1e then ld8({ type: :register8, value: :e }, { type: :immediate8 })
84
+ when 0x1f then rra
85
+ when 0x20 then jr(condition: !flags[:z])
86
+ when 0x21 then ld16({ type: :register16, value: :hl }, { type: :immediate16 })
87
+ when 0x22 then ld8({ type: :hl_inc }, { type: :register8, value: :a })
88
+ when 0x23 then inc16({ type: :register16, value: :hl })
89
+ when 0x24 then inc8({ type: :register8, value: :h })
90
+ when 0x25 then dec8({ type: :register8, value: :h })
91
+ when 0x26 then ld8({ type: :register8, value: :h }, { type: :immediate8 })
92
+ when 0x27 then daa
93
+ when 0x28 then jr(condition: flags[:z])
94
+ when 0x29 then add16({ type: :register16, value: :hl }, { type: :register16, value: :hl })
95
+ when 0x2a then ld8({ type: :register8, value: :a }, { type: :hl_inc })
96
+ when 0x2b then dec16({ type: :register16, value: :hl })
97
+ when 0x2c then inc8({ type: :register8, value: :l })
98
+ when 0x2d then dec8({ type: :register8, value: :l })
99
+ when 0x2e then ld8({ type: :register8, value: :l }, { type: :immediate8 })
100
+ when 0x2f then cpl
101
+ when 0x30 then jr(condition: !flags[:c])
102
+ when 0x31 then ld16({ type: :sp }, { type: :immediate16 })
103
+ when 0x32 then ld8({ type: :hl_dec }, { type: :register8, value: :a })
104
+ when 0x33 then inc16({ type: :sp })
105
+ when 0x34 then inc8({ type: :indirect, value: :hl })
106
+ when 0x35 then dec8({ type: :indirect, value: :hl })
107
+ when 0x36 then ld8({ type: :indirect, value: :hl }, { type: :immediate8 })
108
+ when 0x37 then scf
109
+ when 0x38 then jr(condition: flags[:c])
110
+ when 0x39 then add16({ type: :register16, value: :hl }, { type: :sp })
111
+ when 0x3a then ld8({ type: :register8, value: :a }, { type: :hl_dec })
112
+ when 0x3b then dec16({ type: :sp })
113
+ when 0x3c then inc8({ type: :register8, value: :a })
114
+ when 0x3d then dec8({ type: :register8, value: :a })
115
+ when 0x3e then ld8({ type: :register8, value: :a }, { type: :immediate8 })
116
+ when 0x3f then ccf
117
+ when 0x40 then ld8({ type: :register8, value: :b }, { type: :register8, value: :b })
118
+ when 0x41 then ld8({ type: :register8, value: :b }, { type: :register8, value: :c })
119
+ when 0x42 then ld8({ type: :register8, value: :b }, { type: :register8, value: :d })
120
+ when 0x43 then ld8({ type: :register8, value: :b }, { type: :register8, value: :e })
121
+ when 0x44 then ld8({ type: :register8, value: :b }, { type: :register8, value: :h })
122
+ when 0x45 then ld8({ type: :register8, value: :b }, { type: :register8, value: :l })
123
+ when 0x46 then ld8({ type: :register8, value: :b }, { type: :indirect, value: :hl })
124
+ when 0x47 then ld8({ type: :register8, value: :b }, { type: :register8, value: :a })
125
+ when 0x48 then ld8({ type: :register8, value: :c }, { type: :register8, value: :b })
126
+ when 0x49 then ld8({ type: :register8, value: :c }, { type: :register8, value: :c })
127
+ when 0x4a then ld8({ type: :register8, value: :c }, { type: :register8, value: :d })
128
+ when 0x4b then ld8({ type: :register8, value: :c }, { type: :register8, value: :e })
129
+ when 0x4c then ld8({ type: :register8, value: :c }, { type: :register8, value: :h })
130
+ when 0x4d then ld8({ type: :register8, value: :c }, { type: :register8, value: :l })
131
+ when 0x4e then ld8({ type: :register8, value: :c }, { type: :indirect, value: :hl })
132
+ when 0x4f then ld8({ type: :register8, value: :c }, { type: :register8, value: :a })
133
+ when 0x50 then ld8({ type: :register8, value: :d }, { type: :register8, value: :b })
134
+ when 0x51 then ld8({ type: :register8, value: :d }, { type: :register8, value: :c })
135
+ when 0x52 then ld8({ type: :register8, value: :d }, { type: :register8, value: :d })
136
+ when 0x53 then ld8({ type: :register8, value: :d }, { type: :register8, value: :e })
137
+ when 0x54 then ld8({ type: :register8, value: :d }, { type: :register8, value: :h })
138
+ when 0x55 then ld8({ type: :register8, value: :d }, { type: :register8, value: :l })
139
+ when 0x56 then ld8({ type: :register8, value: :d }, { type: :indirect, value: :hl })
140
+ when 0x57 then ld8({ type: :register8, value: :d }, { type: :register8, value: :a })
141
+ when 0x58 then ld8({ type: :register8, value: :e }, { type: :register8, value: :b })
142
+ when 0x59 then ld8({ type: :register8, value: :e }, { type: :register8, value: :c })
143
+ when 0x5a then ld8({ type: :register8, value: :e }, { type: :register8, value: :d })
144
+ when 0x5b then ld8({ type: :register8, value: :e }, { type: :register8, value: :e })
145
+ when 0x5c then ld8({ type: :register8, value: :e }, { type: :register8, value: :h })
146
+ when 0x5d then ld8({ type: :register8, value: :e }, { type: :register8, value: :l })
147
+ when 0x5e then ld8({ type: :register8, value: :e }, { type: :indirect, value: :hl })
148
+ when 0x5f then ld8({ type: :register8, value: :e }, { type: :register8, value: :a })
149
+ when 0x60 then ld8({ type: :register8, value: :h }, { type: :register8, value: :b })
150
+ when 0x61 then ld8({ type: :register8, value: :h }, { type: :register8, value: :c })
151
+ when 0x62 then ld8({ type: :register8, value: :h }, { type: :register8, value: :d })
152
+ when 0x63 then ld8({ type: :register8, value: :h }, { type: :register8, value: :e })
153
+ when 0x64 then ld8({ type: :register8, value: :h }, { type: :register8, value: :h })
154
+ when 0x65 then ld8({ type: :register8, value: :h }, { type: :register8, value: :l })
155
+ when 0x66 then ld8({ type: :register8, value: :h }, { type: :indirect, value: :hl })
156
+ when 0x67 then ld8({ type: :register8, value: :h }, { type: :register8, value: :a })
157
+ when 0x68 then ld8({ type: :register8, value: :l }, { type: :register8, value: :b })
158
+ when 0x69 then ld8({ type: :register8, value: :l }, { type: :register8, value: :c })
159
+ when 0x6a then ld8({ type: :register8, value: :l }, { type: :register8, value: :d })
160
+ when 0x6b then ld8({ type: :register8, value: :l }, { type: :register8, value: :e })
161
+ when 0x6c then ld8({ type: :register8, value: :l }, { type: :register8, value: :h })
162
+ when 0x6d then ld8({ type: :register8, value: :l }, { type: :register8, value: :l })
163
+ when 0x6e then ld8({ type: :register8, value: :l }, { type: :indirect, value: :hl })
164
+ when 0x6f then ld8({ type: :register8, value: :l }, { type: :register8, value: :a })
165
+ when 0x70 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :b })
166
+ when 0x71 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :c })
167
+ when 0x72 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :d })
168
+ when 0x73 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :e })
169
+ when 0x74 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :h })
170
+ when 0x75 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :l })
171
+ when 0x76 then halt
172
+ when 0x77 then ld8({ type: :indirect, value: :hl }, { type: :register8, value: :a })
173
+ when 0x78 then ld8({ type: :register8, value: :a }, { type: :register8, value: :b })
174
+ when 0x79 then ld8({ type: :register8, value: :a }, { type: :register8, value: :c })
175
+ when 0x7a then ld8({ type: :register8, value: :a }, { type: :register8, value: :d })
176
+ when 0x7b then ld8({ type: :register8, value: :a }, { type: :register8, value: :e })
177
+ when 0x7c then ld8({ type: :register8, value: :a }, { type: :register8, value: :h })
178
+ when 0x7d then ld8({ type: :register8, value: :a }, { type: :register8, value: :l })
179
+ when 0x7e then ld8({ type: :register8, value: :a }, { type: :indirect, value: :hl })
180
+ when 0x7f then ld8({ type: :register8, value: :a }, { type: :register8, value: :a })
181
+ when 0x80 then add8({ type: :register8, value: :b })
182
+ when 0x81 then add8({ type: :register8, value: :c })
183
+ when 0x82 then add8({ type: :register8, value: :d })
184
+ when 0x83 then add8({ type: :register8, value: :e })
185
+ when 0x84 then add8({ type: :register8, value: :h })
186
+ when 0x85 then add8({ type: :register8, value: :l })
187
+ when 0x86 then add8({ type: :indirect, value: :hl })
188
+ when 0x87 then add8({ type: :register8, value: :a })
189
+ when 0x88 then adc8({ type: :register8, value: :b })
190
+ when 0x89 then adc8({ type: :register8, value: :c })
191
+ when 0x8a then adc8({ type: :register8, value: :d })
192
+ when 0x8b then adc8({ type: :register8, value: :e })
193
+ when 0x8c then adc8({ type: :register8, value: :h })
194
+ when 0x8d then adc8({ type: :register8, value: :l })
195
+ when 0x8e then adc8({ type: :indirect, value: :hl })
196
+ when 0x8f then adc8({ type: :register8, value: :a })
197
+ when 0x90 then sub8({ type: :register8, value: :b })
198
+ when 0x91 then sub8({ type: :register8, value: :c })
199
+ when 0x92 then sub8({ type: :register8, value: :d })
200
+ when 0x93 then sub8({ type: :register8, value: :e })
201
+ when 0x94 then sub8({ type: :register8, value: :h })
202
+ when 0x95 then sub8({ type: :register8, value: :l })
203
+ when 0x96 then sub8({ type: :indirect, value: :hl })
204
+ when 0x97 then sub8({ type: :register8, value: :a })
205
+ when 0x98 then sbc8({ type: :register8, value: :b })
206
+ when 0x99 then sbc8({ type: :register8, value: :c })
207
+ when 0x9a then sbc8({ type: :register8, value: :d })
208
+ when 0x9b then sbc8({ type: :register8, value: :e })
209
+ when 0x9c then sbc8({ type: :register8, value: :h })
210
+ when 0x9d then sbc8({ type: :register8, value: :l })
211
+ when 0x9e then sbc8({ type: :indirect, value: :hl })
212
+ when 0x9f then sbc8({ type: :register8, value: :a })
213
+ when 0xa0 then and8({ type: :register8, value: :b })
214
+ when 0xa1 then and8({ type: :register8, value: :c })
215
+ when 0xa2 then and8({ type: :register8, value: :d })
216
+ when 0xa3 then and8({ type: :register8, value: :e })
217
+ when 0xa4 then and8({ type: :register8, value: :h })
218
+ when 0xa5 then and8({ type: :register8, value: :l })
219
+ when 0xa6 then and8({ type: :indirect, value: :hl })
220
+ when 0xa7 then and8({ type: :register8, value: :a })
221
+ when 0xa8 then xor8({ type: :register8, value: :b })
222
+ when 0xa9 then xor8({ type: :register8, value: :c })
223
+ when 0xaa then xor8({ type: :register8, value: :d })
224
+ when 0xab then xor8({ type: :register8, value: :e })
225
+ when 0xac then xor8({ type: :register8, value: :h })
226
+ when 0xad then xor8({ type: :register8, value: :l })
227
+ when 0xae then xor8({ type: :indirect, value: :hl })
228
+ when 0xaf then xor8({ type: :register8, value: :a })
229
+ when 0xb0 then or8({ type: :register8, value: :b })
230
+ when 0xb1 then or8({ type: :register8, value: :c })
231
+ when 0xb2 then or8({ type: :register8, value: :d })
232
+ when 0xb3 then or8({ type: :register8, value: :e })
233
+ when 0xb4 then or8({ type: :register8, value: :h })
234
+ when 0xb5 then or8({ type: :register8, value: :l })
235
+ when 0xb6 then or8({ type: :indirect, value: :hl })
236
+ when 0xb7 then or8({ type: :register8, value: :a })
237
+ when 0xb8 then cp8({ type: :register8, value: :b })
238
+ when 0xb9 then cp8({ type: :register8, value: :c })
239
+ when 0xba then cp8({ type: :register8, value: :d })
240
+ when 0xbb then cp8({ type: :register8, value: :e })
241
+ when 0xbc then cp8({ type: :register8, value: :h })
242
+ when 0xbd then cp8({ type: :register8, value: :l })
243
+ when 0xbe then cp8({ type: :indirect, value: :hl })
244
+ when 0xbf then cp8({ type: :register8, value: :a })
245
+ when 0xc0 then ret_if(!flags[:z])
246
+ when 0xc1 then pop16(:bc)
247
+ when 0xc2 then jp({ type: :immediate16 }, condition: !flags[:z])
248
+ when 0xc3 then jp({ type: :immediate16 })
249
+ when 0xc4 then call16({ type: :immediate16 }, condition: !flags[:z])
250
+ when 0xc5 then push16(:bc)
251
+ when 0xc6 then add8({ type: :immediate8 })
252
+ when 0xc7 then rst(0x00)
253
+ when 0xc8 then ret_if(flags[:z])
254
+ when 0xc9 then ret
255
+ when 0xca then jp({ type: :immediate16 }, condition: flags[:z])
256
+ when 0xcc then call16({ type: :immediate16 }, condition: flags[:z])
257
+ when 0xcd then call16({ type: :immediate16 })
258
+ when 0xce then adc8({ type: :immediate8 })
259
+ when 0xcf then rst(0x08)
260
+ when 0xd0 then ret_if(!flags[:c])
261
+ when 0xd1 then pop16(:de)
262
+ when 0xd2 then jp({ type: :immediate16 }, condition: !flags[:c])
263
+ when 0xd4 then call16({ type: :immediate16 }, condition: !flags[:c])
264
+ when 0xd5 then push16(:de)
265
+ when 0xd6 then sub8({ type: :immediate8 })
266
+ when 0xd7 then rst(0x10)
267
+ when 0xd8 then ret_if(flags[:c])
268
+ when 0xd9 then reti
269
+ when 0xda then jp({ type: :immediate16 }, condition: flags[:c])
270
+ when 0xdc then call16({ type: :immediate16 }, condition: flags[:c])
271
+ when 0xde then sbc8({ type: :immediate8 })
272
+ when 0xdf then rst(0x18)
273
+ when 0xe0 then ld8({ type: :ff00 }, { type: :register8, value: :a })
274
+ when 0xe1 then pop16(:hl)
275
+ when 0xe2 then ld8({ type: :ff00_c }, { type: :register8, value: :a })
276
+ when 0xe5 then push16(:hl)
277
+ when 0xe6 then and8({ type: :immediate8 })
278
+ when 0xe7 then rst(0x20)
279
+ when 0xe8 then add_sp_r8
280
+ when 0xe9 then jp({ type: :register16, value: :hl })
281
+ when 0xea then ld8({ type: :direct8 }, { type: :register8, value: :a })
282
+ when 0xee then xor8({ type: :immediate8 })
283
+ when 0xef then rst(0x28)
284
+ when 0xf0 then ld8({ type: :register8, value: :a }, { type: :ff00 })
285
+ when 0xf1 then pop16(:af)
286
+ when 0xf2 then ld8({ type: :register8, value: :a }, { type: :ff00_c })
287
+ when 0xf3 then di
288
+ when 0xf5 then push16(:af)
289
+ when 0xf6 then or8({ type: :immediate8 })
290
+ when 0xf7 then rst(0x30)
291
+ when 0xf8 then ld_hl_sp_r8
292
+ when 0xf9 then ld16({ type: :sp }, { type: :register16, value: :hl })
293
+ when 0xfa then ld8({ type: :register8, value: :a }, { type: :direct8 })
294
+ when 0xfb then ei
295
+ when 0xfe then cp8({ type: :immediate8 })
296
+ when 0xff then rst(0x38)
903
297
  when 0xcb # CB prefix
904
298
  opcode = read_byte_and_advance_pc
905
- cbprefixed = true
906
-
907
- # p "CB #{opcode.to_s(16)}"
908
299
 
909
300
  case opcode
910
- when 0x00 # RLC B
911
- rlc8(@b)
912
- when 0x01 # RLC C
913
- rlc8(@c)
914
- when 0x02 # RLC D
915
- rlc8(@d)
916
- when 0x03 # RLC E
917
- rlc8(@e)
918
- when 0x04 # RLC H
919
- rlc8(@h)
920
- when 0x05 # RLC L
921
- rlc8(@l)
922
- when 0x06 # RLC (HL)
923
- reg = Register.new(name: 'HL', value: read_byte(hl))
924
- rlc8(reg)
925
- write_byte(hl, reg.value)
926
- when 0x07 # RLC A
927
- rlc8(@a)
928
- when 0x08 # RRC B
929
- rrc8(@b)
930
- when 0x09 # RRC C
931
- rrc8(@c)
932
- when 0x0a # RRC D
933
- rrc8(@d)
934
- when 0x0b # RRC E
935
- rrc8(@e)
936
- when 0x0c # RRC H
937
- rrc8(@h)
938
- when 0x0d # RRC L
939
- rrc8(@l)
940
- when 0x0e # RRC (HL)
941
- reg = Register.new(name: 'HL', value: read_byte(hl))
942
- rrc8(reg)
943
- write_byte(hl, reg.value)
944
- when 0x0f # RRC A
945
- rrc8(@a)
946
- when 0x10 # RL B
947
- rl8(@b)
948
- when 0x11 # RL C
949
- rl8(@c)
950
- when 0x12 # RL D
951
- rl8(@d)
952
- when 0x13 # RL E
953
- rl8(@e)
954
- when 0x14 # RL H
955
- rl8(@h)
956
- when 0x15 # RL L
957
- rl8(@l)
958
- when 0x16 # RL (HL)
959
- reg = Register.new(name: 'HL', value: read_byte(hl))
960
- rl8(reg)
961
- write_byte(hl, reg.value)
962
- when 0x17 # RL A
963
- rl8(@a)
964
- when 0x18 # RR B
965
- rr8(@b)
966
- when 0x19 # RR C
967
- rr8(@c)
968
- when 0x1a # RR D
969
- rr8(@d)
970
- when 0x1b # RR E
971
- rr8(@e)
972
- when 0x1c # RR H
973
- rr8(@h)
974
- when 0x1d # RR L
975
- rr8(@l)
976
- when 0x1e # RR (HL)
977
- reg = Register.new(name: 'HL', value: read_byte(hl))
978
- rr8(reg)
979
- write_byte(hl, reg.value)
980
- when 0x1f # RR A
981
- rr8(@a)
982
- when 0x20 # SLA B
983
- sla8(@b)
984
- when 0x21 # SLA C
985
- sla8(@c)
986
- when 0x22 # SLA D
987
- sla8(@d)
988
- when 0x23 # SLA E
989
- sla8(@e)
990
- when 0x24 # SLA H
991
- sla8(@h)
992
- when 0x25 # SLA L
993
- sla8(@l)
994
- when 0x26 # SLA (HL)
995
- reg = Register.new(name: 'HL', value: read_byte(hl))
996
- sla8(reg)
997
- write_byte(hl, reg.value)
998
- when 0x27 # SLA A
999
- sla8(@a)
1000
- when 0x28 # SRA B
1001
- sra8(@b)
1002
- when 0x29 # SRA C
1003
- sra8(@c)
1004
- when 0x2a # SRA D
1005
- sra8(@d)
1006
- when 0x2b # SRA E
1007
- sra8(@e)
1008
- when 0x2c # SRA H
1009
- sra8(@h)
1010
- when 0x2d # SRA L
1011
- sra8(@l)
1012
- when 0x2e # SRA (HL)
1013
- reg = Register.new(name: 'HL', value: read_byte(hl))
1014
- sra8(reg)
1015
- write_byte(hl, reg.value)
1016
- when 0x2f # SRA A
1017
- sra8(@a)
1018
- when 0x30 # SWAP B
1019
- swap8(@b)
1020
- when 0x31 # SWAP C
1021
- swap8(@c)
1022
- when 0x32 # SWAP D
1023
- swap8(@d)
1024
- when 0x33 # SWAP E
1025
- swap8(@e)
1026
- when 0x34 # SWAP H
1027
- swap8(@h)
1028
- when 0x35 # SWAP L
1029
- swap8(@l)
1030
- when 0x36 # SWAP (HL)
1031
- reg = Register.new(name: 'HL', value: read_byte(hl))
1032
- swap8(reg)
1033
- write_byte(hl, reg.value)
1034
- when 0x37 # SWAP A
1035
- swap8(@a)
1036
- when 0x38 # SRL B
1037
- srl8(@b)
1038
- when 0x39 # SRL C
1039
- srl8(@c)
1040
- when 0x3a # SRL D
1041
- srl8(@d)
1042
- when 0x3b # SRL E
1043
- srl8(@e)
1044
- when 0x3c # SRL H
1045
- srl8(@h)
1046
- when 0x3d # SRL L
1047
- srl8(@l)
1048
- when 0x3e # SRL (HL)
1049
- reg = Register.new(name: 'HL', value: read_byte(hl))
1050
- srl8(reg)
1051
- write_byte(hl, reg.value)
1052
- when 0x3f # SRL A
1053
- srl8(@a)
1054
- when 0x40 # BIT 0, B
1055
- bit8(0, @b)
1056
- when 0x41 # BIT 0, C
1057
- bit8(0, @c)
1058
- when 0x42 # BIT 0, D
1059
- bit8(0, @d)
1060
- when 0x43 # BIT 0, E
1061
- bit8(0, @e)
1062
- when 0x44 # BIT 0, H
1063
- bit8(0, @h)
1064
- when 0x45 # BIT 0, L
1065
- bit8(0, @l)
1066
- when 0x46 # BIT 0, (HL)
1067
- bit8(0, Register.new(name: 'HL', value: read_byte(hl)))
1068
- when 0x47 # BIT 0, A
1069
- bit8(0, @a)
1070
- when 0x48 # BIT 1, B
1071
- bit8(1, @b)
1072
- when 0x49 # BIT 1, C
1073
- bit8(1, @c)
1074
- when 0x4a # BIT 1, D
1075
- bit8(1, @d)
1076
- when 0x4b # BIT 1, E
1077
- bit8(1, @e)
1078
- when 0x4c # BIT 1, H
1079
- bit8(1, @h)
1080
- when 0x4d # BIT 1, L
1081
- bit8(1, @l)
1082
- when 0x4e # BIT 1, (HL)
1083
- bit8(1, Register.new(name: 'HL', value: read_byte(hl)))
1084
- when 0x4f # BIT 1, A
1085
- bit8(1, @a)
1086
- when 0x50 # BIT 2, B
1087
- bit8(2, @b)
1088
- when 0x51 # BIT 2, C
1089
- bit8(2, @c)
1090
- when 0x52 # BIT 2, D
1091
- bit8(2, @d)
1092
- when 0x53 # BIT 2, E
1093
- bit8(2, @e)
1094
- when 0x54 # BIT 2, H
1095
- bit8(2, @h)
1096
- when 0x55 # BIT 2, L
1097
- bit8(2, @l)
1098
- when 0x56 # BIT 2, (HL)
1099
- bit8(2, Register.new(name: 'HL', value: read_byte(hl)))
1100
- when 0x57 # BIT 2, A
1101
- bit8(2, @a)
1102
- when 0x58 # BIT 3, B
1103
- bit8(3, @b)
1104
- when 0x59 # BIT 3, C
1105
- bit8(3, @c)
1106
- when 0x5a # BIT 3, D
1107
- bit8(3, @d)
1108
- when 0x5b # BIT 3, E
1109
- bit8(3, @e)
1110
- when 0x5c # BIT 3, H
1111
- bit8(3, @h)
1112
- when 0x5d # BIT 3, L
1113
- bit8(3, @l)
1114
- when 0x5e # BIT 3, (HL)
1115
- bit8(3, Register.new(name: 'HL', value: read_byte(hl)))
1116
- when 0x5f # BIT 3, A
1117
- bit8(3, @a)
1118
- when 0x60 # BIT 4, B
1119
- bit8(4, @b)
1120
- when 0x61 # BIT 4, C
1121
- bit8(4, @c)
1122
- when 0x62 # BIT 4, D
1123
- bit8(4, @d)
1124
- when 0x63 # BIT 4, E
1125
- bit8(4, @e)
1126
- when 0x64 # BIT 4, H
1127
- bit8(4, @h)
1128
- when 0x65 # BIT 4, L
1129
- bit8(4, @l)
1130
- when 0x66 # BIT 4, (HL)
1131
- bit8(4, Register.new(name: 'HL', value: read_byte(hl)))
1132
- when 0x67 # BIT 4, A
1133
- bit8(4, @a)
1134
- when 0x68 # BIT 5, B
1135
- bit8(5, @b)
1136
- when 0x69 # BIT 5, C
1137
- bit8(5, @c)
1138
- when 0x6a # BIT 5, D
1139
- bit8(5, @d)
1140
- when 0x6b # BIT 5, E
1141
- bit8(5, @e)
1142
- when 0x6c # BIT 5, H
1143
- bit8(5, @h)
1144
- when 0x6d # BIT 5, L
1145
- bit8(5, @l)
1146
- when 0x6e # BIT 5, (HL)
1147
- bit8(5, Register.new(name: 'HL', value: read_byte(hl)))
1148
- when 0x6f # BIT 5, A
1149
- bit8(5, @a)
1150
- when 0x70 # BIT 6, B
1151
- bit8(6, @b)
1152
- when 0x71 # BIT 6, C
1153
- bit8(6, @c)
1154
- when 0x72 # BIT 6, D
1155
- bit8(6, @d)
1156
- when 0x73 # BIT 6, E
1157
- bit8(6, @e)
1158
- when 0x74 # BIT 6, H
1159
- bit8(6, @h)
1160
- when 0x75 # BIT 6, L
1161
- bit8(6, @l)
1162
- when 0x76 # BIT 6, (HL)
1163
- bit8(6, Register.new(name: 'HL', value: read_byte(hl)))
1164
- when 0x77 # BIT 6, A
1165
- bit8(6, @a)
1166
- when 0x78 # BIT 7, B
1167
- bit8(7, @b)
1168
- when 0x79 # BIT 7, C
1169
- bit8(7, @c)
1170
- when 0x7a # BIT 7, D
1171
- bit8(7, @d)
1172
- when 0x7b # BIT 7, E
1173
- bit8(7, @e)
1174
- when 0x7c # BIT 7, H
1175
- bit8(7, @h)
1176
- when 0x7d # BIT 7, L
1177
- bit8(7, @l)
1178
- when 0x7e # BIT 7, (HL)
1179
- bit8(7, Register.new(name: 'HL', value: read_byte(hl)))
1180
- when 0x7f # BIT 7, A
1181
- bit8(7, @a)
1182
- when 0x80 # RES 0, B
1183
- res8(0, @b)
1184
- when 0x81 # RES 0, C
1185
- res8(0, @c)
1186
- when 0x82 # RES 0, D
1187
- res8(0, @d)
1188
- when 0x83 # RES 0, E
1189
- res8(0, @e)
1190
- when 0x84 # RES 0, H
1191
- res8(0, @h)
1192
- when 0x85 # RES 0, L
1193
- res8(0, @l)
1194
- when 0x86 # RES 0, (HL)
1195
- reg = Register.new(name: 'HL', value: read_byte(hl))
1196
- res8(0, reg)
1197
- write_byte(hl, reg.value)
1198
- when 0x87 # RES 0, A
1199
- res8(0, @a)
1200
- when 0x88 # RES 1, B
1201
- res8(1, @b)
1202
- when 0x89 # RES 1, C
1203
- res8(1, @c)
1204
- when 0x8a # RES 1, D
1205
- res8(1, @d)
1206
- when 0x8b # RES 1, E
1207
- res8(1, @e)
1208
- when 0x8c # RES 1, H
1209
- res8(1, @h)
1210
- when 0x8d # RES 1, L
1211
- res8(1, @l)
1212
- when 0x8e # RES 1, (HL)
1213
- reg = Register.new(name: 'HL', value: read_byte(hl))
1214
- res8(1, reg)
1215
- write_byte(hl, reg.value)
1216
- when 0x8f # RES 1, A
1217
- res8(1, @a)
1218
- when 0x90 # RES 2, B
1219
- res8(2, @b)
1220
- when 0x91 # RES 2, C
1221
- res8(2, @c)
1222
- when 0x92 # RES 2, D
1223
- res8(2, @d)
1224
- when 0x93 # RES 2, E
1225
- res8(2, @e)
1226
- when 0x94 # RES 2, H
1227
- res8(2, @h)
1228
- when 0x95 # RES 2, L
1229
- res8(2, @l)
1230
- when 0x96 # RES 2, (HL)
1231
- reg = Register.new(name: 'HL', value: read_byte(hl))
1232
- res8(2, reg)
1233
- write_byte(hl, reg.value)
1234
- when 0x97 # RES 2, A
1235
- res8(2, @a)
1236
- when 0x98 # RES 3, B
1237
- res8(3, @b)
1238
- when 0x99 # RES 3, C
1239
- res8(3, @c)
1240
- when 0x9a # RES 3, D
1241
- res8(3, @d)
1242
- when 0x9b # RES 3, E
1243
- res8(3, @e)
1244
- when 0x9c # RES 3, H
1245
- res8(3, @h)
1246
- when 0x9d # RES 3, L
1247
- res8(3, @l)
1248
- when 0x9e # RES 3, (HL)
1249
- reg = Register.new(name: 'HL', value: read_byte(hl))
1250
- res8(3, reg)
1251
- write_byte(hl, reg.value)
1252
- when 0x9f # RES 3, A
1253
- res8(3, @a)
1254
- when 0xa0 # RES 4, B
1255
- res8(4, @b)
1256
- when 0xa1 # RES 4, C
1257
- res8(4, @c)
1258
- when 0xa2 # RES 4, D
1259
- res8(4, @d)
1260
- when 0xa3 # RES 4, E
1261
- res8(4, @e)
1262
- when 0xa4 # RES 4, H
1263
- res8(4, @h)
1264
- when 0xa5 # RES 4, L
1265
- res8(4, @l)
1266
- when 0xa6 # RES 4, (HL)
1267
- reg = Register.new(name: 'HL', value: read_byte(hl))
1268
- res8(4, reg)
1269
- write_byte(hl, reg.value)
1270
- when 0xa7 # RES 4, A
1271
- res8(4, @a)
1272
- when 0xa8 # RES 5, B
1273
- res8(5, @b)
1274
- when 0xa9 # RES 5, C
1275
- res8(5, @c)
1276
- when 0xaa # RES 5, D
1277
- res8(5, @d)
1278
- when 0xab # RES 5, E
1279
- res8(5, @e)
1280
- when 0xac # RES 5, H
1281
- res8(5, @h)
1282
- when 0xad # RES 5, L
1283
- res8(5, @l)
1284
- when 0xae # RES 5, (HL)
1285
- reg = Register.new(name: 'HL', value: read_byte(hl))
1286
- res8(5, reg)
1287
- write_byte(hl, reg.value)
1288
- when 0xaf # RES 5, A
1289
- res8(5, @a)
1290
- when 0xb0 # RES 6, B
1291
- res8(6, @b)
1292
- when 0xb1 # RES 6, C
1293
- res8(6, @c)
1294
- when 0xb2 # RES 6, D
1295
- res8(6, @d)
1296
- when 0xb3 # RES 6, E
1297
- res8(6, @e)
1298
- when 0xb4 # RES 6, H
1299
- res8(6, @h)
1300
- when 0xb5 # RES 6, L
1301
- res8(6, @l)
1302
- when 0xb6 # RES 6, (HL)
1303
- reg = Register.new(name: 'HL', value: read_byte(hl))
1304
- res8(6, reg)
1305
- write_byte(hl, reg.value)
1306
- when 0xb7 # RES 6, A
1307
- res8(6, @a)
1308
- when 0xb8 # RES 7, B
1309
- res8(7, @b)
1310
- when 0xb9 # RES 7, C
1311
- res8(7, @c)
1312
- when 0xba # RES 7, D
1313
- res8(7, @d)
1314
- when 0xbb # RES 7, E
1315
- res8(7, @e)
1316
- when 0xbc # RES 7, H
1317
- res8(7, @h)
1318
- when 0xbd # RES 7, L
1319
- res8(7, @l)
1320
- when 0xbe # RES 7, (HL)
1321
- reg = Register.new(name: 'HL', value: read_byte(hl))
1322
- res8(7, reg)
1323
- write_byte(hl, reg.value)
1324
- when 0xbf # RES 7, A
1325
- res8(7, @a)
1326
- when 0xc0 # SET 0, B
1327
- set8(0, @b)
1328
- when 0xc1 # SET 0, C
1329
- set8(0, @c)
1330
- when 0xc2 # SET 0, D
1331
- set8(0, @d)
1332
- when 0xc3 # SET 0, E
1333
- set8(0, @e)
1334
- when 0xc4 # SET 0, H
1335
- set8(0, @h)
1336
- when 0xc5 # SET 0, L
1337
- set8(0, @l)
1338
- when 0xc6 # SET 0, (HL)
1339
- reg = Register.new(name: 'HL', value: read_byte(hl))
1340
- set8(0, reg)
1341
- write_byte(hl, reg.value)
1342
- when 0xc7 # SET 0, A
1343
- set8(0, @a)
1344
- when 0xc8 # SET 1, B
1345
- set8(1, @b)
1346
- when 0xc9 # SET 1, C
1347
- set8(1, @c)
1348
- when 0xca # SET 1, D
1349
- set8(1, @d)
1350
- when 0xcb # SET 1, E
1351
- set8(1, @e)
1352
- when 0xcc # SET 1, H
1353
- set8(1, @h)
1354
- when 0xcd # SET 1, L
1355
- set8(1, @l)
1356
- when 0xce # SET 1, (HL)
1357
- reg = Register.new(name: 'HL', value: read_byte(hl))
1358
- set8(1, reg)
1359
- write_byte(hl, reg.value)
1360
- when 0xcf # SET 1, A
1361
- set8(1, @a)
1362
- when 0xd0 # SET 2, B
1363
- set8(2, @b)
1364
- when 0xd1 # SET 2, C
1365
- set8(2, @c)
1366
- when 0xd2 # SET 2, D
1367
- set8(2, @d)
1368
- when 0xd3 # SET 2, E
1369
- set8(2, @e)
1370
- when 0xd4 # SET 2, H
1371
- set8(2, @h)
1372
- when 0xd5 # SET 2, L
1373
- set8(2, @l)
1374
- when 0xd6 # SET 2, (HL)
1375
- reg = Register.new(name: 'HL', value: read_byte(hl))
1376
- set8(2, reg)
1377
- write_byte(hl, reg.value)
1378
- when 0xd7 # SET 2, A
1379
- set8(2, @a)
1380
- when 0xd8 # SET 3, B
1381
- set8(3, @b)
1382
- when 0xd9 # SET 3, C
1383
- set8(3, @c)
1384
- when 0xda # SET 3, D
1385
- set8(3, @d)
1386
- when 0xdb # SET 3, E
1387
- set8(3, @e)
1388
- when 0xdc # SET 3, H
1389
- set8(3, @h)
1390
- when 0xdd # SET 3, L
1391
- set8(3, @l)
1392
- when 0xde # SET 3, (HL)
1393
- reg = Register.new(name: 'HL', value: read_byte(hl))
1394
- set8(3, reg)
1395
- write_byte(hl, reg.value)
1396
- when 0xdf # SET 3, A
1397
- set8(3, @a)
1398
- when 0xe0 # SET 4, B
1399
- set8(4, @b)
1400
- when 0xe1 # SET 4, C
1401
- set8(4, @c)
1402
- when 0xe2 # SET 4, D
1403
- set8(4, @d)
1404
- when 0xe3 # SET 4, E
1405
- set8(4, @e)
1406
- when 0xe4 # SET 4, H
1407
- set8(4, @h)
1408
- when 0xe5 # SET 4, L
1409
- set8(4, @l)
1410
- when 0xe6 # SET 4, (HL)
1411
- reg = Register.new(name: 'HL', value: read_byte(hl))
1412
- set8(4, reg)
1413
- write_byte(hl, reg.value)
1414
- when 0xe7 # SET 4, A
1415
- set8(4, @a)
1416
- when 0xe8 # SET 5, B
1417
- set8(5, @b)
1418
- when 0xe9 # SET 5, C
1419
- set8(5, @c)
1420
- when 0xea # SET 5, D
1421
- set8(5, @d)
1422
- when 0xeb # SET 5, E
1423
- set8(5, @e)
1424
- when 0xec # SET 5, H
1425
- set8(5, @h)
1426
- when 0xed # SET 5, L
1427
- set8(5, @l)
1428
- when 0xee # SET 5, (HL)
1429
- reg = Register.new(name: 'HL', value: read_byte(hl))
1430
- set8(5, reg)
1431
- write_byte(hl, reg.value)
1432
- when 0xef # SET 5, A
1433
- set8(5, @a)
1434
- when 0xf0 # SET 6, B
1435
- set8(6, @b)
1436
- when 0xf1 # SET 6, C
1437
- set8(6, @c)
1438
- when 0xf2 # SET 6, D
1439
- set8(6, @d)
1440
- when 0xf3 # SET 6, E
1441
- set8(6, @e)
1442
- when 0xf4 # SET 6, H
1443
- set8(6, @h)
1444
- when 0xf5 # SET 6, L
1445
- set8(6, @l)
1446
- when 0xf6 # SET 6, (HL)
1447
- reg = Register.new(name: 'HL', value: read_byte(hl))
1448
- set8(6, reg)
1449
- write_byte(hl, reg.value)
1450
- when 0xf7 # SET 6, A
1451
- set8(6, @a)
1452
- when 0xf8 # SET 7, B
1453
- set8(7, @b)
1454
- when 0xf9 # SET 7, C
1455
- set8(7, @c)
1456
- when 0xfa # SET 7, D
1457
- set8(7, @d)
1458
- when 0xfb # SET 7, E
1459
- set8(7, @e)
1460
- when 0xfc then set8(7, @h)
1461
- when 0xfd then set8(7, @l)
1462
- when 0xfe # SET 7, (HL)
1463
- reg = Register.new(name: 'HL', value: read_byte(hl))
1464
- set8(7, reg)
1465
- write_byte(hl, reg.value)
1466
- when 0xff then set8(7, @a) # SET 7, A
301
+ when 0x00 then rlc8({ type: :register8, value: :b })
302
+ when 0x01 then rlc8({ type: :register8, value: :c })
303
+ when 0x02 then rlc8({ type: :register8, value: :d })
304
+ when 0x03 then rlc8({ type: :register8, value: :e })
305
+ when 0x04 then rlc8({ type: :register8, value: :h })
306
+ when 0x05 then rlc8({ type: :register8, value: :l })
307
+ when 0x06 then rlc8({ type: :indirect, value: :hl })
308
+ when 0x07 then rlc8({ type: :register8, value: :a })
309
+ when 0x08 then rrc8({ type: :register8, value: :b })
310
+ when 0x09 then rrc8({ type: :register8, value: :c })
311
+ when 0x0a then rrc8({ type: :register8, value: :d })
312
+ when 0x0b then rrc8({ type: :register8, value: :e })
313
+ when 0x0c then rrc8({ type: :register8, value: :h })
314
+ when 0x0d then rrc8({ type: :register8, value: :l })
315
+ when 0x0e then rrc8({ type: :indirect, value: :hl })
316
+ when 0x0f then rrc8({ type: :register8, value: :a })
317
+ when 0x10 then rl8({ type: :register8, value: :b })
318
+ when 0x11 then rl8({ type: :register8, value: :c })
319
+ when 0x12 then rl8({ type: :register8, value: :d })
320
+ when 0x13 then rl8({ type: :register8, value: :e })
321
+ when 0x14 then rl8({ type: :register8, value: :h })
322
+ when 0x15 then rl8({ type: :register8, value: :l })
323
+ when 0x16 then rl8({ type: :indirect, value: :hl })
324
+ when 0x17 then rl8({ type: :register8, value: :a })
325
+ when 0x18 then rr8({ type: :register8, value: :b })
326
+ when 0x19 then rr8({ type: :register8, value: :c })
327
+ when 0x1a then rr8({ type: :register8, value: :d })
328
+ when 0x1b then rr8({ type: :register8, value: :e })
329
+ when 0x1c then rr8({ type: :register8, value: :h })
330
+ when 0x1d then rr8({ type: :register8, value: :l })
331
+ when 0x1e then rr8({ type: :indirect, value: :hl })
332
+ when 0x1f then rr8({ type: :register8, value: :a })
333
+ when 0x20 then sla8({ type: :register8, value: :b })
334
+ when 0x21 then sla8({ type: :register8, value: :c })
335
+ when 0x22 then sla8({ type: :register8, value: :d })
336
+ when 0x23 then sla8({ type: :register8, value: :e })
337
+ when 0x24 then sla8({ type: :register8, value: :h })
338
+ when 0x25 then sla8({ type: :register8, value: :l })
339
+ when 0x26 then sla8({ type: :indirect, value: :hl })
340
+ when 0x27 then sla8({ type: :register8, value: :a })
341
+ when 0x28 then sra8({ type: :register8, value: :b })
342
+ when 0x29 then sra8({ type: :register8, value: :c })
343
+ when 0x2a then sra8({ type: :register8, value: :d })
344
+ when 0x2b then sra8({ type: :register8, value: :e })
345
+ when 0x2c then sra8({ type: :register8, value: :h })
346
+ when 0x2d then sra8({ type: :register8, value: :l })
347
+ when 0x2e then sra8({ type: :indirect, value: :hl })
348
+ when 0x2f then sra8({ type: :register8, value: :a })
349
+ when 0x30 then swap8({ type: :register8, value: :b })
350
+ when 0x31 then swap8({ type: :register8, value: :c })
351
+ when 0x32 then swap8({ type: :register8, value: :d })
352
+ when 0x33 then swap8({ type: :register8, value: :e })
353
+ when 0x34 then swap8({ type: :register8, value: :h })
354
+ when 0x35 then swap8({ type: :register8, value: :l })
355
+ when 0x36 then swap8({ type: :indirect, value: :hl })
356
+ when 0x37 then swap8({ type: :register8, value: :a })
357
+ when 0x38 then srl8({ type: :register8, value: :b })
358
+ when 0x39 then srl8({ type: :register8, value: :c })
359
+ when 0x3a then srl8({ type: :register8, value: :d })
360
+ when 0x3b then srl8({ type: :register8, value: :e })
361
+ when 0x3c then srl8({ type: :register8, value: :h })
362
+ when 0x3d then srl8({ type: :register8, value: :l })
363
+ when 0x3e then srl8({ type: :indirect, value: :hl })
364
+ when 0x3f then srl8({ type: :register8, value: :a })
365
+ when 0x40 then bit8(0, { type: :register8, value: :b })
366
+ when 0x41 then bit8(0, { type: :register8, value: :c })
367
+ when 0x42 then bit8(0, { type: :register8, value: :d })
368
+ when 0x43 then bit8(0, { type: :register8, value: :e })
369
+ when 0x44 then bit8(0, { type: :register8, value: :h })
370
+ when 0x45 then bit8(0, { type: :register8, value: :l })
371
+ when 0x46 then bit8(0, { type: :indirect, value: :hl })
372
+ when 0x47 then bit8(0, { type: :register8, value: :a })
373
+ when 0x48 then bit8(1, { type: :register8, value: :b })
374
+ when 0x49 then bit8(1, { type: :register8, value: :c })
375
+ when 0x4a then bit8(1, { type: :register8, value: :d })
376
+ when 0x4b then bit8(1, { type: :register8, value: :e })
377
+ when 0x4c then bit8(1, { type: :register8, value: :h })
378
+ when 0x4d then bit8(1, { type: :register8, value: :l })
379
+ when 0x4e then bit8(1, { type: :indirect, value: :hl })
380
+ when 0x4f then bit8(1, { type: :register8, value: :a })
381
+ when 0x50 then bit8(2, { type: :register8, value: :b })
382
+ when 0x51 then bit8(2, { type: :register8, value: :c })
383
+ when 0x52 then bit8(2, { type: :register8, value: :d })
384
+ when 0x53 then bit8(2, { type: :register8, value: :e })
385
+ when 0x54 then bit8(2, { type: :register8, value: :h })
386
+ when 0x55 then bit8(2, { type: :register8, value: :l })
387
+ when 0x56 then bit8(2, { type: :indirect, value: :hl })
388
+ when 0x57 then bit8(2, { type: :register8, value: :a })
389
+ when 0x58 then bit8(3, { type: :register8, value: :b })
390
+ when 0x59 then bit8(3, { type: :register8, value: :c })
391
+ when 0x5a then bit8(3, { type: :register8, value: :d })
392
+ when 0x5b then bit8(3, { type: :register8, value: :e })
393
+ when 0x5c then bit8(3, { type: :register8, value: :h })
394
+ when 0x5d then bit8(3, { type: :register8, value: :l })
395
+ when 0x5e then bit8(3, { type: :indirect, value: :hl })
396
+ when 0x5f then bit8(3, { type: :register8, value: :a })
397
+ when 0x60 then bit8(4, { type: :register8, value: :b })
398
+ when 0x61 then bit8(4, { type: :register8, value: :c })
399
+ when 0x62 then bit8(4, { type: :register8, value: :d })
400
+ when 0x63 then bit8(4, { type: :register8, value: :e })
401
+ when 0x64 then bit8(4, { type: :register8, value: :h })
402
+ when 0x65 then bit8(4, { type: :register8, value: :l })
403
+ when 0x66 then bit8(4, { type: :indirect, value: :hl })
404
+ when 0x67 then bit8(4, { type: :register8, value: :a })
405
+ when 0x68 then bit8(5, { type: :register8, value: :b })
406
+ when 0x69 then bit8(5, { type: :register8, value: :c })
407
+ when 0x6a then bit8(5, { type: :register8, value: :d })
408
+ when 0x6b then bit8(5, { type: :register8, value: :e })
409
+ when 0x6c then bit8(5, { type: :register8, value: :h })
410
+ when 0x6d then bit8(5, { type: :register8, value: :l })
411
+ when 0x6e then bit8(5, { type: :indirect, value: :hl })
412
+ when 0x6f then bit8(5, { type: :register8, value: :a })
413
+ when 0x70 then bit8(6, { type: :register8, value: :b })
414
+ when 0x71 then bit8(6, { type: :register8, value: :c })
415
+ when 0x72 then bit8(6, { type: :register8, value: :d })
416
+ when 0x73 then bit8(6, { type: :register8, value: :e })
417
+ when 0x74 then bit8(6, { type: :register8, value: :h })
418
+ when 0x75 then bit8(6, { type: :register8, value: :l })
419
+ when 0x76 then bit8(6, { type: :indirect, value: :hl })
420
+ when 0x77 then bit8(6, { type: :register8, value: :a })
421
+ when 0x78 then bit8(7, { type: :register8, value: :b })
422
+ when 0x79 then bit8(7, { type: :register8, value: :c })
423
+ when 0x7a then bit8(7, { type: :register8, value: :d })
424
+ when 0x7b then bit8(7, { type: :register8, value: :e })
425
+ when 0x7c then bit8(7, { type: :register8, value: :h })
426
+ when 0x7d then bit8(7, { type: :register8, value: :l })
427
+ when 0x7e then bit8(7, { type: :indirect, value: :hl })
428
+ when 0x7f then bit8(7, { type: :register8, value: :a })
429
+ when 0x80 then res8(0, { type: :register8, value: :b })
430
+ when 0x81 then res8(0, { type: :register8, value: :c })
431
+ when 0x82 then res8(0, { type: :register8, value: :d })
432
+ when 0x83 then res8(0, { type: :register8, value: :e })
433
+ when 0x84 then res8(0, { type: :register8, value: :h })
434
+ when 0x85 then res8(0, { type: :register8, value: :l })
435
+ when 0x86 then res8(0, { type: :indirect, value: :hl })
436
+ when 0x87 then res8(0, { type: :register8, value: :a })
437
+ when 0x88 then res8(1, { type: :register8, value: :b })
438
+ when 0x89 then res8(1, { type: :register8, value: :c })
439
+ when 0x8a then res8(1, { type: :register8, value: :d })
440
+ when 0x8b then res8(1, { type: :register8, value: :e })
441
+ when 0x8c then res8(1, { type: :register8, value: :h })
442
+ when 0x8d then res8(1, { type: :register8, value: :l })
443
+ when 0x8e then res8(1, { type: :indirect, value: :hl })
444
+ when 0x8f then res8(1, { type: :register8, value: :a })
445
+ when 0x90 then res8(2, { type: :register8, value: :b })
446
+ when 0x91 then res8(2, { type: :register8, value: :c })
447
+ when 0x92 then res8(2, { type: :register8, value: :d })
448
+ when 0x93 then res8(2, { type: :register8, value: :e })
449
+ when 0x94 then res8(2, { type: :register8, value: :h })
450
+ when 0x95 then res8(2, { type: :register8, value: :l })
451
+ when 0x96 then res8(2, { type: :indirect, value: :hl })
452
+ when 0x97 then res8(2, { type: :register8, value: :a })
453
+ when 0x98 then res8(3, { type: :register8, value: :b })
454
+ when 0x99 then res8(3, { type: :register8, value: :c })
455
+ when 0x9a then res8(3, { type: :register8, value: :d })
456
+ when 0x9b then res8(3, { type: :register8, value: :e })
457
+ when 0x9c then res8(3, { type: :register8, value: :h })
458
+ when 0x9d then res8(3, { type: :register8, value: :l })
459
+ when 0x9e then res8(3, { type: :indirect, value: :hl })
460
+ when 0x9f then res8(3, { type: :register8, value: :a })
461
+ when 0xa0 then res8(4, { type: :register8, value: :b })
462
+ when 0xa1 then res8(4, { type: :register8, value: :c })
463
+ when 0xa2 then res8(4, { type: :register8, value: :d })
464
+ when 0xa3 then res8(4, { type: :register8, value: :e })
465
+ when 0xa4 then res8(4, { type: :register8, value: :h })
466
+ when 0xa5 then res8(4, { type: :register8, value: :l })
467
+ when 0xa6 then res8(4, { type: :indirect, value: :hl })
468
+ when 0xa7 then res8(4, { type: :register8, value: :a })
469
+ when 0xa8 then res8(5, { type: :register8, value: :b })
470
+ when 0xa9 then res8(5, { type: :register8, value: :c })
471
+ when 0xaa then res8(5, { type: :register8, value: :d })
472
+ when 0xab then res8(5, { type: :register8, value: :e })
473
+ when 0xac then res8(5, { type: :register8, value: :h })
474
+ when 0xad then res8(5, { type: :register8, value: :l })
475
+ when 0xae then res8(5, { type: :indirect, value: :hl })
476
+ when 0xaf then res8(5, { type: :register8, value: :a })
477
+ when 0xb0 then res8(6, { type: :register8, value: :b })
478
+ when 0xb1 then res8(6, { type: :register8, value: :c })
479
+ when 0xb2 then res8(6, { type: :register8, value: :d })
480
+ when 0xb3 then res8(6, { type: :register8, value: :e })
481
+ when 0xb4 then res8(6, { type: :register8, value: :h })
482
+ when 0xb5 then res8(6, { type: :register8, value: :l })
483
+ when 0xb6 then res8(6, { type: :indirect, value: :hl })
484
+ when 0xb7 then res8(6, { type: :register8, value: :a })
485
+ when 0xb8 then res8(7, { type: :register8, value: :b })
486
+ when 0xb9 then res8(7, { type: :register8, value: :c })
487
+ when 0xba then res8(7, { type: :register8, value: :d })
488
+ when 0xbb then res8(7, { type: :register8, value: :e })
489
+ when 0xbc then res8(7, { type: :register8, value: :h })
490
+ when 0xbd then res8(7, { type: :register8, value: :l })
491
+ when 0xbe then res8(7, { type: :indirect, value: :hl })
492
+ when 0xbf then res8(7, { type: :register8, value: :a })
493
+ when 0xc0 then set8(0, { type: :register8, value: :b })
494
+ when 0xc1 then set8(0, { type: :register8, value: :c })
495
+ when 0xc2 then set8(0, { type: :register8, value: :d })
496
+ when 0xc3 then set8(0, { type: :register8, value: :e })
497
+ when 0xc4 then set8(0, { type: :register8, value: :h })
498
+ when 0xc5 then set8(0, { type: :register8, value: :l })
499
+ when 0xc6 then set8(0, { type: :indirect, value: :hl })
500
+ when 0xc7 then set8(0, { type: :register8, value: :a })
501
+ when 0xc8 then set8(1, { type: :register8, value: :b })
502
+ when 0xc9 then set8(1, { type: :register8, value: :c })
503
+ when 0xca then set8(1, { type: :register8, value: :d })
504
+ when 0xcb then set8(1, { type: :register8, value: :e })
505
+ when 0xcc then set8(1, { type: :register8, value: :h })
506
+ when 0xcd then set8(1, { type: :register8, value: :l })
507
+ when 0xce then set8(1, { type: :indirect, value: :hl })
508
+ when 0xcf then set8(1, { type: :register8, value: :a })
509
+ when 0xd0 then set8(2, { type: :register8, value: :b })
510
+ when 0xd1 then set8(2, { type: :register8, value: :c })
511
+ when 0xd2 then set8(2, { type: :register8, value: :d })
512
+ when 0xd3 then set8(2, { type: :register8, value: :e })
513
+ when 0xd4 then set8(2, { type: :register8, value: :h })
514
+ when 0xd5 then set8(2, { type: :register8, value: :l })
515
+ when 0xd6 then set8(2, { type: :indirect, value: :hl })
516
+ when 0xd7 then set8(2, { type: :register8, value: :a })
517
+ when 0xd8 then set8(3, { type: :register8, value: :b })
518
+ when 0xd9 then set8(3, { type: :register8, value: :c })
519
+ when 0xda then set8(3, { type: :register8, value: :d })
520
+ when 0xdb then set8(3, { type: :register8, value: :e })
521
+ when 0xdc then set8(3, { type: :register8, value: :h })
522
+ when 0xdd then set8(3, { type: :register8, value: :l })
523
+ when 0xde then set8(3, { type: :indirect, value: :hl })
524
+ when 0xdf then set8(3, { type: :register8, value: :a })
525
+ when 0xe0 then set8(4, { type: :register8, value: :b })
526
+ when 0xe1 then set8(4, { type: :register8, value: :c })
527
+ when 0xe2 then set8(4, { type: :register8, value: :d })
528
+ when 0xe3 then set8(4, { type: :register8, value: :e })
529
+ when 0xe4 then set8(4, { type: :register8, value: :h })
530
+ when 0xe5 then set8(4, { type: :register8, value: :l })
531
+ when 0xe6 then set8(4, { type: :indirect, value: :hl })
532
+ when 0xe7 then set8(4, { type: :register8, value: :a })
533
+ when 0xe8 then set8(5, { type: :register8, value: :b })
534
+ when 0xe9 then set8(5, { type: :register8, value: :c })
535
+ when 0xea then set8(5, { type: :register8, value: :d })
536
+ when 0xeb then set8(5, { type: :register8, value: :e })
537
+ when 0xec then set8(5, { type: :register8, value: :h })
538
+ when 0xed then set8(5, { type: :register8, value: :l })
539
+ when 0xee then set8(5, { type: :indirect, value: :hl })
540
+ when 0xef then set8(5, { type: :register8, value: :a })
541
+ when 0xf0 then set8(6, { type: :register8, value: :b })
542
+ when 0xf1 then set8(6, { type: :register8, value: :c })
543
+ when 0xf2 then set8(6, { type: :register8, value: :d })
544
+ when 0xf3 then set8(6, { type: :register8, value: :e })
545
+ when 0xf4 then set8(6, { type: :register8, value: :h })
546
+ when 0xf5 then set8(6, { type: :register8, value: :l })
547
+ when 0xf6 then set8(6, { type: :indirect, value: :hl })
548
+ when 0xf7 then set8(6, { type: :register8, value: :a })
549
+ when 0xf8 then set8(7, { type: :register8, value: :b })
550
+ when 0xf9 then set8(7, { type: :register8, value: :c })
551
+ when 0xfa then set8(7, { type: :register8, value: :d })
552
+ when 0xfb then set8(7, { type: :register8, value: :e })
553
+ when 0xfc then set8(7, { type: :register8, value: :h })
554
+ when 0xfd then set8(7, { type: :register8, value: :l })
555
+ when 0xfe then set8(7, { type: :indirect, value: :hl })
556
+ when 0xff then set8(7, { type: :register8, value: :a })
1467
557
  else
1468
558
  raise "unknown opcode: 0xcb 0x#{'%02x' % opcode}"
1469
559
  end
1470
560
  else
1471
561
  raise "unknown opcode: 0x#{'%02x' % opcode}"
1472
562
  end
1473
-
1474
- @sp &= 0xffff
1475
-
1476
- opcode_kind = cbprefixed ? 'cbprefixed' : 'unprefixed'
1477
- opcode_str = "0x#{'%02X' % opcode}"
1478
- cycles = @opcodes[opcode_kind][opcode_str]['cycles']
1479
-
1480
- branched ? cycles.max : cycles.min
1481
563
  end
1482
564
 
1483
565
  private
@@ -1511,24 +593,27 @@ module Rubyboy
1511
593
  end
1512
594
 
1513
595
  def print_log(opcode)
1514
- puts "OP: 0x#{'%02x' % opcode}, PC: 0x#{'%04x' % @pc}, SP: 0x#{'%04x' % @sp}, A: 0x#{'%02x' % @a.value}, B: 0x#{'%02x' % @b.value}, C: 0x#{'%02x' % @c.value}, D: 0x#{'%02x' % @d.value}, E: 0x#{'%02x' % @e.value}, H: 0x#{'%02x' % @h.value}, L: 0x#{'%02x' % @l.value}, F: 0x#{'%02x' % @f.value}"
596
+ puts "PC: 0x#{'%04x' % @pc}, Opcode: 0x#{'%02x' % opcode}, AF: 0x#{'%04x' % @registers.read16(:af)}, BC: 0x#{'%04x' % @registers.read16(:bc)}, HL: 0x#{'%04x' % @registers.read16(:hl)}, SP: 0x#{'%04x' % @sp}"
1515
597
  end
1516
598
 
1517
599
  def flags
600
+ f_value = @registers.read8(:f)
1518
601
  {
1519
- z: @f.value[7] == 1,
1520
- n: @f.value[6] == 1,
1521
- h: @f.value[5] == 1,
1522
- c: @f.value[4] == 1
602
+ z: f_value[7] == 1,
603
+ n: f_value[6] == 1,
604
+ h: f_value[5] == 1,
605
+ c: f_value[4] == 1
1523
606
  }
1524
607
  end
1525
608
 
1526
609
  def update_flags(z: flags[:z], n: flags[:n], h: flags[:h], c: flags[:c])
1527
- @f.value = 0x00
1528
- @f.value |= 0x80 if z
1529
- @f.value |= 0x40 if n
1530
- @f.value |= 0x20 if h
1531
- @f.value |= 0x10 if c
610
+ f_value = 0x00
611
+ f_value |= 0x80 if z
612
+ f_value |= 0x40 if n
613
+ f_value |= 0x20 if h
614
+ f_value |= 0x10 if c
615
+
616
+ @registers.write8(:f, f_value)
1532
617
  end
1533
618
 
1534
619
  def bool_to_integer(bool)
@@ -1543,205 +628,635 @@ module Rubyboy
1543
628
  @pc += byte
1544
629
  end
1545
630
 
1546
- def convert_to_twos_complement(byte)
631
+ def to_signed_byte(byte)
1547
632
  byte &= 0xff
1548
633
  byte > 127 ? byte - 256 : byte
1549
634
  end
1550
635
 
1551
- def ld8(x, y)
1552
- x.value = y.value
636
+ def rlca
637
+ a_value = @registers.read8(:a)
638
+ a_value = ((a_value << 1) | (a_value >> 7)) & 0xff
639
+ @registers.write8(:a, a_value)
640
+ update_flags(
641
+ z: false,
642
+ n: false,
643
+ h: false,
644
+ c: a_value[0] == 1
645
+ )
646
+
647
+ 4
648
+ end
649
+
650
+ def rrca
651
+ a_value = @registers.read8(:a)
652
+ a_value = ((a_value >> 1) | (a_value << 7)) & 0xff
653
+ @registers.write8(:a, a_value)
654
+ update_flags(
655
+ z: false,
656
+ n: false,
657
+ h: false,
658
+ c: a_value[7] == 1
659
+ )
660
+
661
+ 4
662
+ end
663
+
664
+ def rra
665
+ a_value = @registers.read8(:a)
666
+ cflag = a_value[0] == 1
667
+ a_value = ((a_value >> 1) | (bool_to_integer(flags[:c]) << 7)) & 0xff
668
+ @registers.write8(:a, a_value)
669
+ update_flags(
670
+ z: false,
671
+ n: false,
672
+ h: false,
673
+ c: cflag
674
+ )
675
+
676
+ 4
677
+ end
678
+
679
+ def rla
680
+ a_value = @registers.read8(:a)
681
+ cflag = a_value[7] == 1
682
+ a_value = ((a_value << 1) | bool_to_integer(flags[:c])) & 0xff
683
+ @registers.write8(:a, a_value)
684
+ update_flags(
685
+ z: false,
686
+ n: false,
687
+ h: false,
688
+ c: cflag
689
+ )
690
+
691
+ 4
692
+ end
693
+
694
+ def daa
695
+ a_value = @registers.read8(:a)
696
+ if flags[:n]
697
+ a_value -= 0x06 if flags[:h]
698
+ a_value -= 0x60 if flags[:c]
699
+ else
700
+ if flags[:c] || a_value > 0x99
701
+ a_value += 0x60
702
+ update_flags(c: true)
703
+ end
704
+ a_value += 0x06 if flags[:h] || (a_value & 0x0f) > 0x09
705
+ end
706
+
707
+ @registers.write8(:a, a_value)
708
+ update_flags(
709
+ z: @registers.read8(:a) == 0,
710
+ h: false
711
+ )
712
+
713
+ 4
714
+ end
715
+
716
+ def cpl
717
+ @registers.write8(:a, ~@registers.read8(:a))
718
+ update_flags(
719
+ n: true,
720
+ h: true
721
+ )
722
+
723
+ 4
1553
724
  end
1554
725
 
1555
- def add8(x, y)
1556
- hflag = (x.value & 0x0f) + (y.value & 0x0f) > 0x0f
1557
- cflag = x.value + y.value > 0xff
1558
- x.value += y.value
726
+ def scf
1559
727
  update_flags(
1560
- z: x.value.zero?,
728
+ n: false,
729
+ h: false,
730
+ c: true
731
+ )
732
+
733
+ 4
734
+ end
735
+
736
+ def ccf
737
+ update_flags(
738
+ n: false,
739
+ h: false,
740
+ c: !flags[:c]
741
+ )
742
+
743
+ 4
744
+ end
745
+
746
+ def inc8(x)
747
+ value = (get_value(x) + 1) & 0xff
748
+ set_value(x, value)
749
+ update_flags(
750
+ z: value == 0,
751
+ n: false,
752
+ h: (value & 0x0f) == 0
753
+ )
754
+
755
+ x[:type] == :register8 ? 4 : 12
756
+ end
757
+
758
+ def inc16(x)
759
+ set_value(x, get_value(x) + 1)
760
+
761
+ 8
762
+ end
763
+
764
+ def dec8(x)
765
+ value = (get_value(x) - 1) & 0xff
766
+ set_value(x, value)
767
+ update_flags(
768
+ z: value == 0,
769
+ n: true,
770
+ h: (value & 0x0f) == 0x0f
771
+ )
772
+
773
+ x[:type] == :register8 ? 4 : 12
774
+ end
775
+
776
+ def dec16(x)
777
+ set_value(x, get_value(x) - 1)
778
+
779
+ 8
780
+ end
781
+
782
+ def add8(x)
783
+ a_value = @registers.read8(:a)
784
+ x_value = get_value(x)
785
+
786
+ hflag = (a_value & 0x0f) + (x_value & 0x0f) > 0x0f
787
+ cflag = a_value + x_value > 0xff
788
+
789
+ a_value += x_value
790
+ @registers.write8(:a, a_value)
791
+ update_flags(
792
+ z: @registers.read8(:a) == 0,
1561
793
  n: false,
1562
794
  h: hflag,
1563
795
  c: cflag
1564
796
  )
797
+
798
+ x[:type] == :register8 ? 4 : 8
1565
799
  end
1566
800
 
1567
- def adc8(x, y)
1568
- c_value = bool_to_integer(flags[:c])
1569
- hflag = (x.value & 0x0f) + (y.value & 0x0f) + c_value > 0x0f
1570
- cflag = x.value + y.value + c_value > 0xff
1571
- x.value += y.value + c_value
801
+ def add16(x, y)
802
+ x_value = get_value(x)
803
+ y_value = get_value(y)
804
+
805
+ hflag = (x_value & 0x0fff) + (y_value & 0x0fff) > 0x0fff
806
+ cflag = x_value + y_value > 0xffff
807
+
808
+ set_value(x, x_value + y_value)
809
+ update_flags(
810
+ n: false,
811
+ h: hflag,
812
+ c: cflag
813
+ )
814
+
815
+ 8
816
+ end
817
+
818
+ def add_sp_r8
819
+ byte = to_signed_byte(read_byte_and_advance_pc)
820
+
821
+ hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
822
+ cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
823
+
824
+ @sp += byte
825
+ @sp &= 0xffff
1572
826
  update_flags(
1573
- z: x.value.zero?,
827
+ z: false,
1574
828
  n: false,
1575
829
  h: hflag,
1576
830
  c: cflag
1577
831
  )
832
+
833
+ 16
1578
834
  end
1579
835
 
1580
836
  def sub8(x)
1581
- hflag = (x.value & 0x0f) > (@a.value & 0x0f)
1582
- cflag = x.value > @a.value
1583
- @a.value -= x.value
837
+ a_value = @registers.read8(:a)
838
+ x_value = get_value(x)
839
+
840
+ hflag = (x_value & 0x0f) > (a_value & 0x0f)
841
+ cflag = x_value > a_value
842
+ a_value -= x_value
843
+ @registers.write8(:a, a_value)
1584
844
  update_flags(
1585
- z: @a.value.zero?,
845
+ z: a_value == 0,
1586
846
  n: true,
1587
847
  h: hflag,
1588
848
  c: cflag
1589
849
  )
850
+
851
+ x[:type] == :register8 ? 4 : 8
852
+ end
853
+
854
+ def adc8(x)
855
+ a_value = @registers.read8(:a)
856
+ x_value = get_value(x)
857
+ c_value = bool_to_integer(flags[:c])
858
+
859
+ hflag = (a_value & 0x0f) + (x_value & 0x0f) + c_value > 0x0f
860
+ cflag = a_value + x_value + c_value > 0xff
861
+ a_value += x_value + c_value
862
+ @registers.write8(:a, a_value)
863
+ update_flags(
864
+ z: @registers.read8(:a) == 0,
865
+ n: false,
866
+ h: hflag,
867
+ c: cflag
868
+ )
869
+
870
+ x[:type] == :register8 ? 4 : 8
1590
871
  end
1591
872
 
1592
873
  def sbc8(x)
874
+ a_value = @registers.read8(:a)
875
+ x_value = get_value(x)
1593
876
  c_value = bool_to_integer(flags[:c])
1594
- hflag = (x.value & 0x0f) + c_value > (@a.value & 0x0f)
1595
- cflag = x.value + c_value > @a.value
1596
- @a.value -= x.value + c_value
877
+
878
+ hflag = (x_value & 0x0f) + c_value > (a_value & 0x0f)
879
+ cflag = x_value + c_value > a_value
880
+ a_value -= x_value + c_value
881
+ @registers.write8(:a, a_value)
1597
882
  update_flags(
1598
- z: @a.value.zero?,
883
+ z: @registers.read8(:a) == 0,
1599
884
  n: true,
1600
885
  h: hflag,
1601
886
  c: cflag
1602
887
  )
888
+
889
+ x[:type] == :register8 ? 4 : 8
1603
890
  end
1604
891
 
1605
892
  def and8(x)
1606
- @a.value &= x.value
893
+ a_value = @registers.read8(:a) & get_value(x)
894
+ @registers.write8(:a, a_value)
1607
895
  update_flags(
1608
- z: @a.value.zero?,
896
+ z: a_value == 0,
1609
897
  n: false,
1610
898
  h: true,
1611
899
  c: false
1612
900
  )
901
+
902
+ x[:type] == :register8 ? 4 : 8
1613
903
  end
1614
904
 
1615
905
  def or8(x)
1616
- @a.value |= x.value
906
+ a_value = @registers.read8(:a) | get_value(x)
907
+ @registers.write8(:a, a_value)
1617
908
  update_flags(
1618
- z: @a.value.zero?,
909
+ z: a_value == 0,
1619
910
  n: false,
1620
911
  h: false,
1621
912
  c: false
1622
913
  )
914
+
915
+ x[:type] == :register8 ? 4 : 8
1623
916
  end
1624
917
 
1625
918
  def xor8(x)
1626
- @a.value ^= x.value
919
+ a_value = @registers.read8(:a) ^ get_value(x)
920
+ @registers.write8(:a, a_value)
1627
921
  update_flags(
1628
- z: @a.value.zero?,
922
+ z: a_value == 0,
1629
923
  n: false,
1630
924
  h: false,
1631
925
  c: false
1632
926
  )
927
+
928
+ x[:type] == :register8 ? 4 : 8
929
+ end
930
+
931
+ def push16(register16)
932
+ value = @registers.read16(register16)
933
+ @sp -= 2
934
+ write_word(@sp, value)
935
+
936
+ 16
937
+ end
938
+
939
+ def pop16(register16)
940
+ @registers.write16(register16, read_word(@sp))
941
+ @sp += 2
942
+
943
+ 12
944
+ end
945
+
946
+ def halt
947
+ @halted = true
948
+
949
+ 4
950
+ end
951
+
952
+ def ld8(x, y)
953
+ value = get_value(y)
954
+ set_value(x, value)
955
+
956
+ return 4 if x[:type] == :register8 && y[:type] == :register8
957
+ return 12 if x[:type] == :indirect && y[:type] == :immediate8
958
+ return 12 if x[:type] == :ff00 || y[:type] == :ff00
959
+ return 16 if x[:type] == :direct8 || y[:type] == :direct8
960
+
961
+ 8
962
+ end
963
+
964
+ def ld16(x, y)
965
+ value = get_value(y)
966
+ set_value(x, value)
967
+
968
+ return 8 if y[:type] == :register16
969
+ return 20 if y[:type] == :sp
970
+
971
+ 12
972
+ end
973
+
974
+ def ld_hl_sp_r8
975
+ byte = to_signed_byte(read_byte_and_advance_pc)
976
+
977
+ hflag = (@sp & 0x0f) + (byte & 0x0f) > 0x0f
978
+ cflag = (@sp & 0xff) + (byte & 0xff) > 0xff
979
+ @registers.write16(:hl, @sp + byte)
980
+ update_flags(
981
+ z: false,
982
+ n: false,
983
+ h: hflag,
984
+ c: cflag
985
+ )
986
+
987
+ 12
988
+ end
989
+
990
+ def ei
991
+ @ime_delay = true
992
+
993
+ 4
994
+ end
995
+
996
+ def di
997
+ @ime_delay = false
998
+ @ime = false
999
+
1000
+ 4
1633
1001
  end
1634
1002
 
1635
1003
  def cp8(x)
1636
- hflag = (x.value & 0x0f) > (@a.value & 0x0f)
1637
- cflag = x.value > @a.value
1004
+ a_value = @registers.read8(:a)
1005
+ x_value = get_value(x)
1006
+
1007
+ hflag = (x_value & 0x0f) > (a_value & 0x0f)
1008
+ cflag = x_value > a_value
1638
1009
  update_flags(
1639
- z: @a.value == x.value,
1010
+ z: a_value == x_value,
1640
1011
  n: true,
1641
1012
  h: hflag,
1642
1013
  c: cflag
1643
1014
  )
1015
+
1016
+ x[:type] == :register8 ? 4 : 8
1017
+ end
1018
+
1019
+ def rst(addr)
1020
+ @sp -= 2
1021
+ write_word(@sp, @pc)
1022
+ @pc = addr
1023
+
1024
+ 16
1025
+ end
1026
+
1027
+ def jr(condition: true)
1028
+ value = to_signed_byte(read_byte_and_advance_pc)
1029
+ @pc += value if condition
1030
+
1031
+ condition ? 12 : 8
1032
+ end
1033
+
1034
+ def jp(x, condition: true)
1035
+ addr = get_value(x)
1036
+ @pc = addr if condition
1037
+
1038
+ return 4 if x[:type] == :register16
1039
+
1040
+ condition ? 16 : 12
1041
+ end
1042
+
1043
+ def call16(x, condition: true)
1044
+ addr = get_value(x)
1045
+ if condition
1046
+ @sp -= 2
1047
+ write_word(@sp, @pc)
1048
+ @pc = addr
1049
+ end
1050
+
1051
+ condition ? 24 : 12
1052
+ end
1053
+
1054
+ def ret
1055
+ @pc = read_word(@sp)
1056
+ @sp += 2
1057
+
1058
+ 16
1059
+ end
1060
+
1061
+ def ret_if(condition)
1062
+ ret if condition
1063
+
1064
+ condition ? 20 : 8
1065
+ end
1066
+
1067
+ def reti
1068
+ @ime = true
1069
+ ret
1644
1070
  end
1645
1071
 
1646
1072
  def rlc8(x)
1647
- x.value = (x.value << 1) | (x.value >> 7)
1073
+ value = get_value(x)
1074
+ value = (value << 1) | (value >> 7)
1075
+ set_value(x, value)
1648
1076
  update_flags(
1649
- z: x.value.zero?,
1077
+ z: value == 0,
1650
1078
  n: false,
1651
1079
  h: false,
1652
- c: x.value[0] == 1
1080
+ c: value[0] == 1
1653
1081
  )
1082
+
1083
+ x[:type] == :register8 ? 8 : 16
1654
1084
  end
1655
1085
 
1656
1086
  def rrc8(x)
1657
- x.value = (x.value >> 1) | (x.value << 7)
1087
+ value = get_value(x)
1088
+ value = (value >> 1) | (value << 7)
1089
+ set_value(x, value)
1658
1090
  update_flags(
1659
- z: x.value.zero?,
1091
+ z: value == 0,
1660
1092
  n: false,
1661
1093
  h: false,
1662
- c: x.value[7] == 1
1094
+ c: value[7] == 1
1663
1095
  )
1096
+
1097
+ x[:type] == :register8 ? 8 : 16
1664
1098
  end
1665
1099
 
1666
1100
  def rl8(x)
1667
- cflag = x.value[7] == 1
1668
- x.value = (x.value << 1) | bool_to_integer(flags[:c])
1101
+ value = get_value(x)
1102
+ cflag = value[7] == 1
1103
+ value = ((value << 1) | bool_to_integer(flags[:c])) & 0xff
1104
+ set_value(x, value)
1669
1105
  update_flags(
1670
- z: x.value.zero?,
1106
+ z: value == 0,
1671
1107
  n: false,
1672
1108
  h: false,
1673
1109
  c: cflag
1674
1110
  )
1111
+
1112
+ x[:type] == :register8 ? 8 : 16
1675
1113
  end
1676
1114
 
1677
1115
  def rr8(x)
1678
- cflag = x.value[0] == 1
1679
- x.value = (x.value >> 1) | (bool_to_integer(flags[:c]) << 7)
1116
+ value = get_value(x)
1117
+ cflag = value[0] == 1
1118
+ value = (value >> 1) | (bool_to_integer(flags[:c]) << 7)
1119
+ set_value(x, value)
1680
1120
  update_flags(
1681
- z: x.value.zero?,
1121
+ z: value == 0,
1682
1122
  n: false,
1683
1123
  h: false,
1684
1124
  c: cflag
1685
1125
  )
1126
+
1127
+ x[:type] == :register8 ? 8 : 16
1686
1128
  end
1687
1129
 
1688
1130
  def sla8(x)
1689
- cflag = x.value[7] == 1
1690
- x.value <<= 1
1131
+ value = get_value(x)
1132
+ cflag = value[7] == 1
1133
+ value <<= 1
1134
+ value &= 0xff
1135
+ set_value(x, value)
1691
1136
  update_flags(
1692
- z: x.value.zero?,
1137
+ z: value == 0,
1693
1138
  n: false,
1694
1139
  h: false,
1695
1140
  c: cflag
1696
1141
  )
1142
+
1143
+ x[:type] == :register8 ? 8 : 16
1697
1144
  end
1698
1145
 
1699
1146
  def sra8(x)
1700
- cflag = x.value[0] == 1
1701
- x.value = (x.value >> 1) | (x.value[7] << 7)
1147
+ value = get_value(x)
1148
+ cflag = value[0] == 1
1149
+ value = (value >> 1) | (value[7] << 7)
1150
+ set_value(x, value)
1702
1151
  update_flags(
1703
- z: x.value.zero?,
1152
+ z: value == 0,
1704
1153
  n: false,
1705
1154
  h: false,
1706
1155
  c: cflag
1707
1156
  )
1157
+
1158
+ x[:type] == :register8 ? 8 : 16
1708
1159
  end
1709
1160
 
1710
1161
  def swap8(x)
1711
- x.value = ((x.value & 0x0f) << 4) | ((x.value & 0xf0) >> 4)
1162
+ value = get_value(x)
1163
+ value = ((value & 0x0f) << 4) | ((value & 0xf0) >> 4)
1164
+ set_value(x, value)
1712
1165
  update_flags(
1713
- z: x.value.zero?,
1166
+ z: value == 0,
1714
1167
  n: false,
1715
1168
  h: false,
1716
1169
  c: false
1717
1170
  )
1171
+
1172
+ x[:type] == :register8 ? 8 : 16
1718
1173
  end
1719
1174
 
1720
1175
  def srl8(x)
1721
- cflag = x.value[0] == 1
1722
- x.value >>= 1
1176
+ value = get_value(x)
1177
+ cflag = value[0] == 1
1178
+ value >>= 1
1179
+ set_value(x, value)
1723
1180
  update_flags(
1724
- z: x.value.zero?,
1181
+ z: value == 0,
1725
1182
  n: false,
1726
1183
  h: false,
1727
1184
  c: cflag
1728
1185
  )
1186
+
1187
+ x[:type] == :register8 ? 8 : 16
1729
1188
  end
1730
1189
 
1731
1190
  def bit8(n, x)
1191
+ value = get_value(x)
1732
1192
  update_flags(
1733
- z: x.value[n].zero?,
1193
+ z: value[n] == 0,
1734
1194
  n: false,
1735
1195
  h: true
1736
1196
  )
1197
+
1198
+ x[:type] == :register8 ? 8 : 12
1199
+ end
1200
+
1201
+ def res8(n, x)
1202
+ value = get_value(x)
1203
+ value &= ((~(1 << n)) & 0xff)
1204
+ set_value(x, value)
1205
+
1206
+ x[:type] == :register8 ? 8 : 16
1737
1207
  end
1738
1208
 
1739
1209
  def set8(n, x)
1740
- x.value |= (1 << n)
1210
+ value = get_value(x)
1211
+ value |= (1 << n)
1212
+ set_value(x, value)
1213
+
1214
+ x[:type] == :register8 ? 8 : 16
1741
1215
  end
1742
1216
 
1743
- def res8(n, x)
1744
- x.value &= ((~(1 << n)) & 0xff)
1217
+ def get_value(operand)
1218
+ case operand[:type]
1219
+ when :register8 then @registers.read8(operand[:value])
1220
+ when :register16 then @registers.read16(operand[:value])
1221
+ when :sp then @sp
1222
+ when :immediate8 then read_byte_and_advance_pc
1223
+ when :immediate16 then read_word_and_advance_pc
1224
+ when :direct8 then read_byte(read_word_and_advance_pc)
1225
+ when :direct16 then read_word(read_word_and_advance_pc)
1226
+ when :indirect then read_byte(@registers.read16(operand[:value]))
1227
+ when :ff00 then read_byte(0xff00 + read_byte_and_advance_pc)
1228
+ when :ff00_c then read_byte(0xff00 + @registers.read8(:c))
1229
+ when :hl_inc
1230
+ value = read_byte(@registers.read16(:hl))
1231
+ @registers.increment16(:hl)
1232
+ value
1233
+ when :hl_dec
1234
+ value = read_byte(@registers.read16(:hl))
1235
+ @registers.decrement16(:hl)
1236
+ value
1237
+ else raise "unknown operand: #{operand}"
1238
+ end
1239
+ end
1240
+
1241
+ def set_value(operand, value)
1242
+ case operand[:type]
1243
+ when :register8 then @registers.write8(operand[:value], value)
1244
+ when :register16 then @registers.write16(operand[:value], value)
1245
+ when :sp then @sp = value & 0xffff
1246
+ when :direct8 then write_byte(read_word_and_advance_pc, value)
1247
+ when :direct16 then write_word(read_word_and_advance_pc, value)
1248
+ when :indirect then write_byte(@registers.read16(operand[:value]), value)
1249
+ when :ff00 then write_byte(0xff00 + read_byte_and_advance_pc, value)
1250
+ when :ff00_c then write_byte(0xff00 + @registers.read8(:c), value)
1251
+ when :hl_inc
1252
+ write_byte(@registers.read16(:hl), value)
1253
+ @registers.increment16(:hl)
1254
+ when :hl_dec
1255
+ write_byte(@registers.read16(:hl), value)
1256
+ @registers.decrement16(:hl)
1257
+ when :immediate8, :immediate16 then raise 'immediate type is read only'
1258
+ else raise "unknown operand: #{operand}"
1259
+ end
1745
1260
  end
1746
1261
  end
1747
1262
  end