diff options
Diffstat (limited to 'src/devices/cpu/drcbec.cpp')
-rw-r--r-- | src/devices/cpu/drcbec.cpp | 998 |
1 files changed, 594 insertions, 404 deletions
diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp index def49d3b04c..5ec9a0b94e4 100644 --- a/src/devices/cpu/drcbec.cpp +++ b/src/devices/cpu/drcbec.cpp @@ -9,11 +9,19 @@ ***************************************************************************/ #include "emu.h" -#include "debugger.h" #include "drcbec.h" +#include "drcbeut.h" + +#include "debug/debugcpu.h" + #include <cmath> + +namespace drc { + +namespace { + using namespace uml; @@ -22,22 +30,22 @@ using namespace uml; //************************************************************************** // define a bit to match each possible condition, starting at bit 12 -#define ZBIT (0x1000 << (COND_Z & 15)) -#define NZBIT (0x1000 << (COND_NZ & 15)) -#define SBIT (0x1000 << (COND_S & 15)) -#define NSBIT (0x1000 << (COND_NS & 15)) -#define CBIT (0x1000 << (COND_C & 15)) -#define NCBIT (0x1000 << (COND_NC & 15)) -#define VBIT (0x1000 << (COND_V & 15)) -#define NVBIT (0x1000 << (COND_NV & 15)) -#define UBIT (0x1000 << (COND_U & 15)) -#define NUBIT (0x1000 << (COND_NU & 15)) -#define ABIT (0x1000 << (COND_A & 15)) -#define BEBIT (0x1000 << (COND_BE & 15)) -#define GBIT (0x1000 << (COND_G & 15)) -#define GEBIT (0x1000 << (COND_GE & 15)) -#define LBIT (0x1000 << (COND_L & 15)) -#define LEBIT (0x1000 << (COND_LE & 15)) +constexpr uint32_t ZBIT = 0x1000 << (COND_Z & 15); +constexpr uint32_t NZBIT = 0x1000 << (COND_NZ & 15); +constexpr uint32_t SBIT = 0x1000 << (COND_S & 15); +constexpr uint32_t NSBIT = 0x1000 << (COND_NS & 15); +constexpr uint32_t CBIT = 0x1000 << (COND_C & 15); +constexpr uint32_t NCBIT = 0x1000 << (COND_NC & 15); +constexpr uint32_t VBIT = 0x1000 << (COND_V & 15); +constexpr uint32_t NVBIT = 0x1000 << (COND_NV & 15); +constexpr uint32_t UBIT = 0x1000 << (COND_U & 15); +constexpr uint32_t NUBIT = 0x1000 << (COND_NU & 15); +constexpr uint32_t ABIT = 0x1000 << (COND_A & 15); +constexpr uint32_t BEBIT = 0x1000 << (COND_BE & 15); +constexpr uint32_t GBIT = 0x1000 << (COND_G & 15); +constexpr uint32_t GEBIT = 0x1000 << (COND_GE & 15); +constexpr uint32_t LBIT = 0x1000 << (COND_L & 15); +constexpr uint32_t LEBIT = 0x1000 << (COND_LE & 15); // internal opcodes @@ -163,6 +171,11 @@ enum #define PARAM2 (*inst[2].puint32) #define PARAM3 (*inst[3].puint32) +#define SPARAM0 (*inst[0].pint32) +#define SPARAM1 (*inst[1].pint32) +#define SPARAM2 (*inst[2].pint32) +#define SPARAM3 (*inst[3].pint32) + #define DPARAM0 (*inst[0].puint64) #define DPARAM1 (*inst[1].puint64) #define DPARAM2 (*inst[2].puint64) @@ -178,9 +191,15 @@ enum #define FDPARAM2 (*inst[2].pdouble) #define FDPARAM3 (*inst[3].pdouble) +#define SPACEPARAM0 (*inst[0].space) +#define SPACEPARAM1 (*inst[1].space) +#define SPACEPARAM2 (*inst[2].space) +#define SPACEPARAM3 (*inst[3].space) + // compute C and V flags for 32-bit add/subtract #define FLAGS32_C_ADD(a,b) ((uint32_t)~(a) < (uint32_t)(b)) #define FLAGS32_C_SUB(a,b) ((uint32_t)(b) > (uint32_t)(a)) +#define FLAGS32_C_SUBC(a,b,c) (((uint32_t)(c) != 0 && ((uint32_t)(b) + (uint32_t)(c)) == 0) || (uint32_t)(b) + (uint32_t)(c) > (uint32_t)(a)) #define FLAGS32_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V) #define FLAGS32_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V) @@ -188,10 +207,12 @@ enum #define FLAGS32_NZ(v) ((((v) >> 28) & FLAG_S) | (((uint32_t)(v) == 0) << 2)) #define FLAGS32_NZCV_ADD(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_ADD(a,b) | FLAGS32_V_ADD(r,a,b)) #define FLAGS32_NZCV_SUB(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_SUB(a,b) | FLAGS32_V_SUB(r,a,b)) +#define FLAGS32_NZCV_SUBC(r,a,b,c) (FLAGS32_NZ(r) | FLAGS32_C_SUBC(a,b,c) | FLAGS32_V_SUB(r,a,b)) // compute C and V flags for 64-bit add/subtract #define FLAGS64_C_ADD(a,b) ((uint64_t)~(a) < (uint64_t)(b)) #define FLAGS64_C_SUB(a,b) ((uint64_t)(b) > (uint64_t)(a)) +#define FLAGS64_C_SUBC(a,b,c) (((uint64_t)(c) != 0 && ((uint64_t)(b) + (uint64_t)(c)) == 0) || (uint64_t)(b) + (uint64_t)(c) > (uint64_t)(a)) #define FLAGS64_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V) #define FLAGS64_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V) @@ -199,6 +220,122 @@ enum #define FLAGS64_NZ(v) ((((v) >> 60) & FLAG_S) | (((uint64_t)(v) == 0) << 2)) #define FLAGS64_NZCV_ADD(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_ADD(a,b) | FLAGS64_V_ADD(r,a,b)) #define FLAGS64_NZCV_SUB(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_SUB(a,b) | FLAGS64_V_SUB(r,a,b)) +#define FLAGS64_NZCV_SUBC(r,a,b,c) (FLAGS64_NZ(r) | FLAGS64_C_SUBC(a,b,c) | FLAGS64_V_SUB(r,a,b)) + + +//------------------------------------------------- +// dmulu - perform a double-wide unsigned multiply +//------------------------------------------------- + +inline int dmulu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src2, bool flags) +{ + // shortcut if we don't care about the high bits or the flags + if (&dstlo == &dsthi && !flags) + { + dstlo = src1 * src2; + return 0; + } + + // fetch source values + uint64_t a = src1; + uint64_t b = src2; + if (a == 0 || b == 0) + { + dsthi = dstlo = 0; + return FLAG_Z; + } + + // compute high and low parts first + uint64_t lo = uint64_t(uint32_t(a >> 0)) * uint64_t(uint32_t(b >> 0)); + uint64_t hi = uint64_t(uint32_t(a >> 32)) * uint64_t(uint32_t(b >> 32)); + + // compute middle parts + uint64_t prevlo = lo; + uint64_t temp = uint64_t(uint32_t(a >> 32)) * uint64_t(uint32_t(b >> 0)); + lo += temp << 32; + hi += (temp >> 32) + (lo < prevlo); + + prevlo = lo; + temp = uint64_t(uint32_t(a >> 0)) * uint64_t(uint32_t(b >> 32)); + lo += temp << 32; + hi += (temp >> 32) + (lo < prevlo); + + // store the results + dsthi = hi; + dstlo = lo; + return ((hi >> 60) & FLAG_S) | ((hi != 0) << 1); +} + + +//------------------------------------------------- +// dmuls - perform a double-wide signed multiply +//------------------------------------------------- + +inline int dmuls(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2, bool flags) +{ + // shortcut if we don't care about the high bits or the flags + if (&dstlo == &dsthi && !flags) + { + dstlo = src1 * src2; + return 0; + } + + // fetch absolute source values + uint64_t a = src1; if (int64_t(a) < 0) a = -a; + uint64_t b = src2; if (int64_t(b) < 0) b = -b; + if (a == 0 || b == 0) + { + dsthi = dstlo = 0; + return FLAG_Z; + } + + // compute high and low parts first + uint64_t lo = uint64_t(uint32_t(a >> 0)) * uint64_t(uint32_t(b >> 0)); + uint64_t hi = uint64_t(uint32_t(a >> 32)) * uint64_t(uint32_t(b >> 32)); + + // compute middle parts + uint64_t prevlo = lo; + uint64_t temp = uint64_t(uint32_t(a >> 32)) * uint64_t(uint32_t(b >> 0)); + lo += temp << 32; + hi += (temp >> 32) + (lo < prevlo); + + prevlo = lo; + temp = uint64_t(uint32_t(a >> 0)) * uint64_t(uint32_t(b >> 32)); + lo += temp << 32; + hi += (temp >> 32) + (lo < prevlo); + + // adjust for signage + if (int64_t(src1 ^ src2) < 0) + { + hi = ~hi + ((lo == 0) ? 1 : 0); + lo = ~lo + 1; + } + + // store the results + dsthi = hi; + dstlo = lo; + return ((hi >> 60) & FLAG_S) | ((hi != (int64_t(lo) >> 63)) << 1); +} + +inline uint32_t tzcount32(uint32_t value) +{ + for (int i = 0; i < 32; i++) + { + if (value & (uint32_t(1) << i)) + return i; + } + return 32; +} + +inline uint64_t tzcount64(uint64_t value) +{ + for (int i = 0; i < 64; i++) + { + if (value & (uint64_t(1) << i)) + return i; + } + return 64; +} @@ -209,19 +346,20 @@ enum // union to simplify accessing data via the instruction stream union drcbec_instruction { - uint32_t i; + uint32_t i; void * v; char * c; - uint8_t * puint8; - int8_t * pint8; - uint16_t * puint16; - int16_t * pint16; - uint32_t * puint32; - int32_t * pint32; - uint64_t * puint64; - int64_t * pint64; + uint8_t * puint8; + int8_t * pint8; + uint16_t * puint16; + int16_t * pint16; + uint32_t * puint32; + int32_t * pint32; + uint64_t * puint64; + int64_t * pint64; float * pfloat; double * pdouble; + address_space * space; void (*cfunc)(void *); drcuml_machine_state *state; const code_handle * handle; @@ -230,6 +368,36 @@ union drcbec_instruction }; +class drcbe_c : public drcbe_interface +{ +public: + // construction/destruction + drcbe_c(drcuml_state &drcuml, device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits); + virtual ~drcbe_c(); + + // required overrides + virtual void reset() override; + virtual int execute(uml::code_handle &entry) override; + virtual void generate(drcuml_block &block, const uml::instruction *instlist, uint32_t numinst) override; + virtual bool hash_exists(uint32_t mode, uint32_t pc) const noexcept override; + virtual void get_info(drcbe_info &info) const noexcept override; + +private: + // helpers + void output_parameter(drcbec_instruction **dstptr, void *immed, int immoffset, int size, const uml::parameter ¶m); + void fixup_label(void *parameter, drccodeptr labelcodeptr); + + // internal state + drc_hash_table m_hash; // hash table state + drc_map_variables m_map; // code map + drc_label_list m_labels; // label list + drc_label_fixup_delegate m_fixup_delegate; // precomputed delegate + + static const uint32_t s_condition_map[32]; + static uint64_t s_immediate_zero; +}; + + //************************************************************************** // GLOBAL VARIABLES @@ -283,12 +451,12 @@ const uint32_t drcbe_c::s_condition_map[] = // drcbe_c - constructor //------------------------------------------------- -drcbe_c::drcbe_c(drcuml_state &drcuml, device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits) - : drcbe_interface(drcuml, cache, device), - m_hash(cache, modes, addrbits, ignorebits), - m_map(cache, 0xaaaaaaaa55555555), - m_labels(cache), - m_fixup_delegate(&drcbe_c::fixup_label, this) +drcbe_c::drcbe_c(drcuml_state &drcuml, device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits) : + drcbe_interface(drcuml, cache, device), + m_hash(cache, modes, addrbits, ignorebits), + m_map(cache, 0xaaaaaaaa55555555), + m_labels(cache), + m_fixup_delegate(&drcbe_c::fixup_label, this) { } @@ -320,13 +488,30 @@ void drcbe_c::reset() void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_t numinst) { + // Calculate the max possible number of register clears required + uint32_t regclears = 0; + + for (int inum = 0; inum < numinst; inum++) + { + const instruction &inst = instlist[inum]; + + if (inst.size() != 4) + continue; + + for (int pnum = 0; pnum < inst.numparams(); pnum++) + { + if (inst.is_param_out(pnum) && inst.param(pnum).is_int_register()) + regclears++; + } + } + // tell all of our utility objects that a block is beginning - m_hash.block_begin(block, instlist, numinst); + m_hash.block_begin(block, instlist, numinst + regclears); m_labels.block_begin(block); m_map.block_begin(block); // begin codegen; fail if we can't - drccodeptr *cachetop = m_cache.begin_codegen(numinst * sizeof(drcbec_instruction) * 4); + drccodeptr *cachetop = m_cache.begin_codegen((numinst + regclears) * sizeof(drcbec_instruction) * 4); if (cachetop == nullptr) block.abort(); @@ -334,11 +519,15 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ drcbec_instruction *base = (drcbec_instruction *)(((uintptr_t)*cachetop + sizeof(drcbec_instruction) - 1) & ~(sizeof(drcbec_instruction) - 1)); drcbec_instruction *dst = base; + bool ireg_needs_clearing[REG_I_COUNT]; + std::fill(std::begin(ireg_needs_clearing), std::end(ireg_needs_clearing), true); + // generate code by copying the instructions and extracting immediates for (int inum = 0; inum < numinst; inum++) { const instruction &inst = instlist[inum]; uint8_t psize[instruction::MAX_PARAMS]; + int8_t immoffset[instruction::MAX_PARAMS]; // handle most instructions generally, but a few special cases opcode_t opcode = inst.opcode(); @@ -359,9 +548,10 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ m_labels.set_codeptr(inst.param(0).label(), (drccodeptr)dst); break; - // ignore COMMENT and NOP opcodes + // ignore COMMENT, NOP, and BREAK opcodes case OP_COMMENT: case OP_NOP: + case OP_BREAK: break; // when we hit a MAPVAR opcode, log the change for the current PC @@ -386,10 +576,14 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ psize[2] = 4; if (opcode == OP_STORE || opcode == OP_FSTORE) psize[1] = 4; - if (opcode == OP_READ || opcode == OP_READM || opcode == OP_FREAD) + if (opcode == OP_READ || opcode == OP_FREAD) psize[1] = psize[2] = 4; - if (opcode == OP_WRITE || opcode == OP_WRITEM || opcode == OP_FWRITE) + if (opcode == OP_WRITE || opcode == OP_FWRITE) psize[0] = psize[2] = 4; + if (opcode == OP_READM) + psize[1] = psize[3] = 4; + if (opcode == OP_WRITEM) + psize[0] = psize[3] = 4; if (opcode == OP_SEXT && inst.param(2).size() != SIZE_QWORD) psize[1] = 4; if (opcode == OP_FTOINT) @@ -399,35 +593,47 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ // pre-expand opcodes that encode size/scale in them if (opcode == OP_LOAD) - opcode = (opcode_t)(OP_LOAD1 + inst.param(3).size() * 4 + inst.param(3).scale()); + opcode = opcode_t(OP_LOAD1 + inst.param(3).size() * 4 + inst.param(3).scale()); if (opcode == OP_LOADS) - opcode = (opcode_t)(OP_LOADS1 + inst.param(3).size() * 4 + inst.param(3).scale()); + opcode = opcode_t(OP_LOADS1 + inst.param(3).size() * 4 + inst.param(3).scale()); if (opcode == OP_STORE) - opcode = (opcode_t)(OP_STORE1 + inst.param(3).size() * 4 + inst.param(3).scale()); + opcode = opcode_t(OP_STORE1 + inst.param(3).size() * 4 + inst.param(3).scale()); if (opcode == OP_READ) - opcode = (opcode_t)(OP_READ1 + inst.param(2).size()); + opcode = opcode_t(OP_READ1 + inst.param(2).size()); if (opcode == OP_READM) - opcode = (opcode_t)(OP_READM1 + inst.param(3).size()); + opcode = opcode_t(OP_READM1 + inst.param(3).size()); if (opcode == OP_WRITE) - opcode = (opcode_t)(OP_WRITE1 + inst.param(2).size()); + opcode = opcode_t(OP_WRITE1 + inst.param(2).size()); if (opcode == OP_WRITEM) - opcode = (opcode_t)(OP_WRITEM1 + inst.param(3).size()); + opcode = opcode_t(OP_WRITEM1 + inst.param(3).size()); if (opcode == OP_SEXT) - opcode = (opcode_t)(OP_SEXT1 + inst.param(2).size()); + opcode = opcode_t(OP_SEXT1 + inst.param(2).size()); if (opcode == OP_FTOINT) - opcode = (opcode_t)(OP_FTOI4T + 5 * (inst.param(2).size() - 2) + inst.param(3).rounding()); + opcode = opcode_t(OP_FTOI4T + 5 * (inst.param(2).size() - 2) + inst.param(3).rounding()); if (opcode == OP_FFRINT) - opcode = (opcode_t)(OP_FFRI4 + (inst.param(2).size() - 2)); + opcode = opcode_t(OP_FFRI4 + (inst.param(2).size() - 2)); if (opcode == OP_FFRFLT) - opcode = (opcode_t)(OP_FFRFS + (inst.param(2).size() - 2)); + opcode = opcode_t(OP_FFRFS + (inst.param(2).size() - 2)); // count how many bytes of immediates we need int immedbytes = 0; for (int pnum = 0; pnum < inst.numparams(); pnum++) - if (inst.param(pnum).is_mapvar() || - (inst.param(pnum).is_immediate() && inst.param(pnum).immediate() != 0) || - (inst.param(pnum).is_size_space() && inst.param(pnum).space() != 0)) + { + auto const ¶m = inst.param(pnum); + if (param.is_mapvar() || (param.is_immediate() && (param.immediate() != 0))) + { + int const align = (psize[pnum] == 4) ? alignof(uint32_t) : alignof(uint64_t); + int const misalign = immedbytes % align; + if (misalign) + immedbytes += align - misalign; + immoffset[pnum] = immedbytes; immedbytes += psize[pnum]; + } + else + { + immoffset[pnum] = -1; + } + } // compute how many instruction words we need for that int immedwords = (immedbytes + sizeof(drcbec_instruction) - 1) / sizeof(drcbec_instruction); @@ -440,10 +646,43 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ // output each of the parameters for (int pnum = 0; pnum < inst.numparams(); pnum++) - output_parameter(&dst, &immed, psize[pnum], inst.param(pnum)); + output_parameter(&dst, immed, immoffset[pnum], psize[pnum], inst.param(pnum)); // point past the end of the immediates dst += immedwords; + + // Keep track of which registers had an 8 byte write and clear it the next time it's written + if (inst.size() == 4) + { + for (int pnum = 0; pnum < inst.numparams(); pnum++) + { + if (inst.is_param_out(pnum) && inst.param(pnum).is_int_register() && ireg_needs_clearing[inst.param(pnum).ireg() - REG_I0]) + { + immedwords = (8 + sizeof(drcbec_instruction) - 1) / sizeof(drcbec_instruction); + + (dst++)->i = MAKE_OPCODE_FULL(OP_AND, 8, 0, 0, 3 + immedwords); + + immed = dst + 3; + + output_parameter(&dst, immed, -1, 8, inst.param(pnum)); + output_parameter(&dst, immed, -1, 8, inst.param(pnum)); + output_parameter(&dst, immed, 0, 8, 0xffffffff); + + dst += immedwords; + + ireg_needs_clearing[inst.param(pnum).ireg() - REG_I0] = false; + } + } + } + else if (inst.size() == 8) + { + for (int pnum = 0; pnum < inst.numparams(); pnum++) + { + if (inst.is_param_out(pnum) && inst.param(pnum).is_int_register()) + ireg_needs_clearing[inst.param(pnum).ireg() - REG_I0] = true; + } + } + break; } } @@ -464,7 +703,7 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ // exists in the hash table //------------------------------------------------- -bool drcbe_c::hash_exists(uint32_t mode, uint32_t pc) +bool drcbe_c::hash_exists(uint32_t mode, uint32_t pc) const noexcept { return m_hash.code_exists(mode, pc); } @@ -475,7 +714,7 @@ bool drcbe_c::hash_exists(uint32_t mode, uint32_t pc) // back-end implementation //------------------------------------------------- -void drcbe_c::get_info(drcbe_info &info) +void drcbe_c::get_info(drcbe_info &info) const noexcept { info.direct_iregs = 0; info.direct_fregs = 0; @@ -516,7 +755,11 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_MAPVAR, 4, 0): // MAPVAR mapvar,value // these opcodes should be processed at compile-time only - fatalerror("Unexpected opcode\n"); + fatalerror("Unexpected opcode %08x %d %d %d\n", opcode, OPCODE_GET_SHORT(opcode) >> 2, BIT(opcode, 0) ? 8 : 4, BIT(opcode, 1)); + + case MAKE_OPCODE_SHORT(OP_BREAK, 4, 0): + osd_break_into_debugger("break from drc"); + break; case MAKE_OPCODE_SHORT(OP_DEBUG, 4, 0): // DEBUG pc if (m_device.machine().debug_flags & DEBUG_FLAG_CALL_HOOK) @@ -528,7 +771,7 @@ int drcbe_c::execute(code_handle &entry) newinst = (const drcbec_instruction *)m_hash.get_codeptr(PARAM0, PARAM1); if (newinst == nullptr) { - assert(sp < ARRAY_LENGTH(callstack)); + assert(sp < std::size(callstack)); m_state.exp = PARAM1; newinst = (const drcbec_instruction *)inst[2].handle->codeptr(); callstack[sp++] = inst; @@ -540,7 +783,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_EXIT, 4, 1): // EXIT src1[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_EXIT, 4, 0): return PARAM0; @@ -548,7 +791,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_JMP, 4, 1): // JMP imm[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_JMP, 4, 0): newinst = inst[0].inst; @@ -559,10 +802,10 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_CALLH, 4, 1): // CALLH handle[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_CALLH, 4, 0): - assert(sp < ARRAY_LENGTH(callstack)); + assert(sp < std::size(callstack)); newinst = (const drcbec_instruction *)inst[0].handle->codeptr(); assert_in_cache(m_cache, newinst); callstack[sp++] = inst + OPCODE_GET_PWORDS(opcode); @@ -572,7 +815,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_RET, 4, 1): // RET [c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_RET, 4, 0): assert(sp > 0); @@ -584,10 +827,10 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_EXH, 4, 1): // EXH handle,param[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_EXH, 4, 0): - assert(sp < ARRAY_LENGTH(callstack)); + assert(sp < std::size(callstack)); newinst = (const drcbec_instruction *)inst[0].handle->codeptr(); assert_in_cache(m_cache, newinst); m_state.exp = PARAM1; @@ -598,7 +841,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_CALLC, 4, 1): // CALLC func,ptr[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_CALLC, 4, 0): (*inst[0].cfunc)(inst[1].v); @@ -606,7 +849,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_RECOVER, 4, 0): // RECOVER dst,mapvar assert(sp > 0); - PARAM0 = m_map.get_value((drccodeptr)callstack[0], MAPVAR_M0 + PARAM1); + PARAM0 = m_map.get_value(drccodeptr(callstack[0] - 1), PARAM1); break; @@ -628,6 +871,11 @@ int drcbe_c::execute(code_handle &entry) PARAM0 = flags & PARAM1; break; + case MAKE_OPCODE_SHORT(OP_SETFLGS, 4, 0): // SETFLGS src + case MAKE_OPCODE_SHORT(OP_SETFLGS, 4, 1): + flags = PARAM0; + break; + case MAKE_OPCODE_SHORT(OP_SAVE, 4, 0): // SAVE dst *inst[0].state = m_state; inst[0].state->flags = flags; @@ -643,197 +891,206 @@ int drcbe_c::execute(code_handle &entry) // ----------------------- 32-Bit Integer Operations ----------------------- case MAKE_OPCODE_SHORT(OP_LOAD1, 4, 0): // LOAD dst,base,index,BYTE - PARAM0 = inst[1].puint8[PARAM2]; + PARAM0 = inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x2, 4, 0): // LOAD dst,base,index,BYTE_x2 - PARAM0 = *(uint8_t *)&inst[1].puint16[PARAM2]; + PARAM0 = *(uint8_t *)&inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x4, 4, 0): // LOAD dst,base,index,BYTE_x4 - PARAM0 = *(uint8_t *)&inst[1].puint32[PARAM2]; + PARAM0 = *(uint8_t *)&inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x8, 4, 0): // LOAD dst,base,index,BYTE_x8 - PARAM0 = *(uint8_t *)&inst[1].puint64[PARAM2]; + PARAM0 = *(uint8_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x1, 4, 0): // LOAD dst,base,index,WORD_x1 - PARAM0 = *(uint16_t *)&inst[1].puint8[PARAM2]; + PARAM0 = *(uint16_t *)&inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2, 4, 0): // LOAD dst,base,index,WORD - PARAM0 = inst[1].puint16[PARAM2]; + PARAM0 = inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x4, 4, 0): // LOAD dst,base,index,WORD_x4 - PARAM0 = *(uint16_t *)&inst[1].puint32[PARAM2]; + PARAM0 = *(uint16_t *)&inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x8, 4, 0): // LOAD dst,base,index,WORD_x8 - PARAM0 = *(uint16_t *)&inst[1].puint64[PARAM2]; + PARAM0 = *(uint16_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x1, 4, 0): // LOAD dst,base,index,DWORD_x1 - PARAM0 = *(uint32_t *)&inst[1].puint8[PARAM2]; + PARAM0 = *(uint32_t *)&inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x2, 4, 0): // LOAD dst,base,index,DWORD_x2 - PARAM0 = *(uint32_t *)&inst[1].puint16[PARAM2]; + PARAM0 = *(uint32_t *)&inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4, 4, 0): // LOAD dst,base,index,DWORD - PARAM0 = inst[1].puint32[PARAM2]; + PARAM0 = inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x8, 4, 0): // LOAD dst,base,index,DWORD_x8 - PARAM0 = *(uint32_t *)&inst[1].puint64[PARAM2]; + PARAM0 = *(uint32_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1, 4, 0): // LOADS dst,base,index,BYTE - PARAM0 = inst[1].pint8[PARAM2]; + PARAM0 = inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x2, 4, 0): // LOADS dst,base,index,BYTE_x2 - PARAM0 = *(int8_t *)&inst[1].pint16[PARAM2]; + PARAM0 = *(int8_t *)&inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x4, 4, 0): // LOADS dst,base,index,BYTE_x4 - PARAM0 = *(int8_t *)&inst[1].pint32[PARAM2]; + PARAM0 = *(int8_t *)&inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x8, 4, 0): // LOADS dst,base,index,BYTE_x8 - PARAM0 = *(int8_t *)&inst[1].pint64[PARAM2]; + PARAM0 = *(int8_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x1, 4, 0): // LOADS dst,base,index,WORD_x1 - PARAM0 = *(int16_t *)&inst[1].pint8[PARAM2]; + PARAM0 = *(int16_t *)&inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2, 4, 0): // LOADS dst,base,index,WORD - PARAM0 = inst[1].pint16[PARAM2]; + PARAM0 = inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x4, 4, 0): // LOADS dst,base,index,WORD_x4 - PARAM0 = *(int16_t *)&inst[1].pint32[PARAM2]; + PARAM0 = *(int16_t *)&inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x8, 4, 0): // LOADS dst,base,index,WORD_x8 - PARAM0 = *(int16_t *)&inst[1].pint64[PARAM2]; + PARAM0 = *(int16_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x1, 4, 0): // LOADS dst,base,index,DWORD_x1 - PARAM0 = *(int32_t *)&inst[1].pint8[PARAM2]; + PARAM0 = *(int32_t *)&inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x2, 4, 0): // LOADS dst,base,index,DWORD_x2 - PARAM0 = *(int32_t *)&inst[1].pint16[PARAM2]; + PARAM0 = *(int32_t *)&inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4, 4, 0): // LOADS dst,base,index,DWORD - PARAM0 = inst[1].pint32[PARAM2]; + PARAM0 = inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x8, 4, 0): // LOADS dst,base,index,DWORD_x8 - PARAM0 = *(int32_t *)&inst[1].pint64[PARAM2]; + PARAM0 = *(int32_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_STORE1, 4, 0): // STORE dst,base,index,BYTE - inst[0].puint8[PARAM1] = PARAM2; + inst[0].puint8[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x2, 4, 0): // STORE dst,base,index,BYTE_x2 - *(uint8_t *)&inst[0].puint16[PARAM1] = PARAM2; + *(uint8_t *)&inst[0].puint16[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x4, 4, 0): // STORE dst,base,index,BYTE_x4 - *(uint8_t *)&inst[0].puint32[PARAM1] = PARAM2; + *(uint8_t *)&inst[0].puint32[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x8, 4, 0): // STORE dst,base,index,BYTE_x8 - *(uint8_t *)&inst[0].puint64[PARAM1] = PARAM2; + *(uint8_t *)&inst[0].puint64[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x1, 4, 0): // STORE dst,base,index,WORD_x1 - *(uint16_t *)&inst[0].puint8[PARAM1] = PARAM2; + *(uint16_t *)&inst[0].puint8[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2, 4, 0): // STORE dst,base,index,WORD - inst[0].puint16[PARAM1] = PARAM2; + inst[0].puint16[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x4, 4, 0): // STORE dst,base,index,WORD_x4 - *(uint16_t *)&inst[0].puint32[PARAM1] = PARAM2; + *(uint16_t *)&inst[0].puint32[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x8, 4, 0): // STORE dst,base,index,WORD_x8 - *(uint16_t *)&inst[0].puint64[PARAM1] = PARAM2; + *(uint16_t *)&inst[0].puint64[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x1, 4, 0): // STORE dst,base,index,DWORD_x1 - *(uint32_t *)&inst[0].puint8[PARAM1] = PARAM2; + *(uint32_t *)&inst[0].puint8[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x2, 4, 0): // STORE dst,base,index,DWORD_x2 - *(uint32_t *)&inst[0].puint16[PARAM1] = PARAM2; + *(uint32_t *)&inst[0].puint16[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4, 4, 0): // STORE dst,base,index,DWORD - inst[0].puint32[PARAM1] = PARAM2; + inst[0].puint32[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x8, 4, 0): // STORE dst,base,index,DWORD_x8 - *(uint32_t *)&inst[0].puint64[PARAM1] = PARAM2; + *(uint32_t *)&inst[0].puint64[SPARAM1] = PARAM2; break; case MAKE_OPCODE_SHORT(OP_READ1, 4, 0): // READ dst,src1,space_BYTE - PARAM0 = m_space[PARAM2]->read_byte(PARAM1); + PARAM0 = SPACEPARAM2.read_byte(PARAM1); break; case MAKE_OPCODE_SHORT(OP_READ2, 4, 0): // READ dst,src1,space_WORD - PARAM0 = m_space[PARAM2]->read_word(PARAM1); + PARAM0 = SPACEPARAM2.read_word(PARAM1); break; case MAKE_OPCODE_SHORT(OP_READ4, 4, 0): // READ dst,src1,space_DWORD - PARAM0 = m_space[PARAM2]->read_dword(PARAM1); + PARAM0 = SPACEPARAM2.read_dword(PARAM1); + break; + + case MAKE_OPCODE_SHORT(OP_READM1, 4, 0): // READM dst,src1,mask,space_BYTE + PARAM0 = SPACEPARAM3.read_byte(PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_READM2, 4, 0): // READM dst,src1,mask,space_WORD - PARAM0 = m_space[PARAM3]->read_word(PARAM1, PARAM2); + PARAM0 = SPACEPARAM3.read_word(PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_READM4, 4, 0): // READM dst,src1,mask,space_DWORD - PARAM0 = m_space[PARAM3]->read_dword(PARAM1, PARAM2); + PARAM0 = SPACEPARAM3.read_dword(PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITE1, 4, 0): // WRITE dst,src1,space_BYTE - m_space[PARAM2]->write_byte(PARAM0, PARAM1); + SPACEPARAM2.write_byte(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_WRITE2, 4, 0): // WRITE dst,src1,space_WORD - m_space[PARAM2]->write_word(PARAM0, PARAM1); + SPACEPARAM2.write_word(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_WRITE4, 4, 0): // WRITE dst,src1,space_DWORD - m_space[PARAM2]->write_dword(PARAM0, PARAM1); + SPACEPARAM2.write_dword(PARAM0, PARAM1); + break; + + case MAKE_OPCODE_SHORT(OP_WRITEM1, 4, 0): // WRITEM dst,src1,mask,space_BYTE + SPACEPARAM3.write_byte(PARAM0, PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITEM2, 4, 0): // WRITEM dst,src1,mask,space_WORD - m_space[PARAM3]->write_word(PARAM0, PARAM1, PARAM2); + SPACEPARAM3.write_word(PARAM0, PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITEM4, 4, 0): // WRITEM dst,src1,mask,space_DWORD - m_space[PARAM3]->write_dword(PARAM0, PARAM1, PARAM2); + SPACEPARAM3.write_dword(PARAM0, PARAM1, PARAM2); break; - case MAKE_OPCODE_SHORT(OP_CARRY, 4, 1): // CARRY src,bitnum + case MAKE_OPCODE_SHORT(OP_CARRY, 4, 0): // CARRY src,bitnum + case MAKE_OPCODE_SHORT(OP_CARRY, 4, 1): flags = (flags & ~FLAG_C) | ((PARAM0 >> (PARAM1 & 31)) & FLAG_C); break; case MAKE_OPCODE_SHORT(OP_MOV, 4, 1): // MOV dst,src[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_MOV, 4, 0): PARAM0 = PARAM1; @@ -864,25 +1121,21 @@ int drcbe_c::execute(code_handle &entry) break; case MAKE_OPCODE_SHORT(OP_ROLAND, 4, 0): // ROLAND dst,src,count,mask[,f] - shift = PARAM2 & 31; - PARAM0 = ((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3; + PARAM0 = rotl_32(PARAM1, PARAM2) & PARAM3; break; case MAKE_OPCODE_SHORT(OP_ROLAND, 4, 1): - shift = PARAM2 & 31; - temp32 = ((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3; + temp32 = rotl_32(PARAM1, PARAM2) & PARAM3; flags = FLAGS32_NZ(temp32); PARAM0 = temp32; break; case MAKE_OPCODE_SHORT(OP_ROLINS, 4, 0): // ROLINS dst,src,count,mask[,f] - shift = PARAM2 & 31; - PARAM0 = (PARAM0 & ~PARAM3) | (((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3); + PARAM0 = (PARAM0 & ~PARAM3) | (rotl_32(PARAM1, PARAM2) & PARAM3); break; case MAKE_OPCODE_SHORT(OP_ROLINS, 4, 1): - shift = PARAM2 & 31; - temp32 = (PARAM0 & ~PARAM3) | (((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3); + temp32 = (PARAM0 & ~PARAM3) | (rotl_32(PARAM1, PARAM2) & PARAM3); flags = FLAGS32_NZ(temp32); PARAM0 = temp32; break; @@ -934,33 +1187,23 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SUBB, 4, 1): temp32 = PARAM1 - PARAM2 - (flags & FLAG_C); - temp64 = (uint64_t)PARAM1 - (uint64_t)PARAM2 - (uint64_t)(flags & FLAG_C); - if (PARAM2 + 1 != 0) - flags = FLAGS32_NZCV_SUB(temp32, PARAM1, PARAM2 + (flags & FLAG_C)); - else - { - flags = FLAGS32_NZCV_SUB(temp32, PARAM1 - (flags & FLAG_C), PARAM2); - flags &= ~(FLAG_C | FLAG_V); - flags |= ((temp64>>32) & 1) ? FLAG_C : 0; - flags |= (((PARAM1) ^ (PARAM2)) & ((PARAM1) ^ (temp64)) & 0x80000000) ? FLAG_V : 0; - } + flags = FLAGS32_NZCV_SUBC(temp32, PARAM1, PARAM2, flags & FLAG_C); PARAM0 = temp32; break; case MAKE_OPCODE_SHORT(OP_CMP, 4, 1): // CMP src1,src2[,f] temp32 = PARAM0 - PARAM1; flags = FLAGS32_NZCV_SUB(temp32, PARAM0, PARAM1); -// printf("CMP: %08x - %08x = flags %x\n", PARAM0, PARAM1, flags); break; case MAKE_OPCODE_SHORT(OP_MULU, 4, 0): // MULU dst,edst,src1,src2[,f] - temp64 = (uint64_t)(uint32_t)PARAM2 * (uint64_t)(uint32_t)PARAM3; + temp64 = mulu_32x32(PARAM2, PARAM3); PARAM1 = temp64 >> 32; PARAM0 = (uint32_t)temp64; break; case MAKE_OPCODE_SHORT(OP_MULU, 4, 1): - temp64 = (uint64_t)(uint32_t)PARAM2 * (uint64_t)(uint32_t)PARAM3; + temp64 = mulu_32x32(PARAM2, PARAM3); flags = FLAGS64_NZ(temp64); PARAM1 = temp64 >> 32; PARAM0 = (uint32_t)temp64; @@ -968,19 +1211,46 @@ int drcbe_c::execute(code_handle &entry) flags |= FLAG_V; break; + case MAKE_OPCODE_SHORT(OP_MULULW, 4, 0): // MULULW dst,src1,src2[,f] + temp64 = mulu_32x32(PARAM1, PARAM2); + PARAM0 = (uint32_t)temp64; + break; + + case MAKE_OPCODE_SHORT(OP_MULULW, 4, 1): + temp64 = mulu_32x32(PARAM1, PARAM2); + temp32 = (uint32_t)temp64; + flags = FLAGS32_NZ(temp32); + PARAM0 = temp32; + if (temp64 > temp32) + flags |= FLAG_V; + break; + case MAKE_OPCODE_SHORT(OP_MULS, 4, 0): // MULS dst,edst,src1,src2[,f] - temp64 = (int64_t)(int32_t)PARAM2 * (int64_t)(int32_t)PARAM3; + temp64 = mul_32x32(PARAM2, PARAM3); PARAM1 = temp64 >> 32; PARAM0 = (uint32_t)temp64; break; case MAKE_OPCODE_SHORT(OP_MULS, 4, 1): - temp64 = (int64_t)(int32_t)PARAM2 * (int64_t)(int32_t)PARAM3; - temp32 = (int32_t)temp64; - flags = FLAGS32_NZ(temp32); + temp64 = mul_32x32(PARAM2, PARAM3); + flags = FLAGS64_NZ(temp64); PARAM1 = temp64 >> 32; PARAM0 = (uint32_t)temp64; - if (temp64 != (int32_t)temp64) + if ((int64_t)temp64 != (int32_t)temp64) + flags |= FLAG_V; + break; + + case MAKE_OPCODE_SHORT(OP_MULSLW, 4, 0): // MULSLW dst,src1,src2[,f] + temp64 = mul_32x32(PARAM1, PARAM2); + PARAM0 = (int32_t)temp64; + break; + + case MAKE_OPCODE_SHORT(OP_MULSLW, 4, 1): + temp64 = mul_32x32(PARAM1, PARAM2); + temp32 = (int32_t)temp64; + flags = FLAGS32_NZ(temp32); + PARAM0 = temp32; + if ((int64_t)temp64 != (int32_t)temp64) flags |= FLAG_V; break; @@ -1036,7 +1306,10 @@ int drcbe_c::execute(code_handle &entry) PARAM0 = temp32; break; - case MAKE_OPCODE_SHORT(OP_TEST, 4, 1): // TEST src1,src2[,f] + case MAKE_OPCODE_SHORT(OP_TEST, 4, 0): // TEST src1,src2[,f] + break; + + case MAKE_OPCODE_SHORT(OP_TEST, 4, 1): temp32 = PARAM0 & PARAM1; flags = FLAGS32_NZ(temp32); break; @@ -1062,11 +1335,11 @@ int drcbe_c::execute(code_handle &entry) break; case MAKE_OPCODE_SHORT(OP_LZCNT, 4, 0): // LZCNT dst,src - PARAM0 = count_leading_zeros(PARAM1); + PARAM0 = count_leading_zeros_32(PARAM1); break; case MAKE_OPCODE_SHORT(OP_LZCNT, 4, 1): - temp32 = count_leading_zeros(PARAM1); + temp32 = count_leading_zeros_32(PARAM1); flags = FLAGS32_NZ(temp32); PARAM0 = temp32; break; @@ -1088,8 +1361,8 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_BSWAP, 4, 1): temp32 = PARAM1; - flags = FLAGS32_NZ(temp32); PARAM0 = swapendian_int32(temp32); + flags = FLAGS32_NZ(PARAM0); break; case MAKE_OPCODE_SHORT(OP_SHL, 4, 0): // SHL dst,src,count[,f] @@ -1099,11 +1372,9 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SHL, 4, 1): shift = PARAM2 & 31; temp32 = PARAM1 << shift; + flags = FLAGS32_NZ(temp32); if (shift != 0) - { - flags = FLAGS32_NZ(temp32); flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C; - } PARAM0 = temp32; break; @@ -1114,11 +1385,9 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SHR, 4, 1): shift = PARAM2 & 31; temp32 = PARAM1 >> shift; + flags = FLAGS32_NZ(temp32); if (shift != 0) - { - flags = FLAGS32_NZ(temp32); flags |= (PARAM1 >> (shift - 1)) & FLAG_C; - } PARAM0 = temp32; break; @@ -1129,27 +1398,22 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SAR, 4, 1): shift = PARAM2 & 31; temp32 = (int32_t)PARAM1 >> shift; + flags = FLAGS32_NZ(temp32); if (shift != 0) - { - flags = FLAGS32_NZ(temp32); flags |= (PARAM1 >> (shift - 1)) & FLAG_C; - } PARAM0 = temp32; break; case MAKE_OPCODE_SHORT(OP_ROL, 4, 0): // ROL dst,src,count[,f] - shift = PARAM2 & 31; - PARAM0 = (PARAM1 << shift) | (PARAM1 >> ((32 - shift) & 31)); + PARAM0 = rotl_32(PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_ROL, 4, 1): shift = PARAM2 & 31; - temp32 = (PARAM1 << shift) | (PARAM1 >> ((32 - shift) & 31)); + temp32 = rotl_32(PARAM1, shift); + flags = FLAGS32_NZ(temp32); if (shift != 0) - { - flags = FLAGS32_NZ(temp32); flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C; - } PARAM0 = temp32; break; @@ -1159,6 +1423,8 @@ int drcbe_c::execute(code_handle &entry) PARAM0 = (PARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (PARAM1 >> (33 - shift)); else if (shift == 1) PARAM0 = (PARAM1 << shift) | (flags & FLAG_C); + else + PARAM0 = PARAM1; break; case MAKE_OPCODE_SHORT(OP_ROLC, 4, 1): @@ -1169,21 +1435,20 @@ int drcbe_c::execute(code_handle &entry) temp32 = (PARAM1 << shift) | (flags & FLAG_C); else temp32 = PARAM1; - flags = FLAGS32_NZ(temp32); - if (shift != 0) flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C; + flags = FLAGS32_NZ(temp32) | (((shift != 0) ? (PARAM1 >> (32 - shift)) : flags) & FLAG_C); PARAM0 = temp32; break; case MAKE_OPCODE_SHORT(OP_ROR, 4, 0): // ROR dst,src,count[,f] - shift = PARAM2 & 31; - PARAM0 = (PARAM1 >> shift) | (PARAM1 << ((32 - shift) & 31)); + PARAM0 = rotr_32(PARAM1, PARAM2); break; case MAKE_OPCODE_SHORT(OP_ROR, 4, 1): shift = PARAM2 & 31; - temp32 = (PARAM1 >> shift) | (PARAM1 << ((32 - shift) & 31)); + temp32 = rotr_32(PARAM1, shift); flags = FLAGS32_NZ(temp32); - if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C; + if (shift != 0) + flags |= (PARAM1 >> (shift - 1)) & FLAG_C; PARAM0 = temp32; break; @@ -1193,6 +1458,8 @@ int drcbe_c::execute(code_handle &entry) PARAM0 = (PARAM1 >> shift) | (((flags & FLAG_C) << 31) >> (shift - 1)) | (PARAM1 << (33 - shift)); else if (shift == 1) PARAM0 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31); + else + PARAM0 = PARAM1; break; case MAKE_OPCODE_SHORT(OP_RORC, 4, 1): @@ -1203,8 +1470,7 @@ int drcbe_c::execute(code_handle &entry) temp32 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31); else temp32 = PARAM1; - flags = FLAGS32_NZ(temp32); - if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C; + flags = FLAGS32_NZ(temp32) | (((shift != 0) ? (PARAM1 >> (shift - 1)) : flags) & FLAG_C); PARAM0 = temp32; break; @@ -1212,261 +1478,270 @@ int drcbe_c::execute(code_handle &entry) // ----------------------- 64-Bit Integer Operations ----------------------- case MAKE_OPCODE_SHORT(OP_LOAD1, 8, 0): // DLOAD dst,base,index,BYTE - DPARAM0 = inst[1].puint8[PARAM2]; + DPARAM0 = inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x2, 8, 0): // DLOAD dst,base,index,BYTE_x2 - DPARAM0 = *(uint8_t *)&inst[1].puint16[PARAM2]; + DPARAM0 = *(uint8_t *)&inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x4, 8, 0): // DLOAD dst,base,index,BYTE_x4 - DPARAM0 = *(uint8_t *)&inst[1].puint32[PARAM2]; + DPARAM0 = *(uint8_t *)&inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD1x8, 8, 0): // DLOAD dst,base,index,BYTE_x8 - DPARAM0 = *(uint8_t *)&inst[1].puint64[PARAM2]; + DPARAM0 = *(uint8_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x1, 8, 0): // DLOAD dst,base,index,WORD_x1 - DPARAM0 = *(uint16_t *)&inst[1].puint8[PARAM2]; + DPARAM0 = *(uint16_t *)&inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2, 8, 0): // DLOAD dst,base,index,WORD - DPARAM0 = inst[1].puint16[PARAM2]; + DPARAM0 = inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x4, 8, 0): // DLOAD dst,base,index,WORD_x4 - DPARAM0 = *(uint16_t *)&inst[1].puint32[PARAM2]; + DPARAM0 = *(uint16_t *)&inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD2x8, 8, 0): // DLOAD dst,base,index,WORD_x8 - DPARAM0 = *(uint16_t *)&inst[1].puint64[PARAM2]; + DPARAM0 = *(uint16_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x1, 8, 0): // DLOAD dst,base,index,DWORD_x1 - DPARAM0 = *(uint32_t *)&inst[1].puint8[PARAM2]; + DPARAM0 = *(uint32_t *)&inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x2, 8, 0): // DLOAD dst,base,index,DWORD_x2 - DPARAM0 = *(uint32_t *)&inst[1].puint16[PARAM2]; + DPARAM0 = *(uint32_t *)&inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4, 8, 0): // DLOAD dst,base,index,DWORD - DPARAM0 = inst[1].puint32[PARAM2]; + DPARAM0 = inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD4x8, 8, 0): // DLOAD dst,base,index,DWORD_x8 - DPARAM0 = *(uint32_t *)&inst[1].puint64[PARAM2]; + DPARAM0 = *(uint32_t *)&inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD8x1, 8, 0): // DLOAD dst,base,index,QWORD_x1 - DPARAM0 = *(uint64_t *)&inst[1].puint8[PARAM2]; + DPARAM0 = *(uint64_t *)&inst[1].puint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD8x2, 8, 0): // DLOAD dst,base,index,QWORD_x2 - DPARAM0 = *(uint64_t *)&inst[1].puint16[PARAM2]; + DPARAM0 = *(uint64_t *)&inst[1].puint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD8x4, 8, 0): // DLOAD dst,base,index,QWORD_x4 - DPARAM0 = *(uint64_t *)&inst[1].puint32[PARAM2]; + DPARAM0 = *(uint64_t *)&inst[1].puint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOAD8, 8, 0): // DLOAD dst,base,index,QWORD - DPARAM0 = inst[1].puint64[PARAM2]; + DPARAM0 = inst[1].puint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1, 8, 0): // DLOADS dst,base,index,BYTE - DPARAM0 = inst[1].pint8[PARAM2]; + DPARAM0 = inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x2, 8, 0): // DLOADS dst,base,index,BYTE_x2 - DPARAM0 = *(int8_t *)&inst[1].pint16[PARAM2]; + DPARAM0 = *(int8_t *)&inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x4, 8, 0): // DLOADS dst,base,index,BYTE_x4 - DPARAM0 = *(int8_t *)&inst[1].pint32[PARAM2]; + DPARAM0 = *(int8_t *)&inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS1x8, 8, 0): // DLOADS dst,base,index,BYTE_x8 - DPARAM0 = *(int8_t *)&inst[1].pint64[PARAM2]; + DPARAM0 = *(int8_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x1, 8, 0): // DLOADS dst,base,index,WORD_x1 - DPARAM0 = *(int16_t *)&inst[1].pint8[PARAM2]; + DPARAM0 = *(int16_t *)&inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2, 8, 0): // DLOADS dst,base,index,WORD - DPARAM0 = inst[1].pint16[PARAM2]; + DPARAM0 = inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x4, 8, 0): // DLOADS dst,base,index,WORD_x4 - DPARAM0 = *(int16_t *)&inst[1].pint32[PARAM2]; + DPARAM0 = *(int16_t *)&inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS2x8, 8, 0): // DLOADS dst,base,index,WORD_x8 - DPARAM0 = *(int16_t *)&inst[1].pint64[PARAM2]; + DPARAM0 = *(int16_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x1, 8, 0): // DLOADS dst,base,index,DWORD_x1 - DPARAM0 = *(int32_t *)&inst[1].pint8[PARAM2]; + DPARAM0 = *(int32_t *)&inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x2, 8, 0): // DLOADS dst,base,index,DWORD_x2 - DPARAM0 = *(int32_t *)&inst[1].pint16[PARAM2]; + DPARAM0 = *(int32_t *)&inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4, 8, 0): // DLOADS dst,base,index,DWORD - DPARAM0 = inst[1].pint32[PARAM2]; + DPARAM0 = inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS4x8, 8, 0): // DLOADS dst,base,index,DWORD_x8 - DPARAM0 = *(int32_t *)&inst[1].pint64[PARAM2]; + DPARAM0 = *(int32_t *)&inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS8x1, 8, 0): // DLOADS dst,base,index,QWORD_x1 - DPARAM0 = *(int64_t *)&inst[1].pint8[PARAM2]; + DPARAM0 = *(int64_t *)&inst[1].pint8[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS8x2, 8, 0): // DLOADS dst,base,index,QWORD_x2 - DPARAM0 = *(int64_t *)&inst[1].pint16[PARAM2]; + DPARAM0 = *(int64_t *)&inst[1].pint16[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS8x4, 8, 0): // DLOADS dst,base,index,QWORD_x4 - DPARAM0 = *(int64_t *)&inst[1].pint32[PARAM2]; + DPARAM0 = *(int64_t *)&inst[1].pint32[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_LOADS8, 8, 0): // DLOADS dst,base,index,QWORD - DPARAM0 = inst[1].pint64[PARAM2]; + DPARAM0 = inst[1].pint64[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_STORE1, 8, 0): // DSTORE dst,base,index,BYTE - inst[0].puint8[PARAM1] = DPARAM2; + inst[0].puint8[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x2, 8, 0): // DSTORE dst,base,index,BYTE_x2 - *(uint8_t *)&inst[0].puint16[PARAM1] = DPARAM2; + *(uint8_t *)&inst[0].puint16[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x4, 8, 0): // DSTORE dst,base,index,BYTE_x4 - *(uint8_t *)&inst[0].puint32[PARAM1] = DPARAM2; + *(uint8_t *)&inst[0].puint32[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE1x8, 8, 0): // DSTORE dst,base,index,BYTE_x8 - *(uint8_t *)&inst[0].puint64[PARAM1] = DPARAM2; + *(uint8_t *)&inst[0].puint64[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x1, 8, 0): // DSTORE dst,base,index,WORD_x1 - *(uint16_t *)&inst[0].puint8[PARAM1] = DPARAM2; + *(uint16_t *)&inst[0].puint8[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2, 8, 0): // DSTORE dst,base,index,WORD - inst[0].puint16[PARAM1] = DPARAM2; + inst[0].puint16[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x4, 8, 0): // DSTORE dst,base,index,WORD_x4 - *(uint16_t *)&inst[0].puint32[PARAM1] = DPARAM2; + *(uint16_t *)&inst[0].puint32[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE2x8, 8, 0): // DSTORE dst,base,index,WORD_x8 - *(uint16_t *)&inst[0].puint64[PARAM1] = DPARAM2; + *(uint16_t *)&inst[0].puint64[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x1, 8, 0): // DSTORE dst,base,index,DWORD_x1 - *(uint32_t *)&inst[0].puint8[PARAM1] = DPARAM2; + *(uint32_t *)&inst[0].puint8[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x2, 8, 0): // DSTORE dst,base,index,DWORD_x2 - *(uint32_t *)&inst[0].puint16[PARAM1] = DPARAM2; + *(uint32_t *)&inst[0].puint16[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4, 8, 0): // DSTORE dst,base,index,DWORD - inst[0].puint32[PARAM1] = DPARAM2; + inst[0].puint32[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE4x8, 8, 0): // DSTORE dst,base,index,DWORD_x8 - *(uint32_t *)&inst[0].puint64[PARAM1] = DPARAM2; + *(uint32_t *)&inst[0].puint64[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE8x1, 8, 0): // DSTORE dst,base,index,QWORD_x1 - *(uint64_t *)&inst[0].puint8[PARAM1] = DPARAM2; + *(uint64_t *)&inst[0].puint8[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE8x2, 8, 0): // DSTORE dst,base,index,QWORD_x2 - *(uint64_t *)&inst[0].puint16[PARAM1] = DPARAM2; + *(uint64_t *)&inst[0].puint16[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE8x4, 8, 0): // DSTORE dst,base,index,QWORD_x4 - *(uint64_t *)&inst[0].puint32[PARAM1] = DPARAM2; + *(uint64_t *)&inst[0].puint32[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_STORE8, 8, 0): // DSTORE dst,base,index,QWORD - inst[0].puint64[PARAM1] = DPARAM2; + inst[0].puint64[SPARAM1] = DPARAM2; break; case MAKE_OPCODE_SHORT(OP_READ1, 8, 0): // DREAD dst,src1,space_BYTE - DPARAM0 = m_space[PARAM2]->read_byte(PARAM1); + DPARAM0 = SPACEPARAM2.read_byte(PARAM1); break; case MAKE_OPCODE_SHORT(OP_READ2, 8, 0): // DREAD dst,src1,space_WORD - DPARAM0 = m_space[PARAM2]->read_word(PARAM1); + DPARAM0 = SPACEPARAM2.read_word(PARAM1); break; case MAKE_OPCODE_SHORT(OP_READ4, 8, 0): // DREAD dst,src1,space_DWORD - DPARAM0 = m_space[PARAM2]->read_dword(PARAM1); + DPARAM0 = SPACEPARAM2.read_dword(PARAM1); + break; + + case MAKE_OPCODE_SHORT(OP_READ8, 8, 0): // DREAD dst,src1,space_QWORD + DPARAM0 = SPACEPARAM2.read_qword(PARAM1); break; - case MAKE_OPCODE_SHORT(OP_READ8, 8, 0): // DREAD dst,src1,space_QOWRD - DPARAM0 = m_space[PARAM2]->read_qword(PARAM1); + case MAKE_OPCODE_SHORT(OP_READM1, 8, 0): // DREADM dst,src1,mask,space_BYTE + DPARAM0 = SPACEPARAM3.read_byte(PARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_READM2, 8, 0): // DREADM dst,src1,mask,space_WORD - DPARAM0 = m_space[PARAM3]->read_word(PARAM1, PARAM2); + DPARAM0 = SPACEPARAM3.read_word(PARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_READM4, 8, 0): // DREADM dst,src1,mask,space_DWORD - DPARAM0 = m_space[PARAM3]->read_dword(PARAM1, PARAM2); + DPARAM0 = SPACEPARAM3.read_dword(PARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_READM8, 8, 0): // DREADM dst,src1,mask,space_QWORD - DPARAM0 = m_space[PARAM3]->read_qword(PARAM1, PARAM2); + DPARAM0 = SPACEPARAM3.read_qword(PARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITE1, 8, 0): // DWRITE dst,src1,space_BYTE - m_space[PARAM2]->write_byte(PARAM0, PARAM1); + SPACEPARAM2.write_byte(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_WRITE2, 8, 0): // DWRITE dst,src1,space_WORD - m_space[PARAM2]->write_word(PARAM0, PARAM1); + SPACEPARAM2.write_word(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_WRITE4, 8, 0): // DWRITE dst,src1,space_DWORD - m_space[PARAM2]->write_dword(PARAM0, PARAM1); + SPACEPARAM2.write_dword(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_WRITE8, 8, 0): // DWRITE dst,src1,space_QWORD - m_space[PARAM2]->write_qword(PARAM0, DPARAM1); + SPACEPARAM2.write_qword(PARAM0, DPARAM1); + break; + + case MAKE_OPCODE_SHORT(OP_WRITEM1, 8, 0): // DWRITEM dst,src1,mask,space_BYTE + SPACEPARAM3.write_byte(PARAM0, DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITEM2, 8, 0): // DWRITEM dst,src1,mask,space_WORD - m_space[PARAM3]->write_word(PARAM0, DPARAM1, DPARAM2); + SPACEPARAM3.write_word(PARAM0, DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITEM4, 8, 0): // DWRITEM dst,src1,mask,space_DWORD - m_space[PARAM3]->write_dword(PARAM0, DPARAM1, DPARAM2); + SPACEPARAM3.write_dword(PARAM0, DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_WRITEM8, 8, 0): // DWRITEM dst,src1,mask,space_QWORD - m_space[PARAM3]->write_qword(PARAM0, DPARAM1, DPARAM2); + SPACEPARAM3.write_qword(PARAM0, DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_CARRY, 8, 0): // DCARRY src,bitnum + case MAKE_OPCODE_SHORT(OP_CARRY, 8, 1): flags = (flags & ~FLAG_C) | ((DPARAM0 >> (DPARAM1 & 63)) & FLAG_C); break; case MAKE_OPCODE_SHORT(OP_MOV, 8, 1): // DMOV dst,src[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_MOV, 8, 0): DPARAM0 = DPARAM1; @@ -1507,25 +1782,21 @@ int drcbe_c::execute(code_handle &entry) break; case MAKE_OPCODE_SHORT(OP_ROLAND, 8, 0): // DROLAND dst,src,count,mask[,f] - shift = DPARAM2 & 63; - DPARAM0 = ((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3; + DPARAM0 = rotl_64(DPARAM1, DPARAM2) & DPARAM3; break; case MAKE_OPCODE_SHORT(OP_ROLAND, 8, 1): - shift = DPARAM2 & 63; - temp64 = ((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3; + temp64 = rotl_64(DPARAM1, DPARAM2) & DPARAM3; flags = FLAGS64_NZ(temp64); DPARAM0 = temp64; break; case MAKE_OPCODE_SHORT(OP_ROLINS, 8, 0): // DROLINS dst,src,count,mask[,f] - shift = DPARAM2 & 63; - DPARAM0 = (DPARAM0 & ~DPARAM3) | (((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3); + DPARAM0 = (DPARAM0 & ~DPARAM3) | (rotl_64(DPARAM1, DPARAM2) & DPARAM3); break; case MAKE_OPCODE_SHORT(OP_ROLINS, 8, 1): - shift = DPARAM2 & 63; - temp64 = (DPARAM0 & ~DPARAM3) | (((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3); + temp64 = (DPARAM0 & ~DPARAM3) | (rotl_64(DPARAM1, DPARAM2) & DPARAM3); flags = FLAGS64_NZ(temp64); DPARAM0 = temp64; break; @@ -1569,10 +1840,7 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SUBB, 8, 1): temp64 = DPARAM1 - DPARAM2 - (flags & FLAG_C); - if (DPARAM2 + 1 != 0) - flags = FLAGS64_NZCV_SUB(temp64, DPARAM1, DPARAM2 + (flags & FLAG_C)); - else - flags = FLAGS64_NZCV_SUB(temp64, DPARAM1 - (flags & FLAG_C), DPARAM2); + flags = FLAGS64_NZCV_SUBC(temp64, DPARAM1, DPARAM2, flags & FLAG_C); DPARAM0 = temp64; break; @@ -1589,6 +1857,15 @@ int drcbe_c::execute(code_handle &entry) flags = dmulu(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, true); break; + case MAKE_OPCODE_SHORT(OP_MULULW, 8, 0): // DMULULW dst,src1,src2[,f] + dmulu(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, false); + break; + + case MAKE_OPCODE_SHORT(OP_MULULW, 8, 1): + flags = dmulu(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, true); + flags = FLAGS64_NZ(DPARAM0) | (flags & FLAG_V); + break; + case MAKE_OPCODE_SHORT(OP_MULS, 8, 0): // DMULS dst,edst,src1,src2[,f] dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, false); break; @@ -1597,6 +1874,15 @@ int drcbe_c::execute(code_handle &entry) flags = dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, true); break; + case MAKE_OPCODE_SHORT(OP_MULSLW, 8, 0): // DMULSLW dst,src1,src2[,f] + dmuls(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, false); + break; + + case MAKE_OPCODE_SHORT(OP_MULSLW, 8, 1): + flags = dmuls(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, true); + flags = FLAGS64_NZ(DPARAM0) | (flags & FLAG_V); + break; + case MAKE_OPCODE_SHORT(OP_DIVU, 8, 0): // DDIVU dst,edst,src1,src2[,f] if (DPARAM3 != 0) { @@ -1649,8 +1935,11 @@ int drcbe_c::execute(code_handle &entry) DPARAM0 = temp64; break; - case MAKE_OPCODE_SHORT(OP_TEST, 8, 1): // DTEST src1,src2[,f] - temp64 = DPARAM1 & DPARAM2; + case MAKE_OPCODE_SHORT(OP_TEST, 8, 0): // DTEST src1,src2[,f] + break; + + case MAKE_OPCODE_SHORT(OP_TEST, 8, 1): + temp64 = DPARAM0 & DPARAM1; flags = FLAGS64_NZ(temp64); break; @@ -1675,17 +1964,11 @@ int drcbe_c::execute(code_handle &entry) break; case MAKE_OPCODE_SHORT(OP_LZCNT, 8, 0): // DLZCNT dst,src - if ((uint32_t)(DPARAM1 >> 32) != 0) - DPARAM0 = count_leading_zeros(DPARAM1 >> 32); - else - DPARAM0 = 32 + count_leading_zeros(DPARAM1); + DPARAM0 = count_leading_zeros_64(DPARAM1); break; case MAKE_OPCODE_SHORT(OP_LZCNT, 8, 1): - if ((uint32_t)(DPARAM1 >> 32) != 0) - temp64 = count_leading_zeros(DPARAM1 >> 32); - else - temp64 = 32 + count_leading_zeros(DPARAM1); + temp64 = count_leading_zeros_64(DPARAM1); flags = FLAGS64_NZ(temp64); DPARAM0 = temp64; break; @@ -1707,8 +1990,8 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_BSWAP, 8, 1): temp64 = DPARAM1; - flags = FLAGS64_NZ(temp64); DPARAM0 = swapendian_int64(temp64); + flags = FLAGS64_NZ(DPARAM0); break; case MAKE_OPCODE_SHORT(OP_SHL, 8, 0): // DSHL dst,src,count[,f] @@ -1719,7 +2002,8 @@ int drcbe_c::execute(code_handle &entry) shift = DPARAM2 & 63; temp64 = DPARAM1 << shift; flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C; + if (shift != 0) + flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C; DPARAM0 = temp64; break; @@ -1731,7 +2015,8 @@ int drcbe_c::execute(code_handle &entry) shift = DPARAM2 & 63; temp64 = DPARAM1 >> shift; flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; + if (shift != 0) + flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; DPARAM0 = temp64; break; @@ -1741,22 +2026,23 @@ int drcbe_c::execute(code_handle &entry) case MAKE_OPCODE_SHORT(OP_SAR, 8, 1): shift = DPARAM2 & 63; - temp64 = (int32_t)DPARAM1 >> shift; + temp64 = (int64_t)DPARAM1 >> shift; flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; + if (shift != 0) + flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; DPARAM0 = temp64; break; case MAKE_OPCODE_SHORT(OP_ROL, 8, 0): // DROL dst,src,count[,f] - shift = DPARAM2 & 63; - DPARAM0 = (DPARAM1 << shift) | (DPARAM1 >> ((64 - shift) & 63)); + DPARAM0 = rotl_64(DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_ROL, 8, 1): shift = DPARAM2 & 63; - temp64 = (DPARAM1 << shift) | (DPARAM1 >> ((64 - shift) & 63)); + temp64 = rotl_64(DPARAM1, shift); flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C; + if (shift != 0) + flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C; DPARAM0 = temp64; break; @@ -1766,6 +2052,8 @@ int drcbe_c::execute(code_handle &entry) DPARAM0 = (DPARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (DPARAM1 >> (65 - shift)); else if (shift == 1) DPARAM0 = (DPARAM1 << shift) | (flags & FLAG_C); + else + DPARAM0 = DPARAM1; break; case MAKE_OPCODE_SHORT(OP_ROLC, 8, 1): @@ -1776,21 +2064,20 @@ int drcbe_c::execute(code_handle &entry) temp64 = (DPARAM1 << shift) | (flags & FLAG_C); else temp64 = DPARAM1; - flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C; + flags = FLAGS64_NZ(temp64) | (((shift != 0) ? (DPARAM1 >> (64 - shift)) : flags) & FLAG_C); DPARAM0 = temp64; break; case MAKE_OPCODE_SHORT(OP_ROR, 8, 0): // DROR dst,src,count[,f] - shift = DPARAM2 & 63; - DPARAM0 = (DPARAM1 >> shift) | (DPARAM1 << ((64 - shift) & 63)); + DPARAM0 = rotr_64(DPARAM1, DPARAM2); break; case MAKE_OPCODE_SHORT(OP_ROR, 8, 1): shift = DPARAM2 & 63; - temp64 = (DPARAM1 >> shift) | (DPARAM1 << ((64 - shift) & 63)); + temp64 = rotr_64(DPARAM1, shift); flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; + if (shift != 0) + flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; DPARAM0 = temp64; break; @@ -1800,6 +2087,8 @@ int drcbe_c::execute(code_handle &entry) DPARAM0 = (DPARAM1 >> shift) | ((((uint64_t)flags & FLAG_C) << 63) >> (shift - 1)) | (DPARAM1 << (65 - shift)); else if (shift == 1) DPARAM0 = (DPARAM1 >> shift) | (((uint64_t)flags & FLAG_C) << 63); + else + DPARAM0 = DPARAM1; break; case MAKE_OPCODE_SHORT(OP_RORC, 8, 1): @@ -1810,8 +2099,7 @@ int drcbe_c::execute(code_handle &entry) temp64 = (DPARAM1 >> shift) | (((uint64_t)flags & FLAG_C) << 63); else temp64 = DPARAM1; - flags = FLAGS64_NZ(temp64); - if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C; + flags = FLAGS64_NZ(temp64) | (((shift != 0) ? (DPARAM1 >> (shift - 1)) : flags) & FLAG_C); DPARAM0 = temp64; break; @@ -1819,28 +2107,28 @@ int drcbe_c::execute(code_handle &entry) // ----------------------- 32-Bit Floating Point Operations ----------------------- case MAKE_OPCODE_SHORT(OP_FLOAD, 4, 0): // FSLOAD dst,base,index - FSPARAM0 = inst[1].pfloat[PARAM2]; + FSPARAM0 = inst[1].pfloat[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_FSTORE, 4, 0): // FSSTORE dst,base,index - inst[0].pfloat[PARAM1] = FSPARAM2; + inst[0].pfloat[SPARAM1] = FSPARAM2; break; case MAKE_OPCODE_SHORT(OP_FREAD, 4, 0): // FSREAD dst,src1,space - PARAM0 = m_space[PARAM2]->read_dword(PARAM1); + PARAM0 = SPACEPARAM2.read_dword(PARAM1); break; case MAKE_OPCODE_SHORT(OP_FWRITE, 4, 0): // FSWRITE dst,src1,space - m_space[PARAM2]->write_dword(PARAM0, PARAM1); + SPACEPARAM2.write_dword(PARAM0, PARAM1); break; case MAKE_OPCODE_SHORT(OP_FMOV, 4, 1): // FSMOV dst,src[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_FMOV, 4, 0): - FSPARAM0 = FSPARAM1; + PARAM0 = PARAM1; break; case MAKE_OPCODE_SHORT(OP_FTOI4T, 4, 0): // FSTOI4T dst,src1 @@ -1962,28 +2250,28 @@ int drcbe_c::execute(code_handle &entry) // ----------------------- 64-Bit Floating Point Operations ----------------------- case MAKE_OPCODE_SHORT(OP_FLOAD, 8, 0): // FDLOAD dst,base,index - FDPARAM0 = inst[1].pdouble[PARAM2]; + FDPARAM0 = inst[1].pdouble[SPARAM2]; break; case MAKE_OPCODE_SHORT(OP_FSTORE, 8, 0): // FDSTORE dst,base,index - inst[0].pdouble[PARAM1] = FDPARAM2; + inst[0].pdouble[SPARAM1] = FDPARAM2; break; case MAKE_OPCODE_SHORT(OP_FREAD, 8, 0): // FDREAD dst,src1,space - DPARAM0 = m_space[PARAM2]->read_qword(PARAM1); + DPARAM0 = SPACEPARAM2.read_qword(PARAM1); break; case MAKE_OPCODE_SHORT(OP_FWRITE, 8, 0): // FDWRITE dst,src1,space - m_space[PARAM2]->write_qword(PARAM0, DPARAM1); + SPACEPARAM2.write_qword(PARAM0, DPARAM1); break; case MAKE_OPCODE_SHORT(OP_FMOV, 8, 1): // FDMOV dst,src[,c] if (OPCODE_FAIL_CONDITION(opcode, flags)) break; - // fall through... + [[fallthrough]]; case MAKE_OPCODE_SHORT(OP_FMOV, 8, 0): - FDPARAM0 = FDPARAM1; + DPARAM0 = DPARAM1; break; case MAKE_OPCODE_SHORT(OP_FTOI4T, 8, 0): // FDTOI4T dst,src1 @@ -2106,7 +2394,7 @@ int drcbe_c::execute(code_handle &entry) break; default: - fatalerror("Unexpected opcode!\n"); + fatalerror("Unexpected opcode! %08x %d %d %d\n", opcode, OPCODE_GET_SHORT(opcode) >> 2, BIT(opcode, 0) ? 8 : 4, BIT(opcode, 1)); } // advance past the parameters and immediates @@ -2122,26 +2410,27 @@ int drcbe_c::execute(code_handle &entry) // output_parameter - output a parameter //------------------------------------------------- -void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int size, const parameter ¶m) +void drcbe_c::output_parameter(drcbec_instruction **dstptr, void *immed, int immoffset, int size, const parameter ¶m) { drcbec_instruction *dst = *dstptr; - void *immed = *immedptr; - parameter temp_param; switch (param.type()) { // immediates store a pointer to the immediate data, which is stored at the end of the instruction case parameter::PTYPE_IMMEDIATE: if (param.immediate() == 0) + { (dst++)->v = &s_immediate_zero; + } else { - (dst++)->v = immed; + assert(immoffset >= 0); + auto const thisimmed = reinterpret_cast<uint8_t *>(immed) + immoffset; + (dst++)->v = thisimmed; if (size == 4) - *(uint32_t *)immed = (uint32_t)param.immediate(); + *(uint32_t *)thisimmed = (uint32_t)param.immediate(); else - *(uint64_t *)immed = (uint64_t)param.immediate(); - immed = (uint8_t *)immed + size; + *(uint64_t *)thisimmed = (uint64_t)param.immediate(); } break; @@ -2163,8 +2452,7 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int // convert mapvars to immediates case parameter::PTYPE_MAPVAR: - temp_param = m_map.get_last_value(param.mapvar()); - return output_parameter(dstptr, immedptr, size, temp_param); + return output_parameter(dstptr, immed, immoffset, size, param.mapvar()); // memory just points to the memory case parameter::PTYPE_MEMORY: @@ -2176,11 +2464,12 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int case parameter::PTYPE_SIZE_SCALE: case parameter::PTYPE_ROUNDING: case parameter::PTYPE_STRING: - return output_parameter(dstptr, immedptr, size, 0); + return output_parameter(dstptr, immed, immoffset, size, 0); // space/size parameters; sizes are built into our opcodes, but space needs to be encoded case parameter::PTYPE_SIZE_SPACE: - return output_parameter(dstptr, immedptr, size, param.space()); + (dst++)->space = m_space[param.space()]; + break; // code handle just points to the handle case parameter::PTYPE_CODE_HANDLE: @@ -2189,7 +2478,7 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int // code label just contains the label value case parameter::PTYPE_CODE_LABEL: - return output_parameter(dstptr, immedptr, size, uint32_t(param.label())); + return output_parameter(dstptr, immed, immoffset, size, uint32_t(param.label())); // c_function just points to the C function case parameter::PTYPE_C_FUNCTION: @@ -2201,7 +2490,6 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int } *dstptr = dst; - *immedptr = immed; } @@ -2216,117 +2504,19 @@ void drcbe_c::fixup_label(void *parameter, drccodeptr labelcodeptr) dst->inst = (drcbec_instruction *)labelcodeptr; } +} // anonymous namespace -//------------------------------------------------- -// dmulu - perform a double-wide unsigned multiply -//------------------------------------------------- - -int drcbe_c::dmulu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src2, bool flags) -{ - // shortcut if we don't care about the high bits or the flags - if (&dstlo == &dsthi && flags == false) - { - dstlo = src1 * src2; - return 0; - } - - // fetch source values - uint64_t a = src1; - uint64_t b = src2; - if (a == 0 || b == 0) - { - dsthi = dstlo = 0; - return FLAG_Z; - } - - // compute high and low parts first - uint64_t lo = (uint64_t)(uint32_t)(a >> 0) * (uint64_t)(uint32_t)(b >> 0); - uint64_t hi = (uint64_t)(uint32_t)(a >> 32) * (uint64_t)(uint32_t)(b >> 32); - - // compute middle parts - uint64_t prevlo = lo; - uint64_t temp = (uint64_t)(uint32_t)(a >> 32) * (uint64_t)(uint32_t)(b >> 0); - lo += temp << 32; - hi += (temp >> 32) + (lo < prevlo); - - prevlo = lo; - temp = (uint64_t)(uint32_t)(a >> 0) * (uint64_t)(uint32_t)(b >> 32); - lo += temp << 32; - hi += (temp >> 32) + (lo < prevlo); - - // store the results - dsthi = hi; - dstlo = lo; - return ((hi >> 60) & FLAG_S) | ((dsthi != 0) << 1); -} - - -//------------------------------------------------- -// dmuls - perform a double-wide signed multiply -//------------------------------------------------- - -int drcbe_c::dmuls(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2, bool flags) -{ - // shortcut if we don't care about the high bits or the flags - if (&dstlo == &dsthi && flags == false) - { - dstlo = src1 * src2; - return 0; - } - - // fetch absolute source values - uint64_t a = src1; if ((int64_t)a < 0) a = -a; - uint64_t b = src2; if ((int64_t)b < 0) b = -b; - if (a == 0 || b == 0) - { - dsthi = dstlo = 0; - return FLAG_Z; - } - - // compute high and low parts first - uint64_t lo = (uint64_t)(uint32_t)(a >> 0) * (uint64_t)(uint32_t)(b >> 0); - uint64_t hi = (uint64_t)(uint32_t)(a >> 32) * (uint64_t)(uint32_t)(b >> 32); - // compute middle parts - uint64_t prevlo = lo; - uint64_t temp = (uint64_t)(uint32_t)(a >> 32) * (uint64_t)(uint32_t)(b >> 0); - lo += temp << 32; - hi += (temp >> 32) + (lo < prevlo); - - prevlo = lo; - temp = (uint64_t)(uint32_t)(a >> 0) * (uint64_t)(uint32_t)(b >> 32); - lo += temp << 32; - hi += (temp >> 32) + (lo < prevlo); - - // adjust for signage - if ((int64_t)(src1 ^ src2) < 0) - { - hi = ~hi + (lo == 0); - lo = ~lo + 1; - } - - // store the results - dsthi = hi; - dstlo = lo; - return ((hi >> 60) & FLAG_S) | ((dsthi != ((int64_t)lo >> 63)) << 1); -} - -uint32_t drcbe_c::tzcount32(uint32_t value) +std::unique_ptr<drcbe_interface> make_drcbe_c( + drcuml_state &drcuml, + device_t &device, + drc_cache &cache, + uint32_t flags, + int modes, + int addrbits, + int ignorebits) { - for (int i = 0; i < 32; i++) - { - if (value & (1 << i)) - return i; - } - return 32; + return std::unique_ptr<drcbe_interface>(new drcbe_c(drcuml, device, cache, flags, modes, addrbits, ignorebits)); } -uint64_t drcbe_c::tzcount64(uint64_t value) -{ - for (int i = 0; i < 64; i++) - { - if (value & ((uint64_t)(1) << i)) - return i; - } - return 64; -} +} // namespace drc |