Annotation of hatari/src/falcon/dsp.c, revision 1.1.1.13

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.