1 /////////////////////////////////////////////////////////////////////////
2 // $Id: gather.cc 13466 2018-02-16 07:57:32Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //   Copyright (c) 2011-2018 Stanislav Shwartsman
6 //          Written by Stanislav Shwartsman [sshwarts at sourceforge net]
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
21 //
22 /////////////////////////////////////////////////////////////////////////
23 
24 #define NEED_CPU_REG_SHORTCUTS 1
25 #include "bochs.h"
26 #include "cpu.h"
27 #define LOG_THIS BX_CPU_THIS_PTR
28 
29 #if BX_SUPPORT_AVX
30 
BxResolveGatherD(bxInstruction_c * i,unsigned element)31 bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::BxResolveGatherD(bxInstruction_c *i, unsigned element)
32 {
33   Bit32s index = BX_READ_AVX_REG(i->sibIndex()).vmm32s(element);
34 
35   if (i->as64L())
36     return (BX_READ_64BIT_REG(i->sibBase()) + (((Bit64s) index) << i->sibScale()) + i->displ32s());
37   else
38     return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s());
39 }
40 
BxResolveGatherQ(bxInstruction_c * i,unsigned element)41 bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::BxResolveGatherQ(bxInstruction_c *i, unsigned element)
42 {
43   Bit64s index = BX_READ_AVX_REG(i->sibIndex()).vmm64s(element);
44 
45   if (i->as64L())
46     return (BX_READ_64BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s());
47   else
48     return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s());
49 }
50 
VGATHERDPS_VpsHps(bxInstruction_c * i)51 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPS_VpsHps(bxInstruction_c *i)
52 {
53   if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) {
54     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
55     exception(BX_UD_EXCEPTION, 0);
56   }
57 
58   BxPackedYmmRegister *mask = &BX_YMM_REG(i->src2()), *dest = &BX_YMM_REG(i->dst());
59 
60   // index size = 32, element_size = 32, max vector size = 256
61   // num_elements:
62   //     128 bit => 4
63   //     256 bit => 8
64 
65   unsigned n, num_elements = DWORD_ELEMENTS(i->getVL());
66 
67   for (n=0; n < num_elements; n++) {
68     if (mask->ymm32s(n) < 0)
69       mask->ymm32u(n) = 0xffffffff;
70     else
71       mask->ymm32u(n) = 0;
72   }
73 
74 #if BX_SUPPORT_ALIGNMENT_CHECK
75   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
76   BX_CPU_THIS_PTR alignment_check_mask = 0;
77 #endif
78 
79   for (n=0; n < 8; n++)
80   {
81     if (n >= num_elements) {
82         mask->ymm32u(n) = 0;
83         dest->ymm32u(n) = 0;
84         continue;
85     }
86 
87     if (mask->ymm32u(n)) {
88         dest->ymm32u(n) = read_virtual_dword(i->seg(), BxResolveGatherD(i, n));
89     }
90     mask->ymm32u(n) = 0;
91   }
92 
93 #if BX_SUPPORT_ALIGNMENT_CHECK
94   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
95 #endif
96 
97   BX_CLEAR_AVX_HIGH256(i->dst());
98   BX_CLEAR_AVX_HIGH256(i->src2());
99 
100   BX_NEXT_INSTR(i);
101 }
102 
VGATHERQPS_VpsHps(bxInstruction_c * i)103 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPS_VpsHps(bxInstruction_c *i)
104 {
105   if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) {
106     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
107     exception(BX_UD_EXCEPTION, 0);
108   }
109 
110   // index size = 64, element_size = 32, max vector size = 256
111   // num_elements:
112   //     128 bit => 2
113   //     256 bit => 4
114 
115   BxPackedYmmRegister *mask = &BX_YMM_REG(i->src2()), *dest = &BX_YMM_REG(i->dst());
116   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
117 
118   for (n=0; n < num_elements; n++) {
119     if (mask->ymm32s(n) < 0)
120       mask->ymm32u(n) = 0xffffffff;
121     else
122       mask->ymm32u(n) = 0;
123   }
124 
125 #if BX_SUPPORT_ALIGNMENT_CHECK
126   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
127   BX_CPU_THIS_PTR alignment_check_mask = 0;
128 #endif
129 
130   for (n=0; n < 4; n++)
131   {
132     if (n >= num_elements) {
133         mask->ymm32u(n) = 0;
134         dest->ymm32u(n) = 0;
135         continue;
136     }
137 
138     if (mask->ymm32u(n)) {
139         dest->ymm32u(n) = read_virtual_dword(i->seg(), BxResolveGatherQ(i, n));
140     }
141     mask->ymm32u(n) = 0;
142   }
143 
144 #if BX_SUPPORT_ALIGNMENT_CHECK
145   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
146 #endif
147 
148   BX_CLEAR_AVX_HIGH128(i->dst());
149   BX_CLEAR_AVX_HIGH128(i->src2());
150 
151   BX_NEXT_INSTR(i);
152 }
153 
VGATHERDPD_VpdHpd(bxInstruction_c * i)154 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPD_VpdHpd(bxInstruction_c *i)
155 {
156   if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) {
157     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
158     exception(BX_UD_EXCEPTION, 0);
159   }
160 
161   // index size = 32, element_size = 64, max vector size = 256
162   // num_elements:
163   //     128 bit => 2
164   //     256 bit => 4
165 
166   BxPackedYmmRegister *mask = &BX_YMM_REG(i->src2()), *dest = &BX_YMM_REG(i->dst());
167   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
168 
169   for (n=0; n < num_elements; n++) {
170     if (mask->ymm64s(n) < 0)
171       mask->ymm64u(n) = BX_CONST64(0xffffffffffffffff);
172     else
173       mask->ymm64u(n) = 0;
174   }
175 
176 #if BX_SUPPORT_ALIGNMENT_CHECK
177   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
178   BX_CPU_THIS_PTR alignment_check_mask = 0;
179 #endif
180 
181   for (unsigned n=0; n < 4; n++)
182   {
183     if (n >= num_elements) {
184         mask->ymm64u(n) = 0;
185         dest->ymm64u(n) = 0;
186         continue;
187     }
188 
189     if (mask->ymm64u(n)) {
190         dest->ymm64u(n) = read_virtual_qword(i->seg(), BxResolveGatherD(i, n));
191     }
192     mask->ymm64u(n) = 0;
193   }
194 
195 #if BX_SUPPORT_ALIGNMENT_CHECK
196   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
197 #endif
198 
199   BX_CLEAR_AVX_HIGH256(i->dst());
200   BX_CLEAR_AVX_HIGH256(i->src2());
201 
202   BX_NEXT_INSTR(i);
203 }
204 
VGATHERQPD_VpdHpd(bxInstruction_c * i)205 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPD_VpdHpd(bxInstruction_c *i)
206 {
207   if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) {
208     BX_ERROR(("VGATHERQPD_VpdHpd: incorrect source operands"));
209     exception(BX_UD_EXCEPTION, 0);
210   }
211 
212   // index size = 64, element_size = 64, max vector size = 256
213   // num_elements:
214   //     128 bit => 2
215   //     256 bit => 4
216 
217   BxPackedYmmRegister *mask = &BX_YMM_REG(i->src2()), *dest = &BX_YMM_REG(i->dst());
218   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
219 
220   for (n=0; n < num_elements; n++) {
221     if (mask->ymm64s(n) < 0)
222       mask->ymm64u(n) = BX_CONST64(0xffffffffffffffff);
223     else
224       mask->ymm64u(n) = 0;
225   }
226 
227 #if BX_SUPPORT_ALIGNMENT_CHECK
228   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
229   BX_CPU_THIS_PTR alignment_check_mask = 0;
230 #endif
231 
232   for (n=0; n < 4; n++)
233   {
234     if (n >= num_elements) {
235         mask->ymm64u(n) = 0;
236         dest->ymm64u(n) = 0;
237         continue;
238     }
239 
240     if (mask->ymm64u(n)) {
241         dest->ymm64u(n) = read_virtual_qword(i->seg(), BxResolveGatherQ(i, n));
242     }
243     mask->ymm64u(n) = 0;
244   }
245 
246 #if BX_SUPPORT_ALIGNMENT_CHECK
247   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
248 #endif
249 
250   BX_CLEAR_AVX_HIGH256(i->dst());
251   BX_CLEAR_AVX_HIGH256(i->src2());
252 
253   BX_NEXT_INSTR(i);
254 }
255 
256 #if BX_SUPPORT_EVEX
257 
VGATHERDPS_MASK_VpsVSib(bxInstruction_c * i)258 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPS_MASK_VpsVSib(bxInstruction_c *i)
259 {
260   if (i->sibIndex() == i->dst()) {
261     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
262     exception(BX_UD_EXCEPTION, 0);
263   }
264 
265   BxPackedAvxRegister *dest = &BX_AVX_REG(i->dst());
266   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
267 
268   // index size = 32, element_size = 32, max vector size = 512
269   // num_elements:
270   //     128 bit => 4
271   //     256 bit => 8
272   //     512 bit => 16
273 
274   unsigned n, len = i->getVL(), num_elements = DWORD_ELEMENTS(len);
275 
276 #if BX_SUPPORT_ALIGNMENT_CHECK
277   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
278   BX_CPU_THIS_PTR alignment_check_mask = 0;
279 #endif
280 
281   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
282   {
283     if (opmask & mask) {
284       dest->vmm32u(n) = read_virtual_dword(i->seg(), BxResolveGatherD(i, n));
285       opmask &= ~mask;
286       BX_WRITE_OPMASK(i->opmask(), opmask);
287     }
288   }
289 
290 #if BX_SUPPORT_ALIGNMENT_CHECK
291   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
292 #endif
293 
294   BX_WRITE_OPMASK(i->opmask(), 0);
295   BX_CLEAR_AVX_REGZ(i->dst(), len);
296   BX_NEXT_INSTR(i);
297 }
298 
VGATHERQPS_MASK_VpsVSib(bxInstruction_c * i)299 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPS_MASK_VpsVSib(bxInstruction_c *i)
300 {
301   if (i->sibIndex() == i->dst()) {
302     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
303     exception(BX_UD_EXCEPTION, 0);
304   }
305 
306   // index size = 64, element_size = 32, max vector size = 512
307   // num_elements:
308   //     128 bit => 2
309   //     256 bit => 4
310   //     512 bit => 8
311 
312   BxPackedAvxRegister *dest = &BX_AVX_REG(i->dst());
313   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
314 
315   unsigned n, len = i->getVL(), num_elements = QWORD_ELEMENTS(len);
316 
317 #if BX_SUPPORT_ALIGNMENT_CHECK
318   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
319   BX_CPU_THIS_PTR alignment_check_mask = 0;
320 #endif
321 
322   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
323   {
324     if (opmask & mask) {
325       dest->vmm32u(n) = read_virtual_dword(i->seg(), BxResolveGatherQ(i, n));
326       opmask &= ~mask;
327       BX_WRITE_OPMASK(i->opmask(), opmask);
328     }
329   }
330 
331 #if BX_SUPPORT_ALIGNMENT_CHECK
332   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
333 #endif
334 
335   // ensure correct upper part clearing of the destination register
336   if (len == BX_VL128) dest->vmm64u(1) = 0;
337   else len--;
338 
339   BX_WRITE_OPMASK(i->opmask(), 0);
340   BX_CLEAR_AVX_REGZ(i->dst(), len);
341   BX_NEXT_INSTR(i);
342 }
343 
VGATHERDPD_MASK_VpdVSib(bxInstruction_c * i)344 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPD_MASK_VpdVSib(bxInstruction_c *i)
345 {
346   if (i->sibIndex() == i->dst()) {
347     BX_ERROR(("%s: incorrect source operands", i->getIaOpcodeNameShort()));
348     exception(BX_UD_EXCEPTION, 0);
349   }
350 
351   // index size = 32, element_size = 64, max vector size = 512
352   // num_elements:
353   //     128 bit => 2
354   //     256 bit => 4
355   //     512 bit => 8
356 
357   BxPackedAvxRegister *dest = &BX_AVX_REG(i->dst());
358   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
359 
360   unsigned n, len = i->getVL(), num_elements = QWORD_ELEMENTS(len);
361 
362 #if BX_SUPPORT_ALIGNMENT_CHECK
363   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
364   BX_CPU_THIS_PTR alignment_check_mask = 0;
365 #endif
366 
367   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
368   {
369     if (opmask & mask) {
370       dest->vmm64u(n) = read_virtual_qword(i->seg(), BxResolveGatherD(i, n));
371       opmask &= ~mask;
372       BX_WRITE_OPMASK(i->opmask(), opmask);
373     }
374   }
375 
376 #if BX_SUPPORT_ALIGNMENT_CHECK
377   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
378 #endif
379 
380   BX_WRITE_OPMASK(i->opmask(), 0);
381   BX_CLEAR_AVX_REGZ(i->dst(), len);
382   BX_NEXT_INSTR(i);
383 }
384 
VGATHERQPD_MASK_VpdVSib(bxInstruction_c * i)385 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPD_MASK_VpdVSib(bxInstruction_c *i)
386 {
387   if (i->sibIndex() == i->dst()) {
388     BX_ERROR(("VGATHERQPD_VpdHpd: incorrect source operands"));
389     exception(BX_UD_EXCEPTION, 0);
390   }
391 
392   // index size = 64, element_size = 64, max vector size = 512
393   // num_elements:
394   //     128 bit => 2
395   //     256 bit => 4
396   //     512 bit => 8
397 
398   BxPackedAvxRegister *dest = &BX_AVX_REG(i->dst());
399   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
400 
401   unsigned n, len = i->getVL(), num_elements = QWORD_ELEMENTS(len);
402 
403 #if BX_SUPPORT_ALIGNMENT_CHECK
404   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
405   BX_CPU_THIS_PTR alignment_check_mask = 0;
406 #endif
407 
408   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
409   {
410     if (opmask & mask) {
411       dest->vmm64u(n) = read_virtual_qword(i->seg(), BxResolveGatherQ(i, n));
412       opmask &= ~mask;
413       BX_WRITE_OPMASK(i->opmask(), opmask);
414     }
415   }
416 
417 #if BX_SUPPORT_ALIGNMENT_CHECK
418   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
419 #endif
420 
421   BX_WRITE_OPMASK(i->opmask(), 0);
422   BX_CLEAR_AVX_REGZ(i->dst(), len);
423   BX_NEXT_INSTR(i);
424 }
425 
VSCATTERDPS_MASK_VSibVps(bxInstruction_c * i)426 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSCATTERDPS_MASK_VSibVps(bxInstruction_c *i)
427 {
428   BxPackedAvxRegister *src = &BX_AVX_REG(i->src());
429   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
430 
431   // index size = 32, element_size = 32, max vector size = 512
432   // num_elements:
433   //     128 bit => 4
434   //     256 bit => 8
435   //     512 bit => 16
436 
437   unsigned n, num_elements = DWORD_ELEMENTS(i->getVL());
438 
439 #if BX_SUPPORT_ALIGNMENT_CHECK
440   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
441   BX_CPU_THIS_PTR alignment_check_mask = 0;
442 #endif
443 
444   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
445   {
446     if (opmask & mask) {
447       write_virtual_dword(i->seg(), BxResolveGatherD(i, n), src->vmm32u(n));
448       opmask &= ~mask;
449       BX_WRITE_OPMASK(i->opmask(), opmask);
450     }
451   }
452 
453 #if BX_SUPPORT_ALIGNMENT_CHECK
454   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
455 #endif
456 
457   BX_WRITE_OPMASK(i->opmask(), 0);
458   BX_NEXT_INSTR(i);
459 }
460 
VSCATTERQPS_MASK_VSibVps(bxInstruction_c * i)461 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSCATTERQPS_MASK_VSibVps(bxInstruction_c *i)
462 {
463   BxPackedAvxRegister *src = &BX_AVX_REG(i->src());
464   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
465 
466   // index size = 64, element_size = 32, max vector size = 512
467   // num_elements:
468   //     128 bit => 2
469   //     256 bit => 4
470   //     512 bit => 8
471 
472   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
473 
474 #if BX_SUPPORT_ALIGNMENT_CHECK
475   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
476   BX_CPU_THIS_PTR alignment_check_mask = 0;
477 #endif
478 
479   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
480   {
481     if (opmask & mask) {
482       write_virtual_dword(i->seg(), BxResolveGatherQ(i, n), src->vmm32u(n));
483       opmask &= ~mask;
484       BX_WRITE_OPMASK(i->opmask(), opmask);
485     }
486   }
487 
488 #if BX_SUPPORT_ALIGNMENT_CHECK
489   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
490 #endif
491 
492   BX_WRITE_OPMASK(i->opmask(), 0);
493   BX_NEXT_INSTR(i);
494 }
495 
VSCATTERDPD_MASK_VSibVpd(bxInstruction_c * i)496 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSCATTERDPD_MASK_VSibVpd(bxInstruction_c *i)
497 {
498   BxPackedAvxRegister *src = &BX_AVX_REG(i->src());
499   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
500 
501   // index size = 32, element_size = 64, max vector size = 512
502   // num_elements:
503   //     128 bit => 2
504   //     256 bit => 4
505   //     512 bit => 8
506 
507   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
508 
509 #if BX_SUPPORT_ALIGNMENT_CHECK
510   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
511   BX_CPU_THIS_PTR alignment_check_mask = 0;
512 #endif
513 
514   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
515   {
516     if (opmask & mask) {
517       write_virtual_qword(i->seg(), BxResolveGatherD(i, n), src->vmm64u(n));
518       opmask &= ~mask;
519       BX_WRITE_OPMASK(i->opmask(), opmask);
520     }
521   }
522 
523 #if BX_SUPPORT_ALIGNMENT_CHECK
524   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
525 #endif
526 
527   BX_WRITE_OPMASK(i->opmask(), 0);
528   BX_NEXT_INSTR(i);
529 }
530 
VSCATTERQPD_MASK_VSibVpd(bxInstruction_c * i)531 void BX_CPP_AttrRegparmN(1) BX_CPU_C::VSCATTERQPD_MASK_VSibVpd(bxInstruction_c *i)
532 {
533   BxPackedAvxRegister *src = &BX_AVX_REG(i->src());
534   Bit64u opmask = BX_READ_OPMASK(i->opmask()), mask;
535 
536   // index size = 64, element_size = 64, max vector size = 512
537   // num_elements:
538   //     128 bit => 2
539   //     256 bit => 4
540   //     512 bit => 8
541 
542   unsigned n, num_elements = QWORD_ELEMENTS(i->getVL());
543 
544 #if BX_SUPPORT_ALIGNMENT_CHECK
545   unsigned save_alignment_check_mask = BX_CPU_THIS_PTR alignment_check_mask;
546   BX_CPU_THIS_PTR alignment_check_mask = 0;
547 #endif
548 
549   for (n=0, mask = 0x1; n < num_elements; n++, mask <<= 1)
550   {
551     if (opmask & mask) {
552       write_virtual_qword(i->seg(), BxResolveGatherQ(i, n), src->vmm64u(n));
553       opmask &= ~mask;
554       BX_WRITE_OPMASK(i->opmask(), opmask);
555     }
556   }
557 
558 #if BX_SUPPORT_ALIGNMENT_CHECK
559   BX_CPU_THIS_PTR alignment_check_mask = save_alignment_check_mask;
560 #endif
561 
562   BX_WRITE_OPMASK(i->opmask(), 0);
563   BX_NEXT_INSTR(i);
564 }
565 
566 #endif // BX_SUPPORT_EVEX
567 
568 #endif
569