ps2sony: Checkpoint, nw

This commit is contained in:
mooglyguy 2018-07-17 18:14:12 +02:00
parent b33867d92a
commit 5db11a5e02
18 changed files with 2816 additions and 227 deletions

View File

@ -1263,12 +1263,16 @@ if (CPUS["MIPS"]~=null) then
MAME_DIR .. "src/devices/cpu/mips/mips3fe.cpp",
MAME_DIR .. "src/devices/cpu/mips/mips3fe.h",
MAME_DIR .. "src/devices/cpu/mips/mips3drc.cpp",
MAME_DIR .. "src/devices/cpu/mips/sonyvu.cpp",
MAME_DIR .. "src/devices/cpu/mips/sonyvu.h",
}
end
if (CPUS["MIPS"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/mips3dsm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/mips3dsm.h")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/vudasm.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/mips/vudasm.h")
end
--------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ MIPS III/IV emulator.
#include "divtlb.h"
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "sonyvu.h"
// NEC VR4300 series is MIPS III with 32-bit address bus and slightly custom COP0/TLB
@ -366,7 +367,7 @@ protected:
float acc;
/* VU0 registers (R5900 only) */
float vfr[32][4]; // 0..3 = w..x
float vfr[32][4]; // 0..3 = x..w
uint32_t vcr[32];
float vumem[0x1000];
float* vfmem;
@ -629,6 +630,7 @@ private:
void log_register_list(const char *string, const uint32_t *reglist, const uint32_t *regnostarlist);
void log_opcode_desc(const opcode_desc *desclist, int indent);
void load_elf();
};
@ -778,8 +780,17 @@ public:
class r5900le_device : public mips3_device {
public:
// construction/destruction
template <typename T>
r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&vu0_tag)
: r5900le_device(mconfig, tag, owner, clock)
{
m_vu0.set_tag(std::forward<T>(vu0_tag));
}
r5900le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE, 64) {
: mips3_device(mconfig, R5900LE, tag, owner, clock, MIPS3_TYPE_R5900, ENDIANNESS_LITTLE, 64)
, m_vu0(*this, finder_base::DUMMY_TAG)
{
}
protected:
@ -824,6 +835,8 @@ protected:
void handle_sdc2(uint32_t op) override;
void handle_dmfc2(uint32_t op) override;
void handle_dmtc2(uint32_t op) override;
required_device<sonyvu0_device> m_vu0;
};
class qed5271be_device : public mips3_device {

View File

@ -326,7 +326,7 @@ uint32_t mips3_device::compute_prid_register()
return 0x2700;
case MIPS3_TYPE_R5900:
return 0x2e59;
return 0x2e14;
default:
fatalerror("Unknown MIPS flavor specified\n");

View File

@ -14,7 +14,8 @@
#include "debugger.h"
#define ENABLE_OVERFLOWS 0
#define ENABLE_OVERFLOWS (0)
#define ENABLE_IOP_KPUTS (0)
/***************************************************************************
@ -1075,7 +1076,8 @@ void r3000_device::execute_run()
// debugging
m_ppc = m_pc;
debugger_instruction_hook(m_pc);
/*
#if ENABLE_IOP_KPUTS
if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C)
{
uint32_t ptr = m_r[5];
@ -1090,7 +1092,8 @@ void r3000_device::execute_run()
}
fflush(stdout);
}
*/
#endif
// instruction fetch
m_op = readop(m_pc);

View File

@ -0,0 +1,878 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Vector Unit device skeleton
*
* To Do:
* Everything
*
*/
#include "emu.h"
#include "sonyvu.h"
#include "vudasm.h"
#include "debugger.h"
DEFINE_DEVICE_TYPE(SONYVU0, sonyvu0_device, "sonyvu0", "Sony PlayStation 2 VU0")
DEFINE_DEVICE_TYPE(SONYVU1, sonyvu1_device, "sonyvu1", "Sony PlayStation 2 VU1")
sonyvu_device::sonyvu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
address_map_constructor micro_cons, address_map_constructor vu_cons, chip_type chiptype, uint32_t mem_size)
: cpu_device(mconfig, type, tag, owner, clock)
, m_micro_config("micro", ENDIANNESS_LITTLE, 64, 12, 0, micro_cons)
, m_vu_config("vu", ENDIANNESS_LITTLE, 32, 12, 0, vu_cons)
, m_micro_space(nullptr)
, m_vu_space(nullptr)
, m_mem_size(mem_size)
, m_mem_mask(mem_size-1)
, m_micro_mem(*this, "micro")
, m_vu_mem(*this, "vu")
, m_vfmem(nullptr)
, m_vimem(nullptr)
, m_v(nullptr)
, m_status_flag(0)
, m_mac_flag(0)
, m_clip_flag(0)
, m_r(0)
, m_i(0.0f)
, m_q(0.0f)
, m_pc(0)
, m_running(false)
, m_icount(0)
{
}
sonyvu0_device::sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sonyvu_device(mconfig, SONYVU0, tag, owner, clock, address_map_constructor(FUNC(sonyvu0_device::micro_map), this), address_map_constructor(FUNC(sonyvu0_device::vu_map), this), CHIP_TYPE_VU0, 0x1000)
, m_vu1(*this, finder_base::DUMMY_TAG)
{
}
sonyvu1_device::sonyvu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: sonyvu_device(mconfig, SONYVU1, tag, owner, clock, address_map_constructor(FUNC(sonyvu1_device::micro_map), this), address_map_constructor(FUNC(sonyvu1_device::vu_map), this), CHIP_TYPE_VU0, 0x4000)
{
}
void sonyvu_device::device_start()
{
// set our instruction counter
set_icountptr(m_icount);
m_micro_space = &space(AS_PROGRAM);
m_vu_space = &space(AS_DATA);
/* register for save states */
for (int i = 0; i < 32; i++)
{
save_item(NAME(m_vfr[i][0]), i);
save_item(NAME(m_vfr[i][1]), i);
save_item(NAME(m_vfr[i][2]), i);
save_item(NAME(m_vfr[i][3]), i);
}
save_item(NAME(m_vcr));
save_item(NAME(m_acc));
save_item(NAME(m_running));
save_item(NAME(m_icount));
save_item(NAME(m_status_flag));
save_item(NAME(m_mac_flag));
save_item(NAME(m_clip_flag));
save_item(NAME(m_r));
save_item(NAME(m_i));
save_item(NAME(m_q));
save_item(NAME(m_pc));
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
state_add(SONYVU_TPC, "TPC", m_pc);
state_add(SONYVU_SF, "SF", m_status_flag);
state_add(SONYVU_MF, "MF", m_mac_flag);
state_add(SONYVU_CF, "CF", m_clip_flag);
state_add(SONYVU_R, "R", m_r);
state_add(SONYVU_I, "I", *(uint32_t*)&m_i).formatstr("%17s");
state_add(SONYVU_Q, "Q", *(uint32_t*)&m_q).formatstr("%17s");
char elements[4] = { 'x', 'y', 'z', 'w' };
char regname[6];
for (int i = 0; i < 4; i++)
{
snprintf(regname, 6, "ACC%c", elements[i]);
state_add(SONYVU_ACCx + i, regname, *(uint32_t*)&m_acc[i]).formatstr("%17s");
}
for (int i = 0; i < 32; i++)
{
for (int j = 0; j < 4; j++)
{
snprintf(regname, 6, "VF%02d%c", i, elements[j]);
state_add(SONYVU_VF00x + i*4 + j, regname, *(uint32_t*)&m_vfr[i][j]).formatstr("%17s");
}
}
for (int i = 0; i < 16; i++)
{
snprintf(regname, 6, "VI%02d", i);
state_add(SONYVU_VI00 + i, regname, m_vcr[i]);
}
}
void sonyvu_device::device_reset()
{
m_vfmem = reinterpret_cast<float*>(&m_vu_mem[0]);
m_vimem = &m_vu_mem[0];
// clear some additional state
memset(m_vfr, 0, sizeof(float) * 32 * 4);
memset(m_vcr, 0, sizeof(float) * 32);
memset(m_acc, 0, sizeof(float) * 4);
m_v = reinterpret_cast<float*>(m_vfr);
m_status_flag = 0;
m_mac_flag = 0;
m_clip_flag = 0;
m_r = 0;
m_i = 0.0f;
m_q = 0.0f;
m_pc = 0;
m_v[3] = 1.0f;
m_running = false;
}
device_memory_interface::space_config_vector sonyvu_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_micro_config),
std::make_pair(AS_DATA, &m_vu_config)
};
}
void sonyvu_device::state_import(const device_state_entry &entry)
{
switch (entry.index())
{
case STATE_GENFLAGS:
break;
default:
fatalerror("sonyvu_device::state_import called for unexpected value\n");
}
}
void sonyvu_device::state_export(const device_state_entry &entry)
{
switch (entry.index())
{
case STATE_GENFLAGS:
break;
default:
fatalerror("sonyvu_device::state_export called for unexpected value\n");
}
}
void sonyvu_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case SONYVU_I: str = string_format("!%16g", m_i); break;
case SONYVU_Q: str = string_format("!%16g", m_q); break;
case SONYVU_ACCx: str = string_format("!%16g", m_acc[0]); break;
case SONYVU_ACCy: str = string_format("!%16g", m_acc[1]); break;
case SONYVU_ACCz: str = string_format("!%16g", m_acc[2]); break;
case SONYVU_ACCw: str = string_format("!%16g", m_acc[3]); break;
case SONYVU_VF00x: str = string_format("!%16g", m_vfr[0][0]); break;
case SONYVU_VF00y: str = string_format("!%16g", m_vfr[0][1]); break;
case SONYVU_VF00z: str = string_format("!%16g", m_vfr[0][2]); break;
case SONYVU_VF00w: str = string_format("!%16g", m_vfr[0][3]); break;
case SONYVU_VF01x: str = string_format("!%16g", m_vfr[1][0]); break;
case SONYVU_VF01y: str = string_format("!%16g", m_vfr[1][1]); break;
case SONYVU_VF01z: str = string_format("!%16g", m_vfr[1][2]); break;
case SONYVU_VF01w: str = string_format("!%16g", m_vfr[1][3]); break;
case SONYVU_VF02x: str = string_format("!%16g", m_vfr[2][0]); break;
case SONYVU_VF02y: str = string_format("!%16g", m_vfr[2][1]); break;
case SONYVU_VF02z: str = string_format("!%16g", m_vfr[2][2]); break;
case SONYVU_VF02w: str = string_format("!%16g", m_vfr[2][3]); break;
case SONYVU_VF03x: str = string_format("!%16g", m_vfr[3][0]); break;
case SONYVU_VF03y: str = string_format("!%16g", m_vfr[3][1]); break;
case SONYVU_VF03z: str = string_format("!%16g", m_vfr[3][2]); break;
case SONYVU_VF03w: str = string_format("!%16g", m_vfr[3][3]); break;
case SONYVU_VF04x: str = string_format("!%16g", m_vfr[4][0]); break;
case SONYVU_VF04y: str = string_format("!%16g", m_vfr[4][1]); break;
case SONYVU_VF04z: str = string_format("!%16g", m_vfr[4][2]); break;
case SONYVU_VF04w: str = string_format("!%16g", m_vfr[4][3]); break;
case SONYVU_VF05x: str = string_format("!%16g", m_vfr[5][0]); break;
case SONYVU_VF05y: str = string_format("!%16g", m_vfr[5][1]); break;
case SONYVU_VF05z: str = string_format("!%16g", m_vfr[5][2]); break;
case SONYVU_VF05w: str = string_format("!%16g", m_vfr[5][3]); break;
case SONYVU_VF06x: str = string_format("!%16g", m_vfr[6][0]); break;
case SONYVU_VF06y: str = string_format("!%16g", m_vfr[6][1]); break;
case SONYVU_VF06z: str = string_format("!%16g", m_vfr[6][2]); break;
case SONYVU_VF06w: str = string_format("!%16g", m_vfr[6][3]); break;
case SONYVU_VF07x: str = string_format("!%16g", m_vfr[7][0]); break;
case SONYVU_VF07y: str = string_format("!%16g", m_vfr[7][1]); break;
case SONYVU_VF07z: str = string_format("!%16g", m_vfr[7][2]); break;
case SONYVU_VF07w: str = string_format("!%16g", m_vfr[7][3]); break;
case SONYVU_VF08x: str = string_format("!%16g", m_vfr[8][0]); break;
case SONYVU_VF08y: str = string_format("!%16g", m_vfr[8][1]); break;
case SONYVU_VF08z: str = string_format("!%16g", m_vfr[8][2]); break;
case SONYVU_VF08w: str = string_format("!%16g", m_vfr[8][3]); break;
case SONYVU_VF09x: str = string_format("!%16g", m_vfr[9][0]); break;
case SONYVU_VF09y: str = string_format("!%16g", m_vfr[9][1]); break;
case SONYVU_VF09z: str = string_format("!%16g", m_vfr[9][2]); break;
case SONYVU_VF09w: str = string_format("!%16g", m_vfr[9][3]); break;
case SONYVU_VF10x: str = string_format("!%16g", m_vfr[10][0]); break;
case SONYVU_VF10y: str = string_format("!%16g", m_vfr[10][1]); break;
case SONYVU_VF10z: str = string_format("!%16g", m_vfr[10][2]); break;
case SONYVU_VF10w: str = string_format("!%16g", m_vfr[10][3]); break;
case SONYVU_VF11x: str = string_format("!%16g", m_vfr[11][0]); break;
case SONYVU_VF11y: str = string_format("!%16g", m_vfr[11][1]); break;
case SONYVU_VF11z: str = string_format("!%16g", m_vfr[11][2]); break;
case SONYVU_VF11w: str = string_format("!%16g", m_vfr[11][3]); break;
case SONYVU_VF12x: str = string_format("!%16g", m_vfr[12][0]); break;
case SONYVU_VF12y: str = string_format("!%16g", m_vfr[12][1]); break;
case SONYVU_VF12z: str = string_format("!%16g", m_vfr[12][2]); break;
case SONYVU_VF12w: str = string_format("!%16g", m_vfr[12][3]); break;
case SONYVU_VF13x: str = string_format("!%16g", m_vfr[13][0]); break;
case SONYVU_VF13y: str = string_format("!%16g", m_vfr[13][1]); break;
case SONYVU_VF13z: str = string_format("!%16g", m_vfr[13][2]); break;
case SONYVU_VF13w: str = string_format("!%16g", m_vfr[13][3]); break;
case SONYVU_VF14x: str = string_format("!%16g", m_vfr[14][0]); break;
case SONYVU_VF14y: str = string_format("!%16g", m_vfr[14][1]); break;
case SONYVU_VF14z: str = string_format("!%16g", m_vfr[14][2]); break;
case SONYVU_VF14w: str = string_format("!%16g", m_vfr[14][3]); break;
case SONYVU_VF15x: str = string_format("!%16g", m_vfr[15][0]); break;
case SONYVU_VF15y: str = string_format("!%16g", m_vfr[15][1]); break;
case SONYVU_VF15z: str = string_format("!%16g", m_vfr[15][2]); break;
case SONYVU_VF15w: str = string_format("!%16g", m_vfr[15][3]); break;
case SONYVU_VF16x: str = string_format("!%16g", m_vfr[16][0]); break;
case SONYVU_VF16y: str = string_format("!%16g", m_vfr[16][1]); break;
case SONYVU_VF16z: str = string_format("!%16g", m_vfr[16][2]); break;
case SONYVU_VF16w: str = string_format("!%16g", m_vfr[16][3]); break;
case SONYVU_VF17x: str = string_format("!%16g", m_vfr[17][0]); break;
case SONYVU_VF17y: str = string_format("!%16g", m_vfr[17][1]); break;
case SONYVU_VF17z: str = string_format("!%16g", m_vfr[17][2]); break;
case SONYVU_VF17w: str = string_format("!%16g", m_vfr[17][3]); break;
case SONYVU_VF18x: str = string_format("!%16g", m_vfr[18][0]); break;
case SONYVU_VF18y: str = string_format("!%16g", m_vfr[18][1]); break;
case SONYVU_VF18z: str = string_format("!%16g", m_vfr[18][2]); break;
case SONYVU_VF18w: str = string_format("!%16g", m_vfr[18][3]); break;
case SONYVU_VF19x: str = string_format("!%16g", m_vfr[19][0]); break;
case SONYVU_VF19y: str = string_format("!%16g", m_vfr[19][1]); break;
case SONYVU_VF19z: str = string_format("!%16g", m_vfr[19][2]); break;
case SONYVU_VF19w: str = string_format("!%16g", m_vfr[19][3]); break;
case SONYVU_VF20x: str = string_format("!%16g", m_vfr[20][0]); break;
case SONYVU_VF20y: str = string_format("!%16g", m_vfr[20][1]); break;
case SONYVU_VF20z: str = string_format("!%16g", m_vfr[20][2]); break;
case SONYVU_VF20w: str = string_format("!%16g", m_vfr[20][3]); break;
case SONYVU_VF21x: str = string_format("!%16g", m_vfr[21][0]); break;
case SONYVU_VF21y: str = string_format("!%16g", m_vfr[21][1]); break;
case SONYVU_VF21z: str = string_format("!%16g", m_vfr[21][2]); break;
case SONYVU_VF21w: str = string_format("!%16g", m_vfr[21][3]); break;
case SONYVU_VF22x: str = string_format("!%16g", m_vfr[22][0]); break;
case SONYVU_VF22y: str = string_format("!%16g", m_vfr[22][1]); break;
case SONYVU_VF22z: str = string_format("!%16g", m_vfr[22][2]); break;
case SONYVU_VF22w: str = string_format("!%16g", m_vfr[22][3]); break;
case SONYVU_VF23x: str = string_format("!%16g", m_vfr[23][0]); break;
case SONYVU_VF23y: str = string_format("!%16g", m_vfr[23][1]); break;
case SONYVU_VF23z: str = string_format("!%16g", m_vfr[23][2]); break;
case SONYVU_VF23w: str = string_format("!%16g", m_vfr[23][3]); break;
case SONYVU_VF24x: str = string_format("!%16g", m_vfr[24][0]); break;
case SONYVU_VF24y: str = string_format("!%16g", m_vfr[24][1]); break;
case SONYVU_VF24z: str = string_format("!%16g", m_vfr[24][2]); break;
case SONYVU_VF24w: str = string_format("!%16g", m_vfr[24][3]); break;
case SONYVU_VF25x: str = string_format("!%16g", m_vfr[25][0]); break;
case SONYVU_VF25y: str = string_format("!%16g", m_vfr[25][1]); break;
case SONYVU_VF25z: str = string_format("!%16g", m_vfr[25][2]); break;
case SONYVU_VF25w: str = string_format("!%16g", m_vfr[25][3]); break;
case SONYVU_VF26x: str = string_format("!%16g", m_vfr[26][0]); break;
case SONYVU_VF26y: str = string_format("!%16g", m_vfr[26][1]); break;
case SONYVU_VF26z: str = string_format("!%16g", m_vfr[26][2]); break;
case SONYVU_VF26w: str = string_format("!%16g", m_vfr[26][3]); break;
case SONYVU_VF27x: str = string_format("!%16g", m_vfr[27][0]); break;
case SONYVU_VF27y: str = string_format("!%16g", m_vfr[27][1]); break;
case SONYVU_VF27z: str = string_format("!%16g", m_vfr[27][2]); break;
case SONYVU_VF27w: str = string_format("!%16g", m_vfr[27][3]); break;
case SONYVU_VF28x: str = string_format("!%16g", m_vfr[28][0]); break;
case SONYVU_VF28y: str = string_format("!%16g", m_vfr[28][1]); break;
case SONYVU_VF28z: str = string_format("!%16g", m_vfr[28][2]); break;
case SONYVU_VF28w: str = string_format("!%16g", m_vfr[28][3]); break;
case SONYVU_VF29x: str = string_format("!%16g", m_vfr[29][0]); break;
case SONYVU_VF29y: str = string_format("!%16g", m_vfr[29][1]); break;
case SONYVU_VF29z: str = string_format("!%16g", m_vfr[29][2]); break;
case SONYVU_VF29w: str = string_format("!%16g", m_vfr[29][3]); break;
case SONYVU_VF30x: str = string_format("!%16g", m_vfr[30][0]); break;
case SONYVU_VF30y: str = string_format("!%16g", m_vfr[30][1]); break;
case SONYVU_VF30z: str = string_format("!%16g", m_vfr[30][2]); break;
case SONYVU_VF30w: str = string_format("!%16g", m_vfr[30][3]); break;
case SONYVU_VF31x: str = string_format("!%16g", m_vfr[31][0]); break;
case SONYVU_VF31y: str = string_format("!%16g", m_vfr[31][1]); break;
case SONYVU_VF31z: str = string_format("!%16g", m_vfr[31][2]); break;
case SONYVU_VF31w: str = string_format("!%16g", m_vfr[31][3]); break;
}
}
std::unique_ptr<util::disasm_interface> sonyvu_device::create_disassembler()
{
return std::make_unique<sonyvu_disassembler>();
}
void sonyvu_device::execute_run()
{
while (m_icount > 0)
{
if (!m_running)
{
m_icount = 0;
return;
}
debugger_instruction_hook(m_pc);
const uint64_t op = m_micro_mem[(m_pc & m_mem_mask) >> 3];
execute_upper((uint32_t)(op >> 32));
if (op & OP_UPPER_I)
{
uint32_t lower_op = (uint32_t)op;
m_i = *reinterpret_cast<float*>(&lower_op);
}
else
{
execute_lower((uint32_t)op);
}
m_pc += 8;
m_icount--;
}
}
void sonyvu_device::execute_upper(const uint32_t op)
{
switch (op & 0x3f)
{
case 0x00: case 0x01: case 0x02: case 0x03: // ADDbc
printf("Unsupported VU instruction: ADDbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x04: case 0x05: case 0x06: case 0x07: // SUBbc
printf("Unsupported VU instruction: SUBbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: // MADDbc
printf("Unsupported VU instruction: MADDbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f: // MSUBbc
printf("Unsupported VU instruction: MSUBbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x10: case 0x11: case 0x12: case 0x13: // MAXbc
printf("Unsupported VU instruction: MAXbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x14: case 0x15: case 0x16: case 0x17: // MINIbc
printf("Unsupported VU instruction: MINIbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: // MULbc
printf("Unsupported VU instruction: MULbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1c: // MULq
printf("Unsupported VU instruction: MULq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1d: // MAXi
printf("Unsupported VU instruction: MAXi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1e: // MULi
printf("Unsupported VU instruction: MULi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1f: // MINIi
printf("Unsupported VU instruction: MINIi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x20: // ADDq
printf("Unsupported VU instruction: ADDq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x21: // MADDq
printf("Unsupported VU instruction: MADDq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x22: // ADDi
printf("Unsupported VU instruction: ADDi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x23: // MADDi
printf("Unsupported VU instruction: MADDi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x24: // SUBq
printf("Unsupported VU instruction: SUBq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x25: // MSUBq
printf("Unsupported VU instruction: MSUBq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x26: // SUBi
printf("Unsupported VU instruction: SUBi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x27: // MSUBi
printf("Unsupported VU instruction: MSUBi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x28: // ADD
printf("Unsupported VU instruction: ADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x29: // MADD
printf("Unsupported VU instruction: MADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2a: // MUL
printf("Unsupported VU instruction: MUL\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2b: // MAX
printf("Unsupported VU instruction: MAX\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2c: // SUB
printf("Unsupported VU instruction: SUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2d: // MSUB
printf("Unsupported VU instruction: MSUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2e: // OPMSUB
printf("Unsupported VU instruction: OPMSUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2f: // MINI
printf("Unsupported VU instruction: MINI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
{
const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3);
switch (type2_op)
{
case 0x00: case 0x01: case 0x02: case 0x03: // ADDAbc
printf("Unsupported VU instruction: ADDAb\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x04: case 0x05: case 0x06: case 0x07: // SUBAbc
printf("Unsupported VU instruction: SUBAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: // MADDAbc
printf("Unsupported VU instruction: MADDAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f: // MSUBAbc
printf("Unsupported VU instruction: MSUBAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: // MULAbc
printf("Unsupported VU instruction: MULAbc\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x10: // ITOF0
printf("Unsupported VU instruction: ITOF0\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x11: // ITOF4
printf("Unsupported VU instruction: ITOF4\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x12: // ITOF12
printf("Unsupported VU instruction: ITOF12\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x13: // ITOF15
printf("Unsupported VU instruction: ITOF15\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x14: // FTOI0
printf("Unsupported VU instruction: FTOI0\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x15: // FTOI4
printf("Unsupported VU instruction: FTOI4\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x16: // FTOI12
printf("Unsupported VU instruction: FTOI12\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x17: // FTOI15
printf("Unsupported VU instruction: FTOI15\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1c: // MULAq
printf("Unsupported VU instruction: MULAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1d: // ABS
printf("Unsupported VU instruction: ABS\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1e: // MULAi
printf("Unsupported VU instruction: MULAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1f: // CLIP
printf("Unsupported VU instruction: CLIP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x20: // ADDAq
printf("Unsupported VU instruction: ADDAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x21: // MADDAq
printf("Unsupported VU instruction: MADDAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x22: // ADDAi
printf("Unsupported VU instruction: ADDAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x23: // MADDAi
printf("Unsupported VU instruction: MADDAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x24: // SUBAq
printf("Unsupported VU instruction: SUBAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x25: // MSUBAq
printf("Unsupported VU instruction: MSUBAq\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x26: // SUBAi
printf("Unsupported VU instruction: SUBAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x27: // MSUBAi
printf("Unsupported VU instruction: MSUBAi\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x28: // ADDA
printf("Unsupported VU instruction: ADDA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x29: // MADDA
printf("Unsupported VU instruction: MADDA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2a: // MULA
printf("Unsupported VU instruction: MULA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2c: // SUBA
printf("Unsupported VU instruction: SUBA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2d: // MSUBA
printf("Unsupported VU instruction: MSUBA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2e: // OPMULA
printf("Unsupported VU instruction: OPMULA\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2f: // NOP
break;
default:
logerror("%s: %08x: Unknown upper opcode %08x\n", machine().describe_context(), m_pc, op);
break;
}
break;
}
default:
logerror("%s: %08x: Unknown upper opcode %08x\n", machine().describe_context(), m_pc, op);
break;
}
}
void sonyvu_device::execute_lower(const uint32_t op)
{
switch ((op >> 25) & 0x7f)
{
case 0x00: // LQ
printf("Unsupported VU instruction: LQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x01: // SQ
printf("Unsupported VU instruction: SQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x04: // ILW
printf("Unsupported VU instruction: ILW\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x05: // ISW
printf("Unsupported VU instruction: ISW\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x08: // IADDIU
printf("Unsupported VU instruction: IADDIU\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x09: // ISUBIU
printf("Unsupported VU instruction: ISUBIU\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x10: // FCEQ
printf("Unsupported VU instruction: FCEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x11: // FCSET
printf("Unsupported VU instruction: FCSET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x12: // FCAND
printf("Unsupported VU instruction: FCAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x13: // FCOR
printf("Unsupported VU instruction: FCOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x14: // FSEQ
printf("Unsupported VU instruction: FSEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x15: // FSSET
printf("Unsupported VU instruction: FSSET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x16: // FSAND
printf("Unsupported VU instruction: FSAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x17: // FSOR
printf("Unsupported VU instruction: FSOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x18: // FMEQ
printf("Unsupported VU instruction: FMEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1a: // FMAND
printf("Unsupported VU instruction: FMAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1b: // FMOR
printf("Unsupported VU instruction: FMOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x1c: // FCGET
printf("Unsupported VU instruction: FCGET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x20: // B
printf("Unsupported VU instruction: B\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x21: // BAL
printf("Unsupported VU instruction: BAL\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x24: // JR
printf("Unsupported VU instruction: JR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x25: // JALR
printf("Unsupported VU instruction: JALR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x28: // IBEQ
printf("Unsupported VU instruction: IBEQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x29: // IBNE
printf("Unsupported VU instruction: IBNE\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2c: // IBLTZ
printf("Unsupported VU instruction: IBLTZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2d: // IBGTZ
printf("Unsupported VU instruction: IBGTZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2e: // IBLEZ
printf("Unsupported VU instruction: IBLEZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x2f: // IBGEZ
printf("Unsupported VU instruction: IBGEZ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x40: // SPECIAL
{
if ((op & 0x3c) == 0x3c)
{
uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3);
switch (type4_op)
{
case 0x30: // MOVE
printf("Unsupported VU instruction: MOVE\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x31: // MR32
printf("Unsupported VU instruction: MR32\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x34: // LQI
printf("Unsupported VU instruction: LQI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x35: // SQI
printf("Unsupported VU instruction: SQI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x36: // LQD
printf("Unsupported VU instruction: LQD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x37: // SQD
printf("Unsupported VU instruction: SQD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x38: // DIV
printf("Unsupported VU instruction: DIV\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x39: // SQRT
printf("Unsupported VU instruction: SQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3a: // RSQRT
printf("Unsupported VU instruction: RSQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3b: // WAITQ
printf("Unsupported VU instruction: WAITQ\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3c: // MTIR
printf("Unsupported VU instruction: MTIR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3d: // MFIR
printf("Unsupported VU instruction: MFIR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3e: // ILWR
printf("Unsupported VU instruction: ILWR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x3f: // ISWR
printf("Unsupported VU instruction: ISWR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x40: // RNEXT
printf("Unsupported VU instruction: RNEXT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x41: // RGET
printf("Unsupported VU instruction: RGET\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x42: // RINIT
printf("Unsupported VU instruction: RINIT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x43: // RXOR
printf("Unsupported VU instruction: RXOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x64: // MFP
printf("Unsupported VU instruction: MFP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x68: // XTOP
printf("Unsupported VU instruction: XTOP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x69: // XITOP
printf("Unsupported VU instruction: XITOP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x6c: // XGKICK
printf("Unsupported VU instruction: XGKICK\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x70: // ESADD
printf("Unsupported VU instruction: ESADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x71: // ERSADD
printf("Unsupported VU instruction: ERSADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x72: // ELENG
printf("Unsupported VU instruction: ELENG\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x73: // ERLENG
printf("Unsupported VU instruction: ERLENG\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x74: // EATANxy
printf("Unsupported VU instruction: EATANxy\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x75: // EATANxz
printf("Unsupported VU instruction: EATANxz\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x76: // ESUM
printf("Unsupported VU instruction: ESUM\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x78: // ESQRT
printf("Unsupported VU instruction: ESQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x79: // ERSQRT
printf("Unsupported VU instruction: ERSQRT\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x7a: // ERCPR
printf("Unsupported VU instruction: ERCPR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x7b: // WAITP
printf("Unsupported VU instruction: WAITP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x7c: // ESIN
printf("Unsupported VU instruction: ESIN\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x7d: // EATAN
printf("Unsupported VU instruction: EATAN\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x7e: // EEXP
printf("Unsupported VU instruction: EEXP\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
default:
logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op);
break;
}
break;
}
else
{
switch (op & 0x3f)
{
case 0x30: // IADD
printf("Unsupported VU instruction: IADD\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x31: // ISUB
printf("Unsupported VU instruction: ISUB\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x32: // IADDI
printf("Unsupported VU instruction: IADDI\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x34: // IAND
printf("Unsupported VU instruction: IAND\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
case 0x35: // IOR
printf("Unsupported VU instruction: IOR\n"); fflush(stdout); fatalerror("Unsupported VU instruction\n"); break;
break;
default:
logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op);
break;
}
}
break;
}
default:
logerror("%s: %08x: Unknown lower opcode %08x\n", machine().describe_context(), m_pc, op);
break;
}
}
void sonyvu0_device::micro_map(address_map &map)
{
map(0x000, 0xfff).ram().share(m_micro_mem);
}
void sonyvu0_device::vu_map(address_map &map)
{
map(0x000, 0xfff).ram().share(m_vu_mem);
}
void sonyvu0_device::device_start()
{
sonyvu_device::device_start();
save_item(NAME(m_cmsar0));
save_item(NAME(m_cmsar1));
save_item(NAME(m_control));
save_item(NAME(m_vpu_stat));
state_add(SONYVU0_CMSAR0, "CMSAR0", m_cmsar0);
state_add(SONYVU0_CMSAR1, "CMSAR1", m_cmsar1);
state_add(SONYVU0_FBRST, "FBRST", m_control);
state_add(SONYVU0_VPU_STAT, "VPU_STAT", m_vpu_stat);
}
void sonyvu0_device::device_reset()
{
sonyvu_device::device_reset();
m_vu1_regs = m_vu1->vector_regs();
m_cmsar0 = 0;
m_control = 0;
m_vpu_stat = 0;
m_cmsar1 = 0;
}
READ32_MEMBER(sonyvu0_device::vu1_reg_r)
{
return m_vu1_regs[offset];
}
WRITE32_MEMBER(sonyvu0_device::vu1_reg_w)
{
m_vu1_regs[offset] = data;
}
void sonyvu1_device::device_start()
{
sonyvu_device::device_start();
save_item(NAME(m_p));
state_add(SONYVU1_P, "P", *(uint32_t*)&m_p).formatstr("%17s");;
}
void sonyvu1_device::device_reset()
{
sonyvu_device::device_reset();
m_p = 0.0f;
}
void sonyvu1_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case SONYVU1_P: str = string_format("!%16g", m_p); break;
default: sonyvu_device::state_string_export(entry, str); break;
}
}
void sonyvu1_device::micro_map(address_map &map)
{
map(0x000, 0xfff).ram().share(m_micro_mem);
}
void sonyvu1_device::vu_map(address_map &map)
{
map(0x000, 0xfff).ram().share(m_vu_mem);
}
void sonyvu_device::write_vu_mem(uint32_t address, uint32_t data)
{
m_vu_mem[(address & m_mem_mask) >> 2] = data;
}
void sonyvu_device::write_micro_mem(uint32_t address, uint64_t data)
{
m_micro_mem[(address & m_mem_mask) >> 3] = data;
}

View File

@ -0,0 +1,209 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Vector Unit device skeleton
*
* To Do:
* Everything
*
*/
#ifndef MAME_CPU_MIPS_SONYVU_H
#define MAME_CPU_MIPS_SONYVU_H
#pragma once
enum
{
SONYVU_TPC,
SONYVU_SF,
SONYVU_MF,
SONYVU_CF,
SONYVU_R,
SONYVU_I,
SONYVU_Q,
SONYVU_ACCx, SONYVU_ACCy, SONYVU_ACCz, SONYVU_ACCw,
SONYVU_VF00x, SONYVU_VF00y, SONYVU_VF00z, SONYVU_VF00w,
SONYVU_VF01x, SONYVU_VF01y, SONYVU_VF01z, SONYVU_VF01w,
SONYVU_VF02x, SONYVU_VF02y, SONYVU_VF02z, SONYVU_VF02w,
SONYVU_VF03x, SONYVU_VF03y, SONYVU_VF03z, SONYVU_VF03w,
SONYVU_VF04x, SONYVU_VF04y, SONYVU_VF04z, SONYVU_VF04w,
SONYVU_VF05x, SONYVU_VF05y, SONYVU_VF05z, SONYVU_VF05w,
SONYVU_VF06x, SONYVU_VF06y, SONYVU_VF06z, SONYVU_VF06w,
SONYVU_VF07x, SONYVU_VF07y, SONYVU_VF07z, SONYVU_VF07w,
SONYVU_VF08x, SONYVU_VF08y, SONYVU_VF08z, SONYVU_VF08w,
SONYVU_VF09x, SONYVU_VF09y, SONYVU_VF09z, SONYVU_VF09w,
SONYVU_VF10x, SONYVU_VF10y, SONYVU_VF10z, SONYVU_VF10w,
SONYVU_VF11x, SONYVU_VF11y, SONYVU_VF11z, SONYVU_VF11w,
SONYVU_VF12x, SONYVU_VF12y, SONYVU_VF12z, SONYVU_VF12w,
SONYVU_VF13x, SONYVU_VF13y, SONYVU_VF13z, SONYVU_VF13w,
SONYVU_VF14x, SONYVU_VF14y, SONYVU_VF14z, SONYVU_VF14w,
SONYVU_VF15x, SONYVU_VF15y, SONYVU_VF15z, SONYVU_VF15w,
SONYVU_VF16x, SONYVU_VF16y, SONYVU_VF16z, SONYVU_VF16w,
SONYVU_VF17x, SONYVU_VF17y, SONYVU_VF17z, SONYVU_VF17w,
SONYVU_VF18x, SONYVU_VF18y, SONYVU_VF18z, SONYVU_VF18w,
SONYVU_VF19x, SONYVU_VF19y, SONYVU_VF19z, SONYVU_VF19w,
SONYVU_VF20x, SONYVU_VF20y, SONYVU_VF20z, SONYVU_VF20w,
SONYVU_VF21x, SONYVU_VF21y, SONYVU_VF21z, SONYVU_VF21w,
SONYVU_VF22x, SONYVU_VF22y, SONYVU_VF22z, SONYVU_VF22w,
SONYVU_VF23x, SONYVU_VF23y, SONYVU_VF23z, SONYVU_VF23w,
SONYVU_VF24x, SONYVU_VF24y, SONYVU_VF24z, SONYVU_VF24w,
SONYVU_VF25x, SONYVU_VF25y, SONYVU_VF25z, SONYVU_VF25w,
SONYVU_VF26x, SONYVU_VF26y, SONYVU_VF26z, SONYVU_VF26w,
SONYVU_VF27x, SONYVU_VF27y, SONYVU_VF27z, SONYVU_VF27w,
SONYVU_VF28x, SONYVU_VF28y, SONYVU_VF28z, SONYVU_VF28w,
SONYVU_VF29x, SONYVU_VF29y, SONYVU_VF29z, SONYVU_VF29w,
SONYVU_VF30x, SONYVU_VF30y, SONYVU_VF30z, SONYVU_VF30w,
SONYVU_VF31x, SONYVU_VF31y, SONYVU_VF31z, SONYVU_VF31w,
SONYVU_VI00, SONYVU_VI01, SONYVU_VI02, SONYVU_VI03,
SONYVU_VI04, SONYVU_VI05, SONYVU_VI06, SONYVU_VI07,
SONYVU_VI08, SONYVU_VI09, SONYVU_VI10, SONYVU_VI11,
SONYVU_VI12, SONYVU_VI13, SONYVU_VI14, SONYVU_VI15,
SONYVU0_VPU_STAT,
SONYVU0_FBRST,
SONYVU0_CMSAR0,
SONYVU0_CMSAR1,
SONYVU1_P = SONYVU0_VPU_STAT
};
class sonyvu_device : public cpu_device
{
public:
// construction/destruction
virtual ~sonyvu_device() {}
void write_vu_mem(uint32_t address, uint32_t data);
void write_micro_mem(uint32_t address, uint64_t data);
float* vector_regs() { return m_v; }
protected:
enum chip_type
{
CHIP_TYPE_VU0,
CHIP_TYPE_VU1,
};
sonyvu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor micro_cons, address_map_constructor vu_cons, chip_type chiptype, uint32_t mem_size);
enum : uint64_t
{
OP_UPPER_I = 0x8000000000000000ULL,
OP_UPPER_E = 0x4000000000000000ULL,
OP_UPPER_M = 0x2000000000000000ULL,
OP_UPPER_D = 0x1000000000000000ULL,
OP_UPPER_T = 0x0800000000000000ULL
};
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
virtual uint32_t execute_min_cycles() const override { return 1; }
virtual uint32_t execute_max_cycles() const override { return 1; }
virtual uint32_t execute_input_lines() const override { return 0; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override { }
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
// device_state_interface overrides
virtual void state_import(const device_state_entry &entry) override;
virtual void state_export(const device_state_entry &entry) override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
void execute_upper(const uint32_t op);
void execute_lower(const uint32_t op);
// address spaces
const address_space_config m_micro_config;
const address_space_config m_vu_config;
address_space *m_micro_space;
address_space *m_vu_space;
// core registers
uint32_t m_mem_size;
uint32_t m_mem_mask;
required_shared_ptr<uint64_t> m_micro_mem;
required_shared_ptr<uint32_t> m_vu_mem;
float* m_vfmem;
uint32_t* m_vimem;
float m_vfr[32][4]; // 0..3 = x..w
uint32_t m_vcr[16];
float m_acc[4];
float* m_v;
uint32_t m_status_flag;
uint32_t m_mac_flag;
uint32_t m_clip_flag;
uint32_t m_r;
float m_i;
float m_q;
uint32_t m_pc;
bool m_running;
int m_icount;
};
class sonyvu1_device : public sonyvu_device
{
public:
sonyvu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
void micro_map(address_map &map);
void vu_map(address_map &map);
float m_p;
};
class sonyvu0_device : public sonyvu_device
{
public:
template <typename T>
sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&vu1_tag)
: sonyvu0_device(mconfig, tag, owner, clock)
{
m_vu1.set_tag(std::forward<T>(vu1_tag));
}
sonyvu0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_start() override;
virtual void device_reset() override;
void micro_map(address_map &map);
void vu_map(address_map &map);
DECLARE_READ32_MEMBER(vu1_reg_r);
DECLARE_WRITE32_MEMBER(vu1_reg_w);
required_device<sonyvu1_device> m_vu1;
float* m_vu1_regs;
uint32_t m_control;
uint32_t m_vpu_stat;
uint32_t m_cmsar0;
uint32_t m_cmsar1;
};
DECLARE_DEVICE_TYPE(SONYVU1, sonyvu1_device)
DECLARE_DEVICE_TYPE(SONYVU0, sonyvu0_device)
#endif // MAME_CPU_MIPS_SONYVU_H

View File

@ -0,0 +1,461 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Vector Unit disassembler
*
*/
#include "emu.h"
#include "vudasm.h"
/*static*/ const char* sonyvu_disassembler::DEST_STR[] =
{
" ", "w ", "z ", "zw ", "y ", "yw ", "yz ", "yzw ",
"x ", "xw ", "xz ", "xzw ", "xy ", "xyw ", "xyz ", "xyzw"
};
/*static*/ const char* sonyvu_disassembler::DEST_COMMA_STR[] =
{
",", "w,", "z,", "zw,", "y,", "yw,", "yz,", "yzw,",
"x,", "xw,", "xz,", "xzw,", "xy,", "xyw,", "xyz,", "xyzw,"
};
/*static*/ const char* sonyvu_disassembler::BC_STR[] = { "x", "y", "z", "w" };
/*static*/ const char* sonyvu_disassembler::BC_COMMA_STR[] = { "x,", "y,", "z,", "w," };
/*static*/ const char* sonyvu_disassembler::VFREG[] =
{
"$vf00", "$vf01", "$vf02", "$vf03", "$vf04", "$vf05", "$vf06", "$vf07",
"$vf08", "$vf09", "$vf10", "$vf11", "$vf12", "$vf13", "$vf14", "$vf15",
"$vf16", "$vf17", "$vf18", "$vf19", "$vf20", "$vf21", "$vf22", "$vf23",
"$vf24", "$vf25", "$vf26", "$vf27", "$vf28", "$vf29", "$vf30", "$vf31"
};
/*static*/ const char* sonyvu_disassembler::VIREG[] =
{
"$vi00", "$vi01", "$vi02", "$vi03", "$vi04", "$vi05", "$vi06", "$vi07",
"$vi08", "$vi09", "$vi10", "$vi11", "$vi12", "$vi13", "$vi14", "$vi15",
"STATUS", "MACF", "CLIPF", "res19", "R", "I", "Q", "res23",
"res24", "res25", "TPC", "CMSAR0", "FBRST", "VPU_STAT", "res30", "CMSAR1"
};
offs_t sonyvu_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
uint64_t op = opcodes.r64(pc & ~7);
if (pc & 4)
{
if (op & 0x8000000000000000ULL)
{
util::stream_format(stream, "loi %f", *reinterpret_cast<float*>(&op));
}
else
{
dasm_lower(pc, (uint32_t)op, stream);
}
}
else
{
dasm_upper(pc, (uint32_t)(op >> 32), stream);
}
return 4 | SUPPORTED;
}
void sonyvu_disassembler::dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rd = (op >> 6) & 31;
const int rs = (op >> 11) & 31;
const int rt = (op >> 16) & 31;
const char* bc = BC_STR[op & 3];
const char* dest = DEST_STR[(op >> 21) & 15];
const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
switch (op & 0x3f)
{
case 0x08: case 0x09: case 0x0a: case 0x0b:
util::stream_format(stream, "madd%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
util::stream_format(stream, "msub%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x10: case 0x11: case 0x12: case 0x13:
util::stream_format(stream, "max%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x14: case 0x15: case 0x16: case 0x17:
util::stream_format(stream, "mini%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
util::stream_format(stream, "mul%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x1c: util::stream_format(stream, "mulq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x1d: util::stream_format(stream, "maxi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x1e: util::stream_format(stream, "muli.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x1f: util::stream_format(stream, "minii.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x20: util::stream_format(stream, "addq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x21: util::stream_format(stream, "maddq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x22: util::stream_format(stream, "addi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x23: util::stream_format(stream, "maddi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x24: util::stream_format(stream, "subq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x25: util::stream_format(stream, "msubq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x26: util::stream_format(stream, "subi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x27: util::stream_format(stream, "msubi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
case 0x28: util::stream_format(stream, "add.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x29: util::stream_format(stream, "madd.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2a: util::stream_format(stream, "mul.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2b: util::stream_format(stream, "max.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2c: util::stream_format(stream, "sub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2d: util::stream_format(stream, "msub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2e: util::stream_format(stream, "opmsub.xyz %sxyz, %sxyz, %sxyz", VFREG[rd], VFREG[rs], VFREG[rt]); break;
case 0x2f: util::stream_format(stream, "mini.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
{
const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3);
switch (type2_op)
{
case 0x00: case 0x01: case 0x02: case 0x03:
util::stream_format(stream, "adda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x04: case 0x05: case 0x06: case 0x07:
util::stream_format(stream, "suba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x08: case 0x09: case 0x0a: case 0x0b:
util::stream_format(stream, "madda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
util::stream_format(stream, "msuba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x10: util::stream_format(stream, "itof0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x11: util::stream_format(stream, "itof4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x12: util::stream_format(stream, "itof12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x13: util::stream_format(stream, "itof15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x14: util::stream_format(stream, "ftoi0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x15: util::stream_format(stream, "ftoi4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x16: util::stream_format(stream, "ftoi12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x17: util::stream_format(stream, "ftoi15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
util::stream_format(stream, "mula%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
case 0x1c: util::stream_format(stream, "mulaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
case 0x1d: util::stream_format(stream, "abs.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
case 0x1e: util::stream_format(stream, "mulai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
case 0x1f: util::stream_format(stream, "clipw.xyz %sxyz, %sw", VFREG[rs], VFREG[rt]); break;
case 0x20: util::stream_format(stream, "addaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
case 0x21: util::stream_format(stream, "maddaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
case 0x22: util::stream_format(stream, "addai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
case 0x23: util::stream_format(stream, "maddai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
case 0x24: util::stream_format(stream, "subaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
case 0x25: util::stream_format(stream, "msubaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
case 0x26: util::stream_format(stream, "subai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
case 0x27: util::stream_format(stream, "msubai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
case 0x28: util::stream_format(stream, "adda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x29: util::stream_format(stream, "madda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2a: util::stream_format(stream, "mula.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
// 2b?
case 0x2c: util::stream_format(stream, "suba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2d: util::stream_format(stream, "msuba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
case 0x2e: util::stream_format(stream, "opmula.xyz ACCxyz, %sxyz, %sxyz", VFREG[rs], VFREG[rt]); break;
case 0x2f: util::stream_format(stream, "nop"); break;
default:
util::stream_format(stream, "invalid");
break;
}
break;
}
default:
util::stream_format(stream, "invalid");
break;
}
}
void sonyvu_disassembler::dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream)
{
const int rd = (op >> 6) & 31;
const int rs = (op >> 11) & 31;
const int rt = (op >> 16) & 31;
const char* dest = DEST_STR[(op >> 21) & 15];
const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
const char* ftf = BC_STR[(op >> 23) & 3];
const char* fsf = BC_STR[(op >> 21) & 3];
const char* fsfc = BC_COMMA_STR[(op >> 21) & 3];
switch ((op >> 25) & 0x7f)
{
case 0x00: // LQ
util::stream_format(stream, "lq.%s %s%s %s(%s)", dest, VFREG[rt], destc, signed_11bit(op), VIREG[rs]);
break;
case 0x01: // SQ
util::stream_format(stream, "sq.%s %s%s %s(%s)", dest, VFREG[rs], destc, signed_11bit(op), VIREG[rt]);
break;
case 0x04: // ILW
util::stream_format(stream, "ilw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
break;
case 0x05: // ISW
util::stream_format(stream, "isw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
break;
case 0x08: // IADDIU
util::stream_format(stream, "iaddiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
break;
case 0x09: // ISUBIU
util::stream_format(stream, "isubiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
break;
case 0x10: // FCEQ
util::stream_format(stream, "fceq $vi01, %06x", op & 0xffffff);
break;
case 0x11: // FCSET
util::stream_format(stream, "fcset %06x", op & 0xffffff);
break;
case 0x12: // FCAND
util::stream_format(stream, "fcand $vi01, %06x", op & 0xffffff);
break;
case 0x13: // FCOR
util::stream_format(stream, "fcor $vi01, %06x", op & 0xffffff);
break;
case 0x14: // FSEQ
util::stream_format(stream, "fseq %s, %s", VIREG[rt], op & 0xfff);
break;
case 0x15: // FSSET
util::stream_format(stream, "fsset %03x", op & 0xfff);
break;
case 0x16: // FSAND
util::stream_format(stream, "fsand %s, %s", VIREG[rt], op & 0xfff);
break;
case 0x17: // FSOR
util::stream_format(stream, "fsor %s, %s", VIREG[rt], op & 0xfff);
break;
case 0x18: // FMEQ
util::stream_format(stream, "fmeq %s, %s", VIREG[rt], VIREG[rs]);
break;
case 0x1a: // FMAND
util::stream_format(stream, "fmand %s, %s", VIREG[rt], VIREG[rs]);
break;
case 0x1b: // FMOR
util::stream_format(stream, "fmor %s, %s", VIREG[rt], VIREG[rs]);
break;
case 0x1c: // FCGET
util::stream_format(stream, "fcget %s", VIREG[rt]);
break;
case 0x20: // B
util::stream_format(stream, "b %s", signed_11bit_x8(op));
break;
case 0x21: // BAL
util::stream_format(stream, "bal %s, %s", VIREG[rt], signed_11bit_x8(op));
break;
case 0x24: // JR
util::stream_format(stream, "jr %s", VIREG[rs]);
break;
case 0x25: // JALR
util::stream_format(stream, "jalr %s, %s", VIREG[rt], VIREG[rs]);
break;
case 0x28: // IBEQ
util::stream_format(stream, "ibeq %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
break;
case 0x29: // IBNE
util::stream_format(stream, "ibne %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
break;
case 0x2c: // IBLTZ
util::stream_format(stream, "ibltz %s, %s", VIREG[rs], signed_11bit_x8(op));
break;
case 0x2d: // IBGTZ
util::stream_format(stream, "ibgtz %s, %s", VIREG[rs], signed_11bit_x8(op));
break;
case 0x2e: // IBLEZ
util::stream_format(stream, "iblez %s, %s", VIREG[rs], signed_11bit_x8(op));
break;
case 0x2f: // IBGEZ
util::stream_format(stream, "ibgez %s, %s", VIREG[rs], signed_11bit_x8(op));
break;
case 0x40: // SPECIAL
{
if ((op & 0x3c) == 0x3c)
{
uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3);
switch (type4_op)
{
case 0x30: // MOVE
util::stream_format(stream, "move.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
break;
case 0x31: // MR32
util::stream_format(stream, "mr32.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
break;
case 0x34: // LQI
util::stream_format(stream, "lqi.%s %s%s (%s++)", dest, VFREG[rt], destc, VIREG[rs]);
break;
case 0x35: // SQI
util::stream_format(stream, "sqi.%s %s%s (%s++)", dest, VFREG[rs], destc, VIREG[rt]);
break;
case 0x36: // LQD
util::stream_format(stream, "lqi.%s %s%s (--%s)", dest, VFREG[rt], destc, VIREG[rs]);
break;
case 0x37: // SQD
util::stream_format(stream, "sqi.%s %s%s (--%s)", dest, VFREG[rs], destc, VIREG[rt]);
break;
case 0x38: // DIV
util::stream_format(stream, "div Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
break;
case 0x39: // SQRT
util::stream_format(stream, "sqrt Q, %s%s", dest, VFREG[rt], ftf);
break;
case 0x3a: // RSQRT
util::stream_format(stream, "rsqrt Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
break;
case 0x3b: // WAITQ
util::stream_format(stream, "waitq");
break;
case 0x3c: // MTIR
util::stream_format(stream, "mtir %s, %s%s", VIREG[rt], VFREG[rs], fsf);
break;
case 0x3d: // MFIR
util::stream_format(stream, "mtir.%s %s%s %s", dest, VFREG[rt], destc, VIREG[rs] );
break;
case 0x3e: // ILWR
util::stream_format(stream, "ilwr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
break;
case 0x3f: // ISWR
util::stream_format(stream, "iswr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
break;
case 0x40: // RNEXT
util::stream_format(stream, "rnext.%s %s%s R", dest, VFREG[rt], destc);
break;
case 0x41: // RGET
util::stream_format(stream, "rget.%s %s%s R", dest, VFREG[rt], destc);
break;
case 0x42: // RINIT
util::stream_format(stream, "rinit R, %s%s", dest, VFREG[rs], dest);
break;
case 0x43: // RXOR
util::stream_format(stream, "rxor R, %s%s", dest, VFREG[rs], dest);
break;
case 0x64: // MFP
util::stream_format(stream, "mfp.%s %s%s P", dest, VFREG[rt], destc);
break;
case 0x68: // XTOP
util::stream_format(stream, "xtop %s", VIREG[rt]);
break;
case 0x69: // XITOP
util::stream_format(stream, "xitop %s", VIREG[rt]);
break;
case 0x6c: // XGKICK
util::stream_format(stream, "xgkick %s", VIREG[rs]);
break;
case 0x70: // ESADD
util::stream_format(stream, "esadd P, %s", VFREG[rs]);
break;
case 0x71: // ERSADD
util::stream_format(stream, "ersadd P, %s", VFREG[rs]);
break;
case 0x72: // ELENG
util::stream_format(stream, "eleng P, %s", VFREG[rs]);
break;
case 0x73: // ERLENG
util::stream_format(stream, "erleng P, %s", VFREG[rs]);
break;
case 0x74: // EATANxy
util::stream_format(stream, "eatanxy P, %s", VFREG[rs]);
break;
case 0x75: // EATANxz
util::stream_format(stream, "eatanxz P, %s", VFREG[rs]);
break;
case 0x76: // ESUM
util::stream_format(stream, "esum P, %s", VFREG[rs]);
break;
case 0x78: // ESQRT
util::stream_format(stream, "esqrt P, %s%s", VFREG[rs], fsf);
break;
case 0x79: // ERSQRT
util::stream_format(stream, "ersqrt P, %s%s", VFREG[rs], fsf);
break;
case 0x7a: // ERCPR
util::stream_format(stream, "ercpr P, %s%s", VFREG[rs], fsf);
break;
case 0x7b: // WAITP
util::stream_format(stream, "waitp");
break;
case 0x7c: // ESIN
util::stream_format(stream, "esin P, %s%s", VFREG[rs], fsf);
break;
case 0x7d: // EATAN
util::stream_format(stream, "eatan P, %s%s", VFREG[rs], fsf);
break;
case 0x7e: // EEXP
util::stream_format(stream, "eexp P, %s%s", VFREG[rs], fsf);
break;
default:
util::stream_format(stream, "invalid");
break;
}
break;
}
else
{
switch (op & 0x3f)
{
case 0x30: // IADD
util::stream_format(stream, "iadd %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
break;
case 0x31: // ISUB
util::stream_format(stream, "isub %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
break;
case 0x32: // IADDI
util::stream_format(stream, "iaddi %s, %s, %s", VIREG[rt], VIREG[rs], signed_5bit(op));
break;
case 0x34: // IAND
util::stream_format(stream, "iand %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
break;
case 0x35: // IOR
util::stream_format(stream, "ior %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
break;
default:
util::stream_format(stream, "invalid");
break;
}
}
break;
}
default:
util::stream_format(stream, "invalid");
break;
}
}
uint32_t sonyvu_disassembler::opcode_alignment() const
{
return 4;
}
std::string sonyvu_disassembler::signed_5bit(uint16_t val)
{
int16_t sval = (int32_t)val;
sval <<= 11;
sval >>= 11;
if (sval < 0)
return util::string_format("-$%x", -sval);
else
return util::string_format("$%x", sval);
}
std::string sonyvu_disassembler::signed_11bit(uint16_t val)
{
int16_t sval = (int32_t)val;
sval <<= 5;
sval >>= 5;
if (sval < 0)
return util::string_format("-$%x", -sval);
else
return util::string_format("$%x", sval);
}
std::string sonyvu_disassembler::signed_11bit_x8(uint16_t val)
{
int16_t sval = (int32_t)val;
sval <<= 5;
sval >>= 5;
if (sval < 0)
return util::string_format("-$%x", -sval * 8);
else
return util::string_format("$%x", sval * 8);
}
std::string sonyvu_disassembler::signed_15bit(uint16_t val)
{
int16_t sval = (int32_t)val;
sval <<= 1;
sval >>= 1;
if (sval < 0)
return util::string_format("-$%x", -sval);
else
return util::string_format("$%x", sval);
}

View File

@ -0,0 +1,39 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
*
* Sony Playstation 2 Vector Unit disassembler
*
*/
#ifndef MAME_CPU_MIPS_VUDASM_H
#define MAME_CPU_MIPS_VUDASM_H
#pragma once
class sonyvu_disassembler : public util::disasm_interface
{
public:
sonyvu_disassembler() = default;
virtual ~sonyvu_disassembler() = default;
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
void dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream);
void dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream);
std::string signed_5bit(uint16_t val);
std::string signed_11bit(uint16_t val);
std::string signed_11bit_x8(uint16_t val);
std::string signed_15bit(uint16_t val);
static const char * DEST_STR[16];
static const char * DEST_COMMA_STR[16];
static const char * BC_STR[16];
static const char * BC_COMMA_STR[16];
static const char * VFREG[32];
static const char * VIREG[32];
};
#endif // MAME_CPU_MIPS_VUDASM_H

View File

@ -162,6 +162,7 @@ iLinkSGUID=0x--------
#include "cpu/mips/mips3.h"
#include "cpu/mips/r3000.h"
#include "cpu/mips/sonyvu.h"
#include "machine/iopcdvd.h"
#include "machine/iopdma.h"
@ -203,6 +204,8 @@ public:
, m_gif(*this, "gif")
, m_gs(*this, "gs")
, m_vif1(*this, "vif1")
, m_vu0(*this, "vu0")
, m_vu1(*this, "vu1")
, m_pad(*this, "pad%u", 0U)
, m_mc(*this, "mc")
, m_screen(*this, "screen")
@ -266,6 +269,8 @@ protected:
required_device<ps2_gif_device> m_gif;
required_device<ps2_gs_device> m_gs;
required_device<ps2_vif1_device> m_vif1;
required_device<sonyvu0_device> m_vu0;
required_device<sonyvu1_device> m_vu1;
required_device_array<ps2_pad_device, 2> m_pad;
required_device<ps2_mc_device> m_mc;
required_device<screen_device> m_screen;
@ -550,7 +555,7 @@ void ps2sony_state::machine_reset()
memset(m_ipu_out_fifo, 0, sizeof(uint64_t)*0x1000);
m_ipu_out_fifo_index = 0;
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
m_vblank_timer->adjust(m_screen->time_until_pos(0), 1);
}
TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
@ -558,17 +563,17 @@ TIMER_CALLBACK_MEMBER(ps2sony_state::vblank)
if (param)
{
// VBlank enter
m_intc->raise_interrupt(ps2_intc_device::INT_VB_ON);
m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_ON);
m_vblank_timer->adjust(m_screen->time_until_pos(0), 0);
m_intc->raise_interrupt(ps2_intc_device::INT_VB_ON);
m_vblank_timer->adjust(m_screen->time_until_pos(32), 0);
m_gs->vblank_start();
}
else
{
// VBlank exit
//m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF);
m_iop_intc->raise_interrupt(iop_intc_device::INT_VB_OFF);
m_vblank_timer->adjust(m_screen->time_until_pos(480), 1);
m_intc->raise_interrupt(ps2_intc_device::INT_VB_OFF);
m_vblank_timer->adjust(m_screen->time_until_pos(0), 1);
m_gs->vblank_end();
}
}
@ -734,21 +739,24 @@ static INPUT_PORTS_START( ps2sony )
INPUT_PORTS_END
MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_DEVICE_ADD(m_maincpu, R5900LE, 294'912'000)
MCFG_DEVICE_ADD(m_maincpu, R5900LE, 294'912'000, m_vu0)
MCFG_CPU_FORCE_NO_DRC()
MCFG_MIPS3_ICACHE_SIZE(16384)
MCFG_MIPS3_DCACHE_SIZE(16384)
MCFG_DEVICE_PROGRAM_MAP(mem_map)
MCFG_DEVICE_ADD(m_vif1, SONYPS2_VIF1, 294912000/2, m_gif)
MCFG_DEVICE_ADD(m_vu0, SONYVU0, 294'912'000, m_vu1)
MCFG_DEVICE_ADD(m_vu1, SONYVU1, 294'912'000)
MCFG_DEVICE_ADD(m_vif1, SONYPS2_VIF1, 294912000/2, m_gif, m_vu1)
MCFG_DEVICE_ADD(m_timer[0], SONYPS2_TIMER, 294912000/2, true)
MCFG_DEVICE_ADD(m_timer[1], SONYPS2_TIMER, 294912000/2, true)
MCFG_DEVICE_ADD(m_timer[2], SONYPS2_TIMER, 294912000/2, false)
MCFG_DEVICE_ADD(m_timer[3], SONYPS2_TIMER, 294912000/2, false)
MCFG_DEVICE_ADD(m_gs, SONYPS2_GS, 294912000/2)
MCFG_DEVICE_ADD(m_intc, SONYPS2_INTC, m_maincpu)
MCFG_DEVICE_ADD(m_gs, SONYPS2_GS, 294912000/2, m_intc)
MCFG_DEVICE_ADD(m_dmac, SONYPS2_DMAC, 294912000/2, m_maincpu, m_ram, m_sif, m_gif, m_vif1)
MCFG_DEVICE_ADD(m_sif, SONYPS2_SIF, m_intc)
MCFG_DEVICE_ADD(m_gif, SONYPS2_GIF, m_gs)
@ -776,8 +784,8 @@ MACHINE_CONFIG_START(ps2sony_state::ps2sony)
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_UPDATE_DRIVER(ps2sony_state, screen_update)
MCFG_SCREEN_SIZE(640, 525)
MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
MCFG_SCREEN_SIZE(640, 256)
MCFG_SCREEN_VISIBLE_AREA(0, 639, 0, 223)
MCFG_PALETTE_ADD("palette", 65536)
MACHINE_CONFIG_END

View File

@ -11,7 +11,7 @@
#include "iopcdvd.h"
/*static*/ const size_t iop_cdvd_device::BUFFER_SIZE = 2048; // Total guess
/*static*/ const size_t iop_cdvd_device::BUFFER_SIZE = 16; // Total guess
DEFINE_DEVICE_TYPE(SONYIOP_CDVD, iop_cdvd_device, "iopcdvd", "Playstation 2 disc controller")
@ -23,23 +23,31 @@ iop_cdvd_device::iop_cdvd_device(const machine_config &mconfig, const char *tag,
void iop_cdvd_device::device_start()
{
m_out_buf = std::make_unique<uint8_t[]>(BUFFER_SIZE);
save_item(NAME(m_status_0x05));
save_item(NAME(m_status_0x17));
save_item(NAME(m_command));
save_item(NAME(m_out_count));
save_item(NAME(m_out_curr));
save_item(NAME(m_channel[0].m_buffer));
save_item(NAME(m_channel[0].m_curr));
save_item(NAME(m_channel[0].m_end));
save_item(NAME(m_channel[0].m_status));
save_item(NAME(m_channel[0].m_command));
save_item(NAME(m_channel[1].m_buffer));
save_item(NAME(m_channel[1].m_curr));
save_item(NAME(m_channel[1].m_end));
save_item(NAME(m_channel[1].m_status));
save_item(NAME(m_channel[1].m_command));
}
void iop_cdvd_device::device_reset()
{
m_status_0x05 = CDVD_STATUS_BOOT;
m_status_0x17 = CDVD_STATUS_IDLE;
m_command = 0;
memset(&m_out_buf[0], 0, BUFFER_SIZE);
m_out_count = 0;
m_out_curr = 0;
for (offs_t i = 0; i < 2; i++)
{
memset(m_channel[i].m_buffer, 0, BUFFER_SIZE);
m_channel[i].m_curr = 0;
m_channel[i].m_end = 0;
m_channel[i].m_status = 0;
m_channel[i].m_command = 0;
}
m_channel[0].m_status |= CDVD_STATUS_IDLE;
m_channel[1].m_status |= CDVD_STATUS_IDLE;
}
READ8_MEMBER(iop_cdvd_device::read)
@ -47,31 +55,25 @@ READ8_MEMBER(iop_cdvd_device::read)
uint8_t ret = 0;
switch (offset)
{
case 0x04:
ret = m_channel[CHAN_SERVO].m_command;
logerror("%s: cdvd_r: Servo Command (%02x)\n", machine().describe_context(), ret);
break;
case 0x05:
ret = m_status_0x05;
logerror("%s: cdvd_r: Status 0x05? (%02x)\n", machine().describe_context(), ret);
ret = m_channel[CHAN_SERVO].m_status;
logerror("%s: cdvd_r: Servo Status (%02x)\n", machine().describe_context(), ret);
break;
case 0x16:
ret = m_command;
logerror("%s: cdvd_r: Command? (%02x)\n", machine().describe_context(), ret);
ret = m_channel[CHAN_DATA].m_command;
logerror("%s: cdvd_r: Data Command (%02x)\n", machine().describe_context(), ret);
break;
case 0x17:
ret = m_status_0x17;
logerror("%s: cdvd_r: Status 0x17? (%02x)\n", machine().describe_context(), ret);
ret = m_channel[CHAN_DATA].m_status;
logerror("%s: cdvd_r: Data Status (%02x)\n", machine().describe_context(), ret);
break;
case 0x18:
ret = m_out_buf[m_out_curr];
if (m_out_curr < m_out_count)
{
m_out_curr++;
if (m_out_curr == m_out_count)
{
m_status_0x17 |= CDVD_STATUS_IDLE;
m_out_count = 0;
m_out_curr = 0;
}
}
logerror("%s: cdvd_r: Command Output (%02x) (%d left)\n", machine().describe_context(), ret, m_out_count - m_out_curr);
ret = data_fifo_pop();
logerror("%s: cdvd_r: Data FIFO Out (%02x) (%d left)\n", machine().describe_context(), ret, m_channel[CHAN_DATA].m_end - m_channel[CHAN_DATA].m_curr);
break;
default:
logerror("%s: cdvd_r: Unknown read: %08x\n", machine().describe_context(), 0x1f402000 + offset);
@ -80,43 +82,87 @@ READ8_MEMBER(iop_cdvd_device::read)
return ret;
}
void iop_cdvd_device::data_fifo_push(uint8_t data)
{
drive_channel_t &channel = m_channel[CHAN_DATA];
if (channel.m_end >= BUFFER_SIZE)
{
return;
}
channel.m_buffer[channel.m_end++] = data;
}
uint8_t iop_cdvd_device::data_fifo_pop()
{
drive_channel_t &channel = m_channel[CHAN_DATA];
if (channel.m_end == channel.m_curr)
{
channel.m_status |= CDVD_STATUS_IDLE;
return 0;
}
const uint8_t ret = channel.m_buffer[channel.m_curr++];
if (channel.m_end == channel.m_curr)
{
channel.m_status |= CDVD_STATUS_IDLE;
channel.m_curr = 0;
channel.m_end = 0;
}
return ret;
}
WRITE8_MEMBER(iop_cdvd_device::write)
{
switch (offset)
{
case 0x16:
m_command = data;
m_status_0x17 &= ~(CDVD_STATUS_IDLE | CDVD_STATUS_BOOT);
m_status_0x05 &= ~CDVD_STATUS_BOOT;
if (m_out_count > 0)
logerror("%s: cdvd_w: Command warning: Issuing command without reading previous results\n", machine().describe_context());
switch (data)
{
case 0x15:
logerror("%s: cdvd_w: Command 0x15?\n", machine().describe_context());
m_out_buf[m_out_count++] = 1;
m_intc->raise_interrupt(5);
break;
case 0x40:
logerror("%s: cdvd_w: Command 0x40?\n", machine().describe_context());
m_out_buf[m_out_count++] = 0;
break;
case 0x41:
logerror("%s: cdvd_w: Command 0x41?\n", machine().describe_context());
m_out_count = 0x10;
memset(&m_out_buf[0], 0, 0x10);
break;
case 0x43:
logerror("%s: cdvd_w: Command 0x43?\n", machine().describe_context());
m_out_buf[m_out_count++] = 0;
break;
default:
logerror("%s: cdvd_r: Unknown command(?) %02x\n", machine().describe_context(), data);
break;
}
handle_data_command(data);
break;
case 0x17:
data_fifo_push(data);
logerror("%s: cdvd_w: Data FIFO push? %02x\n", machine().describe_context(), data);
break;
default:
logerror("%s: cdvd_w: Unknown write: %08x = %02x\n", machine().describe_context(), 0x1f402000 + offset, data);
break;
}
}
void iop_cdvd_device::handle_data_command(uint8_t data)
{
drive_channel_t &channel = m_channel[CHAN_DATA];
channel.m_command = data;
channel.m_status &= ~CDVD_STATUS_IDLE;
if (channel.m_end)
logerror("%s: cdvd_w: Data Command warning: Issuing command without reading previous results\n", machine().describe_context());
switch (data)
{
case 0x08:
logerror("%s: cdvd_w: Command 0x08?\n", machine().describe_context());
for (size_t i = 0; i < 8; i++)
data_fifo_push(0);
break;
case 0x15:
logerror("%s: cdvd_w: Command 0x15?\n", machine().describe_context());
data_fifo_push(1);
break;
case 0x40:
logerror("%s: cdvd_w: Command 0x40?\n", machine().describe_context());
data_fifo_push(0);
break;
case 0x41:
logerror("%s: cdvd_w: Command 0x41?\n", machine().describe_context());
for (size_t i = 0; i < 0x10; i++)
data_fifo_push(0);
break;
case 0x43:
logerror("%s: cdvd_w: Command 0x43?\n", machine().describe_context());
data_fifo_push(0);
break;
default:
logerror("%s: cdvd_w: Unknown command(?) %02x\n", machine().describe_context(), data);
break;
}
}

View File

@ -36,21 +36,34 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
void handle_data_command(uint8_t data);
void data_fifo_push(uint8_t data);
uint8_t data_fifo_pop();
enum
{
CDVD_STATUS_BOOT = 0x08,
CDVD_STATUS_IDLE = 0x40,
CDVD_COMMAND_0x15 = 0x15,
};
required_device<iop_intc_device> m_intc;
uint8_t m_status_0x05;
uint8_t m_status_0x17;
uint8_t m_command;
std::unique_ptr<uint8_t[]> m_out_buf;
uint8_t m_out_count;
uint8_t m_out_curr;
enum
{
CHAN_SERVO = 0,
CHAN_DATA = 1
};
struct drive_channel_t
{
uint8_t m_buffer[0x10]; // Buffer size is a total guess
uint8_t m_curr;
uint8_t m_end;
uint8_t m_status;
uint8_t m_command;
};
drive_channel_t m_channel[2];
static const size_t BUFFER_SIZE;
};

View File

@ -205,11 +205,11 @@ READ32_MEMBER(iop_timer_device::read)
{
case 0x00:
{
const uint32_t old = m_count;
//const uint32_t old = m_count;
update_count();
ret = m_count;
if (old != m_count)
logerror("%s: IOP timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//if (old != m_count)
//logerror("%s: IOP timer read: COUNT (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
}

View File

@ -129,26 +129,29 @@ void ps2_dmac_device::transfer_vif1()
if (count)
{
//logerror("%s: DMAC VIF1 quadword count: %08x\n", machine().describe_context(), count);
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
uint32_t words[4] = { 0, 0, 0, 0 };
for (int word = 0; word < 4; word++)
if (m_vif1->fifo_available(4))
{
words[word] = space.read_dword(addr);
addr += 4;
uint32_t addr = channel.addr();
if (BIT(addr, 31))
addr -= 0x10000000;
address_space &space = m_ee->space(AS_PROGRAM);
uint32_t words[4] = { 0, 0, 0, 0 };
for (int word = 0; word < 4; word++)
{
words[word] = space.read_dword(addr);
addr += 4;
}
m_vif1->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
}
m_vif1->dma_write(((uint64_t)words[3] << 32) | words[2], ((uint64_t)words[1] << 32) | words[0]);
channel.set_addr(channel.addr() + 0x10);
channel.set_quadword_count(count - 1);
}
else if (channel.end_tag())
{
logerror("%s: DMAC VIF1 end tag\n", machine().describe_context());
transfer_finish(VIF1);
}
else
else if (m_vif1->fifo_available(2))
{
logerror("%s: DMAC VIF1 following source tag\n", machine().describe_context());
uint32_t tag_addr = channel.tag_addr();
@ -232,7 +235,7 @@ void ps2_dmac_device::transfer_sif0()
}
else if (channel.end_tag())
{
logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context());
//logerror("%s: SIF0 end tag, finishing transfer\n", machine().describe_context());
transfer_finish(SIF0);
}
else if (m_sif->fifo_depth(0) >= 2)
@ -240,7 +243,7 @@ void ps2_dmac_device::transfer_sif0()
const uint32_t hi = m_sif->fifo_pop(0);
const uint32_t lo = m_sif->fifo_pop(0);
const uint32_t tag = hi;
logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo);
//logerror("%s: SIF0 chaining tag, tag %08x %08x\n", machine().describe_context(), hi, lo);
channel.set_addr(lo);
channel.set_tag_addr(channel.tag_addr() + 0x10);
channel.set_quadword_count(tag & 0x0000ffff);
@ -280,12 +283,12 @@ void ps2_dmac_device::transfer_sif1()
}
else if (channel.end_tag())
{
logerror("%s: DMAC SIF1 end tag\n", machine().describe_context());
//logerror("%s: DMAC SIF1 end tag\n", machine().describe_context());
transfer_finish(SIF1);
}
else
{
logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context());
//logerror("%s: DMAC SIF1 following source tag\n", machine().describe_context());
follow_source_tag(SIF1);
}
}
@ -301,7 +304,8 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan)
const uint64_t lo = space.read_dword(tag_addr + 8);
const uint32_t tag = (uint32_t)hi;
const uint32_t addr = (uint32_t)(hi >> 32) & ~0xf;
logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
if (chan != GIF && chan != VIF1)
logerror("Trying to follow tag: %08x|%08x %08x|%08x\n", (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
channel.set_chcr((channel.chcr() & 0x0000ffff) | (tag & 0xffff0000));
channel.set_quadword_count(tag & 0x0000ffff);
@ -338,6 +342,7 @@ void ps2_dmac_device::follow_source_tag(uint32_t chan)
logerror("%s: Unknown DMAtag ID: %d\n", machine().describe_context(), id);
break;
}
if (irq && channel.irq_enable())
{
channel.set_end_tag(true);
@ -521,15 +526,15 @@ READ32_MEMBER(ps2_dmac_device::channel_r)
break;
case 0xc000/8: /* SIF0_CHCR */
ret = m_channels[SIF0].chcr();
logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: dmac_channel_r: SIF0_CHCR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xc010/8: /* SIF0_MADR */
ret = m_channels[SIF0].addr();
logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: dmac_channel_r: SIF0_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xc020/8: /* SIF0_QWC */
ret = m_channels[SIF0].quadword_count();
logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: dmac_channel_r: SIF0_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xc400/8: /* SIF1_CHCR */
ret = m_channels[SIF1].chcr();
@ -537,11 +542,11 @@ READ32_MEMBER(ps2_dmac_device::channel_r)
break;
case 0xc410/8: /* SIF1_MADR */
ret = m_channels[SIF1].addr();
logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: dmac_channel_r: SIF1_MADR (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xc420/8: /* SIF1_QWC */
ret = m_channels[SIF1].quadword_count();
logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
//logerror("%s: dmac_channel_r: SIF1_QWC (%08x & %08x)\n", machine().describe_context(), ret, mem_mask);
break;
case 0xc430/8: /* SIF1_TADR */
ret = m_channels[SIF1].tag_addr();
@ -682,33 +687,33 @@ WRITE32_MEMBER(ps2_dmac_device::channel_w)
logerror("%s: dmac_channel_w: D4_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0xc000/8: /* SIF0_CHCR */
logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
//logerror("%s: dmac_channel_w: SIF0_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
//logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
m_channels[SIF0].set_chcr(data);
break;
case 0xc010/8: /* SIF0_MADR */
logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: dmac_channel_w: SIF0_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[SIF0].set_addr(data);
break;
case 0xc020/8: /* SIF0_QWC */
logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: dmac_channel_w: SIF0_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[SIF0].set_quadword_count(data);
break;
case 0xc400/8: /* D6_CHCR */
logerror("%s: dmac_channel_w: SIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
//logerror("%s: dmac_channel_w: SIF1_CHCR = %08x & %08x (DIR=%s Memory, MOD=%s, ASP=%d, TTE=%s DMAtag, \n", machine().describe_context(), data, mem_mask, BIT(data, 0) ? "From" : "To", mode_strings[(data >> 2) & 3], (data >> 4) & 3, BIT(data, 6) ? "Transfers" : "Does not transfer");
//logerror("%s: TIE=%d, START=%d, TAG=%04x\n", machine().describe_context(), BIT(data, 7), BIT(data, 8), data >> 16);
m_channels[SIF1].set_chcr(data);
break;
case 0xc410/8: /* D6_MADR */
logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: dmac_channel_w: SIF1_MADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[SIF1].set_addr(data);
break;
case 0xc420/8: /* D6_QWC */
logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: dmac_channel_w: SIF1_QWC = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[SIF1].set_quadword_count(data);
break;
case 0xc430/8: /* D6_TADR */
logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
//logerror("%s: dmac_channel_w: SIF1_TADR = %08x & %08x\n", machine().describe_context(), data, mem_mask);
m_channels[SIF1].set_tag_addr(data);
break;
case 0xc800/8: /* D7_CHCR */

View File

@ -27,6 +27,7 @@ ps2_vif1_device::ps2_vif1_device(const machine_config &mconfig, const char *tag,
: device_t(mconfig, SONYPS2_VIF1, tag, owner, clock)
, device_execute_interface(mconfig, *this)
, m_gif(*this, finder_base::DUMMY_TAG)
, m_vu1(*this, finder_base::DUMMY_TAG)
{
}
@ -264,11 +265,11 @@ WRITE64_MEMBER(ps2_vif1_device::mmio_w)
void ps2_vif1_device::dma_write(const uint64_t hi, const uint64_t lo)
{
logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
fifo_push((uint32_t)(hi >> 32));
fifo_push((uint32_t)hi);
//logerror("%s: dma_write: %08x%08x%08x%08x\n", machine().describe_context(), (uint32_t)(hi >> 32), (uint32_t)hi, (uint32_t)(lo >> 32), (uint32_t)lo);
fifo_push((uint32_t)(lo >> 32));
fifo_push((uint32_t)lo);
fifo_push((uint32_t)(hi >> 32));
fifo_push((uint32_t)hi);
}
void ps2_vif1_device::tag_write(uint32_t *data)
@ -278,14 +279,19 @@ void ps2_vif1_device::tag_write(uint32_t *data)
fifo_push(data[3]);
}
void ps2_vif1_device::fifo_push(uint32_t value)
void ps2_vif1_device::fifo_push(uint32_t data)
{
if (m_end >= BUFFER_SIZE)
{
printf("FIFO overflow :(\n");
return;
}
m_buffer[m_end++] = value;
m_buffer[m_end++] = data;
m_status &= ~0x1f000000;
m_status |= ((m_end - m_curr) >> 2) << 24;
logerror("%s: Pushing %08x onto FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), data, m_end - m_curr, m_status);
}
uint32_t ps2_vif1_device::fifo_pop()
@ -303,6 +309,11 @@ uint32_t ps2_vif1_device::fifo_pop()
m_curr = 0;
m_end = 0;
}
m_status &= ~0x1f000000;
m_status |= ((m_end - m_curr) >> 2) << 24;
logerror("%s: Popping %08x from FIFO, depth is now %d, status is now %08x\n", machine().describe_context(), ret, m_end - m_curr, m_status);
return ret;
}
@ -322,9 +333,11 @@ void ps2_vif1_device::execute_run()
if (fifo_depth())
{
m_code = fifo_pop();
logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code);
}
else
{
//logerror("%s: Nothing in FIFO, idle\n", machine().describe_context());
m_icount = 0;
break;
}
@ -333,7 +346,7 @@ void ps2_vif1_device::execute_run()
decode_vifcode();
break;
case STAT_MODE_WAIT:
if (fifo_depth() == 0)
if (fifo_depth() < m_data_needed)
{
m_icount = 0;
break;
@ -351,6 +364,7 @@ void ps2_vif1_device::transfer_vifcode_data()
m_status &= ~STAT_MODE_MASK;
if (fifo_depth() < m_data_needed)
{
//logerror("%s: transfer: We need %d but only have %d, waiting\n", machine().describe_context(), m_data_needed, fifo_depth());
m_status |= STAT_MODE_WAIT;
m_icount = 0;
return;
@ -360,15 +374,18 @@ void ps2_vif1_device::transfer_vifcode_data()
{
case 0x20: /* STMASK */
m_mask = fifo_pop();
logerror("%s: STMASK: %08x\n", machine().describe_context(), m_mask);
m_data_needed = 0;
break;
case 0x30: /* STROW */
m_row_fill[m_data_index] = fifo_pop();
m_data_needed = 0;
logerror("%s: STMASK: %08x\n", machine().describe_context(), m_row_fill[m_data_index]);
m_data_needed--;
break;
case 0x31: /* STCOL */
m_col_fill[m_data_index] = fifo_pop();
m_data_needed = 0;
logerror("%s: STMASK: %08x\n", machine().describe_context(), m_col_fill[m_data_index]);
m_data_needed--;
break;
case 0x4a: /* MPG */
transfer_mpg();
@ -376,8 +393,13 @@ void ps2_vif1_device::transfer_vifcode_data()
default:
if ((m_command & 0x60) == 0x60)
{
logerror("%s: Unpack: %02x\n", machine().describe_context(), m_command);
transfer_unpack();
}
else
{
logerror("%s: Unknown command: %02x\n", machine().describe_context(), m_command);
}
break;
}
@ -397,6 +419,7 @@ void ps2_vif1_device::transfer_vifcode_data()
else if (fifo_depth() > 0)
{
m_code = fifo_pop();
logerror("%s: New VIFcode: %08x\n", machine().describe_context(), m_code);
m_status |= STAT_MODE_DECODE;
m_icount--;
}
@ -412,22 +435,28 @@ void ps2_vif1_device::transfer_unpack()
switch (m_unpack_format)
{
case FMT_V4_32:
logerror("%s: Unpacking V4-32.\n", machine().describe_context());
//logerror("%s: Unpacking V4-32.\n", machine().describe_context());
for (int element = 0; element < 4; element++)
{
fifo_pop();
//const uint32_t data = fifo_pop();
//m_vu->write_data(m_unpack_addr, data);
const uint32_t data = fifo_pop();
m_vu1->write_vu_mem(m_unpack_addr, data);
m_unpack_addr += 4;
m_unpack_count--;
}
m_unpack_count--;
break;
default:
logerror("%s: Unsupported unpack format: %02x\n", machine().describe_context(), m_unpack_format);
break;
}
m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0);
if (m_unpack_count > 0)
{
m_data_needed = FORMAT_SIZE[m_unpack_format] - (m_unpack_bits_remaining ? 1 : 0);
}
else
{
m_data_needed = 0;
}
}
void ps2_vif1_device::transfer_mpg()
@ -438,26 +467,27 @@ void ps2_vif1_device::transfer_mpg()
m_data_needed--;
}
m_mpg_insn = fifo_pop();
m_mpg_insn |= (uint64_t)fifo_pop() << 32;
m_mpg_addr += 8;
m_mpg_insn = (uint64_t)fifo_pop() << 32;
m_mpg_insn |= fifo_pop();
m_mpg_count--;
m_vu1->write_micro_mem(m_mpg_addr, m_mpg_insn);
logerror("%s: MPG, VU insn: %08x = %08x%08x, %d remaining\n", machine().describe_context(), m_mpg_addr, (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count);
m_mpg_addr += 8;
m_data_needed = m_mpg_count ? 2 : 0;
logerror("%s: MPG, VU insn: %08x%08x, %d remaining\n", machine().describe_context(), (uint32_t)(m_mpg_insn >> 32), (uint32_t)m_mpg_insn, m_mpg_count);
//m_vu->write_instruction(m_mpg_addr, m_mpg_insn);
}
void ps2_vif1_device::decode_vifcode()
{
//bool trigger_interrupt = BIT(m_code, 31);
bool trigger_interrupt = BIT(m_code, 31);
m_command = (m_code >> 24) & 0x7f;
m_status &= ~STAT_MODE_MASK;
switch (m_command)
{
case 0x00: /* NOP */
logerror("%s: NOP\n", machine().describe_context());
break;
case 0x01: /* STCYCL */
m_cycle = (uint16_t)m_code;
@ -519,6 +549,7 @@ void ps2_vif1_device::decode_vifcode()
m_unpack_add_tops = BIT(m_code, 15);
m_unpack_format = (uint8_t)(m_command & 0xf);
m_data_needed = FORMAT_SIZE[m_unpack_format];
logerror("%s: UNPACK (%08x), count %d\n", machine().describe_context(), m_code, m_unpack_count);
}
else
{ /* unknown */
@ -551,6 +582,11 @@ void ps2_vif1_device::decode_vifcode()
m_status |= STAT_MODE_IDLE;
m_icount = 0;
}
if (trigger_interrupt)
{
printf("******************\n");
}
}
uint32_t ps2_vif1_device::calculate_unpack_count()

View File

@ -15,16 +15,18 @@
#pragma once
#include "emu.h"
#include "cpu/mips/sonyvu.h"
#include "ps2gif.h"
class ps2_vif1_device : public device_t, public device_execute_interface
{
public:
template <typename T>
ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gif_tag)
template <typename T, typename U>
ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&gif_tag, U &&vu1_tag)
: ps2_vif1_device(mconfig, tag, owner, clock)
{
m_gif.set_tag(std::forward<T>(gif_tag));
m_vu1.set_tag(std::forward<U>(vu1_tag));
}
ps2_vif1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -37,6 +39,7 @@ public:
void dma_write(const uint64_t hi, const uint64_t lo);
void tag_write(uint32_t *data);
bool fifo_available(uint32_t count) const { return (BUFFER_SIZE - m_end) >= count; }
protected:
virtual void device_start() override;
@ -103,6 +106,7 @@ protected:
};
required_device<ps2_gif_device> m_gif;
required_device<sonyvu1_device> m_vu1;
int m_icount;

View File

@ -41,6 +41,7 @@ DEFINE_DEVICE_TYPE(SONYPS2_GS, ps2_gs_device, "ps2gs", "Playstation 2 GS")
ps2_gs_device::ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SONYPS2_GS, tag, owner, clock)
, m_intc(*this, finder_base::DUMMY_TAG)
{
}
@ -366,7 +367,7 @@ READ64_MEMBER(ps2_gs_device::priv_regs1_r)
switch (offset)
{
case 0x00:
ret = m_csr;
ret = m_csr | (CSR_REV | CSR_ID | CSR_FIFO_EMPTY);
logerror("%s: regs1_r: CSR (%08x%08x)\n", machine().describe_context(), (uint32_t)(ret >> 32), (uint32_t)ret);
break;
case 0x02:
@ -394,7 +395,8 @@ WRITE64_MEMBER(ps2_gs_device::priv_regs1_w)
{
case 0x00:
logerror("%s: regs1_w: CSR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
m_csr = data &~ CSR_RESET;
m_csr = data &~ (CSR_RESET | CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH);
//m_csr |= (CSR_SIGNAL | CSR_HSINT | CSR_VSINT | CSR_EDWINT | CSR_FLUSH);
break;
case 0x02:
logerror("%s: regs1_w: IMR = %08x%08x\n", machine().describe_context(), (uint32_t)(data >> 32), (uint32_t)data);
@ -724,7 +726,7 @@ void ps2_gs_device::vblank_end()
{
m_curr_field ^= 1;
if (m_curr_field)
m_csr |= CSR_FIELD_ODD;
else
m_csr &= ~CSR_FIELD_ODD;
else
m_csr |= CSR_FIELD_ODD;
}

View File

@ -15,11 +15,20 @@
#pragma once
#include "emu.h"
#include "machine/ps2intc.h"
class ps2_gs_device : public device_t
{
public:
ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename T>
ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc_tag)
: ps2_gs_device(mconfig, tag, owner, clock)
{
m_intc.set_tag(std::forward<T>(intc_tag));
}
ps2_gs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ64_MEMBER(priv_regs0_r);
DECLARE_WRITE64_MEMBER(priv_regs0_w);
@ -115,8 +124,22 @@ protected:
enum : uint32_t
{
CSR_RESET = 0x00000200,
CSR_FIELD_ODD = 0x00002000
CSR_SIGNAL = 0x00000001,
CSR_FINISH = 0x00000002,
CSR_HSINT = 0x00000004,
CSR_VSINT = 0x00000008,
CSR_EDWINT = 0x00000010,
CSR_FLUSH = 0x00000100,
CSR_RESET = 0x00000200,
CSR_NFIELD = 0x00001000,
CSR_FIELD_ODD = 0x00002000,
CSR_FIFO_MASK = 0x0000c000,
CSR_FIFO_MID = 0x00000000,
CSR_FIFO_EMPTY = 0x00004000,
CSR_FIFO_HI = 0x00008000,
CSR_FIFO_INV = 0x0000c000,
CSR_REV = 0x001b0000,
CSR_ID = 0x55000000
};
struct vertex_t
@ -137,6 +160,8 @@ protected:
uint8_t m_fog;
};
required_device<ps2_intc_device> m_intc;
std::unique_ptr<uint32_t[]> m_ram;
std::unique_ptr<vertex_t[]> m_vertices;