|
|
|
@@ -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 ®_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 ®_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); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
####
|
|
|
|
|