cpu/e132xs: Emulate more exceptions, more recompiler optimisation.

Emulate pointer error exception on load/store and range error exception
on store signed byte/half-word.

Further optimised code generation for MOV and MOVI.  These are very hot,
so this alone gains a further 2% performance or so in the dgPIX games.

Also some other miscellaneous cleanup.
This commit is contained in:
Vas Crabb 2025-03-31 04:38:51 +11:00
parent 2fb28016e5
commit eed05ed158
9 changed files with 386 additions and 193 deletions

View File

@ -31,8 +31,7 @@
- GMS30C2232 - GMS30C2232
TODO: TODO:
- Pointer error exception on zero address register for interpreter - All instructions should clear the H flag (not just MOV/MOVI)
- Range error exception on store signed byte/half-word
- Fix behaviour of exceptions in delay slots - Fix behaviour of exceptions in delay slots
- Fix behaviour of branches in delay slots - Fix behaviour of branches in delay slots
- Many wrong cycle counts - Many wrong cycle counts

View File

@ -465,7 +465,7 @@ private:
uint32_t generate_get_pcrel(const opcode_desc *desc); uint32_t generate_get_pcrel(const opcode_desc *desc);
std::pair<uint16_t, uint32_t> generate_get_d_code_dis(const opcode_desc *opcode); std::pair<uint16_t, uint32_t> generate_get_d_code_dis(const opcode_desc *opcode);
void generate_get_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); void generate_get_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t code, uml::parameter dst);
void generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code); void generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code);
void generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src); void generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src);
void generate_set_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src); void generate_set_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src);

View File

@ -26,6 +26,9 @@ public:
compiler_state &operator=(compiler_state const &) = delete; compiler_state &operator=(compiler_state const &) = delete;
uint8_t mode() const { return m_mode; } uint8_t mode() const { return m_mode; }
bool user_mode() const { return !BIT(m_mode, 0); }
bool supervisor_mode() const { return BIT(m_mode, 0); }
bool trace_mode() const { return BIT(m_mode, 1); }
auto next_label() { return m_labelnum++; } auto next_label() { return m_labelnum++; }
@ -828,7 +831,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi
--compiler.m_check_delay; --compiler.m_check_delay;
} }
if (BIT(compiler.mode(), 1) && !desc->delayslots) if (compiler.trace_mode() && !desc->delayslots)
UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_TRACE_EXCEPTION); UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_TRACE_EXCEPTION);
} }
else else

View File

@ -127,6 +127,29 @@ inline void hyperstone_device::generate_add_dis(drcuml_block &block, compiler_st
} }
void hyperstone_device::generate_get_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t code, uml::parameter dst)
{
// Expects cycles in I7 (cleared after use)
code |= 0x10;
if (code == TR_REGISTER)
{
UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I7);
UML_MOV(block, I7, 0);
UML_SHR(block, dst, mem(&m_core->tr_clocks_per_tick), 1);
UML_CMP(block, mem(&m_core->icount), dst);
UML_MOVc(block, uml::COND_BE, dst, 0);
UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), dst);
UML_CALLC(block, &c_funcs::compute_tr, this);
UML_MOV(block, dst, mem(&m_core->tr_result));
}
else
{
UML_MOV(block, dst, mem(&m_core->global_regs[code]));
}
}
void hyperstone_device::generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code) void hyperstone_device::generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code)
{ {
// TODO: this function should be refactored away // TODO: this function should be refactored away
@ -231,7 +254,7 @@ void hyperstone_device::generate_set_global_register_low(drcuml_block &block, co
else if (dst_code == SR_REGISTER) else if (dst_code == SR_REGISTER)
{ {
UML_MOV(block, I4, DRC_SR); UML_MOV(block, I4, DRC_SR);
if (BIT(compiler.mode(), 0) || (src.is_immediate() && !(src.immediate() & L_MASK))) if (compiler.supervisor_mode() || (src.is_immediate() && !(src.immediate() & L_MASK)))
{ {
UML_ROLINS(block, I4, src, 0, 0x0000ffff); UML_ROLINS(block, I4, src, 0, 0x0000ffff);
UML_AND(block, I4, I4, ~0x40); // keep reserved bit clear UML_AND(block, I4, I4, ~0x40); // keep reserved bit clear
@ -923,7 +946,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi
UML_AND(block, I0, I0, ~uint32_t(1)); UML_AND(block, I0, I0, ~uint32_t(1));
UML_MOV(block, DRC_PC, I0); UML_MOV(block, DRC_PC, I0);
if (!BIT(compiler.mode(), 0)) if (compiler.user_mode())
{ {
// privilege exception on setting S or L // privilege exception on setting S or L
UML_XOR(block, I3, I3, ~uint32_t(0)); UML_XOR(block, I3, I3, ~uint32_t(0));
@ -1288,38 +1311,6 @@ void hyperstone_device::generate_cmp(drcuml_block &block, compiler_state &compil
UML_MOV(block, DRC_SR, I2); UML_MOV(block, DRC_SR, I2);
} }
void hyperstone_device::generate_get_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
const uint16_t op = desc->opptr.w[0];
const uint32_t src_code = op & 0xf;
int regular_load = compiler.next_label();
int done = compiler.next_label();
UML_TEST(block, DRC_SR, H_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 16 + src_code);
UML_MOVc(block, uml::COND_Z, I1, src_code);
UML_CMP(block, I1, TR_REGISTER);
UML_JMPc(block, uml::COND_NE, regular_load);
UML_SHR(block, I2, mem(&m_core->tr_clocks_per_tick), 1);
UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I7);
UML_MOV(block, I7, 0);
UML_CMP(block, mem(&m_core->icount), I2);
UML_MOVc(block, uml::COND_BE, I2, 0);
UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I2);
UML_CALLC(block, &c_funcs::compute_tr, this);
UML_MOV(block, I5, mem(&m_core->tr_result));
UML_JMP(block, done);
UML_LABEL(block, regular_load);
UML_LOAD(block, I5, (void *)m_core->global_regs, I1, SIZE_DWORD, SCALE_x4);
UML_SHL(block, I2, 1, I1);
UML_TEST(block, I2, WRITE_ONLY_REGMASK);
UML_MOVc(block, uml::COND_NZ, I5, 0);
UML_LABEL(block, done);
}
template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal> template <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal>
void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{ {
@ -1329,68 +1320,108 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil
const uint32_t src_code = op & 0xf; const uint32_t src_code = op & 0xf;
const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t dst_code = (op & 0xf0) >> 4;
int done; UML_AND(block, I2, DRC_SR, ~(Z_MASK | N_MASK));
if (DstGlobal) if (!SrcGlobal || !DstGlobal)
UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f);
if (DstGlobal && compiler.user_mode())
{ {
done = compiler.next_label(); UML_TEST(block, I2, H_MASK);
if (!BIT(compiler.mode(), 0)) UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_PRIVILEGE_ERROR);
{
const int no_exception = compiler.next_label();
UML_TEST(block, DRC_SR, H_MASK);
UML_JMPc(block, uml::COND_Z, no_exception);
UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR);
UML_JMP(block, done);
UML_LABEL(block, no_exception);
}
} }
if (SrcGlobal) if (SrcGlobal)
{ {
generate_get_global_register(block, compiler, desc); if (!DstGlobal || compiler.supervisor_mode())
if (!DstGlobal) {
UML_ROLAND(block, I1, DRC_SR, 32 - FP_SHIFT, 0x7f); const int highglobal = compiler.next_label();
const int done = compiler.next_label();
UML_TEST(block, I2, H_MASK);
UML_JMPc(block, uml::COND_NZ, highglobal);
UML_MOV(block, I0, mem(&m_core->global_regs[src_code]));
UML_JMP(block, done);
UML_LABEL(block, highglobal);
generate_get_global_register_high(block, compiler, src_code, uml::I0);
UML_LABEL(block, done);
}
else
{
UML_MOV(block, I0, mem(&m_core->global_regs[src_code]));
}
}
else if (DstGlobal || (src_code == dst_code))
{
UML_ADD(block, I3, I3, src_code);
UML_AND(block, I3, I3, 0x3f);
UML_LOAD(block, I0, (void *)m_core->local_regs, I3, SIZE_DWORD, SCALE_x4);
} }
else else
{ {
UML_ROLAND(block, I1, DRC_SR, 32 - FP_SHIFT, 0x7f); UML_ADD(block, I0, I3, src_code);
UML_ADD(block, I2, I1, src_code); UML_AND(block, I0, I0, 0x3f);
UML_AND(block, I2, I2, 0x3f); UML_LOAD(block, I0, (void *)m_core->local_regs, I0, SIZE_DWORD, SCALE_x4);
UML_LOAD(block, I5, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
} }
UML_AND(block, DRC_SR, DRC_SR, ~(Z_MASK | N_MASK)); UML_TEST(block, I0, ~uint32_t(0));
UML_TEST(block, I5, ~0); generate_update_nz(block, compiler, uml::I2);
UML_SETc(block, uml::COND_Z, I2);
UML_ROLINS(block, DRC_SR, I2, Z_SHIFT, Z_MASK);
UML_ROLINS(block, DRC_SR, I5, N_SHIFT + 1, N_MASK);
if (DstGlobal) if (DstGlobal)
{ {
const int highglobal = compiler.next_label(); if (compiler.supervisor_mode())
UML_TEST(block, DRC_SR, H_MASK);
UML_JMPc(block, uml::COND_NZ, highglobal);
generate_set_global_register_low(block, compiler, dst_code, uml::I5);
if (dst_code == PC_REGISTER)
{ {
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); const int highglobal = compiler.next_label();
UML_AND(block, I5, I5, ~uint32_t(1)); const int done = compiler.next_label();
generate_branch(block, compiler, compiler.mode(), uml::I5, desc);
UML_TEST(block, I2, H_MASK);
UML_JMPc(block, uml::COND_NZ, highglobal);
UML_MOV(block, DRC_SR, I2);
generate_set_global_register_low(block, compiler, dst_code, uml::I0);
if (dst_code == PC_REGISTER)
{
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
UML_AND(block, I0, I0, ~uint32_t(1));
generate_branch(block, compiler, compiler.mode(), uml::I0, desc);
}
else
{
UML_JMP(block, done);
}
UML_LABEL(block, highglobal);
UML_AND(block, I2, I2, ~H_MASK);
UML_MOV(block, DRC_SR, I2);
generate_set_global_register_high(block, compiler, dst_code, uml::I0);
UML_LABEL(block, done);
}
else
{
UML_MOV(block, DRC_SR, I2);
generate_set_global_register_low(block, compiler, dst_code, uml::I0);
if (dst_code == PC_REGISTER)
{
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
UML_AND(block, I0, I0, ~uint32_t(1));
generate_branch(block, compiler, compiler.mode(), uml::I0, desc);
}
} }
UML_JMP(block, done);
UML_LABEL(block, highglobal);
UML_AND(block, DRC_SR, DRC_SR, ~H_MASK);
generate_set_global_register_high(block, compiler, dst_code, uml::I5);
UML_LABEL(block, done);
} }
else else
{ {
UML_AND(block, DRC_SR, DRC_SR, ~H_MASK); UML_AND(block, I2, I2, ~H_MASK);
UML_ADD(block, I2, I1, dst_code); UML_MOV(block, DRC_SR, I2);
UML_AND(block, I2, I2, 0x3f);
UML_STORE(block, (void *)m_core->local_regs, I2, I5, SIZE_DWORD, SCALE_x4); if (SrcGlobal || (src_code != dst_code))
{
UML_ADD(block, I3, I3, dst_code);
UML_AND(block, I3, I3, 0x3f);
UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4);
}
} }
} }
@ -1799,6 +1830,13 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
src = op & 0x0f; src = op & 0x0f;
UML_AND(block, I2, DRC_SR, ~(Z_MASK | N_MASK)); UML_AND(block, I2, DRC_SR, ~(Z_MASK | N_MASK));
if (DstGlobal && compiler.user_mode())
{
UML_TEST(block, I2, H_MASK);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_PRIVILEGE_ERROR);
}
if (!src) if (!src)
UML_OR(block, I2, I2, Z_MASK); UML_OR(block, I2, I2, Z_MASK);
else if (src & 0x80000000) else if (src & 0x80000000)
@ -1807,48 +1845,55 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
UML_AND(block, I2, I2, ~V_MASK); UML_AND(block, I2, I2, ~V_MASK);
#endif #endif
if (DstGlobal && !BIT(compiler.mode(), 0))
{
const int no_exception = compiler.next_label();
UML_TEST(block, I2, H_MASK);
UML_JMPc(block, uml::COND_Z, no_exception);
UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR);
UML_LABEL(block, no_exception);
}
UML_MOV(block, DRC_SR, I2);
if (DstGlobal) if (DstGlobal)
{ {
const int highglobal = compiler.next_label(); if (compiler.supervisor_mode())
const int done = compiler.next_label();
UML_TEST(block, I2, H_MASK);
UML_JMPc(block, uml::COND_NZ, highglobal);
generate_set_global_register_low(block, compiler, dst_code, src);
if (dst_code == PC_REGISTER)
{ {
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); const int highglobal = compiler.next_label();
generate_branch(block, compiler, compiler.mode(), src & ~uint32_t(1), desc); const int done = compiler.next_label();
UML_TEST(block, I2, H_MASK);
UML_JMPc(block, uml::COND_NZ, highglobal);
UML_MOV(block, DRC_SR, I2);
generate_set_global_register_low(block, compiler, dst_code, src);
if (dst_code == PC_REGISTER)
{
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
generate_branch(block, compiler, compiler.mode(), src & ~uint32_t(1), desc);
}
else
{
UML_JMP(block, done);
}
UML_LABEL(block, highglobal);
UML_AND(block, I2, I2, ~H_MASK);
UML_MOV(block, DRC_SR, I2);
generate_set_global_register_high(block, compiler, dst_code, src);
UML_LABEL(block, done);
} }
else else
{ {
UML_JMP(block, done); UML_MOV(block, DRC_SR, I2);
generate_set_global_register_low(block, compiler, dst_code, src);
if (dst_code == PC_REGISTER)
{
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
generate_branch(block, compiler, compiler.mode(), src & ~uint32_t(1), desc);
}
} }
UML_LABEL(block, highglobal);
UML_AND(block, DRC_SR, DRC_SR, ~H_MASK);
generate_set_global_register_high(block, compiler, dst_code, src);
UML_LABEL(block, done);
} }
else else
{ {
UML_AND(block, DRC_SR, DRC_SR, ~H_MASK); UML_AND(block, I2, I2, ~H_MASK);
UML_ROLAND(block, I2, DRC_SR, 32 - FP_SHIFT, 0x7f); UML_MOV(block, DRC_SR, I2);
UML_ADD(block, I0, I2, dst_code);
UML_AND(block, I0, I0, 0x3f); UML_ROLAND(block, I2, I2, 32 - FP_SHIFT, 0x7f);
UML_STORE(block, (void *)m_core->local_regs, I0, src, SIZE_DWORD, SCALE_x4); UML_ADD(block, I2, I2, dst_code);
UML_AND(block, I2, I2, 0x3f);
UML_STORE(block, (void *)m_core->local_regs, I2, src, SIZE_DWORD, SCALE_x4);
} }
} }
@ -2967,17 +3012,29 @@ void hyperstone_device::generate_stxx1(drcuml_block &block, compiler_state &comp
{ {
case 0: // STBS.D/A case 0: // STBS.D/A
case 1: // STBU.D/A case 1: // STBU.D/A
// TODO: missing trap on range error for STBS.D/A
UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
generate_add_dis(block, compiler, uml::I0, dstp, extra_s, 1); generate_add_dis(block, compiler, uml::I0, dstp, extra_s, 1);
UML_CALLH(block, *m_mem_write8); UML_CALLH(block, *m_mem_write8);
if (sub_type == 0)
{
UML_SEXT(block, I0, I1, SIZE_BYTE);
UML_CMP(block, I0, I1);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR);
}
break; break;
case 2: // STHS.D/A, STHU.D/A case 2: // STHS.D/A, STHU.D/A
// TODO: missing trap on range error with STHS.D/A
UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
generate_add_dis(block, compiler, uml::I0, dstp, extra_s, 2); generate_add_dis(block, compiler, uml::I0, dstp, extra_s, 2);
UML_CALLH(block, *m_mem_write16); UML_CALLH(block, *m_mem_write16);
if (extra_s & 1)
{
UML_SEXT(block, I0, I1, SIZE_WORD);
UML_CMP(block, I0, I1);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR);
}
break; break;
case 3: case 3:
@ -3072,38 +3129,52 @@ void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &comp
} }
else else
{ {
UML_ADD(block, I2, I3, src_code); UML_ADD(block, I1, I3, src_code);
UML_AND(block, I5, I2, 0x3f); UML_AND(block, I1, I1, 0x3f);
UML_LOAD(block, I1, (void *)m_core->local_regs, I5, SIZE_DWORD, SCALE_x4); UML_LOAD(block, I1, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
} }
switch (sub_type) switch (sub_type)
{ {
case 0: // STBS.N case 0: // STBS.N
case 1: // STBU.N case 1: // STBU.N
// TODO: missing trap on range error with STBS.N
UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
UML_CALLH(block, *m_mem_write8); UML_CALLH(block, *m_mem_write8);
UML_ADD(block, I0, I0, extra_s);
UML_ADD(block, I0, I0, extra_s);
if (DstGlobal) if (DstGlobal)
UML_MOV(block, mem(&m_core->global_regs[dst_code]), I0); UML_MOV(block, mem(&m_core->global_regs[dst_code]), I0);
else else
UML_STORE(block, (void *)m_core->local_regs, I6, I0, SIZE_DWORD, SCALE_x4); UML_STORE(block, (void *)m_core->local_regs, I6, I0, SIZE_DWORD, SCALE_x4);
if (sub_type == 0)
{
UML_SEXT(block, I0, I1, SIZE_BYTE);
UML_CMP(block, I0, I1);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR);
}
break; break;
case 2: // STHS.N, STHU.N case 2: // STHS.N, STHU.N
// TODO: missing trap on range error with STHS.N
UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
UML_MOV(block, I5, I0); UML_MOV(block, I4, I0);
UML_AND(block, I0, I0, ~1); UML_AND(block, I0, I0, ~1);
UML_CALLH(block, *m_mem_write16); UML_CALLH(block, *m_mem_write16);
UML_ADD(block, I5, I5, extra_s & ~1);
UML_ADD(block, I4, I4, extra_s & ~1);
if (DstGlobal) if (DstGlobal)
UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); UML_MOV(block, mem(&m_core->global_regs[dst_code]), I4);
else else
UML_STORE(block, (void *)m_core->local_regs, I6, I5, SIZE_DWORD, SCALE_x4); UML_STORE(block, (void *)m_core->local_regs, I6, I4, SIZE_DWORD, SCALE_x4);
if (extra_s & 1)
{
UML_SEXT(block, I0, I1, SIZE_WORD);
UML_CMP(block, I0, I1);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR);
}
break; break;
case 3: case 3:
switch (extra_s & 3) switch (extra_s & 3)
{ {
@ -3119,6 +3190,7 @@ void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &comp
else else
UML_STORE(block, (void *)m_core->local_regs, I6, I5, SIZE_DWORD, SCALE_x4); UML_STORE(block, (void *)m_core->local_regs, I6, I5, SIZE_DWORD, SCALE_x4);
break; break;
case 1: // STD.N case 1: // STD.N
UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); UML_MOV(block, I7, mem(&m_core->clock_cycles_2));
UML_MOV(block, I5, I0); UML_MOV(block, I5, I0);
@ -3136,9 +3208,11 @@ void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &comp
UML_ADD(block, I0, I0, 4); UML_ADD(block, I0, I0, 4);
UML_CALLH(block, *m_mem_write32); UML_CALLH(block, *m_mem_write32);
break; break;
case 2: // Reserved case 2: // Reserved
osd_printf_error("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", desc->pc); osd_printf_error("Executed Reserved instruction in hyperstone_stxx2. PC = %08X\n", desc->pc);
break; break;
case 3: // STW.S case 3: // STW.S
{ {
UML_MOV(block, I7, mem(&m_core->clock_cycles_3)); UML_MOV(block, I7, mem(&m_core->clock_cycles_3));

View File

@ -1553,6 +1553,12 @@ void hyperstone_device::hyperstone_ldxx1()
const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + fp) & 0x3f); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + fp) & 0x3f);
const uint32_t dreg = ((DstGlobal && dst_code == SR_REGISTER) ? 0 : (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]); const uint32_t dreg = ((DstGlobal && dst_code == SR_REGISTER) ? 0 : (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]);
if ((!DstGlobal || (dst_code != SR_REGISTER)) && !dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
switch (sub_type) switch (sub_type)
{ {
case 0: // LDBS.D case 0: // LDBS.D
@ -1667,18 +1673,36 @@ void hyperstone_device::hyperstone_ldxx2()
check_delay_PC(); check_delay_PC();
const uint32_t fp = GET_FP; const uint32_t fp = GET_FP;
const uint32_t src_code = SrcGlobal ? SRC_CODE : (SRC_CODE + fp) & 0x3f;
const uint32_t srcf_code = SrcGlobal ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t dst_code = DstGlobal ? DST_CODE : (DST_CODE + fp) & 0x3f; const uint32_t dst_code = DstGlobal ? DST_CODE : (DST_CODE + fp) & 0x3f;
const uint32_t dreg = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code];
if (DstGlobal && dst_code < 2) if (DstGlobal && (dst_code <= SR_REGISTER))
{ {
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
LOG("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC); LOG("Denoted PC or SR in hyperstone_ldxx2. PC = %08X\n", PC);
return; return;
} }
const uint32_t src_code = SrcGlobal ? SRC_CODE : (SRC_CODE + fp) & 0x3f; if (!dreg)
const uint32_t srcf_code = SrcGlobal ? (src_code + 1) : ((src_code + 1) & 0x3f); {
const uint32_t dreg = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]; switch (sub_type)
{
case 0: // LDBS.N
case 1: // LDBU.N
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s;
break;
case 2: // LDHS.N, LDHU.N
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~1;
break;
case 3: // LDW.N, LDD.N, LDW.S
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~3;
break;
}
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
switch (sub_type) switch (sub_type)
{ {
@ -1716,7 +1740,7 @@ void hyperstone_device::hyperstone_ldxx2()
m_core->local_regs[src_code] = READ_HW(dreg); m_core->local_regs[src_code] = READ_HW(dreg);
} }
if(DstGlobal != SrcGlobal || src_code != dst_code) if (DstGlobal != SrcGlobal || src_code != dst_code)
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += (extra_s & ~1); (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += (extra_s & ~1);
break; break;
@ -1817,11 +1841,18 @@ void hyperstone_device::hyperstone_stxx1()
const uint32_t dreg = ((DstGlobal && dst_code == SR_REGISTER) ? 0 : (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]); const uint32_t dreg = ((DstGlobal && dst_code == SR_REGISTER) ? 0 : (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]);
const uint32_t sreg = ((SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]); const uint32_t sreg = ((SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]);
if ((!DstGlobal || (dst_code != SR_REGISTER)) && !dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
switch (sub_type) switch (sub_type)
{ {
case 0: // STBS.D case 0: // STBS.D
// TODO: missing trap on range error WRITE_B(dreg + extra_s, uint8_t(sreg));
WRITE_B(dreg + extra_s, (uint8_t)sreg); if (int8_t(uint8_t(sreg)) != int32_t(sreg))
execute_exception(TRAPNO_RANGE_ERROR);
break; break;
case 1: // STBU.D case 1: // STBU.D
@ -1829,8 +1860,9 @@ void hyperstone_device::hyperstone_stxx1()
break; break;
case 2: // STHS.D, STHU.D case 2: // STHS.D, STHU.D
WRITE_HW(dreg + (extra_s & ~1), (uint16_t)sreg); WRITE_HW(dreg + (extra_s & ~1), uint16_t(sreg));
// TODO: missing trap on range error with STHS.D if ((extra_s & 1) && (int16_t(uint16_t(sreg)) != int32_t(sreg)))
execute_exception(TRAPNO_RANGE_ERROR);
break; break;
case 3: case 3:
@ -1907,18 +1939,40 @@ void hyperstone_device::hyperstone_stxx2()
const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + fp) & 0x3f); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + fp) & 0x3f);
const uint32_t dreg = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]; const uint32_t dreg = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code];
if (DstGlobal && dst_code < 2) if (DstGlobal && (dst_code <= SR_REGISTER))
{ {
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
return; return;
} }
if (!dreg)
{
switch (sub_type)
{
case 0: // LDBS.N
case 1: // LDBU.N
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s;
break;
case 2: // LDHS.N, LDHU.N
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~1;
break;
case 3: // LDW.N, LDD.N, LDW.S
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~3;
break;
}
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
bool range_error;
switch (sub_type) switch (sub_type)
{ {
case 0: // STBS.N case 0: // STBS.N
// TODO: missing trap on range error
WRITE_B(dreg, (uint8_t)sreg); WRITE_B(dreg, (uint8_t)sreg);
range_error = int8_t(uint8_t(sreg)) != int32_t(sreg);
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s; (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s;
if (range_error)
execute_exception(TRAPNO_RANGE_ERROR);
break; break;
case 1: // STBU.N case 1: // STBU.N
@ -1928,8 +1982,10 @@ void hyperstone_device::hyperstone_stxx2()
case 2: // STHS.N, STHU.N case 2: // STHS.N, STHU.N
WRITE_HW(dreg, (uint16_t)sreg); WRITE_HW(dreg, (uint16_t)sreg);
range_error = (extra_s & 1) && (int16_t(uint16_t(sreg)) != int32_t(sreg));
(DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~1; (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code] += extra_s & ~1;
// TODO: missing trap on range error with STHS.N if (range_error)
execute_exception(TRAPNO_RANGE_ERROR);
break; break;
case 3: case 3:
@ -2316,11 +2372,20 @@ template <hyperstone_device::reg_bank SrcGlobal>
void hyperstone_device::hyperstone_ldwr() void hyperstone_device::hyperstone_ldwr()
{ {
check_delay_PC(); check_delay_PC();
const uint32_t fp = GET_FP; const uint32_t fp = GET_FP;
const uint32_t dreg = m_core->local_regs[(DST_CODE + fp) & 0x3f];
if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
if (SrcGlobal) if (SrcGlobal)
set_global_register(SRC_CODE, READ_W(m_core->local_regs[(DST_CODE + fp) & 0x3f])); set_global_register(SRC_CODE, READ_W(dreg));
else else
m_core->local_regs[(SRC_CODE + fp) & 0x3f] = READ_W(m_core->local_regs[(DST_CODE + fp) & 0x3f]); m_core->local_regs[(SRC_CODE + fp) & 0x3f] = READ_W(dreg);
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
} }
@ -2333,6 +2398,12 @@ void hyperstone_device::hyperstone_lddr()
const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t dreg = m_core->local_regs[(DST_CODE + fp) & 0x3f]; const uint32_t dreg = m_core->local_regs[(DST_CODE + fp) & 0x3f];
if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
if (SrcGlobal) if (SrcGlobal)
{ {
set_global_register(src_code, READ_W(dreg)); set_global_register(src_code, READ_W(dreg));
@ -2354,20 +2425,28 @@ void hyperstone_device::hyperstone_ldwp()
const uint32_t fp = GET_FP; const uint32_t fp = GET_FP;
const uint32_t dst_code = (DST_CODE + fp) & 0x3f; const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
const uint32_t dreg = m_core->local_regs[dst_code];
if (!dreg)
{
m_core->local_regs[dst_code] = dreg + 4;
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
if (SrcGlobal) if (SrcGlobal)
{ {
set_global_register(SRC_CODE, READ_W(m_core->local_regs[dst_code])); set_global_register(SRC_CODE, READ_W(dreg));
m_core->local_regs[dst_code] += 4; m_core->local_regs[dst_code] = dreg + 4;
} }
else else
{ {
const uint32_t src_code = (SRC_CODE + fp) & 0x3f; const uint32_t src_code = (SRC_CODE + fp) & 0x3f;
m_core->local_regs[src_code] = READ_W(m_core->local_regs[dst_code]); m_core->local_regs[src_code] = READ_W(dreg);
// post increment the destination register if it's different from the source one // post increment the destination register if it's different from the source one
// (needed by Hidden Catch) // (needed by Hidden Catch)
if (src_code != dst_code) if (src_code != dst_code)
m_core->local_regs[dst_code] += 4; m_core->local_regs[dst_code] = dreg + 4;
} }
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
@ -2383,11 +2462,18 @@ void hyperstone_device::hyperstone_lddp()
const uint32_t dst_code = (DST_CODE + fp) & 0x3f; const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
const uint32_t dreg = m_core->local_regs[dst_code]; const uint32_t dreg = m_core->local_regs[dst_code];
if (!dreg)
{
m_core->local_regs[dst_code] = dreg + 8;
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
if (SrcGlobal) if (SrcGlobal)
{ {
set_global_register(src_code, READ_W(dreg)); set_global_register(src_code, READ_W(dreg));
set_global_register(src_code + 1, READ_W(dreg + 4)); set_global_register(src_code + 1, READ_W(dreg + 4));
m_core->local_regs[dst_code] += 8; m_core->local_regs[dst_code] = dreg + 8;
} }
else else
{ {
@ -2398,7 +2484,7 @@ void hyperstone_device::hyperstone_lddp()
// post increment the destination register if it's different from the source one // post increment the destination register if it's different from the source one
// and from the "next source" one // and from the "next source" one
if (src_code != dst_code && srcf_code != dst_code) if (src_code != dst_code && srcf_code != dst_code)
m_core->local_regs[dst_code] += 8; m_core->local_regs[dst_code] = dreg + 8;
} }
m_core->icount -= m_core->clock_cycles_2; m_core->icount -= m_core->clock_cycles_2;
@ -2412,7 +2498,15 @@ void hyperstone_device::hyperstone_stwr()
const uint32_t fp = GET_FP; const uint32_t fp = GET_FP;
const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]; const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code];
WRITE_W(m_core->local_regs[(DST_CODE + fp) & 0x3f], sreg); const uint32_t dreg = m_core->local_regs[(DST_CODE + fp) & 0x3f];
if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
WRITE_W(dreg, sreg);
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
} }
@ -2427,9 +2521,14 @@ void hyperstone_device::hyperstone_stdr()
const uint32_t srcf_code = SrcGlobal ? (SRC_CODE + 1) : ((src_code + 1) & 0x3f); const uint32_t srcf_code = SrcGlobal ? (SRC_CODE + 1) : ((src_code + 1) & 0x3f);
const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]; const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code];
const uint32_t sregf = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[srcf_code]; const uint32_t sregf = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[srcf_code];
const uint32_t dreg = m_core->local_regs[(DST_CODE + GET_FP) & 0x3f]; const uint32_t dreg = m_core->local_regs[(DST_CODE + GET_FP) & 0x3f];
if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
WRITE_W(dreg, sreg); WRITE_W(dreg, sreg);
WRITE_W(dreg + 4, sregf); WRITE_W(dreg + 4, sregf);
@ -2444,12 +2543,18 @@ void hyperstone_device::hyperstone_stwp()
const uint32_t fp = GET_FP; const uint32_t fp = GET_FP;
const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]; const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code];
const uint32_t dst_code = (DST_CODE + fp) & 0x3f; const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
const uint32_t dreg = m_core->local_regs[dst_code]; const uint32_t dreg = m_core->local_regs[dst_code];
m_core->local_regs[dst_code] = dreg + 4;
if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
WRITE_W(dreg, sreg); WRITE_W(dreg, sreg);
m_core->local_regs[dst_code] += 4;
m_core->icount -= m_core->clock_cycles_1; m_core->icount -= m_core->clock_cycles_1;
} }
@ -2463,13 +2568,18 @@ void hyperstone_device::hyperstone_stdp()
const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f);
const uint32_t srcf_code = SrcGlobal ? (src_code + 1) : ((src_code + 1) & 0x3f); const uint32_t srcf_code = SrcGlobal ? (src_code + 1) : ((src_code + 1) & 0x3f);
const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code]; const uint32_t sreg = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[src_code];
const uint32_t dst_code = (DST_CODE + fp) & 0x3f; const uint32_t dst_code = (DST_CODE + fp) & 0x3f;
const uint32_t dreg = m_core->local_regs[dst_code]; const uint32_t dreg = m_core->local_regs[dst_code];
WRITE_W(dreg, sreg); m_core->local_regs[dst_code] = dreg + 8;
m_core->local_regs[dst_code] += 8; if (!dreg)
{
execute_exception(TRAPNO_POINTER_ERROR);
return;
}
WRITE_W(dreg, sreg);
const uint32_t sregf = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[srcf_code]; const uint32_t sregf = (SrcGlobal && src_code == SR_REGISTER) ? 0 : (SrcGlobal ? m_core->global_regs : m_core->local_regs)[srcf_code];

View File

@ -73,10 +73,10 @@ uint32_t v60_device::opCVTSW()
val = u2f(m_op1); val = u2f(m_op1);
switch (TKCW & 7) switch (TKCW & 7)
{ {
case 0: m_modwritevalw = (uint32_t)(int64_t)round(val); break; case 0: m_modwritevalw = (uint32_t)llroundf(val); break;
case 1: m_modwritevalw = (uint32_t)(int64_t)floor(val); break; case 1: m_modwritevalw = (uint32_t)(int64_t)floorf(val); break;
case 2: m_modwritevalw = (uint32_t)(int64_t)ceil(val); break; case 2: m_modwritevalw = (uint32_t)(int64_t)ceilf(val); break;
default: m_modwritevalw = (uint32_t)(int64_t)trunc(val); break; default: m_modwritevalw = (uint32_t)(int64_t)truncf(val); break;
} }
_S = ((m_modwritevalw & 0x80000000) != 0); _S = ((m_modwritevalw & 0x80000000) != 0);

View File

@ -48,17 +48,19 @@ Official test program from pages 4 to 8 of the operator's manual:
#include "emu.h" #include "emu.h"
#include "cpu/i8085/i8085.h" #include "bus/heathzenith/intr_cntrl/intr_cntrl.h"
#include "machine/i8251.h"
#include "machine/clock.h"
#include "machine/timer.h"
#include "bus/rs232/rs232.h" #include "bus/rs232/rs232.h"
#include "cpu/i8085/i8085.h"
#include "imagedev/cassette.h" #include "imagedev/cassette.h"
#include "machine/clock.h"
#include "machine/i8251.h"
#include "machine/timer.h"
#include "sound/beep.h" #include "sound/beep.h"
#include "speaker.h" #include "speaker.h"
#include "bus/heathzenith/intr_cntrl/intr_cntrl.h"
#include "formats/h8_cas.h" #include "formats/h8_cas.h"
#include "h8.lh" #include "h8.lh"
namespace { namespace {

View File

@ -25,28 +25,28 @@ tzbx15_device::tzbx15_device(const machine_config &mconfig, device_type type, co
{ {
} }
tzbx15_device::tzbx15_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, u32 clock, u32 clut_size) tzbx15_device::tzbx15_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 clut_size)
: tzbx15_device(mconfig, type, tag, owner, clock) : tzbx15_device(mconfig, type, tag, owner, clock)
{ {
m_rom_clut_size = clut_size; m_rom_clut_size = clut_size;
} }
tzb215_device::tzb215_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock, u32 clut_size) tzb215_device::tzb215_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 clut_size)
: tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, clut_size) : tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, clut_size)
{ {
} }
tzb215_device::tzb215_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock) tzb215_device::tzb215_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, 0) : tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, 0)
{ {
} }
tzb315_device::tzb315_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock, u32 clut_size) tzb315_device::tzb315_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 clut_size)
: tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, clut_size) : tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, clut_size)
{ {
} }
tzb315_device::tzb315_device(const machine_config& mconfig, const char* tag, device_t* owner, u32 clock) tzb315_device::tzb315_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, 0) : tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, 0)
{ {
} }
@ -54,14 +54,6 @@ tzb315_device::tzb315_device(const machine_config& mconfig, const char* tag, dev
void tzbx15_device::common_init()
{
m_rom_clut_offset = memregion("sprites_l")->bytes() - m_rom_clut_size;
m_shadow_pen_array = make_unique_clear<uint8_t[]>(m_rom_clut_size * 2);
m_temp_bitmap.allocate(512, 512);
}
static const gfx_layout spritelayout = static const gfx_layout spritelayout =
{ {
8,8, 8,8,
@ -80,7 +72,11 @@ GFXDECODE_END
void tzbx15_device::device_start() void tzbx15_device::device_start()
{ {
common_init(); m_rom_clut_offset = memregion("sprites_l")->bytes() - m_rom_clut_size;
m_shadow_pen_array = make_unique_clear<uint8_t[]>(m_rom_clut_size * 2);
m_temp_bitmap.allocate(512, 512);
decode_gfx(gfxinfo); decode_gfx(gfxinfo);
gfx(0)->set_colors(m_rom_clut_size / 8); gfx(0)->set_colors(m_rom_clut_size / 8);
gfx(1)->set_colors(m_rom_clut_size / 8); gfx(1)->set_colors(m_rom_clut_size / 8);
@ -130,7 +126,7 @@ void tzbx15_device::mycopyrozbitmap_core(bitmap_rgb32 &bitmap, const bitmap_rgb3
int x = sx; int x = sx;
uint32_t cx = startx; uint32_t cx = startx;
uint32_t cy = starty; uint32_t cy = starty;
uint32_t* dest = &bitmap.pix(sy, sx); uint32_t *dest = &bitmap.pix(sy, sx);
while (x <= ex) while (x <= ex)
{ {
@ -155,9 +151,12 @@ void tzbx15_device::mycopyrozbitmap_core(bitmap_rgb32 &bitmap, const bitmap_rgb3
} }
template<class BitmapClass> template<class BitmapClass>
void tzbx15_device::roundupt_drawgfxzoomrotate( BitmapClass &dest_bmp, const rectangle &clip, void tzbx15_device::roundupt_drawgfxzoomrotate(
gfx_element *gfx, uint32_t code,uint32_t color,int flipx,int flipy,uint32_t ssx,uint32_t ssy, BitmapClass &dest_bmp, const rectangle &clip,
int scalex, int scaley, int rotate, int write_priority_only ) gfx_element *gfx, uint32_t code, uint32_t color,
int flipx, int flipy, uint32_t ssx, uint32_t ssy,
int scalex, int scaley, int rotate,
int write_priority_only)
{ {
if (!scalex || !scaley) return; if (!scalex || !scaley) return;
@ -172,7 +171,7 @@ void tzbx15_device::roundupt_drawgfxzoomrotate( BitmapClass &dest_bmp, const rec
rectangle myclip = clip; rectangle myclip = clip;
myclip &= dest_bmp.cliprect(); myclip &= dest_bmp.cliprect();
if( gfx ) if (gfx)
{ {
const pen_t *pal = &m_palette_clut->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); const pen_t *pal = &m_palette_clut->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors()));
const uint8_t *shadow_pens = m_shadow_pen_array.get() + (gfx->granularity() * (color % gfx->colors())); const uint8_t *shadow_pens = m_shadow_pen_array.get() + (gfx->granularity() * (color % gfx->colors()));
@ -417,23 +416,27 @@ void tzbx15_device::draw_sprites_main(BitmapClass &bitmap, const rectangle &clip
src1 += 4; src1 += 4;
int h = 0; int h = 0;
while (lines > 0) { while (lines > 0)
{
int base, x_offs, x_width, x_pos, draw_this_line = 1; int base, x_offs, x_width, x_pos, draw_this_line = 1;
int this_extent = 0; int this_extent = 0;
/* Odd and even lines come from different banks */ /* Odd and even lines come from different banks */
if (h & 1) { if (h & 1)
{
x_width = src1[0] + 1; x_width = src1[0] + 1;
x_offs = src1[1] * scale * 8; x_offs = src1[1] * scale * 8;
base = src1[2] | (src1[3] << 8); base = src1[2] | (src1[3] << 8);
} }
else { else
{
x_width = src2[0] + 1; x_width = src2[0] + 1;
x_offs = src2[1] * scale * 8; x_offs = src2[1] * scale * 8;
base = src2[2] | (src2[3] << 8); base = src2[2] | (src2[3] << 8);
} }
if (draw_this_line) { if (draw_this_line)
{
base *= 2; base *= 2;
if (!rotate) if (!rotate)
@ -446,7 +449,8 @@ void tzbx15_device::draw_sprites_main(BitmapClass &bitmap, const rectangle &clip
else else
x_pos = x_offs; x_pos = x_offs;
for (int w = 0; w < x_width; w++) { for (int w = 0; w < x_width; w++)
{
if (rotate) if (rotate)
roundupt_drawgfxzoomrotate( roundupt_drawgfxzoomrotate(
m_temp_bitmap,cliprect,gfx(0 + (base & 1)), m_temp_bitmap,cliprect,gfx(0 + (base & 1)),

View File

@ -15,8 +15,8 @@ public:
template <typename T> void set_basepalette(T &&tag) { m_palette_base.set_tag(std::forward<T>(tag)); } template <typename T> void set_basepalette(T &&tag) { m_palette_base.set_tag(std::forward<T>(tag)); }
template <typename T> void set_spriteram(T &&tag) { m_spriteram.set_tag(std::forward<T>(tag)); } template <typename T> void set_spriteram(T &&tag) { m_spriteram.set_tag(std::forward<T>(tag)); }
void draw_sprites(bitmap_rgb32& bitmap, const rectangle& cliprect, int write_priority_only, int rambank); void draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int write_priority_only, int rambank);
void draw_sprites(bitmap_ind8& bitmap, const rectangle& cliprect, int write_priority_only, int rambank); void draw_sprites(bitmap_ind8 &bitmap, const rectangle &cliprect, int write_priority_only, int rambank);
void update_cluts(); void update_cluts();
@ -31,8 +31,6 @@ private:
virtual void device_start() override ATTR_COLD; virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD; virtual void device_reset() override ATTR_COLD;
void common_init() ATTR_COLD;
void mycopyrozbitmap_core(bitmap_ind8 &bitmap, const bitmap_rgb32 &srcbitmap, void mycopyrozbitmap_core(bitmap_ind8 &bitmap, const bitmap_rgb32 &srcbitmap,
int dstx, int dsty, int srcwidth, int srcheight, int incxx, int incxy, int incyx, int incyy, int dstx, int dsty, int srcwidth, int srcheight, int incxx, int incxy, int incyx, int incyy,
const rectangle &clip, int transparent_color); const rectangle &clip, int transparent_color);
@ -41,9 +39,12 @@ private:
const rectangle &clip, int transparent_color); const rectangle &clip, int transparent_color);
template<class BitmapClass> void draw_sprites_main(BitmapClass &bitmap, const rectangle &cliprect, int write_priority_only, int rambank); template<class BitmapClass> void draw_sprites_main(BitmapClass &bitmap, const rectangle &cliprect, int write_priority_only, int rambank);
template<class BitmapClass> inline void roundupt_drawgfxzoomrotate( BitmapClass &dest_bmp, const rectangle &clip, template<class BitmapClass> void roundupt_drawgfxzoomrotate(
gfx_element *gfx, uint32_t code,uint32_t color,int flipx,int flipy,uint32_t ssx,uint32_t ssy, BitmapClass &dest_bmp, const rectangle &clip,
int scalex, int scaley, int rotate, int write_priority_only ); gfx_element *gfx, uint32_t code, uint32_t color,
int flipx, int flipy, uint32_t ssx, uint32_t ssy,
int scalex, int scaley, int rotate,
int write_priority_only);
DECLARE_GFXDECODE_MEMBER(gfxinfo); DECLARE_GFXDECODE_MEMBER(gfxinfo);