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 /// @file xed-encode.c
19 
20 ////////////////////////////////////////////////////////////////////////////
21 // This file contains the public interface to the encoder.
22 ////////////////////////////////////////////////////////////////////////////
23 #include "xed-internal-header.h"
24 #include "xed-encode-private.h"
25 #include "xed-operand-accessors.h"
26 #include "xed-reg-class.h"
27 
28 #include "xed-encoder.h" // a generated file of prototypes
29 
30 //FIXME just need one proto from the above file: xed_bool_t
31 //xed_encode_nonterminal_ISA_ENCODE(xed_encoder_request_t& xes);
32 
33 
34 const xed_operand_values_t*
xed_encoder_request_operands_const(const xed_encoder_request_t * p)35 xed_encoder_request_operands_const(const xed_encoder_request_t* p) {
36     return p;
37 }
38 xed_operand_values_t*
xed_encoder_request_operands(xed_encoder_request_t * p)39 xed_encoder_request_operands(xed_encoder_request_t* p) {
40     return p;
41 }
42 
43 // Emitting the legacy map bytes.
44 // Need to convert from xed_ild_map_enum_t to the actual bytes.
45 // called from generated code (in OBJDIR/xed-enc-patterns.c)
xed_encoder_request_emit_legacy_map(xed_encoder_request_t * q)46 void xed_encoder_request_emit_legacy_map(xed_encoder_request_t* q)
47 {
48     xed_uint8_t bits;
49     xed_uint16_t value;
50     xed_ild_map_enum_t map;
51     map = XED_STATIC_CAST(xed_ild_map_enum_t,xed_encoder_get_map(q));
52 
53     switch(map) {
54     case XED_ILD_MAP0:
55       return;
56 
57     case XED_ILD_MAP1:
58       value = 0x0F;
59       bits = 8;
60       break;
61 
62     case XED_ILD_MAP2:
63       value = 0x380F; //need to convert big to little endian
64       bits = 16;
65       break;
66 
67     case XED_ILD_MAP3:
68       value = 0x3A0F; //need to convert big to little endian
69       bits = 16;
70       break;
71 
72     case XED_ILD_MAPAMD:
73       value = 0x0F0F;
74       bits = 16;
75       break;
76 
77     default:
78       xed3_operand_set_error(q,XED_ERROR_GENERAL_ERROR);
79       return;
80 
81     }
82     xed_encoder_request_emit_bytes(q,bits,value);
83 }
84 
xed_encoder_request_emit_bytes(xed_encoder_request_t * q,const xed_uint8_t bits,const xed_uint64_t value)85 void xed_encoder_request_emit_bytes(xed_encoder_request_t* q,
86                                    const xed_uint8_t bits,
87                                    const xed_uint64_t value){
88 
89     xed_uint32_t byte_offset;
90     xed_uint8_t* p;
91     xed_uint32_t bit_offset = xed_encoder_request_bit_offset(q);
92 
93     //verify that we are aligned on byte
94     xed_assert((bit_offset & 7) == 0);
95     if ( bit_offset + bits > 8 * xed_encoder_request_ilen(q)) {
96         xed3_operand_set_error(q,XED_ERROR_BUFFER_TOO_SHORT);
97         return;
98     }
99 
100     byte_offset = bit_offset >> 3;
101 
102     xed_encoder_request_update_bit_offset(q, bits);
103     p = q->_byte_array._enc+byte_offset;
104 
105     switch(bits){
106     case 8:
107         *p = XED_STATIC_CAST(xed_uint8_t,value);
108         break;
109     case 16:
110         *XED_REINTERPRET_CAST(xed_uint16_t*,p) =
111                         XED_STATIC_CAST(xed_uint16_t,value);
112         break;
113     case 32:
114         *XED_REINTERPRET_CAST(xed_uint32_t*,p)=
115                         XED_STATIC_CAST(xed_uint32_t,value);
116         break;
117     case 64:
118         *XED_REINTERPRET_CAST(xed_uint64_t*,p)= value;
119         break;
120     default:
121         xed_assert(0);
122     }
123     return;
124 }
125 
126 
xed_encoder_request_encode_emit(xed_encoder_request_t * q,const unsigned int bits,const xed_uint64_t value)127 void xed_encoder_request_encode_emit(xed_encoder_request_t* q,
128                                      const unsigned int bits,
129                                      const xed_uint64_t value) {
130     xed_uint32_t nbits;
131     xed_uint32_t byte_offset;
132     xed_uint32_t bit_in_byte;
133     xed_uint32_t processed_bits;
134     xed_uint32_t t_bit_offset = xed_encoder_request_bit_offset(q);
135     if ( t_bit_offset + bits > 8 * xed_encoder_request_ilen(q)) {
136         xed3_operand_set_error(q,XED_ERROR_BUFFER_TOO_SHORT);
137         return;
138     }
139 
140     nbits = bits;
141     byte_offset = t_bit_offset >> 3;
142     bit_in_byte = t_bit_offset & 7;
143     processed_bits = 0;
144 
145     // looking for multiples of 8 on the input and when we are at natural
146     // byte boundaries in the output.
147     if ((bits&7) == 0 && bit_in_byte == 0)    {
148         xed_uint8_t* p;
149         //int shift;
150 
151         // the value to encode is a multiple of 8 bits and the current bit
152         // pointer is aligned on an 8b boundary, then we can jam in the
153         // bytes efficiently using 8/16/32/64b stores.
154         xed_encoder_request_update_bit_offset(q, bits);
155         p = q->_byte_array._enc+byte_offset;
156 
157         switch(bits)        {
158           case 8:
159             *p = XED_STATIC_CAST(xed_uint8_t,value);
160             break;
161           case 16:
162             *XED_REINTERPRET_CAST(xed_uint16_t*,p) = XED_STATIC_CAST(xed_uint16_t,value);
163             break;
164           case 32:
165             *XED_REINTERPRET_CAST(xed_uint32_t*,p)= XED_STATIC_CAST(xed_uint32_t,value);
166             break;
167           case 64:
168             *XED_REINTERPRET_CAST(xed_uint64_t*,p)= value;
169             break;
170           default:
171             xed_assert(0);
172         }
173         return;
174     }
175 
176     // for inputs that are not multiples of 8-bits:
177     while (nbits > 0) {
178         xed_uint64_t tvalue; // value we'll shift to get to the right bits
179         xed_uint32_t tbits; // # of bits we are taking in this iteraation
180         xed_uint32_t bits_remaining_in_byte = 8 - bit_in_byte;
181 
182 
183         if (bits_remaining_in_byte >= nbits) {
184             // What's left fits in the current byte.
185             tbits  = nbits;
186             nbits  = 0;
187             tvalue = value;
188         }
189         else {
190             xed_uint32_t vshift;
191 
192             // we have more bits than fit in what remains of this
193             // byte. split it up and take just what remains in this byte.
194             tbits  = bits_remaining_in_byte;
195             nbits  = nbits - tbits;
196             vshift = bits - processed_bits - tbits;
197             tvalue = value >> vshift;
198             processed_bits += tbits;
199         }
200 
201         if (tbits == 8)
202             q->_byte_array._enc[byte_offset] = XED_STATIC_CAST(xed_uint8_t,tvalue);
203         else {
204             xed_uint64_t mask;
205             xed_uint32_t shift;
206 
207             // we will be OR'ing bits in to this byte so it had better
208             // start off as zero.
209             if (bit_in_byte == 0)
210                 q->_byte_array._enc[byte_offset] = 0;
211 
212             mask = (1<<tbits)-1;
213             shift = bits_remaining_in_byte - tbits;
214             q->_byte_array._enc[byte_offset] |= XED_STATIC_CAST(xed_uint8_t,(tvalue & mask) << shift);
215         }
216         byte_offset++;
217         bit_in_byte = 0;
218     }
219     xed_encoder_request_update_bit_offset(q,bits);
220 }
221 
222 
223 
224 xed_bool_t
xed_encoder_request__memop_compatible(const xed_encoder_request_t * p,xed_operand_width_enum_t operand_width)225 xed_encoder_request__memop_compatible(const xed_encoder_request_t* p,
226                                       xed_operand_width_enum_t operand_width) {
227     // return 1 if the memop specified in the operand storage is
228     // compatible with the argument operand_width.
229     xed_uint16_t operand_width_bytes;
230     xed_uint16_t request_width_bytes = xed3_operand_get_mem_width(p);
231 
232     // figure out the width, in bytes, of the specified operand
233     xed_uint8_t eosz  = xed3_operand_get_eosz(p);
234     xed_assert(operand_width < XED_OPERAND_WIDTH_LAST);
235     xed_assert(eosz < 4);
236     operand_width_bytes = xed_width_bits[operand_width][eosz]>>3;
237     //variable sized stuff we punt on the width
238     if (operand_width_bytes == 0 || operand_width_bytes == request_width_bytes)
239         return 1;
240     return 0;
241 }
242 
243 
xed_encoder_request_zero_set_mode(xed_encoder_request_t * p,const xed_state_t * dstate)244 void xed_encoder_request_zero_set_mode(xed_encoder_request_t* p,
245                                         const xed_state_t* dstate) {
246     memset(p, 0, sizeof(xed_encoder_request_t));
247     xed_operand_values_set_mode(p,dstate);
248 }
249 
xed_encoder_request_zero(xed_encoder_request_t * p)250 void xed_encoder_request_zero(xed_encoder_request_t* p)    {
251     memset(p, 0, sizeof(xed_encoder_request_t));
252 }
253 
254 xed_iclass_enum_t
xed_encoder_request_get_iclass(const xed_encoder_request_t * p)255 xed_encoder_request_get_iclass( const xed_encoder_request_t* p)
256 {
257     return XED_STATIC_CAST(xed_iclass_enum_t,xed3_operand_get_iclass(p));
258 }
xed_encoder_request_set_iclass(xed_encoder_request_t * p,xed_iclass_enum_t iclass)259 void   xed_encoder_request_set_iclass( xed_encoder_request_t* p,
260                                        xed_iclass_enum_t iclass) {
261     xed3_operand_set_iclass(p,iclass);
262 }
xed_encoder_request_set_repne(xed_encoder_request_t * p)263 void xed_encoder_request_set_repne(xed_encoder_request_t* p) {
264     xed3_operand_set_rep(p,2);
265 }
xed_encoder_request_set_rep(xed_encoder_request_t * p)266 void xed_encoder_request_set_rep(xed_encoder_request_t* p) {
267     xed3_operand_set_rep(p,3);
268 }
xed_encoder_request_clear_rep(xed_encoder_request_t * p)269 void xed_encoder_request_clear_rep(xed_encoder_request_t* p) {
270     xed3_operand_set_rep(p,0);
271 }
272 
273 
274 void
xed_encoder_request_set_effective_operand_width(xed_encoder_request_t * p,xed_uint_t width_bits)275 xed_encoder_request_set_effective_operand_width( xed_encoder_request_t* p,
276                                                  xed_uint_t width_bits) {
277     switch(width_bits) {
278       // x87 memops use the width.
279       case 8:      xed3_operand_set_eosz(p,0); break;
280 
281       case 16:     xed3_operand_set_eosz(p,1); break;
282       case 32:     xed3_operand_set_eosz(p,2); break;
283       case 64:     xed3_operand_set_eosz(p,3); break;
284       default:
285         xed_assert( width_bits == 8 ||
286                     width_bits == 16 ||
287                     width_bits == 32 ||
288                     width_bits == 64 );
289         break;
290     }
291 }
292 void
xed_encoder_request_set_effective_address_size(xed_encoder_request_t * p,xed_uint_t width_bits)293 xed_encoder_request_set_effective_address_size( xed_encoder_request_t* p,
294                                                 xed_uint_t width_bits) {
295     switch(width_bits) {
296       case 16:     xed3_operand_set_easz(p,1); break;
297       case 32:     xed3_operand_set_easz(p,2); break;
298       case 64:     xed3_operand_set_easz(p,3); break;
299       default:
300         xed_assert( width_bits == 16 ||
301                     width_bits == 32 ||
302                     width_bits == 64 );
303         break;
304     }
305 }
306 
xed_encoder_request_set_branch_displacement(xed_encoder_request_t * p,xed_int32_t brdisp,xed_uint_t nbytes)307 void xed_encoder_request_set_branch_displacement(xed_encoder_request_t* p,
308                                                  xed_int32_t brdisp,
309                                                  xed_uint_t nbytes) {
310     xed_operand_values_set_branch_displacement(p, brdisp, nbytes);
311 }
312 
xed_encoder_request_set_relbr(xed_encoder_request_t * p)313 void xed_encoder_request_set_relbr(xed_encoder_request_t* p) {
314     xed3_operand_set_relbr(p,1);
315 }
xed_encoder_request_set_ptr(xed_encoder_request_t * p)316 void xed_encoder_request_set_ptr(xed_encoder_request_t* p) {
317     xed3_operand_set_ptr(p,1);
318 }
319 
xed_encoder_request_set_memory_displacement(xed_encoder_request_t * p,xed_int64_t memdisp,xed_uint_t nbytes)320 void xed_encoder_request_set_memory_displacement(xed_encoder_request_t* p,
321                                                  xed_int64_t memdisp,
322                                                  xed_uint_t nbytes) {
323     xed_operand_values_set_memory_displacement(p, memdisp, nbytes);
324 }
325 
xed_encoder_request_set_uimm0(xed_encoder_request_t * p,xed_uint64_t uimm,xed_uint_t nbytes)326 void xed_encoder_request_set_uimm0(xed_encoder_request_t* p,
327                                    xed_uint64_t uimm,
328                                    xed_uint_t nbytes) {
329     xed_operand_values_set_immediate_unsigned(p, uimm, nbytes);
330     xed3_operand_set_imm0(p,1);
331 }
332 
xed_encoder_request_set_uimm0_bits(xed_encoder_request_t * p,xed_uint64_t uimm,xed_uint_t nbits)333 void xed_encoder_request_set_uimm0_bits(xed_encoder_request_t* p,
334                                         xed_uint64_t uimm,
335                                         xed_uint_t nbits) {
336     xed_operand_values_set_immediate_unsigned_bits(p, uimm, nbits);
337     xed3_operand_set_imm0(p,1);
338 }
xed_encoder_request_set_uimm1(xed_encoder_request_t * p,xed_uint8_t uimm)339 void xed_encoder_request_set_uimm1(xed_encoder_request_t* p,
340                                    xed_uint8_t uimm) {
341     xed3_operand_set_imm1(p,1);
342     xed3_operand_set_uimm1(p,uimm);
343 }
344 
xed_encoder_request_set_simm(xed_encoder_request_t * p,xed_int32_t simm,xed_uint_t nbytes)345 void xed_encoder_request_set_simm(xed_encoder_request_t* p,
346                                   xed_int32_t simm,
347                                   xed_uint_t nbytes) {
348 
349     xed_operand_values_set_immediate_signed(p, simm, nbytes);
350     xed3_operand_set_imm0(p,1);
351 }
352 
xed_encoder_request_set_agen(xed_encoder_request_t * p)353 void xed_encoder_request_set_agen(xed_encoder_request_t* p) {
354     xed3_operand_set_agen(p,1);
355 }
xed_encoder_request_set_mem0(xed_encoder_request_t * p)356 void xed_encoder_request_set_mem0(xed_encoder_request_t* p) {
357     xed3_operand_set_mem0(p,1);
358 }
xed_encoder_request_set_mem1(xed_encoder_request_t * p)359 void xed_encoder_request_set_mem1(xed_encoder_request_t* p) {
360     xed3_operand_set_mem1(p,1);
361 }
xed_encoder_request_set_memory_operand_length(xed_encoder_request_t * p,xed_uint_t nbytes)362 void xed_encoder_request_set_memory_operand_length(xed_encoder_request_t* p,
363                                                    xed_uint_t nbytes) {
364     xed3_operand_set_mem_width(p,nbytes);
365 }
xed_encoder_request_set_seg0(xed_encoder_request_t * p,xed_reg_enum_t seg_reg)366 void xed_encoder_request_set_seg0(xed_encoder_request_t* p,
367                                   xed_reg_enum_t seg_reg) {
368     xed3_operand_set_seg0(p,seg_reg);
369 }
xed_encoder_request_set_seg1(xed_encoder_request_t * p,xed_reg_enum_t seg_reg)370 void xed_encoder_request_set_seg1(xed_encoder_request_t* p,
371                                   xed_reg_enum_t seg_reg) {
372     xed3_operand_set_seg1(p,seg_reg);
373 }
xed_encoder_request_set_base0(xed_encoder_request_t * p,xed_reg_enum_t base_reg)374 void xed_encoder_request_set_base0(xed_encoder_request_t* p,
375                                   xed_reg_enum_t base_reg) {
376     xed3_operand_set_base0(p,base_reg);
377 }
xed_encoder_request_set_base1(xed_encoder_request_t * p,xed_reg_enum_t base_reg)378 void xed_encoder_request_set_base1(xed_encoder_request_t* p,
379                                   xed_reg_enum_t base_reg) {
380     xed3_operand_set_base1(p,base_reg);
381 }
xed_encoder_request_set_index(xed_encoder_request_t * p,xed_reg_enum_t index_reg)382 void xed_encoder_request_set_index(xed_encoder_request_t* p,
383                                   xed_reg_enum_t index_reg) {
384     xed3_operand_set_index(p,index_reg);
385 }
xed_encoder_request_set_scale(xed_encoder_request_t * p,xed_uint_t scale)386 void xed_encoder_request_set_scale(xed_encoder_request_t* p,
387                                    xed_uint_t scale) {
388     xed3_operand_set_scale(p,scale);
389 }
390 
xed_encoder_request_set_operand_order(xed_encoder_request_t * p,xed_uint_t operand_index,xed_operand_enum_t name)391 void xed_encoder_request_set_operand_order(xed_encoder_request_t* p,
392                                            xed_uint_t operand_index,
393                                            xed_operand_enum_t name) {
394     xed_assert(operand_index < XED_ENCODE_ORDER_MAX_OPERANDS);
395     p->_operand_order[operand_index] = name;
396 
397     /* track the maximum number of operands */
398     if (operand_index+1 > p->_n_operand_order)
399         p->_n_operand_order = operand_index + 1;
400 }
401 
402 xed_operand_enum_t
xed_encoder_request_get_operand_order(xed_encoder_request_t * p,xed_uint_t operand_index)403 xed_encoder_request_get_operand_order(xed_encoder_request_t* p,
404                                       xed_uint_t operand_index) {
405     xed_assert(operand_index < XED_ENCODE_ORDER_MAX_OPERANDS &&
406                operand_index < p->_n_operand_order);
407     return XED_STATIC_CAST(xed_operand_enum_t,p->_operand_order[operand_index]);
408 }
409 
410 
xed_encoder_request_zero_operand_order(xed_encoder_request_t * p)411 void xed_encoder_request_zero_operand_order(xed_encoder_request_t* p) {
412     p->_n_operand_order = 0;
413 }
414 
xed_encoder_request_set_reg(xed_encoder_request_t * p,xed_operand_enum_t operand,xed_reg_enum_t reg)415 void xed_encoder_request_set_reg(xed_encoder_request_t* p,
416                                  xed_operand_enum_t operand,
417                                  xed_reg_enum_t reg) {
418     xed_assert(operand < XED_OPERAND_LAST);
419     xed_operand_values_set_operand_reg(p,operand,reg);
420 }
421 
422 void
xed_encode_request_print(const xed_encoder_request_t * p,char * buf,xed_uint_t buflen)423 xed_encode_request_print(const xed_encoder_request_t* p,
424                          char* buf,
425                          xed_uint_t buflen)  {
426     char* t;
427     xed_uint_t i;
428     xed_uint_t blen = buflen;
429     if (buflen < 1000) {
430         (void)xed_strncpy(buf,
431                           "Buffer passed to xed_encode_request_print is "
432                           "too short. Try 1000 bytes",
433                           buflen);
434         return;
435     }
436     blen = xed_strncpy(buf,
437                       xed_iclass_enum_t2str(xed_encoder_request_get_iclass(p)),
438                       blen);
439     blen = xed_strncat(buf, " ",blen);
440     t = buf + xed_strlen(buf);
441     xed_operand_values_print_short( p, t, blen);
442     blen = buflen  - xed_strlen(buf);
443 
444     if (p->_n_operand_order) {
445         blen = xed_strncat(buf,"\nOPERAND ORDER: ",blen);
446         for(i=0;i<p->_n_operand_order;i++) {
447             const char*  s = xed_operand_enum_t2str(XED_STATIC_CAST(xed_operand_enum_t,p->_operand_order[i]));
448             blen = xed_strncat(buf, s, blen);
449             blen = xed_strncat(buf, " ", blen);
450         }
451     }
452     (void) xed_strncat(buf, "\n", blen);
453 }
454 
455 
456 //////////////////////////////////////////////////////////////////////////////////////////////
457 //FIXME: I am not fond of this fixed table, since it is a testament to
458 //how difficult it is to encode instructions. One day, I'll make this
459 //use the XED encoding engine.
460 #define XED_MAX_FIXED_NOPS 9
461 static const xed_uint8_t xed_nop_array[XED_MAX_FIXED_NOPS][XED_MAX_FIXED_NOPS] = {
462     /*1B*/  { 0x90 },
463     /*2B*/  { 0x66, 0x90},
464     /*3B*/  { 0x0F, 0x1F, 0x00},
465     /*4B*/  { 0x0F, 0x1F, 0x40, 0x00},
466     /*5B*/  { 0x0F, 0x1F, 0x44, 0x00, 0x00},
467     /*6B*/  { 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
468     /*7B*/  { 0x0F, 0x1F, 0x80, 0x00, 0x00,0x00, 0x00},
469     /*8B*/  { 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00,0x00, 0x00},
470     /*9B*/  { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00,0x00, 0x00},
471 };
472 
473 XED_DLL_EXPORT xed_error_enum_t
xed_encode_nop(xed_uint8_t * array,const unsigned int ilen)474 xed_encode_nop(xed_uint8_t* array,
475                const unsigned int ilen)
476 {
477     if (ilen >= 1 && ilen <= XED_MAX_FIXED_NOPS)  {
478         // subtract one from the requested length to get the array index.
479         memcpy(array, xed_nop_array[ilen-1], ilen);
480         return XED_ERROR_NONE;
481     }
482     return XED_ERROR_GENERAL_ERROR;
483 }
484 
485 
486 #if defined(XED_AVX) || defined(XED_SUPPORTS_AVX512)
set_vl(xed_reg_enum_t reg,xed_uint_t * vl)487 static void set_vl(xed_reg_enum_t reg, xed_uint_t* vl)
488 {
489     xed_uint_t nvl = *vl;
490     xed_reg_class_enum_t rc = xed_reg_class(reg);
491     // ignore XMM class becaues *vl is either 0 or set by user.
492 
493     if (rc == XED_REG_CLASS_YMM && nvl < 1)
494         nvl = 1;
495 #  if defined(XED_SUPPORTS_AVX512)
496     else if (rc == XED_REG_CLASS_ZMM && nvl < 2)
497         nvl = 2;
498 #  endif
499 
500     *vl = nvl;
501 }
502 
503 
504 // uvl= 0,    1,    2
505 // vl=  012   012   012
506 //      xgg   txt   ttx
507 //
508 // x=match
509 // t=trust
510 // g=grow (using observed guess)
511 
xed_encode_precondition_vl(xed_encoder_request_t * req)512 static void xed_encode_precondition_vl(xed_encoder_request_t* req)
513 {
514     xed_uint_t vl;
515     vl = xed3_operand_get_vl(req);
516     // If user set nonzero value, respect it.  If user set vl=0, we cannot
517     // tell so we try to override.  Note: It would be very wrong to
518     // override incoming nonzero VL values because the observed register
519     // sizes represent a MINIMUM valid VL. The actual VL can be larger for
520     // "shrinking" converts (PD2PS, PD2DQ, PD2UQQ, etc.).
521     if (vl == 0)
522     {
523         xed_operand_enum_t i;
524         xed_reg_enum_t r;
525 
526         r = xed3_operand_get_index(req);
527         // set VL based on index reg if vector reg as it would be for VSIB.
528         set_vl(r,&vl);
529 
530         // set VL based on REG any operands
531         for (i=XED_OPERAND_REG0;i<=XED_OPERAND_REG8;i++)
532         {
533             xed3_get_generic_operand(req, i, &r);
534             if (r == XED_REG_INVALID)
535                 break;
536             set_vl(r,&vl);
537         }
538         xed3_operand_set_vl(req,vl);
539     }
540 }
541 
542 #endif
543 
xed_encode_precondition(xed_encoder_request_t * r)544 static void xed_encode_precondition(xed_encoder_request_t* r) {
545     /* If the base is RIP, then we help the encoder users by adjusting or
546      * supplying a memory displacement. It must be 4B, even if it is zero.
547      *
548      * This ignores the case of a 2B displacement. No one should do that as
549      * it is not legal in 64b mode.
550      */
551     xed_int64_t t;
552     if (xed3_operand_get_base0(r)==XED_REG_RIP) {
553         if (xed3_operand_get_disp_width(r) == 0) {
554             xed3_operand_set_disp_width(r,32);
555             xed3_operand_set_disp(r,0);
556         }
557         else if (xed3_operand_get_disp_width(r) == 8) {
558            xed3_operand_set_disp_width(r,32);
559             /* sign extend the current value to 64b and then pick off the
560              * correct part of it */
561             t = xed3_operand_get_disp(r);
562             xed_operand_values_set_memory_displacement_bits(r,
563                                                             t, 32);
564         }
565     }
566 #if defined(XED_AVX) || defined(XED_SUPPORTS_AVX512)
567     xed_encode_precondition_vl(r);
568 #endif
569 }
570 
xed_encode(xed_encoder_request_t * r,xed_uint8_t * array,const unsigned int ilen,unsigned int * olen)571 XED_DLL_EXPORT xed_error_enum_t xed_encode(xed_encoder_request_t* r,
572                                            xed_uint8_t* array,
573                                            const unsigned int ilen,
574                                            unsigned int* olen) {
575     xed_iclass_enum_t iclass = xed_encoder_request_get_iclass(r);
576     if (iclass != XED_ICLASS_INVALID &&
577         iclass < XED_ICLASS_LAST &&
578         ilen > 0 &&
579         array != 0)
580     {
581         xed_bool_t okay;
582         xed_encoder_vars_t xev;
583         r->_byte_array._enc = array;
584 
585         // FIRST THING: set up the ephemeral storage for the encoder
586         xed_encoder_request_set_encoder_vars(r,&xev);
587 
588         xed_encoder_request_set_ilen(r,ilen);
589         xed_encode_precondition(r);
590         okay = xed_encode_nonterminal_ISA_ENCODE(r);
591 
592         if (okay) {
593             xed_uint32_t t_bit_offset = xed_encoder_request_bit_offset(r);
594             xed_assert((t_bit_offset & 7) == 0); // no partial bytes
595             *olen = (t_bit_offset >> 3); // offset points to the 1st bit of next byte
596             xed_assert(ilen >= *olen);
597             xed_encoder_request_vars_remove(r);
598             return XED_ERROR_NONE;
599         }
600         xed_encoder_request_vars_remove(r);
601         if (xed3_operand_get_error(r) != XED_ERROR_NONE)
602             return xed3_operand_get_error(r);
603         return XED_ERROR_GENERAL_ERROR;
604     }
605     return XED_ERROR_GENERAL_ERROR;
606 }
607 
608 
609 
610 
611