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