1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mmx.cc 14026 2020-12-15 20:05:54Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2002-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 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
28 
29 #if BX_CPU_LEVEL >= 5
30 
print_state_MMX(void)31 void BX_CPU_C::print_state_MMX(void)
32 {
33   for(int i=0;i<8;i++) {
34     BxPackedMmxRegister mm = BX_READ_MMX_REG(i);
35     BX_DEBUG(("MM%d: %08x%08x", i, MMXUD1(mm), MMXUD0(mm)));
36   }
37 }
38 
39 #endif
40 
41 #if BX_CPU_LEVEL >= 6
42 
43 /* 0F 38 00 */
PSHUFB_PqQq(bxInstruction_c * i)44 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFB_PqQq(bxInstruction_c *i)
45 {
46   BX_CPU_THIS_PTR prepareMMX();
47 
48   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result;
49 
50   /* op2 is a register or memory reference */
51   if (i->modC0()) {
52     op2 = BX_READ_MMX_REG(i->src());
53   }
54   else {
55     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
56     /* pointer, segment address pair */
57     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
58   }
59 
60   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
61 
62   for(unsigned j=0; j<8; j++)
63   {
64     unsigned mask = op2.ubyte(j);
65     if (mask & 0x80)
66       result.ubyte(j) = 0;
67     else
68       result.ubyte(j) = op1.ubyte(mask & 0x7);
69   }
70 
71   BX_WRITE_MMX_REG(i->dst(), result);
72 
73   BX_NEXT_INSTR(i);
74 }
75 
76 /* 0F 38 01 */
PHADDW_PqQq(bxInstruction_c * i)77 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDW_PqQq(bxInstruction_c *i)
78 {
79   BX_CPU_THIS_PTR prepareMMX();
80 
81   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
82 
83   /* op2 is a register or memory reference */
84   if (i->modC0()) {
85     op2 = BX_READ_MMX_REG(i->src());
86   }
87   else {
88     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
89     /* pointer, segment address pair */
90     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
91   }
92 
93   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
94 
95   MMXUW0(op1) = MMXUW0(op1) + MMXUW1(op1);
96   MMXUW1(op1) = MMXUW2(op1) + MMXUW3(op1);
97   MMXUW2(op1) = MMXUW0(op2) + MMXUW1(op2);
98   MMXUW3(op1) = MMXUW2(op2) + MMXUW3(op2);
99 
100   BX_WRITE_MMX_REG(i->dst(), op1);
101 
102   BX_NEXT_INSTR(i);
103 }
104 
105 /* 0F 38 02 */
PHADDD_PqQq(bxInstruction_c * i)106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDD_PqQq(bxInstruction_c *i)
107 {
108   BX_CPU_THIS_PTR prepareMMX();
109 
110   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
111 
112   /* op2 is a register or memory reference */
113   if (i->modC0()) {
114     op2 = BX_READ_MMX_REG(i->src());
115   }
116   else {
117     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
118     /* pointer, segment address pair */
119     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
120   }
121 
122   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
123 
124   MMXUD0(op1) = MMXUD0(op1) + MMXUD1(op1);
125   MMXUD1(op1) = MMXUD0(op2) + MMXUD1(op2);
126 
127   BX_WRITE_MMX_REG(i->dst(), op1);
128 
129   BX_NEXT_INSTR(i);
130 }
131 
132 /* 0F 38 03 */
PHADDSW_PqQq(bxInstruction_c * i)133 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDSW_PqQq(bxInstruction_c *i)
134 {
135   BX_CPU_THIS_PTR prepareMMX();
136 
137   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
138 
139   /* op2 is a register or memory reference */
140   if (i->modC0()) {
141     op2 = BX_READ_MMX_REG(i->src());
142   }
143   else {
144     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
145     /* pointer, segment address pair */
146     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
147   }
148 
149   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
150 
151   MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW1(op1)));
152   MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW3(op1)));
153   MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op2)));
154   MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op2)));
155 
156   BX_WRITE_MMX_REG(i->dst(), op1);
157 
158   BX_NEXT_INSTR(i);
159 }
160 
161 /* 0F 38 04 */
PMADDUBSW_PqQq(bxInstruction_c * i)162 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDUBSW_PqQq(bxInstruction_c *i)
163 {
164   BX_CPU_THIS_PTR prepareMMX();
165 
166   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
167 
168   /* op2 is a register or memory reference */
169   if (i->modC0()) {
170     op2 = BX_READ_MMX_REG(i->src());
171   }
172   else {
173     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
174     /* pointer, segment address pair */
175     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
176   }
177 
178   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
179 
180   for(unsigned j=0; j<4; j++)
181   {
182     Bit32s temp = Bit32s(op1.ubyte(j*2+0))*Bit32s(op2.sbyte(j*2)) +
183                   Bit32s(op1.ubyte(j*2+1))*Bit32s(op2.sbyte(j*2+1));
184 
185     op1.s16(j) = SaturateDwordSToWordS(temp);
186   }
187 
188   BX_WRITE_MMX_REG(i->dst(), op1);
189 
190   BX_NEXT_INSTR(i);
191 }
192 
193 /* 0F 38 05 */
PHSUBSW_PqQq(bxInstruction_c * i)194 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBSW_PqQq(bxInstruction_c *i)
195 {
196   BX_CPU_THIS_PTR prepareMMX();
197 
198   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
199 
200   /* op2 is a register or memory reference */
201   if (i->modC0()) {
202     op2 = BX_READ_MMX_REG(i->src());
203   }
204   else {
205     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
206     /* pointer, segment address pair */
207     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
208   }
209 
210   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
211 
212   MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW1(op1)));
213   MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW3(op1)));
214   MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) - Bit32s(MMXSW1(op2)));
215   MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) - Bit32s(MMXSW3(op2)));
216 
217   BX_WRITE_MMX_REG(i->dst(), op1);
218 
219   BX_NEXT_INSTR(i);
220 }
221 
222 /* 0F 38 05 */
PHSUBW_PqQq(bxInstruction_c * i)223 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBW_PqQq(bxInstruction_c *i)
224 {
225   BX_CPU_THIS_PTR prepareMMX();
226 
227   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
228 
229   /* op2 is a register or memory reference */
230   if (i->modC0()) {
231     op2 = BX_READ_MMX_REG(i->src());
232   }
233   else {
234     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
235     /* pointer, segment address pair */
236     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
237   }
238 
239   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
240 
241   MMXUW0(op1) = MMXUW0(op1) - MMXUW1(op1);
242   MMXUW1(op1) = MMXUW2(op1) - MMXUW3(op1);
243   MMXUW2(op1) = MMXUW0(op2) - MMXUW1(op2);
244   MMXUW3(op1) = MMXUW2(op2) - MMXUW3(op2);
245 
246   BX_WRITE_MMX_REG(i->dst(), op1);
247 
248   BX_NEXT_INSTR(i);
249 }
250 
251 /* 0F 38 06 */
PHSUBD_PqQq(bxInstruction_c * i)252 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBD_PqQq(bxInstruction_c *i)
253 {
254   BX_CPU_THIS_PTR prepareMMX();
255 
256   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
257 
258   /* op2 is a register or memory reference */
259   if (i->modC0()) {
260     op2 = BX_READ_MMX_REG(i->src());
261   }
262   else {
263     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
264     /* pointer, segment address pair */
265     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
266   }
267 
268   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
269 
270   MMXUD0(op1) = MMXUD0(op1) - MMXUD1(op1);
271   MMXUD1(op1) = MMXUD0(op2) - MMXUD1(op2);
272 
273   BX_WRITE_MMX_REG(i->dst(), op1);
274 
275   BX_NEXT_INSTR(i);
276 }
277 
278 /* 0F 38 08 */
PSIGNB_PqQq(bxInstruction_c * i)279 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNB_PqQq(bxInstruction_c *i)
280 {
281   BX_CPU_THIS_PTR prepareMMX();
282 
283   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
284 
285   /* op2 is a register or memory reference */
286   if (i->modC0()) {
287     op2 = BX_READ_MMX_REG(i->src());
288   }
289   else {
290     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
291     /* pointer, segment address pair */
292     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
293   }
294 
295   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
296 
297   for(unsigned j=0; j<8; j++) {
298     int sign = (op2.sbyte(j) > 0) - (op2.sbyte(j) < 0);
299     op1.sbyte(j) *= sign;
300   }
301 
302   BX_WRITE_MMX_REG(i->dst(), op1);
303 
304   BX_NEXT_INSTR(i);
305 }
306 
307 /* 0F 38 09 */
PSIGNW_PqQq(bxInstruction_c * i)308 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNW_PqQq(bxInstruction_c *i)
309 {
310   BX_CPU_THIS_PTR prepareMMX();
311 
312   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
313 
314   /* op2 is a register or memory reference */
315   if (i->modC0()) {
316     op2 = BX_READ_MMX_REG(i->src());
317   }
318   else {
319     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
320     /* pointer, segment address pair */
321     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
322   }
323 
324   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
325 
326   for(unsigned j=0; j<4; j++) {
327     int sign = (op2.s16(j) > 0) - (op2.s16(j) < 0);
328     op1.s16(j) *= sign;
329   }
330 
331   BX_WRITE_MMX_REG(i->dst(), op1);
332 
333   BX_NEXT_INSTR(i);
334 }
335 
336 /* 0F 38 0A */
PSIGND_PqQq(bxInstruction_c * i)337 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGND_PqQq(bxInstruction_c *i)
338 {
339   BX_CPU_THIS_PTR prepareMMX();
340 
341   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
342 
343   /* op2 is a register or memory reference */
344   if (i->modC0()) {
345     op2 = BX_READ_MMX_REG(i->src());
346   }
347   else {
348     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
349     /* pointer, segment address pair */
350     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
351   }
352 
353   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
354 
355   int sign;
356 
357   sign = (MMXSD0(op2) > 0) - (MMXSD0(op2) < 0);
358   MMXSD0(op1) *= sign;
359   sign = (MMXSD1(op2) > 0) - (MMXSD1(op2) < 0);
360   MMXSD1(op1) *= sign;
361 
362   BX_WRITE_MMX_REG(i->dst(), op1);
363 
364   BX_NEXT_INSTR(i);
365 }
366 
367 /* 0F 38 0B */
PMULHRSW_PqQq(bxInstruction_c * i)368 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRSW_PqQq(bxInstruction_c *i)
369 {
370   BX_CPU_THIS_PTR prepareMMX();
371 
372   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
373 
374   /* op2 is a register or memory reference */
375   if (i->modC0()) {
376     op2 = BX_READ_MMX_REG(i->src());
377   }
378   else {
379     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
380     /* pointer, segment address pair */
381     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
382   }
383 
384   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
385 
386   MMXUW0(op1) = (((MMXSW0(op1) * MMXSW0(op2)) >> 14) + 1) >> 1;
387   MMXUW1(op1) = (((MMXSW1(op1) * MMXSW1(op2)) >> 14) + 1) >> 1;
388   MMXUW2(op1) = (((MMXSW2(op1) * MMXSW2(op2)) >> 14) + 1) >> 1;
389   MMXUW3(op1) = (((MMXSW3(op1) * MMXSW3(op2)) >> 14) + 1) >> 1;
390 
391   BX_WRITE_MMX_REG(i->dst(), op1);
392 
393   BX_NEXT_INSTR(i);
394 }
395 
396 /* 0F 38 1C */
PABSB_PqQq(bxInstruction_c * i)397 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSB_PqQq(bxInstruction_c *i)
398 {
399   BX_CPU_THIS_PTR prepareMMX();
400 
401   BxPackedMmxRegister op;
402 
403   if (i->modC0()) {
404     op = BX_READ_MMX_REG(i->src());
405   }
406   else {
407     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
408     /* pointer, segment address pair */
409     MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
410   }
411 
412   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
413 
414   if (MMXSB0(op) < 0) MMXUB0(op) = -MMXSB0(op);
415   if (MMXSB1(op) < 0) MMXUB1(op) = -MMXSB1(op);
416   if (MMXSB2(op) < 0) MMXUB2(op) = -MMXSB2(op);
417   if (MMXSB3(op) < 0) MMXUB3(op) = -MMXSB3(op);
418   if (MMXSB4(op) < 0) MMXUB4(op) = -MMXSB4(op);
419   if (MMXSB5(op) < 0) MMXUB5(op) = -MMXSB5(op);
420   if (MMXSB6(op) < 0) MMXUB6(op) = -MMXSB6(op);
421   if (MMXSB7(op) < 0) MMXUB7(op) = -MMXSB7(op);
422 
423   BX_WRITE_MMX_REG(i->dst(), op);
424 
425   BX_NEXT_INSTR(i);
426 }
427 
428 /* 0F 38 1D */
PABSW_PqQq(bxInstruction_c * i)429 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSW_PqQq(bxInstruction_c *i)
430 {
431   BX_CPU_THIS_PTR prepareMMX();
432 
433   BxPackedMmxRegister op;
434 
435   if (i->modC0()) {
436     op = BX_READ_MMX_REG(i->src());
437   }
438   else {
439     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
440     /* pointer, segment address pair */
441     MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
442   }
443 
444   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
445 
446   if (MMXSW0(op) < 0) MMXUW0(op) = -MMXSW0(op);
447   if (MMXSW1(op) < 0) MMXUW1(op) = -MMXSW1(op);
448   if (MMXSW2(op) < 0) MMXUW2(op) = -MMXSW2(op);
449   if (MMXSW3(op) < 0) MMXUW3(op) = -MMXSW3(op);
450 
451   BX_WRITE_MMX_REG(i->dst(), op);
452 
453   BX_NEXT_INSTR(i);
454 }
455 
456 /* 0F 38 1E */
PABSD_PqQq(bxInstruction_c * i)457 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSD_PqQq(bxInstruction_c *i)
458 {
459   BX_CPU_THIS_PTR prepareMMX();
460 
461   BxPackedMmxRegister op;
462 
463   if (i->modC0()) {
464     op = BX_READ_MMX_REG(i->src());
465   }
466   else {
467     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
468     /* pointer, segment address pair */
469     MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
470   }
471 
472   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
473 
474   if (MMXSD0(op) < 0) MMXUD0(op) = -MMXSD0(op);
475   if (MMXSD1(op) < 0) MMXUD1(op) = -MMXSD1(op);
476 
477   BX_WRITE_MMX_REG(i->dst(), op);
478 
479   BX_NEXT_INSTR(i);
480 }
481 
482 /* 0F 3A 0F */
PALIGNR_PqQqIb(bxInstruction_c * i)483 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PALIGNR_PqQqIb(bxInstruction_c *i)
484 {
485   BX_CPU_THIS_PTR prepareMMX();
486 
487   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
488 
489   /* op2 is a register or memory reference */
490   if (i->modC0()) {
491     op2 = BX_READ_MMX_REG(i->src());
492   }
493   else {
494     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
495     /* pointer, segment address pair */
496     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
497   }
498 
499   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
500 
501   unsigned shift = i->Ib() * 8;
502 
503   if(shift == 0)
504     MMXUQ(op1) = MMXUQ(op2);
505   else if(shift < 64)
506     MMXUQ(op1) = (MMXUQ(op2) >> shift) | (MMXUQ(op1) << (64-shift));
507   else if(shift < 128)
508     MMXUQ(op1) = MMXUQ(op1) >> (shift-64);
509   else
510     MMXUQ(op1) = 0;
511 
512   BX_WRITE_MMX_REG(i->dst(), op1);
513 
514   BX_NEXT_INSTR(i);
515 }
516 
517 #endif
518 
519 /* 0F 60 */
PUNPCKLBW_PqQd(bxInstruction_c * i)520 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLBW_PqQd(bxInstruction_c *i)
521 {
522 #if BX_CPU_LEVEL >= 5
523   BX_CPU_THIS_PTR prepareMMX();
524 
525   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
526 
527   /* op2 is a register or memory reference */
528   if (i->modC0()) {
529     op2 = BX_READ_MMX_REG(i->src());
530   }
531   else {
532     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
533     /* pointer, segment address pair */
534     MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr);
535   }
536 
537   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
538 
539   MMXUB7(op1) = MMXUB3(op2);
540   MMXUB6(op1) = MMXUB3(op1);
541   MMXUB5(op1) = MMXUB2(op2);
542   MMXUB4(op1) = MMXUB2(op1);
543   MMXUB3(op1) = MMXUB1(op2);
544   MMXUB2(op1) = MMXUB1(op1);
545   MMXUB1(op1) = MMXUB0(op2);
546 //MMXUB0(op1) = MMXUB0(op1);
547 
548   BX_WRITE_MMX_REG(i->dst(), op1);
549 #endif
550 
551   BX_NEXT_INSTR(i);
552 }
553 
554 /* 0F 61 */
PUNPCKLWD_PqQd(bxInstruction_c * i)555 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLWD_PqQd(bxInstruction_c *i)
556 {
557 #if BX_CPU_LEVEL >= 5
558   BX_CPU_THIS_PTR prepareMMX();
559 
560   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
561 
562   /* op2 is a register or memory reference */
563   if (i->modC0()) {
564     op2 = BX_READ_MMX_REG(i->src());
565   }
566   else {
567     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
568     /* pointer, segment address pair */
569     MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr);
570   }
571 
572   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
573 
574   MMXUW3(op1) = MMXUW1(op2);
575   MMXUW2(op1) = MMXUW1(op1);
576   MMXUW1(op1) = MMXUW0(op2);
577 //MMXUW0(op1) = MMXUW0(op1);
578 
579   BX_WRITE_MMX_REG(i->dst(), op1);
580 #endif
581 
582   BX_NEXT_INSTR(i);
583 }
584 
585 /* 0F 62 */
PUNPCKLDQ_PqQd(bxInstruction_c * i)586 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLDQ_PqQd(bxInstruction_c *i)
587 {
588 #if BX_CPU_LEVEL >= 5
589   BX_CPU_THIS_PTR prepareMMX();
590 
591   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
592 
593   /* op2 is a register or memory reference */
594   if (i->modC0()) {
595     op2 = BX_READ_MMX_REG(i->src());
596   }
597   else {
598     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
599     /* pointer, segment address pair */
600     MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr);
601   }
602 
603   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
604 
605   MMXUD1(op1) = MMXUD0(op2);
606 
607   BX_WRITE_MMX_REG(i->dst(), op1);
608 #endif
609 
610   BX_NEXT_INSTR(i);
611 }
612 
613 /* 0F 63 */
PACKSSWB_PqQq(bxInstruction_c * i)614 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSWB_PqQq(bxInstruction_c *i)
615 {
616 #if BX_CPU_LEVEL >= 5
617   BX_CPU_THIS_PTR prepareMMX();
618 
619   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
620 
621   /* op2 is a register or memory reference */
622   if (i->modC0()) {
623     op2 = BX_READ_MMX_REG(i->src());
624   }
625   else {
626     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
627     /* pointer, segment address pair */
628     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
629   }
630 
631   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
632 
633   MMXSB0(op1) = SaturateWordSToByteS(MMXSW0(op1));
634   MMXSB1(op1) = SaturateWordSToByteS(MMXSW1(op1));
635   MMXSB2(op1) = SaturateWordSToByteS(MMXSW2(op1));
636   MMXSB3(op1) = SaturateWordSToByteS(MMXSW3(op1));
637 
638   MMXSB4(op1) = SaturateWordSToByteS(MMXSW0(op2));
639   MMXSB5(op1) = SaturateWordSToByteS(MMXSW1(op2));
640   MMXSB6(op1) = SaturateWordSToByteS(MMXSW2(op2));
641   MMXSB7(op1) = SaturateWordSToByteS(MMXSW3(op2));
642 
643   BX_WRITE_MMX_REG(i->dst(), op1);
644 #endif
645 
646   BX_NEXT_INSTR(i);
647 }
648 
649 /* 0F 64 */
PCMPGTB_PqQq(bxInstruction_c * i)650 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTB_PqQq(bxInstruction_c *i)
651 {
652 #if BX_CPU_LEVEL >= 5
653   BX_CPU_THIS_PTR prepareMMX();
654 
655   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
656 
657   /* op2 is a register or memory reference */
658   if (i->modC0()) {
659     op2 = BX_READ_MMX_REG(i->src());
660   }
661   else {
662     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
663     /* pointer, segment address pair */
664     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
665   }
666 
667   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
668 
669   MMXUB0(op1) = (MMXSB0(op1) > MMXSB0(op2)) ? 0xff : 0;
670   MMXUB1(op1) = (MMXSB1(op1) > MMXSB1(op2)) ? 0xff : 0;
671   MMXUB2(op1) = (MMXSB2(op1) > MMXSB2(op2)) ? 0xff : 0;
672   MMXUB3(op1) = (MMXSB3(op1) > MMXSB3(op2)) ? 0xff : 0;
673   MMXUB4(op1) = (MMXSB4(op1) > MMXSB4(op2)) ? 0xff : 0;
674   MMXUB5(op1) = (MMXSB5(op1) > MMXSB5(op2)) ? 0xff : 0;
675   MMXUB6(op1) = (MMXSB6(op1) > MMXSB6(op2)) ? 0xff : 0;
676   MMXUB7(op1) = (MMXSB7(op1) > MMXSB7(op2)) ? 0xff : 0;
677 
678   BX_WRITE_MMX_REG(i->dst(), op1);
679 #endif
680 
681   BX_NEXT_INSTR(i);
682 }
683 
684 /* 0F 65 */
PCMPGTW_PqQq(bxInstruction_c * i)685 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTW_PqQq(bxInstruction_c *i)
686 {
687 #if BX_CPU_LEVEL >= 5
688   BX_CPU_THIS_PTR prepareMMX();
689 
690   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
691 
692   /* op2 is a register or memory reference */
693   if (i->modC0()) {
694     op2 = BX_READ_MMX_REG(i->src());
695   }
696   else {
697     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
698     /* pointer, segment address pair */
699     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
700   }
701 
702   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
703 
704   MMXUW0(op1) = (MMXSW0(op1) > MMXSW0(op2)) ? 0xffff : 0;
705   MMXUW1(op1) = (MMXSW1(op1) > MMXSW1(op2)) ? 0xffff : 0;
706   MMXUW2(op1) = (MMXSW2(op1) > MMXSW2(op2)) ? 0xffff : 0;
707   MMXUW3(op1) = (MMXSW3(op1) > MMXSW3(op2)) ? 0xffff : 0;
708 
709   BX_WRITE_MMX_REG(i->dst(), op1);
710 #endif
711 
712   BX_NEXT_INSTR(i);
713 }
714 
715 /* 0F 66 */
PCMPGTD_PqQq(bxInstruction_c * i)716 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTD_PqQq(bxInstruction_c *i)
717 {
718 #if BX_CPU_LEVEL >= 5
719   BX_CPU_THIS_PTR prepareMMX();
720 
721   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
722 
723   /* op2 is a register or memory reference */
724   if (i->modC0()) {
725     op2 = BX_READ_MMX_REG(i->src());
726   }
727   else {
728     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
729     /* pointer, segment address pair */
730     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
731   }
732 
733   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
734 
735   MMXUD0(op1) = (MMXSD0(op1) > MMXSD0(op2)) ? 0xffffffff : 0;
736   MMXUD1(op1) = (MMXSD1(op1) > MMXSD1(op2)) ? 0xffffffff : 0;
737 
738   BX_WRITE_MMX_REG(i->dst(), op1);
739 #endif
740 
741   BX_NEXT_INSTR(i);
742 }
743 
744 /* 0F 67 */
PACKUSWB_PqQq(bxInstruction_c * i)745 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKUSWB_PqQq(bxInstruction_c *i)
746 {
747 #if BX_CPU_LEVEL >= 5
748   BX_CPU_THIS_PTR prepareMMX();
749 
750   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
751 
752   /* op2 is a register or memory reference */
753   if (i->modC0()) {
754     op2 = BX_READ_MMX_REG(i->src());
755   }
756   else {
757     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
758     /* pointer, segment address pair */
759     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
760   }
761 
762   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
763 
764   MMXUB0(op1) = SaturateWordSToByteU(MMXSW0(op1));
765   MMXUB1(op1) = SaturateWordSToByteU(MMXSW1(op1));
766   MMXUB2(op1) = SaturateWordSToByteU(MMXSW2(op1));
767   MMXUB3(op1) = SaturateWordSToByteU(MMXSW3(op1));
768   MMXUB4(op1) = SaturateWordSToByteU(MMXSW0(op2));
769   MMXUB5(op1) = SaturateWordSToByteU(MMXSW1(op2));
770   MMXUB6(op1) = SaturateWordSToByteU(MMXSW2(op2));
771   MMXUB7(op1) = SaturateWordSToByteU(MMXSW3(op2));
772 
773   BX_WRITE_MMX_REG(i->dst(), op1);
774 #endif
775 
776   BX_NEXT_INSTR(i);
777 }
778 
779 /* 0F 68 */
PUNPCKHBW_PqQq(bxInstruction_c * i)780 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHBW_PqQq(bxInstruction_c *i)
781 {
782 #if BX_CPU_LEVEL >= 5
783   BX_CPU_THIS_PTR prepareMMX();
784 
785   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
786 
787   /* op2 is a register or memory reference */
788   if (i->modC0()) {
789     op2 = BX_READ_MMX_REG(i->src());
790   }
791   else {
792     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
793     /* pointer, segment address pair */
794     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
795   }
796 
797   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
798 
799   MMXUB0(op1) = MMXUB4(op1);
800   MMXUB1(op1) = MMXUB4(op2);
801   MMXUB2(op1) = MMXUB5(op1);
802   MMXUB3(op1) = MMXUB5(op2);
803   MMXUB4(op1) = MMXUB6(op1);
804   MMXUB5(op1) = MMXUB6(op2);
805   MMXUB6(op1) = MMXUB7(op1);
806   MMXUB7(op1) = MMXUB7(op2);
807 
808   BX_WRITE_MMX_REG(i->dst(), op1);
809 #endif
810 
811   BX_NEXT_INSTR(i);
812 }
813 
814 /* 0F 69 */
PUNPCKHWD_PqQq(bxInstruction_c * i)815 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHWD_PqQq(bxInstruction_c *i)
816 {
817 #if BX_CPU_LEVEL >= 5
818   BX_CPU_THIS_PTR prepareMMX();
819 
820   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
821 
822   /* op2 is a register or memory reference */
823   if (i->modC0()) {
824     op2 = BX_READ_MMX_REG(i->src());
825   }
826   else {
827     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
828     /* pointer, segment address pair */
829     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
830   }
831 
832   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
833 
834   MMXUW0(op1) = MMXUW2(op1);
835   MMXUW1(op1) = MMXUW2(op2);
836   MMXUW2(op1) = MMXUW3(op1);
837   MMXUW3(op1) = MMXUW3(op2);
838 
839   BX_WRITE_MMX_REG(i->dst(), op1);
840 #endif
841 
842   BX_NEXT_INSTR(i);
843 }
844 
845 /* 0F 6A */
PUNPCKHDQ_PqQq(bxInstruction_c * i)846 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHDQ_PqQq(bxInstruction_c *i)
847 {
848 #if BX_CPU_LEVEL >= 5
849   BX_CPU_THIS_PTR prepareMMX();
850 
851   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
852 
853   /* op2 is a register or memory reference */
854   if (i->modC0()) {
855     op2 = BX_READ_MMX_REG(i->src());
856   }
857   else {
858     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
859     /* pointer, segment address pair */
860     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
861   }
862 
863   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
864 
865   MMXUD0(op1) = MMXUD1(op1);
866   MMXUD1(op1) = MMXUD1(op2);
867 
868   BX_WRITE_MMX_REG(i->dst(), op1);
869 #endif
870 
871   BX_NEXT_INSTR(i);
872 }
873 
874 /* 0F 6B */
PACKSSDW_PqQq(bxInstruction_c * i)875 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSDW_PqQq(bxInstruction_c *i)
876 {
877 #if BX_CPU_LEVEL >= 5
878   BX_CPU_THIS_PTR prepareMMX();
879 
880   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
881 
882   /* op2 is a register or memory reference */
883   if (i->modC0()) {
884     op2 = BX_READ_MMX_REG(i->src());
885   }
886   else {
887     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
888     /* pointer, segment address pair */
889     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
890   }
891 
892   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
893 
894   MMXSW0(op1) = SaturateDwordSToWordS(MMXSD0(op1));
895   MMXSW1(op1) = SaturateDwordSToWordS(MMXSD1(op1));
896   MMXSW2(op1) = SaturateDwordSToWordS(MMXSD0(op2));
897   MMXSW3(op1) = SaturateDwordSToWordS(MMXSD1(op2));
898 
899   BX_WRITE_MMX_REG(i->dst(), op1);
900 #endif
901 
902   BX_NEXT_INSTR(i);
903 }
904 
905 /* 0F 6E */
MOVD_PqEdR(bxInstruction_c * i)906 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEdR(bxInstruction_c *i)
907 {
908 #if BX_CPU_LEVEL >= 5
909   BX_CPU_THIS_PTR prepareMMX();
910   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
911 
912   BxPackedMmxRegister op = (Bit64u) BX_READ_32BIT_REG(i->src());
913   BX_WRITE_MMX_REG(i->dst(), op);
914 #endif
915 
916   BX_NEXT_INSTR(i);
917 }
918 
MOVD_PqEdM(bxInstruction_c * i)919 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEdM(bxInstruction_c *i)
920 {
921 #if BX_CPU_LEVEL >= 5
922   BX_CPU_THIS_PTR prepareMMX();
923 
924   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
925   BxPackedMmxRegister op = (Bit64u) read_virtual_dword(i->seg(), eaddr);
926 
927   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
928 
929   BX_WRITE_MMX_REG(i->dst(), op);
930 #endif
931 
932   BX_NEXT_INSTR(i);
933 }
934 
935 /* 0F 6E */
936 #if BX_SUPPORT_X86_64
MOVQ_PqEqR(bxInstruction_c * i)937 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqEqR(bxInstruction_c *i)
938 {
939   BX_CPU_THIS_PTR prepareMMX();
940   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
941 
942   BxPackedMmxRegister op = BX_READ_64BIT_REG(i->src());
943   BX_WRITE_MMX_REG(i->dst(), op);
944 
945   BX_NEXT_INSTR(i);
946 }
947 #endif
948 
949 /* 0F 6F */
MOVQ_PqQqR(bxInstruction_c * i)950 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQqR(bxInstruction_c *i)
951 {
952 #if BX_CPU_LEVEL >= 5
953   BX_CPU_THIS_PTR prepareMMX();
954   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
955 
956   BX_WRITE_MMX_REG(i->dst(), BX_READ_MMX_REG(i->src()));
957 #endif
958 
959   BX_NEXT_INSTR(i);
960 }
961 
MOVQ_PqQqM(bxInstruction_c * i)962 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQqM(bxInstruction_c *i)
963 {
964 #if BX_CPU_LEVEL >= 5
965   BX_CPU_THIS_PTR prepareMMX();
966 
967   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
968   BxPackedMmxRegister op = read_virtual_qword(i->seg(), eaddr);
969 
970   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
971 
972   BX_WRITE_MMX_REG(i->dst(), op);
973 #endif
974 
975   BX_NEXT_INSTR(i);
976 }
977 
978 /* 0F 70 */
PSHUFW_PqQqIb(bxInstruction_c * i)979 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFW_PqQqIb(bxInstruction_c *i)
980 {
981 #if BX_CPU_LEVEL >= 5
982   BX_CPU_THIS_PTR prepareMMX();
983 
984   BxPackedMmxRegister op, result;
985   Bit8u order = i->Ib();
986 
987   /* op is a register or memory reference */
988   if (i->modC0()) {
989     op = BX_READ_MMX_REG(i->src());
990   }
991   else {
992     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
993     /* pointer, segment address pair */
994     MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
995   }
996 
997   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
998 
999   MMXUW0(result) = op.u16((order)    & 0x3);
1000   MMXUW1(result) = op.u16((order>>2) & 0x3);
1001   MMXUW2(result) = op.u16((order>>4) & 0x3);
1002   MMXUW3(result) = op.u16((order>>6) & 0x3);
1003 
1004   BX_WRITE_MMX_REG(i->dst(), result);
1005 #endif
1006 
1007   BX_NEXT_INSTR(i);
1008 }
1009 
1010 /* 0F 74 */
PCMPEQB_PqQq(bxInstruction_c * i)1011 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQB_PqQq(bxInstruction_c *i)
1012 {
1013 #if BX_CPU_LEVEL >= 5
1014   BX_CPU_THIS_PTR prepareMMX();
1015 
1016   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1017 
1018   /* op2 is a register or memory reference */
1019   if (i->modC0()) {
1020     op2 = BX_READ_MMX_REG(i->src());
1021   }
1022   else {
1023     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1024     /* pointer, segment address pair */
1025     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1026   }
1027 
1028   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1029 
1030   MMXUB0(op1) = (MMXUB0(op1) == MMXUB0(op2)) ? 0xff : 0;
1031   MMXUB1(op1) = (MMXUB1(op1) == MMXUB1(op2)) ? 0xff : 0;
1032   MMXUB2(op1) = (MMXUB2(op1) == MMXUB2(op2)) ? 0xff : 0;
1033   MMXUB3(op1) = (MMXUB3(op1) == MMXUB3(op2)) ? 0xff : 0;
1034   MMXUB4(op1) = (MMXUB4(op1) == MMXUB4(op2)) ? 0xff : 0;
1035   MMXUB5(op1) = (MMXUB5(op1) == MMXUB5(op2)) ? 0xff : 0;
1036   MMXUB6(op1) = (MMXUB6(op1) == MMXUB6(op2)) ? 0xff : 0;
1037   MMXUB7(op1) = (MMXUB7(op1) == MMXUB7(op2)) ? 0xff : 0;
1038 
1039   BX_WRITE_MMX_REG(i->dst(), op1);
1040 #endif
1041 
1042   BX_NEXT_INSTR(i);
1043 }
1044 
1045 /* 0F 75 */
PCMPEQW_PqQq(bxInstruction_c * i)1046 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQW_PqQq(bxInstruction_c *i)
1047 {
1048 #if BX_CPU_LEVEL >= 5
1049   BX_CPU_THIS_PTR prepareMMX();
1050 
1051   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1052 
1053   /* op2 is a register or memory reference */
1054   if (i->modC0()) {
1055     op2 = BX_READ_MMX_REG(i->src());
1056   }
1057   else {
1058     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1059     /* pointer, segment address pair */
1060     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1061   }
1062 
1063   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1064 
1065   MMXUW0(op1) = (MMXUW0(op1) == MMXUW0(op2)) ? 0xffff : 0;
1066   MMXUW1(op1) = (MMXUW1(op1) == MMXUW1(op2)) ? 0xffff : 0;
1067   MMXUW2(op1) = (MMXUW2(op1) == MMXUW2(op2)) ? 0xffff : 0;
1068   MMXUW3(op1) = (MMXUW3(op1) == MMXUW3(op2)) ? 0xffff : 0;
1069 
1070   BX_WRITE_MMX_REG(i->dst(), op1);
1071 #endif
1072 
1073   BX_NEXT_INSTR(i);
1074 }
1075 
1076 /* 0F 76 */
PCMPEQD_PqQq(bxInstruction_c * i)1077 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQD_PqQq(bxInstruction_c *i)
1078 {
1079 #if BX_CPU_LEVEL >= 5
1080   BX_CPU_THIS_PTR prepareMMX();
1081 
1082   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1083 
1084   /* op2 is a register or memory reference */
1085   if (i->modC0()) {
1086     op2 = BX_READ_MMX_REG(i->src());
1087   }
1088   else {
1089     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1090     /* pointer, segment address pair */
1091     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1092   }
1093 
1094   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1095 
1096   MMXUD0(op1) = (MMXUD0(op1) == MMXUD0(op2)) ? 0xffffffff : 0;
1097   MMXUD1(op1) = (MMXUD1(op1) == MMXUD1(op2)) ? 0xffffffff : 0;
1098 
1099   BX_WRITE_MMX_REG(i->dst(), op1);
1100 #endif
1101 
1102   BX_NEXT_INSTR(i);
1103 }
1104 
1105 /* 0F 77 */
EMMS(bxInstruction_c * i)1106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::EMMS(bxInstruction_c *i)
1107 {
1108 #if BX_CPU_LEVEL >= 5
1109   BX_CPU_THIS_PTR prepareMMX();
1110   FPU_TAG_WORD  = 0xffff;
1111   FPU_TOS = 0;        /* reset FPU Top-Of-Stack */
1112 #endif
1113 
1114   BX_NEXT_INSTR(i);
1115 }
1116 
1117 /* 0F 7E */
MOVD_EdPqR(bxInstruction_c * i)1118 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPqR(bxInstruction_c *i)
1119 {
1120 #if BX_CPU_LEVEL >= 5
1121   BX_CPU_THIS_PTR prepareMMX();
1122   BX_CPU_THIS_PTR prepareFPU2MMX();
1123 
1124   BxPackedMmxRegister op = BX_READ_MMX_REG(i->src());
1125   BX_WRITE_32BIT_REGZ(i->dst(), MMXUD0(op));
1126 #endif
1127 
1128   BX_NEXT_INSTR(i);
1129 }
1130 
MOVD_EdPqM(bxInstruction_c * i)1131 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPqM(bxInstruction_c *i)
1132 {
1133 #if BX_CPU_LEVEL >= 5
1134   BX_CPU_THIS_PTR prepareMMX();
1135 
1136   BxPackedMmxRegister op = BX_READ_MMX_REG(i->src());
1137 
1138   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1139   /* pointer, segment address pair */
1140   write_virtual_dword(i->seg(), eaddr, MMXUD0(op));
1141 
1142   // do not cause FPU2MMX transition if memory write faults
1143   BX_CPU_THIS_PTR prepareFPU2MMX();
1144 #endif
1145 
1146   BX_NEXT_INSTR(i);
1147 }
1148 
1149 #if BX_SUPPORT_X86_64
1150 
1151 /* 0F 7E */
MOVQ_EqPqR(bxInstruction_c * i)1152 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_EqPqR(bxInstruction_c *i)
1153 {
1154   BX_CPU_THIS_PTR prepareMMX();
1155   BX_CPU_THIS_PTR prepareFPU2MMX();
1156 
1157   BX_WRITE_64BIT_REG(i->dst(), BX_MMX_REG(i->src()));
1158 
1159   BX_NEXT_INSTR(i);
1160 }
1161 
1162 #endif
1163 
1164 /* 0F 7F - MOVQ_QqPqM  */
1165 /* 0F E7 - MOVNTQ_MqPq */
MOVQ_QqPqM(bxInstruction_c * i)1166 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_QqPqM(bxInstruction_c *i)
1167 {
1168 #if BX_CPU_LEVEL >= 5
1169   BX_CPU_THIS_PTR prepareMMX();
1170 
1171   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1172   /* pointer, segment address pair */
1173   write_virtual_qword(i->seg(), eaddr, BX_MMX_REG(i->src()));
1174 
1175   // do not cause FPU2MMX transition if memory write faults
1176   BX_CPU_THIS_PTR prepareFPU2MMX();
1177 #endif
1178 
1179   BX_NEXT_INSTR(i);
1180 }
1181 
1182 /* 0F C4 */
PINSRW_PqEwIb(bxInstruction_c * i)1183 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRW_PqEwIb(bxInstruction_c *i)
1184 {
1185 #if BX_CPU_LEVEL >= 5
1186   BX_CPU_THIS_PTR prepareMMX();
1187 
1188   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst());
1189   Bit16u op2;
1190 
1191   /* op2 is a register or memory reference */
1192   if (i->modC0()) {
1193     op2 = BX_READ_16BIT_REG(i->src());
1194   }
1195   else {
1196     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1197     /* pointer, segment address pair */
1198     op2 = read_virtual_word(i->seg(), eaddr);
1199   }
1200 
1201   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1202 
1203   op1.u16(i->Ib() & 0x3) = op2;
1204 
1205   BX_WRITE_MMX_REG(i->dst(), op1);
1206 #endif
1207 
1208   BX_NEXT_INSTR(i);
1209 }
1210 
1211 /* 0F C5 */
PEXTRW_GdNqIb(bxInstruction_c * i)1212 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_GdNqIb(bxInstruction_c *i)
1213 {
1214 #if BX_CPU_LEVEL >= 5
1215   BX_CPU_THIS_PTR prepareMMX();
1216   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1217 
1218   BxPackedMmxRegister op = BX_READ_MMX_REG(i->src());
1219   Bit32u result = (Bit32u) op.u16(i->Ib() & 0x3);
1220 
1221   BX_WRITE_32BIT_REGZ(i->dst(), result);
1222 #endif
1223 
1224   BX_NEXT_INSTR(i);
1225 }
1226 
1227 /* 0F D1 */
PSRLW_PqQq(bxInstruction_c * i)1228 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqQq(bxInstruction_c *i)
1229 {
1230 #if BX_CPU_LEVEL >= 5
1231   BX_CPU_THIS_PTR prepareMMX();
1232 
1233   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1234 
1235   /* op2 is a register or memory reference */
1236   if (i->modC0()) {
1237     op2 = BX_READ_MMX_REG(i->src());
1238   }
1239   else {
1240     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1241     /* pointer, segment address pair */
1242     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1243   }
1244 
1245   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1246 
1247   if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
1248   else
1249   {
1250     Bit8u shift = MMXUB0(op2);
1251 
1252     MMXUW0(op1) >>= shift;
1253     MMXUW1(op1) >>= shift;
1254     MMXUW2(op1) >>= shift;
1255     MMXUW3(op1) >>= shift;
1256   }
1257 
1258   BX_WRITE_MMX_REG(i->dst(), op1);
1259 #endif
1260 
1261   BX_NEXT_INSTR(i);
1262 }
1263 
1264 /* 0F D2 */
PSRLD_PqQq(bxInstruction_c * i)1265 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqQq(bxInstruction_c *i)
1266 {
1267 #if BX_CPU_LEVEL >= 5
1268   BX_CPU_THIS_PTR prepareMMX();
1269 
1270   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1271 
1272   /* op2 is a register or memory reference */
1273   if (i->modC0()) {
1274     op2 = BX_READ_MMX_REG(i->src());
1275   }
1276   else {
1277     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1278     /* pointer, segment address pair */
1279     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1280   }
1281 
1282   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1283 
1284   if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
1285   else
1286   {
1287     Bit8u shift = MMXUB0(op2);
1288 
1289     MMXUD0(op1) >>= shift;
1290     MMXUD1(op1) >>= shift;
1291   }
1292 
1293   BX_WRITE_MMX_REG(i->dst(), op1);
1294 #endif
1295 
1296   BX_NEXT_INSTR(i);
1297 }
1298 
1299 /* 0F D3 */
PSRLQ_PqQq(bxInstruction_c * i)1300 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqQq(bxInstruction_c *i)
1301 {
1302 #if BX_CPU_LEVEL >= 5
1303   BX_CPU_THIS_PTR prepareMMX();
1304 
1305   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1306 
1307   /* op2 is a register or memory reference */
1308   if (i->modC0()) {
1309     op2 = BX_READ_MMX_REG(i->src());
1310   }
1311   else {
1312     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1313     /* pointer, segment address pair */
1314     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1315   }
1316 
1317   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1318 
1319   if(MMXUQ(op2) > 63) {
1320     MMXUQ(op1) = 0;
1321   }
1322   else {
1323     MMXUQ(op1) >>= MMXUB0(op2);
1324   }
1325 
1326   BX_WRITE_MMX_REG(i->dst(), op1);
1327 #endif
1328 
1329   BX_NEXT_INSTR(i);
1330 }
1331 
1332 /* 0F D4 */
PADDQ_PqQq(bxInstruction_c * i)1333 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDQ_PqQq(bxInstruction_c *i)
1334 {
1335 #if BX_CPU_LEVEL >= 5
1336   BX_CPU_THIS_PTR prepareMMX();
1337 
1338   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1339 
1340   /* op2 is a register or memory reference */
1341   if (i->modC0()) {
1342     op2 = BX_READ_MMX_REG(i->src());
1343   }
1344   else {
1345     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1346     /* pointer, segment address pair */
1347     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1348   }
1349 
1350   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1351 
1352   MMXUQ(op1) += MMXUQ(op2);
1353 
1354   BX_WRITE_MMX_REG(i->dst(), op1);
1355 #endif
1356 
1357   BX_NEXT_INSTR(i);
1358 }
1359 
1360 /* 0F D5 */
PMULLW_PqQq(bxInstruction_c * i)1361 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULLW_PqQq(bxInstruction_c *i)
1362 {
1363 #if BX_CPU_LEVEL >= 5
1364   BX_CPU_THIS_PTR prepareMMX();
1365 
1366   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1367 
1368   /* op2 is a register or memory reference */
1369   if (i->modC0()) {
1370     op2 = BX_READ_MMX_REG(i->src());
1371   }
1372   else {
1373     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1374     /* pointer, segment address pair */
1375     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1376   }
1377 
1378   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1379 
1380   Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2));
1381   Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2));
1382   Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2));
1383   Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2));
1384 
1385   MMXUW0(op1) = product1 & 0xffff;
1386   MMXUW1(op1) = product2 & 0xffff;
1387   MMXUW2(op1) = product3 & 0xffff;
1388   MMXUW3(op1) = product4 & 0xffff;
1389 
1390   BX_WRITE_MMX_REG(i->dst(), op1);
1391 #endif
1392 
1393   BX_NEXT_INSTR(i);
1394 }
1395 
1396 /* 0F D7 */
PMOVMSKB_GdNq(bxInstruction_c * i)1397 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVMSKB_GdNq(bxInstruction_c *i)
1398 {
1399 #if BX_CPU_LEVEL >= 5
1400   BX_CPU_THIS_PTR prepareMMX();
1401   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1402 
1403   BxPackedMmxRegister op = BX_READ_MMX_REG(i->src());
1404   Bit32u result = 0;
1405 
1406   if(MMXUB0(op) & 0x80) result |= 0x01;
1407   if(MMXUB1(op) & 0x80) result |= 0x02;
1408   if(MMXUB2(op) & 0x80) result |= 0x04;
1409   if(MMXUB3(op) & 0x80) result |= 0x08;
1410   if(MMXUB4(op) & 0x80) result |= 0x10;
1411   if(MMXUB5(op) & 0x80) result |= 0x20;
1412   if(MMXUB6(op) & 0x80) result |= 0x40;
1413   if(MMXUB7(op) & 0x80) result |= 0x80;
1414 
1415   BX_WRITE_32BIT_REGZ(i->dst(), result);
1416 #endif
1417 
1418   BX_NEXT_INSTR(i);
1419 }
1420 
1421 /* 0F D8 */
PSUBUSB_PqQq(bxInstruction_c * i)1422 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSB_PqQq(bxInstruction_c *i)
1423 {
1424 #if BX_CPU_LEVEL >= 5
1425   BX_CPU_THIS_PTR prepareMMX();
1426 
1427   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result;
1428 
1429   /* op2 is a register or memory reference */
1430   if (i->modC0()) {
1431     op2 = BX_READ_MMX_REG(i->src());
1432   }
1433   else {
1434     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1435     /* pointer, segment address pair */
1436     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1437   }
1438 
1439   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1440 
1441   MMXUQ(result) = 0;
1442 
1443   if(MMXUB0(op1) > MMXUB0(op2)) MMXUB0(result) = MMXUB0(op1) - MMXUB0(op2);
1444   if(MMXUB1(op1) > MMXUB1(op2)) MMXUB1(result) = MMXUB1(op1) - MMXUB1(op2);
1445   if(MMXUB2(op1) > MMXUB2(op2)) MMXUB2(result) = MMXUB2(op1) - MMXUB2(op2);
1446   if(MMXUB3(op1) > MMXUB3(op2)) MMXUB3(result) = MMXUB3(op1) - MMXUB3(op2);
1447   if(MMXUB4(op1) > MMXUB4(op2)) MMXUB4(result) = MMXUB4(op1) - MMXUB4(op2);
1448   if(MMXUB5(op1) > MMXUB5(op2)) MMXUB5(result) = MMXUB5(op1) - MMXUB5(op2);
1449   if(MMXUB6(op1) > MMXUB6(op2)) MMXUB6(result) = MMXUB6(op1) - MMXUB6(op2);
1450   if(MMXUB7(op1) > MMXUB7(op2)) MMXUB7(result) = MMXUB7(op1) - MMXUB7(op2);
1451 
1452   BX_WRITE_MMX_REG(i->dst(), result);
1453 #endif
1454 
1455   BX_NEXT_INSTR(i);
1456 }
1457 
1458 /* 0F D9 */
PSUBUSW_PqQq(bxInstruction_c * i)1459 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSW_PqQq(bxInstruction_c *i)
1460 {
1461 #if BX_CPU_LEVEL >= 5
1462   BX_CPU_THIS_PTR prepareMMX();
1463 
1464   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result;
1465 
1466   /* op2 is a register or memory reference */
1467   if (i->modC0()) {
1468     op2 = BX_READ_MMX_REG(i->src());
1469   }
1470   else {
1471     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1472     /* pointer, segment address pair */
1473     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1474   }
1475 
1476   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1477 
1478   MMXUQ(result) = 0;
1479 
1480   if(MMXUW0(op1) > MMXUW0(op2)) MMXUW0(result) = MMXUW0(op1) - MMXUW0(op2);
1481   if(MMXUW1(op1) > MMXUW1(op2)) MMXUW1(result) = MMXUW1(op1) - MMXUW1(op2);
1482   if(MMXUW2(op1) > MMXUW2(op2)) MMXUW2(result) = MMXUW2(op1) - MMXUW2(op2);
1483   if(MMXUW3(op1) > MMXUW3(op2)) MMXUW3(result) = MMXUW3(op1) - MMXUW3(op2);
1484 
1485   BX_WRITE_MMX_REG(i->dst(), result);
1486 #endif
1487 
1488   BX_NEXT_INSTR(i);
1489 }
1490 
1491 /* 0F DA */
PMINUB_PqQq(bxInstruction_c * i)1492 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINUB_PqQq(bxInstruction_c *i)
1493 {
1494 #if BX_CPU_LEVEL >= 5
1495   BX_CPU_THIS_PTR prepareMMX();
1496 
1497   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1498 
1499   /* op2 is a register or memory reference */
1500   if (i->modC0()) {
1501     op2 = BX_READ_MMX_REG(i->src());
1502   }
1503   else {
1504     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1505     /* pointer, segment address pair */
1506     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1507   }
1508 
1509   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1510 
1511   if(MMXUB0(op2) < MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2);
1512   if(MMXUB1(op2) < MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2);
1513   if(MMXUB2(op2) < MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2);
1514   if(MMXUB3(op2) < MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2);
1515   if(MMXUB4(op2) < MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2);
1516   if(MMXUB5(op2) < MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2);
1517   if(MMXUB6(op2) < MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2);
1518   if(MMXUB7(op2) < MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2);
1519 
1520   BX_WRITE_MMX_REG(i->dst(), op1);
1521 #endif
1522 
1523   BX_NEXT_INSTR(i);
1524 }
1525 
1526 /* 0F DB */
PAND_PqQq(bxInstruction_c * i)1527 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAND_PqQq(bxInstruction_c *i)
1528 {
1529 #if BX_CPU_LEVEL >= 5
1530   BX_CPU_THIS_PTR prepareMMX();
1531 
1532   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1533 
1534   /* op2 is a register or memory reference */
1535   if (i->modC0()) {
1536     op2 = BX_READ_MMX_REG(i->src());
1537   }
1538   else {
1539     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1540     /* pointer, segment address pair */
1541     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1542   }
1543 
1544   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1545 
1546   MMXUQ(op1) &= MMXUQ(op2);
1547 
1548   BX_WRITE_MMX_REG(i->dst(), op1);
1549 #endif
1550 
1551   BX_NEXT_INSTR(i);
1552 }
1553 
1554 /* 0F DC */
PADDUSB_PqQq(bxInstruction_c * i)1555 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSB_PqQq(bxInstruction_c *i)
1556 {
1557 #if BX_CPU_LEVEL >= 5
1558   BX_CPU_THIS_PTR prepareMMX();
1559 
1560   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1561 
1562   /* op2 is a register or memory reference */
1563   if (i->modC0()) {
1564     op2 = BX_READ_MMX_REG(i->src());
1565   }
1566   else {
1567     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1568     /* pointer, segment address pair */
1569     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1570   }
1571 
1572   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1573 
1574   MMXUB0(op1) = SaturateWordSToByteU(Bit16s(MMXUB0(op1)) + Bit16s(MMXUB0(op2)));
1575   MMXUB1(op1) = SaturateWordSToByteU(Bit16s(MMXUB1(op1)) + Bit16s(MMXUB1(op2)));
1576   MMXUB2(op1) = SaturateWordSToByteU(Bit16s(MMXUB2(op1)) + Bit16s(MMXUB2(op2)));
1577   MMXUB3(op1) = SaturateWordSToByteU(Bit16s(MMXUB3(op1)) + Bit16s(MMXUB3(op2)));
1578 
1579   MMXUB4(op1) = SaturateWordSToByteU(Bit16s(MMXUB4(op1)) + Bit16s(MMXUB4(op2)));
1580   MMXUB5(op1) = SaturateWordSToByteU(Bit16s(MMXUB5(op1)) + Bit16s(MMXUB5(op2)));
1581   MMXUB6(op1) = SaturateWordSToByteU(Bit16s(MMXUB6(op1)) + Bit16s(MMXUB6(op2)));
1582   MMXUB7(op1) = SaturateWordSToByteU(Bit16s(MMXUB7(op1)) + Bit16s(MMXUB7(op2)));
1583 
1584   BX_WRITE_MMX_REG(i->dst(), op1);
1585 #endif
1586 
1587   BX_NEXT_INSTR(i);
1588 }
1589 
1590 /* 0F DD */
PADDUSW_PqQq(bxInstruction_c * i)1591 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSW_PqQq(bxInstruction_c *i)
1592 {
1593 #if BX_CPU_LEVEL >= 5
1594   BX_CPU_THIS_PTR prepareMMX();
1595 
1596   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1597 
1598   /* op2 is a register or memory reference */
1599   if (i->modC0()) {
1600     op2 = BX_READ_MMX_REG(i->src());
1601   }
1602   else {
1603     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1604     /* pointer, segment address pair */
1605     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1606   }
1607 
1608   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1609 
1610   MMXUW0(op1) = SaturateDwordSToWordU(Bit32s(MMXUW0(op1)) + Bit32s(MMXUW0(op2)));
1611   MMXUW1(op1) = SaturateDwordSToWordU(Bit32s(MMXUW1(op1)) + Bit32s(MMXUW1(op2)));
1612   MMXUW2(op1) = SaturateDwordSToWordU(Bit32s(MMXUW2(op1)) + Bit32s(MMXUW2(op2)));
1613   MMXUW3(op1) = SaturateDwordSToWordU(Bit32s(MMXUW3(op1)) + Bit32s(MMXUW3(op2)));
1614 
1615   BX_WRITE_MMX_REG(i->dst(), op1);
1616 #endif
1617 
1618   BX_NEXT_INSTR(i);
1619 }
1620 
1621 /* 0F DE */
PMAXUB_PqQq(bxInstruction_c * i)1622 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXUB_PqQq(bxInstruction_c *i)
1623 {
1624 #if BX_CPU_LEVEL >= 5
1625   BX_CPU_THIS_PTR prepareMMX();
1626 
1627   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1628 
1629   /* op2 is a register or memory reference */
1630   if (i->modC0()) {
1631     op2 = BX_READ_MMX_REG(i->src());
1632   }
1633   else {
1634     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1635     /* pointer, segment address pair */
1636     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1637   }
1638 
1639   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1640 
1641   if(MMXUB0(op2) > MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2);
1642   if(MMXUB1(op2) > MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2);
1643   if(MMXUB2(op2) > MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2);
1644   if(MMXUB3(op2) > MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2);
1645   if(MMXUB4(op2) > MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2);
1646   if(MMXUB5(op2) > MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2);
1647   if(MMXUB6(op2) > MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2);
1648   if(MMXUB7(op2) > MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2);
1649 
1650   BX_WRITE_MMX_REG(i->dst(), op1);
1651 #endif
1652 
1653   BX_NEXT_INSTR(i);
1654 }
1655 
1656 /* 0F DF */
PANDN_PqQq(bxInstruction_c * i)1657 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PANDN_PqQq(bxInstruction_c *i)
1658 {
1659 #if BX_CPU_LEVEL >= 5
1660   BX_CPU_THIS_PTR prepareMMX();
1661 
1662   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1663 
1664   /* op2 is a register or memory reference */
1665   if (i->modC0()) {
1666     op2 = BX_READ_MMX_REG(i->src());
1667   }
1668   else {
1669     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1670     /* pointer, segment address pair */
1671     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1672   }
1673 
1674   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1675 
1676   MMXUQ(op1) = ~(MMXUQ(op1)) & MMXUQ(op2);
1677 
1678   BX_WRITE_MMX_REG(i->dst(), op1);
1679 #endif
1680 
1681   BX_NEXT_INSTR(i);
1682 }
1683 
1684 /* 0F E0 */
PAVGB_PqQq(bxInstruction_c * i)1685 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGB_PqQq(bxInstruction_c *i)
1686 {
1687 #if BX_CPU_LEVEL >= 5
1688   BX_CPU_THIS_PTR prepareMMX();
1689 
1690   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1691 
1692   /* op2 is a register or memory reference */
1693   if (i->modC0()) {
1694     op2 = BX_READ_MMX_REG(i->src());
1695   }
1696   else {
1697     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1698     /* pointer, segment address pair */
1699     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1700   }
1701 
1702   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1703 
1704   MMXUB0(op1) = (MMXUB0(op1) + MMXUB0(op2) + 1) >> 1;
1705   MMXUB1(op1) = (MMXUB1(op1) + MMXUB1(op2) + 1) >> 1;
1706   MMXUB2(op1) = (MMXUB2(op1) + MMXUB2(op2) + 1) >> 1;
1707   MMXUB3(op1) = (MMXUB3(op1) + MMXUB3(op2) + 1) >> 1;
1708   MMXUB4(op1) = (MMXUB4(op1) + MMXUB4(op2) + 1) >> 1;
1709   MMXUB5(op1) = (MMXUB5(op1) + MMXUB5(op2) + 1) >> 1;
1710   MMXUB6(op1) = (MMXUB6(op1) + MMXUB6(op2) + 1) >> 1;
1711   MMXUB7(op1) = (MMXUB7(op1) + MMXUB7(op2) + 1) >> 1;
1712 
1713   BX_WRITE_MMX_REG(i->dst(), op1);
1714 #endif
1715 
1716   BX_NEXT_INSTR(i);
1717 }
1718 
1719 /* 0F E1 */
PSRAW_PqQq(bxInstruction_c * i)1720 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqQq(bxInstruction_c *i)
1721 {
1722 #if BX_CPU_LEVEL >= 5
1723   BX_CPU_THIS_PTR prepareMMX();
1724 
1725   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1726 
1727   /* op2 is a register or memory reference */
1728   if (i->modC0()) {
1729     op2 = BX_READ_MMX_REG(i->src());
1730   }
1731   else {
1732     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1733     /* pointer, segment address pair */
1734     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1735   }
1736 
1737   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1738 
1739   if(MMXUQ(op2)) {
1740     if(MMXUQ(op2) > 15) {
1741       MMXUW0(op1) = (MMXSW0(op1) < 0) ? 0xffff : 0;
1742       MMXUW1(op1) = (MMXSW1(op1) < 0) ? 0xffff : 0;
1743       MMXUW2(op1) = (MMXSW2(op1) < 0) ? 0xffff : 0;
1744       MMXUW3(op1) = (MMXSW3(op1) < 0) ? 0xffff : 0;
1745     }
1746     else {
1747       Bit8u shift = MMXUB0(op2);
1748 
1749       MMXUW0(op1) = (Bit16u)(MMXSW0(op1) >> shift);
1750       MMXUW1(op1) = (Bit16u)(MMXSW1(op1) >> shift);
1751       MMXUW2(op1) = (Bit16u)(MMXSW2(op1) >> shift);
1752       MMXUW3(op1) = (Bit16u)(MMXSW3(op1) >> shift);
1753     }
1754   }
1755 
1756   BX_WRITE_MMX_REG(i->dst(), op1);
1757 #endif
1758 
1759   BX_NEXT_INSTR(i);
1760 }
1761 
1762 /* 0F E2 */
PSRAD_PqQq(bxInstruction_c * i)1763 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqQq(bxInstruction_c *i)
1764 {
1765 #if BX_CPU_LEVEL >= 5
1766   BX_CPU_THIS_PTR prepareMMX();
1767 
1768   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1769 
1770   /* op2 is a register or memory reference */
1771   if (i->modC0()) {
1772     op2 = BX_READ_MMX_REG(i->src());
1773   }
1774   else {
1775     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1776     /* pointer, segment address pair */
1777     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1778   }
1779 
1780   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1781 
1782   if(MMXUQ(op2)) {
1783     if(MMXUQ(op2) > 31) {
1784       MMXUD0(op1) = (MMXSD0(op1) < 0) ? 0xffffffff : 0;
1785       MMXUD1(op1) = (MMXSD1(op1) < 0) ? 0xffffffff : 0;
1786     }
1787     else {
1788       Bit8u shift = MMXUB0(op2);
1789 
1790       MMXUD0(op1) = (Bit32u)(MMXSD0(op1) >> shift);
1791       MMXUD1(op1) = (Bit32u)(MMXSD1(op1) >> shift);
1792     }
1793   }
1794 
1795   BX_WRITE_MMX_REG(i->dst(), op1);
1796 #endif
1797 
1798   BX_NEXT_INSTR(i);
1799 }
1800 
1801 /* 0F E3 */
PAVGW_PqQq(bxInstruction_c * i)1802 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGW_PqQq(bxInstruction_c *i)
1803 {
1804 #if BX_CPU_LEVEL >= 5
1805   BX_CPU_THIS_PTR prepareMMX();
1806 
1807   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1808 
1809   /* op2 is a register or memory reference */
1810   if (i->modC0()) {
1811     op2 = BX_READ_MMX_REG(i->src());
1812   }
1813   else {
1814     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1815     /* pointer, segment address pair */
1816     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1817   }
1818 
1819   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1820 
1821   MMXUW0(op1) = (MMXUW0(op1) + MMXUW0(op2) + 1) >> 1;
1822   MMXUW1(op1) = (MMXUW1(op1) + MMXUW1(op2) + 1) >> 1;
1823   MMXUW2(op1) = (MMXUW2(op1) + MMXUW2(op2) + 1) >> 1;
1824   MMXUW3(op1) = (MMXUW3(op1) + MMXUW3(op2) + 1) >> 1;
1825 
1826   BX_WRITE_MMX_REG(i->dst(), op1);
1827 #endif
1828 
1829   BX_NEXT_INSTR(i);
1830 }
1831 
1832 /* 0F E4 */
PMULHUW_PqQq(bxInstruction_c * i)1833 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHUW_PqQq(bxInstruction_c *i)
1834 {
1835 #if BX_CPU_LEVEL >= 5
1836   BX_CPU_THIS_PTR prepareMMX();
1837 
1838   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1839 
1840   /* op2 is a register or memory reference */
1841   if (i->modC0()) {
1842     op2 = BX_READ_MMX_REG(i->src());
1843   }
1844   else {
1845     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1846     /* pointer, segment address pair */
1847     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1848   }
1849 
1850   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1851 
1852   Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2));
1853   Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2));
1854   Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2));
1855   Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2));
1856 
1857   MMXUW0(op1) = (Bit16u)(product1 >> 16);
1858   MMXUW1(op1) = (Bit16u)(product2 >> 16);
1859   MMXUW2(op1) = (Bit16u)(product3 >> 16);
1860   MMXUW3(op1) = (Bit16u)(product4 >> 16);
1861 
1862   BX_WRITE_MMX_REG(i->dst(), op1);
1863 #endif
1864 
1865   BX_NEXT_INSTR(i);
1866 }
1867 
1868 /* 0F E5 */
PMULHW_PqQq(bxInstruction_c * i)1869 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHW_PqQq(bxInstruction_c *i)
1870 {
1871 #if BX_CPU_LEVEL >= 5
1872   BX_CPU_THIS_PTR prepareMMX();
1873 
1874   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1875 
1876   /* op2 is a register or memory reference */
1877   if (i->modC0()) {
1878     op2 = BX_READ_MMX_REG(i->src());
1879   }
1880   else {
1881     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1882     /* pointer, segment address pair */
1883     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1884   }
1885 
1886   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1887 
1888   Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2));
1889   Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2));
1890   Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2));
1891   Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2));
1892 
1893   MMXUW0(op1) = Bit16u(product1 >> 16);
1894   MMXUW1(op1) = Bit16u(product2 >> 16);
1895   MMXUW2(op1) = Bit16u(product3 >> 16);
1896   MMXUW3(op1) = Bit16u(product4 >> 16);
1897 
1898   BX_WRITE_MMX_REG(i->dst(), op1);
1899 #endif
1900 
1901   BX_NEXT_INSTR(i);
1902 }
1903 
1904 /* 0F E8 */
PSUBSB_PqQq(bxInstruction_c * i)1905 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSB_PqQq(bxInstruction_c *i)
1906 {
1907 #if BX_CPU_LEVEL >= 5
1908   BX_CPU_THIS_PTR prepareMMX();
1909 
1910   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1911 
1912   /* op2 is a register or memory reference */
1913   if (i->modC0()) {
1914     op2 = BX_READ_MMX_REG(i->src());
1915   }
1916   else {
1917     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1918     /* pointer, segment address pair */
1919     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1920   }
1921 
1922   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1923 
1924   MMXSB0(op1) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) - Bit16s(MMXSB0(op2)));
1925   MMXSB1(op1) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) - Bit16s(MMXSB1(op2)));
1926   MMXSB2(op1) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) - Bit16s(MMXSB2(op2)));
1927   MMXSB3(op1) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) - Bit16s(MMXSB3(op2)));
1928   MMXSB4(op1) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) - Bit16s(MMXSB4(op2)));
1929   MMXSB5(op1) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) - Bit16s(MMXSB5(op2)));
1930   MMXSB6(op1) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) - Bit16s(MMXSB6(op2)));
1931   MMXSB7(op1) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) - Bit16s(MMXSB7(op2)));
1932 
1933   BX_WRITE_MMX_REG(i->dst(), op1);
1934 #endif
1935 
1936   BX_NEXT_INSTR(i);
1937 }
1938 
1939 /* 0F E9 */
PSUBSW_PqQq(bxInstruction_c * i)1940 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSW_PqQq(bxInstruction_c *i)
1941 {
1942 #if BX_CPU_LEVEL >= 5
1943   BX_CPU_THIS_PTR prepareMMX();
1944 
1945   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1946 
1947   /* op2 is a register or memory reference */
1948   if (i->modC0()) {
1949     op2 = BX_READ_MMX_REG(i->src());
1950   }
1951   else {
1952     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1953     /* pointer, segment address pair */
1954     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1955   }
1956 
1957   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1958 
1959   MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW0(op2)));
1960   MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) - Bit32s(MMXSW1(op2)));
1961   MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW2(op2)));
1962   MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) - Bit32s(MMXSW3(op2)));
1963 
1964   BX_WRITE_MMX_REG(i->dst(), op1);
1965 #endif
1966 
1967   BX_NEXT_INSTR(i);
1968 }
1969 
1970 /* 0F EA */
PMINSW_PqQq(bxInstruction_c * i)1971 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINSW_PqQq(bxInstruction_c *i)
1972 {
1973 #if BX_CPU_LEVEL >= 5
1974   BX_CPU_THIS_PTR prepareMMX();
1975 
1976   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
1977 
1978   /* op2 is a register or memory reference */
1979   if (i->modC0()) {
1980     op2 = BX_READ_MMX_REG(i->src());
1981   }
1982   else {
1983     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
1984     /* pointer, segment address pair */
1985     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1986   }
1987 
1988   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1989 
1990   if(MMXSW0(op2) < MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2);
1991   if(MMXSW1(op2) < MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2);
1992   if(MMXSW2(op2) < MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2);
1993   if(MMXSW3(op2) < MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2);
1994 
1995   BX_WRITE_MMX_REG(i->dst(), op1);
1996 #endif
1997 
1998   BX_NEXT_INSTR(i);
1999 }
2000 
2001 /* 0F EB */
POR_PqQq(bxInstruction_c * i)2002 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POR_PqQq(bxInstruction_c *i)
2003 {
2004 #if BX_CPU_LEVEL >= 5
2005   BX_CPU_THIS_PTR prepareMMX();
2006 
2007   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2008 
2009   /* op2 is a register or memory reference */
2010   if (i->modC0()) {
2011     op2 = BX_READ_MMX_REG(i->src());
2012   }
2013   else {
2014     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2015     /* pointer, segment address pair */
2016     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2017   }
2018 
2019   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2020 
2021   MMXUQ(op1) |= MMXUQ(op2);
2022 
2023   BX_WRITE_MMX_REG(i->dst(), op1);
2024 #endif
2025 
2026   BX_NEXT_INSTR(i);
2027 }
2028 
2029 /* 0F EC */
PADDSB_PqQq(bxInstruction_c * i)2030 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSB_PqQq(bxInstruction_c *i)
2031 {
2032 #if BX_CPU_LEVEL >= 5
2033   BX_CPU_THIS_PTR prepareMMX();
2034 
2035   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2036 
2037   /* op2 is a register or memory reference */
2038   if (i->modC0()) {
2039     op2 = BX_READ_MMX_REG(i->src());
2040   }
2041   else {
2042     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2043     /* pointer, segment address pair */
2044     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2045   }
2046 
2047   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2048 
2049   MMXSB0(op1) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) + Bit16s(MMXSB0(op2)));
2050   MMXSB1(op1) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) + Bit16s(MMXSB1(op2)));
2051   MMXSB2(op1) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) + Bit16s(MMXSB2(op2)));
2052   MMXSB3(op1) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) + Bit16s(MMXSB3(op2)));
2053   MMXSB4(op1) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) + Bit16s(MMXSB4(op2)));
2054   MMXSB5(op1) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) + Bit16s(MMXSB5(op2)));
2055   MMXSB6(op1) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) + Bit16s(MMXSB6(op2)));
2056   MMXSB7(op1) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) + Bit16s(MMXSB7(op2)));
2057 
2058   BX_WRITE_MMX_REG(i->dst(), op1);
2059 #endif
2060 
2061   BX_NEXT_INSTR(i);
2062 }
2063 
2064 /* 0F ED */
PADDSW_PqQq(bxInstruction_c * i)2065 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSW_PqQq(bxInstruction_c *i)
2066 {
2067 #if BX_CPU_LEVEL >= 5
2068   BX_CPU_THIS_PTR prepareMMX();
2069 
2070   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2071 
2072   /* op2 is a register or memory reference */
2073   if (i->modC0()) {
2074     op2 = BX_READ_MMX_REG(i->src());
2075   }
2076   else {
2077     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2078     /* pointer, segment address pair */
2079     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2080   }
2081 
2082   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2083 
2084   MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW0(op2)));
2085   MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) + Bit32s(MMXSW1(op2)));
2086   MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW2(op2)));
2087   MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) + Bit32s(MMXSW3(op2)));
2088 
2089   BX_WRITE_MMX_REG(i->dst(), op1);
2090 #endif
2091 
2092   BX_NEXT_INSTR(i);
2093 }
2094 
2095 /* 0F EE */
PMAXSW_PqQq(bxInstruction_c * i)2096 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXSW_PqQq(bxInstruction_c *i)
2097 {
2098 #if BX_CPU_LEVEL >= 5
2099   BX_CPU_THIS_PTR prepareMMX();
2100 
2101   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2102 
2103   /* op2 is a register or memory reference */
2104   if (i->modC0()) {
2105     op2 = BX_READ_MMX_REG(i->src());
2106   }
2107   else {
2108     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2109     /* pointer, segment address pair */
2110     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2111   }
2112 
2113   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2114 
2115   if(MMXSW0(op2) > MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2);
2116   if(MMXSW1(op2) > MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2);
2117   if(MMXSW2(op2) > MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2);
2118   if(MMXSW3(op2) > MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2);
2119 
2120   BX_WRITE_MMX_REG(i->dst(), op1);
2121 #endif
2122 
2123   BX_NEXT_INSTR(i);
2124 }
2125 
2126 /* 0F EF */
PXOR_PqQq(bxInstruction_c * i)2127 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PXOR_PqQq(bxInstruction_c *i)
2128 {
2129 #if BX_CPU_LEVEL >= 5
2130   BX_CPU_THIS_PTR prepareMMX();
2131 
2132   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2133 
2134   /* op2 is a register or memory reference */
2135   if (i->modC0()) {
2136     op2 = BX_READ_MMX_REG(i->src());
2137   }
2138   else {
2139     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2140     /* pointer, segment address pair */
2141     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2142   }
2143 
2144   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2145 
2146   MMXUQ(op1) ^= MMXUQ(op2);
2147 
2148   BX_WRITE_MMX_REG(i->dst(), op1);
2149 #endif
2150 
2151   BX_NEXT_INSTR(i);
2152 }
2153 
2154 /* 0F F1 */
PSLLW_PqQq(bxInstruction_c * i)2155 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqQq(bxInstruction_c *i)
2156 {
2157 #if BX_CPU_LEVEL >= 5
2158   BX_CPU_THIS_PTR prepareMMX();
2159 
2160   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2161 
2162   /* op2 is a register or memory reference */
2163   if (i->modC0()) {
2164     op2 = BX_READ_MMX_REG(i->src());
2165   }
2166   else {
2167     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2168     /* pointer, segment address pair */
2169     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2170   }
2171 
2172   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2173 
2174   if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
2175   else
2176   {
2177     Bit8u shift = MMXUB0(op2);
2178 
2179     MMXUW0(op1) <<= shift;
2180     MMXUW1(op1) <<= shift;
2181     MMXUW2(op1) <<= shift;
2182     MMXUW3(op1) <<= shift;
2183   }
2184 
2185   BX_WRITE_MMX_REG(i->dst(), op1);
2186 #endif
2187 
2188   BX_NEXT_INSTR(i);
2189 }
2190 
2191 /* 0F F2 */
PSLLD_PqQq(bxInstruction_c * i)2192 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqQq(bxInstruction_c *i)
2193 {
2194 #if BX_CPU_LEVEL >= 5
2195   BX_CPU_THIS_PTR prepareMMX();
2196 
2197   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2198 
2199   /* op2 is a register or memory reference */
2200   if (i->modC0()) {
2201     op2 = BX_READ_MMX_REG(i->src());
2202   }
2203   else {
2204     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2205     /* pointer, segment address pair */
2206     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2207   }
2208 
2209   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2210 
2211   if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
2212   else
2213   {
2214     Bit8u shift = MMXUB0(op2);
2215 
2216     MMXUD0(op1) <<= shift;
2217     MMXUD1(op1) <<= shift;
2218   }
2219 
2220   BX_WRITE_MMX_REG(i->dst(), op1);
2221 #endif
2222 
2223   BX_NEXT_INSTR(i);
2224 }
2225 
2226 /* 0F F3 */
PSLLQ_PqQq(bxInstruction_c * i)2227 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqQq(bxInstruction_c *i)
2228 {
2229 #if BX_CPU_LEVEL >= 5
2230   BX_CPU_THIS_PTR prepareMMX();
2231 
2232   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2233 
2234   /* op2 is a register or memory reference */
2235   if (i->modC0()) {
2236     op2 = BX_READ_MMX_REG(i->src());
2237   }
2238   else {
2239     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2240     /* pointer, segment address pair */
2241     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2242   }
2243 
2244   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2245 
2246   if(MMXUQ(op2) > 63) {
2247     MMXUQ(op1) = 0;
2248   }
2249   else {
2250     MMXUQ(op1) <<= MMXUB0(op2);
2251   }
2252 
2253   BX_WRITE_MMX_REG(i->dst(), op1);
2254 #endif
2255 
2256   BX_NEXT_INSTR(i);
2257 }
2258 
2259 /* 0F F4 */
PMULUDQ_PqQq(bxInstruction_c * i)2260 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULUDQ_PqQq(bxInstruction_c *i)
2261 {
2262 #if BX_CPU_LEVEL >= 5
2263   BX_CPU_THIS_PTR prepareMMX();
2264 
2265   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2266 
2267   /* op2 is a register or memory reference */
2268   if (i->modC0()) {
2269     op2 = BX_READ_MMX_REG(i->src());
2270   }
2271   else {
2272     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2273     /* pointer, segment address pair */
2274     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2275   }
2276 
2277   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2278 
2279   MMXUQ(op1) = Bit64u(MMXUD0(op1)) * Bit64u(MMXUD0(op2));
2280 
2281   BX_WRITE_MMX_REG(i->dst(), op1);
2282 #endif
2283 
2284   BX_NEXT_INSTR(i);
2285 }
2286 
2287 /* 0F F5 */
PMADDWD_PqQq(bxInstruction_c * i)2288 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDWD_PqQq(bxInstruction_c *i)
2289 {
2290 #if BX_CPU_LEVEL >= 5
2291   BX_CPU_THIS_PTR prepareMMX();
2292 
2293   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2294 
2295   /* op2 is a register or memory reference */
2296   if (i->modC0()) {
2297     op2 = BX_READ_MMX_REG(i->src());
2298   }
2299   else {
2300     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2301     /* pointer, segment address pair */
2302     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2303   }
2304 
2305   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2306 
2307   if(MMXUD0(op1) == 0x80008000 && MMXUD0(op2) == 0x80008000) {
2308     MMXUD0(op1) = 0x80000000;
2309   }
2310   else {
2311     MMXUD0(op1) = Bit32s(MMXSW0(op1))*Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op1))*Bit32s(MMXSW1(op2));
2312   }
2313 
2314   if(MMXUD1(op1) == 0x80008000 && MMXUD1(op2) == 0x80008000) {
2315     MMXUD1(op1) = 0x80000000;
2316   }
2317   else {
2318     MMXUD1(op1) = Bit32s(MMXSW2(op1))*Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op1))*Bit32s(MMXSW3(op2));
2319   }
2320 
2321   BX_WRITE_MMX_REG(i->dst(), op1);
2322 #endif
2323 
2324   BX_NEXT_INSTR(i);
2325 }
2326 
2327 /* 0F F6 */
PSADBW_PqQq(bxInstruction_c * i)2328 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSADBW_PqQq(bxInstruction_c *i)
2329 {
2330 #if BX_CPU_LEVEL >= 5
2331   BX_CPU_THIS_PTR prepareMMX();
2332 
2333   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2334   Bit16u temp = 0;
2335 
2336   /* op2 is a register or memory reference */
2337   if (i->modC0()) {
2338     op2 = BX_READ_MMX_REG(i->src());
2339   }
2340   else {
2341     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2342     /* pointer, segment address pair */
2343     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2344   }
2345 
2346   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2347 
2348   temp += abs(MMXUB0(op1) - MMXUB0(op2));
2349   temp += abs(MMXUB1(op1) - MMXUB1(op2));
2350   temp += abs(MMXUB2(op1) - MMXUB2(op2));
2351   temp += abs(MMXUB3(op1) - MMXUB3(op2));
2352   temp += abs(MMXUB4(op1) - MMXUB4(op2));
2353   temp += abs(MMXUB5(op1) - MMXUB5(op2));
2354   temp += abs(MMXUB6(op1) - MMXUB6(op2));
2355   temp += abs(MMXUB7(op1) - MMXUB7(op2));
2356 
2357   MMXUQ(op1) = (Bit64u) temp;
2358 
2359   BX_WRITE_MMX_REG(i->dst(), op1);
2360 #endif
2361 
2362   BX_NEXT_INSTR(i);
2363 }
2364 
2365 /* 0F F7 */
MASKMOVQ_PqNq(bxInstruction_c * i)2366 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MASKMOVQ_PqNq(bxInstruction_c *i)
2367 {
2368 #if BX_CPU_LEVEL >= 5
2369   BX_CPU_THIS_PTR prepareMMX();
2370   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2371 
2372   bx_address rdi = RDI & i->asize_mask();
2373   BxPackedMmxRegister op = BX_READ_MMX_REG(i->src1()), tmp,
2374     mask = BX_READ_MMX_REG(i->src2());
2375 
2376   /* do read-modify-write for efficiency */
2377   MMXUQ(tmp) = read_RMW_virtual_qword(i->seg(), rdi);
2378 
2379   if(!MMXUQ(mask)) {
2380     BX_NEXT_INSTR(i);
2381   }
2382 
2383   if(MMXUB0(mask) & 0x80) MMXUB0(tmp) = MMXUB0(op);
2384   if(MMXUB1(mask) & 0x80) MMXUB1(tmp) = MMXUB1(op);
2385   if(MMXUB2(mask) & 0x80) MMXUB2(tmp) = MMXUB2(op);
2386   if(MMXUB3(mask) & 0x80) MMXUB3(tmp) = MMXUB3(op);
2387   if(MMXUB4(mask) & 0x80) MMXUB4(tmp) = MMXUB4(op);
2388   if(MMXUB5(mask) & 0x80) MMXUB5(tmp) = MMXUB5(op);
2389   if(MMXUB6(mask) & 0x80) MMXUB6(tmp) = MMXUB6(op);
2390   if(MMXUB7(mask) & 0x80) MMXUB7(tmp) = MMXUB7(op);
2391 
2392   write_RMW_linear_qword(MMXUQ(tmp));
2393 #endif
2394 
2395   BX_NEXT_INSTR(i);
2396 }
2397 
2398 /* 0F F8 */
PSUBB_PqQq(bxInstruction_c * i)2399 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBB_PqQq(bxInstruction_c *i)
2400 {
2401 #if BX_CPU_LEVEL >= 5
2402   BX_CPU_THIS_PTR prepareMMX();
2403 
2404   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2405 
2406   /* op2 is a register or memory reference */
2407   if (i->modC0()) {
2408     op2 = BX_READ_MMX_REG(i->src());
2409   }
2410   else {
2411     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2412     /* pointer, segment address pair */
2413     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2414   }
2415 
2416   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2417 
2418   MMXUB0(op1) -= MMXUB0(op2);
2419   MMXUB1(op1) -= MMXUB1(op2);
2420   MMXUB2(op1) -= MMXUB2(op2);
2421   MMXUB3(op1) -= MMXUB3(op2);
2422   MMXUB4(op1) -= MMXUB4(op2);
2423   MMXUB5(op1) -= MMXUB5(op2);
2424   MMXUB6(op1) -= MMXUB6(op2);
2425   MMXUB7(op1) -= MMXUB7(op2);
2426 
2427   BX_WRITE_MMX_REG(i->dst(), op1);
2428 #endif
2429 
2430   BX_NEXT_INSTR(i);
2431 }
2432 
2433 /* 0F F9 */
PSUBW_PqQq(bxInstruction_c * i)2434 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBW_PqQq(bxInstruction_c *i)
2435 {
2436 #if BX_CPU_LEVEL >= 5
2437   BX_CPU_THIS_PTR prepareMMX();
2438 
2439   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2440 
2441   /* op2 is a register or memory reference */
2442   if (i->modC0()) {
2443     op2 = BX_READ_MMX_REG(i->src());
2444   }
2445   else {
2446     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2447     /* pointer, segment address pair */
2448     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2449   }
2450 
2451   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2452 
2453   MMXUW0(op1) -= MMXUW0(op2);
2454   MMXUW1(op1) -= MMXUW1(op2);
2455   MMXUW2(op1) -= MMXUW2(op2);
2456   MMXUW3(op1) -= MMXUW3(op2);
2457 
2458   BX_WRITE_MMX_REG(i->dst(), op1);
2459 #endif
2460 
2461   BX_NEXT_INSTR(i);
2462 }
2463 
2464 /* 0F FA */
PSUBD_PqQq(bxInstruction_c * i)2465 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBD_PqQq(bxInstruction_c *i)
2466 {
2467 #if BX_CPU_LEVEL >= 5
2468   BX_CPU_THIS_PTR prepareMMX();
2469 
2470   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2471 
2472   /* op2 is a register or memory reference */
2473   if (i->modC0()) {
2474     op2 = BX_READ_MMX_REG(i->src());
2475   }
2476   else {
2477     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2478     /* pointer, segment address pair */
2479     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2480   }
2481 
2482   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2483 
2484   MMXUD0(op1) -= MMXUD0(op2);
2485   MMXUD1(op1) -= MMXUD1(op2);
2486 
2487   BX_WRITE_MMX_REG(i->dst(), op1);
2488 #endif
2489 
2490   BX_NEXT_INSTR(i);
2491 }
2492 
2493 /* 0F FB */
PSUBQ_PqQq(bxInstruction_c * i)2494 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBQ_PqQq(bxInstruction_c *i)
2495 {
2496 #if BX_CPU_LEVEL >= 5
2497   BX_CPU_THIS_PTR prepareMMX();
2498 
2499   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2500 
2501   /* op2 is a register or memory reference */
2502   if (i->modC0()) {
2503     op2 = BX_READ_MMX_REG(i->src());
2504   }
2505   else {
2506     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2507     /* pointer, segment address pair */
2508     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2509   }
2510 
2511   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2512 
2513   MMXUQ(op1) -= MMXUQ(op2);
2514 
2515   BX_WRITE_MMX_REG(i->dst(), op1);
2516 #endif
2517 
2518   BX_NEXT_INSTR(i);
2519 }
2520 
2521 /* 0F FC */
PADDB_PqQq(bxInstruction_c * i)2522 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDB_PqQq(bxInstruction_c *i)
2523 {
2524 #if BX_CPU_LEVEL >= 5
2525   BX_CPU_THIS_PTR prepareMMX();
2526 
2527   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2528 
2529   /* op2 is a register or memory reference */
2530   if (i->modC0()) {
2531     op2 = BX_READ_MMX_REG(i->src());
2532   }
2533   else {
2534     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2535     /* pointer, segment address pair */
2536     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2537   }
2538 
2539   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2540 
2541   MMXUB0(op1) += MMXUB0(op2);
2542   MMXUB1(op1) += MMXUB1(op2);
2543   MMXUB2(op1) += MMXUB2(op2);
2544   MMXUB3(op1) += MMXUB3(op2);
2545   MMXUB4(op1) += MMXUB4(op2);
2546   MMXUB5(op1) += MMXUB5(op2);
2547   MMXUB6(op1) += MMXUB6(op2);
2548   MMXUB7(op1) += MMXUB7(op2);
2549 
2550   BX_WRITE_MMX_REG(i->dst(), op1);
2551 #endif
2552 
2553   BX_NEXT_INSTR(i);
2554 }
2555 
2556 /* 0F FD */
PADDW_PqQq(bxInstruction_c * i)2557 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDW_PqQq(bxInstruction_c *i)
2558 {
2559 #if BX_CPU_LEVEL >= 5
2560   BX_CPU_THIS_PTR prepareMMX();
2561 
2562   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2563 
2564   /* op2 is a register or memory reference */
2565   if (i->modC0()) {
2566     op2 = BX_READ_MMX_REG(i->src());
2567   }
2568   else {
2569     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2570     /* pointer, segment address pair */
2571     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2572   }
2573 
2574   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2575 
2576   MMXUW0(op1) += MMXUW0(op2);
2577   MMXUW1(op1) += MMXUW1(op2);
2578   MMXUW2(op1) += MMXUW2(op2);
2579   MMXUW3(op1) += MMXUW3(op2);
2580 
2581   BX_WRITE_MMX_REG(i->dst(), op1);
2582 #endif
2583 
2584   BX_NEXT_INSTR(i);
2585 }
2586 
2587 /* 0F FE */
PADDD_PqQq(bxInstruction_c * i)2588 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDD_PqQq(bxInstruction_c *i)
2589 {
2590 #if BX_CPU_LEVEL >= 5
2591   BX_CPU_THIS_PTR prepareMMX();
2592 
2593   BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2;
2594 
2595   /* op2 is a register or memory reference */
2596   if (i->modC0()) {
2597     op2 = BX_READ_MMX_REG(i->src());
2598   }
2599   else {
2600     bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
2601     /* pointer, segment address pair */
2602     MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2603   }
2604 
2605   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2606 
2607   MMXUD0(op1) += MMXUD0(op2);
2608   MMXUD1(op1) += MMXUD1(op2);
2609 
2610   BX_WRITE_MMX_REG(i->dst(), op1);
2611 #endif
2612 
2613   BX_NEXT_INSTR(i);
2614 }
2615 
2616 /* 0F 71 GrpA 010 */
PSRLW_NqIb(bxInstruction_c * i)2617 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_NqIb(bxInstruction_c *i)
2618 {
2619 #if BX_CPU_LEVEL >= 5
2620   BX_CPU_THIS_PTR prepareMMX();
2621   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2622 
2623   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2624   Bit8u shift = i->Ib();
2625 
2626   if(shift > 15) MMXUQ(op) = 0;
2627   else
2628   {
2629     MMXUW0(op) >>= shift;
2630     MMXUW1(op) >>= shift;
2631     MMXUW2(op) >>= shift;
2632     MMXUW3(op) >>= shift;
2633   }
2634 
2635   BX_WRITE_MMX_REG(i->dst(), op);
2636 #endif
2637 
2638   BX_NEXT_INSTR(i);
2639 }
2640 
2641 /* 0F 71 GrpA 100 */
PSRAW_NqIb(bxInstruction_c * i)2642 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_NqIb(bxInstruction_c *i)
2643 {
2644 #if BX_CPU_LEVEL >= 5
2645   BX_CPU_THIS_PTR prepareMMX();
2646   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2647 
2648   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2649   Bit8u shift = i->Ib();
2650 
2651   if(shift == 0) {
2652     BX_NEXT_INSTR(i);
2653   }
2654 
2655   if(shift > 15) {
2656     MMXUW0(op) = (MMXSW0(op) < 0) ? 0xffff : 0;
2657     MMXUW1(op) = (MMXSW1(op) < 0) ? 0xffff : 0;
2658     MMXUW2(op) = (MMXSW2(op) < 0) ? 0xffff : 0;
2659     MMXUW3(op) = (MMXSW3(op) < 0) ? 0xffff : 0;
2660   }
2661   else {
2662     MMXUW0(op) = (Bit16u)(MMXSW0(op) >> shift);
2663     MMXUW1(op) = (Bit16u)(MMXSW1(op) >> shift);
2664     MMXUW2(op) = (Bit16u)(MMXSW2(op) >> shift);
2665     MMXUW3(op) = (Bit16u)(MMXSW3(op) >> shift);
2666   }
2667 
2668   BX_WRITE_MMX_REG(i->dst(), op);
2669 #endif
2670 
2671   BX_NEXT_INSTR(i);
2672 }
2673 
2674 /* 0F 71 GrpA 110 */
PSLLW_NqIb(bxInstruction_c * i)2675 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_NqIb(bxInstruction_c *i)
2676 {
2677 #if BX_CPU_LEVEL >= 5
2678   BX_CPU_THIS_PTR prepareMMX();
2679   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2680 
2681   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2682   Bit8u shift = i->Ib();
2683 
2684   if(shift > 15) MMXUQ(op) = 0;
2685   else
2686   {
2687     MMXUW0(op) <<= shift;
2688     MMXUW1(op) <<= shift;
2689     MMXUW2(op) <<= shift;
2690     MMXUW3(op) <<= shift;
2691   }
2692 
2693   BX_WRITE_MMX_REG(i->dst(), op);
2694 #endif
2695 
2696   BX_NEXT_INSTR(i);
2697 }
2698 
2699 /* 0F 72 GrpA 010 */
PSRLD_NqIb(bxInstruction_c * i)2700 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_NqIb(bxInstruction_c *i)
2701 {
2702 #if BX_CPU_LEVEL >= 5
2703   BX_CPU_THIS_PTR prepareMMX();
2704   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2705 
2706   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2707   Bit8u shift = i->Ib();
2708 
2709   if(shift > 31) MMXUQ(op) = 0;
2710   else
2711   {
2712     MMXUD0(op) >>= shift;
2713     MMXUD1(op) >>= shift;
2714   }
2715 
2716   BX_WRITE_MMX_REG(i->dst(), op);
2717 #endif
2718 
2719   BX_NEXT_INSTR(i);
2720 }
2721 
2722 /* 0F 72 GrpA 100 */
PSRAD_NqIb(bxInstruction_c * i)2723 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_NqIb(bxInstruction_c *i)
2724 {
2725 #if BX_CPU_LEVEL >= 5
2726   BX_CPU_THIS_PTR prepareMMX();
2727   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2728 
2729   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2730   Bit8u shift = i->Ib();
2731 
2732   if(shift == 0) {
2733     BX_NEXT_INSTR(i);
2734   }
2735 
2736   if(shift > 31) {
2737     MMXUD0(op) = (MMXSD0(op) < 0) ? 0xffffffff : 0;
2738     MMXUD1(op) = (MMXSD1(op) < 0) ? 0xffffffff : 0;
2739   }
2740   else {
2741     MMXUD0(op) = (Bit32u)(MMXSD0(op) >> shift);
2742     MMXUD1(op) = (Bit32u)(MMXSD1(op) >> shift);
2743   }
2744 
2745   BX_WRITE_MMX_REG(i->dst(), op);
2746 #endif
2747 
2748   BX_NEXT_INSTR(i);
2749 }
2750 
2751 /* 0F 72 GrpA 110 */
PSLLD_NqIb(bxInstruction_c * i)2752 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_NqIb(bxInstruction_c *i)
2753 {
2754 #if BX_CPU_LEVEL >= 5
2755   BX_CPU_THIS_PTR prepareMMX();
2756   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2757 
2758   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2759   Bit8u shift = i->Ib();
2760 
2761   if(shift > 31) MMXUQ(op) = 0;
2762   else
2763   {
2764     MMXUD0(op) <<= shift;
2765     MMXUD1(op) <<= shift;
2766   }
2767 
2768   BX_WRITE_MMX_REG(i->dst(), op);
2769 #endif
2770 
2771   BX_NEXT_INSTR(i);
2772 }
2773 
2774 /* 0F 73 GrpA 010 */
PSRLQ_NqIb(bxInstruction_c * i)2775 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_NqIb(bxInstruction_c *i)
2776 {
2777 #if BX_CPU_LEVEL >= 5
2778   BX_CPU_THIS_PTR prepareMMX();
2779   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2780 
2781   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2782   Bit8u shift = i->Ib();
2783 
2784   if(shift > 63) {
2785     MMXUQ(op) = 0;
2786   }
2787   else {
2788     MMXUQ(op) >>= shift;
2789   }
2790 
2791   BX_WRITE_MMX_REG(i->dst(), op);
2792 #endif
2793 
2794   BX_NEXT_INSTR(i);
2795 }
2796 
2797 /* 0F 73 GrpA 110 */
PSLLQ_NqIb(bxInstruction_c * i)2798 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_NqIb(bxInstruction_c *i)
2799 {
2800 #if BX_CPU_LEVEL >= 5
2801   BX_CPU_THIS_PTR prepareMMX();
2802   BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2803 
2804   BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst());
2805   Bit8u shift = i->Ib();
2806 
2807   if(shift > 63) {
2808     MMXUQ(op) = 0;
2809   }
2810   else {
2811     MMXUQ(op) <<= shift;
2812   }
2813 
2814   BX_WRITE_MMX_REG(i->dst(), op);
2815 #endif
2816 
2817   BX_NEXT_INSTR(i);
2818 }
2819