summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu
diff options
context:
space:
mode:
author Ville Linde <villedevs@gmail.com>2016-04-03 18:43:36 +0300
committer Ville Linde <villedevs@gmail.com>2016-04-03 18:46:02 +0300
commite49f3ccb97755a11685b601c741c9981da83336c (patch)
tree79c67834f272c6b39722c7cfcd57a0db229b5391 /src/devices/cpu
parent26c8434a70b280d288df56866d07c841fb39b76d (diff)
UML: Added FCOPYI and ICOPYF instructions to pass raw data between integer and floating-point registers. [Ville Linde]
Diffstat (limited to 'src/devices/cpu')
-rw-r--r--src/devices/cpu/drcbec.cpp16
-rw-r--r--src/devices/cpu/drcbex64.cpp132
-rw-r--r--src/devices/cpu/drcbex64.h2
-rw-r--r--src/devices/cpu/drcbex86.cpp103
-rw-r--r--src/devices/cpu/drcbex86.h2
-rw-r--r--src/devices/cpu/drcumlsh.h4
-rw-r--r--src/devices/cpu/uml.cpp5
-rw-r--r--src/devices/cpu/uml.h6
8 files changed, 265 insertions, 5 deletions
diff --git a/src/devices/cpu/drcbec.cpp b/src/devices/cpu/drcbec.cpp
index 8736a2b6703..ac6da189688 100644
--- a/src/devices/cpu/drcbec.cpp
+++ b/src/devices/cpu/drcbec.cpp
@@ -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");
}
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index b9583123af0..7e9628bc671 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -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
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/devices/cpu/drcbex64.h b/src/devices/cpu/drcbex64.h
index f60b8970aa9..a538f9bf1e7 100644
--- a/src/devices/cpu/drcbex64.h
+++ b/src/devices/cpu/drcbex64.h
@@ -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);
diff --git a/src/devices/cpu/drcbex86.cpp b/src/devices/cpu/drcbex86.cpp
index be63ac1e869..92b5f628939 100644
--- a/src/devices/cpu/drcbex86.cpp
+++ b/src/devices/cpu/drcbex86.cpp
@@ -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
diff --git a/src/devices/cpu/drcbex86.h b/src/devices/cpu/drcbex86.h
index df81ee0c7c7..397cbb53215 100644
--- a/src/devices/cpu/drcbex86.h
+++ b/src/devices/cpu/drcbex86.h
@@ -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);
diff --git a/src/devices/cpu/drcumlsh.h b/src/devices/cpu/drcumlsh.h
index d14c1321d9e..12f5abc20eb 100644
--- a/src/devices/cpu/drcumlsh.h
+++ b/src/devices/cpu/drcumlsh.h
@@ -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__ */
diff --git a/src/devices/cpu/uml.cpp b/src/devices/cpu/uml.cpp
index 07d5de9b57f..6974b884e1b 100644
--- a/src/devices/cpu/uml.cpp
+++ b/src/devices/cpu/uml.cpp
@@ -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))
};
diff --git a/src/devices/cpu/uml.h b/src/devices/cpu/uml.h
index 2dfd95adbea..5b390700ced 100644
--- a/src/devices/cpu/uml.h
+++ b/src/devices/cpu/uml.h
@@ -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;