|
|
1.1 root 1: /*
2: DSP M56001 emulation
3: Dummy emulation, Hatari glue
4:
5: (C) 2001-2008 ARAnyM developer team
6: Adaption to Hatari (C) 2008 by Thomas Huth
7:
8: This program is free software; you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation; either version 2 of the License, or
11: (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21: */
22:
23: #include <ctype.h>
24:
25: #include "main.h"
26: #include "sysdeps.h"
27: #include "newcpu.h"
28: #include "ioMem.h"
29: #include "dsp.h"
30: #include "configuration.h"
31: #include "cycInt.h"
32: #include "statusbar.h"
33: #include "m68000.h"
34: #include "sysReg.h"
35: #include "dma.h"
36:
37: #if ENABLE_DSP_EMU
38: #include "dsp_cpu.h"
39: #include "dsp_disasm.h"
40: #endif
41:
42: #define DEBUG 0
43: #if DEBUG
44: #define Dprintf(a) printf a
45: #else
46: #define Dprintf(a)
47: #endif
48:
49: #define LOG_DSP_LEVEL LOG_DEBUG
50:
51: #define DSP_HW_OFFSET 0xFFA200
52:
53:
54: #if ENABLE_DSP_EMU
55: static const char* x_ext_memory_addr_name[] = {
56: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
57: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
58: "PBC", "PCC", "PBDDR", "PCDDR", "PBD", "PCD", "", "",
59: "HCR", "HSR", "", "HRX/HTX", "CRA", "CRB", "SSISR/TSR", "RX/TX",
60: "SCR", "SSR", "SCCR", "STXA", "SRX/STX", "SRX/STX", "SRX/STX", "",
61: "", "", "", "", "", "", "BCR", "IPR"
62: };
63:
64: static Sint32 save_cycles;
65: #endif
66:
67: static bool bDspDebugging;
68:
69: bool bDspEnabled = false;
70: bool bDspEmulated = false;
71: bool bDspHostInterruptPending = false;
72:
73:
74: /**
75: * Handle TXD interrupt at host CPU
76: */
77: #if ENABLE_DSP_EMU
78: void DSP_HandleTXD(int set) {
79: if (set) {
80: Log_Printf(LOG_WARN, "[DSP] Set TXD interrupt");
81: //set_dsp_interrupt(SET_INT);
82: } else {
83: Log_Printf(LOG_WARN, "[DSP] Release TXD interrupt");
84: //set_dsp_interrupt(RELEASE_INT);
85: }
86: }
87: #endif
88:
89:
90: /**
91: * Handle HREQ at the host CPU.
92: */
93: #if ENABLE_DSP_EMU
94: static void DSP_HandleHREQ(int set)
95: {
96: if (dsp_core.dma_mode) {
97: set_dsp_interrupt(RELEASE_INT);
98: if (set) {
99: dsp_core.dma_request = 1;
100: } else {
101: dsp_core.dma_request = 0;
102: }
103: } else {
104: dsp_core.dma_request = 0;
105: if (set) {
106: Log_Printf(LOG_DSP_LEVEL, "[DSP] Set HREQ interrupt");
107: set_dsp_interrupt(SET_INT);
108: } else {
109: Log_Printf(LOG_DSP_LEVEL, "[DSP] Release HREQ interrupt");
110: set_dsp_interrupt(RELEASE_INT);
111: }
112: }
113: }
114: #endif
115:
116:
117: /**
118: * Host DSP DMA interface
119: */
120:
121: /**
122: * Set DSP IRQB at the end of a DMA block.
123: */
124: void DSP_SetIRQB(void)
125: {
126: #if ENABLE_DSP_EMU
127: if (dsp_intr_at_block_end) {
128: dsp_set_interrupt(DSP_INTER_IRQB, 1);
129: }
130: #endif
131: }
132:
133:
134: /**
135: * Handling DMA transfers.
136: */
137: #if ENABLE_DSP_EMU
138: static void DSP_HandleDMA(void)
139: {
140: if (dsp_core.dma_mode && dsp_core.dma_request && dma_dsp_ready()) {
141: /* Set the counter according to selected DMA mode */
142: if (dsp_core.dma_address_counter==0) {
143: dsp_core.dma_address_counter = 4-dsp_core.dma_mode;
144: /* Handle unpacked mode on Turbo systems */
145: if (dsp_dma_unpacked && ConfigureParams.System.bTurbo) {
146: dsp_core.dma_address_counter = 4;
147: }
148: }
149: dsp_core.dma_address_counter--;
150:
151: /* Read or write via DMA */
152: if (dsp_core.dma_direction==(1<<CPU_HOST_ICR_TREQ)) {
153: dsp_core_write_host(CPU_HOST_TRXL-dsp_core.dma_address_counter, dma_dsp_read_memory());
154: } else {
155: dma_dsp_write_memory(dsp_core_read_host(CPU_HOST_TRXL-dsp_core.dma_address_counter));
156: }
157:
158: /* Handle unpacked mode on non-Turbo systems */
159: if (dsp_dma_unpacked && dsp_core.dma_address_counter==0 && !ConfigureParams.System.bTurbo) {
160: if (dsp_core.dma_direction==(1<<CPU_HOST_ICR_TREQ)) {
161: dsp_core_write_host(CPU_HOST_TRX0, dma_dsp_read_memory());
162: } else {
163: dma_dsp_write_memory(dsp_core_read_host(CPU_HOST_TRX0));
164: }
165: return;
166: }
167: }
168: }
169: #endif
170:
171:
172: /**
173: * This function is called from the CPU emulation part when SPCFLAG_DSP is set.
174: * If the DSP's IRQ signal is set, we check that SR allows a level 6 interrupt,
175: * and if so, we call M68000_Exception.
176: */
177: #if ENABLE_DSP_EMU
178: bool DSP_ProcessIRQ(void)
179: {
180: if (bDspHostInterruptPending && regs.intmask < 6)
181: {
182: M68000_Exception(IoMem_ReadByte(0xffa203)*4, M68000_EXC_SRC_INT_DSP);
183: bDspHostInterruptPending = false;
184: // M68000_UnsetSpecial(SPCFLAG_DSP);
185: return true;
186: }
187:
188: return false;
189: }
190: #endif
191:
192:
193: /**
194: * Initialize the DSP emulation
195: */
196: void DSP_Init(void)
197: {
198: #if ENABLE_DSP_EMU
199: if (bDspEnabled)
200: return;
201: dsp_core_init(DSP_HandleHREQ);
202: dsp56k_init_cpu();
203: bDspEnabled = true;
204: save_cycles = 0;
205: #endif
206: }
207:
208:
209: /**
210: * Shut down the DSP emulation
211: */
212: void DSP_UnInit(void)
213: {
214: #if ENABLE_DSP_EMU
215: if (!bDspEnabled)
216: return;
217: dsp_core_shutdown();
218: bDspEnabled = false;
219: #endif
220: }
221:
222:
223: /**
224: * Reset the DSP emulation
225: */
226: void DSP_Reset(void)
227: {
228: #if ENABLE_DSP_EMU
229: //LogTraceFlags = TRACE_DSP_ALL;
230: if (ConfigureParams.System.bDSPMemoryExpansion) {
231: DSP_RAMSIZE = DSP_RAMSIZE_96kB;
232: } else {
233: DSP_RAMSIZE = DSP_RAMSIZE_24kB;
234: }
235: if (ConfigureParams.System.nDSPType==DSP_TYPE_EMU) {
236: bDspEmulated = true;
237: } else {
238: bDspEmulated = false;
239: }
240: Statusbar_SetDspLed(false);
241:
242: dsp_core_reset();
243: save_cycles = 0;
244: #endif
245: }
246:
247:
248: /**
249: * Start the DSP emulation
250: */
251: void DSP_Start(Uint8 mode)
252: {
253: if (!bDspEmulated) {
254: return;
255: }
256: #if ENABLE_DSP_EMU
257: dsp_core_start(mode);
258: save_cycles = 0;
259: #endif
260: }
261:
262: /**
263: * Run DSP for certain cycles
264: */
265: void DSP_Run(int nHostCycles)
266: {
267: #if ENABLE_DSP_EMU
268: if (dsp_core.running == 0)
269: return;
270:
271: save_cycles += nHostCycles * 2;
272:
273: if (save_cycles <= 0)
274: return;
275:
276: while (save_cycles > 0)
277: {
278: dsp56k_execute_instruction();
279: save_cycles -= dsp_core.instr_cycle;
280: }
281:
282: DSP_HandleDMA();
283: #endif
284: }
285:
286: /**
287: * Enable/disable DSP debugging mode
288: */
289: void DSP_SetDebugging(bool enabled)
290: {
291: bDspDebugging = enabled;
292: }
293:
294: /**
295: * Get DSP program counter (for debugging)
296: */
297: Uint16 DSP_GetPC(void)
298: {
299: #if ENABLE_DSP_EMU
300: if (bDspEnabled)
301: return dsp_core.pc;
302: else
303: #endif
304: return 0;
305: }
306:
307: /**
308: * Get next DSP PC without output (for debugging)
309: */
310: Uint16 DSP_GetNextPC(Uint16 pc)
311: {
312: #if ENABLE_DSP_EMU
313: /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */
314: dsp_core_t dsp_core_save;
315: Uint16 instruction_length;
316:
317: if (!bDspEnabled)
318: return 0;
319:
320: /* Save DSP context */
321: memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core));
322:
323: /* Disasm instruction */
324: dsp_core.pc = pc;
325: /* why dsp56k_execute_one_disasm_instruction() does "-1"
326: * for this value, that doesn't seem right???
327: */
328: instruction_length = dsp56k_disasm(DSP_DISASM_MODE);
329:
330: /* Restore DSP context */
331: memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core));
332:
333: return pc + instruction_length;
334: #else
335: return 0;
336: #endif
337: }
338:
339: /**
340: * Get current DSP instruction cycles (for profiling)
341: */
342: Uint16 DSP_GetInstrCycles(void)
343: {
344: #if ENABLE_DSP_EMU
345: if (bDspEnabled)
346: return dsp_core.instr_cycle;
347: else
348: #endif
349: return 0;
350: }
351:
352:
353: /**
354: * Disassemble DSP code between given addresses, return next PC address
355: */
356: Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr)
357: {
358: #if ENABLE_DSP_EMU
359: Uint16 dsp_pc;
360:
361: for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) {
362: dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc);
363: }
364: return dsp_pc;
365: #else
366: return 0;
367: #endif
368: }
369:
370:
371: /**
372: * Get the value from the given (16-bit) DSP memory address / space
373: * exactly the same way as in dsp_cpu.c::read_memory() (except for
374: * the host/transmit peripheral register values which access has
375: * side-effects). Set the mem_str to suitable string for that
376: * address / space.
377: * Return the value at given address. For valid values AND the return
378: * value with BITMASK(24).
379: */
380: Uint32 DSP_ReadMemory(Uint16 address, char space_id, const char **mem_str)
381: {
382: #if ENABLE_DSP_EMU
383: static const char *spaces[3][4] = {
384: { "X ram", "X rom", "X", "X periph" },
385: { "Y ram", "Y rom", "Y", "Y periph" },
386: { "P ram", "P ram", "P ext memory", "P ext memory" }
387: };
388: int idx, space;
389:
390: switch (space_id) {
391: case 'X':
392: space = DSP_SPACE_X;
393: idx = 0;
394: break;
395: case 'Y':
396: space = DSP_SPACE_Y;
397: idx = 1;
398: break;
399: case 'P':
400: space = DSP_SPACE_P;
401: idx = 2;
402: break;
403: default:
404: space = DSP_SPACE_X;
405: idx = 0;
406: }
407: address &= 0xFFFF;
408:
409: /* Internal RAM ? */
410: if (address < 0x100) {
411: *mem_str = spaces[idx][0];
412: return dsp_core.ramint[space][address];
413: }
414:
415: if (space == DSP_SPACE_P) {
416: /* Internal RAM ? */
417: if (address < 0x200) {
418: *mem_str = spaces[idx][0];
419: return dsp_core.ramint[DSP_SPACE_P][address];
420: }
421: /* External RAM, mask address to available ram size */
422: *mem_str = spaces[idx][2];
423: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
424: }
425:
426: /* Internal ROM ? */
427: if (address < 0x200) {
428: if (dsp_core.registers[DSP_REG_OMR] & (1<<DSP_OMR_DE)) {
429: *mem_str = spaces[idx][1];
430: return dsp_core.rom[space][address];
431: }
432: }
433:
434: /* Peripheral address ? */
435: if (address >= 0xffc0) {
436: *mem_str = spaces[idx][3];
437: /* reading host/transmit regs has side-effects,
438: * so just give the memory value.
439: */
440: return dsp_core.periph[space][address-0xffc0];
441: }
442:
443: /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */
444: address &= (DSP_RAMSIZE>>1) - 1;
445: if (space == DSP_SPACE_X) {
446: address += DSP_RAMSIZE>>1;
447: }
448:
449: /* Falcon: External RAM, finally map X,Y to P */
450: *mem_str = spaces[idx][2];
451: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
452: #endif
453: return 0;
454: }
455:
456:
457: /**
458: * Output memory values between given addresses in given DSP address space.
459: * Return next DSP address value.
460: */
461: Uint16 DSP_DisasmMemory(Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space)
462: {
463: #if ENABLE_DSP_EMU
464: Uint32 mem, mem2, value;
465: const char *mem_str;
466:
467: for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) {
468: /* special printing of host communication/transmit registers */
469: if (space == 'X' && mem >= 0xffc0) {
470: if (mem == 0xffeb) {
471: fprintf(stderr,"X periph:%04x HTX : %06x RTX:%06x\n",
472: mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx);
473: }
474: else if (mem == 0xffef) {
475: fprintf(stderr,"X periph:%04x SSI TX : %06x SSI RX:%06x\n",
476: mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value);
477: }
478: else {
479: value = DSP_ReadMemory(mem, space, &mem_str);
480: fprintf(stderr,"%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]);
481: }
482: continue;
483: }
484: /* special printing of X & Y external RAM values */
485: if ((space == 'X' || space == 'Y') &&
486: mem >= 0x200 && mem < 0xffc0) {
487: mem2 = mem & ((DSP_RAMSIZE>>1)-1);
488: if (space == 'X') {
489: mem2 += (DSP_RAMSIZE>>1);
490: }
491: fprintf(stderr,"%c:%04x (P:%04x): %06x\n", space,
492: mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]);
493: continue;
494: }
495: value = DSP_ReadMemory(mem, space, &mem_str);
496: fprintf(stderr,"%s:%04x %06x\n", mem_str, mem, value);
497: }
498: #endif
499: return dsp_memdump_upper+1;
500: }
501:
502: /**
503: * Show information on DSP core state which isn't
504: * shown by any of the other commands (dd, dm, dr).
505: */
506: void DSP_Info(Uint32 dummy)
507: {
508: #if ENABLE_DSP_EMU
509: int i, j;
510: const char *stackname[] = { "SSH", "SSL" };
511:
512: fputs("DSP core information:\n", stderr);
513:
514: for (i = 0; i < ARRAYSIZE(stackname); i++) {
515: fprintf(stderr, "- %s stack:", stackname[i]);
516: for (j = 0; j < ARRAYSIZE(dsp_core.stack[0]); j++) {
517: fprintf(stderr, " %04hx", dsp_core.stack[i][j]);
518: }
519: fputs("\n", stderr);
520: }
521:
522: fprintf(stderr, "- Interrupts:\n");
523: for (i = 0; i < 32; i++) {
524: fprintf(stderr, "%s: ", dsp_interrupt_name[i]);
525: if ((1<<i) & dsp_core.interrupt_status & (dsp_core.interrupt_mask|DSP_INTER_NMI_MASK)) {
526: fprintf(stderr, "Pending ");
527: }
528: if ((1<<i) & DSP_INTER_NMI_MASK) {
529: fprintf(stderr, "at level 3");
530: } else {
531: for (j = 2; j>=0; j--) {
532: if ((1<<i) & dsp_core.interrupt_mask_level[j]) {
533: fprintf(stderr, "at level %i", j);
534: }
535: }
536: }
537: fputs("\n", stderr);
538: }
539: fprintf(stderr, "- Hostport:");
540: for (i = 0; i < ARRAYSIZE(dsp_core.hostport); i++) {
541: fprintf(stderr, " %02x", dsp_core.hostport[i]);
542: }
543: fputs("\n", stderr);
544: #endif
545: }
546:
547: /**
548: * Show DSP register contents
549: */
550: void DSP_DisasmRegisters(void)
551: {
552: #if ENABLE_DSP_EMU
553: Uint32 i;
554:
555: fprintf(stderr,"A: A2: %02x A1: %06x A0: %06x\n",
556: dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]);
557: fprintf(stderr,"B: B2: %02x B1: %06x B0: %06x\n",
558: dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]);
559:
560: fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]);
561: fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp_core.registers[DSP_REG_Y1], dsp_core.registers[DSP_REG_Y0]);
562:
563: for (i=0; i<8; i++) {
564: fprintf(stderr,"R%01x: %04x N%01x: %04x M%01x: %04x\n",
565: i, dsp_core.registers[DSP_REG_R0+i],
566: i, dsp_core.registers[DSP_REG_N0+i],
567: i, dsp_core.registers[DSP_REG_M0+i]);
568: }
569:
570: fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc);
571: fprintf(stderr,"SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]);
572: fprintf(stderr,"SP: %02x SSH: %04x SSL: %04x\n",
573: dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]);
574: #endif
575: }
576:
577:
578: /**
579: * Get given DSP register address and required bit mask.
580: * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP,
581: * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers
582: * need special handling (in DSP*SetRegister()) when they are set.
583: * Return the register width in bits or zero for an error.
584: */
585: int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask)
586: {
587: #if ENABLE_DSP_EMU
588: #define MAX_REGNAME_LEN 4
589: typedef struct {
590: const char name[MAX_REGNAME_LEN];
591: Uint32 *addr;
592: size_t bits;
593: Uint32 mask;
594: } reg_addr_t;
595:
596: /* sorted by name so that this can be bisected */
597: static const reg_addr_t registers[] = {
598:
599: /* 56-bit A register */
600: { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) },
601: { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) },
602: { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) },
603:
604: /* 56-bit B register */
605: { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) },
606: { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) },
607: { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) },
608:
609: /* 16-bit LA & LC registers */
610: { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) },
611: { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) },
612:
613: /* 16-bit M registers */
614: { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) },
615: { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) },
616: { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) },
617: { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) },
618: { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) },
619: { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) },
620: { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) },
621: { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) },
622:
623: /* 16-bit N registers */
624: { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) },
625: { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) },
626: { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) },
627: { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) },
628: { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) },
629: { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) },
630: { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) },
631: { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) },
632:
633: { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f },
634:
635: /* 16-bit program counter */
636: { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) },
637:
638: /* 16-bit DSP R (address) registers */
639: { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) },
640: { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) },
641: { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) },
642: { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) },
643: { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) },
644: { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) },
645: { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) },
646: { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) },
647:
648: { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) },
649: { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) },
650: { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) },
651:
652: /* 16-bit status register */
653: { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff },
654:
655: /* 48-bit X register */
656: { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) },
657: { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) },
658:
659: /* 48-bit Y register */
660: { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) },
661: { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) }
662: };
663: /* left, right, middle, direction */
664: int l, r, m, dir = 0;
665: unsigned int i, len;
666: char reg[MAX_REGNAME_LEN];
667:
668: if (!bDspEnabled) {
669: return 0;
670: }
671:
672: for (i = 0; i < sizeof(reg) && regname[i]; i++) {
673: reg[i] = toupper((unsigned char)regname[i]);
674: }
675: if (i < 2 || regname[i]) {
676: /* too short or longer than any of the names */
677: return 0;
678: }
679: len = i;
680:
681: /* bisect */
682: l = 0;
683: r = ARRAYSIZE(registers) - 1;
684: do {
685: m = (l+r) >> 1;
686: for (i = 0; i < len; i++) {
687: dir = (int)reg[i] - registers[m].name[i];
688: if (dir) {
689: break;
690: }
691: }
692: if (dir == 0) {
693: *addr = registers[m].addr;
694: *mask = registers[m].mask;
695: return registers[m].bits;
696: }
697: if (dir < 0) {
698: r = m-1;
699: } else {
700: l = m+1;
701: }
702: } while (l <= r);
703: #undef MAX_REGNAME_LEN
704: #endif
705: return 0;
706: }
707:
708:
709: /**
710: * Set given DSP register value, return false if unknown register given
711: */
712: bool DSP_Disasm_SetRegister(const char *arg, Uint32 value)
713: {
714: #if ENABLE_DSP_EMU
715: Uint32 *addr, mask, sp_value;
716: int bits;
717:
718: /* first check registers needing special handling... */
719: if (arg[0]=='S' || arg[0]=='s') {
720: if (arg[1]=='P' || arg[1]=='p') {
721: dsp_core.registers[DSP_REG_SP] = value & BITMASK(6);
722: value &= BITMASK(4);
723: dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value];
724: dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value];
725: return true;
726: }
727: if (arg[1]=='S' || arg[1]=='s') {
728: sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4);
729: if (arg[2]=='H' || arg[2]=='h') {
730: if (sp_value == 0) {
731: dsp_core.registers[DSP_REG_SSH] = 0;
732: dsp_core.stack[0][sp_value] = 0;
733: } else {
734: dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16);
735: dsp_core.stack[0][sp_value] = value & BITMASK(16);
736: }
737: return true;
738: }
739: if (arg[2]=='L' || arg[2]=='l') {
740: if (sp_value == 0) {
741: dsp_core.registers[DSP_REG_SSL] = 0;
742: dsp_core.stack[1][sp_value] = 0;
743: } else {
744: dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16);
745: dsp_core.stack[1][sp_value] = value & BITMASK(16);
746: }
747: return true;
748: }
749: }
750: }
751:
752: /* ...then registers where address & mask are enough */
753: bits = DSP_GetRegisterAddress(arg, &addr, &mask);
754: switch (bits) {
755: case 32:
756: *addr = value & mask;
757: return true;
758: case 16:
759: *(Uint16*)addr = value & mask;
760: return true;
761: }
762: #endif
763: return false;
764: }
765:
766: /**
767: * Read SSI transmit value
768: */
769: Uint32 DSP_SsiReadTxValue(void)
770: {
771: #if ENABLE_DSP_EMU
772: return dsp_core.ssi.transmit_value;
773: #else
774: return 0;
775: #endif
776: }
777:
778: /**
779: * Write SSI receive value
780: */
781: void DSP_SsiWriteRxValue(Uint32 value)
782: {
783: #if ENABLE_DSP_EMU
784: dsp_core.ssi.received_value = value & 0xffffff;
785: #endif
786: }
787:
788: /**
789: * Signal SSI clock tick to DSP
790: */
791:
792: void DSP_SsiReceive_SC0(void)
793: {
794: #if ENABLE_DSP_EMU
795: dsp_core_ssi_Receive_SC0();
796: #endif
797: }
798:
799: void DSP_SsiTransmit_SC0(void)
800: {
801: #if ENABLE_DSP_EMU
802: #endif
803: }
804:
805: void DSP_SsiReceive_SC1(Uint32 FrameCounter)
806: {
807: #if ENABLE_DSP_EMU
808: dsp_core_ssi_Receive_SC1(FrameCounter);
809: #endif
810: }
811:
812: void DSP_SsiTransmit_SC1(void)
813: {
814: #if ENABLE_DSP_EMU
815: // Crossbar_DmaPlayInHandShakeMode();
816: #endif
817: }
818:
819: void DSP_SsiReceive_SC2(Uint32 FrameCounter)
820: {
821: #if ENABLE_DSP_EMU
822: dsp_core_ssi_Receive_SC2(FrameCounter);
823: #endif
824: }
825:
826: void DSP_SsiTransmit_SC2(Uint32 frame)
827: {
828: #if ENABLE_DSP_EMU
829: // Crossbar_DmaRecordInHandShakeMode_Frame(frame);
830: #endif
831: }
832:
833: void DSP_SsiReceive_SCK(void)
834: {
835: #if ENABLE_DSP_EMU
836: dsp_core_ssi_Receive_SCK();
837: #endif
838: }
839:
840: void DSP_SsiTransmit_SCK(void)
841: {
842: #if ENABLE_DSP_EMU
843: #endif
844: }
845:
846: /**
847: * Read access wrapper for ioMemTabFalcon (DSP Host port)
848: * DSP Host interface port is accessed by the 68030 in Byte mode.
849: * A move.w value,$ffA206 results in 2 bus access for the 68030.
850: */
851: void DSP_HandleReadAccess(void)
852: {
853: Uint32 addr;
854: Uint8 value;
855: bool multi_access = false;
856:
857: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
858: {
859: #if ENABLE_DSP_EMU
860: value = dsp_core_read_host(addr-DSP_HW_OFFSET);
861: #else
862: /* this value prevents TOS from hanging in the DSP init code */
863: value = 0xff;
864: #endif
865: if (multi_access == true)
866: M68000_AddCycles(4);
867: multi_access = true;
868:
869: Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc()));
870: IoMem_WriteByte(addr, value);
871: }
872: }
873:
874: /**
875: * Write access wrapper for ioMemTabFalcon (DSP Host port)
876: * DSP Host interface port is accessed by the 68030 in Byte mode.
877: * A move.w value,$ffA206 results in 2 bus access for the 68030.
878: */
879: void DSP_HandleWriteAccess(void)
880: {
881: Uint32 addr;
882: bool multi_access = false;
883:
884: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
885: {
886: #if ENABLE_DSP_EMU
887: Uint8 value = IoMem_ReadByte(addr);
888: Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc()));
889: dsp_core_write_host(addr-DSP_HW_OFFSET, value);
890: #endif
891: if (multi_access == true)
892: M68000_AddCycles(4);
893: multi_access = true;
894: }
895: }
896:
897:
898:
899: /* Previous Register Access */
900: #define LOG_DSP_REG_LEVEL LOG_DEBUG
901:
902: #define IO_SEG_MASK 0x1FFFF
903:
904: /* Register bits */
905:
906: #define ICR_INIT 0x80
907: #define ICR_HM1 0x40
908: #define ICR_HM0 0x20
909: #define ICR_HF1 0x10
910: #define ICR_HF0 0x08
911: #define ICR_TREQ 0x02
912: #define ICR_RREQ 0x01
913:
914: #define CVR_HC 0x80
915: #define CVR_HV 0x1F
916:
917: #define ISR_HREQ 0x80
918: #define ISR_DMA 0x40
919: #define ISR_HF3 0x10
920: #define ISR_HF2 0x08
921: #define ISR_TRDY 0x04
922: #define ISR_TXDE 0x02
923: #define ISR_RXDF 0x01
924:
925:
926: void DSP_ICR_Read(void) { // 0x02008000
927: #if ENABLE_DSP_EMU
928: if (bDspEmulated)
929: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_ICR);
930: else
931: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x7F;
932: #else
933: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x7F;
934: #endif
935: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ICR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
936: }
937:
938: void DSP_ICR_Write(void) {
939: #if ENABLE_DSP_EMU
940: if (bDspEmulated)
941: dsp_core_write_host(CPU_HOST_ICR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
942: #endif
943: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ICR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
944: }
945:
946: void DSP_CVR_Read(void) { // 0x02008001
947: #if ENABLE_DSP_EMU
948: if (bDspEmulated)
949: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_CVR);
950: else
951: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
952: #else
953: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
954: #endif
955: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] CVR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
956: }
957:
958: void DSP_CVR_Write(void) {
959: #if ENABLE_DSP_EMU
960: if (bDspEmulated)
961: dsp_core_write_host(CPU_HOST_CVR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
962: #endif
963: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] CVR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
964: }
965:
966: void DSP_ISR_Read(void) { // 0x02008002
967: #if ENABLE_DSP_EMU
968: if (bDspEmulated)
969: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_ISR);
970: else
971: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
972: #else
973: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
974: #endif
975: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ISR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
976: }
977:
978: void DSP_ISR_Write(void) {
979: #if ENABLE_DSP_EMU
980: if (bDspEmulated)
981: dsp_core_write_host(CPU_HOST_ISR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
982: #endif
983: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ISR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
984: }
985:
986: void DSP_IVR_Read(void) { // 0x02008003
987: #if ENABLE_DSP_EMU
988: if (bDspEmulated)
989: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_IVR);
990: else
991: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
992: #else
993: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
994: #endif
995: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] IVR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
996: }
997:
998: void DSP_IVR_Write(void) {
999: #if ENABLE_DSP_EMU
1000: if (bDspEmulated)
1001: dsp_core_write_host(CPU_HOST_IVR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1002: #endif
1003: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] IVR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1004: }
1005:
1006: void DSP_Data0_Read(void) { // 0x02008004
1007: #if ENABLE_DSP_EMU
1008: if (bDspEmulated)
1009: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRX0);
1010: else
1011: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1012: #else
1013: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1014: #endif
1015: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data0 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1016: }
1017:
1018: void DSP_Data0_Write(void) {
1019: #if ENABLE_DSP_EMU
1020: if (bDspEmulated)
1021: dsp_core_write_host(CPU_HOST_TRX0, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1022: #endif
1023: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data0 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1024: }
1025:
1026: void DSP_Data1_Read(void) { // 0x02008005
1027: #if ENABLE_DSP_EMU
1028: if (bDspEmulated)
1029: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXH);
1030: else
1031: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1032: #else
1033: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1034: #endif
1035: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data1 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1036: }
1037:
1038: void DSP_Data1_Write(void) {
1039: #if ENABLE_DSP_EMU
1040: if (bDspEmulated)
1041: dsp_core_write_host(CPU_HOST_TRXH, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1042: #endif
1043: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data1 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1044: }
1045:
1046: void DSP_Data2_Read(void) { // 0x02008006
1047: #if ENABLE_DSP_EMU
1048: if (bDspEmulated)
1049: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXM);
1050: else
1051: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1052: #else
1053: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1054: #endif
1055: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data2 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1056: }
1057:
1058: void DSP_Data2_Write(void) {
1059: #if ENABLE_DSP_EMU
1060: if (bDspEmulated)
1061: dsp_core_write_host(CPU_HOST_TRXM, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1062: #endif
1063: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1064: }
1065:
1066: void DSP_Data3_Read(void) { // 0x02008007
1067: #if ENABLE_DSP_EMU
1068: if (bDspEmulated)
1069: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXL);
1070: else
1071: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1072: #else
1073: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1074: #endif
1075: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data3 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1076: }
1077:
1078: void DSP_Data3_Write(void) {
1079: #if ENABLE_DSP_EMU
1080: if (bDspEmulated)
1081: dsp_core_write_host(CPU_HOST_TRXL, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1082: #endif
1083: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data3 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1084: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.