Skip to content

Commit fa2736f

Browse files
committed
fix decoding instructions with W1
1 parent 3af7f54 commit fa2736f

File tree

4 files changed

+12851
-15177
lines changed

4 files changed

+12851
-15177
lines changed

x86/x86asm/decode.go

Lines changed: 60 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -418,25 +418,21 @@ ReadPrefixes:
418418
vexIndex = pos
419419
inst.Prefix[pos] = p
420420
inst.Prefix[pos+1] = Prefix(src[pos+1])
421-
pos += 1
422-
continue
423-
} else {
424-
nprefix = pos
425-
break ReadPrefixes
421+
pos += 2
426422
}
423+
nprefix = pos
424+
break ReadPrefixes
427425
case 0xC4:
428426
if pos == 0 && pos+2 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {
429427
vex = p
430428
vexIndex = pos
431429
inst.Prefix[pos] = p
432430
inst.Prefix[pos+1] = Prefix(src[pos+1])
433431
inst.Prefix[pos+2] = Prefix(src[pos+2])
434-
pos += 2
435-
continue
436-
} else {
437-
nprefix = pos
438-
break ReadPrefixes
432+
pos += 3
439433
}
434+
nprefix = pos
435+
break ReadPrefixes
440436
}
441437

442438
if pos >= len(inst.Prefix) {
@@ -855,48 +851,71 @@ Decode:
855851
}
856852
continue
857853
}
854+
855+
vexFlag := (prefix & 0xf00) >> 8
858856
ok := false
859-
if prefix == 0 {
860-
ok = true
861-
} else if prefix.IsREX() {
862-
rexUsed |= prefix
863-
if rex&prefix == prefix {
864-
ok = true
857+
858+
if vexFlag != 0 {
859+
if vex == 0 {
860+
continue
865861
}
866-
} else if prefix.IsVEX() {
867-
if vex == prefix {
868-
var vexL Prefix
869-
if vex == 0xC5 {
870-
vexL = inst.Prefix[vexIndex+1]
871-
} else {
872-
vexL = inst.Prefix[vexIndex+2]
862+
863+
var vexW, vexL, vexP Prefix
864+
if vex == 0xC4 {
865+
vexW = inst.Prefix[vexIndex+2] & 0x80
866+
vexL = inst.Prefix[vexIndex+2] & 0x04
867+
vexP = inst.Prefix[vexIndex+2] & 0x03
868+
} else {
869+
vexL = inst.Prefix[vexIndex+1] & 0x04
870+
vexP = inst.Prefix[vexIndex+1] & 0x03
871+
}
872+
873+
switch vexFlag {
874+
case 1:
875+
// all good (any vex prefix, any W)
876+
case 2:
877+
// check for W0
878+
if vexW != 0 {
879+
continue
880+
}
881+
case 3:
882+
// check for W1 (only valid with 0xC4)
883+
if vexW == 0 {
884+
continue
873885
}
886+
default:
887+
println("unknown vex prefix flag", vexFlag)
888+
return Inst{Len: pos}, errInternal
889+
}
874890

891+
// this is looking good, check the prefix
892+
switch prefix & 0xFF {
893+
case 0:
894+
ok = true
895+
case 0x66:
896+
ok = vexP == 1
897+
case 0xF3:
898+
ok = vexP == 2
899+
case 0xF2:
900+
ok = vexP == 3
901+
}
902+
903+
if ok {
904+
// TODO: bit of a hack, some instructions ignore the L bit
875905
if vexL&4 == 0 {
876906
dataMode = 128
877907
} else {
878908
dataMode = 256
879909
}
880-
ok = true
881910
}
882-
} else if dataMode >= 128 && (prefix == 0x66 || prefix == 0xF2 || prefix == 0xF3) {
883-
var vexM, vexP Prefix
884-
if vex == 0xC5 {
885-
vexM = 1 // 2 byte vex always implies 0F
886-
vexP = inst.Prefix[vexIndex+1]
887-
} else {
888-
vexM = inst.Prefix[vexIndex+1]
889-
vexP = inst.Prefix[vexIndex+2]
890-
}
891-
_ = vexM
911+
}
892912

893-
switch prefix {
894-
case 0x66:
895-
ok = vexP&3 == 1
896-
case 0xF3:
897-
ok = vexP&3 == 2
898-
case 0xF2:
899-
ok = vexP&3 == 3
913+
if prefix == 0 {
914+
ok = true
915+
} else if prefix.IsREX() {
916+
rexUsed |= prefix
917+
if rex&prefix == prefix {
918+
ok = true
900919
}
901920
} else {
902921
if prefix == 0xF3 {

0 commit comments

Comments
 (0)