tms32082: Added Parallel Processor + more MP opcodes (nw)

This commit is contained in:
Ville Linde 2013-07-26 16:13:05 +00:00
parent 551ab3c613
commit 52d4a43e1b
4 changed files with 433 additions and 9 deletions

View File

@ -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);
}

View File

@ -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
{

View File

@ -10,16 +10,21 @@
#include "tms32082.h"
extern CPU_DISASSEMBLE(tms32082_mp);
extern CPU_DISASSEMBLE(tms32082_pp);
const device_type TMS32082_MP = &device_creator<tms32082_mp_device>;
const device_type TMS32082_PP = &device_creator<tms32082_pp_device>;
// 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;
}

View File

@ -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__ */