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
unicore32
kernel
fpu-ucf64.c
Go to the documentation of this file.
1
/*
2
* linux/arch/unicore32/kernel/fpu-ucf64.c
3
*
4
* Code specific to PKUnity SoC and UniCore ISA
5
*
6
* Copyright (C) 2001-2010 GUAN Xue-tao
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License version 2 as
10
* published by the Free Software Foundation.
11
*/
12
#include <linux/module.h>
13
#include <linux/types.h>
14
#include <linux/kernel.h>
15
#include <linux/signal.h>
16
#include <linux/sched.h>
17
#include <
linux/init.h
>
18
19
#include <
asm/fpu-ucf64.h
>
20
21
/*
22
* A special flag to tell the normalisation code not to normalise.
23
*/
24
#define F64_NAN_FLAG 0x100
25
26
/*
27
* A bit pattern used to indicate the initial (unset) value of the
28
* exception mask, in case nothing handles an instruction. This
29
* doesn't include the NAN flag, which get masked out before
30
* we check for an error.
31
*/
32
#define F64_EXCEPTION_ERROR ((u32)-1 & ~F64_NAN_FLAG)
33
34
/*
35
* Since we aren't building with -mfpu=f64, we need to code
36
* these instructions using their MRC/MCR equivalents.
37
*/
38
#define f64reg(_f64_) #_f64_
39
40
#define cff(_f64_) ({ \
41
u32 __v; \
42
asm("cff %0, " f64reg(_f64_) "@ fmrx %0, " #_f64_ \
43
: "=r" (__v) : : "cc"); \
44
__v; \
45
})
46
47
#define ctf(_f64_, _var_) \
48
asm("ctf %0, " f64reg(_f64_) "@ fmxr " #_f64_ ", %0" \
49
: : "r" (_var_) : "cc")
50
51
/*
52
* Raise a SIGFPE for the current process.
53
* sicode describes the signal being raised.
54
*/
55
void
ucf64_raise_sigfpe
(
unsigned
int
sicode,
struct
pt_regs
*
regs
)
56
{
57
siginfo_t
info
;
58
59
memset
(&info, 0,
sizeof
(info));
60
61
info.
si_signo
=
SIGFPE
;
62
info.
si_code
= sicode;
63
info.si_addr = (
void
__user
*)(
instruction_pointer
(regs) - 4);
64
65
/*
66
* This is the same as NWFPE, because it's not clear what
67
* this is used for
68
*/
69
current
->thread.error_code = 0;
70
current
->thread.trap_no = 6;
71
72
send_sig_info
(
SIGFPE
, &info,
current
);
73
}
74
75
/*
76
* Handle exceptions of UniCore-F64.
77
*/
78
void
ucf64_exchandler
(
u32
inst,
u32
fpexc,
struct
pt_regs
*
regs
)
79
{
80
u32
tmp
= fpexc;
81
u32
exc =
F64_EXCEPTION_ERROR
& fpexc;
82
83
pr_debug
(
"UniCore-F64: instruction %08x fpscr %08x\n"
,
84
inst, fpexc);
85
86
if
(exc &
FPSCR_CMPINSTR_BIT
) {
87
if
(exc &
FPSCR_CON
)
88
tmp |=
FPSCR_CON
;
89
else
90
tmp &= ~(
FPSCR_CON
);
91
exc &= ~(FPSCR_CMPINSTR_BIT |
FPSCR_CON
);
92
}
else
{
93
pr_debug
(
KERN_ERR
"UniCore-F64 Error: unhandled exceptions\n"
);
94
pr_debug
(
KERN_ERR
"UniCore-F64 FPSCR 0x%08x INST 0x%08x\n"
,
95
cff
(
FPSCR
), inst);
96
97
ucf64_raise_sigfpe
(0, regs);
98
return
;
99
}
100
101
/*
102
* Update the FPSCR with the additional exception flags.
103
* Comparison instructions always return at least one of
104
* these flags set.
105
*/
106
tmp &= ~(
FPSCR_TRAP
|
FPSCR_IOS
|
FPSCR_OFS
|
FPSCR_UFS
|
107
FPSCR_IXS
|
FPSCR_HIS
|
FPSCR_IOC
|
FPSCR_OFC
|
108
FPSCR_UFC
|
FPSCR_IXC
|
FPSCR_HIC
);
109
110
tmp |= exc;
111
ctf
(
FPSCR
, tmp);
112
}
113
114
/*
115
* F64 support code initialisation.
116
*/
117
static
int
__init
ucf64_init(
void
)
118
{
119
ctf
(
FPSCR
, 0x0);
/* FPSCR_UFE | FPSCR_NDE perhaps better */
120
121
printk
(
KERN_INFO
"Enable UniCore-F64 support.\n"
);
122
123
return
0;
124
}
125
126
late_initcall
(ucf64_init);
Generated on Thu Jan 10 2013 13:19:42 for Linux Kernel by
1.8.2