driver.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  3.  *
  4.  * Floating-point emulation code
  5.  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2, or (at your option)
  10.  *    any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21. /*
  22.  *  linux/arch/math-emu/driver.c.c
  23.  *
  24.  * decodes and dispatches unimplemented FPU instructions
  25.  *
  26.  *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org>
  27.  *  Copyright (C) 2001       Hewlett-Packard <bame@debian.org>
  28.  */
  29. #include <linux/config.h>
  30. #include <linux/sched.h>
  31. #include "float.h"
  32. #include "math-emu.h"
  33. #define fptpos 31
  34. #define fpr1pos 10
  35. #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
  36. #define FPUDEBUG 0
  37. /* Format of the floating-point exception registers. */
  38. struct exc_reg {
  39. unsigned int exception : 6;
  40. unsigned int ei : 26;
  41. };
  42. /* Macros for grabbing bits of the instruction format from the 'ei'
  43.    field above. */
  44. /* Major opcode 0c and 0e */
  45. #define FP0CE_UID(i) (((i) >> 6) & 3)
  46. #define FP0CE_CLASS(i) (((i) >> 9) & 3)
  47. #define FP0CE_SUBOP(i) (((i) >> 13) & 7)
  48. #define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
  49. #define FP0C_FORMAT(i) (((i) >> 11) & 3)
  50. #define FP0E_FORMAT(i) (((i) >> 11) & 1)
  51. /* Major opcode 0c, uid 2 (performance monitoring) */
  52. #define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
  53. /* Major opcode 2e (fused operations).   */
  54. #define FP2E_SUBOP(i)  (((i) >> 5) & 1)
  55. #define FP2E_FORMAT(i) (((i) >> 11) & 1)
  56. /* Major opcode 26 (FMPYSUB) */
  57. /* Major opcode 06 (FMPYADD) */
  58. #define FPx6_FORMAT(i) ((i) & 0x1f)
  59. /* Flags and enable bits of the status word. */
  60. #define FPSW_FLAGS(w) ((w) >> 27)
  61. #define FPSW_ENABLE(w) ((w) & 0x1f)
  62. #define FPSW_V (1<<4)
  63. #define FPSW_Z (1<<3)
  64. #define FPSW_O (1<<2)
  65. #define FPSW_U (1<<1)
  66. #define FPSW_I (1<<0)
  67. /* Handle a floating point exception.  Return zero if the faulting
  68.    instruction can be completed successfully. */
  69. int
  70. handle_fpe(struct pt_regs *regs)
  71. {
  72. extern void printbinary(unsigned long x, int nbits);
  73. struct siginfo si;
  74. unsigned int orig_sw, sw;
  75. int signalcode;
  76. /* need an intermediate copy of float regs because FPU emulation
  77.  * code expects an artificial last entry which contains zero
  78.  */
  79. __u64 frcopy[33];
  80. memcpy(frcopy, regs->fr, sizeof regs->fr);
  81. frcopy[32] = 0;
  82. memcpy(&orig_sw, frcopy, sizeof(orig_sw));
  83. if (FPUDEBUG) {
  84. printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->n   ");
  85. printbinary(orig_sw, 32);
  86. printk(KERN_DEBUG "n");
  87. }
  88. signalcode = decode_fpu(frcopy, 0x666);
  89. /* Status word = FR0L. */
  90. memcpy(&sw, frcopy, sizeof(sw));
  91. if (FPUDEBUG) {
  92. printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%xn",
  93. signalcode >> 24, signalcode & 0xffffff);
  94. printbinary(sw, 32);
  95. printk(KERN_DEBUG "n");
  96. }
  97. memcpy(regs->fr, frcopy, sizeof regs->fr);
  98. if (signalcode != 0) {
  99.     si.si_signo = signalcode >> 24;
  100.     si.si_errno = 0;
  101.     si.si_code = signalcode & 0xffffff;
  102.     si.si_addr = (void *) regs->iaoq[0];
  103.     force_sig_info(si.si_signo, &si, current);
  104.     return -1;
  105. }
  106. return signalcode ? -1 : 0;
  107. }