-dspp: Preliminary DRC. Still disabled by default. [Ryan Holtz]

This commit is contained in:
mooglyguy 2018-12-25 17:41:15 +01:00
parent 46ade7d73d
commit 1cd0c11908
5 changed files with 1013 additions and 833 deletions

View File

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

View File

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

View File

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

View File

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