e132xs: merged divs/u and muls/u using templates, nw

This commit is contained in:
mooglyguy 2017-11-17 21:35:22 +01:00
parent 7572b7241d
commit f86271bade
3 changed files with 38 additions and 116 deletions

View File

@ -1641,14 +1641,14 @@ void hyperstone_device::execute_run()
case 0x05: hyperstone_movd<GLOBAL, LOCAL>(); break; case 0x05: hyperstone_movd<GLOBAL, LOCAL>(); break;
case 0x06: hyperstone_movd<LOCAL, GLOBAL>(); break; case 0x06: hyperstone_movd<LOCAL, GLOBAL>(); break;
case 0x07: hyperstone_movd<LOCAL, LOCAL>(); break; case 0x07: hyperstone_movd<LOCAL, LOCAL>(); break;
case 0x08: hyperstone_divu<GLOBAL, GLOBAL>(); break; case 0x08: hyperstone_divsu<GLOBAL, GLOBAL, IS_UNSIGNED>(); break;
case 0x09: hyperstone_divu<GLOBAL, LOCAL>(); break; case 0x09: hyperstone_divsu<GLOBAL, LOCAL, IS_UNSIGNED>(); break;
case 0x0a: hyperstone_divu<LOCAL, GLOBAL>(); break; case 0x0a: hyperstone_divsu<LOCAL, GLOBAL, IS_UNSIGNED>(); break;
case 0x0b: hyperstone_divu<LOCAL, LOCAL>(); break; case 0x0b: hyperstone_divsu<LOCAL, LOCAL, IS_UNSIGNED>(); break;
case 0x0c: hyperstone_divs<GLOBAL, GLOBAL>(); break; case 0x0c: hyperstone_divsu<GLOBAL, GLOBAL, IS_SIGNED>(); break;
case 0x0d: hyperstone_divs<GLOBAL, LOCAL>(); break; case 0x0d: hyperstone_divsu<GLOBAL, LOCAL, IS_SIGNED>(); break;
case 0x0e: hyperstone_divs<LOCAL, GLOBAL>(); break; case 0x0e: hyperstone_divsu<LOCAL, GLOBAL, IS_SIGNED>(); break;
case 0x0f: hyperstone_divs<LOCAL, LOCAL>(); break; case 0x0f: hyperstone_divsu<LOCAL, LOCAL, IS_SIGNED>(); break;
case 0x10: hyperstone_xm<GLOBAL, GLOBAL>(); break; case 0x10: hyperstone_xm<GLOBAL, GLOBAL>(); break;
case 0x11: hyperstone_xm<GLOBAL, LOCAL>(); break; case 0x11: hyperstone_xm<GLOBAL, LOCAL>(); break;
case 0x12: hyperstone_xm<LOCAL, GLOBAL>(); break; case 0x12: hyperstone_xm<LOCAL, GLOBAL>(); break;
@ -1809,14 +1809,14 @@ void hyperstone_device::execute_run()
case 0xad: hyperstone_reserved(); break; case 0xad: hyperstone_reserved(); break;
case 0xae: hyperstone_reserved(); break; case 0xae: hyperstone_reserved(); break;
case 0xaf: hyperstone_reserved(); break; case 0xaf: hyperstone_reserved(); break;
case 0xb0: hyperstone_mulu<GLOBAL, GLOBAL>(); break; case 0xb0: hyperstone_mulsu<GLOBAL, GLOBAL, IS_UNSIGNED>(); break;
case 0xb1: hyperstone_mulu<GLOBAL, LOCAL>(); break; case 0xb1: hyperstone_mulsu<GLOBAL, LOCAL, IS_UNSIGNED>(); break;
case 0xb2: hyperstone_mulu<LOCAL, GLOBAL>(); break; case 0xb2: hyperstone_mulsu<LOCAL, GLOBAL, IS_UNSIGNED>(); break;
case 0xb3: hyperstone_mulu<LOCAL, LOCAL>(); break; case 0xb3: hyperstone_mulsu<LOCAL, LOCAL, IS_UNSIGNED>(); break;
case 0xb4: hyperstone_muls<GLOBAL, GLOBAL>(); break; case 0xb4: hyperstone_mulsu<GLOBAL, GLOBAL, IS_SIGNED>(); break;
case 0xb5: hyperstone_muls<GLOBAL, LOCAL>(); break; case 0xb5: hyperstone_mulsu<GLOBAL, LOCAL, IS_SIGNED>(); break;
case 0xb6: hyperstone_muls<LOCAL, GLOBAL>(); break; case 0xb6: hyperstone_mulsu<LOCAL, GLOBAL, IS_SIGNED>(); break;
case 0xb7: hyperstone_muls<LOCAL, LOCAL>(); break; case 0xb7: hyperstone_mulsu<LOCAL, LOCAL, IS_SIGNED>(); break;
case 0xb8: hyperstone_set<N_LO, GLOBAL>(); break; case 0xb8: hyperstone_set<N_LO, GLOBAL>(); break;
case 0xb9: hyperstone_set<N_HI, GLOBAL>(); break; case 0xb9: hyperstone_set<N_HI, GLOBAL>(); break;
case 0xba: hyperstone_set<N_LO, LOCAL>(); break; case 0xba: hyperstone_set<N_LO, LOCAL>(); break;

View File

@ -111,7 +111,13 @@ protected:
enum shift_type enum shift_type
{ {
N_LO = 0, N_LO = 0,
N_HI = 1, N_HI = 1
};
enum sign_mode
{
IS_UNSIGNED = 0,
IS_SIGNED = 1
}; };
// construction/destruction // construction/destruction
@ -216,8 +222,7 @@ private:
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_chk(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_chk();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_movd(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_movd();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_divu(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL, sign_mode SIGNED> void hyperstone_divsu();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_divs();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_xm(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_xm();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mask(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mask();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_sum(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_sum();
@ -265,8 +270,7 @@ private:
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_stxx1(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_stxx1();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_stxx2(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_stxx2();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mulu(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL, sign_mode SIGNED> void hyperstone_mulsu();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_muls();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mul(); template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mul();
template <shift_type HI_N, reg_bank DST_GLOBAL> void hyperstone_set(); template <shift_type HI_N, reg_bank DST_GLOBAL> void hyperstone_set();

View File

@ -119,8 +119,8 @@ void hyperstone_device::hyperstone_movd()
} }
} }
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL> template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL, hyperstone_device::sign_mode SIGNED>
void hyperstone_device::hyperstone_divu() void hyperstone_device::hyperstone_divsu()
{ {
check_delay_PC(); check_delay_PC();
@ -137,58 +137,11 @@ void hyperstone_device::hyperstone_divu()
} }
const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
if (sreg == 0)
{
//Rd//Rdf -> undefined
//Z -> undefined
//N -> undefined
SR |= V_MASK;
execute_exception(get_trap_addr(TRAPNO_RANGE_ERROR));
}
else
{
const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const uint32_t dregf = (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code]; const uint32_t dregf = (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code];
const uint64_t dividend = concat_64(dreg, dregf); const uint64_t dividend = concat_64(dreg, dregf);
/* TODO: add quotient overflow */ if (sreg == 0 || (SIGNED && (dividend & 0x8000000000000000U)))
uint32_t quotient = dividend / sreg;
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = dividend % sreg;
(DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = quotient;
SR &= ~(V_MASK | Z_MASK | N_MASK);
if (quotient == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(quotient);
}
m_icount -= 36 << m_clck_scale;
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::hyperstone_divs()
{
check_delay_PC();
const uint32_t fp = GET_FP;
const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + fp) & 0x3f);
const uint32_t dstf_code = DST_GLOBAL ? (dst_code + 1) : ((dst_code + 1) & 0x3f);
const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
if ((SRC_GLOBAL == DST_GLOBAL && (src_code == dst_code || src_code == dstf_code)) || (SRC_GLOBAL && src_code < 2))
{
LOG("Denoted invalid register code in hyperstone_divs instruction. PC = %08X\n", PC);
m_icount -= 36 << m_clck_scale;
return;
}
const int32_t sreg = (int32_t)(SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const uint32_t dregf = (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code];
const int64_t dividend = (int64_t) concat_64(dreg, dregf);
if (sreg == 0 || (dividend & 0x8000000000000000U))
{ {
//Rd//Rdf -> undefined //Rd//Rdf -> undefined
//Z -> undefined //Z -> undefined
@ -199,10 +152,9 @@ void hyperstone_device::hyperstone_divs()
else else
{ {
/* TODO: add quotient overflow */ /* TODO: add quotient overflow */
const int32_t quotient = dividend / sreg; const uint32_t quotient = SIGNED ? (uint32_t)((int64_t)dividend / (int32_t)sreg) : (dividend / sreg);
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = dividend % sreg; (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = SIGNED ? (uint32_t)((int64_t)dividend % (int32_t)sreg) : (dividend % sreg);
(DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = quotient; (DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)quotient;
SR &= ~(V_MASK | Z_MASK | N_MASK); SR &= ~(V_MASK | Z_MASK | N_MASK);
if (quotient == 0) if (quotient == 0)
SR |= Z_MASK; SR |= Z_MASK;
@ -2239,8 +2191,8 @@ void hyperstone_device::hyperstone_shli()
m_icount -= m_clock_cycles_1; m_icount -= m_clock_cycles_1;
} }
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL> template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL, hyperstone_device::sign_mode SIGNED>
void hyperstone_device::hyperstone_mulu() void hyperstone_device::hyperstone_mulsu()
{ {
check_delay_PC(); check_delay_PC();
@ -2251,13 +2203,13 @@ void hyperstone_device::hyperstone_mulu()
if ((SRC_GLOBAL && src_code < 2) || (DST_GLOBAL && dst_code < 2)) if ((SRC_GLOBAL && src_code < 2) || (DST_GLOBAL && dst_code < 2))
{ {
LOG("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC); LOG("Denoted PC or SR in hyperstone_muls/u instruction. PC = %08X\n", PC);
return; return;
} }
const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code]; const uint32_t dreg = (DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code]; const uint32_t sreg = (SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
const uint64_t double_word = (uint64_t)sreg *(uint64_t)dreg; const uint64_t double_word = SIGNED ? (uint64_t)((int64_t)(int32_t)sreg * (int64_t)(int32_t)dreg) : ((uint64_t)sreg *(uint64_t)dreg);
const uint32_t high_order = (uint32_t)(double_word >> 32); const uint32_t high_order = (uint32_t)(double_word >> 32);
@ -2269,43 +2221,9 @@ void hyperstone_device::hyperstone_mulu()
SR |= Z_MASK; SR |= Z_MASK;
SR |= SIGN_TO_N(high_order); SR |= SIGN_TO_N(high_order);
if(sreg <= 0xffff && dreg <= 0xffff) if(SIGNED == IS_SIGNED && (sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff))
m_icount -= m_clock_cycles_4; m_icount -= m_clock_cycles_4;
else else if(SIGNED == IS_UNSIGNED && sreg <= 0xffff && dreg <= 0xffff)
m_icount -= m_clock_cycles_6;
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::hyperstone_muls()
{
check_delay_PC();
const uint32_t fp = GET_FP;
const uint32_t src_code = SRC_GLOBAL ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t dst_code = DST_GLOBAL ? DST_CODE : ((DST_CODE + fp) & 0x3f);
const uint32_t dstf_code = DST_GLOBAL ? (dst_code + 1) : ((dst_code + 1) & 0x3f);
if ((SRC_GLOBAL && src_code < 2) || (DST_GLOBAL && dst_code < 2))
{
LOG("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC);
return;
}
const int32_t dreg = (int32_t)(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code];
const int32_t sreg = (int32_t)(SRC_GLOBAL ? m_global_regs : m_local_regs)[src_code];
const int64_t double_word = (int64_t)sreg * (int64_t)dreg;
const uint32_t high_order = (uint32_t)(double_word >> 32);
(DST_GLOBAL ? m_global_regs : m_local_regs)[dst_code] = high_order;
(DST_GLOBAL ? m_global_regs : m_local_regs)[dstf_code] = (uint32_t)double_word;
SR &= ~(Z_MASK | N_MASK);
if (double_word == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(high_order);
if((sreg >= 0xffff8000 && sreg <= 0x7fff) && (dreg >= 0xffff8000 && dreg <= 0x7fff))
m_icount -= m_clock_cycles_4; m_icount -= m_clock_cycles_4;
else else
m_icount -= m_clock_cycles_6; m_icount -= m_clock_cycles_6;