Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/microblaze/microblaze.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Subroutines used for code generation on Xilinx MicroBlaze. | 1 /* Subroutines used for code generation on Xilinx MicroBlaze. |
2 Copyright (C) 2009-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2009-2018 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Michael Eager <eager@eagercon.com>. | 4 Contributed by Michael Eager <eager@eagercon.com>. |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
16 License for more details. | 16 License for more details. |
17 | 17 |
18 You should have received a copy of the GNU General Public License | 18 You should have received a copy of the GNU General Public License |
19 along with GCC; see the file COPYING3. If not see | 19 along with GCC; see the file COPYING3. If not see |
20 <http://www.gnu.org/licenses/>. */ | 20 <http://www.gnu.org/licenses/>. */ |
21 | |
22 #define IN_TARGET_CODE 1 | |
21 | 23 |
22 #include "config.h" | 24 #include "config.h" |
23 #include "system.h" | 25 #include "system.h" |
24 #include "coretypes.h" | 26 #include "coretypes.h" |
25 #include "backend.h" | 27 #include "backend.h" |
87 ADDRESS_REG_INDEX, | 89 ADDRESS_REG_INDEX, |
88 ADDRESS_CONST_INT, | 90 ADDRESS_CONST_INT, |
89 ADDRESS_SYMBOLIC, | 91 ADDRESS_SYMBOLIC, |
90 ADDRESS_GOTOFF, | 92 ADDRESS_GOTOFF, |
91 ADDRESS_PLT, | 93 ADDRESS_PLT, |
92 ADDRESS_TLS | 94 ADDRESS_TLS, |
95 ADDRESS_SYMBOLIC_TXT_REL | |
93 }; | 96 }; |
94 | 97 |
95 /* Classifies symbols | 98 /* Classifies symbols |
96 | 99 |
97 SYMBOL_TYPE_GENERAL | 100 SYMBOL_TYPE_GENERAL |
213 int break_handler; | 216 int break_handler; |
214 int fast_interrupt; | 217 int fast_interrupt; |
215 int save_volatiles; | 218 int save_volatiles; |
216 | 219 |
217 const struct attribute_spec microblaze_attribute_table[] = { | 220 const struct attribute_spec microblaze_attribute_table[] = { |
218 /* name min_len, max_len, decl_req, type_req, fn_type, req_handler, | 221 /* name min_len, max_len, decl_req, type_req, fn_type_req, |
219 affects_type_identity */ | 222 affects_type_identity, handler, exclude */ |
220 {"interrupt_handler", 0, 0, true, false, false, NULL, | 223 {"interrupt_handler", 0, 0, true, false, false, false, NULL, NULL }, |
221 false }, | 224 {"break_handler", 0, 0, true, false, false, false, NULL, NULL }, |
222 {"break_handler", 0, 0, true, false, false, NULL, | 225 {"fast_interrupt", 0, 0, true, false, false, false, NULL, NULL }, |
223 false }, | 226 {"save_volatiles", 0, 0, true, false, false, false, NULL, NULL }, |
224 {"fast_interrupt", 0, 0, true, false, false, NULL, | 227 { NULL, 0, 0, false, false, false, false, NULL, NULL } |
225 false }, | |
226 {"save_volatiles" , 0, 0, true, false, false, NULL, | |
227 false }, | |
228 { NULL, 0, 0, false, false, false, NULL, | |
229 false } | |
230 }; | 228 }; |
231 | 229 |
232 static int microblaze_interrupt_function_p (tree); | 230 static int microblaze_interrupt_function_p (tree); |
233 | 231 |
234 static void microblaze_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; | 232 static void microblaze_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; |
651 else if (XINT (x, 1) == UNSPEC_TLS) | 649 else if (XINT (x, 1) == UNSPEC_TLS) |
652 { | 650 { |
653 info->type = ADDRESS_TLS; | 651 info->type = ADDRESS_TLS; |
654 info->tls_type = tls_reloc (INTVAL (XVECEXP (x, 0, 1))); | 652 info->tls_type = tls_reloc (INTVAL (XVECEXP (x, 0, 1))); |
655 } | 653 } |
654 else if (XINT (x, 1) == UNSPEC_TEXT) | |
655 { | |
656 info->type = ADDRESS_SYMBOLIC_TXT_REL; | |
657 } | |
656 else | 658 else |
657 { | 659 { |
658 return false; | 660 return false; |
659 } | 661 } |
660 return true; | 662 return true; |
702 | 704 |
703 return base_reg; | 705 return base_reg; |
704 } | 706 } |
705 | 707 |
706 /* Return true if X is a valid address for machine mode MODE. If it is, | 708 /* Return true if X is a valid address for machine mode MODE. If it is, |
707 fill in INFO appropriately. STRICT is true if we should only accept | 709 fill in INFO appropriately. |
708 hard base registers. | 710 STRICT > 0 if we should only accept hard base registers. |
711 STRICT = 2 if the operand address is being printed thus | |
712 function has been called by print_operand_address. | |
709 | 713 |
710 type regA regB offset symbol | 714 type regA regB offset symbol |
711 | 715 |
712 ADDRESS_INVALID NULL NULL NULL NULL | 716 ADDRESS_INVALID NULL NULL NULL NULL |
713 | 717 |
729 microblaze_classify_address (struct microblaze_address_info *info, rtx x, | 733 microblaze_classify_address (struct microblaze_address_info *info, rtx x, |
730 machine_mode mode, int strict) | 734 machine_mode mode, int strict) |
731 { | 735 { |
732 rtx xplus0; | 736 rtx xplus0; |
733 rtx xplus1; | 737 rtx xplus1; |
738 rtx offset; | |
734 | 739 |
735 info->type = ADDRESS_INVALID; | 740 info->type = ADDRESS_INVALID; |
736 info->regA = NULL; | 741 info->regA = NULL; |
737 info->regB = NULL; | 742 info->regB = NULL; |
738 info->offset = NULL; | 743 info->offset = NULL; |
739 info->symbol = NULL; | 744 info->symbol = NULL; |
740 info->symbol_type = SYMBOL_TYPE_INVALID; | 745 info->symbol_type = SYMBOL_TYPE_INVALID; |
746 offset = NULL; | |
741 | 747 |
742 switch (GET_CODE (x)) | 748 switch (GET_CODE (x)) |
743 { | 749 { |
744 case REG: | 750 case REG: |
745 case SUBREG: | 751 case SUBREG: |
796 } | 802 } |
797 | 803 |
798 /* for (plus x const_int) just look at x. */ | 804 /* for (plus x const_int) just look at x. */ |
799 if (GET_CODE (xconst0) == PLUS | 805 if (GET_CODE (xconst0) == PLUS |
800 && GET_CODE (XEXP (xconst0, 1)) == CONST_INT | 806 && GET_CODE (XEXP (xconst0, 1)) == CONST_INT |
801 && SMALL_INT (XEXP (xconst0, 1))) | 807 && (SMALL_INT (XEXP (xconst0, 1)) |
808 || GET_CODE (XEXP (xconst0, 0)) == UNSPEC)) | |
802 { | 809 { |
810 /* Hold CONST_INT Value in offset in case of | |
811 UNSPEC + CONST_INT. */ | |
812 offset = XEXP (xconst0, 1); | |
813 | |
803 /* This is ok as info->symbol is set to xplus1 the full | 814 /* This is ok as info->symbol is set to xplus1 the full |
804 const-expression below. */ | 815 const-expression below. */ |
805 xconst0 = XEXP (xconst0, 0); | 816 xconst0 = XEXP (xconst0, 0); |
806 } | 817 } |
807 | 818 |
813 | 824 |
814 info->type = ADDRESS_SYMBOLIC; | 825 info->type = ADDRESS_SYMBOLIC; |
815 info->symbol = xplus1; | 826 info->symbol = xplus1; |
816 info->symbol_type = SYMBOL_TYPE_GENERAL; | 827 info->symbol_type = SYMBOL_TYPE_GENERAL; |
817 return true; | 828 return true; |
829 } | |
830 | |
831 if (GET_CODE (xconst0) == UNSPEC && TARGET_PIC_DATA_TEXT_REL) | |
832 { | |
833 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) | |
834 return false; | |
835 | |
836 info->offset = offset; | |
837 return microblaze_classify_unspec (info, xconst0); | |
818 } | 838 } |
819 | 839 |
820 /* Not base + symbol || base + UNSPEC. */ | 840 /* Not base + symbol || base + UNSPEC. */ |
821 return false; | 841 return false; |
822 | 842 |
859 return microblaze_classify_unspec (info, XEXP (x, 0)); | 879 return microblaze_classify_unspec (info, XEXP (x, 0)); |
860 } | 880 } |
861 return !(flag_pic && pic_address_needs_scratch (x)); | 881 return !(flag_pic && pic_address_needs_scratch (x)); |
862 } | 882 } |
863 | 883 |
884 /* Avoid error in print_operand_address in case UNSPEC | |
885 is removed from SYMBOL or LABEL REFS during optimization. */ | |
886 if ((GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) | |
887 && flag_pic && TARGET_PIC_DATA_TEXT_REL && strict == 2) | |
888 { | |
889 info->type = ADDRESS_SYMBOLIC_TXT_REL; | |
890 return true; | |
891 } | |
892 | |
864 if (flag_pic == 2) | 893 if (flag_pic == 2) |
865 return false; | 894 return false; |
866 else if (microblaze_tls_symbol_p(x)) | 895 else if (microblaze_tls_symbol_p(x)) |
867 return false; | 896 return false; |
868 | 897 |
894 struct microblaze_address_info addr; | 923 struct microblaze_address_info addr; |
895 | 924 |
896 return microblaze_classify_address (&addr, x, mode, strict); | 925 return microblaze_classify_address (&addr, x, mode, strict); |
897 } | 926 } |
898 | 927 |
928 bool | |
929 microblaze_constant_address_p (rtx x) | |
930 { | |
931 return ((GET_CODE (x) == LABEL_REF) || (GET_CODE (x) == SYMBOL_REF) | |
932 || GET_CODE (x) == CONST_INT | |
933 || (GET_CODE (x) == CONST | |
934 && ! (flag_pic && pic_address_needs_scratch (x)))); | |
935 } | |
936 | |
899 int | 937 int |
900 microblaze_valid_pic_const (rtx x) | 938 microblaze_valid_pic_const (rtx x) |
901 { | 939 { |
902 switch (GET_CODE (x)) | 940 switch (GET_CODE (x)) |
903 { | 941 { |
911 } | 949 } |
912 | 950 |
913 int | 951 int |
914 microblaze_legitimate_pic_operand (rtx x) | 952 microblaze_legitimate_pic_operand (rtx x) |
915 { | 953 { |
916 if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x))) | 954 if (flag_pic == 2 && (symbol_mentioned_p (x) || label_mentioned_p (x)) |
955 && !(TARGET_PIC_DATA_TEXT_REL && call_insn_operand (x,VOIDmode))) | |
917 return 0; | 956 return 0; |
918 | 957 |
919 if (microblaze_tls_referenced_p(x)) | 958 if (microblaze_tls_referenced_p(x)) |
920 return 0; | 959 return 0; |
921 | 960 |
1025 | 1064 |
1026 return result; | 1065 return result; |
1027 } | 1066 } |
1028 else if (flag_pic == 2) | 1067 else if (flag_pic == 2) |
1029 { | 1068 { |
1030 rtx pic_ref, reg; | 1069 if (!TARGET_PIC_DATA_TEXT_REL) |
1031 reg = gen_reg_rtx (Pmode); | 1070 { |
1032 | 1071 rtx pic_ref, reg; |
1033 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), | 1072 reg = gen_reg_rtx (Pmode); |
1034 UNSPEC_GOTOFF); | 1073 |
1035 pic_ref = gen_rtx_CONST (Pmode, pic_ref); | 1074 pic_ref = gen_rtx_UNSPEC (Pmode, |
1036 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); | 1075 gen_rtvec (1, xplus1), |
1037 pic_ref = gen_const_mem (Pmode, pic_ref); | 1076 UNSPEC_GOTOFF); |
1038 emit_move_insn (reg, pic_ref); | 1077 pic_ref = gen_rtx_CONST (Pmode, pic_ref); |
1039 result = gen_rtx_PLUS (Pmode, xplus0, reg); | 1078 pic_ref = gen_rtx_PLUS (Pmode, |
1040 return result; | 1079 pic_offset_table_rtx, pic_ref); |
1080 pic_ref = gen_const_mem (Pmode, pic_ref); | |
1081 emit_move_insn (reg, pic_ref); | |
1082 result = gen_rtx_PLUS (Pmode, xplus0, reg); | |
1083 return result; | |
1084 } | |
1085 else | |
1086 { | |
1087 rtx pic_ref, reg; | |
1088 reg = gen_reg_rtx (Pmode); | |
1089 pic_ref = gen_rtx_UNSPEC (Pmode, | |
1090 gen_rtvec (1, xplus1), | |
1091 UNSPEC_TEXT); | |
1092 pic_ref = gen_rtx_CONST (Pmode, pic_ref); | |
1093 emit_insn (gen_addsi3 (reg, | |
1094 pic_offset_table_rtx, xplus0)); | |
1095 result = gen_rtx_PLUS (Pmode, reg, pic_ref); | |
1096 return result; | |
1097 } | |
1041 } | 1098 } |
1042 } | 1099 } |
1043 } | 1100 } |
1044 } | 1101 } |
1045 | 1102 |
1048 rtx reg; | 1105 rtx reg; |
1049 if (microblaze_tls_symbol_p(xinsn)) | 1106 if (microblaze_tls_symbol_p(xinsn)) |
1050 { | 1107 { |
1051 reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX); | 1108 reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX); |
1052 } | 1109 } |
1053 else | 1110 else if (flag_pic == 2) |
1054 { | 1111 { |
1055 rtx pic_ref; | 1112 if (reload_in_progress) |
1056 | 1113 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); |
1057 if (reload_in_progress) | 1114 |
1058 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); | 1115 if (!TARGET_PIC_DATA_TEXT_REL) |
1059 | 1116 { |
1060 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF); | 1117 rtx pic_ref; |
1061 pic_ref = gen_rtx_CONST (Pmode, pic_ref); | 1118 |
1062 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); | 1119 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF); |
1063 pic_ref = gen_const_mem (Pmode, pic_ref); | 1120 pic_ref = gen_rtx_CONST (Pmode, pic_ref); |
1064 reg = pic_ref; | 1121 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); |
1065 } | 1122 pic_ref = gen_const_mem (Pmode, pic_ref); |
1123 reg = pic_ref; | |
1124 } | |
1125 else | |
1126 { | |
1127 rtx pic_ref; | |
1128 | |
1129 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_TEXT); | |
1130 pic_ref = gen_rtx_CONST (Pmode, pic_ref); | |
1131 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); | |
1132 reg = pic_ref; | |
1133 } | |
1134 } | |
1066 return reg; | 1135 return reg; |
1067 } | 1136 } |
1068 | 1137 |
1069 return x; | 1138 return x; |
1070 } | 1139 } |
1389 else | 1458 else |
1390 return 2; | 1459 return 2; |
1391 case ADDRESS_REG_INDEX: | 1460 case ADDRESS_REG_INDEX: |
1392 return 1; | 1461 return 1; |
1393 case ADDRESS_SYMBOLIC: | 1462 case ADDRESS_SYMBOLIC: |
1463 case ADDRESS_SYMBOLIC_TXT_REL: | |
1394 case ADDRESS_GOTOFF: | 1464 case ADDRESS_GOTOFF: |
1395 return 2; | 1465 return 2; |
1396 case ADDRESS_TLS: | 1466 case ADDRESS_TLS: |
1397 switch (addr.tls_type) | 1467 switch (addr.tls_type) |
1398 { | 1468 { |
2067 if ((args_size == 0) && cfun->calls_alloca) | 2137 if ((args_size == 0) && cfun->calls_alloca) |
2068 args_size = NUM_OF_ARGS * UNITS_PER_WORD; | 2138 args_size = NUM_OF_ARGS * UNITS_PER_WORD; |
2069 | 2139 |
2070 total_size = var_size + args_size; | 2140 total_size = var_size + args_size; |
2071 | 2141 |
2072 if (flag_pic == 2) | 2142 if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL) |
2073 /* force setting GOT. */ | 2143 /* force setting GOT. */ |
2074 df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true); | 2144 df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true); |
2075 | 2145 |
2076 /* Calculate space needed for gp registers. */ | 2146 /* Calculate space needed for gp registers. */ |
2077 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) | 2147 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) |
2323 switch (info.type) | 2393 switch (info.type) |
2324 { | 2394 { |
2325 case ADDRESS_REG: | 2395 case ADDRESS_REG: |
2326 case ADDRESS_CONST_INT: | 2396 case ADDRESS_CONST_INT: |
2327 case ADDRESS_SYMBOLIC: | 2397 case ADDRESS_SYMBOLIC: |
2398 case ADDRESS_SYMBOLIC_TXT_REL: | |
2328 case ADDRESS_GOTOFF: | 2399 case ADDRESS_GOTOFF: |
2329 case ADDRESS_TLS: | 2400 case ADDRESS_TLS: |
2330 fputs ("i", file); | 2401 fputs ("i", file); |
2331 break; | 2402 break; |
2332 case ADDRESS_REG_INDEX: | 2403 case ADDRESS_REG_INDEX: |
2490 void | 2561 void |
2491 print_operand_address (FILE * file, rtx addr) | 2562 print_operand_address (FILE * file, rtx addr) |
2492 { | 2563 { |
2493 struct microblaze_address_info info; | 2564 struct microblaze_address_info info; |
2494 enum microblaze_address_type type; | 2565 enum microblaze_address_type type; |
2495 if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1)) | 2566 if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 2)) |
2496 fatal_insn ("insn contains an invalid address !", addr); | 2567 fatal_insn ("insn contains an invalid address !", addr); |
2497 | 2568 |
2498 type = info.type; | 2569 type = info.type; |
2499 switch (info.type) | 2570 switch (info.type) |
2500 { | 2571 { |
2516 case ADDRESS_CONST_INT: | 2587 case ADDRESS_CONST_INT: |
2517 fprintf (file, "%s,", reg_names[REGNO (info.regA)]); | 2588 fprintf (file, "%s,", reg_names[REGNO (info.regA)]); |
2518 output_addr_const (file, info.offset); | 2589 output_addr_const (file, info.offset); |
2519 break; | 2590 break; |
2520 case ADDRESS_SYMBOLIC: | 2591 case ADDRESS_SYMBOLIC: |
2592 case ADDRESS_SYMBOLIC_TXT_REL: | |
2521 case ADDRESS_GOTOFF: | 2593 case ADDRESS_GOTOFF: |
2522 case ADDRESS_PLT: | 2594 case ADDRESS_PLT: |
2523 case ADDRESS_TLS: | 2595 case ADDRESS_TLS: |
2524 if (info.regA) | 2596 if (info.regA) |
2525 fprintf (file, "%s,", reg_names[REGNO (info.regA)]); | 2597 fprintf (file, "%s,", reg_names[REGNO (info.regA)]); |
2530 } | 2602 } |
2531 else if (type == ADDRESS_PLT) | 2603 else if (type == ADDRESS_PLT) |
2532 { | 2604 { |
2533 fputs ("@PLT", file); | 2605 fputs ("@PLT", file); |
2534 } | 2606 } |
2607 else if (type == ADDRESS_SYMBOLIC_TXT_REL) | |
2608 { | |
2609 if (info.offset != NULL && CONST_INT_P (info.offset) | |
2610 && INTVAL (info.offset) > 0) | |
2611 { | |
2612 fprintf (file, "+"); | |
2613 output_addr_const (file, info.offset); | |
2614 } | |
2615 fputs ("@TXTREL", file); | |
2616 } | |
2535 else if (type == ADDRESS_TLS) | 2617 else if (type == ADDRESS_TLS) |
2536 { | 2618 { |
2537 switch (info.tls_type) | 2619 switch (info.tls_type) |
2538 { | 2620 { |
2539 case TLS_GD: | 2621 case TLS_GD: |
2724 (reg_names[(frame_pointer_needed) | 2806 (reg_names[(frame_pointer_needed) |
2725 ? HARD_FRAME_POINTER_REGNUM : | 2807 ? HARD_FRAME_POINTER_REGNUM : |
2726 STACK_POINTER_REGNUM]), fsiz, | 2808 STACK_POINTER_REGNUM]), fsiz, |
2727 reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST], | 2809 reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST], |
2728 current_frame_info.var_size, current_frame_info.num_gp, | 2810 current_frame_info.var_size, current_frame_info.num_gp, |
2729 crtl->outgoing_args_size); | 2811 (int) crtl->outgoing_args_size); |
2730 fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask); | 2812 fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask); |
2731 } | 2813 } |
2732 } | 2814 } |
2733 | 2815 |
2734 /* Output extra assembler code at the end of a prologue. */ | 2816 /* Output extra assembler code at the end of a prologue. */ |
2889 fsiz = compute_frame_size (get_frame_size ()); | 2971 fsiz = compute_frame_size (get_frame_size ()); |
2890 | 2972 |
2891 if (flag_stack_usage_info) | 2973 if (flag_stack_usage_info) |
2892 current_function_static_stack_size = fsiz; | 2974 current_function_static_stack_size = fsiz; |
2893 | 2975 |
2894 | |
2895 /* If this function is a varargs function, store any registers that | 2976 /* If this function is a varargs function, store any registers that |
2896 would normally hold arguments ($5 - $10) on the stack. */ | 2977 would normally hold arguments ($5 - $10) on the stack. */ |
2897 if (((TYPE_ARG_TYPES (fntype) != 0 | 2978 if (((TYPE_ARG_TYPES (fntype) != 0 |
2898 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) | 2979 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) |
2899 != void_type_node)) | 2980 != void_type_node)) |
2914 emit_move_insn (gen_rtx_MEM (SImode, ptr), | 2995 emit_move_insn (gen_rtx_MEM (SImode, ptr), |
2915 gen_rtx_REG (SImode, regno)); | 2996 gen_rtx_REG (SImode, regno)); |
2916 | 2997 |
2917 offset += GET_MODE_SIZE (SImode); | 2998 offset += GET_MODE_SIZE (SImode); |
2918 } | 2999 } |
2919 | |
2920 } | 3000 } |
2921 | 3001 |
2922 if (fsiz > 0) | 3002 if (fsiz > 0) |
2923 { | 3003 { |
2924 rtx fsiz_rtx = GEN_INT (fsiz); | 3004 rtx fsiz_rtx = GEN_INT (fsiz); |
2961 } | 3041 } |
2962 | 3042 |
2963 if ((flag_pic == 2 || TLS_NEEDS_GOT ) | 3043 if ((flag_pic == 2 || TLS_NEEDS_GOT ) |
2964 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM)) | 3044 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM)) |
2965 { | 3045 { |
2966 SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); | 3046 if ((flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL) || TLS_NEEDS_GOT) |
2967 emit_insn (gen_set_got (pic_offset_table_rtx)); /* setting GOT. */ | 3047 { |
3048 SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); | |
3049 /* setting GOT. */ | |
3050 emit_insn (gen_set_got (pic_offset_table_rtx)); | |
3051 } | |
3052 else | |
3053 { | |
3054 SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); | |
3055 /* setting start of text. */ | |
3056 emit_insn (gen_set_text (pic_offset_table_rtx)); | |
3057 } | |
2968 } | 3058 } |
2969 | 3059 |
2970 /* If we are profiling, make sure no instructions are scheduled before | 3060 /* If we are profiling, make sure no instructions are scheduled before |
2971 the call to mcount. */ | 3061 the call to mcount. */ |
2972 | 3062 |
3155 size = int_size_in_bytes (TREE_TYPE (decl)); | 3245 size = int_size_in_bytes (TREE_TYPE (decl)); |
3156 | 3246 |
3157 return (size > 0 && size <= microblaze_section_threshold); | 3247 return (size > 0 && size <= microblaze_section_threshold); |
3158 } | 3248 } |
3159 | 3249 |
3250 /* We need to disable address diff vectors in | |
3251 case of pic data text relative mode. */ | |
3252 | |
3253 static bool | |
3254 microblaze_gen_pic_addr_dif_vec (void) | |
3255 { | |
3256 return (flag_pic && !TARGET_PIC_DATA_TEXT_REL); | |
3257 } | |
3160 | 3258 |
3161 static section * | 3259 static section * |
3162 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) | 3260 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) |
3163 { | 3261 { |
3164 switch (categorize_decl_for_section (decl, reloc)) | 3262 switch (categorize_decl_for_section (decl, reloc)) |
3188 | 3286 |
3189 static rtx | 3287 static rtx |
3190 expand_pic_symbol_ref (machine_mode mode ATTRIBUTE_UNUSED, rtx op) | 3288 expand_pic_symbol_ref (machine_mode mode ATTRIBUTE_UNUSED, rtx op) |
3191 { | 3289 { |
3192 rtx result; | 3290 rtx result; |
3193 result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF); | 3291 bool isFunc = (GET_CODE (op) == SYMBOL_REF |
3292 && (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCTION)); | |
3293 result = (!TARGET_PIC_DATA_TEXT_REL) | |
3294 ? gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF) | |
3295 : gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_TEXT); | |
3194 result = gen_rtx_CONST (Pmode, result); | 3296 result = gen_rtx_CONST (Pmode, result); |
3195 result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); | 3297 result = (TARGET_PIC_DATA_TEXT_REL && isFunc) |
3196 result = gen_const_mem (Pmode, result); | 3298 ? gen_rtx_PLUS (Pmode, gen_raw_REG (Pmode, |
3299 get_base_reg (op)), result) | |
3300 : gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); | |
3301 result = (!TARGET_PIC_DATA_TEXT_REL) | |
3302 ? gen_const_mem (Pmode, result) : result; | |
3303 | |
3197 return result; | 3304 return result; |
3198 } | 3305 } |
3199 | 3306 |
3200 static void | 3307 static void |
3201 microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, | 3308 microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, |
3295 else if (flag_pic) | 3402 else if (flag_pic) |
3296 { | 3403 { |
3297 if (reload_in_progress) | 3404 if (reload_in_progress) |
3298 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); | 3405 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); |
3299 result = expand_pic_symbol_ref (mode, op1); | 3406 result = expand_pic_symbol_ref (mode, op1); |
3407 | |
3408 if (TARGET_PIC_DATA_TEXT_REL && GET_CODE (op0) == REG | |
3409 && REGNO (op0) >= FIRST_PSEUDO_REGISTER) | |
3410 result = force_reg (SImode, result); | |
3411 | |
3300 emit_move_insn (op0, result); | 3412 emit_move_insn (op0, result); |
3413 return true; | |
3414 } | |
3415 } | |
3416 if (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1,1)) == CONST) | |
3417 { | |
3418 rtx p0, p1, result, temp; | |
3419 | |
3420 p0 = XEXP (XEXP (op1,1), 0); | |
3421 | |
3422 if (GET_CODE (p0) == PLUS) | |
3423 { | |
3424 p1 = XEXP (p0, 1); | |
3425 p0 = XEXP (p0, 0); | |
3426 } | |
3427 | |
3428 if (GET_CODE (p0) == UNSPEC && GET_CODE (p1) == CONST_INT | |
3429 && flag_pic && TARGET_PIC_DATA_TEXT_REL) | |
3430 { | |
3431 result = gen_rtx_CONST (Pmode, p0); | |
3432 result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); | |
3433 temp = force_reg (SImode, result); | |
3434 emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, p1)); | |
3301 return true; | 3435 return true; |
3302 } | 3436 } |
3303 } | 3437 } |
3304 /* Handle Case of (const (plus symbol const_int)). */ | 3438 /* Handle Case of (const (plus symbol const_int)). */ |
3305 if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS) | 3439 if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS) |
3395 if (size <= microblaze_section_threshold) | 3529 if (size <= microblaze_section_threshold) |
3396 section_asm_op = SDATA2_SECTION_ASM_OP; | 3530 section_asm_op = SDATA2_SECTION_ASM_OP; |
3397 else | 3531 else |
3398 section_asm_op = READONLY_DATA_SECTION_ASM_OP; | 3532 section_asm_op = READONLY_DATA_SECTION_ASM_OP; |
3399 | 3533 |
3400 buf = ACONCAT ((section_asm_op, "\n\t.ascii \"", string, "\\0\"\n", NULL)); | 3534 buf = ACONCAT (("\t.pushsection", section_asm_op, |
3535 "\n\t.ascii \"", string, "\\0\"\n", | |
3536 "\t.popsection\n", NULL)); | |
3401 symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); | 3537 symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); |
3402 } | 3538 } |
3403 | 3539 |
3404 static void | 3540 static void |
3405 microblaze_elf_asm_init_sections (void) | 3541 microblaze_elf_asm_init_sections (void) |
3911 #define TARGET_OPTION_OVERRIDE microblaze_option_override | 4047 #define TARGET_OPTION_OVERRIDE microblaze_option_override |
3912 | 4048 |
3913 #undef TARGET_LEGITIMATE_CONSTANT_P | 4049 #undef TARGET_LEGITIMATE_CONSTANT_P |
3914 #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p | 4050 #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p |
3915 | 4051 |
4052 #undef TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC | |
4053 #define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC microblaze_gen_pic_addr_dif_vec | |
4054 | |
3916 #undef TARGET_MACHINE_DEPENDENT_REORG | 4055 #undef TARGET_MACHINE_DEPENDENT_REORG |
3917 #define TARGET_MACHINE_DEPENDENT_REORG microblaze_machine_dependent_reorg | 4056 #define TARGET_MACHINE_DEPENDENT_REORG microblaze_machine_dependent_reorg |
3918 | 4057 |
3919 #undef TARGET_HARD_REGNO_MODE_OK | 4058 #undef TARGET_HARD_REGNO_MODE_OK |
3920 #define TARGET_HARD_REGNO_MODE_OK microblaze_hard_regno_mode_ok | 4059 #define TARGET_HARD_REGNO_MODE_OK microblaze_hard_regno_mode_ok |