|
|
1.1 root 1: /*
2: DSP M56001 emulation
3: Host/Emulator <-> DSP glue
4:
5: (C) 2003-2008 ARAnyM developer team
6:
7: This program is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2 of the License, or
10: (at your option) any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20: */
21:
22: #ifdef HAVE_CONFIG_H
23: #include "config.h"
24: #endif
25:
26: #include <string.h>
27:
28: #include "math.h"
29: #include "dsp_core.h"
30: #include "dsp_cpu.h"
31:
32: #ifndef M_PI
33: #define M_PI 3.141592653589793238462643383279502
34: #endif
35:
36: #define DEBUG 0
37:
38: /* More disasm infos, if wanted */
39: #define DSP_DISASM_HOSTREAD 0 /* Dsp->Host transfer */
40: #define DSP_DISASM_HOSTWRITE 0 /* Host->Dsp transfer */
41: #define DSP_DISASM_STATE 0 /* State changes */
42:
43: /* Execute DSP instructions till the DSP waits for a read/write */
44: #define DSP_HOST_FORCEEXEC 1
45:
46: /* Init DSP emulation */
47: void dsp_core_init(dsp_core_t *dsp_core)
48: {
49: int i;
50:
51: #if DEBUG
52: fprintf(stderr, "Dsp: core init\n");
53: #endif
54:
55: memset(dsp_core->ram, 0,sizeof(dsp_core->ram));
56: memset(dsp_core->ramint, 0,sizeof(dsp_core->ramint));
57: memset(dsp_core->hostport, 0,sizeof(dsp_core->hostport));
58:
59: /* Initialize Y:rom[0x0100-0x01ff] with a sin table */
60: for (i=0;i<256;i++) {
61: float src = (((float) i)*M_PI)/128.0;
62: Sint32 dest = (Sint32) (sin(src) * 8388608.0); /* 1<<23 */
63: if (dest>8388607) {
64: dest = 8388607;
65: } else if (dest<-8388608) {
66: dest = -8388608;
67: }
68: dsp_core->rom[DSP_SPACE_Y][0x100+i]=dest & 0x00ffffff;
69: }
70:
71: /* Initialize X:rom[0x0100-0x017f] with a mu-law table */
72: {
73: const Uint16 mulaw_base[8]={
74: 0x7d7c, 0x3e7c, 0x1efc, 0x0f3c, 0x075c, 0x036c, 0x0174, 0x0078
75: };
76:
77: Uint32 position = 0x0100;
78: Uint32 offset = 0x040000;
79:
80: for(i=0;i<8;i++) {
81: int j;
82: Uint32 value = mulaw_base[i]<<8;
83:
84: for (j=0;j<16;j++) {
85: dsp_core->rom[DSP_SPACE_X][position++]=value;
86: value -= offset;
87: }
88:
89: offset >>= 1;
90: }
91: }
92:
93: /* Initialize X:rom[0x0180-0x01ff] with a a-law table */
94: {
95: const Sint32 multiply_base[8]={
96: 0x1580, 0x0ac0, 0x5600, 0x2b00,
97: 0x1580, 0x0058, 0x0560, 0x02b0
98: };
99: const Sint32 multiply_col[4]={0x10, 0x01, 0x04, 0x02};
100: const Sint32 multiply_line[4]={0x40, 0x04, 0x10, 0x08};
101: const Sint32 base_values[4]={0, -1, 2, 1};
102: Uint32 pos=0x0180;
103:
104: for (i=0;i<8;i++) {
105: Sint32 alawbase, j;
106:
107: alawbase = multiply_base[i]<<8;
108: for (j=0;j<4;j++) {
109: Sint32 alawbase1, k;
110:
111: alawbase1 = alawbase + ((base_values[j]*multiply_line[i & 3])<<12);
112:
113: for (k=0;k<4;k++) {
114: Sint32 alawbase2;
115:
116: alawbase2 = alawbase1 + ((base_values[k]*multiply_col[i & 3])<<12);
117:
118: dsp_core->rom[DSP_SPACE_X][pos++]=alawbase2;
119: }
120: }
121: }
122: }
123:
124: dsp_core->thread = NULL;
125: dsp_core->semaphore = NULL;
126: dsp_core->mutex = NULL;
127:
128: dsp_core->running = 0;
129: }
130:
131: /* Shutdown DSP emulation */
132: void dsp_core_shutdown(dsp_core_t *dsp_core)
133: {
134: #if DEBUG
135: fprintf(stderr, "Dsp: core shutdown\n");
136: #endif
137:
138: dsp_core->running = 0;
139:
140: if (dsp_core->thread) {
141: if (SDL_SemValue(dsp_core->semaphore)==0) {
142: SDL_SemPost(dsp_core->semaphore);
143: }
144: SDL_WaitThread(dsp_core->thread, NULL);
145: dsp_core->thread = NULL;
146: }
147:
148: /* Destroy the semaphore */
149: if (dsp_core->semaphore) {
150: SDL_DestroySemaphore(dsp_core->semaphore);
151: dsp_core->semaphore = NULL;
152: }
153:
154: /* Destroy mutex */
155: if (dsp_core->mutex) {
156: SDL_DestroyMutex(dsp_core->mutex);
157: dsp_core->mutex = NULL;
158: }
159: }
160:
161: /* Reset */
162: void dsp_core_reset(dsp_core_t *dsp_core)
163: {
164: int i;
165:
166: #if DEBUG
167: fprintf(stderr, "Dsp: core reset\n");
168: #endif
169:
170: /* Kill existing thread and semaphore */
171: dsp_core_shutdown(dsp_core);
172:
173: /* Memory */
174: memset(dsp_core->periph, 0,sizeof(dsp_core->periph));
175: memset(dsp_core->stack, 0,sizeof(dsp_core->stack));
176: memset(dsp_core->registers, 0,sizeof(dsp_core->registers));
177:
178: dsp_core->bootstrap_pos = 0;
179:
180: /* Registers */
181: dsp_core->pc = 0x0000;
182: dsp_core->registers[DSP_REG_OMR]=0x02;
183: for (i=0;i<8;i++) {
184: dsp_core->registers[DSP_REG_M0+i]=0x00ffff;
185: }
186:
187: /* host port init, dsp side */
188: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR]=(1<<DSP_HOST_HSR_HTDE);
189:
190: /* host port init, cpu side */
191: dsp_core->hostport[CPU_HOST_CVR]=0x12;
192: dsp_core->hostport[CPU_HOST_ISR]=(1<<CPU_HOST_ISR_TRDY)|(1<<CPU_HOST_ISR_TXDE);
193: dsp_core->hostport[CPU_HOST_IVR]=0x0f;
194:
195: /* Other hardware registers */
196: dsp_core->periph[DSP_SPACE_X][DSP_IPR]=0;
197: dsp_core->periph[DSP_SPACE_X][DSP_BCR]=0xffff;
198:
199: /* Misc */
200: dsp_core->loop_rep = 0;
201:
202: #if DEBUG
203: fprintf(stderr, "Dsp: reset done\n");
204: #endif
205:
206: /* Create thread, semaphore, mutex if needed */
207: if (dsp_core->semaphore == NULL) {
208: dsp_core->semaphore = SDL_CreateSemaphore(0);
209: }
210: if (dsp_core->mutex == NULL) {
211: dsp_core->mutex = SDL_CreateMutex();
212: }
213: if (dsp_core->thread == NULL) {
214: dsp_core->thread = SDL_CreateThread(dsp56k_do_execute, dsp_core);
215: }
216: }
217:
218: /* Force execution of DSP instructions, till cpu has read/written host port
219: Should not be needed at all, as it slows down host cpu emulation
220: */
221:
222: #if DSP_HOST_FORCEEXEC
223: static void dsp_core_force_exec(dsp_core_t *dsp_core)
224: {
225: Uint32 start = SDL_GetTicks();
226:
227: while (dsp_core->running /* DSP thread running */
228: && (SDL_SemValue(dsp_core->semaphore)!=0) /* and executing instructions */
229: && (SDL_GetTicks()-start<200))
230: {
231: SDL_Delay(1);
232: }
233: }
234: #endif
235:
236: static void dsp_core_hostport_update_trdy(dsp_core_t *dsp_core)
237: {
238: int trdy;
239:
240: /* Clear/set TRDY bit */
241: dsp_core->hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TRDY);
242: trdy = (dsp_core->hostport[CPU_HOST_ISR]>>CPU_HOST_ISR_TXDE)
243: & ~(dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR]>>DSP_HOST_HSR_HRDF);
244: dsp_core->hostport[CPU_HOST_ISR] |= (trdy & 1)<< CPU_HOST_ISR_TRDY;
245: }
246:
247: /* Host port transfer ? (dsp->host) */
248: static void dsp_core_dsp2host(dsp_core_t *dsp_core)
249: {
250: if (dsp_core->hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_RXDF)) {
251: return;
252: }
253: if (dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HTDE)) {
254: return;
255: }
256:
257: dsp_core->hostport[CPU_HOST_RXL] = dsp_core->periph[DSP_SPACE_X][DSP_HOST_HTX];
258: dsp_core->hostport[CPU_HOST_RXM] = dsp_core->periph[DSP_SPACE_X][DSP_HOST_HTX]>>8;
259: dsp_core->hostport[CPU_HOST_RXH] = dsp_core->periph[DSP_SPACE_X][DSP_HOST_HTX]>>16;
260: #if DSP_DISASM_HOSTWRITE
261: fprintf(stderr, "Dsp: (D->H): Transfer 0x%06x\n", dsp_core->periph[DSP_SPACE_X][DSP_HOST_HTX]);
262: #endif
263:
264: /* Set HTDE bit to say that DSP can write */
265: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HTDE;
266: #if DSP_DISASM_HOSTWRITE
267: fprintf(stderr, "Dsp: (D->H): Dsp HTDE set\n");
268: #endif
269:
270: /* Set RXDF bit to say that host can read */
271: dsp_core->hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_RXDF;
272: #if DSP_DISASM_HOSTWRITE
273: fprintf(stderr, "Dsp: (D->H): Host RXDF set\n");
274: #endif
275: }
276:
277: /* Host port transfer ? (host->dsp) */
278: static void dsp_core_host2dsp(dsp_core_t *dsp_core)
279: {
280: if (dsp_core->hostport[CPU_HOST_ISR] & (1<<CPU_HOST_ISR_TXDE)) {
281: return;
282: }
283: if (dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<<DSP_HOST_HSR_HRDF)) {
284: return;
285: }
286:
287: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HRX] = dsp_core->hostport[CPU_HOST_TXL];
288: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HRX] |= dsp_core->hostport[CPU_HOST_TXM]<<8;
289: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HRX] |= dsp_core->hostport[CPU_HOST_TXH]<<16;
290: #if DSP_DISASM_HOSTREAD
291: fprintf(stderr, "Dsp: (H->D): Transfer 0x%06x\n", dsp_core->periph[DSP_SPACE_X][DSP_HOST_HRX]);
292: #endif
293:
294: /* Set HRDF bit to say that DSP can read */
295: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HRDF;
296: #if DSP_DISASM_HOSTREAD
297: fprintf(stderr, "Dsp: (H->D): Dsp HRDF set\n");
298: #endif
299:
300: /* Set TXDE bit to say that host can write */
301: dsp_core->hostport[CPU_HOST_ISR] |= 1<<CPU_HOST_ISR_TXDE;
302: # if DSP_DISASM_HOSTREAD
303: fprintf(stderr, "Dsp: (H->D): Host TXDE set\n");
304: # endif
305:
306: dsp_core_hostport_update_trdy(dsp_core);
307: }
308:
309: void dsp_core_hostport_dspread(dsp_core_t *dsp_core)
310: {
311: /* Clear HRDF bit to say that DSP has read */
312: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HRDF);
313: #if DSP_DISASM_HOSTREAD
314: fprintf(stderr, "Dsp: (H->D): Dsp HRDF cleared\n");
315: #endif
316: dsp_core_hostport_update_trdy(dsp_core);
317: dsp_core_host2dsp(dsp_core);
318: }
319:
320: void dsp_core_hostport_dspwrite(dsp_core_t *dsp_core)
321: {
322: /* Clear HTDE bit to say that DSP has written */
323: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<<DSP_HOST_HSR_HTDE);
324: #if DSP_DISASM_HOSTWRITE
325: fprintf(stderr, "Dsp: (D->H): Dsp HTDE cleared\n");
326: #endif
327:
328: dsp_core_dsp2host(dsp_core);
329: }
330:
331: static void dsp_core_hostport_cpuread(dsp_core_t *dsp_core)
332: {
333: /* Clear RXDF bit to say that CPU has read */
334: dsp_core->hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_RXDF);
335: #if DSP_DISASM_HOSTWRITE
336: fprintf(stderr, "Dsp: (D->H): Host RXDF cleared\n");
337: #endif
338: dsp_core_dsp2host(dsp_core);
339: }
340:
341: static void dsp_core_hostport_cpuwrite(dsp_core_t *dsp_core)
342: {
343: /* Clear TXDE to say that CPU has written */
344: dsp_core->hostport[CPU_HOST_ISR] &= 0xff-(1<<CPU_HOST_ISR_TXDE);
345: #if DSP_DISASM_HOSTREAD
346: fprintf(stderr, "Dsp: (H->D): Host TXDE cleared\n");
347: #endif
348:
349: dsp_core_hostport_update_trdy(dsp_core);
350: dsp_core_host2dsp(dsp_core);
351: }
352:
353: /* Read/writes on host port */
354:
355: Uint8 dsp_core_read_host(dsp_core_t *dsp_core, int addr)
356: {
357: #if 0 /* DSP_HOST_FORCEEXEC */
358: switch(addr) {
359: case CPU_HOST_RXH:
360: case CPU_HOST_RXM:
361: case CPU_HOST_RXL:
362: dsp_core_force_exec(dsp_core);
363: break;
364: }
365: #endif
366:
367: SDL_LockMutex(dsp_core->mutex);
368: Uint8 value = dsp_core->hostport[addr];
369: if (addr == CPU_HOST_RXL) {
370: dsp_core_hostport_cpuread(dsp_core);
371:
372: /* Wake up DSP if it was waiting our read */
373: #if DSP_DISASM_STATE
374: fprintf(stderr, "Dsp: WAIT_HOSTREAD done\n");
375: #endif
376: SDL_SemPost(dsp_core->semaphore);
377: }
378: SDL_UnlockMutex(dsp_core->mutex);
379:
380: return value;
381: }
382:
383: void dsp_core_write_host(dsp_core_t *dsp_core, int addr, Uint8 value)
384: {
385: #if DSP_HOST_FORCEEXEC
386: switch(addr) {
387: case CPU_HOST_TXH:
388: case CPU_HOST_TXM:
389: case CPU_HOST_TXL:
390: dsp_core_force_exec(dsp_core);
391: break;
392: }
393: #endif
394:
395: SDL_LockMutex(dsp_core->mutex);
396: switch(addr) {
397: case CPU_HOST_ICR:
398: dsp_core->hostport[CPU_HOST_ICR]=value & 0xfb;
399: /* Set HF1 and HF0 accordingly on the host side */
400: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] &=
401: 0xff-((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
402: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] |=
403: dsp_core->hostport[CPU_HOST_ICR] & ((1<<DSP_HOST_HSR_HF1)|(1<<DSP_HOST_HSR_HF0));
404: break;
405: case CPU_HOST_CVR:
406: dsp_core->hostport[CPU_HOST_CVR]=value & 0x9f;
407: /* if bit 7=1, host command */
408: if (value & (1<<7)) {
409: dsp_core->periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<<DSP_HOST_HSR_HCP;
410: }
411: break;
412: case CPU_HOST_ISR:
413: case CPU_HOST_TX0:
414: /* Read only */
415: break;
416: case CPU_HOST_IVR:
417: case CPU_HOST_TXH:
418: case CPU_HOST_TXM:
419: dsp_core->hostport[addr]=value;
420: break;
421: case CPU_HOST_TXL:
422: dsp_core->hostport[CPU_HOST_TXL]=value;
423:
424: if (!dsp_core->running) {
425: dsp_core->ramint[DSP_SPACE_P][dsp_core->bootstrap_pos] =
426: (dsp_core->hostport[CPU_HOST_TXH]<<16) |
427: (dsp_core->hostport[CPU_HOST_TXM]<<8) |
428: dsp_core->hostport[CPU_HOST_TXL];
429: #if DEBUG
430: fprintf(stderr, "Dsp: bootstrap p:0x%04x = 0x%06x\n",
431: dsp_core->bootstrap_pos,
432: dsp_core->ramint[DSP_SPACE_P][dsp_core->bootstrap_pos]);
433: #endif
434: if (++dsp_core->bootstrap_pos == 0x200) {
435: #if DSP_DISASM_STATE
436: fprintf(stderr, "Dsp: WAIT_BOOTSTRAP done\n");
437: #endif
438: dsp_core->running = 1;
439: SDL_SemPost(dsp_core->semaphore);
440: }
441: } else {
442: dsp_core_hostport_cpuwrite(dsp_core);
443:
444: /* Wake up DSP if it was waiting our write */
445: #if DSP_DISASM_STATE
446: fprintf(stderr, "Dsp: WAIT_HOSTWRITE done\n");
447: #endif
448: SDL_SemPost(dsp_core->semaphore);
449: }
450: break;
451: }
452: SDL_UnlockMutex(dsp_core->mutex);
453: }
454:
455: /*
456: vim:ts=4:sw=4:
457: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.