Module Name: src
Committed By: isaki
Date: Sat Dec 28 05:56:15 UTC 2024
Modified Files:
src/sys/arch/m68k/fpe: fpu_emulate.c
Log Message:
m68k/fpe: Fix several FMOVEM FPctl emulation.
- Fix the write order of FMOVEM FPctl,-(An).
For example, "FMOVEM FPCR/FPSR,-(An)" instruction first decrements An by
the total size (4*2 bytes), then writes FPCR and FPSR in this order.
Therefore, it's differs from "FMOVEM FPCR,-(An); FMOVEM FPSR,-(An)" sequence.
- Support multiple immediate case like "FMOVEM #imm/#imm,FPCR/FPIAR".
- Mask writes to FPSR and FPCR registers correctly.
- Support reglist=0 case too. It's not common case but makes code easier.
To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/sys/arch/m68k/fpe/fpu_emulate.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/m68k/fpe/fpu_emulate.c
diff -u src/sys/arch/m68k/fpe/fpu_emulate.c:1.42 src/sys/arch/m68k/fpe/fpu_emulate.c:1.43
--- src/sys/arch/m68k/fpe/fpu_emulate.c:1.42 Sat Dec 28 05:52:53 2024
+++ src/sys/arch/m68k/fpe/fpu_emulate.c Sat Dec 28 05:56:15 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu_emulate.c,v 1.42 2024/12/28 05:52:53 isaki Exp $ */
+/* $NetBSD: fpu_emulate.c,v 1.43 2024/12/28 05:56:15 isaki Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.42 2024/12/28 05:52:53 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.43 2024/12/28 05:56:15 isaki Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -332,74 +332,81 @@ fpu_emul_fmovmcr(struct fpemu *fe, struc
struct fpframe *fpf = fe->fe_fpframe;
int sig;
int reglist;
+ int regcount;
int fpu_to_mem;
+ uint32_t tmp[3];
/* move to/from control registers */
reglist = (insn->is_word1 & 0x1c00) >> 10;
- /* Bit 13 selects direction (FPU to/from Mem) */
- fpu_to_mem = insn->is_word1 & 0x2000;
+ /*
+ * If reglist is 0b000, treat it as FPIAR. This is not specification
+ * but the behavior described in the 6888x user's manual.
+ */
+ if (reglist == 0)
+ reglist = 1;
- insn->is_datasize = 4;
+ if (reglist == 7) {
+ regcount = 3;
+ } else if (reglist == 3 || reglist == 5 || reglist == 6) {
+ regcount = 2;
+ } else {
+ regcount = 1;
+ }
+ insn->is_datasize = regcount * 4;
insn->is_advance = 4;
sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode);
if (sig)
return sig;
- if (reglist != 1 && reglist != 2 && reglist != 4 &&
- (insn->is_ea.ea_flags & EA_DIRECT)) {
- /* attempted to copy more than one FPcr to CPU regs */
- DPRINTF(("%s: tried to copy too many FPcr\n", __func__));
- return SIGILL;
- }
-
- if (reglist & 4) {
- /* fpcr */
- if ((insn->is_ea.ea_flags & EA_DIRECT) &&
- insn->is_ea.ea_regnum >= 8 /* address reg */) {
- /* attempted to copy FPCR to An */
- DPRINTF(("%s: tried to copy FPCR from/to A%d\n",
- __func__, insn->is_ea.ea_regnum & 7));
- return SIGILL;
- }
- if (fpu_to_mem) {
- sig = fpu_store_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpcr);
+ /*
+ * For data register, only single register can be transferred.
+ * For addr register, only FPIAR can be transferred.
+ */
+ if ((insn->is_ea.ea_flags & EA_DIRECT)) {
+ if (insn->is_ea.ea_regnum < 8) {
+ if (regcount != 1) {
+ return SIGILL;
+ }
} else {
- sig = fpu_load_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpcr);
+ if (reglist != 1) {
+ return SIGILL;
+ }
}
}
- if (sig)
- return sig;
- if (reglist & 2) {
- /* fpsr */
- if ((insn->is_ea.ea_flags & EA_DIRECT) &&
- insn->is_ea.ea_regnum >= 8 /* address reg */) {
- /* attempted to copy FPSR to An */
- DPRINTF(("%s: tried to copy FPSR from/to A%d\n",
- __func__, insn->is_ea.ea_regnum & 7));
- return SIGILL;
+ /* Bit 13 selects direction (FPU to/from Mem) */
+ fpu_to_mem = insn->is_word1 & 0x2000;
+ if (fpu_to_mem) {
+ uint32_t *s = &tmp[0];
+
+ if ((reglist & 4)) {
+ *s++ = fpf->fpf_fpcr;
}
- if (fpu_to_mem) {
- sig = fpu_store_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpsr);
- } else {
- sig = fpu_load_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpsr);
+ if ((reglist & 2)) {
+ *s++ = fpf->fpf_fpsr;
+ }
+ if ((reglist & 1)) {
+ *s++ = fpf->fpf_fpiar;
}
- }
- if (sig)
- return sig;
- if (reglist & 1) {
- /* fpiar - can be moved to/from An */
- if (fpu_to_mem) {
- sig = fpu_store_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpiar);
- } else {
- sig = fpu_load_ea(frame, insn, &insn->is_ea,
- (char *)&fpf->fpf_fpiar);
+ sig = fpu_store_ea(frame, insn, &insn->is_ea, (char *)tmp);
+ } else {
+ const uint32_t *d = &tmp[0];
+
+ sig = fpu_load_ea(frame, insn, &insn->is_ea, (char *)tmp);
+ if (sig)
+ return sig;
+
+ if ((reglist & 4)) {
+ fpf->fpf_fpcr = *d++;
+ fpf->fpf_fpcr &= 0x0000fff0;
+ }
+ if ((reglist & 2)) {
+ fpf->fpf_fpsr = *d++;
+ fpf->fpf_fpsr &= 0x0ffffff8;
+ }
+ if ((reglist & 1)) {
+ fpf->fpf_fpiar = *d++;
}
}
return sig;