Browse Source

Actually playing with an implementation of a CPU. Also added some notes.

master
Zack Marvel 4 years ago
parent
commit
bddf70bcf1
3 changed files with 547 additions and 101 deletions
  1. +96
    -87
      notes.txt
  2. +34
    -0
      regs.txt
  3. +417
    -14
      slowboy/z80.py

+ 96
- 87
notes.txt View File

@@ -1,9 +1,27 @@
0x40 0100 0000 ld B, B
0x76 0111 0110 halt
0x00 0000 0000 nop
0x10 0001 0000 stop
0xfb 1111 1011 ei
0xf3 1111 0011 di

B: 000
C: 001
D: 010
E: 011
H: 100
L: 101
(HL): 110
A: 111

01dd dsss

0x40 0100 0000 ld B, B ✓
0x41 0100 0001 ld B, C
0x42 0100 0010 ld B, D
0x43 0100 0011 ld B, E
0x44 0100 0100 ld B, H
0x45 0100 0101 ld B, L
0x46 0100 0110 ld B, (HL)
0x47 0100 0111 ld B, A

0x48 0100 1000 ld C, B
@@ -12,6 +30,7 @@
0x4b 0100 1011 ld C, E
0x4c 0100 1100 ld C, H
0x4d 0100 1101 ld C, L
0x4e 0100 1110 ld C, (HL)
0x4f 0100 1111 ld C, A

0x50 0101 0000 ld D, B
@@ -20,6 +39,7 @@
0x53 0101 0011 ld D, E
0x54 0101 0100 ld D, H
0x55 0101 0101 ld D, L
0x56 0101 0110 ld D, (HL)
0x57 0101 0111 ld D, A

0x58 0101 1000 ld E, B
@@ -28,6 +48,7 @@
0x5b 0101 1011 ld E, E
0x5c 0101 1100 ld E, H
0x5d 0101 1101 ld E, L
0x5e 0101 1110 ld E, (HL)
0x5f 0101 1111 ld E, A

0x60 0110 0000 ld H, B
@@ -36,6 +57,7 @@
0x63 0110 0011 ld H, E
0x64 0110 0100 ld H, H
0x65 0110 0101 ld H, L
0x66 0110 0110 ld H, (HL)
0x67 0110 0111 ld H, A

0x68 0110 1000 ld L, B
@@ -44,6 +66,7 @@
0x6b 0110 1011 ld L, E
0x6c 0110 1100 ld L, H
0x6d 0110 1101 ld L, L
0x6e 0110 1110 ld L, (HL)
0x6f 0110 1111 ld L, A

0x70 0111 0000 ld (HL), B
@@ -52,7 +75,6 @@
0x73 0111 0011 ld (HL), E
0x74 0111 0100 ld (HL), H
0x75 0111 0101 ld (HL), L
0x76 0111 0110 halt
0x77 0111 0111 ld (HL), A

0x78 0111 1000 ld A, B
@@ -61,27 +83,20 @@
0x7b 0111 1011 ld A, E
0x7c 0111 1100 ld A, H
0x7d 0111 1101 ld A, L
0x7f 0111 1111 ld A, A

0x46 0100 0110 ld B, (HL)
0x4e 0100 1110 ld C, (HL)
0x56 0101 0110 ld D, (HL)
0x5e 0101 1110 ld E, (HL)
0x66 0110 0110 ld H, (HL)
0x6e 0110 1110 ld L, (HL)
0x7e 0111 1110 ld A, (HL)
0x7f 0111 1111 ld A, A

0x01 0000 0001 ld BC, nn
0x01 0000 0001 ld BC, nn 00xx 0001 ✓
0x11 0001 0001 ld DE, nn
0x21 0010 0001 ld HL, nn
0x31 0011 0001 ld SP, nn

0x02 0000 0010 ld (BC), A
0x02 0000 0010 ld (BC), A 00xx 0010 ✓
0x12 0001 0010 ld (DE), A
0x22 0010 0010 ldi (HL), A
0x22 0010 0010 ldi (HL), A
0x32 0011 0010 ldd (HL), A

0x06 0000 0110 ld B, n
0x06 0000 0110 ld B, n 00xx x110 ✓
0x0e 0000 1110 ld C, n
0x16 0001 0110 ld D, n
0x1e 0001 1110 ld E, n
@@ -90,26 +105,23 @@
0x36 0011 0110 ld (HL), n
0x3e 0001 1110 ld A, n

0x08 0000 1000 ld (nn), SP
0x08 0000 1000 ld (nn), SP

0x0a 0000 1010 ld A, (BC)
0x0a 0000 1010 ld A, (BC) 00xx 1010 ✓
0x1a 0001 1010 ld A, (DE)
0x2a 0010 1010 ldi A, (HL)
0x3a 0010 1010 ldd A, (HL)
0x2a 0010 1010 ldi A, (HL)
0x3a 0011 1010 ldd A, (HL)

0xe0 1110 0000 ldh (n), A
0xe0 1110 0000 ldh (n), A
0xf0 1111 0000 ldh A, (n)

0xea 1110 1010 ld (nn), A
0xea 1110 1010 ld (nn), A
0xfa 1111 1010 ld A, (nn)

0xf8 1111 1000 ldhl SP, n
0xf8 1111 1000 ldhl SP, n
0xf9 1111 1001 ld SP, HL

0x00 0000 0000 nop
0x10 0001 0000 stop

0x04 0000 0100 inc B
0x04 0000 0100 inc B 00xx x100 ✓
0x0c 0000 1100 inc C
0x14 0001 0100 inc D
0x1c 0001 1100 inc E
@@ -118,16 +130,16 @@
0x34 0011 0100 inc (HL)
0x3c 0011 1100 inc A

0x03 0000 0011 inc BC
0x03 0000 0011 inc BC 00xx 0011 ✓
0x13 0001 0011 inc DE
0x23 0010 0011 inc HL
0x33 0011 0011 inc SP
0x0b 0000 1011 dec BC
0x0b 0000 1011 dec BC 00xx 1011 ✓
0x1b 0001 1011 dec DE
0x2b 0010 1011 dec HL
0x3b 0011 1011 dec SP

0x05 0000 0101 dec B
0x05 0000 0101 dec B 00xx x101 ✓
0x0d 0000 1101 dec C
0x15 0001 0101 dec D
0x1d 0001 1101 dec E
@@ -136,141 +148,138 @@
0x35 0011 0101 dec (HL)
0x3d 0011 1101 dec A

0x07 0000 0111 rlc A
0x07 0000 0111 rlc A 000x 0111 ✓
0x17 0001 0111 rl A
0x27 0010 0111 daa
0x37 0011 0111 scf

0x80 1000 0000 add A, B
0x80 1000 0000 add A, B 1000 0xxx ✓
0x81 1000 0001 add A, C
0x82 1000 0010 add A, D
0x83 1000 0011 add A, E
0x84 1000 0100 add A, H
0x85 1000 0101 add A, L
0x86 1000 0110 add A, (HL)
0x87 1000 0111 add A, A

0x88 1000 1000 adc A, B
0x88 1000 1000 adc A, B 1000 1xxx ✓
0x89 1000 1001 adc A, C
0x8a 1000 1010 adc A, D
0x8b 1000 1011 adc A, E
0x8c 1000 1100 adc A, H
0x8d 1000 1101 adc A, L
0x8e 1000 1110 adc A, (HL)
0x8f 1000 1111 adc A, A

0x90 1001 0000 sub A, B
0xe8 1110 1000 add SP, d 1110 1000 ✓

0x90 1001 0000 sub A, B 1001 0xxx ✓
0x91 1001 0001 sub A, C
0x92 1001 0010 sub A, D
0x93 1001 0011 sub A, E
0x94 1001 0100 sub A, H
0x95 1001 0101 sub A, L
0x96 1001 0110 sub A, (HL)
0x97 1001 0111 sub A, A

0x98 1001 1000 sbc A, B
0x98 1001 1000 sbc A, B 1001 1xxx ✓
0x99 1001 1001 sbc A, C
0x9a 1001 1010 sbc A, D
0x9b 1001 1011 sbc A, E
0x9c 1001 1100 sbc A, H
0x9d 1001 1101 sbc A, L
0x9e 1001 1110 sbc A, (HL)
0x9f 1001 1111 sbc A, A

0xa0 1010 0000 and B
0xa0 1010 0000 and B 1010 0xxx ✓
0xa1 1010 0001 and C
0xa2 1010 0010 and D
0xa3 1010 0011 and E
0xa4 1010 0100 and H
0xa5 1010 0101 and L
0xa6 1010 0110 and (HL)
0xa7 1010 0111 and A

0xa8 1010 1000 xor B
0xa8 1010 1000 xor B 1010 1xxx ✓
0xa9 1010 1001 xor C
0xaa 1010 1010 xor D
0xab 1010 1011 xor E
0xac 1010 1100 xor H
0xad 1010 1101 xor L
0xae 1010 1110 xor (HL)
0xaf 1010 1111 xor A

0xb0 1011 0000 or B
0xb0 1011 0000 or B 1011 0xxx ✓
0xb1 1011 0001 or C
0xb2 1011 0010 or D
0xb3 1011 0011 or E
0xb4 1011 0100 or H
0xb5 1011 0101 or L
0xb6 1011 0110 or (HL)
0xb7 1011 0111 or A

0xb8 1011 1000 cp B
0xb8 1011 1000 cp B 1011 1xxx ✓
0xb9 1011 1001 cp C
0xba 1011 1010 cp D
0xbb 1011 1011 cp E
0xbc 1011 1100 cp H
0xbd 1011 1101 cp L
0xbe 1011 1110 cp (HL)
0xbf 1011 1111 cp A

0xc0 1100 0000 ret NZ
0xd0 1101 0000 ret NC
0x86 1000 0110 add A, (HL) 1000 x110 ✓
0x8e 1000 1110 adc A, (HL)
0x96 1001 0110 sub A, (HL) 1101 x110 ✓
0x9e 1001 1110 sbc A, (HL)
0xa6 1010 0110 and (HL) 101x x110 ✓
0xae 1010 1110 xor (HL)
0xb6 1011 0110 or (HL)
0xbe 1011 1110 cp (HL)

0xc1 1100 0001 pop BC
11xx x1x0
0xc6 1100 0110 add A, n 1100 x110 ✓
0xce 1100 1110 adc A, n
0xd6 1101 0110 sub A, n 1101 x110 ✓
0xde 1101 1110 sbc A, n
0xe6 1110 0110 and n 111x x110 ✓
0xee 1110 1110 xor n
0xf6 1111 0110 or n
0xfe 1111 1110 cp n

0xc1 1100 0001 pop BC 11xx 0001 ✓
0xd1 1101 0001 pop DE
0xe1 1110 0001 pop HL
0xf1 1111 0001 pop AF

0xc5 1100 0101 push BC
0xc5 1100 0101 push BC 11xx 0101 ✓
0xd5 1101 0101 push DE
0xe5 1110 0101 push HL
0xf5 1111 0101 push AF

0x20 0010 0000 jr NZ, n ☑ relative jump
0x30 0011 0000 jr NC, n
0x20 0010 0000 jr NZ, n 001x 0000
0x30 0011 0000 jr NC, n

0xc2 1100 0010 jp NZ, nn ☑
0xca 1100 1010 jp Z, nn ☑
0xd2 1101 0010 jp NC, nn ☑
0xda 1101 1010 jp C, nn ☑
0xe9 1110 1001 jp (HL)
0xc3 1100 0011 jp nn
0xca 1100 1010 jp Z, nn 110x 1010
0xda 1101 1010 jp C, nn
0xc2 1100 0010 jp NZ, nn 110x 0010
0xd2 1101 0010 jp NC, nn
0xe9 1110 1001 jp (HL) 1110 1001
0xc3 1100 0011 jp nn 1100 0011


0xc4 1100 0100 call NZ, nn
0xcc 1100 1100 call Z, nn
0xd4 1101 0100 call NC, nn
0xcc 1100 1100 call Z, nn 110x 1100
0xdc 1101 1100 call C, nn
0xcd 1100 1101 call nn

-------------------------------

0xc6 1100 0110 add A, n
0xd6 1101 0110 sub A, n
0xe6 1110 0110 and n
0xf6 1111 0110 or n

0xc7 1100 0111 rst 0
0xd7 1101 0111 rst 10
0xe7 1110 0111 rst 20
0xf7 1111 0111 rst 30
0xc4 1100 0100 call NZ, nn 110x 0100
0xd4 1101 0100 call NC, nn
0xcd 1100 1101 call nn 1100 1101

0xc8 1100 1000 ret Z
0xc8 1100 1000 ret Z 110x 1000
0xd8 1101 1000 ret C

0xe8 1110 1000 add SP, d

0xc9 1100 1001 ret
0xc0 1100 0000 ret NZ 110x 0000
0xd0 1101 0000 ret NC
0xc9 1100 1001 ret 110x 1001
0xd9 1101 1001 reti

0xcb 1100 1011 16-BIT OPERATION
0xc7 1100 0111 rst 0x00 10xx x111
0xcf 1100 1111 rst 0x08
0xd7 1101 0111 rst 0x10
0xdf 1101 1111 rst 0x18
0xe7 1110 0111 rst 0x20
0xef 1110 1111 rst 0x28
0xf7 1111 0111 rst 0x30
0xff 1111 1111 rst 0x38

0xfb 1111 1011 ei


0xce 1100 1110 adc A, n
0xde 1101 1110 sbc A, n
0xee 1110 1110 xor n
0xfe 1111 1110 cp n

0xcf 1100 1111 rst 8
0xcb 1100 1011 16-BIT OPERATION

+ 34
- 0
regs.txt View File

@@ -0,0 +1,34 @@

0x04 0000 0100 inc B
0x14 0001 0100 inc D
0x24 0010 0100 inc H
0x34 0011 0100 inc (HL)
0x0c 0000 1100 inc C
0x1c 0001 1100 inc E
0x2c 0010 1100 inc L
0x3c 0011 1100 inc A

B: 0b000
C: 0b001
D: 0b010
E: 0b011
H: 0b100
L: 0b101
(HL): 0b110
A: 0b111

The lowest bit is unset to indicate an 8-bit operation.

--------------------------

0x03 0000 0011 inc BC
0x13 0001 0011 inc DE
0x23 0010 0011 inc HL
0x33 0011 0011 inc SP

BC: 0b10
DE: 0b01
HL: 0b10
SP: 0b11

Here the lowest bit is set to indicate this is a 16-bit operation.

+ 417
- 14
slowboy/z80.py View File

@@ -1,9 +1,12 @@

from functools import partial

class gb_z80(object):
c = 0
m = 0
registers = {

def __init__(self):
self.clk = 0
self.m = 0
self.registers = {
'a': 0, 'f': 0,
'b': 0, 'c': 0,
'd': 0, 'e': 0,
@@ -12,10 +15,409 @@ class gb_z80(object):
'pc': 0
}

instructions = {
}
def _init_opcodes(self):
opcodes = { # all opcodes are functions that take the opcode as the first argument
0x00: partial(self._nop, 0x00),
0x10: partial(self._stop, 0x10),
0x76: partial(self._halt, 0x76),
0xfb: partial(self._ei, 0xfb),
0xf3: partial(self._di, 0xf3),
}

reg8s = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
reg16s = ['BC', 'DE', 'HL', 'SP']

for i in range(8):
for j in range(8): # ld reg8, reg8
# 01dd dsss
opcode = 0x40 | (i << 3) | j
opcodes[opcode] = partial(self._ld, opcode)
for i in range(4): # ld reg16, imm16
opcode = 0x01 | (i << 4)
opcodes[opcode] = partial(self._ld, opcode)

opcodes[0x01] = partial(self._ld, 0x01) # ld (be), a
opcodes[0x12] = partial(self._ld, 0x12) # ld (de), a
opcodes[0x22] = partial(self._ld, 0x22) # ldi (hl), a
opcodes[0x32] = partial(self._ld, 0x32) # ldd (hl), a

for i in range(8): # ld reg8, imm8
opcode = 0x06 | i << 3
opcodes[opcode] = partial(self._ld, opcode)

opcodes[0x08] = partial(self_.ld, 0x08) # ld (imm16), SP

for i in range (4): # ld A, (BC)/(DE) ; ldi/ldd A, (HL)
opcode = 0x0a | (i << 4)
opcodes[opcode] = partial(self._ld, opcode)
opcodes[0xe0] = partial(self._ld, 0xe0) # ld ($ff00+imm8), A
opcodes[0xea] = partial(self._ld, 0xea) # ld ($ff00+imm16), A
opcodes[0xf0] = partial(self._ld, 0xf0) # ld A, ($ff00+imm8)
opcodes[0xfa] = partial(self._ld, 0xfa) # ld A, ($ff00+imm16)

opcodes[0xf8] = partial(self._ld, 0xf8) # ld HL, SP+imm8
opcodes[0xf9] = partial(self._ld, 0xf9) # ld SP, HL

for i in range(8): # inc reg8
opcode = 0x04 | (i << 3)
opcodes[opcode] = partial(self._inc, opcode)

for i in range(8): # dec reg8
opcode = 0x05 | (i << 3)
opcodes[opcode] = partial(self._dec, opcode)

for i in range(4): # inc reg16
opcode = 0x03 | (i << 4)
opcodes[opcode] = partial(self._inc, opcode)

for i in range(4): # dec reg16
opcode = 0x0b | (i << 4)
opcodes[opcode] = partial(self._dec, opcode)

opcode[0x07] = partial(self._rlc, 0x07)
opcode[0x17] = partial(self._rl, 0x17)
opcode[0x27] = partial(self._daa, 0x27)
opcode[0x37] = partial(self._scf, 0x37)

for i in range(8): # add reg8, reg8
opcode = 0x80 | i
opcodes[opcode] = partial(self._add, opcode)
for i in range(8): # adc reg8, reg8
opcode = 0x88 | i
opcodes[opcode] = partial(self._adc, opcode)

opcodes[0xe8] = partial(self._add, opcde) # add SP, imm8 (signed)

for i in range(8): # sub A, reg8
opcode = 0x90 | i
opcodes[opcode] = partial(self._sub, opcode)

for i in range(8): # sbc A, reg8
opcode = 0x98 | i
opcodes[opcode] = partial(self._sbc, opcode)
for i in range(8): # and reg8
opcode = 0xa0 | i
opcodes[opcode] = partial(self._and, opcode)

for i in range(8): # xor reg8
opcode = 0xa8 | i
opcodes[opcode] = partial(self._xor, opcode)

for i in range(8): # or reg8
opcode = 0xb0 | i
opcodes[opcode] = partial(self._or, opcode)

for i in range(8): # cp reg8
opcode = 0xb8 | i
opcodes[opcode] = partial(self._cp, opcode)

opcode = 0xc6 # add A, imm8
opcodes[opcode] = partial(self._add, opcode)
opcode = 0xce # adc A, imm8
opcodes[opcode] = partial(self._adc, opcode)
opcode = 0xd6 # sub A, imm8
opcodes[opcode] = partial(self._sub, opcode)
opcode = 0xde # sbc A, imm8
opcodes[opcode] = partial(self._sbc, opcode)
opcode = 0xe6 # and imm8
opcodes[opcode] = partial(self._and, opcode)
opcode = 0xee # xor imm8
opcodes[opcode] = partial(self._xor, opcode)
opcode = 0xf6 # or imm8
opcodes[opcode] = partial(self._or, opcode)
opcode = 0xfe # cp imm8
opcodes[opcode] = partial(self._cp, opcode)

for i in range(4): # push reg16
opcode = 0xc5 | (i << 4)
opcodes[opcode] = partial(self._push, opcode)

for i in range(4): # pop reg16
opcode = 0xc1 | (i << 4)
opcodes[opcode] = partial(self._pop, opcode)

opcode = 0x20 # jr nz, imm8
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0x30 # jr nc, imm8
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0xca # jp z, imm16
opcodes[opcode] = partial(self._jp, opcode)
opcode = 0xda # jp c, imm16
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0xc2 # jp nz, imm16
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0xd2 # jp nc, imm16
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0xe9 # jp (hl)
opcodes[opcode] = partial(self._jr, opcode)
opcode = 0xc3 # jp imm16
opcodes[opcode] = partial(self._jr, opcode)

def read_register(self, reg: str) -> int:
opcode = 0xcc # call z, imm16
opcodes[opcode] = partial(self._call, opcode)
opcode = 0xdc # call c, imm16
opcodes[opcode] = partial(self._call, opcode)
opcode = 0xc4 # call nz, imm16
opcodes[opcode] = partial(self._call, opcode)
opcode = 0xd4 # call nc, imm16
opcodes[opcode] = partial(self._call, opcode)
opcode = 0xcd # call imm16
opcodes[opcode] = partial(self._call, opcode)

opcode = 0xc8 # ret z
opcodes[opcode] = partial(self._ret, opcode)
opcode = 0xd8 # ret c
opcodes[opcode] = partial(self._ret, opcode)
opcode = 0xc0 # ret nz
opcodes[opcode] = partial(self._ret, opcode)
opcode = 0xd0 # ret nc
opcodes[opcode] = partial(self._ret, opcode)
opcode = 0xc9 # ret
opcodes[opcode] = partial(self._ret, opcode)
opcode = 0xd9 # ret i
opcodes[opcode] = partial(self._ret, opcode)

opcode = 0xc7
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xcf
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xd7
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xdf
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xe7
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xef
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xf7
opcodes[opcode] = partial(self._rst, opcode)
opcode = 0xff
opcodes[opcode] = partial(self._rst, opcode)




def _increment_pc(self):
registers['pc'] += 1

def _advance(self):
byte = self._read_memory(registers['pc'])
self.increment_pc()
return byte
def tick(self):
op = self._advance()
opcodes[op]()

def ld(

def lookup_opcode(self, opcode):
hn = opcode >> 4
ln = opcode & 0xf
if opcode == 0x00:
return self._nop
elif opcode == 0x10:
return self._stop
elif opcode == 0x76:
return self._halt
elif opcode == 0xcf:
# di (disable interrupts)
return self._di
elif opcode == 0xfb:
# enable interrupts
return self._ei
elif hn >> 2 == 0x1:
# 01xx xxxx : ld into 8-bit reg
src_registers = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
dest_registers = src_registers
src_idx = opcode & 0x7
dest_idx = (opcode >> 3) & 0x7
return self._ld # ld src_registers[src_idx], dest_idx[dest_idx]
elif opcode & 0xcf == 0x01:
# 00xx 0001 : ld 16-bit imm into reg
dest_registers = ['BC', 'DE', 'HL', 'SP']
dest_idx = hn & 0x3
return self._ld # ld dest_registers[dest_idx], imm16
elif opcode & 0xef == 0x02:
# 000x 0010 : ld value at 16-bit addr, reg a
dest_addrs = ['(BC)', '(DE)']
dest_idx = hn & 0x1
return self._ld # ld dest_addrs[dest_idx], a
elif opcode & 0xef == 0x22:
# 001x 0010 : ld (HL), reg a then increment/decrement HL
if hn & 0x1 == 1:
return self._ldi
else:
return self._ldd
elif opcode & 0xc7 == 0x06:
# 00xx x110 : ld reg8, imm8
dest_registers = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
dest_idx = (opcode >> 3) & 0x7
return self._ld # ld dest_registers[dest_idx], imm8
elif opcode == 0x08:
# 0000 1000 : ld SP into value at immediate address
return self._ld # ld (imm16), SP
elif opcode & 0xcf == 0x0a:
# 00xx 1010 : ld value at addr in a reg into reg A
if hn >> 1 == 0: # 000x 1010
dest_addrs = ['(BC)', '(DE)']
dest_idx = hn & 0x1
return self._ld
elif hn & 0x1 == 0:
return self._ldi # ldi a, (hl)
else:
return self._ldd # ldd a, (hl)
elif opcode & 0xef == 0xe0:
# 111x 0000
if hn & 0x1 == 0: # ldh (imm8), a -> ld ($FF00+imm8), a
return self._ldh
else: # ldh a, (imm8) -> ld a, ($FF00+imm8)
return self._ldh
elif opcode & 0xef == 0xea:
# 111x 1010
if hn & 1: # ld (imm16), a
return self._ld
else: # ld a, (imm16)
return self._ld
elif opcode & 0xfe == 0xf8:
# 1111 111x
if ln & 0x1 == 1: # ld SP, HL
return self._ld
else: # ldhl SP, imm8 -> ld HL, SP+imm8
return self._ld
elif opcode & 0xc7 == 0x04:
# 00xx x100: inc regs[reg_idx] (8-bit)
regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
reg_idx = (opcode >> 3) & 0x7
return self._inc
elif opcode & 0xc7 == 0x05:
# 00xx x101 : dec regs[reg_idx] (8-bit)
regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
reg_idx = (opcode >> 3) & 0x7
return self._dec
elif opcode & 0xcf == 0x03:
# 00xx 0011 : inc regs[reg_idx] (16-bit)
regs = ['BC', 'DE', 'HL', 'SP']
reg_idx = hn & 0x3
return self._inc
elif opcode & 0xcf == 0x0b:
# 00xx 1011 : dec regs[reg_dx] (16-bit)
regs = ['BC', 'DE', 'HL', 'SP']
reg_idx = hn & 0x3
return self._dec
elif opcode & 0xef == 0x07:
# 000x 0111 : rl/rlc a
if hn & 0x1 == 1:
return self._rl
else:
return self._rlc
elif opcode == 0x27:
return self._daa
elif opcode == 0x37:
return self._scf
elif opcode & 0xf0 == 0x80:
# 1000 xxxx : add/adc A, reg8
src_regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
src_idx = ln & 0x3
if ln >> 3 == 1:
return self._adc
else:
return self._add
elif opcode == 0xe8:
# 1110 1000 : add SP, imm8 (signed)
return self._add
elif opcode & 0xf8 == 0x90:
# 1001 1xxx : sub/subc A, reg8
src_regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
src_idx = ln & 0x3
if ln >> 3 == 1:
return self._sbc
else:
return self._sub
elif opcode & 0xf8 == 0xa8:
# 1010 1xxx : xor reg8 (i.e. reg8 ^ A)
src_regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
src_idx = ln & 0x3
return self._xor
elif opcode & 0xf8 == 0xb0:
# 1011 0xxx : or reg8 (i.e. reg8 | A)
src_regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
src_idx = ln & 0x3
return self._or
elif opcode & 0xf8 == 0xb8:
# 1011 1xxx : cp reg8 (i.e. reg8 == A)
src_regs = ['B', 'C', 'D', 'E', 'H', 'L', '(HL)', 'A']
src_idx = ln & 0x3
return self._cp
elif opcode & 0xf7 == 0x86:
# 1000 x110 : add/c A, (HL)
if hn >> 3 == 1:
return self._adc
else:
return self._add
elif opcode & 0xf7 == 0xd6:
if hn >> 3 == 1:
return self._sbc
else:
return self._sub
elif opcode & 0xe7 == 0xa6:
# 101x x110 : and/xor/or/cp (HL)
instructions = [self._and, self._xor, self._or, self_cp]
instruction_idx = (opcode >> 3) & 0x3
return instructions[instructions_idx]
elif opcode & 0xf7 == 0xc6:
# 1100 x110 : add/adc A, imm8
if ln >> 3 == 1:
return self._adc
else:
return self._add
elif opcode & 0xf7 == 0xd6:
# 1101 x110 : sub/subc A, imm8
if ln >> 3 == 1:
return self._sbc
else:
return self._sub
elif opcode & 0xe7 == 0xe6:
# 111x x110 : and/xor/or/cp imm8 (i.e. and/xor/or/cp imm8, A)
instructions = [self._and, self._xor, self._or, self_cp]
instruction_idx = (opcode >> 3) & 0x3
return instructions[instruction_idx]
elif opcode & 0xcf == 0xc1:
# 11xx 0001 : pop reg16
dest_regs = ['BC', 'DE', 'HL', 'AF']
dest_idx = hn & 0x2
return self._pop
elif opcode & 0xcf == 0xc5:
# 11xx 0101 : push reg16
src_egs = ['BC', 'DE', 'HL', 'AF']
src_idx = hn & 0x2
return self._pop
elif














def read_register(self, reg: str) -> int:
if len(reg) == 1:
return (registers[reg[0]] << 8) | registers[reg[1]]
return registers[reg]
@@ -27,27 +429,28 @@ class gb_z80(object):
registers[reg[1]] = v & 0x0f
registers[reg] = v
def set_zero_flag(self):
def _set_zero_flag(self):
registers['f'] |= 0x80
def reset_zero_flag(self):
def _reset_zero_flag(self):
registers['f'] &= 0x7f

def set_carry_flag(self):
def _set_carry_flag(self):
registers['f'] |= 0x10

def reset_carry_flag(self):
def _reset_carry_flag(self):
registers['f'] &= 0xef

def set_addsub_flag(self):
def _set_addsub_flag(self):
registers['f'] |= 0x40

def reset_addsub_flag(self):
def _reset_addsub_flag(self):
registers['f'] &= 0xbf

def set_halfcarry_flag(self):
def _set_halfcarry_flag(self):
registers['f'] |= 0x20

def reset_halfcarry_flag(self):
def _reset_halfcarry_flag(self):
registers['f'] &= 0xdf


Loading…
Cancel
Save