diff options
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 |
commit | e49f3ccb97755a11685b601c741c9981da83336c (patch) | |
tree | 79c67834f272c6b39722c7cfcd57a0db229b5391 /src/devices/cpu | |
parent | 26c8434a70b280d288df56866d07c841fb39b76d (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.cpp | 16 | ||||
-rw-r--r-- | src/devices/cpu/drcbex64.cpp | 132 | ||||
-rw-r--r-- | src/devices/cpu/drcbex64.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/drcbex86.cpp | 103 | ||||
-rw-r--r-- | src/devices/cpu/drcbex86.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/drcumlsh.h | 4 | ||||
-rw-r--r-- | src/devices/cpu/uml.cpp | 5 | ||||
-rw-r--r-- | src/devices/cpu/uml.h | 6 |
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 ¶m); 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 ¶m); 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; |