diff --git a/hw/xbox/dsp/dsp_cpu.c b/hw/xbox/dsp/dsp_cpu.c index 9229505699..05a5ec90b7 100644 --- a/hw/xbox/dsp/dsp_cpu.c +++ b/hw/xbox/dsp/dsp_cpu.c @@ -138,15 +138,28 @@ static const int registers_mask[64] = { #include "dsp_dis.inl" +typedef bool (*match_func_t)(uint32_t op); + typedef struct OpcodeEntry { const char* template; const char* name; dis_func_t dis_func; emu_func_t emu_func; + match_func_t match_func; } OpcodeEntry; +static bool match_MMMRRR(uint32_t op) +{ + uint32_t RRR = (op >> 8) & BITMASK(3); + uint32_t MMM = (op >> 11) & BITMASK(3); + if (MMM == 0x6) { + return RRR == 0x0 || RRR == 0x4; + } + return true; +} + static const OpcodeEntry nonparallel_opcodes[] = { - { "0000000101iiiiii1000d000", "add #xx, D", NULL, NULL }, + { "0000000101iiiiii1000d000", "add #xx, D", dis_add_imm, emu_add_imm }, { "00000001010000001100d000", "add #xxxx, D", dis_add_long, emu_add_long }, { "0000000101iiiiii1000d110", "and #xx, D", NULL, NULL }, { "00000001010000001100d110", "and #xxxx, D", dis_and_long, emu_and_long }, @@ -158,12 +171,12 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00001101000100000100CCCC", "bcc xxxx", dis_bcc_long, emu_bcc_long }, //?? { "00000101CCCC01aaaa0aaaaa", "bcc xxx", dis_bcc_imm, emu_bcc_imm }, { "0000110100011RRR0100CCCC", "bcc Rn", NULL, NULL }, - { "0000101101MMMRRR0S00bbbb", "bchg #n, [X or Y]:ea", dis_bchg_ea, emu_bchg_ea }, + { "0000101101MMMRRR0S00bbbb", "bchg #n, [X or Y]:ea", dis_bchg_ea, emu_bchg_ea, match_MMMRRR }, { "0000101100aaaaaa0S00bbbb", "bchg #n, [X or Y]:aa", dis_bchg_aa, emu_bchg_aa }, { "0000101110pppppp0S00bbbb", "bchg #n, [X or Y]:pp", dis_bchg_pp, emu_bchg_pp }, { "0000000101qqqqqq0S0bbbbb", "bchg #n, [X or Y]:qq", NULL, NULL }, { "0000101111DDDDDD010bbbbb", "bchg, #n, D", dis_bchg_reg, emu_bchg_reg }, - { "0000101001MMMRRR0S00bbbb", "bclr #n, [X or Y]:ea", dis_bclr_ea, emu_bclr_ea }, + { "0000101001MMMRRR0S00bbbb", "bclr #n, [X or Y]:ea", dis_bclr_ea, emu_bclr_ea, match_MMMRRR }, { "0000101000aaaaaa0S00bbbb", "bclr #n, [X or Y]:aa", dis_bclr_aa, emu_bclr_aa }, { "0000101010pppppp0S00bbbb", "bclr #n, [X or Y]:pp", dis_bclr_pp, emu_bclr_pp }, { "0000000100qqqqqq0S00bbbb", "bclr #n, [X or Y]:qq", NULL, NULL }, @@ -171,26 +184,26 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "000011010001000011000000", "bra xxxx", NULL, NULL }, { "00000101000011aaaa0aaaaa", "bra xxx", dis_bra_imm, emu_bra_imm }, { "0000110100011RRR11000000", "bra Rn", NULL, NULL }, - { "0000110010MMMRRR0S0bbbbb", "brclr #n, [X or Y]:ea, xxxx", NULL, NULL }, + { "0000110010MMMRRR0S0bbbbb", "brclr #n, [X or Y]:ea, xxxx", NULL, NULL, match_MMMRRR }, { "0000110010aaaaaa1S0bbbbb", "brclr #n, [X or Y]:aa, xxxx", NULL, NULL }, { "0000110011pppppp0S0bbbbb", "brclr #n, [X or Y]:pp, xxxx", dis_brclr_pp, emu_brclr_pp }, { "0000010010qqqqqq0S0bbbbb", "brclr #n, [X or Y]:qq, xxxx", NULL, NULL }, - { "0000110011DDDDDD100bbbbb", "brclr #n, S, xxxx", NULL, NULL }, + { "0000110011DDDDDD100bbbbb", "brclr #n, S, xxxx", dis_brclr_reg, emu_brclr_reg }, { "00000000000000100001CCCC", "brkcc", NULL, NULL }, - { "0000110010MMMRRR0S1bbbbb", "brset #n, [X or Y]:ea, xxxx", NULL, NULL }, + { "0000110010MMMRRR0S1bbbbb", "brset #n, [X or Y]:ea, xxxx", NULL, NULL, match_MMMRRR }, { "0000110010aaaaaa1S1bbbbb", "brset #n, [X or Y]:aa, xxxx", NULL, NULL }, { "0000110011pppppp0S1bbbbb", "brset #n, [X or Y]:pp, xxxx", dis_brset_pp, emu_brset_pp }, { "0000010010qqqqqq0S1bbbbb", "brset #n, [X or Y]:qq, xxxx", NULL, NULL }, - { "0000110011DDDDDD101bbbbb", "brset #n, S, xxxx", NULL, NULL }, + { "0000110011DDDDDD101bbbbb", "brset #n, S, xxxx", dis_brset_reg, emu_brset_reg }, { "00001101000100000000CCCC", "bscc xxxx", NULL, NULL }, { "00000101CCCC00aaaa0aaaaa", "bscc xxx", NULL, NULL }, { "0000110100011RRR0000CCCC", "bscc Rn", NULL, NULL }, - { "0000110110MMMRRR0S0bbbbb", "bsclr #n, [X or Y]:ea, xxxx", NULL, NULL }, + { "0000110110MMMRRR0S0bbbbb", "bsclr #n, [X or Y]:ea, xxxx", NULL, NULL, match_MMMRRR }, { "0000110110aaaaaa1S0bbbbb", "bsclr #n, [X or Y]:aa, xxxx", NULL, NULL }, { "0000010010qqqqqq1S0bbbbb", "bsclr #n, [X or Y]:qq, xxxx", NULL, NULL }, { "0000110111pppppp0S0bbbbb", "bsclr #n, [X or Y]:pp, xxxx", NULL, NULL }, { "0000110111DDDDDD100bbbbb", "bsclr, #n, S, xxxx", NULL, NULL }, - { "0000101001MMMRRR0S1bbbbb", "bset #n, [X or Y]:ea", dis_bset_ea, emu_bset_ea }, + { "0000101001MMMRRR0S1bbbbb", "bset #n, [X or Y]:ea", dis_bset_ea, emu_bset_ea, match_MMMRRR }, { "0000101000aaaaaa0S1bbbbb", "bset #n, [X or Y]:aa", dis_bset_aa, emu_bset_aa }, { "0000101010pppppp0S1bbbbb", "bset #n, [X or Y]:pp", dis_bset_pp, emu_bset_pp }, { "0000000100qqqqqq0S1bbbbb", "bset #n, [X or Y]:qq", NULL, NULL }, @@ -198,18 +211,18 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "000011010001000010000000", "bsr xxxx", dis_bsr_long, emu_bsr_long }, { "00000101000010aaaa0aaaaa", "bsr xxx", dis_bsr_imm, emu_bsr_imm }, { "0000110100011RRR10000000", "bsr Rn", NULL, NULL }, - { "0000110110MMMRRR0S1bbbbb", "bsset #n, [X or Y]:ea, xxxx", NULL, NULL }, + { "0000110110MMMRRR0S1bbbbb", "bsset #n, [X or Y]:ea, xxxx", NULL, NULL, match_MMMRRR }, { "0000110110aaaaaa1S1bbbbb", "bsset #n, [X or Y]:aa, xxxx", NULL, NULL }, { "0000110111pppppp0S1bbbbb", "bsset #n, [X or Y]:pp, xxxx", NULL, NULL }, { "0000010010qqqqqq1S1bbbbb", "bsset #n, [X or Y]:qq, xxxx", NULL, NULL }, { "0000110111DDDDDD101bbbbb", "bsset #n, S, xxxx", NULL, NULL }, - { "0000101101MMMRRR0S10bbbb", "btst #n, [X or Y]:ea", dis_btst_ea, emu_btst_ea }, + { "0000101101MMMRRR0S10bbbb", "btst #n, [X or Y]:ea", dis_btst_ea, emu_btst_ea, match_MMMRRR }, { "0000101100aaaaaa0S10bbbb", "btst #n, [X or Y]:aa", dis_btst_aa, emu_btst_aa }, { "0000101110pppppp0S10bbbb", "btst #n, [X or Y]:pp", dis_btst_pp, emu_btst_pp }, { "0000000101qqqqqq0S10bbbb", "btst #n, [X or Y]:qq", NULL, NULL }, { "0000101111DDDDDD0110bbbb", "btst #n, D", dis_btst_reg, emu_btst_reg }, { "0000110000011110000000SD", "clb S, D", NULL, NULL }, - { "0000000101iiiiii1000d101", "cmp #xx, S2", NULL, NULL }, + { "0000000101iiiiii1000d101", "cmp #xx, S2", dis_cmp_imm, emu_cmp_imm }, { "00000001010000001100d101", "cmp #xxxx, S2", NULL, NULL }, { "00001100000111111111gggd", "cmpu S1, S2", dis_cmpu, emu_cmpu }, { "000000000000001000000000", "debug", NULL, NULL }, @@ -217,15 +230,15 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00000000000000000000101d", "dec D", NULL, NULL, /*dis_dec, emu_dec*/ }, { "000000011000000001JJd000", "div S, D", dis_div, emu_div }, { "000000010010010s1sdkQQQQ", "dmac S1, S2, D", NULL, NULL }, - { "0000011001MMMRRR0S000000", "do [X or Y]:ea, expr", dis_do_ea, emu_do_ea }, + { "0000011001MMMRRR0S000000", "do [X or Y]:ea, expr", dis_do_ea, emu_do_ea, match_MMMRRR }, { "0000011000aaaaaa0S000000", "do [X or Y]:aa, expr", dis_do_aa, emu_do_aa }, { "00000110iiiiiiii1000hhhh", "do #xxx, expr", dis_do_imm, emu_do_imm }, { "0000011011DDDDDD00000000", "do S, expr", dis_do_reg, emu_do_reg }, { "000000000000001000000011", "do_f", NULL, NULL }, - { "0000011001MMMRRR0S010000", "dor [X or Y]:ea, label", NULL, NULL }, + { "0000011001MMMRRR0S010000", "dor [X or Y]:ea, label", NULL, NULL, match_MMMRRR }, { "0000011000aaaaaa0S010000", "dor [X or Y]:aa, label", NULL, NULL }, { "00000110iiiiiiii1001hhhh", "dor #xxx, label", dis_dor_imm, emu_dor_imm }, - { "0000011011DDDDDD00010000", "dor S, label", NULL, NULL }, + { "0000011011DDDDDD00010000", "dor S, label", dis_dor_reg, emu_dor_reg }, { "000000000000001000000010", "dor_f", NULL, NULL }, { "000000000000000010001100", "enddo", NULL, emu_enddo }, { "0000000101iiiiii1000d011", "eor #xx, D", NULL, NULL }, @@ -239,29 +252,29 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00001100000110110qqqSSSD", "insert S1, S2, D", NULL, NULL }, { "00001100000110010qqq000D", "insert #CO, S2, D", NULL, NULL }, { "00001110CCCCaaaaaaaaaaaa", "jcc xxx", dis_jcc_imm, emu_jcc_imm }, - { "0000101011MMMRRR1010CCCC", "jcc ea", dis_jcc_ea, emu_jcc_ea }, - { "0000101001MMMRRR1S00bbbb", "jclr #n, [X or Y]:ea, xxxx", dis_jclr_ea, emu_jclr_ea }, + { "0000101011MMMRRR1010CCCC", "jcc ea", dis_jcc_ea, emu_jcc_ea, match_MMMRRR }, + { "0000101001MMMRRR1S00bbbb", "jclr #n, [X or Y]:ea, xxxx", dis_jclr_ea, emu_jclr_ea, match_MMMRRR }, { "0000101000aaaaaa1S00bbbb", "jclr #n, [X or Y]:aa, xxxx", dis_jclr_aa, emu_jclr_aa }, { "0000101010pppppp1S00bbbb", "jclr #n, [X or Y]:pp, xxxx", dis_jclr_pp, emu_jclr_pp }, { "0000000110qqqqqq1S00bbbb", "jclr #n, [X or Y]:qq, xxxx", NULL, NULL }, { "0000101011DDDDDD0000bbbb", "jclr #n, S, xxxx", dis_jclr_reg, emu_jclr_reg }, - { "0000101011MMMRRR10000000", "jmp ea", dis_jmp_ea, emu_jmp_ea }, + { "0000101011MMMRRR10000000", "jmp ea", dis_jmp_ea, emu_jmp_ea, match_MMMRRR }, { "000011000000aaaaaaaaaaaa", "jmp xxx", dis_jmp_imm, emu_jmp_imm }, { "00001111CCCCaaaaaaaaaaaa", "jscc xxx", dis_jscc_imm, emu_jscc_imm }, - { "0000101111MMMRRR1010CCCC", "jscc ea", dis_jscc_ea, emu_jscc_ea }, - { "0000101101MMMRRR1S00bbbb", "jsclr #n, [X or Y]:ea, xxxx", dis_jsclr_ea, emu_jsclr_ea }, - { "0000101100MMMRRR1S00bbbb", "jsclr #n, [X or Y]:aa, xxxx", dis_jsclr_aa, emu_jsclr_aa }, + { "0000101111MMMRRR1010CCCC", "jscc ea", dis_jscc_ea, emu_jscc_ea, match_MMMRRR }, + { "0000101101MMMRRR1S00bbbb", "jsclr #n, [X or Y]:ea, xxxx", dis_jsclr_ea, emu_jsclr_ea, match_MMMRRR }, + { "0000101100MMMRRR1S00bbbb", "jsclr #n, [X or Y]:aa, xxxx", dis_jsclr_aa, emu_jsclr_aa, match_MMMRRR }, { "0000101110pppppp1S0bbbbb", "jsclr #n, [X or Y]:pp, xxxx", dis_jsclr_pp, emu_jsclr_pp }, { "0000000111qqqqqq1S0bbbbb", "jsclr #n, [X or Y]:qq, xxxx", NULL, NULL }, { "0000101111DDDDDD000bbbbb", "jsclr #n, S, xxxx", dis_jsclr_reg, emu_jsclr_reg }, - { "0000101001MMMRRR1S10bbbb", "jset #n, [X or Y]:ea, xxxx", dis_jset_ea, emu_jset_ea }, - { "0000101000MMMRRR1S10bbbb", "jset #n, [X or Y]:aa, xxxx", dis_jset_aa, emu_jset_aa }, + { "0000101001MMMRRR1S10bbbb", "jset #n, [X or Y]:ea, xxxx", dis_jset_ea, emu_jset_ea, match_MMMRRR }, + { "0000101000MMMRRR1S10bbbb", "jset #n, [X or Y]:aa, xxxx", dis_jset_aa, emu_jset_aa, match_MMMRRR }, { "0000101010pppppp1S10bbbb", "jset #n, [X or Y]:pp, xxxx", dis_jset_pp, emu_jset_pp }, { "0000000110qqqqqq1S10bbbb", "jset #n, [X or Y]:qq, xxxx", NULL, NULL }, { "0000101011DDDDDD0010bbbb", "jset #n, S, xxxx", dis_jset_reg, emu_jset_reg }, - { "0000101111MMMRRR10000000", "jsr ea", dis_jsr_ea, emu_jsr_ea }, + { "0000101111MMMRRR10000000", "jsr ea", dis_jsr_ea, emu_jsr_ea, match_MMMRRR }, { "000011010000aaaaaaaaaaaa", "jsr xxx", dis_jsr_imm, emu_jsr_imm }, - { "0000101101MMMRRR1S10bbbb", "jsset #n, [X or Y]:ea, xxxx", dis_jsset_ea, emu_jsset_ea }, + { "0000101101MMMRRR1S10bbbb", "jsset #n, [X or Y]:ea, xxxx", dis_jsset_ea, emu_jsset_ea, match_MMMRRR }, { "0000101100aaaaaa1S10bbbb", "jsset #n, [X or Y]:aa, xxxx", dis_jsset_aa, emu_jsset_aa }, { "0000101110pppppp1S1bbbbb", "jsset #n, [X or Y]:pp, xxxx", dis_jsset_pp, emu_jsset_pp }, { "0000000111qqqqqq1S1bbbbb", "jsset #n, [X or Y]:qq, xxxx", NULL, NULL }, @@ -284,17 +297,17 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "0000101101110RRR1WDDDDDD", "move Y:{Rn + xxxx} <-> R", NULL, NULL }, { "0000001aaaaaaRRR1a0WDDDD", "move X:{Rn + xxx} <-> R", dis_move_x_imm, emu_move_x_imm }, { "0000001aaaaaaRRR1a1WDDDD", "move Y:{Rn + xxx} <-> R", NULL, NULL }, - { "00000101W1MMMRRR0s1ddddd", "movec [X or Y]:ea <-> R", dis_movec_ea, emu_movec_ea }, - { "00000101W0aaaaaa0s1ddddd", "movec [X or Y]:aa <-> R", dis_movec_aa, emu_movec_aa }, + { "00000101W1MMMRRR0s1ddddd", "movec [X or Y]:ea <-> R", dis_movec_ea, emu_movec_ea, match_MMMRRR }, + { "00000101W0aaaaaa0s1ddddd", "movec [X or Y]:aa <-> R", dis_movec_aa, emu_movec_aa, match_MMMRRR }, { "00000100W1eeeeee101ddddd", "movec R1, R2", dis_movec_reg, emu_movec_reg }, { "00000101iiiiiiii101ddddd", "movec #xx, D1", dis_movec_imm, emu_movec_imm }, - { "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_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 }, + { "00000111W1MMMRRR10dddddd", "movem P:ea <-> R", dis_movem_ea, emu_movem_ea, match_MMMRRR }, + { "00000111W0aaaaaa00dddddd", "movem P:ea <-> R", dis_movem_aa, emu_movem_aa, match_MMMRRR }, + { "0000100sW1MMMRRR1Spppppp", "movep [X or Y]:ea <-> [X or Y]:pp", dis_movep_23, emu_movep_23, match_MMMRRR }, + { "00000111W1MMMRRR0Sqqqqqq", "movep [X or Y]:ea <-> X:qq", dis_movep_x_qq, emu_movep_x_qq, match_MMMRRR }, + { "00000111W0MMMRRR1Sqqqqqq", "movep [X or Y]:ea <-> Y:qq", NULL, NULL, match_MMMRRR }, + { "0000100sW1MMMRRR01pppppp", "movep [X or Y]:pp <-> P:ea", dis_movep_1, emu_movep_1, match_MMMRRR }, + { "000000001WMMMRRR0sqqqqqq", "movep [X or Y]:qq <-> P:ea", NULL, NULL, match_MMMRRR }, { "0000100sW1dddddd00pppppp", "movep [X or Y]:pp <-> R", dis_movep_0, emu_movep_0 }, { "00000100W1dddddd1q0qqqqq", "movep X:qq <-> R", NULL, NULL }, { "00000100W1dddddd0q1qqqqq", "movep Y:qq <-> R", NULL, NULL }, @@ -312,11 +325,11 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "000000000000000000000011", "pflush", NULL, NULL }, { "000000000000000000000001", "pflushun", NULL, NULL }, { "000000000000000000000010", "pfree", NULL, NULL }, - { "0000101111MMMRRR10000001", "plock ea", NULL, NULL }, + { "0000101111MMMRRR10000001", "plock ea", NULL, NULL, match_MMMRRR }, { "000000000000000000001111", "plockr xxxx", NULL, NULL }, - { "0000101011MMMRRR10000001", "punlock ea", NULL, NULL }, + { "0000101011MMMRRR10000001", "punlock ea", NULL, NULL, match_MMMRRR }, { "000000000000000000001110", "punlockr xxxx", NULL, NULL }, - { "0000011001MMMRRR0S100000", "rep [X or Y]:ea", dis_rep_ea, emu_rep_ea }, + { "0000011001MMMRRR0S100000", "rep [X or Y]:ea", dis_rep_ea, emu_rep_ea, match_MMMRRR }, { "0000011000aaaaaa0S100000", "rep [X or Y]:aa", dis_rep_aa, emu_rep_aa }, { "00000110iiiiiiii1010hhhh", "rep #xxx", dis_rep_imm, emu_rep_imm }, { "0000011011dddddd00100000", "rep S", dis_rep_reg, emu_rep_reg }, @@ -331,7 +344,7 @@ static const OpcodeEntry nonparallel_opcodes[] = { { "00000010CCCC1ttt00000TTT", "tcc S2, D2", dis_tcc, emu_tcc }, { "000000000000000000000110", "trap", NULL, NULL }, { "00000000000000000001CCCC", "trapcc", NULL, NULL }, - { "0000101S11MMMRRR110i0000", "vsl", NULL, NULL }, + { "0000101S11MMMRRR110i0000", "vsl", NULL, NULL, match_MMMRRR }, { "000000000000000010000110", "wait", NULL, emu_wait }, }; @@ -412,6 +425,11 @@ static OpcodeEntry lookup_opcode(uint32_t op) { int i; for (i=0; i= DSP_PERIPH_BASE) { assert(dsp->read_peripheral); return dsp->read_peripheral(dsp, address); + } else if (address >= DSP_MIXBUFFER_BASE && address < DSP_MIXBUFFER_BASE+DSP_MIXBUFFER_SIZE) { + return dsp->mixbuffer[address-DSP_MIXBUFFER_BASE]; + } else if (address >= DSP_MIXBUFFER_READ_BASE && address < DSP_MIXBUFFER_READ_BASE+DSP_MIXBUFFER_SIZE) { + return dsp->mixbuffer[address-DSP_MIXBUFFER_READ_BASE]; + } else { + assert(address < DSP_XRAM_SIZE); + return dsp->xram[address]; } - assert(address < DSP_XRAM_SIZE); - return dsp->xram[address]; } else if (space == DSP_SPACE_Y) { assert(address < DSP_YRAM_SIZE); return dsp->yram[address]; @@ -984,9 +1007,14 @@ static void write_memory_raw(dsp_core_t* dsp, int space, uint32_t address, uint3 assert(dsp->write_peripheral); dsp->write_peripheral(dsp, address, value); return; + } else if (address >= DSP_MIXBUFFER_BASE && address < DSP_MIXBUFFER_BASE+DSP_MIXBUFFER_SIZE) { + dsp->mixbuffer[address-DSP_MIXBUFFER_BASE] = value; + } else if (address >= DSP_MIXBUFFER_READ_BASE && address < DSP_MIXBUFFER_READ_BASE+DSP_MIXBUFFER_SIZE) { + dsp->mixbuffer[address-DSP_MIXBUFFER_READ_BASE] = value; + } else { + assert(address < DSP_XRAM_SIZE); + dsp->xram[address] = value; } - assert(address < DSP_XRAM_SIZE); - dsp->xram[address] = value; } else if (space == DSP_SPACE_Y) { assert(address < DSP_YRAM_SIZE); dsp->yram[address] = value; @@ -1027,8 +1055,10 @@ static void write_memory_disasm(dsp_core_t* dsp, int space, uint32_t address, ui } curvalue = read_memory_disasm(dsp, space, address); - sprintf(dsp->str_disasm_memory[dsp->disasm_memory_ptr],"Mem: %c:0x%04x 0x%06x -> 0x%06x", space_c, address, oldvalue, curvalue); - dsp->disasm_memory_ptr ++; + if (dsp->disasm_memory_ptr < ARRAYSIZE(dsp->str_disasm_memory)) { + sprintf(dsp->str_disasm_memory[dsp->disasm_memory_ptr], "Mem: %c:0x%04x 0x%06x -> 0x%06x", space_c, address, oldvalue, curvalue); + dsp->disasm_memory_ptr ++; + } } static void dsp_write_reg(dsp_core_t* dsp, uint32_t numreg, uint32_t value) diff --git a/hw/xbox/dsp/dsp_cpu.h b/hw/xbox/dsp/dsp_cpu.h index e9256c5e20..c0770d394c 100644 --- a/hw/xbox/dsp/dsp_cpu.h +++ b/hw/xbox/dsp/dsp_cpu.h @@ -111,10 +111,14 @@ #define DSP_SPACE_Y 0x01 #define DSP_SPACE_P 0x02 -#define DSP_XRAM_SIZE 4096 +#define DSP_XRAM_SIZE 3072 #define DSP_YRAM_SIZE 2048 #define DSP_PRAM_SIZE 4096 +#define DSP_MIXBUFFER_BASE 3072 +#define DSP_MIXBUFFER_SIZE 1024 +#define DSP_MIXBUFFER_READ_BASE 5120 + #define DSP_PERIPH_BASE 0xFFFF80 #define DSP_PERIPH_SIZE 128 @@ -164,6 +168,8 @@ struct dsp_core_s { uint32_t yram[DSP_YRAM_SIZE]; uint32_t pram[DSP_PRAM_SIZE]; + uint32_t mixbuffer[DSP_MIXBUFFER_SIZE]; + /* peripheral space, x:0xffff80-0xffffff */ uint32_t periph[DSP_PERIPH_SIZE]; diff --git a/hw/xbox/dsp/dsp_dis.inl b/hw/xbox/dsp/dsp_dis.inl index 280ec56a44..801721d07e 100644 --- a/hw/xbox/dsp/dsp_dis.inl +++ b/hw/xbox/dsp/dsp_dis.inl @@ -219,10 +219,18 @@ static void dis_undefined(dsp_core_t* dsp) } } +static void dis_add_imm(dsp_core_t* dsp) +{ + uint32_t xx = (dsp->disasm_cur_inst >> 8) & BITMASK(6); + uint32_t accname = ((dsp->disasm_cur_inst >> 3) & 1) ? DSP_REG_B : DSP_REG_A; + sprintf(dsp->disasm_str_instr, "add #$%02x,%s", xx, registers_name[accname]); +} + static void dis_add_long(dsp_core_t* dsp) { - dsp->disasm_cur_inst_len++; uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + uint32_t accname = ((dsp->disasm_cur_inst >> 3) & 1) ? DSP_REG_B : DSP_REG_A; sprintf(dsp->disasm_str_instr, "add #$%04x,%s", xxxx, registers_name[accname]); } @@ -424,7 +432,8 @@ static void dis_bra_imm(dsp_core_t* dsp) { 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); + sprintf(dsp->disasm_str_instr, "bra p:$%04x", + (dsp->pc + dsp_signextend(9, xxx)) & BITMASK(24) ); } static void dis_brclr_pp(dsp_core_t* dsp) @@ -443,7 +452,20 @@ static void dis_brclr_pp(dsp_core_t* dsp) sprintf(name,"x:$%06x",value+0xffffc0); } - sprintf(dsp->disasm_str_instr,"brclr #%d,%s,p:$%06x", numbit, name, xxxx); + sprintf(dsp->disasm_str_instr,"brclr #%d,%s,p:$%06x", + numbit, name, (dsp->pc + xxxx) & BITMASK(24) ); +} + +static void dis_brclr_reg(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + + uint32_t value = (dsp->disasm_cur_inst>>8) & BITMASK(6); + uint32_t numbit = dsp->disasm_cur_inst & BITMASK(5); + + sprintf(dsp->disasm_str_instr, "brclr #%d,%s,p:$%04x", + numbit, registers_name[value], (dsp->pc + xxxx) & BITMASK(24)); } static void dis_brset_pp(dsp_core_t* dsp) @@ -462,7 +484,20 @@ static void dis_brset_pp(dsp_core_t* dsp) sprintf(name,"x:$%06x",value+0xffffc0); } - sprintf(dsp->disasm_str_instr,"brset #%d,%s,p:$%06x", numbit, name, xxxx); + sprintf(dsp->disasm_str_instr,"brset #%d,%s,p:$%06x", + numbit, name, (dsp->pc + xxxx) & BITMASK(24) ); +} + +static void dis_brset_reg(dsp_core_t* dsp) +{ + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + + uint32_t value = (dsp->disasm_cur_inst>>8) & BITMASK(6); + uint32_t numbit = dsp->disasm_cur_inst & BITMASK(5); + + sprintf(dsp->disasm_str_instr, "brset #%d,%s,p:$%04x", + numbit, registers_name[value], (dsp->pc + xxxx) & BITMASK(24)); } static void dis_bset_aa(dsp_core_t* dsp) @@ -541,14 +576,16 @@ static void dis_bsr_long(dsp_core_t* dsp) { dsp->disasm_cur_inst_len++; uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); - sprintf(dsp->disasm_str_instr, "bsr p:$%06x", xxxx); + sprintf(dsp->disasm_str_instr, "bsr p:$%06x", + (dsp->pc + xxxx) & BITMASK(24)); } static void dis_bsr_imm(dsp_core_t* dsp) { uint32_t xxx = (dsp->disasm_cur_inst & BITMASK(5)) + ((dsp->disasm_cur_inst & (BITMASK(4) << 6)) >> 1); - sprintf(dsp->disasm_str_instr, "bsr p:$%04x", xxx); + sprintf(dsp->disasm_str_instr, "bsr p:$%04x", + (dsp->pc + dsp_signextend(9, xxx)) & BITMASK(24) ); } static void dis_btst_aa(dsp_core_t* dsp) @@ -623,6 +660,14 @@ static void dis_btst_reg(dsp_core_t* dsp) sprintf(dsp->disasm_str_instr,"btst #%d,%s", numbit, registers_name[value]); } +static void dis_cmp_imm(dsp_core_t* dsp) { + uint32_t xx = (dsp->disasm_cur_inst >> 8) & BITMASK(6); + uint32_t d = (dsp->disasm_cur_inst >> 3) & 1; + + sprintf(dsp->disasm_str_instr, "cmp #$%02x,%s", + xx, 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; @@ -725,12 +770,24 @@ static void dis_do_reg(dsp_core_t* dsp) static void dis_dor_imm(dsp_core_t* dsp) { + uint32_t addr = read_memory_p(dsp, dsp->pc+1); dsp->disasm_cur_inst_len++; + uint32_t xxx = ((dsp->disasm_cur_inst>>8) & BITMASK(8)) | ((dsp->disasm_cur_inst & BITMASK(4))<<8); + sprintf(dsp->disasm_str_instr,"dor #$%04x,p:$%04x", - ((dsp->disasm_cur_inst>>8) & BITMASK(8))|((dsp->disasm_cur_inst & BITMASK(4))<<8), - read_memory_p(dsp, dsp->pc+1) - ); + xxx, (dsp->pc + addr) & BITMASK(24)); +} + +static void dis_dor_reg(dsp_core_t* dsp) +{ + uint32_t addr = read_memory_p(dsp, dsp->pc+1); + dsp->disasm_cur_inst_len++; + + uint32_t numreg = (dsp->disasm_cur_inst >> 8) & BITMASK(6); + + sprintf(dsp->disasm_str_instr,"dor %s,p:$%04x", + registers_name[numreg], (dsp->pc + addr) & BITMASK(24)); } static void dis_jcc_ea(dsp_core_t* dsp) @@ -1501,7 +1558,7 @@ static void dis_movep_x_qq(dsp_core_t* dsp) { char srcname[16]="",dstname[16]="",name[16]=""; uint32_t addr = 0xffff80 + (dsp->disasm_cur_inst & BITMASK(6)); - uint32_t ea_mode = (dsp->cur_inst>>8) & BITMASK(6); + uint32_t ea_mode = (dsp->disasm_cur_inst>>8) & BITMASK(6); uint32_t easpace = (dsp->disasm_cur_inst>>6) & 1; int retour = dis_calc_ea(dsp, ea_mode, name); diff --git a/hw/xbox/dsp/dsp_dma.c b/hw/xbox/dsp/dsp_dma.c index 5c96b4120d..9780a53852 100644 --- a/hw/xbox/dsp/dsp_dma.c +++ b/hw/xbox/dsp/dsp_dma.c @@ -21,6 +21,7 @@ #define DMA_CONTROL_FROZEN (1 << 3) #define DMA_CONTROL_RUNNING (1 << 4) #define DMA_CONTROL_STOPPED (1 << 5) +#define DMA_CONTROL_WRITE_ #define NODE_POINTER_VAL 0x3fff #define NODE_POINTER_EOL (1 << 14) @@ -37,13 +38,13 @@ static void dsp_dma_run(DSPDMAState *s) uint32_t addr = s->next_block & NODE_POINTER_VAL; assert((addr+6) < sizeof(s->core->xram)); - uint32_t next_block = s->core->xram[addr]; - uint32_t control = s->core->xram[addr+1]; - uint32_t count = s->core->xram[addr+2]; - uint32_t dsp_offset = s->core->xram[addr+3]; - uint32_t scratch_offset = s->core->xram[addr+4]; - uint32_t scratch_base = s->core->xram[addr+5]; - uint32_t scratch_size = s->core->xram[addr+6]+1; + uint32_t next_block = dsp56k_read_memory(s->core, DSP_SPACE_X, addr); + uint32_t control = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+1); + uint32_t count = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+2); + uint32_t dsp_offset = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+3); + uint32_t scratch_offset = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+4); + uint32_t scratch_base = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+5); + uint32_t scratch_size = dsp56k_read_memory(s->core, DSP_SPACE_X, addr+6)+1; printf("\n\n\nQQQ DMA addr %x, control %x, count %x, dsp_offset %x, scratch_offset %x, base %x, size %x\n\n\n", addr, control, count, dsp_offset, scratch_offset, scratch_base, scratch_size); @@ -64,25 +65,31 @@ static void dsp_dma_run(DSPDMAState *s) uint32_t buf_id = (control >> 5) & 0xf; - size_t scratch_addr = scratch_offset; + size_t scratch_addr; if (buf_id == 0xe) { // 'circular'? - assert(scratch_addr == 0); + // assert(scratch_offset == 0); assert(scratch_offset + count * item_size < scratch_size); - scratch_addr += scratch_base; //?? - } else if (buf_id != 0xf) { // 'offset'? + scratch_addr = scratch_base + scratch_offset; //?? + } else if (buf_id == 0xf) { // 'offset'? + scratch_addr = scratch_offset; + } else { assert(false); } - uint32_t* dsp_ptr; + uint32_t mem_address; + int mem_space; if (dsp_offset < 0x1800) { - assert(dsp_offset+count < sizeof(s->core->xram)); - dsp_ptr = s->core->xram + dsp_offset; + assert(dsp_offset+count < 0x1800); + mem_space = DSP_SPACE_X; + mem_address = dsp_offset; } else if (dsp_offset >= 0x1800 && dsp_offset < 0x2000) { //? - assert(dsp_offset-0x1800 + count < sizeof(s->core->yram)); - dsp_ptr = s->core->yram + dsp_offset - 0x1800; + assert(dsp_offset+count < 0x2000); + mem_space = DSP_SPACE_Y; + mem_address = dsp_offset - 0x1800; } else if (dsp_offset >= 0x2800 && dsp_offset < 0x3800) { //? - assert(dsp_offset-0x2800 + count < sizeof(s->core->pram)); - dsp_ptr = s->core->pram + dsp_offset - 0x2800; + assert(dsp_offset+count < 0x3800); + mem_space = DSP_SPACE_P; + mem_address = dsp_offset - 0x2800; } else { assert(false); } @@ -94,9 +101,10 @@ static void dsp_dma_run(DSPDMAState *s) if (control & NODE_CONTROL_DIRECTION) { int i; for (i=0; icore, mem_space, mem_address+i); switch(item_size) { case 4: - *(uint32_t*)(scratch_buf + i*4) = dsp_ptr[i]; + *(uint32_t*)(scratch_buf + i*4) = v; break; default: assert(false); @@ -112,14 +120,16 @@ static void dsp_dma_run(DSPDMAState *s) int i; for (i=0; icore, mem_space, mem_address+i, v); } } diff --git a/hw/xbox/dsp/dsp_emu.inl b/hw/xbox/dsp/dsp_emu.inl index 0ae000db77..180057f164 100644 --- a/hw/xbox/dsp/dsp_emu.inl +++ b/hw/xbox/dsp/dsp_emu.inl @@ -5742,13 +5742,50 @@ static const emu_func_t opcodes_parmove[16] = { * Non-parallel moves instructions **********************************/ +static void emu_add_imm(dsp_core_t* dsp) +{ + uint32_t xx = (dsp->cur_inst >> 8) & BITMASK(6); + + 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] = xx; + source[0] = 0; + + 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; +} + 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]; - uint16_t newsr; if ((dsp->cur_inst >> 3) & 1) { dest[0] = dsp->registers[DSP_REG_B2]; @@ -5764,7 +5801,7 @@ static void emu_add_long(dsp_core_t* dsp) source[1] = xxxx; source[0] = source[1] & (1<<23) ? 0xff : 0x0; - newsr = dsp_add56(source, dest); + uint16_t newsr = dsp_add56(source, dest); if ((dsp->cur_inst >> 3) & 1) { dsp->registers[DSP_REG_B2] = dest[0]; @@ -6071,6 +6108,29 @@ static void emu_brclr_pp(dsp_core_t* dsp) { } } +static void emu_brclr_reg(dsp_core_t* dsp) { + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + uint32_t numreg = (dsp->cur_inst>>8) & BITMASK(6); + uint32_t numbit = dsp->cur_inst & BITMASK(5); + + uint32_t value; + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + emu_pm_read_accu24(dsp, numreg, &value); + } else { + value = dsp->registers[numreg]; + } + + 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) { uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); dsp->cur_inst_len++; @@ -6083,6 +6143,29 @@ static void emu_brset_pp(dsp_core_t* dsp) { dsp->instr_cycle += 4; + if (value & (1<pc += xxxx; + dsp->pc &= BITMASK(24); + dsp->cur_inst_len = 0; + } +} + +static void emu_brset_reg(dsp_core_t* dsp) { + uint32_t xxxx = read_memory_p(dsp, dsp->pc+1); + dsp->cur_inst_len++; + + uint32_t numreg = (dsp->cur_inst>>8) & BITMASK(6); + uint32_t numbit = dsp->cur_inst & BITMASK(5); + + uint32_t value; + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + emu_pm_read_accu24(dsp, numreg, &value); + } else { + value = dsp->registers[numreg]; + } + + dsp->instr_cycle += 4; + if (value & (1<pc += xxxx; dsp->pc &= BITMASK(24); @@ -6292,9 +6375,37 @@ static void emu_btst_reg(dsp_core_t* dsp) dsp->instr_cycle += 2; } +static void emu_cmp_imm(dsp_core_t* dsp) { + uint32_t xx = (dsp->cur_inst >> 8) & BITMASK(6); + 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] = xx; + 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->disasm_cur_inst >> 1) & BITMASK(3); - uint32_t d = dsp->disasm_cur_inst & 1; + uint32_t ggg = (dsp->cur_inst >> 1) & BITMASK(3); + uint32_t d = dsp->cur_inst & 1; uint32_t srcreg = DSP_REG_NULL; switch (ggg) { @@ -6503,6 +6614,28 @@ static void emu_dor_imm(dsp_core_t* dsp) dsp->instr_cycle += 4; } +static void emu_dor_reg(dsp_core_t* dsp) +{ + 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<cur_inst>>8) & BITMASK(6); + if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + emu_pm_read_accu24(dsp, numreg, &dsp->registers[DSP_REG_LC]); + } else { + dsp->registers[DSP_REG_LC] = dsp->registers[numreg]; + } + dsp->registers[DSP_REG_LC] &= BITMASK(16); + + dsp->instr_cycle += 4; +} + static void emu_enddo(dsp_core_t* dsp) { uint32_t saved_pc, saved_sr; @@ -7366,11 +7499,11 @@ static void emu_move_x_long(dsp_core_t* dsp) { static void emu_move_x_imm(dsp_core_t* dsp) { // 0000001aaaaaaRRR1a0WDDDD - 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 xxx = (((dsp->cur_inst >> 11) & BITMASK(6)) << 1) + + ((dsp->cur_inst >> 6) & 1); + int W = (dsp->cur_inst >> 4) & 1; + uint32_t offreg = DSP_REG_R0 + ((dsp->cur_inst >> 8) & BITMASK(3)); + uint32_t numreg = dsp->cur_inst & BITMASK(4); uint32_t x_addr = (dsp->registers[offreg] + dsp_signextend(7, xxx)) & BITMASK(24); if (!W) {