summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2025-03-21 17:56:15 +1100
committer Vas Crabb <vas@vastheman.com>2025-03-21 17:56:15 +1100
commit17cd39bb4c52325f00c030f850d85c865fb2b8df (patch)
treea26fef63dddbf4c850e050a187f79c121d660403
parentc9294a989ce963c1363db8d8bfad8f71eab7c289 (diff)
cpu/e132xs, cpu/drcbex64.cpp: Recompiler fixes and optimisations:
cpu/e132xs.cpp: Refactored code generation to improve performance and fixed some issues: * Moved a considerable amound of logic from execution time to code generation time. * Fixed some cases where add/subtract carry was being interpreted incorrectly. * Fixed a case where a load double intruction was incorrectly writing the same register twice. * Use UML flags to generate condition codes for addition/subtraction. * Use UML carry flag for carry-/borrow-in. * Reduced UML register pressure (improves performance for hosts with fewer callee-saved CPU registers). * Moved more logic to helper functions to simplify maintenance. cpu/drcbex64.cpp: Fixed upper bits of UML registers being cleared when used as address offset for LOAD/STORE. cpu/drcbex64.cpp: Don't do expensive zero/sign flag update for shift operations if only carry flag will be used. cpu/drcbex64.cpp: Reduced copy/paste in READ[M]/WRITE[M] generators.
-rw-r--r--src/devices/cpu/drcbex64.cpp408
-rw-r--r--src/devices/cpu/drcbex86.cpp18
-rw-r--r--src/devices/cpu/e132xs/e132xs.h17
-rw-r--r--src/devices/cpu/e132xs/e132xsdrc_ops.hxx1810
4 files changed, 753 insertions, 1500 deletions
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index 834685d8d77..46d6b27a179 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -458,6 +458,43 @@ private:
bool m_coldreg; // true for a UML register held in memory
};
+ // state to live in the near cache
+ struct near_state
+ {
+ x86code * debug_log_hashjmp; // hashjmp debugging
+ x86code * debug_log_hashjmp_fail; // hashjmp debugging
+
+ uint32_t ssemode; // saved SSE mode
+ uint32_t ssemodesave; // temporary location for saving
+ uint32_t ssecontrol[4]; // copy of the sse_control array
+ float single1; // 1.0 in single-precision
+ double double1; // 1.0 in double-precision
+
+ void * stacksave; // saved stack pointer
+
+ uint8_t flagsmap[0x1000]; // flags map
+ uint64_t flagsunmap[0x20]; // flags unmapper
+ };
+
+ // resolved memory handler functions
+ struct memory_accessors
+ {
+ resolved_memory_accessors resolved;
+ address_space::specific_access_info specific;
+ offs_t address_mask;
+ bool no_mask;
+ bool has_high_bits;
+ bool mask_high_bits;
+ };
+
+ using opcode_generate_func = void (drcbe_x64::*)(asmjit::x86::Assembler &, const uml::instruction &);
+
+ struct opcode_table_entry
+ {
+ uml::opcode_t opcode; // opcode in question
+ opcode_generate_func func; // function pointer to the work
+ };
+
// helpers
asmjit::x86::Mem MABS(const void *ptr, const uint32_t size = 0) const { return asmjit::x86::Mem(asmjit::x86::rbp, offset_from_rbp(ptr), size); }
bool short_immediate(int64_t immediate) const { return (int32_t)immediate == immediate; }
@@ -465,8 +502,9 @@ private:
void normalize_commutative(const be_parameter &dst, be_parameter &inner, be_parameter &outer);
int32_t offset_from_rbp(const void *ptr) const;
asmjit::x86::Gp get_base_register_and_offset(asmjit::x86::Assembler &a, void *target, asmjit::x86::Gp const &reg, int32_t &offset);
- void smart_call_r64(asmjit::x86::Assembler &a, x86code *target, asmjit::x86::Gp const &reg);
- void smart_call_m64(asmjit::x86::Assembler &a, x86code **target);
+ void smart_call_r64(asmjit::x86::Assembler &a, x86code *target, asmjit::x86::Gp const &reg) const;
+ void smart_call_m64(asmjit::x86::Assembler &a, x86code **target) const;
+ void emit_memaccess_setup(asmjit::x86::Assembler &a, const memory_accessors &accessors, const address_space::specific_access_info::side &side) const;
[[noreturn]] void end_of_block() const;
static void debug_log_hashjmp(offs_t pc, int mode);
@@ -557,7 +595,7 @@ 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; });
- 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, bool update_flags);
+ 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
void mov_reg_param(asmjit::x86::Assembler &a, asmjit::x86::Gp const &reg, be_parameter const &param, bool const keepflags = false);
@@ -566,7 +604,7 @@ private:
// special-case move helpers
void movsx_r64_p32(asmjit::x86::Assembler &a, asmjit::x86::Gp const &reg, be_parameter const &param);
- void mov_r64_imm(asmjit::x86::Assembler &a, asmjit::x86::Gp const &reg, uint64_t const imm);
+ void mov_r64_imm(asmjit::x86::Assembler &a, asmjit::x86::Gp const &reg, uint64_t const imm) const;
// floating-point helpers
void movss_r128_p32(asmjit::x86::Assembler &a, asmjit::x86::Xmm const &reg, be_parameter const &param);
@@ -595,46 +633,13 @@ private:
x86code * m_nocode; // nocode handler
x86code * m_endofblock; // end of block handler
- // state to live in the near cache
- struct near_state
- {
- x86code * debug_log_hashjmp; // hashjmp debugging
- x86code * debug_log_hashjmp_fail; // hashjmp debugging
-
- uint32_t ssemode; // saved SSE mode
- uint32_t ssemodesave; // temporary location for saving
- uint32_t ssecontrol[4]; // copy of the sse_control array
- float single1; // 1.0 in single-precision
- double double1; // 1.0 in double-precision
-
- void * stacksave; // saved stack pointer
-
- uint8_t flagsmap[0x1000]; // flags map
- uint64_t flagsunmap[0x20]; // flags unmapper
- };
near_state & m_near;
- // resolved memory handler functions
- struct memory_accessors
- {
- resolved_memory_accessors resolved;
- address_space::specific_access_info specific;
- offs_t address_mask;
- bool no_mask;
- bool has_high_bits;
- bool mask_high_bits;
- };
resolved_member_function m_debug_cpu_instruction_hook;
resolved_member_function m_drcmap_get_value;
std::vector<memory_accessors> m_memory_accessors;
// globals
- using opcode_generate_func = void (drcbe_x64::*)(asmjit::x86::Assembler &, const uml::instruction &);
- struct opcode_table_entry
- {
- uml::opcode_t opcode; // opcode in question
- opcode_generate_func func; // function pointer to the work
- };
static const opcode_table_entry s_opcode_table_source[];
static opcode_generate_func s_opcode_table[uml::OP_MAX];
};
@@ -926,7 +931,7 @@ inline Gp drcbe_x64::get_base_register_and_offset(Assembler &a, void *target, Gp
// directly or via a call through pointer
//-------------------------------------------------
-inline void drcbe_x64::smart_call_r64(Assembler &a, x86code *target, Gp const &reg)
+inline void drcbe_x64::smart_call_r64(Assembler &a, x86code *target, Gp const &reg) const
{
const int64_t delta = target - (x86code *)(a.code()->baseAddress() + a.offset() + 5);
if (short_immediate(delta))
@@ -944,7 +949,7 @@ inline void drcbe_x64::smart_call_r64(Assembler &a, x86code *target, Gp const &r
// directly or via a call through pointer
//-------------------------------------------------
-inline void drcbe_x64::smart_call_m64(Assembler &a, x86code **target)
+inline void drcbe_x64::smart_call_m64(Assembler &a, x86code **target) const
{
const int64_t delta = *target - (x86code *)(a.code()->baseAddress() + a.offset() + 5);
if (short_immediate(delta))
@@ -954,6 +959,54 @@ inline void drcbe_x64::smart_call_m64(Assembler &a, x86code **target)
}
+//-------------------------------------------------
+// emit_memaccess_setup - set up for call to a
+// memory access handler
+//-------------------------------------------------
+
+void drcbe_x64::emit_memaccess_setup(Assembler &a, const memory_accessors &accessors, const address_space::specific_access_info::side &side) const
+{
+ if (accessors.has_high_bits && !accessors.mask_high_bits)
+ a.mov(r10d, Gpd(REG_PARAM2)); // copy address for dispatch index
+ if (!accessors.no_mask)
+ a.and_(Gpd(REG_PARAM2), imm(accessors.address_mask)); // apply address mask
+ if (accessors.has_high_bits && !accessors.mask_high_bits)
+ a.shr(r10d, accessors.specific.low_bits); // shift off low bits
+ mov_r64_imm(a, rax, uintptr_t(side.dispatch)); // load dispatch table pointer
+ if (accessors.has_high_bits)
+ {
+ if (accessors.mask_high_bits)
+ {
+ if (accessors.specific.low_bits)
+ {
+ a.mov(r10d, Gpd(REG_PARAM2)); // save masked address
+ a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
+ }
+ a.mov(Gpq(REG_PARAM1), ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
+ if (accessors.specific.low_bits)
+ a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
+ }
+ else
+ {
+ a.mov(Gpq(REG_PARAM1), ptr(rax, r10, 3)); // load dispatch table entry
+ }
+ }
+ else
+ {
+ a.mov(Gpq(REG_PARAM1), ptr(rax)); // load dispatch table entry
+ }
+
+ if (side.is_virtual)
+ a.mov(rax, ptr(Gpq(REG_PARAM1), side.displacement)); // load vtable pointer
+ if (side.displacement)
+ a.add(Gpq(REG_PARAM1), side.displacement); // apply this pointer offset
+ if (side.is_virtual)
+ a.call(ptr(rax, side.function)); // call virtual member function
+ else
+ smart_call_r64(a, (x86code *)side.function, rax); // call non-virtual member function
+}
+
+
//**************************************************************************
// BACKEND CALLBACKS
@@ -1504,7 +1557,7 @@ void drcbe_x64::calculate_status_flags_mul_low(Assembler &a, uint32_t instsize,
a.sahf();
}
-void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsize, Operand const &dst, be_parameter const &param, bool update_flags)
+void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsize, Operand const &dst, be_parameter const &param, u8 update_flags)
{
// FIXME: upper bits may not be cleared for 32-bit form when shift count is zero
const bool carryin = (opcode == Inst::kIdRcl) || (opcode == Inst::kIdRcr);
@@ -1513,22 +1566,18 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
{
const uint32_t bitshift = param.immediate() & (opsize * 8 - 1);
- if (bitshift != 0)
+ if (bitshift)
a.emit(opcode, dst, imm(param.immediate()));
+ else if (update_flags & FLAG_C)
+ a.clc(); // throw away carry since it'll never be used
- if (update_flags)
- {
- if (bitshift == 0)
- a.clc(); // throw away carry since it'll never be used
-
+ if (update_flags & (FLAG_S | FLAG_Z))
calculate_status_flags(a, opsize, dst, FLAG_S | FLAG_Z);
- }
}
else if (update_flags || carryin)
{
- // TODO: flag update could be optimised substantially
- Label calc = a.newLabel();
- Label end = a.newLabel();
+ // TODO: flag update could be optimised
+ Label end;
const Gp shift = ecx;
@@ -1541,17 +1590,24 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
mov_reg_param(a, shift, param);
a.and_(shift, opsize * 8 - 1);
- a.short_().jnz(calc);
- if (carryin)
- a.mov(rax, r10);
+ if ((update_flags & FLAG_C) || carryin)
+ {
+ const Label calc = a.newLabel();
+ end = a.newLabel();
- if (update_flags)
- a.clc(); // throw away carry since it'll never be used
+ a.short_().jnz(calc);
- a.short_().jmp(end);
+ if (carryin)
+ a.mov(rax, r10);
- a.bind(calc);
+ if (update_flags & FLAG_C)
+ a.clc(); // throw away carry since it'll never be used
+
+ a.short_().jmp(end);
+
+ a.bind(calc);
+ }
if (carryin)
{
@@ -1561,9 +1617,10 @@ void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsiz
a.emit(opcode, dst, cl);
- a.bind(end);
+ if ((update_flags & FLAG_C) || carryin)
+ a.bind(end);
- if (update_flags)
+ if (update_flags & (FLAG_S | FLAG_Z))
calculate_status_flags(a, opsize, dst, FLAG_S | FLAG_Z); // calculate status flags but preserve carry
}
else
@@ -1656,7 +1713,7 @@ void drcbe_x64::movsx_r64_p32(Assembler &a, Gp const &reg, be_parameter const &p
a.movsxd(reg, Gpd(param.ireg())); // movsxd reg,param
}
-void drcbe_x64::mov_r64_imm(Assembler &a, Gp const &reg, uint64_t const imm)
+void drcbe_x64::mov_r64_imm(Assembler &a, Gp const &reg, uint64_t const imm) const
{
if (s32(u32(imm)) == s64(imm))
{
@@ -2672,14 +2729,14 @@ void drcbe_x64::op_load(Assembler &a, const instruction &inst)
// determine the pointer base
int32_t baseoffs;
- Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
+ const Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
// pick a target register for the general case
- Gp dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax);
+ const Gp dstreg = dstp.select_register((inst.size() == 4) ? Gp(eax) : Gp(rax));
- // immediate index
if (indp.is_immediate())
{
+ // immediate index
s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale());
if (size == SIZE_BYTE)
@@ -2691,11 +2748,10 @@ void drcbe_x64::op_load(Assembler &a, const instruction &inst)
else if (size == SIZE_QWORD)
a.mov(dstreg, ptr(basereg, offset));
}
-
- // other index
else
{
- Gp indreg = indp.select_register(rcx);
+ // other index
+ const Gp indreg = rcx;
movsx_r64_p32(a, indreg, indp);
if (size == SIZE_BYTE)
a.movzx(dstreg, byte_ptr(basereg, indreg, scalesizep.scale(), baseoffs));
@@ -2733,14 +2789,14 @@ void drcbe_x64::op_loads(Assembler &a, const instruction &inst)
// determine the pointer base
int32_t baseoffs;
- Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
+ const Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
// pick a target register for the general case
- Gp dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax);
+ const Gp dstreg = dstp.select_register((inst.size() == 4) ? Gp(eax) : Gp(rax));
- // immediate index
if (indp.is_immediate())
{
+ // immediate index
s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale());
if (size == SIZE_BYTE)
@@ -2754,11 +2810,10 @@ void drcbe_x64::op_loads(Assembler &a, const instruction &inst)
else if (size == SIZE_QWORD)
a.mov(dstreg, ptr(basereg, offset)); // mov dstreg,[basep + scale*indp]
}
-
- // other index
else
{
- Gp indreg = indp.select_register(rcx);
+ // other index
+ const Gp indreg = rcx;
movsx_r64_p32(a, indreg, indp);
if (size == SIZE_BYTE)
a.movsx(dstreg, byte_ptr(basereg, indreg, scalesizep.scale(), baseoffs)); // movsx dstreg,[basep + scale*indp]
@@ -2797,14 +2852,14 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst)
// determine the pointer base
int32_t baseoffs;
- Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
+ const Gp basereg = get_base_register_and_offset(a, basep.memory(), rdx, baseoffs);
// pick a source register for the general case
- Gp srcreg = srcp.select_register(rax);
+ const Gp srcreg = srcp.select_register(rax);
- // degenerate case: constant index
if (indp.is_immediate())
{
+ // degenerate case: constant index
s32 const offset = baseoffs + (s32(indp.immediate()) << scalesizep.scale());
// immediate source
@@ -2813,7 +2868,9 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst)
if (size == SIZE_QWORD)
{
if (short_immediate(srcp.immediate()))
+ {
a.mov(qword_ptr(basereg, offset), s32(srcp.immediate())); // mov [basep + scale*indp],srcp
+ }
else
{
a.mov(ptr(basereg, offset + 0), u32(srcp.immediate() >> 0)); // mov [basep + scale*indp],srcp
@@ -2821,16 +2878,18 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst)
}
}
else
+ {
a.mov(ptr(basereg, offset, 1 << size), srcp.immediate()); // mov [basep + scale*indp],srcp
+ }
}
-
- // variable source
else
{
+ // variable source
if (size != SIZE_QWORD)
mov_reg_param(a, srcreg.r32(), srcp); // mov srcreg,srcp
else
mov_reg_param(a, srcreg.r64(), srcp); // mov srcreg,srcp
+
if (size == SIZE_BYTE)
a.mov(ptr(basereg, offset), srcreg.r8()); // mov [basep + scale*indp],srcreg
else if (size == SIZE_WORD)
@@ -2841,20 +2900,21 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst)
a.mov(ptr(basereg, offset), srcreg.r64()); // mov [basep + scale*indp],srcreg
}
}
-
- // normal case: variable index
else
{
- Gp indreg = indp.select_register(rcx);
+ // normal case: variable index
+ const Gp indreg = rcx;
movsx_r64_p32(a, indreg, indp); // mov indreg,indp
- // immediate source
if (srcp.is_immediate())
{
+ // immediate source
if (size == SIZE_QWORD)
{
if (short_immediate(srcp.immediate()))
+ {
a.mov(qword_ptr(basereg, indreg, scalesizep.scale(), baseoffs), s32(srcp.immediate())); // mov [basep + scale*indp],srcp
+ }
else
{
a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs + 0), u32(srcp.immediate() >> 0)); // mov [basep + scale*ecx],srcp
@@ -2862,16 +2922,18 @@ void drcbe_x64::op_store(Assembler &a, const instruction &inst)
}
}
else
+ {
a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs, 1 << size), srcp.immediate()); // mov [basep + scale*ecx],srcp
+ }
}
-
- // variable source
else
{
+ // variable source
if (size != SIZE_QWORD)
mov_reg_param(a, srcreg.r32(), srcp); // mov srcreg,srcp
else
mov_reg_param(a, srcreg.r64(), srcp); // mov edx:srcreg,srcp
+
if (size == SIZE_BYTE)
a.mov(ptr(basereg, indreg, scalesizep.scale(), baseoffs), srcreg.r8()); // mov [basep + scale*ecx],srcreg
else if (size == SIZE_WORD)
@@ -2917,44 +2979,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
else
a.mov(Gpq(REG_PARAM3), make_bitmask<uint64_t>(accessors.specific.native_bytes << 3));
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.mov(r10d, Gpd(REG_PARAM2)); // copy address for dispatch index
- if (!accessors.no_mask)
- a.and_(Gpd(REG_PARAM2), imm(accessors.address_mask)); // apply address mask
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.shr(r10d, accessors.specific.low_bits); // shift off low bits
- mov_r64_imm(a, rax, uintptr_t(accessors.specific.read.dispatch)); // load dispatch table pointer
- if (accessors.has_high_bits)
- {
- if (accessors.mask_high_bits)
- {
- if (accessors.specific.low_bits)
- {
- a.mov(r10d, Gpd(REG_PARAM2)); // save masked address
- a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
- }
- a.mov(Gpq(REG_PARAM1), ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
- if (accessors.specific.low_bits)
- a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax, r10d, 3)); // load dispatch table entry
- }
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax)); // load dispatch table entry
- }
-
- if (accessors.specific.read.is_virtual)
- a.mov(rax, ptr(Gpq(REG_PARAM1), accessors.specific.read.displacement)); // load vtable pointer
- if (accessors.specific.read.displacement)
- a.add(Gpq(REG_PARAM1), accessors.specific.read.displacement); // apply this pointer offset
- if (accessors.specific.read.is_virtual)
- a.call(ptr(rax, accessors.specific.read.function)); // call virtual member function
- else
- smart_call_r64(a, (x86code *)accessors.specific.read.function, rax); // call non-virtual member function
+ emit_memaccess_setup(a, accessors, accessors.specific.read); // get dispatch table entry
}
else if (have_specific && ((1 << spacesizep.size()) < accessors.specific.native_bytes))
{
@@ -2993,11 +3018,11 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
- a.mov(rax, ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
}
else
{
- a.mov(rax, ptr(rax, r10d, 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, r10, 3)); // load dispatch table entry
}
}
else
@@ -3121,44 +3146,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
mov_reg_param(a, Gpq(REG_PARAM3), maskp);
if (have_specific && ((1 << spacesizep.size()) == accessors.specific.native_bytes))
{
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.mov(r10d, Gpd(REG_PARAM2)); // copy address for dispatch index
- if (!accessors.no_mask)
- a.and_(Gpd(REG_PARAM2), imm(accessors.address_mask)); // apply address mask
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.shr(r10d, accessors.specific.low_bits); // shift off low bits
- mov_r64_imm(a, rax, uintptr_t(accessors.specific.read.dispatch)); // load dispatch table pointer
- if (accessors.has_high_bits)
- {
- if (accessors.mask_high_bits)
- {
- if (accessors.specific.low_bits)
- {
- a.mov(r10d, Gpd(REG_PARAM2)); // save masked address
- a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
- }
- a.mov(Gpq(REG_PARAM1), ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
- if (accessors.specific.low_bits)
- a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax, r10d, 3)); // load dispatch table entry
- }
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax)); // load dispatch table entry
- }
-
- if (accessors.specific.read.is_virtual)
- a.mov(rax, ptr(Gpq(REG_PARAM1), accessors.specific.read.displacement)); // load vtable pointer
- if (accessors.specific.read.displacement)
- a.add(Gpq(REG_PARAM1), accessors.specific.read.displacement); // apply this pointer offset
- if (accessors.specific.read.is_virtual)
- a.call(ptr(rax, accessors.specific.read.function)); // call virtual member function
- else
- smart_call_r64(a, (x86code *)accessors.specific.read.function, rax); // call non-virtual member function
+ emit_memaccess_setup(a, accessors, accessors.specific.read); // get dispatch table entry
}
else if (have_specific && ((1 << spacesizep.size()) < accessors.specific.native_bytes))
{
@@ -3192,11 +3180,11 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
- a.mov(rax, ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
}
else
{
- a.mov(rax, ptr(rax, r10d, 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, r10, 3)); // load dispatch table entry
}
}
else
@@ -3322,44 +3310,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
else
a.mov(Gpq(REG_PARAM4), make_bitmask<uint64_t>(accessors.specific.native_bytes << 3));
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.mov(r10d, Gpd(REG_PARAM2)); // copy address for dispatch index
- if (!accessors.no_mask)
- a.and_(Gpd(REG_PARAM2), imm(accessors.address_mask)); // apply address mask
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.shr(r10d, accessors.specific.low_bits); // shift off low bits
- mov_r64_imm(a, rax, uintptr_t(accessors.specific.write.dispatch)); // load dispatch table pointer
- if (accessors.has_high_bits)
- {
- if (accessors.mask_high_bits)
- {
- if (accessors.specific.low_bits)
- {
- a.mov(r10d, Gpd(REG_PARAM2)); // save masked address
- a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
- }
- a.mov(Gpq(REG_PARAM1), ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
- if (accessors.specific.low_bits)
- a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax, r10d, 3)); // load dispatch table entry
- }
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax)); // load dispatch table entry
- }
-
- if (accessors.specific.write.is_virtual)
- a.mov(rax, ptr(Gpq(REG_PARAM1), accessors.specific.write.displacement)); // load vtable pointer
- if (accessors.specific.write.displacement)
- a.add(Gpq(REG_PARAM1), accessors.specific.write.displacement); // apply this pointer offset
- if (accessors.specific.write.is_virtual)
- a.call(ptr(rax, accessors.specific.write.function)); // call virtual member function
- else
- smart_call_r64(a, (x86code *)accessors.specific.write.function, rax); // call non-virtual member function
+ emit_memaccess_setup(a, accessors, accessors.specific.write);
}
else if (have_specific && ((1 << spacesizep.size()) < accessors.specific.native_bytes))
{
@@ -3388,11 +3339,11 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
- a.mov(rax, ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
}
else
{
- a.mov(rax, ptr(rax, r10d, 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, r10, 3)); // load dispatch table entry
}
}
else
@@ -3488,44 +3439,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
else
mov_reg_param(a, Gpq(REG_PARAM4), maskp); // get mem_mask
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.mov(r10d, Gpd(REG_PARAM2)); // copy address for dispatch index
- if (!accessors.no_mask)
- a.and_(Gpd(REG_PARAM2), imm(accessors.address_mask)); // apply address mask
- if (accessors.has_high_bits && !accessors.mask_high_bits)
- a.shr(r10d, accessors.specific.low_bits); // shift off low bits
- mov_r64_imm(a, rax, uintptr_t(accessors.specific.write.dispatch)); // load dispatch table pointer
- if (accessors.has_high_bits)
- {
- if (accessors.mask_high_bits)
- {
- if (accessors.specific.low_bits)
- {
- a.mov(r10d, Gpd(REG_PARAM2)); // save masked address
- a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
- }
- a.mov(Gpq(REG_PARAM1), ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
- if (accessors.specific.low_bits)
- a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax, r10d, 3)); // load dispatch table entry
- }
- }
- else
- {
- a.mov(Gpq(REG_PARAM1), ptr(rax)); // load dispatch table entry
- }
-
- if (accessors.specific.write.is_virtual)
- a.mov(rax, ptr(Gpq(REG_PARAM1), accessors.specific.write.displacement)); // load vtable pointer
- if (accessors.specific.write.displacement)
- a.add(Gpq(REG_PARAM1), accessors.specific.write.displacement); // apply this pointer offset
- if (accessors.specific.write.is_virtual)
- a.call(ptr(rax, accessors.specific.write.function)); // call virtual member function
- else
- smart_call_r64(a, (x86code *)accessors.specific.write.function, rax); // call non-virtual member function
+ emit_memaccess_setup(a, accessors, accessors.specific.write);
}
else if (have_specific && ((1 << spacesizep.size()) < accessors.specific.native_bytes))
{
@@ -3558,11 +3472,11 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
- a.mov(rax, ptr(rax, Gpd(REG_PARAM2), 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
}
else
{
- a.mov(rax, ptr(rax, r10d, 3)); // load dispatch table entry
+ a.mov(rax, ptr(rax, r10, 3)); // load dispatch table entry
}
}
else
@@ -4002,7 +3916,7 @@ void drcbe_x64::op_roland(Assembler &a, const instruction &inst)
else
{
mov_reg_param(a, dstreg, srcp);
- shift_op_param(a, Inst::kIdRol, inst.size(), dstreg, shiftp, false);
+ shift_op_param(a, Inst::kIdRol, inst.size(), dstreg, shiftp, 0);
alu_op_param(a, Inst::kIdAnd, dstreg, maskp,
[inst](Assembler &a, Operand const &dst, be_parameter const &src)
{
@@ -4293,7 +4207,7 @@ void drcbe_x64::op_rolins(Assembler &a, const instruction &inst)
if (!maskimm)
mov_reg_param(a, maskreg, maskp);
- shift_op_param(a, Inst::kIdRol, inst.size(), srcreg, shiftp, false);
+ shift_op_param(a, Inst::kIdRol, inst.size(), srcreg, shiftp, 0);
mov_reg_param(a, dstreg, dstp);
if (!maskimm)
@@ -5416,7 +5330,7 @@ void drcbe_x64::op_shift(Assembler &a, const uml::instruction &inst)
if (dstp.is_memory() && ((inst.size() == 8) || !dstp.is_cold_register()) && (dstp == src1p))
{
// dstp == src1p in memory
- shift_op_param(a, Opcode, inst.size(), MABS(dstp.memory(), inst.size()), src2p, bool(inst.flags()));
+ shift_op_param(a, Opcode, inst.size(), MABS(dstp.memory(), inst.size()), src2p, inst.flags());
}
else
{
@@ -5429,7 +5343,7 @@ void drcbe_x64::op_shift(Assembler &a, const uml::instruction &inst)
mov_reg_param(a, dstreg, src1p, true);
else
mov_reg_param(a, dstreg, src1p);
- shift_op_param(a, Opcode, inst.size(), dstreg, src2p, bool(inst.flags()));
+ shift_op_param(a, Opcode, inst.size(), dstreg, src2p, inst.flags());
mov_param_reg(a, dstp, dstreg);
}
}
diff --git a/src/devices/cpu/drcbex86.cpp b/src/devices/cpu/drcbex86.cpp
index b3acf261860..724da1cd125 100644
--- a/src/devices/cpu/drcbex86.cpp
+++ b/src/devices/cpu/drcbex86.cpp
@@ -1495,7 +1495,9 @@ void drcbe_x86::emit_mov_r32_p32(Assembler &a, Gp const &reg, be_parameter const
a.mov(reg, param.immediate()); // mov reg,param
}
else if (param.is_memory())
+ {
a.mov(reg, MABS(param.memory())); // mov reg,[param]
+ }
else if (param.is_int_register())
{
if (reg.id() != param.ireg())
@@ -3839,14 +3841,14 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst)
if (size == SIZE_BYTE && (srcreg.id() & 4)) // FIXME: &4?
srcreg = eax;
- // degenerate case: constant index
if (indp.is_immediate())
{
+ // degenerate case: constant index
int const scale = 1 << (scalesizep.scale());
- // immediate source
if (srcp.is_immediate())
{
+ // immediate source
if (size == SIZE_BYTE)
a.mov(MABS(basep.memory(scale*indp.immediate()), 1), srcp.immediate()); // mov [basep + scale*indp],srcp
else if (size == SIZE_WORD)
@@ -3860,14 +3862,14 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst)
// mov [basep + scale*indp + 4],srcp >> 32
}
}
-
- // variable source
else
{
+ // variable source
if (size != SIZE_QWORD)
emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp
else
emit_mov_r64_p64(a, srcreg, edx, srcp); // mov edx:srcreg,srcp
+
if (size == SIZE_BYTE)
a.mov(MABS(basep.memory(scale*indp.immediate())), srcreg.r8()); // mov [basep + scale*indp],srcreg
else if (size == SIZE_WORD)
@@ -3881,16 +3883,15 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst)
}
}
}
-
- // normal case: variable index
else
{
+ // normal case: variable index
Gp const indreg = indp.select_register(ecx);
emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp
- // immediate source
if (srcp.is_immediate())
{
+ // immediate source
if (size == SIZE_BYTE)
a.mov(ptr(u64(basep.memory()), indreg, scalesizep.scale(), 1), srcp.immediate()); // mov [basep + 1*ecx],srcp
else if (size == SIZE_WORD)
@@ -3904,10 +3905,9 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst)
// mov [basep + 8*ecx + 4],srcp >> 32
}
}
-
- // variable source
else
{
+ // variable source
if (size != SIZE_QWORD)
emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp
else
diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h
index 81cba7ee059..5ce7e5ce423 100644
--- a/src/devices/cpu/e132xs/e132xs.h
+++ b/src/devices/cpu/e132xs/e132xs.h
@@ -501,20 +501,31 @@ private:
void generate_get_trap_addr(drcuml_block &block, uml::code_label &label, uint32_t trapno);
void generate_check_delay_pc(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_decode_const(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_decode_immediate_s(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ uint32_t generate_get_const(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ uint32_t generate_get_immediate_s(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
void generate_ignore_immediate_s(drcuml_block &block, const opcode_desc *desc);
- void generate_decode_pcrel(drcuml_block &block, const opcode_desc *desc);
+ uint32_t generate_get_pcrel(drcuml_block &block, const opcode_desc *desc);
void generate_ignore_pcrel(drcuml_block &block, const opcode_desc *desc);
void generate_get_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
void generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ 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_load_operand(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx);
+ void generate_load_src_addsub(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx, uml::parameter sr);
+ void generate_set_dst(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx);
+ void generate_update_flags_addsub(drcuml_block &block, compiler_state &compiler, uml::parameter sr);
+ void generate_update_flags_addsubc(drcuml_block &block, compiler_state &compiler, uml::parameter sr);
+ void generate_update_flags_addsubs(drcuml_block &block, compiler_state &compiler, uml::parameter sr);
template <trap_exception_or_int TYPE> void generate_trap_exception_or_int(drcuml_block &block);
void generate_int(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t addr);
void generate_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t addr);
void generate_software(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ template <reg_bank DST_GLOBAL, typename T> void generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, T &&body);
+
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_chk(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL> void generate_movd(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
template <reg_bank DST_GLOBAL, reg_bank SRC_GLOBAL, sign_mode SIGNED> void generate_divsu(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx
index f8fc201828a..98b491c4d04 100644
--- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx
+++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx
@@ -18,7 +18,7 @@ void hyperstone_device::generate_check_delay_pc(drcuml_block &block, compiler_st
UML_SETc(block, uml::COND_NZ, mem(&m_core->delay_slot_taken));
}
-void hyperstone_device::generate_decode_const(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
+uint32_t hyperstone_device::generate_get_const(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
const uint16_t imm_1 = m_pr16(desc->pc + 2);
@@ -26,14 +26,13 @@ void hyperstone_device::generate_decode_const(drcuml_block &block, compiler_stat
{
const uint16_t imm_2 = m_pr16(desc->pc + 4);
- uint32_t imm = imm_2;
- imm |= ((imm_1 & 0x3fff) << 16);
+ uint32_t imm = imm_2 | (uint32_t(imm_1 & 0x3fff) << 16);
if (imm_1 & 0x4000)
imm |= 0xc0000000;
UML_ADD(block, DRC_PC, DRC_PC, 4);
- UML_MOV(block, I1, imm);
+ return imm;
}
else
{
@@ -43,43 +42,29 @@ void hyperstone_device::generate_decode_const(drcuml_block &block, compiler_stat
imm |= 0xffffc000;
UML_ADD(block, DRC_PC, DRC_PC, 2);
- UML_MOV(block, I1, imm);
+ return imm;
}
}
-void hyperstone_device::generate_decode_immediate_s(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
+uint32_t hyperstone_device::generate_get_immediate_s(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
const uint16_t op = desc->opptr.w[0];
switch (op & 0xf)
{
case 0:
- UML_MOV(block, I1, 16);
- return;
+ return 16;
case 1:
- {
- uint32_t extra_u = (m_pr16(desc->pc + 2) << 16) | m_pr16(desc->pc + 4);
UML_ADD(block, DRC_PC, DRC_PC, 4);
- UML_MOV(block, I1, extra_u);
- return;
- }
+ return (uint32_t(m_pr16(desc->pc + 2)) << 16) | m_pr16(desc->pc + 4);
case 2:
- {
- uint32_t extra_u = m_pr16(desc->pc + 2);
UML_ADD(block, DRC_PC, DRC_PC, 2);
- UML_MOV(block, I1, extra_u);
- return;
- }
+ return m_pr16(desc->pc + 2);
case 3:
- {
- uint32_t extra_u = 0xffff0000 | m_pr16(desc->pc + 2);
UML_ADD(block, DRC_PC, DRC_PC, 2);
- UML_MOV(block, I1, extra_u);
- return;
- }
+ return 0xffff0000 | m_pr16(desc->pc + 2);
default:
- UML_MOV(block, I1, s_immediate_values[op & 0xf]);
- return;
+ return s_immediate_values[op & 0xf];
}
}
@@ -93,32 +78,29 @@ void hyperstone_device::generate_ignore_immediate_s(drcuml_block &block, const o
UML_ADD(block, DRC_PC, DRC_PC, offsets[nybble]);
}
-void hyperstone_device::generate_decode_pcrel(drcuml_block &block, const opcode_desc *desc)
+uint32_t hyperstone_device::generate_get_pcrel(drcuml_block &block, const opcode_desc *desc)
{
const uint16_t op = desc->opptr.w[0];
- int32_t offset;
if (op & 0x80)
{
- uint16_t next = m_pr16(desc->pc + 2);
-
- offset = (op & 0x7f) << 16;
- offset |= (next & 0xfffe);
-
+ const uint16_t next = m_pr16(desc->pc + 2);
+ uint32_t offset = (uint32_t(op & 0x7f) << 16) | (next & 0xfffe);
if (next & 1)
offset |= 0xff800000;
UML_ADD(block, DRC_PC, DRC_PC, 2);
+
+ return offset;
}
else
{
- offset = op & 0x7e;
-
+ uint32_t offset = op & 0x7e;
if (op & 1)
offset |= 0xffffff80;
- }
- UML_MOV(block, I1, offset);
+ return offset;
+ }
}
void hyperstone_device::generate_ignore_pcrel(drcuml_block &block, const opcode_desc *desc)
@@ -236,6 +218,223 @@ void hyperstone_device::generate_set_global_register(drcuml_block &block, compil
UML_LABEL(block, done);
}
+void hyperstone_device::generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src)
+{
+ if (dst_code == PC_REGISTER)
+ {
+ UML_AND(block, DRC_PC, src, ~uint32_t(1));
+ }
+ else if (dst_code == SR_REGISTER)
+ {
+ UML_ROLINS(block, DRC_SR, src, 0, 0x0000ffff);
+ UML_AND(block, DRC_SR, DRC_SR, ~0x40);
+ UML_TEST(block, mem(&m_core->intblock), ~uint32_t(0));
+ UML_MOVc(block, uml::COND_Z, mem(&m_core->intblock), 1);
+ }
+ else
+ {
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ }
+}
+
+void hyperstone_device::generate_set_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src)
+{
+ // Expects cycles in I7 (cleared after use), clobbers I6
+ dst_code |= 0x10;
+
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I7);
+ UML_MOV(block, I7, 0);
+ switch (dst_code)
+ {
+ case 16: // G16 reserved
+ case 17: // G17 reserved
+ case BCR_REGISTER: // G20 Bus Control Register
+ case WCR_REGISTER: // G24 Watchdog Compare Register
+ case 28: // G28 reserved
+ case 29: // G29 reserved
+ case 30: // G30 reserved
+ case 31: // G31 reserved
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ break;
+ case SP_REGISTER: // G18 Stack Pointer
+ case UB_REGISTER: // G19 Upper Stack Bound
+ UML_AND(block, I6, src, ~uint32_t(3));
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, I6, SIZE_DWORD, SCALE_x4);
+ break;
+ case TPR_REGISTER: // G21 Timer Prescaler Register
+ {
+ const int skip_compute_tr = compiler.m_labelnum++;
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ UML_TEST(block, src, 0x80000000);
+ UML_JMPc(block, uml::COND_NZ, skip_compute_tr);
+ UML_CALLC(block, cfunc_compute_tr, this);
+ UML_CALLC(block, cfunc_update_timer_prescale, this);
+ UML_LABEL(block, skip_compute_tr);
+ UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
+ }
+ break;
+ case TCR_REGISTER: // G22 Timer Compare Register
+ {
+ const int done = compiler.m_labelnum++;
+ UML_LOAD(block, I6, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
+ UML_CMP(block, I6, src);
+ UML_JMPc(block, uml::COND_E, done);
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
+ UML_CMP(block, mem(&m_core->intblock), 1);
+ UML_MOVc(block, uml::COND_L, mem(&m_core->intblock), 1);
+ UML_LABEL(block, done);
+ }
+ break;
+ case TR_REGISTER: // G23 Timer Register
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ UML_MOV(block, mem(&m_core->tr_base_value), src);
+ UML_CALLC(block, cfunc_total_cycles, this);
+ UML_DMOV(block, mem(&m_core->tr_base_cycles), mem(&m_core->numcycles));
+ UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
+ break;
+ case ISR_REGISTER: // G25 Input Status Register (read-only)
+ break;
+ case FCR_REGISTER: // G26 Function Control Register
+ {
+ const int skip_adjust_timer = compiler.m_labelnum++;
+ UML_LOAD(block, I6, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
+ UML_XOR(block, I6, I6, src);
+ UML_TEST(block, I6, 0x80000000);
+ UML_JMPc(block, uml::COND_Z, skip_adjust_timer);
+ UML_CALLC(block, cfunc_adjust_timer_interrupt, this);
+ UML_LABEL(block, skip_adjust_timer);
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ UML_CMP(block, mem(&m_core->intblock), 1);
+ UML_MOVc(block, uml::COND_L, mem(&m_core->intblock), 1);
+ }
+ break;
+ case MCR_REGISTER: // G27 Memory Control Register
+ UML_ROLAND(block, I6, src, 20, 0x7);
+ UML_LOAD(block, I6, (void *)s_trap_entries, I6, SIZE_DWORD, SCALE_x4);
+ UML_MOV(block, mem(&m_core->trap_entry), I6);
+ UML_STORE(block, (void *)m_core->global_regs, dst_code, src, SIZE_DWORD, SCALE_x4);
+ break;
+ default:
+ throw emu_fatalerror("%s: invalid high global register G%u\n", dst_code);
+ }
+}
+
+void hyperstone_device::generate_load_operand(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx)
+{
+ // expects frame pointer in I3 if local
+ // sets localidx if local before setting dst
+ if (global)
+ {
+ UML_LOAD(block, dst, (void *)m_core->global_regs, code, SIZE_DWORD, SCALE_x4);
+ }
+ else
+ {
+ UML_ADD(block, localidx, I3, code);
+ UML_AND(block, localidx, localidx, 0x3f);
+ UML_LOAD(block, dst, (void *)m_core->local_regs, localidx, SIZE_DWORD, SCALE_x4);
+ }
+}
+
+void hyperstone_device::generate_load_src_addsub(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx, uml::parameter sr)
+{
+ // expects frame pointer in I3 if local
+ // sets localidx if local before setting dst
+ if (global)
+ {
+ if (code == SR_REGISTER)
+ UML_AND(block, dst, sr, C_MASK);
+ else
+ UML_LOAD(block, dst, (void *)m_core->global_regs, code, SIZE_DWORD, SCALE_x4);
+ }
+ else
+ {
+ UML_ADD(block, localidx, I3, code);
+ UML_AND(block, localidx, localidx, 0x3f);
+ UML_LOAD(block, dst, (void *)m_core->local_regs, localidx, SIZE_DWORD, SCALE_x4);
+ }
+}
+
+void hyperstone_device::generate_set_dst(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx)
+{
+ // expects frame pointer in I3 if local and calcidx is true
+ // sets localidx if local and calcidx is true before storing src
+ // localidx is input if local and calcidx is false
+ if (global)
+ {
+ generate_set_global_register_low(block, compiler, code, src);
+ if (code == PC_REGISTER)
+ {
+ UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
+ generate_branch(block, desc->targetpc, desc);
+ }
+ }
+ else
+ {
+ if (calcidx)
+ {
+ UML_ADD(block, localidx, I3, code);
+ UML_AND(block, localidx, localidx, 0x3f);
+ }
+ UML_STORE(block, (void *)m_core->local_regs, localidx, src, SIZE_DWORD, SCALE_x4);
+ }
+}
+
+void hyperstone_device::generate_update_flags_addsub(drcuml_block &block, compiler_state &compiler, uml::parameter sr)
+{
+ // expects result in I0 and UML flags set by ADD/SUB
+ // clobbers I1, I4 and I5
+
+ UML_SETc(block, uml::COND_V, I4); // I4 = ...V
+ UML_SETc(block, uml::COND_Z, I5); // I5 = ...Z
+ UML_SETc(block, uml::COND_C, I1); // I1 = ...C
+ UML_SHL(block, I4, I4, V_SHIFT); // I4 = V...
+ UML_OR(block, I1, I1, I4); // I1 = V..C
+ UML_SHL(block, I4, I5, Z_SHIFT); // I4 = ..Z.
+ UML_OR(block, I1, I1, I4); // I1 = V.ZC
+ UML_ROLAND(block, I4, I0, 3, N_MASK); // I4 = .N..
+ UML_OR(block, I1, I1, I4); // I1 = VNZC
+
+ UML_ROLINS(block, sr, I1, 0, (V_MASK | N_MASK | Z_MASK | C_MASK));
+}
+
+void hyperstone_device::generate_update_flags_addsubc(drcuml_block &block, compiler_state &compiler, uml::parameter sr)
+{
+ // expects result in I0 and UML flags set by ADD/SUB
+ // clobbers I1, I4 and I5
+
+ UML_SETc(block, uml::COND_V, I4); // I4 = ...V
+ UML_SETc(block, uml::COND_Z, I5); // I5 = ...Z
+ UML_SETc(block, uml::COND_C, I1); // I1 = ...C
+ UML_SHL(block, I4, I4, V_SHIFT); // I4 = V...
+ UML_OR(block, I1, I1, I4); // I1 = V..C
+ UML_SHL(block, I4, I5, Z_SHIFT); // I4 = ..Z.
+ UML_OR(block, I1, I1, I4); // I1 = V.ZC
+ UML_ROLAND(block, I4, I0, 3, N_MASK); // I4 = .N..
+ UML_OR(block, I1, I1, I4); // I1 = VNZC
+ UML_OR(block, I4, I2, ~(Z_MASK)); // combine with old Z flag
+ UML_AND(block, I1, I1, I4);
+
+ UML_ROLINS(block, sr, I1, 0, (V_MASK | N_MASK | Z_MASK | C_MASK));
+}
+
+void hyperstone_device::generate_update_flags_addsubs(drcuml_block &block, compiler_state &compiler, uml::parameter sr)
+{
+ // expects UML flags set by ADD/SUB
+ // clobbers I1, I4 and I5
+
+ UML_SETc(block, uml::COND_V, I4); // I4 = ...V
+ UML_SETc(block, uml::COND_S, I1); // I1 = ...S
+ UML_SETc(block, uml::COND_Z, I5); // I5 = ...Z
+ UML_SHL(block, I4, I4, V_SHIFT); // I4 = V...
+ UML_SHL(block, I1, I1, N_SHIFT); // I1 = .N..
+ UML_OR(block, I1, I1, I4); // I1 = VN..
+ UML_SHL(block, I4, I5, Z_SHIFT); // I4 = ..Z.
+ UML_OR(block, I1, I1, I4); // I1 = VNZ.
+
+ UML_ROLINS(block, sr, I1, 0, (V_MASK | N_MASK | Z_MASK));
+}
+
template <hyperstone_device::trap_exception_or_int TYPE>
void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block)
{
@@ -366,6 +565,29 @@ void hyperstone_device::generate_software(drcuml_block &block, compiler_state &c
}
+
+template <hyperstone_device::reg_bank DST_GLOBAL, typename T>
+inline void hyperstone_device::generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, T &&body)
+{
+ // clobbers I0, I1 and I3, body should update I0 and set Z flag
+
+ generate_check_delay_pc(block, compiler, desc);
+
+ if (!DST_GLOBAL)
+ UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
+
+ body();
+
+ UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
+ UML_MOVc(block, uml::COND_NZ, I1, 0);
+ UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
+
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
+}
+
+
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::generate_chk(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
@@ -524,9 +746,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi
UML_AND(block, DRC_SR, DRC_SR, ~N_MASK);
if (DST_GLOBAL)
{
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, 0);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, dst_code, 0);
UML_MOV(block, I4, dstf_code);
UML_MOV(block, I5, 0);
generate_set_global_register(block, compiler, desc);
@@ -579,9 +799,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi
if (DST_GLOBAL)
{
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I0);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, dst_code, uml::I0);
UML_MOV(block, I4, dstf_code);
UML_MOV(block, I5, I1);
generate_set_global_register(block, compiler, desc);
@@ -790,53 +1008,21 @@ void hyperstone_device::generate_mask(drcuml_block &block, compiler_state &compi
const uint32_t src_code = op & 0xf;
const uint32_t dst_code = (op & 0xf0) >> 4;
- generate_decode_const(block, compiler, desc);
+ const uint32_t src = generate_get_const(block, compiler, desc);
+
generate_check_delay_pc(block, compiler, desc);
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
-
- UML_AND(block, I1, I1, I2);
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0);
- int skip_mask;
- UML_AND(block, DRC_SR, DRC_SR, ~Z_MASK);
- UML_TEST(block, I1, ~0);
- UML_JMPc(block, uml::COND_NZ, skip_mask = compiler.m_labelnum++);
- UML_OR(block, DRC_SR, DRC_SR, Z_MASK);
- UML_LABEL(block, skip_mask);
+ UML_AND(block, I0, I0, src);
+ UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
+ UML_MOVc(block, uml::COND_NZ, I1, 0);
+ UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
- if (dst_code == PC_REGISTER)
- generate_branch(block, desc->targetpc, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I1, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I0, I3, dst_code);
- UML_AND(block, I0, I0, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I0, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true);
}
@@ -849,68 +1035,22 @@ void hyperstone_device::generate_sum(drcuml_block &block, compiler_state &compil
const uint32_t src_code = op & 0xf;
const uint32_t dst_code = (op & 0xf0) >> 4;
- generate_decode_const(block, compiler, desc);
+ const uint32_t src = generate_get_const(block, compiler, desc);
+
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- {
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- }
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
-
-#ifndef PTR64
- UML_DAND(block, I1, I1, 0x00000000ffffffffULL);
-#endif
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0);
- UML_DADD(block, I5, I1, I2);
+ UML_ADD(block, I0, I0, src);
- UML_AND(block, DRC_SR, DRC_SR, ~(C_MASK | V_MASK | Z_MASK | N_MASK));
- UML_DTEST(block, I5, 0x100000000ULL);
- UML_SETc(block, uml::COND_NZ, I6);
- UML_ROLINS(block, DRC_SR, I6, C_SHIFT, C_MASK);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- UML_XOR(block, I6, I5, I1);
- UML_XOR(block, I1, I5, I2);
- UML_AND(block, I1, I1, I6);
- UML_AND(block, I1, I1, 0x80000000);
- UML_ROLINS(block, DRC_SR, I1, 4, V_MASK);
-
- UML_TEST(block, I5, ~0);
- UML_SETc(block, uml::COND_Z, I6);
- UML_ROLINS(block, DRC_SR, I6, Z_SHIFT, Z_MASK);
-
- UML_ROLINS(block, DRC_SR, I5, 3, N_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- if (dst_code == PC_REGISTER)
- generate_branch(block, desc->targetpc, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I0, I3, dst_code);
- UML_AND(block, I0, I0, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I0, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true);
}
@@ -934,58 +1074,17 @@ void hyperstone_device::generate_cmp(drcuml_block &block, compiler_state &compil
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I2, DRC_SR, 7, 0x7f);
-
- if (SRC_GLOBAL)
- {
- if (src_code == SR_REGISTER)
- UML_AND(block, I0, DRC_SR, C_MASK);
- else
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I1, I2, src_code);
- UML_AND(block, I1, I1, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I2, dst_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
-
-#ifndef PTR64
- UML_DAND(block, I0, I0, 0x00000000ffffffffULL);
-#endif
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- UML_DSUB(block, I2, I1, I0); // tmp
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_XOR(block, I2, I2, I1);
- UML_XOR(block, I3, I1, I0);
- UML_AND(block, I3, I3, I2);
- UML_ROLINS(block, I3, I3, 4, V_MASK);
+ UML_SUB(block, I0, I0, I1);
- UML_CMP(block, I1, I0);
- UML_SETc(block, uml::COND_B, I2);
- UML_ROLINS(block, I3, I2, C_SHIFT, C_MASK);
-
- UML_CMP(block, I1, I0);
- UML_SETc(block, uml::COND_E, I2);
- UML_ROLINS(block, I3, I2, Z_SHIFT, Z_MASK);
-
- UML_CMP(block, I1, I0);
- UML_SETc(block, uml::COND_L, I2);
- UML_ROLINS(block, I3, I2, N_SHIFT, N_MASK);
-
- UML_ROLINS(block, DRC_SR, I3, 0, (V_MASK | N_MASK | Z_MASK | C_MASK));
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
}
void hyperstone_device::generate_get_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
@@ -1031,14 +1130,16 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil
generate_check_delay_pc(block, compiler, desc);
+ int done;
if (DST_GLOBAL)
{
- int no_exception;
+ const int no_exception = compiler.m_labelnum++;
UML_TEST(block, DRC_SR, H_MASK);
- UML_JMPc(block, uml::COND_Z, no_exception = compiler.m_labelnum++);
+ UML_JMPc(block, uml::COND_Z, no_exception);
UML_TEST(block, DRC_SR, S_MASK);
UML_JMPc(block, uml::COND_NZ, no_exception);
UML_EXH(block, *m_exception[EXCEPTION_PRIVILEGE_ERROR], 0);
+ UML_JMP(block, done = compiler.m_labelnum++);
UML_LABEL(block, no_exception);
}
@@ -1062,18 +1163,25 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil
UML_ROLINS(block, DRC_SR, I2, Z_SHIFT, Z_MASK);
UML_ROLINS(block, DRC_SR, I5, 3, N_MASK);
- int done = compiler.m_labelnum++;
if (DST_GLOBAL)
{
+ const int highglobal = compiler.m_labelnum++;
+
UML_TEST(block, DRC_SR, H_MASK);
- UML_MOVc(block, uml::COND_NZ, I4, 16 + dst_code);
- UML_MOVc(block, uml::COND_Z, I4, dst_code);
+ 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);
+ generate_branch(block, desc->targetpc, desc);
+ }
+ UML_JMP(block, done);
+
+ UML_LABEL(block, highglobal);
UML_AND(block, DRC_SR, DRC_SR, ~H_MASK);
- UML_MOV(block, I3, I4);
- generate_set_global_register(block, compiler, desc);
- UML_CMP(block, I3, 0);
- UML_JMPc(block, uml::COND_NE, done);
- generate_branch(block, desc->targetpc, desc);
+ generate_set_global_register_high(block, compiler, dst_code, uml::I5);
+
+ UML_LABEL(block, done);
}
else
{
@@ -1082,8 +1190,6 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil
UML_AND(block, I2, I2, 0x3f);
UML_STORE(block, (void *)m_core->local_regs, I2, I5, SIZE_DWORD, SCALE_x4);
}
-
- UML_LABEL(block, done);
}
@@ -1098,81 +1204,53 @@ void hyperstone_device::generate_add(drcuml_block &block, compiler_state &compil
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- if (src_code == SR_REGISTER)
- UML_AND(block, I0, DRC_SR, C_MASK);
- else
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I3, I3, dst_code);
- UML_AND(block, I3, I3, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I3, SIZE_DWORD, SCALE_x4);
- }
-
- UML_ADD(block, I2, I0, I1);
-
- UML_SETc(block, uml::COND_C, I6);
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_XOR(block, I4, I0, I2);
- UML_XOR(block, I5, I1, I2);
- UML_AND(block, I4, I4, I5);
- UML_ROLINS(block, I6, I4, 4, V_MASK);
-
- UML_TEST(block, I2, ~0);
- UML_SETc(block, uml::COND_Z, I4);
- UML_ROLINS(block, I6, I4, Z_SHIFT, Z_MASK);
- UML_ROLINS(block, I6, I2, 3, N_MASK);
- UML_ROLINS(block, DRC_SR, I6, 0, (V_MASK | N_MASK | Z_MASK | C_MASK));
+ UML_ADD(block, I0, I0, I1);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I2);
- generate_set_global_register(block, compiler, desc);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- if (dst_code == PC_REGISTER)
- {
- UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I2, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I3, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
template <hyperstone_device::reg_bank DST_GLOBAL, hyperstone_device::reg_bank SRC_GLOBAL>
void hyperstone_device::generate_adds(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
{
- osd_printf_error("Unimplemented: generate_adds (%08x)\n", desc->pc);
- fflush(stdout);
- fatalerror(" ");
+ UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
+
+ const uint16_t op = desc->opptr.w[0];
+ const uint32_t src_code = op & 0xf;
+ const uint32_t dst_code = (op & 0xf0) >> 4;
+
+ generate_check_delay_pc(block, compiler, desc);
+
+ UML_MOV(block, I2, DRC_SR);
+ if (!SRC_GLOBAL || !DST_GLOBAL)
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
+
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
+
+ UML_ADD(block, I0, I0, I1);
+
+ generate_update_flags_addsubs(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
+
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
+
+ const int no_exception = compiler.m_labelnum++;
+ UML_TEST(block, DRC_SR, V_MASK);
+ UML_JMPc(block, uml::COND_Z, no_exception);
+ UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT), 0, ILC_MASK);
+ generate_trap_exception_or_int<IS_EXCEPTION>(block);
+ UML_LABEL(block, no_exception);
}
@@ -1188,31 +1266,12 @@ void hyperstone_device::generate_cmpb(drcuml_block &block, compiler_state &compi
generate_check_delay_pc(block, compiler, desc);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I2, DRC_SR, 7, 0x7f);
-
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I1, I2, src_code);
- UML_AND(block, I1, I1, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
+ UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I2, dst_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_TEST(block, I1, I0);
+ UML_TEST(block, I0, I1);
UML_SETc(block, uml::COND_Z, I0);
UML_ROLINS(block, DRC_SR, I0, Z_SHIFT, Z_MASK);
}
@@ -1229,80 +1288,27 @@ void hyperstone_device::generate_subc(drcuml_block &block, compiler_state &compi
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- UML_AND(block, I0, DRC_SR, C_MASK);
-#ifndef PTR64
- UML_DAND(block, I0, I0, 0x00000000ffffffffULL);
-#endif
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL,src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- if (SRC_GLOBAL)
- {
- if (src_code != SR_REGISTER)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- UML_DADD(block, I0, I2, I0);
- }
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- UML_DADD(block, I0, I2, I0);
- }
-
- if (DST_GLOBAL)
+ if (!SRC_GLOBAL || (src_code != SR_REGISTER))
{
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
+ UML_SHR(block, I4, I2, 1); // set up carry in, result unused
+ UML_SUBB(block, I0, I0, I1);
}
else
{
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
+ UML_SUB(block, I0, I0, I1);
}
- UML_AND(block, I6, DRC_SR, Z_MASK);
- UML_AND(block, I5, DRC_SR, ~(C_MASK | V_MASK | Z_MASK | N_MASK));
-
- UML_DSUB(block, I2, I1, I0);
- UML_DROLINS(block, I5, I2, 32, C_MASK);
- UML_XOR(block, I2, I2, I1); // tmp ^ dreg
- UML_XOR(block, I3, I1, I0); // dreg ^ sreg_c
- UML_AND(block, I3, I2, I3); // (tmp ^ dreg) ^ (dreg ^ sreg_c)
- UML_ROLINS(block, I5, I3, 4, V_MASK);
-
- UML_SUB(block, I1, I1, I0);
- UML_TEST(block, I1, ~0);
- UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I2, 0);
- UML_AND(block, I2, I2, I6); // old_z && dreg == 0
- UML_OR(block, I5, I5, I2);
- UML_ROLINS(block, I5, I1, 3, N_MASK);
- UML_ROLINS(block, DRC_SR, I5, 0, (C_MASK | V_MASK | Z_MASK | N_MASK));
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_update_flags_addsubc(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- if (dst_code == PC_REGISTER)
- generate_branch(block, desc->targetpc, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I1, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I4, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1317,83 +1323,19 @@ void hyperstone_device::generate_sub(drcuml_block &block, compiler_state &compil
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- if (src_code == SR_REGISTER)
- UML_AND(block, I0, DRC_SR, C_MASK);
- else
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
-#ifndef PTR64
- UML_DAND(block, I0, I0, 0x00000000ffffffffULL);
-#endif
-
- UML_DSUB(block, I2, I1, I0);
-
- UML_AND(block, DRC_SR, DRC_SR, ~(C_MASK | V_MASK | Z_MASK | N_MASK));
-
- UML_DTEST(block, I2, 0x100000000ULL);
- UML_SETc(block, uml::COND_NZ, I4);
- UML_ROLINS(block, DRC_SR, I4, 0, C_MASK);
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_XOR(block, I4, I1, I2);
- UML_XOR(block, I5, I0, I1);
- UML_AND(block, I6, I4, I5);
- UML_ROLINS(block, DRC_SR, I6, 4, V_MASK);
+ UML_SUB(block, I0, I0, I1);
- UML_SUB(block, I2, I1, I0);
-
- UML_TEST(block, I2, ~0);
- UML_SETc(block, uml::COND_Z, I4);
- UML_ROLINS(block, DRC_SR, I4, Z_SHIFT, Z_MASK);
- UML_ROLINS(block, DRC_SR, I2, 3, N_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I2);
- generate_set_global_register(block, compiler, desc);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- if (dst_code == PC_REGISTER)
- {
- UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I2, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I5, I4, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I5, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1408,76 +1350,21 @@ void hyperstone_device::generate_subs(drcuml_block &block, compiler_state &compi
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- if (src_code == SR_REGISTER)
- UML_AND(block, I0, DRC_SR, C_MASK);
- else
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
-
- UML_DSEXT(block, I0, I0, SIZE_DWORD);
- UML_DSEXT(block, I1, I1, SIZE_DWORD);
- UML_DSUB(block, I2, I1, I0);
+ UML_SUB(block, I0, I0, I1);
- UML_AND(block, DRC_SR, DRC_SR, ~(V_MASK | Z_MASK | N_MASK));
+ generate_update_flags_addsubs(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- UML_XOR(block, I4, I1, I2);
- UML_XOR(block, I5, I0, I1);
- UML_AND(block, I4, I4, I5);
- UML_ROLINS(block, DRC_SR, I4, 4, V_MASK);
-
- UML_TEST(block, I2, ~0);
- UML_SETc(block, uml::COND_Z, I4);
- UML_ROLINS(block, DRC_SR, I4, Z_SHIFT, Z_MASK);
- UML_ROLINS(block, DRC_SR, I2, 3, N_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I2);
- generate_set_global_register(block, compiler, desc);
-
- if (dst_code == PC_REGISTER)
- {
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I2, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I5, I4, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I5, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
- int no_exception = compiler.m_labelnum++;
+ const int no_exception = compiler.m_labelnum++;
UML_TEST(block, DRC_SR, V_MASK);
UML_JMPc(block, uml::COND_Z, no_exception);
UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT), 0, ILC_MASK);
@@ -1497,85 +1384,27 @@ void hyperstone_device::generate_addc(drcuml_block &block, compiler_state &compi
generate_check_delay_pc(block, compiler, desc);
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- if (src_code == SR_REGISTER)
- {
- UML_AND(block, I0, DRC_SR, C_MASK);
- }
- else
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- UML_AND(block, I1, DRC_SR, C_MASK);
-#ifndef PTR64
- UML_DAND(block, I1, I1, 0x00000000ffffffffULL);
-#endif
- UML_DADD(block, I0, I0, I1);
- }
- }
- else
- {
- UML_ADD(block, I1, I3, src_code);
- UML_AND(block, I1, I1, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- UML_AND(block, I1, DRC_SR, C_MASK);
-#ifndef PTR64
- UML_DAND(block, I1, I1, 0x00000000ffffffffULL);
-#endif
- UML_DADD(block, I0, I0, I1);
- }
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL,src_code, uml::I1, uml::I1, uml::I2);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- if (DST_GLOBAL)
+ if (!SRC_GLOBAL || (src_code != SR_REGISTER))
{
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
+ UML_SHR(block, I4, I2, 1); // set up carry in, result unused
+ UML_ADDC(block, I0, I0, I1);
}
else
{
- UML_ADD(block, I3, I3, dst_code);
- UML_AND(block, I3, I3, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I3, SIZE_DWORD, SCALE_x4);
+ UML_ADD(block, I0, I0, I1);
}
- UML_DADD(block, I2, I0, I1);
+ generate_update_flags_addsubc(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- UML_XOR(block, I4, I0, I2);
- UML_XOR(block, I5, I1, I2);
- UML_AND(block, I4, I4, I5);
- UML_AND(block, I4, I4, I2);
- UML_ROLAND(block, I4, I4, 4, V_MASK);
- UML_DROLINS(block, I4, I2, 32, C_MASK);
-
- UML_ADD(block, I0, I0, I1);
- UML_SHR(block, I1, DRC_SR, Z_SHIFT);
- UML_AND(block, I1, I1, 1);
- UML_TEST(block, I0, ~0);
- UML_SETc(block, uml::COND_Z, I2);
- UML_AND(block, I1, I1, I2);
- UML_ROLINS(block, I4, I1, Z_SHIFT, Z_MASK);
- UML_ROLINS(block, I4, I0, 3, N_MASK);
-
- UML_ROLINS(block, DRC_SR, I4, 0, (C_MASK | V_MASK | Z_MASK | N_MASK));
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I0);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I0, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1591,53 +1420,18 @@ void hyperstone_device::generate_neg(drcuml_block &block, compiler_state &compil
const uint32_t dst_code = (op & 0xf0) >> 4;
const uint32_t src_code = op & 0xf;
+ UML_MOV(block, I2, DRC_SR);
if (!SRC_GLOBAL || !DST_GLOBAL)
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_load_src_addsub(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0, uml::I2);
- UML_DSUB(block, I4, 0, I0);
- UML_SUB(block, I2, 0, I0);
+ UML_SUB(block, I0, 0, I0);
- UML_TEST(block, I2, ~0);
- UML_MOVc(block, uml::COND_Z, I6, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I6, 0);
-
- UML_AND(block, I5, DRC_SR, ~(C_MASK | V_MASK | Z_MASK | N_MASK));
- UML_DROLINS(block, I6, I4, 32, C_MASK);
- UML_AND(block, I1, I4, I0);
- UML_ROLINS(block, I6, I1, 4, V_MASK);
- UML_ROLINS(block, I6, I2, 3, N_MASK);
- UML_OR(block, DRC_SR, I5, I6);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I2);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I2, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I1, I3, dst_code);
- UML_AND(block, I4, I1, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I2, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true);
}
@@ -1665,51 +1459,15 @@ void hyperstone_device::generate_and(drcuml_block &block, compiler_state &compil
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_AND(block, I5, I1, I0);
-
- UML_TEST(block, I5, ~0);
+ UML_AND(block, I0, I0, I1);
UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 0);
UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1728,52 +1486,16 @@ void hyperstone_device::generate_andn(drcuml_block &block, compiler_state &compi
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_XOR(block, I2, I0, ~0);
- UML_AND(block, I5, I1, I2);
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_TEST(block, I5, ~0);
+ UML_XOR(block, I1, I1, ~uint32_t(0));
+ UML_AND(block, I0, I0, I1);
UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 0);
UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1792,51 +1514,15 @@ void hyperstone_device::generate_or(drcuml_block &block, compiler_state &compile
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_OR(block, I5, I1, I0);
-
- UML_TEST(block, I5, ~0);
+ UML_OR(block, I0, I0, I1);
UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 0);
UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1855,51 +1541,15 @@ void hyperstone_device::generate_xor(drcuml_block &block, compiler_state &compil
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I1, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_XOR(block, I5, I1, I0);
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I1, uml::I1);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
- UML_TEST(block, I5, ~0);
+ UML_XOR(block, I0, I0, I1);
UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 0);
UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -1918,40 +1568,14 @@ void hyperstone_device::generate_not(drcuml_block &block, compiler_state &compil
if (!SRC_GLOBAL || !DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- if (SRC_GLOBAL)
- UML_LOAD(block, I0, (void *)m_core->global_regs, src_code, SIZE_DWORD, SCALE_x4);
- else
- {
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- }
-
- UML_XOR(block, I5, I0, ~0);
+ generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0);
- UML_TEST(block, I5, ~0);
+ UML_XOR(block, I0, I0, ~uint32_t(0));
UML_MOVc(block, uml::COND_Z, I1, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I1, 0);
UML_ROLINS(block, DRC_SR, I1, 0, Z_MASK);
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, true);
}
@@ -1963,52 +1587,24 @@ void hyperstone_device::generate_cmpi(drcuml_block &block, compiler_state &compi
const uint16_t op = desc->opptr.w[0];
const uint32_t dst_code = (op & 0xf0) >> 4;
+ uint32_t src;
if (IMM_LONG)
- {
- generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
- }
+ src = generate_get_immediate_s(block, compiler, desc);
else
- {
- UML_MOV(block, I1, op & 0xf);
- }
+ src = op & 0x0f;
generate_check_delay_pc(block, compiler, desc);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_AND(block, DRC_SR, DRC_SR, ~(V_MASK | Z_MASK | N_MASK | C_MASK));
+ UML_MOV(block, I2, DRC_SR);
+ if (!DST_GLOBAL)
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- UML_DSUB(block, I0, I2, I1);
-
- int no_v;
- UML_XOR(block, I0, I0, I2);
- UML_XOR(block, I3, I1, I2);
- UML_AND(block, I0, I0, I3);
- UML_TEST(block, I0, 0x80000000);
- UML_JMPc(block, uml::COND_Z, no_v = compiler.m_labelnum++);
- UML_OR(block, DRC_SR, DRC_SR, V_MASK);
- UML_LABEL(block, no_v);
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I0);
- int no_n;
- UML_MOV(block, I3, 0);
- UML_CMP(block, I2, I1);
- UML_MOVc(block, uml::COND_E, I3, Z_MASK);
- UML_MOVc(block, uml::COND_B, I3, C_MASK);
- UML_JMPc(block, uml::COND_GE, no_n = compiler.m_labelnum++);
- UML_OR(block, I3, I3, N_MASK);
- UML_LABEL(block, no_n);
+ UML_SUB(block, I0, I0, src);
- UML_OR(block, DRC_SR, DRC_SR, I3);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
}
@@ -2019,20 +1615,21 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
const uint16_t op = desc->opptr.w[0];
const uint32_t dst_code = (op & 0xf0) >> 4;
- const uint32_t src_code = op & 0xf;
+ uint32_t src;
if (IMM_LONG)
- generate_decode_immediate_s(block, compiler, desc);
+ src = generate_get_immediate_s(block, compiler, desc);
else
- UML_MOV(block, I1, src_code);
+ src = op & 0x0f;
generate_check_delay_pc(block, compiler, desc);
- int done, no_exception;
+ int done;
if (DST_GLOBAL)
{
+ const int no_exception = compiler.m_labelnum++;
UML_TEST(block, DRC_SR, H_MASK);
- UML_JMPc(block, uml::COND_Z, no_exception = compiler.m_labelnum++);
+ UML_JMPc(block, uml::COND_Z, no_exception);
UML_TEST(block, DRC_SR, S_MASK);
UML_JMPc(block, uml::COND_NZ, no_exception);
UML_EXH(block, *m_exception[EXCEPTION_PRIVILEGE_ERROR], 0);
@@ -2042,17 +1639,8 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
UML_AND(block, DRC_SR, DRC_SR, ~(Z_MASK | N_MASK));
- int no_z;
- UML_TEST(block, I1, ~0);
- UML_JMPc(block, uml::COND_NZ, no_z = compiler.m_labelnum++);
- UML_OR(block, DRC_SR, DRC_SR, Z_MASK);
- UML_LABEL(block, no_z);
-
- int no_n;
- UML_TEST(block, I1, 0x80000000);
- UML_JMPc(block, uml::COND_Z, no_n = compiler.m_labelnum++);
- UML_OR(block, DRC_SR, DRC_SR, N_MASK);
- UML_LABEL(block, no_n);
+ if (src)
+ UML_OR(block, DRC_SR, DRC_SR, (src & 0x80000000) ? (Z_MASK | N_MASK) : Z_MASK);
#if MISSIONCRAFT_FLAGS
UML_AND(block, DRC_SR, DRC_SR, ~V_MASK);
@@ -2060,17 +1648,21 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
if (DST_GLOBAL)
{
+ const int highglobal = compiler.m_labelnum++;
+
UML_TEST(block, DRC_SR, H_MASK);
- UML_MOVc(block, uml::COND_NZ, I4, dst_code + 16);
- UML_MOVc(block, uml::COND_Z, I4, dst_code);
- UML_AND(block, DRC_SR, DRC_SR, ~H_MASK);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ 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);
+ generate_branch(block, desc->targetpc, desc);
+ }
+ UML_JMP(block, done);
- UML_TEST(block, op, 0xf0);
- UML_JMPc(block, uml::COND_NZ, done);
- UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
- generate_branch(block, desc->targetpc, 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);
}
@@ -2080,7 +1672,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi
UML_ROLAND(block, I2, DRC_SR, 7, 0x7f);
UML_ADD(block, I0, I2, dst_code);
UML_AND(block, I0, I0, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I0, I1, SIZE_DWORD, SCALE_x4);
+ UML_STORE(block, (void *)m_core->local_regs, I0, src, SIZE_DWORD, SCALE_x4);
}
}
@@ -2092,78 +1684,38 @@ void hyperstone_device::generate_addi(drcuml_block &block, compiler_state &compi
const uint16_t op = desc->opptr.w[0];
const uint32_t dst_code = (op & 0xf0) >> 4;
- const uint32_t src_code = op & 0xf;
+ uint32_t src;
if (IMM_LONG)
- {
- generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
- }
+ src = generate_get_immediate_s(block, compiler, desc);
else
- {
- UML_MOV(block, I1, src_code);
- }
+ src = op & 0x0f;
generate_check_delay_pc(block, compiler, desc);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I0, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ROLAND(block, I2, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I2, dst_code);
- UML_AND(block, I2, I2, 0x3f);
- UML_LOAD(block, I0, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4);
- }
+ UML_MOV(block, I2, DRC_SR);
+ if (!DST_GLOBAL)
+ UML_ROLAND(block, I3, I2, 7, 0x7f);
- if (!(op & 0x10f))
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
+
+ const bool roundeven = !(op & 0x10f);
+ uml::parameter srcp = roundeven ? uml::I1 : src;
+ if (roundeven)
{
- UML_ROLAND(block, I3, DRC_SR, 32-Z_SHIFT, 1);
- UML_XOR(block, I3, I3, 1);
- UML_AND(block, I4, I0, 1);
- UML_OR(block, I3, I3, I4);
- UML_AND(block, I1, DRC_SR, I3);
+ UML_MOV(block, I4, DRC_SR);
+ UML_AND(block, I1, I0, 1); // Rd(0)
+ UML_AND(block, I1, I1, I4); // & C
+ UML_TEST(block, I4, Z_MASK);
+ UML_MOVc(block, uml::COND_NZ, I1, 0); // & ~Z
}
- UML_DADD(block, I3, I0, I1);
-
- UML_DROLAND(block, I6, I3, 32, C_MASK);
+ UML_ADD(block, I0, I0, srcp);
- UML_XOR(block, I4, I0, I3);
- UML_XOR(block, I5, I1, I3);
- UML_AND(block, I4, I4, I5);
- UML_ROLINS(block, I6, I4, 4, V_MASK);
-
- UML_TEST(block, I3, ~0);
- UML_SETc(block, uml::COND_Z, I4);
- UML_ROLINS(block, I6, I4, Z_SHIFT, Z_MASK);
- UML_ROLINS(block, I6, I3, 3, N_MASK);
- UML_ROLINS(block, DRC_SR, I6, 0, (V_MASK | N_MASK | Z_MASK | C_MASK));
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I3);
- generate_set_global_register(block, compiler, desc);
+ generate_update_flags_addsub(block, compiler, uml::I2);
+ UML_MOV(block, DRC_SR, I2);
- if (dst_code == PC_REGISTER)
- {
- UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I3, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I2, I3, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false);
}
@@ -2187,21 +1739,15 @@ void hyperstone_device::generate_cmpbi(drcuml_block &block, compiler_state &comp
if (!IMM_LONG)
generate_check_delay_pc(block, compiler, desc);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
+ if (!DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I5, I4, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I5, SIZE_DWORD, SCALE_x4);
- }
+
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
const uint32_t n = ((op & 0x100) >> 4) | (op & 0x0f);
if (n)
{
+ uint32_t src;
if (n == 31)
{
if (IMM_LONG)
@@ -2209,25 +1755,21 @@ void hyperstone_device::generate_cmpbi(drcuml_block &block, compiler_state &comp
generate_ignore_immediate_s(block, desc);
generate_check_delay_pc(block, compiler, desc);
}
- UML_MOV(block, I1, 0x7fffffff);
+ src = 0x7fffffff;
+ }
+ else if (IMM_LONG)
+ {
+ src = generate_get_immediate_s(block, compiler, desc);
+ generate_check_delay_pc(block, compiler, desc);
}
else
{
- if (IMM_LONG)
- {
- generate_decode_immediate_s(block, compiler, desc);
- generate_check_delay_pc(block, compiler, desc);
- }
- else
- {
- UML_MOV(block, I1, op & 0xf);
- }
+ src = op & 0xf;
}
- UML_AND(block, DRC_SR, DRC_SR, ~Z_MASK);
- UML_TEST(block, I2, I1);
- UML_SETc(block, uml::COND_Z, I3);
- UML_ROLINS(block, DRC_SR, I3, Z_SHIFT, Z_MASK);
+ UML_TEST(block, I0, src);
+ UML_SETc(block, uml::COND_Z, I1);
+ UML_ROLINS(block, DRC_SR, I1, Z_SHIFT, Z_MASK);
}
else
{
@@ -2239,13 +1781,13 @@ void hyperstone_device::generate_cmpbi(drcuml_block &block, compiler_state &comp
const int or_mask = compiler.m_labelnum++;
const int done = compiler.m_labelnum++;
- UML_TEST(block, I2, 0xff000000);
+ UML_TEST(block, I0, 0xff000000);
UML_JMPc(block, uml::COND_Z, or_mask);
- UML_TEST(block, I2, 0x00ff0000);
+ UML_TEST(block, I0, 0x00ff0000);
UML_JMPc(block, uml::COND_Z, or_mask);
- UML_TEST(block, I2, 0x0000ff00);
+ UML_TEST(block, I0, 0x0000ff00);
UML_JMPc(block, uml::COND_Z, or_mask);
- UML_TEST(block, I2, 0x000000ff);
+ UML_TEST(block, I0, 0x000000ff);
UML_JMPc(block, uml::COND_Z, or_mask);
UML_AND(block, DRC_SR, DRC_SR, ~Z_MASK);
UML_JMP(block, done);
@@ -2264,59 +1806,22 @@ void hyperstone_device::generate_andni(drcuml_block &block, compiler_state &comp
UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
const uint16_t op = desc->opptr.w[0];
- const uint32_t dst_code = (op & 0xf0) >> 4;
+ uint32_t src;
if (DRC_N_OP_MASK == 0x10f)
- UML_MOV(block, I1, 0x7fffffff);
+ src = 0x7fffffff;
else if (IMM_LONG)
- generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
+ src = generate_get_immediate_s(block, compiler, desc);
else
- UML_MOV(block, I1, op & 0xf);
-
- generate_check_delay_pc(block, compiler, desc);
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_XOR(block, I1, I1, ~0);
- UML_AND(block, I5, I2, I1);
-
- UML_TEST(block, I5, ~0);
- UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I2, 0);
- UML_ROLINS(block, DRC_SR, I2, 0, Z_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- if (dst_code == PC_REGISTER)
- {
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I4, I4, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ src = op & 0x0f;
+ src = ~src;
+
+ generate_logic_op<DST_GLOBAL>(
+ block,
+ compiler,
+ desc,
+ (op & 0xf0) >> 4,
+ [&block, src] () { UML_AND(block, I0, I0, src); });
}
@@ -2326,60 +1831,19 @@ void hyperstone_device::generate_ori(drcuml_block &block, compiler_state &compil
UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
const uint16_t op = desc->opptr.w[0];
- const uint32_t dst_code = (op & 0xf0) >> 4;
+ uint32_t src;
if (IMM_LONG)
- {
- generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
- }
- else
- {
- UML_MOV(block, I1, op & 0xf);
- }
-
- generate_check_delay_pc(block, compiler, desc);
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
+ src = generate_get_immediate_s(block, compiler, desc);
else
- {
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_OR(block, I5, I2, I1);
-
- UML_TEST(block, I5, ~0);
- UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I2, 0);
- UML_ROLINS(block, DRC_SR, I2, 0, Z_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- if (dst_code == PC_REGISTER)
- {
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I4, I4, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ src = op & 0x0f;
+
+ generate_logic_op<DST_GLOBAL>(
+ block,
+ compiler,
+ desc,
+ (op & 0xf0) >> 4,
+ [&block, src] () { UML_OR(block, I0, I0, src); });
}
@@ -2389,60 +1853,19 @@ void hyperstone_device::generate_xori(drcuml_block &block, compiler_state &compi
UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
const uint16_t op = desc->opptr.w[0];
- const uint32_t dst_code = (op & 0xf0) >> 4;
+ uint32_t src;
if (IMM_LONG)
- {
- generate_decode_immediate_s(block, compiler, desc); // I1 <-- imm32
- }
+ src = generate_get_immediate_s(block, compiler, desc);
else
- {
- UML_MOV(block, I1, op & 0xf);
- }
-
- generate_check_delay_pc(block, compiler, desc);
-
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I2, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_LOAD(block, I2, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4);
- }
-
- UML_XOR(block, I5, I2, I1);
-
- UML_TEST(block, I5, ~0);
- UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I2, 0);
- UML_ROLINS(block, DRC_SR, I2, 0, Z_MASK);
-
- if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- if (dst_code == PC_REGISTER)
- {
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
- else
- {
- UML_ADD(block, I4, I3, dst_code);
- UML_AND(block, I4, I4, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
- }
+ src = op & 0x0f;
+
+ generate_logic_op<DST_GLOBAL>(
+ block,
+ compiler,
+ desc,
+ (op & 0xf0) >> 4,
+ [&block, src] () { UML_XOR(block, I0, I0, src); });
}
@@ -2567,16 +1990,16 @@ void hyperstone_device::generate_shr(drcuml_block &block, compiler_state &compil
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I4, I2, 0x3f);
+ UML_ADD(block, I4, I3, dst_code);
+ UML_AND(block, I4, I4, 0x3f);
UML_LOAD(block, I0, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4); // I0 = dreg
- UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I1, I2, 0x3f);
- UML_LOAD(block, I5, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4);
- UML_AND(block, I1, I5, 0x1f); // I1 = sreg & 0x1f
+ UML_ADD(block, I3, I3, src_code);
+ UML_AND(block, I3, I3, 0x3f);
+ UML_LOAD(block, I1, (void *)m_core->local_regs, I3, SIZE_DWORD, SCALE_x4);
+ UML_AND(block, I1, I1, 0x1f); // I1 = sreg & 0x1f
- UML_AND(block, I6, DRC_SR, ~(C_MASK | Z_MASK | N_MASK));
+ UML_AND(block, I3, DRC_SR, ~(C_MASK | Z_MASK | N_MASK));
int no_shift = compiler.m_labelnum++;
int no_carry = compiler.m_labelnum++;
@@ -2586,18 +2009,18 @@ void hyperstone_device::generate_shr(drcuml_block &block, compiler_state &compil
UML_SHL(block, I2, 1, I2);
UML_TEST(block, I0, I2);
UML_JMPc(block, uml::COND_Z, no_carry);
- UML_OR(block, I6, I6, C_MASK);
+ UML_OR(block, I3, I3, C_MASK);
UML_LABEL(block, no_carry);
UML_SHR(block, I0, I0, I1);
UML_LABEL(block, no_shift);
- UML_TEST(block, I0, ~0);
- UML_MOVc(block, uml::COND_Z, I5, Z_MASK);
- UML_MOVc(block, uml::COND_NZ, I5, 0);
- UML_ROLINS(block, I5, I0, 3, N_MASK);
+ UML_TEST(block, I0, ~uint32_t(0));
+ UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
+ UML_MOVc(block, uml::COND_NZ, I2, 0);
+ UML_ROLINS(block, I2, I0, 3, N_MASK);
- UML_OR(block, DRC_SR, I5, I6);
+ UML_OR(block, DRC_SR, I2, I3);
UML_STORE(block, (void *)m_core->local_regs, I4, I0, SIZE_DWORD, SCALE_x4);
}
@@ -2613,47 +2036,26 @@ void hyperstone_device::generate_shri(drcuml_block &block, compiler_state &compi
generate_check_delay_pc(block, compiler, desc);
- if (DST_GLOBAL)
- {
- UML_LOAD(block, I4, (void *)m_core->global_regs, dst_code, SIZE_DWORD, SCALE_x4);
- }
- else
- {
+ if (!DST_GLOBAL)
UML_ROLAND(block, I3, DRC_SR, 7, 0x7f);
- UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I6, I2, 0x3f);
- UML_LOAD(block, I4, (void *)m_core->local_regs, I6, SIZE_DWORD, SCALE_x4);
- }
+
+ generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I3);
UML_AND(block, I1, DRC_SR, ~(C_MASK | Z_MASK | N_MASK));
const uint32_t n = HI_N ? (0x10 | (op & 0xf)) : (op & 0xf);
if (HI_N || n)
- UML_ROLINS(block, I1, I4, 32 - (n - 1), 1);
-
- UML_SHR(block, I5, I4, n);
+ UML_ROLINS(block, I1, I0, 32 - (n - 1), 1);
- UML_TEST(block, I5, ~0);
+ UML_SHR(block, I0, I0, n);
UML_MOVc(block, uml::COND_Z, I2, Z_MASK);
UML_MOVc(block, uml::COND_NZ, I2, 0);
- UML_ROLINS(block, I2, I5, 3, N_MASK);
+ UML_ROLINS(block, I2, I0, 3, N_MASK);
UML_OR(block, DRC_SR, I1, I2);
if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
+ generate_set_global_register_low(block, compiler, dst_code, uml::I0);
else
- {
- UML_STORE(block, (void *)m_core->local_regs, I6, I5, SIZE_DWORD, SCALE_x4);
- }
+ UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4);
}
@@ -2848,22 +2250,9 @@ void hyperstone_device::generate_sari(drcuml_block &block, compiler_state &compi
UML_ROLINS(block, DRC_SR, I2, 0, (C_MASK | Z_MASK | N_MASK));
if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- UML_MOV(block, I5, I0);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I0, SIZE_DWORD, SCALE_x4);
- }
- }
+ generate_set_global_register_low(block, compiler, dst_code, uml::I0);
else
- {
UML_STORE(block, (void *)m_core->local_regs, I1, I0, SIZE_DWORD, SCALE_x4);
- }
}
@@ -3131,21 +2520,9 @@ void hyperstone_device::generate_shli(drcuml_block &block, compiler_state &compi
UML_OR(block, DRC_SR, I1, I2);
if (DST_GLOBAL)
- {
- if (dst_code < 2)
- {
- UML_MOV(block, I4, dst_code);
- generate_set_global_register(block, compiler, desc);
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, dst_code, I5, SIZE_DWORD, SCALE_x4);
- }
- }
+ generate_set_global_register_low(block, compiler, dst_code, uml::I5);
else
- {
UML_STORE(block, (void *)m_core->local_regs, I6, I5, SIZE_DWORD, SCALE_x4);
- }
}
@@ -3289,12 +2666,11 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
UML_MOV(block, I7, mem(&m_core->clock_cycles_1));
UML_ADD(block, I0, I4, extra_s);
UML_CALLH(block, *m_mem_read8);
- UML_SEXT(block, I5, I1, SIZE_BYTE);
+ UML_SEXT(block, I1, I1, SIZE_BYTE);
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == PC_REGISTER)
generate_branch(block, desc->targetpc, desc);
}
@@ -3302,7 +2678,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
{
UML_ADD(block, I2, I3, src_code);
UML_AND(block, I2, I2, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I2, I5, SIZE_DWORD, SCALE_x4);
+ UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4);
}
break;
@@ -3313,9 +2689,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == PC_REGISTER)
generate_branch(block, desc->targetpc, desc);
}
@@ -3332,17 +2706,12 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
UML_ADD(block, I0, I4, extra_s & ~1);
UML_AND(block, I0, I0, ~1);
UML_CALLH(block, *m_mem_read16);
+ if (extra_s & 1) // LDHS.A
+ UML_SEXT(block, I1, I1, SIZE_WORD);
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- if (extra_s & 1) // LDHS.A
- UML_SEXT(block, I5, I1, SIZE_WORD);
- else // LDHU.A
- UML_MOV(block, I5, I1);
-
- generate_set_global_register(block, compiler, desc);
-
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == 0)
generate_branch(block, desc->targetpc, desc);
}
@@ -3350,15 +2719,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
{
UML_ADD(block, I2, I3, src_code);
UML_AND(block, I2, I2, 0x3f);
- if (extra_s & 1)
- {
- UML_SEXT(block, I5, I1, SIZE_WORD);
- UML_STORE(block, (void *)m_core->local_regs, I2, I5, SIZE_DWORD, SCALE_x4);
- }
- else
- {
- UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4);
- }
+ UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4);
}
break;
@@ -3376,9 +2737,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I5, I1);
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == PC_REGISTER)
generate_branch(block, desc->targetpc, desc);
}
@@ -3395,9 +2754,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I5, I1);
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == PC_REGISTER)
generate_branch(block, desc->targetpc, desc);
}
@@ -3431,9 +2788,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I5, I1);
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == 0)
generate_branch(block, desc->targetpc, desc);
}
@@ -3452,9 +2807,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I5, I1);
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
if (src_code == PC_REGISTER)
generate_branch(block, desc->targetpc, desc);
}
@@ -3555,34 +2908,30 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp
{
UML_MOV(block, I0, I6);
UML_CALLH(block, *m_mem_read8);
- UML_SEXT(block, I5, I1, SIZE_BYTE);
+ UML_SEXT(block, I1, I1, SIZE_BYTE);
}
else if (sub_type == 2)
{
UML_AND(block, I0, I6, ~1);
UML_CALLH(block, *m_mem_read16);
if (extra_s & 1)
- UML_SEXT(block, I5, I1, SIZE_WORD);
- else
- UML_MOV(block, I5, I1);
+ UML_SEXT(block, I1, I1, SIZE_WORD);
}
else
{
UML_MOV(block, I0, I6);
UML_CALLH(block, *m_mem_read8);
- UML_MOV(block, I5, I1);
}
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
}
else
{
UML_ADD(block, I2, I3, src_code);
- UML_AND(block, I4, I2, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I4, I5, SIZE_DWORD, SCALE_x4);
+ UML_AND(block, I2, I2, 0x3f);
+ UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4);
}
if (DST_GLOBAL != SRC_GLOBAL || src_code != dst_code)
@@ -3599,8 +2948,8 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp
else
{
UML_ADD(block, I2, I3, dst_code);
- UML_AND(block, I5, I2, 0x3f);
- UML_STORE(block, (void *)m_core->local_regs, I5, I4, SIZE_DWORD, SCALE_x4);
+ UML_AND(block, I2, I2, 0x3f);
+ UML_STORE(block, (void *)m_core->local_regs, I2, I4, SIZE_DWORD, SCALE_x4);
}
}
break;
@@ -3616,9 +2965,7 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
}
else
{
@@ -3652,14 +2999,12 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
UML_ADD(block, I0, I0, 4);
UML_CALLH(block, *m_mem_read32);
- UML_MOV(block, I4, src_code);
+ UML_MOV(block, I4, srcf_code);
UML_MOV(block, I5, I1);
generate_set_global_register(block, compiler, desc);
}
@@ -3720,9 +3065,7 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
}
else
{
@@ -4351,20 +3694,9 @@ void hyperstone_device::generate_ldwr(drcuml_block &block, compiler_state &compi
if (SRC_GLOBAL)
{
- if (src_code < 2)
- {
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
- if (src_code == PC_REGISTER)
- {
- generate_branch(block, desc->targetpc, desc);
- }
- }
- else
- {
- UML_STORE(block, (void *)m_core->global_regs, src_code, I1, SIZE_DWORD, SCALE_x4);
- }
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
+ if (src_code == PC_REGISTER)
+ generate_branch(block, desc->targetpc, desc);
}
else
{
@@ -4396,9 +3728,7 @@ void hyperstone_device::generate_lddr(drcuml_block &block, compiler_state &compi
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
UML_ADD(block, I0, I0, 4);
UML_CALLH(block, *m_mem_read32);
@@ -4446,9 +3776,7 @@ void hyperstone_device::generate_ldwp(drcuml_block &block, compiler_state &compi
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I1);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I1);
UML_ROLAND(block, I0, DRC_SR, 7, 0x7f);
UML_ADD(block, I1, I0, dst_code);
@@ -4501,9 +3829,7 @@ void hyperstone_device::generate_lddp(drcuml_block &block, compiler_state &compi
if (SRC_GLOBAL)
{
- UML_MOV(block, I4, src_code);
- UML_MOV(block, I5, I2);
- generate_set_global_register(block, compiler, desc);
+ generate_set_global_register_low(block, compiler, src_code, uml::I2);
UML_MOV(block, I4, src_code + 1);
UML_MOV(block, I5, I1);
generate_set_global_register(block, compiler, desc);
@@ -4755,10 +4081,11 @@ void hyperstone_device::generate_br(drcuml_block &block, compiler_state &compile
{
UML_MOV(block, I7, mem(&m_core->clock_cycles_2));
- generate_decode_pcrel(block, desc);
+ const uint32_t target = generate_get_pcrel(block, desc);
+
generate_check_delay_pc(block, compiler, desc);
- UML_ADD(block, DRC_PC, DRC_PC, I1);
+ UML_ADD(block, DRC_PC, DRC_PC, target);
UML_AND(block, DRC_SR, DRC_SR, ~M_MASK);
generate_branch(block, desc->targetpc, desc);
@@ -4795,11 +4122,12 @@ void hyperstone_device::generate_dbr(drcuml_block &block, compiler_state &compil
{
UML_MOV(block, I7, mem(&m_core->clock_cycles_2));
- generate_decode_pcrel(block, desc);
+ const uint32_t target = generate_get_pcrel(block, desc);
+
generate_check_delay_pc(block, compiler, desc);
UML_MOV(block, mem(&m_core->delay_slot), 1);
- UML_ADD(block, mem(&m_core->delay_pc), DRC_PC, I1);
+ UML_ADD(block, mem(&m_core->delay_pc), DRC_PC, target);
UML_MOV(block, mem(&m_core->intblock), 3);
}