1/* SPDX-License-Identifier: GPL-2.0-or-later */
2#ifndef _ASM_X86_INAT_H
3#define _ASM_X86_INAT_H
4/*
5 * x86 instruction attributes
6 *
7 * Written by Masami Hiramatsu <mhiramat@redhat.com>
8 */
9#include <asm/inat_types.h> /* __ignore_sync_check__ */
10
11/*
12 * Internal bits. Don't use bitmasks directly, because these bits are
13 * unstable. You should use checking functions.
14 */
15
16#define INAT_OPCODE_TABLE_SIZE 256
17#define INAT_GROUP_TABLE_SIZE 8
18
19/* Legacy last prefixes */
20#define INAT_PFX_OPNDSZ 1 /* 0x66 */ /* LPFX1 */
21#define INAT_PFX_REPE 2 /* 0xF3 */ /* LPFX2 */
22#define INAT_PFX_REPNE 3 /* 0xF2 */ /* LPFX3 */
23/* Other Legacy prefixes */
24#define INAT_PFX_LOCK 4 /* 0xF0 */
25#define INAT_PFX_CS 5 /* 0x2E */
26#define INAT_PFX_DS 6 /* 0x3E */
27#define INAT_PFX_ES 7 /* 0x26 */
28#define INAT_PFX_FS 8 /* 0x64 */
29#define INAT_PFX_GS 9 /* 0x65 */
30#define INAT_PFX_SS 10 /* 0x36 */
31#define INAT_PFX_ADDRSZ 11 /* 0x67 */
32/* x86-64 REX prefix */
33#define INAT_PFX_REX 12 /* 0x4X */
34/* AVX VEX prefixes */
35#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
36#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
37#define INAT_PFX_EVEX 15 /* EVEX prefix */
38/* x86-64 REX2 prefix */
39#define INAT_PFX_REX2 16 /* 0xD5 */
40/* AMD XOP prefix */
41#define INAT_PFX_XOP 17 /* 0x8F */
42
43#define INAT_LSTPFX_MAX 3
44#define INAT_LGCPFX_MAX 11
45
46/* Immediate size */
47#define INAT_IMM_BYTE 1
48#define INAT_IMM_WORD 2
49#define INAT_IMM_DWORD 3
50#define INAT_IMM_QWORD 4
51#define INAT_IMM_PTR 5
52#define INAT_IMM_VWORD32 6
53#define INAT_IMM_VWORD 7
54
55/* Legacy prefix */
56#define INAT_PFX_OFFS 0
57#define INAT_PFX_BITS 5
58#define INAT_PFX_MAX ((1 << INAT_PFX_BITS) - 1)
59#define INAT_PFX_MASK (INAT_PFX_MAX << INAT_PFX_OFFS)
60/* Escape opcodes */
61#define INAT_ESC_OFFS (INAT_PFX_OFFS + INAT_PFX_BITS)
62#define INAT_ESC_BITS 2
63#define INAT_ESC_MAX ((1 << INAT_ESC_BITS) - 1)
64#define INAT_ESC_MASK (INAT_ESC_MAX << INAT_ESC_OFFS)
65/* Group opcodes (1-16) */
66#define INAT_GRP_OFFS (INAT_ESC_OFFS + INAT_ESC_BITS)
67#define INAT_GRP_BITS 5
68#define INAT_GRP_MAX ((1 << INAT_GRP_BITS) - 1)
69#define INAT_GRP_MASK (INAT_GRP_MAX << INAT_GRP_OFFS)
70/* Immediates */
71#define INAT_IMM_OFFS (INAT_GRP_OFFS + INAT_GRP_BITS)
72#define INAT_IMM_BITS 3
73#define INAT_IMM_MASK (((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
74/* Flags */
75#define INAT_FLAG_OFFS (INAT_IMM_OFFS + INAT_IMM_BITS)
76#define INAT_MODRM (1 << (INAT_FLAG_OFFS))
77#define INAT_FORCE64 (1 << (INAT_FLAG_OFFS + 1))
78#define INAT_SCNDIMM (1 << (INAT_FLAG_OFFS + 2))
79#define INAT_MOFFSET (1 << (INAT_FLAG_OFFS + 3))
80#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
81#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
82#define INAT_XOPOK INAT_VEXOK
83#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
84#define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7))
85#define INAT_NO_REX2 (1 << (INAT_FLAG_OFFS + 8))
86#define INAT_REX2_VARIANT (1 << (INAT_FLAG_OFFS + 9))
87#define INAT_EVEX_SCALABLE (1 << (INAT_FLAG_OFFS + 10))
88#define INAT_INV64 (1 << (INAT_FLAG_OFFS + 11))
89/* Attribute making macros for attribute tables */
90#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
91#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
92#define INAT_MAKE_GROUP(grp) ((grp << INAT_GRP_OFFS) | INAT_MODRM)
93#define INAT_MAKE_IMM(imm) (imm << INAT_IMM_OFFS)
94
95/* Identifiers for segment registers */
96#define INAT_SEG_REG_IGNORE 0
97#define INAT_SEG_REG_DEFAULT 1
98#define INAT_SEG_REG_CS 2
99#define INAT_SEG_REG_SS 3
100#define INAT_SEG_REG_DS 4
101#define INAT_SEG_REG_ES 5
102#define INAT_SEG_REG_FS 6
103#define INAT_SEG_REG_GS 7
104
105/* Attribute search APIs */
106extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
107extern int inat_get_last_prefix_id(insn_byte_t last_pfx);
108extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
109 int lpfx_id,
110 insn_attr_t esc_attr);
111extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
112 int lpfx_id,
113 insn_attr_t esc_attr);
114extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
115 insn_byte_t vex_m,
116 insn_byte_t vex_pp);
117extern insn_attr_t inat_get_xop_attribute(insn_byte_t opcode,
118 insn_byte_t map_select);
119
120/* Attribute checking functions */
121static inline int inat_is_legacy_prefix(insn_attr_t attr)
122{
123 attr &= INAT_PFX_MASK;
124 return attr && attr <= INAT_LGCPFX_MAX;
125}
126
127static inline int inat_is_address_size_prefix(insn_attr_t attr)
128{
129 return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
130}
131
132static inline int inat_is_operand_size_prefix(insn_attr_t attr)
133{
134 return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
135}
136
137static inline int inat_is_rex_prefix(insn_attr_t attr)
138{
139 return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
140}
141
142static inline int inat_is_rex2_prefix(insn_attr_t attr)
143{
144 return (attr & INAT_PFX_MASK) == INAT_PFX_REX2;
145}
146
147static inline int inat_last_prefix_id(insn_attr_t attr)
148{
149 if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
150 return 0;
151 else
152 return attr & INAT_PFX_MASK;
153}
154
155static inline int inat_is_vex_prefix(insn_attr_t attr)
156{
157 attr &= INAT_PFX_MASK;
158 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 ||
159 attr == INAT_PFX_EVEX;
160}
161
162static inline int inat_is_evex_prefix(insn_attr_t attr)
163{
164 return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX;
165}
166
167static inline int inat_is_vex3_prefix(insn_attr_t attr)
168{
169 return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
170}
171
172static inline int inat_is_xop_prefix(insn_attr_t attr)
173{
174 return (attr & INAT_PFX_MASK) == INAT_PFX_XOP;
175}
176
177static inline int inat_is_escape(insn_attr_t attr)
178{
179 return attr & INAT_ESC_MASK;
180}
181
182static inline int inat_escape_id(insn_attr_t attr)
183{
184 return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
185}
186
187static inline int inat_is_group(insn_attr_t attr)
188{
189 return attr & INAT_GRP_MASK;
190}
191
192static inline int inat_group_id(insn_attr_t attr)
193{
194 return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
195}
196
197static inline int inat_group_common_attribute(insn_attr_t attr)
198{
199 return attr & ~INAT_GRP_MASK;
200}
201
202static inline int inat_has_immediate(insn_attr_t attr)
203{
204 return attr & INAT_IMM_MASK;
205}
206
207static inline int inat_immediate_size(insn_attr_t attr)
208{
209 return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
210}
211
212static inline int inat_has_modrm(insn_attr_t attr)
213{
214 return attr & INAT_MODRM;
215}
216
217static inline int inat_is_force64(insn_attr_t attr)
218{
219 return attr & INAT_FORCE64;
220}
221
222static inline int inat_has_second_immediate(insn_attr_t attr)
223{
224 return attr & INAT_SCNDIMM;
225}
226
227static inline int inat_has_moffset(insn_attr_t attr)
228{
229 return attr & INAT_MOFFSET;
230}
231
232static inline int inat_has_variant(insn_attr_t attr)
233{
234 return attr & INAT_VARIANT;
235}
236
237static inline int inat_accept_vex(insn_attr_t attr)
238{
239 return attr & INAT_VEXOK;
240}
241
242static inline int inat_accept_xop(insn_attr_t attr)
243{
244 return attr & INAT_XOPOK;
245}
246
247static inline int inat_must_vex(insn_attr_t attr)
248{
249 return attr & (INAT_VEXONLY | INAT_EVEXONLY);
250}
251
252static inline int inat_must_evex(insn_attr_t attr)
253{
254 return attr & INAT_EVEXONLY;
255}
256
257static inline int inat_evex_scalable(insn_attr_t attr)
258{
259 return attr & INAT_EVEX_SCALABLE;
260}
261
262static inline int inat_is_invalid64(insn_attr_t attr)
263{
264 return attr & INAT_INV64;
265}
266#endif
267