1 /////////////////////////////////////////////////////////////////////////
2 // $Id: mmx.cc,v 1.83 2008/10/08 11:14:35 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (c) 2002 Stanislav Shwartsman
6 // Written by Stanislav Shwartsman [sshwarts at sourceforge net]
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
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)
42 FPU_TOS
= 0; /* reset FPU Top-Of-Stack */
47 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
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 */
59 op2
= BX_READ_MMX_REG(i
->rm());
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
);
73 result
.mmxubyte(j
) = 0;
75 result
.mmxubyte(j
) = op1
.mmxubyte(mask
& 0x7);
78 BX_WRITE_MMX_REG(i
->nnn(), result
);
80 BX_INFO(("PSHUFB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
81 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
95 op2
= BX_READ_MMX_REG(i
->rm());
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
);
112 BX_INFO(("PHADDW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
113 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
127 op2
= BX_READ_MMX_REG(i
->rm());
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
);
142 BX_INFO(("PHADDD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
143 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
157 op2
= BX_READ_MMX_REG(i
->rm());
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
);
175 BX_INFO(("PHADDSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
176 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
190 op2
= BX_READ_MMX_REG(i
->rm());
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
);
211 BX_INFO(("PMADDUBSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
212 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
226 op2
= BX_READ_MMX_REG(i
->rm());
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
);
244 BX_INFO(("PHSUBSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
245 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
259 op2
= BX_READ_MMX_REG(i
->rm());
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
);
276 BX_INFO(("PHSUBW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
277 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
291 op2
= BX_READ_MMX_REG(i
->rm());
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
);
306 BX_INFO(("PHSUBD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
307 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
321 op2
= BX_READ_MMX_REG(i
->rm());
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
);
338 BX_INFO(("PSIGNB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
339 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
353 op2
= BX_READ_MMX_REG(i
->rm());
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
);
370 BX_INFO(("PSIGNW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
371 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
385 op2
= BX_READ_MMX_REG(i
->rm());
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 */
397 sign
= (MMXSD0(op2
) > 0) - (MMXSD0(op2
) < 0);
399 sign
= (MMXSD1(op2
) > 0) - (MMXSD1(op2
) < 0);
402 BX_WRITE_MMX_REG(i
->nnn(), op1
);
404 BX_INFO(("PSIGND_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
405 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
419 op2
= BX_READ_MMX_REG(i
->rm());
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
);
442 BX_INFO(("PMULHRSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
443 exception(BX_UD_EXCEPTION
, 0, 0);
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
;
456 op
= BX_READ_MMX_REG(i
->rm());
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
);
478 BX_INFO(("PABSB_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
479 exception(BX_UD_EXCEPTION
, 0, 0);
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
;
492 op
= BX_READ_MMX_REG(i
->rm());
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
);
510 BX_INFO(("PABSW_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
511 exception(BX_UD_EXCEPTION
, 0, 0);
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
;
524 op
= BX_READ_MMX_REG(i
->rm());
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
);
540 BX_INFO(("PABSD_PqQq: required SSE3E, use --enable-sse and --enable-sse-extension options"));
541 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
555 op2
= BX_READ_MMX_REG(i
->rm());
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;
568 MMXUQ(result
) = MMXUQ(op2
);
570 MMXUQ(result
) = (MMXUQ(op2
) >> shift
) | (MMXUQ(op1
) << (64-shift
));
572 MMXUQ(result
) = MMXUQ(op1
) >> (shift
-64);
576 /* now write result back to destination */
577 BX_WRITE_MMX_REG(i
->nnn(), result
);
579 BX_INFO(("PALIGNR_PqQqIb: required SSE3E, use --enable-sse and --enable-sse-extension options"));
580 exception(BX_UD_EXCEPTION
, 0, 0);
584 #endif // BX_SUPPORT_SSE >= 4 || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
587 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLBW_PqQd(bxInstruction_c
*i
)
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 */
596 op2
= BX_READ_MMX_REG(i
->rm());
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
);
618 BX_INFO(("PUNPCKLBW_PqQd: required MMX, configure --enable-mmx"));
619 exception(BX_UD_EXCEPTION
, 0, 0);
624 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLWD_PqQd(bxInstruction_c
*i
)
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 */
633 op2
= BX_READ_MMX_REG(i
->rm());
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
);
651 BX_INFO(("PUNPCKLWD_PqQd: required MMX, use --enable-mmx option"));
652 exception(BX_UD_EXCEPTION
, 0, 0);
657 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLDQ_PqQd(bxInstruction_c
*i
)
660 BX_CPU_THIS_PTR
prepareMMX();
662 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
664 /* op2 is a register or memory reference */
666 op2
= BX_READ_MMX_REG(i
->rm());
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
);
681 BX_INFO(("PUNPCKLDQ_PqQd: required MMX, use --enable-mmx option"));
682 exception(BX_UD_EXCEPTION
, 0, 0);
687 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSWB_PqQq(bxInstruction_c
*i
)
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 */
696 op2
= BX_READ_MMX_REG(i
->rm());
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
);
718 BX_INFO(("PACKSSWB_PqQq: required MMX, use --enable-mmx option"));
719 exception(BX_UD_EXCEPTION
, 0, 0);
724 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTB_PqQq(bxInstruction_c
*i
)
727 BX_CPU_THIS_PTR
prepareMMX();
729 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
731 /* op2 is a register or memory reference */
733 op2
= BX_READ_MMX_REG(i
->rm());
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
);
755 BX_INFO(("PCMPGTB_PqQq: required MMX, use --enable-mmx option"));
756 exception(BX_UD_EXCEPTION
, 0, 0);
761 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTW_PqQq(bxInstruction_c
*i
)
764 BX_CPU_THIS_PTR
prepareMMX();
766 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
768 /* op2 is a register or memory reference */
770 op2
= BX_READ_MMX_REG(i
->rm());
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
);
788 BX_INFO(("PCMPGTW_PqQq: required MMX, use --enable-mmx option"));
789 exception(BX_UD_EXCEPTION
, 0, 0);
794 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTD_PqQq(bxInstruction_c
*i
)
797 BX_CPU_THIS_PTR
prepareMMX();
799 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
801 /* op2 is a register or memory reference */
803 op2
= BX_READ_MMX_REG(i
->rm());
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
);
819 BX_INFO(("PCMPGTD_PqQq: required MMX, use --enable-mmx option"));
820 exception(BX_UD_EXCEPTION
, 0, 0);
825 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKUSWB_PqQq(bxInstruction_c
*i
)
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 */
834 op2
= BX_READ_MMX_REG(i
->rm());
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
);
856 BX_INFO(("PACKUSWB_PqQq: required MMX, use --enable-mmx option"));
857 exception(BX_UD_EXCEPTION
, 0, 0);
862 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHBW_PqQq(bxInstruction_c
*i
)
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 */
871 op2
= BX_READ_MMX_REG(i
->rm());
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
);
893 BX_INFO(("PUNPCKHBW_PqQq: required MMX, use --enable-mmx option"));
894 exception(BX_UD_EXCEPTION
, 0, 0);
899 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHWD_PqQq(bxInstruction_c
*i
)
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 */
908 op2
= BX_READ_MMX_REG(i
->rm());
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
);
926 BX_INFO(("PUNPCKHWD_PqQq: required MMX, use --enable-mmx option"));
927 exception(BX_UD_EXCEPTION
, 0, 0);
932 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHDQ_PqQq(bxInstruction_c
*i
)
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 */
941 op2
= BX_READ_MMX_REG(i
->rm());
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
);
957 BX_INFO(("PUNPCKHDQ_PqQq: required MMX, use --enable-mmx option"));
958 exception(BX_UD_EXCEPTION
, 0, 0);
963 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSDW_PqQq(bxInstruction_c
*i
)
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 */
972 op2
= BX_READ_MMX_REG(i
->rm());
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
);
990 BX_INFO(("PACKSSDW_PqQq: required MMX, use --enable-mmx option"));
991 exception(BX_UD_EXCEPTION
, 0, 0);
996 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEd(bxInstruction_c
*i
)
999 BX_CPU_THIS_PTR
prepareMMX();
1001 BxPackedMmxRegister op
;
1005 /* op is a register or memory reference */
1007 MMXUD0(op
) = BX_READ_32BIT_REG(i
->rm());
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
);
1020 BX_INFO(("MOVD_PqEd: required MMX, use --enable-mmx option"));
1021 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1036 MMXUQ(op
) = BX_READ_64BIT_REG(i
->rm());
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
);
1053 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQq(bxInstruction_c
*i
)
1056 BX_CPU_THIS_PTR
prepareMMX();
1058 BxPackedMmxRegister op
;
1060 /* op is a register or memory reference */
1062 op
= BX_READ_MMX_REG(i
->rm());
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
);
1075 BX_INFO(("MOVQ_PqQq: required MMX, use --enable-mmx option"));
1076 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1091 op
= BX_READ_MMX_REG(i
->rm());
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
);
1109 BX_INFO(("PSHUFW_PqQqIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1110 exception(BX_UD_EXCEPTION
, 0, 0);
1115 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQB_PqQq(bxInstruction_c
*i
)
1118 BX_CPU_THIS_PTR
prepareMMX();
1120 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1122 /* op2 is a register or memory reference */
1124 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1146 BX_INFO(("PCMPEQB_PqQq: required MMX, use --enable-mmx option"));
1147 exception(BX_UD_EXCEPTION
, 0, 0);
1152 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQW_PqQq(bxInstruction_c
*i
)
1155 BX_CPU_THIS_PTR
prepareMMX();
1157 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1159 /* op2 is a register or memory reference */
1161 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1179 BX_INFO(("PCMPEQW_PqQq: required MMX, use --enable-mmx option"));
1180 exception(BX_UD_EXCEPTION
, 0, 0);
1185 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQD_PqQq(bxInstruction_c
*i
)
1188 BX_CPU_THIS_PTR
prepareMMX();
1190 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1192 /* op2 is a register or memory reference */
1194 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1210 BX_INFO(("PCMPEQD_PqQq: required MMX, use --enable-mmx option"));
1211 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1223 BX_INFO(("EMMS: required MMX, use --enable-mmx option"));
1224 exception(BX_UD_EXCEPTION
, 0, 0);
1229 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPd(bxInstruction_c
*i
)
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 */
1239 BX_WRITE_32BIT_REGZ(i
->rm(), MMXUD0(op
));
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
));
1247 BX_INFO(("MOVD_EdPd: required MMX, use --enable-mmx option"));
1248 exception(BX_UD_EXCEPTION
, 0, 0);
1252 #if BX_SUPPORT_X86_64
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 */
1264 BX_WRITE_64BIT_REG(i
->rm(), MMXUQ(op
));
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
));
1276 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_QqPq(bxInstruction_c
*i
)
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 */
1286 BX_WRITE_MMX_REG(i
->rm(), op
);
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
));
1294 BX_INFO(("MOVQ_QqPq: required MMX, use --enable-mmx option"));
1295 exception(BX_UD_EXCEPTION
, 0, 0);
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());
1308 /* op2 is a register or memory reference */
1310 op2
= BX_READ_16BIT_REG(i
->rm());
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
);
1325 BX_INFO(("PINSRW_PqEdIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1326 exception(BX_UD_EXCEPTION
, 0, 0);
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
);
1342 BX_INFO(("PEXTRW_GdPqIb: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1343 exception(BX_UD_EXCEPTION
, 0, 0);
1348 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqQq(bxInstruction_c
*i
)
1351 BX_CPU_THIS_PTR
prepareMMX();
1353 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1355 /* op2 is a register or memory reference */
1357 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
1381 BX_INFO(("PSRLW_PqQq: required MMX, use --enable-mmx option"));
1382 exception(BX_UD_EXCEPTION
, 0, 0);
1387 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqQq(bxInstruction_c
*i
)
1390 BX_CPU_THIS_PTR
prepareMMX();
1392 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1394 /* op2 is a register or memory reference */
1396 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
1418 BX_INFO(("PSRLD_PqQq: required MMX, use --enable-mmx option"));
1419 exception(BX_UD_EXCEPTION
, 0, 0);
1424 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqQq(bxInstruction_c
*i
)
1427 BX_CPU_THIS_PTR
prepareMMX();
1429 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1431 /* op2 is a register or memory reference */
1433 op2
= BX_READ_MMX_REG(i
->rm());
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) {
1447 MMXUQ(op1
) >>= MMXUB0(op2
);
1450 /* now write result back to destination */
1451 BX_WRITE_MMX_REG(i
->nnn(), op1
);
1453 BX_INFO(("PSRLQ_PqQq: required MMX, use --enable-mmx option"));
1454 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1468 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1483 BX_INFO(("PADDQ_PqQq: required SSE2, use --enable-sse option"));
1484 exception(BX_UD_EXCEPTION
, 0, 0);
1489 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULLW_PqQq(bxInstruction_c
*i
)
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 */
1498 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1521 BX_INFO(("PMULLW_PqQq: required MMX, use --enable-mmx option"));
1522 exception(BX_UD_EXCEPTION
, 0, 0);
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());
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
);
1549 BX_INFO(("PMOVMSKB_GdPRq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1550 exception(BX_UD_EXCEPTION
, 0, 0);
1555 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSB_PqQq(bxInstruction_c
*i
)
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 */
1564 op2
= BX_READ_MMX_REG(i
->rm());
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 */
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
);
1588 BX_INFO(("PSUBUSB_PqQq: required MMX, use --enable-mmx option"));
1589 exception(BX_UD_EXCEPTION
, 0, 0);
1594 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSW_PqQq(bxInstruction_c
*i
)
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 */
1603 op2
= BX_READ_MMX_REG(i
->rm());
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 */
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
);
1623 BX_INFO(("PSUBUSW_PqQq: required MMX, use --enable-mmx option"));
1624 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1638 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1660 BX_INFO(("PMINUB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1661 exception(BX_UD_EXCEPTION
, 0, 0);
1666 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PAND_PqQq(bxInstruction_c
*i
)
1669 BX_CPU_THIS_PTR
prepareMMX();
1671 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1673 /* op2 is a register or memory reference */
1675 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1690 BX_INFO(("PAND_PqQq: required MMX, use --enable-mmx option"));
1691 exception(BX_UD_EXCEPTION
, 0, 0);
1696 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSB_PqQq(bxInstruction_c
*i
)
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 */
1705 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1727 BX_INFO(("PADDUSB_PqQq: required MMX, use --enable-mmx option"));
1728 exception(BX_UD_EXCEPTION
, 0, 0);
1733 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSW_PqQq(bxInstruction_c
*i
)
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 */
1742 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1760 BX_INFO(("PADDUSW_PqQq: required MMX, use --enable-mmx option"));
1761 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1775 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1797 BX_INFO(("PMAXUB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1798 exception(BX_UD_EXCEPTION
, 0, 0);
1803 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PANDN_PqQq(bxInstruction_c
*i
)
1806 BX_CPU_THIS_PTR
prepareMMX();
1808 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
1810 /* op2 is a register or memory reference */
1812 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1827 BX_INFO(("PANDN_PqQq: required MMX, use --enable-mmx option"));
1828 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1842 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1864 BX_INFO(("PAVGB_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1865 exception(BX_UD_EXCEPTION
, 0, 0);
1870 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqQq(bxInstruction_c
*i
)
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 */
1879 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
1914 BX_INFO(("PSRAW_PqQq: required MMX, use --enable-mmx option"));
1915 exception(BX_UD_EXCEPTION
, 0, 0);
1920 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqQq(bxInstruction_c
*i
)
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 */
1929 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
1961 BX_INFO(("PSRAD_PqQq: required MMX, use --enable-mmx option"));
1962 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
1976 op2
= BX_READ_MMX_REG(i
->rm());
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
);
1994 BX_INFO(("PAVGW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
1995 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
2009 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2032 BX_INFO(("PMULHUW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2033 exception(BX_UD_EXCEPTION
, 0, 0);
2038 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHW_PqQq(bxInstruction_c
*i
)
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 */
2047 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2070 BX_INFO(("PMULHW_PqQq: required MMX, use --enable-mmx option"));
2071 exception(BX_UD_EXCEPTION
, 0, 0);
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
));
2086 BX_INFO(("MOVNTQ_MqPq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2087 exception(BX_UD_EXCEPTION
, 0, 0);
2092 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSB_PqQq(bxInstruction_c
*i
)
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 */
2101 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2123 BX_INFO(("PSUBSB_PqQq: required MMX, use --enable-mmx option"));
2124 exception(BX_UD_EXCEPTION
, 0, 0);
2129 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSW_PqQq(bxInstruction_c
*i
)
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 */
2138 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2156 BX_INFO(("PSUBSW_PqQq: required MMX, use --enable-mmx option"));
2157 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
2171 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2189 BX_INFO(("PMINSW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2190 exception(BX_UD_EXCEPTION
, 0, 0);
2195 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POR_PqQq(bxInstruction_c
*i
)
2198 BX_CPU_THIS_PTR
prepareMMX();
2200 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2202 /* op2 is a register or memory reference */
2204 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2219 BX_INFO(("POR_PqQq: required MMX, use --enable-mmx option"));
2220 exception(BX_UD_EXCEPTION
, 0, 0);
2225 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSB_PqQq(bxInstruction_c
*i
)
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 */
2234 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2256 BX_INFO(("PADDSB_PqQq: required MMX, use --enable-mmx option"));
2257 exception(BX_UD_EXCEPTION
, 0, 0);
2262 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSW_PqQq(bxInstruction_c
*i
)
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 */
2271 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2289 BX_INFO(("PADDSW_PqQq: required MMX, use --enable-mmx option"));
2290 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
2304 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2322 BX_INFO(("PMAXSW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2323 exception(BX_UD_EXCEPTION
, 0, 0);
2328 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PXOR_PqQq(bxInstruction_c
*i
)
2331 BX_CPU_THIS_PTR
prepareMMX();
2333 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2335 /* op2 is a register or memory reference */
2337 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2352 BX_INFO(("PXOR_PqQq: required MMX, use --enable-mmx option"));
2353 exception(BX_UD_EXCEPTION
, 0, 0);
2358 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqQq(bxInstruction_c
*i
)
2361 BX_CPU_THIS_PTR
prepareMMX();
2363 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2365 /* op2 is a register or memory reference */
2367 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
2391 BX_INFO(("PSLLW_PqQq: required MMX, use --enable-mmx option"));
2392 exception(BX_UD_EXCEPTION
, 0, 0);
2397 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqQq(bxInstruction_c
*i
)
2400 BX_CPU_THIS_PTR
prepareMMX();
2402 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2404 /* op2 is a register or memory reference */
2406 op2
= BX_READ_MMX_REG(i
->rm());
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;
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
);
2428 BX_INFO(("PSLLD_PqQq: required MMX, use --enable-mmx option"));
2429 exception(BX_UD_EXCEPTION
, 0, 0);
2434 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqQq(bxInstruction_c
*i
)
2437 BX_CPU_THIS_PTR
prepareMMX();
2439 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2441 /* op2 is a register or memory reference */
2443 op2
= BX_READ_MMX_REG(i
->rm());
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) {
2457 MMXUQ(op1
) <<= MMXUB0(op2
);
2460 /* now write result back to destination */
2461 BX_WRITE_MMX_REG(i
->nnn(), op1
);
2463 BX_INFO(("PSLLQ_PqQq: required MMX, use --enable-mmx option"));
2464 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
2478 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2493 BX_INFO(("PMULUDQ_PqQq: required SSE2, use --enable-sse option"));
2494 exception(BX_UD_EXCEPTION
, 0, 0);
2499 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDWD_PqQq(bxInstruction_c
*i
)
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 */
2508 op2
= BX_READ_MMX_REG(i
->rm());
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;
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;
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
);
2535 BX_INFO(("PMADDWD_PqQq: required MMX, use --enable-mmx option"));
2536 exception(BX_UD_EXCEPTION
, 0, 0);
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
;
2549 /* op2 is a register or memory reference */
2551 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2575 BX_INFO(("PSADBW_PqQq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2576 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
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 */
2601 else { /* 16 bit address mode */
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
));
2621 BX_INFO(("MASKMOVQ_PqPRq: required SSE or 3DNOW, use --enable-sse or --enable-3dnow options"));
2622 exception(BX_UD_EXCEPTION
, 0, 0);
2627 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBB_PqQq(bxInstruction_c
*i
)
2630 BX_CPU_THIS_PTR
prepareMMX();
2632 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2634 /* op2 is a register or memory reference */
2636 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2658 BX_INFO(("PSUBB_PqQq: required MMX, use --enable-mmx option"));
2659 exception(BX_UD_EXCEPTION
, 0, 0);
2664 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBW_PqQq(bxInstruction_c
*i
)
2667 BX_CPU_THIS_PTR
prepareMMX();
2669 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2671 /* op2 is a register or memory reference */
2673 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2691 BX_INFO(("PSUBW_PqQq: required MMX, use --enable-mmx option"));
2692 exception(BX_UD_EXCEPTION
, 0, 0);
2697 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBD_PqQq(bxInstruction_c
*i
)
2700 BX_CPU_THIS_PTR
prepareMMX();
2702 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2704 /* op2 is a register or memory reference */
2706 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2722 BX_INFO(("PSUBD_PqQq: required MMX, use --enable-mmx option"));
2723 exception(BX_UD_EXCEPTION
, 0, 0);
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 */
2737 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2752 BX_INFO(("PSUBQ_PqQq: required SSE2, use --enable-sse option"));
2753 exception(BX_UD_EXCEPTION
, 0, 0);
2758 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDB_PqQq(bxInstruction_c
*i
)
2761 BX_CPU_THIS_PTR
prepareMMX();
2763 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2765 /* op2 is a register or memory reference */
2767 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2789 BX_INFO(("PADDB_PqQq: required MMX, use --enable-mmx option"));
2790 exception(BX_UD_EXCEPTION
, 0, 0);
2795 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDW_PqQq(bxInstruction_c
*i
)
2798 BX_CPU_THIS_PTR
prepareMMX();
2800 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2802 /* op2 is a register or memory reference */
2804 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2822 BX_INFO(("PADDW_PqQq: required MMX, use --enable-mmx option"));
2823 exception(BX_UD_EXCEPTION
, 0, 0);
2828 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDD_PqQq(bxInstruction_c
*i
)
2831 BX_CPU_THIS_PTR
prepareMMX();
2833 BxPackedMmxRegister op1
= BX_READ_MMX_REG(i
->nnn()), op2
;
2835 /* op2 is a register or memory reference */
2837 op2
= BX_READ_MMX_REG(i
->rm());
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
);
2853 BX_INFO(("PADDD_PqQq: required MMX, use --enable-mmx option"));
2854 exception(BX_UD_EXCEPTION
, 0, 0);
2858 /* 0F 71 GrpA 010 */
2859 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqIb(bxInstruction_c
*i
)
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;
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
);
2880 BX_INFO(("PSRLW_PqIb: required MMX, use --enable-mmx option"));
2881 exception(BX_UD_EXCEPTION
, 0, 0);
2885 /* 0F 71 GrpA 100 */
2886 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqIb(bxInstruction_c
*i
)
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;
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;
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
);
2918 BX_INFO(("PSRAW_PqIb: required MMX, use --enable-mmx option"));
2919 exception(BX_UD_EXCEPTION
, 0, 0);
2923 /* 0F 71 GrpA 110 */
2924 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqIb(bxInstruction_c
*i
)
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;
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
);
2945 BX_INFO(("PSLLW_PqIb: required MMX, use --enable-mmx option"));
2946 exception(BX_UD_EXCEPTION
, 0, 0);
2950 /* 0F 72 GrpA 010 */
2951 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqIb(bxInstruction_c
*i
)
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;
2963 MMXUD0(op
) >>= shift
;
2964 MMXUD1(op
) >>= shift
;
2967 /* now write result back to destination */
2968 BX_WRITE_MMX_REG(i
->rm(), op
);
2970 BX_INFO(("PSRLD_PqIb: required MMX, use --enable-mmx option"));
2971 exception(BX_UD_EXCEPTION
, 0, 0);
2975 /* 0F 72 GrpA 100 */
2976 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqIb(bxInstruction_c
*i
)
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;
2988 MMXUD0(result
) = (MMXUD0(op
) & 0x80000000) ? 0xffffffff : 0;
2989 MMXUD1(result
) = (MMXUD1(op
) & 0x80000000) ? 0xffffffff : 0;
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
);
3005 BX_INFO(("PSRAD_PqIb: required MMX, use --enable-mmx option"));
3006 exception(BX_UD_EXCEPTION
, 0, 0);
3010 /* 0F 72 GrpA 110 */
3011 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqIb(bxInstruction_c
*i
)
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;
3023 MMXUD0(op
) <<= shift
;
3024 MMXUD1(op
) <<= shift
;
3027 /* now write result back to destination */
3028 BX_WRITE_MMX_REG(i
->rm(), op
);
3030 BX_INFO(("PSLLD_PqIb: required MMX, use --enable-mmx option"));
3031 exception(BX_UD_EXCEPTION
, 0, 0);
3035 /* 0F 73 GrpA 010 */
3036 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqIb(bxInstruction_c
*i
)
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();
3049 MMXUQ(op
) >>= shift
;
3052 /* now write result back to destination */
3053 BX_WRITE_MMX_REG(i
->rm(), op
);
3055 BX_INFO(("PSRLQ_PqIb: required MMX, use --enable-mmx option"));
3056 exception(BX_UD_EXCEPTION
, 0, 0);
3060 /* 0F 73 GrpA 110 */
3061 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqIb(bxInstruction_c
*i
)
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();
3074 MMXUQ(op
) <<= shift
;
3077 /* now write result back to destination */
3078 BX_WRITE_MMX_REG(i
->rm(), op
);
3080 BX_INFO(("PSLLQ_PqIb: required MMX, use --enable-mmx option"));
3081 exception(BX_UD_EXCEPTION
, 0, 0);