mirror of
https://github.com/holub/mame
synced 2025-04-22 00:11:58 +03:00
tms32082: Added Parallel Processor + more MP opcodes (nw)
This commit is contained in:
parent
551ab3c613
commit
52d4a43e1b
@ -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);
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
@ -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__ */
|
||||
|
Loading…
Reference in New Issue
Block a user