Module Name: src Committed By: tsutsui Date: Mon May 23 14:52:31 UTC 2011
Modified Files: src/sys/arch/m68k/fpe: fpu_emulate.c Log Message: KNF, mostly indent. No binary change. To generate a diff of this commit: cvs rdiff -u -r1.31 -r1.32 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.31 src/sys/arch/m68k/fpe/fpu_emulate.c:1.32 --- src/sys/arch/m68k/fpe/fpu_emulate.c:1.31 Sat May 14 16:17:55 2011 +++ src/sys/arch/m68k/fpe/fpu_emulate.c Mon May 23 14:52:31 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: fpu_emulate.c,v 1.31 2011/05/14 16:17:55 tsutsui Exp $ */ +/* $NetBSD: fpu_emulate.c,v 1.32 2011/05/23 14:52:31 tsutsui Exp $ */ /* * Copyright (c) 1995 Gordon W. Ross @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.31 2011/05/14 16:17:55 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: fpu_emulate.c,v 1.32 2011/05/23 14:52:31 tsutsui Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -51,29 +51,29 @@ #include "fpu_emulate.h" -#define fpe_abort(tfp, ksi, signo, code) \ - do { \ - (ksi)->ksi_signo = (signo); \ - (ksi)->ksi_code = (code); \ - (ksi)->ksi_addr = (void *)(frame)->f_pc; \ - return -1; \ - } while (/*CONSTCOND*/0) - -static int fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn); -static int fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn); -static int fpu_emul_arith(struct fpemu *fe, struct instruction *insn); -static int fpu_emul_type1(struct fpemu *fe, struct instruction *insn); -static int fpu_emul_brcc(struct fpemu *fe, struct instruction *insn); -static int test_cc(struct fpemu *fe, int pred); -static struct fpn *fpu_cmp(struct fpemu *fe); - -#if DEBUG_FPE -# define DUMP_INSN(insn) \ - printf("fpu_emulate: insn={adv=%d,siz=%d,op=%04x,w1=%04x}\n", \ - (insn)->is_advance, (insn)->is_datasize, \ - (insn)->is_opcode, (insn)->is_word1) +#define fpe_abort(tfp, ksi, signo, code) \ + do { \ + (ksi)->ksi_signo = (signo); \ + (ksi)->ksi_code = (code); \ + (ksi)->ksi_addr = (void *)(frame)->f_pc; \ + return -1; \ + } while (/* CONSTCOND */ 0) + +static int fpu_emul_fmovmcr(struct fpemu *, struct instruction *); +static int fpu_emul_fmovm(struct fpemu *, struct instruction *); +static int fpu_emul_arith(struct fpemu *, struct instruction *); +static int fpu_emul_type1(struct fpemu *, struct instruction *); +static int fpu_emul_brcc(struct fpemu *, struct instruction *); +static int test_cc(struct fpemu *, int); +static struct fpn *fpu_cmp(struct fpemu *); + +#if DEBUG_FPE +#define DUMP_INSN(insn) \ + printf("fpu_emulate: insn={adv=%d,siz=%d,op=%04x,w1=%04x}\n", \ + (insn)->is_advance, (insn)->is_datasize, \ + (insn)->is_opcode, (insn)->is_word1) #else -# define DUMP_INSN(insn) +#define DUMP_INSN(insn) #endif /* @@ -84,370 +84,378 @@ int fpu_emulate(struct frame *frame, struct fpframe *fpf, ksiginfo_t *ksi) { - static struct instruction insn; - static struct fpemu fe; - int word, optype, sig; - - - /* initialize insn.is_datasize to tell it is *not* initialized */ - insn.is_datasize = -1; - - fe.fe_frame = frame; - fe.fe_fpframe = fpf; - fe.fe_fpsr = fpf->fpf_fpsr; - fe.fe_fpcr = fpf->fpf_fpcr; - -#if DEBUG_FPE - printf("ENTERING fpu_emulate: FPSR=%08x, FPCR=%08x\n", - fe.fe_fpsr, fe.fe_fpcr); + static struct instruction insn; + static struct fpemu fe; + int word, optype, sig; + + + /* initialize insn.is_datasize to tell it is *not* initialized */ + insn.is_datasize = -1; + + fe.fe_frame = frame; + fe.fe_fpframe = fpf; + fe.fe_fpsr = fpf->fpf_fpsr; + fe.fe_fpcr = fpf->fpf_fpcr; + +#if DEBUG_FPE + printf("ENTERING fpu_emulate: FPSR=%08x, FPCR=%08x\n", + fe.fe_fpsr, fe.fe_fpcr); +#endif + + /* always set this (to avoid a warning) */ + insn.is_pc = frame->f_pc; + insn.is_nextpc = 0; + if (frame->f_format == 4) { + /* + * A format 4 is generated by the 68{EC,LC}040. The PC is + * already set to the instruction following the faulting + * instruction. We need to calculate that, anyway. The + * fslw is the PC of the faulted instruction, which is what + * we expect to be in f_pc. + * + * XXX - This is a hack; it assumes we at least know the + * sizes of all instructions we run across. + * XXX TODO: This may not be true, so we might want to save + * the PC in order to restore it later. + */ +#if 0 + insn.is_nextpc = frame->f_pc; #endif + insn.is_pc = frame->f_fmt4.f_fslw; + frame->f_pc = insn.is_pc; + } - /* always set this (to avoid a warning) */ - insn.is_pc = frame->f_pc; - insn.is_nextpc = 0; - if (frame->f_format == 4) { - /* - * A format 4 is generated by the 68{EC,LC}040. The PC is - * already set to the instruction following the faulting - * instruction. We need to calculate that, anyway. The - * fslw is the PC of the faulted instruction, which is what - * we expect to be in f_pc. - * - * XXX - This is a hack; it assumes we at least know the - * sizes of all instructions we run across. - * XXX TODO: This may not be true, so we might want to save the PC - * in order to restore it later. - */ - /* insn.is_nextpc = frame->f_pc; */ - insn.is_pc = frame->f_fmt4.f_fslw; - frame->f_pc = insn.is_pc; - } - - word = fusword((void *) (insn.is_pc)); - if (word < 0) { + word = fusword((void *)(insn.is_pc)); + if (word < 0) { #ifdef DEBUG - printf("fpu_emulate: fault reading opcode\n"); + printf("fpu_emulate: fault reading opcode\n"); #endif - fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); - } + fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); + } - if ((word & 0xf000) != 0xf000) { + if ((word & 0xf000) != 0xf000) { #ifdef DEBUG - printf("fpu_emulate: not coproc. insn.: opcode=0x%x\n", word); + printf("fpu_emulate: not coproc. insn.: opcode=0x%x\n", word); #endif - fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); - } + fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); + } - if ((word & 0x0E00) != 0x0200) { + if ((word & 0x0E00) != 0x0200) { #ifdef DEBUG - printf("fpu_emulate: bad coproc. id: opcode=0x%x\n", word); + printf("fpu_emulate: bad coproc. id: opcode=0x%x\n", word); #endif - fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); - } + fpe_abort(frame, ksi, SIGILL, ILL_ILLOPC); + } - insn.is_opcode = word; - optype = (word & 0x01C0); + insn.is_opcode = word; + optype = (word & 0x01C0); - word = fusword((void *) (insn.is_pc + 2)); - if (word < 0) { + word = fusword((void *)(insn.is_pc + 2)); + if (word < 0) { #ifdef DEBUG - printf("fpu_emulate: fault reading word1\n"); + printf("fpu_emulate: fault reading word1\n"); #endif - fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); - } - insn.is_word1 = word; - /* all FPU instructions are at least 4-byte long */ - insn.is_advance = 4; + fpe_abort(frame, ksi, SIGSEGV, SEGV_ACCERR); + } + insn.is_word1 = word; + /* all FPU instructions are at least 4-byte long */ + insn.is_advance = 4; - DUMP_INSN(&insn); + DUMP_INSN(&insn); - /* - * Which family (or type) of opcode is it? - * Tests ordered by likelihood (hopefully). - * Certainly, type 0 is the most common. - */ - if (optype == 0x0000) { - /* type=0: generic */ - if ((word & 0xc000) == 0xc000) { + /* + * Which family (or type) of opcode is it? + * Tests ordered by likelihood (hopefully). + * Certainly, type 0 is the most common. + */ + if (optype == 0x0000) { + /* type=0: generic */ + if ((word & 0xc000) == 0xc000) { #if DEBUG_FPE - printf("fpu_emulate: fmovm FPr\n"); + printf("fpu_emulate: fmovm FPr\n"); #endif - sig = fpu_emul_fmovm(&fe, &insn); - } else if ((word & 0xc000) == 0x8000) { + sig = fpu_emul_fmovm(&fe, &insn); + } else if ((word & 0xc000) == 0x8000) { #if DEBUG_FPE - printf("fpu_emulate: fmovm FPcr\n"); + printf("fpu_emulate: fmovm FPcr\n"); #endif - sig = fpu_emul_fmovmcr(&fe, &insn); - } else if ((word & 0xe000) == 0x6000) { - /* fstore = fmove FPn,mem */ + sig = fpu_emul_fmovmcr(&fe, &insn); + } else if ((word & 0xe000) == 0x6000) { + /* fstore = fmove FPn,mem */ #if DEBUG_FPE - printf("fpu_emulate: fmove to mem\n"); + printf("fpu_emulate: fmove to mem\n"); #endif - sig = fpu_emul_fstore(&fe, &insn); - } else if ((word & 0xfc00) == 0x5c00) { - /* fmovecr */ + sig = fpu_emul_fstore(&fe, &insn); + } else if ((word & 0xfc00) == 0x5c00) { + /* fmovecr */ #if DEBUG_FPE - printf("fpu_emulate: fmovecr\n"); + printf("fpu_emulate: fmovecr\n"); #endif - sig = fpu_emul_fmovecr(&fe, &insn); - } else if ((word & 0xa07f) == 0x26) { - /* fscale */ + sig = fpu_emul_fmovecr(&fe, &insn); + } else if ((word & 0xa07f) == 0x26) { + /* fscale */ #if DEBUG_FPE - printf("fpu_emulate: fscale\n"); + printf("fpu_emulate: fscale\n"); #endif - sig = fpu_emul_fscale(&fe, &insn); - } else { + sig = fpu_emul_fscale(&fe, &insn); + } else { #if DEBUG_FPE - printf("fpu_emulate: other type0\n"); + printf("fpu_emulate: other type0\n"); #endif - /* all other type0 insns are arithmetic */ - sig = fpu_emul_arith(&fe, &insn); - } - if (sig == 0) { + /* all other type0 insns are arithmetic */ + sig = fpu_emul_arith(&fe, &insn); + } + if (sig == 0) { #if DEBUG_FPE - printf("fpu_emulate: type 0 returned 0\n"); + printf("fpu_emulate: type 0 returned 0\n"); #endif - sig = fpu_upd_excp(&fe); - } - } else if (optype == 0x0080 || optype == 0x00C0) { - /* type=2 or 3: fbcc, short or long disp. */ + sig = fpu_upd_excp(&fe); + } + } else if (optype == 0x0080 || optype == 0x00C0) { + /* type=2 or 3: fbcc, short or long disp. */ #if DEBUG_FPE - printf("fpu_emulate: fbcc %s\n", - (optype & 0x40) ? "long" : "short"); + printf("fpu_emulate: fbcc %s\n", + (optype & 0x40) ? "long" : "short"); #endif - sig = fpu_emul_brcc(&fe, &insn); - } else if (optype == 0x0040) { - /* type=1: fdbcc, fscc, ftrapcc */ + sig = fpu_emul_brcc(&fe, &insn); + } else if (optype == 0x0040) { + /* type=1: fdbcc, fscc, ftrapcc */ #if DEBUG_FPE - printf("fpu_emulate: type1\n"); + printf("fpu_emulate: type1\n"); #endif - sig = fpu_emul_type1(&fe, &insn); - } else { - /* type=4: fsave (privileged) */ - /* type=5: frestore (privileged) */ - /* type=6: reserved */ - /* type=7: reserved */ + sig = fpu_emul_type1(&fe, &insn); + } else { + /* type=4: fsave (privileged) */ + /* type=5: frestore (privileged) */ + /* type=6: reserved */ + /* type=7: reserved */ #ifdef DEBUG - printf("fpu_emulate: bad opcode type: opcode=0x%x\n", insn.is_opcode); + printf("fpu_emulate: bad opcode type: opcode=0x%x\n", + insn.is_opcode); #endif - sig = SIGILL; - } + sig = SIGILL; + } - DUMP_INSN(&insn); + DUMP_INSN(&insn); - /* - * XXX it is not clear to me, if we should progress the PC always, - * for SIGFPE || 0, or only for 0; however, without SIGFPE, we - * don't pass the signalling regression tests. -is - */ - if ((sig == 0) || (sig == SIGFPE)) - frame->f_pc += insn.is_advance; + /* + * XXX it is not clear to me, if we should progress the PC always, + * for SIGFPE || 0, or only for 0; however, without SIGFPE, we + * don't pass the signalling regression tests. -is + */ + if ((sig == 0) || (sig == SIGFPE)) + frame->f_pc += insn.is_advance; #if defined(DDB) && defined(DEBUG_FPE) - else { - printf("fpu_emulate: sig=%d, opcode=%x, word1=%x\n", - sig, insn.is_opcode, insn.is_word1); - kdb_trap(-1, (db_regs_t *)&frame); - } + else { + printf("fpu_emulate: sig=%d, opcode=%x, word1=%x\n", + sig, insn.is_opcode, insn.is_word1); + kdb_trap(-1, (db_regs_t *)&frame); + } #endif #if 0 /* XXX something is wrong */ - if (frame->f_format == 4) { - /* XXX Restore PC -- 68{EC,LC}040 only */ - if (insn.is_nextpc) - frame->f_pc = insn.is_nextpc; - } + if (frame->f_format == 4) { + /* XXX Restore PC -- 68{EC,LC}040 only */ + if (insn.is_nextpc) + frame->f_pc = insn.is_nextpc; + } #endif #if DEBUG_FPE - printf("EXITING fpu_emulate: w/FPSR=%08x, FPCR=%08x\n", - fe.fe_fpsr, fe.fe_fpcr); + printf("EXITING fpu_emulate: w/FPSR=%08x, FPCR=%08x\n", + fe.fe_fpsr, fe.fe_fpcr); #endif - if (sig) - fpe_abort(frame, ksi, sig, 0); - return (sig); + if (sig) + fpe_abort(frame, ksi, sig, 0); + return sig; } /* update accrued exception bits and see if there's an FP exception */ int fpu_upd_excp(struct fpemu *fe) { - u_int fpsr; - u_int fpcr; + u_int fpsr; + u_int fpcr; - fpsr = fe->fe_fpsr; - fpcr = fe->fe_fpcr; - /* update fpsr accrued exception bits; each insn doesn't have to - update this */ - if (fpsr & (FPSR_BSUN | FPSR_SNAN | FPSR_OPERR)) { - fpsr |= FPSR_AIOP; - } - if (fpsr & FPSR_OVFL) { - fpsr |= FPSR_AOVFL; - } - if ((fpsr & FPSR_UNFL) && (fpsr & FPSR_INEX2)) { - fpsr |= FPSR_AUNFL; - } - if (fpsr & FPSR_DZ) { - fpsr |= FPSR_ADZ; - } - if (fpsr & (FPSR_INEX1 | FPSR_INEX2 | FPSR_OVFL)) { - fpsr |= FPSR_AINEX; - } + fpsr = fe->fe_fpsr; + fpcr = fe->fe_fpcr; + /* + * update fpsr accrued exception bits; each insn doesn't have to + * update this + */ + if (fpsr & (FPSR_BSUN | FPSR_SNAN | FPSR_OPERR)) { + fpsr |= FPSR_AIOP; + } + if (fpsr & FPSR_OVFL) { + fpsr |= FPSR_AOVFL; + } + if ((fpsr & FPSR_UNFL) && (fpsr & FPSR_INEX2)) { + fpsr |= FPSR_AUNFL; + } + if (fpsr & FPSR_DZ) { + fpsr |= FPSR_ADZ; + } + if (fpsr & (FPSR_INEX1 | FPSR_INEX2 | FPSR_OVFL)) { + fpsr |= FPSR_AINEX; + } - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; + fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; - return (fpsr & fpcr & FPSR_EXCP) ? SIGFPE : 0; + return (fpsr & fpcr & FPSR_EXCP) ? SIGFPE : 0; } /* update fpsr according to fp (= result of an fp op) */ u_int fpu_upd_fpsr(struct fpemu *fe, struct fpn *fp) { - u_int fpsr; + u_int fpsr; #if DEBUG_FPE - printf("fpu_upd_fpsr: previous fpsr=%08x\n", fe->fe_fpsr); + printf("fpu_upd_fpsr: previous fpsr=%08x\n", fe->fe_fpsr); #endif - /* clear all condition code */ - fpsr = fe->fe_fpsr & ~FPSR_CCB; + /* clear all condition code */ + fpsr = fe->fe_fpsr & ~FPSR_CCB; #if DEBUG_FPE - printf("fpu_upd_fpsr: result is a "); + printf("fpu_upd_fpsr: result is a "); #endif - if (fp->fp_sign) { + if (fp->fp_sign) { #if DEBUG_FPE - printf("negative "); + printf("negative "); #endif - fpsr |= FPSR_NEG; + fpsr |= FPSR_NEG; #if DEBUG_FPE - } else { - printf("positive "); + } else { + printf("positive "); #endif - } + } - switch (fp->fp_class) { - case FPC_SNAN: + switch (fp->fp_class) { + case FPC_SNAN: #if DEBUG_FPE - printf("signaling NAN\n"); + printf("signaling NAN\n"); #endif - fpsr |= (FPSR_NAN | FPSR_SNAN); - break; - case FPC_QNAN: + fpsr |= (FPSR_NAN | FPSR_SNAN); + break; + case FPC_QNAN: #if DEBUG_FPE - printf("quiet NAN\n"); + printf("quiet NAN\n"); #endif - fpsr |= FPSR_NAN; - break; - case FPC_ZERO: + fpsr |= FPSR_NAN; + break; + case FPC_ZERO: #if DEBUG_FPE - printf("Zero\n"); + printf("Zero\n"); #endif - fpsr |= FPSR_ZERO; - break; - case FPC_INF: + fpsr |= FPSR_ZERO; + break; + case FPC_INF: #if DEBUG_FPE - printf("Inf\n"); + printf("Inf\n"); #endif - fpsr |= FPSR_INF; - break; - default: + fpsr |= FPSR_INF; + break; + default: #if DEBUG_FPE - printf("Number\n"); + printf("Number\n"); #endif - /* anything else is treated as if it is a number */ - break; - } + /* anything else is treated as if it is a number */ + break; + } - fe->fe_fpsr = fe->fe_fpframe->fpf_fpsr = fpsr; + fe->fe_fpsr = fe->fe_fpframe->fpf_fpsr = fpsr; #if DEBUG_FPE - printf("fpu_upd_fpsr: new fpsr=%08x\n", fe->fe_fpframe->fpf_fpsr); + printf("fpu_upd_fpsr: new fpsr=%08x\n", fe->fe_fpframe->fpf_fpsr); #endif - return fpsr; + return fpsr; } static int fpu_emul_fmovmcr(struct fpemu *fe, struct instruction *insn) { - struct frame *frame = fe->fe_frame; - struct fpframe *fpf = fe->fe_fpframe; - int sig; - int reglist; - int fpu_to_mem; - - /* 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; - - insn->is_datasize = 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 */ + struct frame *frame = fe->fe_frame; + struct fpframe *fpf = fe->fe_fpframe; + int sig; + int reglist; + int fpu_to_mem; + + /* 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; + + insn->is_datasize = 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 */ #ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy too many FPcr\n"); + printf("fpu_emul_fmovmcr: tried to copy too many FPcr\n"); #endif - return SIGILL; - } + 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 */ + 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 */ #ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy FPCR from/to A%d\n", - insn->is_ea.ea_regnum & 7); + printf("fpu_emul_fmovmcr: tried to copy FPCR from/to " + "A%d\n", insn->is_ea.ea_regnum & 7); #endif - return SIGILL; - } - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpcr); - } else { - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char *)&fpf->fpf_fpcr); + return SIGILL; + } + if (fpu_to_mem) { + sig = fpu_store_ea(frame, insn, &insn->is_ea, + (char *)&fpf->fpf_fpcr); + } else { + sig = fpu_load_ea(frame, insn, &insn->is_ea, + (char *)&fpf->fpf_fpcr); + } } - } - if (sig) { return sig; } + 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 */ + 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 */ #ifdef DEBUG - printf("fpu_emul_fmovmcr: tried to copy FPSR from/to A%d\n", - insn->is_ea.ea_regnum & 7); + printf("fpu_emul_fmovmcr: tried to copy FPSR from/to " + "A%d\n", insn->is_ea.ea_regnum & 7); #endif - return SIGILL; - } - 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); + return SIGILL; + } + 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 (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); + 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); + } } - } - return sig; + return sig; } /* @@ -463,128 +471,141 @@ static int fpu_emul_fmovm(struct fpemu *fe, struct instruction *insn) { - struct frame *frame = fe->fe_frame; - struct fpframe *fpf = fe->fe_fpframe; - int word1, sig; - int reglist, regmask, regnum; - int fpu_to_mem, order; - int w1_post_incr; - int *fpregs; - - insn->is_advance = 4; - insn->is_datasize = 12; - word1 = insn->is_word1; - - /* Bit 13 selects direction (FPU to/from Mem) */ - fpu_to_mem = word1 & 0x2000; - - /* - * Bits 12,11 select register list mode: - * 0,0: Static reg list, pre-decr. - * 0,1: Dynamic reg list, pre-decr. - * 1,0: Static reg list, post-incr. - * 1,1: Dynamic reg list, post-incr - */ - w1_post_incr = word1 & 0x1000; - if (word1 & 0x0800) { - /* dynamic reg list */ - reglist = frame->f_regs[(word1 & 0x70) >> 4]; - } else { - reglist = word1; - } - reglist &= 0xFF; - - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); - if (sig) { return sig; } - - /* Get address of soft coprocessor regs. */ - fpregs = &fpf->fpf_regs[0]; - - if (insn->is_ea.ea_flags & EA_PREDECR) { - regnum = 7; - order = -1; - } else { - regnum = 0; - order = 1; - } - - regmask = 0x80; - while ((0 <= regnum) && (regnum < 8)) { - if (regmask & reglist) { - if (fpu_to_mem) { - sig = fpu_store_ea(frame, insn, &insn->is_ea, - (char*)&fpregs[regnum * 3]); -#if DEBUG_FPE - printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) saved\n", - regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], - fpregs[regnum * 3 + 2]); -#endif - } else { /* mem to fpu */ - sig = fpu_load_ea(frame, insn, &insn->is_ea, - (char*)&fpregs[regnum * 3]); -#if DEBUG_FPE - printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) loaded\n", - regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], - fpregs[regnum * 3 + 2]); -#endif - } - if (sig) { break; } - } - regnum += order; - regmask >>= 1; - } + struct frame *frame = fe->fe_frame; + struct fpframe *fpf = fe->fe_fpframe; + int word1, sig; + int reglist, regmask, regnum; + int fpu_to_mem, order; + int w1_post_incr; + int *fpregs; + + insn->is_advance = 4; + insn->is_datasize = 12; + word1 = insn->is_word1; + + /* Bit 13 selects direction (FPU to/from Mem) */ + fpu_to_mem = word1 & 0x2000; + + /* + * Bits 12,11 select register list mode: + * 0,0: Static reg list, pre-decr. + * 0,1: Dynamic reg list, pre-decr. + * 1,0: Static reg list, post-incr. + * 1,1: Dynamic reg list, post-incr + */ + w1_post_incr = word1 & 0x1000; + if (word1 & 0x0800) { + /* dynamic reg list */ + reglist = frame->f_regs[(word1 & 0x70) >> 4]; + } else { + reglist = word1; + } + reglist &= 0xFF; + + /* Get effective address. (modreg=opcode&077) */ + sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); + if (sig) + return sig; + + /* Get address of soft coprocessor regs. */ + fpregs = &fpf->fpf_regs[0]; + + if (insn->is_ea.ea_flags & EA_PREDECR) { + regnum = 7; + order = -1; + } else { + regnum = 0; + order = 1; + } + + regmask = 0x80; + while ((0 <= regnum) && (regnum < 8)) { + if (regmask & reglist) { + if (fpu_to_mem) { + sig = fpu_store_ea(frame, insn, &insn->is_ea, + (char *)&fpregs[regnum * 3]); +#if DEBUG_FPE + printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) " + "saved\n", regnum, + fpregs[regnum * 3], + fpregs[regnum * 3 + 1], + fpregs[regnum * 3 + 2]); +#endif + } else { /* mem to fpu */ + sig = fpu_load_ea(frame, insn, &insn->is_ea, + (char *)&fpregs[regnum * 3]); +#if DEBUG_FPE + printf("fpu_emul_fmovm: FP%d (%08x,%08x,%08x) " + "loaded\n", regnum, + fpregs[regnum * 3], + fpregs[regnum * 3 + 1], + fpregs[regnum * 3 + 2]); +#endif + } + if (sig) + break; + } + regnum += order; + regmask >>= 1; + } - return sig; + return sig; } static struct fpn * fpu_cmp(struct fpemu *fe) { - struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2; + struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2; - /* take care of special cases */ - if (x->fp_class < 0 || y->fp_class < 0) { - /* if either of two is a SNAN, result is SNAN */ - x->fp_class = (y->fp_class < x->fp_class) ? y->fp_class : x->fp_class; - } else if (x->fp_class == FPC_INF) { - if (y->fp_class == FPC_INF) { - /* both infinities */ - if (x->fp_sign == y->fp_sign) { - x->fp_class = FPC_ZERO; /* return a signed zero */ - } else { - x->fp_class = FPC_NUM; /* return a faked number w/x's sign */ + /* take care of special cases */ + if (x->fp_class < 0 || y->fp_class < 0) { + /* if either of two is a SNAN, result is SNAN */ + x->fp_class = + (y->fp_class < x->fp_class) ? y->fp_class : x->fp_class; + } else if (x->fp_class == FPC_INF) { + if (y->fp_class == FPC_INF) { + /* both infinities */ + if (x->fp_sign == y->fp_sign) { + /* return a signed zero */ + x->fp_class = FPC_ZERO; + } else { + /* return a faked number w/x's sign */ + x->fp_class = FPC_NUM; + x->fp_exp = 16383; + x->fp_mant[0] = FP_1; + } + } else { + /* y is a number */ + /* return a forged number w/x's sign */ + x->fp_class = FPC_NUM; + x->fp_exp = 16383; + x->fp_mant[0] = FP_1; + } + } else if (y->fp_class == FPC_INF) { + /* x is a Num but y is an Inf */ + /* return a forged number w/y's sign inverted */ + x->fp_class = FPC_NUM; + x->fp_sign = !y->fp_sign; x->fp_exp = 16383; x->fp_mant[0] = FP_1; - } } else { - /* y is a number */ - x->fp_class = FPC_NUM; /* return a forged number w/x's sign */ - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } - } else if (y->fp_class == FPC_INF) { - /* x is a Num but y is an Inf */ - /* return a forged number w/y's sign inverted */ - x->fp_class = FPC_NUM; - x->fp_sign = !y->fp_sign; - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; - } else { - /* x and y are both numbers or zeros, or pair of a number and a zero */ - y->fp_sign = !y->fp_sign; - x = fpu_add(fe); /* (x - y) */ - /* - * FCMP does not set Inf bit in CC, so return a forged number - * (value doesn't matter) if Inf is the result of fsub. - */ - if (x->fp_class == FPC_INF) { - x->fp_class = FPC_NUM; - x->fp_exp = 16383; - x->fp_mant[0] = FP_1; + /* + * x and y are both numbers or zeros, + * or pair of a number and a zero + */ + y->fp_sign = !y->fp_sign; + x = fpu_add(fe); /* (x - y) */ + /* + * FCMP does not set Inf bit in CC, so return a forged number + * (value doesn't matter) if Inf is the result of fsub. + */ + if (x->fp_class == FPC_INF) { + x->fp_class = FPC_NUM; + x->fp_exp = 16383; + x->fp_mant[0] = FP_1; + } } - } - return x; + return x; } /* @@ -593,474 +614,479 @@ static int fpu_emul_arith(struct fpemu *fe, struct instruction *insn) { - struct frame *frame = fe->fe_frame; - u_int *fpregs = &(fe->fe_fpframe->fpf_regs[0]); - struct fpn *res; - int word1, sig = 0; - int regnum, format; - int discard_result = 0; - u_int buf[3]; + struct frame *frame = fe->fe_frame; + u_int *fpregs = &(fe->fe_fpframe->fpf_regs[0]); + struct fpn *res; + int word1, sig = 0; + int regnum, format; + int discard_result = 0; + u_int buf[3]; #if DEBUG_FPE - int flags; - char regname; + int flags; + char regname; #endif - fe->fe_fpsr &= ~FPSR_EXCP; + fe->fe_fpsr &= ~FPSR_EXCP; - DUMP_INSN(insn); + DUMP_INSN(insn); #if DEBUG_FPE - printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", - fe->fe_fpsr, fe->fe_fpcr); + printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", + fe->fe_fpsr, fe->fe_fpcr); #endif - word1 = insn->is_word1; - format = (word1 >> 10) & 7; - regnum = (word1 >> 7) & 7; + word1 = insn->is_word1; + format = (word1 >> 10) & 7; + regnum = (word1 >> 7) & 7; - /* fetch a source operand : may not be used */ + /* fetch a source operand : may not be used */ #if DEBUG_FPE - printf("fpu_emul_arith: dst/src FP%d=%08x,%08x,%08x\n", - regnum, fpregs[regnum*3], fpregs[regnum*3+1], - fpregs[regnum*3+2]); + printf("fpu_emul_arith: dst/src FP%d=%08x,%08x,%08x\n", + regnum, fpregs[regnum * 3], fpregs[regnum * 3 + 1], + fpregs[regnum * 3 + 2]); #endif - fpu_explode(fe, &fe->fe_f1, FTYPE_EXT, &fpregs[regnum * 3]); + fpu_explode(fe, &fe->fe_f1, FTYPE_EXT, &fpregs[regnum * 3]); - DUMP_INSN(insn); + DUMP_INSN(insn); - /* get the other operand which is always the source */ - if ((word1 & 0x4000) == 0) { + /* get the other operand which is always the source */ + if ((word1 & 0x4000) == 0) { #if DEBUG_FPE - printf("fpu_emul_arith: FP%d op FP%d => FP%d\n", - format, regnum, regnum); - printf("fpu_emul_arith: src opr FP%d=%08x,%08x,%08x\n", - format, fpregs[format*3], fpregs[format*3+1], - fpregs[format*3+2]); + printf("fpu_emul_arith: FP%d op FP%d => FP%d\n", + format, regnum, regnum); + printf("fpu_emul_arith: src opr FP%d=%08x,%08x,%08x\n", + format, fpregs[format * 3], fpregs[format * 3 + 1], + fpregs[format * 3 + 2]); #endif - fpu_explode(fe, &fe->fe_f2, FTYPE_EXT, &fpregs[format * 3]); - } else { - /* the operand is in memory */ - if (format == FTYPE_DBL) { - insn->is_datasize = 8; - } else if (format == FTYPE_SNG || format == FTYPE_LNG) { - insn->is_datasize = 4; - } else if (format == FTYPE_WRD) { - insn->is_datasize = 2; - } else if (format == FTYPE_BYT) { - insn->is_datasize = 1; - } else if (format == FTYPE_EXT) { - insn->is_datasize = 12; + fpu_explode(fe, &fe->fe_f2, FTYPE_EXT, &fpregs[format * 3]); } else { - /* invalid or unsupported operand format */ - sig = SIGFPE; - return sig; - } + /* the operand is in memory */ + if (format == FTYPE_DBL) { + insn->is_datasize = 8; + } else if (format == FTYPE_SNG || format == FTYPE_LNG) { + insn->is_datasize = 4; + } else if (format == FTYPE_WRD) { + insn->is_datasize = 2; + } else if (format == FTYPE_BYT) { + insn->is_datasize = 1; + } else if (format == FTYPE_EXT) { + insn->is_datasize = 12; + } else { + /* invalid or unsupported operand format */ + sig = SIGFPE; + return sig; + } - /* Get effective address. (modreg=opcode&077) */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); - if (sig) { + /* Get effective address. (modreg=opcode&077) */ + sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); + if (sig) { #if DEBUG_FPE - printf("fpu_emul_arith: error in fpu_decode_ea\n"); + printf("fpu_emul_arith: error in fpu_decode_ea\n"); #endif - return sig; - } + return sig; + } - DUMP_INSN(insn); + DUMP_INSN(insn); #if DEBUG_FPE - printf("fpu_emul_arith: addr mode = "); - flags = insn->is_ea.ea_flags; - regname = (insn->is_ea.ea_regnum & 8) ? 'a' : 'd'; - - if (flags & EA_DIRECT) { - printf("%c%d\n", - regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_PC_REL) { - if (flags & EA_OFFSET) { - printf("pc@(%d)\n", insn->is_ea.ea_offset); - } else if (flags & EA_INDEXED) { - printf("pc@(...)\n"); - } - } else if (flags & EA_PREDECR) { - printf("%c%d@-\n", - regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_POSTINCR) { - printf("%c%d@+\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_OFFSET) { - printf("%c%d@(%d)\n", regname, insn->is_ea.ea_regnum & 7, - insn->is_ea.ea_offset); - } else if (flags & EA_INDEXED) { - printf("%c%d@(...)\n", regname, insn->is_ea.ea_regnum & 7); - } else if (flags & EA_ABS) { - printf("0x%08x\n", insn->is_ea.ea_absaddr); - } else if (flags & EA_IMMED) { + printf("fpu_emul_arith: addr mode = "); + flags = insn->is_ea.ea_flags; + regname = (insn->is_ea.ea_regnum & 8) ? 'a' : 'd'; + + if (flags & EA_DIRECT) { + printf("%c%d\n", + regname, insn->is_ea.ea_regnum & 7); + } else if (flags & EA_PC_REL) { + if (flags & EA_OFFSET) { + printf("pc@(%d)\n", insn->is_ea.ea_offset); + } else if (flags & EA_INDEXED) { + printf("pc@(...)\n"); + } + } else if (flags & EA_PREDECR) { + printf("%c%d@-\n", + regname, insn->is_ea.ea_regnum & 7); + } else if (flags & EA_POSTINCR) { + printf("%c%d@+\n", regname, insn->is_ea.ea_regnum & 7); + } else if (flags & EA_OFFSET) { + printf("%c%d@(%d)\n", regname, + insn->is_ea.ea_regnum & 7, + insn->is_ea.ea_offset); + } else if (flags & EA_INDEXED) { + printf("%c%d@(...)\n", regname, + insn->is_ea.ea_regnum & 7); + } else if (flags & EA_ABS) { + printf("0x%08x\n", insn->is_ea.ea_absaddr); + } else if (flags & EA_IMMED) { + printf("#0x%08x,%08x,%08x\n", insn->is_ea.ea_immed[0], + insn->is_ea.ea_immed[1], insn->is_ea.ea_immed[2]); + } else { + printf("%c%d@\n", regname, insn->is_ea.ea_regnum & 7); + } +#endif /* DEBUG_FPE */ - printf("#0x%08x,%08x,%08x\n", insn->is_ea.ea_immed[0], - insn->is_ea.ea_immed[1], insn->is_ea.ea_immed[2]); - } else { - printf("%c%d@\n", regname, insn->is_ea.ea_regnum & 7); + fpu_load_ea(frame, insn, &insn->is_ea, (char*)buf); + if (format == FTYPE_WRD) { + /* sign-extend */ + buf[0] &= 0xffff; + if (buf[0] & 0x8000) + buf[0] |= 0xffff0000; + format = FTYPE_LNG; + } else if (format == FTYPE_BYT) { + /* sign-extend */ + buf[0] &= 0xff; + if (buf[0] & 0x80) + buf[0] |= 0xffffff00; + format = FTYPE_LNG; + } +#if DEBUG_FPE + printf("fpu_emul_arith: src = %08x %08x %08x, siz = %d\n", + buf[0], buf[1], buf[2], insn->is_datasize); +#endif + fpu_explode(fe, &fe->fe_f2, format, buf); } -#endif /* DEBUG_FPE */ - fpu_load_ea(frame, insn, &insn->is_ea, (char*)buf); - if (format == FTYPE_WRD) { - /* sign-extend */ - buf[0] &= 0xffff; - if (buf[0] & 0x8000) { - buf[0] |= 0xffff0000; - } - format = FTYPE_LNG; - } else if (format == FTYPE_BYT) { - /* sign-extend */ - buf[0] &= 0xff; - if (buf[0] & 0x80) { - buf[0] |= 0xffffff00; - } - format = FTYPE_LNG; - } -#if DEBUG_FPE - printf("fpu_emul_arith: src = %08x %08x %08x, siz = %d\n", - buf[0], buf[1], buf[2], insn->is_datasize); -#endif - fpu_explode(fe, &fe->fe_f2, format, buf); - } - - DUMP_INSN(insn); - - /* An arithmetic instruction emulate function has a prototype of - * struct fpn *fpu_op(struct fpemu *); - - * 1) If the instruction is monadic, then fpu_op() must use - * fe->fe_f2 as its operand, and return a pointer to the - * result. - - * 2) If the instruction is diadic, then fpu_op() must use - * fe->fe_f1 and fe->fe_f2 as its two operands, and return a - * pointer to the result. - - */ - res = NULL; - switch (word1 & 0x7f) { - case 0x00: /* fmove */ - res = &fe->fe_f2; - break; - - case 0x01: /* fint */ - res = fpu_int(fe); - break; - - case 0x02: /* fsinh */ - res = fpu_sinh(fe); - break; - - case 0x03: /* fintrz */ - res = fpu_intrz(fe); - break; - - case 0x04: /* fsqrt */ - res = fpu_sqrt(fe); - break; - - case 0x06: /* flognp1 */ - res = fpu_lognp1(fe); - break; - - case 0x08: /* fetoxm1 */ - res = fpu_etoxm1(fe); - break; - - case 0x09: /* ftanh */ - res = fpu_tanh(fe); - break; - - case 0x0A: /* fatan */ - res = fpu_atan(fe); - break; - - case 0x0C: /* fasin */ - res = fpu_asin(fe); - break; - - case 0x0D: /* fatanh */ - res = fpu_atanh(fe); - break; - - case 0x0E: /* fsin */ - res = fpu_sin(fe); - break; - - case 0x0F: /* ftan */ - res = fpu_tan(fe); - break; - - case 0x10: /* fetox */ - res = fpu_etox(fe); - break; - - case 0x11: /* ftwotox */ - res = fpu_twotox(fe); - break; - - case 0x12: /* ftentox */ - res = fpu_tentox(fe); - break; - - case 0x14: /* flogn */ - res = fpu_logn(fe); - break; - - case 0x15: /* flog10 */ - res = fpu_log10(fe); - break; - - case 0x16: /* flog2 */ - res = fpu_log2(fe); - break; - - case 0x18: /* fabs */ - fe->fe_f2.fp_sign = 0; - res = &fe->fe_f2; - break; - - case 0x19: /* fcosh */ - res = fpu_cosh(fe); - break; - - case 0x1A: /* fneg */ - fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; - res = &fe->fe_f2; - break; - - case 0x1C: /* facos */ - res = fpu_acos(fe); - break; - - case 0x1D: /* fcos */ - res = fpu_cos(fe); - break; - - case 0x1E: /* fgetexp */ - res = fpu_getexp(fe); - break; - - case 0x1F: /* fgetman */ - res = fpu_getman(fe); - break; - - case 0x20: /* fdiv */ - case 0x24: /* fsgldiv: cheating - better than nothing */ - res = fpu_div(fe); - break; - - case 0x21: /* fmod */ - res = fpu_mod(fe); - break; - - case 0x28: /* fsub */ - fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */ - case 0x22: /* fadd */ - res = fpu_add(fe); - break; - - case 0x23: /* fmul */ - case 0x27: /* fsglmul: cheating - better than nothing */ - res = fpu_mul(fe); - break; - - case 0x25: /* frem */ - res = fpu_rem(fe); - break; - - case 0x26: - /* fscale is handled by a separate function */ - break; - - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: /* fsincos */ - res = fpu_sincos(fe, word1 & 7); - break; - - case 0x38: /* fcmp */ - res = fpu_cmp(fe); - discard_result = 1; - break; - - case 0x3A: /* ftst */ - res = &fe->fe_f2; - discard_result = 1; - break; + DUMP_INSN(insn); + + /* + * An arithmetic instruction emulate function has a prototype of + * struct fpn *fpu_op(struct fpemu *); + * + * 1) If the instruction is monadic, then fpu_op() must use + * fe->fe_f2 as its operand, and return a pointer to the + * result. + * + * 2) If the instruction is diadic, then fpu_op() must use + * fe->fe_f1 and fe->fe_f2 as its two operands, and return a + * pointer to the result. + * + */ + res = NULL; + switch (word1 & 0x7f) { + case 0x00: /* fmove */ + res = &fe->fe_f2; + break; + + case 0x01: /* fint */ + res = fpu_int(fe); + break; + + case 0x02: /* fsinh */ + res = fpu_sinh(fe); + break; + + case 0x03: /* fintrz */ + res = fpu_intrz(fe); + break; + + case 0x04: /* fsqrt */ + res = fpu_sqrt(fe); + break; + + case 0x06: /* flognp1 */ + res = fpu_lognp1(fe); + break; + + case 0x08: /* fetoxm1 */ + res = fpu_etoxm1(fe); + break; + + case 0x09: /* ftanh */ + res = fpu_tanh(fe); + break; + + case 0x0A: /* fatan */ + res = fpu_atan(fe); + break; + + case 0x0C: /* fasin */ + res = fpu_asin(fe); + break; + + case 0x0D: /* fatanh */ + res = fpu_atanh(fe); + break; + + case 0x0E: /* fsin */ + res = fpu_sin(fe); + break; + + case 0x0F: /* ftan */ + res = fpu_tan(fe); + break; + + case 0x10: /* fetox */ + res = fpu_etox(fe); + break; + + case 0x11: /* ftwotox */ + res = fpu_twotox(fe); + break; + + case 0x12: /* ftentox */ + res = fpu_tentox(fe); + break; + + case 0x14: /* flogn */ + res = fpu_logn(fe); + break; + + case 0x15: /* flog10 */ + res = fpu_log10(fe); + break; + + case 0x16: /* flog2 */ + res = fpu_log2(fe); + break; + + case 0x18: /* fabs */ + fe->fe_f2.fp_sign = 0; + res = &fe->fe_f2; + break; + + case 0x19: /* fcosh */ + res = fpu_cosh(fe); + break; + + case 0x1A: /* fneg */ + fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; + res = &fe->fe_f2; + break; + + case 0x1C: /* facos */ + res = fpu_acos(fe); + break; + + case 0x1D: /* fcos */ + res = fpu_cos(fe); + break; + + case 0x1E: /* fgetexp */ + res = fpu_getexp(fe); + break; + + case 0x1F: /* fgetman */ + res = fpu_getman(fe); + break; + + case 0x20: /* fdiv */ + case 0x24: /* fsgldiv: cheating - better than nothing */ + res = fpu_div(fe); + break; + + case 0x21: /* fmod */ + res = fpu_mod(fe); + break; - default: /* possibly 040/060 instructions */ + case 0x28: /* fsub */ + fe->fe_f2.fp_sign = !fe->fe_f2.fp_sign; /* f2 = -f2 */ + /* FALLTHROUGH */ + case 0x22: /* fadd */ + res = fpu_add(fe); + break; + + case 0x23: /* fmul */ + case 0x27: /* fsglmul: cheating - better than nothing */ + res = fpu_mul(fe); + break; + + case 0x25: /* frem */ + res = fpu_rem(fe); + break; + + case 0x26: + /* fscale is handled by a separate function */ + break; + + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: /* fsincos */ + res = fpu_sincos(fe, word1 & 7); + break; + + case 0x38: /* fcmp */ + res = fpu_cmp(fe); + discard_result = 1; + break; + + case 0x3A: /* ftst */ + res = &fe->fe_f2; + discard_result = 1; + break; + + default: /* possibly 040/060 instructions */ #ifdef DEBUG - printf("fpu_emul_arith: bad opcode=0x%x, word1=0x%x\n", - insn->is_opcode, insn->is_word1); + printf("fpu_emul_arith: bad opcode=0x%x, word1=0x%x\n", + insn->is_opcode, insn->is_word1); #endif - sig = SIGILL; - } /* switch (word1 & 0x3f) */ - - /* for sanity */ - if (res == NULL) - sig = SIGILL; - - if (sig == 0) { - if (!discard_result) - fpu_implode(fe, res, FTYPE_EXT, &fpregs[regnum * 3]); - - /* update fpsr according to the result of operation */ - fpu_upd_fpsr(fe, res); -#if DEBUG_FPE - if (!discard_result) { - printf("fpu_emul_arith: %08x,%08x,%08x stored in FP%d\n", - fpregs[regnum*3], fpregs[regnum*3+1], - fpregs[regnum*3+2], regnum); - } else { - static const char *class_name[] = - { "SNAN", "QNAN", "ZERO", "NUM", "INF" }; - printf("fpu_emul_arith: result(%s,%c,%d,%08x,%08x,%08x)" - " discarded\n", - class_name[res->fp_class + 2], - res->fp_sign ? '-' : '+', res->fp_exp, - res->fp_mant[0], res->fp_mant[1], - res->fp_mant[2]); + sig = SIGILL; } + + /* for sanity */ + if (res == NULL) + sig = SIGILL; + + if (sig == 0) { + if (!discard_result) + fpu_implode(fe, res, FTYPE_EXT, &fpregs[regnum * 3]); + + /* update fpsr according to the result of operation */ + fpu_upd_fpsr(fe, res); +#if DEBUG_FPE + if (!discard_result) { + printf("fpu_emul_arith: %08x,%08x,%08x stored in " + "FP%d\n", + fpregs[regnum * 3], + fpregs[regnum * 3 + 1], + fpregs[regnum * 3 + 2], + regnum); + } else { + static const char *class_name[] = + { "SNAN", "QNAN", "ZERO", "NUM", "INF" }; + printf("fpu_emul_arith: result(%s,%c,%d,%08x,%08x,%08x)" + " discarded\n", + class_name[res->fp_class + 2], + res->fp_sign ? '-' : '+', res->fp_exp, + res->fp_mant[0], res->fp_mant[1], + res->fp_mant[2]); + } #endif - } + } #if DEBUG_FPE - else { - printf("fpu_emul_arith: received signal %d\n", sig); - } + else { + printf("fpu_emul_arith: received signal %d\n", sig); + } #endif #if DEBUG_FPE - printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", - fe->fe_fpsr, fe->fe_fpcr); + printf("fpu_emul_arith: FPSR = %08x, FPCR = %08x\n", + fe->fe_fpsr, fe->fe_fpcr); #endif - DUMP_INSN(insn); + DUMP_INSN(insn); - return sig; + return sig; } -/* test condition code according to the predicate in the opcode. +/* + * test condition code according to the predicate in the opcode. * returns -1 when the predicate evaluates to true, 0 when false. * signal numbers are returned when an error is detected. */ static int test_cc(struct fpemu *fe, int pred) { - int result, sig_bsun, invert; - int fpsr; + int result, sig_bsun, invert; + int fpsr; - fpsr = fe->fe_fpsr; - invert = 0; - fpsr &= ~FPSR_EXCP; /* clear all exceptions */ + fpsr = fe->fe_fpsr; + invert = 0; + fpsr &= ~FPSR_EXCP; /* clear all exceptions */ #if DEBUG_FPE - printf("test_cc: fpsr=0x%08x\n", fpsr); + printf("test_cc: fpsr=0x%08x\n", fpsr); #endif - pred &= 0x3f; /* lowest 6 bits */ + pred &= 0x3f; /* lowest 6 bits */ #if DEBUG_FPE - printf("test_cc: "); + printf("test_cc: "); #endif - if (pred >= 0x20) { - return SIGILL; - } else if (pred & 0x10) { - /* IEEE nonaware tests */ - sig_bsun = 1; - pred &= 0x0f; /* lower 4 bits */ - } else { - /* IEEE aware tests */ + if (pred >= 0x20) { + return SIGILL; + } else if (pred & 0x10) { + /* IEEE nonaware tests */ + sig_bsun = 1; + pred &= 0x0f; /* lower 4 bits */ + } else { + /* IEEE aware tests */ #if DEBUG_FPE - printf("IEEE "); + printf("IEEE "); #endif - sig_bsun = 0; - } + sig_bsun = 0; + } - if (pred & 0x08) { + if (pred & 0x08) { #if DEBUG_FPE - printf("Not "); + printf("Not "); #endif - /* predicate is "NOT ..." */ - pred ^= 0xf; /* invert */ - invert = -1; - } - switch (pred) { - case 0: /* (Signaling) False */ + /* predicate is "NOT ..." */ + pred ^= 0xf; /* invert */ + invert = -1; + } + switch (pred) { + case 0: /* (Signaling) False */ #if DEBUG_FPE - printf("False"); + printf("False"); #endif - result = 0; - break; - case 1: /* (Signaling) Equal */ + result = 0; + break; + case 1: /* (Signaling) Equal */ #if DEBUG_FPE - printf("Equal"); + printf("Equal"); #endif - result = -((fpsr & FPSR_ZERO) == FPSR_ZERO); - break; - case 2: /* Greater Than */ + result = -((fpsr & FPSR_ZERO) == FPSR_ZERO); + break; + case 2: /* Greater Than */ #if DEBUG_FPE - printf("GT"); + printf("GT"); #endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == 0); - break; - case 3: /* Greater or Equal */ + result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == 0); + break; + case 3: /* Greater or Equal */ #if DEBUG_FPE - printf("GE"); + printf("GE"); #endif - result = -((fpsr & FPSR_ZERO) || - (fpsr & (FPSR_NAN|FPSR_NEG)) == 0); - break; - case 4: /* Less Than */ + result = -((fpsr & FPSR_ZERO) || + (fpsr & (FPSR_NAN|FPSR_NEG)) == 0); + break; + case 4: /* Less Than */ #if DEBUG_FPE - printf("LT"); + printf("LT"); #endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == FPSR_NEG); - break; - case 5: /* Less or Equal */ + result = -((fpsr & (FPSR_NAN|FPSR_ZERO|FPSR_NEG)) == FPSR_NEG); + break; + case 5: /* Less or Equal */ #if DEBUG_FPE - printf("LE"); + printf("LE"); #endif - result = -((fpsr & FPSR_ZERO) || - ((fpsr & (FPSR_NAN|FPSR_NEG)) == FPSR_NEG)); - break; - case 6: /* Greater or Less than */ + result = -((fpsr & FPSR_ZERO) || + ((fpsr & (FPSR_NAN|FPSR_NEG)) == FPSR_NEG)); + break; + case 6: /* Greater or Less than */ #if DEBUG_FPE - printf("GLT"); + printf("GLT"); #endif - result = -((fpsr & (FPSR_NAN|FPSR_ZERO)) == 0); - break; - case 7: /* Greater, Less or Equal */ + result = -((fpsr & (FPSR_NAN|FPSR_ZERO)) == 0); + break; + case 7: /* Greater, Less or Equal */ #if DEBUG_FPE - printf("GLE"); + printf("GLE"); #endif - result = -((fpsr & FPSR_NAN) == 0); - break; - default: - /* invalid predicate */ - return SIGILL; - } - result ^= invert; /* if the predicate is "NOT ...", then - invert the result */ + result = -((fpsr & FPSR_NAN) == 0); + break; + default: + /* invalid predicate */ + return SIGILL; + } + /* if the predicate is "NOT ...", then invert the result */ + result ^= invert; #if DEBUG_FPE - printf("=> %s (%d)\n", result ? "true" : "false", result); + printf("=> %s (%d)\n", result ? "true" : "false", result); #endif - /* if it's an IEEE unaware test and NAN is set, BSUN is set */ - if (sig_bsun && (fpsr & FPSR_NAN)) { - fpsr |= FPSR_BSUN; - } + /* if it's an IEEE unaware test and NAN is set, BSUN is set */ + if (sig_bsun && (fpsr & FPSR_NAN)) { + fpsr |= FPSR_BSUN; + } - /* put fpsr back */ - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; + /* put fpsr back */ + fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr = fpsr; - return result; + return result; } /* @@ -1071,93 +1097,100 @@ static int fpu_emul_type1(struct fpemu *fe, struct instruction *insn) { - struct frame *frame = fe->fe_frame; - int advance, sig, branch, displ; + struct frame *frame = fe->fe_frame; + int advance, sig, branch, displ; - branch = test_cc(fe, insn->is_word1); - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; + branch = test_cc(fe, insn->is_word1); + fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; - insn->is_advance = 4; - sig = 0; + insn->is_advance = 4; + sig = 0; - switch (insn->is_opcode & 070) { - case 010: /* fdbcc */ - if (branch == -1) { - /* advance */ - insn->is_advance = 6; - } else if (!branch) { - /* decrement Dn and if (Dn != -1) branch */ - u_int16_t count = frame->f_regs[insn->is_opcode & 7]; - - if (count-- != 0) { - displ = fusword((void *) (insn->is_pc + insn->is_advance)); - if (displ < 0) { + switch (insn->is_opcode & 070) { + case 010: /* fdbcc */ + if (branch == -1) { + /* advance */ + insn->is_advance = 6; + } else if (!branch) { + /* decrement Dn and if (Dn != -1) branch */ + 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) { #ifdef DEBUG - printf("fpu_emul_type1: fault reading displacement\n"); + printf("fpu_emul_type1: " + "fault reading displacement\n"); #endif - return SIGSEGV; + return SIGSEGV; + } + /* sign-extend the displacement */ + displ &= 0xffff; + if (displ & 0x8000) { + displ |= 0xffff0000; + } + insn->is_advance += displ; +#if 0 /* XXX */ + insn->is_nextpc = insn->is_pc + + insn->is_advance; +#endif + } else { + insn->is_advance = 6; + } + /* write it back */ + frame->f_regs[insn->is_opcode & 7] &= 0xffff0000; + frame->f_regs[insn->is_opcode & 7] |= (uint32_t)count; + } else { /* got a signal */ + sig = SIGFPE; } - /* sign-extend the displacement */ - displ &= 0xffff; - if (displ & 0x8000) { - displ |= 0xffff0000; - } - insn->is_advance += displ; - /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */ - } else { - insn->is_advance = 6; - } - /* write it back */ - frame->f_regs[insn->is_opcode & 7] &= 0xffff0000; - frame->f_regs[insn->is_opcode & 7] |= (u_int32_t)count; - } else { /* got a signal */ - sig = SIGFPE; - } - break; - - case 070: /* ftrapcc or fscc */ - advance = 4; - if ((insn->is_opcode & 07) >= 2) { - switch (insn->is_opcode & 07) { - case 3: /* long opr */ - advance += 2; - case 2: /* word opr */ - advance += 2; - case 4: /* no opr */ - break; - default: - return SIGILL; break; - } - if (branch == 0) { - /* no trap */ - insn->is_advance = advance; - sig = 0; - } else { - /* trap */ - sig = SIGFPE; - } - break; - } /* if ((insn->is_opcode & 7) < 2), fall through to FScc */ + case 070: /* ftrapcc or fscc */ + advance = 4; + if ((insn->is_opcode & 07) >= 2) { + switch (insn->is_opcode & 07) { + case 3: /* long opr */ + advance += 2; + case 2: /* word opr */ + advance += 2; + case 4: /* no opr */ + break; + default: + return SIGILL; + break; + } + + if (branch == 0) { + /* no trap */ + insn->is_advance = advance; + sig = 0; + } else { + /* trap */ + sig = SIGFPE; + } + break; + } + /* FALLTHROUGH */ - default: /* fscc */ - insn->is_advance = 4; - insn->is_datasize = 1; /* always byte */ - sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); - if (sig) { - break; - } - if (branch == -1 || branch == 0) { - /* set result */ - sig = fpu_store_ea(frame, insn, &insn->is_ea, (char *)&branch); - } else { - /* got an exception */ - sig = branch; + default: /* fscc */ + insn->is_advance = 4; + insn->is_datasize = 1; /* always byte */ + sig = fpu_decode_ea(frame, insn, &insn->is_ea, insn->is_opcode); + if (sig) { + break; + } + if (branch == -1 || branch == 0) { + /* set result */ + sig = fpu_store_ea(frame, insn, &insn->is_ea, + (char *)&branch); + } else { + /* got an exception */ + sig = branch; + } + break; } - break; - } - return sig; + return sig; } /* @@ -1168,49 +1201,54 @@ static int fpu_emul_brcc(struct fpemu *fe, struct instruction *insn) { - int displ, word2; - int sig; + int displ, word2; + int sig; - /* - * Get branch displacement. - */ - insn->is_advance = 4; - displ = insn->is_word1; - - if (insn->is_opcode & 0x40) { - word2 = fusword((void *) (insn->is_pc + insn->is_advance)); - if (word2 < 0) { + /* + * Get branch displacement. + */ + insn->is_advance = 4; + displ = insn->is_word1; + + if (insn->is_opcode & 0x40) { + word2 = fusword((void *)(insn->is_pc + insn->is_advance)); + if (word2 < 0) { #ifdef DEBUG - printf("fpu_emul_brcc: fault reading word2\n"); + printf("fpu_emul_brcc: fault reading word2\n"); #endif - return SIGSEGV; + return SIGSEGV; + } + displ <<= 16; + displ |= word2; + insn->is_advance += 2; + } else { + /* displacement is word sized */ + if (displ & 0x8000) + displ |= 0xFFFF0000; + } + + /* XXX: If CC, insn->is_pc += displ */ + sig = test_cc(fe, insn->is_opcode); + fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; + + if (fe->fe_fpsr & fe->fe_fpcr & FPSR_EXCP) { + return SIGFPE; /* caught an exception */ } - displ <<= 16; - displ |= word2; - insn->is_advance += 2; - } else /* displacement is word sized */ - if (displ & 0x8000) - displ |= 0xFFFF0000; - - /* XXX: If CC, insn->is_pc += displ */ - sig = test_cc(fe, insn->is_opcode); - fe->fe_fpframe->fpf_fpsr = fe->fe_fpsr; - - if (fe->fe_fpsr & fe->fe_fpcr & FPSR_EXCP) { - return SIGFPE; /* caught an exception */ - } - if (sig == -1) { - /* branch does take place; 2 is the offset to the 1st disp word */ - insn->is_advance = displ + 2; - /* XXX insn->is_nextpc = insn->is_pc + insn->is_advance; */ - } else if (sig) { - return SIGILL; /* got a signal */ - } -#if DEBUG_FPE - printf("fpu_emul_brcc: %s insn @ %x (%x+%x) (disp=%x)\n", - (sig == -1) ? "BRANCH to" : "NEXT", - insn->is_pc + insn->is_advance, insn->is_pc, insn->is_advance, - displ); + if (sig == -1) { + /* + * branch does take place; 2 is the offset to the 1st disp word + */ + insn->is_advance = displ + 2; +#if 0 /* XXX */ + insn->is_nextpc = insn->is_pc + insn->is_advance; +#endif + } else if (sig) + return SIGILL; /* got a signal */ +#if DEBUG_FPE + printf("fpu_emul_brcc: %s insn @ %x (%x+%x) (disp=%x)\n", + (sig == -1) ? "BRANCH to" : "NEXT", + insn->is_pc + insn->is_advance, insn->is_pc, insn->is_advance, + displ); #endif - return 0; + return 0; }