|
|
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: */
1.1.1.2 ! root 137: static void DSP_HandleDMA(void)
1.1 root 138: {
139: #if ENABLE_DSP_EMU
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: #endif
169: }
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: //LogTraceFlags = TRACE_DSP_ALL;
229: if (ConfigureParams.System.bDSPMemoryExpansion) {
230: DSP_RAMSIZE = DSP_RAMSIZE_96kB;
231: } else {
232: DSP_RAMSIZE = DSP_RAMSIZE_24kB;
233: }
234: if (ConfigureParams.System.nDSPType==DSP_TYPE_EMU) {
235: bDspEmulated = true;
236: } else {
237: bDspEmulated = false;
238: }
239: Statusbar_SetDspLed(false);
240: #if ENABLE_DSP_EMU
241: dsp_core_reset();
242: save_cycles = 0;
243: #endif
244: }
245:
246:
247: /**
248: * Start the DSP emulation
249: */
250: void DSP_Start(Uint8 mode)
251: {
252: if (!bDspEmulated) {
253: return;
254: }
255: #if ENABLE_DSP_EMU
256: dsp_core_start(mode);
257: save_cycles = 0;
258: #endif
259: }
260:
261: /**
262: * Run DSP for certain cycles
263: */
264: void DSP_Run(int nHostCycles)
265: {
266: #if ENABLE_DSP_EMU
267: if (dsp_core.running == 0)
268: return;
269:
270: save_cycles += nHostCycles * 2;
271:
272: if (save_cycles <= 0)
273: return;
274:
275: while (save_cycles > 0)
276: {
277: dsp56k_execute_instruction();
278: save_cycles -= dsp_core.instr_cycle;
279: }
280:
281: DSP_HandleDMA();
282: #endif
283: }
284:
285: /**
286: * Enable/disable DSP debugging mode
287: */
288: void DSP_SetDebugging(bool enabled)
289: {
290: bDspDebugging = enabled;
291: }
292:
293: /**
294: * Get DSP program counter (for debugging)
295: */
296: Uint16 DSP_GetPC(void)
297: {
298: #if ENABLE_DSP_EMU
299: if (bDspEnabled)
300: return dsp_core.pc;
301: else
302: #endif
303: return 0;
304: }
305:
306: /**
307: * Get next DSP PC without output (for debugging)
308: */
309: Uint16 DSP_GetNextPC(Uint16 pc)
310: {
311: #if ENABLE_DSP_EMU
312: /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */
313: dsp_core_t dsp_core_save;
314: Uint16 instruction_length;
315:
316: if (!bDspEnabled)
317: return 0;
318:
319: /* Save DSP context */
320: memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core));
321:
322: /* Disasm instruction */
323: dsp_core.pc = pc;
324: /* why dsp56k_execute_one_disasm_instruction() does "-1"
325: * for this value, that doesn't seem right???
326: */
327: instruction_length = dsp56k_disasm(DSP_DISASM_MODE);
328:
329: /* Restore DSP context */
330: memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core));
331:
332: return pc + instruction_length;
333: #else
334: return 0;
335: #endif
336: }
337:
338: /**
339: * Get current DSP instruction cycles (for profiling)
340: */
341: Uint16 DSP_GetInstrCycles(void)
342: {
343: #if ENABLE_DSP_EMU
344: if (bDspEnabled)
345: return dsp_core.instr_cycle;
346: else
347: #endif
348: return 0;
349: }
350:
351:
352: /**
353: * Disassemble DSP code between given addresses, return next PC address
354: */
355: Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr)
356: {
357: #if ENABLE_DSP_EMU
358: Uint16 dsp_pc;
359:
360: for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) {
361: dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc);
362: }
363: return dsp_pc;
364: #else
365: return 0;
366: #endif
367: }
368:
369:
370: /**
371: * Get the value from the given (16-bit) DSP memory address / space
372: * exactly the same way as in dsp_cpu.c::read_memory() (except for
373: * the host/transmit peripheral register values which access has
374: * side-effects). Set the mem_str to suitable string for that
375: * address / space.
376: * Return the value at given address. For valid values AND the return
377: * value with BITMASK(24).
378: */
379: Uint32 DSP_ReadMemory(Uint16 address, char space_id, const char **mem_str)
380: {
381: #if ENABLE_DSP_EMU
382: static const char *spaces[3][4] = {
383: { "X ram", "X rom", "X", "X periph" },
384: { "Y ram", "Y rom", "Y", "Y periph" },
385: { "P ram", "P ram", "P ext memory", "P ext memory" }
386: };
387: int idx, space;
388:
389: switch (space_id) {
390: case 'X':
391: space = DSP_SPACE_X;
392: idx = 0;
393: break;
394: case 'Y':
395: space = DSP_SPACE_Y;
396: idx = 1;
397: break;
398: case 'P':
399: space = DSP_SPACE_P;
400: idx = 2;
401: break;
402: default:
403: space = DSP_SPACE_X;
404: idx = 0;
405: }
406: address &= 0xFFFF;
407:
408: /* Internal RAM ? */
409: if (address < 0x100) {
410: *mem_str = spaces[idx][0];
411: return dsp_core.ramint[space][address];
412: }
413:
414: if (space == DSP_SPACE_P) {
415: /* Internal RAM ? */
416: if (address < 0x200) {
417: *mem_str = spaces[idx][0];
418: return dsp_core.ramint[DSP_SPACE_P][address];
419: }
420: /* External RAM, mask address to available ram size */
421: *mem_str = spaces[idx][2];
422: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
423: }
424:
425: /* Internal ROM ? */
426: if (address < 0x200) {
427: if (dsp_core.registers[DSP_REG_OMR] & (1<<DSP_OMR_DE)) {
428: *mem_str = spaces[idx][1];
429: return dsp_core.rom[space][address];
430: }
431: }
432:
433: /* Peripheral address ? */
434: if (address >= 0xffc0) {
435: *mem_str = spaces[idx][3];
436: /* reading host/transmit regs has side-effects,
437: * so just give the memory value.
438: */
439: return dsp_core.periph[space][address-0xffc0];
440: }
441:
442: /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */
443: address &= (DSP_RAMSIZE>>1) - 1;
444: if (space == DSP_SPACE_X) {
445: address += DSP_RAMSIZE>>1;
446: }
447:
448: /* Falcon: External RAM, finally map X,Y to P */
449: *mem_str = spaces[idx][2];
450: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
451: #endif
452: return 0;
453: }
454:
455:
456: /**
457: * Output memory values between given addresses in given DSP address space.
458: * Return next DSP address value.
459: */
460: Uint16 DSP_DisasmMemory(Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space)
461: {
462: #if ENABLE_DSP_EMU
463: Uint32 mem, mem2, value;
464: const char *mem_str;
465:
466: for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) {
467: /* special printing of host communication/transmit registers */
468: if (space == 'X' && mem >= 0xffc0) {
469: if (mem == 0xffeb) {
470: fprintf(stderr,"X periph:%04x HTX : %06x RTX:%06x\n",
471: mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx);
472: }
473: else if (mem == 0xffef) {
474: fprintf(stderr,"X periph:%04x SSI TX : %06x SSI RX:%06x\n",
475: mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value);
476: }
477: else {
478: value = DSP_ReadMemory(mem, space, &mem_str);
479: fprintf(stderr,"%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]);
480: }
481: continue;
482: }
483: /* special printing of X & Y external RAM values */
484: if ((space == 'X' || space == 'Y') &&
485: mem >= 0x200 && mem < 0xffc0) {
486: mem2 = mem & ((DSP_RAMSIZE>>1)-1);
487: if (space == 'X') {
488: mem2 += (DSP_RAMSIZE>>1);
489: }
490: fprintf(stderr,"%c:%04x (P:%04x): %06x\n", space,
491: mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]);
492: continue;
493: }
494: value = DSP_ReadMemory(mem, space, &mem_str);
495: fprintf(stderr,"%s:%04x %06x\n", mem_str, mem, value);
496: }
497: #endif
498: return dsp_memdump_upper+1;
499: }
500:
501: /**
502: * Show information on DSP core state which isn't
503: * shown by any of the other commands (dd, dm, dr).
504: */
505: void DSP_Info(Uint32 dummy)
506: {
507: #if ENABLE_DSP_EMU
508: int i, j;
509: const char *stackname[] = { "SSH", "SSL" };
510:
511: fputs("DSP core information:\n", stderr);
512:
513: for (i = 0; i < ARRAYSIZE(stackname); i++) {
514: fprintf(stderr, "- %s stack:", stackname[i]);
515: for (j = 0; j < ARRAYSIZE(dsp_core.stack[0]); j++) {
516: fprintf(stderr, " %04hx", dsp_core.stack[i][j]);
517: }
518: fputs("\n", stderr);
519: }
520:
521: fprintf(stderr, "- Interrupts:\n");
522: for (i = 0; i < 32; i++) {
523: fprintf(stderr, "%s: ", dsp_interrupt_name[i]);
524: if ((1<<i) & dsp_core.interrupt_status & (dsp_core.interrupt_mask|DSP_INTER_NMI_MASK)) {
525: fprintf(stderr, "Pending ");
526: }
527: if ((1<<i) & DSP_INTER_NMI_MASK) {
528: fprintf(stderr, "at level 3");
529: } else {
530: for (j = 2; j>=0; j--) {
531: if ((1<<i) & dsp_core.interrupt_mask_level[j]) {
532: fprintf(stderr, "at level %i", j);
533: }
534: }
535: }
536: fputs("\n", stderr);
537: }
538: fprintf(stderr, "- Hostport:");
539: for (i = 0; i < ARRAYSIZE(dsp_core.hostport); i++) {
540: fprintf(stderr, " %02x", dsp_core.hostport[i]);
541: }
542: fputs("\n", stderr);
543: #endif
544: }
545:
546: /**
547: * Show DSP register contents
548: */
549: void DSP_DisasmRegisters(void)
550: {
551: #if ENABLE_DSP_EMU
552: Uint32 i;
553:
554: fprintf(stderr,"A: A2: %02x A1: %06x A0: %06x\n",
555: dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]);
556: fprintf(stderr,"B: B2: %02x B1: %06x B0: %06x\n",
557: dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]);
558:
559: fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]);
560: fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp_core.registers[DSP_REG_Y1], dsp_core.registers[DSP_REG_Y0]);
561:
562: for (i=0; i<8; i++) {
563: fprintf(stderr,"R%01x: %04x N%01x: %04x M%01x: %04x\n",
564: i, dsp_core.registers[DSP_REG_R0+i],
565: i, dsp_core.registers[DSP_REG_N0+i],
566: i, dsp_core.registers[DSP_REG_M0+i]);
567: }
568:
569: fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc);
570: fprintf(stderr,"SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]);
571: fprintf(stderr,"SP: %02x SSH: %04x SSL: %04x\n",
572: dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]);
573: #endif
574: }
575:
576:
577: /**
578: * Get given DSP register address and required bit mask.
579: * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP,
580: * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers
581: * need special handling (in DSP*SetRegister()) when they are set.
582: * Return the register width in bits or zero for an error.
583: */
584: int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask)
585: {
586: #if ENABLE_DSP_EMU
587: #define MAX_REGNAME_LEN 4
588: typedef struct {
589: const char name[MAX_REGNAME_LEN];
590: Uint32 *addr;
591: size_t bits;
592: Uint32 mask;
593: } reg_addr_t;
594:
595: /* sorted by name so that this can be bisected */
596: static const reg_addr_t registers[] = {
597:
598: /* 56-bit A register */
599: { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) },
600: { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) },
601: { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) },
602:
603: /* 56-bit B register */
604: { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) },
605: { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) },
606: { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) },
607:
608: /* 16-bit LA & LC registers */
609: { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) },
610: { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) },
611:
612: /* 16-bit M registers */
613: { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) },
614: { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) },
615: { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) },
616: { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) },
617: { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) },
618: { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) },
619: { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) },
620: { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) },
621:
622: /* 16-bit N registers */
623: { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) },
624: { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) },
625: { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) },
626: { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) },
627: { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) },
628: { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) },
629: { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) },
630: { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) },
631:
632: { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f },
633:
634: /* 16-bit program counter */
635: { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) },
636:
637: /* 16-bit DSP R (address) registers */
638: { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) },
639: { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) },
640: { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) },
641: { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) },
642: { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) },
643: { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) },
644: { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) },
645: { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) },
646:
647: { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) },
648: { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) },
649: { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) },
650:
651: /* 16-bit status register */
652: { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff },
653:
654: /* 48-bit X register */
655: { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) },
656: { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) },
657:
658: /* 48-bit Y register */
659: { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) },
660: { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) }
661: };
662: /* left, right, middle, direction */
663: int l, r, m, dir = 0;
664: unsigned int i, len;
665: char reg[MAX_REGNAME_LEN];
666:
667: if (!bDspEnabled) {
668: return 0;
669: }
670:
671: for (i = 0; i < sizeof(reg) && regname[i]; i++) {
672: reg[i] = toupper((unsigned char)regname[i]);
673: }
674: if (i < 2 || regname[i]) {
675: /* too short or longer than any of the names */
676: return 0;
677: }
678: len = i;
679:
680: /* bisect */
681: l = 0;
682: r = ARRAYSIZE(registers) - 1;
683: do {
684: m = (l+r) >> 1;
685: for (i = 0; i < len; i++) {
686: dir = (int)reg[i] - registers[m].name[i];
687: if (dir) {
688: break;
689: }
690: }
691: if (dir == 0) {
692: *addr = registers[m].addr;
693: *mask = registers[m].mask;
694: return registers[m].bits;
695: }
696: if (dir < 0) {
697: r = m-1;
698: } else {
699: l = m+1;
700: }
701: } while (l <= r);
702: #undef MAX_REGNAME_LEN
703: #endif
704: return 0;
705: }
706:
707:
708: /**
709: * Set given DSP register value, return false if unknown register given
710: */
711: bool DSP_Disasm_SetRegister(const char *arg, Uint32 value)
712: {
713: #if ENABLE_DSP_EMU
714: Uint32 *addr, mask, sp_value;
715: int bits;
716:
717: /* first check registers needing special handling... */
718: if (arg[0]=='S' || arg[0]=='s') {
719: if (arg[1]=='P' || arg[1]=='p') {
720: dsp_core.registers[DSP_REG_SP] = value & BITMASK(6);
721: value &= BITMASK(4);
722: dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value];
723: dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value];
724: return true;
725: }
726: if (arg[1]=='S' || arg[1]=='s') {
727: sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4);
728: if (arg[2]=='H' || arg[2]=='h') {
729: if (sp_value == 0) {
730: dsp_core.registers[DSP_REG_SSH] = 0;
731: dsp_core.stack[0][sp_value] = 0;
732: } else {
733: dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16);
734: dsp_core.stack[0][sp_value] = value & BITMASK(16);
735: }
736: return true;
737: }
738: if (arg[2]=='L' || arg[2]=='l') {
739: if (sp_value == 0) {
740: dsp_core.registers[DSP_REG_SSL] = 0;
741: dsp_core.stack[1][sp_value] = 0;
742: } else {
743: dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16);
744: dsp_core.stack[1][sp_value] = value & BITMASK(16);
745: }
746: return true;
747: }
748: }
749: }
750:
751: /* ...then registers where address & mask are enough */
752: bits = DSP_GetRegisterAddress(arg, &addr, &mask);
753: switch (bits) {
754: case 32:
755: *addr = value & mask;
756: return true;
757: case 16:
758: *(Uint16*)addr = value & mask;
759: return true;
760: }
761: #endif
762: return false;
763: }
764:
765: /**
766: * Read SSI transmit value
767: */
768: Uint32 DSP_SsiReadTxValue(void)
769: {
770: #if ENABLE_DSP_EMU
771: return dsp_core.ssi.transmit_value;
772: #else
773: return 0;
774: #endif
775: }
776:
777: /**
778: * Write SSI receive value
779: */
780: void DSP_SsiWriteRxValue(Uint32 value)
781: {
782: #if ENABLE_DSP_EMU
783: dsp_core.ssi.received_value = value & 0xffffff;
784: #endif
785: }
786:
787: /**
788: * Signal SSI clock tick to DSP
789: */
790:
791: void DSP_SsiReceive_SC0(void)
792: {
793: #if ENABLE_DSP_EMU
794: dsp_core_ssi_Receive_SC0();
795: #endif
796: }
797:
798: void DSP_SsiTransmit_SC0(void)
799: {
800: #if ENABLE_DSP_EMU
801: #endif
802: }
803:
804: void DSP_SsiReceive_SC1(Uint32 FrameCounter)
805: {
806: #if ENABLE_DSP_EMU
807: dsp_core_ssi_Receive_SC1(FrameCounter);
808: #endif
809: }
810:
811: void DSP_SsiTransmit_SC1(void)
812: {
813: #if ENABLE_DSP_EMU
814: // Crossbar_DmaPlayInHandShakeMode();
815: #endif
816: }
817:
818: void DSP_SsiReceive_SC2(Uint32 FrameCounter)
819: {
820: #if ENABLE_DSP_EMU
821: dsp_core_ssi_Receive_SC2(FrameCounter);
822: #endif
823: }
824:
825: void DSP_SsiTransmit_SC2(Uint32 frame)
826: {
827: #if ENABLE_DSP_EMU
828: // Crossbar_DmaRecordInHandShakeMode_Frame(frame);
829: #endif
830: }
831:
832: void DSP_SsiReceive_SCK(void)
833: {
834: #if ENABLE_DSP_EMU
835: dsp_core_ssi_Receive_SCK();
836: #endif
837: }
838:
839: void DSP_SsiTransmit_SCK(void)
840: {
841: #if ENABLE_DSP_EMU
842: #endif
843: }
844:
845: /**
846: * Read access wrapper for ioMemTabFalcon (DSP Host port)
847: * DSP Host interface port is accessed by the 68030 in Byte mode.
848: * A move.w value,$ffA206 results in 2 bus access for the 68030.
849: */
850: void DSP_HandleReadAccess(void)
851: {
852: Uint32 addr;
853: Uint8 value;
854: bool multi_access = false;
855:
856: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
857: {
858: #if ENABLE_DSP_EMU
859: value = dsp_core_read_host(addr-DSP_HW_OFFSET);
860: #else
861: /* this value prevents TOS from hanging in the DSP init code */
862: value = 0xff;
863: #endif
864: if (multi_access == true)
865: M68000_AddCycles(4);
866: multi_access = true;
867:
868: Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc()));
869: IoMem_WriteByte(addr, value);
870: }
871: }
872:
873: /**
874: * Write access wrapper for ioMemTabFalcon (DSP Host port)
875: * DSP Host interface port is accessed by the 68030 in Byte mode.
876: * A move.w value,$ffA206 results in 2 bus access for the 68030.
877: */
878: void DSP_HandleWriteAccess(void)
879: {
880: Uint32 addr;
881: bool multi_access = false;
882:
883: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
884: {
885: #if ENABLE_DSP_EMU
886: Uint8 value = IoMem_ReadByte(addr);
887: Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc()));
888: dsp_core_write_host(addr-DSP_HW_OFFSET, value);
889: #endif
890: if (multi_access == true)
891: M68000_AddCycles(4);
892: multi_access = true;
893: }
894: }
895:
896:
897:
898: /* Previous Register Access */
899: #define LOG_DSP_REG_LEVEL LOG_DEBUG
900:
901: #define IO_SEG_MASK 0x1FFFF
902:
903: /* Register bits */
904:
905: #define ICR_INIT 0x80
906: #define ICR_HM1 0x40
907: #define ICR_HM0 0x20
908: #define ICR_HF1 0x10
909: #define ICR_HF0 0x08
910: #define ICR_TREQ 0x02
911: #define ICR_RREQ 0x01
912:
913: #define CVR_HC 0x80
914: #define CVR_HV 0x1F
915:
916: #define ISR_HREQ 0x80
917: #define ISR_DMA 0x40
918: #define ISR_HF3 0x10
919: #define ISR_HF2 0x08
920: #define ISR_TRDY 0x04
921: #define ISR_TXDE 0x02
922: #define ISR_RXDF 0x01
923:
924:
925: void DSP_ICR_Read(void) { // 0x02008000
926: #if ENABLE_DSP_EMU
927: if (bDspEmulated)
928: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_ICR);
929: else
930: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x7F;
931: #else
932: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x7F;
933: #endif
934: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ICR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
935: }
936:
937: void DSP_ICR_Write(void) {
938: #if ENABLE_DSP_EMU
939: if (bDspEmulated)
940: dsp_core_write_host(CPU_HOST_ICR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
941: #endif
942: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ICR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
943: }
944:
945: void DSP_CVR_Read(void) { // 0x02008001
946: #if ENABLE_DSP_EMU
947: if (bDspEmulated)
948: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_CVR);
949: else
950: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
951: #else
952: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
953: #endif
954: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] CVR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
955: }
956:
957: void DSP_CVR_Write(void) {
958: #if ENABLE_DSP_EMU
959: if (bDspEmulated)
960: dsp_core_write_host(CPU_HOST_CVR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
961: #endif
962: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] CVR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
963: }
964:
965: void DSP_ISR_Read(void) { // 0x02008002
966: #if ENABLE_DSP_EMU
967: if (bDspEmulated)
968: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_ISR);
969: else
970: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
971: #else
972: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
973: #endif
974: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ISR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
975: }
976:
977: void DSP_ISR_Write(void) {
978: #if ENABLE_DSP_EMU
979: if (bDspEmulated)
980: dsp_core_write_host(CPU_HOST_ISR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
981: #endif
982: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] ISR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
983: }
984:
985: void DSP_IVR_Read(void) { // 0x02008003
986: #if ENABLE_DSP_EMU
987: if (bDspEmulated)
988: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_IVR);
989: else
990: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
991: #else
992: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0xFF;
993: #endif
994: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] IVR read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
995: }
996:
997: void DSP_IVR_Write(void) {
998: #if ENABLE_DSP_EMU
999: if (bDspEmulated)
1000: dsp_core_write_host(CPU_HOST_IVR, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1001: #endif
1002: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] IVR write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1003: }
1004:
1005: void DSP_Data0_Read(void) { // 0x02008004
1006: #if ENABLE_DSP_EMU
1007: if (bDspEmulated)
1008: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRX0);
1009: else
1010: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1011: #else
1012: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1013: #endif
1014: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data0 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1015: }
1016:
1017: void DSP_Data0_Write(void) {
1018: #if ENABLE_DSP_EMU
1019: if (bDspEmulated)
1020: dsp_core_write_host(CPU_HOST_TRX0, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1021: #endif
1022: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data0 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1023: }
1024:
1025: void DSP_Data1_Read(void) { // 0x02008005
1026: #if ENABLE_DSP_EMU
1027: if (bDspEmulated)
1028: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXH);
1029: else
1030: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1031: #else
1032: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1033: #endif
1034: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data1 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1035: }
1036:
1037: void DSP_Data1_Write(void) {
1038: #if ENABLE_DSP_EMU
1039: if (bDspEmulated)
1040: dsp_core_write_host(CPU_HOST_TRXH, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1041: #endif
1042: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data1 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1043: }
1044:
1045: void DSP_Data2_Read(void) { // 0x02008006
1046: #if ENABLE_DSP_EMU
1047: if (bDspEmulated)
1048: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXM);
1049: else
1050: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1051: #else
1052: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1053: #endif
1054: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data2 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1055: }
1056:
1057: void DSP_Data2_Write(void) {
1058: #if ENABLE_DSP_EMU
1059: if (bDspEmulated)
1060: dsp_core_write_host(CPU_HOST_TRXM, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1061: #endif
1062: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data2 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1063: }
1064:
1065: void DSP_Data3_Read(void) { // 0x02008007
1066: #if ENABLE_DSP_EMU
1067: if (bDspEmulated)
1068: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = dsp_core_read_host(CPU_HOST_TRXL);
1069: else
1070: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1071: #else
1072: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = 0x00;
1073: #endif
1074: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data3 read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1075: }
1076:
1077: void DSP_Data3_Write(void) {
1078: #if ENABLE_DSP_EMU
1079: if (bDspEmulated)
1080: dsp_core_write_host(CPU_HOST_TRXL, IoMem[IoAccessCurrentAddress & IO_SEG_MASK]);
1081: #endif
1082: Log_Printf(LOG_DSP_REG_LEVEL,"[DSP] Data3 write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc());
1083: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.