summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/i386/x87priv.h
blob: 1d2c227b29253336fde2d83e3a48117fb4b24013 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// license:BSD-3-Clause
// copyright-holders:Philip Bennett
#pragma once

#ifndef __X87PRIV_H__
#define __X87PRIV_H__

#include <cmath>


/*************************************
 *
 * Defines
 *
 *************************************/

#define X87_SW_IE               0x0001
#define X87_SW_DE               0x0002
#define X87_SW_ZE               0x0004
#define X87_SW_OE               0x0008
#define X87_SW_UE               0x0010
#define X87_SW_PE               0x0020
#define X87_SW_SF               0x0040
#define X87_SW_ES               0x0080
#define X87_SW_C0               0x0100
#define X87_SW_C1               0x0200
#define X87_SW_C2               0x0400
#define X87_SW_TOP_SHIFT        11
#define X87_SW_TOP_MASK         7
#define X87_SW_C3               0x4000
#define X87_SW_BUSY             0x8000

#define X87_CW_IM               0x0001
#define X87_CW_DM               0x0002
#define X87_CW_ZM               0x0004
#define X87_CW_OM               0x0008
#define X87_CW_UM               0x0010
#define X87_CW_PM               0x0020
#define X87_CW_PC_SHIFT         8
#define X87_CW_PC_MASK          3
#define X87_CW_PC_SINGLE        0
#define X87_CW_PC_DOUBLE        2
#define X87_CW_PC_EXTEND        3
#define X87_CW_RC_SHIFT         10
#define X87_CW_RC_MASK          3
#define X87_CW_RC_NEAREST       0
#define X87_CW_RC_DOWN          1
#define X87_CW_RC_UP            2
#define X87_CW_RC_ZERO          3

#define X87_TW_MASK             3
#define X87_TW_VALID            0
#define X87_TW_ZERO             1
#define X87_TW_SPECIAL          2
#define X87_TW_EMPTY            3


 /*************************************
  *
  * Macros
  *
  *************************************/

#define ST_TO_PHYS(x)           (((m_x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK)
#define ST(x)                   (m_x87_reg[ST_TO_PHYS(x)])
#define X87_TW_FIELD_SHIFT(x)   ((x) << 1)
#define X87_TAG(x)              ((m_x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK)
#define X87_RC                  ((m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK)
#define X87_IS_ST_EMPTY(x)      (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY)
#define X87_SW_C3_0             X87_SW_C0

#define UNIMPLEMENTED           fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, m_pc)


  /*************************************
   *
   * Constants
   *
   *************************************/

static const floatx80 fx80_zero = { 0x0000, 0x0000000000000000U };
static const floatx80 fx80_one = { 0x3fff, 0x8000000000000000U };

static const floatx80 fx80_ninf = { 0xffff, 0x8000000000000000U };
static const floatx80 fx80_inan = { 0xffff, 0xc000000000000000U };

/* Maps x87 round modes to SoftFloat round modes */
static const int x87_to_sf_rc[4] =
{
	float_round_nearest_even,
	float_round_down,
	float_round_up,
	float_round_to_zero,
};


/*************************************
 *
 * SoftFloat helpers
 *
 *************************************/

extern flag floatx80_is_nan(floatx80 a);

extern flag floatx80_is_signaling_nan(floatx80 a);

static inline flag floatx80_is_quiet_nan(floatx80 a)
{
	bits64 aLow;

	aLow = a.low & ~LIT64(0x4000000000000000);
	return
		((a.high & 0x7FFF) == 0x7FFF)
		&& (bits64)(aLow << 1)
		&& (a.low != aLow);
}

static inline int floatx80_is_zero(floatx80 fx)
{
	return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0));
}

static inline int floatx80_is_inf(floatx80 fx)
{
	return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0));
}

static inline int floatx80_is_denormal(floatx80 fx)
{
	return (((fx.high & 0x7fff) == 0) &&
		((fx.low & 0x8000000000000000U) == 0) &&
		((fx.low << 1) != 0));
}

static inline floatx80 floatx80_abs(floatx80 fx)
{
	fx.high &= 0x7fff;
	return fx;
}

static inline double fx80_to_double(floatx80 fx)
{
	uint64_t d = floatx80_to_float64(fx);
	return *(double*)&d;
}

static inline floatx80 double_to_fx80(double in)
{
	return float64_to_floatx80(*(uint64_t*)&in);
}

floatx80 i386_device::READ80(uint32_t ea)
{
	floatx80 t;

	t.low = READ64(ea);
	t.high = READ16(ea + 8);

	return t;
}

void i386_device::WRITE80(uint32_t ea, floatx80 t)
{
	WRITE64(ea, t.low);
	WRITE16(ea + 8, t.high);
}

#endif /* __X87PRIV_H__ */