Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67698528e1 | ||
|
|
e35aa06471 | ||
|
|
6ada7261e7 | ||
|
|
ff2f94fc05 |
+31
-23
@@ -7,7 +7,7 @@ GameBoy terminology.
|
|||||||
|
|
||||||
** Terminology
|
** Terminology
|
||||||
|
|
||||||
*** Hardware
|
*** Hardware [[#references][(1)]][[#references][(2)]]
|
||||||
|
|
||||||
| Name | Modern equivalent | Description |
|
| Name | Modern equivalent | Description |
|
||||||
|-----------------+-------------------+-------------------------------------------|
|
|-----------------+-------------------+-------------------------------------------|
|
||||||
@@ -28,18 +28,20 @@ We start counting from the right as bit *#0*!
|
|||||||
|
|
||||||
*** Opcode
|
*** Opcode
|
||||||
|
|
||||||
| Name | Bits | Sign | Mnemonics | [[https://gbdev.io/gb-opcodes/optables/][1]] | [[https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7/][2]] | [[https://gekkio.fi/files/gb-docs/gbctr.pdf][3]]/[[http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf][3]] | [[https://gbdev.io/pandocs/CPU_Instruction_Set.html][4]] | Description | Note |
|
| Name | Bits | Sign | Mnemonics | [[https://gbdev.io/gb-opcodes/optables/][1]] | [[https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7/][2]] | [[https://gekkio.fi/files/gb-docs/gbctr.pdf][3]]/[[http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf][3]] | [[https://gbdev.io/pandocs/CPU_Instruction_Set.html][4]] | Description | Note |
|
||||||
|-----------+------+----------+-----------+------+-----+------+-----+------------------------------+-------------------|
|
|-----------+------+----------+-----------+------+-----+------+-----+------------------------------+------------------------|
|
||||||
| | | | | <r> | <r> | <r> | <r> | | |
|
| | | | | <r> | <r> | <r> | <r> | | |
|
||||||
| immediate | 8 | unsigned | i8 | d8 | n8 | n | | Next byte in memory | |
|
| immediate | 8 | unsigned | i8 | d8 | n8 | n | | Next byte in memory | |
|
||||||
| immediate | 16 | unsigned | i16 | d16 | n16 | nn | | Next byte in memory | little-endian |
|
| immediate | 16 | unsigned | i16 | d16 | n16 | nn | | Next byte in memory | little-endian |
|
||||||
| register | 8 | unsigned | r8 | | r8 | r | | Any of the registers | |
|
| register | 8 | unsigned | r8 | | r8 | r | | Any of the registers | |
|
||||||
| register | 16 | unsigned | r16 | | r16 | rr | | Any of the registers | little-endian |
|
| register | 16 | unsigned | r16 | | r16 | rr | | Any of the registers | little-endian |
|
||||||
| address | 8 | unsigned | a8 | | | (n) | | Address at value | |
|
| address | 8 | unsigned | a8 | | | (n) | | Address at value | |
|
||||||
| address | 16 | unsigned | a16 or () | a16 | n16 | (nn) | nn | Address at value | little-endian |
|
| address | 16 | unsigned | a16 or () | a16 | n16 | (nn) | nn | Address at value | little-endian |
|
||||||
| immediate | 8 | signed | s8 | r8 | e8 | e | dd | Next byte in memory | |
|
| immediate | 8 | signed | s8 | r8 | e8 | e | dd | Next byte in memory | used as offset |
|
||||||
| immediate | 8 | unsigned | io8 | (a8) | n16 | (n) | n | 0xff00 + next byte in memory | write to I/O-port |
|
| immediate | 8 | unsigned | io8 | (a8) | n16 | (n) | n | 0xff00 + next byte in memory | write to I/O-port |
|
||||||
| condition | | | <ZNHC> | NZ | cc | | f | Execute if condition met | |
|
| condition | | | <ZNHC> | | cc | | f | Execute if condition met | |
|
||||||
|
| constant | 8 | unsigned | b | | u3 | b | n | Single bit at position 'x' | |
|
||||||
|
| constant | 8 | unsigned | vec | | vec | | n | One of RST vectors | absolute fixed address |
|
||||||
|
|
||||||
d = data \\
|
d = data \\
|
||||||
n = constant
|
n = constant
|
||||||
@@ -47,14 +49,19 @@ n = constant
|
|||||||
**** Flag conditions
|
**** Flag conditions
|
||||||
|
|
||||||
Flag conditions, sometimes referred to as ~cc~, are the state the flags need to
|
Flag conditions, sometimes referred to as ~cc~, are the state the flags need to
|
||||||
be in to execute the opcode. There are four possible checks[[#references][(4)]]:
|
be in to execute the opcode. There are four possible checks[[#references][(4)]][[#references][(5)]]:
|
||||||
|
|
||||||
| Code | Meaning | State |
|
| Code | Meaning | State |
|
||||||
|------+---------------------+-------|
|
|------+--------------------------------+-------|
|
||||||
| C | Carry flag is set | 1 |
|
| Z | Execute if Zero flag is set | 1 |
|
||||||
| NC | Carry flag is unset | 0 |
|
| NZ | Execute if Zero flag is unset | 0 |
|
||||||
| Z | Zero flag is set | 1 |
|
| C | Execute if Carry flag is set | 1 |
|
||||||
| NZ | Zero flag is unset | 0 |
|
| NC | Execute if Carry flag is unset | 0 |
|
||||||
|
|
||||||
|
**** RST vectors
|
||||||
|
|
||||||
|
Absolute fixed address, possible values are[[#references][(4)]]: ~0x00~, ~0x08~, ~0x10~, ~0x18~,
|
||||||
|
~0x20~, ~0x28~, ~0x30~, and ~0x38~.
|
||||||
|
|
||||||
*** Variables
|
*** Variables
|
||||||
|
|
||||||
@@ -68,7 +75,8 @@ be in to execute the opcode. There are four possible checks[[#references][(4)]]:
|
|||||||
|
|
||||||
** References
|
** References
|
||||||
|
|
||||||
1. https://gbdev.io/pandocs/Memory_Map.html
|
1. [[https://gbdev.io/pandocs/Memory_Map.html]["Memory Map"]]. rgbdev.io. Retrieved 22 Aug 2022.
|
||||||
2. https://gbdev.io/pandocs/Specifications.html
|
2. [[https://gbdev.io/pandocs/Specifications.html]["Specifications"]]. rgbdev.io. Retrieved 22 Aug 2022.
|
||||||
3. [[https://robdor.com/2016/08/10/gameboy-emulator-half-carry-flag/]["A Visual Guide to the Gameboy's Half-Carry Flag"]]. robdor.com. Retrieved 24 Aug 2022.
|
3. [[https://robdor.com/2016/08/10/gameboy-emulator-half-carry-flag/]["A Visual Guide to the Gameboy's Half-Carry Flag"]]. robdor.com. Retrieved 24 Aug 2022.
|
||||||
4. [[http://www.devrs.com/gb/files/opcodes.html]["GameBoy Opcode Summary"]]. devrs.com. Retrieved 25 Aug 2022.
|
4. [[https://rgbds.gbdev.io/docs/v0.5.2/gbz80.7#LEGEND]["gbz80(7) — CPU opcode reference"]]. rgbds.gbdev.io. Retrieved 26 Aug 2022.
|
||||||
|
5. [[http://www.devrs.com/gb/files/opcodes.html]["GameBoy Opcode Summary"]]. devrs.com. Retrieved 25 Aug 2022.
|
||||||
|
|||||||
@@ -0,0 +1,335 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // uint32_t
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "ruc/format/print.h"
|
||||||
|
#include "ruc/meta/assert.h"
|
||||||
|
|
||||||
|
void CPU::prefix()
|
||||||
|
{
|
||||||
|
// Skip 0xcb opcode
|
||||||
|
m_pc = (m_pc + 1) & 0xffff;
|
||||||
|
|
||||||
|
// Read next opcode
|
||||||
|
uint8_t opcode = read(m_pc);
|
||||||
|
print("running opcode: {:#04x} @ ({:#06x})\n", opcode, m_pc);
|
||||||
|
if (opcode >= 0x40 && opcode <= 0x7f) {
|
||||||
|
bit();
|
||||||
|
}
|
||||||
|
else if (opcode >= 0x80 && opcode <= 0xbf) {
|
||||||
|
res();
|
||||||
|
}
|
||||||
|
else if (opcode >= 0xc0 && opcode <= 0xff) {
|
||||||
|
set();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print("opcode {:#04x} not implemented\n", opcode);
|
||||||
|
print("immediate: {:#04x}\n", m_pc, pcRead());
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::bit()
|
||||||
|
{
|
||||||
|
auto test_bit = [this](uint32_t bit, uint32_t byte) -> void {
|
||||||
|
// BIT b,r8, flags: Z 0 1 -
|
||||||
|
m_wait_cycles += 8;
|
||||||
|
|
||||||
|
// Set flags
|
||||||
|
// Set zero flag if bit at position 'x' of register r8 is 0
|
||||||
|
m_zf = (byte & bit) == 0x0;
|
||||||
|
m_nf = 0;
|
||||||
|
m_hf = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto test_bit_hl = [this](uint32_t bit) -> void {
|
||||||
|
// BIT b,(HL), flags: Z 0 1 -
|
||||||
|
m_wait_cycles += 12;
|
||||||
|
|
||||||
|
// Set flags
|
||||||
|
// Set zero flag if bit at position 'x' of byte pointed by HL is 0
|
||||||
|
m_zf = (read(hl()) & bit) == 0x0;
|
||||||
|
m_nf = 0;
|
||||||
|
m_hf = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t opcode = pcRead();
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x40: /* BIT 0,B */ test_bit(0x01, m_b); break;
|
||||||
|
case 0x41: /* BIT 0,C */ test_bit(0x01, m_c); break;
|
||||||
|
case 0x42: /* BIT 0,D */ test_bit(0x01, m_d); break;
|
||||||
|
case 0x43: /* BIT 0,E */ test_bit(0x01, m_e); break;
|
||||||
|
case 0x44: /* BIT 0,H */ test_bit(0x01, m_h); break;
|
||||||
|
case 0x45: /* BIT 0,L */ test_bit(0x01, m_l); break;
|
||||||
|
case 0x46: /* BIT 0,(HL) */ test_bit_hl(0x01); break;
|
||||||
|
case 0x47: /* BIT 0,A */ test_bit(0x01, m_a); break;
|
||||||
|
|
||||||
|
case 0x48: /* BIT 1,B */ test_bit(0x02, m_b); break;
|
||||||
|
case 0x49: /* BIT 1,C */ test_bit(0x02, m_c); break;
|
||||||
|
case 0x4a: /* BIT 1,D */ test_bit(0x02, m_d); break;
|
||||||
|
case 0x4b: /* BIT 1,E */ test_bit(0x02, m_e); break;
|
||||||
|
case 0x4c: /* BIT 1,H */ test_bit(0x02, m_h); break;
|
||||||
|
case 0x4d: /* BIT 1,L */ test_bit(0x02, m_l); break;
|
||||||
|
case 0x4e: /* BIT 1,(HL) */ test_bit_hl(0x02); break;
|
||||||
|
case 0x4f: /* BIT 1,A */ test_bit(0x02, m_a); break;
|
||||||
|
|
||||||
|
case 0x50: /* BIT 2,B */ test_bit(0x04, m_b); break;
|
||||||
|
case 0x51: /* BIT 2,C */ test_bit(0x04, m_c); break;
|
||||||
|
case 0x52: /* BIT 2,D */ test_bit(0x04, m_d); break;
|
||||||
|
case 0x53: /* BIT 2,E */ test_bit(0x04, m_e); break;
|
||||||
|
case 0x54: /* BIT 2,H */ test_bit(0x04, m_h); break;
|
||||||
|
case 0x55: /* BIT 2,L */ test_bit(0x04, m_l); break;
|
||||||
|
case 0x56: /* BIT 2,(HL) */ test_bit_hl(0x04); break;
|
||||||
|
case 0x57: /* BIT 2,A */ test_bit(0x04, m_a); break;
|
||||||
|
|
||||||
|
case 0x58: /* BIT 3,B */ test_bit(0x08, m_b); break;
|
||||||
|
case 0x59: /* BIT 3,C */ test_bit(0x08, m_c); break;
|
||||||
|
case 0x5a: /* BIT 3,D */ test_bit(0x08, m_d); break;
|
||||||
|
case 0x5b: /* BIT 3,E */ test_bit(0x08, m_e); break;
|
||||||
|
case 0x5c: /* BIT 3,H */ test_bit(0x08, m_h); break;
|
||||||
|
case 0x5d: /* BIT 3,L */ test_bit(0x08, m_l); break;
|
||||||
|
case 0x5e: /* BIT 3,(HL) */ test_bit_hl(0x08); break;
|
||||||
|
case 0x5f: /* BIT 3,A */ test_bit(0x08, m_a); break;
|
||||||
|
|
||||||
|
case 0x60: /* BIT 4,B */ test_bit(0x10, m_b); break;
|
||||||
|
case 0x61: /* BIT 4,C */ test_bit(0x10, m_c); break;
|
||||||
|
case 0x62: /* BIT 4,D */ test_bit(0x10, m_d); break;
|
||||||
|
case 0x63: /* BIT 4,E */ test_bit(0x10, m_e); break;
|
||||||
|
case 0x64: /* BIT 4,H */ test_bit(0x10, m_h); break;
|
||||||
|
case 0x65: /* BIT 4,L */ test_bit(0x10, m_l); break;
|
||||||
|
case 0x66: /* BIT 4,(HL) */ test_bit_hl(0x10); break;
|
||||||
|
case 0x67: /* BIT 4,A */ test_bit(0x10, m_a); break;
|
||||||
|
|
||||||
|
case 0x68: /* BIT 5,B */ test_bit(0x20, m_b); break;
|
||||||
|
case 0x69: /* BIT 5,C */ test_bit(0x20, m_c); break;
|
||||||
|
case 0x6a: /* BIT 5,D */ test_bit(0x20, m_d); break;
|
||||||
|
case 0x6b: /* BIT 5,E */ test_bit(0x20, m_e); break;
|
||||||
|
case 0x6c: /* BIT 5,H */ test_bit(0x20, m_h); break;
|
||||||
|
case 0x6d: /* BIT 5,L */ test_bit(0x20, m_l); break;
|
||||||
|
case 0x6e: /* BIT 5,(HL) */ test_bit_hl(0x20); break;
|
||||||
|
case 0x6f: /* BIT 5,A */ test_bit(0x20, m_a); break;
|
||||||
|
|
||||||
|
case 0x70: /* BIT 6,B */ test_bit(0x40, m_b); break;
|
||||||
|
case 0x71: /* BIT 6,C */ test_bit(0x40, m_c); break;
|
||||||
|
case 0x72: /* BIT 6,D */ test_bit(0x40, m_d); break;
|
||||||
|
case 0x73: /* BIT 6,E */ test_bit(0x40, m_e); break;
|
||||||
|
case 0x74: /* BIT 6,H */ test_bit(0x40, m_h); break;
|
||||||
|
case 0x75: /* BIT 6,L */ test_bit(0x40, m_l); break;
|
||||||
|
case 0x76: /* BIT 6,(HL) */ test_bit_hl(0x40); break;
|
||||||
|
case 0x77: /* BIT 6,A */ test_bit(0x40, m_a); break;
|
||||||
|
|
||||||
|
case 0x78: /* BIT 7,B */ test_bit(0x80, m_b); break;
|
||||||
|
case 0x79: /* BIT 7,C */ test_bit(0x80, m_c); break;
|
||||||
|
case 0x7a: /* BIT 7,D */ test_bit(0x80, m_d); break;
|
||||||
|
case 0x7b: /* BIT 7,E */ test_bit(0x80, m_e); break;
|
||||||
|
case 0x7c: /* BIT 7,H */ test_bit(0x80, m_h); break;
|
||||||
|
case 0x7d: /* BIT 7,L */ test_bit(0x80, m_l); break;
|
||||||
|
case 0x7e: /* BIT 7,(HL) */ test_bit_hl(0x80); break;
|
||||||
|
case 0x7f: /* BIT 7,A */ test_bit(0x80, m_a); break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::res()
|
||||||
|
{
|
||||||
|
auto reset_bit = [this](uint32_t bit, uint32_t& register_) -> void {
|
||||||
|
// RES b,r8
|
||||||
|
m_wait_cycles += 8;
|
||||||
|
|
||||||
|
// Reset bit at position 'x' in register r8
|
||||||
|
register_ = register_ & (~bit);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto reset_bit_hl = [this](uint32_t bit) -> void {
|
||||||
|
// RES b,(HL)
|
||||||
|
m_wait_cycles += 16;
|
||||||
|
|
||||||
|
// Set bit at postition 'x' in the byte pointed by HL to 0
|
||||||
|
uint32_t data = read(hl());
|
||||||
|
data = data & (~bit);
|
||||||
|
write(hl(), data);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t opcode = pcRead();
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x40: /* RES 0,B */ reset_bit(0x01, m_b); break;
|
||||||
|
case 0x41: /* RES 0,C */ reset_bit(0x01, m_c); break;
|
||||||
|
case 0x42: /* RES 0,D */ reset_bit(0x01, m_d); break;
|
||||||
|
case 0x43: /* RES 0,E */ reset_bit(0x01, m_e); break;
|
||||||
|
case 0x44: /* RES 0,H */ reset_bit(0x01, m_h); break;
|
||||||
|
case 0x45: /* RES 0,L */ reset_bit(0x01, m_l); break;
|
||||||
|
case 0x46: /* RES 0,(HL) */ reset_bit_hl(0x01); break;
|
||||||
|
case 0x47: /* RES 0,A */ reset_bit(0x01, m_a); break;
|
||||||
|
|
||||||
|
case 0x48: /* RES 1,B */ reset_bit(0x02, m_b); break;
|
||||||
|
case 0x49: /* RES 1,C */ reset_bit(0x02, m_c); break;
|
||||||
|
case 0x4a: /* RES 1,D */ reset_bit(0x02, m_d); break;
|
||||||
|
case 0x4b: /* RES 1,E */ reset_bit(0x02, m_e); break;
|
||||||
|
case 0x4c: /* RES 1,H */ reset_bit(0x02, m_h); break;
|
||||||
|
case 0x4d: /* RES 1,L */ reset_bit(0x02, m_l); break;
|
||||||
|
case 0x4e: /* RES 1,(HL) */ reset_bit_hl(0x02); break;
|
||||||
|
case 0x4f: /* RES 1,A */ reset_bit(0x02, m_a); break;
|
||||||
|
|
||||||
|
case 0x50: /* RES 2,B */ reset_bit(0x04, m_b); break;
|
||||||
|
case 0x51: /* RES 2,C */ reset_bit(0x04, m_c); break;
|
||||||
|
case 0x52: /* RES 2,D */ reset_bit(0x04, m_d); break;
|
||||||
|
case 0x53: /* RES 2,E */ reset_bit(0x04, m_e); break;
|
||||||
|
case 0x54: /* RES 2,H */ reset_bit(0x04, m_h); break;
|
||||||
|
case 0x55: /* RES 2,L */ reset_bit(0x04, m_l); break;
|
||||||
|
case 0x56: /* RES 2,(HL) */ reset_bit_hl(0x04); break;
|
||||||
|
case 0x57: /* RES 2,A */ reset_bit(0x04, m_a); break;
|
||||||
|
|
||||||
|
case 0x58: /* RES 3,B */ reset_bit(0x08, m_b); break;
|
||||||
|
case 0x59: /* RES 3,C */ reset_bit(0x08, m_c); break;
|
||||||
|
case 0x5a: /* RES 3,D */ reset_bit(0x08, m_d); break;
|
||||||
|
case 0x5b: /* RES 3,E */ reset_bit(0x08, m_e); break;
|
||||||
|
case 0x5c: /* RES 3,H */ reset_bit(0x08, m_h); break;
|
||||||
|
case 0x5d: /* RES 3,L */ reset_bit(0x08, m_l); break;
|
||||||
|
case 0x5e: /* RES 3,(HL) */ reset_bit_hl(0x08); break;
|
||||||
|
case 0x5f: /* RES 3,A */ reset_bit(0x08, m_a); break;
|
||||||
|
|
||||||
|
case 0x60: /* RES 4,B */ reset_bit(0x10, m_b); break;
|
||||||
|
case 0x61: /* RES 4,C */ reset_bit(0x10, m_c); break;
|
||||||
|
case 0x62: /* RES 4,D */ reset_bit(0x10, m_d); break;
|
||||||
|
case 0x63: /* RES 4,E */ reset_bit(0x10, m_e); break;
|
||||||
|
case 0x64: /* RES 4,H */ reset_bit(0x10, m_h); break;
|
||||||
|
case 0x65: /* RES 4,L */ reset_bit(0x10, m_l); break;
|
||||||
|
case 0x66: /* RES 4,(HL) */ reset_bit_hl(0x10); break;
|
||||||
|
case 0x67: /* RES 4,A */ reset_bit(0x10, m_a); break;
|
||||||
|
|
||||||
|
case 0x68: /* RES 5,B */ reset_bit(0x20, m_b); break;
|
||||||
|
case 0x69: /* RES 5,C */ reset_bit(0x20, m_c); break;
|
||||||
|
case 0x6a: /* RES 5,D */ reset_bit(0x20, m_d); break;
|
||||||
|
case 0x6b: /* RES 5,E */ reset_bit(0x20, m_e); break;
|
||||||
|
case 0x6c: /* RES 5,H */ reset_bit(0x20, m_h); break;
|
||||||
|
case 0x6d: /* RES 5,L */ reset_bit(0x20, m_l); break;
|
||||||
|
case 0x6e: /* RES 5,(HL) */ reset_bit_hl(0x20); break;
|
||||||
|
case 0x6f: /* RES 5,A */ reset_bit(0x20, m_a); break;
|
||||||
|
|
||||||
|
case 0x70: /* RES 6,B */ reset_bit(0x40, m_b); break;
|
||||||
|
case 0x71: /* RES 6,C */ reset_bit(0x40, m_c); break;
|
||||||
|
case 0x72: /* RES 6,D */ reset_bit(0x40, m_d); break;
|
||||||
|
case 0x73: /* RES 6,E */ reset_bit(0x40, m_e); break;
|
||||||
|
case 0x74: /* RES 6,H */ reset_bit(0x40, m_h); break;
|
||||||
|
case 0x75: /* RES 6,L */ reset_bit(0x40, m_l); break;
|
||||||
|
case 0x76: /* RES 6,(HL) */ reset_bit_hl(0x40); break;
|
||||||
|
case 0x77: /* RES 6,A */ reset_bit(0x40, m_a); break;
|
||||||
|
|
||||||
|
case 0x78: /* RES 7,B */ reset_bit(0x80, m_b); break;
|
||||||
|
case 0x79: /* RES 7,C */ reset_bit(0x80, m_c); break;
|
||||||
|
case 0x7a: /* RES 7,D */ reset_bit(0x80, m_d); break;
|
||||||
|
case 0x7b: /* RES 7,E */ reset_bit(0x80, m_e); break;
|
||||||
|
case 0x7c: /* RES 7,H */ reset_bit(0x80, m_h); break;
|
||||||
|
case 0x7d: /* RES 7,L */ reset_bit(0x80, m_l); break;
|
||||||
|
case 0x7e: /* RES 7,(HL) */ reset_bit_hl(0x80); break;
|
||||||
|
case 0x7f: /* RES 7,A */ reset_bit(0x80, m_a); break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPU::set()
|
||||||
|
{
|
||||||
|
auto set_bit = [this](uint32_t bit, uint32_t& register_) -> void {
|
||||||
|
// RES b,r8
|
||||||
|
m_wait_cycles += 8;
|
||||||
|
|
||||||
|
// Set bit at position 'x' in register r8
|
||||||
|
register_ = register_ | bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto set_bit_hl = [this](uint32_t bit) -> void {
|
||||||
|
// RES b,(HL)
|
||||||
|
m_wait_cycles += 16;
|
||||||
|
|
||||||
|
// Set bit at postition 'x' in the byte pointed by HL to 0
|
||||||
|
uint32_t data = read(hl());
|
||||||
|
data = data | bit;
|
||||||
|
write(hl(), data);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t opcode = pcRead();
|
||||||
|
switch (opcode) {
|
||||||
|
case 0x40: /* SET 0,B */ set_bit(0x01, m_b); break;
|
||||||
|
case 0x41: /* SET 0,C */ set_bit(0x01, m_c); break;
|
||||||
|
case 0x42: /* SET 0,D */ set_bit(0x01, m_d); break;
|
||||||
|
case 0x43: /* SET 0,E */ set_bit(0x01, m_e); break;
|
||||||
|
case 0x44: /* SET 0,H */ set_bit(0x01, m_h); break;
|
||||||
|
case 0x45: /* SET 0,L */ set_bit(0x01, m_l); break;
|
||||||
|
case 0x46: /* SET 0,(HL) */ set_bit_hl(0x01); break;
|
||||||
|
case 0x47: /* SET 0,A */ set_bit(0x01, m_a); break;
|
||||||
|
|
||||||
|
case 0x48: /* SET 1,B */ set_bit(0x02, m_b); break;
|
||||||
|
case 0x49: /* SET 1,C */ set_bit(0x02, m_c); break;
|
||||||
|
case 0x4a: /* SET 1,D */ set_bit(0x02, m_d); break;
|
||||||
|
case 0x4b: /* SET 1,E */ set_bit(0x02, m_e); break;
|
||||||
|
case 0x4c: /* SET 1,H */ set_bit(0x02, m_h); break;
|
||||||
|
case 0x4d: /* SET 1,L */ set_bit(0x02, m_l); break;
|
||||||
|
case 0x4e: /* SET 1,(HL) */ set_bit_hl(0x02); break;
|
||||||
|
case 0x4f: /* SET 1,A */ set_bit(0x02, m_a); break;
|
||||||
|
|
||||||
|
case 0x50: /* SET 2,B */ set_bit(0x04, m_b); break;
|
||||||
|
case 0x51: /* SET 2,C */ set_bit(0x04, m_c); break;
|
||||||
|
case 0x52: /* SET 2,D */ set_bit(0x04, m_d); break;
|
||||||
|
case 0x53: /* SET 2,E */ set_bit(0x04, m_e); break;
|
||||||
|
case 0x54: /* SET 2,H */ set_bit(0x04, m_h); break;
|
||||||
|
case 0x55: /* SET 2,L */ set_bit(0x04, m_l); break;
|
||||||
|
case 0x56: /* SET 2,(HL) */ set_bit_hl(0x04); break;
|
||||||
|
case 0x57: /* SET 2,A */ set_bit(0x04, m_a); break;
|
||||||
|
|
||||||
|
case 0x58: /* SET 3,B */ set_bit(0x08, m_b); break;
|
||||||
|
case 0x59: /* SET 3,C */ set_bit(0x08, m_c); break;
|
||||||
|
case 0x5a: /* SET 3,D */ set_bit(0x08, m_d); break;
|
||||||
|
case 0x5b: /* SET 3,E */ set_bit(0x08, m_e); break;
|
||||||
|
case 0x5c: /* SET 3,H */ set_bit(0x08, m_h); break;
|
||||||
|
case 0x5d: /* SET 3,L */ set_bit(0x08, m_l); break;
|
||||||
|
case 0x5e: /* SET 3,(HL) */ set_bit_hl(0x08); break;
|
||||||
|
case 0x5f: /* SET 3,A */ set_bit(0x08, m_a); break;
|
||||||
|
|
||||||
|
case 0x60: /* SET 4,B */ set_bit(0x10, m_b); break;
|
||||||
|
case 0x61: /* SET 4,C */ set_bit(0x10, m_c); break;
|
||||||
|
case 0x62: /* SET 4,D */ set_bit(0x10, m_d); break;
|
||||||
|
case 0x63: /* SET 4,E */ set_bit(0x10, m_e); break;
|
||||||
|
case 0x64: /* SET 4,H */ set_bit(0x10, m_h); break;
|
||||||
|
case 0x65: /* SET 4,L */ set_bit(0x10, m_l); break;
|
||||||
|
case 0x66: /* SET 4,(HL) */ set_bit_hl(0x10); break;
|
||||||
|
case 0x67: /* SET 4,A */ set_bit(0x10, m_a); break;
|
||||||
|
|
||||||
|
case 0x68: /* SET 5,B */ set_bit(0x20, m_b); break;
|
||||||
|
case 0x69: /* SET 5,C */ set_bit(0x20, m_c); break;
|
||||||
|
case 0x6a: /* SET 5,D */ set_bit(0x20, m_d); break;
|
||||||
|
case 0x6b: /* SET 5,E */ set_bit(0x20, m_e); break;
|
||||||
|
case 0x6c: /* SET 5,H */ set_bit(0x20, m_h); break;
|
||||||
|
case 0x6d: /* SET 5,L */ set_bit(0x20, m_l); break;
|
||||||
|
case 0x6e: /* SET 5,(HL) */ set_bit_hl(0x20); break;
|
||||||
|
case 0x6f: /* SET 5,A */ set_bit(0x20, m_a); break;
|
||||||
|
|
||||||
|
case 0x70: /* SET 6,B */ set_bit(0x40, m_b); break;
|
||||||
|
case 0x71: /* SET 6,C */ set_bit(0x40, m_c); break;
|
||||||
|
case 0x72: /* SET 6,D */ set_bit(0x40, m_d); break;
|
||||||
|
case 0x73: /* SET 6,E */ set_bit(0x40, m_e); break;
|
||||||
|
case 0x74: /* SET 6,H */ set_bit(0x40, m_h); break;
|
||||||
|
case 0x75: /* SET 6,L */ set_bit(0x40, m_l); break;
|
||||||
|
case 0x76: /* SET 6,(HL) */ set_bit_hl(0x40); break;
|
||||||
|
case 0x77: /* SET 6,A */ set_bit(0x40, m_a); break;
|
||||||
|
|
||||||
|
case 0x78: /* SET 7,B */ set_bit(0x80, m_b); break;
|
||||||
|
case 0x79: /* SET 7,C */ set_bit(0x80, m_c); break;
|
||||||
|
case 0x7a: /* SET 7,D */ set_bit(0x80, m_d); break;
|
||||||
|
case 0x7b: /* SET 7,E */ set_bit(0x80, m_e); break;
|
||||||
|
case 0x7c: /* SET 7,H */ set_bit(0x80, m_h); break;
|
||||||
|
case 0x7d: /* SET 7,L */ set_bit(0x80, m_l); break;
|
||||||
|
case 0x7e: /* SET 7,(HL) */ set_bit_hl(0x80); break;
|
||||||
|
case 0x7f: /* RES 7,A */ set_bit(0x80, m_a); break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-2
@@ -64,7 +64,7 @@ void CPU::update()
|
|||||||
|
|
||||||
// Read next opcode
|
// Read next opcode
|
||||||
uint8_t opcode = read(m_pc);
|
uint8_t opcode = read(m_pc);
|
||||||
print("running opcode: {:#x}\n", opcode);
|
print("running opcode: {:#04x} @ ({:#06x})\n", opcode, m_pc);
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|
||||||
case 0x00: nop(); break;
|
case 0x00: nop(); break;
|
||||||
@@ -202,6 +202,7 @@ void CPU::update()
|
|||||||
case 0xc4: call(); break;
|
case 0xc4: call(); break;
|
||||||
case 0xc6: addi8(); break;
|
case 0xc6: addi8(); break;
|
||||||
case 0xc7: rst(); break;
|
case 0xc7: rst(); break;
|
||||||
|
case 0xcb: prefix(); break;
|
||||||
case 0xcc: call(); break;
|
case 0xcc: call(); break;
|
||||||
case 0xcd: call(); break;
|
case 0xcd: call(); break;
|
||||||
case 0xcf: rst(); break;
|
case 0xcf: rst(); break;
|
||||||
@@ -227,7 +228,7 @@ void CPU::update()
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
print("opcode {:#x} not implemented\n", opcode);
|
print("opcode {:#x} not implemented\n", opcode);
|
||||||
print("pc: {:#x}, immediate: {:#x}\n", m_pc, pcRead());
|
print("immediate: {:#04x}\n", m_pc, pcRead());
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ public:
|
|||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Bit Operations Instructions
|
// Bit Operations Instructions
|
||||||
|
|
||||||
|
void bit();
|
||||||
|
void res();
|
||||||
|
void set();
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
// Bit Shift Instructions
|
// Bit Shift Instructions
|
||||||
|
|
||||||
@@ -77,6 +81,7 @@ public:
|
|||||||
|
|
||||||
void misc();
|
void misc();
|
||||||
void nop();
|
void nop();
|
||||||
|
void prefix();
|
||||||
|
|
||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user