OLD | NEW |
1 /* | 1 /* |
2 * x86 expression handling | 2 * x86 expression handling |
3 * | 3 * |
4 * Copyright (C) 2001-2007 Peter Johnson | 4 * Copyright (C) 2001-2007 Peter Johnson |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' | 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE | 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * POSSIBILITY OF SUCH DAMAGE. | 25 * POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 #include <util.h> | 27 #include <util.h> |
28 /*@unused@*/ RCSID("$Id: x86expr.c 2199 2009-05-10 05:24:46Z peter $"); | |
29 | 28 |
30 #include <libyasm.h> | 29 #include <libyasm.h> |
31 | 30 |
32 #include "x86arch.h" | 31 #include "x86arch.h" |
33 | 32 |
34 | 33 |
35 typedef struct x86_checkea_reg3264_data { | 34 typedef struct x86_checkea_reg3264_data { |
36 int *regs; /* total multiplier for each reg */ | 35 int *regs; /* total multiplier for each reg */ |
| 36 unsigned char vsib_mode; |
37 unsigned char bits; | 37 unsigned char bits; |
38 unsigned char addrsize; | 38 unsigned char addrsize; |
39 } x86_checkea_reg3264_data; | 39 } x86_checkea_reg3264_data; |
40 | 40 |
41 /* Only works if ei->type == EXPR_REG (doesn't check). | 41 /* Only works if ei->type == EXPR_REG (doesn't check). |
42 * Overwrites ei with intnum of 0 (to eliminate regs from the final expr). | 42 * Overwrites ei with intnum of 0 (to eliminate regs from the final expr). |
43 */ | 43 */ |
44 static /*@null@*/ /*@dependent@*/ int * | 44 static /*@null@*/ /*@dependent@*/ int * |
45 x86_expr_checkea_get_reg3264(yasm_expr__item *ei, int *regnum, | 45 x86_expr_checkea_get_reg3264(yasm_expr__item *ei, int *regnum, |
46 /*returned*/ void *d) | 46 /*returned*/ void *d) |
47 { | 47 { |
48 x86_checkea_reg3264_data *data = d; | 48 x86_checkea_reg3264_data *data = d; |
49 | 49 |
50 switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) { | 50 switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) { |
51 case X86_REG32: | 51 case X86_REG32: |
52 if (data->addrsize != 32) | 52 if (data->addrsize != 32) |
53 return 0; | 53 return 0; |
54 *regnum = (unsigned int)(ei->data.reg & 0xF); | 54 *regnum = (unsigned int)(ei->data.reg & 0xF); |
55 break; | 55 break; |
56 case X86_REG64: | 56 case X86_REG64: |
57 if (data->addrsize != 64) | 57 if (data->addrsize != 64) |
58 return 0; | 58 return 0; |
59 *regnum = (unsigned int)(ei->data.reg & 0xF); | 59 *regnum = (unsigned int)(ei->data.reg & 0xF); |
60 break; | 60 break; |
| 61 case X86_XMMREG: |
| 62 if (data->vsib_mode != 1) |
| 63 return 0; |
| 64 if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8) |
| 65 return 0; |
| 66 *regnum = 17+(unsigned int)(ei->data.reg & 0xF); |
| 67 break; |
| 68 case X86_YMMREG: |
| 69 if (data->vsib_mode != 2) |
| 70 return 0; |
| 71 if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8) |
| 72 return 0; |
| 73 *regnum = 17+(unsigned int)(ei->data.reg & 0xF); |
| 74 break; |
61 case X86_RIP: | 75 case X86_RIP: |
62 if (data->bits != 64) | 76 if (data->bits != 64) |
63 return 0; | 77 return 0; |
64 *regnum = 16; | 78 *regnum = 16; |
65 break; | 79 break; |
66 default: | 80 default: |
67 return 0; | 81 return 0; |
68 } | 82 } |
69 | 83 |
70 /* overwrite with 0 to eliminate register from displacement expr */ | 84 /* overwrite with 0 to eliminate register from displacement expr */ |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 /* Must be 32-bit in 16-bit or 32-bit modes. In 64-bit mode, | 613 /* Must be 32-bit in 16-bit or 32-bit modes. In 64-bit mode, |
600 * we don't know unless we look at the registers, except in the | 614 * we don't know unless we look at the registers, except in the |
601 * MemOffs case (see the end of this function). | 615 * MemOffs case (see the end of this function). |
602 */ | 616 */ |
603 if (bits != 64 || (!x86_ea->need_modrm && !x86_ea->need_sib)) { | 617 if (bits != 64 || (!x86_ea->need_modrm && !x86_ea->need_sib)) { |
604 *addrsize = 32; | 618 *addrsize = 32; |
605 break; | 619 break; |
606 } | 620 } |
607 /*@fallthrough@*/ | 621 /*@fallthrough@*/ |
608 default: | 622 default: |
| 623 /* If SIB is required, but we're in 16-bit mode, set to 32. */ |
| 624 if (bits == 16 && x86_ea->need_sib == 1) { |
| 625 *addrsize = 32; |
| 626 break; |
| 627 } |
609 /* check for use of 16 or 32-bit registers; if none are used | 628 /* check for use of 16 or 32-bit registers; if none are used |
610 * default to bits setting. | 629 * default to bits setting. |
611 */ | 630 */ |
612 if (!x86_ea->ea.disp.abs || | 631 if (!x86_ea->ea.disp.abs || |
613 !yasm_expr__traverse_leaves_in(x86_ea->ea.disp.abs, | 632 !yasm_expr__traverse_leaves_in(x86_ea->ea.disp.abs, |
614 addrsize, x86_expr_checkea_getregsize_callback)) | 633 addrsize, x86_expr_checkea_getregsize_callback)) |
615 *addrsize = bits; | 634 *addrsize = bits; |
616 /* TODO: Add optional warning here if switched address size | 635 /* TODO: Add optional warning here if switched address size |
617 * from bits setting just by register use.. eg [ax] in | 636 * from bits setting just by register use.. eg [ax] in |
618 * 32-bit mode would generate a warning. | 637 * 32-bit mode would generate a warning. |
(...skipping 17 matching lines...) Expand all Loading... |
636 REG3264_ESI, | 655 REG3264_ESI, |
637 REG3264_EDI, | 656 REG3264_EDI, |
638 REG64_R8, | 657 REG64_R8, |
639 REG64_R9, | 658 REG64_R9, |
640 REG64_R10, | 659 REG64_R10, |
641 REG64_R11, | 660 REG64_R11, |
642 REG64_R12, | 661 REG64_R12, |
643 REG64_R13, | 662 REG64_R13, |
644 REG64_R14, | 663 REG64_R14, |
645 REG64_R15, | 664 REG64_R15, |
646 REG64_RIP | 665 REG64_RIP, |
| 666 SIMDREGS |
647 } reg3264type; | 667 } reg3264type; |
648 int reg3264mult[17] = {0, 0, 0, 0, 0, 0, 0, 0, | 668 int reg3264mult[33] = |
649 0, 0, 0, 0, 0, 0, 0, 0, 0}; | 669 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 670 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
650 x86_checkea_reg3264_data reg3264_data; | 671 x86_checkea_reg3264_data reg3264_data; |
651 int basereg = REG3264_NONE; /* "base" register (for SIB) */ | 672 int basereg = REG3264_NONE; /* "base" register (for SIB) */ |
652 int indexreg = REG3264_NONE; /* "index" register (for SIB) */ | 673 int indexreg = REG3264_NONE; /* "index" register (for SIB) */ |
| 674 int regcount = 17; /* normally don't check SIMD regs */ |
| 675 |
| 676 if (x86_ea->vsib_mode != 0) |
| 677 regcount = 33; |
653 | 678 |
654 /* We can only do 64-bit addresses in 64-bit mode. */ | 679 /* We can only do 64-bit addresses in 64-bit mode. */ |
655 if (*addrsize == 64 && bits != 64) { | 680 if (*addrsize == 64 && bits != 64) { |
656 yasm_error_set(YASM_ERROR_TYPE, | 681 yasm_error_set(YASM_ERROR_TYPE, |
657 N_("invalid effective address (64-bit in non-64-bit mode)")); | 682 N_("invalid effective address (64-bit in non-64-bit mode)")); |
658 return 1; | 683 return 1; |
659 } | 684 } |
660 | 685 |
661 if (x86_ea->ea.pc_rel && bits != 64) { | 686 if (x86_ea->ea.pc_rel && bits != 64) { |
662 yasm_warn_set(YASM_WARN_GENERAL, | 687 yasm_warn_set(YASM_WARN_GENERAL, |
663 N_("RIP-relative directive ignored in non-64-bit mode")); | 688 N_("RIP-relative directive ignored in non-64-bit mode")); |
664 x86_ea->ea.pc_rel = 0; | 689 x86_ea->ea.pc_rel = 0; |
665 } | 690 } |
666 | 691 |
667 reg3264_data.regs = reg3264mult; | 692 reg3264_data.regs = reg3264mult; |
| 693 reg3264_data.vsib_mode = x86_ea->vsib_mode; |
668 reg3264_data.bits = bits; | 694 reg3264_data.bits = bits; |
669 reg3264_data.addrsize = *addrsize; | 695 reg3264_data.addrsize = *addrsize; |
670 if (x86_ea->ea.disp.abs) { | 696 if (x86_ea->ea.disp.abs) { |
671 int pcrel = 0; | 697 int pcrel = 0; |
672 switch (x86_expr_checkea_getregusage | 698 switch (x86_expr_checkea_getregusage |
673 (&x86_ea->ea.disp.abs, &indexreg, &pcrel, bits, | 699 (&x86_ea->ea.disp.abs, &indexreg, &pcrel, bits, |
674 ®3264_data, x86_expr_checkea_get_reg3264)) { | 700 ®3264_data, x86_expr_checkea_get_reg3264)) { |
675 case 1: | 701 case 1: |
676 yasm_error_set(YASM_ERROR_VALUE, | 702 yasm_error_set(YASM_ERROR_VALUE, |
677 N_("invalid effective address")); | 703 N_("invalid effective address")); |
(...skipping 13 matching lines...) Expand all Loading... |
691 * This is possible because of the way indexreg is found in | 717 * This is possible because of the way indexreg is found in |
692 * expr_checkea_getregusage(). | 718 * expr_checkea_getregusage(). |
693 */ | 719 */ |
694 if (indexreg != REG3264_NONE && reg3264mult[indexreg] == 0) | 720 if (indexreg != REG3264_NONE && reg3264mult[indexreg] == 0) |
695 indexreg = REG3264_NONE; | 721 indexreg = REG3264_NONE; |
696 | 722 |
697 /* Find a basereg (*1, but not indexreg), if there is one. | 723 /* Find a basereg (*1, but not indexreg), if there is one. |
698 * Also, if an indexreg hasn't been assigned, try to find one. | 724 * Also, if an indexreg hasn't been assigned, try to find one. |
699 * Meanwhile, check to make sure there's no negative register mults. | 725 * Meanwhile, check to make sure there's no negative register mults. |
700 */ | 726 */ |
701 for (i=0; i<17; i++) { | 727 for (i=0; i<regcount; i++) { |
702 if (reg3264mult[i] < 0) { | 728 if (reg3264mult[i] < 0) { |
703 yasm_error_set(YASM_ERROR_VALUE, | 729 yasm_error_set(YASM_ERROR_VALUE, |
704 N_("invalid effective address")); | 730 N_("invalid effective address")); |
705 return 1; | 731 return 1; |
706 } | 732 } |
707 if (i != indexreg && reg3264mult[i] == 1 && | 733 if (i != indexreg && reg3264mult[i] == 1 && |
708 basereg == REG3264_NONE) | 734 basereg == REG3264_NONE) |
709 basereg = i; | 735 basereg = i; |
710 else if (indexreg == REG3264_NONE && reg3264mult[i] > 0) | 736 else if (indexreg == REG3264_NONE && reg3264mult[i] > 0) |
711 indexreg = i; | 737 indexreg = i; |
712 } | 738 } |
713 | 739 |
714 /* Handle certain special cases of indexreg mults when basereg is | 740 if (x86_ea->vsib_mode != 0) { |
715 * empty. | 741 /* For VSIB, the SIMD register needs to go into the indexreg. |
716 */ | 742 * Also check basereg (must be a GPR if present) and indexreg |
717 if (indexreg != REG3264_NONE && basereg == REG3264_NONE) | 743 * (must be a SIMD register). |
| 744 */ |
| 745 if (basereg >= SIMDREGS && |
| 746 (indexreg == REG3264_NONE || reg3264mult[indexreg] == 1)) { |
| 747 int temp = basereg; |
| 748 basereg = indexreg; |
| 749 indexreg = temp; |
| 750 } |
| 751 if (basereg >= REG64_RIP || indexreg < SIMDREGS) { |
| 752 yasm_error_set(YASM_ERROR_VALUE, |
| 753 N_("invalid effective address")); |
| 754 return 1; |
| 755 } |
| 756 } else if (indexreg != REG3264_NONE && basereg == REG3264_NONE) |
| 757 /* Handle certain special cases of indexreg mults when basereg is |
| 758 * empty. |
| 759 */ |
718 switch (reg3264mult[indexreg]) { | 760 switch (reg3264mult[indexreg]) { |
719 case 1: | 761 case 1: |
720 /* Only optimize this way if nosplit wasn't specified */ | 762 /* Only optimize this way if nosplit wasn't specified */ |
721 if (!x86_ea->ea.nosplit) { | 763 if (!x86_ea->ea.nosplit) { |
722 basereg = indexreg; | 764 basereg = indexreg; |
723 indexreg = -1; | 765 indexreg = -1; |
724 } | 766 } |
725 break; | 767 break; |
726 case 2: | 768 case 2: |
727 /* Only split if nosplit wasn't specified */ | 769 /* Only split if nosplit wasn't specified */ |
728 if (!x86_ea->ea.nosplit) { | 770 if (!x86_ea->ea.nosplit) { |
729 basereg = indexreg; | 771 basereg = indexreg; |
730 reg3264mult[indexreg] = 1; | 772 reg3264mult[indexreg] = 1; |
731 } | 773 } |
732 break; | 774 break; |
733 case 3: | 775 case 3: |
734 case 5: | 776 case 5: |
735 case 9: | 777 case 9: |
736 basereg = indexreg; | 778 basereg = indexreg; |
737 reg3264mult[indexreg]--; | 779 reg3264mult[indexreg]--; |
738 break; | 780 break; |
739 } | 781 } |
740 | 782 |
741 /* Make sure there's no other registers than the basereg and indexreg | 783 /* Make sure there's no other registers than the basereg and indexreg |
742 * we just found. | 784 * we just found. |
743 */ | 785 */ |
744 for (i=0; i<17; i++) | 786 for (i=0; i<regcount; i++) |
745 if (i != basereg && i != indexreg && reg3264mult[i] != 0) { | 787 if (i != basereg && i != indexreg && reg3264mult[i] != 0) { |
746 yasm_error_set(YASM_ERROR_VALUE, | 788 yasm_error_set(YASM_ERROR_VALUE, |
747 N_("invalid effective address")); | 789 N_("invalid effective address")); |
748 return 1; | 790 return 1; |
749 } | 791 } |
750 | 792 |
751 /* Check the index multiplier value for validity if present. */ | 793 /* Check the index multiplier value for validity if present. */ |
752 if (indexreg != REG3264_NONE && reg3264mult[indexreg] != 1 && | 794 if (indexreg != REG3264_NONE && reg3264mult[indexreg] != 1 && |
753 reg3264mult[indexreg] != 2 && reg3264mult[indexreg] != 4 && | 795 reg3264mult[indexreg] != 2 && reg3264mult[indexreg] != 4 && |
754 reg3264mult[indexreg] != 8) { | 796 reg3264mult[indexreg] != 8) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 X86_REX_B)) | 896 X86_REX_B)) |
855 return 1; | 897 return 1; |
856 x86_ea->sib |= low3; | 898 x86_ea->sib |= low3; |
857 } | 899 } |
858 | 900 |
859 /* Put in indexreg, checking for none case */ | 901 /* Put in indexreg, checking for none case */ |
860 if (indexreg == REG3264_NONE) | 902 if (indexreg == REG3264_NONE) |
861 x86_ea->sib |= 040; | 903 x86_ea->sib |= 040; |
862 /* Any scale field is valid, just leave at 0. */ | 904 /* Any scale field is valid, just leave at 0. */ |
863 else { | 905 else { |
864 if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int) | 906 if (indexreg >= SIMDREGS) { |
865 (X86_REG64 | indexreg), bits, | 907 if (yasm_x86__set_rex_from_reg(rex, &low3, |
866 X86_REX_X)) | 908 (unsigned int)(X86_XMMREG | (indexreg-SIMDREGS)), |
867 return 1; | 909 bits, X86_REX_X)) |
| 910 return 1; |
| 911 } else { |
| 912 if (yasm_x86__set_rex_from_reg(rex, &low3, |
| 913 (unsigned int)(X86_REG64 | indexreg), |
| 914 bits, X86_REX_X)) |
| 915 return 1; |
| 916 } |
868 x86_ea->sib |= low3 << 3; | 917 x86_ea->sib |= low3 << 3; |
869 /* Set scale field, 1 case -> 0, so don't bother. */ | 918 /* Set scale field, 1 case -> 0, so don't bother. */ |
870 switch (reg3264mult[indexreg]) { | 919 switch (reg3264mult[indexreg]) { |
871 case 2: | 920 case 2: |
872 x86_ea->sib |= 0100; | 921 x86_ea->sib |= 0100; |
873 break; | 922 break; |
874 case 4: | 923 case 4: |
875 x86_ea->sib |= 0200; | 924 x86_ea->sib |= 0200; |
876 break; | 925 break; |
877 case 8: | 926 case 8: |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1003 { | 1052 { |
1004 if (!yasm_floatnum_check_size(flt, valsize)) { | 1053 if (!yasm_floatnum_check_size(flt, valsize)) { |
1005 yasm_error_set(YASM_ERROR_FLOATING_POINT, | 1054 yasm_error_set(YASM_ERROR_FLOATING_POINT, |
1006 N_("invalid floating point constant size")); | 1055 N_("invalid floating point constant size")); |
1007 return 1; | 1056 return 1; |
1008 } | 1057 } |
1009 | 1058 |
1010 yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn); | 1059 yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn); |
1011 return 0; | 1060 return 0; |
1012 } | 1061 } |
OLD | NEW |