Added preliminary MB86235 recompiler [Ville Linde]

This commit is contained in:
Ville Linde 2016-12-17 22:06:48 +02:00
parent 3cb2a973fd
commit dbcf903c78
8 changed files with 3098 additions and 70 deletions

View File

@ -13,7 +13,7 @@
-- Dynamic recompiler objects
--------------------------------------------------
if (CPUS["SH2"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null) then
if (CPUS["SH2"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RSP"]~=null or CPUS["ARM7"]~=null or CPUS["ADSP21062"]~=null or CPUS["MB86235"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/drcbec.cpp",
MAME_DIR .. "src/devices/cpu/drcbec.h",
@ -1064,6 +1064,9 @@ if (CPUS["MB86235"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/mb86235/mb86235.cpp",
MAME_DIR .. "src/devices/cpu/mb86235/mb86235.h",
MAME_DIR .. "src/devices/cpu/mb86235/mb86235drc.cpp",
MAME_DIR .. "src/devices/cpu/mb86235/mb86235fe.cpp",
MAME_DIR .. "src/devices/cpu/mb86235/mb86235fe.h",
}
end

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese, ElSemi
// copyright-holders:Angelo Salese, ElSemi, Ville Linde
/*****************************************************************************
*
* MB86235 "TGPx4" (c) Fujitsu
@ -14,69 +14,163 @@
#include "emu.h"
#include "debugger.h"
#include "mb86235.h"
const device_type MB86235 = &device_creator<mb86235_cpu_device>;
#include "mb86235fe.h"
#define CACHE_SIZE (1 * 1024 * 1024)
#define COMPILE_BACKWARDS_BYTES 128
#define COMPILE_FORWARDS_BYTES 512
#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
#define COMPILE_MAX_SEQUENCE 64
#define mb86235_readop(A) m_program->read_dword(A)
#define mb86235_readmem(A) m_program->read_dword(A)
#define mb86235_writemem(A,B) m_program->write_dword((A),B)
const device_type MB86235 = &device_creator<mb86235_device>;
static ADDRESS_MAP_START(internal_abus, AS_DATA, 32, mb86235_device)
AM_RANGE(0x000000, 0x0003ff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START(internal_bbus, AS_IO, 32, mb86235_device)
AM_RANGE(0x000000, 0x0003ff) AM_RAM
ADDRESS_MAP_END
/***********************************
* illegal opcodes
***********************************/
void mb86235_cpu_device::mb86235_illegal()
{
//logerror("mb86235 illegal opcode at 0x%04x\n", m_pc);
m_icount -= 1;
}
/* Execute cycles */
void mb86235_cpu_device::execute_run()
void mb86235_device::execute_run()
{
uint32_t opcode;
do
{
debugger_instruction_hook(this, m_pc);
opcode = mb86235_readop(m_pc);
//m_pc++;
switch( opcode )
{
default:
mb86235_illegal();
break;
}
} while( m_icount > 0 );
run_drc();
}
void mb86235_cpu_device::device_start()
void mb86235_device::device_start()
{
m_program = &space(AS_PROGRAM);
m_direct = &m_program->direct();
m_dataa = &space(AS_DATA);
m_datab = &space(AS_IO);
m_core = (mb86235_internal_state *)m_cache.alloc_near(sizeof(mb86235_internal_state));
memset(m_core, 0, sizeof(mb86235_internal_state));
// init UML generator
uint32_t umlflags = 0;
m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 24, 0);
// add UML symbols
m_drcuml->symbol_add(&m_core->pc, sizeof(m_core->pc), "pc");
m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
for (int i = 0; i < 8; i++)
{
char buf[10];
sprintf(buf, "aa%d", i);
m_drcuml->symbol_add(&m_core->aa[i], sizeof(m_core->aa[i]), buf);
sprintf(buf, "ab%d", i);
m_drcuml->symbol_add(&m_core->ab[i], sizeof(m_core->ab[i]), buf);
sprintf(buf, "ma%d", i);
m_drcuml->symbol_add(&m_core->ma[i], sizeof(m_core->ma[i]), buf);
sprintf(buf, "mb%d", i);
m_drcuml->symbol_add(&m_core->mb[i], sizeof(m_core->mb[i]), buf);
sprintf(buf, "ar%d", i);
m_drcuml->symbol_add(&m_core->ar[i], sizeof(m_core->ar[i]), buf);
}
m_drcuml->symbol_add(&m_core->flags.az, sizeof(m_core->flags.az), "flags_az");
m_drcuml->symbol_add(&m_core->flags.an, sizeof(m_core->flags.an), "flags_an");
m_drcuml->symbol_add(&m_core->flags.av, sizeof(m_core->flags.av), "flags_av");
m_drcuml->symbol_add(&m_core->flags.au, sizeof(m_core->flags.au), "flags_au");
m_drcuml->symbol_add(&m_core->flags.ad, sizeof(m_core->flags.ad), "flags_ad");
m_drcuml->symbol_add(&m_core->flags.zc, sizeof(m_core->flags.zc), "flags_zc");
m_drcuml->symbol_add(&m_core->flags.il, sizeof(m_core->flags.il), "flags_il");
m_drcuml->symbol_add(&m_core->flags.nr, sizeof(m_core->flags.nr), "flags_nr");
m_drcuml->symbol_add(&m_core->flags.zd, sizeof(m_core->flags.zd), "flags_zd");
m_drcuml->symbol_add(&m_core->flags.mn, sizeof(m_core->flags.mn), "flags_mn");
m_drcuml->symbol_add(&m_core->flags.mz, sizeof(m_core->flags.mz), "flags_mz");
m_drcuml->symbol_add(&m_core->flags.mv, sizeof(m_core->flags.mv), "flags_mv");
m_drcuml->symbol_add(&m_core->flags.mu, sizeof(m_core->flags.mu), "flags_mu");
m_drcuml->symbol_add(&m_core->flags.md, sizeof(m_core->flags.md), "flags_md");
m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
m_drcuml->symbol_add(&m_core->arg2, sizeof(m_core->arg2), "arg2");
m_drcuml->symbol_add(&m_core->arg3, sizeof(m_core->arg3), "arg3");
m_drcuml->symbol_add(&m_core->alutemp, sizeof(m_core->alutemp), "alutemp");
m_drcuml->symbol_add(&m_core->multemp, sizeof(m_core->multemp), "multemp");
m_drcuml->symbol_add(&m_core->pcs_ptr, sizeof(m_core->pcs_ptr), "pcs_ptr");
m_drcfe = std::make_unique<mb86235_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE);
for (int i = 0; i < 8; i++)
{
m_regmap[i] = uml::mem(&m_core->aa[i]);
m_regmap[i + 8] = uml::mem(&m_core->ab[i]);
m_regmap[i + 16] = uml::mem(&m_core->ma[i]);
m_regmap[i + 24] = uml::mem(&m_core->mb[i]);
}
save_item(NAME(m_pc));
save_item(NAME(m_flags));
// Register state for debugger
//state_add( CP1610_R0, "PC", m_pc ).formatstr("%02X");
state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow();
state_add( STATE_GENFLAGS, "GENFLAGS", m_flags ).noshow();
state_add(MB86235_PC, "PC", m_core->pc).formatstr("%08X");
state_add(MB86235_AR0, "AR0", m_core->ar[0]).formatstr("%08X");
state_add(MB86235_AR1, "AR1", m_core->ar[1]).formatstr("%08X");
state_add(MB86235_AR2, "AR2", m_core->ar[2]).formatstr("%08X");
state_add(MB86235_AR3, "AR3", m_core->ar[3]).formatstr("%08X");
state_add(MB86235_AR4, "AR4", m_core->ar[4]).formatstr("%08X");
state_add(MB86235_AR5, "AR5", m_core->ar[5]).formatstr("%08X");
state_add(MB86235_AR6, "AR6", m_core->ar[6]).formatstr("%08X");
state_add(MB86235_AR7, "AR7", m_core->ar[7]).formatstr("%08X");
state_add(MB86235_AA0, "AA0", m_core->aa[0]).formatstr("%08X");
state_add(MB86235_AA1, "AA1", m_core->aa[1]).formatstr("%08X");
state_add(MB86235_AA2, "AA2", m_core->aa[2]).formatstr("%08X");
state_add(MB86235_AA3, "AA3", m_core->aa[3]).formatstr("%08X");
state_add(MB86235_AA4, "AA4", m_core->aa[4]).formatstr("%08X");
state_add(MB86235_AA5, "AA5", m_core->aa[5]).formatstr("%08X");
state_add(MB86235_AA6, "AA6", m_core->aa[6]).formatstr("%08X");
state_add(MB86235_AA7, "AA7", m_core->aa[7]).formatstr("%08X");
state_add(MB86235_AB0, "AB0", m_core->ab[0]).formatstr("%08X");
state_add(MB86235_AB1, "AB1", m_core->ab[1]).formatstr("%08X");
state_add(MB86235_AB2, "AB2", m_core->ab[2]).formatstr("%08X");
state_add(MB86235_AB3, "AB3", m_core->ab[3]).formatstr("%08X");
state_add(MB86235_AB4, "AB4", m_core->ab[4]).formatstr("%08X");
state_add(MB86235_AB5, "AB5", m_core->ab[5]).formatstr("%08X");
state_add(MB86235_AB6, "AB6", m_core->ab[6]).formatstr("%08X");
state_add(MB86235_AB7, "AB7", m_core->ab[7]).formatstr("%08X");
state_add(MB86235_MA0, "MA0", m_core->ma[0]).formatstr("%08X");
state_add(MB86235_MA1, "MA1", m_core->ma[1]).formatstr("%08X");
state_add(MB86235_MA2, "MA2", m_core->ma[2]).formatstr("%08X");
state_add(MB86235_MA3, "MA3", m_core->ma[3]).formatstr("%08X");
state_add(MB86235_MA4, "MA4", m_core->ma[4]).formatstr("%08X");
state_add(MB86235_MA5, "MA5", m_core->ma[5]).formatstr("%08X");
state_add(MB86235_MA6, "MA6", m_core->ma[6]).formatstr("%08X");
state_add(MB86235_MA7, "MA7", m_core->ma[7]).formatstr("%08X");
state_add(MB86235_MB0, "MB0", m_core->mb[0]).formatstr("%08X");
state_add(MB86235_MB1, "MB1", m_core->mb[1]).formatstr("%08X");
state_add(MB86235_MB2, "MB2", m_core->mb[2]).formatstr("%08X");
state_add(MB86235_MB3, "MB3", m_core->mb[3]).formatstr("%08X");
state_add(MB86235_MB4, "MB4", m_core->mb[4]).formatstr("%08X");
state_add(MB86235_MB5, "MB5", m_core->mb[5]).formatstr("%08X");
state_add(MB86235_MB6, "MB6", m_core->mb[6]).formatstr("%08X");
state_add(MB86235_MB7, "MB7", m_core->mb[7]).formatstr("%08X");
state_add(STATE_GENPC, "GENPC", m_core->pc ).noshow();
m_icountptr = &m_icount;
m_icountptr = &m_core->icount;
m_core->fp0 = 0.0f;
}
void mb86235_cpu_device::device_reset()
void mb86235_device::device_reset()
{
flush_cache();
m_core->pc = 0;
}
#if 0
@ -102,29 +196,62 @@ void mb86235_cpu_device::execute_set_input(int irqline, int state)
}
#endif
mb86235_cpu_device::mb86235_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
mb86235_device::mb86235_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, MB86235, "MB86235", tag, owner, clock, "mb86235", __FILE__)
, m_program_config("program", ENDIANNESS_LITTLE, 64, 32, -3)
, m_dataa_config("data_a", ENDIANNESS_LITTLE, 32, 24, -2, ADDRESS_MAP_NAME(internal_abus))
, m_datab_config("data_b", ENDIANNESS_LITTLE, 32, 10, -2, ADDRESS_MAP_NAME(internal_bbus))
, m_cache(CACHE_SIZE + sizeof(mb86235_internal_state))
, m_drcuml(nullptr)
, m_drcfe(nullptr)
{
}
void mb86235_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
void mb86235_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case STATE_GENFLAGS:
str = string_format("%c%c%c%c",
m_flags & 0x80 ? 'S':'.',
m_flags & 0x40 ? 'Z':'.',
m_flags & 0x20 ? 'V':'.',
m_flags & 0x10 ? 'C':'.');
str = string_format("?");
break;
}
}
offs_t mb86235_cpu_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
offs_t mb86235_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
{
extern CPU_DISASSEMBLE( mb86235 );
return CPU_DISASSEMBLE_NAME(mb86235)(this, stream, pc, oprom, opram, options);
}
void mb86235_device::fifoin_w(uint64_t data)
{
if (m_core->fifoin.num >= FIFOIN_SIZE)
{
fatalerror("fifoin_w: pushing to full fifo");
}
printf("FIFOIN push %08X%08X\n", (uint32_t)(data >> 32), (uint32_t)(data));
m_core->fifoin.data[m_core->fifoin.wpos] = data;
m_core->fifoin.wpos++;
m_core->fifoin.wpos &= FIFOIN_SIZE-1;
m_core->fifoin.num++;
}
bool mb86235_device::is_fifoin_full()
{
return m_core->fifoin.num >= FIFOIN_SIZE;
}
uint64_t mb86235_device::fifoout0_r()
{
fatalerror("fifoout0_r");
}
bool mb86235_device::is_fifoout0_empty()
{
return m_core->fifoout0.num == 0;
}

View File

@ -11,20 +11,62 @@
#ifndef __MB86235_H__
#define __MB86235_H__
#if 0
enum
{
MB86235_R0=1, MB86235_R1, MB86235_R2, MB86235_R3,
MB86235_R4, MB86235_R5, MB86235_R6, MB86235_R7
};
#endif
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
class mb86235_frontend;
class mb86235_cpu_device : public cpu_device
#define OP_USERFLAG_FIFOIN 0x1
#define OP_USERFLAG_FIFOOUT0 0x2
#define OP_USERFLAG_FIFOOUT1 0x4
#define OP_USERFLAG_REPEAT 0x8
#define OP_USERFLAG_REPEATED_OP 0x10
#define OP_USERFLAG_ALU_PRP_UPDATE 0x100
#define OP_USERFLAG_MUL_PRP_UPDATE 0x200
#define OP_USERFLAG_XFER_PRP_UPDATE 0x400
#define OP_USERFLAG_ALU_PWP_UPDATE 0x800
#define OP_USERFLAG_MUL_PWP_UPDATE 0x1000
#define OP_USERFLAG_XFER_PWP_UPDATE 0x2000
class mb86235_device : public cpu_device
{
friend class mb86235_frontend;
public:
// construction/destruction
mb86235_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
mb86235_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t clock);
void unimplemented_op();
void unimplemented_alu();
void unimplemented_control();
void unimplemented_xfer1();
void unimplemented_double_xfer1();
void unimplemented_double_xfer2();
void pcs_overflow();
void pcs_underflow();
void fifoin_w(uint64_t data);
bool is_fifoin_full();
uint64_t fifoout0_r();
bool is_fifoout0_empty();
enum
{
MB86235_PC = 1,
MB86235_AA0, MB86235_AA1, MB86235_AA2, MB86235_AA3, MB86235_AA4, MB86235_AA5, MB86235_AA6, MB86235_AA7,
MB86235_AB0, MB86235_AB1, MB86235_AB2, MB86235_AB3, MB86235_AB4, MB86235_AB5, MB86235_AB6, MB86235_AB7,
MB86235_MA0, MB86235_MA1, MB86235_MA2, MB86235_MA3, MB86235_MA4, MB86235_MA5, MB86235_MA6, MB86235_MA7,
MB86235_MB0, MB86235_MB1, MB86235_MB2, MB86235_MB3, MB86235_MB4, MB86235_MB5, MB86235_MB6, MB86235_MB7,
MB86235_AR0, MB86235_AR1, MB86235_AR2, MB86235_AR3, MB86235_AR4, MB86235_AR5, MB86235_AR6, MB86235_AR7,
};
const int FIFOIN_SIZE = 16;
const int FIFOOUT0_SIZE = 16;
const int FIFOOUT1_SIZE = 16;
protected:
// device-level overrides
@ -39,7 +81,7 @@ protected:
//virtual void execute_set_input(int inputnum, int state);
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : nullptr; }
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override { return (spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_DATA) ? &m_dataa_config : (spacenum == AS_IO) ? &m_datab_config : nullptr); }
// device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
@ -49,16 +91,154 @@ protected:
virtual uint32_t disasm_max_opcode_bytes() const override { return 8; }
virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
direct_read_data *m_direct;
private:
struct mb86235_flags
{
uint32_t az;
uint32_t an;
uint32_t av;
uint32_t au;
uint32_t ad;
uint32_t zc;
uint32_t il;
uint32_t nr;
uint32_t zd;
uint32_t mn;
uint32_t mz;
uint32_t mv;
uint32_t mu;
uint32_t md;
};
struct fifo
{
int rpos;
int wpos;
int num;
uint64_t data[16];
};
struct mb86235_internal_state
{
uint32_t pc;
uint32_t aa[8];
uint32_t ab[8];
uint32_t ma[8];
uint32_t mb[8];
uint32_t ar[8];
uint32_t sp;
uint32_t eb;
uint32_t eo;
uint32_t rpc;
uint32_t lpc;
uint32_t prp;
uint32_t pwp;
uint32_t pr[24];
uint32_t mod;
mb86235_flags flags;
int icount;
uint32_t arg0;
uint32_t arg1;
uint32_t arg2;
uint32_t arg3;
uint64_t arg64;
uint32_t pcs[4];
int pcs_ptr;
uint32_t jmpdest;
uint32_t alutemp;
uint32_t multemp;
uint32_t condtemp;
uint32_t pdr;
uint32_t ddr;
float fp0;
fifo fifoin;
fifo fifoout0;
fifo fifoout1;
};
mb86235_internal_state *m_core;
drc_cache m_cache;
std::unique_ptr<drcuml_state> m_drcuml;
std::unique_ptr<mb86235_frontend> m_drcfe;
uml::parameter m_regmap[32];
uml::code_handle *m_entry; /* entry point */
uml::code_handle *m_nocode; /* nocode exception handler */
uml::code_handle *m_out_of_cycles; /* out of cycles exception handler */
uml::code_handle *m_clear_fifo_in;
uml::code_handle *m_clear_fifo_out0;
uml::code_handle *m_clear_fifo_out1;
uml::code_handle *m_read_fifo_in;
uml::code_handle *m_write_fifo_out0;
uml::code_handle *m_write_fifo_out1;
uml::code_handle *m_read_abus;
uml::code_handle *m_write_abus;
address_space_config m_program_config;
address_space_config m_dataa_config;
address_space_config m_datab_config;
uint8_t m_pc; /* registers */
uint8_t m_flags; /* flags */
address_space *m_program;
int m_icount;
address_space *m_dataa;
address_space *m_datab;
void mb86235_illegal();
/* internal compiler state */
struct compiler_state
{
uint32_t cycles; /* accumulated cycles */
uint8_t checkints; /* need to check interrupts before next instruction */
uml::code_label labelnum; /* index for local labels */
};
void run_drc();
void flush_cache();
void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name);
void compile_block(offs_t pc);
void load_fast_iregs(drcuml_block *block);
void save_fast_iregs(drcuml_block *block);
void static_generate_entry_point();
void static_generate_nocode_handler();
void static_generate_out_of_cycles();
void static_generate_fifo();
void static_generate_memory_accessors();
void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception);
bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_alu(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int aluop, bool alu_temp);
void generate_mul(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int mulop, bool mul_temp);
void generate_pre_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_control(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_double_xfer1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_double_xfer2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_xfer3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void generate_ea(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int md, int arx, int ary, int disp);
void generate_reg_read(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst);
void generate_reg_write(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter src);
void generate_alumul_input(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int reg, uml::parameter dst, bool fp, bool mul);
uml::parameter get_alu1_input(int reg);
uml::parameter get_alu_output(int reg);
uml::parameter get_mul1_input(int reg);
void generate_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int cc, bool not, uml::code_label skip_label, bool condtemp);
void generate_branch_target(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int type, int ef2);
bool has_register_clash(const opcode_desc *desc, int outreg);
bool aluop_has_result(int aluop);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,845 @@
// license:BSD-3-Clause
// copyright-holders:Ville Linde
/******************************************************************************
Front-end for MB86235 recompiler
******************************************************************************/
#include "emu.h"
#include "mb86235fe.h"
#define AA_USED(desc,x) do { (desc).regin[0] |= 1 << (x); } while(0)
#define AA_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (x); } while(0)
#define AB_USED(desc,x) do { (desc).regin[0] |= 1 << (8+x); } while(0)
#define AB_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (8+x); } while(0)
#define MA_USED(desc,x) do { (desc).regin[0] |= 1 << (16+x); } while(0)
#define MA_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (16+x); } while(0)
#define MB_USED(desc,x) do { (desc).regin[0] |= 1 << (24+x); } while(0)
#define MB_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (24+x); } while(0)
#define AR_USED(desc,x) do { (desc).regin[1] |= 1 << (24+x); } while(0)
#define AR_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << (24+x); } while(0)
#define AZ_USED(desc) do { (desc).regin[1] |= 1 << 0; } while (0)
#define AZ_MODIFIED(desc) do { (desc).regout[1] |= 1 << 0; } while (0)
#define AN_USED(desc) do { (desc).regin[1] |= 1 << 1; } while (0)
#define AN_MODIFIED(desc) do { (desc).regout[1] |= 1 << 1; } while (0)
#define AV_USED(desc) do { (desc).regin[1] |= 1 << 2; } while (0)
#define AV_MODIFIED(desc) do { (desc).regout[1] |= 1 << 2; } while (0)
#define AU_USED(desc) do { (desc).regin[1] |= 1 << 3; } while (0)
#define AU_MODIFIED(desc) do { (desc).regout[1] |= 1 << 3; } while (0)
#define AD_USED(desc) do { (desc).regin[1] |= 1 << 4; } while (0)
#define AD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 4; } while (0)
#define ZC_USED(desc) do { (desc).regin[1] |= 1 << 5; } while (0)
#define ZC_MODIFIED(desc) do { (desc).regout[1] |= 1 << 5; } while (0)
#define IL_USED(desc) do { (desc).regin[1] |= 1 << 6; } while (0)
#define IL_MODIFIED(desc) do { (desc).regout[1] |= 1 << 6; } while (0)
#define NR_USED(desc) do { (desc).regin[1] |= 1 << 7; } while (0)
#define NR_MODIFIED(desc) do { (desc).regout[1] |= 1 << 7; } while (0)
#define ZD_USED(desc) do { (desc).regin[1] |= 1 << 8; } while (0)
#define ZD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 8; } while (0)
#define MN_USED(desc) do { (desc).regin[1] |= 1 << 9; } while (0)
#define MN_MODIFIED(desc) do { (desc).regout[1] |= 1 << 9; } while (0)
#define MZ_USED(desc) do { (desc).regin[1] |= 1 << 10; } while (0)
#define MZ_MODIFIED(desc) do { (desc).regout[1] |= 1 << 10; } while (0)
#define MV_USED(desc) do { (desc).regin[1] |= 1 << 11; } while (0)
#define MV_MODIFIED(desc) do { (desc).regout[1] |= 1 << 11; } while (0)
#define MU_USED(desc) do { (desc).regin[1] |= 1 << 12; } while (0)
#define MU_MODIFIED(desc) do { (desc).regout[1] |= 1 << 12; } while (0)
#define MD_USED(desc) do { (desc).regin[1] |= 1 << 13; } while (0)
#define MD_MODIFIED(desc) do { (desc).regout[1] |= 1 << 13; } while (0)
mb86235_frontend::mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
: drc_frontend(*core, window_start, window_end, max_sequence),
m_core(core)
{
}
bool mb86235_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
{
uint64_t opcode = desc.opptr.q[0] = m_core->m_direct->read_qword(desc.pc * 8, 0);
desc.length = 1;
desc.cycles = 1;
// repeatable instruction needs an entry point
if (prev != nullptr)
{
if (prev->userflags & OP_USERFLAG_REPEAT)
{
desc.flags |= OPFLAG_IS_BRANCH_TARGET;
desc.userflags |= OP_USERFLAG_REPEATED_OP;
}
}
switch ((opcode >> 61) & 7)
{
case 0: // ALU / MUL / double transfer (type 1)
describe_alu(desc, (opcode >> 42) & 0x7ffff);
describe_mul(desc, (opcode >> 27) & 0x7fff);
describe_double_xfer1(desc);
break;
case 1: // ALU / MUL / transfer (type 1)
describe_alu(desc, (opcode >> 42) & 0x7ffff);
describe_mul(desc, (opcode >> 27) & 0x7fff);
describe_xfer1(desc);
break;
case 2: // ALU / MUL / control
describe_alu(desc, (opcode >> 42) & 0x7ffff);
describe_mul(desc, (opcode >> 27) & 0x7fff);
describe_control(desc);
break;
case 4: // ALU or MUL / double transfer (type 2)
if (opcode & ((uint64_t)(1) << 41))
describe_alu(desc, (opcode >> 42) & 0x7ffff);
else
describe_mul(desc, (opcode >> 42) & 0x7fff);
describe_double_xfer2(desc);
break;
case 5: // ALU or MUL / transfer (type 2)
if (opcode & ((uint64_t)(1) << 41))
describe_alu(desc, (opcode >> 42) & 0x7ffff);
else
describe_mul(desc, (opcode >> 42) & 0x7fff);
describe_xfer2(desc);
break;
case 6: // ALU or MUL / control
if (opcode & ((uint64_t)(1) << 41))
describe_alu(desc, (opcode >> 42) & 0x7ffff);
else
describe_mul(desc, (opcode >> 42) & 0x7fff);
describe_control(desc);
break;
case 7: // transfer (type 3)
describe_xfer3(desc);
break;
default:
return false;
}
return true;
}
void mb86235_frontend::describe_alu_input(opcode_desc &desc, int reg)
{
switch (reg)
{
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
AA_USED(desc, reg & 7);
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
AB_USED(desc, reg & 7);
break;
case 0x10: // PR
case 0x11: // PR++
case 0x12: // PR--
case 0x13: // PR#0
desc.userflags |= OP_USERFLAG_ALU_PRP_UPDATE;
break;
default:
break;
}
}
void mb86235_frontend::describe_mul_input(opcode_desc &desc, int reg)
{
switch (reg)
{
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
MA_USED(desc, reg & 7);
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
MB_USED(desc, reg & 7);
break;
case 0x10: // PR
case 0x11: // PR++
case 0x12: // PR--
case 0x13: // PR#0
desc.userflags |= OP_USERFLAG_MUL_PRP_UPDATE;
break;
default:
break;
}
}
void mb86235_frontend::describe_alumul_output(opcode_desc &desc, int reg)
{
switch (reg >> 3)
{
case 0:
MA_MODIFIED(desc, reg & 7);
break;
case 1:
MB_MODIFIED(desc, reg & 7);
break;
case 2:
AA_MODIFIED(desc, reg & 7);
break;
case 3:
AB_MODIFIED(desc, reg & 7);
break;
default:
break;
}
}
void mb86235_frontend::describe_reg_read(opcode_desc &desc, int reg)
{
switch (reg)
{
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
// MA0-7
MA_USED(desc, reg & 7);
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
// AA0-7
AA_USED(desc, reg & 7);
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
// AR0-7
AR_USED(desc, reg & 7);
break;
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
// MB0-7
MB_USED(desc, reg & 7);
break;
case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
// AB0-7
AB_USED(desc, reg & 7);
break;
case 0x31: // FI
desc.userflags |= OP_USERFLAG_FIFOIN;
desc.flags |= OPFLAG_IS_BRANCH_TARGET; // fifo check makes this a branch target
break;
case 0x32: // FO0
break;
case 0x33: // FO1
break;
case 0x10: // EB
case 0x11: // EBU
case 0x12: // EBL
case 0x13: // EO
case 0x15: // ST
case 0x16: // MOD
case 0x17: // LRPC
case 0x34: // PDR
case 0x35: // DDR
case 0x36: // PRP
case 0x37: // PWP
break;
case 0x30: // PR
desc.userflags |= OP_USERFLAG_XFER_PRP_UPDATE;
break;
}
}
void mb86235_frontend::describe_reg_write(opcode_desc &desc, int reg)
{
switch (reg)
{
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
// MA0-7
MA_MODIFIED(desc, reg & 7);
break;
case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
// AA0-7
AA_MODIFIED(desc, reg & 7);
break;
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
// AR0-7
AR_MODIFIED(desc, reg & 7);
break;
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
// MB0-7
MB_MODIFIED(desc, reg & 7);
break;
case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
// AB0-7
AB_MODIFIED(desc, reg & 7);
break;
case 0x31: // FI
break;
case 0x32: // FO0
desc.userflags |= OP_USERFLAG_FIFOOUT0;
desc.flags |= OPFLAG_IS_BRANCH_TARGET; // fifo check makes this a branch target
break;
case 0x33: // FO1
desc.userflags |= OP_USERFLAG_FIFOOUT1;
desc.flags |= OPFLAG_IS_BRANCH_TARGET; // fifo check makes this a branch target
break;
case 0x10: // EB
case 0x11: // EBU
case 0x12: // EBL
case 0x13: // EO
case 0x15: // ST
case 0x16: // MOD
case 0x17: // LRPC
case 0x34: // PDR
case 0x35: // DDR
case 0x36: // PRP
case 0x37: // PWP
break;
case 0x30: // PR
desc.userflags |= OP_USERFLAG_XFER_PWP_UPDATE;
break;
}
}
void mb86235_frontend::describe_alu(opcode_desc &desc, uint32_t aluop)
{
int i1 = (aluop >> 10) & 0xf;
int i2 = (aluop >> 5) & 0x1f;
int io = aluop & 0x1f;
int op = (aluop >> 14) & 0x1f;
switch (op)
{
case 0x00: // FADD
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x01: // FADDZ
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
ZC_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x02: // FSUB
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x03: // FSUBZ
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
ZC_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x04: // FCMP
describe_alu_input(desc, i1); describe_alu_input(desc, i2);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x05: // FABS
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x06: // FABC
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x07: // NOP
break;
case 0x08: // FEA
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x09: // FES
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x0a: // FRCP
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
ZD_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x0b: // FRSQ
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
NR_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AU_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x0c: // FLOG
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
IL_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x0d: // CIF
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
break;
case 0x0e: // CFI
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AD_MODIFIED(desc);
break;
case 0x0f: // CFIB
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AD_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x10: // ADD
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x11: // ADDZ
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
ZC_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x12: // SUB
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x13: // SUBZ
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
ZC_MODIFIED(desc);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x14: // CMP
describe_alu_input(desc, i1); describe_alu_input(desc, i2);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x15: // ABS
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
break;
case 0x16: // ATR
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
break;
case 0x17: // ATRZ
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
ZC_MODIFIED(desc);
break;
case 0x18: // AND
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x19: // OR
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x1a: // XOR
describe_alu_input(desc, i1); describe_alu_input(desc, i2); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x1b: // NOT
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x1c: // LSR
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x1d: // LSL
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
AV_MODIFIED(desc);
AU_MODIFIED(desc);
break;
case 0x1e: // ASR
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
break;
case 0x1f: // ASL
describe_alu_input(desc, i1); describe_alumul_output(desc, io);
AN_MODIFIED(desc);
AZ_MODIFIED(desc);
break;
}
}
void mb86235_frontend::describe_mul(opcode_desc &desc, uint32_t mulop)
{
int i1 = (mulop >> 10) & 0xf;
int i2 = (mulop >> 5) & 0x1f;
int io = mulop & 0x1f;
int m = mulop & 0x4000;
describe_mul_input(desc, i1);
describe_mul_input(desc, i2);
describe_alumul_output(desc, io);
if (m)
{
// FMUL
MN_MODIFIED(desc);
MZ_MODIFIED(desc);
MV_MODIFIED(desc);
MU_MODIFIED(desc);
MD_MODIFIED(desc);
}
else
{
// MUL
MN_MODIFIED(desc);
MZ_MODIFIED(desc);
MV_MODIFIED(desc);
}
}
void mb86235_frontend::describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp)
{
switch (md)
{
case 0x0: // @ARx
AR_USED(desc, arx);
break;
case 0x1: // @ARx++
AR_USED(desc, arx); AR_MODIFIED(desc, arx);
break;
case 0x2: // @ARx--
AR_USED(desc, arx); AR_MODIFIED(desc, arx);
break;
case 0x3: // @ARx++disp
AR_USED(desc, arx); AR_MODIFIED(desc, arx);
break;
case 0x4: // @ARx+ARy
AR_USED(desc, arx); AR_USED(desc, ary);
break;
case 0x5: // @ARx+ARy++
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
case 0x6: // @ARx+ARy--
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
case 0x7: // @ARx+ARy++disp
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
case 0x8: // @ARx+ARyU
AR_USED(desc, arx); AR_USED(desc, ary);
break;
case 0x9: // @ARx+ARyL
AR_USED(desc, arx); AR_USED(desc, ary);
break;
case 0xa: // @ARx+disp
AR_USED(desc, arx);
break;
case 0xb: // @ARx+ARy+disp
AR_USED(desc, arx); AR_USED(desc, ary);
break;
case 0xc: // @disp
break;
case 0xd: // @ARx+[ARy++]
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
case 0xe: // @ARx+[ARy--]
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
case 0xf: // @ARx+[ARy++disp]
AR_USED(desc, arx); AR_USED(desc, ary); AR_MODIFIED(desc, ary);
break;
}
}
void mb86235_frontend::describe_xfer1(opcode_desc &desc)
{
uint64_t opcode = desc.opptr.q[0];
fatalerror("mb86235_frontend: describe_xfer1 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
}
void mb86235_frontend::describe_double_xfer1(opcode_desc &desc)
{
uint64_t opcode = desc.opptr.q[0];
fatalerror("mb86235_frontend: describe_double_xfer1 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
}
void mb86235_frontend::describe_xfer2(opcode_desc &desc)
{
uint64_t opcode = desc.opptr.q[0];
int op = (opcode >> 39) & 3;
int trm = (opcode >> 38) & 1;
int dir = (opcode >> 37) & 1;
int sr = (opcode >> 31) & 0x7f;
int dr = (opcode >> 24) & 0x7f;
int ary = (opcode >> 4) & 7;
int md = opcode & 0xf;
int disp14 = (opcode >> 7) & 0x3fff;
if (op == 0) // MOV2
{
if (trm == 0)
{
if ((sr & 0x40) == 0)
{
describe_reg_read(desc, sr & 0x3f);
}
else if (sr == 0x58)
{
// MOV2 #imm24, DR
}
else
{
describe_ea(desc, md, sr & 7, ary, disp14);
desc.flags |= OPFLAG_READS_MEMORY;
}
if ((dr & 0x40) == 0)
{
describe_reg_write(desc, dr & 0x3f);
}
else
{
describe_ea(desc, md, dr & 7, ary, disp14);
desc.flags |= OPFLAG_WRITES_MEMORY;
}
}
else
{
// external transfer
if (dir == 0)
{
describe_reg_read(desc, dr & 0x3f);
desc.flags |= OPFLAG_WRITES_MEMORY;
}
else
{
describe_reg_write(desc, dr & 0x3f);
desc.flags |= OPFLAG_READS_MEMORY;
}
}
}
else if (op == 2) // MOV4
{
fatalerror("mb86235_frontend: describe_xfer2 MOV4 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
}
}
void mb86235_frontend::describe_double_xfer2(opcode_desc &desc)
{
uint64_t opcode = desc.opptr.q[0];
fatalerror("mb86235_frontend: describe_double_xfer2 at %08X (%08X%08X)", desc.pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
}
void mb86235_frontend::describe_xfer3(opcode_desc &desc)
{
uint64_t opcode = desc.opptr.q[0];
int dr = (opcode >> 19) & 0x7f;
int disp = (opcode >> 7) & 0xfff;
int ary = (opcode >> 4) & 7;
int md = opcode & 0xf;
switch (dr >> 4)
{
case 0:
case 1: // reg
describe_reg_write(desc, dr & 0x3f);
break;
case 2: // RAM-A
case 3: // RAM-B
desc.flags |= OPFLAG_WRITES_MEMORY;
describe_ea(desc, md, dr & 7, ary, disp);
break;
}
}
void mb86235_frontend::describe_control(opcode_desc &desc)
{
int ef1 = (desc.opptr.q[0] >> 16) & 0x3f;
int ef2 = desc.opptr.q[0] & 0xffff;
int cop = (desc.opptr.q[0] >> 22) & 0x1f;
int rel12 = (desc.opptr.q[0] & 0x800) ? (0xfffff000 | (desc.opptr.q[0] & 0xfff)) : (desc.opptr.q[0] & 0xfff);
switch (cop)
{
case 0x00: // NOP
break;
case 0x01: // REP
if (ef1 != 0) // ARx
AR_USED(desc, (ef2 >> 12) & 7);
desc.userflags |= OP_USERFLAG_REPEAT;
break;
case 0x02: // SETL
if (ef1 != 0) // ARx
AR_USED(desc, (ef2 >> 12) & 7);
break;
case 0x03: // CLRFI/CLRFO/CLRF
break;
case 0x04: // PUSH
describe_reg_read(desc, (ef2 >> 6) & 0x3f);
break;
case 0x05: // POP
describe_reg_write(desc, (ef2 >> 6) & 0x3f);
break;
case 0x08: // SETM #imm16
break;
case 0x09: // SETM #imm3, CBSA
break;
case 0x0a: // SETM #imm3, CBSB
break;
case 0x0b: // SETM #imm1, RF
break;
case 0x0c: // SETM #imm1, RDY
break;
case 0x0d: // SETM #imm1, WAIT
break;
case 0x13: // DBLP rel12
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.targetpc = desc.pc + rel12;
desc.delayslots = 1;
break;
case 0x14: // DBBC ARx:y, rel12
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.targetpc = desc.pc + rel12;
desc.delayslots = 1;
AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7));
break;
case 0x15: // DBBS ARx:y, rel12
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.targetpc = desc.pc + rel12;
desc.delayslots = 1;
AR_USED(desc, ((desc.opptr.q[0] >> 13) & 7));
break;
case 0x1b: // DRET
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.targetpc = BRANCH_TARGET_DYNAMIC;
desc.delayslots = 1;
break;
case 0x10: // DBcc
case 0x11: // DBNcc
case 0x18: // DCcc
case 0x19: // DCNcc
{
switch ((desc.opptr.q[0] >> 12) & 0xf)
{
case 0x0: desc.targetpc = ef2 & 0xfff; break;
case 0x1: desc.targetpc = desc.pc + rel12; break;
case 0x2: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x3: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x4: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x5: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x6: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x7: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x8: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0x9: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xa: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xb: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xc: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xd: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xe: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
}
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.delayslots = 1;
break;
}
case 0x1a: // DCALL
case 0x12: // DJMP
{
switch ((desc.opptr.q[0] >> 12) & 0xf)
{
case 0x0: desc.targetpc = ef2 & 0xfff; break;
case 0x1: desc.targetpc = desc.pc + rel12; break;
case 0x2: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x3: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x4: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x5: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x6: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x7: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0x8: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0x9: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xa: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xb: desc.targetpc = BRANCH_TARGET_DYNAMIC; break;
case 0xc: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xd: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xe: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
case 0xf: desc.targetpc = BRANCH_TARGET_DYNAMIC; describe_reg_read(desc, (ef2 >> 6) & 0x3f); break;
}
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.delayslots = 1;
break;
}
}
}

View File

@ -0,0 +1,47 @@
// license:BSD-3-Clause
// copyright-holders:Ville Linde
/******************************************************************************
Front-end for MB86235 recompiler
******************************************************************************/
#pragma once
#include "mb86235.h"
#include "cpu/drcfe.h"
#ifndef __MB86235FE_H__
#define __MB86235FE_H__
class mb86235_frontend : public drc_frontend
{
public:
mb86235_frontend(mb86235_device *core, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
protected:
// required overrides
virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
private:
mb86235_device *m_core;
void describe_alu(opcode_desc &desc, uint32_t aluop);
void describe_mul(opcode_desc &desc, uint32_t mulop);
void describe_xfer1(opcode_desc &desc);
void describe_double_xfer1(opcode_desc &desc);
void describe_xfer2(opcode_desc &desc);
void describe_double_xfer2(opcode_desc &desc);
void describe_xfer3(opcode_desc &desc);
void describe_control(opcode_desc &desc);
void describe_alu_input(opcode_desc &desc, int reg);
void describe_mul_input(opcode_desc &desc, int reg);
void describe_alumul_output(opcode_desc &desc, int reg);
void describe_reg_read(opcode_desc &desc, int reg);
void describe_reg_write(opcode_desc &desc, int reg);
void describe_ea(opcode_desc &desc, int md, int arx, int ary, int disp);
};
#endif /* __MB86235FE_H__ */

View File

@ -752,14 +752,42 @@ WRITE32_MEMBER(model2_state::copro_function_port_w)
//logerror("copro_function_port_w: %08X, %08X, %08X\n", data, offset, mem_mask);
if (m_dsp_type == DSP_TYPE_SHARC)
copro_fifoin_push(machine().device("dsp"), d,offset,mem_mask);
else
else if (m_dsp_type == DSP_TYPE_TGP)
copro_fifoin_push(machine().device("tgp"), d,offset,mem_mask);
else if (m_dsp_type == DSP_TYPE_TGPX4)
{
if (m_tgpx4->is_fifoin_full())
printf("trying to push to full fifo! (function port)\n");
m_tgpx4->fifoin_w(d);
}
}
READ32_MEMBER(model2_state::copro_fifo_r)
{
//logerror("copro_fifo_r: %08X, %08X\n", offset, mem_mask);
return copro_fifoout_pop(space,offset,mem_mask);
if (m_dsp_type == DSP_TYPE_SHARC || m_dsp_type == DSP_TYPE_TGP)
{
return copro_fifoout_pop(space, offset, mem_mask);
}
else
{
// TODO
printf("FIFO OUT read\n");
if (m_tgpx4->is_fifoout0_empty())
{
/* Reading from empty FIFO causes the i960 to enter wait state */
downcast<i960_cpu_device &>(space.device()).i960_stall();
/* spin the main cpu and let the TGP catch up */
space.device().execute().spin_until_time(attotime::from_usec(100));
printf("stalled\n");
}
else
{
return (uint32_t)(m_tgpx4->fifoout0_r());
}
}
return 0;
}
WRITE32_MEMBER(model2_state::copro_fifo_w)
@ -774,6 +802,19 @@ WRITE32_MEMBER(model2_state::copro_fifo_w)
{
m_tgp_program[m_coprocnt] = data;
}
else if (m_dsp_type == DSP_TYPE_TGPX4)
{
if (m_coprocnt & 1)
{
m_tgpx4_program[m_coprocnt / 2] &= 0xffffffffU;
m_tgpx4_program[m_coprocnt / 2] |= u64(data) << 32;
}
else
{
m_tgpx4_program[m_coprocnt / 2] &= 0xffffffff00000000U;
m_tgpx4_program[m_coprocnt / 2] |= data;
}
}
m_coprocnt++;
}
@ -785,8 +826,16 @@ WRITE32_MEMBER(model2_state::copro_fifo_w)
//osd_printf_debug("copro_fifo_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, space.device().safe_pc());
if (m_dsp_type == DSP_TYPE_SHARC)
copro_fifoin_push(machine().device("dsp"), data,offset,mem_mask);
else
else if (m_dsp_type == DSP_TYPE_TGP)
copro_fifoin_push(machine().device("tgp"), data,offset,mem_mask);
else if (m_dsp_type == DSP_TYPE_TGPX4)
{
if (m_tgpx4->is_fifoin_full())
printf("trying to push to full fifo!\n");
printf("push %08X at %08X\n", data, space.device().safe_pc());
m_tgpx4->fifoin_w(data);
}
}
}
@ -1624,7 +1673,8 @@ static ADDRESS_MAP_START( model2c_crx_mem, AS_PROGRAM, 32, model2_state )
AM_RANGE(0x00200000, 0x0023ffff) AM_RAM
AM_RANGE(0x00804000, 0x00807fff) AM_READWRITE(geo_prg_r, geo_prg_w)
AM_RANGE(0x00884000, 0x00887fff) AM_READWRITE(copro_prg_r, copro_prg_w)
AM_RANGE(0x00880000, 0x00883fff) AM_WRITE(copro_function_port_w)
AM_RANGE(0x00884000, 0x00887fff) AM_READWRITE(copro_fifo_r, copro_fifo_w)
AM_RANGE(0x00980000, 0x00980003) AM_READWRITE(copro_ctl1_r,copro_ctl1_w)
AM_RANGE(0x00980008, 0x0098000b) AM_WRITE(geo_ctl1_w )

View File

@ -5,6 +5,7 @@
#include "audio/segam1audio.h"
#include "machine/eepromser.h"
#include "cpu/i960/i960.h"
#include "cpu/mb86235/mb86235.h"
#include "sound/scsp.h"
#include "machine/315-5881_crypt.h"
#include "machine/315-5838_317-0229_comp.h"
@ -67,7 +68,7 @@ public:
optional_device<cpu_device> m_audiocpu;
optional_device<cpu_device> m_tgp;
optional_device<cpu_device> m_dsp;
optional_device<cpu_device> m_tgpx4;
optional_device<mb86235_device> m_tgpx4;
optional_device<cpu_device> m_drivecpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<screen_device> m_screen;