From 52d4a43e1b2c2a8f4424a91679a1c0531ed18a98 Mon Sep 17 00:00:00 2001 From: Ville Linde Date: Fri, 26 Jul 2013 16:13:05 +0000 Subject: [PATCH] tms32082: Added Parallel Processor + more MP opcodes (nw) --- src/emu/cpu/tms32082/dis32082.c | 38 ++++- src/emu/cpu/tms32082/mp_ops.c | 269 ++++++++++++++++++++++++++++++++ src/emu/cpu/tms32082/tms32082.c | 79 +++++++++- src/emu/cpu/tms32082/tms32082.h | 56 +++++++ 4 files changed, 433 insertions(+), 9 deletions(-) diff --git a/src/emu/cpu/tms32082/dis32082.c b/src/emu/cpu/tms32082/dis32082.c index 9ef481d9f07..d950957b86e 100644 --- a/src/emu/cpu/tms32082/dis32082.c +++ b/src/emu/cpu/tms32082/dis32082.c @@ -2,6 +2,9 @@ #include "emu.h" + +// Master Processor + #define SIMM15(v) (INT32)((v & 0x4000) ? (v | 0xffffe000) : (v)) #define UIMM15(v) (v) @@ -41,6 +44,11 @@ static const char *ACC_SEL[4] = "A0", "A1", "A2", "A3" }; +static const char *FLOATOP_ROUND[4] = +{ + "n", "z", "p", "m" +}; + static char *output; static const UINT8 *opdata; static int opbytes; @@ -171,9 +179,9 @@ static char* format_vector_op(UINT32 op, UINT32 imm32) // align the line end int len = strlen(buffer); - if (len < 29) + if (len < 30) { - for (int i=0; i < (29-len); i++) + for (int i=0; i < (30-len); i++) { b += sprintf(b, " "); } @@ -313,6 +321,8 @@ static offs_t tms32082_disasm_mp(char *buffer, offs_t pc, const UINT8 *oprom) int p2 = (op >> 7) & 3; int pd = (op >> 9) & 3; + int rndmode = (op >> 7) & 3; + switch (subop) { @@ -474,8 +484,8 @@ static offs_t tms32082_disasm_mp(char *buffer, offs_t pc, const UINT8 *oprom) case 0xe5: print("fmpy.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; case 0xe6: print("fdiv.%s%s%s R%d, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], src1, rs, rd); break; case 0xe7: print("fdiv.%s%s%s 0x%08X, R%d, R%d", FLOATOP_PRECISION[p1], FLOATOP_PRECISION[p2], FLOATOP_PRECISION[pd], imm32, rs, rd); break; - case 0xe8: print("frndx R%d, R%d", src1, rd); break; - case 0xe9: print("frndx 0x%08X, R%d", imm32, rd); break; + case 0xe8: print("frnd%s.%s%s R%d, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], src1, rd); break; + case 0xe9: print("frnd%s.%s%s 0x%08X, R%d", FLOATOP_ROUND[rndmode], FLOATOP_PRECISION[p1], FLOATOP_PRECISION[pd], imm32, rd); break; case 0xea: print("fcmp R%d, R%d, R%d", src1, rs, rd); break; case 0xeb: print("fcmp 0x%08X, R%d, R%d", imm32, rs, rd); break; case 0xee: print("fsqrt R%d, R%d", src1, rd); break; @@ -501,3 +511,23 @@ CPU_DISASSEMBLE(tms32082_mp) { return tms32082_disasm_mp(buffer, pc, oprom); } + + + +// Parallel Processor + +static offs_t tms32082_disasm_pp(char *buffer, offs_t pc, const UINT8 *oprom) +{ + output = buffer; + UINT32 flags = 0; + + print("???"); + + return opbytes | flags | DASMFLAG_SUPPORTED; +} + + +CPU_DISASSEMBLE(tms32082_pp) +{ + return tms32082_disasm_pp(buffer, pc, oprom); +} \ No newline at end of file diff --git a/src/emu/cpu/tms32082/mp_ops.c b/src/emu/cpu/tms32082/mp_ops.c index 4a12725953e..0b091502109 100644 --- a/src/emu/cpu/tms32082/mp_ops.c +++ b/src/emu/cpu/tms32082/mp_ops.c @@ -786,6 +786,37 @@ void tms32082_mp_device::execute_reg_long_imm() break; } + case 0x1c: // shift.iz + { + int r = (m_ir & (1 << 10)); + int inv = (m_ir & (1 << 11)); + int rot = m_reg[OP_ROTATE()]; + int end = OP_ENDMASK(); + UINT32 source = m_reg[OP_RS()]; + int rd = OP_RD(); + + UINT32 endmask = end ? SHIFT_MASK[end ? end : 32] : m_reg[OP_ROTATE()+1]; + if (inv) endmask = ~endmask; + + int shift = r ? 32-rot : rot; + UINT32 shiftmask = SHIFT_MASK[shift ? shift : 32]; + UINT32 compmask = endmask & ~shiftmask; + + UINT32 res = 0; + if (r) // right + { + res = ROTATE_R(source, rot) & compmask; + } + else // left + { + res = ROTATE_L(source, rot) & compmask; + } + + if (rd) + m_reg[rd] = res; + break; + } + case 0x22: case 0x23: // and { @@ -898,6 +929,27 @@ void tms32082_mp_device::execute_reg_long_imm() break; } + case 0x4e: + case 0x4f: + case 0x46: + case 0x47: // ld.d + { + int shift = (m_ir & (1 << 11)) ? 3 : 0; + int m = m_ir & (1 << 15); + int base = OP_BASE(); + int rd = OP_RD(); + + UINT32 address = m_reg[base] + ((has_imm ? imm32 : m_reg[OP_SRC1()]) << shift); + UINT64 r = m_program->read_qword(address); + + if (rd) + m_fpair[rd >> 1] = r; + + if (m && base) + m_reg[base] = address; + break; + } + case 0x5a: case 0x5b: case 0x52: @@ -1086,6 +1138,57 @@ void tms32082_mp_device::execute_reg_long_imm() break; } + case 0xc8: + case 0xd8: + case 0xc9: + case 0xd9: // vrnd + { + int acc = OP_ACC(); + int p1 = m_ir & (1 << 5); + int pd = (m_ir >> 7) & 3; + int ls_bit1 = m_ir & (1 << 10); + int ls_bit2 = m_ir & (1 << 6); + int rd = OP_RS(); + int rs1 = OP_SRC1(); + + double source = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1])); + + if (rd) + { + // destination register + switch (pd) + { + case 0: + m_reg[rd] = f2u((float)source); + break; + case 1: + m_fpair[rd >> 1] = d2u(source); + break; + case 2: + m_reg[rd] = (INT32)(source); + break; + case 3: + m_reg[rd] = (UINT32)(source); + break; + } + } + else + { + // destination accumulator + if (pd != 3) + fatalerror("vrnd pd = %d\n", pd); + + m_facc[acc] = source; + } + + // parallel load/store op + if (!(ls_bit1 == 0 && ls_bit2 == 0)) + { + vector_loadstore(); + } + break; + } + case 0xcc: case 0xdc: case 0xcd: @@ -1172,6 +1275,64 @@ void tms32082_mp_device::execute_reg_long_imm() break; } + case 0xe0: + case 0xe1: // fadd + { + int rd = OP_RD(); + int rs = OP_RS(); + int src1 = OP_SRC1(); + int precision = (m_ir >> 5) & 0x3f; + + if (rd) // only calculate if destination register is valid + { + switch (precision) + { + case 0x00: // SP - SP -> SP + { + float s1 = u2f(has_imm ? imm32 : m_reg[src1]); + float s2 = u2f(m_reg[rs]); + m_reg[rd] = f2u(s1 + s2); + break; + } + case 0x10: // SP - SP -> DP + { + float s1 = u2f(has_imm ? imm32 : m_reg[src1]); + float s2 = u2f(m_reg[rs]); + UINT64 res = d2u((double)(s1 + s2)); + m_fpair[rd >> 1] = res; + break; + } + case 0x14: // SP - DP -> DP + { + float s1 = u2f(has_imm ? imm32 : m_reg[src1]); + double s2 = u2d(m_fpair[rs >> 1]); + UINT64 res = d2u((double)(s1 + s2)); + m_fpair[rd >> 1] = res; + break; + } + case 0x11: // DP - SP -> DP + { + double s1 = u2d(m_fpair[src1 >> 1]); + float s2 = u2f(m_reg[rs]); + UINT64 res = d2u((double)(s1 + s2)); + m_fpair[rd >> 1] = res; + break; + } + case 0x15: // DP - DP -> DP + { + double s1 = u2d(m_fpair[src1 >> 1]); + double s2 = u2d(m_fpair[rs >> 1]); + UINT64 res = d2u((double)(s1 + s2)); + m_fpair[rd >> 1] = res; + break; + } + default: + fatalerror("fadd: invalid precision combination %02X\n", precision); + } + } + break; + } + case 0xe2: case 0xe3: // fsub { @@ -1298,6 +1459,114 @@ void tms32082_mp_device::execute_reg_long_imm() break; } + case 0xe6: + case 0xe7: // fdiv + { + int rd = OP_RD(); + int p1 = m_ir & (1 << 5); + int p2 = m_ir & (1 << 7); + int pd = m_ir & (1 << 9); + int rs1 = OP_SRC1(); + int rs2 = OP_RS(); + + if (rd) + { + double src1 = has_imm ? (double)u2f(imm32) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1])); + double src2 = p2 ? u2d(m_fpair[rs2 >> 1]) : (double)u2f(m_reg[rs2]); + + double res = src1 / src2; + + if (pd) + m_fpair[rd >> 1] = d2u(res); + else + m_reg[rd] = f2u((float)res); + } + break; + } + + case 0xe8: + case 0xe9: // frnd + { + //int mode = (m_ir >> 7) & 3; + int p1 = (m_ir >> 5) & 3; + int pd = (m_ir >> 9) & 3; + int src1 = OP_SRC1(); + int rd = OP_RD(); + + double s = 0.0; + + switch (p1) + { + case 0: + s = has_imm ? (double)(u2f(imm32)) : (double)u2f(m_reg[src1]); + break; + case 1: + s = u2d(m_fpair[src1 >> 1]); + break; + case 2: + s = has_imm ? (double)((INT32)(imm32)) : (double)(INT32)(m_reg[src1]); + break; + case 3: + s = has_imm ? (double)((UINT32)(imm32)) : (double)(UINT32)(m_reg[src1]); + break; + } + + // TODO: round + + if (rd) + { + switch (pd) + { + case 0: + m_reg[rd] = f2u((float)(s)); + break; + case 1: + m_fpair[rd] = d2u(s); + break; + case 2: + m_reg[rd] = (INT32)(s); + break; + case 3: + m_reg[rd] = (UINT32)(s); + break; + } + } + break; + } + + case 0xea: + case 0xeb: // fcmp + { + int rd = OP_RD(); + int p1 = m_ir & (1 << 5); + int p2 = m_ir & (1 << 7); + int rs1 = OP_SRC1(); + int rs2 = OP_RS(); + + double src1 = has_imm ? (double)(u2f(imm32)) : (p1 ? u2d(m_fpair[rs1 >> 1]) : (double)u2f(m_reg[rs1])); + double src2 = p2 ? u2d(m_fpair[rs2 >> 1]) : (double)u2f(m_reg[rs2]); + + if (rd) + { + UINT32 flags = 0; + flags |= (src1 == src2) ? (1 << 20) : 0; + flags |= (src1 != src2) ? (1 << 21) : 0; + flags |= (src1 > src2) ? (1 << 22) : 0; + flags |= (src1 <= src2) ? (1 << 23) : 0; + flags |= (src1 < src2) ? (1 << 24) : 0; + flags |= (src1 >= src2) ? (1 << 25) : 0; + flags |= (src1 < 0 || src1 > src2) ? (1 << 26) : 0; + flags |= (src1 > 0 && src1 < src2) ? (1 << 27) : 0; + flags |= (src1 >= 0 && src1 <= src2) ? (1 << 28) : 0; + flags |= (src1 <= 0 || src1 >= src2) ? (1 << 29) : 0; + // TODO: src1 or src2 unordered + // TODO: src1 and src2 ordered + + m_reg[rd] = flags; + } + break; + } + case 0xee: case 0xef: // fsqrt { diff --git a/src/emu/cpu/tms32082/tms32082.c b/src/emu/cpu/tms32082/tms32082.c index 0a76b055db1..51e77d080f1 100644 --- a/src/emu/cpu/tms32082/tms32082.c +++ b/src/emu/cpu/tms32082/tms32082.c @@ -10,16 +10,21 @@ #include "tms32082.h" extern CPU_DISASSEMBLE(tms32082_mp); +extern CPU_DISASSEMBLE(tms32082_pp); const device_type TMS32082_MP = &device_creator; +const device_type TMS32082_PP = &device_creator; + + + + +// Master Processor // internal memory map -static ADDRESS_MAP_START(internal_map, AS_PROGRAM, 32, tms32082_mp_device) +static ADDRESS_MAP_START(mp_internal_map, AS_PROGRAM, 32, tms32082_mp_device) AM_RANGE(0x01010000, 0x010107ff) AM_READWRITE(mp_param_r, mp_param_w) ADDRESS_MAP_END - - const UINT32 tms32082_mp_device::SHIFT_MASK[] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, @@ -31,10 +36,9 @@ const UINT32 tms32082_mp_device::SHIFT_MASK[] = - tms32082_mp_device::tms32082_mp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : cpu_device(mconfig, TMS32082_MP, "TMS32082 MP", tag, owner, clock, "tms32082_mp", __FILE__) - , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(internal_map)) + , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(mp_internal_map)) { } @@ -289,3 +293,68 @@ void tms32082_mp_device::execute_run() return; } + + + + +// Parallel Processor + +// internal memory map +static ADDRESS_MAP_START(pp_internal_map, AS_PROGRAM, 32, tms32082_mp_device) +ADDRESS_MAP_END + +tms32082_pp_device::tms32082_pp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : cpu_device(mconfig, TMS32082_PP, "TMS32082 PP", tag, owner, clock, "tms32082_pp", __FILE__) + , m_program_config("program", ENDIANNESS_BIG, 32, 32, 0, ADDRESS_MAP_NAME(pp_internal_map)) +{ +} + + +offs_t tms32082_pp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + return CPU_DISASSEMBLE_NAME(tms32082_pp)(this, buffer, pc, oprom, opram, options); +} + +void tms32082_pp_device::device_start() +{ + m_program = &space(AS_PROGRAM); + + save_item(NAME(m_pc)); + save_item(NAME(m_fetchpc)); + + // Register state for debugger + state_add(PP_PC, "pc", m_pc).formatstr("%08X"); + + state_add(STATE_GENPC, "curpc", m_pc).noshow(); + + m_program = &space(AS_PROGRAM); + m_direct = &m_program->direct(); + + m_icountptr = &m_icount; +} + +void tms32082_pp_device::state_string_export(const device_state_entry &entry, astring &string) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + string.printf("?"); + break; + } +} + +void tms32082_pp_device::device_reset() +{ + m_pc = 0; + m_fetchpc = 0; +} + +void tms32082_pp_device::execute_run() +{ + m_pc = m_fetchpc; + debugger_instruction_hook(this, m_pc); + + m_icount = 0; + + return; +} \ No newline at end of file diff --git a/src/emu/cpu/tms32082/tms32082.h b/src/emu/cpu/tms32082/tms32082.h index d8f709d5e84..b91d7822c22 100644 --- a/src/emu/cpu/tms32082/tms32082.h +++ b/src/emu/cpu/tms32082/tms32082.h @@ -3,6 +3,7 @@ #ifndef __TMS32082_H__ #define __TMS32082_H__ +// Master Processor class class tms32082_mp_device : public cpu_device { public: @@ -128,7 +129,62 @@ protected: void vector_loadstore(); }; + +// Parallel Processor class +class tms32082_pp_device : public cpu_device +{ +public: + // construction/destruction + tms32082_pp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + enum + { + PP_PC = 1, + }; + +protected: + // device level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 1; } + virtual UINT32 execute_max_cycles() const { return 1; } + virtual UINT32 execute_input_lines() const { return 0; } + virtual void execute_run(); + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const + { + switch (spacenum) + { + case AS_PROGRAM: return &m_program_config; + default: return NULL; + } + } + + // device_state_interface overrides + void state_string_export(const device_state_entry &entry, astring &string); + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 8; } + virtual UINT32 disasm_max_opcode_bytes() const { return 8; } + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + + address_space_config m_program_config; + + UINT32 m_pc; + UINT32 m_fetchpc; + + int m_icount; + + address_space *m_program; + direct_read_data* m_direct; +}; + + extern const device_type TMS32082_MP; +extern const device_type TMS32082_PP; #endif /* __TMS32082_H__ */