diff options
author | 2025-04-12 13:22:51 +1000 | |
---|---|---|
committer | 2025-04-12 13:25:58 +1000 | |
commit | de4064155569540b15c1f56bd99c2ceae54fa44f (patch) | |
tree | 1acf2bc767923b8a923924c91099f69be0c9a11f | |
parent | 2f93065a39cdc17e3b8d64e1cb7c7a543e704d2e (diff) |
More recompiler fixes:
* cpu/drcbec.cpp: Interpret index operand for load/store instructions as
a signed value for consistency with other back-ends.
* cpu/drcbec.cpp: Honour alignment rules when packing immediate values.
* cpu/drcbex64.cpp: Don't special-case SEXT with an immediate source -
the simplifier takes care of this.
* cpu/drcbex86.cpp: Be explicit about preserving flags in load/store
instructions.
* docs: Added a couple more UML data movement instructions.
-rw-r--r-- | docs/source/techspecs/uml_instructions.rst | 82 | ||||
-rw-r--r-- | src/devices/cpu/drcbearm64.cpp | 1 | ||||
-rw-r--r-- | src/devices/cpu/drcbec.cpp | 260 | ||||
-rw-r--r-- | src/devices/cpu/drcbex64.cpp | 42 | ||||
-rw-r--r-- | src/devices/cpu/drcbex86.cpp | 28 |
5 files changed, 248 insertions, 165 deletions
diff --git a/docs/source/techspecs/uml_instructions.rst b/docs/source/techspecs/uml_instructions.rst index 771ff64974d..5d379dd1c60 100644 --- a/docs/source/techspecs/uml_instructions.rst +++ b/docs/source/techspecs/uml_instructions.rst @@ -751,6 +751,88 @@ Simplification rules * Converted to :ref:`NOP <umlinst-nop>` if the ``src`` and ``dst`` operands refer to the same memory location or register. +.. _umlinst-fcopyi: + +FCOPYI +~~~~~~ + +Reinterpret an integer value as a floating point value. The binary +value will be preserved even if it is not a valid representation of a +floating point number. + ++---------------------+-----------------------------------+ +| Disassembly | Usage | ++=====================+===================================+ +| .. code-block:: | .. code-block:: C++ | +| | | +| fscopyi dst,src | UML_FSCOPYI(block, dst, src); | +| fdcopyi dst,src | UML_FDCOPYI(block, dst, src); | ++---------------------+-----------------------------------+ + +Operands +^^^^^^^^ + +dst (32-bit or 64-bit – memory, floating point register) + The destination where the value will be copied to. +src (32-bit or 64-bit – memory, integer register) + The source value to copy. + +Flags +^^^^^ + ++---------------+------------+ +| carry (C) | Unchanged. | ++---------------+------------+ +| overflow (V) | Unchanged. | ++---------------+------------+ +| zero (Z) | Unchanged. | ++---------------+------------+ +| sign (S) | Unchanged. | ++---------------+------------+ +| unordered (U) | Unchanged. | ++---------------+------------+ + +.. _umlinst-icopyf: + +ICOPYF +~~~~~~ + +Reinterpret a floating point value as an integer value. The binary +value will be preserved even if it is not a valid representation of a +floating point number. + ++---------------------+-----------------------------------+ +| Disassembly | Usage | ++=====================+===================================+ +| .. code-block:: | .. code-block:: C++ | +| | | +| icopyfs dst,src | UML_ICOPYFS(block, dst, src); | +| icopyfd dst,src | UML_ICOPYFD(block, dst, src); | ++---------------------+-----------------------------------+ + +Operands +^^^^^^^^ + +dst (32-bit or 64-bit – memory, integer register) + The destination where the value will be copied to. +src (32-bit or 64-bit – memory, floating point register) + The source value to copy. + +Flags +^^^^^ + ++---------------+------------+ +| carry (C) | Unchanged. | ++---------------+------------+ +| overflow (V) | Unchanged. | ++---------------+------------+ +| zero (Z) | Unchanged. | ++---------------+------------+ +| sign (S) | Unchanged. | ++---------------+------------+ +| unordered (U) | Unchanged. | ++---------------+------------+ + .. _umlinst-load: LOAD diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp index f323396729a..a8a679c3d07 100644 --- a/src/devices/cpu/drcbearm64.cpp +++ b/src/devices/cpu/drcbearm64.cpp @@ -3089,6 +3089,7 @@ void drcbe_arm64::op_sext(a64::Assembler &a, const uml::instruction &inst) { if (srcp.is_memory()) { + // FIXME: need to mangle addresses for big Endian hosts if (size == SIZE_BYTE) emit_ldrsb_mem(a, dstreg.x(), srcp.memory()); else if (size == SIZE_WORD) diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp index 757ba9b28e9..7b2b9818db2 100644 --- a/src/devices/cpu/drcbec.cpp +++ b/src/devices/cpu/drcbec.cpp @@ -171,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) @@ -373,7 +378,7 @@ public: private: // helpers - void output_parameter(drcbec_instruction **dstptr, void **immedptr, int size, const uml::parameter ¶m); + 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 @@ -516,6 +521,7 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ { 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(); @@ -581,35 +587,49 @@ 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)) || + (param.is_size_space() && (param.space() != 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); @@ -622,7 +642,7 @@ 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; @@ -640,9 +660,9 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ immed = dst + 3; - output_parameter(&dst, &immed, 8, inst.param(pnum)); - output_parameter(&dst, &immed, 8, inst.param(pnum)); - output_parameter(&dst, &immed, 8, 0xffffffff); + 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; @@ -655,9 +675,7 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_ 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; - } } } @@ -869,147 +887,147 @@ 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 @@ -1172,7 +1190,6 @@ int drcbe_c::execute(code_handle &entry) 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] @@ -1454,195 +1471,195 @@ 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 @@ -2072,11 +2089,11 @@ 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 @@ -2215,11 +2232,11 @@ 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 @@ -2375,25 +2392,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; 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; @@ -2415,7 +2434,7 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int // convert mapvars to immediates case parameter::PTYPE_MAPVAR: - return output_parameter(dstptr, immedptr, size, param.mapvar()); + return output_parameter(dstptr, immed, immoffset, size, param.mapvar()); // memory just points to the memory case parameter::PTYPE_MEMORY: @@ -2427,11 +2446,11 @@ 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()); + return output_parameter(dstptr, immed, immoffset, size, param.space()); // code handle just points to the handle case parameter::PTYPE_CODE_HANDLE: @@ -2440,7 +2459,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: @@ -2452,7 +2471,6 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int } *dstptr = dst; - *immedptr = immed; } diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index 7b870ece35a..b3c51da2a01 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -3744,23 +3744,16 @@ void drcbe_x64::op_sext(Assembler &a, const instruction &inst) else if (sizep.size() == SIZE_DWORD) a.mov(dstreg, MABS(srcp.memory())); } - else if (srcp.is_int_register()) - { - if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, GpbLo(srcp.ireg())); - else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, Gpw(srcp.ireg())); - else if (sizep.size() == SIZE_DWORD) - a.mov(dstreg, Gpd(srcp.ireg())); - } - else if (srcp.is_immediate()) + else { + Gp const srcreg = srcp.select_register(dstreg); + mov_reg_param(a, srcreg, srcp); if (sizep.size() == SIZE_BYTE) - a.mov(dstreg, int32_t(int8_t(uint8_t(srcp.immediate())))); + a.movsx(dstreg, srcreg.r8()); else if (sizep.size() == SIZE_WORD) - a.mov(dstreg, int32_t(int16_t(uint16_t(srcp.immediate())))); + a.movsx(dstreg, srcreg.r16()); else if (sizep.size() == SIZE_DWORD) - a.mov(dstreg, int32_t(uint32_t(srcp.immediate()))); + a.mov(dstreg, srcreg); } mov_param_reg(a, dstp, dstreg); @@ -3779,27 +3772,18 @@ void drcbe_x64::op_sext(Assembler &a, const instruction &inst) else if (sizep.size() == SIZE_QWORD) a.mov(dstreg, MABS(srcp.memory())); } - else if (srcp.is_int_register()) - { - if (sizep.size() == SIZE_BYTE) - a.movsx(dstreg, GpbLo(srcp.ireg())); - else if (sizep.size() == SIZE_WORD) - a.movsx(dstreg, Gpw(srcp.ireg())); - else if (sizep.size() == SIZE_DWORD) - a.movsxd(dstreg, Gpd(srcp.ireg())); - else if (sizep.size() == SIZE_QWORD) - a.mov(dstreg, Gpq(srcp.ireg())); - } - else if (srcp.is_immediate()) + else { + Gp const srcreg = srcp.select_register(dstreg); + mov_reg_param(a, srcreg, srcp); if (sizep.size() == SIZE_BYTE) - a.mov(dstreg, int64_t(int8_t(uint8_t(srcp.immediate())))); + a.movsx(dstreg, srcreg.r8()); else if (sizep.size() == SIZE_WORD) - a.mov(dstreg, int64_t(int16_t(uint16_t(srcp.immediate())))); + a.movsx(dstreg, srcreg.r16()); else if (sizep.size() == SIZE_DWORD) - a.mov(dstreg, int64_t(int32_t(uint32_t(srcp.immediate())))); + a.movsxd(dstreg, srcreg.r32()); else if (sizep.size() == SIZE_QWORD) - a.mov(dstreg, int64_t(srcp.immediate())); + a.mov(dstreg, srcreg); } mov_param_reg(a, dstp, dstreg); diff --git a/src/devices/cpu/drcbex86.cpp b/src/devices/cpu/drcbex86.cpp index 24de0549334..43f4c69b233 100644 --- a/src/devices/cpu/drcbex86.cpp +++ b/src/devices/cpu/drcbex86.cpp @@ -3659,7 +3659,7 @@ void drcbe_x86::op_load(Assembler &a, const instruction &inst) { // other index Gp const indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); + emit_mov_r32_p32_keepflags(a, indreg, indp); if (size == SIZE_BYTE) a.movzx(dstreg, ptr(uintptr_t(basep.memory()), indreg, scalesizep.scale(), 1)); // movzx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) @@ -3679,18 +3679,17 @@ void drcbe_x86::op_load(Assembler &a, const instruction &inst) // 64-bit form stores upper 32 bits if (inst.size() == 8) { - // 1, 2, or 4-byte case if (size != SIZE_QWORD) { + // 1, 2, or 4-byte case if (dstp.is_memory()) a.mov(MABS(dstp.memory(4), 4), 0); // mov [dstp+4],0 else if (dstp.is_int_register()) a.mov(MABS(m_reghi[dstp.ireg()], 4), 0); // mov [reghi],0 } - - // 8-byte case else { + // 8-byte case if (dstp.is_memory()) a.mov(MABS(dstp.memory(4)), edx); // mov [dstp+4],edx else if (dstp.is_int_register()) @@ -3745,7 +3744,7 @@ void drcbe_x86::op_loads(Assembler &a, const instruction &inst) { // other index Gp const indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); + emit_mov_r32_p32_keepflags(a, indreg, indp); if (size == SIZE_BYTE) a.movsx(dstreg, ptr(uintptr_t(basep.memory()), indreg, scalesizep.scale(), 1)); // movsx dstreg,[basep + scale*indp] else if (size == SIZE_WORD) @@ -3829,9 +3828,9 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst) { // variable source if (size != SIZE_QWORD) - emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp + emit_mov_r32_p32_keepflags(a, srcreg, srcp); // mov srcreg,srcp else - emit_mov_r64_p64(a, srcreg, edx, srcp); // mov edx:srcreg,srcp + emit_mov_r64_p64_keepflags(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 @@ -3850,7 +3849,7 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst) { // normal case: variable index Gp const indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); // mov indreg,indp + emit_mov_r32_p32_keepflags(a, indreg, indp); // mov indreg,indp if (srcp.is_immediate()) { @@ -3872,9 +3871,9 @@ void drcbe_x86::op_store(Assembler &a, const instruction &inst) { // variable source if (size != SIZE_QWORD) - emit_mov_r32_p32(a, srcreg, srcp); // mov srcreg,srcp + emit_mov_r32_p32_keepflags(a, srcreg, srcp); // mov srcreg,srcp else - emit_mov_r64_p64(a, srcreg, edx, srcp); // mov edx:srcreg,srcp + emit_mov_r64_p64_keepflags(a, srcreg, edx, srcp); // mov edx:srcreg,srcp if (size == SIZE_BYTE) a.mov(ptr(uintptr_t(basep.memory()), indreg, scalesizep.scale()), srcreg.r8()); // mov [basep + 1*ecx],srcreg else if (size == SIZE_WORD) @@ -6534,19 +6533,18 @@ void drcbe_x86::op_fload(Assembler &a, const instruction &inst) be_parameter basep(*this, inst.param(1), PTYPE_M); be_parameter indp(*this, inst.param(2), PTYPE_MRI); - // immediate index if (indp.is_immediate()) { + // immediate index a.mov(eax, MABS(basep.memory(inst.size()*indp.immediate()))); if (inst.size() == 8) a.mov(edx, MABS(basep.memory(4 + inst.size()*indp.immediate()))); } - - // other index else { + // other index Gp const indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); + emit_mov_r32_p32_keepflags(a, indreg, indp); a.mov(eax, ptr(uintptr_t(basep.memory(0)), indreg, (inst.size() == 8) ? 3 : 2)); if (inst.size() == 8) a.mov(edx, ptr(uintptr_t(basep.memory(4)), indreg, (inst.size() == 8) ? 3 : 2)); @@ -6590,7 +6588,7 @@ void drcbe_x86::op_fstore(Assembler &a, const instruction &inst) { // other index Gp const indreg = indp.select_register(ecx); - emit_mov_r32_p32(a, indreg, indp); + emit_mov_r32_p32_keepflags(a, indreg, indp); a.mov(ptr(uintptr_t(basep.memory(0)), indreg, (inst.size() == 8) ? 3 : 2), eax); if (inst.size() == 8) a.mov(ptr(uintptr_t(basep.memory(4)), indreg, (inst.size() == 8) ? 3 : 2), edx); |