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
x86
math-emu
reg_mul.c
Go to the documentation of this file.
1
/*---------------------------------------------------------------------------+
2
| reg_mul.c |
3
| |
4
| Multiply one FPU_REG by another, put the result in a destination FPU_REG. |
5
| |
6
| Copyright (C) 1992,1993,1997 |
7
| W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia |
8
| E-mail
[email protected]
|
9
| |
10
| Returns the tag of the result if no exceptions or errors occurred. |
11
| |
12
+---------------------------------------------------------------------------*/
13
14
/*---------------------------------------------------------------------------+
15
| The destination may be any FPU_REG, including one of the source FPU_REGs. |
16
+---------------------------------------------------------------------------*/
17
18
#include "
fpu_emu.h
"
19
#include "
exception.h
"
20
#include "
reg_constant.h
"
21
#include "
fpu_system.h
"
22
23
/*
24
Multiply two registers to give a register result.
25
The sources are st(deststnr) and (b,tagb,signb).
26
The destination is st(deststnr).
27
*/
28
/* This routine must be called with non-empty source registers */
29
int
FPU_mul
(
FPU_REG
const
*
b
,
u_char
tagb,
int
deststnr,
int
control_w)
30
{
31
FPU_REG
*
a
= &
st
(deststnr);
32
FPU_REG
*
dest
=
a
;
33
u_char
taga =
FPU_gettagi
(deststnr);
34
u_char
saved_sign =
getsign
(dest);
35
u_char
sign
= (
getsign
(a) ^
getsign
(b));
36
int
tag
;
37
38
if
(!(taga | tagb)) {
39
/* Both regs Valid, this should be the most common case. */
40
41
tag =
42
FPU_u_mul
(a, b, dest, control_w, sign,
43
exponent
(a) +
exponent
(b));
44
if
(tag < 0) {
45
setsign
(dest, saved_sign);
46
return
tag
;
47
}
48
FPU_settagi
(deststnr, tag);
49
return
tag
;
50
}
51
52
if
(taga ==
TAG_Special
)
53
taga =
FPU_Special
(a);
54
if
(tagb ==
TAG_Special
)
55
tagb =
FPU_Special
(b);
56
57
if
(((taga ==
TAG_Valid
) && (tagb ==
TW_Denormal
))
58
|| ((taga ==
TW_Denormal
) && (tagb ==
TAG_Valid
))
59
|| ((taga ==
TW_Denormal
) && (tagb ==
TW_Denormal
))) {
60
FPU_REG
x
,
y
;
61
if
(
denormal_operand
() < 0)
62
return
FPU_Exception
;
63
64
FPU_to_exp16
(a, &x);
65
FPU_to_exp16
(b, &y);
66
tag =
FPU_u_mul
(&x, &y, dest, control_w, sign,
67
exponent16
(&x) +
exponent16
(&y));
68
if
(tag < 0) {
69
setsign
(dest, saved_sign);
70
return
tag
;
71
}
72
FPU_settagi
(deststnr, tag);
73
return
tag
;
74
}
else
if
((taga <=
TW_Denormal
) && (tagb <=
TW_Denormal
)) {
75
if
(((tagb ==
TW_Denormal
) || (taga ==
TW_Denormal
))
76
&& (
denormal_operand
() < 0))
77
return
FPU_Exception
;
78
79
/* Must have either both arguments == zero, or
80
one valid and the other zero.
81
The result is therefore zero. */
82
FPU_copy_to_regi
(&
CONST_Z
,
TAG_Zero
, deststnr);
83
/* The 80486 book says that the answer is +0, but a real
84
80486 behaves this way.
85
IEEE-754 apparently says it should be this way. */
86
setsign
(dest, sign);
87
return
TAG_Zero
;
88
}
89
/* Must have infinities, NaNs, etc */
90
else
if
((taga ==
TW_NaN
) || (tagb ==
TW_NaN
)) {
91
return
real_2op_NaN
(b, tagb, deststnr, &
st
(0));
92
}
else
if
(((taga ==
TW_Infinity
) && (tagb ==
TAG_Zero
))
93
|| ((tagb ==
TW_Infinity
) && (taga ==
TAG_Zero
))) {
94
return
arith_invalid
(deststnr);
/* Zero*Infinity is invalid */
95
}
else
if
(((taga ==
TW_Denormal
) || (tagb ==
TW_Denormal
))
96
&& (
denormal_operand
() < 0)) {
97
return
FPU_Exception
;
98
}
else
if
(taga ==
TW_Infinity
) {
99
FPU_copy_to_regi
(a,
TAG_Special
, deststnr);
100
setsign
(dest, sign);
101
return
TAG_Special
;
102
}
else
if
(tagb ==
TW_Infinity
) {
103
FPU_copy_to_regi
(b,
TAG_Special
, deststnr);
104
setsign
(dest, sign);
105
return
TAG_Special
;
106
}
107
#ifdef PARANOID
108
else
{
109
EXCEPTION
(
EX_INTERNAL
| 0x102);
110
return
FPU_Exception
;
111
}
112
#endif
/* PARANOID */
113
114
return
0;
115
}
Generated on Thu Jan 10 2013 13:21:26 for Linux Kernel by
1.8.2