mirror of https://github.com/mgba-emu/mgba.git
GB: Revamp IRQ handling based on new information
This commit is contained in:
parent
148e7cd0b5
commit
a949fdfced
1
CHANGES
1
CHANGES
|
@ -44,6 +44,7 @@ Bugfixes:
|
|||
- GBA Video: Fix broken sprite blending hack (fixes mgba.io/i/532)
|
||||
- GBA I/O: Fix reading from a few invalid I/O registers (fixes mgba.io/i/876)
|
||||
- GBA Savedata: Fix size of SRAM saves (fixes mgba.io/i/883)
|
||||
- GB: Revamp IRQ handling based on new information
|
||||
Misc:
|
||||
- GBA Timer: Use global cycles for timers
|
||||
- GBA: Extend oddly-sized ROMs to full address space (fixes mgba.io/i/722)
|
||||
|
|
|
@ -42,7 +42,7 @@ mLOG_DECLARE_CATEGORY(GB_STATE);
|
|||
* | 0x00036 - 0x00037: Index address
|
||||
* | 0x00038: Bus value
|
||||
* | 0x00039: Execution state
|
||||
* | 0x0003A - 0x0003B: IRQ vector
|
||||
* | 0x0003A - 0x0003B: Reserved
|
||||
* | 0x0003C - 0x0003F: EI pending cycles
|
||||
* | 0x00040 - 0x00043: Reserved (DI pending cycles)
|
||||
* | 0x00044 - 0x00047: Flags
|
||||
|
@ -287,7 +287,7 @@ struct GBSerializedState {
|
|||
uint8_t bus;
|
||||
uint8_t executionState;
|
||||
|
||||
uint16_t irqVector;
|
||||
uint16_t reserved;
|
||||
|
||||
uint32_t eiPending;
|
||||
int32_t reservedDiPending;
|
||||
|
|
|
@ -66,6 +66,7 @@ struct LR35902InterruptHandler {
|
|||
void (*reset)(struct LR35902Core* cpu);
|
||||
void (*processEvents)(struct LR35902Core* cpu);
|
||||
void (*setInterrupts)(struct LR35902Core* cpu, bool enable);
|
||||
uint16_t (*irqVector)(struct LR35902Core* cpu);
|
||||
void (*halt)(struct LR35902Core* cpu);
|
||||
void (*stop)(struct LR35902Core* cpu);
|
||||
|
||||
|
@ -118,7 +119,6 @@ struct LR35902Core {
|
|||
LR35902Instruction instruction;
|
||||
|
||||
bool irqPending;
|
||||
uint16_t irqVector;
|
||||
|
||||
struct LR35902Memory memory;
|
||||
struct LR35902InterruptHandler irqh;
|
||||
|
@ -136,7 +136,7 @@ void LR35902HotplugAttach(struct LR35902Core* cpu, size_t slot);
|
|||
void LR35902HotplugDetach(struct LR35902Core* cpu, size_t slot);
|
||||
|
||||
void LR35902Reset(struct LR35902Core* cpu);
|
||||
void LR35902RaiseIRQ(struct LR35902Core* cpu, uint8_t vector);
|
||||
void LR35902RaiseIRQ(struct LR35902Core* cpu);
|
||||
|
||||
void LR35902Tick(struct LR35902Core* cpu);
|
||||
void LR35902Run(struct LR35902Core* cpu);
|
||||
|
|
55
src/gb/gb.c
55
src/gb/gb.c
|
@ -39,6 +39,7 @@ static void GBDeinit(struct mCPUComponent* component);
|
|||
static void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh);
|
||||
static void GBProcessEvents(struct LR35902Core* cpu);
|
||||
static void GBSetInterrupts(struct LR35902Core* cpu, bool enable);
|
||||
static uint16_t GBIRQVector(struct LR35902Core* cpu);
|
||||
static void GBIllegal(struct LR35902Core* cpu);
|
||||
static void GBStop(struct LR35902Core* cpu);
|
||||
|
||||
|
@ -371,6 +372,7 @@ void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
|
|||
irqh->reset = GBReset;
|
||||
irqh->processEvents = GBProcessEvents;
|
||||
irqh->setInterrupts = GBSetInterrupts;
|
||||
irqh->irqVector = GBIRQVector;
|
||||
irqh->hitIllegal = GBIllegal;
|
||||
irqh->stop = GBStop;
|
||||
irqh->halt = GBHalt;
|
||||
|
@ -596,31 +598,7 @@ void GBUpdateIRQs(struct GB* gb) {
|
|||
if (!gb->memory.ime || gb->cpu->irqPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (irqs & (1 << GB_IRQ_VBLANK)) {
|
||||
LR35902RaiseIRQ(gb->cpu, GB_VECTOR_VBLANK);
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_VBLANK);
|
||||
return;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_LCDSTAT)) {
|
||||
LR35902RaiseIRQ(gb->cpu, GB_VECTOR_LCDSTAT);
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_LCDSTAT);
|
||||
return;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_TIMER)) {
|
||||
LR35902RaiseIRQ(gb->cpu, GB_VECTOR_TIMER);
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER);
|
||||
return;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_SIO)) {
|
||||
LR35902RaiseIRQ(gb->cpu, GB_VECTOR_SIO);
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_SIO);
|
||||
return;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_KEYPAD)) {
|
||||
LR35902RaiseIRQ(gb->cpu, GB_VECTOR_KEYPAD);
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_KEYPAD);
|
||||
}
|
||||
LR35902RaiseIRQ(gb->cpu);
|
||||
}
|
||||
|
||||
void GBProcessEvents(struct LR35902Core* cpu) {
|
||||
|
@ -663,6 +641,33 @@ void GBSetInterrupts(struct LR35902Core* cpu, bool enable) {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t GBIRQVector(struct LR35902Core* cpu) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
int irqs = gb->memory.ie & gb->memory.io[REG_IF];
|
||||
|
||||
if (irqs & (1 << GB_IRQ_VBLANK)) {
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_VBLANK);
|
||||
return GB_VECTOR_VBLANK;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_LCDSTAT)) {
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_LCDSTAT);
|
||||
return GB_VECTOR_LCDSTAT;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_TIMER)) {
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_TIMER);
|
||||
return GB_VECTOR_TIMER;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_SIO)) {
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_SIO);
|
||||
return GB_VECTOR_SIO;
|
||||
}
|
||||
if (irqs & (1 << GB_IRQ_KEYPAD)) {
|
||||
gb->memory.io[REG_IF] &= ~(1 << GB_IRQ_KEYPAD);
|
||||
return GB_VECTOR_KEYPAD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cyclesLate) {
|
||||
UNUSED(timing);
|
||||
UNUSED(cyclesLate);
|
||||
|
|
|
@ -47,7 +47,6 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) {
|
|||
STORE_16LE(gb->cpu->index, 0, &state->cpu.index);
|
||||
state->cpu.bus = gb->cpu->bus;
|
||||
state->cpu.executionState = gb->cpu->executionState;
|
||||
STORE_16LE(gb->cpu->irqVector, 0, &state->cpu.irqVector);
|
||||
|
||||
GBSerializedCpuFlags flags = 0;
|
||||
flags = GBSerializedCpuFlagsSetCondition(flags, gb->cpu->condition);
|
||||
|
@ -154,7 +153,6 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) {
|
|||
LOAD_16LE(gb->cpu->index, 0, &state->cpu.index);
|
||||
gb->cpu->bus = state->cpu.bus;
|
||||
gb->cpu->executionState = state->cpu.executionState;
|
||||
LOAD_16LE(gb->cpu->irqVector, 0, &state->cpu.irqVector);
|
||||
|
||||
GBSerializedCpuFlags flags;
|
||||
LOAD_32LE(flags, 0, &state->cpu.flags);
|
||||
|
|
|
@ -70,9 +70,8 @@ void LR35902Reset(struct LR35902Core* cpu) {
|
|||
cpu->irqh.reset(cpu);
|
||||
}
|
||||
|
||||
void LR35902RaiseIRQ(struct LR35902Core* cpu, uint8_t vector) {
|
||||
void LR35902RaiseIRQ(struct LR35902Core* cpu) {
|
||||
cpu->irqPending = true;
|
||||
cpu->irqVector = vector;
|
||||
}
|
||||
|
||||
static void _LR35902InstructionIRQStall(struct LR35902Core* cpu) {
|
||||
|
@ -85,18 +84,19 @@ static void _LR35902InstructionIRQFinish(struct LR35902Core* cpu) {
|
|||
}
|
||||
|
||||
static void _LR35902InstructionIRQDelay(struct LR35902Core* cpu) {
|
||||
cpu->index = cpu->sp + 1;
|
||||
cpu->bus = cpu->pc >> 8;
|
||||
--cpu->sp;
|
||||
cpu->index = cpu->sp;
|
||||
cpu->bus = cpu->pc;
|
||||
cpu->executionState = LR35902_CORE_MEMORY_STORE;
|
||||
cpu->instruction = _LR35902InstructionIRQFinish;
|
||||
cpu->pc = cpu->irqVector;
|
||||
cpu->pc = cpu->irqh.irqVector(cpu);
|
||||
cpu->memory.setActiveRegion(cpu, cpu->pc);
|
||||
}
|
||||
|
||||
static void _LR35902InstructionIRQ(struct LR35902Core* cpu) {
|
||||
cpu->sp -= 2; /* TODO: Atomic incrementing? */
|
||||
--cpu->sp;
|
||||
cpu->index = cpu->sp;
|
||||
cpu->bus = cpu->pc;
|
||||
cpu->bus = cpu->pc >> 8;
|
||||
cpu->executionState = LR35902_CORE_MEMORY_STORE;
|
||||
cpu->instruction = _LR35902InstructionIRQDelay;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 518 B |
Binary file not shown.
|
@ -0,0 +1,282 @@
|
|||
; this file was created with wlalink by ville helin <vhelin@iki.fi>.
|
||||
; wla symbolic information for "/Users/vicki/Scratch/mooneye-gb/tests/build/acceptance/interrupts/ie_push.gb".
|
||||
|
||||
[labels]
|
||||
01:4bff print_load_font
|
||||
01:4c0c print_string
|
||||
01:4c16 print_a
|
||||
01:4c20 print_newline
|
||||
01:4c2b print_digit
|
||||
01:4c38 print_regs
|
||||
01:4c41 _print_sl_data0
|
||||
01:4c47 _print_sl_out0
|
||||
01:4c54 _print_sl_data1
|
||||
01:4c5a _print_sl_out1
|
||||
01:4c6c _print_sl_data2
|
||||
01:4c72 _print_sl_out2
|
||||
01:4c7f _print_sl_data3
|
||||
01:4c85 _print_sl_out3
|
||||
01:4c97 _print_sl_data4
|
||||
01:4c9d _print_sl_out4
|
||||
01:4caa _print_sl_data5
|
||||
01:4cb0 _print_sl_out5
|
||||
01:4cc2 _print_sl_data6
|
||||
01:4cc8 _print_sl_out6
|
||||
01:4cd5 _print_sl_data7
|
||||
01:4cdb _print_sl_out7
|
||||
01:4000 font
|
||||
00:c000 regs_save
|
||||
00:c000 regs_save.f
|
||||
00:c001 regs_save.a
|
||||
00:c002 regs_save.c
|
||||
00:c003 regs_save.b
|
||||
00:c004 regs_save.e
|
||||
00:c005 regs_save.d
|
||||
00:c006 regs_save.l
|
||||
00:c007 regs_save.h
|
||||
00:c008 regs_flags
|
||||
00:c009 regs_assert
|
||||
00:c009 regs_assert.f
|
||||
00:c00a regs_assert.a
|
||||
00:c00b regs_assert.c
|
||||
00:c00c regs_assert.b
|
||||
00:c00d regs_assert.e
|
||||
00:c00e regs_assert.d
|
||||
00:c00f regs_assert.l
|
||||
00:c010 regs_assert.h
|
||||
00:c011 memdump_len
|
||||
00:c012 memdump_addr
|
||||
01:47f0 memcpy
|
||||
01:47f9 memset
|
||||
01:4802 memcmp
|
||||
01:4810 clear_vram
|
||||
01:481a clear_oam
|
||||
01:4824 disable_lcd_safe
|
||||
01:482a _wait_ly_0
|
||||
01:4830 _wait_ly_1
|
||||
01:4839 reset_screen
|
||||
01:484d process_results
|
||||
01:4861 _wait_ly_2
|
||||
01:4867 _wait_ly_3
|
||||
01:487d _print_results_halt_0
|
||||
01:4880 _process_results_cb
|
||||
01:488b _print_sl_data8
|
||||
01:4895 _print_sl_out8
|
||||
01:48af _print_sl_data9
|
||||
01:48ba _print_sl_out9
|
||||
01:48d2 _print_sl_data10
|
||||
01:48de _print_sl_out10
|
||||
01:48df dump_mem
|
||||
01:48fe _dump_mem_line
|
||||
01:4928 _check_asserts
|
||||
01:4936 _print_sl_data11
|
||||
01:4939 _print_sl_out11
|
||||
01:4945 _print_sl_data12
|
||||
01:4947 _print_sl_out12
|
||||
01:494f _print_sl_data13
|
||||
01:4952 _print_sl_out13
|
||||
01:495c __check_assert_fail0
|
||||
01:4967 _print_sl_data14
|
||||
01:496a _print_sl_out14
|
||||
01:496d __check_assert_ok0
|
||||
01:4975 _print_sl_data15
|
||||
01:497a _print_sl_out15
|
||||
01:497c __check_assert_skip0
|
||||
01:4984 _print_sl_data16
|
||||
01:498c _print_sl_out16
|
||||
01:498c __check_assert_out0
|
||||
01:4998 _print_sl_data17
|
||||
01:499a _print_sl_out17
|
||||
01:49a2 _print_sl_data18
|
||||
01:49a5 _print_sl_out18
|
||||
01:49af __check_assert_fail1
|
||||
01:49ba _print_sl_data19
|
||||
01:49bd _print_sl_out19
|
||||
01:49c0 __check_assert_ok1
|
||||
01:49c8 _print_sl_data20
|
||||
01:49cd _print_sl_out20
|
||||
01:49cf __check_assert_skip1
|
||||
01:49d7 _print_sl_data21
|
||||
01:49df _print_sl_out21
|
||||
01:49df __check_assert_out1
|
||||
01:49ea _print_sl_data22
|
||||
01:49ed _print_sl_out22
|
||||
01:49f9 _print_sl_data23
|
||||
01:49fb _print_sl_out23
|
||||
01:4a03 _print_sl_data24
|
||||
01:4a06 _print_sl_out24
|
||||
01:4a10 __check_assert_fail2
|
||||
01:4a1b _print_sl_data25
|
||||
01:4a1e _print_sl_out25
|
||||
01:4a21 __check_assert_ok2
|
||||
01:4a29 _print_sl_data26
|
||||
01:4a2e _print_sl_out26
|
||||
01:4a30 __check_assert_skip2
|
||||
01:4a38 _print_sl_data27
|
||||
01:4a40 _print_sl_out27
|
||||
01:4a40 __check_assert_out2
|
||||
01:4a4c _print_sl_data28
|
||||
01:4a4e _print_sl_out28
|
||||
01:4a56 _print_sl_data29
|
||||
01:4a59 _print_sl_out29
|
||||
01:4a63 __check_assert_fail3
|
||||
01:4a6e _print_sl_data30
|
||||
01:4a71 _print_sl_out30
|
||||
01:4a74 __check_assert_ok3
|
||||
01:4a7c _print_sl_data31
|
||||
01:4a81 _print_sl_out31
|
||||
01:4a83 __check_assert_skip3
|
||||
01:4a8b _print_sl_data32
|
||||
01:4a93 _print_sl_out32
|
||||
01:4a93 __check_assert_out3
|
||||
01:4a9e _print_sl_data33
|
||||
01:4aa1 _print_sl_out33
|
||||
01:4aad _print_sl_data34
|
||||
01:4aaf _print_sl_out34
|
||||
01:4ab7 _print_sl_data35
|
||||
01:4aba _print_sl_out35
|
||||
01:4ac4 __check_assert_fail4
|
||||
01:4acf _print_sl_data36
|
||||
01:4ad2 _print_sl_out36
|
||||
01:4ad5 __check_assert_ok4
|
||||
01:4add _print_sl_data37
|
||||
01:4ae2 _print_sl_out37
|
||||
01:4ae4 __check_assert_skip4
|
||||
01:4aec _print_sl_data38
|
||||
01:4af4 _print_sl_out38
|
||||
01:4af4 __check_assert_out4
|
||||
01:4b00 _print_sl_data39
|
||||
01:4b02 _print_sl_out39
|
||||
01:4b0a _print_sl_data40
|
||||
01:4b0d _print_sl_out40
|
||||
01:4b17 __check_assert_fail5
|
||||
01:4b22 _print_sl_data41
|
||||
01:4b25 _print_sl_out41
|
||||
01:4b28 __check_assert_ok5
|
||||
01:4b30 _print_sl_data42
|
||||
01:4b35 _print_sl_out42
|
||||
01:4b37 __check_assert_skip5
|
||||
01:4b3f _print_sl_data43
|
||||
01:4b47 _print_sl_out43
|
||||
01:4b47 __check_assert_out5
|
||||
01:4b52 _print_sl_data44
|
||||
01:4b55 _print_sl_out44
|
||||
01:4b61 _print_sl_data45
|
||||
01:4b63 _print_sl_out45
|
||||
01:4b6b _print_sl_data46
|
||||
01:4b6e _print_sl_out46
|
||||
01:4b78 __check_assert_fail6
|
||||
01:4b83 _print_sl_data47
|
||||
01:4b86 _print_sl_out47
|
||||
01:4b89 __check_assert_ok6
|
||||
01:4b91 _print_sl_data48
|
||||
01:4b96 _print_sl_out48
|
||||
01:4b98 __check_assert_skip6
|
||||
01:4ba0 _print_sl_data49
|
||||
01:4ba8 _print_sl_out49
|
||||
01:4ba8 __check_assert_out6
|
||||
01:4bb4 _print_sl_data50
|
||||
01:4bb6 _print_sl_out50
|
||||
01:4bbe _print_sl_data51
|
||||
01:4bc1 _print_sl_out51
|
||||
01:4bcb __check_assert_fail7
|
||||
01:4bd6 _print_sl_data52
|
||||
01:4bd9 _print_sl_out52
|
||||
01:4bdc __check_assert_ok7
|
||||
01:4be4 _print_sl_data53
|
||||
01:4be9 _print_sl_out53
|
||||
01:4beb __check_assert_skip7
|
||||
01:4bf3 _print_sl_data54
|
||||
01:4bfb _print_sl_out54
|
||||
01:4bfb __check_assert_out7
|
||||
00:0200 round1
|
||||
00:0214 finish_round1
|
||||
00:021d round2
|
||||
00:0224 round3
|
||||
00:0235 target
|
||||
00:0238 finish_round3
|
||||
00:023f round4
|
||||
00:0253 finish_round4
|
||||
00:0270 _wait_ly_4
|
||||
00:0276 _wait_ly_5
|
||||
00:028c _print_results_halt_1
|
||||
00:028f _test_ok_cb_0
|
||||
00:0297 _print_sl_data55
|
||||
00:029f _print_sl_out55
|
||||
00:1000 fail_round1_nointr
|
||||
00:1017 _wait_ly_6
|
||||
00:101d _wait_ly_7
|
||||
00:1033 _print_results_halt_2
|
||||
00:1036 _test_failure_cb_0
|
||||
00:103e _print_sl_data56
|
||||
00:104f _print_sl_out56
|
||||
00:1052 fail_round1_nocancel
|
||||
00:1069 _wait_ly_8
|
||||
00:106f _wait_ly_9
|
||||
00:1085 _print_results_halt_3
|
||||
00:1088 _test_failure_cb_1
|
||||
00:1090 _print_sl_data57
|
||||
00:10a2 _print_sl_out57
|
||||
00:10a5 fail_round1_if
|
||||
00:10bc _wait_ly_10
|
||||
00:10c2 _wait_ly_11
|
||||
00:10d8 _print_results_halt_4
|
||||
00:10db _test_failure_cb_2
|
||||
00:10e3 _print_sl_data58
|
||||
00:10f3 _print_sl_out58
|
||||
00:10f6 fail_round2_intr
|
||||
00:110d _wait_ly_12
|
||||
00:1113 _wait_ly_13
|
||||
00:1129 _print_results_halt_5
|
||||
00:112c _test_failure_cb_3
|
||||
00:1134 _print_sl_data59
|
||||
00:1146 _print_sl_out59
|
||||
00:1149 fail_round3_nointr
|
||||
00:1160 _wait_ly_14
|
||||
00:1166 _wait_ly_15
|
||||
00:117c _print_results_halt_6
|
||||
00:117f _test_failure_cb_4
|
||||
00:1187 _print_sl_data60
|
||||
00:1198 _print_sl_out60
|
||||
00:119b fail_round3_cancel
|
||||
00:11b2 _wait_ly_16
|
||||
00:11b8 _wait_ly_17
|
||||
00:11ce _print_results_halt_7
|
||||
00:11d1 _test_failure_cb_5
|
||||
00:11d9 _print_sl_data61
|
||||
00:11ed _print_sl_out61
|
||||
00:11f0 fail_round3_if
|
||||
00:1207 _wait_ly_18
|
||||
00:120d _wait_ly_19
|
||||
00:1223 _print_results_halt_8
|
||||
00:1226 _test_failure_cb_6
|
||||
00:122e _print_sl_data62
|
||||
00:123e _print_sl_out62
|
||||
00:1241 fail_round4_nointr
|
||||
00:1258 _wait_ly_20
|
||||
00:125e _wait_ly_21
|
||||
00:1274 _print_results_halt_9
|
||||
00:1277 _test_failure_cb_7
|
||||
00:127f _print_sl_data63
|
||||
00:1290 _print_sl_out63
|
||||
00:1293 fail_round4_cancel
|
||||
00:12aa _wait_ly_22
|
||||
00:12b0 _wait_ly_23
|
||||
00:12c6 _print_results_halt_10
|
||||
00:12c9 _test_failure_cb_8
|
||||
00:12d1 _print_sl_data64
|
||||
00:12e5 _print_sl_out64
|
||||
00:12e8 fail_round4_if
|
||||
00:12ff _wait_ly_24
|
||||
00:1305 _wait_ly_25
|
||||
00:131b _print_results_halt_11
|
||||
00:131e _test_failure_cb_9
|
||||
00:1326 _print_sl_data65
|
||||
00:1333 _print_sl_out65
|
||||
00:1336 fail_round4_vblank
|
||||
00:134d _wait_ly_26
|
||||
00:1353 _wait_ly_27
|
||||
00:1369 _print_results_halt_12
|
||||
00:136c _test_failure_cb_10
|
||||
00:1374 _print_sl_data66
|
||||
00:1383 _print_sl_out66
|
Loading…
Reference in New Issue