1 | #ifndef _ASM_X86_INAT_H |
2 | #define _ASM_X86_INAT_H |
3 | /* |
4 | * x86 instruction attributes |
5 | * |
6 | * Written by Masami Hiramatsu <mhiramat@redhat.com> |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | * GNU General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 | * |
22 | */ |
23 | #include <asm/inat_types.h> |
24 | |
25 | /* |
26 | * Internal bits. Don't use bitmasks directly, because these bits are |
27 | * unstable. You should use checking functions. |
28 | */ |
29 | |
30 | #define INAT_OPCODE_TABLE_SIZE 256 |
31 | #define INAT_GROUP_TABLE_SIZE 8 |
32 | |
33 | /* Legacy last prefixes */ |
34 | #define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */ |
35 | #define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */ |
36 | #define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */ |
37 | /* Other Legacy prefixes */ |
38 | #define INAT_PFX_LOCK 4 /* 0xF0 */ |
39 | #define INAT_PFX_CS 5 /* 0x2E */ |
40 | #define INAT_PFX_DS 6 /* 0x3E */ |
41 | #define INAT_PFX_ES 7 /* 0x26 */ |
42 | #define INAT_PFX_FS 8 /* 0x64 */ |
43 | #define INAT_PFX_GS 9 /* 0x65 */ |
44 | #define INAT_PFX_SS 10 /* 0x36 */ |
45 | #define INAT_PFX_ADDRSZ 11 /* 0x67 */ |
46 | /* x86-64 REX prefix */ |
47 | #define INAT_PFX_REX 12 /* 0x4X */ |
48 | /* AVX VEX prefixes */ |
49 | #define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ |
50 | #define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ |
51 | #define INAT_PFX_EVEX 15 /* EVEX prefix */ |
52 | |
53 | #define INAT_LSTPFX_MAX 3 |
54 | #define INAT_LGCPFX_MAX 11 |
55 | |
56 | /* Immediate size */ |
57 | #define INAT_IMM_BYTE 1 |
58 | #define INAT_IMM_WORD 2 |
59 | #define INAT_IMM_DWORD 3 |
60 | #define INAT_IMM_QWORD 4 |
61 | #define INAT_IMM_PTR 5 |
62 | #define INAT_IMM_VWORD32 6 |
63 | #define INAT_IMM_VWORD 7 |
64 | |
65 | /* Legacy prefix */ |
66 | #define INAT_PFX_OFFS 0 |
67 | #define INAT_PFX_BITS 4 |
68 | #define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1) |
69 | #define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS) |
70 | /* Escape opcodes */ |
71 | #define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS) |
72 | #define INAT_ESC_BITS 2 |
73 | #define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1) |
74 | #define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS) |
75 | /* Group opcodes (1-16) */ |
76 | #define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS) |
77 | #define INAT_GRP_BITS 5 |
78 | #define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1) |
79 | #define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS) |
80 | /* Immediates */ |
81 | #define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS) |
82 | #define INAT_IMM_BITS 3 |
83 | #define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS) |
84 | /* Flags */ |
85 | #define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS) |
86 | #define INAT_MODRM (1 << (INAT_FLAG_OFFS)) |
87 | #define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1)) |
88 | #define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2)) |
89 | #define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3)) |
90 | #define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) |
91 | #define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) |
92 | #define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) |
93 | #define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7)) |
94 | /* Attribute making macros for attribute tables */ |
95 | #define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) |
96 | #define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) |
97 | #define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM) |
98 | #define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS) |
99 | |
100 | /* Identifiers for segment registers */ |
101 | #define INAT_SEG_REG_IGNORE 0 |
102 | #define INAT_SEG_REG_DEFAULT 1 |
103 | #define INAT_SEG_REG_CS 2 |
104 | #define INAT_SEG_REG_SS 3 |
105 | #define INAT_SEG_REG_DS 4 |
106 | #define INAT_SEG_REG_ES 5 |
107 | #define INAT_SEG_REG_FS 6 |
108 | #define INAT_SEG_REG_GS 7 |
109 | |
110 | /* Attribute search APIs */ |
111 | extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); |
112 | extern int inat_get_last_prefix_id(insn_byte_t last_pfx); |
113 | extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, |
114 | int lpfx_id, |
115 | insn_attr_t esc_attr); |
116 | extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, |
117 | int lpfx_id, |
118 | insn_attr_t esc_attr); |
119 | extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, |
120 | insn_byte_t vex_m, |
121 | insn_byte_t vex_pp); |
122 | |
123 | /* Attribute checking functions */ |
124 | static inline int inat_is_legacy_prefix(insn_attr_t attr) |
125 | { |
126 | attr &= INAT_PFX_MASK; |
127 | return attr && attr <= INAT_LGCPFX_MAX; |
128 | } |
129 | |
130 | static inline int inat_is_address_size_prefix(insn_attr_t attr) |
131 | { |
132 | return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ; |
133 | } |
134 | |
135 | static inline int inat_is_operand_size_prefix(insn_attr_t attr) |
136 | { |
137 | return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ; |
138 | } |
139 | |
140 | static inline int inat_is_rex_prefix(insn_attr_t attr) |
141 | { |
142 | return (attr & INAT_PFX_MASK) == INAT_PFX_REX; |
143 | } |
144 | |
145 | static inline int inat_last_prefix_id(insn_attr_t attr) |
146 | { |
147 | if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX) |
148 | return 0; |
149 | else |
150 | return attr & INAT_PFX_MASK; |
151 | } |
152 | |
153 | static inline int inat_is_vex_prefix(insn_attr_t attr) |
154 | { |
155 | attr &= INAT_PFX_MASK; |
156 | return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 || |
157 | attr == INAT_PFX_EVEX; |
158 | } |
159 | |
160 | static inline int inat_is_evex_prefix(insn_attr_t attr) |
161 | { |
162 | return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX; |
163 | } |
164 | |
165 | static inline int inat_is_vex3_prefix(insn_attr_t attr) |
166 | { |
167 | return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; |
168 | } |
169 | |
170 | static inline int inat_is_escape(insn_attr_t attr) |
171 | { |
172 | return attr & INAT_ESC_MASK; |
173 | } |
174 | |
175 | static inline int inat_escape_id(insn_attr_t attr) |
176 | { |
177 | return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS; |
178 | } |
179 | |
180 | static inline int inat_is_group(insn_attr_t attr) |
181 | { |
182 | return attr & INAT_GRP_MASK; |
183 | } |
184 | |
185 | static inline int inat_group_id(insn_attr_t attr) |
186 | { |
187 | return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; |
188 | } |
189 | |
190 | static inline int inat_group_common_attribute(insn_attr_t attr) |
191 | { |
192 | return attr & ~INAT_GRP_MASK; |
193 | } |
194 | |
195 | static inline int inat_has_immediate(insn_attr_t attr) |
196 | { |
197 | return attr & INAT_IMM_MASK; |
198 | } |
199 | |
200 | static inline int inat_immediate_size(insn_attr_t attr) |
201 | { |
202 | return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS; |
203 | } |
204 | |
205 | static inline int inat_has_modrm(insn_attr_t attr) |
206 | { |
207 | return attr & INAT_MODRM; |
208 | } |
209 | |
210 | static inline int inat_is_force64(insn_attr_t attr) |
211 | { |
212 | return attr & INAT_FORCE64; |
213 | } |
214 | |
215 | static inline int inat_has_second_immediate(insn_attr_t attr) |
216 | { |
217 | return attr & INAT_SCNDIMM; |
218 | } |
219 | |
220 | static inline int inat_has_moffset(insn_attr_t attr) |
221 | { |
222 | return attr & INAT_MOFFSET; |
223 | } |
224 | |
225 | static inline int inat_has_variant(insn_attr_t attr) |
226 | { |
227 | return attr & INAT_VARIANT; |
228 | } |
229 | |
230 | static inline int inat_accept_vex(insn_attr_t attr) |
231 | { |
232 | return attr & INAT_VEXOK; |
233 | } |
234 | |
235 | static inline int inat_must_vex(insn_attr_t attr) |
236 | { |
237 | return attr & (INAT_VEXONLY | INAT_EVEXONLY); |
238 | } |
239 | |
240 | static inline int inat_must_evex(insn_attr_t attr) |
241 | { |
242 | return attr & INAT_EVEXONLY; |
243 | } |
244 | #endif |
245 | |