mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-18 15:07:16 +00:00
target/m68k: add fmod/frem
Using a local m68k floatx80_mod() [copied from previous: Written by Andreas Grabher for Previous, NeXT Computer Emulator.] The quotient byte of the FPSR is updated with the result of the operation. Backports commit 591596b77a1872d0652e666271ca055e57ea1e21 from qemu
This commit is contained in:
parent
b42fcb5496
commit
08c03a5de4
|
@ -33,6 +33,7 @@
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\cpu.h" />
|
<ClInclude Include="..\..\..\qemu\target\m68k\cpu.h" />
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\helper.h" />
|
<ClInclude Include="..\..\..\qemu\target\m68k\helper.h" />
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\m68k-qreg.h" />
|
<ClInclude Include="..\..\..\qemu\target\m68k\m68k-qreg.h" />
|
||||||
|
<ClInclude Include="..\..\..\qemu\target\m68k\softfloat.h" />
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\unicorn.h" />
|
<ClInclude Include="..\..\..\qemu\target\m68k\unicorn.h" />
|
||||||
<ClInclude Include="..\..\..\qemu\m68k.h" />
|
<ClInclude Include="..\..\..\qemu\m68k.h" />
|
||||||
<ClInclude Include="..\config-host.h" />
|
<ClInclude Include="..\config-host.h" />
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\fpu_helper.c" />
|
<ClCompile Include="..\..\..\qemu\target\m68k\fpu_helper.c" />
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\helper.c" />
|
<ClCompile Include="..\..\..\qemu\target\m68k\helper.c" />
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\op_helper.c" />
|
<ClCompile Include="..\..\..\qemu\target\m68k\op_helper.c" />
|
||||||
|
<ClCompile Include="..\..\..\qemu\target\m68k\softfloat.c" />
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\translate.c" />
|
<ClCompile Include="..\..\..\qemu\target\m68k\translate.c" />
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\unicorn.c" />
|
<ClCompile Include="..\..\..\qemu\target\m68k\unicorn.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -63,6 +63,9 @@
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\m68k-qreg.h">
|
<ClInclude Include="..\..\..\qemu\target\m68k\m68k-qreg.h">
|
||||||
<Filter>target\m68k</Filter>
|
<Filter>target\m68k</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\qemu\target\m68k\softfloat.h">
|
||||||
|
<Filter>target\m68k</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\..\qemu\target\m68k\unicorn.h">
|
<ClInclude Include="..\..\..\qemu\target\m68k\unicorn.h">
|
||||||
<Filter>target\m68k</Filter>
|
<Filter>target\m68k</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -119,6 +122,9 @@
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\op_helper.c">
|
<ClCompile Include="..\..\..\qemu\target\m68k\op_helper.c">
|
||||||
<Filter>target\m68k</Filter>
|
<Filter>target\m68k</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\qemu\target\m68k\softfloat.c">
|
||||||
|
<Filter>target\m68k</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\qemu\target\m68k\translate.c">
|
<ClCompile Include="..\..\..\qemu\target\m68k\translate.c">
|
||||||
<Filter>target\m68k</Filter>
|
<Filter>target\m68k</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o
|
obj-y += translate.o op_helper.o helper.o cpu.o fpu_helper.o
|
||||||
|
obj-y += softfloat.o
|
||||||
obj-y += unicorn.o
|
obj-y += unicorn.o
|
||||||
|
|
|
@ -423,6 +423,7 @@ typedef enum {
|
||||||
/* Quotient */
|
/* Quotient */
|
||||||
|
|
||||||
#define FPSR_QT_MASK 0x00ff0000
|
#define FPSR_QT_MASK 0x00ff0000
|
||||||
|
#define FPSR_QT_SHIFT 16
|
||||||
|
|
||||||
/* Floating-Point Control Register */
|
/* Floating-Point Control Register */
|
||||||
/* Rounding mode */
|
/* Rounding mode */
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/exec-all.h"
|
#include "exec/exec-all.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
#include "fpu/softfloat.h"
|
#include "softfloat.h"
|
||||||
|
|
||||||
/* Undefined offsets may be different on various FPU.
|
/* Undefined offsets may be different on various FPU.
|
||||||
* On 68040 they return 0.0 (floatx80_zero)
|
* On 68040 they return 0.0 (floatx80_zero)
|
||||||
|
@ -520,3 +520,36 @@ uint32_t HELPER(fmovemd_ld_postinc)(CPUM68KState *env, uint32_t addr,
|
||||||
{
|
{
|
||||||
return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra);
|
return fmovem_postinc(env, addr, mask, cpu_ld_float64_ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void make_quotient(CPUM68KState *env, floatx80 val)
|
||||||
|
{
|
||||||
|
int32_t quotient;
|
||||||
|
int sign;
|
||||||
|
|
||||||
|
if (floatx80_is_any_nan(val)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quotient = floatx80_to_int32(val, &env->fp_status);
|
||||||
|
sign = quotient < 0;
|
||||||
|
if (sign) {
|
||||||
|
quotient = -quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
quotient = (sign << 7) | (quotient & 0x7f);
|
||||||
|
env->fpsr = (env->fpsr & ~FPSR_QT_MASK) | (quotient << FPSR_QT_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(fmod)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
|
||||||
|
{
|
||||||
|
res->d = floatx80_mod(val1->d, val0->d, &env->fp_status);
|
||||||
|
|
||||||
|
make_quotient(env, res->d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(frem)(CPUM68KState *env, FPReg *res, FPReg *val0, FPReg *val1)
|
||||||
|
{
|
||||||
|
res->d = floatx80_rem(val1->d, val0->d, &env->fp_status);
|
||||||
|
|
||||||
|
make_quotient(env, res->d);
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ DEF_HELPER_3(fmovemx_ld_postinc, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(fmovemd_st_predec, i32, env, i32, i32)
|
DEF_HELPER_3(fmovemd_st_predec, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32)
|
DEF_HELPER_3(fmovemd_st_postinc, i32, env, i32, i32)
|
||||||
DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32)
|
DEF_HELPER_3(fmovemd_ld_postinc, i32, env, i32, i32)
|
||||||
|
DEF_HELPER_4(fmod, void, env, fp, fp, fp)
|
||||||
|
DEF_HELPER_4(frem, void, env, fp, fp, fp)
|
||||||
|
|
||||||
DEF_HELPER_3(mac_move, void, env, i32, i32)
|
DEF_HELPER_3(mac_move, void, env, i32, i32)
|
||||||
DEF_HELPER_3(macmulf, i64, env, i32, i32)
|
DEF_HELPER_3(macmulf, i64, env, i32, i32)
|
||||||
|
|
105
qemu/target/m68k/softfloat.c
Normal file
105
qemu/target/m68k/softfloat.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* Ported from a work by Andreas Grabher for Previous, NeXT Computer Emulator,
|
||||||
|
* derived from NetBSD M68040 FPSP functions,
|
||||||
|
* derived from release 2a of the SoftFloat IEC/IEEE Floating-point Arithmetic
|
||||||
|
* Package. Those parts of the code (and some later contributions) are
|
||||||
|
* provided under that license, as detailed below.
|
||||||
|
* It has subsequently been modified by contributors to the QEMU Project,
|
||||||
|
* so some portions are provided under:
|
||||||
|
* the SoftFloat-2a license
|
||||||
|
* the BSD license
|
||||||
|
* GPL-v2-or-later
|
||||||
|
*
|
||||||
|
* Any future contributions to this file will be taken to be licensed under
|
||||||
|
* the Softfloat-2a license unless specifically indicated otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||||
|
* version 2 or later. See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "softfloat.h"
|
||||||
|
#include "fpu/softfloat-macros.h"
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
| Returns the modulo remainder of the extended double-precision floating-point
|
||||||
|
| value `a' with respect to the corresponding value `b'.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status)
|
||||||
|
{
|
||||||
|
flag aSign, zSign;
|
||||||
|
int32_t aExp, bExp, expDiff;
|
||||||
|
uint64_t aSig0, aSig1, bSig;
|
||||||
|
uint64_t qTemp, term0, term1;
|
||||||
|
|
||||||
|
aSig0 = extractFloatx80Frac(a);
|
||||||
|
aExp = extractFloatx80Exp(a);
|
||||||
|
aSign = extractFloatx80Sign(a);
|
||||||
|
bSig = extractFloatx80Frac(b);
|
||||||
|
bExp = extractFloatx80Exp(b);
|
||||||
|
|
||||||
|
if (aExp == 0x7FFF) {
|
||||||
|
if ((uint64_t) (aSig0 << 1)
|
||||||
|
|| ((bExp == 0x7FFF) && (uint64_t) (bSig << 1))) {
|
||||||
|
return propagateFloatx80NaN(a, b, status);
|
||||||
|
}
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
if (bExp == 0x7FFF) {
|
||||||
|
if ((uint64_t) (bSig << 1)) {
|
||||||
|
return propagateFloatx80NaN(a, b, status);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (bExp == 0) {
|
||||||
|
if (bSig == 0) {
|
||||||
|
invalid:
|
||||||
|
float_raise(float_flag_invalid, status);
|
||||||
|
return floatx80_default_nan(status);
|
||||||
|
}
|
||||||
|
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||||
|
}
|
||||||
|
if (aExp == 0) {
|
||||||
|
if ((uint64_t) (aSig0 << 1) == 0) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
|
||||||
|
}
|
||||||
|
bSig |= LIT64(0x8000000000000000);
|
||||||
|
zSign = aSign;
|
||||||
|
expDiff = aExp - bExp;
|
||||||
|
aSig1 = 0;
|
||||||
|
if (expDiff < 0) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
qTemp = (bSig <= aSig0);
|
||||||
|
if (qTemp) {
|
||||||
|
aSig0 -= bSig;
|
||||||
|
}
|
||||||
|
expDiff -= 64;
|
||||||
|
while (0 < expDiff) {
|
||||||
|
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
|
||||||
|
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
|
||||||
|
mul64To128(bSig, qTemp, &term0, &term1);
|
||||||
|
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
|
||||||
|
shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1);
|
||||||
|
}
|
||||||
|
expDiff += 64;
|
||||||
|
if (0 < expDiff) {
|
||||||
|
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
|
||||||
|
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
|
||||||
|
qTemp >>= 64 - expDiff;
|
||||||
|
mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1);
|
||||||
|
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
|
||||||
|
shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1);
|
||||||
|
while (le128(term0, term1, aSig0, aSig1)) {
|
||||||
|
++qTemp;
|
||||||
|
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
normalizeRoundAndPackFloatx80(
|
||||||
|
80, zSign, bExp + expDiff, aSig0, aSig1, status);
|
||||||
|
}
|
26
qemu/target/m68k/softfloat.h
Normal file
26
qemu/target/m68k/softfloat.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Ported from a work by Andreas Grabher for Previous, NeXT Computer Emulator,
|
||||||
|
* derived from NetBSD M68040 FPSP functions,
|
||||||
|
* derived from release 2a of the SoftFloat IEC/IEEE Floating-point Arithmetic
|
||||||
|
* Package. Those parts of the code (and some later contributions) are
|
||||||
|
* provided under that license, as detailed below.
|
||||||
|
* It has subsequently been modified by contributors to the QEMU Project,
|
||||||
|
* so some portions are provided under:
|
||||||
|
* the SoftFloat-2a license
|
||||||
|
* the BSD license
|
||||||
|
* GPL-v2-or-later
|
||||||
|
*
|
||||||
|
* Any future contributions to this file will be taken to be licensed under
|
||||||
|
* the Softfloat-2a license unless specifically indicated otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Portions of this work are licensed under the terms of the GNU GPL,
|
||||||
|
* version 2 or later. See the COPYING file in the top-level directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TARGET_M68K_SOFTFLOAT_H
|
||||||
|
#define TARGET_M68K_SOFTFLOAT_H
|
||||||
|
#include "fpu/softfloat.h"
|
||||||
|
|
||||||
|
floatx80 floatx80_mod(floatx80 a, floatx80 b, float_status *status);
|
||||||
|
#endif
|
|
@ -5280,6 +5280,9 @@ DISAS_INSN(fpu)
|
||||||
case 0x64: /* fddiv */
|
case 0x64: /* fddiv */
|
||||||
gen_helper_fddiv(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
gen_helper_fddiv(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
break;
|
break;
|
||||||
|
case 0x21: /* fmod */
|
||||||
|
gen_helper_fmod(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
|
break;
|
||||||
case 0x22: /* fadd */
|
case 0x22: /* fadd */
|
||||||
gen_helper_fadd(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
gen_helper_fadd(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
break;
|
break;
|
||||||
|
@ -5301,6 +5304,9 @@ DISAS_INSN(fpu)
|
||||||
case 0x24: /* fsgldiv */
|
case 0x24: /* fsgldiv */
|
||||||
gen_helper_fsgldiv(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
gen_helper_fsgldiv(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
break;
|
break;
|
||||||
|
case 0x25: /* frem */
|
||||||
|
gen_helper_frem(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
|
break;
|
||||||
case 0x27: /* fsglmul */
|
case 0x27: /* fsglmul */
|
||||||
gen_helper_fsglmul(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
gen_helper_fsglmul(tcg_ctx, tcg_ctx->cpu_env, cpu_dest, cpu_src, cpu_dest);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue