diff --git a/hw/xbox/dsp/dsp.c b/hw/xbox/dsp/dsp.c index 64f5c8e9dd..8fbb3f95b0 100644 --- a/hw/xbox/dsp/dsp.c +++ b/hw/xbox/dsp/dsp.c @@ -40,7 +40,7 @@ dsp_core_t* dsp_init(void) { - DPRINTF("dsp_init %d\n", sizeof(dsp_core_t)); + DPRINTF("dsp_init\n"); dsp_core_t* dsp = (dsp_core_t*)malloc(sizeof(dsp_core_t)); memset(dsp, 0, sizeof(dsp_core_t)); diff --git a/hw/xbox/dsp/dsp_cpu.c b/hw/xbox/dsp/dsp_cpu.c index bc8752a13f..1ff4024f93 100644 --- a/hw/xbox/dsp/dsp_cpu.c +++ b/hw/xbox/dsp/dsp_cpu.c @@ -75,6 +75,7 @@ static uint16_t dsp_add56(dsp_core_t* dsp, uint32_t *source, uint32_t *dest); static uint16_t dsp_sub56(dsp_core_t* dsp, uint32_t *source, uint32_t *dest); static void dsp_mul56(dsp_core_t* dsp, uint32_t source1, uint32_t source2, uint32_t *dest, uint8_t signe); static void dsp_rnd56(dsp_core_t* dsp, uint32_t *dest); +static uint32_t dsp_signextend(int bits, uint32_t v); static const dsp_interrupt_t dsp_interrupt[12] = { {DSP_INTER_RESET , 0x00, 0, "Reset"}, @@ -292,7 +293,7 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00000111W1MMMRRR10dddddd", "movem P:ea <-> R", dis_movem_ea, emu_movem_ea }, { "00000111W0aaaaaa00dddddd", "movem P:ea <-> R", dis_movem_aa, emu_movem_aa }, { "0000100sW1MMMRRR1Spppppp", "movep [X or Y]:ea <-> [X or Y]:pp", dis_movep_23, emu_movep_23 }, - { "00000111W1MMMRRR0Sqqqqqq", "movep [X or Y]:ea <-> X:qq", dis_movep_x_low, emu_movep_x_low }, + { "00000111W1MMMRRR0Sqqqqqq", "movep [X or Y]:ea <-> X:qq", dis_movep_x_qq, emu_movep_x_qq }, { "00000111W0MMMRRR1Sqqqqqq", "movep [X or Y]:ea <-> Y:qq", NULL, NULL }, { "0000100sW1MMMRRR01pppppp", "movep [X or Y]:pp <-> P:ea", dis_movep_1, emu_movep_1 }, { "000000001WMMMRRR0sqqqqqq", "movep [X or Y]:qq <-> P:ea", NULL, NULL }, @@ -898,7 +899,9 @@ static uint32_t read_memory_p(dsp_core_t* dsp, uint32_t address) { assert((address & 0xFF000000) == 0); assert(address < DSP_PRAM_SIZE); - return dsp->pram[address]; + uint32_t r = dsp->pram[address]; + assert((r & 0xFF000000) == 0); + return r; } uint32_t dsp56k_read_memory(dsp_core_t* dsp, int space, uint32_t address) @@ -1365,3 +1368,10 @@ static void dsp_rnd56(dsp_core_t* dsp, uint32_t *dest) } } +static uint32_t dsp_signextend(int bits, uint32_t v) { + const int shift = sizeof(int)*8 - bits; + assert(shift > 0); + return (uint32_t)(((int32_t)v << shift) >> shift); +} + + diff --git a/hw/xbox/dsp/dsp_dis.inl b/hw/xbox/dsp/dsp_dis.inl index 350c4a7bcd..280ec56a44 100644 --- a/hw/xbox/dsp/dsp_dis.inl +++ b/hw/xbox/dsp/dsp_dis.inl @@ -422,7 +422,6 @@ static void dis_bclr_reg(dsp_core_t* dsp) static void dis_bra_imm(dsp_core_t* dsp) { - // QQQ - sign-extend uint32_t xxx = (dsp->disasm_cur_inst & BITMASK(5)) + ((dsp->disasm_cur_inst & (BITMASK(4) << 6)) >> 1); sprintf(dsp->disasm_str_instr, "bra p:$%04x", xxx); @@ -628,8 +627,8 @@ static void dis_cmpu(dsp_core_t* dsp) { uint32_t ggg = (dsp->disasm_cur_inst >> 1) & BITMASK(3); uint32_t d = dsp->disasm_cur_inst & 1; - uint32_t srcreg = DSP_REG_NULL; uint32_t srcacc = d ? DSP_REG_B : DSP_REG_A; + uint32_t srcreg = DSP_REG_NULL; switch (ggg) { case 0: srcreg = d ? DSP_REG_A : DSP_REG_B; break; case 4: srcreg = DSP_REG_X0; break; @@ -1496,18 +1495,18 @@ static void dis_movep_23(dsp_core_t* dsp) sprintf(dsp->disasm_str_instr,"movep %s,%s", srcname, dstname); } -static void dis_movep_x_low(dsp_core_t* dsp) { +static void dis_movep_x_qq(dsp_core_t* dsp) { // 00000111W1MMMRRR0Sqqqqqq char srcname[16]="",dstname[16]="",name[16]=""; - uint32_t addr, easpace, retour; - addr = 0xffff80 + (dsp->disasm_cur_inst & BITMASK(6)); - retour = dis_calc_ea(dsp, (dsp->disasm_cur_inst>>8) & BITMASK(6), name); - easpace = (dsp->disasm_cur_inst>>6) & 1; + uint32_t addr = 0xffff80 + (dsp->disasm_cur_inst & BITMASK(6)); + uint32_t ea_mode = (dsp->cur_inst>>8) & BITMASK(6); + uint32_t easpace = (dsp->disasm_cur_inst>>6) & 1; + int retour = dis_calc_ea(dsp, ea_mode, name); if (dsp->disasm_cur_inst & (1<<15)) { - /* Write pp */ + /* Write qq */ if (retour) { sprintf(srcname, "#%s", name); @@ -1521,7 +1520,7 @@ static void dis_movep_x_low(dsp_core_t* dsp) { sprintf(dstname, "x:$%04x", addr); } else { - /* Read pp */ + /* Read qq */ sprintf(srcname, "x:$%04x", addr); @@ -1555,7 +1554,7 @@ static void dis_move_x_long(dsp_core_t* dsp) { static void dis_move_x_imm(dsp_core_t* dsp) { // 0000001aaaaaaRRR1a0WDDDD int W = (dsp->disasm_cur_inst >> 4) & 1; - int xxx = (((dsp->disasm_cur_inst >> 11) & BITMASK(6)) << 1) + uint32_t xxx = (((dsp->disasm_cur_inst >> 11) & BITMASK(6)) << 1) + ((dsp->disasm_cur_inst >> 6) & 1); uint32_t offreg = DSP_REG_R0 + ((dsp->disasm_cur_inst >> 8) & BITMASK(3)); uint32_t numreg = dsp->disasm_cur_inst & BITMASK(4); diff --git a/hw/xbox/dsp/dsp_emu.inl b/hw/xbox/dsp/dsp_emu.inl index 11e1a9b6dc..44d9e0047a 100644 --- a/hw/xbox/dsp/dsp_emu.inl +++ b/hw/xbox/dsp/dsp_emu.inl @@ -5745,15 +5745,60 @@ static const emu_func_t opcodes_parmove[16] = { static void emu_add_long(dsp_core_t* dsp) { uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); - // QQQ dsp->cur_inst_len++; + + uint32_t source[3], dest[3]; + uint16_t newsr; + + if ((dsp->cur_inst >> 3) & 1) { + dest[0] = dsp->registers[DSP_REG_B2]; + dest[1] = dsp->registers[DSP_REG_B1]; + dest[2] = dsp->registers[DSP_REG_B0]; + } else { + dest[0] = dsp->registers[DSP_REG_A2]; + dest[1] = dsp->registers[DSP_REG_A1]; + dest[2] = dsp->registers[DSP_REG_A0]; + } + + source[2] = 0; + source[1] = xxxx; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_add56(dsp, source, dest); + + if ((dsp->cur_inst >> 3) & 1) { + dsp->registers[DSP_REG_B2] = dest[0]; + dsp->registers[DSP_REG_B1] = dest[1]; + dsp->registers[DSP_REG_B0] = dest[2]; + } else { + dsp->registers[DSP_REG_A2] = dest[0]; + dsp->registers[DSP_REG_A1] = dest[1]; + dsp->registers[DSP_REG_A0] = dest[2]; + } + + emu_ccr_update_e_u_n_z(dsp, dest[0], dest[1], dest[2]); + + dsp->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= newsr; } static void emu_and_long(dsp_core_t* dsp) { uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); - // QQQ dsp->cur_inst_len++; + + int dstreg; + if ((dsp->cur_inst >> 3) & 1) { + dstreg = DSP_REG_B1; + } else { + dstreg = DSP_REG_A1; + } + + dsp->registers[dstreg] &= xxxx; + + dsp->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= ((dsp->registers[dstreg]>>23) & 1)<registers[DSP_REG_SR] |= (dsp->registers[dstreg]==0)<pc+1); dsp->cur_inst_len++; - //QQQ - dsp->instr_cycle += 2; //?? + + uint32_t cc_code = dsp->cur_inst & BITMASK(4); + if (emu_calc_cc(dsp, cc_code)) { + dsp->pc += xxxx; + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + } + + //TODO: cycles? } static void emu_bcc_imm(dsp_core_t* dsp) { - //QQQ - dsp->instr_cycle += 2; //?? + uint32_t xxx = (dsp->cur_inst & BITMASK(5)) + + ((dsp->cur_inst & (BITMASK(4) << 6)) >> 1); + + uint32_t cc_code = (dsp->cur_inst >> 12) & BITMASK(4); + + if (emu_calc_cc(dsp, cc_code)) { + dsp->pc += dsp_signextend(9, xxx); + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + } + + //TODO: cycles } static void emu_bchg_aa(dsp_core_t* dsp) @@ -5982,8 +6044,12 @@ static void emu_bclr_reg(dsp_core_t* dsp) } static void emu_bra_imm(dsp_core_t* dsp) { - // QQQ - dsp->instr_cycle += 2; + uint32_t xxx = (dsp->cur_inst & BITMASK(5)) + + ((dsp->cur_inst & (BITMASK(4) << 6)) >> 1); + + dsp->pc += dsp_signextend(9, xxx); + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; } static void emu_brclr_pp(dsp_core_t* dsp) { @@ -5995,8 +6061,14 @@ static void emu_brclr_pp(dsp_core_t* dsp) { uint32_t numbit = dsp->cur_inst & BITMASK(5); uint32_t addr = 0xffffc0 + value; value = dsp56k_read_memory(dsp, memspace, addr); - //QQQ + dsp->instr_cycle += 4; + + if ((value & (1<pc += xxxx; + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + } } static void emu_brset_pp(dsp_core_t* dsp) { @@ -6008,8 +6080,14 @@ static void emu_brset_pp(dsp_core_t* dsp) { uint32_t numbit = dsp->cur_inst & BITMASK(5); uint32_t addr = 0xffffc0 + value; value = dsp56k_read_memory(dsp, memspace, addr); - //QQQ + dsp->instr_cycle += 4; + + if (value & (1<pc += xxxx; + dsp->pc &= BITMASK(24); + dsp->cur_inst_len=0; + } } static void emu_bset_aa(dsp_core_t* dsp) @@ -6038,14 +6116,35 @@ static void emu_bsr_long(dsp_core_t* dsp) uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); dsp->cur_inst_len++; - // QQQ + if (dsp->interrupt_state != DSP_INTERRUPT_LONG){ + dsp_stack_push(dsp, dsp->pc+dsp->cur_inst_len, dsp->registers[DSP_REG_SR], 0); + } else { + dsp->interrupt_state = DSP_INTERRUPT_DISABLED; + } + + dsp->pc += xxxx; + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + + dsp->instr_cycle += 4; } static void emu_bsr_imm(dsp_core_t* dsp) { - uint32_t xxx = (dsp->disasm_cur_inst & BITMASK(5)) - + ((dsp->disasm_cur_inst & (BITMASK(4) << 6)) >> 1); - // QQQ + uint32_t xxx = (dsp->cur_inst & BITMASK(5)) + + ((dsp->cur_inst & (BITMASK(4) << 6)) >> 1); + + if (dsp->interrupt_state != DSP_INTERRUPT_LONG){ + dsp_stack_push(dsp, dsp->pc+dsp->cur_inst_len, dsp->registers[DSP_REG_SR], 0); + } else { + dsp->interrupt_state = DSP_INTERRUPT_DISABLED; + } + + dsp->pc += dsp_signextend(9, xxx); + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + + dsp->instr_cycle += 2; } static void emu_bset_ea(dsp_core_t* dsp) @@ -6194,7 +6293,52 @@ static void emu_btst_reg(dsp_core_t* dsp) } static void emu_cmpu(dsp_core_t* dsp) { - // QQQ + uint32_t ggg = (dsp->disasm_cur_inst >> 1) & BITMASK(3); + uint32_t d = dsp->disasm_cur_inst & 1; + + uint32_t srcreg = DSP_REG_NULL; + switch (ggg) { + case 0: srcreg = d ? DSP_REG_A : DSP_REG_B; break; + case 4: srcreg = DSP_REG_X0; break; + case 5: srcreg = DSP_REG_Y0; break; + case 6: srcreg = DSP_REG_X1; break; + case 7: srcreg = DSP_REG_Y1; break; + } + + uint32_t source[3], dest[3]; + if (d) { + dest[2] = dsp->registers[DSP_REG_B0]; + dest[1] = dsp->registers[DSP_REG_B1]; + dest[0] = dsp->registers[DSP_REG_B2]; + } else { + dest[2] = dsp->registers[DSP_REG_A0]; + dest[1] = dsp->registers[DSP_REG_A1]; + dest[0] = dsp->registers[DSP_REG_A2]; + } + + uint32_t value; + if (srcreg == DSP_REG_A || srcreg == DSP_REG_B) { + emu_pm_read_accu24(dsp, srcreg, &value); + } else { + value = dsp->registers[srcreg]; + } + + source[2] = 0; + source[1] = value; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + uint16_t newsr = dsp_sub56(dsp, source, dest); + + dsp->registers[DSP_REG_SR] &= BITMASK(16)-( + (1<registers[DSP_REG_SR] |= newsr & (1<registers[DSP_REG_SR] |= 1 << DSP_SR_Z; + + /* Negative Flag (N) */ + dsp->registers[DSP_REG_SR] |= (dest[0]>>4) & 0x8; } static void emu_div(dsp_core_t* dsp) @@ -6218,8 +6362,7 @@ static void emu_div(dsp_core_t* dsp) dest[0] = dsp->registers[DSP_REG_A2]; dest[1] = dsp->registers[DSP_REG_A1]; dest[2] = dsp->registers[DSP_REG_A0]; - } - else { + } else { dest[0] = dsp->registers[DSP_REG_B2]; dest[1] = dsp->registers[DSP_REG_B1]; dest[2] = dsp->registers[DSP_REG_B0]; @@ -6241,8 +6384,7 @@ static void emu_div(dsp_core_t* dsp) dsp->registers[DSP_REG_A2] = dest[0]; dsp->registers[DSP_REG_A1] = dest[1]; dsp->registers[DSP_REG_A0] = dest[2]; - } - else { + } else { dsp->registers[DSP_REG_B2] = dest[0]; dsp->registers[DSP_REG_B1] = dest[1]; dsp->registers[DSP_REG_B0] = dest[2]; @@ -6346,7 +6488,17 @@ static void emu_do_reg(dsp_core_t* dsp) static void emu_dor_imm(dsp_core_t* dsp) { - //QQQ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + dsp_stack_push(dsp, dsp->registers[DSP_REG_LA], dsp->registers[DSP_REG_LC], 0); + dsp->registers[DSP_REG_LA] = (dsp->pc + xxxx) & BITMASK(16); + + dsp_stack_push(dsp, dsp->pc+dsp->cur_inst_len, dsp->registers[DSP_REG_SR], 0); + dsp->registers[DSP_REG_SR] |= (1<registers[DSP_REG_LC] = ((dsp->cur_inst>>8) & BITMASK(8)) + + ((dsp->cur_inst & BITMASK(4))<<8); dsp->instr_cycle += 4; } @@ -7161,38 +7313,67 @@ static void emu_movep_23(dsp_core_t* dsp) dsp->instr_cycle += 2; } -static void emu_movep_x_low(dsp_core_t* dsp) { +static void emu_movep_x_qq(dsp_core_t* dsp) { // 00000111W1MMMRRR0sqqqqqq - uint32_t addr, peraddr, easpace, ea_mode; - int retour; + uint32_t x_addr = 0xffff80 + (dsp->cur_inst & BITMASK(6)); + uint32_t ea_mode = (dsp->cur_inst>>8) & BITMASK(6); + uint32_t ea_space = (dsp->cur_inst>>6) & 1; + uint32_t ea_addr; + int retour = emu_calc_ea(dsp, ea_mode, &ea_addr); - peraddr = 0xffff80 + (dsp->cur_inst & BITMASK(6)); - - ea_mode = (dsp->cur_inst>>8) & BITMASK(6); - easpace = (dsp->cur_inst>>6) & 1; - retour = emu_calc_ea(dsp, ea_mode, &addr); + if (dsp->cur_inst & (1<<15)) { + /* Write qq */ + + if (retour) { + dsp56k_write_memory(dsp, DSP_SPACE_X, x_addr, ea_addr); + } else { + dsp56k_write_memory(dsp, DSP_SPACE_X, x_addr, + dsp56k_read_memory(dsp, ea_space, ea_addr)); + } + } else { + /* Read qq */ + dsp56k_write_memory(dsp, ea_space, ea_addr, + dsp56k_read_memory(dsp, DSP_SPACE_X, x_addr)); + } - // QQQ - - dsp->instr_cycle += 2; // ??? + dsp->instr_cycle += 2; } static void emu_move_x_long(dsp_core_t* dsp) { - int W = (dsp->cur_inst >> 6) & 1; uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); dsp->cur_inst_len++; - //QQQ - dsp->instr_cycle += 2; //??? + + int W = (dsp->cur_inst >> 6) & 1; + uint32_t offreg = DSP_REG_R0 + ((dsp->cur_inst >> 8) & BITMASK(3)); + uint32_t numreg = dsp->cur_inst & BITMASK(6); + uint32_t x_addr = (dsp->registers[offreg] + xxxx) & BITMASK(24); + + if (W) { + dsp56k_write_memory(dsp, DSP_SPACE_X, x_addr, dsp->registers[numreg]); + } else { + dsp->registers[numreg] = dsp56k_read_memory(dsp, DSP_SPACE_X, x_addr); + } + + // TODO: cycles } static void emu_move_x_imm(dsp_core_t* dsp) { // 0000001aaaaaaRRR1a0WDDDD - int W = (dsp->cur_inst >> 4) & 1; - int a = (((dsp->cur_inst >> 11) & BITMASK(6)) << 1) - + ((dsp->cur_inst >> 6) & 1); - //QQQ - dsp->instr_cycle += 2; //??? + uint32_t xxx = (((dsp->disasm_cur_inst >> 11) & BITMASK(6)) << 1) + + ((dsp->disasm_cur_inst >> 6) & 1); + int W = (dsp->disasm_cur_inst >> 4) & 1; + uint32_t offreg = DSP_REG_R0 + ((dsp->disasm_cur_inst >> 8) & BITMASK(3)); + uint32_t numreg = dsp->disasm_cur_inst & BITMASK(4); + uint32_t x_addr = (dsp->registers[offreg] + dsp_signextend(7, xxx)) & BITMASK(24); + + if (W) { + dsp56k_write_memory(dsp, DSP_SPACE_X, x_addr, dsp->registers[numreg]); + } else { + dsp->registers[numreg] = dsp56k_read_memory(dsp, DSP_SPACE_X, x_addr); + } + + // TODO: cycles } static void emu_norm(dsp_core_t* dsp) @@ -7238,8 +7419,22 @@ static void emu_norm(dsp_core_t* dsp) static void emu_or_long(dsp_core_t* dsp) { uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); - // QQQ dsp->cur_inst_len++; + + int dstreg; + if ((dsp->cur_inst >> 3) & 1) { + dstreg = DSP_REG_B1; + } else { + dstreg = DSP_REG_A1; + } + + dsp->registers[dstreg] |= xxxx; + + dsp->registers[DSP_REG_SR] &= BITMASK(16)-((1<registers[DSP_REG_SR] |= ((dsp->registers[dstreg]>>23) & 1)<registers[DSP_REG_SR] |= (dsp->registers[dstreg]==0)<