Skip to content

Commit 3533b7f

Browse files
committed
cpu/e132xs: More recompiler optimisation:
* Disabled single-instruction-per-block mode. * Don't bother with delay slot checks where it's unnecessary. * Try to generate a speicalised copy of the delay slot instruction followed by a direct branch of possible. * Use the pre-decoded instruction length for updating the PC. * Specialised versions of the CHK instruction that always or never raise exceptions.
1 parent d48596b commit 3533b7f

File tree

4 files changed

+137
-299
lines changed

4 files changed

+137
-299
lines changed

src/devices/cpu/e132xs/e132xs.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
- GMS30C2232
3232
3333
TODO:
34+
- Fix behaviour of branches in delay slots
3435
- Many wrong cycle counts
3536
- No emulation of memory access latency and pipleline
3637
- Should a zero bit shift clear C or leave it unchanged?

src/devices/cpu/e132xs/e132xs.h

+1-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
#define E132XS_STRICT_VERIFY 0x0001 /* verify all instructions */
4040

41-
#define SINGLE_INSTRUCTION_MODE (1)
41+
#define SINGLE_INSTRUCTION_MODE (0)
4242

4343
#define ENABLE_E132XS_DRC (1)
4444

@@ -486,12 +486,9 @@ class hyperstone_device : public cpu_device, public hyperstone_disassembler::con
486486
bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
487487

488488
void generate_get_trap_addr(drcuml_block &block, uml::code_label &label, uml::parameter trapno);
489-
void generate_check_delay_pc(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
490489
uint32_t generate_get_const(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
491490
uint32_t generate_get_immediate_s(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
492-
void generate_ignore_immediate_s(drcuml_block &block, const opcode_desc *desc);
493491
uint32_t generate_get_pcrel(drcuml_block &block, const opcode_desc *desc);
494-
void generate_ignore_pcrel(drcuml_block &block, const opcode_desc *desc);
495492

496493
void generate_get_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
497494
void generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code);
@@ -507,8 +504,6 @@ class hyperstone_device : public cpu_device, public hyperstone_disassembler::con
507504
void generate_update_flags_cmp(drcuml_block &block, compiler_state &compiler, uml::parameter sr);
508505

509506
template <trap_exception_or_int TYPE> void generate_trap_exception_or_int(drcuml_block &block, uml::code_label &label, uml::parameter trapno);
510-
void generate_int(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t addr);
511-
void generate_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t addr);
512507
void generate_software(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
513508

514509
void generate_trap_on_overflow(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uml::parameter sr);

src/devices/cpu/e132xs/e132xsdrc.cpp

+40-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct hyperstone_device::compiler_state
1515

1616
const uint8_t m_mode;
1717
uml::code_label m_labelnum = 1;
18+
uint8_t m_check_delay = 1;
1819
};
1920

2021

@@ -260,6 +261,7 @@ void hyperstone_device::code_compile_block(uint8_t mode, offs_t pc)
260261
UML_MOV(block, I7, 0);
261262

262263
/* iterate over instructions in the sequence and compile them */
264+
compiler.m_check_delay = 1;
263265
for (const opcode_desc *curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
264266
{
265267
generate_sequence_instruction(block, compiler, curdesc);
@@ -759,10 +761,46 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi
759761

760762
if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
761763
{
764+
if (compiler.m_check_delay == 1)
765+
{
766+
// if PC is used in a delay instruction, the delayed PC should be used
767+
const int nodelay = compiler.m_labelnum++;
768+
const int done = compiler.m_labelnum++;
769+
UML_TEST(block, mem(&m_core->delay_slot), 1);
770+
UML_JMPc(block, uml::COND_Z, nodelay);
771+
UML_MOV(block, DRC_PC, mem(&m_core->delay_pc));
772+
UML_MOV(block, mem(&m_core->delay_slot), 0);
773+
UML_MOV(block, mem(&m_core->delay_slot_taken), 1);
774+
UML_JMP(block, done);
775+
UML_LABEL(block, nodelay);
776+
UML_ADD(block, DRC_PC, DRC_PC, desc->length);
777+
UML_MOV(block, mem(&m_core->delay_slot_taken), 0);
778+
UML_LABEL(block, done);
779+
}
780+
else
781+
{
782+
UML_ADD(block, DRC_PC, DRC_PC, desc->length);
783+
UML_MOV(block, mem(&m_core->delay_slot_taken), 0);
784+
}
785+
762786
// compile the instruction
763-
if (!generate_opcode(block, compiler, desc))
787+
if (generate_opcode(block, compiler, desc))
788+
{
789+
if (compiler.m_check_delay)
790+
{
791+
if (compiler.m_check_delay == 1)
792+
{
793+
UML_TEST(block, mem(&m_core->delay_slot_taken), ~uint32_t(0));
794+
UML_CALLHc(block, uml::COND_NZ, *m_delay_taken[compiler.m_mode]);
795+
}
796+
--compiler.m_check_delay;
797+
}
798+
799+
if (BIT(compiler.m_mode, 1) && !desc->delayslots)
800+
UML_EXHc(block, uml::COND_Z, *m_exception, EXCEPTION_TRACE);
801+
}
802+
else
764803
{
765-
UML_MOV(block, DRC_PC, desc->pc);
766804
UML_MOV(block, mem(&m_core->arg0), desc->opptr.w[0]);
767805
UML_CALLC(block, &c_funcs::unimplemented, this);
768806
}
@@ -775,8 +813,6 @@ bool hyperstone_device::generate_opcode(drcuml_block &block, compiler_state &com
775813
{
776814
uint32_t op = (uint32_t)desc->opptr.w[0];
777815

778-
UML_ADD(block, DRC_PC, DRC_PC, 2);
779-
780816
switch (op >> 8)
781817
{
782818
case 0x00: generate_chk<GLOBAL, GLOBAL>(block, compiler, desc); break;
@@ -1039,14 +1075,5 @@ bool hyperstone_device::generate_opcode(drcuml_block &block, compiler_state &com
10391075

10401076
UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK);
10411077

1042-
UML_TEST(block, mem(&m_core->delay_slot_taken), ~uint32_t(0));
1043-
UML_CALLHc(block, uml::COND_NZ, *m_delay_taken[compiler.m_mode]);
1044-
1045-
if (BIT(compiler.m_mode, 1))
1046-
{
1047-
UML_TEST(block, mem(&m_core->delay_slot), 1);
1048-
UML_EXHc(block, uml::COND_Z, *m_exception, EXCEPTION_TRACE);
1049-
}
1050-
10511078
return true;
10521079
}

0 commit comments

Comments
 (0)