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 #include "xed-internal-header.h"
20 #include "xed-decoded-inst.h"
21 #include "xed-decoded-inst-api.h"
22 #include "xed-decoded-inst-private.h"
23 #include "xed-util.h"
24 #include "xed-operand-values-interface.h"
25 #include "xed-reg-class.h"
26 #include "xed-isa-set.h"
27 #include "xed-ild.h"
28
xed_decoded_inst_get_reg(const xed_decoded_inst_t * p,xed_operand_enum_t reg_operand)29 xed_reg_enum_t xed_decoded_inst_get_reg(const xed_decoded_inst_t* p,
30 xed_operand_enum_t reg_operand) {
31
32 switch(reg_operand) {
33 case XED_OPERAND_REG0: return xed3_operand_get_reg0(p);
34 case XED_OPERAND_REG1: return xed3_operand_get_reg1(p);
35 case XED_OPERAND_REG2: return xed3_operand_get_reg2(p);
36 case XED_OPERAND_REG3: return xed3_operand_get_reg3(p);
37 case XED_OPERAND_REG4: return xed3_operand_get_reg4(p);
38 case XED_OPERAND_REG5: return xed3_operand_get_reg5(p);
39 case XED_OPERAND_REG6: return xed3_operand_get_reg6(p);
40 case XED_OPERAND_REG7: return xed3_operand_get_reg7(p);
41 case XED_OPERAND_REG8: return xed3_operand_get_reg8(p);
42 case XED_OPERAND_BASE0: return xed3_operand_get_base0(p);
43 case XED_OPERAND_BASE1: return xed3_operand_get_base1(p);
44 case XED_OPERAND_SEG0: return xed3_operand_get_seg0(p);
45 case XED_OPERAND_SEG1: return xed3_operand_get_seg1(p);
46 case XED_OPERAND_INDEX: return xed3_operand_get_index(p);
47 default:
48 return XED_REG_INVALID;
49 }
50
51 }
52
53
54 xed_uint32_t
xed_decoded_inst_get_attribute(const xed_decoded_inst_t * p,xed_attribute_enum_t attr)55 xed_decoded_inst_get_attribute(const xed_decoded_inst_t* p,
56 xed_attribute_enum_t attr)
57 {
58 xed_assert(p->_inst != 0);
59 return xed_inst_get_attribute(p->_inst, attr);
60 }
61
62 xed_attributes_t
xed_decoded_inst_get_attributes(const xed_decoded_inst_t * p)63 xed_decoded_inst_get_attributes(const xed_decoded_inst_t* p)
64 {
65 xed_assert(p->_inst != 0);
66 return xed_inst_get_attributes(p->_inst);
67 }
68
69 /* xrelease is valid when we have:
70 1: F3 (REP) prefix AND
71 2: (a) xchg inst. OR
72 (b) lock prefix OR
73 (c) mov mem,reg or mov mem,imm where reg is a normal register.
74
75 ** cmpxchg16b inst. is special and can not have xacquire
76 */
77 xed_uint32_t
xed_decoded_inst_is_xrelease(const xed_decoded_inst_t * p)78 xed_decoded_inst_is_xrelease(const xed_decoded_inst_t* p){
79 xed_iclass_enum_t iclass;
80 const xed_operand_values_t* ov;
81 xed_uint32_t rel_able =
82 xed_decoded_inst_get_attribute(p,XED_ATTRIBUTE_HLE_REL_ABLE);
83
84 if (rel_able){
85 ov = xed_decoded_inst_operands_const(p);
86 if (xed_operand_values_has_rep_prefix(ov)){
87 iclass = xed_decoded_inst_get_iclass(p);
88 if (xed_operand_values_get_atomic(ov) || iclass == XED_ICLASS_MOV){
89 //mov instruction do not need the lock prefix
90 return 1;
91 }
92 }
93 }
94 return 0;
95 }
96
97 /* xacquire is valid when we have:
98 1: F2 (REPNE) prefix
99 2: xchg inst. OR lock prefix
100 ** cmpxchg16b inst. is special and can not have xacquire
101 */
102 xed_uint32_t
xed_decoded_inst_is_xacquire(const xed_decoded_inst_t * p)103 xed_decoded_inst_is_xacquire(const xed_decoded_inst_t* p){
104 const xed_operand_values_t* ov;
105 xed_uint32_t acq_able =
106 xed_decoded_inst_get_attribute(p,XED_ATTRIBUTE_HLE_ACQ_ABLE);
107
108 if (acq_able){
109 ov = xed_decoded_inst_operands_const(p);
110 if (xed_operand_values_has_repne_prefix(ov)){
111 return xed_operand_values_get_atomic(ov);
112 }
113 }
114 return 0;
115 }
116
117 xed_uint32_t
xed_decoded_inst_has_mpx_prefix(const xed_decoded_inst_t * p)118 xed_decoded_inst_has_mpx_prefix(const xed_decoded_inst_t* p){
119 const xed_operand_values_t* ov;
120 xed_uint32_t mpx_able = xed_decoded_inst_get_attribute(p,
121 XED_ATTRIBUTE_MPX_PREFIX_ABLE);
122 if (mpx_able){
123 ov = xed_decoded_inst_operands_const(p);
124 if (xed_operand_values_has_repne_prefix(ov)){
125 return 1;
126 }
127 }
128 return 0;
129 }
130
131 xed_uint8_t
xed_decoded_inst_get_modrm(const xed_decoded_inst_t * p)132 xed_decoded_inst_get_modrm(const xed_decoded_inst_t* p)
133 {
134 return xed3_operand_get_modrm_byte(p);
135 }
136
137 /////////////////////////////////////////////////////////////////////////
138 xed_int32_t
xed_decoded_inst_get_branch_displacement(const xed_decoded_inst_t * p)139 xed_decoded_inst_get_branch_displacement(const xed_decoded_inst_t* p) {
140 return xed_operand_values_get_branch_displacement_int32(p);
141 }
142 xed_uint_t
xed_decoded_inst_get_branch_displacement_width(const xed_decoded_inst_t * p)143 xed_decoded_inst_get_branch_displacement_width(const xed_decoded_inst_t* p) {
144 return xed3_operand_get_brdisp_width(p)/8;
145 }
146 xed_uint_t
xed_decoded_inst_get_branch_displacement_width_bits(const xed_decoded_inst_t * p)147 xed_decoded_inst_get_branch_displacement_width_bits(const xed_decoded_inst_t* p) {
148 return xed3_operand_get_brdisp_width(p);
149 }
150 /////////////////////////////////////////////////////////////////////////
151
152
153 xed_uint64_t
xed_decoded_inst_get_unsigned_immediate(const xed_decoded_inst_t * p)154 xed_decoded_inst_get_unsigned_immediate(const xed_decoded_inst_t* p) {
155 return xed_operand_values_get_immediate_uint64(p);
156 }
157 xed_int32_t
xed_decoded_inst_get_signed_immediate(const xed_decoded_inst_t * p)158 xed_decoded_inst_get_signed_immediate(const xed_decoded_inst_t* p) {
159 xed_int64_t y = xed_operand_values_get_immediate_int64(p);
160 return XED_STATIC_CAST(xed_int32_t,y);
161 }
162 xed_uint_t
xed_decoded_inst_get_immediate_width(const xed_decoded_inst_t * p)163 xed_decoded_inst_get_immediate_width(const xed_decoded_inst_t* p) {
164 return xed3_operand_get_imm_width(p)/8;
165 }
166 xed_uint_t
xed_decoded_inst_get_immediate_width_bits(const xed_decoded_inst_t * p)167 xed_decoded_inst_get_immediate_width_bits(const xed_decoded_inst_t* p) {
168 return xed3_operand_get_imm_width(p);
169 }
170
171 xed_uint_t
xed_decoded_inst_get_immediate_is_signed(const xed_decoded_inst_t * p)172 xed_decoded_inst_get_immediate_is_signed(const xed_decoded_inst_t* p) {
173 //return xed_operand_values_get_immediate_is_signed(p);
174 return xed3_operand_get_imm0signed(p);
175 }
176
177
178 /////////////////////////////////////////////////////////////////////////
179
180 xed_int64_t
xed_decoded_inst_get_memory_displacement(const xed_decoded_inst_t * p,unsigned int mem_idx)181 xed_decoded_inst_get_memory_displacement(const xed_decoded_inst_t* p,
182 unsigned int mem_idx)
183 {
184 if (xed_operand_values_has_memory_displacement(p))
185 {
186 switch(mem_idx)
187 {
188 case 0:
189 return xed_operand_values_get_memory_displacement_int64(p);
190
191 case 1:
192 return 0;
193
194 default:
195 xed_assert(mem_idx == 0 || mem_idx == 1);
196 }
197 }
198 return 0;
199 }
200 xed_uint_t
xed_decoded_inst_get_memory_displacement_width(const xed_decoded_inst_t * p,unsigned int mem_idx)201 xed_decoded_inst_get_memory_displacement_width(const xed_decoded_inst_t* p,
202 unsigned int mem_idx)
203 {
204 return xed_decoded_inst_get_memory_displacement_width_bits(p,mem_idx)/8;
205 }
206 xed_uint_t
xed_decoded_inst_get_memory_displacement_width_bits(const xed_decoded_inst_t * p,unsigned int mem_idx)207 xed_decoded_inst_get_memory_displacement_width_bits(
208 const xed_decoded_inst_t* p,
209 unsigned int mem_idx)
210 {
211
212 if (xed_operand_values_has_memory_displacement(p))
213 {
214 switch(mem_idx) {
215 case 0:
216 return xed_operand_values_get_memory_displacement_length_bits(p);
217 case 1:
218 return 0;
219
220 default:
221 xed_assert(mem_idx == 0 || mem_idx == 1);
222 }
223 }
224 return 0;
225 }
226
xed_decoded_inst_get_seg_reg(const xed_decoded_inst_t * p,unsigned int mem_idx)227 xed_reg_enum_t xed_decoded_inst_get_seg_reg(const xed_decoded_inst_t* p,
228 unsigned int mem_idx) {
229 switch(mem_idx) {
230 case 0: return XED_STATIC_CAST(xed_reg_enum_t,xed3_operand_get_seg0(p));
231 case 1: return XED_STATIC_CAST(xed_reg_enum_t,xed3_operand_get_seg1(p));
232 default: xed_assert(mem_idx == 0 || mem_idx == 1);
233 }
234 return XED_REG_INVALID;
235 }
xed_decoded_inst_get_base_reg(const xed_decoded_inst_t * p,unsigned int mem_idx)236 xed_reg_enum_t xed_decoded_inst_get_base_reg(const xed_decoded_inst_t* p,
237 unsigned int mem_idx) {
238 switch(mem_idx) {
239 case 0: return XED_STATIC_CAST(xed_reg_enum_t,xed3_operand_get_base0(p));
240 case 1: return XED_STATIC_CAST(xed_reg_enum_t,xed3_operand_get_base1(p));
241 default: xed_assert(mem_idx == 0 || mem_idx == 1);
242 }
243 return XED_REG_INVALID;
244 }
xed_decoded_inst_get_index_reg(const xed_decoded_inst_t * p,unsigned int mem_idx)245 xed_reg_enum_t xed_decoded_inst_get_index_reg(const xed_decoded_inst_t* p,
246 unsigned int mem_idx) {
247 switch(mem_idx) {
248 case 0: return XED_STATIC_CAST(xed_reg_enum_t,xed3_operand_get_index(p));
249 case 1: return XED_REG_INVALID;
250 default: xed_assert(mem_idx == 0 || mem_idx == 1);
251 }
252 return XED_REG_INVALID;
253 }
xed_decoded_inst_get_scale(const xed_decoded_inst_t * p,unsigned int mem_idx)254 xed_uint_t xed_decoded_inst_get_scale(const xed_decoded_inst_t* p,
255 unsigned int mem_idx) {
256 switch(mem_idx) {
257 case 0: return xed3_operand_get_scale(p);
258 case 1: return 1;
259 default: xed_assert(mem_idx == 0 || mem_idx == 1);
260 }
261 return XED_REG_INVALID;
262 }
263
xed_decoded_inst_mem_read(const xed_decoded_inst_t * p,unsigned int mem_idx)264 xed_bool_t xed_decoded_inst_mem_read(const xed_decoded_inst_t* p,
265 unsigned int mem_idx) {
266 const xed_inst_t* inst = p->_inst;
267 const unsigned int noperands = xed_inst_noperands(inst);
268 unsigned int i;
269 for( i=0;i<noperands;i++) {
270 const xed_operand_t* o = xed_inst_operand(inst,i);
271 if ((mem_idx == 0 && xed_operand_name(o) == XED_OPERAND_MEM0) ||
272 (mem_idx == 1 && xed_operand_name(o) == XED_OPERAND_MEM1))
273 switch(xed_decoded_inst_operand_action(p,i))
274 {
275 case XED_OPERAND_ACTION_RW:
276 case XED_OPERAND_ACTION_R:
277 case XED_OPERAND_ACTION_RCW:
278 case XED_OPERAND_ACTION_CRW:
279 case XED_OPERAND_ACTION_CR:
280 return 1;
281 default:
282 break;
283 }
284 }
285 return 0;
286
287 }
288
289 xed_bool_t
xed_decoded_inst_mem_written(const xed_decoded_inst_t * p,unsigned int mem_idx)290 xed_decoded_inst_mem_written(const xed_decoded_inst_t* p,
291 unsigned int mem_idx)
292 {
293 const xed_inst_t* inst = p->_inst;
294 const unsigned int noperands = xed_inst_noperands(inst);
295 unsigned int i;
296 for( i=0;i<noperands;i++)
297 {
298 const xed_operand_t* o = xed_inst_operand(inst,i);
299 if ((mem_idx == 0 && xed_operand_name(o) == XED_OPERAND_MEM0) ||
300 (mem_idx == 1 && xed_operand_name(o) == XED_OPERAND_MEM1))
301 switch(xed_decoded_inst_operand_action(p,i))
302 {
303 case XED_OPERAND_ACTION_RW:
304 case XED_OPERAND_ACTION_W:
305 case XED_OPERAND_ACTION_RCW:
306 case XED_OPERAND_ACTION_CRW:
307 case XED_OPERAND_ACTION_CW:
308 return 1;
309 default:
310 break;
311 }
312 }
313 return 0;
314 }
315
316
317 xed_bool_t
xed_decoded_inst_conditionally_writes_registers(const xed_decoded_inst_t * p)318 xed_decoded_inst_conditionally_writes_registers(const xed_decoded_inst_t* p )
319 {
320 const xed_inst_t* inst = p->_inst;
321 const unsigned int noperands = xed_inst_noperands(inst);
322 unsigned int i;
323 for( i=0;i<noperands;i++) {
324 switch(xed_decoded_inst_operand_action(p,i)) {
325 case XED_OPERAND_ACTION_RCW:
326 case XED_OPERAND_ACTION_CW:
327 return 1;
328 default:
329 break;
330 }
331 }
332 return 0;
333 }
334
335 xed_bool_t
xed_decoded_inst_mem_written_only(const xed_decoded_inst_t * p,unsigned int mem_idx)336 xed_decoded_inst_mem_written_only(const xed_decoded_inst_t* p,
337 unsigned int mem_idx)
338 {
339 const xed_inst_t* inst = p->_inst;
340 const unsigned int noperands = xed_inst_noperands(inst);
341 unsigned int i;
342 for( i=0;i<noperands;i++)
343 {
344 const xed_operand_t* o = xed_inst_operand(inst,i);
345
346 if ((mem_idx == 0 && xed_operand_name(o) == XED_OPERAND_MEM0) ||
347 (mem_idx == 1 && xed_operand_name(o) == XED_OPERAND_MEM1))
348 switch(xed_decoded_inst_operand_action(p,i))
349 {
350 case XED_OPERAND_ACTION_W:
351 case XED_OPERAND_ACTION_CW:
352 return 1;
353 default:
354 break;
355 }
356 }
357 return 0;
358 }
359
360
361 static XED_INLINE unsigned int
xed_decoded_inst_get_find_memop(const xed_decoded_inst_t * p,xed_uint_t memop_idx)362 xed_decoded_inst_get_find_memop(const xed_decoded_inst_t* p,
363 xed_uint_t memop_idx) {
364 const xed_inst_t* inst = p->_inst;
365 const unsigned int noperands = xed_inst_noperands(inst);
366 unsigned int i;
367 for( i=0;i<noperands;i++) { //FIXME: slow scan...
368 const xed_operand_t* o = xed_inst_operand(inst,i);
369 const xed_operand_enum_t op_name = xed_operand_name(o);
370 if ((memop_idx == 0 && op_name == XED_OPERAND_MEM0) ||
371 (memop_idx == 1 && op_name == XED_OPERAND_MEM1)) {
372 return i;
373 }
374 }
375 xed_assert(0);
376 return 0;
377 }
378
379 unsigned int
xed_decoded_inst_get_memop_address_width(const xed_decoded_inst_t * p,xed_uint_t memop_idx)380 xed_decoded_inst_get_memop_address_width(const xed_decoded_inst_t* p,
381 xed_uint_t memop_idx) {
382 /* Return the addressing width for memop_idx (0 or 1).
383 *
384 * In 16/32b modes, if the memop is an implicit stack reference, then
385 * use the stack addressing width as the effective address size for
386 * that memop. This DOES NOT include base references that use rSP/rBP
387 * which implicitly have SS as their stack selector (if not
388 * overridden).
389 *
390 * In 64b mode, the effective addressing width of a reference that
391 * would use the stack is 64b.
392 */
393
394 const xed_inst_t* inst = p->_inst;
395 const xed_uint32_t i = xed_decoded_inst_get_find_memop(p,memop_idx);
396 const xed_operand_t* o = xed_inst_operand(inst,i);
397 const xed_operand_width_enum_t width = xed_operand_width(o);
398 xed_uint32_t bits;
399
400 if ( width == XED_OPERAND_WIDTH_SSZ ||
401 width == XED_OPERAND_WIDTH_SPW ||
402 width == XED_OPERAND_WIDTH_SPW2 ||
403 width == XED_OPERAND_WIDTH_SPW3 ||
404 width == XED_OPERAND_WIDTH_SPW8 ) {
405 bits=xed_operand_values_get_stack_address_width(
406 xed_decoded_inst_operands_const(p));
407 }
408 else {
409 bits=xed_operand_values_get_effective_address_width(
410 xed_decoded_inst_operands_const(p));
411 }
412 return bits;
413 }
414
415
416 static XED_INLINE unsigned int
xed_decoded_inst_get_operand_width_bits(const xed_decoded_inst_t * p,const xed_operand_t * o)417 xed_decoded_inst_get_operand_width_bits(const xed_decoded_inst_t* p,
418 const xed_operand_t* o ) {
419 const xed_operand_width_enum_t width = xed_operand_width(o);
420 unsigned int bits=0;
421 if (width == XED_OPERAND_WIDTH_SSZ) {
422 bits=xed_operand_values_get_stack_address_width(
423 xed_decoded_inst_operands_const(p));
424 }
425 else if (width == XED_OPERAND_WIDTH_ASZ) {
426 bits=xed_operand_values_get_effective_address_width(
427 xed_decoded_inst_operands_const(p));
428 }
429 else {
430 const xed_uint32_t eosz = xed3_operand_get_eosz(p);
431 xed_assert(width < XED_OPERAND_WIDTH_LAST);
432 xed_assert(eosz <= 3);
433 bits = xed_width_bits[width][eosz];
434 }
435 return bits;
436 }
437
438
439 static xed_uint32_t
xed_decoded_inst_compute_variable_width(const xed_decoded_inst_t * p,const xed_operand_t * o)440 xed_decoded_inst_compute_variable_width(const xed_decoded_inst_t* p,
441 const xed_operand_t* o) {
442 const xed_uint32_t nelem = xed3_operand_get_nelem(p);
443 const xed_uint32_t element_size = xed3_operand_get_element_size(p);
444 return nelem*element_size;
445 (void)o; // pacify compiler
446 }
447
448
449 unsigned int
xed_decoded_inst_compute_memory_operand_length(const xed_decoded_inst_t * p,unsigned int memop_idx)450 xed_decoded_inst_compute_memory_operand_length(const xed_decoded_inst_t* p,
451 unsigned int memop_idx) {
452 const xed_inst_t* inst = p->_inst;
453 const unsigned int i = xed_decoded_inst_get_find_memop(p, memop_idx);
454 const xed_operand_t* o = xed_inst_operand(inst,i);
455 xed_uint32_t bits = xed_decoded_inst_get_operand_width_bits(p,o);
456 if (bits)
457 return bits>>3;
458 bits = xed_decoded_inst_compute_variable_width(p,o);
459 return bits>>3;
460 }
461
462 // returns bytes
463 unsigned int
xed_decoded_inst_get_memory_operand_length(const xed_decoded_inst_t * p,unsigned int memop_idx)464 xed_decoded_inst_get_memory_operand_length(const xed_decoded_inst_t* p,
465 unsigned int memop_idx)
466 {
467 if (xed_decoded_inst_number_of_memory_operands(p) > memop_idx)
468 return xed_decoded_inst_compute_memory_operand_length(p,memop_idx);
469 return 0;
470 }
471
472 static xed_uint32_t
xed_decoded_inst_operand_length_bits_register(const xed_decoded_inst_t * p,unsigned int operand_index)473 xed_decoded_inst_operand_length_bits_register(
474 const xed_decoded_inst_t* p,
475 unsigned int operand_index)
476 {
477 xed_uint32_t mode = 0;
478 xed_uint_t idx = 0; // default for 16b and 32b
479 const xed_inst_t* inst = p->_inst;
480 const xed_operand_t* o = xed_inst_operand(inst,operand_index);
481 xed_operand_enum_t op_name = xed_operand_name(o);
482
483 xed_reg_enum_t r;
484
485 /* some registers have a special width specified */
486 const xed_operand_width_enum_t width = xed_operand_width(o);
487 if (width != XED_OPERAND_WIDTH_INVALID)
488 return xed_decoded_inst_get_operand_width_bits(p,o);
489
490 r = xed_decoded_inst_get_reg(p,op_name);
491 mode = xed_decoded_inst_get_machine_mode_bits(p);
492 if (mode == 64)
493 idx = 1;
494 return xed_reg_width_bits[r][idx];
495 }
496
497
498 unsigned int
xed_decoded_inst_operand_length_bits(const xed_decoded_inst_t * p,unsigned int operand_index)499 xed_decoded_inst_operand_length_bits(
500 const xed_decoded_inst_t* p,
501 unsigned int operand_index)
502 {
503 const xed_inst_t* inst = p->_inst;
504 const unsigned int noperands = xed_inst_noperands(inst);
505 const xed_operand_t* o = xed_inst_operand(inst,operand_index);
506 xed_operand_enum_t op_name;
507 xed_uint32_t len;
508 if (noperands <= operand_index)
509 return 0;
510
511
512 op_name = xed_operand_name(o);
513 if (xed_operand_template_is_register(o)) {
514 len= xed_decoded_inst_operand_length_bits_register( p,operand_index);
515 return len;
516 }
517 else if (op_name == XED_OPERAND_AGEN) {
518 len=xed_operand_values_get_effective_address_width(
519 xed_decoded_inst_operands_const(p));
520
521 return len;
522 }
523 // MEM0, MEM1,PTR, IMM0, IMM1, and RELBR use the width codes now.
524 // use the "scalable" width codes from the operand template.
525
526 len = xed_decoded_inst_get_operand_width_bits(p,o);
527 if (len)
528 return len;
529
530 // variable width stuff must compute it based on nelem * element_size
531 len = xed_decoded_inst_compute_variable_width(p,o);
532 return len;
533 }
534
xed_decoded_inst_operand_length(const xed_decoded_inst_t * p,unsigned int operand_index)535 unsigned int xed_decoded_inst_operand_length(const xed_decoded_inst_t* p,
536 unsigned int operand_index) {
537 unsigned int bits = xed_decoded_inst_operand_length_bits(p, operand_index);
538 return bits >> 3;
539 }
540
541
542
543 /*******************************************************************/
544
545 // The number of elements in the operand
xed_decoded_inst_operand_elements(const xed_decoded_inst_t * p,unsigned int operand_index)546 unsigned int xed_decoded_inst_operand_elements(const xed_decoded_inst_t* p,
547 unsigned int operand_index)
548 {
549 unsigned int nelem = 1;
550 const xed_inst_t* inst = p->_inst;
551 const unsigned int noperands = xed_inst_noperands(inst);
552 const xed_operand_t* o = xed_inst_operand(inst,operand_index);
553 xed_operand_width_enum_t width;
554 xed_operand_element_xtype_enum_t xtype;
555 const xed_operand_type_info_t* q;
556
557 if ( operand_index >= noperands )
558 return 0;
559
560 width = xed_operand_width(o);
561 if ( width >= XED_OPERAND_WIDTH_LAST)
562 return 0;
563
564 xtype = xed_operand_xtype(o);
565 if ( xtype >= XED_OPERAND_XTYPE_LAST)
566 return 0;
567
568 q = xed_operand_xtype_info+xtype;
569 if (q->bits_per_element) {
570 const xed_uint_t bits =
571 xed_decoded_inst_operand_length_bits(p, operand_index);
572
573 nelem = bits / q->bits_per_element;
574 }
575 else if (q->dtype == XED_OPERAND_ELEMENT_TYPE_STRUCT) {
576 nelem = 1;
577 }
578 else if (q->dtype == XED_OPERAND_ELEMENT_TYPE_VARIABLE) {
579 nelem = xed3_operand_get_nelem(p);
580 }
581 else { // XED_OPERAND_ELEMENT_TYPE_INT, XED_OPERAND_ELEMENT_TYPE_UINT
582 nelem = 1;
583 }
584
585 return nelem;
586 }
587
588 unsigned int
xed_decoded_inst_operand_element_size_bits(const xed_decoded_inst_t * p,unsigned int operand_index)589 xed_decoded_inst_operand_element_size_bits(
590 const xed_decoded_inst_t* p,
591 unsigned int operand_index)
592 {
593
594 unsigned int element_size = 0;
595 const xed_inst_t* inst = p->_inst;
596 const xed_operand_t* o = xed_inst_operand(inst,operand_index);
597 const xed_operand_element_xtype_enum_t xtype = xed_operand_xtype(o);
598 const xed_operand_type_info_t* q;
599 if ( xtype >= XED_OPERAND_XTYPE_LAST)
600 return 0;
601
602 q = xed_operand_xtype_info+xtype;
603 if (q->bits_per_element) {
604 element_size = q->bits_per_element;
605 }
606 else if ( q->dtype == XED_OPERAND_ELEMENT_TYPE_STRUCT ||
607 q->dtype == XED_OPERAND_ELEMENT_TYPE_INT ||
608 q->dtype == XED_OPERAND_ELEMENT_TYPE_UINT ) {
609 element_size = xed_decoded_inst_operand_length_bits(p, operand_index);
610 }
611 else if (q->dtype == XED_OPERAND_ELEMENT_TYPE_VARIABLE) {
612 element_size = xed3_operand_get_element_size(p);
613 }
614 else if (xed_operand_template_is_register(o)) {
615 return xed_decoded_inst_operand_length_bits_register(p, operand_index);
616 }
617 else {
618 // catch all
619 xed_assert(0);
620 }
621 return element_size;
622 }
623
624 xed_operand_element_type_enum_t
xed_decoded_inst_operand_element_type(const xed_decoded_inst_t * p,unsigned int operand_index)625 xed_decoded_inst_operand_element_type(const xed_decoded_inst_t* p,
626 unsigned int operand_index)
627 {
628 xed_operand_element_type_enum_t dtype = XED_OPERAND_ELEMENT_TYPE_INVALID;
629 const xed_inst_t* inst = p->_inst;
630 const unsigned int noperands = xed_inst_noperands(inst);
631 const xed_operand_t* o = xed_inst_operand(inst,operand_index);
632 xed_operand_width_enum_t width;
633 xed_operand_element_xtype_enum_t xtype;
634 if ( operand_index >= noperands )
635 return dtype;
636
637 width = xed_operand_width(o);
638 if ( width >= XED_OPERAND_WIDTH_LAST)
639 return dtype;
640
641 xtype = xed_operand_xtype(o);
642 if ( xtype < XED_OPERAND_XTYPE_LAST) {
643
644 const xed_operand_type_info_t* q = xed_operand_xtype_info+xtype;
645 dtype = q->dtype;
646 /* This is a catch case for the register NTs that do not have
647 type codes. It is not 100% accurate */
648 if (dtype == XED_OPERAND_ELEMENT_TYPE_INVALID)
649 return XED_OPERAND_ELEMENT_TYPE_INT;
650 else if (dtype == XED_OPERAND_ELEMENT_TYPE_VARIABLE)
651 dtype = XED_STATIC_CAST(xed_operand_element_type_enum_t,
652 xed3_operand_get_type(p));
653 }
654 return dtype;
655 }
656
657 /*******************************************************************/
658
659
660 xed_bool_t
xed_decoded_inst_uses_rflags(const xed_decoded_inst_t * q)661 xed_decoded_inst_uses_rflags(const xed_decoded_inst_t* q)
662 {
663 const xed_simple_flag_t* p = xed_decoded_inst_get_rflags_info(q);
664 if (p && xed_simple_flag_get_nflags(p) > 0 )
665 return 1;
666 return 0;
667 }
668
669
670 static xed_uint8_t
xed_decoded_inst__compute_masked_immediate(const xed_decoded_inst_t * p)671 xed_decoded_inst__compute_masked_immediate( const xed_decoded_inst_t* p)
672 {
673 xed_uint8_t imm_byte;
674 xed_uint8_t masked_imm_byte;
675 xed_uint8_t mask = 0x1F;
676 if (xed_operand_values_get_effective_operand_width(p) == 64)
677 mask = 0x3F;
678 xed_assert(xed3_operand_get_imm_width(p) == 8);
679 imm_byte = xed3_operand_get_uimm0(p);
680 masked_imm_byte = imm_byte & mask;
681 return masked_imm_byte;
682 }
683
684 const xed_simple_flag_t*
xed_decoded_inst_get_rflags_info(const xed_decoded_inst_t * q)685 xed_decoded_inst_get_rflags_info(const xed_decoded_inst_t* q)
686 {
687 xed_uint32_t complex_simple_index;
688 const xed_complex_flag_t* p;
689
690 // no flags
691 const xed_inst_t* inst = xed_decoded_inst_inst(q);
692 xed_uint32_t t_index = inst->_flag_info_index;
693 if(t_index == 0)
694 return 0;
695
696 // simple
697
698 if (inst->_flag_complex==0)
699 return xed_flags_simple_table+t_index;
700
701 // complex
702
703 complex_simple_index=0;
704 p = xed_flags_complex_table + t_index;
705 if (p->check_rep)
706 {
707 if (xed_operand_values_has_real_rep(q))
708 complex_simple_index = p->cases[XED_FLAG_CASE_HAS_REP];
709 else
710 complex_simple_index = p->cases[XED_FLAG_CASE_NO_REP];
711 }
712 else if (p->check_imm)
713 {
714 xed_uint8_t masked_imm_byte =
715 xed_decoded_inst__compute_masked_immediate(q);
716
717 if (masked_imm_byte == 0)
718 complex_simple_index = p->cases[XED_FLAG_CASE_IMMED_ZERO];
719 else if (masked_imm_byte == 1)
720 complex_simple_index = p->cases[XED_FLAG_CASE_IMMED_ONE];
721 else
722 complex_simple_index = p->cases[XED_FLAG_CASE_IMMED_OTHER];
723 }
724 else
725 xed_assert(0);
726
727 if (complex_simple_index == 0)
728 return 0;
729 return xed_flags_simple_table+complex_simple_index;
730 }
731
732 xed_bool_t
xed_decoded_inst_is_prefetch(const xed_decoded_inst_t * p)733 xed_decoded_inst_is_prefetch(const xed_decoded_inst_t* p)
734 {
735 return xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_PREFETCH);
736 }
737
738 xed_uint_t
xed_decoded_inst_number_of_memory_operands(const xed_decoded_inst_t * p)739 xed_decoded_inst_number_of_memory_operands(const xed_decoded_inst_t* p) {
740 return (xed3_operand_get_mem0(p) +
741 xed3_operand_get_mem1(p) + xed3_operand_get_agen(p));
742 }
743
744
745
746
747 //////////////////////////////////////////////////////////////////////////
748 // Modifying decoded instructions before re-encoding
749
750
xed_decoded_inst_set_scale(xed_decoded_inst_t * p,xed_uint_t scale)751 void xed_decoded_inst_set_scale(xed_decoded_inst_t* p, xed_uint_t scale) {
752 xed3_operand_set_scale(p,scale);
753 }
xed_decoded_inst_set_memory_displacement(xed_decoded_inst_t * p,xed_int64_t disp,xed_uint_t length_bytes)754 void xed_decoded_inst_set_memory_displacement(xed_decoded_inst_t* p,
755 xed_int64_t disp,
756 xed_uint_t length_bytes) {
757 xed_operand_values_set_memory_displacement(p, disp, length_bytes);
758 }
xed_decoded_inst_set_branch_displacement(xed_decoded_inst_t * p,xed_int32_t disp,xed_uint_t length_bytes)759 void xed_decoded_inst_set_branch_displacement(xed_decoded_inst_t* p,
760 xed_int32_t disp,
761 xed_uint_t length_bytes) {
762 xed_operand_values_set_branch_displacement(p, disp, length_bytes);
763 }
764
xed_decoded_inst_set_immediate_signed(xed_decoded_inst_t * p,xed_int32_t x,xed_uint_t length_bytes)765 void xed_decoded_inst_set_immediate_signed(xed_decoded_inst_t* p,
766 xed_int32_t x,
767 xed_uint_t length_bytes) {
768 xed_operand_values_set_immediate_signed(p, x,length_bytes);
769 }
xed_decoded_inst_set_immediate_unsigned(xed_decoded_inst_t * p,xed_uint64_t x,xed_uint_t length_bytes)770 void xed_decoded_inst_set_immediate_unsigned(xed_decoded_inst_t* p,
771 xed_uint64_t x,
772 xed_uint_t length_bytes) {
773 xed_operand_values_set_immediate_unsigned(p, x,length_bytes);
774 }
775
776 ////////
777
xed_decoded_inst_set_memory_displacement_bits(xed_decoded_inst_t * p,xed_int64_t disp,xed_uint_t length_bits)778 void xed_decoded_inst_set_memory_displacement_bits(xed_decoded_inst_t* p,
779 xed_int64_t disp,
780 xed_uint_t length_bits) {
781 xed_operand_values_set_memory_displacement_bits(p, disp, length_bits);
782 }
xed_decoded_inst_set_branch_displacement_bits(xed_decoded_inst_t * p,xed_int32_t disp,xed_uint_t length_bits)783 void xed_decoded_inst_set_branch_displacement_bits(xed_decoded_inst_t* p,
784 xed_int32_t disp,
785 xed_uint_t length_bits) {
786 xed_operand_values_set_branch_displacement_bits(p, disp, length_bits);
787 }
788
xed_decoded_inst_set_immediate_signed_bits(xed_decoded_inst_t * p,xed_int32_t x,xed_uint_t length_bits)789 void xed_decoded_inst_set_immediate_signed_bits(xed_decoded_inst_t* p,
790 xed_int32_t x,
791 xed_uint_t length_bits) {
792 xed_operand_values_set_immediate_signed_bits(p, x,length_bits);
793 }
xed_decoded_inst_set_immediate_unsigned_bits(xed_decoded_inst_t * p,xed_uint64_t x,xed_uint_t length_bits)794 void xed_decoded_inst_set_immediate_unsigned_bits(xed_decoded_inst_t* p,
795 xed_uint64_t x,
796 xed_uint_t length_bits) {
797 xed_operand_values_set_immediate_unsigned_bits(p, x,length_bits);
798 }
799
800
801 ////////////////////////////////////////////////////////////////////////////
802
803
xed_decoded_inst_get_operand_width(const xed_decoded_inst_t * p)804 xed_uint32_t xed_decoded_inst_get_operand_width(const xed_decoded_inst_t* p) {
805 if (xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_BYTEOP))
806 return 8;
807 return xed_operand_values_get_effective_operand_width(p);
808 }
809
810
811
812 xed_bool_t
xed_decoded_inst_valid_for_chip(xed_decoded_inst_t const * const p,xed_chip_enum_t chip)813 xed_decoded_inst_valid_for_chip(xed_decoded_inst_t const* const p,
814 xed_chip_enum_t chip)
815 {
816 xed_isa_set_enum_t isa_set;
817
818 isa_set = xed_decoded_inst_get_isa_set( p);
819 return xed_isa_set_is_valid_for_chip(isa_set, chip);
820 }
821
822 xed_uint_t
xed_decoded_inst_vector_length_bits(xed_decoded_inst_t const * const p)823 xed_decoded_inst_vector_length_bits(xed_decoded_inst_t const* const p)
824 {
825 xed_uint_t vl_bits=0;
826 #if defined(XED_AVX)
827 xed_uint_t vl_encoded;
828 // only valid for VEX, EVEX (and XOP) instructions.
829 if (xed3_operand_get_vexvalid(p) == 0)
830 return 0;
831
832 /* vl_encoded 0=128,1=256,2=512*/
833 vl_encoded = xed3_operand_get_vl(p);
834
835 /* 0->128, 1->256, 2->512 */
836 vl_bits = 1 << (vl_encoded+7);
837 #endif
838 return vl_bits;
839 (void)p; // pacify (msvs) compiler for noavx builds
840 }
841
842 xed_bool_t
xed_decoded_inst_masked_vector_operation(xed_decoded_inst_t * p)843 xed_decoded_inst_masked_vector_operation(xed_decoded_inst_t* p)
844 {
845 // pre-evex masked operations
846 xed_uint32_t maskop =
847 xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_MASKOP);
848 if (maskop)
849 return 1;
850 // if evex, and not k0, and not mask-as-control, then report it as a
851 // masked operation. Evex operations that mask-as-control are a
852 // different kind of masked operation.
853
854 if (xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_MASKOP_EVEX) &&
855 !xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_MASK_AS_CONTROL))
856 {
857 const xed_uint_t write_mask_operand = 1;
858 const xed_operand_t* op = xed_inst_operand(p->_inst, write_mask_operand);
859 xed_operand_enum_t op_name = xed_operand_name(op);
860 if (op_name == XED_OPERAND_REG0 || op_name == XED_OPERAND_REG1) {
861 xed_reg_enum_t r = xed_decoded_inst_get_reg(p, op_name);
862 if (xed_reg_class(r) == XED_REG_CLASS_MASK) {
863 if (r != XED_REG_K0)
864 return 1;
865 }
866 }
867 }
868
869 return 0;
870 }
871
872
873
874 xed_uint_t
xed_decoded_inst_get_nprefixes(xed_decoded_inst_t * p)875 xed_decoded_inst_get_nprefixes(xed_decoded_inst_t* p) {
876 return xed3_operand_get_nprefixes(p);
877 }
878
xed_decoded_inst_masking(const xed_decoded_inst_t * p)879 xed_bool_t xed_decoded_inst_masking(const xed_decoded_inst_t* p) {
880 #if defined(XED_SUPPORTS_AVX512) || defined(XED_SUPPORTS_KNC)
881 if (xed3_operand_get_mask(p) != 0)
882 return 1;
883 #endif
884 return 0;
885 (void)p; //pacify compiler
886 }
xed_decoded_inst_merging(const xed_decoded_inst_t * p)887 xed_bool_t xed_decoded_inst_merging(const xed_decoded_inst_t* p) {
888 #if defined(XED_SUPPORTS_AVX512) || defined(XED_SUPPORTS_KNC)
889 if (xed3_operand_get_mask(p) != 0)
890 # if defined(XED_SUPPORTS_AVX512)
891 if (xed3_operand_get_zeroing(p) == 0)
892 if (!xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_MASK_AS_CONTROL))
893 return 1;
894 # elif defined(XED_SUPPORTS_KNC)
895 return 1;
896 # endif
897 #endif
898 return 0;
899 (void)p; //pacify compiler
900 }
xed_decoded_inst_zeroing(const xed_decoded_inst_t * p)901 xed_bool_t xed_decoded_inst_zeroing(const xed_decoded_inst_t* p) {
902 #if defined(XED_SUPPORTS_AVX512)
903 if (xed3_operand_get_mask(p) != 0)
904 if (xed3_operand_get_zeroing(p) == 1)
905 return 1;
906 #endif
907 return 0;
908 (void)p; //pacify compiler
909 }
910
911 xed_operand_action_enum_t
xed_decoded_inst_operand_action(const xed_decoded_inst_t * p,unsigned int operand_index)912 xed_decoded_inst_operand_action(const xed_decoded_inst_t* p,
913 unsigned int operand_index)
914 {
915
916 /* For the 0th operand, except for stores and except if attribute MASK_AS_CONTROL
917 RW W <<< SDM/XED notion
918 ===========================================
919 aaa=0 control n/a w
920 aaa=0 merging rw w
921 aaa=0 zeroing n/a n/a
922
923 aaa!=0 control n/a w
924 aaa!=0 merging r+cw r+cw <<< This one requires special handling
925 aaa!=0 zeroing r+w w
926 */
927
928 const xed_inst_t* xi = xed_decoded_inst_inst(p);
929 const xed_operand_t* op = xed_inst_operand(xi,operand_index);
930 xed_operand_action_enum_t rw = xed_operand_rw(op);
931
932 if (operand_index == 0)
933 {
934 if (xed_decoded_inst_masking(p) && xed_decoded_inst_merging(p))
935 {
936 if (rw == XED_OPERAND_ACTION_RW)
937 return XED_OPERAND_ACTION_RCW;
938 //need to filter out stores which do NOT read memory when merging.
939 if (rw == XED_OPERAND_ACTION_W)
940 {
941 const xed_operand_t* zero_op = xed_inst_operand(xi,0);
942 if (xed_operand_name(zero_op) == XED_OPERAND_MEM0)
943 return XED_OPERAND_ACTION_CW;
944 // reflect dest register input dependence when merging
945 return XED_OPERAND_ACTION_RCW;
946 }
947
948 }
949 }
950
951 return rw;
952 }
953
954 xed_bool_t
xed_decoded_inst_uses_embedded_broadcast(const xed_decoded_inst_t * p)955 xed_decoded_inst_uses_embedded_broadcast(const xed_decoded_inst_t* p)
956 {
957 #if defined(XED_SUPPORTS_AVX512)
958 if (xed_decoded_inst_get_attribute(p, XED_ATTRIBUTE_BROADCAST_ENABLED))
959 if (xed3_operand_get_bcast(p))
960 return 1;
961 #endif
962 return 0;
963 (void) p;
964 }
965 xed_bool_t
xed_decoded_inst_is_broadcast_instruction(const xed_decoded_inst_t * p)966 xed_decoded_inst_is_broadcast_instruction(const xed_decoded_inst_t* p)
967 {
968 #if defined(XED_AVX) // also reports AVX512 broadcast instr
969 if (xed_decoded_inst_get_category(p) == XED_CATEGORY_BROADCAST)
970 return 1;
971 #endif
972 return 0;
973 (void) p;
974 }
975 xed_bool_t
xed_decoded_inst_is_broadcast(const xed_decoded_inst_t * p)976 xed_decoded_inst_is_broadcast(const xed_decoded_inst_t* p)
977 {
978 //FIXME: add an enum for the broadcast values so we can give a better answer here
979 if (xed_decoded_inst_is_broadcast_instruction(p))
980 return 1;
981 if (xed_decoded_inst_uses_embedded_broadcast(p))
982 return 1;
983 return 0;
984 }
985