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