From 8f09c447d2a7704b5e02886f09b0a87cdb98f009 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Fri, 9 Aug 2013 17:20:05 +0000 Subject: [PATCH] tms32082: MP interrupts + more PP disasm work (nw) --- src/emu/cpu/tms32082/dis_pp.c | 141 ++++++++++++++++++++++++-------- src/emu/cpu/tms32082/mp_ops.c | 2 +- src/emu/cpu/tms32082/tms32082.c | 138 ++++++++++++++++++++++++++++++- src/emu/cpu/tms32082/tms32082.h | 19 ++++- 4 files changed, 262 insertions(+), 38 deletions(-) diff --git a/src/emu/cpu/tms32082/dis_pp.c b/src/emu/cpu/tms32082/dis_pp.c index d9814676dc3..01397ac39d3 100644 --- a/src/emu/cpu/tms32082/dis_pp.c +++ b/src/emu/cpu/tms32082/dis_pp.c @@ -83,10 +83,14 @@ static char *format_address_mode(int mode, int areg, int s, int limx) static void format_transfer(UINT64 op) { + char buffer[128]; + char *b = buffer; int lmode = (op >> 35) & 0xf; int gmode = (op >> 13) & 0xf; - print(" || "); + bool is_nop = false; + + memset(buffer, 0, sizeof(char)*128); switch (lmode) { @@ -109,8 +113,8 @@ static void format_transfer(UINT64 op) int dreg = (dstbank << 3) | dst; int sreg = (srcbank << 3) | src; - print("%s", CONDITION_CODES[cond]); - print("%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); + b += sprintf(b, "%s", CONDITION_CODES[cond]); + b += sprintf(b, "%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); break; } case 0x01: // Format 8: Conditional DU ||Conditional Field Move @@ -125,8 +129,8 @@ static void format_transfer(UINT64 op) int dreg = (dstbank << 3) | dst; int sreg = (4 << 3) | src; - print("%s", CONDITION_CODES[cond]); - print("%s = [%s:%d]%s", REG_NAMES[dreg], TRANSFER_SIZE[size], itm, REG_NAMES[sreg]); + b += sprintf(b, "%s", CONDITION_CODES[cond]); + b += sprintf(b, "%s = [%s%d]%s", REG_NAMES[dreg], TRANSFER_SIZE[size], itm, REG_NAMES[sreg]); break; } case 0x02: case 0x03: // Format 10: Conditional Non-D Data Unit @@ -139,14 +143,14 @@ static void format_transfer(UINT64 op) int dreg = (adstbank << 3) | dst; int sreg = (as1bank << 3) | src; - if (dreg == 0x20 && sreg == 0x20) + if (dreg == sreg) { - print("nop"); + is_nop = true; } else { - print("%s", CONDITION_CODES[cond]); - print("%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); + b += sprintf(b, "%s", CONDITION_CODES[cond]); + b += sprintf(b, "%s = %s", REG_NAMES[dreg], REG_NAMES[sreg]); } break; } @@ -154,8 +158,25 @@ static void format_transfer(UINT64 op) { if (op & 0x4) // Format 9: Conditional DU || Conditional Global { - print("%s", CONDITION_CODES[cond]); - print("cond du||cond global"); + int bank = (op >> 18) & 0xf; + int le = ((op >> 16) & 2) | ((op >> 9) & 1); + int size = (op >> 7) & 0x3; + int s = (op & (1 << 6)); + int reg = (op >> 10) & 0x7; + int ga = (op >> 3) & 0x7; + int gimx = (op >> 22) & 0x7; + + int greg = (bank << 3) | reg; + + b += sprintf(b, "%s", CONDITION_CODES[cond]); + + switch (le) + { + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx), REG_NAMES[greg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, gimx)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, gimx)); break; + } } else // Format 5: Global (Long Offset) { @@ -176,10 +197,10 @@ static void format_transfer(UINT64 op) switch (le) { - case 0: print("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset), REG_NAMES[greg]); break; - case 1: print("%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, offset)); break; - case 2: print("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; - case 3: print("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset), REG_NAMES[greg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, s, offset)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[size], format_address_mode(gmode, ga, s, offset)); break; } } break; @@ -196,17 +217,32 @@ static void format_transfer(UINT64 op) { case 0x00: // Format 2: Move || Local { - print("move||local"); + b += sprintf(b, "move||local "); break; } case 0x01: // Format 3: Field Move || Local { - print("field move||local"); + b += sprintf(b, "field move||local "); break; } case 0x02: case 0x03: // Format 6: Non-D DU || Local { - print("non-d du||local"); + int d = (op >> 32) & 0x7; + int s = (op & (1 << 28)); + int size = (op >> 29) & 0x3; + int le = ((op >> 16) & 2) | ((op >> 31) & 1); + int la = (op >> 25) & 0x7; + int limx = op & 0x7; + + int reg = (4 << 3) | d; + + switch (le) + { + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx), REG_NAMES[reg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, limx)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, limx)); break; + } break; } case 0x10: case 0x11: case 0x12: case 0x13: // Format 4: Local (Long Offset) @@ -234,10 +270,10 @@ static void format_transfer(UINT64 op) switch (le) { - case 0: print("&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset), REG_NAMES[reg]); break; - case 1: print("%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, offset)); break; - case 2: print("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; - case 3: print("%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset), REG_NAMES[reg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[reg], format_address_mode(lmode, la, s, offset)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[reg], TRANSFER_SIZE[size], format_address_mode(lmode, la, s, offset)); break; } break; } @@ -265,10 +301,10 @@ static void format_transfer(UINT64 op) // local transfer switch (local_le) { - case 0: print("&%s%s = %s", TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx), REG_NAMES[lreg]); break; - case 1: print("%s = %s", REG_NAMES[lreg], format_address_mode(lmode, la, local_s, local_imx)); break; - case 2: print("%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; - case 3: print("%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx), REG_NAMES[lreg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[lreg], format_address_mode(lmode, la, local_s, local_imx)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[lreg], TRANSFER_SIZE[local_size], format_address_mode(lmode, la, local_s, local_imx)); break; } print(", "); @@ -276,16 +312,19 @@ static void format_transfer(UINT64 op) // global transfer switch (global_le) { - case 0: print("&%s%s = %s", TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx), REG_NAMES[greg]); break; - case 1: print("%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, global_s, global_imx)); break; - case 2: print("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; - case 3: print("%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; + case 0: b += sprintf(b, "&%s%s = %s", TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx), REG_NAMES[greg]); break; + case 1: b += sprintf(b, "%s = %s", REG_NAMES[greg], format_address_mode(gmode, ga, global_s, global_imx)); break; + case 2: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; + case 3: b += sprintf(b, "%s = &%s%s", REG_NAMES[greg], TRANSFER_SIZE[global_size], format_address_mode(gmode, ga, global_s, global_imx)); break; } break; } } } } + + if (!is_nop) + print(" || %s", buffer); } static void format_alu_op(int aluop, int a, const char *dst_text, const char *a_text, const char *b_text, const char *c_text) @@ -366,6 +405,10 @@ static void format_alu_op(int aluop, int a, const char *dst_text, const char *a_ print("%s = %s | %s", dst_text, a_text, b_text); break; + case 0x44: // ~A & B & C | ~A & B & ~C = ~A & B + print("%s = ~%s & %s", dst_text, a_text, b_text); + break; + default: print("%s = b%02X(%s, %s, %s)", dst_text, aluop, a_text, b_text, c_text); break; @@ -386,7 +429,7 @@ static offs_t tms32082_disasm_pp(char *buffer, offs_t pc, const UINT8 *oprom) case 0x6: case 0x7: // Six-operand { - print("A: six operand"); + print("A: six operand "); break; } @@ -435,8 +478,22 @@ static offs_t tms32082_disasm_pp(char *buffer, offs_t pc, const UINT8 *oprom) int aluop = (op >> 51) & 0xff; int a = (op >> 59) & 1; - int s1reg = src1 | (0x4 << 3); - int dreg = dst | (0x4 << 3); + int adstbank; + int as1bank; + + if ((op & 0x0101c000) == 0x00004000) + { + adstbank = (op >> 18) & 0xf; + as1bank = (op >> 6) & 0xf; + } + else + { + adstbank = 4; + as1bank = 4; + } + + int s1reg = src1 | (as1bank << 3); + int dreg = dst | (adstbank << 3); int dstcreg = dst | (0x4 << 3); sprintf(dst_text, "%s", REG_NAMES[dreg]); @@ -500,10 +557,24 @@ static offs_t tms32082_disasm_pp(char *buffer, offs_t pc, const UINT8 *oprom) int aluop = (op >> 51) & 0xff; int a = (op >> 59) & 1; - int s1reg = src1 | (0x4 << 3); + int adstbank; + int as1bank; + + if ((op & 0x0101c000) == 0x00004000) + { + adstbank = (op >> 18) & 0xf; + as1bank = (op >> 6) & 0xf; + } + else + { + adstbank = 4; + as1bank = 4; + } + + int s1reg = src1 | (as1bank << 3); int s2reg = src2 | (0x4 << 3); int dstcreg = dst | (0x4 << 3); - int dreg = dst | (0x4 << 3); + int dreg = dst | (adstbank << 3); sprintf(dst_text, "%s", REG_NAMES[dreg]); switch (cl) diff --git a/src/emu/cpu/tms32082/mp_ops.c b/src/emu/cpu/tms32082/mp_ops.c index 0b091502109..2c7604795c7 100644 --- a/src/emu/cpu/tms32082/mp_ops.c +++ b/src/emu/cpu/tms32082/mp_ops.c @@ -751,7 +751,7 @@ void tms32082_mp_device::execute_reg_long_imm() { UINT32 data = has_imm ? imm32 : m_reg[OP_SRC1()]; - printf("CMND %08X\n", data); + processor_command(data); break; } diff --git a/src/emu/cpu/tms32082/tms32082.c b/src/emu/cpu/tms32082/tms32082.c index 7d206641798..b5d55620c44 100644 --- a/src/emu/cpu/tms32082/tms32082.c +++ b/src/emu/cpu/tms32082/tms32082.c @@ -135,6 +135,12 @@ void tms32082_mp_device::device_start() save_item(NAME(m_fetchpc)); save_item(NAME(m_reg)); save_item(NAME(m_acc)); + + save_item(NAME(m_in0p)); + save_item(NAME(m_in1p)); + save_item(NAME(m_outp)); + save_item(NAME(m_ie)); + save_item(NAME(m_intpen)); // Register state for debugger state_add(MP_PC, "pc", m_pc).formatstr("%08X"); @@ -180,6 +186,8 @@ void tms32082_mp_device::device_start() state_add(MP_IN0P, "in0p", m_in0p).formatstr("%08X"); state_add(MP_IN1P, "in1p", m_in1p).formatstr("%08X"); state_add(MP_OUTP, "outp", m_outp).formatstr("%08X"); + state_add(MP_IE, "ie", m_ie).formatstr("%08X"); + state_add(MP_INTPEN, "intpen", m_intpen).formatstr("%08X"); state_add(STATE_GENPC, "curpc", m_pc).noshow(); @@ -215,12 +223,74 @@ void tms32082_mp_device::device_reset() m_acc[1] = 0; m_acc[2] = 0; m_acc[3] = 0; + + m_in0p = 0; + m_in1p = 0; + m_outp = 0; + + m_intpen = 0; + m_ie = 0; +} + +void tms32082_mp_device::processor_command(UINT32 command) +{ + printf("MP CMND %08X: ", command); + + if (command & 0x80000000) + printf("Reset "); + if (command & 0x40000000) + printf("Halt "); + if (command & 0x20000000) + printf("Unhalt "); + if (command & 0x10000000) + printf("ICR "); + if (command & 0x08000000) + printf("DCR "); + if (command & 0x00004000) + printf("Task "); + if (command & 0x00002000) + printf("Msg "); + + printf("to: "); + + if (command & 0x00000400) + printf("VC "); + if (command & 0x00000200) + printf("TC "); + if (command & 0x00000100) + printf("MP "); + if (command & 0x00000008) + printf("PP3 "); + if (command & 0x00000004) + printf("PP2 "); + if (command & 0x00000002) + printf("PP1 "); + if (command & 0x00000001) + printf("PP0 "); + + printf("\n"); + + // PP0 + if (command & 1) + { + if (command & 0x20004000) + { + // simulate PP behavior for now... + m_program->write_dword(0x00000084, 3); + } + } } UINT32 tms32082_mp_device::read_creg(int reg) { switch (reg) { + case 0x4: // INTPEN + return m_intpen; + + case 0x6: // IE + return m_ie; + case 0xa: // PPERROR return 0xe0000; @@ -244,6 +314,21 @@ void tms32082_mp_device::write_creg(int reg, UINT32 data) { switch (reg) { + case 0x4: // INTPEN + { + for (int i=0; i < 32; i++) + { + if (data & (1 << i)) + m_intpen &= ~(1 << i); + } + break; + } + + case 0x6: // IE + m_ie = data; + printf("IE = %08X\n", data); + break; + case 0x4000: // IN0P m_in0p = data; break; @@ -262,6 +347,54 @@ void tms32082_mp_device::write_creg(int reg, UINT32 data) } } +void tms32082_mp_device::check_interrupts() +{ + if (m_ie & 1) // global interrupt mask + { + for (int i=1; i < 32; i++) + { + if (m_ie & m_intpen & (1 << i)) + { + m_epc = (m_fetchpc & ~3); + m_epc |= (m_ie & 1); // save global interrupt mask + // TODO: user mode bit to EPC + + m_eip = m_pc; + + m_ie &= ~1; // clear global interrupt mask + + // get new pc from vector table + m_fetchpc = m_pc = m_program->read_dword(0x01010180 + (i * 4)); + return; + } + } + } +} + +void tms32082_mp_device::execute_set_input(int inputnum, int state) +{ + if (state == ASSERT_LINE) + { + switch (inputnum) + { + case INPUT_X1: + m_intpen |= (1 << 11); + break; + case INPUT_X2: + m_intpen |= (1 << 12); + break; + case INPUT_X3: + m_intpen |= (1 << 29); + break; + case INPUT_X4: + m_intpen |= (1 << 30); + break; + default: + break; + } + } +} + UINT32 tms32082_mp_device::fetch() { UINT32 w = m_direct->read_decrypted_dword(m_fetchpc); @@ -283,6 +416,9 @@ void tms32082_mp_device::execute_run() while (m_icount > 0) { m_pc = m_fetchpc; + + check_interrupts(); + debugger_instruction_hook(this, m_pc); m_ir = fetch(); @@ -346,7 +482,7 @@ void tms32082_pp_device::state_string_export(const device_state_entry &entry, as void tms32082_pp_device::device_reset() { m_pc = 0; - m_fetchpc = 0; + m_fetchpc = 0x400010a0; } void tms32082_pp_device::execute_run() diff --git a/src/emu/cpu/tms32082/tms32082.h b/src/emu/cpu/tms32082/tms32082.h index b91d7822c22..81dd80296fd 100644 --- a/src/emu/cpu/tms32082/tms32082.h +++ b/src/emu/cpu/tms32082/tms32082.h @@ -51,7 +51,17 @@ public: MP_ACC3, MP_IN0P, MP_IN1P, - MP_OUTP + MP_OUTP, + MP_IE, + MP_INTPEN, + }; + + enum + { + INPUT_X1 = 1, + INPUT_X2 = 2, + INPUT_X3 = 3, + INPUT_X4 = 4, }; DECLARE_READ32_MEMBER(mp_param_r); @@ -68,6 +78,7 @@ protected: virtual UINT32 execute_max_cycles() const { return 1; } virtual UINT32 execute_input_lines() const { return 0; } virtual void execute_run(); + virtual void execute_set_input(int inputnum, int state); // device_memory_interface overrides virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const @@ -109,6 +120,10 @@ protected: UINT32 m_in0p; UINT32 m_in1p; UINT32 m_outp; + UINT32 m_ie; + UINT32 m_intpen; + UINT32 m_epc; + UINT32 m_eip; UINT32 *m_param_ram; @@ -117,6 +132,8 @@ protected: address_space *m_program; direct_read_data* m_direct; + void check_interrupts(); + void processor_command(UINT32 command); UINT32 fetch(); void delay_slot(); void execute();