1 /**
2 * @namespace biew_plugins_II
3 * @file plugins/disasm/ix86/ix86_fun.c
4 * @brief This file contains implementation common function and utility
5 * for Intel x86 disassembler.
6 * @version -
7 * @remark this source file is part of Binary vIEW project (BIEW).
8 * The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
9 * All rights reserved. This software is redistributable under the
10 * licence given in the file "Licence.en" ("Licence.ru" in russian
11 * translation) distributed in the BIEW archive.
12 * @note Requires POSIX compatible development system
13 *
14 * @author Nickols_K
15 * @since 1995
16 * @note Development, fixes and improvements
17 * @author Kostya Nosov <k-nosov@yandex.ru>
18 * @date 12.09.2000
19 * @note Adding navigation for indirect jumps
20 **/
21 #include <string.h>
22 #include <limits.h>
23 #include <stdio.h>
24
25 #include "plugins/disasm.h"
26 #include "plugins/disasm/ix86/ix86.h"
27 #include "biewutil.h"
28 #include "bmfile.h"
29 #include "codeguid.h"
30 #include "reg_form.h"
31
32 #define MODRM_REG(X) (((X)&0x38)>>3)
33 #define MODRM_COP(X) MODRM_REG(X)
34 #define MODRM_MOD(X) (((X)&0xC0)>>6)
35 #define MODRM_RM(X) ((X)&0x07)
36
37 char *ix86_appstr;
38 char *ix86_dtile;
39 char *ix86_appbuffer;
40 char *ix86_apistr;
41 char *ix86_modrm_ret;
42 char *ix86_Katmai_buff;
43
44 #define ix86_setModifier(str,modf) disSetModifier(str,modf)
45 #define getSREG(sreg) (ix86_SegRegs[(unsigned char)sreg])
46
47 #define REX_reg(rex,reg) (reg|((rex&1)<<3))
48
49 #define HAS_REX (DisP->pfx&PFX_REX)
50 #define K64_REX (DisP->REX)
51
52 #define HAS_REX (DisP->pfx&PFX_REX)
53 #define USE_WIDE_DATA (DisP->mode&MOD_WIDE_DATA)
54 #define USE_WIDE_ADDR (DisP->mode&MOD_WIDE_ADDR)
55 #define HAS_67_IN64 ((x86_Bitness == DAB_USE64)&&(DisP->pfx&PFX_67))
56
ix86_calcModifier(ix86Param * DisP,unsigned w)57 static inline unsigned ix86_calcModifier(ix86Param* DisP,unsigned w) {
58 unsigned sizptr;
59 if(!w) sizptr = BYTE_PTR;
60 else
61 if(x86_Bitness == DAB_USE64)
62 sizptr = REX_w(DisP->REX)?QWORD_PTR:USE_WIDE_DATA?DWORD_PTR:WORD_PTR;
63 else
64 sizptr = USE_WIDE_DATA ? DWORD_PTR : WORD_PTR;
65 return sizptr;
66 }
67
k64_getREG(ix86Param * DisP,unsigned char reg,tBool w,tBool rex,tBool use_qregs)68 static const char * __FASTCALL__ k64_getREG(ix86Param*DisP,unsigned char reg,tBool w,tBool rex, tBool use_qregs)
69 {
70 if((DisP->mode&MOD_SSE)) {
71 const char **k64_xmm_regs;
72 unsigned ridx;
73 if((DisP->pfx&PFX_VEX) && (DisP->VEX_vlp&0x04)) k64_xmm_regs=k64_YMMXRegs; /* 256-bit vectors */
74 else k64_xmm_regs=k64_XMMXRegs; /* 128-bit vectors */
75 ridx = x86_Bitness==DAB_USE64?REX_reg(rex,reg):(reg&0x07);
76 return k64_xmm_regs[ridx];
77 }
78 else
79 if((DisP->mode&MOD_MMX)) return ix86_MMXRegs[reg];
80 else
81 if(!w) return (x86_Bitness==DAB_USE64&&HAS_REX)?k64_ByteRegs[REX_reg(rex,reg)]:i8086_ByteRegs[reg];
82 else
83 return use_qregs?k64_QWordRegs[REX_reg(rex,reg)]:USE_WIDE_DATA?k64_DWordRegs[REX_reg(rex,reg)]:k64_WordRegs[REX_reg(rex,reg)];
84 }
85
get_VEX_reg(ix86Param * DisP)86 static const char *get_VEX_reg(ix86Param* DisP)
87 {
88 unsigned rg,brex,wrex;
89 const char *rval=NULL;
90 rg = (x86_Bitness == DAB_USE64)?((DisP->VEX_vlp>>3)&0x0F)^0x0F:((DisP->VEX_vlp>>3)&0x07)^0x07;
91 wrex = REX_W(K64_REX);
92 brex = (rg>>3)&0x01;
93 if(DisP->insn_flags&INSN_VEX_V) rval=k64_getREG(DisP,rg,1,brex,wrex);
94 return rval;
95 }
96
GetDigitsApp(unsigned char loc_off,ix86Param * DisP,char codelen,int type)97 static char * __NEAR__ __FASTCALL__ GetDigitsApp(unsigned char loc_off,
98 ix86Param *DisP,
99 char codelen,int type)
100 {
101 ix86_appbuffer[0] = 0;
102 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
103 disAppendDigits(ix86_appbuffer,DisP->CodeAddress + loc_off,
104 APREF_USE_TYPE,codelen,&DisP->RealCmd[loc_off],type);
105 return ix86_appbuffer;
106 }
107
108 #define Get2DigitApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,1,DISARG_BYTE)
109 #define Get2SignDigApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,1,DISARG_CHAR)
110 #define Get4DigitApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,2,DISARG_WORD)
111 #define Get4SignDigApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,2,DISARG_SHORT)
112 #define Get8DigitApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,4,DISARG_DWORD)
113 #define Get8SignDigApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,4,DISARG_LONG)
114 #define Get16DigitApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,8,DISARG_QWORD)
115 #define Get16SignDigApp(loc_off,DisP) GetDigitsApp(loc_off,DisP,8,DISARG_LLONG)
Get2SquareDig(unsigned char loc_off,ix86Param * DisP,tBool as_sign)116 static char * __NEAR__ __FASTCALL__ Get2SquareDig(unsigned char loc_off,ix86Param *DisP,tBool as_sign)
117 {
118 char *ptr = ix86_apistr;
119 char *rets;
120 *ptr = 0;
121 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
122 {
123 rets = GetDigitsApp(loc_off,DisP,1,as_sign ? DISARG_CHAR : DISARG_BYTE);
124 if(!(rets[0] == '+' || rets[0] == '-')) *ptr++ = '+';
125 strcpy(ptr,rets);
126 }
127 return ix86_apistr;
128 }
129
Get4SquareDig(unsigned char loc_off,ix86Param * DisP,tBool as_sign,tBool is_disponly)130 static char * __NEAR__ __FASTCALL__ Get4SquareDig(unsigned char loc_off,ix86Param *DisP,tBool as_sign, tBool is_disponly)
131 {
132 char *ptr = ix86_apistr;
133 char *rets;
134 unsigned type;
135 *ptr = 0;
136 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
137 {
138 type = as_sign ? DISARG_SHORT : DISARG_WORD;
139 type |= is_disponly ? DISARG_DISP : DISARG_IDXDISP;
140 rets = GetDigitsApp(loc_off,DisP,2,type);
141 if(!(rets[0] == '+' || rets[0] == '-')) *ptr++ = '+';
142 strcpy(ptr,rets);
143 }
144 return ix86_apistr;
145 }
146
Get8SquareDig(unsigned char loc_off,ix86Param * DisP,tBool as_sign,tBool is_disponly,tBool as_rip)147 static char * __NEAR__ __FASTCALL__ Get8SquareDig(unsigned char loc_off,ix86Param *DisP,tBool as_sign,tBool is_disponly,tBool as_rip)
148 {
149 char *ptr = ix86_apistr;
150 char *rets;
151 unsigned type;
152 *ptr = 0;
153 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
154 {
155 type = as_sign ? DISARG_LONG : DISARG_DWORD;
156 type |= is_disponly ? DISARG_DISP : DISARG_IDXDISP;
157 if(as_rip) type |= DISARG_RIP;
158 rets = GetDigitsApp(loc_off,DisP,4,type);
159 if(!(rets[0] == '+' || rets[0] == '-')) *ptr++ = '+';
160 strcpy(ptr,rets);
161 }
162 return ix86_apistr;
163 }
164
Get16SquareDig(unsigned char loc_off,ix86Param * DisP,tBool as_sign,tBool is_disponly)165 static char * __NEAR__ __FASTCALL__ Get16SquareDig(unsigned char loc_off,ix86Param *DisP,tBool as_sign,tBool is_disponly)
166 {
167 char *ptr = ix86_apistr;
168 char *rets;
169 unsigned type;
170 *ptr = 0;
171 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
172 {
173 type = as_sign ? DISARG_LLONG : DISARG_QWORD;
174 type |= is_disponly ? DISARG_DISP : DISARG_IDXDISP;
175 rets = GetDigitsApp(loc_off,DisP,8,type);
176 if(!(rets[0] == '+' || rets[0] == '-')) *ptr++ = '+';
177 strcpy(ptr,rets);
178 }
179 return ix86_apistr;
180 }
181
ix86_ArgES(char * str,ix86Param * param)182 void __FASTCALL__ ix86_ArgES(char *str,ix86Param *param)
183 {
184 UNUSED(param);
185 strcat(str,"es");
186 }
187
ix86_ArgDS(char * str,ix86Param * param)188 void __FASTCALL__ ix86_ArgDS(char *str,ix86Param *param)
189 {
190 UNUSED(param);
191 strcat(str,"ds");
192 }
193
ix86_ArgSS(char * str,ix86Param * param)194 void __FASTCALL__ ix86_ArgSS(char *str,ix86Param *param)
195 {
196 UNUSED(param);
197 strcat(str,"ss");
198 }
199
ix86_ArgCS(char * str,ix86Param * param)200 void __FASTCALL__ ix86_ArgCS(char *str,ix86Param *param)
201 {
202 UNUSED(param);
203 strcat(str,"cs");
204 }
205
ix86_ArgFS(char * str,ix86Param * param)206 void __FASTCALL__ ix86_ArgFS(char *str,ix86Param *param)
207 {
208 UNUSED(param);
209 strcat(str,"fs");
210 }
211
ix86_ArgGS(char * str,ix86Param * param)212 void __FASTCALL__ ix86_ArgGS(char *str,ix86Param *param)
213 {
214 UNUSED(param);
215 strcat(str,"gs");
216 }
217
218
ix86_GetDigitTile(ix86Param * DisP,char wrd,char sgn,unsigned char loc_off)219 static char * __FASTCALL__ ix86_GetDigitTile(ix86Param* DisP,char wrd,char sgn,unsigned char loc_off)
220 {
221 int cl,type;
222 int do_64;
223 do_64 = 0;
224 if(x86_Bitness == DAB_USE64 && wrd == -1) do_64 = 1; /* special case for */
225 cl = do_64 ? 8 : wrd ? ( USE_WIDE_DATA ? 4 : 2 ) : 1;
226 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
227 {
228 if(do_64) type = sgn ? DISARG_LLONG : DISARG_QWORD;
229 else
230 type = sgn ? wrd ? ( USE_WIDE_DATA ? DISARG_LONG : DISARG_SHORT ) : DISARG_CHAR:
231 wrd ? ( USE_WIDE_DATA ? DISARG_DWORD : DISARG_WORD ) : DISARG_BYTE;
232 type |= DISARG_IMM;
233 ix86_dtile[0] = 0;
234 disAppendDigits(ix86_dtile,
235 DisP->CodeAddress + loc_off,
236 APREF_USE_TYPE,cl,&DisP->RealCmd[loc_off],type);
237 }
238 DisP->codelen += cl;
239 return ix86_dtile;
240 }
241
arg_segoff(char * str,ix86Param * DisP)242 void __FASTCALL__ arg_segoff(char * str,ix86Param *DisP)
243 {
244 unsigned long newpos = 0L;
245 long off = 0L;
246 unsigned short seg = 0;
247 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
248 {
249 seg = USE_WIDE_DATA ? *((tInt16 *)(&DisP->RealCmd[5])) : *((tInt16 *)(&DisP->RealCmd[3]));
250 off = USE_WIDE_DATA ? *((tInt32 *)(&DisP->RealCmd[1])) : (tInt32)(*((tInt16 *)(&DisP->RealCmd[1])));
251 newpos = ((long)(seg) << 4) + off; /* It is computing of x86 real-mode address */
252 }
253 DisP->codelen += USE_WIDE_DATA ? 6 : 4;
254 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
255 disAppendFAddr(str,DisP->CodeAddress + 1,off,newpos,
256 USE_WIDE_DATA ? DISADR_FAR32 : DISADR_FAR16,seg,DisP->codelen-1);
257 }
258
arg_offset(char * str,ix86Param * DisP)259 void __FASTCALL__ arg_offset(char * str,ix86Param *DisP)
260 {
261 long lshift = 0L;
262 unsigned long newpos;
263 unsigned modifier,off8;
264 off8 = (DisP->insn_flags&IMM_BYTE)?1:0;
265 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
266 lshift = off8 ? (long)(*((tInt8 *)(&DisP->RealCmd[1]))):
267 USE_WIDE_DATA ?(long)(*((tInt32 *)(&DisP->RealCmd[1]))) :
268 (long)(*((tInt16 *)(&DisP->RealCmd[1])));
269 #if 0
270 /*
271 In 64-bit mode, the operand size defaults to 64 bits. The processor sign-extends
272 the 8-bit or 32-bit displacement value to 64 bits before adding it to the RIP.
273 */
274 if(x86_Bitness == DAB_USE64) {
275 DisP->codelen += 8;
276 modifier=DISADR_NEAR64;
277 }
278 else
279 #endif
280 {
281 DisP->codelen += off8 ? 1 : USE_WIDE_DATA ? 4 : 2;
282 modifier = USE_WIDE_DATA ? off8 ? DISARG_SHORT : DISADR_NEAR32 : DISADR_NEAR16;
283 }
284 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
285 {
286 newpos = DisP->CodeAddress + lshift + DisP->codelen;
287 disAppendFAddr(str,DisP->CodeAddress + 1,lshift,newpos,modifier,0,DisP->codelen);
288 }
289 }
290
getSIBRegs(ix86Param * DisP,char * base,char * scale,char * _index,char * mod,char code)291 static void __NEAR__ __FASTCALL__ getSIBRegs(ix86Param*DisP,char * base,char * scale,char * _index,char *mod,char code)
292 {
293 char scl = (code & 0xC0) >> 6;
294 char bas = code & 0x07;
295 char ind = (code & 0x38) >> 3;
296 unsigned long mode = DisP->mode;
297 tBool brex, wrex;
298 DisP->mode|=MOD_WIDE_DATA;
299 DisP->mode&=~MOD_MMX;
300 DisP->mode&=~MOD_SSE;
301 brex = wrex = 0;
302 if(scl)
303 {
304 scale[0] = '*';
305 scale[1] = ( 1 << scl ) + 0x30;
306 scale[2] = 0;
307 }
308 else scale[0] = 0;
309 if(ind == 4)
310 {
311 if(x86_Bitness == DAB_USE64 && REX_X(K64_REX))
312 /* AMD 24594.pdf rev 3.02 aug 2002:
313 REX adds fourth bit (X) which is decoded
314 that allows to use R12 as index.
315 */
316 goto do_r12;
317 else
318 _index[0] = 0;
319 }
320 else
321 {
322 do_r12:
323 if(x86_Bitness == DAB_USE64)
324 {
325 wrex = HAS_67_IN64?0:1;
326 brex = REX_X(K64_REX);
327 }
328 strcpy(_index,k64_getREG(DisP,ind,True,brex,wrex));
329 }
330 if(bas == 5 && *mod == 0) { base[0] = 0; *mod = 2; }
331 else
332 {
333 if(x86_Bitness == DAB_USE64)
334 {
335 wrex = HAS_67_IN64?0:1;
336 brex = REX_B(K64_REX);
337 }
338 strcpy(base,k64_getREG(DisP,bas,True,brex,wrex));
339 }
340 DisP->mode = mode;
341 #if 0
342 return ind == 4 || ind == 5 || bas == 4 || bas == 5; /** return is_stack */
343 #endif
344 }
345
ConstrSibMod(ix86Param * DisP,char * store,char * scale,char * _index,char * base,char code,char * mod)346 static char * __NEAR__ __FASTCALL__ ConstrSibMod(ix86Param*DisP,char * store,char * scale,char * _index,char * base,char code,char *mod)
347 {
348 getSIBRegs(DisP,base,scale,_index,mod,code);
349 store[0] = 0;
350 if(_index[0])
351 {
352 strcat(store,_index);
353 strcat(store,scale);
354 }
355 if(base[0])
356 {
357 if(_index[0]) strcat(store,"+");
358 strcat(store,base);
359 }
360 return store;
361 }
362
363
ix86_getModRM16(tBool w,unsigned char mod,unsigned char rm,ix86Param * DisP)364 char * __FASTCALL__ ix86_getModRM16(tBool w,unsigned char mod,unsigned char rm,ix86Param *DisP)
365 {
366 char square[50];
367 char new_mode = mod;
368 unsigned char clen;
369 tBool as_sign,is_disponly,as_rip;
370 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
371 strcpy(square,ix86_A16[rm]);
372 mod = new_mode;
373 if(mod != 3)
374 {
375 strcat(ix86_modrm_ret,ix86_segpref);
376 ix86_segpref[0] = 0;
377 }
378 is_disponly = False;
379 as_sign = True;
380 as_rip=False;
381 }
382 clen = 2;
383 switch(mod) {
384 case 0:
385 if(rm!=6) clen=0;
386 else clen=2;
387 break;
388 case 1:
389 clen = 1;
390 break;
391 case 2:
392 clen=2;
393 break;
394 default:
395 clen=0;
396 break;
397 }
398 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
399 switch(mod) {
400 case 0:
401 if(rm != 6) /* i.e. combine address */
402 strcat(ix86_modrm_ret,square);
403 else { /* i.e. displacement only. fake mod = 2 */
404 square[0] = 0;
405 is_disponly = True;
406 as_sign = False;
407 goto disp_long;
408 }
409 break;
410 case 1:
411 strcat(ix86_modrm_ret,ix86_segpref);
412 ix86_segpref[0] = 0;
413 strcat(ix86_modrm_ret,square);
414 /* The "disp8" nomenclature denotes an 8-bit displacement
415 following the ModR/M or SIB byte, to be sign-extended
416 and added to the index. */
417 strcat(ix86_modrm_ret,Get2SquareDig(2,DisP,True));
418 break;
419 case 2: {
420 disp_long:
421 strcat(ix86_modrm_ret,ix86_segpref);
422 ix86_segpref[0] = 0;
423 strcat(ix86_modrm_ret,square);
424 strcat(ix86_modrm_ret,Get4SquareDig(2,DisP,as_sign,is_disponly));
425 }
426 break;
427 default:
428 strcat(ix86_modrm_ret,k64_getREG(DisP,rm,w,0,0));
429 break;
430 }
431 }
432 if(mod != 3) DisP->codelen += clen;
433 return ix86_modrm_ret;
434 }
435
ix86_getModRM32(tBool w,unsigned char mod,unsigned char rm,ix86Param * DisP)436 char * __FASTCALL__ ix86_getModRM32(tBool w,unsigned char mod,unsigned char rm,ix86Param *DisP)
437 {
438 const char *cptr;
439 char square[50];
440 char ret1[50];
441 char base[8];
442 char _index[8];
443 char scale[4];
444 char new_mode = mod;
445 unsigned char clen,tmp;
446 tBool as_sign,is_disponly,as_rip;
447 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
448 if(rm == 4) cptr = ConstrSibMod(DisP,ret1,base,_index,scale,DisP->RealCmd[2],&new_mode);
449 else cptr = k64_DWordRegs[REX_reg(REX_b(K64_REX),rm)];
450 strcpy(square,cptr);
451 mod = new_mode;
452 if(mod != 3) {
453 strcat(ix86_modrm_ret,ix86_segpref);
454 ix86_segpref[0] = 0;
455 }
456 is_disponly = False;
457 as_sign = True;
458 as_rip=False;
459 }
460 clen = 2;
461 switch(mod) {
462 case 0:
463 if(rm != 5) { /* i.e. combine address */
464 clen = 0;
465 if(rm == 4) clen = 1;
466 }
467 else goto __disp_long;
468 break;
469 case 1:
470 if(rm != 4) clen = 1;
471 else clen = 2;
472 break;
473 case 2: {
474 __disp_long:
475 if(rm != 4) clen = 4;
476 else clen = 5;
477 }
478 break;
479 default:
480 clen=0;
481 break;
482 }
483 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
484 switch(mod) {
485 case 0:
486 if(rm != 5) /* i.e. combine address */
487 strcat(ix86_modrm_ret,square);
488 else { /* i.e. displacement only. fake mod = 2 */
489 square[0] = 0;
490 is_disponly = True;
491 as_sign = False;
492 goto disp_long;
493 }
494 break;
495 case 1:
496 if(rm != 4) tmp = 2;
497 else tmp = 3;
498 strcat(ix86_modrm_ret,square);
499 /* The "disp8" nomenclature denotes an 8-bit displacement
500 following the ModR/M or SIB byte, to be sign-extended
501 and added to the index. */
502 strcat(ix86_modrm_ret,Get2SquareDig(tmp,DisP,True));
503 break;
504 case 2: {
505 disp_long:
506 if(rm != 4) tmp = 2;
507 else tmp = 3;
508 strcat(ix86_modrm_ret,square);
509 strcat(ix86_modrm_ret,Get8SquareDig(tmp,DisP,as_sign,is_disponly,as_rip));
510 }
511 break;
512 default:
513 strcat(ix86_modrm_ret,k64_getREG(DisP,rm,w,0,0));
514 break;
515 }
516 }
517 if(mod != 3) DisP->codelen += clen;
518 return ix86_modrm_ret;
519 }
520
ix86_getModRM64(tBool w,unsigned char mod,unsigned char rm,ix86Param * DisP)521 char * __FASTCALL__ ix86_getModRM64(tBool w,unsigned char mod,unsigned char rm,ix86Param *DisP)
522 {
523 const char *cptr;
524 char square[50];
525 char ret1[50];
526 char base[8];
527 char _index[8];
528 char scale[4];
529 char new_mode = mod;
530 unsigned char clen,tmp;
531 tBool as_sign,is_disponly,as_rip;
532 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
533 if(rm == 4) cptr = ConstrSibMod(DisP,ret1,base,_index,scale,DisP->RealCmd[2],&new_mode);
534 else cptr = k64_QWordRegs[REX_reg(REX_b(K64_REX),rm)];
535 strcpy(square,cptr);
536 mod = new_mode;
537 if(mod != 3) {
538 strcat(ix86_modrm_ret,ix86_segpref);
539 ix86_segpref[0] = 0;
540 }
541 is_disponly = False;
542 as_sign = True;
543 as_rip=False;
544 }
545 clen = 2;
546 switch(mod) {
547 case 0:
548 if(rm != 5) { /* i.e. combine address */
549 clen = 0;
550 if(rm == 4) clen = 1;
551 }
552 else goto __disp_long;
553 break;
554 case 1:
555 if(rm != 4) clen = 1;
556 else clen = 2;
557 break;
558 case 2: {
559 __disp_long:
560 if(rm != 4) clen = 4;
561 else clen = 5;
562 }
563 break;
564 default:
565 clen=0;
566 break;
567 }
568 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
569 switch(mod) {
570 case 0:
571 if(rm != 5) /* i.e. combine address */
572 strcat(ix86_modrm_ret,square);
573 else { /* i.e. displacement only. fake mod = 2 */
574 square[0] = 0;
575 is_disponly = True;
576 as_sign = False;
577 goto disp_long;
578 }
579 break;
580 case 1:
581 if(rm != 4) tmp = 2;
582 else tmp = 3;
583 strcat(ix86_modrm_ret,square);
584 /* The "disp8" nomenclature denotes an 8-bit displacement
585 following the ModR/M or SIB byte, to be sign-extended
586 and added to the index. */
587 strcat(ix86_modrm_ret,Get2SquareDig(tmp,DisP,True));
588 break;
589 case 2: {
590 disp_long:
591 if(is_disponly) {
592 strcat(ix86_modrm_ret,"rip");
593 as_sign = True;
594 is_disponly = False;
595 as_rip=True;
596 }
597 if(rm != 4) tmp = 2;
598 else tmp = 3;
599 strcat(ix86_modrm_ret,square);
600 strcat(ix86_modrm_ret,Get8SquareDig(tmp,DisP,as_sign,is_disponly,as_rip));
601 }
602 break;
603 default: {
604 tBool brex, use64;
605 brex = REX_B(K64_REX);
606 use64 = REX_W(K64_REX);
607 strcat(ix86_modrm_ret,k64_getREG(DisP,rm,w,brex,use64));
608 }
609 break;
610 }
611 }
612 if(mod != 3) DisP->codelen += clen;
613 return ix86_modrm_ret;
614 }
615
ix86_getModRM(tBool w,unsigned char mod,unsigned char rm,ix86Param * DisP)616 char * __FASTCALL__ ix86_getModRM(tBool w,unsigned char mod,unsigned char rm,ix86Param *DisP)
617 {
618 char *rval;
619 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
620 if(mod!=3) strcpy(ix86_modrm_ret,"[");
621 else ix86_modrm_ret[0]=0;
622 }
623 if((x86_Bitness == DAB_USE16 || x86_Bitness == DAB_USE32) && !USE_WIDE_ADDR) rval = ix86_getModRM16(w,mod,rm,DisP);
624 else
625 if(x86_Bitness == DAB_USE64 && USE_WIDE_ADDR) rval = ix86_getModRM64(w,mod,rm,DisP);
626 else rval = ix86_getModRM32(w,mod,rm,DisP);
627 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
628 if(mod!=3) strcat(ix86_modrm_ret,"]");
629 }
630 return rval;
631 }
632
ix86_CStile(ix86Param * DisP,char * str,const char * arg2)633 char * __FASTCALL__ ix86_CStile(ix86Param *DisP,char *str,const char *arg2)
634 {
635 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) {
636 strcat(str,",");
637 strcat(str,arg2);
638 }
639 return str;
640 }
641
__buildModRegRm(ix86Param * DisP,tBool w,tBool d)642 static char * __NEAR__ __FASTCALL__ __buildModRegRm(ix86Param *DisP,tBool w,tBool d)
643 {
644 char reg = MODRM_REG(DisP->RealCmd[1]);
645 char mod = MODRM_MOD(DisP->RealCmd[1]);
646 char rm = MODRM_RM(DisP->RealCmd[1]);
647 const char *regs,* modrm, *ends, *vxx=NULL;
648 tBool brex, wrex, vex_d;
649 brex = REX_R(K64_REX);
650 wrex = REX_W(K64_REX);
651 regs = k64_getREG(DisP,reg,w,brex,wrex);
652 brex = REX_B(K64_REX);
653 if(mod == 3) modrm = k64_getREG(DisP,rm,w,brex,wrex);
654 else modrm = ix86_getModRM(w,mod,rm,DisP);
655 ix86_dtile[0] = 0;
656 vex_d = 0;
657 if(DisP->insn_flags&INSN_VEXW_AS_SWAP && DisP->pfx&PFX_VEX) vex_d = REX_W(K64_REX);
658 strcat(ix86_dtile,d ? regs : modrm);
659 /* add VEX.vvvv field as first source operand */
660 ends = d ? modrm : regs;
661 if((DisP->pfx&PFX_VEX) && (DisP->insn_flags&INSN_VEX_V)) vxx = get_VEX_reg(DisP);
662 if(vxx) {
663 ix86_CStile(DisP,ix86_dtile,vex_d ? ends : vxx);
664 ix86_CStile(DisP,ix86_dtile,vex_d ? vxx : ends);
665 }
666 else ix86_CStile(DisP,ix86_dtile,ends);
667 return ix86_dtile;
668 }
669
__buildModRegRmReg(ix86Param * DisP,tBool d,unsigned char wrex)670 static char * __NEAR__ __FASTCALL__ __buildModRegRmReg(ix86Param *DisP,tBool d,unsigned char wrex)
671 {
672 char reg = MODRM_REG(DisP->RealCmd[1]);
673 char mod = MODRM_MOD(DisP->RealCmd[1]);
674 char rm = MODRM_RM(DisP->RealCmd[1]);
675 const char *dest,*src1,*src2;
676 unsigned char is4,brex,reg2;
677 brex = REX_R(K64_REX);
678 dest = k64_getREG(DisP,reg,1,brex,wrex);
679 brex = REX_B(K64_REX);
680 DisP->codelen++;
681 if(mod == 3) src1 = k64_getREG(DisP,rm,1,brex,wrex);
682 else src1 = ix86_getModRM(1,mod,rm,DisP);
683 is4=DisP->RealCmd[DisP->codelen];
684 reg2 = ((is4>>4)&0x0F);
685 src2 = k64_getREG(DisP,reg2&0x07,1,(reg2>>3)&1,wrex);
686 ix86_dtile[0] = 0;
687 strcat(ix86_dtile,dest);
688 /* add VEX.vvvv field as first source operand */
689 if((DisP->pfx&PFX_VEX) && (DisP->insn_flags&INSN_VEX_V)) ix86_CStile(DisP,ix86_dtile,get_VEX_reg(DisP));
690 ix86_CStile(DisP,ix86_dtile,d ? src2 : src1);
691 ix86_CStile(DisP,ix86_dtile,d ? src1 : src2);
692 DisP->codelen++;
693 return ix86_dtile;
694 }
695
arg_cpu_modregrm(char * str,ix86Param * DisP)696 void __FASTCALL__ arg_cpu_modregrm(char * str,ix86Param *DisP)
697 {
698 DisP->codelen++;
699 strcat(str,__buildModRegRm(DisP,(DisP->insn_flags&INSN_OP_BYTE)?False:True,(DisP->insn_flags&INSN_STORE)?False:True));
700 }
701
arg_cpu_modREGrm(char * str,ix86Param * DisP)702 void __FASTCALL__ arg_cpu_modREGrm(char * str,ix86Param *DisP)
703 {
704 tBool brex,wrex;
705 char reg = MODRM_REG(DisP->RealCmd[1]);
706 char mod = MODRM_MOD(DisP->RealCmd[1]);
707 char rm = MODRM_RM(DisP->RealCmd[1]);
708 unsigned long mode = DisP->mode;
709 brex = REX_B(K64_REX);
710 wrex = REX_W(K64_REX);
711 if(x86_Bitness>DAB_USE16) DisP->mode|=MOD_WIDE_DATA;
712 strcat(str,k64_getREG(DisP,reg,True,brex,wrex));
713 DisP->mode=mode;
714 DisP->codelen++;
715 ix86_CStile(DisP,str,ix86_getModRM((DisP->insn_flags&INSN_OP_BYTE)?False:True,mod,rm,DisP));
716 }
717
arg_cpu_mod_rm(char * str,ix86Param * DisP)718 void __FASTCALL__ arg_cpu_mod_rm(char* str,ix86Param *DisP)
719 {
720 char mod = MODRM_MOD(DisP->RealCmd[1]);
721 char rm = MODRM_RM(DisP->RealCmd[1]);
722 tBool w = (DisP->insn_flags&INSN_OP_BYTE)?False:True;
723 if(mod<3) ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
724 DisP->codelen++;
725 strcat(str,ix86_getModRM(w,mod,rm,DisP));
726 }
727
arg_cpu_mod_rm_imm(char * str,ix86Param * DisP)728 void __FASTCALL__ arg_cpu_mod_rm_imm(char *str,ix86Param *DisP)
729 {
730 arg_cpu_mod_rm(str,DisP);
731 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,(DisP->insn_flags&IMM_BYTE)?False:True,0,DisP->codelen));
732 }
733
arg_cpu_modregrm_imm(char * str,ix86Param * DisP)734 void __FASTCALL__ arg_cpu_modregrm_imm(char *str,ix86Param *DisP)
735 {
736 arg_cpu_modregrm(str,DisP);
737 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,(DisP->insn_flags&IMM_BYTE)?False:True,0,DisP->codelen));
738 }
739
arg_cpu_modsegrm(char * str,ix86Param * DisP)740 void __FASTCALL__ arg_cpu_modsegrm(char * str,ix86Param *DisP)
741 {
742 char direct = ( DisP->RealCmd[0] & 0x02 ) >> 1;
743 char sreg = MODRM_REG(DisP->RealCmd[1]);
744 char reg = MODRM_RM(DisP->RealCmd[1]);
745 char mod = MODRM_MOD(DisP->RealCmd[1]);
746 const char *tileptr,*sregptr;
747 unsigned long mode = DisP->mode;
748 DisP->mode&= ~MOD_WIDE_DATA; /* disable: 'mov eax, ds' constructions */
749 sregptr = getSREG(sreg);
750 DisP->codelen = 2;
751 tileptr = ix86_getModRM(True,mod,reg,DisP);
752 if(sreg > 3)
753 if(((DisP->pro_clone & IX86_CPUMASK) < 3) && (x86_Bitness != DAB_USE64))
754 DisP->pro_clone = IX86_CPU386;
755 DisP->mode = mode;
756 strcat(str,direct ? sregptr : tileptr);
757 ix86_CStile(DisP,str,direct ? tileptr : sregptr);
758 }
759
arg_r0_imm(char * str,ix86Param * DisP)760 void __FASTCALL__ arg_r0_imm(char * str,ix86Param *DisP)
761 {
762 char w = DisP->RealCmd[0] & 0x01;
763 tBool wrex=0;
764 wrex = REX_W(K64_REX);
765 /* I guess that K9 will support "OP rax, imm64" forms
766 same as "OP rrx, imm64" since they are not longer
767 than 15 bytes in length
768 (example: "adc r13, 123456789ABCDEF0").
769 TODO: if(use64) w = -1; here */
770 strcat(str,k64_getREG(DisP,0,w,0,wrex));
771 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,w,0,1));
772 }
773
arg_r0rm(char * str,ix86Param * DisP)774 void __FASTCALL__ arg_r0rm(char *str,ix86Param *DisP)
775 {
776 unsigned char rm = MODRM_RM(DisP->RealCmd[0]);
777 tBool brex,wrex;
778 brex = REX_B(K64_REX);
779 wrex = REX_W(K64_REX);
780 if(rm==0 && !HAS_REX) strcpy(str,"nop");
781 else {
782 strcat(str,k64_getREG(DisP,0,True,0,wrex));
783 ix86_CStile(DisP,str,k64_getREG(DisP,rm,True,brex,wrex));
784 }
785 }
786
arg_r0mem(char * str,ix86Param * DisP)787 void __FASTCALL__ arg_r0mem(char *str,ix86Param *DisP)
788 {
789 unsigned char d = DisP->RealCmd[0] & 0x02;
790 const char *mem,*reg;
791 tBool wrex = REX_W(K64_REX);
792 if(x86_Bitness == DAB_USE64 && !HAS_67_IN64)
793 /* Opcodes A0 through A3 are address sized. In 64-bit mode, memory offset default to 64-bit. */
794 {
795 mem = Get16SquareDig(1,DisP,False,True);
796 }
797 else
798 mem = USE_WIDE_ADDR ? Get8SquareDig(1,DisP,False,True,False) :
799 Get4SquareDig(1,DisP,False,True);
800 strcpy(ix86_appstr,"[");
801 strcat(ix86_appstr,ix86_segpref);
802 ix86_segpref[0] = 0;
803 strcat(ix86_appstr,mem);
804 strcat(ix86_appstr,"]");
805 reg = k64_getREG(DisP,0,DisP->RealCmd[0] & 0x01,0,wrex);
806 if(x86_Bitness == DAB_USE64 && !HAS_67_IN64) DisP->codelen = 9;
807 else DisP->codelen = USE_WIDE_ADDR ? 5 : 3;
808 strcat(str,d ? ix86_appstr : reg);
809 ix86_CStile(DisP,str,d ? reg : ix86_appstr);
810 }
811
arg_insnreg(char * str,ix86Param * DisP)812 void __FASTCALL__ arg_insnreg(char *str,ix86Param *DisP)
813 {
814 tBool brex,wrex;
815 brex = REX_B(K64_REX);
816 wrex = REX_W(K64_REX);
817 strcat(str,k64_getREG(DisP,MODRM_RM(DisP->RealCmd[0]),(DisP->insn_flags&INSN_OP_BYTE)?False:True,brex,(DisP->insn_flags&K64_FORCE64)?1:wrex));
818 }
819
arg_insnreg_imm(char * str,ix86Param * DisP)820 void __FASTCALL__ arg_insnreg_imm(char * str,ix86Param *DisP)
821 {
822 char w = (DisP->insn_flags&INSN_OP_BYTE)?0:1;
823 arg_insnreg(str,DisP);
824 if(x86_Bitness == DAB_USE64 && REX_W(K64_REX) && w) w = -1; /* special case for do64 */
825 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,w,0,1));
826 }
827
arg_imm(char * str,ix86Param * DisP)828 void __FASTCALL__ arg_imm(char *str,ix86Param *DisP)
829 {
830 char wrd = 1,sgn = 0;
831 if(DisP->insn_flags&IMM_BYTE) {
832 ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,1)]);
833 wrd = 0;
834 sgn = 1;
835 }
836 if(x86_Bitness == DAB_USE64 && REX_W(K64_REX)) wrd=-1;
837 strcat(str,ix86_GetDigitTile(DisP,wrd,sgn,1));
838 }
839
arg_imm8(char * str,ix86Param * DisP)840 void __FASTCALL__ arg_imm8(char *str,ix86Param *DisP)
841 {
842 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
843 disAppendDigits(str,DisP->CodeAddress + DisP->codelen,
844 APREF_USE_TYPE,1,&DisP->RealCmd[DisP->codelen],DISARG_BYTE);
845 DisP->codelen++;
846 }
847
arg_imm16(char * str,ix86Param * DisP)848 void __FASTCALL__ arg_imm16(char *str,ix86Param *DisP)
849 {
850 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY))
851 disAppendDigits(str,DisP->CodeAddress + DisP->codelen,
852 APREF_USE_TYPE,2,&DisP->RealCmd[DisP->codelen],DISARG_WORD | DISARG_IMM);
853 DisP->codelen+=2;
854 }
855
arg_imm16_imm8(char * str,ix86Param * DisP)856 void __FASTCALL__ arg_imm16_imm8(char *str,ix86Param *DisP)
857 {
858 arg_imm16(str,DisP);
859 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
860 arg_imm8(str,DisP);
861 }
862
ix86_ArgRmDigit(char * str,ix86Param * DisP,char w,char s)863 static void __FASTCALL__ ix86_ArgRmDigit(char *str,ix86Param *DisP,char w,char s)
864 {
865 char mod = MODRM_MOD(DisP->RealCmd[1]);
866 char rm = MODRM_RM(DisP->RealCmd[1]);
867 strcat(str,ix86_getModRM(w == 2 ? True : w,mod,rm,DisP));
868 DisP->codelen++;
869 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,w == 2 ? 0 : w,s,DisP->codelen));
870 }
871
ix86_ArgOp1(char * str,ix86Param * DisP)872 void __FASTCALL__ ix86_ArgOp1(char *str,ix86Param *DisP)
873 {
874 unsigned char w = DisP->RealCmd[0] & 0x01;
875 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
876 strcpy(str,ix86_Op1Names[cop]);
877 TabSpace(str,TAB_POS);
878 ix86_ArgRmDigit(str,DisP,w,cop == 0 || cop == 2 || cop == 3 || cop == 5 ? 1 : 0);
879 }
880
ix86_ArgOp2(char * str,ix86Param * DisP)881 void __FASTCALL__ ix86_ArgOp2(char *str,ix86Param *DisP)
882 {
883 unsigned char w = DisP->RealCmd[0] & 0x01;
884 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
885 strcpy(str,ix86_Op1Names[cop]);
886 TabSpace(str,TAB_POS);
887 if(w) ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
888 ix86_ArgRmDigit(str,DisP,w ? 2 : w, w ? 1 : 0);
889 }
890
ix86_ShOp2(char * str,ix86Param * DisP)891 void __FASTCALL__ ix86_ShOp2(char *str,ix86Param *DisP)
892 {
893 char *a1,*a2;
894 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
895 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
896 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
897 unsigned char w = DisP->RealCmd[0] & 0x01;
898 DisP->codelen++;
899 strcpy(str,ix86_ShNames[cop]);
900 TabSpace(str,TAB_POS);
901 ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
902 a1 = ix86_getModRM(w,mod,rm,DisP);
903 strcat(str,a1);
904 a2 = ix86_GetDigitTile(DisP,0,0,DisP->codelen);
905 ix86_CStile(DisP,str,a2);
906 }
907
ix86_DblShift(char * str,ix86Param * DisP)908 void __FASTCALL__ ix86_DblShift(char *str,ix86Param *DisP)
909 {
910 unsigned char code = DisP->RealCmd[0];
911 arg_cpu_modregrm(str,DisP);
912 if(code&0x01) ix86_CStile(DisP,str,"cl");
913 else {
914 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
915 arg_imm8(str,DisP);
916 }
917 }
918
ix86_ShOp1(char * str,ix86Param * DisP)919 void __FASTCALL__ ix86_ShOp1(char *str,ix86Param *DisP)
920 {
921 char *a1;
922 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
923 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
924 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
925 unsigned char w = DisP->RealCmd[0] & 0x01;
926 DisP->codelen++;
927 a1 = ix86_getModRM(w,mod,rm,DisP);
928 strcpy(str,ix86_ShNames[cop]);
929 TabSpace(str,TAB_POS);
930 ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
931 strcat(str,a1);
932 ix86_CStile(DisP,str,"1");
933 }
934
ix86_ShOpCL(char * str,ix86Param * DisP)935 void __FASTCALL__ ix86_ShOpCL(char *str,ix86Param *DisP)
936 {
937 char *a1;
938 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
939 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
940 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
941 unsigned char w = DisP->RealCmd[0] & 0x01;
942 DisP->codelen++;
943 a1 = ix86_getModRM(w,mod,rm,DisP);
944 strcpy(str,ix86_ShNames[cop]);
945 TabSpace(str,TAB_POS);
946 ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
947 strcat(str,a1);
948 ix86_CStile(DisP,str,"cl");
949 }
950
ix86_ArgGrp1(char * str,ix86Param * DisP)951 void __FASTCALL__ ix86_ArgGrp1(char *str,ix86Param *DisP)
952 {
953 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
954 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
955 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
956 unsigned char w = DisP->RealCmd[0] & 0x01;
957 strcpy(str,ix86_Gr1Names[cop]);
958 TabSpace(str,TAB_POS);
959 DisP->codelen++;
960 ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,w)]);
961 if(!cop) /** test only */
962 {
963 strcat(str,ix86_getModRM(w,mod,rm,DisP));
964 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,w == 2 ? 0 : w,0,DisP->codelen));
965 }
966 else
967 strcat(str,ix86_getModRM(w,mod,rm,DisP));
968 }
969
ix86_ArgGrp2(char * str,ix86Param * DisP)970 void __FASTCALL__ ix86_ArgGrp2(char *str,ix86Param *DisP)
971 {
972 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
973 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
974 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
975 unsigned char w = DisP->RealCmd[0] & 0x01;
976 unsigned char wrd = cop & 0x01;
977 unsigned sizptr;
978 unsigned oldDisNeedRef;
979 unsigned char REX = DisP->REX;
980 DisP->codelen++;
981 strcpy(str,ix86_Gr2Names[cop]);
982 /*
983 Added by "Kostya Nosov" <k-nosov@yandex.ru>:
984 make NEEDREF_ALL for indirect "jmp" and "call"
985 */
986 oldDisNeedRef = disNeedRef;
987 /*
988 if(code2 >= 2 && code2 <= 5 && disNeedRef != NEEDREF_NONE)
989 disNeedRef = NEEDREF_ALL;
990 */
991 TabSpace(str,TAB_POS);
992 if(cop >=2 && cop <= 5) DisP->REX|=0x08;
993 if(cop == 0 || cop == 1) { strcat(str,ix86_getModRM(w,mod,rm,DisP)); } /** inc dec */
994 else
995 {
996 wrd = cop == 0x06 || cop == 0x07 ? 0 : wrd; /** push / pop; */
997 if(x86_Bitness == DAB_USE64) sizptr = HAS_REX?REX_w(K64_REX)?QWORD_PTR:DWORD_PTR:QWORD_PTR;
998 else
999 if(!wrd) sizptr = USE_WIDE_DATA?DWORD_PTR:WORD_PTR;
1000 else sizptr = USE_WIDE_DATA?PWORD_PTR:DWORD_PTR;
1001 ix86_setModifier(str,ix86_sizes[sizptr]);
1002 strcat(str,ix86_getModRM(True,mod,rm,DisP));
1003 }
1004 disNeedRef = oldDisNeedRef;
1005 DisP->REX = REX;
1006 }
1007
ix86_InOut(char * str,ix86Param * DisP)1008 void __FASTCALL__ ix86_InOut(char * str,ix86Param *DisP)
1009 {
1010 const char *arg,*reg1,*reg2,*regptr,*dig;
1011 char i;
1012 regptr = k64_getREG(DisP,0,DisP->RealCmd[0] & 0x01,0,0);
1013 dig = Get2Digit(DisP->RealCmd[1]);
1014 i = DisP->RealCmd[0] & 0x08;
1015 if(!i) DisP->codelen++;
1016 arg = i ? "dx" : dig;
1017 if(DisP->RealCmd[0] & 0x02)
1018 {
1019 reg1 = arg;
1020 reg2 = regptr;
1021 }
1022 else
1023 {
1024 reg1 = regptr;
1025 reg2 = arg;
1026 }
1027 strcat(str,reg1);
1028 ix86_CStile(DisP,str,reg2);
1029 }
1030
ix86_prepare_flags(const ix86_ExOpcodes * extable,ix86Param * DisP,unsigned char * code,unsigned char * codelen)1031 const ix86_ExOpcodes* __FASTCALL__ ix86_prepare_flags(const ix86_ExOpcodes *extable,ix86Param *DisP,unsigned char *code,unsigned char* codelen)
1032 {
1033 int in_chain=1;
1034 while(in_chain)
1035 {
1036 if(x86_Bitness == DAB_USE64)
1037 {
1038 if(extable[*code].flags64&TAB_NAME_IS_TABLE)
1039 extable=(ix86_ExOpcodes*)(extable[*code].name64);
1040 else in_chain=0;
1041 }
1042 else
1043 if(extable[*code].pro_clone&TAB_NAME_IS_TABLE)
1044 extable=(ix86_ExOpcodes*)(extable[*code].name);
1045 else in_chain = 0;
1046
1047 if(in_chain) {
1048 DisP->RealCmd = &DisP->RealCmd[1];
1049 *code = DisP->RealCmd[0];
1050 (*codelen)++;
1051 }
1052 else {
1053 if(x86_Bitness == DAB_USE64) {
1054 DisP->pro_clone = extable[*code].flags64&(~INSN_FLAGS_MASK);
1055 DisP->insn_flags = extable[*code].flags64;
1056 }
1057 else {
1058 DisP->pro_clone = extable[*code].pro_clone&(~INSN_FLAGS_MASK);
1059 DisP->insn_flags = extable[*code].pro_clone;
1060 }
1061 in_chain=0;
1062 }
1063 }
1064 return extable;
1065 }
1066
1067 /** 0f xx opcodes */
1068
ix86_ExOpCodes(char * str,ix86Param * DisP)1069 void __FASTCALL__ ix86_ExOpCodes(char *str,ix86Param *DisP)
1070 {
1071 unsigned char code,up;
1072 const ix86_ExOpcodes *extable=ix86_extable;
1073 DisP->RealCmd = &DisP->RealCmd[1];
1074 DisP->CodeAddress++;
1075 code = DisP->RealCmd[0];
1076 up = 0;
1077 extable=ix86_prepare_flags(extable,DisP,&code,&up);
1078 if(x86_Bitness == DAB_USE64)
1079 strcpy(str,extable[code].name64?extable[code].name64:"???");
1080 else
1081 strcpy(str,extable[code].name?extable[code].name:"???");
1082 if(x86_Bitness == DAB_USE64)
1083 {
1084 if(extable[code].method64)
1085 {
1086 TabSpace(str,TAB_POS);
1087 extable[code].method64(str,DisP);
1088 }
1089 }
1090 else
1091 if(extable[code].method)
1092 {
1093 TabSpace(str,TAB_POS);
1094 extable[code].method(str,DisP);
1095 }
1096 if(x86_Bitness == DAB_USE64) DisP->pro_clone = extable[code].flags64&K64_CPUMASK;
1097 else
1098 if((DisP->pro_clone&IX86_CPUMASK) < (extable[code].pro_clone&IX86_CPUMASK))
1099 {
1100 DisP->pro_clone &= ~IX86_CPUMASK;
1101 DisP->pro_clone |= extable[code].pro_clone;
1102 }
1103 DisP->codelen+=up+1;
1104 }
1105
ix86_ArgExGr0(char * str,ix86Param * DisP)1106 void __FASTCALL__ ix86_ArgExGr0(char *str,ix86Param *DisP)
1107 {
1108 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1109 unsigned char reg = MODRM_RM(DisP->RealCmd[1]);
1110 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1111 strcpy(str,ix86_ExGrp0[cop]);
1112 TabSpace(str,TAB_POS);
1113 DisP->codelen++;
1114 ix86_setModifier(str,ix86_sizes[WORD_PTR]);
1115 strcat(str,ix86_getModRM(True,mod,reg,DisP));
1116 if((x86_Bitness != DAB_USE64) && (cop < 4)) DisP->pro_clone |= INSN_CPL0;
1117 }
1118
1119 static char *ix86_vmxname[]={"???","???","???","???","???","???","vmclear","???",};
ix86_VMX(char * str,ix86Param * DisP)1120 void __FASTCALL__ ix86_VMX(char *str,ix86Param *DisP)
1121 {
1122 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1123 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
1124 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1125 strcpy(str,ix86_vmxname[cop]);
1126 TabSpace(str,TAB_POS);
1127 DisP->codelen++;
1128 strcat(str,ix86_getModRM(True,mod,rm,DisP));
1129 DisP->pro_clone &= ~IX86_CPUMASK;
1130 DisP->pro_clone |= IX86_P6;
1131 }
1132
1133 static const char *ix86_0Fvmxname[]={"???","cmpxchg8b","???","???","???","???","vmptrld","vmptrst",};
ix86_0FVMX(char * str,ix86Param * DisP)1134 void __FASTCALL__ ix86_0FVMX(char *str,ix86Param *DisP)
1135 {
1136 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
1137 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1138 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1139 if(x86_Bitness == DAB_USE64 && REX_W(K64_REX) && cop==1)
1140 strcpy(str,"cmpxchg16b");
1141 else
1142 strcpy(str,ix86_0Fvmxname[cop]);
1143 TabSpace(str,TAB_POS);
1144 DisP->codelen++;
1145 strcat(str,ix86_getModRM(True,mod,rm,DisP));
1146 if(rm > 1) {
1147 DisP->pro_clone &= ~IX86_CPUMASK;
1148 DisP->pro_clone |= IX86_P6;
1149 }
1150 }
1151
1152 static const char *ix86_660Fvmxname[]={"???","???","???","???","???","???","vmclear","???",};
ix86_660FVMX(char * str,ix86Param * DisP)1153 void __FASTCALL__ ix86_660FVMX(char *str,ix86Param *DisP)
1154 {
1155 unsigned char rm = MODRM_RM(DisP->RealCmd[1]);
1156 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1157 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1158 strcpy(str,ix86_660Fvmxname[cop]);
1159 TabSpace(str,TAB_POS);
1160 DisP->codelen++;
1161 strcat(str,ix86_getModRM(True,mod,rm,DisP));
1162 if(rm > 1) {
1163 DisP->pro_clone &= ~IX86_CPUMASK;
1164 DisP->pro_clone |= IX86_P6;
1165 }
1166 }
1167
1168 static const char * ix86_ExGrp1[] = { "sgdt", "sidt", "lgdt", "lidt", "smsw", "???", "lmsw", "invlpg" };
ix86_ArgExGr1(char * str,ix86Param * DisP)1169 void __FASTCALL__ ix86_ArgExGr1(char *str,ix86Param *DisP)
1170 {
1171 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1172 unsigned char reg = MODRM_RM(DisP->RealCmd[1]);
1173 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1174 unsigned char buf,ptr;
1175 tBool word;
1176 if(x86_Bitness == DAB_USE64)
1177 {
1178 if(DisP->RealCmd[1] == 0xF8)
1179 {
1180 strcpy(str,"swapgs");
1181 DisP->codelen++;
1182 DisP->pro_clone |= INSN_CPL0;
1183 return;
1184 }
1185 }
1186 {
1187 if(DisP->RealCmd[1] == 0xC1)
1188 {
1189 strcpy(str,"vmcall");
1190 DisP->codelen++;
1191 DisP->pro_clone &= ~IX86_CPUMASK;
1192 DisP->pro_clone |= IX86_P6;
1193 return;
1194 }
1195 else
1196 if(DisP->RealCmd[1] == 0xC2)
1197 {
1198 strcpy(str,"vmlaunch");
1199 DisP->codelen++;
1200 DisP->pro_clone &= ~IX86_CPUMASK;
1201 DisP->pro_clone |= IX86_P6;
1202 return;
1203 }
1204 else
1205 if(DisP->RealCmd[1] == 0xC3)
1206 {
1207 strcpy(str,"vmresume");
1208 DisP->codelen++;
1209 DisP->pro_clone &= ~IX86_CPUMASK;
1210 DisP->pro_clone |= IX86_P6;
1211 return;
1212 }
1213 else
1214 if(DisP->RealCmd[1] == 0xC4)
1215 {
1216 strcpy(str,"vmxoff");
1217 DisP->codelen++;
1218 DisP->pro_clone &= ~IX86_CPUMASK;
1219 DisP->pro_clone |= IX86_P6;
1220 return;
1221 }
1222 else
1223 if(DisP->RealCmd[1] == 0xC8)
1224 {
1225 strcpy(str,"monitor");
1226 DisP->codelen++;
1227 DisP->pro_clone &= ~(IX86_CPUMASK|INSN_CPL0);
1228 DisP->pro_clone |= IX86_P5;
1229 return;
1230 }
1231 else
1232 if(DisP->RealCmd[1] == 0xC9)
1233 {
1234 strcpy(str,"mwait");
1235 DisP->codelen++;
1236 DisP->pro_clone &= ~(IX86_CPUMASK|INSN_CPL0);
1237 DisP->pro_clone |= IX86_P5;
1238 return;
1239 }
1240 else
1241 if(DisP->RealCmd[1] == 0xD0)
1242 {
1243 strcpy(str,"xgetbv");
1244 DisP->codelen++;
1245 DisP->pro_clone &= ~(IX86_CPUMASK|INSN_CPL0);
1246 DisP->pro_clone |= IX86_P8;
1247 return;
1248 }
1249 else
1250 if(DisP->RealCmd[1] == 0xD1)
1251 {
1252 strcpy(str,"xsetbv");
1253 DisP->codelen++;
1254 DisP->pro_clone &= ~(IX86_CPUMASK|INSN_CPL0);
1255 DisP->pro_clone |= IX86_P8;
1256 return;
1257 }
1258 else
1259 if(DisP->RealCmd[1] == 0xD8)
1260 {
1261 strcpy(str,"vmrun");
1262 DisP->codelen++;
1263 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1264 TabSpace(str,TAB_POS);
1265 strcat(str,k64_getREG(DisP,0,True,REX_B(K64_REX),REX_W(K64_REX)));
1266 return;
1267 }
1268 else
1269 if(DisP->RealCmd[1] == 0xD9)
1270 {
1271 strcpy(str,"vmmcall");
1272 DisP->codelen++;
1273 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1274 return;
1275 }
1276 else
1277 if(DisP->RealCmd[1] == 0xDA)
1278 {
1279 strcpy(str,"vmload");
1280 DisP->codelen++;
1281 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1282 TabSpace(str,TAB_POS);
1283 strcat(str,k64_getREG(DisP,0,True,REX_B(K64_REX),REX_W(K64_REX)));
1284 return;
1285 }
1286 else
1287 if(DisP->RealCmd[1] == 0xDB)
1288 {
1289 strcpy(str,"vmsave");
1290 DisP->codelen++;
1291 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1292 TabSpace(str,TAB_POS);
1293 strcat(str,k64_getREG(DisP,0,True,REX_B(K64_REX),REX_W(K64_REX)));
1294 return;
1295 }
1296 else
1297 if(DisP->RealCmd[1] == 0xDC)
1298 {
1299 strcpy(str,"stgi");
1300 DisP->codelen++;
1301 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1302 return;
1303 }
1304 else
1305 if(DisP->RealCmd[1] == 0xDD)
1306 {
1307 strcpy(str,"clgi");
1308 DisP->codelen++;
1309 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1310 return;
1311 }
1312 else
1313 if(DisP->RealCmd[1] == 0xDE)
1314 {
1315 strcpy(str,"skinit");
1316 DisP->codelen++;
1317 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1318 TabSpace(str,TAB_POS);
1319 strcat(str,"eax");
1320 return;
1321 }
1322 else
1323 if(DisP->RealCmd[1] == 0xDF)
1324 {
1325 strcpy(str,"invlpga");
1326 DisP->codelen++;
1327 DisP->pro_clone = K64_FAM10|INSN_CPL0;
1328 TabSpace(str,TAB_POS);
1329 strcat(str,k64_getREG(DisP,0,True,REX_B(K64_REX),REX_W(K64_REX)));
1330 ix86_CStile(DisP,str,"ecx");
1331 return;
1332 }
1333 }
1334 strcpy(str,ix86_ExGrp1[cop]);
1335 TabSpace(str,TAB_POS);
1336 DisP->codelen++;
1337 buf = DisP->RealCmd[1];
1338 ptr = PWORD_PTR;
1339 word = True;
1340 if(cop == 7)
1341 {
1342 word = False;
1343 if(x86_Bitness != DAB_USE64) DisP->pro_clone = IX86_CPU486;
1344 buf = 1;
1345 ptr = DUMMY_PTR;
1346 }
1347 else if(cop == 4 || cop == 6) ptr = WORD_PTR;
1348 ix86_setModifier(str,ix86_sizes[ptr]);
1349 strcat(str,ix86_getModRM(word ? True : buf & 0x01,mod,reg,DisP));
1350 }
1351
1352 static const char ** k64_xry[] = { k64_CrxRegs, k64_DrxRegs, k64_TrxRegs, k64_XrxRegs };
1353
ix86_ArgMovXRY(char * str,ix86Param * DisP)1354 void __FASTCALL__ ix86_ArgMovXRY(char *str,ix86Param *DisP)
1355 {
1356 unsigned char code = DisP->RealCmd[0];
1357 unsigned char xreg = MODRM_REG(DisP->RealCmd[1]);
1358 unsigned char reg = MODRM_RM(DisP->RealCmd[1]);
1359 unsigned char ridx = (code & 0x01) + ((code >> 1) & 0x02);
1360 unsigned char d = (code >> 1) & 0x01;
1361 unsigned long mode = DisP->mode;
1362 tBool brex,wrex;
1363 brex = REX_B(K64_REX);
1364 wrex = REX_W(K64_REX);
1365 if(x86_Bitness == DAB_USE64) wrex = 1;
1366 DisP->codelen++;
1367 DisP->mode|=MOD_WIDE_DATA;
1368 /* according on intel 30083401.pdf p# 1.4.3 to access cr8-tr15 is used REX.r */
1369 strcat(str,d ? k64_xry[ridx][xreg|(REX_R(K64_REX)<<3)] : k64_getREG(DisP,reg,True,brex,wrex));
1370 ix86_CStile(DisP,str,d ? k64_getREG(DisP,reg,True,brex,wrex) : k64_xry[ridx][xreg|(REX_R(K64_REX)<<3)]);
1371 DisP->mode=mode;
1372 }
1373
1374 /* MMX and SSE(2) opcodes */
1375
ix86_bridge_cpu_simd(char * str,ix86Param * DisP,tBool direct,tBool as_xmmx)1376 static void __NEAR__ __FASTCALL__ ix86_bridge_cpu_simd(char *str,ix86Param *DisP,tBool direct,tBool as_xmmx)
1377 {
1378 unsigned long mode=DisP->mode;
1379 if(as_xmmx) DisP->mode|=MOD_SSE;
1380 else DisP->mode|=MOD_MMX;
1381 if((DisP->RealCmd[1] & 0xC0) != 0xC0) {
1382 if(direct) DisP->mode=mode;
1383 arg_cpu_modregrm(str,DisP);
1384 }
1385 else
1386 {
1387 const char *mmx,*exx,*vxx=NULL;
1388 tBool brex,wrex;
1389 brex = direct?REX_B(K64_REX):REX_R(K64_REX);
1390 wrex = REX_W(K64_REX);
1391 if(brex && !as_xmmx) brex = 0; /* Note: there are only 8 mmx registers */
1392 mmx = k64_getREG(DisP,direct?MODRM_RM(DisP->RealCmd[1]):MODRM_REG(DisP->RealCmd[1]),True,brex,wrex);
1393 if(DisP->pfx&PFX_VEX) vxx = get_VEX_reg(DisP);
1394 else {
1395 if(as_xmmx) DisP->mode&=~MOD_SSE;
1396 else DisP->mode&=~MOD_MMX;
1397 }
1398 brex = direct?REX_R(K64_REX):REX_B(K64_REX);
1399 exx = k64_getREG(DisP,direct?MODRM_REG(DisP->RealCmd[1]):MODRM_RM(DisP->RealCmd[1]),True,brex,wrex);
1400 strcat(str,direct ? exx : mmx);
1401 if(vxx) ix86_CStile(DisP,str, vxx);
1402 ix86_CStile(DisP,str,direct ? mmx : exx);
1403 DisP->codelen++;
1404 }
1405 DisP->mode=mode;
1406 }
1407
bridge_simd_cpu(char * str,ix86Param * DisP)1408 void __FASTCALL__ bridge_simd_cpu(char *str,ix86Param* DisP)
1409 {
1410 ix86_bridge_cpu_simd(str,DisP,(DisP->insn_flags&BRIDGE_CPU_SSE)?True:False,(DisP->insn_flags&INSN_SSE)?True:False);
1411 }
1412
bridge_simd_cpu_imm8(char * str,ix86Param * DisP)1413 void __FASTCALL__ bridge_simd_cpu_imm8(char *str,ix86Param *DisP)
1414 {
1415 bridge_simd_cpu(str,DisP);
1416 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1417 arg_imm8(str,DisP);
1418 }
1419
ix86_bridge_sse_mmx(char * str,ix86Param * DisP,tBool xmmx_first)1420 static void __NEAR__ __FASTCALL__ ix86_bridge_sse_mmx(char *str,ix86Param *DisP,tBool xmmx_first)
1421 {
1422 unsigned long mode=DisP->mode;
1423 if(xmmx_first) DisP->mode|=MOD_SSE;
1424 else DisP->mode|=MOD_MMX;
1425 if((DisP->RealCmd[1] & 0xC0) != 0xC0)
1426 arg_cpu_modregrm(str,DisP);
1427 else
1428 {
1429 const char *mmx,*exx;
1430 tBool brex,wrex;
1431 brex = REX_R(K64_REX);
1432 wrex = REX_W(K64_REX);
1433 if(brex && !xmmx_first) brex = 0; /* Note: there are only 8 mmx registers */
1434 mmx = k64_getREG(DisP,MODRM_REG(DisP->RealCmd[1]),True,brex,wrex);
1435 if(xmmx_first)
1436 {
1437 DisP->mode&=~MOD_SSE;
1438 DisP->mode|=MOD_MMX;
1439 }
1440 else
1441 {
1442 DisP->mode|=MOD_SSE;
1443 DisP->mode&=~MOD_MMX;
1444 }
1445 brex = REX_B(K64_REX);
1446 exx = k64_getREG(DisP,MODRM_RM(DisP->RealCmd[1]),True,brex,wrex);
1447 strcat(str,mmx);
1448 ix86_CStile(DisP,str,exx);
1449 DisP->codelen++;
1450 }
1451 DisP->mode=mode;
1452 }
1453
bridge_sse_mmx(char * str,ix86Param * DisP)1454 void __FASTCALL__ bridge_sse_mmx(char *str,ix86Param* DisP)
1455 {
1456 ix86_bridge_sse_mmx(str,DisP,(DisP->insn_flags&BRIDGE_MMX_SSE)?False:True);
1457 }
1458
arg_emms(char * str,ix86Param * DisP)1459 void __FASTCALL__ arg_emms(char *str,ix86Param *DisP)
1460 {
1461 if(DisP->pfx&PFX_VEX) {
1462 if(DisP->VEX_vlp&0x04) strcpy(str,"vzeroall");
1463 else strcpy(str,"vzeroupper");
1464 }
1465 }
1466
arg_simd(char * str,ix86Param * DisP)1467 void __FASTCALL__ arg_simd(char *str,ix86Param *DisP)
1468 {
1469 unsigned long mode=DisP->mode;
1470 if(DisP->insn_flags&INSN_MMX) DisP->mode|=MOD_MMX;
1471 else DisP->mode|=MOD_SSE;
1472 arg_cpu_modregrm(str,DisP);
1473 DisP->mode=mode;
1474 }
1475
ix86_ArgxMMXGroup(char * str,const char * name,ix86Param * DisP,tBool as_xmmx)1476 static void __NEAR__ __FASTCALL__ ix86_ArgxMMXGroup(char *str,const char *name,ix86Param *DisP,tBool as_xmmx)
1477 {
1478 unsigned long mode=DisP->mode;
1479 tBool brex,wrex;
1480 brex = REX_B(K64_REX);
1481 wrex = REX_W(K64_REX);
1482 if(brex && !as_xmmx) brex = 0; /* Note: there are only 8 mmx registers */
1483 DisP->codelen++;
1484 strcpy(str,name);
1485 TabSpace(str,TAB_POS);
1486 if(as_xmmx) DisP->mode|=MOD_SSE;
1487 else DisP->mode|=MOD_MMX;
1488 strcat(str,k64_getREG(DisP,MODRM_RM(DisP->RealCmd[1]),True,brex,wrex));
1489 if(as_xmmx) DisP->mode&=~MOD_SSE;
1490 else DisP->mode&=~MOD_MMX;
1491 ix86_CStile(DisP,str,Get2Digit(DisP->RealCmd[2]));
1492 DisP->codelen++;
1493 DisP->mode=mode;
1494 }
1495
ix86_ArgMMXGr1(char * str,ix86Param * DisP)1496 void __FASTCALL__ ix86_ArgMMXGr1(char *str,ix86Param *DisP)
1497 {
1498 ix86_ArgxMMXGroup(str,ix86_MMXGr1[MODRM_COP(DisP->RealCmd[1])],DisP,False);
1499 }
1500
ix86_ArgMMXGr2(char * str,ix86Param * DisP)1501 void __FASTCALL__ ix86_ArgMMXGr2(char *str,ix86Param *DisP)
1502 {
1503 ix86_ArgxMMXGroup(str,ix86_MMXGr2[MODRM_COP(DisP->RealCmd[1])],DisP,False);
1504 }
1505
ix86_ArgMMXGr3(char * str,ix86Param * DisP)1506 void __FASTCALL__ ix86_ArgMMXGr3(char *str,ix86Param *DisP)
1507 {
1508 ix86_ArgxMMXGroup(str,ix86_MMXGr3[MODRM_COP(DisP->RealCmd[1])],DisP,False);
1509 }
1510
ix86_ArgXMMXGr1(char * str,ix86Param * DisP)1511 void __FASTCALL__ ix86_ArgXMMXGr1(char *str,ix86Param *DisP)
1512 {
1513 ix86_ArgxMMXGroup(str,ix86_XMMXGr1[MODRM_COP(DisP->RealCmd[1])],DisP,True);
1514 }
1515
ix86_ArgXMMXGr2(char * str,ix86Param * DisP)1516 void __FASTCALL__ ix86_ArgXMMXGr2(char *str,ix86Param *DisP)
1517 {
1518 ix86_ArgxMMXGroup(str,ix86_XMMXGr2[MODRM_COP(DisP->RealCmd[1])],DisP,True);
1519 }
1520
ix86_ArgXMMXGr3(char * str,ix86Param * DisP)1521 void __FASTCALL__ ix86_ArgXMMXGr3(char *str,ix86Param *DisP)
1522 {
1523 ix86_ArgxMMXGroup(str,ix86_XMMXGr3[MODRM_COP(DisP->RealCmd[1])],DisP,True);
1524 }
1525
ix86_ArgMovYX(char * str,ix86Param * DisP)1526 void __FASTCALL__ ix86_ArgMovYX(char *str,ix86Param *DisP)
1527 {
1528 const char *dst,*src;
1529 unsigned char mod;
1530 unsigned long mode=DisP->mode;
1531 tBool brex,wrex;
1532 brex = REX_R(K64_REX);
1533 wrex = REX_W(K64_REX);
1534 mod = MODRM_MOD(DisP->RealCmd[1]);
1535 /*ix86_setModifier(str,ix86_sizes[ix86_calcModifier(DisP,1)]);*/
1536 dst = k64_getREG(DisP,MODRM_REG(DisP->RealCmd[1]),True,brex,wrex);
1537 DisP->mode&=~MOD_WIDE_DATA;
1538 src = ix86_getModRM(DisP->RealCmd[0] & 0x01,mod,MODRM_RM(DisP->RealCmd[1]),DisP);
1539 DisP->mode=mode;
1540 strcat(str,dst);
1541 ix86_CStile(DisP,str,src);
1542 DisP->codelen++;
1543 }
1544
ix86_BitGrp(char * str,ix86Param * DisP)1545 void __FASTCALL__ ix86_BitGrp(char *str,ix86Param *DisP)
1546 {
1547 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1548 char mod = MODRM_MOD(DisP->RealCmd[1]);
1549 char rm = MODRM_RM(DisP->RealCmd[1]);
1550 strcpy(str,ix86_BitGrpNames[cop]);
1551 TabSpace(str,TAB_POS);
1552 strcat(str,ix86_getModRM(True,mod,rm,DisP));
1553 ix86_CStile(DisP,str,ix86_GetDigitTile(DisP,0,0,++DisP->codelen));
1554 }
1555
1556 static const char *ix86_KatmaiGr1Names[] = { "fxsave", "fxrstor", "ldmxcsr", "stmxcsr", "xsave", "xrstor", "???", "???" };
1557 static const char *ix86_KatmaiGr1Names11[] = { "???", "???", "???", "???", "???", "lfence", "mfence", "sfence" };
ix86_ArgKatmaiGrp1(char * str,ix86Param * DisP)1558 void __FASTCALL__ ix86_ArgKatmaiGrp1(char *str,ix86Param *DisP)
1559 {
1560 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1561 unsigned char mod = MODRM_MOD(DisP->RealCmd[1]);
1562 if(mod==3) strcpy(str,ix86_KatmaiGr1Names11[cop]);
1563 else strcpy(str,ix86_KatmaiGr1Names[cop]);
1564 if(mod < 3)
1565 {
1566 TabSpace(str,TAB_POS);
1567 arg_cpu_mod_rm(str,DisP);
1568 if(x86_Bitness != DAB_USE64) {
1569 DisP->pro_clone &= ~IX86_CPUMASK;
1570 DisP->pro_clone |= IX86_P8|INSN_SSE;
1571 }
1572 else {
1573 DisP->pro_clone &= ~K64_CPUMASK;
1574 DisP->pro_clone |= K64_FAM11|INSN_SSE;
1575 }
1576 }
1577 else DisP->codelen++;
1578 if((cop==5 || cop==6) && mod==3)
1579 if(x86_Bitness != DAB_USE64) {
1580 DisP->pro_clone &= ~IX86_CPUMASK;
1581 DisP->pro_clone |= IX86_P4|INSN_MMX;
1582 }
1583 }
1584
ix86_ArgKatmaiGrp2(char * str,ix86Param * DisP)1585 void __FASTCALL__ ix86_ArgKatmaiGrp2(char *str,ix86Param *DisP)
1586 {
1587 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1588 strcpy(str,ix86_KatmaiGr2Names[cop]);
1589 TabSpace(str,TAB_POS);
1590 arg_cpu_mod_rm(str,DisP);
1591 }
1592
arg_simd_imm8(char * str,ix86Param * DisP)1593 void __FASTCALL__ arg_simd_imm8(char *str,ix86Param *DisP)
1594 {
1595 arg_simd(str,DisP);
1596 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1597 arg_imm8(str,DisP);
1598 }
1599
arg_simd_regrm(char * str,ix86Param * DisP)1600 void __FASTCALL__ arg_simd_regrm(char *str,ix86Param *DisP)
1601 {
1602 tBool brex,wrex;
1603 unsigned long mode=DisP->mode;
1604 DisP->codelen++;
1605 brex = REX_B(K64_REX);
1606 wrex = REX_W(K64_REX);
1607 DisP->mode|=MOD_SSE;
1608 strcat(str,k64_getREG(DisP,MODRM_REG(DisP->RealCmd[1]),True,brex,wrex));
1609 ix86_CStile(DisP,str,k64_getREG(DisP,MODRM_RM(DisP->RealCmd[1]),True,brex,wrex));
1610 DisP->mode=mode;
1611 }
1612
arg_simd_regrm_imm8_imm8(char * str,ix86Param * DisP)1613 void __FASTCALL__ arg_simd_regrm_imm8_imm8(char *str,ix86Param *DisP)
1614 {
1615 arg_simd_regrm(str,DisP);
1616 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1617 arg_imm8(str,DisP);
1618 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1619 arg_imm8(str,DisP);
1620 }
1621
arg_simd_rm_imm8_imm8(char * str,ix86Param * DisP)1622 void __FASTCALL__ arg_simd_rm_imm8_imm8(char *str,ix86Param *DisP)
1623 {
1624 tBool brex,wrex;
1625 unsigned long mode=DisP->mode;
1626 brex = REX_B(K64_REX);
1627 wrex = REX_W(K64_REX);
1628 DisP->mode|=MOD_SSE;
1629 strcat(str,k64_getREG(DisP,MODRM_RM(DisP->RealCmd[1]),True,brex,wrex));
1630 DisP->mode=mode;
1631 DisP->codelen++;
1632
1633 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1634 arg_imm8(str,DisP);
1635 if(!((DisP->flags & __DISF_SIZEONLY) == __DISF_SIZEONLY)) strcat(str,",");
1636 arg_imm8(str,DisP);
1637 }
1638
ix86_ArgXMMCmp(char * str,ix86Param * DisP,const char ** sfx,unsigned nsfx,unsigned namlen,unsigned precopy)1639 static void __FASTCALL__ ix86_ArgXMMCmp(char *str,ix86Param *DisP,const char **sfx,unsigned nsfx,unsigned namlen,unsigned precopy)
1640 {
1641 char *a;
1642 unsigned char suffix;
1643 char name[6], realname[10];
1644 unsigned long mode=DisP->mode;
1645 DisP->mode|=MOD_SSE;
1646 ix86_Katmai_buff[0] = 0;
1647 arg_cpu_modregrm(ix86_Katmai_buff,DisP);
1648 suffix = DisP->RealCmd[DisP->codelen];
1649 a = NULL;
1650 if(suffix < nsfx)
1651 {
1652 strncpy(name, str, namlen);
1653 name[namlen] = 0;
1654 strncpy(realname,name,precopy);
1655 realname[precopy] = 0;
1656 strcat(realname,sfx[suffix]);
1657 strcat(realname, &name[precopy]);
1658 strcpy(str, realname);
1659 TabSpace(str, TAB_POS);
1660 }
1661 else {
1662 a = Get2Digit(suffix);
1663 }
1664 strcat(str,ix86_Katmai_buff);
1665 if(a) ix86_CStile(DisP,str,a);
1666 DisP->mode = mode;
1667 DisP->codelen++;
1668 }
1669
1670 static const char *ix86_KatmaiCmpSuffixes[] = { "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord" };
1671 static const char *vex_cmp_sfx[] = {
1672 "eq", "lt", "le", "unord", "neq", "nlt", "nle", "ord", "eq_uq", "nge", "ngt", "false", "neq_oq", "ge", "gt",
1673 "true", "eq_os", "lt_oq", "le_oq", "unord_s", "neq_us", "nlt_uq", "nle_uq", "ord_s", "eq_us" };
arg_simd_cmp(char * str,ix86Param * DisP)1674 void __FASTCALL__ arg_simd_cmp(char *str,ix86Param *DisP)
1675 {
1676 /*Note: this code suppose that name is cmpXY*/
1677 return (str[0]=='v' && (DisP->pfx&PFX_VEX))?
1678 ix86_ArgXMMCmp(str,DisP,vex_cmp_sfx,0x19,6,4):
1679 ix86_ArgXMMCmp(str,DisP,ix86_KatmaiCmpSuffixes,8,5,3);
1680 }
1681
1682
1683 static const char *xop_cmp_sfx[] = { "lt", "le", "gt", "ge", "eq", "ne", "false", "true" };
arg_xop_cmp(char * str,ix86Param * DisP)1684 void __FASTCALL__ arg_xop_cmp(char *str,ix86Param *DisP)
1685 {
1686 /*Note: this code suppose that name is vpcomXY?? */
1687 return ix86_ArgXMMCmp(str,DisP,xop_cmp_sfx,8,7,5);
1688 }
1689
1690 static const char *ix86_clmul_sfx[] = { "lqlq", "hqlq", "lqh", "hqh" };
arg_simd_clmul(char * str,ix86Param * DisP)1691 void __FASTCALL__ arg_simd_clmul(char *str,ix86Param *DisP)
1692 {
1693 char *a;
1694 unsigned char suffix;
1695 char name[6], realname[10];
1696 unsigned long mode=DisP->mode;
1697 unsigned namlen,precopy;
1698 DisP->mode|=MOD_SSE;
1699 ix86_Katmai_buff[0] = 0;
1700 arg_cpu_modregrm(ix86_Katmai_buff,DisP);
1701 suffix = DisP->RealCmd[DisP->codelen];
1702 suffix = (suffix&0x0F)|((suffix&0xF0)>>3);
1703 namlen=8;
1704 precopy=6;
1705 if(str[0]=='v' && (DisP->pfx&PFX_VEX)) { namlen++; precopy++; }
1706 a = NULL;
1707 if(suffix < 4)
1708 {
1709 strncpy(name, str, namlen);
1710 name[namlen] = 0;
1711 strncpy(realname,name,precopy);
1712 realname[precopy] = 0;
1713 strcat(realname,ix86_clmul_sfx[suffix]);
1714 strcat(realname, &name[precopy]);
1715 strcpy(str, realname);
1716 TabSpace(str, TAB_POS);
1717 }
1718 else {
1719 a = Get2Digit(suffix);
1720 }
1721 strcat(str,ix86_Katmai_buff);
1722 if(a) ix86_CStile(DisP,str,a);
1723 DisP->mode = mode;
1724 DisP->codelen++;
1725 }
1726
arg_simd_xmm0(char * str,ix86Param * DisP)1727 void __FASTCALL__ arg_simd_xmm0(char *str,ix86Param *DisP) {
1728 arg_simd(str,DisP);
1729 ix86_CStile(DisP,str,"xmm0");
1730 }
1731
1732 /* TODO: fix it !!! */
arg_fma4(char * str,ix86Param * DisP)1733 void __FASTCALL__ arg_fma4(char *str,ix86Param *DisP) {
1734 unsigned wrex;
1735 unsigned long mod = DisP->mode;
1736 unsigned char d;
1737 DisP->mode |= MOD_SSE;
1738 d = 0;
1739 if(DisP->insn_flags&INSN_VEXW_AS_SWAP && DisP->pfx&PFX_VEX) d = REX_W(K64_REX)^0x01;
1740 wrex=0;
1741 strcat(str,__buildModRegRmReg(DisP,d,wrex));
1742 DisP->mode = mod;
1743 }
1744
arg_fma4_imm8(char * str,ix86Param * DisP)1745 void __FASTCALL__ arg_fma4_imm8(char *str,ix86Param *DisP) {
1746 unsigned is4;
1747 arg_fma4(str,DisP);
1748 is4=DisP->RealCmd[DisP->codelen-1];
1749 ix86_CStile(DisP,str,Get2Digit(is4&0x0F));
1750 }
1751
arg_fma(char * str,ix86Param * DisP)1752 void __FASTCALL__ arg_fma(char *str,ix86Param *DisP)
1753 {
1754 unsigned long mode=DisP->mode;
1755 if(DisP->insn_flags&INSN_MMX) DisP->mode|=MOD_MMX;
1756 else DisP->mode|=MOD_SSE;
1757 if(DisP->pfx&PFX_VEX) {
1758 char *ptr;
1759 char vex_w = REX_W(DisP->REX)^1; /* complement it back */
1760 if(!vex_w) {
1761 ptr=strstr(str,"pd ");
1762 if(!ptr) ptr=strstr(str,"sd ");
1763 if(ptr) ptr[1] = 's';
1764 }
1765 }
1766 arg_cpu_modregrm(str,DisP);
1767 DisP->mode=mode;
1768 }
1769
ix86_3dNowOpCodes(char * str,ix86Param * DisP)1770 void __FASTCALL__ ix86_3dNowOpCodes( char *str,ix86Param *DisP)
1771 {
1772 unsigned char code;
1773 unsigned long mode=DisP->mode;
1774 DisP->mode|=MOD_MMX;
1775 ix86_Katmai_buff[0] = 0;
1776 arg_cpu_modregrm(ix86_Katmai_buff,DisP);
1777 DisP->mode=mode;
1778 code = DisP->RealCmd[DisP->codelen];
1779 DisP->codelen++;
1780 strcpy(str,ix86_3dNowtable[code].name);
1781 TabSpace(str,TAB_POS);
1782 strcat(str,ix86_Katmai_buff);
1783 if(x86_Bitness == DAB_USE64) DisP->pro_clone = K64_ATHLON|INSN_MMX;
1784 else DisP->pro_clone = ix86_3dNowtable[code].pro_clone;
1785 }
1786
ix86_3dNowPrefetchGrp(char * str,ix86Param * DisP)1787 void __FASTCALL__ ix86_3dNowPrefetchGrp(char *str,ix86Param *DisP)
1788 {
1789 unsigned char cop = MODRM_COP(DisP->RealCmd[1]);
1790 strcpy(str,ix86_3dPrefetchGrp[cop]);
1791 TabSpace(str,TAB_POS);
1792 arg_cpu_mod_rm(str,DisP);
1793 }
1794
1795