Cleanup: separate InstructionDecoderImpl into new files, remove impl files from publi...
[dyninst.git] / instructionAPI / src / InstructionDecoder-x86.C
1 /*
2 * Copyright (c) 1996-2009 Barton P. Miller
3 *
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as "Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance.  We reserve the right to update, modify,
7 * or discontinue this software at any time.  We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
10 *
11 * By your use of Paradyn, you understand and agree that we (or any
12 * other person or entity with proprietary rights in Paradyn) are
13 * under no obligation to provide either maintenance services,
14 * update services, notices of latent defects, or correction of
15 * defects for Paradyn.
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License, or (at your option) any later version.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 * Lesser General Public License for more details.
26 *
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32 #define INSIDE_INSTRUCTION_API
33
34 #include "InstructionDecoder-x86.h"
35 #include "../h/Expression.h"
36 #include "arch-x86.h"
37 #include "../h/Register.h"
38 #include "../h/Dereference.h"
39 #include "../h/Immediate.h"
40 #include "../h/BinaryFunction.h"
41 #include "../../common/h/singleton_object_pool.h"
42
43 using namespace std;
44 namespace Dyninst
45 {
46     namespace InstructionAPI
47     {
48     
49         bool readsOperand(unsigned int opsema, unsigned int i)
50         {
51             switch(opsema) {
52                 case s1R2R:
53                     return (i == 0 || i == 1);
54                 case s1R:
55                 case s1RW:
56                     return i == 0;
57                 case s1W:
58                     return false;
59                 case s1W2RW:
60                 case s1W2R:   // second operand read, first operand written (e.g. mov)
61                     return i == 1;
62                 case s1RW2R:  // two operands read, first written (e.g. add)
63                 case s1RW2RW: // e.g. xchg
64                 case s1R2RW:
65                     return i == 0 || i == 1;
66                 case s1W2R3R: // e.g. imul
67                 case s1W2RW3R: // some mul
68                 case s1W2R3RW: // (stack) push & pop
69                     return i == 1 || i == 2;
70                 case s1W2W3R: // e.g. les
71                     return i == 2;
72                 case s1RW2R3R: // shld/shrd
73                 case s1RW2RW3R: // [i]div, cmpxch8b
74                 case s1R2R3R:
75                     return i == 0 || i == 1 || i == 2;
76                     break;
77                 case sNONE:
78                 default:
79                     return false;
80             }
81       
82         }
83       
84         bool writesOperand(unsigned int opsema, unsigned int i)
85         {
86             switch(opsema) {
87                 case s1R2R:
88                 case s1R:
89                     return false;
90                 case s1RW:
91                 case s1W:
92                     case s1W2R:   // second operand read, first operand written (e.g. mov)
93                         case s1RW2R:  // two operands read, first written (e.g. add)
94                             case s1W2R3R: // e.g. imul
95                                 case s1RW2R3R: // shld/shrd
96                                     return i == 0;
97                 case s1R2RW:
98                     return i == 1;
99                 case s1W2RW:
100                     case s1RW2RW: // e.g. xchg
101                         case s1W2RW3R: // some mul
102                             case s1W2W3R: // e.g. les
103                                 case s1RW2RW3R: // [i]div, cmpxch8b
104                                     return i == 0 || i == 1;
105                                     case s1W2R3RW: // (stack) push & pop
106                                         return i == 0 || i == 2;
107                 case sNONE:
108                 default:
109                     return false;
110             }
111         }
112
113
114     
115     INSTRUCTION_EXPORT InstructionDecoder_x86::InstructionDecoder_x86(Architecture a) :
116       InstructionDecoderImpl(a),
117     locs(NULL),
118     decodedInstruction(NULL),
119     is32BitMode(true),
120     sizePrefixPresent(false)
121     {
122     }
123     INSTRUCTION_EXPORT InstructionDecoder_x86::~InstructionDecoder_x86()
124     {
125         if(decodedInstruction) decodedInstruction->~ia32_instruction();
126         free(decodedInstruction);
127         if(locs) locs->~ia32_locations();
128         free(locs);
129
130     }
131     static const unsigned char modrm_use_sib = 4;
132     
133     INSTRUCTION_EXPORT void InstructionDecoder_x86::setMode(bool is64)
134     {
135         ia32_set_mode_64(is64);
136     }
137     
138       Expression::Ptr InstructionDecoder_x86::makeSIBExpression(const InstructionDecoder::buffer& b)
139     {
140         unsigned scale;
141         Register index;
142         Register base;
143         Result_Type registerType = ia32_is_mode_64() ? u32 : u64;
144
145         decode_SIB(locs->sib_byte, scale, index, base);
146
147         Expression::Ptr scaleAST(make_shared(singleton_object_pool<Immediate>::construct(Result(u8, dword_t(scale)))));
148         Expression::Ptr indexAST(make_shared(singleton_object_pool<RegisterAST>::construct(makeRegisterID(index, registerType,
149                                     locs->rex_x))));
150         Expression::Ptr baseAST;
151         if(base == 0x05)
152         {
153             switch(locs->modrm_mod)
154             {
155                 case 0x00:
156                     baseAST = decodeImmediate(op_d, b.start + locs->sib_position + 1);
157                     break;
158                     case 0x01: {
159                         MachRegister reg;
160                         if (locs->rex_b)
161                             reg = x86_64::r13;
162                         else
163                           reg = MachRegister::getFramePointer(m_Arch);
164                         
165                         baseAST = makeAddExpression(make_shared(singleton_object_pool<RegisterAST>::construct(reg)),
166                                                     decodeImmediate(op_b, b.start + locs->sib_position + 1),
167                                                     registerType);
168                         break;
169                     }
170                     case 0x02: {
171                         MachRegister reg;
172                         if (locs->rex_b)
173                             reg = x86_64::r13;
174                         else
175                             reg = MachRegister::getFramePointer(m_Arch);
176
177                         baseAST = makeAddExpression(make_shared(singleton_object_pool<RegisterAST>::construct(reg)), 
178                                                     decodeImmediate(op_d, b.start + locs->sib_position + 1),
179                                                     registerType);
180                         break;
181                     }
182                 case 0x03:
183                 default:
184                     assert(0);
185                     break;
186             };
187         }
188         else
189         {
190             baseAST = make_shared(singleton_object_pool<RegisterAST>::construct(makeRegisterID(base, 
191                                                                                                registerType,
192                                                                                                locs->rex_b)));
193         }
194         if(index == 0x04 && (!(ia32_is_mode_64()) || !(locs->rex_x)))
195         {
196             return baseAST;
197         }
198         return makeAddExpression(baseAST, makeMultiplyExpression(indexAST, scaleAST, registerType), registerType);
199     }
200
201       Expression::Ptr InstructionDecoder_x86::makeModRMExpression(const InstructionDecoder::buffer& b,
202                                                                   unsigned int opType)
203     {
204         unsigned int regType = op_d;
205         if(ia32_is_mode_64())
206         {
207             regType = op_q;
208         }
209         Result_Type aw = ia32_is_mode_64() ? u32 : u64;
210         Expression::Ptr e =
211           makeRegisterExpression(makeRegisterID(locs->modrm_rm, regType, (locs->rex_b == 1)));
212         switch(locs->modrm_mod)
213         {
214             case 0:
215                 if(locs->modrm_rm == modrm_use_sib) {
216                     e = makeSIBExpression(b);
217                 }
218                 if(locs->modrm_rm == 0x5)
219                 {
220                     assert(locs->opcode_position > -1);
221                     entryID opcode = decodedInstruction->getEntry()->getID(locs);
222         // treat FP decodes as legacy mode since it appears that's what we've got in our
223         // old code...
224                     if(ia32_is_mode_64() && (opcode < e_fadd || opcode > e_fxsave) && opcode != e_fp_generic)
225                     {
226                         e = makeAddExpression(makeRegisterExpression(x86_64::rip),
227                                             getModRMDisplacement(b), aw);
228                     }
229                     else
230                     {
231                         e = getModRMDisplacement(b);
232                     }
233         
234                 }
235                 if(opType == op_lea)
236                 {
237                     return e;
238                 }
239                 return makeDereferenceExpression(e, makeSizeType(opType));
240             case 1:
241             case 2:
242             {
243                 if(locs->modrm_rm == modrm_use_sib) {
244                     e = makeSIBExpression(b);
245                 }
246                 Expression::Ptr disp_e = makeAddExpression(e, getModRMDisplacement(b), aw);
247                 if(opType == op_lea)
248                 {
249                     return disp_e;
250                 }
251                 return makeDereferenceExpression(disp_e, makeSizeType(opType));
252             }
253             case 3:
254               return makeRegisterExpression(makeRegisterID(locs->modrm_rm, opType, (locs->rex_b == 1)));
255             default:
256                 return Expression::Ptr();
257         
258         };
259         
260     }
261
262     Expression::Ptr InstructionDecoder_x86::decodeImmediate(unsigned int opType, const unsigned char* immStart, 
263                                                             bool isSigned)
264     {
265         switch(opType)
266         {
267             case op_b:
268                 return Immediate::makeImmediate(Result(isSigned ? s8 : u8 ,*(const byte_t*)(immStart)));
269                 break;
270             case op_d:
271                 return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
272             case op_w:
273                 return Immediate::makeImmediate(Result(isSigned ? s16 : u16,*(const word_t*)(immStart)));
274                 break;
275             case op_q:
276                 return Immediate::makeImmediate(Result(isSigned ? s64 : u64,*(const int64_t*)(immStart)));
277                 break;
278             case op_v:
279             case op_z:
280         // 32 bit mode & no prefix, or 16 bit mode & prefix => 32 bit
281         // 16 bit mode, no prefix or 32 bit mode, prefix => 16 bit
282                 if(!sizePrefixPresent)
283                 {
284                     return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
285                 }
286                 else
287                 {
288                     return Immediate::makeImmediate(Result(isSigned ? s16 : u16,*(const word_t*)(immStart)));
289                 }
290         
291                 break;
292             case op_p:
293         // 32 bit mode & no prefix, or 16 bit mode & prefix => 48 bit
294         // 16 bit mode, no prefix or 32 bit mode, prefix => 32 bit
295                 if(!sizePrefixPresent)
296                 {
297                     return Immediate::makeImmediate(Result(isSigned ? s48 : u48,*(const int64_t*)(immStart)));
298                 }
299                 else
300                 {
301                     return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
302                 }
303         
304                 break;
305             case op_a:
306             case op_dq:
307             case op_pd:
308             case op_ps:
309             case op_s:
310             case op_si:
311             case op_lea:
312             case op_allgprs:
313             case op_512:
314             case op_c:
315                 assert(!"Can't happen: opType unexpected for valid ways to decode an immediate");
316                 return Expression::Ptr();
317             default:
318                 assert(!"Can't happen: opType out of range");
319                 return Expression::Ptr();
320         }
321     }
322     
323     Expression::Ptr InstructionDecoder_x86::getModRMDisplacement(const InstructionDecoder::buffer& b)
324     {
325         int disp_pos;
326
327         if(locs->sib_position != -1)
328         {
329             disp_pos = locs->sib_position + 1;
330         }
331         else
332         {
333             disp_pos = locs->modrm_position + 1;
334         }
335         switch(locs->modrm_mod)
336         {
337             case 1:
338                 return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, (*(const byte_t*)(b.start +
339                         disp_pos)))));
340                 break;
341             case 2:
342                 if(sizePrefixPresent)
343                 {
344                     return make_shared(singleton_object_pool<Immediate>::construct(Result(s16, *((const word_t*)(b.start +
345                             disp_pos)))));
346                 }
347                 else
348                 {
349                     return make_shared(singleton_object_pool<Immediate>::construct(Result(s32, *((const dword_t*)(b.start +
350                             disp_pos)))));
351                 }
352                 break;
353             case 0:
354                 // In 16-bit mode, the word displacement is modrm r/m 6
355                 if(sizePrefixPresent)
356                 {
357                     if(locs->modrm_rm == 6)
358                     {
359                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s16,
360                                            *((const dword_t*)(b.start + disp_pos)))));
361                     }
362                     else
363                     {
364                         assert(b.start + disp_pos + 1 <= b.end);
365                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
366                     }
367                     break;
368                 }
369                 // ...and in 32-bit mode, the dword displacement is modrm r/m 5
370                 else
371                 {
372                     if(locs->modrm_rm == 5)
373                     {
374                         assert(b.start + disp_pos + 4 <= b.end);
375                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s32,
376                                            *((const dword_t*)(b.start + disp_pos)))));
377                     }
378                     else
379                     {
380                         assert(b.start + disp_pos + 1 <= b.end);
381                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
382                     }
383                     break;
384                 }
385             default:
386                 assert(b.start + disp_pos + 1 <= b.end);
387                 return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
388                 break;
389         }
390     }
391
392     enum intelRegBanks
393     {
394         b_8bitNoREX = 0,
395         b_16bit,
396         b_32bit,
397         b_segment,
398         b_64bit,
399         b_xmm,
400         b_mm,
401         b_cr,
402         b_dr,
403         b_tr,
404         b_amd64ext,
405         b_8bitWithREX
406     };
407     using namespace x86;
408     
409     static MachRegister IntelRegTable[][8] = {
410         {
411             al, cl, dl, bl, ah, ch, dh, bh
412         },
413         {
414             ax, cx, dx, bx, sp, bp, si, di
415         },
416         {
417             eax, ecx, edx, ebx, esp, ebp, esi, edi
418         },
419         {
420             es, cs, ss, ds, fs, gs, InvalidReg, InvalidReg
421         },
422         {
423             x86_64::rax, x86_64::rcx, x86_64::rdx, x86_64::rbx, x86_64::rsp, x86_64::rbp, x86_64::rsi, x86_64::rdi
424         },
425         {
426             xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
427         },
428         {
429             mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7
430         },
431         {
432             cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7
433         },
434         {
435             dr0, dr1, dr2, dr3, dr4, dr5, dr6, dr7
436         },
437         {
438             tr0, tr1, tr2, tr3, tr4, tr5, tr6, tr7
439         },
440         {
441             x86_64::r8, x86_64::r9, x86_64::r10, x86_64::r11, x86_64::r12, x86_64::r13, x86_64::r14, x86_64::r15
442         },
443         {
444             x86_64::al, x86_64::cl, x86_64::dl, x86_64::bl, x86_64::spl, x86_64::bpl, x86_64::sil, x86_64::dil
445         }
446
447     };
448
449     MachRegister InstructionDecoder_x86::makeRegisterID(unsigned int intelReg, unsigned int opType,
450                                         bool isExtendedReg)
451     {
452         MachRegister retVal;
453         if(isExtendedReg)
454         {
455             retVal = IntelRegTable[b_amd64ext][intelReg];
456         }
457         else if(locs->rex_w)
458         {
459             // AMD64 with 64-bit operands
460             retVal = IntelRegTable[b_64bit][intelReg];
461         }
462         else
463         {
464             switch(opType)
465             {
466                 case op_b:
467                     if (locs->rex_position == -1) {
468                         retVal = IntelRegTable[b_8bitNoREX][intelReg];
469                     } else {
470                         retVal = IntelRegTable[b_8bitWithREX][intelReg];
471                     }
472                     break;
473                 case op_q:
474                     retVal = IntelRegTable[b_64bit][intelReg];
475                     break;
476                 case op_w:
477                   retVal = IntelRegTable[b_16bit][intelReg];
478                   break;
479                 case op_d:
480                 case op_si:
481                 default:
482                     retVal = IntelRegTable[b_32bit][intelReg];
483                     break;
484                   
485             }
486         }
487         if (!ia32_is_mode_64()) {
488           if ((retVal.val() & 0x00ffffff) == 0x0001000c)
489             assert(0);
490         }
491
492         return MachRegister((retVal.val() & ~retVal.getArchitecture()) | m_Arch);
493     }
494     
495     Result_Type InstructionDecoder_x86::makeSizeType(unsigned int opType)
496     {
497         switch(opType)
498         {
499             case op_b:
500             case op_c:
501                 return u8;
502             case op_d:
503             case op_ss:
504             case op_allgprs:
505             case op_si:
506                 return u32;
507             case op_w:
508             case op_a:
509                 return u16;
510             case op_q:
511             case op_sd:
512                 return u64;
513             case op_v:
514             case op_lea:
515             case op_z:
516                 if(is32BitMode ^ sizePrefixPresent)
517                 {
518                     return u32;
519                 }
520                 else
521                 {
522                     return u16;
523                 }
524                 break;
525             case op_p:
526                 // book says operand size; arch-x86 says word + word * operand size
527                 if(is32BitMode ^ sizePrefixPresent)
528                 {
529                     return u48;
530                 }
531                 else
532                 {
533                     return u32;
534                 }
535             case op_dq:
536                 return u64;
537             case op_512:
538                 return m512;
539             case op_pi:
540             case op_ps:
541             case op_pd:
542                 return dbl128;
543             case op_s:
544                 return u48;
545             case op_f:
546                 return sp_float;
547             case op_dbl:
548                 return dp_float;
549             case op_14:
550                 return m14;
551             default:
552                 assert(!"Can't happen!");
553                 return u8;
554         }
555     }
556
557
558     bool InstructionDecoder_x86::decodeOneOperand(const InstructionDecoder::buffer& b,
559                                                   const ia32_operand& operand,
560                                                   int & imm_index, /* immediate operand index */
561                                                   const Instruction* insn_to_complete, 
562                                                   bool isRead, bool isWritten)
563     {
564       unsigned int regType = op_d;
565       if(ia32_is_mode_64())
566         {
567           regType = op_q;
568         }
569       bool isCFT = false;
570       bool isCall = false;
571       InsnCategory cat = insn_to_complete->getCategory();
572       if(cat == c_BranchInsn || cat == c_CallInsn)
573         {
574           isCFT = true;
575           if(cat == c_CallInsn)
576             {
577               isCall = true;
578             }
579         }
580       unsigned int optype = operand.optype;
581       if (sizePrefixPresent && 
582           ((optype == op_v) ||
583            (optype == op_z))) {
584         optype = op_w;
585       }
586                 switch(operand.admet)
587                 {
588                     case 0:
589                     // No operand
590                     {
591 /*                        fprintf(stderr, "ERROR: Instruction with mismatched operands. Raw bytes: ");
592                         for(unsigned int i = 0; i < decodedInstruction->getSize(); i++) {
593                             fprintf(stderr, "%x ", b.start[i]);
594                         }
595                         fprintf(stderr, "\n");*/
596                         assert(!"Mismatched number of operands--check tables");
597                         return false;
598                     }
599                     case am_A:
600                     {
601                         // am_A only shows up as a far call/jump.  Position 1 should be universally safe.
602                         Expression::Ptr addr(decodeImmediate(optype, b.start + 1));
603                         Expression::Ptr op(makeDereferenceExpression(addr, makeSizeType(optype)));
604                         insn_to_complete->addSuccessor(op, isCall, false, false, false);
605                     }
606                     break;
607                     case am_C:
608                     {
609                         Expression::Ptr op(makeRegisterExpression(IntelRegTable[b_cr][locs->modrm_reg]));
610                         insn_to_complete->appendOperand(op, isRead, isWritten);
611                     }
612                     break;
613                     case am_D:
614                     {
615                         Expression::Ptr op(makeRegisterExpression(IntelRegTable[b_dr][locs->modrm_reg]));
616                         insn_to_complete->appendOperand(op, isRead, isWritten);
617                     }
618                     break;
619                     case am_E:
620                     // am_M is like am_E, except that mod of 0x03 should never occur (am_M specified memory,
621                     // mod of 0x03 specifies direct register access).
622                     case am_M:
623                     // am_R is the inverse of am_M; it should only have a mod of 3
624                     case am_R:
625                         if(isCFT)
626                         {
627                           insn_to_complete->addSuccessor(makeModRMExpression(b, optype), isCall, true, false, false);
628                         }
629                         else
630                         {
631                           insn_to_complete->appendOperand(makeModRMExpression(b, optype), isRead, isWritten);
632                         }
633                     break;
634                     case am_F:
635                     {
636                         Expression::Ptr op(makeRegisterExpression(flags));
637                         insn_to_complete->appendOperand(op, isRead, isWritten);
638                     }
639                     break;
640                     case am_G:
641                     {
642                         Expression::Ptr op(makeRegisterExpression(makeRegisterID(locs->modrm_reg,
643                                 optype, locs->rex_r)));
644                         insn_to_complete->appendOperand(op, isRead, isWritten);
645                     }
646                     break;
647                     case am_I:
648                         insn_to_complete->appendOperand(decodeImmediate(optype, b.start + 
649                                                                         locs->imm_position[imm_index++]), 
650                                                         isRead, isWritten);
651                         break;
652                     case am_J:
653                     {
654                         Expression::Ptr Offset(decodeImmediate(optype, 
655                                                                b.start + locs->imm_position[imm_index++], 
656                                                                true));
657                         Expression::Ptr EIP(makeRegisterExpression(MachRegister::getPC(m_Arch)));
658                         Expression::Ptr InsnSize(make_shared(singleton_object_pool<Immediate>::construct(Result(u8,
659                             decodedInstruction->getSize()))));
660                         Expression::Ptr postEIP(makeAddExpression(EIP, InsnSize, u32));
661
662                         Expression::Ptr op(makeAddExpression(Offset, postEIP, u32));
663                         insn_to_complete->addSuccessor(op, isCall, false, false, false);
664                     }
665                     break;
666                     case am_O:
667                     {
668                     // Address/offset width, which is *not* what's encoded by the optype...
669                     // The deref's width is what's actually encoded here.
670                         int pseudoOpType;
671                         switch(locs->address_size)
672                         {
673                             case 1:
674                                 pseudoOpType = op_b;
675                                 break;
676                             case 2:
677                                 pseudoOpType = op_w;
678                                 break;
679                             case 4:
680                                 pseudoOpType = op_d;
681                                 break;
682                             case 0:
683                                 // closest I can get to "will be address size by default"
684                                 pseudoOpType = op_v;
685                                 break;
686                             default:
687                                 assert(!"Bad address size, should be 0, 1, 2, or 4!");
688                                 pseudoOpType = op_b;
689                                 break;
690                         }
691
692
693                         int offset_position = locs->opcode_position;
694                         if(locs->modrm_position > offset_position && locs->modrm_operand <
695                            (int)(insn_to_complete->m_Operands.size()))
696                         {
697                             offset_position = locs->modrm_position;
698                         }
699                         if(locs->sib_position > offset_position)
700                         {
701                             offset_position = locs->sib_position;
702                         }
703                         offset_position++;
704                         insn_to_complete->appendOperand(makeDereferenceExpression(
705                                 decodeImmediate(pseudoOpType, b.start + offset_position), makeSizeType(optype)), 
706                                                         isRead, isWritten);
707                     }
708                     break;
709                     case am_P:
710                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_mm][locs->modrm_reg]),
711                                 isRead, isWritten);
712                         break;
713                     case am_Q:
714         
715                         switch(locs->modrm_mod)
716                         {
717                             // direct dereference
718                             case 0x00:
719                             case 0x01:
720                             case 0x02:
721                               insn_to_complete->appendOperand(makeModRMExpression(b, optype), isRead, isWritten);
722                                 break;
723                             case 0x03:
724                                 // use of actual register
725                                 insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_mm][locs->modrm_rm]),
726                                                                isRead, isWritten);
727                                 break;
728                             default:
729                                 assert(!"2-bit value modrm_mod out of range");
730                                 break;
731                         };
732                         break;
733                     case am_S:
734                     // Segment register in modrm reg field.
735                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_segment][locs->modrm_reg]),
736                                 isRead, isWritten);
737                         break;
738                     case am_T:
739                         // test register in modrm reg; should only be tr6/tr7, but we'll decode any of them
740                         // NOTE: this only appears in deprecated opcodes
741                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_tr][locs->modrm_reg]),
742                                                        isRead, isWritten);
743                         break;
744                     case am_V:
745                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_xmm][locs->modrm_reg]),
746                                                        isRead, isWritten);
747                         break;
748                     case am_W:
749                         switch(locs->modrm_mod)
750                         {
751                             // direct dereference
752                             case 0x00:
753                             case 0x01:
754                             case 0x02:
755                               insn_to_complete->appendOperand(makeModRMExpression(b, makeSizeType(optype)),
756                                                                isRead, isWritten);
757                                 break;
758                             case 0x03:
759                             // use of actual register
760                             {
761                                 insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_xmm][locs->modrm_rm]),
762                                                                isRead, isWritten);
763                                 break;
764                             }
765                             default:
766                                 assert(!"2-bit value modrm_mod out of range");
767                                 break;
768                         };
769                         break;
770                     case am_X:
771                     {
772                         Expression::Ptr ds(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ds : x86_64::ds));
773                         Expression::Ptr si(makeRegisterExpression(m_Arch == Arch_x86 ? x86::si : x86_64::si));
774                         Expression::Ptr segmentOffset(make_shared(singleton_object_pool<Immediate>::construct(
775                                 Result(u32, 0x10))));
776                         Expression::Ptr ds_segment = makeMultiplyExpression(ds, segmentOffset, u32);
777                         Expression::Ptr ds_si = makeAddExpression(ds_segment, si, u32);
778                         insn_to_complete->appendOperand(makeDereferenceExpression(ds_si, makeSizeType(optype)),
779                                                        isRead, isWritten);
780                     }
781                     break;
782                     case am_Y:
783                     {
784                         Expression::Ptr es(makeRegisterExpression(m_Arch == Arch_x86 ? x86::es : x86_64::es));
785                         Expression::Ptr di(makeRegisterExpression(m_Arch == Arch_x86 ? x86::di : x86_64::di));
786                         Expression::Ptr es_segment = makeMultiplyExpression(es,
787                             make_shared(singleton_object_pool<Immediate>::construct(Result(u32, 0x10))), u32);
788                         Expression::Ptr es_di = makeAddExpression(es_segment, di, u32);
789                         insn_to_complete->appendOperand(makeDereferenceExpression(es_di, makeSizeType(optype)),
790                                                        isRead, isWritten);
791                     }
792                     break;
793                     case am_tworeghack:
794                     {
795                         if(optype == r_EDXEAX)
796                         {
797                             Expression::Ptr edx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::edx : x86_64::edx));
798                             Expression::Ptr eax(makeRegisterExpression(m_Arch == Arch_x86 ? x86::eax : x86_64::eax));
799                             Expression::Ptr highAddr = makeMultiplyExpression(edx,
800                                     Immediate::makeImmediate(Result(u64, 2^32)), u64);
801                             Expression::Ptr addr = makeAddExpression(highAddr, eax, u64);
802                             Expression::Ptr op = makeDereferenceExpression(addr, u64);
803                             insn_to_complete->appendOperand(op, isRead, isWritten);
804                         }
805                         else if (optype == r_ECXEBX)
806                         {
807                             Expression::Ptr ecx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ecx : x86_64::ecx));
808                             Expression::Ptr ebx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ebx : x86_64::ebx));
809                             Expression::Ptr highAddr = makeMultiplyExpression(ecx,
810                                     Immediate::makeImmediate(Result(u64, 2^32)), u64);
811                             Expression::Ptr addr = makeAddExpression(highAddr, ebx, u64);
812                             Expression::Ptr op = makeDereferenceExpression(addr, u64);
813                             insn_to_complete->appendOperand(op, isRead, isWritten);
814                         }
815                     }
816                     break;
817                     
818                     case am_reg:
819                     {
820                         MachRegister r(optype);
821                         r = MachRegister(r.val() & ~r.getArchitecture() | m_Arch);
822                         if(locs->rex_b)
823                         {
824                             r = MachRegister((r.val()) | x86_64::r8.val());
825                         }
826                         if(sizePrefixPresent)
827                         {
828                             r = MachRegister((r.val() & ~x86::FULL) | x86::W_REG);
829                         }
830                         Expression::Ptr op(makeRegisterExpression(r));
831                         insn_to_complete->appendOperand(op, isRead, isWritten);
832                     }
833                     break;
834                 case am_stackH:
835                 case am_stackP:
836                 // handled elsewhere
837                     break;
838                 case am_allgprs:
839                 {
840                     if(m_Arch == Arch_x86)
841                     {
842                         insn_to_complete->appendOperand(makeRegisterExpression(x86::eax), isRead, isWritten);
843                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ecx), isRead, isWritten);
844                         insn_to_complete->appendOperand(makeRegisterExpression(x86::edx), isRead, isWritten);
845                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ebx), isRead, isWritten);
846                         insn_to_complete->appendOperand(makeRegisterExpression(x86::esp), isRead, isWritten);
847                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ebp), isRead, isWritten);
848                         insn_to_complete->appendOperand(makeRegisterExpression(x86::esi), isRead, isWritten);
849                         insn_to_complete->appendOperand(makeRegisterExpression(x86::edi), isRead, isWritten);
850                     }
851                     else
852                     {
853                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::eax), isRead, isWritten);
854                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ecx), isRead, isWritten);
855                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::edx), isRead, isWritten);
856                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ebx), isRead, isWritten);
857                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::esp), isRead, isWritten);
858                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ebp), isRead, isWritten);
859                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::esi), isRead, isWritten);
860                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::edi), isRead, isWritten);
861                     }
862                 }
863                     break;
864                 case am_ImplImm: {
865                   insn_to_complete->appendOperand(Immediate::makeImmediate(Result(makeSizeType(optype), 1)), isRead, isWritten);
866                   break;
867                 }
868
869                 default:
870                     printf("decodeOneOperand() called with unknown addressing method %d\n", operand.admet);
871                         break;
872                 };
873                 return true;
874             }
875
876     extern ia32_entry invalid;
877     
878     void InstructionDecoder_x86::doIA32Decode(InstructionDecoder::buffer& b)
879     {
880         if(decodedInstruction == NULL)
881         {
882             decodedInstruction = reinterpret_cast<ia32_instruction*>(malloc(sizeof(ia32_instruction)));
883             assert(decodedInstruction);
884         }
885         if(locs == NULL)
886         {
887             locs = reinterpret_cast<ia32_locations*>(malloc(sizeof(ia32_locations)));
888             assert(locs);
889         }
890         locs = new(locs) ia32_locations; //reinit();
891         assert(locs->sib_position == -1);
892         decodedInstruction = new (decodedInstruction) ia32_instruction(NULL, NULL, locs);
893         ia32_decode(IA32_DECODE_PREFIXES, b.start, *decodedInstruction);
894         sizePrefixPresent = (decodedInstruction->getPrefix()->getOperSzPrefix() == 0x66);
895         addrSizePrefixPresent = (decodedInstruction->getPrefix()->getAddrSzPrefix() == 0x67);
896     }
897     
898     void InstructionDecoder_x86::decodeOpcode(InstructionDecoder::buffer& b)
899     {
900         static ia32_entry invalid = { e_No_Entry, 0, 0, true, { {0,0}, {0,0}, {0,0} }, 0, 0 };
901         doIA32Decode(b);
902         if(decodedInstruction->getEntry()) {
903             m_Operation = make_shared(singleton_object_pool<Operation>::construct(decodedInstruction->getEntry(),
904                                     decodedInstruction->getPrefix(), locs, m_Arch));
905         }
906         else
907         {
908                 // Gap parsing can trigger this case; in particular, when it encounters prefixes in an invalid order.
909                 // Notably, if a REX prefix (0x40-0x48) appears followed by another prefix (0x66, 0x67, etc)
910                 // we'll reject the instruction as invalid and send it back with no entry.  Since this is a common
911                 // byte sequence to see in, for example, ASCII strings, we want to simply accept this and move on, not
912                 // yell at the user.
913             m_Operation = make_shared(singleton_object_pool<Operation>::construct(&invalid,
914                                     decodedInstruction->getPrefix(), locs, m_Arch));
915         }
916         b.start += decodedInstruction->getSize();
917     }
918     
919       bool InstructionDecoder_x86::decodeOperands(const Instruction* insn_to_complete)
920     {
921         int imm_index = 0; // handle multiple immediate operands
922         if(!decodedInstruction) return false;
923         unsigned int opsema = decodedInstruction->getEntry()->opsema & 0xFF;
924         InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
925         
926         for(unsigned i = 0; i < 3; i++)
927         {
928             if(decodedInstruction->getEntry()->operands[i].admet == 0 && 
929                decodedInstruction->getEntry()->operands[i].optype == 0)
930                 return true;
931             if(!decodeOneOperand(b,
932                                  decodedInstruction->getEntry()->operands[i], 
933                                  imm_index, 
934                                  insn_to_complete, 
935                                  readsOperand(opsema, i),
936                                  writesOperand(opsema, i)))
937             {
938                 return false;
939             }
940         }
941     
942         return true;
943     }
944
945     
946       INSTRUCTION_EXPORT Instruction::Ptr InstructionDecoder_x86::decode(InstructionDecoder::buffer& b)
947     {
948         return InstructionDecoderImpl::decode(b);
949     }
950     void InstructionDecoder_x86::doDelayedDecode(const Instruction* insn_to_complete)
951     {
952       InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
953       //insn_to_complete->m_Operands.reserve(4);
954       doIA32Decode(b);        
955       decodeOperands(insn_to_complete);
956     }
957     
958 };
959 };
960