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