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