diff options
-rw-r--r-- | src/jit/dis_x86.lua | 225 |
1 files changed, 155 insertions, 70 deletions
diff --git a/src/jit/dis_x86.lua b/src/jit/dis_x86.lua index 6bc38066..49bbcad0 100644 --- a/src/jit/dis_x86.lua +++ b/src/jit/dis_x86.lua | |||
@@ -15,13 +15,12 @@ | |||
15 | -- Intel and AMD manuals. The supported instruction set is quite extensive | 15 | -- Intel and AMD manuals. The supported instruction set is quite extensive |
16 | -- and reflects what a current generation Intel or AMD CPU implements in | 16 | -- and reflects what a current generation Intel or AMD CPU implements in |
17 | -- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, | 17 | -- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, |
18 | -- SSE4.1, SSE4.2, SSE4a and even privileged and hypervisor (VMX/SVM) | 18 | -- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor |
19 | -- instructions. | 19 | -- (VMX/SVM) instructions. |
20 | -- | 20 | -- |
21 | -- Notes: | 21 | -- Notes: |
22 | -- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. | 22 | -- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. |
23 | -- * No attempt at optimization has been made -- it's fast enough for my needs. | 23 | -- * No attempt at optimization has been made -- it's fast enough for my needs. |
24 | -- * The public API may change when more architectures are added. | ||
25 | ------------------------------------------------------------------------------ | 24 | ------------------------------------------------------------------------------ |
26 | 25 | ||
27 | local type = type | 26 | local type = type |
@@ -78,7 +77,7 @@ local map_opc1_32 = { | |||
78 | "movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", | 77 | "movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", |
79 | "movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", | 78 | "movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", |
80 | --Cx | 79 | --Cx |
81 | "shift!Bmu","shift!Vmu","retBw","ret","$lesVrm","$ldsVrm","movBmi","movVmi", | 80 | "shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi", |
82 | "enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", | 81 | "enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", |
83 | --Dx | 82 | --Dx |
84 | "shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", | 83 | "shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", |
@@ -103,7 +102,7 @@ local map_opc1_64 = setmetatable({ | |||
103 | [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", | 102 | [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", |
104 | [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", | 103 | [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", |
105 | [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", | 104 | [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", |
106 | [0x82]=false, [0x9a]=false, [0xc4]=false, [0xc5]=false, [0xce]=false, | 105 | [0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false, |
107 | [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, | 106 | [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, |
108 | }, { __index = map_opc1_32 }) | 107 | }, { __index = map_opc1_32 }) |
109 | 108 | ||
@@ -114,12 +113,12 @@ local map_opc2 = { | |||
114 | [0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", | 113 | [0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", |
115 | "invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", | 114 | "invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", |
116 | --1x | 115 | --1x |
117 | "movupsXrm|movssXrm|movupdXrm|movsdXrm", | 116 | "movupsXrm|movssXrvm|movupdXrm|movsdXrvm", |
118 | "movupsXmr|movssXmr|movupdXmr|movsdXmr", | 117 | "movupsXmr|movssXmvr|movupdXmr|movsdXmvr", |
119 | "movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", | 118 | "movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", |
120 | "movlpsXmr||movlpdXmr", | 119 | "movlpsXmr||movlpdXmr", |
121 | "unpcklpsXrm||unpcklpdXrm", | 120 | "unpcklpsXrvm||unpcklpdXrvm", |
122 | "unpckhpsXrm||unpckhpdXrm", | 121 | "unpckhpsXrvm||unpckhpdXrvm", |
123 | "movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", | 122 | "movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", |
124 | "movhpsXmr||movhpdXmr", | 123 | "movhpsXmr||movhpdXmr", |
125 | "$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", | 124 | "$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", |
@@ -128,7 +127,7 @@ local map_opc2 = { | |||
128 | "movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, | 127 | "movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, |
129 | "movapsXrm||movapdXrm", | 128 | "movapsXrm||movapdXrm", |
130 | "movapsXmr||movapdXmr", | 129 | "movapsXmr||movapdXmr", |
131 | "cvtpi2psXrMm|cvtsi2ssXrVmt|cvtpi2pdXrMm|cvtsi2sdXrVmt", | 130 | "cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt", |
132 | "movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", | 131 | "movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", |
133 | "cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", | 132 | "cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", |
134 | "cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", | 133 | "cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", |
@@ -144,27 +143,27 @@ local map_opc2 = { | |||
144 | "cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", | 143 | "cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", |
145 | --5x | 144 | --5x |
146 | "movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", | 145 | "movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", |
147 | "rsqrtpsXrm|rsqrtssXrm","rcppsXrm|rcpssXrm", | 146 | "rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm", |
148 | "andpsXrm||andpdXrm","andnpsXrm||andnpdXrm", | 147 | "andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm", |
149 | "orpsXrm||orpdXrm","xorpsXrm||xorpdXrm", | 148 | "orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm", |
150 | "addpsXrm|addssXrm|addpdXrm|addsdXrm","mulpsXrm|mulssXrm|mulpdXrm|mulsdXrm", | 149 | "addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm", |
151 | "cvtps2pdXrm|cvtss2sdXrm|cvtpd2psXrm|cvtsd2ssXrm", | 150 | "cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm", |
152 | "cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", | 151 | "cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", |
153 | "subpsXrm|subssXrm|subpdXrm|subsdXrm","minpsXrm|minssXrm|minpdXrm|minsdXrm", | 152 | "subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm", |
154 | "divpsXrm|divssXrm|divpdXrm|divsdXrm","maxpsXrm|maxssXrm|maxpdXrm|maxsdXrm", | 153 | "divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm", |
155 | --6x | 154 | --6x |
156 | "punpcklbwPrm","punpcklwdPrm","punpckldqPrm","packsswbPrm", | 155 | "punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm", |
157 | "pcmpgtbPrm","pcmpgtwPrm","pcmpgtdPrm","packuswbPrm", | 156 | "pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm", |
158 | "punpckhbwPrm","punpckhwdPrm","punpckhdqPrm","packssdwPrm", | 157 | "punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm", |
159 | "||punpcklqdqXrm","||punpckhqdqXrm", | 158 | "||punpcklqdqXrvm","||punpckhqdqXrvm", |
160 | "movPrVSm","movqMrm|movdquXrm|movdqaXrm", | 159 | "movPrVSm","movqMrm|movdquXrm|movdqaXrm", |
161 | --7x | 160 | --7x |
162 | "pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu", | 161 | "pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu", |
163 | "pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu", | 162 | "pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu", |
164 | "pcmpeqbPrm","pcmpeqwPrm","pcmpeqdPrm","emms|", | 163 | "pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|", |
165 | "vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", | 164 | "vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", |
166 | nil,nil, | 165 | nil,nil, |
167 | "||haddpdXrm|haddpsXrm","||hsubpdXrm|hsubpsXrm", | 166 | "||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm", |
168 | "movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", | 167 | "movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", |
169 | --8x | 168 | --8x |
170 | "joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", | 169 | "joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", |
@@ -182,27 +181,27 @@ nil,nil, | |||
182 | "bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", | 181 | "bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", |
183 | --Cx | 182 | --Cx |
184 | "xaddBmr","xaddVmr", | 183 | "xaddBmr","xaddVmr", |
185 | "cmppsXrmu|cmpssXrmu|cmppdXrmu|cmpsdXrmu","$movntiVmr|", | 184 | "cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|", |
186 | "pinsrwPrWmu","pextrwDrPmu", | 185 | "pinsrwPrvWmu","pextrwDrPmu", |
187 | "shufpsXrmu||shufpdXrmu","$cmpxchg!Qmp", | 186 | "shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp", |
188 | "bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", | 187 | "bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", |
189 | --Dx | 188 | --Dx |
190 | "||addsubpdXrm|addsubpsXrm","psrlwPrm","psrldPrm","psrlqPrm", | 189 | "||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm", |
191 | "paddqPrm","pmullwPrm", | 190 | "paddqPrvm","pmullwPrvm", |
192 | "|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", | 191 | "|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", |
193 | "psubusbPrm","psubuswPrm","pminubPrm","pandPrm", | 192 | "psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm", |
194 | "paddusbPrm","padduswPrm","pmaxubPrm","pandnPrm", | 193 | "paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm", |
195 | --Ex | 194 | --Ex |
196 | "pavgbPrm","psrawPrm","psradPrm","pavgwPrm", | 195 | "pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm", |
197 | "pmulhuwPrm","pmulhwPrm", | 196 | "pmulhuwPrvm","pmulhwPrvm", |
198 | "|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", | 197 | "|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", |
199 | "psubsbPrm","psubswPrm","pminswPrm","porPrm", | 198 | "psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm", |
200 | "paddsbPrm","paddswPrm","pmaxswPrm","pxorPrm", | 199 | "paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm", |
201 | --Fx | 200 | --Fx |
202 | "|||lddquXrm","psllwPrm","pslldPrm","psllqPrm", | 201 | "|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm", |
203 | "pmuludqPrm","pmaddwdPrm","psadbwPrm","maskmovqMrm||maskmovdquXrm$", | 202 | "pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$", |
204 | "psubbPrm","psubwPrm","psubdPrm","psubqPrm", | 203 | "psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm", |
205 | "paddbPrm","paddwPrm","padddPrm","ud", | 204 | "paddbPrvm","paddwPrvm","padddPrvm","ud", |
206 | } | 205 | } |
207 | assert(map_opc2[255] == "ud") | 206 | assert(map_opc2[255] == "ud") |
208 | 207 | ||
@@ -210,46 +209,62 @@ assert(map_opc2[255] == "ud") | |||
210 | local map_opc3 = { | 209 | local map_opc3 = { |
211 | ["38"] = { -- [66] 0f 38 xx | 210 | ["38"] = { -- [66] 0f 38 xx |
212 | --0x | 211 | --0x |
213 | [0]="pshufbPrm","phaddwPrm","phadddPrm","phaddswPrm", | 212 | [0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm", |
214 | "pmaddubswPrm","phsubwPrm","phsubdPrm","phsubswPrm", | 213 | "pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm", |
215 | "psignbPrm","psignwPrm","psigndPrm","pmulhrswPrm", | 214 | "psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm", |
216 | nil,nil,nil,nil, | 215 | "||permilpsXrvm","||permilpdXrvm",nil,nil, |
217 | --1x | 216 | --1x |
218 | "||pblendvbXrma",nil,nil,nil, | 217 | "||pblendvbXrma",nil,nil,nil, |
219 | "||blendvpsXrma","||blendvpdXrma",nil,"||ptestXrm", | 218 | "||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm", |
220 | nil,nil,nil,nil, | 219 | "||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil, |
221 | "pabsbPrm","pabswPrm","pabsdPrm",nil, | 220 | "pabsbPrm","pabswPrm","pabsdPrm",nil, |
222 | --2x | 221 | --2x |
223 | "||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", | 222 | "||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", |
224 | "||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, | 223 | "||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, |
225 | "||pmuldqXrm","||pcmpeqqXrm","||$movntdqaXrm","||packusdwXrm", | 224 | "||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm", |
226 | nil,nil,nil,nil, | 225 | "||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr", |
227 | --3x | 226 | --3x |
228 | "||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", | 227 | "||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", |
229 | "||pmovzxwqXrm","||pmovzxdqXrm",nil,"||pcmpgtqXrm", | 228 | "||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm", |
230 | "||pminsbXrm","||pminsdXrm","||pminuwXrm","||pminudXrm", | 229 | "||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm", |
231 | "||pmaxsbXrm","||pmaxsdXrm","||pmaxuwXrm","||pmaxudXrm", | 230 | "||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm", |
232 | --4x | 231 | --4x |
233 | "||pmulddXrm","||phminposuwXrm", | 232 | "||pmulddXrvm","||phminposuwXrm",nil,nil, |
233 | nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm", | ||
234 | --5x | ||
235 | [0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm", | ||
236 | [0x5a] = "||broadcasti128XrlXm", | ||
237 | --7x | ||
238 | [0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm", | ||
239 | --8x | ||
240 | [0x8c] = "||pmaskmovXrvVSm", | ||
241 | [0x8e] = "||pmaskmovVSmXvr", | ||
234 | --Fx | 242 | --Fx |
235 | [0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", | 243 | [0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", |
236 | }, | 244 | }, |
237 | 245 | ||
238 | ["3a"] = { -- [66] 0f 3a xx | 246 | ["3a"] = { -- [66] 0f 3a xx |
239 | --0x | 247 | --0x |
240 | [0x00]=nil,nil,nil,nil,nil,nil,nil,nil, | 248 | [0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil, |
241 | "||roundpsXrmu","||roundpdXrmu","||roundssXrmu","||roundsdXrmu", | 249 | "||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil, |
242 | "||blendpsXrmu","||blendpdXrmu","||pblendwXrmu","palignrPrmu", | 250 | "||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu", |
251 | "||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu", | ||
243 | --1x | 252 | --1x |
244 | nil,nil,nil,nil, | 253 | nil,nil,nil,nil, |
245 | "||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", | 254 | "||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", |
246 | nil,nil,nil,nil,nil,nil,nil,nil, | 255 | "||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil, |
256 | nil,nil,nil,nil, | ||
247 | --2x | 257 | --2x |
248 | "||pinsrbXrVmu","||insertpsXrmu","||pinsrXrVmuS",nil, | 258 | "||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil, |
259 | --3x | ||
260 | [0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru", | ||
249 | --4x | 261 | --4x |
250 | [0x40] = "||dppsXrmu", | 262 | [0x40] = "||dppsXrvmu", |
251 | [0x41] = "||dppdXrmu", | 263 | [0x41] = "||dppdXrvmu", |
252 | [0x42] = "||mpsadbwXrmu", | 264 | [0x42] = "||mpsadbwXrvmu", |
265 | [0x46] = "||perm2i128Xrvmu", | ||
266 | [0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb", | ||
267 | [0x4c] = "||pblendvbXrvmb", | ||
253 | --6x | 268 | --6x |
254 | [0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", | 269 | [0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", |
255 | [0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", | 270 | [0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", |
@@ -356,17 +371,19 @@ local map_regs = { | |||
356 | "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! | 371 | "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! |
357 | X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", | 372 | X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", |
358 | "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, | 373 | "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, |
374 | Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", | ||
375 | "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" }, | ||
359 | } | 376 | } |
360 | local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } | 377 | local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } |
361 | 378 | ||
362 | -- Maps for size names. | 379 | -- Maps for size names. |
363 | local map_sz2n = { | 380 | local map_sz2n = { |
364 | B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, | 381 | B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32, |
365 | } | 382 | } |
366 | local map_sz2prefix = { | 383 | local map_sz2prefix = { |
367 | B = "byte", W = "word", D = "dword", | 384 | B = "byte", W = "word", D = "dword", |
368 | Q = "qword", | 385 | Q = "qword", |
369 | M = "qword", X = "xword", | 386 | M = "qword", X = "xword", Y = "yword", |
370 | F = "dword", G = "qword", -- No need for sizes/register names for these two. | 387 | F = "dword", G = "qword", -- No need for sizes/register names for these two. |
371 | } | 388 | } |
372 | 389 | ||
@@ -389,10 +406,13 @@ local function putop(ctx, text, operands) | |||
389 | if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end | 406 | if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end |
390 | if ctx.rex then | 407 | if ctx.rex then |
391 | local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. | 408 | local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. |
392 | (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "") | 409 | (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "").. |
393 | if t ~= "" then text = "rex."..t.." "..text end | 410 | (ctx.vexl and "l" or "") |
411 | if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end | ||
412 | if t ~= "" then text = ctx.rex.."."..t.." "..text | ||
413 | elseif ctx.rex == "vex" then text = "v"..text end | ||
394 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false | 414 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false |
395 | ctx.rex = false | 415 | ctx.rex = false; ctx.vexl = false; ctx.vexv = false |
396 | end | 416 | end |
397 | if ctx.seg then | 417 | if ctx.seg then |
398 | local text2, n = gsub(text, "%[", "["..ctx.seg..":") | 418 | local text2, n = gsub(text, "%[", "["..ctx.seg..":") |
@@ -407,6 +427,7 @@ local function putop(ctx, text, operands) | |||
407 | end | 427 | end |
408 | ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) | 428 | ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) |
409 | ctx.mrm = false | 429 | ctx.mrm = false |
430 | ctx.vexv = false | ||
410 | ctx.start = pos | 431 | ctx.start = pos |
411 | ctx.imm = nil | 432 | ctx.imm = nil |
412 | end | 433 | end |
@@ -415,7 +436,7 @@ end | |||
415 | local function clearprefixes(ctx) | 436 | local function clearprefixes(ctx) |
416 | ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false | 437 | ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false |
417 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false | 438 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false |
418 | ctx.rex = false; ctx.a32 = false | 439 | ctx.rex = false; ctx.a32 = false; ctx.vexl = false |
419 | end | 440 | end |
420 | 441 | ||
421 | -- Fallback for incomplete opcodes at the end. | 442 | -- Fallback for incomplete opcodes at the end. |
@@ -452,9 +473,9 @@ end | |||
452 | -- Process pattern string and generate the operands. | 473 | -- Process pattern string and generate the operands. |
453 | local function putpat(ctx, name, pat) | 474 | local function putpat(ctx, name, pat) |
454 | local operands, regs, sz, mode, sp, rm, sc, rx, sdisp | 475 | local operands, regs, sz, mode, sp, rm, sc, rx, sdisp |
455 | local code, pos, stop = ctx.code, ctx.pos, ctx.stop | 476 | local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl |
456 | 477 | ||
457 | -- Chars used: 1DFGIMPQRSTUVWXacdfgijmoprstuwxyz | 478 | -- Chars used: 1DFGIMPQRSTUVWXYabcdfgijlmoprstuvwxyz |
458 | for p in gmatch(pat, ".") do | 479 | for p in gmatch(pat, ".") do |
459 | local x = nil | 480 | local x = nil |
460 | if p == "V" or p == "U" then | 481 | if p == "V" or p == "U" then |
@@ -469,11 +490,13 @@ local function putpat(ctx, name, pat) | |||
469 | elseif p == "B" then | 490 | elseif p == "B" then |
470 | sz = "B" | 491 | sz = "B" |
471 | regs = ctx.rex and map_regs.B64 or map_regs.B | 492 | regs = ctx.rex and map_regs.B64 or map_regs.B |
472 | elseif match(p, "[WDQMXFG]") then | 493 | elseif match(p, "[WDQMXYFG]") then |
473 | sz = p | 494 | sz = p |
495 | if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end | ||
474 | regs = map_regs[sz] | 496 | regs = map_regs[sz] |
475 | elseif p == "P" then | 497 | elseif p == "P" then |
476 | sz = ctx.o16 and "X" or "M"; ctx.o16 = false | 498 | sz = ctx.o16 and "X" or "M"; ctx.o16 = false |
499 | if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end | ||
477 | regs = map_regs[sz] | 500 | regs = map_regs[sz] |
478 | elseif p == "S" then | 501 | elseif p == "S" then |
479 | name = name..lower(sz) | 502 | name = name..lower(sz) |
@@ -486,6 +509,10 @@ local function putpat(ctx, name, pat) | |||
486 | local imm = getimm(ctx, pos, 1); if not imm then return end | 509 | local imm = getimm(ctx, pos, 1); if not imm then return end |
487 | x = format("0x%02x", imm) | 510 | x = format("0x%02x", imm) |
488 | pos = pos+1 | 511 | pos = pos+1 |
512 | elseif p == "b" then | ||
513 | local imm = getimm(ctx, pos, 1); if not imm then return end | ||
514 | x = regs[imm/16+1] | ||
515 | pos = pos+1 | ||
489 | elseif p == "w" then | 516 | elseif p == "w" then |
490 | local imm = getimm(ctx, pos, 2); if not imm then return end | 517 | local imm = getimm(ctx, pos, 2); if not imm then return end |
491 | x = format("0x%x", imm) | 518 | x = format("0x%x", imm) |
@@ -618,8 +645,13 @@ local function putpat(ctx, name, pat) | |||
618 | else | 645 | else |
619 | x = "CR"..sp | 646 | x = "CR"..sp |
620 | end | 647 | end |
648 | elseif p == "v" then | ||
649 | if ctx.vexv then | ||
650 | x = regs[ctx.vexv+1]; ctx.vexv = false | ||
651 | end | ||
621 | elseif p == "y" then x = "DR"..sp | 652 | elseif p == "y" then x = "DR"..sp |
622 | elseif p == "z" then x = "TR"..sp | 653 | elseif p == "z" then x = "TR"..sp |
654 | elseif p == "l" then vexl = false | ||
623 | elseif p == "t" then | 655 | elseif p == "t" then |
624 | else | 656 | else |
625 | error("bad pattern `"..pat.."'") | 657 | error("bad pattern `"..pat.."'") |
@@ -694,7 +726,7 @@ map_act = { | |||
694 | B = putpat, W = putpat, D = putpat, Q = putpat, | 726 | B = putpat, W = putpat, D = putpat, Q = putpat, |
695 | V = putpat, U = putpat, T = putpat, | 727 | V = putpat, U = putpat, T = putpat, |
696 | M = putpat, X = putpat, P = putpat, | 728 | M = putpat, X = putpat, P = putpat, |
697 | F = putpat, G = putpat, | 729 | F = putpat, G = putpat, Y = putpat, |
698 | 730 | ||
699 | -- Collect prefixes. | 731 | -- Collect prefixes. |
700 | [":"] = function(ctx, name, pat) | 732 | [":"] = function(ctx, name, pat) |
@@ -755,15 +787,68 @@ map_act = { | |||
755 | 787 | ||
756 | -- REX prefix. | 788 | -- REX prefix. |
757 | rex = function(ctx, name, pat) | 789 | rex = function(ctx, name, pat) |
758 | if ctx.rex then return unknown(ctx) end -- Only 1 REX prefix allowed. | 790 | if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. |
759 | for p in gmatch(pat, ".") do ctx["rex"..p] = true end | 791 | for p in gmatch(pat, ".") do ctx["rex"..p] = true end |
760 | ctx.rex = true | 792 | ctx.rex = "rex" |
793 | end, | ||
794 | |||
795 | -- VEX prefix. | ||
796 | vex = function(ctx, name, pat) | ||
797 | if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed. | ||
798 | ctx.rex = "vex" | ||
799 | local pos = ctx.pos | ||
800 | if ctx.mrm then | ||
801 | ctx.mrm = nil | ||
802 | pos = pos-1 | ||
803 | end | ||
804 | local b = byte(ctx.code, pos, pos) | ||
805 | if not b then return incomplete(ctx) end | ||
806 | pos = pos+1 | ||
807 | if b < 128 then ctx.rexr = true end | ||
808 | local m = 1 | ||
809 | if pat == "3" then | ||
810 | m = b%32; b = (b-m)/32 | ||
811 | local nb = b%2; b = (b-nb)/2 | ||
812 | if nb == 0 then ctx.rexb = true end | ||
813 | local nx = b%2; b = (b-nx)/2 | ||
814 | if nx == 0 then ctx.rexx = true end | ||
815 | b = byte(ctx.code, pos, pos) | ||
816 | if not b then return incomplete(ctx) end | ||
817 | pos = pos+1 | ||
818 | if b >= 128 then ctx.rexw = true end | ||
819 | end | ||
820 | ctx.pos = pos | ||
821 | local map | ||
822 | if m == 1 then map = map_opc2 | ||
823 | elseif m == 2 then map = map_opc3["38"] | ||
824 | elseif m == 3 then map = map_opc3["3a"] | ||
825 | else return unknown(ctx) end | ||
826 | local p = b%4; b = (b-p)/4 | ||
827 | if p == 1 then ctx.o16 = "o16" | ||
828 | elseif p == 2 then ctx.rep = "rep" | ||
829 | elseif p == 3 then ctx.rep = "repne" end | ||
830 | local l = b%2; b = (b-l)/2 | ||
831 | if l ~= 0 then ctx.vexl = true end | ||
832 | ctx.vexv = (-1-b)%16 | ||
833 | return dispatchmap(ctx, map) | ||
761 | end, | 834 | end, |
762 | 835 | ||
763 | -- Special case for nop with REX prefix. | 836 | -- Special case for nop with REX prefix. |
764 | nop = function(ctx, name, pat) | 837 | nop = function(ctx, name, pat) |
765 | return dispatch(ctx, ctx.rex and pat or "nop") | 838 | return dispatch(ctx, ctx.rex and pat or "nop") |
766 | end, | 839 | end, |
840 | |||
841 | -- Special case for 0F 77. | ||
842 | emms = function(ctx, name, pat) | ||
843 | if ctx.rex ~= "vex" then | ||
844 | return putop(ctx, "emms") | ||
845 | elseif ctx.vexl then | ||
846 | ctx.vexl = false | ||
847 | return putop(ctx, "zeroall") | ||
848 | else | ||
849 | return putop(ctx, "zeroupper") | ||
850 | end | ||
851 | end, | ||
767 | } | 852 | } |
768 | 853 | ||
769 | ------------------------------------------------------------------------------ | 854 | ------------------------------------------------------------------------------ |