IAPI: Fix address size interpretation of SI/DI regs
[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 "Expression.h"
36 #include "arch-x86.h"
37 #include "Register.h"
38 #include "Dereference.h"
39 #include "Immediate.h"
40 #include "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 && !addrSizePrefixPresent)
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(locs->modrm_rm == 0x6 && addrSizePrefixPresent)
236                 {
237                     e = getModRMDisplacement(b);
238                 }
239                 if(opType == op_lea)
240                 {
241                     return e;
242                 }
243                 return makeDereferenceExpression(e, makeSizeType(opType));
244             case 1:
245             case 2:
246             {
247                 if(locs->modrm_rm == modrm_use_sib) {
248                     e = makeSIBExpression(b);
249                 }
250                 Expression::Ptr disp_e = makeAddExpression(e, getModRMDisplacement(b), aw);
251                 if(opType == op_lea)
252                 {
253                     return disp_e;
254                 }
255                 return makeDereferenceExpression(disp_e, makeSizeType(opType));
256             }
257             case 3:
258               return makeRegisterExpression(makeRegisterID(locs->modrm_rm, opType, (locs->rex_b == 1)));
259             default:
260                 return Expression::Ptr();
261         
262         };
263         
264     }
265
266     Expression::Ptr InstructionDecoder_x86::decodeImmediate(unsigned int opType, const unsigned char* immStart, 
267                                                             bool isSigned)
268     {
269         switch(opType)
270         {
271             case op_b:
272                 return Immediate::makeImmediate(Result(isSigned ? s8 : u8 ,*(const byte_t*)(immStart)));
273                 break;
274             case op_d:
275                 return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
276             case op_w:
277                 return Immediate::makeImmediate(Result(isSigned ? s16 : u16,*(const word_t*)(immStart)));
278                 break;
279             case op_q:
280                 return Immediate::makeImmediate(Result(isSigned ? s64 : u64,*(const int64_t*)(immStart)));
281                 break;
282             case op_v:
283             case op_z:
284         // 32 bit mode & no prefix, or 16 bit mode & prefix => 32 bit
285         // 16 bit mode, no prefix or 32 bit mode, prefix => 16 bit
286                 if(!sizePrefixPresent)
287                 {
288                     return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
289                 }
290                 else
291                 {
292                     return Immediate::makeImmediate(Result(isSigned ? s16 : u16,*(const word_t*)(immStart)));
293                 }
294         
295                 break;
296             case op_p:
297         // 32 bit mode & no prefix, or 16 bit mode & prefix => 48 bit
298         // 16 bit mode, no prefix or 32 bit mode, prefix => 32 bit
299                 if(!sizePrefixPresent)
300                 {
301                     return Immediate::makeImmediate(Result(isSigned ? s48 : u48,*(const int64_t*)(immStart)));
302                 }
303                 else
304                 {
305                     return Immediate::makeImmediate(Result(isSigned ? s32 : u32,*(const dword_t*)(immStart)));
306                 }
307         
308                 break;
309             case op_a:
310             case op_dq:
311             case op_pd:
312             case op_ps:
313             case op_s:
314             case op_si:
315             case op_lea:
316             case op_allgprs:
317             case op_512:
318             case op_c:
319                 assert(!"Can't happen: opType unexpected for valid ways to decode an immediate");
320                 return Expression::Ptr();
321             default:
322                 assert(!"Can't happen: opType out of range");
323                 return Expression::Ptr();
324         }
325     }
326     
327     Expression::Ptr InstructionDecoder_x86::getModRMDisplacement(const InstructionDecoder::buffer& b)
328     {
329         int disp_pos;
330
331         if(locs->sib_position != -1)
332         {
333             disp_pos = locs->sib_position + 1;
334         }
335         else
336         {
337             disp_pos = locs->modrm_position + 1;
338         }
339         switch(locs->modrm_mod)
340         {
341             case 1:
342                 return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, (*(const byte_t*)(b.start +
343                         disp_pos)))));
344                 break;
345             case 2:
346                 if(sizePrefixPresent)
347                 {
348                     return make_shared(singleton_object_pool<Immediate>::construct(Result(s16, *((const word_t*)(b.start +
349                             disp_pos)))));
350                 }
351                 else
352                 {
353                     return make_shared(singleton_object_pool<Immediate>::construct(Result(s32, *((const dword_t*)(b.start +
354                             disp_pos)))));
355                 }
356                 break;
357             case 0:
358                 // In 16-bit mode, the word displacement is modrm r/m 6
359                 if(sizePrefixPresent)
360                 {
361                     if(locs->modrm_rm == 6)
362                     {
363                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s16,
364                                            *((const dword_t*)(b.start + disp_pos)))));
365                     }
366                     else
367                     {
368                         assert(b.start + disp_pos + 1 <= b.end);
369                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
370                     }
371                     break;
372                 }
373                 // ...and in 32-bit mode, the dword displacement is modrm r/m 5
374                 else
375                 {
376                     if(locs->modrm_rm == 5)
377                     {
378                         assert(b.start + disp_pos + 4 <= b.end);
379                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s32,
380                                            *((const dword_t*)(b.start + disp_pos)))));
381                     }
382                     else
383                     {
384                         assert(b.start + disp_pos + 1 <= b.end);
385                         return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
386                     }
387                     break;
388                 }
389             default:
390                 assert(b.start + disp_pos + 1 <= b.end);
391                 return make_shared(singleton_object_pool<Immediate>::construct(Result(s8, 0)));
392                 break;
393         }
394     }
395
396     enum intelRegBanks
397     {
398         b_8bitNoREX = 0,
399         b_16bit,
400         b_32bit,
401         b_segment,
402         b_64bit,
403         b_xmm,
404         b_mm,
405         b_cr,
406         b_dr,
407         b_tr,
408         b_amd64ext,
409         b_8bitWithREX
410     };
411     using namespace x86;
412     
413     static MachRegister IntelRegTable[][8] = {
414         {
415             al, cl, dl, bl, ah, ch, dh, bh
416         },
417         {
418             ax, cx, dx, bx, sp, bp, si, di
419         },
420         {
421             eax, ecx, edx, ebx, esp, ebp, esi, edi
422         },
423         {
424             es, cs, ss, ds, fs, gs, InvalidReg, InvalidReg
425         },
426         {
427             x86_64::rax, x86_64::rcx, x86_64::rdx, x86_64::rbx, x86_64::rsp, x86_64::rbp, x86_64::rsi, x86_64::rdi
428         },
429         {
430             xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
431         },
432         {
433             mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7
434         },
435         {
436             cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7
437         },
438         {
439             dr0, dr1, dr2, dr3, dr4, dr5, dr6, dr7
440         },
441         {
442             tr0, tr1, tr2, tr3, tr4, tr5, tr6, tr7
443         },
444         {
445             x86_64::r8, x86_64::r9, x86_64::r10, x86_64::r11, x86_64::r12, x86_64::r13, x86_64::r14, x86_64::r15
446         },
447         {
448             x86_64::al, x86_64::cl, x86_64::dl, x86_64::bl, x86_64::spl, x86_64::bpl, x86_64::sil, x86_64::dil
449         }
450
451     };
452
453     MachRegister InstructionDecoder_x86::makeRegisterID(unsigned int intelReg, unsigned int opType,
454                                         bool isExtendedReg)
455     {
456         MachRegister retVal;
457         if(isExtendedReg)
458         {
459             retVal = IntelRegTable[b_amd64ext][intelReg];
460         }
461         else if(locs->rex_w)
462         {
463             // AMD64 with 64-bit operands
464             retVal = IntelRegTable[b_64bit][intelReg];
465         }
466         else
467         {
468             switch(opType)
469             {
470                 case op_b:
471                     if (locs->rex_position == -1) {
472                         retVal = IntelRegTable[b_8bitNoREX][intelReg];
473                     } else {
474                         retVal = IntelRegTable[b_8bitWithREX][intelReg];
475                     }
476                     break;
477                 case op_q:
478                     retVal = IntelRegTable[b_64bit][intelReg];
479                     break;
480                 case op_w:
481                   retVal = IntelRegTable[b_16bit][intelReg];
482                   break;
483                 case op_d:
484                 case op_si:
485                 default:
486                     retVal = IntelRegTable[b_32bit][intelReg];
487                     break;
488                   
489             }
490         }
491         if (!ia32_is_mode_64()) {
492           if ((retVal.val() & 0x00ffffff) == 0x0001000c)
493             assert(0);
494         }
495
496         return MachRegister((retVal.val() & ~retVal.getArchitecture()) | m_Arch);
497     }
498     
499     Result_Type InstructionDecoder_x86::makeSizeType(unsigned int opType)
500     {
501         switch(opType)
502         {
503             case op_b:
504             case op_c:
505                 return u8;
506             case op_d:
507             case op_ss:
508             case op_allgprs:
509             case op_si:
510                 return u32;
511             case op_w:
512             case op_a:
513                 return u16;
514             case op_q:
515             case op_sd:
516                 return u64;
517             case op_v:
518             case op_lea:
519             case op_z:
520                 if(is32BitMode ^ sizePrefixPresent)
521                 {
522                     return u32;
523                 }
524                 else
525                 {
526                     return u16;
527                 }
528                 break;
529             case op_p:
530                 // book says operand size; arch-x86 says word + word * operand size
531                 if(is32BitMode ^ sizePrefixPresent)
532                 {
533                     return u48;
534                 }
535                 else
536                 {
537                     return u32;
538                 }
539             case op_dq:
540                 return u64;
541             case op_512:
542                 return m512;
543             case op_pi:
544             case op_ps:
545             case op_pd:
546                 return dbl128;
547             case op_s:
548                 return u48;
549             case op_f:
550                 return sp_float;
551             case op_dbl:
552                 return dp_float;
553             case op_14:
554                 return m14;
555             default:
556                 assert(!"Can't happen!");
557                 return u8;
558         }
559     }
560
561
562     bool InstructionDecoder_x86::decodeOneOperand(const InstructionDecoder::buffer& b,
563                                                   const ia32_operand& operand,
564                                                   int & imm_index, /* immediate operand index */
565                                                   const Instruction* insn_to_complete, 
566                                                   bool isRead, bool isWritten)
567     {
568       unsigned int regType = op_d;
569       if(ia32_is_mode_64())
570         {
571           regType = op_q;
572         }
573       bool isCFT = false;
574       bool isCall = false;
575       bool isConditional = false;
576       InsnCategory cat = insn_to_complete->getCategory();
577       if(cat == c_BranchInsn || cat == c_CallInsn)
578         {
579           isCFT = true;
580           if(cat == c_CallInsn)
581             {
582               isCall = true;
583             }
584         }
585       if (cat == c_BranchInsn && insn_to_complete->getOperation().getID() != e_jmp) {
586         isConditional = true;
587       }
588
589       unsigned int optype = operand.optype;
590       if (sizePrefixPresent && 
591           ((optype == op_v) ||
592            (optype == op_z))) {
593         optype = op_w;
594       }
595                 switch(operand.admet)
596                 {
597                     case 0:
598                     // No operand
599                     {
600 /*                        fprintf(stderr, "ERROR: Instruction with mismatched operands. Raw bytes: ");
601                         for(unsigned int i = 0; i < decodedInstruction->getSize(); i++) {
602                             fprintf(stderr, "%x ", b.start[i]);
603                         }
604                         fprintf(stderr, "\n");*/
605                         assert(!"Mismatched number of operands--check tables");
606                         return false;
607                     }
608                     case am_A:
609                     {
610                         // am_A only shows up as a far call/jump.  Position 1 should be universally safe.
611                         Expression::Ptr addr(decodeImmediate(optype, b.start + 1));
612                         Expression::Ptr op(makeDereferenceExpression(addr, makeSizeType(optype)));
613                         insn_to_complete->addSuccessor(op, isCall, false, false, false);
614                     }
615                     break;
616                     case am_C:
617                     {
618                         Expression::Ptr op(makeRegisterExpression(IntelRegTable[b_cr][locs->modrm_reg]));
619                         insn_to_complete->appendOperand(op, isRead, isWritten);
620                     }
621                     break;
622                     case am_D:
623                     {
624                         Expression::Ptr op(makeRegisterExpression(IntelRegTable[b_dr][locs->modrm_reg]));
625                         insn_to_complete->appendOperand(op, isRead, isWritten);
626                     }
627                     break;
628                     case am_E:
629                     // am_M is like am_E, except that mod of 0x03 should never occur (am_M specified memory,
630                     // mod of 0x03 specifies direct register access).
631                     case am_M:
632                     // am_R is the inverse of am_M; it should only have a mod of 3
633                     case am_R:
634                         if(isCFT)
635                         {
636                           insn_to_complete->addSuccessor(makeModRMExpression(b, optype), isCall, true, false, false);
637                         }
638                         else
639                         {
640                           insn_to_complete->appendOperand(makeModRMExpression(b, optype), isRead, isWritten);
641                         }
642                     break;
643                     case am_F:
644                     {
645                         Expression::Ptr op(makeRegisterExpression(flags));
646                         insn_to_complete->appendOperand(op, isRead, isWritten);
647                     }
648                     break;
649                     case am_G:
650                     {
651                         Expression::Ptr op(makeRegisterExpression(makeRegisterID(locs->modrm_reg,
652                                 optype, locs->rex_r)));
653                         insn_to_complete->appendOperand(op, isRead, isWritten);
654                     }
655                     break;
656                     case am_I:
657                         insn_to_complete->appendOperand(decodeImmediate(optype, b.start + 
658                                                                         locs->imm_position[imm_index++]), 
659                                                         isRead, isWritten);
660                         break;
661                     case am_J:
662                     {
663                         Expression::Ptr Offset(decodeImmediate(optype, 
664                                                                b.start + locs->imm_position[imm_index++], 
665                                                                true));
666                         Expression::Ptr EIP(makeRegisterExpression(MachRegister::getPC(m_Arch)));
667                         Expression::Ptr InsnSize(make_shared(singleton_object_pool<Immediate>::construct(Result(u8,
668                             decodedInstruction->getSize()))));
669                         Expression::Ptr postEIP(makeAddExpression(EIP, InsnSize, u32));
670
671                         Expression::Ptr op(makeAddExpression(Offset, postEIP, u32));
672                         insn_to_complete->addSuccessor(op, isCall, false, isConditional, false);
673                         if (isConditional) 
674                           insn_to_complete->addSuccessor(postEIP, false, false, true, true);
675                     }
676                     break;
677                     case am_O:
678                     {
679                     // Address/offset width, which is *not* what's encoded by the optype...
680                     // The deref's width is what's actually encoded here.
681                         int pseudoOpType;
682                         switch(locs->address_size)
683                         {
684                             case 1:
685                                 pseudoOpType = op_b;
686                                 break;
687                             case 2:
688                                 pseudoOpType = op_w;
689                                 break;
690                             case 4:
691                                 pseudoOpType = op_d;
692                                 break;
693                             case 0:
694                                 // closest I can get to "will be address size by default"
695                                 pseudoOpType = op_v;
696                                 break;
697                             default:
698                                 assert(!"Bad address size, should be 0, 1, 2, or 4!");
699                                 pseudoOpType = op_b;
700                                 break;
701                         }
702
703
704                         int offset_position = locs->opcode_position;
705                         if(locs->modrm_position > offset_position && locs->modrm_operand <
706                            (int)(insn_to_complete->m_Operands.size()))
707                         {
708                             offset_position = locs->modrm_position;
709                         }
710                         if(locs->sib_position > offset_position)
711                         {
712                             offset_position = locs->sib_position;
713                         }
714                         offset_position++;
715                         insn_to_complete->appendOperand(makeDereferenceExpression(
716                                 decodeImmediate(pseudoOpType, b.start + offset_position), makeSizeType(optype)), 
717                                                         isRead, isWritten);
718                     }
719                     break;
720                     case am_P:
721                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_mm][locs->modrm_reg]),
722                                 isRead, isWritten);
723                         break;
724                     case am_Q:
725         
726                         switch(locs->modrm_mod)
727                         {
728                             // direct dereference
729                             case 0x00:
730                             case 0x01:
731                             case 0x02:
732                               insn_to_complete->appendOperand(makeModRMExpression(b, optype), isRead, isWritten);
733                                 break;
734                             case 0x03:
735                                 // use of actual register
736                                 insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_mm][locs->modrm_rm]),
737                                                                isRead, isWritten);
738                                 break;
739                             default:
740                                 assert(!"2-bit value modrm_mod out of range");
741                                 break;
742                         };
743                         break;
744                     case am_S:
745                     // Segment register in modrm reg field.
746                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_segment][locs->modrm_reg]),
747                                 isRead, isWritten);
748                         break;
749                     case am_T:
750                         // test register in modrm reg; should only be tr6/tr7, but we'll decode any of them
751                         // NOTE: this only appears in deprecated opcodes
752                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_tr][locs->modrm_reg]),
753                                                        isRead, isWritten);
754                         break;
755                     case am_V:
756                         insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_xmm][locs->modrm_reg]),
757                                                        isRead, isWritten);
758                         break;
759                     case am_W:
760                         switch(locs->modrm_mod)
761                         {
762                             // direct dereference
763                             case 0x00:
764                             case 0x01:
765                             case 0x02:
766                               insn_to_complete->appendOperand(makeModRMExpression(b, makeSizeType(optype)),
767                                                                isRead, isWritten);
768                                 break;
769                             case 0x03:
770                             // use of actual register
771                             {
772                                 insn_to_complete->appendOperand(makeRegisterExpression(IntelRegTable[b_xmm][locs->modrm_rm]),
773                                                                isRead, isWritten);
774                                 break;
775                             }
776                             default:
777                                 assert(!"2-bit value modrm_mod out of range");
778                                 break;
779                         };
780                         break;
781                     case am_X:
782                     {
783                         MachRegister si_reg;
784                         if(m_Arch == Arch_x86)
785                         {
786                                 if(addrSizePrefixPresent)
787                                 {
788                                         si_reg = x86::si;
789                                 } else
790                                 {
791                                         si_reg = x86::esi;
792                                 }
793                         }
794                         else
795                         {
796                                 if(addrSizePrefixPresent)
797                                 {
798                                         si_reg = x86_64::esi;
799                                 } else
800                                 {
801                                         si_reg = x86_64::rsi;
802                                 }
803                         }
804                         Expression::Ptr ds(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ds : x86_64::ds));
805                         Expression::Ptr si(makeRegisterExpression(si_reg));
806                         Expression::Ptr segmentOffset(make_shared(singleton_object_pool<Immediate>::construct(
807                                 Result(u32, 0x10))));
808                         Expression::Ptr ds_segment = makeMultiplyExpression(ds, segmentOffset, u32);
809                         Expression::Ptr ds_si = makeAddExpression(ds_segment, si, u32);
810                         insn_to_complete->appendOperand(makeDereferenceExpression(ds_si, makeSizeType(optype)),
811                                                        isRead, isWritten);
812                     }
813                     break;
814                     case am_Y:
815                     {
816                         MachRegister di_reg;
817                         if(m_Arch == Arch_x86)
818                         {
819                                 if(addrSizePrefixPresent)
820                                 {
821                                         di_reg = x86::di;
822                                 } else
823                                 {
824                                         di_reg = x86::edi;
825                                 }
826                         }
827                         else
828                         {
829                                 if(addrSizePrefixPresent)
830                                 {
831                                         di_reg = x86_64::edi;
832                                 } else
833                                 {
834                                         di_reg = x86_64::rdi;
835                                 }
836                         }
837                         Expression::Ptr es(makeRegisterExpression(m_Arch == Arch_x86 ? x86::es : x86_64::es));
838                         Expression::Ptr di(makeRegisterExpression(di_reg));
839                         Expression::Ptr es_segment = makeMultiplyExpression(es,
840                             make_shared(singleton_object_pool<Immediate>::construct(Result(u32, 0x10))), u32);
841                         Expression::Ptr es_di = makeAddExpression(es_segment, di, u32);
842                         insn_to_complete->appendOperand(makeDereferenceExpression(es_di, makeSizeType(optype)),
843                                                        isRead, isWritten);
844                     }
845                     break;
846                     case am_tworeghack:
847                     {
848                         if(optype == op_edxeax)
849                         {
850                             Expression::Ptr edx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::edx : x86_64::edx));
851                             Expression::Ptr eax(makeRegisterExpression(m_Arch == Arch_x86 ? x86::eax : x86_64::eax));
852                             Expression::Ptr highAddr = makeMultiplyExpression(edx,
853                                     Immediate::makeImmediate(Result(u64, 2^32)), u64);
854                             Expression::Ptr addr = makeAddExpression(highAddr, eax, u64);
855                             Expression::Ptr op = makeDereferenceExpression(addr, u64);
856                             insn_to_complete->appendOperand(op, isRead, isWritten);
857                         }
858                         else if (optype == op_ecxebx)
859                         {
860                             Expression::Ptr ecx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ecx : x86_64::ecx));
861                             Expression::Ptr ebx(makeRegisterExpression(m_Arch == Arch_x86 ? x86::ebx : x86_64::ebx));
862                             Expression::Ptr highAddr = makeMultiplyExpression(ecx,
863                                     Immediate::makeImmediate(Result(u64, 2^32)), u64);
864                             Expression::Ptr addr = makeAddExpression(highAddr, ebx, u64);
865                             Expression::Ptr op = makeDereferenceExpression(addr, u64);
866                             insn_to_complete->appendOperand(op, isRead, isWritten);
867                         }
868                     }
869                     break;
870                     
871                     case am_reg:
872                     {
873                         MachRegister r(optype);
874                         r = MachRegister(r.val() & ~r.getArchitecture() | m_Arch);
875                         if(locs->rex_b)
876                         {
877                             r = MachRegister((r.val()) | x86_64::r8.val());
878                         }
879                         if(sizePrefixPresent)
880                         {
881                             r = MachRegister((r.val() & ~x86::FULL) | x86::W_REG);
882                         }
883                         Expression::Ptr op(makeRegisterExpression(r));
884                         insn_to_complete->appendOperand(op, isRead, isWritten);
885                     }
886                     break;
887                 case am_stackH:
888                 case am_stackP:
889                 // handled elsewhere
890                     break;
891                 case am_allgprs:
892                 {
893                     if(m_Arch == Arch_x86)
894                     {
895                         insn_to_complete->appendOperand(makeRegisterExpression(x86::eax), isRead, isWritten);
896                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ecx), isRead, isWritten);
897                         insn_to_complete->appendOperand(makeRegisterExpression(x86::edx), isRead, isWritten);
898                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ebx), isRead, isWritten);
899                         insn_to_complete->appendOperand(makeRegisterExpression(x86::esp), isRead, isWritten);
900                         insn_to_complete->appendOperand(makeRegisterExpression(x86::ebp), isRead, isWritten);
901                         insn_to_complete->appendOperand(makeRegisterExpression(x86::esi), isRead, isWritten);
902                         insn_to_complete->appendOperand(makeRegisterExpression(x86::edi), isRead, isWritten);
903                     }
904                     else
905                     {
906                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::eax), isRead, isWritten);
907                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ecx), isRead, isWritten);
908                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::edx), isRead, isWritten);
909                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ebx), isRead, isWritten);
910                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::esp), isRead, isWritten);
911                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::ebp), isRead, isWritten);
912                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::esi), isRead, isWritten);
913                         insn_to_complete->appendOperand(makeRegisterExpression(x86_64::edi), isRead, isWritten);
914                     }
915                 }
916                     break;
917                 case am_ImplImm: {
918                   insn_to_complete->appendOperand(Immediate::makeImmediate(Result(makeSizeType(optype), 1)), isRead, isWritten);
919                   break;
920                 }
921
922                 default:
923                     printf("decodeOneOperand() called with unknown addressing method %d\n", operand.admet);
924                         break;
925                 };
926                 return true;
927             }
928
929     extern ia32_entry invalid;
930     
931     void InstructionDecoder_x86::doIA32Decode(InstructionDecoder::buffer& b)
932     {
933         if(decodedInstruction == NULL)
934         {
935             decodedInstruction = reinterpret_cast<ia32_instruction*>(malloc(sizeof(ia32_instruction)));
936             assert(decodedInstruction);
937         }
938         if(locs == NULL)
939         {
940             locs = reinterpret_cast<ia32_locations*>(malloc(sizeof(ia32_locations)));
941             assert(locs);
942         }
943         locs = new(locs) ia32_locations; //reinit();
944         assert(locs->sib_position == -1);
945         decodedInstruction = new (decodedInstruction) ia32_instruction(NULL, NULL, locs);
946         ia32_decode(IA32_DECODE_PREFIXES, b.start, *decodedInstruction);
947         sizePrefixPresent = (decodedInstruction->getPrefix()->getOperSzPrefix() == 0x66);
948         addrSizePrefixPresent = (decodedInstruction->getPrefix()->getAddrSzPrefix() == 0x67);
949     }
950     
951     void InstructionDecoder_x86::decodeOpcode(InstructionDecoder::buffer& b)
952     {
953         static ia32_entry invalid = { e_No_Entry, 0, 0, true, { {0,0}, {0,0}, {0,0} }, 0, 0 };
954         doIA32Decode(b);
955         if(decodedInstruction->getEntry()) {
956             m_Operation = make_shared(singleton_object_pool<Operation>::construct(decodedInstruction->getEntry(),
957                                     decodedInstruction->getPrefix(), locs, m_Arch));
958         }
959         else
960         {
961                 // Gap parsing can trigger this case; in particular, when it encounters prefixes in an invalid order.
962                 // Notably, if a REX prefix (0x40-0x48) appears followed by another prefix (0x66, 0x67, etc)
963                 // we'll reject the instruction as invalid and send it back with no entry.  Since this is a common
964                 // byte sequence to see in, for example, ASCII strings, we want to simply accept this and move on, not
965                 // yell at the user.
966             m_Operation = make_shared(singleton_object_pool<Operation>::construct(&invalid,
967                                     decodedInstruction->getPrefix(), locs, m_Arch));
968         }
969         b.start += decodedInstruction->getSize();
970     }
971     
972       bool InstructionDecoder_x86::decodeOperands(const Instruction* insn_to_complete)
973     {
974         int imm_index = 0; // handle multiple immediate operands
975         if(!decodedInstruction) return false;
976         unsigned int opsema = decodedInstruction->getEntry()->opsema & 0xFF;
977         InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
978         
979         for(unsigned i = 0; i < 3; i++)
980         {
981             if(decodedInstruction->getEntry()->operands[i].admet == 0 && 
982                decodedInstruction->getEntry()->operands[i].optype == 0)
983                 return true;
984             if(!decodeOneOperand(b,
985                                  decodedInstruction->getEntry()->operands[i], 
986                                  imm_index, 
987                                  insn_to_complete, 
988                                  readsOperand(opsema, i),
989                                  writesOperand(opsema, i)))
990             {
991                 return false;
992             }
993         }
994     
995         return true;
996     }
997
998     
999       INSTRUCTION_EXPORT Instruction::Ptr InstructionDecoder_x86::decode(InstructionDecoder::buffer& b)
1000     {
1001         return InstructionDecoderImpl::decode(b);
1002     }
1003     void InstructionDecoder_x86::doDelayedDecode(const Instruction* insn_to_complete)
1004     {
1005       InstructionDecoder::buffer b(insn_to_complete->ptr(), insn_to_complete->size());
1006       //insn_to_complete->m_Operands.reserve(4);
1007       doIA32Decode(b);        
1008       decodeOperands(insn_to_complete);
1009     }
1010     
1011 };
1012 };
1013