blob: e956eeeff82c2372cbb827f1f63cb5aad87a3041 [file] [log] [blame]
sewardjc9a65702004-07-07 16:32:57 +00001
2/*--------------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (x86toIR.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*--------------------------------------------------------------------*/
8
9/* Translates x86 code to IR. */
10
11#include "libvex_basictypes.h"
12#include "libvex_ir.h"
13#include "vex_util.h"
14#include "vex_globals.h"
15#include "x86guest_defs.h"
16
17
18/*------------------------------------------------------------*/
19/*--- Globals ---*/
20/*------------------------------------------------------------*/
21
22/* These are set at the start of the translation of a BB, so
23 that we don't have to pass them around endlessly. */
24
25/* We need to know this to do sub-register accesses correctly. */
26/* CONST */
27static Bool host_is_bigendian;
28
29/* Are we being verbose? */
30/* CONST */
31static Bool print_codegen;
32
33/* Pointer to the guest code area. */
34/* CONST */
35static UChar* guest_code;
36
37/* The guest address corresponding to guest_code[0]. */
38/* CONST */
39static Addr32 guest_eip;
40
41/* The BBIR* into which we're generating code. */
42/* What it points to changes as we work through the bb. */
43static IRBB* irbb;
44
45/* Points to the last stmt added to the statement list of irbb, so
46 that when a new stmt is added, the .link field can be correctly
47 updated. */
48static IRStmt* last_stmt;
49
50/* Used to generate new IRTemps. */
51static IRTemp next_irtemp;
52
53
54/* Add a statement to the list held by "irbb". */
sewardjd1061ab2004-07-08 01:45:30 +000055static void stmt ( IRStmt* stmt )
sewardjc9a65702004-07-07 16:32:57 +000056{
57 stmt->link = NULL;
58 if (irbb->stmts == NULL) {
59 irbb->stmts = stmt;
60 } else {
61 last_stmt->link = stmt;
62 }
63 last_stmt = stmt;
64}
65
66/* Generate a new temporary of the given type. */
67static IRTemp newTemp ( IRType ty )
68{
69 addToIRTypeEnv ( irbb->tyenv, next_irtemp, ty );
70 return next_irtemp++;
71}
72
sewardjc9a65702004-07-07 16:32:57 +000073/* Bomb out if we can't handle something. */
sewardjd1061ab2004-07-08 01:45:30 +000074__attribute__ ((noreturn))
sewardjc9a65702004-07-07 16:32:57 +000075static void unimplemented ( Char* str )
76{
77 vex_printf("x86toIR: unimplemented feature\n");
78 vpanic(str);
79}
80
81
82/*------------------------------------------------------------*/
83/*--- Debugging output ---*/
84/*------------------------------------------------------------*/
85
86#define DIP(format, args...) \
87 if (print_codegen) \
88 vex_printf(format, ## args)
89
90#define DIS(buf, format, args...) \
91 if (print_codegen) \
92 vex_sprintf(buf, format, ## args)
93
94
95/*------------------------------------------------------------*/
96/*--- Helper bits and pieces for deconstructing the ---*/
97/*--- x86 insn stream. ---*/
98/*------------------------------------------------------------*/
99
sewardjd1061ab2004-07-08 01:45:30 +0000100/* This is the Intel register encoding -- integer regs. */
101#define R_EAX 0
102#define R_ECX 1
103#define R_EDX 2
104#define R_EBX 3
105#define R_ESP 4
106#define R_EBP 5
107#define R_ESI 6
108#define R_EDI 7
109
110
111static __inline__ UInt extend_s_8to32( UInt x )
112{
113 return (UInt)((((Int)x) << 24) >> 24);
114}
115
116/* Fetch a byte from the guest insn stream. */
117static __inline__ UChar getIByte ( UInt delta )
118{
119 return guest_code[delta];
120}
121
sewardjc9a65702004-07-07 16:32:57 +0000122/* Extract the reg field from a modRM byte. */
123static __inline__ Int gregOfRM ( UChar mod_reg_rm )
124{
125 return (Int)( (mod_reg_rm >> 3) & 7 );
126}
127
128/* Figure out whether the mod and rm parts of a modRM byte refer to a
129 register or memory. If so, the byte will have the form 11XXXYYY,
130 where YYY is the register number. */
131static __inline__ Bool epartIsReg ( UChar mod_reg_rm )
132{
133 return (0xC0 == (mod_reg_rm & 0xC0));
134}
135
136/* ... and extract the register number ... */
137static __inline__ Int eregOfRM ( UChar mod_reg_rm )
138{
139 return (Int)(mod_reg_rm & 0x7);
140}
141
sewardjd1061ab2004-07-08 01:45:30 +0000142/* Get a 32-bit value out of the insn stream. */
143static __inline__ UInt getUDisp32 ( UInt delta )
144{
145 UInt v = guest_code[delta+3]; v <<= 8;
146 v |= guest_code[delta+2]; v <<= 8;
147 v |= guest_code[delta+1]; v <<= 8;
148 v |= guest_code[delta+0];
149 return v;
150}
151
152/* Get a byte value out of the insn stream and sign-extend to 32
153 bits. */
154__inline__ static UInt getSDisp8 ( UInt delta )
155{
156 return extend_s_8to32( (UInt) (guest_code[delta]) );
157}
158
159
sewardjc9a65702004-07-07 16:32:57 +0000160
161/*------------------------------------------------------------*/
162/*--- Helpers for constructing IR. ---*/
163/*------------------------------------------------------------*/
164
165/* Create a 1/2/4 byte read of an x86 integer registers. For 16/8 bit
166 register references, we need to take the host endianness into
167 account. Supplied value is 0 .. 7 and in the Intel instruction
168 encoding. */
sewardjd1061ab2004-07-08 01:45:30 +0000169static IRExpr* getIReg ( Int sz, UInt archreg )
sewardjc9a65702004-07-07 16:32:57 +0000170{
171 vassert(sz == 1 || sz == 2 || sz == 4);
172 vassert(archreg < 8);
173
174 vassert(!host_is_bigendian);
175 vassert(sz == 4);
sewardjd1061ab2004-07-08 01:45:30 +0000176 return IRExpr_Get(OFFB_EAX + 4*archreg, Ity_I32);
sewardjc9a65702004-07-07 16:32:57 +0000177}
178
179/* Ditto, but write to a reg instead. */
sewardjd1061ab2004-07-08 01:45:30 +0000180static IRStmt* putIReg ( Int sz, UInt archreg, IRExpr* e )
sewardjc9a65702004-07-07 16:32:57 +0000181{
182 vassert(sz == 1 || sz == 2 || sz == 4);
183 vassert(archreg < 8);
184
185 vassert(!host_is_bigendian);
186 vassert(sz == 4);
sewardjd1061ab2004-07-08 01:45:30 +0000187 return IRStmt_Put(OFFB_EAX + 4*archreg, e);
188}
189
190static IRStmt* assign ( IRTemp dst, IRExpr* e )
191{
192 return IRStmt_Tmp(dst, e);
193}
194
195static IRStmt* storeLE ( IRExpr* addr, IRExpr* data )
196{
197 return IRStmt_STle(addr,data);
198}
199
200static IRStmt* copyToFrom ( IRTemp dst, IRTemp src )
201{
202 return IRStmt_Tmp(dst, IRExpr_Tmp(src));
203}
204
205static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
206{
207 return IRExpr_Binop(op, a1, a2);
208}
209
210static IRExpr* mkexpr ( IRTemp tmp )
211{
212 return IRExpr_Tmp(tmp);
213}
214
215static IRExpr* mkU32 ( UInt i )
216{
217 return IRExpr_Const(IRConst_U32(i));
sewardjc9a65702004-07-07 16:32:57 +0000218}
219
220
221//-- /*------------------------------------------------------------*/
222//-- /*--- CPU feature set stuff ---*/
223//-- /*--- This is a little out of place here, but it will do ---*/
224//-- /*--- for now. ---*/
225//-- /*------------------------------------------------------------*/
226//--
227//-- #define VG_CPU_VENDOR_GENERIC 0
228//-- #define VG_CPU_VENDOR_INTEL 1
229//-- #define VG_CPU_VENDOR_AMD 2
230//--
231//-- static Int cpu_vendor = VG_CPU_VENDOR_GENERIC;
232//--
233//-- static const struct cpu_vendor {
234//-- const Char *vendorstr;
235//-- Int vendorid;
236//-- } cpu_vendors[] = {
237//-- { "GenuineIntel", VG_CPU_VENDOR_INTEL },
238//-- { "AuthenticAMD", VG_CPU_VENDOR_AMD },
239//-- };
240//--
241//-- static Int cpuid_level = -2; /* -2 -> not initialized */
242//-- static UInt cpu_features[VG_N_FEATURE_WORDS];
243//--
244//-- /* Standard macro to see if a specific flag is changeable */
245//-- static inline Bool flag_is_changeable(UInt flag)
246//-- {
247//-- UInt f1, f2;
248//--
249//-- asm("pushfl\n\t"
250//-- "pushfl\n\t"
251//-- "popl %0\n\t"
252//-- "movl %0,%1\n\t"
253//-- "xorl %2,%0\n\t"
254//-- "pushl %0\n\t"
255//-- "popfl\n\t"
256//-- "pushfl\n\t"
257//-- "popl %0\n\t"
258//-- "popfl\n\t"
259//-- : "=&r" (f1), "=&r" (f2)
260//-- : "ir" (flag));
261//--
262//-- return ((f1^f2) & flag) != 0;
263//-- }
264//--
265//--
266//-- /* Probe for the CPUID instruction */
267//-- static Bool has_cpuid(void)
268//-- {
269//-- return flag_is_changeable(EFlagID);
270//-- }
271//--
272//-- static void get_cpu_features(void)
273//-- {
274//-- Char vendorstr[13];
275//-- Int i;
276//--
277//-- if (!has_cpuid()) {
278//-- cpuid_level = -1;
279//-- return;
280//-- }
281//--
282//-- cpu_features[VG_INT_FEAT] |= (1 << (VG_X86_FEAT_CPUID%32));
283//--
284//-- VG_(cpuid)(0, &cpuid_level, (UInt *)&vendorstr[0], (UInt *)&vendorstr[8], (UInt *)&vendorstr[4]);
285//-- vendorstr[12] = '\0';
286//--
287//-- for(i = 0; i < sizeof(cpu_vendors)/sizeof(*cpu_vendors); i++)
288//-- if (VG_(memcmp)(vendorstr, cpu_vendors[i].vendorstr, 12) == 0) {
289//-- cpu_vendor = cpu_vendors[i].vendorid;
290//-- break;
291//-- }
292//--
293//-- if (cpuid_level >= 1)
294//-- VG_(cpuid)(1, NULL, NULL, &cpu_features[VG_EXT_FEAT], &cpu_features[VG_X86_FEAT]);
295//--
296//-- switch(cpu_vendor) {
297//-- case VG_CPU_VENDOR_AMD:
298//-- /* get AMD-specific flags */
299//-- VG_(cpuid)(0x80000001, NULL, NULL, NULL, &cpu_features[VG_AMD_FEAT]);
300//-- break;
301//--
302//-- default:
303//-- break;
304//-- }
305//-- }
306//--
307//-- Bool VG_(cpu_has_feature)(UInt feature)
308//-- {
309//-- UInt word = feature / 32;
310//-- UInt bit = feature % 32;
311//--
312//-- if (cpuid_level == -2)
313//-- get_cpu_features();
314//--
315//-- vg_assert(word >= 0 && word < VG_N_FEATURE_WORDS);
316//--
317//-- return !!(cpu_features[word] & (1 << bit));
318//-- }
319//--
320//-- /* The set of features we're willing to support for the client
321//--
322//-- This includes supported instruction set extensions, plus any
323//-- extensions which don't have any user-mode visible effect (but the
324//-- client may find interesting).
325//-- */
sewardjd1061ab2004-07-08 01:45:30 +0000326#define VG_X86_SUPPORTED_FEATURES \
327 ((1 << VG_X86_FEAT_FPU) | \
328 (1 << VG_X86_FEAT_VME) | \
329 (1 << VG_X86_FEAT_DE) | \
330 (1 << VG_X86_FEAT_PSE) | \
331 (1 << VG_X86_FEAT_TSC) | \
332 (0 << VG_X86_FEAT_MSR) | \
333 (1 << VG_X86_FEAT_PAE) | \
334 (1 << VG_X86_FEAT_MCE) | \
335 (1 << VG_X86_FEAT_CX8) | \
336 (1 << VG_X86_FEAT_APIC) | \
337 (0 << VG_X86_FEAT_SEP) | \
338 (1 << VG_X86_FEAT_MTRR) | \
339 (1 << VG_X86_FEAT_PGE) | \
340 (1 << VG_X86_FEAT_MCA) | \
341 (1 << VG_X86_FEAT_CMOV) | \
342 (1 << VG_X86_FEAT_PAT) | \
343 (1 << VG_X86_FEAT_PSE36) | \
344 (0 << VG_X86_FEAT_CLFSH) | \
345 (1 << VG_X86_FEAT_DS) | \
346 (1 << VG_X86_FEAT_ACPI) | \
347 (1 << VG_X86_FEAT_MMX) | \
348 (1 << VG_X86_FEAT_FXSR) | \
349 (1 << VG_X86_FEAT_SSE) | \
350 (1 << VG_X86_FEAT_SSE2) | \
351 (1 << VG_X86_FEAT_SS) | \
352 (1 << VG_X86_FEAT_HT) | \
353 (1 << VG_X86_FEAT_TM) | \
354 (0 << VG_X86_FEAT_IA64) | \
355 (1 << VG_X86_FEAT_PBE))
356
357#define VG_AMD_SUPPORTED_FEATURES \
358 ((0 << (VG_AMD_FEAT_SYSCALL % 32)) | \
359 (0 << (VG_AMD_FEAT_NXP % 32)) | \
360 (1 << (VG_AMD_FEAT_MMXEXT % 32)) | \
361 (0 << (VG_AMD_FEAT_FFXSR % 32)) | \
362 (0 << (VG_AMD_FEAT_LONGMODE % 32)) | \
363 (0 << (VG_AMD_FEAT_3DNOWEXT % 32)) | \
364 (0 << (VG_AMD_FEAT_3DNOW % 32)) | \
365 /* Common bits between standard features and AMD features */ \
366 (1 << VG_X86_FEAT_FPU) | \
367 (1 << VG_X86_FEAT_VME) | \
368 (1 << VG_X86_FEAT_DE) | \
369 (1 << VG_X86_FEAT_PSE) | \
370 (1 << VG_X86_FEAT_TSC) | \
371 (0 << VG_X86_FEAT_MSR) | \
372 (1 << VG_X86_FEAT_PAE) | \
373 (1 << VG_X86_FEAT_MCE) | \
374 (1 << VG_X86_FEAT_CX8) | \
375 (1 << VG_X86_FEAT_APIC) | \
376 (1 << VG_X86_FEAT_MTRR) | \
377 (1 << VG_X86_FEAT_PGE) | \
378 (1 << VG_X86_FEAT_MCA) | \
379 (1 << VG_X86_FEAT_CMOV) | \
380 (1 << VG_X86_FEAT_PAT) | \
381 (1 << VG_X86_FEAT_PSE36) | \
382 (1 << VG_X86_FEAT_MMX) | \
383 (1 << VG_X86_FEAT_FXSR))
384
385
sewardjc9a65702004-07-07 16:32:57 +0000386//-- /*
387//-- For simulating the cpuid instruction, we will
388//-- issue a "real" cpuid instruction and then mask out
389//-- the bits of the features we do not support currently (3dnow mostly).
390//-- We also claim to not support most CPUID operations.
391//--
392//-- Dirk Mueller <mueller@kde.org>
393//--
394//-- http://www.sandpile.org/ia32/cpuid.htm
395//--
396//-- references:
397//--
398//-- pre-MMX pentium:
399//--
400//-- <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
401//-- <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
402//--
403//-- Updated to be more extensible about future vendor extensions and
404//-- vendor-specific parts of CPUID.
405//-- */
406//-- void VG_(helperc_CPUID)(UInt op, UInt *eax_ret, UInt *ebx_ret, UInt *ecx_ret, UInt *edx_ret)
407//-- {
408//-- UInt eax, ebx, ecx, edx;
409//--
410//-- if (cpuid_level == -2)
411//-- get_cpu_features(); /* for cpu_vendor */
412//--
413//-- VG_(cpuid)(op, &eax, &ebx, &ecx, &edx);
414//--
415//-- /* Common mangling */
416//-- switch(op) {
417//-- case 1:
418//-- edx &= VG_X86_SUPPORTED_FEATURES;
419//-- break;
420//--
421//-- case 0xd8000000: {
422//-- /* Implement some private information at 0xd8000000 */
423//-- static const Char valgrind_vendor[] = "ValgrindVCPU";
424//--
425//-- eax = 0xd8000000; /* max request */
426//-- ebx = *(UInt *)&valgrind_vendor[0];
427//-- ecx = *(UInt *)&valgrind_vendor[8];
428//-- edx = *(UInt *)&valgrind_vendor[4];
429//-- }
430//-- break;
431//-- }
432//--
433//-- /* Vendor-specific mangling of the results */
434//-- switch(cpu_vendor) {
435//-- case VG_CPU_VENDOR_INTEL:
436//-- switch(op) {
437//-- case 1:
438//-- ecx = 0; /* mask out all extended features for now */
439//-- break;
440//--
441//-- case 0x80000001:
442//-- ebx = ecx = edx = 0;
443//-- break;
444//-- }
445//-- break;
446//--
447//-- case VG_CPU_VENDOR_AMD:
448//-- switch(op) {
449//-- case 0x80000001:
450//-- edx &= VG_AMD_SUPPORTED_FEATURES;
451//-- break;
452//-- }
453//-- break;
454//-- }
455//--
456//-- *eax_ret = eax;
457//-- *ebx_ret = ebx;
458//-- *ecx_ret = ecx;
459//-- *edx_ret = edx;
460//-- }
461//--
462//--
463//-- /*------------------------------------------------------------*/
464//-- /*--- Here so it can be inlined everywhere. ---*/
465//-- /*------------------------------------------------------------*/
466//--
467//-- /* Allocate a new temp reg number. */
468//-- __inline__ Int VG_(get_new_temp) ( UCodeBlock* cb )
469//-- {
470//-- Int t = cb->nextTemp;
471//-- cb->nextTemp += 2;
472//-- return t;
473//-- }
474//--
475//-- Int VG_(get_new_shadow) ( UCodeBlock* cb )
476//-- {
477//-- Int t = cb->nextTemp;
478//-- cb->nextTemp += 2;
479//-- return SHADOW(t);
480//-- }
481
482
483//--
484//-- static Char* nameGrp1 ( Int opc_aux )
485//-- {
486//-- static Char* grp1_names[8]
487//-- = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
488//-- if (opc_aux < 0 || opc_aux > 7) VG_(core_panic)("nameGrp1");
489//-- return grp1_names[opc_aux];
490//-- }
491//--
492//-- static Char* nameGrp2 ( Int opc_aux )
493//-- {
494//-- static Char* grp2_names[8]
495//-- = { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" };
496//-- if (opc_aux < 0 || opc_aux > 7) VG_(core_panic)("nameGrp2");
497//-- return grp2_names[opc_aux];
498//-- }
499//--
500//-- static Char* nameGrp4 ( Int opc_aux )
501//-- {
502//-- static Char* grp4_names[8]
503//-- = { "inc", "dec", "???", "???", "???", "???", "???", "???" };
504//-- if (opc_aux < 0 || opc_aux > 1) VG_(core_panic)("nameGrp4");
505//-- return grp4_names[opc_aux];
506//-- }
507//--
508//-- static Char* nameGrp5 ( Int opc_aux )
509//-- {
510//-- static Char* grp5_names[8]
511//-- = { "inc", "dec", "call*", "call*", "jmp*", "jmp*", "push", "???" };
512//-- if (opc_aux < 0 || opc_aux > 6) VG_(core_panic)("nameGrp5");
513//-- return grp5_names[opc_aux];
514//-- }
515//--
516//-- static Char* nameGrp8 ( Int opc_aux )
517//-- {
518//-- static Char* grp8_names[8]
519//-- = { "???", "???", "???", "???", "bt", "bts", "btr", "btc" };
520//-- if (opc_aux < 4 || opc_aux > 7) VG_(core_panic)("nameGrp8");
521//-- return grp8_names[opc_aux];
522//-- }
523
524static
525const Char* nameIReg ( Int size, Int reg )
526{
527 static Char* ireg32_names[8]
528 = { "%eax", "%ecx", "%edx", "%ebx",
529 "%esp", "%ebp", "%esi", "%edi" };
530 static Char* ireg16_names[8]
531 = { "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di" };
532 static Char* ireg8_names[8]
533 = { "%al", "%cl", "%dl", "%bl",
534 "%ah{sp}", "%ch{bp}", "%dh{si}", "%bh{di}" };
535 if (reg < 0 || reg > 7) goto bad;
536 switch (size) {
537 case 4: return ireg32_names[reg];
538 case 2: return ireg16_names[reg];
539 case 1: return ireg8_names[reg];
540 }
541 bad:
542 vpanic("nameIReg(X86)");
543 return NULL; /*notreached*/
544}
545
546//-- const Char* VG_(name_of_seg_reg) ( Int sreg )
547//-- {
548//-- switch (sreg) {
549//-- case R_ES: return "%es";
550//-- case R_CS: return "%cs";
551//-- case R_SS: return "%ss";
552//-- case R_DS: return "%ds";
553//-- case R_FS: return "%fs";
554//-- case R_GS: return "%gs";
555//-- default: VG_(core_panic)("nameOfSegReg");
556//-- }
557//-- }
558//--
559//-- const Char* VG_(name_of_mmx_reg) ( Int mmxreg )
560//-- {
561//-- static const Char* mmx_names[8]
562//-- = { "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" };
563//-- if (mmxreg < 0 || mmxreg > 7) VG_(core_panic)("name_of_mmx_reg");
564//-- return mmx_names[mmxreg];
565//-- }
566//--
567//-- const Char* VG_(name_of_xmm_reg) ( Int xmmreg )
568//-- {
569//-- static const Char* xmm_names[8]
570//-- = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
571//-- if (xmmreg < 0 || xmmreg > 7) VG_(core_panic)("name_of_xmm_reg");
572//-- return xmm_names[xmmreg];
573//-- }
574//--
575//-- const Char* VG_(name_of_mmx_gran) ( UChar gran )
576//-- {
577//-- switch (gran) {
578//-- case 0: return "b";
579//-- case 1: return "w";
580//-- case 2: return "d";
581//-- case 3: return "q";
582//-- default: VG_(core_panic)("name_of_mmx_gran");
583//-- }
584//-- }
585
586static
587const Char nameISize ( Int size )
588{
589 switch (size) {
590 case 4: return 'l';
591 case 2: return 'w';
592 case 1: return 'b';
593 default: vpanic("nameISize(x86)");
594 }
595}
596
sewardjc9a65702004-07-07 16:32:57 +0000597//-- __inline__ static UInt extend_s_16to32 ( UInt x )
598//-- {
599//-- return (UInt)((((Int)x) << 16) >> 16);
600//-- }
601//--
602//--
sewardjc9a65702004-07-07 16:32:57 +0000603//-- __inline__ static UInt getSDisp16 ( Addr eip0 )
604//-- {
605//-- UChar* eip = (UChar*)eip0;
606//-- UInt d = *eip++;
607//-- d |= ((*eip++) << 8);
608//-- return extend_s_16to32(d);
609//-- }
sewardjc9a65702004-07-07 16:32:57 +0000610//-- __inline__ static UInt getUDisp16 ( Addr eip0 )
611//-- {
612//-- UChar* eip = (UChar*)eip0;
613//-- UInt v = eip[1]; v <<= 8;
614//-- v |= eip[0];
615//-- return v;
616//-- }
617//--
618//-- __inline__ static UChar getUChar ( Addr eip0 )
619//-- {
620//-- UChar* eip = (UChar*)eip0;
621//-- return eip[0];
622//-- }
623//--
624//-- __inline__ static UInt LOW24 ( UInt x )
625//-- {
626//-- return x & 0x00FFFFFF;
627//-- }
628//--
629//-- __inline__ static UInt HI8 ( UInt x )
630//-- {
631//-- return x >> 24;
632//-- }
633//--
634//-- __inline__ static UInt getUDisp ( Int size, Addr eip )
635//-- {
636//-- switch (size) {
637//-- case 4: return getUDisp32(eip);
638//-- case 2: return getUDisp16(eip);
639//-- case 1: return getUChar(eip);
640//-- default: VG_(core_panic)("getUDisp");
641//-- }
642//-- return 0; /*notreached*/
643//-- }
644//--
645//-- __inline__ static UInt getSDisp ( Int size, Addr eip )
646//-- {
647//-- switch (size) {
648//-- case 4: return getUDisp32(eip);
649//-- case 2: return getSDisp16(eip);
650//-- case 1: return getSDisp8(eip);
651//-- default: VG_(core_panic)("getUDisp");
652//-- }
653//-- return 0; /*notreached*/
654//-- }
655//--
656//-- /*------------------------------------------------------------*/
657//-- /*--- Flag-related helpers. ---*/
658//-- /*------------------------------------------------------------*/
659//--
660//-- static void setFlagsFromUOpcode ( UCodeBlock* cb, Int uopc )
661//-- {
662//-- switch (uopc) {
663//-- case XOR: case OR: case AND:
664//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZCP, FlagA); break;
665//-- case ADC: case SBB:
666//-- uFlagsRWU(cb, FlagC, FlagsOSZACP, FlagsEmpty); break;
667//-- case MUL: case UMUL:
668//-- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP); break;
669//-- case ADD: case SUB: case NEG:
670//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty); break;
671//-- case INC: case DEC:
672//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZAP, FlagsEmpty); break;
673//-- case SHR: case SAR: case SHL:
674//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZCP, FlagA); break;
675//-- case ROL: case ROR:
676//-- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsEmpty); break;
677//-- case RCR: case RCL:
678//-- uFlagsRWU(cb, FlagC, FlagsOC, FlagsEmpty); break;
679//-- case NOT:
680//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty); break;
681//-- default:
682//-- VG_(printf)("unhandled case is %s\n",
683//-- VG_(name_UOpcode)(True, uopc));
684//-- VG_(core_panic)("setFlagsFromUOpcode: unhandled case");
685//-- }
686//-- }
sewardjd1061ab2004-07-08 01:45:30 +0000687
688/*------------------------------------------------------------*/
689/*--- JMP helpers ---*/
690/*------------------------------------------------------------*/
691
692static __inline__
693void jmp_lit( Addr32 d32 )
694{
695 irbb->next = IRNext_UJump( IRConst_U32(d32) );
696}
697
sewardjc9a65702004-07-07 16:32:57 +0000698//-- static __inline__
699//-- void jmp_treg( UCodeBlock* cb, Int t )
700//-- {
701//-- uInstr1 (cb, JMP, 0, TempReg, t);
702//-- uCond (cb, CondAlways);
703//-- }
704//--
705//-- static __inline__
706//-- void jcc_lit( UCodeBlock* cb, Addr d32, Condcode cond )
707//-- {
708//-- uInstr1 (cb, JMP, 0, Literal, 0);
709//-- uLiteral (cb, d32);
710//-- uCond (cb, cond);
711//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
712//-- }
sewardjc9a65702004-07-07 16:32:57 +0000713
714
sewardjd1061ab2004-07-08 01:45:30 +0000715/*------------------------------------------------------------*/
716/*--- Disassembling addressing modes ---*/
717/*------------------------------------------------------------*/
sewardjc9a65702004-07-07 16:32:57 +0000718
sewardjd1061ab2004-07-08 01:45:30 +0000719static
720UChar* sorbTxt ( UChar sorb )
721{
722 switch (sorb) {
723 case 0: return ""; /* no override */
724 case 0x3E: return "%ds";
725 case 0x26: return "%es:";
726 case 0x64: return "%fs:";
727 case 0x65: return "%gs:";
728 default: vpanic("sorbTxt(x86)");
729 }
730}
731
732
733/* Tmp is a TempReg holding a virtual address. Convert it to a linear
734 address by adding any required segment override as indicated by
735 sorb. */
736static
737IRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual )
738{
739 //Int sreg, tsreg;
740
741 if (sorb == 0)
742 /* the common case - no override */
743 return virtual;
744
745 unimplemented("segment overrides in new x86->IR phase");
746#if 0
747 switch (sorb) {
748 case 0x3E: sreg = R_DS; break;
749 case 0x26: sreg = R_ES; break;
750 case 0x64: sreg = R_FS; break;
751 case 0x65: sreg = R_GS; break;
752 default: VG_(core_panic)("handleSegOverride");
753 }
754
755 tsreg = newTemp(cb);
756
757 /* sreg -> tsreg */
758 uInstr2(cb, GETSEG, 2, ArchRegS, sreg, TempReg, tsreg );
759
760 /* tmp += segment_base(ldt[tsreg]); also do limit check */
761 uInstr2(cb, USESEG, 0, TempReg, tsreg, TempReg, tmp );
762#endif
763}
764
765
766/* Generate IR to calculate an address indicated by a ModRM and
767 following SIB bytes. The expression, and the number of bytes in
768 the address mode, are returned. Note that this fn should not be
769 called if the R/M part of the address denotes a register instead of
770 memory. If print_codegen is true, text of the addressing mode is
771 placed in buf. */
772
773static
774IRExpr* disAMode ( Int* len, UChar sorb, UInt delta, UChar* buf )
775{
776 UChar mod_reg_rm = getIByte(delta);
777 delta++;
778
779 /* squeeze out the reg field from mod_reg_rm, since a 256-entry
780 jump table seems a bit excessive.
781 */
782 mod_reg_rm &= 0xC7; /* is now XX000YYY */
783 mod_reg_rm |= (mod_reg_rm >> 3); /* is now XX0XXYYY */
784 mod_reg_rm &= 0x1F; /* is now 000XXYYY */
785 switch (mod_reg_rm) {
786
787 /* (%eax) .. (%edi), not including (%esp) or (%ebp).
788 --> GET %reg, t
789 */
790 case 0x00: case 0x01: case 0x02: case 0x03:
791 /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
792 { UChar rm = mod_reg_rm;
793 DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm));
794 *len = 1;
795 return handleSegOverride(sorb, getIReg(4,rm));
796 }
797
798 /* d8(%eax) ... d8(%edi), not including d8(%esp)
799 --> GET %reg, t ; ADDL d8, t
800 */
801 case 0x08: case 0x09: case 0x0A: case 0x0B:
802 /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
803 { UChar rm = mod_reg_rm & 7;
804 UInt d = getSDisp8(delta);
805 DIS(buf, "%s%d(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
806 *len = 2;
807 return handleSegOverride(sorb,
808 binop(Iop_Add32,getIReg(4,rm),mkU32(d)));
809 }
810
811 /* d32(%eax) ... d32(%edi), not including d32(%esp)
812 --> GET %reg, t ; ADDL d8, t
813 */
814 case 0x10: case 0x11: case 0x12: case 0x13:
815 /* ! 14 */ case 0x15: case 0x16: case 0x17:
816 { UChar rm = mod_reg_rm & 7;
817 UInt d = getUDisp32(delta);
818 DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
819 *len = 5;
820 return handleSegOverride(sorb,
821 binop(Iop_Add32,getIReg(4,rm),mkU32(d)));
822 }
823
824 /* a register, %eax .. %edi. This shouldn't happen. */
825 case 0x18: case 0x19: case 0x1A: case 0x1B:
826 case 0x1C: case 0x1D: case 0x1E: case 0x1F:
827 vpanic("disAMode(x86): not an addr!");
828
829 /* a 32-bit literal address
830 --> MOV d32, tmp
831 */
832 case 0x05:
833 { UInt d = getUDisp32(delta);
834 *len = 5;
835 DIS(buf, "%s(0x%x)", sorbTxt(sorb), d);
836 return handleSegOverride(sorb, mkU32(d));
837 }
838
839 case 0x04: {
840 /* SIB, with no displacement. Special cases:
841 -- %esp cannot act as an index value.
842 If index_r indicates %esp, zero is used for the index.
843 -- when mod is zero and base indicates EBP, base is instead
844 a 32-bit literal.
845 It's all madness, I tell you. Extract %index, %base and
846 scale from the SIB byte. The value denoted is then:
847 | %index == %ESP && %base == %EBP
848 = d32 following SIB byte
849 | %index == %ESP && %base != %EBP
850 = %base
851 | %index != %ESP && %base == %EBP
852 = d32 following SIB byte + (%index << scale)
853 | %index != %ESP && %base != %ESP
854 = %base + (%index << scale)
855
856 What happens to the souls of CPU architects who dream up such
857 horrendous schemes, do you suppose?
858 */
859 UChar sib = getIByte(delta);
860 UChar scale = (sib >> 6) & 3;
861 UChar index_r = (sib >> 3) & 7;
862 UChar base_r = sib & 7;
863 delta++;
864
865 if (index_r != R_ESP && base_r != R_EBP) {
866 DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb),
867 nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
868 *len = 2;
869 return
870 handleSegOverride(sorb,
871 binop(Iop_Add32,
872 getIReg(4,base_r),
873 binop(Iop_Shl32, getIReg(4,index_r),
874 mkU32(scale))));
875 }
876
877 if (index_r != R_ESP && base_r == R_EBP) {
878 UInt d = getUDisp32(delta);
879 DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d,
880 nameIReg(4,index_r), 1<<scale);
881 *len = 6;
882 return
883 handleSegOverride(sorb,
884 binop(Iop_Add32,
885 binop(Iop_Shl32, getIReg(4,index_r), mkU32(scale)),
886 mkU32(d)));
887 }
888
889 if (index_r == R_ESP && base_r != R_EBP) {
890 DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
891 *len = 2;
892 return handleSegOverride(sorb, getIReg(4,base_r));
893 }
894
895 if (index_r == R_ESP && base_r == R_EBP) {
896 UInt d = getUDisp32(delta);
897 DIS(buf, "%s0x%x()", sorbTxt(sorb), d);
898 *len = 6;
899 return handleSegOverride(sorb, mkU32(d));
900 }
901
902 vassert(0);
903 }
904
905 /* SIB, with 8-bit displacement. Special cases:
906 -- %esp cannot act as an index value.
907 If index_r indicates %esp, zero is used for the index.
908 Denoted value is:
909 | %index == %ESP
910 = d8 + %base
911 | %index != %ESP
912 = d8 + %base + (%index << scale)
913 */
914 case 0x0C: {
915 UChar sib = getIByte(delta);
916 UChar scale = (sib >> 6) & 3;
917 UChar index_r = (sib >> 3) & 7;
918 UChar base_r = sib & 7;
919 UInt d = getSDisp8(delta+1);
920
921 if (index_r == R_ESP) {
922 DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
923 *len = 3;
924 return handleSegOverride(sorb,
925 binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) );
926 } else {
927 DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d,
928 nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
929 *len = 3;
930 return handleSegOverride(sorb,
931 binop(Iop_Add32,
932 binop(Iop_Add32,
933 getIReg(4,base_r),
934 binop(Iop_Shl32, getIReg(4,index_r), mkU32(scale))),
935 mkU32(d)));
936 }
937 vassert(0);
938 }
939
940 /* SIB, with 32-bit displacement. Special cases:
941 -- %esp cannot act as an index value.
942 If index_r indicates %esp, zero is used for the index.
943 Denoted value is:
944 | %index == %ESP
945 = d32 + %base
946 | %index != %ESP
947 = d32 + %base + (%index << scale)
948 */
949 case 0x14: {
950 UChar sib = getIByte(delta);
951 UChar scale = (sib >> 6) & 3;
952 UChar index_r = (sib >> 3) & 7;
953 UChar base_r = sib & 7;
954 UInt d = getUDisp32(delta+1);
955
956 if (index_r == R_ESP) {
957 DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
958 *len = 6;
959 return handleSegOverride(sorb,
960 binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) );
961 } else {
962 DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d,
963 nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
964 *len = 6;
965 return handleSegOverride(sorb,
966 binop(Iop_Add32,
967 binop(Iop_Add32,
968 getIReg(4,base_r),
969 binop(Iop_Shl32, getIReg(4,index_r), mkU32(scale))),
970 mkU32(d)));
971 }
972 vassert(0);
973 }
974
975 default:
976 vpanic("disAMode(x86)");
977 return 0; /*notreached*/
978 }
979}
980
981
982/* Figure out the number of (insn-stream) bytes constituting the amode
983 beginning at delta. Is useful for getting hold of literals beyond
984 the end of the amode before it has been disassembled. */
985
986static UInt lengthAMode ( UInt delta )
987{
988 UChar mod_reg_rm = getIByte(delta); delta++;
989
990 /* squeeze out the reg field from mod_reg_rm, since a 256-entry
991 jump table seems a bit excessive.
992 */
993 mod_reg_rm &= 0xC7; /* is now XX000YYY */
994 mod_reg_rm |= (mod_reg_rm >> 3); /* is now XX0XXYYY */
995 mod_reg_rm &= 0x1F; /* is now 000XXYYY */
996 switch (mod_reg_rm) {
997
998 /* (%eax) .. (%edi), not including (%esp) or (%ebp). */
999 case 0x00: case 0x01: case 0x02: case 0x03:
1000 /* ! 04 */ /* ! 05 */ case 0x06: case 0x07:
1001 return 1;
1002
1003 /* d8(%eax) ... d8(%edi), not including d8(%esp). */
1004 case 0x08: case 0x09: case 0x0A: case 0x0B:
1005 /* ! 0C */ case 0x0D: case 0x0E: case 0x0F:
1006 return 2;
1007
1008 /* d32(%eax) ... d32(%edi), not including d32(%esp). */
1009 case 0x10: case 0x11: case 0x12: case 0x13:
1010 /* ! 14 */ case 0x15: case 0x16: case 0x17:
1011 return 5;
1012
1013 /* a register, %eax .. %edi. (Not an addr, but still handled.) */
1014 case 0x18: case 0x19: case 0x1A: case 0x1B:
1015 case 0x1C: case 0x1D: case 0x1E: case 0x1F:
1016 return 1;
1017
1018 /* a 32-bit literal address. */
1019 case 0x05: return 5;
1020
1021 /* SIB, no displacement. */
1022 case 0x04: {
1023 UChar sib = getIByte(delta);
1024 UChar base_r = sib & 7;
1025 if (base_r == R_EBP) return 6; else return 2;
1026 }
1027 /* SIB, with 8-bit displacement. */
1028 case 0x0C: return 3;
1029
1030 /* SIB, with 32-bit displacement. */
1031 case 0x14: return 6;
1032
1033 default:
1034 vpanic("lengthAMode");
1035 return 0; /*notreached*/
1036 }
1037}
1038
1039/*------------------------------------------------------------*/
1040/*--- Disassembling common idioms ---*/
1041/*------------------------------------------------------------*/
1042
sewardjc9a65702004-07-07 16:32:57 +00001043//-- static
1044//-- void codegen_XOR_reg_with_itself ( UCodeBlock* cb, Int size,
1045//-- Int ge_reg, Int tmp )
1046//-- {
1047//-- DIP("xor%c %s, %s\n", nameISize(size),
1048//-- nameIReg(size,ge_reg), nameIReg(size,ge_reg) );
1049//-- uInstr2(cb, MOV, size, Literal, 0, TempReg, tmp);
1050//-- uLiteral(cb, 0);
1051//-- uInstr2(cb, XOR, size, TempReg, tmp, TempReg, tmp);
1052//-- setFlagsFromUOpcode(cb, XOR);
1053//-- uInstr2(cb, PUT, size, TempReg, tmp, ArchReg, ge_reg);
1054//-- }
1055//--
1056//-- /* Handle binary integer instructions of the form
1057//-- op E, G meaning
1058//-- op reg-or-mem, reg
1059//-- Is passed the a ptr to the modRM byte, the actual operation, and the
1060//-- data size. Returns the address advanced completely over this
1061//-- instruction.
1062//--
1063//-- E(src) is reg-or-mem
1064//-- G(dst) is reg.
1065//--
1066//-- If E is reg, --> GET %G, tmp
1067//-- OP %E, tmp
1068//-- PUT tmp, %G
1069//--
1070//-- If E is mem and OP is not reversible,
1071//-- --> (getAddr E) -> tmpa
1072//-- LD (tmpa), tmpa
1073//-- GET %G, tmp2
1074//-- OP tmpa, tmp2
1075//-- PUT tmp2, %G
1076//--
1077//-- If E is mem and OP is reversible
1078//-- --> (getAddr E) -> tmpa
1079//-- LD (tmpa), tmpa
1080//-- OP %G, tmpa
1081//-- PUT tmpa, %G
1082//-- */
1083//-- static
1084//-- Addr dis_op2_E_G ( UCodeBlock* cb,
1085//-- UChar sorb,
1086//-- Opcode opc,
1087//-- Bool keep,
1088//-- Int size,
1089//-- Addr eip0,
1090//-- Char* t_x86opc )
1091//-- {
1092//-- Bool reversible;
1093//-- UChar rm = getUChar(eip0);
1094//-- UChar dis_buf[50];
1095//--
1096//-- if (epartIsReg(rm)) {
1097//-- Int tmp = newTemp(cb);
1098//--
1099//-- /* Specially handle XOR reg,reg, because that doesn't really
1100//-- depend on reg, and doing the obvious thing potentially
1101//-- generates a spurious value check failure due to the bogus
1102//-- dependency. */
1103//-- if (opc == XOR && gregOfRM(rm) == eregOfRM(rm)) {
1104//-- codegen_XOR_reg_with_itself ( cb, size, gregOfRM(rm), tmp );
1105//-- return 1+eip0;
1106//-- }
1107//--
1108//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tmp);
1109//-- if (opc == AND || opc == OR) {
1110//-- Int tao = newTemp(cb);
1111//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, tao);
1112//-- uInstr2(cb, opc, size, TempReg, tao, TempReg, tmp);
1113//-- setFlagsFromUOpcode(cb, opc);
1114//-- } else {
1115//-- uInstr2(cb, opc, size, ArchReg, eregOfRM(rm), TempReg, tmp);
1116//-- setFlagsFromUOpcode(cb, opc);
1117//-- }
1118//-- if (keep)
1119//-- uInstr2(cb, PUT, size, TempReg, tmp, ArchReg, gregOfRM(rm));
1120//-- DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
1121//-- nameIReg(size,eregOfRM(rm)),
1122//-- nameIReg(size,gregOfRM(rm)));
1123//-- return 1+eip0;
1124//-- }
1125//--
1126//-- /* E refers to memory */
1127//-- reversible
1128//-- = (opc == ADD || opc == OR || opc == AND || opc == XOR || opc == ADC)
1129//-- ? True : False;
1130//-- if (reversible) {
1131//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf);
1132//-- Int tmpa = LOW24(pair);
1133//-- uInstr2(cb, LOAD, size, TempReg, tmpa, TempReg, tmpa);
1134//--
1135//-- if (opc == AND || opc == OR) {
1136//-- Int tao = newTemp(cb);
1137//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tao);
1138//-- uInstr2(cb, opc, size, TempReg, tao, TempReg, tmpa);
1139//-- setFlagsFromUOpcode(cb, opc);
1140//-- } else {
1141//-- uInstr2(cb, opc, size, ArchReg, gregOfRM(rm), TempReg, tmpa);
1142//-- setFlagsFromUOpcode(cb, opc);
1143//-- }
1144//-- if (keep)
1145//-- uInstr2(cb, PUT, size, TempReg, tmpa, ArchReg, gregOfRM(rm));
1146//-- DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
1147//-- dis_buf,nameIReg(size,gregOfRM(rm)));
1148//-- return HI8(pair)+eip0;
1149//-- } else {
1150//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf);
1151//-- Int tmpa = LOW24(pair);
1152//-- Int tmp2 = newTemp(cb);
1153//-- uInstr2(cb, LOAD, size, TempReg, tmpa, TempReg, tmpa);
1154//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tmp2);
1155//-- uInstr2(cb, opc, size, TempReg, tmpa, TempReg, tmp2);
1156//-- setFlagsFromUOpcode(cb, opc);
1157//-- if (keep)
1158//-- uInstr2(cb, PUT, size, TempReg, tmp2, ArchReg, gregOfRM(rm));
1159//-- DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
1160//-- dis_buf,nameIReg(size,gregOfRM(rm)));
1161//-- return HI8(pair)+eip0;
1162//-- }
1163//-- }
1164//--
1165//--
1166//--
1167//-- /* Handle binary integer instructions of the form
1168//-- op G, E meaning
1169//-- op reg, reg-or-mem
1170//-- Is passed the a ptr to the modRM byte, the actual operation, and the
1171//-- data size. Returns the address advanced completely over this
1172//-- instruction.
1173//--
1174//-- G(src) is reg.
1175//-- E(dst) is reg-or-mem
1176//--
1177//-- If E is reg, --> GET %E, tmp
1178//-- OP %G, tmp
1179//-- PUT tmp, %E
1180//--
1181//-- If E is mem, --> (getAddr E) -> tmpa
1182//-- LD (tmpa), tmpv
1183//-- OP %G, tmpv
1184//-- ST tmpv, (tmpa)
1185//-- */
1186//-- static
1187//-- Addr dis_op2_G_E ( UCodeBlock* cb,
1188//-- UChar sorb,
1189//-- Opcode opc,
1190//-- Bool keep,
1191//-- Int size,
1192//-- Addr eip0,
1193//-- Char* t_x86opc )
1194//-- {
1195//-- UChar rm = getUChar(eip0);
1196//-- UChar dis_buf[50];
1197//--
1198//-- if (epartIsReg(rm)) {
1199//-- Int tmp = newTemp(cb);
1200//--
1201//-- /* Specially handle XOR reg,reg, because that doesn't really
1202//-- depend on reg, and doing the obvious thing potentially
1203//-- generates a spurious value check failure due to the bogus
1204//-- dependency. */
1205//-- if (opc == XOR && gregOfRM(rm) == eregOfRM(rm)) {
1206//-- codegen_XOR_reg_with_itself ( cb, size, gregOfRM(rm), tmp );
1207//-- return 1+eip0;
1208//-- }
1209//--
1210//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, tmp);
1211//--
1212//-- if (opc == AND || opc == OR) {
1213//-- Int tao = newTemp(cb);
1214//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tao);
1215//-- uInstr2(cb, opc, size, TempReg, tao, TempReg, tmp);
1216//-- setFlagsFromUOpcode(cb, opc);
1217//-- } else {
1218//-- uInstr2(cb, opc, size, ArchReg, gregOfRM(rm), TempReg, tmp);
1219//-- setFlagsFromUOpcode(cb, opc);
1220//-- }
1221//-- if (keep)
1222//-- uInstr2(cb, PUT, size, TempReg, tmp, ArchReg, eregOfRM(rm));
1223//-- DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
1224//-- nameIReg(size,gregOfRM(rm)),
1225//-- nameIReg(size,eregOfRM(rm)));
1226//-- return 1+eip0;
1227//-- }
1228//--
1229//-- /* E refers to memory */
1230//-- {
1231//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf);
1232//-- Int tmpa = LOW24(pair);
1233//-- Int tmpv = newTemp(cb);
1234//-- uInstr2(cb, LOAD, size, TempReg, tmpa, TempReg, tmpv);
1235//--
1236//-- if (opc == AND || opc == OR) {
1237//-- Int tao = newTemp(cb);
1238//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tao);
1239//-- uInstr2(cb, opc, size, TempReg, tao, TempReg, tmpv);
1240//-- setFlagsFromUOpcode(cb, opc);
1241//-- } else {
1242//-- uInstr2(cb, opc, size, ArchReg, gregOfRM(rm), TempReg, tmpv);
1243//-- setFlagsFromUOpcode(cb, opc);
1244//-- }
1245//-- if (keep) {
1246//-- uInstr2(cb, STORE, size, TempReg, tmpv, TempReg, tmpa);
1247//-- }
1248//-- DIP("%s%c %s,%s\n", t_x86opc, nameISize(size),
1249//-- nameIReg(size,gregOfRM(rm)), dis_buf);
1250//-- return HI8(pair)+eip0;
1251//-- }
1252//-- }
1253//--
1254//--
1255//-- /* Handle move instructions of the form
1256//-- mov E, G meaning
1257//-- mov reg-or-mem, reg
1258//-- Is passed the a ptr to the modRM byte, and the data size. Returns
1259//-- the address advanced completely over this instruction.
1260//--
1261//-- E(src) is reg-or-mem
1262//-- G(dst) is reg.
1263//--
1264//-- If E is reg, --> GET %E, tmpv
1265//-- PUT tmpv, %G
1266//--
1267//-- If E is mem --> (getAddr E) -> tmpa
1268//-- LD (tmpa), tmpb
1269//-- PUT tmpb, %G
1270//-- */
1271//-- static
1272//-- Addr dis_mov_E_G ( UCodeBlock* cb,
1273//-- UChar sorb,
1274//-- Int size,
1275//-- Addr eip0 )
1276//-- {
1277//-- UChar rm = getUChar(eip0);
1278//-- UChar dis_buf[50];
1279//--
1280//-- if (epartIsReg(rm)) {
1281//-- Int tmpv = newTemp(cb);
1282//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, tmpv);
1283//-- uInstr2(cb, PUT, size, TempReg, tmpv, ArchReg, gregOfRM(rm));
1284//-- DIP("mov%c %s,%s\n", nameISize(size),
1285//-- nameIReg(size,eregOfRM(rm)),
1286//-- nameIReg(size,gregOfRM(rm)));
1287//-- return 1+eip0;
1288//-- }
1289//--
1290//-- /* E refers to memory */
1291//-- {
1292//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf);
1293//-- Int tmpa = LOW24(pair);
1294//-- Int tmpb = newTemp(cb);
1295//-- uInstr2(cb, LOAD, size, TempReg, tmpa, TempReg, tmpb);
1296//-- uInstr2(cb, PUT, size, TempReg, tmpb, ArchReg, gregOfRM(rm));
1297//-- DIP("mov%c %s,%s\n", nameISize(size),
1298//-- dis_buf,nameIReg(size,gregOfRM(rm)));
1299//-- return HI8(pair)+eip0;
1300//-- }
1301//-- }
1302//--
1303//--
1304//-- /* Handle move instructions of the form
1305//-- mov G, E meaning
1306//-- mov reg, reg-or-mem
1307//-- Is passed the a ptr to the modRM byte, and the data size. Returns
1308//-- the address advanced completely over this instruction.
1309//--
1310//-- G(src) is reg.
1311//-- E(dst) is reg-or-mem
1312//--
1313//-- If E is reg, --> GET %G, tmp
1314//-- PUT tmp, %E
1315//--
1316//-- If E is mem, --> (getAddr E) -> tmpa
1317//-- GET %G, tmpv
1318//-- ST tmpv, (tmpa)
1319//-- */
1320static
1321UInt dis_mov_G_E ( UChar sorb,
1322 Int size,
1323 UInt delta0 )
1324{
1325 UChar rm = getIByte(delta0);
sewardjd1061ab2004-07-08 01:45:30 +00001326 // UChar dis_buf[50];
sewardjc9a65702004-07-07 16:32:57 +00001327
1328 if (epartIsReg(rm)) {
sewardjd1061ab2004-07-08 01:45:30 +00001329 stmt( putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm))) );
sewardjc9a65702004-07-07 16:32:57 +00001330 DIP("mov%c %s,%s\n", nameISize(size),
1331 nameIReg(size,gregOfRM(rm)),
1332 nameIReg(size,eregOfRM(rm)));
1333 return 1+delta0;
1334 }
1335
sewardjd1061ab2004-07-08 01:45:30 +00001336 vassert(0 ==0+0); return 0;
sewardjc9a65702004-07-07 16:32:57 +00001337#if 0
1338 /* E refers to memory */
1339 {
1340 UInt pair = disAMode ( cb, sorb, eip0, dis_buf);
1341 Int tmpa = LOW24(pair);
1342 Int tmpv = newTemp(cb);
1343 uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tmpv);
1344 uInstr2(cb, STORE, size, TempReg, tmpv, TempReg, tmpa);
1345 DIP("mov%c %s,%s\n", nameISize(size),
1346 nameIReg(size,gregOfRM(rm)), dis_buf);
1347 return HI8(pair)+eip0;
1348 }
1349#endif
1350}
1351
1352
1353//-- /* op $immediate, AL/AX/EAX. */
1354//-- static
1355//-- Addr dis_op_imm_A ( UCodeBlock* cb,
1356//-- Int size,
1357//-- Opcode opc,
1358//-- Bool keep,
1359//-- Addr eip,
1360//-- Char* t_x86opc )
1361//-- {
1362//-- Int tmp = newTemp(cb);
1363//-- UInt lit = getUDisp(size,eip);
1364//-- uInstr2(cb, GET, size, ArchReg, R_EAX, TempReg, tmp);
1365//-- if (opc == AND || opc == OR) {
1366//-- Int tao = newTemp(cb);
1367//-- uInstr2(cb, MOV, size, Literal, 0, TempReg, tao);
1368//-- uLiteral(cb, lit);
1369//-- uInstr2(cb, opc, size, TempReg, tao, TempReg, tmp);
1370//-- setFlagsFromUOpcode(cb, opc);
1371//-- } else {
1372//-- uInstr2(cb, opc, size, Literal, 0, TempReg, tmp);
1373//-- uLiteral(cb, lit);
1374//-- setFlagsFromUOpcode(cb, opc);
1375//-- }
1376//-- if (keep)
1377//-- uInstr2(cb, PUT, size, TempReg, tmp, ArchReg, R_EAX);
1378//-- DIP("%s%c $0x%x, %s\n", t_x86opc, nameISize(size),
1379//-- lit, nameIReg(size,R_EAX));
1380//-- return eip+size;
1381//-- }
1382//--
1383//--
1384//-- /* Sign- and Zero-extending moves. */
1385//-- static
1386//-- Addr dis_movx_E_G ( UCodeBlock* cb,
1387//-- UChar sorb,
1388//-- Addr eip, Int szs, Int szd, Bool sign_extend )
1389//-- {
1390//-- UChar dis_buf[50];
1391//-- UChar rm = getIByte(delta);
1392//-- if (epartIsReg(rm)) {
1393//-- Int tmpv = newTemp(cb);
1394//-- uInstr2(cb, GET, szs, ArchReg, eregOfRM(rm), TempReg, tmpv);
1395//-- uInstr1(cb, WIDEN, szd, TempReg, tmpv);
1396//-- uWiden(cb, szs, sign_extend);
1397//-- uInstr2(cb, PUT, szd, TempReg, tmpv, ArchReg, gregOfRM(rm));
1398//-- DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
1399//-- nameISize(szs), nameISize(szd),
1400//-- nameIReg(szs,eregOfRM(rm)),
1401//-- nameIReg(szd,gregOfRM(rm)));
1402//-- return 1+eip;
1403//-- }
1404//--
1405//-- /* E refers to memory */
1406//-- {
1407//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf);
1408//-- Int tmpa = LOW24(pair);
1409//-- uInstr2(cb, LOAD, szs, TempReg, tmpa, TempReg, tmpa);
1410//-- uInstr1(cb, WIDEN, szd, TempReg, tmpa);
1411//-- uWiden(cb, szs, sign_extend);
1412//-- uInstr2(cb, PUT, szd, TempReg, tmpa, ArchReg, gregOfRM(rm));
1413//-- DIP("mov%c%c%c %s,%s\n", sign_extend ? 's' : 'z',
1414//-- nameISize(szs), nameISize(szd),
1415//-- dis_buf, nameIReg(szd,gregOfRM(rm)));
1416//-- return HI8(pair)+eip;
1417//-- }
1418//-- }
1419//--
1420//--
1421//-- /* Generate code to divide ArchRegs EDX:EAX / DX:AX / AX by the 32 /
1422//-- 16 / 8 bit quantity in the given TempReg. */
1423//-- static
1424//-- void codegen_div ( UCodeBlock* cb, Int sz, Int t, Bool signed_divide )
1425//-- {
1426//-- Int helper;
1427//-- Int ta = newTemp(cb);
1428//-- Int td = newTemp(cb);
1429//--
1430//-- switch (sz) {
1431//-- case 4: helper = (signed_divide ? VGOFF_(helper_idiv_64_32)
1432//-- : VGOFF_(helper_div_64_32));
1433//-- break;
1434//-- case 2: helper = (signed_divide ? VGOFF_(helper_idiv_32_16)
1435//-- : VGOFF_(helper_div_32_16));
1436//-- break;
1437//-- case 1: helper = (signed_divide ? VGOFF_(helper_idiv_16_8)
1438//-- : VGOFF_(helper_div_16_8));
1439//-- break;
1440//-- default: VG_(core_panic)("codegen_div");
1441//-- }
1442//-- uInstr0(cb, CALLM_S, 0);
1443//-- if (sz == 4 || sz == 2) {
1444//-- uInstr1(cb, PUSH, sz, TempReg, t);
1445//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
1446//-- uInstr1(cb, PUSH, sz, TempReg, ta);
1447//-- uInstr2(cb, GET, sz, ArchReg, R_EDX, TempReg, td);
1448//-- uInstr1(cb, PUSH, sz, TempReg, td);
1449//-- uInstr1(cb, CALLM, 0, Lit16, helper);
1450//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsOSZACP);
1451//-- uInstr1(cb, POP, sz, TempReg, t);
1452//-- uInstr2(cb, PUT, sz, TempReg, t, ArchReg, R_EDX);
1453//-- uInstr1(cb, POP, sz, TempReg, t);
1454//-- uInstr2(cb, PUT, sz, TempReg, t, ArchReg, R_EAX);
1455//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
1456//-- } else {
1457//-- uInstr1(cb, PUSH, 1, TempReg, t);
1458//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, ta);
1459//-- uInstr1(cb, PUSH, 2, TempReg, ta);
1460//-- uInstr2(cb, MOV, 1, Literal, 0, TempReg, td);
1461//-- uLiteral(cb, 0);
1462//-- uInstr1(cb, PUSH, 1, TempReg, td);
1463//-- uInstr1(cb, CALLM, 0, Lit16, helper);
1464//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsOSZACP);
1465//-- uInstr1(cb, POP, 1, TempReg, t);
1466//-- uInstr2(cb, PUT, 1, TempReg, t, ArchReg, R_AL);
1467//-- uInstr1(cb, POP, 1, TempReg, t);
1468//-- uInstr2(cb, PUT, 1, TempReg, t, ArchReg, R_AH);
1469//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
1470//-- }
1471//-- uInstr0(cb, CALLM_E, 0);
1472//-- }
1473//--
1474//--
1475//-- static
1476//-- Addr dis_Grp1 ( UCodeBlock* cb,
1477//-- UChar sorb,
1478//-- Addr eip, UChar modrm,
1479//-- Int am_sz, Int d_sz, Int sz, UInt d32 )
1480//-- {
1481//-- Int t1, t2, uopc;
1482//-- UInt pair;
1483//-- UChar dis_buf[50];
1484//-- if (epartIsReg(modrm)) {
1485//-- vg_assert(am_sz == 1);
1486//-- t1 = newTemp(cb);
1487//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1488//-- switch (gregOfRM(modrm)) {
1489//-- case 0: uopc = ADD; break; case 1: uopc = OR; break;
1490//-- case 2: uopc = ADC; break; case 3: uopc = SBB; break;
1491//-- case 4: uopc = AND; break; case 5: uopc = SUB; break;
1492//-- case 6: uopc = XOR; break; case 7: uopc = SUB; break;
1493//-- default: VG_(core_panic)("dis_Grp1(Reg): unhandled case");
1494//-- }
1495//-- if (uopc == AND || uopc == OR) {
1496//-- Int tao = newTemp(cb);
1497//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
1498//-- uLiteral(cb, d32);
1499//-- uInstr2(cb, uopc, sz, TempReg, tao, TempReg, t1);
1500//-- setFlagsFromUOpcode(cb, uopc);
1501//-- } else {
1502//-- uInstr2(cb, uopc, sz, Literal, 0, TempReg, t1);
1503//-- uLiteral(cb, d32);
1504//-- setFlagsFromUOpcode(cb, uopc);
1505//-- }
1506//-- if (gregOfRM(modrm) < 7)
1507//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
1508//-- eip += (am_sz + d_sz);
1509//-- DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32,
1510//-- nameIReg(sz,eregOfRM(modrm)));
1511//-- } else {
1512//-- pair = disAMode ( cb, sorb, eip, dis_buf);
1513//-- t1 = LOW24(pair);
1514//-- t2 = newTemp(cb);
1515//-- eip += HI8(pair);
1516//-- eip += d_sz;
1517//-- uInstr2(cb, LOAD, sz, TempReg, t1, TempReg, t2);
1518//-- switch (gregOfRM(modrm)) {
1519//-- case 0: uopc = ADD; break; case 1: uopc = OR; break;
1520//-- case 2: uopc = ADC; break; case 3: uopc = SBB; break;
1521//-- case 4: uopc = AND; break; case 5: uopc = SUB; break;
1522//-- case 6: uopc = XOR; break; case 7: uopc = SUB; break;
1523//-- default: VG_(core_panic)("dis_Grp1(Mem): unhandled case");
1524//-- }
1525//-- if (uopc == AND || uopc == OR) {
1526//-- Int tao = newTemp(cb);
1527//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
1528//-- uLiteral(cb, d32);
1529//-- uInstr2(cb, uopc, sz, TempReg, tao, TempReg, t2);
1530//-- setFlagsFromUOpcode(cb, uopc);
1531//-- } else {
1532//-- uInstr2(cb, uopc, sz, Literal, 0, TempReg, t2);
1533//-- uLiteral(cb, d32);
1534//-- setFlagsFromUOpcode(cb, uopc);
1535//-- }
1536//-- if (gregOfRM(modrm) < 7) {
1537//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
1538//-- }
1539//-- DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
1540//-- d32, dis_buf);
1541//-- }
1542//-- return eip;
1543//-- }
1544//--
1545//--
1546//-- /* Group 2 extended opcodes. */
1547//-- static
1548//-- Addr dis_Grp2 ( UCodeBlock* cb,
1549//-- UChar sorb,
1550//-- Addr eip, UChar modrm,
1551//-- Int am_sz, Int d_sz, Int sz,
1552//-- Tag orig_src_tag, UInt orig_src_val )
1553//-- {
1554//-- /* orig_src_tag and orig_src_val denote either ArchReg(%CL) or a
1555//-- Literal. And eip on entry points at the modrm byte. */
1556//-- Int t1, t2, uopc;
1557//-- UInt pair;
1558//-- UChar dis_buf[50];
1559//-- UInt src_val;
1560//-- Tag src_tag;
1561//--
1562//-- /* Get the amount to be shifted by into src_tag/src_val. */
1563//-- if (orig_src_tag == ArchReg) {
1564//-- src_val = newTemp(cb);
1565//-- src_tag = TempReg;
1566//-- uInstr2(cb, GET, 1, orig_src_tag, orig_src_val, TempReg, src_val);
1567//-- } else {
1568//-- src_val = orig_src_val;
1569//-- src_tag = Literal;
1570//-- }
1571//--
1572//-- if (epartIsReg(modrm)) {
1573//-- vg_assert(am_sz == 1);
1574//-- t1 = newTemp(cb);
1575//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1576//-- switch (gregOfRM(modrm)) {
1577//-- case 0: uopc = ROL; break; case 1: uopc = ROR; break;
1578//-- case 2: uopc = RCL; break; case 3: uopc = RCR; break;
1579//-- case 4: uopc = SHL; break; case 5: uopc = SHR; break;
1580//-- case 7: uopc = SAR; break;
1581//-- default: VG_(core_panic)("dis_Grp2(Reg): unhandled case");
1582//-- }
1583//-- if (src_tag == Literal) {
1584//-- uInstr2(cb, uopc, sz, Literal, 0, TempReg, t1);
1585//-- uLiteral(cb, src_val);
1586//-- } else {
1587//-- uInstr2(cb, uopc, sz, src_tag, src_val, TempReg, t1);
1588//-- }
1589//-- setFlagsFromUOpcode(cb, uopc);
1590//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
1591//-- eip += (am_sz + d_sz);
1592//-- if (VG_(print_codegen)) {
1593//-- if (orig_src_tag == Literal)
1594//-- VG_(printf)("%s%c $0x%x, %s\n",
1595//-- nameGrp2(gregOfRM(modrm)), nameISize(sz),
1596//-- orig_src_val, nameIReg(sz,eregOfRM(modrm)));
1597//-- else
1598//-- VG_(printf)("%s%c %s, %s\n",
1599//-- nameGrp2(gregOfRM(modrm)), nameISize(sz),
1600//-- nameIReg(1,orig_src_val),
1601//-- nameIReg(sz,eregOfRM(modrm)));
1602//-- }
1603//-- } else {
1604//-- pair = disAMode ( cb, sorb, eip, dis_buf);
1605//-- t1 = LOW24(pair);
1606//-- t2 = newTemp(cb);
1607//-- eip += HI8(pair);
1608//-- eip += d_sz;
1609//-- uInstr2(cb, LOAD, sz, TempReg, t1, TempReg, t2);
1610//-- switch (gregOfRM(modrm)) {
1611//-- case 0: uopc = ROL; break; case 1: uopc = ROR; break;
1612//-- case 2: uopc = RCL; break; case 3: uopc = RCR; break;
1613//-- case 4: uopc = SHL; break; case 5: uopc = SHR; break;
1614//-- case 7: uopc = SAR; break;
1615//-- default: VG_(core_panic)("dis_Grp2(Reg): unhandled case");
1616//-- }
1617//-- if (src_tag == Literal) {
1618//-- uInstr2(cb, uopc, sz, Literal, 0, TempReg, t2);
1619//-- uLiteral(cb, src_val);
1620//-- } else {
1621//-- uInstr2(cb, uopc, sz, src_tag, src_val, TempReg, t2);
1622//-- }
1623//-- setFlagsFromUOpcode(cb, uopc);
1624//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
1625//-- if (VG_(print_codegen)) {
1626//-- if (orig_src_tag == Literal)
1627//-- VG_(printf)("%s%c $0x%x, %s\n",
1628//-- nameGrp2(gregOfRM(modrm)), nameISize(sz),
1629//-- orig_src_val, dis_buf);
1630//-- else
1631//-- VG_(printf)("%s%c %s, %s\n",
1632//-- nameGrp2(gregOfRM(modrm)), nameISize(sz),
1633//-- nameIReg(1,orig_src_val),
1634//-- dis_buf);
1635//-- }
1636//-- }
1637//-- return eip;
1638//-- }
1639//--
1640//--
1641//--
1642//-- /* Group 8 extended opcodes (but BT/BTS/BTC/BTR only). */
1643//-- static
1644//-- Addr dis_Grp8_BT ( UCodeBlock* cb,
1645//-- UChar sorb,
1646//-- Addr eip, UChar modrm,
1647//-- Int am_sz, Int sz, UInt src_val )
1648//-- {
sewardjd1061ab2004-07-08 01:45:30 +00001649# define MODIFY_t2_AND_SET_CARRY_FLAG \
1650 /* t2 is the value to be op'd on. Copy to t_fetched, then \
1651 modify t2, if non-BT. */ \
1652 uInstr2(cb, MOV, 4, TempReg, t2, TempReg, t_fetched); \
1653 uInstr2(cb, MOV, sz, Literal, 0, TempReg, t_mask); \
1654 uLiteral(cb, v_mask); \
1655 switch (gregOfRM(modrm)) { \
1656 case 4: /* BT */ break; \
1657 case 5: /* BTS */ \
1658 uInstr2(cb, OR, sz, TempReg, t_mask, TempReg, t2); break; \
1659 case 6: /* BTR */ \
1660 uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t2); break; \
1661 case 7: /* BTC */ \
1662 uInstr2(cb, XOR, sz, TempReg, t_mask, TempReg, t2); break; \
1663 } \
1664 /* Copy relevant bit from t_fetched into carry flag. */ \
1665 uInstr2(cb, SHR, sz, Literal, 0, TempReg, t_fetched); \
1666 uLiteral(cb, src_val); \
1667 uInstr2(cb, MOV, sz, Literal, 0, TempReg, t_mask); \
1668 uLiteral(cb, 1); \
1669 uInstr2(cb, AND, sz, TempReg, t_mask, TempReg, t_fetched); \
1670 uInstr1(cb, NEG, sz, TempReg, t_fetched); \
1671 setFlagsFromUOpcode(cb, NEG);
1672
1673
sewardjc9a65702004-07-07 16:32:57 +00001674//-- /* src_val denotes a d8.
1675//-- And eip on entry points at the modrm byte. */
1676//-- Int t1, t2, t_fetched, t_mask;
1677//-- UInt pair;
1678//-- Char dis_buf[50];
1679//-- UInt v_mask;
1680//--
1681//-- /* There is no 1-byte form of this instruction, AFAICS. */
1682//-- vg_assert(sz == 2 || sz == 4);
1683//--
1684//-- /* Limit src_val -- the bit offset -- to something within a word.
1685//-- The Intel docs say that literal offsets larger than a word are
1686//-- masked in this way. */
1687//-- switch (sz) {
1688//-- case 2: src_val &= 15; break;
1689//-- case 4: src_val &= 31; break;
1690//-- default: VG_(core_panic)("dis_Grp8_BT: invalid size");
1691//-- }
1692//--
1693//-- /* Invent a mask suitable for the operation. */
1694//--
1695//-- switch (gregOfRM(modrm)) {
1696//-- case 4: /* BT */ v_mask = 0; break;
1697//-- case 5: /* BTS */ v_mask = 1 << src_val; break;
1698//-- case 6: /* BTR */ v_mask = ~(1 << src_val); break;
1699//-- case 7: /* BTC */ v_mask = 1 << src_val; break;
1700//-- /* If this needs to be extended, probably simplest to make a
1701//-- new function to handle the other cases (0 .. 3). The
1702//-- Intel docs do however not indicate any use for 0 .. 3, so
1703//-- we don't expect this to happen. */
1704//-- default: VG_(core_panic)("dis_Grp8_BT");
1705//-- }
1706//-- /* Probably excessively paranoid. */
1707//-- if (sz == 2)
1708//-- v_mask &= 0x0000FFFF;
1709//--
1710//-- t1 = INVALID_TEMPREG;
1711//-- t_fetched = newTemp(cb);
1712//-- t_mask = newTemp(cb);
1713//--
1714//-- if (epartIsReg(modrm)) {
1715//-- vg_assert(am_sz == 1);
1716//-- t2 = newTemp(cb);
1717//--
1718//-- /* Fetch the value to be tested and modified. */
1719//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t2);
1720//-- /* Do it! */
1721//-- MODIFY_t2_AND_SET_CARRY_FLAG;
1722//-- /* Dump the result back, if non-BT. */
1723//-- if (gregOfRM(modrm) != 4 /* BT */)
1724//-- uInstr2(cb, PUT, sz, TempReg, t2, ArchReg, eregOfRM(modrm));
1725//--
1726//-- eip += (am_sz + 1);
1727//-- DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
1728//-- src_val, nameIReg(sz,eregOfRM(modrm)));
1729//-- } else {
1730//-- pair = disAMode ( cb, sorb, eip, dis_buf);
1731//-- t1 = LOW24(pair);
1732//-- t2 = newTemp(cb);
1733//-- eip += HI8(pair);
1734//-- eip += 1;
1735//--
1736//-- /* Fetch the value to be tested and modified. */
1737//-- uInstr2(cb, LOAD, sz, TempReg, t1, TempReg, t2);
1738//-- /* Do it! */
1739//-- MODIFY_t2_AND_SET_CARRY_FLAG;
1740//-- /* Dump the result back, if non-BT. */
1741//-- if (gregOfRM(modrm) != 4 /* BT */) {
1742//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
1743//-- }
1744//-- DIP("%s%c $0x%x, %s\n", nameGrp8(gregOfRM(modrm)), nameISize(sz),
1745//-- src_val, dis_buf);
1746//-- }
1747//-- return eip;
1748//--
1749//-- # undef MODIFY_t2_AND_SET_CARRY_FLAG
1750//-- }
1751//--
1752//--
1753//--
1754//-- /* Generate ucode to multiply the value in EAX/AX/AL by the register
1755//-- specified by the ereg of modrm, and park the result in
1756//-- EDX:EAX/DX:AX/AX. */
1757//-- static void codegen_mul_A_D_Reg ( UCodeBlock* cb, Int sz,
1758//-- UChar modrm, Bool signed_multiply )
1759//-- {
1760//-- Int helper = signed_multiply
1761//-- ?
1762//-- (sz==1 ? VGOFF_(helper_imul_8_16)
1763//-- : (sz==2 ? VGOFF_(helper_imul_16_32)
1764//-- : VGOFF_(helper_imul_32_64)))
1765//-- :
1766//-- (sz==1 ? VGOFF_(helper_mul_8_16)
1767//-- : (sz==2 ? VGOFF_(helper_mul_16_32)
1768//-- : VGOFF_(helper_mul_32_64)));
1769//-- Int t1 = newTemp(cb);
1770//-- Int ta = newTemp(cb);
1771//-- uInstr0(cb, CALLM_S, 0);
1772//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1773//-- uInstr1(cb, PUSH, sz, TempReg, t1);
1774//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
1775//-- uInstr1(cb, PUSH, sz, TempReg, ta);
1776//-- uInstr1(cb, CALLM, 0, Lit16, helper);
1777//-- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
1778//-- if (sz > 1) {
1779//-- uInstr1(cb, POP, sz, TempReg, t1);
1780//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EDX);
1781//-- uInstr1(cb, POP, sz, TempReg, t1);
1782//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EAX);
1783//-- } else {
1784//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
1785//-- uInstr1(cb, POP, 2, TempReg, t1);
1786//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
1787//-- }
1788//-- uInstr0(cb, CALLM_E, 0);
1789//-- DIP("%s%c %s\n", signed_multiply ? "imul" : "mul",
1790//-- nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
1791//--
1792//-- }
1793//--
1794//--
1795//-- /* Generate ucode to multiply the value in EAX/AX/AL by the value in
1796//-- TempReg temp, and park the result in EDX:EAX/DX:AX/AX. */
1797//-- static void codegen_mul_A_D_Temp ( UCodeBlock* cb, Int sz,
1798//-- Int temp, Bool signed_multiply,
1799//-- UChar* dis_buf )
1800//-- {
1801//-- Int helper = signed_multiply
1802//-- ?
1803//-- (sz==1 ? VGOFF_(helper_imul_8_16)
1804//-- : (sz==2 ? VGOFF_(helper_imul_16_32)
1805//-- : VGOFF_(helper_imul_32_64)))
1806//-- :
1807//-- (sz==1 ? VGOFF_(helper_mul_8_16)
1808//-- : (sz==2 ? VGOFF_(helper_mul_16_32)
1809//-- : VGOFF_(helper_mul_32_64)));
1810//-- Int t1 = newTemp(cb);
1811//-- uInstr0(cb, CALLM_S, 0);
1812//-- uInstr1(cb, PUSH, sz, TempReg, temp);
1813//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1);
1814//-- uInstr1(cb, PUSH, sz, TempReg, t1);
1815//-- uInstr1(cb, CALLM, 0, Lit16, helper);
1816//-- uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
1817//-- if (sz > 1) {
1818//-- uInstr1(cb, POP, sz, TempReg, t1);
1819//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EDX);
1820//-- uInstr1(cb, POP, sz, TempReg, t1);
1821//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EAX);
1822//-- } else {
1823//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
1824//-- uInstr1(cb, POP, 2, TempReg, t1);
1825//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
1826//-- }
1827//-- uInstr0(cb, CALLM_E, 0);
1828//-- DIP("%s%c %s\n", signed_multiply ? "imul" : "mul",
1829//-- nameISize(sz), dis_buf);
1830//-- }
1831//--
1832//--
1833//-- /* Group 3 extended opcodes. */
1834//-- static
1835//-- Addr dis_Grp3 ( UCodeBlock* cb,
1836//-- UChar sorb,
1837//-- Int sz, Addr eip )
1838//-- {
1839//-- Int t1, t2;
1840//-- UInt pair, d32;
1841//-- UChar modrm;
1842//-- UChar dis_buf[50];
1843//-- t1 = t2 = INVALID_TEMPREG;
1844//-- modrm = getIByte(delta);
1845//-- if (epartIsReg(modrm)) {
1846//-- t1 = newTemp(cb);
1847//-- switch (gregOfRM(modrm)) {
1848//-- case 0: { /* TEST */
1849//-- Int tao = newTemp(cb);
1850//-- eip++; d32 = getUDisp(sz, eip); eip += sz;
1851//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1852//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
1853//-- uLiteral(cb, d32);
1854//-- uInstr2(cb, AND, sz, TempReg, tao, TempReg, t1);
1855//-- setFlagsFromUOpcode(cb, AND);
1856//-- DIP("test%c $0x%x, %s\n",
1857//-- nameISize(sz), d32, nameIReg(sz, eregOfRM(modrm)));
1858//-- break;
1859//-- }
1860//-- case 2: /* NOT */
1861//-- eip++;
1862//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1863//-- uInstr1(cb, NOT, sz, TempReg, t1);
1864//-- setFlagsFromUOpcode(cb, NOT);
1865//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
1866//-- DIP("not%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
1867//-- break;
1868//-- case 3: /* NEG */
1869//-- eip++;
1870//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1871//-- uInstr1(cb, NEG, sz, TempReg, t1);
1872//-- setFlagsFromUOpcode(cb, NEG);
1873//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
1874//-- DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
1875//-- break;
1876//-- case 4: /* MUL */
1877//-- eip++;
1878//-- codegen_mul_A_D_Reg ( cb, sz, modrm, False );
1879//-- break;
1880//-- case 5: /* IMUL */
1881//-- eip++;
1882//-- codegen_mul_A_D_Reg ( cb, sz, modrm, True );
1883//-- break;
1884//-- case 6: /* DIV */
1885//-- eip++;
1886//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1887//-- codegen_div ( cb, sz, t1, False );
1888//-- DIP("div%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
1889//-- break;
1890//-- case 7: /* IDIV */
1891//-- eip++;
1892//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
1893//-- codegen_div ( cb, sz, t1, True );
1894//-- DIP("idiv%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
1895//-- break;
1896//-- default:
1897//-- VG_(printf)(
1898//-- "unhandled Grp3(R) case %d\n", (UInt)gregOfRM(modrm));
1899//-- VG_(core_panic)("Grp3");
1900//-- }
1901//-- } else {
1902//-- pair = disAMode ( cb, sorb, eip, dis_buf );
1903//-- t2 = LOW24(pair);
1904//-- t1 = newTemp(cb);
1905//-- eip += HI8(pair);
1906//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
1907//-- switch (gregOfRM(modrm)) {
1908//-- case 0: { /* TEST */
1909//-- Int tao = newTemp(cb);
1910//-- d32 = getUDisp(sz, eip); eip += sz;
1911//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
1912//-- uLiteral(cb, d32);
1913//-- uInstr2(cb, AND, sz, TempReg, tao, TempReg, t1);
1914//-- setFlagsFromUOpcode(cb, AND);
1915//-- DIP("test%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
1916//-- break;
1917//-- }
1918//-- case 2: /* NOT */
1919//-- uInstr1(cb, NOT, sz, TempReg, t1);
1920//-- setFlagsFromUOpcode(cb, NOT);
1921//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
1922//-- DIP("not%c %s\n", nameISize(sz), dis_buf);
1923//-- break;
1924//-- case 3: /* NEG */
1925//-- uInstr1(cb, NEG, sz, TempReg, t1);
1926//-- setFlagsFromUOpcode(cb, NEG);
1927//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
1928//-- DIP("neg%c %s\n", nameISize(sz), dis_buf);
1929//-- break;
1930//-- case 4: /* MUL */
1931//-- codegen_mul_A_D_Temp ( cb, sz, t1, False,
1932//-- dis_buf );
1933//-- break;
1934//-- case 5: /* IMUL */
1935//-- codegen_mul_A_D_Temp ( cb, sz, t1, True, dis_buf );
1936//-- break;
1937//-- case 6: /* DIV */
1938//-- codegen_div ( cb, sz, t1, False );
1939//-- DIP("div%c %s\n", nameISize(sz), dis_buf);
1940//-- break;
1941//-- case 7: /* IDIV */
1942//-- codegen_div ( cb, sz, t1, True );
1943//-- DIP("idiv%c %s\n", nameISize(sz), dis_buf);
1944//-- break;
1945//-- default:
1946//-- VG_(printf)(
1947//-- "unhandled Grp3(M) case %d\n", (UInt)gregOfRM(modrm));
1948//-- VG_(core_panic)("Grp3");
1949//-- }
1950//-- }
1951//-- return eip;
1952//-- }
1953//--
1954//--
1955//-- /* Group 4 extended opcodes. */
1956//-- static
1957//-- Addr dis_Grp4 ( UCodeBlock* cb,
1958//-- UChar sorb,
1959//-- Addr eip )
1960//-- {
1961//-- Int t1, t2;
1962//-- UInt pair;
1963//-- UChar modrm;
1964//-- UChar dis_buf[50];
1965//-- t1 = t2 = INVALID_TEMPREG;
1966//--
1967//-- modrm = getIByte(delta);
1968//-- if (epartIsReg(modrm)) {
1969//-- t1 = newTemp(cb);
1970//-- uInstr2(cb, GET, 1, ArchReg, eregOfRM(modrm), TempReg, t1);
1971//-- switch (gregOfRM(modrm)) {
1972//-- case 0: /* INC */
1973//-- uInstr1(cb, INC, 1, TempReg, t1);
1974//-- setFlagsFromUOpcode(cb, INC);
1975//-- uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, eregOfRM(modrm));
1976//-- break;
1977//-- case 1: /* DEC */
1978//-- uInstr1(cb, DEC, 1, TempReg, t1);
1979//-- setFlagsFromUOpcode(cb, DEC);
1980//-- uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, eregOfRM(modrm));
1981//-- break;
1982//-- default:
1983//-- VG_(printf)(
1984//-- "unhandled Grp4(R) case %d\n", (UInt)gregOfRM(modrm));
1985//-- VG_(core_panic)("Grp4");
1986//-- }
1987//-- eip++;
1988//-- DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)),
1989//-- nameIReg(1, eregOfRM(modrm)));
1990//-- } else {
1991//-- pair = disAMode ( cb, sorb, eip, dis_buf );
1992//-- t2 = LOW24(pair);
1993//-- t1 = newTemp(cb);
1994//-- uInstr2(cb, LOAD, 1, TempReg, t2, TempReg, t1);
1995//-- switch (gregOfRM(modrm)) {
1996//-- case 0: /* INC */
1997//-- uInstr1(cb, INC, 1, TempReg, t1);
1998//-- setFlagsFromUOpcode(cb, INC);
1999//-- uInstr2(cb, STORE, 1, TempReg, t1, TempReg, t2);
2000//-- break;
2001//-- case 1: /* DEC */
2002//-- uInstr1(cb, DEC, 1, TempReg, t1);
2003//-- setFlagsFromUOpcode(cb, DEC);
2004//-- uInstr2(cb, STORE, 1, TempReg, t1, TempReg, t2);
2005//-- break;
2006//-- default:
2007//-- VG_(printf)(
2008//-- "unhandled Grp4(M) case %d\n", (UInt)gregOfRM(modrm));
2009//-- VG_(core_panic)("Grp4");
2010//-- }
2011//-- eip += HI8(pair);
2012//-- DIP("%sb %s\n", nameGrp4(gregOfRM(modrm)), dis_buf);
2013//-- }
2014//-- return eip;
2015//-- }
2016//--
2017//--
2018//-- /* Group 5 extended opcodes. */
2019//-- static
2020//-- Addr dis_Grp5 ( UCodeBlock* cb,
2021//-- UChar sorb,
2022//-- Int sz, Addr eip, Bool* isEnd )
2023//-- {
2024//-- Int t1, t2, t3, t4;
2025//-- UInt pair;
2026//-- UChar modrm;
2027//-- UChar dis_buf[50];
2028//-- t1 = t2 = t3 = t4 = INVALID_TEMPREG;
2029//--
2030//-- modrm = getIByte(delta);
2031//-- if (epartIsReg(modrm)) {
2032//-- t1 = newTemp(cb);
2033//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
2034//-- switch (gregOfRM(modrm)) {
2035//-- case 0: /* INC */
2036//-- uInstr1(cb, INC, sz, TempReg, t1);
2037//-- setFlagsFromUOpcode(cb, INC);
2038//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
2039//-- break;
2040//-- case 1: /* DEC */
2041//-- uInstr1(cb, DEC, sz, TempReg, t1);
2042//-- setFlagsFromUOpcode(cb, DEC);
2043//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
2044//-- break;
2045//-- case 2: /* call Ev */
2046//-- t3 = newTemp(cb); t4 = newTemp(cb);
2047//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t3);
2048//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t3);
2049//-- uLiteral(cb, 4);
2050//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_ESP);
2051//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t4);
2052//-- uLiteral(cb, eip+1);
2053//-- uInstr2(cb, STORE, 4, TempReg, t4, TempReg, t3);
2054//-- jmp_treg(cb, t1);
2055//-- LAST_UINSTR(cb).jmpkind = JmpCall;
2056//-- *isEnd = True;
2057//-- break;
2058//-- case 4: /* jmp Ev */
2059//-- jmp_treg(cb, t1);
2060//-- *isEnd = True;
2061//-- break;
2062//-- default:
2063//-- VG_(printf)(
2064//-- "unhandled Grp5(R) case %d\n", (UInt)gregOfRM(modrm));
2065//-- VG_(core_panic)("Grp5");
2066//-- }
2067//-- eip++;
2068//-- DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
2069//-- nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
2070//-- } else {
2071//-- pair = disAMode ( cb, sorb, eip, dis_buf );
2072//-- t2 = LOW24(pair);
2073//-- t1 = newTemp(cb);
2074//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
2075//-- switch (gregOfRM(modrm)) {
2076//-- case 0: /* INC */
2077//-- uInstr1(cb, INC, sz, TempReg, t1);
2078//-- setFlagsFromUOpcode(cb, INC);
2079//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
2080//-- break;
2081//-- case 1: /* DEC */
2082//-- uInstr1(cb, DEC, sz, TempReg, t1);
2083//-- setFlagsFromUOpcode(cb, DEC);
2084//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
2085//-- break;
2086//-- case 2: /* call Ev */
2087//-- t3 = newTemp(cb); t4 = newTemp(cb);
2088//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t3);
2089//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t3);
2090//-- uLiteral(cb, 4);
2091//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_ESP);
2092//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t4);
2093//-- uLiteral(cb, eip+HI8(pair));
2094//-- uInstr2(cb, STORE, 4, TempReg, t4, TempReg, t3);
2095//-- jmp_treg(cb, t1);
2096//-- LAST_UINSTR(cb).jmpkind = JmpCall;
2097//-- *isEnd = True;
2098//-- break;
2099//-- case 4: /* JMP Ev */
2100//-- jmp_treg(cb, t1);
2101//-- *isEnd = True;
2102//-- break;
2103//-- case 6: /* PUSH Ev */
2104//-- t3 = newTemp(cb);
2105//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t3);
2106//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t3);
2107//-- uLiteral(cb, sz);
2108//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_ESP);
2109//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t3);
2110//-- break;
2111//-- default:
2112//-- VG_(printf)(
2113//-- "unhandled Grp5(M) case %d\n", (UInt)gregOfRM(modrm));
2114//-- VG_(core_panic)("Grp5");
2115//-- }
2116//-- eip += HI8(pair);
2117//-- DIP("%s%c %s\n", nameGrp5(gregOfRM(modrm)),
2118//-- nameISize(sz), dis_buf);
2119//-- }
2120//-- return eip;
2121//-- }
2122//--
2123//-- /*------------------------------------------------------------*/
2124//-- /*--- Disassembling string ops (including REP prefixes) ---*/
2125//-- /*------------------------------------------------------------*/
2126//--
2127//-- /* Code shared by all the string ops */
2128//-- static
2129//-- void dis_string_op_increment(UCodeBlock* cb, Int sz, Int t_inc)
2130//-- {
2131//-- uInstr0 (cb, CALLM_S, 0);
2132//-- uInstr2 (cb, MOV, 4, Literal, 0, TempReg, t_inc);
2133//-- uLiteral(cb, 0);
2134//-- uInstr1 (cb, PUSH, 4, TempReg, t_inc);
2135//--
2136//-- uInstr1 (cb, CALLM, 0, Lit16, VGOFF_(helper_get_dirflag));
2137//-- uFlagsRWU(cb, FlagD, FlagsEmpty, FlagsEmpty);
2138//--
2139//-- uInstr1(cb, POP, 4, TempReg, t_inc);
2140//-- uInstr0(cb, CALLM_E, 0);
2141//--
2142//-- if (sz == 4 || sz == 2) {
2143//-- uInstr2(cb, SHL, 4, Literal, 0, TempReg, t_inc);
2144//-- uLiteral(cb, sz/2);
2145//-- }
2146//-- }
2147//--
2148//-- static
2149//-- void dis_string_op( UCodeBlock* cb, void (*dis_OP)( UCodeBlock*, Int, Int ),
2150//-- Int sz, Char* name, UChar sorb )
2151//-- {
2152//-- Int t_inc = newTemp(cb);
2153//-- vg_assert(sorb == 0);
2154//-- dis_string_op_increment(cb, sz, t_inc);
2155//-- dis_OP( cb, sz, t_inc );
2156//-- DIP("%s%c\n", name, nameISize(sz));
2157//-- }
2158//--
2159//--
2160//-- static
2161//-- void dis_MOVS ( UCodeBlock* cb, Int sz, Int t_inc )
2162//-- {
2163//-- Int tv = newTemp(cb); /* value being copied */
2164//-- Int td = newTemp(cb); /* EDI */
2165//-- Int ts = newTemp(cb); /* ESI */
2166//--
2167//-- uInstr2(cb, GET, 4, ArchReg, R_EDI, TempReg, td);
2168//-- uInstr2(cb, GET, 4, ArchReg, R_ESI, TempReg, ts);
2169//--
2170//-- uInstr2(cb, LOAD, sz, TempReg, ts, TempReg, tv);
2171//-- uInstr2(cb, STORE,sz, TempReg, tv, TempReg, td);
2172//--
2173//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
2174//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, ts);
2175//--
2176//-- uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI);
2177//-- uInstr2(cb, PUT, 4, TempReg, ts, ArchReg, R_ESI);
2178//-- }
2179//--
2180//-- static
2181//-- void dis_LODS ( UCodeBlock* cb, Int sz, Int t_inc )
2182//-- {
2183//-- Int ta = newTemp(cb); /* EAX */
2184//-- Int ts = newTemp(cb); /* ESI */
2185//--
2186//-- uInstr2(cb, GET, 4, ArchReg, R_ESI, TempReg, ts);
2187//-- uInstr2(cb, LOAD, sz, TempReg, ts, TempReg, ta);
2188//-- uInstr2(cb, PUT, sz, TempReg, ta, ArchReg, R_EAX);
2189//--
2190//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, ts);
2191//-- uInstr2(cb, PUT, 4, TempReg, ts, ArchReg, R_ESI);
2192//-- }
2193//--
2194//-- static
2195//-- void dis_STOS ( UCodeBlock* cb, Int sz, Int t_inc )
2196//-- {
2197//-- Int ta = newTemp(cb); /* EAX */
2198//-- Int td = newTemp(cb); /* EDI */
2199//--
2200//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
2201//-- uInstr2(cb, GET, 4, ArchReg, R_EDI, TempReg, td);
2202//-- uInstr2(cb, STORE, sz, TempReg, ta, TempReg, td);
2203//--
2204//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
2205//-- uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI);
2206//-- }
2207//--
2208//-- static
2209//-- void dis_CMPS ( UCodeBlock* cb, Int sz, Int t_inc )
2210//-- {
2211//-- Int tdv = newTemp(cb); /* (EDI) */
2212//-- Int tsv = newTemp(cb); /* (ESI) */
2213//-- Int td = newTemp(cb); /* EDI */
2214//-- Int ts = newTemp(cb); /* ESI */
2215//--
2216//-- uInstr2(cb, GET, 4, ArchReg, R_EDI, TempReg, td);
2217//-- uInstr2(cb, GET, 4, ArchReg, R_ESI, TempReg, ts);
2218//--
2219//-- uInstr2(cb, LOAD, sz, TempReg, td, TempReg, tdv);
2220//-- uInstr2(cb, LOAD, sz, TempReg, ts, TempReg, tsv);
2221//--
2222//-- uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, tsv);
2223//-- setFlagsFromUOpcode(cb, SUB);
2224//--
2225//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
2226//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, ts);
2227//--
2228//-- uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI);
2229//-- uInstr2(cb, PUT, 4, TempReg, ts, ArchReg, R_ESI);
2230//-- }
2231//--
2232//-- static
2233//-- void dis_SCAS ( UCodeBlock* cb, Int sz, Int t_inc )
2234//-- {
2235//-- Int ta = newTemp(cb); /* EAX */
2236//-- Int td = newTemp(cb); /* EDI */
2237//-- Int tdv = newTemp(cb); /* (EDI) */
2238//--
2239//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, ta);
2240//-- uInstr2(cb, GET, 4, ArchReg, R_EDI, TempReg, td);
2241//-- uInstr2(cb, LOAD, sz, TempReg, td, TempReg, tdv);
2242//-- /* next uinstr kills ta, but that's ok -- don't need it again */
2243//-- uInstr2(cb, SUB, sz, TempReg, tdv, TempReg, ta);
2244//-- setFlagsFromUOpcode(cb, SUB);
2245//--
2246//-- uInstr2(cb, ADD, 4, TempReg, t_inc, TempReg, td);
2247//-- uInstr2(cb, PUT, 4, TempReg, td, ArchReg, R_EDI);
2248//-- }
2249//--
2250//--
2251//-- /* Wrap the appropriate string op inside a REP/REPE/REPNE.
2252//-- We assume the insn is the last one in the basic block, and so emit a jump
2253//-- to the next insn, rather than just falling through. */
2254//-- static
2255//-- void dis_REP_op ( UCodeBlock* cb, Int cond,
2256//-- void (*dis_OP)(UCodeBlock*, Int, Int),
2257//-- Int sz, Addr eip, Addr eip_next, Char* name )
2258//-- {
2259//-- Int t_inc = newTemp(cb);
2260//-- Int tc = newTemp(cb); /* ECX */
2261//--
2262//-- dis_string_op_increment(cb, sz, t_inc);
2263//--
2264//-- uInstr2 (cb, GET, 4, ArchReg, R_ECX, TempReg, tc);
2265//-- uInstr2 (cb, JIFZ, 4, TempReg, tc, Literal, 0);
2266//-- uLiteral(cb, eip_next);
2267//-- uInstr1 (cb, DEC, 4, TempReg, tc);
2268//-- uInstr2 (cb, PUT, 4, TempReg, tc, ArchReg, R_ECX);
2269//--
2270//-- dis_OP (cb, sz, t_inc);
2271//--
2272//-- if (cond == CondAlways) {
2273//-- jmp_lit(cb, eip);
2274//-- } else {
2275//-- jcc_lit(cb, eip, cond);
2276//-- jmp_lit(cb, eip_next);
2277//-- }
2278//-- DIP("%s%c\n", name, nameISize(sz));
2279//-- }
2280//--
2281//-- /*------------------------------------------------------------*/
2282//-- /*--- Arithmetic, etc. ---*/
2283//-- /*------------------------------------------------------------*/
2284//--
2285//-- /* (I)MUL E, G. Supplied eip points to the modR/M byte. */
2286//-- static
2287//-- Addr dis_mul_E_G ( UCodeBlock* cb,
2288//-- UChar sorb,
2289//-- Int size,
2290//-- Addr eip0,
2291//-- Bool signed_multiply )
2292//-- {
2293//-- Int ta, tg, te;
2294//-- UChar dis_buf[50];
2295//-- UChar rm = getIByte(delta0);
2296//-- ta = INVALID_TEMPREG;
2297//-- te = newTemp(cb);
2298//-- tg = newTemp(cb);
2299//--
2300//-- if (epartIsReg(rm)) {
2301//-- vg_assert(signed_multiply);
2302//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tg);
2303//-- uInstr2(cb, MUL, size, ArchReg, eregOfRM(rm), TempReg, tg);
2304//-- setFlagsFromUOpcode(cb, MUL);
2305//-- uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
2306//-- DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
2307//-- nameISize(size),
2308//-- nameIReg(size,eregOfRM(rm)),
2309//-- nameIReg(size,gregOfRM(rm)));
2310//-- return 1+eip0;
2311//-- } else {
2312//-- UInt pair;
2313//-- vg_assert(signed_multiply);
2314//-- pair = disAMode ( cb, sorb, eip0, dis_buf );
2315//-- ta = LOW24(pair);
2316//-- uInstr2(cb, LOAD, size, TempReg, ta, TempReg, te);
2317//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tg);
2318//-- uInstr2(cb, MUL, size, TempReg, te, TempReg, tg);
2319//-- setFlagsFromUOpcode(cb, MUL);
2320//-- uInstr2(cb, PUT, size, TempReg, tg, ArchReg, gregOfRM(rm));
2321//--
2322//-- DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
2323//-- nameISize(size),
2324//-- dis_buf, nameIReg(size,gregOfRM(rm)));
2325//-- return HI8(pair)+eip0;
2326//-- }
2327//-- }
2328//--
2329//--
2330//-- /* IMUL I * E -> G. Supplied eip points to the modR/M byte. */
2331//-- static
2332//-- Addr dis_imul_I_E_G ( UCodeBlock* cb,
2333//-- UChar sorb,
2334//-- Int size,
2335//-- Addr eip,
2336//-- Int litsize )
2337//-- {
2338//-- Int ta, te, tl, d32;
2339//-- Char dis_buf[50];
2340//-- UChar rm = getIByte(delta);
2341//-- ta = INVALID_TEMPREG;
2342//-- te = newTemp(cb);
2343//-- tl = newTemp(cb);
2344//--
2345//-- if (epartIsReg(rm)) {
2346//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, te);
2347//-- eip++;
2348//-- } else {
2349//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
2350//-- ta = LOW24(pair);
2351//-- uInstr2(cb, LOAD, size, TempReg, ta, TempReg, te);
2352//-- eip += HI8(pair);
2353//-- }
2354//--
2355//-- d32 = getSDisp(litsize,eip);
2356//-- eip += litsize;
2357//--
2358//-- uInstr2(cb, MOV, size, Literal, 0, TempReg, tl);
2359//-- uLiteral(cb, d32);
2360//-- uInstr2(cb, MUL, size, TempReg, tl, TempReg, te);
2361//-- setFlagsFromUOpcode(cb, MUL);
2362//-- uInstr2(cb, PUT, size, TempReg, te, ArchReg, gregOfRM(rm));
2363//--
2364//-- DIP("imul %d, %s, %s\n", d32,
2365//-- ( epartIsReg(rm) ? nameIReg(size,eregOfRM(rm)) : dis_buf ),
2366//-- nameIReg(size,gregOfRM(rm)) );
2367//--
2368//-- return eip;
2369//-- }
2370//--
2371//--
2372//-- /* Handle FPU insns which read/write memory. On entry, eip points to
2373//-- the second byte of the insn (the one following D8 .. DF). */
2374//-- static
2375//-- Addr dis_fpu_mem ( UCodeBlock* cb,
2376//-- UChar sorb,
2377//-- Int size, Bool is_write,
2378//-- Addr eip, UChar first_byte )
2379//-- {
2380//-- Int ta;
2381//-- UInt pair;
2382//-- UChar dis_buf[50];
2383//-- UChar second_byte = getIByte(delta);
2384//-- vg_assert(second_byte < 0xC0);
2385//-- second_byte &= 0x38;
2386//-- pair = disAMode ( cb, sorb, eip, dis_buf );
2387//-- ta = LOW24(pair);
2388//-- eip += HI8(pair);
2389//-- uInstr2(cb, is_write ? FPU_W : FPU_R, size,
2390//-- Lit16,
2391//-- (((UShort)first_byte) << 8) | ((UShort)second_byte),
2392//-- TempReg, ta);
2393//-- if (is_write) {
2394//-- DIP("fpu_w_%d 0x%x:0x%x, %s\n",
2395//-- size, (UInt)first_byte, (UInt)second_byte, dis_buf );
2396//-- } else {
2397//-- DIP("fpu_r_%d %s, 0x%x:0x%x\n",
2398//-- size, dis_buf, (UInt)first_byte, (UInt)second_byte );
2399//-- }
2400//-- return eip;
2401//-- }
2402//--
2403//--
2404//-- /* Handle FPU insns which don't reference memory. On entry, eip points to
2405//-- the second byte of the insn (the one following D8 .. DF). */
2406//-- static
2407//-- Addr dis_fpu_no_mem ( UCodeBlock* cb, Addr eip, UChar first_byte )
2408//-- {
2409//-- Bool sets_ZCP = False;
2410//-- Bool uses_ZCP = False;
2411//-- UChar second_byte = getUChar(eip); eip++;
2412//-- vg_assert(second_byte >= 0xC0);
2413//--
2414//-- /* Does the insn write any integer condition codes (%EIP) ? */
2415//--
2416//-- if (first_byte == 0xDB && second_byte >= 0xF0 && second_byte <= 0xF7) {
2417//-- /* FCOMI */
2418//-- sets_ZCP = True;
2419//-- } else
2420//-- if (first_byte == 0xDF && second_byte >= 0xF0 && second_byte <= 0xF7) {
2421//-- /* FCOMIP */
2422//-- sets_ZCP = True;
2423//-- } else
2424//-- if (first_byte == 0xDB && second_byte >= 0xE8 && second_byte <= 0xEF) {
2425//-- /* FUCOMI */
2426//-- sets_ZCP = True;
2427//-- } else
2428//-- if (first_byte == 0xDF && second_byte >= 0xE8 && second_byte <= 0xEF) {
2429//-- /* FUCOMIP */
2430//-- sets_ZCP = True;
2431//-- }
2432//--
2433//-- /* Dually, does the insn read any integer condition codes (%EIP) ? */
2434//--
2435//-- if (first_byte == 0xDA && second_byte >= 0xC0 && second_byte <= 0xDF) {
2436//-- /* FCMOVB %st(n), %st(0)
2437//-- FCMOVE %st(n), %st(0)
2438//-- FCMOVBE %st(n), %st(0)
2439//-- FCMOVU %st(n), %st(0)
2440//-- */
2441//-- uses_ZCP = True;
2442//-- } else
2443//-- if (first_byte == 0xDB && second_byte >= 0xC0 && second_byte <= 0xDF) {
2444//-- /* FCMOVNB %st(n), %st(0)
2445//-- FCMOVNE %st(n), %st(0)
2446//-- FCMOVNBE %st(n), %st(0)
2447//-- FCMOVNU %st(n), %st(0)
2448//-- */
2449//-- uses_ZCP = True;
2450//-- }
2451//--
2452//-- uInstr1(cb, FPU, 0,
2453//-- Lit16,
2454//-- (((UShort)first_byte) << 8) | ((UShort)second_byte)
2455//-- );
2456//-- if (uses_ZCP) {
2457//-- /* VG_(printf)("!!! --- FPU insn which reads %EFLAGS\n"); */
2458//-- uFlagsRWU(cb, FlagsZCP, FlagsEmpty, FlagsEmpty);
2459//-- vg_assert(!sets_ZCP);
2460//-- }
2461//-- if (sets_ZCP) {
2462//-- /* VG_(printf)("!!! --- FPU insn which writes %EFLAGS\n"); */
2463//-- uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
2464//-- vg_assert(!uses_ZCP);
2465//-- }
2466//--
2467//-- DIP("fpu 0x%x:0x%x%s%s\n", (UInt)first_byte, (UInt)second_byte,
2468//-- uses_ZCP ? " -rZCP" : "",
2469//-- sets_ZCP ? " -wZCP" : "" );
2470//-- return eip;
2471//-- }
2472//--
2473//--
2474//-- /* Top-level handler for all FPU insns. On entry, eip points to the
2475//-- second byte of the insn. */
2476//-- static
2477//-- Addr dis_fpu ( UCodeBlock* cb,
2478//-- UChar sorb,
2479//-- UChar first_byte, Addr eip )
2480//-- {
2481//-- const Bool rd = False;
2482//-- const Bool wr = True;
2483//-- UChar second_byte = getUChar(eip);
2484//--
2485//-- /* Handle FSTSW %ax specially. */
2486//-- if (first_byte == 0xDF && second_byte == 0xE0) {
2487//-- Int t1 = newTemp(cb);
2488//-- uInstr0(cb, CALLM_S, 0);
2489//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t1);
2490//-- uLiteral(cb, 0);
2491//-- uInstr1(cb, PUSH, 4, TempReg, t1);
2492//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_fstsw_AX) );
2493//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
2494//-- uInstr1(cb, POP, 2, TempReg, t1);
2495//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
2496//-- uInstr0(cb, CALLM_E, 0);
2497//-- DIP("fstsw %%ax\n");
2498//-- eip++;
2499//-- return eip;
2500//-- }
2501//--
2502//-- /* Handle all non-memory FPU ops simply. */
2503//-- if (second_byte >= 0xC0)
2504//-- return dis_fpu_no_mem ( cb, eip, first_byte );
2505//--
2506//-- /* The insn references memory; need to determine
2507//-- whether it reads or writes, and at what size. */
2508//-- switch (first_byte) {
2509//--
2510//-- case 0xD8:
2511//-- switch ((second_byte >> 3) & 7) {
2512//-- case 0: /* FADDs */
2513//-- case 1: /* FMULs */
2514//-- case 2: /* FCOMs */
2515//-- case 3: /* FCOMPs */
2516//-- case 4: /* FSUBs */
2517//-- case 5: /* FSUBRs */
2518//-- case 6: /* FDIVs */
2519//-- case 7: /* FDIVRs */
2520//-- return dis_fpu_mem(cb, sorb, 4, rd, eip, first_byte);
2521//-- default:
2522//-- goto unhandled;
2523//-- }
2524//-- break;
2525//--
2526//-- case 0xD9:
2527//-- switch ((second_byte >> 3) & 7) {
2528//-- case 0: /* FLDs */
2529//-- return dis_fpu_mem(cb, sorb, 4, rd, eip, first_byte);
2530//-- case 2: /* FSTs */
2531//-- case 3: /* FSTPs */
2532//-- return dis_fpu_mem(cb, sorb, 4, wr, eip, first_byte);
2533//-- case 4: /* FLDENV */
2534//-- return dis_fpu_mem(cb, sorb, 28, rd, eip, first_byte);
2535//-- case 5: /* FLDCW */
2536//-- return dis_fpu_mem(cb, sorb, 2, rd, eip, first_byte);
2537//-- case 6: /* FNSTENV */
2538//-- return dis_fpu_mem(cb, sorb, 28, wr, eip, first_byte);
2539//-- case 7: /* FSTCW */
2540//-- /* HACK! FSTCW actually writes 2 bytes, not 4. glibc
2541//-- gets lots of moaning in __floor() if we do the right
2542//-- thing here. */
2543//-- /* Later ... hack disabled .. we do do the Right Thing. */
2544//-- return dis_fpu_mem(cb, sorb, /*4*/ 2, wr, eip, first_byte);
2545//-- default:
2546//-- goto unhandled;
2547//-- }
2548//-- break;
2549//--
2550//-- case 0xDA:
2551//-- switch ((second_byte >> 3) & 7) {
2552//-- case 0: /* FIADD dword-integer */
2553//-- case 1: /* FIMUL dword-integer */
2554//-- case 2: /* FICOM dword-integer */
2555//-- case 3: /* FICOMP dword-integer */
2556//-- case 4: /* FISUB dword-integer */
2557//-- case 5: /* FISUBR dword-integer */
2558//-- case 6: /* FIDIV dword-integer */
2559//-- case 7: /* FIDIVR dword-integer */
2560//-- return dis_fpu_mem(cb, sorb, 4, rd, eip, first_byte);
2561//-- default:
2562//-- goto unhandled;
2563//-- }
2564//-- break;
2565//--
2566//-- case 0xDB:
2567//-- switch ((second_byte >> 3) & 7) {
2568//-- case 0: /* FILD dword-integer */
2569//-- return dis_fpu_mem(cb, sorb, 4, rd, eip, first_byte);
2570//-- case 2: /* FIST dword-integer */
2571//-- return dis_fpu_mem(cb, sorb, 4, wr, eip, first_byte);
2572//-- case 3: /* FISTPl */
2573//-- return dis_fpu_mem(cb, sorb, 4, wr, eip, first_byte);
2574//-- case 5: /* FLD extended-real */
2575//-- return dis_fpu_mem(cb, sorb, 10, rd, eip, first_byte);
2576//-- case 7: /* FSTP extended-real */
2577//-- return dis_fpu_mem(cb, sorb, 10, wr, eip, first_byte);
2578//-- default:
2579//-- goto unhandled;
2580//-- }
2581//-- break;
2582//--
2583//-- case 0xDC:
2584//-- switch ((second_byte >> 3) & 7) {
2585//-- case 0: /* FADD double-real */
2586//-- case 1: /* FMUL double-real */
2587//-- case 2: /* FCOM double-real */
2588//-- case 3: /* FCOMP double-real */
2589//-- case 4: /* FSUB double-real */
2590//-- case 5: /* FSUBR double-real */
2591//-- case 6: /* FDIV double-real */
2592//-- case 7: /* FDIVR double-real */
2593//-- return dis_fpu_mem(cb, sorb, 8, rd, eip, first_byte);
2594//-- default:
2595//-- goto unhandled;
2596//-- }
2597//-- break;
2598//--
2599//-- case 0xDD:
2600//-- switch ((second_byte >> 3) & 7) {
2601//-- case 0: /* FLD double-real */
2602//-- return dis_fpu_mem(cb, sorb, 8, rd, eip, first_byte);
2603//-- case 2: /* FST double-real */
2604//-- case 3: /* FSTP double-real */
2605//-- return dis_fpu_mem(cb, sorb, 8, wr, eip, first_byte);
2606//-- case 4: /* FRSTOR */
2607//-- return dis_fpu_mem(cb, sorb, 108, rd, eip, first_byte);
2608//-- case 6: /* FSAVE */
2609//-- return dis_fpu_mem(cb, sorb, 108, wr, eip, first_byte);
2610//-- case 7: /* FSTSW */
2611//-- return dis_fpu_mem(cb, sorb, 2, wr, eip, first_byte);
2612//-- default:
2613//-- goto unhandled;
2614//-- }
2615//-- break;
2616//--
2617//-- case 0xDE:
2618//-- switch ((second_byte >> 3) & 7) {
2619//-- case 0: /* FIADD word-integer */
2620//-- case 1: /* FIMUL word-integer */
2621//-- case 2: /* FICOM word-integer */
2622//-- case 3: /* FICOMP word-integer */
2623//-- case 4: /* FISUB word-integer */
2624//-- case 5: /* FISUBR word-integer */
2625//-- case 6: /* FIDIV word-integer */
2626//-- case 7: /* FIDIVR word-integer */
2627//-- return dis_fpu_mem(cb, sorb, 2, rd, eip, first_byte);
2628//-- default:
2629//-- goto unhandled;
2630//-- }
2631//-- break;
2632//--
2633//-- case 0xDF:
2634//-- switch ((second_byte >> 3) & 7) {
2635//-- case 0: /* FILD word-integer */
2636//-- return dis_fpu_mem(cb, sorb, 2, rd, eip, first_byte);
2637//-- case 2: /* FIST word-integer */
2638//-- return dis_fpu_mem(cb, sorb, 2, wr, eip, first_byte);
2639//-- case 3: /* FISTP word-integer */
2640//-- return dis_fpu_mem(cb, sorb, 2, wr, eip, first_byte);
2641//-- case 5: /* FILD qword-integer */
2642//-- return dis_fpu_mem(cb, sorb, 8, rd, eip, first_byte);
2643//-- case 7: /* FISTP qword-integer */
2644//-- return dis_fpu_mem(cb, sorb, 8, wr, eip, first_byte);
2645//-- default:
2646//-- goto unhandled;
2647//-- }
2648//-- break;
2649//--
2650//-- default: goto unhandled;
2651//-- }
2652//--
2653//-- unhandled:
2654//-- VG_(printf)("dis_fpu: unhandled memory case 0x%2x:0x%2x(%d)\n",
2655//-- (UInt)first_byte, (UInt)second_byte,
2656//-- (UInt)((second_byte >> 3) & 7) );
2657//-- VG_(core_panic)("dis_fpu: unhandled opcodes");
2658//-- }
2659//--
2660//--
2661//-- /* Double length left shifts. Apparently only required in v-size (no
2662//-- b- variant). */
2663//-- static
2664//-- Addr dis_SHLRD_Gv_Ev ( UCodeBlock* cb,
2665//-- UChar sorb,
2666//-- Addr eip, UChar modrm,
2667//-- Int sz,
2668//-- Tag amt_tag, UInt amt_val,
2669//-- Bool left_shift )
2670//-- {
2671//-- /* amt_tag and amt_val denote either ArchReg(%CL) or a Literal.
2672//-- And eip on entry points at the modrm byte. */
2673//-- Int t, t1, t2, ta, helper;
2674//-- UInt pair;
2675//-- UChar dis_buf[50];
2676//--
2677//-- vg_assert(sz == 2 || sz == 4);
2678//--
2679//-- helper = left_shift
2680//-- ? (sz==4 ? VGOFF_(helper_shldl)
2681//-- : VGOFF_(helper_shldw))
2682//-- : (sz==4 ? VGOFF_(helper_shrdl)
2683//-- : VGOFF_(helper_shrdw));
2684//--
2685//-- /* Get the amount to be shifted by onto the stack. */
2686//-- t = newTemp(cb);
2687//-- t1 = newTemp(cb);
2688//-- t2 = newTemp(cb);
2689//-- if (amt_tag == ArchReg) {
2690//-- vg_assert(amt_val == R_CL);
2691//-- uInstr2(cb, GET, 1, ArchReg, amt_val, TempReg, t);
2692//-- } else {
2693//-- uInstr2(cb, MOV, 1, Literal, 0, TempReg, t);
2694//-- uLiteral(cb, amt_val);
2695//-- }
2696//--
2697//-- uInstr0(cb, CALLM_S, 0);
2698//-- uInstr1(cb, PUSH, 1, TempReg, t);
2699//--
2700//-- /* The E-part is the destination; this is shifted. The G-part
2701//-- supplies bits to be shifted into the E-part, but is not
2702//-- changed. */
2703//--
2704//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(modrm), TempReg, t1);
2705//-- uInstr1(cb, PUSH, sz, TempReg, t1);
2706//--
2707//-- if (epartIsReg(modrm)) {
2708//-- eip++;
2709//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t2);
2710//-- uInstr1(cb, PUSH, sz, TempReg, t2);
2711//-- uInstr1(cb, CALLM, 0, Lit16, helper);
2712//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
2713//-- uInstr1(cb, POP, sz, TempReg, t);
2714//-- uInstr2(cb, PUT, sz, TempReg, t, ArchReg, eregOfRM(modrm));
2715//-- DIP("sh%cd%c %%cl, %s, %s\n",
2716//-- ( left_shift ? 'l' : 'r' ), nameISize(sz),
2717//-- nameIReg(sz, gregOfRM(modrm)), nameIReg(sz, eregOfRM(modrm)));
2718//-- } else {
2719//-- pair = disAMode ( cb, sorb, eip, dis_buf );
2720//-- ta = LOW24(pair);
2721//-- eip += HI8(pair);
2722//-- uInstr2(cb, LOAD, sz, TempReg, ta, TempReg, t2);
2723//-- uInstr1(cb, PUSH, sz, TempReg, t2);
2724//-- uInstr1(cb, CALLM, 0, Lit16, helper);
2725//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
2726//-- uInstr1(cb, POP, sz, TempReg, t);
2727//-- uInstr2(cb, STORE, sz, TempReg, t, TempReg, ta);
2728//-- DIP("sh%cd%c %%cl, %s, %s\n", ( left_shift ? 'l' : 'r' ),
2729//-- nameISize(sz), nameIReg(sz, gregOfRM(modrm)), dis_buf);
2730//-- }
2731//--
2732//-- if (amt_tag == Literal) eip++;
2733//-- uInstr1(cb, CLEAR, 0, Lit16, 8);
2734//--
2735//-- uInstr0(cb, CALLM_E, 0);
2736//-- return eip;
2737//-- }
2738//--
2739//--
2740//-- /* Handle BT/BTS/BTR/BTC Gv, Ev. Apparently b-size is not
2741//-- required. */
2742//--
2743//-- typedef enum { BtOpNone, BtOpSet, BtOpReset, BtOpComp } BtOp;
2744//--
2745//-- static Char* nameBtOp ( BtOp op )
2746//-- {
2747//-- switch (op) {
2748//-- case BtOpNone: return "";
2749//-- case BtOpSet: return "s";
2750//-- case BtOpReset: return "r";
2751//-- case BtOpComp: return "c";
2752//-- default: VG_(core_panic)("nameBtOp");
2753//-- }
2754//-- }
2755//--
2756//--
2757//-- static
2758//-- Addr dis_bt_G_E ( UCodeBlock* cb,
2759//-- UChar sorb,
2760//-- Int sz, Addr eip, BtOp op )
2761//-- {
2762//-- UInt pair;
2763//-- Char dis_buf[50];
2764//-- UChar modrm;
2765//--
2766//-- Int t_addr, t_bitno, t_mask, t_fetched, t_esp, temp, lit;
2767//--
2768//-- vg_assert(sz == 2 || sz == 4);
2769//--
2770//-- t_addr = t_bitno = t_mask
2771//-- = t_fetched = t_esp = temp = INVALID_TEMPREG;
2772//--
2773//-- t_fetched = newTemp(cb);
2774//-- t_bitno = newTemp(cb);
2775//-- temp = newTemp(cb);
2776//-- lit = newTemp(cb);
2777//--
2778//-- modrm = getUChar(eip);
2779//--
2780//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(modrm), TempReg, t_bitno);
2781//--
2782//-- if (sz == 2) {
2783//-- uInstr1(cb, WIDEN, 4, TempReg, t_bitno);
2784//-- uWiden(cb, 2, False);
2785//-- }
2786//--
2787//-- if (epartIsReg(modrm)) {
2788//-- eip++;
2789//-- /* Get it onto the client's stack. */
2790//-- t_esp = newTemp(cb);
2791//-- t_addr = newTemp(cb);
2792//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t_esp);
2793//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t_esp);
2794//-- uLiteral(cb, sz);
2795//-- uInstr2(cb, PUT, 4, TempReg, t_esp, ArchReg, R_ESP);
2796//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, temp);
2797//-- uInstr2(cb, STORE, sz, TempReg, temp, TempReg, t_esp);
2798//-- /* Make t_addr point at it. */
2799//-- uInstr2(cb, MOV, 4, TempReg, t_esp, TempReg, t_addr);
2800//-- /* Mask out upper bits of the shift amount, since we're doing a
2801//-- reg. */
2802//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, lit);
2803//-- uLiteral(cb, sz == 4 ? 31 : 15);
2804//-- uInstr2(cb, AND, 4, TempReg, lit, TempReg, t_bitno);
2805//-- } else {
2806//-- pair = disAMode ( cb, sorb, eip, dis_buf );
2807//-- t_addr = LOW24(pair);
2808//-- eip += HI8(pair);
2809//-- }
2810//--
2811//-- /* At this point: t_addr points to the address being operated on. If
2812//-- it was a reg, we will have pushed it onto the client's stack.
2813//-- t_bitno is the bit number, suitable masked in the case of a reg. */
2814//--
2815//-- /* Now the main sequence. */
2816//--
2817//-- uInstr2(cb, MOV, 4, TempReg, t_bitno, TempReg, temp);
2818//-- uInstr2(cb, SAR, 4, Literal, 0, TempReg, temp);
2819//-- uLiteral(cb, 3);
2820//-- uInstr2(cb, ADD, 4, TempReg, temp, TempReg, t_addr);
2821//-- /* t_addr now holds effective address */
2822//--
2823//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, lit);
2824//-- uLiteral(cb, 7);
2825//-- uInstr2(cb, AND, 4, TempReg, lit, TempReg, t_bitno);
2826//-- /* t_bitno contains offset of bit within byte */
2827//--
2828//-- if (op != BtOpNone) {
2829//-- t_mask = newTemp(cb);
2830//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_mask);
2831//-- uLiteral(cb, 1);
2832//-- uInstr2(cb, SHL, 4, TempReg, t_bitno, TempReg, t_mask);
2833//-- }
2834//-- /* t_mask is now a suitable byte mask */
2835//--
2836//-- uInstr2(cb, LOAD, 1, TempReg, t_addr, TempReg, t_fetched);
2837//-- if (op != BtOpNone) {
2838//-- uInstr2(cb, MOV, 4, TempReg, t_fetched, TempReg, temp);
2839//-- switch (op) {
2840//-- case BtOpSet:
2841//-- uInstr2(cb, OR, 4, TempReg, t_mask, TempReg, temp);
2842//-- break;
2843//-- case BtOpComp:
2844//-- uInstr2(cb, XOR, 4, TempReg, t_mask, TempReg, temp);
2845//-- break;
2846//-- case BtOpReset:
2847//-- uInstr1(cb, NOT, 4, TempReg, t_mask);
2848//-- uInstr2(cb, AND, 4, TempReg, t_mask, TempReg, temp);
2849//-- break;
2850//-- default:
2851//-- VG_(core_panic)("dis_bt_G_E");
2852//-- }
2853//-- uInstr2(cb, STORE, 1, TempReg, temp, TempReg, t_addr);
2854//-- }
2855//--
2856//-- /* Side effect done; now get selected bit into Carry flag */
2857//--
2858//-- uInstr2(cb, SHR, 4, TempReg, t_bitno, TempReg, t_fetched);
2859//-- /* at bit 0 of fetched */
2860//--
2861//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, lit);
2862//-- uLiteral(cb, 1);
2863//-- uInstr2(cb, AND, 4, TempReg, lit, TempReg, t_fetched);
2864//-- /* t_fetched is now 1 or 0 */
2865//--
2866//-- /* NEG is a handy way to convert zero/nonzero into the carry
2867//-- flag. */
2868//-- uInstr1(cb, NEG, 4, TempReg, t_fetched);
2869//-- setFlagsFromUOpcode(cb, NEG);
2870//-- /* t_fetched is now in carry flag */
2871//--
2872//-- /* Move reg operand from stack back to reg */
2873//-- if (epartIsReg(modrm)) {
2874//-- /* t_esp still points at it. */
2875//-- uInstr2(cb, LOAD, sz, TempReg, t_esp, TempReg, temp);
2876//-- uInstr2(cb, PUT, sz, TempReg, temp, ArchReg, eregOfRM(modrm));
2877//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t_esp);
2878//-- uLiteral(cb, sz);
2879//-- uInstr2(cb, PUT, 4, TempReg, t_esp, ArchReg, R_ESP);
2880//-- }
2881//--
2882//-- DIP("bt%s%c %s, %s\n",
2883//-- nameBtOp(op), nameISize(sz), nameIReg(sz, gregOfRM(modrm)),
2884//-- ( epartIsReg(modrm) ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ) );
2885//--
2886//-- return eip;
2887//-- }
2888//--
2889//--
2890//--
2891//-- /* Handle BSF/BSR. Only v-size seems necessary. */
2892//-- static
2893//-- Addr dis_bs_E_G ( UCodeBlock* cb,
2894//-- UChar sorb,
2895//-- Int sz, Addr eip, Bool fwds )
2896//-- {
2897//-- Int t, t1, ta, helper;
2898//-- UInt pair;
2899//-- Char dis_buf[50];
2900//-- UChar modrm;
2901//-- Bool isReg;
2902//--
2903//-- vg_assert(sz == 2 || sz == 4);
2904//--
2905//-- if (fwds)
2906//-- helper = sz == 2 ? VGOFF_(helper_bsfw) : VGOFF_(helper_bsfl);
2907//-- else
2908//-- helper = sz == 2 ? VGOFF_(helper_bsrw) : VGOFF_(helper_bsrl);
2909//--
2910//-- modrm = getUChar(eip);
2911//-- t1 = newTemp(cb);
2912//-- t = newTemp(cb);
2913//--
2914//-- uInstr0(cb, CALLM_S, 0);
2915//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(modrm), TempReg, t1);
2916//-- uInstr1(cb, PUSH, sz, TempReg, t1);
2917//--
2918//-- isReg = epartIsReg(modrm);
2919//-- if (isReg) {
2920//-- eip++;
2921//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t);
2922//-- } else {
2923//-- pair = disAMode ( cb, sorb, eip, dis_buf );
2924//-- ta = LOW24(pair);
2925//-- eip += HI8(pair);
2926//-- uInstr2(cb, LOAD, sz, TempReg, ta, TempReg, t);
2927//-- }
2928//-- DIP("bs%c%c %s, %s\n",
2929//-- fwds ? 'f' : 'r', nameISize(sz),
2930//-- ( isReg ? nameIReg(sz, eregOfRM(modrm)) : dis_buf ),
2931//-- nameIReg(sz, gregOfRM(modrm)));
2932//--
2933//-- uInstr1(cb, PUSH, sz, TempReg, t);
2934//-- uInstr1(cb, CALLM, 0, Lit16, helper);
2935//-- uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsOSACP);
2936//-- uInstr1(cb, POP, sz, TempReg, t);
2937//-- uInstr1(cb, POP, sz, TempReg, t);
2938//-- uInstr2(cb, PUT, sz, TempReg, t, ArchReg, gregOfRM(modrm));
2939//-- uInstr0(cb, CALLM_E, 0);
2940//--
2941//-- return eip;
2942//-- }
2943//--
2944//--
2945//-- static
2946//-- void codegen_xchg_eAX_Reg ( UCodeBlock* cb, Int sz, Int reg )
2947//-- {
2948//-- Int t1, t2;
2949//-- vg_assert(sz == 2 || sz == 4);
2950//-- t1 = newTemp(cb);
2951//-- t2 = newTemp(cb);
2952//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1);
2953//-- uInstr2(cb, GET, sz, ArchReg, reg, TempReg, t2);
2954//-- uInstr2(cb, PUT, sz, TempReg, t2, ArchReg, R_EAX);
2955//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, reg);
2956//-- DIP("xchg%c %s, %s\n",
2957//-- nameISize(sz), nameIReg(sz, R_EAX), nameIReg(sz, reg));
2958//-- }
2959//--
2960//--
2961//-- static
2962//-- void codegen_SAHF ( UCodeBlock* cb )
2963//-- {
2964//-- Int t = newTemp(cb);
2965//-- Int t2 = newTemp(cb);
2966//-- uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, t);
2967//--
2968//-- /* Mask out parts of t not corresponding to %AH. This stops the
2969//-- instrumenter complaining if they are undefined. Otherwise, the
2970//-- instrumenter would check all 32 bits of t at the PUSH, which
2971//-- could be the cause of incorrect warnings. Discovered by Daniel
2972//-- Veillard <veillard@redhat.com>.
2973//-- */
2974//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
2975//-- uLiteral(cb, 0x0000FF00);
2976//-- uInstr2(cb, AND, 4, TempReg, t2, TempReg, t);
2977//-- /* We deliberately don't set the condition codes here, since this
2978//-- AND is purely internal to Valgrind and nothing to do with the
2979//-- client's state. */
2980//--
2981//-- uInstr0(cb, CALLM_S, 0);
2982//-- uInstr1(cb, PUSH, 4, TempReg, t);
2983//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_SAHF));
2984//-- uFlagsRWU(cb, FlagsEmpty, FlagsSZACP, FlagsEmpty);
2985//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
2986//-- uInstr0(cb, CALLM_E, 0);
2987//-- }
2988//--
2989//-- static
2990//-- void codegen_LAHF ( UCodeBlock* cb )
2991//-- {
2992//-- Int t = newTemp(cb);
2993//--
2994//-- /* Pushed arg is ignored, it just provides somewhere to put the
2995//-- return value. */
2996//-- uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, t);
2997//-- uInstr0(cb, CALLM_S, 0);
2998//-- uInstr1(cb, PUSH, 4, TempReg, t);
2999//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_LAHF));
3000//-- uFlagsRWU(cb, FlagsSZACP, FlagsEmpty, FlagsEmpty);
3001//-- uInstr1(cb, POP, 4, TempReg, t);
3002//-- uInstr0(cb, CALLM_E, 0);
3003//--
3004//-- /* At this point, the %ah sub-register in %eax has been updated,
3005//-- the rest is the same, so do a PUT of the whole thing. */
3006//-- uInstr2(cb, PUT, 4, TempReg, t, ArchReg, R_EAX);
3007//-- }
3008//--
3009//--
3010//-- static
3011//-- Addr dis_cmpxchg_G_E ( UCodeBlock* cb,
3012//-- UChar sorb,
3013//-- Int size,
3014//-- Addr eip0 )
3015//-- {
3016//-- Int ta, junk, dest, src, acc;
3017//-- UChar dis_buf[50];
3018//-- UChar rm;
3019//--
3020//-- rm = getUChar(eip0);
3021//-- acc = newTemp(cb);
3022//-- src = newTemp(cb);
3023//-- dest = newTemp(cb);
3024//-- junk = newTemp(cb);
3025//-- /* Only needed to get gcc's dataflow analyser off my back. */
3026//-- ta = INVALID_TEMPREG;
3027//--
3028//-- if (epartIsReg(rm)) {
3029//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, dest);
3030//-- eip0++;
3031//-- DIP("cmpxchg%c %s,%s\n", nameISize(size),
3032//-- nameIReg(size,gregOfRM(rm)),
3033//-- nameIReg(size,eregOfRM(rm)) );
3034//-- } else {
3035//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf );
3036//-- ta = LOW24(pair);
3037//-- uInstr2(cb, LOAD, size, TempReg, ta, TempReg, dest);
3038//-- eip0 += HI8(pair);
3039//-- DIP("cmpxchg%c %s,%s\n", nameISize(size),
3040//-- nameIReg(size,gregOfRM(rm)), dis_buf);
3041//-- }
3042//--
3043//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, src);
3044//-- uInstr2(cb, GET, size, ArchReg, R_EAX, TempReg, acc);
3045//-- uInstr2(cb, MOV, 4, TempReg, acc, TempReg, junk);
3046//-- uInstr2(cb, SUB, size, TempReg, dest, TempReg, junk);
3047//-- setFlagsFromUOpcode(cb, SUB);
3048//--
3049//-- uInstr2(cb, CMOV, 4, TempReg, src, TempReg, dest);
3050//-- uCond(cb, CondZ);
3051//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
3052//-- uInstr2(cb, CMOV, 4, TempReg, dest, TempReg, acc);
3053//-- uCond(cb, CondNZ);
3054//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
3055//--
3056//-- uInstr2(cb, PUT, size, TempReg, acc, ArchReg, R_EAX);
3057//-- if (epartIsReg(rm)) {
3058//-- uInstr2(cb, PUT, size, TempReg, dest, ArchReg, eregOfRM(rm));
3059//-- } else {
3060//-- uInstr2(cb, STORE, size, TempReg, dest, TempReg, ta);
3061//-- }
3062//--
3063//-- return eip0;
3064//-- }
3065//--
3066//--
3067//-- static
3068//-- Addr dis_cmpxchg8b ( UCodeBlock* cb,
3069//-- UChar sorb,
3070//-- Addr eip0 )
3071//-- {
3072//-- Int tal, tah, junkl, junkh, destl, desth, srcl, srch, accl, acch;
3073//-- UChar dis_buf[50];
3074//-- UChar rm;
3075//-- UInt pair;
3076//--
3077//-- rm = getUChar(eip0);
3078//-- accl = newTemp(cb);
3079//-- acch = newTemp(cb);
3080//-- srcl = newTemp(cb);
3081//-- srch = newTemp(cb);
3082//-- destl = newTemp(cb);
3083//-- desth = newTemp(cb);
3084//-- junkl = newTemp(cb);
3085//-- junkh = newTemp(cb);
3086//--
3087//-- vg_assert(!epartIsReg(rm));
3088//--
3089//-- pair = disAMode ( cb, sorb, eip0, dis_buf );
3090//-- tal = LOW24(pair);
3091//-- tah = newTemp(cb);
3092//-- uInstr2(cb, MOV, 4, TempReg, tal, TempReg, tah);
3093//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, tah);
3094//-- uLiteral(cb, 4);
3095//-- eip0 += HI8(pair);
3096//-- DIP("cmpxchg8b %s\n", dis_buf);
3097//--
3098//-- uInstr0(cb, CALLM_S, 0);
3099//--
3100//-- uInstr2(cb, LOAD, 4, TempReg, tah, TempReg, desth);
3101//-- uInstr1(cb, PUSH, 4, TempReg, desth);
3102//-- uInstr2(cb, LOAD, 4, TempReg, tal, TempReg, destl);
3103//-- uInstr1(cb, PUSH, 4, TempReg, destl);
3104//-- uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, srch);
3105//-- uInstr1(cb, PUSH, 4, TempReg, srch);
3106//-- uInstr2(cb, GET, 4, ArchReg, R_EBX, TempReg, srcl);
3107//-- uInstr1(cb, PUSH, 4, TempReg, srcl);
3108//-- uInstr2(cb, GET, 4, ArchReg, R_EDX, TempReg, acch);
3109//-- uInstr1(cb, PUSH, 4, TempReg, acch);
3110//-- uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, accl);
3111//-- uInstr1(cb, PUSH, 4, TempReg, accl);
3112//--
3113//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_cmpxchg8b));
3114//-- uFlagsRWU(cb, FlagsEmpty, FlagZ, FlagsEmpty);
3115//--
3116//-- uInstr1(cb, POP, 4, TempReg, accl);
3117//-- uInstr2(cb, PUT, 4, TempReg, accl, ArchReg, R_EAX);
3118//-- uInstr1(cb, POP, 4, TempReg, acch);
3119//-- uInstr2(cb, PUT, 4, TempReg, acch, ArchReg, R_EDX);
3120//-- uInstr1(cb, POP, 4, TempReg, srcl);
3121//-- uInstr2(cb, PUT, 4, TempReg, srcl, ArchReg, R_EBX);
3122//-- uInstr1(cb, POP, 4, TempReg, srch);
3123//-- uInstr2(cb, PUT, 4, TempReg, srch, ArchReg, R_ECX);
3124//-- uInstr1(cb, POP, 4, TempReg, destl);
3125//-- uInstr2(cb, STORE, 4, TempReg, destl, TempReg, tal);
3126//-- uInstr1(cb, POP, 4, TempReg, desth);
3127//-- uInstr2(cb, STORE, 4, TempReg, desth, TempReg, tah);
3128//--
3129//-- uInstr0(cb, CALLM_E, 0);
3130//--
3131//-- return eip0;
3132//-- }
3133//--
3134//--
3135//-- /* Handle conditional move instructions of the form
3136//-- cmovcc E(reg-or-mem), G(reg)
3137//--
3138//-- E(src) is reg-or-mem
3139//-- G(dst) is reg.
3140//--
3141//-- If E is reg, --> GET %E, tmps
3142//-- GET %G, tmpd
3143//-- CMOVcc tmps, tmpd
3144//-- PUT tmpd, %G
3145//--
3146//-- If E is mem --> (getAddr E) -> tmpa
3147//-- LD (tmpa), tmps
3148//-- GET %G, tmpd
3149//-- CMOVcc tmps, tmpd
3150//-- PUT tmpd, %G
3151//-- */
3152//-- static
3153//-- Addr dis_cmov_E_G ( UCodeBlock* cb,
3154//-- UChar sorb,
3155//-- Int size,
3156//-- Condcode cond,
3157//-- Addr eip0 )
3158//-- {
3159//-- UChar rm = getUChar(eip0);
3160//-- UChar dis_buf[50];
3161//--
3162//-- Int tmps = newTemp(cb);
3163//-- Int tmpd = newTemp(cb);
3164//--
3165//-- if (epartIsReg(rm)) {
3166//-- uInstr2(cb, GET, size, ArchReg, eregOfRM(rm), TempReg, tmps);
3167//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tmpd);
3168//-- uInstr2(cb, CMOV, 4, TempReg, tmps, TempReg, tmpd);
3169//-- uCond(cb, cond);
3170//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
3171//-- uInstr2(cb, PUT, size, TempReg, tmpd, ArchReg, gregOfRM(rm));
3172//-- DIP("cmov%c%s %s,%s\n", nameISize(size),
3173//-- VG_(name_UCondcode)(cond),
3174//-- nameIReg(size,eregOfRM(rm)),
3175//-- nameIReg(size,gregOfRM(rm)));
3176//-- return 1+eip0;
3177//-- }
3178//--
3179//-- /* E refers to memory */
3180//-- {
3181//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf );
3182//-- Int tmpa = LOW24(pair);
3183//-- uInstr2(cb, LOAD, size, TempReg, tmpa, TempReg, tmps);
3184//-- uInstr2(cb, GET, size, ArchReg, gregOfRM(rm), TempReg, tmpd);
3185//-- uInstr2(cb, CMOV, 4, TempReg, tmps, TempReg, tmpd);
3186//-- uCond(cb, cond);
3187//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
3188//-- uInstr2(cb, PUT, size, TempReg, tmpd, ArchReg, gregOfRM(rm));
3189//-- DIP("cmov%c%s %s,%s\n", nameISize(size),
3190//-- VG_(name_UCondcode)(cond),
3191//-- dis_buf,
3192//-- nameIReg(size,gregOfRM(rm)));
3193//-- return HI8(pair)+eip0;
3194//-- }
3195//-- }
3196//--
3197//--
3198//-- static
3199//-- Addr dis_xadd_G_E ( UCodeBlock* cb,
3200//-- UChar sorb,
3201//-- Int sz,
3202//-- Addr eip0 )
3203//-- {
3204//-- UChar rm = getUChar(eip0);
3205//-- UChar dis_buf[50];
3206//--
3207//-- Int tmpd = newTemp(cb);
3208//-- Int tmpt = newTemp(cb);
3209//--
3210//-- if (epartIsReg(rm)) {
3211//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(rm), TempReg, tmpd);
3212//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(rm), TempReg, tmpt);
3213//-- uInstr2(cb, ADD, sz, TempReg, tmpd, TempReg, tmpt);
3214//-- setFlagsFromUOpcode(cb, ADD);
3215//-- uInstr2(cb, PUT, sz, TempReg, tmpt, ArchReg, eregOfRM(rm));
3216//-- uInstr2(cb, PUT, sz, TempReg, tmpd, ArchReg, gregOfRM(rm));
3217//-- DIP("xadd%c %s, %s\n",
3218//-- nameISize(sz), nameIReg(sz,gregOfRM(rm)), nameIReg(sz,eregOfRM(rm)));
3219//-- return 1+eip0;
3220//-- } else {
3221//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf );
3222//-- Int tmpa = LOW24(pair);
3223//-- uInstr2(cb, LOAD, sz, TempReg, tmpa, TempReg, tmpd);
3224//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(rm), TempReg, tmpt);
3225//-- uInstr2(cb, ADD, sz, TempReg, tmpd, TempReg, tmpt);
3226//-- setFlagsFromUOpcode(cb, ADD);
3227//-- uInstr2(cb, STORE, sz, TempReg, tmpt, TempReg, tmpa);
3228//-- uInstr2(cb, PUT, sz, TempReg, tmpd, ArchReg, gregOfRM(rm));
3229//-- DIP("xadd%c %s, %s\n",
3230//-- nameISize(sz), nameIReg(sz,gregOfRM(rm)), dis_buf);
3231//-- return HI8(pair)+eip0;
3232//-- }
3233//-- }
3234//--
3235//--
3236//-- /* Moves of Ew into a segment register.
3237//-- mov Ew, Sw meaning
3238//-- mov reg-or-mem, reg
3239//-- Is passed the a ptr to the modRM byte, and the data size. Returns
3240//-- the address advanced completely over this instruction.
3241//--
3242//-- Ew(src) is reg-or-mem
3243//-- Sw(dst) is seg reg.
3244//--
3245//-- If E is reg, --> GETw %Ew, tmpv
3246//-- PUTSEG tmpv, %Sw
3247//--
3248//-- If E is mem --> (getAddr E) -> tmpa
3249//-- LDw (tmpa), tmpb
3250//-- PUTSEG tmpb, %Sw
3251//-- */
3252//-- static
3253//-- Addr dis_mov_Ew_Sw ( UCodeBlock* cb,
3254//-- UChar sorb,
3255//-- Addr eip0 )
3256//-- {
3257//-- UChar rm = getUChar(eip0);
3258//-- UChar dis_buf[50];
3259//--
3260//-- if (epartIsReg(rm)) {
3261//-- Int tmpv = newTemp(cb);
3262//-- uInstr2(cb, GET, 2, ArchReg, eregOfRM(rm), TempReg, tmpv);
3263//-- uInstr2(cb, PUTSEG, 2, TempReg, tmpv, ArchRegS, gregOfRM(rm));
3264//-- DIP("movw %s,%s\n", nameIReg(2,eregOfRM(rm)), nameSReg(gregOfRM(rm)));
3265//-- return 1+eip0;
3266//-- }
3267//--
3268//-- /* E refers to memory */
3269//-- {
3270//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf );
3271//-- Int tmpa = LOW24(pair);
3272//-- Int tmpb = newTemp(cb);
3273//-- uInstr2(cb, LOAD, 2, TempReg, tmpa, TempReg, tmpb);
3274//-- uInstr2(cb, PUTSEG, 2, TempReg, tmpb, ArchRegS, gregOfRM(rm));
3275//-- DIP("movw %s,%s\n", dis_buf,nameSReg(gregOfRM(rm)));
3276//-- return HI8(pair)+eip0;
3277//-- }
3278//-- }
3279//--
3280//--
3281//-- /* Moves of a segment register to Ew.
3282//-- mov Sw, Ew meaning
3283//-- mov reg, reg-or-mem
3284//-- Is passed the a ptr to the modRM byte, and the data size. Returns
3285//-- the address advanced completely over this instruction.
3286//--
3287//-- Sw(src) is seg reg.
3288//-- Ew(dst) is reg-or-mem
3289//--
3290//-- If E is reg, --> GETSEG %Sw, tmp
3291//-- PUTW tmp, %Ew
3292//--
3293//-- If E is mem, --> (getAddr E) -> tmpa
3294//-- GETSEG %Sw, tmpv
3295//-- STW tmpv, (tmpa)
3296//-- */
3297//-- static
3298//-- Addr dis_mov_Sw_Ew ( UCodeBlock* cb,
3299//-- UChar sorb,
3300//-- Addr eip0 )
3301//-- {
3302//-- UChar rm = getUChar(eip0);
3303//-- UChar dis_buf[50];
3304//--
3305//-- if (epartIsReg(rm)) {
3306//-- Int tmpv = newTemp(cb);
3307//-- uInstr2(cb, GETSEG, 2, ArchRegS, gregOfRM(rm), TempReg, tmpv);
3308//-- uInstr2(cb, PUT, 2, TempReg, tmpv, ArchReg, eregOfRM(rm));
3309//-- DIP("movw %s,%s\n", nameSReg(gregOfRM(rm)), nameIReg(2,eregOfRM(rm)));
3310//-- return 1+eip0;
3311//-- }
3312//--
3313//-- /* E refers to memory */
3314//-- {
3315//-- UInt pair = disAMode ( cb, sorb, eip0, dis_buf );
3316//-- Int tmpa = LOW24(pair);
3317//-- Int tmpv = newTemp(cb);
3318//-- uInstr2(cb, GETSEG, 2, ArchRegS, gregOfRM(rm), TempReg, tmpv);
3319//-- uInstr2(cb, STORE, 2, TempReg, tmpv, TempReg, tmpa);
3320//-- DIP("mov %s,%s\n", nameSReg(gregOfRM(rm)), dis_buf);
3321//-- return HI8(pair)+eip0;
3322//-- }
3323//-- }
3324//--
3325//--
3326//--
3327//-- /* Simple MMX operations, either
3328//-- op (src)mmxreg, (dst)mmxreg
3329//-- or
3330//-- op (src)address, (dst)mmxreg
3331//-- opc is the byte following the 0x0F prefix.
3332//-- */
3333//-- static
3334//-- Addr dis_MMXop_regmem_to_reg ( UCodeBlock* cb,
3335//-- UChar sorb,
3336//-- Addr eip,
3337//-- UChar opc,
3338//-- Char* name,
3339//-- Bool show_granularity )
3340//-- {
3341//-- Char dis_buf[50];
3342//-- UChar modrm = getUChar(eip);
3343//-- Bool isReg = epartIsReg(modrm);
3344//--
3345//-- if (isReg) {
3346//-- eip++;
3347//-- uInstr1(cb, MMX2, 0,
3348//-- Lit16,
3349//-- (((UShort)(opc)) << 8) | ((UShort)modrm) );
3350//-- } else {
3351//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3352//-- Int tmpa = LOW24(pair);
3353//-- eip += HI8(pair);
3354//-- uInstr2(cb, MMX2_MemRd, 8,
3355//-- Lit16,
3356//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
3357//-- TempReg, tmpa);
3358//-- }
3359//--
3360//-- DIP("%s%s %s, %s\n",
3361//-- name, show_granularity ? nameMMXGran(opc & 3) : (Char*)"",
3362//-- ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
3363//-- nameMMXReg(gregOfRM(modrm)) );
3364//--
3365//-- return eip;
3366//-- }
3367//--
3368//--
3369//-- /* Simple MMX operations, either
3370//-- op (src)mmxreg, (dst)mmxreg
3371//-- or
3372//-- op (src)address, (dst)mmxreg
3373//-- opc is the byte following the 0x0F prefix.
3374//-- */
3375//-- static
3376//-- Addr dis_MMXop_regmem_to_reg_Imm8 ( UCodeBlock* cb,
3377//-- UChar sorb,
3378//-- Addr eip,
3379//-- UChar opc,
3380//-- Char* name,
3381//-- Bool show_granularity )
3382//-- {
3383//-- Char dis_buf[50];
3384//-- UChar modrm = getUChar(eip);
3385//-- UChar imm8;
3386//-- Bool isReg = epartIsReg(modrm);
3387//--
3388//-- if (isReg) {
3389//-- eip++;
3390//-- imm8 = getUChar(eip);
3391//-- eip++;
3392//-- uInstr2(cb, MMX3, 0,
3393//-- Lit16,
3394//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
3395//-- Lit16,
3396//-- ((UShort)imm8));
3397//-- } else {
3398//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3399//-- Int tmpa = LOW24(pair);
3400//-- eip += HI8(pair);
3401//-- imm8 = getUChar(eip);
3402//-- eip++;
3403//-- uInstr3(cb, MMX2a1_MemRd, 8,
3404//-- Lit16,
3405//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
3406//-- Lit16,
3407//-- ((UShort)imm8),
3408//-- TempReg, tmpa);
3409//-- }
3410//--
3411//-- DIP("%s%s %s, %s, $%d\n",
3412//-- name, show_granularity ? nameMMXGran(opc & 3) : (Char*)"",
3413//-- ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
3414//-- nameMMXReg(gregOfRM(modrm)), (Int)imm8 );
3415//--
3416//-- return eip;
3417//-- }
3418//--
3419//--
3420//--
3421//-- /* Simple SSE operations, either
3422//-- op (src)xmmreg, (dst)xmmreg
3423//-- or
3424//-- op (src)address, (dst)xmmreg
3425//-- 3 opcode bytes.
3426//-- Supplied eip points to the first address mode byte.
3427//-- */
3428//-- static
3429//-- Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb,
3430//-- UChar sorb,
3431//-- Addr eip,
3432//-- Int sz,
3433//-- Char* name,
3434//-- UChar opc1,
3435//-- UChar opc2,
3436//-- UChar opc3 )
3437//-- {
3438//-- Char dis_buf[50];
3439//-- UChar modrm = getUChar(eip);
3440//-- Bool isReg = epartIsReg(modrm);
3441//--
3442//-- if (isReg) {
3443//-- /* Completely internal SSE insn. */
3444//-- uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */
3445//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3446//-- Lit16, (((UShort)opc3) << 8) | (UShort)modrm );
3447//-- eip++;
3448//-- } else {
3449//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3450//-- Int tmpa = LOW24(pair);
3451//-- eip += HI8(pair);
3452//-- uInstr3(cb, SSE3a_MemRd, sz,
3453//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3454//-- Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
3455//-- TempReg, tmpa);
3456//-- }
3457//--
3458//-- DIP("%s %s, %s\n",
3459//-- name,
3460//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3461//-- nameXMMReg(gregOfRM(modrm)) );
3462//--
3463//-- return eip;
3464//-- }
3465//--
3466//--
3467//-- /* Simple SSE operations, either
3468//-- op (src)xmmreg, (dst)xmmreg
3469//-- or
3470//-- op (src)address, (dst)xmmreg
3471//-- 2 opcode bytes.
3472//-- Supplied eip points to the first address mode byte.
3473//-- */
3474//-- static
3475//-- Addr dis_SSE2_reg_or_mem ( UCodeBlock* cb,
3476//-- UChar sorb,
3477//-- Addr eip,
3478//-- Int sz,
3479//-- Char* name,
3480//-- UChar opc1,
3481//-- UChar opc2 )
3482//-- {
3483//-- Char dis_buf[50];
3484//-- UChar modrm = getUChar(eip);
3485//-- Bool isReg = epartIsReg(modrm);
3486//--
3487//-- if (isReg) {
3488//-- /* Completely internal SSE insn. */
3489//-- uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
3490//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3491//-- Lit16, (UShort)modrm );
3492//-- eip++;
3493//-- } else {
3494//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3495//-- Int tmpa = LOW24(pair);
3496//-- eip += HI8(pair);
3497//-- uInstr3(cb, SSE2a_MemRd, sz,
3498//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3499//-- Lit16, (UShort)modrm,
3500//-- TempReg, tmpa);
3501//-- }
3502//-- DIP("%s %s, %s\n",
3503//-- name,
3504//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3505//-- nameXMMReg(gregOfRM(modrm)) );
3506//--
3507//-- return eip;
3508//-- }
3509//--
3510//--
3511//-- /* Simple SSE operations, either
3512//-- op (src)xmmreg, (dst)xmmreg
3513//-- or
3514//-- op (src)address, (dst)xmmreg
3515//-- 2 opcode bytes and an 8-bit immediate after the amode.
3516//-- Supplied eip points to the first address mode byte.
3517//-- */
3518//-- static
3519//-- Addr dis_SSE2_reg_or_mem_Imm8 ( UCodeBlock* cb,
3520//-- UChar sorb,
3521//-- Addr eip,
3522//-- Int sz,
3523//-- Char* name,
3524//-- UChar opc1,
3525//-- UChar opc2 )
3526//-- {
3527//-- Char dis_buf[50];
3528//-- UChar modrm = getUChar(eip);
3529//-- UChar imm8;
3530//-- Bool isReg = epartIsReg(modrm);
3531//--
3532//-- if (isReg) {
3533//-- /* Completely internal SSE insn. */
3534//-- eip++;
3535//-- imm8 = getUChar(eip);
3536//-- uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */
3537//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3538//-- Lit16, (((UShort)modrm) << 8) | (UShort)imm8 );
3539//-- eip++;
3540//-- } else {
3541//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3542//-- Int tmpa = LOW24(pair);
3543//-- eip += HI8(pair);
3544//-- imm8 = getUChar(eip);
3545//-- eip++;
3546//-- uInstr3(cb, SSE2a1_MemRd, sz,
3547//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3548//-- Lit16, (((UShort)(modrm)) << 8) | ((UShort)imm8),
3549//-- TempReg, tmpa);
3550//-- }
3551//-- DIP("%s %s, %s, $%d\n",
3552//-- name, ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3553//-- nameXMMReg(gregOfRM(modrm)), (Int)imm8 );
3554//-- return eip;
3555//-- }
3556//--
3557//--
3558//-- /* Simple SSE operations, either
3559//-- op (src)xmmreg, (dst)xmmreg
3560//-- or
3561//-- op (src)address, (dst)xmmreg
3562//-- 3 opcode bytes and an 8-bit immediate after the amode.
3563//-- Supplied eip points to the first address mode byte.
3564//-- */
3565//-- static
3566//-- Addr dis_SSE3_reg_or_mem_Imm8 ( UCodeBlock* cb,
3567//-- UChar sorb,
3568//-- Addr eip,
3569//-- Int sz,
3570//-- Char* name,
3571//-- UChar opc1,
3572//-- UChar opc2,
3573//-- UChar opc3 )
3574//-- {
3575//-- Char dis_buf[50];
3576//-- UChar modrm = getUChar(eip);
3577//-- UChar imm8;
3578//-- Bool isReg = epartIsReg(modrm);
3579//--
3580//-- if (isReg) {
3581//-- /* Completely internal SSE insn. */
3582//-- eip++;
3583//-- imm8 = getUChar(eip);
3584//-- uInstr3(cb, SSE5, 0, /* ignore sz for internal ops */
3585//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3586//-- Lit16, (((UShort)opc3) << 8) | (UShort)modrm,
3587//-- Lit16, (UShort)imm8 );
3588//-- eip++;
3589//-- } else {
3590//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3591//-- Int tmpa = LOW24(pair);
3592//-- eip += HI8(pair);
3593//-- imm8 = getUChar(eip);
3594//-- eip++;
3595//-- uInstr3(cb, SSE3a1_MemRd, sz,
3596//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3597//-- Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
3598//-- TempReg, tmpa);
3599//-- uLiteral(cb, imm8);
3600//-- }
3601//-- DIP("%s %s, %s, $%d\n",
3602//-- name, ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3603//-- nameXMMReg(gregOfRM(modrm)), (Int)imm8 );
3604//-- return eip;
3605//-- }
3606//--
3607//--
3608//-- /* Disassemble an SSE insn which is either a simple reg-reg move or a
3609//-- move between registers and memory. Supplied eip points to the
3610//-- first address mode byte.
3611//-- */
3612//-- static
3613//-- Addr dis_SSE3_load_store_or_mov ( UCodeBlock* cb,
3614//-- UChar sorb,
3615//-- Addr eip,
3616//-- Int sz,
3617//-- Bool is_store,
3618//-- Char* name,
3619//-- UChar insn0,
3620//-- UChar insn1,
3621//-- UChar insn2 )
3622//-- {
3623//-- Char dis_buf[50];
3624//-- UChar modrm = getUChar(eip);
3625//-- Bool isReg = epartIsReg(modrm);
3626//-- UInt pair;
3627//-- Int t1;
3628//--
3629//-- if (isReg) {
3630//-- /* Completely internal; we can issue SSE4. */
3631//-- eip++;
3632//-- uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */
3633//-- Lit16, (((UShort)insn0) << 8) | (UShort)insn1,
3634//-- Lit16, (((UShort)insn2) << 8) | (UShort)modrm );
3635//-- } else {
3636//-- pair = disAMode ( cb, sorb, eip, dis_buf );
3637//-- t1 = LOW24(pair);
3638//-- eip += HI8(pair);
3639//-- uInstr3(cb, is_store ? SSE3a_MemWr : SSE3a_MemRd, sz,
3640//-- Lit16, (((UShort)insn0) << 8) | (UShort)insn1,
3641//-- Lit16, (((UShort)insn2) << 8) | (UShort)modrm,
3642//-- TempReg, t1 );
3643//-- }
3644//--
3645//-- if (is_store) {
3646//-- DIP("%s %s, %s\n",
3647//-- name,
3648//-- nameXMMReg(gregOfRM(modrm)),
3649//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ) );
3650//-- } else {
3651//-- DIP("%s %s, %s\n",
3652//-- name,
3653//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3654//-- nameXMMReg(gregOfRM(modrm)) );
3655//-- }
3656//-- return eip;
3657//-- }
3658//--
3659//--
3660//-- /* Disassemble an SSE insn which is either a simple reg-reg move or a
3661//-- move between registers and memory. Supplied eip points to the
3662//-- first address mode byte. */
3663//-- static
3664//-- Addr dis_SSE2_load_store_or_mov ( UCodeBlock* cb,
3665//-- UChar sorb,
3666//-- Addr eip,
3667//-- Int sz,
3668//-- Bool is_store,
3669//-- Char* name,
3670//-- UChar insn0,
3671//-- UChar insn1 )
3672//-- {
3673//-- Char dis_buf[50];
3674//-- UChar modrm = getUChar(eip);
3675//-- Bool isReg = epartIsReg(modrm);
3676//-- UInt pair;
3677//-- Int t1;
3678//--
3679//-- if (isReg) {
3680//-- /* Completely internal; we can issue SSE3. */
3681//-- eip++;
3682//-- uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
3683//-- Lit16, (((UShort)insn0) << 8) | (UShort)insn1,
3684//-- Lit16, (UShort)modrm );
3685//-- } else {
3686//-- pair = disAMode ( cb, sorb, eip, dis_buf );
3687//-- t1 = LOW24(pair);
3688//-- eip += HI8(pair);
3689//-- uInstr3(cb, is_store ? SSE2a_MemWr : SSE2a_MemRd, sz,
3690//-- Lit16, (((UShort)insn0) << 8) | (UShort)insn1,
3691//-- Lit16, (UShort)modrm,
3692//-- TempReg, t1 );
3693//-- }
3694//--
3695//-- if (is_store) {
3696//-- DIP("%s %s, %s\n",
3697//-- name,
3698//-- nameXMMReg(gregOfRM(modrm)),
3699//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ) );
3700//-- } else {
3701//-- DIP("%s %s, %s\n",
3702//-- name,
3703//-- ( isReg ? nameXMMReg(eregOfRM(modrm)) : dis_buf ),
3704//-- nameXMMReg(gregOfRM(modrm)) );
3705//-- }
3706//-- return eip;
3707//-- }
3708//--
3709//--
3710//-- /* Simple SSE operations, either
3711//-- op (src)xmmreg, (dst)mmxreg
3712//-- or
3713//-- op (src)address, (dst)mmxreg
3714//-- 2 opcode bytes.
3715//-- Supplied eip points to the first address mode byte.
3716//-- */
3717//-- static
3718//-- Addr dis_SSE2_to_MMX ( UCodeBlock *cb,
3719//-- UChar sorb,
3720//-- Addr eip,
3721//-- Int sz,
3722//-- Char* name,
3723//-- UChar opc1,
3724//-- UChar opc2 )
3725//-- {
3726//-- UChar dis_buf[50];
3727//-- UChar modrm = getUChar(eip);
3728//-- if (epartIsReg(modrm)) {
3729//-- /* Completely internal SSE insn. */
3730//-- uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
3731//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3732//-- Lit16, (UShort)modrm );
3733//-- DIP("%s %s, %s\n",
3734//-- name, nameXMMReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)) );
3735//-- eip++;
3736//-- } else {
3737//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3738//-- Int tmpa = LOW24(pair);
3739//-- eip += HI8(pair);
3740//-- uInstr3(cb, SSE2a_MemRd, sz,
3741//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3742//-- Lit16, ((UShort)modrm),
3743//-- TempReg, tmpa);
3744//-- DIP("%s %s, %s\n", name, dis_buf, nameMMXReg(gregOfRM(modrm)));
3745//-- }
3746//-- return eip;
3747//-- }
3748//--
3749//--
3750//-- /* Simple SSE operations, either
3751//-- op (src)mmxreg, (dst)xmmreg
3752//-- or
3753//-- op (src)address, (dst)xmmreg
3754//-- 2 opcode bytes.
3755//-- Supplied eip points to the first address mode byte.
3756//-- */
3757//-- static
3758//-- Addr dis_SSE2_from_MMX ( UCodeBlock *cb,
3759//-- UChar sorb,
3760//-- Addr eip,
3761//-- Int sz,
3762//-- Char* name,
3763//-- UChar opc1,
3764//-- UChar opc2 )
3765//-- {
3766//-- UChar dis_buf[50];
3767//-- UChar modrm = getUChar(eip);
3768//-- if (epartIsReg(modrm)) {
3769//-- /* Completely internal SSE insn. */
3770//-- uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
3771//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3772//-- Lit16, (UShort)modrm );
3773//-- DIP("%s %s, %s\n",
3774//-- name, nameMMXReg(eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)) );
3775//-- eip++;
3776//-- } else {
3777//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3778//-- Int tmpa = LOW24(pair);
3779//-- eip += HI8(pair);
3780//-- uInstr3(cb, SSE2a_MemRd, sz,
3781//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3782//-- Lit16, ((UShort)modrm),
3783//-- TempReg, tmpa);
3784//-- DIP("%s %s, %s\n", name, dis_buf, nameXMMReg(gregOfRM(modrm)));
3785//-- }
3786//-- return eip;
3787//-- }
3788//--
3789//--
3790//-- /* Simple SSE operations, either
3791//-- op (src)xmmreg, (dst)mmxreg
3792//-- or
3793//-- op (src)address, (dst)mmxreg
3794//-- 3 opcode bytes.
3795//-- Supplied eip points to the first address mode byte.
3796//-- */
3797//-- static
3798//-- Addr dis_SSE3_to_MMX ( UCodeBlock *cb,
3799//-- UChar sorb,
3800//-- Addr eip,
3801//-- Int sz,
3802//-- Char* name,
3803//-- UChar opc1,
3804//-- UChar opc2,
3805//-- UChar opc3 )
3806//-- {
3807//-- UChar dis_buf[50];
3808//-- UChar modrm = getUChar(eip);
3809//-- if (epartIsReg(modrm)) {
3810//-- /* Completely internal SSE insn. */
3811//-- uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */
3812//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3813//-- Lit16, (((UShort)opc3) << 8) | (UShort)modrm );
3814//-- DIP("%s %s, %s\n",
3815//-- name, nameXMMReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)) );
3816//-- eip++;
3817//-- } else {
3818//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3819//-- Int tmpa = LOW24(pair);
3820//-- eip += HI8(pair);
3821//-- uInstr3(cb, SSE3a_MemRd, sz,
3822//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3823//-- Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
3824//-- TempReg, tmpa);
3825//-- DIP("%s %s, %s\n", name, dis_buf, nameMMXReg(gregOfRM(modrm)));
3826//-- }
3827//-- return eip;
3828//-- }
3829//--
3830//--
3831//-- /* Simple SSE operations, either
3832//-- op (src)mmxreg, (dst)xmmreg
3833//-- or
3834//-- op (src)address, (dst)xmmreg
3835//-- 3 opcode bytes.
3836//-- Supplied eip points to the first address mode byte.
3837//-- */
3838//-- static
3839//-- Addr dis_SSE3_from_MMX ( UCodeBlock *cb,
3840//-- UChar sorb,
3841//-- Addr eip,
3842//-- Int sz,
3843//-- Char* name,
3844//-- UChar opc1,
3845//-- UChar opc2,
3846//-- UChar opc3 )
3847//-- {
3848//-- UChar dis_buf[50];
3849//-- UChar modrm = getUChar(eip);
3850//-- if (epartIsReg(modrm)) {
3851//-- /* Completely internal SSE insn. */
3852//-- uInstr2(cb, SSE4, 0, /* ignore sz for internal ops */
3853//-- Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
3854//-- Lit16, (((UShort)opc3) << 8) | (UShort)modrm );
3855//-- DIP("%s %s, %s\n",
3856//-- name, nameMMXReg(eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)) );
3857//-- eip++;
3858//-- } else {
3859//-- UInt pair = disAMode ( cb, sorb, eip, dis_buf );
3860//-- Int tmpa = LOW24(pair);
3861//-- eip += HI8(pair);
3862//-- uInstr3(cb, SSE3a_MemRd, sz,
3863//-- Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
3864//-- Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
3865//-- TempReg, tmpa);
3866//-- DIP("%s %s, %s\n", name, dis_buf, nameXMMReg(gregOfRM(modrm)));
3867//-- }
3868//-- return eip;
3869//-- }
3870//--
3871//--
3872//-- static
3873//-- void dis_push_segreg ( UCodeBlock* cb, UInt sreg, Int sz )
3874//-- {
3875//-- Int t1 = newTemp(cb), t2 = newTemp(cb);
3876//-- vg_assert(sz == 2 || sz == 4);
3877//-- uInstr2(cb, GETSEG, 2, ArchRegS, sreg, TempReg, t1);
3878//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
3879//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
3880//-- uLiteral(cb, sz);
3881//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
3882//-- uInstr2(cb, STORE, 2, TempReg, t1, TempReg, t2);
3883//-- DIP("push %s\n", VG_(name_of_seg_reg)(sreg));
3884//-- }
3885//--
3886//-- static
3887//-- void dis_pop_segreg ( UCodeBlock* cb, UInt sreg, Int sz )
3888//-- {
3889//-- Int t1 = newTemp(cb), t2 = newTemp(cb);
3890//-- vg_assert(sz == 2 || sz == 4);
3891//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
3892//-- uInstr2(cb, LOAD, 2, TempReg, t2, TempReg, t1);
3893//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
3894//-- uLiteral(cb, sz);
3895//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
3896//-- uInstr2(cb, PUTSEG, 2, TempReg, t1, ArchRegS, sreg);
3897//-- DIP("pop %s\n", VG_(name_of_seg_reg)(sreg));
3898//-- }
3899//--
3900//-- static
3901//-- void dis_ret ( UCodeBlock* cb, UInt d32 )
3902//-- {
3903//-- Int t1 = newTemp(cb), t2 = newTemp(cb);
3904//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t1);
3905//-- uInstr2(cb, LOAD, 4, TempReg, t1, TempReg, t2);
3906//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t1);
3907//-- uLiteral(cb, 4+d32);
3908//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ESP);
3909//-- jmp_treg(cb, t2);
3910//-- LAST_UINSTR(cb).jmpkind = JmpRet;
3911//-- }
3912
3913/*------------------------------------------------------------*/
3914/*--- Disassembling entire basic blocks ---*/
3915/*------------------------------------------------------------*/
3916
3917/* Disassemble a single instruction into IR, returning the updated
3918 delta, and setting *isEnd to True if this is the last insn in a
3919 basic block. Also do debug printing if necessary. */
3920
3921static UInt disInstr ( UInt delta, Bool* isEnd )
3922{
sewardjd1061ab2004-07-08 01:45:30 +00003923 UChar opc, modrm /* , abyte*/;
3924 UInt d32 /*, pair*/;
3925 // UChar dis_buf[50];
3926 Int am_sz, d_sz;
3927 IRTemp t1, t2, t3, t4;
3928 IRType ty;
sewardjc9a65702004-07-07 16:32:57 +00003929 //Char loc_buf[M_VG_ERRTXT];
3930
3931 /* Holds eip at the start of the insn, so that we can print
3932 consistent error messages for unimplemented insns. */
3933 UInt delta_start = delta;
3934
3935 /* sz denotes the nominal data-op size of the insn; we change it to
3936 2 if an 0x66 prefix is seen */
3937 Int sz = 4;
3938
3939 /* sorb holds the segment-override-prefix byte, if any. Zero if no
3940 prefix has been seen, else one of {0x26, 0x3E, 0x64, 0x65}
3941 indicating the prefix. */
3942 UChar sorb = 0;
3943
3944 /* For printing the stmts after each insn. */
3945 IRStmt* first_stmt = last_stmt;
3946
3947 *isEnd = False;
sewardjd1061ab2004-07-08 01:45:30 +00003948 t1 = t2 = t3 = t4 = INVALID_IRTEMP;
sewardjc9a65702004-07-07 16:32:57 +00003949
3950 DIP("\t0x%x: ", guest_eip+delta);
3951
3952//-- /* Spot the client-request magic sequence. */
3953//-- {
3954//-- UChar* myeip = (UChar*)eip;
3955//-- /* Spot this:
3956//-- C1C01D roll $29, %eax
3957//-- C1C003 roll $3, %eax
3958//-- C1C81B rorl $27, %eax
3959//-- C1C805 rorl $5, %eax
3960//-- C1C00D roll $13, %eax
3961//-- C1C013 roll $19, %eax
3962//-- */
3963//-- if (myeip[ 0] == 0xC1 && myeip[ 1] == 0xC0 && myeip[ 2] == 0x1D &&
3964//-- myeip[ 3] == 0xC1 && myeip[ 4] == 0xC0 && myeip[ 5] == 0x03 &&
3965//-- myeip[ 6] == 0xC1 && myeip[ 7] == 0xC8 && myeip[ 8] == 0x1B &&
3966//-- myeip[ 9] == 0xC1 && myeip[10] == 0xC8 && myeip[11] == 0x05 &&
3967//-- myeip[12] == 0xC1 && myeip[13] == 0xC0 && myeip[14] == 0x0D &&
3968//-- myeip[15] == 0xC1 && myeip[16] == 0xC0 && myeip[17] == 0x13
3969//-- ) {
3970//-- eip += 18;
3971//-- jmp_lit(cb, eip);
3972//-- LAST_UINSTR(cb).jmpkind = JmpClientReq;
3973//-- *isEnd = True;
3974//-- DIP("%%edx = client_request ( %%eax )\n");
3975//-- return eip;
3976//-- }
3977//-- }
3978
3979 /* Skip a LOCK prefix. */
3980 if (getIByte(delta) == 0xF0) {
3981 /* VG_(printf)("LOCK LOCK LOCK LOCK LOCK \n"); */
3982 vpanic("x86 LOCK. what to do?");
3983 delta++;
3984 }
3985
3986 /* Detect operand-size overrides. */
3987 if (getIByte(delta) == 0x66) { sz = 2; delta++; };
3988
3989 /* segment override prefixes come after the operand-size override,
3990 it seems */
3991 switch (getIByte(delta)) {
3992 case 0x3E: /* %DS: */
3993 case 0x26: /* %ES: */
3994 case 0x64: /* %FS: */
3995 case 0x65: /* %GS: */
3996 sorb = getIByte(delta); delta++;
3997 break;
3998 case 0x2E: /* %CS: */
3999 /* 2E prefix on a conditional branch instruction is a
4000 branch-prediction hint, which can safely be ignored. */
4001 {
4002 UChar op1 = getIByte(delta+1);
4003 UChar op2 = getIByte(delta+2);
4004 if ((op1 >= 0x70 && op1 <= 0x7F)
4005 || (op1 == 0xE3)
4006 || (op1 == 0x0F && op2 >= 0x80 && op2 <= 0x8F)) {
4007 sorb = getIByte(delta); delta++;
4008 break;
4009 }
4010 }
4011 unimplemented("x86 segment override (SEG=CS) prefix");
4012 /*NOTREACHED*/
4013 break;
4014 case 0x36: /* %SS: */
4015 unimplemented("x86 segment override (SEG=SS) prefix");
4016 /*NOTREACHED*/
4017 break;
4018 default:
4019 break;
4020 }
4021
4022//-- /* ---------------------------------------------------- */
4023//-- /* --- The SSE/SSE2 decoder. --- */
4024//-- /* ---------------------------------------------------- */
4025//--
4026//-- /* If it looks like this CPU might support SSE, try decoding SSE
4027//-- insns. */
4028//-- if (VG_(have_ssestate)) {
4029//-- UChar* insn = (UChar*)eip;
4030//--
4031//-- /* FXSAVE/FXRSTOR m32 -- load/store the FPU/MMX/SSE state. */
4032//-- if (insn[0] == 0x0F && insn[1] == 0xAE
4033//-- && (!epartIsReg(insn[2]))
4034//-- && (gregOfRM(insn[2]) == 1 || gregOfRM(insn[2]) == 0) ) {
4035//-- Bool store = gregOfRM(insn[2]) == 0;
4036//-- vg_assert(sz == 4);
4037//-- pair = disAMode ( cb, sorb, eip+2, dis_buf );
4038//-- t1 = LOW24(pair);
4039//-- eip += 2+HI8(pair);
4040//-- uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 512,
4041//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
4042//-- Lit16, (UShort)insn[2],
4043//-- TempReg, t1 );
4044//-- DIP("fx%s %s\n", store ? "save" : "rstor", dis_buf );
4045//-- goto decode_success;
4046//-- }
4047//--
4048//-- /* STMXCSR/LDMXCSR m32 -- load/store the MXCSR register. */
4049//-- if (insn[0] == 0x0F && insn[1] == 0xAE
4050//-- && (!epartIsReg(insn[2]))
4051//-- && (gregOfRM(insn[2]) == 3 || gregOfRM(insn[2]) == 2) ) {
4052//-- Bool store = gregOfRM(insn[2]) == 3;
4053//-- vg_assert(sz == 4);
4054//-- pair = disAMode ( cb, sorb, eip+2, dis_buf );
4055//-- t1 = LOW24(pair);
4056//-- eip += 2+HI8(pair);
4057//-- uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 4,
4058//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
4059//-- Lit16, (UShort)insn[2],
4060//-- TempReg, t1 );
4061//-- DIP("%smxcsr %s\n", store ? "st" : "ld", dis_buf );
4062//-- goto decode_success;
4063//-- }
4064//--
4065//-- /* LFENCE/MFENCE/SFENCE -- flush pending operations to memory */
4066//-- if (insn[0] == 0x0F && insn[1] == 0xAE
4067//-- && (epartIsReg(insn[2]))
4068//-- && (gregOfRM(insn[2]) >= 5 && gregOfRM(insn[2]) <= 7))
4069//-- {
4070//-- vg_assert(sz == 4);
4071//-- eip += 3;
4072//-- uInstr2(cb, SSE3, 0, /* ignore sz for internal ops */
4073//-- Lit16, (((UShort)0x0F) << 8) | (UShort)0xAE,
4074//-- Lit16, (UShort)insn[2] );
4075//-- DIP("sfence\n");
4076//-- goto decode_success;
4077//-- }
4078//--
4079//-- /* CLFLUSH -- flush cache line */
4080//-- if (insn[0] == 0x0F && insn[1] == 0xAE
4081//-- && (!epartIsReg(insn[2]))
4082//-- && (gregOfRM(insn[2]) == 7))
4083//-- {
4084//-- vg_assert(sz == 4);
4085//-- pair = disAMode ( cb, sorb, eip+2, dis_buf );
4086//-- t1 = LOW24(pair);
4087//-- eip += 2+HI8(pair);
4088//-- uInstr3(cb, SSE2a_MemRd, 0, /* ignore sz for internal ops */
4089//-- Lit16, (((UShort)0x0F) << 8) | (UShort)0xAE,
4090//-- Lit16, (UShort)insn[2],
4091//-- TempReg, t1 );
4092//-- DIP("clflush %s\n", dis_buf);
4093//-- goto decode_success;
4094//-- }
4095//--
4096//-- /* CVTPI2PS (0x0F,0x2A) -- mm/m64, xmm */
4097//-- /* CVTPI2PD (0x66,0x0F,0x2A) -- mm/m64, xmm */
4098//-- if (insn[0] == 0x0F && insn[1] == 0x2A) {
4099//-- if (sz == 4) {
4100//-- eip = dis_SSE2_from_MMX
4101//-- ( cb, sorb, eip+2, 8, "cvtpi2ps",
4102//-- insn[0], insn[1] );
4103//-- } else {
4104//-- eip = dis_SSE3_from_MMX
4105//-- ( cb, sorb, eip+2, 8, "cvtpi2pd",
4106//-- 0x66, insn[0], insn[1] );
4107//-- }
4108//-- goto decode_success;
4109//-- }
4110//--
4111//-- /* CVTTPS2PI (0x0F,0x2C) -- xmm/m64, mm */
4112//-- /* CVTPS2PI (0x0F,0x2D) -- xmm/m64, mm */
4113//-- /* CVTTPD2PI (0x66,0x0F,0x2C) -- xmm/m128, mm */
4114//-- /* CVTPD2PI (0x66,0x0F,0x2D) -- xmm/m128, mm */
4115//-- if (insn[0] == 0x0F
4116//-- && (insn[1] == 0x2C || insn[1] == 0x2D)) {
4117//-- if (sz == 4) {
4118//-- eip = dis_SSE2_to_MMX
4119//-- ( cb, sorb, eip+2, 8, "cvt{t}ps2pi",
4120//-- insn[0], insn[1] );
4121//-- } else {
4122//-- eip = dis_SSE3_to_MMX
4123//-- ( cb, sorb, eip+2, 16, "cvt{t}pd2pi",
4124//-- 0x66, insn[0], insn[1] );
4125//-- }
4126//-- goto decode_success;
4127//-- }
4128//--
4129//-- /* CVTTSD2SI (0xF2,0x0F,0x2C) -- convert a double-precision float
4130//-- value in memory or xmm reg to int and put it in an ireg.
4131//-- Truncate. */
4132//-- /* CVTTSS2SI (0xF3,0x0F,0x2C) -- convert a single-precision float
4133//-- value in memory or xmm reg to int and put it in an ireg.
4134//-- Truncate. */
4135//-- /* CVTSD2SI (0xF2,0x0F,0x2D) -- convert a double-precision float
4136//-- value in memory or xmm reg to int and put it in an ireg. Round
4137//-- as per MXCSR. */
4138//-- /* CVTSS2SI (0xF3,0x0F,0x2D) -- convert a single-precision float
4139//-- value in memory or xmm reg to int and put it in an ireg. Round
4140//-- as per MXCSR. */
4141//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4142//-- && insn[1] == 0x0F
4143//-- && (insn[2] == 0x2C || insn[2] == 0x2D)) {
4144//-- vg_assert(sz == 4);
4145//-- modrm = insn[3];
4146//-- if (epartIsReg(modrm)) {
4147//-- /* We're moving a value in an xmm reg to an ireg. */
4148//-- eip += 4;
4149//-- t1 = newTemp(cb);
4150//-- /* sz is 4 for all 4 insns. */
4151//-- vg_assert(epartIsReg(modrm));
4152//-- uInstr3(cb, SSE3g_RegWr, 4,
4153//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
4154//-- Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm,
4155//-- TempReg, t1 );
4156//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
4157//-- DIP("cvt{t}s{s,d}2si %s, %s\n",
4158//-- nameXMMReg(eregOfRM(modrm)), nameIReg(4,gregOfRM(modrm)) );
4159//-- } else {
4160//-- /* So, we're reading memory and writing an ireg. This calls
4161//-- for the ultra-horrible SSE3ag_MemRd_RegWr uinstr. We
4162//-- can't do it in a roundabout route because it does some
4163//-- kind of conversion on the way, which we need to have
4164//-- happen too. So our only choice is to re-emit a suitably
4165//-- rehashed version of the instruction. */
4166//-- /* Destination ireg is GREG. Address goes as EREG as
4167//-- usual. */
4168//-- t1 = newTemp(cb); /* t1 holds value on its way to ireg */
4169//-- pair = disAMode ( cb, sorb, eip+3, dis_buf );
4170//-- t2 = LOW24(pair); /* t2 holds addr */
4171//-- eip += 3+HI8(pair);
4172//-- uInstr2(cb, SSE3ag_MemRd_RegWr, insn[0]==0xF2 ? 8 : 4,
4173//-- TempReg, t2, /* address */
4174//-- TempReg, t1 /* dest */);
4175//-- uLiteral(cb , (((UInt)insn[0]) << 24)
4176//-- | (((UInt)insn[1]) << 16)
4177//-- | (((UInt)insn[2]) << 8)
4178//-- | ((UInt)modrm) );
4179//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
4180//-- DIP("cvt{t}s{s,d}2si %s, %s\n",
4181//-- dis_buf, nameIReg(4,gregOfRM(modrm)) );
4182//-- }
4183//-- goto decode_success;
4184//-- }
4185//--
4186//-- /* CVTSI2SS -- convert int reg, or int value in memory, to low 4
4187//-- bytes of XMM reg. */
4188//-- /* CVTSI2SD -- convert int reg, or int value in memory, to low 8
4189//-- bytes of XMM reg. */
4190//-- if ((insn[0] == 0xF3 /*CVTSI2SS*/ || insn[0] == 0xF2 /* CVTSI2SD*/)
4191//-- && insn[1] == 0x0F && insn[2] == 0x2A) {
4192//-- Char* s_or_d = insn[0]==0xF3 ? "s" : "d";
4193//-- vg_assert(sz == 4);
4194//-- modrm = insn[3];
4195//-- t1 = newTemp(cb);
4196//-- if (epartIsReg(modrm)) {
4197//-- uInstr2(cb, GET, 4, ArchReg, eregOfRM(modrm), TempReg, t1);
4198//-- vg_assert(epartIsReg(modrm));
4199//-- uInstr3(cb, SSE3e_RegRd, 4,
4200//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
4201//-- Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm,
4202//-- TempReg, t1 );
4203//-- eip += 4;
4204//-- DIP("cvtsi2s%s %s, %s\n", s_or_d,
4205//-- nameIReg(4,eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)));
4206//-- } else {
4207//-- pair = disAMode ( cb, sorb, eip+3, dis_buf );
4208//-- t2 = LOW24(pair);
4209//-- eip += 3+HI8(pair);
4210//-- uInstr3(cb, SSE3a_MemRd, 4,
4211//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
4212//-- Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm,
4213//-- TempReg, t2 );
4214//-- DIP("cvtsi2s%s %s, %s\n",
4215//-- s_or_d, dis_buf, nameXMMReg(gregOfRM(modrm)));
4216//-- }
4217//-- goto decode_success;
4218//-- }
4219//--
4220//-- /* CVTPS2PD -- convert two packed floats to two packed doubles. */
4221//-- /* 0x66: CVTPD2PS -- convert two packed doubles to two packed floats. */
4222//-- if (insn[0] == 0x0F && insn[1] == 0x5A) {
4223//-- vg_assert(sz == 2 || sz == 4);
4224//-- if (sz == 4) {
4225//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 8, "cvtps2pd",
4226//-- insn[0], insn[1] );
4227//-- } else {
4228//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "cvtpd2ps",
4229//-- 0x66, insn[0], insn[1] );
4230//-- }
4231//-- goto decode_success;
4232//-- }
4233//--
4234//-- /* CVTSS2SD -- convert one single float to double. */
4235//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5A) {
4236//-- vg_assert(sz == 4);
4237//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 4, "cvtss2sd",
4238//-- insn[0], insn[1], insn[2] );
4239//-- goto decode_success;
4240//-- }
4241//--
4242//-- /* CVTSD2SS -- convert one single double. to float. */
4243//-- if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
4244//-- vg_assert(sz == 4);
4245//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvtsd2ss",
4246//-- insn[0], insn[1], insn[2] );
4247//-- goto decode_success;
4248//-- }
4249//--
4250//-- /* CVTDQ2PS -- convert four ints to four packed floats. */
4251//-- /* 0x66: CVTPS2DQ -- convert four packed floats to four ints. */
4252//-- if (insn[0] == 0x0F && insn[1] == 0x5B) {
4253//-- vg_assert(sz == 2 || sz == 4);
4254//-- if (sz == 4) {
4255//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "cvtdq2ps",
4256//-- insn[0], insn[1] );
4257//-- } else {
4258//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "cvtps2dq",
4259//-- 0x66, insn[0], insn[1] );
4260//-- }
4261//-- goto decode_success;
4262//-- }
4263//--
4264//-- /* CVTPD2DQ -- convert two packed doubles to two ints. */
4265//-- if (sz == 2
4266//-- && insn[0] == 0x0F && insn[1] == 0xE6) {
4267//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 8, "cvtpd2dq",
4268//-- 0x66, insn[0], insn[1] );
4269//-- goto decode_success;
4270//-- }
4271//--
4272//-- /* CVTTPD2DQ -- convert two packed doubles to two ints with truncation. */
4273//-- if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xE6) {
4274//-- vg_assert(sz == 4);
4275//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvttpd2dq",
4276//-- insn[0], insn[1], insn[2] );
4277//-- goto decode_success;
4278//-- }
4279//--
4280//-- /* CVTDQ2PD -- convert two ints to two packed doubles. */
4281//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xE6) {
4282//-- vg_assert(sz == 4);
4283//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvtdq2pd",
4284//-- insn[0], insn[1], insn[2] );
4285//-- goto decode_success;
4286//-- }
4287//--
4288//-- /* CVTTPS2DQ -- convert four packed floats to four ints with truncation. */
4289//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5B) {
4290//-- vg_assert(sz == 4);
4291//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 16, "cvttps2dq",
4292//-- insn[0], insn[1], insn[2] );
4293//-- goto decode_success;
4294//-- }
4295//--
4296//-- /* CMPSS -- compare scalar floats. */
4297//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0xC2) {
4298//-- vg_assert(sz == 4);
4299//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+3, 8, "cmpss",
4300//-- insn[0], insn[1], insn[2] );
4301//-- goto decode_success;
4302//-- }
4303//--
4304//-- /* CMPSD -- compare scalar doubles. */
4305//-- if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0xC2) {
4306//-- vg_assert(sz == 4);
4307//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+3, 8, "cmpsd",
4308//-- insn[0], insn[1], insn[2] );
4309//-- goto decode_success;
4310//-- }
4311//--
4312//-- /* sz==4: CMPPS -- compare packed floats */
4313//-- /* sz==2: CMPPD -- compare packed doubles */
4314//-- if (insn[0] == 0x0F && insn[1] == 0xC2) {
4315//-- vg_assert(sz == 4 || sz == 2);
4316//-- if (sz == 4) {
4317//-- eip = dis_SSE2_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16, "cmpps",
4318//-- insn[0], insn[1] );
4319//-- } else {
4320//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16, "cmppd",
4321//-- 0x66, insn[0], insn[1] );
4322//-- }
4323//-- goto decode_success;
4324//-- }
4325//--
4326//-- /* PSHUFD */
4327//-- if (sz == 2
4328//-- && insn[0] == 0x0F && insn[1] == 0x70) {
4329//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16,
4330//-- "pshufd",
4331//-- 0x66, insn[0], insn[1] );
4332//-- goto decode_success;
4333//-- }
4334//--
4335//-- /* PSHUFLW */
4336//-- if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x70) {
4337//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+3, 16,
4338//-- "pshuflw",
4339//-- insn[0], insn[1], insn[2] );
4340//-- goto decode_success;
4341//-- }
4342//--
4343//-- /* PSHUFHW */
4344//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x70) {
4345//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+3, 16,
4346//-- "pshufhw",
4347//-- insn[0], insn[1], insn[2] );
4348//-- goto decode_success;
4349//-- }
4350//--
4351//-- /* SHUFPD */
4352//-- if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC6) {
4353//-- eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16, "shufpd",
4354//-- 0x66, insn[0], insn[1] );
4355//-- goto decode_success;
4356//-- }
4357//--
4358//-- /* SHUFPS */
4359//-- if (insn[0] == 0x0F && insn[1] == 0xC6) {
4360//-- vg_assert(sz == 4);
4361//-- eip = dis_SSE2_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16, "shufps",
4362//-- insn[0], insn[1] );
4363//-- goto decode_success;
4364//-- }
4365//--
4366//-- /* 0xF2: MULSD */
4367//-- /* 0xF3: MULSS -- multiply low 4 bytes of XMM reg. */
4368//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4369//-- && insn[1] == 0x0F && insn[2] == 0x59) {
4370//-- Bool sz8 = insn[0] == 0xF2;
4371//-- vg_assert(sz == 4);
4372//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4373//-- sz8 ? "mulss" : "mulsd",
4374//-- insn[0], insn[1], insn[2] );
4375//-- goto decode_success;
4376//-- }
4377//--
4378//-- /* MULPS */
4379//-- /* 0x66: MULPD */
4380//-- if (insn[0] == 0x0F && insn[1] == 0x59) {
4381//-- vg_assert(sz == 4 || sz == 2);
4382//-- if (sz == 4) {
4383//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "mulps",
4384//-- insn[0], insn[1] );
4385//-- } else {
4386//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "mulpd",
4387//-- 0x66, insn[0], insn[1] );
4388//-- }
4389//-- goto decode_success;
4390//-- }
4391//--
4392//-- /* 0xF2: DIVSD */
4393//-- /* 0xF3: DIVSS -- divide low 4 bytes of XMM reg. */
4394//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4395//-- && insn[1] == 0x0F && insn[2] == 0x5E) {
4396//-- Bool sz8 = insn[0] == 0xF2;
4397//-- vg_assert(sz == 4);
4398//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4399//-- sz8 ? "divsd" : "divss",
4400//-- insn[0], insn[1], insn[2] );
4401//-- goto decode_success;
4402//-- }
4403//--
4404//-- /* DIVPS */
4405//-- /* 0x66: DIVPD */
4406//-- if (insn[0] == 0x0F && insn[1] == 0x5E) {
4407//-- vg_assert(sz == 4 || sz == 2);
4408//-- if (sz == 4) {
4409//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "divps",
4410//-- insn[0], insn[1] );
4411//-- } else {
4412//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "divpd",
4413//-- 0x66, insn[0], insn[1] );
4414//-- }
4415//-- goto decode_success;
4416//-- }
4417//--
4418//-- /* 0xF2: SUBSD */
4419//-- /* 0xF3: SUBSS */
4420//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4421//-- && insn[1] == 0x0F && insn[2] == 0x5C) {
4422//-- Bool sz8 = insn[0] == 0xF2;
4423//-- vg_assert(sz == 4);
4424//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4425//-- sz8 ? "subsd" : "subss",
4426//-- insn[0], insn[1], insn[2] );
4427//-- goto decode_success;
4428//-- }
4429//--
4430//-- /* SUBPS */
4431//-- /* 0x66: SUBPD */
4432//-- if (insn[0] == 0x0F && insn[1] == 0x5C) {
4433//-- vg_assert(sz == 4 || sz == 2);
4434//-- if (sz == 4) {
4435//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "subps",
4436//-- insn[0], insn[1] );
4437//-- } else {
4438//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "subpd",
4439//-- 0x66, insn[0], insn[1] );
4440//-- }
4441//-- goto decode_success;
4442//-- }
4443//--
4444//-- /* 0xF2: ADDSD */
4445//-- /* 0xF3: ADDSS */
4446//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4447//-- && insn[1] == 0x0F && insn[2] == 0x58) {
4448//-- Bool sz8 = insn[0] == 0xF2;
4449//-- vg_assert(sz == 4);
4450//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4451//-- sz8 ? "addsd" : "addss",
4452//-- insn[0], insn[1], insn[2] );
4453//-- goto decode_success;
4454//-- }
4455//--
4456//-- /* ADDPS */
4457//-- /* 0x66: ADDPD */
4458//-- if (insn[0] == 0x0F && insn[1] == 0x58) {
4459//-- vg_assert(sz == 4 || sz == 2);
4460//-- if (sz == 4) {
4461//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "addps",
4462//-- insn[0], insn[1] );
4463//-- } else {
4464//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "addpd",
4465//-- 0x66, insn[0], insn[1] );
4466//-- }
4467//-- goto decode_success;
4468//-- }
4469//--
4470//-- /* 0xF2: MINSD */
4471//-- /* 0xF3: MINSS */
4472//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4473//-- && insn[1] == 0x0F && insn[2] == 0x5D) {
4474//-- Bool sz8 = insn[0] == 0xF2;
4475//-- vg_assert(sz == 4);
4476//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4477//-- sz8 ? "minsd" : "minss",
4478//-- insn[0], insn[1], insn[2] );
4479//-- goto decode_success;
4480//-- }
4481//--
4482//-- /* MINPS */
4483//-- /* 0x66: MINPD */
4484//-- if (insn[0] == 0x0F && insn[1] == 0x5D) {
4485//-- vg_assert(sz == 4 || sz == 2);
4486//-- if (sz == 4) {
4487//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "minps",
4488//-- insn[0], insn[1] );
4489//-- } else {
4490//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "minpd",
4491//-- 0x66, insn[0], insn[1] );
4492//-- }
4493//-- goto decode_success;
4494//-- }
4495//--
4496//-- /* 0xF3: MAXSD */
4497//-- /* 0xF3: MAXSS */
4498//-- if ((insn[0] == 0xF2 || insn[0] == 0xF3)
4499//-- && insn[1] == 0x0F && insn[2] == 0x5F) {
4500//-- Bool sz8 = insn[0] == 0xF2;
4501//-- vg_assert(sz == 4);
4502//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, sz8 ? 8 : 4,
4503//-- sz8 ? "maxsd" : "maxss",
4504//-- insn[0], insn[1], insn[2] );
4505//-- goto decode_success;
4506//-- }
4507//--
4508//-- /* MAXPS */
4509//-- /* 0x66: MAXPD */
4510//-- if (insn[0] == 0x0F && insn[1] == 0x5F) {
4511//-- vg_assert(sz == 4 || sz == 2);
4512//-- if (sz == 4) {
4513//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "maxps",
4514//-- insn[0], insn[1] );
4515//-- } else {
4516//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "maxpd",
4517//-- 0x66, insn[0], insn[1] );
4518//-- }
4519//-- goto decode_success;
4520//-- }
4521//--
4522//-- /* RCPPS -- reciprocal of packed floats */
4523//-- if (insn[0] == 0x0F && insn[1] == 0x53) {
4524//-- vg_assert(sz == 4);
4525//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "rcpps",
4526//-- insn[0], insn[1] );
4527//-- goto decode_success;
4528//-- }
4529//--
4530//-- /* XORPS */
4531//-- /* 0x66: XORPD (src)xmmreg-or-mem, (dst)xmmreg */
4532//-- if (insn[0] == 0x0F && insn[1] == 0x57) {
4533//-- vg_assert(sz == 4 || sz == 2);
4534//-- if (sz == 4) {
4535//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "xorps",
4536//-- insn[0], insn[1] );
4537//-- } else {
4538//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "xorpd",
4539//-- 0x66, insn[0], insn[1] );
4540//-- }
4541//-- goto decode_success;
4542//-- }
4543//--
4544//-- /* ANDPS */
4545//-- /* 0x66: ANDPD (src)xmmreg-or-mem, (dst)xmmreg */
4546//-- if (insn[0] == 0x0F && insn[1] == 0x54) {
4547//-- vg_assert(sz == 4 || sz == 2);
4548//-- if (sz == 4) {
4549//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "andps",
4550//-- insn[0], insn[1] );
4551//-- } else {
4552//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "andpd",
4553//-- 0x66, insn[0], insn[1] );
4554//-- }
4555//-- goto decode_success;
4556//-- }
4557//--
4558//-- /* ORPS */
4559//-- /* 0x66: ORPD (src)xmmreg-or-mem, (dst)xmmreg */
4560//-- if (insn[0] == 0x0F && insn[1] == 0x56) {
4561//-- vg_assert(sz == 4 || sz == 2);
4562//-- if (sz == 4) {
4563//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "orps",
4564//-- insn[0], insn[1] );
4565//-- } else {
4566//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "orpd",
4567//-- 0x66, insn[0], insn[1] );
4568//-- }
4569//-- goto decode_success;
4570//-- }
4571//--
4572//-- /* PXOR (src)xmmreg-or-mem, (dst)xmmreg */
4573//-- if (sz == 2
4574//-- && insn[0] == 0x0F && insn[1] == 0xEF) {
4575//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pxor",
4576//-- 0x66, insn[0], insn[1] );
4577//-- goto decode_success;
4578//-- }
4579//--
4580//-- /* PAND (src)xmmreg-or-mem, (dst)xmmreg */
4581//-- if (sz == 2
4582//-- && insn[0] == 0x0F && insn[1] == 0xDB) {
4583//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pand",
4584//-- 0x66, insn[0], insn[1] );
4585//-- goto decode_success;
4586//-- }
4587//--
4588//-- /* PANDN (src)xmmreg-or-mem, (dst)xmmreg */
4589//-- if (sz == 2
4590//-- && insn[0] == 0x0F && insn[1] == 0xDF) {
4591//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pandn",
4592//-- 0x66, insn[0], insn[1] );
4593//-- goto decode_success;
4594//-- }
4595//--
4596//-- /* POR (src)xmmreg-or-mem, (dst)xmmreg */
4597//-- if (sz == 2
4598//-- && insn[0] == 0x0F && insn[1] == 0xEB) {
4599//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "por",
4600//-- 0x66, insn[0], insn[1] );
4601//-- goto decode_success;
4602//-- }
4603//--
4604//-- /* 0xDA: PMINUB(src)xmmreg-or-mem, (dst)xmmreg */
4605//-- /* 0xEA: PMINSW(src)xmmreg-or-mem, (dst)xmmreg */
4606//-- if (sz == 2
4607//-- && insn[0] == 0x0F
4608//-- && (insn[1] == 0xDA || insn[1] == 0xEA)) {
4609//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pmin{ub,sw}",
4610//-- 0x66, insn[0], insn[1] );
4611//-- goto decode_success;
4612//-- }
4613//--
4614//-- /* 0xDE: PMAXUB(src)xmmreg-or-mem, (dst)xmmreg */
4615//-- /* 0xEE: PMAXSW(src)xmmreg-or-mem, (dst)xmmreg */
4616//-- if (sz == 2
4617//-- && insn[0] == 0x0F
4618//-- && (insn[1] == 0xDE || insn[1] == 0xEE)) {
4619//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pmax{ub,sw}",
4620//-- 0x66, insn[0], insn[1] );
4621//-- goto decode_success;
4622//-- }
4623//--
4624//-- /* 0xE0: PAVGB(src)xmmreg-or-mem, (dst)xmmreg */
4625//-- /* 0xE3: PAVGW(src)xmmreg-or-mem, (dst)xmmreg */
4626//-- if (sz == 2
4627//-- && insn[0] == 0x0F
4628//-- && (insn[1] == 0xE0 || insn[1] == 0xE3)) {
4629//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pavg{b,w}",
4630//-- 0x66, insn[0], insn[1] );
4631//-- goto decode_success;
4632//-- }
4633//--
4634//-- /* 0xF6: PSADBW(src)xmmreg-or-mem, (dst)xmmreg */
4635//-- if (sz == 2
4636//-- && insn[0] == 0x0F && insn[1] == 0xF6) {
4637//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psadbw",
4638//-- 0x66, insn[0], insn[1] );
4639//-- goto decode_success;
4640//-- }
4641//--
4642//-- /* 0x60: PUNPCKLBW (src)xmmreg-or-mem, (dst)xmmreg */
4643//-- /* 0x61: PUNPCKLWD (src)xmmreg-or-mem, (dst)xmmreg */
4644//-- /* 0x62: PUNPCKLDQ (src)xmmreg-or-mem, (dst)xmmreg */
4645//-- /* 0x6C: PUNPCKQLQDQ (src)xmmreg-or-mem, (dst)xmmreg */
4646//-- if (sz == 2
4647//-- && insn[0] == 0x0F
4648//-- && (insn[1] == 0x60 || insn[1] == 0x61
4649//-- || insn[1] == 0x62 || insn[1] == 0x6C)) {
4650//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16,
4651//-- "punpckl{bw,wd,dq,qdq}",
4652//-- 0x66, insn[0], insn[1] );
4653//-- goto decode_success;
4654//-- }
4655//--
4656//-- /* 0x68: PUNPCKHBW (src)xmmreg-or-mem, (dst)xmmreg */
4657//-- /* 0x69: PUNPCKHWD (src)xmmreg-or-mem, (dst)xmmreg */
4658//-- /* 0x6A: PUNPCKHDQ (src)xmmreg-or-mem, (dst)xmmreg */
4659//-- /* 0x6D: PUNPCKHQDQ (src)xmmreg-or-mem, (dst)xmmreg */
4660//-- if (sz == 2
4661//-- && insn[0] == 0x0F
4662//-- && (insn[1] == 0x68 || insn[1] == 0x69
4663//-- || insn[1] == 0x6A || insn[1] == 0x6D)) {
4664//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16,
4665//-- "punpckh{bw,wd,dq,qdq}",
4666//-- 0x66, insn[0], insn[1] );
4667//-- goto decode_success;
4668//-- }
4669//--
4670//-- /* 0x14: UNPCKLPD (src)xmmreg-or-mem, (dst)xmmreg. Reads a+0
4671//-- .. a+7, so we can say size 8 */
4672//-- /* 0x15: UNPCKHPD (src)xmmreg-or-mem, (dst)xmmreg. Reads a+8
4673//-- .. a+15, but we have no way to express this, so better say size
4674//-- 16. Sigh. */
4675//-- if (sz == 2
4676//-- && insn[0] == 0x0F
4677//-- && (insn[1] == 0x14 || insn[1] == 0x15)) {
4678//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2,
4679//-- insn[1]==0x14 ? 8 : 16,
4680//-- "unpck{l,h}pd",
4681//-- 0x66, insn[0], insn[1] );
4682//-- goto decode_success;
4683//-- }
4684//--
4685//-- /* 0x14: UNPCKLPS (src)xmmreg-or-mem, (dst)xmmreg Reads a+0
4686//-- .. a+7, so we can say size 8 */
4687//-- /* 0x15: UNPCKHPS (src)xmmreg-or-mem, (dst)xmmreg Reads a+8
4688//-- .. a+15, but we have no way to express this, so better say size
4689//-- 16. Sigh. */
4690//-- if (sz == 4
4691//-- && insn[0] == 0x0F
4692//-- && (insn[1] == 0x14 || insn[1] == 0x15)) {
4693//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2,
4694//-- insn[1]==0x14 ? 8 : 16,
4695//-- "unpck{l,h}ps",
4696//-- insn[0], insn[1] );
4697//-- goto decode_success;
4698//-- }
4699//--
4700//-- /* 0xFC: PADDB (src)xmmreg-or-mem, (dst)xmmreg */
4701//-- /* 0xFD: PADDW (src)xmmreg-or-mem, (dst)xmmreg */
4702//-- /* 0xFE: PADDD (src)xmmreg-or-mem, (dst)xmmreg */
4703//-- /* 0xD4: PADDQ (src)xmmreg-or-mem, (dst)xmmreg */
4704//-- if (sz == 2
4705//-- && insn[0] == 0x0F
4706//-- && (insn[1] == 0xFC || insn[1] == 0xFD
4707//-- || insn[1] == 0xFE || insn[1] == 0xD4)) {
4708//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "padd{b,w,d,q}",
4709//-- 0x66, insn[0], insn[1] );
4710//-- goto decode_success;
4711//-- }
4712//--
4713//-- /* 0xEC: PADDSB (src)xmmreg-or-mem, (dst)xmmreg */
4714//-- /* 0xED: PADDSW (src)xmmreg-or-mem, (dst)xmmreg */
4715//-- if (sz == 2
4716//-- && insn[0] == 0x0F
4717//-- && (insn[1] == 0xEC || insn[1] == 0xED)) {
4718//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "padds{b,w}",
4719//-- 0x66, insn[0], insn[1] );
4720//-- goto decode_success;
4721//-- }
4722//--
4723//-- /* 0xDC: PADDUSB (src)xmmreg-or-mem, (dst)xmmreg */
4724//-- /* 0xDD: PADDUSW (src)xmmreg-or-mem, (dst)xmmreg */
4725//-- if (sz == 2
4726//-- && insn[0] == 0x0F
4727//-- && (insn[1] == 0xDC || insn[1] == 0xDD)) {
4728//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "paddus{b,w}",
4729//-- 0x66, insn[0], insn[1] );
4730//-- goto decode_success;
4731//-- }
4732//--
4733//-- /* 0xF8: PSUBB (src)xmmreg-or-mem, (dst)xmmreg */
4734//-- /* 0xF9: PSUBW (src)xmmreg-or-mem, (dst)xmmreg */
4735//-- /* 0xFA: PSUBD (src)xmmreg-or-mem, (dst)xmmreg */
4736//-- /* 0xFB: PSUBQ (src)xmmreg-or-mem, (dst)xmmreg */
4737//-- if (sz == 2
4738//-- && insn[0] == 0x0F
4739//-- && (insn[1] == 0xF8 || insn[1] == 0xF9
4740//-- || insn[1] == 0xFA || insn[1] == 0xFB)) {
4741//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psub{b,w,d,q}",
4742//-- 0x66, insn[0], insn[1] );
4743//-- goto decode_success;
4744//-- }
4745//--
4746//-- /* 0xE8: PSUBSB (src)xmmreg-or-mem, (dst)xmmreg */
4747//-- /* 0xE9: PSUBSW (src)xmmreg-or-mem, (dst)xmmreg */
4748//-- if (sz == 2
4749//-- && insn[0] == 0x0F
4750//-- && (insn[1] == 0xE8 || insn[1] == 0xE9)) {
4751//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psubs{b,w}",
4752//-- 0x66, insn[0], insn[1] );
4753//-- goto decode_success;
4754//-- }
4755//--
4756//-- /* 0xD8: PSUBUSB (src)xmmreg-or-mem, (dst)xmmreg */
4757//-- /* 0xD9: PSUBUSW (src)xmmreg-or-mem, (dst)xmmreg */
4758//-- if (sz == 2
4759//-- && insn[0] == 0x0F
4760//-- && (insn[1] == 0xD8 || insn[1] == 0xD9)) {
4761//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psubus{b,w}",
4762//-- 0x66, insn[0], insn[1] );
4763//-- goto decode_success;
4764//-- }
4765//--
4766//-- /* 0xE4: PMULHUW(src)xmmreg-or-mem, (dst)xmmreg */
4767//-- /* 0xE5: PMULHW(src)xmmreg-or-mem, (dst)xmmreg */
4768//-- /* 0xD5: PMULLW(src)xmmreg-or-mem, (dst)xmmreg */
4769//-- if (sz == 2
4770//-- && insn[0] == 0x0F
4771//-- && (insn[1] == 0xE4 || insn[1] == 0xE5 || insn[1] == 0xD5)) {
4772//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pmul{hu,h,l}w",
4773//-- 0x66, insn[0], insn[1] );
4774//-- goto decode_success;
4775//-- }
4776//--
4777//-- /* 0xD5: PMULUDQ(src)xmmreg-or-mem, (dst)xmmreg */
4778//-- if (sz == 2
4779//-- && insn[0] == 0x0F && insn[1] == 0xF4) {
4780//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pmuludq",
4781//-- 0x66, insn[0], insn[1] );
4782//-- goto decode_success;
4783//-- }
4784//--
4785//-- /* 0xF5: PMADDWD(src)xmmreg-or-mem, (dst)xmmreg */
4786//-- if (sz == 2
4787//-- && insn[0] == 0x0F
4788//-- && insn[1] == 0xF5) {
4789//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pmaddwd",
4790//-- 0x66, insn[0], insn[1] );
4791//-- goto decode_success;
4792//-- }
4793//--
4794//-- /* 0x74: PCMPEQB (src)xmmreg-or-mem, (dst)xmmreg */
4795//-- /* 0x75: PCMPEQW (src)xmmreg-or-mem, (dst)xmmreg */
4796//-- /* 0x76: PCMPEQD (src)xmmreg-or-mem, (dst)xmmreg */
4797//-- if (sz == 2
4798//-- && insn[0] == 0x0F
4799//-- && (insn[1] == 0x74 || insn[1] == 0x75 || insn[1] == 0x76)) {
4800//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pcmpeq{b,w,d}",
4801//-- 0x66, insn[0], insn[1] );
4802//-- goto decode_success;
4803//-- }
4804//--
4805//-- /* 0x64: PCMPGTB (src)xmmreg-or-mem, (dst)xmmreg */
4806//-- /* 0x65: PCMPGTW (src)xmmreg-or-mem, (dst)xmmreg */
4807//-- /* 0x66: PCMPGTD (src)xmmreg-or-mem, (dst)xmmreg */
4808//-- if (sz == 2
4809//-- && insn[0] == 0x0F
4810//-- && (insn[1] == 0x64 || insn[1] == 0x65 || insn[1] == 0x66)) {
4811//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pcmpgt{b,w,d}",
4812//-- 0x66, insn[0], insn[1] );
4813//-- goto decode_success;
4814//-- }
4815//--
4816//-- /* 0x63: PACKSSWB (src)xmmreg-or-mem, (dst)xmmreg */
4817//-- /* 0x6B: PACKSSDW (src)xmmreg-or-mem, (dst)xmmreg */
4818//-- if (sz == 2
4819//-- && insn[0] == 0x0F
4820//-- && (insn[1] == 0x63 || insn[1] == 0x6B)) {
4821//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "packss{wb,dw}",
4822//-- 0x66, insn[0], insn[1] );
4823//-- goto decode_success;
4824//-- }
4825//--
4826//-- /* 0x67: PACKUSWB (src)xmmreg-or-mem, (dst)xmmreg */
4827//-- if (sz == 2
4828//-- && insn[0] == 0x0F
4829//-- && insn[1] == 0x67) {
4830//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "packuswb",
4831//-- 0x66, insn[0], insn[1] );
4832//-- goto decode_success;
4833//-- }
4834//--
4835//-- /* 0xF1: PSLLW (src)xmmreg-or-mem, (dst)xmmreg */
4836//-- /* 0xF2: PSLLD (src)xmmreg-or-mem, (dst)xmmreg */
4837//-- /* 0xF3: PSLLQ (src)xmmreg-or-mem, (dst)xmmreg */
4838//-- if (sz == 2
4839//-- && insn[0] == 0x0F
4840//-- && (insn[1] == 0xF1 || insn[1] == 0xF2 || insn[1] == 0xF3)) {
4841//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psll{b,w,d}",
4842//-- 0x66, insn[0], insn[1] );
4843//-- goto decode_success;
4844//-- }
4845//--
4846//-- /* 0xD1: PSRLW (src)xmmreg-or-mem, (dst)xmmreg */
4847//-- /* 0xD2: PSRLD (src)xmmreg-or-mem, (dst)xmmreg */
4848//-- /* 0xD3: PSRLQ (src)xmmreg-or-mem, (dst)xmmreg */
4849//-- if (sz == 2
4850//-- && insn[0] == 0x0F
4851//-- && (insn[1] == 0xD1 || insn[1] == 0xD2 || insn[1] == 0xD3)) {
4852//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psrl{b,w,d}",
4853//-- 0x66, insn[0], insn[1] );
4854//-- goto decode_success;
4855//-- }
4856//--
4857//-- /* 0xE1: PSRAW (src)xmmreg-or-mem, (dst)xmmreg */
4858//-- /* 0xE2: PSRAD (src)xmmreg-or-mem, (dst)xmmreg */
4859//-- if (sz == 2
4860//-- && insn[0] == 0x0F
4861//-- && (insn[1] == 0xE1 || insn[1] == 0xE2)) {
4862//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "psra{w,d}",
4863//-- 0x66, insn[0], insn[1] );
4864//-- goto decode_success;
4865//-- }
4866//--
4867//-- /* (U)COMISD (src)xmmreg-or-mem, (dst)xmmreg */
4868//-- if (sz == 2
4869//-- && insn[0] == 0x0F
4870//-- && ( insn[1] == 0x2E || insn[1] == 0x2F ) ) {
4871//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 8, "{u}comisd",
4872//-- 0x66, insn[0], insn[1] );
4873//-- vg_assert(LAST_UINSTR(cb).opcode == SSE3a_MemRd
4874//-- || LAST_UINSTR(cb).opcode == SSE4);
4875//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
4876//-- goto decode_success;
4877//-- }
4878//--
4879//-- /* (U)COMISS (src)xmmreg-or-mem, (dst)xmmreg */
4880//-- if (sz == 4
4881//-- && insn[0] == 0x0F
4882//-- && ( insn[1] == 0x2E || insn[ 1 ] == 0x2F )) {
4883//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 4, "{u}comiss",
4884//-- insn[0], insn[1] );
4885//-- vg_assert(LAST_UINSTR(cb).opcode == SSE2a_MemRd
4886//-- || LAST_UINSTR(cb).opcode == SSE3);
4887//-- uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty);
4888//-- goto decode_success;
4889//-- }
4890//--
4891//-- /* MOVSD -- move 8 bytes of XMM reg to/from XMM reg or mem. */
4892//-- if (insn[0] == 0xF2
4893//-- && insn[1] == 0x0F
4894//-- && (insn[2] == 0x11 || insn[2] == 0x10)) {
4895//-- vg_assert(sz == 4);
4896//-- eip = dis_SSE3_load_store_or_mov
4897//-- ( cb, sorb, eip+3, 8, insn[2]==0x11, "movsd",
4898//-- insn[0], insn[1], insn[2] );
4899//-- goto decode_success;
4900//-- }
4901//--
4902//-- /* MOVQ -- move 8 bytes of XMM reg to XMM reg or mem. How
4903//-- does this differ from MOVSD ?? */
4904//-- if (sz == 2
4905//-- && insn[0] == 0x0F
4906//-- && insn[1] == 0xD6) {
4907//-- eip = dis_SSE3_load_store_or_mov
4908//-- ( cb, sorb, eip+2, 8, True /*store*/, "movq",
4909//-- 0x66, insn[0], insn[1] );
4910//-- goto decode_success;
4911//-- }
4912//--
4913//-- /* MOVQ -- move 8 bytes of XMM reg or mem to XMM reg. How
4914//-- does this differ from MOVSD ?? */
4915//-- if (insn[0] == 0xF3
4916//-- && insn[1] == 0x0F
4917//-- && insn[2] == 0x7E) {
4918//-- eip = dis_SSE3_load_store_or_mov
4919//-- ( cb, sorb, eip+3, 8, False /*load*/, "movq",
4920//-- insn[0], insn[1], insn[2] );
4921//-- goto decode_success;
4922//-- }
4923//--
4924//-- /* MOVDQ2Q -- move low 4 bytes of XMM reg to MMX reg. */
4925//-- if (insn[0] == 0xF2
4926//-- && insn[1] == 0x0F
4927//-- && insn[2] == 0xD6) {
4928//-- eip = dis_SSE3_to_MMX
4929//-- ( cb, sorb, eip+3, 8, "movdq2q",
4930//-- insn[0], insn[1], insn[2] );
4931//-- goto decode_success;
4932//-- }
4933//--
4934//-- /* MOVQ2DQ -- move MMX reg to low 4 bytes of XMM reg. */
4935//-- if (insn[0] == 0xF3
4936//-- && insn[1] == 0x0F
4937//-- && insn[2] == 0xD6) {
4938//-- eip = dis_SSE3_from_MMX
4939//-- ( cb, sorb, eip+3, 8, "movq2dq",
4940//-- insn[0], insn[1], insn[2] );
4941//-- goto decode_success;
4942//-- }
4943//--
4944//-- /* MOVSS -- move 4 bytes of XMM reg to/from XMM reg or mem. */
4945//-- if (insn[0] == 0xF3
4946//-- && insn[1] == 0x0F
4947//-- && (insn[2] == 0x11 || insn[2] == 0x10)) {
4948//-- vg_assert(sz == 4);
4949//-- eip = dis_SSE3_load_store_or_mov
4950//-- ( cb, sorb, eip+3, 4, insn[2]==0x11, "movss",
4951//-- insn[0], insn[1], insn[2] );
4952//-- goto decode_success;
4953//-- }
4954//--
4955//-- /* I don't understand how MOVAPD differs from MOVAPS. */
4956//-- /* MOVAPD (28,29) -- aligned load/store of xmm reg, or xmm-xmm reg
4957//-- move */
4958//-- if (sz == 2
4959//-- && insn[0] == 0x0F && insn[1] == 0x28) {
4960//-- UChar* name = "movapd";
4961//-- //(insn[1] == 0x10 || insn[1] == 0x11)
4962//-- // ? "movups" : "movaps";
4963//-- Bool store = False; //insn[1] == 0x29 || insn[1] == 11;
4964//-- eip = dis_SSE3_load_store_or_mov
4965//-- ( cb, sorb, eip+2, 16, store, name,
4966//-- 0x66, insn[0], insn[1] );
4967//-- goto decode_success;
4968//-- }
4969//--
4970//-- /* sz==4: MOVAPS (28,29) -- aligned load/store of xmm reg, or
4971//-- xmm-xmm reg move */
4972//-- /* sz==4: MOVUPS (10,11) -- unaligned load/store of xmm reg, or
4973//-- xmm-xmm reg move */
4974//-- /* sz==2: MOVAPD (28,29) -- aligned load/store of xmm reg, or
4975//-- xmm-xmm reg move */
4976//-- /* sz==2: MOVUPD (10,11) -- unaligned load/store of xmm reg, or
4977//-- xmm-xmm reg move */
4978//-- if (insn[0] == 0x0F && (insn[1] == 0x28
4979//-- || insn[1] == 0x29
4980//-- || insn[1] == 0x10
4981//-- || insn[1] == 0x11)) {
4982//-- UChar* name = (insn[1] == 0x10 || insn[1] == 0x11)
4983//-- ? "movups" : "movaps";
4984//-- Bool store = insn[1] == 0x29 || insn[1] == 11;
4985//-- vg_assert(sz == 2 || sz == 4);
4986//-- if (sz == 4) {
4987//-- eip = dis_SSE2_load_store_or_mov
4988//-- ( cb, sorb, eip+2, 16, store, name,
4989//-- insn[0], insn[1] );
4990//-- } else {
4991//-- eip = dis_SSE3_load_store_or_mov
4992//-- ( cb, sorb, eip+2, 16, store, name,
4993//-- 0x66, insn[0], insn[1] );
4994//-- }
4995//-- goto decode_success;
4996//-- }
4997//--
4998//-- /* MOVDQA -- aligned 16-byte load/store. */
4999//-- if (sz == 2
5000//-- && insn[0] == 0x0F
5001//-- && (insn[1] == 0x6F || insn[1] == 0x7F)) {
5002//-- Bool is_store = insn[1]==0x7F;
5003//-- eip = dis_SSE3_load_store_or_mov
5004//-- (cb, sorb, eip+2, 16, is_store, "movdqa",
5005//-- 0x66, insn[0], insn[1] );
5006//-- goto decode_success;
5007//-- }
5008//--
5009//-- /* MOVDQU -- unaligned 16-byte load/store. */
5010//-- if (insn[0] == 0xF3
5011//-- && insn[1] == 0x0F
5012//-- && (insn[2] == 0x6F || insn[2] == 0x7F)) {
5013//-- Bool is_store = insn[2]==0x7F;
5014//-- eip = dis_SSE3_load_store_or_mov
5015//-- (cb, sorb, eip+3, 16, is_store, "movdqu",
5016//-- insn[0], insn[1], insn[2] );
5017//-- goto decode_success;
5018//-- }
5019//--
5020//-- /* MOVNTDQ -- 16-byte store with temporal hint (which we
5021//-- ignore). */
5022//-- if (sz == 2
5023//-- && insn[0] == 0x0F
5024//-- && insn[1] == 0xE7) {
5025//-- eip = dis_SSE3_load_store_or_mov
5026//-- (cb, sorb, eip+2, 16, True /* is_store */, "movntdq",
5027//-- 0x66, insn[0], insn[1] );
5028//-- goto decode_success;
5029//-- }
5030//--
5031//-- /* MOVNTPS -- 16-byte store with temporal hint (which we
5032//-- ignore). */
5033//-- if (insn[0] == 0x0F
5034//-- && insn[1] == 0x2B) {
5035//-- eip = dis_SSE2_load_store_or_mov
5036//-- (cb, sorb, eip+2, 16, True /* is_store */, "movntps",
5037//-- insn[0], insn[1] );
5038//-- goto decode_success;
5039//-- }
5040//--
5041//-- /* MOVNTPD -- 16-byte store with temporal hint (which we
5042//-- ignore). */
5043//-- if (sz == 2
5044//-- && insn[0] == 0x0F
5045//-- && insn[1] == 0x2B) {
5046//-- eip = dis_SSE3_load_store_or_mov
5047//-- (cb, sorb, eip+2, 16, True /* is_store */, "movntpd",
5048//-- 0x66, insn[0], insn[1] );
5049//-- goto decode_success;
5050//-- }
5051//--
5052//-- /* MOVD -- 4-byte move between xmmregs and (ireg or memory). */
5053//-- if (sz == 2
5054//-- && insn[0] == 0x0F
5055//-- && (insn[1] == 0x6E || insn[1] == 0x7E)) {
5056//-- Bool is_store = insn[1]==0x7E;
5057//-- modrm = insn[2];
5058//-- if (epartIsReg(modrm) && is_store) {
5059//-- t1 = newTemp(cb);
5060//-- uInstr3(cb, SSE3e_RegWr, 4,
5061//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5062//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5063//-- TempReg, t1 );
5064//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, eregOfRM(modrm));
5065//-- DIP("movd %s, %s\n",
5066//-- nameXMMReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
5067//-- eip += 3;
5068//-- } else
5069//-- if (epartIsReg(modrm) && !is_store) {
5070//-- t1 = newTemp(cb);
5071//-- uInstr2(cb, GET, 4, ArchReg, eregOfRM(modrm), TempReg, t1);
5072//-- uInstr3(cb, SSE3e_RegRd, 4,
5073//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5074//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5075//-- TempReg, t1 );
5076//-- DIP("movd %s, %s\n",
5077//-- nameIReg(4,eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)));
5078//-- eip += 3;
5079//-- } else {
5080//-- eip = dis_SSE3_load_store_or_mov
5081//-- (cb, sorb, eip+2, 4, is_store, "movd",
5082//-- 0x66, insn[0], insn[1] );
5083//-- }
5084//-- goto decode_success;
5085//-- }
5086//--
5087//-- /* PEXTRW from SSE register; writes ireg */
5088//-- if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC5) {
5089//-- t1 = newTemp(cb);
5090//-- modrm = insn[2];
5091//-- vg_assert(epartIsReg(modrm));
5092//-- vg_assert((modrm & 0xC0) == 0xC0);
5093//-- uInstr3(cb, SSE3g1_RegWr, 4,
5094//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5095//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5096//-- TempReg, t1 );
5097//-- uLiteral(cb, insn[3]);
5098//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
5099//-- DIP("pextrw %s, %d, %s\n",
5100//-- nameXMMReg(eregOfRM(modrm)), (Int)insn[3],
5101//-- nameIReg(4, gregOfRM(modrm)));
5102//-- eip += 4;
5103//-- goto decode_success;
5104//-- }
5105//--
5106//-- /* PINSRW to SSE register; reads mem or ireg */
5107//-- if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xC4) {
5108//-- t1 = newTemp(cb);
5109//-- modrm = insn[2];
5110//-- if (epartIsReg(modrm)) {
5111//-- uInstr2(cb, GET, 2, ArchReg, eregOfRM(modrm), TempReg, t1);
5112//-- vg_assert(epartIsReg(modrm));
5113//-- uInstr3(cb, SSE3e1_RegRd, 2,
5114//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5115//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5116//-- TempReg, t1 );
5117//-- uLiteral(cb, insn[3]);
5118//-- DIP("pinsrw %s, %d, %s\n",
5119//-- nameIReg(2, eregOfRM(modrm)), (Int)insn[3],
5120//-- nameXMMReg(gregOfRM(modrm)));
5121//-- eip += 4;
5122//-- } else {
5123//-- VG_(core_panic)("PINSRW mem");
5124//-- }
5125//-- goto decode_success;
5126//-- }
5127//--
5128//-- /* SQRTSD: square root of scalar double. */
5129//-- if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x51) {
5130//-- vg_assert(sz == 4);
5131//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8,
5132//-- "sqrtsd",
5133//-- insn[0], insn[1], insn[2] );
5134//-- goto decode_success;
5135//-- }
5136//--
5137//-- /* SQRTSS: square root of scalar float. */
5138//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x51) {
5139//-- vg_assert(sz == 4);
5140//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 4,
5141//-- "sqrtss",
5142//-- insn[0], insn[1], insn[2] );
5143//-- goto decode_success;
5144//-- }
5145//--
5146//-- /* RSQRTSS: square root reciprocal of scalar float. */
5147//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x52) {
5148//-- vg_assert(sz == 4);
5149//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 4,
5150//-- "sqrtss",
5151//-- insn[0], insn[1], insn[2] );
5152//-- goto decode_success;
5153//-- }
5154//--
5155//-- /* 0xF3: RCPSS -- reciprocal of scalar float */
5156//-- if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x53) {
5157//-- vg_assert(sz == 4);
5158//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 4,
5159//-- "rcpss",
5160//-- insn[0], insn[1], insn[2] );
5161//-- goto decode_success;
5162//-- }
5163//--
5164//-- /* MOVMSKPD -- extract 2 sign bits from a xmm reg and copy them to
5165//-- an ireg. Top 30 bits of ireg are set to zero. */
5166//-- /* MOVMSKPS -- extract 4 sign bits from a xmm reg and copy them to
5167//-- an ireg. Top 28 bits of ireg are set to zero. */
5168//-- if (insn[0] == 0x0F && insn[1] == 0x50) {
5169//-- vg_assert(sz == 4 || sz == 2);
5170//-- modrm = insn[2];
5171//-- /* Intel docs don't say anything about a memory source being
5172//-- allowed here. */
5173//-- vg_assert(epartIsReg(modrm));
5174//-- t1 = newTemp(cb);
5175//-- if (sz == 4) {
5176//-- uInstr3(cb, SSE2g_RegWr, 4,
5177//-- Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
5178//-- Lit16, (UShort)modrm,
5179//-- TempReg, t1 );
5180//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
5181//-- } else {
5182//-- uInstr3(cb, SSE3g_RegWr, 4,
5183//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5184//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5185//-- TempReg, t1 );
5186//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
5187//-- }
5188//-- DIP("movmskp%c %s, %s\n", sz == 4 ? 's' : 'd',
5189//-- nameXMMReg(eregOfRM(modrm)), nameIReg(4,gregOfRM(modrm)));
5190//-- eip += 3;
5191//-- goto decode_success;
5192//-- }
5193//--
5194//-- /* ANDNPS */
5195//-- /* 0x66: ANDNPD (src)xmmreg-or-mem, (dst)xmmreg */
5196//-- if (insn[0] == 0x0F && insn[1] == 0x55) {
5197//-- vg_assert(sz == 4 || sz == 2);
5198//-- if (sz == 4) {
5199//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "andnps",
5200//-- insn[0], insn[1] );
5201//-- } else {
5202//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "andnpd",
5203//-- 0x66, insn[0], insn[1] );
5204//-- }
5205//-- goto decode_success;
5206//-- }
5207//--
5208//-- /* MOVHLPS -- move two packed floats from high quadword to low quadword */
5209//-- /* MOVLPS -- load/store two packed floats to/from low quadword. */
5210//-- /* MOVLPD -- load/store packed double to/from low quadword. */
5211//-- if (insn[0] == 0x0F
5212//-- && (insn[1] == 0x12 || insn[1] == 0x13)) {
5213//-- Bool is_store = insn[1]==0x13;
5214//-- vg_assert(sz == 4 || sz == 2);
5215//-- if (sz == 4) {
5216//-- if (epartIsReg(insn[2])) {
5217//-- vg_assert(insn[1]==0x12);
5218//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "movhlps",
5219//-- insn[0], insn[1] );
5220//-- } else {
5221//-- eip = dis_SSE2_load_store_or_mov
5222//-- (cb, sorb, eip+2, 8, is_store, "movlps",
5223//-- insn[0], insn[1] );
5224//-- }
5225//-- } else {
5226//-- vg_assert(!epartIsReg(insn[2]));
5227//-- eip = dis_SSE3_load_store_or_mov
5228//-- (cb, sorb, eip+2, 8, is_store, "movlpd",
5229//-- 0x66, insn[0], insn[1] );
5230//-- }
5231//-- goto decode_success;
5232//-- }
5233//--
5234//-- /* MOVLHPS -- move two packed floats from low quadword to high quadword */
5235//-- /* MOVHPS -- load/store two packed floats to/from high quadword. */
5236//-- /* MOVHPD -- load/store packed double to/from high quadword. */
5237//-- if (insn[0] == 0x0F
5238//-- && (insn[1] == 0x16 || insn[1] == 0x17)) {
5239//-- Bool is_store = insn[1]==0x17;
5240//-- vg_assert(sz == 4 || sz == 2);
5241//-- if (sz == 4) {
5242//-- if (epartIsReg(insn[2])) {
5243//-- vg_assert(insn[1]==0x16);
5244//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16, "movlhps",
5245//-- insn[0], insn[1] );
5246//-- } else {
5247//-- eip = dis_SSE2_load_store_or_mov
5248//-- (cb, sorb, eip+2, 8, is_store, "movhps",
5249//-- insn[0], insn[1] );
5250//-- }
5251//-- } else {
5252//-- vg_assert(!epartIsReg(insn[2]));
5253//-- eip = dis_SSE3_load_store_or_mov
5254//-- (cb, sorb, eip+2, 8, is_store, "movhpd",
5255//-- 0x66, insn[0], insn[1] );
5256//-- }
5257//-- goto decode_success;
5258//-- }
5259//--
5260//-- /* PMOVMSKB -- extract 16 sign bits from a xmm reg and copy them to
5261//-- an ireg. Top 16 bits of ireg are set to zero. */
5262//-- if (sz == 2 && insn[0] == 0x0F && insn[1] == 0xD7) {
5263//-- modrm = insn[2];
5264//-- /* Intel docs don't say anything about a memory source being
5265//-- allowed here. */
5266//-- vg_assert(epartIsReg(modrm));
5267//-- t1 = newTemp(cb);
5268//-- uInstr3(cb, SSE3g_RegWr, 4,
5269//-- Lit16, (((UShort)0x66) << 8) | (UShort)insn[0],
5270//-- Lit16, (((UShort)insn[1]) << 8) | (UShort)modrm,
5271//-- TempReg, t1 );
5272//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
5273//-- DIP("pmovmskb %s, %s\n",
5274//-- nameXMMReg(eregOfRM(modrm)), nameIReg(4,gregOfRM(modrm)));
5275//-- eip += 3;
5276//-- goto decode_success;
5277//-- }
5278//--
5279//-- /* sz==4: SQRTPS: square root of packed float. */
5280//-- /* sz==2: SQRTPD: square root of packed double. */
5281//-- if (insn[0] == 0x0F && insn[1] == 0x51) {
5282//-- vg_assert(sz == 2 || sz == 4);
5283//-- if (sz == 4) {
5284//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16,
5285//-- "sqrtps",
5286//-- insn[0], insn[1] );
5287//-- } else {
5288//-- eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16,
5289//-- "sqrtpd",
5290//-- 0x66, insn[0], insn[1] );
5291//-- }
5292//-- goto decode_success;
5293//-- }
5294//--
5295//-- /* RSQRTPS: square root reciprocal of packed float. */
5296//-- if (insn[0] == 0x0F && insn[1] == 0x52) {
5297//-- vg_assert(sz == 4);
5298//-- eip = dis_SSE2_reg_or_mem ( cb, sorb, eip+2, 16,
5299//-- "rsqrtps",
5300//-- insn[0], insn[1] );
5301//-- goto decode_success;
5302//-- }
5303//--
5304//-- /* Fall through into the non-SSE decoder. */
5305//--
5306//-- } /* if (VG_(have_ssestate)) */
5307
5308
5309 /* ---------------------------------------------------- */
5310 /* --- end of the SSE/SSE2 decoder. --- */
5311 /* ---------------------------------------------------- */
5312
5313 /* Get the primary opcode. */
5314 opc = getIByte(delta); delta++;
5315
5316 /* We get here if the current insn isn't SSE, or this CPU doesn't
5317 support SSE. */
5318
5319 switch (opc) {
5320
5321 /* ------------------------ Control flow --------------- */
5322//--
5323//-- case 0xC2: /* RET imm16 */
5324//-- d32 = getUDisp16(eip); eip += 2;
5325//-- dis_ret(cb, d32);
5326//-- *isEnd = True;
5327//-- DIP("ret %d\n", d32);
5328//-- break;
5329//-- case 0xC3: /* RET */
5330//-- dis_ret(cb, 0);
5331//-- *isEnd = True;
5332//-- DIP("ret\n");
5333//-- break;
sewardjd1061ab2004-07-08 01:45:30 +00005334
5335 case 0xE8: /* CALL J4 */
5336 d32 = getUDisp32(delta); delta += 4;
5337 d32 += (guest_eip+delta);
5338 /* (guest_eip+delta) == return-to addr, d32 == call-to addr */
5339#if 0
5340 if (d32 == eip && getIByte(delta) >= 0x58
5341 && getIByte(delta) <= 0x5F) {
5342 /* Specially treat the position-independent-code idiom
5343 call X
5344 X: popl %reg
5345 as
5346 movl %eip, %reg.
5347 since this generates better code, but for no other reason. */
5348 Int archReg = getIByte(delta) - 0x58;
5349 /* VG_(printf)("-- fPIC thingy\n"); */
5350 t1 = newTemp(cb);
5351 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t1);
5352 uLiteral(cb, eip);
5353 uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, archReg);
5354 delta++; /* Step over the POP */
5355 DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
5356 } else
5357#endif
5358 {
5359 /* The normal sequence for a call. */
5360 t1 = newTemp(Ity_I32);
5361 stmt( assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4))) );
5362 stmt( putIReg(4, R_ESP, mkexpr(t1)) );
5363 stmt( storeLE( mkexpr(t1), mkU32(guest_eip+delta)) );
5364 jmp_lit(d32);
5365 // LAST_UINSTR(cb).jmpkind = JmpCall;
5366 *isEnd = True;
5367 DIP("call 0x%x\n",d32);
5368 }
5369 break;
5370
sewardjc9a65702004-07-07 16:32:57 +00005371//-- case 0xC8: /* ENTER */
5372//-- d32 = getUDisp16(eip); eip += 2;
5373//-- abyte = getIByte(delta); delta++;
5374//--
5375//-- vg_assert(sz == 4);
5376//-- vg_assert(abyte == 0);
5377//--
5378//-- t1 = newTemp(cb); t2 = newTemp(cb);
5379//-- uInstr2(cb, GET, sz, ArchReg, R_EBP, TempReg, t1);
5380//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
5381//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
5382//-- uLiteral(cb, sz);
5383//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
5384//-- uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
5385//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_EBP);
5386//-- if (d32) {
5387//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
5388//-- uLiteral(cb, d32);
5389//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
5390//-- }
5391//-- DIP("enter 0x%x, 0x%x", d32, abyte);
5392//-- break;
5393//--
5394//-- case 0xC9: /* LEAVE */
5395//-- t1 = newTemp(cb); t2 = newTemp(cb);
5396//-- uInstr2(cb, GET, 4, ArchReg, R_EBP, TempReg, t1);
5397//-- /* First PUT ESP looks redundant, but need it because ESP must
5398//-- always be up-to-date for Memcheck to work... */
5399//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ESP);
5400//-- uInstr2(cb, LOAD, 4, TempReg, t1, TempReg, t2);
5401//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_EBP);
5402//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t1);
5403//-- uLiteral(cb, 4);
5404//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ESP);
5405//-- DIP("leave");
5406//-- break;
5407//--
5408//-- /* ---------------- Misc weird-ass insns --------------- */
5409//--
5410//-- case 0x27: /* DAA */
5411//-- case 0x2F: /* DAS */
5412//-- t1 = newTemp(cb);
5413//-- uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t1);
5414//-- /* Widen %AL to 32 bits, so it's all defined when we push it. */
5415//-- uInstr1(cb, WIDEN, 4, TempReg, t1);
5416//-- uWiden(cb, 1, False);
5417//-- uInstr0(cb, CALLM_S, 0);
5418//-- uInstr1(cb, PUSH, 4, TempReg, t1);
5419//-- uInstr1(cb, CALLM, 0, Lit16,
5420//-- opc == 0x27 ? VGOFF_(helper_DAA) : VGOFF_(helper_DAS) );
5421//-- uFlagsRWU(cb, FlagsAC, FlagsSZACP, FlagO);
5422//-- uInstr1(cb, POP, 4, TempReg, t1);
5423//-- uInstr0(cb, CALLM_E, 0);
5424//-- uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, R_AL);
5425//-- DIP(opc == 0x27 ? "daa\n" : "das\n");
5426//-- break;
5427//--
5428//-- case 0x37: /* AAA */
5429//-- case 0x3F: /* AAS */
5430//-- t1 = newTemp(cb);
5431//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
5432//-- /* Widen %AL to 32 bits, so it's all defined when we push it. */
5433//-- uInstr1(cb, WIDEN, 4, TempReg, t1);
5434//-- uWiden(cb, 2, False);
5435//-- uInstr0(cb, CALLM_S, 0);
5436//-- uInstr1(cb, PUSH, 4, TempReg, t1);
5437//-- uInstr1(cb, CALLM, 0, Lit16,
5438//-- opc == 0x37 ? VGOFF_(helper_AAA) : VGOFF_(helper_AAS) );
5439//-- uFlagsRWU(cb, FlagA, FlagsAC, FlagsEmpty);
5440//-- uInstr1(cb, POP, 4, TempReg, t1);
5441//-- uInstr0(cb, CALLM_E, 0);
5442//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
5443//-- DIP(opc == 0x37 ? "aaa\n" : "aas\n");
5444//-- break;
5445//--
5446//-- case 0xD4: /* AAM */
5447//-- case 0xD5: /* AAD */
5448//-- d32 = getIByte(delta); delta++;
5449//-- if (d32 != 10) VG_(core_panic)("disInstr: AAM/AAD but base not 10 !");
5450//-- t1 = newTemp(cb);
5451//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
5452//-- /* Widen %AX to 32 bits, so it's all defined when we push it. */
5453//-- uInstr1(cb, WIDEN, 4, TempReg, t1);
5454//-- uWiden(cb, 2, False);
5455//-- uInstr0(cb, CALLM_S, 0);
5456//-- uInstr1(cb, PUSH, 4, TempReg, t1);
5457//-- uInstr1(cb, CALLM, 0, Lit16,
5458//-- opc == 0xD4 ? VGOFF_(helper_AAM) : VGOFF_(helper_AAD) );
5459//-- uFlagsRWU(cb, FlagsEmpty, FlagsSZP, FlagsEmpty);
5460//-- uInstr1(cb, POP, 4, TempReg, t1);
5461//-- uInstr0(cb, CALLM_E, 0);
5462//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
5463//-- DIP(opc == 0xD4 ? "aam\n" : "aad\n");
5464//-- break;
5465//--
5466//-- /* ------------------------ CWD/CDQ -------------------- */
5467//--
5468//-- case 0x98: /* CBW */
5469//-- t1 = newTemp(cb);
5470//-- if (sz == 4) {
5471//-- uInstr2(cb, GET, 2, ArchReg, R_EAX, TempReg, t1);
5472//-- uInstr1(cb, WIDEN, 4, TempReg, t1); /* 4 == dst size */
5473//-- uWiden(cb, 2, True);
5474//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_EAX);
5475//-- DIP("cwd\n");
5476//-- } else {
5477//-- vg_assert(sz == 2);
5478//-- uInstr2(cb, GET, 1, ArchReg, R_EAX, TempReg, t1);
5479//-- uInstr1(cb, WIDEN, 2, TempReg, t1); /* 2 == dst size */
5480//-- uWiden(cb, 1, True);
5481//-- uInstr2(cb, PUT, 2, TempReg, t1, ArchReg, R_EAX);
5482//-- DIP("cbw\n");
5483//-- }
5484//-- break;
5485//--
5486//-- case 0x99: /* CWD/CDQ */
5487//-- t1 = newTemp(cb);
5488//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1);
5489//-- uInstr2(cb, SAR, sz, Literal, 0, TempReg, t1);
5490//-- uLiteral(cb, sz == 2 ? 15 : 31);
5491//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EDX);
5492//-- DIP(sz == 2 ? "cwdq\n" : "cdqq\n");
5493//-- break;
5494//--
5495//-- /* ------------------------ FPU ops -------------------- */
5496//--
5497//-- case 0x9E: /* SAHF */
5498//-- codegen_SAHF ( cb );
5499//-- DIP("sahf\n");
5500//-- break;
5501//--
5502//-- case 0x9F: /* LAHF */
5503//-- codegen_LAHF ( cb );
5504//-- DIP("lahf\n");
5505//-- break;
5506//--
5507//-- case 0x9B: /* FWAIT */
5508//-- /* ignore? */
5509//-- DIP("fwait\n");
5510//-- break;
5511//--
5512//-- case 0xD8:
5513//-- case 0xD9:
5514//-- case 0xDA:
5515//-- case 0xDB:
5516//-- case 0xDC:
5517//-- case 0xDD:
5518//-- case 0xDE:
5519//-- case 0xDF:
5520//-- eip = dis_fpu ( cb, sorb, opc, eip );
5521//-- break;
5522//--
5523//-- /* ------------------------ INC & DEC ------------------ */
5524//--
5525//-- case 0x40: /* INC eAX */
5526//-- case 0x41: /* INC eCX */
5527//-- case 0x42: /* INC eDX */
5528//-- case 0x43: /* INC eBX */
5529//-- case 0x44: /* INC eSP */
5530//-- case 0x45: /* INC eBP */
5531//-- case 0x46: /* INC eSI */
5532//-- case 0x47: /* INC eDI */
5533//-- t1 = newTemp(cb);
5534//-- uInstr2(cb, GET, sz, ArchReg, (UInt)(opc - 0x40),
5535//-- TempReg, t1);
5536//-- uInstr1(cb, INC, sz, TempReg, t1);
5537//-- setFlagsFromUOpcode(cb, INC);
5538//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg,
5539//-- (UInt)(opc - 0x40));
5540//-- DIP("inc%c %s\n", nameISize(sz), nameIReg(sz,opc-0x40));
5541//-- break;
5542//--
5543//-- case 0x48: /* DEC eAX */
5544//-- case 0x49: /* DEC eCX */
5545//-- case 0x4A: /* DEC eDX */
5546//-- case 0x4B: /* DEC eBX */
5547//-- case 0x4C: /* DEC eSP */
5548//-- case 0x4D: /* DEC eBP */
5549//-- case 0x4E: /* DEC eSI */
5550//-- case 0x4F: /* DEC eDI */
5551//-- t1 = newTemp(cb);
5552//-- uInstr2(cb, GET, sz, ArchReg, (UInt)(opc - 0x48),
5553//-- TempReg, t1);
5554//-- uInstr1(cb, DEC, sz, TempReg, t1);
5555//-- setFlagsFromUOpcode(cb, DEC);
5556//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg,
5557//-- (UInt)(opc - 0x48));
5558//-- DIP("dec%c %s\n", nameISize(sz), nameIReg(sz,opc-0x48));
5559//-- break;
5560//--
5561//-- /* ------------------------ INT ------------------------ */
5562//--
5563//-- case 0xCD: /* INT imm8 */
5564//-- d32 = getIByte(delta); delta++;
5565//-- if (d32 != 0x80) goto decode_failure;
5566//-- /* It's important that all ArchRegs carry their up-to-date value
5567//-- at this point. So we declare an end-of-block here, which
5568//-- forces any TempRegs caching ArchRegs to be flushed. */
5569//-- jmp_lit(cb, eip);
5570//-- LAST_UINSTR(cb).jmpkind = JmpSyscall;
5571//-- *isEnd = True;
5572//-- DIP("int $0x80\n");
5573//-- break;
5574//--
5575//-- /* ------------------------ Jcond, byte offset --------- */
5576//--
5577//-- case 0xEB: /* Jb (jump, byte offset) */
5578//-- d32 = (eip+1) + getSDisp8(eip); eip++;
5579//-- jmp_lit(cb, d32);
5580//-- *isEnd = True;
5581//-- DIP("jmp-8 0x%x\n", d32);
5582//-- break;
5583//--
5584//-- case 0xE9: /* Jv (jump, 16/32 offset) */
5585//-- d32 = (eip+sz) + getSDisp(sz,eip); eip += sz;
5586//-- jmp_lit(cb, d32);
5587//-- *isEnd = True;
5588//-- DIP("jmp 0x%x\n", d32);
5589//-- break;
5590//--
5591//-- case 0x70:
5592//-- case 0x71:
5593//-- case 0x72: /* JBb/JNAEb (jump below) */
5594//-- case 0x73: /* JNBb/JAEb (jump not below) */
5595//-- case 0x74: /* JZb/JEb (jump zero) */
5596//-- case 0x75: /* JNZb/JNEb (jump not zero) */
5597//-- case 0x76: /* JBEb/JNAb (jump below or equal) */
5598//-- case 0x77: /* JNBEb/JAb (jump not below or equal) */
5599//-- case 0x78: /* JSb (jump negative) */
5600//-- case 0x79: /* JSb (jump not negative) */
5601//-- case 0x7A: /* JP (jump parity even) */
5602//-- case 0x7B: /* JNP/JPO (jump parity odd) */
5603//-- case 0x7C: /* JLb/JNGEb (jump less) */
5604//-- case 0x7D: /* JGEb/JNLb (jump greater or equal) */
5605//-- case 0x7E: /* JLEb/JNGb (jump less or equal) */
5606//-- case 0x7F: /* JGb/JNLEb (jump greater) */
5607//-- d32 = (eip+1) + getSDisp8(eip); eip++;
5608//-- jcc_lit(cb, d32, (Condcode)(opc - 0x70));
5609//-- /* It's actually acceptable not to end this basic block at a
5610//-- control transfer, reducing the number of jumps through
5611//-- vg_dispatch, at the expense of possibly translating the insns
5612//-- following this jump twice. This does give faster code, but
5613//-- on the whole I don't think the effort is worth it. */
5614//-- jmp_lit(cb, eip);
5615//-- *isEnd = True;
5616//-- /* The above 3 lines would be removed if the bb was not to end
5617//-- here. */
5618//-- DIP("j%s-8 0x%x\n", VG_(name_UCondcode)(opc - 0x70), d32);
5619//-- break;
5620//--
5621//-- case 0xE3: /* JECXZ or perhaps JCXZ, depending on OSO ? Intel
5622//-- manual says it depends on address size override,
5623//-- which doesn't sound right to me. */
5624//-- d32 = (eip+1) + getSDisp8(eip); eip++;
5625//-- t1 = newTemp(cb);
5626//-- uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
5627//-- uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
5628//-- uLiteral(cb, d32);
5629//-- DIP("j%sz 0x%x\n", nameIReg(sz, R_ECX), d32);
5630//-- break;
5631//--
5632//-- case 0xE0: /* LOOPNE disp8 */
5633//-- case 0xE1: /* LOOPE disp8 */
5634//-- case 0xE2: /* LOOP disp8 */
5635//-- /* Again, the docs say this uses ECX/CX as a count depending on
5636//-- the address size override, not the operand one. Since we
5637//-- don't handle address size overrides, I guess that means
5638//-- ECX. */
5639//-- d32 = (eip+1) + getSDisp8(eip); eip++;
5640//-- t1 = newTemp(cb);
5641//-- uInstr2(cb, GET, 4, ArchReg, R_ECX, TempReg, t1);
5642//-- uInstr1(cb, DEC, 4, TempReg, t1);
5643//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ECX);
5644//-- uInstr2(cb, JIFZ, 4, TempReg, t1, Literal, 0);
5645//-- uLiteral(cb, eip);
5646//-- if (opc == 0xE0 || opc == 0xE1) { /* LOOPE/LOOPNE */
5647//-- jcc_lit(cb, eip, (opc == 0xE1 ? CondNZ : CondZ));
5648//-- }
5649//-- jmp_lit(cb, d32);
5650//-- *isEnd = True;
5651//-- DIP("loop 0x%x\n", d32);
5652//-- break;
5653//--
5654//-- /* ------------------------ IMUL ----------------------- */
5655//--
5656//-- case 0x69: /* IMUL Iv, Ev, Gv */
5657//-- eip = dis_imul_I_E_G ( cb, sorb, sz, eip, sz );
5658//-- break;
5659//-- case 0x6B: /* IMUL Ib, Ev, Gv */
5660//-- eip = dis_imul_I_E_G ( cb, sorb, sz, eip, 1 );
5661//-- break;
5662//--
5663//-- /* ------------------------ MOV ------------------------ */
5664//--
5665//-- case 0x88: /* MOV Gb,Eb */
5666//-- eip = dis_mov_G_E(cb, sorb, 1, eip);
5667//-- break;
5668
5669 case 0x89: /* MOV Gv,Ev */
5670 delta = dis_mov_G_E(sorb, sz, delta);
5671 break;
5672
5673//-- case 0x8A: /* MOV Eb,Gb */
5674//-- eip = dis_mov_E_G(cb, sorb, 1, eip);
5675//-- break;
5676//--
5677//-- case 0x8B: /* MOV Ev,Gv */
5678//-- eip = dis_mov_E_G(cb, sorb, sz, eip);
5679//-- break;
5680//--
5681//-- case 0x8D: /* LEA M,Gv */
5682//-- modrm = getIByte(delta);
5683//-- if (epartIsReg(modrm))
5684//-- VG_(core_panic)("LEA M,Gv: modRM refers to register");
5685//-- /* NOTE! this is the one place where a segment override prefix
5686//-- has no effect on the address calculation. Therefore we pass
5687//-- zero instead of sorb here. */
5688//-- pair = disAMode ( cb, /*sorb*/ 0, eip, dis_buf );
5689//-- eip += HI8(pair);
5690//-- t1 = LOW24(pair);
5691//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, gregOfRM(modrm));
5692//-- DIP("lea%c %s, %s\n", nameISize(sz), dis_buf,
5693//-- nameIReg(sz,gregOfRM(modrm)));
5694//-- break;
5695//--
5696//-- case 0x8C: /* MOV Sw,Ew -- MOV from a SEGMENT REGISTER */
5697//-- eip = dis_mov_Sw_Ew(cb, sorb, eip);
5698//-- break;
5699//--
5700//-- case 0x8E: /* MOV Ew,Sw -- MOV to a SEGMENT REGISTER */
5701//-- eip = dis_mov_Ew_Sw(cb, sorb, eip);
5702//-- break;
5703//--
5704//-- case 0xA0: /* MOV Ob,AL */
5705//-- sz = 1;
5706//-- /* Fall through ... */
5707//-- case 0xA1: /* MOV Ov,eAX */
5708//-- d32 = getUDisp32(eip); eip += 4;
5709//-- t1 = newTemp(cb); t2 = newTemp(cb);
5710//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
5711//-- uLiteral(cb, d32);
5712//-- handleSegOverride(cb, sorb, t2);
5713//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
5714//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, R_EAX);
5715//-- DIP("mov%c %s0x%x, %s\n", nameISize(sz), sorbTxt(sorb),
5716//-- d32, nameIReg(sz,R_EAX));
5717//-- break;
5718//--
5719//-- case 0xA2: /* MOV AL,Ob */
5720//-- sz = 1;
5721//-- /* Fall through ... */
5722//-- case 0xA3: /* MOV eAX,Ov */
5723//-- d32 = getUDisp32(eip); eip += 4;
5724//-- t1 = newTemp(cb); t2 = newTemp(cb);
5725//-- uInstr2(cb, GET, sz, ArchReg, R_EAX, TempReg, t1);
5726//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
5727//-- uLiteral(cb, d32);
5728//-- handleSegOverride(cb, sorb, t2);
5729//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
5730//-- DIP("mov%c %s, %s0x%x\n", nameISize(sz), nameIReg(sz,R_EAX),
5731//-- sorbTxt(sorb), d32);
5732//-- break;
5733//--
5734//-- case 0xB0: /* MOV imm,AL */
5735//-- case 0xB1: /* MOV imm,CL */
5736//-- case 0xB2: /* MOV imm,DL */
5737//-- case 0xB3: /* MOV imm,BL */
5738//-- case 0xB4: /* MOV imm,AH */
5739//-- case 0xB5: /* MOV imm,CH */
5740//-- case 0xB6: /* MOV imm,DH */
5741//-- case 0xB7: /* MOV imm,BH */
5742//-- d32 = getIByte(delta); eip += 1;
5743//-- t1 = newTemp(cb);
5744//-- uInstr2(cb, MOV, 1, Literal, 0, TempReg, t1);
5745//-- uLiteral(cb, d32);
5746//-- uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, opc-0xB0);
5747//-- DIP("movb $0x%x,%s\n", d32, nameIReg(1,opc-0xB0));
5748//-- break;
5749//--
5750//-- case 0xB8: /* MOV imm,eAX */
5751//-- case 0xB9: /* MOV imm,eCX */
5752//-- case 0xBA: /* MOV imm,eDX */
5753//-- case 0xBB: /* MOV imm,eBX */
5754//-- case 0xBC: /* MOV imm,eSP */
5755//-- case 0xBD: /* MOV imm,eBP */
5756//-- case 0xBE: /* MOV imm,eSI */
5757//-- case 0xBF: /* MOV imm,eDI */
5758//-- d32 = getUDisp(sz,eip); eip += sz;
5759//-- t1 = newTemp(cb);
5760//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, t1);
5761//-- uLiteral(cb, d32);
5762//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, opc-0xB8);
5763//-- DIP("mov%c $0x%x,%s\n", nameISize(sz), d32, nameIReg(sz,opc-0xB8));
5764//-- break;
5765//--
5766//-- case 0xC6: /* MOV Ib,Eb */
5767//-- sz = 1;
5768//-- goto do_Mov_I_E;
5769//-- case 0xC7: /* MOV Iv,Ev */
5770//-- goto do_Mov_I_E;
5771//--
5772//-- do_Mov_I_E:
5773//-- modrm = getIByte(delta);
5774//-- if (epartIsReg(modrm)) {
5775//-- eip++; /* mod/rm byte */
5776//-- d32 = getUDisp(sz,eip); eip += sz;
5777//-- t1 = newTemp(cb);
5778//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, t1);
5779//-- uLiteral(cb, d32);
5780//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
5781//-- DIP("mov%c $0x%x, %s\n", nameISize(sz), d32,
5782//-- nameIReg(sz,eregOfRM(modrm)));
5783//-- } else {
5784//-- pair = disAMode ( cb, sorb, eip, dis_buf );
5785//-- eip += HI8(pair);
5786//-- d32 = getUDisp(sz,eip); eip += sz;
5787//-- t1 = newTemp(cb);
5788//-- t2 = LOW24(pair);
5789//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, t1);
5790//-- uLiteral(cb, d32);
5791//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
5792//-- DIP("mov%c $0x%x, %s\n", nameISize(sz), d32, dis_buf);
5793//-- }
5794//-- break;
5795//--
5796//-- /* ------------------------ opl imm, A ----------------- */
5797//--
5798//-- case 0x04: /* ADD Ib, AL */
5799//-- eip = dis_op_imm_A(cb, 1, ADD, True, eip, "add" );
5800//-- break;
5801//-- case 0x05: /* ADD Iv, eAX */
5802//-- eip = dis_op_imm_A(cb, sz, ADD, True, eip, "add" );
5803//-- break;
5804//--
5805//-- case 0x0C: /* OR Ib, AL */
5806//-- eip = dis_op_imm_A(cb, 1, OR, True, eip, "or" );
5807//-- break;
5808//-- case 0x0D: /* OR Iv, eAX */
5809//-- eip = dis_op_imm_A(cb, sz, OR, True, eip, "or" );
5810//-- break;
5811//--
5812//-- case 0x14: /* ADC Ib, AL */
5813//-- eip = dis_op_imm_A(cb, 1, ADC, True, eip, "adc" );
5814//-- break;
5815//-- case 0x15: /* ADC Iv, eAX */
5816//-- eip = dis_op_imm_A(cb, sz, ADC, True, eip, "adc" );
5817//-- break;
5818//--
5819//-- case 0x1C: /* SBB Ib, AL */
5820//-- eip = dis_op_imm_A(cb, 1, SBB, True, eip, "sbb" );
5821//-- break;
5822//-- case 0x1D: /* SBB Iv, eAX */
5823//-- eip = dis_op_imm_A(cb, sz, SBB, True, eip, "sbb" );
5824//-- break;
5825//--
5826//-- case 0x24: /* AND Ib, AL */
5827//-- eip = dis_op_imm_A(cb, 1, AND, True, eip, "and" );
5828//-- break;
5829//-- case 0x25: /* AND Iv, eAX */
5830//-- eip = dis_op_imm_A(cb, sz, AND, True, eip, "and" );
5831//-- break;
5832//--
5833//-- case 0x2C: /* SUB Ib, AL */
5834//-- eip = dis_op_imm_A(cb, 1, SUB, True, eip, "sub" );
5835//-- break;
5836//-- case 0x2D: /* SUB Iv, eAX */
5837//-- eip = dis_op_imm_A(cb, sz, SUB, True, eip, "sub" );
5838//-- break;
5839//--
5840//-- case 0x34: /* XOR Ib, AL */
5841//-- eip = dis_op_imm_A(cb, 1, XOR, True, eip, "xor" );
5842//-- break;
5843//-- case 0x35: /* XOR Iv, eAX */
5844//-- eip = dis_op_imm_A(cb, sz, XOR, True, eip, "xor" );
5845//-- break;
5846//--
5847//-- case 0x3C: /* CMP Ib, AL */
5848//-- eip = dis_op_imm_A(cb, 1, SUB, False, eip, "cmp" );
5849//-- break;
5850//-- case 0x3D: /* CMP Iv, eAX */
5851//-- eip = dis_op_imm_A(cb, sz, SUB, False, eip, "cmp" );
5852//-- break;
5853//--
5854//-- case 0xA8: /* TEST Ib, AL */
5855//-- eip = dis_op_imm_A(cb, 1, AND, False, eip, "test" );
5856//-- break;
5857//-- case 0xA9: /* TEST Iv, eAX */
5858//-- eip = dis_op_imm_A(cb, sz, AND, False, eip, "test" );
5859//-- break;
5860//--
5861//-- /* ------------------------ opl Ev, Gv ----------------- */
5862//--
5863//-- case 0x02: /* ADD Eb,Gb */
5864//-- eip = dis_op2_E_G ( cb, sorb, ADD, True, 1, eip, "add" );
5865//-- break;
5866//-- case 0x03: /* ADD Ev,Gv */
5867//-- eip = dis_op2_E_G ( cb, sorb, ADD, True, sz, eip, "add" );
5868//-- break;
5869//--
5870//-- case 0x0A: /* OR Eb,Gb */
5871//-- eip = dis_op2_E_G ( cb, sorb, OR, True, 1, eip, "or" );
5872//-- break;
5873//-- case 0x0B: /* OR Ev,Gv */
5874//-- eip = dis_op2_E_G ( cb, sorb, OR, True, sz, eip, "or" );
5875//-- break;
5876//--
5877//-- case 0x12: /* ADC Eb,Gb */
5878//-- eip = dis_op2_E_G ( cb, sorb, ADC, True, 1, eip, "adc" );
5879//-- break;
5880//-- case 0x13: /* ADC Ev,Gv */
5881//-- eip = dis_op2_E_G ( cb, sorb, ADC, True, sz, eip, "adc" );
5882//-- break;
5883//--
5884//-- case 0x1A: /* SBB Eb,Gb */
5885//-- eip = dis_op2_E_G ( cb, sorb, SBB, True, 1, eip, "sbb" );
5886//-- break;
5887//-- case 0x1B: /* SBB Ev,Gv */
5888//-- eip = dis_op2_E_G ( cb, sorb, SBB, True, sz, eip, "sbb" );
5889//-- break;
5890//--
5891//-- case 0x22: /* AND Eb,Gb */
5892//-- eip = dis_op2_E_G ( cb, sorb, AND, True, 1, eip, "and" );
5893//-- break;
5894//-- case 0x23: /* AND Ev,Gv */
5895//-- eip = dis_op2_E_G ( cb, sorb, AND, True, sz, eip, "and" );
5896//-- break;
5897//--
5898//-- case 0x2A: /* SUB Eb,Gb */
5899//-- eip = dis_op2_E_G ( cb, sorb, SUB, True, 1, eip, "sub" );
5900//-- break;
5901//-- case 0x2B: /* SUB Ev,Gv */
5902//-- eip = dis_op2_E_G ( cb, sorb, SUB, True, sz, eip, "sub" );
5903//-- break;
5904//--
5905//-- case 0x32: /* XOR Eb,Gb */
5906//-- eip = dis_op2_E_G ( cb, sorb, XOR, True, 1, eip, "xor" );
5907//-- break;
5908//-- case 0x33: /* XOR Ev,Gv */
5909//-- eip = dis_op2_E_G ( cb, sorb, XOR, True, sz, eip, "xor" );
5910//-- break;
5911//--
5912//-- case 0x3A: /* CMP Eb,Gb */
5913//-- eip = dis_op2_E_G ( cb, sorb, SUB, False, 1, eip, "cmp" );
5914//-- break;
5915//-- case 0x3B: /* CMP Ev,Gv */
5916//-- eip = dis_op2_E_G ( cb, sorb, SUB, False, sz, eip, "cmp" );
5917//-- break;
5918//--
5919//-- case 0x84: /* TEST Eb,Gb */
5920//-- eip = dis_op2_E_G ( cb, sorb, AND, False, 1, eip, "test" );
5921//-- break;
5922//-- case 0x85: /* TEST Ev,Gv */
5923//-- eip = dis_op2_E_G ( cb, sorb, AND, False, sz, eip, "test" );
5924//-- break;
5925//--
5926//-- /* ------------------------ opl Gv, Ev ----------------- */
5927//--
5928//-- case 0x00: /* ADD Gb,Eb */
5929//-- eip = dis_op2_G_E ( cb, sorb, ADD, True, 1, eip, "add" );
5930//-- break;
5931//-- case 0x01: /* ADD Gv,Ev */
5932//-- eip = dis_op2_G_E ( cb, sorb, ADD, True, sz, eip, "add" );
5933//-- break;
5934//--
5935//-- case 0x08: /* OR Gb,Eb */
5936//-- eip = dis_op2_G_E ( cb, sorb, OR, True, 1, eip, "or" );
5937//-- break;
5938//-- case 0x09: /* OR Gv,Ev */
5939//-- eip = dis_op2_G_E ( cb, sorb, OR, True, sz, eip, "or" );
5940//-- break;
5941//--
5942//-- case 0x10: /* ADC Gb,Eb */
5943//-- eip = dis_op2_G_E ( cb, sorb, ADC, True, 1, eip, "adc" );
5944//-- break;
5945//-- case 0x11: /* ADC Gv,Ev */
5946//-- eip = dis_op2_G_E ( cb, sorb, ADC, True, sz, eip, "adc" );
5947//-- break;
5948//--
5949//-- case 0x18: /* SBB Gb,Eb */
5950//-- eip = dis_op2_G_E ( cb, sorb, SBB, True, 1, eip, "sbb" );
5951//-- break;
5952//-- case 0x19: /* SBB Gv,Ev */
5953//-- eip = dis_op2_G_E ( cb, sorb, SBB, True, sz, eip, "sbb" );
5954//-- break;
5955//--
5956//-- case 0x20: /* AND Gb,Eb */
5957//-- eip = dis_op2_G_E ( cb, sorb, AND, True, 1, eip, "and" );
5958//-- break;
5959//-- case 0x21: /* AND Gv,Ev */
5960//-- eip = dis_op2_G_E ( cb, sorb, AND, True, sz, eip, "and" );
5961//-- break;
5962//--
5963//-- case 0x28: /* SUB Gb,Eb */
5964//-- eip = dis_op2_G_E ( cb, sorb, SUB, True, 1, eip, "sub" );
5965//-- break;
5966//-- case 0x29: /* SUB Gv,Ev */
5967//-- eip = dis_op2_G_E ( cb, sorb, SUB, True, sz, eip, "sub" );
5968//-- break;
5969//--
5970//-- case 0x30: /* XOR Gb,Eb */
5971//-- eip = dis_op2_G_E ( cb, sorb, XOR, True, 1, eip, "xor" );
5972//-- break;
5973//-- case 0x31: /* XOR Gv,Ev */
5974//-- eip = dis_op2_G_E ( cb, sorb, XOR, True, sz, eip, "xor" );
5975//-- break;
5976//--
5977//-- case 0x38: /* CMP Gb,Eb */
5978//-- eip = dis_op2_G_E ( cb, sorb, SUB, False, 1, eip, "cmp" );
5979//-- break;
5980//-- case 0x39: /* CMP Gv,Ev */
5981//-- eip = dis_op2_G_E ( cb, sorb, SUB, False, sz, eip, "cmp" );
5982//-- break;
5983//--
5984//-- /* ------------------------ POP ------------------------ */
5985//--
5986//-- case 0x58: /* POP eAX */
5987//-- case 0x59: /* POP eCX */
5988//-- case 0x5A: /* POP eDX */
5989//-- case 0x5B: /* POP eBX */
5990//-- case 0x5D: /* POP eBP */
5991//-- case 0x5E: /* POP eSI */
5992//-- case 0x5F: /* POP eDI */
5993//-- case 0x5C: /* POP eSP */
5994//-- t1 = newTemp(cb); t2 = newTemp(cb);
5995//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
5996//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
5997//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
5998//-- uLiteral(cb, sz);
5999//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
6000//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, opc-0x58);
6001//-- DIP("pop%c %s\n", nameISize(sz), nameIReg(sz,opc-0x58));
6002//-- break;
6003//--
6004//-- case 0x9D: /* POPF */
6005//-- vg_assert(sz == 2 || sz == 4);
6006//-- t1 = newTemp(cb); t2 = newTemp(cb);
6007//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
6008//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
6009//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
6010//-- uLiteral(cb, sz);
6011//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
6012//-- uInstr1(cb, PUTF, sz, TempReg, t1);
6013//-- /* PUTF writes all the flags we are interested in */
6014//-- uFlagsRWU(cb, FlagsEmpty, FlagsALL, FlagsEmpty);
6015//-- DIP("popf%c\n", nameISize(sz));
6016//-- break;
6017//--
6018//-- case 0x61: /* POPA */
6019//-- { Int reg;
6020//-- /* Just to keep things sane, we assert for a size 4. It's
6021//-- probably OK for size 2 as well, but I'd like to find a test
6022//-- case; ie, have the assertion fail, before committing to it.
6023//-- If it fails for you, uncomment the sz == 2 bit, try again,
6024//-- and let me know whether or not it works. (jseward@acm.org). */
6025//-- vg_assert(sz == 4 /* || sz == 2 */);
6026//--
6027//-- /* Eight values are popped, one per register, but the value of
6028//-- %esp on the stack is ignored and instead incremented (in one
6029//-- hit at the end) for each of the values. */
6030//-- t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);
6031//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t2);
6032//-- uInstr2(cb, MOV, 4, TempReg, t2, TempReg, t3);
6033//--
6034//-- /* Do %edi, %esi, %ebp */
6035//-- for (reg = 7; reg >= 5; reg--) {
6036//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
6037//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
6038//-- uLiteral(cb, sz);
6039//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, reg);
6040//-- }
6041//-- /* Ignore (skip) value of %esp on stack. */
6042//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
6043//-- uLiteral(cb, sz);
6044//-- /* Do %ebx, %edx, %ecx, %eax */
6045//-- for (reg = 3; reg >= 0; reg--) {
6046//-- uInstr2(cb, LOAD, sz, TempReg, t2, TempReg, t1);
6047//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t2);
6048//-- uLiteral(cb, sz);
6049//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, reg);
6050//-- }
6051//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t3);
6052//-- uLiteral(cb, sz * 8); /* One 'sz' per register */
6053//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_ESP);
6054//-- DIP("popa%c\n", nameISize(sz));
6055//-- break;
6056//-- }
6057//--
6058//-- case 0x8F: /* POPL/POPW m32 */
6059//-- { UInt pair1;
6060//-- Int tmpa;
6061//-- UChar rm = getIByte(delta);
6062//--
6063//-- /* make sure this instruction is correct POP */
6064//-- vg_assert(!epartIsReg(rm) && (gregOfRM(rm) == 0));
6065//-- /* and has correct size */
6066//-- vg_assert(sz == 4);
6067//--
6068//-- t1 = newTemp(cb); t3 = newTemp(cb);
6069//-- /* set t1 to ESP: t1 = ESP */
6070//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t1);
6071//-- /* load M[ESP] to virtual register t3: t3 = M[t1] */
6072//-- uInstr2(cb, LOAD, 4, TempReg, t1, TempReg, t3);
6073//--
6074//-- /* increase ESP; must be done before the STORE. Intel manual says:
6075//-- If the ESP register is used as a base register for addressing
6076//-- a destination operand in memory, the POP instruction computes
6077//-- the effective address of the operand after it increments the
6078//-- ESP register.
6079//-- */
6080//-- uInstr2(cb, ADD, 4, Literal, 0, TempReg, t1);
6081//-- uLiteral(cb, sz);
6082//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ESP);
6083//--
6084//-- /* resolve MODR/M */
6085//-- pair1 = disAMode ( cb, sorb, eip, dis_buf );
6086//--
6087//-- tmpa = LOW24(pair1);
6088//-- /* uInstr2(cb, LOAD, sz, TempReg, tmpa, TempReg, tmpa); */
6089//-- /* store value from stack in memory, M[m32] = t3 */
6090//-- uInstr2(cb, STORE, 4, TempReg, t3, TempReg, tmpa);
6091//--
6092//-- DIP("popl %s\n", dis_buf);
6093//--
6094//-- eip += HI8(pair1);
6095//-- break;
6096//-- }
6097//--
6098//-- case 0x1F: /* POP %DS */
6099//-- dis_pop_segreg( cb, R_DS, sz ); break;
6100//-- case 0x07: /* POP %ES */
6101//-- dis_pop_segreg( cb, R_ES, sz ); break;
6102//-- case 0x17: /* POP %SS */
6103//-- dis_pop_segreg( cb, R_SS, sz ); break;
sewardjd1061ab2004-07-08 01:45:30 +00006104
6105 /* ------------------------ PUSH ----------------------- */
6106
6107 case 0x50: /* PUSH eAX */
6108 case 0x51: /* PUSH eCX */
6109 case 0x52: /* PUSH eDX */
6110 case 0x53: /* PUSH eBX */
6111 case 0x55: /* PUSH eBP */
6112 case 0x56: /* PUSH eSI */
6113 case 0x57: /* PUSH eDI */
6114 case 0x54: /* PUSH eSP */
6115 /* This is the Right Way, in that the value to be pushed is
6116 established before %esp is changed, so that pushl %esp
6117 correctly pushes the old value. */
6118 vassert(sz == 2 || sz == 4);
6119 ty = sz==2 ? Ity_I16 : Ity_I32;
6120 t1 = newTemp(ty); t2 = newTemp(ty);
6121 stmt( assign(t1, getIReg(sz, opc-0x50)) );
6122 stmt( assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz))) );
6123 stmt( putIReg(4, R_ESP, mkexpr(t2) ) );
6124 stmt( storeLE(mkexpr(t2),mkexpr(t1)) );
6125 DIP("push%c %s\n", nameISize(sz), nameIReg(sz,opc-0x50));
6126 break;
6127
6128
sewardjc9a65702004-07-07 16:32:57 +00006129//-- case 0x68: /* PUSH Iv */
6130//-- d32 = getUDisp(sz,eip); eip += sz;
6131//-- goto do_push_I;
6132//-- case 0x6A: /* PUSH Ib, sign-extended to sz */
6133//-- d32 = getSDisp8(eip); eip += 1;
6134//-- goto do_push_I;
6135//-- do_push_I:
6136//-- t1 = newTemp(cb); t2 = newTemp(cb);
6137//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t1);
6138//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t1);
6139//-- uLiteral(cb, sz);
6140//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_ESP);
6141//-- uInstr2(cb, MOV, sz, Literal, 0, TempReg, t2);
6142//-- uLiteral(cb, d32);
6143//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
6144//-- DIP("push%c $0x%x\n", nameISize(sz), d32);
6145//-- break;
6146//--
6147//-- case 0x9C: /* PUSHF */
6148//-- vg_assert(sz == 2 || sz == 4);
6149//-- t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);
6150//-- uInstr1(cb, GETF, sz, TempReg, t1);
6151//-- /* GETF reads all the flags we are interested in */
6152//-- uFlagsRWU(cb, FlagsALL, FlagsEmpty, FlagsEmpty);
6153//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t3);
6154//-- uInstr2(cb, MOV, 4, TempReg, t3, TempReg, t2);
6155//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
6156//-- uLiteral(cb, sz);
6157//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_ESP);
6158//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
6159//-- DIP("pushf%c\n", nameISize(sz));
6160//-- break;
6161//--
6162//-- case 0x60: /* PUSHA */
6163//-- { Int reg;
6164//-- /* Just to keep things sane, we assert for a size 4. It's
6165//-- probably OK for size 2 as well, but I'd like to find a test
6166//-- case; ie, have the assertion fail, before committing to it.
6167//-- If it fails for you, uncomment the sz == 2 bit, try again,
6168//-- and let me know whether or not it works. (jseward@acm.org). */
6169//-- vg_assert(sz == 4 /* || sz == 2 */);
6170//--
6171//-- /* This is the Right Way, in that the value to be pushed is
6172//-- established before %esp is changed, so that pusha
6173//-- correctly pushes the old %esp value. New value of %esp is
6174//-- pushed at start. */
6175//-- t1 = newTemp(cb); t2 = newTemp(cb); t3 = newTemp(cb);
6176//-- t4 = newTemp(cb);
6177//-- uInstr2(cb, GET, 4, ArchReg, R_ESP, TempReg, t3);
6178//-- uInstr2(cb, MOV, 4, TempReg, t3, TempReg, t2);
6179//-- uInstr2(cb, MOV, 4, TempReg, t3, TempReg, t4);
6180//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t4);
6181//-- uLiteral(cb, sz * 8); /* One 'sz' per register. */
6182//-- uInstr2(cb, PUT, 4, TempReg, t4, ArchReg, R_ESP);
6183//-- /* Do %eax, %ecx, %edx, %ebx */
6184//-- for (reg = 0; reg <= 3; reg++) {
6185//-- uInstr2(cb, GET, sz, ArchReg, reg, TempReg, t1);
6186//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
6187//-- uLiteral(cb, sz);
6188//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
6189//-- }
6190//-- /* Push old value of %esp */
6191//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
6192//-- uLiteral(cb, sz);
6193//-- uInstr2(cb, STORE, sz, TempReg, t3, TempReg, t2);
6194//-- /* Do %ebp, %esi, %edi */
6195//-- for (reg = 5; reg <= 7; reg++) {
6196//-- uInstr2(cb, GET, sz, ArchReg, reg, TempReg, t1);
6197//-- uInstr2(cb, SUB, 4, Literal, 0, TempReg, t2);
6198//-- uLiteral(cb, sz);
6199//-- uInstr2(cb, STORE, sz, TempReg, t1, TempReg, t2);
6200//-- }
6201//-- DIP("pusha%c\n", nameISize(sz));
6202//-- break;
6203//-- }
6204//--
6205//-- case 0x0E: /* PUSH %CS */
6206//-- dis_push_segreg( cb, R_CS, sz ); break;
6207//-- case 0x1E: /* PUSH %DS */
6208//-- dis_push_segreg( cb, R_DS, sz ); break;
6209//-- case 0x06: /* PUSH %ES */
6210//-- dis_push_segreg( cb, R_ES, sz ); break;
6211//-- case 0x16: /* PUSH %SS */
6212//-- dis_push_segreg( cb, R_SS, sz ); break;
6213//--
6214//-- /* ------------------------ SCAS et al ----------------- */
6215//--
6216//-- case 0xA4: /* MOVS, no REP prefix */
6217//-- case 0xA5:
6218//-- dis_string_op( cb, dis_MOVS, ( opc == 0xA4 ? 1 : sz ), "movs", sorb );
6219//-- break;
6220//--
6221//-- case 0xA6: /* CMPSb, no REP prefix */
6222//-- case 0xA7:
6223//-- dis_string_op( cb, dis_CMPS, ( opc == 0xA6 ? 1 : sz ), "cmps", sorb );
6224//-- break;
6225//--
6226//-- case 0xAA: /* STOS, no REP prefix */
6227//-- case 0xAB:
6228//-- dis_string_op( cb, dis_STOS, ( opc == 0xAA ? 1 : sz ), "stos", sorb );
6229//-- break;
6230//--
6231//-- case 0xAC: /* LODS, no REP prefix */
6232//-- case 0xAD:
6233//-- dis_string_op( cb, dis_LODS, ( opc == 0xAC ? 1 : sz ), "lods", sorb );
6234//-- break;
6235//--
6236//-- case 0xAE: /* SCAS, no REP prefix */
6237//-- case 0xAF:
6238//-- dis_string_op( cb, dis_SCAS, ( opc == 0xAE ? 1 : sz ), "scas", sorb );
6239//-- break;
6240//--
6241//--
6242//-- case 0xFC: /* CLD */
6243//-- uInstr0(cb, CALLM_S, 0);
6244//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLD));
6245//-- uFlagsRWU(cb, FlagsEmpty, FlagD, FlagsEmpty);
6246//-- uInstr0(cb, CALLM_E, 0);
6247//-- DIP("cld\n");
6248//-- break;
6249//--
6250//-- case 0xFD: /* STD */
6251//-- uInstr0(cb, CALLM_S, 0);
6252//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STD));
6253//-- uFlagsRWU(cb, FlagsEmpty, FlagD, FlagsEmpty);
6254//-- uInstr0(cb, CALLM_E, 0);
6255//-- DIP("std\n");
6256//-- break;
6257//--
6258//-- case 0xF8: /* CLC */
6259//-- uInstr0(cb, CALLM_S, 0);
6260//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CLC));
6261//-- uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
6262//-- uInstr0(cb, CALLM_E, 0);
6263//-- DIP("clc\n");
6264//-- break;
6265//--
6266//-- case 0xF9: /* STC */
6267//-- uInstr0(cb, CALLM_S, 0);
6268//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_STC));
6269//-- uFlagsRWU(cb, FlagsEmpty, FlagC, FlagsOSZAP);
6270//-- uInstr0(cb, CALLM_E, 0);
6271//-- DIP("stc\n");
6272//-- break;
6273//--
6274//-- case 0xF5: /* CMC */
6275//-- uInstr0(cb, CALLM_S, 0);
6276//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CMC));
6277//-- uFlagsRWU(cb, FlagC, FlagC, FlagsOSZAP);
6278//-- uInstr0(cb, CALLM_E, 0);
6279//-- DIP("cmc\n");
6280//-- break;
6281//--
6282//-- /* REPNE prefix insn */
6283//-- case 0xF2: {
6284//-- Addr eip_orig = eip - 1;
6285//-- vg_assert(sorb == 0);
6286//-- abyte = getIByte(delta); eip++;
6287//--
6288//-- if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); eip++; }
6289//-- *isEnd = True;
6290//--
6291//-- switch (abyte) {
6292//-- /* According to the Intel manual, "repne movs" should never occur, but
6293//-- * in practice it has happened, so allow for it here... */
6294//-- case 0xA4: sz = 1; /* REPNE MOVS<sz> */
6295//-- case 0xA5:
6296//-- dis_REP_op ( cb, CondNZ, dis_MOVS, sz, eip_orig, eip, "repne movs" );
6297//-- break;
6298//--
6299//-- case 0xA6: sz = 1; /* REPNE CMPS<sz> */
6300//-- case 0xA7:
6301//-- dis_REP_op ( cb, CondNZ, dis_CMPS, sz, eip_orig, eip, "repne cmps" );
6302//-- break;
6303//--
6304//-- case 0xAE: sz = 1; /* REPNE SCAS<sz> */
6305//-- case 0xAF:
6306//-- dis_REP_op ( cb, CondNZ, dis_SCAS, sz, eip_orig, eip, "repne scas" );
6307//-- break;
6308//--
6309//-- default:
6310//-- goto decode_failure;
6311//-- }
6312//-- break;
6313//-- }
6314//--
6315//-- /* REP/REPE prefix insn (for SCAS and CMPS, 0xF3 means REPE,
6316//-- for the rest, it means REP) */
6317//-- case 0xF3: {
6318//-- Addr eip_orig = eip - 1;
6319//-- vg_assert(sorb == 0);
6320//-- abyte = getUChar(eip); eip++;
6321//--
6322//-- if (abyte == 0x66) { sz = 2; abyte = getUChar(eip); eip++; }
6323//-- *isEnd = True;
6324//--
6325//-- switch (abyte) {
6326//-- case 0xA4: sz = 1; /* REP MOVS<sz> */
6327//-- case 0xA5:
6328//-- dis_REP_op ( cb, CondAlways, dis_MOVS, sz, eip_orig, eip, "rep movs" );
6329//-- break;
6330//--
6331//-- case 0xA6: sz = 1; /* REPE CMP<sz> */
6332//-- case 0xA7:
6333//-- dis_REP_op ( cb, CondZ, dis_CMPS, sz, eip_orig, eip, "repe cmps" );
6334//-- break;
6335//--
6336//-- case 0xAA: sz = 1; /* REP STOS<sz> */
6337//-- case 0XAB:
6338//-- dis_REP_op ( cb, CondAlways, dis_STOS, sz, eip_orig, eip, "rep stos" );
6339//-- break;
6340//--
6341//-- case 0xAE: sz = 1; /* REPE SCAS<sz> */
6342//-- case 0xAF:
6343//-- dis_REP_op ( cb, CondZ, dis_SCAS, sz, eip_orig, eip, "repe scas" );
6344//-- break;
6345//--
6346//-- case 0x90: /* REP NOP (PAUSE) */
6347//-- /* a hint to the P4 re spin-wait loop */
6348//-- DIP("rep nop (P4 pause)\n");
6349//-- jmp_lit(cb, eip);
6350//-- LAST_UINSTR(cb).jmpkind = JmpYield;
6351//-- break;
6352//--
6353//-- case 0xC3: /* REP RET */
6354//-- /* AMD K7/K8-specific optimisation; faster than vanilla RET */
6355//-- dis_ret(cb, 0);
6356//-- DIP("rep ret\n");
6357//-- break;
6358//--
6359//-- default:
6360//-- goto decode_failure;
6361//-- }
6362//-- break;
6363//-- }
6364//--
6365//-- /* ------------------------ XCHG ----------------------- */
6366//--
6367//-- case 0x86: /* XCHG Gb,Eb */
6368//-- sz = 1;
6369//-- /* Fall through ... */
6370//-- case 0x87: /* XCHG Gv,Ev */
6371//-- modrm = getUChar(eip);
6372//-- t1 = newTemp(cb); t2 = newTemp(cb);
6373//-- if (epartIsReg(modrm)) {
6374//-- uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
6375//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(modrm), TempReg, t2);
6376//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, gregOfRM(modrm));
6377//-- uInstr2(cb, PUT, sz, TempReg, t2, ArchReg, eregOfRM(modrm));
6378//-- eip++;
6379//-- DIP("xchg%c %s, %s\n",
6380//-- nameISize(sz), nameIReg(sz,gregOfRM(modrm)),
6381//-- nameIReg(sz,eregOfRM(modrm)));
6382//-- } else {
6383//-- pair = disAMode ( cb, sorb, eip, dis_buf );
6384//-- t3 = LOW24(pair);
6385//-- uInstr2(cb, LOAD, sz, TempReg, t3, TempReg, t1);
6386//-- uInstr2(cb, GET, sz, ArchReg, gregOfRM(modrm), TempReg, t2);
6387//-- uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t3);
6388//-- uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, gregOfRM(modrm));
6389//-- eip += HI8(pair);
6390//-- DIP("xchg%c %s, %s\n", nameISize(sz),
6391//-- nameIReg(sz,gregOfRM(modrm)), dis_buf);
6392//-- }
6393//-- break;
6394//--
6395//-- case 0x90: /* XCHG eAX,eAX */
6396//-- DIP("nop\n");
6397//-- break;
6398//-- case 0x91: /* XCHG eAX,eCX */
6399//-- case 0x92: /* XCHG eAX,eDX */
6400//-- case 0x93: /* XCHG eAX,eBX */
6401//-- case 0x94: /* XCHG eAX,eSP */
6402//-- case 0x95: /* XCHG eAX,eBP */
6403//-- case 0x96: /* XCHG eAX,eSI */
6404//-- case 0x97: /* XCHG eAX,eDI */
6405//-- codegen_xchg_eAX_Reg ( cb, sz, opc - 0x90 );
6406//-- break;
6407//--
6408//-- /* ------------------------ XLAT ----------------------- */
6409//--
6410//-- case 0xD7: /* XLAT */
6411//-- t1 = newTemp(cb); t2 = newTemp(cb);
6412//-- uInstr2(cb, GET, sz, ArchReg, R_EBX, TempReg, t1); /* get eBX */
6413//-- handleSegOverride( cb, sorb, t1 ); /* make t1 DS:eBX */
6414//-- uInstr2(cb, GET, 1, ArchReg, R_AL, TempReg, t2); /* get AL */
6415//-- /* Widen %AL to 32 bits, so it's all defined when we add it. */
6416//-- uInstr1(cb, WIDEN, 4, TempReg, t2);
6417//-- uWiden(cb, 1, False);
6418//-- uInstr2(cb, ADD, sz, TempReg, t2, TempReg, t1); /* add AL to eBX */
6419//-- uInstr2(cb, LOAD, 1, TempReg, t1, TempReg, t2); /* get byte at t1 into t2 */
6420//-- uInstr2(cb, PUT, 1, TempReg, t2, ArchReg, R_AL); /* put byte into AL */
6421//--
6422//-- DIP("xlat%c [ebx]\n", nameISize(sz));
6423//-- break;
6424//--
6425//-- /* ------------------------ IN / OUT ----------------------- */
6426//--
6427//-- case 0xE4: /* IN ib, %al */
6428//-- case 0xE5: /* IN ib, %{e}ax */
6429//-- case 0xEC: /* IN (%dx),%al */
6430//-- case 0xED: /* IN (%dx),%{e}ax */
6431//-- t1 = newTemp(cb);
6432//-- t2 = newTemp(cb);
6433//-- t3 = newTemp(cb);
6434//--
6435//-- uInstr0(cb, CALLM_S, 0);
6436//-- /* operand size? */
6437//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t1);
6438//-- uLiteral(cb, ( opc == 0xE4 || opc == 0xEC ) ? 1 : sz);
6439//-- uInstr1(cb, PUSH, 4, TempReg, t1);
6440//-- /* port number ? */
6441//-- if ( opc == 0xE4 || opc == 0xE5 ) {
6442//-- abyte = getUChar(eip); eip++;
6443//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
6444//-- uLiteral(cb, abyte);
6445//-- }
6446//-- else
6447//-- uInstr2(cb, GET, 4, ArchReg, R_EDX, TempReg, t2);
6448//--
6449//-- uInstr1(cb, PUSH, 4, TempReg, t2);
6450//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_IN));
6451//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
6452//-- uInstr1(cb, POP, 4, TempReg, t2);
6453//-- uInstr1(cb, CLEAR, 0, Lit16, 4);
6454//-- uInstr0(cb, CALLM_E, 0);
6455//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_EAX);
6456//-- if ( opc == 0xE4 || opc == 0xE5 ) {
6457//-- DIP("in 0x%x, %%eax/%%ax/%%al\n", getUChar(eip-1) );
6458//-- } else {
6459//-- DIP("in (%%dx), %%eax/%%ax/%%al\n");
6460//-- }
6461//-- break;
6462//-- case 0xE6: /* OUT %al,ib */
6463//-- case 0xE7: /* OUT %{e}ax,ib */
6464//-- case 0xEE: /* OUT %al,(%dx) */
6465//-- case 0xEF: /* OUT %{e}ax,(%dx) */
6466//-- t1 = newTemp(cb);
6467//-- t2 = newTemp(cb);
6468//-- t3 = newTemp(cb);
6469//--
6470//-- uInstr0(cb, CALLM_S, 0);
6471//-- /* operand size? */
6472//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t1);
6473//-- uLiteral(cb, ( opc == 0xE6 || opc == 0xEE ) ? 1 : sz);
6474//-- uInstr1(cb, PUSH, 4, TempReg, t1);
6475//-- /* port number ? */
6476//-- if ( opc == 0xE6 || opc == 0xE7 ) {
6477//-- abyte = getUChar(eip); eip++;
6478//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
6479//-- uLiteral(cb, abyte);
6480//-- }
6481//-- else
6482//-- uInstr2(cb, GET, 4, ArchReg, R_EDX, TempReg, t2);
6483//-- uInstr1(cb, PUSH, 4, TempReg, t2);
6484//-- uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, t3);
6485//-- uInstr1(cb, PUSH, 4, TempReg, t3);
6486//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_OUT));
6487//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
6488//-- uInstr1(cb, CLEAR, 0, Lit16, 12);
6489//-- uInstr0(cb, CALLM_E, 0);
6490//-- if ( opc == 0xE4 || opc == 0xE5 ) {
6491//-- DIP("out %%eax/%%ax/%%al, 0x%x\n", getUChar(eip-1) );
6492//-- } else {
6493//-- DIP("out %%eax/%%ax/%%al, (%%dx)\n");
6494//-- }
6495//-- break;
6496//--
6497//-- /* ------------------------ (Grp1 extensions) ---------- */
6498//--
6499//-- case 0x80: /* Grp1 Ib,Eb */
6500//-- modrm = getUChar(eip);
6501//-- am_sz = lengthAMode(eip);
6502//-- sz = 1;
6503//-- d_sz = 1;
6504//-- d32 = getSDisp8(eip + am_sz);
6505//-- eip = dis_Grp1 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, d32 );
6506//-- break;
6507//--
6508//-- case 0x81: /* Grp1 Iv,Ev */
6509//-- modrm = getUChar(eip);
6510//-- am_sz = lengthAMode(eip);
6511//-- d_sz = sz;
6512//-- d32 = getUDisp(d_sz, eip + am_sz);
6513//-- eip = dis_Grp1 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, d32 );
6514//-- break;
sewardjd1061ab2004-07-08 01:45:30 +00006515
6516 case 0x83: /* Grp1 Ib,Ev */
6517 modrm = getIByte(delta);
6518 am_sz = lengthAMode(delta);
6519 d_sz = 1;
6520 d32 = getSDisp8(delta + am_sz);
6521 delta = dis_Grp1 ( sorb, delta, modrm, am_sz, d_sz, sz, d32 );
6522 break;
6523
sewardjc9a65702004-07-07 16:32:57 +00006524//-- /* ------------------------ (Grp2 extensions) ---------- */
6525//--
6526//-- case 0xC0: /* Grp2 Ib,Eb */
6527//-- modrm = getUChar(eip);
6528//-- am_sz = lengthAMode(eip);
6529//-- d_sz = 1;
6530//-- d32 = getSDisp8(eip + am_sz);
6531//-- sz = 1;
6532//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, Literal, d32 );
6533//-- break;
6534//--
6535//-- case 0xC1: /* Grp2 Ib,Ev */
6536//-- modrm = getUChar(eip);
6537//-- am_sz = lengthAMode(eip);
6538//-- d_sz = 1;
6539//-- d32 = getSDisp8(eip + am_sz);
6540//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, Literal, d32 );
6541//-- break;
6542//--
6543//-- case 0xD0: /* Grp2 1,Eb */
6544//-- modrm = getUChar(eip);
6545//-- am_sz = lengthAMode(eip);
6546//-- d_sz = 0;
6547//-- d32 = 1;
6548//-- sz = 1;
6549//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, Literal, d32 );
6550//-- break;
6551//--
6552//-- case 0xD1: /* Grp2 1,Ev */
6553//-- modrm = getUChar(eip);
6554//-- am_sz = lengthAMode(eip);
6555//-- d_sz = 0;
6556//-- d32 = 1;
6557//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, Literal, d32 );
6558//-- break;
6559//--
6560//-- case 0xD2: /* Grp2 CL,Eb */
6561//-- modrm = getUChar(eip);
6562//-- am_sz = lengthAMode(eip);
6563//-- d_sz = 0;
6564//-- sz = 1;
6565//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, ArchReg, R_ECX );
6566//-- break;
6567//--
6568//-- case 0xD3: /* Grp2 CL,Ev */
6569//-- modrm = getUChar(eip);
6570//-- am_sz = lengthAMode(eip);
6571//-- d_sz = 0;
6572//-- eip = dis_Grp2 ( cb, sorb, eip, modrm, am_sz, d_sz, sz, ArchReg, R_ECX );
6573//-- break;
6574//--
6575//-- /* ------------------------ (Grp3 extensions) ---------- */
6576//--
6577//-- case 0xF6: /* Grp3 Eb */
6578//-- eip = dis_Grp3 ( cb, sorb, 1, eip );
6579//-- break;
6580//-- case 0xF7: /* Grp3 Ev */
6581//-- eip = dis_Grp3 ( cb, sorb, sz, eip );
6582//-- break;
6583//--
6584//-- /* ------------------------ (Grp4 extensions) ---------- */
6585//--
6586//-- case 0xFE: /* Grp4 Eb */
6587//-- eip = dis_Grp4 ( cb, sorb, eip );
6588//-- break;
6589//--
6590//-- /* ------------------------ (Grp5 extensions) ---------- */
6591//--
6592//-- case 0xFF: /* Grp5 Ev */
6593//-- eip = dis_Grp5 ( cb, sorb, sz, eip, isEnd );
6594//-- break;
6595//--
6596//-- /* ------------------------ Escapes to 2-byte opcodes -- */
6597//--
6598//-- case 0x0F: {
6599//-- opc = getUChar(eip); eip++;
6600//-- switch (opc) {
6601//--
6602//-- /* =-=-=-=-=-=-=-=-=- Grp8 =-=-=-=-=-=-=-=-=-=-=-= */
6603//--
6604//-- case 0xBA: /* Grp8 Ib,Ev */
6605//-- modrm = getUChar(eip);
6606//-- am_sz = lengthAMode(eip);
6607//-- d32 = getSDisp8(eip + am_sz);
6608//-- eip = dis_Grp8_BT ( cb, sorb, eip, modrm, am_sz, sz, d32 );
6609//-- break;
6610//--
6611//-- /* =-=-=-=-=-=-=-=-=- BSF/BSR -=-=-=-=-=-=-=-=-=-= */
6612//--
6613//-- case 0xBC: /* BSF Gv,Ev */
6614//-- eip = dis_bs_E_G ( cb, sorb, sz, eip, True );
6615//-- break;
6616//-- case 0xBD: /* BSR Gv,Ev */
6617//-- eip = dis_bs_E_G ( cb, sorb, sz, eip, False );
6618//-- break;
6619//--
6620//-- /* =-=-=-=-=-=-=-=-=- BSWAP -=-=-=-=-=-=-=-=-=-=-= */
6621//--
6622//-- case 0xC8: /* BSWAP %eax */
6623//-- case 0xC9:
6624//-- case 0xCA:
6625//-- case 0xCB:
6626//-- case 0xCC:
6627//-- case 0xCD:
6628//-- case 0xCE:
6629//-- case 0xCF: /* BSWAP %edi */
6630//-- /* AFAICS from the Intel docs, this only exists at size 4. */
6631//-- vg_assert(sz == 4);
6632//-- t1 = newTemp(cb);
6633//-- uInstr2(cb, GET, 4, ArchReg, opc-0xC8, TempReg, t1);
6634//-- uInstr1(cb, BSWAP, 4, TempReg, t1);
6635//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, opc-0xC8);
6636//-- DIP("bswapl %s\n", nameIReg(4, opc-0xC8));
6637//-- break;
6638//--
6639//-- /* =-=-=-=-=-=-=-=-=- BT/BTS/BTR/BTC =-=-=-=-=-=-= */
6640//--
6641//-- case 0xA3: /* BT Gv,Ev */
6642//-- eip = dis_bt_G_E ( cb, sorb, sz, eip, BtOpNone );
6643//-- break;
6644//-- case 0xB3: /* BTR Gv,Ev */
6645//-- eip = dis_bt_G_E ( cb, sorb, sz, eip, BtOpReset );
6646//-- break;
6647//-- case 0xAB: /* BTS Gv,Ev */
6648//-- eip = dis_bt_G_E ( cb, sorb, sz, eip, BtOpSet );
6649//-- break;
6650//-- case 0xBB: /* BTC Gv,Ev */
6651//-- eip = dis_bt_G_E ( cb, sorb, sz, eip, BtOpComp );
6652//-- break;
6653//--
6654//-- /* =-=-=-=-=-=-=-=-=- CMOV =-=-=-=-=-=-=-=-=-=-=-= */
6655//--
6656//-- case 0x40:
6657//-- case 0x41:
6658//-- case 0x42: /* CMOVBb/CMOVNAEb (cmov below) */
6659//-- case 0x43: /* CMOVNBb/CMOVAEb (cmov not below) */
6660//-- case 0x44: /* CMOVZb/CMOVEb (cmov zero) */
6661//-- case 0x45: /* CMOVNZb/CMOVNEb (cmov not zero) */
6662//-- case 0x46: /* CMOVBEb/CMOVNAb (cmov below or equal) */
6663//-- case 0x47: /* CMOVNBEb/CMOVAb (cmov not below or equal) */
6664//-- case 0x48: /* CMOVSb (cmov negative) */
6665//-- case 0x49: /* CMOVSb (cmov not negative) */
6666//-- case 0x4A: /* CMOVP (cmov parity even) */
6667//-- case 0x4B: /* CMOVNP (cmov parity odd) */
6668//-- case 0x4C: /* CMOVLb/CMOVNGEb (cmov less) */
6669//-- case 0x4D: /* CMOVGEb/CMOVNLb (cmov greater or equal) */
6670//-- case 0x4E: /* CMOVLEb/CMOVNGb (cmov less or equal) */
6671//-- case 0x4F: /* CMOVGb/CMOVNLEb (cmov greater) */
6672//-- eip = dis_cmov_E_G(cb, sorb, sz, (Condcode)(opc - 0x40), eip);
6673//-- break;
6674//--
6675//-- /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
6676//--
6677//-- case 0xB0: /* CMPXCHG Gv,Ev */
6678//-- eip = dis_cmpxchg_G_E ( cb, sorb, 1, eip );
6679//-- break;
6680//-- case 0xB1: /* CMPXCHG Gv,Ev */
6681//-- eip = dis_cmpxchg_G_E ( cb, sorb, sz, eip );
6682//-- break;
6683//-- case 0xC7: /* CMPXCHG8B Gv */
6684//-- eip = dis_cmpxchg8b ( cb, sorb, eip );
6685//-- break;
6686//--
6687//-- /* =-=-=-=-=-=-=-=-=- CPUID -=-=-=-=-=-=-=-=-=-=-= */
6688//--
6689//-- case 0xA2: /* CPUID */
6690//-- if (!VG_(cpu_has_feature)(VG_X86_FEAT_CPUID))
6691//-- goto decode_failure;
6692//--
6693//-- t1 = newTemp(cb);
6694//-- t2 = newTemp(cb);
6695//-- t3 = newTemp(cb);
6696//-- t4 = newTemp(cb);
6697//-- uInstr0(cb, CALLM_S, 0);
6698//--
6699//-- uInstr2(cb, GET, 4, ArchReg, R_EAX, TempReg, t1);
6700//-- uInstr1(cb, PUSH, 4, TempReg, t1);
6701//--
6702//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
6703//-- uLiteral(cb, 0);
6704//-- uInstr1(cb, PUSH, 4, TempReg, t2);
6705//--
6706//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t3);
6707//-- uLiteral(cb, 0);
6708//-- uInstr1(cb, PUSH, 4, TempReg, t3);
6709//--
6710//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t4);
6711//-- uLiteral(cb, 0);
6712//-- uInstr1(cb, PUSH, 4, TempReg, t4);
6713//--
6714//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_CPUID));
6715//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
6716//--
6717//-- uInstr1(cb, POP, 4, TempReg, t4);
6718//-- uInstr2(cb, PUT, 4, TempReg, t4, ArchReg, R_EDX);
6719//--
6720//-- uInstr1(cb, POP, 4, TempReg, t3);
6721//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_ECX);
6722//--
6723//-- uInstr1(cb, POP, 4, TempReg, t2);
6724//-- uInstr2(cb, PUT, 4, TempReg, t2, ArchReg, R_EBX);
6725//--
6726//-- uInstr1(cb, POP, 4, TempReg, t1);
6727//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, R_EAX);
6728//--
6729//-- uInstr0(cb, CALLM_E, 0);
6730//-- DIP("cpuid\n");
6731//-- break;
6732//--
6733//-- /* =-=-=-=-=-=-=-=-=- MOVZX, MOVSX =-=-=-=-=-=-=-= */
6734//--
6735//-- case 0xB6: /* MOVZXb Eb,Gv */
6736//-- eip = dis_movx_E_G ( cb, sorb, eip, 1, 4, False );
6737//-- break;
6738//-- case 0xB7: /* MOVZXw Ew,Gv */
6739//-- eip = dis_movx_E_G ( cb, sorb, eip, 2, 4, False );
6740//-- break;
6741//--
6742//-- case 0xBE: /* MOVSXb Eb,Gv */
6743//-- eip = dis_movx_E_G ( cb, sorb, eip, 1, 4, True );
6744//-- break;
6745//-- case 0xBF: /* MOVSXw Ew,Gv */
6746//-- eip = dis_movx_E_G ( cb, sorb, eip, 2, 4, True );
6747//-- break;
6748//--
6749//-- /* =-=-=-=-=-=-=-=-=-=-= MOVNTI -=-=-=-=-=-=-=-=-= */
6750//--
6751//-- case 0xC3: /* MOVNTI Gv,Ev */
6752//-- vg_assert(sz == 4);
6753//-- modrm = getUChar(eip);
6754//-- vg_assert(!epartIsReg(modrm));
6755//-- t1 = newTemp(cb);
6756//-- uInstr2(cb, GET, 4, ArchReg, gregOfRM(modrm), TempReg, t1);
6757//-- pair = disAMode ( cb, sorb, eip, dis_buf );
6758//-- t2 = LOW24(pair);
6759//-- eip += HI8(pair);
6760//-- uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
6761//-- DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
6762//-- break;
6763//--
6764//-- /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
6765//--
6766//-- case 0xAF: /* IMUL Ev, Gv */
6767//-- eip = dis_mul_E_G ( cb, sorb, sz, eip, True );
6768//-- break;
6769//--
6770//-- /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
6771//-- case 0x80:
6772//-- case 0x81:
6773//-- case 0x82: /* JBb/JNAEb (jump below) */
6774//-- case 0x83: /* JNBb/JAEb (jump not below) */
6775//-- case 0x84: /* JZb/JEb (jump zero) */
6776//-- case 0x85: /* JNZb/JNEb (jump not zero) */
6777//-- case 0x86: /* JBEb/JNAb (jump below or equal) */
6778//-- case 0x87: /* JNBEb/JAb (jump not below or equal) */
6779//-- case 0x88: /* JSb (jump negative) */
6780//-- case 0x89: /* JSb (jump not negative) */
6781//-- case 0x8A: /* JP (jump parity even) */
6782//-- case 0x8B: /* JNP/JPO (jump parity odd) */
6783//-- case 0x8C: /* JLb/JNGEb (jump less) */
6784//-- case 0x8D: /* JGEb/JNLb (jump greater or equal) */
6785//-- case 0x8E: /* JLEb/JNGb (jump less or equal) */
6786//-- case 0x8F: /* JGb/JNLEb (jump greater) */
6787//-- d32 = (eip+4) + getUDisp32(eip); eip += 4;
6788//-- jcc_lit(cb, d32, (Condcode)(opc - 0x80));
6789//-- jmp_lit(cb, eip);
6790//-- *isEnd = True;
6791//-- DIP("j%s-32 0x%x\n", VG_(name_UCondcode)(opc - 0x80), d32);
6792//-- break;
6793//--
6794//-- /* =-=-=-=-=-=-=-=-=- RDTSC -=-=-=-=-=-=-=-=-=-=-= */
6795//--
6796//-- case 0x31: /* RDTSC */
6797//-- t1 = newTemp(cb);
6798//-- t2 = newTemp(cb);
6799//-- t3 = newTemp(cb);
6800//-- uInstr0(cb, CALLM_S, 0);
6801//-- // Nb: even though these args aren't used by RDTSC_helper, need
6802//-- // them to be defined (for Memcheck). The TempRegs pushed must
6803//-- // also be distinct.
6804//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t1);
6805//-- uLiteral(cb, 0);
6806//-- uInstr1(cb, PUSH, 4, TempReg, t1);
6807//-- uInstr2(cb, MOV, 4, Literal, 0, TempReg, t2);
6808//-- uLiteral(cb, 0);
6809//-- uInstr1(cb, PUSH, 4, TempReg, t2);
6810//-- uInstr1(cb, CALLM, 0, Lit16, VGOFF_(helper_RDTSC));
6811//-- uFlagsRWU(cb, FlagsEmpty, FlagsEmpty, FlagsEmpty);
6812//-- uInstr1(cb, POP, 4, TempReg, t3);
6813//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_EDX);
6814//-- uInstr1(cb, POP, 4, TempReg, t3);
6815//-- uInstr2(cb, PUT, 4, TempReg, t3, ArchReg, R_EAX);
6816//-- uInstr0(cb, CALLM_E, 0);
6817//-- DIP("rdtsc\n");
6818//-- break;
6819//--
6820//-- /* =-=-=-=-=-=-=-=-=- SETcc Eb =-=-=-=-=-=-=-=-=-= */
6821//-- case 0x90:
6822//-- case 0x91:
6823//-- case 0x92: /* set-Bb/set-NAEb (jump below) */
6824//-- case 0x93: /* set-NBb/set-AEb (jump not below) */
6825//-- case 0x94: /* set-Zb/set-Eb (jump zero) */
6826//-- case 0x95: /* set-NZb/set-NEb (jump not zero) */
6827//-- case 0x96: /* set-BEb/set-NAb (jump below or equal) */
6828//-- case 0x97: /* set-NBEb/set-Ab (jump not below or equal) */
6829//-- case 0x98: /* set-Sb (jump negative) */
6830//-- case 0x99: /* set-Sb (jump not negative) */
6831//-- case 0x9A: /* set-P (jump parity even) */
6832//-- case 0x9B: /* set-NP (jump parity odd) */
6833//-- case 0x9C: /* set-Lb/set-NGEb (jump less) */
6834//-- case 0x9D: /* set-GEb/set-NLb (jump greater or equal) */
6835//-- case 0x9E: /* set-LEb/set-NGb (jump less or equal) */
6836//-- case 0x9F: /* set-Gb/set-NLEb (jump greater) */
6837//-- modrm = getUChar(eip);
6838//-- t1 = newTemp(cb);
6839//-- if (epartIsReg(modrm)) {
6840//-- eip++;
6841//-- uInstr1(cb, CC2VAL, 1, TempReg, t1);
6842//-- uCond(cb, (Condcode)(opc-0x90));
6843//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
6844//-- uInstr2(cb, PUT, 1, TempReg, t1, ArchReg, eregOfRM(modrm));
6845//-- DIP("set%s %s\n", VG_(name_UCondcode)(opc-0x90),
6846//-- nameIReg(1,eregOfRM(modrm)));
6847//-- } else {
6848//-- pair = disAMode ( cb, sorb, eip, dis_buf );
6849//-- t2 = LOW24(pair);
6850//-- eip += HI8(pair);
6851//-- uInstr1(cb, CC2VAL, 1, TempReg, t1);
6852//-- uCond(cb, (Condcode)(opc-0x90));
6853//-- uFlagsRWU(cb, FlagsOSZACP, FlagsEmpty, FlagsEmpty);
6854//-- uInstr2(cb, STORE, 1, TempReg, t1, TempReg, t2);
6855//-- DIP("set%s %s\n", VG_(name_UCondcode)(opc-0x90), dis_buf);
6856//-- }
6857//-- break;
6858//--
6859//-- /* =-=-=-=-=-=-=-=-=- SHLD/SHRD -=-=-=-=-=-=-=-=-= */
6860//--
6861//-- case 0xA4: /* SHLDv imm8,Gv,Ev */
6862//-- modrm = getUChar(eip);
6863//-- eip = dis_SHLRD_Gv_Ev (
6864//-- cb, sorb, eip, modrm, sz,
6865//-- Literal, getUChar(eip + lengthAMode(eip)),
6866//-- True );
6867//-- break;
6868//-- case 0xA5: /* SHLDv %cl,Gv,Ev */
6869//-- modrm = getUChar(eip);
6870//-- eip = dis_SHLRD_Gv_Ev (
6871//-- cb, sorb, eip, modrm, sz, ArchReg, R_CL, True );
6872//-- break;
6873//--
6874//-- case 0xAC: /* SHRDv imm8,Gv,Ev */
6875//-- modrm = getUChar(eip);
6876//-- eip = dis_SHLRD_Gv_Ev (
6877//-- cb, sorb, eip, modrm, sz,
6878//-- Literal, getUChar(eip + lengthAMode(eip)),
6879//-- False );
6880//-- break;
6881//-- case 0xAD: /* SHRDv %cl,Gv,Ev */
6882//-- modrm = getUChar(eip);
6883//-- eip = dis_SHLRD_Gv_Ev (
6884//-- cb, sorb, eip, modrm, sz, ArchReg, R_CL, False );
6885//-- break;
6886//--
6887//-- /* =-=-=-=-=-=-=-=-=- CMPXCHG -=-=-=-=-=-=-=-=-=-= */
6888//--
6889//-- case 0xC0: /* XADD Gb,Eb */
6890//-- eip = dis_xadd_G_E ( cb, sorb, 1, eip );
6891//-- break;
6892//-- case 0xC1: /* XADD Gv,Ev */
6893//-- eip = dis_xadd_G_E ( cb, sorb, sz, eip );
6894//-- break;
6895//--
6896//-- /* =-=-=-=-=-=-=-=-=- MMXery =-=-=-=-=-=-=-=-=-=-= */
6897//--
6898//-- case 0x0D: /* PREFETCH / PREFETCHW - 3Dnow!ery*/
6899//-- case 0x18: /* PREFETCHT0/PREFETCHT1/PREFETCHT2/PREFETCHNTA */
6900//--
6901//-- vg_assert(sz == 4);
6902//-- modrm = getUChar(eip);
6903//-- if (epartIsReg(modrm)) {
6904//-- goto decode_failure;
6905//-- }
6906//-- if (gregOfRM(modrm) > 3) {
6907//-- goto decode_failure;
6908//-- }
6909//-- eip += lengthAMode(eip);
6910//-- if (VG_(print_codegen)) {
6911//-- UChar* hintstr;
6912//-- if (opc == 0x0D) {
6913//-- switch (gregOfRM(modrm)) {
6914//-- case 0: hintstr = ""; break;
6915//-- case 1: hintstr = "w"; break;
6916//-- default: goto decode_failure;
6917//-- }
6918//-- }
6919//-- else {
6920//-- switch (gregOfRM(modrm)) {
6921//-- case 0: hintstr = "nta"; break;
6922//-- case 1: hintstr = "t0"; break;
6923//-- case 2: hintstr = "t1"; break;
6924//-- case 3: hintstr = "t2"; break;
6925//-- default: goto decode_failure;
6926//-- }
6927//-- }
6928//-- VG_(printf)("prefetch%s ...\n", hintstr);
6929//-- }
6930//-- break;
6931//--
6932//-- case 0x71: case 0x72: case 0x73: {
6933//-- /* (sz==4): PSLL/PSRA/PSRL mmxreg by imm8 */
6934//-- /* (sz==2): PSLL/PSRA/PSRL xmmreg by imm8 */
6935//-- UChar byte1, byte2, byte3, subopc, mmreg;
6936//-- vg_assert(sz == 4 || sz == 2);
6937//-- byte1 = opc; /* 0x71/72/73 */
6938//-- byte2 = getUChar(eip); eip++; /* amode / sub-opcode */
6939//-- byte3 = getUChar(eip); eip++; /* imm8 */
6940//-- mmreg = byte2 & 7;
6941//-- subopc = (byte2 >> 3) & 7;
6942//-- if (subopc == 2 || subopc == 6 || subopc == 4) {
6943//-- /* 2 == 010 == SRL, 6 == 110 == SLL, 4 == 100 == SRA */
6944//-- /* ok */
6945//-- } else
6946//-- if (sz == 2 && opc == 0x73 && (subopc == 7 || subopc == 3)) {
6947//-- /* 3 == PSRLDQ, 7 == PSLLDQ */
6948//-- /* This is allowable in SSE. Because sz==2 we fall thru to
6949//-- SSE5 below. */
6950//-- } else {
6951//-- eip -= (sz==2 ? 3 : 2);
6952//-- goto decode_failure;
6953//-- }
6954//-- if (sz == 4) {
6955//-- /* The leading 0x0F is implied for MMX*, so we don't
6956//-- include it. */
6957//-- uInstr2(cb, MMX3, 0,
6958//-- Lit16, (((UShort)byte1) << 8) | ((UShort)byte2),
6959//-- Lit16, ((UShort)byte3) );
6960//-- DIP("ps%s%s $%d, %s\n",
6961//-- ( subopc == 2 ? "rl"
6962//-- : subopc == 6 ? "ll"
6963//-- : subopc == 4 ? "ra"
6964//-- : "??"),
6965//-- nameMMXGran(opc & 3), (Int)byte3, nameMMXReg(mmreg) );
6966//-- } else {
6967//-- /* Whereas we have to include it for SSE. */
6968//-- uInstr3(cb, SSE5, 0,
6969//-- Lit16, (((UShort)0x66) << 8) | ((UShort)0x0F),
6970//-- Lit16, (((UShort)byte1) << 8) | ((UShort)byte2),
6971//-- Lit16, ((UShort)byte3) );
6972//-- DIP("ps%s%s $%d, %s\n",
6973//-- ( subopc == 2 ? "rl"
6974//-- : subopc == 6 ? "ll"
6975//-- : subopc == 4 ? "ra"
6976//-- : subopc == 3 ? "(PSRLDQ)"
6977//-- : subopc == 7 ? "(PSLLDQ)"
6978//-- : "??"),
6979//-- nameMMXGran(opc & 3), (Int)byte3, nameXMMReg(mmreg) );
6980//-- }
6981//-- break;
6982//-- }
6983//--
6984//-- case 0x77: /* EMMS */
6985//-- vg_assert(sz == 4);
6986//-- uInstr1(cb, MMX1, 0, Lit16, ((UShort)(opc)) );
6987//-- DIP("emms\n");
6988//-- break;
6989//--
6990//-- case 0x7E: /* MOVD (src)mmxreg, (dst)ireg-or-mem */
6991//-- vg_assert(sz == 4);
6992//-- modrm = getUChar(eip);
6993//-- if (epartIsReg(modrm)) {
6994//-- eip++;
6995//-- t1 = newTemp(cb);
6996//-- uInstr2(cb, MMX2_ERegWr, 4,
6997//-- Lit16,
6998//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
6999//-- TempReg, t1 );
7000//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, eregOfRM(modrm));
7001//-- DIP("movd %s, %s\n",
7002//-- nameMMXReg(gregOfRM(modrm)), nameIReg(4,eregOfRM(modrm)));
7003//-- } else {
7004//-- Int tmpa;
7005//-- pair = disAMode ( cb, sorb, eip, dis_buf );
7006//-- tmpa = LOW24(pair);
7007//-- eip += HI8(pair);
7008//-- uInstr2(cb, MMX2_MemWr, 4,
7009//-- Lit16,
7010//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
7011//-- TempReg, tmpa);
7012//-- DIP("movd %s, %s\n", nameMMXReg(gregOfRM(modrm)), dis_buf);
7013//-- }
7014//-- break;
7015//--
7016//-- case 0x6E: /* MOVD (src)ireg-or-mem, (dst)mmxreg */
7017//-- vg_assert(sz == 4);
7018//-- modrm = getUChar(eip);
7019//-- if (epartIsReg(modrm)) {
7020//-- eip++;
7021//-- t1 = newTemp(cb);
7022//-- uInstr2(cb, GET, 4, ArchReg, eregOfRM(modrm), TempReg, t1);
7023//-- uInstr2(cb, MMX2_ERegRd, 4,
7024//-- Lit16,
7025//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
7026//-- TempReg, t1 );
7027//-- DIP("movd %s, %s\n",
7028//-- nameIReg(4,eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
7029//-- } else {
7030//-- Int tmpa;
7031//-- pair = disAMode ( cb, sorb, eip, dis_buf );
7032//-- tmpa = LOW24(pair);
7033//-- eip += HI8(pair);
7034//-- uInstr2(cb, MMX2_MemRd, 4,
7035//-- Lit16,
7036//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
7037//-- TempReg, tmpa);
7038//-- DIP("movd %s, %s\n", dis_buf, nameMMXReg(gregOfRM(modrm)));
7039//-- }
7040//-- break;
7041//--
7042//-- case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
7043//-- vg_assert(sz == 4);
7044//-- modrm = getUChar(eip);
7045//-- if (epartIsReg(modrm)) {
7046//-- eip++;
7047//-- uInstr1(cb, MMX2, 0,
7048//-- Lit16,
7049//-- (((UShort)(opc)) << 8) | ((UShort)modrm) );
7050//-- DIP("movq %s, %s\n",
7051//-- nameMMXReg(eregOfRM(modrm)), nameMMXReg(gregOfRM(modrm)));
7052//-- } else {
7053//-- Int tmpa;
7054//-- pair = disAMode ( cb, sorb, eip, dis_buf );
7055//-- tmpa = LOW24(pair);
7056//-- eip += HI8(pair);
7057//-- uInstr2(cb, MMX2_MemRd, 8,
7058//-- Lit16,
7059//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
7060//-- TempReg, tmpa);
7061//-- DIP("movq %s, %s\n",
7062//-- dis_buf, nameMMXReg(gregOfRM(modrm)));
7063//-- }
7064//-- break;
7065//--
7066//-- case 0x7F: /* MOVQ (src)mmxreg, (dst)mmxreg-or-mem */
7067//-- case 0xE7: /* MOVNTQ (src)mmxreg, (dst)mmxreg-or-mem */
7068//-- vg_assert(sz == 4);
7069//-- modrm = getUChar(eip);
7070//-- if (epartIsReg(modrm)) {
7071//-- eip++;
7072//-- uInstr1(cb, MMX2, 0,
7073//-- Lit16,
7074//-- (((UShort)(opc)) << 8) | ((UShort)modrm) );
7075//-- DIP("movq %s, %s\n",
7076//-- nameMMXReg(gregOfRM(modrm)), nameMMXReg(eregOfRM(modrm)));
7077//-- } else {
7078//-- Int tmpa;
7079//-- pair = disAMode ( cb, sorb, eip, dis_buf );
7080//-- tmpa = LOW24(pair);
7081//-- eip += HI8(pair);
7082//-- uInstr2(cb, MMX2_MemWr, 8,
7083//-- Lit16,
7084//-- (((UShort)(opc)) << 8) | ((UShort)modrm),
7085//-- TempReg, tmpa);
7086//-- DIP("mov(nt)q %s, %s\n",
7087//-- nameMMXReg(gregOfRM(modrm)), dis_buf);
7088//-- }
7089//-- break;
7090//--
7091//-- case 0xFC: case 0xFD: case 0xFE:
7092//-- /* PADDgg (src)mmxreg-or-mem, (dst)mmxreg */
7093//-- vg_assert(sz == 4);
7094//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "padd", True );
7095//-- break;
7096//--
7097//-- case 0xD4:
7098//-- /* PADDQ (src)mmxreg-or-mem, (dst)mmxreg */
7099//-- vg_assert(sz == 4);
7100//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "paddq", False );
7101//-- break;
7102//--
7103//-- case 0xEC: case 0xED:
7104//-- /* PADDSgg (src)mmxreg-or-mem, (dst)mmxreg */
7105//-- vg_assert(sz == 4);
7106//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "padds", True );
7107//-- break;
7108//--
7109//-- case 0xDC: case 0xDD:
7110//-- /* PADDUSgg (src)mmxreg-or-mem, (dst)mmxreg */
7111//-- vg_assert(sz == 4);
7112//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "paddus", True );
7113//-- break;
7114//--
7115//-- case 0xF8: case 0xF9: case 0xFA: case 0xFB:
7116//-- /* PSUBgg (src)mmxreg-or-mem, (dst)mmxreg */
7117//-- vg_assert(sz == 4);
7118//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psub", True );
7119//-- break;
7120//--
7121//-- case 0xE8: case 0xE9:
7122//-- /* PSUBSgg (src)mmxreg-or-mem, (dst)mmxreg */
7123//-- vg_assert(sz == 4);
7124//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psubs", True );
7125//-- break;
7126//--
7127//-- case 0xD8: case 0xD9:
7128//-- /* PSUBUSgg (src)mmxreg-or-mem, (dst)mmxreg */
7129//-- vg_assert(sz == 4);
7130//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psubus", True );
7131//-- break;
7132//--
7133//-- case 0xE4: /* PMULHUW (src)mmxreg-or-mem, (dst)mmxreg */
7134//-- vg_assert(sz == 4);
7135//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmulhuw", False );
7136//-- break;
7137//--
7138//-- case 0xE5: /* PMULHW (src)mmxreg-or-mem, (dst)mmxreg */
7139//-- vg_assert(sz == 4);
7140//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmulhw", False );
7141//-- break;
7142//--
7143//-- case 0xD5: /* PMULLW (src)mmxreg-or-mem, (dst)mmxreg */
7144//-- vg_assert(sz == 4);
7145//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmullw", False );
7146//-- break;
7147//--
7148//-- case 0xF4: /* PMULUDQ (src)mmxreg-or-mem, (dst)mmxreg */
7149//-- vg_assert(sz == 4);
7150//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmuludq", False );
7151//-- break;
7152//--
7153//-- case 0xF5: /* PMADDWD (src)mmxreg-or-mem, (dst)mmxreg */
7154//-- vg_assert(sz == 4);
7155//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmaddwd", False );
7156//-- break;
7157//--
7158//-- case 0x74: case 0x75: case 0x76:
7159//-- /* PCMPEQgg (src)mmxreg-or-mem, (dst)mmxreg */
7160//-- vg_assert(sz == 4);
7161//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pcmpeq", True );
7162//-- break;
7163//--
7164//-- case 0x64: case 0x65: case 0x66:
7165//-- /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
7166//-- vg_assert(sz == 4);
7167//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pcmpgt", True );
7168//-- break;
7169//--
7170//-- case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
7171//-- vg_assert(sz == 4);
7172//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "packssdw", False );
7173//-- break;
7174//--
7175//-- case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
7176//-- vg_assert(sz == 4);
7177//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "packsswb", False );
7178//-- break;
7179//--
7180//-- case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
7181//-- vg_assert(sz == 4);
7182//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "packuswb", False );
7183//-- break;
7184//--
7185//-- case 0x68: case 0x69: case 0x6A:
7186//-- /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
7187//-- vg_assert(sz == 4);
7188//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "punpckh", True );
7189//-- break;
7190//--
7191//-- case 0x60: case 0x61: case 0x62:
7192//-- /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
7193//-- vg_assert(sz == 4);
7194//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "punpckl", True );
7195//-- break;
7196//--
7197//-- case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
7198//-- vg_assert(sz == 4);
7199//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pand", False );
7200//-- break;
7201//--
7202//-- case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
7203//-- vg_assert(sz == 4);
7204//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pandn", False );
7205//-- break;
7206//--
7207//-- case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
7208//-- vg_assert(sz == 4);
7209//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "por", False );
7210//-- break;
7211//--
7212//-- case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
7213//-- vg_assert(sz == 4);
7214//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pxor", False );
7215//-- break;
7216//--
7217//-- case 0xF1: case 0xF2: case 0xF3:
7218//-- /* PSLLgg (src)mmxreg-or-mem, (dst)mmxreg */
7219//-- vg_assert(sz == 4);
7220//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psll", True );
7221//-- break;
7222//--
7223//-- case 0xD1: case 0xD2: case 0xD3:
7224//-- /* PSRLgg (src)mmxreg-or-mem, (dst)mmxreg */
7225//-- vg_assert(sz == 4);
7226//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psrl", True );
7227//-- break;
7228//--
7229//-- case 0xE1: case 0xE2:
7230//-- /* PSRAgg (src)mmxreg-or-mem, (dst)mmxreg */
7231//-- vg_assert(sz == 4);
7232//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psra", True );
7233//-- break;
7234//--
7235//-- case 0xDA:
7236//-- /* PMINUB (src)mmxreg-or-mem, (dst)mmxreg */
7237//-- vg_assert(sz == 4);
7238//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pminub", False );
7239//-- break;
7240//--
7241//-- case 0xDE:
7242//-- /* PMAXUB (src)mmxreg-or-mem, (dst)mmxreg */
7243//-- vg_assert(sz == 4);
7244//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmaxub", False );
7245//-- break;
7246//--
7247//-- case 0xEA:
7248//-- /* PMINSW (src)mmxreg-or-mem, (dst)mmxreg */
7249//-- vg_assert(sz == 4);
7250//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pminsw", False );
7251//-- break;
7252//--
7253//-- case 0xEE:
7254//-- /* PMAXSW (src)mmxreg-or-mem, (dst)mmxreg */
7255//-- vg_assert(sz == 4);
7256//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pmaxsw", False );
7257//-- break;
7258//--
7259//-- case 0xE0:
7260//-- /* PAVGB (src)mmxreg-or-mem, (dst)mmxreg */
7261//-- vg_assert(sz == 4);
7262//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pavgb", False );
7263//-- break;
7264//--
7265//-- case 0xE3:
7266//-- /* PAVGW (src)mmxreg-or-mem, (dst)mmxreg */
7267//-- vg_assert(sz == 4);
7268//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "pavgw", False );
7269//-- break;
7270//--
7271//-- case 0xF6:
7272//-- /* PSADBW (src)mmxreg-or-mem, (dst)mmxreg */
7273//-- vg_assert(sz == 4);
7274//-- eip = dis_MMXop_regmem_to_reg ( cb, sorb, eip, opc, "psadbw", False );
7275//-- break;
7276//--
7277//-- case 0x70:
7278//-- /* PSHUFW imm8, (src)mmxreg-or-mem, (dst)mmxreg */
7279//-- vg_assert(sz == 4);
7280//-- eip = dis_MMXop_regmem_to_reg_Imm8 ( cb, sorb, eip, opc, "pshufw", False );
7281//-- break;
7282//--
7283//-- case 0xD7:
7284//-- /* PMOVMSKB (src)mmxreg, (dst)ireg */
7285//-- vg_assert(sz == 4);
7286//-- modrm = getUChar(eip);
7287//-- vg_assert(epartIsReg(modrm));
7288//-- t1 = newTemp(cb);
7289//-- uInstr3(cb, SSE2g_RegWr, 4,
7290//-- Lit16, (((UShort)(0x0F)) << 8) | (UShort)(opc),
7291//-- Lit16, (UShort)modrm,
7292//-- TempReg, t1 );
7293//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
7294//-- DIP("pmovmskb %s, %s\n",
7295//-- nameMMXReg(eregOfRM(modrm)), nameIReg(4,gregOfRM(modrm)));
7296//-- eip++;
7297//-- break;
7298//--
7299//-- case 0xC5:
7300//-- /* PEXTRW (src)mmxreg, (dst)ireg */
7301//-- vg_assert(sz == 4);
7302//-- t1 = newTemp(cb);
7303//-- modrm = getUChar(eip); eip++;
7304//-- abyte = getUChar(eip); eip++;
7305//-- vg_assert(epartIsReg(modrm));
7306//-- uInstr3(cb, SSE2g1_RegWr, 4,
7307//-- Lit16, (((UShort)(0x0F)) << 8) | (UShort)(opc),
7308//-- Lit16, (UShort)modrm,
7309//-- TempReg, t1 );
7310//-- uLiteral(cb, abyte);
7311//-- uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
7312//-- DIP("pextrw %s, %d, %s\n",
7313//-- nameMMXReg(eregOfRM(modrm)), (Int)abyte,
7314//-- nameIReg(4, gregOfRM(modrm)));
7315//-- break;
7316//--
7317//-- case 0xC4:
7318//-- /* PINSRW (src)ireg, (dst)mmxreg */
7319//-- vg_assert(sz == 4);
7320//-- t1 = newTemp(cb);
7321//-- modrm = getUChar(eip); eip++;
7322//-- abyte = getUChar(eip); eip++;
7323//-- vg_assert(epartIsReg(modrm));
7324//-- uInstr2(cb, GET, 2, ArchReg, eregOfRM(modrm), TempReg, t1);
7325//-- uInstr3(cb, SSE2e1_RegRd, 2,
7326//-- Lit16, (((UShort)(0x0F)) << 8) | (UShort)(opc),
7327//-- Lit16, (UShort)modrm,
7328//-- TempReg, t1 );
7329//-- uLiteral(cb, abyte);
7330//-- DIP("pinsrw %s, %d, %s\n", nameIReg(2, eregOfRM(modrm)),
7331//-- (Int)abyte, nameMMXReg(gregOfRM(modrm)));
7332//-- break;
7333//--
7334//-- case 0xA1: /* POP %FS */
7335//-- dis_pop_segreg( cb, R_FS, sz ); break;
7336//-- case 0xA9: /* POP %GS */
7337//-- dis_pop_segreg( cb, R_GS, sz ); break;
7338//--
7339//-- case 0xA0: /* PUSH %FS */
7340//-- dis_push_segreg( cb, R_FS, sz ); break;
7341//-- case 0xA8: /* PUSH %GS */
7342//-- dis_push_segreg( cb, R_GS, sz ); break;
7343//--
7344//-- /* =-=-=-=-=-=-=-=-=- unimp2 =-=-=-=-=-=-=-=-=-=-= */
7345//--
7346//-- default:
7347//-- goto decode_failure;
7348//-- } /* switch (opc) for the 2-byte opcodes */
7349//-- goto decode_success;
7350//-- } /* case 0x0F: of primary opcode */
7351
7352 /* ------------------------ ??? ------------------------ */
7353
7354 default:
sewardjd1061ab2004-07-08 01:45:30 +00007355 // decode_failure:
sewardjc9a65702004-07-07 16:32:57 +00007356 /* All decode failures end up here. */
7357 vex_printf("disInstr(x86): unhandled instruction bytes: "
7358 "0x%x 0x%x 0x%x 0x%x\n",
7359 (Int)getIByte(delta_start+0),
7360 (Int)getIByte(delta_start+1),
7361 (Int)getIByte(delta_start+2),
7362 (Int)getIByte(delta_start+3) );
7363 vpanic("x86toIR: unimplemented insn");
7364 /* Print address of failing instruction. */
7365 //VG_(describe_eip)((Addr)eip_start, loc_buf, M_VG_ERRTXT);
7366 //VG_(printf)(" at %s\n", loc_buf);
7367
7368 //uInstr0(cb, CALLM_S, 0);
7369 //uInstr1(cb, CALLM, 0, Lit16,
7370 // VGOFF_(helper_undefined_instruction));
7371 //uInstr0(cb, CALLM_E, 0);
7372
7373 /* just because everything else insists the last instruction of
7374 a BB is a jmp */
7375 //jmp_lit(cb, eip);
7376 //*isEnd = True;
7377 //break;
7378 //return eip;
7379
7380 } /* switch (opc) for the main (primary) opcode switch. */
7381
sewardjd1061ab2004-07-08 01:45:30 +00007382 //decode_success:
sewardjc9a65702004-07-07 16:32:57 +00007383 /* All decode successes end up here. */
7384 DIP("\n");
7385 if (first_stmt == NULL)
7386 first_stmt = irbb->stmts;
7387 else
7388 first_stmt = first_stmt->link;
7389 while (True) {
7390 if (!first_stmt)
7391 break;
7392 vex_printf(" ");
7393 ppIRStmt(first_stmt);
sewardjd1061ab2004-07-08 01:45:30 +00007394 DIP("\n");
sewardjc9a65702004-07-07 16:32:57 +00007395 if (first_stmt == last_stmt)
7396 break;
7397 first_stmt = first_stmt->link;
7398 }
sewardjd1061ab2004-07-08 01:45:30 +00007399 if (*isEnd) {
7400 vassert(irbb->next != NULL);
7401 vex_printf(" ");
7402 ppIRNext(irbb->next);
7403 DIP("\n");
7404 }
sewardjc9a65702004-07-07 16:32:57 +00007405 //for (; first_uinstr < cb->used; first_uinstr++) {
7406 // Bool sane = VG_(saneUInstr)(True, True, &cb->instrs[first_uinstr]);
7407 // if (!sane)
7408 // VG_(up_UInstr)(first_uinstr, &cb->instrs[first_uinstr]);
7409 // else if (VG_(print_codegen))
7410 // VG_(pp_UInstr)(first_uinstr, &cb->instrs[first_uinstr]);
7411 // vg_assert(sane);
7412 // }
7413 return delta;
7414}
7415
7416
7417/* Disassemble a complete basic block, starting at eip, and dumping
7418 the ucode into cb. Returns the size, in bytes, of the basic
7419 block. */
7420IRBB* bbToIR_X86Instr ( Char* x86code,
7421 Addr64 eip,
7422 Int* guest_bytes_read,
7423 Bool (*byte_accessible)(Addr64),
7424 Bool host_bigendian )
7425{
7426 UInt delta;
7427 Int n_instrs;
7428 Bool isEnd;
7429
7430 /* Set up globals. */
7431 host_is_bigendian = host_bigendian;
7432 print_codegen = (vex_verbosity >= 1);
7433 guest_code = x86code;
7434 guest_eip = (Addr32)eip;
7435 irbb = mkIRBB( newIRTypeEnv(), NULL, NULL );
7436 last_stmt = NULL;
7437 next_irtemp = (IRTemp)0;
7438
7439 vassert((eip >> 32) == 0);
7440
7441 DIP("Original x86 code to IR:\n\n");
7442
7443 /* Delta keeps track of how far along the x86code array we
7444 have so far gone. */
7445 isEnd = False;
7446 delta = 0;
7447 n_instrs = 0;
7448 while (True) {
7449 if (isEnd) break;
7450 vassert(n_instrs < vex_guest_insns_per_bb);
7451 delta = disInstr ( delta, &isEnd );
7452 n_instrs++;
7453 DIP("\n");
7454 }
7455
sewardjd1061ab2004-07-08 01:45:30 +00007456 *guest_bytes_read = delta;
sewardjc9a65702004-07-07 16:32:57 +00007457 return irbb;
7458}
7459
7460#undef DIP
7461#undef DIS
7462
7463/*--------------------------------------------------------------------*/
7464/*--- end vg_to_ucode.c ---*/
7465/*--------------------------------------------------------------------*/