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