| 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 */ | 
|---|
| 106 | extern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode); | 
|---|
| 107 | extern int inat_get_last_prefix_id(insn_byte_t last_pfx); | 
|---|
| 108 | extern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, | 
|---|
| 109 | int lpfx_id, | 
|---|
| 110 | insn_attr_t esc_attr); | 
|---|
| 111 | extern insn_attr_t inat_get_group_attribute(insn_byte_t modrm, | 
|---|
| 112 | int lpfx_id, | 
|---|
| 113 | insn_attr_t esc_attr); | 
|---|
| 114 | extern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, | 
|---|
| 115 | insn_byte_t vex_m, | 
|---|
| 116 | insn_byte_t vex_pp); | 
|---|
| 117 | extern insn_attr_t inat_get_xop_attribute(insn_byte_t opcode, | 
|---|
| 118 | insn_byte_t map_select); | 
|---|
| 119 |  | 
|---|
| 120 | /* Attribute checking functions */ | 
|---|
| 121 | static 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 |  | 
|---|
| 127 | static inline int inat_is_address_size_prefix(insn_attr_t attr) | 
|---|
| 128 | { | 
|---|
| 129 | return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ; | 
|---|
| 130 | } | 
|---|
| 131 |  | 
|---|
| 132 | static inline int inat_is_operand_size_prefix(insn_attr_t attr) | 
|---|
| 133 | { | 
|---|
| 134 | return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ; | 
|---|
| 135 | } | 
|---|
| 136 |  | 
|---|
| 137 | static inline int inat_is_rex_prefix(insn_attr_t attr) | 
|---|
| 138 | { | 
|---|
| 139 | return (attr & INAT_PFX_MASK) == INAT_PFX_REX; | 
|---|
| 140 | } | 
|---|
| 141 |  | 
|---|
| 142 | static inline int inat_is_rex2_prefix(insn_attr_t attr) | 
|---|
| 143 | { | 
|---|
| 144 | return (attr & INAT_PFX_MASK) == INAT_PFX_REX2; | 
|---|
| 145 | } | 
|---|
| 146 |  | 
|---|
| 147 | static 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 |  | 
|---|
| 155 | static 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 |  | 
|---|
| 162 | static inline int inat_is_evex_prefix(insn_attr_t attr) | 
|---|
| 163 | { | 
|---|
| 164 | return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX; | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | static inline int inat_is_vex3_prefix(insn_attr_t attr) | 
|---|
| 168 | { | 
|---|
| 169 | return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3; | 
|---|
| 170 | } | 
|---|
| 171 |  | 
|---|
| 172 | static inline int inat_is_xop_prefix(insn_attr_t attr) | 
|---|
| 173 | { | 
|---|
| 174 | return (attr & INAT_PFX_MASK) == INAT_PFX_XOP; | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | static inline int inat_is_escape(insn_attr_t attr) | 
|---|
| 178 | { | 
|---|
| 179 | return attr & INAT_ESC_MASK; | 
|---|
| 180 | } | 
|---|
| 181 |  | 
|---|
| 182 | static inline int inat_escape_id(insn_attr_t attr) | 
|---|
| 183 | { | 
|---|
| 184 | return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS; | 
|---|
| 185 | } | 
|---|
| 186 |  | 
|---|
| 187 | static inline int inat_is_group(insn_attr_t attr) | 
|---|
| 188 | { | 
|---|
| 189 | return attr & INAT_GRP_MASK; | 
|---|
| 190 | } | 
|---|
| 191 |  | 
|---|
| 192 | static inline int inat_group_id(insn_attr_t attr) | 
|---|
| 193 | { | 
|---|
| 194 | return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; | 
|---|
| 195 | } | 
|---|
| 196 |  | 
|---|
| 197 | static inline int inat_group_common_attribute(insn_attr_t attr) | 
|---|
| 198 | { | 
|---|
| 199 | return attr & ~INAT_GRP_MASK; | 
|---|
| 200 | } | 
|---|
| 201 |  | 
|---|
| 202 | static inline int inat_has_immediate(insn_attr_t attr) | 
|---|
| 203 | { | 
|---|
| 204 | return attr & INAT_IMM_MASK; | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | static inline int inat_immediate_size(insn_attr_t attr) | 
|---|
| 208 | { | 
|---|
| 209 | return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS; | 
|---|
| 210 | } | 
|---|
| 211 |  | 
|---|
| 212 | static inline int inat_has_modrm(insn_attr_t attr) | 
|---|
| 213 | { | 
|---|
| 214 | return attr & INAT_MODRM; | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | static inline int inat_is_force64(insn_attr_t attr) | 
|---|
| 218 | { | 
|---|
| 219 | return attr & INAT_FORCE64; | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | static inline int inat_has_second_immediate(insn_attr_t attr) | 
|---|
| 223 | { | 
|---|
| 224 | return attr & INAT_SCNDIMM; | 
|---|
| 225 | } | 
|---|
| 226 |  | 
|---|
| 227 | static inline int inat_has_moffset(insn_attr_t attr) | 
|---|
| 228 | { | 
|---|
| 229 | return attr & INAT_MOFFSET; | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | static inline int inat_has_variant(insn_attr_t attr) | 
|---|
| 233 | { | 
|---|
| 234 | return attr & INAT_VARIANT; | 
|---|
| 235 | } | 
|---|
| 236 |  | 
|---|
| 237 | static inline int inat_accept_vex(insn_attr_t attr) | 
|---|
| 238 | { | 
|---|
| 239 | return attr & INAT_VEXOK; | 
|---|
| 240 | } | 
|---|
| 241 |  | 
|---|
| 242 | static inline int inat_accept_xop(insn_attr_t attr) | 
|---|
| 243 | { | 
|---|
| 244 | return attr & INAT_XOPOK; | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | static inline int inat_must_vex(insn_attr_t attr) | 
|---|
| 248 | { | 
|---|
| 249 | return attr & (INAT_VEXONLY | INAT_EVEXONLY); | 
|---|
| 250 | } | 
|---|
| 251 |  | 
|---|
| 252 | static inline int inat_must_evex(insn_attr_t attr) | 
|---|
| 253 | { | 
|---|
| 254 | return attr & INAT_EVEXONLY; | 
|---|
| 255 | } | 
|---|
| 256 |  | 
|---|
| 257 | static inline int inat_evex_scalable(insn_attr_t attr) | 
|---|
| 258 | { | 
|---|
| 259 | return attr & INAT_EVEX_SCALABLE; | 
|---|
| 260 | } | 
|---|
| 261 |  | 
|---|
| 262 | static inline int inat_is_invalid64(insn_attr_t attr) | 
|---|
| 263 | { | 
|---|
| 264 | return attr & INAT_INV64; | 
|---|
| 265 | } | 
|---|
| 266 | #endif | 
|---|
| 267 |  | 
|---|