Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
parisc
math-emu
driver.c
Go to the documentation of this file.
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) <
[email protected]
>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <
[email protected]
>
27
* Copyright (C) 2001 Hewlett-Packard <
[email protected]
>
28
*/
29
30
#include <linux/sched.h>
31
#include "
float.h
"
32
#include "
math-emu.h
"
33
34
35
#define fptpos 31
36
#define fpr1pos 10
37
#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
38
39
#define FPUDEBUG 0
40
41
/* Format of the floating-point exception registers. */
42
struct
exc_reg
{
43
unsigned
int
exception
: 6;
44
unsigned
int
ei
: 26;
45
};
46
47
/* Macros for grabbing bits of the instruction format from the 'ei'
48
field above. */
49
/* Major opcode 0c and 0e */
50
#define FP0CE_UID(i) (((i) >> 6) & 3)
51
#define FP0CE_CLASS(i) (((i) >> 9) & 3)
52
#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
53
#define FP0CE_SUBOP1(i) (((i) >> 15) & 7)
/* Class 1 subopcode */
54
#define FP0C_FORMAT(i) (((i) >> 11) & 3)
55
#define FP0E_FORMAT(i) (((i) >> 11) & 1)
56
57
/* Major opcode 0c, uid 2 (performance monitoring) */
58
#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
59
60
/* Major opcode 2e (fused operations). */
61
#define FP2E_SUBOP(i) (((i) >> 5) & 1)
62
#define FP2E_FORMAT(i) (((i) >> 11) & 1)
63
64
/* Major opcode 26 (FMPYSUB) */
65
/* Major opcode 06 (FMPYADD) */
66
#define FPx6_FORMAT(i) ((i) & 0x1f)
67
68
/* Flags and enable bits of the status word. */
69
#define FPSW_FLAGS(w) ((w) >> 27)
70
#define FPSW_ENABLE(w) ((w) & 0x1f)
71
#define FPSW_V (1<<4)
72
#define FPSW_Z (1<<3)
73
#define FPSW_O (1<<2)
74
#define FPSW_U (1<<1)
75
#define FPSW_I (1<<0)
76
77
/* Handle a floating point exception. Return zero if the faulting
78
instruction can be completed successfully. */
79
int
80
handle_fpe
(
struct
pt_regs
*
regs
)
81
{
82
extern
void
printbinary(
unsigned
long
x
,
int
nbits);
83
struct
siginfo
si;
84
unsigned
int
orig_sw,
sw
;
85
int
signalcode;
86
/* need an intermediate copy of float regs because FPU emulation
87
* code expects an artificial last entry which contains zero
88
*
89
* also, the passed in fr registers contain one word that defines
90
* the fpu type. the fpu type information is constructed
91
* inside the emulation code
92
*/
93
__u64
frcopy[36];
94
95
memcpy
(frcopy, regs->
fr
,
sizeof
regs->
fr
);
96
frcopy[32] = 0;
97
98
memcpy
(&orig_sw, frcopy,
sizeof
(orig_sw));
99
100
if
(
FPUDEBUG
) {
101
printk
(
KERN_DEBUG
"FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n "
);
102
printbinary(orig_sw, 32);
103
printk
(
KERN_DEBUG
"\n"
);
104
}
105
106
signalcode =
decode_fpu
(frcopy, 0x666);
107
108
/* Status word = FR0L. */
109
memcpy
(&sw, frcopy,
sizeof
(sw));
110
if
(
FPUDEBUG
) {
111
printk
(
KERN_DEBUG
"VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n"
,
112
signalcode >> 24, signalcode & 0xffffff);
113
printbinary(sw, 32);
114
printk
(
KERN_DEBUG
"\n"
);
115
}
116
117
memcpy
(regs->
fr
, frcopy,
sizeof
regs->
fr
);
118
if
(signalcode != 0) {
119
si.
si_signo
= signalcode >> 24;
120
si.
si_errno
= 0;
121
si.
si_code
= signalcode & 0xffffff;
122
si.si_addr = (
void
__user
*) regs->
iaoq
[0];
123
force_sig_info
(si.
si_signo
, &si,
current
);
124
return
-1;
125
}
126
127
return
signalcode ? -1 : 0;
128
}
Generated on Thu Jan 10 2013 13:12:59 for Linux Kernel by
1.8.2