mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
-dspp: Preliminary DRC. Still disabled by default. [Ryan Holtz]
This commit is contained in:
parent
46ade7d73d
commit
1cd0c11908
@ -33,8 +33,8 @@ enum
|
||||
#define SINGLE_INSTRUCTION_MODE (0)
|
||||
|
||||
|
||||
#define CACHE_SIZE (4 * 1024 * 1024) // FIXME
|
||||
// FIXME!!!
|
||||
#define CACHE_SIZE (4 * 1024 * 1024)
|
||||
|
||||
/* compilation boundaries -- how far back/forward does the analysis extend? */
|
||||
#define COMPILE_BACKWARDS_BYTES 128
|
||||
#define COMPILE_FORWARDS_BYTES 512
|
||||
@ -47,56 +47,6 @@ enum
|
||||
#define EXECUTE_UNMAPPED_CODE 2
|
||||
#define EXECUTE_RESET_CACHE 3
|
||||
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS
|
||||
//**************************************************************************
|
||||
|
||||
//#define DSPI_FLAG_CC_CARRY 0x0001
|
||||
//#define DSPI_FLAG_CC_ZERO 0x0002
|
||||
//#define DSPI_FLAG_CC_NEG 0x0004
|
||||
//#define DSPI_FLAG_CC_OVER 0x0008
|
||||
//#define DSPI_FLAG_CC_EXACT 0x0010
|
||||
//#define DSPI_FLAG_AUDLOCK 0x0020
|
||||
//#define DSPI_FLAG_SLEEP 0x0040
|
||||
//#define DSPI_FLAG_CC_MASK 0x001f
|
||||
|
||||
#define DSPX_CONTROL_GWILLING 0x0001
|
||||
#define DSPX_CONTROL_STEP_CYCLE 0x0002
|
||||
#define DSPX_CONTROL_STEP_PC 0x0004
|
||||
#define DSPX_CONTROL_SNOOP 0x0008
|
||||
|
||||
#define DSPX_RESET_DSPP 0x0001
|
||||
#define DSPX_RESET_INPUT 0x0002
|
||||
#define DSPX_RESET_OUTPUT 0x0004
|
||||
|
||||
#define DSPX_F_DMA_NEXTVALID 0x0001
|
||||
#define DSPX_F_DMA_GO_FOREVER 0x0002
|
||||
#define DSPX_F_INT_DMANEXT_EN 0x0004
|
||||
#define DSPX_F_SHADOW_SET_DMANEXT 0x00040000
|
||||
#define DSPX_F_SHADOW_SET_FOREVER 0x00020000
|
||||
#define DSPX_F_SHADOW_SET_NEXTVALID 0x00010000
|
||||
#define DSPX_F_SHADOW_SET_ADDRESS_COUNT 0x80000000
|
||||
|
||||
#define DSPX_F_INT_TIMER 0x00000100
|
||||
#define DSPX_F_INT_INPUT_UNDER 0x00000080
|
||||
#define DSPX_F_INT_INPUT_OVER 0x00000040
|
||||
#define DSPX_F_INT_OUTPUT_UNDER 0x00000020
|
||||
#define DSPX_F_INT_OUTPUT_OVER 0x00000010
|
||||
#define DSPX_F_INT_UNDEROVER 0x00000008
|
||||
#define DSPX_F_INT_CONSUMED 0x00000002
|
||||
#define DSPX_F_INT_DMANEXT 0x00000001
|
||||
|
||||
#define DSPX_F_INT_ALL_DMA (DSPX_F_INT_DMANEXT | DSPX_F_INT_CONSUMED | DSPX_F_INT_UNDEROVER)
|
||||
|
||||
#define DSPX_FLD_INT_SOFT_WIDTH 16 /* width of the field and the number of interrupts */
|
||||
#define DSPX_FLD_INT_SOFT_SHIFT 16
|
||||
#define DSPX_FLD_INT_SOFT_MASK (0xffff0000)
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERNAL MEMORY MAPS
|
||||
//**************************************************************************
|
||||
@ -153,7 +103,6 @@ dspp_device::dspp_device(const machine_config &mconfig, device_type type, const
|
||||
m_data(nullptr),
|
||||
m_output_fifo_start(0),
|
||||
m_output_fifo_count(0),
|
||||
m_dspx_control(0),
|
||||
m_dspx_reset(0),
|
||||
m_dspx_int_enable(0),
|
||||
m_dspx_channel_enable(0),
|
||||
@ -194,7 +143,6 @@ dspp_device::dspp_device(const machine_config &mconfig, device_type type, const
|
||||
|
||||
void dspp_device::device_start()
|
||||
{
|
||||
// DSPP DRC is not yet ready for prime time
|
||||
m_isdrc = false;//allow_drc();
|
||||
|
||||
m_core = (dspp_internal_state *)m_cache.alloc_near(sizeof(dspp_internal_state));
|
||||
@ -215,6 +163,7 @@ void dspp_device::device_start()
|
||||
m_data = &space(AS_DATA);
|
||||
auto code_cache = m_code->cache<1, -1, ENDIANNESS_BIG>();
|
||||
m_code_cache = code_cache;
|
||||
m_code16 = [code_cache](offs_t address) -> uint16_t { return code_cache->read_word(address); };
|
||||
m_codeptr = [code_cache](offs_t address) -> const void * { return code_cache->read_ptr(address); };
|
||||
|
||||
// Register our state for the debugger
|
||||
@ -275,7 +224,7 @@ void dspp_device::device_start()
|
||||
|
||||
save_item(NAME(m_core->m_partial_int));
|
||||
|
||||
save_item(NAME(m_dspx_control));
|
||||
save_item(NAME(m_core->m_dspx_control));
|
||||
save_item(NAME(m_dspx_reset));
|
||||
save_item(NAME(m_dspx_int_enable));
|
||||
save_item(NAME(m_dspx_channel_enable));
|
||||
@ -489,8 +438,8 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
for (uint32_t i = 0; i < MAX_OPERANDS; ++i)
|
||||
{
|
||||
// Reset operands
|
||||
m_operands[i].value = -1;
|
||||
m_operands[i].addr = -1;
|
||||
m_core->m_operands[i].value = -1;
|
||||
m_core->m_operands[i].addr = -1;
|
||||
}
|
||||
|
||||
// Reset global op index
|
||||
@ -520,7 +469,7 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
if (val & 0x1000)
|
||||
val |= 0xe000;
|
||||
}
|
||||
m_operands[opidx++].value = val;
|
||||
m_core->m_operands[opidx++].value = val;
|
||||
}
|
||||
else if((operand & 0xe000) == 0x8000)
|
||||
{
|
||||
@ -532,14 +481,14 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
// Indirect
|
||||
addr = read_data(addr);
|
||||
}
|
||||
m_operands[opidx].addr = addr;
|
||||
m_core->m_operands[opidx].addr = addr;
|
||||
|
||||
if (operand & 0x0800)
|
||||
{
|
||||
// Write Back
|
||||
m_core->m_writeback = addr;
|
||||
}
|
||||
++opidx;
|
||||
opidx++;
|
||||
}
|
||||
else if ((operand & 0xe000) == 0xa000)
|
||||
{
|
||||
@ -582,7 +531,7 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
m_core->m_writeback = addr;
|
||||
}
|
||||
|
||||
m_operands[opidx++].addr = addr;
|
||||
m_core->m_operands[opidx++].addr = addr;
|
||||
}
|
||||
numregs = 0;
|
||||
}
|
||||
@ -597,10 +546,14 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
|
||||
uint16_t dspp_device::read_next_operand()
|
||||
{
|
||||
int32_t value = m_operands[m_core->m_opidx].value;
|
||||
int32_t value = m_core->m_operands[m_core->m_opidx].value;
|
||||
//if (m_core->m_op == 0x46a0) printf("Value is %08x\n", value);
|
||||
|
||||
if (value < 0)
|
||||
value = read_data(m_operands[m_core->m_opidx].addr);
|
||||
{
|
||||
value = read_data(m_core->m_operands[m_core->m_opidx].addr);
|
||||
//if (m_core->m_op == 0x46a0) printf("New value is %08x from %08x\n", value, m_core->m_operands[m_core->m_opidx].addr);
|
||||
}
|
||||
|
||||
// Next operand
|
||||
++m_core->m_opidx;
|
||||
@ -616,7 +569,7 @@ uint16_t dspp_device::read_next_operand()
|
||||
|
||||
void dspp_device::write_next_operand(uint16_t value)
|
||||
{
|
||||
int32_t addr = m_operands[m_core->m_opidx].addr;
|
||||
int32_t addr = m_core->m_operands[m_core->m_opidx].addr;
|
||||
|
||||
assert(addr != -1);
|
||||
|
||||
@ -724,11 +677,19 @@ void dspp_device::execute_run()
|
||||
{
|
||||
if (m_isdrc)
|
||||
{
|
||||
// TODO: TEMPORARY HACK!
|
||||
if (m_dspx_control & DSPX_CONTROL_GWILLING)
|
||||
execute_run_drc();
|
||||
else
|
||||
m_core->m_icount = 0;
|
||||
// Only run if enabled
|
||||
do
|
||||
{
|
||||
if (m_core->m_dspx_control & DSPX_CONTROL_GWILLING)
|
||||
{
|
||||
execute_run_drc();
|
||||
}
|
||||
else
|
||||
{
|
||||
update_ticks();
|
||||
update_fifo_dma();
|
||||
}
|
||||
} while (m_core->m_icount > 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -740,12 +701,13 @@ void dspp_device::execute_run()
|
||||
update_fifo_dma();
|
||||
|
||||
// Only run if enabled
|
||||
if (m_dspx_control & DSPX_CONTROL_GWILLING)
|
||||
if (m_core->m_dspx_control & DSPX_CONTROL_GWILLING)
|
||||
{
|
||||
if (check_debugger)
|
||||
debugger_instruction_hook(m_core->m_pc);
|
||||
|
||||
m_core->m_op = read_op(m_core->m_pc);
|
||||
//printf("%04x: %04x\n", (uint16_t)m_core->m_pc, (uint16_t)m_core->m_op);
|
||||
update_pc();
|
||||
|
||||
// Decode and execute
|
||||
@ -845,7 +807,6 @@ inline void dspp_device::exec_special()
|
||||
if (regdi & 0x0010)
|
||||
{
|
||||
addr = read_data(addr);
|
||||
break;
|
||||
}
|
||||
|
||||
parse_operands(1);
|
||||
@ -908,6 +869,8 @@ void dspp_device::exec_branch()
|
||||
if (mode == 2)
|
||||
branch = !branch;
|
||||
|
||||
//printf("Branch: %d %d %d %d %d\n", branch ? 1 : 0, flag0 ? 1 : 0, mask0 ? 1 : 0, flag1 ? 1 : 0, mask1 ? 1 : 0);
|
||||
|
||||
if (branch)
|
||||
m_core->m_pc = m_core->m_op & 0x3ff;
|
||||
}
|
||||
@ -1072,6 +1035,9 @@ inline void dspp_device::exec_arithmetic()
|
||||
|
||||
int32_t alu_a, alu_b;
|
||||
|
||||
//if (m_core->m_op == 0x46a0)
|
||||
//printf("Arithmetic: numops:%d, muxa:%d, muxb:%d, alu_op:%d, barrel_code:%d\n", numops, muxa, muxb, alu_op, barrel_code);
|
||||
|
||||
switch (muxa)
|
||||
{
|
||||
case 0:
|
||||
@ -1082,6 +1048,8 @@ inline void dspp_device::exec_arithmetic()
|
||||
case 1: case 2:
|
||||
{
|
||||
alu_a = read_next_operand() << 4;
|
||||
//if (m_core->m_op == 0x46a0)
|
||||
//printf("Arithmetic: Next operand: %04x\n", alu_a >> 4);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
@ -2122,7 +2090,7 @@ uint32_t dspp_device::read_ext_control(offs_t offset)
|
||||
// DSPX_CONTROL
|
||||
case 0x6070/4:
|
||||
{
|
||||
data = m_dspx_control;
|
||||
data = m_core->m_dspx_control;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -2346,7 +2314,7 @@ void dspp_device::write_ext_control(offs_t offset, uint32_t data)
|
||||
// DSPX_CONTROL
|
||||
case 0x6070/4:
|
||||
{
|
||||
m_dspx_control = data;
|
||||
m_core->m_dspx_control = data;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2620,7 +2588,7 @@ void dspp_device::dump_state()
|
||||
char buffer[64];
|
||||
|
||||
printf("\n=== GLOBAL REGISTER===\n");
|
||||
printf("DSPX_CONTROL: %08X\n", m_dspx_control);
|
||||
printf("DSPX_CONTROL: %08X\n", m_core->m_dspx_control);
|
||||
printf("DSPX_RESET: %08X\n", m_dspx_reset);
|
||||
printf("DSPX_INT_ENABLE: %08X\n", m_dspx_int_enable);
|
||||
printf("DSPX_CHANNEL_ENABLE: %08X %s\n", m_dspx_channel_enable, GetBinary(buffer, m_dspx_channel_enable, 32));
|
||||
|
@ -66,6 +66,12 @@ public:
|
||||
DECLARE_WRITE16_MEMBER( clock_w );
|
||||
DECLARE_READ16_MEMBER( noise_r );
|
||||
|
||||
void update_fifo_dma();
|
||||
void print_sums() { printf("%04x: %04x\n", (uint16_t)m_core->m_arg0, (uint16_t)m_core->m_arg1); }
|
||||
void print_branches() { printf("Branch: %d %d %d %d %d\n", m_core->m_arg0 ? 1 : 0, m_core->m_arg1 ? 1 : 0, m_core->m_arg2 ? 1 : 0, m_core->m_arg3 ? 1 : 0, m_core->m_arg4 ? 1 : 0); }
|
||||
void print_value() { printf("Value is %08x\n", m_core->m_arg0); }
|
||||
void print_addr() { printf("New value is %08x from %08x\n", m_core->m_arg0, m_core->m_arg1); }
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -90,6 +96,41 @@ protected:
|
||||
void code_map(address_map &map);
|
||||
void data_map(address_map &map);
|
||||
|
||||
enum
|
||||
{
|
||||
DSPX_CONTROL_GWILLING = 0x0001,
|
||||
DSPX_CONTROL_STEP_CYCLE = 0x0002,
|
||||
DSPX_CONTROL_STEP_PC = 0x0004,
|
||||
DSPX_CONTROL_SNOOP = 0x0008,
|
||||
|
||||
DSPX_RESET_DSPP = 0x0001,
|
||||
DSPX_RESET_INPUT = 0x0002,
|
||||
DSPX_RESET_OUTPUT = 0x0004,
|
||||
|
||||
DSPX_F_DMA_NEXTVALID = 0x0001,
|
||||
DSPX_F_DMA_GO_FOREVER = 0x0002,
|
||||
DSPX_F_INT_DMANEXT_EN = 0x0004,
|
||||
DSPX_F_SHADOW_SET_DMANEXT = 0x00040000,
|
||||
DSPX_F_SHADOW_SET_FOREVER = 0x00020000,
|
||||
DSPX_F_SHADOW_SET_NEXTVALID = 0x00010000,
|
||||
DSPX_F_SHADOW_SET_ADDRESS_COUNT = 0x80000000,
|
||||
|
||||
DSPX_F_INT_TIMER = 0x00000100,
|
||||
DSPX_F_INT_INPUT_UNDER = 0x00000080,
|
||||
DSPX_F_INT_INPUT_OVER = 0x00000040,
|
||||
DSPX_F_INT_OUTPUT_UNDER = 0x00000020,
|
||||
DSPX_F_INT_OUTPUT_OVER = 0x00000010,
|
||||
DSPX_F_INT_UNDEROVER = 0x00000008,
|
||||
DSPX_F_INT_CONSUMED = 0x00000002,
|
||||
DSPX_F_INT_DMANEXT = 0x00000001,
|
||||
|
||||
DSPX_F_INT_ALL_DMA = (DSPX_F_INT_DMANEXT | DSPX_F_INT_CONSUMED | DSPX_F_INT_UNDEROVER),
|
||||
|
||||
DSPX_FLD_INT_SOFT_WIDTH = 16, /* width of the field and the number of interrupts */
|
||||
DSPX_FLD_INT_SOFT_SHIFT = 16,
|
||||
DSPX_FLD_INT_SOFT_MASK = 0xffff0000
|
||||
};
|
||||
|
||||
private:
|
||||
// Constants
|
||||
static const uint32_t PC_STACK_DEPTH = 4;
|
||||
@ -130,7 +171,6 @@ private:
|
||||
inline void set_rbase(uint32_t base, uint32_t addr);
|
||||
inline uint16_t translate_reg(uint16_t reg);
|
||||
|
||||
void update_fifo_dma();
|
||||
void process_next_dma(int32_t channel);
|
||||
void service_input_dma(int32_t channel);
|
||||
void service_output_dma(int32_t channel);
|
||||
@ -162,6 +202,7 @@ private:
|
||||
address_space * m_code;
|
||||
address_space * m_data;
|
||||
memory_access_cache<1, -1, ENDIANNESS_BIG> *m_code_cache;
|
||||
std::function<uint16_t (offs_t)> m_code16;
|
||||
std::function<const void * (offs_t)> m_codeptr;
|
||||
|
||||
struct dspp_internal_state
|
||||
@ -187,16 +228,24 @@ private:
|
||||
uint16_t m_op;
|
||||
uint32_t m_opidx;
|
||||
int32_t m_writeback;
|
||||
uint32_t m_jmpdest;
|
||||
|
||||
const char *m_format;
|
||||
uint32_t m_arg0;
|
||||
} * m_core;
|
||||
uint32_t m_arg1;
|
||||
uint32_t m_arg2;
|
||||
uint32_t m_arg3;
|
||||
uint32_t m_arg4;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t addr;
|
||||
} m_operands[MAX_OPERANDS];
|
||||
struct
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t addr;
|
||||
} m_operands[MAX_OPERANDS];
|
||||
|
||||
// External control registers
|
||||
uint32_t m_dspx_control;
|
||||
} * m_core;
|
||||
|
||||
// DMA
|
||||
struct fifo_dma
|
||||
@ -229,7 +278,6 @@ private:
|
||||
uint32_t m_output_fifo_count;
|
||||
|
||||
// External control registers
|
||||
uint32_t m_dspx_control;
|
||||
uint32_t m_dspx_reset;
|
||||
uint32_t m_dspx_int_enable;
|
||||
uint32_t m_dspx_channel_enable;
|
||||
@ -268,6 +316,7 @@ private:
|
||||
uint32_t cycles; /* accumulated cycles */
|
||||
uint8_t checkints; /* need to check interrupts before next instruction */
|
||||
uint8_t checksoftints; /* need to check software interrupts before next instruction */
|
||||
uml::code_label abortlabel; /* label to abort execution of this block */
|
||||
uml::code_label labelnum; /* index for local labels */
|
||||
};
|
||||
|
||||
@ -288,18 +337,44 @@ public: // TODO
|
||||
void static_generate_entry_point();
|
||||
void static_generate_nocode_handler();
|
||||
void static_generate_out_of_cycles();
|
||||
void static_generate_memory_accessor(int size, bool istlb, bool iswrite, const char *name, uml::code_handle **handleptr);
|
||||
void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr);
|
||||
void generate_update_cycles(drcuml_block &block, compiler_state *compiler, uml::parameter param);
|
||||
void generate_checksum_block(drcuml_block &block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
|
||||
void generate_sequence_instruction(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
||||
bool generate_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
||||
void generate_push_pc(drcuml_block &block);
|
||||
void generate_read_next_operand(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_write_next_operand(drcuml_block &block, compiler_state *compiler);
|
||||
void generate_update_pc(drcuml_block &block);
|
||||
void generate_update_ticks(drcuml_block &block);
|
||||
void generate_translate_reg(drcuml_block &block, uint16_t reg);
|
||||
void generate_set_rbase(drcuml_block &block, compiler_state *compiler, uint32_t base, uint32_t addr);
|
||||
void generate_branch(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_branch_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_complex_branch_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_super_special(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_special_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_arithmetic_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_parse_operands(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc, uint32_t numops);
|
||||
|
||||
/* subroutines */
|
||||
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_entry; /* entry point */
|
||||
uml::code_handle *m_nocode; /* nocode exception handler */
|
||||
uml::code_handle *m_out_of_cycles; /* out of cycles exception handler */
|
||||
|
||||
enum
|
||||
{
|
||||
MEM_ACCESSOR_PM_READ48,
|
||||
MEM_ACCESSOR_PM_WRITE48,
|
||||
MEM_ACCESSOR_PM_READ32,
|
||||
MEM_ACCESSOR_PM_WRITE32,
|
||||
MEM_ACCESSOR_DM_READ32,
|
||||
MEM_ACCESSOR_DM_WRITE32
|
||||
};
|
||||
|
||||
uml::code_handle *m_dm_read16;
|
||||
uml::code_handle *m_dm_write16;
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,8 +26,6 @@
|
||||
#define CC_X_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0)
|
||||
|
||||
#define CC_FLAGS_MODIFIED(desc) do { } while(0)
|
||||
//#define MULT_FLAGS_MODIFIED(desc) do { MN_MODIFIED(desc);MV_MODIFIED(desc);MU_MODIFIED(desc);MI_MODIFIED(desc); } while(0)
|
||||
//#define SHIFT_FLAGS_MODIFIED(desc) do { SZ_MODIFIED(desc);SV_MODIFIED(desc);SS_MODIFIED(desc); } while(0)
|
||||
|
||||
dspp_frontend::dspp_frontend(dspp_device *dspp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
|
||||
: drc_frontend(*dspp, window_start, window_end, max_sequence),
|
||||
@ -78,9 +76,8 @@ bool dspp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
{
|
||||
uint16_t op = desc.opptr.w[0] = m_dspp->read_op(desc.physpc);
|
||||
|
||||
// TODO: NOOOOPE
|
||||
desc.cycles = 1; // TODO: Extra cycles for extra operands
|
||||
desc.length = 2;
|
||||
desc.cycles = 1;
|
||||
desc.length = 1;
|
||||
|
||||
// Decode and execute
|
||||
if (op & 0x8000)
|
||||
@ -88,28 +85,25 @@ bool dspp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
switch ((op >> 13) & 3)
|
||||
{
|
||||
case 0:
|
||||
return describe_special(op, desc);
|
||||
describe_special(op, desc);
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
return describe_branch(op, desc);
|
||||
describe_branch(op, desc);
|
||||
|
||||
case 3:
|
||||
return describe_complex_branch(op, desc);
|
||||
describe_complex_branch(op, desc);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return describe_arithmetic(op, desc);
|
||||
describe_arithmetic(op, desc);
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool dspp_frontend::describe_special(uint16_t op, opcode_desc &desc)
|
||||
void dspp_frontend::describe_special(uint16_t op, opcode_desc &desc)
|
||||
{
|
||||
switch ((op >> 10) & 7)
|
||||
{
|
||||
@ -118,58 +112,55 @@ bool dspp_frontend::describe_special(uint16_t op, opcode_desc &desc)
|
||||
// Super-special
|
||||
switch ((op >> 7) & 7)
|
||||
{
|
||||
case 1: // BAC - TODO: MERGE?
|
||||
case 1: // BAC
|
||||
{
|
||||
//desc.regin[0] = m_acc;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case 4: // RTS
|
||||
{
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case 5: // OP_MASK
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
case 7: // SLEEP
|
||||
{
|
||||
// TODO
|
||||
return true;
|
||||
desc.flags |= OPFLAG_END_SEQUENCE | OPFLAG_RETURN_TO_START;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0: // NOP
|
||||
case 2: // Unused
|
||||
case 3:
|
||||
case 6:
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: // JUMP - TODO: MERGE?
|
||||
case 1: // JUMP
|
||||
{
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
desc.targetpc = op & 0x3ff;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case 2: // JSR
|
||||
{
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
desc.targetpc = op & 0x3ff;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case 3: // BFM
|
||||
{
|
||||
// TODO: What sort of branch is this?
|
||||
// desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
// desc.targetpc = 0; // FIXME
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
case 4: // MOVEREG
|
||||
{
|
||||
@ -179,28 +170,29 @@ bool dspp_frontend::describe_special(uint16_t op, opcode_desc &desc)
|
||||
if (op & 0x0010)
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
|
||||
return true;
|
||||
parse_operands(op, desc, 1);
|
||||
return;
|
||||
}
|
||||
case 5: // RBASE
|
||||
{
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
case 6: // MOVED
|
||||
{
|
||||
desc.flags |= OPFLAG_WRITES_MEMORY;
|
||||
return true;
|
||||
parse_operands(op, desc, 1);
|
||||
return;
|
||||
}
|
||||
case 7: // MOVEI
|
||||
{
|
||||
desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY;
|
||||
return true;
|
||||
parse_operands(op, desc, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dspp_frontend::describe_branch(uint16_t op, opcode_desc &desc)
|
||||
void dspp_frontend::describe_branch(uint16_t op, opcode_desc &desc)
|
||||
{
|
||||
const uint32_t select = (op >> 12) & 1;
|
||||
|
||||
@ -218,11 +210,9 @@ bool dspp_frontend::describe_branch(uint16_t op, opcode_desc &desc)
|
||||
// TODO: Can these be unconditional?
|
||||
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
|
||||
desc.targetpc = op & 0x3ff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dspp_frontend::describe_complex_branch(uint16_t op, opcode_desc &desc)
|
||||
void dspp_frontend::describe_complex_branch(uint16_t op, opcode_desc &desc)
|
||||
{
|
||||
switch ((op >> 10) & 7)
|
||||
{
|
||||
@ -257,13 +247,10 @@ bool dspp_frontend::describe_complex_branch(uint16_t op, opcode_desc &desc)
|
||||
|
||||
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
|
||||
desc.targetpc = op & 0x3ff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc)
|
||||
void dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc)
|
||||
{
|
||||
#if 0
|
||||
// Decode the various fields
|
||||
uint32_t numops = (op >> 13) & 3;
|
||||
uint32_t muxa = (op >> 10) & 3;
|
||||
@ -271,9 +258,6 @@ bool dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc)
|
||||
uint32_t alu_op = (op >> 4) & 0xf;
|
||||
uint32_t barrel_code = op & 0xf;
|
||||
|
||||
int32_t mul_res = 0;
|
||||
uint32_t alu_res = 0;
|
||||
|
||||
// Check for operand overflow
|
||||
if (numops == 0 && ((muxa == 1) || (muxa == 2) || (muxb == 1) || (muxb == 2)))
|
||||
numops = 4;
|
||||
@ -282,7 +266,6 @@ bool dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc)
|
||||
if (barrel_code == 8)
|
||||
++numops;
|
||||
|
||||
// TODO: We need to know:
|
||||
// Number of cycles
|
||||
// Number of bytes
|
||||
// Registers read
|
||||
@ -290,293 +273,82 @@ bool dspp_frontend::describe_arithmetic(uint16_t op, opcode_desc &desc)
|
||||
// Does it read memory?
|
||||
// Does it write memory?
|
||||
|
||||
// parse_operands(numops);
|
||||
parse_operands(op, desc, numops);
|
||||
|
||||
if (muxa == 3 || muxb == 3)
|
||||
if (muxa > 0 || muxb > 0)
|
||||
{
|
||||
uint32_t mul_sel = (op >> 12) & 1;
|
||||
|
||||
int32_t op1 = sign_extend16(read_next_operand());
|
||||
int32_t op2 = sign_extend16(mul_sel ? read_next_operand() : m_core->m_acc >> 4);
|
||||
|
||||
mul_res = (op1 * op2) >> 11;
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
}
|
||||
|
||||
int32_t alu_a, alu_b;
|
||||
|
||||
switch (muxa)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ACCUMULATOR_USED
|
||||
alu_a = m_core->m_acc;
|
||||
break;
|
||||
}
|
||||
case 1: case 2:
|
||||
{
|
||||
alu_a = read_next_operand() << 4;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
alu_a = mul_res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (muxb)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
ACCUMULATOR_USED
|
||||
alu_b = m_core->m_acc;
|
||||
break;
|
||||
}
|
||||
case 1: case 2:
|
||||
{
|
||||
alu_b = read_next_operand() << 4;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
alu_b = mul_res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All flags ar emodifed
|
||||
CC_FLAGS_MODIFIED(desc);
|
||||
|
||||
switch (alu_op)
|
||||
{
|
||||
case 0: // _TRA
|
||||
{
|
||||
// alu_res = alu_a;
|
||||
break;
|
||||
}
|
||||
case 1: // _NEG
|
||||
{
|
||||
// alu_res = -alu_b;
|
||||
break;
|
||||
}
|
||||
case 2: // _+
|
||||
case 4: // _-
|
||||
case 6: // _++
|
||||
case 7: // _--
|
||||
case 8: // _TRL
|
||||
case 9: // _NOT
|
||||
case 10: // _AND
|
||||
case 11: // _NAND
|
||||
case 12: // _OR
|
||||
case 13: // _NOR
|
||||
case 14: // _XOR
|
||||
case 15: // _XNOR
|
||||
{
|
||||
// alu_res = alu_a + alu_b;
|
||||
|
||||
// if ((alu_a & 0x80000) == (alu_b & 0x80000) &&
|
||||
// (alu_a & 0x80000) != (alu_res & 0x80000))
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_OVER;
|
||||
|
||||
// if (alu_res & 0x00100000)
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_CARRY;
|
||||
|
||||
// CC_V_MODIFIED(desc);
|
||||
// CC_C_MODIFIED(desc);
|
||||
CC_C_MODIFIED(desc);
|
||||
CC_V_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 3: // _+C
|
||||
{
|
||||
// alu_res = alu_a + (m_core->m_flags & DSPI_FLAG_CC_CARRY) ? (1 << 4) : 0;
|
||||
|
||||
// if (alu_res & 0x00100000)
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_CARRY;
|
||||
|
||||
CC_C_USED(desc);
|
||||
CC_C_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 4: // _-
|
||||
{
|
||||
// alu_res = alu_a - alu_b;
|
||||
|
||||
// if ((alu_a & 0x80000) == (~alu_b & 0x80000) &&
|
||||
// (alu_a & 0x80000) != (alu_res & 0x80000))
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_OVER;
|
||||
|
||||
// if (alu_res & 0x00100000)
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_CARRY;
|
||||
|
||||
CC_C_MODIFIED(desc);
|
||||
CC_V_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 5: // _-B
|
||||
{
|
||||
// alu_res = alu_a - (m_core->m_flags & DSPI_FLAG_CC_CARRY) ? (1 << 4) : 0;
|
||||
|
||||
// if (alu_res & 0x00100000)
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_CARRY;
|
||||
|
||||
CC_C_USED(desc);
|
||||
CC_C_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 6: // _++
|
||||
{
|
||||
// alu_res = alu_a + 1;
|
||||
|
||||
// if (!(alu_a & 0x80000) && (alu_res & 0x80000))
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_OVER;
|
||||
|
||||
CC_V_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 7: // _--
|
||||
{
|
||||
// alu_res = alu_a - 1;
|
||||
|
||||
// if ((alu_a & 0x80000) && !(alu_res & 0x80000))
|
||||
// m_core->m_flags |= DSPI_FLAG_CC_OVER;
|
||||
|
||||
CC_V_MODIFIED(desc);
|
||||
break;
|
||||
}
|
||||
case 8: // _TRL
|
||||
{
|
||||
//alu_res = alu_a;
|
||||
break;
|
||||
}
|
||||
case 9: // _NOT
|
||||
{
|
||||
//alu_res = ~alu_a;
|
||||
break;
|
||||
}
|
||||
case 10: // _AND
|
||||
{
|
||||
//alu_res = alu_a & alu_b;
|
||||
break;
|
||||
}
|
||||
case 11: // _NAND
|
||||
{
|
||||
//alu_res = ~(alu_a & alu_b);
|
||||
break;
|
||||
}
|
||||
case 12: // _OR
|
||||
{
|
||||
//alu_res = alu_a | alu_b;
|
||||
break;
|
||||
}
|
||||
case 13: // _NOR
|
||||
{
|
||||
//alu_res = ~(alu_a | alu_b);
|
||||
break;
|
||||
}
|
||||
case 14: // _XOR
|
||||
{
|
||||
//alu_res = alu_a ^ alu_b;
|
||||
break;
|
||||
}
|
||||
case 15: // _XNOR
|
||||
{
|
||||
//alu_res = ~(alu_a ^ alu_b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (alu_res & 0x00080000)
|
||||
m_core->m_flags |= DSPI_FLAG_CC_NEG;
|
||||
|
||||
if ((alu_res & 0x000ffff0) == 0)
|
||||
m_core->m_flags |= DSPI_FLAG_CC_ZERO;
|
||||
|
||||
if ((alu_res & 0x0000000f) == 0)
|
||||
m_core->m_flags |= DSPI_FLAG_CC_EXACT;
|
||||
|
||||
CC_N_MODIFIED(desc);
|
||||
CC_Z_MODIFIED(desc);
|
||||
CC_X_MODIFIED(desc);
|
||||
|
||||
ACCUMULATOR_MODIFIED_ALWAYS;
|
||||
|
||||
// Barrel shift
|
||||
static const int32_t shifts[8] = { 0, 1, 2, 3, 4, 5, 8, 16 };
|
||||
|
||||
if (barrel_code == 8)
|
||||
barrel_code = read_next_operand();
|
||||
|
||||
if (barrel_code & 8)
|
||||
{
|
||||
// Right shift
|
||||
uint32_t shift = shifts[(~barrel_code + 1) & 7];
|
||||
|
||||
if (alu_op < 8)
|
||||
{
|
||||
// Arithmetic
|
||||
m_core->m_acc = sign_extend20(alu_res) >> shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Logical
|
||||
m_core->m_acc = (alu_res & 0xfffff) >> shift;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Left shift
|
||||
uint32_t shift = shifts[barrel_code];
|
||||
|
||||
if (shift == 16)
|
||||
{
|
||||
// Clip and saturate
|
||||
if (m_core->m_flags & DSPI_FLAG_CC_OVER)
|
||||
m_core->m_acc = (m_core->m_flags & DSPI_FLAG_CC_NEG) ? 0x7ffff : 0xfff80000;
|
||||
else
|
||||
m_core->m_acc = sign_extend20(alu_res);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_core->m_acc = sign_extend20(alu_res) << shift;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_core->m_writeback >= 0)
|
||||
{
|
||||
write_data(m_core->m_writeback, m_core->m_acc >> 4);
|
||||
m_core->m_writeback = -1;
|
||||
}
|
||||
else if (opidx < numops)
|
||||
{
|
||||
write_next_operand(m_core->m_acc >> 4);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void dspp_device::parse_operands(uint32_t numops)
|
||||
void dspp_frontend::parse_operands(uint16_t op, opcode_desc &desc, uint32_t numops)
|
||||
{
|
||||
uint32_t addr, val = 0xBAD;
|
||||
uint32_t opidx = 0;
|
||||
uint32_t operand = 0;
|
||||
uint32_t numregs = 0;
|
||||
|
||||
uint32_t opidx = 0;
|
||||
|
||||
while (opidx < numops)
|
||||
{
|
||||
uint16_t op = desc.opptr.w[opidx + 1] = m_dspp->read_op(desc.physpc + opidx * 2);
|
||||
uint16_t operand = desc.opptr.w[opidx + 1] = m_dspp->read_op(desc.physpc + opidx + 1);
|
||||
|
||||
desc.length += 2;
|
||||
++desc.cycles;
|
||||
desc.length++;
|
||||
desc.cycles++;
|
||||
|
||||
if (op & 0x8000)
|
||||
if (operand & 0x8000)
|
||||
{
|
||||
// Immediate value
|
||||
if ((op & 0xc000) == 0xc000)
|
||||
if ((operand & 0xc000) == 0xc000)
|
||||
{
|
||||
// Nothing?-
|
||||
opidx++;
|
||||
}
|
||||
else if((op & 0xe000) == 0x8000)
|
||||
else if((operand & 0xe000) == 0x8000)
|
||||
{
|
||||
if (op & 0x0400) // Indirect
|
||||
if (operand & 0x0400) // Indirect
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
|
||||
if (op & 0x0800 )// Write Back
|
||||
if (operand & 0x0800 )// Write Back
|
||||
desc.flags |= OPFLAG_WRITES_MEMORY;
|
||||
|
||||
++opidx;
|
||||
opidx++;
|
||||
}
|
||||
else if ((op & 0xe000) == 0xa000)
|
||||
{
|
||||
@ -596,7 +368,6 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
{
|
||||
uint32_t shift = ((numregs - i) - 1) * 5;
|
||||
uint32_t regdi = (operand >> shift) & 0x1f;
|
||||
// OP USES REGBASE?
|
||||
|
||||
if (regdi & 0x0010)
|
||||
{
|
||||
@ -617,9 +388,9 @@ void dspp_device::parse_operands(uint32_t numops)
|
||||
if (operand & 0x800)
|
||||
desc.flags |= OPFLAG_WRITES_MEMORY;
|
||||
}
|
||||
opidx++;
|
||||
}
|
||||
numregs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -59,10 +59,11 @@ private:
|
||||
// inlines
|
||||
|
||||
// internal helpers
|
||||
bool describe_special(uint16_t op, opcode_desc &desc);
|
||||
bool describe_branch(uint16_t op, opcode_desc &desc);
|
||||
bool describe_complex_branch(uint16_t op, opcode_desc &desc);
|
||||
bool describe_arithmetic(uint16_t op, opcode_desc &desc);
|
||||
void describe_special(uint16_t op, opcode_desc &desc);
|
||||
void describe_branch(uint16_t op, opcode_desc &desc);
|
||||
void describe_complex_branch(uint16_t op, opcode_desc &desc);
|
||||
void describe_arithmetic(uint16_t op, opcode_desc &desc);
|
||||
void parse_operands(uint16_t op, opcode_desc &desc, uint32_t numops);
|
||||
|
||||
// internal state
|
||||
dspp_device *m_dspp;
|
||||
|
Loading…
Reference in New Issue
Block a user