136ac495dSmrg /* Target Code for R8C/M16C/M32C
2*8feb0f0bSmrg Copyright (C) 2005-2020 Free Software Foundation, Inc.
336ac495dSmrg Contributed by Red Hat.
436ac495dSmrg
536ac495dSmrg This file is part of GCC.
636ac495dSmrg
736ac495dSmrg GCC is free software; you can redistribute it and/or modify it
836ac495dSmrg under the terms of the GNU General Public License as published
936ac495dSmrg by the Free Software Foundation; either version 3, or (at your
1036ac495dSmrg option) any later version.
1136ac495dSmrg
1236ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
1336ac495dSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1436ac495dSmrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1536ac495dSmrg License for more details.
1636ac495dSmrg
1736ac495dSmrg You should have received a copy of the GNU General Public License
1836ac495dSmrg along with GCC; see the file COPYING3. If not see
1936ac495dSmrg <http://www.gnu.org/licenses/>. */
2036ac495dSmrg
21a2dc1f3fSmrg #define IN_TARGET_CODE 1
22a2dc1f3fSmrg
2336ac495dSmrg #include "config.h"
2436ac495dSmrg #include "system.h"
2536ac495dSmrg #include "coretypes.h"
2636ac495dSmrg #include "backend.h"
2736ac495dSmrg #include "target.h"
2836ac495dSmrg #include "rtl.h"
2936ac495dSmrg #include "tree.h"
30a2dc1f3fSmrg #include "stringpool.h"
31a2dc1f3fSmrg #include "attribs.h"
3236ac495dSmrg #include "df.h"
3336ac495dSmrg #include "memmodel.h"
3436ac495dSmrg #include "tm_p.h"
3536ac495dSmrg #include "optabs.h"
3636ac495dSmrg #include "regs.h"
3736ac495dSmrg #include "emit-rtl.h"
3836ac495dSmrg #include "recog.h"
3936ac495dSmrg #include "diagnostic-core.h"
4036ac495dSmrg #include "output.h"
4136ac495dSmrg #include "insn-attr.h"
4236ac495dSmrg #include "flags.h"
4336ac495dSmrg #include "reload.h"
4436ac495dSmrg #include "stor-layout.h"
4536ac495dSmrg #include "varasm.h"
4636ac495dSmrg #include "calls.h"
4736ac495dSmrg #include "explow.h"
4836ac495dSmrg #include "expr.h"
4936ac495dSmrg #include "tm-constrs.h"
5036ac495dSmrg #include "builtins.h"
5136ac495dSmrg
5236ac495dSmrg /* This file should be included last. */
5336ac495dSmrg #include "target-def.h"
5436ac495dSmrg
5536ac495dSmrg /* Prototypes */
5636ac495dSmrg
5736ac495dSmrg /* Used by m32c_pushm_popm. */
5836ac495dSmrg typedef enum
5936ac495dSmrg {
6036ac495dSmrg PP_pushm,
6136ac495dSmrg PP_popm,
6236ac495dSmrg PP_justcount
6336ac495dSmrg } Push_Pop_Type;
6436ac495dSmrg
6536ac495dSmrg static bool m32c_function_needs_enter (void);
6636ac495dSmrg static tree interrupt_handler (tree *, tree, tree, int, bool *);
6736ac495dSmrg static tree function_vector_handler (tree *, tree, tree, int, bool *);
6836ac495dSmrg static int interrupt_p (tree node);
6936ac495dSmrg static int bank_switch_p (tree node);
7036ac495dSmrg static int fast_interrupt_p (tree node);
7136ac495dSmrg static int interrupt_p (tree node);
7236ac495dSmrg static bool m32c_asm_integer (rtx, unsigned int, int);
7336ac495dSmrg static int m32c_comp_type_attributes (const_tree, const_tree);
7436ac495dSmrg static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
7536ac495dSmrg static struct machine_function *m32c_init_machine_status (void);
7636ac495dSmrg static void m32c_insert_attributes (tree, tree *);
7736ac495dSmrg static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
7836ac495dSmrg static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
79*8feb0f0bSmrg static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
80*8feb0f0bSmrg static bool m32c_pass_by_reference (cumulative_args_t,
81*8feb0f0bSmrg const function_arg_info &);
82*8feb0f0bSmrg static void m32c_function_arg_advance (cumulative_args_t,
83*8feb0f0bSmrg const function_arg_info &);
8436ac495dSmrg static unsigned int m32c_function_arg_boundary (machine_mode, const_tree);
8536ac495dSmrg static int m32c_pushm_popm (Push_Pop_Type);
8636ac495dSmrg static bool m32c_strict_argument_naming (cumulative_args_t);
8736ac495dSmrg static rtx m32c_struct_value_rtx (tree, int);
8836ac495dSmrg static rtx m32c_subreg (machine_mode, rtx, machine_mode, int);
8936ac495dSmrg static int need_to_save (int);
9036ac495dSmrg static rtx m32c_function_value (const_tree, const_tree, bool);
9136ac495dSmrg static rtx m32c_libcall_value (machine_mode, const_rtx);
9236ac495dSmrg
9336ac495dSmrg /* Returns true if an address is specified, else false. */
9436ac495dSmrg static bool m32c_get_pragma_address (const char *varname, unsigned *addr);
9536ac495dSmrg
96a2dc1f3fSmrg static bool m32c_hard_regno_mode_ok (unsigned int, machine_mode);
97a2dc1f3fSmrg
9836ac495dSmrg #define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
9936ac495dSmrg
10036ac495dSmrg #define streq(a,b) (strcmp ((a), (b)) == 0)
10136ac495dSmrg
10236ac495dSmrg /* Internal support routines */
10336ac495dSmrg
10436ac495dSmrg /* Debugging statements are tagged with DEBUG0 only so that they can
10536ac495dSmrg be easily enabled individually, by replacing the '0' with '1' as
10636ac495dSmrg needed. */
10736ac495dSmrg #define DEBUG0 0
10836ac495dSmrg #define DEBUG1 1
10936ac495dSmrg
11036ac495dSmrg #if DEBUG0
11136ac495dSmrg #include "print-tree.h"
11236ac495dSmrg /* This is needed by some of the commented-out debug statements
11336ac495dSmrg below. */
11436ac495dSmrg static char const *class_names[LIM_REG_CLASSES] = REG_CLASS_NAMES;
11536ac495dSmrg #endif
11636ac495dSmrg static int class_contents[LIM_REG_CLASSES][1] = REG_CLASS_CONTENTS;
11736ac495dSmrg
11836ac495dSmrg /* These are all to support encode_pattern(). */
11936ac495dSmrg static char pattern[30], *patternp;
12036ac495dSmrg static GTY(()) rtx patternr[30];
12136ac495dSmrg #define RTX_IS(x) (streq (pattern, x))
12236ac495dSmrg
12336ac495dSmrg /* Some macros to simplify the logic throughout this file. */
12436ac495dSmrg #define IS_MEM_REGNO(regno) ((regno) >= MEM0_REGNO && (regno) <= MEM7_REGNO)
12536ac495dSmrg #define IS_MEM_REG(rtx) (GET_CODE (rtx) == REG && IS_MEM_REGNO (REGNO (rtx)))
12636ac495dSmrg
12736ac495dSmrg #define IS_CR_REGNO(regno) ((regno) >= SB_REGNO && (regno) <= PC_REGNO)
12836ac495dSmrg #define IS_CR_REG(rtx) (GET_CODE (rtx) == REG && IS_CR_REGNO (REGNO (rtx)))
12936ac495dSmrg
13036ac495dSmrg static int
far_addr_space_p(rtx x)13136ac495dSmrg far_addr_space_p (rtx x)
13236ac495dSmrg {
13336ac495dSmrg if (GET_CODE (x) != MEM)
13436ac495dSmrg return 0;
13536ac495dSmrg #if DEBUG0
13636ac495dSmrg fprintf(stderr, "\033[35mfar_addr_space: "); debug_rtx(x);
13736ac495dSmrg fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
13836ac495dSmrg #endif
13936ac495dSmrg return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
14036ac495dSmrg }
14136ac495dSmrg
14236ac495dSmrg /* We do most RTX matching by converting the RTX into a string, and
14336ac495dSmrg using string compares. This vastly simplifies the logic in many of
14436ac495dSmrg the functions in this file.
14536ac495dSmrg
14636ac495dSmrg On exit, pattern[] has the encoded string (use RTX_IS("...") to
14736ac495dSmrg compare it) and patternr[] has pointers to the nodes in the RTX
14836ac495dSmrg corresponding to each character in the encoded string. The latter
14936ac495dSmrg is mostly used by print_operand().
15036ac495dSmrg
15136ac495dSmrg Unrecognized patterns have '?' in them; this shows up when the
15236ac495dSmrg assembler complains about syntax errors.
15336ac495dSmrg */
15436ac495dSmrg
15536ac495dSmrg static void
encode_pattern_1(rtx x)15636ac495dSmrg encode_pattern_1 (rtx x)
15736ac495dSmrg {
15836ac495dSmrg int i;
15936ac495dSmrg
16036ac495dSmrg if (patternp == pattern + sizeof (pattern) - 2)
16136ac495dSmrg {
16236ac495dSmrg patternp[-1] = '?';
16336ac495dSmrg return;
16436ac495dSmrg }
16536ac495dSmrg
16636ac495dSmrg patternr[patternp - pattern] = x;
16736ac495dSmrg
16836ac495dSmrg switch (GET_CODE (x))
16936ac495dSmrg {
17036ac495dSmrg case REG:
17136ac495dSmrg *patternp++ = 'r';
17236ac495dSmrg break;
17336ac495dSmrg case SUBREG:
17436ac495dSmrg if (GET_MODE_SIZE (GET_MODE (x)) !=
17536ac495dSmrg GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
17636ac495dSmrg *patternp++ = 'S';
17736ac495dSmrg if (GET_MODE (x) == PSImode
17836ac495dSmrg && GET_CODE (XEXP (x, 0)) == REG)
17936ac495dSmrg *patternp++ = 'S';
18036ac495dSmrg encode_pattern_1 (XEXP (x, 0));
18136ac495dSmrg break;
18236ac495dSmrg case MEM:
18336ac495dSmrg *patternp++ = 'm';
18436ac495dSmrg /* FALLTHRU */
18536ac495dSmrg case CONST:
18636ac495dSmrg encode_pattern_1 (XEXP (x, 0));
18736ac495dSmrg break;
18836ac495dSmrg case SIGN_EXTEND:
18936ac495dSmrg *patternp++ = '^';
19036ac495dSmrg *patternp++ = 'S';
19136ac495dSmrg encode_pattern_1 (XEXP (x, 0));
19236ac495dSmrg break;
19336ac495dSmrg case ZERO_EXTEND:
19436ac495dSmrg *patternp++ = '^';
19536ac495dSmrg *patternp++ = 'Z';
19636ac495dSmrg encode_pattern_1 (XEXP (x, 0));
19736ac495dSmrg break;
19836ac495dSmrg case PLUS:
19936ac495dSmrg *patternp++ = '+';
20036ac495dSmrg encode_pattern_1 (XEXP (x, 0));
20136ac495dSmrg encode_pattern_1 (XEXP (x, 1));
20236ac495dSmrg break;
20336ac495dSmrg case PRE_DEC:
20436ac495dSmrg *patternp++ = '>';
20536ac495dSmrg encode_pattern_1 (XEXP (x, 0));
20636ac495dSmrg break;
20736ac495dSmrg case POST_INC:
20836ac495dSmrg *patternp++ = '<';
20936ac495dSmrg encode_pattern_1 (XEXP (x, 0));
21036ac495dSmrg break;
21136ac495dSmrg case LO_SUM:
21236ac495dSmrg *patternp++ = 'L';
21336ac495dSmrg encode_pattern_1 (XEXP (x, 0));
21436ac495dSmrg encode_pattern_1 (XEXP (x, 1));
21536ac495dSmrg break;
21636ac495dSmrg case HIGH:
21736ac495dSmrg *patternp++ = 'H';
21836ac495dSmrg encode_pattern_1 (XEXP (x, 0));
21936ac495dSmrg break;
22036ac495dSmrg case SYMBOL_REF:
22136ac495dSmrg *patternp++ = 's';
22236ac495dSmrg break;
22336ac495dSmrg case LABEL_REF:
22436ac495dSmrg *patternp++ = 'l';
22536ac495dSmrg break;
22636ac495dSmrg case CODE_LABEL:
22736ac495dSmrg *patternp++ = 'c';
22836ac495dSmrg break;
22936ac495dSmrg case CONST_INT:
23036ac495dSmrg case CONST_DOUBLE:
23136ac495dSmrg *patternp++ = 'i';
23236ac495dSmrg break;
23336ac495dSmrg case UNSPEC:
23436ac495dSmrg *patternp++ = 'u';
23536ac495dSmrg *patternp++ = '0' + XCINT (x, 1, UNSPEC);
23636ac495dSmrg for (i = 0; i < XVECLEN (x, 0); i++)
23736ac495dSmrg encode_pattern_1 (XVECEXP (x, 0, i));
23836ac495dSmrg break;
23936ac495dSmrg case USE:
24036ac495dSmrg *patternp++ = 'U';
24136ac495dSmrg break;
24236ac495dSmrg case PARALLEL:
24336ac495dSmrg *patternp++ = '|';
24436ac495dSmrg for (i = 0; i < XVECLEN (x, 0); i++)
24536ac495dSmrg encode_pattern_1 (XVECEXP (x, 0, i));
24636ac495dSmrg break;
24736ac495dSmrg case EXPR_LIST:
24836ac495dSmrg *patternp++ = 'E';
24936ac495dSmrg encode_pattern_1 (XEXP (x, 0));
25036ac495dSmrg if (XEXP (x, 1))
25136ac495dSmrg encode_pattern_1 (XEXP (x, 1));
25236ac495dSmrg break;
25336ac495dSmrg default:
25436ac495dSmrg *patternp++ = '?';
25536ac495dSmrg #if DEBUG0
25636ac495dSmrg fprintf (stderr, "can't encode pattern %s\n",
25736ac495dSmrg GET_RTX_NAME (GET_CODE (x)));
25836ac495dSmrg debug_rtx (x);
25936ac495dSmrg #endif
26036ac495dSmrg break;
26136ac495dSmrg }
26236ac495dSmrg }
26336ac495dSmrg
26436ac495dSmrg static void
encode_pattern(rtx x)26536ac495dSmrg encode_pattern (rtx x)
26636ac495dSmrg {
26736ac495dSmrg patternp = pattern;
26836ac495dSmrg encode_pattern_1 (x);
26936ac495dSmrg *patternp = 0;
27036ac495dSmrg }
27136ac495dSmrg
27236ac495dSmrg /* Since register names indicate the mode they're used in, we need a
27336ac495dSmrg way to determine which name to refer to the register with. Called
27436ac495dSmrg by print_operand(). */
27536ac495dSmrg
27636ac495dSmrg static const char *
reg_name_with_mode(int regno,machine_mode mode)27736ac495dSmrg reg_name_with_mode (int regno, machine_mode mode)
27836ac495dSmrg {
27936ac495dSmrg int mlen = GET_MODE_SIZE (mode);
28036ac495dSmrg if (regno == R0_REGNO && mlen == 1)
28136ac495dSmrg return "r0l";
28236ac495dSmrg if (regno == R0_REGNO && (mlen == 3 || mlen == 4))
28336ac495dSmrg return "r2r0";
28436ac495dSmrg if (regno == R0_REGNO && mlen == 6)
28536ac495dSmrg return "r2r1r0";
28636ac495dSmrg if (regno == R0_REGNO && mlen == 8)
28736ac495dSmrg return "r3r1r2r0";
28836ac495dSmrg if (regno == R1_REGNO && mlen == 1)
28936ac495dSmrg return "r1l";
29036ac495dSmrg if (regno == R1_REGNO && (mlen == 3 || mlen == 4))
29136ac495dSmrg return "r3r1";
29236ac495dSmrg if (regno == A0_REGNO && TARGET_A16 && (mlen == 3 || mlen == 4))
29336ac495dSmrg return "a1a0";
29436ac495dSmrg return reg_names[regno];
29536ac495dSmrg }
29636ac495dSmrg
29736ac495dSmrg /* How many bytes a register uses on stack when it's pushed. We need
29836ac495dSmrg to know this because the push opcode needs to explicitly indicate
29936ac495dSmrg the size of the register, even though the name of the register
30036ac495dSmrg already tells it that. Used by m32c_output_reg_{push,pop}, which
30136ac495dSmrg is only used through calls to ASM_OUTPUT_REG_{PUSH,POP}. */
30236ac495dSmrg
30336ac495dSmrg static int
reg_push_size(int regno)30436ac495dSmrg reg_push_size (int regno)
30536ac495dSmrg {
30636ac495dSmrg switch (regno)
30736ac495dSmrg {
30836ac495dSmrg case R0_REGNO:
30936ac495dSmrg case R1_REGNO:
31036ac495dSmrg return 2;
31136ac495dSmrg case R2_REGNO:
31236ac495dSmrg case R3_REGNO:
31336ac495dSmrg case FLG_REGNO:
31436ac495dSmrg return 2;
31536ac495dSmrg case A0_REGNO:
31636ac495dSmrg case A1_REGNO:
31736ac495dSmrg case SB_REGNO:
31836ac495dSmrg case FB_REGNO:
31936ac495dSmrg case SP_REGNO:
32036ac495dSmrg if (TARGET_A16)
32136ac495dSmrg return 2;
32236ac495dSmrg else
32336ac495dSmrg return 3;
32436ac495dSmrg default:
32536ac495dSmrg gcc_unreachable ();
32636ac495dSmrg }
32736ac495dSmrg }
32836ac495dSmrg
32936ac495dSmrg /* Given two register classes, find the largest intersection between
33036ac495dSmrg them. If there is no intersection, return RETURNED_IF_EMPTY
33136ac495dSmrg instead. */
33236ac495dSmrg static reg_class_t
reduce_class(reg_class_t original_class,reg_class_t limiting_class,reg_class_t returned_if_empty)33336ac495dSmrg reduce_class (reg_class_t original_class, reg_class_t limiting_class,
33436ac495dSmrg reg_class_t returned_if_empty)
33536ac495dSmrg {
33636ac495dSmrg HARD_REG_SET cc;
33736ac495dSmrg int i;
33836ac495dSmrg reg_class_t best = NO_REGS;
33936ac495dSmrg unsigned int best_size = 0;
34036ac495dSmrg
34136ac495dSmrg if (original_class == limiting_class)
34236ac495dSmrg return original_class;
34336ac495dSmrg
344*8feb0f0bSmrg cc = reg_class_contents[original_class] & reg_class_contents[limiting_class];
34536ac495dSmrg
34636ac495dSmrg for (i = 0; i < LIM_REG_CLASSES; i++)
34736ac495dSmrg {
34836ac495dSmrg if (hard_reg_set_subset_p (reg_class_contents[i], cc))
34936ac495dSmrg if (best_size < reg_class_size[i])
35036ac495dSmrg {
35136ac495dSmrg best = (reg_class_t) i;
35236ac495dSmrg best_size = reg_class_size[i];
35336ac495dSmrg }
35436ac495dSmrg
35536ac495dSmrg }
35636ac495dSmrg if (best == NO_REGS)
35736ac495dSmrg return returned_if_empty;
35836ac495dSmrg return best;
35936ac495dSmrg }
36036ac495dSmrg
36136ac495dSmrg /* Used by m32c_register_move_cost to determine if a move is
36236ac495dSmrg impossibly expensive. */
36336ac495dSmrg static bool
class_can_hold_mode(reg_class_t rclass,machine_mode mode)36436ac495dSmrg class_can_hold_mode (reg_class_t rclass, machine_mode mode)
36536ac495dSmrg {
36636ac495dSmrg /* Cache the results: 0=untested 1=no 2=yes */
36736ac495dSmrg static char results[LIM_REG_CLASSES][MAX_MACHINE_MODE];
36836ac495dSmrg
36936ac495dSmrg if (results[(int) rclass][mode] == 0)
37036ac495dSmrg {
37136ac495dSmrg int r;
37236ac495dSmrg results[rclass][mode] = 1;
37336ac495dSmrg for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
37436ac495dSmrg if (in_hard_reg_set_p (reg_class_contents[(int) rclass], mode, r)
375a2dc1f3fSmrg && m32c_hard_regno_mode_ok (r, mode))
37636ac495dSmrg {
37736ac495dSmrg results[rclass][mode] = 2;
37836ac495dSmrg break;
37936ac495dSmrg }
38036ac495dSmrg }
38136ac495dSmrg
38236ac495dSmrg #if DEBUG0
38336ac495dSmrg fprintf (stderr, "class %s can hold %s? %s\n",
38436ac495dSmrg class_names[(int) rclass], mode_name[mode],
38536ac495dSmrg (results[rclass][mode] == 2) ? "yes" : "no");
38636ac495dSmrg #endif
38736ac495dSmrg return results[(int) rclass][mode] == 2;
38836ac495dSmrg }
38936ac495dSmrg
39036ac495dSmrg /* Run-time Target Specification. */
39136ac495dSmrg
39236ac495dSmrg /* Memregs are memory locations that gcc treats like general
39336ac495dSmrg registers, as there are a limited number of true registers and the
39436ac495dSmrg m32c families can use memory in most places that registers can be
39536ac495dSmrg used.
39636ac495dSmrg
39736ac495dSmrg However, since memory accesses are more expensive than registers,
39836ac495dSmrg we allow the user to limit the number of memregs available, in
39936ac495dSmrg order to try to persuade gcc to try harder to use real registers.
40036ac495dSmrg
40136ac495dSmrg Memregs are provided by lib1funcs.S.
40236ac495dSmrg */
40336ac495dSmrg
40436ac495dSmrg int ok_to_change_target_memregs = TRUE;
40536ac495dSmrg
40636ac495dSmrg /* Implements TARGET_OPTION_OVERRIDE. */
40736ac495dSmrg
40836ac495dSmrg #undef TARGET_OPTION_OVERRIDE
40936ac495dSmrg #define TARGET_OPTION_OVERRIDE m32c_option_override
41036ac495dSmrg
41136ac495dSmrg static void
m32c_option_override(void)41236ac495dSmrg m32c_option_override (void)
41336ac495dSmrg {
41436ac495dSmrg /* We limit memregs to 0..16, and provide a default. */
41536ac495dSmrg if (global_options_set.x_target_memregs)
41636ac495dSmrg {
41736ac495dSmrg if (target_memregs < 0 || target_memregs > 16)
418c0a68be4Smrg error ("invalid target memregs value %<%d%>", target_memregs);
41936ac495dSmrg }
42036ac495dSmrg else
42136ac495dSmrg target_memregs = 16;
42236ac495dSmrg
42336ac495dSmrg if (TARGET_A24)
42436ac495dSmrg flag_ivopts = 0;
42536ac495dSmrg
42636ac495dSmrg /* This target defaults to strict volatile bitfields. */
42736ac495dSmrg if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
42836ac495dSmrg flag_strict_volatile_bitfields = 1;
42936ac495dSmrg
43036ac495dSmrg /* r8c/m16c have no 16-bit indirect call, so thunks are involved.
43136ac495dSmrg This is always worse than an absolute call. */
43236ac495dSmrg if (TARGET_A16)
43336ac495dSmrg flag_no_function_cse = 1;
43436ac495dSmrg
43536ac495dSmrg /* This wants to put insns between compares and their jumps. */
43636ac495dSmrg /* FIXME: The right solution is to properly trace the flags register
43736ac495dSmrg values, but that is too much work for stage 4. */
43836ac495dSmrg flag_combine_stack_adjustments = 0;
43936ac495dSmrg }
44036ac495dSmrg
44136ac495dSmrg #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
44236ac495dSmrg #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE m32c_override_options_after_change
44336ac495dSmrg
44436ac495dSmrg static void
m32c_override_options_after_change(void)44536ac495dSmrg m32c_override_options_after_change (void)
44636ac495dSmrg {
44736ac495dSmrg if (TARGET_A16)
44836ac495dSmrg flag_no_function_cse = 1;
44936ac495dSmrg }
45036ac495dSmrg
45136ac495dSmrg /* Defining data structures for per-function information */
45236ac495dSmrg
45336ac495dSmrg /* The usual; we set up our machine_function data. */
45436ac495dSmrg static struct machine_function *
m32c_init_machine_status(void)45536ac495dSmrg m32c_init_machine_status (void)
45636ac495dSmrg {
45736ac495dSmrg return ggc_cleared_alloc<machine_function> ();
45836ac495dSmrg }
45936ac495dSmrg
46036ac495dSmrg /* Implements INIT_EXPANDERS. We just set up to call the above
46136ac495dSmrg function. */
46236ac495dSmrg void
m32c_init_expanders(void)46336ac495dSmrg m32c_init_expanders (void)
46436ac495dSmrg {
46536ac495dSmrg init_machine_status = m32c_init_machine_status;
46636ac495dSmrg }
46736ac495dSmrg
46836ac495dSmrg /* Storage Layout */
46936ac495dSmrg
47036ac495dSmrg /* Register Basics */
47136ac495dSmrg
47236ac495dSmrg /* Basic Characteristics of Registers */
47336ac495dSmrg
47436ac495dSmrg /* Whether a mode fits in a register is complex enough to warrant a
47536ac495dSmrg table. */
47636ac495dSmrg static struct
47736ac495dSmrg {
47836ac495dSmrg char qi_regs;
47936ac495dSmrg char hi_regs;
48036ac495dSmrg char pi_regs;
48136ac495dSmrg char si_regs;
48236ac495dSmrg char di_regs;
48336ac495dSmrg } nregs_table[FIRST_PSEUDO_REGISTER] =
48436ac495dSmrg {
48536ac495dSmrg { 1, 1, 2, 2, 4 }, /* r0 */
48636ac495dSmrg { 0, 1, 0, 0, 0 }, /* r2 */
48736ac495dSmrg { 1, 1, 2, 2, 0 }, /* r1 */
48836ac495dSmrg { 0, 1, 0, 0, 0 }, /* r3 */
48936ac495dSmrg { 0, 1, 1, 0, 0 }, /* a0 */
49036ac495dSmrg { 0, 1, 1, 0, 0 }, /* a1 */
49136ac495dSmrg { 0, 1, 1, 0, 0 }, /* sb */
49236ac495dSmrg { 0, 1, 1, 0, 0 }, /* fb */
49336ac495dSmrg { 0, 1, 1, 0, 0 }, /* sp */
49436ac495dSmrg { 1, 1, 1, 0, 0 }, /* pc */
49536ac495dSmrg { 0, 0, 0, 0, 0 }, /* fl */
49636ac495dSmrg { 1, 1, 1, 0, 0 }, /* ap */
49736ac495dSmrg { 1, 1, 2, 2, 4 }, /* mem0 */
49836ac495dSmrg { 1, 1, 2, 2, 4 }, /* mem1 */
49936ac495dSmrg { 1, 1, 2, 2, 4 }, /* mem2 */
50036ac495dSmrg { 1, 1, 2, 2, 4 }, /* mem3 */
50136ac495dSmrg { 1, 1, 2, 2, 4 }, /* mem4 */
50236ac495dSmrg { 1, 1, 2, 2, 0 }, /* mem5 */
50336ac495dSmrg { 1, 1, 2, 2, 0 }, /* mem6 */
50436ac495dSmrg { 1, 1, 0, 0, 0 }, /* mem7 */
50536ac495dSmrg };
50636ac495dSmrg
50736ac495dSmrg /* Implements TARGET_CONDITIONAL_REGISTER_USAGE. We adjust the number
50836ac495dSmrg of available memregs, and select which registers need to be preserved
50936ac495dSmrg across calls based on the chip family. */
51036ac495dSmrg
51136ac495dSmrg #undef TARGET_CONDITIONAL_REGISTER_USAGE
51236ac495dSmrg #define TARGET_CONDITIONAL_REGISTER_USAGE m32c_conditional_register_usage
51336ac495dSmrg void
m32c_conditional_register_usage(void)51436ac495dSmrg m32c_conditional_register_usage (void)
51536ac495dSmrg {
51636ac495dSmrg int i;
51736ac495dSmrg
518a2dc1f3fSmrg if (target_memregs >= 0 && target_memregs <= 16)
51936ac495dSmrg {
52036ac495dSmrg /* The command line option is bytes, but our "registers" are
52136ac495dSmrg 16-bit words. */
52236ac495dSmrg for (i = (target_memregs+1)/2; i < 8; i++)
52336ac495dSmrg {
52436ac495dSmrg fixed_regs[MEM0_REGNO + i] = 1;
52536ac495dSmrg CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i);
52636ac495dSmrg }
52736ac495dSmrg }
52836ac495dSmrg
52936ac495dSmrg /* M32CM and M32C preserve more registers across function calls. */
53036ac495dSmrg if (TARGET_A24)
53136ac495dSmrg {
53236ac495dSmrg call_used_regs[R1_REGNO] = 0;
53336ac495dSmrg call_used_regs[R2_REGNO] = 0;
53436ac495dSmrg call_used_regs[R3_REGNO] = 0;
53536ac495dSmrg call_used_regs[A0_REGNO] = 0;
53636ac495dSmrg call_used_regs[A1_REGNO] = 0;
53736ac495dSmrg }
53836ac495dSmrg }
53936ac495dSmrg
54036ac495dSmrg /* How Values Fit in Registers */
54136ac495dSmrg
542a2dc1f3fSmrg /* Implements TARGET_HARD_REGNO_NREGS. This is complicated by the fact that
54336ac495dSmrg different registers are different sizes from each other, *and* may
54436ac495dSmrg be different sizes in different chip families. */
545a2dc1f3fSmrg static unsigned int
m32c_hard_regno_nregs_1(unsigned int regno,machine_mode mode)546a2dc1f3fSmrg m32c_hard_regno_nregs_1 (unsigned int regno, machine_mode mode)
54736ac495dSmrg {
54836ac495dSmrg if (regno == FLG_REGNO && mode == CCmode)
54936ac495dSmrg return 1;
55036ac495dSmrg if (regno >= FIRST_PSEUDO_REGISTER)
55136ac495dSmrg return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
55236ac495dSmrg
55336ac495dSmrg if (regno >= MEM0_REGNO && regno <= MEM7_REGNO)
55436ac495dSmrg return (GET_MODE_SIZE (mode) + 1) / 2;
55536ac495dSmrg
55636ac495dSmrg if (GET_MODE_SIZE (mode) <= 1)
55736ac495dSmrg return nregs_table[regno].qi_regs;
55836ac495dSmrg if (GET_MODE_SIZE (mode) <= 2)
55936ac495dSmrg return nregs_table[regno].hi_regs;
56036ac495dSmrg if (regno == A0_REGNO && mode == SImode && TARGET_A16)
56136ac495dSmrg return 2;
56236ac495dSmrg if ((GET_MODE_SIZE (mode) <= 3 || mode == PSImode) && TARGET_A24)
56336ac495dSmrg return nregs_table[regno].pi_regs;
56436ac495dSmrg if (GET_MODE_SIZE (mode) <= 4)
56536ac495dSmrg return nregs_table[regno].si_regs;
56636ac495dSmrg if (GET_MODE_SIZE (mode) <= 8)
56736ac495dSmrg return nregs_table[regno].di_regs;
56836ac495dSmrg return 0;
56936ac495dSmrg }
57036ac495dSmrg
571a2dc1f3fSmrg static unsigned int
m32c_hard_regno_nregs(unsigned int regno,machine_mode mode)572a2dc1f3fSmrg m32c_hard_regno_nregs (unsigned int regno, machine_mode mode)
57336ac495dSmrg {
574a2dc1f3fSmrg unsigned int rv = m32c_hard_regno_nregs_1 (regno, mode);
57536ac495dSmrg return rv ? rv : 1;
57636ac495dSmrg }
57736ac495dSmrg
578a2dc1f3fSmrg /* Implement TARGET_HARD_REGNO_MODE_OK. The above function does the work
57936ac495dSmrg already; just test its return value. */
580a2dc1f3fSmrg static bool
m32c_hard_regno_mode_ok(unsigned int regno,machine_mode mode)581a2dc1f3fSmrg m32c_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
58236ac495dSmrg {
58336ac495dSmrg return m32c_hard_regno_nregs_1 (regno, mode) != 0;
58436ac495dSmrg }
58536ac495dSmrg
586a2dc1f3fSmrg /* Implement TARGET_MODES_TIEABLE_P. In general, modes aren't tieable since
58736ac495dSmrg registers are all different sizes. However, since most modes are
58836ac495dSmrg bigger than our registers anyway, it's easier to implement this
58936ac495dSmrg function that way, leaving QImode as the only unique case. */
590a2dc1f3fSmrg static bool
m32c_modes_tieable_p(machine_mode m1,machine_mode m2)59136ac495dSmrg m32c_modes_tieable_p (machine_mode m1, machine_mode m2)
59236ac495dSmrg {
59336ac495dSmrg if (GET_MODE_SIZE (m1) == GET_MODE_SIZE (m2))
59436ac495dSmrg return 1;
59536ac495dSmrg
59636ac495dSmrg #if 0
59736ac495dSmrg if (m1 == QImode || m2 == QImode)
59836ac495dSmrg return 0;
59936ac495dSmrg #endif
60036ac495dSmrg
60136ac495dSmrg return 1;
60236ac495dSmrg }
60336ac495dSmrg
60436ac495dSmrg /* Register Classes */
60536ac495dSmrg
60636ac495dSmrg /* Implements REGNO_REG_CLASS. */
60736ac495dSmrg enum reg_class
m32c_regno_reg_class(int regno)60836ac495dSmrg m32c_regno_reg_class (int regno)
60936ac495dSmrg {
61036ac495dSmrg switch (regno)
61136ac495dSmrg {
61236ac495dSmrg case R0_REGNO:
61336ac495dSmrg return R0_REGS;
61436ac495dSmrg case R1_REGNO:
61536ac495dSmrg return R1_REGS;
61636ac495dSmrg case R2_REGNO:
61736ac495dSmrg return R2_REGS;
61836ac495dSmrg case R3_REGNO:
61936ac495dSmrg return R3_REGS;
62036ac495dSmrg case A0_REGNO:
62136ac495dSmrg return A0_REGS;
62236ac495dSmrg case A1_REGNO:
62336ac495dSmrg return A1_REGS;
62436ac495dSmrg case SB_REGNO:
62536ac495dSmrg return SB_REGS;
62636ac495dSmrg case FB_REGNO:
62736ac495dSmrg return FB_REGS;
62836ac495dSmrg case SP_REGNO:
62936ac495dSmrg return SP_REGS;
63036ac495dSmrg case FLG_REGNO:
63136ac495dSmrg return FLG_REGS;
63236ac495dSmrg default:
63336ac495dSmrg if (IS_MEM_REGNO (regno))
63436ac495dSmrg return MEM_REGS;
63536ac495dSmrg return ALL_REGS;
63636ac495dSmrg }
63736ac495dSmrg }
63836ac495dSmrg
63936ac495dSmrg /* Implements REGNO_OK_FOR_BASE_P. */
64036ac495dSmrg int
m32c_regno_ok_for_base_p(int regno)64136ac495dSmrg m32c_regno_ok_for_base_p (int regno)
64236ac495dSmrg {
64336ac495dSmrg if (regno == A0_REGNO
64436ac495dSmrg || regno == A1_REGNO || regno >= FIRST_PSEUDO_REGISTER)
64536ac495dSmrg return 1;
64636ac495dSmrg return 0;
64736ac495dSmrg }
64836ac495dSmrg
64936ac495dSmrg /* Implements TARGET_PREFERRED_RELOAD_CLASS. In general, prefer general
65036ac495dSmrg registers of the appropriate size. */
65136ac495dSmrg
65236ac495dSmrg #undef TARGET_PREFERRED_RELOAD_CLASS
65336ac495dSmrg #define TARGET_PREFERRED_RELOAD_CLASS m32c_preferred_reload_class
65436ac495dSmrg
65536ac495dSmrg static reg_class_t
m32c_preferred_reload_class(rtx x,reg_class_t rclass)65636ac495dSmrg m32c_preferred_reload_class (rtx x, reg_class_t rclass)
65736ac495dSmrg {
65836ac495dSmrg reg_class_t newclass = rclass;
65936ac495dSmrg
66036ac495dSmrg #if DEBUG0
66136ac495dSmrg fprintf (stderr, "\npreferred_reload_class for %s is ",
66236ac495dSmrg class_names[rclass]);
66336ac495dSmrg #endif
66436ac495dSmrg if (rclass == NO_REGS)
66536ac495dSmrg rclass = GET_MODE (x) == QImode ? HL_REGS : R03_REGS;
66636ac495dSmrg
66736ac495dSmrg if (reg_classes_intersect_p (rclass, CR_REGS))
66836ac495dSmrg {
66936ac495dSmrg switch (GET_MODE (x))
67036ac495dSmrg {
671a2dc1f3fSmrg case E_QImode:
67236ac495dSmrg newclass = HL_REGS;
67336ac495dSmrg break;
67436ac495dSmrg default:
67536ac495dSmrg /* newclass = HI_REGS; */
67636ac495dSmrg break;
67736ac495dSmrg }
67836ac495dSmrg }
67936ac495dSmrg
68036ac495dSmrg else if (newclass == QI_REGS && GET_MODE_SIZE (GET_MODE (x)) > 2)
68136ac495dSmrg newclass = SI_REGS;
68236ac495dSmrg else if (GET_MODE_SIZE (GET_MODE (x)) > 4
68336ac495dSmrg && ! reg_class_subset_p (R03_REGS, rclass))
68436ac495dSmrg newclass = DI_REGS;
68536ac495dSmrg
68636ac495dSmrg rclass = reduce_class (rclass, newclass, rclass);
68736ac495dSmrg
68836ac495dSmrg if (GET_MODE (x) == QImode)
68936ac495dSmrg rclass = reduce_class (rclass, HL_REGS, rclass);
69036ac495dSmrg
69136ac495dSmrg #if DEBUG0
69236ac495dSmrg fprintf (stderr, "%s\n", class_names[rclass]);
69336ac495dSmrg debug_rtx (x);
69436ac495dSmrg
69536ac495dSmrg if (GET_CODE (x) == MEM
69636ac495dSmrg && GET_CODE (XEXP (x, 0)) == PLUS
69736ac495dSmrg && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
69836ac495dSmrg fprintf (stderr, "Glorm!\n");
69936ac495dSmrg #endif
70036ac495dSmrg return rclass;
70136ac495dSmrg }
70236ac495dSmrg
70336ac495dSmrg /* Implements TARGET_PREFERRED_OUTPUT_RELOAD_CLASS. */
70436ac495dSmrg
70536ac495dSmrg #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
70636ac495dSmrg #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS m32c_preferred_output_reload_class
70736ac495dSmrg
70836ac495dSmrg static reg_class_t
m32c_preferred_output_reload_class(rtx x,reg_class_t rclass)70936ac495dSmrg m32c_preferred_output_reload_class (rtx x, reg_class_t rclass)
71036ac495dSmrg {
71136ac495dSmrg return m32c_preferred_reload_class (x, rclass);
71236ac495dSmrg }
71336ac495dSmrg
71436ac495dSmrg /* Implements LIMIT_RELOAD_CLASS. We basically want to avoid using
71536ac495dSmrg address registers for reloads since they're needed for address
71636ac495dSmrg reloads. */
71736ac495dSmrg int
m32c_limit_reload_class(machine_mode mode,int rclass)71836ac495dSmrg m32c_limit_reload_class (machine_mode mode, int rclass)
71936ac495dSmrg {
72036ac495dSmrg #if DEBUG0
72136ac495dSmrg fprintf (stderr, "limit_reload_class for %s: %s ->",
72236ac495dSmrg mode_name[mode], class_names[rclass]);
72336ac495dSmrg #endif
72436ac495dSmrg
72536ac495dSmrg if (mode == QImode)
72636ac495dSmrg rclass = reduce_class (rclass, HL_REGS, rclass);
72736ac495dSmrg else if (mode == HImode)
72836ac495dSmrg rclass = reduce_class (rclass, HI_REGS, rclass);
72936ac495dSmrg else if (mode == SImode)
73036ac495dSmrg rclass = reduce_class (rclass, SI_REGS, rclass);
73136ac495dSmrg
73236ac495dSmrg if (rclass != A_REGS)
73336ac495dSmrg rclass = reduce_class (rclass, DI_REGS, rclass);
73436ac495dSmrg
73536ac495dSmrg #if DEBUG0
73636ac495dSmrg fprintf (stderr, " %s\n", class_names[rclass]);
73736ac495dSmrg #endif
73836ac495dSmrg return rclass;
73936ac495dSmrg }
74036ac495dSmrg
74136ac495dSmrg /* Implements SECONDARY_RELOAD_CLASS. QImode have to be reloaded in
74236ac495dSmrg r0 or r1, as those are the only real QImode registers. CR regs get
74336ac495dSmrg reloaded through appropriately sized general or address
74436ac495dSmrg registers. */
74536ac495dSmrg int
m32c_secondary_reload_class(int rclass,machine_mode mode,rtx x)74636ac495dSmrg m32c_secondary_reload_class (int rclass, machine_mode mode, rtx x)
74736ac495dSmrg {
74836ac495dSmrg int cc = class_contents[rclass][0];
74936ac495dSmrg #if DEBUG0
75036ac495dSmrg fprintf (stderr, "\nsecondary reload class %s %s\n",
75136ac495dSmrg class_names[rclass], mode_name[mode]);
75236ac495dSmrg debug_rtx (x);
75336ac495dSmrg #endif
75436ac495dSmrg if (mode == QImode
75536ac495dSmrg && GET_CODE (x) == MEM && (cc & ~class_contents[R23_REGS][0]) == 0)
75636ac495dSmrg return QI_REGS;
75736ac495dSmrg if (reg_classes_intersect_p (rclass, CR_REGS)
75836ac495dSmrg && GET_CODE (x) == REG
75936ac495dSmrg && REGNO (x) >= SB_REGNO && REGNO (x) <= SP_REGNO)
76036ac495dSmrg return (TARGET_A16 || mode == HImode) ? HI_REGS : A_REGS;
76136ac495dSmrg return NO_REGS;
76236ac495dSmrg }
76336ac495dSmrg
76436ac495dSmrg /* Implements TARGET_CLASS_LIKELY_SPILLED_P. A_REGS is needed for address
76536ac495dSmrg reloads. */
76636ac495dSmrg
76736ac495dSmrg #undef TARGET_CLASS_LIKELY_SPILLED_P
76836ac495dSmrg #define TARGET_CLASS_LIKELY_SPILLED_P m32c_class_likely_spilled_p
76936ac495dSmrg
77036ac495dSmrg static bool
m32c_class_likely_spilled_p(reg_class_t regclass)77136ac495dSmrg m32c_class_likely_spilled_p (reg_class_t regclass)
77236ac495dSmrg {
77336ac495dSmrg if (regclass == A_REGS)
77436ac495dSmrg return true;
77536ac495dSmrg
77636ac495dSmrg return (reg_class_size[(int) regclass] == 1);
77736ac495dSmrg }
77836ac495dSmrg
77936ac495dSmrg /* Implements TARGET_CLASS_MAX_NREGS. We calculate this according to its
78036ac495dSmrg documented meaning, to avoid potential inconsistencies with actual
78136ac495dSmrg class definitions. */
78236ac495dSmrg
78336ac495dSmrg #undef TARGET_CLASS_MAX_NREGS
78436ac495dSmrg #define TARGET_CLASS_MAX_NREGS m32c_class_max_nregs
78536ac495dSmrg
78636ac495dSmrg static unsigned char
m32c_class_max_nregs(reg_class_t regclass,machine_mode mode)78736ac495dSmrg m32c_class_max_nregs (reg_class_t regclass, machine_mode mode)
78836ac495dSmrg {
78936ac495dSmrg int rn;
79036ac495dSmrg unsigned char max = 0;
79136ac495dSmrg
79236ac495dSmrg for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
79336ac495dSmrg if (TEST_HARD_REG_BIT (reg_class_contents[(int) regclass], rn))
79436ac495dSmrg {
79536ac495dSmrg unsigned char n = m32c_hard_regno_nregs (rn, mode);
79636ac495dSmrg if (max < n)
79736ac495dSmrg max = n;
79836ac495dSmrg }
79936ac495dSmrg return max;
80036ac495dSmrg }
80136ac495dSmrg
802a2dc1f3fSmrg /* Implements TARGET_CAN_CHANGE_MODE_CLASS. Only r0 and r1 can change to
80336ac495dSmrg QI (r0l, r1l) because the chip doesn't support QI ops on other
80436ac495dSmrg registers (well, it does on a0/a1 but if we let gcc do that, reload
80536ac495dSmrg suffers). Otherwise, we allow changes to larger modes. */
806a2dc1f3fSmrg static bool
m32c_can_change_mode_class(machine_mode from,machine_mode to,reg_class_t rclass)807a2dc1f3fSmrg m32c_can_change_mode_class (machine_mode from,
808a2dc1f3fSmrg machine_mode to, reg_class_t rclass)
80936ac495dSmrg {
81036ac495dSmrg int rn;
81136ac495dSmrg #if DEBUG0
812a2dc1f3fSmrg fprintf (stderr, "can change from %s to %s in %s\n",
81336ac495dSmrg mode_name[from], mode_name[to], class_names[rclass]);
81436ac495dSmrg #endif
81536ac495dSmrg
81636ac495dSmrg /* If the larger mode isn't allowed in any of these registers, we
81736ac495dSmrg can't allow the change. */
81836ac495dSmrg for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
81936ac495dSmrg if (class_contents[rclass][0] & (1 << rn))
820a2dc1f3fSmrg if (! m32c_hard_regno_mode_ok (rn, to))
821a2dc1f3fSmrg return false;
82236ac495dSmrg
82336ac495dSmrg if (to == QImode)
824a2dc1f3fSmrg return (class_contents[rclass][0] & 0x1ffa) == 0;
82536ac495dSmrg
82636ac495dSmrg if (class_contents[rclass][0] & 0x0005 /* r0, r1 */
82736ac495dSmrg && GET_MODE_SIZE (from) > 1)
828a2dc1f3fSmrg return true;
82936ac495dSmrg if (GET_MODE_SIZE (from) > 2) /* all other regs */
830a2dc1f3fSmrg return true;
83136ac495dSmrg
832a2dc1f3fSmrg return false;
83336ac495dSmrg }
83436ac495dSmrg
83536ac495dSmrg /* Helpers for the rest of the file. */
83636ac495dSmrg /* TRUE if the rtx is a REG rtx for the given register. */
83736ac495dSmrg #define IS_REG(rtx,regno) (GET_CODE (rtx) == REG \
83836ac495dSmrg && REGNO (rtx) == regno)
83936ac495dSmrg /* TRUE if the rtx is a pseudo - specifically, one we can use as a
84036ac495dSmrg base register in address calculations (hence the "strict"
84136ac495dSmrg argument). */
84236ac495dSmrg #define IS_PSEUDO(rtx,strict) (!strict && GET_CODE (rtx) == REG \
84336ac495dSmrg && (REGNO (rtx) == AP_REGNO \
84436ac495dSmrg || REGNO (rtx) >= FIRST_PSEUDO_REGISTER))
84536ac495dSmrg
84636ac495dSmrg #define A0_OR_PSEUDO(x) (IS_REG(x, A0_REGNO) || REGNO (x) >= FIRST_PSEUDO_REGISTER)
84736ac495dSmrg
84836ac495dSmrg /* Implements matching for constraints (see next function too). 'S' is
84936ac495dSmrg for memory constraints, plus "Rpa" for PARALLEL rtx's we use for
85036ac495dSmrg call return values. */
85136ac495dSmrg bool
m32c_matches_constraint_p(rtx value,int constraint)85236ac495dSmrg m32c_matches_constraint_p (rtx value, int constraint)
85336ac495dSmrg {
85436ac495dSmrg encode_pattern (value);
85536ac495dSmrg
85636ac495dSmrg switch (constraint) {
85736ac495dSmrg case CONSTRAINT_SF:
85836ac495dSmrg return (far_addr_space_p (value)
85936ac495dSmrg && ((RTX_IS ("mr")
86036ac495dSmrg && A0_OR_PSEUDO (patternr[1])
86136ac495dSmrg && GET_MODE (patternr[1]) == SImode)
86236ac495dSmrg || (RTX_IS ("m+^Sri")
86336ac495dSmrg && A0_OR_PSEUDO (patternr[4])
86436ac495dSmrg && GET_MODE (patternr[4]) == HImode)
86536ac495dSmrg || (RTX_IS ("m+^Srs")
86636ac495dSmrg && A0_OR_PSEUDO (patternr[4])
86736ac495dSmrg && GET_MODE (patternr[4]) == HImode)
86836ac495dSmrg || (RTX_IS ("m+^S+ris")
86936ac495dSmrg && A0_OR_PSEUDO (patternr[5])
87036ac495dSmrg && GET_MODE (patternr[5]) == HImode)
87136ac495dSmrg || RTX_IS ("ms")));
87236ac495dSmrg case CONSTRAINT_Sd:
87336ac495dSmrg {
87436ac495dSmrg /* This is the common "src/dest" address */
87536ac495dSmrg rtx r;
87636ac495dSmrg if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)))
87736ac495dSmrg return true;
87836ac495dSmrg if (RTX_IS ("ms") || RTX_IS ("m+si"))
87936ac495dSmrg return true;
88036ac495dSmrg if (RTX_IS ("m++rii"))
88136ac495dSmrg {
88236ac495dSmrg if (REGNO (patternr[3]) == FB_REGNO
88336ac495dSmrg && INTVAL (patternr[4]) == 0)
88436ac495dSmrg return true;
88536ac495dSmrg }
88636ac495dSmrg if (RTX_IS ("mr"))
88736ac495dSmrg r = patternr[1];
88836ac495dSmrg else if (RTX_IS ("m+ri") || RTX_IS ("m+rs") || RTX_IS ("m+r+si"))
88936ac495dSmrg r = patternr[2];
89036ac495dSmrg else
89136ac495dSmrg return false;
89236ac495dSmrg if (REGNO (r) == SP_REGNO)
89336ac495dSmrg return false;
89436ac495dSmrg return m32c_legitimate_address_p (GET_MODE (value), XEXP (value, 0), 1);
89536ac495dSmrg }
89636ac495dSmrg case CONSTRAINT_Sa:
89736ac495dSmrg {
89836ac495dSmrg rtx r;
89936ac495dSmrg if (RTX_IS ("mr"))
90036ac495dSmrg r = patternr[1];
90136ac495dSmrg else if (RTX_IS ("m+ri"))
90236ac495dSmrg r = patternr[2];
90336ac495dSmrg else
90436ac495dSmrg return false;
90536ac495dSmrg return (IS_REG (r, A0_REGNO) || IS_REG (r, A1_REGNO));
90636ac495dSmrg }
90736ac495dSmrg case CONSTRAINT_Si:
90836ac495dSmrg return (RTX_IS ("mi") || RTX_IS ("ms") || RTX_IS ("m+si"));
90936ac495dSmrg case CONSTRAINT_Ss:
91036ac495dSmrg return ((RTX_IS ("mr")
91136ac495dSmrg && (IS_REG (patternr[1], SP_REGNO)))
91236ac495dSmrg || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SP_REGNO))));
91336ac495dSmrg case CONSTRAINT_Sf:
91436ac495dSmrg return ((RTX_IS ("mr")
91536ac495dSmrg && (IS_REG (patternr[1], FB_REGNO)))
91636ac495dSmrg || (RTX_IS ("m+ri") && (IS_REG (patternr[2], FB_REGNO))));
91736ac495dSmrg case CONSTRAINT_Sb:
91836ac495dSmrg return ((RTX_IS ("mr")
91936ac495dSmrg && (IS_REG (patternr[1], SB_REGNO)))
92036ac495dSmrg || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SB_REGNO))));
92136ac495dSmrg case CONSTRAINT_Sp:
92236ac495dSmrg /* Absolute addresses 0..0x1fff used for bit addressing (I/O ports) */
92336ac495dSmrg return (RTX_IS ("mi")
92436ac495dSmrg && !(INTVAL (patternr[1]) & ~0x1fff));
92536ac495dSmrg case CONSTRAINT_S1:
92636ac495dSmrg return r1h_operand (value, QImode);
92736ac495dSmrg case CONSTRAINT_Rpa:
92836ac495dSmrg return GET_CODE (value) == PARALLEL;
92936ac495dSmrg default:
93036ac495dSmrg return false;
93136ac495dSmrg }
93236ac495dSmrg }
93336ac495dSmrg
93436ac495dSmrg /* STACK AND CALLING */
93536ac495dSmrg
93636ac495dSmrg /* Frame Layout */
93736ac495dSmrg
93836ac495dSmrg /* Implements RETURN_ADDR_RTX. Note that R8C and M16C push 24 bits
93936ac495dSmrg (yes, THREE bytes) onto the stack for the return address, but we
94036ac495dSmrg don't support pointers bigger than 16 bits on those chips. This
94136ac495dSmrg will likely wreak havoc with exception unwinding. FIXME. */
94236ac495dSmrg rtx
m32c_return_addr_rtx(int count)94336ac495dSmrg m32c_return_addr_rtx (int count)
94436ac495dSmrg {
94536ac495dSmrg machine_mode mode;
94636ac495dSmrg int offset;
94736ac495dSmrg rtx ra_mem;
94836ac495dSmrg
94936ac495dSmrg if (count)
95036ac495dSmrg return NULL_RTX;
95136ac495dSmrg /* we want 2[$fb] */
95236ac495dSmrg
95336ac495dSmrg if (TARGET_A24)
95436ac495dSmrg {
95536ac495dSmrg /* It's four bytes */
95636ac495dSmrg mode = PSImode;
95736ac495dSmrg offset = 4;
95836ac495dSmrg }
95936ac495dSmrg else
96036ac495dSmrg {
96136ac495dSmrg /* FIXME: it's really 3 bytes */
96236ac495dSmrg mode = HImode;
96336ac495dSmrg offset = 2;
96436ac495dSmrg }
96536ac495dSmrg
96636ac495dSmrg ra_mem =
96736ac495dSmrg gen_rtx_MEM (mode, plus_constant (Pmode, gen_rtx_REG (Pmode, FP_REGNO),
96836ac495dSmrg offset));
96936ac495dSmrg return copy_to_mode_reg (mode, ra_mem);
97036ac495dSmrg }
97136ac495dSmrg
97236ac495dSmrg /* Implements INCOMING_RETURN_ADDR_RTX. See comment above. */
97336ac495dSmrg rtx
m32c_incoming_return_addr_rtx(void)97436ac495dSmrg m32c_incoming_return_addr_rtx (void)
97536ac495dSmrg {
97636ac495dSmrg /* we want [sp] */
97736ac495dSmrg return gen_rtx_MEM (PSImode, gen_rtx_REG (PSImode, SP_REGNO));
97836ac495dSmrg }
97936ac495dSmrg
98036ac495dSmrg /* Exception Handling Support */
98136ac495dSmrg
98236ac495dSmrg /* Implements EH_RETURN_DATA_REGNO. Choose registers able to hold
98336ac495dSmrg pointers. */
98436ac495dSmrg int
m32c_eh_return_data_regno(int n)98536ac495dSmrg m32c_eh_return_data_regno (int n)
98636ac495dSmrg {
98736ac495dSmrg switch (n)
98836ac495dSmrg {
98936ac495dSmrg case 0:
99036ac495dSmrg return MEM0_REGNO;
99136ac495dSmrg case 1:
99236ac495dSmrg return MEM0_REGNO+4;
99336ac495dSmrg default:
99436ac495dSmrg return INVALID_REGNUM;
99536ac495dSmrg }
99636ac495dSmrg }
99736ac495dSmrg
99836ac495dSmrg /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
99936ac495dSmrg m32c_emit_eh_epilogue. */
100036ac495dSmrg rtx
m32c_eh_return_stackadj_rtx(void)100136ac495dSmrg m32c_eh_return_stackadj_rtx (void)
100236ac495dSmrg {
100336ac495dSmrg if (!cfun->machine->eh_stack_adjust)
100436ac495dSmrg {
100536ac495dSmrg rtx sa;
100636ac495dSmrg
100736ac495dSmrg sa = gen_rtx_REG (Pmode, R0_REGNO);
100836ac495dSmrg cfun->machine->eh_stack_adjust = sa;
100936ac495dSmrg }
101036ac495dSmrg return cfun->machine->eh_stack_adjust;
101136ac495dSmrg }
101236ac495dSmrg
101336ac495dSmrg /* Registers That Address the Stack Frame */
101436ac495dSmrg
101536ac495dSmrg /* Implements DWARF_FRAME_REGNUM and DBX_REGISTER_NUMBER. Note that
101636ac495dSmrg the original spec called for dwarf numbers to vary with register
101736ac495dSmrg width as well, for example, r0l, r0, and r2r0 would each have
101836ac495dSmrg different dwarf numbers. GCC doesn't support this, and we don't do
101936ac495dSmrg it, and gdb seems to like it this way anyway. */
102036ac495dSmrg unsigned int
m32c_dwarf_frame_regnum(int n)102136ac495dSmrg m32c_dwarf_frame_regnum (int n)
102236ac495dSmrg {
102336ac495dSmrg switch (n)
102436ac495dSmrg {
102536ac495dSmrg case R0_REGNO:
102636ac495dSmrg return 5;
102736ac495dSmrg case R1_REGNO:
102836ac495dSmrg return 6;
102936ac495dSmrg case R2_REGNO:
103036ac495dSmrg return 7;
103136ac495dSmrg case R3_REGNO:
103236ac495dSmrg return 8;
103336ac495dSmrg case A0_REGNO:
103436ac495dSmrg return 9;
103536ac495dSmrg case A1_REGNO:
103636ac495dSmrg return 10;
103736ac495dSmrg case FB_REGNO:
103836ac495dSmrg return 11;
103936ac495dSmrg case SB_REGNO:
104036ac495dSmrg return 19;
104136ac495dSmrg
104236ac495dSmrg case SP_REGNO:
104336ac495dSmrg return 12;
104436ac495dSmrg case PC_REGNO:
104536ac495dSmrg return 13;
104636ac495dSmrg default:
104736ac495dSmrg return DWARF_FRAME_REGISTERS + 1;
104836ac495dSmrg }
104936ac495dSmrg }
105036ac495dSmrg
105136ac495dSmrg /* The frame looks like this:
105236ac495dSmrg
105336ac495dSmrg ap -> +------------------------------
105436ac495dSmrg | Return address (3 or 4 bytes)
105536ac495dSmrg | Saved FB (2 or 4 bytes)
105636ac495dSmrg fb -> +------------------------------
105736ac495dSmrg | local vars
105836ac495dSmrg | register saves fb
105936ac495dSmrg | through r0 as needed
106036ac495dSmrg sp -> +------------------------------
106136ac495dSmrg */
106236ac495dSmrg
106336ac495dSmrg /* We use this to wrap all emitted insns in the prologue. */
106436ac495dSmrg static rtx
F(rtx x)106536ac495dSmrg F (rtx x)
106636ac495dSmrg {
106736ac495dSmrg RTX_FRAME_RELATED_P (x) = 1;
106836ac495dSmrg return x;
106936ac495dSmrg }
107036ac495dSmrg
107136ac495dSmrg /* This maps register numbers to the PUSHM/POPM bitfield, and tells us
107236ac495dSmrg how much the stack pointer moves for each, for each cpu family. */
107336ac495dSmrg static struct
107436ac495dSmrg {
107536ac495dSmrg int reg1;
107636ac495dSmrg int bit;
107736ac495dSmrg int a16_bytes;
107836ac495dSmrg int a24_bytes;
107936ac495dSmrg } pushm_info[] =
108036ac495dSmrg {
108136ac495dSmrg /* These are in reverse push (nearest-to-sp) order. */
108236ac495dSmrg { R0_REGNO, 0x80, 2, 2 },
108336ac495dSmrg { R1_REGNO, 0x40, 2, 2 },
108436ac495dSmrg { R2_REGNO, 0x20, 2, 2 },
108536ac495dSmrg { R3_REGNO, 0x10, 2, 2 },
108636ac495dSmrg { A0_REGNO, 0x08, 2, 4 },
108736ac495dSmrg { A1_REGNO, 0x04, 2, 4 },
108836ac495dSmrg { SB_REGNO, 0x02, 2, 4 },
108936ac495dSmrg { FB_REGNO, 0x01, 2, 4 }
109036ac495dSmrg };
109136ac495dSmrg
109236ac495dSmrg #define PUSHM_N (sizeof(pushm_info)/sizeof(pushm_info[0]))
109336ac495dSmrg
109436ac495dSmrg /* Returns TRUE if we need to save/restore the given register. We
109536ac495dSmrg save everything for exception handlers, so that any register can be
109636ac495dSmrg unwound. For interrupt handlers, we save everything if the handler
109736ac495dSmrg calls something else (because we don't know what *that* function
109836ac495dSmrg might do), but try to be a bit smarter if the handler is a leaf
109936ac495dSmrg function. We always save $a0, though, because we use that in the
110036ac495dSmrg epilogue to copy $fb to $sp. */
110136ac495dSmrg static int
need_to_save(int regno)110236ac495dSmrg need_to_save (int regno)
110336ac495dSmrg {
110436ac495dSmrg if (fixed_regs[regno])
110536ac495dSmrg return 0;
110636ac495dSmrg if (crtl->calls_eh_return)
110736ac495dSmrg return 1;
110836ac495dSmrg if (regno == FP_REGNO)
110936ac495dSmrg return 0;
111036ac495dSmrg if (cfun->machine->is_interrupt
111136ac495dSmrg && (!cfun->machine->is_leaf
111236ac495dSmrg || (regno == A0_REGNO
111336ac495dSmrg && m32c_function_needs_enter ())
111436ac495dSmrg ))
111536ac495dSmrg return 1;
111636ac495dSmrg if (df_regs_ever_live_p (regno)
1117*8feb0f0bSmrg && (!call_used_or_fixed_reg_p (regno) || cfun->machine->is_interrupt))
111836ac495dSmrg return 1;
111936ac495dSmrg return 0;
112036ac495dSmrg }
112136ac495dSmrg
112236ac495dSmrg /* This function contains all the intelligence about saving and
112336ac495dSmrg restoring registers. It always figures out the register save set.
112436ac495dSmrg When called with PP_justcount, it merely returns the size of the
112536ac495dSmrg save set (for eliminating the frame pointer, for example). When
112636ac495dSmrg called with PP_pushm or PP_popm, it emits the appropriate
112736ac495dSmrg instructions for saving (pushm) or restoring (popm) the
112836ac495dSmrg registers. */
112936ac495dSmrg static int
m32c_pushm_popm(Push_Pop_Type ppt)113036ac495dSmrg m32c_pushm_popm (Push_Pop_Type ppt)
113136ac495dSmrg {
113236ac495dSmrg int reg_mask = 0;
113336ac495dSmrg int byte_count = 0, bytes;
113436ac495dSmrg int i;
113536ac495dSmrg rtx dwarf_set[PUSHM_N];
113636ac495dSmrg int n_dwarfs = 0;
113736ac495dSmrg int nosave_mask = 0;
113836ac495dSmrg
113936ac495dSmrg if (crtl->return_rtx
114036ac495dSmrg && GET_CODE (crtl->return_rtx) == PARALLEL
114136ac495dSmrg && !(crtl->calls_eh_return || cfun->machine->is_interrupt))
114236ac495dSmrg {
114336ac495dSmrg rtx exp = XVECEXP (crtl->return_rtx, 0, 0);
114436ac495dSmrg rtx rv = XEXP (exp, 0);
114536ac495dSmrg int rv_bytes = GET_MODE_SIZE (GET_MODE (rv));
114636ac495dSmrg
114736ac495dSmrg if (rv_bytes > 2)
114836ac495dSmrg nosave_mask |= 0x20; /* PSI, SI */
114936ac495dSmrg else
115036ac495dSmrg nosave_mask |= 0xf0; /* DF */
115136ac495dSmrg if (rv_bytes > 4)
115236ac495dSmrg nosave_mask |= 0x50; /* DI */
115336ac495dSmrg }
115436ac495dSmrg
115536ac495dSmrg for (i = 0; i < (int) PUSHM_N; i++)
115636ac495dSmrg {
115736ac495dSmrg /* Skip if neither register needs saving. */
115836ac495dSmrg if (!need_to_save (pushm_info[i].reg1))
115936ac495dSmrg continue;
116036ac495dSmrg
116136ac495dSmrg if (pushm_info[i].bit & nosave_mask)
116236ac495dSmrg continue;
116336ac495dSmrg
116436ac495dSmrg reg_mask |= pushm_info[i].bit;
116536ac495dSmrg bytes = TARGET_A16 ? pushm_info[i].a16_bytes : pushm_info[i].a24_bytes;
116636ac495dSmrg
116736ac495dSmrg if (ppt == PP_pushm)
116836ac495dSmrg {
116936ac495dSmrg machine_mode mode = (bytes == 2) ? HImode : SImode;
117036ac495dSmrg rtx addr;
117136ac495dSmrg
117236ac495dSmrg /* Always use stack_pointer_rtx instead of calling
117336ac495dSmrg rtx_gen_REG ourselves. Code elsewhere in GCC assumes
117436ac495dSmrg that there is a single rtx representing the stack pointer,
117536ac495dSmrg namely stack_pointer_rtx, and uses == to recognize it. */
117636ac495dSmrg addr = stack_pointer_rtx;
117736ac495dSmrg
117836ac495dSmrg if (byte_count != 0)
117936ac495dSmrg addr = gen_rtx_PLUS (GET_MODE (addr), addr, GEN_INT (byte_count));
118036ac495dSmrg
118136ac495dSmrg dwarf_set[n_dwarfs++] =
118236ac495dSmrg gen_rtx_SET (gen_rtx_MEM (mode, addr),
118336ac495dSmrg gen_rtx_REG (mode, pushm_info[i].reg1));
118436ac495dSmrg F (dwarf_set[n_dwarfs - 1]);
118536ac495dSmrg
118636ac495dSmrg }
118736ac495dSmrg byte_count += bytes;
118836ac495dSmrg }
118936ac495dSmrg
119036ac495dSmrg if (cfun->machine->is_interrupt)
119136ac495dSmrg {
119236ac495dSmrg cfun->machine->intr_pushm = reg_mask & 0xfe;
119336ac495dSmrg reg_mask = 0;
119436ac495dSmrg byte_count = 0;
119536ac495dSmrg }
119636ac495dSmrg
119736ac495dSmrg if (cfun->machine->is_interrupt)
119836ac495dSmrg for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
119936ac495dSmrg if (need_to_save (i))
120036ac495dSmrg {
120136ac495dSmrg byte_count += 2;
120236ac495dSmrg cfun->machine->intr_pushmem[i - MEM0_REGNO] = 1;
120336ac495dSmrg }
120436ac495dSmrg
120536ac495dSmrg if (ppt == PP_pushm && byte_count)
120636ac495dSmrg {
120736ac495dSmrg rtx note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (n_dwarfs + 1));
120836ac495dSmrg rtx pushm;
120936ac495dSmrg
121036ac495dSmrg if (reg_mask)
121136ac495dSmrg {
121236ac495dSmrg XVECEXP (note, 0, 0)
121336ac495dSmrg = gen_rtx_SET (stack_pointer_rtx,
121436ac495dSmrg gen_rtx_PLUS (GET_MODE (stack_pointer_rtx),
121536ac495dSmrg stack_pointer_rtx,
121636ac495dSmrg GEN_INT (-byte_count)));
121736ac495dSmrg F (XVECEXP (note, 0, 0));
121836ac495dSmrg
121936ac495dSmrg for (i = 0; i < n_dwarfs; i++)
122036ac495dSmrg XVECEXP (note, 0, i + 1) = dwarf_set[i];
122136ac495dSmrg
122236ac495dSmrg pushm = F (emit_insn (gen_pushm (GEN_INT (reg_mask))));
122336ac495dSmrg
122436ac495dSmrg add_reg_note (pushm, REG_FRAME_RELATED_EXPR, note);
122536ac495dSmrg }
122636ac495dSmrg
122736ac495dSmrg if (cfun->machine->is_interrupt)
122836ac495dSmrg for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
122936ac495dSmrg if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
123036ac495dSmrg {
123136ac495dSmrg if (TARGET_A16)
123236ac495dSmrg pushm = emit_insn (gen_pushhi_16 (gen_rtx_REG (HImode, i)));
123336ac495dSmrg else
123436ac495dSmrg pushm = emit_insn (gen_pushhi_24 (gen_rtx_REG (HImode, i)));
123536ac495dSmrg F (pushm);
123636ac495dSmrg }
123736ac495dSmrg }
123836ac495dSmrg if (ppt == PP_popm && byte_count)
123936ac495dSmrg {
124036ac495dSmrg if (cfun->machine->is_interrupt)
124136ac495dSmrg for (i = MEM7_REGNO; i >= MEM0_REGNO; i--)
124236ac495dSmrg if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
124336ac495dSmrg {
124436ac495dSmrg if (TARGET_A16)
124536ac495dSmrg emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, i)));
124636ac495dSmrg else
124736ac495dSmrg emit_insn (gen_pophi_24 (gen_rtx_REG (HImode, i)));
124836ac495dSmrg }
124936ac495dSmrg if (reg_mask)
125036ac495dSmrg emit_insn (gen_popm (GEN_INT (reg_mask)));
125136ac495dSmrg }
125236ac495dSmrg
125336ac495dSmrg return byte_count;
125436ac495dSmrg }
125536ac495dSmrg
125636ac495dSmrg /* Implements INITIAL_ELIMINATION_OFFSET. See the comment above that
125736ac495dSmrg diagrams our call frame. */
125836ac495dSmrg int
m32c_initial_elimination_offset(int from,int to)125936ac495dSmrg m32c_initial_elimination_offset (int from, int to)
126036ac495dSmrg {
126136ac495dSmrg int ofs = 0;
126236ac495dSmrg
126336ac495dSmrg if (from == AP_REGNO)
126436ac495dSmrg {
126536ac495dSmrg if (TARGET_A16)
126636ac495dSmrg ofs += 5;
126736ac495dSmrg else
126836ac495dSmrg ofs += 8;
126936ac495dSmrg }
127036ac495dSmrg
127136ac495dSmrg if (to == SP_REGNO)
127236ac495dSmrg {
127336ac495dSmrg ofs += m32c_pushm_popm (PP_justcount);
127436ac495dSmrg ofs += get_frame_size ();
127536ac495dSmrg }
127636ac495dSmrg
127736ac495dSmrg /* Account for push rounding. */
127836ac495dSmrg if (TARGET_A24)
127936ac495dSmrg ofs = (ofs + 1) & ~1;
128036ac495dSmrg #if DEBUG0
128136ac495dSmrg fprintf (stderr, "initial_elimination_offset from=%d to=%d, ofs=%d\n", from,
128236ac495dSmrg to, ofs);
128336ac495dSmrg #endif
128436ac495dSmrg return ofs;
128536ac495dSmrg }
128636ac495dSmrg
128736ac495dSmrg /* Passing Function Arguments on the Stack */
128836ac495dSmrg
128936ac495dSmrg /* Implements PUSH_ROUNDING. The R8C and M16C have byte stacks, the
129036ac495dSmrg M32C has word stacks. */
1291a2dc1f3fSmrg poly_int64
m32c_push_rounding(poly_int64 n)1292a2dc1f3fSmrg m32c_push_rounding (poly_int64 n)
129336ac495dSmrg {
129436ac495dSmrg if (TARGET_R8C || TARGET_M16C)
129536ac495dSmrg return n;
129636ac495dSmrg return (n + 1) & ~1;
129736ac495dSmrg }
129836ac495dSmrg
129936ac495dSmrg /* Passing Arguments in Registers */
130036ac495dSmrg
130136ac495dSmrg /* Implements TARGET_FUNCTION_ARG. Arguments are passed partly in
130236ac495dSmrg registers, partly on stack. If our function returns a struct, a
130336ac495dSmrg pointer to a buffer for it is at the top of the stack (last thing
130436ac495dSmrg pushed). The first few real arguments may be in registers as
130536ac495dSmrg follows:
130636ac495dSmrg
130736ac495dSmrg R8C/M16C: arg1 in r1 if it's QI or HI (else it's pushed on stack)
130836ac495dSmrg arg2 in r2 if it's HI (else pushed on stack)
130936ac495dSmrg rest on stack
131036ac495dSmrg M32C: arg1 in r0 if it's QI or HI (else it's pushed on stack)
131136ac495dSmrg rest on stack
131236ac495dSmrg
131336ac495dSmrg Structs are not passed in registers, even if they fit. Only
131436ac495dSmrg integer and pointer types are passed in registers.
131536ac495dSmrg
131636ac495dSmrg Note that when arg1 doesn't fit in r1, arg2 may still be passed in
131736ac495dSmrg r2 if it fits. */
131836ac495dSmrg #undef TARGET_FUNCTION_ARG
131936ac495dSmrg #define TARGET_FUNCTION_ARG m32c_function_arg
132036ac495dSmrg static rtx
m32c_function_arg(cumulative_args_t ca_v,const function_arg_info & arg)1321*8feb0f0bSmrg m32c_function_arg (cumulative_args_t ca_v, const function_arg_info &arg)
132236ac495dSmrg {
132336ac495dSmrg CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
132436ac495dSmrg
132536ac495dSmrg /* Can return a reg, parallel, or 0 for stack */
132636ac495dSmrg rtx rv = NULL_RTX;
132736ac495dSmrg #if DEBUG0
132836ac495dSmrg fprintf (stderr, "func_arg %d (%s, %d)\n",
1329*8feb0f0bSmrg ca->parm_num, mode_name[arg.mode], arg.named);
1330*8feb0f0bSmrg debug_tree (arg.type);
133136ac495dSmrg #endif
133236ac495dSmrg
1333*8feb0f0bSmrg if (arg.end_marker_p ())
133436ac495dSmrg return GEN_INT (0);
133536ac495dSmrg
1336*8feb0f0bSmrg if (ca->force_mem || !arg.named)
133736ac495dSmrg {
133836ac495dSmrg #if DEBUG0
133936ac495dSmrg fprintf (stderr, "func arg: force %d named %d, mem\n", ca->force_mem,
1340*8feb0f0bSmrg arg.named);
134136ac495dSmrg #endif
134236ac495dSmrg return NULL_RTX;
134336ac495dSmrg }
134436ac495dSmrg
1345*8feb0f0bSmrg if (arg.type && INTEGRAL_TYPE_P (arg.type) && POINTER_TYPE_P (arg.type))
134636ac495dSmrg return NULL_RTX;
134736ac495dSmrg
1348*8feb0f0bSmrg if (arg.aggregate_type_p ())
134936ac495dSmrg return NULL_RTX;
135036ac495dSmrg
135136ac495dSmrg switch (ca->parm_num)
135236ac495dSmrg {
135336ac495dSmrg case 1:
1354*8feb0f0bSmrg if (GET_MODE_SIZE (arg.mode) == 1 || GET_MODE_SIZE (arg.mode) == 2)
1355*8feb0f0bSmrg rv = gen_rtx_REG (arg.mode, TARGET_A16 ? R1_REGNO : R0_REGNO);
135636ac495dSmrg break;
135736ac495dSmrg
135836ac495dSmrg case 2:
1359*8feb0f0bSmrg if (TARGET_A16 && GET_MODE_SIZE (arg.mode) == 2)
1360*8feb0f0bSmrg rv = gen_rtx_REG (arg.mode, R2_REGNO);
136136ac495dSmrg break;
136236ac495dSmrg }
136336ac495dSmrg
136436ac495dSmrg #if DEBUG0
136536ac495dSmrg debug_rtx (rv);
136636ac495dSmrg #endif
136736ac495dSmrg return rv;
136836ac495dSmrg }
136936ac495dSmrg
137036ac495dSmrg #undef TARGET_PASS_BY_REFERENCE
137136ac495dSmrg #define TARGET_PASS_BY_REFERENCE m32c_pass_by_reference
137236ac495dSmrg static bool
m32c_pass_by_reference(cumulative_args_t,const function_arg_info &)1373*8feb0f0bSmrg m32c_pass_by_reference (cumulative_args_t, const function_arg_info &)
137436ac495dSmrg {
137536ac495dSmrg return 0;
137636ac495dSmrg }
137736ac495dSmrg
137836ac495dSmrg /* Implements INIT_CUMULATIVE_ARGS. */
137936ac495dSmrg void
m32c_init_cumulative_args(CUMULATIVE_ARGS * ca,tree fntype,rtx libname ATTRIBUTE_UNUSED,tree fndecl,int n_named_args ATTRIBUTE_UNUSED)138036ac495dSmrg m32c_init_cumulative_args (CUMULATIVE_ARGS * ca,
138136ac495dSmrg tree fntype,
138236ac495dSmrg rtx libname ATTRIBUTE_UNUSED,
138336ac495dSmrg tree fndecl,
138436ac495dSmrg int n_named_args ATTRIBUTE_UNUSED)
138536ac495dSmrg {
138636ac495dSmrg if (fntype && aggregate_value_p (TREE_TYPE (fntype), fndecl))
138736ac495dSmrg ca->force_mem = 1;
138836ac495dSmrg else
138936ac495dSmrg ca->force_mem = 0;
139036ac495dSmrg ca->parm_num = 1;
139136ac495dSmrg }
139236ac495dSmrg
139336ac495dSmrg /* Implements TARGET_FUNCTION_ARG_ADVANCE. force_mem is set for
139436ac495dSmrg functions returning structures, so we always reset that. Otherwise,
139536ac495dSmrg we only need to know the sequence number of the argument to know what
139636ac495dSmrg to do with it. */
139736ac495dSmrg #undef TARGET_FUNCTION_ARG_ADVANCE
139836ac495dSmrg #define TARGET_FUNCTION_ARG_ADVANCE m32c_function_arg_advance
139936ac495dSmrg static void
m32c_function_arg_advance(cumulative_args_t ca_v,const function_arg_info &)140036ac495dSmrg m32c_function_arg_advance (cumulative_args_t ca_v,
1401*8feb0f0bSmrg const function_arg_info &)
140236ac495dSmrg {
140336ac495dSmrg CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
140436ac495dSmrg
140536ac495dSmrg if (ca->force_mem)
140636ac495dSmrg ca->force_mem = 0;
140736ac495dSmrg else
140836ac495dSmrg ca->parm_num++;
140936ac495dSmrg }
141036ac495dSmrg
141136ac495dSmrg /* Implements TARGET_FUNCTION_ARG_BOUNDARY. */
141236ac495dSmrg #undef TARGET_FUNCTION_ARG_BOUNDARY
141336ac495dSmrg #define TARGET_FUNCTION_ARG_BOUNDARY m32c_function_arg_boundary
141436ac495dSmrg static unsigned int
m32c_function_arg_boundary(machine_mode mode ATTRIBUTE_UNUSED,const_tree type ATTRIBUTE_UNUSED)141536ac495dSmrg m32c_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
141636ac495dSmrg const_tree type ATTRIBUTE_UNUSED)
141736ac495dSmrg {
141836ac495dSmrg return (TARGET_A16 ? 8 : 16);
141936ac495dSmrg }
142036ac495dSmrg
142136ac495dSmrg /* Implements FUNCTION_ARG_REGNO_P. */
142236ac495dSmrg int
m32c_function_arg_regno_p(int r)142336ac495dSmrg m32c_function_arg_regno_p (int r)
142436ac495dSmrg {
142536ac495dSmrg if (TARGET_A24)
142636ac495dSmrg return (r == R0_REGNO);
142736ac495dSmrg return (r == R1_REGNO || r == R2_REGNO);
142836ac495dSmrg }
142936ac495dSmrg
143036ac495dSmrg /* HImode and PSImode are the two "native" modes as far as GCC is
143136ac495dSmrg concerned, but the chips also support a 32-bit mode which is used
143236ac495dSmrg for some opcodes in R8C/M16C and for reset vectors and such. */
143336ac495dSmrg #undef TARGET_VALID_POINTER_MODE
143436ac495dSmrg #define TARGET_VALID_POINTER_MODE m32c_valid_pointer_mode
143536ac495dSmrg static bool
m32c_valid_pointer_mode(scalar_int_mode mode)1436a2dc1f3fSmrg m32c_valid_pointer_mode (scalar_int_mode mode)
143736ac495dSmrg {
143836ac495dSmrg if (mode == HImode
143936ac495dSmrg || mode == PSImode
144036ac495dSmrg || mode == SImode
144136ac495dSmrg )
144236ac495dSmrg return 1;
144336ac495dSmrg return 0;
144436ac495dSmrg }
144536ac495dSmrg
144636ac495dSmrg /* How Scalar Function Values Are Returned */
144736ac495dSmrg
144836ac495dSmrg /* Implements TARGET_LIBCALL_VALUE. Most values are returned in $r0, or some
144936ac495dSmrg combination of registers starting there (r2r0 for longs, r3r1r2r0
145036ac495dSmrg for long long, r3r2r1r0 for doubles), except that that ABI
145136ac495dSmrg currently doesn't work because it ends up using all available
145236ac495dSmrg general registers and gcc often can't compile it. So, instead, we
145336ac495dSmrg return anything bigger than 16 bits in "mem0" (effectively, a
145436ac495dSmrg memory location). */
145536ac495dSmrg
145636ac495dSmrg #undef TARGET_LIBCALL_VALUE
145736ac495dSmrg #define TARGET_LIBCALL_VALUE m32c_libcall_value
145836ac495dSmrg
145936ac495dSmrg static rtx
m32c_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)146036ac495dSmrg m32c_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
146136ac495dSmrg {
146236ac495dSmrg /* return reg or parallel */
146336ac495dSmrg #if 0
146436ac495dSmrg /* FIXME: GCC has difficulty returning large values in registers,
146536ac495dSmrg because that ties up most of the general registers and gives the
146636ac495dSmrg register allocator little to work with. Until we can resolve
146736ac495dSmrg this, large values are returned in memory. */
146836ac495dSmrg if (mode == DFmode)
146936ac495dSmrg {
147036ac495dSmrg rtx rv;
147136ac495dSmrg
147236ac495dSmrg rv = gen_rtx_PARALLEL (mode, rtvec_alloc (4));
147336ac495dSmrg XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
147436ac495dSmrg gen_rtx_REG (HImode,
147536ac495dSmrg R0_REGNO),
147636ac495dSmrg GEN_INT (0));
147736ac495dSmrg XVECEXP (rv, 0, 1) = gen_rtx_EXPR_LIST (VOIDmode,
147836ac495dSmrg gen_rtx_REG (HImode,
147936ac495dSmrg R1_REGNO),
148036ac495dSmrg GEN_INT (2));
148136ac495dSmrg XVECEXP (rv, 0, 2) = gen_rtx_EXPR_LIST (VOIDmode,
148236ac495dSmrg gen_rtx_REG (HImode,
148336ac495dSmrg R2_REGNO),
148436ac495dSmrg GEN_INT (4));
148536ac495dSmrg XVECEXP (rv, 0, 3) = gen_rtx_EXPR_LIST (VOIDmode,
148636ac495dSmrg gen_rtx_REG (HImode,
148736ac495dSmrg R3_REGNO),
148836ac495dSmrg GEN_INT (6));
148936ac495dSmrg return rv;
149036ac495dSmrg }
149136ac495dSmrg
149236ac495dSmrg if (TARGET_A24 && GET_MODE_SIZE (mode) > 2)
149336ac495dSmrg {
149436ac495dSmrg rtx rv;
149536ac495dSmrg
149636ac495dSmrg rv = gen_rtx_PARALLEL (mode, rtvec_alloc (1));
149736ac495dSmrg XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
149836ac495dSmrg gen_rtx_REG (mode,
149936ac495dSmrg R0_REGNO),
150036ac495dSmrg GEN_INT (0));
150136ac495dSmrg return rv;
150236ac495dSmrg }
150336ac495dSmrg #endif
150436ac495dSmrg
150536ac495dSmrg if (GET_MODE_SIZE (mode) > 2)
150636ac495dSmrg return gen_rtx_REG (mode, MEM0_REGNO);
150736ac495dSmrg return gen_rtx_REG (mode, R0_REGNO);
150836ac495dSmrg }
150936ac495dSmrg
151036ac495dSmrg /* Implements TARGET_FUNCTION_VALUE. Functions and libcalls have the same
151136ac495dSmrg conventions. */
151236ac495dSmrg
151336ac495dSmrg #undef TARGET_FUNCTION_VALUE
151436ac495dSmrg #define TARGET_FUNCTION_VALUE m32c_function_value
151536ac495dSmrg
151636ac495dSmrg static rtx
m32c_function_value(const_tree valtype,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)151736ac495dSmrg m32c_function_value (const_tree valtype,
151836ac495dSmrg const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
151936ac495dSmrg bool outgoing ATTRIBUTE_UNUSED)
152036ac495dSmrg {
152136ac495dSmrg /* return reg or parallel */
152236ac495dSmrg const machine_mode mode = TYPE_MODE (valtype);
152336ac495dSmrg return m32c_libcall_value (mode, NULL_RTX);
152436ac495dSmrg }
152536ac495dSmrg
152636ac495dSmrg /* Implements TARGET_FUNCTION_VALUE_REGNO_P. */
152736ac495dSmrg
152836ac495dSmrg #undef TARGET_FUNCTION_VALUE_REGNO_P
152936ac495dSmrg #define TARGET_FUNCTION_VALUE_REGNO_P m32c_function_value_regno_p
153036ac495dSmrg
153136ac495dSmrg static bool
m32c_function_value_regno_p(const unsigned int regno)153236ac495dSmrg m32c_function_value_regno_p (const unsigned int regno)
153336ac495dSmrg {
153436ac495dSmrg return (regno == R0_REGNO || regno == MEM0_REGNO);
153536ac495dSmrg }
153636ac495dSmrg
153736ac495dSmrg /* How Large Values Are Returned */
153836ac495dSmrg
153936ac495dSmrg /* We return structures by pushing the address on the stack, even if
154036ac495dSmrg we use registers for the first few "real" arguments. */
154136ac495dSmrg #undef TARGET_STRUCT_VALUE_RTX
154236ac495dSmrg #define TARGET_STRUCT_VALUE_RTX m32c_struct_value_rtx
154336ac495dSmrg static rtx
m32c_struct_value_rtx(tree fndecl ATTRIBUTE_UNUSED,int incoming ATTRIBUTE_UNUSED)154436ac495dSmrg m32c_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
154536ac495dSmrg int incoming ATTRIBUTE_UNUSED)
154636ac495dSmrg {
154736ac495dSmrg return 0;
154836ac495dSmrg }
154936ac495dSmrg
155036ac495dSmrg /* Function Entry and Exit */
155136ac495dSmrg
155236ac495dSmrg /* Implements EPILOGUE_USES. Interrupts restore all registers. */
155336ac495dSmrg int
m32c_epilogue_uses(int regno ATTRIBUTE_UNUSED)155436ac495dSmrg m32c_epilogue_uses (int regno ATTRIBUTE_UNUSED)
155536ac495dSmrg {
155636ac495dSmrg if (cfun->machine->is_interrupt)
155736ac495dSmrg return 1;
155836ac495dSmrg return 0;
155936ac495dSmrg }
156036ac495dSmrg
156136ac495dSmrg /* Implementing the Varargs Macros */
156236ac495dSmrg
156336ac495dSmrg #undef TARGET_STRICT_ARGUMENT_NAMING
156436ac495dSmrg #define TARGET_STRICT_ARGUMENT_NAMING m32c_strict_argument_naming
156536ac495dSmrg static bool
m32c_strict_argument_naming(cumulative_args_t ca ATTRIBUTE_UNUSED)156636ac495dSmrg m32c_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
156736ac495dSmrg {
156836ac495dSmrg return 1;
156936ac495dSmrg }
157036ac495dSmrg
157136ac495dSmrg /* Trampolines for Nested Functions */
157236ac495dSmrg
157336ac495dSmrg /*
157436ac495dSmrg m16c:
157536ac495dSmrg 1 0000 75C43412 mov.w #0x1234,a0
157636ac495dSmrg 2 0004 FC000000 jmp.a label
157736ac495dSmrg
157836ac495dSmrg m32c:
157936ac495dSmrg 1 0000 BC563412 mov.l:s #0x123456,a0
158036ac495dSmrg 2 0004 CC000000 jmp.a label
158136ac495dSmrg */
158236ac495dSmrg
158336ac495dSmrg /* Implements TRAMPOLINE_SIZE. */
158436ac495dSmrg int
m32c_trampoline_size(void)158536ac495dSmrg m32c_trampoline_size (void)
158636ac495dSmrg {
158736ac495dSmrg /* Allocate extra space so we can avoid the messy shifts when we
158836ac495dSmrg initialize the trampoline; we just write past the end of the
158936ac495dSmrg opcode. */
159036ac495dSmrg return TARGET_A16 ? 8 : 10;
159136ac495dSmrg }
159236ac495dSmrg
159336ac495dSmrg /* Implements TRAMPOLINE_ALIGNMENT. */
159436ac495dSmrg int
m32c_trampoline_alignment(void)159536ac495dSmrg m32c_trampoline_alignment (void)
159636ac495dSmrg {
159736ac495dSmrg return 2;
159836ac495dSmrg }
159936ac495dSmrg
160036ac495dSmrg /* Implements TARGET_TRAMPOLINE_INIT. */
160136ac495dSmrg
160236ac495dSmrg #undef TARGET_TRAMPOLINE_INIT
160336ac495dSmrg #define TARGET_TRAMPOLINE_INIT m32c_trampoline_init
160436ac495dSmrg static void
m32c_trampoline_init(rtx m_tramp,tree fndecl,rtx chainval)160536ac495dSmrg m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
160636ac495dSmrg {
160736ac495dSmrg rtx function = XEXP (DECL_RTL (fndecl), 0);
160836ac495dSmrg
160936ac495dSmrg #define A0(m,i) adjust_address (m_tramp, m, i)
161036ac495dSmrg if (TARGET_A16)
161136ac495dSmrg {
161236ac495dSmrg /* Note: we subtract a "word" because the moves want signed
161336ac495dSmrg constants, not unsigned constants. */
161436ac495dSmrg emit_move_insn (A0 (HImode, 0), GEN_INT (0xc475 - 0x10000));
161536ac495dSmrg emit_move_insn (A0 (HImode, 2), chainval);
161636ac495dSmrg emit_move_insn (A0 (QImode, 4), GEN_INT (0xfc - 0x100));
161736ac495dSmrg /* We use 16-bit addresses here, but store the zero to turn it
161836ac495dSmrg into a 24-bit offset. */
161936ac495dSmrg emit_move_insn (A0 (HImode, 5), function);
162036ac495dSmrg emit_move_insn (A0 (QImode, 7), GEN_INT (0x00));
162136ac495dSmrg }
162236ac495dSmrg else
162336ac495dSmrg {
162436ac495dSmrg /* Note that the PSI moves actually write 4 bytes. Make sure we
162536ac495dSmrg write stuff out in the right order, and leave room for the
162636ac495dSmrg extra byte at the end. */
162736ac495dSmrg emit_move_insn (A0 (QImode, 0), GEN_INT (0xbc - 0x100));
162836ac495dSmrg emit_move_insn (A0 (PSImode, 1), chainval);
162936ac495dSmrg emit_move_insn (A0 (QImode, 4), GEN_INT (0xcc - 0x100));
163036ac495dSmrg emit_move_insn (A0 (PSImode, 5), function);
163136ac495dSmrg }
163236ac495dSmrg #undef A0
163336ac495dSmrg }
163436ac495dSmrg
163536ac495dSmrg #undef TARGET_LRA_P
163636ac495dSmrg #define TARGET_LRA_P hook_bool_void_false
163736ac495dSmrg
163836ac495dSmrg /* Addressing Modes */
163936ac495dSmrg
164036ac495dSmrg /* The r8c/m32c family supports a wide range of non-orthogonal
164136ac495dSmrg addressing modes, including the ability to double-indirect on *some*
164236ac495dSmrg of them. Not all insns support all modes, either, but we rely on
164336ac495dSmrg predicates and constraints to deal with that. */
164436ac495dSmrg #undef TARGET_LEGITIMATE_ADDRESS_P
164536ac495dSmrg #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
164636ac495dSmrg bool
m32c_legitimate_address_p(machine_mode mode,rtx x,bool strict)164736ac495dSmrg m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
164836ac495dSmrg {
164936ac495dSmrg int mode_adjust;
165036ac495dSmrg if (CONSTANT_P (x))
165136ac495dSmrg return 1;
165236ac495dSmrg
165336ac495dSmrg if (TARGET_A16 && GET_MODE (x) != HImode && GET_MODE (x) != SImode)
165436ac495dSmrg return 0;
165536ac495dSmrg if (TARGET_A24 && GET_MODE (x) != PSImode)
165636ac495dSmrg return 0;
165736ac495dSmrg
165836ac495dSmrg /* Wide references to memory will be split after reload, so we must
165936ac495dSmrg ensure that all parts of such splits remain legitimate
166036ac495dSmrg addresses. */
166136ac495dSmrg mode_adjust = GET_MODE_SIZE (mode) - 1;
166236ac495dSmrg
166336ac495dSmrg /* allowing PLUS yields mem:HI(plus:SI(mem:SI(plus:SI in m32c_split_move */
166436ac495dSmrg if (GET_CODE (x) == PRE_DEC
166536ac495dSmrg || GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_MODIFY)
166636ac495dSmrg {
166736ac495dSmrg return (GET_CODE (XEXP (x, 0)) == REG
166836ac495dSmrg && REGNO (XEXP (x, 0)) == SP_REGNO);
166936ac495dSmrg }
167036ac495dSmrg
167136ac495dSmrg #if 0
167236ac495dSmrg /* This is the double indirection detection, but it currently
167336ac495dSmrg doesn't work as cleanly as this code implies, so until we've had
167436ac495dSmrg a chance to debug it, leave it disabled. */
167536ac495dSmrg if (TARGET_A24 && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) != PLUS)
167636ac495dSmrg {
167736ac495dSmrg #if DEBUG_DOUBLE
167836ac495dSmrg fprintf (stderr, "double indirect\n");
167936ac495dSmrg #endif
168036ac495dSmrg x = XEXP (x, 0);
168136ac495dSmrg }
168236ac495dSmrg #endif
168336ac495dSmrg
168436ac495dSmrg encode_pattern (x);
168536ac495dSmrg if (RTX_IS ("r"))
168636ac495dSmrg {
168736ac495dSmrg /* Most indexable registers can be used without displacements,
168836ac495dSmrg although some of them will be emitted with an explicit zero
168936ac495dSmrg to please the assembler. */
169036ac495dSmrg switch (REGNO (patternr[0]))
169136ac495dSmrg {
169236ac495dSmrg case A1_REGNO:
169336ac495dSmrg case SB_REGNO:
169436ac495dSmrg case FB_REGNO:
169536ac495dSmrg case SP_REGNO:
169636ac495dSmrg if (TARGET_A16 && GET_MODE (x) == SImode)
169736ac495dSmrg return 0;
169836ac495dSmrg /* FALLTHRU */
169936ac495dSmrg case A0_REGNO:
170036ac495dSmrg return 1;
170136ac495dSmrg
170236ac495dSmrg default:
170336ac495dSmrg if (IS_PSEUDO (patternr[0], strict))
170436ac495dSmrg return 1;
170536ac495dSmrg return 0;
170636ac495dSmrg }
170736ac495dSmrg }
170836ac495dSmrg
170936ac495dSmrg if (TARGET_A16 && GET_MODE (x) == SImode)
171036ac495dSmrg return 0;
171136ac495dSmrg
171236ac495dSmrg if (RTX_IS ("+ri"))
171336ac495dSmrg {
171436ac495dSmrg /* This is more interesting, because different base registers
171536ac495dSmrg allow for different displacements - both range and signedness
171636ac495dSmrg - and it differs from chip series to chip series too. */
171736ac495dSmrg int rn = REGNO (patternr[1]);
171836ac495dSmrg HOST_WIDE_INT offs = INTVAL (patternr[2]);
171936ac495dSmrg switch (rn)
172036ac495dSmrg {
172136ac495dSmrg case A0_REGNO:
172236ac495dSmrg case A1_REGNO:
172336ac495dSmrg case SB_REGNO:
172436ac495dSmrg /* The syntax only allows positive offsets, but when the
172536ac495dSmrg offsets span the entire memory range, we can simulate
172636ac495dSmrg negative offsets by wrapping. */
172736ac495dSmrg if (TARGET_A16)
172836ac495dSmrg return (offs >= -65536 && offs <= 65535 - mode_adjust);
172936ac495dSmrg if (rn == SB_REGNO)
173036ac495dSmrg return (offs >= 0 && offs <= 65535 - mode_adjust);
173136ac495dSmrg /* A0 or A1 */
173236ac495dSmrg return (offs >= -16777216 && offs <= 16777215);
173336ac495dSmrg
173436ac495dSmrg case FB_REGNO:
173536ac495dSmrg if (TARGET_A16)
173636ac495dSmrg return (offs >= -128 && offs <= 127 - mode_adjust);
173736ac495dSmrg return (offs >= -65536 && offs <= 65535 - mode_adjust);
173836ac495dSmrg
173936ac495dSmrg case SP_REGNO:
174036ac495dSmrg return (offs >= -128 && offs <= 127 - mode_adjust);
174136ac495dSmrg
174236ac495dSmrg default:
174336ac495dSmrg if (IS_PSEUDO (patternr[1], strict))
174436ac495dSmrg return 1;
174536ac495dSmrg return 0;
174636ac495dSmrg }
174736ac495dSmrg }
174836ac495dSmrg if (RTX_IS ("+rs") || RTX_IS ("+r+si"))
174936ac495dSmrg {
175036ac495dSmrg rtx reg = patternr[1];
175136ac495dSmrg
175236ac495dSmrg /* We don't know where the symbol is, so only allow base
175336ac495dSmrg registers which support displacements spanning the whole
175436ac495dSmrg address range. */
175536ac495dSmrg switch (REGNO (reg))
175636ac495dSmrg {
175736ac495dSmrg case A0_REGNO:
175836ac495dSmrg case A1_REGNO:
175936ac495dSmrg /* $sb needs a secondary reload, but since it's involved in
176036ac495dSmrg memory address reloads too, we don't deal with it very
176136ac495dSmrg well. */
176236ac495dSmrg /* case SB_REGNO: */
176336ac495dSmrg return 1;
176436ac495dSmrg default:
176536ac495dSmrg if (GET_CODE (reg) == SUBREG)
176636ac495dSmrg return 0;
176736ac495dSmrg if (IS_PSEUDO (reg, strict))
176836ac495dSmrg return 1;
176936ac495dSmrg return 0;
177036ac495dSmrg }
177136ac495dSmrg }
177236ac495dSmrg return 0;
177336ac495dSmrg }
177436ac495dSmrg
177536ac495dSmrg /* Implements REG_OK_FOR_BASE_P. */
177636ac495dSmrg int
m32c_reg_ok_for_base_p(rtx x,int strict)177736ac495dSmrg m32c_reg_ok_for_base_p (rtx x, int strict)
177836ac495dSmrg {
177936ac495dSmrg if (GET_CODE (x) != REG)
178036ac495dSmrg return 0;
178136ac495dSmrg switch (REGNO (x))
178236ac495dSmrg {
178336ac495dSmrg case A0_REGNO:
178436ac495dSmrg case A1_REGNO:
178536ac495dSmrg case SB_REGNO:
178636ac495dSmrg case FB_REGNO:
178736ac495dSmrg case SP_REGNO:
178836ac495dSmrg return 1;
178936ac495dSmrg default:
179036ac495dSmrg if (IS_PSEUDO (x, strict))
179136ac495dSmrg return 1;
179236ac495dSmrg return 0;
179336ac495dSmrg }
179436ac495dSmrg }
179536ac495dSmrg
179636ac495dSmrg /* We have three choices for choosing fb->aN offsets. If we choose -128,
179736ac495dSmrg we need one MOVA -128[fb],aN opcode and 16-bit aN displacements,
179836ac495dSmrg like this:
179936ac495dSmrg EB 4B FF mova -128[$fb],$a0
180036ac495dSmrg D8 0C FF FF mov.w:Q #0,-1[$a0]
180136ac495dSmrg
180236ac495dSmrg Alternately, we subtract the frame size, and hopefully use 8-bit aN
180336ac495dSmrg displacements:
180436ac495dSmrg 7B F4 stc $fb,$a0
180536ac495dSmrg 77 54 00 01 sub #256,$a0
180636ac495dSmrg D8 08 01 mov.w:Q #0,1[$a0]
180736ac495dSmrg
180836ac495dSmrg If we don't offset (i.e. offset by zero), we end up with:
180936ac495dSmrg 7B F4 stc $fb,$a0
181036ac495dSmrg D8 0C 00 FF mov.w:Q #0,-256[$a0]
181136ac495dSmrg
181236ac495dSmrg We have to subtract *something* so that we have a PLUS rtx to mark
181336ac495dSmrg that we've done this reload. The -128 offset will never result in
181436ac495dSmrg an 8-bit aN offset, and the payoff for the second case is five
181536ac495dSmrg loads *if* those loads are within 256 bytes of the other end of the
181636ac495dSmrg frame, so the third case seems best. Note that we subtract the
181736ac495dSmrg zero, but detect that in the addhi3 pattern. */
181836ac495dSmrg
181936ac495dSmrg #define BIG_FB_ADJ 0
182036ac495dSmrg
182136ac495dSmrg /* Implements LEGITIMIZE_ADDRESS. The only address we really have to
182236ac495dSmrg worry about is frame base offsets, as $fb has a limited
182336ac495dSmrg displacement range. We deal with this by attempting to reload $fb
182436ac495dSmrg itself into an address register; that seems to result in the best
182536ac495dSmrg code. */
182636ac495dSmrg #undef TARGET_LEGITIMIZE_ADDRESS
182736ac495dSmrg #define TARGET_LEGITIMIZE_ADDRESS m32c_legitimize_address
182836ac495dSmrg static rtx
m32c_legitimize_address(rtx x,rtx oldx ATTRIBUTE_UNUSED,machine_mode mode)182936ac495dSmrg m32c_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
183036ac495dSmrg machine_mode mode)
183136ac495dSmrg {
183236ac495dSmrg #if DEBUG0
183336ac495dSmrg fprintf (stderr, "m32c_legitimize_address for mode %s\n", mode_name[mode]);
183436ac495dSmrg debug_rtx (x);
183536ac495dSmrg fprintf (stderr, "\n");
183636ac495dSmrg #endif
183736ac495dSmrg
183836ac495dSmrg if (GET_CODE (x) == PLUS
183936ac495dSmrg && GET_CODE (XEXP (x, 0)) == REG
184036ac495dSmrg && REGNO (XEXP (x, 0)) == FB_REGNO
184136ac495dSmrg && GET_CODE (XEXP (x, 1)) == CONST_INT
184236ac495dSmrg && (INTVAL (XEXP (x, 1)) < -128
184336ac495dSmrg || INTVAL (XEXP (x, 1)) > (128 - GET_MODE_SIZE (mode))))
184436ac495dSmrg {
184536ac495dSmrg /* reload FB to A_REGS */
184636ac495dSmrg rtx temp = gen_reg_rtx (Pmode);
184736ac495dSmrg x = copy_rtx (x);
184836ac495dSmrg emit_insn (gen_rtx_SET (temp, XEXP (x, 0)));
184936ac495dSmrg XEXP (x, 0) = temp;
185036ac495dSmrg }
185136ac495dSmrg
185236ac495dSmrg return x;
185336ac495dSmrg }
185436ac495dSmrg
185536ac495dSmrg /* Implements LEGITIMIZE_RELOAD_ADDRESS. See comment above. */
185636ac495dSmrg int
m32c_legitimize_reload_address(rtx * x,machine_mode mode,int opnum,int type,int ind_levels ATTRIBUTE_UNUSED)185736ac495dSmrg m32c_legitimize_reload_address (rtx * x,
185836ac495dSmrg machine_mode mode,
185936ac495dSmrg int opnum,
186036ac495dSmrg int type, int ind_levels ATTRIBUTE_UNUSED)
186136ac495dSmrg {
186236ac495dSmrg #if DEBUG0
186336ac495dSmrg fprintf (stderr, "\nm32c_legitimize_reload_address for mode %s\n",
186436ac495dSmrg mode_name[mode]);
186536ac495dSmrg debug_rtx (*x);
186636ac495dSmrg #endif
186736ac495dSmrg
186836ac495dSmrg /* At one point, this function tried to get $fb copied to an address
186936ac495dSmrg register, which in theory would maximize sharing, but gcc was
187036ac495dSmrg *also* still trying to reload the whole address, and we'd run out
187136ac495dSmrg of address registers. So we let gcc do the naive (but safe)
187236ac495dSmrg reload instead, when the above function doesn't handle it for
187336ac495dSmrg us.
187436ac495dSmrg
187536ac495dSmrg The code below is a second attempt at the above. */
187636ac495dSmrg
187736ac495dSmrg if (GET_CODE (*x) == PLUS
187836ac495dSmrg && GET_CODE (XEXP (*x, 0)) == REG
187936ac495dSmrg && REGNO (XEXP (*x, 0)) == FB_REGNO
188036ac495dSmrg && GET_CODE (XEXP (*x, 1)) == CONST_INT
188136ac495dSmrg && (INTVAL (XEXP (*x, 1)) < -128
188236ac495dSmrg || INTVAL (XEXP (*x, 1)) > (128 - GET_MODE_SIZE (mode))))
188336ac495dSmrg {
188436ac495dSmrg rtx sum;
188536ac495dSmrg int offset = INTVAL (XEXP (*x, 1));
188636ac495dSmrg int adjustment = -BIG_FB_ADJ;
188736ac495dSmrg
188836ac495dSmrg sum = gen_rtx_PLUS (Pmode, XEXP (*x, 0),
188936ac495dSmrg GEN_INT (adjustment));
189036ac495dSmrg *x = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - adjustment));
189136ac495dSmrg if (type == RELOAD_OTHER)
189236ac495dSmrg type = RELOAD_FOR_OTHER_ADDRESS;
189336ac495dSmrg push_reload (sum, NULL_RTX, &XEXP (*x, 0), NULL,
189436ac495dSmrg A_REGS, Pmode, VOIDmode, 0, 0, opnum,
189536ac495dSmrg (enum reload_type) type);
189636ac495dSmrg return 1;
189736ac495dSmrg }
189836ac495dSmrg
189936ac495dSmrg if (GET_CODE (*x) == PLUS
190036ac495dSmrg && GET_CODE (XEXP (*x, 0)) == PLUS
190136ac495dSmrg && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG
190236ac495dSmrg && REGNO (XEXP (XEXP (*x, 0), 0)) == FB_REGNO
190336ac495dSmrg && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT
190436ac495dSmrg && GET_CODE (XEXP (*x, 1)) == CONST_INT
190536ac495dSmrg )
190636ac495dSmrg {
190736ac495dSmrg if (type == RELOAD_OTHER)
190836ac495dSmrg type = RELOAD_FOR_OTHER_ADDRESS;
190936ac495dSmrg push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
191036ac495dSmrg A_REGS, Pmode, VOIDmode, 0, 0, opnum,
191136ac495dSmrg (enum reload_type) type);
191236ac495dSmrg return 1;
191336ac495dSmrg }
191436ac495dSmrg
191536ac495dSmrg if (TARGET_A24 && GET_MODE (*x) == PSImode)
191636ac495dSmrg {
191736ac495dSmrg push_reload (*x, NULL_RTX, x, NULL,
191836ac495dSmrg A_REGS, PSImode, VOIDmode, 0, 0, opnum,
191936ac495dSmrg (enum reload_type) type);
192036ac495dSmrg return 1;
192136ac495dSmrg }
192236ac495dSmrg
192336ac495dSmrg return 0;
192436ac495dSmrg }
192536ac495dSmrg
192636ac495dSmrg /* Return the appropriate mode for a named address pointer. */
192736ac495dSmrg #undef TARGET_ADDR_SPACE_POINTER_MODE
192836ac495dSmrg #define TARGET_ADDR_SPACE_POINTER_MODE m32c_addr_space_pointer_mode
1929a2dc1f3fSmrg static scalar_int_mode
m32c_addr_space_pointer_mode(addr_space_t addrspace)193036ac495dSmrg m32c_addr_space_pointer_mode (addr_space_t addrspace)
193136ac495dSmrg {
193236ac495dSmrg switch (addrspace)
193336ac495dSmrg {
193436ac495dSmrg case ADDR_SPACE_GENERIC:
193536ac495dSmrg return TARGET_A24 ? PSImode : HImode;
193636ac495dSmrg case ADDR_SPACE_FAR:
193736ac495dSmrg return SImode;
193836ac495dSmrg default:
193936ac495dSmrg gcc_unreachable ();
194036ac495dSmrg }
194136ac495dSmrg }
194236ac495dSmrg
194336ac495dSmrg /* Return the appropriate mode for a named address address. */
194436ac495dSmrg #undef TARGET_ADDR_SPACE_ADDRESS_MODE
194536ac495dSmrg #define TARGET_ADDR_SPACE_ADDRESS_MODE m32c_addr_space_address_mode
1946a2dc1f3fSmrg static scalar_int_mode
m32c_addr_space_address_mode(addr_space_t addrspace)194736ac495dSmrg m32c_addr_space_address_mode (addr_space_t addrspace)
194836ac495dSmrg {
194936ac495dSmrg switch (addrspace)
195036ac495dSmrg {
195136ac495dSmrg case ADDR_SPACE_GENERIC:
195236ac495dSmrg return TARGET_A24 ? PSImode : HImode;
195336ac495dSmrg case ADDR_SPACE_FAR:
195436ac495dSmrg return SImode;
195536ac495dSmrg default:
195636ac495dSmrg gcc_unreachable ();
195736ac495dSmrg }
195836ac495dSmrg }
195936ac495dSmrg
196036ac495dSmrg /* Like m32c_legitimate_address_p, except with named addresses. */
196136ac495dSmrg #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
196236ac495dSmrg #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
196336ac495dSmrg m32c_addr_space_legitimate_address_p
196436ac495dSmrg static bool
m32c_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)196536ac495dSmrg m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
196636ac495dSmrg bool strict, addr_space_t as)
196736ac495dSmrg {
196836ac495dSmrg if (as == ADDR_SPACE_FAR)
196936ac495dSmrg {
197036ac495dSmrg if (TARGET_A24)
197136ac495dSmrg return 0;
197236ac495dSmrg encode_pattern (x);
197336ac495dSmrg if (RTX_IS ("r"))
197436ac495dSmrg {
197536ac495dSmrg if (GET_MODE (x) != SImode)
197636ac495dSmrg return 0;
197736ac495dSmrg switch (REGNO (patternr[0]))
197836ac495dSmrg {
197936ac495dSmrg case A0_REGNO:
198036ac495dSmrg return 1;
198136ac495dSmrg
198236ac495dSmrg default:
198336ac495dSmrg if (IS_PSEUDO (patternr[0], strict))
198436ac495dSmrg return 1;
198536ac495dSmrg return 0;
198636ac495dSmrg }
198736ac495dSmrg }
198836ac495dSmrg if (RTX_IS ("+^Sri"))
198936ac495dSmrg {
199036ac495dSmrg int rn = REGNO (patternr[3]);
199136ac495dSmrg HOST_WIDE_INT offs = INTVAL (patternr[4]);
199236ac495dSmrg if (GET_MODE (patternr[3]) != HImode)
199336ac495dSmrg return 0;
199436ac495dSmrg switch (rn)
199536ac495dSmrg {
199636ac495dSmrg case A0_REGNO:
199736ac495dSmrg return (offs >= 0 && offs <= 0xfffff);
199836ac495dSmrg
199936ac495dSmrg default:
200036ac495dSmrg if (IS_PSEUDO (patternr[3], strict))
200136ac495dSmrg return 1;
200236ac495dSmrg return 0;
200336ac495dSmrg }
200436ac495dSmrg }
200536ac495dSmrg if (RTX_IS ("+^Srs"))
200636ac495dSmrg {
200736ac495dSmrg int rn = REGNO (patternr[3]);
200836ac495dSmrg if (GET_MODE (patternr[3]) != HImode)
200936ac495dSmrg return 0;
201036ac495dSmrg switch (rn)
201136ac495dSmrg {
201236ac495dSmrg case A0_REGNO:
201336ac495dSmrg return 1;
201436ac495dSmrg
201536ac495dSmrg default:
201636ac495dSmrg if (IS_PSEUDO (patternr[3], strict))
201736ac495dSmrg return 1;
201836ac495dSmrg return 0;
201936ac495dSmrg }
202036ac495dSmrg }
202136ac495dSmrg if (RTX_IS ("+^S+ris"))
202236ac495dSmrg {
202336ac495dSmrg int rn = REGNO (patternr[4]);
202436ac495dSmrg if (GET_MODE (patternr[4]) != HImode)
202536ac495dSmrg return 0;
202636ac495dSmrg switch (rn)
202736ac495dSmrg {
202836ac495dSmrg case A0_REGNO:
202936ac495dSmrg return 1;
203036ac495dSmrg
203136ac495dSmrg default:
203236ac495dSmrg if (IS_PSEUDO (patternr[4], strict))
203336ac495dSmrg return 1;
203436ac495dSmrg return 0;
203536ac495dSmrg }
203636ac495dSmrg }
203736ac495dSmrg if (RTX_IS ("s"))
203836ac495dSmrg {
203936ac495dSmrg return 1;
204036ac495dSmrg }
204136ac495dSmrg return 0;
204236ac495dSmrg }
204336ac495dSmrg
204436ac495dSmrg else if (as != ADDR_SPACE_GENERIC)
204536ac495dSmrg gcc_unreachable ();
204636ac495dSmrg
204736ac495dSmrg return m32c_legitimate_address_p (mode, x, strict);
204836ac495dSmrg }
204936ac495dSmrg
205036ac495dSmrg /* Like m32c_legitimate_address, except with named address support. */
205136ac495dSmrg #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
205236ac495dSmrg #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS m32c_addr_space_legitimize_address
205336ac495dSmrg static rtx
m32c_addr_space_legitimize_address(rtx x,rtx oldx,machine_mode mode,addr_space_t as)205436ac495dSmrg m32c_addr_space_legitimize_address (rtx x, rtx oldx, machine_mode mode,
205536ac495dSmrg addr_space_t as)
205636ac495dSmrg {
205736ac495dSmrg if (as != ADDR_SPACE_GENERIC)
205836ac495dSmrg {
205936ac495dSmrg #if DEBUG0
206036ac495dSmrg fprintf (stderr, "\033[36mm32c_addr_space_legitimize_address for mode %s\033[0m\n", mode_name[mode]);
206136ac495dSmrg debug_rtx (x);
206236ac495dSmrg fprintf (stderr, "\n");
206336ac495dSmrg #endif
206436ac495dSmrg
206536ac495dSmrg if (GET_CODE (x) != REG)
206636ac495dSmrg {
206736ac495dSmrg x = force_reg (SImode, x);
206836ac495dSmrg }
206936ac495dSmrg return x;
207036ac495dSmrg }
207136ac495dSmrg
207236ac495dSmrg return m32c_legitimize_address (x, oldx, mode);
207336ac495dSmrg }
207436ac495dSmrg
207536ac495dSmrg /* Determine if one named address space is a subset of another. */
207636ac495dSmrg #undef TARGET_ADDR_SPACE_SUBSET_P
207736ac495dSmrg #define TARGET_ADDR_SPACE_SUBSET_P m32c_addr_space_subset_p
207836ac495dSmrg static bool
m32c_addr_space_subset_p(addr_space_t subset,addr_space_t superset)207936ac495dSmrg m32c_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
208036ac495dSmrg {
208136ac495dSmrg gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
208236ac495dSmrg gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
208336ac495dSmrg
208436ac495dSmrg if (subset == superset)
208536ac495dSmrg return true;
208636ac495dSmrg
208736ac495dSmrg else
208836ac495dSmrg return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
208936ac495dSmrg }
209036ac495dSmrg
209136ac495dSmrg #undef TARGET_ADDR_SPACE_CONVERT
209236ac495dSmrg #define TARGET_ADDR_SPACE_CONVERT m32c_addr_space_convert
209336ac495dSmrg /* Convert from one address space to another. */
209436ac495dSmrg static rtx
m32c_addr_space_convert(rtx op,tree from_type,tree to_type)209536ac495dSmrg m32c_addr_space_convert (rtx op, tree from_type, tree to_type)
209636ac495dSmrg {
209736ac495dSmrg addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
209836ac495dSmrg addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
209936ac495dSmrg rtx result;
210036ac495dSmrg
210136ac495dSmrg gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
210236ac495dSmrg gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
210336ac495dSmrg
210436ac495dSmrg if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
210536ac495dSmrg {
210636ac495dSmrg /* This is unpredictable, as we're truncating off usable address
210736ac495dSmrg bits. */
210836ac495dSmrg
210936ac495dSmrg result = gen_reg_rtx (HImode);
211036ac495dSmrg emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
211136ac495dSmrg return result;
211236ac495dSmrg }
211336ac495dSmrg else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
211436ac495dSmrg {
211536ac495dSmrg /* This always works. */
211636ac495dSmrg result = gen_reg_rtx (SImode);
211736ac495dSmrg emit_insn (gen_zero_extendhisi2 (result, op));
211836ac495dSmrg return result;
211936ac495dSmrg }
212036ac495dSmrg else
212136ac495dSmrg gcc_unreachable ();
212236ac495dSmrg }
212336ac495dSmrg
212436ac495dSmrg /* Condition Code Status */
212536ac495dSmrg
212636ac495dSmrg #undef TARGET_FIXED_CONDITION_CODE_REGS
212736ac495dSmrg #define TARGET_FIXED_CONDITION_CODE_REGS m32c_fixed_condition_code_regs
212836ac495dSmrg static bool
m32c_fixed_condition_code_regs(unsigned int * p1,unsigned int * p2)212936ac495dSmrg m32c_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
213036ac495dSmrg {
213136ac495dSmrg *p1 = FLG_REGNO;
213236ac495dSmrg *p2 = INVALID_REGNUM;
213336ac495dSmrg return true;
213436ac495dSmrg }
213536ac495dSmrg
213636ac495dSmrg /* Describing Relative Costs of Operations */
213736ac495dSmrg
213836ac495dSmrg /* Implements TARGET_REGISTER_MOVE_COST. We make impossible moves
213936ac495dSmrg prohibitively expensive, like trying to put QIs in r2/r3 (there are
214036ac495dSmrg no opcodes to do that). We also discourage use of mem* registers
214136ac495dSmrg since they're really memory. */
214236ac495dSmrg
214336ac495dSmrg #undef TARGET_REGISTER_MOVE_COST
214436ac495dSmrg #define TARGET_REGISTER_MOVE_COST m32c_register_move_cost
214536ac495dSmrg
214636ac495dSmrg static int
m32c_register_move_cost(machine_mode mode,reg_class_t from,reg_class_t to)214736ac495dSmrg m32c_register_move_cost (machine_mode mode, reg_class_t from,
214836ac495dSmrg reg_class_t to)
214936ac495dSmrg {
215036ac495dSmrg int cost = COSTS_N_INSNS (3);
215136ac495dSmrg HARD_REG_SET cc;
215236ac495dSmrg
215336ac495dSmrg /* FIXME: pick real values, but not 2 for now. */
2154*8feb0f0bSmrg cc = reg_class_contents[from] | reg_class_contents[(int) to];
215536ac495dSmrg
215636ac495dSmrg if (mode == QImode
215736ac495dSmrg && hard_reg_set_intersect_p (cc, reg_class_contents[R23_REGS]))
215836ac495dSmrg {
215936ac495dSmrg if (hard_reg_set_subset_p (cc, reg_class_contents[R23_REGS]))
216036ac495dSmrg cost = COSTS_N_INSNS (1000);
216136ac495dSmrg else
216236ac495dSmrg cost = COSTS_N_INSNS (80);
216336ac495dSmrg }
216436ac495dSmrg
216536ac495dSmrg if (!class_can_hold_mode (from, mode) || !class_can_hold_mode (to, mode))
216636ac495dSmrg cost = COSTS_N_INSNS (1000);
216736ac495dSmrg
216836ac495dSmrg if (reg_classes_intersect_p (from, CR_REGS))
216936ac495dSmrg cost += COSTS_N_INSNS (5);
217036ac495dSmrg
217136ac495dSmrg if (reg_classes_intersect_p (to, CR_REGS))
217236ac495dSmrg cost += COSTS_N_INSNS (5);
217336ac495dSmrg
217436ac495dSmrg if (from == MEM_REGS || to == MEM_REGS)
217536ac495dSmrg cost += COSTS_N_INSNS (50);
217636ac495dSmrg else if (reg_classes_intersect_p (from, MEM_REGS)
217736ac495dSmrg || reg_classes_intersect_p (to, MEM_REGS))
217836ac495dSmrg cost += COSTS_N_INSNS (10);
217936ac495dSmrg
218036ac495dSmrg #if DEBUG0
218136ac495dSmrg fprintf (stderr, "register_move_cost %s from %s to %s = %d\n",
218236ac495dSmrg mode_name[mode], class_names[(int) from], class_names[(int) to],
218336ac495dSmrg cost);
218436ac495dSmrg #endif
218536ac495dSmrg return cost;
218636ac495dSmrg }
218736ac495dSmrg
218836ac495dSmrg /* Implements TARGET_MEMORY_MOVE_COST. */
218936ac495dSmrg
219036ac495dSmrg #undef TARGET_MEMORY_MOVE_COST
219136ac495dSmrg #define TARGET_MEMORY_MOVE_COST m32c_memory_move_cost
219236ac495dSmrg
219336ac495dSmrg static int
m32c_memory_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)219436ac495dSmrg m32c_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
219536ac495dSmrg reg_class_t rclass ATTRIBUTE_UNUSED,
219636ac495dSmrg bool in ATTRIBUTE_UNUSED)
219736ac495dSmrg {
219836ac495dSmrg /* FIXME: pick real values. */
219936ac495dSmrg return COSTS_N_INSNS (10);
220036ac495dSmrg }
220136ac495dSmrg
220236ac495dSmrg /* Here we try to describe when we use multiple opcodes for one RTX so
220336ac495dSmrg that gcc knows when to use them. */
220436ac495dSmrg #undef TARGET_RTX_COSTS
220536ac495dSmrg #define TARGET_RTX_COSTS m32c_rtx_costs
220636ac495dSmrg static bool
m32c_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed ATTRIBUTE_UNUSED)220736ac495dSmrg m32c_rtx_costs (rtx x, machine_mode mode, int outer_code,
220836ac495dSmrg int opno ATTRIBUTE_UNUSED,
220936ac495dSmrg int *total, bool speed ATTRIBUTE_UNUSED)
221036ac495dSmrg {
221136ac495dSmrg int code = GET_CODE (x);
221236ac495dSmrg switch (code)
221336ac495dSmrg {
221436ac495dSmrg case REG:
221536ac495dSmrg if (REGNO (x) >= MEM0_REGNO && REGNO (x) <= MEM7_REGNO)
221636ac495dSmrg *total += COSTS_N_INSNS (500);
221736ac495dSmrg else
221836ac495dSmrg *total += COSTS_N_INSNS (1);
221936ac495dSmrg return true;
222036ac495dSmrg
222136ac495dSmrg case ASHIFT:
222236ac495dSmrg case LSHIFTRT:
222336ac495dSmrg case ASHIFTRT:
222436ac495dSmrg if (GET_CODE (XEXP (x, 1)) != CONST_INT)
222536ac495dSmrg {
222636ac495dSmrg /* mov.b r1l, r1h */
222736ac495dSmrg *total += COSTS_N_INSNS (1);
222836ac495dSmrg return true;
222936ac495dSmrg }
223036ac495dSmrg if (INTVAL (XEXP (x, 1)) > 8
223136ac495dSmrg || INTVAL (XEXP (x, 1)) < -8)
223236ac495dSmrg {
223336ac495dSmrg /* mov.b #N, r1l */
223436ac495dSmrg /* mov.b r1l, r1h */
223536ac495dSmrg *total += COSTS_N_INSNS (2);
223636ac495dSmrg return true;
223736ac495dSmrg }
223836ac495dSmrg return true;
223936ac495dSmrg
224036ac495dSmrg case LE:
224136ac495dSmrg case LEU:
224236ac495dSmrg case LT:
224336ac495dSmrg case LTU:
224436ac495dSmrg case GT:
224536ac495dSmrg case GTU:
224636ac495dSmrg case GE:
224736ac495dSmrg case GEU:
224836ac495dSmrg case NE:
224936ac495dSmrg case EQ:
225036ac495dSmrg if (outer_code == SET)
225136ac495dSmrg {
225236ac495dSmrg *total += COSTS_N_INSNS (2);
225336ac495dSmrg return true;
225436ac495dSmrg }
225536ac495dSmrg break;
225636ac495dSmrg
225736ac495dSmrg case ZERO_EXTRACT:
225836ac495dSmrg {
225936ac495dSmrg rtx dest = XEXP (x, 0);
226036ac495dSmrg rtx addr = XEXP (dest, 0);
226136ac495dSmrg switch (GET_CODE (addr))
226236ac495dSmrg {
226336ac495dSmrg case CONST_INT:
226436ac495dSmrg *total += COSTS_N_INSNS (1);
226536ac495dSmrg break;
226636ac495dSmrg case SYMBOL_REF:
226736ac495dSmrg *total += COSTS_N_INSNS (3);
226836ac495dSmrg break;
226936ac495dSmrg default:
227036ac495dSmrg *total += COSTS_N_INSNS (2);
227136ac495dSmrg break;
227236ac495dSmrg }
227336ac495dSmrg return true;
227436ac495dSmrg }
227536ac495dSmrg break;
227636ac495dSmrg
227736ac495dSmrg default:
227836ac495dSmrg /* Reasonable default. */
227936ac495dSmrg if (TARGET_A16 && mode == SImode)
228036ac495dSmrg *total += COSTS_N_INSNS (2);
228136ac495dSmrg break;
228236ac495dSmrg }
228336ac495dSmrg return false;
228436ac495dSmrg }
228536ac495dSmrg
228636ac495dSmrg #undef TARGET_ADDRESS_COST
228736ac495dSmrg #define TARGET_ADDRESS_COST m32c_address_cost
228836ac495dSmrg static int
m32c_address_cost(rtx addr,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)228936ac495dSmrg m32c_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED,
229036ac495dSmrg addr_space_t as ATTRIBUTE_UNUSED,
229136ac495dSmrg bool speed ATTRIBUTE_UNUSED)
229236ac495dSmrg {
229336ac495dSmrg int i;
229436ac495dSmrg /* fprintf(stderr, "\naddress_cost\n");
229536ac495dSmrg debug_rtx(addr);*/
229636ac495dSmrg switch (GET_CODE (addr))
229736ac495dSmrg {
229836ac495dSmrg case CONST_INT:
229936ac495dSmrg i = INTVAL (addr);
230036ac495dSmrg if (i == 0)
230136ac495dSmrg return COSTS_N_INSNS(1);
2302a2dc1f3fSmrg if (i > 0 && i <= 255)
230336ac495dSmrg return COSTS_N_INSNS(2);
2304a2dc1f3fSmrg if (i > 0 && i <= 65535)
230536ac495dSmrg return COSTS_N_INSNS(3);
230636ac495dSmrg return COSTS_N_INSNS(4);
230736ac495dSmrg case SYMBOL_REF:
230836ac495dSmrg return COSTS_N_INSNS(4);
230936ac495dSmrg case REG:
231036ac495dSmrg return COSTS_N_INSNS(1);
231136ac495dSmrg case PLUS:
231236ac495dSmrg if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
231336ac495dSmrg {
231436ac495dSmrg i = INTVAL (XEXP (addr, 1));
231536ac495dSmrg if (i == 0)
231636ac495dSmrg return COSTS_N_INSNS(1);
2317a2dc1f3fSmrg if (i > 0 && i <= 255)
231836ac495dSmrg return COSTS_N_INSNS(2);
2319a2dc1f3fSmrg if (i > 0 && i <= 65535)
232036ac495dSmrg return COSTS_N_INSNS(3);
232136ac495dSmrg }
232236ac495dSmrg return COSTS_N_INSNS(4);
232336ac495dSmrg default:
232436ac495dSmrg return 0;
232536ac495dSmrg }
232636ac495dSmrg }
232736ac495dSmrg
232836ac495dSmrg /* Defining the Output Assembler Language */
232936ac495dSmrg
233036ac495dSmrg /* Output of Data */
233136ac495dSmrg
233236ac495dSmrg /* We may have 24 bit sizes, which is the native address size.
233336ac495dSmrg Currently unused, but provided for completeness. */
233436ac495dSmrg #undef TARGET_ASM_INTEGER
233536ac495dSmrg #define TARGET_ASM_INTEGER m32c_asm_integer
233636ac495dSmrg static bool
m32c_asm_integer(rtx x,unsigned int size,int aligned_p)233736ac495dSmrg m32c_asm_integer (rtx x, unsigned int size, int aligned_p)
233836ac495dSmrg {
233936ac495dSmrg switch (size)
234036ac495dSmrg {
234136ac495dSmrg case 3:
234236ac495dSmrg fprintf (asm_out_file, "\t.3byte\t");
234336ac495dSmrg output_addr_const (asm_out_file, x);
234436ac495dSmrg fputc ('\n', asm_out_file);
234536ac495dSmrg return true;
234636ac495dSmrg case 4:
234736ac495dSmrg if (GET_CODE (x) == SYMBOL_REF)
234836ac495dSmrg {
234936ac495dSmrg fprintf (asm_out_file, "\t.long\t");
235036ac495dSmrg output_addr_const (asm_out_file, x);
235136ac495dSmrg fputc ('\n', asm_out_file);
235236ac495dSmrg return true;
235336ac495dSmrg }
235436ac495dSmrg break;
235536ac495dSmrg }
235636ac495dSmrg return default_assemble_integer (x, size, aligned_p);
235736ac495dSmrg }
235836ac495dSmrg
235936ac495dSmrg /* Output of Assembler Instructions */
236036ac495dSmrg
236136ac495dSmrg /* We use a lookup table because the addressing modes are non-orthogonal. */
236236ac495dSmrg
236336ac495dSmrg static struct
236436ac495dSmrg {
236536ac495dSmrg char code;
236636ac495dSmrg char const *pattern;
236736ac495dSmrg char const *format;
236836ac495dSmrg }
236936ac495dSmrg const conversions[] = {
237036ac495dSmrg { 0, "r", "0" },
237136ac495dSmrg
237236ac495dSmrg { 0, "mr", "z[1]" },
237336ac495dSmrg { 0, "m+ri", "3[2]" },
237436ac495dSmrg { 0, "m+rs", "3[2]" },
237536ac495dSmrg { 0, "m+^Zrs", "5[4]" },
237636ac495dSmrg { 0, "m+^Zri", "5[4]" },
237736ac495dSmrg { 0, "m+^Z+ris", "7+6[5]" },
237836ac495dSmrg { 0, "m+^Srs", "5[4]" },
237936ac495dSmrg { 0, "m+^Sri", "5[4]" },
238036ac495dSmrg { 0, "m+^S+ris", "7+6[5]" },
238136ac495dSmrg { 0, "m+r+si", "4+5[2]" },
238236ac495dSmrg { 0, "ms", "1" },
238336ac495dSmrg { 0, "mi", "1" },
238436ac495dSmrg { 0, "m+si", "2+3" },
238536ac495dSmrg
238636ac495dSmrg { 0, "mmr", "[z[2]]" },
238736ac495dSmrg { 0, "mm+ri", "[4[3]]" },
238836ac495dSmrg { 0, "mm+rs", "[4[3]]" },
238936ac495dSmrg { 0, "mm+r+si", "[5+6[3]]" },
239036ac495dSmrg { 0, "mms", "[[2]]" },
239136ac495dSmrg { 0, "mmi", "[[2]]" },
239236ac495dSmrg { 0, "mm+si", "[4[3]]" },
239336ac495dSmrg
239436ac495dSmrg { 0, "i", "#0" },
239536ac495dSmrg { 0, "s", "#0" },
239636ac495dSmrg { 0, "+si", "#1+2" },
239736ac495dSmrg { 0, "l", "#0" },
239836ac495dSmrg
239936ac495dSmrg { 'l', "l", "0" },
240036ac495dSmrg { 'd', "i", "0" },
240136ac495dSmrg { 'd', "s", "0" },
240236ac495dSmrg { 'd', "+si", "1+2" },
240336ac495dSmrg { 'D', "i", "0" },
240436ac495dSmrg { 'D', "s", "0" },
240536ac495dSmrg { 'D', "+si", "1+2" },
240636ac495dSmrg { 'x', "i", "#0" },
240736ac495dSmrg { 'X', "i", "#0" },
240836ac495dSmrg { 'm', "i", "#0" },
240936ac495dSmrg { 'b', "i", "#0" },
241036ac495dSmrg { 'B', "i", "0" },
241136ac495dSmrg { 'p', "i", "0" },
241236ac495dSmrg
241336ac495dSmrg { 0, 0, 0 }
241436ac495dSmrg };
241536ac495dSmrg
241636ac495dSmrg /* This is in order according to the bitfield that pushm/popm use. */
241736ac495dSmrg static char const *pushm_regs[] = {
241836ac495dSmrg "fb", "sb", "a1", "a0", "r3", "r2", "r1", "r0"
241936ac495dSmrg };
242036ac495dSmrg
242136ac495dSmrg /* Implements TARGET_PRINT_OPERAND. */
242236ac495dSmrg
242336ac495dSmrg #undef TARGET_PRINT_OPERAND
242436ac495dSmrg #define TARGET_PRINT_OPERAND m32c_print_operand
242536ac495dSmrg
242636ac495dSmrg static void
m32c_print_operand(FILE * file,rtx x,int code)242736ac495dSmrg m32c_print_operand (FILE * file, rtx x, int code)
242836ac495dSmrg {
242936ac495dSmrg int i, j, b;
243036ac495dSmrg const char *comma;
243136ac495dSmrg HOST_WIDE_INT ival;
243236ac495dSmrg int unsigned_const = 0;
243336ac495dSmrg int force_sign;
243436ac495dSmrg
243536ac495dSmrg /* Multiplies; constants are converted to sign-extended format but
243636ac495dSmrg we need unsigned, so 'u' and 'U' tell us what size unsigned we
243736ac495dSmrg need. */
243836ac495dSmrg if (code == 'u')
243936ac495dSmrg {
244036ac495dSmrg unsigned_const = 2;
244136ac495dSmrg code = 0;
244236ac495dSmrg }
244336ac495dSmrg if (code == 'U')
244436ac495dSmrg {
244536ac495dSmrg unsigned_const = 1;
244636ac495dSmrg code = 0;
244736ac495dSmrg }
244836ac495dSmrg /* This one is only for debugging; you can put it in a pattern to
244936ac495dSmrg force this error. */
245036ac495dSmrg if (code == '!')
245136ac495dSmrg {
245236ac495dSmrg fprintf (stderr, "dj: unreviewed pattern:");
245336ac495dSmrg if (current_output_insn)
245436ac495dSmrg debug_rtx (current_output_insn);
245536ac495dSmrg gcc_unreachable ();
245636ac495dSmrg }
245736ac495dSmrg /* PSImode operations are either .w or .l depending on the target. */
245836ac495dSmrg if (code == '&')
245936ac495dSmrg {
246036ac495dSmrg if (TARGET_A16)
246136ac495dSmrg fprintf (file, "w");
246236ac495dSmrg else
246336ac495dSmrg fprintf (file, "l");
246436ac495dSmrg return;
246536ac495dSmrg }
246636ac495dSmrg /* Inverted conditionals. */
246736ac495dSmrg if (code == 'C')
246836ac495dSmrg {
246936ac495dSmrg switch (GET_CODE (x))
247036ac495dSmrg {
247136ac495dSmrg case LE:
247236ac495dSmrg fputs ("gt", file);
247336ac495dSmrg break;
247436ac495dSmrg case LEU:
247536ac495dSmrg fputs ("gtu", file);
247636ac495dSmrg break;
247736ac495dSmrg case LT:
247836ac495dSmrg fputs ("ge", file);
247936ac495dSmrg break;
248036ac495dSmrg case LTU:
248136ac495dSmrg fputs ("geu", file);
248236ac495dSmrg break;
248336ac495dSmrg case GT:
248436ac495dSmrg fputs ("le", file);
248536ac495dSmrg break;
248636ac495dSmrg case GTU:
248736ac495dSmrg fputs ("leu", file);
248836ac495dSmrg break;
248936ac495dSmrg case GE:
249036ac495dSmrg fputs ("lt", file);
249136ac495dSmrg break;
249236ac495dSmrg case GEU:
249336ac495dSmrg fputs ("ltu", file);
249436ac495dSmrg break;
249536ac495dSmrg case NE:
249636ac495dSmrg fputs ("eq", file);
249736ac495dSmrg break;
249836ac495dSmrg case EQ:
249936ac495dSmrg fputs ("ne", file);
250036ac495dSmrg break;
250136ac495dSmrg default:
250236ac495dSmrg gcc_unreachable ();
250336ac495dSmrg }
250436ac495dSmrg return;
250536ac495dSmrg }
250636ac495dSmrg /* Regular conditionals. */
250736ac495dSmrg if (code == 'c')
250836ac495dSmrg {
250936ac495dSmrg switch (GET_CODE (x))
251036ac495dSmrg {
251136ac495dSmrg case LE:
251236ac495dSmrg fputs ("le", file);
251336ac495dSmrg break;
251436ac495dSmrg case LEU:
251536ac495dSmrg fputs ("leu", file);
251636ac495dSmrg break;
251736ac495dSmrg case LT:
251836ac495dSmrg fputs ("lt", file);
251936ac495dSmrg break;
252036ac495dSmrg case LTU:
252136ac495dSmrg fputs ("ltu", file);
252236ac495dSmrg break;
252336ac495dSmrg case GT:
252436ac495dSmrg fputs ("gt", file);
252536ac495dSmrg break;
252636ac495dSmrg case GTU:
252736ac495dSmrg fputs ("gtu", file);
252836ac495dSmrg break;
252936ac495dSmrg case GE:
253036ac495dSmrg fputs ("ge", file);
253136ac495dSmrg break;
253236ac495dSmrg case GEU:
253336ac495dSmrg fputs ("geu", file);
253436ac495dSmrg break;
253536ac495dSmrg case NE:
253636ac495dSmrg fputs ("ne", file);
253736ac495dSmrg break;
253836ac495dSmrg case EQ:
253936ac495dSmrg fputs ("eq", file);
254036ac495dSmrg break;
254136ac495dSmrg default:
254236ac495dSmrg gcc_unreachable ();
254336ac495dSmrg }
254436ac495dSmrg return;
254536ac495dSmrg }
254636ac495dSmrg /* Used in negsi2 to do HImode ops on the two parts of an SImode
254736ac495dSmrg operand. */
254836ac495dSmrg if (code == 'h' && GET_MODE (x) == SImode)
254936ac495dSmrg {
255036ac495dSmrg x = m32c_subreg (HImode, x, SImode, 0);
255136ac495dSmrg code = 0;
255236ac495dSmrg }
255336ac495dSmrg if (code == 'H' && GET_MODE (x) == SImode)
255436ac495dSmrg {
255536ac495dSmrg x = m32c_subreg (HImode, x, SImode, 2);
255636ac495dSmrg code = 0;
255736ac495dSmrg }
255836ac495dSmrg if (code == 'h' && GET_MODE (x) == HImode)
255936ac495dSmrg {
256036ac495dSmrg x = m32c_subreg (QImode, x, HImode, 0);
256136ac495dSmrg code = 0;
256236ac495dSmrg }
256336ac495dSmrg if (code == 'H' && GET_MODE (x) == HImode)
256436ac495dSmrg {
256536ac495dSmrg /* We can't actually represent this as an rtx. Do it here. */
256636ac495dSmrg if (GET_CODE (x) == REG)
256736ac495dSmrg {
256836ac495dSmrg switch (REGNO (x))
256936ac495dSmrg {
257036ac495dSmrg case R0_REGNO:
257136ac495dSmrg fputs ("r0h", file);
257236ac495dSmrg return;
257336ac495dSmrg case R1_REGNO:
257436ac495dSmrg fputs ("r1h", file);
257536ac495dSmrg return;
257636ac495dSmrg default:
257736ac495dSmrg gcc_unreachable();
257836ac495dSmrg }
257936ac495dSmrg }
258036ac495dSmrg /* This should be a MEM. */
258136ac495dSmrg x = m32c_subreg (QImode, x, HImode, 1);
258236ac495dSmrg code = 0;
258336ac495dSmrg }
258436ac495dSmrg /* This is for BMcond, which always wants word register names. */
258536ac495dSmrg if (code == 'h' && GET_MODE (x) == QImode)
258636ac495dSmrg {
258736ac495dSmrg if (GET_CODE (x) == REG)
258836ac495dSmrg x = gen_rtx_REG (HImode, REGNO (x));
258936ac495dSmrg code = 0;
259036ac495dSmrg }
259136ac495dSmrg /* 'x' and 'X' need to be ignored for non-immediates. */
259236ac495dSmrg if ((code == 'x' || code == 'X') && GET_CODE (x) != CONST_INT)
259336ac495dSmrg code = 0;
259436ac495dSmrg
259536ac495dSmrg encode_pattern (x);
259636ac495dSmrg force_sign = 0;
259736ac495dSmrg for (i = 0; conversions[i].pattern; i++)
259836ac495dSmrg if (conversions[i].code == code
259936ac495dSmrg && streq (conversions[i].pattern, pattern))
260036ac495dSmrg {
260136ac495dSmrg for (j = 0; conversions[i].format[j]; j++)
260236ac495dSmrg /* backslash quotes the next character in the output pattern. */
260336ac495dSmrg if (conversions[i].format[j] == '\\')
260436ac495dSmrg {
260536ac495dSmrg fputc (conversions[i].format[j + 1], file);
260636ac495dSmrg j++;
260736ac495dSmrg }
260836ac495dSmrg /* Digits in the output pattern indicate that the
260936ac495dSmrg corresponding RTX is to be output at that point. */
261036ac495dSmrg else if (ISDIGIT (conversions[i].format[j]))
261136ac495dSmrg {
261236ac495dSmrg rtx r = patternr[conversions[i].format[j] - '0'];
261336ac495dSmrg switch (GET_CODE (r))
261436ac495dSmrg {
261536ac495dSmrg case REG:
261636ac495dSmrg fprintf (file, "%s",
261736ac495dSmrg reg_name_with_mode (REGNO (r), GET_MODE (r)));
261836ac495dSmrg break;
261936ac495dSmrg case CONST_INT:
262036ac495dSmrg switch (code)
262136ac495dSmrg {
262236ac495dSmrg case 'b':
262336ac495dSmrg case 'B':
262436ac495dSmrg {
262536ac495dSmrg int v = INTVAL (r);
262636ac495dSmrg int i = (int) exact_log2 (v);
262736ac495dSmrg if (i == -1)
262836ac495dSmrg i = (int) exact_log2 ((v ^ 0xffff) & 0xffff);
262936ac495dSmrg if (i == -1)
263036ac495dSmrg i = (int) exact_log2 ((v ^ 0xff) & 0xff);
263136ac495dSmrg /* Bit position. */
263236ac495dSmrg fprintf (file, "%d", i);
263336ac495dSmrg }
263436ac495dSmrg break;
263536ac495dSmrg case 'x':
263636ac495dSmrg /* Unsigned byte. */
263736ac495dSmrg fprintf (file, HOST_WIDE_INT_PRINT_HEX,
263836ac495dSmrg INTVAL (r) & 0xff);
263936ac495dSmrg break;
264036ac495dSmrg case 'X':
264136ac495dSmrg /* Unsigned word. */
264236ac495dSmrg fprintf (file, HOST_WIDE_INT_PRINT_HEX,
264336ac495dSmrg INTVAL (r) & 0xffff);
264436ac495dSmrg break;
264536ac495dSmrg case 'p':
264636ac495dSmrg /* pushm and popm encode a register set into a single byte. */
264736ac495dSmrg comma = "";
264836ac495dSmrg for (b = 7; b >= 0; b--)
264936ac495dSmrg if (INTVAL (r) & (1 << b))
265036ac495dSmrg {
265136ac495dSmrg fprintf (file, "%s%s", comma, pushm_regs[b]);
265236ac495dSmrg comma = ",";
265336ac495dSmrg }
265436ac495dSmrg break;
265536ac495dSmrg case 'm':
265636ac495dSmrg /* "Minus". Output -X */
265736ac495dSmrg ival = (-INTVAL (r) & 0xffff);
265836ac495dSmrg if (ival & 0x8000)
265936ac495dSmrg ival = ival - 0x10000;
266036ac495dSmrg fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
266136ac495dSmrg break;
266236ac495dSmrg default:
266336ac495dSmrg ival = INTVAL (r);
266436ac495dSmrg if (conversions[i].format[j + 1] == '[' && ival < 0)
266536ac495dSmrg {
266636ac495dSmrg /* We can simulate negative displacements by
266736ac495dSmrg taking advantage of address space
266836ac495dSmrg wrapping when the offset can span the
266936ac495dSmrg entire address range. */
267036ac495dSmrg rtx base =
267136ac495dSmrg patternr[conversions[i].format[j + 2] - '0'];
267236ac495dSmrg if (GET_CODE (base) == REG)
267336ac495dSmrg switch (REGNO (base))
267436ac495dSmrg {
267536ac495dSmrg case A0_REGNO:
267636ac495dSmrg case A1_REGNO:
267736ac495dSmrg if (TARGET_A24)
267836ac495dSmrg ival = 0x1000000 + ival;
267936ac495dSmrg else
268036ac495dSmrg ival = 0x10000 + ival;
268136ac495dSmrg break;
268236ac495dSmrg case SB_REGNO:
268336ac495dSmrg if (TARGET_A16)
268436ac495dSmrg ival = 0x10000 + ival;
268536ac495dSmrg break;
268636ac495dSmrg }
268736ac495dSmrg }
268836ac495dSmrg else if (code == 'd' && ival < 0 && j == 0)
268936ac495dSmrg /* The "mova" opcode is used to do addition by
269036ac495dSmrg computing displacements, but again, we need
269136ac495dSmrg displacements to be unsigned *if* they're
269236ac495dSmrg the only component of the displacement
269336ac495dSmrg (i.e. no "symbol-4" type displacement). */
269436ac495dSmrg ival = (TARGET_A24 ? 0x1000000 : 0x10000) + ival;
269536ac495dSmrg
269636ac495dSmrg if (conversions[i].format[j] == '0')
269736ac495dSmrg {
269836ac495dSmrg /* More conversions to unsigned. */
269936ac495dSmrg if (unsigned_const == 2)
270036ac495dSmrg ival &= 0xffff;
270136ac495dSmrg if (unsigned_const == 1)
270236ac495dSmrg ival &= 0xff;
270336ac495dSmrg }
270436ac495dSmrg if (streq (conversions[i].pattern, "mi")
270536ac495dSmrg || streq (conversions[i].pattern, "mmi"))
270636ac495dSmrg {
270736ac495dSmrg /* Integers used as addresses are unsigned. */
270836ac495dSmrg ival &= (TARGET_A24 ? 0xffffff : 0xffff);
270936ac495dSmrg }
271036ac495dSmrg if (force_sign && ival >= 0)
271136ac495dSmrg fputc ('+', file);
271236ac495dSmrg fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
271336ac495dSmrg break;
271436ac495dSmrg }
271536ac495dSmrg break;
271636ac495dSmrg case CONST_DOUBLE:
271736ac495dSmrg /* We don't have const_double constants. If it
271836ac495dSmrg happens, make it obvious. */
271936ac495dSmrg fprintf (file, "[const_double 0x%lx]",
272036ac495dSmrg (unsigned long) CONST_DOUBLE_HIGH (r));
272136ac495dSmrg break;
272236ac495dSmrg case SYMBOL_REF:
272336ac495dSmrg assemble_name (file, XSTR (r, 0));
272436ac495dSmrg break;
272536ac495dSmrg case LABEL_REF:
272636ac495dSmrg output_asm_label (r);
272736ac495dSmrg break;
272836ac495dSmrg default:
272936ac495dSmrg fprintf (stderr, "don't know how to print this operand:");
273036ac495dSmrg debug_rtx (r);
273136ac495dSmrg gcc_unreachable ();
273236ac495dSmrg }
273336ac495dSmrg }
273436ac495dSmrg else
273536ac495dSmrg {
273636ac495dSmrg if (conversions[i].format[j] == 'z')
273736ac495dSmrg {
273836ac495dSmrg /* Some addressing modes *must* have a displacement,
273936ac495dSmrg so insert a zero here if needed. */
274036ac495dSmrg int k;
274136ac495dSmrg for (k = j + 1; conversions[i].format[k]; k++)
274236ac495dSmrg if (ISDIGIT (conversions[i].format[k]))
274336ac495dSmrg {
274436ac495dSmrg rtx reg = patternr[conversions[i].format[k] - '0'];
274536ac495dSmrg if (GET_CODE (reg) == REG
274636ac495dSmrg && (REGNO (reg) == SB_REGNO
274736ac495dSmrg || REGNO (reg) == FB_REGNO
274836ac495dSmrg || REGNO (reg) == SP_REGNO))
274936ac495dSmrg fputc ('0', file);
275036ac495dSmrg }
275136ac495dSmrg continue;
275236ac495dSmrg }
275336ac495dSmrg /* Signed displacements off symbols need to have signs
275436ac495dSmrg blended cleanly. */
275536ac495dSmrg if (conversions[i].format[j] == '+'
275636ac495dSmrg && (!code || code == 'D' || code == 'd')
275736ac495dSmrg && ISDIGIT (conversions[i].format[j + 1])
275836ac495dSmrg && (GET_CODE (patternr[conversions[i].format[j + 1] - '0'])
275936ac495dSmrg == CONST_INT))
276036ac495dSmrg {
276136ac495dSmrg force_sign = 1;
276236ac495dSmrg continue;
276336ac495dSmrg }
276436ac495dSmrg fputc (conversions[i].format[j], file);
276536ac495dSmrg }
276636ac495dSmrg break;
276736ac495dSmrg }
276836ac495dSmrg if (!conversions[i].pattern)
276936ac495dSmrg {
277036ac495dSmrg fprintf (stderr, "unconvertible operand %c `%s'", code ? code : '-',
277136ac495dSmrg pattern);
277236ac495dSmrg debug_rtx (x);
277336ac495dSmrg fprintf (file, "[%c.%s]", code ? code : '-', pattern);
277436ac495dSmrg }
277536ac495dSmrg
277636ac495dSmrg return;
277736ac495dSmrg }
277836ac495dSmrg
277936ac495dSmrg /* Implements TARGET_PRINT_OPERAND_PUNCT_VALID_P.
278036ac495dSmrg
278136ac495dSmrg See m32c_print_operand above for descriptions of what these do. */
278236ac495dSmrg
278336ac495dSmrg #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
278436ac495dSmrg #define TARGET_PRINT_OPERAND_PUNCT_VALID_P m32c_print_operand_punct_valid_p
278536ac495dSmrg
278636ac495dSmrg static bool
m32c_print_operand_punct_valid_p(unsigned char c)278736ac495dSmrg m32c_print_operand_punct_valid_p (unsigned char c)
278836ac495dSmrg {
278936ac495dSmrg if (c == '&' || c == '!')
279036ac495dSmrg return true;
279136ac495dSmrg
279236ac495dSmrg return false;
279336ac495dSmrg }
279436ac495dSmrg
279536ac495dSmrg /* Implements TARGET_PRINT_OPERAND_ADDRESS. Nothing unusual here. */
279636ac495dSmrg
279736ac495dSmrg #undef TARGET_PRINT_OPERAND_ADDRESS
279836ac495dSmrg #define TARGET_PRINT_OPERAND_ADDRESS m32c_print_operand_address
279936ac495dSmrg
280036ac495dSmrg static void
m32c_print_operand_address(FILE * stream,machine_mode,rtx address)280136ac495dSmrg m32c_print_operand_address (FILE * stream, machine_mode /*mode*/, rtx address)
280236ac495dSmrg {
280336ac495dSmrg if (GET_CODE (address) == MEM)
280436ac495dSmrg address = XEXP (address, 0);
280536ac495dSmrg else
280636ac495dSmrg /* cf: gcc.dg/asm-4.c. */
280736ac495dSmrg gcc_assert (GET_CODE (address) == REG);
280836ac495dSmrg
280936ac495dSmrg m32c_print_operand (stream, address, 0);
281036ac495dSmrg }
281136ac495dSmrg
281236ac495dSmrg /* Implements ASM_OUTPUT_REG_PUSH. Control registers are pushed
281336ac495dSmrg differently than general registers. */
281436ac495dSmrg void
m32c_output_reg_push(FILE * s,int regno)281536ac495dSmrg m32c_output_reg_push (FILE * s, int regno)
281636ac495dSmrg {
281736ac495dSmrg if (regno == FLG_REGNO)
281836ac495dSmrg fprintf (s, "\tpushc\tflg\n");
281936ac495dSmrg else
282036ac495dSmrg fprintf (s, "\tpush.%c\t%s\n",
282136ac495dSmrg " bwll"[reg_push_size (regno)], reg_names[regno]);
282236ac495dSmrg }
282336ac495dSmrg
282436ac495dSmrg /* Likewise for ASM_OUTPUT_REG_POP. */
282536ac495dSmrg void
m32c_output_reg_pop(FILE * s,int regno)282636ac495dSmrg m32c_output_reg_pop (FILE * s, int regno)
282736ac495dSmrg {
282836ac495dSmrg if (regno == FLG_REGNO)
282936ac495dSmrg fprintf (s, "\tpopc\tflg\n");
283036ac495dSmrg else
283136ac495dSmrg fprintf (s, "\tpop.%c\t%s\n",
283236ac495dSmrg " bwll"[reg_push_size (regno)], reg_names[regno]);
283336ac495dSmrg }
283436ac495dSmrg
283536ac495dSmrg /* Defining target-specific uses of `__attribute__' */
283636ac495dSmrg
283736ac495dSmrg /* Used to simplify the logic below. Find the attributes wherever
283836ac495dSmrg they may be. */
283936ac495dSmrg #define M32C_ATTRIBUTES(decl) \
284036ac495dSmrg (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
284136ac495dSmrg : DECL_ATTRIBUTES (decl) \
284236ac495dSmrg ? (DECL_ATTRIBUTES (decl)) \
284336ac495dSmrg : TYPE_ATTRIBUTES (TREE_TYPE (decl))
284436ac495dSmrg
284536ac495dSmrg /* Returns TRUE if the given tree has the "interrupt" attribute. */
284636ac495dSmrg static int
interrupt_p(tree node ATTRIBUTE_UNUSED)284736ac495dSmrg interrupt_p (tree node ATTRIBUTE_UNUSED)
284836ac495dSmrg {
284936ac495dSmrg tree list = M32C_ATTRIBUTES (node);
285036ac495dSmrg while (list)
285136ac495dSmrg {
285236ac495dSmrg if (is_attribute_p ("interrupt", TREE_PURPOSE (list)))
285336ac495dSmrg return 1;
285436ac495dSmrg list = TREE_CHAIN (list);
285536ac495dSmrg }
285636ac495dSmrg return fast_interrupt_p (node);
285736ac495dSmrg }
285836ac495dSmrg
285936ac495dSmrg /* Returns TRUE if the given tree has the "bank_switch" attribute. */
286036ac495dSmrg static int
bank_switch_p(tree node ATTRIBUTE_UNUSED)286136ac495dSmrg bank_switch_p (tree node ATTRIBUTE_UNUSED)
286236ac495dSmrg {
286336ac495dSmrg tree list = M32C_ATTRIBUTES (node);
286436ac495dSmrg while (list)
286536ac495dSmrg {
286636ac495dSmrg if (is_attribute_p ("bank_switch", TREE_PURPOSE (list)))
286736ac495dSmrg return 1;
286836ac495dSmrg list = TREE_CHAIN (list);
286936ac495dSmrg }
287036ac495dSmrg return 0;
287136ac495dSmrg }
287236ac495dSmrg
287336ac495dSmrg /* Returns TRUE if the given tree has the "fast_interrupt" attribute. */
287436ac495dSmrg static int
fast_interrupt_p(tree node ATTRIBUTE_UNUSED)287536ac495dSmrg fast_interrupt_p (tree node ATTRIBUTE_UNUSED)
287636ac495dSmrg {
287736ac495dSmrg tree list = M32C_ATTRIBUTES (node);
287836ac495dSmrg while (list)
287936ac495dSmrg {
288036ac495dSmrg if (is_attribute_p ("fast_interrupt", TREE_PURPOSE (list)))
288136ac495dSmrg return 1;
288236ac495dSmrg list = TREE_CHAIN (list);
288336ac495dSmrg }
288436ac495dSmrg return 0;
288536ac495dSmrg }
288636ac495dSmrg
288736ac495dSmrg static tree
interrupt_handler(tree * node ATTRIBUTE_UNUSED,tree name ATTRIBUTE_UNUSED,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs ATTRIBUTE_UNUSED)288836ac495dSmrg interrupt_handler (tree * node ATTRIBUTE_UNUSED,
288936ac495dSmrg tree name ATTRIBUTE_UNUSED,
289036ac495dSmrg tree args ATTRIBUTE_UNUSED,
289136ac495dSmrg int flags ATTRIBUTE_UNUSED,
289236ac495dSmrg bool * no_add_attrs ATTRIBUTE_UNUSED)
289336ac495dSmrg {
289436ac495dSmrg return NULL_TREE;
289536ac495dSmrg }
289636ac495dSmrg
289736ac495dSmrg /* Returns TRUE if given tree has the "function_vector" attribute. */
289836ac495dSmrg int
m32c_special_page_vector_p(tree func)289936ac495dSmrg m32c_special_page_vector_p (tree func)
290036ac495dSmrg {
290136ac495dSmrg tree list;
290236ac495dSmrg
290336ac495dSmrg if (TREE_CODE (func) != FUNCTION_DECL)
290436ac495dSmrg return 0;
290536ac495dSmrg
290636ac495dSmrg list = M32C_ATTRIBUTES (func);
290736ac495dSmrg while (list)
290836ac495dSmrg {
290936ac495dSmrg if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
291036ac495dSmrg return 1;
291136ac495dSmrg list = TREE_CHAIN (list);
291236ac495dSmrg }
291336ac495dSmrg return 0;
291436ac495dSmrg }
291536ac495dSmrg
291636ac495dSmrg static tree
function_vector_handler(tree * node ATTRIBUTE_UNUSED,tree name ATTRIBUTE_UNUSED,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs ATTRIBUTE_UNUSED)291736ac495dSmrg function_vector_handler (tree * node ATTRIBUTE_UNUSED,
291836ac495dSmrg tree name ATTRIBUTE_UNUSED,
291936ac495dSmrg tree args ATTRIBUTE_UNUSED,
292036ac495dSmrg int flags ATTRIBUTE_UNUSED,
292136ac495dSmrg bool * no_add_attrs ATTRIBUTE_UNUSED)
292236ac495dSmrg {
292336ac495dSmrg if (TARGET_R8C)
292436ac495dSmrg {
292536ac495dSmrg /* The attribute is not supported for R8C target. */
292636ac495dSmrg warning (OPT_Wattributes,
292736ac495dSmrg "%qE attribute is not supported for R8C target",
292836ac495dSmrg name);
292936ac495dSmrg *no_add_attrs = true;
293036ac495dSmrg }
293136ac495dSmrg else if (TREE_CODE (*node) != FUNCTION_DECL)
293236ac495dSmrg {
293336ac495dSmrg /* The attribute must be applied to functions only. */
293436ac495dSmrg warning (OPT_Wattributes,
293536ac495dSmrg "%qE attribute applies only to functions",
293636ac495dSmrg name);
293736ac495dSmrg *no_add_attrs = true;
293836ac495dSmrg }
293936ac495dSmrg else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
294036ac495dSmrg {
294136ac495dSmrg /* The argument must be a constant integer. */
294236ac495dSmrg warning (OPT_Wattributes,
294336ac495dSmrg "%qE attribute argument not an integer constant",
294436ac495dSmrg name);
294536ac495dSmrg *no_add_attrs = true;
294636ac495dSmrg }
294736ac495dSmrg else if (TREE_INT_CST_LOW (TREE_VALUE (args)) < 18
294836ac495dSmrg || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
294936ac495dSmrg {
295036ac495dSmrg /* The argument value must be between 18 to 255. */
295136ac495dSmrg warning (OPT_Wattributes,
295236ac495dSmrg "%qE attribute argument should be between 18 to 255",
295336ac495dSmrg name);
295436ac495dSmrg *no_add_attrs = true;
295536ac495dSmrg }
295636ac495dSmrg return NULL_TREE;
295736ac495dSmrg }
295836ac495dSmrg
295936ac495dSmrg /* If the function is assigned the attribute 'function_vector', it
296036ac495dSmrg returns the function vector number, otherwise returns zero. */
296136ac495dSmrg int
current_function_special_page_vector(rtx x)296236ac495dSmrg current_function_special_page_vector (rtx x)
296336ac495dSmrg {
296436ac495dSmrg int num;
296536ac495dSmrg
296636ac495dSmrg if ((GET_CODE(x) == SYMBOL_REF)
296736ac495dSmrg && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
296836ac495dSmrg {
296936ac495dSmrg tree list;
297036ac495dSmrg tree t = SYMBOL_REF_DECL (x);
297136ac495dSmrg
297236ac495dSmrg if (TREE_CODE (t) != FUNCTION_DECL)
297336ac495dSmrg return 0;
297436ac495dSmrg
297536ac495dSmrg list = M32C_ATTRIBUTES (t);
297636ac495dSmrg while (list)
297736ac495dSmrg {
297836ac495dSmrg if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
297936ac495dSmrg {
298036ac495dSmrg num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
298136ac495dSmrg return num;
298236ac495dSmrg }
298336ac495dSmrg
298436ac495dSmrg list = TREE_CHAIN (list);
298536ac495dSmrg }
298636ac495dSmrg
298736ac495dSmrg return 0;
298836ac495dSmrg }
298936ac495dSmrg else
299036ac495dSmrg return 0;
299136ac495dSmrg }
299236ac495dSmrg
299336ac495dSmrg #undef TARGET_ATTRIBUTE_TABLE
299436ac495dSmrg #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
299536ac495dSmrg static const struct attribute_spec m32c_attribute_table[] = {
2996a2dc1f3fSmrg /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
2997a2dc1f3fSmrg affects_type_identity, handler, exclude } */
2998a2dc1f3fSmrg { "interrupt", 0, 0, false, false, false, false, interrupt_handler, NULL },
2999a2dc1f3fSmrg { "bank_switch", 0, 0, false, false, false, false, interrupt_handler, NULL },
3000a2dc1f3fSmrg { "fast_interrupt", 0, 0, false, false, false, false,
3001a2dc1f3fSmrg interrupt_handler, NULL },
3002a2dc1f3fSmrg { "function_vector", 1, 1, true, false, false, false,
3003a2dc1f3fSmrg function_vector_handler, NULL },
3004a2dc1f3fSmrg { NULL, 0, 0, false, false, false, false, NULL, NULL }
300536ac495dSmrg };
300636ac495dSmrg
300736ac495dSmrg #undef TARGET_COMP_TYPE_ATTRIBUTES
300836ac495dSmrg #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
300936ac495dSmrg static int
m32c_comp_type_attributes(const_tree type1 ATTRIBUTE_UNUSED,const_tree type2 ATTRIBUTE_UNUSED)301036ac495dSmrg m32c_comp_type_attributes (const_tree type1 ATTRIBUTE_UNUSED,
301136ac495dSmrg const_tree type2 ATTRIBUTE_UNUSED)
301236ac495dSmrg {
301336ac495dSmrg /* 0=incompatible 1=compatible 2=warning */
301436ac495dSmrg return 1;
301536ac495dSmrg }
301636ac495dSmrg
301736ac495dSmrg #undef TARGET_INSERT_ATTRIBUTES
301836ac495dSmrg #define TARGET_INSERT_ATTRIBUTES m32c_insert_attributes
301936ac495dSmrg static void
m32c_insert_attributes(tree node ATTRIBUTE_UNUSED,tree * attr_ptr ATTRIBUTE_UNUSED)302036ac495dSmrg m32c_insert_attributes (tree node ATTRIBUTE_UNUSED,
302136ac495dSmrg tree * attr_ptr ATTRIBUTE_UNUSED)
302236ac495dSmrg {
302336ac495dSmrg unsigned addr;
302436ac495dSmrg /* See if we need to make #pragma address variables volatile. */
302536ac495dSmrg
302636ac495dSmrg if (TREE_CODE (node) == VAR_DECL)
302736ac495dSmrg {
302836ac495dSmrg const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
302936ac495dSmrg if (m32c_get_pragma_address (name, &addr))
303036ac495dSmrg {
303136ac495dSmrg TREE_THIS_VOLATILE (node) = true;
303236ac495dSmrg }
303336ac495dSmrg }
303436ac495dSmrg }
303536ac495dSmrg
303636ac495dSmrg /* Hash table of pragma info. */
303736ac495dSmrg static GTY(()) hash_map<nofree_string_hash, unsigned> *pragma_htab;
303836ac495dSmrg
303936ac495dSmrg void
m32c_note_pragma_address(const char * varname,unsigned address)304036ac495dSmrg m32c_note_pragma_address (const char *varname, unsigned address)
304136ac495dSmrg {
304236ac495dSmrg if (!pragma_htab)
304336ac495dSmrg pragma_htab = hash_map<nofree_string_hash, unsigned>::create_ggc (31);
304436ac495dSmrg
304536ac495dSmrg const char *name = ggc_strdup (varname);
304636ac495dSmrg unsigned int *slot = &pragma_htab->get_or_insert (name);
304736ac495dSmrg *slot = address;
304836ac495dSmrg }
304936ac495dSmrg
305036ac495dSmrg static bool
m32c_get_pragma_address(const char * varname,unsigned * address)305136ac495dSmrg m32c_get_pragma_address (const char *varname, unsigned *address)
305236ac495dSmrg {
305336ac495dSmrg if (!pragma_htab)
305436ac495dSmrg return false;
305536ac495dSmrg
305636ac495dSmrg unsigned int *slot = pragma_htab->get (varname);
305736ac495dSmrg if (slot)
305836ac495dSmrg {
305936ac495dSmrg *address = *slot;
306036ac495dSmrg return true;
306136ac495dSmrg }
306236ac495dSmrg return false;
306336ac495dSmrg }
306436ac495dSmrg
306536ac495dSmrg void
m32c_output_aligned_common(FILE * stream,tree decl ATTRIBUTE_UNUSED,const char * name,int size,int align,int global)306636ac495dSmrg m32c_output_aligned_common (FILE *stream, tree decl ATTRIBUTE_UNUSED,
306736ac495dSmrg const char *name,
306836ac495dSmrg int size, int align, int global)
306936ac495dSmrg {
307036ac495dSmrg unsigned address;
307136ac495dSmrg
307236ac495dSmrg if (m32c_get_pragma_address (name, &address))
307336ac495dSmrg {
307436ac495dSmrg /* We never output these as global. */
307536ac495dSmrg assemble_name (stream, name);
307636ac495dSmrg fprintf (stream, " = 0x%04x\n", address);
307736ac495dSmrg return;
307836ac495dSmrg }
307936ac495dSmrg if (!global)
308036ac495dSmrg {
308136ac495dSmrg fprintf (stream, "\t.local\t");
308236ac495dSmrg assemble_name (stream, name);
308336ac495dSmrg fprintf (stream, "\n");
308436ac495dSmrg }
308536ac495dSmrg fprintf (stream, "\t.comm\t");
308636ac495dSmrg assemble_name (stream, name);
308736ac495dSmrg fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
308836ac495dSmrg }
308936ac495dSmrg
309036ac495dSmrg /* Predicates */
309136ac495dSmrg
309236ac495dSmrg /* This is a list of legal subregs of hard regs. */
309336ac495dSmrg static const struct {
309436ac495dSmrg unsigned char outer_mode_size;
309536ac495dSmrg unsigned char inner_mode_size;
309636ac495dSmrg unsigned char byte_mask;
309736ac495dSmrg unsigned char legal_when;
309836ac495dSmrg unsigned int regno;
309936ac495dSmrg } legal_subregs[] = {
310036ac495dSmrg {1, 2, 0x03, 1, R0_REGNO}, /* r0h r0l */
310136ac495dSmrg {1, 2, 0x03, 1, R1_REGNO}, /* r1h r1l */
310236ac495dSmrg {1, 2, 0x01, 1, A0_REGNO},
310336ac495dSmrg {1, 2, 0x01, 1, A1_REGNO},
310436ac495dSmrg
310536ac495dSmrg {1, 4, 0x01, 1, A0_REGNO},
310636ac495dSmrg {1, 4, 0x01, 1, A1_REGNO},
310736ac495dSmrg
310836ac495dSmrg {2, 4, 0x05, 1, R0_REGNO}, /* r2 r0 */
310936ac495dSmrg {2, 4, 0x05, 1, R1_REGNO}, /* r3 r1 */
311036ac495dSmrg {2, 4, 0x05, 16, A0_REGNO}, /* a1 a0 */
311136ac495dSmrg {2, 4, 0x01, 24, A0_REGNO}, /* a1 a0 */
311236ac495dSmrg {2, 4, 0x01, 24, A1_REGNO}, /* a1 a0 */
311336ac495dSmrg
311436ac495dSmrg {4, 8, 0x55, 1, R0_REGNO}, /* r3 r1 r2 r0 */
311536ac495dSmrg };
311636ac495dSmrg
311736ac495dSmrg /* Returns TRUE if OP is a subreg of a hard reg which we don't
311836ac495dSmrg support. We also bail on MEMs with illegal addresses. */
311936ac495dSmrg bool
m32c_illegal_subreg_p(rtx op)312036ac495dSmrg m32c_illegal_subreg_p (rtx op)
312136ac495dSmrg {
312236ac495dSmrg int offset;
312336ac495dSmrg unsigned int i;
312436ac495dSmrg machine_mode src_mode, dest_mode;
312536ac495dSmrg
312636ac495dSmrg if (GET_CODE (op) == MEM
312736ac495dSmrg && ! m32c_legitimate_address_p (Pmode, XEXP (op, 0), false))
312836ac495dSmrg {
312936ac495dSmrg return true;
313036ac495dSmrg }
313136ac495dSmrg
313236ac495dSmrg if (GET_CODE (op) != SUBREG)
313336ac495dSmrg return false;
313436ac495dSmrg
313536ac495dSmrg dest_mode = GET_MODE (op);
313636ac495dSmrg offset = SUBREG_BYTE (op);
313736ac495dSmrg op = SUBREG_REG (op);
313836ac495dSmrg src_mode = GET_MODE (op);
313936ac495dSmrg
314036ac495dSmrg if (GET_MODE_SIZE (dest_mode) == GET_MODE_SIZE (src_mode))
314136ac495dSmrg return false;
314236ac495dSmrg if (GET_CODE (op) != REG)
314336ac495dSmrg return false;
314436ac495dSmrg if (REGNO (op) >= MEM0_REGNO)
314536ac495dSmrg return false;
314636ac495dSmrg
314736ac495dSmrg offset = (1 << offset);
314836ac495dSmrg
314936ac495dSmrg for (i = 0; i < ARRAY_SIZE (legal_subregs); i ++)
315036ac495dSmrg if (legal_subregs[i].outer_mode_size == GET_MODE_SIZE (dest_mode)
315136ac495dSmrg && legal_subregs[i].regno == REGNO (op)
315236ac495dSmrg && legal_subregs[i].inner_mode_size == GET_MODE_SIZE (src_mode)
315336ac495dSmrg && legal_subregs[i].byte_mask & offset)
315436ac495dSmrg {
315536ac495dSmrg switch (legal_subregs[i].legal_when)
315636ac495dSmrg {
315736ac495dSmrg case 1:
315836ac495dSmrg return false;
315936ac495dSmrg case 16:
316036ac495dSmrg if (TARGET_A16)
316136ac495dSmrg return false;
316236ac495dSmrg break;
316336ac495dSmrg case 24:
316436ac495dSmrg if (TARGET_A24)
316536ac495dSmrg return false;
316636ac495dSmrg break;
316736ac495dSmrg }
316836ac495dSmrg }
316936ac495dSmrg return true;
317036ac495dSmrg }
317136ac495dSmrg
317236ac495dSmrg /* Returns TRUE if we support a move between the first two operands.
317336ac495dSmrg At the moment, we just want to discourage mem to mem moves until
317436ac495dSmrg after reload, because reload has a hard time with our limited
317536ac495dSmrg number of address registers, and we can get into a situation where
317636ac495dSmrg we need three of them when we only have two. */
317736ac495dSmrg bool
m32c_mov_ok(rtx * operands,machine_mode mode ATTRIBUTE_UNUSED)317836ac495dSmrg m32c_mov_ok (rtx * operands, machine_mode mode ATTRIBUTE_UNUSED)
317936ac495dSmrg {
318036ac495dSmrg rtx op0 = operands[0];
318136ac495dSmrg rtx op1 = operands[1];
318236ac495dSmrg
318336ac495dSmrg if (TARGET_A24)
318436ac495dSmrg return true;
318536ac495dSmrg
318636ac495dSmrg #define DEBUG_MOV_OK 0
318736ac495dSmrg #if DEBUG_MOV_OK
318836ac495dSmrg fprintf (stderr, "m32c_mov_ok %s\n", mode_name[mode]);
318936ac495dSmrg debug_rtx (op0);
319036ac495dSmrg debug_rtx (op1);
319136ac495dSmrg #endif
319236ac495dSmrg
319336ac495dSmrg if (GET_CODE (op0) == SUBREG)
319436ac495dSmrg op0 = XEXP (op0, 0);
319536ac495dSmrg if (GET_CODE (op1) == SUBREG)
319636ac495dSmrg op1 = XEXP (op1, 0);
319736ac495dSmrg
319836ac495dSmrg if (GET_CODE (op0) == MEM
319936ac495dSmrg && GET_CODE (op1) == MEM
320036ac495dSmrg && ! reload_completed)
320136ac495dSmrg {
320236ac495dSmrg #if DEBUG_MOV_OK
320336ac495dSmrg fprintf (stderr, " - no, mem to mem\n");
320436ac495dSmrg #endif
320536ac495dSmrg return false;
320636ac495dSmrg }
320736ac495dSmrg
320836ac495dSmrg #if DEBUG_MOV_OK
320936ac495dSmrg fprintf (stderr, " - ok\n");
321036ac495dSmrg #endif
321136ac495dSmrg return true;
321236ac495dSmrg }
321336ac495dSmrg
321436ac495dSmrg /* Returns TRUE if two consecutive HImode mov instructions, generated
321536ac495dSmrg for moving an immediate double data to a double data type variable
321636ac495dSmrg location, can be combined into single SImode mov instruction. */
321736ac495dSmrg bool
m32c_immd_dbl_mov(rtx * operands ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED)321836ac495dSmrg m32c_immd_dbl_mov (rtx * operands ATTRIBUTE_UNUSED,
321936ac495dSmrg machine_mode mode ATTRIBUTE_UNUSED)
322036ac495dSmrg {
322136ac495dSmrg /* ??? This relied on the now-defunct MEM_SCALAR and MEM_IN_STRUCT_P
322236ac495dSmrg flags. */
322336ac495dSmrg return false;
322436ac495dSmrg }
322536ac495dSmrg
322636ac495dSmrg /* Expanders */
322736ac495dSmrg
322836ac495dSmrg /* Subregs are non-orthogonal for us, because our registers are all
322936ac495dSmrg different sizes. */
323036ac495dSmrg static rtx
m32c_subreg(machine_mode outer,rtx x,machine_mode inner,int byte)323136ac495dSmrg m32c_subreg (machine_mode outer,
323236ac495dSmrg rtx x, machine_mode inner, int byte)
323336ac495dSmrg {
323436ac495dSmrg int r, nr = -1;
323536ac495dSmrg
323636ac495dSmrg /* Converting MEMs to different types that are the same size, we
323736ac495dSmrg just rewrite them. */
323836ac495dSmrg if (GET_CODE (x) == SUBREG
323936ac495dSmrg && SUBREG_BYTE (x) == 0
324036ac495dSmrg && GET_CODE (SUBREG_REG (x)) == MEM
324136ac495dSmrg && (GET_MODE_SIZE (GET_MODE (x))
324236ac495dSmrg == GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
324336ac495dSmrg {
324436ac495dSmrg rtx oldx = x;
324536ac495dSmrg x = gen_rtx_MEM (GET_MODE (x), XEXP (SUBREG_REG (x), 0));
324636ac495dSmrg MEM_COPY_ATTRIBUTES (x, SUBREG_REG (oldx));
324736ac495dSmrg }
324836ac495dSmrg
324936ac495dSmrg /* Push/pop get done as smaller push/pops. */
325036ac495dSmrg if (GET_CODE (x) == MEM
325136ac495dSmrg && (GET_CODE (XEXP (x, 0)) == PRE_DEC
325236ac495dSmrg || GET_CODE (XEXP (x, 0)) == POST_INC))
325336ac495dSmrg return gen_rtx_MEM (outer, XEXP (x, 0));
325436ac495dSmrg if (GET_CODE (x) == SUBREG
325536ac495dSmrg && GET_CODE (XEXP (x, 0)) == MEM
325636ac495dSmrg && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PRE_DEC
325736ac495dSmrg || GET_CODE (XEXP (XEXP (x, 0), 0)) == POST_INC))
325836ac495dSmrg return gen_rtx_MEM (outer, XEXP (XEXP (x, 0), 0));
325936ac495dSmrg
326036ac495dSmrg if (GET_CODE (x) != REG)
326136ac495dSmrg {
326236ac495dSmrg rtx r = simplify_gen_subreg (outer, x, inner, byte);
326336ac495dSmrg if (GET_CODE (r) == SUBREG
326436ac495dSmrg && GET_CODE (x) == MEM
326536ac495dSmrg && MEM_VOLATILE_P (x))
326636ac495dSmrg {
326736ac495dSmrg /* Volatile MEMs don't get simplified, but we need them to
326836ac495dSmrg be. We are little endian, so the subreg byte is the
326936ac495dSmrg offset. */
327036ac495dSmrg r = adjust_address_nv (x, outer, byte);
327136ac495dSmrg }
327236ac495dSmrg return r;
327336ac495dSmrg }
327436ac495dSmrg
327536ac495dSmrg r = REGNO (x);
327636ac495dSmrg if (r >= FIRST_PSEUDO_REGISTER || r == AP_REGNO)
327736ac495dSmrg return simplify_gen_subreg (outer, x, inner, byte);
327836ac495dSmrg
327936ac495dSmrg if (IS_MEM_REGNO (r))
328036ac495dSmrg return simplify_gen_subreg (outer, x, inner, byte);
328136ac495dSmrg
328236ac495dSmrg /* This is where the complexities of our register layout are
328336ac495dSmrg described. */
328436ac495dSmrg if (byte == 0)
328536ac495dSmrg nr = r;
328636ac495dSmrg else if (outer == HImode)
328736ac495dSmrg {
328836ac495dSmrg if (r == R0_REGNO && byte == 2)
328936ac495dSmrg nr = R2_REGNO;
329036ac495dSmrg else if (r == R0_REGNO && byte == 4)
329136ac495dSmrg nr = R1_REGNO;
329236ac495dSmrg else if (r == R0_REGNO && byte == 6)
329336ac495dSmrg nr = R3_REGNO;
329436ac495dSmrg else if (r == R1_REGNO && byte == 2)
329536ac495dSmrg nr = R3_REGNO;
329636ac495dSmrg else if (r == A0_REGNO && byte == 2)
329736ac495dSmrg nr = A1_REGNO;
329836ac495dSmrg }
329936ac495dSmrg else if (outer == SImode)
330036ac495dSmrg {
330136ac495dSmrg if (r == R0_REGNO && byte == 0)
330236ac495dSmrg nr = R0_REGNO;
330336ac495dSmrg else if (r == R0_REGNO && byte == 4)
330436ac495dSmrg nr = R1_REGNO;
330536ac495dSmrg }
330636ac495dSmrg if (nr == -1)
330736ac495dSmrg {
330836ac495dSmrg fprintf (stderr, "m32c_subreg %s %s %d\n",
330936ac495dSmrg mode_name[outer], mode_name[inner], byte);
331036ac495dSmrg debug_rtx (x);
331136ac495dSmrg gcc_unreachable ();
331236ac495dSmrg }
331336ac495dSmrg return gen_rtx_REG (outer, nr);
331436ac495dSmrg }
331536ac495dSmrg
331636ac495dSmrg /* Used to emit move instructions. We split some moves,
331736ac495dSmrg and avoid mem-mem moves. */
331836ac495dSmrg int
m32c_prepare_move(rtx * operands,machine_mode mode)331936ac495dSmrg m32c_prepare_move (rtx * operands, machine_mode mode)
332036ac495dSmrg {
332136ac495dSmrg if (far_addr_space_p (operands[0])
332236ac495dSmrg && CONSTANT_P (operands[1]))
332336ac495dSmrg {
332436ac495dSmrg operands[1] = force_reg (GET_MODE (operands[0]), operands[1]);
332536ac495dSmrg }
332636ac495dSmrg if (TARGET_A16 && mode == PSImode)
332736ac495dSmrg return m32c_split_move (operands, mode, 1);
332836ac495dSmrg if ((GET_CODE (operands[0]) == MEM)
332936ac495dSmrg && (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY))
333036ac495dSmrg {
333136ac495dSmrg rtx pmv = XEXP (operands[0], 0);
333236ac495dSmrg rtx dest_reg = XEXP (pmv, 0);
333336ac495dSmrg rtx dest_mod = XEXP (pmv, 1);
333436ac495dSmrg
333536ac495dSmrg emit_insn (gen_rtx_SET (dest_reg, dest_mod));
333636ac495dSmrg operands[0] = gen_rtx_MEM (mode, dest_reg);
333736ac495dSmrg }
333836ac495dSmrg if (can_create_pseudo_p () && MEM_P (operands[0]) && MEM_P (operands[1]))
333936ac495dSmrg operands[1] = copy_to_mode_reg (mode, operands[1]);
334036ac495dSmrg return 0;
334136ac495dSmrg }
334236ac495dSmrg
334336ac495dSmrg #define DEBUG_SPLIT 0
334436ac495dSmrg
334536ac495dSmrg /* Returns TRUE if the given PSImode move should be split. We split
334636ac495dSmrg for all r8c/m16c moves, since it doesn't support them, and for
334736ac495dSmrg POP.L as we can only *push* SImode. */
334836ac495dSmrg int
m32c_split_psi_p(rtx * operands)334936ac495dSmrg m32c_split_psi_p (rtx * operands)
335036ac495dSmrg {
335136ac495dSmrg #if DEBUG_SPLIT
335236ac495dSmrg fprintf (stderr, "\nm32c_split_psi_p\n");
335336ac495dSmrg debug_rtx (operands[0]);
335436ac495dSmrg debug_rtx (operands[1]);
335536ac495dSmrg #endif
335636ac495dSmrg if (TARGET_A16)
335736ac495dSmrg {
335836ac495dSmrg #if DEBUG_SPLIT
335936ac495dSmrg fprintf (stderr, "yes, A16\n");
336036ac495dSmrg #endif
336136ac495dSmrg return 1;
336236ac495dSmrg }
336336ac495dSmrg if (GET_CODE (operands[1]) == MEM
336436ac495dSmrg && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
336536ac495dSmrg {
336636ac495dSmrg #if DEBUG_SPLIT
336736ac495dSmrg fprintf (stderr, "yes, pop.l\n");
336836ac495dSmrg #endif
336936ac495dSmrg return 1;
337036ac495dSmrg }
337136ac495dSmrg #if DEBUG_SPLIT
337236ac495dSmrg fprintf (stderr, "no, default\n");
337336ac495dSmrg #endif
337436ac495dSmrg return 0;
337536ac495dSmrg }
337636ac495dSmrg
337736ac495dSmrg /* Split the given move. SPLIT_ALL is 0 if splitting is optional
337836ac495dSmrg (define_expand), 1 if it is not optional (define_insn_and_split),
337936ac495dSmrg and 3 for define_split (alternate api). */
338036ac495dSmrg int
m32c_split_move(rtx * operands,machine_mode mode,int split_all)338136ac495dSmrg m32c_split_move (rtx * operands, machine_mode mode, int split_all)
338236ac495dSmrg {
338336ac495dSmrg rtx s[4], d[4];
338436ac495dSmrg int parts, si, di, rev = 0;
338536ac495dSmrg int rv = 0, opi = 2;
338636ac495dSmrg machine_mode submode = HImode;
338736ac495dSmrg rtx *ops, local_ops[10];
338836ac495dSmrg
338936ac495dSmrg /* define_split modifies the existing operands, but the other two
339036ac495dSmrg emit new insns. OPS is where we store the operand pairs, which
339136ac495dSmrg we emit later. */
339236ac495dSmrg if (split_all == 3)
339336ac495dSmrg ops = operands;
339436ac495dSmrg else
339536ac495dSmrg ops = local_ops;
339636ac495dSmrg
339736ac495dSmrg /* Else HImode. */
339836ac495dSmrg if (mode == DImode)
339936ac495dSmrg submode = SImode;
340036ac495dSmrg
340136ac495dSmrg /* Before splitting mem-mem moves, force one operand into a
340236ac495dSmrg register. */
340336ac495dSmrg if (can_create_pseudo_p () && MEM_P (operands[0]) && MEM_P (operands[1]))
340436ac495dSmrg {
340536ac495dSmrg #if DEBUG0
340636ac495dSmrg fprintf (stderr, "force_reg...\n");
340736ac495dSmrg debug_rtx (operands[1]);
340836ac495dSmrg #endif
340936ac495dSmrg operands[1] = force_reg (mode, operands[1]);
341036ac495dSmrg #if DEBUG0
341136ac495dSmrg debug_rtx (operands[1]);
341236ac495dSmrg #endif
341336ac495dSmrg }
341436ac495dSmrg
341536ac495dSmrg parts = 2;
341636ac495dSmrg
341736ac495dSmrg #if DEBUG_SPLIT
341836ac495dSmrg fprintf (stderr, "\nsplit_move %d all=%d\n", !can_create_pseudo_p (),
341936ac495dSmrg split_all);
342036ac495dSmrg debug_rtx (operands[0]);
342136ac495dSmrg debug_rtx (operands[1]);
342236ac495dSmrg #endif
342336ac495dSmrg
342436ac495dSmrg /* Note that split_all is not used to select the api after this
342536ac495dSmrg point, so it's safe to set it to 3 even with define_insn. */
342636ac495dSmrg /* None of the chips can move SI operands to sp-relative addresses,
342736ac495dSmrg so we always split those. */
342836ac495dSmrg if (satisfies_constraint_Ss (operands[0]))
342936ac495dSmrg split_all = 3;
343036ac495dSmrg
343136ac495dSmrg if (TARGET_A16
343236ac495dSmrg && (far_addr_space_p (operands[0])
343336ac495dSmrg || far_addr_space_p (operands[1])))
343436ac495dSmrg split_all |= 1;
343536ac495dSmrg
343636ac495dSmrg /* We don't need to split these. */
343736ac495dSmrg if (TARGET_A24
343836ac495dSmrg && split_all != 3
343936ac495dSmrg && (mode == SImode || mode == PSImode)
344036ac495dSmrg && !(GET_CODE (operands[1]) == MEM
344136ac495dSmrg && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
344236ac495dSmrg return 0;
344336ac495dSmrg
344436ac495dSmrg /* First, enumerate the subregs we'll be dealing with. */
344536ac495dSmrg for (si = 0; si < parts; si++)
344636ac495dSmrg {
344736ac495dSmrg d[si] =
344836ac495dSmrg m32c_subreg (submode, operands[0], mode,
344936ac495dSmrg si * GET_MODE_SIZE (submode));
345036ac495dSmrg s[si] =
345136ac495dSmrg m32c_subreg (submode, operands[1], mode,
345236ac495dSmrg si * GET_MODE_SIZE (submode));
345336ac495dSmrg }
345436ac495dSmrg
345536ac495dSmrg /* Split pushes by emitting a sequence of smaller pushes. */
345636ac495dSmrg if (GET_CODE (d[0]) == MEM && GET_CODE (XEXP (d[0], 0)) == PRE_DEC)
345736ac495dSmrg {
345836ac495dSmrg for (si = parts - 1; si >= 0; si--)
345936ac495dSmrg {
346036ac495dSmrg ops[opi++] = gen_rtx_MEM (submode,
346136ac495dSmrg gen_rtx_PRE_DEC (Pmode,
346236ac495dSmrg gen_rtx_REG (Pmode,
346336ac495dSmrg SP_REGNO)));
346436ac495dSmrg ops[opi++] = s[si];
346536ac495dSmrg }
346636ac495dSmrg
346736ac495dSmrg rv = 1;
346836ac495dSmrg }
346936ac495dSmrg /* Likewise for pops. */
347036ac495dSmrg else if (GET_CODE (s[0]) == MEM && GET_CODE (XEXP (s[0], 0)) == POST_INC)
347136ac495dSmrg {
347236ac495dSmrg for (di = 0; di < parts; di++)
347336ac495dSmrg {
347436ac495dSmrg ops[opi++] = d[di];
347536ac495dSmrg ops[opi++] = gen_rtx_MEM (submode,
347636ac495dSmrg gen_rtx_POST_INC (Pmode,
347736ac495dSmrg gen_rtx_REG (Pmode,
347836ac495dSmrg SP_REGNO)));
347936ac495dSmrg }
348036ac495dSmrg rv = 1;
348136ac495dSmrg }
348236ac495dSmrg else if (split_all)
348336ac495dSmrg {
348436ac495dSmrg /* if d[di] == s[si] for any di < si, we'll early clobber. */
348536ac495dSmrg for (di = 0; di < parts - 1; di++)
348636ac495dSmrg for (si = di + 1; si < parts; si++)
348736ac495dSmrg if (reg_mentioned_p (d[di], s[si]))
348836ac495dSmrg rev = 1;
348936ac495dSmrg
349036ac495dSmrg if (rev)
349136ac495dSmrg for (si = 0; si < parts; si++)
349236ac495dSmrg {
349336ac495dSmrg ops[opi++] = d[si];
349436ac495dSmrg ops[opi++] = s[si];
349536ac495dSmrg }
349636ac495dSmrg else
349736ac495dSmrg for (si = parts - 1; si >= 0; si--)
349836ac495dSmrg {
349936ac495dSmrg ops[opi++] = d[si];
350036ac495dSmrg ops[opi++] = s[si];
350136ac495dSmrg }
350236ac495dSmrg rv = 1;
350336ac495dSmrg }
350436ac495dSmrg /* Now emit any moves we may have accumulated. */
350536ac495dSmrg if (rv && split_all != 3)
350636ac495dSmrg {
350736ac495dSmrg int i;
350836ac495dSmrg for (i = 2; i < opi; i += 2)
350936ac495dSmrg emit_move_insn (ops[i], ops[i + 1]);
351036ac495dSmrg }
351136ac495dSmrg return rv;
351236ac495dSmrg }
351336ac495dSmrg
351436ac495dSmrg /* The m32c has a number of opcodes that act like memcpy, strcmp, and
351536ac495dSmrg the like. For the R8C they expect one of the addresses to be in
351636ac495dSmrg R1L:An so we need to arrange for that. Otherwise, it's just a
351736ac495dSmrg matter of picking out the operands we want and emitting the right
351836ac495dSmrg pattern for them. All these expanders, which correspond to
351936ac495dSmrg patterns in blkmov.md, must return nonzero if they expand the insn,
352036ac495dSmrg or zero if they should FAIL. */
352136ac495dSmrg
352236ac495dSmrg /* This is a memset() opcode. All operands are implied, so we need to
352336ac495dSmrg arrange for them to be in the right registers. The opcode wants
352436ac495dSmrg addresses, not [mem] syntax. $0 is the destination (MEM:BLK), $1
352536ac495dSmrg the count (HI), and $2 the value (QI). */
352636ac495dSmrg int
m32c_expand_setmemhi(rtx * operands)352736ac495dSmrg m32c_expand_setmemhi(rtx *operands)
352836ac495dSmrg {
352936ac495dSmrg rtx desta, count, val;
353036ac495dSmrg rtx desto, counto;
353136ac495dSmrg
353236ac495dSmrg desta = XEXP (operands[0], 0);
353336ac495dSmrg count = operands[1];
353436ac495dSmrg val = operands[2];
353536ac495dSmrg
353636ac495dSmrg desto = gen_reg_rtx (Pmode);
353736ac495dSmrg counto = gen_reg_rtx (HImode);
353836ac495dSmrg
353936ac495dSmrg if (GET_CODE (desta) != REG
354036ac495dSmrg || REGNO (desta) < FIRST_PSEUDO_REGISTER)
354136ac495dSmrg desta = copy_to_mode_reg (Pmode, desta);
354236ac495dSmrg
354336ac495dSmrg /* This looks like an arbitrary restriction, but this is by far the
354436ac495dSmrg most common case. For counts 8..14 this actually results in
354536ac495dSmrg smaller code with no speed penalty because the half-sized
354636ac495dSmrg constant can be loaded with a shorter opcode. */
354736ac495dSmrg if (GET_CODE (count) == CONST_INT
354836ac495dSmrg && GET_CODE (val) == CONST_INT
354936ac495dSmrg && ! (INTVAL (count) & 1)
355036ac495dSmrg && (INTVAL (count) > 1)
355136ac495dSmrg && (INTVAL (val) <= 7 && INTVAL (val) >= -8))
355236ac495dSmrg {
355336ac495dSmrg unsigned v = INTVAL (val) & 0xff;
355436ac495dSmrg v = v | (v << 8);
355536ac495dSmrg count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
355636ac495dSmrg val = copy_to_mode_reg (HImode, GEN_INT (v));
355736ac495dSmrg if (TARGET_A16)
355836ac495dSmrg emit_insn (gen_setmemhi_whi_op (desto, counto, val, desta, count));
355936ac495dSmrg else
356036ac495dSmrg emit_insn (gen_setmemhi_wpsi_op (desto, counto, val, desta, count));
356136ac495dSmrg return 1;
356236ac495dSmrg }
356336ac495dSmrg
356436ac495dSmrg /* This is the generalized memset() case. */
356536ac495dSmrg if (GET_CODE (val) != REG
356636ac495dSmrg || REGNO (val) < FIRST_PSEUDO_REGISTER)
356736ac495dSmrg val = copy_to_mode_reg (QImode, val);
356836ac495dSmrg
356936ac495dSmrg if (GET_CODE (count) != REG
357036ac495dSmrg || REGNO (count) < FIRST_PSEUDO_REGISTER)
357136ac495dSmrg count = copy_to_mode_reg (HImode, count);
357236ac495dSmrg
357336ac495dSmrg if (TARGET_A16)
357436ac495dSmrg emit_insn (gen_setmemhi_bhi_op (desto, counto, val, desta, count));
357536ac495dSmrg else
357636ac495dSmrg emit_insn (gen_setmemhi_bpsi_op (desto, counto, val, desta, count));
357736ac495dSmrg
357836ac495dSmrg return 1;
357936ac495dSmrg }
358036ac495dSmrg
358136ac495dSmrg /* This is a memcpy() opcode. All operands are implied, so we need to
358236ac495dSmrg arrange for them to be in the right registers. The opcode wants
358336ac495dSmrg addresses, not [mem] syntax. $0 is the destination (MEM:BLK), $1
358436ac495dSmrg is the source (MEM:BLK), and $2 the count (HI). */
358536ac495dSmrg int
m32c_expand_cpymemhi(rtx * operands)3586*8feb0f0bSmrg m32c_expand_cpymemhi(rtx *operands)
358736ac495dSmrg {
358836ac495dSmrg rtx desta, srca, count;
358936ac495dSmrg rtx desto, srco, counto;
359036ac495dSmrg
359136ac495dSmrg desta = XEXP (operands[0], 0);
359236ac495dSmrg srca = XEXP (operands[1], 0);
359336ac495dSmrg count = operands[2];
359436ac495dSmrg
359536ac495dSmrg desto = gen_reg_rtx (Pmode);
359636ac495dSmrg srco = gen_reg_rtx (Pmode);
359736ac495dSmrg counto = gen_reg_rtx (HImode);
359836ac495dSmrg
359936ac495dSmrg if (GET_CODE (desta) != REG
360036ac495dSmrg || REGNO (desta) < FIRST_PSEUDO_REGISTER)
360136ac495dSmrg desta = copy_to_mode_reg (Pmode, desta);
360236ac495dSmrg
360336ac495dSmrg if (GET_CODE (srca) != REG
360436ac495dSmrg || REGNO (srca) < FIRST_PSEUDO_REGISTER)
360536ac495dSmrg srca = copy_to_mode_reg (Pmode, srca);
360636ac495dSmrg
360736ac495dSmrg /* Similar to setmem, but we don't need to check the value. */
360836ac495dSmrg if (GET_CODE (count) == CONST_INT
360936ac495dSmrg && ! (INTVAL (count) & 1)
361036ac495dSmrg && (INTVAL (count) > 1))
361136ac495dSmrg {
361236ac495dSmrg count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
361336ac495dSmrg if (TARGET_A16)
3614*8feb0f0bSmrg emit_insn (gen_cpymemhi_whi_op (desto, srco, counto, desta, srca, count));
361536ac495dSmrg else
3616*8feb0f0bSmrg emit_insn (gen_cpymemhi_wpsi_op (desto, srco, counto, desta, srca, count));
361736ac495dSmrg return 1;
361836ac495dSmrg }
361936ac495dSmrg
362036ac495dSmrg /* This is the generalized memset() case. */
362136ac495dSmrg if (GET_CODE (count) != REG
362236ac495dSmrg || REGNO (count) < FIRST_PSEUDO_REGISTER)
362336ac495dSmrg count = copy_to_mode_reg (HImode, count);
362436ac495dSmrg
362536ac495dSmrg if (TARGET_A16)
3626*8feb0f0bSmrg emit_insn (gen_cpymemhi_bhi_op (desto, srco, counto, desta, srca, count));
362736ac495dSmrg else
3628*8feb0f0bSmrg emit_insn (gen_cpymemhi_bpsi_op (desto, srco, counto, desta, srca, count));
362936ac495dSmrg
363036ac495dSmrg return 1;
363136ac495dSmrg }
363236ac495dSmrg
363336ac495dSmrg /* This is a stpcpy() opcode. $0 is the destination (MEM:BLK) after
363436ac495dSmrg the copy, which should point to the NUL at the end of the string,
363536ac495dSmrg $1 is the destination (MEM:BLK), and $2 is the source (MEM:BLK).
363636ac495dSmrg Since our opcode leaves the destination pointing *after* the NUL,
363736ac495dSmrg we must emit an adjustment. */
363836ac495dSmrg int
m32c_expand_movstr(rtx * operands)363936ac495dSmrg m32c_expand_movstr(rtx *operands)
364036ac495dSmrg {
364136ac495dSmrg rtx desta, srca;
364236ac495dSmrg rtx desto, srco;
364336ac495dSmrg
364436ac495dSmrg desta = XEXP (operands[1], 0);
364536ac495dSmrg srca = XEXP (operands[2], 0);
364636ac495dSmrg
364736ac495dSmrg desto = gen_reg_rtx (Pmode);
364836ac495dSmrg srco = gen_reg_rtx (Pmode);
364936ac495dSmrg
365036ac495dSmrg if (GET_CODE (desta) != REG
365136ac495dSmrg || REGNO (desta) < FIRST_PSEUDO_REGISTER)
365236ac495dSmrg desta = copy_to_mode_reg (Pmode, desta);
365336ac495dSmrg
365436ac495dSmrg if (GET_CODE (srca) != REG
365536ac495dSmrg || REGNO (srca) < FIRST_PSEUDO_REGISTER)
365636ac495dSmrg srca = copy_to_mode_reg (Pmode, srca);
365736ac495dSmrg
365836ac495dSmrg emit_insn (gen_movstr_op (desto, srco, desta, srca));
365936ac495dSmrg /* desto ends up being a1, which allows this type of add through MOVA. */
366036ac495dSmrg emit_insn (gen_addpsi3 (operands[0], desto, GEN_INT (-1)));
366136ac495dSmrg
366236ac495dSmrg return 1;
366336ac495dSmrg }
366436ac495dSmrg
366536ac495dSmrg /* This is a strcmp() opcode. $0 is the destination (HI) which holds
366636ac495dSmrg <=>0 depending on the comparison, $1 is one string (MEM:BLK), and
366736ac495dSmrg $2 is the other (MEM:BLK). We must do the comparison, and then
366836ac495dSmrg convert the flags to a signed integer result. */
366936ac495dSmrg int
m32c_expand_cmpstr(rtx * operands)367036ac495dSmrg m32c_expand_cmpstr(rtx *operands)
367136ac495dSmrg {
367236ac495dSmrg rtx src1a, src2a;
367336ac495dSmrg
367436ac495dSmrg src1a = XEXP (operands[1], 0);
367536ac495dSmrg src2a = XEXP (operands[2], 0);
367636ac495dSmrg
367736ac495dSmrg if (GET_CODE (src1a) != REG
367836ac495dSmrg || REGNO (src1a) < FIRST_PSEUDO_REGISTER)
367936ac495dSmrg src1a = copy_to_mode_reg (Pmode, src1a);
368036ac495dSmrg
368136ac495dSmrg if (GET_CODE (src2a) != REG
368236ac495dSmrg || REGNO (src2a) < FIRST_PSEUDO_REGISTER)
368336ac495dSmrg src2a = copy_to_mode_reg (Pmode, src2a);
368436ac495dSmrg
368536ac495dSmrg emit_insn (gen_cmpstrhi_op (src1a, src2a, src1a, src2a));
368636ac495dSmrg emit_insn (gen_cond_to_int (operands[0]));
368736ac495dSmrg
368836ac495dSmrg return 1;
368936ac495dSmrg }
369036ac495dSmrg
369136ac495dSmrg
369236ac495dSmrg typedef rtx (*shift_gen_func)(rtx, rtx, rtx);
369336ac495dSmrg
369436ac495dSmrg static shift_gen_func
shift_gen_func_for(int mode,int code)369536ac495dSmrg shift_gen_func_for (int mode, int code)
369636ac495dSmrg {
369736ac495dSmrg #define GFF(m,c,f) if (mode == m && code == c) return f
369836ac495dSmrg GFF(QImode, ASHIFT, gen_ashlqi3_i);
369936ac495dSmrg GFF(QImode, ASHIFTRT, gen_ashrqi3_i);
370036ac495dSmrg GFF(QImode, LSHIFTRT, gen_lshrqi3_i);
370136ac495dSmrg GFF(HImode, ASHIFT, gen_ashlhi3_i);
370236ac495dSmrg GFF(HImode, ASHIFTRT, gen_ashrhi3_i);
370336ac495dSmrg GFF(HImode, LSHIFTRT, gen_lshrhi3_i);
370436ac495dSmrg GFF(PSImode, ASHIFT, gen_ashlpsi3_i);
370536ac495dSmrg GFF(PSImode, ASHIFTRT, gen_ashrpsi3_i);
370636ac495dSmrg GFF(PSImode, LSHIFTRT, gen_lshrpsi3_i);
370736ac495dSmrg GFF(SImode, ASHIFT, TARGET_A16 ? gen_ashlsi3_16 : gen_ashlsi3_24);
370836ac495dSmrg GFF(SImode, ASHIFTRT, TARGET_A16 ? gen_ashrsi3_16 : gen_ashrsi3_24);
370936ac495dSmrg GFF(SImode, LSHIFTRT, TARGET_A16 ? gen_lshrsi3_16 : gen_lshrsi3_24);
371036ac495dSmrg #undef GFF
371136ac495dSmrg gcc_unreachable ();
371236ac495dSmrg }
371336ac495dSmrg
371436ac495dSmrg /* The m32c only has one shift, but it takes a signed count. GCC
371536ac495dSmrg doesn't want this, so we fake it by negating any shift count when
371636ac495dSmrg we're pretending to shift the other way. Also, the shift count is
371736ac495dSmrg limited to -8..8. It's slightly better to use two shifts for 9..15
371836ac495dSmrg than to load the count into r1h, so we do that too. */
371936ac495dSmrg int
m32c_prepare_shift(rtx * operands,int scale,int shift_code)372036ac495dSmrg m32c_prepare_shift (rtx * operands, int scale, int shift_code)
372136ac495dSmrg {
372236ac495dSmrg machine_mode mode = GET_MODE (operands[0]);
372336ac495dSmrg shift_gen_func func = shift_gen_func_for (mode, shift_code);
372436ac495dSmrg rtx temp;
372536ac495dSmrg
372636ac495dSmrg if (GET_CODE (operands[2]) == CONST_INT)
372736ac495dSmrg {
372836ac495dSmrg int maxc = TARGET_A24 && (mode == PSImode || mode == SImode) ? 32 : 8;
372936ac495dSmrg int count = INTVAL (operands[2]) * scale;
373036ac495dSmrg
373136ac495dSmrg while (count > maxc)
373236ac495dSmrg {
373336ac495dSmrg temp = gen_reg_rtx (mode);
373436ac495dSmrg emit_insn (func (temp, operands[1], GEN_INT (maxc)));
373536ac495dSmrg operands[1] = temp;
373636ac495dSmrg count -= maxc;
373736ac495dSmrg }
373836ac495dSmrg while (count < -maxc)
373936ac495dSmrg {
374036ac495dSmrg temp = gen_reg_rtx (mode);
374136ac495dSmrg emit_insn (func (temp, operands[1], GEN_INT (-maxc)));
374236ac495dSmrg operands[1] = temp;
374336ac495dSmrg count += maxc;
374436ac495dSmrg }
374536ac495dSmrg emit_insn (func (operands[0], operands[1], GEN_INT (count)));
374636ac495dSmrg return 1;
374736ac495dSmrg }
374836ac495dSmrg
374936ac495dSmrg temp = gen_reg_rtx (QImode);
375036ac495dSmrg if (scale < 0)
375136ac495dSmrg /* The pattern has a NEG that corresponds to this. */
375236ac495dSmrg emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2]));
375336ac495dSmrg else if (TARGET_A16 && mode == SImode)
375436ac495dSmrg /* We do this because the code below may modify this, we don't
375536ac495dSmrg want to modify the origin of this value. */
375636ac495dSmrg emit_move_insn (temp, operands[2]);
375736ac495dSmrg else
375836ac495dSmrg /* We'll only use it for the shift, no point emitting a move. */
375936ac495dSmrg temp = operands[2];
376036ac495dSmrg
376136ac495dSmrg if (TARGET_A16 && GET_MODE_SIZE (mode) == 4)
376236ac495dSmrg {
376336ac495dSmrg /* The m16c has a limit of -16..16 for SI shifts, even when the
376436ac495dSmrg shift count is in a register. Since there are so many targets
376536ac495dSmrg of these shifts, it's better to expand the RTL here than to
376636ac495dSmrg call a helper function.
376736ac495dSmrg
376836ac495dSmrg The resulting code looks something like this:
376936ac495dSmrg
377036ac495dSmrg cmp.b r1h,-16
377136ac495dSmrg jge.b 1f
377236ac495dSmrg shl.l -16,dest
377336ac495dSmrg add.b r1h,16
377436ac495dSmrg 1f: cmp.b r1h,16
377536ac495dSmrg jle.b 1f
377636ac495dSmrg shl.l 16,dest
377736ac495dSmrg sub.b r1h,16
377836ac495dSmrg 1f: shl.l r1h,dest
377936ac495dSmrg
378036ac495dSmrg We take advantage of the fact that "negative" shifts are
378136ac495dSmrg undefined to skip one of the comparisons. */
378236ac495dSmrg
378336ac495dSmrg rtx count;
378436ac495dSmrg rtx tempvar;
378536ac495dSmrg rtx_insn *insn;
378636ac495dSmrg
378736ac495dSmrg emit_move_insn (operands[0], operands[1]);
378836ac495dSmrg
378936ac495dSmrg count = temp;
379036ac495dSmrg rtx_code_label *label = gen_label_rtx ();
379136ac495dSmrg LABEL_NUSES (label) ++;
379236ac495dSmrg
379336ac495dSmrg tempvar = gen_reg_rtx (mode);
379436ac495dSmrg
379536ac495dSmrg if (shift_code == ASHIFT)
379636ac495dSmrg {
379736ac495dSmrg /* This is a left shift. We only need check positive counts. */
379836ac495dSmrg emit_jump_insn (gen_cbranchqi4 (gen_rtx_LE (VOIDmode, 0, 0),
379936ac495dSmrg count, GEN_INT (16), label));
380036ac495dSmrg emit_insn (func (tempvar, operands[0], GEN_INT (8)));
380136ac495dSmrg emit_insn (func (operands[0], tempvar, GEN_INT (8)));
380236ac495dSmrg insn = emit_insn (gen_addqi3 (count, count, GEN_INT (-16)));
380336ac495dSmrg emit_label_after (label, insn);
380436ac495dSmrg }
380536ac495dSmrg else
380636ac495dSmrg {
380736ac495dSmrg /* This is a right shift. We only need check negative counts. */
380836ac495dSmrg emit_jump_insn (gen_cbranchqi4 (gen_rtx_GE (VOIDmode, 0, 0),
380936ac495dSmrg count, GEN_INT (-16), label));
381036ac495dSmrg emit_insn (func (tempvar, operands[0], GEN_INT (-8)));
381136ac495dSmrg emit_insn (func (operands[0], tempvar, GEN_INT (-8)));
381236ac495dSmrg insn = emit_insn (gen_addqi3 (count, count, GEN_INT (16)));
381336ac495dSmrg emit_label_after (label, insn);
381436ac495dSmrg }
381536ac495dSmrg operands[1] = operands[0];
381636ac495dSmrg emit_insn (func (operands[0], operands[0], count));
381736ac495dSmrg return 1;
381836ac495dSmrg }
381936ac495dSmrg
382036ac495dSmrg operands[2] = temp;
382136ac495dSmrg return 0;
382236ac495dSmrg }
382336ac495dSmrg
382436ac495dSmrg /* The m32c has a limited range of operations that work on PSImode
382536ac495dSmrg values; we have to expand to SI, do the math, and truncate back to
382636ac495dSmrg PSI. Yes, this is expensive, but hopefully gcc will learn to avoid
382736ac495dSmrg those cases. */
382836ac495dSmrg void
m32c_expand_neg_mulpsi3(rtx * operands)382936ac495dSmrg m32c_expand_neg_mulpsi3 (rtx * operands)
383036ac495dSmrg {
383136ac495dSmrg /* operands: a = b * i */
383236ac495dSmrg rtx temp1; /* b as SI */
383336ac495dSmrg rtx scale /* i as SI */;
383436ac495dSmrg rtx temp2; /* a*b as SI */
383536ac495dSmrg
383636ac495dSmrg temp1 = gen_reg_rtx (SImode);
383736ac495dSmrg temp2 = gen_reg_rtx (SImode);
383836ac495dSmrg if (GET_CODE (operands[2]) != CONST_INT)
383936ac495dSmrg {
384036ac495dSmrg scale = gen_reg_rtx (SImode);
384136ac495dSmrg emit_insn (gen_zero_extendpsisi2 (scale, operands[2]));
384236ac495dSmrg }
384336ac495dSmrg else
384436ac495dSmrg scale = copy_to_mode_reg (SImode, operands[2]);
384536ac495dSmrg
384636ac495dSmrg emit_insn (gen_zero_extendpsisi2 (temp1, operands[1]));
384736ac495dSmrg temp2 = expand_simple_binop (SImode, MULT, temp1, scale, temp2, 1, OPTAB_LIB);
384836ac495dSmrg emit_insn (gen_truncsipsi2 (operands[0], temp2));
384936ac495dSmrg }
385036ac495dSmrg
385136ac495dSmrg /* Pattern Output Functions */
385236ac495dSmrg
385336ac495dSmrg int
m32c_expand_movcc(rtx * operands)385436ac495dSmrg m32c_expand_movcc (rtx *operands)
385536ac495dSmrg {
385636ac495dSmrg rtx rel = operands[1];
385736ac495dSmrg
385836ac495dSmrg if (GET_CODE (rel) != EQ && GET_CODE (rel) != NE)
385936ac495dSmrg return 1;
386036ac495dSmrg if (GET_CODE (operands[2]) != CONST_INT
386136ac495dSmrg || GET_CODE (operands[3]) != CONST_INT)
386236ac495dSmrg return 1;
386336ac495dSmrg if (GET_CODE (rel) == NE)
386436ac495dSmrg {
386536ac495dSmrg rtx tmp = operands[2];
386636ac495dSmrg operands[2] = operands[3];
386736ac495dSmrg operands[3] = tmp;
386836ac495dSmrg rel = gen_rtx_EQ (GET_MODE (rel), XEXP (rel, 0), XEXP (rel, 1));
386936ac495dSmrg }
387036ac495dSmrg
387136ac495dSmrg emit_move_insn (operands[0],
387236ac495dSmrg gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
387336ac495dSmrg rel,
387436ac495dSmrg operands[2],
387536ac495dSmrg operands[3]));
387636ac495dSmrg return 0;
387736ac495dSmrg }
387836ac495dSmrg
387936ac495dSmrg /* Used for the "insv" pattern. Return nonzero to fail, else done. */
388036ac495dSmrg int
m32c_expand_insv(rtx * operands)388136ac495dSmrg m32c_expand_insv (rtx *operands)
388236ac495dSmrg {
388336ac495dSmrg rtx op0, src0, p;
388436ac495dSmrg int mask;
388536ac495dSmrg
388636ac495dSmrg if (INTVAL (operands[1]) != 1)
388736ac495dSmrg return 1;
388836ac495dSmrg
388936ac495dSmrg /* Our insv opcode (bset, bclr) can only insert a one-bit constant. */
389036ac495dSmrg if (GET_CODE (operands[3]) != CONST_INT)
389136ac495dSmrg return 1;
389236ac495dSmrg if (INTVAL (operands[3]) != 0
389336ac495dSmrg && INTVAL (operands[3]) != 1
389436ac495dSmrg && INTVAL (operands[3]) != -1)
389536ac495dSmrg return 1;
389636ac495dSmrg
389736ac495dSmrg mask = 1 << INTVAL (operands[2]);
389836ac495dSmrg
389936ac495dSmrg op0 = operands[0];
390036ac495dSmrg if (GET_CODE (op0) == SUBREG
390136ac495dSmrg && SUBREG_BYTE (op0) == 0)
390236ac495dSmrg {
390336ac495dSmrg rtx sub = SUBREG_REG (op0);
390436ac495dSmrg if (GET_MODE (sub) == HImode || GET_MODE (sub) == QImode)
390536ac495dSmrg op0 = sub;
390636ac495dSmrg }
390736ac495dSmrg
390836ac495dSmrg if (!can_create_pseudo_p ()
390936ac495dSmrg || (GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)))
391036ac495dSmrg src0 = op0;
391136ac495dSmrg else
391236ac495dSmrg {
391336ac495dSmrg src0 = gen_reg_rtx (GET_MODE (op0));
391436ac495dSmrg emit_move_insn (src0, op0);
391536ac495dSmrg }
391636ac495dSmrg
391736ac495dSmrg if (GET_MODE (op0) == HImode
391836ac495dSmrg && INTVAL (operands[2]) >= 8
391936ac495dSmrg && GET_CODE (op0) == MEM)
392036ac495dSmrg {
392136ac495dSmrg /* We are little endian. */
392236ac495dSmrg rtx new_mem = gen_rtx_MEM (QImode, plus_constant (Pmode,
392336ac495dSmrg XEXP (op0, 0), 1));
392436ac495dSmrg MEM_COPY_ATTRIBUTES (new_mem, op0);
392536ac495dSmrg mask >>= 8;
392636ac495dSmrg }
392736ac495dSmrg
392836ac495dSmrg /* First, we generate a mask with the correct polarity. If we are
392936ac495dSmrg storing a zero, we want an AND mask, so invert it. */
393036ac495dSmrg if (INTVAL (operands[3]) == 0)
393136ac495dSmrg {
393236ac495dSmrg /* Storing a zero, use an AND mask */
393336ac495dSmrg if (GET_MODE (op0) == HImode)
393436ac495dSmrg mask ^= 0xffff;
393536ac495dSmrg else
393636ac495dSmrg mask ^= 0xff;
393736ac495dSmrg }
393836ac495dSmrg /* Now we need to properly sign-extend the mask in case we need to
393936ac495dSmrg fall back to an AND or OR opcode. */
394036ac495dSmrg if (GET_MODE (op0) == HImode)
394136ac495dSmrg {
394236ac495dSmrg if (mask & 0x8000)
394336ac495dSmrg mask -= 0x10000;
394436ac495dSmrg }
394536ac495dSmrg else
394636ac495dSmrg {
394736ac495dSmrg if (mask & 0x80)
394836ac495dSmrg mask -= 0x100;
394936ac495dSmrg }
395036ac495dSmrg
395136ac495dSmrg switch ( (INTVAL (operands[3]) ? 4 : 0)
395236ac495dSmrg + ((GET_MODE (op0) == HImode) ? 2 : 0)
395336ac495dSmrg + (TARGET_A24 ? 1 : 0))
395436ac495dSmrg {
395536ac495dSmrg case 0: p = gen_andqi3_16 (op0, src0, GEN_INT (mask)); break;
395636ac495dSmrg case 1: p = gen_andqi3_24 (op0, src0, GEN_INT (mask)); break;
395736ac495dSmrg case 2: p = gen_andhi3_16 (op0, src0, GEN_INT (mask)); break;
395836ac495dSmrg case 3: p = gen_andhi3_24 (op0, src0, GEN_INT (mask)); break;
395936ac495dSmrg case 4: p = gen_iorqi3_16 (op0, src0, GEN_INT (mask)); break;
396036ac495dSmrg case 5: p = gen_iorqi3_24 (op0, src0, GEN_INT (mask)); break;
396136ac495dSmrg case 6: p = gen_iorhi3_16 (op0, src0, GEN_INT (mask)); break;
396236ac495dSmrg case 7: p = gen_iorhi3_24 (op0, src0, GEN_INT (mask)); break;
396336ac495dSmrg default: p = NULL_RTX; break; /* Not reached, but silences a warning. */
396436ac495dSmrg }
396536ac495dSmrg
396636ac495dSmrg emit_insn (p);
396736ac495dSmrg return 0;
396836ac495dSmrg }
396936ac495dSmrg
397036ac495dSmrg const char *
m32c_scc_pattern(rtx * operands,RTX_CODE code)397136ac495dSmrg m32c_scc_pattern(rtx *operands, RTX_CODE code)
397236ac495dSmrg {
397336ac495dSmrg static char buf[30];
397436ac495dSmrg if (GET_CODE (operands[0]) == REG
397536ac495dSmrg && REGNO (operands[0]) == R0_REGNO)
397636ac495dSmrg {
397736ac495dSmrg if (code == EQ)
397836ac495dSmrg return "stzx\t#1,#0,r0l";
397936ac495dSmrg if (code == NE)
398036ac495dSmrg return "stzx\t#0,#1,r0l";
398136ac495dSmrg }
398236ac495dSmrg sprintf(buf, "bm%s\t0,%%h0\n\tand.b\t#1,%%0", GET_RTX_NAME (code));
398336ac495dSmrg return buf;
398436ac495dSmrg }
398536ac495dSmrg
398636ac495dSmrg /* Encode symbol attributes of a SYMBOL_REF into its
398736ac495dSmrg SYMBOL_REF_FLAGS. */
398836ac495dSmrg static void
m32c_encode_section_info(tree decl,rtx rtl,int first)398936ac495dSmrg m32c_encode_section_info (tree decl, rtx rtl, int first)
399036ac495dSmrg {
399136ac495dSmrg int extra_flags = 0;
399236ac495dSmrg
399336ac495dSmrg default_encode_section_info (decl, rtl, first);
399436ac495dSmrg if (TREE_CODE (decl) == FUNCTION_DECL
399536ac495dSmrg && m32c_special_page_vector_p (decl))
399636ac495dSmrg
399736ac495dSmrg extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
399836ac495dSmrg
399936ac495dSmrg if (extra_flags)
400036ac495dSmrg SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
400136ac495dSmrg }
400236ac495dSmrg
400336ac495dSmrg /* Returns TRUE if the current function is a leaf, and thus we can
400436ac495dSmrg determine which registers an interrupt function really needs to
400536ac495dSmrg save. The logic below is mostly about finding the insn sequence
400636ac495dSmrg that's the function, versus any sequence that might be open for the
400736ac495dSmrg current insn. */
400836ac495dSmrg static int
m32c_leaf_function_p(void)400936ac495dSmrg m32c_leaf_function_p (void)
401036ac495dSmrg {
401136ac495dSmrg int rv;
401236ac495dSmrg
401336ac495dSmrg push_topmost_sequence ();
401436ac495dSmrg rv = leaf_function_p ();
401536ac495dSmrg pop_topmost_sequence ();
401636ac495dSmrg return rv;
401736ac495dSmrg }
401836ac495dSmrg
401936ac495dSmrg /* Returns TRUE if the current function needs to use the ENTER/EXIT
402036ac495dSmrg opcodes. If the function doesn't need the frame base or stack
402136ac495dSmrg pointer, it can use the simpler RTS opcode. */
402236ac495dSmrg static bool
m32c_function_needs_enter(void)402336ac495dSmrg m32c_function_needs_enter (void)
402436ac495dSmrg {
402536ac495dSmrg rtx_insn *insn;
402636ac495dSmrg rtx sp = gen_rtx_REG (Pmode, SP_REGNO);
402736ac495dSmrg rtx fb = gen_rtx_REG (Pmode, FB_REGNO);
402836ac495dSmrg
402936ac495dSmrg for (insn = get_topmost_sequence ()->first; insn; insn = NEXT_INSN (insn))
403036ac495dSmrg if (NONDEBUG_INSN_P (insn))
403136ac495dSmrg {
403236ac495dSmrg if (reg_mentioned_p (sp, insn))
403336ac495dSmrg return true;
403436ac495dSmrg if (reg_mentioned_p (fb, insn))
403536ac495dSmrg return true;
403636ac495dSmrg }
403736ac495dSmrg return false;
403836ac495dSmrg }
403936ac495dSmrg
404036ac495dSmrg /* Mark all the subexpressions of the PARALLEL rtx PAR as
404136ac495dSmrg frame-related. Return PAR.
404236ac495dSmrg
404336ac495dSmrg dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a
404436ac495dSmrg PARALLEL rtx other than the first if they do not have the
404536ac495dSmrg FRAME_RELATED flag set on them. So this function is handy for
404636ac495dSmrg marking up 'enter' instructions. */
404736ac495dSmrg static rtx
m32c_all_frame_related(rtx par)404836ac495dSmrg m32c_all_frame_related (rtx par)
404936ac495dSmrg {
405036ac495dSmrg int len = XVECLEN (par, 0);
405136ac495dSmrg int i;
405236ac495dSmrg
405336ac495dSmrg for (i = 0; i < len; i++)
405436ac495dSmrg F (XVECEXP (par, 0, i));
405536ac495dSmrg
405636ac495dSmrg return par;
405736ac495dSmrg }
405836ac495dSmrg
405936ac495dSmrg /* Emits the prologue. See the frame layout comment earlier in this
406036ac495dSmrg file. We can reserve up to 256 bytes with the ENTER opcode, beyond
406136ac495dSmrg that we manually update sp. */
406236ac495dSmrg void
m32c_emit_prologue(void)406336ac495dSmrg m32c_emit_prologue (void)
406436ac495dSmrg {
406536ac495dSmrg int frame_size, extra_frame_size = 0, reg_save_size;
406636ac495dSmrg int complex_prologue = 0;
406736ac495dSmrg
406836ac495dSmrg cfun->machine->is_leaf = m32c_leaf_function_p ();
406936ac495dSmrg if (interrupt_p (cfun->decl))
407036ac495dSmrg {
407136ac495dSmrg cfun->machine->is_interrupt = 1;
407236ac495dSmrg complex_prologue = 1;
407336ac495dSmrg }
407436ac495dSmrg else if (bank_switch_p (cfun->decl))
407536ac495dSmrg warning (OPT_Wattributes,
407636ac495dSmrg "%<bank_switch%> has no effect on non-interrupt functions");
407736ac495dSmrg
407836ac495dSmrg reg_save_size = m32c_pushm_popm (PP_justcount);
407936ac495dSmrg
408036ac495dSmrg if (interrupt_p (cfun->decl))
408136ac495dSmrg {
408236ac495dSmrg if (bank_switch_p (cfun->decl))
408336ac495dSmrg emit_insn (gen_fset_b ());
408436ac495dSmrg else if (cfun->machine->intr_pushm)
408536ac495dSmrg emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
408636ac495dSmrg }
408736ac495dSmrg
408836ac495dSmrg frame_size =
408936ac495dSmrg m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size;
409036ac495dSmrg if (frame_size == 0
409136ac495dSmrg && !m32c_function_needs_enter ())
409236ac495dSmrg cfun->machine->use_rts = 1;
409336ac495dSmrg
409436ac495dSmrg if (flag_stack_usage_info)
409536ac495dSmrg current_function_static_stack_size = frame_size;
409636ac495dSmrg
409736ac495dSmrg if (frame_size > 254)
409836ac495dSmrg {
409936ac495dSmrg extra_frame_size = frame_size - 254;
410036ac495dSmrg frame_size = 254;
410136ac495dSmrg }
410236ac495dSmrg if (cfun->machine->use_rts == 0)
410336ac495dSmrg F (emit_insn (m32c_all_frame_related
410436ac495dSmrg (TARGET_A16
410536ac495dSmrg ? gen_prologue_enter_16 (GEN_INT (frame_size + 2))
410636ac495dSmrg : gen_prologue_enter_24 (GEN_INT (frame_size + 4)))));
410736ac495dSmrg
410836ac495dSmrg if (extra_frame_size)
410936ac495dSmrg {
411036ac495dSmrg complex_prologue = 1;
411136ac495dSmrg if (TARGET_A16)
411236ac495dSmrg F (emit_insn (gen_addhi3 (gen_rtx_REG (HImode, SP_REGNO),
411336ac495dSmrg gen_rtx_REG (HImode, SP_REGNO),
411436ac495dSmrg GEN_INT (-extra_frame_size))));
411536ac495dSmrg else
411636ac495dSmrg F (emit_insn (gen_addpsi3 (gen_rtx_REG (PSImode, SP_REGNO),
411736ac495dSmrg gen_rtx_REG (PSImode, SP_REGNO),
411836ac495dSmrg GEN_INT (-extra_frame_size))));
411936ac495dSmrg }
412036ac495dSmrg
412136ac495dSmrg complex_prologue += m32c_pushm_popm (PP_pushm);
412236ac495dSmrg
412336ac495dSmrg /* This just emits a comment into the .s file for debugging. */
412436ac495dSmrg if (complex_prologue)
412536ac495dSmrg emit_insn (gen_prologue_end ());
412636ac495dSmrg }
412736ac495dSmrg
412836ac495dSmrg /* Likewise, for the epilogue. The only exception is that, for
412936ac495dSmrg interrupts, we must manually unwind the frame as the REIT opcode
413036ac495dSmrg doesn't do that. */
413136ac495dSmrg void
m32c_emit_epilogue(void)413236ac495dSmrg m32c_emit_epilogue (void)
413336ac495dSmrg {
413436ac495dSmrg int popm_count = m32c_pushm_popm (PP_justcount);
413536ac495dSmrg
413636ac495dSmrg /* This just emits a comment into the .s file for debugging. */
413736ac495dSmrg if (popm_count > 0 || cfun->machine->is_interrupt)
413836ac495dSmrg emit_insn (gen_epilogue_start ());
413936ac495dSmrg
414036ac495dSmrg if (popm_count > 0)
414136ac495dSmrg m32c_pushm_popm (PP_popm);
414236ac495dSmrg
414336ac495dSmrg if (cfun->machine->is_interrupt)
414436ac495dSmrg {
414536ac495dSmrg machine_mode spmode = TARGET_A16 ? HImode : PSImode;
414636ac495dSmrg
414736ac495dSmrg /* REIT clears B flag and restores $fp for us, but we still
414836ac495dSmrg have to fix up the stack. USE_RTS just means we didn't
414936ac495dSmrg emit ENTER. */
415036ac495dSmrg if (!cfun->machine->use_rts)
415136ac495dSmrg {
415236ac495dSmrg emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
415336ac495dSmrg gen_rtx_REG (spmode, FP_REGNO));
415436ac495dSmrg emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
415536ac495dSmrg gen_rtx_REG (spmode, A0_REGNO));
415636ac495dSmrg /* We can't just add this to the POPM because it would be in
415736ac495dSmrg the wrong order, and wouldn't fix the stack if we're bank
415836ac495dSmrg switching. */
415936ac495dSmrg if (TARGET_A16)
416036ac495dSmrg emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
416136ac495dSmrg else
416236ac495dSmrg emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
416336ac495dSmrg }
416436ac495dSmrg if (!bank_switch_p (cfun->decl) && cfun->machine->intr_pushm)
416536ac495dSmrg emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
416636ac495dSmrg
416736ac495dSmrg /* The FREIT (Fast REturn from InTerrupt) instruction should be
416836ac495dSmrg generated only for M32C/M32CM targets (generate the REIT
416936ac495dSmrg instruction otherwise). */
417036ac495dSmrg if (fast_interrupt_p (cfun->decl))
417136ac495dSmrg {
417236ac495dSmrg /* Check if fast_attribute is set for M32C or M32CM. */
417336ac495dSmrg if (TARGET_A24)
417436ac495dSmrg {
417536ac495dSmrg emit_jump_insn (gen_epilogue_freit ());
417636ac495dSmrg }
417736ac495dSmrg /* If fast_interrupt attribute is set for an R8C or M16C
417836ac495dSmrg target ignore this attribute and generated REIT
417936ac495dSmrg instruction. */
418036ac495dSmrg else
418136ac495dSmrg {
418236ac495dSmrg warning (OPT_Wattributes,
418336ac495dSmrg "%<fast_interrupt%> attribute directive ignored");
418436ac495dSmrg emit_jump_insn (gen_epilogue_reit_16 ());
418536ac495dSmrg }
418636ac495dSmrg }
418736ac495dSmrg else if (TARGET_A16)
418836ac495dSmrg emit_jump_insn (gen_epilogue_reit_16 ());
418936ac495dSmrg else
419036ac495dSmrg emit_jump_insn (gen_epilogue_reit_24 ());
419136ac495dSmrg }
419236ac495dSmrg else if (cfun->machine->use_rts)
419336ac495dSmrg emit_jump_insn (gen_epilogue_rts ());
419436ac495dSmrg else if (TARGET_A16)
419536ac495dSmrg emit_jump_insn (gen_epilogue_exitd_16 ());
419636ac495dSmrg else
419736ac495dSmrg emit_jump_insn (gen_epilogue_exitd_24 ());
419836ac495dSmrg }
419936ac495dSmrg
420036ac495dSmrg void
m32c_emit_eh_epilogue(rtx ret_addr)420136ac495dSmrg m32c_emit_eh_epilogue (rtx ret_addr)
420236ac495dSmrg {
420336ac495dSmrg /* R0[R2] has the stack adjustment. R1[R3] has the address to
420436ac495dSmrg return to. We have to fudge the stack, pop everything, pop SP
420536ac495dSmrg (fudged), and return (fudged). This is actually easier to do in
420636ac495dSmrg assembler, so punt to libgcc. */
420736ac495dSmrg emit_jump_insn (gen_eh_epilogue (ret_addr, cfun->machine->eh_stack_adjust));
420836ac495dSmrg /* emit_clobber (gen_rtx_REG (HImode, R0L_REGNO)); */
420936ac495dSmrg }
421036ac495dSmrg
421136ac495dSmrg /* Indicate which flags must be properly set for a given conditional. */
421236ac495dSmrg static int
flags_needed_for_conditional(rtx cond)421336ac495dSmrg flags_needed_for_conditional (rtx cond)
421436ac495dSmrg {
421536ac495dSmrg switch (GET_CODE (cond))
421636ac495dSmrg {
421736ac495dSmrg case LE:
421836ac495dSmrg case GT:
421936ac495dSmrg return FLAGS_OSZ;
422036ac495dSmrg case LEU:
422136ac495dSmrg case GTU:
422236ac495dSmrg return FLAGS_ZC;
422336ac495dSmrg case LT:
422436ac495dSmrg case GE:
422536ac495dSmrg return FLAGS_OS;
422636ac495dSmrg case LTU:
422736ac495dSmrg case GEU:
422836ac495dSmrg return FLAGS_C;
422936ac495dSmrg case EQ:
423036ac495dSmrg case NE:
423136ac495dSmrg return FLAGS_Z;
423236ac495dSmrg default:
423336ac495dSmrg return FLAGS_N;
423436ac495dSmrg }
423536ac495dSmrg }
423636ac495dSmrg
423736ac495dSmrg #define DEBUG_CMP 0
423836ac495dSmrg
423936ac495dSmrg /* Returns true if a compare insn is redundant because it would only
424036ac495dSmrg set flags that are already set correctly. */
424136ac495dSmrg static bool
m32c_compare_redundant(rtx_insn * cmp,rtx * operands)424236ac495dSmrg m32c_compare_redundant (rtx_insn *cmp, rtx *operands)
424336ac495dSmrg {
424436ac495dSmrg int flags_needed;
424536ac495dSmrg int pflags;
424636ac495dSmrg rtx_insn *prev;
424736ac495dSmrg rtx pp, next;
424836ac495dSmrg rtx op0, op1;
424936ac495dSmrg #if DEBUG_CMP
425036ac495dSmrg int prev_icode, i;
425136ac495dSmrg #endif
425236ac495dSmrg
425336ac495dSmrg op0 = operands[0];
425436ac495dSmrg op1 = operands[1];
425536ac495dSmrg
425636ac495dSmrg #if DEBUG_CMP
425736ac495dSmrg fprintf(stderr, "\n\033[32mm32c_compare_redundant\033[0m\n");
425836ac495dSmrg debug_rtx(cmp);
425936ac495dSmrg for (i=0; i<2; i++)
426036ac495dSmrg {
426136ac495dSmrg fprintf(stderr, "operands[%d] = ", i);
426236ac495dSmrg debug_rtx(operands[i]);
426336ac495dSmrg }
426436ac495dSmrg #endif
426536ac495dSmrg
426636ac495dSmrg next = next_nonnote_insn (cmp);
426736ac495dSmrg if (!next || !INSN_P (next))
426836ac495dSmrg {
426936ac495dSmrg #if DEBUG_CMP
427036ac495dSmrg fprintf(stderr, "compare not followed by insn\n");
427136ac495dSmrg debug_rtx(next);
427236ac495dSmrg #endif
427336ac495dSmrg return false;
427436ac495dSmrg }
427536ac495dSmrg if (GET_CODE (PATTERN (next)) == SET
427636ac495dSmrg && GET_CODE (XEXP ( PATTERN (next), 1)) == IF_THEN_ELSE)
427736ac495dSmrg {
427836ac495dSmrg next = XEXP (XEXP (PATTERN (next), 1), 0);
427936ac495dSmrg }
428036ac495dSmrg else if (GET_CODE (PATTERN (next)) == SET)
428136ac495dSmrg {
428236ac495dSmrg /* If this is a conditional, flags_needed will be something
428336ac495dSmrg other than FLAGS_N, which we test below. */
428436ac495dSmrg next = XEXP (PATTERN (next), 1);
428536ac495dSmrg }
428636ac495dSmrg else
428736ac495dSmrg {
428836ac495dSmrg #if DEBUG_CMP
428936ac495dSmrg fprintf(stderr, "compare not followed by conditional\n");
429036ac495dSmrg debug_rtx(next);
429136ac495dSmrg #endif
429236ac495dSmrg return false;
429336ac495dSmrg }
429436ac495dSmrg #if DEBUG_CMP
429536ac495dSmrg fprintf(stderr, "conditional is: ");
429636ac495dSmrg debug_rtx(next);
429736ac495dSmrg #endif
429836ac495dSmrg
429936ac495dSmrg flags_needed = flags_needed_for_conditional (next);
430036ac495dSmrg if (flags_needed == FLAGS_N)
430136ac495dSmrg {
430236ac495dSmrg #if DEBUG_CMP
430336ac495dSmrg fprintf(stderr, "compare not followed by conditional\n");
430436ac495dSmrg debug_rtx(next);
430536ac495dSmrg #endif
430636ac495dSmrg return false;
430736ac495dSmrg }
430836ac495dSmrg
430936ac495dSmrg /* Compare doesn't set overflow and carry the same way that
431036ac495dSmrg arithmetic instructions do, so we can't replace those. */
431136ac495dSmrg if (flags_needed & FLAGS_OC)
431236ac495dSmrg return false;
431336ac495dSmrg
431436ac495dSmrg prev = cmp;
431536ac495dSmrg do {
431636ac495dSmrg prev = prev_nonnote_insn (prev);
431736ac495dSmrg if (!prev)
431836ac495dSmrg {
431936ac495dSmrg #if DEBUG_CMP
432036ac495dSmrg fprintf(stderr, "No previous insn.\n");
432136ac495dSmrg #endif
432236ac495dSmrg return false;
432336ac495dSmrg }
432436ac495dSmrg if (!INSN_P (prev))
432536ac495dSmrg {
432636ac495dSmrg #if DEBUG_CMP
432736ac495dSmrg fprintf(stderr, "Previous insn is a non-insn.\n");
432836ac495dSmrg #endif
432936ac495dSmrg return false;
433036ac495dSmrg }
433136ac495dSmrg pp = PATTERN (prev);
433236ac495dSmrg if (GET_CODE (pp) != SET)
433336ac495dSmrg {
433436ac495dSmrg #if DEBUG_CMP
433536ac495dSmrg fprintf(stderr, "Previous insn is not a SET.\n");
433636ac495dSmrg #endif
433736ac495dSmrg return false;
433836ac495dSmrg }
433936ac495dSmrg pflags = get_attr_flags (prev);
434036ac495dSmrg
434136ac495dSmrg /* Looking up attributes of previous insns corrupted the recog
434236ac495dSmrg tables. */
434336ac495dSmrg INSN_UID (cmp) = -1;
434436ac495dSmrg recog (PATTERN (cmp), cmp, 0);
434536ac495dSmrg
434636ac495dSmrg if (pflags == FLAGS_N
434736ac495dSmrg && reg_mentioned_p (op0, pp))
434836ac495dSmrg {
434936ac495dSmrg #if DEBUG_CMP
435036ac495dSmrg fprintf(stderr, "intermediate non-flags insn uses op:\n");
435136ac495dSmrg debug_rtx(prev);
435236ac495dSmrg #endif
435336ac495dSmrg return false;
435436ac495dSmrg }
435536ac495dSmrg
435636ac495dSmrg /* Check for comparisons against memory - between volatiles and
435736ac495dSmrg aliases, we just can't risk this one. */
435836ac495dSmrg if (GET_CODE (operands[0]) == MEM
435936ac495dSmrg || GET_CODE (operands[0]) == MEM)
436036ac495dSmrg {
436136ac495dSmrg #if DEBUG_CMP
436236ac495dSmrg fprintf(stderr, "comparisons with memory:\n");
436336ac495dSmrg debug_rtx(prev);
436436ac495dSmrg #endif
436536ac495dSmrg return false;
436636ac495dSmrg }
436736ac495dSmrg
436836ac495dSmrg /* Check for PREV changing a register that's used to compute a
436936ac495dSmrg value in CMP, even if it doesn't otherwise change flags. */
437036ac495dSmrg if (GET_CODE (operands[0]) == REG
437136ac495dSmrg && rtx_referenced_p (SET_DEST (PATTERN (prev)), operands[0]))
437236ac495dSmrg {
437336ac495dSmrg #if DEBUG_CMP
437436ac495dSmrg fprintf(stderr, "sub-value affected, op0:\n");
437536ac495dSmrg debug_rtx(prev);
437636ac495dSmrg #endif
437736ac495dSmrg return false;
437836ac495dSmrg }
437936ac495dSmrg if (GET_CODE (operands[1]) == REG
438036ac495dSmrg && rtx_referenced_p (SET_DEST (PATTERN (prev)), operands[1]))
438136ac495dSmrg {
438236ac495dSmrg #if DEBUG_CMP
438336ac495dSmrg fprintf(stderr, "sub-value affected, op1:\n");
438436ac495dSmrg debug_rtx(prev);
438536ac495dSmrg #endif
438636ac495dSmrg return false;
438736ac495dSmrg }
438836ac495dSmrg
438936ac495dSmrg } while (pflags == FLAGS_N);
439036ac495dSmrg #if DEBUG_CMP
439136ac495dSmrg fprintf(stderr, "previous flag-setting insn:\n");
439236ac495dSmrg debug_rtx(prev);
439336ac495dSmrg debug_rtx(pp);
439436ac495dSmrg #endif
439536ac495dSmrg
439636ac495dSmrg if (GET_CODE (pp) == SET
439736ac495dSmrg && GET_CODE (XEXP (pp, 0)) == REG
439836ac495dSmrg && REGNO (XEXP (pp, 0)) == FLG_REGNO
439936ac495dSmrg && GET_CODE (XEXP (pp, 1)) == COMPARE)
440036ac495dSmrg {
440136ac495dSmrg /* Adjacent cbranches must have the same operands to be
440236ac495dSmrg redundant. */
440336ac495dSmrg rtx pop0 = XEXP (XEXP (pp, 1), 0);
440436ac495dSmrg rtx pop1 = XEXP (XEXP (pp, 1), 1);
440536ac495dSmrg #if DEBUG_CMP
440636ac495dSmrg fprintf(stderr, "adjacent cbranches\n");
440736ac495dSmrg debug_rtx(pop0);
440836ac495dSmrg debug_rtx(pop1);
440936ac495dSmrg #endif
441036ac495dSmrg if (rtx_equal_p (op0, pop0)
441136ac495dSmrg && rtx_equal_p (op1, pop1))
441236ac495dSmrg return true;
441336ac495dSmrg #if DEBUG_CMP
441436ac495dSmrg fprintf(stderr, "prev cmp not same\n");
441536ac495dSmrg #endif
441636ac495dSmrg return false;
441736ac495dSmrg }
441836ac495dSmrg
441936ac495dSmrg /* Else the previous insn must be a SET, with either the source or
442036ac495dSmrg dest equal to operands[0], and operands[1] must be zero. */
442136ac495dSmrg
442236ac495dSmrg if (!rtx_equal_p (op1, const0_rtx))
442336ac495dSmrg {
442436ac495dSmrg #if DEBUG_CMP
442536ac495dSmrg fprintf(stderr, "operands[1] not const0_rtx\n");
442636ac495dSmrg #endif
442736ac495dSmrg return false;
442836ac495dSmrg }
442936ac495dSmrg if (GET_CODE (pp) != SET)
443036ac495dSmrg {
443136ac495dSmrg #if DEBUG_CMP
443236ac495dSmrg fprintf (stderr, "pp not set\n");
443336ac495dSmrg #endif
443436ac495dSmrg return false;
443536ac495dSmrg }
443636ac495dSmrg if (!rtx_equal_p (op0, SET_SRC (pp))
443736ac495dSmrg && !rtx_equal_p (op0, SET_DEST (pp)))
443836ac495dSmrg {
443936ac495dSmrg #if DEBUG_CMP
444036ac495dSmrg fprintf(stderr, "operands[0] not found in set\n");
444136ac495dSmrg #endif
444236ac495dSmrg return false;
444336ac495dSmrg }
444436ac495dSmrg
444536ac495dSmrg #if DEBUG_CMP
444636ac495dSmrg fprintf(stderr, "cmp flags %x prev flags %x\n", flags_needed, pflags);
444736ac495dSmrg #endif
444836ac495dSmrg if ((pflags & flags_needed) == flags_needed)
444936ac495dSmrg return true;
445036ac495dSmrg
445136ac495dSmrg return false;
445236ac495dSmrg }
445336ac495dSmrg
445436ac495dSmrg /* Return the pattern for a compare. This will be commented out if
445536ac495dSmrg the compare is redundant, else a normal pattern is returned. Thus,
445636ac495dSmrg the assembler output says where the compare would have been. */
445736ac495dSmrg char *
m32c_output_compare(rtx_insn * insn,rtx * operands)445836ac495dSmrg m32c_output_compare (rtx_insn *insn, rtx *operands)
445936ac495dSmrg {
446036ac495dSmrg static char templ[] = ";cmp.b\t%1,%0";
446136ac495dSmrg /* ^ 5 */
446236ac495dSmrg
446336ac495dSmrg templ[5] = " bwll"[GET_MODE_SIZE(GET_MODE(operands[0]))];
446436ac495dSmrg if (m32c_compare_redundant (insn, operands))
446536ac495dSmrg {
446636ac495dSmrg #if DEBUG_CMP
446736ac495dSmrg fprintf(stderr, "cbranch: cmp not needed\n");
446836ac495dSmrg #endif
446936ac495dSmrg return templ;
447036ac495dSmrg }
447136ac495dSmrg
447236ac495dSmrg #if DEBUG_CMP
447336ac495dSmrg fprintf(stderr, "cbranch: cmp needed: `%s'\n", templ + 1);
447436ac495dSmrg #endif
447536ac495dSmrg return templ + 1;
447636ac495dSmrg }
447736ac495dSmrg
447836ac495dSmrg #undef TARGET_ENCODE_SECTION_INFO
447936ac495dSmrg #define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
448036ac495dSmrg
448136ac495dSmrg /* If the frame pointer isn't used, we detect it manually. But the
448236ac495dSmrg stack pointer doesn't have as flexible addressing as the frame
448336ac495dSmrg pointer, so we always assume we have it. */
448436ac495dSmrg
448536ac495dSmrg #undef TARGET_FRAME_POINTER_REQUIRED
448636ac495dSmrg #define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true
448736ac495dSmrg
4488a2dc1f3fSmrg #undef TARGET_HARD_REGNO_NREGS
4489a2dc1f3fSmrg #define TARGET_HARD_REGNO_NREGS m32c_hard_regno_nregs
4490a2dc1f3fSmrg #undef TARGET_HARD_REGNO_MODE_OK
4491a2dc1f3fSmrg #define TARGET_HARD_REGNO_MODE_OK m32c_hard_regno_mode_ok
4492a2dc1f3fSmrg #undef TARGET_MODES_TIEABLE_P
4493a2dc1f3fSmrg #define TARGET_MODES_TIEABLE_P m32c_modes_tieable_p
4494a2dc1f3fSmrg
4495a2dc1f3fSmrg #undef TARGET_CAN_CHANGE_MODE_CLASS
4496a2dc1f3fSmrg #define TARGET_CAN_CHANGE_MODE_CLASS m32c_can_change_mode_class
4497a2dc1f3fSmrg
449836ac495dSmrg /* The Global `targetm' Variable. */
449936ac495dSmrg
450036ac495dSmrg struct gcc_target targetm = TARGET_INITIALIZER;
450136ac495dSmrg
450236ac495dSmrg #include "gt-m32c.h"
4503