2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_types.h>
22 #define FLAGS_MASK 0x00000cff
26 #define MAKE_1OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * flags) { \
27 addr_t guest_flags = *flags & FLAGS_MASK; \
28 uint8_t tmp_dst = *(uint8_t *)dst; \
38 : "=&q"(tmp_dst),"=q"(guest_flags) \
39 : "1"(guest_flags), "0"(tmp_dst) \
42 *flags &= ~FLAGS_MASK; \
43 *flags |= (guest_flags & FLAGS_MASK); \
44 *(uint8_t *)dst = tmp_dst; \
48 #define MAKE_1OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * flags) { \
49 addr_t guest_flags = *flags & FLAGS_MASK; \
50 uint16_t tmp_dst = *(uint16_t *)dst; \
60 : "=&q"(tmp_dst),"=q"(guest_flags) \
61 : "1"(guest_flags), "0"(tmp_dst) \
64 *flags &= ~FLAGS_MASK; \
65 *flags |= (guest_flags & FLAGS_MASK); \
66 *(uint16_t *)dst = tmp_dst; \
69 #define MAKE_1OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * flags) { \
70 addr_t guest_flags = *flags & FLAGS_MASK; \
71 uint32_t tmp_dst = *(uint32_t *)dst; \
81 : "=&q"(tmp_dst),"=q"(guest_flags) \
82 : "1"(guest_flags), "0"(tmp_dst) \
86 *flags &= ~FLAGS_MASK; \
87 *flags |= (guest_flags & FLAGS_MASK); \
88 *(uint32_t *)dst = tmp_dst; \
91 #define MAKE_1OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * flags) { \
92 addr_t guest_flags = *flags & FLAGS_MASK; \
93 uint64_t tmp_dst = *(uint64_t *)dst; \
103 : "=q"(tmp_dst),"=q"(guest_flags) \
104 : "q"(guest_flags), "0"(tmp_dst) \
108 *flags &= ~FLAGS_MASK; \
109 *flags |= (guest_flags & FLAGS_MASK); \
110 *(uint64_t *)dst = tmp_dst; \
115 #define MAKE_1OP_8_INST(iname) static inline void iname##8(addr_t * dst) { \
116 uint8_t tmp_dst = *(uint8_t *)dst; \
123 *(uint8_t *)dst = tmp_dst; \
126 #define MAKE_1OP_16_INST(iname) static inline void iname##16(addr_t * dst) { \
127 uint16_t tmp_dst = *(uint16_t *)dst; \
134 *(uint16_t *)dst = tmp_dst; \
137 #define MAKE_1OP_32_INST(iname) static inline void iname##32(addr_t * dst) { \
138 uint32_t tmp_dst = *(uint32_t *)dst; \
145 *(uint32_t *)dst = tmp_dst; \
148 #define MAKE_1OP_64_INST(iname) static inline void iname##64(addr_t * dst) { \
149 uint64_t tmp_dst = *(uint64_t *)dst; \
156 *(uint64_t *)dst = tmp_dst; \
160 #define MAKE_2OP_64FLAGS_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src, addr_t * flags) { \
161 addr_t guest_flags = *flags & FLAGS_MASK; \
162 uint64_t tmp_dst = *(uint64_t *)dst; \
168 #iname"q %2, %0\r\n" \
172 : "=&q"(tmp_dst),"=q"(guest_flags) \
173 : "q"(*(uint64_t *)src),"1"(guest_flags), "0"(tmp_dst) \
176 *flags &= ~FLAGS_MASK; \
177 *flags |= (guest_flags & FLAGS_MASK); \
178 *(uint64_t *)dst = tmp_dst; \
184 #define MAKE_2OP_32FLAGS_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src, addr_t * flags) { \
185 addr_t guest_flags = *flags & FLAGS_MASK; \
186 uint32_t tmp_dst = *(uint32_t *)dst; \
196 : "=&q"(tmp_dst),"=q"(guest_flags) \
197 : "q"(*(uint32_t *)src),"1"(guest_flags), "0"(tmp_dst) \
200 *flags &= ~FLAGS_MASK; \
201 *flags |= (guest_flags & FLAGS_MASK); \
202 *(uint32_t *)dst = tmp_dst; \
206 #define MAKE_2OP_16FLAGS_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, addr_t * flags) { \
207 addr_t guest_flags = *flags & FLAGS_MASK; \
208 uint16_t tmp_dst = *(uint16_t *)dst; \
218 : "=&q"(tmp_dst),"=q"(guest_flags) \
219 : "q"(*(uint16_t *)src),"1"(guest_flags), "0"(tmp_dst) \
222 *flags &= ~FLAGS_MASK; \
223 *flags |= (guest_flags & FLAGS_MASK); \
224 *(uint16_t *)dst = tmp_dst; \
227 #define MAKE_2OP_8FLAGS_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, addr_t * flags) { \
228 addr_t guest_flags = *flags & FLAGS_MASK; \
229 uint8_t tmp_dst = *(uint8_t *)dst; \
239 : "=q"(tmp_dst),"=q"(guest_flags) \
240 : "q"(*(uint8_t *)src),"1"(guest_flags), "0"(tmp_dst) \
243 *flags &= ~FLAGS_MASK; \
244 *flags |= (guest_flags & FLAGS_MASK); \
245 *(uint8_t *)dst = tmp_dst; \
252 #define MAKE_2OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
254 addr_t * ecx, addr_t * flags) { \
255 addr_t guest_flags = *flags & FLAGS_MASK; \
256 uint64_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \
267 : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
268 : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \
271 *flags &= ~FLAGS_MASK; \
272 *flags |= (guest_flags & FLAGS_MASK); \
276 #define MAKE_2OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
278 addr_t * ecx, addr_t * flags) { \
279 addr_t guest_flags = *flags & FLAGS_MASK; \
280 uint32_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \
291 : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
292 : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \
295 *flags &= ~FLAGS_MASK; \
296 *flags |= (guest_flags & FLAGS_MASK); \
299 #define MAKE_2OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
301 addr_t * ecx, addr_t * flags) { \
302 addr_t guest_flags = *flags & FLAGS_MASK; \
303 uint16_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \
314 : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
315 : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \
318 *flags &= ~FLAGS_MASK; \
319 *flags |= (guest_flags & FLAGS_MASK); \
324 #define MAKE_2OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
326 addr_t * ecx, addr_t * flags) { \
327 addr_t guest_flags = *flags & FLAGS_MASK; \
328 uint8_t tmp_dst = 0, tmp_ecx = 0, tmp_src = 0; \
339 : "=q"(guest_flags), "=&D"(tmp_dst), "=&S"(tmp_src), "=&c"(tmp_ecx) \
340 : "1"(*dst),"2"(*src),"3"(*ecx),"0"(guest_flags) \
343 *flags &= ~FLAGS_MASK; \
344 *flags |= (guest_flags & FLAGS_MASK); \
350 #define MAKE_1OP_64STR_INST(iname) static inline void iname##64(addr_t * dst, \
352 addr_t * ecx, addr_t * flags) { \
353 addr_t guest_flags = *flags & FLAGS_MASK; \
354 uint64_t tmp_dst = 0, tmp_ecx = 0; \
365 : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
366 : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \
370 *flags &= ~FLAGS_MASK; \
371 *flags |= (guest_flags & FLAGS_MASK); \
375 #define MAKE_1OP_32STR_INST(iname) static inline void iname##32(addr_t * dst, \
377 addr_t * ecx, addr_t * flags) { \
378 addr_t guest_flags = *flags & FLAGS_MASK; \
379 uint32_t tmp_dst = 0, tmp_ecx = 0; \
390 : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
391 : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \
395 *flags &= ~FLAGS_MASK; \
396 *flags |= (guest_flags & FLAGS_MASK); \
399 #define MAKE_1OP_16STR_INST(iname) static inline void iname##16(addr_t * dst, \
401 addr_t * ecx, addr_t * flags) { \
402 addr_t guest_flags = *flags & FLAGS_MASK; \
403 uint16_t tmp_dst = 0, tmp_ecx = 0; \
414 : "=q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
415 : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \
418 *flags &= ~FLAGS_MASK; \
419 *flags |= (guest_flags & FLAGS_MASK); \
424 #define MAKE_1OP_8STR_INST(iname) static inline void iname##8(addr_t * dst, \
426 addr_t * ecx, addr_t * flags) { \
427 /* Some of the flags values are not copied out in a pushf, we save them here */ \
428 addr_t guest_flags = *flags & 0x00000cff; \
429 uint8_t tmp_dst = 0, tmp_ecx = 0; \
440 : "=&q"(guest_flags), "=&D"(tmp_dst), "=&c"(tmp_ecx) \
441 : "1"(*dst),"a"(*src),"2"(*ecx),"0"(guest_flags) \
444 *flags &= ~FLAGS_MASK; \
445 *flags |= (guest_flags & FLAGS_MASK); \
451 #define MAKE_2OP_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
452 uint64_t tmp_dst = *(uint64_t *)dst; \
456 : "q"(*(uint64_t *)src), "0"(tmp_dst) \
459 *(uint64_t *)dst = tmp_dst; \
462 #define MAKE_2OP_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
463 uint32_t tmp_dst = *(uint32_t *)dst; \
467 : "q"(*(uint32_t *)src), "0"(tmp_dst) \
470 *(uint32_t *)dst = tmp_dst; \
473 #define MAKE_2OP_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
474 uint16_t tmp_dst = *(uint16_t *)dst; \
478 : "q"(*(uint16_t *)src), "0"(tmp_dst) \
481 *(uint16_t *)dst = tmp_dst; \
484 #define MAKE_2OP_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
485 uint8_t tmp_dst = *(uint8_t *)dst; \
489 : "q"(*(uint8_t *)src), "0"(tmp_dst) \
492 *(uint8_t *)dst = tmp_dst; \
499 #define MAKE_2OP_8EXT_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src, uint_t dst_len) { \
500 if (dst_len == 2) { \
501 uint16_t tmp_dst = *(uint16_t *)dst; \
505 : "q"(*(uint8_t *)src), "0"(tmp_dst) \
508 *(uint16_t *)dst = tmp_dst; \
509 } else if (dst_len == 4) { \
510 uint32_t tmp_dst = *(uint32_t *)dst; \
514 : "q"(*(uint8_t *)src), "0"(tmp_dst) \
517 *(uint32_t *)dst = tmp_dst; \
518 } else if (dst_len == 8) { \
519 uint64_t tmp_dst = *(uint64_t *)dst; \
523 : "q"(*(uint8_t *)src), "0"(tmp_dst) \
526 *(uint64_t *)dst = tmp_dst; \
530 #define MAKE_2OP_16EXT_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src, uint_t dst_len) { \
531 if (dst_len == 4) { \
532 uint32_t tmp_dst = *(uint32_t *)dst; \
536 : "q"(*(uint16_t *)src), "0"(tmp_dst) \
539 *(uint32_t *)dst = tmp_dst; \
540 } else if (dst_len == 8) { \
541 uint64_t tmp_dst = *(uint64_t *)dst; \
545 : "q"(*(uint16_t *)src), "0"(tmp_dst) \
548 *(uint64_t *)dst = tmp_dst; \
555 #define MAKE_2OUT_64_INST(iname) static inline void iname##64(addr_t * dst, addr_t * src) { \
556 uint64_t tmp_dst = *(uint64_t *)dst; \
557 uint64_t tmp_src = *(uint64_t *)src; \
561 : "=&q"(tmp_dst), "=&q"(tmp_src) \
562 : "0"(tmp_dst), "1"(tmp_src) \
565 *(uint64_t *)src = tmp_src; \
566 *(uint64_t *)dst = tmp_dst; \
569 #define MAKE_2OUT_32_INST(iname) static inline void iname##32(addr_t * dst, addr_t * src) { \
570 uint32_t tmp_dst = *(uint32_t *)dst; \
571 uint32_t tmp_src = *(uint32_t *)src; \
575 : "=&q"(tmp_dst), "=&q"(tmp_src) \
576 : "0"(tmp_dst), "1"(tmp_src) \
579 *(uint32_t *)src = tmp_src; \
580 *(uint32_t *)dst = tmp_dst; \
583 #define MAKE_2OUT_16_INST(iname) static inline void iname##16(addr_t * dst, addr_t * src) { \
584 uint16_t tmp_dst = *(uint16_t *)dst; \
585 uint16_t tmp_src = *(uint16_t *)src; \
589 : "=&q"(tmp_dst), "=&q"(tmp_src) \
590 : "0"(tmp_dst), "1"(tmp_src) \
593 *(uint16_t *)src = tmp_src; \
594 *(uint16_t *)dst = tmp_dst; \
597 #define MAKE_2OUT_8_INST(iname) static inline void iname##8(addr_t * dst, addr_t * src) { \
598 uint8_t tmp_dst = *(uint8_t *)dst; \
599 uint8_t tmp_src = *(uint8_t *)src; \
603 : "=&q"(tmp_dst), "=&q"(tmp_src) \
604 : "0"(tmp_dst), "1"(tmp_src) \
607 *(uint8_t *)src = tmp_src; \
608 *(uint8_t *)dst = tmp_dst; \
616 /****************************/
617 /* 8 Bit instruction forms */
618 /****************************/
620 MAKE_2OP_8FLAGS_INST(adc);
621 MAKE_2OP_8FLAGS_INST(add);
622 MAKE_2OP_8FLAGS_INST(and);
623 MAKE_2OP_8FLAGS_INST(or);
624 MAKE_2OP_8FLAGS_INST(xor);
625 MAKE_2OP_8FLAGS_INST(sub);
628 MAKE_1OP_8FLAGS_INST(inc);
629 MAKE_1OP_8FLAGS_INST(dec);
630 MAKE_1OP_8FLAGS_INST(neg);
631 MAKE_1OP_8FLAGS_INST(setb);
632 MAKE_1OP_8FLAGS_INST(setbe);
633 MAKE_1OP_8FLAGS_INST(setl);
634 MAKE_1OP_8FLAGS_INST(setle);
635 MAKE_1OP_8FLAGS_INST(setnb);
636 MAKE_1OP_8FLAGS_INST(setnbe);
637 MAKE_1OP_8FLAGS_INST(setnl);
638 MAKE_1OP_8FLAGS_INST(setnle);
639 MAKE_1OP_8FLAGS_INST(setno);
640 MAKE_1OP_8FLAGS_INST(setnp);
641 MAKE_1OP_8FLAGS_INST(setns);
642 MAKE_1OP_8FLAGS_INST(setnz);
643 MAKE_1OP_8FLAGS_INST(seto);
644 MAKE_1OP_8FLAGS_INST(setp);
645 MAKE_1OP_8FLAGS_INST(sets);
646 MAKE_1OP_8FLAGS_INST(setz);
649 MAKE_1OP_8_INST(not);
651 MAKE_2OP_8_INST(mov);
652 MAKE_2OP_8EXT_INST(movzx);
653 MAKE_2OP_8EXT_INST(movsx);
655 MAKE_2OUT_8_INST(xchg);
657 MAKE_2OP_8STR_INST(movs);
658 MAKE_1OP_8STR_INST(stos);
659 MAKE_1OP_8STR_INST(scas);
662 /****************************/
663 /* 16 Bit instruction forms */
664 /****************************/
665 MAKE_2OP_16FLAGS_INST(adc);
666 MAKE_2OP_16FLAGS_INST(add);
667 MAKE_2OP_16FLAGS_INST(and);
668 MAKE_2OP_16FLAGS_INST(or);
669 MAKE_2OP_16FLAGS_INST(xor);
670 MAKE_2OP_16FLAGS_INST(sub);
673 MAKE_1OP_16FLAGS_INST(inc);
674 MAKE_1OP_16FLAGS_INST(dec);
675 MAKE_1OP_16FLAGS_INST(neg);
677 MAKE_1OP_16_INST(not);
679 MAKE_2OP_16_INST(mov);
680 MAKE_2OP_16EXT_INST(movzx);
681 MAKE_2OP_16EXT_INST(movsx);
682 MAKE_2OUT_16_INST(xchg);
684 MAKE_2OP_16STR_INST(movs);
685 MAKE_1OP_16STR_INST(stos);
686 MAKE_1OP_16STR_INST(scas);
689 /****************************/
690 /* 32 Bit instruction forms */
691 /****************************/
692 MAKE_2OP_32FLAGS_INST(adc);
693 MAKE_2OP_32FLAGS_INST(add);
694 MAKE_2OP_32FLAGS_INST(and);
695 MAKE_2OP_32FLAGS_INST(or);
696 MAKE_2OP_32FLAGS_INST(xor);
697 MAKE_2OP_32FLAGS_INST(sub);
700 MAKE_1OP_32FLAGS_INST(inc);
701 MAKE_1OP_32FLAGS_INST(dec);
702 MAKE_1OP_32FLAGS_INST(neg);
704 MAKE_1OP_32_INST(not);
706 MAKE_2OP_32_INST(mov);
708 MAKE_2OUT_32_INST(xchg);
712 MAKE_2OP_32STR_INST(movs);
713 MAKE_1OP_32STR_INST(stos);
714 MAKE_1OP_32STR_INST(scas);
720 /****************************/
721 /* 64 Bit instruction forms */
722 /****************************/
723 MAKE_2OP_64FLAGS_INST(adc);
724 MAKE_2OP_64FLAGS_INST(add);
725 MAKE_2OP_64FLAGS_INST(and);
726 MAKE_2OP_64FLAGS_INST(or);
727 MAKE_2OP_64FLAGS_INST(xor);
728 MAKE_2OP_64FLAGS_INST(sub);
730 MAKE_1OP_64FLAGS_INST(inc);
731 MAKE_1OP_64FLAGS_INST(dec);
732 MAKE_1OP_64FLAGS_INST(neg);
734 MAKE_1OP_64_INST(not);
737 MAKE_2OP_64_INST(mov);
738 MAKE_2OP_64STR_INST(movs);
739 MAKE_1OP_64STR_INST(stos);
740 MAKE_1OP_64STR_INST(scas);
742 MAKE_2OUT_64_INST(xchg);