1 #include "c68000.h"
2 #include "driver.h"
3 #include "cpuintrf.h"
4 #include "cyclone.h"
5 
6 typedef struct
7 {
8 	struct Cyclone regs;
9 	int pending_interrupts;
10 	int (*MAMEIrqCallback)(int int_level);
11 } Cyclone_Regs;
12 
13 static Cyclone_Regs cyclone;
14 int *cyclone_cycles=&cyclone.regs.cycles;
15 
MyCheckPc(unsigned int pc)16 static unsigned int MyCheckPc(unsigned int pc)
17 {
18   	pc = (pc-cyclone.regs.membase) & 0xffffff; /* Get the real program counter */
19 	change_pc24bew(pc);
20 	cyclone.regs.membase=(unsigned int)OP_ROM;
21   	return cyclone.regs.membase+pc; /* New program counter */
22 }
23 
update_irq_line(void)24 static void update_irq_line(void)
25 {
26 	if (cyclone.pending_interrupts & 0xff000000)
27 	{
28 		int level, mask = 0x80000000;
29 		for (level = 7; level; level--, mask >>= 1)
30 			if (cyclone.pending_interrupts & mask)
31 				break;
32 		cyclone.regs.irq = level;
33 	}
34 	else
35 	{
36 		cyclone.regs.irq = 0;
37 	}
38 }
39 
MyIrqCallback(int irq)40 static int MyIrqCallback(int irq)
41 {
42 	cyclone.pending_interrupts &= ~(1 << (24 + irq));
43 	if (cyclone.MAMEIrqCallback)
44 		cyclone.MAMEIrqCallback(irq);
45 	update_irq_line();
46 	return CYCLONE_INT_ACK_AUTOVECTOR;
47 }
48 
cyclone_Cause_Interrupt(int level)49 static void cyclone_Cause_Interrupt(int level)
50 {
51 	if (level >= 1 && level <= 7)
52 		cyclone.pending_interrupts |= 1 << (24 + level);
53 	update_irq_line();
54 }
55 
cyclone_Clear_Interrupt(int level)56 static void cyclone_Clear_Interrupt (int level)
57 {
58 	if (level >= 1 && level <= 7)
59 		cyclone.pending_interrupts &= ~(1 << (24 + level));
60 	update_irq_line();
61 }
62 
cyclone_reset(void * param)63 void cyclone_reset(void *param)
64 {
65    	CycloneInit();
66 	memset(&cyclone, 0,sizeof(Cyclone_Regs));
67 	cyclone.regs.checkpc=MyCheckPc;
68 	cyclone.regs.read8  = (unsigned int (*)(unsigned int)) cpu_readmem24bew;
69 	cyclone.regs.read16 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_word;
70 	cyclone.regs.read32 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_dword;
71 	cyclone.regs.write8 = (void (*)(unsigned int, unsigned char)) cpu_writemem24bew;
72 	cyclone.regs.write16= (void (*)(unsigned int, unsigned short)) cpu_writemem24bew_word;
73 	cyclone.regs.write32= (void (*)(unsigned int, unsigned int)) cpu_writemem24bew_dword;
74 	cyclone.regs.fetch8  = (unsigned int (*)(unsigned int)) cpu_readmem24bew;
75 	cyclone.regs.fetch16 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_word;
76 	cyclone.regs.fetch32 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_dword;
77 	cyclone.regs.IrqCallback=MyIrqCallback; /* 0 */
78   	cyclone.regs.srh=0x27; /* Set supervisor mode */
79   	cyclone.regs.a[7]=cyclone.regs.read32(0); /* Get Stack Pointer */
80   	cyclone.regs.membase=0;
81   	cyclone.regs.pc=cyclone.regs.checkpc(cyclone.regs.read32(4)); /* Get Program Counter */
82 	cyclone.regs.state_flags = 0; /* not stopped or tracing */
83    	cyclone.pending_interrupts = 0;
84 	CycloneReset(&cyclone.regs);
85 }
86 
cyclone_get_pc(void)87 unsigned int cyclone_get_pc(void)
88 {
89 	return (cyclone.regs.pc - cyclone.regs.membase) & 0xffffff;
90 }
91 
cyclone_set_context(void * src)92 void cyclone_set_context(void *src)
93 {
94 	if (src)
95 	{
96 		memcpy(&cyclone,src,sizeof(Cyclone_Regs));
97 	}
98 	update_irq_line();
99 }
100 
cyclone_get_context(void * dst)101 unsigned cyclone_get_context(void *dst)
102 {
103 	if (dst)
104 	{
105 		memcpy(dst,&cyclone,sizeof(Cyclone_Regs));
106 	}
107 	return sizeof(Cyclone_Regs);
108 
109 }
110 
cyclone_execute(int cycles)111 int cyclone_execute(int cycles)
112 {
113 	cyclone.regs.cycles = cycles;
114 	CycloneRun(&cyclone.regs);
115    	return (cycles - cyclone.regs.cycles);
116 }
117 
cyclone_exit(void)118 void cyclone_exit(void)
119 {
120 }
121 
cyclone_set_pc(unsigned val)122 void cyclone_set_pc(unsigned val)
123 {
124 	cyclone.regs.pc=MyCheckPc(val);
125 }
cyclone_get_sp(void)126 unsigned cyclone_get_sp(void)
127 {
128 	return cyclone.regs.a[7];
129 }
130 
cyclone_set_sp(unsigned val)131 void cyclone_set_sp(unsigned val)
132 {
133 	cyclone.regs.a[7] = val;
134 }
135 
136 enum
137 {
138 	/* NOTE: M68K_SP fetches the current SP, be it USP, ISP, or MSP */
139 	M68K_PC=1, M68K_SP, M68K_ISP, M68K_USP, M68K_MSP, M68K_SR, M68K_VBR,
140 	M68K_SFC, M68K_DFC, M68K_CACR, M68K_CAAR, M68K_PREF_ADDR, M68K_PREF_DATA,
141 	M68K_D0, M68K_D1, M68K_D2, M68K_D3, M68K_D4, M68K_D5, M68K_D6, M68K_D7,
142 	M68K_A0, M68K_A1, M68K_A2, M68K_A3, M68K_A4, M68K_A5, M68K_A6, M68K_A7
143 };
144 
cyclone_get_reg(int regnum)145 unsigned cyclone_get_reg(int regnum)
146 {
147     switch( regnum )
148     {
149 		case M68K_PC: return cyclone_get_pc();
150 		case M68K_SP: return cyclone_get_sp();
151 		case M68K_ISP: return cyclone.regs.osp;
152 		case M68K_USP: return cyclone.regs.osp;
153 		case M68K_SR: return CycloneGetSr(&cyclone.regs);
154 		case M68K_D0: return cyclone.regs.d[0];
155 		case M68K_D1: return cyclone.regs.d[1];
156 		case M68K_D2: return cyclone.regs.d[2];
157 		case M68K_D3: return cyclone.regs.d[3];
158 		case M68K_D4: return cyclone.regs.d[4];
159 		case M68K_D5: return cyclone.regs.d[5];
160 		case M68K_D6: return cyclone.regs.d[6];
161 		case M68K_D7: return cyclone.regs.d[7];
162 		case M68K_A0: return cyclone.regs.a[0];
163 		case M68K_A1: return cyclone.regs.a[1];
164 		case M68K_A2: return cyclone.regs.a[2];
165 		case M68K_A3: return cyclone.regs.a[3];
166 		case M68K_A4: return cyclone.regs.a[4];
167 		case M68K_A5: return cyclone.regs.a[5];
168 		case M68K_A6: return cyclone.regs.a[6];
169 		case M68K_A7: return cyclone.regs.a[7];
170 		case M68K_PREF_ADDR:  return 0; /*?*/
171 		case M68K_PREF_DATA:  return 0; /*?*/
172 		case REG_PREVIOUSPC: return (cyclone.regs.prev_pc - cyclone.regs.membase - 2) & 0xffffff;
173 		default:
174 			if( regnum < REG_SP_CONTENTS )
175 			{
176 				unsigned offset = cyclone_get_sp() + 4 * (REG_SP_CONTENTS - regnum);
177 				if( offset < 0xfffffd )
178 					return cpu_readmem24bew_dword( offset );
179             }
180     }
181     return 0;
182 }
183 
cyclone_set_reg(int regnum,unsigned val)184 void cyclone_set_reg(int regnum, unsigned val)
185 {
186     switch( regnum )
187     {
188 		case M68K_PC: cyclone_set_pc(val); break;
189 		case M68K_SP: cyclone_set_sp(val); break;
190 		case M68K_ISP: cyclone.regs.osp = val; break;
191 		case M68K_USP: cyclone.regs.osp = val; break;
192 		case M68K_SR: CycloneSetSr (&cyclone.regs,val); break;
193 		case M68K_D0: cyclone.regs.d[0] = val; break;
194 		case M68K_D1: cyclone.regs.d[1] = val; break;
195 		case M68K_D2: cyclone.regs.d[2] = val; break;
196 		case M68K_D3: cyclone.regs.d[3] = val; break;
197 		case M68K_D4: cyclone.regs.d[4] = val; break;
198 		case M68K_D5: cyclone.regs.d[5] = val; break;
199 		case M68K_D6: cyclone.regs.d[6] = val; break;
200 		case M68K_D7: cyclone.regs.d[7] = val; break;
201 		case M68K_A0: cyclone.regs.a[0] = val; break;
202 		case M68K_A1: cyclone.regs.a[1] = val; break;
203 		case M68K_A2: cyclone.regs.a[2] = val; break;
204 		case M68K_A3: cyclone.regs.a[3] = val; break;
205 		case M68K_A4: cyclone.regs.a[4] = val; break;
206 		case M68K_A5: cyclone.regs.a[5] = val; break;
207 		case M68K_A6: cyclone.regs.a[6] = val; break;
208 		case M68K_A7: cyclone.regs.a[7] = val; break;
209 		default:
210 			if( regnum < REG_SP_CONTENTS )
211 			{
212 				unsigned offset = cyclone_get_sp() + 4 * (REG_SP_CONTENTS - regnum);
213 				if( offset < 0xfffffd )
214 					cpu_writemem24bew_word( offset, val );
215             }
216     }
217 }
cyclone_set_nmi_line(int state)218 void cyclone_set_nmi_line(int state)
219 {
220 	switch(state)
221 	{
222 		case CLEAR_LINE:
223 			cyclone_Clear_Interrupt(7);
224 			return;
225 		case ASSERT_LINE:
226 			cyclone_Cause_Interrupt(7);
227 			return;
228 		default:
229 			cyclone_Cause_Interrupt(7);
230 			return;
231 	}
232 }
233 
cyclone_set_irq_line(int irqline,int state)234 void cyclone_set_irq_line(int irqline, int state)
235 {
236 	switch(state)
237 	{
238 		case CLEAR_LINE:
239 			cyclone_Clear_Interrupt(irqline);
240 			return;
241 		case ASSERT_LINE:
242 			cyclone_Cause_Interrupt(irqline);
243 			return;
244 		default:
245 			cyclone_Cause_Interrupt(irqline);
246 			return;
247 	}
248 }
249 
cyclone_set_irq_callback(int (* callback)(int irqline))250 void cyclone_set_irq_callback(int (*callback)(int irqline))
251 {
252 	cyclone.MAMEIrqCallback = callback;
253 }
254 
cyclone_info(void * context,int regnum)255 const char *cyclone_info(void *context, int regnum)
256 {
257 	switch( regnum )
258 	{
259 		case CPU_INFO_NAME: return "Cyclone 68000";
260 		case CPU_INFO_FAMILY: return "Motorola 68K";
261 		case CPU_INFO_VERSION: return "v0.0088";
262 		case CPU_INFO_FILE: return __FILE__;
263 		case CPU_INFO_CREDITS: return "Copyright Copyright 2004-2007 Dave, Reesy and Notaz. All rights reserved";
264 	}
265 	return "";
266 }
267 
cyclone_dasm(char * buffer,unsigned pc)268 unsigned cyclone_dasm(char *buffer, unsigned pc)
269 {
270 	change_pc24(pc);
271 	sprintf(buffer, "$%04X", cpu_readop16(pc) );
272 	return 2;
273 }
274