Emulator: Add isCarry() function to CPU
This commit is contained in:
+51
-13
@@ -5,7 +5,7 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdint> // int32_t, uint8_t, uint32_t
|
#include <cstdint> // uint8_t, uint32_t
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
@@ -113,13 +113,15 @@ void CPU::add()
|
|||||||
m_wait_cycles += 8;
|
m_wait_cycles += 8;
|
||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
m_zf = m_a + immediate == 0;
|
|
||||||
m_nf = 0;
|
m_nf = 0;
|
||||||
m_hf = m_a + immediate > 16;
|
m_hf = isCarry(m_a, immediate, 0x10);
|
||||||
m_cf = m_a + immediate > 255;
|
m_cf = isCarry(m_a, immediate, 0x100);
|
||||||
|
|
||||||
// A = A + r
|
// A = A + r
|
||||||
m_a = (m_a + immediate) & 0x00ff;
|
m_a = (m_a + immediate) & 0xff;
|
||||||
|
|
||||||
|
// Zero flag
|
||||||
|
m_zf = m_a == 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
@@ -134,13 +136,15 @@ void CPU::dec8()
|
|||||||
// DEC C, flags: Z 1 H -
|
// DEC C, flags: Z 1 H -
|
||||||
m_wait_cycles += 4;
|
m_wait_cycles += 4;
|
||||||
|
|
||||||
m_c = (m_c - 1) & 0x00ff;
|
|
||||||
|
|
||||||
// Set flags
|
// Set flags
|
||||||
// TODO
|
|
||||||
// m_zf = ?
|
|
||||||
m_nf = 1;
|
m_nf = 1;
|
||||||
// m_hf = ?
|
m_hf = isCarry(m_c, -1, 0x10);
|
||||||
|
|
||||||
|
// C = C - 1
|
||||||
|
m_c = (m_c - 1) & 0xff;
|
||||||
|
|
||||||
|
// Zero flag
|
||||||
|
m_zf = m_c == 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -355,10 +359,16 @@ void CPU::ld16()
|
|||||||
m_wait_cycles += 12;
|
m_wait_cycles += 12;
|
||||||
|
|
||||||
// Put SP + next (signed) byte in memory into HL
|
// Put SP + next (signed) byte in memory into HL
|
||||||
// TODO
|
uint32_t signed_data = (pcRead() ^ 0x80) - 0x80;
|
||||||
|
uint32_t sum = m_sp + signed_data;
|
||||||
|
m_h = sum >> 8;
|
||||||
|
m_l = sum & 0xff;
|
||||||
|
|
||||||
// Unsets ZF and NF, may enable HF and CF
|
// Set flags
|
||||||
// TODO flags
|
m_zf = 0;
|
||||||
|
m_nf = 0;
|
||||||
|
m_hf = isCarry(m_sp, signed_data, 0x10);
|
||||||
|
m_cf = isCarry(m_sp, signed_data, 0x100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xf9: {
|
case 0xf9: {
|
||||||
@@ -479,6 +489,34 @@ uint32_t CPU::ffRead(uint32_t address)
|
|||||||
return Emu::the().readMemory(address | (0xff << 8)) & 0x00ff;
|
return Emu::the().readMemory(address | (0xff << 8)) & 0x00ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CPU::isCarry(uint32_t lhs, uint32_t rhs, uint32_t limit_bit)
|
||||||
|
{
|
||||||
|
// limit_bit values:
|
||||||
|
// 8-bit half-carry = 0x10 or 16
|
||||||
|
// 8-bit carry = 0x100 or 256
|
||||||
|
// 16-bit half-carry = 0x1000 or 4096
|
||||||
|
// 16-bit carry = 0x10000 or 65536
|
||||||
|
|
||||||
|
// Example for 8-bit half-carry:
|
||||||
|
// 0b00111110 62 | 0b00111000 56
|
||||||
|
// 0b00100010 34 + | 0b00010001 17 +
|
||||||
|
// --------------- | ---------------
|
||||||
|
// 0b01100000 96 | 0b01001001 73
|
||||||
|
// |
|
||||||
|
// 0b00111110 62 | 0b00111000 56
|
||||||
|
// 0b00100010 34 ^ | 0b00010001 17 ^
|
||||||
|
// --------------- | ---------------
|
||||||
|
// 0b00011100 | 0b00101001
|
||||||
|
// 0b01100000 96 ^ | 0b01001001 73 ^
|
||||||
|
// --------------- | ---------------
|
||||||
|
// 0b01111100 | 0b01100000
|
||||||
|
// 0b00010000 16 & | 0b00010000 16 &
|
||||||
|
// --------------- | ---------------
|
||||||
|
// 0b00010000 = true! | 0b00000000 = false!
|
||||||
|
|
||||||
|
return (lhs ^ rhs ^ (lhs + rhs)) & limit_bit;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void Formatter<CPU>::parse(Parser& parser)
|
void Formatter<CPU>::parse(Parser& parser)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // int8_t, int32_t, uint8_t, uint32_t
|
#include <cstdint> // int8_t, uint8_t, uint32_t
|
||||||
#include <functional> // std::function
|
#include <functional> // std::function
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -81,6 +81,8 @@ private:
|
|||||||
void ffWrite(uint32_t address, uint32_t value);
|
void ffWrite(uint32_t address, uint32_t value);
|
||||||
uint32_t ffRead(uint32_t address);
|
uint32_t ffRead(uint32_t address);
|
||||||
|
|
||||||
|
bool isCarry(uint32_t lhs, uint32_t rhs, uint32_t limit_bit);
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
uint32_t m_a { 0 }; // Accumulator
|
uint32_t m_a { 0 }; // Accumulator
|
||||||
uint32_t m_b { 0 }; // B
|
uint32_t m_b { 0 }; // B
|
||||||
|
|||||||
Reference in New Issue
Block a user