1 /* Subroutines used for code generation on the Lattice Mico32 architecture.
2 Contributed by Jon Beniston <jon@beniston.com>
4 Copyright (C) 2009-2015 Free Software Foundation, Inc.
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"
40 #include "tm-constrs.h"
43 /* This file should be included last. */
44 #include "target-def.h"
46 struct lm32_frame_info
48 HOST_WIDE_INT total_size
; /* number of bytes of entire frame. */
49 HOST_WIDE_INT callee_size
; /* number of bytes to save callee saves. */
50 HOST_WIDE_INT pretend_size
; /* number of bytes we pretend caller did. */
51 HOST_WIDE_INT args_size
; /* number of bytes for outgoing arguments. */
52 HOST_WIDE_INT locals_size
; /* number of bytes for local variables. */
53 unsigned int reg_save_mask
; /* mask of saved registers. */
56 /* Prototypes for static functions. */
57 static rtx
emit_add (rtx dest
, rtx src0
, rtx src1
);
58 static void expand_save_restore (struct lm32_frame_info
*info
, int op
);
59 static void stack_adjust (HOST_WIDE_INT amount
);
60 static bool lm32_in_small_data_p (const_tree
);
61 static void lm32_setup_incoming_varargs (cumulative_args_t cum
,
62 machine_mode mode
, tree type
,
63 int *pretend_size
, int no_rtl
);
64 static bool lm32_rtx_costs (rtx x
, machine_mode mode
, int outer_code
, int opno
,
65 int *total
, bool speed
);
66 static bool lm32_can_eliminate (const int, const int);
68 lm32_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
);
69 static HOST_WIDE_INT
lm32_compute_frame_size (int size
);
70 static void lm32_option_override (void);
71 static rtx
lm32_function_arg (cumulative_args_t cum
,
72 machine_mode mode
, const_tree type
,
74 static void lm32_function_arg_advance (cumulative_args_t cum
,
76 const_tree type
, bool named
);
78 #undef TARGET_OPTION_OVERRIDE
79 #define TARGET_OPTION_OVERRIDE lm32_option_override
80 #undef TARGET_ADDRESS_COST
81 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
82 #undef TARGET_RTX_COSTS
83 #define TARGET_RTX_COSTS lm32_rtx_costs
84 #undef TARGET_IN_SMALL_DATA_P
85 #define TARGET_IN_SMALL_DATA_P lm32_in_small_data_p
86 #undef TARGET_PROMOTE_FUNCTION_MODE
87 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
88 #undef TARGET_SETUP_INCOMING_VARARGS
89 #define TARGET_SETUP_INCOMING_VARARGS lm32_setup_incoming_varargs
90 #undef TARGET_FUNCTION_ARG
91 #define TARGET_FUNCTION_ARG lm32_function_arg
92 #undef TARGET_FUNCTION_ARG_ADVANCE
93 #define TARGET_FUNCTION_ARG_ADVANCE lm32_function_arg_advance
94 #undef TARGET_PROMOTE_PROTOTYPES
95 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
96 #undef TARGET_MIN_ANCHOR_OFFSET
97 #define TARGET_MIN_ANCHOR_OFFSET -0x8000
98 #undef TARGET_MAX_ANCHOR_OFFSET
99 #define TARGET_MAX_ANCHOR_OFFSET 0x7fff
100 #undef TARGET_CAN_ELIMINATE
101 #define TARGET_CAN_ELIMINATE lm32_can_eliminate
102 #undef TARGET_LEGITIMATE_ADDRESS_P
103 #define TARGET_LEGITIMATE_ADDRESS_P lm32_legitimate_address_p
105 struct gcc_target targetm
= TARGET_INITIALIZER
;
107 /* Current frame information calculated by lm32_compute_frame_size. */
108 static struct lm32_frame_info current_frame_info
;
110 /* Return non-zero if the given return type should be returned in memory. */
113 lm32_return_in_memory (tree type
)
117 if (!AGGREGATE_TYPE_P (type
))
119 /* All simple types are returned in registers. */
123 size
= int_size_in_bytes (type
);
124 if (size
>= 0 && size
<= UNITS_PER_WORD
)
126 /* If it can fit in one register. */
133 /* Generate an emit a word sized add instruction. */
136 emit_add (rtx dest
, rtx src0
, rtx src1
)
139 insn
= emit_insn (gen_addsi3 (dest
, src0
, src1
));
143 /* Generate the code to compare (and possibly branch) two integer values
144 TEST_CODE is the comparison code we are trying to emulate
145 (or implement directly)
146 RESULT is where to store the result of the comparison,
147 or null to emit a branch
148 CMP0 CMP1 are the two comparison operands
149 DESTINATION is the destination of the branch, or null to only compare
153 gen_int_relational (enum rtx_code code
,
162 mode
= GET_MODE (cmp0
);
163 if (mode
== VOIDmode
)
164 mode
= GET_MODE (cmp1
);
166 /* Is this a branch or compare. */
167 branch_p
= (destination
!= 0);
169 /* Instruction set doesn't support LE or LT, so swap operands and use
180 code
= swap_condition (code
);
192 rtx insn
, cond
, label
;
194 /* Operands must be in registers. */
195 if (!register_operand (cmp0
, mode
))
196 cmp0
= force_reg (mode
, cmp0
);
197 if (!register_operand (cmp1
, mode
))
198 cmp1
= force_reg (mode
, cmp1
);
200 /* Generate conditional branch instruction. */
201 cond
= gen_rtx_fmt_ee (code
, mode
, cmp0
, cmp1
);
202 label
= gen_rtx_LABEL_REF (VOIDmode
, destination
);
203 insn
= gen_rtx_SET (pc_rtx
, gen_rtx_IF_THEN_ELSE (VOIDmode
,
204 cond
, label
, pc_rtx
));
205 emit_jump_insn (insn
);
209 /* We can't have const_ints in cmp0, other than 0. */
210 if ((GET_CODE (cmp0
) == CONST_INT
) && (INTVAL (cmp0
) != 0))
211 cmp0
= force_reg (mode
, cmp0
);
213 /* If the comparison is against an int not in legal range
214 move it into a register. */
215 if (GET_CODE (cmp1
) == CONST_INT
)
225 if (!satisfies_constraint_K (cmp1
))
226 cmp1
= force_reg (mode
, cmp1
);
232 if (!satisfies_constraint_L (cmp1
))
233 cmp1
= force_reg (mode
, cmp1
);
240 /* Generate compare instruction. */
241 emit_move_insn (result
, gen_rtx_fmt_ee (code
, mode
, cmp0
, cmp1
));
245 /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
246 and OPERAND[3]. Store the result in OPERANDS[0]. */
249 lm32_expand_scc (rtx operands
[])
251 rtx target
= operands
[0];
252 enum rtx_code code
= GET_CODE (operands
[1]);
253 rtx op0
= operands
[2];
254 rtx op1
= operands
[3];
256 gen_int_relational (code
, target
, op0
, op1
, NULL_RTX
);
259 /* Compare OPERANDS[1] with OPERANDS[2] using comparison code
260 CODE and jump to OPERANDS[3] if the condition holds. */
263 lm32_expand_conditional_branch (rtx operands
[])
265 enum rtx_code code
= GET_CODE (operands
[0]);
266 rtx op0
= operands
[1];
267 rtx op1
= operands
[2];
268 rtx destination
= operands
[3];
270 gen_int_relational (code
, NULL_RTX
, op0
, op1
, destination
);
273 /* Generate and emit RTL to save or restore callee save registers. */
275 expand_save_restore (struct lm32_frame_info
*info
, int op
)
277 unsigned int reg_save_mask
= info
->reg_save_mask
;
279 HOST_WIDE_INT offset
;
282 /* Callee saves are below locals and above outgoing arguments. */
283 offset
= info
->args_size
+ info
->callee_size
;
284 for (regno
= 0; regno
<= 31; regno
++)
286 if ((reg_save_mask
& (1 << regno
)) != 0)
291 offset_rtx
= GEN_INT (offset
);
292 if (satisfies_constraint_K (offset_rtx
))
294 mem
= gen_rtx_MEM (word_mode
,
301 /* r10 is caller saved so it can be used as a temp reg. */
304 r10
= gen_rtx_REG (word_mode
, 10);
305 insn
= emit_move_insn (r10
, offset_rtx
);
307 RTX_FRAME_RELATED_P (insn
) = 1;
308 insn
= emit_add (r10
, r10
, stack_pointer_rtx
);
310 RTX_FRAME_RELATED_P (insn
) = 1;
311 mem
= gen_rtx_MEM (word_mode
, r10
);
315 insn
= emit_move_insn (mem
, gen_rtx_REG (word_mode
, regno
));
317 insn
= emit_move_insn (gen_rtx_REG (word_mode
, regno
), mem
);
319 /* only prologue instructions which set the sp fp or save a
320 register should be marked as frame related. */
322 RTX_FRAME_RELATED_P (insn
) = 1;
323 offset
-= UNITS_PER_WORD
;
329 stack_adjust (HOST_WIDE_INT amount
)
333 if (!IN_RANGE (amount
, -32776, 32768))
335 /* r10 is caller saved so it can be used as a temp reg. */
337 r10
= gen_rtx_REG (word_mode
, 10);
338 insn
= emit_move_insn (r10
, GEN_INT (amount
));
340 RTX_FRAME_RELATED_P (insn
) = 1;
341 insn
= emit_add (stack_pointer_rtx
, stack_pointer_rtx
, r10
);
343 RTX_FRAME_RELATED_P (insn
) = 1;
347 insn
= emit_add (stack_pointer_rtx
,
348 stack_pointer_rtx
, GEN_INT (amount
));
350 RTX_FRAME_RELATED_P (insn
) = 1;
355 /* Create and emit instructions for a functions prologue. */
357 lm32_expand_prologue (void)
361 lm32_compute_frame_size (get_frame_size ());
363 if (current_frame_info
.total_size
> 0)
365 /* Add space on stack new frame. */
366 stack_adjust (-current_frame_info
.total_size
);
368 /* Save callee save registers. */
369 if (current_frame_info
.reg_save_mask
!= 0)
370 expand_save_restore (¤t_frame_info
, 0);
372 /* Setup frame pointer if it's needed. */
373 if (frame_pointer_needed
== 1)
376 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
377 RTX_FRAME_RELATED_P (insn
) = 1;
379 /* Add offset - Don't use total_size, as that includes pretend_size,
380 which isn't part of this frame? */
381 insn
= emit_add (frame_pointer_rtx
,
383 GEN_INT (current_frame_info
.args_size
+
384 current_frame_info
.callee_size
+
385 current_frame_info
.locals_size
));
386 RTX_FRAME_RELATED_P (insn
) = 1;
389 /* Prevent prologue from being scheduled into function body. */
390 emit_insn (gen_blockage ());
394 /* Create an emit instructions for a functions epilogue. */
396 lm32_expand_epilogue (void)
398 rtx ra_rtx
= gen_rtx_REG (Pmode
, RA_REGNUM
);
400 lm32_compute_frame_size (get_frame_size ());
402 if (current_frame_info
.total_size
> 0)
404 /* Prevent stack code from being reordered. */
405 emit_insn (gen_blockage ());
407 /* Restore callee save registers. */
408 if (current_frame_info
.reg_save_mask
!= 0)
409 expand_save_restore (¤t_frame_info
, 1);
411 /* Deallocate stack. */
412 stack_adjust (current_frame_info
.total_size
);
414 /* Return to calling function. */
415 emit_jump_insn (gen_return_internal (ra_rtx
));
419 /* Return to calling function. */
420 emit_jump_insn (gen_return_internal (ra_rtx
));
424 /* Return the bytes needed to compute the frame pointer from the current
427 lm32_compute_frame_size (int size
)
430 HOST_WIDE_INT total_size
, locals_size
, args_size
, pretend_size
, callee_size
;
431 unsigned int reg_save_mask
;
434 args_size
= crtl
->outgoing_args_size
;
435 pretend_size
= crtl
->args
.pretend_args_size
;
439 /* Build mask that actually determines which regsiters we save
440 and calculate size required to store them in the stack. */
441 for (regno
= 1; regno
< SP_REGNUM
; regno
++)
443 if (df_regs_ever_live_p (regno
) && !call_used_regs
[regno
])
445 reg_save_mask
|= 1 << regno
;
446 callee_size
+= UNITS_PER_WORD
;
449 if (df_regs_ever_live_p (RA_REGNUM
) || ! crtl
->is_leaf
452 reg_save_mask
|= 1 << RA_REGNUM
;
453 callee_size
+= UNITS_PER_WORD
;
455 if (!(reg_save_mask
& (1 << FP_REGNUM
)) && frame_pointer_needed
)
457 reg_save_mask
|= 1 << FP_REGNUM
;
458 callee_size
+= UNITS_PER_WORD
;
461 /* Compute total frame size. */
462 total_size
= pretend_size
+ args_size
+ locals_size
+ callee_size
;
464 /* Align frame to appropriate boundary. */
465 total_size
= (total_size
+ 3) & ~3;
467 /* Save computed information. */
468 current_frame_info
.total_size
= total_size
;
469 current_frame_info
.callee_size
= callee_size
;
470 current_frame_info
.pretend_size
= pretend_size
;
471 current_frame_info
.locals_size
= locals_size
;
472 current_frame_info
.args_size
= args_size
;
473 current_frame_info
.reg_save_mask
= reg_save_mask
;
479 lm32_print_operand (FILE * file
, rtx op
, int letter
)
483 code
= GET_CODE (op
);
485 if (code
== SIGN_EXTEND
)
486 op
= XEXP (op
, 0), code
= GET_CODE (op
);
487 else if (code
== REG
|| code
== SUBREG
)
494 regnum
= true_regnum (op
);
496 fprintf (file
, "%s", reg_names
[regnum
]);
498 else if (code
== HIGH
)
499 output_addr_const (file
, XEXP (op
, 0));
500 else if (code
== MEM
)
501 output_address (XEXP (op
, 0));
502 else if (letter
== 'z' && GET_CODE (op
) == CONST_INT
&& INTVAL (op
) == 0)
503 fprintf (file
, "%s", reg_names
[0]);
504 else if (GET_CODE (op
) == CONST_DOUBLE
)
506 if ((CONST_DOUBLE_LOW (op
) != 0) || (CONST_DOUBLE_HIGH (op
) != 0))
507 output_operand_lossage ("only 0.0 can be loaded as an immediate");
512 fprintf (file
, "e ");
514 fprintf (file
, "ne ");
516 fprintf (file
, "g ");
517 else if (code
== GTU
)
518 fprintf (file
, "gu ");
520 fprintf (file
, "l ");
521 else if (code
== LTU
)
522 fprintf (file
, "lu ");
524 fprintf (file
, "ge ");
525 else if (code
== GEU
)
526 fprintf (file
, "geu");
528 fprintf (file
, "le ");
529 else if (code
== LEU
)
530 fprintf (file
, "leu");
532 output_addr_const (file
, op
);
535 /* A C compound statement to output to stdio stream STREAM the
536 assembler syntax for an instruction operand that is a memory
537 reference whose address is ADDR. ADDR is an RTL expression.
539 On some machines, the syntax for a symbolic address depends on
540 the section that the address refers to. On these machines,
541 define the macro `ENCODE_SECTION_INFO' to store the information
542 into the `symbol_ref', and then check for it here. */
545 lm32_print_operand_address (FILE * file
, rtx addr
)
547 switch (GET_CODE (addr
))
550 fprintf (file
, "(%s+0)", reg_names
[REGNO (addr
)]);
554 output_address (XEXP (addr
, 0));
559 rtx arg0
= XEXP (addr
, 0);
560 rtx arg1
= XEXP (addr
, 1);
562 if (GET_CODE (arg0
) == REG
&& CONSTANT_P (arg1
))
564 if (GET_CODE (arg1
) == CONST_INT
)
565 fprintf (file
, "(%s+%ld)", reg_names
[REGNO (arg0
)],
569 fprintf (file
, "(%s+", reg_names
[REGNO (arg0
)]);
570 output_addr_const (file
, arg1
);
574 else if (CONSTANT_P (arg0
) && CONSTANT_P (arg1
))
575 output_addr_const (file
, addr
);
577 fatal_insn ("bad operand", addr
);
582 if (SYMBOL_REF_SMALL_P (addr
))
584 fprintf (file
, "gp(");
585 output_addr_const (file
, addr
);
589 fatal_insn ("can't use non gp relative absolute address", addr
);
593 fatal_insn ("invalid addressing mode", addr
);
598 /* Determine where to put an argument to a function.
599 Value is zero to push the argument on the stack,
600 or a hard register in which to store the argument.
602 MODE is the argument's machine mode.
603 TYPE is the data type of the argument (as a tree).
604 This is null for libcalls where that information may
606 CUM is a variable of type CUMULATIVE_ARGS which gives info about
607 the preceding args and about the function being called.
608 NAMED is nonzero if this argument is a named parameter
609 (otherwise it is an extra parameter matching an ellipsis). */
612 lm32_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
613 const_tree type
, bool named
)
615 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
617 if (mode
== VOIDmode
)
618 /* Compute operand 2 of the call insn. */
621 if (targetm
.calls
.must_pass_in_stack (mode
, type
))
624 if (!named
|| (*cum
+ LM32_NUM_REGS2 (mode
, type
) > LM32_NUM_ARG_REGS
))
627 return gen_rtx_REG (mode
, *cum
+ LM32_FIRST_ARG_REG
);
631 lm32_function_arg_advance (cumulative_args_t cum
, machine_mode mode
,
632 const_tree type
, bool named ATTRIBUTE_UNUSED
)
634 *get_cumulative_args (cum
) += LM32_NUM_REGS2 (mode
, type
);
638 lm32_compute_initial_elimination_offset (int from
, int to
)
640 HOST_WIDE_INT offset
= 0;
644 case ARG_POINTER_REGNUM
:
647 case FRAME_POINTER_REGNUM
:
650 case STACK_POINTER_REGNUM
:
652 lm32_compute_frame_size (get_frame_size ()) -
653 current_frame_info
.pretend_size
;
667 lm32_setup_incoming_varargs (cumulative_args_t cum_v
, machine_mode mode
,
668 tree type
, int *pretend_size
, int no_rtl
)
670 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
674 fntype
= TREE_TYPE (current_function_decl
);
676 if (stdarg_p (fntype
))
677 first_anon_arg
= *cum
+ LM32_FIRST_ARG_REG
;
680 /* this is the common case, we have been passed details setup
681 for the last named argument, we want to skip over the
682 registers, if any used in passing this named paramter in
683 order to determine which is the first registers used to pass
684 anonymous arguments. */
688 size
= int_size_in_bytes (type
);
690 size
= GET_MODE_SIZE (mode
);
693 *cum
+ LM32_FIRST_ARG_REG
+
694 ((size
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
697 if ((first_anon_arg
< (LM32_FIRST_ARG_REG
+ LM32_NUM_ARG_REGS
)) && !no_rtl
)
699 int first_reg_offset
= first_anon_arg
;
700 int size
= LM32_FIRST_ARG_REG
+ LM32_NUM_ARG_REGS
- first_anon_arg
;
703 regblock
= gen_rtx_MEM (BLKmode
,
704 plus_constant (Pmode
, arg_pointer_rtx
,
705 FIRST_PARM_OFFSET (0)));
706 move_block_from_reg (first_reg_offset
, regblock
, size
);
708 *pretend_size
= size
* UNITS_PER_WORD
;
712 /* Override command line options. */
714 lm32_option_override (void)
716 /* We must have sign-extend enabled if barrel-shift isn't. */
717 if (!TARGET_BARREL_SHIFT_ENABLED
&& !TARGET_SIGN_EXTEND_ENABLED
)
718 target_flags
|= MASK_SIGN_EXTEND_ENABLED
;
721 /* Return nonzero if this function is known to have a null epilogue.
722 This allows the optimizer to omit jumps to jumps if no stack
725 lm32_can_use_return (void)
727 if (!reload_completed
)
730 if (df_regs_ever_live_p (RA_REGNUM
) || crtl
->profile
)
733 if (lm32_compute_frame_size (get_frame_size ()) != 0)
739 /* Support function to determine the return address of the function
740 'count' frames back up the stack. */
742 lm32_return_addr_rtx (int count
, rtx frame
)
747 if (!df_regs_ever_live_p (RA_REGNUM
))
748 r
= gen_rtx_REG (Pmode
, RA_REGNUM
);
751 r
= gen_rtx_MEM (Pmode
,
752 gen_rtx_PLUS (Pmode
, frame
,
753 GEN_INT (-2 * UNITS_PER_WORD
)));
754 set_mem_alias_set (r
, get_frame_alias_set ());
757 else if (flag_omit_frame_pointer
)
761 r
= gen_rtx_MEM (Pmode
,
762 gen_rtx_PLUS (Pmode
, frame
,
763 GEN_INT (-2 * UNITS_PER_WORD
)));
764 set_mem_alias_set (r
, get_frame_alias_set ());
769 /* Return true if EXP should be placed in the small data section. */
772 lm32_in_small_data_p (const_tree exp
)
774 /* We want to merge strings, so we never consider them small data. */
775 if (TREE_CODE (exp
) == STRING_CST
)
778 /* Functions are never in the small data area. Duh. */
779 if (TREE_CODE (exp
) == FUNCTION_DECL
)
782 if (TREE_CODE (exp
) == VAR_DECL
&& DECL_SECTION_NAME (exp
))
784 const char *section
= DECL_SECTION_NAME (exp
);
785 if (strcmp (section
, ".sdata") == 0 || strcmp (section
, ".sbss") == 0)
790 HOST_WIDE_INT size
= int_size_in_bytes (TREE_TYPE (exp
));
792 /* If this is an incomplete type with size 0, then we can't put it
793 in sdata because it might be too big when completed. */
794 if (size
> 0 && size
<= g_switch_value
)
801 /* Emit straight-line code to move LENGTH bytes from SRC to DEST.
802 Assume that the areas do not overlap. */
805 lm32_block_move_inline (rtx dest
, rtx src
, HOST_WIDE_INT length
,
806 HOST_WIDE_INT alignment
)
808 HOST_WIDE_INT offset
, delta
;
809 unsigned HOST_WIDE_INT bits
;
814 /* Work out how many bits to move at a time. */
828 mode
= mode_for_size (bits
, MODE_INT
, 0);
829 delta
= bits
/ BITS_PER_UNIT
;
831 /* Allocate a buffer for the temporary registers. */
832 regs
= XALLOCAVEC (rtx
, length
/ delta
);
834 /* Load as many BITS-sized chunks as possible. */
835 for (offset
= 0, i
= 0; offset
+ delta
<= length
; offset
+= delta
, i
++)
837 regs
[i
] = gen_reg_rtx (mode
);
838 emit_move_insn (regs
[i
], adjust_address (src
, mode
, offset
));
841 /* Copy the chunks to the destination. */
842 for (offset
= 0, i
= 0; offset
+ delta
<= length
; offset
+= delta
, i
++)
843 emit_move_insn (adjust_address (dest
, mode
, offset
), regs
[i
]);
845 /* Mop up any left-over bytes. */
848 src
= adjust_address (src
, BLKmode
, offset
);
849 dest
= adjust_address (dest
, BLKmode
, offset
);
850 move_by_pieces (dest
, src
, length
- offset
,
851 MIN (MEM_ALIGN (src
), MEM_ALIGN (dest
)), 0);
855 /* Expand string/block move operations.
857 operands[0] is the pointer to the destination.
858 operands[1] is the pointer to the source.
859 operands[2] is the number of bytes to move.
860 operands[3] is the alignment. */
863 lm32_expand_block_move (rtx
* operands
)
865 if ((GET_CODE (operands
[2]) == CONST_INT
) && (INTVAL (operands
[2]) <= 32))
867 lm32_block_move_inline (operands
[0], operands
[1], INTVAL (operands
[2]),
868 INTVAL (operands
[3]));
874 /* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
875 isn't protected by a PIC unspec. */
877 nonpic_symbol_mentioned_p (rtx x
)
882 if (GET_CODE (x
) == SYMBOL_REF
|| GET_CODE (x
) == LABEL_REF
883 || GET_CODE (x
) == PC
)
886 /* We don't want to look into the possible MEM location of a
887 CONST_DOUBLE, since we're not going to use it, in general. */
888 if (GET_CODE (x
) == CONST_DOUBLE
)
891 if (GET_CODE (x
) == UNSPEC
)
894 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
895 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
901 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
902 if (nonpic_symbol_mentioned_p (XVECEXP (x
, i
, j
)))
905 else if (fmt
[i
] == 'e' && nonpic_symbol_mentioned_p (XEXP (x
, i
)))
912 /* Compute a (partial) cost for rtx X. Return true if the complete
913 cost has been computed, and false if subexpressions should be
914 scanned. In either case, *TOTAL contains the cost result. */
917 lm32_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
918 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
920 int code
= GET_CODE (x
);
923 const int arithmetic_latency
= 1;
924 const int shift_latency
= 1;
925 const int compare_latency
= 2;
926 const int multiply_latency
= 3;
927 const int load_latency
= 3;
928 const int libcall_size_cost
= 5;
930 /* Determine if we can handle the given mode size in a single instruction. */
931 small_mode
= (mode
== QImode
) || (mode
== HImode
) || (mode
== SImode
);
944 *total
= COSTS_N_INSNS (LM32_NUM_REGS (mode
));
947 COSTS_N_INSNS (arithmetic_latency
+ (LM32_NUM_REGS (mode
) - 1));
954 *total
= COSTS_N_INSNS (1);
956 *total
= COSTS_N_INSNS (compare_latency
);
960 /* FIXME. Guessing here. */
961 *total
= COSTS_N_INSNS (LM32_NUM_REGS (mode
) * (2 + 3) / 2);
968 if (TARGET_BARREL_SHIFT_ENABLED
&& small_mode
)
971 *total
= COSTS_N_INSNS (1);
973 *total
= COSTS_N_INSNS (shift_latency
);
975 else if (TARGET_BARREL_SHIFT_ENABLED
)
977 /* FIXME: Guessing here. */
978 *total
= COSTS_N_INSNS (LM32_NUM_REGS (mode
) * 4);
980 else if (small_mode
&& GET_CODE (XEXP (x
, 1)) == CONST_INT
)
982 *total
= COSTS_N_INSNS (INTVAL (XEXP (x
, 1)));
988 *total
= COSTS_N_INSNS (libcall_size_cost
);
990 *total
= COSTS_N_INSNS (100);
995 if (TARGET_MULTIPLY_ENABLED
&& small_mode
)
998 *total
= COSTS_N_INSNS (1);
1000 *total
= COSTS_N_INSNS (multiply_latency
);
1006 *total
= COSTS_N_INSNS (libcall_size_cost
);
1008 *total
= COSTS_N_INSNS (100);
1016 if (TARGET_DIVIDE_ENABLED
&& small_mode
)
1019 *total
= COSTS_N_INSNS (1);
1022 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
1025 unsigned HOST_WIDE_INT i
= INTVAL (XEXP (x
, 1));
1032 if (IN_RANGE (i
, 0, 65536))
1033 *total
= COSTS_N_INSNS (1 + 1 + cycles
);
1035 *total
= COSTS_N_INSNS (2 + 1 + cycles
);
1038 else if (GET_CODE (XEXP (x
, 1)) == REG
)
1040 *total
= COSTS_N_INSNS (1 + GET_MODE_SIZE (mode
) / 2);
1045 *total
= COSTS_N_INSNS (1 + GET_MODE_SIZE (mode
) / 2);
1054 *total
= COSTS_N_INSNS (libcall_size_cost
);
1056 *total
= COSTS_N_INSNS (100);
1063 *total
= COSTS_N_INSNS (1);
1065 *total
= COSTS_N_INSNS (arithmetic_latency
);
1069 if (MEM_P (XEXP (x
, 0)))
1070 *total
= COSTS_N_INSNS (0);
1071 else if (small_mode
)
1074 *total
= COSTS_N_INSNS (1);
1076 *total
= COSTS_N_INSNS (arithmetic_latency
);
1079 *total
= COSTS_N_INSNS (LM32_NUM_REGS (mode
) / 2);
1088 *total
= COSTS_N_INSNS (0);
1099 if (satisfies_constraint_L (x
))
1100 *total
= COSTS_N_INSNS (0);
1102 *total
= COSTS_N_INSNS (2);
1109 if (satisfies_constraint_K (x
))
1110 *total
= COSTS_N_INSNS (0);
1112 *total
= COSTS_N_INSNS (2);
1116 if (TARGET_MULTIPLY_ENABLED
)
1118 if (satisfies_constraint_K (x
))
1119 *total
= COSTS_N_INSNS (0);
1121 *total
= COSTS_N_INSNS (2);
1127 if (satisfies_constraint_K (x
))
1128 *total
= COSTS_N_INSNS (1);
1130 *total
= COSTS_N_INSNS (2);
1141 *total
= COSTS_N_INSNS (0);
1148 *total
= COSTS_N_INSNS (0);
1157 *total
= COSTS_N_INSNS (2);
1161 *total
= COSTS_N_INSNS (1);
1166 *total
= COSTS_N_INSNS (1);
1168 *total
= COSTS_N_INSNS (load_latency
);
1176 /* Implemenent TARGET_CAN_ELIMINATE. */
1179 lm32_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
1181 return (to
== STACK_POINTER_REGNUM
&& frame_pointer_needed
) ? false : true;
1184 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */
1187 lm32_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
, bool strict
)
1190 if (strict
&& REG_P (x
) && STRICT_REG_OK_FOR_BASE_P (x
))
1192 if (!strict
&& REG_P (x
) && NONSTRICT_REG_OK_FOR_BASE_P (x
))
1196 if (GET_CODE (x
) == PLUS
1197 && REG_P (XEXP (x
, 0))
1198 && ((strict
&& STRICT_REG_OK_FOR_BASE_P (XEXP (x
, 0)))
1199 || (!strict
&& NONSTRICT_REG_OK_FOR_BASE_P (XEXP (x
, 0))))
1200 && GET_CODE (XEXP (x
, 1)) == CONST_INT
1201 && satisfies_constraint_K (XEXP ((x
), 1)))
1205 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
1211 /* Check a move is not memory to memory. */
1214 lm32_move_ok (machine_mode mode
, rtx operands
[2]) {
1215 if (memory_operand (operands
[0], mode
))
1216 return register_or_zero_operand (operands
[1], mode
);