-cpu/e132xs: General cleanup and usability improvements:

* Aligned the operand field in disassembly.
* Calculate results of immediate values against the PC to make
  position-independent code easier to read  without constantly using a
  calculator (e.g. this shows destinations for call Rd, PC, imm).
* Added more symbols to the UML helper to make logged generated code
  more readable.
* Made single-instruction-per-sequence mode configurable rather than a
  compile-time option.
* Got rid of a criminal amount of copy/paste in the disassembler, and
  got rid of all the deprecated strcpy calls.
* Got rid of some duplicated constants, changed some constants from
  macros to enumerated values or constexpr globals.
* Reduced the amound of stuff in headers that doesn't need to be there.

-cpu/drcbex64.cpp: Don't construct std::function objects during code
 generation - they require allocation.

-eolith/eolith.cpp: Turned single-instruction-per-sequence mode on for
 now until someone works out why turning it off causes Raccoon World to
 generate so much code it's unplayably slow.
This commit is contained in:
Vas Crabb 2025-03-29 04:53:34 +11:00
parent 345ab51e9d
commit 40a0638ba7
10 changed files with 525 additions and 1395 deletions

View File

@ -594,7 +594,9 @@ private:
// alu and shift operation helpers
static bool ones(u64 const value, unsigned const size) noexcept { return (size == 4) ? u32(value) == 0xffffffffU : value == 0xffffffff'ffffffffULL; }
void alu_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const &param, std::function<bool(asmjit::x86::Assembler &a, asmjit::Operand const &dst, be_parameter const &src)> optimize = [](asmjit::x86::Assembler &a, asmjit::Operand dst, be_parameter const &src) { return false; });
template <typename T>
void alu_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const &param, T &&optimize);
void alu_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const &param) { alu_op_param(a, opcode, dst, param, [] (asmjit::x86::Assembler &a, asmjit::Operand dst, be_parameter const &src) { return false; }); }
void shift_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, size_t opsize, asmjit::Operand const &dst, be_parameter const &param, u8 update_flags);
// parameter helpers
@ -1401,7 +1403,8 @@ void drcbe_x64::get_info(drcbe_info &info) const noexcept
break;
}
void drcbe_x64::alu_op_param(Assembler &a, Inst::Id const opcode, Operand const &dst, be_parameter const &param, std::function<bool(Assembler &a, Operand const &dst, be_parameter const &src)> optimize)
template <typename T>
void drcbe_x64::alu_op_param(Assembler &a, Inst::Id const opcode, Operand const &dst, be_parameter const &param, T &&optimize)
{
bool const is64 = dst.x86RmSize() == 8;
@ -3945,7 +3948,7 @@ void drcbe_x64::op_roland(Assembler &a, const instruction &inst)
a.rol(dstreg, cl);
}
alu_op_param(a, Inst::kIdAnd, dstreg, maskp,
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// all-one cases
if (ones(src.immediate(), inst.size()))
@ -4277,7 +4280,7 @@ void drcbe_x64::op_add(Assembler &a, const instruction &inst)
{
// dstp == src1p in memory
alu_op_param(a, Inst::kIdAdd, MABS(dstp.memory(), inst.size()), src2p, // add [dstp],src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize zero case
return (!inst.flags() && !src.immediate());
@ -4309,7 +4312,7 @@ void drcbe_x64::op_add(Assembler &a, const instruction &inst)
mov_reg_param(a, dstreg, src1p); // mov dstreg,src1p
alu_op_param(a, Inst::kIdAdd, dstreg, src2p, // add dstreg,src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize zero case
return (!inst.flags() && !src.immediate() && (inst.size() != 4));
@ -4375,7 +4378,7 @@ void drcbe_x64::op_sub(Assembler &a, const instruction &inst)
{
// dstp == src1p in memory
alu_op_param(a, Inst::kIdSub, MABS(dstp.memory(), inst.size()), src2p, // sub [dstp],src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize zero case
return (!inst.flags() && !src.immediate());
@ -4398,7 +4401,7 @@ void drcbe_x64::op_sub(Assembler &a, const instruction &inst)
mov_reg_param(a, dstreg, src1p); // mov dstreg,src1p
alu_op_param(a, Inst::kIdSub, dstreg, src2p, // sub dstreg,src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize zero case
return (!inst.flags() && !src.immediate() && (inst.size() != 4));
@ -5006,7 +5009,7 @@ void drcbe_x64::op_test(Assembler &a, const instruction &inst)
mov_reg_param(a, src1reg, src1p);
alu_op_param(a, Inst::kIdTest, src1reg, src2p,
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-one cases
if (ones(src.immediate(), inst.size()))
@ -5042,7 +5045,7 @@ void drcbe_x64::op_or(Assembler &a, const instruction &inst)
{
// dstp == src1p in memory
alu_op_param(a, Inst::kIdOr, MABS(dstp.memory(), inst.size()), src2p, // or [dstp],src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-zero and all-one cases
if (!inst.flags() && ones(src.immediate(), inst.size()))
@ -5066,7 +5069,7 @@ void drcbe_x64::op_or(Assembler &a, const instruction &inst)
mov_reg_param(a, dstreg, src1p); // mov dstreg,src1p
alu_op_param(a, Inst::kIdOr, dstreg, src2p, // or dstreg,src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-zero and all-one cases
if (!inst.flags() && ones(src.immediate(), inst.size()))
@ -5120,7 +5123,7 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst)
{
// dstp == src1p in memory
alu_op_param(a, Inst::kIdXor, MABS(dstp.memory(), inst.size()), src2p, // xor [dstp],src2p
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-zero and all-one cases
if (!inst.flags() && ones(src.immediate(), inst.size()))
@ -5140,7 +5143,7 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst)
Gp const dst = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, dstp.ireg());
alu_op_param(a, Inst::kIdXor, dst, src2p,
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-zero and all-one cases
if (!inst.flags() && ones(src.immediate(), inst.size()))
@ -5173,7 +5176,7 @@ void drcbe_x64::op_xor(Assembler &a, const instruction &inst)
mov_reg_param(a, dstreg, src1p);
alu_op_param(a, Inst::kIdXor, dstreg, src2p,
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
[inst] (Assembler &a, Operand const &dst, be_parameter const &src)
{
// optimize all-zero and all-one cases
if (!inst.flags() && ones(src.immediate(), inst.size()))

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,14 @@
#pragma once
#include <string_view>
class hyperstone_disassembler : public util::disasm_interface
{
public:
struct config {
struct config
{
virtual ~config() = default;
virtual bool get_h() const = 0;
@ -32,16 +36,11 @@ private:
int size;
void LL_format(char *source, char *dest, uint16_t op);
void LR_format(char *source, char *dest, uint16_t op);
void RR_format(char *source, char *dest, uint16_t op, unsigned h_flag);
uint32_t LRconst_format(char *source, char *dest, uint16_t op, offs_t &pc, const data_buffer &opcodes);
uint32_t RRconst_format(char *source, char *dest, uint16_t op, offs_t &pc, const data_buffer &opcodes);
int32_t Rimm_format(char *dest, uint16_t op, offs_t &pc, const data_buffer &opcodes, unsigned h_flag);
uint8_t Ln_format(char *dest, uint16_t op);
uint8_t Rn_format(char *dest, uint16_t op);
uint32_t LRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes);
uint32_t RRconst_format(std::string_view &source, std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes);
int32_t Rimm_format(std::string_view &dest, uint16_t op, offs_t pc, const data_buffer &opcodes, unsigned h_flag);
int32_t PCrel_format(uint16_t op, offs_t pc, const data_buffer &opcodes);
uint32_t RRdis_format(char *source, char *dest, uint16_t op, uint16_t next_op, offs_t pc, const data_buffer &opcodes);
uint32_t RRdis_format(std::string_view &source, std::string_view &dest, uint16_t op, uint16_t next_op, offs_t pc, const data_buffer &opcodes);
};
#endif

View File

@ -9,18 +9,30 @@
COMPILE-TIME DEFINITIONS
***************************************************************************/
#define PC_REGISTER 0
#define SR_REGISTER 1
#define SP_REGISTER 18
#define UB_REGISTER 19
#define BCR_REGISTER 20
#define TPR_REGISTER 21
#define TCR_REGISTER 22
#define TR_REGISTER 23
#define WCR_REGISTER 24
#define ISR_REGISTER 25
#define FCR_REGISTER 26
#define MCR_REGISTER 27
// compilation boundaries -- how far back/forward does the analysis extend?
enum : u32
{
COMPILE_BACKWARDS_BYTES = 128,
COMPILE_FORWARDS_BYTES = 512,
COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 2) + (COMPILE_FORWARDS_BYTES / 2),
COMPILE_MAX_SEQUENCE = 64
};
enum
{
PC_REGISTER = 0,
SR_REGISTER = 1,
SP_REGISTER = 18,
UB_REGISTER = 19,
BCR_REGISTER = 20,
TPR_REGISTER = 21,
TCR_REGISTER = 22,
TR_REGISTER = 23,
WCR_REGISTER = 24,
ISR_REGISTER = 25,
FCR_REGISTER = 26,
MCR_REGISTER = 27
};
#define X_CODE(val) ((val & 0x7000) >> 12)
#define E_BIT(val) ((val & 0x8000) >> 15)
@ -59,34 +71,40 @@
#define EMSUBD 0x11e
#define EHCFFTSD 0x296
/* IRQ numbers */
#define IRQ_INT1 0
#define IRQ_INT2 1
#define IRQ_INT3 2
#define IRQ_INT4 3
#define IRQ_IO1 4
#define IRQ_IO2 5
#define IRQ_IO3 6
// IRQ numbers
enum
{
IRQ_INT1 = 0,
IRQ_INT2 = 1,
IRQ_INT3 = 2,
IRQ_INT4 = 3,
IRQ_IO1 = 4,
IRQ_IO2 = 5,
IRQ_IO3 = 6
};
/* Trap numbers */
#define TRAPNO_IO2 48
#define TRAPNO_IO1 49
#define TRAPNO_INT4 50
#define TRAPNO_INT3 51
#define TRAPNO_INT2 52
#define TRAPNO_INT1 53
#define TRAPNO_IO3 54
#define TRAPNO_TIMER 55
#define TRAPNO_RESERVED1 56
#define TRAPNO_TRACE_EXCEPTION 57
#define TRAPNO_PARITY_ERROR 58
#define TRAPNO_EXTENDED_OVERFLOW 59
#define TRAPNO_RANGE_ERROR 60
#define TRAPNO_PRIVILEGE_ERROR TRAPNO_RANGE_ERROR
#define TRAPNO_FRAME_ERROR TRAPNO_RANGE_ERROR
#define TRAPNO_RESERVED2 61
#define TRAPNO_RESET 62 // reserved if not mapped @ MEM3
#define TRAPNO_ERROR_ENTRY 63 // for instruction code of all ones
// Trap numbers
enum
{
TRAPNO_IO2 = 48,
TRAPNO_IO1 = 49,
TRAPNO_INT4 = 50,
TRAPNO_INT3 = 51,
TRAPNO_INT2 = 52,
TRAPNO_INT1 = 53,
TRAPNO_IO3 = 54,
TRAPNO_TIMER = 55,
TRAPNO_RESERVED1 = 56,
TRAPNO_TRACE_EXCEPTION = 57,
TRAPNO_PARITY_ERROR = 58,
TRAPNO_EXTENDED_OVERFLOW = 59,
TRAPNO_RANGE_ERROR = 60,
TRAPNO_PRIVILEGE_ERROR = TRAPNO_RANGE_ERROR,
TRAPNO_FRAME_ERROR = TRAPNO_RANGE_ERROR,
TRAPNO_RESERVED2 = 61,
TRAPNO_RESET = 62, // reserved if not mapped @ MEM3
TRAPNO_ERROR_ENTRY = 63 // for instruction code of all ones
};
/* Trap codes */
#define TRAPLE 4

View File

@ -120,6 +120,7 @@ hyperstone_device::hyperstone_device(
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
, m_single_instruction_mode(false)
, m_cache_dirty(0)
, m_entry(nullptr)
, m_nocode(nullptr)
@ -999,9 +1000,18 @@ void hyperstone_device::device_start()
m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 4, 32, 1);
// add UML symbols-
m_drcuml->symbol_add(&m_core->global_regs[0], sizeof(uint32_t), "pc");
m_drcuml->symbol_add(&m_core->global_regs[1], sizeof(uint32_t), "sr");
m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
m_drcuml->symbol_add(&m_core->global_regs[PC_REGISTER], sizeof(m_core->global_regs[PC_REGISTER]), "pc");
m_drcuml->symbol_add(&m_core->global_regs[SR_REGISTER], sizeof(m_core->global_regs[SR_REGISTER]), "sr");
m_drcuml->symbol_add(&m_core->global_regs[SP_REGISTER], sizeof(m_core->global_regs[SP_REGISTER]), "sp");
m_drcuml->symbol_add(&m_core->global_regs[UB_REGISTER], sizeof(m_core->global_regs[UB_REGISTER]), "ub");
m_drcuml->symbol_add(&m_core->trap_entry, sizeof(m_core->trap_entry), "trap_entry");
m_drcuml->symbol_add(&m_core->delay_pc, sizeof(m_core->delay_pc), "delay_pc");
m_drcuml->symbol_add(&m_core->delay_slot, sizeof(m_core->delay_slot), "delay_slot");
m_drcuml->symbol_add(&m_core->delay_slot_taken, sizeof(m_core->delay_slot_taken), "delay_slot_taken");
m_drcuml->symbol_add(&m_core->intblock, sizeof(m_core->intblock), "intblock");
m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
char buf[4];
buf[3] = '\0';
@ -1040,7 +1050,7 @@ void hyperstone_device::device_start()
m_drcuml->symbol_add(&m_core->arg1, sizeof(uint32_t), "arg1");
/* initialize the front-end helper */
m_drcfe = std::make_unique<e132xs_frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
m_drcfe = std::make_unique<e132xs_frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, m_single_instruction_mode ? 1 : COMPILE_MAX_SEQUENCE);
/* mark the cache dirty so it is updated on next execute */
m_cache_dirty = true;

View File

@ -32,10 +32,6 @@
CONSTANTS
***************************************************************************/
/* map variables */
#define MAPVAR_PC M0
#define MAPVAR_CYCLES M1
#define E132XS_STRICT_VERIFY 0x0001 /* verify all instructions */
#define SINGLE_INSTRUCTION_MODE (0)
@ -116,18 +112,12 @@ class hyperstone_device : public cpu_device, public hyperstone_disassembler::con
friend class e132xs_frontend;
public:
// configuration
void set_single_instruction_mode(bool val) { m_single_instruction_mode = val; }
virtual ~hyperstone_device() override;
protected:
// compilation boundaries -- how far back/forward does the analysis extend?
enum : u32
{
COMPILE_BACKWARDS_BYTES = 128,
COMPILE_FORWARDS_BYTES = 512,
COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 4) + (COMPILE_FORWARDS_BYTES / 4),
COMPILE_MAX_SEQUENCE = 64
};
// exit codes
enum : int
{
@ -230,31 +220,16 @@ protected:
IS_TIMER = 1
};
enum
{
EXCEPTION_IO2 = 48,
EXCEPTION_IO1 = 49,
EXCEPTION_INT4 = 50,
EXCEPTION_INT3 = 51,
EXCEPTION_INT2 = 52,
EXCEPTION_INT1 = 53,
EXCEPTION_IO3 = 54,
EXCEPTION_TIMER = 55,
EXCEPTION_RESERVED1 = 56,
EXCEPTION_TRACE = 57,
EXCEPTION_PARITY_ERROR = 58,
EXCEPTION_EXTENDED_OVERFLOW = 59,
EXCEPTION_RANGE_ERROR = 60,
EXCEPTION_PRIVILEGE_ERROR = EXCEPTION_RANGE_ERROR,
EXCEPTION_FRAME_ERROR = EXCEPTION_RANGE_ERROR,
EXCEPTION_RESERVED2 = 61,
EXCEPTION_RESET = 62, // reserved if not mapped @ MEM3
EXCEPTION_ERROR_ENTRY = 63, // for instruction code of all ones
};
// construction/destruction
hyperstone_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock,
const device_type type, uint32_t prg_data_width, uint32_t io_data_width, address_map_constructor internal_map);
hyperstone_device(
const machine_config &mconfig,
const char *tag,
device_t *owner,
uint32_t clock,
const device_type type,
uint32_t prg_data_width,
uint32_t io_data_width,
address_map_constructor internal_map);
// device_t implementation
virtual void device_start() override ATTR_COLD;
@ -441,6 +416,7 @@ private:
std::unique_ptr<drcuml_state> m_drcuml;
std::unique_ptr<e132xs_frontend> m_drcfe;
uint32_t m_drcoptions;
bool m_single_instruction_mode;
uint8_t m_cache_dirty;
uml::code_handle *m_entry;

View File

@ -7,6 +7,11 @@
#include "32xsdefs.h"
/* map variables */
#define MAPVAR_PC M0
#define MAPVAR_CYCLES M1
struct hyperstone_device::compiler_state
{
private:
@ -824,7 +829,7 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi
}
if (BIT(compiler.mode(), 1) && !desc->delayslots)
UML_EXHc(block, uml::COND_Z, *m_exception, EXCEPTION_TRACE);
UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_TRACE_EXCEPTION);
}
else
{

View File

@ -203,7 +203,7 @@ void hyperstone_device::generate_set_global_register_low(drcuml_block &block, co
UML_AND(block, I4, I4, ~0x40); // keep reserved bit clear
}
UML_MOV(block, DRC_SR, I4);
UML_EXH(block, *m_exception, EXCEPTION_PRIVILEGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR);
UML_LABEL(block, no_exception);
if (src.is_immediate())
{
@ -725,7 +725,7 @@ void hyperstone_device::generate_chk(drcuml_block &block, compiler_state &compil
UML_ROLINS(block, I2, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK);
UML_MOV(block, DRC_SR, I2);
UML_EXH(block, *m_exception, EXCEPTION_RANGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR);
if (!unconditional)
UML_LABEL(block, done);
@ -783,7 +783,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi
UML_XOR(block, I3, I3, ~uint32_t(0));
UML_AND(block, I3, I3, S_MASK | L_MASK);
UML_TEST(block, I3, I2);
UML_EXHc(block, uml::COND_NZ, *m_exception, EXCEPTION_PRIVILEGE_ERROR);
UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_PRIVILEGE_ERROR);
}
else
{
@ -794,7 +794,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi
UML_SHL(block, I3, I3, S_SHIFT - L_SHIFT); // I3(18) = L || !L'
UML_OR(block, I3, I3, I2); // I3(18) = L || !L' || S'
UML_TEST(block, I3, S_MASK);
UML_EXHc(block, uml::COND_Z, *m_exception, EXCEPTION_PRIVILEGE_ERROR);
UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_PRIVILEGE_ERROR);
}
const int pop_next = compiler.next_label();
@ -970,7 +970,7 @@ void hyperstone_device::generate_divsu(drcuml_block &block, compiler_state &comp
UML_LABEL(block, no_result);
UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK | V_MASK, 0, ILC_MASK | P_MASK | V_MASK);
UML_EXH(block, *m_exception, EXCEPTION_RANGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR);
UML_LABEL(block, done);
}
@ -1017,7 +1017,7 @@ void hyperstone_device::generate_xm(drcuml_block &block, compiler_state &compile
UML_ROLINS(block, I2, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK);
UML_MOV(block, DRC_SR, I2);
UML_EXH(block, *m_exception, EXCEPTION_RANGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR);
UML_LABEL(block, done);
}
}
@ -1192,7 +1192,7 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil
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, EXCEPTION_PRIVILEGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR);
UML_JMP(block, done);
UML_LABEL(block, no_exception);
}
@ -1666,7 +1666,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
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, EXCEPTION_PRIVILEGE_ERROR);
UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR);
UML_LABEL(block, no_exception);
}
@ -3932,7 +3932,7 @@ void hyperstone_device::generate_frame(drcuml_block &block, compiler_state &comp
UML_TEST(block, I4, ~uint32_t(0));
UML_JMPc(block, uml::COND_Z, done);
UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK);
UML_EXH(block, *m_exception, EXCEPTION_FRAME_ERROR);
UML_EXH(block, *m_exception, TRAPNO_FRAME_ERROR);
UML_LABEL(block, done);
}

View File

@ -179,7 +179,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.regin[0] |= 1 << gsrcf_code;
desc.regout[0] |= 1 << gdst_code;
desc.regout[0] |= 1 << gdstf_code;
if (gdst_code == 0)
if (gdst_code == PC_REGISTER)
{
desc.targetpc = BRANCH_TARGET_DYNAMIC;
desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES;
@ -1170,7 +1170,7 @@ bool e132xs_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.targetpc = desc.physpc + desc.length + decode_pcrel(desc, op);
break;
case 0xec: // dbr
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH;
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.delayslots = 1;
desc.length = (op & 0x80) ? 4 : 2;
desc.targetpc = desc.physpc + desc.length + decode_pcrel(desc, op);

View File

@ -690,7 +690,8 @@ INPUT_PORTS_END
void eolith_state::eolith45(machine_config &config)
{
E132N(config, m_maincpu, 45000000); /* 45 MHz */
// TODO: turning off single instruction mode makes Raccoon World slow due to constant recompilation
E132N(config, m_maincpu, 45'000'000).set_single_instruction_mode(true); /* 45 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &eolith_state::eolith_map);
TIMER(config, "scantimer").configure_scanline(FUNC(eolith_state::eolith_speedup), "screen", 0, 1);