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