A more succinct definition of the LR35902 interrupt mechanism.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2017-12-12 22:29:37 +00:00
parent a1c753d63e
commit 697bfb636d
2 changed files with 34 additions and 33 deletions

View File

@ -281,40 +281,23 @@ void EightBit::GameBoy::LR35902::ccf(uint8_t& a, uint8_t& f) {
int EightBit::GameBoy::LR35902::singleStep() {
int current = 0;
const auto interruptEnable = m_bus.peek(IoRegisters::BASE + IoRegisters::IE);
const auto interruptEnable = BUS().peek(IoRegisters::BASE + IoRegisters::IE);
const auto interruptFlags = m_bus.IO().peek(IoRegisters::IF);
const auto ime = IME();
auto masked = interruptEnable & interruptFlags;
if (masked) {
if (ime) {
if (IME()) {
m_bus.IO().poke(IoRegisters::IF, 0);
lower(INT());
const int index = EightBit::findFirstSet(masked);
BUS().placeDATA(0x38 + (index << 3));
} else {
if (halted())
proceed();
}
}
if (ime && (masked & IoRegisters::Interrupts::VerticalBlank)) {
lower(INT());
BUS().placeDATA(0x40);
} else if (ime && (masked & IoRegisters::Interrupts::DisplayControlStatus)) {
lower(INT());
BUS().placeDATA(0x48);
} else if (ime && (masked & IoRegisters::Interrupts::TimerOverflow)) {
lower(INT());
BUS().placeDATA(0x50);
} else if (ime && (masked & IoRegisters::Interrupts::SerialTransfer)) {
lower(INT());
BUS().placeDATA(0x58);
} else if (ime && (masked & IoRegisters::Interrupts::KeypadPressed)) {
lower(INT());
BUS().placeDATA(0x60);
}
current += step();
const auto current = step();
m_bus.IO().checkTimers(current);
m_bus.IO().transferDma();
@ -653,7 +636,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
addCycles(2);
break;
case 4: // GB: LD (FF00 + n),A
m_bus.write(IoRegisters::BASE + fetchByte(), a);
BUS().write(IoRegisters::BASE + fetchByte(), a);
addCycles(3);
break;
case 5: { // GB: ADD SP,dd
@ -669,7 +652,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
addCycles(4);
break;
case 6: // GB: LD A,(FF00 + n)
a = m_bus.read(IoRegisters::BASE + fetchByte());
a = BUS().read(IoRegisters::BASE + fetchByte());
addCycles(3);
break;
case 7: { // GB: LD HL,SP + dd
@ -730,7 +713,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
addCycles(3);
break;
case 4: // GB: LD (FF00 + C),A
m_bus.write(IoRegisters::BASE + C(), a);
BUS().write(IoRegisters::BASE + C(), a);
addCycles(2);
break;
case 5: // GB: LD (nn),A
@ -739,7 +722,7 @@ void EightBit::GameBoy::LR35902::executeOther(int x, int y, int z, int p, int q)
addCycles(4);
break;
case 6: // GB: LD A,(FF00 + C)
a = m_bus.read(IoRegisters::BASE + C());
a = BUS().read(IoRegisters::BASE + C());
addCycles(2);
break;
case 7: // GB: LD A,(nn)

View File

@ -1,8 +1,17 @@
#pragma once
#ifdef _MSC_VER
# include <intrin.h>
#endif
#ifdef __GNUG__
# include <x86intrin.h>
#endif
namespace EightBit {
int countBits(uint8_t value);
bool oddParity(uint8_t value);
int findFirstSet(int value);
}
/*
@ -25,25 +34,34 @@ inline bool EightBit::oddParity(uint8_t value) {
return countBits(value) % 2;
}
inline int EightBit::findFirstSet(int value) {
#ifdef _MSC_VER
unsigned long index;
if (_BitScanForward(&index, value))
return index + 1;
return 0;
#elif defined(__GNUG__)
return __builtin_ffs(value);
#else
# error Find first set not implemented
#endif
}
# include <intrin.h>
#ifdef _MSC_VER
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
# define EIGHTBIT_PARITY(x) (__popcnt(x) % 2)
# define PARITY(x) (__popcnt(x) % 2)
# define UNREACHABLE __assume(0)
#elif defined(__GNUG__)
# include <x86intrin.h>
# define LIKELY(x) __builtin_expect(!!(x), 1)
# define UNLIKELY(x) __builtin_expect(!!(x), 0)
# define EIGHTBIT_PARITY(x) __builtin_parity(value)
# define PARITY(x) __builtin_parity(value)
# define UNREACHABLE __builtin_unreachable();
@ -52,7 +70,7 @@ inline bool EightBit::oddParity(uint8_t value) {
# define LIKELY(x) (x)
# define UNLIKELY(x) (x)
# define EIGHTBIT_PARITY(x) EightBit::oddParity(x)
# define PARITY(x) EightBit::oddParity(x)
# define UNREACHABLE