- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / mmx.cc
blob1361d6cfff94ed38faaf444f80c3db1ecb6a8d79
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mmx.cc,v 1.83 2008/10/08 11:14:35 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /////////////////////////////////////////////////////////////////////////
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
29 #if BX_SUPPORT_MMX || BX_SUPPORT_SSE
31 void BX_CPU_C::print_state_MMX(void)
33 for(int i=0;i<8;i++) {
34 BxPackedMmxRegister mm = BX_READ_MMX_REG(i);
35 BX_DEBUG(("MM%d: %08x%08x\n", i, MMXUD1(mm), MMXUD0(mm)));
39 void BX_CPU_C::prepareFPU2MMX(void)
41 FPU_TAG_WORD = 0;
42 FPU_TOS = 0; /* reset FPU Top-Of-Stack */
45 #endif
47 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
49 /* 0F 38 00 */
50 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFB_PqQq(bxInstruction_c *i)
52 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
53 BX_CPU_THIS_PTR prepareMMX();
55 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
57 /* op2 is a register or memory reference */
58 if (i->modC0()) {
59 op2 = BX_READ_MMX_REG(i->rm());
61 else {
62 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
63 /* pointer, segment address pair */
64 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
67 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
69 for(unsigned j=0; j<8; j++)
71 unsigned mask = op2.mmxubyte(j);
72 if (mask & 0x80)
73 result.mmxubyte(j) = 0;
74 else
75 result.mmxubyte(j) = op1.mmxubyte(mask & 0x7);
78 BX_WRITE_MMX_REG(i->nnn(), result);
79 #else
80 BX_INFO(("PSHUFB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
81 exception(BX_UD_EXCEPTION, 0, 0);
82 #endif
85 /* 0F 38 01 */
86 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDW_PqQq(bxInstruction_c *i)
88 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
89 BX_CPU_THIS_PTR prepareMMX();
91 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
93 /* op2 is a register or memory reference */
94 if (i->modC0()) {
95 op2 = BX_READ_MMX_REG(i->rm());
97 else {
98 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
99 /* pointer, segment address pair */
100 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
103 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
105 MMXUW0(result) = MMXUW0(op1) + MMXUW1(op1);
106 MMXUW1(result) = MMXUW2(op1) + MMXUW3(op1);
107 MMXUW2(result) = MMXUW0(op2) + MMXUW1(op2);
108 MMXUW3(result) = MMXUW2(op2) + MMXUW3(op2);
110 BX_WRITE_MMX_REG(i->nnn(), result);
111 #else
112 BX_INFO(("PHADDW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
113 exception(BX_UD_EXCEPTION, 0, 0);
114 #endif
117 /* 0F 38 02 */
118 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDD_PqQq(bxInstruction_c *i)
120 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
121 BX_CPU_THIS_PTR prepareMMX();
123 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
125 /* op2 is a register or memory reference */
126 if (i->modC0()) {
127 op2 = BX_READ_MMX_REG(i->rm());
129 else {
130 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
131 /* pointer, segment address pair */
132 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
135 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
137 MMXUD0(result) = MMXUD0(op1) + MMXUD1(op1);
138 MMXUD1(result) = MMXUD0(op2) + MMXUD1(op2);
140 BX_WRITE_MMX_REG(i->nnn(), result);
141 #else
142 BX_INFO(("PHADDD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
143 exception(BX_UD_EXCEPTION, 0, 0);
144 #endif
147 /* 0F 38 03 */
148 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDSW_PqQq(bxInstruction_c *i)
150 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
151 BX_CPU_THIS_PTR prepareMMX();
153 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
155 /* op2 is a register or memory reference */
156 if (i->modC0()) {
157 op2 = BX_READ_MMX_REG(i->rm());
159 else {
160 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
161 /* pointer, segment address pair */
162 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
165 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
167 MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW1(op1)));
168 MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW3(op1)));
169 MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op2)));
170 MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op2)));
172 /* now write result back to destination */
173 BX_WRITE_MMX_REG(i->nnn(), result);
174 #else
175 BX_INFO(("PHADDSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
176 exception(BX_UD_EXCEPTION, 0, 0);
177 #endif
180 /* 0F 38 04 */
181 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDUBSW_PqQq(bxInstruction_c *i)
183 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
184 BX_CPU_THIS_PTR prepareMMX();
186 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
188 /* op2 is a register or memory reference */
189 if (i->modC0()) {
190 op2 = BX_READ_MMX_REG(i->rm());
192 else {
193 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
194 /* pointer, segment address pair */
195 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
198 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
200 for(unsigned j=0; j<4; j++)
202 Bit32s temp = Bit32s(op1.mmxubyte(j*2+0))*Bit32s(op2.mmxsbyte(j*2+0)) +
203 Bit32s(op1.mmxubyte(j*2+1))*Bit32s(op2.mmxsbyte(j*2+1));
205 result.mmx16s(j) = SaturateDwordSToWordS(temp);
208 /* now write result back to destination */
209 BX_WRITE_MMX_REG(i->nnn(), result);
210 #else
211 BX_INFO(("PMADDUBSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
212 exception(BX_UD_EXCEPTION, 0, 0);
213 #endif
216 /* 0F 38 05 */
217 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBSW_PqQq(bxInstruction_c *i)
219 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
220 BX_CPU_THIS_PTR prepareMMX();
222 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
224 /* op2 is a register or memory reference */
225 if (i->modC0()) {
226 op2 = BX_READ_MMX_REG(i->rm());
228 else {
229 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
230 /* pointer, segment address pair */
231 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
234 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
236 MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW1(op1)));
237 MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW3(op1)));
238 MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) - Bit32s(MMXSW1(op2)));
239 MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) - Bit32s(MMXSW3(op2)));
241 /* now write result back to destination */
242 BX_WRITE_MMX_REG(i->nnn(), result);
243 #else
244 BX_INFO(("PHSUBSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
245 exception(BX_UD_EXCEPTION, 0, 0);
246 #endif
249 /* 0F 38 05 */
250 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBW_PqQq(bxInstruction_c *i)
252 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
253 BX_CPU_THIS_PTR prepareMMX();
255 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
257 /* op2 is a register or memory reference */
258 if (i->modC0()) {
259 op2 = BX_READ_MMX_REG(i->rm());
261 else {
262 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
263 /* pointer, segment address pair */
264 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
267 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
269 MMXUW0(result) = MMXUW0(op1) - MMXUW1(op1);
270 MMXUW1(result) = MMXUW2(op1) - MMXUW3(op1);
271 MMXUW2(result) = MMXUW0(op2) - MMXUW1(op2);
272 MMXUW3(result) = MMXUW2(op2) - MMXUW3(op2);
274 BX_WRITE_MMX_REG(i->nnn(), result);
275 #else
276 BX_INFO(("PHSUBW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
277 exception(BX_UD_EXCEPTION, 0, 0);
278 #endif
281 /* 0F 38 06 */
282 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBD_PqQq(bxInstruction_c *i)
284 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
285 BX_CPU_THIS_PTR prepareMMX();
287 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
289 /* op2 is a register or memory reference */
290 if (i->modC0()) {
291 op2 = BX_READ_MMX_REG(i->rm());
293 else {
294 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
295 /* pointer, segment address pair */
296 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
299 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
301 MMXUD0(result) = MMXUD0(op1) - MMXUD1(op1);
302 MMXUD1(result) = MMXUD0(op2) - MMXUD1(op2);
304 BX_WRITE_MMX_REG(i->nnn(), result);
305 #else
306 BX_INFO(("PHSUBD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
307 exception(BX_UD_EXCEPTION, 0, 0);
308 #endif
311 /* 0F 38 08 */
312 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNB_PqQq(bxInstruction_c *i)
314 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
315 BX_CPU_THIS_PTR prepareMMX();
317 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
319 /* op2 is a register or memory reference */
320 if (i->modC0()) {
321 op2 = BX_READ_MMX_REG(i->rm());
323 else {
324 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
325 /* pointer, segment address pair */
326 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
329 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
331 for(unsigned j=0; j<8; j++) {
332 int sign = (op2.mmxsbyte(j) > 0) - (op2.mmxsbyte(j) < 0);
333 op1.mmxsbyte(j) *= sign;
336 BX_WRITE_MMX_REG(i->nnn(), op1);
337 #else
338 BX_INFO(("PSIGNB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
339 exception(BX_UD_EXCEPTION, 0, 0);
340 #endif
343 /* 0F 38 09 */
344 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNW_PqQq(bxInstruction_c *i)
346 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
347 BX_CPU_THIS_PTR prepareMMX();
349 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
351 /* op2 is a register or memory reference */
352 if (i->modC0()) {
353 op2 = BX_READ_MMX_REG(i->rm());
355 else {
356 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
357 /* pointer, segment address pair */
358 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
361 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
363 for(unsigned j=0; j<4; j++) {
364 int sign = (op2.mmx16s(j) > 0) - (op2.mmx16s(j) < 0);
365 op1.mmx16s(j) *= sign;
368 BX_WRITE_MMX_REG(i->nnn(), op1);
369 #else
370 BX_INFO(("PSIGNW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
371 exception(BX_UD_EXCEPTION, 0, 0);
372 #endif
375 /* 0F 38 0A */
376 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGND_PqQq(bxInstruction_c *i)
378 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
379 BX_CPU_THIS_PTR prepareMMX();
381 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
383 /* op2 is a register or memory reference */
384 if (i->modC0()) {
385 op2 = BX_READ_MMX_REG(i->rm());
387 else {
388 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
389 /* pointer, segment address pair */
390 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
393 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
395 int sign;
397 sign = (MMXSD0(op2) > 0) - (MMXSD0(op2) < 0);
398 MMXSD0(op1) *= sign;
399 sign = (MMXSD1(op2) > 0) - (MMXSD1(op2) < 0);
400 MMXSD1(op1) *= sign;
402 BX_WRITE_MMX_REG(i->nnn(), op1);
403 #else
404 BX_INFO(("PSIGND_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
405 exception(BX_UD_EXCEPTION, 0, 0);
406 #endif
409 /* 0F 38 0B */
410 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRSW_PqQq(bxInstruction_c *i)
412 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
413 BX_CPU_THIS_PTR prepareMMX();
415 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
417 /* op2 is a register or memory reference */
418 if (i->modC0()) {
419 op2 = BX_READ_MMX_REG(i->rm());
421 else {
422 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
423 /* pointer, segment address pair */
424 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
427 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
429 for(unsigned j=0; j<4; j++) {
430 Bit32s temp = Bit32s(op1.mmx16s(j)) * Bit32s(op2.mmx16s(j));
431 result.mmx16u(j) = ((temp >> 14) + 1) >> 1;
434 MMXUW0(result) = (((MMXSW0(op1) * MMXSW0(op2)) >> 14) + 1) >> 1;
435 MMXUW1(result) = (((MMXSW1(op1) * MMXSW1(op2)) >> 14) + 1) >> 1;
436 MMXUW2(result) = (((MMXSW2(op1) * MMXSW2(op2)) >> 14) + 1) >> 1;
437 MMXUW3(result) = (((MMXSW3(op1) * MMXSW3(op2)) >> 14) + 1) >> 1;
439 /* now write result back to destination */
440 BX_WRITE_MMX_REG(i->nnn(), result);
441 #else
442 BX_INFO(("PMULHRSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
443 exception(BX_UD_EXCEPTION, 0, 0);
444 #endif
447 /* 0F 38 1C */
448 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSB_PqQq(bxInstruction_c *i)
450 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
451 BX_CPU_THIS_PTR prepareMMX();
453 BxPackedMmxRegister op;
455 if (i->modC0()) {
456 op = BX_READ_MMX_REG(i->rm());
458 else {
459 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
460 /* pointer, segment address pair */
461 MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
464 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
466 if (MMXSB0(op) < 0) MMXUB0(op) = -MMXSB0(op);
467 if (MMXSB1(op) < 0) MMXUB1(op) = -MMXSB1(op);
468 if (MMXSB2(op) < 0) MMXUB2(op) = -MMXSB2(op);
469 if (MMXSB3(op) < 0) MMXUB3(op) = -MMXSB3(op);
470 if (MMXSB4(op) < 0) MMXUB4(op) = -MMXSB4(op);
471 if (MMXSB5(op) < 0) MMXUB5(op) = -MMXSB5(op);
472 if (MMXSB6(op) < 0) MMXUB6(op) = -MMXSB6(op);
473 if (MMXSB7(op) < 0) MMXUB7(op) = -MMXSB7(op);
475 /* now write result back to destination */
476 BX_WRITE_MMX_REG(i->nnn(), op);
477 #else
478 BX_INFO(("PABSB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
479 exception(BX_UD_EXCEPTION, 0, 0);
480 #endif
483 /* 0F 38 1D */
484 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSW_PqQq(bxInstruction_c *i)
486 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
487 BX_CPU_THIS_PTR prepareMMX();
489 BxPackedMmxRegister op;
491 if (i->modC0()) {
492 op = BX_READ_MMX_REG(i->rm());
494 else {
495 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
496 /* pointer, segment address pair */
497 MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
500 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
502 if (MMXSW0(op) < 0) MMXUW0(op) = -MMXSW0(op);
503 if (MMXSW1(op) < 0) MMXUW1(op) = -MMXSW1(op);
504 if (MMXSW2(op) < 0) MMXUW2(op) = -MMXSW2(op);
505 if (MMXSW3(op) < 0) MMXUW3(op) = -MMXSW3(op);
507 /* now write result back to destination */
508 BX_WRITE_MMX_REG(i->nnn(), op);
509 #else
510 BX_INFO(("PABSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
511 exception(BX_UD_EXCEPTION, 0, 0);
512 #endif
515 /* 0F 38 1E */
516 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSD_PqQq(bxInstruction_c *i)
518 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
519 BX_CPU_THIS_PTR prepareMMX();
521 BxPackedMmxRegister op;
523 if (i->modC0()) {
524 op = BX_READ_MMX_REG(i->rm());
526 else {
527 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
528 /* pointer, segment address pair */
529 MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
532 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
534 if (MMXSD0(op) < 0) MMXUD0(op) = -MMXSD0(op);
535 if (MMXSD1(op) < 0) MMXUD1(op) = -MMXSD1(op);
537 /* now write result back to destination */
538 BX_WRITE_MMX_REG(i->nnn(), op);
539 #else
540 BX_INFO(("PABSD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
541 exception(BX_UD_EXCEPTION, 0, 0);
542 #endif
545 /* 0F 3A 0F */
546 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PALIGNR_PqQqIb(bxInstruction_c *i)
548 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
549 BX_CPU_THIS_PTR prepareMMX();
551 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
553 /* op2 is a register or memory reference */
554 if (i->modC0()) {
555 op2 = BX_READ_MMX_REG(i->rm());
557 else {
558 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
559 /* pointer, segment address pair */
560 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
563 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
565 unsigned shift = i->Ib() * 8;
567 if(shift == 0)
568 MMXUQ(result) = MMXUQ(op2);
569 else if(shift < 64)
570 MMXUQ(result) = (MMXUQ(op2) >> shift) | (MMXUQ(op1) << (64-shift));
571 else if(shift < 128)
572 MMXUQ(result) = MMXUQ(op1) >> (shift-64);
573 else
574 MMXUQ(result) = 0;
576 /* now write result back to destination */
577 BX_WRITE_MMX_REG(i->nnn(), result);
578 #else
579 BX_INFO(("PALIGNR_PqQqIb: required SSE3E, use --enable-sse and --enable-sse-extension options"));
580 exception(BX_UD_EXCEPTION, 0, 0);
581 #endif
584 #endif // BX_SUPPORT_SSE >= 4 || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
586 /* 0F 60 */
587 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLBW_PqQd(bxInstruction_c *i)
589 #if BX_SUPPORT_MMX
590 BX_CPU_THIS_PTR prepareMMX();
592 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
594 /* op2 is a register or memory reference */
595 if (i->modC0()) {
596 op2 = BX_READ_MMX_REG(i->rm());
598 else {
599 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
600 /* pointer, segment address pair */
601 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
604 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
606 MMXUB7(result) = MMXUB3(op2);
607 MMXUB6(result) = MMXUB3(op1);
608 MMXUB5(result) = MMXUB2(op2);
609 MMXUB4(result) = MMXUB2(op1);
610 MMXUB3(result) = MMXUB1(op2);
611 MMXUB2(result) = MMXUB1(op1);
612 MMXUB1(result) = MMXUB0(op2);
613 MMXUB0(result) = MMXUB0(op1);
615 /* now write result back to destination */
616 BX_WRITE_MMX_REG(i->nnn(), result);
617 #else
618 BX_INFO(("PUNPCKLBW_PqQd: required MMX, configure --enable-mmx"));
619 exception(BX_UD_EXCEPTION, 0, 0);
620 #endif
623 /* 0F 61 */
624 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLWD_PqQd(bxInstruction_c *i)
626 #if BX_SUPPORT_MMX
627 BX_CPU_THIS_PTR prepareMMX();
629 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
631 /* op2 is a register or memory reference */
632 if (i->modC0()) {
633 op2 = BX_READ_MMX_REG(i->rm());
635 else {
636 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
637 /* pointer, segment address pair */
638 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
641 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
643 MMXUW3(result) = MMXUW1(op2);
644 MMXUW2(result) = MMXUW1(op1);
645 MMXUW1(result) = MMXUW0(op2);
646 MMXUW0(result) = MMXUW0(op1);
648 /* now write result back to destination */
649 BX_WRITE_MMX_REG(i->nnn(), result);
650 #else
651 BX_INFO(("PUNPCKLWD_PqQd: required MMX, use --enable-mmx option"));
652 exception(BX_UD_EXCEPTION, 0, 0);
653 #endif
656 /* 0F 62 */
657 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLDQ_PqQd(bxInstruction_c *i)
659 #if BX_SUPPORT_MMX
660 BX_CPU_THIS_PTR prepareMMX();
662 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
664 /* op2 is a register or memory reference */
665 if (i->modC0()) {
666 op2 = BX_READ_MMX_REG(i->rm());
668 else {
669 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
670 /* pointer, segment address pair */
671 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
674 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
676 MMXUD1(op1) = MMXUD0(op2);
678 /* now write result back to destination */
679 BX_WRITE_MMX_REG(i->nnn(), op1);
680 #else
681 BX_INFO(("PUNPCKLDQ_PqQd: required MMX, use --enable-mmx option"));
682 exception(BX_UD_EXCEPTION, 0, 0);
683 #endif
686 /* 0F 63 */
687 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSWB_PqQq(bxInstruction_c *i)
689 #if BX_SUPPORT_MMX
690 BX_CPU_THIS_PTR prepareMMX();
692 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
694 /* op2 is a register or memory reference */
695 if (i->modC0()) {
696 op2 = BX_READ_MMX_REG(i->rm());
698 else {
699 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
700 /* pointer, segment address pair */
701 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
704 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
706 MMXSB0(result) = SaturateWordSToByteS(MMXSW0(op1));
707 MMXSB1(result) = SaturateWordSToByteS(MMXSW1(op1));
708 MMXSB2(result) = SaturateWordSToByteS(MMXSW2(op1));
709 MMXSB3(result) = SaturateWordSToByteS(MMXSW3(op1));
710 MMXSB4(result) = SaturateWordSToByteS(MMXSW0(op2));
711 MMXSB5(result) = SaturateWordSToByteS(MMXSW1(op2));
712 MMXSB6(result) = SaturateWordSToByteS(MMXSW2(op2));
713 MMXSB7(result) = SaturateWordSToByteS(MMXSW3(op2));
715 /* now write result back to destination */
716 BX_WRITE_MMX_REG(i->nnn(), result);
717 #else
718 BX_INFO(("PACKSSWB_PqQq: required MMX, use --enable-mmx option"));
719 exception(BX_UD_EXCEPTION, 0, 0);
720 #endif
723 /* 0F 64 */
724 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTB_PqQq(bxInstruction_c *i)
726 #if BX_SUPPORT_MMX
727 BX_CPU_THIS_PTR prepareMMX();
729 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
731 /* op2 is a register or memory reference */
732 if (i->modC0()) {
733 op2 = BX_READ_MMX_REG(i->rm());
735 else {
736 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
737 /* pointer, segment address pair */
738 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
741 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
743 MMXUB0(op1) = (MMXSB0(op1) > MMXSB0(op2)) ? 0xff : 0;
744 MMXUB1(op1) = (MMXSB1(op1) > MMXSB1(op2)) ? 0xff : 0;
745 MMXUB2(op1) = (MMXSB2(op1) > MMXSB2(op2)) ? 0xff : 0;
746 MMXUB3(op1) = (MMXSB3(op1) > MMXSB3(op2)) ? 0xff : 0;
747 MMXUB4(op1) = (MMXSB4(op1) > MMXSB4(op2)) ? 0xff : 0;
748 MMXUB5(op1) = (MMXSB5(op1) > MMXSB5(op2)) ? 0xff : 0;
749 MMXUB6(op1) = (MMXSB6(op1) > MMXSB6(op2)) ? 0xff : 0;
750 MMXUB7(op1) = (MMXSB7(op1) > MMXSB7(op2)) ? 0xff : 0;
752 /* now write result back to destination */
753 BX_WRITE_MMX_REG(i->nnn(), op1);
754 #else
755 BX_INFO(("PCMPGTB_PqQq: required MMX, use --enable-mmx option"));
756 exception(BX_UD_EXCEPTION, 0, 0);
757 #endif
760 /* 0F 65 */
761 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTW_PqQq(bxInstruction_c *i)
763 #if BX_SUPPORT_MMX
764 BX_CPU_THIS_PTR prepareMMX();
766 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
768 /* op2 is a register or memory reference */
769 if (i->modC0()) {
770 op2 = BX_READ_MMX_REG(i->rm());
772 else {
773 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
774 /* pointer, segment address pair */
775 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
778 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
780 MMXUW0(op1) = (MMXSW0(op1) > MMXSW0(op2)) ? 0xffff : 0;
781 MMXUW1(op1) = (MMXSW1(op1) > MMXSW1(op2)) ? 0xffff : 0;
782 MMXUW2(op1) = (MMXSW2(op1) > MMXSW2(op2)) ? 0xffff : 0;
783 MMXUW3(op1) = (MMXSW3(op1) > MMXSW3(op2)) ? 0xffff : 0;
785 /* now write result back to destination */
786 BX_WRITE_MMX_REG(i->nnn(), op1);
787 #else
788 BX_INFO(("PCMPGTW_PqQq: required MMX, use --enable-mmx option"));
789 exception(BX_UD_EXCEPTION, 0, 0);
790 #endif
793 /* 0F 66 */
794 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTD_PqQq(bxInstruction_c *i)
796 #if BX_SUPPORT_MMX
797 BX_CPU_THIS_PTR prepareMMX();
799 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
801 /* op2 is a register or memory reference */
802 if (i->modC0()) {
803 op2 = BX_READ_MMX_REG(i->rm());
805 else {
806 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
807 /* pointer, segment address pair */
808 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
811 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
813 MMXUD0(op1) = (MMXSD0(op1) > MMXSD0(op2)) ? 0xffffffff : 0;
814 MMXUD1(op1) = (MMXSD1(op1) > MMXSD1(op2)) ? 0xffffffff : 0;
816 /* now write result back to destination */
817 BX_WRITE_MMX_REG(i->nnn(), op1);
818 #else
819 BX_INFO(("PCMPGTD_PqQq: required MMX, use --enable-mmx option"));
820 exception(BX_UD_EXCEPTION, 0, 0);
821 #endif
824 /* 0F 67 */
825 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKUSWB_PqQq(bxInstruction_c *i)
827 #if BX_SUPPORT_MMX
828 BX_CPU_THIS_PTR prepareMMX();
830 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
832 /* op2 is a register or memory reference */
833 if (i->modC0()) {
834 op2 = BX_READ_MMX_REG(i->rm());
836 else {
837 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
838 /* pointer, segment address pair */
839 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
842 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
844 MMXUB0(result) = SaturateWordSToByteU(MMXSW0(op1));
845 MMXUB1(result) = SaturateWordSToByteU(MMXSW1(op1));
846 MMXUB2(result) = SaturateWordSToByteU(MMXSW2(op1));
847 MMXUB3(result) = SaturateWordSToByteU(MMXSW3(op1));
848 MMXUB4(result) = SaturateWordSToByteU(MMXSW0(op2));
849 MMXUB5(result) = SaturateWordSToByteU(MMXSW1(op2));
850 MMXUB6(result) = SaturateWordSToByteU(MMXSW2(op2));
851 MMXUB7(result) = SaturateWordSToByteU(MMXSW3(op2));
853 /* now write result back to destination */
854 BX_WRITE_MMX_REG(i->nnn(), result);
855 #else
856 BX_INFO(("PACKUSWB_PqQq: required MMX, use --enable-mmx option"));
857 exception(BX_UD_EXCEPTION, 0, 0);
858 #endif
861 /* 0F 68 */
862 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHBW_PqQq(bxInstruction_c *i)
864 #if BX_SUPPORT_MMX
865 BX_CPU_THIS_PTR prepareMMX();
867 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
869 /* op2 is a register or memory reference */
870 if (i->modC0()) {
871 op2 = BX_READ_MMX_REG(i->rm());
873 else {
874 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
875 /* pointer, segment address pair */
876 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
879 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
881 MMXUB7(result) = MMXUB7(op2);
882 MMXUB6(result) = MMXUB7(op1);
883 MMXUB5(result) = MMXUB6(op2);
884 MMXUB4(result) = MMXUB6(op1);
885 MMXUB3(result) = MMXUB5(op2);
886 MMXUB2(result) = MMXUB5(op1);
887 MMXUB1(result) = MMXUB4(op2);
888 MMXUB0(result) = MMXUB4(op1);
890 /* now write result back to destination */
891 BX_WRITE_MMX_REG(i->nnn(), result);
892 #else
893 BX_INFO(("PUNPCKHBW_PqQq: required MMX, use --enable-mmx option"));
894 exception(BX_UD_EXCEPTION, 0, 0);
895 #endif
898 /* 0F 69 */
899 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHWD_PqQq(bxInstruction_c *i)
901 #if BX_SUPPORT_MMX
902 BX_CPU_THIS_PTR prepareMMX();
904 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
906 /* op2 is a register or memory reference */
907 if (i->modC0()) {
908 op2 = BX_READ_MMX_REG(i->rm());
910 else {
911 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
912 /* pointer, segment address pair */
913 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
916 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
918 MMXUW3(result) = MMXUW3(op2);
919 MMXUW2(result) = MMXUW3(op1);
920 MMXUW1(result) = MMXUW2(op2);
921 MMXUW0(result) = MMXUW2(op1);
923 /* now write result back to destination */
924 BX_WRITE_MMX_REG(i->nnn(), result);
925 #else
926 BX_INFO(("PUNPCKHWD_PqQq: required MMX, use --enable-mmx option"));
927 exception(BX_UD_EXCEPTION, 0, 0);
928 #endif
931 /* 0F 6A */
932 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHDQ_PqQq(bxInstruction_c *i)
934 #if BX_SUPPORT_MMX
935 BX_CPU_THIS_PTR prepareMMX();
937 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
939 /* op2 is a register or memory reference */
940 if (i->modC0()) {
941 op2 = BX_READ_MMX_REG(i->rm());
943 else {
944 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
945 /* pointer, segment address pair */
946 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
949 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
951 MMXUD1(result) = MMXUD1(op2);
952 MMXUD0(result) = MMXUD1(op1);
954 /* now write result back to destination */
955 BX_WRITE_MMX_REG(i->nnn(), result);
956 #else
957 BX_INFO(("PUNPCKHDQ_PqQq: required MMX, use --enable-mmx option"));
958 exception(BX_UD_EXCEPTION, 0, 0);
959 #endif
962 /* 0F 6B */
963 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSDW_PqQq(bxInstruction_c *i)
965 #if BX_SUPPORT_MMX
966 BX_CPU_THIS_PTR prepareMMX();
968 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
970 /* op2 is a register or memory reference */
971 if (i->modC0()) {
972 op2 = BX_READ_MMX_REG(i->rm());
974 else {
975 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
976 /* pointer, segment address pair */
977 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
980 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
982 MMXSW0(result) = SaturateDwordSToWordS(MMXSD0(op1));
983 MMXSW1(result) = SaturateDwordSToWordS(MMXSD1(op1));
984 MMXSW2(result) = SaturateDwordSToWordS(MMXSD0(op2));
985 MMXSW3(result) = SaturateDwordSToWordS(MMXSD1(op2));
987 /* now write result back to destination */
988 BX_WRITE_MMX_REG(i->nnn(), result);
989 #else
990 BX_INFO(("PACKSSDW_PqQq: required MMX, use --enable-mmx option"));
991 exception(BX_UD_EXCEPTION, 0, 0);
992 #endif
995 /* 0F 6E */
996 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEd(bxInstruction_c *i)
998 #if BX_SUPPORT_MMX
999 BX_CPU_THIS_PTR prepareMMX();
1001 BxPackedMmxRegister op;
1003 MMXUD1(op) = 0;
1005 /* op is a register or memory reference */
1006 if (i->modC0()) {
1007 MMXUD0(op) = BX_READ_32BIT_REG(i->rm());
1009 else {
1010 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1011 /* pointer, segment address pair */
1012 MMXUD0(op) = read_virtual_dword(i->seg(), eaddr);
1015 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1017 /* now write result back to destination */
1018 BX_WRITE_MMX_REG(i->nnn(), op);
1019 #else
1020 BX_INFO(("MOVD_PqEd: required MMX, use --enable-mmx option"));
1021 exception(BX_UD_EXCEPTION, 0, 0);
1022 #endif
1025 /* 0F 6E */
1026 #if BX_SUPPORT_X86_64
1028 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqEq(bxInstruction_c *i)
1030 BX_CPU_THIS_PTR prepareMMX();
1032 BxPackedMmxRegister op;
1034 /* op is a register or memory reference */
1035 if (i->modC0()) {
1036 MMXUQ(op) = BX_READ_64BIT_REG(i->rm());
1038 else {
1039 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1040 /* pointer, segment address pair */
1041 MMXUQ(op) = read_virtual_qword_64(i->seg(), eaddr);
1044 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1046 /* now write result back to destination */
1047 BX_WRITE_MMX_REG(i->nnn(), op);
1050 #endif
1052 /* 0F 6F */
1053 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQq(bxInstruction_c *i)
1055 #if BX_SUPPORT_MMX
1056 BX_CPU_THIS_PTR prepareMMX();
1058 BxPackedMmxRegister op;
1060 /* op is a register or memory reference */
1061 if (i->modC0()) {
1062 op = BX_READ_MMX_REG(i->rm());
1064 else {
1065 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1066 /* pointer, segment address pair */
1067 MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
1070 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1072 /* now write result back to destination */
1073 BX_WRITE_MMX_REG(i->nnn(), op);
1074 #else
1075 BX_INFO(("MOVQ_PqQq: required MMX, use --enable-mmx option"));
1076 exception(BX_UD_EXCEPTION, 0, 0);
1077 #endif
1080 /* 0F 70 */
1081 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFW_PqQqIb(bxInstruction_c *i)
1083 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1084 BX_CPU_THIS_PTR prepareMMX();
1086 BxPackedMmxRegister op, result;
1087 Bit8u order = i->Ib();
1089 /* op is a register or memory reference */
1090 if (i->modC0()) {
1091 op = BX_READ_MMX_REG(i->rm());
1093 else {
1094 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1095 /* pointer, segment address pair */
1096 MMXUQ(op) = read_virtual_qword(i->seg(), eaddr);
1099 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1101 MMXUW0(result) = op.mmx16u((order) & 0x3);
1102 MMXUW1(result) = op.mmx16u((order>>2) & 0x3);
1103 MMXUW2(result) = op.mmx16u((order>>4) & 0x3);
1104 MMXUW3(result) = op.mmx16u((order>>6) & 0x3);
1106 /* now write result back to destination */
1107 BX_WRITE_MMX_REG(i->nnn(), result);
1108 #else
1109 BX_INFO(("PSHUFW_PqQqIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1110 exception(BX_UD_EXCEPTION, 0, 0);
1111 #endif
1114 /* 0F 74 */
1115 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQB_PqQq(bxInstruction_c *i)
1117 #if BX_SUPPORT_MMX
1118 BX_CPU_THIS_PTR prepareMMX();
1120 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1122 /* op2 is a register or memory reference */
1123 if (i->modC0()) {
1124 op2 = BX_READ_MMX_REG(i->rm());
1126 else {
1127 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1128 /* pointer, segment address pair */
1129 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1132 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1134 MMXUB0(op1) = (MMXUB0(op1) == MMXUB0(op2)) ? 0xff : 0;
1135 MMXUB1(op1) = (MMXUB1(op1) == MMXUB1(op2)) ? 0xff : 0;
1136 MMXUB2(op1) = (MMXUB2(op1) == MMXUB2(op2)) ? 0xff : 0;
1137 MMXUB3(op1) = (MMXUB3(op1) == MMXUB3(op2)) ? 0xff : 0;
1138 MMXUB4(op1) = (MMXUB4(op1) == MMXUB4(op2)) ? 0xff : 0;
1139 MMXUB5(op1) = (MMXUB5(op1) == MMXUB5(op2)) ? 0xff : 0;
1140 MMXUB6(op1) = (MMXUB6(op1) == MMXUB6(op2)) ? 0xff : 0;
1141 MMXUB7(op1) = (MMXUB7(op1) == MMXUB7(op2)) ? 0xff : 0;
1143 /* now write result back to destination */
1144 BX_WRITE_MMX_REG(i->nnn(), op1);
1145 #else
1146 BX_INFO(("PCMPEQB_PqQq: required MMX, use --enable-mmx option"));
1147 exception(BX_UD_EXCEPTION, 0, 0);
1148 #endif
1151 /* 0F 75 */
1152 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQW_PqQq(bxInstruction_c *i)
1154 #if BX_SUPPORT_MMX
1155 BX_CPU_THIS_PTR prepareMMX();
1157 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1159 /* op2 is a register or memory reference */
1160 if (i->modC0()) {
1161 op2 = BX_READ_MMX_REG(i->rm());
1163 else {
1164 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1165 /* pointer, segment address pair */
1166 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1169 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1171 MMXUW0(op1) = (MMXUW0(op1) == MMXUW0(op2)) ? 0xffff : 0;
1172 MMXUW1(op1) = (MMXUW1(op1) == MMXUW1(op2)) ? 0xffff : 0;
1173 MMXUW2(op1) = (MMXUW2(op1) == MMXUW2(op2)) ? 0xffff : 0;
1174 MMXUW3(op1) = (MMXUW3(op1) == MMXUW3(op2)) ? 0xffff : 0;
1176 /* now write result back to destination */
1177 BX_WRITE_MMX_REG(i->nnn(), op1);
1178 #else
1179 BX_INFO(("PCMPEQW_PqQq: required MMX, use --enable-mmx option"));
1180 exception(BX_UD_EXCEPTION, 0, 0);
1181 #endif
1184 /* 0F 76 */
1185 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQD_PqQq(bxInstruction_c *i)
1187 #if BX_SUPPORT_MMX
1188 BX_CPU_THIS_PTR prepareMMX();
1190 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1192 /* op2 is a register or memory reference */
1193 if (i->modC0()) {
1194 op2 = BX_READ_MMX_REG(i->rm());
1196 else {
1197 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1198 /* pointer, segment address pair */
1199 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1202 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1204 MMXUD0(op1) = (MMXUD0(op1) == MMXUD0(op2)) ? 0xffffffff : 0;
1205 MMXUD1(op1) = (MMXUD1(op1) == MMXUD1(op2)) ? 0xffffffff : 0;
1207 /* now write result back to destination */
1208 BX_WRITE_MMX_REG(i->nnn(), op1);
1209 #else
1210 BX_INFO(("PCMPEQD_PqQq: required MMX, use --enable-mmx option"));
1211 exception(BX_UD_EXCEPTION, 0, 0);
1212 #endif
1215 /* 0F 77 */
1216 void BX_CPP_AttrRegparmN(1) BX_CPU_C::EMMS(bxInstruction_c *i)
1218 #if BX_SUPPORT_MMX || BX_SUPPORT_3DNOW
1219 BX_CPU_THIS_PTR prepareMMX();
1220 FPU_TAG_WORD = 0xffff;
1221 FPU_TOS = 0; /* reset FPU Top-Of-Stack */
1222 #else
1223 BX_INFO(("EMMS: required MMX, use --enable-mmx option"));
1224 exception(BX_UD_EXCEPTION, 0, 0);
1225 #endif
1228 /* 0F 7E */
1229 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPd(bxInstruction_c *i)
1231 #if BX_SUPPORT_MMX
1232 BX_CPU_THIS_PTR prepareMMX();
1233 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1235 BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn());
1237 /* destination is a register or memory reference */
1238 if (i->modC0()) {
1239 BX_WRITE_32BIT_REGZ(i->rm(), MMXUD0(op));
1241 else {
1242 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1243 /* pointer, segment address pair */
1244 write_virtual_dword(i->seg(), eaddr, MMXUD0(op));
1246 #else
1247 BX_INFO(("MOVD_EdPd: required MMX, use --enable-mmx option"));
1248 exception(BX_UD_EXCEPTION, 0, 0);
1249 #endif
1252 #if BX_SUPPORT_X86_64
1254 /* 0F 7E */
1255 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_EqPq(bxInstruction_c *i)
1257 BX_CPU_THIS_PTR prepareMMX();
1258 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1260 BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn());
1262 /* destination is a register or memory reference */
1263 if (i->modC0()) {
1264 BX_WRITE_64BIT_REG(i->rm(), MMXUQ(op));
1266 else {
1267 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1268 /* pointer, segment address pair */
1269 write_virtual_qword_64(i->seg(), eaddr, MMXUQ(op));
1273 #endif
1275 /* 0F 7F */
1276 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_QqPq(bxInstruction_c *i)
1278 #if BX_SUPPORT_MMX
1279 BX_CPU_THIS_PTR prepareMMX();
1280 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1282 BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn());
1284 /* op is a register or memory reference */
1285 if (i->modC0()) {
1286 BX_WRITE_MMX_REG(i->rm(), op);
1288 else {
1289 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1290 /* pointer, segment address pair */
1291 write_virtual_qword(i->seg(), eaddr, MMXUQ(op));
1293 #else
1294 BX_INFO(("MOVQ_QqPq: required MMX, use --enable-mmx option"));
1295 exception(BX_UD_EXCEPTION, 0, 0);
1296 #endif
1299 /* 0F C4 */
1300 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRW_PqEwIb(bxInstruction_c *i)
1302 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1303 BX_CPU_THIS_PTR prepareMMX();
1305 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn());
1306 Bit16u op2;
1308 /* op2 is a register or memory reference */
1309 if (i->modC0()) {
1310 op2 = BX_READ_16BIT_REG(i->rm());
1312 else {
1313 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1314 /* pointer, segment address pair */
1315 op2 = read_virtual_word(i->seg(), eaddr);
1318 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1320 op1.xmm16u(i->Ib() & 0x3) = op2;
1322 /* now write result back to destination */
1323 BX_WRITE_MMX_REG(i->nnn(), op1);
1324 #else
1325 BX_INFO(("PINSRW_PqEdIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1326 exception(BX_UD_EXCEPTION, 0, 0);
1327 #endif
1330 /* 0F C5 */
1331 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_GdPqIb(bxInstruction_c *i)
1333 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1334 BX_CPU_THIS_PTR prepareMMX();
1335 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1337 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
1338 Bit32u result = (Bit32u) op.mmx16u(i->Ib() & 0x3);
1340 BX_WRITE_32BIT_REGZ(i->nnn(), result);
1341 #else
1342 BX_INFO(("PEXTRW_GdPqIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1343 exception(BX_UD_EXCEPTION, 0, 0);
1344 #endif
1347 /* 0F D1 */
1348 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqQq(bxInstruction_c *i)
1350 #if BX_SUPPORT_MMX
1351 BX_CPU_THIS_PTR prepareMMX();
1353 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1355 /* op2 is a register or memory reference */
1356 if (i->modC0()) {
1357 op2 = BX_READ_MMX_REG(i->rm());
1359 else {
1360 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1361 /* pointer, segment address pair */
1362 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1365 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1367 if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
1368 else
1370 Bit8u shift = MMXUB0(op2);
1372 MMXUW0(op1) >>= shift;
1373 MMXUW1(op1) >>= shift;
1374 MMXUW2(op1) >>= shift;
1375 MMXUW3(op1) >>= shift;
1378 /* now write result back to destination */
1379 BX_WRITE_MMX_REG(i->nnn(), op1);
1380 #else
1381 BX_INFO(("PSRLW_PqQq: required MMX, use --enable-mmx option"));
1382 exception(BX_UD_EXCEPTION, 0, 0);
1383 #endif
1386 /* 0F D2 */
1387 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqQq(bxInstruction_c *i)
1389 #if BX_SUPPORT_MMX
1390 BX_CPU_THIS_PTR prepareMMX();
1392 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1394 /* op2 is a register or memory reference */
1395 if (i->modC0()) {
1396 op2 = BX_READ_MMX_REG(i->rm());
1398 else {
1399 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1400 /* pointer, segment address pair */
1401 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1404 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1406 if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
1407 else
1409 Bit8u shift = MMXUB0(op2);
1411 MMXUD0(op1) >>= shift;
1412 MMXUD1(op1) >>= shift;
1415 /* now write result back to destination */
1416 BX_WRITE_MMX_REG(i->nnn(), op1);
1417 #else
1418 BX_INFO(("PSRLD_PqQq: required MMX, use --enable-mmx option"));
1419 exception(BX_UD_EXCEPTION, 0, 0);
1420 #endif
1423 /* 0F D3 */
1424 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqQq(bxInstruction_c *i)
1426 #if BX_SUPPORT_MMX
1427 BX_CPU_THIS_PTR prepareMMX();
1429 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1431 /* op2 is a register or memory reference */
1432 if (i->modC0()) {
1433 op2 = BX_READ_MMX_REG(i->rm());
1435 else {
1436 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1437 /* pointer, segment address pair */
1438 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1441 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1443 if(MMXUQ(op2) > 63) {
1444 MMXUQ(op1) = 0;
1446 else {
1447 MMXUQ(op1) >>= MMXUB0(op2);
1450 /* now write result back to destination */
1451 BX_WRITE_MMX_REG(i->nnn(), op1);
1452 #else
1453 BX_INFO(("PSRLQ_PqQq: required MMX, use --enable-mmx option"));
1454 exception(BX_UD_EXCEPTION, 0, 0);
1455 #endif
1458 /* 0F D4 */
1459 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDQ_PqQq(bxInstruction_c *i)
1461 #if BX_SUPPORT_SSE >= 2
1462 BX_CPU_THIS_PTR prepareMMX();
1464 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1466 /* op2 is a register or memory reference */
1467 if (i->modC0()) {
1468 op2 = BX_READ_MMX_REG(i->rm());
1470 else {
1471 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1472 /* pointer, segment address pair */
1473 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1476 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1478 MMXUQ(op1) += MMXUQ(op2);
1480 /* now write result back to destination */
1481 BX_WRITE_MMX_REG(i->nnn(), op1);
1482 #else
1483 BX_INFO(("PADDQ_PqQq: required SSE2, use --enable-sse option"));
1484 exception(BX_UD_EXCEPTION, 0, 0);
1485 #endif
1488 /* 0F D5 */
1489 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULLW_PqQq(bxInstruction_c *i)
1491 #if BX_SUPPORT_MMX
1492 BX_CPU_THIS_PTR prepareMMX();
1494 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1496 /* op2 is a register or memory reference */
1497 if (i->modC0()) {
1498 op2 = BX_READ_MMX_REG(i->rm());
1500 else {
1501 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1502 /* pointer, segment address pair */
1503 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1506 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1508 Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2));
1509 Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2));
1510 Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2));
1511 Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2));
1513 MMXUW0(result) = product1 & 0xffff;
1514 MMXUW1(result) = product2 & 0xffff;
1515 MMXUW2(result) = product3 & 0xffff;
1516 MMXUW3(result) = product4 & 0xffff;
1518 /* now write result back to destination */
1519 BX_WRITE_MMX_REG(i->nnn(), result);
1520 #else
1521 BX_INFO(("PMULLW_PqQq: required MMX, use --enable-mmx option"));
1522 exception(BX_UD_EXCEPTION, 0, 0);
1523 #endif
1526 /* 0F D7 */
1527 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVMSKB_GdPRq(bxInstruction_c *i)
1529 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1530 BX_CPU_THIS_PTR prepareMMX();
1531 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1533 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
1534 Bit32u result = 0;
1536 if(MMXUB0(op) & 0x80) result |= 0x01;
1537 if(MMXUB1(op) & 0x80) result |= 0x02;
1538 if(MMXUB2(op) & 0x80) result |= 0x04;
1539 if(MMXUB3(op) & 0x80) result |= 0x08;
1540 if(MMXUB4(op) & 0x80) result |= 0x10;
1541 if(MMXUB5(op) & 0x80) result |= 0x20;
1542 if(MMXUB6(op) & 0x80) result |= 0x40;
1543 if(MMXUB7(op) & 0x80) result |= 0x80;
1545 /* now write result back to destination */
1546 BX_WRITE_32BIT_REGZ(i->nnn(), result);
1548 #else
1549 BX_INFO(("PMOVMSKB_GdPRq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1550 exception(BX_UD_EXCEPTION, 0, 0);
1551 #endif
1554 /* 0F D8 */
1555 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSB_PqQq(bxInstruction_c *i)
1557 #if BX_SUPPORT_MMX
1558 BX_CPU_THIS_PTR prepareMMX();
1560 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1562 /* op2 is a register or memory reference */
1563 if (i->modC0()) {
1564 op2 = BX_READ_MMX_REG(i->rm());
1566 else {
1567 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1568 /* pointer, segment address pair */
1569 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1572 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1574 MMXUQ(result) = 0;
1576 if(MMXUB0(op1) > MMXUB0(op2)) MMXUB0(result) = MMXUB0(op1) - MMXUB0(op2);
1577 if(MMXUB1(op1) > MMXUB1(op2)) MMXUB1(result) = MMXUB1(op1) - MMXUB1(op2);
1578 if(MMXUB2(op1) > MMXUB2(op2)) MMXUB2(result) = MMXUB2(op1) - MMXUB2(op2);
1579 if(MMXUB3(op1) > MMXUB3(op2)) MMXUB3(result) = MMXUB3(op1) - MMXUB3(op2);
1580 if(MMXUB4(op1) > MMXUB4(op2)) MMXUB4(result) = MMXUB4(op1) - MMXUB4(op2);
1581 if(MMXUB5(op1) > MMXUB5(op2)) MMXUB5(result) = MMXUB5(op1) - MMXUB5(op2);
1582 if(MMXUB6(op1) > MMXUB6(op2)) MMXUB6(result) = MMXUB6(op1) - MMXUB6(op2);
1583 if(MMXUB7(op1) > MMXUB7(op2)) MMXUB7(result) = MMXUB7(op1) - MMXUB7(op2);
1585 /* now write result back to destination */
1586 BX_WRITE_MMX_REG(i->nnn(), result);
1587 #else
1588 BX_INFO(("PSUBUSB_PqQq: required MMX, use --enable-mmx option"));
1589 exception(BX_UD_EXCEPTION, 0, 0);
1590 #endif
1593 /* 0F D9 */
1594 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSW_PqQq(bxInstruction_c *i)
1596 #if BX_SUPPORT_MMX
1597 BX_CPU_THIS_PTR prepareMMX();
1599 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1601 /* op2 is a register or memory reference */
1602 if (i->modC0()) {
1603 op2 = BX_READ_MMX_REG(i->rm());
1605 else {
1606 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1607 /* pointer, segment address pair */
1608 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1611 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1613 MMXUQ(result) = 0;
1615 if(MMXUW0(op1) > MMXUW0(op2)) MMXUW0(result) = MMXUW0(op1) - MMXUW0(op2);
1616 if(MMXUW1(op1) > MMXUW1(op2)) MMXUW1(result) = MMXUW1(op1) - MMXUW1(op2);
1617 if(MMXUW2(op1) > MMXUW2(op2)) MMXUW2(result) = MMXUW2(op1) - MMXUW2(op2);
1618 if(MMXUW3(op1) > MMXUW3(op2)) MMXUW3(result) = MMXUW3(op1) - MMXUW3(op2);
1620 /* now write result back to destination */
1621 BX_WRITE_MMX_REG(i->nnn(), result);
1622 #else
1623 BX_INFO(("PSUBUSW_PqQq: required MMX, use --enable-mmx option"));
1624 exception(BX_UD_EXCEPTION, 0, 0);
1625 #endif
1628 /* 0F DA */
1629 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINUB_PqQq(bxInstruction_c *i)
1631 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1632 BX_CPU_THIS_PTR prepareMMX();
1634 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1636 /* op2 is a register or memory reference */
1637 if (i->modC0()) {
1638 op2 = BX_READ_MMX_REG(i->rm());
1640 else {
1641 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1642 /* pointer, segment address pair */
1643 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1646 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1648 if(MMXUB0(op2) < MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2);
1649 if(MMXUB1(op2) < MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2);
1650 if(MMXUB2(op2) < MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2);
1651 if(MMXUB3(op2) < MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2);
1652 if(MMXUB4(op2) < MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2);
1653 if(MMXUB5(op2) < MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2);
1654 if(MMXUB6(op2) < MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2);
1655 if(MMXUB7(op2) < MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2);
1657 /* now write result back to destination */
1658 BX_WRITE_MMX_REG(i->nnn(), op1);
1659 #else
1660 BX_INFO(("PMINUB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1661 exception(BX_UD_EXCEPTION, 0, 0);
1662 #endif
1665 /* 0F DB */
1666 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAND_PqQq(bxInstruction_c *i)
1668 #if BX_SUPPORT_MMX
1669 BX_CPU_THIS_PTR prepareMMX();
1671 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1673 /* op2 is a register or memory reference */
1674 if (i->modC0()) {
1675 op2 = BX_READ_MMX_REG(i->rm());
1677 else {
1678 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1679 /* pointer, segment address pair */
1680 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1683 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1685 MMXUQ(op1) &= MMXUQ(op2);
1687 /* now write result back to destination */
1688 BX_WRITE_MMX_REG(i->nnn(), op1);
1689 #else
1690 BX_INFO(("PAND_PqQq: required MMX, use --enable-mmx option"));
1691 exception(BX_UD_EXCEPTION, 0, 0);
1692 #endif
1695 /* 0F DC */
1696 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSB_PqQq(bxInstruction_c *i)
1698 #if BX_SUPPORT_MMX
1699 BX_CPU_THIS_PTR prepareMMX();
1701 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1703 /* op2 is a register or memory reference */
1704 if (i->modC0()) {
1705 op2 = BX_READ_MMX_REG(i->rm());
1707 else {
1708 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1709 /* pointer, segment address pair */
1710 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1713 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1715 MMXUB0(result) = SaturateWordSToByteU(Bit16s(MMXUB0(op1)) + Bit16s(MMXUB0(op2)));
1716 MMXUB1(result) = SaturateWordSToByteU(Bit16s(MMXUB1(op1)) + Bit16s(MMXUB1(op2)));
1717 MMXUB2(result) = SaturateWordSToByteU(Bit16s(MMXUB2(op1)) + Bit16s(MMXUB2(op2)));
1718 MMXUB3(result) = SaturateWordSToByteU(Bit16s(MMXUB3(op1)) + Bit16s(MMXUB3(op2)));
1719 MMXUB4(result) = SaturateWordSToByteU(Bit16s(MMXUB4(op1)) + Bit16s(MMXUB4(op2)));
1720 MMXUB5(result) = SaturateWordSToByteU(Bit16s(MMXUB5(op1)) + Bit16s(MMXUB5(op2)));
1721 MMXUB6(result) = SaturateWordSToByteU(Bit16s(MMXUB6(op1)) + Bit16s(MMXUB6(op2)));
1722 MMXUB7(result) = SaturateWordSToByteU(Bit16s(MMXUB7(op1)) + Bit16s(MMXUB7(op2)));
1724 /* now write result back to destination */
1725 BX_WRITE_MMX_REG(i->nnn(), result);
1726 #else
1727 BX_INFO(("PADDUSB_PqQq: required MMX, use --enable-mmx option"));
1728 exception(BX_UD_EXCEPTION, 0, 0);
1729 #endif
1732 /* 0F DD */
1733 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSW_PqQq(bxInstruction_c *i)
1735 #if BX_SUPPORT_MMX
1736 BX_CPU_THIS_PTR prepareMMX();
1738 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1740 /* op2 is a register or memory reference */
1741 if (i->modC0()) {
1742 op2 = BX_READ_MMX_REG(i->rm());
1744 else {
1745 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1746 /* pointer, segment address pair */
1747 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1750 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1752 MMXUW0(result) = SaturateDwordSToWordU(Bit32s(MMXUW0(op1)) + Bit32s(MMXUW0(op2)));
1753 MMXUW1(result) = SaturateDwordSToWordU(Bit32s(MMXUW1(op1)) + Bit32s(MMXUW1(op2)));
1754 MMXUW2(result) = SaturateDwordSToWordU(Bit32s(MMXUW2(op1)) + Bit32s(MMXUW2(op2)));
1755 MMXUW3(result) = SaturateDwordSToWordU(Bit32s(MMXUW3(op1)) + Bit32s(MMXUW3(op2)));
1757 /* now write result back to destination */
1758 BX_WRITE_MMX_REG(i->nnn(), result);
1759 #else
1760 BX_INFO(("PADDUSW_PqQq: required MMX, use --enable-mmx option"));
1761 exception(BX_UD_EXCEPTION, 0, 0);
1762 #endif
1765 /* 0F DE */
1766 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXUB_PqQq(bxInstruction_c *i)
1768 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1769 BX_CPU_THIS_PTR prepareMMX();
1771 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1773 /* op2 is a register or memory reference */
1774 if (i->modC0()) {
1775 op2 = BX_READ_MMX_REG(i->rm());
1777 else {
1778 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1779 /* pointer, segment address pair */
1780 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1783 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1785 if(MMXUB0(op2) > MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2);
1786 if(MMXUB1(op2) > MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2);
1787 if(MMXUB2(op2) > MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2);
1788 if(MMXUB3(op2) > MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2);
1789 if(MMXUB4(op2) > MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2);
1790 if(MMXUB5(op2) > MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2);
1791 if(MMXUB6(op2) > MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2);
1792 if(MMXUB7(op2) > MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2);
1794 /* now write result back to destination */
1795 BX_WRITE_MMX_REG(i->nnn(), op1);
1796 #else
1797 BX_INFO(("PMAXUB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1798 exception(BX_UD_EXCEPTION, 0, 0);
1799 #endif
1802 /* 0F DF */
1803 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PANDN_PqQq(bxInstruction_c *i)
1805 #if BX_SUPPORT_MMX
1806 BX_CPU_THIS_PTR prepareMMX();
1808 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1810 /* op2 is a register or memory reference */
1811 if (i->modC0()) {
1812 op2 = BX_READ_MMX_REG(i->rm());
1814 else {
1815 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1816 /* pointer, segment address pair */
1817 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1820 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1822 MMXUQ(op1) = ~(MMXUQ(op1)) & MMXUQ(op2);
1824 /* now write result back to destination */
1825 BX_WRITE_MMX_REG(i->nnn(), op1);
1826 #else
1827 BX_INFO(("PANDN_PqQq: required MMX, use --enable-mmx option"));
1828 exception(BX_UD_EXCEPTION, 0, 0);
1829 #endif
1832 /* 0F E0 */
1833 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGB_PqQq(bxInstruction_c *i)
1835 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1836 BX_CPU_THIS_PTR prepareMMX();
1838 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1840 /* op2 is a register or memory reference */
1841 if (i->modC0()) {
1842 op2 = BX_READ_MMX_REG(i->rm());
1844 else {
1845 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1846 /* pointer, segment address pair */
1847 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1850 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1852 MMXUB0(op1) = (MMXUB0(op1) + MMXUB0(op2) + 1) >> 1;
1853 MMXUB1(op1) = (MMXUB1(op1) + MMXUB1(op2) + 1) >> 1;
1854 MMXUB2(op1) = (MMXUB2(op1) + MMXUB2(op2) + 1) >> 1;
1855 MMXUB3(op1) = (MMXUB3(op1) + MMXUB3(op2) + 1) >> 1;
1856 MMXUB4(op1) = (MMXUB4(op1) + MMXUB4(op2) + 1) >> 1;
1857 MMXUB5(op1) = (MMXUB5(op1) + MMXUB5(op2) + 1) >> 1;
1858 MMXUB6(op1) = (MMXUB6(op1) + MMXUB6(op2) + 1) >> 1;
1859 MMXUB7(op1) = (MMXUB7(op1) + MMXUB7(op2) + 1) >> 1;
1861 /* now write result back to destination */
1862 BX_WRITE_MMX_REG(i->nnn(), op1);
1863 #else
1864 BX_INFO(("PAVGB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1865 exception(BX_UD_EXCEPTION, 0, 0);
1866 #endif
1869 /* 0F E1 */
1870 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqQq(bxInstruction_c *i)
1872 #if BX_SUPPORT_MMX
1873 BX_CPU_THIS_PTR prepareMMX();
1875 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1877 /* op2 is a register or memory reference */
1878 if (i->modC0()) {
1879 op2 = BX_READ_MMX_REG(i->rm());
1881 else {
1882 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1883 /* pointer, segment address pair */
1884 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1887 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1889 if(!MMXUQ(op2)) return;
1891 if(MMXUQ(op2) > 15) {
1892 MMXUW0(result) = (MMXUW0(op1) & 0x8000) ? 0xffff : 0;
1893 MMXUW1(result) = (MMXUW1(op1) & 0x8000) ? 0xffff : 0;
1894 MMXUW2(result) = (MMXUW2(op1) & 0x8000) ? 0xffff : 0;
1895 MMXUW3(result) = (MMXUW3(op1) & 0x8000) ? 0xffff : 0;
1897 else {
1898 Bit8u shift = MMXUB0(op2);
1900 MMXUW0(result) = MMXUW0(op1) >> shift;
1901 MMXUW1(result) = MMXUW1(op1) >> shift;
1902 MMXUW2(result) = MMXUW2(op1) >> shift;
1903 MMXUW3(result) = MMXUW3(op1) >> shift;
1905 if(MMXUW0(op1) & 0x8000) MMXUW0(result) |= (0xffff << (16 - shift));
1906 if(MMXUW1(op1) & 0x8000) MMXUW1(result) |= (0xffff << (16 - shift));
1907 if(MMXUW2(op1) & 0x8000) MMXUW2(result) |= (0xffff << (16 - shift));
1908 if(MMXUW3(op1) & 0x8000) MMXUW3(result) |= (0xffff << (16 - shift));
1911 /* now write result back to destination */
1912 BX_WRITE_MMX_REG(i->nnn(), result);
1913 #else
1914 BX_INFO(("PSRAW_PqQq: required MMX, use --enable-mmx option"));
1915 exception(BX_UD_EXCEPTION, 0, 0);
1916 #endif
1919 /* 0F E2 */
1920 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqQq(bxInstruction_c *i)
1922 #if BX_SUPPORT_MMX
1923 BX_CPU_THIS_PTR prepareMMX();
1925 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
1927 /* op2 is a register or memory reference */
1928 if (i->modC0()) {
1929 op2 = BX_READ_MMX_REG(i->rm());
1931 else {
1932 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1933 /* pointer, segment address pair */
1934 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1937 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1939 if(!MMXUQ(op2)) return;
1941 if(MMXUQ(op2) > 31) {
1942 MMXUD0(result) = (MMXUD0(op1) & 0x80000000) ? 0xffffffff : 0;
1943 MMXUD1(result) = (MMXUD1(op1) & 0x80000000) ? 0xffffffff : 0;
1945 else {
1946 Bit8u shift = MMXUB0(op2);
1948 MMXUD0(result) = MMXUD0(op1) >> shift;
1949 MMXUD1(result) = MMXUD1(op1) >> shift;
1951 if(MMXUD0(op1) & 0x80000000)
1952 MMXUD0(result) |= (0xffffffff << (32 - shift));
1954 if(MMXUD1(op1) & 0x80000000)
1955 MMXUD1(result) |= (0xffffffff << (32 - shift));
1958 /* now write result back to destination */
1959 BX_WRITE_MMX_REG(i->nnn(), result);
1960 #else
1961 BX_INFO(("PSRAD_PqQq: required MMX, use --enable-mmx option"));
1962 exception(BX_UD_EXCEPTION, 0, 0);
1963 #endif
1966 /* 0F E3 */
1967 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGW_PqQq(bxInstruction_c *i)
1969 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
1970 BX_CPU_THIS_PTR prepareMMX();
1972 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
1974 /* op2 is a register or memory reference */
1975 if (i->modC0()) {
1976 op2 = BX_READ_MMX_REG(i->rm());
1978 else {
1979 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
1980 /* pointer, segment address pair */
1981 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
1984 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
1986 MMXUW0(op1) = (MMXUW0(op1) + MMXUW0(op2) + 1) >> 1;
1987 MMXUW1(op1) = (MMXUW1(op1) + MMXUW1(op2) + 1) >> 1;
1988 MMXUW2(op1) = (MMXUW2(op1) + MMXUW2(op2) + 1) >> 1;
1989 MMXUW3(op1) = (MMXUW3(op1) + MMXUW3(op2) + 1) >> 1;
1991 /* now write result back to destination */
1992 BX_WRITE_MMX_REG(i->nnn(), op1);
1993 #else
1994 BX_INFO(("PAVGW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1995 exception(BX_UD_EXCEPTION, 0, 0);
1996 #endif
1999 /* 0F E4 */
2000 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHUW_PqQq(bxInstruction_c *i)
2002 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2003 BX_CPU_THIS_PTR prepareMMX();
2005 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2007 /* op2 is a register or memory reference */
2008 if (i->modC0()) {
2009 op2 = BX_READ_MMX_REG(i->rm());
2011 else {
2012 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2013 /* pointer, segment address pair */
2014 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2017 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2019 Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2));
2020 Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2));
2021 Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2));
2022 Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2));
2024 MMXUW0(result) = (Bit16u)(product1 >> 16);
2025 MMXUW1(result) = (Bit16u)(product2 >> 16);
2026 MMXUW2(result) = (Bit16u)(product3 >> 16);
2027 MMXUW3(result) = (Bit16u)(product4 >> 16);
2029 /* now write result back to destination */
2030 BX_WRITE_MMX_REG(i->nnn(), result);
2031 #else
2032 BX_INFO(("PMULHUW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2033 exception(BX_UD_EXCEPTION, 0, 0);
2034 #endif
2037 /* 0F E5 */
2038 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHW_PqQq(bxInstruction_c *i)
2040 #if BX_SUPPORT_MMX
2041 BX_CPU_THIS_PTR prepareMMX();
2043 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2045 /* op2 is a register or memory reference */
2046 if (i->modC0()) {
2047 op2 = BX_READ_MMX_REG(i->rm());
2049 else {
2050 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2051 /* pointer, segment address pair */
2052 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2055 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2057 Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2));
2058 Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2));
2059 Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2));
2060 Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2));
2062 MMXUW0(result) = Bit16u(product1 >> 16);
2063 MMXUW1(result) = Bit16u(product2 >> 16);
2064 MMXUW2(result) = Bit16u(product3 >> 16);
2065 MMXUW3(result) = Bit16u(product4 >> 16);
2067 /* now write result back to destination */
2068 BX_WRITE_MMX_REG(i->nnn(), result);
2069 #else
2070 BX_INFO(("PMULHW_PqQq: required MMX, use --enable-mmx option"));
2071 exception(BX_UD_EXCEPTION, 0, 0);
2072 #endif
2075 /* 0F E7 */
2076 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVNTQ_MqPq(bxInstruction_c *i)
2078 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2079 BX_CPU_THIS_PTR prepareMMX();
2080 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2082 BxPackedMmxRegister reg = BX_READ_MMX_REG(i->nnn());
2083 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2084 write_virtual_qword(i->seg(), eaddr, MMXUQ(reg));
2085 #else
2086 BX_INFO(("MOVNTQ_MqPq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2087 exception(BX_UD_EXCEPTION, 0, 0);
2088 #endif
2091 /* 0F E8 */
2092 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSB_PqQq(bxInstruction_c *i)
2094 #if BX_SUPPORT_MMX
2095 BX_CPU_THIS_PTR prepareMMX();
2097 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2099 /* op2 is a register or memory reference */
2100 if (i->modC0()) {
2101 op2 = BX_READ_MMX_REG(i->rm());
2103 else {
2104 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2105 /* pointer, segment address pair */
2106 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2109 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2111 MMXSB0(result) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) - Bit16s(MMXSB0(op2)));
2112 MMXSB1(result) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) - Bit16s(MMXSB1(op2)));
2113 MMXSB2(result) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) - Bit16s(MMXSB2(op2)));
2114 MMXSB3(result) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) - Bit16s(MMXSB3(op2)));
2115 MMXSB4(result) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) - Bit16s(MMXSB4(op2)));
2116 MMXSB5(result) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) - Bit16s(MMXSB5(op2)));
2117 MMXSB6(result) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) - Bit16s(MMXSB6(op2)));
2118 MMXSB7(result) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) - Bit16s(MMXSB7(op2)));
2120 /* now write result back to destination */
2121 BX_WRITE_MMX_REG(i->nnn(), result);
2122 #else
2123 BX_INFO(("PSUBSB_PqQq: required MMX, use --enable-mmx option"));
2124 exception(BX_UD_EXCEPTION, 0, 0);
2125 #endif
2128 /* 0F E9 */
2129 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSW_PqQq(bxInstruction_c *i)
2131 #if BX_SUPPORT_MMX
2132 BX_CPU_THIS_PTR prepareMMX();
2134 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2136 /* op2 is a register or memory reference */
2137 if (i->modC0()) {
2138 op2 = BX_READ_MMX_REG(i->rm());
2140 else {
2141 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2142 /* pointer, segment address pair */
2143 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2146 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2148 MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW0(op2)));
2149 MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) - Bit32s(MMXSW1(op2)));
2150 MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW2(op2)));
2151 MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) - Bit32s(MMXSW3(op2)));
2153 /* now write result back to destination */
2154 BX_WRITE_MMX_REG(i->nnn(), result);
2155 #else
2156 BX_INFO(("PSUBSW_PqQq: required MMX, use --enable-mmx option"));
2157 exception(BX_UD_EXCEPTION, 0, 0);
2158 #endif
2161 /* 0F EA */
2162 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINSW_PqQq(bxInstruction_c *i)
2164 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2165 BX_CPU_THIS_PTR prepareMMX();
2167 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2169 /* op2 is a register or memory reference */
2170 if (i->modC0()) {
2171 op2 = BX_READ_MMX_REG(i->rm());
2173 else {
2174 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2175 /* pointer, segment address pair */
2176 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2179 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2181 if(MMXSW0(op2) < MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2);
2182 if(MMXSW1(op2) < MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2);
2183 if(MMXSW2(op2) < MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2);
2184 if(MMXSW3(op2) < MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2);
2186 /* now write result back to destination */
2187 BX_WRITE_MMX_REG(i->nnn(), op1);
2188 #else
2189 BX_INFO(("PMINSW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2190 exception(BX_UD_EXCEPTION, 0, 0);
2191 #endif
2194 /* 0F EB */
2195 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POR_PqQq(bxInstruction_c *i)
2197 #if BX_SUPPORT_MMX
2198 BX_CPU_THIS_PTR prepareMMX();
2200 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2202 /* op2 is a register or memory reference */
2203 if (i->modC0()) {
2204 op2 = BX_READ_MMX_REG(i->rm());
2206 else {
2207 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2208 /* pointer, segment address pair */
2209 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2212 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2214 MMXUQ(op1) |= MMXUQ(op2);
2216 /* now write result back to destination */
2217 BX_WRITE_MMX_REG(i->nnn(), op1);
2218 #else
2219 BX_INFO(("POR_PqQq: required MMX, use --enable-mmx option"));
2220 exception(BX_UD_EXCEPTION, 0, 0);
2221 #endif
2224 /* 0F EC */
2225 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSB_PqQq(bxInstruction_c *i)
2227 #if BX_SUPPORT_MMX
2228 BX_CPU_THIS_PTR prepareMMX();
2230 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2232 /* op2 is a register or memory reference */
2233 if (i->modC0()) {
2234 op2 = BX_READ_MMX_REG(i->rm());
2236 else {
2237 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2238 /* pointer, segment address pair */
2239 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2242 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2244 MMXSB0(result) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) + Bit16s(MMXSB0(op2)));
2245 MMXSB1(result) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) + Bit16s(MMXSB1(op2)));
2246 MMXSB2(result) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) + Bit16s(MMXSB2(op2)));
2247 MMXSB3(result) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) + Bit16s(MMXSB3(op2)));
2248 MMXSB4(result) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) + Bit16s(MMXSB4(op2)));
2249 MMXSB5(result) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) + Bit16s(MMXSB5(op2)));
2250 MMXSB6(result) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) + Bit16s(MMXSB6(op2)));
2251 MMXSB7(result) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) + Bit16s(MMXSB7(op2)));
2253 /* now write result back to destination */
2254 BX_WRITE_MMX_REG(i->nnn(), result);
2255 #else
2256 BX_INFO(("PADDSB_PqQq: required MMX, use --enable-mmx option"));
2257 exception(BX_UD_EXCEPTION, 0, 0);
2258 #endif
2261 /* 0F ED */
2262 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSW_PqQq(bxInstruction_c *i)
2264 #if BX_SUPPORT_MMX
2265 BX_CPU_THIS_PTR prepareMMX();
2267 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2269 /* op2 is a register or memory reference */
2270 if (i->modC0()) {
2271 op2 = BX_READ_MMX_REG(i->rm());
2273 else {
2274 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2275 /* pointer, segment address pair */
2276 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2279 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2281 MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW0(op2)));
2282 MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) + Bit32s(MMXSW1(op2)));
2283 MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW2(op2)));
2284 MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) + Bit32s(MMXSW3(op2)));
2286 /* now write result back to destination */
2287 BX_WRITE_MMX_REG(i->nnn(), result);
2288 #else
2289 BX_INFO(("PADDSW_PqQq: required MMX, use --enable-mmx option"));
2290 exception(BX_UD_EXCEPTION, 0, 0);
2291 #endif
2294 /* 0F EE */
2295 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXSW_PqQq(bxInstruction_c *i)
2297 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2298 BX_CPU_THIS_PTR prepareMMX();
2300 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2302 /* op2 is a register or memory reference */
2303 if (i->modC0()) {
2304 op2 = BX_READ_MMX_REG(i->rm());
2306 else {
2307 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2308 /* pointer, segment address pair */
2309 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2312 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2314 if(MMXSW0(op2) > MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2);
2315 if(MMXSW1(op2) > MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2);
2316 if(MMXSW2(op2) > MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2);
2317 if(MMXSW3(op2) > MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2);
2319 /* now write result back to destination */
2320 BX_WRITE_MMX_REG(i->nnn(), op1);
2321 #else
2322 BX_INFO(("PMAXSW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2323 exception(BX_UD_EXCEPTION, 0, 0);
2324 #endif
2327 /* 0F EF */
2328 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PXOR_PqQq(bxInstruction_c *i)
2330 #if BX_SUPPORT_MMX
2331 BX_CPU_THIS_PTR prepareMMX();
2333 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2335 /* op2 is a register or memory reference */
2336 if (i->modC0()) {
2337 op2 = BX_READ_MMX_REG(i->rm());
2339 else {
2340 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2341 /* pointer, segment address pair */
2342 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2345 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2347 MMXUQ(op1) ^= MMXUQ(op2);
2349 /* now write result back to destination */
2350 BX_WRITE_MMX_REG(i->nnn(), op1);
2351 #else
2352 BX_INFO(("PXOR_PqQq: required MMX, use --enable-mmx option"));
2353 exception(BX_UD_EXCEPTION, 0, 0);
2354 #endif
2357 /* 0F F1 */
2358 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqQq(bxInstruction_c *i)
2360 #if BX_SUPPORT_MMX
2361 BX_CPU_THIS_PTR prepareMMX();
2363 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2365 /* op2 is a register or memory reference */
2366 if (i->modC0()) {
2367 op2 = BX_READ_MMX_REG(i->rm());
2369 else {
2370 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2371 /* pointer, segment address pair */
2372 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2375 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2377 if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
2378 else
2380 Bit8u shift = MMXUB0(op2);
2382 MMXUW0(op1) <<= shift;
2383 MMXUW1(op1) <<= shift;
2384 MMXUW2(op1) <<= shift;
2385 MMXUW3(op1) <<= shift;
2388 /* now write result back to destination */
2389 BX_WRITE_MMX_REG(i->nnn(), op1);
2390 #else
2391 BX_INFO(("PSLLW_PqQq: required MMX, use --enable-mmx option"));
2392 exception(BX_UD_EXCEPTION, 0, 0);
2393 #endif
2396 /* 0F F2 */
2397 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqQq(bxInstruction_c *i)
2399 #if BX_SUPPORT_MMX
2400 BX_CPU_THIS_PTR prepareMMX();
2402 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2404 /* op2 is a register or memory reference */
2405 if (i->modC0()) {
2406 op2 = BX_READ_MMX_REG(i->rm());
2408 else {
2409 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2410 /* pointer, segment address pair */
2411 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2414 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2416 if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
2417 else
2419 Bit8u shift = MMXUB0(op2);
2421 MMXUD0(op1) <<= shift;
2422 MMXUD1(op1) <<= shift;
2425 /* now write result back to destination */
2426 BX_WRITE_MMX_REG(i->nnn(), op1);
2427 #else
2428 BX_INFO(("PSLLD_PqQq: required MMX, use --enable-mmx option"));
2429 exception(BX_UD_EXCEPTION, 0, 0);
2430 #endif
2433 /* 0F F3 */
2434 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqQq(bxInstruction_c *i)
2436 #if BX_SUPPORT_MMX
2437 BX_CPU_THIS_PTR prepareMMX();
2439 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2441 /* op2 is a register or memory reference */
2442 if (i->modC0()) {
2443 op2 = BX_READ_MMX_REG(i->rm());
2445 else {
2446 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2447 /* pointer, segment address pair */
2448 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2451 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2453 if(MMXUQ(op2) > 63) {
2454 MMXUQ(op1) = 0;
2456 else {
2457 MMXUQ(op1) <<= MMXUB0(op2);
2460 /* now write result back to destination */
2461 BX_WRITE_MMX_REG(i->nnn(), op1);
2462 #else
2463 BX_INFO(("PSLLQ_PqQq: required MMX, use --enable-mmx option"));
2464 exception(BX_UD_EXCEPTION, 0, 0);
2465 #endif
2468 /* 0F F4 */
2469 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULUDQ_PqQq(bxInstruction_c *i)
2471 #if BX_SUPPORT_SSE >= 2
2472 BX_CPU_THIS_PTR prepareMMX();
2474 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2476 /* op2 is a register or memory reference */
2477 if (i->modC0()) {
2478 op2 = BX_READ_MMX_REG(i->rm());
2480 else {
2481 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2482 /* pointer, segment address pair */
2483 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2486 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2488 MMXUQ(result) = Bit64u(MMXUD0(op1)) * Bit64u(MMXUD0(op2));
2490 /* now write result back to destination */
2491 BX_WRITE_MMX_REG(i->nnn(), result);
2492 #else
2493 BX_INFO(("PMULUDQ_PqQq: required SSE2, use --enable-sse option"));
2494 exception(BX_UD_EXCEPTION, 0, 0);
2495 #endif
2498 /* 0F F5 */
2499 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDWD_PqQq(bxInstruction_c *i)
2501 #if BX_SUPPORT_MMX
2502 BX_CPU_THIS_PTR prepareMMX();
2504 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result;
2506 /* op2 is a register or memory reference */
2507 if (i->modC0()) {
2508 op2 = BX_READ_MMX_REG(i->rm());
2510 else {
2511 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2512 /* pointer, segment address pair */
2513 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2516 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2518 if(MMXUD0(op1) == 0x80008000 && MMXUD0(op2) == 0x80008000) {
2519 MMXUD0(result) = 0x80000000;
2521 else {
2522 MMXUD0(result) = Bit32s(MMXSW0(op1))*Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op1))*Bit32s(MMXSW1(op2));
2525 if(MMXUD1(op1) == 0x80008000 && MMXUD1(op2) == 0x80008000) {
2526 MMXUD1(result) = 0x80000000;
2528 else {
2529 MMXUD1(result) = Bit32s(MMXSW2(op1))*Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op1))*Bit32s(MMXSW3(op2));
2532 /* now write result back to destination */
2533 BX_WRITE_MMX_REG(i->nnn(), result);
2534 #else
2535 BX_INFO(("PMADDWD_PqQq: required MMX, use --enable-mmx option"));
2536 exception(BX_UD_EXCEPTION, 0, 0);
2537 #endif
2540 /* 0F F6 */
2541 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSADBW_PqQq(bxInstruction_c *i)
2543 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2544 BX_CPU_THIS_PTR prepareMMX();
2546 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2547 Bit16u temp = 0;
2549 /* op2 is a register or memory reference */
2550 if (i->modC0()) {
2551 op2 = BX_READ_MMX_REG(i->rm());
2553 else {
2554 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2555 /* pointer, segment address pair */
2556 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2559 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2561 temp += abs(MMXUB0(op1) - MMXUB0(op2));
2562 temp += abs(MMXUB1(op1) - MMXUB1(op2));
2563 temp += abs(MMXUB2(op1) - MMXUB2(op2));
2564 temp += abs(MMXUB3(op1) - MMXUB3(op2));
2565 temp += abs(MMXUB4(op1) - MMXUB4(op2));
2566 temp += abs(MMXUB5(op1) - MMXUB5(op2));
2567 temp += abs(MMXUB6(op1) - MMXUB6(op2));
2568 temp += abs(MMXUB7(op1) - MMXUB7(op2));
2570 MMXUQ(op1) = (Bit64u) temp;
2572 /* now write result back to destination */
2573 BX_WRITE_MMX_REG(i->nnn(), op1);
2574 #else
2575 BX_INFO(("PSADBW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2576 exception(BX_UD_EXCEPTION, 0, 0);
2577 #endif
2580 /* 0F F7 */
2581 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MASKMOVQ_PqPRq(bxInstruction_c *i)
2583 #if BX_SUPPORT_3DNOW || BX_SUPPORT_SSE >= 1
2585 BX_CPU_THIS_PTR prepareMMX();
2586 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2588 bx_address rdi;
2589 BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn()), tmp,
2590 mask = BX_READ_MMX_REG(i->rm());
2592 #if BX_SUPPORT_X86_64
2593 if (i->as64L()) { /* 64 bit address mode */
2594 rdi = RDI;
2596 else
2597 #endif
2598 if (i->as32L()) {
2599 rdi = EDI;
2601 else { /* 16 bit address mode */
2602 rdi = DI;
2605 if (MMXUQ(mask) == 0) return;
2607 /* do read-modify-write for efficiency */
2608 MMXUQ(tmp) = read_RMW_virtual_qword(i->seg(), rdi);
2610 if(MMXUB0(mask) & 0x80) MMXUB0(tmp) = MMXUB0(op);
2611 if(MMXUB1(mask) & 0x80) MMXUB1(tmp) = MMXUB1(op);
2612 if(MMXUB2(mask) & 0x80) MMXUB2(tmp) = MMXUB2(op);
2613 if(MMXUB3(mask) & 0x80) MMXUB3(tmp) = MMXUB3(op);
2614 if(MMXUB4(mask) & 0x80) MMXUB4(tmp) = MMXUB4(op);
2615 if(MMXUB5(mask) & 0x80) MMXUB5(tmp) = MMXUB5(op);
2616 if(MMXUB6(mask) & 0x80) MMXUB6(tmp) = MMXUB6(op);
2617 if(MMXUB7(mask) & 0x80) MMXUB7(tmp) = MMXUB7(op);
2619 write_RMW_virtual_qword(MMXUQ(tmp));
2620 #else
2621 BX_INFO(("MASKMOVQ_PqPRq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2622 exception(BX_UD_EXCEPTION, 0, 0);
2623 #endif
2626 /* 0F F8 */
2627 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBB_PqQq(bxInstruction_c *i)
2629 #if BX_SUPPORT_MMX
2630 BX_CPU_THIS_PTR prepareMMX();
2632 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2634 /* op2 is a register or memory reference */
2635 if (i->modC0()) {
2636 op2 = BX_READ_MMX_REG(i->rm());
2638 else {
2639 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2640 /* pointer, segment address pair */
2641 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2644 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2646 MMXUB0(op1) -= MMXUB0(op2);
2647 MMXUB1(op1) -= MMXUB1(op2);
2648 MMXUB2(op1) -= MMXUB2(op2);
2649 MMXUB3(op1) -= MMXUB3(op2);
2650 MMXUB4(op1) -= MMXUB4(op2);
2651 MMXUB5(op1) -= MMXUB5(op2);
2652 MMXUB6(op1) -= MMXUB6(op2);
2653 MMXUB7(op1) -= MMXUB7(op2);
2655 /* now write result back to destination */
2656 BX_WRITE_MMX_REG(i->nnn(), op1);
2657 #else
2658 BX_INFO(("PSUBB_PqQq: required MMX, use --enable-mmx option"));
2659 exception(BX_UD_EXCEPTION, 0, 0);
2660 #endif
2663 /* 0F F9 */
2664 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBW_PqQq(bxInstruction_c *i)
2666 #if BX_SUPPORT_MMX
2667 BX_CPU_THIS_PTR prepareMMX();
2669 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2671 /* op2 is a register or memory reference */
2672 if (i->modC0()) {
2673 op2 = BX_READ_MMX_REG(i->rm());
2675 else {
2676 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2677 /* pointer, segment address pair */
2678 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2681 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2683 MMXUW0(op1) -= MMXUW0(op2);
2684 MMXUW1(op1) -= MMXUW1(op2);
2685 MMXUW2(op1) -= MMXUW2(op2);
2686 MMXUW3(op1) -= MMXUW3(op2);
2688 /* now write result back to destination */
2689 BX_WRITE_MMX_REG(i->nnn(), op1);
2690 #else
2691 BX_INFO(("PSUBW_PqQq: required MMX, use --enable-mmx option"));
2692 exception(BX_UD_EXCEPTION, 0, 0);
2693 #endif
2696 /* 0F FA */
2697 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBD_PqQq(bxInstruction_c *i)
2699 #if BX_SUPPORT_MMX
2700 BX_CPU_THIS_PTR prepareMMX();
2702 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2704 /* op2 is a register or memory reference */
2705 if (i->modC0()) {
2706 op2 = BX_READ_MMX_REG(i->rm());
2708 else {
2709 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2710 /* pointer, segment address pair */
2711 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2714 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2716 MMXUD0(op1) -= MMXUD0(op2);
2717 MMXUD1(op1) -= MMXUD1(op2);
2719 /* now write result back to destination */
2720 BX_WRITE_MMX_REG(i->nnn(), op1);
2721 #else
2722 BX_INFO(("PSUBD_PqQq: required MMX, use --enable-mmx option"));
2723 exception(BX_UD_EXCEPTION, 0, 0);
2724 #endif
2727 /* 0F FB */
2728 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBQ_PqQq(bxInstruction_c *i)
2730 #if BX_SUPPORT_SSE >= 2
2731 BX_CPU_THIS_PTR prepareMMX();
2733 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2735 /* op2 is a register or memory reference */
2736 if (i->modC0()) {
2737 op2 = BX_READ_MMX_REG(i->rm());
2739 else {
2740 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2741 /* pointer, segment address pair */
2742 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2745 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2747 MMXUQ(op1) -= MMXUQ(op2);
2749 /* now write result back to destination */
2750 BX_WRITE_MMX_REG(i->nnn(), op1);
2751 #else
2752 BX_INFO(("PSUBQ_PqQq: required SSE2, use --enable-sse option"));
2753 exception(BX_UD_EXCEPTION, 0, 0);
2754 #endif
2757 /* 0F FC */
2758 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDB_PqQq(bxInstruction_c *i)
2760 #if BX_SUPPORT_MMX
2761 BX_CPU_THIS_PTR prepareMMX();
2763 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2765 /* op2 is a register or memory reference */
2766 if (i->modC0()) {
2767 op2 = BX_READ_MMX_REG(i->rm());
2769 else {
2770 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2771 /* pointer, segment address pair */
2772 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2775 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2777 MMXUB0(op1) += MMXUB0(op2);
2778 MMXUB1(op1) += MMXUB1(op2);
2779 MMXUB2(op1) += MMXUB2(op2);
2780 MMXUB3(op1) += MMXUB3(op2);
2781 MMXUB4(op1) += MMXUB4(op2);
2782 MMXUB5(op1) += MMXUB5(op2);
2783 MMXUB6(op1) += MMXUB6(op2);
2784 MMXUB7(op1) += MMXUB7(op2);
2786 /* now write result back to destination */
2787 BX_WRITE_MMX_REG(i->nnn(), op1);
2788 #else
2789 BX_INFO(("PADDB_PqQq: required MMX, use --enable-mmx option"));
2790 exception(BX_UD_EXCEPTION, 0, 0);
2791 #endif
2794 /* 0F FD */
2795 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDW_PqQq(bxInstruction_c *i)
2797 #if BX_SUPPORT_MMX
2798 BX_CPU_THIS_PTR prepareMMX();
2800 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2802 /* op2 is a register or memory reference */
2803 if (i->modC0()) {
2804 op2 = BX_READ_MMX_REG(i->rm());
2806 else {
2807 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2808 /* pointer, segment address pair */
2809 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2812 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2814 MMXUW0(op1) += MMXUW0(op2);
2815 MMXUW1(op1) += MMXUW1(op2);
2816 MMXUW2(op1) += MMXUW2(op2);
2817 MMXUW3(op1) += MMXUW3(op2);
2819 /* now write result back to destination */
2820 BX_WRITE_MMX_REG(i->nnn(), op1);
2821 #else
2822 BX_INFO(("PADDW_PqQq: required MMX, use --enable-mmx option"));
2823 exception(BX_UD_EXCEPTION, 0, 0);
2824 #endif
2827 /* 0F FE */
2828 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDD_PqQq(bxInstruction_c *i)
2830 #if BX_SUPPORT_MMX
2831 BX_CPU_THIS_PTR prepareMMX();
2833 BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2;
2835 /* op2 is a register or memory reference */
2836 if (i->modC0()) {
2837 op2 = BX_READ_MMX_REG(i->rm());
2839 else {
2840 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
2841 /* pointer, segment address pair */
2842 MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr);
2845 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2847 MMXUD0(op1) += MMXUD0(op2);
2848 MMXUD1(op1) += MMXUD1(op2);
2850 /* now write result back to destination */
2851 BX_WRITE_MMX_REG(i->nnn(), op1);
2852 #else
2853 BX_INFO(("PADDD_PqQq: required MMX, use --enable-mmx option"));
2854 exception(BX_UD_EXCEPTION, 0, 0);
2855 #endif
2858 /* 0F 71 GrpA 010 */
2859 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqIb(bxInstruction_c *i)
2861 #if BX_SUPPORT_MMX
2862 BX_CPU_THIS_PTR prepareMMX();
2863 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2865 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
2866 Bit8u shift = i->Ib();
2868 if(shift > 15) MMXUQ(op) = 0;
2869 else
2871 MMXUW0(op) >>= shift;
2872 MMXUW1(op) >>= shift;
2873 MMXUW2(op) >>= shift;
2874 MMXUW3(op) >>= shift;
2877 /* now write result back to destination */
2878 BX_WRITE_MMX_REG(i->rm(), op);
2879 #else
2880 BX_INFO(("PSRLW_PqIb: required MMX, use --enable-mmx option"));
2881 exception(BX_UD_EXCEPTION, 0, 0);
2882 #endif
2885 /* 0F 71 GrpA 100 */
2886 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqIb(bxInstruction_c *i)
2888 #if BX_SUPPORT_MMX
2889 BX_CPU_THIS_PTR prepareMMX();
2890 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2892 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm()), result;
2893 Bit8u shift = i->Ib();
2895 if(shift == 0) return;
2897 if(shift > 15) {
2898 MMXUW0(result) = (MMXUW0(op) & 0x8000) ? 0xffff : 0;
2899 MMXUW1(result) = (MMXUW1(op) & 0x8000) ? 0xffff : 0;
2900 MMXUW2(result) = (MMXUW2(op) & 0x8000) ? 0xffff : 0;
2901 MMXUW3(result) = (MMXUW3(op) & 0x8000) ? 0xffff : 0;
2903 else {
2904 MMXUW0(result) = MMXUW0(op) >> shift;
2905 MMXUW1(result) = MMXUW1(op) >> shift;
2906 MMXUW2(result) = MMXUW2(op) >> shift;
2907 MMXUW3(result) = MMXUW3(op) >> shift;
2909 if(MMXUW0(op) & 0x8000) MMXUW0(result) |= (0xffff << (16 - shift));
2910 if(MMXUW1(op) & 0x8000) MMXUW1(result) |= (0xffff << (16 - shift));
2911 if(MMXUW2(op) & 0x8000) MMXUW2(result) |= (0xffff << (16 - shift));
2912 if(MMXUW3(op) & 0x8000) MMXUW3(result) |= (0xffff << (16 - shift));
2915 /* now write result back to destination */
2916 BX_WRITE_MMX_REG(i->rm(), result);
2917 #else
2918 BX_INFO(("PSRAW_PqIb: required MMX, use --enable-mmx option"));
2919 exception(BX_UD_EXCEPTION, 0, 0);
2920 #endif
2923 /* 0F 71 GrpA 110 */
2924 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqIb(bxInstruction_c *i)
2926 #if BX_SUPPORT_MMX
2927 BX_CPU_THIS_PTR prepareMMX();
2928 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2930 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
2931 Bit8u shift = i->Ib();
2933 if(shift > 15) MMXUQ(op) = 0;
2934 else
2936 MMXUW0(op) <<= shift;
2937 MMXUW1(op) <<= shift;
2938 MMXUW2(op) <<= shift;
2939 MMXUW3(op) <<= shift;
2942 /* now write result back to destination */
2943 BX_WRITE_MMX_REG(i->rm(), op);
2944 #else
2945 BX_INFO(("PSLLW_PqIb: required MMX, use --enable-mmx option"));
2946 exception(BX_UD_EXCEPTION, 0, 0);
2947 #endif
2950 /* 0F 72 GrpA 010 */
2951 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqIb(bxInstruction_c *i)
2953 #if BX_SUPPORT_MMX
2954 BX_CPU_THIS_PTR prepareMMX();
2955 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2957 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
2958 Bit8u shift = i->Ib();
2960 if(shift > 31) MMXUQ(op) = 0;
2961 else
2963 MMXUD0(op) >>= shift;
2964 MMXUD1(op) >>= shift;
2967 /* now write result back to destination */
2968 BX_WRITE_MMX_REG(i->rm(), op);
2969 #else
2970 BX_INFO(("PSRLD_PqIb: required MMX, use --enable-mmx option"));
2971 exception(BX_UD_EXCEPTION, 0, 0);
2972 #endif
2975 /* 0F 72 GrpA 100 */
2976 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqIb(bxInstruction_c *i)
2978 #if BX_SUPPORT_MMX
2979 BX_CPU_THIS_PTR prepareMMX();
2980 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
2982 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm()), result;
2983 Bit8u shift = i->Ib();
2985 if(shift == 0) return;
2987 if(shift > 31) {
2988 MMXUD0(result) = (MMXUD0(op) & 0x80000000) ? 0xffffffff : 0;
2989 MMXUD1(result) = (MMXUD1(op) & 0x80000000) ? 0xffffffff : 0;
2991 else {
2992 MMXUD0(result) = MMXUD0(op) >> shift;
2993 MMXUD1(result) = MMXUD1(op) >> shift;
2995 if(MMXUD0(op) & 0x80000000)
2996 MMXUD0(result) |= (0xffffffff << (32 - shift));
2998 if(MMXUD1(op) & 0x80000000)
2999 MMXUD1(result) |= (0xffffffff << (32 - shift));
3002 /* now write result back to destination */
3003 BX_WRITE_MMX_REG(i->rm(), result);
3004 #else
3005 BX_INFO(("PSRAD_PqIb: required MMX, use --enable-mmx option"));
3006 exception(BX_UD_EXCEPTION, 0, 0);
3007 #endif
3010 /* 0F 72 GrpA 110 */
3011 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqIb(bxInstruction_c *i)
3013 #if BX_SUPPORT_MMX
3014 BX_CPU_THIS_PTR prepareMMX();
3015 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
3017 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
3018 Bit8u shift = i->Ib();
3020 if(shift > 31) MMXUQ(op) = 0;
3021 else
3023 MMXUD0(op) <<= shift;
3024 MMXUD1(op) <<= shift;
3027 /* now write result back to destination */
3028 BX_WRITE_MMX_REG(i->rm(), op);
3029 #else
3030 BX_INFO(("PSLLD_PqIb: required MMX, use --enable-mmx option"));
3031 exception(BX_UD_EXCEPTION, 0, 0);
3032 #endif
3035 /* 0F 73 GrpA 010 */
3036 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqIb(bxInstruction_c *i)
3038 #if BX_SUPPORT_MMX
3039 BX_CPU_THIS_PTR prepareMMX();
3040 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
3042 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
3043 Bit8u shift = i->Ib();
3045 if(shift > 63) {
3046 MMXUQ(op) = 0;
3048 else {
3049 MMXUQ(op) >>= shift;
3052 /* now write result back to destination */
3053 BX_WRITE_MMX_REG(i->rm(), op);
3054 #else
3055 BX_INFO(("PSRLQ_PqIb: required MMX, use --enable-mmx option"));
3056 exception(BX_UD_EXCEPTION, 0, 0);
3057 #endif
3060 /* 0F 73 GrpA 110 */
3061 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqIb(bxInstruction_c *i)
3063 #if BX_SUPPORT_MMX
3064 BX_CPU_THIS_PTR prepareMMX();
3065 BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */
3067 BxPackedMmxRegister op = BX_READ_MMX_REG(i->rm());
3068 Bit8u shift = i->Ib();
3070 if(shift > 63) {
3071 MMXUQ(op) = 0;
3073 else {
3074 MMXUQ(op) <<= shift;
3077 /* now write result back to destination */
3078 BX_WRITE_MMX_REG(i->rm(), op);
3079 #else
3080 BX_INFO(("PSLLQ_PqIb: required MMX, use --enable-mmx option"));
3081 exception(BX_UD_EXCEPTION, 0, 0);
3082 #endif