/* Copyright (c) 2013-2016 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "isa-lr35902.h" #include "lr35902/emitter-lr35902.h" #include "lr35902/lr35902.h" #define DEFINE_INSTRUCTION_LR35902(NAME, BODY) \ static void _LR35902Instruction ## NAME (struct LR35902Core* cpu) { \ UNUSED(cpu); \ BODY; \ } DEFINE_INSTRUCTION_LR35902(NOP,); #define DEFINE_CONDITIONAL_INSTRUCTION_LR35902(NAME) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(, true) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->f.c) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Z, cpu->f.z) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(NC, !cpu->f.c) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(NZ, !cpu->f.z) DEFINE_INSTRUCTION_LR35902(JPFinish, if (cpu->condition) { cpu->pc = (cpu->bus << 8) | cpu->index; cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->executionState = LR35902_CORE_STALL; }) DEFINE_INSTRUCTION_LR35902(JPDelay, cpu->executionState = LR35902_CORE_READ_PC; cpu->instruction = _LR35902InstructionJPFinish; cpu->index = cpu->bus;) #define DEFINE_JP_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \ DEFINE_INSTRUCTION_LR35902(JP ## CONDITION_NAME, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionJPDelay; \ cpu->condition = CONDITION;) DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JP); DEFINE_INSTRUCTION_LR35902(JPHL, cpu->pc = LR35902ReadHL(cpu); cpu->memory.setActiveRegion(cpu, cpu->pc);) DEFINE_INSTRUCTION_LR35902(JRFinish, if (cpu->condition) { cpu->pc += (int8_t) cpu->bus; cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->executionState = LR35902_CORE_STALL; }) #define DEFINE_JR_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \ DEFINE_INSTRUCTION_LR35902(JR ## CONDITION_NAME, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionJRFinish; \ cpu->condition = CONDITION;) DEFINE_CONDITIONAL_INSTRUCTION_LR35902(JR); DEFINE_INSTRUCTION_LR35902(CALLFinish, if (cpu->condition) { cpu->pc = (cpu->bus << 8) | cpu->index; cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->executionState = LR35902_CORE_STALL; }) DEFINE_INSTRUCTION_LR35902(CALLUpdatePC, cpu->executionState = LR35902_CORE_READ_PC; cpu->index = cpu->bus; cpu->instruction = _LR35902InstructionCALLFinish;) DEFINE_INSTRUCTION_LR35902(CALLUpdateSPL, cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionCALLUpdatePC;) DEFINE_INSTRUCTION_LR35902(CALLUpdateSPH, cpu->index = cpu->sp + 1; cpu->bus = (cpu->pc + 2) >> 8; cpu->executionState = LR35902_CORE_MEMORY_STORE; cpu->instruction = _LR35902InstructionCALLUpdateSPL;) #define DEFINE_CALL_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \ DEFINE_INSTRUCTION_LR35902(CALL ## CONDITION_NAME, \ cpu->condition = CONDITION; \ if (CONDITION) { \ cpu->sp -= 2; /* TODO: Atomic incrementing? */ \ cpu->index = cpu->sp; \ cpu->bus = cpu->pc + 2; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionCALLUpdateSPH; \ } else { \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionCALLUpdatePC; \ }) DEFINE_CONDITIONAL_INSTRUCTION_LR35902(CALL) DEFINE_INSTRUCTION_LR35902(RETUpdateSPL, cpu->pc |= cpu->bus << 8; cpu->sp += 2; /* TODO: Atomic incrementing? */ cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->executionState = LR35902_CORE_STALL;) DEFINE_INSTRUCTION_LR35902(RETUpdateSPH, if (cpu->condition) { cpu->index = cpu->sp + 1; cpu->pc = cpu->bus; cpu->executionState = LR35902_CORE_MEMORY_LOAD; cpu->instruction = _LR35902InstructionRETUpdateSPL; }) #define DEFINE_RET_INSTRUCTION_LR35902(CONDITION_NAME, CONDITION) \ DEFINE_INSTRUCTION_LR35902(RET ## CONDITION_NAME, \ cpu->condition = CONDITION; \ cpu->index = cpu->sp; \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionRETUpdateSPH;) DEFINE_INSTRUCTION_LR35902(RETI, cpu->condition = true; cpu->index = cpu->sp; cpu->executionState = LR35902_CORE_MEMORY_LOAD; cpu->irqh.setInterrupts(cpu, true); cpu->instruction = _LR35902InstructionRETUpdateSPH;) DEFINE_CONDITIONAL_INSTRUCTION_LR35902(RET) #define DEFINE_AND_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(AND ## NAME, \ cpu->a &= OPERAND; \ cpu->f.z = !cpu->a; \ cpu->f.n = 0; \ cpu->f.c = 0; \ cpu->f.h = 1;) #define DEFINE_XOR_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(XOR ## NAME, \ cpu->a ^= OPERAND; \ cpu->f.z = !cpu->a; \ cpu->f.n = 0; \ cpu->f.c = 0; \ cpu->f.h = 0;) #define DEFINE_OR_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(OR ## NAME, \ cpu->a |= OPERAND; \ cpu->f.z = !cpu->a; \ cpu->f.n = 0; \ cpu->f.c = 0; \ cpu->f.h = 0;) #define DEFINE_CP_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(CP ## NAME, \ int diff = cpu->a - OPERAND; \ cpu->f.n = 1; \ cpu->f.z = !diff; \ cpu->f.c = diff < 0; \ /* TODO: Find explanation of H flag */) #define DEFINE_LDB__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDB_ ## NAME, \ cpu->b = OPERAND;) #define DEFINE_LDC__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDC_ ## NAME, \ cpu->c = OPERAND;) #define DEFINE_LDD__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDD_ ## NAME, \ cpu->d = OPERAND;) #define DEFINE_LDE__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDE_ ## NAME, \ cpu->e = OPERAND;) #define DEFINE_LDH__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDH_ ## NAME, \ cpu->h = OPERAND;) #define DEFINE_LDL__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDL_ ## NAME, \ cpu->l = OPERAND;) #define DEFINE_LDHL__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDHL_ ## NAME, \ cpu->bus = OPERAND; \ cpu->index = LR35902ReadHL(cpu); \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) #define DEFINE_LDA__INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(LDA_ ## NAME, \ cpu->a = OPERAND;) #define DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(A, cpu->a); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(B, cpu->b); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(C, cpu->c); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(D, cpu->d); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(E, cpu->e); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(H, cpu->h); \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(L, cpu->l); DEFINE_INSTRUCTION_LR35902(LDHL_Bus, \ cpu->index = LR35902ReadHL(cpu); \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDHL_, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDHL_Bus;) DEFINE_INSTRUCTION_LR35902(LDHL_SPDelay, int diff = cpu->sp + (int8_t) cpu->bus; LR35902WriteHL(cpu, diff); cpu->executionState = LR35902_CORE_STALL; cpu->f.z = 0; cpu->f.n = 0; cpu->f.c = !!(diff & 0xFFFF0000); /* Figure out h flag*/) DEFINE_INSTRUCTION_LR35902(LDHL_SP, cpu->executionState = LR35902_CORE_READ_PC; cpu->instruction = _LR35902InstructionLDHL_SPDelay;) DEFINE_INSTRUCTION_LR35902(LDSP_HL, cpu->sp = LR35902ReadHL(cpu); cpu->executionState = LR35902_CORE_STALL;) #define DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, REG) \ DEFINE_INSTRUCTION_LR35902(NAME ## REG, \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->index = LR35902Read ## REG (cpu); \ cpu->instruction = _LR35902Instruction ## NAME ## Bus;) #define DEFINE_ALU_INSTRUCTION_LR35902(NAME) \ DEFINE_ ## NAME ## _INSTRUCTION_LR35902(Bus, cpu->bus); \ DEFINE_ALU_INSTRUCTION_LR35902_MEM(NAME, HL) \ DEFINE_INSTRUCTION_LR35902(NAME, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902Instruction ## NAME ## Bus;) \ DEFINE_ALU_INSTRUCTION_LR35902_NOHL(NAME) DEFINE_ALU_INSTRUCTION_LR35902(AND); DEFINE_ALU_INSTRUCTION_LR35902(XOR); DEFINE_ALU_INSTRUCTION_LR35902(OR); DEFINE_ALU_INSTRUCTION_LR35902(CP); static void _LR35902InstructionLDB_Bus(struct LR35902Core*); static void _LR35902InstructionLDC_Bus(struct LR35902Core*); static void _LR35902InstructionLDD_Bus(struct LR35902Core*); static void _LR35902InstructionLDE_Bus(struct LR35902Core*); static void _LR35902InstructionLDH_Bus(struct LR35902Core*); static void _LR35902InstructionLDL_Bus(struct LR35902Core*); static void _LR35902InstructionLDHL_Bus(struct LR35902Core*); static void _LR35902InstructionLDA_Bus(struct LR35902Core*); #define DEFINE_ADD_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(ADD ## NAME, \ int diff = cpu->a + OPERAND; \ cpu->a = diff; \ cpu->f.n = 0; \ cpu->f.z = !diff; \ cpu->f.c = diff >= 0x100; \ /* TODO: Find explanation of H flag */) #define DEFINE_ADC_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(ADC ## NAME, \ int diff = cpu->a + OPERAND + cpu->f.c; \ cpu->a = diff; \ cpu->f.n = 0; \ cpu->f.z = !diff; \ cpu->f.c = diff > 0x100; \ /* TODO: Find explanation of H flag */) #define DEFINE_SUB_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(SUB ## NAME, \ int diff = cpu->a - OPERAND; \ cpu->a = diff; \ cpu->f.n = 1; \ cpu->f.z = !diff; \ cpu->f.c = diff < 0; \ /* TODO: Find explanation of H flag */) #define DEFINE_SBC_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(SBC ## NAME, \ int diff = cpu->a - OPERAND - cpu->f.c; \ cpu->a = diff; \ cpu->f.n = 1; \ cpu->f.z = !diff; \ cpu->f.c = diff < 0; \ /* TODO: Find explanation of H flag */) DEFINE_ALU_INSTRUCTION_LR35902(LDB_); DEFINE_ALU_INSTRUCTION_LR35902(LDC_); DEFINE_ALU_INSTRUCTION_LR35902(LDD_); DEFINE_ALU_INSTRUCTION_LR35902(LDE_); DEFINE_ALU_INSTRUCTION_LR35902(LDH_); DEFINE_ALU_INSTRUCTION_LR35902(LDL_); DEFINE_ALU_INSTRUCTION_LR35902_NOHL(LDHL_); DEFINE_ALU_INSTRUCTION_LR35902(LDA_); DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, BC); DEFINE_ALU_INSTRUCTION_LR35902_MEM(LDA_, DE); DEFINE_ALU_INSTRUCTION_LR35902(ADD); DEFINE_ALU_INSTRUCTION_LR35902(ADC); DEFINE_ALU_INSTRUCTION_LR35902(SUB); DEFINE_ALU_INSTRUCTION_LR35902(SBC); DEFINE_INSTRUCTION_LR35902(ADDSPFinish, cpu->sp = cpu->index; cpu->executionState = LR35902_CORE_STALL;) DEFINE_INSTRUCTION_LR35902(ADDSPDelay, int diff = cpu->sp + (int8_t) cpu->bus; cpu->index = diff; cpu->executionState = LR35902_CORE_OP2; cpu->instruction = _LR35902InstructionADDSPFinish; cpu->f.z = 0; cpu->f.n = 0; cpu->f.c = !!(diff & 0xFFFF0000); /* Figure out h flag*/) DEFINE_INSTRUCTION_LR35902(ADDSP, cpu->executionState = LR35902_CORE_READ_PC; cpu->instruction = _LR35902InstructionADDSPDelay;) DEFINE_INSTRUCTION_LR35902(LDBCDelay, \ cpu->c = cpu->bus; \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDB_Bus;) DEFINE_INSTRUCTION_LR35902(LDBC, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDBCDelay;) DEFINE_INSTRUCTION_LR35902(LDBC_A, \ cpu->index = LR35902ReadBC(cpu); \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDDEDelay, \ cpu->e = cpu->bus; \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDD_Bus;) DEFINE_INSTRUCTION_LR35902(LDDE, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDDEDelay;) DEFINE_INSTRUCTION_LR35902(LDDE_A, \ cpu->index = LR35902ReadDE(cpu); \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDHLDelay, \ cpu->l = cpu->bus; \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDH_Bus;) DEFINE_INSTRUCTION_LR35902(LDHL, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDHLDelay;) DEFINE_INSTRUCTION_LR35902(LDSPFinish, cpu->sp |= cpu->bus << 8;) DEFINE_INSTRUCTION_LR35902(LDSPDelay, \ cpu->sp = cpu->bus; \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDSPFinish;) DEFINE_INSTRUCTION_LR35902(LDSP, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDSPDelay;) DEFINE_INSTRUCTION_LR35902(LDIHLA, \ cpu->index = LR35902ReadHL(cpu); \ LR35902WriteHL(cpu, cpu->index + 1); \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDDHLA, \ cpu->index = LR35902ReadHL(cpu); \ LR35902WriteHL(cpu, cpu->index - 1); \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDA_IHL, \ cpu->index = LR35902ReadHL(cpu); \ LR35902WriteHL(cpu, cpu->index + 1); \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionLDA_Bus;) DEFINE_INSTRUCTION_LR35902(LDA_DHL, \ cpu->index = LR35902ReadHL(cpu); \ LR35902WriteHL(cpu, cpu->index - 1); \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionLDA_Bus;) DEFINE_INSTRUCTION_LR35902(LDIAFinish, \ cpu->index |= cpu->bus << 8; cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDIADelay, \ cpu->index = cpu->bus; cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDIAFinish;) DEFINE_INSTRUCTION_LR35902(LDIA, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDIADelay;) DEFINE_INSTRUCTION_LR35902(LDAIFinish, \ cpu->index |= cpu->bus << 8; cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionLDA_Bus;) DEFINE_INSTRUCTION_LR35902(LDAIDelay, \ cpu->index = cpu->bus; cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDAIFinish;) DEFINE_INSTRUCTION_LR35902(LDAI, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDAIDelay;) DEFINE_INSTRUCTION_LR35902(LDAIOC, \ cpu->index = 0xFF00 | cpu->c; \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionLDA_Bus;) DEFINE_INSTRUCTION_LR35902(LDIOCA, \ cpu->index = 0xFF00 | cpu->c; \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDAIODelay, \ cpu->index = 0xFF00 | cpu->bus; \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902InstructionLDA_Bus;) DEFINE_INSTRUCTION_LR35902(LDAIO, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDAIODelay;) DEFINE_INSTRUCTION_LR35902(LDIOADelay, \ cpu->index = 0xFF00 | cpu->bus; \ cpu->bus = cpu->a; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDIOA, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionLDIOADelay;) DEFINE_INSTRUCTION_LR35902(LDISPStoreH, ++cpu->index; cpu->bus = cpu->sp >> 8; cpu->executionState = LR35902_CORE_MEMORY_STORE; cpu->instruction = _LR35902InstructionNOP;) DEFINE_INSTRUCTION_LR35902(LDISPStoreL, cpu->index |= cpu->bus << 8; cpu->bus = cpu->sp; cpu->executionState = LR35902_CORE_MEMORY_STORE; cpu->instruction = _LR35902InstructionLDISPStoreH;) DEFINE_INSTRUCTION_LR35902(LDISPReadAddr, cpu->index = cpu->bus; cpu->executionState = LR35902_CORE_READ_PC; cpu->instruction = _LR35902InstructionLDISPStoreL;) DEFINE_INSTRUCTION_LR35902(LDISP, cpu->executionState = LR35902_CORE_READ_PC; cpu->instruction = _LR35902InstructionLDISPReadAddr;) #define DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(REG) \ DEFINE_INSTRUCTION_LR35902(INC ## REG, \ uint16_t reg = LR35902Read ## REG (cpu); \ LR35902Write ## REG (cpu, reg + 1); \ cpu->executionState = LR35902_CORE_STALL;) \ DEFINE_INSTRUCTION_LR35902(DEC ## REG, \ uint16_t reg = LR35902Read ## REG (cpu); \ LR35902Write ## REG (cpu, reg - 1); \ cpu->executionState = LR35902_CORE_STALL;) DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(BC); DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(DE); DEFINE_INCDEC_WIDE_INSTRUCTION_LR35902(HL); #define DEFINE_ADD_HL_INSTRUCTION_LR35902(REG, L, H) \ DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG ## Finish, \ int diff = H + cpu->h + cpu->f.c; \ cpu->h = diff; \ cpu->f.c = diff >= 0x100; \ cpu->f.n = 0; \ /* TODO: Find explanation of H flag */) \ DEFINE_INSTRUCTION_LR35902(ADDHL_ ## REG, \ int diff = L + cpu->l; \ cpu->l = diff; \ cpu->f.c = diff >= 0x100; \ cpu->executionState = LR35902_CORE_OP2; \ cpu->instruction = _LR35902InstructionADDHL_ ## REG ## Finish;) DEFINE_ADD_HL_INSTRUCTION_LR35902(BC, cpu->c, cpu->b); DEFINE_ADD_HL_INSTRUCTION_LR35902(DE, cpu->e, cpu->d); DEFINE_ADD_HL_INSTRUCTION_LR35902(HL, cpu->l, cpu->h); DEFINE_ADD_HL_INSTRUCTION_LR35902(SP, (cpu->sp & 0xFF), (cpu->sp >> 8)); #define DEFINE_INC_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(INC ## NAME, \ int diff = OPERAND + 1; \ OPERAND = diff; \ cpu->f.n = 0; \ cpu->f.z = !diff; \ /* TODO: Find explanation of H flag */) #define DEFINE_DEC_INSTRUCTION_LR35902(NAME, OPERAND) \ DEFINE_INSTRUCTION_LR35902(DEC ## NAME, \ int diff = OPERAND - 1; \ OPERAND = diff; \ cpu->f.n = 1; \ cpu->f.z = !diff; \ /* TODO: Find explanation of H flag */) DEFINE_ALU_INSTRUCTION_LR35902_NOHL(INC); DEFINE_ALU_INSTRUCTION_LR35902_NOHL(DEC); DEFINE_INSTRUCTION_LR35902(INC_HLDelay, int diff = cpu->bus + 1; cpu->bus = diff; cpu->f.n = 0; cpu->f.z = !diff; /* TODO: Find explanation of H flag */ cpu->instruction = _LR35902InstructionNOP; cpu->executionState = LR35902_CORE_MEMORY_STORE;) DEFINE_INSTRUCTION_LR35902(INC_HL, cpu->index = LR35902ReadHL(cpu); cpu->instruction = _LR35902InstructionINC_HLDelay; cpu->executionState = LR35902_CORE_MEMORY_LOAD;) DEFINE_INSTRUCTION_LR35902(DEC_HLDelay, int diff = cpu->bus - 1; cpu->bus = diff; cpu->f.n = 1; cpu->f.z = !diff; /* TODO: Find explanation of H flag */ cpu->instruction = _LR35902InstructionNOP; cpu->executionState = LR35902_CORE_MEMORY_STORE;) DEFINE_INSTRUCTION_LR35902(DEC_HL, cpu->index = LR35902ReadHL(cpu); cpu->instruction = _LR35902InstructionDEC_HLDelay; cpu->executionState = LR35902_CORE_MEMORY_LOAD;) DEFINE_INSTRUCTION_LR35902(INCSP, ++cpu->sp; cpu->executionState = LR35902_CORE_STALL;) DEFINE_INSTRUCTION_LR35902(DECSP, --cpu->sp; cpu->executionState = LR35902_CORE_STALL;) DEFINE_INSTRUCTION_LR35902(SCF, cpu->f.c = 1; cpu->f.h = 0; cpu->f.n = 0;) DEFINE_INSTRUCTION_LR35902(CCF, cpu->f.c ^= 1; cpu->f.h = 0; cpu->f.n = 0;) DEFINE_INSTRUCTION_LR35902(CPL_, cpu->a ^= 0xFF; cpu->f.h = 1; cpu->f.n = 1;) #define DEFINE_POPPUSH_INSTRUCTION_LR35902(REG, HH, H, L) \ DEFINE_INSTRUCTION_LR35902(POP ## REG ## Delay, \ cpu-> L = cpu->bus; \ cpu->index = cpu->sp; \ ++cpu->sp; \ cpu->instruction = _LR35902InstructionLD ## HH ## _Bus; \ cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \ DEFINE_INSTRUCTION_LR35902(POP ## REG, \ cpu->index = cpu->sp; \ ++cpu->sp; \ cpu->instruction = _LR35902InstructionPOP ## REG ## Delay; \ cpu->executionState = LR35902_CORE_MEMORY_LOAD;) \ DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Finish, \ cpu->executionState = LR35902_CORE_STALL;) \ DEFINE_INSTRUCTION_LR35902(PUSH ## REG ## Delay, \ --cpu->sp; \ cpu->index = cpu->sp; \ cpu->bus = cpu-> L; \ cpu->instruction = _LR35902InstructionPUSH ## REG ## Finish; \ cpu->executionState = LR35902_CORE_MEMORY_STORE;) \ DEFINE_INSTRUCTION_LR35902(PUSH ## REG, \ --cpu->sp; \ cpu->index = cpu->sp; \ cpu->bus = cpu-> H; \ cpu->instruction = _LR35902InstructionPUSH ## REG ## Delay; \ cpu->executionState = LR35902_CORE_MEMORY_STORE;) DEFINE_POPPUSH_INSTRUCTION_LR35902(BC, B, b, c); DEFINE_POPPUSH_INSTRUCTION_LR35902(DE, D, d, e); DEFINE_POPPUSH_INSTRUCTION_LR35902(HL, H, h, l); DEFINE_POPPUSH_INSTRUCTION_LR35902(AF, A, a, f.packed); #define DEFINE_CB_2_INSTRUCTION_LR35902(NAME, BODY) \ DEFINE_INSTRUCTION_LR35902(NAME ## B, uint8_t reg = cpu->b; BODY; cpu->b = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## C, uint8_t reg = cpu->c; BODY; cpu->c = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## D, uint8_t reg = cpu->d; BODY; cpu->d = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## E, uint8_t reg = cpu->e; BODY; cpu->e = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## H, uint8_t reg = cpu->h; BODY; cpu->h = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## L, uint8_t reg = cpu->l; BODY; cpu->l = reg) \ DEFINE_INSTRUCTION_LR35902(NAME ## HLDelay, \ uint8_t reg = cpu->bus; \ BODY; \ cpu->bus = reg; \ cpu->executionState = LR35902_CORE_MEMORY_STORE; \ cpu->instruction = _LR35902InstructionNOP;) \ DEFINE_INSTRUCTION_LR35902(NAME ## HL, \ cpu->index = LR35902ReadHL(cpu); \ cpu->executionState = LR35902_CORE_MEMORY_LOAD; \ cpu->instruction = _LR35902Instruction ## NAME ## HLDelay;) \ DEFINE_INSTRUCTION_LR35902(NAME ## A, uint8_t reg = cpu->a; BODY; cpu->a = reg) #define DEFINE_CB_INSTRUCTION_LR35902(NAME, BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 0, uint8_t bit = 1; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 1, uint8_t bit = 2; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 2, uint8_t bit = 4; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 3, uint8_t bit = 8; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 4, uint8_t bit = 16; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 5, uint8_t bit = 32; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 6, uint8_t bit = 64; BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME ## 7, uint8_t bit = 128; BODY) DEFINE_CB_INSTRUCTION_LR35902(BIT, cpu->f.n = 0; cpu->f.h = 1; cpu->f.z = !(reg & bit)) DEFINE_CB_INSTRUCTION_LR35902(RES, reg &= ~bit) DEFINE_CB_INSTRUCTION_LR35902(SET, reg |= bit) #define DEFINE_CB_ALU_INSTRUCTION_LR35902(NAME, BODY) \ DEFINE_CB_2_INSTRUCTION_LR35902(NAME, \ BODY; \ cpu->f.n = 0; \ cpu->f.h = 0; \ cpu->f.z = !reg;) DEFINE_CB_ALU_INSTRUCTION_LR35902(RL, int wide = (reg << 1) | cpu->f.c; reg = wide; cpu->f.c = wide >> 8) DEFINE_CB_ALU_INSTRUCTION_LR35902(RLC, reg = (reg << 1) | (reg >> 7); cpu->f.c = reg & 1) DEFINE_CB_ALU_INSTRUCTION_LR35902(RR, int low = reg & 1; reg = (reg >> 1) | (cpu->f.c << 7); cpu->f.c = low) DEFINE_CB_ALU_INSTRUCTION_LR35902(RRC, int low = reg & 1; reg = (reg >> 1) | (low << 7); cpu->f.c = low) DEFINE_CB_ALU_INSTRUCTION_LR35902(SLA, cpu->f.c = reg >> 7; reg <<= 1) DEFINE_CB_ALU_INSTRUCTION_LR35902(SRA, reg = ((int8_t) reg) >> 1; cpu->f.c = 0) DEFINE_CB_ALU_INSTRUCTION_LR35902(SRL, cpu->f.c = reg & 1; reg >>= 1) DEFINE_CB_ALU_INSTRUCTION_LR35902(SWAP, reg = (reg << 4) | (reg >> 4); cpu->f.c = 0) DEFINE_INSTRUCTION_LR35902(RLA_, int wide = (cpu->a << 1) | cpu->f.c; cpu->a = wide; cpu->f.z = 0; cpu->f.h = 0; cpu->f.n = 0; cpu->f.c = wide >> 8;) DEFINE_INSTRUCTION_LR35902(RLCA_, cpu->a = (cpu->a << 1) | (cpu->a >> 7); cpu->f.z = 0; cpu->f.h = 0; cpu->f.n = 0; cpu->f.c = cpu->a & 1;) DEFINE_INSTRUCTION_LR35902(RRA_, int low = cpu->a & 1; cpu->a = (cpu->a >> 1) | (cpu->f.c << 7); cpu->f.z = 0; cpu->f.h = 0; cpu->f.n = 0; cpu->f.c = cpu->f.c = low;) DEFINE_INSTRUCTION_LR35902(RRCA_, int low = cpu->a & 1; cpu->a = (cpu->a >> 1) | (low << 7); cpu->f.z = 0; cpu->f.h = 0; cpu->f.n = 0; cpu->f.c = low;) DEFINE_INSTRUCTION_LR35902(DI, cpu->irqh.setInterrupts(cpu, false)); DEFINE_INSTRUCTION_LR35902(EI, cpu->irqh.setInterrupts(cpu, true)); DEFINE_INSTRUCTION_LR35902(HALT, cpu->cycles = cpu->nextEvent); DEFINE_INSTRUCTION_LR35902(RST00, LR35902RaiseIRQ(cpu, 0x00)); DEFINE_INSTRUCTION_LR35902(RST08, LR35902RaiseIRQ(cpu, 0x08)); DEFINE_INSTRUCTION_LR35902(RST10, LR35902RaiseIRQ(cpu, 0x10)); DEFINE_INSTRUCTION_LR35902(RST18, LR35902RaiseIRQ(cpu, 0x18)); DEFINE_INSTRUCTION_LR35902(RST20, LR35902RaiseIRQ(cpu, 0x20)); DEFINE_INSTRUCTION_LR35902(RST28, LR35902RaiseIRQ(cpu, 0x28)); DEFINE_INSTRUCTION_LR35902(RST30, LR35902RaiseIRQ(cpu, 0x30)); DEFINE_INSTRUCTION_LR35902(RST38, LR35902RaiseIRQ(cpu, 0x38)); DEFINE_INSTRUCTION_LR35902(STUB, cpu->irqh.hitStub(cpu)); static const LR35902Instruction _lr35902CBInstructionTable[0x100] = { DECLARE_LR35902_CB_EMITTER_BLOCK(_LR35902Instruction) }; DEFINE_INSTRUCTION_LR35902(CBDelegate, _lr35902CBInstructionTable[cpu->bus](cpu)) DEFINE_INSTRUCTION_LR35902(CB, \ cpu->executionState = LR35902_CORE_READ_PC; \ cpu->instruction = _LR35902InstructionCBDelegate;) const LR35902Instruction _lr35902InstructionTable[0x100] = { DECLARE_LR35902_EMITTER_BLOCK(_LR35902Instruction) };