|
|
1.1 root 1: /*
1.1.1.2 root 2: DSP M56001 emulation
3: Dummy emulation, Hatari glue
1.1 root 4:
1.1.1.2 root 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
1.1.1.13! root 19: along with this program; if not, write to the Free Software Foundation,
! 20: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
1.1.1.2 root 21: */
22:
1.1.1.10 root 23: #include <ctype.h>
24:
1.1 root 25: #include "main.h"
26: #include "sysdeps.h"
1.1.1.2 root 27: #include "newcpu.h"
1.1.1.3 root 28: #include "memorySnapShot.h"
1.1 root 29: #include "ioMem.h"
30: #include "dsp.h"
1.1.1.4 root 31: #include "crossbar.h"
32: #include "configuration.h"
1.1.1.6 root 33: #include "cycInt.h"
1.1.1.9 root 34: #include "m68000.h"
1.1.1.4 root 35:
1.1.1.3 root 36: #if ENABLE_DSP_EMU
1.1.1.4 root 37: #include "debugdsp.h"
1.1.1.3 root 38: #include "dsp_cpu.h"
39: #include "dsp_disasm.h"
40: #endif
1.1 root 41:
1.1.1.2 root 42: #define DEBUG 0
1.1.1.3 root 43: #if DEBUG
44: #define Dprintf(a) printf a
45: #else
46: #define Dprintf(a)
47: #endif
48:
49: #define DSP_HW_OFFSET 0xFFA200
50:
1.1.1.4 root 51:
1.1.1.3 root 52: #if ENABLE_DSP_EMU
1.1.1.7 root 53: static const char* x_ext_memory_addr_name[] = {
54: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
55: "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
56: "PBC", "PCC", "PBDDR", "PCDDR", "PBD", "PCD", "", "",
57: "HCR", "HSR", "", "HRX/HTX", "CRA", "CRB", "SSISR/TSR", "RX/TX",
58: "SCR", "SSR", "SCCR", "STXA", "SRX/STX", "SRX/STX", "SRX/STX", "",
1.1.1.9 root 59: "", "", "", "", "", "", "BCR", "IPR"
1.1.1.7 root 60: };
61:
1.1.1.9 root 62: static Sint32 save_cycles;
63: #endif
64:
65: static bool bDspDebugging;
66:
67: bool bDspEnabled = false;
68: bool bDspHostInterruptPending = false;
69:
1.1.1.12 root 70: Uint64 DSP_CyclesGlobalClockCounter = 0; /* Value of CyclesGlobalClockCounter when DSP_Run was last called */
71:
1.1.1.4 root 72:
73: /**
74: * Trigger HREQ interrupt at the host CPU.
75: */
76: #if ENABLE_DSP_EMU
1.1.1.11 root 77: static void DSP_TriggerHostInterrupt(int hreq)
1.1.1.4 root 78: {
1.1.1.11 root 79: //fprintf ( stderr, "DSP_TriggerHostInterrupt %d %x %x\n" , hreq , regs.sr , regs.intmask );
80: if ( hreq )
81: {
82: M68000_SetSpecial(SPCFLAG_DSP); // TODO for old cpu core, remove, use level 6 instead and M68000_Update_intlev()
83: bDspHostInterruptPending = true;
84: M68000_Update_intlev ();
85: }
86: else
87: {
88: M68000_UnsetSpecial(SPCFLAG_DSP); // TODO for old cpu core, remove, use level 6 instead and M68000_Update_intlev()
89: bDspHostInterruptPending = false;
90: M68000_Update_intlev ();
91: }
1.1.1.9 root 92: }
93: #endif
1.1.1.4 root 94:
1.1.1.9 root 95:
96: /**
1.1.1.11 root 97: * Return the state of HREQ
98: */
99: Uint8 DSP_GetHREQ ( void )
100: {
101: if ( bDspHostInterruptPending )
102: return 1;
103: else
104: return 0;
105: }
106:
107:
108: /**
109: * Return the vector number associated to the HREQ interrupt.
110: * If this function is called when HREQ=0, then we return -1 to indicate
111: * a spurious interrupt.
112: */
113: int DSP_ProcessIACK ( void )
114: {
115: int VecNr;
116:
117: if ( bDspHostInterruptPending )
118: VecNr = IoMem_ReadByte ( 0xffa203 );
119: else
120: VecNr = -1;
121:
122: return VecNr;
123: }
124:
125:
126: /**
1.1.1.9 root 127: * This function is called from the CPU emulation part when SPCFLAG_DSP is set.
128: * If the DSP's IRQ signal is set, we check that SR allows a level 6 interrupt,
129: * and if so, we call M68000_Exception.
130: */
131: #if ENABLE_DSP_EMU
132: bool DSP_ProcessIRQ(void)
133: {
134: if (bDspHostInterruptPending && regs.intmask < 6)
135: {
1.1.1.11 root 136: M68000_Exception(IoMem_ReadByte(0xffa203), M68000_EXC_SRC_INT_DSP);
137: bDspHostInterruptPending = false; // [NP] TODO : remove this line, should be cleared by DSP_TriggerHostInterrupt ?
138: M68000_UnsetSpecial(SPCFLAG_DSP); // [NP] TODO : remove this line, should be cleared by DSP_TriggerHostInterrupt ?
1.1.1.9 root 139: return true;
140: }
141:
142: return false;
1.1.1.4 root 143: }
144: #endif
1.1 root 145:
146:
1.1.1.3 root 147: /**
1.1.1.11 root 148: * Initialize the DSP emulation (should be called only once at start)
1.1.1.3 root 149: */
1.1 root 150: void DSP_Init(void)
151: {
1.1.1.3 root 152: #if ENABLE_DSP_EMU
1.1.1.5 root 153: dsp_core_init(DSP_TriggerHostInterrupt);
154: dsp56k_init_cpu();
1.1.1.4 root 155: save_cycles = 0;
1.1 root 156: #endif
157: }
158:
1.1.1.3 root 159:
160: /**
1.1.1.11 root 161: * Shut down the DSP emulation (should be called only once at exit)
1.1.1.3 root 162: */
1.1 root 163: void DSP_UnInit(void)
164: {
1.1.1.3 root 165: #if ENABLE_DSP_EMU
1.1.1.5 root 166: dsp_core_shutdown();
1.1.1.3 root 167: bDspEnabled = false;
1.1.1.2 root 168: #endif
1.1 root 169: }
170:
1.1.1.3 root 171:
172: /**
173: * Reset the DSP emulation
174: */
1.1 root 175: void DSP_Reset(void)
176: {
1.1.1.3 root 177: #if ENABLE_DSP_EMU
1.1.1.5 root 178: dsp_core_reset();
1.1.1.11 root 179: DSP_TriggerHostInterrupt ( 0 ); /* Clear HREQ */
1.1.1.4 root 180: save_cycles = 0;
1.1 root 181: #endif
182: }
183:
184:
1.1.1.3 root 185: /**
1.1.1.11 root 186: * Enable the DSP emulation
187: */
188: void DSP_Enable(void)
189: {
190: #if ENABLE_DSP_EMU
191: bDspEnabled = true;
1.1.1.12 root 192: DSP_CyclesGlobalClockCounter = CyclesGlobalClockCounter;
1.1.1.11 root 193: #endif
194: }
195:
196:
197: /**
198: * Disable the DSP emulation
199: */
200: void DSP_Disable(void)
201: {
202: #if ENABLE_DSP_EMU
203: bDspEnabled = false;
204: #endif
205: }
206:
207:
208: /**
1.1.1.3 root 209: * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
210: */
211: void DSP_MemorySnapShot_Capture(bool bSave)
212: {
213: #if ENABLE_DSP_EMU
214: MemorySnapShot_Store(&bDspEnabled, sizeof(bDspEnabled));
215: MemorySnapShot_Store(&dsp_core, sizeof(dsp_core));
1.1.1.4 root 216: MemorySnapShot_Store(&save_cycles, sizeof(save_cycles));
1.1.1.11 root 217:
218: if ( bDspEnabled )
219: DSP_Enable();
220: else
221: DSP_Disable();
1.1.1.3 root 222: #endif
223: }
224:
225: /**
226: * Run DSP for certain cycles
227: */
228: void DSP_Run(int nHostCycles)
229: {
230: #if ENABLE_DSP_EMU
1.1.1.12 root 231: if ( nHostCycles == 0 )
232: return;
233:
234: DSP_CyclesGlobalClockCounter = CyclesGlobalClockCounter;
235:
1.1.1.13! root 236: save_cycles += nHostCycles * 2;
1.1.1.3 root 237:
1.1.1.13! root 238: if (dsp_core.running == 0)
! 239: return;
1.1.1.3 root 240:
1.1.1.13! root 241: if (save_cycles <= 0)
! 242: return;
1.1.1.5 root 243:
1.1.1.13! root 244: if (unlikely(bDspDebugging))
! 245: {
! 246: while (save_cycles > 0)
! 247: {
! 248: dsp56k_execute_instruction();
! 249: save_cycles -= dsp_core.instr_cycle;
! 250: DebugDsp_Check();
! 251: }
! 252: }
! 253: else
! 254: {
! 255: // fprintf(stderr, "--> %d\n", save_cycles);
! 256: while (save_cycles > 0)
! 257: {
! 258: dsp56k_execute_instruction();
! 259: save_cycles -= dsp_core.instr_cycle;
! 260: }
! 261: }
1.1.1.4 root 262:
1.1.1.3 root 263: #endif
1.1.1.5 root 264: }
1.1.1.3 root 265:
266: /**
267: * Enable/disable DSP debugging mode
268: */
269: void DSP_SetDebugging(bool enabled)
270: {
271: bDspDebugging = enabled;
272: }
273:
274: /**
1.1.1.5 root 275: * Get DSP program counter (for debugging)
1.1.1.3 root 276: */
277: Uint16 DSP_GetPC(void)
278: {
279: #if ENABLE_DSP_EMU
280: if (bDspEnabled)
281: return dsp_core.pc;
282: else
283: #endif
284: return 0;
285: }
286:
1.1.1.5 root 287: /**
1.1.1.9 root 288: * Get next DSP PC without output (for debugging)
289: */
290: Uint16 DSP_GetNextPC(Uint16 pc)
291: {
292: #if ENABLE_DSP_EMU
293: /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */
294: dsp_core_t dsp_core_save;
295: Uint16 instruction_length;
296:
297: if (!bDspEnabled)
298: return 0;
299:
300: /* Save DSP context */
301: memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core));
302:
303: /* Disasm instruction */
304: dsp_core.pc = pc;
305: /* why dsp56k_execute_one_disasm_instruction() does "-1"
306: * for this value, that doesn't seem right???
307: */
1.1.1.12 root 308: instruction_length = dsp56k_disasm(DSP_DISASM_MODE, stderr);
1.1.1.9 root 309:
310: /* Restore DSP context */
311: memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core));
312:
313: return pc + instruction_length;
314: #else
315: return 0;
316: #endif
317: }
318:
319: /**
1.1.1.5 root 320: * Get current DSP instruction cycles (for profiling)
321: */
322: Uint16 DSP_GetInstrCycles(void)
323: {
324: #if ENABLE_DSP_EMU
325: if (bDspEnabled)
326: return dsp_core.instr_cycle;
327: else
328: #endif
329: return 0;
330: }
331:
1.1.1.3 root 332:
333: /**
1.1.1.4 root 334: * Disassemble DSP code between given addresses, return next PC address
1.1.1.3 root 335: */
1.1.1.9 root 336: Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr)
1.1.1.3 root 337: {
338: #if ENABLE_DSP_EMU
1.1.1.8 root 339: Uint16 dsp_pc;
1.1.1.4 root 340:
1.1.1.5 root 341: for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) {
1.1.1.9 root 342: dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc);
1.1.1.3 root 343: }
344: return dsp_pc;
345: #else
346: return 0;
347: #endif
348: }
349:
350:
351: /**
352: * Get the value from the given (16-bit) DSP memory address / space
353: * exactly the same way as in dsp_cpu.c::read_memory() (except for
354: * the host/transmit peripheral register values which access has
355: * side-effects). Set the mem_str to suitable string for that
356: * address / space.
357: * Return the value at given address. For valid values AND the return
358: * value with BITMASK(24).
359: */
360: Uint32 DSP_ReadMemory(Uint16 address, char space_id, const char **mem_str)
361: {
362: #if ENABLE_DSP_EMU
363: static const char *spaces[3][4] = {
364: { "X ram", "X rom", "X", "X periph" },
365: { "Y ram", "Y rom", "Y", "Y periph" },
366: { "P ram", "P ram", "P ext memory", "P ext memory" }
367: };
368: int idx, space;
369:
370: switch (space_id) {
371: case 'X':
372: space = DSP_SPACE_X;
373: idx = 0;
374: break;
375: case 'Y':
376: space = DSP_SPACE_Y;
377: idx = 1;
378: break;
379: case 'P':
380: space = DSP_SPACE_P;
381: idx = 2;
382: break;
383: default:
384: space = DSP_SPACE_X;
385: idx = 0;
386: }
387: address &= 0xFFFF;
388:
389: /* Internal RAM ? */
390: if (address < 0x100) {
391: *mem_str = spaces[idx][0];
392: return dsp_core.ramint[space][address];
393: }
394:
395: if (space == DSP_SPACE_P) {
396: /* Internal RAM ? */
397: if (address < 0x200) {
398: *mem_str = spaces[idx][0];
399: return dsp_core.ramint[DSP_SPACE_P][address];
400: }
401: /* External RAM, mask address to available ram size */
402: *mem_str = spaces[idx][2];
403: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
404: }
405:
406: /* Internal ROM ? */
407: if (address < 0x200) {
408: if (dsp_core.registers[DSP_REG_OMR] & (1<<DSP_OMR_DE)) {
409: *mem_str = spaces[idx][1];
410: return dsp_core.rom[space][address];
411: }
412: }
413:
414: /* Peripheral address ? */
415: if (address >= 0xffc0) {
416: *mem_str = spaces[idx][3];
417: /* reading host/transmit regs has side-effects,
418: * so just give the memory value.
419: */
420: return dsp_core.periph[space][address-0xffc0];
421: }
422:
423: /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */
424: address &= (DSP_RAMSIZE>>1) - 1;
425: if (space == DSP_SPACE_X) {
426: address += DSP_RAMSIZE>>1;
427: }
428:
429: /* Falcon: External RAM, finally map X,Y to P */
430: *mem_str = spaces[idx][2];
431: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
432: #endif
433: return 0;
434: }
435:
436:
437: /**
438: * Output memory values between given addresses in given DSP address space.
1.1.1.4 root 439: * Return next DSP address value.
1.1.1.3 root 440: */
1.1.1.12 root 441: Uint16 DSP_DisasmMemory(FILE *fp, Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space)
1.1.1.3 root 442: {
443: #if ENABLE_DSP_EMU
444: Uint32 mem, mem2, value;
445: const char *mem_str;
446:
447: for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) {
448: /* special printing of host communication/transmit registers */
1.1.1.7 root 449: if (space == 'X' && mem >= 0xffc0) {
1.1.1.3 root 450: if (mem == 0xffeb) {
1.1.1.12 root 451: fprintf(fp, "X periph:%04x HTX : %06x RTX:%06x\n",
1.1.1.3 root 452: mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx);
453: }
454: else if (mem == 0xffef) {
1.1.1.12 root 455: fprintf(fp, "X periph:%04x SSI TX : %06x SSI RX:%06x\n",
1.1.1.3 root 456: mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value);
457: }
1.1.1.7 root 458: else {
459: value = DSP_ReadMemory(mem, space, &mem_str);
1.1.1.12 root 460: fprintf(fp, "%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]);
1.1.1.7 root 461: }
1.1.1.3 root 462: continue;
463: }
464: /* special printing of X & Y external RAM values */
465: if ((space == 'X' || space == 'Y') &&
466: mem >= 0x200 && mem < 0xffc0) {
467: mem2 = mem & ((DSP_RAMSIZE>>1)-1);
468: if (space == 'X') {
469: mem2 += (DSP_RAMSIZE>>1);
470: }
1.1.1.12 root 471: fprintf(fp, "%c:%04x (P:%04x): %06x\n", space,
1.1.1.3 root 472: mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]);
473: continue;
474: }
475: value = DSP_ReadMemory(mem, space, &mem_str);
1.1.1.12 root 476: fprintf(fp, "%s:%04x %06x\n", mem_str, mem, value);
1.1.1.3 root 477: }
478: #endif
1.1.1.4 root 479: return dsp_memdump_upper+1;
1.1.1.3 root 480: }
481:
1.1.1.9 root 482: /**
483: * Show information on DSP core state which isn't
484: * shown by any of the other commands (dd, dm, dr).
485: */
1.1.1.11 root 486: void DSP_Info(FILE *fp, Uint32 dummy)
1.1.1.9 root 487: {
488: #if ENABLE_DSP_EMU
489: int i, j;
490: const char *stackname[] = { "SSH", "SSL" };
491:
1.1.1.11 root 492: fputs("DSP core information:\n", fp);
1.1.1.9 root 493:
1.1.1.12 root 494: for (i = 0; i < ARRAY_SIZE(stackname); i++) {
1.1.1.11 root 495: fprintf(fp, "- %s stack:", stackname[i]);
1.1.1.12 root 496: for (j = 0; j < ARRAY_SIZE(dsp_core.stack[0]); j++) {
1.1.1.11 root 497: fprintf(fp, " %04hx", dsp_core.stack[i][j]);
1.1.1.9 root 498: }
1.1.1.11 root 499: fputs("\n", fp);
1.1.1.9 root 500: }
501:
1.1.1.11 root 502: fprintf(fp, "- Interrupt IPL:");
1.1.1.12 root 503: for (i = 0; i < ARRAY_SIZE(dsp_core.interrupt_ipl); i++) {
1.1.1.11 root 504: fprintf(fp, " %04hx", dsp_core.interrupt_ipl[i]);
1.1.1.9 root 505: }
1.1.1.11 root 506: fputs("\n", fp);
1.1.1.9 root 507:
1.1.1.11 root 508: fprintf(fp, "- Pending ints: ");
1.1.1.12 root 509: for (i = 0; i < ARRAY_SIZE(dsp_core.interrupt_isPending); i++) {
1.1.1.11 root 510: fprintf(fp, " %04hx", dsp_core.interrupt_isPending[i]);
1.1.1.9 root 511: }
1.1.1.11 root 512: fputs("\n", fp);
1.1.1.9 root 513:
1.1.1.11 root 514: fprintf(fp, "- Hostport:");
1.1.1.12 root 515: for (i = 0; i < ARRAY_SIZE(dsp_core.hostport); i++) {
1.1.1.11 root 516: fprintf(fp, " %02x", dsp_core.hostport[i]);
1.1.1.9 root 517: }
1.1.1.11 root 518: fputs("\n", fp);
1.1.1.9 root 519: #endif
520: }
1.1.1.3 root 521:
1.1.1.9 root 522: /**
523: * Show DSP register contents
524: */
1.1.1.12 root 525: void DSP_DisasmRegisters(FILE *fp)
1.1.1.3 root 526: {
527: #if ENABLE_DSP_EMU
528: Uint32 i;
529:
1.1.1.12 root 530: fprintf(fp, "A: A2: %02x A1: %06x A0: %06x\n",
1.1.1.3 root 531: dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]);
1.1.1.12 root 532: fprintf(fp, "B: B2: %02x B1: %06x B0: %06x\n",
1.1.1.3 root 533: dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]);
534:
1.1.1.12 root 535: fprintf(fp, "X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]);
536: fprintf(fp, "Y: Y1: %06x Y0: %06x\n", dsp_core.registers[DSP_REG_Y1], dsp_core.registers[DSP_REG_Y0]);
1.1.1.3 root 537:
538: for (i=0; i<8; i++) {
1.1.1.12 root 539: fprintf(fp, "R%01x: %04x N%01x: %04x M%01x: %04x\n",
1.1.1.3 root 540: i, dsp_core.registers[DSP_REG_R0+i],
541: i, dsp_core.registers[DSP_REG_N0+i],
542: i, dsp_core.registers[DSP_REG_M0+i]);
543: }
544:
1.1.1.12 root 545: fprintf(fp, "LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc);
546: fprintf(fp, "SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]);
547: fprintf(fp, "SP: %02x SSH: %04x SSL: %04x\n",
1.1.1.3 root 548: dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]);
549: #endif
550: }
551:
552:
553: /**
554: * Get given DSP register address and required bit mask.
555: * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP,
556: * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers
557: * need special handling (in DSP*SetRegister()) when they are set.
558: * Return the register width in bits or zero for an error.
559: */
560: int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask)
561: {
562: #if ENABLE_DSP_EMU
563: #define MAX_REGNAME_LEN 4
564: typedef struct {
565: const char name[MAX_REGNAME_LEN];
566: Uint32 *addr;
567: size_t bits;
568: Uint32 mask;
569: } reg_addr_t;
570:
571: /* sorted by name so that this can be bisected */
572: static const reg_addr_t registers[] = {
573:
574: /* 56-bit A register */
575: { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) },
576: { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) },
577: { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) },
578:
579: /* 56-bit B register */
580: { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) },
581: { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) },
582: { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) },
583:
584: /* 16-bit LA & LC registers */
585: { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) },
586: { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) },
587:
588: /* 16-bit M registers */
589: { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) },
590: { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) },
591: { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) },
592: { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) },
593: { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) },
594: { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) },
595: { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) },
596: { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) },
597:
598: /* 16-bit N registers */
599: { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) },
600: { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) },
601: { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) },
602: { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) },
603: { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) },
604: { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) },
605: { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) },
606: { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) },
607:
608: { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f },
609:
610: /* 16-bit program counter */
611: { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) },
612:
613: /* 16-bit DSP R (address) registers */
614: { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) },
615: { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) },
616: { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) },
617: { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) },
618: { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) },
619: { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) },
620: { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) },
621: { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) },
622:
623: { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) },
624: { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) },
625: { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) },
626:
627: /* 16-bit status register */
628: { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff },
629:
630: /* 48-bit X register */
631: { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) },
632: { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) },
633:
634: /* 48-bit Y register */
635: { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) },
636: { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) }
637: };
638: /* left, right, middle, direction */
1.1.1.10 root 639: int l, r, m, dir = 0;
1.1.1.4 root 640: unsigned int i, len;
1.1.1.3 root 641: char reg[MAX_REGNAME_LEN];
642:
1.1.1.4 root 643: if (!bDspEnabled) {
644: return 0;
645: }
646:
1.1.1.3 root 647: for (i = 0; i < sizeof(reg) && regname[i]; i++) {
1.1.1.10 root 648: reg[i] = toupper((unsigned char)regname[i]);
1.1.1.3 root 649: }
650: if (i < 2 || regname[i]) {
651: /* too short or longer than any of the names */
652: return 0;
653: }
1.1.1.4 root 654: len = i;
655:
1.1.1.3 root 656: /* bisect */
657: l = 0;
1.1.1.12 root 658: r = ARRAY_SIZE(registers) - 1;
1.1.1.3 root 659: do {
660: m = (l+r) >> 1;
1.1.1.4 root 661: for (i = 0; i < len; i++) {
1.1.1.3 root 662: dir = (int)reg[i] - registers[m].name[i];
663: if (dir) {
664: break;
665: }
666: }
667: if (dir == 0) {
668: *addr = registers[m].addr;
669: *mask = registers[m].mask;
670: return registers[m].bits;
671: }
672: if (dir < 0) {
673: r = m-1;
674: } else {
675: l = m+1;
676: }
677: } while (l <= r);
678: #undef MAX_REGNAME_LEN
679: #endif
680: return 0;
681: }
682:
683:
684: /**
1.1.1.4 root 685: * Set given DSP register value, return false if unknown register given
1.1.1.3 root 686: */
1.1.1.4 root 687: bool DSP_Disasm_SetRegister(const char *arg, Uint32 value)
1.1.1.3 root 688: {
689: #if ENABLE_DSP_EMU
690: Uint32 *addr, mask, sp_value;
691: int bits;
692:
693: /* first check registers needing special handling... */
694: if (arg[0]=='S' || arg[0]=='s') {
695: if (arg[1]=='P' || arg[1]=='p') {
696: dsp_core.registers[DSP_REG_SP] = value & BITMASK(6);
697: value &= BITMASK(4);
698: dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value];
699: dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value];
1.1.1.4 root 700: return true;
1.1.1.3 root 701: }
702: if (arg[1]=='S' || arg[1]=='s') {
703: sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4);
704: if (arg[2]=='H' || arg[2]=='h') {
705: if (sp_value == 0) {
706: dsp_core.registers[DSP_REG_SSH] = 0;
707: dsp_core.stack[0][sp_value] = 0;
708: } else {
709: dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16);
710: dsp_core.stack[0][sp_value] = value & BITMASK(16);
711: }
1.1.1.4 root 712: return true;
1.1.1.3 root 713: }
714: if (arg[2]=='L' || arg[2]=='l') {
715: if (sp_value == 0) {
716: dsp_core.registers[DSP_REG_SSL] = 0;
717: dsp_core.stack[1][sp_value] = 0;
718: } else {
719: dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16);
720: dsp_core.stack[1][sp_value] = value & BITMASK(16);
721: }
1.1.1.4 root 722: return true;
1.1.1.3 root 723: }
724: }
725: }
726:
727: /* ...then registers where address & mask are enough */
728: bits = DSP_GetRegisterAddress(arg, &addr, &mask);
729: switch (bits) {
730: case 32:
731: *addr = value & mask;
1.1.1.4 root 732: return true;
1.1.1.3 root 733: case 16:
734: *(Uint16*)addr = value & mask;
1.1.1.4 root 735: return true;
1.1.1.3 root 736: }
737: #endif
1.1.1.4 root 738: return false;
1.1.1.3 root 739: }
740:
741: /**
742: * Read SSI transmit value
743: */
744: Uint32 DSP_SsiReadTxValue(void)
745: {
746: #if ENABLE_DSP_EMU
747: return dsp_core.ssi.transmit_value;
748: #else
749: return 0;
750: #endif
751: }
752:
753: /**
754: * Write SSI receive value
755: */
756: void DSP_SsiWriteRxValue(Uint32 value)
757: {
758: #if ENABLE_DSP_EMU
759: dsp_core.ssi.received_value = value & 0xffffff;
760: #endif
761: }
762:
763: /**
764: * Signal SSI clock tick to DSP
765: */
1.1.1.4 root 766:
767: void DSP_SsiReceive_SC0(void)
1.1.1.3 root 768: {
769: #if ENABLE_DSP_EMU
1.1.1.5 root 770: dsp_core_ssi_Receive_SC0();
1.1.1.3 root 771: #endif
772: }
773:
1.1.1.4 root 774: void DSP_SsiTransmit_SC0(void)
1.1.1.3 root 775: {
776: #if ENABLE_DSP_EMU
777: #endif
778: }
779:
1.1.1.4 root 780: void DSP_SsiReceive_SC1(Uint32 FrameCounter)
1.1 root 781: {
1.1.1.3 root 782: #if ENABLE_DSP_EMU
1.1.1.5 root 783: dsp_core_ssi_Receive_SC1(FrameCounter);
1.1 root 784: #endif
1.1.1.4 root 785: }
1.1 root 786:
1.1.1.4 root 787: void DSP_SsiTransmit_SC1(void)
788: {
789: #if ENABLE_DSP_EMU
790: Crossbar_DmaPlayInHandShakeMode();
791: #endif
1.1 root 792: }
793:
1.1.1.4 root 794: void DSP_SsiReceive_SC2(Uint32 FrameCounter)
1.1 root 795: {
1.1.1.4 root 796: #if ENABLE_DSP_EMU
1.1.1.5 root 797: dsp_core_ssi_Receive_SC2(FrameCounter);
1.1.1.4 root 798: #endif
799: }
800:
801: void DSP_SsiTransmit_SC2(Uint32 frame)
802: {
803: #if ENABLE_DSP_EMU
804: Crossbar_DmaRecordInHandShakeMode_Frame(frame);
805: #endif
1.1 root 806: }
807:
1.1.1.4 root 808: void DSP_SsiReceive_SCK(void)
809: {
810: #if ENABLE_DSP_EMU
1.1.1.5 root 811: dsp_core_ssi_Receive_SCK();
1.1.1.4 root 812: #endif
813: }
814:
815: void DSP_SsiTransmit_SCK(void)
816: {
817: #if ENABLE_DSP_EMU
818: #endif
819: }
1.1.1.2 root 820:
1.1.1.3 root 821: /**
1.1.1.4 root 822: * Read access wrapper for ioMemTabFalcon (DSP Host port)
1.1.1.6 root 823: * DSP Host interface port is accessed by the 68030 in Byte mode.
824: * A move.w value,$ffA206 results in 2 bus access for the 68030.
1.1.1.3 root 825: */
1.1.1.4 root 826: void DSP_HandleReadAccess(void)
1.1 root 827: {
1.1.1.4 root 828: Uint32 addr;
829: Uint8 value;
1.1.1.6 root 830: bool multi_access = false;
831:
1.1.1.4 root 832: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
833: {
1.1.1.3 root 834: #if ENABLE_DSP_EMU
1.1.1.5 root 835: value = dsp_core_read_host(addr-DSP_HW_OFFSET);
1.1.1.4 root 836: #else
837: /* this value prevents TOS from hanging in the DSP init code */
838: value = 0xff;
1.1 root 839: #endif
1.1.1.9 root 840: if (multi_access == true)
841: M68000_AddCycles(4);
842: multi_access = true;
1.1.1.4 root 843:
844: Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc()));
845: IoMem_WriteByte(addr, value);
846: }
1.1 root 847: }
848:
1.1.1.3 root 849: /**
1.1.1.4 root 850: * Write access wrapper for ioMemTabFalcon (DSP Host port)
1.1.1.6 root 851: * DSP Host interface port is accessed by the 68030 in Byte mode.
852: * A move.w value,$ffA206 results in 2 bus access for the 68030.
1.1.1.3 root 853: */
1.1 root 854: void DSP_HandleWriteAccess(void)
855: {
1.1.1.4 root 856: Uint32 addr;
1.1.1.6 root 857: bool multi_access = false;
858:
1.1.1.4 root 859: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
1.1 root 860: {
1.1.1.4 root 861: #if ENABLE_DSP_EMU
1.1.1.9 root 862: Uint8 value = IoMem_ReadByte(addr);
863: Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc()));
1.1.1.5 root 864: dsp_core_write_host(addr-DSP_HW_OFFSET, value);
1.1.1.9 root 865: #endif
1.1.1.6 root 866: if (multi_access == true)
867: M68000_AddCycles(4);
868: multi_access = true;
1.1 root 869: }
870: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.