Merge remote-tracking branch

'origin/GP-6675_ghidorahrex_PR-9097_jcrussell_x86-bug-fixes' into patch
(Closes #9097)
This commit is contained in:
Ryan Kurtz
2026-05-14 05:08:10 -04:00
6 changed files with 174 additions and 128 deletions
@@ -1453,6 +1453,7 @@ define pcodeop vmpsadbw_avx ;
YmmReg1[128,32] = vexVVVV_YmmReg[128,32] f* m[128,32];
YmmReg1[160,32] = vexVVVV_YmmReg[160,32] f* m[160,32];
YmmReg1[192,32] = vexVVVV_YmmReg[192,32] f* m[192,32];
YmmReg1[224,32] = vexVVVV_YmmReg[224,32] f* m[224,32];
ZmmReg1 = zext(YmmReg1);
}
@@ -3054,9 +3055,9 @@ define pcodeop vtestps_avx ;
local val1 = YmmReg2_m256;
local val2 = YmmReg1;
local ztest = val1 & val2;
ZF = (ztest[31,1] | ztest[63,1] | ztest[95,1] | ztest[127,1] | ztest[160,1] | ztest[191,1] | ztest[224,1] | ztest[255,1]) == 0;
ZF = (ztest[31,1] | ztest[63,1] | ztest[95,1] | ztest[127,1] | ztest[159,1] | ztest[191,1] | ztest[223,1] | ztest[255,1]) == 0;
local ctest = val1 & ~val2;
CF = (ctest[31,1] | ctest[63,1] | ctest[95,1] | ctest[127,1] | ctest[160,1] | ctest[191,1] | ctest[224,1] | ctest[255,1]) == 0;
CF = (ctest[31,1] | ctest[63,1] | ctest[95,1] | ctest[127,1] | ctest[159,1] | ctest[191,1] | ctest[223,1] | ctest[255,1]) == 0;
AF = 0;
OF = 0;
PF = 0;
@@ -147,9 +147,10 @@ define pcodeop vandps_avx512vl ;
:VANDPS YmmReg1^YmmOpMask32, evexV5_YmmReg, YmmReg2_m256_m32bcst is $(EVEX_NONE) & $(VEX_L256) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_W0) & evexV5_YmmReg; byte=0x54; (YmmReg1 & ZmmReg1 & YmmOpMask32) ... & YmmReg2_m256_m32bcst
[ evexD8Type = 0; evexTType = 0; ] # (TupleType FV)
{
local tmp:32 = vandps_avx512vl( evexV5_YmmReg, YmmReg2_m256_m32bcst );
YmmResult = vandps_avx512vl( evexV5_YmmReg, YmmReg2_m256_m32bcst );
YmmMask = YmmReg1;
build YmmOpMask32;
ZmmReg1 = zext(YmmResult);
}
@@ -1545,7 +1546,7 @@ define pcodeop vmovdqu64_avx512f ;
local src1 = evexV5_XmmReg[64,64];
local src2 = XmmReg2[64,64];
XmmReg1[0,64] = src2;
XmmReg1[64,64] = src2;
XmmReg1[64,64] = src1;
ZmmReg1 = zext(XmmReg1);
}
@@ -1556,7 +1557,7 @@ define pcodeop vmovhpd_avx512f ;
{
local src1 = evexV5_XmmReg[0,64];
local src2 = m64[0,64];
XmmReg1[0,64] = src2;
XmmReg1[0,64] = src1;
XmmReg1[64,64] = src2;
ZmmReg1 = zext(XmmReg1);
}
@@ -5486,10 +5487,11 @@ define pcodeop vpsubsw_avx512vl ;
}
# PSUBSB/PSUBSW 4-480 PAGE 1600 LINE 83302
define pcodeop psubsw_avx512bw ;
:PSUBSW ZmmReg1^ZmmOpMask16, evexV5_ZmmReg, ZmmReg2_m512 is $(VEX_NDS) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & evexV5_ZmmReg; byte=0xE9; (ZmmReg1 & ZmmOpMask16) ... & ZmmReg2_m512
define pcodeop vpsubsw_avx512bw ;
:VPSUBSW ZmmReg1^ZmmOpMask16, evexV5_ZmmReg, ZmmReg2_m512 is $(EVEX_NONE) & $(EVEX_L512) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_WIG) & evexV5_ZmmReg; byte=0xE9; (ZmmReg1 & ZmmOpMask16) ... & ZmmReg2_m512
{
ZmmReg1 = psubsw_avx512bw( evexV5_ZmmReg, ZmmReg2_m512 );
ZmmResult = vpsubsw_avx512bw( evexV5_ZmmReg, ZmmReg2_m512 );
ZmmMask = ZmmReg1;
build ZmmOpMask16;
ZmmReg1 = ZmmResult;
}
@@ -6119,9 +6121,7 @@ define pcodeop vucomisd_avx512f ;
:VUCOMISD XmmReg1, XmmReg2_m64 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x2E; (XmmReg1 & ZmmReg1) ... & XmmReg2_m64
[ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S)
{
local tmp:16 = vucomisd_avx512f( XmmReg2_m64 );
ZmmReg1 = zext(tmp);
# TODO set flags AF, CF, OF, PF, SF, ZF
fucompe(XmmReg1[0,64], XmmReg2_m64[0,64]);
}
# UCOMISS 4-685 PAGE 1805 LINE 93507
@@ -6129,9 +6129,7 @@ define pcodeop vucomiss_avx512f ;
:VUCOMISS XmmReg1, XmmReg2_m32 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_NONE) & $(VEX_0F) & $(VEX_W0); byte=0x2E; (XmmReg1 & ZmmReg1) ... & XmmReg2_m32
[ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S)
{
local tmp:16 = vucomiss_avx512f( XmmReg2_m32 );
ZmmReg1 = zext(tmp);
# TODO set flags AF, CF, OF, PF, SF, ZF
fucompe(XmmReg1[0,32], XmmReg2_m32[0,32]);
}
# UNPCKHPD 4-688 PAGE 1808 LINE 93629
@@ -9330,18 +9328,18 @@ define pcodeop vfpclassps_avx512dq ;
# VFPCLASSSD 5-247 PAGE 2071 LINE 106722
define pcodeop vfpclasssd_avx512dq ;
:VFPCLASSSD KReg_reg AVXOpMask, XmmReg2_m64 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & AVXOpMask; byte=0x67; KReg_reg ... & XmmReg2_m64
:VFPCLASSSD KReg_reg AVXOpMask, XmmReg2_m64, imm8 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & AVXOpMask; byte=0x67; KReg_reg ... & XmmReg2_m64; imm8
[ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S)
{
KReg_reg = vfpclasssd_avx512dq( XmmReg2_m64, AVXOpMask );
KReg_reg = vfpclasssd_avx512dq( XmmReg2_m64, AVXOpMask, imm8:1 );
}
# VFPCLASSSS 5-249 PAGE 2073 LINE 106810
define pcodeop vfpclassss_avx512dq ;
:VFPCLASSSS KReg_reg AVXOpMask, XmmReg2_m32 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & AVXOpMask; byte=0x67; KReg_reg ... & XmmReg2_m32
:VFPCLASSSS KReg_reg AVXOpMask, XmmReg2_m32, imm8 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & AVXOpMask; byte=0x67; KReg_reg ... & XmmReg2_m32; imm8
[ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S)
{
KReg_reg = vfpclassss_avx512dq( XmmReg2_m32, AVXOpMask );
KReg_reg = vfpclassss_avx512dq( XmmReg2_m32, AVXOpMask, imm8:1 );
}
# VGATHERDPS/VGATHERDPD 5-261 PAGE 2085 LINE 107357
@@ -12782,10 +12780,10 @@ define pcodeop vrangesd_avx512dq ;
# VRANGESS 5-482 PAGE 2306 LINE 118473
define pcodeop vrangess_avx512dq ;
:VRANGESS XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m32 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m32
:VRANGESS XmmReg1^XmmOpMask32, evexV5_XmmReg, XmmReg2_m32, imm8 is $(EVEX_NONE) & $(VEX_LIG) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W0) & evexV5_XmmReg; byte=0x51; (XmmReg1 & ZmmReg1 & XmmOpMask32) ... & XmmReg2_m32; imm8
[ evexD8Type = 1; evexTType = 3; ] # (TupleType T1S)
{
XmmResult = vrangess_avx512dq( evexV5_XmmReg, XmmReg2_m32 );
XmmResult = vrangess_avx512dq( evexV5_XmmReg, XmmReg2_m32, imm8:1 );
XmmMask = XmmReg1;
build XmmOpMask32;
ZmmReg1 = zext(XmmResult);
@@ -50,7 +50,7 @@ define pcodeop writeToUserShadowStack;
writeToShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
:WRSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(REX_W) & byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
writeToShadowStack(rm64, Reg64);
}
@endif
@@ -59,7 +59,7 @@ define pcodeop writeToUserShadowStack;
writeToUserShadowStack(rm32, Reg32);
}
@ifdef IA64
:WRUSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
:WRUSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
writeToUserShadowStack(rm64, Reg64);
}
@endif
@@ -87,7 +87,7 @@ define pcodeop vfmadd231ps_fma ;
# VFIXUPIMMSS 5-127 PAGE 1951 LINE 101587
# WARNING: did not recognize VEX field 0 for "VFMADD231PS ymm1, ymm2, ymm3/m256"
:VFMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xB8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
:VFMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xB8; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
{
local tmp:16 = vfmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
ZmmReg1 = zext(tmp);
@@ -406,7 +406,7 @@ define pcodeop vfmsub231ps_fma ;
# VFMSUB132PS/VFMSUB213PS/VFMSUB231PS 5-186 PAGE 2010 LINE 104394
# WARNING: did not recognize VEX field 0 for "VFMSUB231PS ymm1, ymm2, ymm3/m256"
:VFMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
:VFMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBA; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
{
local tmp:16 = vfmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
ZmmReg1 = zext(tmp);
@@ -545,7 +545,7 @@ define pcodeop vfnmadd231ps_fma ;
# VFNMADD132PS/VFNMADD213PS/VFNMADD231PS 5-206 PAGE 2030 LINE 105462
# WARNING: did not recognize VEX field 0 for "VFNMADD231PS ymm1, ymm2, ymm3/m256"
:VFNMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
:VFNMADD231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBC; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
{
local tmp:16 = vfnmadd231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
ZmmReg1 = zext(tmp);
@@ -684,7 +684,7 @@ define pcodeop vfnmsub231ps_fma ;
# VFNMSUB132PS/VFNMSUB213PS/VFNMSUB231PS 5-224 PAGE 2048 LINE 106502
# WARNING: did not recognize VEX field 0 for "VFNMSUB231PS ymm1, ymm2, ymm3/m256"
:VFNMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & vexVVVV_YmmReg; byte=0xBE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
:VFNMSUB231PS YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 is $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_YmmReg; byte=0xBE; (YmmReg1 & ZmmReg1) ... & YmmReg2_m256
{
local tmp:16 = vfnmsub231ps_fma( YmmReg1, vexVVVV_YmmReg, YmmReg2_m256 );
ZmmReg1 = zext(tmp);
+142 -95
View File
@@ -2623,7 +2623,7 @@ with : lockprefx=0 {
#ARPL is not encodable in 64-bit mode
:ARPL rm16,Reg16 is $(LONGMODE_OFF) & vexMode=0 & bit64=0 & byte=0x63; rm16 & Reg16 ... { local rpldest=rm16&3; local rplsrc=Reg16&3; local rpldiff=rplsrc-rpldest;
ZF = rpldiff s> 0; rm16 = rm16 + (zext(CF) * rpldiff); }
ZF = rpldiff s> 0; rm16 = rm16 + (zext(ZF) * rpldiff); }
:BOUND Reg16,m16 is $(LONGMODE_OFF) & vexMode=0 & bit64=0 & opsize=0 & byte=0x62; m16 & Reg16 ... { }
:BOUND Reg32,m32 is $(LONGMODE_OFF) & vexMode=0 & bit64=0 & opsize=1 & byte=0x62; m32 & Reg32 ... { }
@@ -3258,20 +3258,28 @@ define pcodeop cpuid_brand_part3_info;
}
:DAA is vexMode=0 & bit64=0 & byte=0x27 { local car = ((AL & 0xf) > 9) | AF;
:DAA is vexMode=0 & bit64=0 & byte=0x27 { local oldAL = AL;
local oldCF = CF;
CF = 0;
local car = ((AL & 0xf) > 9) | AF;
AL = AL + 6 * car;
CF = CF | car * carry(AL,6);
AF = car;
car = ((AL & 0xf0) > 0x90) | CF;
# CF set if car, but immediately overwritten by second if-else pair regardless
car = (oldAL > 0x99) | oldCF;
AL = AL + 0x60 * car;
CF = car; }
:DAS is vexMode=0 & bit64=0 & byte=0x2f { local car = ((AL & 0xf) > 9) | AF;
CF = car;
resultflags(AL); }
:DAS is vexMode=0 & bit64=0 & byte=0x2f { local oldAL = AL;
local oldCF = CF;
CF = 0;
local car = ((AL & 0xf) > 9) | AF;
CF = oldCF | (AL < 6); # borrow from AL - 6
AL = AL - 6 * car;
CF = CF | car * (AL < 6);
AF = car;
car = (AL > 0x9f) | CF;
car = (oldAL > 0x99) | oldCF;
AL = AL - 0x60 * car;
CF = car; }
CF = car;
resultflags(AL); }
# See 'lockable.sinc' for memory destination, lockable variants
:DEC Rmr8 is vexMode=0 & byte=0xfe; mod=3 & Rmr8 & reg_opcode=1 { OF = sborrow(Rmr8,1); Rmr8 = Rmr8 - 1; resultflags( Rmr8); }
@@ -4670,23 +4678,23 @@ define pcodeop smm_restore_state;
shrdflags(tmp,rm64,count); shiftresultflags(rm64,count); }
@endif
:SHR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=5 ... { CF = rm8 & 1; OF = 0; rm8 = rm8 >> 1; resultflags(rm8); }
:SHR rm8,n1 is vexMode=0 & byte=0xD0; rm8 & n1 & reg_opcode=5 ... { OF = (rm8 s< 0); CF = rm8 & 1; rm8 = rm8 >> 1; resultflags(rm8); }
:SHR rm8,CL is vexMode=0 & byte=0xD2; CL & rm8 & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm8; rm8 = rm8 >> count;
shrflags(tmp, rm8,count); shiftresultflags(rm8,count); }
:SHR rm8,imm8 is vexMode=0 & byte=0xC0; rm8 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm8; rm8 = rm8 >> count;
shrflags(tmp, rm8,count); shiftresultflags(rm8,count); }
:SHR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=5 ... { CF = (rm16 & 1) != 0; OF = 0; rm16 = rm16 >> 1; resultflags(rm16); }
:SHR rm16,n1 is vexMode=0 & opsize=0 & byte=0xD1; rm16 & n1 & reg_opcode=5 ... { OF = (rm16 s< 0); CF = (rm16 & 1) != 0; rm16 = rm16 >> 1; resultflags(rm16); }
:SHR rm16,CL is vexMode=0 & opsize=0 & byte=0xD3; CL & rm16 & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm16; rm16 = rm16 >> count;
shrflags(tmp, rm16,count); shiftresultflags(rm16,count); }
:SHR rm16,imm8 is vexMode=0 & opsize=0 & byte=0xC1; rm16 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm16; rm16 = rm16 >> count;
shrflags(tmp, rm16,count); shiftresultflags(rm16,count); }
:SHR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=5 ... { CF = (rm32 & 1) != 0; OF = 0; rm32 = rm32 >> 1; build check_rm32_dest; resultflags(rm32); }
:SHR rm32,n1 is vexMode=0 & opsize=1 & byte=0xD1; rm32 & n1 & check_rm32_dest ... & reg_opcode=5 ... { OF = (rm32 s< 0); CF = (rm32 & 1) != 0; rm32 = rm32 >> 1; build check_rm32_dest; resultflags(rm32); }
:SHR rm32,CL is vexMode=0 & opsize=1 & byte=0xD3; CL & rm32 & check_rm32_dest ... & reg_opcode=5 ... { local count = CL & 0x1f; local tmp = rm32; rm32 = rm32 >> count; build check_rm32_dest;
shrflags(tmp, rm32,count); shiftresultflags(rm32,count); }
:SHR rm32,imm8 is vexMode=0 & opsize=1 & byte=0xC1; rm32 & check_rm32_dest ... & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x1f; local tmp = rm32; rm32 = rm32 >> count; build check_rm32_dest;
shrflags(tmp, rm32,count); shiftresultflags(rm32,count); }
@ifdef IA64
:SHR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 &reg_opcode=5 ... { CF = (rm64 & 1) != 0; OF = 0; rm64 = rm64 >> 1; resultflags(rm64); }
:SHR rm64,n1 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD1; rm64 & n1 &reg_opcode=5 ... { OF = (rm64 s< 0); CF = (rm64 & 1) != 0; rm64 = rm64 >> 1; resultflags(rm64); }
:SHR rm64,CL is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xD3; CL & rm64 & reg_opcode=5 ... { local count = CL & 0x3f; local tmp = rm64; rm64 = rm64 >> count;
shrflags(tmp, rm64,count); shiftresultflags(rm64,count); }
:SHR rm64,imm8 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0xC1; rm64 & reg_opcode=5 ... ; imm8 { local count = imm8 & 0x3f; local tmp = rm64; rm64 = rm64 >> count;
@@ -4797,13 +4805,26 @@ define pcodeop skinit;
@endif
:SYSENTER is vexMode=0 & byte=0x0f; byte=0x34 { sysenter(); }
:SYSEXIT is vexMode=0 & byte=0x0f; byte=0x35 { sysexit();
:SYSEXIT is vexMode=0 & opsize=1 & byte=0x0f; byte=0x35 { sysexit();
@ifdef IA64
RIP=RCX; return [RIP];
RSP=zext(ECX); RIP=zext(EDX); return [RIP];
@else
ESP=ECX; EIP=EDX; return [EIP];
@endif
}
:SYSCALL is vexMode=0 & byte=0x0f; byte=0x05 { syscall(); }
@ifdef IA64
:SYSEXIT is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x35 { sysexit();
RSP=RCX; RIP=RDX; return [RIP];
}
@endif
@ifdef IA64
:SYSCALL is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0x05 {
RCX = inst_next; R11 = rflags;
syscall(); }
@endif
# returning to 32bit mode loads ECX
# returning to 64bit mode loads RCX
@@ -4815,7 +4836,7 @@ define pcodeop skinit;
:SWAPGS is vexMode=0 & bit64=1 & byte=0x0f; byte=0x01; byte=0xf8 { swapgs(); }
:RDTSCP is vexMode=0 & bit64=1 & byte=0x0f; byte=0x01; byte=0xf9 { rdtscp(); }
:RDTSCP is vexMode=0 & byte=0x0f; byte=0x01; byte=0xf9 { rdtscp(); }
:TEST AL,imm8 is vexMode=0 & byte=0xA8; AL & imm8 { logicalflags(); local tmp = AL & imm8; resultflags(tmp); }
:TEST AX,imm16 is vexMode=0 & opsize=0; byte=0xA9; AX & imm16 { logicalflags(); local tmp = AX & imm16; resultflags(tmp); }
@@ -4868,44 +4889,43 @@ define pcodeop verw;
#
# Intel hardware assisted virtualization opcodes
# All except VMCALL and VMFUNC generate invalid-opcode exceptions if executed in compatibility mode
@ifdef IA64
:INVEPT Reg64, m128 is $(LONGMODE_ON) & vexMode=0 & bit64=1 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x80; Reg64 ... & m128 { invept(Reg64, m128); }
@endif
:INVEPT Reg32, m128 is vexMode=0 & bit64=0 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x80; Reg32 ... & m128 { invept(Reg32, m128); }
@ifdef IA64
:INVVPID Reg64, m128 is $(LONGMODE_ON) & vexMode=0 & bit64=1 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x81; Reg64 ... & m128 { invvpid(Reg64, m128); }
@endif
:INVVPID Reg32, m128 is vexMode=0 & bit64=0 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x81; Reg32 ... & m128 { invvpid(Reg32, m128); }
:VMCALL is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc1 { vmcall(); }
@ifdef IA64
:VMCLEAR m64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmclear(m64); }
@endif
#TODO: invokes a VM function specified in EAX
:VMFUNC EAX is vexMode=0 & byte=0x0f; byte=0x01; byte=0xd4 & EAX { vmfunc(EAX); }
#TODO: this launches the VM managed by the current VMCS. How is the VMCS expressed for the emulator? For Ghidra analysis?
:VMLAUNCH is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc2 { vmlaunch(); }
:VMLAUNCH is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0x01; byte=0xc2 { vmlaunch(); }
#TODO: this resumes the VM managed by the current VMCS. How is the VMCS expressed for the emulator? For Ghidra analysis?
:VMRESUME is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc3 { vmresume(); }
:VMRESUME is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0x01; byte=0xc3 { vmresume(); }
#TODO: this loads the VMCS pointer from the m64 memory address and makes the VMCS pointer valid; how to express
# this for analysis and emulation?
:VMPTRLD m64 is vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmptrld(m64); }
:VMPTRLD m64 is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmptrld(m64); }
#TODO: stores the current VMCS pointer into the specified 64-bit memory address; how to express this for analysis and emulation?
#TODO: note that the Intel manual does not specify m64 (which it does for VMPTRLD, yet it does state that "the operand
# of this instruction is always 64-bits and is always in memory". Is it an error that the "Instruction" entry in the
# box giving the definition does not specify m64?
:VMPTRST m64 is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=7 ) ... & m64 { vmptrst(m64); }
:VMREAD rm64, Reg64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x78; rm64 & Reg64 ... { rm64 = vmread(Reg64); }
:VMWRITE Reg64, rm64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x79; rm64 & Reg64 ... { vmwrite(rm64,Reg64); }
:VMXOFF is $(LONGMODE_ON) & vexMode=0 & byte=0x0f; byte=0x01; byte=0xc4 { vmxoff(); }
:VMXON m64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmxon(m64); }
@else
:INVEPT Reg32, m128 is vexMode=0 & bit64=0 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x80; Reg32 ... & m128 { invept(Reg32, m128); }
:INVVPID Reg32, m128 is vexMode=0 & bit64=0 & $(PRE_66) & byte=0x0f; byte=0x38; byte=0x81; Reg32 ... & m128 { invvpid(Reg32, m128); }
:VMCLEAR m64 is vexMode=0 & $(PRE_66) & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmclear(m64); }
:VMLAUNCH is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc2 { vmlaunch(); }
:VMRESUME is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc3 { vmresume(); }
:VMPTRLD m64 is vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmptrld(m64); }
:VMPTRST m64 is vexMode=0 & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=7 ) ... & m64 { vmptrst(m64); }
:VMREAD rm32, Reg32 is $(PRE_NO) & vexMode=0 & opsize=1 & byte=0x0f; byte=0x78; rm32 & check_rm32_dest ... & Reg32 ... { rm32 = vmread(Reg32); build check_rm32_dest; }
@ifdef IA64
:VMREAD rm64, Reg64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x78; rm64 & Reg64 ... { rm64 = vmread(Reg64); }
@endif
:VMWRITE Reg32, rm32 is $(PRE_NO) & vexMode=0 & opsize=1 & byte=0x0f; byte=0x79; rm32 & Reg32 ... & check_Reg32_dest ... { vmwrite(rm32,Reg32); build check_Reg32_dest; }
@ifdef IA64
:VMWRITE Reg64, rm64 is $(LONGMODE_ON) & $(PRE_NO) & vexMode=0 & opsize=2 & byte=0x0f; byte=0x79; rm64 & Reg64 ... { vmwrite(rm64,Reg64); }
@endif
:VMXOFF is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc4 { vmxoff(); }
# NB: this opcode is incorrect in the 2005 edition of the Intel manual. Opcode below is taken from the 2008 version.
:VMXON m64 is vexMode=0 & $(PRE_F3) & byte=0x0f; byte=0xc7; ( mod != 0b11 & reg_opcode=6 ) ... & m64 { vmxon(m64); }
@endif
:VMCALL is vexMode=0 & byte=0x0f; byte=0x01; byte=0xc1 { vmcall(); }
#TODO: invokes a VM function specified in EAX
:VMFUNC EAX is vexMode=0 & byte=0x0f; byte=0x01; byte=0xd4 & EAX { vmfunc(EAX); }
#END of changes for VMX opcodes
:WAIT is vexMode=0 & byte=0x9b { }
@@ -4998,8 +5018,9 @@ define pcodeop xend;
:XOR Reg64,rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & byte=0x33; rm64 & Reg64 ... { logicalflags(); Reg64 = Reg64 ^ rm64; resultflags(Reg64); }
@endif
:XGETBV is vexMode=0 & byte=0x0F; byte=0x01; byte=0xD0 { local tmp = XCR0 >> 32; EDX = tmp:4; EAX = XCR0:4; }
:XSETBV is vexMode=0 & byte=0x0F; byte=0x01; byte=0xD1 { XCR0 = (zext(EDX) << 32) | zext(EAX); }
define pcodeop xinuse;
:XGETBV is vexMode=0 & byte=0x0F; byte=0x01; byte=0xD0 { local test = (ECX == 1); local xiu:8 = xinuse(test); local tXCR0 = (zext(test) * XCR0) + (zext(!test) * (XCR0 & xiu)); local tmp = tXCR0 >> 32; EDX = tmp:4; EAX = tXCR0:4; }
:XSETBV is vexMode=0 & byte=0x0F; byte=0x01; byte=0xD1 { local sel = ECX; XCR0 = (zext(EDX) << 32) | zext(EAX); }
define pcodeop xsave;
define pcodeop xsave64;
@@ -5193,11 +5214,11 @@ define pcodeop to_bcd;
ST0 = freg;
}
:FCMOVNBE ST0, freg is vexMode=0 & byte=0xDB; frow=13 & fpage=0 & freg & ST0
{
:FCMOVNBE ST0, freg is vexMode=0 & byte=0xDB; frow=13 & fpage=0 & freg & ST0
{
FPUInstructionPointer = inst_start;
if ( CF & ZF ) goto inst_next;
ST0 = freg;
if ( CF | ZF ) goto inst_next;
ST0 = freg;
}
:FCMOVNU ST0, freg is vexMode=0 & byte=0xDB; frow=13 & fpage=1 & freg & ST0
{
@@ -5303,12 +5324,12 @@ define pcodeop fcos;
ST0 = fcos(ST0);
}
:FDECSTP is vexMode=0 & byte=0xD9; byte=0xF6
{
:FDECSTP is vexMode=0 & byte=0xD9; byte=0xF6
{
FPUInstructionPointer = inst_start;
fdec();
FPUStatusWord = FPUStatusWord & 0xfeff;
C0 = 0; #Clear C0
fdec();
FPUStatusWord = FPUStatusWord & 0xfdff;
C1 = 0; #Clear C1
}
# Legacy 8087 instructions. Still valid but treated as NOP instructions.
@@ -5732,20 +5753,22 @@ define pcodeop fpatan;
fpop();
}
:FPREM is vexMode=0 & byte=0xD9; byte=0xF8
{
:FPREM is vexMode=0 & byte=0xD9; byte=0xF8
{
FPUInstructionPointer = inst_start;
local tmp = ST0 f/ ST1;
tmp = tmp f* ST1;
ST0 = ST0 f- tmp;
local tmp = ST0 f/ ST1;
tmp = trunc(tmp);
tmp = tmp f* ST1;
ST0 = ST0 f- tmp;
}
:FPREM1 is vexMode=0 & byte=0xD9; byte=0xF5
{
:FPREM1 is vexMode=0 & byte=0xD9; byte=0xF5
{
FPUInstructionPointer = inst_start;
local tmp = ST0 f/ ST1;
tmp = tmp f* ST1;
ST0 = ST0 f- tmp;
local tmp = ST0 f/ ST1;
tmp = round(tmp);
tmp = tmp f* ST1;
ST0 = ST0 f- tmp;
}
define pcodeop fptan;
@@ -6179,6 +6202,7 @@ define pcodeop _fxrstor64;
define pcodeop extract_significand;
define pcodeop extract_exponent;
define pcodeop log2;
:FXTRACT is vexMode=0 & byte=0xD9; byte=0xF4
{
FPUInstructionPointer = inst_start;
@@ -6188,20 +6212,20 @@ define pcodeop extract_exponent;
fpushv(significand);
}
:FYL2X is vexMode=0 & byte=0xD9; byte=0xF1
{
:FYL2X is vexMode=0 & byte=0xD9; byte=0xF1
{
FPUInstructionPointer = inst_start;
local log2st0 = ST0;
ST1 = ST1 f* log2st0;
local log2st0:10 = log2(ST0);
ST1 = ST1 f* log2st0;
fpop();
}
:FYL2XP1 is vexMode=0 & byte=0xD9; byte=0xF9
{
:FYL2XP1 is vexMode=0 & byte=0xD9; byte=0xF9
{
FPUInstructionPointer = inst_start;
one:4 = 1;
tmp:10 = int2float(one);
log2st0:10 = ST0 f+ tmp;
ST1 = ST1 f* log2st0;
log2st0:10 = log2(ST0 f+ tmp);
ST1 = ST1 f* log2st0;
fpop();
}
@@ -7145,8 +7169,15 @@ define pcodeop divps;
define pcodeop lddqu;
:LDDQU XmmReg, m128 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0xF0; XmmReg ... & m128 { XmmReg = lddqu(XmmReg, m128); }
maskMovDI: seg16^DI is addrsize=0 & seg16 & DI { tmp:$(SIZE) = segment(seg16,DI); export tmp; }
maskMovDI: segWide^EDI is addrsize=1 & segWide & EDI { tmp:$(SIZE) = zext(EDI); export tmp; }
maskMovDI: segWide^EDI is addrsize=1 & segWide & highseg=1 & EDI { tmp:$(SIZE) = segWide + zext(EDI); export tmp; }
@ifdef IA64
maskMovDI: segWide^RDI is $(LONGMODE_ON) & addrsize=2 & segWide & RDI { tmp:$(SIZE) = RDI; export tmp; }
maskMovDI: segWide^RDI is $(LONGMODE_ON) & addrsize=2 & segWide & highseg=1 & RDI { tmp:$(SIZE) = segWide + RDI; export tmp; }
@endif
define pcodeop maskmovdqu;
:MASKMOVDQU XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF7; XmmReg1 & XmmReg2 { XmmReg1 = maskmovdqu(XmmReg1, XmmReg2); }
:MASKMOVDQU XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF7 & maskMovDI; XmmReg1 & XmmReg2 { maskmovdqu(XmmReg1, XmmReg2, maskMovDI); }
define pcodeop maxpd;
:MAXPD XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x5F; XmmReg ... & m128 { XmmReg = maxpd(XmmReg, m128); }
@@ -8868,17 +8899,19 @@ define pcodeop psllw;
:PSLLD XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF2; XmmReg ... & m128 ... {
local m:16 = m128;
XmmReg[0,32] = XmmReg[0,32] << m[0,32];
XmmReg[32,32] = XmmReg[32,32] << m[32,32];
XmmReg[64,32] = XmmReg[64,32] << m[64,32];
XmmReg[96,32] = XmmReg[96,32] << m[96,32];
local count:4 = m[0,32];
XmmReg[0,32] = XmmReg[0,32] << count;
XmmReg[32,32] = XmmReg[32,32] << count;
XmmReg[64,32] = XmmReg[64,32] << count;
XmmReg[96,32] = XmmReg[96,32] << count;
}
:PSLLD XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF2; xmmmod = 3 & XmmReg1 & XmmReg2 {
XmmReg1[0,32] = XmmReg1[0,32] << XmmReg2[0,32];
XmmReg1[32,32] = XmmReg1[32,32] << XmmReg2[32,32];
XmmReg1[64,32] = XmmReg1[64,32] << XmmReg2[64,32];
XmmReg1[96,32] = XmmReg1[96,32] << XmmReg2[96,32];
local count:4 = XmmReg2[0,32];
XmmReg1[0,32] = XmmReg1[0,32] << count;
XmmReg1[32,32] = XmmReg1[32,32] << count;
XmmReg1[64,32] = XmmReg1[64,32] << count;
XmmReg1[96,32] = XmmReg1[96,32] << count;
}
:PSLLD XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x72; mod = 0b11 & reg_opcode=6 & XmmReg2; imm8 {
@@ -8890,13 +8923,15 @@ define pcodeop psllw;
:PSLLQ XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF3; XmmReg ... & m128 ... {
local m:16 = m128;
XmmReg[0,64] = XmmReg[0,64] << m[0,64];
XmmReg[64,64] = XmmReg[64,64] << m[64,64];
local count:8 = m[0,64];
XmmReg[0,64] = XmmReg[0,64] << count;
XmmReg[64,64] = XmmReg[64,64] << count;
}
:PSLLQ XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xF3; xmmmod = 3 & XmmReg1 & XmmReg2 {
XmmReg1[0,64] = XmmReg1[0,64] << XmmReg2[0,64];
XmmReg1[64,64] = XmmReg1[64,64] << XmmReg2[64,64];
local count:8 = XmmReg2[0,64];
XmmReg1[0,64] = XmmReg1[0,64] << count;
XmmReg1[64,64] = XmmReg1[64,64] << count;
}
:PSLLQ XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x73; mod = 0b11 & reg_opcode=6 & XmmReg2; imm8 {
@@ -8937,19 +8972,22 @@ define pcodeop psraw;
:PSRAD XmmReg, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xE2; m128 & XmmReg ...
{
# a count greater than 31 just clears all the bits
XmmReg[0,32] = XmmReg[0,32] s>> m128;
XmmReg[32,32] = XmmReg[32,32] s>> m128;
XmmReg[64,32] = XmmReg[64,32] s>> m128;
XmmReg[96,32] = XmmReg[96,32] s>> m128;
local m:16 = m128;
local count:4 = m[0,32];
XmmReg[0,32] = XmmReg[0,32] s>> count;
XmmReg[32,32] = XmmReg[32,32] s>> count;
XmmReg[64,32] = XmmReg[64,32] s>> count;
XmmReg[96,32] = XmmReg[96,32] s>> count;
}
:PSRAD XmmReg1, XmmReg2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xE2; xmmmod = 3 & XmmReg1 & XmmReg2
{
# a count greater than 31 just clears all the bits
XmmReg1[0,32] = XmmReg1[0,32] s>> XmmReg2;
XmmReg1[32,32] = XmmReg1[32,32] s>> XmmReg2;
XmmReg1[64,32] = XmmReg1[64,32] s>> XmmReg2;
XmmReg1[96,32] = XmmReg1[96,32] s>> XmmReg2;
local count:4 = XmmReg2[0,32];
XmmReg1[0,32] = XmmReg1[0,32] s>> count;
XmmReg1[32,32] = XmmReg1[32,32] s>> count;
XmmReg1[64,32] = XmmReg1[64,32] s>> count;
XmmReg1[96,32] = XmmReg1[96,32] s>> count;
}
:PSRAD XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x72; mod = 0b11 & reg_opcode=4 & XmmReg2; imm8
@@ -9127,6 +9165,7 @@ define pcodeop psraw;
:PSUBB mmxreg1, mmxreg2 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF8; mmxmod = 3 & mmxreg1 & mmxreg2
{
mmxreg1[0,8] = mmxreg1[0,8] - mmxreg2[0,8];
mmxreg1[8,8] = mmxreg1[8,8] - mmxreg2[8,8];
mmxreg1[16,8] = mmxreg1[16,8] - mmxreg2[16,8];
mmxreg1[24,8] = mmxreg1[24,8] - mmxreg2[24,8];
mmxreg1[32,8] = mmxreg1[32,8] - mmxreg2[32,8];
@@ -10248,12 +10287,20 @@ define pcodeop crc32;
@endif
define pcodeop pcmpestri;
:PCMPESTRI XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; XmmReg ... & m128; imm8 { ECX = pcmpestri(XmmReg, m128, imm8:8); }
:PCMPESTRI XmmReg1, XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { ECX = pcmpestri(XmmReg1, XmmReg2, imm8:8); }
:PCMPESTRI XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; XmmReg ... & m128; imm8 { ECX = pcmpestri(XmmReg, m128, imm8:8, EAX, EDX); }
:PCMPESTRI XmmReg1, XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { ECX = pcmpestri(XmmReg1, XmmReg2, imm8:8, EAX, EDX); }
@ifdef IA64
:PCMPESTRI XmmReg, m128, imm8 is vexMode=0 & $(REX_W) & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; XmmReg ... & m128; imm8 { ECX = pcmpestri(XmmReg, m128, imm8:8, RAX, RDX); }
:PCMPESTRI XmmReg1, XmmReg2, imm8 is vexMode=0 & $(REX_W) & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x61; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { ECX = pcmpestri(XmmReg1, XmmReg2, imm8:8, RAX, RDX); }
@endif
define pcodeop pcmpestrm;
:PCMPESTRM XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; XmmReg ... & m128; imm8 { XMM0 = pcmpestrm(XmmReg, m128, imm8:8); }
:PCMPESTRM XmmReg1, XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { XMM0 = pcmpestrm(XmmReg1, XmmReg2, imm8:8); }
:PCMPESTRM XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; XmmReg ... & m128; imm8 { XMM0 = pcmpestrm(XmmReg, m128, imm8:8, EAX, EDX); }
:PCMPESTRM XmmReg1, XmmReg2, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { XMM0 = pcmpestrm(XmmReg1, XmmReg2, imm8:8, EAX, EDX); }
@ifdef IA64
:PCMPESTRM XmmReg, m128, imm8 is vexMode=0 & $(REX_W) & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; XmmReg ... & m128; imm8 { XMM0 = pcmpestrm(XmmReg, m128, imm8:8, RAX, RDX); }
:PCMPESTRM XmmReg1, XmmReg2, imm8 is vexMode=0 & $(REX_W) & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x60; xmmmod=3 & XmmReg1 & XmmReg2; imm8 { XMM0 = pcmpestrm(XmmReg1, XmmReg2, imm8:8, RAX, RDX); }
@endif
define pcodeop pcmpistri;
:PCMPISTRI XmmReg, m128, imm8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x3A; byte=0x63; XmmReg ... & m128; imm8 { ECX = pcmpistri(XmmReg, m128, imm8:8); }
@@ -10455,7 +10502,7 @@ define pcodeop PackedSwapDWords;
:PSWAPD mmxreg1, mmxreg2 is vexMode=0 & suffix3D=0xBB & mandover=0 & byte=0x0F; byte=0x0F; mmxmod = 3 & mmxreg1 & mmxreg2 { mmxreg1 = PackedSwapDWords(mmxreg1, mmxreg2); }
define pcodeop MaskedMoveQWord;
:MASKMOVQ mmxreg1, mmxreg2 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF7; mmxmod = 3 & mmxreg1 & mmxreg2 { mmxreg1 = MaskedMoveQWord(mmxreg1, mmxreg2); }
:MASKMOVQ mmxreg1, mmxreg2 is vexMode=0 & mandover=0 & byte=0x0F; byte=0xF7 & maskMovDI; mmxmod = 3 & mmxreg1 & mmxreg2 { MaskedMoveQWord(mmxreg1, mmxreg2, maskMovDI); }
####
@@ -5,7 +5,7 @@
endian="little"
size="32"
variant="default"
version="4.6"
version="4.7"
slafile="x86.sla"
processorspec="x86.pspec"
manualindexfile="../manuals/x86.idx"
@@ -37,7 +37,7 @@
endian="little"
size="32"
variant="System Management Mode"
version="4.6"
version="4.7"
slafile="x86.sla"
processorspec="x86-16.pspec"
manualindexfile="../manuals/x86.idx"
@@ -50,7 +50,7 @@
endian="little"
size="16"
variant="Real Mode"
version="4.6"
version="4.7"
slafile="x86.sla"
processorspec="x86-16-real.pspec"
manualindexfile="../manuals/x86.idx"
@@ -70,7 +70,7 @@
endian="little"
size="16"
variant="Protected Mode"
version="4.6"
version="4.7"
slafile="x86.sla"
processorspec="x86-16.pspec"
manualindexfile="../manuals/x86.idx"
@@ -85,7 +85,7 @@
endian="little"
size="64"
variant="default"
version="4.6"
version="4.7"
slafile="x86-64.sla"
processorspec="x86-64.pspec"
manualindexfile="../manuals/x86.idx"
@@ -108,7 +108,7 @@
endian="little"
size="64"
variant="compat32"
version="4.6"
version="4.7"
slafile="x86-64.sla"
processorspec="x86-64-compat32.pspec"
manualindexfile="../manuals/x86.idx"