Module Name: src Committed By: rin Date: Tue Aug 30 11:09:34 UTC 2022
Modified Files: src/sys/arch/powerpc/fpu: fpu_emu.c fpu_emu.h fpu_extern.h fpu_implode.c Log Message: Fix fcti{w,d}{,z}. - Treat 64-bit integer correctly for fctid{,z}. - Respect round mode specified by FPSCR[RN]. XXX - Set FPSCR[FR] and [FI] appropriately. - Also set FPSCR[FPRF]? - fctid{,z} traps on powerpc32 (confirmed on 603e and G4). To generate a diff of this commit: cvs rdiff -u -r1.42 -r1.43 src/sys/arch/powerpc/fpu/fpu_emu.c cvs rdiff -u -r1.5 -r1.6 src/sys/arch/powerpc/fpu/fpu_emu.h cvs rdiff -u -r1.6 -r1.7 src/sys/arch/powerpc/fpu/fpu_extern.h cvs rdiff -u -r1.9 -r1.10 src/sys/arch/powerpc/fpu/fpu_implode.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/powerpc/fpu/fpu_emu.c diff -u src/sys/arch/powerpc/fpu/fpu_emu.c:1.42 src/sys/arch/powerpc/fpu/fpu_emu.c:1.43 --- src/sys/arch/powerpc/fpu/fpu_emu.c:1.42 Tue Aug 30 10:59:43 2022 +++ src/sys/arch/powerpc/fpu/fpu_emu.c Tue Aug 30 11:09:34 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_emu.c,v 1.42 2022/08/30 10:59:43 rin Exp $ */ +/* $NetBSD: fpu_emu.c,v 1.43 2022/08/30 11:09:34 rin Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.42 2022/08/30 10:59:43 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu_emu.c,v 1.43 2022/08/30 11:09:34 rin Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -504,6 +504,8 @@ fpu_execute(struct trapframe *tf, struct DPRINTF(FPE_INSN, ("fpu_execute: FCTIW\n")); fpu_explode(fe, fp = &fe->fe_f1, type, rb); type = FTYPE_INT; + if (instr.i_x.i_xo == OPC63_FCTIWZ) + type |= FTYPE_RD_RZ; break; case OPC63_FCMPO: FPU_EMU_EVCNT_INCR(fcmpo); @@ -614,6 +616,8 @@ fpu_execute(struct trapframe *tf, struct DPRINTF(FPE_INSN, ("fpu_execute: FCTID\n")); fpu_explode(fe, fp = &fe->fe_f1, type, rb); type = FTYPE_LNG; + if (instr.i_x.i_xo == OPC63_FCTIDZ) + type |= FTYPE_RD_RZ; break; case OPC63_FCFID: FPU_EMU_EVCNT_INCR(fcfid); Index: src/sys/arch/powerpc/fpu/fpu_emu.h diff -u src/sys/arch/powerpc/fpu/fpu_emu.h:1.5 src/sys/arch/powerpc/fpu/fpu_emu.h:1.6 --- src/sys/arch/powerpc/fpu/fpu_emu.h:1.5 Tue Aug 30 11:05:59 2022 +++ src/sys/arch/powerpc/fpu/fpu_emu.h Tue Aug 30 11:09:34 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_emu.h,v 1.5 2022/08/30 11:05:59 rin Exp $ */ +/* $NetBSD: fpu_emu.h,v 1.6 2022/08/30 11:09:34 rin Exp $ */ /* * Copyright (c) 1992, 1993 @@ -136,10 +136,12 @@ struct fpn { /* * FPU data types. */ -#define FTYPE_LNG -1 /* data = 64-bit signed long integer */ -#define FTYPE_INT 0 /* data = 32-bit signed integer */ -#define FTYPE_SNG 1 /* data = 32-bit float */ -#define FTYPE_DBL 2 /* data = 64-bit double */ +#define FTYPE_INT 0x0 /* data = 32-bit signed integer */ +#define FTYPE_LNG 0x1 /* data = 64-bit signed long integer */ +#define FTYPE_SNG 0x2 /* data = 32-bit float */ +#define FTYPE_DBL 0x4 /* data = 64-bit double */ +#define FTYPE_RD_RZ 0x8 +#define FTYPE_RD_MASK (FTYPE_RD_RZ) /* * Emulator state. Index: src/sys/arch/powerpc/fpu/fpu_extern.h diff -u src/sys/arch/powerpc/fpu/fpu_extern.h:1.6 src/sys/arch/powerpc/fpu/fpu_extern.h:1.7 --- src/sys/arch/powerpc/fpu/fpu_extern.h:1.6 Sun Aug 28 22:22:41 2022 +++ src/sys/arch/powerpc/fpu/fpu_extern.h Tue Aug 30 11:09:34 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_extern.h,v 1.6 2022/08/28 22:22:41 rin Exp $ */ +/* $NetBSD: fpu_extern.h,v 1.7 2022/08/30 11:09:34 rin Exp $ */ /*- * Copyright (c) 1995 The NetBSD Foundation, Inc. @@ -63,8 +63,8 @@ int fpu_dtof(struct fpn *, u_int, u_int) void fpu_explode(struct fpemu *, struct fpn *, int, int); /* fpu_implode.c */ -u_int fpu_ftoi(struct fpemu *, struct fpn *); -u_int fpu_ftox(struct fpemu *, struct fpn *, u_int *); +u_int fpu_ftoi(struct fpemu *, struct fpn *, int); +uint64_t fpu_ftox(struct fpemu *, struct fpn *, int); u_int fpu_ftos(struct fpemu *, struct fpn *); u_int fpu_ftod(struct fpemu *, struct fpn *, u_int *); void fpu_implode(struct fpemu *, struct fpn *, int, u_int *); Index: src/sys/arch/powerpc/fpu/fpu_implode.c diff -u src/sys/arch/powerpc/fpu/fpu_implode.c:1.9 src/sys/arch/powerpc/fpu/fpu_implode.c:1.10 --- src/sys/arch/powerpc/fpu/fpu_implode.c:1.9 Tue Aug 30 11:00:49 2022 +++ src/sys/arch/powerpc/fpu/fpu_implode.c Tue Aug 30 11:09:34 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_implode.c,v 1.9 2022/08/30 11:00:49 rin Exp $ */ +/* $NetBSD: fpu_implode.c,v 1.10 2022/08/30 11:09:34 rin Exp $ */ /* * Copyright (c) 1992, 1993 @@ -46,7 +46,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fpu_implode.c,v 1.9 2022/08/30 11:00:49 rin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu_implode.c,v 1.10 2022/08/30 11:09:34 rin Exp $"); #include <sys/types.h> #include <sys/systm.h> @@ -191,15 +191,12 @@ toinf(struct fpemu *fe, int sign) /* * fpn -> int (int value returned as return value). - * - * N.B.: this conversion always rounds towards zero (this is a peculiarity - * of the SPARC instruction set). */ u_int -fpu_ftoi(struct fpemu *fe, struct fpn *fp) +fpu_ftoi(struct fpemu *fe, struct fpn *fp, int rn) { u_int i; - int sign, exp; + int sign, exp, g, rs; sign = fp->fp_sign; switch (fp->fp_class) { @@ -221,9 +218,29 @@ fpu_ftoi(struct fpemu *fe, struct fpn *f if ((exp = fp->fp_exp) >= 32) break; /* NB: the following includes exp < 0 cases */ - if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0) + if (fpu_shr(fp, FP_NMANT - 32 - 1 - exp) != 0) fe->fe_cx |= FPSCR_UX; - i = fp->fp_mant[3]; + i = fp->fp_mant[2]; + + g = fp->fp_mant[3] & 0x80000000; + rs = (fp->fp_mant[3] & 0x7fffffff) | fp->fp_sticky; + switch (rn) { + case FSR_RD_RN: + if (g && (rs | (i & 1))) + i++; + break; + case FSR_RD_RZ: + break; + case FSR_RD_RP: + if (!sign && (g | rs)) + i++; + break; + case FSR_RD_RM: + if (sign && (g | rs)) + i++; + break; + } + if (i >= ((u_int)0x80000000 + sign)) break; return (sign ? -i : i); @@ -242,17 +259,16 @@ fpu_ftoi(struct fpemu *fe, struct fpn *f * N.B.: this conversion always rounds towards zero (this is a peculiarity * of the SPARC instruction set). */ -u_int -fpu_ftox(struct fpemu *fe, struct fpn *fp, u_int *res) +uint64_t +fpu_ftox(struct fpemu *fe, struct fpn *fp, int rn) { uint64_t i; - int sign, exp; + int sign, exp, g, rs; sign = fp->fp_sign; switch (fp->fp_class) { case FPC_ZERO: - res[1] = 0; return (0); case FPC_NUM: @@ -269,9 +285,29 @@ fpu_ftox(struct fpemu *fe, struct fpn *f if ((exp = fp->fp_exp) >= 64) break; /* NB: the following includes exp < 0 cases */ - if (fpu_shr(fp, FP_NMANT - 1 - exp) != 0) + if (fpu_shr(fp, FP_NMANT - 32 - 1 - exp) != 0) fe->fe_cx |= FPSCR_UX; - i = ((uint64_t)fp->fp_mant[2]<<32)|fp->fp_mant[3]; + i = ((uint64_t)fp->fp_mant[1] << 32) | fp->fp_mant[2]; + + g = fp->fp_mant[3] & 0x80000000; + rs = (fp->fp_mant[3] & 0x7fffffff) | fp->fp_sticky; + switch (rn) { + case FSR_RD_RN: + if (g && (rs | (i & 1))) + i++; + break; + case FSR_RD_RZ: + break; + case FSR_RD_RP: + if (!sign && (g | rs)) + i++; + break; + case FSR_RD_RM: + if (sign && (g | rs)) + i++; + break; + } + if (i >= ((uint64_t)0x8000000000000000LL + sign)) break; return (sign ? -i : i); @@ -427,18 +463,25 @@ done: void fpu_implode(struct fpemu *fe, struct fpn *fp, int type, u_int *space) { + int rn; + + if (type & FTYPE_RD_RZ) + rn = FSR_RD_RZ; + else + rn = fe->fe_fpscr & FPSCR_RN; + type &= ~FTYPE_RD_MASK; switch (type) { case FTYPE_LNG: - space[0] = fpu_ftox(fe, fp, space); + *(uint64_t *)space = fpu_ftox(fe, fp, rn); DPRINTF(FPE_REG, ("fpu_implode: long %x %x\n", space[0], space[1])); break; case FTYPE_INT: space[0] = 0; - space[1] = fpu_ftoi(fe, fp); + space[1] = fpu_ftoi(fe, fp, rn); DPRINTF(FPE_REG, ("fpu_implode: int %x\n", space[1])); break;