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