2015-09-21 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / config / ft32 / ft32.c
blob95df59676ab54d7c2128b48c7481421922e29bc2
1 /* Target Code for ft32
2 Copyright (C) 2015 Free Software Foundation
3 Contributed by FTDI <support@ftdi.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "cfghooks.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "df.h"
29 #include "regs.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "recog.h"
37 #include "reload.h"
38 #include "diagnostic-core.h"
39 #include "alias.h"
40 #include "stor-layout.h"
41 #include "calls.h"
42 #include "expr.h"
43 #include "optabs.h"
44 #include "except.h"
45 #include "target.h"
46 #include "tm_p.h"
47 #include "langhooks.h"
48 #include "cfgrtl.h"
49 #include "cfganal.h"
50 #include "lcm.h"
51 #include "cfgbuild.h"
52 #include "cfgcleanup.h"
53 #include "builtins.h"
54 #include "emit-rtl.h"
56 /* This file should be included last. */
57 #include "target-def.h"
59 #include <stdint.h>
61 #define LOSE_AND_RETURN(msgid, x) \
62 do \
63 { \
64 ft32_operand_lossage (msgid, x); \
65 return; \
66 } while (0)
68 /* Worker function for TARGET_RETURN_IN_MEMORY. */
70 static bool
71 ft32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
73 const HOST_WIDE_INT size = int_size_in_bytes (type);
74 return (size == -1 || size > 2 * UNITS_PER_WORD);
77 /* Define how to find the value returned by a function.
78 VALTYPE is the data type of the value (as a tree).
79 If the precise function being called is known, FUNC is its
80 FUNCTION_DECL; otherwise, FUNC is 0.
82 We always return values in register $r0 for ft32. */
84 static rtx
85 ft32_function_value (const_tree valtype,
86 const_tree fntype_or_decl ATTRIBUTE_UNUSED,
87 bool outgoing ATTRIBUTE_UNUSED)
89 return gen_rtx_REG (TYPE_MODE (valtype), FT32_R0);
92 /* Define how to find the value returned by a library function.
94 We always return values in register $r0 for ft32. */
96 static rtx
97 ft32_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
99 return gen_rtx_REG (mode, FT32_R0);
102 /* Handle TARGET_FUNCTION_VALUE_REGNO_P.
104 We always return values in register $r0 for ft32. */
106 static bool
107 ft32_function_value_regno_p (const unsigned int regno)
109 return (regno == FT32_R0);
112 /* Emit an error message when we're in an asm, and a fatal error for
113 "normal" insns. Formatted output isn't easily implemented, since we
114 use output_operand_lossage to output the actual message and handle the
115 categorization of the error. */
117 static void
118 ft32_operand_lossage (const char *msgid, rtx op)
120 debug_rtx (op);
121 output_operand_lossage ("%s", msgid);
124 /* The PRINT_OPERAND_ADDRESS worker. */
126 void
127 ft32_print_operand_address (FILE * file, rtx x)
129 switch (GET_CODE (x))
131 case REG:
132 fprintf (file, "%s,0", reg_names[REGNO (x)]);
133 break;
135 case PLUS:
136 switch (GET_CODE (XEXP (x, 1)))
138 case CONST_INT:
139 fprintf (file, "%s,%ld",
140 reg_names[REGNO (XEXP (x, 0))], INTVAL (XEXP (x, 1)));
141 break;
142 case SYMBOL_REF:
143 output_addr_const (file, XEXP (x, 1));
144 fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
145 break;
146 case CONST:
148 rtx plus = XEXP (XEXP (x, 1), 0);
149 if (GET_CODE (XEXP (plus, 0)) == SYMBOL_REF
150 && CONST_INT_P (XEXP (plus, 1)))
152 output_addr_const (file, XEXP (plus, 0));
153 fprintf (file, "+%ld(%s)", INTVAL (XEXP (plus, 1)),
154 reg_names[REGNO (XEXP (x, 0))]);
156 else
157 abort ();
159 break;
160 default:
161 abort ();
163 break;
165 default:
166 output_addr_const (file, x);
167 break;
171 /* The PRINT_OPERAND worker. */
173 void
174 ft32_print_operand (FILE * file, rtx x, int code)
176 rtx operand = x;
178 /* New code entries should just be added to the switch below. If
179 handling is finished, just return. If handling was just a
180 modification of the operand, the modified operand should be put in
181 "operand", and then do a break to let default handling
182 (zero-modifier) output the operand. */
184 switch (code)
186 case 0:
187 /* No code, print as usual. */
188 break;
190 case 'h':
191 if (GET_CODE (operand) != REG)
192 internal_error ("'h' applied to non-register operand");
193 fprintf (file, "%s", reg_names[REGNO (operand) + 1]);
194 return;
196 case 'm':
197 fprintf (file, "%ld", (long) (- INTVAL(x)));
198 return;
200 case 'd': // a DW spec, from an integer alignment (for BLKmode insns)
202 int i = INTVAL (x);
203 char dwspec;
204 switch (i)
206 case 1:
207 dwspec = 'b';
208 break;
209 case 2:
210 dwspec = 's';
211 break;
212 case 4:
213 dwspec = 'l';
214 break;
215 default:
216 if ((i % 4) != 0)
217 internal_error ("bad alignment: %d", i);
218 else
219 dwspec = 'l';
220 break;
222 fprintf (file, "%c", dwspec);
223 return;
226 case 'f':
228 int bf = ft32_as_bitfield (INTVAL (x));
229 fprintf (file, "512|(%d<<5)|%d", bf >> 5, bf & 31);
230 return;
233 case 'g':
235 int bf = ft32_as_bitfield (0xffffffff ^ INTVAL (x));
236 fprintf (file, "(%d<<5)|%d", bf >> 5, bf & 31);
237 return;
240 case 'b':
242 ft32_print_operand (file, XEXP (x, 0), 0);
243 return;
246 default:
247 LOSE_AND_RETURN ("invalid operand modifier letter", x);
250 /* Print an operand as without a modifier letter. */
251 switch (GET_CODE (operand))
253 case REG:
254 fprintf (file, "%s", reg_names[REGNO (operand)]);
255 return;
257 case MEM:
258 output_address (XEXP (operand, 0));
259 return;
261 default:
262 /* No need to handle all strange variants, let output_addr_const
263 do it for us. */
264 if (CONSTANT_P (operand))
266 output_addr_const (file, operand);
267 return;
270 LOSE_AND_RETURN ("unexpected operand", x);
274 const char *
275 ft32_load_immediate (rtx dst, int32_t i)
277 char pattern[100];
279 if ((-524288 <= i) && (i <= 524287))
281 sprintf (pattern, "ldk.l %%0,%d", i);
282 output_asm_insn (pattern, &dst);
284 else if ((-536870912 <= i) && (i <= 536870911))
286 ft32_load_immediate (dst, i >> 10);
287 sprintf (pattern, "ldl.l %%0,%%0,%d", i & 1023);
288 output_asm_insn (pattern, &dst);
290 else
292 int rd; // rotate distance
293 uint32_t u = i;
294 for (rd = 1; rd < 32; rd++)
296 u = ((u >> 31) & 1) | (u << 1);
297 if ((-524288 <= (int32_t) u) && ((int32_t) u <= 524287))
299 ft32_load_immediate (dst, (int32_t) u);
300 sprintf (pattern, "ror.l %%0,%%0,%d", rd);
301 output_asm_insn (pattern, &dst);
302 return "";
305 ft32_load_immediate (dst, i >> 10);
306 sprintf (pattern, "ldl.l %%0,%%0,%d", i & 1023);
307 output_asm_insn (pattern, &dst);
310 return "";
313 // x is a bit mask, for example:
314 // 00000000000000000000001111111110
315 // If x contains a single bit mask, return the bitfield spec.
316 // in the above case it returns ((9 << 5) | 1)
317 // Otherwise return -1.
320 #define NBITS(n) ((1U << (n)) - 1U)
323 ft32_as_bitfield (unsigned int x)
325 int lobit, hibit;
327 if (x == 0)
328 return -1;
330 for (lobit = 0; lobit < 32; lobit++)
331 if (x & (1 << lobit))
332 break;
333 for (hibit = 31; hibit >= 0; hibit--)
334 if (x & (1 << hibit))
335 break;
337 int width = 1 + hibit - lobit;
338 if (width > 16)
339 return -1;
341 if (x != (NBITS (width) << lobit))
342 return -1; // not a clean bitfield
344 return ((width & 15) << 5) | lobit;
347 /* Per-function machine data. */
348 struct GTY (()) machine_function
350 /* Number of bytes saved on the stack for callee saved registers. */
351 int callee_saved_reg_size;
353 /* Number of bytes saved on the stack for local variables. */
354 int local_vars_size;
356 /* The sum of 2 sizes: locals vars and padding byte for saving the
357 * registers. Used in expand_prologue () and expand_epilogue (). */
358 int size_for_adjusting_sp;
361 /* Zero initialization is OK for all current fields. */
363 static struct machine_function *
364 ft32_init_machine_status (void)
366 return ggc_cleared_alloc < machine_function > ();
370 /* The TARGET_OPTION_OVERRIDE worker.
371 All this curently does is set init_machine_status. */
372 static void
373 ft32_option_override (void)
375 /* Set the per-function-data initializer. */
376 init_machine_status = ft32_init_machine_status;
379 /* Implement targetm.select_section. */
380 static section *
381 ft32_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
383 /* Variables and constants defined in the __ea address space
384 go into a special section named "._ea". */
385 if (TREE_TYPE (decl) != error_mark_node
386 && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_PM)
388 /* We might get called with string constants, but get_named_section
389 doesn't like them as they are not DECLs. Also, we need to set
390 flags in that case. */
391 if (!DECL_P (decl))
392 return get_section ("._pm", SECTION_WRITE | SECTION_DEBUG, NULL);
394 return get_named_section (decl, "._pm", reloc);
397 return default_elf_select_section (decl, reloc, align);
400 /* Compute the size of the local area and the size to be adjusted by the
401 * prologue and epilogue. */
403 static void
404 ft32_compute_frame (void)
406 /* For aligning the local variables. */
407 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
408 int padding_locals;
409 int regno;
411 /* Padding needed for each element of the frame. */
412 cfun->machine->local_vars_size = get_frame_size ();
414 /* Align to the stack alignment. */
415 padding_locals = cfun->machine->local_vars_size % stack_alignment;
416 if (padding_locals)
417 padding_locals = stack_alignment - padding_locals;
419 cfun->machine->local_vars_size += padding_locals;
421 cfun->machine->callee_saved_reg_size = 0;
423 /* Save callee-saved registers. */
424 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
425 if (df_regs_ever_live_p (regno) && (!call_used_regs[regno]))
426 cfun->machine->callee_saved_reg_size += 4;
428 cfun->machine->size_for_adjusting_sp =
429 crtl->args.pretend_args_size
430 + cfun->machine->local_vars_size
431 + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
434 // Must use LINK/UNLINK when...
435 // the frame is bigger than 512 bytes so cannot just "SUB" from SP
436 // the function actually uses $fp
438 static int
439 must_link (void)
441 int bigframe = (cfun->machine->size_for_adjusting_sp >= 512);
442 return (bigframe || frame_pointer_needed || df_regs_ever_live_p (FT32_FP)
443 || df_regs_ever_live_p (FT32_FP));
446 void
447 ft32_expand_prologue (void)
449 int regno;
450 rtx insn;
452 ft32_compute_frame ();
454 if (flag_stack_usage_info)
455 current_function_static_stack_size = cfun->machine->size_for_adjusting_sp;
457 if (!must_link () && (cfun->machine->callee_saved_reg_size == 4))
459 insn =
460 emit_insn (gen_link
461 (gen_rtx_REG (Pmode, FT32_R13),
462 GEN_INT (-cfun->machine->size_for_adjusting_sp)));
463 RTX_FRAME_RELATED_P (insn) = 1;
464 return;
466 /* Save callee-saved registers. */
467 if (optimize_size)
469 for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0;)
471 if (!fixed_regs[regno] && !call_used_regs[regno]
472 && df_regs_ever_live_p (regno))
474 rtx preg = gen_rtx_REG (Pmode, regno);
475 emit_insn (gen_call_prolog (preg));
476 break;
480 else
482 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
484 if (!fixed_regs[regno] && df_regs_ever_live_p (regno)
485 && !call_used_regs[regno])
487 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
488 RTX_FRAME_RELATED_P (insn) = 1;
493 if (65536 <= cfun->machine->size_for_adjusting_sp)
495 error ("stack frame must be smaller than 64K");
496 return;
498 if (must_link ())
500 insn =
501 emit_insn (gen_link
502 (gen_rtx_REG (Pmode, FT32_FP),
503 GEN_INT (-cfun->machine->size_for_adjusting_sp)));
504 RTX_FRAME_RELATED_P (insn) = 1;
506 else if (cfun->machine->size_for_adjusting_sp > 0)
508 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, FT32_SP),
509 gen_rtx_REG (SImode, FT32_SP),
510 GEN_INT (-(cfun->machine->
511 size_for_adjusting_sp))));
512 RTX_FRAME_RELATED_P (insn) = 1;
516 void
517 ft32_expand_epilogue (void)
519 int regno;
521 if (!must_link ()
522 && (cfun->machine->size_for_adjusting_sp == 24)
523 && (cfun->machine->callee_saved_reg_size == 0))
525 emit_jump_insn (gen_returner24 ());
526 return;
529 // Set when the epilog code will also add 24 to $sp
530 int epilog24 = (!must_link ()
531 && (cfun->machine->size_for_adjusting_sp == 24)
532 && optimize_size);
534 if (must_link ())
536 emit_insn (gen_unlink ());
538 else if (!epilog24 && (cfun->machine->size_for_adjusting_sp > 0))
540 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, FT32_SP),
541 gen_rtx_REG (SImode, FT32_SP),
542 GEN_INT (cfun->machine->size_for_adjusting_sp)));
545 if (cfun->machine->callee_saved_reg_size != 0)
547 for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0;)
549 if (!fixed_regs[regno] && !call_used_regs[regno]
550 && df_regs_ever_live_p (regno))
552 rtx preg = gen_rtx_REG (Pmode, regno);
553 if (optimize_size)
555 if (epilog24)
556 emit_insn (gen_jump_epilog24 (preg));
557 else
558 emit_insn (gen_jump_epilog (preg));
559 return;
561 emit_insn (gen_movsi_pop (preg));
566 emit_jump_insn (gen_returner ());
569 #undef TARGET_FRAME_POINTER_REQUIRED
570 #define TARGET_FRAME_POINTER_REQUIRED ft32_frame_pointer_required
571 static bool
572 ft32_frame_pointer_required (void)
574 return cfun->calls_alloca;
577 #undef TARGET_CAN_ELIMINATE
578 #define TARGET_CAN_ELIMINATE ft32_can_eliminate
580 /* Return true if register FROM can be eliminated via register TO. */
582 static bool
583 ft32_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
585 return 1;
586 return (to == FRAME_POINTER_REGNUM) || !ft32_frame_pointer_required ();
589 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
592 ft32_initial_elimination_offset (int from, int to)
594 ft32_compute_frame ();
596 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
598 return cfun->machine->callee_saved_reg_size + 2 * UNITS_PER_WORD;
601 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
603 int arg_offset;
604 arg_offset = must_link ()? 2 : 1;
605 return ((cfun->machine->callee_saved_reg_size
606 + arg_offset * UNITS_PER_WORD)
607 + cfun->machine->size_for_adjusting_sp);
610 if ((from == FRAME_POINTER_REGNUM) && (to == STACK_POINTER_REGNUM))
612 return cfun->machine->size_for_adjusting_sp;
615 gcc_unreachable ();
618 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
620 static void
621 ft32_setup_incoming_varargs (cumulative_args_t cum_v,
622 enum machine_mode mode ATTRIBUTE_UNUSED,
623 tree type ATTRIBUTE_UNUSED,
624 int *pretend_size, int no_rtl)
626 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
627 int regno;
628 int regs = 8 - *cum;
630 *pretend_size = regs < 0 ? 0 : GET_MODE_SIZE (SImode) * regs;
632 if (no_rtl)
633 return;
635 for (regno = *cum; regno < 8; regno++)
637 rtx reg = gen_rtx_REG (SImode, regno);
638 rtx slot = gen_rtx_PLUS (Pmode,
639 gen_rtx_REG (SImode, ARG_POINTER_REGNUM),
640 GEN_INT (UNITS_PER_WORD * (regno - FT32_R0)));
642 emit_move_insn (gen_rtx_MEM (SImode, slot), reg);
647 /* Return the fixed registers used for condition codes. */
649 static bool
650 ft32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
652 *p1 = CC_REG;
653 *p2 = INVALID_REGNUM;
654 return true;
657 /* Return the next register to be used to hold a function argument or
658 NULL_RTX if there's no more space. */
660 static rtx
661 ft32_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
662 const_tree type ATTRIBUTE_UNUSED,
663 bool named ATTRIBUTE_UNUSED)
665 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
667 if (*cum < 8)
668 return gen_rtx_REG (mode, *cum);
669 else
670 return NULL_RTX;
673 #define FT32_FUNCTION_ARG_SIZE(MODE, TYPE) \
674 ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \
675 : (unsigned) int_size_in_bytes (TYPE))
677 static void
678 ft32_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
679 const_tree type, bool named ATTRIBUTE_UNUSED)
681 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
683 *cum = (*cum < FT32_R6
684 ? *cum + ((3 + FT32_FUNCTION_ARG_SIZE (mode, type)) / 4) : *cum);
687 /* Return non-zero if the function argument described by TYPE is to be
688 passed by reference. */
690 static bool
691 ft32_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
692 enum machine_mode mode, const_tree type,
693 bool named ATTRIBUTE_UNUSED)
695 unsigned HOST_WIDE_INT size;
697 if (type)
699 if (AGGREGATE_TYPE_P (type))
700 return true;
701 size = int_size_in_bytes (type);
703 else
704 size = GET_MODE_SIZE (mode);
706 return size > 4 * 6;
709 /* Some function arguments will only partially fit in the registers
710 that hold arguments. Given a new arg, return the number of bytes
711 that fit in argument passing registers. */
713 static int
714 ft32_arg_partial_bytes (cumulative_args_t cum_v,
715 enum machine_mode mode, tree type, bool named)
717 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
718 int bytes_left, size;
720 if (*cum >= 8)
721 return 0;
723 if (ft32_pass_by_reference (cum_v, mode, type, named))
724 size = 4;
725 else if (type)
727 if (AGGREGATE_TYPE_P (type))
728 return 0;
729 size = int_size_in_bytes (type);
731 else
732 size = GET_MODE_SIZE (mode);
734 bytes_left = (4 * 6) - ((*cum - 2) * 4);
736 if (size > bytes_left)
737 return bytes_left;
738 else
739 return 0;
742 /* Used by constraints.md to distinguish between GENERIC and PM
743 memory addresses. */
746 ft32_is_mem_pm (rtx o)
748 return (MEM_P (o)
749 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (o)));
752 /* The Global `targetm' Variable. */
754 /* Initialize the GCC target structure. */
756 #undef TARGET_PROMOTE_PROTOTYPES
757 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
759 #undef TARGET_RETURN_IN_MEMORY
760 #define TARGET_RETURN_IN_MEMORY ft32_return_in_memory
761 #undef TARGET_MUST_PASS_IN_STACK
762 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
763 #undef TARGET_PASS_BY_REFERENCE
764 #define TARGET_PASS_BY_REFERENCE ft32_pass_by_reference
765 #undef TARGET_ARG_PARTIAL_BYTES
766 #define TARGET_ARG_PARTIAL_BYTES ft32_arg_partial_bytes
767 #undef TARGET_FUNCTION_ARG
768 #define TARGET_FUNCTION_ARG ft32_function_arg
769 #undef TARGET_FUNCTION_ARG_ADVANCE
770 #define TARGET_FUNCTION_ARG_ADVANCE ft32_function_arg_advance
773 #undef TARGET_SETUP_INCOMING_VARARGS
774 #define TARGET_SETUP_INCOMING_VARARGS ft32_setup_incoming_varargs
776 #undef TARGET_FIXED_CONDITION_CODE_REGS
777 #define TARGET_FIXED_CONDITION_CODE_REGS ft32_fixed_condition_code_regs
779 /* Define this to return an RTX representing the place where a
780 function returns or receives a value of data type RET_TYPE, a tree
781 node representing a data type. */
782 #undef TARGET_FUNCTION_VALUE
783 #define TARGET_FUNCTION_VALUE ft32_function_value
784 #undef TARGET_LIBCALL_VALUE
785 #define TARGET_LIBCALL_VALUE ft32_libcall_value
786 #undef TARGET_FUNCTION_VALUE_REGNO_P
787 #define TARGET_FUNCTION_VALUE_REGNO_P ft32_function_value_regno_p
789 #undef TARGET_OPTION_OVERRIDE
790 #define TARGET_OPTION_OVERRIDE ft32_option_override
792 #undef TARGET_ASM_SELECT_SECTION
793 #define TARGET_ASM_SELECT_SECTION ft32_select_section
795 #undef TARGET_VALID_POINTER_MODE
796 #define TARGET_VALID_POINTER_MODE ft32_valid_pointer_mode
797 static bool
798 ft32_valid_pointer_mode (enum machine_mode mode)
800 if (mode == SImode)
801 return 1;
802 return 0;
805 #undef TARGET_ADDR_SPACE_POINTER_MODE
806 #define TARGET_ADDR_SPACE_POINTER_MODE ft32_addr_space_pointer_mode
807 static enum machine_mode
808 ft32_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
810 return Pmode;
813 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
814 #define TARGET_ADDR_SPACE_ADDRESS_MODE ft32_addr_space_address_mode
815 static enum machine_mode
816 ft32_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
818 return Pmode;
821 #undef TARGET_ADDR_SPACE_SUBSET_P
822 #define TARGET_ADDR_SPACE_SUBSET_P ft32_addr_space_subset_p
823 static bool
824 ft32_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
825 addr_space_t superset ATTRIBUTE_UNUSED)
827 return false;
830 #undef TARGET_CASE_VALUES_THRESHOLD
831 #define TARGET_CASE_VALUES_THRESHOLD ft32_target_case_values_threshold
833 static unsigned int
834 ft32_target_case_values_threshold (void)
836 return 4;
839 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
840 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
841 ft32_addr_space_legitimate_address_p
844 // Enabling LRA gives the infamous
845 // internal compiler error: Max. number of generated reload insns per insn is achieved (90)
846 // errors e.g. when compiling sieve.c
848 static bool
849 ft32_lra_p (void)
851 return ft32_lra_flag;
854 #undef TARGET_LRA_P
855 #define TARGET_LRA_P ft32_lra_p
857 static bool
858 reg_ok_for_base_p (rtx r, bool strict)
860 int NUM = REGNO (r);
861 if (strict)
862 return (HARD_REGNO_OK_FOR_BASE_P (NUM)
863 || HARD_REGNO_OK_FOR_BASE_P (reg_renumber[(NUM)]));
864 else
865 return ((NUM) >= FIRST_PSEUDO_REGISTER || HARD_REGNO_OK_FOR_BASE_P (NUM));
868 static bool
869 ft32_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
870 bool strict,
871 addr_space_t as ATTRIBUTE_UNUSED)
873 if (mode != BLKmode)
875 if (GET_CODE (x) == PLUS)
877 rtx op1, op2;
878 op1 = XEXP (x, 0);
879 op2 = XEXP (x, 1);
880 if (GET_CODE (op1) == REG
881 && CONST_INT_P (op2)
882 && INTVAL (op2) >= -128
883 && INTVAL (op2) < 128 && reg_ok_for_base_p (op1, strict))
884 goto yes;
885 if (GET_CODE (op1) == SYMBOL_REF && CONST_INT_P (op2))
886 goto yes;
888 if (REG_P (x) && reg_ok_for_base_p (x, strict))
889 goto yes;
890 if (GET_CODE (x) == SYMBOL_REF
891 || GET_CODE (x) == LABEL_REF || CONST_INT_P (x))
892 goto yes;
894 else
896 if (REG_P (x) && reg_ok_for_base_p (x, strict))
897 goto yes;
900 return 0;
901 yes:
902 return 1;
905 struct gcc_target targetm = TARGET_INITIALIZER;
907 #include "gt-ft32.h"