hyperstone: template register-register mov and correct trap behaviour

(nw) privilege trap should prevent user state code from writing high
global registers; also change DEBUG_PRINTF to standard logmacro.h
stuff
This commit is contained in:
Vas Crabb 2017-11-15 16:47:52 +11:00
parent 50637d602b
commit cebbf30159
3 changed files with 95 additions and 166 deletions

View File

@ -220,11 +220,8 @@
#include "32xsdefs.h"
#ifdef MAME_DEBUG
#define DEBUG_PRINTF(x) do { osd_printf_debug x; } while (0)
#else
#define DEBUG_PRINTF(x) do { } while (0)
#endif
//#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// INTERNAL ADDRESS MAP
@ -473,7 +470,7 @@ void hyperstone_device::hyperstone_set_trap_entry(int which)
break;
default:
DEBUG_PRINTF(("Set entry point to a reserved value: %d\n", which));
LOG("Set entry point to a reserved value: %d\n", which);
break;
}
}
@ -573,23 +570,23 @@ uint32_t hyperstone_device::get_global_register(uint8_t code)
case 29:
case 30:
case 31:
DEBUG_PRINTF(("read _Reserved_ Global Register %d @ %08X\n",code,PC));
LOG("read _Reserved_ Global Register %d @ %08X\n",code,PC);
break;
case BCR_REGISTER:
DEBUG_PRINTF(("read write-only BCR register @ %08X\n",PC));
LOG("read write-only BCR register @ %08X\n",PC);
return 0;
case TPR_REGISTER:
DEBUG_PRINTF(("read write-only TPR register @ %08X\n",PC));
LOG("read write-only TPR register @ %08X\n",PC);
return 0;
case FCR_REGISTER:
DEBUG_PRINTF(("read write-only FCR register @ %08X\n",PC));
LOG("read write-only FCR register @ %08X\n",PC);
return 0;
case MCR_REGISTER:
DEBUG_PRINTF(("read write-only MCR register @ %08X\n",PC));
LOG("read write-only MCR register @ %08X\n",PC);
return 0;
}
}
@ -706,15 +703,15 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val)
#define SIGN_BIT(val) ((val & 0x80000000) >> 31)
#define SIGN_TO_N(val) ((val & 0x80000000) >> 29)
static const int32_t immediate_values[32] =
static constexpr int32_t immediate_values[32] =
{
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 0, 0, 0, 32, 64, 128, static_cast<int32_t>(0x80000000),
16, 0, 0, 0, 32, 64, 128, int32_t(0x80000000),
-8, -7, -6, -5, -4, -3, -2, -1
};
#define WRITE_ONLY_REGMASK ((1 << BCR_REGISTER) | (1 << TPR_REGISTER) | (1 << FCR_REGISTER) | (1 << MCR_REGISTER))
constexpr uint32_t WRITE_ONLY_REGMASK = (1 << BCR_REGISTER) | (1 << TPR_REGISTER) | (1 << FCR_REGISTER) | (1 << MCR_REGISTER);
#define check_delay_PC() \
do \
@ -929,7 +926,7 @@ void hyperstone_device::execute_exception(uint32_t addr)
PPC = PC;
PC = addr;
DEBUG_PRINTF(("EXCEPTION! PPC = %08X PC = %08X\n",PPC-2,PC-2));
LOG("EXCEPTION! PPC = %08X PC = %08X\n",PPC-2,PC-2);
m_icount -= m_clock_cycles_2;
}
@ -1600,7 +1597,7 @@ void hyperstone_device::execute_set_input(int inputnum, int state)
void hyperstone_device::hyperstone_reserved()
{
DEBUG_PRINTF(("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP));
LOG("Executed Reserved opcode. PC = %08X OP = %04X\n", PC, OP);
}
void hyperstone_device::hyperstone_do()
@ -1670,10 +1667,10 @@ void hyperstone_device::execute_run()
case 0x21: hyperstone_cmp<GLOBAL, LOCAL>(); break;
case 0x22: hyperstone_cmp<LOCAL, GLOBAL>(); break;
case 0x23: hyperstone_cmp<LOCAL, LOCAL>(); break;
case 0x24: hyperstone_mov_global_global(); break;
case 0x25: hyperstone_mov_global_local(); break;
case 0x26: hyperstone_mov_local_global(); break;
case 0x27: hyperstone_mov_local_local(); break;
case 0x24: hyperstone_mov<GLOBAL, GLOBAL>(); break;
case 0x25: hyperstone_mov<GLOBAL, LOCAL>(); break;
case 0x26: hyperstone_mov<LOCAL, GLOBAL>(); break;
case 0x27: hyperstone_mov<LOCAL, LOCAL>(); break;
case 0x28: hyperstone_add<GLOBAL, GLOBAL>(); break;
case 0x29: hyperstone_add<GLOBAL, LOCAL>(); break;
case 0x2a: hyperstone_add<LOCAL, GLOBAL>(); break;

View File

@ -226,10 +226,7 @@ private:
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_sum();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_sums();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_cmp();
void hyperstone_mov_global_global();
void hyperstone_mov_global_local();
void hyperstone_mov_local_global();
void hyperstone_mov_local_local();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_mov();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_add();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_adds();
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void hyperstone_cmpb();

View File

@ -39,7 +39,7 @@ void hyperstone_device::hyperstone_movd_global_global()
// RET instruction
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in RET instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in RET instruction. PC = %08X\n", PC);
m_icount -= m_clock_cycles_1;
return;
}
@ -227,7 +227,7 @@ void hyperstone_device::hyperstone_divu_global_global()
if (src_code == dst_code || src_code == dstf_code || src_code < 2)
{
DEBUG_PRINTF(("Denoted the same register code or PC/SR as source in hyperstone_divu instruction. PC = %08X\n", PC));
LOG("Denoted the same register code or PC/SR as source in hyperstone_divu instruction. PC = %08X\n", PC);
m_icount -= 36 << m_clck_scale;
return;
}
@ -305,7 +305,7 @@ void hyperstone_device::hyperstone_divu_local_global()
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted the same register code or PC/SR as source in hyperstone_divu instruction. PC = %08X\n", PC));
LOG("Denoted the same register code or PC/SR as source in hyperstone_divu instruction. PC = %08X\n", PC);
m_icount -= 36 << m_clck_scale;
return;
}
@ -390,7 +390,7 @@ void hyperstone_device::hyperstone_divs_global_global()
if(src_code == dst_code || src_code == dstf_code || src_code < 2)
{
DEBUG_PRINTF(("Denoted invalid register code in hyperstone_divs instruction. PC = %08X\n", PC));
LOG("Denoted invalid register code in hyperstone_divs instruction. PC = %08X\n", PC);
m_icount -= 36 << m_clck_scale;
return;
}
@ -465,7 +465,7 @@ void hyperstone_device::hyperstone_divs_local_global()
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR as source register in hyperstone_divs instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR as source register in hyperstone_divs instruction. PC = %08X\n", PC);
m_icount -= 36 << m_clck_scale;
return;
}
@ -570,7 +570,7 @@ void hyperstone_device::hyperstone_xm()
if ((SRC_GLOBAL && (src_code == SR_REGISTER)) || (DST_GLOBAL && (dst_code < 2)))
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_xm. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_xm. PC = %08X\n", PC);
m_icount -= m_clock_cycles_1;
return;
}
@ -712,108 +712,41 @@ void hyperstone_device::hyperstone_cmp()
m_icount -= m_clock_cycles_1;
}
void hyperstone_device::hyperstone_mov_global_global()
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::hyperstone_mov()
{
check_delay_PC();
const uint32_t dst_code = DST_CODE;
uint32_t sreg;
if (SR & H_MASK)
const bool h = (SR & H_MASK) != 0;
if (DST_GLOBAL && h && !(SR & S_MASK))
{
if (!(SR & S_MASK))
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
const uint32_t src_code = SRC_CODE + 16;
sreg = (WRITE_ONLY_REGMASK & (1 << src_code)) ? 0 : get_global_register(src_code);
set_global_register(dst_code + 16, sreg);
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
}
else
{
sreg = m_global_regs[SRC_CODE];
m_global_regs[dst_code] = sreg;
const uint32_t fp = GET_FP;
const uint32_t src_code = SRC_GLOBAL ? (SRC_CODE + (h ? 16 : 0)) : ((SRC_CODE + fp) & 0x3f);
const uint32_t sreg = SRC_GLOBAL ? ((WRITE_ONLY_REGMASK & (1 << src_code)) ? 0 : get_global_register(src_code)) : m_local_regs[src_code];
if (dst_code == PC_REGISTER)
SR &= ~M_MASK;
if (DST_GLOBAL)
{
const uint32_t dst_code = DST_CODE + (h ? 16 : 0);
set_global_register(dst_code, sreg);
if (dst_code == PC_REGISTER)
SR &= ~M_MASK;
}
else
{
m_local_regs[(DST_CODE + fp) & 0x3f] = sreg;
}
SR &= ~(Z_MASK | N_MASK);
if (sreg == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(sreg);
}
SR &= ~(Z_MASK | N_MASK);
if (sreg == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(sreg);
m_icount -= m_clock_cycles_1;
}
void hyperstone_device::hyperstone_mov_global_local()
{
check_delay_PC();
const uint32_t dst_code = DST_CODE;
const uint32_t sreg = m_local_regs[(SRC_CODE + GET_FP) & 0x3f];
if (SR & H_MASK)
{
if (!(SR & S_MASK))
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
set_global_register(DST_CODE + 16, sreg);
}
else
{
m_global_regs[dst_code] = sreg;
if (dst_code == PC_REGISTER)
SR &= ~M_MASK;
}
SR &= ~(Z_MASK | N_MASK);
if (sreg == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(sreg);
m_icount -= m_clock_cycles_1;
}
void hyperstone_device::hyperstone_mov_local_global()
{
check_delay_PC();
uint32_t src_code = SRC_CODE;
uint32_t sreg;
if (SR & H_MASK)
{
src_code += 16;
sreg = (WRITE_ONLY_REGMASK & (1 << src_code)) ? 0 : get_global_register(src_code);
}
else
{
sreg = m_global_regs[src_code]; \
}
m_local_regs[(DST_CODE + GET_FP) & 0x3f] = sreg;
SR &= ~(Z_MASK | N_MASK);
if (sreg == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(sreg);
m_icount -= m_clock_cycles_1;
}
void hyperstone_device::hyperstone_mov_local_local()
{
check_delay_PC();
const uint32_t fp = GET_FP;
const uint32_t sreg = m_local_regs[(SRC_CODE + fp) & 0x3f];
m_local_regs[(DST_CODE + fp) & 0x3f] = sreg;
SR &= ~(Z_MASK | N_MASK);
if (sreg == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(sreg);
m_icount -= m_clock_cycles_1;
}
@ -1293,34 +1226,36 @@ void hyperstone_device::hyperstone_movi()
if (!IMM_LONG)
imm = immediate_values[m_op & 0x0f];
if (DST_GLOBAL)
const bool h = (SR & H_MASK) != 0;
if (DST_GLOBAL && h && !(SR & S_MASK))
{
uint32_t dst_code = DST_CODE;
if (SR & H_MASK)
{
dst_code += 16;
if (!(SR & S_MASK))
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
}
set_global_register(dst_code, imm);
if (dst_code == PC_REGISTER)
SR &= ~M_MASK;
execute_exception(get_trap_addr(TRAPNO_PRIVILEGE_ERROR));
}
else
{
m_local_regs[(DST_CODE + GET_FP) & 0x3f] = imm;
}
if (DST_GLOBAL)
{
const uint32_t dst_code = DST_CODE + (h ? 16 : 0);
set_global_register(dst_code, imm);
SR &= ~(Z_MASK | N_MASK);
if (imm == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(imm);
if (dst_code == PC_REGISTER)
SR &= ~M_MASK;
}
else
{
m_local_regs[(DST_CODE + GET_FP) & 0x3f] = imm;
}
SR &= ~(Z_MASK | N_MASK);
if (imm == 0)
SR |= Z_MASK;
SR |= SIGN_TO_N(imm);
#if MISSIONCRAFT_FLAGS
SR &= ~V_MASK; // or V undefined ?
SR &= ~V_MASK; // or V undefined ?
#endif
}
m_icount -= m_clock_cycles_1;
}
@ -1845,7 +1780,7 @@ void hyperstone_device::hyperstone_shld()
// result undefined if Ls denotes the same register as Ld or Ldf
if (src_code == dst_code || src_code == dstf_code)
{
DEBUG_PRINTF(("Denoted same registers in hyperstone_shld. PC = %08X\n", PC));
LOG("Denoted same registers in hyperstone_shld. PC = %08X\n", PC);
m_icount -= m_clock_cycles_2;
return;
}
@ -2444,7 +2379,7 @@ void hyperstone_device::hyperstone_ldxx2_global_global()
if (dst_code < 2)
{
m_icount -= m_clock_cycles_1;
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC);
return;
}
@ -2493,7 +2428,7 @@ void hyperstone_device::hyperstone_ldxx2_global_global()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC);
break;
case 3: // LDW.S
if (dreg < SP)
@ -2553,7 +2488,7 @@ void hyperstone_device::hyperstone_ldxx2_global_local()
if (dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC);
m_icount -= m_clock_cycles_1;
return;
}
@ -2592,7 +2527,7 @@ void hyperstone_device::hyperstone_ldxx2_global_local()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC);
break;
case 3: // LDW.S
if (dreg < SP)
@ -2678,7 +2613,7 @@ void hyperstone_device::hyperstone_ldxx2_local_global()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC);
break;
case 3: // LDW.S
if (dreg < SP)
@ -2772,7 +2707,7 @@ void hyperstone_device::hyperstone_ldxx2_local_local()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_ldxx2. PC = %08X\n", PC);
break;
case 3: // LDW.S
if (dreg < SP)
@ -3270,7 +3205,7 @@ void hyperstone_device::hyperstone_stxx2_global_global()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC);
break;
case 3: // STW.S
if(dreg < SP)
@ -3320,7 +3255,7 @@ void hyperstone_device::hyperstone_stxx2_global_local()
if (dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_stxx2. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_stxx2. PC = %08X\n", PC);
m_icount -= m_clock_cycles_1;
return;
}
@ -3364,7 +3299,7 @@ void hyperstone_device::hyperstone_stxx2_global_local()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC);
break;
case 3: // STW.S
if(dreg < SP)
@ -3452,7 +3387,7 @@ void hyperstone_device::hyperstone_stxx2_local_global()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC);
break;
case 3: // STW.S
if(dreg < SP)
@ -3540,7 +3475,7 @@ void hyperstone_device::hyperstone_stxx2_local_local()
m_icount -= m_clock_cycles_1; // extra cycle
break;
case 2: // Reserved
DEBUG_PRINTF(("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC));
LOG("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", PC);
break;
case 3: // STW.S
if(dreg < SP)
@ -3725,7 +3660,7 @@ void hyperstone_device::hyperstone_mulu_global_global()
if (src_code < 2 || dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC);
return;
}
@ -3758,7 +3693,7 @@ void hyperstone_device::hyperstone_mulu_global_local()
if (dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC);
return;
}
@ -3792,7 +3727,7 @@ void hyperstone_device::hyperstone_mulu_local_global()
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mulu instruction. PC = %08X\n", PC);
return;
}
@ -3855,7 +3790,7 @@ void hyperstone_device::hyperstone_muls_global_global()
if (src_code < 2 || dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC);
return;
}
@ -3889,7 +3824,7 @@ void hyperstone_device::hyperstone_muls_global_local()
if (dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC);
return;
}
@ -3926,7 +3861,7 @@ void hyperstone_device::hyperstone_muls_local_global()
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_muls instruction. PC = %08X\n", PC);
return;
}
@ -4006,7 +3941,7 @@ void hyperstone_device::hyperstone_set_global()
case 16:
case 17:
case 19:
DEBUG_PRINTF(("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC));
LOG("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC);
break;
// SETxx
@ -4213,7 +4148,7 @@ void hyperstone_device::hyperstone_set_local()
case 16:
case 17:
case 19:
DEBUG_PRINTF(("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC));
LOG("Used reserved N value (%d) in hyperstone_set. PC = %08X\n", n, PC);
break;
// SETxx
@ -4410,7 +4345,7 @@ void hyperstone_device::hyperstone_mul_global_global()
if (src_code < 2 || dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC);
return;
}
@ -4440,7 +4375,7 @@ void hyperstone_device::hyperstone_mul_global_local()
if (dst_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC);
return;
}
@ -4470,7 +4405,7 @@ void hyperstone_device::hyperstone_mul_local_global()
if (src_code < 2)
{
DEBUG_PRINTF(("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC));
LOG("Denoted PC or SR in hyperstone_mul instruction. PC = %08X\n", PC);
return;
}
@ -4641,7 +4576,7 @@ void hyperstone_device::hyperstone_extend()
}
default:
DEBUG_PRINTF(("Executed Illegal extended opcode (%X). PC = %08X\n", func, PC));
LOG("Executed Illegal extended opcode (%X). PC = %08X\n", func, PC);
break;
}