diff options
Diffstat (limited to 'arch/x86/math-emu/fpu_etc.c')
-rw-r--r-- | arch/x86/math-emu/fpu_etc.c | 193 |
1 files changed, 90 insertions, 103 deletions
diff --git a/arch/x86/math-emu/fpu_etc.c b/arch/x86/math-emu/fpu_etc.c index e3b5d465587f..e73631e0cde9 100644 --- a/arch/x86/math-emu/fpu_etc.c +++ b/arch/x86/math-emu/fpu_etc.c | |||
@@ -16,128 +16,115 @@ | |||
16 | #include "status_w.h" | 16 | #include "status_w.h" |
17 | #include "reg_constant.h" | 17 | #include "reg_constant.h" |
18 | 18 | ||
19 | 19 | static void fchs(FPU_REG * st0_ptr, u_char st0tag) | |
20 | static void fchs(FPU_REG *st0_ptr, u_char st0tag) | ||
21 | { | 20 | { |
22 | if ( st0tag ^ TAG_Empty ) | 21 | if (st0tag ^ TAG_Empty) { |
23 | { | 22 | signbyte(st0_ptr) ^= SIGN_NEG; |
24 | signbyte(st0_ptr) ^= SIGN_NEG; | 23 | clear_C1(); |
25 | clear_C1(); | 24 | } else |
26 | } | 25 | FPU_stack_underflow(); |
27 | else | ||
28 | FPU_stack_underflow(); | ||
29 | } | 26 | } |
30 | 27 | ||
31 | 28 | static void fabs(FPU_REG * st0_ptr, u_char st0tag) | |
32 | static void fabs(FPU_REG *st0_ptr, u_char st0tag) | ||
33 | { | 29 | { |
34 | if ( st0tag ^ TAG_Empty ) | 30 | if (st0tag ^ TAG_Empty) { |
35 | { | 31 | setpositive(st0_ptr); |
36 | setpositive(st0_ptr); | 32 | clear_C1(); |
37 | clear_C1(); | 33 | } else |
38 | } | 34 | FPU_stack_underflow(); |
39 | else | ||
40 | FPU_stack_underflow(); | ||
41 | } | 35 | } |
42 | 36 | ||
43 | 37 | static void ftst_(FPU_REG * st0_ptr, u_char st0tag) | |
44 | static void ftst_(FPU_REG *st0_ptr, u_char st0tag) | ||
45 | { | 38 | { |
46 | switch (st0tag) | 39 | switch (st0tag) { |
47 | { | 40 | case TAG_Zero: |
48 | case TAG_Zero: | ||
49 | setcc(SW_C3); | ||
50 | break; | ||
51 | case TAG_Valid: | ||
52 | if (getsign(st0_ptr) == SIGN_POS) | ||
53 | setcc(0); | ||
54 | else | ||
55 | setcc(SW_C0); | ||
56 | break; | ||
57 | case TAG_Special: | ||
58 | switch ( FPU_Special(st0_ptr) ) | ||
59 | { | ||
60 | case TW_Denormal: | ||
61 | if (getsign(st0_ptr) == SIGN_POS) | ||
62 | setcc(0); | ||
63 | else | ||
64 | setcc(SW_C0); | ||
65 | if ( denormal_operand() < 0 ) | ||
66 | { | ||
67 | #ifdef PECULIAR_486 | ||
68 | /* This is weird! */ | ||
69 | if (getsign(st0_ptr) == SIGN_POS) | ||
70 | setcc(SW_C3); | 41 | setcc(SW_C3); |
42 | break; | ||
43 | case TAG_Valid: | ||
44 | if (getsign(st0_ptr) == SIGN_POS) | ||
45 | setcc(0); | ||
46 | else | ||
47 | setcc(SW_C0); | ||
48 | break; | ||
49 | case TAG_Special: | ||
50 | switch (FPU_Special(st0_ptr)) { | ||
51 | case TW_Denormal: | ||
52 | if (getsign(st0_ptr) == SIGN_POS) | ||
53 | setcc(0); | ||
54 | else | ||
55 | setcc(SW_C0); | ||
56 | if (denormal_operand() < 0) { | ||
57 | #ifdef PECULIAR_486 | ||
58 | /* This is weird! */ | ||
59 | if (getsign(st0_ptr) == SIGN_POS) | ||
60 | setcc(SW_C3); | ||
71 | #endif /* PECULIAR_486 */ | 61 | #endif /* PECULIAR_486 */ |
72 | return; | 62 | return; |
73 | } | 63 | } |
74 | break; | 64 | break; |
75 | case TW_NaN: | 65 | case TW_NaN: |
76 | setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */ | 66 | setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ |
77 | EXCEPTION(EX_Invalid); | 67 | EXCEPTION(EX_Invalid); |
78 | break; | 68 | break; |
79 | case TW_Infinity: | 69 | case TW_Infinity: |
80 | if (getsign(st0_ptr) == SIGN_POS) | 70 | if (getsign(st0_ptr) == SIGN_POS) |
81 | setcc(0); | 71 | setcc(0); |
82 | else | 72 | else |
83 | setcc(SW_C0); | 73 | setcc(SW_C0); |
84 | break; | 74 | break; |
85 | default: | 75 | default: |
86 | setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */ | 76 | setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */ |
87 | EXCEPTION(EX_INTERNAL|0x14); | 77 | EXCEPTION(EX_INTERNAL | 0x14); |
88 | break; | 78 | break; |
79 | } | ||
80 | break; | ||
81 | case TAG_Empty: | ||
82 | setcc(SW_C0 | SW_C2 | SW_C3); | ||
83 | EXCEPTION(EX_StackUnder); | ||
84 | break; | ||
89 | } | 85 | } |
90 | break; | ||
91 | case TAG_Empty: | ||
92 | setcc(SW_C0|SW_C2|SW_C3); | ||
93 | EXCEPTION(EX_StackUnder); | ||
94 | break; | ||
95 | } | ||
96 | } | 86 | } |
97 | 87 | ||
98 | 88 | static void fxam(FPU_REG * st0_ptr, u_char st0tag) | |
99 | static void fxam(FPU_REG *st0_ptr, u_char st0tag) | ||
100 | { | 89 | { |
101 | int c = 0; | 90 | int c = 0; |
102 | switch (st0tag) | 91 | switch (st0tag) { |
103 | { | 92 | case TAG_Empty: |
104 | case TAG_Empty: | 93 | c = SW_C3 | SW_C0; |
105 | c = SW_C3|SW_C0; | 94 | break; |
106 | break; | 95 | case TAG_Zero: |
107 | case TAG_Zero: | 96 | c = SW_C3; |
108 | c = SW_C3; | 97 | break; |
109 | break; | 98 | case TAG_Valid: |
110 | case TAG_Valid: | 99 | c = SW_C2; |
111 | c = SW_C2; | 100 | break; |
112 | break; | 101 | case TAG_Special: |
113 | case TAG_Special: | 102 | switch (FPU_Special(st0_ptr)) { |
114 | switch ( FPU_Special(st0_ptr) ) | 103 | case TW_Denormal: |
115 | { | 104 | c = SW_C2 | SW_C3; /* Denormal */ |
116 | case TW_Denormal: | 105 | break; |
117 | c = SW_C2|SW_C3; /* Denormal */ | 106 | case TW_NaN: |
118 | break; | 107 | /* We also use NaN for unsupported types. */ |
119 | case TW_NaN: | 108 | if ((st0_ptr->sigh & 0x80000000) |
120 | /* We also use NaN for unsupported types. */ | 109 | && (exponent(st0_ptr) == EXP_OVER)) |
121 | if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) ) | 110 | c = SW_C0; |
122 | c = SW_C0; | 111 | break; |
123 | break; | 112 | case TW_Infinity: |
124 | case TW_Infinity: | 113 | c = SW_C2 | SW_C0; |
125 | c = SW_C2|SW_C0; | 114 | break; |
126 | break; | 115 | } |
127 | } | 116 | } |
128 | } | 117 | if (getsign(st0_ptr) == SIGN_NEG) |
129 | if ( getsign(st0_ptr) == SIGN_NEG ) | 118 | c |= SW_C1; |
130 | c |= SW_C1; | 119 | setcc(c); |
131 | setcc(c); | ||
132 | } | 120 | } |
133 | 121 | ||
134 | |||
135 | static FUNC_ST0 const fp_etc_table[] = { | 122 | static FUNC_ST0 const fp_etc_table[] = { |
136 | fchs, fabs, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal, | 123 | fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal, |
137 | ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal | 124 | ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal |
138 | }; | 125 | }; |
139 | 126 | ||
140 | void FPU_etc(void) | 127 | void FPU_etc(void) |
141 | { | 128 | { |
142 | (fp_etc_table[FPU_rm])(&st(0), FPU_gettag0()); | 129 | (fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0()); |
143 | } | 130 | } |