Mercurial > hg > CbC > CbC_gcc
diff 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 |
line wrap: on
line diff
--- a/gcc/config/microblaze/microblaze.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/config/microblaze/microblaze.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Subroutines used for code generation on Xilinx MicroBlaze. - Copyright (C) 2009-2017 Free Software Foundation, Inc. + Copyright (C) 2009-2018 Free Software Foundation, Inc. Contributed by Michael Eager <eager@eagercon.com>. @@ -19,6 +19,8 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#define IN_TARGET_CODE 1 + #include "config.h" #include "system.h" #include "coretypes.h" @@ -89,7 +91,8 @@ ADDRESS_SYMBOLIC, ADDRESS_GOTOFF, ADDRESS_PLT, - ADDRESS_TLS + ADDRESS_TLS, + ADDRESS_SYMBOLIC_TXT_REL }; /* Classifies symbols @@ -215,18 +218,13 @@ int save_volatiles; const struct attribute_spec microblaze_attribute_table[] = { - /* name min_len, max_len, decl_req, type_req, fn_type, req_handler, - affects_type_identity */ - {"interrupt_handler", 0, 0, true, false, false, NULL, - false }, - {"break_handler", 0, 0, true, false, false, NULL, - false }, - {"fast_interrupt", 0, 0, true, false, false, NULL, - false }, - {"save_volatiles" , 0, 0, true, false, false, NULL, - false }, - { NULL, 0, 0, false, false, false, NULL, - false } + /* name min_len, max_len, decl_req, type_req, fn_type_req, + affects_type_identity, handler, exclude */ + {"interrupt_handler", 0, 0, true, false, false, false, NULL, NULL }, + {"break_handler", 0, 0, true, false, false, false, NULL, NULL }, + {"fast_interrupt", 0, 0, true, false, false, false, NULL, NULL }, + {"save_volatiles", 0, 0, true, false, false, false, NULL, NULL }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } }; static int microblaze_interrupt_function_p (tree); @@ -653,6 +651,10 @@ info->type = ADDRESS_TLS; info->tls_type = tls_reloc (INTVAL (XVECEXP (x, 0, 1))); } + else if (XINT (x, 1) == UNSPEC_TEXT) + { + info->type = ADDRESS_SYMBOLIC_TXT_REL; + } else { return false; @@ -704,8 +706,10 @@ } /* Return true if X is a valid address for machine mode MODE. If it is, - fill in INFO appropriately. STRICT is true if we should only accept - hard base registers. + fill in INFO appropriately. + STRICT > 0 if we should only accept hard base registers. + STRICT = 2 if the operand address is being printed thus + function has been called by print_operand_address. type regA regB offset symbol @@ -731,6 +735,7 @@ { rtx xplus0; rtx xplus1; + rtx offset; info->type = ADDRESS_INVALID; info->regA = NULL; @@ -738,6 +743,7 @@ info->offset = NULL; info->symbol = NULL; info->symbol_type = SYMBOL_TYPE_INVALID; + offset = NULL; switch (GET_CODE (x)) { @@ -798,8 +804,13 @@ /* for (plus x const_int) just look at x. */ if (GET_CODE (xconst0) == PLUS && GET_CODE (XEXP (xconst0, 1)) == CONST_INT - && SMALL_INT (XEXP (xconst0, 1))) + && (SMALL_INT (XEXP (xconst0, 1)) + || GET_CODE (XEXP (xconst0, 0)) == UNSPEC)) { + /* Hold CONST_INT Value in offset in case of + UNSPEC + CONST_INT. */ + offset = XEXP (xconst0, 1); + /* This is ok as info->symbol is set to xplus1 the full const-expression below. */ xconst0 = XEXP (xconst0, 0); @@ -817,6 +828,15 @@ return true; } + if (GET_CODE (xconst0) == UNSPEC && TARGET_PIC_DATA_TEXT_REL) + { + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) + return false; + + info->offset = offset; + return microblaze_classify_unspec (info, xconst0); + } + /* Not base + symbol || base + UNSPEC. */ return false; @@ -861,6 +881,15 @@ return !(flag_pic && pic_address_needs_scratch (x)); } + /* Avoid error in print_operand_address in case UNSPEC + is removed from SYMBOL or LABEL REFS during optimization. */ + if ((GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) + && flag_pic && TARGET_PIC_DATA_TEXT_REL && strict == 2) + { + info->type = ADDRESS_SYMBOLIC_TXT_REL; + return true; + } + if (flag_pic == 2) return false; else if (microblaze_tls_symbol_p(x)) @@ -896,6 +925,15 @@ return microblaze_classify_address (&addr, x, mode, strict); } +bool +microblaze_constant_address_p (rtx x) +{ + return ((GET_CODE (x) == LABEL_REF) || (GET_CODE (x) == SYMBOL_REF) + || GET_CODE (x) == CONST_INT + || (GET_CODE (x) == CONST + && ! (flag_pic && pic_address_needs_scratch (x)))); +} + int microblaze_valid_pic_const (rtx x) { @@ -913,7 +951,8 @@ int microblaze_legitimate_pic_operand (rtx x) { - if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x))) + if (flag_pic == 2 && (symbol_mentioned_p (x) || label_mentioned_p (x)) + && !(TARGET_PIC_DATA_TEXT_REL && call_insn_operand (x,VOIDmode))) return 0; if (microblaze_tls_referenced_p(x)) @@ -1027,17 +1066,35 @@ } else if (flag_pic == 2) { - rtx pic_ref, reg; - reg = gen_reg_rtx (Pmode); - - pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), - UNSPEC_GOTOFF); - pic_ref = gen_rtx_CONST (Pmode, pic_ref); - pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); - pic_ref = gen_const_mem (Pmode, pic_ref); - emit_move_insn (reg, pic_ref); - result = gen_rtx_PLUS (Pmode, xplus0, reg); - return result; + if (!TARGET_PIC_DATA_TEXT_REL) + { + rtx pic_ref, reg; + reg = gen_reg_rtx (Pmode); + + pic_ref = gen_rtx_UNSPEC (Pmode, + gen_rtvec (1, xplus1), + UNSPEC_GOTOFF); + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + pic_ref = gen_rtx_PLUS (Pmode, + pic_offset_table_rtx, pic_ref); + pic_ref = gen_const_mem (Pmode, pic_ref); + emit_move_insn (reg, pic_ref); + result = gen_rtx_PLUS (Pmode, xplus0, reg); + return result; + } + else + { + rtx pic_ref, reg; + reg = gen_reg_rtx (Pmode); + pic_ref = gen_rtx_UNSPEC (Pmode, + gen_rtvec (1, xplus1), + UNSPEC_TEXT); + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + emit_insn (gen_addsi3 (reg, + pic_offset_table_rtx, xplus0)); + result = gen_rtx_PLUS (Pmode, reg, pic_ref); + return result; + } } } } @@ -1050,19 +1107,31 @@ { reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX); } - else + else if (flag_pic == 2) { - rtx pic_ref; - - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); - - pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF); - pic_ref = gen_rtx_CONST (Pmode, pic_ref); - pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); - pic_ref = gen_const_mem (Pmode, pic_ref); - reg = pic_ref; - } + if (reload_in_progress) + df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + + if (!TARGET_PIC_DATA_TEXT_REL) + { + rtx pic_ref; + + pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF); + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); + pic_ref = gen_const_mem (Pmode, pic_ref); + reg = pic_ref; + } + else + { + rtx pic_ref; + + pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_TEXT); + pic_ref = gen_rtx_CONST (Pmode, pic_ref); + pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref); + reg = pic_ref; + } + } return reg; } @@ -1391,6 +1460,7 @@ case ADDRESS_REG_INDEX: return 1; case ADDRESS_SYMBOLIC: + case ADDRESS_SYMBOLIC_TXT_REL: case ADDRESS_GOTOFF: return 2; case ADDRESS_TLS: @@ -2069,7 +2139,7 @@ total_size = var_size + args_size; - if (flag_pic == 2) + if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL) /* force setting GOT. */ df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true); @@ -2325,6 +2395,7 @@ case ADDRESS_REG: case ADDRESS_CONST_INT: case ADDRESS_SYMBOLIC: + case ADDRESS_SYMBOLIC_TXT_REL: case ADDRESS_GOTOFF: case ADDRESS_TLS: fputs ("i", file); @@ -2492,7 +2563,7 @@ { struct microblaze_address_info info; enum microblaze_address_type type; - if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1)) + if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 2)) fatal_insn ("insn contains an invalid address !", addr); type = info.type; @@ -2518,6 +2589,7 @@ output_addr_const (file, info.offset); break; case ADDRESS_SYMBOLIC: + case ADDRESS_SYMBOLIC_TXT_REL: case ADDRESS_GOTOFF: case ADDRESS_PLT: case ADDRESS_TLS: @@ -2532,6 +2604,16 @@ { fputs ("@PLT", file); } + else if (type == ADDRESS_SYMBOLIC_TXT_REL) + { + if (info.offset != NULL && CONST_INT_P (info.offset) + && INTVAL (info.offset) > 0) + { + fprintf (file, "+"); + output_addr_const (file, info.offset); + } + fputs ("@TXTREL", file); + } else if (type == ADDRESS_TLS) { switch (info.tls_type) @@ -2726,7 +2808,7 @@ STACK_POINTER_REGNUM]), fsiz, reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST], current_frame_info.var_size, current_frame_info.num_gp, - crtl->outgoing_args_size); + (int) crtl->outgoing_args_size); fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask); } } @@ -2891,7 +2973,6 @@ if (flag_stack_usage_info) current_function_static_stack_size = fsiz; - /* If this function is a varargs function, store any registers that would normally hold arguments ($5 - $10) on the stack. */ if (((TYPE_ARG_TYPES (fntype) != 0 @@ -2916,7 +2997,6 @@ offset += GET_MODE_SIZE (SImode); } - } if (fsiz > 0) @@ -2963,8 +3043,18 @@ if ((flag_pic == 2 || TLS_NEEDS_GOT ) && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM)) { - SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); - emit_insn (gen_set_got (pic_offset_table_rtx)); /* setting GOT. */ + if ((flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL) || TLS_NEEDS_GOT) + { + SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); + /* setting GOT. */ + emit_insn (gen_set_got (pic_offset_table_rtx)); + } + else + { + SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM); + /* setting start of text. */ + emit_insn (gen_set_text (pic_offset_table_rtx)); + } } /* If we are profiling, make sure no instructions are scheduled before @@ -3157,6 +3247,14 @@ return (size > 0 && size <= microblaze_section_threshold); } +/* We need to disable address diff vectors in +case of pic data text relative mode. */ + +static bool +microblaze_gen_pic_addr_dif_vec (void) +{ + return (flag_pic && !TARGET_PIC_DATA_TEXT_REL); +} static section * microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) @@ -3190,10 +3288,19 @@ expand_pic_symbol_ref (machine_mode mode ATTRIBUTE_UNUSED, rtx op) { rtx result; - result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF); + bool isFunc = (GET_CODE (op) == SYMBOL_REF + && (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCTION)); + result = (!TARGET_PIC_DATA_TEXT_REL) + ? gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF) + : gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_TEXT); result = gen_rtx_CONST (Pmode, result); - result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); - result = gen_const_mem (Pmode, result); + result = (TARGET_PIC_DATA_TEXT_REL && isFunc) + ? gen_rtx_PLUS (Pmode, gen_raw_REG (Pmode, + get_base_reg (op)), result) + : gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); + result = (!TARGET_PIC_DATA_TEXT_REL) + ? gen_const_mem (Pmode, result) : result; + return result; } @@ -3297,10 +3404,37 @@ if (reload_in_progress) df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); result = expand_pic_symbol_ref (mode, op1); + + if (TARGET_PIC_DATA_TEXT_REL && GET_CODE (op0) == REG + && REGNO (op0) >= FIRST_PSEUDO_REGISTER) + result = force_reg (SImode, result); + emit_move_insn (op0, result); return true; } } + if (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1,1)) == CONST) + { + rtx p0, p1, result, temp; + + p0 = XEXP (XEXP (op1,1), 0); + + if (GET_CODE (p0) == PLUS) + { + p1 = XEXP (p0, 1); + p0 = XEXP (p0, 0); + } + + if (GET_CODE (p0) == UNSPEC && GET_CODE (p1) == CONST_INT + && flag_pic && TARGET_PIC_DATA_TEXT_REL) + { + result = gen_rtx_CONST (Pmode, p0); + result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result); + temp = force_reg (SImode, result); + emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, p1)); + return true; + } + } /* Handle Case of (const (plus symbol const_int)). */ if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS) { @@ -3397,7 +3531,9 @@ else section_asm_op = READONLY_DATA_SECTION_ASM_OP; - buf = ACONCAT ((section_asm_op, "\n\t.ascii \"", string, "\\0\"\n", NULL)); + buf = ACONCAT (("\t.pushsection", section_asm_op, + "\n\t.ascii \"", string, "\\0\"\n", + "\t.popsection\n", NULL)); symtab->finalize_toplevel_asm (build_string (strlen (buf), buf)); } @@ -3913,6 +4049,9 @@ #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p +#undef TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC +#define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC microblaze_gen_pic_addr_dif_vec + #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG microblaze_machine_dependent_reorg