Inital version of the rewritten IA-32 decoder added
[dyninst.git] / dyninstAPI / src / arch-ia32.h
1 // $Id: arch-ia32.h,v 1.1 2002/06/06 18:25:17 gaburici Exp $
2 // VG(02/06/2002): configurable IA-32 decoder
3
4 #if !(defined(i386_unknown_linux2_0))
5 #error "invalid architecture-os inclusion"
6 #endif
7
8 #ifndef _ARCH_IA32_H
9 #define _ARCH_IA32_H
10
11 #include <stdlib.h>
12 #include "arch-x86.h"
13
14
15 #define PREFIX_LOCK   0xF0
16 #define PREFIX_REPNZ  0xF2
17 #define PREFIX_REP    0xF3
18
19 #define PREFIX_SEGCS  0x2E
20 #define PREFIX_SEGSS  0x36
21 #define PREFIX_SEGDS  0x3E
22 #define PREFIX_SEGES  0x26
23 #define PREFIX_SEGFS  0x64
24 #define PREFIX_SEGGS  0x65
25
26 #define PREFIX_BRANCH0 0x2E
27 #define PREFIX_BRANCH1 0x3E
28
29 #define PREFIX_SZOPER  0x66
30 #define PREFIX_SZADDR  0x67
31
32
33 class ia32_prefixes
34 {
35   friend ia32_prefixes& ia32_decode_prefixes(const unsigned char* addr, ia32_prefixes&);
36  private:
37   unsigned int count;
38   // At most 4 prefixes are allowed for Intel 32-bit CPUs
39   // There also 4 groups, so this array is 0 if no prefix
40   // from that group is present, otherwise it contains the
41   // prefix opcode
42   unsigned char prfx[4];
43  public:
44   unsigned int const getCount() const { return count; }
45   unsigned char getPrefix(unsigned char group) const { return prfx[group]; }
46 };
47
48
49 ia32_prefixes& ia32_decode_prefixes(const unsigned char* addr, ia32_prefixes&);
50
51
52 class ia32_entry;
53
54 class ia32_instruction {
55   friend unsigned int ia32_decode_operands (const ia32_prefixes& pref, const ia32_entry& gotit, 
56                                             const char* addr, ia32_instruction& instruct);
57   template <unsigned int capa>
58     friend ia32_instruction& ia32_decode(const unsigned char* addr, ia32_instruction& instruct);
59   friend unsigned int ia32_decode_operands (const ia32_prefixes& pref, const ia32_entry& gotit, 
60                                      const unsigned char* addr, ia32_instruction& instruct);
61   friend ia32_instruction& ia32_decode_FP(const ia32_prefixes& pref, const unsigned char* addr,
62                                           ia32_instruction& instruct);
63   friend unsigned int ia32_emulate_old_type(ia32_instruction& instruct);
64   // these are primary attributes
65   unsigned int size;
66   ia32_prefixes prf;
67   unsigned int legacy_type;
68   // these are derived attributes
69
70   
71
72 /*   unsigned type() const { return 0; } */
73 /*   const unsigned char *ptr() const { return NULL; } */
74 /*   bool isCall() const { return true; } */
75 /*   bool isReturn() const { return true; } */
76 /*   Address getTarget(Address addr) const { return 0; } */
77
78 /*   ia32_instruction(): type_(0), size_(0), ptr_(0) {} */
79
80 /*   ia32_instruction(const unsigned char *p, unsigned type, unsigned sz): */
81 /*     type_(type), size_(sz), ptr_(p) {} */
82
83 /*   ia32_instruction(const ia32_instruction &insn) { */
84 /*     type_ = insn.type_; */
85 /*     size_ = insn.size_; */
86 /*     ptr_ = insn.ptr_; */
87 /*   } */
88
89 /*   unsigned getNextInstruction(const unsigned char *p) { */
90 /*     ptr_ = p; */
91 /*     size_ = get_instruction(ptr_, type_); */
92 /*     return size_; */
93 /*   } */
94
95 /*   // if the instruction is a jump or call, return the target, else return zero */
96 /*   Address getTarget(Address addr) const {  */
97 /*     return (Address)get_target(ptr_, type_, size_, addr);  */
98 /*   } */
99
100 /*   // return the size of the instruction in bytes */
101     public:
102   unsigned int getSize() const { return size; }
103   unsigned int getLegacyType() const { return legacy_type; }
104
105 /*   // return the type of the instruction */
106 /*   unsigned type() const { return type_; } */
107
108 /*   // return a pointer to the instruction */
109 /*   const unsigned char *ptr() const { return ptr_; } */
110
111 /*   bool isCall() const { return type_ & IS_CALL; } */
112 /*   bool isCallIndir() const { return (type_ & IS_CALL) && (type_ & INDIR); } */
113 /*   bool isReturn() const { return (type_ & IS_RET) || (type_ & IS_RETF); } */
114 /*   bool isRetFar() const { return type_ & IS_RETF; } */
115 /*   bool isJumpIndir() const { return (type_ & IS_JUMP) && (type_ & INDIR); } */
116 /*   bool isJumpDir() const */
117 /*     { return ~(type_ & INDIR) && ((type_ & IS_JUMP) || (type_ & IS_JCC)); } */
118 /*   bool isNop() const { return *ptr_ == 0x90; } */
119 /*   bool isIndir() const { return type_ & INDIR; } */
120 /*   bool isIllegal() const { return type_ & ILLEGAL; } */
121
122 /*  private: */
123 /*   unsigned type_;   // type of the instruction (e.g. IS_CALL | INDIR) */
124 /*   unsigned size_;   // size in bytes */
125 /*   const unsigned char *ptr_;       // pointer to the instruction */
126   
127 };
128
129 // VG(02/07/2002): Information that the decoder can return is
130 //   #defined below. The decoder always returns the size of the 
131 //   instruction because that has to be determined anyway.
132 //   Please don't add things that should be external to the
133 //   decoder, e.g.: how may bytes a relocated instruction needs
134 //   IMHO that stuff should go into inst-x86...
135
136 #define IA32_DECODE_PREFIXES    (1<<0)
137 #define IA32_DECODE_MNEMONICS   (1<<1)
138 #define IA32_DECODE_OPERANDS    (1<<2)
139 #define IA32_DECODE_JMPS        (1<<3)
140 #define IA32_DECODE_MOVS        (1<<4)
141 #define IA32_DECODE_CONDITIONS  (1<<5)
142
143 #define IA32_FULL_DECODER 0xffffffffffffffffu
144 #define IA32_SIZE_DECODER 0
145
146 template <unsigned int capabilities>
147 ia32_instruction& ia32_decode(const unsigned char* addr, ia32_instruction&);
148
149 //ia32_instruction& ia32_decode_size(const unsigned char* addr, ia32_instruction&);
150
151 // If typing the template every time is a pain, the following should help:
152 #define ia32_decode_all  ia32_decode<IA32_FULL_DECODER>
153 #define ia32_decode_size ia32_decode<IA32_SIZE_DECODER>
154 #define ia32_size(a,i)   ia32_decode_size((a),(i)).size
155
156 #endif