#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <fenv.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "debug.h"
#include "box64stack.h"
#include "x64emu.h"
#include "x64run.h"
#include "x64emu_private.h"
#include "x64run_private.h"
#include "x64primop.h"
#include "x64trace.h"
#include "x87emu_private.h"
#include "box64context.h"
#include "bridge.h"
#include "modrm.h"
#include "x64compstrings.h"
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
#ifdef TEST_INTERPRETER
uintptr_t Test660F(x64test_t *test, rex_t rex, uintptr_t addr)
#else
uintptr_t Run660F(x64emu_t *emu, rex_t rex, uintptr_t addr)
#endif
{
uint8_t opcode;
uint8_t nextop;
uint8_t tmp8u;
int8_t tmp8s;
int16_t tmp16s;
uint16_t tmp16u;
int32_t tmp32s;
uint32_t tmp32u;
uint64_t tmp64u, tmp64u2;
int64_t tmp64s, i64[4];
float tmpf;
double tmpd;
#ifndef NOALIGN
int is_nan;
#endif
reg64_t *oped, *opgd;
sse_regs_t *opex, *opgx, eax1, *opex2, eax2;
mmx87_regs_t *opem, *opgm;
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
#ifdef TEST_INTERPRETER
x64emu_t* emu = test->emu;
#endif
opcode = F8;
switch(opcode) {
case 0x10:
nextop = F8;
GETEX(0);
GETGX;
memcpy(GX, EX, 16);
break;
case 0x11:
nextop = F8;
GETEX(0);
GETGX;
memcpy(EX, GX, 16);
break;
case 0x12:
nextop = F8;
GETE8(0);
GETGX;
GX->q[0] = ED->q[0];
break;
case 0x13:
nextop = F8;
GETE8(0);
GETGX;
ED->q[0] = GX->q[0];
break;
case 0x14:
nextop = F8;
GETEX(0);
GETGX;
GX->q[1] = EX->q[0];
break;
case 0x15:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = GX->q[1];
GX->q[1] = EX->q[1];
break;
case 0x16:
nextop = F8;
GETE8(0);
GETGX;
GX->q[1] = ED->q[0];
break;
case 0x17:
nextop = F8;
GETE8(0);
GETGX;
ED->q[0] = GX->q[1];
break;
case 0x1F:
nextop = F8;
FAKEED(0);
break;
case 0x28:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = EX->q[0];
GX->q[1] = EX->q[1];
break;
case 0x29:
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0x2A:
nextop = F8;
GETEM(0);
GETGX;
GX->d[0] = EM->sd[0];
GX->d[1] = EM->sd[1];
break;
case 0x2B:
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0x2C:
nextop = F8;
GETEX(0);
GETGM;
tmp64s = EX->d[0];
if (tmp64s==(int32_t)tmp64s && !isnan(EX->d[0]))
GM->sd[0] = (int32_t)tmp64s;
else
GM->sd[0] = INT32_MIN;
tmp64s = EX->d[1];
if (tmp64s==(int32_t)tmp64s && !isnan(EX->d[1]))
GM->sd[1] = (int32_t)tmp64s;
else
GM->sd[1] = INT32_MIN;
break;
case 0x2D:
nextop = F8;
GETEX(0);
GETGM;
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
i64[0] = nearbyint(EX->d[0]);
i64[1] = nearbyint(EX->d[1]);
fesetround(round);
break;
}
case ROUND_Down:
i64[0] = floor(EX->d[0]);
i64[1] = floor(EX->d[1]);
break;
case ROUND_Up:
i64[0] = ceil(EX->d[0]);
i64[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
i64[0] = EX->d[0];
i64[1] = EX->d[1];
break;
}
for(int i=0; i<2; ++i)
if (i64[i]==(int32_t)i64[i] && !isnan(EX->d[i]))
GM->sd[i] = (int32_t)i64[i];
else
GM->sd[i] = INT32_MIN;
break;
case 0x2E:
case 0x2F:
RESET_FLAGS(emu);
nextop = F8;
GETEX(0);
GETGX;
if(isnan(GX->d[0]) || isnan(EX->d[0])) {
SET_FLAG(F_ZF); SET_FLAG(F_PF); SET_FLAG(F_CF);
} else if(isgreater(GX->d[0], EX->d[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
} else if(isless(GX->d[0], EX->d[0])) {
CLEAR_FLAG(F_ZF); CLEAR_FLAG(F_PF); SET_FLAG(F_CF);
} else {
SET_FLAG(F_ZF); CLEAR_FLAG(F_PF); CLEAR_FLAG(F_CF);
}
CLEAR_FLAG(F_OF); CLEAR_FLAG(F_AF); CLEAR_FLAG(F_SF);
break;
case 0x38:
opcode = F8;
switch(opcode) {
case 0x00:
nextop = F8;
GETEX(0);
GETGX;
eax1 = *GX;
for (int i=0; i<16; ++i) {
if(EX->ub[i]&128)
GX->ub[i] = 0;
else
GX->ub[i] = eax1.ub[EX->ub[i]&15];
}
break;
case 0x01:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sw[i] = GX->sw[i*2+0]+GX->sw[i*2+1];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i)
GX->sw[4+i] = EX->sw[i*2+0] + EX->sw[i*2+1];
}
break;
case 0x02:
nextop = F8;
GETEX(0);
GETGX;
GX->sd[0] += GX->sd[1];
GX->sd[1] = GX->sd[2] + GX->sd[3];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
GX->sd[2] = EX->sd[0] + EX->sd[1];
GX->sd[3] = EX->sd[2] + EX->sd[3];
}
break;
case 0x03:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
tmp32s = GX->sw[i*2+0]+GX->sw[i*2+1];
GX->sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] + EX->sw[i*2+1];
GX->sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x04:
nextop = F8;
GETEX(0);
GETGX;
if(GX==EX) {
eax1 = *EX;
EX=&eax1;
}
for (int i=0; i<8; ++i) {
tmp32s = (int32_t)(GX->ub[i*2+0])*EX->sb[i*2+0] + (int32_t)(GX->ub[i*2+1])*EX->sb[i*2+1];
GX->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0x05:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sw[i] = GX->sw[i*2+0] - GX->sw[i*2+1];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i)
GX->sw[4+i] = EX->sw[i*2+0] - EX->sw[i*2+1];
}
break;
case 0x06:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<2; ++i)
GX->sd[i] = GX->sd[i*2+0] - GX->sd[i*2+1];
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<2; ++i)
GX->sd[2+i] = EX->sd[i*2+0] - EX->sd[i*2+1];
}
break;
case 0x07:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
tmp32s = GX->sw[i*2+0] - GX->sw[i*2+1];
GX->sw[i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
if(GX == EX) {
GX->q[1] = GX->q[0];
} else {
for (int i=0; i<4; ++i) {
tmp32s = EX->sw[i*2+0] - EX->sw[i*2+1];
GX->sw[4+i] = (tmp32s<-32768)?-32768:((tmp32s>32767)?32767:tmp32s);
}
}
break;
case 0x08:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
GX->sb[i] *= (EX->sb[i]<0)?-1:((EX->sb[i]>0)?1:0);
break;
case 0x09:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i)
GX->sw[i] *= (EX->sw[i]<0)?-1:((EX->sw[i]>0)?1:0);
break;
case 0x0A:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sd[i] *= (EX->sd[i]<0)?-1:((EX->sd[i]>0)?1:0);
break;
case 0x0B:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i) {
tmp32s = ((((int32_t)(GX->sw[i])*(int32_t)(EX->sw[i]))>>14) + 1)>>1;
GX->uw[i] = tmp32s&0xffff;
}
break;
case 0x10:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i) {
if(emu->xmm[0].ub[i]&0x80)
GX->ub[i] = EX->ub[i];
}
break;
case 0x14:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
if(emu->xmm[0].ud[i]&0x80000000)
GX->ud[i] = EX->ud[i];
}
break;
case 0x15:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<2; ++i) {
if(emu->xmm[0].q[i]&0x8000000000000000LL)
GX->q[i] = EX->q[i];
}
break;
case 0x17:
nextop = F8;
GETEX(0);
GETGX;
RESET_FLAGS(emu);
CONDITIONAL_SET_FLAG(!(GX->u128&EX->u128), F_ZF);
CONDITIONAL_SET_FLAG(!((~GX->u128)&EX->u128), F_CF);
CLEAR_FLAG(F_AF);
CLEAR_FLAG(F_OF);
CLEAR_FLAG(F_SF);
CLEAR_FLAG(F_PF);
break;
case 0x1C:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i) {
GX->ub[i] = abs(EX->sb[i]);
}
break;
case 0x1D:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i) {
GX->uw[i] = abs(EX->sw[i]);
}
break;
case 0x1E:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i) {
GX->ud[i] = abs(EX->sd[i]);
}
break;
case 0x20:
nextop = F8;
GETEX(0);
GETGX;
for(int i=7; i>=0; --i)
GX->sw[i] = EX->sb[i];
break;
case 0x21:
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->sd[i] = EX->sb[i];
break;
case 0x22:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sb[i];
break;
case 0x23:
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->sd[i] = EX->sw[i];
break;
case 0x24:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sw[i];
break;
case 0x25:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = EX->sd[i];
break;
case 0x28:
nextop = F8;
GETEX(0);
GETGX;
GX->sq[1] = ((int64_t)GX->sd[2])*(int64_t)EX->sd[2];
GX->sq[0] = ((int64_t)GX->sd[0])*(int64_t)EX->sd[0];
break;
case 0x29:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = (GX->sq[i]==EX->sq[i])?-1LL:0LL;
break;
case 0x2A:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = EX->q[0];
GX->q[1] = EX->q[1];
break;
case 0x2B:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->uw[i] = (GX->sd[i]<0)?0:((GX->sd[i]>65535)?65535:GX->sd[i]);
if(GX==EX)
GX->q[1] = GX->q[0];
else
for(int i=0; i<4; ++i)
GX->uw[i+4] = (EX->sd[i]<0)?0:((EX->sd[i]>65535)?65535:EX->sd[i]);
break;
case 0x30:
nextop = F8;
GETEX(0);
GETGX;
for(int i=7; i>=0; --i)
GX->uw[i] = EX->ub[i];
break;
case 0x31:
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->ud[i] = EX->ub[i];
break;
case 0x32:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->q[i] = EX->ub[i];
break;
case 0x33:
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i)
GX->ud[i] = EX->uw[i];
break;
case 0x34:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->q[i] = EX->uw[i];
break;
case 0x35:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->q[i] = EX->ud[i];
break;
case 0x37:
nextop = F8;
GETEX(0);
GETGX;
for(int i=1; i>=0; --i)
GX->sq[i] = (GX->sq[i]>EX->sq[i])?-1LL:0LL;
break;
case 0x38:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
if(GX->sb[i]>EX->sb[i])
GX->sb[i] = EX->sb[i];
break;
case 0x39:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]>EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0x3A:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
if(GX->uw[i]>EX->uw[i])
GX->uw[i] = EX->uw[i];
break;
case 0x3B:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->ud[i]>EX->ud[i])
GX->ud[i] = EX->ud[i];
break;
case 0x3C:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
if(GX->sb[i]<EX->sb[i])
GX->sb[i] = EX->sb[i];
break;
case 0x3D:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->sd[i]<EX->sd[i])
GX->sd[i] = EX->sd[i];
break;
case 0x3E:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
if(GX->uw[i]<EX->uw[i])
GX->uw[i] = EX->uw[i];
break;
case 0x3F:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
if(GX->ud[i]<EX->ud[i])
GX->ud[i] = EX->ud[i];
break;
case 0x40:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] *= EX->ud[i];
break;
case 0x41:
nextop = F8;
GETEX(0);
GETGX;
tmp16u = EX->uw[0];
tmp16s = 0;
for(int i=1; i<8; ++i) {
if(EX->uw[i]<tmp16u) {
tmp16u = EX->uw[i];
tmp16s = i;
}
}
GX->q[1] = 0;
GX->uw[0] = tmp16u;
GX->uw[1] = tmp16s;
GX->ud[1] = 0;
break;
case 0xDB:
nextop = F8;
GETEX(0);
GETGX;
if (EX == GX) {
for(int i=0; i<16; ++i)
eax1.ub[i] = EX->ub[i];
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX->ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX->ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
} else {
for(int j=0; j<4; ++j) {
GX->ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
GX->ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
GX->ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
GX->ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
}
}
break;
case 0xDC:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[shiftrows[i]];
for(int i=0; i<16; ++i)
eax1.ub[i] = subbytes[eax1.ub[i]];
for(int j=0; j<4; ++j) {
eax2.ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
eax2.ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
eax2.ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
eax2.ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
GX->q[0] = eax2.q[0] ^ EX->q[0];
GX->q[1] = eax2.q[1] ^ EX->q[1];
break;
case 0xDD:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[shiftrows[i]];
for(int i=0; i<16; ++i)
eax1.ub[i] = subbytes[eax1.ub[i]];
GX->q[0] = eax1.q[0] ^ EX->q[0];
GX->q[1] = eax1.q[1] ^ EX->q[1];
break;
case 0xDE:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[invshiftrows[i]];
for(int i=0; i<16; ++i)
eax1.ub[i] = invsubbytes[eax1.ub[i]];
for(int j=0; j<4; ++j) {
eax2.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
eax2.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
eax2.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
eax2.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
GX->q[0] = eax2.q[0] ^ EX->q[0];
GX->q[1] = eax2.q[1] ^ EX->q[1];
break;
case 0xDF:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
eax1.ub[i] = GX->ub[invshiftrows[i]];
for(int i=0; i<16; ++i)
eax1.ub[i] = invsubbytes[eax1.ub[i]];
GX->q[0] = eax1.q[0] ^ EX->q[0];
GX->q[1] = eax1.q[1] ^ EX->q[1];
break;
case 0xF0:
nextop = F8;
GETED(0);
GETGD;
GD->word[0] = __builtin_bswap16(ED->word[0]);
break;
case 0xF1:
nextop = F8;
GETED(0);
GETGD;
ED->word[0] = __builtin_bswap16(GD->word[0]);
break;
case 0xF6:
nextop = F8;
GETED(0);
GETGD;
CHECK_FLAGS(emu);
if(rex.w) {
if (ACCESS_FLAG(F_CF)) {
tmp64u = 1 + (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF);
tmp64u2 = 1 + GD->q[0] + ED->q[0];
}
else {
tmp64u = (GD->q[0] & 0xFFFFFFFF) + (ED->q[0] & 0xFFFFFFFF);
tmp64u2 = GD->q[0] + ED->q[0];
}
tmp64u = (tmp64u >> 32) + (GD->q[0] >> 32) + (ED->q[0] >> 32);
CONDITIONAL_SET_FLAG(tmp64u & 0x100000000L, F_CF);
GD->q[0] = tmp64u2;
} else {
if (ACCESS_FLAG(F_CF))
GD->q[0] = 1LL + GD->dword[0] + ED->dword[0];
else
GD->q[0] = (uint64_t)GD->dword[0] + ED->dword[0];
CONDITIONAL_SET_FLAG(GD->q[0] & 0x100000000LL, F_CF);
}
break;
default:
return 0;
}
break;
case 0x3A:
opcode = F8;
switch(opcode) {
case 0x08:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u&4)
tmp8u = emu->mxcsr.f.MXCSR_RC;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
for(int i=0; i<4; ++i)
GX->f[i] = nearbyintf(EX->f[i]);
fesetround(round);
break;
}
case ROUND_Down:
for(int i=0; i<4; ++i)
GX->f[i] = floorf(EX->f[i]);
break;
case ROUND_Up:
for(int i=0; i<4; ++i)
GX->f[i] = ceilf(EX->f[i]);
break;
case ROUND_Chop:
for(int i=0; i<4; ++i)
GX->f[i] = truncf(EX->f[i]);
break;
}
break;
case 0x09:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u&4)
tmp8u = emu->mxcsr.f.MXCSR_RC;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
GX->d[0] = nearbyint(EX->d[0]);
GX->d[1] = nearbyint(EX->d[1]);
fesetround(round);
break;
}
case ROUND_Down:
GX->d[0] = floor(EX->d[0]);
GX->d[1] = floor(EX->d[1]);
break;
case ROUND_Up:
GX->d[0] = ceil(EX->d[0]);
GX->d[1] = ceil(EX->d[1]);
break;
case ROUND_Chop:
GX->d[0] = trunc(EX->d[0]);
GX->d[1] = trunc(EX->d[1]);
break;
}
break;
case 0x0A:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u&4)
tmp8u = emu->mxcsr.f.MXCSR_RC;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
GX->f[0] = nearbyintf(EX->f[0]);
fesetround(round);
break;
}
case ROUND_Down:
GX->f[0] = floorf(EX->f[0]);
break;
case ROUND_Up:
GX->f[0] = ceilf(EX->f[0]);
break;
case ROUND_Chop:
GX->f[0] = truncf(EX->f[0]);
break;
}
break;
case 0x0B:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u&4)
tmp8u = emu->mxcsr.f.MXCSR_RC;
else
tmp8u &= 3;
switch(tmp8u) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
GX->d[0] = nearbyint(EX->d[0]);
fesetround(round);
break;
}
case ROUND_Down:
GX->d[0] = floor(EX->d[0]);
break;
case ROUND_Up:
GX->d[0] = ceil(EX->d[0]);
break;
case ROUND_Chop:
GX->d[0] = trunc(EX->d[0]);
break;
}
break;
case 0x0C:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for (int i=0; i<4; ++i) {
if(tmp8u&(1<<i))
GX->ud[i] = EX->ud[i];
}
break;
case 0x0D:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for (int i=0; i<2; ++i) {
if(tmp8u&(1<<i))
GX->q[i] = EX->q[i];
}
break;
case 0x0E:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for (int i=0; i<8; ++i) {
if(tmp8u&(1<<i))
GX->uw[i] = EX->uw[i];
}
break;
case 0x0F:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(tmp8u>31)
{GX->q[0] = GX->q[1] = 0;}
else
{
for (int i=0; i<16; ++i, ++tmp8u)
eax1.ub[i] = (tmp8u>15)?((tmp8u>31)?0:GX->ub[tmp8u-16]):EX->ub[tmp8u];
GX->q[0] = eax1.q[0];
GX->q[1] = eax1.q[1];
}
break;
case 0x14:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
if(MODREG)
ED->q[0] = GX->ub[tmp8u&0x0f];
else
ED->byte[0] = GX->ub[tmp8u&0x0f];
break;
case 0x15:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
if(MODREG)
ED->q[0] = GX->uw[tmp8u&7];
else
ED->word[0] = GX->uw[tmp8u&7];
break;
case 0x16:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
if(rex.w) {
ED->q[0] = GX->q[tmp8u&1];
} else {
if(MODREG)
ED->q[0] = GX->ud[tmp8u&3];
else
ED->dword[0] = GX->ud[tmp8u&3];
}
break;
case 0x17:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
ED->dword[0] = GX->ud[tmp8u&3];
if(MODREG) ED->dword[1] = 0;
break;
case 0x20:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
GX->ub[tmp8u&0xf] = ED->byte[0];
break;
case 0x21:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(MODREG) tmp8s = (tmp8u>>6)&3; else tmp8s = 0;
GX->ud[(tmp8u>>4)&3] = EX->ud[tmp8s];
for(int i=0; i<4; ++i)
if(tmp8u&(1<<i))
GX->ud[i] = 0;
break;
case 0x22:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
if(rex.w)
GX->q[tmp8u&0x1] = ED->q[0];
else
GX->ud[tmp8u&0x3] = ED->dword[0];
break;
case 0x40:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmpf = 0.0f;
for(int i=0; i<4; ++i)
if(tmp8u&(1<<(i+4)))
tmpf += GX->f[i]*EX->f[i];
for(int i=0; i<4; ++i)
GX->f[i] = (tmp8u&(1<<i))?tmpf:0.0f;
break;
case 0x41:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmpd = 0.0;
if(tmp8u&(1<<(4+0)))
tmpd += GX->d[0]*EX->d[0];
if(tmp8u&(1<<(4+1)))
tmpd += GX->d[1]*EX->d[1];
GX->d[0] = (tmp8u&(1<<(0)))?tmpd:0.0;
GX->d[1] = (tmp8u&(1<<(1)))?tmpd:0.0;
break;
case 0x42:
nextop = F8;
GETEX(1);
GETGX;
if(GX==EX) {
eax1 = *EX;
EX=&eax1;
}
tmp8u = F8;
{
int src = tmp8u&3;
int dst = (tmp8u>>2)&1;
int b[11];
for (int i=0; i<11; ++i)
b[i] = GX->ub[dst*4+i];
for(int i=0; i<8; ++i) {
int tmp = abs(b[i+0]-EX->ub[src*4+0]);
tmp += abs(b[i+1]-EX->ub[src*4+1]);
tmp += abs(b[i+2]-EX->ub[src*4+2]);
tmp += abs(b[i+3]-EX->ub[src*4+3]);
GX->uw[i] = tmp;
}
}
break;
case 0x44:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
{
int g = (tmp8u&1)?1:0;
int e = (tmp8u&0b10000)?1:0;
__int128 result = 0;
__int128 op2 = EX->q[e];
for (int i=0; i<64; ++i)
if(GX->q[g]&(1LL<<i))
result ^= (op2<<i);
GX->q[0] = result&0xffffffffffffffffLL;
GX->q[1] = (result>>64)&0xffffffffffffffffLL;
}
break;
case 0x60:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, GX, R_EAX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
emu->xmm[0].uw[0] = tmp32u;
}
break;
case 0x61:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmp32u = sse42_compare_string_explicit_len(emu, EX, R_EDX, GX, R_EAX, tmp8u);
if(!tmp32u)
R_RCX = (tmp8u&1)?8:16;
else if(tmp8u&0b1000000)
R_RCX = 31-__builtin_clz(tmp32u);
else
R_RCX = __builtin_ffs(tmp32u) - 1;
break;
case 0x62:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmp32u = sse42_compare_string_implicit_len(emu, EX, GX, tmp8u);
if(tmp8u&0b1000000) {
switch(tmp8u&1) {
case 0: for(int i=0; i<16; ++i) emu->xmm[0].ub[i] = ((tmp32u>>i)&1)?0xff:0x00; break;
case 1: for(int i=0; i<8; ++i) emu->xmm[0].uw[i] = ((tmp32u>>i)&1)?0xffff:0x0000; break;
}
} else {
emu->xmm[0].q[1] = emu->xmm[0].q[0] = 0;
emu->xmm[0].uw[0] = tmp32u;
}
break;
case 0x63:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
tmp32u = sse42_compare_string_implicit_len(emu, EX, GX, tmp8u);
if(!tmp32u)
R_RCX = (tmp8u&1)?8:16;
else if(tmp8u&0b1000000)
R_RCX = 31-__builtin_clz(tmp32u);
else
R_RCX = __builtin_ffs(tmp32u) - 1;
break;
case 0xDF:
nextop = F8;
GETEX(1);
GETGX;
tmp32u = F8;
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= tmp32u;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= tmp32u;
break;
default:
return 0;
}
break;
GOCOND(0x40
, nextop = F8;
CHECK_FLAGS(emu);
GETEW(0);
GETGW;
, if(rex.w) GW->q[0] = EW->q[0]; else GW->word[0] = EW->word[0];
,,
)
case 0x50:
nextop = F8;
GETEX(0);
GETGD;
GD->q[0] = 0;
for(int i=0; i<2; ++i)
GD->dword[0] |= ((EX->q[i]>>63)&1)<<i;
break;
case 0x51:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
if(EX->d[i]<0.0)
GX->d[i] = -NAN;
else
#endif
GX->d[i] = sqrt(EX->d[i]);
}
break;
case 0x54:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] &= EX->q[0];
GX->q[1] &= EX->q[1];
break;
case 0x55:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = (~GX->q[0]) & EX->q[0];
GX->q[1] = (~GX->q[1]) & EX->q[1];
break;
case 0x56:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] |= EX->q[0];
GX->q[1] |= EX->q[1];
break;
case 0x57:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
case 0x58:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)!=(GX->q[i]&0x8000000000000000LL)))
GX->d[i] = -NAN;
else
#endif
GX->d[i] += EX->d[i];
}
break;
case 0x59:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
if((isinf(GX->d[i]) && EX->d[i]==0.0) || (isinf(EX->d[i]) && GX->d[i]==0.0))
GX->d[i] = -NAN;
else
#endif
GX->d[i] *= EX->d[i];
}
break;
case 0x5A:
nextop = F8;
GETEX(0);
GETGX;
GX->f[0] = EX->d[0];
GX->f[1] = EX->d[1];
GX->q[1] = 0;
break;
case 0x5B:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
if(isnanf(EX->f[i]))
tmp64s = INT32_MIN;
else
switch(emu->mxcsr.f.MXCSR_RC) {
case ROUND_Nearest: {
int round = fegetround();
fesetround(FE_TONEAREST);
tmp64s = nearbyintf(EX->f[i]);
fesetround(round);
break;
}
case ROUND_Down:
tmp64s = floorf(EX->f[i]);
break;
case ROUND_Up:
tmp64s = ceilf(EX->f[i]);
break;
case ROUND_Chop:
tmp64s = EX->f[i];
break;
}
if (tmp64s==(int32_t)tmp64s) {
GX->sd[i] = (int32_t)tmp64s;
} else {
GX->sd[i] = INT32_MIN;
}
}
break;
case 0x5C:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<2; ++i) {
#ifndef NOALIGN
if((isinf(GX->d[i]) && isinf(EX->d[i]) && (EX->q[i]&0x8000000000000000LL)==(GX->q[i]&0x8000000000000000LL)))
GX->d[i] = -NAN;
else
#endif
GX->d[i] -= EX->d[i];
}
break;
case 0x5D:
nextop = F8;
GETEX(0);
GETGX;
if (isnan(GX->d[0]) || isnan(EX->d[0]) || isless(EX->d[0], GX->d[0]))
GX->d[0] = EX->d[0];
if (isnan(GX->d[1]) || isnan(EX->d[1]) || isless(EX->d[1], GX->d[1]))
GX->d[1] = EX->d[1];
break;
case 0x5E:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<2; ++i) {
#ifndef NOALIGN
is_nan = isnan(GX->d[i]) || isnan(EX->d[i]);
#endif
GX->d[i] /= EX->d[i];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[i]))
GX->d[i] = -NAN;
#endif
}
break;
case 0x5F:
nextop = F8;
GETEX(0);
GETGX;
if (isnan(GX->d[0]) || isnan(EX->d[0]) || isgreater(EX->d[0], GX->d[0]))
GX->d[0] = EX->d[0];
if (isnan(GX->d[1]) || isnan(EX->d[1]) || isgreater(EX->d[1], GX->d[1]))
GX->d[1] = EX->d[1];
break;
case 0x60:
nextop = F8;
GETEX(0);
GETGX;
for(int i=7; i>=0; --i) {
GX->ub[2 * i] = GX->ub[i];
GX->ub[2 * i + 1] = EX->ub[i];
}
break;
case 0x61:
nextop = F8;
GETEX(0);
GETGX;
for(int i=3; i>=0; --i) {
GX->uw[2 * i] = GX->uw[i];
GX->uw[2 * i + 1] = EX->uw[i];
}
break;
case 0x62:
nextop = F8;
GETEX(0);
GETGX;
GX->ud[3] = EX->ud[1];
GX->ud[2] = GX->ud[1];
GX->ud[1] = EX->ud[0];
break;
case 0x63:
nextop = F8;
GETEX(0);
GETGX;
if(GX==EX) {
for(int i=0; i<8; ++i)
GX->sb[i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
GX->q[1] = GX->q[0];
} else {
for(int i=0; i<8; ++i)
GX->sb[i] = (GX->sw[i]<-128)?-128:((GX->sw[i]>127)?127:GX->sw[i]);
for(int i=0; i<8; ++i)
GX->sb[8+i] = (EX->sw[i]<-128)?-128:((EX->sw[i]>127)?127:EX->sw[i]);
}
break;
case 0x64:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
GX->ub[i] = (GX->sb[i]>EX->sb[i])?0xFF:0x00;
break;
case 0x65:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
GX->uw[i] = (GX->sw[i]>EX->sw[i])?0xFFFF:0x0000;
break;
case 0x66:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i)
GX->ud[i] = (GX->sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000;
break;
case 0x67:
nextop = F8;
GETEX(0);
GETGX;
if(GX==EX) {
for(int i=0; i<8; ++i)
GX->ub[i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
GX->q[1] = GX->q[0];
} else {
for(int i=0; i<8; ++i)
GX->ub[i] = (GX->sw[i]<0)?0:((GX->sw[i]>0xff)?0xff:GX->sw[i]);
for(int i=0; i<8; ++i)
GX->ub[8+i] = (EX->sw[i]<0)?0:((EX->sw[i]>0xff)?0xff:EX->sw[i]);
}
break;
case 0x68:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
GX->ub[2 * i] = GX->ub[i + 8];
GX->ub[2 * i + 1] = EX->ub[i + 8];
}
break;
case 0x69:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<4; ++i) {
GX->uw[2 * i] = GX->uw[i + 4];
GX->uw[2 * i + 1] = EX->uw[i + 4];
}
break;
case 0x6A:
nextop = F8;
GETEX(0);
GETGX;
GX->ud[0] = GX->ud[2];
GX->ud[1] = EX->ud[2];
GX->ud[2] = GX->ud[3];
GX->ud[3] = EX->ud[3];
break;
case 0x6B:
nextop = F8;
GETEX(0);
GETGX;
if(GX==EX) {
for(int i=0; i<4; ++i)
GX->sw[i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
GX->q[1] = GX->q[0];
} else {
for(int i=0; i<4; ++i)
GX->sw[i] = (GX->sd[i]<-32768)?-32768:((GX->sd[i]>32767)?32767:GX->sd[i]);
for(int i=0; i<4; ++i)
GX->sw[4+i] = (EX->sd[i]<-32768)?-32768:((EX->sd[i]>32767)?32767:EX->sd[i]);
}
break;
case 0x6C:
nextop = F8;
GETEX(0);
GETGX;
GX->q[1] = EX->q[0];
break;
case 0x6D:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = GX->q[1];
GX->q[1] = EX->q[1];
break;
case 0x6E:
nextop = F8;
GETED(0);
GETGX;
if(rex.w)
GX->q[0] = ED->q[0];
else
GX->q[0] = ED->dword[0];
GX->q[1] = 0;
break;
case 0x6F:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = EX->q[0];
GX->q[1] = EX->q[1];
break;
case 0x70:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
if(EX==GX) {eax1 = *GX; EX = &eax1;}
for (int i=0; i<4; ++i)
GX->ud[i] = EX->ud[(tmp8u>>(i*2))&3];
break;
case 0x71:
nextop = F8;
GETEX(1);
switch((nextop>>3)&7) {
case 2:
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else
for (int i=0; i<8; ++i) EX->uw[i] >>= tmp8u;
break;
case 4:
tmp8u = F8;
if(tmp8u>15) tmp8u=15;
for (int i=0; i<8; ++i) EX->sw[i] >>= tmp8u;
break;
case 6:
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else
for (int i=0; i<8; ++i) EX->uw[i] <<= tmp8u;
break;
default:
return 0;
}
break;
case 0x72:
nextop = F8;
GETEX(1);
switch((nextop>>3)&7) {
case 2:
tmp8u = F8;
if(tmp8u>31)
{EX->q[0] = EX->q[1] = 0;}
else
for (int i=0; i<4; ++i) EX->ud[i] >>= tmp8u;
break;
case 4:
tmp8u = F8;
if(tmp8u>31) tmp8u=31;
for (int i=0; i<4; ++i) EX->sd[i] >>= tmp8u;
break;
case 6:
tmp8u = F8;
if(tmp8u>31)
{EX->q[0] = EX->q[1] = 0;}
else
for (int i=0; i<4; ++i) EX->ud[i] <<= tmp8u;
break;
default:
return 0;
}
break;
case 0x73:
nextop = F8;
GETEX(1);
switch((nextop>>3)&7) {
case 2:
tmp8u = F8;
if(tmp8u>63)
{EX->q[0] = EX->q[1] = 0;}
else
{EX->q[0] >>= tmp8u; EX->q[1] >>= tmp8u;}
break;
case 3:
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else if (tmp8u!=0) {
tmp8u*=8;
if (tmp8u < 64) {
EX->q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u));
EX->q[1] = (EX->q[1] >> tmp8u);
} else {
EX->q[0] = EX->q[1] >> (tmp8u - 64);
EX->q[1] = 0;
}
}
break;
case 6:
tmp8u = F8;
if(tmp8u>63)
{EX->q[0] = EX->q[1] = 0;}
else
{EX->q[0] <<= tmp8u; EX->q[1] <<= tmp8u;}
break;
case 7:
tmp8u = F8;
if(tmp8u>15)
{EX->q[0] = EX->q[1] = 0;}
else if (tmp8u!=0) {
tmp8u*=8;
if (tmp8u < 64) {
EX->q[1] = (EX->q[1] << tmp8u) | (EX->q[0] >> (64 - tmp8u));
EX->q[0] = (EX->q[0] << tmp8u);
} else {
EX->q[1] = EX->q[0] << (tmp8u - 64);
EX->q[0] = 0;
}
}
break;
default:
return 0;
}
break;
case 0x74:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
GX->ub[i] = (GX->ub[i]==EX->ub[i])?0xff:0;
break;
case 0x75:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i)
GX->uw[i] = (GX->uw[i]==EX->uw[i])?0xffff:0;
break;
case 0x76:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->ud[i] = (GX->ud[i]==EX->ud[i])?0xffffffff:0;
break;
case 0x7C:
nextop = F8;
GETEX(0);
GETGX;
#ifndef NOALIGN
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
#endif
GX->d[0] += GX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
#endif
if(EX==GX) {
GX->d[1] = GX->d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX->d[1] = EX->d[0] + EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
#endif
}
break;
case 0x7D:
nextop = F8;
GETEX(0);
GETGX;
#ifndef NOALIGN
is_nan = isnan(GX->d[0]) || isnan(GX->d[1]);
#endif
GX->d[0] -= GX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[0]))
GX->d[0] = -NAN;
#endif
if(EX==GX) {
GX->d[1] = GX->d[0];
} else {
#ifndef NOALIGN
is_nan = isnan(EX->d[0]) || isnan(EX->d[1]);
#endif
GX->d[1] = EX->d[0] - EX->d[1];
#ifndef NOALIGN
if(!is_nan && isnan(GX->d[1]))
GX->d[1] = -NAN;
#endif
}
break;
case 0x7E:
nextop = F8;
GETED(0);
GETGX;
if(rex.w)
ED->q[0] = GX->q[0];
else {
if(MODREG)
ED->q[0] = GX->ud[0];
else
ED->dword[0] = GX->ud[0];
}
break;
case 0x7F:
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0xA3:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 0xA4:
case 0xA5:
nextop = F8;
GETEW((nextop==0xA4)?1:0);
GETGW;
if(opcode==0xA4)
tmp8u = F8;
else
tmp8u = R_CL;
if(rex.w)
EW->q[0] = shld64(emu, EW->q[0], GW->q[0], tmp8u);
else
EW->word[0] = shld16(emu, EW->word[0], GW->word[0], tmp8u);
break;
case 0xAB:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else {
EW->q[0] |= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else {
EW->word[0] |= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
break;
case 0xAC:
case 0xAD:
nextop = F8;
GETEW((nextop==0xAC)?1:0);
GETGW;
if(opcode==0xAC)
tmp8u = F8;
else
tmp8u = R_CL;
if(rex.w)
EW->q[0] = shrd64(emu, EW->q[0], GW->q[0], tmp8u);
else
EW->word[0] = shrd16(emu, EW->word[0], GW->word[0], tmp8u);
break;
case 0xAF:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
GW->q[0] = imul64(emu, GW->q[0], EW->q[0]);
else
GW->word[0] = imul16(emu, GW->word[0], EW->word[0]);
break;
case 0xB1:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w) {
cmp64(emu, R_RAX, EW->q[0]);
if(ACCESS_FLAG(F_ZF)) {
EW->q[0] = GW->q[0];
} else {
R_RAX = EW->q[0];
}
} else {
cmp16(emu, R_AX, EW->word[0]);
if(ACCESS_FLAG(F_ZF)) {
EW->word[0] = GW->word[0];
} else {
R_AX = EW->word[0];
}
}
break;
case 0xB3:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
tmp32s = rex.w?GW->sdword[0]:GW->sword[0];
tmp8u=tmp32s&(rex.w?63:15);
tmp32s >>= (rex.w?6:4);
if(!MODREG)
{
#ifdef TEST_INTERPRETER
test->memaddr=((test->memaddr)+(tmp32s<<(rex.w?3:1)));
if(rex.w)
*(uint64_t*)test->mem = *(uint64_t*)test->memaddr;
else
*(uint16_t*)test->mem = *(uint16_t*)test->memaddr;
#else
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp32s<<(rex.w?3:1)));
#endif
}
if(rex.w) {
if(EW->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
EW->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
break;
case 0xB6:
nextop = F8;
GETEB(0);
GETGW;
if(rex.w)
GW->q[0] = EB->byte[0];
else
GW->word[0] = EB->byte[0];
break;
case 0xB7:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
GW->q[0] = EW->word[0];
else
GW->word[0] = EW->word[0];
break;
case 0xBA:
nextop = F8;
switch((nextop>>3)&7) {
case 4:
CHECK_FLAGS(emu);
GETEW(1);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
}
break;
case 5:
CHECK_FLAGS(emu);
GETEW(1);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
} else {
ED->q[0] ^= (1LL<<tmp8u);
CLEAR_FLAG(F_CF);
}
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
} else {
EW->word[0] ^= (1<<tmp8u);
CLEAR_FLAG(F_CF);
}
}
break;
case 6:
CHECK_FLAGS(emu);
GETEW(1);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u)) {
SET_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else
CLEAR_FLAG(F_CF);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u)) {
SET_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
} else
CLEAR_FLAG(F_CF);
}
break;
case 7:
CHECK_FLAGS(emu);
GETEW(1);
GETGW;
tmp8u = F8;
if(rex.w) {
tmp8u&=63;
if(ED->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
ED->q[0] ^= (1LL<<tmp8u);
} else {
tmp8u&=15;
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
}
break;
default:
return 0;
}
break;
case 0xBB:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
tmp64s = rex.w?GW->sq[0]:GW->sword[0];
tmp8u=tmp64s&(rex.w?63:15);
tmp64s >>= (rex.w?6:4);
if(!MODREG)
{
EW=(reg64_t*)(((uintptr_t)(EW))+(tmp64s<<(rex.w?3:1)));
}
if(rex.w) {
if(EW->q[0] & (1LL<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->q[0] ^= (1LL<<tmp8u);
} else {
if(EW->word[0] & (1<<tmp8u))
SET_FLAG(F_CF);
else
CLEAR_FLAG(F_CF);
EW->word[0] ^= (1<<tmp8u);
}
break;
case 0xBC:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
if(rex.w) {
tmp64u = EW->q[0];
if(tmp64u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;
GW->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
} else {
tmp16u = EW->word[0];
if(tmp16u) {
CLEAR_FLAG(F_ZF);
tmp8u = 0;
while(!(tmp16u&(1<<tmp8u))) ++tmp8u;
GW->word[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
}
break;
case 0xBD:
CHECK_FLAGS(emu);
nextop = F8;
GETEW(0);
GETGW;
if(rex.w) {
tmp64u = EW->q[0];
if(tmp64u) {
CLEAR_FLAG(F_ZF);
tmp8u = 63;
while(!(tmp64u&(1LL<<tmp8u))) --tmp8u;
GW->q[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
} else {
tmp16u = EW->word[0];
if(tmp16u) {
CLEAR_FLAG(F_ZF);
tmp8u = 15;
while(!(tmp16u&(1<<tmp8u))) --tmp8u;
GW->word[0] = tmp8u;
} else {
SET_FLAG(F_ZF);
}
}
break;
case 0xBE:
nextop = F8;
GETEB(0);
GETGW;
if(rex.w)
GW->sq[0] = EB->sbyte[0];
else
GW->sword[0] = EB->sbyte[0];
break;
case 0xBF:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w)
GW->sq[0] = EB->sword[0];
else
GW->sword[0] = EB->sword[0];
break;
case 0xC1:
nextop = F8;
GETEW(0);
GETGW;
if(rex.w) {
tmp64u = add64(emu, EW->q[0], GW->q[0]);
GW->q[0] = EW->q[0];
EW->q[0] = tmp64u;
} else {
tmp16u = add16(emu, EW->word[0], GW->word[0]);
GW->word[0] = EW->word[0];
EW->word[0] = tmp16u;
}
break;
case 0xC2:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
for(int i=0; i<2; ++i) {
tmp8s = 0;
switch(tmp8u&7) {
case 0: tmp8s=(GX->d[i] == EX->d[i]); break;
case 1: tmp8s=isless(GX->d[i], EX->d[i]); break;
case 2: tmp8s=islessequal(GX->d[i], EX->d[i]); break;
case 3: tmp8s=isnan(GX->d[i]) || isnan(EX->d[i]); break;
case 4: tmp8s=isnan(GX->d[i]) || isnan(EX->d[i]) || (GX->d[i] != EX->d[i]); break;
case 5: tmp8s=isnan(GX->d[i]) || isnan(EX->d[i]) || isgreaterequal(GX->d[i], EX->d[i]); break;
case 6: tmp8s=isnan(GX->d[i]) || isnan(EX->d[i]) || isgreater(GX->d[i], EX->d[i]); break;
case 7: tmp8s=!isnan(GX->d[i]) && !isnan(EX->d[i]); break;
}
GX->q[i]=(tmp8s)?0xffffffffffffffffLL:0LL;
}
break;
case 0xC4:
nextop = F8;
GETED(1);
GETGX;
tmp8u = F8;
GX->uw[tmp8u&7] = ED->word[0];
break;
case 0xC5:
nextop = F8;
GETEX(1);
GETGD;
tmp8u = F8;
GD->q[0] = EX->uw[tmp8u&7];
break;
case 0xC6:
nextop = F8;
GETEX(1);
GETGX;
tmp8u = F8;
eax1.q[0] = GX->q[tmp8u&1];
eax1.q[1] = EX->q[(tmp8u>>1)&1];
GX->q[0] = eax1.q[0];
GX->q[1] = eax1.q[1];
break;
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
tmp8u = (opcode&7)+(rex.b<<3);
if(rex.w) {
emu->regs[tmp8u].q[0] = __builtin_bswap64(emu->regs[tmp8u].q[0]);
} else {
emu->regs[tmp8u].word[0] = __builtin_bswap16(emu->regs[tmp8u].word[0]);
}
break;
case 0xD0:
nextop = F8;
GETEX(0);
GETGX;
GX->d[0] -= EX->d[0];
GX->d[1] += EX->d[1];
break;
case 0xD1:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>15)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<8; ++i) GX->uw[i] >>= tmp8u;}
break;
case 0xD2:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>31)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<4; ++i) GX->ud[i] >>= tmp8u;}
break;
case 0xD3:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>63)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<2; ++i) GX->q[i] >>= tmp8u;}
break;
case 0xD4:
nextop = F8;
GETEX(0);
GETGX;
GX->sq[0] += EX->sq[0];
GX->sq[1] += EX->sq[1];
break;
case 0xD5:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->sw[i] * EX->sw[i];
GX->sw[i] = tmp32s&0xffff;
}
break;
case 0xD6:
nextop = F8;
GETEX8(0);
GETGX;
EX->q[0] = GX->q[0];
if(MODREG)
EX->q[1] = 0;
break;
case 0xD7:
nextop = F8;
if(MODREG) {
GETEX(0);
GETGD;
GD->q[0] = 0;
for (int i=0; i<16; ++i)
if(EX->ub[i]&0x80)
GD->dword[0] |= (1<<i);
} else
return 0;
break;
case 0xD8:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX->ub[i] - EX->ub[i];
GX->ub[i] = (tmp16s<0)?0:tmp16s;
}
break;
case 0xD9:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->uw[i] - EX->uw[i];
GX->uw[i] = (tmp32s<0)?0:tmp32s;
}
break;
case 0xDA:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
if(EX->ub[i]<GX->ub[i]) GX->ub[i] = EX->ub[i];
break;
case 0xDB:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] &= EX->q[0];
GX->q[1] &= EX->q[1];
break;
case 0xDC:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX->ub[i] + EX->ub[i];
GX->ub[i] = (tmp16s>255)?255:tmp16s;
}
break;
case 0xDD:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->uw[i] + EX->uw[i];
GX->uw[i] = (tmp32s>65535)?65535:tmp32s;
}
break;
case 0xDE:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
if(EX->ub[i]>GX->ub[i]) GX->ub[i] = EX->ub[i];
break;
case 0xDF:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] = (~(GX->q[0])) & EX->q[0];
GX->q[1] = (~(GX->q[1])) & EX->q[1];
break;
case 0xE0:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<16; ++i)
GX->ub[i] = ((uint16_t)GX->ub[i] + EX->ub[i] + 1)>>1;
break;
case 0xE1:
nextop = F8;
GETEX(0);
GETGX;
tmp8u=(EX->q[0]>15)?15:EX->ub[0];
for (int i=0; i<8; ++i)
GX->sw[i] >>= tmp8u;
break;
case 0xE2:
nextop = F8;
GETEX(0);
GETGX;
tmp8u=(EX->q[0]>31)?31:EX->ub[0];
for (int i=0; i<4; ++i)
GX->sd[i] >>= tmp8u;
break;
case 0xE3:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i)
GX->uw[i] = ((uint32_t)GX->uw[i] + EX->uw[i] + 1)>>1;
break;
case 0xE4:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32u = (uint32_t)GX->uw[i] * EX->uw[i];
GX->uw[i] = (tmp32u>>16)&0xffff;
}
break;
case 0xE5:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->sw[i] * EX->sw[i];
GX->uw[i] = (tmp32s>>16)&0xffff;
}
break;
case 0xE6:
nextop = F8;
GETEX(0);
GETGX;
if(isnan(EX->d[0]) || isinf(EX->d[0]) || EX->d[0]>0x7fffffff)
GX->sd[0] = 0x80000000;
else
GX->sd[0] = EX->d[0];
if(isnan(EX->d[1]) || isinf(EX->d[1]) || EX->d[1]>0x7fffffff)
GX->sd[1] = 0x80000000;
else
GX->sd[1] = EX->d[1];
GX->q[1] = 0;
break;
case 0xE7:
nextop = F8;
GETEX(0);
GETGX;
EX->q[0] = GX->q[0];
EX->q[1] = GX->q[1];
break;
case 0xE8:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX->sb[i] - EX->sb[i];
GX->sb[i] = (tmp16s<-128)?-128:((tmp16s>127)?127:tmp16s);
}
break;
case 0xE9:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->sw[i] - EX->sw[i];
GX->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0xEA:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<8; ++i)
GX->sw[i] = (GX->sw[i]<EX->sw[i])?GX->sw[i]:EX->sw[i];
break;
case 0xEB:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] |= EX->q[0];
GX->q[1] |= EX->q[1];
break;
case 0xEC:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i) {
tmp16s = (int16_t)GX->sb[i] + EX->sb[i];
GX->sb[i] = (tmp16s>127)?127:((tmp16s<-128)?-128:tmp16s);
}
break;
case 0xED:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i) {
tmp32s = (int32_t)GX->sw[i] + EX->sw[i];
GX->sw[i] = (tmp32s>32767)?32767:((tmp32s<-32768)?-32768:tmp32s);
}
break;
case 0xEE:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
GX->sw[i] = (GX->sw[i]>EX->sw[i])?GX->sw[i]:EX->sw[i];
break;
case 0xEF:
nextop = F8;
GETEX(0);
GETGX;
GX->q[0] ^= EX->q[0];
GX->q[1] ^= EX->q[1];
break;
case 0xF1:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>15)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<8; ++i) GX->uw[i] <<= tmp8u;}
break;
case 0xF2:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>31)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<4; ++i) GX->ud[i] <<= tmp8u;}
break;
case 0xF3:
nextop = F8;
GETEX(0);
GETGX;
if(EX->q[0]>63)
{GX->q[0] = GX->q[1] = 0;}
else
{tmp8u=EX->ub[0]; for (int i=0; i<2; ++i) GX->q[i] <<= tmp8u;}
break;
case 0xF4:
nextop = F8;
GETEX(0);
GETGX;
GX->q[1] = (uint64_t)EX->ud[2]*GX->ud[2];
GX->q[0] = (uint64_t)EX->ud[0]*GX->ud[0];
break;
case 0xF5:
nextop = F8;
GETEX(0);
GETGX;
for (int i=0; i<4; ++i)
GX->sd[i] = (int32_t)(GX->sw[i*2+0])*EX->sw[i*2+0] + (int32_t)(GX->sw[i*2+1])*EX->sw[i*2+1];
break;
case 0xF6:
nextop = F8;
GETEX(0);
GETGX;
tmp32u = 0;
for (int i=0; i<8; ++i)
tmp32u += (GX->ub[i]>EX->ub[i])?(GX->ub[i] - EX->ub[i]):(EX->ub[i] - GX->ub[i]);
GX->q[0] = tmp32u;
tmp32u = 0;
for (int i=8; i<16; ++i)
tmp32u += (GX->ub[i]>EX->ub[i])?(GX->ub[i] - EX->ub[i]):(EX->ub[i] - GX->ub[i]);
GX->q[1] = tmp32u;
break;
case 0xF7:
nextop = F8;
GETEX(0);
GETGX;
opex2 = (sse_regs_t *)(R_RDI);
for (int i=0; i<16; ++i) {
if(EX->ub[i]&0x80)
opex2->ub[i] = GX->ub[i];
}
break;
case 0xF8:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
GX->sb[i] -= EX->sb[i];
break;
case 0xF9:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
GX->sw[i] -= EX->sw[i];
break;
case 0xFA:
nextop = F8;
GETEX(0);
GETGX;
GX->sd[0] -= EX->sd[0];
GX->sd[1] -= EX->sd[1];
GX->sd[2] -= EX->sd[2];
GX->sd[3] -= EX->sd[3];
break;
case 0xFB:
nextop = F8;
GETEX(0);
GETGX;
GX->sq[0] -= EX->sq[0];
GX->sq[1] -= EX->sq[1];
break;
case 0xFC:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<16; ++i)
GX->sb[i] += EX->sb[i];
break;
case 0xFD:
nextop = F8;
GETEX(0);
GETGX;
for(int i=0; i<8; ++i)
GX->sw[i] += EX->sw[i];
break;
case 0xFE:
nextop = F8;
GETEX(0);
GETGX;
GX->sd[0] += EX->sd[0];
GX->sd[1] += EX->sd[1];
GX->sd[2] += EX->sd[2];
GX->sd[3] += EX->sd[3];
break;
default:
return 0;
}
return addr;
}