mirror of
https://github.com/holub/mame
synced 2025-06-30 16:00:01 +03:00
e132xs: Added mask, sum, cmpi, movi, and ori, nw
This commit is contained in:
parent
bccc962b69
commit
ad5172a47d
@ -1,4 +1,3 @@
|
||||
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Pierpaolo Prazzoli
|
||||
/********************************************************************
|
||||
@ -401,46 +400,26 @@ uint32_t hyperstone_device::get_emu_code_addr(uint8_t num) /* num is OP */
|
||||
return addr;
|
||||
}
|
||||
|
||||
void hyperstone_device::hyperstone_set_trap_entry(int which)
|
||||
{
|
||||
switch( which )
|
||||
{
|
||||
case E132XS_ENTRY_MEM0:
|
||||
m_trap_entry = 0x00000000;
|
||||
break;
|
||||
/*static*/ const uint32_t hyperstone_device::s_trap_entries[8] = {
|
||||
0x00000000, // MEM0
|
||||
0x40000000, // MEM1
|
||||
0x80000000, // MEM2
|
||||
0xc0000000, // IRAM
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0xffffff00, // MEM3
|
||||
};
|
||||
|
||||
case E132XS_ENTRY_MEM1:
|
||||
m_trap_entry = 0x40000000;
|
||||
break;
|
||||
|
||||
case E132XS_ENTRY_MEM2:
|
||||
m_trap_entry = 0x80000000;
|
||||
break;
|
||||
|
||||
case E132XS_ENTRY_MEM3:
|
||||
m_trap_entry = 0xffffff00;
|
||||
break;
|
||||
|
||||
case E132XS_ENTRY_IRAM:
|
||||
m_trap_entry = 0xc0000000;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("Set entry point to a reserved value: %d\n", which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t hyperstone_device::compute_tr()
|
||||
void hyperstone_device::compute_tr()
|
||||
{
|
||||
uint64_t cycles_since_base = total_cycles() - m_tr_base_cycles;
|
||||
uint64_t clocks_since_base = cycles_since_base >> m_clck_scale;
|
||||
return m_tr_base_value + (clocks_since_base / m_tr_clocks_per_tick);
|
||||
m_tr_result = m_tr_base_value + (clocks_since_base / m_tr_clocks_per_tick);
|
||||
}
|
||||
|
||||
void hyperstone_device::update_timer_prescale()
|
||||
{
|
||||
uint32_t prevtr = compute_tr();
|
||||
TPR &= ~0x80000000;
|
||||
m_clck_scale = (TPR >> 26) & m_clock_scale_mask;
|
||||
m_clock_cycles_1 = 1 << m_clck_scale;
|
||||
@ -449,7 +428,7 @@ void hyperstone_device::update_timer_prescale()
|
||||
m_clock_cycles_4 = 4 << m_clck_scale;
|
||||
m_clock_cycles_6 = 6 << m_clck_scale;
|
||||
m_tr_clocks_per_tick = ((TPR >> 16) & 0xff) + 2;
|
||||
m_tr_base_value = prevtr;
|
||||
m_tr_base_value = m_tr_result;
|
||||
m_tr_base_cycles = total_cycles();
|
||||
}
|
||||
|
||||
@ -499,10 +478,13 @@ TIMER_CALLBACK_MEMBER( hyperstone_device::timer_callback )
|
||||
|
||||
/* update the values if necessary */
|
||||
if (update)
|
||||
{
|
||||
compute_tr();
|
||||
update_timer_prescale();
|
||||
}
|
||||
|
||||
/* see if the timer is right for firing */
|
||||
if (!((compute_tr() - TCR) & 0x80000000))
|
||||
if (!((m_tr_result - TCR) & 0x80000000))
|
||||
m_timer_int_pending = 1;
|
||||
|
||||
/* adjust ourselves for the next time */
|
||||
@ -552,7 +534,8 @@ uint32_t hyperstone_device::get_global_register(uint8_t code)
|
||||
/* it is common to poll this in a loop */
|
||||
if (m_icount > m_tr_clocks_per_tick / 2)
|
||||
m_icount -= m_tr_clocks_per_tick / 2;
|
||||
return compute_tr();
|
||||
compute_tr();
|
||||
return m_tr_result;
|
||||
}
|
||||
return m_global_regs[code & 0x1f];
|
||||
}
|
||||
@ -606,7 +589,10 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val)
|
||||
case TPR_REGISTER:
|
||||
m_global_regs[code] = val;
|
||||
if (!(val & 0x80000000)) /* change immediately */
|
||||
{
|
||||
compute_tr();
|
||||
update_timer_prescale();
|
||||
}
|
||||
adjust_timer_interrupt();
|
||||
return;
|
||||
case TCR_REGISTER:
|
||||
@ -632,15 +618,19 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val)
|
||||
case FCR_REGISTER:
|
||||
if ((m_global_regs[code] ^ val) & 0x00800000)
|
||||
adjust_timer_interrupt();
|
||||
m_global_regs[code] = val;
|
||||
m_global_regs[code] = val;
|
||||
if (m_intblock < 1)
|
||||
m_intblock = 1;
|
||||
return;
|
||||
case MCR_REGISTER:
|
||||
{
|
||||
// bits 14..12 EntryTableMap
|
||||
hyperstone_set_trap_entry((val & 0x7000) >> 12);
|
||||
const int which = (val & 0x7000) >> 12;
|
||||
assert(which < 4 || which == 7);
|
||||
m_trap_entry = s_trap_entries[which];
|
||||
m_global_regs[code] = val;
|
||||
return;
|
||||
}
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
@ -1043,6 +1033,7 @@ void hyperstone_device::init(int scale_mask)
|
||||
|
||||
m_tr_base_cycles = 0;
|
||||
m_tr_base_value = 0;
|
||||
m_tr_result = 0;
|
||||
m_tr_clocks_per_tick = 0;
|
||||
m_timer_int_pending = 0;
|
||||
|
||||
@ -1081,7 +1072,7 @@ void hyperstone_device::init(int scale_mask)
|
||||
for (int i=0; i < 64; i++)
|
||||
{
|
||||
sprintf(buf, "l%d", i);
|
||||
m_drcuml->symbol_add(&m_global_regs[i], sizeof(uint32_t), buf);
|
||||
m_drcuml->symbol_add(&m_local_regs[i], sizeof(uint32_t), buf);
|
||||
}
|
||||
|
||||
m_drcuml->symbol_add(&m_drc_arg0, sizeof(uint32_t), "arg0");
|
||||
@ -1328,7 +1319,7 @@ void hyperstone_device::device_reset()
|
||||
|
||||
m_tr_clocks_per_tick = 2;
|
||||
|
||||
hyperstone_set_trap_entry(E132XS_ENTRY_MEM3); /* default entry point @ MEM3 */
|
||||
m_trap_entry = s_trap_entries[E132XS_ENTRY_MEM3]; // default entry point @ MEM3
|
||||
|
||||
set_global_register(BCR_REGISTER, ~0);
|
||||
set_global_register(MCR_REGISTER, ~0);
|
||||
|
@ -65,6 +65,10 @@ class hyperstone_device : public cpu_device
|
||||
public:
|
||||
inline void ccfunc_unimplemented();
|
||||
inline void ccfunc_print();
|
||||
inline void ccfunc_total_cycles();
|
||||
void update_timer_prescale();
|
||||
void compute_tr();
|
||||
void adjust_timer_interrupt();
|
||||
|
||||
protected:
|
||||
enum
|
||||
@ -223,10 +227,13 @@ protected:
|
||||
|
||||
uint64_t m_tr_base_cycles;
|
||||
uint32_t m_tr_base_value;
|
||||
uint32_t m_tr_result;
|
||||
uint32_t m_tr_clocks_per_tick;
|
||||
uint8_t m_timer_int_pending;
|
||||
emu_timer *m_timer;
|
||||
|
||||
uint64_t m_numcycles;
|
||||
|
||||
uint32_t m_delay_pc;
|
||||
uint32_t m_delay_slot;
|
||||
|
||||
@ -239,6 +246,7 @@ protected:
|
||||
int m_icount;
|
||||
|
||||
uint8_t m_fl_lut[16];
|
||||
static const uint32_t s_trap_entries[8];
|
||||
static const int32_t s_immediate_values[16];
|
||||
|
||||
uint32_t get_trap_addr(uint8_t trapno);
|
||||
@ -253,10 +261,6 @@ private:
|
||||
uint32_t get_global_register(uint8_t code);
|
||||
|
||||
uint32_t get_emu_code_addr(uint8_t num);
|
||||
void hyperstone_set_trap_entry(int which);
|
||||
uint32_t compute_tr();
|
||||
void update_timer_prescale();
|
||||
void adjust_timer_interrupt();
|
||||
|
||||
TIMER_CALLBACK_MEMBER(timer_callback);
|
||||
|
||||
@ -407,15 +411,15 @@ private:
|
||||
void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op);
|
||||
bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
||||
int generate_get_trap_addr(drcuml_block *block, int label, uint32_t trapno);
|
||||
void generate_check_delay_pc(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_get_trap_addr(drcuml_block *block, uml::code_label &label, uint32_t trapno);
|
||||
void generate_check_delay_pc(drcuml_block *block);
|
||||
void generate_decode_const(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
int generate_decode_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_decode_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_ignore_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_decode_pcrel(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
void generate_ignore_pcrel(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
||||
int generate_set_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int label);
|
||||
void generate_set_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
||||
void generate_trap(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t addr);
|
||||
void generate_int(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t addr);
|
||||
@ -446,7 +450,7 @@ private:
|
||||
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_xor(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_not(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_cmpi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> int generate_movi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_movi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_addi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_addsi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
template <reg_bank DST_GLOBAL, imm_size IMM_LONG> void generate_cmpbi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
using namespace uml;
|
||||
|
||||
#define DRC_PC mem(m_global_regs)
|
||||
#define DRC_SR mem(&m_global_regs[1])
|
||||
|
||||
void hyperstone_device::execute_run_drc()
|
||||
@ -44,6 +45,66 @@ void hyperstone_device::execute_run_drc()
|
||||
} while (execute_result != EXECUTE_OUT_OF_CYCLES);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
C FUNCTION CALLBACKS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
cfunc_unimplemented - handler for
|
||||
unimplemented opcdes
|
||||
-------------------------------------------------*/
|
||||
|
||||
inline void hyperstone_device::ccfunc_unimplemented()
|
||||
{
|
||||
fatalerror("PC=%08X: Unimplemented op %08X\n", PC, m_drc_arg0);
|
||||
}
|
||||
|
||||
inline void hyperstone_device::ccfunc_print()
|
||||
{
|
||||
printf("%c: %08X\n", (char)m_drc_arg0, m_drc_arg1);
|
||||
}
|
||||
|
||||
static void cfunc_unimplemented(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->ccfunc_unimplemented();
|
||||
}
|
||||
|
||||
static void cfunc_adjust_timer_interrupt(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->adjust_timer_interrupt();
|
||||
}
|
||||
|
||||
static void cfunc_compute_tr(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->compute_tr();
|
||||
}
|
||||
|
||||
static void cfunc_update_timer_prescale(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->update_timer_prescale();
|
||||
}
|
||||
|
||||
static void cfunc_print(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->ccfunc_print();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
ccfunc_total_cycles - compute the total number
|
||||
of cycles executed so far
|
||||
-------------------------------------------------*/
|
||||
|
||||
void hyperstone_device::ccfunc_total_cycles()
|
||||
{
|
||||
m_numcycles = total_cycles();
|
||||
}
|
||||
|
||||
static void cfunc_total_cycles(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->ccfunc_total_cycles();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
CACHE MANAGEMENT
|
||||
***************************************************************************/
|
||||
@ -99,7 +160,7 @@ void hyperstone_device::code_flush_cache()
|
||||
}
|
||||
|
||||
/* Return the entry point for a determinated trap */
|
||||
int hyperstone_device::generate_get_trap_addr(drcuml_block *block, int label, uint32_t trapno)
|
||||
void hyperstone_device::generate_get_trap_addr(drcuml_block *block, uml::code_label &label, uint32_t trapno)
|
||||
{
|
||||
int no_mem3;
|
||||
UML_MOV(block, I0, trapno);
|
||||
@ -110,7 +171,6 @@ int hyperstone_device::generate_get_trap_addr(drcuml_block *block, int label, ui
|
||||
UML_LABEL(block, no_mem3);
|
||||
UML_SHL(block, I0, I0, 2);
|
||||
UML_OR(block, I0, I0, mem(&m_trap_entry));
|
||||
return label;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
@ -196,7 +256,9 @@ void hyperstone_device::code_compile_block(offs_t pc)
|
||||
|
||||
/* otherwise we just go to the next instruction */
|
||||
else
|
||||
nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2;
|
||||
{
|
||||
nextpc = seqlast->pc + seqlast->length;
|
||||
}
|
||||
|
||||
/* count off cycles and go there */
|
||||
generate_update_cycles(block, &compiler, nextpc); // <subtract cycles>
|
||||
@ -220,37 +282,6 @@ void hyperstone_device::code_compile_block(offs_t pc)
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
C FUNCTION CALLBACKS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
cfunc_unimplemented - handler for
|
||||
unimplemented opcdes
|
||||
-------------------------------------------------*/
|
||||
|
||||
inline void hyperstone_device::ccfunc_unimplemented()
|
||||
{
|
||||
fatalerror("PC=%08X: Unimplemented op %08X\n", PC, m_drc_arg0);
|
||||
}
|
||||
|
||||
inline void hyperstone_device::ccfunc_print()
|
||||
{
|
||||
printf("%c: %08X\n", (char)m_drc_arg0, m_drc_arg1);
|
||||
}
|
||||
|
||||
static void cfunc_unimplemented(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->ccfunc_unimplemented();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void cfunc_print(void *param)
|
||||
{
|
||||
((hyperstone_device *)param)->ccfunc_print();
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
STATIC CODEGEN
|
||||
***************************************************************************/
|
||||
@ -294,7 +325,8 @@ void hyperstone_device::static_generate_exception(uint32_t exception, const char
|
||||
alloc_handle(drcuml, &exception_handle, name);
|
||||
UML_HANDLE(block, *exception_handle);
|
||||
|
||||
generate_get_trap_addr(block, 1, exception);
|
||||
uml::code_label label = 1;
|
||||
generate_get_trap_addr(block, label, exception);
|
||||
UML_ROLAND(block, I1, DRC_SR, 7, 0x7f);
|
||||
UML_ROLAND(block, I2, DRC_SR, 11, 0xf);
|
||||
UML_TEST(block, I2, 0xf);
|
||||
@ -309,7 +341,7 @@ void hyperstone_device::static_generate_exception(uint32_t exception, const char
|
||||
UML_ROLINS(block, DRC_SR, I1, 25, 0xfe000000);
|
||||
|
||||
UML_AND(block, I3, I1, 0x3f);
|
||||
UML_AND(block, I1, mem(m_global_regs), ~1);
|
||||
UML_AND(block, I1, DRC_PC, ~1);
|
||||
UML_ROLAND(block, I2, DRC_SR, 14, 1);
|
||||
UML_OR(block, I1, I1, I2);
|
||||
UML_STORE(block, (void *)m_local_regs, I3, I1, SIZE_DWORD, SCALE_x4);
|
||||
@ -320,7 +352,7 @@ void hyperstone_device::static_generate_exception(uint32_t exception, const char
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~(M_MASK | T_MASK));
|
||||
UML_OR(block, DRC_SR, DRC_SR, (L_MASK | S_MASK));
|
||||
|
||||
UML_MOV(block, mem(m_global_regs), I0);
|
||||
UML_MOV(block, DRC_PC, I0);
|
||||
UML_SUB(block, mem(&m_icount), mem(&m_icount), 2);
|
||||
UML_EXHc(block, COND_S, *m_out_of_cycles, 0);
|
||||
|
||||
@ -622,7 +654,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block *block, compi
|
||||
/* if we are debugging, call the debugger */
|
||||
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
|
||||
{
|
||||
UML_MOV(block, mem(m_global_regs), desc->pc);
|
||||
UML_MOV(block, DRC_PC, desc->pc);
|
||||
//save_fast_iregs(block);
|
||||
UML_DEBUG(block, desc->pc);
|
||||
}
|
||||
@ -632,7 +664,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block *block, compi
|
||||
/* compile the instruction */
|
||||
if (!generate_opcode(block, compiler, desc))
|
||||
{
|
||||
UML_MOV(block, mem(m_global_regs), desc->pc);
|
||||
UML_MOV(block, DRC_PC, desc->pc);
|
||||
UML_MOV(block, mem(&m_drc_arg0), desc->opptr.l[0]);
|
||||
UML_CALLC(block, cfunc_unimplemented, this);
|
||||
}
|
||||
@ -649,10 +681,9 @@ bool hyperstone_device::generate_opcode(drcuml_block *block, compiler_state *com
|
||||
|
||||
UML_MOV(block, I0, op);
|
||||
UML_AND(block, I7, DRC_SR, H_MASK);
|
||||
UML_ADD(block, mem(m_global_regs), mem(m_global_regs), 2);
|
||||
UML_ADD(block, DRC_PC, DRC_PC, 2);
|
||||
UML_MOV(block, mem(&m_instruction_length), (1 << 19));
|
||||
|
||||
int label = 1;
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0x00: generate_chk<GLOBAL, GLOBAL>(block, compiler, desc); break;
|
||||
@ -755,10 +786,10 @@ bool hyperstone_device::generate_opcode(drcuml_block *block, compiler_state *com
|
||||
case 0x61: generate_cmpi<GLOBAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x62: generate_cmpi<LOCAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x63: generate_cmpi<LOCAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x64: label = generate_movi<GLOBAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x65: label = generate_movi<GLOBAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x66: label = generate_movi<LOCAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x67: label = generate_movi<LOCAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x64: generate_movi<GLOBAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x65: generate_movi<GLOBAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x66: generate_movi<LOCAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x67: generate_movi<LOCAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x68: generate_addi<GLOBAL, SIMM>(block, compiler, desc); break;
|
||||
case 0x69: generate_addi<GLOBAL, LIMM>(block, compiler, desc); break;
|
||||
case 0x6a: generate_addi<LOCAL, SIMM>(block, compiler, desc); break;
|
||||
@ -919,7 +950,7 @@ bool hyperstone_device::generate_opcode(drcuml_block *block, compiler_state *com
|
||||
int done;
|
||||
UML_AND(block, I0, DRC_SR, (T_MASK | P_MASK));
|
||||
UML_CMP(block, I0, (T_MASK | P_MASK));
|
||||
UML_JMPc(block, uml::COND_NE, done = label++);
|
||||
UML_JMPc(block, uml::COND_NE, done = compiler->m_labelnum++);
|
||||
UML_TEST(block, mem(&m_delay_slot), 1);
|
||||
UML_EXHc(block, uml::COND_E, *m_exception[EXCEPTION_TRACE], 0);
|
||||
|
||||
|
@ -3,19 +3,51 @@
|
||||
|
||||
#include "e132xs.h"
|
||||
|
||||
void hyperstone_device::generate_check_delay_pc(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
void hyperstone_device::generate_check_delay_pc(drcuml_block *block)
|
||||
{
|
||||
/* if PC is used in a delay instruction, the delayed PC should be used */
|
||||
UML_TEST(block, mem(&m_delay_slot), 1);
|
||||
UML_MOVc(block, COND_E, mem(m_global_regs), mem(&m_delay_pc));
|
||||
UML_MOVc(block, COND_E, mem(&m_delay_slot), 0);
|
||||
UML_MOVc(block, uml::COND_NZ, DRC_PC, mem(&m_delay_pc));
|
||||
UML_MOVc(block, uml::COND_NZ, mem(&m_delay_slot), 0);
|
||||
}
|
||||
|
||||
void hyperstone_device::generate_decode_const(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
int half_read;
|
||||
UML_READ(block, I1, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_ADD(block, DRC_PC, DRC_PC, 2);
|
||||
UML_TEST(block, I1, 0x8000);
|
||||
UML_JMPc(block, uml::COND_Z, half_read = compiler->m_labelnum++);
|
||||
|
||||
UML_MOV(block, mem(&m_instruction_length), (3<<19));
|
||||
|
||||
int skip;
|
||||
UML_SHL(block, I1, I1, 16);
|
||||
UML_AND(block, I2, I1, 0x3fff0000);
|
||||
UML_TEST(block, I1, 0x40000000);
|
||||
UML_MOVc(block, uml::COND_Z, I1, I2);
|
||||
UML_JMPc(block, uml::COND_Z, skip = compiler->m_labelnum++);
|
||||
UML_OR(block, I1, I2, 0xc0000000);
|
||||
UML_LABEL(block, skip);
|
||||
UML_READ(block, I2, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_ADD(block, DRC_PC, DRC_PC, 2);
|
||||
UML_OR(block, I1, I1, I2);
|
||||
|
||||
int done;
|
||||
UML_JMP(block, done = compiler->m_labelnum++);
|
||||
|
||||
UML_LABEL(block, half_read);
|
||||
UML_MOV(block, mem(&m_instruction_length), (2<<19));
|
||||
UML_TEST(block, I1, 0x4000);
|
||||
UML_MOVc(block, uml::COND_NZ, I2, 0xffffc000);
|
||||
UML_MOVc(block, uml::COND_Z, I2, 0);
|
||||
UML_AND(block, I1, I1, 0x3fff);
|
||||
UML_OR(block, I1, I1, I2);
|
||||
|
||||
UML_LABEL(block, done);
|
||||
}
|
||||
|
||||
int hyperstone_device::generate_decode_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
void hyperstone_device::generate_decode_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
static int32_t immediate_values[16] =
|
||||
{
|
||||
@ -23,25 +55,24 @@ int hyperstone_device::generate_decode_immediate_s(drcuml_block *block, compiler
|
||||
-8, -7, -6, -5, -4, -3, -2, -1
|
||||
};
|
||||
|
||||
int label = 1;
|
||||
int nolut, done, zero_or_one, three;
|
||||
|
||||
UML_AND(block, I1, I0, 0x0f);
|
||||
UML_CMP(block, I1, 4);
|
||||
UML_JMPc(block, COND_L, nolut = label++);
|
||||
UML_JMPc(block, COND_L, nolut = compiler->m_labelnum++);
|
||||
|
||||
// 4..f, immediate lookup
|
||||
UML_LOAD(block, I1, (void *)immediate_values, I1, SIZE_DWORD, SCALE_x4);
|
||||
UML_JMP(block, done = label++);
|
||||
UML_JMP(block, done = compiler->m_labelnum++);
|
||||
|
||||
UML_LABEL(block, nolut);
|
||||
UML_CMP(block, I1, 2);
|
||||
UML_JMPc(block, COND_L, zero_or_one = label++);
|
||||
UML_JMPc(block, COND_G, three = label++);
|
||||
UML_JMPc(block, COND_L, zero_or_one = compiler->m_labelnum++);
|
||||
UML_JMPc(block, COND_G, three = compiler->m_labelnum++);
|
||||
|
||||
// 2
|
||||
UML_MOV(block, mem(&m_instruction_length), (2<<19));
|
||||
UML_READ(block, I1, mem(m_global_regs), SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_READ(block, I1, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_JMP(block, done);
|
||||
|
||||
// 0..1
|
||||
@ -52,22 +83,21 @@ int hyperstone_device::generate_decode_immediate_s(drcuml_block *block, compiler
|
||||
|
||||
// 1
|
||||
UML_MOV(block, mem(&m_instruction_length), (3<<19));
|
||||
UML_READ(block, I1, mem(m_global_regs), SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_READ(block, I1, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_SHL(block, I1, I1, 16);
|
||||
UML_ADD(block, mem(m_global_regs), mem(m_global_regs), 2);
|
||||
UML_READ(block, I2, mem(m_global_regs), SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_ADD(block, mem(m_global_regs), mem(m_global_regs), 2);
|
||||
UML_ADD(block, DRC_PC, DRC_PC, 2);
|
||||
UML_READ(block, I2, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_ADD(block, DRC_PC, DRC_PC, 2);
|
||||
UML_JMP(block, done);
|
||||
|
||||
// 3
|
||||
UML_LABEL(block, three);
|
||||
UML_MOV(block, mem(&m_instruction_length), (2<<19));
|
||||
UML_READ(block, I1, mem(m_global_regs), SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_READ(block, I1, DRC_PC, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_SEXT(block, I1, I1, SIZE_WORD);
|
||||
// fall through to done
|
||||
|
||||
UML_LABEL(block, done);
|
||||
return label;
|
||||
}
|
||||
|
||||
void hyperstone_device::generate_ignore_immediate_s(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
@ -82,10 +112,108 @@ void hyperstone_device::generate_ignore_pcrel(drcuml_block *block, compiler_stat
|
||||
{
|
||||
}
|
||||
|
||||
int hyperstone_device::generate_set_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int label)
|
||||
void hyperstone_device::generate_set_global_register(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
// Expects register index in I0, value in I1
|
||||
return label;
|
||||
// Expects register index in I4, value in I5, clobbers I6
|
||||
int extended;
|
||||
UML_CMP(block, I4, 16);
|
||||
UML_JMPc(block, uml::COND_AE, extended = compiler->m_labelnum++);
|
||||
|
||||
int generic_store, set_sr, done;
|
||||
UML_CMP(block, I4, 1);
|
||||
UML_JMPc(block, uml::COND_A, generic_store = compiler->m_labelnum++);
|
||||
UML_JMPc(block, uml::COND_E, set_sr = compiler->m_labelnum++);
|
||||
UML_AND(block, DRC_PC, I5, ~1);
|
||||
generate_delay_slot_and_branch(block, compiler, desc);
|
||||
UML_JMP(block, done = compiler->m_labelnum++);
|
||||
|
||||
UML_LABEL(block, set_sr);
|
||||
UML_ROLINS(block, DRC_SR, I5, 0, 0x0000ffff);
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~0x40);
|
||||
UML_TEST(block, mem(&m_intblock), ~0);
|
||||
UML_MOVc(block, uml::COND_Z, mem(&m_intblock), 1);
|
||||
UML_JMP(block, done);
|
||||
|
||||
UML_LABEL(block, generic_store);
|
||||
UML_STORE(block, (void *)m_global_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
UML_JMP(block, done);
|
||||
|
||||
int above_bcr;
|
||||
UML_LABEL(block, extended);
|
||||
UML_CMP(block, I4, 17);
|
||||
UML_JMPc(block, uml::COND_BE, generic_store);
|
||||
UML_CMP(block, I4, BCR_REGISTER);
|
||||
UML_JMPc(block, uml::COND_A, above_bcr = compiler->m_labelnum++);
|
||||
UML_JMPc(block, uml::COND_E, generic_store);
|
||||
|
||||
// SP or UB
|
||||
UML_AND(block, I5, I5, ~3);
|
||||
UML_JMP(block, generic_store);
|
||||
|
||||
int set_tpr, set_tcr, set_tr, set_fcr;
|
||||
UML_LABEL(block, above_bcr);
|
||||
UML_CMP(block, I4, TCR_REGISTER);
|
||||
UML_JMPc(block, uml::COND_B, set_tpr = compiler->m_labelnum++);
|
||||
UML_JMPc(block, uml::COND_E, set_tcr = compiler->m_labelnum++);
|
||||
// Above TCR
|
||||
UML_CMP(block, I4, WCR_REGISTER);
|
||||
UML_JMPc(block, uml::COND_B, set_tr = compiler->m_labelnum++);
|
||||
UML_JMPc(block, uml::COND_E, generic_store); // WCR
|
||||
// Above WCR
|
||||
UML_CMP(block, I4, FCR_REGISTER);
|
||||
UML_JMPc(block, uml::COND_B, done); // ISR - read only
|
||||
UML_JMPc(block, uml::COND_E, set_fcr = compiler->m_labelnum++);
|
||||
UML_CMP(block, I4, MCR_REGISTER);
|
||||
UML_JMPc(block, uml::COND_A, generic_store); // regs 28..31
|
||||
// Set MCR
|
||||
UML_ROLAND(block, I6, I5, 20, 0x7);
|
||||
UML_LOAD(block, I6, (void *)s_trap_entries, I6, SIZE_DWORD, SCALE_x4);
|
||||
UML_MOV(block, mem(&m_trap_entry), I6);
|
||||
UML_JMP(block, generic_store);
|
||||
|
||||
int skip_compute_tr;
|
||||
UML_LABEL(block, set_tpr);
|
||||
UML_STORE(block, (void *)m_global_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
UML_TEST(block, I5, 0x80000000);
|
||||
UML_JMPc(block, uml::COND_NZ, skip_compute_tr = compiler->m_labelnum++);
|
||||
UML_CALLC(block, cfunc_compute_tr, this);
|
||||
UML_CALLC(block, cfunc_update_timer_prescale, this);
|
||||
UML_LABEL(block, skip_compute_tr);
|
||||
UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
|
||||
UML_JMP(block, done);
|
||||
|
||||
UML_LABEL(block, set_tcr);
|
||||
UML_LOAD(block, I6, (void *)m_global_regs, I4, SIZE_DWORD, SCALE_x4);
|
||||
UML_CMP(block, I6, I5);
|
||||
UML_JMPc(block, uml::COND_E, done);
|
||||
UML_STORE(block, (void *)m_global_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
|
||||
UML_CMP(block, mem(&m_intblock), 1);
|
||||
UML_MOVc(block, uml::COND_L, mem(&m_intblock), 1);
|
||||
UML_JMP(block, done);
|
||||
|
||||
UML_LABEL(block, set_tr);
|
||||
UML_STORE(block, (void *)m_global_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
UML_MOV(block, mem(&m_tr_base_value), I5);
|
||||
UML_CALLC(block, cfunc_total_cycles, this);
|
||||
UML_DMOV(block, mem(&m_tr_base_cycles), mem(&m_numcycles));
|
||||
UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
|
||||
UML_JMP(block, done);
|
||||
|
||||
int skip_adjust_timer;
|
||||
UML_LABEL(block, set_fcr);
|
||||
UML_LOAD(block, I6, (void *)m_global_regs, I4, SIZE_DWORD, SCALE_x4);
|
||||
UML_XOR(block, I6, I6, I5);
|
||||
UML_TEST(block, I6, 0x80000000);
|
||||
UML_JMPc(block, uml::COND_Z, skip_adjust_timer = compiler->m_labelnum++);
|
||||
UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
|
||||
UML_LABEL(block, skip_adjust_timer);
|
||||
UML_STORE(block, (void *)m_global_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
UML_CMP(block, mem(&m_intblock), 1);
|
||||
UML_MOVc(block, uml::COND_L, mem(&m_intblock), 1);
|
||||
// Fall through to done
|
||||
|
||||
UML_LABEL(block, done);
|
||||
}
|
||||
|
||||
void hyperstone_device::generate_trap(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t addr)
|
||||
@ -132,12 +260,111 @@ void hyperstone_device::generate_xm(drcuml_block *block, compiler_state *compile
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
|
||||
void hyperstone_device::generate_mask(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
generate_decode_const(block, compiler, desc);
|
||||
generate_check_delay_pc(block);
|
||||
UML_AND(block, I2, I0, 0x000f);
|
||||
if (!SRC_GLOBAL || !DST_GLOBAL)
|
||||
{
|
||||
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
|
||||
}
|
||||
|
||||
if (SRC_GLOBAL)
|
||||
{
|
||||
UML_LOAD(block, I2, (void *)m_global_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ADD(block, I2, I2, I3);
|
||||
UML_AND(block, I2, I2, 0x3f);
|
||||
UML_LOAD(block, I2, (void *)m_local_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
|
||||
UML_AND(block, I1, I2, I1);
|
||||
|
||||
int skip_mask;
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~Z_MASK);
|
||||
UML_TEST(block, I1, ~0);
|
||||
UML_JMPc(block, uml::COND_NZ, skip_mask = compiler->m_labelnum++);
|
||||
UML_OR(block, DRC_SR, DRC_SR, Z_MASK);
|
||||
UML_LABEL(block, skip_mask);
|
||||
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
UML_ROLAND(block, I4, I0, 28, 0xf);
|
||||
UML_MOV(block, I5, I2);
|
||||
generate_set_global_register(block, compiler, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ROLAND(block, I0, I0, 28, 0xf);
|
||||
UML_ADD(block, I0, I0, I3);
|
||||
UML_AND(block, I0, I0, 0x3f);
|
||||
UML_STORE(block, (void *)m_local_regs, I0, I1, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
|
||||
void hyperstone_device::generate_sum(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
generate_decode_const(block, compiler, desc);
|
||||
generate_check_delay_pc(block);
|
||||
UML_AND(block, I2, I0, 0x000f);
|
||||
if (!SRC_GLOBAL || !DST_GLOBAL)
|
||||
{
|
||||
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
|
||||
}
|
||||
|
||||
if (SRC_GLOBAL)
|
||||
{
|
||||
UML_LOAD(block, I2, (void *)m_global_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ADD(block, I2, I2, I3);
|
||||
UML_AND(block, I2, I2, 0x3f);
|
||||
UML_LOAD(block, I2, (void *)m_local_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
|
||||
UML_MOV(block, mem(&m_drc_arg0), (uint32_t)'Q');
|
||||
UML_MOV(block, mem(&m_drc_arg1), I1);
|
||||
UML_CALLC(block, cfunc_print, this);
|
||||
UML_MOV(block, mem(&m_drc_arg0), (uint32_t)'R');
|
||||
UML_MOV(block, mem(&m_drc_arg1), I2);
|
||||
UML_CALLC(block, cfunc_print, this);
|
||||
UML_DADD(block, I5, I1, I2);
|
||||
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~(C_MASK | V_MASK | Z_MASK | N_MASK));
|
||||
UML_DTEST(block, I5, 0x100000000U);
|
||||
UML_SETc(block, uml::COND_NZ, I6);
|
||||
UML_ROLINS(block, DRC_SR, I6, 0, C_MASK);
|
||||
|
||||
UML_XOR(block, I1, I5, I2);
|
||||
UML_XOR(block, I6, I5, I1);
|
||||
UML_AND(block, I1, I1, I6);
|
||||
UML_TEST(block, I1, 0x80000000);
|
||||
UML_SETc(block, uml::COND_NZ, I6);
|
||||
UML_ROLINS(block, DRC_SR, I6, 0, V_MASK);
|
||||
|
||||
UML_TEST(block, I5, ~0);
|
||||
UML_SETc(block, uml::COND_Z, I6);
|
||||
UML_ROLINS(block, DRC_SR, I6, 0, Z_MASK);
|
||||
|
||||
UML_TEST(block, I5, 0x80000000);
|
||||
UML_SETc(block, uml::COND_NZ, I6);
|
||||
UML_ROLINS(block, DRC_SR, I6, 0, N_MASK);
|
||||
|
||||
UML_ROLAND(block, I4, I0, 28, 0xf);
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
generate_set_global_register(block, compiler, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ADD(block, I0, I4, I3);
|
||||
UML_AND(block, I2, I0, 0x3f);
|
||||
UML_STORE(block, (void *)m_local_regs, I0, I1, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -246,42 +473,90 @@ void hyperstone_device::generate_not(drcuml_block *block, compiler_state *compil
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
|
||||
void hyperstone_device::generate_cmpi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
|
||||
int hyperstone_device::generate_movi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
int label = 1;
|
||||
if (IMM_LONG)
|
||||
{
|
||||
label = generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
|
||||
generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_AND(block, I1, I0, 0xf);
|
||||
}
|
||||
|
||||
int done = label++;
|
||||
generate_check_delay_pc(block);
|
||||
|
||||
UML_ROLAND(block, I2, I0, 28, 0xf);
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
UML_LOAD(block, I2, (void *)m_global_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
|
||||
UML_ADD(block, I2, I2, I3);
|
||||
UML_LOAD(block, I2, (void *)m_local_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~(V_MASK | Z_MASK | N_MASK | C_MASK));
|
||||
UML_DSUB(block, I0, I2, I1);
|
||||
|
||||
int no_v;
|
||||
UML_XOR(block, I0, I0, I2);
|
||||
UML_XOR(block, I3, I1, I2);
|
||||
UML_AND(block, I0, I0, I3);
|
||||
UML_TEST(block, I0, 0x80000000);
|
||||
UML_JMPc(block, uml::COND_Z, no_v = compiler->m_labelnum++);
|
||||
UML_OR(block, DRC_SR, DRC_SR, V_MASK);
|
||||
UML_LABEL(block, no_v);
|
||||
|
||||
int no_n;
|
||||
UML_MOV(block, I3, 0);
|
||||
UML_CMP(block, I2, I1);
|
||||
UML_MOVc(block, uml::COND_E, I3, Z_MASK);
|
||||
UML_MOVc(block, uml::COND_B, I3, C_MASK);
|
||||
UML_JMPc(block, uml::COND_L, no_n = compiler->m_labelnum++);
|
||||
UML_OR(block, I3, I3, N_MASK);
|
||||
UML_LABEL(block, no_n);
|
||||
UML_OR(block, DRC_SR, DRC_SR, I3);
|
||||
|
||||
UML_CMP(block, I2, I1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
|
||||
void hyperstone_device::generate_movi(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
if (IMM_LONG)
|
||||
{
|
||||
generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_AND(block, I1, I0, 0xf);
|
||||
}
|
||||
|
||||
generate_check_delay_pc(block);
|
||||
|
||||
int done;
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
UML_AND(block, I2, mem(&m_global_regs[1]), H_MASK);
|
||||
UML_TEST(block, mem(&m_global_regs[1]), S_MASK);
|
||||
UML_EXHc(block, uml::COND_Z, *m_exception[EXCEPTION_PRIVILEGE_ERROR], 0);
|
||||
UML_JMPc(block, uml::COND_Z, done);
|
||||
UML_JMPc(block, uml::COND_Z, done = compiler->m_labelnum++);
|
||||
}
|
||||
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~(Z_MASK | N_MASK));
|
||||
|
||||
int no_z;
|
||||
UML_TEST(block, I1, ~0);
|
||||
UML_JMPc(block, uml::COND_NZ, no_z = label++);
|
||||
UML_JMPc(block, uml::COND_NZ, no_z = compiler->m_labelnum++);
|
||||
UML_OR(block, DRC_SR, DRC_SR, Z_MASK);
|
||||
UML_LABEL(block, no_z);
|
||||
|
||||
int no_n;
|
||||
UML_TEST(block, I1, 0x80000000);
|
||||
UML_JMPc(block, uml::COND_Z, no_n = label++);
|
||||
UML_JMPc(block, uml::COND_Z, no_n = compiler->m_labelnum++);
|
||||
UML_OR(block, DRC_SR, DRC_SR, N_MASK);
|
||||
UML_LABEL(block, no_n);
|
||||
|
||||
@ -289,22 +564,22 @@ int hyperstone_device::generate_movi(drcuml_block *block, compiler_state *compil
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~V_MASK);
|
||||
#endif
|
||||
|
||||
UML_ROLAND(block, I0, I0, 30, 0x3c);
|
||||
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
int no_pc;
|
||||
UML_ROLAND(block, I4, I0, 28, 0xf);
|
||||
UML_TEST(block, I2, ~0);
|
||||
UML_MOVc(block, uml::COND_NZ, I2, 16);
|
||||
UML_MOVc(block, uml::COND_Z, I2, 0);
|
||||
UML_ADD(block, I4, I4, I2);
|
||||
UML_MOV(block, I5, I1);
|
||||
generate_set_global_register(block, compiler, desc);
|
||||
|
||||
UML_TEST(block, I0, 0xf0);
|
||||
UML_JMPc(block, uml::COND_NZ, no_pc = label++);
|
||||
UML_AND(block, mem(m_global_regs), I1, ~1);
|
||||
UML_JMPc(block, uml::COND_NZ, done);
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
|
||||
generate_delay_slot_and_branch(block, compiler, desc);
|
||||
UML_JMP(block, done);
|
||||
|
||||
UML_LABEL(block, no_pc);
|
||||
|
||||
// TODO
|
||||
UML_JMP(block, done);
|
||||
UML_LABEL(block, done);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -313,9 +588,6 @@ int hyperstone_device::generate_movi(drcuml_block *block, compiler_state *compil
|
||||
UML_AND(block, I0, I0, 0x3f);
|
||||
UML_STORE(block, (void *)m_local_regs, I0, I1, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
|
||||
UML_LABEL(block, done);
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
@ -346,6 +618,44 @@ void hyperstone_device::generate_andni(drcuml_block *block, compiler_state *comp
|
||||
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::imm_size IMM_LONG>
|
||||
void hyperstone_device::generate_ori(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
|
||||
{
|
||||
if (IMM_LONG)
|
||||
{
|
||||
generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_AND(block, I1, I0, 0xf);
|
||||
}
|
||||
|
||||
generate_check_delay_pc(block);
|
||||
|
||||
UML_ROLAND(block, I2, I0, 28, 0xf);
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
UML_LOAD(block, I2, (void *)m_global_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
|
||||
UML_ADD(block, I2, I2, I3);
|
||||
UML_LOAD(block, I2, (void *)m_local_regs, I2, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
|
||||
UML_AND(block, DRC_SR, DRC_SR, ~Z_MASK);
|
||||
UML_OR(block, I5, I2, I1);
|
||||
UML_ROLAND(block, I4, I0, 28, 0xf);
|
||||
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
generate_set_global_register(block, compiler, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_ROLAND(block, I4, I0, 28, 0xf);
|
||||
UML_ADD(block, I4, I4, I2);
|
||||
UML_AND(block, I4, I4, 0x3f);
|
||||
UML_STORE(block, (void *)m_local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,10 +28,21 @@ e132xs_frontend::e132xs_frontend(hyperstone_device *e132xs, uint32_t window_star
|
||||
{
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
describe_instruction - build a description
|
||||
of a single instruction
|
||||
-------------------------------------------------*/
|
||||
inline uint32_t e132xs_frontend::imm_length(opcode_desc &desc, uint16_t op)
|
||||
{
|
||||
uint8_t nybble = op & 0x0f;
|
||||
switch (nybble)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
return 2;
|
||||
case 1:
|
||||
return 6;
|
||||
case 2:
|
||||
case 3:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint16_t e132xs_frontend::read_word(opcode_desc &desc)
|
||||
{
|
||||
@ -142,6 +153,12 @@ inline int32_t e132xs_frontend::decode_call(opcode_desc &desc)
|
||||
return extra_s;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
describe - build a description of a single
|
||||
instruction
|
||||
-------------------------------------------------*/
|
||||
|
||||
bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
{
|
||||
uint16_t op = desc.opptr.w[0] = read_word(desc);
|
||||
@ -164,6 +181,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
const uint32_t lsrc_group = 1 + (((SRC_CODE + fp) & 0x20) >> 5);
|
||||
const uint32_t lsrcf_group = 1 + ((SRC_CODE + fp + 1) >> 5);
|
||||
|
||||
printf("physpc: %08x\n", desc.physpc);
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0x00: // chk global,global
|
||||
@ -612,7 +630,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
case 0x71: // cmpbi global,limm
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
break;
|
||||
case 0x62: // cmpi local,simm
|
||||
case 0x72: // cmpbi local,simm
|
||||
@ -625,7 +643,8 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[0] |= SR_CODE;
|
||||
desc.regout[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
printf("%04x, %d\n", read_imm1(desc), desc.length);
|
||||
break;
|
||||
case 0x64: // movi global,simm
|
||||
desc.regin[0] |= SR_CODE;
|
||||
@ -644,7 +663,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= 1 << (gdst_code + 16);
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
@ -661,7 +680,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[0] |= SR_CODE;
|
||||
desc.regout[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
break;
|
||||
case 0x68: // addi global,simm
|
||||
case 0x6c: // addsi global,simm
|
||||
@ -670,6 +689,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
case 0x69: // addi global,limm
|
||||
case 0x6d: // addsi global,limm
|
||||
@ -677,8 +701,13 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
case 0x6a: // addi local,simm
|
||||
case 0x6e: // addsi local,simm
|
||||
@ -694,7 +723,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
if (op & 0x04) desc.flags |= OPFLAG_CAN_CAUSE_EXCEPTION; // addsi
|
||||
break;
|
||||
case 0x74: // andni global,simm
|
||||
@ -704,6 +733,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
case 0x75: // andni global,limm
|
||||
case 0x79: // ori global,limm
|
||||
@ -712,7 +746,12 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= 1 << gdst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
case 0x76: // andni local,simm
|
||||
case 0x7a: // ori local,simm
|
||||
@ -729,7 +768,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
desc.regin[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[ldst_group] |= 1 << ldst_code;
|
||||
desc.regout[0] |= SR_CODE;
|
||||
desc.length = (read_imm1(desc) & 0x8000) ? 6 : 4;
|
||||
desc.length = imm_length(desc, op);
|
||||
break;
|
||||
case 0x80: case 0x81: // shrdi
|
||||
case 0x84: case 0x85: // sardi
|
||||
@ -777,6 +816,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
|
||||
desc.length = (imm1 & 0x8000) ? 6 : 4;
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x91: // ldxx1 global,local
|
||||
@ -791,6 +835,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
|
||||
desc.length = (imm1 & 0x8000) ? 6 : 4;
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x92: // ldxx1 local,global
|
||||
@ -833,6 +882,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
|
||||
desc.length = (imm1 & 0x8000) ? 6 : 4;
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x95: // ldxx2 global,local
|
||||
@ -848,6 +902,11 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
|
||||
|
||||
desc.length = (imm1 & 0x8000) ? 6 : 4;
|
||||
desc.flags |= OPFLAG_READS_MEMORY;
|
||||
if (gdst_code == PC_REGISTER)
|
||||
{
|
||||
desc.targetpc = BRANCH_TARGET_DYNAMIC;
|
||||
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x96: // ldxx2 local,global
|
||||
|
@ -19,6 +19,7 @@ protected:
|
||||
virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
|
||||
|
||||
private:
|
||||
inline uint32_t imm_length(opcode_desc &desc, uint16_t op);
|
||||
inline uint16_t read_word(opcode_desc &desc);
|
||||
inline uint16_t read_imm1(opcode_desc &desc);
|
||||
inline uint16_t read_imm2(opcode_desc &desc);
|
||||
|
@ -1101,11 +1101,11 @@ void hyperstone_device::hyperstone_ori()
|
||||
|
||||
if (!IMM_LONG)
|
||||
imm = m_op & 0x0f;
|
||||
uint32_t dreg;
|
||||
|
||||
if (DST_GLOBAL)
|
||||
{
|
||||
const uint32_t dst_code = DST_CODE;
|
||||
dreg = m_global_regs[dst_code] | imm;
|
||||
const uint32_t dreg = m_global_regs[dst_code] | imm;
|
||||
|
||||
if (dreg)
|
||||
SR &= ~Z_MASK;
|
||||
@ -1117,7 +1117,7 @@ void hyperstone_device::hyperstone_ori()
|
||||
else
|
||||
{
|
||||
const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f;
|
||||
dreg = m_local_regs[dst_code] |= imm;
|
||||
const uint32_t dreg = m_local_regs[dst_code] |= imm;
|
||||
|
||||
if (dreg)
|
||||
SR &= ~Z_MASK;
|
||||
|
@ -73,20 +73,20 @@ namespace uml
|
||||
COND_NV, // requires V
|
||||
COND_U, // requires U
|
||||
COND_NU, // requires U
|
||||
COND_A, // requires CZ
|
||||
COND_BE, // requires CZ
|
||||
COND_G, // requires SVZ
|
||||
COND_LE, // requires SVZ
|
||||
COND_L, // requires SV
|
||||
COND_GE, // requires SV
|
||||
COND_A, // requires CZ, unsigned
|
||||
COND_BE, // requires CZ, unsigned
|
||||
COND_G, // requires SVZ, signed
|
||||
COND_LE, // requires SVZ, signed
|
||||
COND_L, // requires SV, signed
|
||||
COND_GE, // requires SV, signed
|
||||
|
||||
COND_MAX,
|
||||
|
||||
// basic condition code aliases
|
||||
COND_E = COND_Z,
|
||||
COND_NE = COND_NZ,
|
||||
COND_B = COND_C,
|
||||
COND_AE = COND_NC
|
||||
COND_B = COND_C, // unsigned
|
||||
COND_AE = COND_NC // unsigned
|
||||
};
|
||||
|
||||
// floating point rounding modes
|
||||
|
Loading…
Reference in New Issue
Block a user