1 /* Subroutines used for code generation on Xilinx MicroBlaze.
2 Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
4 Contributed by Michael Eager <eager@eagercon.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "insn-attr.h"
34 #include "integrate.h"
45 #include "target-def.h"
50 #include "diagnostic-core.h"
52 #define MICROBLAZE_VERSION_COMPARE(VA,VB) strcasecmp (VA, VB)
54 /* Classifies an address.
61 A natural register or a register + const_int offset address.
62 The register satisfies microblaze_valid_base_register_p and the
63 offset is a const_arith_operand.
67 A natural register offset by the index contained in an index register. The base
68 register satisfies microblaze_valid_base_register_p and the index register
69 satisfies microblaze_valid_index_register_p
73 A signed 16/32-bit constant address.
77 A constant symbolic address or a (register + symbol). */
79 enum microblaze_address_type
95 enum microblaze_symbol_type
101 /* Classification of a MicroBlaze address. */
102 struct microblaze_address_info
104 enum microblaze_address_type type;
105 rtx regA; /* Contains valid values on ADDRESS_REG, ADDRESS_REG_INDEX,
107 rtx regB; /* Contains valid values on ADDRESS_REG_INDEX. */
108 rtx offset; /* Contains valid values on ADDRESS_CONST_INT and ADDRESS_REG. */
109 rtx symbol; /* Contains valid values on ADDRESS_SYMBOLIC. */
110 enum microblaze_symbol_type symbol_type;
113 /* Structure to be filled in by compute_frame_size with register
114 save masks, and offsets for the current function. */
116 struct GTY(()) microblaze_frame_info {
117 long total_size; /* # bytes that the entire frame takes up. */
118 long var_size; /* # bytes that variables take up. */
119 long args_size; /* # bytes that outgoing arguments take up. */
120 int link_debug_size; /* # bytes for the link reg and back pointer. */
121 int gp_reg_size; /* # bytes needed to store gp regs. */
122 long gp_offset; /* offset from new sp to store gp registers. */
123 long mask; /* mask of saved gp registers. */
124 int initialized; /* != 0 if frame size already calculated. */
125 int num_gp; /* number of gp registers saved. */
126 long insns_len; /* length of insns. */
127 int alloc_stack; /* Flag to indicate if the current function
128 must not create stack space. (As an optimization). */
131 /* Global variables for machine-dependent things. */
133 /* Toggle which pipleline interface to use. */
134 static GTY(()) int microblaze_sched_use_dfa = 0;
136 /* Threshold for data being put into the small data/bss area, instead
137 of the normal data area (references to the small data/bss area take
138 1 instruction, and use the global pointer, references to the normal
139 data area takes 2 instructions). */
140 int microblaze_section_threshold = -1;
142 /* Prevent scheduling potentially exception causing instructions in
143 delay slots. -mcpu=v3.00.a or v4.00.a turns this on. */
144 int microblaze_no_unsafe_delay;
146 /* Which CPU pipeline do we use. We haven't really standardized on a CPU
147 version having only a particular type of pipeline. There can still be
148 options on the CPU to scale pipeline features up or down. :(
149 Bad Presentation (??), so we let the MD file rely on the value of
150 this variable instead Making PIPE_5 the default. It should be backward
151 optimal with PIPE_3 MicroBlazes. */
152 enum pipeline_type microblaze_pipe = MICROBLAZE_PIPE_5;
154 /* High and low marks for floating point values which we will accept
155 as legitimate constants for TARGET_LEGITIMATE_CONSTANT_P. These are
156 initialized in override_options. */
157 REAL_VALUE_TYPE dfhigh, dflow, sfhigh, sflow;
159 /* Array giving truth value on whether or not a given hard register
160 can support a given mode. */
161 char microblaze_hard_regno_mode_ok[(int)MAX_MACHINE_MODE]
162 [FIRST_PSEUDO_REGISTER];
164 /* Current frame information calculated by compute_frame_size. */
165 struct microblaze_frame_info current_frame_info;
167 /* Zero structure to initialize current_frame_info. */
168 struct microblaze_frame_info zero_frame_info;
170 /* List of all MICROBLAZE punctuation characters used by print_operand. */
171 char microblaze_print_operand_punct[256];
173 /* Map GCC register number to debugger register number. */
174 int microblaze_dbx_regno[FIRST_PSEUDO_REGISTER];
176 /* Map hard register number to register class. */
177 enum reg_class microblaze_regno_to_class[] =
179 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
180 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
181 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
182 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
183 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
184 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
185 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
186 GR_REGS, GR_REGS, GR_REGS, GR_REGS,
187 ST_REGS, GR_REGS, GR_REGS, GR_REGS
190 /* MicroBlaze specific machine attributes.
191 interrupt_handler - Interrupt handler attribute to add interrupt prologue
192 and epilogue and use appropriate interrupt return.
193 save_volatiles - Similiar to interrupt handler, but use normal return. */
194 int interrupt_handler;
197 const struct attribute_spec microblaze_attribute_table[] = {
198 /* name min_len, max_len, decl_req, type_req, fn_type, req_handler,
199 affects_type_identity */
200 {"interrupt_handler", 0, 0, true, false, false, NULL,
202 {"save_volatiles" , 0, 0, true, false, false, NULL,
204 { NULL, 0, 0, false, false, false, NULL,
208 static int microblaze_interrupt_function_p (tree);
210 section *sdata2_section;
212 /* Return truth value if a CONST_DOUBLE is ok to be a legitimate constant. */
214 microblaze_const_double_ok (rtx op, enum machine_mode mode)
218 if (GET_CODE (op) != CONST_DOUBLE)
221 if (GET_MODE (op) == VOIDmode)
224 if (mode != SFmode && mode != DFmode)
227 if (op == CONST0_RTX (mode))
230 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
232 if (REAL_VALUE_ISNAN (d))
235 if (REAL_VALUE_NEGATIVE (d))
236 d = real_value_negate (&d);
240 if (REAL_VALUES_LESS (d, dfhigh) && REAL_VALUES_LESS (dflow, d))
245 if (REAL_VALUES_LESS (d, sfhigh) && REAL_VALUES_LESS (sflow, d))
252 /* Return truth value if a memory operand fits in a single instruction
253 (ie, register + small offset) or (register + register). */
256 simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
258 rtx addr, plus0, plus1;
260 /* Eliminate non-memory operations. */
261 if (GET_CODE (op) != MEM)
264 /* dword operations really put out 2 instructions, so eliminate them. */
265 /* ??? This isn't strictly correct. It is OK to accept multiword modes
266 here, since the length attributes are being set correctly, but only
267 if the address is offsettable. */
268 if (GET_MODE_SIZE (GET_MODE (op)) > UNITS_PER_WORD)
272 /* Decode the address now. */
274 switch (GET_CODE (addr))
281 plus0 = XEXP (addr, 0);
282 plus1 = XEXP (addr, 1);
284 if (GET_CODE (plus0) == REG && GET_CODE (plus1) == CONST_INT
285 && SMALL_INT (plus1))
289 else if (GET_CODE (plus1) == REG && GET_CODE (plus0) == CONST_INT)
293 else if (GET_CODE (plus0) == REG && GET_CODE (plus1) == REG)
310 /* Return nonzero for a memory address that can be used to load or store
314 double_memory_operand (rtx op, enum machine_mode mode)
318 if (GET_CODE (op) != MEM || !memory_operand (op, mode))
320 /* During reload, we accept a pseudo register if it has an
321 appropriate memory address. If we don't do this, we will
322 wind up reloading into a register, and then reloading that
323 register from memory, when we could just reload directly from
325 if (reload_in_progress
326 && GET_CODE (op) == REG
327 && REGNO (op) >= FIRST_PSEUDO_REGISTER
328 && reg_renumber[REGNO (op)] < 0
329 && reg_equiv_mem (REGNO (op)) != 0
330 && double_memory_operand (reg_equiv_mem (REGNO (op)), mode))
335 /* Make sure that 4 added to the address is a valid memory address.
336 This essentially just checks for overflow in an added constant. */
340 if (CONSTANT_ADDRESS_P (addr))
343 return memory_address_p ((GET_MODE_CLASS (mode) == MODE_INT
344 ? SImode : SFmode), plus_constant (addr, 4));
347 /* Implement REG_OK_FOR_BASE_P -and- REG_OK_FOR_INDEX_P. */
349 microblaze_regno_ok_for_base_p (int regno, int strict)
351 if (regno >= FIRST_PSEUDO_REGISTER)
355 regno = reg_renumber[regno];
358 /* These fake registers will be eliminated to either the stack or
359 hard frame pointer, both of which are usually valid base registers.
360 Reload deals with the cases where the eliminated form isn't valid. */
361 if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
364 return GP_REG_P (regno);
367 /* Return true if X is a valid base register for the given mode.
368 Allow only hard registers if STRICT. */
371 microblaze_valid_base_register_p (rtx x,
372 enum machine_mode mode ATTRIBUTE_UNUSED,
375 if (!strict && GET_CODE (x) == SUBREG)
378 return (GET_CODE (x) == REG
379 && microblaze_regno_ok_for_base_p (REGNO (x), strict));
383 microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
385 info->symbol_type = SYMBOL_TYPE_GENERAL;
386 info->symbol = XVECEXP (x, 0, 0);
388 if (XINT (x, 1) == UNSPEC_GOTOFF)
390 info->regA = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
391 info->type = ADDRESS_GOTOFF;
393 else if (XINT (x, 1) == UNSPEC_PLT)
395 info->type = ADDRESS_PLT;
405 /* Return true if X is a valid index register for the given mode.
406 Allow only hard registers if STRICT. */
409 microblaze_valid_index_register_p (rtx x,
410 enum machine_mode mode ATTRIBUTE_UNUSED,
413 if (!strict && GET_CODE (x) == SUBREG)
416 return (GET_CODE (x) == REG
417 /* A base register is good enough to be an index register on MicroBlaze. */
418 && microblaze_regno_ok_for_base_p (REGNO (x), strict));
421 /* Get the base register for accessing a value from the memory or
422 Symbol ref. Used for MicroBlaze Small Data Area Pointer Optimization. */
427 int base_reg = (flag_pic ? MB_ABI_PIC_ADDR_REGNUM : MB_ABI_BASE_REGNUM);
430 && GET_CODE (x) == SYMBOL_REF
431 && SYMBOL_REF_SMALL_P (x) && (decl = SYMBOL_REF_DECL (x)) != NULL)
433 if (TREE_READONLY (decl))
434 base_reg = MB_ABI_GPRO_REGNUM;
436 base_reg = MB_ABI_GPRW_REGNUM;
442 /* Return true if X is a valid address for machine mode MODE. If it is,
443 fill in INFO appropriately. STRICT is true if we should only accept
446 type regA regB offset symbol
448 ADDRESS_INVALID NULL NULL NULL NULL
450 ADDRESS_REG %0 NULL const_0 / NULL
452 ADDRESS_REG_INDEX %0 %1 NULL NULL
454 ADDRESS_SYMBOLIC r0 / NULL NULL symbol
457 ADDRESS_CONST_INT r0 NULL const NULL
459 For modes spanning multiple registers (DFmode in 32-bit GPRs,
460 DImode, TImode), indexed addressing cannot be used because
461 adjacent memory cells are accessed by adding word-sized offsets
462 during assembly output. */
465 microblaze_classify_address (struct microblaze_address_info *info, rtx x,
466 enum machine_mode mode, int strict)
471 info->type = ADDRESS_INVALID;
476 info->symbol_type = SYMBOL_TYPE_INVALID;
478 switch (GET_CODE (x))
483 info->type = ADDRESS_REG;
485 info->offset = const0_rtx;
486 return microblaze_valid_base_register_p (info->regA, mode, strict);
490 xplus0 = XEXP (x, 0);
491 xplus1 = XEXP (x, 1);
493 if (microblaze_valid_base_register_p (xplus0, mode, strict))
495 info->type = ADDRESS_REG;
498 if (GET_CODE (xplus1) == CONST_INT)
500 info->offset = xplus1;
503 else if (GET_CODE (xplus1) == UNSPEC)
505 return microblaze_classify_unspec (info, xplus1);
507 else if ((GET_CODE (xplus1) == SYMBOL_REF ||
508 GET_CODE (xplus1) == LABEL_REF) && flag_pic == 2)
512 else if (GET_CODE (xplus1) == SYMBOL_REF ||
513 GET_CODE (xplus1) == LABEL_REF ||
514 GET_CODE (xplus1) == CONST)
516 if (GET_CODE (XEXP (xplus1, 0)) == UNSPEC)
517 return microblaze_classify_unspec (info, XEXP (xplus1, 0));
518 else if (flag_pic == 2)
522 info->type = ADDRESS_SYMBOLIC;
523 info->symbol = xplus1;
524 info->symbol_type = SYMBOL_TYPE_GENERAL;
527 else if (GET_CODE (xplus1) == REG
528 && microblaze_valid_index_register_p (xplus1, mode,
530 && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
532 /* Restrict larger than word-width modes from using an index register. */
533 info->type = ADDRESS_REG_INDEX;
542 info->regA = gen_rtx_raw_REG (mode, 0);
543 info->type = ADDRESS_CONST_INT;
551 info->type = ADDRESS_SYMBOLIC;
552 info->symbol_type = SYMBOL_TYPE_GENERAL;
554 info->regA = gen_rtx_raw_REG (mode, get_base_reg (x));
556 if (GET_CODE (x) == CONST)
558 return !(flag_pic && pic_address_needs_scratch (x));
560 else if (flag_pic == 2)
570 if (reload_in_progress)
571 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
572 return microblaze_classify_unspec (info, x);
582 /* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It
583 returns a nonzero value if X is a legitimate address for a memory
584 operand of the indicated MODE. STRICT is nonzero if this function
585 is called during reload. */
588 microblaze_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
590 struct microblaze_address_info addr;
592 return microblaze_classify_address (&addr, x, mode, strict);
596 /* Try machine-dependent ways of modifying an illegitimate address
597 to be legitimate. If we find one, return the new, valid address.
598 This is used from only one place: `memory_address' in explow.c.
600 OLDX is the address as it was before break_out_memory_refs was
601 called. In some cases it is useful to look at this to decide what
604 It is always safe for this function to do nothing. It exists to
605 recognize opportunities to optimize the output.
607 For the MicroBlaze, transform:
609 memory(X + <large int>)
613 Y = <large int> & ~0x7fff;
615 memory (Z + (<large int> & 0x7fff));
617 This is for CSE to find several similar references, and only use one Z.
619 When PIC, convert addresses of the form memory (symbol+large int) to
620 memory (reg+large int). */
623 microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
624 enum machine_mode mode ATTRIBUTE_UNUSED)
626 register rtx xinsn = x, result;
628 if (GET_CODE (xinsn) == CONST
629 && flag_pic && pic_address_needs_scratch (xinsn))
631 rtx ptr_reg = gen_reg_rtx (Pmode);
632 rtx constant = XEXP (XEXP (xinsn, 0), 1);
634 emit_move_insn (ptr_reg, XEXP (XEXP (xinsn, 0), 0));
636 result = gen_rtx_PLUS (Pmode, ptr_reg, constant);
637 if (SMALL_INT (constant))
639 /* Otherwise we fall through so the code below will fix the
644 if (GET_CODE (xinsn) == PLUS)
646 register rtx xplus0 = XEXP (xinsn, 0);
647 register rtx xplus1 = XEXP (xinsn, 1);
648 register enum rtx_code code0 = GET_CODE (xplus0);
649 register enum rtx_code code1 = GET_CODE (xplus1);
651 if (code0 != REG && code1 == REG)
653 xplus0 = XEXP (xinsn, 1);
654 xplus1 = XEXP (xinsn, 0);
655 code0 = GET_CODE (xplus0);
656 code1 = GET_CODE (xplus1);
659 if (code0 == REG && REG_OK_FOR_BASE_P (xplus0)
660 && code1 == CONST_INT && !SMALL_INT (xplus1))
662 rtx int_reg = gen_reg_rtx (Pmode);
663 rtx ptr_reg = gen_reg_rtx (Pmode);
665 emit_move_insn (int_reg, GEN_INT (INTVAL (xplus1) & ~0x7fff));
667 emit_insn (gen_rtx_SET (VOIDmode,
669 gen_rtx_PLUS (Pmode, xplus0, int_reg)));
671 result = gen_rtx_PLUS (Pmode, ptr_reg,
672 GEN_INT (INTVAL (xplus1) & 0x7fff));
676 if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) && flag_pic == 2)
678 if (reload_in_progress)
679 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
682 xplus1 = XEXP (xplus1, 0);
683 code1 = GET_CODE (xplus1);
685 if (code1 == SYMBOL_REF)
688 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1), UNSPEC_GOTOFF);
689 result = gen_rtx_CONST (Pmode, result);
690 result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
691 result = gen_const_mem (Pmode, result);
692 result = gen_rtx_PLUS (Pmode, xplus0, result);
698 if (GET_CODE (xinsn) == SYMBOL_REF)
700 if (reload_in_progress)
701 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
702 result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
703 result = gen_rtx_CONST (Pmode, result);
704 result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
705 result = gen_const_mem (Pmode, result);
714 #define MAX_MOVE_REGS 8
715 #define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
717 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
718 Assume that the areas do not overlap. */
721 microblaze_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
723 HOST_WIDE_INT offset, delta;
724 unsigned HOST_WIDE_INT bits;
726 enum machine_mode mode;
729 bits = BITS_PER_WORD;
730 mode = mode_for_size (bits, MODE_INT, 0);
731 delta = bits / BITS_PER_UNIT;
733 /* Allocate a buffer for the temporary registers. */
734 regs = XALLOCAVEC (rtx, length / delta);
736 /* Load as many BITS-sized chunks as possible. Use a normal load if
737 the source has enough alignment, otherwise use left/right pairs. */
738 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
740 regs[i] = gen_reg_rtx (mode);
741 emit_move_insn (regs[i], adjust_address (src, mode, offset));
744 /* Copy the chunks to the destination. */
745 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
746 emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
748 /* Mop up any left-over bytes. */
751 src = adjust_address (src, BLKmode, offset);
752 dest = adjust_address (dest, BLKmode, offset);
753 move_by_pieces (dest, src, length - offset,
754 MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
758 /* Helper function for doing a loop-based block operation on memory
759 reference MEM. Each iteration of the loop will operate on LENGTH
762 Create a new base register for use within the loop and point it to
763 the start of MEM. Create a new memory reference that uses this
764 register. Store them in *LOOP_REG and *LOOP_MEM respectively. */
767 microblaze_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
768 rtx * loop_reg, rtx * loop_mem)
770 *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
772 /* Although the new mem does not refer to a known location,
773 it does keep up to LENGTH bytes of alignment. */
774 *loop_mem = change_address (mem, BLKmode, *loop_reg);
775 set_mem_align (*loop_mem,
776 MIN ((HOST_WIDE_INT) MEM_ALIGN (mem),
777 length * BITS_PER_UNIT));
781 /* Move LENGTH bytes from SRC to DEST using a loop that moves MAX_MOVE_BYTES
782 per iteration. LENGTH must be at least MAX_MOVE_BYTES. Assume that the
783 memory regions do not overlap. */
786 microblaze_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
788 rtx label, src_reg, dest_reg, final_src;
789 HOST_WIDE_INT leftover;
791 leftover = length % MAX_MOVE_BYTES;
794 /* Create registers and memory references for use within the loop. */
795 microblaze_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src);
796 microblaze_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest);
798 /* Calculate the value that SRC_REG should have after the last iteration
800 final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
803 /* Emit the start of the loop. */
804 label = gen_label_rtx ();
807 /* Emit the loop body. */
808 microblaze_block_move_straight (dest, src, MAX_MOVE_BYTES);
810 /* Move on to the next block. */
811 emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES));
812 emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES));
814 /* Emit the test & branch. */
815 emit_insn (gen_cbranchsi4 (gen_rtx_NE (SImode, src_reg, final_src),
816 src_reg, final_src, label));
818 /* Mop up any left-over bytes. */
820 microblaze_block_move_straight (dest, src, leftover);
823 /* Expand a movmemsi instruction. */
826 microblaze_expand_block_move (rtx dest, rtx src, rtx length, rtx align_rtx)
829 if (GET_CODE (length) == CONST_INT)
831 HOST_WIDE_INT bytes = INTVAL (length);
832 int align = INTVAL (align_rtx);
834 if (align > UNITS_PER_WORD)
836 align = UNITS_PER_WORD; /* We can't do any better. */
838 else if (align < UNITS_PER_WORD)
840 if (INTVAL (length) <= MAX_MOVE_BYTES)
842 move_by_pieces (dest, src, bytes, align, 0);
849 if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
851 microblaze_block_move_straight (dest, src, INTVAL (length));
856 microblaze_block_move_loop (dest, src, INTVAL (length));
864 microblaze_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
865 bool speed ATTRIBUTE_UNUSED)
867 enum machine_mode mode = GET_MODE (x);
873 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
874 if (simple_memory_operand (x, mode))
875 *total = COSTS_N_INSNS (2 * num_words);
877 *total = COSTS_N_INSNS (2 * (2 * num_words));
885 *total = COSTS_N_INSNS (2);
888 *total = COSTS_N_INSNS (1);
897 *total = COSTS_N_INSNS (2);
900 *total = COSTS_N_INSNS (1);
908 if (TARGET_BARREL_SHIFT)
910 if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a")
912 *total = COSTS_N_INSNS (1);
914 *total = COSTS_N_INSNS (2);
916 else if (!TARGET_SOFT_MUL)
917 *total = COSTS_N_INSNS (1);
918 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
920 /* Add 1 to make shift slightly more expensive than add. */
921 *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1))) + 1;
922 /* Reduce shift costs for special circumstances. */
923 if (optimize_size && INTVAL (XEXP (x, 1)) > 5)
925 if (!optimize_size && INTVAL (XEXP (x, 1)) > 17)
929 /* Double the worst cost of shifts when there is no barrel shifter and
930 the shift amount is in a reg. */
931 *total = COSTS_N_INSNS (32 * 4);
937 if (mode == SFmode || mode == DFmode)
939 if (TARGET_HARD_FLOAT)
940 *total = COSTS_N_INSNS (6);
943 else if (mode == DImode)
945 *total = COSTS_N_INSNS (4);
950 *total = COSTS_N_INSNS (1);
959 *total = COSTS_N_INSNS (4);
967 if (TARGET_HARD_FLOAT)
968 *total = COSTS_N_INSNS (6);
970 else if (!TARGET_SOFT_MUL)
972 if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a")
974 *total = COSTS_N_INSNS (1);
976 *total = COSTS_N_INSNS (3);
979 *total = COSTS_N_INSNS (10);
987 if (TARGET_HARD_FLOAT)
988 *total = COSTS_N_INSNS (23);
994 *total = COSTS_N_INSNS (1);
999 *total = COSTS_N_INSNS (1);
1007 /* Return the number of instructions needed to load or store a value
1008 of mode MODE at X. Return 0 if X isn't valid for MODE. */
1011 microblaze_address_insns (rtx x, enum machine_mode mode)
1013 struct microblaze_address_info addr;
1015 if (microblaze_classify_address (&addr, x, mode, false))
1020 if (SMALL_INT (addr.offset))
1024 case ADDRESS_CONST_INT:
1029 case ADDRESS_REG_INDEX:
1030 case ADDRESS_SYMBOLIC:
1032 case ADDRESS_GOTOFF:
1041 /* Provide the costs of an addressing mode that contains ADDR.
1042 If ADDR is not a valid address, its cost is irrelevant. */
1044 microblaze_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
1046 return COSTS_N_INSNS (microblaze_address_insns (addr, GET_MODE (addr)));
1049 /* Return nonzero if X is an address which needs a temporary register when
1050 reloaded while generating PIC code. */
1053 pic_address_needs_scratch (rtx x)
1055 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
1056 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
1057 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
1058 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
1059 && (flag_pic == 2 || !SMALL_INT (XEXP (XEXP (x, 0), 1))))
1065 /* Argument support functions. */
1066 /* Initialize CUMULATIVE_ARGS for a function. */
1069 init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
1070 rtx libname ATTRIBUTE_UNUSED)
1072 static CUMULATIVE_ARGS zero_cum;
1073 tree param, next_param;
1077 /* Determine if this function has variable arguments. This is
1078 indicated by the last argument being 'void_type_mode' if there
1079 are no variable arguments. The standard MicroBlaze calling sequence
1080 passes all arguments in the general purpose registers in this case. */
1082 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
1083 param != 0; param = next_param)
1085 next_param = TREE_CHAIN (param);
1086 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
1087 cum->gp_reg_found = 1;
1091 /* Advance the argument to the next argument position. */
1094 microblaze_function_arg_advance (cumulative_args_t cum_v,
1095 enum machine_mode mode,
1096 const_tree type, bool named ATTRIBUTE_UNUSED)
1098 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1107 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1108 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1110 cum->gp_reg_found = 1;
1111 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1116 cum->gp_reg_found = 1;
1117 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1123 if (!cum->gp_reg_found && cum->arg_number <= 2)
1124 cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1128 cum->arg_words += 2;
1129 if (!cum->gp_reg_found && cum->arg_number <= 2)
1130 cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1134 cum->gp_reg_found = 1;
1135 cum->arg_words += 2;
1142 cum->gp_reg_found = 1;
1148 /* Return an RTL expression containing the register for the given mode,
1149 or 0 if the argument is to be passed on the stack. */
1152 microblaze_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
1153 const_tree type ATTRIBUTE_UNUSED,
1154 bool named ATTRIBUTE_UNUSED)
1156 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1160 int *arg_words = &cum->arg_words;
1162 cum->last_arg_fp = 0;
1173 regbase = GP_ARG_FIRST;
1176 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1177 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1178 /* Drops through. */
1180 regbase = GP_ARG_FIRST;
1184 if (*arg_words >= MAX_ARGS_IN_REGISTERS)
1188 gcc_assert (regbase != -1);
1190 ret = gen_rtx_REG (mode, regbase + *arg_words);
1193 if (mode == VOIDmode)
1195 if (cum->num_adjusts > 0)
1196 ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
1197 gen_rtvec_v (cum->num_adjusts, cum->adjust));
1203 /* Return number of bytes of argument to put in registers. */
1205 function_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
1206 tree type, bool named ATTRIBUTE_UNUSED)
1208 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1210 if ((mode == BLKmode
1211 || GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
1212 || GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
1213 && cum->arg_words < MAX_ARGS_IN_REGISTERS)
1216 if (mode == BLKmode)
1217 words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1220 words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1222 if (words + cum->arg_words <= MAX_ARGS_IN_REGISTERS)
1223 return 0; /* structure fits in registers */
1225 return (MAX_ARGS_IN_REGISTERS - cum->arg_words) * UNITS_PER_WORD;
1228 else if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
1229 return UNITS_PER_WORD;
1234 /* Convert a version number of the form "vX.YY.Z" to an integer encoding
1235 for easier range comparison. */
1237 microblaze_version_to_int (const char *version)
1240 const char *tmpl = "vX.YY.Z";
1249 { /* Looking for major */
1250 if (!(*p >= '0' && *p <= '9'))
1252 iver += (int) (*p - '0');
1256 { /* Looking for minor */
1257 if (!(*p >= '0' && *p <= '9'))
1259 iver += (int) (*p - '0');
1263 { /* Looking for compat */
1264 if (!(*p >= 'a' && *p <= 'z'))
1267 iver += (int) (*p - 'a');
1287 microblaze_option_override (void)
1289 register int i, start;
1291 register enum machine_mode mode;
1294 microblaze_section_threshold = (global_options_set.x_g_switch_value
1296 : MICROBLAZE_DEFAULT_GVALUE);
1298 /* Check the MicroBlaze CPU version for any special action to be done. */
1299 if (microblaze_select_cpu == NULL)
1300 microblaze_select_cpu = MICROBLAZE_DEFAULT_CPU;
1301 ver = microblaze_version_to_int (microblaze_select_cpu);
1304 error ("%qs is an invalid argument to -mcpu=", microblaze_select_cpu);
1307 ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v3.00.a");
1310 /* No hardware exceptions in earlier versions. So no worries. */
1312 microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1314 microblaze_no_unsafe_delay = 0;
1315 microblaze_pipe = MICROBLAZE_PIPE_3;
1318 || (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v4.00.b")
1322 microblaze_select_flags |= (MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1324 microblaze_no_unsafe_delay = 1;
1325 microblaze_pipe = MICROBLAZE_PIPE_3;
1329 /* We agree to use 5 pipe-stage model even on area optimized 3
1330 pipe-stage variants. */
1332 microblaze_select_flags &= ~(MICROBLAZE_MASK_NO_UNSAFE_DELAY);
1334 microblaze_no_unsafe_delay = 0;
1335 microblaze_pipe = MICROBLAZE_PIPE_5;
1336 if (MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v5.00.a") == 0
1337 || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1339 || MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu,
1342 /* Pattern compares are to be turned on by default only when
1343 compiling for MB v5.00.'z'. */
1344 target_flags |= MASK_PATTERN_COMPARE;
1348 ver = MICROBLAZE_VERSION_COMPARE (microblaze_select_cpu, "v6.00.a");
1351 if (TARGET_MULTIPLY_HIGH)
1353 "-mxl-multiply-high can be used only with -mcpu=v6.00.a or greater");
1356 if (TARGET_MULTIPLY_HIGH && TARGET_SOFT_MUL)
1357 error ("-mxl-multiply-high requires -mno-xl-soft-mul");
1359 /* Always use DFA scheduler. */
1360 microblaze_sched_use_dfa = 1;
1363 microblaze_abicalls = MICROBLAZE_ABICALLS_NO;
1366 /* Initialize the high, low values for legit floating point constants. */
1367 real_maxval (&dfhigh, 0, DFmode);
1368 real_maxval (&dflow, 1, DFmode);
1369 real_maxval (&sfhigh, 0, SFmode);
1370 real_maxval (&sflow, 1, SFmode);
1372 microblaze_print_operand_punct['?'] = 1;
1373 microblaze_print_operand_punct['#'] = 1;
1374 microblaze_print_operand_punct['&'] = 1;
1375 microblaze_print_operand_punct['!'] = 1;
1376 microblaze_print_operand_punct['*'] = 1;
1377 microblaze_print_operand_punct['@'] = 1;
1378 microblaze_print_operand_punct['.'] = 1;
1379 microblaze_print_operand_punct['('] = 1;
1380 microblaze_print_operand_punct[')'] = 1;
1381 microblaze_print_operand_punct['['] = 1;
1382 microblaze_print_operand_punct[']'] = 1;
1383 microblaze_print_operand_punct['<'] = 1;
1384 microblaze_print_operand_punct['>'] = 1;
1385 microblaze_print_operand_punct['{'] = 1;
1386 microblaze_print_operand_punct['}'] = 1;
1387 microblaze_print_operand_punct['^'] = 1;
1388 microblaze_print_operand_punct['$'] = 1;
1389 microblaze_print_operand_punct['+'] = 1;
1391 /* Set up array to map GCC register number to debug register number.
1392 Ignore the special purpose register numbers. */
1394 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1395 microblaze_dbx_regno[i] = -1;
1397 start = GP_DBX_FIRST - GP_REG_FIRST;
1398 for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
1399 microblaze_dbx_regno[i] = i + start;
1401 /* Set up array giving whether a given register can hold a given mode. */
1403 for (mode = VOIDmode;
1404 mode != MAX_MACHINE_MODE; mode = (enum machine_mode) ((int) mode + 1))
1406 register int size = GET_MODE_SIZE (mode);
1408 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1414 ok = (ST_REG_P (regno) || GP_REG_P (regno));
1416 else if (GP_REG_P (regno))
1417 ok = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
1421 microblaze_hard_regno_mode_ok[(int) mode][regno] = ok;
1426 /* Return true if FUNC is an interrupt function as specified
1427 by the "interrupt_handler" attribute. */
1430 microblaze_interrupt_function_p (tree func)
1434 if (TREE_CODE (func) != FUNCTION_DECL)
1437 a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
1438 return a != NULL_TREE;
1441 /* Return true if FUNC is an interrupt function which uses
1442 normal return, indicated by the "save_volatiles" attribute. */
1445 microblaze_save_volatiles (tree func)
1449 if (TREE_CODE (func) != FUNCTION_DECL)
1452 a = lookup_attribute ("save_volatiles", DECL_ATTRIBUTES (func));
1453 return a != NULL_TREE;
1456 /* Return whether function is tagged with 'interrupt_handler'
1457 attribute. Return true if function should use return from
1458 interrupt rather than normal function return. */
1460 microblaze_is_interrupt_handler (void)
1462 return interrupt_handler;
1465 /* Determine of register must be saved/restored in call. */
1467 microblaze_must_save_register (int regno)
1469 if (pic_offset_table_rtx &&
1470 (regno == MB_ABI_PIC_ADDR_REGNUM) && df_regs_ever_live_p (regno))
1473 if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
1476 if (frame_pointer_needed && (regno == HARD_FRAME_POINTER_REGNUM))
1479 if (!current_function_is_leaf)
1481 if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
1483 if ((interrupt_handler || save_volatiles) &&
1484 (regno >= 3 && regno <= 12))
1488 if (interrupt_handler)
1490 if (df_regs_ever_live_p (regno)
1491 || regno == MB_ABI_MSR_SAVE_REG
1492 || regno == MB_ABI_ASM_TEMP_REGNUM
1493 || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1499 if (df_regs_ever_live_p (regno)
1500 || regno == MB_ABI_ASM_TEMP_REGNUM
1501 || regno == MB_ABI_EXCEPTION_RETURN_ADDR_REGNUM)
1508 /* Return the bytes needed to compute the frame pointer from the current
1511 MicroBlaze stack frames look like:
1515 Before call After call
1516 +-----------------------+ +-----------------------+
1518 mem. | local variables, | | local variables, |
1519 | callee saved and | | callee saved and |
1521 +-----------------------+ +-----------------------+
1522 | arguments for called | | arguments for called |
1523 | subroutines | | subroutines |
1524 | (optional) | | (optional) |
1525 +-----------------------+ +-----------------------+
1526 | Link register | | Link register |
1528 +-----------------------+ +-----------------------+
1530 | local variables, |
1531 | callee saved and |
1533 +-----------------------+
1534 | MSR (optional if, |
1535 | interrupt handler) |
1536 +-----------------------+
1538 | alloca allocations |
1540 +-----------------------+
1542 | arguments for called |
1546 +-----------------------+
1549 memory +-----------------------+
1553 static HOST_WIDE_INT
1554 compute_frame_size (HOST_WIDE_INT size)
1557 HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
1558 HOST_WIDE_INT var_size; /* # bytes that local variables take up. */
1559 HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up. */
1560 int link_debug_size; /* # bytes for link register. */
1561 HOST_WIDE_INT gp_reg_size; /* # bytes needed to store calle-saved gp regs. */
1562 long mask; /* mask of saved gp registers. */
1565 microblaze_interrupt_function_p (current_function_decl);
1566 save_volatiles = microblaze_save_volatiles (current_function_decl);
1571 args_size = crtl->outgoing_args_size;
1573 if ((args_size == 0) && cfun->calls_alloca)
1574 args_size = NUM_OF_ARGS * UNITS_PER_WORD;
1576 total_size = var_size + args_size;
1579 /* force setting GOT. */
1580 df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true);
1582 /* Calculate space needed for gp registers. */
1583 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1585 if (microblaze_must_save_register (regno))
1588 if (regno != MB_ABI_SUB_RETURN_ADDR_REGNUM)
1589 /* Don't account for link register. It is accounted specially below. */
1590 gp_reg_size += GET_MODE_SIZE (SImode);
1592 mask |= (1L << (regno - GP_REG_FIRST));
1596 total_size += gp_reg_size;
1598 /* Add 4 bytes for MSR. */
1599 if (interrupt_handler)
1602 /* No space to be allocated for link register in leaf functions with no other
1603 stack requirements. */
1604 if (total_size == 0 && current_function_is_leaf)
1605 link_debug_size = 0;
1607 link_debug_size = UNITS_PER_WORD;
1609 total_size += link_debug_size;
1611 /* Save other computed information. */
1612 current_frame_info.total_size = total_size;
1613 current_frame_info.var_size = var_size;
1614 current_frame_info.args_size = args_size;
1615 current_frame_info.gp_reg_size = gp_reg_size;
1616 current_frame_info.mask = mask;
1617 current_frame_info.initialized = reload_completed;
1618 current_frame_info.num_gp = gp_reg_size / UNITS_PER_WORD;
1619 current_frame_info.link_debug_size = link_debug_size;
1622 /* Offset from which to callee-save GP regs. */
1623 current_frame_info.gp_offset = (total_size - gp_reg_size);
1625 current_frame_info.gp_offset = 0;
1627 /* Ok, we're done. */
1631 /* Make sure that we're not trying to eliminate to the wrong hard frame
1635 microblaze_can_eliminate (const int from, const int to)
1637 return ((from == RETURN_ADDRESS_POINTER_REGNUM && !leaf_function_p())
1638 || (to == MB_ABI_SUB_RETURN_ADDR_REGNUM && leaf_function_p())
1639 || (from != RETURN_ADDRESS_POINTER_REGNUM
1640 && (to == HARD_FRAME_POINTER_REGNUM
1641 || (to == STACK_POINTER_REGNUM && !frame_pointer_needed))));
1644 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
1645 pointer or argument pointer or the return address pointer. TO is either
1646 the stack pointer or hard frame pointer. */
1649 microblaze_initial_elimination_offset (int from, int to)
1651 HOST_WIDE_INT offset;
1655 case FRAME_POINTER_REGNUM:
1658 case ARG_POINTER_REGNUM:
1659 if (to == STACK_POINTER_REGNUM || to == HARD_FRAME_POINTER_REGNUM)
1660 offset = compute_frame_size (get_frame_size ());
1664 case RETURN_ADDRESS_POINTER_REGNUM:
1665 if (current_function_is_leaf)
1668 offset = current_frame_info.gp_offset +
1669 ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)));
1677 /* Print operands using format code.
1679 The MicroBlaze specific codes are:
1681 'X' X is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
1682 'x' X is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x",
1683 'F' op is CONST_DOUBLE, print 32 bits in hex,
1684 'd' output integer constant in decimal,
1685 'z' if the operand is 0, use $0 instead of normal operand.
1686 'D' print second register of double-word register operand.
1687 'L' print low-order register of double-word register operand.
1688 'M' print high-order register of double-word register operand.
1689 'C' print part of opcode for a branch condition.
1690 'N' print part of opcode for a branch condition, inverted.
1691 'S' X is CODE_LABEL, print with prefix of "LS" (for embedded switch).
1692 'B' print 'z' for EQ, 'n' for NE
1693 'b' print 'n' for EQ, 'z' for NE
1694 'T' print 'f' for EQ, 't' for NE
1695 't' print 't' for EQ, 'f' for NE
1696 'm' Print 1<<operand.
1697 'i' Print 'i' if MEM operand has immediate value
1698 'o' Print operand address+4
1699 '?' Print 'd' if we use a branch with delay slot instead of normal branch.
1700 'h' Print high word of const_double (int or float) value as hex
1701 'j' Print low word of const_double (int or float) value as hex
1702 's' Print -1 if operand is negative, 0 if positive (sign extend)
1703 '@' Print the name of the temporary register (rMB_ABI_ASM_TEMP_REGNUM).
1704 '#' Print nop if the delay slot of a branch is not filled.
1708 print_operand (FILE * file, rtx op, int letter)
1710 register enum rtx_code code;
1712 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
1717 /* Conditionally add a 'd' to indicate filled delay slot. */
1718 if (final_sequence != NULL)
1723 /* Conditionally add a nop in unfilled delay slot. */
1724 if (final_sequence == NULL)
1725 fputs ("nop\t\t# Unfilled delay slot\n", file);
1729 fputs (reg_names[GP_REG_FIRST + MB_ABI_ASM_TEMP_REGNUM], file);
1733 output_operand_lossage ("unknown punctuation '%c'", letter);
1742 output_operand_lossage ("null pointer");
1746 code = GET_CODE (op);
1748 if (code == SIGN_EXTEND)
1749 op = XEXP (op, 0), code = GET_CODE (op);
1777 fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
1780 else if (letter == 'N')
1806 fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
1809 else if (letter == 'S')
1813 ASM_GENERATE_INTERNAL_LABEL (buffer, "LS", CODE_LABEL_NUMBER (op));
1814 assemble_name (file, buffer);
1817 /* Print 'i' for memory operands which have immediate values. */
1818 else if (letter == 'i')
1822 struct microblaze_address_info info;
1824 if (!microblaze_classify_address
1825 (&info, XEXP (op, 0), GET_MODE (op), 1))
1826 fatal_insn ("insn contains an invalid address !", op);
1831 case ADDRESS_CONST_INT:
1832 case ADDRESS_SYMBOLIC:
1833 case ADDRESS_GOTOFF:
1836 case ADDRESS_REG_INDEX:
1838 case ADDRESS_INVALID:
1840 fatal_insn ("invalid address", op);
1845 else if (code == REG || code == SUBREG)
1847 register int regnum;
1850 regnum = REGNO (op);
1852 regnum = true_regnum (op);
1854 if ((letter == 'M' && !WORDS_BIG_ENDIAN)
1855 || (letter == 'L' && WORDS_BIG_ENDIAN) || letter == 'D')
1858 fprintf (file, "%s", reg_names[regnum]);
1861 else if (code == MEM)
1864 rtx op4 = adjust_address (op, GET_MODE (op), 4);
1865 output_address (XEXP (op4, 0));
1868 output_address (XEXP (op, 0));
1870 else if (letter == 'h' || letter == 'j')
1873 if (code == CONST_DOUBLE)
1875 if (GET_MODE (op) == DFmode)
1877 REAL_VALUE_TYPE value;
1878 REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1879 REAL_VALUE_TO_TARGET_DOUBLE (value, val);
1883 val[0] = CONST_DOUBLE_HIGH (op);
1884 val[1] = CONST_DOUBLE_LOW (op);
1887 else if (code == CONST_INT)
1889 val[0] = (INTVAL (op) & 0xffffffff00000000LL) >> 32;
1890 val[1] = INTVAL (op) & 0x00000000ffffffffLL;
1891 if (val[0] == 0 && val[1] < 0)
1895 fprintf (file, "0x%8.8lx", (letter == 'h') ? val[0] : val[1]);
1897 else if (code == CONST_DOUBLE)
1901 unsigned long value_long;
1902 REAL_VALUE_TYPE value;
1903 REAL_VALUE_FROM_CONST_DOUBLE (value, op);
1904 REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
1905 fprintf (file, HOST_WIDE_INT_PRINT_HEX, value_long);
1910 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
1915 else if (code == UNSPEC)
1917 print_operand_address (file, op);
1920 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
1921 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL (op));
1923 else if (letter == 'X' && GET_CODE (op) == CONST_INT)
1924 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
1926 else if (letter == 'd' && GET_CODE (op) == CONST_INT)
1927 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL (op)));
1929 else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
1930 fputs (reg_names[GP_REG_FIRST], file);
1932 else if (letter == 's' && GET_CODE (op) == CONST_INT)
1933 if (INTVAL (op) < 0)
1938 else if (letter == 'd' || letter == 'x' || letter == 'X' || letter == 's')
1939 output_operand_lossage ("letter %c was found & insn was not CONST_INT", letter);
1941 else if (letter == 'B')
1942 fputs (code == EQ ? "z" : "n", file);
1943 else if (letter == 'b')
1944 fputs (code == EQ ? "n" : "z", file);
1945 else if (letter == 'T')
1946 fputs (code == EQ ? "f" : "t", file);
1947 else if (letter == 't')
1948 fputs (code == EQ ? "t" : "f", file);
1950 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
1952 print_operand (file, XEXP (op, 0), letter);
1954 else if (letter == 'm')
1955 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (1L << INTVAL (op)));
1957 output_addr_const (file, op);
1960 /* A C compound statement to output to stdio stream STREAM the
1961 assembler syntax for an instruction operand that is a memory
1962 reference whose address is ADDR. ADDR is an RTL expression.
1964 Possible address classifications and output formats are,
1966 ADDRESS_REG "%0, r0"
1968 ADDRESS_REG with non-zero "%0, <addr_const>"
1971 ADDRESS_REG_INDEX "rA, RB"
1972 (if rA is r0, rA and rB are swapped)
1974 ADDRESS_CONST_INT "r0, <addr_const>"
1976 ADDRESS_SYMBOLIC "rBase, <addr_const>"
1977 (rBase is a base register suitable for the
1982 print_operand_address (FILE * file, rtx addr)
1984 struct microblaze_address_info info;
1985 enum microblaze_address_type type;
1986 if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1))
1987 fatal_insn ("insn contains an invalid address !", addr);
1993 fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
1994 output_addr_const (file, info.offset);
1996 case ADDRESS_REG_INDEX:
1997 if (REGNO (info.regA) == 0)
1998 /* Make rB == r0 instead of rA == r0. This helps reduce read port
2000 fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2001 reg_names[REGNO (info.regA)]);
2002 else if (REGNO (info.regB) != 0)
2003 /* This is a silly swap to help Dhrystone. */
2004 fprintf (file, "%s,%s", reg_names[REGNO (info.regB)],
2005 reg_names[REGNO (info.regA)]);
2007 case ADDRESS_CONST_INT:
2008 fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2009 output_addr_const (file, info.offset);
2011 case ADDRESS_SYMBOLIC:
2012 case ADDRESS_GOTOFF:
2015 fprintf (file, "%s,", reg_names[REGNO (info.regA)]);
2016 output_addr_const (file, info.symbol);
2017 if (type == ADDRESS_GOTOFF)
2019 fputs ("@GOT", file);
2021 else if (type == ADDRESS_PLT)
2023 fputs ("@PLT", file);
2026 case ADDRESS_INVALID:
2027 fatal_insn ("invalid address", addr);
2032 /* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
2033 is used, so that we don't emit an .extern for it in
2034 microblaze_asm_file_end. */
2037 microblaze_declare_object (FILE * stream, const char *name,
2038 const char *section, const char *fmt, int size)
2041 fputs (section, stream);
2042 assemble_name (stream, name);
2043 fprintf (stream, fmt, size);
2046 /* Common code to emit the insns (or to write the instructions to a file)
2047 to save/restore registers.
2049 Other parts of the code assume that MICROBLAZE_TEMP1_REGNUM (aka large_reg)
2050 is not modified within save_restore_insns. */
2052 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
2054 /* Save or restore instructions based on whether this is the prologue or
2055 epilogue. prologue is 1 for the prologue. */
2057 save_restore_insns (int prologue)
2059 rtx base_reg_rtx, reg_rtx, mem_rtx, /* msr_rtx, */ isr_reg_rtx =
2061 rtx isr_msr_rtx = 0, insn;
2062 long mask = current_frame_info.mask;
2063 HOST_WIDE_INT gp_offset;
2066 if (frame_pointer_needed
2067 && !BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
2073 /* Save registers starting from high to low. The debuggers prefer at least
2074 the return register be stored at func+4, and also it allows us not to
2075 need a nop in the epilog if at least one register is reloaded in
2076 addition to return address. */
2078 /* Pick which pointer to use as a base register. For small frames, just
2079 use the stack pointer. Otherwise, use a temporary register. Save 2
2080 cycles if the save area is near the end of a large frame, by reusing
2081 the constant created in the prologue/epilogue to adjust the stack
2084 gp_offset = current_frame_info.gp_offset;
2086 gcc_assert (gp_offset > 0);
2088 base_reg_rtx = stack_pointer_rtx;
2090 /* For interrupt_handlers, need to save/restore the MSR. */
2091 if (interrupt_handler)
2093 isr_mem_rtx = gen_rtx_MEM (SImode,
2094 gen_rtx_PLUS (Pmode, base_reg_rtx,
2095 GEN_INT (current_frame_info.
2099 /* Do not optimize in flow analysis. */
2100 MEM_VOLATILE_P (isr_mem_rtx) = 1;
2101 isr_reg_rtx = gen_rtx_REG (SImode, MB_ABI_MSR_SAVE_REG);
2102 isr_msr_rtx = gen_rtx_REG (SImode, ST_REG);
2105 if (interrupt_handler && !prologue)
2107 emit_move_insn (isr_reg_rtx, isr_mem_rtx);
2108 emit_move_insn (isr_msr_rtx, isr_reg_rtx);
2109 /* Do not optimize in flow analysis. */
2110 emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2111 emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2114 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
2116 if (BITSET_P (mask, regno - GP_REG_FIRST))
2118 if (regno == MB_ABI_SUB_RETURN_ADDR_REGNUM)
2119 /* Don't handle here. Already handled as the first register. */
2122 reg_rtx = gen_rtx_REG (SImode, regno);
2123 insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
2124 mem_rtx = gen_rtx_MEM (SImode, insn);
2125 if (interrupt_handler || save_volatiles)
2126 /* Do not optimize in flow analysis. */
2127 MEM_VOLATILE_P (mem_rtx) = 1;
2131 insn = emit_move_insn (mem_rtx, reg_rtx);
2132 RTX_FRAME_RELATED_P (insn) = 1;
2136 insn = emit_move_insn (reg_rtx, mem_rtx);
2139 gp_offset += GET_MODE_SIZE (SImode);
2143 if (interrupt_handler && prologue)
2145 emit_move_insn (isr_reg_rtx, isr_msr_rtx);
2146 emit_move_insn (isr_mem_rtx, isr_reg_rtx);
2148 /* Do not optimize in flow analysis. */
2149 emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
2150 emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
2153 /* Done saving and restoring */
2157 /* Set up the stack and frame (if desired) for the function. */
2159 microblaze_function_prologue (FILE * file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2162 long fsiz = current_frame_info.total_size;
2164 /* Get the function name the same way that toplev.c does before calling
2165 assemble_start_function. This is needed so that the name used here
2166 exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */
2167 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2168 if (!flag_inhibit_size_directive)
2170 fputs ("\t.ent\t", file);
2171 if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2172 fputs ("_interrupt_handler", file);
2174 assemble_name (file, fnname);
2176 if (!interrupt_handler)
2177 ASM_OUTPUT_TYPE_DIRECTIVE (file, fnname, "function");
2180 assemble_name (file, fnname);
2181 fputs (":\n", file);
2183 if (interrupt_handler && strcmp (INTERRUPT_HANDLER_NAME, fnname))
2184 fputs ("_interrupt_handler:\n", file);
2186 if (!flag_inhibit_size_directive)
2188 /* .frame FRAMEREG, FRAMESIZE, RETREG. */
2190 "\t.frame\t%s,%ld,%s\t\t# vars= %ld, regs= %d, args= %d\n",
2191 (reg_names[(frame_pointer_needed)
2192 ? HARD_FRAME_POINTER_REGNUM :
2193 STACK_POINTER_REGNUM]), fsiz,
2194 reg_names[MB_ABI_SUB_RETURN_ADDR_REGNUM + GP_REG_FIRST],
2195 current_frame_info.var_size, current_frame_info.num_gp,
2196 crtl->outgoing_args_size);
2197 fprintf (file, "\t.mask\t0x%08lx\n", current_frame_info.mask);
2201 /* Output extra assembler code at the end of a prologue. */
2203 microblaze_function_end_prologue (FILE * file)
2205 if (TARGET_STACK_CHECK)
2207 fprintf (file, "\t# Stack Check Stub -- Start.\n\t");
2208 fprintf (file, "ori\tr18,r0,_stack_end\n\t");
2209 fprintf (file, "cmpu\tr18,r1,r18\n\t");
2210 fprintf (file, "bgei\tr18,_stack_overflow_exit\n\t");
2211 fprintf (file, "# Stack Check Stub -- End.\n");
2215 /* Expand the prologue into a bunch of separate insns. */
2218 microblaze_expand_prologue (void)
2222 const char *arg_name = 0;
2223 tree fndecl = current_function_decl;
2224 tree fntype = TREE_TYPE (fndecl);
2225 tree fnargs = DECL_ARGUMENTS (fndecl);
2230 CUMULATIVE_ARGS args_so_far_v;
2231 cumulative_args_t args_so_far;
2232 rtx mem_rtx, reg_rtx;
2234 /* If struct value address is treated as the first argument, make it so. */
2235 if (aggregate_value_p (DECL_RESULT (fndecl), fntype)
2236 && !cfun->returns_pcc_struct)
2238 tree type = build_pointer_type (fntype);
2239 tree function_result_decl = build_decl (BUILTINS_LOCATION, PARM_DECL,
2242 DECL_ARG_TYPE (function_result_decl) = type;
2243 TREE_CHAIN (function_result_decl) = fnargs;
2244 fnargs = function_result_decl;
2247 /* Determine the last argument, and get its name. */
2249 INIT_CUMULATIVE_ARGS (args_so_far_v, fntype, NULL_RTX, 0, 0);
2250 args_so_far = pack_cumulative_args (&args_so_far_v);
2251 regno = GP_ARG_FIRST;
2253 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
2255 tree passed_type = DECL_ARG_TYPE (cur_arg);
2256 enum machine_mode passed_mode = TYPE_MODE (passed_type);
2259 if (TREE_ADDRESSABLE (passed_type))
2261 passed_type = build_pointer_type (passed_type);
2262 passed_mode = Pmode;
2265 entry_parm = targetm.calls.function_arg (args_so_far, passed_mode,
2272 /* passed in a register, so will get homed automatically. */
2273 if (GET_MODE (entry_parm) == BLKmode)
2274 words = (int_size_in_bytes (passed_type) + 3) / 4;
2276 words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
2278 regno = REGNO (entry_parm) + words - 1;
2282 regno = GP_ARG_LAST + 1;
2286 targetm.calls.function_arg_advance (args_so_far, passed_mode,
2289 next_arg = TREE_CHAIN (cur_arg);
2292 if (DECL_NAME (cur_arg))
2293 arg_name = IDENTIFIER_POINTER (DECL_NAME (cur_arg));
2299 /* Split parallel insn into a sequence of insns. */
2301 next_arg_reg = targetm.calls.function_arg (args_so_far, VOIDmode,
2302 void_type_node, true);
2303 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
2305 rtvec adjust = XVEC (next_arg_reg, 0);
2306 int num = GET_NUM_ELEM (adjust);
2308 for (i = 0; i < num; i++)
2310 rtx pattern = RTVEC_ELT (adjust, i);
2311 emit_insn (pattern);
2315 fsiz = compute_frame_size (get_frame_size ());
2317 /* If this function is a varargs function, store any registers that
2318 would normally hold arguments ($5 - $10) on the stack. */
2319 if (((TYPE_ARG_TYPES (fntype) != 0
2320 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2323 && ((arg_name[0] == '_'
2324 && strcmp (arg_name, "__builtin_va_alist") == 0)
2325 || (arg_name[0] == 'v'
2326 && strcmp (arg_name, "va_alist") == 0)))))
2328 int offset = (regno - GP_ARG_FIRST + 1) * UNITS_PER_WORD;
2329 rtx ptr = stack_pointer_rtx;
2331 /* If we are doing svr4-abi, sp has already been decremented by fsiz. */
2332 for (; regno <= GP_ARG_LAST; regno++)
2335 ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2336 emit_move_insn (gen_rtx_MEM (SImode, ptr),
2337 gen_rtx_REG (SImode, regno));
2339 offset += GET_MODE_SIZE (SImode);
2346 rtx fsiz_rtx = GEN_INT (fsiz);
2349 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2352 RTX_FRAME_RELATED_P (insn) = 1;
2354 /* Handle SUB_RETURN_ADDR_REGNUM specially at first. */
2355 if (!current_function_is_leaf || interrupt_handler)
2357 mem_rtx = gen_rtx_MEM (SImode,
2358 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2361 if (interrupt_handler)
2362 /* Do not optimize in flow analysis. */
2363 MEM_VOLATILE_P (mem_rtx) = 1;
2365 reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2366 insn = emit_move_insn (mem_rtx, reg_rtx);
2367 RTX_FRAME_RELATED_P (insn) = 1;
2370 /* _save_ registers for prologue. */
2371 save_restore_insns (1);
2373 if (frame_pointer_needed)
2377 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2378 stack_pointer_rtx));
2381 RTX_FRAME_RELATED_P (insn) = 1;
2385 if (flag_pic == 2 && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
2387 SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
2388 emit_insn (gen_set_got (pic_offset_table_rtx)); /* setting GOT. */
2391 /* If we are profiling, make sure no instructions are scheduled before
2392 the call to mcount. */
2395 emit_insn (gen_blockage ());
2398 /* Do necessary cleanup after a function to restore stack, frame, and regs. */
2400 #define RA_MASK ((long) 0x80000000) /* 1 << 31 */
2401 #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
2404 microblaze_function_epilogue (FILE * file ATTRIBUTE_UNUSED,
2405 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
2409 /* Get the function name the same way that toplev.c does before calling
2410 assemble_start_function. This is needed so that the name used here
2411 exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */
2412 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
2414 if (!flag_inhibit_size_directive)
2416 fputs ("\t.end\t", file);
2417 if (interrupt_handler)
2418 fputs ("_interrupt_handler", file);
2420 assemble_name (file, fnname);
2424 /* Reset state info for each function. */
2425 current_frame_info = zero_frame_info;
2427 /* Restore the output file if optimizing the GP (optimizing the GP causes
2428 the text to be diverted to a tempfile, so that data decls come before
2429 references to the data). */
2432 /* Expand the epilogue into a bunch of separate insns. */
2435 microblaze_expand_epilogue (void)
2437 HOST_WIDE_INT fsiz = current_frame_info.total_size;
2438 rtx fsiz_rtx = GEN_INT (fsiz);
2442 /* In case of interrupt handlers use addki instead of addi for changing the
2443 stack pointer value. */
2445 if (microblaze_can_use_return_insn ())
2447 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2449 MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2455 /* Restore SUB_RETURN_ADDR_REGNUM at first. This is to prevent the
2456 sequence of load-followed by a use (in rtsd) in every prologue. Saves
2457 a load-use stall cycle :) This is also important to handle alloca.
2458 (See comments for if (frame_pointer_needed) below. */
2460 if (!current_function_is_leaf || interrupt_handler)
2463 gen_rtx_MEM (SImode,
2464 gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx));
2465 if (interrupt_handler)
2466 /* Do not optimize in flow analysis. */
2467 MEM_VOLATILE_P (mem_rtx) = 1;
2468 reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
2469 emit_move_insn (reg_rtx, mem_rtx);
2472 /* It is important that this is done after we restore the return address
2473 register (above). When alloca is used, we want to restore the
2474 sub-routine return address only from the current stack top and not
2475 from the frame pointer (which we restore below). (frame_pointer + 0)
2476 might have been over-written since alloca allocates memory on the
2478 if (frame_pointer_needed)
2479 emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2481 /* _restore_ registers for epilogue. */
2482 save_restore_insns (0);
2483 emit_insn (gen_blockage ());
2484 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
2487 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
2488 MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2492 /* Return nonzero if this function is known to have a null epilogue.
2493 This allows the optimizer to omit jumps to jumps if no stack
2497 microblaze_can_use_return_insn (void)
2499 if (!reload_completed)
2502 if (df_regs_ever_live_p (MB_ABI_SUB_RETURN_ADDR_REGNUM) || profile_flag)
2505 if (current_frame_info.initialized)
2506 return current_frame_info.total_size == 0;
2508 return compute_frame_size (get_frame_size ()) == 0;
2511 /* Implement TARGET_SECONDARY_RELOAD. */
2514 microblaze_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
2515 reg_class_t rclass, enum machine_mode mode ATTRIBUTE_UNUSED,
2516 secondary_reload_info *sri ATTRIBUTE_UNUSED)
2518 if (rclass == ST_REGS)
2525 microblaze_globalize_label (FILE * stream, const char *name)
2527 fputs ("\t.globl\t", stream);
2528 if (interrupt_handler && strcmp (name, INTERRUPT_HANDLER_NAME))
2530 fputs (INTERRUPT_HANDLER_NAME, stream);
2531 fputs ("\n\t.globl\t", stream);
2533 assemble_name (stream, name);
2534 fputs ("\n", stream);
2537 /* Returns true if decl should be placed into a "small data" section. */
2539 microblaze_elf_in_small_data_p (const_tree decl)
2543 if (!TARGET_XLGPOPT)
2546 /* We want to merge strings, so we never consider them small data. */
2547 if (TREE_CODE (decl) == STRING_CST)
2550 /* Functions are never in the small data area. */
2551 if (TREE_CODE (decl) == FUNCTION_DECL)
2554 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
2556 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
2557 if (strcmp (section, ".sdata") == 0
2558 || strcmp (section, ".sdata2") == 0
2559 || strcmp (section, ".sbss") == 0
2560 || strcmp (section, ".sbss2") == 0)
2564 size = int_size_in_bytes (TREE_TYPE (decl));
2566 return (size > 0 && size <= microblaze_section_threshold);
2571 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2573 switch (categorize_decl_for_section (decl, reloc))
2575 case SECCAT_RODATA_MERGE_STR:
2576 case SECCAT_RODATA_MERGE_STR_INIT:
2577 /* MB binutils have various issues with mergeable string sections and
2578 relaxation/relocation. Currently, turning mergeable sections
2579 into regular readonly sections. */
2581 return readonly_data_section;
2583 return default_elf_select_section (decl, reloc, align);
2588 Encode info about sections into the RTL based on a symbol's declaration.
2589 The default definition of this hook, default_encode_section_info in
2590 `varasm.c', sets a number of commonly-useful bits in SYMBOL_REF_FLAGS. */
2593 microblaze_encode_section_info (tree decl, rtx rtl, int first)
2595 default_encode_section_info (decl, rtl, first);
2599 expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
2602 result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF);
2603 result = gen_rtx_CONST (Pmode, result);
2604 result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
2605 result = gen_const_mem (Pmode, result);
2610 microblaze_expand_move (enum machine_mode mode, rtx operands[])
2612 /* If operands[1] is a constant address invalid for pic, then we need to
2613 handle it just like LEGITIMIZE_ADDRESS does. */
2616 if (GET_CODE (operands[0]) == MEM)
2618 rtx addr = XEXP (operands[0], 0);
2619 if (GET_CODE (addr) == SYMBOL_REF)
2621 rtx ptr_reg, result;
2623 if (reload_in_progress)
2624 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2626 addr = expand_pic_symbol_ref (mode, addr);
2627 ptr_reg = gen_reg_rtx (Pmode);
2628 emit_move_insn (ptr_reg, addr);
2629 result = gen_rtx_MEM (mode, ptr_reg);
2630 operands[0] = result;
2633 if (GET_CODE (operands[1]) == SYMBOL_REF
2634 || GET_CODE (operands[1]) == LABEL_REF)
2637 if (reload_in_progress)
2638 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2639 result = expand_pic_symbol_ref (mode, operands[1]);
2640 if (GET_CODE (operands[0]) != REG)
2642 rtx ptr_reg = gen_reg_rtx (Pmode);
2643 emit_move_insn (ptr_reg, result);
2644 emit_move_insn (operands[0], ptr_reg);
2648 emit_move_insn (operands[0], result);
2652 else if (GET_CODE (operands[1]) == MEM &&
2653 GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
2657 if (reload_in_progress)
2658 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2659 result = expand_pic_symbol_ref (mode, XEXP (operands[1], 0));
2661 ptr_reg = gen_reg_rtx (Pmode);
2663 emit_move_insn (ptr_reg, result);
2664 result = gen_rtx_MEM (mode, ptr_reg);
2665 emit_move_insn (operands[0], result);
2668 else if (pic_address_needs_scratch (operands[1]))
2670 rtx temp = force_reg (SImode, XEXP (XEXP (operands[1], 0), 0));
2671 rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
2673 if (reload_in_progress)
2674 df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
2675 emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, temp2));
2680 if ((reload_in_progress | reload_completed) == 0
2681 && !register_operand (operands[0], SImode)
2682 && !register_operand (operands[1], SImode)
2683 && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0))
2685 rtx temp = force_reg (SImode, operands[1]);
2686 emit_move_insn (operands[0], temp);
2692 /* Expand shift operations. */
2694 microblaze_expand_shift (rtx operands[])
2696 gcc_assert ((GET_CODE (operands[2]) == CONST_INT)
2697 || (GET_CODE (operands[2]) == REG)
2698 || (GET_CODE (operands[2]) == SUBREG));
2700 /* Shift by one -- generate pattern. */
2701 if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 1))
2704 /* Have barrel shifter and shift > 1: use it. */
2705 if (TARGET_BARREL_SHIFT)
2708 gcc_assert ((GET_CODE (operands[0]) == REG)
2709 || (GET_CODE (operands[0]) == SUBREG)
2710 || (GET_CODE (operands[1]) == REG)
2711 || (GET_CODE (operands[1]) == SUBREG));
2713 /* Shift by zero -- copy regs if necessary. */
2714 if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
2716 if (REGNO (operands[0]) != REGNO (operands[1]))
2717 emit_insn (gen_movsi (operands[0], operands[1]));
2724 /* Return an RTX indicating where the return address to the
2725 calling function can be found. */
2727 microblaze_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
2732 return gen_rtx_PLUS (Pmode,
2733 get_hard_reg_initial_val (Pmode,
2734 MB_ABI_SUB_RETURN_ADDR_REGNUM),
2738 /* Put string into .sdata2 if below threashold. */
2740 microblaze_asm_output_ident (FILE *file ATTRIBUTE_UNUSED, const char *string)
2742 int size = strlen (string) + 1;
2743 if (size <= microblaze_section_threshold)
2744 switch_to_section (sdata2_section);
2746 switch_to_section (readonly_data_section);
2747 assemble_string (string, size);
2751 microblaze_elf_asm_init_sections (void)
2754 = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
2755 SDATA2_SECTION_ASM_OP);
2758 /* Generate assembler code for constant parts of a trampoline. */
2761 microblaze_asm_trampoline_template (FILE *f)
2763 fprintf (f, "\t.word\t0x03e00821\t\t# move $1,$31\n");
2764 fprintf (f, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n");
2765 fprintf (f, "\t.word\t0x00000000\t\t# nop\n");
2766 fprintf (f, "\t.word\t0x8fe30014\t\t# lw $3,20($31)\n");
2767 fprintf (f, "\t.word\t0x8fe20018\t\t# lw $2,24($31)\n");
2768 fprintf (f, "\t.word\t0x0060c821\t\t# move $25,$3 (abicalls)\n");
2769 fprintf (f, "\t.word\t0x00600008\t\t# jr $3\n");
2770 fprintf (f, "\t.word\t0x0020f821\t\t# move $31,$1\n");
2771 /* fprintf (f, "\t.word\t0x00000000\t\t# <function address>\n"); */
2772 /* fprintf (f, "\t.word\t0x00000000\t\t# <static chain value>\n"); */
2775 /* Implement TARGET_TRAMPOLINE_INIT. */
2778 microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2780 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2783 emit_block_move (m_tramp, assemble_trampoline_template (),
2784 GEN_INT (8*UNITS_PER_WORD), BLOCK_OP_NORMAL);
2786 mem = adjust_address (m_tramp, SImode, 8);
2787 emit_move_insn (mem, chain_value);
2788 mem = adjust_address (m_tramp, SImode, 12);
2789 emit_move_insn (mem, fnaddr);
2792 /* Emit instruction to perform compare.
2793 cmp is (compare_op op0 op1). */
2795 microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
2797 rtx cmp_op0 = XEXP (cmp, 0);
2798 rtx cmp_op1 = XEXP (cmp, 1);
2799 rtx comp_reg = gen_reg_rtx (SImode);
2800 enum rtx_code code = *cmp_code;
2802 gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
2804 /* If comparing against zero, just test source reg. */
2805 if (cmp_op1 == const0_rtx)
2808 if (code == EQ || code == NE)
2810 if (TARGET_PATTERN_COMPARE && GET_CODE(cmp_op1) == REG)
2813 emit_insn (gen_seq_internal_pat (comp_reg, cmp_op0, cmp_op1));
2816 emit_insn (gen_sne_internal_pat (comp_reg, cmp_op0, cmp_op1));
2821 /* Use xor for equal/not-equal comparison. */
2822 emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
2824 else if (code == GT || code == GTU || code == LE || code == LEU)
2826 /* MicroBlaze compare is not symmetrical. */
2827 /* Swap argument order. */
2828 cmp_op1 = force_reg (mode, cmp_op1);
2829 if (code == GT || code == LE)
2830 emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
2832 emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
2833 /* Translate test condition. */
2834 *cmp_code = swap_condition (code);
2836 else /* if (code == GE || code == GEU || code == LT || code == LTU) */
2838 cmp_op1 = force_reg (mode, cmp_op1);
2839 if (code == GE || code == LT)
2840 emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
2842 emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
2848 /* Generate conditional branch -- first, generate test condition,
2849 second, generate correct branch instruction. */
2852 microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
2854 enum rtx_code code = GET_CODE (operands[0]);
2858 comp = microblaze_emit_compare (mode, operands[0], &code);
2859 condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
2860 emit_jump_insn (gen_condjump (condition, operands[3]));
2864 microblaze_expand_conditional_branch_sf (rtx operands[])
2867 rtx cmp_op0 = XEXP (operands[0], 0);
2868 rtx cmp_op1 = XEXP (operands[0], 1);
2869 rtx comp_reg = gen_reg_rtx (SImode);
2871 emit_insn (gen_cstoresf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
2872 condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
2873 emit_jump_insn (gen_condjump (condition, operands[3]));
2876 /* Implement TARGET_FRAME_POINTER_REQUIRED. */
2879 microblaze_frame_pointer_required (void)
2881 /* If the function contains dynamic stack allocations, we need to
2882 use the frame pointer to access the static parts of the frame. */
2883 if (cfun->calls_alloca)
2889 microblaze_expand_divide (rtx operands[])
2891 /* Table lookup software divides. Works for all (nr/dr) where (0 <= nr,dr <= 15). */
2893 rtx regt1 = gen_reg_rtx (SImode);
2894 rtx reg18 = gen_rtx_REG (SImode, R_TMP);
2895 rtx regqi = gen_reg_rtx (QImode);
2896 rtx div_label = gen_label_rtx ();
2897 rtx div_end_label = gen_label_rtx ();
2898 rtx div_table_rtx = gen_rtx_SYMBOL_REF (QImode,"_divsi3_table");
2901 rtx jump, cjump, insn;
2903 insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
2904 cjump = emit_jump_insn_after (gen_cbranchsi4 (
2905 gen_rtx_GTU (SImode, regt1, GEN_INT (15)),
2906 regt1, GEN_INT (15), div_label), insn);
2907 LABEL_NUSES (div_label) = 1;
2908 JUMP_LABEL (cjump) = div_label;
2909 emit_insn (gen_rtx_CLOBBER (SImode, reg18));
2911 emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
2912 emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
2913 mem_rtx = gen_rtx_MEM (QImode,
2914 gen_rtx_PLUS (Pmode, regt1, div_table_rtx));
2916 insn = emit_insn (gen_movqi (regqi, mem_rtx));
2917 insn = emit_insn (gen_movsi (operands[0], gen_rtx_SUBREG (SImode, regqi, 0)));
2918 jump = emit_jump_insn_after (gen_jump (div_end_label), insn);
2919 JUMP_LABEL (jump) = div_end_label;
2920 LABEL_NUSES (div_end_label) = 1;
2923 emit_label (div_label);
2924 ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, "__divsi3"),
2925 operands[0], LCT_NORMAL,
2926 GET_MODE (operands[0]), 2, operands[1],
2927 GET_MODE (operands[1]), operands[2],
2928 GET_MODE (operands[2]));
2929 if (ret != operands[0])
2930 emit_move_insn (operands[0], ret);
2932 emit_label (div_end_label);
2933 emit_insn (gen_blockage ());
2936 /* Implement TARGET_FUNCTION_VALUE. */
2938 microblaze_function_value (const_tree valtype,
2939 const_tree func ATTRIBUTE_UNUSED,
2940 bool outgoing ATTRIBUTE_UNUSED)
2942 return LIBCALL_VALUE (TYPE_MODE (valtype));
2945 /* Implement TARGET_SCHED_ADJUST_COST. */
2947 microblaze_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
2948 rtx dep ATTRIBUTE_UNUSED, int cost)
2950 if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
2952 if (REG_NOTE_KIND (link) != 0)
2957 /* Implement TARGET_LEGITIMATE_CONSTANT_P.
2959 At present, GAS doesn't understand li.[sd], so don't allow it
2960 to be generated at present. */
2962 microblaze_legitimate_constant_p (enum machine_mode mode, rtx x)
2964 return GET_CODE (x) != CONST_DOUBLE || microblaze_const_double_ok (x, mode);
2967 #undef TARGET_ENCODE_SECTION_INFO
2968 #define TARGET_ENCODE_SECTION_INFO microblaze_encode_section_info
2970 #undef TARGET_ASM_GLOBALIZE_LABEL
2971 #define TARGET_ASM_GLOBALIZE_LABEL microblaze_globalize_label
2973 #undef TARGET_ASM_FUNCTION_PROLOGUE
2974 #define TARGET_ASM_FUNCTION_PROLOGUE microblaze_function_prologue
2976 #undef TARGET_ASM_FUNCTION_EPILOGUE
2977 #define TARGET_ASM_FUNCTION_EPILOGUE microblaze_function_epilogue
2979 #undef TARGET_RTX_COSTS
2980 #define TARGET_RTX_COSTS microblaze_rtx_costs
2982 #undef TARGET_ADDRESS_COST
2983 #define TARGET_ADDRESS_COST microblaze_address_cost
2985 #undef TARGET_ATTRIBUTE_TABLE
2986 #define TARGET_ATTRIBUTE_TABLE microblaze_attribute_table
2988 #undef TARGET_IN_SMALL_DATA_P
2989 #define TARGET_IN_SMALL_DATA_P microblaze_elf_in_small_data_p
2991 #undef TARGET_ASM_SELECT_SECTION
2992 #define TARGET_ASM_SELECT_SECTION microblaze_select_section
2994 #undef TARGET_HAVE_SRODATA_SECTION
2995 #define TARGET_HAVE_SRODATA_SECTION true
2997 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
2998 #define TARGET_ASM_FUNCTION_END_PROLOGUE \
2999 microblaze_function_end_prologue
3001 #undef TARGET_ARG_PARTIAL_BYTES
3002 #define TARGET_ARG_PARTIAL_BYTES function_arg_partial_bytes
3004 #undef TARGET_FUNCTION_ARG
3005 #define TARGET_FUNCTION_ARG microblaze_function_arg
3007 #undef TARGET_FUNCTION_ARG_ADVANCE
3008 #define TARGET_FUNCTION_ARG_ADVANCE microblaze_function_arg_advance
3010 #undef TARGET_CAN_ELIMINATE
3011 #define TARGET_CAN_ELIMINATE microblaze_can_eliminate
3013 #undef TARGET_LEGITIMIZE_ADDRESS
3014 #define TARGET_LEGITIMIZE_ADDRESS microblaze_legitimize_address
3016 #undef TARGET_LEGITIMATE_ADDRESS_P
3017 #define TARGET_LEGITIMATE_ADDRESS_P microblaze_legitimate_address_p
3019 #undef TARGET_FRAME_POINTER_REQUIRED
3020 #define TARGET_FRAME_POINTER_REQUIRED microblaze_frame_pointer_required
3022 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
3023 #define TARGET_ASM_TRAMPOLINE_TEMPLATE microblaze_asm_trampoline_template
3025 #undef TARGET_TRAMPOLINE_INIT
3026 #define TARGET_TRAMPOLINE_INIT microblaze_trampoline_init
3028 #undef TARGET_PROMOTE_FUNCTION_MODE
3029 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
3031 #undef TARGET_FUNCTION_VALUE
3032 #define TARGET_FUNCTION_VALUE microblaze_function_value
3034 #undef TARGET_SECONDARY_RELOAD
3035 #define TARGET_SECONDARY_RELOAD microblaze_secondary_reload
3037 #undef TARGET_SCHED_ADJUST_COST
3038 #define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost
3040 #undef TARGET_ASM_INIT_SECTIONS
3041 #define TARGET_ASM_INIT_SECTIONS microblaze_elf_asm_init_sections
3043 #undef TARGET_OPTION_OVERRIDE
3044 #define TARGET_OPTION_OVERRIDE microblaze_option_override
3046 #undef TARGET_LEGITIMATE_CONSTANT_P
3047 #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p
3049 struct gcc_target targetm = TARGET_INITIALIZER;
3051 #include "gt-microblaze.h"