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