1 /*BEGIN_LEGAL
2 
3 Copyright (c) 2018 Intel Corporation
4 
5   Licensed under the Apache License, Version 2.0 (the "License");
6   you may not use this file except in compliance with the License.
7   You may obtain a copy of the License at
8 
9       http://www.apache.org/licenses/LICENSE-2.0
10 
11   Unless required by applicable law or agreed to in writing, software
12   distributed under the License is distributed on an "AS IS" BASIS,
13   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   See the License for the specific language governing permissions and
15   limitations under the License.
16 
17 END_LEGAL */
18 
19 /// @file xed-ild-private.h
20 /// instruction length decoder private header
21 
22 #if !defined(XED_ILD_PRIVATE_H)
23 # define XED_ILD_PRIVATE_H
24 
25 
26 
27 
28 #include "xed-ild.h"
29 #include "xed-machine-mode-enum.h"
xed_modrm_mod(xed_uint8_t m)30 static XED_INLINE xed_uint_t xed_modrm_mod(xed_uint8_t m) { return m>>6; }
xed_modrm_reg(xed_uint8_t m)31 static XED_INLINE xed_uint_t xed_modrm_reg(xed_uint8_t m) { return (m>>3)&7; }
xed_modrm_rm(xed_uint8_t m)32 static XED_INLINE xed_uint_t xed_modrm_rm(xed_uint8_t m) { return m&7; }
xed_sib_scale(xed_uint8_t m)33 static XED_INLINE xed_uint_t xed_sib_scale(xed_uint8_t m) { return m>>6; }
xed_sib_index(xed_uint8_t m)34 static XED_INLINE xed_uint_t xed_sib_index(xed_uint8_t m) { return (m>>3)&7; }
xed_sib_base(xed_uint8_t m)35 static XED_INLINE xed_uint_t xed_sib_base(xed_uint8_t m) { return m&7; }
bits2bytes(xed_uint_t bits)36 static XED_INLINE xed_uint_t bits2bytes(xed_uint_t bits) { return bits>>3; }
bytes2bits(xed_uint_t bytes)37 static XED_INLINE xed_uint_t bytes2bits(xed_uint_t bytes) { return bytes<<3; }
38 
39 
40 typedef void(*xed_ild_l1_func_t)(xed_decoded_inst_t*);
41 typedef xed_uint32_t(*xed3_find_func_t)(const xed_decoded_inst_t*);
42 
43 typedef struct {xed_uint32_t key; xed_uint32_t value;} lu1_entry_t;
44 typedef struct {xed_uint32_t key; xed3_find_func_t l2_func;} lu2_entry_t;
45 
46 
47 typedef enum {
48     XED_ILD_MAP0,
49     XED_ILD_MAP1, /* 0F */
50     XED_ILD_MAP2, /* 0F38 */
51     XED_ILD_MAP3, /* 0F3A */
52     XED_ILD_MAP4,  /* required placeholders */
53     XED_ILD_MAP5,
54     XED_ILD_MAP6,
55     XED_ILD_MAPAMD,   /* fake map 7 -  amd 3dnow */
56     XED_ILD_MAP_XOP8, /* amd xop */
57     XED_ILD_MAP_XOP9, /* amd xop */
58     XED_ILD_MAP_XOPA, /* amd xop */
59     XED_ILD_MAP_LAST,  /* for array sizing */
60     XED_ILD_MAP_INVALID /* for error handling */
61 } xed_ild_map_enum_t;
62 
63 
64 #define XED_GRAMMAR_MODE_64 2
65 #define XED_GRAMMAR_MODE_32 1
66 #define XED_GRAMMAR_MODE_16 0
67 
68 /*
69 Double immediate instructions are special. There are only 3 of them
70 and anyway they require a special care. It seems that the simplest way
71 is just to define L1 functions for both such map-opcode pairs:
72 (0x0F,0x78) and (0x0, 0xC8)
73 */
74 
75 /* (0x0f,0x78) map-opcode pair is even more special, because it has a conflict
76 on imm_bytes between AMD's INSERTQ,EXTRQ and Intel's VMREAD.
77 We already hardcode L1 functions for double immediate instructions, so we will
78 hardcode a conflict resolution here too. */
xed_ild_hasimm_map0x0F_op0x78_l1(xed_decoded_inst_t * x)79 static XED_INLINE void xed_ild_hasimm_map0x0F_op0x78_l1(xed_decoded_inst_t* x) {
80     /*FIXME: f3 prefix is not mentioned in INSERTQ or EXTRQ grammar
81     definitions, however is forbidden for VMREAD. It seems that it can
82     go with INSERTQ and EXTRQ. Right? */
83     if (xed3_operand_get_osz(x) ||
84         xed3_operand_get_ild_f2(x)
85         //    || xed3_operand_get_ild_f3(x)
86     )
87     {
88         /*for INSERTQ and EXTRQ*/
89         /*straight in bytes*/
90         xed3_operand_set_imm_width(x, bytes2bits(1));
91         xed3_operand_set_imm1_bytes(x, 1);
92         return;
93     }
94     /* for VMREAD imm_bytes is 0*/
95 }
96 
97 /*ENTER instruction has UIMM16 and UIMM8_1 NTs*/
xed_ild_hasimm_map0x0_op0xc8_l1(xed_decoded_inst_t * x)98 static XED_INLINE void xed_ild_hasimm_map0x0_op0xc8_l1(xed_decoded_inst_t* x) {
99     /* for ENTER */
100     /*straight in bytes*/
101     xed3_operand_set_imm_width(x, bytes2bits(2));
102     xed3_operand_set_imm1_bytes(x, 1);
103 }
104 
105 /*FIXME: need to put getters in scanners headers to keep layering working*/
106 
107 /// Convert xed_machine_mode_enum_t to a corresponding xed_bits_t value
108 /// for MODE operand
109 ///  @param mmode - machine mode in xed_machine_mode_enum_t type
110 /// @return mode value for MODE operand in xed_bits_t type
111 ///
112 /// @ingroup ILD
113 xed_bits_t xed_ild_cvt_mode(xed_machine_mode_enum_t mmode);
114 
115 /// Initialize internal data structures of the ILD.
116 void xed_ild_init_decoder(void);
117 
118 
119 
120 /* Special getter for RM  */
121 static XED_INLINE xed_uint_t
xed_ild_get_rm(const xed_decoded_inst_t * ild)122 xed_ild_get_rm(const xed_decoded_inst_t* ild) {
123     /* Sometimes we don't have modrm, but grammar still
124      * likes to use RM operand - in this case it is first
125      * 3 bits of the opcode.
126      */
127     xed_uint8_t modrm;
128     if (xed3_operand_get_has_modrm(ild))
129         return xed3_operand_get_rm(ild);
130     modrm = xed3_operand_get_nominal_opcode(ild);
131     return xed_modrm_rm(modrm);
132 }
133 
134 /* compressed operand getters */
135 static XED_INLINE xed_uint_t
xed3_operand_get_mod3(const xed_decoded_inst_t * ild)136 xed3_operand_get_mod3(const xed_decoded_inst_t* ild) {
137     return xed3_operand_get_mod(ild) == 3;
138 }
139 
140 static XED_INLINE xed_uint_t
xed3_operand_get_rm4(const xed_decoded_inst_t * ild)141 xed3_operand_get_rm4(const xed_decoded_inst_t* ild) {
142     return xed3_operand_get_rm(ild) == 4;
143 }
144 
145 static XED_INLINE xed_uint_t
xed3_operand_get_uimm0_1(const xed_decoded_inst_t * ild)146 xed3_operand_get_uimm0_1(const xed_decoded_inst_t* ild) {
147     return xed3_operand_get_uimm0(ild) == 1;
148 }
149 
150 
151 #if defined(XED_AVX)
152 static XED_INLINE xed_uint_t
xed3_operand_get_vexdest210_7(const xed_decoded_inst_t * ild)153 xed3_operand_get_vexdest210_7(const xed_decoded_inst_t* ild) {
154     return xed3_operand_get_vexdest210(ild) == 7;
155 }
156 #endif
157 
158 #if defined(XED_SUPPORTS_AVX512)
159 static XED_INLINE
xed3_operand_get_mask_not0(const xed_decoded_inst_t * d)160 xed_uint32_t xed3_operand_get_mask_not0(const xed_decoded_inst_t *d) {
161     /* aaa != 0  */
162     return xed3_operand_get_mask(d) != 0;
163 }
164 static XED_INLINE
xed3_operand_get_mask_zero(const xed_decoded_inst_t * d)165 xed_uint32_t xed3_operand_get_mask_zero(const xed_decoded_inst_t *d) {
166     /* aaa == 0  */
167     return xed3_operand_get_mask(d) == 0;
168 }
169 #endif
170 
171 void
172 xed_instruction_length_decode(xed_decoded_inst_t* d);
173 
174 
175 #endif
176 
177