162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci#ifndef _ASM_X86_INAT_H
362306a36Sopenharmony_ci#define _ASM_X86_INAT_H
462306a36Sopenharmony_ci/*
562306a36Sopenharmony_ci * x86 instruction attributes
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Written by Masami Hiramatsu <mhiramat@redhat.com>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <asm/inat_types.h> /* __ignore_sync_check__ */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * Internal bits. Don't use bitmasks directly, because these bits are
1362306a36Sopenharmony_ci * unstable. You should use checking functions.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define INAT_OPCODE_TABLE_SIZE 256
1762306a36Sopenharmony_ci#define INAT_GROUP_TABLE_SIZE 8
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* Legacy last prefixes */
2062306a36Sopenharmony_ci#define INAT_PFX_OPNDSZ	1	/* 0x66 */ /* LPFX1 */
2162306a36Sopenharmony_ci#define INAT_PFX_REPE	2	/* 0xF3 */ /* LPFX2 */
2262306a36Sopenharmony_ci#define INAT_PFX_REPNE	3	/* 0xF2 */ /* LPFX3 */
2362306a36Sopenharmony_ci/* Other Legacy prefixes */
2462306a36Sopenharmony_ci#define INAT_PFX_LOCK	4	/* 0xF0 */
2562306a36Sopenharmony_ci#define INAT_PFX_CS	5	/* 0x2E */
2662306a36Sopenharmony_ci#define INAT_PFX_DS	6	/* 0x3E */
2762306a36Sopenharmony_ci#define INAT_PFX_ES	7	/* 0x26 */
2862306a36Sopenharmony_ci#define INAT_PFX_FS	8	/* 0x64 */
2962306a36Sopenharmony_ci#define INAT_PFX_GS	9	/* 0x65 */
3062306a36Sopenharmony_ci#define INAT_PFX_SS	10	/* 0x36 */
3162306a36Sopenharmony_ci#define INAT_PFX_ADDRSZ	11	/* 0x67 */
3262306a36Sopenharmony_ci/* x86-64 REX prefix */
3362306a36Sopenharmony_ci#define INAT_PFX_REX	12	/* 0x4X */
3462306a36Sopenharmony_ci/* AVX VEX prefixes */
3562306a36Sopenharmony_ci#define INAT_PFX_VEX2	13	/* 2-bytes VEX prefix */
3662306a36Sopenharmony_ci#define INAT_PFX_VEX3	14	/* 3-bytes VEX prefix */
3762306a36Sopenharmony_ci#define INAT_PFX_EVEX	15	/* EVEX prefix */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define INAT_LSTPFX_MAX	3
4062306a36Sopenharmony_ci#define INAT_LGCPFX_MAX	11
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* Immediate size */
4362306a36Sopenharmony_ci#define INAT_IMM_BYTE		1
4462306a36Sopenharmony_ci#define INAT_IMM_WORD		2
4562306a36Sopenharmony_ci#define INAT_IMM_DWORD		3
4662306a36Sopenharmony_ci#define INAT_IMM_QWORD		4
4762306a36Sopenharmony_ci#define INAT_IMM_PTR		5
4862306a36Sopenharmony_ci#define INAT_IMM_VWORD32	6
4962306a36Sopenharmony_ci#define INAT_IMM_VWORD		7
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/* Legacy prefix */
5262306a36Sopenharmony_ci#define INAT_PFX_OFFS	0
5362306a36Sopenharmony_ci#define INAT_PFX_BITS	4
5462306a36Sopenharmony_ci#define INAT_PFX_MAX    ((1 << INAT_PFX_BITS) - 1)
5562306a36Sopenharmony_ci#define INAT_PFX_MASK	(INAT_PFX_MAX << INAT_PFX_OFFS)
5662306a36Sopenharmony_ci/* Escape opcodes */
5762306a36Sopenharmony_ci#define INAT_ESC_OFFS	(INAT_PFX_OFFS + INAT_PFX_BITS)
5862306a36Sopenharmony_ci#define INAT_ESC_BITS	2
5962306a36Sopenharmony_ci#define INAT_ESC_MAX	((1 << INAT_ESC_BITS) - 1)
6062306a36Sopenharmony_ci#define INAT_ESC_MASK	(INAT_ESC_MAX << INAT_ESC_OFFS)
6162306a36Sopenharmony_ci/* Group opcodes (1-16) */
6262306a36Sopenharmony_ci#define INAT_GRP_OFFS	(INAT_ESC_OFFS + INAT_ESC_BITS)
6362306a36Sopenharmony_ci#define INAT_GRP_BITS	5
6462306a36Sopenharmony_ci#define INAT_GRP_MAX	((1 << INAT_GRP_BITS) - 1)
6562306a36Sopenharmony_ci#define INAT_GRP_MASK	(INAT_GRP_MAX << INAT_GRP_OFFS)
6662306a36Sopenharmony_ci/* Immediates */
6762306a36Sopenharmony_ci#define INAT_IMM_OFFS	(INAT_GRP_OFFS + INAT_GRP_BITS)
6862306a36Sopenharmony_ci#define INAT_IMM_BITS	3
6962306a36Sopenharmony_ci#define INAT_IMM_MASK	(((1 << INAT_IMM_BITS) - 1) << INAT_IMM_OFFS)
7062306a36Sopenharmony_ci/* Flags */
7162306a36Sopenharmony_ci#define INAT_FLAG_OFFS	(INAT_IMM_OFFS + INAT_IMM_BITS)
7262306a36Sopenharmony_ci#define INAT_MODRM	(1 << (INAT_FLAG_OFFS))
7362306a36Sopenharmony_ci#define INAT_FORCE64	(1 << (INAT_FLAG_OFFS + 1))
7462306a36Sopenharmony_ci#define INAT_SCNDIMM	(1 << (INAT_FLAG_OFFS + 2))
7562306a36Sopenharmony_ci#define INAT_MOFFSET	(1 << (INAT_FLAG_OFFS + 3))
7662306a36Sopenharmony_ci#define INAT_VARIANT	(1 << (INAT_FLAG_OFFS + 4))
7762306a36Sopenharmony_ci#define INAT_VEXOK	(1 << (INAT_FLAG_OFFS + 5))
7862306a36Sopenharmony_ci#define INAT_VEXONLY	(1 << (INAT_FLAG_OFFS + 6))
7962306a36Sopenharmony_ci#define INAT_EVEXONLY	(1 << (INAT_FLAG_OFFS + 7))
8062306a36Sopenharmony_ci/* Attribute making macros for attribute tables */
8162306a36Sopenharmony_ci#define INAT_MAKE_PREFIX(pfx)	(pfx << INAT_PFX_OFFS)
8262306a36Sopenharmony_ci#define INAT_MAKE_ESCAPE(esc)	(esc << INAT_ESC_OFFS)
8362306a36Sopenharmony_ci#define INAT_MAKE_GROUP(grp)	((grp << INAT_GRP_OFFS) | INAT_MODRM)
8462306a36Sopenharmony_ci#define INAT_MAKE_IMM(imm)	(imm << INAT_IMM_OFFS)
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci/* Identifiers for segment registers */
8762306a36Sopenharmony_ci#define INAT_SEG_REG_IGNORE	0
8862306a36Sopenharmony_ci#define INAT_SEG_REG_DEFAULT	1
8962306a36Sopenharmony_ci#define INAT_SEG_REG_CS		2
9062306a36Sopenharmony_ci#define INAT_SEG_REG_SS		3
9162306a36Sopenharmony_ci#define INAT_SEG_REG_DS		4
9262306a36Sopenharmony_ci#define INAT_SEG_REG_ES		5
9362306a36Sopenharmony_ci#define INAT_SEG_REG_FS		6
9462306a36Sopenharmony_ci#define INAT_SEG_REG_GS		7
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Attribute search APIs */
9762306a36Sopenharmony_ciextern insn_attr_t inat_get_opcode_attribute(insn_byte_t opcode);
9862306a36Sopenharmony_ciextern int inat_get_last_prefix_id(insn_byte_t last_pfx);
9962306a36Sopenharmony_ciextern insn_attr_t inat_get_escape_attribute(insn_byte_t opcode,
10062306a36Sopenharmony_ci					     int lpfx_id,
10162306a36Sopenharmony_ci					     insn_attr_t esc_attr);
10262306a36Sopenharmony_ciextern insn_attr_t inat_get_group_attribute(insn_byte_t modrm,
10362306a36Sopenharmony_ci					    int lpfx_id,
10462306a36Sopenharmony_ci					    insn_attr_t esc_attr);
10562306a36Sopenharmony_ciextern insn_attr_t inat_get_avx_attribute(insn_byte_t opcode,
10662306a36Sopenharmony_ci					  insn_byte_t vex_m,
10762306a36Sopenharmony_ci					  insn_byte_t vex_pp);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/* Attribute checking functions */
11062306a36Sopenharmony_cistatic inline int inat_is_legacy_prefix(insn_attr_t attr)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	attr &= INAT_PFX_MASK;
11362306a36Sopenharmony_ci	return attr && attr <= INAT_LGCPFX_MAX;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic inline int inat_is_address_size_prefix(insn_attr_t attr)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	return (attr & INAT_PFX_MASK) == INAT_PFX_ADDRSZ;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic inline int inat_is_operand_size_prefix(insn_attr_t attr)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	return (attr & INAT_PFX_MASK) == INAT_PFX_OPNDSZ;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic inline int inat_is_rex_prefix(insn_attr_t attr)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	return (attr & INAT_PFX_MASK) == INAT_PFX_REX;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic inline int inat_last_prefix_id(insn_attr_t attr)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	if ((attr & INAT_PFX_MASK) > INAT_LSTPFX_MAX)
13462306a36Sopenharmony_ci		return 0;
13562306a36Sopenharmony_ci	else
13662306a36Sopenharmony_ci		return attr & INAT_PFX_MASK;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline int inat_is_vex_prefix(insn_attr_t attr)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	attr &= INAT_PFX_MASK;
14262306a36Sopenharmony_ci	return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 ||
14362306a36Sopenharmony_ci	       attr == INAT_PFX_EVEX;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline int inat_is_evex_prefix(insn_attr_t attr)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic inline int inat_is_vex3_prefix(insn_attr_t attr)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	return (attr & INAT_PFX_MASK) == INAT_PFX_VEX3;
15462306a36Sopenharmony_ci}
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic inline int inat_is_escape(insn_attr_t attr)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	return attr & INAT_ESC_MASK;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic inline int inat_escape_id(insn_attr_t attr)
16262306a36Sopenharmony_ci{
16362306a36Sopenharmony_ci	return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic inline int inat_is_group(insn_attr_t attr)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	return attr & INAT_GRP_MASK;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic inline int inat_group_id(insn_attr_t attr)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic inline int inat_group_common_attribute(insn_attr_t attr)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	return attr & ~INAT_GRP_MASK;
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic inline int inat_has_immediate(insn_attr_t attr)
18262306a36Sopenharmony_ci{
18362306a36Sopenharmony_ci	return attr & INAT_IMM_MASK;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic inline int inat_immediate_size(insn_attr_t attr)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic inline int inat_has_modrm(insn_attr_t attr)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	return attr & INAT_MODRM;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_cistatic inline int inat_is_force64(insn_attr_t attr)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	return attr & INAT_FORCE64;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cistatic inline int inat_has_second_immediate(insn_attr_t attr)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	return attr & INAT_SCNDIMM;
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic inline int inat_has_moffset(insn_attr_t attr)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	return attr & INAT_MOFFSET;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic inline int inat_has_variant(insn_attr_t attr)
21262306a36Sopenharmony_ci{
21362306a36Sopenharmony_ci	return attr & INAT_VARIANT;
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic inline int inat_accept_vex(insn_attr_t attr)
21762306a36Sopenharmony_ci{
21862306a36Sopenharmony_ci	return attr & INAT_VEXOK;
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic inline int inat_must_vex(insn_attr_t attr)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	return attr & (INAT_VEXONLY | INAT_EVEXONLY);
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic inline int inat_must_evex(insn_attr_t attr)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	return attr & INAT_EVEXONLY;
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci#endif
231