Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fpu_etc.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------+
2  | fpu_etc.c |
3  | |
4  | Implement a few FPU instructions. |
5  | |
6  | Copyright (C) 1992,1993,1994,1997 |
7  | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
8  | Australia. E-mail [email protected] |
9  | |
10  | |
11  +---------------------------------------------------------------------------*/
12 
13 #include "fpu_system.h"
14 #include "exception.h"
15 #include "fpu_emu.h"
16 #include "status_w.h"
17 #include "reg_constant.h"
18 
19 static void fchs(FPU_REG *st0_ptr, u_char st0tag)
20 {
21  if (st0tag ^ TAG_Empty) {
22  signbyte(st0_ptr) ^= SIGN_NEG;
23  clear_C1();
24  } else
26 }
27 
28 static void fabs(FPU_REG *st0_ptr, u_char st0tag)
29 {
30  if (st0tag ^ TAG_Empty) {
31  setpositive(st0_ptr);
32  clear_C1();
33  } else
35 }
36 
37 static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
38 {
39  switch (st0tag) {
40  case TAG_Zero:
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);
61 #endif /* PECULIAR_486 */
62  return;
63  }
64  break;
65  case TW_NaN:
66  setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
68  break;
69  case TW_Infinity:
70  if (getsign(st0_ptr) == SIGN_POS)
71  setcc(0);
72  else
73  setcc(SW_C0);
74  break;
75  default:
76  setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
77  EXCEPTION(EX_INTERNAL | 0x14);
78  break;
79  }
80  break;
81  case TAG_Empty:
82  setcc(SW_C0 | SW_C2 | SW_C3);
84  break;
85  }
86 }
87 
88 static void fxam(FPU_REG *st0_ptr, u_char st0tag)
89 {
90  int c = 0;
91  switch (st0tag) {
92  case TAG_Empty:
93  c = SW_C3 | SW_C0;
94  break;
95  case TAG_Zero:
96  c = SW_C3;
97  break;
98  case TAG_Valid:
99  c = SW_C2;
100  break;
101  case TAG_Special:
102  switch (FPU_Special(st0_ptr)) {
103  case TW_Denormal:
104  c = SW_C2 | SW_C3; /* Denormal */
105  break;
106  case TW_NaN:
107  /* We also use NaN for unsupported types. */
108  if ((st0_ptr->sigh & 0x80000000)
109  && (exponent(st0_ptr) == EXP_OVER))
110  c = SW_C0;
111  break;
112  case TW_Infinity:
113  c = SW_C2 | SW_C0;
114  break;
115  }
116  }
117  if (getsign(st0_ptr) == SIGN_NEG)
118  c |= SW_C1;
119  setcc(c);
120 }
121 
122 static FUNC_ST0 const fp_etc_table[] = {
124  ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal
125 };
126 
127 void FPU_etc(void)
128 {
129  (fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0());
130 }