From 17cd39bb4c52325f00c030f850d85c865fb2b8df Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Fri, 21 Mar 2025 17:56:15 +1100 Subject: [PATCH] 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. --- src/devices/cpu/drcbex64.cpp | 408 ++--- src/devices/cpu/drcbex86.cpp | 18 +- src/devices/cpu/e132xs/e132xs.h | 17 +- src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 1810 +++++++--------------- 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 ®, int32_t &offset); - void smart_call_r64(asmjit::x86::Assembler &a, x86code *target, asmjit::x86::Gp const ®); - void smart_call_m64(asmjit::x86::Assembler &a, x86code **target); + void smart_call_r64(asmjit::x86::Assembler &a, x86code *target, asmjit::x86::Gp const ®) 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 ¶m, std::function 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 ¶m, 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 ¶m, u8 update_flags); // parameter helpers void mov_reg_param(asmjit::x86::Assembler &a, asmjit::x86::Gp const ®, be_parameter const ¶m, 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 ®, be_parameter const ¶m); - void mov_r64_imm(asmjit::x86::Assembler &a, asmjit::x86::Gp const ®, uint64_t const imm); + void mov_r64_imm(asmjit::x86::Assembler &a, asmjit::x86::Gp const ®, uint64_t const imm) const; // floating-point helpers void movss_r128_p32(asmjit::x86::Assembler &a, asmjit::x86::Xmm const ®, be_parameter const ¶m); @@ -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 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 ®) +inline void drcbe_x64::smart_call_r64(Assembler &a, x86code *target, Gp const ®) 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 ¶m, bool update_flags) +void drcbe_x64::shift_op_param(Assembler &a, Inst::Id const opcode, size_t opsize, Operand const &dst, be_parameter const ¶m, 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 ®, be_parameter const &p a.movsxd(reg, Gpd(param.ireg())); // movsxd reg,param } -void drcbe_x64::mov_r64_imm(Assembler &a, Gp const ®, uint64_t const imm) +void drcbe_x64::mov_r64_imm(Assembler &a, Gp const ®, 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(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(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 ®, 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 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 void generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, T &&body); + template void generate_chk(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); template void generate_movd(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); template 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 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 +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 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); - } + generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0); - UML_AND(block, I1, I1, I2); + 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); - 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); - - 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); - } + generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0); -#ifndef PTR64 - UML_DAND(block, I1, I1, 0x00000000ffffffffULL); -#endif + UML_ADD(block, I0, I0, src); - UML_DADD(block, I5, I1, I2); + generate_update_flags_addsub(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - 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); - - 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); + 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, I1, I2, src_code); - UML_AND(block, I1, I1, 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::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, I2, dst_code); - UML_AND(block, I2, I2, 0x3f); - UML_LOAD(block, I1, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4); - } + UML_SUB(block, I0, I0, I1); -#ifndef PTR64 - UML_DAND(block, I0, I0, 0x00000000ffffffffULL); -#endif - - UML_DSUB(block, I2, I1, I0); // tmp - - 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_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); - } + 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, 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_ADD(block, I2, I0, I1); + generate_update_flags_addsub(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - UML_SETc(block, uml::COND_C, I6); - - 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)); - - 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) - { - 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 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(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); + 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, I1, I2, src_code); - UML_AND(block, I1, I1, 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, I2, dst_code); - UML_AND(block, I2, I2, 0x3f); - UML_LOAD(block, I1, (void *)m_core->local_regs, I2, SIZE_DWORD, SCALE_x4); - } - - 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_GLOBAL || (src_code != SR_REGISTER)) { - 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); - } + UML_SHR(block, I4, I2, 1); // set up carry in, result unused + UML_SUBB(block, I0, I0, I1); } 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); + UML_SUB(block, I0, I0, I1); } - 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); - } + generate_update_flags_addsubc(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - 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); - - 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); - } + 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, I4, I2, 0x3f); - UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4); - } + UML_SUB(block, I0, I0, I1); -#ifndef PTR64 - UML_DAND(block, I0, I0, 0x00000000ffffffffULL); -#endif + generate_update_flags_addsub(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - 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); - - 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, 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); - - 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_SUB(block, I0, I0, I1); - UML_DSEXT(block, I0, I0, SIZE_DWORD); - UML_DSEXT(block, I1, I1, SIZE_DWORD); - UML_DSUB(block, I2, I1, I0); + generate_update_flags_addsubs(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - UML_AND(block, DRC_SR, DRC_SR, ~(V_MASK | Z_MASK | N_MASK)); + generate_set_dst(block, compiler, desc, DST_GLOBAL, dst_code, uml::I0, uml::I3, false); - 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); - } - - 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) + 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 || (src_code != SR_REGISTER)) { - 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); - } + UML_SHR(block, I4, I2, 1); // set up carry in, result unused + UML_ADDC(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); + UML_ADD(block, I0, I0, I1); } - 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); - } + generate_update_flags_addsubc(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - UML_DADD(block, I2, I0, I1); - - 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); + generate_update_flags_addsub(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - 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); - - 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); - } + 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_XOR(block, I2, I0, ~0); - UML_AND(block, I5, I1, I2); - - 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); - } + 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_XOR(block, I5, I1, I0); - - 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); - } + generate_load_operand(block, compiler, SRC_GLOBAL, src_code, uml::I0, uml::I0); - UML_XOR(block, I5, I0, ~0); - - 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_MOV(block, I2, DRC_SR); + if (!DST_GLOBAL) + UML_ROLAND(block, I3, I2, 7, 0x7f); - UML_AND(block, DRC_SR, DRC_SR, ~(V_MASK | Z_MASK | N_MASK | C_MASK)); + generate_load_operand(block, compiler, DST_GLOBAL, dst_code, uml::I0, uml::I0); - UML_DSUB(block, I0, I2, I1); + UML_SUB(block, I0, I0, src); - 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); - - 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_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) { - 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); + const int highglobal = compiler.m_labelnum++; - 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_TEST(block, DRC_SR, H_MASK); + UML_JMPc(block, uml::COND_NZ, highglobal); + generate_set_global_register_low(block, compiler, dst_code, src); + if (dst_code == PC_REGISTER) + { + UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); + generate_branch(block, desc->targetpc, desc); + } + UML_JMP(block, done); + + UML_LABEL(block, highglobal); + UML_AND(block, DRC_SR, DRC_SR, ~H_MASK); + generate_set_global_register_high(block, compiler, dst_code, 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_MOV(block, I2, DRC_SR); + if (!DST_GLOBAL) + UML_ROLAND(block, I3, I2, 7, 0x7f); + + 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_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, 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 } - if (!(op & 0x10f)) - { - 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_ADD(block, I0, I0, srcp); - UML_DADD(block, I3, I0, I1); + generate_update_flags_addsub(block, compiler, uml::I2); + UML_MOV(block, DRC_SR, I2); - UML_DROLAND(block, I6, I3, 32, C_MASK); - - 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); - - 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); + src = op & 0x0f; + src = ~src; - 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); - } + generate_logic_op( + 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 - } + 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_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); - } + generate_logic_op( + 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); - } + 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_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); - } + generate_logic_op( + 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_ROLINS(block, I1, I0, 32 - (n - 1), 1); - UML_SHR(block, I5, I4, n); - - 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); }