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