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