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