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