/*1* Linux/PA-RISC Project (http://www.parisc-linux.org/)2*3* Floating-point emulation code4* Copyright (C) 2001 Hewlett-Packard (Paul Bame) <[email protected]>5*6* This program is free software; you can redistribute it and/or modify7* it under the terms of the GNU General Public License as published by8* the Free Software Foundation; either version 2, or (at your option)9* any later version.10*11* This program is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14* GNU General Public License for more details.15*16* You should have received a copy of the GNU General Public License17* along with this program; if not, write to the Free Software18* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA19*/20/*21* linux/arch/math-emu/driver.c.c22*23* decodes and dispatches unimplemented FPU instructions24*25* Copyright (C) 1999, 2000 Philipp Rumpf <[email protected]>26* Copyright (C) 2001 Hewlett-Packard <[email protected]>27*/2829#include <linux/sched.h>30#include "float.h"31#include "math-emu.h"323334#define fptpos 3135#define fpr1pos 1036#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))3738#define FPUDEBUG 03940/* Format of the floating-point exception registers. */41struct exc_reg {42unsigned int exception : 6;43unsigned int ei : 26;44};4546/* Macros for grabbing bits of the instruction format from the 'ei'47field above. */48/* Major opcode 0c and 0e */49#define FP0CE_UID(i) (((i) >> 6) & 3)50#define FP0CE_CLASS(i) (((i) >> 9) & 3)51#define FP0CE_SUBOP(i) (((i) >> 13) & 7)52#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */53#define FP0C_FORMAT(i) (((i) >> 11) & 3)54#define FP0E_FORMAT(i) (((i) >> 11) & 1)5556/* Major opcode 0c, uid 2 (performance monitoring) */57#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)5859/* Major opcode 2e (fused operations). */60#define FP2E_SUBOP(i) (((i) >> 5) & 1)61#define FP2E_FORMAT(i) (((i) >> 11) & 1)6263/* Major opcode 26 (FMPYSUB) */64/* Major opcode 06 (FMPYADD) */65#define FPx6_FORMAT(i) ((i) & 0x1f)6667/* Flags and enable bits of the status word. */68#define FPSW_FLAGS(w) ((w) >> 27)69#define FPSW_ENABLE(w) ((w) & 0x1f)70#define FPSW_V (1<<4)71#define FPSW_Z (1<<3)72#define FPSW_O (1<<2)73#define FPSW_U (1<<1)74#define FPSW_I (1<<0)7576/* Handle a floating point exception. Return zero if the faulting77instruction can be completed successfully. */78int79handle_fpe(struct pt_regs *regs)80{81extern void printbinary(unsigned long x, int nbits);82struct siginfo si;83unsigned int orig_sw, sw;84int signalcode;85/* need an intermediate copy of float regs because FPU emulation86* code expects an artificial last entry which contains zero87*88* also, the passed in fr registers contain one word that defines89* the fpu type. the fpu type information is constructed90* inside the emulation code91*/92__u64 frcopy[36];9394memcpy(frcopy, regs->fr, sizeof regs->fr);95frcopy[32] = 0;9697memcpy(&orig_sw, frcopy, sizeof(orig_sw));9899if (FPUDEBUG) {100printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n ");101printbinary(orig_sw, 32);102printk(KERN_DEBUG "\n");103}104105signalcode = decode_fpu(frcopy, 0x666);106107/* Status word = FR0L. */108memcpy(&sw, frcopy, sizeof(sw));109if (FPUDEBUG) {110printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n",111signalcode >> 24, signalcode & 0xffffff);112printbinary(sw, 32);113printk(KERN_DEBUG "\n");114}115116memcpy(regs->fr, frcopy, sizeof regs->fr);117if (signalcode != 0) {118si.si_signo = signalcode >> 24;119si.si_errno = 0;120si.si_code = signalcode & 0xffffff;121si.si_addr = (void __user *) regs->iaoq[0];122force_sig_info(si.si_signo, &si, current);123return -1;124}125126return signalcode ? -1 : 0;127}128129130