From 8f556211d90b6e4253700a90290114786a23489c Mon Sep 17 00:00:00 2001 From: espes Date: Fri, 12 Jun 2015 23:27:23 +1000 Subject: [PATCH] more rejig --- hw/xbox/dsp/dsp.c | 248 ++++++++++++++++++++++++++---------------- hw/xbox/dsp/dsp.h | 27 +++-- hw/xbox/dsp/dsp_cpu.c | 49 ++++----- hw/xbox/dsp/dsp_cpu.h | 211 ++++++++++++++++++++++++++++++++++- hw/xbox/dsp/dsp_dma.c | 42 +++++++ hw/xbox/dsp/dsp_dma.h | 23 ++++ hw/xbox/dsp/dsp_int.h | 238 ---------------------------------------- 7 files changed, 465 insertions(+), 373 deletions(-) create mode 100644 hw/xbox/dsp/dsp_dma.c create mode 100644 hw/xbox/dsp/dsp_dma.h delete mode 100644 hw/xbox/dsp/dsp_int.h diff --git a/hw/xbox/dsp/dsp.c b/hw/xbox/dsp/dsp.c index 3030a8427f..9ef5bfa9ba 100644 --- a/hw/xbox/dsp/dsp.c +++ b/hw/xbox/dsp/dsp.c @@ -27,8 +27,10 @@ #include #include +#include + #include "dsp_cpu.h" -#include "dsp_int.h" +#include "dsp_dma.h" #include "dsp.h" @@ -36,64 +38,120 @@ #define BITMASK(x) ((1<<(x))-1) #define ARRAYSIZE(x) (int)(sizeof(x)/sizeof(x[0])) +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type *) 0)->member) *__mptr = (ptr); \ + (type *) ((char *) __mptr - offsetof(type, member));}) +#endif + + #define DPRINTF(s, ...) fprintf(stderr, s, ## __VA_ARGS__) -dsp_core_t* dsp_init(void) +struct DSPState { + dsp_core_t core; + DSPDMAState dma; + int save_cycles; +}; + +static uint32_t read_peripheral(dsp_core_t* core, uint32_t address); +static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value); + +DSPState* dsp_init(void) { DPRINTF("dsp_init\n"); - dsp_core_t* dsp = (dsp_core_t*)malloc(sizeof(dsp_core_t)); - memset(dsp, 0, sizeof(dsp_core_t)); + DSPState* dsp = (DSPState*)malloc(sizeof(DSPState)); + memset(dsp, 0, sizeof(*dsp)); - dsp56k_init_cpu(dsp); - dsp->save_cycles = 0; + dsp->core.read_peripheral = read_peripheral; + dsp->core.write_peripheral = write_peripheral; + dsp_reset(dsp); return dsp; } +void dsp_reset(DSPState* dsp) +{ + dsp56k_reset_cpu(&dsp->core); + dsp->save_cycles = 0; +} -void dsp_destroy(dsp_core_t* dsp) +void dsp_destroy(DSPState* dsp) { free(dsp); } +static uint32_t read_peripheral(dsp_core_t* core, uint32_t address) { + DSPState* dsp = container_of(core, DSPState, core); -/** - * Run DSP for certain cycles - */ -void dsp_run(dsp_core_t* dsp, int cycles) + printf("read_peripheral 0x%06x\n", address); + + switch(address) { + // case 0xFFFFC5: // interrupt + case 0xFFFFD6: + return dsp_dma_read(&dsp->dma, DMA_CONTROL); + } + + return 0xababa; +} + +static void write_peripheral(dsp_core_t* core, uint32_t address, uint32_t value) { + DSPState* dsp = container_of(core, DSPState, core); + + printf("write_peripheral [0x%06x] = 0x%06x\n", address, value); + + switch(address) { + // case 0xFFFFC5: // interrupt + case 0xFFFFD6: + return dsp_dma_write(&dsp->dma, DMA_CONTROL, value); + } +} + + +void dsp_step(DSPState* dsp) +{ + dsp56k_execute_instruction(&dsp->core); +} + +void dsp_run(DSPState* dsp, int cycles) { dsp->save_cycles += cycles; if (dsp->save_cycles <= 0) return; // if (unlikely(bDspDebugging)) { - // while (dsp->save_cycles > 0) + // while (dsp->core.save_cycles > 0) // { // dsp56k_execute_instruction(); - // dsp->save_cycles -= dsp->instr_cycle; + // dsp->core.save_cycles -= dsp->core.instr_cycle; // DebugDsp_Check(); // } // } else { - // fprintf(stderr, "--> %d\n", dsp->save_cycles); + // fprintf(stderr, "--> %d\n", dsp->core.save_cycles); while (dsp->save_cycles > 0) { - dsp56k_execute_instruction(dsp); - dsp->save_cycles -= dsp->instr_cycle; + dsp56k_execute_instruction(&dsp->core); + dsp->save_cycles -= dsp->core.instr_cycle; } } +void dsp_bootstrap(DSPState* dsp, const uint32_t* pram, size_t len) +{ + assert(sizeof(dsp->core.pram) >= len); + memcpy(dsp->core.pram, pram, len); +} + /** * Disassemble DSP code between given addresses, return next PC address */ -uint32_t dsp_disasm_address(dsp_core_t* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) +uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr) { uint32_t dsp_pc; for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { - dsp_pc += dsp56k_execute_one_disasm_instruction(dsp, out, dsp_pc); + dsp_pc += dsp56k_execute_one_disasm_instruction(&dsp->core, out, dsp_pc); } return dsp_pc; } @@ -108,7 +166,7 @@ uint32_t dsp_disasm_address(dsp_core_t* dsp, FILE *out, uint32_t lowerAdr, uint3 * Return the value at given address. For valid values AND the return * value with BITMASK(24). */ -uint32_t dsp_read_memory(dsp_core_t* dsp, uint32_t address, char space_id, const char **mem_str) +uint32_t dsp_read_memory(DSPState* dsp, uint32_t address, char space_id, const char **mem_str) { int space; @@ -133,7 +191,7 @@ uint32_t dsp_read_memory(dsp_core_t* dsp, uint32_t address, char space_id, const assert(false); } - return dsp56k_read_memory(dsp, space, address); + return dsp56k_read_memory(&dsp->core, space, address); } @@ -141,7 +199,7 @@ uint32_t dsp_read_memory(dsp_core_t* dsp, uint32_t address, char space_id, const * Output memory values between given addresses in given DSP address space. * Return next DSP address value. */ -uint32_t dsp_disasm_memory(dsp_core_t* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space) { uint32_t mem, value; const char *mem_str; @@ -157,7 +215,7 @@ uint32_t dsp_disasm_memory(dsp_core_t* dsp, uint32_t dsp_memdump_addr, uint32_t * Show information on DSP core state which isn't * shown by any of the other commands (dd, dm, dr). */ -void dsp_info(dsp_core_t* dsp) +void dsp_info(DSPState* dsp) { int i, j; const char *stackname[] = { "SSH", "SSL" }; @@ -166,21 +224,21 @@ void dsp_info(dsp_core_t* dsp) for (i = 0; i < ARRAYSIZE(stackname); i++) { fprintf(stderr, "- %s stack:", stackname[i]); - for (j = 0; j < ARRAYSIZE(dsp->stack[0]); j++) { - fprintf(stderr, " %04x", dsp->stack[i][j]); + for (j = 0; j < ARRAYSIZE(dsp->core.stack[0]); j++) { + fprintf(stderr, " %04x", dsp->core.stack[i][j]); } fputs("\n", stderr); } fprintf(stderr, "- Interrupt IPL:"); - for (i = 0; i < ARRAYSIZE(dsp->interrupt_ipl); i++) { - fprintf(stderr, " %04x", dsp->interrupt_ipl[i]); + for (i = 0; i < ARRAYSIZE(dsp->core.interrupt_ipl); i++) { + fprintf(stderr, " %04x", dsp->core.interrupt_ipl[i]); } fputs("\n", stderr); fprintf(stderr, "- Pending ints: "); - for (i = 0; i < ARRAYSIZE(dsp->interrupt_is_pending); i++) { - fprintf(stderr, " %04hx", dsp->interrupt_is_pending[i]); + for (i = 0; i < ARRAYSIZE(dsp->core.interrupt_is_pending); i++) { + fprintf(stderr, " %04hx", dsp->core.interrupt_is_pending[i]); } fputs("\n", stderr); } @@ -188,29 +246,29 @@ void dsp_info(dsp_core_t* dsp) /** * Show DSP register contents */ -void dsp_print_registers(dsp_core_t* dsp) +void dsp_print_registers(DSPState* dsp) { uint32_t i; fprintf(stderr,"A: A2: %02x A1: %06x A0: %06x\n", - dsp->registers[DSP_REG_A2], dsp->registers[DSP_REG_A1], dsp->registers[DSP_REG_A0]); + dsp->core.registers[DSP_REG_A2], dsp->core.registers[DSP_REG_A1], dsp->core.registers[DSP_REG_A0]); fprintf(stderr,"B: B2: %02x B1: %06x B0: %06x\n", - dsp->registers[DSP_REG_B2], dsp->registers[DSP_REG_B1], dsp->registers[DSP_REG_B0]); + dsp->core.registers[DSP_REG_B2], dsp->core.registers[DSP_REG_B1], dsp->core.registers[DSP_REG_B0]); - fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp->registers[DSP_REG_X1], dsp->registers[DSP_REG_X0]); - fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp->registers[DSP_REG_Y1], dsp->registers[DSP_REG_Y0]); + fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp->core.registers[DSP_REG_X1], dsp->core.registers[DSP_REG_X0]); + fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp->core.registers[DSP_REG_Y1], dsp->core.registers[DSP_REG_Y0]); for (i=0; i<8; i++) { fprintf(stderr,"R%01x: %04x N%01x: %04x M%01x: %04x\n", - i, dsp->registers[DSP_REG_R0+i], - i, dsp->registers[DSP_REG_N0+i], - i, dsp->registers[DSP_REG_M0+i]); + i, dsp->core.registers[DSP_REG_R0+i], + i, dsp->core.registers[DSP_REG_N0+i], + i, dsp->core.registers[DSP_REG_M0+i]); } - fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp->registers[DSP_REG_LA], dsp->registers[DSP_REG_LC], dsp->pc); - fprintf(stderr,"SR: %04x OMR: %02x\n", dsp->registers[DSP_REG_SR], dsp->registers[DSP_REG_OMR]); + fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp->core.registers[DSP_REG_LA], dsp->core.registers[DSP_REG_LC], dsp->core.pc); + fprintf(stderr,"SR: %04x OMR: %02x\n", dsp->core.registers[DSP_REG_SR], dsp->core.registers[DSP_REG_OMR]); fprintf(stderr,"SP: %02x SSH: %04x SSL: %04x\n", - dsp->registers[DSP_REG_SP], dsp->registers[DSP_REG_SSH], dsp->registers[DSP_REG_SSL]); + dsp->core.registers[DSP_REG_SP], dsp->core.registers[DSP_REG_SSH], dsp->core.registers[DSP_REG_SSL]); } @@ -221,7 +279,7 @@ void dsp_print_registers(dsp_core_t* dsp) * need special handling (in DSP*SetRegister()) when they are set. * Return the register width in bits or zero for an error. */ -int dsp_get_register_address(dsp_core_t* dsp, const char *regname, uint32_t **addr, uint32_t *mask) +int dsp_get_register_address(DSPState* dsp, const char *regname, uint32_t **addr, uint32_t *mask) { #define MAX_REGNAME_LEN 4 typedef struct { @@ -235,68 +293,68 @@ int dsp_get_register_address(dsp_core_t* dsp, const char *regname, uint32_t **ad const reg_addr_t registers[] = { /* 56-bit A register */ - { "A0", &dsp->registers[DSP_REG_A0], 32, BITMASK(24) }, - { "A1", &dsp->registers[DSP_REG_A1], 32, BITMASK(24) }, - { "A2", &dsp->registers[DSP_REG_A2], 32, BITMASK(8) }, + { "A0", &dsp->core.registers[DSP_REG_A0], 32, BITMASK(24) }, + { "A1", &dsp->core.registers[DSP_REG_A1], 32, BITMASK(24) }, + { "A2", &dsp->core.registers[DSP_REG_A2], 32, BITMASK(8) }, /* 56-bit B register */ - { "B0", &dsp->registers[DSP_REG_B0], 32, BITMASK(24) }, - { "B1", &dsp->registers[DSP_REG_B1], 32, BITMASK(24) }, - { "B2", &dsp->registers[DSP_REG_B2], 32, BITMASK(8) }, + { "B0", &dsp->core.registers[DSP_REG_B0], 32, BITMASK(24) }, + { "B1", &dsp->core.registers[DSP_REG_B1], 32, BITMASK(24) }, + { "B2", &dsp->core.registers[DSP_REG_B2], 32, BITMASK(8) }, /* 16-bit LA & LC registers */ - { "LA", &dsp->registers[DSP_REG_LA], 32, BITMASK(16) }, - { "LC", &dsp->registers[DSP_REG_LC], 32, BITMASK(16) }, + { "LA", &dsp->core.registers[DSP_REG_LA], 32, BITMASK(16) }, + { "LC", &dsp->core.registers[DSP_REG_LC], 32, BITMASK(16) }, /* 16-bit M registers */ - { "M0", &dsp->registers[DSP_REG_M0], 32, BITMASK(16) }, - { "M1", &dsp->registers[DSP_REG_M1], 32, BITMASK(16) }, - { "M2", &dsp->registers[DSP_REG_M2], 32, BITMASK(16) }, - { "M3", &dsp->registers[DSP_REG_M3], 32, BITMASK(16) }, - { "M4", &dsp->registers[DSP_REG_M4], 32, BITMASK(16) }, - { "M5", &dsp->registers[DSP_REG_M5], 32, BITMASK(16) }, - { "M6", &dsp->registers[DSP_REG_M6], 32, BITMASK(16) }, - { "M7", &dsp->registers[DSP_REG_M7], 32, BITMASK(16) }, + { "M0", &dsp->core.registers[DSP_REG_M0], 32, BITMASK(16) }, + { "M1", &dsp->core.registers[DSP_REG_M1], 32, BITMASK(16) }, + { "M2", &dsp->core.registers[DSP_REG_M2], 32, BITMASK(16) }, + { "M3", &dsp->core.registers[DSP_REG_M3], 32, BITMASK(16) }, + { "M4", &dsp->core.registers[DSP_REG_M4], 32, BITMASK(16) }, + { "M5", &dsp->core.registers[DSP_REG_M5], 32, BITMASK(16) }, + { "M6", &dsp->core.registers[DSP_REG_M6], 32, BITMASK(16) }, + { "M7", &dsp->core.registers[DSP_REG_M7], 32, BITMASK(16) }, /* 16-bit N registers */ - { "N0", &dsp->registers[DSP_REG_N0], 32, BITMASK(16) }, - { "N1", &dsp->registers[DSP_REG_N1], 32, BITMASK(16) }, - { "N2", &dsp->registers[DSP_REG_N2], 32, BITMASK(16) }, - { "N3", &dsp->registers[DSP_REG_N3], 32, BITMASK(16) }, - { "N4", &dsp->registers[DSP_REG_N4], 32, BITMASK(16) }, - { "N5", &dsp->registers[DSP_REG_N5], 32, BITMASK(16) }, - { "N6", &dsp->registers[DSP_REG_N6], 32, BITMASK(16) }, - { "N7", &dsp->registers[DSP_REG_N7], 32, BITMASK(16) }, + { "N0", &dsp->core.registers[DSP_REG_N0], 32, BITMASK(16) }, + { "N1", &dsp->core.registers[DSP_REG_N1], 32, BITMASK(16) }, + { "N2", &dsp->core.registers[DSP_REG_N2], 32, BITMASK(16) }, + { "N3", &dsp->core.registers[DSP_REG_N3], 32, BITMASK(16) }, + { "N4", &dsp->core.registers[DSP_REG_N4], 32, BITMASK(16) }, + { "N5", &dsp->core.registers[DSP_REG_N5], 32, BITMASK(16) }, + { "N6", &dsp->core.registers[DSP_REG_N6], 32, BITMASK(16) }, + { "N7", &dsp->core.registers[DSP_REG_N7], 32, BITMASK(16) }, - { "OMR", &dsp->registers[DSP_REG_OMR], 32, 0x5f }, + { "OMR", &dsp->core.registers[DSP_REG_OMR], 32, 0x5f }, /* 16-bit program counter */ - { "PC", (uint32_t*)(&dsp->pc), 24, BITMASK(24) }, + { "PC", (uint32_t*)(&dsp->core.pc), 24, BITMASK(24) }, /* 16-bit DSP R (address) registers */ - { "R0", &dsp->registers[DSP_REG_R0], 32, BITMASK(16) }, - { "R1", &dsp->registers[DSP_REG_R1], 32, BITMASK(16) }, - { "R2", &dsp->registers[DSP_REG_R2], 32, BITMASK(16) }, - { "R3", &dsp->registers[DSP_REG_R3], 32, BITMASK(16) }, - { "R4", &dsp->registers[DSP_REG_R4], 32, BITMASK(16) }, - { "R5", &dsp->registers[DSP_REG_R5], 32, BITMASK(16) }, - { "R6", &dsp->registers[DSP_REG_R6], 32, BITMASK(16) }, - { "R7", &dsp->registers[DSP_REG_R7], 32, BITMASK(16) }, + { "R0", &dsp->core.registers[DSP_REG_R0], 32, BITMASK(16) }, + { "R1", &dsp->core.registers[DSP_REG_R1], 32, BITMASK(16) }, + { "R2", &dsp->core.registers[DSP_REG_R2], 32, BITMASK(16) }, + { "R3", &dsp->core.registers[DSP_REG_R3], 32, BITMASK(16) }, + { "R4", &dsp->core.registers[DSP_REG_R4], 32, BITMASK(16) }, + { "R5", &dsp->core.registers[DSP_REG_R5], 32, BITMASK(16) }, + { "R6", &dsp->core.registers[DSP_REG_R6], 32, BITMASK(16) }, + { "R7", &dsp->core.registers[DSP_REG_R7], 32, BITMASK(16) }, - { "SSH", &dsp->registers[DSP_REG_SSH], 32, BITMASK(16) }, - { "SSL", &dsp->registers[DSP_REG_SSL], 32, BITMASK(16) }, - { "SP", &dsp->registers[DSP_REG_SP], 32, BITMASK(6) }, + { "SSH", &dsp->core.registers[DSP_REG_SSH], 32, BITMASK(16) }, + { "SSL", &dsp->core.registers[DSP_REG_SSL], 32, BITMASK(16) }, + { "SP", &dsp->core.registers[DSP_REG_SP], 32, BITMASK(6) }, /* 16-bit status register */ - { "SR", &dsp->registers[DSP_REG_SR], 32, 0xefff }, + { "SR", &dsp->core.registers[DSP_REG_SR], 32, 0xefff }, /* 48-bit X register */ - { "X0", &dsp->registers[DSP_REG_X0], 32, BITMASK(24) }, - { "X1", &dsp->registers[DSP_REG_X1], 32, BITMASK(24) }, + { "X0", &dsp->core.registers[DSP_REG_X0], 32, BITMASK(24) }, + { "X1", &dsp->core.registers[DSP_REG_X1], 32, BITMASK(24) }, /* 48-bit Y register */ - { "Y0", &dsp->registers[DSP_REG_Y0], 32, BITMASK(24) }, - { "Y1", &dsp->registers[DSP_REG_Y1], 32, BITMASK(24) } + { "Y0", &dsp->core.registers[DSP_REG_Y0], 32, BITMASK(24) }, + { "Y1", &dsp->core.registers[DSP_REG_Y1], 32, BITMASK(24) } }; /* left, right, middle, direction */ int l, r, m, dir = 0; @@ -342,7 +400,7 @@ int dsp_get_register_address(dsp_core_t* dsp, const char *regname, uint32_t **ad /** * Set given DSP register value, return false if unknown register given */ -bool dsp_disasm_set_register(dsp_core_t* dsp, const char *arg, uint32_t value) +bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value) { uint32_t *addr, mask, sp_value; int bits; @@ -350,31 +408,31 @@ bool dsp_disasm_set_register(dsp_core_t* dsp, const char *arg, uint32_t value) /* first check registers needing special handling... */ if (arg[0]=='S' || arg[0]=='s') { if (arg[1]=='P' || arg[1]=='p') { - dsp->registers[DSP_REG_SP] = value & BITMASK(6); + dsp->core.registers[DSP_REG_SP] = value & BITMASK(6); value &= BITMASK(4); - dsp->registers[DSP_REG_SSH] = dsp->stack[0][value]; - dsp->registers[DSP_REG_SSL] = dsp->stack[1][value]; + dsp->core.registers[DSP_REG_SSH] = dsp->core.stack[0][value]; + dsp->core.registers[DSP_REG_SSL] = dsp->core.stack[1][value]; return true; } if (arg[1]=='S' || arg[1]=='s') { - sp_value = dsp->registers[DSP_REG_SP] & BITMASK(4); + sp_value = dsp->core.registers[DSP_REG_SP] & BITMASK(4); if (arg[2]=='H' || arg[2]=='h') { if (sp_value == 0) { - dsp->registers[DSP_REG_SSH] = 0; - dsp->stack[0][sp_value] = 0; + dsp->core.registers[DSP_REG_SSH] = 0; + dsp->core.stack[0][sp_value] = 0; } else { - dsp->registers[DSP_REG_SSH] = value & BITMASK(16); - dsp->stack[0][sp_value] = value & BITMASK(16); + dsp->core.registers[DSP_REG_SSH] = value & BITMASK(16); + dsp->core.stack[0][sp_value] = value & BITMASK(16); } return true; } if (arg[2]=='L' || arg[2]=='l') { if (sp_value == 0) { - dsp->registers[DSP_REG_SSL] = 0; - dsp->stack[1][sp_value] = 0; + dsp->core.registers[DSP_REG_SSL] = 0; + dsp->core.stack[1][sp_value] = 0; } else { - dsp->registers[DSP_REG_SSL] = value & BITMASK(16); - dsp->stack[1][sp_value] = value & BITMASK(16); + dsp->core.registers[DSP_REG_SSL] = value & BITMASK(16); + dsp->core.stack[1][sp_value] = value & BITMASK(16); } return true; } diff --git a/hw/xbox/dsp/dsp.h b/hw/xbox/dsp/dsp.h index 2800a65790..f8f84799d2 100644 --- a/hw/xbox/dsp/dsp.h +++ b/hw/xbox/dsp/dsp.h @@ -29,22 +29,27 @@ #include #include -typedef struct dsp_core_s dsp_core_t; +typedef struct DSPState DSPState; /* Dsp commands */ -dsp_core_t* dsp_init(void); -void dsp_destroy(dsp_core_t* dsp); -void dsp_run(dsp_core_t* dsp, int nHostCycles); +DSPState* dsp_init(void); +void dsp_destroy(DSPState* dsp); +void dsp_reset(DSPState* dsp); + +void dsp_step(DSPState* dsp); +void dsp_run(DSPState* dsp, int cycles); + +void dsp_bootstrap(DSPState* dsp, const uint32_t* pmem, size_t len); /* Dsp Debugger commands */ -uint32_t dsp_read_memory(dsp_core_t* dsp, uint32_t addr, char space, const char **mem_str); -uint32_t dsp_disasm_memory(dsp_core_t* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); -uint32_t dsp_disasm_address(dsp_core_t* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); -void dsp_info(dsp_core_t* dsp); -void dsp_print_registers(dsp_core_t* dsp); -int dsp_get_register_address(dsp_core_t* dsp, const char *arg, uint32_t **addr, uint32_t *mask); -bool dsp_disasm_set_register(dsp_core_t* dsp, const char *arg, uint32_t value); +uint32_t dsp_read_memory(DSPState* dsp, uint32_t addr, char space, const char **mem_str); +uint32_t dsp_disasm_memory(DSPState* dsp, uint32_t dsp_memdump_addr, uint32_t dsp_memdump_upper, char space); +uint32_t dsp_disasm_address(DSPState* dsp, FILE *out, uint32_t lowerAdr, uint32_t UpperAdr); +void dsp_info(DSPState* dsp); +void dsp_print_registers(DSPState* dsp); +int dsp_get_register_address(DSPState* dsp, const char *arg, uint32_t **addr, uint32_t *mask); +bool dsp_disasm_set_register(DSPState* dsp, const char *arg, uint32_t value); #endif /* DSP_H */ diff --git a/hw/xbox/dsp/dsp_cpu.c b/hw/xbox/dsp/dsp_cpu.c index d19b009f24..9229505699 100644 --- a/hw/xbox/dsp/dsp_cpu.c +++ b/hw/xbox/dsp/dsp_cpu.c @@ -25,8 +25,6 @@ #include #include -#include "dsp.h" -#include "dsp_int.h" #include "dsp_cpu.h" #define TRACE_DSP_DISASM 1 @@ -337,31 +335,35 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "000000000000000010000110", "wait", NULL, emu_wait }, }; +static bool matches_initialised; static uint32_t nonparallel_matches[ARRAYSIZE(nonparallel_opcodes)][2]; /********************************** * Emulator kernel **********************************/ -void dsp56k_init_cpu(dsp_core_t* dsp) +void dsp56k_reset_cpu(dsp_core_t* dsp) { int i; - for (i=0; i= DSP_PERIPH_BASE) { - // assert(false); - return 0xababa; + assert(dsp->read_peripheral); + return dsp->read_peripheral(dsp, address); } assert(address < DSP_XRAM_SIZE); return dsp->xram[address]; @@ -972,14 +974,6 @@ void dsp56k_write_memory(dsp_core_t* dsp, int space, uint32_t address, uint32_t write_memory_raw(dsp, space, address, value); } -static void write_memory_peripheral(dsp_core_t* dsp, uint32_t address, uint32_t value) { - assert((value & 0xFF000000) == 0); - assert((address & 0xFF000000) == 0); - - // assert(false); -} - - static void write_memory_raw(dsp_core_t* dsp, int space, uint32_t address, uint32_t value) { assert((value & 0xFF000000) == 0); @@ -987,7 +981,8 @@ static void write_memory_raw(dsp_core_t* dsp, int space, uint32_t address, uint3 if (space == DSP_SPACE_X) { if (address >= DSP_PERIPH_BASE) { - write_memory_peripheral(dsp, address, value); + assert(dsp->write_peripheral); + dsp->write_peripheral(dsp, address, value); return; } assert(address < DSP_XRAM_SIZE); diff --git a/hw/xbox/dsp/dsp_cpu.h b/hw/xbox/dsp/dsp_cpu.h index ca4482c7b9..e9256c5e20 100644 --- a/hw/xbox/dsp/dsp_cpu.h +++ b/hw/xbox/dsp/dsp_cpu.h @@ -26,11 +26,218 @@ #include #include +#include -#include "dsp.h" +#define DSP_OMR_MA 0x00 +#define DSP_OMR_MB 0x01 +#define DSP_OMR_DE 0x02 +#define DSP_OMR_SD 0x06 +#define DSP_OMR_EA 0x07 + +#define DSP_SR_C 0x00 +#define DSP_SR_V 0x01 +#define DSP_SR_Z 0x02 +#define DSP_SR_N 0x03 +#define DSP_SR_U 0x04 +#define DSP_SR_E 0x05 +#define DSP_SR_L 0x06 + +#define DSP_SR_I0 0x08 +#define DSP_SR_I1 0x09 +#define DSP_SR_S0 0x0a +#define DSP_SR_S1 0x0b +#define DSP_SR_T 0x0d +#define DSP_SR_LF 0x0f + +#define DSP_SP_SE 0x04 +#define DSP_SP_UF 0x05 + +/* Registers numbers in dsp.registers[] */ +#define DSP_REG_X0 0x04 +#define DSP_REG_X1 0x05 +#define DSP_REG_Y0 0x06 +#define DSP_REG_Y1 0x07 +#define DSP_REG_A0 0x08 +#define DSP_REG_B0 0x09 +#define DSP_REG_A2 0x0a +#define DSP_REG_B2 0x0b +#define DSP_REG_A1 0x0c +#define DSP_REG_B1 0x0d +#define DSP_REG_A 0x0e +#define DSP_REG_B 0x0f + +#define DSP_REG_R0 0x10 +#define DSP_REG_R1 0x11 +#define DSP_REG_R2 0x12 +#define DSP_REG_R3 0x13 +#define DSP_REG_R4 0x14 +#define DSP_REG_R5 0x15 +#define DSP_REG_R6 0x16 +#define DSP_REG_R7 0x17 + +#define DSP_REG_N0 0x18 +#define DSP_REG_N1 0x19 +#define DSP_REG_N2 0x1a +#define DSP_REG_N3 0x1b +#define DSP_REG_N4 0x1c +#define DSP_REG_N5 0x1d +#define DSP_REG_N6 0x1e +#define DSP_REG_N7 0x1f + +#define DSP_REG_M0 0x20 +#define DSP_REG_M1 0x21 +#define DSP_REG_M2 0x22 +#define DSP_REG_M3 0x23 +#define DSP_REG_M4 0x24 +#define DSP_REG_M5 0x25 +#define DSP_REG_M6 0x26 +#define DSP_REG_M7 0x27 + +#define DSP_REG_SR 0x39 +#define DSP_REG_OMR 0x3a +#define DSP_REG_SP 0x3b +#define DSP_REG_SSH 0x3c +#define DSP_REG_SSL 0x3d +#define DSP_REG_LA 0x3e +#define DSP_REG_LC 0x3f + +#define DSP_REG_NULL 0x00 +#define DSP_REG_LCSAVE 0x30 + +#define DSP_REG_MAX 0x40 + +/* Memory spaces for dsp.ram[], dsp.rom[] */ +#define DSP_SPACE_X 0x00 +#define DSP_SPACE_Y 0x01 +#define DSP_SPACE_P 0x02 + +#define DSP_XRAM_SIZE 4096 +#define DSP_YRAM_SIZE 2048 +#define DSP_PRAM_SIZE 4096 + +#define DSP_PERIPH_BASE 0xFFFF80 +#define DSP_PERIPH_SIZE 128 + +#define DSP_INTERRUPT_NONE 0x0 +#define DSP_INTERRUPT_DISABLED 0x1 +#define DSP_INTERRUPT_LONG 0x2 + +#define DSP_INTER_RESET 0x0 +#define DSP_INTER_ILLEGAL 0x1 +#define DSP_INTER_STACK_ERROR 0x2 +#define DSP_INTER_TRACE 0x3 +#define DSP_INTER_SWI 0x4 +#define DSP_INTER_HOST_COMMAND 0x5 +#define DSP_INTER_HOST_RCV_DATA 0x6 +#define DSP_INTER_HOST_TRX_DATA 0x7 +#define DSP_INTER_SSI_RCV_DATA_E 0x8 +#define DSP_INTER_SSI_RCV_DATA 0x9 +#define DSP_INTER_SSI_TRX_DATA_E 0xa +#define DSP_INTER_SSI_TRX_DATA 0xb + +typedef enum { + DSP_TRACE_MODE, + DSP_DISASM_MODE +} dsp_trace_disasm_t; + +typedef struct dsp_interrupt_s { + const uint16_t inter; + const uint16_t vectorAddr; + const uint16_t periph; + const char *name; +} dsp_interrupt_t; + +typedef struct dsp_core_s dsp_core_t; + +struct dsp_core_s { + /* DSP instruction Cycle counter */ + uint16_t instr_cycle; + + /* Registers */ + uint32_t pc; + uint32_t registers[DSP_REG_MAX]; + + /* stack[0=ssh], stack[1=ssl] */ + uint32_t stack[2][16]; + + uint32_t xram[DSP_XRAM_SIZE]; + uint32_t yram[DSP_YRAM_SIZE]; + uint32_t pram[DSP_PRAM_SIZE]; + + /* peripheral space, x:0xffff80-0xffffff */ + uint32_t periph[DSP_PERIPH_SIZE]; + + /* Misc */ + uint32_t loop_rep; /* executing rep ? */ + uint32_t pc_on_rep; /* True if PC is on REP instruction */ + + /* Interruptions */ + uint16_t interrupt_state; /* NONE, FAST or LONG interrupt */ + uint16_t interrupt_instr_fetch; /* vector of the current interrupt */ + uint16_t interrupt_save_pc; /* save next pc value before interrupt */ + uint16_t interrupt_counter; /* count number of pending interrupts */ + uint16_t interrupt_ipl_to_raise; /* save the IPL level to save in the SR register */ + uint16_t interrupt_pipeline_count; /* used to prefetch correctly the 2 inter instructions */ + int16_t interrupt_ipl[12]; /* store the current IPL for each interrupt */ + uint16_t interrupt_is_pending[12]; /* store if interrupt is pending for each interrupt */ + + /* callbacks */ + uint32_t (*read_peripheral)(dsp_core_t* core, uint32_t address); + void (*write_peripheral)(dsp_core_t* core, uint32_t address, uint32_t value); + + /* runtime data */ + + /* Instructions per second */ +#ifdef DSP_COUNT_IPS + uint32_t start_time; +#endif + uint32_t num_inst; + + /* Length of current instruction */ + uint32_t cur_inst_len; /* =0:jump, >0:increment */ + /* Current instruction */ + uint32_t cur_inst; + + /* DSP is in disasm mode ? */ + /* If yes, stack overflow, underflow and illegal instructions messages are not displayed */ + bool executing_for_disasm; + + char str_disasm_memory[2][50]; /* Buffer for memory change text in disasm mode */ + uint32_t disasm_memory_ptr; /* Pointer for memory change in disasm mode */ + + bool exception_debugging; + + + /* disasm data */ + + /* Previous instruction */ + uint32_t disasm_prev_inst_pc; + bool disasm_is_looping; + + /* Used to display dc instead of unknown instruction for illegal opcodes */ + dsp_trace_disasm_t disasm_mode; + + uint32_t disasm_cur_inst; + uint16_t disasm_cur_inst_len; + + /* Current instruction */ + char disasm_str_instr[50]; + char disasm_str_instr2[120]; + char disasm_parallelmove_name[64]; + + /********************************** + * Register change + **********************************/ + + uint32_t disasm_registers_save[64]; +#if DSP_DISASM_REG_PC + uint32_t pc_save; +#endif + +}; /* Functions */ -void dsp56k_init_cpu(dsp_core_t* dsp); /* Set dsp_core to use */ +void dsp56k_reset_cpu(dsp_core_t* dsp); /* Set dsp_core to use */ void dsp56k_execute_instruction(dsp_core_t* dsp); /* Execute 1 instruction */ uint16_t dsp56k_execute_one_disasm_instruction(dsp_core_t* dsp, FILE *out, uint32_t pc); /* Execute 1 instruction in disasm mode */ diff --git a/hw/xbox/dsp/dsp_dma.c b/hw/xbox/dsp/dsp_dma.c new file mode 100644 index 0000000000..1c9db71e02 --- /dev/null +++ b/hw/xbox/dsp/dsp_dma.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "dsp_dma.h" + +uint32_t dsp_dma_read(DSPDMAState *s, DSPDMARegister reg) +{ + switch (reg) { + case DMA_CONFIGURATION: + return s->configuration; + case DMA_CONTROL: + return s->control; + case DMA_START_BLOCK: + return s->start_block; + case DMA_NEXT_BLOCK: + return s->next_block; + default: + assert(false); + } + return 0; +} +void dsp_dma_write(DSPDMAState *s, DSPDMARegister reg, uint32_t v) +{ + switch (reg) { + case DMA_CONFIGURATION: + s->configuration = v; + break; + case DMA_CONTROL: + s->control = v; + break; + case DMA_START_BLOCK: + s->start_block = v; + break; + case DMA_NEXT_BLOCK: + s->next_block = v; + break; + default: + assert(false); + } +} + diff --git a/hw/xbox/dsp/dsp_dma.h b/hw/xbox/dsp/dsp_dma.h new file mode 100644 index 0000000000..3cfccc54be --- /dev/null +++ b/hw/xbox/dsp/dsp_dma.h @@ -0,0 +1,23 @@ +#ifndef DSP_DMA_H +#define DSP_DMA_H + +#include + +typedef enum DSPDMARegister { + DMA_CONFIGURATION, + DMA_CONTROL, + DMA_START_BLOCK, + DMA_NEXT_BLOCK, +} DSPDMARegister; + +typedef struct DSPDMAState { + uint32_t configuration; + uint32_t control; + uint32_t start_block; + uint32_t next_block; +} DSPDMAState; + +uint32_t dsp_dma_read(DSPDMAState *s, DSPDMARegister reg); +void dsp_dma_write(DSPDMAState *s, DSPDMARegister reg, uint32_t v); + +#endif \ No newline at end of file diff --git a/hw/xbox/dsp/dsp_int.h b/hw/xbox/dsp/dsp_int.h deleted file mode 100644 index 9e4a337d79..0000000000 --- a/hw/xbox/dsp/dsp_int.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - DSP56300 emulation - - Copyright (c) 2015 espes - - Adapted from Hatari DSP M56001 emulation - (C) 2001-2008 ARAnyM developer team - Adaption to Hatari (C) 2008 by Thomas Huth - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DSP_INT_H -#define DSP_INT_H - -#include - -#define DSP_OMR_MA 0x00 -#define DSP_OMR_MB 0x01 -#define DSP_OMR_DE 0x02 -#define DSP_OMR_SD 0x06 -#define DSP_OMR_EA 0x07 - -#define DSP_SR_C 0x00 -#define DSP_SR_V 0x01 -#define DSP_SR_Z 0x02 -#define DSP_SR_N 0x03 -#define DSP_SR_U 0x04 -#define DSP_SR_E 0x05 -#define DSP_SR_L 0x06 - -#define DSP_SR_I0 0x08 -#define DSP_SR_I1 0x09 -#define DSP_SR_S0 0x0a -#define DSP_SR_S1 0x0b -#define DSP_SR_T 0x0d -#define DSP_SR_LF 0x0f - -#define DSP_SP_SE 0x04 -#define DSP_SP_UF 0x05 - -/* Registers numbers in dsp.registers[] */ -#define DSP_REG_X0 0x04 -#define DSP_REG_X1 0x05 -#define DSP_REG_Y0 0x06 -#define DSP_REG_Y1 0x07 -#define DSP_REG_A0 0x08 -#define DSP_REG_B0 0x09 -#define DSP_REG_A2 0x0a -#define DSP_REG_B2 0x0b -#define DSP_REG_A1 0x0c -#define DSP_REG_B1 0x0d -#define DSP_REG_A 0x0e -#define DSP_REG_B 0x0f - -#define DSP_REG_R0 0x10 -#define DSP_REG_R1 0x11 -#define DSP_REG_R2 0x12 -#define DSP_REG_R3 0x13 -#define DSP_REG_R4 0x14 -#define DSP_REG_R5 0x15 -#define DSP_REG_R6 0x16 -#define DSP_REG_R7 0x17 - -#define DSP_REG_N0 0x18 -#define DSP_REG_N1 0x19 -#define DSP_REG_N2 0x1a -#define DSP_REG_N3 0x1b -#define DSP_REG_N4 0x1c -#define DSP_REG_N5 0x1d -#define DSP_REG_N6 0x1e -#define DSP_REG_N7 0x1f - -#define DSP_REG_M0 0x20 -#define DSP_REG_M1 0x21 -#define DSP_REG_M2 0x22 -#define DSP_REG_M3 0x23 -#define DSP_REG_M4 0x24 -#define DSP_REG_M5 0x25 -#define DSP_REG_M6 0x26 -#define DSP_REG_M7 0x27 - -#define DSP_REG_SR 0x39 -#define DSP_REG_OMR 0x3a -#define DSP_REG_SP 0x3b -#define DSP_REG_SSH 0x3c -#define DSP_REG_SSL 0x3d -#define DSP_REG_LA 0x3e -#define DSP_REG_LC 0x3f - -#define DSP_REG_NULL 0x00 -#define DSP_REG_LCSAVE 0x30 - -#define DSP_REG_MAX 0x40 - -/* Memory spaces for dsp.ram[], dsp.rom[] */ -#define DSP_SPACE_X 0x00 -#define DSP_SPACE_Y 0x01 -#define DSP_SPACE_P 0x02 - -#define DSP_XRAM_SIZE 4096 -#define DSP_YRAM_SIZE 2048 -#define DSP_PRAM_SIZE 4096 - -#define DSP_PERIPH_BASE 0xFFFF80 -#define DSP_PERIPH_SIZE 128 - -#define DSP_INTERRUPT_NONE 0x0 -#define DSP_INTERRUPT_DISABLED 0x1 -#define DSP_INTERRUPT_LONG 0x2 - -#define DSP_INTER_RESET 0x0 -#define DSP_INTER_ILLEGAL 0x1 -#define DSP_INTER_STACK_ERROR 0x2 -#define DSP_INTER_TRACE 0x3 -#define DSP_INTER_SWI 0x4 -#define DSP_INTER_HOST_COMMAND 0x5 -#define DSP_INTER_HOST_RCV_DATA 0x6 -#define DSP_INTER_HOST_TRX_DATA 0x7 -#define DSP_INTER_SSI_RCV_DATA_E 0x8 -#define DSP_INTER_SSI_RCV_DATA 0x9 -#define DSP_INTER_SSI_TRX_DATA_E 0xa -#define DSP_INTER_SSI_TRX_DATA 0xb - -typedef enum { - DSP_TRACE_MODE, - DSP_DISASM_MODE -} dsp_trace_disasm_t; - -typedef struct dsp_interrupt_s { - const uint16_t inter; - const uint16_t vectorAddr; - const uint16_t periph; - const char *name; -} dsp_interrupt_t; - -struct dsp_core_s { - /* DSP instruction Cycle counter */ - uint16_t instr_cycle; - - /* Registers */ - uint32_t pc; - uint32_t registers[DSP_REG_MAX]; - - /* stack[0=ssh], stack[1=ssl] */ - uint32_t stack[2][16]; - - uint32_t xram[DSP_XRAM_SIZE]; - uint32_t yram[DSP_YRAM_SIZE]; - uint32_t pram[DSP_PRAM_SIZE]; - - /* peripheral space, x:0xffff80-0xffffff */ - uint32_t periph[DSP_PERIPH_SIZE]; - - /* Misc */ - uint32_t loop_rep; /* executing rep ? */ - uint32_t pc_on_rep; /* True if PC is on REP instruction */ - - /* Interruptions */ - uint16_t interrupt_state; /* NONE, FAST or LONG interrupt */ - uint16_t interrupt_instr_fetch; /* vector of the current interrupt */ - uint16_t interrupt_save_pc; /* save next pc value before interrupt */ - uint16_t interrupt_counter; /* count number of pending interrupts */ - uint16_t interrupt_ipl_to_raise; /* save the IPL level to save in the SR register */ - uint16_t interrupt_pipeline_count; /* used to prefetch correctly the 2 inter instructions */ - int16_t interrupt_ipl[12]; /* store the current IPL for each interrupt */ - uint16_t interrupt_is_pending[12]; /* store if interrupt is pending for each interrupt */ - - - /* runtime data */ - - int save_cycles; - - /* Instructions per second */ -#ifdef DSP_COUNT_IPS - uint32_t start_time; -#endif - uint32_t num_inst; - -/* Length of current instruction */ - uint32_t cur_inst_len; /* =0:jump, >0:increment */ -/* Current instruction */ - uint32_t cur_inst; - - /* DSP is in disasm mode ? */ - /* If yes, stack overflow, underflow and illegal instructions messages are not displayed */ - bool executing_for_disasm; - - char str_disasm_memory[2][50]; /* Buffer for memory change text in disasm mode */ - uint32_t disasm_memory_ptr; /* Pointer for memory change in disasm mode */ - - bool exception_debugging; - - - /* disasm data */ - - /* Previous instruction */ - uint32_t disasm_prev_inst_pc; - bool disasm_is_looping; - - /* Used to display dc instead of unknown instruction for illegal opcodes */ - dsp_trace_disasm_t disasm_mode; - - uint32_t disasm_cur_inst; - uint16_t disasm_cur_inst_len; - - /* Current instruction */ - char disasm_str_instr[50]; - char disasm_str_instr2[120]; - char disasm_parallelmove_name[64]; - - /********************************** - * Register change - **********************************/ - - uint32_t disasm_registers_save[64]; -#if DSP_DISASM_REG_PC - uint32_t pc_save; -#endif - -}; - -/* DSP */ -extern dsp_core_t dsp_core; - -#endif \ No newline at end of file