From 79e8643d16c54c5c1fc8908206be58edd6dbfc54 Mon Sep 17 00:00:00 2001 From: espes Date: Sat, 4 Jul 2015 21:32:02 +1000 Subject: [PATCH] a couple more dsp instructions --- hw/xbox/dsp/dsp_cpu.c | 6 +- hw/xbox/dsp/dsp_dis.inl | 58 ++++++++++++---- hw/xbox/dsp/dsp_emu.inl | 150 ++++++++++++++++++++++++++-------------- 3 files changed, 149 insertions(+), 65 deletions(-) diff --git a/hw/xbox/dsp/dsp_cpu.c b/hw/xbox/dsp/dsp_cpu.c index 64465370cf..73663a60b0 100644 --- a/hw/xbox/dsp/dsp_cpu.c +++ b/hw/xbox/dsp/dsp_cpu.c @@ -224,7 +224,7 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "0000101111DDDDDD0110bbbb", "btst #n, D", dis_btst_reg, emu_btst_reg }, { "0000110000011110000000SD", "clb S, D", NULL, NULL }, { "0000000101iiiiii1000d101", "cmp #xx, S2", dis_cmp_imm, emu_cmp_imm }, - { "00000001010000001100d101", "cmp #xxxx, S2", NULL, NULL }, + { "00000001010000001100d101", "cmp #xxxx, S2", dis_cmp_long, emu_cmp_long }, { "00001100000111111111gggd", "cmpu S1, S2", dis_cmpu, emu_cmpu }, { "000000000000001000000000", "debug", NULL, NULL }, { "00000000000000110000CCCC", "debugcc", NULL, NULL }, @@ -314,7 +314,7 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00000100W1dddddd0q1qqqqq", "movep Y:qq <-> R", NULL, NULL }, { "00000001000sssss11QQdk00", "mpy S, #n, D", NULL, NULL }, { "00000001001001111sdkQQQQ", "mpy_s_u S1, S2, D", NULL, NULL }, - { "000000010100000111qqdk00", "mpyi #xxxx, S, D", NULL, NULL }, + { "000000010100000111qqdk00", "mpyi #xxxx, S, D", dis_mpyi, emu_mpyi }, { "00000001000sssss11QQdk01", "mpyr S, #n, D", NULL, NULL }, { "000000010100000111qqdk01", "mpyri #xxxx, S, D", NULL, NULL }, { "000000000000000000000000", "nop", NULL, emu_nop}, @@ -339,7 +339,7 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "000000000000000000001100", "rts", NULL, emu_rts }, { "000000000000000010000111", "stop", NULL, emu_stop }, { "0000000101iiiiii1000d100", "sub #xx, D", dis_sub_imm, emu_sub_imm }, - { "00000001010000001100d100", "sub #xxxx, D", NULL, NULL }, + { "00000001010000001100d100", "sub #xxxx, D", dis_sub_long, emu_sub_long }, { "00000010CCCC00000JJJd000", "tcc S1, D1", dis_tcc, emu_tcc }, { "00000011CCCC0ttt0JJJdTTT", "tcc S1,D2 S2,D2", dis_tcc, emu_tcc }, { "00000010CCCC1ttt00000TTT", "tcc S2, D2", dis_tcc, emu_tcc }, diff --git a/hw/xbox/dsp/dsp_dis.inl b/hw/xbox/dsp/dsp_dis.inl index 666ce3c08f..908e3b6238 100644 --- a/hw/xbox/dsp/dsp_dis.inl +++ b/hw/xbox/dsp/dsp_dis.inl @@ -723,6 +723,15 @@ static void dis_cmp_imm(dsp_core_t* dsp) { xx, registers_name[d ? DSP_REG_B : DSP_REG_A]); } +static void dis_cmp_long(dsp_core_t* dsp) { + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + + uint32_t d = (dsp->disasm_cur_inst >> 3) & 1; + sprintf(dsp->disasm_str_instr, "cmp #$%06x,%s", + xxxx, registers_name[d ? DSP_REG_B : DSP_REG_A]); +} + 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; @@ -745,18 +754,10 @@ static void dis_div(dsp_core_t* dsp) uint32_t srcreg=DSP_REG_NULL, destreg; switch((dsp->disasm_cur_inst>>4) & BITMASK(2)) { - case 0: - srcreg = DSP_REG_X0; - break; - case 1: - srcreg = DSP_REG_Y0; - break; - case 2: - srcreg = DSP_REG_X1; - break; - case 3: - srcreg = DSP_REG_Y1; - break; + case 0: srcreg = DSP_REG_X0; break; + case 1: srcreg = DSP_REG_Y0; break; + case 2: srcreg = DSP_REG_X1; break; + case 3: srcreg = DSP_REG_Y1; break; } destreg = DSP_REG_A+((dsp->disasm_cur_inst>>3) & 1); @@ -1710,6 +1711,30 @@ static void dis_move_y_imm(dsp_core_t* dsp) { dis_move_xy_imm(dsp, DSP_SPACE_Y); } +static void dis_mpyi(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + + uint32_t k = (dsp->disasm_cur_inst >> 2) & 1; + uint32_t d = (dsp->disasm_cur_inst >> 3) & 1; + uint32_t qq = (dsp->disasm_cur_inst >> 4) & BITMASK(2); + + unsigned int srcreg = DSP_REG_NULL; + switch (qq) { + case 0: srcreg = DSP_REG_X0; break; + case 1: srcreg = DSP_REG_Y0; break; + case 2: srcreg = DSP_REG_X1; break; + case 3: srcreg = DSP_REG_Y1; break; + } + + unsigned int destreg = d ? DSP_REG_B : DSP_REG_A; + + sprintf(dsp->disasm_str_instr, "mpyi %s#$%06x,%s,%s", + k ? "-" : "+", xxxx, + registers_name[srcreg], registers_name[destreg]); +} + static void dis_norm(dsp_core_t* dsp) { uint32_t srcreg, destreg; @@ -1801,6 +1826,15 @@ static void dis_sub_imm(dsp_core_t* dsp) xx, registers_name[d ? DSP_REG_B : DSP_REG_A]); } +static void dis_sub_long(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + uint32_t d = (dsp->disasm_cur_inst >> 3) & 1; + sprintf(dsp->disasm_str_instr, "sub #$%06x,%s", + xxxx, registers_name[d ? DSP_REG_B : DSP_REG_A]); +} + static void dis_tcc(dsp_core_t* dsp) { char ccname[16]; diff --git a/hw/xbox/dsp/dsp_emu.inl b/hw/xbox/dsp/dsp_emu.inl index 3121c17984..4188554509 100644 --- a/hw/xbox/dsp/dsp_emu.inl +++ b/hw/xbox/dsp/dsp_emu.inl @@ -5765,13 +5765,10 @@ static const emu_func_t opcodes_parmove[16] = { * Non-parallel moves instructions **********************************/ -static void emu_add_imm(dsp_core_t* dsp) +static void emu_add_x(dsp_core_t* dsp, uint32_t x, uint32_t d) { - uint32_t xx = (dsp->cur_inst >> 8) & BITMASK(6); - uint32_t source[3], dest[3]; - - if ((dsp->cur_inst >> 3) & 1) { + if (d) { dest[0] = dsp->registers[DSP_REG_B2]; dest[1] = dsp->registers[DSP_REG_B1]; dest[2] = dsp->registers[DSP_REG_B0]; @@ -5782,8 +5779,8 @@ static void emu_add_imm(dsp_core_t* dsp) } source[2] = 0; - source[1] = xx; - source[0] = 0; + source[1] = x; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; uint16_t newsr = dsp_add56(source, dest); @@ -5803,43 +5800,19 @@ static void emu_add_imm(dsp_core_t* dsp) dsp->registers[DSP_REG_SR] |= newsr; } +static void emu_add_imm(dsp_core_t* dsp) +{ + uint32_t xx = (dsp->cur_inst >> 8) & BITMASK(6); + uint32_t d = (dsp->cur_inst >> 3) & 1; + emu_add_x(dsp, xx, d); +} + static void emu_add_long(dsp_core_t* dsp) { uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); dsp->cur_inst_len++; - - uint32_t source[3], dest[3]; - - 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; - - uint16_t newsr = dsp_add56(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; + uint32_t d = (dsp->cur_inst >> 3) & 1; + emu_add_x(dsp, xxxx, d); } static void emu_and_long(dsp_core_t* dsp) @@ -6515,6 +6488,36 @@ static void emu_cmp_imm(dsp_core_t* dsp) dsp->registers[DSP_REG_SR] |= newsr; } +static void emu_cmp_long(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + uint32_t d = (dsp->cur_inst >> 3) & 1; + + 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]; + } + + source[2] = 0; + source[1] = xxxx; + source[0] = 0x0; + + uint16_t newsr = dsp_sub56(source, dest); + + 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_cmpu(dsp_core_t* dsp) { uint32_t ggg = (dsp->cur_inst >> 1) & BITMASK(3); @@ -6572,10 +6575,10 @@ static void emu_div(dsp_core_t* dsp) srcreg = DSP_REG_NULL; switch((dsp->cur_inst>>4) & BITMASK(2)) { - case 0: srcreg = DSP_REG_X0; break; - case 1: srcreg = DSP_REG_Y0; break; - case 2: srcreg = DSP_REG_X1; break; - case 3: srcreg = DSP_REG_Y1; break; + case 0: srcreg = DSP_REG_X0; break; + case 1: srcreg = DSP_REG_Y0; break; + case 2: srcreg = DSP_REG_X1; break; + case 3: srcreg = DSP_REG_Y1; break; } source[2] = 0; source[1] = dsp->registers[srcreg]; @@ -7667,6 +7670,40 @@ static void emu_move_y_imm(dsp_core_t* dsp) emu_move_xy_imm(dsp, DSP_SPACE_Y); } +static void emu_mpyi(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + uint32_t k = (dsp->cur_inst >> 2) & 1; + uint32_t d = (dsp->cur_inst >> 3) & 1; + uint32_t qq = (dsp->cur_inst >> 4) & BITMASK(2); + + unsigned int srcreg = DSP_REG_NULL; + switch (qq) { + case 0: srcreg = DSP_REG_X0; break; + case 1: srcreg = DSP_REG_Y0; break; + case 2: srcreg = DSP_REG_X1; break; + case 3: srcreg = DSP_REG_Y1; break; + } + + uint32_t source[3]; + dsp_mul56(xxxx, dsp->registers[srcreg], source, k ? SIGN_MINUS : SIGN_PLUS); + + if (d) { + dsp->registers[DSP_REG_B2] = source[0]; + dsp->registers[DSP_REG_B1] = source[1]; + dsp->registers[DSP_REG_B0] = source[2]; + } else { + dsp->registers[DSP_REG_A2] = source[0]; + dsp->registers[DSP_REG_A1] = source[1]; + dsp->registers[DSP_REG_A0] = source[2]; + } + + emu_ccr_update_e_u_n_z(dsp, source[0], source[1], source[2]); + dsp->registers[DSP_REG_SR] &= BITMASK(16)-(1<cur_inst >> 8) & BITMASK(6); - uint32_t d = (dsp->cur_inst >> 3) & 1; - uint32_t source[3], dest[3]; if (d) { @@ -7876,8 +7910,8 @@ static void emu_sub_imm(dsp_core_t* dsp) } source[2] = 0; - source[1] = xx; - source[0] = 0; + source[1] = x; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; uint16_t newsr = dsp_sub56(source, dest); @@ -7897,6 +7931,22 @@ static void emu_sub_imm(dsp_core_t* dsp) dsp->registers[DSP_REG_SR] |= newsr; } +static void emu_sub_imm(dsp_core_t* dsp) +{ + uint32_t xx = (dsp->cur_inst >> 8) & BITMASK(6); + uint32_t d = (dsp->cur_inst >> 3) & 1; + emu_sub_x(dsp, xx, d); +} + +static void emu_sub_long(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + uint32_t d = (dsp->cur_inst >> 3) & 1; + emu_sub_x(dsp, xxxx, d); +} + static void emu_tcc(dsp_core_t* dsp) { uint32_t cc_code, regsrc1, regdest1;