| 1 | /* |
| 2 | * linux/include/linux/math_emu.h |
| 3 | * |
| 4 | * (C) 1991 Linus Torvalds |
| 5 | * |
| 6 | * $FreeBSD: src/sys/i386/i386/math_emu.h,v 1.7.2.1 2001/08/15 01:23:50 peter Exp $ |
| 7 | * $DragonFly: src/sys/i386/i386/Attic/math_emu.h,v 1.4 2003/06/18 18:29:55 dillon Exp $ |
| 8 | */ |
| 9 | #ifndef _LINUX_MATH_EMU_H |
| 10 | #define _LINUX_MATH_EMU_H |
| 11 | |
| 12 | /*#define math_abort(x,y) \ |
| 13 | (((volatile void (*)(struct info *,unsigned int)) __math_abort)((x),(y)))*/ |
| 14 | |
| 15 | /* |
| 16 | * Gcc forces this stupid alignment problem: I want to use only two int32_t's |
| 17 | * for the temporary real 64-bit mantissa, but then gcc aligns out the |
| 18 | * structure to 12 bytes which breaks things in math_emulate.c. Shit. I |
| 19 | * want some kind of "no-alignt" pragma or something. |
| 20 | */ |
| 21 | |
| 22 | typedef struct { |
| 23 | int32_t a,b; |
| 24 | short exponent; |
| 25 | } temp_real; |
| 26 | |
| 27 | typedef struct { |
| 28 | short m0,m1,m2,m3; |
| 29 | short exponent; |
| 30 | } temp_real_unaligned; |
| 31 | |
| 32 | #define real_to_real(a,b) \ |
| 33 | ((*(long long *) (b) = *(long long *) (a)),((b)->exponent = (a)->exponent)) |
| 34 | |
| 35 | typedef struct { |
| 36 | int32_t a,b; |
| 37 | } long_real; |
| 38 | |
| 39 | typedef int32_t short_real; |
| 40 | |
| 41 | typedef struct { |
| 42 | int32_t a,b; |
| 43 | short sign; |
| 44 | } temp_int; |
| 45 | |
| 46 | struct swd { |
| 47 | int ie:1; |
| 48 | int de:1; |
| 49 | int ze:1; |
| 50 | int oe:1; |
| 51 | int ue:1; |
| 52 | int pe:1; |
| 53 | int sf:1; |
| 54 | int ir:1; |
| 55 | int c0:1; |
| 56 | int c1:1; |
| 57 | int c2:1; |
| 58 | int top:3; |
| 59 | int c3:1; |
| 60 | int b:1; |
| 61 | }; |
| 62 | struct i387_struct { |
| 63 | int32_t cwd; |
| 64 | int32_t swd; |
| 65 | int32_t twd; |
| 66 | int32_t fip; |
| 67 | int32_t fcs; |
| 68 | int32_t foo; |
| 69 | int32_t fos; |
| 70 | int32_t st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ |
| 71 | }; |
| 72 | |
| 73 | #define I387 (*(struct i387_struct *)&((curthread->td_pcb)->pcb_save.sv_87)) |
| 74 | #define SWD (*(struct swd *) &I387.swd) |
| 75 | #define ROUNDING ((I387.cwd >> 10) & 3) |
| 76 | #define PRECISION ((I387.cwd >> 8) & 3) |
| 77 | |
| 78 | #define BITS24 0 |
| 79 | #define BITS53 2 |
| 80 | #define BITS64 3 |
| 81 | |
| 82 | #define ROUND_NEAREST 0 |
| 83 | #define ROUND_DOWN 1 |
| 84 | #define ROUND_UP 2 |
| 85 | #define ROUND_0 3 |
| 86 | |
| 87 | #define CONSTZ (temp_real_unaligned) {0x0000,0x0000,0x0000,0x0000,0x0000} |
| 88 | #define CONST1 (temp_real_unaligned) {0x0000,0x0000,0x0000,0x8000,0x3FFF} |
| 89 | #define CONSTPI (temp_real_unaligned) {0xC235,0x2168,0xDAA2,0xC90F,0x4000} |
| 90 | #define CONSTLN2 (temp_real_unaligned) {0x79AC,0xD1CF,0x17F7,0xB172,0x3FFE} |
| 91 | #define CONSTLG2 (temp_real_unaligned) {0xF799,0xFBCF,0x9A84,0x9A20,0x3FFD} |
| 92 | #define CONSTL2E (temp_real_unaligned) {0xF0BC,0x5C17,0x3B29,0xB8AA,0x3FFF} |
| 93 | #define CONSTL2T (temp_real_unaligned) {0x8AFE,0xCD1B,0x784B,0xD49A,0x4000} |
| 94 | |
| 95 | #define set_IE() (I387.swd |= 1) |
| 96 | #define set_DE() (I387.swd |= 2) |
| 97 | #define set_ZE() (I387.swd |= 4) |
| 98 | #define set_OE() (I387.swd |= 8) |
| 99 | #define set_UE() (I387.swd |= 16) |
| 100 | #define set_PE() (I387.swd |= 32) |
| 101 | |
| 102 | #define set_C0() (I387.swd |= 0x0100) |
| 103 | #define set_C1() (I387.swd |= 0x0200) |
| 104 | #define set_C2() (I387.swd |= 0x0400) |
| 105 | #define set_C3() (I387.swd |= 0x4000) |
| 106 | |
| 107 | /* ea.c */ |
| 108 | |
| 109 | static char * ea(struct trapframe *, unsigned short); |
| 110 | |
| 111 | /* convert.c */ |
| 112 | |
| 113 | static void frndint(const temp_real * __a, temp_real * __b); |
| 114 | static void Fscale(const temp_real *, const temp_real *, temp_real *); |
| 115 | static void short_to_temp(const short_real * __a, temp_real * __b); |
| 116 | static void long_to_temp(const long_real * __a, temp_real * __b); |
| 117 | static void temp_to_short(const temp_real * __a, short_real * __b); |
| 118 | static void temp_to_long(const temp_real * __a, long_real * __b); |
| 119 | static void real_to_int(const temp_real * __a, temp_int * __b); |
| 120 | static void int_to_real(const temp_int * __a, temp_real * __b); |
| 121 | |
| 122 | /* get_put.c */ |
| 123 | |
| 124 | static void get_short_real(temp_real *, struct trapframe *, unsigned short); |
| 125 | static void get_long_real(temp_real *, struct trapframe *, unsigned short); |
| 126 | static void get_temp_real(temp_real *, struct trapframe *, unsigned short); |
| 127 | static void get_short_int(temp_real *, struct trapframe *, unsigned short); |
| 128 | static void get_long_int(temp_real *, struct trapframe *, unsigned short); |
| 129 | static void get_longlong_int(temp_real *, struct trapframe *, unsigned short); |
| 130 | static void get_BCD(temp_real *, struct trapframe *, unsigned short); |
| 131 | static void put_short_real(const temp_real *, struct trapframe *, unsigned short); |
| 132 | static void put_long_real(const temp_real *, struct trapframe *, unsigned short); |
| 133 | static void put_temp_real(const temp_real *, struct trapframe *, unsigned short); |
| 134 | static void put_short_int(const temp_real *, struct trapframe *, unsigned short); |
| 135 | static void put_long_int(const temp_real *, struct trapframe *, unsigned short); |
| 136 | static void put_longlong_int(const temp_real *, struct trapframe *, unsigned short); |
| 137 | static void put_BCD(const temp_real *, struct trapframe *, unsigned short); |
| 138 | |
| 139 | /* add.c */ |
| 140 | |
| 141 | static void fadd(const temp_real *, const temp_real *, temp_real *); |
| 142 | |
| 143 | /* mul.c */ |
| 144 | |
| 145 | static void fmul(const temp_real *, const temp_real *, temp_real *); |
| 146 | |
| 147 | /* div.c */ |
| 148 | |
| 149 | static void fdiv(const temp_real *, const temp_real *, temp_real *); |
| 150 | |
| 151 | /* compare.c */ |
| 152 | |
| 153 | static void fcom(const temp_real *, const temp_real *); |
| 154 | static void fucom(const temp_real *, const temp_real *); |
| 155 | static void ftst(const temp_real *); |
| 156 | |
| 157 | #endif |