/* Copyright 2003-2004 Stephane Dallongeville12This file is part of Yabause.34Yabause is free software; you can redistribute it and/or modify5it under the terms of the GNU General Public License as published by6the Free Software Foundation; either version 2 of the License, or7(at your option) any later version.89Yabause is distributed in the hope that it will be useful,10but WITHOUT ANY WARRANTY; without even the implied warranty of11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12GNU General Public License for more details.1314You should have received a copy of the GNU General Public License15along with Yabause; if not, write to the Free Software16Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA17*/1819#include "../core.h"20#include "c68k.h"2122// #define TRACE_WITH_Q68 // Define to use Q68 tracing code to trace insns23// (requires Q68 built in, of course)2425#ifdef NEOCD_HLE26void cdrom_load_files(void);27void neogeo_cdda_control(void);28void neogeo_prio_switch(void);29void neogeo_upload(void);30#endif3132// exception cycle table (taken from musashi core)33static const s32 c68k_exception_cycle_table[256] =34{354, // 0: Reset - Initial Stack Pointer364, // 1: Reset - Initial Program Counter3750, // 2: Bus Error3850, // 3: Address Error3934, // 4: Illegal Instruction4038, // 5: Divide by Zero4140, // 6: CHK4234, // 7: TRAPV4334, // 8: Privilege Violation4434, // 9: Trace454, // 10:464, // 11:474, // 12: RESERVED484, // 13: Coprocessor Protocol Violation494, // 14: Format Error5044, // 15: Uninitialized Interrupt514, // 16: RESERVED524, // 17: RESERVED534, // 18: RESERVED544, // 19: RESERVED554, // 20: RESERVED564, // 21: RESERVED574, // 22: RESERVED584, // 23: RESERVED5944, // 24: Spurious Interrupt6044, // 25: Level 1 Interrupt Autovector6144, // 26: Level 2 Interrupt Autovector6244, // 27: Level 3 Interrupt Autovector6344, // 28: Level 4 Interrupt Autovector6444, // 29: Level 5 Interrupt Autovector6544, // 30: Level 6 Interrupt Autovector6644, // 31: Level 7 Interrupt Autovector6734, // 32: TRAP #06834, // 33: TRAP #16934, // 34: TRAP #27034, // 35: TRAP #37134, // 36: TRAP #47234, // 37: TRAP #57334, // 38: TRAP #67434, // 39: TRAP #77534, // 40: TRAP #87634, // 41: TRAP #97734, // 42: TRAP #107834, // 43: TRAP #117934, // 44: TRAP #128034, // 45: TRAP #138134, // 46: TRAP #148234, // 47: TRAP #15834, // 48: FP Branch or Set on Unknown Condition844, // 49: FP Inexact Result854, // 50: FP Divide by Zero864, // 51: FP Underflow874, // 52: FP Operand Error884, // 53: FP Overflow894, // 54: FP Signaling NAN904, // 55: FP Unimplemented Data Type914, // 56: MMU Configuration Error924, // 57: MMU Illegal Operation Error934, // 58: MMU Access Level Violation Error944, // 59: RESERVED954, // 60: RESERVED964, // 61: RESERVED974, // 62: RESERVED984, // 63: RESERVED99// 64-255: User Defined1004,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1014,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1024,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1034,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1044,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1054,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4106};107108// global variable109///////////////////110111#ifndef C68K_GEN112113#ifndef C68K_NO_JUMP_TABLE114#ifndef C68K_CONST_JUMP_TABLE115static void *JumpTable[0x10000];116#endif117#endif118119static u32 C68k_Initialised = 0;120121#endif // C68K_GEN122123#ifdef NEOCD_HLE124extern int img_display;125#endif126127// include macro file128//////////////////////129130#include "c68kmac.inc"131132#ifndef C68K_GEN133# ifdef TRACE_WITH_Q68134#include "../q68/q68.h"135static c68k_struc *TRACE_CPU;136static uint32_t readw(uint32_t address) {137return TRACE_CPU->Read_Word(address);138}139/* Make our own version of the structure to avoid the overhead of dozens of140* function calls every instruction */141static struct {142u32 D[8], A[8], PC, SR, USP, SSP, dummy[7];143void *readb, *readw, *writeb, *writew;144} state = {.readw = readw};145void TRACE(int PC,c68k_struc *CPU,int Opcode,int CCnt) {146static FILE *f;147if (!f) f = fopen("c68k.log", "w");148TRACE_CPU = CPU;149memcpy(state.D, CPU->D, 16*4);150state.PC = PC - 2 - CPU->BasePC;151state.SR = GET_SR;152if (f) q68_trace((Q68State *)&state, f,153CPU->CycleToDo - CCnt, CPU->CycleToDo);154}155# endif // TRACE_WITH_Q68156#endif // !C68K_GEN157158// main exec function159//////////////////////160161s32 FASTCALL C68k_Exec(c68k_struc *cpu, s32 cycle)162{163#ifndef C68K_GEN164#if 0165register c68k_struc *CPU asm ("ebx");166register pointer PC asm ("esi");167register s32 CCnt asm ("edi");168// register u32 Opcode asm ("edi");169// c68k_struc *CPU;170// u32 PC;171// s32 CCnt;172u32 Opcode;173#else174// register c68k_struc *CPU asm ("r10");175// register u32 PC asm ("r11");176// register s32 CCnt asm ("r12");177// register u32 Opcode asm ("r13");178c68k_struc *CPU;179pointer PC;180s32 CCnt;181u32 Opcode;182#endif183#endif184185#ifndef C68K_GEN186187#ifndef C68K_NO_JUMP_TABLE188#ifdef C68K_CONST_JUMP_TABLE189#include "c68k_ini.inc"190#endif191#else192C68k_Initialised = 1;193#endif194195CPU = cpu;196PC = CPU->PC;197198if (CPU->Status & (C68K_RUNNING | C68K_DISABLE | C68K_FAULTED))199{200#ifndef C68K_NO_JUMP_TABLE201#ifndef C68K_CONST_JUMP_TABLE202if (!C68k_Initialised) goto C68k_Init;203#endif204#endif205return (CPU->Status | 0x80000000);206}207208if (cycle <= 0) return -cycle;209210CPU->CycleToDo = CCnt = cycle;211212#ifndef C68K_DEBUG213CHECK_INT214#else215{216s32 line, vect;217218line = CPU->IRQLine;219220if ((line == 7) || (line > CPU->flag_I))221{222PRE_IO223224/* get vector */225CPU->IRQLine = 0;226vect = CPU->Interrupt_CallBack(line);227if (vect == C68K_INT_ACK_AUTOVECTOR)228vect = C68K_INTERRUPT_AUTOVECTOR_EX + (line & 7);229230/* adjust CCnt */231CCnt -= c68k_exception_cycle_table[vect];232233/* swap A7 and USP */234if (!CPU->flag_S)235{236u32 tmpSP;237238tmpSP = CPU->USP;239CPU->USP = CPU->A[7];240CPU->A[7] = tmpSP;241}242243/* push PC and SR */244PUSH_32_F(PC - CPU->BasePC)245PUSH_16_F(GET_SR)246247/* adjust SR */248CPU->flag_S = C68K_SR_S;249CPU->flag_I = line;250251/* fetch new PC */252READ_LONG_F(vect * 4, PC)253SET_PC(PC)254255POST_IO256}257}258#endif259260if (CPU->Status & (C68K_HALTED | C68K_WAITING)) return CPU->CycleToDo;261262CPU->CycleSup = 0;263CPU->Status |= C68K_RUNNING;264265#ifndef C68K_DEBUG266NEXT267#else268#ifdef C68K_NO_JUMP_TABLE269NEXT270#else271Opcode = FETCH_WORD;272PC += 2;273goto *JumpTable[Opcode];274#endif275#endif276277#ifdef C68K_NO_JUMP_TABLE278SwitchTable:279switch(Opcode)280{281#endif282#include "c68k_op0.inc"283#include "c68k_op1.inc"284#include "c68k_op2.inc"285#include "c68k_op3.inc"286#include "c68k_op4.inc"287#include "c68k_op5.inc"288#include "c68k_op6.inc"289#include "c68k_op7.inc"290#include "c68k_op8.inc"291#include "c68k_op9.inc"292#include "c68k_opA.inc"293#include "c68k_opB.inc"294#include "c68k_opC.inc"295#include "c68k_opD.inc"296#include "c68k_opE.inc"297#include "c68k_opF.inc"298#ifdef C68K_NO_JUMP_TABLE299}300#endif301302C68k_Exec_End:303CHECK_INT304if ((CCnt += CPU->CycleSup) > 0)305{306CPU->CycleSup = 0;307NEXT;308}309310C68k_Exec_Really_End:311CPU->Status &= ~C68K_RUNNING;312CPU->PC = PC;313314return (CPU->CycleToDo - CCnt);315316#ifndef C68K_CONST_JUMP_TABLE317#ifndef C68K_NO_JUMP_TABLE318C68k_Init:319{320u32 i, j;321322#include "c68k_ini.inc"323324C68k_Initialised = 1;325}326327return 0;328#endif329#endif330#else331return 0;332#endif333}334335336337