Bochs/bochs/patches/bochs-1.4.1-mmx.patch-endian-support
Stanislav Shwartsman 21413f26aa MMX support patch
Now with BIG_ENDIAN systems compatability
Tested on HP1100 and Solaris systems
(for Bochs 1.4.1 release)
2002-09-04 19:30:09 +00:00

2824 lines
85 KiB
Plaintext

----------------------------------------------------------------------
Patch name: bochs-1.4.1-mmx.patch-endian-support
Author: Stanislav Shwartsman
Date: 01/09/2002
Detailed description: MMX instruction set support.
Also supports BIG_ENDIAN systems. Tested on Solaris and HP1100.
Patch was created with:
cvs diff -u
Apply patch to what version:
cvs checked out on DATE, release version VER
Instructions:
To patch, go to main bochs directory.
Type "patch -p0 < THIS_PATCH_FILE".
----------------------------------------------------------------------
diff -r -u -N bochs-1.4.1/config.h.in bochs-1.4.1-mmx-release-endian/config.h.in
--- bochs-1.4.1/config.h.in 2002-06-24 00:19:42.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/config.h.in 2002-08-25 13:41:34.000000000 +0200
@@ -533,6 +533,7 @@
#define BX_DYNAMIC_CPU_SPARC 0
#define BX_SUPPORT_FPU 0
+#define BX_SUPPORT_MMX 1
#define BX_HAVE_GETENV 0
#define BX_HAVE_SELECT 0
diff -r -u -N bochs-1.4.1/cpu/Makefile.in bochs-1.4.1-mmx-release-endian/cpu/Makefile.in
--- bochs-1.4.1/cpu/Makefile.in 2001-10-07 22:19:04.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/Makefile.in 2002-08-24 18:05:28.000000000 +0200
@@ -48,7 +48,7 @@
OBJS = \
init.o \
access.o \
- cpu.o resolve32.o fetchdecode.o \
+ cpu.o mmx.o resolve32.o fetchdecode.o \
exception.o \
ctrl_xfer_pro.o \
flag_ctrl_pro.o \
@@ -198,6 +198,16 @@
../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
../iodev/guest2host.h ../iodev/slowdown_timer.h \
../instrument/stubs/instrument.h
+mmx.o: mmx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../debug/debug.h \
+ ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
+ ../cpu/lazy_flags.h ../memory/memory.h ../pc_system.h ../gui/gui.h \
+ ../gui/control.h ../iodev/iodev.h ../iodev/pci.h ../iodev/vga.h \
+ ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
+ ../iodev/keyboard.h ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h \
+ ../iodev/pit_wrap.h ../iodev/pit82c54.h ../iodev/serial.h \
+ ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
+ ../iodev/guest2host.h ../iodev/slowdown_timer.h \
+ ../instrument/stubs/instrument.h
ctrl_xfer16.o: ctrl_xfer16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
../debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
../cpu/cpu.h ../cpu/lazy_flags.h ../memory/memory.h ../pc_system.h \
diff -r -u -N bochs-1.4.1/cpu/access.cc bochs-1.4.1-mmx-release-endian/cpu/access.cc
--- bochs-1.4.1/cpu/access.cc 2001-10-03 15:10:38.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/access.cc 2002-08-24 18:17:36.000000000 +0200
@@ -228,105 +228,84 @@
}
}
-
-
-
void
-BX_CPU_C::write_virtual_byte(unsigned s, Bit32u offset, Bit8u *data)
+BX_CPU_C::write_virtual(unsigned s, Bit32u offset, unsigned len, void *data)
{
Bit32u laddr;
bx_segment_reg_t *seg;
seg = &BX_CPU_THIS_PTR sregs[s];
- write_virtual_checks(seg, offset, 1);
+ write_virtual_checks(seg, offset, len);
laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 1, BX_WRITE);
+ BX_INSTR_MEM_DATA(laddr, len, BX_WRITE);
// all checks OK
- access_linear(laddr, 1, CPL==3, BX_WRITE, (void *) data);
+ access_linear(laddr, len, CPL==3, BX_WRITE, data);
}
void
-BX_CPU_C::write_virtual_word(unsigned s, Bit32u offset, Bit16u *data)
+BX_CPU_C::write_virtual_byte(unsigned s, Bit32u offset, Bit8u *data)
{
- Bit32u laddr;
- bx_segment_reg_t *seg;
-
- seg = &BX_CPU_THIS_PTR sregs[s];
- write_virtual_checks(seg, offset, 2);
-
- laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 2, BX_WRITE);
+ write_virtual(s, offset, 1, (void*) data);
+}
- // all checks OK
- access_linear(laddr, 2, CPL==3, BX_WRITE, (void *) data);
+ void
+BX_CPU_C::write_virtual_word(unsigned s, Bit32u offset, Bit16u *data)
+{
+ write_virtual(s, offset, 2, (void*) data);
}
void
BX_CPU_C::write_virtual_dword(unsigned s, Bit32u offset, Bit32u *data)
{
- Bit32u laddr;
- bx_segment_reg_t *seg;
-
- seg = &BX_CPU_THIS_PTR sregs[s];
- write_virtual_checks(seg, offset, 4);
-
- laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 4, BX_WRITE);
-
- // all checks OK
- access_linear(laddr, 4, CPL==3, BX_WRITE, (void *) data);
+ write_virtual(s, offset, 4, (void*) data);
}
void
-BX_CPU_C::read_virtual_byte(unsigned s, Bit32u offset, Bit8u *data)
+BX_CPU_C::write_virtual_qword(unsigned s, Bit32u offset, Bit64u *data)
+{
+ write_virtual(s, offset, 8, (void*) data);
+}
+
+ void
+BX_CPU_C::read_virtual(unsigned s, Bit32u offset, unsigned len, void *data)
{
Bit32u laddr;
bx_segment_reg_t *seg;
seg = &BX_CPU_THIS_PTR sregs[s];
- read_virtual_checks(seg, offset, 1);
+ read_virtual_checks(seg, offset, len);
laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 1, BX_READ);
+ BX_INSTR_MEM_DATA(laddr, len, BX_READ);
// all checks OK
- access_linear(laddr, 1, CPL==3, BX_READ, (void *) data);
+ access_linear(laddr, len, CPL==3, BX_READ, data);
}
+ void
+BX_CPU_C::read_virtual_byte(unsigned s, Bit32u offset, Bit8u *data)
+{
+ read_virtual(s, offset, 1, (void*) data);
+}
void
BX_CPU_C::read_virtual_word(unsigned s, Bit32u offset, Bit16u *data)
{
- Bit32u laddr;
- bx_segment_reg_t *seg;
-
- seg = &BX_CPU_THIS_PTR sregs[s];
- read_virtual_checks(seg, offset, 2);
-
- laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 2, BX_READ);
-
- // all checks OK
- access_linear(laddr, 2, CPL==3, BX_READ, (void *) data);
+ read_virtual(s, offset, 2, (void*) data);
}
-
void
BX_CPU_C::read_virtual_dword(unsigned s, Bit32u offset, Bit32u *data)
{
- Bit32u laddr;
- bx_segment_reg_t *seg;
-
- seg = &BX_CPU_THIS_PTR sregs[s];
- read_virtual_checks(seg, offset, 4);
-
- laddr = seg->cache.u.segment.base + offset;
- BX_INSTR_MEM_DATA(laddr, 4, BX_READ);
+ read_virtual(s, offset, 4, (void*) data);
+}
- // all checks OK
- access_linear(laddr, 4, CPL==3, BX_READ, (void *) data);
+ void
+BX_CPU_C::read_virtual_qword(unsigned s, Bit32u offset, Bit64u *data)
+{
+ read_virtual(s, offset, 8, (void*) data);
}
//////////////////////////////////////////////////////////////
diff -r -u -N bochs-1.4.1/cpu/cpu.h bochs-1.4.1-mmx-release-endian/cpu/cpu.h
--- bochs-1.4.1/cpu/cpu.h 2002-07-16 22:01:29.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/cpu.h 2002-08-29 19:53:51.000000000 +0200
@@ -707,6 +707,8 @@
class BX_MEM_C;
+#include "cpu/i387.h"
+
class BX_CPU_C : public logfunctions {
public: // for now...
@@ -808,6 +810,8 @@
bx_regs_msr_t msr;
#endif
+ i387_t the_i387;
+
// pointer to the address space that this processor uses.
BX_MEM_C *mem;
@@ -1267,6 +1271,71 @@
BX_SMF void ESC6(BxInstruction_t *);
BX_SMF void ESC7(BxInstruction_t *);
+ /* MMX */
+ BX_SMF void PUNPCKLBW_PqQd(BxInstruction_t *i);
+ BX_SMF void PUNPCKLWD_PqQd(BxInstruction_t *i);
+ BX_SMF void PUNPCKLDQ_PqQd(BxInstruction_t *i);
+ BX_SMF void PACKSSWB_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPGTB_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPGTW_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPGTD_PqQq(BxInstruction_t *i);
+ BX_SMF void PACKUSWB_PqQq(BxInstruction_t *i);
+ BX_SMF void PUNPCKHBW_PqQq(BxInstruction_t *i);
+ BX_SMF void PUNPCKHWD_PqQq(BxInstruction_t *i);
+ BX_SMF void PUNPCKHDQ_PqQq(BxInstruction_t *i);
+ BX_SMF void PACKSSDW_PqQq(BxInstruction_t *i);
+ BX_SMF void MOVD_PqEd(BxInstruction_t *i);
+ BX_SMF void MOVQ_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPEQB_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPEQW_PqQq(BxInstruction_t *i);
+ BX_SMF void PCMPEQD_PqQq(BxInstruction_t *i);
+ BX_SMF void EMMS(BxInstruction_t *i);
+ BX_SMF void MOVD_EdPd(BxInstruction_t *i);
+ BX_SMF void MOVQ_QqPq(BxInstruction_t *i);
+ BX_SMF void PSRLW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSRLD_PqQq(BxInstruction_t *i);
+ BX_SMF void PSRLQ_PqQq(BxInstruction_t *i);
+ BX_SMF void PMULLW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBUSB_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBUSW_PqQq(BxInstruction_t *i);
+ BX_SMF void PAND_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDUSB_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDUSW_PqQq(BxInstruction_t *i);
+ BX_SMF void PANDN_PqQq(BxInstruction_t *i);
+ BX_SMF void PSRAW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSRAD_PqQq(BxInstruction_t *i);
+ BX_SMF void PMULHW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBSB_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBSW_PqQq(BxInstruction_t *i);
+ BX_SMF void POR_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDSB_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDSW_PqQq(BxInstruction_t *i);
+ BX_SMF void PXOR_PqQq(BxInstruction_t *i);
+ BX_SMF void PSLLW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSLLD_PqQq(BxInstruction_t *i);
+ BX_SMF void PSLLQ_PqQq(BxInstruction_t *i);
+ BX_SMF void PMADDWD_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBB_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBW_PqQq(BxInstruction_t *i);
+ BX_SMF void PSUBD_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDB_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDW_PqQq(BxInstruction_t *i);
+ BX_SMF void PADDD_PqQq(BxInstruction_t *i);
+ BX_SMF void PSRLW_PqIb(BxInstruction_t *i);
+ BX_SMF void PSRAW_PqIb(BxInstruction_t *i);
+ BX_SMF void PSLLW_PqIb(BxInstruction_t *i);
+ BX_SMF void PSRLD_PqIb(BxInstruction_t *i);
+ BX_SMF void PSRAD_PqIb(BxInstruction_t *i);
+ BX_SMF void PSLLD_PqIb(BxInstruction_t *i);
+ BX_SMF void PSRLQ_PqIb(BxInstruction_t *i);
+ BX_SMF void PSLLQ_PqIb(BxInstruction_t *i);
+ /* MMX */
+
+#if BX_SUPPORT_MMX
+ BX_SMF void PrepareMmxInstruction(void);
+ BX_SMF void PrintMmxRegisters(void);
+#endif
+
BX_SMF void fpu_execute(BxInstruction_t *i);
BX_SMF void fpu_init(void);
BX_SMF void fpu_print_regs (void);
@@ -1439,14 +1508,18 @@
BX_SMF void revalidate_prefetch_q(void);
BX_SMF void invalidate_prefetch_q(void);
+ BX_SMF void write_virtual(unsigned seg, Bit32u offset, unsigned len, void *data);
+ BX_SMF void read_virtual(unsigned seg, Bit32u offset, unsigned len, void *data);
BX_SMF void write_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned length);
BX_SMF void read_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned length);
BX_SMF void write_virtual_byte(unsigned seg, Bit32u offset, Bit8u *data);
BX_SMF void write_virtual_word(unsigned seg, Bit32u offset, Bit16u *data);
BX_SMF void write_virtual_dword(unsigned seg, Bit32u offset, Bit32u *data);
+ BX_SMF void write_virtual_qword(unsigned seg, Bit32u offset, Bit64u *data);
BX_SMF void read_virtual_byte(unsigned seg, Bit32u offset, Bit8u *data);
BX_SMF void read_virtual_word(unsigned seg, Bit32u offset, Bit16u *data);
BX_SMF void read_virtual_dword(unsigned seg, Bit32u offset, Bit32u *data);
+ BX_SMF void read_virtual_qword(unsigned seg, Bit32u offset, Bit64u *data);
BX_SMF void read_RMW_virtual_byte(unsigned seg, Bit32u offset, Bit8u *data);
BX_SMF void read_RMW_virtual_word(unsigned seg, Bit32u offset, Bit16u *data);
@@ -1568,6 +1641,8 @@
BX_SMF BX_CPP_INLINE Bit16u get_CX(void);
BX_SMF BX_CPP_INLINE Bit16u get_DX(void);
+ BX_SMF BX_CPP_INLINE int which_cpu(void);
+
#if BX_CPU_LEVEL >= 2
BX_SMF BX_CPP_INLINE Boolean real_mode(void);
#endif
@@ -1589,6 +1664,14 @@
#define BX_HWDebugMemRW 0x03
#endif
+BX_SMF BX_CPP_INLINE int BX_CPU_C_PREFIX which_cpu(void)
+{
+#if (BX_SMP_PROCESSORS==1)
+ return 0;
+#else
+ return local_apic.get_id();
+#endif
+}
#if BX_SMP_PROCESSORS==1
// single processor simulation, so there's one of everything
@@ -1840,7 +1923,13 @@
#define BxGroup7 BxGroupN
#define BxGroup8 BxGroupN
#define BxGroup9 BxGroupN
-#define BxGroupa BxGroupN
+#define BxGroupA BxGroupN
+
+#if BX_SUPPORT_MMX
+#define BxAnotherMMX BxAnother
+#else
+#define BxAnotherMMX (0)
+#endif
#if BX_DEBUGGER
typedef enum _show_flags {
diff -r -u -N bochs-1.4.1/cpu/fetchdecode.cc bochs-1.4.1-mmx-release-endian/cpu/fetchdecode.cc
--- bochs-1.4.1/cpu/fetchdecode.cc 2001-10-03 15:10:38.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/fetchdecode.cc 2002-08-25 13:01:36.000000000 +0200
@@ -344,6 +344,40 @@
/* 7 */ { 0, &BX_CPU_C::BxError }
};
+#if BX_SUPPORT_MMX
+static BxOpcodeInfo_t BxOpcodeInfoGAw[8] = { /* MMX */
+ /* 0 */ { 0, &BX_CPU_C::BxError },
+ /* 1 */ { 0, &BX_CPU_C::BxError },
+ /* 2 */ { BxImmediate_Ib, &BX_CPU_C::PSRLW_PqIb },
+ /* 3 */ { 0, &BX_CPU_C::BxError },
+ /* 4 */ { BxImmediate_Ib, &BX_CPU_C::PSRAW_PqIb },
+ /* 5 */ { 0, &BX_CPU_C::BxError },
+ /* 6 */ { BxImmediate_Ib, &BX_CPU_C::PSLLW_PqIb },
+ /* 7 */ { 0, &BX_CPU_C::BxError }
+ };
+
+static BxOpcodeInfo_t BxOpcodeInfoGAd[8] = { /* MMX */
+ /* 0 */ { 0, &BX_CPU_C::BxError },
+ /* 1 */ { 0, &BX_CPU_C::BxError },
+ /* 2 */ { BxImmediate_Ib, &BX_CPU_C::PSRLD_PqIb },
+ /* 3 */ { 0, &BX_CPU_C::BxError },
+ /* 4 */ { BxImmediate_Ib, &BX_CPU_C::PSRAD_PqIb },
+ /* 5 */ { 0, &BX_CPU_C::BxError },
+ /* 6 */ { BxImmediate_Ib, &BX_CPU_C::PSLLD_PqIb },
+ /* 7 */ { 0, &BX_CPU_C::BxError }
+ };
+
+static BxOpcodeInfo_t BxOpcodeInfoGAq[8] = { /* MMX */
+ /* 0 */ { 0, &BX_CPU_C::BxError },
+ /* 1 */ { 0, &BX_CPU_C::BxError },
+ /* 2 */ { BxImmediate_Ib, &BX_CPU_C::PSRLQ_PqIb },
+ /* 3 */ { 0, &BX_CPU_C::BxError },
+ /* 4 */ { 0, &BX_CPU_C::BxError },
+ /* 5 */ { 0, &BX_CPU_C::BxError },
+ /* 6 */ { BxImmediate_Ib, &BX_CPU_C::PSLLQ_PqIb },
+ /* 7 */ { 0, &BX_CPU_C::BxError }
+ };
+#endif
// 512 entries for 16bit mode
// 512 entries for 32bit mode
@@ -703,38 +737,44 @@
/* 0F 5D */ { 0, &BX_CPU_C::BxError },
/* 0F 5E */ { 0, &BX_CPU_C::BxError },
/* 0F 5F */ { 0, &BX_CPU_C::BxError },
- /* 0F 60 */ { 0, &BX_CPU_C::BxError },
- /* 0F 61 */ { 0, &BX_CPU_C::BxError },
- /* 0F 62 */ { 0, &BX_CPU_C::BxError },
- /* 0F 63 */ { 0, &BX_CPU_C::BxError },
- /* 0F 64 */ { 0, &BX_CPU_C::BxError },
- /* 0F 65 */ { 0, &BX_CPU_C::BxError },
- /* 0F 66 */ { 0, &BX_CPU_C::BxError },
- /* 0F 67 */ { 0, &BX_CPU_C::BxError },
- /* 0F 68 */ { 0, &BX_CPU_C::BxError },
- /* 0F 69 */ { 0, &BX_CPU_C::BxError },
- /* 0F 6A */ { 0, &BX_CPU_C::BxError },
- /* 0F 6B */ { 0, &BX_CPU_C::BxError },
+ /* 0F 60 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLBW_PqQd }, /* MMX */
+ /* 0F 61 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLWD_PqQd }, /* MMX */
+ /* 0F 62 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLDQ_PqQd }, /* MMX */
+ /* 0F 63 */ { BxAnotherMMX, &BX_CPU_C::PACKSSWB_PqQq }, /* MMX */
+ /* 0F 64 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTB_PqQq }, /* MMX */
+ /* 0F 65 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTW_PqQq }, /* MMX */
+ /* 0F 66 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTD_PqQq }, /* MMX */
+ /* 0F 67 */ { BxAnotherMMX, &BX_CPU_C::PACKUSWB_PqQq }, /* MMX */
+ /* 0F 68 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHBW_PqQq }, /* MMX */
+ /* 0F 69 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHWD_PqQq }, /* MMX */
+ /* 0F 6A */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHDQ_PqQq }, /* MMX */
+ /* 0F 6B */ { BxAnotherMMX, &BX_CPU_C::PACKSSDW_PqQq }, /* MMX */
/* 0F 6C */ { 0, &BX_CPU_C::BxError },
/* 0F 6D */ { 0, &BX_CPU_C::BxError },
- /* 0F 6E */ { 0, &BX_CPU_C::BxError },
- /* 0F 6F */ { 0, &BX_CPU_C::BxError },
+ /* 0F 6E */ { BxAnotherMMX, &BX_CPU_C::MOVD_PqEd }, /* MMX */
+ /* 0F 6F */ { BxAnotherMMX, &BX_CPU_C::MOVQ_PqQq }, /* MMX */
/* 0F 70 */ { 0, &BX_CPU_C::BxError },
+#if BX_SUPPORT_MMX
+ /* 0F 71 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAw },
+ /* 0F 72 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAd },
+ /* 0F 73 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAq },
+#else
/* 0F 71 */ { 0, &BX_CPU_C::BxError },
/* 0F 72 */ { 0, &BX_CPU_C::BxError },
/* 0F 73 */ { 0, &BX_CPU_C::BxError },
- /* 0F 74 */ { 0, &BX_CPU_C::BxError },
- /* 0F 75 */ { 0, &BX_CPU_C::BxError },
- /* 0F 76 */ { 0, &BX_CPU_C::BxError },
- /* 0F 77 */ { 0, &BX_CPU_C::BxError },
+#endif
+ /* 0F 74 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQB_PqQq }, /* MMX */
+ /* 0F 75 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQW_PqQq }, /* MMX */
+ /* 0F 76 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQD_PqQq }, /* MMX */
+ /* 0F 77 */ { 0, &BX_CPU_C::EMMS }, /* MMX */
/* 0F 78 */ { 0, &BX_CPU_C::BxError },
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
- /* 0F 7E */ { 0, &BX_CPU_C::BxError },
- /* 0F 7F */ { 0, &BX_CPU_C::BxError },
+ /* 0F 7E */ { BxAnotherMMX, &BX_CPU_C::MOVD_EdPd }, /* MMX */
+ /* 0F 7F */ { BxAnotherMMX, &BX_CPU_C::MOVQ_QqPq }, /* MMX */
/* 0F 80 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jw },
/* 0F 81 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jw },
/* 0F 82 */ { BxImmediate_BrOff16, &BX_CPU_C::JCC_Jw },
@@ -816,53 +856,53 @@
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
- /* 0F D1 */ { 0, &BX_CPU_C::BxError },
- /* 0F D2 */ { 0, &BX_CPU_C::BxError },
- /* 0F D3 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D1 */ { BxAnotherMMX, &BX_CPU_C::PSRLW_PqQq }, /* MMX */
+ /* 0F D2 */ { BxAnotherMMX, &BX_CPU_C::PSRLD_PqQq }, /* MMX */
+ /* 0F D3 */ { BxAnotherMMX, &BX_CPU_C::PSRLQ_PqQq }, /* MMX */
/* 0F D4 */ { 0, &BX_CPU_C::BxError },
- /* 0F D5 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D5 */ { BxAnotherMMX, &BX_CPU_C::PMULLW_PqQq }, /* MMX */
/* 0F D6 */ { 0, &BX_CPU_C::BxError },
/* 0F D7 */ { 0, &BX_CPU_C::BxError },
- /* 0F D8 */ { 0, &BX_CPU_C::BxError },
- /* 0F D9 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D8 */ { BxAnotherMMX, &BX_CPU_C::PSUBUSB_PqQq }, /* MMX */
+ /* 0F D9 */ { BxAnotherMMX, &BX_CPU_C::PSUBUSW_PqQq }, /* MMX */
/* 0F DA */ { 0, &BX_CPU_C::BxError },
- /* 0F DB */ { 0, &BX_CPU_C::BxError },
- /* 0F DC */ { 0, &BX_CPU_C::BxError },
- /* 0F DD */ { 0, &BX_CPU_C::BxError },
+ /* 0F DB */ { BxAnotherMMX, &BX_CPU_C::PAND_PqQq }, /* MMX */
+ /* 0F DC */ { BxAnotherMMX, &BX_CPU_C::PADDUSB_PqQq }, /* MMX */
+ /* 0F DD */ { BxAnotherMMX, &BX_CPU_C::PADDUSW_PqQq }, /* MMX */
/* 0F DE */ { 0, &BX_CPU_C::BxError },
- /* 0F DF */ { 0, &BX_CPU_C::BxError },
+ /* 0F DF */ { BxAnotherMMX, &BX_CPU_C::PANDN_PqQq }, /* MMX */
/* 0F E0 */ { 0, &BX_CPU_C::BxError },
- /* 0F E1 */ { 0, &BX_CPU_C::BxError },
- /* 0F E2 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E1 */ { BxAnotherMMX, &BX_CPU_C::PSRAW_PqQq }, /* MMX */
+ /* 0F E2 */ { BxAnotherMMX, &BX_CPU_C::PSRAD_PqQq }, /* MMX */
/* 0F E3 */ { 0, &BX_CPU_C::BxError },
/* 0F E4 */ { 0, &BX_CPU_C::BxError },
- /* 0F E5 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E5 */ { BxAnotherMMX, &BX_CPU_C::PMULHW_PqQq }, /* MMX */
/* 0F E6 */ { 0, &BX_CPU_C::BxError },
/* 0F E7 */ { 0, &BX_CPU_C::BxError },
- /* 0F E8 */ { 0, &BX_CPU_C::BxError },
- /* 0F E9 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E8 */ { BxAnotherMMX, &BX_CPU_C::PSUBSB_PqQq }, /* MMX */
+ /* 0F E9 */ { BxAnotherMMX, &BX_CPU_C::PSUBSW_PqQq }, /* MMX */
/* 0F EA */ { 0, &BX_CPU_C::BxError },
- /* 0F EB */ { 0, &BX_CPU_C::BxError },
- /* 0F EC */ { 0, &BX_CPU_C::BxError },
- /* 0F ED */ { 0, &BX_CPU_C::BxError },
+ /* 0F EB */ { BxAnotherMMX, &BX_CPU_C::POR_PqQq }, /* MMX */
+ /* 0F EC */ { BxAnotherMMX, &BX_CPU_C::PADDSB_PqQq }, /* MMX */
+ /* 0F ED */ { BxAnotherMMX, &BX_CPU_C::PADDSW_PqQq }, /* MMX */
/* 0F EE */ { 0, &BX_CPU_C::BxError },
- /* 0F EF */ { 0, &BX_CPU_C::BxError },
- /* 0F F0 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F1 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F2 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F3 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F4 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F5 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F6 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F7 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F8 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F9 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FA */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FB */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FC */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FD */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FE */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FF */ { 0, &BX_CPU_C::UndefinedOpcode },
+ /* 0F EF */ { BxAnotherMMX, &BX_CPU_C::PXOR_PqQq }, /* MMX */
+ /* 0F F0 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F1 */ { BxAnotherMMX, &BX_CPU_C::PSLLW_PqQq }, /* MMX */
+ /* 0F F2 */ { BxAnotherMMX, &BX_CPU_C::PSLLD_PqQq }, /* MMX */
+ /* 0F F3 */ { BxAnotherMMX, &BX_CPU_C::PSLLQ_PqQq }, /* MMX */
+ /* 0F F4 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F5 */ { BxAnotherMMX, &BX_CPU_C::PMADDWD_PqQq }, /* MMX */
+ /* 0F F6 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F7 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F8 */ { BxAnotherMMX, &BX_CPU_C::PSUBB_PqQq }, /* MMX */
+ /* 0F F9 */ { BxAnotherMMX, &BX_CPU_C::PSUBW_PqQq }, /* MMX */
+ /* 0F FA */ { BxAnotherMMX, &BX_CPU_C::PSUBD_PqQq }, /* MMX */
+ /* 0F FB */ { 0, &BX_CPU_C::BxError },
+ /* 0F FC */ { BxAnotherMMX, &BX_CPU_C::PADDB_PqQq }, /* MMX */
+ /* 0F FD */ { BxAnotherMMX, &BX_CPU_C::PADDW_PqQq }, /* MMX */
+ /* 0F FE */ { BxAnotherMMX, &BX_CPU_C::PADDD_PqQq }, /* MMX */
+ /* 0F FF */ { 0, &BX_CPU_C::BxError },
// 512 entries for 32bit mod
/* 00 */ { BxAnother, &BX_CPU_C::ADD_EbGb },
@@ -1218,38 +1258,44 @@
/* 0F 5D */ { 0, &BX_CPU_C::BxError },
/* 0F 5E */ { 0, &BX_CPU_C::BxError },
/* 0F 5F */ { 0, &BX_CPU_C::BxError },
- /* 0F 60 */ { 0, &BX_CPU_C::BxError },
- /* 0F 61 */ { 0, &BX_CPU_C::BxError },
- /* 0F 62 */ { 0, &BX_CPU_C::BxError },
- /* 0F 63 */ { 0, &BX_CPU_C::BxError },
- /* 0F 64 */ { 0, &BX_CPU_C::BxError },
- /* 0F 65 */ { 0, &BX_CPU_C::BxError },
- /* 0F 66 */ { 0, &BX_CPU_C::BxError },
- /* 0F 67 */ { 0, &BX_CPU_C::BxError },
- /* 0F 68 */ { 0, &BX_CPU_C::BxError },
- /* 0F 69 */ { 0, &BX_CPU_C::BxError },
- /* 0F 6A */ { 0, &BX_CPU_C::BxError },
- /* 0F 6B */ { 0, &BX_CPU_C::BxError },
+ /* 0F 60 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLBW_PqQd }, /* MMX */
+ /* 0F 61 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLWD_PqQd }, /* MMX */
+ /* 0F 62 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKLDQ_PqQd }, /* MMX */
+ /* 0F 63 */ { BxAnotherMMX, &BX_CPU_C::PACKSSWB_PqQq }, /* MMX */
+ /* 0F 64 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTB_PqQq }, /* MMX */
+ /* 0F 65 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTW_PqQq }, /* MMX */
+ /* 0F 66 */ { BxAnotherMMX, &BX_CPU_C::PCMPGTD_PqQq }, /* MMX */
+ /* 0F 67 */ { BxAnotherMMX, &BX_CPU_C::PACKUSWB_PqQq }, /* MMX */
+ /* 0F 68 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHBW_PqQq }, /* MMX */
+ /* 0F 69 */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHWD_PqQq }, /* MMX */
+ /* 0F 6A */ { BxAnotherMMX, &BX_CPU_C::PUNPCKHDQ_PqQq }, /* MMX */
+ /* 0F 6B */ { BxAnotherMMX, &BX_CPU_C::PACKSSDW_PqQq }, /* MMX */
/* 0F 6C */ { 0, &BX_CPU_C::BxError },
/* 0F 6D */ { 0, &BX_CPU_C::BxError },
- /* 0F 6E */ { 0, &BX_CPU_C::BxError },
- /* 0F 6F */ { 0, &BX_CPU_C::BxError },
+ /* 0F 6E */ { BxAnotherMMX, &BX_CPU_C::MOVD_PqEd }, /* MMX */
+ /* 0F 6F */ { BxAnotherMMX, &BX_CPU_C::MOVQ_PqQq }, /* MMX */
/* 0F 70 */ { 0, &BX_CPU_C::BxError },
+#if BX_SUPPORT_MMX
+ /* 0F 71 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAw },
+ /* 0F 72 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAd },
+ /* 0F 73 */ { BxAnother | BxGroupA, NULL, BxOpcodeInfoGAq },
+#else
/* 0F 71 */ { 0, &BX_CPU_C::BxError },
/* 0F 72 */ { 0, &BX_CPU_C::BxError },
/* 0F 73 */ { 0, &BX_CPU_C::BxError },
- /* 0F 74 */ { 0, &BX_CPU_C::BxError },
- /* 0F 75 */ { 0, &BX_CPU_C::BxError },
- /* 0F 76 */ { 0, &BX_CPU_C::BxError },
- /* 0F 77 */ { 0, &BX_CPU_C::BxError },
+#endif
+ /* 0F 74 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQB_PqQq }, /* MMX */
+ /* 0F 75 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQW_PqQq }, /* MMX */
+ /* 0F 76 */ { BxAnotherMMX, &BX_CPU_C::PCMPEQD_PqQq }, /* MMX */
+ /* 0F 77 */ { 0, &BX_CPU_C::EMMS }, /* MMX */
/* 0F 78 */ { 0, &BX_CPU_C::BxError },
/* 0F 79 */ { 0, &BX_CPU_C::BxError },
/* 0F 7A */ { 0, &BX_CPU_C::BxError },
/* 0F 7B */ { 0, &BX_CPU_C::BxError },
/* 0F 7C */ { 0, &BX_CPU_C::BxError },
/* 0F 7D */ { 0, &BX_CPU_C::BxError },
- /* 0F 7E */ { 0, &BX_CPU_C::BxError },
- /* 0F 7F */ { 0, &BX_CPU_C::BxError },
+ /* 0F 7E */ { BxAnotherMMX, &BX_CPU_C::MOVD_EdPd }, /* MMX */
+ /* 0F 7F */ { BxAnotherMMX, &BX_CPU_C::MOVQ_QqPq }, /* MMX */
/* 0F 80 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jd },
/* 0F 81 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jd },
/* 0F 82 */ { BxImmediate_BrOff32, &BX_CPU_C::JCC_Jd },
@@ -1331,53 +1377,53 @@
/* 0F CE */ { 0, &BX_CPU_C::BSWAP_ESI },
/* 0F CF */ { 0, &BX_CPU_C::BSWAP_EDI },
/* 0F D0 */ { 0, &BX_CPU_C::BxError },
- /* 0F D1 */ { 0, &BX_CPU_C::BxError },
- /* 0F D2 */ { 0, &BX_CPU_C::BxError },
- /* 0F D3 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D1 */ { BxAnotherMMX, &BX_CPU_C::PSRLW_PqQq }, /* MMX */
+ /* 0F D2 */ { BxAnotherMMX, &BX_CPU_C::PSRLD_PqQq }, /* MMX */
+ /* 0F D3 */ { BxAnotherMMX, &BX_CPU_C::PSRLQ_PqQq }, /* MMX */
/* 0F D4 */ { 0, &BX_CPU_C::BxError },
- /* 0F D5 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D5 */ { BxAnotherMMX, &BX_CPU_C::PMULLW_PqQq }, /* MMX */
/* 0F D6 */ { 0, &BX_CPU_C::BxError },
/* 0F D7 */ { 0, &BX_CPU_C::BxError },
- /* 0F D8 */ { 0, &BX_CPU_C::BxError },
- /* 0F D9 */ { 0, &BX_CPU_C::BxError },
+ /* 0F D8 */ { BxAnotherMMX, &BX_CPU_C::PSUBUSB_PqQq }, /* MMX */
+ /* 0F D9 */ { BxAnotherMMX, &BX_CPU_C::PSUBUSW_PqQq }, /* MMX */
/* 0F DA */ { 0, &BX_CPU_C::BxError },
- /* 0F DB */ { 0, &BX_CPU_C::BxError },
- /* 0F DC */ { 0, &BX_CPU_C::BxError },
- /* 0F DD */ { 0, &BX_CPU_C::BxError },
+ /* 0F DB */ { BxAnotherMMX, &BX_CPU_C::PAND_PqQq }, /* MMX */
+ /* 0F DC */ { BxAnotherMMX, &BX_CPU_C::PADDUSB_PqQq }, /* MMX */
+ /* 0F DD */ { BxAnotherMMX, &BX_CPU_C::PADDUSW_PqQq }, /* MMX */
/* 0F DE */ { 0, &BX_CPU_C::BxError },
- /* 0F DF */ { 0, &BX_CPU_C::BxError },
+ /* 0F DF */ { BxAnotherMMX, &BX_CPU_C::PANDN_PqQq }, /* MMX */
/* 0F E0 */ { 0, &BX_CPU_C::BxError },
- /* 0F E1 */ { 0, &BX_CPU_C::BxError },
- /* 0F E2 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E1 */ { BxAnotherMMX, &BX_CPU_C::PSRAW_PqQq }, /* MMX */
+ /* 0F E2 */ { BxAnotherMMX, &BX_CPU_C::PSRAD_PqQq }, /* MMX */
/* 0F E3 */ { 0, &BX_CPU_C::BxError },
/* 0F E4 */ { 0, &BX_CPU_C::BxError },
- /* 0F E5 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E5 */ { BxAnotherMMX, &BX_CPU_C::PMULHW_PqQq }, /* MMX */
/* 0F E6 */ { 0, &BX_CPU_C::BxError },
/* 0F E7 */ { 0, &BX_CPU_C::BxError },
- /* 0F E8 */ { 0, &BX_CPU_C::BxError },
- /* 0F E9 */ { 0, &BX_CPU_C::BxError },
+ /* 0F E8 */ { BxAnotherMMX, &BX_CPU_C::PSUBSB_PqQq }, /* MMX */
+ /* 0F E9 */ { BxAnotherMMX, &BX_CPU_C::PSUBSW_PqQq }, /* MMX */
/* 0F EA */ { 0, &BX_CPU_C::BxError },
- /* 0F EB */ { 0, &BX_CPU_C::BxError },
- /* 0F EC */ { 0, &BX_CPU_C::BxError },
- /* 0F ED */ { 0, &BX_CPU_C::BxError },
+ /* 0F EB */ { BxAnotherMMX, &BX_CPU_C::POR_PqQq }, /* MMX */
+ /* 0F EC */ { BxAnotherMMX, &BX_CPU_C::PADDSB_PqQq }, /* MMX */
+ /* 0F ED */ { BxAnotherMMX, &BX_CPU_C::PADDSW_PqQq }, /* MMX */
/* 0F EE */ { 0, &BX_CPU_C::BxError },
- /* 0F EF */ { 0, &BX_CPU_C::BxError },
- /* 0F F0 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F1 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F2 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F3 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F4 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F5 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F6 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F7 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F8 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F F9 */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FA */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FB */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FC */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FD */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FE */ { 0, &BX_CPU_C::UndefinedOpcode },
- /* 0F FF */ { 0, &BX_CPU_C::UndefinedOpcode },
+ /* 0F EF */ { BxAnotherMMX, &BX_CPU_C::PXOR_PqQq }, /* MMX */
+ /* 0F F0 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F1 */ { BxAnotherMMX, &BX_CPU_C::PSLLW_PqQq }, /* MMX */
+ /* 0F F2 */ { BxAnotherMMX, &BX_CPU_C::PSLLD_PqQq }, /* MMX */
+ /* 0F F3 */ { BxAnotherMMX, &BX_CPU_C::PSLLQ_PqQq }, /* MMX */
+ /* 0F F4 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F5 */ { BxAnotherMMX, &BX_CPU_C::PMADDWD_PqQq }, /* MMX */
+ /* 0F F6 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F7 */ { 0, &BX_CPU_C::BxError },
+ /* 0F F8 */ { BxAnotherMMX, &BX_CPU_C::PSUBB_PqQq }, /* MMX */
+ /* 0F F9 */ { BxAnotherMMX, &BX_CPU_C::PSUBW_PqQq }, /* MMX */
+ /* 0F FA */ { BxAnotherMMX, &BX_CPU_C::PSUBD_PqQq }, /* MMX */
+ /* 0F FB */ { 0, &BX_CPU_C::BxError },
+ /* 0F FC */ { BxAnotherMMX, &BX_CPU_C::PADDB_PqQq }, /* MMX */
+ /* 0F FD */ { BxAnotherMMX, &BX_CPU_C::PADDW_PqQq }, /* MMX */
+ /* 0F FE */ { BxAnotherMMX, &BX_CPU_C::PADDD_PqQq }, /* MMX */
+ /* 0F FF */ { 0, &BX_CPU_C::BxError }
};
diff -r -u -N bochs-1.4.1/cpu/i387.h bochs-1.4.1-mmx-release-endian/cpu/i387.h
--- bochs-1.4.1/cpu/i387.h 1970-01-01 02:00:00.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/i387.h 2002-09-04 16:03:49.000000000 +0200
@@ -0,0 +1,157 @@
+#ifndef BX_I387_RELATED_EXTENSIONS_H
+#define BX_I387_RELATED_EXTENSIONS_H
+
+/* Get data sizes from config.h generated from simulator's
+ * configure script
+ */
+#include "config.h"
+typedef Bit8u u8; /* for FPU only */
+typedef Bit8s s8;
+typedef Bit16u u16;
+typedef Bit16s s16;
+typedef Bit32u u32;
+typedef Bit32s s32;
+typedef Bit64u u64;
+typedef Bit64s s64;
+
+//
+// Minimal i387 structure, pruned from the linux headers. Only
+// the fields which were necessary are included.
+//
+struct BxFpuRegisters {
+ s32 cwd;
+ s32 swd;
+ s32 twd;
+ s32 fip;
+ s32 fcs;
+ s32 foo;
+ s32 fos;
+ u32 fill0; /* to make sure the following aligns on an 8byte boundary */
+ u64 st_space[16]; /* 8*16 bytes per FP-reg (aligned) = 128 bytes */
+ unsigned char ftop;
+ unsigned char no_update;
+ unsigned char rm;
+ unsigned char alimit;
+};
+
+#if BX_SUPPORT_MMX
+typedef union {
+ Bit8u u8;
+ Bit8s s8;
+} MMX_BYTE;
+
+typedef union {
+ Bit16u u16;
+ Bit16s s16;
+ struct {
+#ifdef BX_BIG_ENDIAN
+ MMX_BYTE hi;
+ MMX_BYTE lo;
+#else
+ MMX_BYTE lo;
+ MMX_BYTE hi;
+#endif
+ } bytes;
+} MMX_WORD;
+
+typedef union {
+ Bit32u u32;
+ Bit32s s32;
+ struct {
+#ifdef BX_BIG_ENDIAN
+ MMX_WORD hi;
+ MMX_WORD lo;
+#else
+ MMX_WORD lo;
+ MMX_WORD hi;
+#endif
+ } words;
+} MMX_DWORD;
+
+typedef union {
+ Bit64u u64;
+ Bit64s s64;
+ struct {
+#ifdef BX_BIG_ENDIAN
+ MMX_DWORD hi;
+ MMX_DWORD lo;
+#else
+ MMX_DWORD lo;
+ MMX_DWORD hi;
+#endif
+ } dwords;
+} MMX_QWORD, BxPackedMmxRegister;
+
+#define MMXSB0(reg) (reg.dwords.lo.words.lo.bytes.lo.s8)
+#define MMXSB1(reg) (reg.dwords.lo.words.lo.bytes.hi.s8)
+#define MMXSB2(reg) (reg.dwords.lo.words.hi.bytes.lo.s8)
+#define MMXSB3(reg) (reg.dwords.lo.words.hi.bytes.hi.s8)
+#define MMXSB4(reg) (reg.dwords.hi.words.lo.bytes.lo.s8)
+#define MMXSB5(reg) (reg.dwords.hi.words.lo.bytes.hi.s8)
+#define MMXSB6(reg) (reg.dwords.hi.words.hi.bytes.lo.s8)
+#define MMXSB7(reg) (reg.dwords.hi.words.hi.bytes.hi.s8)
+
+#define MMXUB0(reg) (reg.dwords.lo.words.lo.bytes.lo.u8)
+#define MMXUB1(reg) (reg.dwords.lo.words.lo.bytes.hi.u8)
+#define MMXUB2(reg) (reg.dwords.lo.words.hi.bytes.lo.u8)
+#define MMXUB3(reg) (reg.dwords.lo.words.hi.bytes.hi.u8)
+#define MMXUB4(reg) (reg.dwords.hi.words.lo.bytes.lo.u8)
+#define MMXUB5(reg) (reg.dwords.hi.words.lo.bytes.hi.u8)
+#define MMXUB6(reg) (reg.dwords.hi.words.hi.bytes.lo.u8)
+#define MMXUB7(reg) (reg.dwords.hi.words.hi.bytes.hi.u8)
+
+#define MMXSW0(reg) (reg.dwords.lo.words.lo.s16)
+#define MMXSW1(reg) (reg.dwords.lo.words.hi.s16)
+#define MMXSW2(reg) (reg.dwords.hi.words.lo.s16)
+#define MMXSW3(reg) (reg.dwords.hi.words.hi.s16)
+
+#define MMXUW0(reg) (reg.dwords.lo.words.lo.u16)
+#define MMXUW1(reg) (reg.dwords.lo.words.hi.u16)
+#define MMXUW2(reg) (reg.dwords.hi.words.lo.u16)
+#define MMXUW3(reg) (reg.dwords.hi.words.hi.u16)
+
+#define MMXSD0(reg) (reg.dwords.lo.s32)
+#define MMXSD1(reg) (reg.dwords.hi.s32)
+
+#define MMXUD0(reg) (reg.dwords.lo.u32)
+#define MMXUD1(reg) (reg.dwords.hi.u32)
+
+#define MMXSQ(reg) (reg.s64)
+#define MMXUQ(reg) (reg.u64)
+
+typedef struct mmx_physical_reg_t
+{
+ BxPackedMmxRegister packed_mmx_register;
+ Bit16u exp; /* 4 bytes: exponent of fp register,
+ set to 0xFFFF by all mmx commands */
+ Bit32u aligment; /* 4 bytes: aligment */
+} BxMmxRegister;
+
+/* to be compatible with fpu register file */
+struct BxMmxRegisters
+{
+ Bit32u cwd; /* fpu control word */
+ Bit32u swd; /* fpu status word */
+ Bit32u twd; /* fpu tag word */
+ Bit32u fip;
+ Bit32u fcs;
+ Bit32u foo;
+ Bit32u fos;
+ Bit32u alignment;
+ BxMmxRegister mmx[8];
+ unsigned char tos; /* top-of-stack */
+ unsigned char no_update;
+ unsigned char rm;
+ unsigned char alimit;
+};
+#endif /* BX_SUPPORT_MMX */
+
+typedef union FpuMmxRegisters
+{
+ struct BxFpuRegisters soft;
+#if BX_SUPPORT_MMX
+ struct BxMmxRegisters mmx;
+#endif
+} i387_t;
+
+#endif
diff -r -u -N bochs-1.4.1/cpu/mmx.cc bochs-1.4.1-mmx-release-endian/cpu/mmx.cc
--- bochs-1.4.1/cpu/mmx.cc 1970-01-01 02:00:00.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/mmx.cc 2002-09-04 21:44:15.000000000 +0200
@@ -0,0 +1,1842 @@
+#define NEED_CPU_REG_SHORTCUTS 1
+#include "bochs.h"
+#define LOG_THIS BX_CPU_THIS_PTR
+
+#if BX_SUPPORT_MMX
+
+#define MMX_REGFILE ((BX_CPU_THIS_PTR the_i387).mmx)
+
+#define MMX_TWD (MMX_REGFILE.twd)
+#define MMX_SWD (MMX_REGFILE.swd)
+#define MMX_TOS (MMX_REGFILE.tos)
+#define BX_READ_MMX_REG(index) (MMX_REGFILE.mmx[index].packed_mmx_register)
+
+#define BX_WRITE_MMX_REG(index, value) \
+{ \
+ MMX_REGFILE.mmx[index].packed_mmx_register = value; \
+ MMX_REGFILE.mmx[index].exp = 0xFFFF; \
+}
+
+#endif
+
+static Bit8s SaturateWordSToByteS(Bit16s value)
+{
+/*
+ SaturateWordSToByteS converts a signed 16-bit value to a
+ signed 8-bit value. If the signed 16-bit value is less than -128, it
+ is represented by the saturated value -128 (0x80). If it is greater
+ than 127, it is represented by the saturated value 127 (0x7F).
+*/
+ if(value < -128) return -128;
+ if(value > 127) return 127;
+ return value;
+}
+
+static Bit16s SaturateDwordSToWordS(Bit32s value)
+{
+/*
+ SaturateDwordSToWordS converts a signed 32-bit value to a
+ signed 16-bit value. If the signed 32-bit value is less than -32768,
+ it is represented by the saturated value -32768 (0x8000). If it is
+ greater than 32767, it is represented by the saturated value 32767
+ (0x7FFF).
+*/
+ if(value < -32768) return -32768;
+ if(value > 32767) return 32767;
+ return value;
+}
+
+static Bit8u SaturateWordSToByteU(Bit16s value)
+{
+/*
+ SaturateWordSToByteU converts a signed 16-bit value to an
+ unsigned 8-bit value. If the signed 16-bit value is less than zero it
+ is represented by the saturated value zero (0x00).If it is greater
+ than 255 it is represented by the saturated value 255 (0xFF).
+*/
+ if(value < 0) return 0;
+ if(value > 255) return 255;
+ return value;
+}
+
+static Bit16u SaturateDwordSToWordU(Bit32s value)
+{
+/*
+ SaturateDwordSToWordU converts a signed 32-bit value
+ to an unsigned 16-bit value. If the signed 32-bit value is less
+ than zero, it is represented by the saturated value 65535
+ (0x0000). If it is greater than 65535, it is represented by
+ the saturated value 65535 (0xFFFF).
+*/
+ if(value < 0) return 0;
+ if(value > 65535) return 65535;
+ return value;
+}
+
+#if BX_SUPPORT_MMX
+void BX_CPU_C::PrintMmxRegisters(void)
+{
+ for(int i=0;i<8;i++) {
+ BxPackedMmxRegister mm = BX_READ_MMX_REG(i);
+ fprintf(stderr, "MM%d: %.16llx\n", i, MMXUQ(mm));
+ }
+}
+
+void BX_CPU_C::PrepareMmxInstruction(void)
+{
+ MMX_TWD = 0;
+ MMX_TOS = 0; /* Each time an MMX instruction is */
+ MMX_SWD &= 0xC7FF; /* executed, the TOS value is set to 000B */
+
+ if(BX_CPU_THIS_PTR cr0.em)
+ exception(BX_UD_EXCEPTION, 0, 0);
+
+ if(BX_CPU_THIS_PTR cr0.ts)
+ exception(BX_NM_EXCEPTION, 0, 0);
+}
+#endif
+
+/* 0F 60 */
+void BX_CPU_C::PUNPCKLBW_PqQd(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), result;
+ Bit32u op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_32BIT_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_dword(i->seg, i->rm_addr, &op2);
+ }
+
+ MMXUB7(result) = (op2) >> 24;
+ MMXUB6(result) = MMXUB3(op1);
+ MMXUB5(result) = (op2 & 0x00FF0000) >> 16;
+ MMXUB4(result) = MMXUB2(op1);
+ MMXUB3(result) = (op2 & 0x0000FF00) >> 8;
+ MMXUB2(result) = MMXUB1(op1);
+ MMXUB1(result) = (op2 & 0x000000FF);
+ MMXUB0(result) = MMXUB0(op1);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 61 */
+void BX_CPU_C::PUNPCKLWD_PqQd(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), result;
+ Bit32u op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_32BIT_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_dword(i->seg, i->rm_addr, &op2);
+ }
+
+ MMXUW3(result) = (op2) >> 16;
+ MMXUW2(result) = MMXUW1(op1);
+ MMXUW1(result) = (op2 & 0x0000FFFF);
+ MMXUW0(result) = MMXUW0(op1);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 62 */
+void BX_CPU_C::PUNPCKLDQ_PqQd(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn);
+ Bit32u op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_32BIT_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_dword(i->seg, i->rm_addr, &op2);
+ }
+
+ MMXUD1(op1) = op2;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 63 */
+void BX_CPU_C::PACKSSWB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSB0(result) = SaturateWordSToByteS(MMXSW0(op1));
+ MMXSB1(result) = SaturateWordSToByteS(MMXSW1(op1));
+ MMXSB2(result) = SaturateWordSToByteS(MMXSW2(op1));
+ MMXSB3(result) = SaturateWordSToByteS(MMXSW3(op1));
+ MMXSB4(result) = SaturateWordSToByteS(MMXSW0(op2));
+ MMXSB5(result) = SaturateWordSToByteS(MMXSW1(op2));
+ MMXSB6(result) = SaturateWordSToByteS(MMXSW2(op2));
+ MMXSB7(result) = SaturateWordSToByteS(MMXSW3(op2));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 64 */
+void BX_CPU_C::PCMPGTB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB0(result) = (MMXSB0(op1) > MMXSB0(op2)) ? 0xFF : 0;
+ MMXUB1(result) = (MMXSB1(op1) > MMXSB1(op2)) ? 0xFF : 0;
+ MMXUB2(result) = (MMXSB2(op1) > MMXSB2(op2)) ? 0xFF : 0;
+ MMXUB3(result) = (MMXSB3(op1) > MMXSB3(op2)) ? 0xFF : 0;
+ MMXUB4(result) = (MMXSB4(op1) > MMXSB4(op2)) ? 0xFF : 0;
+ MMXUB5(result) = (MMXSB5(op1) > MMXSB5(op2)) ? 0xFF : 0;
+ MMXUB6(result) = (MMXSB6(op1) > MMXSB6(op2)) ? 0xFF : 0;
+ MMXUB7(result) = (MMXSB7(op1) > MMXSB7(op2)) ? 0xFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 65 */
+void BX_CPU_C::PCMPGTW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW0(result) = (MMXSW0(op1) > MMXSW0(op2)) ? 0xFFFF : 0;
+ MMXUW1(result) = (MMXSW1(op1) > MMXSW1(op2)) ? 0xFFFF : 0;
+ MMXUW2(result) = (MMXSW2(op1) > MMXSW2(op2)) ? 0xFFFF : 0;
+ MMXUW3(result) = (MMXSW3(op1) > MMXSW3(op2)) ? 0xFFFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 66 */
+void BX_CPU_C::PCMPGTD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUD0(result) = (MMXSD0(op1) > MMXSD0(op2)) ? 0xFFFFFFFF : 0;
+ MMXUD1(result) = (MMXSD1(op1) > MMXSD1(op2)) ? 0xFFFFFFFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 67 */
+void BX_CPU_C::PACKUSWB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB0(result) = SaturateWordSToByteU(MMXSW0(op1));
+ MMXUB1(result) = SaturateWordSToByteU(MMXSW1(op1));
+ MMXUB2(result) = SaturateWordSToByteU(MMXSW2(op1));
+ MMXUB3(result) = SaturateWordSToByteU(MMXSW3(op1));
+ MMXUB4(result) = SaturateWordSToByteU(MMXSW0(op2));
+ MMXUB5(result) = SaturateWordSToByteU(MMXSW1(op2));
+ MMXUB6(result) = SaturateWordSToByteU(MMXSW2(op2));
+ MMXUB7(result) = SaturateWordSToByteU(MMXSW3(op2));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 68 */
+void BX_CPU_C::PUNPCKHBW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB7(result) = MMXUB7(op2);
+ MMXUB6(result) = MMXUB7(op1);
+ MMXUB5(result) = MMXUB6(op2);
+ MMXUB4(result) = MMXUB6(op1);
+ MMXUB3(result) = MMXUB5(op2);
+ MMXUB2(result) = MMXUB5(op1);
+ MMXUB1(result) = MMXUB4(op2);
+ MMXUB0(result) = MMXUB4(op1);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 69 */
+void BX_CPU_C::PUNPCKHWD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW3(result) = MMXUW3(op2);
+ MMXUW2(result) = MMXUW3(op1);
+ MMXUW1(result) = MMXUW2(op2);
+ MMXUW0(result) = MMXUW2(op1);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 6A */
+void BX_CPU_C::PUNPCKHDQ_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUD1(result) = MMXUD1(op2);
+ MMXUD0(result) = MMXUD1(op1);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 6B */
+void BX_CPU_C::PACKSSDW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSW0(result) = SaturateDwordSToWordS(MMXSD0(op1));
+ MMXSW1(result) = SaturateDwordSToWordS(MMXSD1(op1));
+ MMXSW2(result) = SaturateDwordSToWordS(MMXSD0(op2));
+ MMXSW3(result) = SaturateDwordSToWordS(MMXSD1(op2));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 6E */
+void BX_CPU_C::MOVD_PqEd(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op;
+ MMXUD1(op) = 0;
+
+ /* op is a register or memory reference */
+ if (i->mod == 0xc0) {
+ MMXUD0(op) = BX_READ_32BIT_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_dword(i->seg, i->rm_addr, &(MMXUD0(op)));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 6F */
+void BX_CPU_C::MOVQ_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op;
+
+ /* op is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op);
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 74 */
+void BX_CPU_C::PCMPEQB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB0(result) = (MMXUB0(op1) == MMXUB0(op2)) ? 0xFF : 0;
+ MMXUB1(result) = (MMXUB1(op1) == MMXUB1(op2)) ? 0xFF : 0;
+ MMXUB2(result) = (MMXUB2(op1) == MMXUB2(op2)) ? 0xFF : 0;
+ MMXUB3(result) = (MMXUB3(op1) == MMXUB3(op2)) ? 0xFF : 0;
+ MMXUB4(result) = (MMXUB4(op1) == MMXUB4(op2)) ? 0xFF : 0;
+ MMXUB5(result) = (MMXUB5(op1) == MMXUB5(op2)) ? 0xFF : 0;
+ MMXUB6(result) = (MMXUB6(op1) == MMXUB6(op2)) ? 0xFF : 0;
+ MMXUB7(result) = (MMXUB7(op1) == MMXUB7(op2)) ? 0xFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 75 */
+void BX_CPU_C::PCMPEQW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW0(result) = (MMXUW0(op1) == MMXUW0(op2)) ? 0xFFFF : 0;
+ MMXUW1(result) = (MMXUW1(op1) == MMXUW1(op2)) ? 0xFFFF : 0;
+ MMXUW2(result) = (MMXUW2(op1) == MMXUW2(op2)) ? 0xFFFF : 0;
+ MMXUW3(result) = (MMXUW3(op1) == MMXUW3(op2)) ? 0xFFFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 76 */
+void BX_CPU_C::PCMPEQD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUD0(result) = (MMXUD0(op1) == MMXUD0(op2)) ? 0xFFFFFFFF : 0;
+ MMXUD1(result) = (MMXUD1(op1) == MMXUD1(op2)) ? 0xFFFFFFFF : 0;
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 77 */
+void BX_CPU_C::EMMS(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+
+ if(BX_CPU_THIS_PTR cr0.em)
+ exception(BX_UD_EXCEPTION, 0, 0);
+
+ if(BX_CPU_THIS_PTR cr0.ts)
+ exception(BX_NM_EXCEPTION, 0, 0);
+
+ MMX_TWD = 0xFFFFFFFF;
+ MMX_TOS = 0; /* Each time an MMX instruction is */
+ MMX_SWD &= 0xC7FF; /* executed, the TOS value is set to 000B */
+
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 7E */
+void BX_CPU_C::MOVD_EdPd(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn);
+
+ /* op is a register or memory reference */
+ if (i->mod == 0xc0) {
+ BX_WRITE_32BIT_REG(i->rm, MMXUD0(op));
+ }
+ else {
+ write_virtual_dword(i->seg, i->rm_addr, &(MMXUD0(op)));
+ }
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 7F */
+void BX_CPU_C::MOVQ_QqPq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op = BX_READ_MMX_REG(i->nnn);
+
+ /* op is a register or memory reference */
+ if (i->mod == 0xc0) {
+ BX_WRITE_MMX_REG(i->rm, op);
+ }
+ else {
+ write_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op);
+ }
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D1 */
+void BX_CPU_C::PSRLW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
+ else
+ {
+ Bit8u shift = MMXUB0(op2);
+
+ MMXUW0(op1) >>= shift;
+ MMXUW1(op1) >>= shift;
+ MMXUW2(op1) >>= shift;
+ MMXUW3(op1) >>= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D2 */
+void BX_CPU_C::PSRLD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
+ else
+ {
+ Bit8u shift = MMXUB0(op2);
+
+ MMXUD0(op1) >>= shift;
+ MMXUD1(op1) >>= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D3 */
+void BX_CPU_C::PSRLQ_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 63) {
+ MMXUQ(op1) = 0;
+ }
+ else {
+ MMXUQ(op1) >>= MMXUB0(op2);
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D5 */
+void BX_CPU_C::PMULLW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ Bit32u product1 = (Bit32u)(MMXUW0(op1)) * (Bit32u)(MMXUW0(op2));
+ Bit32u product2 = (Bit32u)(MMXUW1(op1)) * (Bit32u)(MMXUW1(op2));
+ Bit32u product3 = (Bit32u)(MMXUW2(op1)) * (Bit32u)(MMXUW2(op2));
+ Bit32u product4 = (Bit32u)(MMXUW3(op1)) * (Bit32u)(MMXUW3(op2));
+
+ MMXUW0(result) = (Bit16u)(product1 & 0xFFFF);
+ MMXUW1(result) = (Bit16u)(product2 & 0xFFFF);
+ MMXUW2(result) = (Bit16u)(product3 & 0xFFFF);
+ MMXUW3(result) = (Bit16u)(product4 & 0xFFFF);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D8 */
+void BX_CPU_C::PSUBUSB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(result) = 0;
+
+ if(MMXUB0(op1) > MMXUB0(op2)) MMXUB0(result) = MMXUB0(op1) - MMXUB0(op2);
+ if(MMXUB1(op1) > MMXUB1(op2)) MMXUB1(result) = MMXUB1(op1) - MMXUB1(op2);
+ if(MMXUB2(op1) > MMXUB2(op2)) MMXUB2(result) = MMXUB2(op1) - MMXUB2(op2);
+ if(MMXUB3(op1) > MMXUB3(op2)) MMXUB3(result) = MMXUB3(op1) - MMXUB3(op2);
+ if(MMXUB4(op1) > MMXUB4(op2)) MMXUB4(result) = MMXUB4(op1) - MMXUB4(op2);
+ if(MMXUB5(op1) > MMXUB5(op2)) MMXUB5(result) = MMXUB5(op1) - MMXUB5(op2);
+ if(MMXUB6(op1) > MMXUB6(op2)) MMXUB6(result) = MMXUB6(op1) - MMXUB6(op2);
+ if(MMXUB7(op1) > MMXUB7(op2)) MMXUB7(result) = MMXUB7(op1) - MMXUB7(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F D9 */
+void BX_CPU_C::PSUBUSW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(result) = 0;
+
+ if(MMXUW0(op1) > MMXUW0(op2)) MMXUW0(result) = MMXUW0(op1) - MMXUW0(op2);
+ if(MMXUW1(op1) > MMXUW1(op2)) MMXUW1(result) = MMXUW1(op1) - MMXUW1(op2);
+ if(MMXUW2(op1) > MMXUW2(op2)) MMXUW2(result) = MMXUW2(op1) - MMXUW2(op2);
+ if(MMXUW3(op1) > MMXUW3(op2)) MMXUW3(result) = MMXUW3(op1) - MMXUW3(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F DB */
+void BX_CPU_C::PAND_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(op1) &= MMXUQ(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F DC */
+void BX_CPU_C::PADDUSB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB0(result) = SaturateWordSToByteU(Bit16s(MMXUB0(op1)) + Bit16s(MMXUB0(op2)));
+ MMXUB1(result) = SaturateWordSToByteU(Bit16s(MMXUB1(op1)) + Bit16s(MMXUB1(op2)));
+ MMXUB2(result) = SaturateWordSToByteU(Bit16s(MMXUB2(op1)) + Bit16s(MMXUB2(op2)));
+ MMXUB3(result) = SaturateWordSToByteU(Bit16s(MMXUB3(op1)) + Bit16s(MMXUB3(op2)));
+ MMXUB4(result) = SaturateWordSToByteU(Bit16s(MMXUB4(op1)) + Bit16s(MMXUB4(op2)));
+ MMXUB5(result) = SaturateWordSToByteU(Bit16s(MMXUB5(op1)) + Bit16s(MMXUB5(op2)));
+ MMXUB6(result) = SaturateWordSToByteU(Bit16s(MMXUB6(op1)) + Bit16s(MMXUB6(op2)));
+ MMXUB7(result) = SaturateWordSToByteU(Bit16s(MMXUB7(op1)) + Bit16s(MMXUB7(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F DD */
+void BX_CPU_C::PADDUSW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW0(result) = SaturateDwordSToWordU(Bit32s(MMXUW0(op1)) + Bit32s(MMXUW0(op2)));
+ MMXUW1(result) = SaturateDwordSToWordU(Bit32s(MMXUW1(op1)) + Bit32s(MMXUW1(op2)));
+ MMXUW2(result) = SaturateDwordSToWordU(Bit32s(MMXUW2(op1)) + Bit32s(MMXUW2(op2)));
+ MMXUW3(result) = SaturateDwordSToWordU(Bit32s(MMXUW3(op1)) + Bit32s(MMXUW3(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F DF */
+void BX_CPU_C::PANDN_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(result) = ~(MMXUQ(op1)) & MMXUQ(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F E1 */
+void BX_CPU_C::PSRAW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ Bit8u shift = MMXUB0(op2);
+
+ if(MMXUQ(op2) > 15) {
+ MMXUW0(result) = (MMXUW0(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW1(result) = (MMXUW1(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW2(result) = (MMXUW2(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW3(result) = (MMXUW3(op1) & 0x8000) ? 0xFFFF : 0;
+ }
+ else {
+ MMXUW0(result) = MMXUW0(op1) >> shift;
+ MMXUW1(result) = MMXUW1(op1) >> shift;
+ MMXUW2(result) = MMXUW2(op1) >> shift;
+ MMXUW3(result) = MMXUW3(op1) >> shift;
+
+ if(MMXUW0(op1) & 0x8000) MMXUW0(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW1(op1) & 0x8000) MMXUW1(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW2(op1) & 0x8000) MMXUW2(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW3(op1) & 0x8000) MMXUW3(result) |= (0xFFFF << (16 - shift));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F E2 */
+void BX_CPU_C::PSRAD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ Bit8u shift = MMXUB0(op2);
+
+ if(MMXUQ(op2) > 31) {
+ MMXUD0(result) = (MMXUD0(op1) & 0x80000000) ? 0xFFFFFFFF : 0;
+ MMXUD1(result) = (MMXUD1(op1) & 0x80000000) ? 0xFFFFFFFF : 0;
+ }
+ else {
+ MMXUD0(result) = MMXUD0(op1) >> shift;
+ MMXUD1(result) = MMXUD1(op1) >> shift;
+
+ if(MMXUD0(op1) & 0x80000000) MMXUD0(result) |= (0xFFFFFFFF << (32 - shift));
+ if(MMXUD1(op1) & 0x80000000) MMXUD1(result) |= (0xFFFFFFFF << (32 - shift));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F E5 */
+void BX_CPU_C::PMULHW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ Bit32s product1 = (Bit32s)(MMXSW0(op1)) * (Bit32s)(MMXSW0(op2));
+ Bit32s product2 = (Bit32s)(MMXSW1(op1)) * (Bit32s)(MMXSW1(op2));
+ Bit32s product3 = (Bit32s)(MMXSW2(op1)) * (Bit32s)(MMXSW2(op2));
+ Bit32s product4 = (Bit32s)(MMXSW3(op1)) * (Bit32s)(MMXSW3(op2));
+
+ MMXUW0(result) = (Bit16u)(product1 >> 16);
+ MMXUW1(result) = (Bit16u)(product2 >> 16);
+ MMXUW2(result) = (Bit16u)(product3 >> 16);
+ MMXUW3(result) = (Bit16u)(product4 >> 16);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F E8 */
+void BX_CPU_C::PSUBSB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSB0(result) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) - Bit16s(MMXSB0(op2)));
+ MMXSB1(result) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) - Bit16s(MMXSB1(op2)));
+ MMXSB2(result) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) - Bit16s(MMXSB2(op2)));
+ MMXSB3(result) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) - Bit16s(MMXSB3(op2)));
+ MMXSB4(result) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) - Bit16s(MMXSB4(op2)));
+ MMXSB5(result) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) - Bit16s(MMXSB5(op2)));
+ MMXSB6(result) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) - Bit16s(MMXSB6(op2)));
+ MMXSB7(result) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) - Bit16s(MMXSB7(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F E9 */
+void BX_CPU_C::PSUBSW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW0(op2)));
+ MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) - Bit32s(MMXSW1(op2)));
+ MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW2(op2)));
+ MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) - Bit32s(MMXSW3(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F EB */
+void BX_CPU_C::POR_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(op1) |= MMXUQ(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F EC */
+void BX_CPU_C::PADDSB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSB0(result) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) + Bit16s(MMXSB0(op2)));
+ MMXSB1(result) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) + Bit16s(MMXSB1(op2)));
+ MMXSB2(result) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) + Bit16s(MMXSB2(op2)));
+ MMXSB3(result) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) + Bit16s(MMXSB3(op2)));
+ MMXSB4(result) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) + Bit16s(MMXSB4(op2)));
+ MMXSB5(result) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) + Bit16s(MMXSB5(op2)));
+ MMXSB6(result) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) + Bit16s(MMXSB6(op2)));
+ MMXSB7(result) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) + Bit16s(MMXSB7(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F ED */
+void BX_CPU_C::PADDSW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXSW0(result) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW0(op2)));
+ MMXSW1(result) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) + Bit32s(MMXSW1(op2)));
+ MMXSW2(result) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW2(op2)));
+ MMXSW3(result) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) + Bit32s(MMXSW3(op2)));
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F EF */
+void BX_CPU_C::PXOR_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUQ(op1) ^= MMXUQ(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F1 */
+void BX_CPU_C::PSLLW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 15) MMXUQ(op1) = 0;
+ else
+ {
+ Bit8u shift = MMXUB0(op2);
+
+ MMXUW0(op1) <<= shift;
+ MMXUW1(op1) <<= shift;
+ MMXUW2(op1) <<= shift;
+ MMXUW3(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F2 */
+void BX_CPU_C::PSLLD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 31) MMXUQ(op1) = 0;
+ else
+ {
+ Bit8u shift = MMXUB0(op2);
+
+ MMXUD0(op1) <<= shift;
+ MMXUD1(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F3 */
+void BX_CPU_C::PSLLQ_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUQ(op2) > 63) {
+ MMXUQ(op1) = 0;
+ }
+ else {
+ MMXUQ(op1) <<= MMXUB0(op2);
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F5 */
+void BX_CPU_C::PMADDWD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2, result;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ if(MMXUW0(op1) == 0x80008000 && MMXUW0(op2) == 0x80008000) {
+ MMXUD0(result) = 0x80000000;
+ }
+ else {
+ MMXUD0(result) = Bit32s(MMXSW0(op1))*Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op1))*Bit32s(MMXSW1(op2));
+ }
+
+ if(MMXUW2(op1) == 0x80008000 && MMXUW2(op2) == 0x80008000) {
+ MMXUD1(result) = 0x80000000;
+ }
+ else {
+ MMXUD1(result) = Bit32s(MMXSW2(op1))*Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op1))*Bit32s(MMXSW3(op2));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F8 */
+void BX_CPU_C::PSUBB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUB0(op1) -= MMXUB0(op2);
+ MMXUB1(op1) -= MMXUB1(op2);
+ MMXUB2(op1) -= MMXUB2(op2);
+ MMXUB3(op1) -= MMXUB3(op2);
+ MMXUB4(op1) -= MMXUB4(op2);
+ MMXUB5(op1) -= MMXUB5(op2);
+ MMXUB6(op1) -= MMXUB6(op2);
+ MMXUB7(op1) -= MMXUB7(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F F9 */
+void BX_CPU_C::PSUBW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW0(op1) -= MMXUW0(op2);
+ MMXUW1(op1) -= MMXUW1(op2);
+ MMXUW2(op1) -= MMXUW2(op2);
+ MMXUW3(op1) -= MMXUW3(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F FA */
+void BX_CPU_C::PSUBD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUD0(op1) -= MMXUD0(op2);
+ MMXUD1(op1) -= MMXUD1(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F FC */
+void BX_CPU_C::PADDB_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+
+ MMXUB0(op1) += MMXUB0(op2);
+ MMXUB1(op1) += MMXUB1(op2);
+ MMXUB2(op1) += MMXUB2(op2);
+ MMXUB3(op1) += MMXUB3(op2);
+ MMXUB4(op1) += MMXUB4(op2);
+ MMXUB5(op1) += MMXUB5(op2);
+ MMXUB6(op1) += MMXUB6(op2);
+ MMXUB7(op1) += MMXUB7(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F FD */
+void BX_CPU_C::PADDW_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUW0(op1) += MMXUW0(op2);
+ MMXUW1(op1) += MMXUW1(op2);
+ MMXUW2(op1) += MMXUW2(op2);
+ MMXUW3(op1) += MMXUW3(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F FE */
+void BX_CPU_C::PADDD_PqQq(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn), op2;
+
+ /* op2 is a register or memory reference */
+ if (i->mod == 0xc0) {
+ op2 = BX_READ_MMX_REG(i->rm);
+ }
+ else {
+ /* pointer, segment address pair */
+ read_virtual_qword(i->seg, i->rm_addr, (Bit64u *) &op2);
+ }
+
+ MMXUD0(op1) += MMXUD0(op2);
+ MMXUD1(op1) += MMXUD1(op2);
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->nnn, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 71 GrpA 010 */
+void BX_CPU_C::PSRLW_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 15) MMXUQ(op1) = 0;
+ else
+ {
+ MMXUW0(op1) >>= shift;
+ MMXUW1(op1) >>= shift;
+ MMXUW2(op1) >>= shift;
+ MMXUW3(op1) >>= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 71 GrpA 100 */
+void BX_CPU_C::PSRAW_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm), result;
+ Bit8u shift = i->Ib;
+
+ if(shift > 15) {
+ MMXUW0(result) = (MMXUW0(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW1(result) = (MMXUW1(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW2(result) = (MMXUW2(op1) & 0x8000) ? 0xFFFF : 0;
+ MMXUW3(result) = (MMXUW3(op1) & 0x8000) ? 0xFFFF : 0;
+ }
+ else {
+ MMXUW0(result) = MMXUW0(op1) >> shift;
+ MMXUW1(result) = MMXUW1(op1) >> shift;
+ MMXUW2(result) = MMXUW2(op1) >> shift;
+ MMXUW3(result) = MMXUW3(op1) >> shift;
+
+ if(MMXUW0(op1) & 0x8000) MMXUW0(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW1(op1) & 0x8000) MMXUW1(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW2(op1) & 0x8000) MMXUW2(result) |= (0xFFFF << (16 - shift));
+ if(MMXUW3(op1) & 0x8000) MMXUW3(result) |= (0xFFFF << (16 - shift));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 71 GrpA 110 */
+void BX_CPU_C::PSLLW_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 15) MMXUQ(op1) = 0;
+ else
+ {
+ MMXUW0(op1) <<= shift;
+ MMXUW1(op1) <<= shift;
+ MMXUW2(op1) <<= shift;
+ MMXUW3(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+
+/* 0F 72 GrpA 010 */
+void BX_CPU_C::PSRLD_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 31) MMXUQ(op1) = 0;
+ else
+ {
+ MMXUD0(op1) <<= shift;
+ MMXUD1(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 72 GrpA 100 */
+void BX_CPU_C::PSRAD_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm), result;
+ Bit8u shift = i->Ib;
+
+ if(shift > 31) {
+ MMXUD0(result) = (MMXUD0(op1) & 0x80000000) ? 0xFFFFFFFF : 0;
+ MMXUD1(result) = (MMXUD1(op1) & 0x80000000) ? 0xFFFFFFFF : 0;
+ }
+ else {
+ MMXUD0(result) = MMXUD0(op1) >> shift;
+ MMXUD1(result) = MMXUD1(op1) >> shift;
+
+ if(MMXUD0(op1) & 0x80000000) MMXUD0(result) |= (0xFFFFFFFF << (32 - shift));
+ if(MMXUD1(op1) & 0x80000000) MMXUD1(result) |= (0xFFFFFFFF << (32 - shift));
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, result);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 72 GrpA 110 */
+void BX_CPU_C::PSLLD_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 31) MMXUQ(op1) = 0;
+ else
+ {
+ MMXUD0(op1) <<= shift;
+ MMXUD1(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 73 GrpA 010 */
+void BX_CPU_C::PSRLQ_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 63) {
+ MMXUQ(op1) = 0;
+ }
+ else {
+ MMXUQ(op1) >>= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
+
+/* 0F 73 GrpA 110 */
+void BX_CPU_C::PSLLQ_PqIb(BxInstruction_t *i)
+{
+#if BX_SUPPORT_MMX
+ BX_CPU_THIS_PTR PrepareMmxInstruction();
+
+ BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->rm);
+ Bit8u shift = i->Ib;
+
+ if(shift > 63) {
+ MMXUQ(op1) = 0;
+ }
+ else {
+ MMXUQ(op1) <<= shift;
+ }
+
+ /* now write result back to destination */
+ BX_WRITE_MMX_REG(i->rm, op1);
+#else
+ BX_INFO(("MMX Instructions Set Not Implemented"));
+ UndefinedOpcode(i);
+#endif
+}
diff -r -u -N bochs-1.4.1/cpu/proc_ctrl.cc bochs-1.4.1-mmx-release-endian/cpu/proc_ctrl.cc
--- bochs-1.4.1/cpu/proc_ctrl.cc 2002-06-24 00:19:44.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/cpu/proc_ctrl.cc 2002-08-23 17:00:30.000000000 +0200
@@ -1026,6 +1026,9 @@
# if BX_SUPPORT_FPU
features |= 0x01;
# endif
+# if BX_SUPPORT_MMX
+ features |= (1<<23); // support MMX
+# endif
#elif BX_CPU_LEVEL == 6
family = 6;
@@ -1038,6 +1041,9 @@
# if BX_SUPPORT_FPU
features |= 0x01; // has FPU
# endif
+# if BX_SUPPORT_MMX
+ features |= (1<<23); // support MMX
+# endif
#else
BX_PANIC(("CPUID: not implemented for > 6"));
#endif
diff -r -u -N bochs-1.4.1/fpu/fpu_system.h bochs-1.4.1-mmx-release-endian/fpu/fpu_system.h
--- bochs-1.4.1/fpu/fpu_system.h 2001-10-06 05:53:46.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/fpu/fpu_system.h 2002-08-24 18:57:12.000000000 +0200
@@ -96,18 +96,7 @@
* rather than a kernel (ported by Kevin Lawton)
* ------------------------------------------------------------ */
-/* Get data sizes from config.h generated from simulator's
- * configure script
- */
-#include "config.h"
-typedef Bit8u u8;
-typedef Bit8s s8;
-typedef Bit16u u16;
-typedef Bit16s s16;
-typedef Bit32u u32;
-typedef Bit32s s32;
-typedef Bit64u u64;
-typedef Bit64s s64;
+#include <cpu/i387.h>
/* bbd: include ported linux headers after config.h for GCC_ATTRIBUTE macro */
#include <linux/kernel.h>
@@ -144,36 +133,13 @@
#define FPU_info ((struct info *) NULL)
-
-//
-// Minimal i387 structure, pruned from the linux headers. Only
-// the fields which were necessary are included.
-//
-typedef struct {
- struct {
- s32 cwd;
- s32 swd;
- s32 twd;
- s32 fip;
- s32 fcs;
- s32 foo;
- s32 fos;
- u32 fill0; /* to make sure the following aligns on an 8byte boundary */
- u64 st_space[16]; /* 8*16 bytes per FP-reg (aligned) = 128 bytes */
- unsigned char ftop;
- unsigned char no_update;
- unsigned char rm;
- unsigned char alimit;
- } GCC_ATTRIBUTE((aligned(16), packed)) soft;
- } i387_t;
-
-extern i387_t i387;
-
-
#endif
#define SIGSEGV 11
+extern i387_t *current_i387;
+
+#define i387 (*current_i387)
#define I387 i387
diff -r -u -N bochs-1.4.1/fpu/wmFPUemu_glue.cc bochs-1.4.1-mmx-release-endian/fpu/wmFPUemu_glue.cc
--- bochs-1.4.1/fpu/wmFPUemu_glue.cc 2001-09-15 08:55:14.000000000 +0200
+++ bochs-1.4.1-mmx-release-endian/fpu/wmFPUemu_glue.cc 2002-08-24 19:28:36.000000000 +0200
@@ -45,7 +45,7 @@
static BxInstruction_t *fpu_iptr = NULL;
static BX_CPU_C *fpu_cpu_ptr = NULL;
-i387_t i387;
+i387_t *current_i387;
extern "C" void
math_emulate2(fpu_addr_modes addr_modes,
@@ -62,6 +62,7 @@
void
BX_CPU_C::fpu_init(void)
{
+ current_i387 = &(BX_CPU_THIS_PTR the_i387);
finit();
}
@@ -76,6 +77,7 @@
fpu_iptr = i;
fpu_cpu_ptr = this;
+ current_i387 = &(BX_CPU_THIS_PTR the_i387);
#if 0
addr_modes.default_mode = VM86;