|
|
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
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:
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.5 root 236: save_cycles += nHostCycles * 2;
1.1.1.3 root 237:
1.1.1.5 root 238: if (dsp_core.running == 0)
239: return;
1.1.1.3 root 240:
1.1.1.5 root 241: if (save_cycles <= 0)
242: return;
243:
244: if (unlikely(bDspDebugging)) {
245: while (save_cycles > 0)
246: {
247: dsp56k_execute_instruction();
248: save_cycles -= dsp_core.instr_cycle;
1.1.1.9 root 249: DebugDsp_Check();
1.1.1.5 root 250: }
251: } else {
252: // fprintf(stderr, "--> %d\n", save_cycles);
253: while (save_cycles > 0)
254: {
255: dsp56k_execute_instruction();
256: save_cycles -= dsp_core.instr_cycle;
257: }
258: }
1.1.1.4 root 259:
1.1.1.3 root 260: #endif
1.1.1.5 root 261: }
1.1.1.3 root 262:
263: /**
264: * Enable/disable DSP debugging mode
265: */
266: void DSP_SetDebugging(bool enabled)
267: {
268: bDspDebugging = enabled;
269: }
270:
271: /**
1.1.1.5 root 272: * Get DSP program counter (for debugging)
1.1.1.3 root 273: */
274: Uint16 DSP_GetPC(void)
275: {
276: #if ENABLE_DSP_EMU
277: if (bDspEnabled)
278: return dsp_core.pc;
279: else
280: #endif
281: return 0;
282: }
283:
1.1.1.5 root 284: /**
1.1.1.9 root 285: * Get next DSP PC without output (for debugging)
286: */
287: Uint16 DSP_GetNextPC(Uint16 pc)
288: {
289: #if ENABLE_DSP_EMU
290: /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */
291: dsp_core_t dsp_core_save;
292: Uint16 instruction_length;
293:
294: if (!bDspEnabled)
295: return 0;
296:
297: /* Save DSP context */
298: memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core));
299:
300: /* Disasm instruction */
301: dsp_core.pc = pc;
302: /* why dsp56k_execute_one_disasm_instruction() does "-1"
303: * for this value, that doesn't seem right???
304: */
1.1.1.12! root 305: instruction_length = dsp56k_disasm(DSP_DISASM_MODE, stderr);
1.1.1.9 root 306:
307: /* Restore DSP context */
308: memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core));
309:
310: return pc + instruction_length;
311: #else
312: return 0;
313: #endif
314: }
315:
316: /**
1.1.1.5 root 317: * Get current DSP instruction cycles (for profiling)
318: */
319: Uint16 DSP_GetInstrCycles(void)
320: {
321: #if ENABLE_DSP_EMU
322: if (bDspEnabled)
323: return dsp_core.instr_cycle;
324: else
325: #endif
326: return 0;
327: }
328:
1.1.1.3 root 329:
330: /**
1.1.1.4 root 331: * Disassemble DSP code between given addresses, return next PC address
1.1.1.3 root 332: */
1.1.1.9 root 333: Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr)
1.1.1.3 root 334: {
335: #if ENABLE_DSP_EMU
1.1.1.8 root 336: Uint16 dsp_pc;
1.1.1.4 root 337:
1.1.1.5 root 338: for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) {
1.1.1.9 root 339: dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc);
1.1.1.3 root 340: }
341: return dsp_pc;
342: #else
343: return 0;
344: #endif
345: }
346:
347:
348: /**
349: * Get the value from the given (16-bit) DSP memory address / space
350: * exactly the same way as in dsp_cpu.c::read_memory() (except for
351: * the host/transmit peripheral register values which access has
352: * side-effects). Set the mem_str to suitable string for that
353: * address / space.
354: * Return the value at given address. For valid values AND the return
355: * value with BITMASK(24).
356: */
357: Uint32 DSP_ReadMemory(Uint16 address, char space_id, const char **mem_str)
358: {
359: #if ENABLE_DSP_EMU
360: static const char *spaces[3][4] = {
361: { "X ram", "X rom", "X", "X periph" },
362: { "Y ram", "Y rom", "Y", "Y periph" },
363: { "P ram", "P ram", "P ext memory", "P ext memory" }
364: };
365: int idx, space;
366:
367: switch (space_id) {
368: case 'X':
369: space = DSP_SPACE_X;
370: idx = 0;
371: break;
372: case 'Y':
373: space = DSP_SPACE_Y;
374: idx = 1;
375: break;
376: case 'P':
377: space = DSP_SPACE_P;
378: idx = 2;
379: break;
380: default:
381: space = DSP_SPACE_X;
382: idx = 0;
383: }
384: address &= 0xFFFF;
385:
386: /* Internal RAM ? */
387: if (address < 0x100) {
388: *mem_str = spaces[idx][0];
389: return dsp_core.ramint[space][address];
390: }
391:
392: if (space == DSP_SPACE_P) {
393: /* Internal RAM ? */
394: if (address < 0x200) {
395: *mem_str = spaces[idx][0];
396: return dsp_core.ramint[DSP_SPACE_P][address];
397: }
398: /* External RAM, mask address to available ram size */
399: *mem_str = spaces[idx][2];
400: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
401: }
402:
403: /* Internal ROM ? */
404: if (address < 0x200) {
405: if (dsp_core.registers[DSP_REG_OMR] & (1<<DSP_OMR_DE)) {
406: *mem_str = spaces[idx][1];
407: return dsp_core.rom[space][address];
408: }
409: }
410:
411: /* Peripheral address ? */
412: if (address >= 0xffc0) {
413: *mem_str = spaces[idx][3];
414: /* reading host/transmit regs has side-effects,
415: * so just give the memory value.
416: */
417: return dsp_core.periph[space][address-0xffc0];
418: }
419:
420: /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */
421: address &= (DSP_RAMSIZE>>1) - 1;
422: if (space == DSP_SPACE_X) {
423: address += DSP_RAMSIZE>>1;
424: }
425:
426: /* Falcon: External RAM, finally map X,Y to P */
427: *mem_str = spaces[idx][2];
428: return dsp_core.ramext[address & (DSP_RAMSIZE-1)];
429: #endif
430: return 0;
431: }
432:
433:
434: /**
435: * Output memory values between given addresses in given DSP address space.
1.1.1.4 root 436: * Return next DSP address value.
1.1.1.3 root 437: */
1.1.1.12! root 438: Uint16 DSP_DisasmMemory(FILE *fp, Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space)
1.1.1.3 root 439: {
440: #if ENABLE_DSP_EMU
441: Uint32 mem, mem2, value;
442: const char *mem_str;
443:
444: for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) {
445: /* special printing of host communication/transmit registers */
1.1.1.7 root 446: if (space == 'X' && mem >= 0xffc0) {
1.1.1.3 root 447: if (mem == 0xffeb) {
1.1.1.12! root 448: fprintf(fp, "X periph:%04x HTX : %06x RTX:%06x\n",
1.1.1.3 root 449: mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx);
450: }
451: else if (mem == 0xffef) {
1.1.1.12! root 452: fprintf(fp, "X periph:%04x SSI TX : %06x SSI RX:%06x\n",
1.1.1.3 root 453: mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value);
454: }
1.1.1.7 root 455: else {
456: value = DSP_ReadMemory(mem, space, &mem_str);
1.1.1.12! root 457: fprintf(fp, "%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]);
1.1.1.7 root 458: }
1.1.1.3 root 459: continue;
460: }
461: /* special printing of X & Y external RAM values */
462: if ((space == 'X' || space == 'Y') &&
463: mem >= 0x200 && mem < 0xffc0) {
464: mem2 = mem & ((DSP_RAMSIZE>>1)-1);
465: if (space == 'X') {
466: mem2 += (DSP_RAMSIZE>>1);
467: }
1.1.1.12! root 468: fprintf(fp, "%c:%04x (P:%04x): %06x\n", space,
1.1.1.3 root 469: mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]);
470: continue;
471: }
472: value = DSP_ReadMemory(mem, space, &mem_str);
1.1.1.12! root 473: fprintf(fp, "%s:%04x %06x\n", mem_str, mem, value);
1.1.1.3 root 474: }
475: #endif
1.1.1.4 root 476: return dsp_memdump_upper+1;
1.1.1.3 root 477: }
478:
1.1.1.9 root 479: /**
480: * Show information on DSP core state which isn't
481: * shown by any of the other commands (dd, dm, dr).
482: */
1.1.1.11 root 483: void DSP_Info(FILE *fp, Uint32 dummy)
1.1.1.9 root 484: {
485: #if ENABLE_DSP_EMU
486: int i, j;
487: const char *stackname[] = { "SSH", "SSL" };
488:
1.1.1.11 root 489: fputs("DSP core information:\n", fp);
1.1.1.9 root 490:
1.1.1.12! root 491: for (i = 0; i < ARRAY_SIZE(stackname); i++) {
1.1.1.11 root 492: fprintf(fp, "- %s stack:", stackname[i]);
1.1.1.12! root 493: for (j = 0; j < ARRAY_SIZE(dsp_core.stack[0]); j++) {
1.1.1.11 root 494: fprintf(fp, " %04hx", dsp_core.stack[i][j]);
1.1.1.9 root 495: }
1.1.1.11 root 496: fputs("\n", fp);
1.1.1.9 root 497: }
498:
1.1.1.11 root 499: fprintf(fp, "- Interrupt IPL:");
1.1.1.12! root 500: for (i = 0; i < ARRAY_SIZE(dsp_core.interrupt_ipl); i++) {
1.1.1.11 root 501: fprintf(fp, " %04hx", dsp_core.interrupt_ipl[i]);
1.1.1.9 root 502: }
1.1.1.11 root 503: fputs("\n", fp);
1.1.1.9 root 504:
1.1.1.11 root 505: fprintf(fp, "- Pending ints: ");
1.1.1.12! root 506: for (i = 0; i < ARRAY_SIZE(dsp_core.interrupt_isPending); i++) {
1.1.1.11 root 507: fprintf(fp, " %04hx", dsp_core.interrupt_isPending[i]);
1.1.1.9 root 508: }
1.1.1.11 root 509: fputs("\n", fp);
1.1.1.9 root 510:
1.1.1.11 root 511: fprintf(fp, "- Hostport:");
1.1.1.12! root 512: for (i = 0; i < ARRAY_SIZE(dsp_core.hostport); i++) {
1.1.1.11 root 513: fprintf(fp, " %02x", dsp_core.hostport[i]);
1.1.1.9 root 514: }
1.1.1.11 root 515: fputs("\n", fp);
1.1.1.9 root 516: #endif
517: }
1.1.1.3 root 518:
1.1.1.9 root 519: /**
520: * Show DSP register contents
521: */
1.1.1.12! root 522: void DSP_DisasmRegisters(FILE *fp)
1.1.1.3 root 523: {
524: #if ENABLE_DSP_EMU
525: Uint32 i;
526:
1.1.1.12! root 527: fprintf(fp, "A: A2: %02x A1: %06x A0: %06x\n",
1.1.1.3 root 528: dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]);
1.1.1.12! root 529: fprintf(fp, "B: B2: %02x B1: %06x B0: %06x\n",
1.1.1.3 root 530: dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]);
531:
1.1.1.12! root 532: fprintf(fp, "X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]);
! 533: 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 534:
535: for (i=0; i<8; i++) {
1.1.1.12! root 536: fprintf(fp, "R%01x: %04x N%01x: %04x M%01x: %04x\n",
1.1.1.3 root 537: i, dsp_core.registers[DSP_REG_R0+i],
538: i, dsp_core.registers[DSP_REG_N0+i],
539: i, dsp_core.registers[DSP_REG_M0+i]);
540: }
541:
1.1.1.12! root 542: fprintf(fp, "LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc);
! 543: fprintf(fp, "SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]);
! 544: fprintf(fp, "SP: %02x SSH: %04x SSL: %04x\n",
1.1.1.3 root 545: dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]);
546: #endif
547: }
548:
549:
550: /**
551: * Get given DSP register address and required bit mask.
552: * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP,
553: * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers
554: * need special handling (in DSP*SetRegister()) when they are set.
555: * Return the register width in bits or zero for an error.
556: */
557: int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask)
558: {
559: #if ENABLE_DSP_EMU
560: #define MAX_REGNAME_LEN 4
561: typedef struct {
562: const char name[MAX_REGNAME_LEN];
563: Uint32 *addr;
564: size_t bits;
565: Uint32 mask;
566: } reg_addr_t;
567:
568: /* sorted by name so that this can be bisected */
569: static const reg_addr_t registers[] = {
570:
571: /* 56-bit A register */
572: { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) },
573: { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) },
574: { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) },
575:
576: /* 56-bit B register */
577: { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) },
578: { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) },
579: { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) },
580:
581: /* 16-bit LA & LC registers */
582: { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) },
583: { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) },
584:
585: /* 16-bit M registers */
586: { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) },
587: { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) },
588: { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) },
589: { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) },
590: { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) },
591: { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) },
592: { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) },
593: { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) },
594:
595: /* 16-bit N registers */
596: { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) },
597: { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) },
598: { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) },
599: { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) },
600: { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) },
601: { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) },
602: { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) },
603: { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) },
604:
605: { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f },
606:
607: /* 16-bit program counter */
608: { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) },
609:
610: /* 16-bit DSP R (address) registers */
611: { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) },
612: { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) },
613: { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) },
614: { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) },
615: { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) },
616: { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) },
617: { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) },
618: { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) },
619:
620: { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) },
621: { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) },
622: { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) },
623:
624: /* 16-bit status register */
625: { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff },
626:
627: /* 48-bit X register */
628: { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) },
629: { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) },
630:
631: /* 48-bit Y register */
632: { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) },
633: { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) }
634: };
635: /* left, right, middle, direction */
1.1.1.10 root 636: int l, r, m, dir = 0;
1.1.1.4 root 637: unsigned int i, len;
1.1.1.3 root 638: char reg[MAX_REGNAME_LEN];
639:
1.1.1.4 root 640: if (!bDspEnabled) {
641: return 0;
642: }
643:
1.1.1.3 root 644: for (i = 0; i < sizeof(reg) && regname[i]; i++) {
1.1.1.10 root 645: reg[i] = toupper((unsigned char)regname[i]);
1.1.1.3 root 646: }
647: if (i < 2 || regname[i]) {
648: /* too short or longer than any of the names */
649: return 0;
650: }
1.1.1.4 root 651: len = i;
652:
1.1.1.3 root 653: /* bisect */
654: l = 0;
1.1.1.12! root 655: r = ARRAY_SIZE(registers) - 1;
1.1.1.3 root 656: do {
657: m = (l+r) >> 1;
1.1.1.4 root 658: for (i = 0; i < len; i++) {
1.1.1.3 root 659: dir = (int)reg[i] - registers[m].name[i];
660: if (dir) {
661: break;
662: }
663: }
664: if (dir == 0) {
665: *addr = registers[m].addr;
666: *mask = registers[m].mask;
667: return registers[m].bits;
668: }
669: if (dir < 0) {
670: r = m-1;
671: } else {
672: l = m+1;
673: }
674: } while (l <= r);
675: #undef MAX_REGNAME_LEN
676: #endif
677: return 0;
678: }
679:
680:
681: /**
1.1.1.4 root 682: * Set given DSP register value, return false if unknown register given
1.1.1.3 root 683: */
1.1.1.4 root 684: bool DSP_Disasm_SetRegister(const char *arg, Uint32 value)
1.1.1.3 root 685: {
686: #if ENABLE_DSP_EMU
687: Uint32 *addr, mask, sp_value;
688: int bits;
689:
690: /* first check registers needing special handling... */
691: if (arg[0]=='S' || arg[0]=='s') {
692: if (arg[1]=='P' || arg[1]=='p') {
693: dsp_core.registers[DSP_REG_SP] = value & BITMASK(6);
694: value &= BITMASK(4);
695: dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value];
696: dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value];
1.1.1.4 root 697: return true;
1.1.1.3 root 698: }
699: if (arg[1]=='S' || arg[1]=='s') {
700: sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4);
701: if (arg[2]=='H' || arg[2]=='h') {
702: if (sp_value == 0) {
703: dsp_core.registers[DSP_REG_SSH] = 0;
704: dsp_core.stack[0][sp_value] = 0;
705: } else {
706: dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16);
707: dsp_core.stack[0][sp_value] = value & BITMASK(16);
708: }
1.1.1.4 root 709: return true;
1.1.1.3 root 710: }
711: if (arg[2]=='L' || arg[2]=='l') {
712: if (sp_value == 0) {
713: dsp_core.registers[DSP_REG_SSL] = 0;
714: dsp_core.stack[1][sp_value] = 0;
715: } else {
716: dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16);
717: dsp_core.stack[1][sp_value] = value & BITMASK(16);
718: }
1.1.1.4 root 719: return true;
1.1.1.3 root 720: }
721: }
722: }
723:
724: /* ...then registers where address & mask are enough */
725: bits = DSP_GetRegisterAddress(arg, &addr, &mask);
726: switch (bits) {
727: case 32:
728: *addr = value & mask;
1.1.1.4 root 729: return true;
1.1.1.3 root 730: case 16:
731: *(Uint16*)addr = value & mask;
1.1.1.4 root 732: return true;
1.1.1.3 root 733: }
734: #endif
1.1.1.4 root 735: return false;
1.1.1.3 root 736: }
737:
738: /**
739: * Read SSI transmit value
740: */
741: Uint32 DSP_SsiReadTxValue(void)
742: {
743: #if ENABLE_DSP_EMU
744: return dsp_core.ssi.transmit_value;
745: #else
746: return 0;
747: #endif
748: }
749:
750: /**
751: * Write SSI receive value
752: */
753: void DSP_SsiWriteRxValue(Uint32 value)
754: {
755: #if ENABLE_DSP_EMU
756: dsp_core.ssi.received_value = value & 0xffffff;
757: #endif
758: }
759:
760: /**
761: * Signal SSI clock tick to DSP
762: */
1.1.1.4 root 763:
764: void DSP_SsiReceive_SC0(void)
1.1.1.3 root 765: {
766: #if ENABLE_DSP_EMU
1.1.1.5 root 767: dsp_core_ssi_Receive_SC0();
1.1.1.3 root 768: #endif
769: }
770:
1.1.1.4 root 771: void DSP_SsiTransmit_SC0(void)
1.1.1.3 root 772: {
773: #if ENABLE_DSP_EMU
774: #endif
775: }
776:
1.1.1.4 root 777: void DSP_SsiReceive_SC1(Uint32 FrameCounter)
1.1 root 778: {
1.1.1.3 root 779: #if ENABLE_DSP_EMU
1.1.1.5 root 780: dsp_core_ssi_Receive_SC1(FrameCounter);
1.1 root 781: #endif
1.1.1.4 root 782: }
1.1 root 783:
1.1.1.4 root 784: void DSP_SsiTransmit_SC1(void)
785: {
786: #if ENABLE_DSP_EMU
787: Crossbar_DmaPlayInHandShakeMode();
788: #endif
1.1 root 789: }
790:
1.1.1.4 root 791: void DSP_SsiReceive_SC2(Uint32 FrameCounter)
1.1 root 792: {
1.1.1.4 root 793: #if ENABLE_DSP_EMU
1.1.1.5 root 794: dsp_core_ssi_Receive_SC2(FrameCounter);
1.1.1.4 root 795: #endif
796: }
797:
798: void DSP_SsiTransmit_SC2(Uint32 frame)
799: {
800: #if ENABLE_DSP_EMU
801: Crossbar_DmaRecordInHandShakeMode_Frame(frame);
802: #endif
1.1 root 803: }
804:
1.1.1.4 root 805: void DSP_SsiReceive_SCK(void)
806: {
807: #if ENABLE_DSP_EMU
1.1.1.5 root 808: dsp_core_ssi_Receive_SCK();
1.1.1.4 root 809: #endif
810: }
811:
812: void DSP_SsiTransmit_SCK(void)
813: {
814: #if ENABLE_DSP_EMU
815: #endif
816: }
1.1.1.2 root 817:
1.1.1.3 root 818: /**
1.1.1.4 root 819: * Read access wrapper for ioMemTabFalcon (DSP Host port)
1.1.1.6 root 820: * DSP Host interface port is accessed by the 68030 in Byte mode.
821: * A move.w value,$ffA206 results in 2 bus access for the 68030.
1.1.1.3 root 822: */
1.1.1.4 root 823: void DSP_HandleReadAccess(void)
1.1 root 824: {
1.1.1.4 root 825: Uint32 addr;
826: Uint8 value;
1.1.1.6 root 827: bool multi_access = false;
828:
1.1.1.4 root 829: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
830: {
1.1.1.3 root 831: #if ENABLE_DSP_EMU
1.1.1.5 root 832: value = dsp_core_read_host(addr-DSP_HW_OFFSET);
1.1.1.4 root 833: #else
834: /* this value prevents TOS from hanging in the DSP init code */
835: value = 0xff;
1.1 root 836: #endif
1.1.1.9 root 837: if (multi_access == true)
838: M68000_AddCycles(4);
839: multi_access = true;
1.1.1.4 root 840:
841: Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc()));
842: IoMem_WriteByte(addr, value);
843: }
1.1 root 844: }
845:
1.1.1.3 root 846: /**
1.1.1.4 root 847: * Write access wrapper for ioMemTabFalcon (DSP Host port)
1.1.1.6 root 848: * DSP Host interface port is accessed by the 68030 in Byte mode.
849: * A move.w value,$ffA206 results in 2 bus access for the 68030.
1.1.1.3 root 850: */
1.1 root 851: void DSP_HandleWriteAccess(void)
852: {
1.1.1.4 root 853: Uint32 addr;
1.1.1.6 root 854: bool multi_access = false;
855:
1.1.1.4 root 856: for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++)
1.1 root 857: {
1.1.1.4 root 858: #if ENABLE_DSP_EMU
1.1.1.9 root 859: Uint8 value = IoMem_ReadByte(addr);
860: Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc()));
1.1.1.5 root 861: dsp_core_write_host(addr-DSP_HW_OFFSET, value);
1.1.1.9 root 862: #endif
1.1.1.6 root 863: if (multi_access == true)
864: M68000_AddCycles(4);
865: multi_access = true;
1.1 root 866: }
867: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.