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