1 /////////////////////////////////////////////////////////////////////////
2 // $Id: xmm.h 13963 2020-10-03 09:23:28Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2003-2018 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #ifndef BX_SSE_EXTENSIONS_H
25 #define BX_SSE_EXTENSIONS_H
26 
27 /* XMM REGISTER */
28 
29 typedef
30 #if defined(_MSC_VER) && (_MSC_VER>=1300)
31 __declspec(align(16))
32 #endif
33 union bx_xmm_reg_t {
34    Bit8s   xmm_sbyte[16];
35    Bit16s  xmm_s16[8];
36    Bit32s  xmm_s32[4];
37    Bit64s  xmm_s64[2];
38    Bit8u   xmm_ubyte[16];
39    Bit16u  xmm_u16[8];
40    Bit32u  xmm_u32[4];
41    Bit64u  xmm_u64[2];
42 
43    void clear() { xmm_u64[0] = xmm_u64[1] = 0; }
44 } BxPackedXmmRegister;
45 
46 #ifdef BX_BIG_ENDIAN
47 #define xmm64s(i)   xmm_s64[1 - (i)]
48 #define xmm32s(i)   xmm_s32[3 - (i)]
49 #define xmm16s(i)   xmm_s16[7 - (i)]
50 #define xmmsbyte(i) xmm_sbyte[15 - (i)]
51 #define xmmubyte(i) xmm_ubyte[15 - (i)]
52 #define xmm16u(i)   xmm_u16[7 - (i)]
53 #define xmm32u(i)   xmm_u32[3 - (i)]
54 #define xmm64u(i)   xmm_u64[1 - (i)]
55 #else
56 #define xmm64s(i)   xmm_s64[(i)]
57 #define xmm32s(i)   xmm_s32[(i)]
58 #define xmm16s(i)   xmm_s16[(i)]
59 #define xmmsbyte(i) xmm_sbyte[(i)]
60 #define xmmubyte(i) xmm_ubyte[(i)]
61 #define xmm16u(i)   xmm_u16[(i)]
62 #define xmm32u(i)   xmm_u32[(i)]
63 #define xmm64u(i)   xmm_u64[(i)]
64 #endif
65 
66 /* AVX REGISTER */
67 
68 typedef
69 #if defined(_MSC_VER) && (_MSC_VER>=1300)
70 __declspec(align(32))
71 #endif
72 union bx_ymm_reg_t {
73    Bit8s   ymm_sbyte[32];
74    Bit16s  ymm_s16[16];
75    Bit32s  ymm_s32[8];
76    Bit64s  ymm_s64[4];
77    Bit8u   ymm_ubyte[32];
78    Bit16u  ymm_u16[16];
79    Bit32u  ymm_u32[8];
80    Bit64u  ymm_u64[4];
81    BxPackedXmmRegister ymm_v128[2];
82 
83    void clear() {
84      ymm_v128[0].clear();
85      ymm_v128[1].clear();
86    }
87 } BxPackedYmmRegister;
88 
89 #ifdef BX_BIG_ENDIAN
90 #define ymm64s(i)   ymm_s64[3 - (i)]
91 #define ymm32s(i)   ymm_s32[7 - (i)]
92 #define ymm16s(i)   ymm_s16[15 - (i)]
93 #define ymmsbyte(i) ymm_sbyte[31 - (i)]
94 #define ymmubyte(i) ymm_ubyte[31 - (i)]
95 #define ymm16u(i)   ymm_u16[15 - (i)]
96 #define ymm32u(i)   ymm_u32[7 - (i)]
97 #define ymm64u(i)   ymm_u64[3 - (i)]
98 #define ymm128(i)   ymm_v128[1 - (i)]
99 #else
100 #define ymm64s(i)   ymm_s64[(i)]
101 #define ymm32s(i)   ymm_s32[(i)]
102 #define ymm16s(i)   ymm_s16[(i)]
103 #define ymmsbyte(i) ymm_sbyte[(i)]
104 #define ymmubyte(i) ymm_ubyte[(i)]
105 #define ymm16u(i)   ymm_u16[(i)]
106 #define ymm32u(i)   ymm_u32[(i)]
107 #define ymm64u(i)   ymm_u64[(i)]
108 #define ymm128(i)   ymm_v128[(i)]
109 #endif
110 
111 typedef
112 #if defined(_MSC_VER) && (_MSC_VER>=1300)
113 __declspec(align(64))
114 #endif
115 union bx_zmm_reg_t {
116    Bit8s   zmm_sbyte[64];
117    Bit16s  zmm_s16[32];
118    Bit32s  zmm_s32[16];
119    Bit64s  zmm_s64[8];
120    Bit8u   zmm_ubyte[64];
121    Bit16u  zmm_u16[32];
122    Bit32u  zmm_u32[16];
123    Bit64u  zmm_u64[8];
124    BxPackedXmmRegister zmm_v128[4];
125    BxPackedYmmRegister zmm_v256[2];
126 
127    void clear() {
128      zmm_v256[0].clear();
129      zmm_v256[1].clear();
130    }
131 } BxPackedZmmRegister;
132 
133 #ifdef BX_BIG_ENDIAN
134 #define zmm64s(i)   zmm_s64[7 - (i)]
135 #define zmm32s(i)   zmm_s32[15 - (i)]
136 #define zmm16s(i)   zmm_s16[31 - (i)]
137 #define zmmsbyte(i) zmm_sbyte[63 - (i)]
138 #define zmmubyte(i) zmm_ubyte[63 - (i)]
139 #define zmm16u(i)   zmm_u16[31 - (i)]
140 #define zmm32u(i)   zmm_u32[15 - (i)]
141 #define zmm64u(i)   zmm_u64[7 - (i)]
142 #define zmm128(i)   zmm_v128[3 - (i)]
143 #define zmm256(i)   zmm_v256[1 - (i)]
144 #else
145 #define zmm64s(i)   zmm_s64[(i)]
146 #define zmm32s(i)   zmm_s32[(i)]
147 #define zmm16s(i)   zmm_s16[(i)]
148 #define zmmsbyte(i) zmm_sbyte[(i)]
149 #define zmmubyte(i) zmm_ubyte[(i)]
150 #define zmm16u(i)   zmm_u16[(i)]
151 #define zmm32u(i)   zmm_u32[(i)]
152 #define zmm64u(i)   zmm_u64[(i)]
153 #define zmm128(i)   zmm_v128[(i)]
154 #define zmm256(i)   zmm_v256[(i)]
155 #endif
156 
157 #if BX_SUPPORT_EVEX
158 #  define vmm64s(i)   zmm64s(i)
159 #  define vmm32s(i)   zmm32s(i)
160 #  define vmm16s(i)   zmm16s(i)
161 #  define vmmsbyte(i) zmmsbyte(i)
162 #  define vmmubyte(i) zmmubyte(i)
163 #  define vmm16u(i)   zmm16u(i)
164 #  define vmm32u(i)   zmm32u(i)
165 #  define vmm64u(i)   zmm64u(i)
166 #  define vmm128(i)   zmm128(i)
167 #  define vmm256(i)   zmm256(i)
168 #else
169 #  if BX_SUPPORT_AVX
170 #    define vmm64s(i)   ymm64s(i)
171 #    define vmm32s(i)   ymm32s(i)
172 #    define vmm16s(i)   ymm16s(i)
173 #    define vmmsbyte(i) ymmsbyte(i)
174 #    define vmmubyte(i) ymmubyte(i)
175 #    define vmm16u(i)   ymm16u(i)
176 #    define vmm32u(i)   ymm32u(i)
177 #    define vmm64u(i)   ymm64u(i)
178 #    define vmm128(i)   ymm128(i)
179 #  else
180 #    define vmm64s(i)   xmm64s(i)
181 #    define vmm32s(i)   xmm32s(i)
182 #    define vmm16s(i)   xmm16s(i)
183 #    define vmmsbyte(i) xmmsbyte(i)
184 #    define vmmubyte(i) xmmubyte(i)
185 #    define vmm16u(i)   xmm16u(i)
186 #    define vmm32u(i)   xmm32u(i)
187 #    define vmm64u(i)   xmm64u(i)
188 #  endif
189 #endif
190 
191 #if BX_SUPPORT_EVEX
192 typedef BxPackedZmmRegister BxPackedAvxRegister;
193 #else
194 #if BX_SUPPORT_AVX
195 typedef BxPackedYmmRegister BxPackedAvxRegister;
196 #endif
197 #endif
198 
199 #define  BYTE_ELEMENTS(vlen) (16 * (vlen))
200 #define  WORD_ELEMENTS(vlen)  (8 * (vlen))
201 #define DWORD_ELEMENTS(vlen)  (4 * (vlen))
202 #define QWORD_ELEMENTS(vlen)  (2 * (vlen))
203 
204 /* ************ */
205 /* XMM REGISTER */
206 /* ************ */
207 
208 #if BX_SUPPORT_AVX
209 
210 /* read XMM register */
211 #define BX_READ_XMM_REG(index) (BX_CPU_THIS_PTR vmm[index].vmm128(0))
212 
213 #else /* BX_SUPPORT_AVX */
214 
215 /* read XMM register */
216 #define BX_READ_XMM_REG(index) (BX_CPU_THIS_PTR vmm[index])
217 
218 #endif /* BX_SUPPORT_AVX */
219 
220 /* read only high 64 bit of the register */
221 #define BX_READ_XMM_REG_HI_QWORD(index) \
222     (BX_CPU_THIS_PTR vmm[index].vmm64u(1))
223 
224 /* read only low 64 bit of the register */
225 #define BX_READ_XMM_REG_LO_QWORD(index) \
226     (BX_CPU_THIS_PTR vmm[index].vmm64u(0))
227 
228 /* read only low 32 bit of the register */
229 #define BX_READ_XMM_REG_LO_DWORD(index) \
230     (BX_CPU_THIS_PTR vmm[index].vmm32u(0))
231 
232 /* read only low 16 bit of the register */
233 #define BX_READ_XMM_REG_LO_WORD(index) \
234     (BX_CPU_THIS_PTR vmm[index].vmm16u(0))
235 
236 /* read only low 8 bit of the register */
237 #define BX_READ_XMM_REG_LO_BYTE(index) \
238     (BX_CPU_THIS_PTR vmm[index].vmmubyte(0))
239 
240 /* short names for above macroses */
241 #define BX_XMM_REG_HI_QWORD BX_READ_XMM_REG_HI_QWORD
242 #define BX_XMM_REG_LO_QWORD BX_READ_XMM_REG_LO_QWORD
243 #define BX_XMM_REG_LO_DWORD BX_READ_XMM_REG_LO_DWORD
244 
245 #define BX_XMM_REG BX_READ_XMM_REG
246 
247 /* store only high 64 bit of the register, rest of the register unchanged */
248 #define BX_WRITE_XMM_REG_HI_QWORD(index, reg64) \
249     { BX_CPU_THIS_PTR vmm[index].vmm64u(1) = (reg64); }
250 
251 /* store only low 64 bit of the register, rest of the register unchanged */
252 #define BX_WRITE_XMM_REG_LO_QWORD(index, reg64) \
253     { BX_CPU_THIS_PTR vmm[index].vmm64u(0) = (reg64); }
254 
255 /* store only low 32 bit of the register, rest of the register unchanged */
256 #define BX_WRITE_XMM_REG_LO_DWORD(index, reg32) \
257     { BX_CPU_THIS_PTR vmm[index].vmm32u(0) = (reg32); }
258 
259 /* store only low 16 bit of the register, rest of the register unchanged */
260 #define BX_WRITE_XMM_REG_LO_WORD(index, reg16) \
261     { BX_CPU_THIS_PTR vmm[index].vmm16u(0) = (reg16); }
262 
263 /* store only low 8 bit of the register, rest of the register unchanged */
264 #define BX_WRITE_XMM_REG_LO_BYTE(index, reg8) \
265     { BX_CPU_THIS_PTR vmm[index].vmmubyte(0) = (reg8); }
266 
267 /* store XMM register, upper part of the YMM or ZMM register unchanged */
268 #define BX_WRITE_XMM_REG(index, reg) \
269     { (BX_XMM_REG(index)) = (reg); }
270 
271 /* clear XMM register, upper part of the YMM or ZMM register unchanged */
272 #define BX_CLEAR_XMM_REG(index) { BX_XMM_REG(index).clear(); }
273 
274 /* ************ */
275 /* YMM REGISTER */
276 /* ************ */
277 
278 #if BX_SUPPORT_AVX
279 
280 #if BX_SUPPORT_EVEX
281 
282 /* read YMM register */
283 #define BX_READ_YMM_REG(index) (BX_CPU_THIS_PTR vmm[index].vmm256(0))
284 
285 /* clear upper part of the ZMM register */
286 #define BX_CLEAR_AVX_HIGH256(index) { BX_CPU_THIS_PTR vmm[index].vmm256(1).clear(); }
287 
288 #else /* BX_SUPPORT_EVEX */
289 
290 /* read YMM register */
291 #define BX_READ_YMM_REG(index) (BX_CPU_THIS_PTR vmm[index])
292 
293 /* clear upper part of the ZMM register - no upper part ;) */
294 #define BX_CLEAR_AVX_HIGH256(index)
295 
296 #endif /* BX_SUPPORT_EVEX */
297 
298 #define BX_YMM_REG BX_READ_YMM_REG
299 
300 /* clear upper part of AVX128 register */
301 #define BX_CLEAR_AVX_HIGH128(index) \
302     { BX_CPU_THIS_PTR vmm[index].vmm128(1).clear(); \
303       BX_CLEAR_AVX_HIGH256(index); }
304 
305 /* write YMM register and clear upper part of the AVX register */
306 #define BX_WRITE_YMM_REGZ(index, reg) \
307     { (BX_READ_YMM_REG(index)) = (reg); BX_CLEAR_AVX_HIGH256(index); }
308 
309 /* write XMM register and clear upper part of AVX register (if not SSE instruction) */
310 #define BX_WRITE_XMM_REGZ(index, reg, vlen) \
311     { (BX_XMM_REG(index)) = (reg); \
312        if (vlen) BX_CLEAR_AVX_HIGH128(index); }
313 
314 /* write XMM register while clearing upper part of the AVX register */
315 #define BX_WRITE_XMM_REG_CLEAR_HIGH(index, reg) \
316     { BX_XMM_REG(index) = (reg); BX_CLEAR_AVX_HIGH128(index); }
317 
318 #define BX_WRITE_XMM_REG_LO_QWORD_CLEAR_HIGH(index, reg64) \
319     { BX_CPU_THIS_PTR vmm[index].vmm64u(0) = (reg64); \
320       BX_CPU_THIS_PTR vmm[index].vmm64u(1) = 0; BX_CLEAR_AVX_HIGH128(index); }
321 
322 #else /* BX_SUPPORT_AVX */
323 
324 /* write XMM register while clearing upper part of AVX register */
325 #define BX_WRITE_XMM_REG_CLEAR_HIGH(index, reg) \
326     BX_WRITE_XMM_REG(index, reg)
327 
328 /* write XMM register while clearing upper part of AVX register */
329 #define BX_WRITE_XMM_REGZ(index, reg, vlen) \
330     BX_WRITE_XMM_REG(index, reg)
331 
332 #endif /* BX_SUPPORT_AVX */
333 
334 /* ************ */
335 /* AVX REGISTER */
336 /* ************ */
337 
338 // vector length independent accessors, i.e. access YMM when no EVEX was compiled in
339 // or ZMM when EVEX support was compiled in
340 
341 /* read AVX register */
342 #define BX_READ_AVX_REG(index) (BX_CPU_THIS_PTR vmm[index])
343 
344 #define BX_AVX_REG BX_READ_AVX_REG
345 
346 /* write AVX register */
347 #define BX_WRITE_AVX_REG(index, reg) { (BX_CPU_THIS_PTR vmm[index]) = (reg); }
348 
349 /* read AVX register lane */
350 #define BX_READ_AVX_REG_LANE(index, line) \
351      (BX_CPU_THIS_PTR vmm[index].vmm128(line))
352 
353 /* write AVX register and potentialy clear upper part of the register */
354 #define BX_WRITE_YMM_REGZ_VLEN(index, reg256, vlen)               \
355     { (BX_YMM_REG(index)) = (reg256);                             \
356       if (vlen == BX_VL256) { BX_CLEAR_AVX_HIGH256(index); }      \
357       else if (vlen == BX_VL128) { BX_CLEAR_AVX_HIGH128(index); } \
358     }
359 
360 /* clear upper part of the AVX register */
361 #define BX_CLEAR_AVX_REGZ(index, vlen)                              \
362     { if ((vlen) == BX_VL256) { BX_CLEAR_AVX_HIGH256(index); }      \
363       else if ((vlen) == BX_VL128) { BX_CLEAR_AVX_HIGH128(index); } \
364     }
365 
366 /* write AVX register and potentialy clear upper part of the register */
367 #define BX_WRITE_AVX_REGZ(index, reg, vlen)                       \
368     { BX_CPU_THIS_PTR vmm[index] = (reg);                         \
369       BX_CLEAR_AVX_REGZ(index, vlen);                             \
370     }
371 
372 /* clear AVX register */
373 #define BX_CLEAR_AVX_REG(index) { BX_CPU_THIS_PTR vmm[index].clear(); }
374 
375 #if BX_SUPPORT_EVEX
376 
377 /* read upper 256-bit part of ZMM register */
378 #define BX_READ_ZMM_REG_HI(index) \
379      (BX_CPU_THIS_PTR vmm[index].vmm256(1))
380 
381 #endif
382 
is_clear(const BxPackedXmmRegister * r)383 BX_CPP_INLINE int is_clear(const BxPackedXmmRegister *r)
384 {
385   return (r->xmm64u(0) | r->xmm64u(1)) == 0;
386 }
387 
388 #if BX_SUPPORT_EVEX
389 // implement SAE and EVEX encoded rounding control
softfloat_status_word_rc_override(float_status_t & status,bxInstruction_c * i)390 BX_CPP_INLINE void softfloat_status_word_rc_override(float_status_t &status, bxInstruction_c *i)
391 {
392   /* must be VL512 otherwise EVEX.LL encodes vector length */
393   if (i->modC0() && i->getEvexb()) {
394     status.float_rounding_mode = i->getRC();
395     status.float_suppress_exception = float_all_exceptions_mask;
396     status.float_exception_masks = float_all_exceptions_mask;
397   }
398 }
399 #else
400   #define softfloat_status_word_rc_override(status, i)
401 #endif
402 
403 /* convert float32 NaN number to QNaN */
convert_to_QNaN(float32 op)404 BX_CPP_INLINE float32 convert_to_QNaN(float32 op)
405 {
406   return op | 0x7FC00000;
407 }
408 
409 /* convert float64 NaN number to QNaN */
convert_to_QNaN(float64 op)410 BX_CPP_INLINE float64 convert_to_QNaN(float64 op)
411 {
412   return op | BX_CONST64(0x7FF8000000000000);
413 }
414 
415 /* MXCSR REGISTER */
416 
417 /* 31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16
418  * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==  (reserved)
419  *  0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|MM| 0
420  *
421  * 15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0
422  * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|==
423  * FZ| R C |PM|UM|OM|ZM|DM|IM|DZ|PE|UE|OE|ZE|DE|IE
424  */
425 
426 /* MXCSR REGISTER FIELDS DESCRIPTION */
427 
428 /*
429  * IE  0    Invalid-Operation Exception             0
430  * DE  1    Denormalized-Operand Exception          0
431  * ZE  2    Zero-Divide Exception                   0
432  * OE  3    Overflow Exception                      0
433  * UE  4    Underflow Exception                     0
434  * PE  5    Precision Exception                     0
435  * DZ  6    Denormals are Zeros                     0
436  * IM  7    Invalid-Operation Exception Mask        1
437  * DM  8    Denormalized-Operand Exception Mask     1
438  * ZM  9    Zero-Divide Exception Mask              1
439  * OM 10    Overflow Exception Mask                 1
440  * UM 11    Underflow Exception Mask                1
441  * PM 12    Precision Exception Mask                1
442  * RC 13-14 Floating-Point Rounding Control         00
443  * FZ 15    Flush-to-Zero for Masked Underflow      0
444  * RZ 16    Reserved                                0
445  * MM 17    Misaligned Exception Mask               0
446  */
447 
448 const Bit32u MXCSR_EXCEPTIONS                = 0x0000003F;
449 const Bit32u MXCSR_DAZ                       = 0x00000040;
450 const Bit32u MXCSR_MASKED_EXCEPTIONS         = 0x00001F80;
451 const Bit32u MXCSR_ROUNDING_CONTROL          = 0x00006000;
452 const Bit32u MXCSR_FLUSH_MASKED_UNDERFLOW    = 0x00008000;
453 const Bit32u MXCSR_MISALIGNED_EXCEPTION_MASK = 0x00020000;
454 
455 #define MXCSR_IE 0x00000001
456 #define MXCSR_DE 0x00000002
457 #define MXCSR_ZE 0x00000004
458 #define MXCSR_OE 0x00000008
459 #define MXCSR_UE 0x00000010
460 #define MXCSR_PE 0x00000020
461 
462 #define MXCSR_IM 0x00000080
463 #define MXCSR_DM 0x00000100
464 #define MXCSR_ZM 0x00000200
465 #define MXCSR_OM 0x00000400
466 #define MXCSR_UM 0x00000800
467 #define MXCSR_PM 0x00001000
468 
469 const Bit32u MXCSR_RESET = 0x00001F80;  /* reset value of the MXCSR register */
470 
471 struct BOCHSAPI bx_mxcsr_t
472 {
473   Bit32u mxcsr;
474 
475   bx_mxcsr_t (Bit32u val = MXCSR_RESET)
mxcsrbx_mxcsr_t476 	: mxcsr(val) {}
477 
478 #define IMPLEMENT_MXCSR_ACCESSOR(name, bitmask, bitnum)        \
479   int get_##name () const {                                    \
480     return (mxcsr & (bitmask)) >> (bitnum);                    \
481   }
482 
483   IMPLEMENT_MXCSR_ACCESSOR(exceptions_masks, MXCSR_MASKED_EXCEPTIONS, 7);
484   IMPLEMENT_MXCSR_ACCESSOR(DAZ, MXCSR_DAZ, 6);
485   IMPLEMENT_MXCSR_ACCESSOR(rounding_mode, MXCSR_ROUNDING_CONTROL, 13);
486   IMPLEMENT_MXCSR_ACCESSOR(flush_masked_underflow, MXCSR_FLUSH_MASKED_UNDERFLOW, 15);
487   IMPLEMENT_MXCSR_ACCESSOR(MM, MXCSR_MISALIGNED_EXCEPTION_MASK, 17);
488 
489   IMPLEMENT_MXCSR_ACCESSOR(IE, MXCSR_IE, 0);
490   IMPLEMENT_MXCSR_ACCESSOR(DE, MXCSR_DE, 1);
491   IMPLEMENT_MXCSR_ACCESSOR(ZE, MXCSR_ZE, 2);
492   IMPLEMENT_MXCSR_ACCESSOR(OE, MXCSR_OE, 3);
493   IMPLEMENT_MXCSR_ACCESSOR(UE, MXCSR_UE, 4);
494   IMPLEMENT_MXCSR_ACCESSOR(PE, MXCSR_PE, 5);
495 
496   IMPLEMENT_MXCSR_ACCESSOR(IM, MXCSR_IM, 7);
497   IMPLEMENT_MXCSR_ACCESSOR(DM, MXCSR_DM, 8);
498   IMPLEMENT_MXCSR_ACCESSOR(ZM, MXCSR_ZM, 9);
499   IMPLEMENT_MXCSR_ACCESSOR(OM, MXCSR_OM, 10);
500   IMPLEMENT_MXCSR_ACCESSOR(UM, MXCSR_UM, 11);
501   IMPLEMENT_MXCSR_ACCESSOR(PM, MXCSR_PM, 12);
502 
set_exceptionsbx_mxcsr_t503   void set_exceptions(int status) {
504     mxcsr |= (status & MXCSR_EXCEPTIONS);
505   }
506 
mask_all_exceptionsbx_mxcsr_t507   void mask_all_exceptions() {
508     mxcsr |= (MXCSR_MASKED_EXCEPTIONS);
509   }
510 
511 };
512 
513 #if defined(NEED_CPU_REG_SHORTCUTS)
514   #define MXCSR             (BX_CPU_THIS_PTR mxcsr)
515   #define BX_MXCSR_REGISTER (BX_CPU_THIS_PTR mxcsr.mxcsr)
516   #define MXCSR_MASK        (BX_CPU_THIS_PTR mxcsr_mask)
517 #endif
518 
519 /* INTEGER SATURATION */
520 
521 /*
522  * SaturateWordSToByteS  converts  a  signed  16-bit  value  to a signed
523  * 8-bit value.  If  the signed 16-bit value is less than -128, it is
524  * represented by the saturated value  -128  (0x80).  If it is  greater
525  * than 127, it is represented by the saturated value 127 (0x7F).
526 */
SaturateWordSToByteS(Bit16s value)527 BX_CPP_INLINE Bit8s BX_CPP_AttrRegparmN(1) SaturateWordSToByteS(Bit16s value)
528 {
529   if(value < -128) return -128;
530   if(value >  127) return  127;
531   return (Bit8s) value;
532 }
533 
534 /*
535  * SaturateQwordSToByteS converts a signed 32-bit value to a signed
536  * 8-bit value. If the signed 32-bit value is less than -128, it is
537  * represented by the saturated value -128 (0x80). If it is greater
538  * than 127, it is represented by the saturated value 127 (0x7F).
539 */
SaturateDwordSToByteS(Bit32s value)540 BX_CPP_INLINE Bit8s BX_CPP_AttrRegparmN(1) SaturateDwordSToByteS(Bit32s value)
541 {
542   if(value < -128) return -128;
543   if(value >  127) return  127;
544   return (Bit8s) value;
545 }
546 
547 /*
548  * SaturateQwordSToByteS converts a signed 64-bit value to a signed
549  * 8-bit value. If the signed 64-bit value is less than -128, it is
550  * represented by the saturated value -128 (0x80). If it is greater
551  * than 127, it is represented by the saturated value 127 (0x7F).
552 */
SaturateQwordSToByteS(Bit64s value)553 BX_CPP_INLINE Bit8s BX_CPP_AttrRegparmN(1) SaturateQwordSToByteS(Bit64s value)
554 {
555   if(value < -128) return -128;
556   if(value >  127) return  127;
557   return (Bit8s) value;
558 }
559 
560 /*
561  * SaturateQwordSToWordS  converts  a  signed  64-bit  value  to a signed
562  * 16-bit  value.  If  the signed 64-bit value is less than -32768, it is
563  * represented  by  the saturated value -32768 (0x8000). If it is greater
564  * than 32767, it is represented by the saturated value 32767 (0x7FFF).
565 */
SaturateQwordSToWordS(Bit64s value)566 BX_CPP_INLINE Bit16s BX_CPP_AttrRegparmN(1) SaturateQwordSToWordS(Bit64s value)
567 {
568   if(value < -32768) return -32768;
569   if(value >  32767) return  32767;
570   return (Bit16s) value;
571 }
572 
573 /*
574  * SaturateDwordSToWordS  converts  a  signed  32-bit  value  to a signed
575  * 16-bit  value.  If  the signed 32-bit value is less than -32768, it is
576  * represented  by  the saturated value -32768 (0x8000). If it is greater
577  * than 32767, it is represented by the saturated value 32767 (0x7FFF).
578 */
SaturateDwordSToWordS(Bit32s value)579 BX_CPP_INLINE Bit16s BX_CPP_AttrRegparmN(1) SaturateDwordSToWordS(Bit32s value)
580 {
581   if(value < -32768) return -32768;
582   if(value >  32767) return  32767;
583   return (Bit16s) value;
584 }
585 
586 /*
587  * SaturateQwordSToDwordS  converts  a  signed  64-bit  value  to a signed
588  * 32-bit value. If the signed 64-bit value is less than -2147483648, it
589  * is represented by the saturated value -2147483648 (0x80000000). If it
590  * is greater than 2147483647, it is represented by the saturated value
591  * 2147483647 (0x7FFFFFFF).
592 */
SaturateQwordSToDwordS(Bit64s value)593 BX_CPP_INLINE Bit32s BX_CPP_AttrRegparmN(1) SaturateQwordSToDwordS(Bit64s value)
594 {
595   if(value < BX_CONST64(-2147483648)) return BX_CONST64(-2147483648);
596   if(value >  2147483647) return  2147483647;
597   return (Bit32s) value;
598 }
599 
600 /*
601  * SaturateWordSToByteU  converts  a  signed  16-bit value to an unsigned
602  * 8-bit  value.  If  the  signed  16-bit  value  is less than zero it is
603  * represented  by the saturated value zero (0x00). If it is greater than
604  * 255 it is represented by the saturated value 255 (0xFF).
605 */
SaturateWordSToByteU(Bit16s value)606 BX_CPP_INLINE Bit8u BX_CPP_AttrRegparmN(1) SaturateWordSToByteU(Bit16s value)
607 {
608   if(value < 0) return 0;
609   if(value > 255) return 255;
610   return (Bit8u) value;
611 }
612 
613 /*
614  * SaturateDwordSToWordU  converts  a  signed 32-bit value to an unsigned
615  * 16-bit  value.  If  the  signed  32-bit value is less than zero, it is
616  * represented  by  the  saturated  value zero (0x0000). If it is greater
617  * than  65535, it is represented by the saturated value 65535 (0xFFFF).
618 */
SaturateDwordSToWordU(Bit32s value)619 BX_CPP_INLINE Bit16u BX_CPP_AttrRegparmN(1) SaturateDwordSToWordU(Bit32s value)
620 {
621   if(value < 0) return 0;
622   if(value > 65535) return 65535;
623   return (Bit16u) value;
624 }
625 
626 /*
627  * SaturateQwordSToDwordU  converts  a  signed 64-bit value to an unsigned
628  * 32-bit  value.  If  the  signed  64-bit value is less than  zero, it is
629  * represented by the saturated value zero (0x00000000). If it is  greater
630  * than  4294967295, it is represented  by the  saturated value 4294967295
631  * (0xFFFFFFFF).
632 */
SaturateQwordSToDwordU(Bit64s value)633 BX_CPP_INLINE Bit32u BX_CPP_AttrRegparmN(1) SaturateQwordSToDwordU(Bit64s value)
634 {
635   if(value < 0) return 0;
636   if(value > BX_CONST64(4294967295)) return BX_CONST64(4294967295);
637   return (Bit32u) value;
638 }
639 
640 /*
641  * SaturateWordUToByteU converts an unsigned  16-bit value to unsigned
642  * 8-bit value. If the unsigned 16-bit value is greater than 255, it is
643  * represented by the saturated value 255 (0xFF).
644 */
SaturateWordUToByteU(Bit16u value)645 BX_CPP_INLINE Bit8u BX_CPP_AttrRegparmN(1) SaturateWordUToByteU(Bit16u value)
646 {
647   if(value > 255) return 255;
648   return (Bit8u) value;
649 }
650 
651 /*
652  * SaturateDWordUToByteU converts an unsigned  32-bit value to unsigned
653  * 8-bit value. If the unsigned 32-bit value is greater than 255, it is
654  * represented by the saturated value 255 (0xFF).
655 */
SaturateDwordUToByteU(Bit32u value)656 BX_CPP_INLINE Bit8u BX_CPP_AttrRegparmN(1) SaturateDwordUToByteU(Bit32u value)
657 {
658   if(value > 255) return 255;
659   return (Bit8u) value;
660 }
661 
662 /*
663  * SaturateQWordUToByteU converts an unsigned  64-bit value to unsigned
664  * 8-bit value. If the unsigned 64-bit value is greater than 255, it is
665  * represented by the saturated value 255 (0xFF).
666 */
SaturateQwordUToByteU(Bit64u value)667 BX_CPP_INLINE Bit8u BX_CPP_AttrRegparmN(1) SaturateQwordUToByteU(Bit64u value)
668 {
669   if(value > 255) return 255;
670   return (Bit8u) value;
671 }
672 
673 /*
674  * SaturateQwordUToWordU converts an unsigned 64-bit value to unsigned
675  * 16-bit value. If the unsigned 64-bit value is greater than 65535,
676  * it is represented by the saturated value 65535 (0xFFFF).
677 */
SaturateQwordUToWordU(Bit64u value)678 BX_CPP_INLINE Bit16u BX_CPP_AttrRegparmN(1) SaturateQwordUToWordU(Bit64u value)
679 {
680   if(value > 65535) return 65535;
681   return (Bit16u) value;
682 }
683 
684 /*
685  * SaturateDwordUToWordU converts an unsigned 32-bit value to unsigned
686  * 16-bit value. If the unsigned 32-bit value is greater than 65535,
687  * it is represented by the saturated value 65535 (0xFFFF).
688 */
SaturateDwordUToWordU(Bit32u value)689 BX_CPP_INLINE Bit16u BX_CPP_AttrRegparmN(1) SaturateDwordUToWordU(Bit32u value)
690 {
691   if(value > 65535) return 65535;
692   return (Bit16u) value;
693 }
694 
695 /*
696  * SaturateQwordUToDwordU converts  an unsigned 64-bit value to unsigned
697  * 32-bit value. If the unsigned 64-bit value is greater than 4294967295,
698  * it is represented by the saturated value 4294967295 (0xFFFFFFFF).
699 */
SaturateQwordUToDwordU(Bit64u value)700 BX_CPP_INLINE Bit32u BX_CPP_AttrRegparmN(1) SaturateQwordUToDwordU(Bit64u value)
701 {
702   if(value > BX_CONST64(4294967295)) return BX_CONST64(4294967295);
703   return (Bit32u) value;
704 }
705 
706 #endif
707