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