UML: Added FCOPYI and ICOPYF instructions to pass raw data between integer and floating-point registers. [Ville Linde]

This commit is contained in:
Ville Linde 2016-04-03 18:43:36 +03:00
parent 26c8434a70
commit e49f3ccb97
8 changed files with 265 additions and 5 deletions

View File

@ -1929,6 +1929,14 @@ int drcbe_c::execute(code_handle &entry)
FSPARAM0 = 1.0f / sqrtf(FSPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FCOPYI, 4, 0): // FSCOPYI dst,src
FSPARAM0 = u2f(*inst[1].pint32);
break;
case MAKE_OPCODE_SHORT(OP_ICOPYF, 4, 0): // ICOPYFS dst,src
*inst[0].pint32 = f2u(FSPARAM1);
break;
// ----------------------- 64-Bit Floating Point Operations -----------------------
@ -2068,6 +2076,14 @@ int drcbe_c::execute(code_handle &entry)
FDPARAM0 = 1.0 / sqrt(FDPARAM1);
break;
case MAKE_OPCODE_SHORT(OP_FCOPYI, 8, 0): // FDCOPYI dst,src
FDPARAM0 = u2d(*inst[1].pint64);
break;
case MAKE_OPCODE_SHORT(OP_ICOPYF, 8, 0): // ICOPYFD dst,src
*inst[0].pint64 = d2u(FDPARAM1);
break;
default:
fatalerror("Unexpected opcode!\n");
}

View File

@ -388,7 +388,9 @@ const drcbe_x64::opcode_table_entry drcbe_x64::s_opcode_table_source[] =
{ uml::OP_FABS, &drcbe_x64::op_fabs }, // FABS dst,src1
{ uml::OP_FSQRT, &drcbe_x64::op_fsqrt }, // FSQRT dst,src1
{ uml::OP_FRECIP, &drcbe_x64::op_frecip }, // FRECIP dst,src1
{ uml::OP_FRSQRT, &drcbe_x64::op_frsqrt } // FRSQRT dst,src1
{ uml::OP_FRSQRT, &drcbe_x64::op_frsqrt }, // FRSQRT dst,src1
{ uml::OP_FCOPYI, &drcbe_x64::op_fcopyi }, // FCOPYI dst,src
{ uml::OP_ICOPYF, &drcbe_x64::op_icopyf } // ICOPYF dst,src
};
@ -6707,3 +6709,131 @@ void drcbe_x64::op_frsqrt(x86code *&dst, const instruction &inst)
emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
}
}
//-------------------------------------------------
// op_fcopyi - process a FCOPYI opcode
//-------------------------------------------------
void drcbe_x64::op_fcopyi(x86code *&dst, const instruction &inst)
{
// validate instruction
assert(inst.size() == 4 || inst.size() == 8);
assert_no_condition(inst);
assert_no_flags(inst);
// normalize parameters
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
be_parameter srcp(*this, inst.param(1), PTYPE_MR);
// pick a target register for the general case
int dstreg = dstp.select_register(REG_XMM0);
// 32-bit form
if (inst.size() == 4)
{
if (srcp.is_memory())
{
emit_movd_r128_m32(dst, dstreg, MABS(srcp.memory())); // movd dstreg,[srcp]
emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
}
else
{
if (dstp.is_memory())
{
emit_mov_p32_r32(dst, dstp, srcp.ireg()); // mov dstp,srcp
}
else
{
emit_movd_r128_r32(dst, dstreg, srcp.ireg()); // movd dstreg,srcp
emit_movss_p32_r128(dst, dstp, dstreg); // movss dstp,dstreg
}
}
}
// 64-bit form
else if (inst.size() == 8)
{
if (srcp.is_memory())
{
emit_movq_r128_m64(dst, dstreg, MABS(srcp.memory())); // movq dstreg,[srcp]
emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
}
else
{
if (dstp.is_memory())
{
emit_mov_p64_r64(dst, dstp, srcp.ireg()); // mov dstp,srcp
}
else
{
emit_movq_r128_r64(dst, dstreg, srcp.ireg()); // movq dstreg,srcp
emit_movsd_p64_r128(dst, dstp, dstreg); // movsd dstp,dstreg
}
}
}
}
//-------------------------------------------------
// op_icopyf - process a ICOPYF opcode
//-------------------------------------------------
void drcbe_x64::op_icopyf(x86code *&dst, const instruction &inst)
{
// validate instruction
assert(inst.size() == 4 || inst.size() == 8);
assert_no_condition(inst);
assert_no_flags(inst);
// normalize parameters
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
// 32-bit form
if (inst.size() == 4)
{
if (srcp.is_memory())
{
int dstreg = dstp.select_register(REG_EAX);
emit_mov_r32_m32(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
emit_mov_p32_r32(dst, dstp, dstreg); // mov dstp,dstreg
}
else
{
if (dstp.is_memory())
{
emit_movd_m32_r128(dst, MABS(dstp.memory()), srcp.freg()); // movd dstp,srcp
}
else
{
emit_movd_r32_r128(dst, dstp.ireg(), srcp.freg()); // movd dstp,srcp
}
}
}
// 64-bit form
else if (inst.size() == 8)
{
if (srcp.is_memory())
{
int dstreg = dstp.select_register(REG_RAX);
emit_mov_r64_m64(dst, dstreg, MABS(srcp.memory())); // mov dstreg,[srcp]
emit_mov_p64_r64(dst, dstp, dstreg); // mov dstp,dstreg
}
else
{
if (dstp.is_memory())
{
emit_movq_m64_r128(dst, MABS(dstp.memory()), srcp.freg()); // movq dstp,srcp
}
else
{
emit_movq_r64_r128(dst, dstp.ireg(), srcp.freg()); // movq dstp,srcp
}
}
}
}

View File

@ -207,6 +207,8 @@ private:
void op_fsqrt(x86code *&dst, const uml::instruction &inst);
void op_frecip(x86code *&dst, const uml::instruction &inst);
void op_frsqrt(x86code *&dst, const uml::instruction &inst);
void op_fcopyi(x86code *&dst, const uml::instruction &inst);
void op_icopyf(x86code *&dst, const uml::instruction &inst);
// 32-bit code emission helpers
void emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param);

View File

@ -270,7 +270,9 @@ const drcbe_x86::opcode_table_entry drcbe_x86::s_opcode_table_source[] =
{ uml::OP_FABS, &drcbe_x86::op_fabs }, // FABS dst,src1
{ uml::OP_FSQRT, &drcbe_x86::op_fsqrt }, // FSQRT dst,src1
{ uml::OP_FRECIP, &drcbe_x86::op_frecip }, // FRECIP dst,src1
{ uml::OP_FRSQRT, &drcbe_x86::op_frsqrt } // FRSQRT dst,src1
{ uml::OP_FRSQRT, &drcbe_x86::op_frsqrt }, // FRSQRT dst,src1
{ uml::OP_FCOPYI, &drcbe_x86::op_fcopyi }, // FCOPYI dst,src
{ uml::OP_ICOPYF, &drcbe_x86::op_icopyf }, // ICOPYF dst,src
};
@ -6448,6 +6450,105 @@ void drcbe_x86::op_frsqrt(x86code *&dst, const instruction &inst)
}
//-------------------------------------------------
// op_fcopyi - process a FCOPYI opcode
//-------------------------------------------------
void drcbe_x86::op_fcopyi(x86code *&dst, const instruction &inst)
{
// validate instruction
assert(inst.size() == 4 || inst.size() == 8);
assert_no_condition(inst);
assert_no_flags(inst);
// normalize parameters
be_parameter dstp(*this, inst.param(0), PTYPE_MF);
be_parameter srcp(*this, inst.param(1), PTYPE_MR);
// 32-bit case
if (inst.size() == 4)
{
if (srcp.is_memory())
{
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
}
else if (srcp.is_int_register())
{
emit_mov_m32_r32(dst, MABS(dstp.memory()), srcp.ireg()); // mov [dstp],srcp
}
}
// 64-bit case
else if (inst.size() == 8)
{
if (srcp.is_memory())
{
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp+4]
}
else if (srcp.is_int_register())
{
emit_mov_r32_m32(dst, REG_EDX, MABS(m_reghi[srcp.ireg()])); // mov edx,[reghi[srcp]]
emit_mov_r32_r32(dst, REG_EAX, srcp.ireg()); // mov eax,srcp
}
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
}
}
//-------------------------------------------------
// op_icopyf - process a ICOPYF opcode
//-------------------------------------------------
void drcbe_x86::op_icopyf(x86code *&dst, const instruction &inst)
{
// validate instruction
assert(inst.size() == 4 || inst.size() == 8);
assert_no_condition(inst);
assert_no_flags(inst);
// normalize parameters
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
be_parameter srcp(*this, inst.param(1), PTYPE_MF);
// 32-bit case
if (inst.size() == 4)
{
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
if (dstp.is_memory())
{
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
}
else if (dstp.is_int_register())
{
emit_mov_r32_r32(dst, dstp.ireg(), REG_EAX); // mov dstp,eax
}
}
// 64-bit case
else if (inst.size() == 8)
{
emit_mov_r32_m32(dst, REG_EAX, MABS(srcp.memory())); // mov eax,[srcp]
emit_mov_r32_m32(dst, REG_EDX, MABS(srcp.memory(4))); // mov edx,[srcp+4]
if (dstp.is_memory())
{
emit_mov_m32_r32(dst, MABS(dstp.memory()), REG_EAX); // mov [dstp],eax
emit_mov_m32_r32(dst, MABS(dstp.memory(4)), REG_EDX); // mov [dstp+4],edx
}
else
{
emit_mov_m32_r32(dst, MABS(m_reghi[dstp.ireg()]), REG_EDX); // mov [reghi[dstp]],edx
emit_mov_r32_r32(dst, dstp.ireg(), REG_EAX); // mov dstp,eax
}
}
}
//**************************************************************************
// MISCELLAENOUS FUNCTIONS

View File

@ -208,6 +208,8 @@ private:
void op_fsqrt(x86code *&dst, const uml::instruction &inst);
void op_frecip(x86code *&dst, const uml::instruction &inst);
void op_frsqrt(x86code *&dst, const uml::instruction &inst);
void op_fcopyi(x86code *&dst, const uml::instruction &inst);
void op_icopyf(x86code *&dst, const uml::instruction &inst);
// 32-bit code emission helpers
void emit_mov_r32_p32(x86code *&dst, UINT8 reg, const be_parameter &param);

View File

@ -156,6 +156,8 @@
#define UML_FSSQRT(block, dst, src1) do { block->append().fssqrt(dst, src1); } while (0)
#define UML_FSRECIP(block, dst, src1) do { block->append().fsrecip(dst, src1); } while (0)
#define UML_FSRSQRT(block, dst, src1) do { block->append().fsrsqrt(dst, src1); } while (0)
#define UML_FSCOPYI(block, dst, src) do { block->append().fscopyi(dst, src); } while (0)
#define UML_ICOPYFS(block, dst, src) do { block->append().icopyfs(dst, src); } while (0)
/* ----- 64-bit Floating Point Arithmetic Operations ----- */
@ -179,6 +181,8 @@
#define UML_FDSQRT(block, dst, src1) do { block->append().fdsqrt(dst, src1); } while (0)
#define UML_FDRECIP(block, dst, src1) do { block->append().fdrecip(dst, src1); } while (0)
#define UML_FDRSQRT(block, dst, src1) do { block->append().fdrsqrt(dst, src1); } while (0)
#define UML_FDCOPYI(block, dst, src) do { block->append().fdcopyi(dst, src); } while (0)
#define UML_ICOPYFD(block, dst, src) do { block->append().icopyfd(dst, src); } while (0)
#endif /* __DRCUMLSH_H__ */

View File

@ -22,9 +22,6 @@
* Support for FPU exceptions
* New instructions?
- FCOPYI, ICOPYF
copy raw between float and integer registers
- VALID opcode_desc,handle,param
checksum/compare code referenced by opcode_desc; if not
matching, generate exception with handle,param
@ -214,6 +211,8 @@ const opcode_info instruction::s_opcode_info_table[OP_MAX] =
OPINFO2(FSQRT, "f#sqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
OPINFO2(FRECIP, "f#recip", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
OPINFO2(FRSQRT, "f#rsqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
OPINFO2(FCOPYI, "f#copyi", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, FRM), PINFO(IN, OP, IRM))
OPINFO2(ICOPYF, "icopyf#", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, FRM))
};

View File

@ -218,6 +218,8 @@ namespace uml
OP_FSQRT, // FSQRT dst,src1
OP_FRECIP, // FRECIP dst,src1
OP_FRSQRT, // FRSQRT dst,src1
OP_FCOPYI, // FCOPYI dst,src
OP_ICOPYF, // ICOPYF dst,src
OP_MAX
};
@ -544,6 +546,8 @@ namespace uml
void fssqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 4, dst, src1); }
void fsrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 4, dst, src1); }
void fsrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 4, dst, src1); }
void fscopyi(parameter dst, parameter src) { configure(OP_FCOPYI, 4, dst, src); }
void icopyfs(parameter dst, parameter src) { configure(OP_ICOPYF, 4, dst, src); }
// 64-bit floating point operations
void fdload(parameter dst, const void *base, parameter index) { configure(OP_FLOAD, 8, dst, parameter::make_memory(base), index); }
@ -566,6 +570,8 @@ namespace uml
void fdsqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 8, dst, src1); }
void fdrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 8, dst, src1); }
void fdrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 8, dst, src1); }
void fdcopyi(parameter dst, parameter src) { configure(OP_FCOPYI, 8, dst, src); }
void icopyfd(parameter dst, parameter src) { configure(OP_ICOPYF, 8, dst, src); }
// constants
static const int MAX_PARAMS = 4;