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.
This commit is contained in:
Vas Crabb 2025-04-12 13:22:51 +10:00
parent 2f93065a39
commit de40641555
5 changed files with 248 additions and 165 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 &param);
void output_parameter(drcbec_instruction **dstptr, void *immed, int immoffset, int size, const uml::parameter &param);
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 &param = 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 &param)
void drcbe_c::output_parameter(drcbec_instruction **dstptr, void *immed, int immoffset, int size, const parameter &param)
{
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;
}

View File

@ -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())
else
{
Gp const srcreg = srcp.select_register(dstreg);
mov_reg_param(a, srcreg, srcp);
if (sizep.size() == SIZE_BYTE)
a.movsx(dstreg, GpbLo(srcp.ireg()));
a.movsx(dstreg, srcreg.r8());
else if (sizep.size() == SIZE_WORD)
a.movsx(dstreg, Gpw(srcp.ireg()));
a.movsx(dstreg, srcreg.r16());
else if (sizep.size() == SIZE_DWORD)
a.mov(dstreg, Gpd(srcp.ireg()));
}
else if (srcp.is_immediate())
{
if (sizep.size() == SIZE_BYTE)
a.mov(dstreg, int32_t(int8_t(uint8_t(srcp.immediate()))));
else if (sizep.size() == SIZE_WORD)
a.mov(dstreg, int32_t(int16_t(uint16_t(srcp.immediate()))));
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())
else
{
Gp const srcreg = srcp.select_register(dstreg);
mov_reg_param(a, srcreg, srcp);
if (sizep.size() == SIZE_BYTE)
a.movsx(dstreg, GpbLo(srcp.ireg()));
a.movsx(dstreg, srcreg.r8());
else if (sizep.size() == SIZE_WORD)
a.movsx(dstreg, Gpw(srcp.ireg()));
a.movsx(dstreg, srcreg.r16());
else if (sizep.size() == SIZE_DWORD)
a.movsxd(dstreg, Gpd(srcp.ireg()));
a.movsxd(dstreg, srcreg.r32());
else if (sizep.size() == SIZE_QWORD)
a.mov(dstreg, Gpq(srcp.ireg()));
}
else if (srcp.is_immediate())
{
if (sizep.size() == SIZE_BYTE)
a.mov(dstreg, int64_t(int8_t(uint8_t(srcp.immediate()))));
else if (sizep.size() == SIZE_WORD)
a.mov(dstreg, int64_t(int16_t(uint16_t(srcp.immediate()))));
else if (sizep.size() == SIZE_DWORD)
a.mov(dstreg, int64_t(int32_t(uint32_t(srcp.immediate()))));
else if (sizep.size() == SIZE_QWORD)
a.mov(dstreg, int64_t(srcp.immediate()));
a.mov(dstreg, srcreg);
}
mov_param_reg(a, dstp, dstreg);

View File

@ -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);