1 /*  Copyright 2003-2004 Stephane Dallongeville
2 
3     This file is part of Yabause.
4 
5     Yabause is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     Yabause is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with Yabause; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
18 */
19 
20 /*! \file c68k.c
21     \brief C68K init, interrupt and memory access functions.
22 */
23 
24 /*********************************************************************************
25  *
26  * C68K (68000 CPU emulator) version 0.80
27  * Compiled with Dev-C++
28  * Copyright 2003-2004 Stephane Dallongeville
29  *
30  ********************************************************************************/
31 
32 #include <stdio.h>
33 #include <string.h>
34 
35 #include "c68k.h"
36 
37 // shared global variable
38 //////////////////////////
39 
40 c68k_struc C68K;
41 
42 // include macro file
43 //////////////////////
44 
45 #include "c68kmac.inc"
46 
47 // prototype
48 /////////////
49 
50 u32 FASTCALL C68k_Read_Dummy(const u32 adr);
51 void FASTCALL C68k_Write_Dummy(const u32 adr, u32 data);
52 
53 u32 C68k_Read_Byte(c68k_struc *cpu, u32 adr);
54 u32 C68k_Read_Word(c68k_struc *cpu, u32 adr);
55 u32 C68k_Read_Long(c68k_struc *cpu, u32 adr);
56 void C68k_Write_Byte(c68k_struc *cpu, u32 adr, u32 data);
57 void C68k_Write_Word(c68k_struc *cpu, u32 adr, u32 data);
58 void C68k_Write_Long(c68k_struc *cpu, u32 adr, u32 data);
59 
60 s32  FASTCALL C68k_Interrupt_Ack_Dummy(s32 level);
61 void FASTCALL C68k_Reset_Dummy(void);
62 
63 // core main functions
64 ///////////////////////
65 
C68k_Init(c68k_struc * cpu,C68K_INT_CALLBACK * int_cb)66 void C68k_Init(c68k_struc *cpu, C68K_INT_CALLBACK *int_cb)
67 {
68     memset(cpu, 0, sizeof(c68k_struc));
69 
70     C68k_Set_ReadB(cpu, C68k_Read_Dummy);
71     C68k_Set_ReadW(cpu, C68k_Read_Dummy);
72 
73     C68k_Set_WriteB(cpu, C68k_Write_Dummy);
74     C68k_Set_WriteW(cpu, C68k_Write_Dummy);
75 
76     if (int_cb) cpu->Interrupt_CallBack = int_cb;
77     else cpu->Interrupt_CallBack = C68k_Interrupt_Ack_Dummy;
78     cpu->Reset_CallBack = C68k_Reset_Dummy;
79 
80     // used to init JumpTable
81     cpu->Status |= C68K_DISABLE;
82     C68k_Exec(cpu, 0);
83 
84     cpu->Status &= ~C68K_DISABLE;
85 }
86 
C68k_Reset(c68k_struc * cpu)87 s32 FASTCALL C68k_Reset(c68k_struc *cpu)
88 {
89     memset(cpu, 0, ((u8 *)&(cpu->dirty1)) - ((u8 *)&(cpu->D[0])));
90 
91     cpu->flag_notZ = 1;
92     cpu->flag_I = 7;
93     cpu->flag_S = C68K_SR_S;
94 
95     cpu->A[7] = C68k_Read_Long(cpu, 0);
96     C68k_Set_PC(cpu, C68k_Read_Long(cpu, 4));
97 
98     return cpu->Status;
99 }
100 
101 /////////////////////////////////
102 
C68k_Set_IRQ(c68k_struc * cpu,s32 level)103 void FASTCALL C68k_Set_IRQ(c68k_struc *cpu, s32 level)
104 {
105     cpu->IRQLine = level;
106     if (cpu->Status & C68K_RUNNING)
107     {
108         cpu->CycleSup = cpu->CycleIO;
109         cpu->CycleIO = 0;
110     }
111     cpu->Status &= ~(C68K_HALTED | C68K_WAITING);
112 }
113 
114 /////////////////////////////////
115 
C68k_Get_CycleToDo(c68k_struc * cpu)116 s32 FASTCALL C68k_Get_CycleToDo(c68k_struc *cpu)
117 {
118     if (!(cpu->Status & C68K_RUNNING)) return -1;
119 
120     return cpu->CycleToDo;
121 }
122 
C68k_Get_CycleRemaining(c68k_struc * cpu)123 s32 FASTCALL C68k_Get_CycleRemaining(c68k_struc *cpu)
124 {
125     if (!(cpu->Status & C68K_RUNNING)) return -1;
126 
127     return (cpu->CycleIO + cpu->CycleSup);
128 }
129 
C68k_Get_CycleDone(c68k_struc * cpu)130 s32 FASTCALL C68k_Get_CycleDone(c68k_struc *cpu)
131 {
132     if (!(cpu->Status & C68K_RUNNING)) return -1;
133 
134     return (cpu->CycleToDo - (cpu->CycleIO + cpu->CycleSup));
135 }
136 
C68k_Release_Cycle(c68k_struc * cpu)137 void FASTCALL C68k_Release_Cycle(c68k_struc *cpu)
138 {
139     if (cpu->Status & C68K_RUNNING) cpu->CycleIO = cpu->CycleSup = 0;
140 }
141 
C68k_Add_Cycle(c68k_struc * cpu,s32 cycle)142 void FASTCALL C68k_Add_Cycle(c68k_struc *cpu, s32 cycle)
143 {
144     if (cpu->Status & C68K_RUNNING) cpu->CycleIO -= cycle;
145 }
146 
147 // Read / Write dummy functions
148 ////////////////////////////////
149 
C68k_Read_Dummy(UNUSED const u32 adr)150 u32 FASTCALL C68k_Read_Dummy(UNUSED const u32 adr)
151 {
152     return 0;
153 }
154 
C68k_Write_Dummy(UNUSED const u32 adr,UNUSED u32 data)155 void FASTCALL C68k_Write_Dummy(UNUSED const u32 adr, UNUSED u32 data)
156 {
157 
158 }
159 
C68k_Interrupt_Ack_Dummy(s32 level)160 s32 FASTCALL C68k_Interrupt_Ack_Dummy(s32 level)
161 {
162     // return vector
163     return (C68K_INTERRUPT_AUTOVECTOR_EX + level);
164 }
165 
C68k_Reset_Dummy(void)166 void FASTCALL C68k_Reset_Dummy(void)
167 {
168 
169 }
170 
171 // Read / Write core functions
172 ///////////////////////////////
173 
C68k_Read_Byte(c68k_struc * cpu,u32 adr)174 u32 C68k_Read_Byte(c68k_struc *cpu, u32 adr)
175 {
176     return cpu->Read_Byte(adr);
177 }
178 
C68k_Read_Word(c68k_struc * cpu,u32 adr)179 u32 C68k_Read_Word(c68k_struc *cpu, u32 adr)
180 {
181     return cpu->Read_Word(adr);
182 }
183 
C68k_Read_Long(c68k_struc * cpu,u32 adr)184 u32 C68k_Read_Long(c68k_struc *cpu, u32 adr)
185 {
186 #ifdef C68K_BIG_ENDIAN
187     return (cpu->Read_Word(adr) << 16) | (cpu->Read_Word(adr + 2) & 0xFFFF);
188 #else
189     return (cpu->Read_Word(adr) << 16) | (cpu->Read_Word(adr + 2) & 0xFFFF);
190 #endif
191 }
192 
C68k_Write_Byte(c68k_struc * cpu,u32 adr,u32 data)193 void C68k_Write_Byte(c68k_struc *cpu, u32 adr, u32 data)
194 {
195     cpu->Write_Byte(adr, data);
196 }
197 
C68k_Write_Word(c68k_struc * cpu,u32 adr,u32 data)198 void C68k_Write_Word(c68k_struc *cpu, u32 adr, u32 data)
199 {
200     cpu->Write_Word(adr, data);
201 }
202 
C68k_Write_Long(c68k_struc * cpu,u32 adr,u32 data)203 void C68k_Write_Long(c68k_struc *cpu, u32 adr, u32 data)
204 {
205 #ifdef C68K_BIG_ENDIAN
206     cpu->Write_Word(adr, data >> 16);
207     cpu->Write_Word(adr + 2, data & 0xFFFF);
208 #else
209     cpu->Write_Word(adr, data >> 16);
210     cpu->Write_Word(adr + 2, data & 0xFFFF);
211 #endif
212 }
213 
214 // setting core functions
215 //////////////////////////
216 
C68k_Set_Fetch(c68k_struc * cpu,u32 low_adr,u32 high_adr,pointer fetch_adr)217 void C68k_Set_Fetch(c68k_struc *cpu, u32 low_adr, u32 high_adr, pointer fetch_adr)
218 {
219     u32 i, j;
220 
221     i = (low_adr >> C68K_FETCH_SFT) & C68K_FETCH_MASK;
222     j = (high_adr >> C68K_FETCH_SFT) & C68K_FETCH_MASK;
223     fetch_adr -= i << C68K_FETCH_SFT;
224     while (i <= j) cpu->Fetch[i++] = fetch_adr;
225 }
226 
C68k_Set_ReadB(c68k_struc * cpu,C68K_READ * Func)227 void C68k_Set_ReadB(c68k_struc *cpu, C68K_READ *Func)
228 {
229     cpu->Read_Byte = Func;
230 }
231 
C68k_Set_ReadW(c68k_struc * cpu,C68K_READ * Func)232 void C68k_Set_ReadW(c68k_struc *cpu, C68K_READ *Func)
233 {
234     cpu->Read_Word = Func;
235 }
236 
C68k_Set_WriteB(c68k_struc * cpu,C68K_WRITE * Func)237 void C68k_Set_WriteB(c68k_struc *cpu, C68K_WRITE *Func)
238 {
239     cpu->Write_Byte = Func;
240 }
241 
C68k_Set_WriteW(c68k_struc * cpu,C68K_WRITE * Func)242 void C68k_Set_WriteW(c68k_struc *cpu, C68K_WRITE *Func)
243 {
244     cpu->Write_Word = Func;
245 }
246 
247 // externals main functions
248 ////////////////////////////
249 
C68k_Get_DReg(c68k_struc * cpu,u32 num)250 u32 C68k_Get_DReg(c68k_struc *cpu, u32 num)
251 {
252     return cpu->D[num];
253 }
254 
C68k_Get_AReg(c68k_struc * cpu,u32 num)255 u32 C68k_Get_AReg(c68k_struc *cpu, u32 num)
256 {
257     return cpu->A[num];
258 }
259 
C68k_Get_PC(c68k_struc * cpu)260 u32 C68k_Get_PC(c68k_struc *cpu)
261 {
262     return (u32)(cpu->PC - cpu->BasePC);
263 }
264 
C68k_Get_SR(c68k_struc * cpu)265 u32 C68k_Get_SR(c68k_struc *cpu)
266 {
267     c68k_struc *CPU = cpu;
268     return GET_SR;
269 }
270 
C68k_Get_USP(c68k_struc * cpu)271 u32 C68k_Get_USP(c68k_struc *cpu)
272 {
273     if (cpu->flag_S) return cpu->USP;
274     else return cpu->A[7];
275 }
276 
C68k_Get_MSP(c68k_struc * cpu)277 u32 C68k_Get_MSP(c68k_struc *cpu)
278 {
279     if (cpu->flag_S) return cpu->A[7];
280     else return cpu->USP;
281 }
282 
C68k_Set_DReg(c68k_struc * cpu,u32 num,u32 val)283 void C68k_Set_DReg(c68k_struc *cpu, u32 num, u32 val)
284 {
285     cpu->D[num] = val;
286 }
287 
C68k_Set_AReg(c68k_struc * cpu,u32 num,u32 val)288 void C68k_Set_AReg(c68k_struc *cpu, u32 num, u32 val)
289 {
290     cpu->A[num] = val;
291 }
292 
C68k_Set_PC(c68k_struc * cpu,u32 val)293 void C68k_Set_PC(c68k_struc *cpu, u32 val)
294 {
295     cpu->BasePC = cpu->Fetch[(val >> C68K_FETCH_SFT) & C68K_FETCH_MASK];
296     cpu->PC = val + cpu->BasePC;
297 }
298 
C68k_Set_SR(c68k_struc * cpu,u32 val)299 void C68k_Set_SR(c68k_struc *cpu, u32 val)
300 {
301     c68k_struc *CPU = cpu;
302     SET_SR(val);
303 }
304 
C68k_Set_USP(c68k_struc * cpu,u32 val)305 void C68k_Set_USP(c68k_struc *cpu, u32 val)
306 {
307     if (cpu->flag_S) cpu->USP = val;
308     else cpu->A[7] = val;
309 }
310 
C68k_Set_MSP(c68k_struc * cpu,u32 val)311 void C68k_Set_MSP(c68k_struc *cpu, u32 val)
312 {
313     if (cpu->flag_S) cpu->A[7] = val;
314     else cpu->USP = val;
315 }
316