1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// Several simple types used by the disassembler and some of the patching
6// mechanisms.
7
8#ifndef SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__
9#define SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__
10
11namespace sidestep {
12
13// Categories of instructions that we care about
14enum InstructionType {
15  // This opcode is not used
16  IT_UNUSED,
17  // This disassembler does not recognize this opcode (error)
18  IT_UNKNOWN,
19  // This is not an instruction but a reference to another table
20  IT_REFERENCE,
21  // This byte is a prefix byte that we can ignore
22  IT_PREFIX,
23  // This is a prefix byte that switches to the nondefault address size
24  IT_PREFIX_ADDRESS,
25  // This is a prefix byte that switches to the nondefault operand size
26  IT_PREFIX_OPERAND,
27  // A jump or call instruction
28  IT_JUMP,
29  // A return instruction
30  IT_RETURN,
31  // Any other type of instruction (in this case we don't care what it is)
32  IT_GENERIC,
33};
34
35// Lists IA-32 operand sizes in multiples of 8 bits
36enum OperandSize {
37  OS_ZERO = 0,
38  OS_BYTE = 1,
39  OS_WORD = 2,
40  OS_DOUBLE_WORD = 4,
41  OS_QUAD_WORD = 8,
42  OS_DOUBLE_QUAD_WORD = 16,
43  OS_32_BIT_POINTER = 32/8,
44  OS_48_BIT_POINTER = 48/8,
45  OS_SINGLE_PRECISION_FLOATING = 32/8,
46  OS_DOUBLE_PRECISION_FLOATING = 64/8,
47  OS_DOUBLE_EXTENDED_PRECISION_FLOATING = 80/8,
48  OS_128_BIT_PACKED_SINGLE_PRECISION_FLOATING = 128/8,
49  OS_PSEUDO_DESCRIPTOR = 6
50};
51
52// Operand addressing methods from the IA-32 manual.  The enAmMask value
53// is a mask for the rest.  The other enumeration values are named for the
54// names given to the addressing methods in the manual, e.g. enAm_D is for
55// the D addressing method.
56//
57// The reason we use a full 4 bytes and a mask, is that we need to combine
58// these flags with the enOperandType to store the details
59// on the operand in a single integer.
60enum AddressingMethod {
61  AM_NOT_USED = 0,        // This operand is not used for this instruction
62  AM_MASK = 0x00FF0000,  // Mask for the rest of the values in this enumeration
63  AM_A = 0x00010000,    // A addressing type
64  AM_C = 0x00020000,    // C addressing type
65  AM_D = 0x00030000,    // D addressing type
66  AM_E = 0x00040000,    // E addressing type
67  AM_F = 0x00050000,    // F addressing type
68  AM_G = 0x00060000,    // G addressing type
69  AM_I = 0x00070000,    // I addressing type
70  AM_J = 0x00080000,    // J addressing type
71  AM_M = 0x00090000,    // M addressing type
72  AM_O = 0x000A0000,    // O addressing type
73  AM_P = 0x000B0000,    // P addressing type
74  AM_Q = 0x000C0000,    // Q addressing type
75  AM_R = 0x000D0000,    // R addressing type
76  AM_S = 0x000E0000,    // S addressing type
77  AM_T = 0x000F0000,    // T addressing type
78  AM_V = 0x00100000,    // V addressing type
79  AM_W = 0x00110000,    // W addressing type
80  AM_X = 0x00120000,    // X addressing type
81  AM_Y = 0x00130000,    // Y addressing type
82  AM_REGISTER = 0x00140000,  // Specific register is always used as this op
83  AM_IMPLICIT = 0x00150000,  // An implicit, fixed value is used
84};
85
86// Operand types from the IA-32 manual. The enOtMask value is
87// a mask for the rest. The rest of the values are named for the
88// names given to these operand types in the manual, e.g. enOt_ps
89// is for the ps operand type in the manual.
90//
91// The reason we use a full 4 bytes and a mask, is that we need
92// to combine these flags with the enAddressingMethod to store the details
93// on the operand in a single integer.
94enum OperandType {
95  OT_MASK = 0xFF000000,
96  OT_A = 0x01000000,
97  OT_B = 0x02000000,
98  OT_C = 0x03000000,
99  OT_D = 0x04000000,
100  OT_DQ = 0x05000000,
101  OT_P = 0x06000000,
102  OT_PI = 0x07000000,
103  OT_PS = 0x08000000,  // actually unsupported for (we don't know its size)
104  OT_Q = 0x09000000,
105  OT_S = 0x0A000000,
106  OT_SS = 0x0B000000,
107  OT_SI = 0x0C000000,
108  OT_V = 0x0D000000,
109  OT_W = 0x0E000000,
110  OT_SD = 0x0F000000,  // scalar double-precision floating-point value
111  OT_PD = 0x10000000,  // double-precision floating point
112  // dummy "operand type" for address mode M - which doesn't specify
113  // operand type
114  OT_ADDRESS_MODE_M = 0x80000000
115};
116
117// Everything that's in an Opcode (see below) except the three
118// alternative opcode structs for different prefixes.
119struct SpecificOpcode {
120  // Index to continuation table, or 0 if this is the last
121  // byte in the opcode.
122  int table_index_;
123
124  // The opcode type
125  InstructionType type_;
126
127  // Description of the type of the dest, src and aux operands,
128  // put together from an enOperandType flag and an enAddressingMethod
129  // flag.
130  int flag_dest_;
131  int flag_source_;
132  int flag_aux_;
133
134  // We indicate the mnemonic for debugging purposes
135  const char* mnemonic_;
136};
137
138// The information we keep in our tables about each of the different
139// valid instructions recognized by the IA-32 architecture.
140struct Opcode {
141  // Index to continuation table, or 0 if this is the last
142  // byte in the opcode.
143  int table_index_;
144
145  // The opcode type
146  InstructionType type_;
147
148  // Description of the type of the dest, src and aux operands,
149  // put together from an enOperandType flag and an enAddressingMethod
150  // flag.
151  int flag_dest_;
152  int flag_source_;
153  int flag_aux_;
154
155  // We indicate the mnemonic for debugging purposes
156  const char* mnemonic_;
157
158  // Alternative opcode info if certain prefixes are specified.
159  // In most cases, all of these are zeroed-out.  Only used if
160  // bPrefixDependent is true.
161  bool is_prefix_dependent_;
162  SpecificOpcode opcode_if_f2_prefix_;
163  SpecificOpcode opcode_if_f3_prefix_;
164  SpecificOpcode opcode_if_66_prefix_;
165};
166
167// Information about each table entry.
168struct OpcodeTable {
169  // Table of instruction entries
170  const Opcode* table_;
171  // How many bytes left to shift ModR/M byte <b>before</b> applying mask
172  unsigned char shift_;
173  // Mask to apply to byte being looked at before comparing to table
174  unsigned char mask_;
175  // Minimum/maximum indexes in table.
176  unsigned char min_lim_;
177  unsigned char max_lim_;
178};
179
180// Information about each entry in table used to decode ModR/M byte.
181struct ModrmEntry {
182  // Is the operand encoded as bytes in the instruction (rather than
183  // if it's e.g. a register in which case it's just encoded in the
184  // ModR/M byte)
185  bool is_encoded_in_instruction_;
186
187  // Is there a SIB byte?  In this case we always need to decode it.
188  bool use_sib_byte_;
189
190  // What is the size of the operand (only important if it's encoded
191  // in the instruction)?
192  OperandSize operand_size_;
193};
194
195};  // namespace sidestep
196
197#endif  // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__
198