--- nono/fpe/fpu_emulate.c 2026/04/29 17:05:08 1.1.1.2 +++ nono/fpe/fpu_emulate.c 2026/04/29 17:05:31 1.1.1.5 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_emulate.c,v 1.38 2013/10/25 21:32:45 martin Exp $ */ +/* $NetBSD: fpu_emulate.c,v 1.41 2023/09/17 13:14:08 andvar Exp $ */ /* * Copyright (c) 1995 Gordon W. Ross @@ -79,8 +79,8 @@ fpu_emulate(struct frame *frame, struct { static struct instruction insn; static struct fpemu fe; - int word, optype, sig; - + int optype, sig; + unsigned short sval; /* initialize insn.is_datasize to tell it is *not* initialized */ insn.is_datasize = -1; @@ -116,32 +116,30 @@ fpu_emulate(struct frame *frame, struct frame->f_pc = insn.is_pc; } - word = fusword((void *)(insn.is_pc)); - if (word < 0) { + if (ufetch_short((void *)(insn.is_pc), &sval)) { DPRINTF(("%s: fault reading opcode\n", __func__)); fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); } - if ((word & 0xf000) != 0xf000) { + if ((sval & 0xf000) != 0xf000) { DPRINTF(("%s: not coproc. insn.: opcode=0x%x\n", - __func__, word)); + __func__, sval)); fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); } - if ((word & 0x0E00) != 0x0200) { - DPRINTF(("%s: bad coproc. id: opcode=0x%x\n", __func__, word)); + if ((sval & 0x0E00) != 0x0200) { + DPRINTF(("%s: bad coproc. id: opcode=0x%x\n", __func__, sval)); fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); } - insn.is_opcode = word; - optype = (word & 0x01C0); + insn.is_opcode = sval; + optype = (sval & 0x01C0); - word = fusword((void *)(insn.is_pc + 2)); - if (word < 0) { + if (ufetch_short((void *)(insn.is_pc + 2), &sval)) { DPRINTF(("%s: fault reading word1\n", __func__)); fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); } - insn.is_word1 = word; + insn.is_word1 = sval; /* all FPU instructions are at least 4-byte long */ insn.is_advance = 4; @@ -154,21 +152,21 @@ fpu_emulate(struct frame *frame, struct */ if (optype == 0x0000) { /* type=0: generic */ - if ((word & 0xc000) == 0xc000) { + if ((sval & 0xc000) == 0xc000) { DPRINTF(("%s: fmovm FPr\n", __func__)); sig = fpu_emul_fmovm(&fe, &insn); - } else if ((word & 0xc000) == 0x8000) { + } else if ((sval & 0xc000) == 0x8000) { DPRINTF(("%s: fmovm FPcr\n", __func__)); sig = fpu_emul_fmovmcr(&fe, &insn); - } else if ((word & 0xe000) == 0x6000) { + } else if ((sval & 0xe000) == 0x6000) { /* fstore = fmove FPn,mem */ DPRINTF(("%s: fmove to mem\n", __func__)); sig = fpu_emul_fstore(&fe, &insn); - } else if ((word & 0xfc00) == 0x5c00) { + } else if ((sval & 0xfc00) == 0x5c00) { /* fmovecr */ DPRINTF(("%s: fmovecr\n", __func__)); sig = fpu_emul_fmovecr(&fe, &insn); - } else if ((word & 0xa07f) == 0x26) { + } else if ((sval & 0xa07f) == 0x26) { /* fscale */ DPRINTF(("%s: fscale\n", __func__)); sig = fpu_emul_fscale(&fe, &insn); @@ -586,7 +584,7 @@ fpu_sgldiv(struct fpemu *fe) #if !defined(XM6i_FPE) /* - * arithmetic oprations + * arithmetic operations */ static int fpu_emul_arith(struct fpemu *fe, struct instruction *insn) @@ -950,7 +948,6 @@ test_cc(struct fpemu *fe, int pred) int fpsr; fpsr = fe->fe_fpsr; - fpsr &= ~FPSR_EXCP; /* clear all exceptions */ DPRINTF(("%s: fpsr=0x%08x\n", __func__, fpsr)); pred &= 0x3f; /* lowest 6 bits */ @@ -1024,6 +1021,10 @@ test_cc(struct fpemu *fe, int pred) if (sig_bsun && (fpsr & FPSR_NAN)) { fpsr |= FPSR_BSUN; } + /* if BSUN is set, IOP is set */ + if ((fpsr & FPSR_BSUN)) { + fpsr |= FPSR_AIOP; + } /* put fpsr back */ fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; @@ -1042,6 +1043,7 @@ fpu_emul_type1(struct fpemu *fe, struct { struct frame *frame = fe->fe_frame; int advance, sig, branch, displ; + unsigned short sval; branch = test_cc(fe, insn->is_word1); fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; @@ -1059,13 +1061,14 @@ fpu_emul_type1(struct fpemu *fe, struct uint16_t count = frame->f_regs[insn->is_opcode & 7]; if (count-- != 0) { - displ = fusword((void *)(insn->is_pc + - insn->is_advance)); - if (displ < 0) { + if (ufetch_short((void *)(insn->is_pc + + insn->is_advance), + &sval)) { DPRINTF(("%s: fault reading " "displacement\n", __func__)); return SIGSEGV; } + displ = sval; /* sign-extend the displacement */ displ &= 0xffff; if (displ & 0x8000) { @@ -1144,6 +1147,7 @@ fpu_emul_brcc(struct fpemu *fe, struct i { int displ, word2; int sig; + unsigned short sval; /* * Get branch displacement. @@ -1152,11 +1156,12 @@ fpu_emul_brcc(struct fpemu *fe, struct i displ = insn->is_word1; if (insn->is_opcode & 0x40) { - word2 = fusword((void *)(insn->is_pc + insn->is_advance)); - if (word2 < 0) { + if (ufetch_short((void *)(insn->is_pc + insn->is_advance), + &sval)) { DPRINTF(("%s: fault reading word2\n", __func__)); return SIGSEGV; } + word2 = sval; displ <<= 16; displ |= word2; insn->is_advance += 2; @@ -1190,3 +1195,23 @@ fpu_emul_brcc(struct fpemu *fe, struct i return 0; } #endif /* !XM6i_FPE */ + +#if defined(XM6i_FPE) +// fpn のタグ情報のうち、ゼロ、Inf、NAN、それ以外(ここでは正規化数)を返す。 +// 非正規化数とアンノーマル数はここに来る前に弾いてある。 +// 68040 の FSAVE で使う。 +int +fpu_gettag(const struct fpn *fpn) +{ + if (ISZERO(fpn)) { + return 1; + } + if (ISINF(fpn)) { + return 2; + } + if (ISNAN(fpn)) { + return 3; + } + return 0; +} +#endif