summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/alpha/gnu.h49
-rw-r--r--gcc/config/arc/arc-modes.def24
-rw-r--r--gcc/config/arc/arc-protos.h63
-rw-r--r--gcc/config/arc/arc.c2493
-rw-r--r--gcc/config/arc/arc.h935
-rw-r--r--gcc/config/arc/arc.md1376
-rw-r--r--gcc/config/arc/arc.opt60
-rw-r--r--gcc/config/arc/initfini.c155
-rw-r--r--gcc/config/arc/lib1funcs.asm266
-rw-r--r--gcc/config/arc/t-arc60
-rw-r--r--gcc/config/arm/netbsd.h150
-rw-r--r--gcc/config/arm/t-pe52
-rw-r--r--gcc/config/crx/crx-protos.h79
-rw-r--r--gcc/config/crx/crx.c1466
-rw-r--r--gcc/config/crx/crx.h478
-rw-r--r--gcc/config/crx/crx.md899
-rw-r--r--gcc/config/crx/crx.opt34
-rw-r--r--gcc/config/crx/t-crx37
-rw-r--r--gcc/config/i386/netbsd.h96
-rw-r--r--gcc/config/m68hc11/larith.asm1333
-rw-r--r--gcc/config/m68hc11/m68hc11-crt0.S86
-rw-r--r--gcc/config/m68hc11/m68hc11-protos.h109
-rw-r--r--gcc/config/m68hc11/m68hc11.c5588
-rw-r--r--gcc/config/m68hc11/m68hc11.h1382
-rw-r--r--gcc/config/m68hc11/m68hc11.md7579
-rw-r--r--gcc/config/m68hc11/m68hc11.opt94
-rw-r--r--gcc/config/m68hc11/m68hc12.h45
-rw-r--r--gcc/config/m68hc11/predicates.md228
-rw-r--r--gcc/config/m68hc11/t-m68hc1196
-rw-r--r--gcc/config/m68k/uclinux-oldabi.h70
-rw-r--r--gcc/config/mcore/mcore-pe.h102
-rw-r--r--gcc/config/mcore/t-mcore-pe56
-rw-r--r--gcc/config/netbsd-aout.h196
-rw-r--r--gcc/config/rs6000/gnu.h37
-rw-r--r--gcc/config/rs6000/linux64.h5
-rw-r--r--gcc/config/rs6000/sysv4.h46
-rw-r--r--gcc/config/sh/sh-protos.h16
-rw-r--r--gcc/config/sh/sh-symbian.h42
-rw-r--r--gcc/config/sh/sh.c30
-rw-r--r--gcc/config/sh/symbian-base.c244
-rw-r--r--gcc/config/sh/symbian-c.c181
-rw-r--r--gcc/config/sh/symbian-cxx.c662
-rw-r--r--gcc/config/sh/symbian-post.h88
-rw-r--r--gcc/config/sh/symbian-pre.h40
-rw-r--r--gcc/config/sh/t-symbian81
-rw-r--r--gcc/config/svr3.h146
-rw-r--r--gcc/config/vax/netbsd.h47
47 files changed, 3 insertions, 27398 deletions
diff --git a/gcc/config/alpha/gnu.h b/gcc/config/alpha/gnu.h
deleted file mode 100644
index ca719803906..00000000000
--- a/gcc/config/alpha/gnu.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Configuration for an Alpha running GNU with ELF as the target machine.
-
-Copyright (C) 2002, 2003, 2004, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (Alpha GNU)");
-
-#undef TARGET_OS_CPP_BUILTINS /* config.gcc includes alpha/linux.h. */
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- LINUX_TARGET_OS_CPP_BUILTINS(); \
- builtin_define ("_LONGLONG"); \
- } while (0)
-
-#undef ELF_DYNAMIC_LINKER
-#define ELF_DYNAMIC_LINKER "/lib/ld.so"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{!static: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
- %{static:crt0.o%s}} \
- crti.o%s \
- %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
-
-/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
-#undef MD_UNWIND_SUPPORT
diff --git a/gcc/config/arc/arc-modes.def b/gcc/config/arc/arc-modes.def
deleted file mode 100644
index c2d2ceaf82f..00000000000
--- a/gcc/config/arc/arc-modes.def
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 2002, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Some insns set all condition code flags, some only set the ZNC flags, and
- some only set the ZN flags. */
-
-CC_MODE (CCZNC);
-CC_MODE (CCZN);
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
deleted file mode 100644
index 5550ebfbe2c..00000000000
--- a/gcc/config/arc/arc-protos.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 2000, 2004, 2007, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef RTX_CODE
-extern enum machine_mode arc_select_cc_mode (enum rtx_code, rtx, rtx);
-
-/* Define the function that build the compare insn for scc and bcc. */
-extern struct rtx_def *gen_compare_reg (enum rtx_code, rtx, rtx);
-#endif
-
-/* Declarations for various fns used in the .md file. */
-extern const char *output_shift (rtx *);
-
-extern int symbolic_operand (rtx, enum machine_mode);
-extern int arc_double_limm_p (rtx);
-extern int arc_eligible_for_epilogue_delay (rtx, int);
-extern void arc_initialize_trampoline (rtx, rtx, rtx);
-extern void arc_print_operand (FILE *, rtx, int);
-extern void arc_print_operand_address (FILE *, rtx);
-extern void arc_final_prescan_insn (rtx, rtx *, int);
-extern int call_address_operand (rtx, enum machine_mode);
-extern int call_operand (rtx, enum machine_mode);
-extern int symbolic_memory_operand (rtx, enum machine_mode);
-extern int short_immediate_operand (rtx, enum machine_mode);
-extern int long_immediate_operand (rtx, enum machine_mode);
-extern int long_immediate_loadstore_operand (rtx, enum machine_mode);
-extern int move_src_operand (rtx, enum machine_mode);
-extern int move_double_src_operand (rtx, enum machine_mode);
-extern int move_dest_operand (rtx, enum machine_mode);
-extern int load_update_operand (rtx, enum machine_mode);
-extern int store_update_operand (rtx, enum machine_mode);
-extern int nonvol_nonimm_operand (rtx, enum machine_mode);
-extern int const_sint32_operand (rtx, enum machine_mode);
-extern int const_uint32_operand (rtx, enum machine_mode);
-extern int proper_comparison_operator (rtx, enum machine_mode);
-extern int shift_operator (rtx, enum machine_mode);
-
-extern enum arc_function_type arc_compute_function_type (tree);
-
-
-extern unsigned int arc_compute_frame_size (int);
-extern void arc_save_restore (FILE *, const char *, unsigned int,
- unsigned int, const char *);
-extern int arc_delay_slots_for_epilogue (void);
-extern void arc_ccfsm_at_label (const char *, int);
-extern int arc_ccfsm_branch_deleted_p (void);
-extern void arc_ccfsm_record_branch_deleted (void);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
deleted file mode 100644
index fa92ccf7479..00000000000
--- a/gcc/config/arc/arc.c
+++ /dev/null
@@ -1,2493 +0,0 @@
-/* Subroutines used for code generation on the Argonaut ARC cpu.
- Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* ??? This is an old port, and is undoubtedly suffering from bit rot. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "rtl.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "function.h"
-#include "expr.h"
-#include "recog.h"
-#include "diagnostic-core.h"
-#include "df.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
-
-/* Which cpu we're compiling for. */
-int arc_cpu_type;
-
-/* Name of mangle string to add to symbols to separate code compiled for each
- cpu (or NULL). */
-const char *arc_mangle_cpu;
-
-/* Name of text, data, and rodata sections used in varasm.c. */
-const char *arc_text_section;
-const char *arc_data_section;
-const char *arc_rodata_section;
-
-/* Array of valid operand punctuation characters. */
-char arc_punct_chars[256];
-
-/* Variables used by arc_final_prescan_insn to implement conditional
- execution. */
-static int arc_ccfsm_state;
-static int arc_ccfsm_current_cc;
-static rtx arc_ccfsm_target_insn;
-static int arc_ccfsm_target_label;
-
-/* The maximum number of insns skipped which will be conditionalised if
- possible. */
-#define MAX_INSNS_SKIPPED 3
-
-/* A nop is needed between a 4 byte insn that sets the condition codes and
- a branch that uses them (the same isn't true for an 8 byte insn that sets
- the condition codes). Set by arc_final_prescan_insn. Used by
- arc_print_operand. */
-static int last_insn_set_cc_p;
-static int current_insn_set_cc_p;
-static bool arc_handle_option (size_t, const char *, int);
-static void record_cc_ref (rtx);
-static void arc_init_reg_tables (void);
-static int get_arc_condition_code (rtx);
-static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
-static bool arc_assemble_integer (rtx, unsigned int, int);
-static void arc_output_function_prologue (FILE *, HOST_WIDE_INT);
-static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void arc_file_start (void);
-static void arc_internal_label (FILE *, const char *, unsigned long);
-static void arc_va_start (tree, rtx);
-static void arc_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int *, int);
-static bool arc_rtx_costs (rtx, int, int, int *, bool);
-static int arc_address_cost (rtx, bool);
-static void arc_external_libcall (rtx);
-static bool arc_return_in_memory (const_tree, const_tree);
-static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static rtx arc_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static void arc_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static unsigned int arc_function_arg_boundary (enum machine_mode, const_tree);
-static void arc_trampoline_init (rtx, tree, rtx);
-static void arc_option_override (void);
-static void arc_conditional_register_usage (void);
-
-
-/* ARC specific attributs. */
-
-static const struct attribute_spec arc_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-
-/* Initialize the GCC target structure. */
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
-#undef TARGET_ASM_ALIGNED_SI_OP
-#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
-#undef TARGET_ASM_INTEGER
-#define TARGET_ASM_INTEGER arc_assemble_integer
-
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
-#undef TARGET_ASM_FILE_START
-#define TARGET_ASM_FILE_START arc_file_start
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
-#undef TARGET_ASM_INTERNAL_LABEL
-#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
-#undef TARGET_ASM_EXTERNAL_LIBCALL
-#define TARGET_ASM_EXTERNAL_LIBCALL arc_external_libcall
-
-#undef TARGET_HANDLE_OPTION
-#define TARGET_HANDLE_OPTION arc_handle_option
-
-#undef TARGET_OPTION_OVERRIDE
-#define TARGET_OPTION_OVERRIDE arc_option_override
-
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS arc_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST arc_address_cost
-
-#undef TARGET_PROMOTE_FUNCTION_MODE
-#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
-#undef TARGET_PASS_BY_REFERENCE
-#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG arc_function_arg
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
-#undef TARGET_FUNCTION_ARG_BOUNDARY
-#define TARGET_FUNCTION_ARG_BOUNDARY arc_function_arg_boundary
-#undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
-
-#undef TARGET_SETUP_INCOMING_VARARGS
-#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
-
-#undef TARGET_EXPAND_BUILTIN_VA_START
-#define TARGET_EXPAND_BUILTIN_VA_START arc_va_start
-
-#undef TARGET_TRAMPOLINE_INIT
-#define TARGET_TRAMPOLINE_INIT arc_trampoline_init
-
-#undef TARGET_CONDITIONAL_REGISTER_USAGE
-#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-/* Implement TARGET_HANDLE_OPTION. */
-
-static bool
-arc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- case OPT_mcpu_:
- return strcmp (arg, "base") == 0 || ARC_EXTENSION_CPU (arg);
-
- default:
- return true;
- }
-}
-
-/* Implement TARGET_OPTION_OVERRIDE.
- These need to be done at start up. It's convenient to do them here. */
-
-static void
-arc_option_override (void)
-{
- char *tmp;
-
- /* Set the pseudo-ops for the various standard sections. */
- arc_text_section = tmp = XNEWVEC (char, strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_text_string);
- arc_data_section = tmp = XNEWVEC (char, strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_data_string);
- arc_rodata_section = tmp = XNEWVEC (char, strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1);
- sprintf (tmp, ARC_SECTION_FORMAT, arc_rodata_string);
-
- arc_init_reg_tables ();
-
- /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
- memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
- arc_punct_chars['#'] = 1;
- arc_punct_chars['*'] = 1;
- arc_punct_chars['?'] = 1;
- arc_punct_chars['!'] = 1;
- arc_punct_chars['~'] = 1;
-}
-
-/* The condition codes of the ARC, and the inverse function. */
-static const char *const arc_condition_codes[] =
-{
- "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv",
- "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
-};
-
-#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
-
-/* Returns the index of the ARC condition code string in
- `arc_condition_codes'. COMPARISON should be an rtx like
- `(eq (...) (...))'. */
-
-static int
-get_arc_condition_code (rtx comparison)
-{
- switch (GET_CODE (comparison))
- {
- case EQ : return 2;
- case NE : return 3;
- case GT : return 10;
- case LE : return 11;
- case GE : return 12;
- case LT : return 13;
- case GTU : return 14;
- case LEU : return 15;
- case LTU : return 6;
- case GEU : return 7;
- default : gcc_unreachable ();
- }
- /*NOTREACHED*/
- return (42);
-}
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-
-enum machine_mode
-arc_select_cc_mode (enum rtx_code op,
- rtx x ATTRIBUTE_UNUSED,
- rtx y ATTRIBUTE_UNUSED)
-{
- switch (op)
- {
- case EQ :
- case NE :
- return CCZNmode;
- default :
- switch (GET_CODE (x))
- {
- case AND :
- case IOR :
- case XOR :
- case SIGN_EXTEND :
- case ZERO_EXTEND :
- return CCZNmode;
- case ASHIFT :
- case ASHIFTRT :
- case LSHIFTRT :
- return CCZNCmode;
- default:
- break;
- }
- }
- return CCmode;
-}
-
-/* Vectors to keep interesting information about registers where it can easily
- be got. We use to use the actual mode value as the bit number, but there
- is (or may be) more than 32 modes now. Instead we use two tables: one
- indexed by hard register number, and one indexed by mode. */
-
-/* The purpose of arc_mode_class is to shrink the range of modes so that
- they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
- mapped into one arc_mode_class mode. */
-
-enum arc_mode_class {
- C_MODE,
- S_MODE, D_MODE, T_MODE, O_MODE,
- SF_MODE, DF_MODE, TF_MODE, OF_MODE
-};
-
-/* Modes for condition codes. */
-#define C_MODES (1 << (int) C_MODE)
-
-/* Modes for single-word and smaller quantities. */
-#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
-
-/* Modes for double-word and smaller quantities. */
-#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
-
-/* Modes for quad-word and smaller quantities. */
-#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
-
-/* Value is 1 if register/mode pair is acceptable on arc. */
-
-const unsigned int arc_hard_regno_mode_ok[] = {
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
- T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
- D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
-
- /* ??? Leave these as S_MODES for now. */
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
- S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES
-};
-
-unsigned int arc_mode_class [NUM_MACHINE_MODES];
-
-enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
-
-static void
-arc_init_reg_tables (void)
-{
- int i;
-
- for (i = 0; i < NUM_MACHINE_MODES; i++)
- {
- switch (GET_MODE_CLASS (i))
- {
- case MODE_INT:
- case MODE_PARTIAL_INT:
- case MODE_COMPLEX_INT:
- if (GET_MODE_SIZE (i) <= 4)
- arc_mode_class[i] = 1 << (int) S_MODE;
- else if (GET_MODE_SIZE (i) == 8)
- arc_mode_class[i] = 1 << (int) D_MODE;
- else if (GET_MODE_SIZE (i) == 16)
- arc_mode_class[i] = 1 << (int) T_MODE;
- else if (GET_MODE_SIZE (i) == 32)
- arc_mode_class[i] = 1 << (int) O_MODE;
- else
- arc_mode_class[i] = 0;
- break;
- case MODE_FLOAT:
- case MODE_COMPLEX_FLOAT:
- if (GET_MODE_SIZE (i) <= 4)
- arc_mode_class[i] = 1 << (int) SF_MODE;
- else if (GET_MODE_SIZE (i) == 8)
- arc_mode_class[i] = 1 << (int) DF_MODE;
- else if (GET_MODE_SIZE (i) == 16)
- arc_mode_class[i] = 1 << (int) TF_MODE;
- else if (GET_MODE_SIZE (i) == 32)
- arc_mode_class[i] = 1 << (int) OF_MODE;
- else
- arc_mode_class[i] = 0;
- break;
- case MODE_CC:
- arc_mode_class[i] = 1 << (int) C_MODE;
- break;
- default:
- arc_mode_class[i] = 0;
- break;
- }
- }
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (i < 60)
- arc_regno_reg_class[i] = GENERAL_REGS;
- else if (i == 60)
- arc_regno_reg_class[i] = LPCOUNT_REG;
- else if (i == 61)
- arc_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */;
- else
- arc_regno_reg_class[i] = NO_REGS;
- }
-}
-
-/* ARC specific attribute support.
-
- The ARC has these attributes:
- interrupt - for interrupt functions
-*/
-
-/* Handle an "interrupt" attribute; arguments as in
- struct attribute_spec.handler. */
-static tree
-arc_handle_interrupt_attribute (tree *node ATTRIBUTE_UNUSED,
- tree name,
- tree args,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
-{
- tree value = TREE_VALUE (args);
-
- if (TREE_CODE (value) != STRING_CST)
- {
- warning (OPT_Wattributes,
- "argument of %qE attribute is not a string constant",
- name);
- *no_add_attrs = true;
- }
- else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
- && strcmp (TREE_STRING_POINTER (value), "ilink2"))
- {
- warning (OPT_Wattributes,
- "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-
-/* Acceptable arguments to the call insn. */
-
-int
-call_address_operand (rtx op, enum machine_mode mode)
-{
- return (symbolic_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op))
- || (GET_CODE (op) == REG));
-}
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- return call_address_operand (op, mode);
-}
-
-/* Returns 1 if OP is a symbol reference. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- case CONST :
- return 1;
- default:
- return 0;
- }
-}
-
-/* Return truth value of statement that OP is a symbolic memory
- operand of mode MODE. */
-
-int
-symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
- || GET_CODE (op) == LABEL_REF);
-}
-
-/* Return true if OP is a short immediate (shimm) value. */
-
-int
-short_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return SMALL_INT (INTVAL (op));
-}
-
-/* Return true if OP will require a long immediate (limm) value.
- This is currently only used when calculating length attributes. */
-
-int
-long_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- return !SMALL_INT (INTVAL (op));
- case CONST_DOUBLE :
- /* These can happen because large unsigned 32-bit constants are
- represented this way (the multiplication patterns can cause these
- to be generated). They also occur for SFmode values. */
- return 1;
- default:
- break;
- }
- return 0;
-}
-
-/* Return true if OP is a MEM that when used as a load or store address will
- require an 8 byte insn.
- Load and store instructions don't allow the same possibilities but they're
- similar enough that this one function will do.
- This is currently only used when calculating length attributes. */
-
-int
-long_immediate_loadstore_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- /* This must be handled as "st c,[limm]". Ditto for load.
- Technically, the assembler could translate some possibilities to
- "st c,[limm/2 + limm/2]" if limm/2 will fit in a shimm, but we don't
- assume that it does. */
- return 1;
- case CONST_DOUBLE :
- /* These can happen because large unsigned 32-bit constants are
- represented this way (the multiplication patterns can cause these
- to be generated). They also occur for SFmode values. */
- return 1;
- case REG :
- return 0;
- case PLUS :
- if (GET_CODE (XEXP (op, 1)) == CONST_INT
- && !SMALL_INT (INTVAL (XEXP (op, 1))))
- return 1;
- return 0;
- default:
- break;
- }
- return 0;
-}
-
-/* Return true if OP is an acceptable argument for a single word
- move source. */
-
-int
-move_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- case LABEL_REF :
- case CONST :
- return 1;
- case CONST_INT :
- return (LARGE_INT (INTVAL (op)));
- case CONST_DOUBLE :
- /* We can handle DImode integer constants in SImode if the value
- (signed or unsigned) will fit in 32 bits. This is needed because
- large unsigned 32-bit constants are represented as CONST_DOUBLEs. */
- if (mode == SImode)
- return arc_double_limm_p (op);
- /* We can handle 32-bit floating point constants. */
- if (mode == SFmode)
- return GET_MODE (op) == SFmode;
- return 0;
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a double word
- move source. */
-
-int
-move_double_src_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return move_double_src_operand (SUBREG_REG (op), mode);
- else
- return register_operand (op, mode);
- case MEM :
- /* Disallow auto inc/dec for now. */
- if (GET_CODE (XEXP (op, 0)) == PRE_DEC
- || GET_CODE (XEXP (op, 0)) == PRE_INC)
- return 0;
- return address_operand (XEXP (op, 0), mode);
- case CONST_INT :
- case CONST_DOUBLE :
- return 1;
- default :
- return 0;
- }
-}
-
-/* Return true if OP is an acceptable argument for a move destination. */
-
-int
-move_dest_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case REG :
- return register_operand (op, mode);
- case SUBREG :
- /* (subreg (mem ...) ...) can occur here if the inner part was once a
- pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
- return address_operand (XEXP (SUBREG_REG (op), 0), mode);
- else
- return register_operand (op, mode);
- case MEM :
- return address_operand (XEXP (op, 0), mode);
- default :
- return 0;
- }
-}
-
-/* Return true if OP is valid load with update operand. */
-
-int
-load_update_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM
- || GET_MODE (op) != mode)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_MODE (op) != Pmode
- || !register_operand (XEXP (op, 0), Pmode)
- || !nonmemory_operand (XEXP (op, 1), Pmode))
- return 0;
- return 1;
-}
-
-/* Return true if OP is valid store with update operand. */
-
-int
-store_update_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM
- || GET_MODE (op) != mode)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_MODE (op) != Pmode
- || !register_operand (XEXP (op, 0), Pmode)
- || !(GET_CODE (XEXP (op, 1)) == CONST_INT
- && SMALL_INT (INTVAL (XEXP (op, 1)))))
- return 0;
- return 1;
-}
-
-/* Return true if OP is a non-volatile non-immediate operand.
- Volatile memory refs require a special "cache-bypass" instruction
- and only the standard movXX patterns are set up to handle them. */
-
-int
-nonvol_nonimm_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
- return 0;
- return nonimmediate_operand (op, mode);
-}
-
-/* Accept integer operands in the range -0x80000000..0x7fffffff. We have
- to check the range carefully since this predicate is used in DImode
- contexts. */
-
-int
-const_sint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
-}
-
-/* Accept integer operands in the range 0..0xffffffff. We have to check the
- range carefully since this predicate is used in DImode contexts. Also, we
- need some extra crud to make it work when hosted on 64-bit machines. */
-
-int
-const_uint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-#if HOST_BITS_PER_WIDE_INT > 32
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
-#else
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
- || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
-#endif
-}
-
-/* Return 1 if OP is a comparison operator valid for the mode of CC.
- This allows the use of MATCH_OPERATOR to recognize all the branch insns.
-
- Some insns only set a few bits in the condition code. So only allow those
- comparisons that use the bits that are valid. */
-
-int
-proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code;
- if (!COMPARISON_P (op))
- return 0;
-
- code = GET_CODE (op);
- if (GET_MODE (XEXP (op, 0)) == CCZNmode)
- return (code == EQ || code == NE);
- if (GET_MODE (XEXP (op, 0)) == CCZNCmode)
- return (code == EQ || code == NE
- || code == LTU || code == GEU || code == GTU || code == LEU);
- return 1;
-}
-
-/* Misc. utilities. */
-
-/* X and Y are two things to compare using CODE. Return the rtx
- for the cc reg in the proper mode. */
-
-rtx
-gen_compare_reg (enum rtx_code code, rtx x, rtx y)
-{
- enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- return gen_rtx_REG (mode, 61);
-}
-
-/* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number).
- We assume the value can be either signed or unsigned. */
-
-int
-arc_double_limm_p (rtx value)
-{
- HOST_WIDE_INT low, high;
-
- gcc_assert (GET_CODE (value) == CONST_DOUBLE);
-
- low = CONST_DOUBLE_LOW (value);
- high = CONST_DOUBLE_HIGH (value);
-
- if (low & 0x80000000)
- {
- return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
- || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
- == - (unsigned HOST_WIDE_INT) 0x80000000)
- && high == -1));
- }
- else
- {
- return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
- }
-}
-
-/* Do any needed setup for a variadic function. For the ARC, we must
- create a register parameter block, and then copy any anonymous arguments
- in registers to memory.
-
- CUM has not been updated for the last named argument which has type TYPE
- and mode MODE, and we rely on this fact.
-
- We do things a little weird here. We're supposed to only allocate space
- for the anonymous arguments. However we need to keep the stack eight byte
- aligned. So we round the space up if necessary, and leave it to va_start
- to compensate. */
-
-static void
-arc_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
- enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED,
- int *pretend_size,
- int no_rtl)
-{
- int first_anon_arg;
-
- /* All BLKmode values are passed by reference. */
- gcc_assert (mode != BLKmode);
-
- first_anon_arg = *cum + ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
-
- if (first_anon_arg < MAX_ARC_PARM_REGS && !no_rtl)
- {
- /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
- int first_reg_offset = first_anon_arg;
- /* Size in words to "pretend" allocate. */
- int size = MAX_ARC_PARM_REGS - first_reg_offset;
- /* Extra slop to keep stack eight byte aligned. */
- int align_slop = size & 1;
- rtx regblock;
-
- regblock = gen_rtx_MEM (BLKmode,
- plus_constant (arg_pointer_rtx,
- FIRST_PARM_OFFSET (0)
- + align_slop * UNITS_PER_WORD));
- set_mem_alias_set (regblock, get_varargs_alias_set ());
- set_mem_align (regblock, BITS_PER_WORD);
- move_block_from_reg (first_reg_offset, regblock,
- MAX_ARC_PARM_REGS - first_reg_offset);
-
- *pretend_size = ((MAX_ARC_PARM_REGS - first_reg_offset + align_slop)
- * UNITS_PER_WORD);
- }
-}
-
-/* Cost functions. */
-
-/* Compute a (partial) cost for rtx X. Return true if the complete
- cost has been computed, and false if subexpressions should be
- scanned. In either case, *TOTAL contains the cost result. */
-
-static bool
-arc_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
- bool speed ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- /* Small integers are as cheap as registers. 4 byte values can
- be fetched as immediate constants - let's give that the cost
- of an extra insn. */
- case CONST_INT:
- if (SMALL_INT (INTVAL (x)))
- {
- *total = 0;
- return true;
- }
- /* FALLTHRU */
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = COSTS_N_INSNS (1);
- return true;
-
- case CONST_DOUBLE:
- {
- rtx high, low;
- split_double (x, &high, &low);
- *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
- + !SMALL_INT (INTVAL (low)));
- return true;
- }
-
- /* Encourage synth_mult to find a synthetic multiply when reasonable.
- If we need more than 12 insns to do a multiply, then go out-of-line,
- since the call overhead will be < 10% of the cost of the multiply. */
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- if (TARGET_SHIFTER)
- *total = COSTS_N_INSNS (1);
- else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- *total = COSTS_N_INSNS (16);
- else
- *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
- return false;
-
- default:
- return false;
- }
-}
-
-
-/* Provide the costs of an addressing mode that contains ADDR.
- If ADDR is not a valid address, its cost is irrelevant. */
-
-static int
-arc_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (addr))
- {
- case REG :
- return 1;
-
- case LABEL_REF :
- case SYMBOL_REF :
- case CONST :
- return 2;
-
- case PLUS :
- {
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
-
- if (GET_CODE (plus0) != REG)
- break;
-
- switch (GET_CODE (plus1))
- {
- case CONST_INT :
- return SMALL_INT (INTVAL (plus1)) ? 1 : 2;
- case CONST :
- case SYMBOL_REF :
- case LABEL_REF :
- return 2;
- default:
- break;
- }
- break;
- }
- default:
- break;
- }
-
- return 4;
-}
-
-/* Function prologue/epilogue handlers. */
-
-/* ARC stack frames look like:
-
- Before call After call
- +-----------------------+ +-----------------------+
- | | | |
- high | local variables, | | local variables, |
- mem | reg save area, etc. | | reg save area, etc. |
- | | | |
- +-----------------------+ +-----------------------+
- | | | |
- | arguments on stack. | | arguments on stack. |
- | | | |
- SP+16->+-----------------------+FP+48->+-----------------------+
- | 4 word save area for | | reg parm save area, |
- | return addr, prev %fp | | only created for |
- SP+0->+-----------------------+ | variable argument |
- | functions |
- FP+16->+-----------------------+
- | 4 word save area for |
- | return addr, prev %fp |
- FP+0->+-----------------------+
- | |
- | local variables |
- | |
- +-----------------------+
- | |
- | register save area |
- | |
- +-----------------------+
- | |
- | alloca allocations |
- | |
- +-----------------------+
- | |
- | arguments on stack |
- | |
- SP+16->+-----------------------+
- low | 4 word save area for |
- memory | return addr, prev %fp |
- SP+0->+-----------------------+
-
-Notes:
-1) The "reg parm save area" does not exist for non variable argument fns.
- The "reg parm save area" can be eliminated completely if we created our
- own va-arc.h, but that has tradeoffs as well (so it's not done). */
-
-/* Structure to be filled in by arc_compute_frame_size with register
- save masks, and offsets for the current function. */
-struct arc_frame_info
-{
- unsigned int total_size; /* # bytes that the entire frame takes up. */
- unsigned int extra_size; /* # bytes of extra stuff. */
- unsigned int pretend_size; /* # bytes we push and pretend caller did. */
- unsigned int args_size; /* # bytes that outgoing arguments take up. */
- unsigned int reg_size; /* # bytes needed to store regs. */
- unsigned int var_size; /* # bytes that variables take up. */
- unsigned int reg_offset; /* Offset from new sp to store regs. */
- unsigned int gmask; /* Mask of saved gp registers. */
- int initialized; /* Nonzero if frame size already calculated. */
-};
-
-/* Current frame information calculated by arc_compute_frame_size. */
-static struct arc_frame_info current_frame_info;
-
-/* Zero structure to initialize current_frame_info. */
-static struct arc_frame_info zero_frame_info;
-
-/* Type of function DECL.
-
- The result is cached. To reset the cache at the end of a function,
- call with DECL = NULL_TREE. */
-
-enum arc_function_type
-arc_compute_function_type (tree decl)
-{
- tree a;
- /* Cached value. */
- static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN;
- /* Last function we were called for. */
- static tree last_fn = NULL_TREE;
-
- /* Resetting the cached value? */
- if (decl == NULL_TREE)
- {
- fn_type = ARC_FUNCTION_UNKNOWN;
- last_fn = NULL_TREE;
- return fn_type;
- }
-
- if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN)
- return fn_type;
-
- /* Assume we have a normal function (not an interrupt handler). */
- fn_type = ARC_FUNCTION_NORMAL;
-
- /* Now see if this is an interrupt handler. */
- for (a = DECL_ATTRIBUTES (current_function_decl);
- a;
- a = TREE_CHAIN (a))
- {
- tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
-
- if (name == get_identifier ("__interrupt__")
- && list_length (args) == 1
- && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
- {
- tree value = TREE_VALUE (args);
-
- if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
- fn_type = ARC_FUNCTION_ILINK1;
- else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
- fn_type = ARC_FUNCTION_ILINK2;
- else
- gcc_unreachable ();
- break;
- }
- }
-
- last_fn = decl;
- return fn_type;
-}
-
-#define ILINK1_REGNUM 29
-#define ILINK2_REGNUM 30
-#define RETURN_ADDR_REGNUM 31
-#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
-#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
-
-/* Tell prologue and epilogue if register REGNO should be saved / restored.
- The return address and frame pointer are treated separately.
- Don't consider them here. */
-#define MUST_SAVE_REGISTER(regno, interrupt_p) \
-((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
- && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p)))
-
-#define MUST_SAVE_RETURN_ADDR (df_regs_ever_live_p (RETURN_ADDR_REGNUM))
-
-/* Return the bytes needed to compute the frame pointer from the current
- stack pointer.
-
- SIZE is the size needed for local variables. */
-
-unsigned int
-arc_compute_frame_size (int size /* # of var. bytes allocated. */)
-{
- int regno;
- unsigned int total_size, var_size, args_size, pretend_size, extra_size;
- unsigned int reg_size, reg_offset;
- unsigned int gmask;
- enum arc_function_type fn_type;
- int interrupt_p;
-
- var_size = size;
- args_size = crtl->outgoing_args_size;
- pretend_size = crtl->args.pretend_args_size;
- extra_size = FIRST_PARM_OFFSET (0);
- total_size = extra_size + pretend_size + args_size + var_size;
- reg_offset = FIRST_PARM_OFFSET(0) + crtl->outgoing_args_size;
- reg_size = 0;
- gmask = 0;
-
- /* See if this is an interrupt handler. Call used registers must be saved
- for them too. */
- fn_type = arc_compute_function_type (current_function_decl);
- interrupt_p = ARC_INTERRUPT_P (fn_type);
-
- /* Calculate space needed for registers.
- ??? We ignore the extension registers for now. */
-
- for (regno = 0; regno <= 31; regno++)
- {
- if (MUST_SAVE_REGISTER (regno, interrupt_p))
- {
- reg_size += UNITS_PER_WORD;
- gmask |= 1 << regno;
- }
- }
-
- total_size += reg_size;
-
- /* If the only space to allocate is the fp/blink save area this is an
- empty frame. However, if we'll be making a function call we need to
- allocate a stack frame for our callee's fp/blink save area. */
- if (total_size == extra_size
- && !MUST_SAVE_RETURN_ADDR)
- total_size = extra_size = 0;
-
- total_size = ARC_STACK_ALIGN (total_size);
-
- /* Save computed information. */
- current_frame_info.total_size = total_size;
- current_frame_info.extra_size = extra_size;
- current_frame_info.pretend_size = pretend_size;
- current_frame_info.var_size = var_size;
- current_frame_info.args_size = args_size;
- current_frame_info.reg_size = reg_size;
- current_frame_info.reg_offset = reg_offset;
- current_frame_info.gmask = gmask;
- current_frame_info.initialized = reload_completed;
-
- /* Ok, we're done. */
- return total_size;
-}
-
-/* Common code to save/restore registers. */
-
-void
-arc_save_restore (FILE *file,
- const char *base_reg,
- unsigned int offset,
- unsigned int gmask,
- const char *op)
-{
- int regno;
-
- if (gmask == 0)
- return;
-
- for (regno = 0; regno <= 31; regno++)
- {
- if ((gmask & (1L << regno)) != 0)
- {
- fprintf (file, "\t%s %s,[%s,%d]\n",
- op, reg_names[regno], base_reg, offset);
- offset += UNITS_PER_WORD;
- }
- }
-}
-
-/* Target hook to assemble an integer object. The ARC version needs to
- emit a special directive for references to labels and function
- symbols. */
-
-static bool
-arc_assemble_integer (rtx x, unsigned int size, int aligned_p)
-{
- if (size == UNITS_PER_WORD && aligned_p
- && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
- || GET_CODE (x) == LABEL_REF))
- {
- fputs ("\t.word\t%st(", asm_out_file);
- output_addr_const (asm_out_file, x);
- fputs (")\n", asm_out_file);
- return true;
- }
- return default_assemble_integer (x, size, aligned_p);
-}
-
-/* Set up the stack and frame pointer (if desired) for the function. */
-
-static void
-arc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
-{
- const char *sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
- unsigned int gmask = current_frame_info.gmask;
- enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
-
- /* If this is an interrupt handler, set up our stack frame.
- ??? Optimize later. */
- if (ARC_INTERRUPT_P (fn_type))
- {
- fprintf (file, "\t%s interrupt handler\n",
- ASM_COMMENT_START);
- fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str);
- }
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n",
- ASM_COMMENT_START, ASM_COMMENT_START,
- current_frame_info.var_size,
- current_frame_info.reg_size / 4,
- current_frame_info.args_size,
- current_frame_info.extra_size);
-
- size = ARC_STACK_ALIGN (size);
- size = (! current_frame_info.initialized
- ? arc_compute_frame_size (size)
- : current_frame_info.total_size);
-
- /* These cases shouldn't happen. Catch them now. */
- gcc_assert (size || !gmask);
-
- /* Allocate space for register arguments if this is a variadic function. */
- if (current_frame_info.pretend_size != 0)
- fprintf (file, "\tsub %s,%s,%d\n",
- sp_str, sp_str, current_frame_info.pretend_size);
-
- /* The home-grown ABI says link register is saved first. */
- if (MUST_SAVE_RETURN_ADDR)
- fprintf (file, "\tst %s,[%s,%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD);
-
- /* Set up the previous frame pointer next (if we need to). */
- if (frame_pointer_needed)
- {
- fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str);
- fprintf (file, "\tmov %s,%s\n", fp_str, sp_str);
- }
-
- /* ??? We don't handle the case where the saved regs are more than 252
- bytes away from sp. This can be handled by decrementing sp once, saving
- the regs, and then decrementing it again. The epilogue doesn't have this
- problem as the `ld' insn takes reg+limm values (though it would be more
- efficient to avoid reg+limm). */
-
- /* Allocate the stack frame. */
- if (size - current_frame_info.pretend_size > 0)
- fprintf (file, "\tsub %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
- sp_str, sp_str, size - current_frame_info.pretend_size);
-
- /* Save any needed call-saved regs (and call-used if this is an
- interrupt handler). */
- arc_save_restore (file, sp_str, current_frame_info.reg_offset,
- /* The zeroing of these two bits is unnecessary,
- but leave this in for clarity. */
- gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- "st");
-
- fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START);
-}
-
-/* Do any necessary cleanup after a function to restore stack, frame,
- and regs. */
-
-static void
-arc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
-{
- rtx epilogue_delay = crtl->epilogue_delay_list;
- int noepilogue = FALSE;
- enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);
-
- size = ARC_STACK_ALIGN (size);
- size = (!current_frame_info.initialized
- ? arc_compute_frame_size (size)
- : current_frame_info.total_size);
-
- if (size == 0 && epilogue_delay == 0)
- {
- rtx insn = get_last_insn ();
-
- /* If the last insn was a BARRIER, we don't have to write any code
- because a jump (aka return) was put there. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- noepilogue = TRUE;
- }
-
- if (!noepilogue)
- {
- unsigned int pretend_size = current_frame_info.pretend_size;
- unsigned int frame_size = size - pretend_size;
- int restored, fp_restored_p;
- int can_trust_sp_p = !cfun->calls_alloca;
- const char *sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
-
- /* ??? There are lots of optimizations that can be done here.
- EG: Use fp to restore regs if it's closer.
- Maybe in time we'll do them all. For now, always restore regs from
- sp, but don't restore sp if we don't have to. */
-
- if (!can_trust_sp_p)
- {
- gcc_assert (frame_pointer_needed);
- fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n",
- sp_str, fp_str, frame_size, ASM_COMMENT_START);
- }
-
- /* Restore any saved registers. */
- arc_save_restore (file, sp_str, current_frame_info.reg_offset,
- /* The zeroing of these two bits is unnecessary,
- but leave this in for clarity. */
- current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- "ld");
-
- if (MUST_SAVE_RETURN_ADDR)
- fprintf (file, "\tld %s,[%s,%d]\n",
- reg_names[RETURN_ADDR_REGNUM],
- frame_pointer_needed ? fp_str : sp_str,
- UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size));
-
- /* Keep track of how much of the stack pointer we've restored.
- It makes the following a lot more readable. */
- restored = 0;
- fp_restored_p = 0;
-
- /* We try to emit the epilogue delay slot insn right after the load
- of the return address register so that it can execute with the
- stack intact. Secondly, loads are delayed. */
- /* ??? If stack intactness is important, always emit now. */
- if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX)
- {
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- epilogue_delay = NULL_RTX;
- }
-
- if (frame_pointer_needed)
- {
- /* Try to restore the frame pointer in the delay slot. We can't,
- however, if any of these is true. */
- if (epilogue_delay != NULL_RTX
- || !SMALL_INT (frame_size)
- || pretend_size
- || ARC_INTERRUPT_P (fn_type))
- {
- /* Note that we restore fp and sp here! */
- fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
- restored += frame_size;
- fp_restored_p = 1;
- }
- }
- else if (!SMALL_INT (size /* frame_size + pretend_size */)
- || ARC_INTERRUPT_P (fn_type))
- {
- fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size);
- restored += frame_size;
- }
-
- /* These must be done before the return insn because the delay slot
- does the final stack restore. */
- if (ARC_INTERRUPT_P (fn_type))
- {
- if (epilogue_delay)
- {
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- }
- }
-
- /* Emit the return instruction. */
- {
- static const int regs[4] = {
- 0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM
- };
-
- /* Update the flags, if returning from an interrupt handler. */
- if (ARC_INTERRUPT_P (fn_type))
- fprintf (file, "\tj.d.f %s\n", reg_names[regs[fn_type]]);
- else
- fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]);
- }
-
- /* If the only register saved is the return address, we need a
- nop, unless we have an instruction to put into it. Otherwise
- we don't since reloading multiple registers doesn't reference
- the register being loaded. */
-
- if (ARC_INTERRUPT_P (fn_type))
- fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str);
- else if (epilogue_delay != NULL_RTX)
- {
- gcc_assert (!frame_pointer_needed || fp_restored_p);
- gcc_assert (restored >= size);
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
- }
- else if (frame_pointer_needed && !fp_restored_p)
- {
- gcc_assert (SMALL_INT (frame_size));
- /* Note that we restore fp and sp here! */
- fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
- }
- else if (restored < size)
- {
- gcc_assert (SMALL_INT (size - restored));
- fprintf (file, "\tadd %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
- sp_str, sp_str, size - restored);
- }
- else
- fprintf (file, "\tnop\n");
- }
-
- /* Reset state info for each function. */
- current_frame_info = zero_frame_info;
- arc_compute_function_type (NULL_TREE);
-}
-
-/* Define the number of delay slots needed for the function epilogue.
-
- Interrupt handlers can't have any epilogue delay slots (it's always needed
- for something else, I think). For normal functions, we have to worry about
- using call-saved regs as they'll be restored before the delay slot insn.
- Functions with non-empty frames already have enough choices for the epilogue
- delay slot so for now we only consider functions with empty frames. */
-
-int
-arc_delay_slots_for_epilogue (void)
-{
- if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL)
- return 0;
- if (!current_frame_info.initialized)
- (void) arc_compute_frame_size (get_frame_size ());
- if (current_frame_info.total_size == 0)
- return 1;
- return 0;
-}
-
-/* Return true if TRIAL is a valid insn for the epilogue delay slot.
- Any single length instruction which doesn't reference the stack or frame
- pointer or any call-saved register is OK. SLOT will always be 0. */
-
-int
-arc_eligible_for_epilogue_delay (rtx trial, int slot)
-{
- gcc_assert (!slot);
-
- if (get_attr_length (trial) == 1
- /* If registers where saved, presumably there's more than enough
- possibilities for the delay slot. The alternative is something
- more complicated (of course, if we expanded the epilogue as rtl
- this problem would go away). */
- /* ??? Note that this will always be true since only functions with
- empty frames have epilogue delay slots. See
- arc_delay_slots_for_epilogue. */
- && current_frame_info.gmask == 0
- && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
- && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
- return 1;
- return 0;
-}
-
-/* Return true if OP is a shift operator. */
-
-int
-shift_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case ASHIFTRT:
- case LSHIFTRT:
- case ASHIFT:
- return 1;
- default:
- return 0;
- }
-}
-
-/* Output the assembler code for doing a shift.
- We go to a bit of trouble to generate efficient code as the ARC only has
- single bit shifts. This is taken from the h8300 port. We only have one
- mode of shifting and can't access individual bytes like the h8300 can, so
- this is greatly simplified (at the expense of not generating hyper-
- efficient code).
-
- This function is not used if the variable shift insns are present. */
-
-/* ??? We assume the output operand is the same as operand 1.
- This can be optimized (deleted) in the case of 1 bit shifts. */
-/* ??? We use the loop register here. We don't use it elsewhere (yet) and
- using it here will give us a chance to play with it. */
-
-const char *
-output_shift (rtx *operands)
-{
- rtx shift = operands[3];
- enum machine_mode mode = GET_MODE (shift);
- enum rtx_code code = GET_CODE (shift);
- const char *shift_one;
-
- gcc_assert (mode == SImode);
-
- switch (code)
- {
- case ASHIFT: shift_one = "asl %0,%0"; break;
- case ASHIFTRT: shift_one = "asr %0,%0"; break;
- case LSHIFTRT: shift_one = "lsr %0,%0"; break;
- default: gcc_unreachable ();
- }
-
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- if (optimize)
- {
- output_asm_insn ("sub.f 0,%2,0", operands);
- output_asm_insn ("mov lp_count,%2", operands);
- output_asm_insn ("bz 2f", operands);
- }
- else
- output_asm_insn ("mov %4,%2", operands);
- goto shiftloop;
- }
- else
- {
- int n;
-
- /* If the count is negative, make it 0. */
- n = INTVAL (operands[2]);
- if (n < 0)
- n = 0;
- /* If the count is too big, truncate it.
- ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
- do the intuitive thing. */
- else if (n > GET_MODE_BITSIZE (mode))
- n = GET_MODE_BITSIZE (mode);
-
- /* First see if we can do them inline. */
- if (n <= 8)
- {
- while (--n >= 0)
- output_asm_insn (shift_one, operands);
- }
- /* See if we can use a rotate/and. */
- else if (n == BITS_PER_WORD - 1)
- {
- switch (code)
- {
- case ASHIFT :
- output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands);
- break;
- case ASHIFTRT :
- /* The ARC doesn't have a rol insn. Use something else. */
- output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands);
- break;
- case LSHIFTRT :
- /* The ARC doesn't have a rol insn. Use something else. */
- output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands);
- break;
- default:
- break;
- }
- }
- /* Must loop. */
- else
- {
- char buf[100];
-
- if (optimize)
- output_asm_insn ("mov lp_count,%c2", operands);
- else
- output_asm_insn ("mov %4,%c2", operands);
- shiftloop:
- if (optimize)
- {
- if (flag_pic)
- sprintf (buf, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
- ASM_COMMENT_START);
- else
- sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
- ASM_COMMENT_START);
- output_asm_insn (buf, operands);
- output_asm_insn ("sr %4,[lp_start]", operands);
- output_asm_insn ("add %4,%4,1", operands);
- output_asm_insn ("sr %4,[lp_end]", operands);
- output_asm_insn ("nop\n\tnop", operands);
- if (flag_pic)
- fprintf (asm_out_file, "\t%s single insn loop\n",
- ASM_COMMENT_START);
- else
- fprintf (asm_out_file, "1:\t%s single insn loop\n",
- ASM_COMMENT_START);
- output_asm_insn (shift_one, operands);
- fprintf (asm_out_file, "2:\t%s end single insn loop\n",
- ASM_COMMENT_START);
- }
- else
- {
- fprintf (asm_out_file, "1:\t%s begin shift loop\n",
- ASM_COMMENT_START);
- output_asm_insn ("sub.f %4,%4,1", operands);
- output_asm_insn ("nop", operands);
- output_asm_insn ("bn.nd 2f", operands);
- output_asm_insn (shift_one, operands);
- output_asm_insn ("b.nd 1b", operands);
- fprintf (asm_out_file, "2:\t%s end shift loop\n",
- ASM_COMMENT_START);
- }
- }
- }
-
- return "";
-}
-
-/* Nested function support. */
-
-/* Emit RTL insns to initialize the variable parts of a trampoline.
- FNADDR is an RTX for the address of the function's pure code.
- CXT is an RTX for the static chain value for the function. */
-
-void
-arc_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED,
- rtx fnaddr ATTRIBUTE_UNUSED,
- rtx cxt ATTRIBUTE_UNUSED)
-{
-}
-
-/* Set the cpu type and print out other fancy things,
- at the top of the file. */
-
-static void
-arc_file_start (void)
-{
- default_file_start ();
- fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
-}
-
-/* Print operand X (an rtx) in assembler syntax to file FILE.
- CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-
-void
-arc_print_operand (FILE *file, rtx x, int code)
-{
- switch (code)
- {
- case '#' :
- /* Conditional branches. For now these are equivalent. */
- case '*' :
- /* Unconditional branches. Output the appropriate delay slot suffix. */
- if (!final_sequence || XVECLEN (final_sequence, 0) == 1)
- {
- /* There's nothing in the delay slot. */
- fputs (".nd", file);
- }
- else
- {
- rtx jump = XVECEXP (final_sequence, 0, 0);
- rtx delay = XVECEXP (final_sequence, 0, 1);
- if (INSN_ANNULLED_BRANCH_P (jump))
- fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file);
- else
- fputs (".d", file);
- }
- return;
- case '?' : /* with leading "." */
- case '!' : /* without leading "." */
- /* This insn can be conditionally executed. See if the ccfsm machinery
- says it should be conditionalized. */
- if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4)
- {
- /* Is this insn in a delay slot? */
- if (final_sequence && XVECLEN (final_sequence, 0) == 2)
- {
- rtx insn = XVECEXP (final_sequence, 0, 1);
-
- /* If the insn is annulled and is from the target path, we need
- to inverse the condition test. */
- if (INSN_ANNULLED_BRANCH_P (insn))
- {
- if (INSN_FROM_TARGET_P (insn))
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]);
- else
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[arc_ccfsm_current_cc]);
- }
- else
- {
- /* This insn is executed for either path, so don't
- conditionalize it at all. */
- ; /* nothing to do */
- }
- }
- else
- {
- /* This insn isn't in a delay slot. */
- fprintf (file, "%s%s",
- code == '?' ? "." : "",
- arc_condition_codes[arc_ccfsm_current_cc]);
- }
- }
- return;
- case '~' :
- /* Output a nop if we're between a set of the condition codes,
- and a conditional branch. */
- if (last_insn_set_cc_p)
- fputs ("nop\n\t", file);
- return;
- case 'd' :
- fputs (arc_condition_codes[get_arc_condition_code (x)], file);
- return;
- case 'D' :
- fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
- (get_arc_condition_code (x))],
- file);
- return;
- case 'R' :
- /* Write second word of DImode or DFmode reference,
- register or memory. */
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)+1], file);
- else if (GET_CODE (x) == MEM)
- {
- fputc ('[', file);
- /* Handle possible auto-increment. Since it is pre-increment and
- we have already done it, we can just use an offset of four. */
- /* ??? This is taken from rs6000.c I think. I don't think it is
- currently necessary, but keep it around. */
- if (GET_CODE (XEXP (x, 0)) == PRE_INC
- || GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
- else
- output_address (plus_constant (XEXP (x, 0), 4));
- fputc (']', file);
- }
- else
- output_operand_lossage ("invalid operand to %%R code");
- return;
- case 'S' :
- if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
- || GET_CODE (x) == LABEL_REF)
- {
- fprintf (file, "%%st(");
- output_addr_const (file, x);
- fprintf (file, ")");
- return;
- }
- break;
- case 'H' :
- case 'L' :
- if (GET_CODE (x) == REG)
- {
- /* L = least significant word, H = most significant word */
- if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L'))
- fputs (reg_names[REGNO (x)], file);
- else
- fputs (reg_names[REGNO (x)+1], file);
- }
- else if (GET_CODE (x) == CONST_INT
- || GET_CODE (x) == CONST_DOUBLE)
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- fprintf (file, "0x%08lx",
- (long)(code == 'L' ? INTVAL (first) : INTVAL (second)));
- }
- else
- output_operand_lossage ("invalid operand to %%H/%%L code");
- return;
- case 'A' :
- {
- char str[30];
-
- gcc_assert (GET_CODE (x) == CONST_DOUBLE
- && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
-
- real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
- fprintf (file, "%s", str);
- return;
- }
- case 'U' :
- /* Output a load/store with update indicator if appropriate. */
- if (GET_CODE (x) == MEM)
- {
- if (GET_CODE (XEXP (x, 0)) == PRE_INC
- || GET_CODE (XEXP (x, 0)) == PRE_DEC)
- fputs (".a", file);
- }
- else
- output_operand_lossage ("invalid operand to %%U code");
- return;
- case 'V' :
- /* Output cache bypass indicator for a load/store insn. Volatile memory
- refs are defined to use the cache bypass mechanism. */
- if (GET_CODE (x) == MEM)
- {
- if (MEM_VOLATILE_P (x))
- fputs (".di", file);
- }
- else
- output_operand_lossage ("invalid operand to %%V code");
- return;
- case 0 :
- /* Do nothing special. */
- break;
- default :
- /* Unknown flag. */
- output_operand_lossage ("invalid operand output code");
- }
-
- switch (GET_CODE (x))
- {
- case REG :
- fputs (reg_names[REGNO (x)], file);
- break;
- case MEM :
- fputc ('[', file);
- if (GET_CODE (XEXP (x, 0)) == PRE_INC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0),
- GET_MODE_SIZE (GET_MODE (x))));
- else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
- output_address (plus_constant (XEXP (XEXP (x, 0), 0),
- - GET_MODE_SIZE (GET_MODE (x))));
- else
- output_address (XEXP (x, 0));
- fputc (']', file);
- break;
- case CONST_DOUBLE :
- /* We handle SFmode constants here as output_addr_const doesn't. */
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_TYPE d;
- long l;
-
- REAL_VALUE_FROM_CONST_DOUBLE (d, x);
- REAL_VALUE_TO_TARGET_SINGLE (d, l);
- fprintf (file, "0x%08lx", l);
- break;
- }
- /* Fall through. Let output_addr_const deal with it. */
- default :
- output_addr_const (file, x);
- break;
- }
-}
-
-/* Print a memory address as an operand to reference that memory location. */
-
-void
-arc_print_operand_address (FILE *file, rtx addr)
-{
- register rtx base, index = 0;
- int offset = 0;
-
- switch (GET_CODE (addr))
- {
- case REG :
- fputs (reg_names[REGNO (addr)], file);
- break;
- case SYMBOL_REF :
- if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr))
- {
- fprintf (file, "%%st(");
- output_addr_const (file, addr);
- fprintf (file, ")");
- }
- else
- output_addr_const (file, addr);
- break;
- case PLUS :
- if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
- offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
- else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
- offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
- else
- base = XEXP (addr, 0), index = XEXP (addr, 1);
- gcc_assert (GET_CODE (base) == REG);
- fputs (reg_names[REGNO (base)], file);
- if (index == 0)
- {
- if (offset != 0)
- fprintf (file, ",%d", offset);
- }
- else
- {
- switch (GET_CODE (index))
- {
- case REG:
- fprintf (file, ",%s", reg_names[REGNO (index)]);
- break;
- case SYMBOL_REF:
- fputc (',', file), output_addr_const (file, index);
- break;
- default:
- gcc_unreachable ();
- }
- }
- break;
- case PRE_INC :
- case PRE_DEC :
- /* We shouldn't get here as we've lost the mode of the memory object
- (which says how much to inc/dec by. */
- gcc_unreachable ();
- break;
- default :
- output_addr_const (file, addr);
- break;
- }
-}
-
-/* Update compare/branch separation marker. */
-
-static void
-record_cc_ref (rtx insn)
-{
- last_insn_set_cc_p = current_insn_set_cc_p;
-
- switch (get_attr_cond (insn))
- {
- case COND_SET :
- case COND_SET_ZN :
- case COND_SET_ZNC :
- if (get_attr_length (insn) == 1)
- current_insn_set_cc_p = 1;
- else
- current_insn_set_cc_p = 0;
- break;
- default :
- current_insn_set_cc_p = 0;
- break;
- }
-}
-
-/* Conditional execution support.
-
- This is based on the ARM port but for now is much simpler.
-
- A finite state machine takes care of noticing whether or not instructions
- can be conditionally executed, and thus decrease execution time and code
- size by deleting branch instructions. The fsm is controlled by
- final_prescan_insn, and controls the actions of PRINT_OPERAND. The patterns
- in the .md file for the branch insns also have a hand in this. */
-
-/* The state of the fsm controlling condition codes are:
- 0: normal, do nothing special
- 1: don't output this insn
- 2: don't output this insn
- 3: make insns conditional
- 4: make insns conditional
-
- State transitions (state->state by whom, under what condition):
- 0 -> 1 final_prescan_insn, if insn is conditional branch
- 0 -> 2 final_prescan_insn, if the `target' is an unconditional branch
- 1 -> 3 branch patterns, after having not output the conditional branch
- 2 -> 4 branch patterns, after having not output the conditional branch
- 3 -> 0 (*targetm.asm_out.internal_label), if the `target' label is reached
- (the target label has CODE_LABEL_NUMBER equal to
- arc_ccfsm_target_label).
- 4 -> 0 final_prescan_insn, if `target' unconditional branch is reached
-
- If the jump clobbers the conditions then we use states 2 and 4.
-
- A similar thing can be done with conditional return insns.
-
- We also handle separating branches from sets of the condition code.
- This is done here because knowledge of the ccfsm state is required,
- we may not be outputting the branch. */
-
-void
-arc_final_prescan_insn (rtx insn,
- rtx *opvec ATTRIBUTE_UNUSED,
- int noperands ATTRIBUTE_UNUSED)
-{
- /* BODY will hold the body of INSN. */
- register rtx body = PATTERN (insn);
-
- /* This will be 1 if trying to repeat the trick (i.e.: do the `else' part of
- an if/then/else), and things need to be reversed. */
- int reverse = 0;
-
- /* If we start with a return insn, we only succeed if we find another one. */
- int seeking_return = 0;
-
- /* START_INSN will hold the insn from where we start looking. This is the
- first insn after the following code_label if REVERSE is true. */
- rtx start_insn = insn;
-
- /* Update compare/branch separation marker. */
- record_cc_ref (insn);
-
- /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
- We can't do this in macro FINAL_PRESCAN_INSN because its called from
- final_scan_insn which has `optimize' as a local. */
- if (optimize < 2 || TARGET_NO_COND_EXEC)
- return;
-
- /* If in state 4, check if the target branch is reached, in order to
- change back to state 0. */
- if (arc_ccfsm_state == 4)
- {
- if (insn == arc_ccfsm_target_insn)
- {
- arc_ccfsm_target_insn = NULL;
- arc_ccfsm_state = 0;
- }
- return;
- }
-
- /* If in state 3, it is possible to repeat the trick, if this insn is an
- unconditional branch to a label, and immediately following this branch
- is the previous target label which is only used once, and the label this
- branch jumps to is not too far off. Or in other words "we've done the
- `then' part, see if we can do the `else' part." */
- if (arc_ccfsm_state == 3)
- {
- if (simplejump_p (insn))
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- {
- /* ??? Isn't this always a barrier? */
- start_insn = next_nonnote_insn (start_insn);
- }
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
- && LABEL_NUSES (start_insn) == 1)
- reverse = TRUE;
- else
- return;
- }
- else if (GET_CODE (body) == RETURN)
- {
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == BARRIER)
- start_insn = next_nonnote_insn (start_insn);
- if (GET_CODE (start_insn) == CODE_LABEL
- && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
- && LABEL_NUSES (start_insn) == 1)
- {
- reverse = TRUE;
- seeking_return = 1;
- }
- else
- return;
- }
- else
- return;
- }
-
- if (GET_CODE (insn) != JUMP_INSN)
- return;
-
- /* This jump might be paralleled with a clobber of the condition codes,
- the jump should always come first. */
- if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
- body = XVECEXP (body, 0, 0);
-
- if (reverse
- || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
- && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
- {
- int insns_skipped = 0, fail = FALSE, succeed = FALSE;
- /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
- int then_not_else = TRUE;
- /* Nonzero if next insn must be the target label. */
- int next_must_be_target_label_p;
- rtx this_insn = start_insn, label = 0;
-
- /* Register the insn jumped to. */
- if (reverse)
- {
- if (!seeking_return)
- label = XEXP (SET_SRC (body), 0);
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
- label = XEXP (XEXP (SET_SRC (body), 1), 0);
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
- {
- label = XEXP (XEXP (SET_SRC (body), 2), 0);
- then_not_else = FALSE;
- }
- else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
- seeking_return = 1;
- else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
- {
- seeking_return = 1;
- then_not_else = FALSE;
- }
- else
- gcc_unreachable ();
-
- /* See how many insns this branch skips, and what kind of insns. If all
- insns are okay, and the label or unconditional branch to the same
- label is not too far away, succeed. */
- for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
- !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
- insns_skipped++)
- {
- rtx scanbody;
-
- this_insn = next_nonnote_insn (this_insn);
- if (!this_insn)
- break;
-
- if (next_must_be_target_label_p)
- {
- if (GET_CODE (this_insn) == BARRIER)
- continue;
- if (GET_CODE (this_insn) == CODE_LABEL
- && this_insn == label)
- {
- arc_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
- }
-
- scanbody = PATTERN (this_insn);
-
- switch (GET_CODE (this_insn))
- {
- case CODE_LABEL:
- /* Succeed if it is the target label, otherwise fail since
- control falls in from somewhere else. */
- if (this_insn == label)
- {
- arc_ccfsm_state = 1;
- succeed = TRUE;
- }
- else
- fail = TRUE;
- break;
-
- case BARRIER:
- /* Succeed if the following insn is the target label.
- Otherwise fail.
- If return insns are used then the last insn in a function
- will be a barrier. */
- next_must_be_target_label_p = TRUE;
- break;
-
- case CALL_INSN:
- /* Can handle a call insn if there are no insns after it.
- IE: The next "insn" is the target label. We don't have to
- worry about delay slots as such insns are SEQUENCE's inside
- INSN's. ??? It is possible to handle such insns though. */
- if (get_attr_cond (this_insn) == COND_CANUSE)
- next_must_be_target_label_p = TRUE;
- else
- fail = TRUE;
- break;
-
- case JUMP_INSN:
- /* If this is an unconditional branch to the same label, succeed.
- If it is to another label, do nothing. If it is conditional,
- fail. */
- /* ??? Probably, the test for the SET and the PC are unnecessary. */
-
- if (GET_CODE (scanbody) == SET
- && GET_CODE (SET_DEST (scanbody)) == PC)
- {
- if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
- && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
- {
- arc_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
- fail = TRUE;
- }
- else if (GET_CODE (scanbody) == RETURN
- && seeking_return)
- {
- arc_ccfsm_state = 2;
- succeed = TRUE;
- }
- else if (GET_CODE (scanbody) == PARALLEL)
- {
- if (get_attr_cond (this_insn) != COND_CANUSE)
- fail = TRUE;
- }
- break;
-
- case INSN:
- /* We can only do this with insns that can use the condition
- codes (and don't set them). */
- if (GET_CODE (scanbody) == SET
- || GET_CODE (scanbody) == PARALLEL)
- {
- if (get_attr_cond (this_insn) != COND_CANUSE)
- fail = TRUE;
- }
- /* We can't handle other insns like sequences. */
- else
- fail = TRUE;
- break;
-
- default:
- break;
- }
- }
-
- if (succeed)
- {
- if ((!seeking_return) && (arc_ccfsm_state == 1 || reverse))
- arc_ccfsm_target_label = CODE_LABEL_NUMBER (label);
- else
- {
- gcc_assert (seeking_return || arc_ccfsm_state == 2);
- while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
- {
- this_insn = next_nonnote_insn (this_insn);
- gcc_assert (!this_insn
- || (GET_CODE (this_insn) != BARRIER
- && GET_CODE (this_insn) != CODE_LABEL));
- }
- if (!this_insn)
- {
- /* Oh dear! we ran off the end, give up. */
- extract_insn_cached (insn);
- arc_ccfsm_state = 0;
- arc_ccfsm_target_insn = NULL;
- return;
- }
- arc_ccfsm_target_insn = this_insn;
- }
-
- /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
- what it was. */
- if (!reverse)
- arc_ccfsm_current_cc = get_arc_condition_code (XEXP (SET_SRC (body),
- 0));
-
- if (reverse || then_not_else)
- arc_ccfsm_current_cc = ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc);
- }
-
- /* Restore recog_data. Getting the attributes of other insns can
- destroy this array, but final.c assumes that it remains intact
- across this call. */
- extract_insn_cached (insn);
- }
-}
-
-/* Record that we are currently outputting label NUM with prefix PREFIX.
- It it's the label we're looking for, reset the ccfsm machinery.
-
- Called from (*targetm.asm_out.internal_label). */
-
-void
-arc_ccfsm_at_label (const char *prefix, int num)
-{
- if (arc_ccfsm_state == 3 && arc_ccfsm_target_label == num
- && !strcmp (prefix, "L"))
- {
- arc_ccfsm_state = 0;
- arc_ccfsm_target_insn = NULL_RTX;
- }
-}
-
-/* See if the current insn, which is a conditional branch, is to be
- deleted. */
-
-int
-arc_ccfsm_branch_deleted_p (void)
-{
- if (arc_ccfsm_state == 1 || arc_ccfsm_state == 2)
- return 1;
- return 0;
-}
-
-/* Record a branch isn't output because subsequent insns can be
- conditionalized. */
-
-void
-arc_ccfsm_record_branch_deleted (void)
-{
- /* Indicate we're conditionalizing insns now. */
- arc_ccfsm_state += 2;
-
- /* If the next insn is a subroutine call, we still need a nop between the
- cc setter and user. We need to undo the effect of calling record_cc_ref
- for the just deleted branch. */
- current_insn_set_cc_p = last_insn_set_cc_p;
-}
-
-static void
-arc_va_start (tree valist, rtx nextarg)
-{
- /* See arc_setup_incoming_varargs for reasons for this oddity. */
- if (crtl->args.info < 8
- && (crtl->args.info & 1))
- nextarg = plus_constant (nextarg, UNITS_PER_WORD);
-
- std_expand_builtin_va_start (valist, nextarg);
-}
-
-/* This is how to output a definition of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-static void
-arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
-{
- arc_ccfsm_at_label (prefix, labelno);
- default_internal_label (stream, prefix, labelno);
-}
-
-/* Worker function for TARGET_ASM_EXTERNAL_LIBCALL. */
-
-static void
-arc_external_libcall (rtx fun ATTRIBUTE_UNUSED)
-{
-#if 0
-/* On the ARC we want to have libgcc's for multiple cpus in one binary.
- We can't use `assemble_name' here as that will call ASM_OUTPUT_LABELREF
- and we'll get another suffix added on if -mmangle-cpu. */
- if (TARGET_MANGLE_CPU_LIBGCC)
- {
- fprintf (FILE, "\t.rename\t_%s, _%s%s\n",
- XSTR (SYMREF, 0), XSTR (SYMREF, 0),
- arc_mangle_suffix);
- }
-#endif
-}
-
-/* Worker function for TARGET_RETURN_IN_MEMORY. */
-
-static bool
-arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (AGGREGATE_TYPE_P (type))
- return true;
- else
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 8);
- }
-}
-
-/* For ARC, All aggregates and arguments greater than 8 bytes are
- passed by reference. */
-
-static bool
-arc_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- enum machine_mode mode, const_tree type,
- bool named ATTRIBUTE_UNUSED)
-{
- unsigned HOST_WIDE_INT size;
-
- if (type)
- {
- if (AGGREGATE_TYPE_P (type))
- return true;
- size = int_size_in_bytes (type);
- }
- else
- size = GET_MODE_SIZE (mode);
-
- return size > 8;
-}
-
-/* Round SIZE up to a word boundary. */
-#define ROUND_ADVANCE(SIZE) \
-(((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Round arg MODE/TYPE up to the next word boundary. */
-#define ROUND_ADVANCE_ARG(MODE, TYPE) \
-((MODE) == BLKmode \
- ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
- : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
-
-/* Round CUM up to the necessary point for argument MODE/TYPE. */
-#define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
-((((MODE) == BLKmode ? TYPE_ALIGN (TYPE) : GET_MODE_BITSIZE (MODE)) \
- > BITS_PER_WORD) \
- ? (((CUM) + 1) & ~1) \
- : (CUM))
-
-/* Return boolean indicating arg of type TYPE and mode MODE will be passed in
- a reg. This includes arguments that have to be passed by reference as the
- pointer to them is passed in a reg if one is available (and that is what
- we're given). */
-#define PASS_IN_REG_P(CUM, MODE, TYPE) \
-((CUM) < MAX_ARC_PARM_REGS \
- && ((ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) \
- + ROUND_ADVANCE_ARG ((MODE), (TYPE)) \
- <= MAX_ARC_PARM_REGS)))
-
-/* Determine where to put an argument to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
- and the rest are pushed. */
-
-static rtx
-arc_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- return (PASS_IN_REG_P (*cum, mode, type)
- ? gen_rtx_REG (mode, ROUND_ADVANCE_CUM (*cum, mode, type))
- : NULL_RTX);
-}
-
-/* Worker function for TARGET_FUNCTION_ARG_ADVANCE. */
-
-static void
-arc_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- *cum = (ROUND_ADVANCE_CUM (*cum, mode, type)
- + ROUND_ADVANCE_ARG (mode, type));
-}
-
-/* Worker function for TARGET_FUNCTION_ARG_BOUNDARY. */
-
-static unsigned int
-arc_function_arg_boundary (enum machine_mode mode, const_tree type)
-{
- return (type != NULL_TREE
- ? TYPE_ALIGN (type)
- : (GET_MODE_BITSIZE (mode) <= PARM_BOUNDARY
- ? PARM_BOUNDARY
- : 2 * PARM_BOUNDARY));
-}
-
-/* Trampolines. */
-/* ??? This doesn't work yet because GCC will use as the address of a nested
- function the address of the trampoline. We need to use that address
- right shifted by 2. It looks like we'll need PSImode after all. :-(
-
- ??? The above comment sounds like it's doable via
- TARGET_TRAMPOLINE_ADJUST_ADDRESS; no PSImode needed.
-
- On the ARC, the trampoline is quite simple as we have 32-bit immediate
- constants.
-
- mov r24,STATIC
- j.nd FUNCTION
-*/
-
-static void
-arc_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
-{
- rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
- rtx mem;
-
- mem = adjust_address (m_tramp, SImode, 0);
- emit_move_insn (mem, GEN_INT (0x631f7c00));
-
- mem = adjust_address (m_tramp, SImode, 4);
- emit_move_insn (mem, chain_value);
-
- mem = adjust_address (m_tramp, SImode, 8);
- emit_move_insn (mem, GEN_INT (0x381f0000));
-
- mem = adjust_address (m_tramp, SImode, 12);
- emit_move_insn (mem, fnaddr);
-
- emit_insn (gen_flush_icache (m_tramp));
-}
-
-/* Worker function for TARGET_CONDITIONAL_REGISTER_USAGE. */
-
-static void
-arc_conditional_register_usage (void)
-{
- if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
- {
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- }
-}
-
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
deleted file mode 100644
index 0f2b99c199c..00000000000
--- a/gcc/config/arc/arc.h
+++ /dev/null
@@ -1,935 +0,0 @@
-/* Definitions of target machine for GNU compiler, Argonaut ARC cpu.
- Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005,
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* ??? This is an old port, and is undoubtedly suffering from bit rot. */
-
-/* Things to do:
-
- - incscc, decscc?
- - print active compiler options in assembler output
-*/
-
-
-#undef ASM_SPEC
-#undef LINK_SPEC
-#undef LIB_SPEC
-#undef STARTFILE_SPEC
-#undef ENDFILE_SPEC
-#undef SIZE_TYPE
-#undef PTRDIFF_TYPE
-#undef WCHAR_TYPE
-#undef WCHAR_TYPE_SIZE
-#undef ASM_OUTPUT_LABELREF
-
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (arc)")
-
-/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__arc__"); \
- if (TARGET_BIG_ENDIAN) \
- builtin_define ("__big_endian__"); \
- if (arc_cpu_type == 0) \
- builtin_define ("__base__"); \
- builtin_assert ("cpu=arc"); \
- builtin_assert ("machine=arc"); \
- } while (0)
-
-/* Pass -mmangle-cpu if we get -mcpu=*.
- Doing it this way lets one have it on as default with -mcpu=*,
- but also lets one turn it off with -mno-mangle-cpu. */
-#define CC1_SPEC "\
-%{mcpu=*:-mmangle-cpu} \
-%{EB:%{EL:%emay not use both -EB and -EL}} \
-%{EB:-mbig-endian} %{EL:-mlittle-endian} \
-"
-
-#define ASM_SPEC "%{EB} %{EL}"
-
-#define LINK_SPEC "%{v} %{EB} %{EL}"
-
-#define LIB_SPEC "-lc"
-
-#define STARTFILE_SPEC "%{!shared:crt0.o%s} crtinit.o%s"
-
-#define ENDFILE_SPEC "crtfini.o%s"
-
-/* Instruction set characteristics.
- These are internal macros, set by the appropriate -mcpu= option. */
-
-/* Nonzero means the cpu has a barrel shifter. */
-#define TARGET_SHIFTER 0
-
-/* Which cpu we're compiling for. */
-extern int arc_cpu_type;
-
-/* Check if CPU is an extension and set `arc_cpu_type' and `arc_mangle_cpu'
- appropriately. The result should be nonzero if the cpu is recognized,
- otherwise zero. This is intended to be redefined in a cover file.
- This is used by arc_handle_option. */
-#define ARC_EXTENSION_CPU(cpu) 0
-
-
-/* Target machine storage layout. */
-
-/* Define this if most significant bit is lowest numbered
- in instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 1
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
-
-/* Define this if most significant word of a multiword number is the lowest
- numbered. */
-#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
-
-/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD 4
-
-/* Define this macro if it is advisable to hold scalars in registers
- in a wider mode than that declared by the program. In such cases,
- the value is constrained to be within the bounds of the declared
- type, but kept valid in the wider mode. The signedness of the
- extension may differ from that of the type. */
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
-{ \
- (MODE) = SImode; \
-}
-
-/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-#define PARM_BOUNDARY 32
-
-/* Boundary (in *bits*) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY 64
-
-/* ALIGN FRAMES on word boundaries */
-#define ARC_STACK_ALIGN(LOC) (((LOC)+7) & ~7)
-
-/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 32
-
-/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY 32
-
-/* Every structure's size must be a multiple of this. */
-#define STRUCTURE_SIZE_BOUNDARY 8
-
-/* A bit-field declared as `int' forces `int' alignment for the struct. */
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/* No data type wants to be aligned rounder than this. */
-/* This is bigger than currently necessary for the ARC. If 8 byte floats are
- ever added it's not clear whether they'll need such alignment or not. For
- now we assume they will. We can always relax it if necessary but the
- reverse isn't true. */
-#define BIGGEST_ALIGNMENT 64
-
-/* The best alignment to use in cases where we have a choice. */
-#define FASTEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- ((TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < FASTEST_ALIGNMENT) \
- ? FASTEST_ALIGNMENT : (ALIGN))
-
-/* Make arrays of chars word-aligned for the same reasons. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE \
- && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < FASTEST_ALIGNMENT ? FASTEST_ALIGNMENT : (ALIGN))
-
-/* Set this nonzero if move instructions will actually fail to work
- when given unaligned data. */
-/* On the ARC the lower address bits are masked to 0 as necessary. The chip
- won't croak when given an unaligned address, but the insn will still fail
- to produce the correct result. */
-#define STRICT_ALIGNMENT 1
-
-/* Layout of source language data types. */
-
-#define SHORT_TYPE_SIZE 16
-#define INT_TYPE_SIZE 32
-#define LONG_TYPE_SIZE 32
-#define LONG_LONG_TYPE_SIZE 64
-#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-#define DEFAULT_SIGNED_CHAR 1
-
-#define SIZE_TYPE "long unsigned int"
-#define PTRDIFF_TYPE "long int"
-#define WCHAR_TYPE "short unsigned int"
-#define WCHAR_TYPE_SIZE 16
-
-/* Standard register usage. */
-
-/* Number of actual hardware registers.
- The hardware registers are assigned numbers for the compiler
- from 0 to just below FIRST_PSEUDO_REGISTER.
- All registers that the compiler knows about must be given numbers,
- even those that are not normally considered general registers. */
-/* Registers 61, 62, and 63 are not really registers and we needn't treat
- them as such. We still need a register for the condition code. */
-#define FIRST_PSEUDO_REGISTER 62
-
-/* 1 for registers that have pervasive standard uses
- and are not available for the register allocator.
-
- 0-28 - general purpose registers
- 29 - ilink1 (interrupt link register)
- 30 - ilink2 (interrupt link register)
- 31 - blink (branch link register)
- 32-59 - reserved for extensions
- 60 - LP_COUNT
- 61 - condition code
-
- For doc purposes:
- 61 - short immediate data indicator (setting flags)
- 62 - long immediate data indicator
- 63 - short immediate data indicator (not setting flags).
-
- The general purpose registers are further broken down into:
- 0-7 - arguments/results
- 8-15 - call used
- 16-23 - call saved
- 24 - call used, static chain pointer
- 25 - call used, gptmp
- 26 - global pointer
- 27 - frame pointer
- 28 - stack pointer
-
- By default, the extension registers are not available. */
-
-#define FIXED_REGISTERS \
-{ 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 1, 1, 1, 1, 0, \
- \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1 }
-
-/* 1 for registers not available across function calls.
- These must include the FIXED_REGISTERS and also any
- registers that can be used without being saved.
- The latter must include the registers where values are returned
- and the register where structure-value addresses are passed.
- Aside from that, you can include as many other registers as you like. */
-
-#define CALL_USED_REGISTERS \
-{ 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 0, 0, 0, 0, 0, 0, 0, 0, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1 }
-
-/* If defined, an initializer for a vector of integers, containing the
- numbers of hard registers in the order in which GCC should
- prefer to use them (from most preferred to least). */
-#define REG_ALLOC_ORDER \
-{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, \
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 31, \
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, \
- 27, 28, 29, 30 }
-
-/* Return number of consecutive hard regs needed starting at reg REGNO
- to hold something of mode MODE.
- This is ordinarily the length in words of a value of mode MODE
- but can be less for certain modes in special long registers. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
-extern const unsigned int arc_hard_regno_mode_ok[];
-extern unsigned int arc_mode_class[];
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
-((arc_hard_regno_mode_ok[REGNO] & arc_mode_class[MODE]) != 0)
-
-/* A C expression that is nonzero if it is desirable to choose
- register allocation so as to avoid move instructions between a
- value of mode MODE1 and a value of mode MODE2.
-
- If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R,
- MODE2)' are ever different for any R, then `MODES_TIEABLE_P (MODE1,
- MODE2)' must be zero. */
-
-/* Tie QI/HI/SI modes together. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
-(GET_MODE_CLASS (MODE1) == MODE_INT \
- && GET_MODE_CLASS (MODE2) == MODE_INT \
- && GET_MODE_SIZE (MODE1) <= UNITS_PER_WORD \
- && GET_MODE_SIZE (MODE2) <= UNITS_PER_WORD)
-
-/* Register classes and constants. */
-
-/* Define the classes of registers for register constraints in the
- machine description. Also define ranges of constants.
-
- One of the classes must always be named ALL_REGS and include all hard regs.
- If there is more than one class, another class must be named NO_REGS
- and contain no registers.
-
- The name GENERAL_REGS must be the name of a class (or an alias for
- another name such as ALL_REGS). This is the class of registers
- that is allowed by "g" or "r" in a register constraint.
- Also, registers outside this class are allocated only when
- instructions express preferences for them.
-
- The classes must be numbered in nondecreasing order; that is,
- a larger-numbered class must never be contained completely
- in a smaller-numbered class.
-
- For any two classes, it is very desirable that there be another
- class that represents their union.
-
- It is important that any condition codes have class NO_REGS.
- See `register_operand'. */
-
-enum reg_class {
- NO_REGS, LPCOUNT_REG, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
-};
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
-{ "NO_REGS", "LPCOUNT_REG", "GENERAL_REGS", "ALL_REGS" }
-
-/* Define which registers fit in which classes.
- This is an initializer for a vector of HARD_REG_SET
- of length N_REG_CLASSES. */
-
-#define REG_CLASS_CONTENTS \
-{ {0, 0}, {0, 0x10000000}, {0xffffffff, 0xfffffff}, \
- {0xffffffff, 0x1fffffff} }
-
-/* The same information, inverted:
- Return the class number of the smallest class containing
- reg number REGNO. This could be a conditional expression
- or could index an array. */
-extern enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
-#define REGNO_REG_CLASS(REGNO) \
-(arc_regno_reg_class[REGNO])
-
-/* The class value for index registers, and the one for base regs. */
-#define INDEX_REG_CLASS GENERAL_REGS
-#define BASE_REG_CLASS GENERAL_REGS
-
-/* Get reg_class from a letter such as appears in the machine description. */
-#define REG_CLASS_FROM_LETTER(C) \
-((C) == 'l' ? LPCOUNT_REG /* ??? needed? */ \
- : NO_REGS)
-
-/* These assume that REGNO is a hard or pseudo reg number.
- They give nonzero only if REGNO is a hard reg of the suitable class
- or a pseudo reg currently allocated to a suitable hard reg.
- Since they use reg_renumber, they are safe only once reg_renumber
- has been allocated, which happens in local-alloc.c. */
-#define REGNO_OK_FOR_BASE_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < 32)
-
-/* Return the maximum number of consecutive registers
- needed to represent mode MODE in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
-((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* The letters I, J, K, L, M, N, O, P in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- This macro defines what the ranges are.
- C is the letter, and VALUE is a constant value.
- Return 1 if VALUE is in the range specified by C. */
-/* 'I' is used for short immediates (always signed).
- 'J' is used for long immediates.
- 'K' is used for any constant up to 64 bits (for 64x32 situations?). */
-
-/* local to this file */
-#define SMALL_INT(X) ((unsigned) ((X) + 0x100) < 0x200)
-/* local to this file */
-#define LARGE_INT(X) \
-((X) >= (-(HOST_WIDE_INT) 0x7fffffff - 1) \
- && (unsigned HOST_WIDE_INT)(X) <= (unsigned HOST_WIDE_INT) 0xffffffff)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? SMALL_INT (VALUE) \
- : (C) == 'J' ? LARGE_INT (VALUE) \
- : (C) == 'K' ? 1 \
- : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself. */
-/* 'G' is used for integer values for the multiplication insns where the
- operands are extended from 4 bytes to 8 bytes.
- 'H' is used when any 64-bit constant is allowed. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'G' ? arc_double_limm_p (VALUE) \
- : (C) == 'H' ? 1 \
- : 0)
-
-/* A C expression that defines the optional machine-dependent constraint
- letters that can be used to segregate specific types of operands,
- usually memory references, for the target machine. It should return 1 if
- VALUE corresponds to the operand type represented by the constraint letter
- C. If C is not defined as an extra constraint, the value returned should
- be 0 regardless of VALUE. */
-/* ??? This currently isn't used. Waiting for PIC. */
-#if 0
-#define EXTRA_CONSTRAINT(VALUE, C) \
-((C) == 'R' ? (SYMBOL_REF_FUNCTION_P (VALUE) || GET_CODE (VALUE) == LABEL_REF) \
- : 0)
-#endif
-
-/* Stack layout and stack pointer usage. */
-
-/* Define this macro if pushing a word onto the stack moves the stack
- pointer to a smaller address. */
-#define STACK_GROWS_DOWNWARD
-
-/* Define this to nonzero if the nominal address of the stack frame
- is at the high-address end of the local variables;
- that is, each additional local variable allocated
- goes at a more negative offset in the frame. */
-#define FRAME_GROWS_DOWNWARD 1
-
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated. */
-#define STARTING_FRAME_OFFSET 0
-
-/* Offset from the stack pointer register to the first location at which
- outgoing arguments are placed. */
-#define STACK_POINTER_OFFSET FIRST_PARM_OFFSET (0)
-
-/* Offset of first parameter from the argument pointer register value. */
-/* 4 bytes for each of previous fp, return address, and previous gp.
- 4 byte reserved area for future considerations. */
-#define FIRST_PARM_OFFSET(FNDECL) 16
-
-/* A C expression whose value is RTL representing the address in a
- stack frame where the pointer to the caller's frame is stored.
- Assume that FRAMEADDR is an RTL expression for the address of the
- stack frame itself.
-
- If you don't define this macro, the default is to return the value
- of FRAMEADDR--that is, the stack frame address is also the address
- of the stack word that points to the previous frame. */
-/* ??? unfinished */
-/*define DYNAMIC_CHAIN_ADDRESS (FRAMEADDR)*/
-
-/* A C expression whose value is RTL representing the value of the
- return address for the frame COUNT steps up from the current frame.
- FRAMEADDR is the frame pointer of the COUNT frame, or the frame
- pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME'
- is defined. */
-/* The current return address is in r31. The return address of anything
- farther back is at [%fp,4]. */
-#if 0 /* The default value should work. */
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
-(((COUNT) == -1) \
- ? gen_rtx_REG (Pmode, 31) \
- : copy_to_reg (gen_rtx_MEM (Pmode, \
- memory_address (Pmode, \
- plus_constant ((FRAME), \
- UNITS_PER_WORD)))))
-#endif
-
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM 28
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 27
-
-/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
-
-/* Register in which static-chain is passed to a function. This must
- not be a register used by the prologue. */
-#define STATIC_CHAIN_REGNUM 24
-
-/* C statement to store the difference between the frame pointer
- and the stack pointer values immediately after the function prologue. */
-#define INITIAL_FRAME_POINTER_OFFSET(VAR) \
-((VAR) = arc_compute_frame_size (get_frame_size ()))
-
-/* Function argument passing. */
-
-/* If defined, the maximum amount of space required for outgoing
- arguments will be computed and placed into the variable
- `crtl->outgoing_args_size'. No space will be pushed
- onto the stack for each call; instead, the function prologue should
- increase the stack frame size by this amount. */
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-/* Define a data type for recording info about an argument list
- during the scan of that argument list. This data type should
- hold all necessary information about the function itself
- and about the args processed so far, enough to enable macros
- such as FUNCTION_ARG to determine where the next arg should go. */
-#define CUMULATIVE_ARGS int
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
-((CUM) = 0)
-
-/* The number of registers used for parameter passing. Local to this file. */
-#define MAX_ARC_PARM_REGS 8
-
-/* 1 if N is a possible register number for function argument passing. */
-#define FUNCTION_ARG_REGNO_P(N) \
-((unsigned) (N) < MAX_ARC_PARM_REGS)
-
-
-/* Function results. */
-
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx_REG (TYPE_MODE (VALTYPE), 0)
-
-/* Define how to find the value returned by a library function
- assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
-
-/* 1 if N is a possible register number for a function value
- as seen by the caller. */
-/* ??? What about r1 in DI/DF values. */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
-
-/* Tell GCC to use TARGET_RETURN_IN_MEMORY. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
- the stack pointer does not matter. The value is tested only in
- functions that have frame pointers.
- No definition is equivalent to always zero. */
-#define EXIT_IGNORE_STACK 0
-
-/* Epilogue delay slots. */
-#define DELAY_SLOTS_FOR_EPILOGUE arc_delay_slots_for_epilogue ()
-
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(TRIAL, SLOTS_FILLED) \
-arc_eligible_for_epilogue_delay (TRIAL, SLOTS_FILLED)
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO)
-
-#define TRAMPOLINE_ALIGNMENT 32
-#define TRAMPOLINE_SIZE 16
-
-/* Addressing modes, and classification of registers for them. */
-
-/* Maximum number of registers that can appear in a valid memory address. */
-/* The `ld' insn allows 2, but the `st' insn only allows 1. */
-#define MAX_REGS_PER_ADDRESS 1
-
-/* We have pre inc/dec (load/store with update). */
-#define HAVE_PRE_INCREMENT 1
-#define HAVE_PRE_DECREMENT 1
-
-/* Recognize any constant value that is a valid address. */
-#define CONSTANT_ADDRESS_P(X) \
-(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST)
-
-/* Nonzero if the constant value X is a legitimate general operand.
- We can handle any 32- or 64-bit constant. */
-/* "1" should work since the largest constant should be a 64 bit critter. */
-/* ??? Not sure what to do for 64x32 compiler. */
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
- and check its validity for a certain class.
- We have two alternate definitions for each of them.
- The usual definition accepts all pseudo regs; the other rejects
- them unless they have been allocated suitable hard regs.
- The symbol REG_OK_STRICT causes the latter definition to be used.
-
- Most source files want to accept pseudo regs in the hope that
- they will get allocated to the class that the insn wants them to be in.
- Source files for reload pass need to be strict.
- After reload, it makes no difference, since pseudo regs have
- been eliminated by then. */
-
-#ifndef REG_OK_STRICT
-
-/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. */
-#define REG_OK_FOR_INDEX_P(X) \
-((unsigned) REGNO (X) - 32 >= FIRST_PSEUDO_REGISTER - 32)
-/* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) \
-((unsigned) REGNO (X) - 32 >= FIRST_PSEUDO_REGISTER - 32)
-
-#else
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-/* Nonzero if X is a hard reg that can be used as a base reg. */
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#endif
-
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address. */
-/* The `ld' insn allows [reg],[reg+shimm],[reg+limm],[reg+reg],[limm]
- but the `st' insn only allows [reg],[reg+shimm],[limm].
- The only thing we can do is only allow the most strict case `st' and hope
- other parts optimize out the restrictions for `ld'. */
-
-/* local to this file */
-#define RTX_OK_FOR_BASE_P(X) \
-(REG_P (X) && REG_OK_FOR_BASE_P (X))
-
-/* local to this file */
-#define RTX_OK_FOR_INDEX_P(X) \
-(0 && /*???*/ REG_P (X) && REG_OK_FOR_INDEX_P (X))
-
-/* local to this file */
-/* ??? Loads can handle any constant, stores can only handle small ones. */
-#define RTX_OK_FOR_OFFSET_P(X) \
-(GET_CODE (X) == CONST_INT && SMALL_INT (INTVAL (X)))
-
-#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
-(GET_CODE (X) == PLUS \
- && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
- && (RTX_OK_FOR_INDEX_P (XEXP (X, 1)) \
- || RTX_OK_FOR_OFFSET_P (XEXP (X, 1))))
-
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
-{ if (RTX_OK_FOR_BASE_P (X)) \
- goto ADDR; \
- if (LEGITIMATE_OFFSET_ADDRESS_P ((MODE), (X))) \
- goto ADDR; \
- if (GET_CODE (X) == CONST_INT && LARGE_INT (INTVAL (X))) \
- goto ADDR; \
- if (GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == CONST) \
- goto ADDR; \
- if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \
- /* We're restricted here by the `st' insn. */ \
- && RTX_OK_FOR_BASE_P (XEXP ((X), 0))) \
- goto ADDR; \
-}
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) \
-arc_select_cc_mode (OP, X, Y)
-
-/* Return nonzero if SELECT_CC_MODE will never return MODE for a
- floating point inequality comparison. */
-#define REVERSIBLE_CC_MODE(MODE) 1 /*???*/
-
-/* Costs. */
-
-/* Compute extra cost of moving data between one register class
- and another. */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) 2
-
-/* Compute the cost of moving data between registers and memory. */
-/* Memory is 3 times as expensive as registers.
- ??? Is that the right way to look at it? */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
-(GET_MODE_SIZE (MODE) <= UNITS_PER_WORD ? 6 : 12)
-
-/* The cost of a branch insn. */
-/* ??? What's the right value here? Branches are certainly more
- expensive than reg->reg moves. */
-#define BRANCH_COST(speed_p, predictable_p) 2
-
-/* Nonzero if access to memory by bytes is slow and undesirable.
- For RISC chips, it means that access to memory by bytes is no
- better than access by words when possible, so grab a whole word
- and maybe make use of that. */
-#define SLOW_BYTE_ACCESS 1
-
-/* Define this macro if it is as good or better to call a constant
- function address than to call an address kept in a register. */
-/* On the ARC, calling through registers is slow. */
-#define NO_FUNCTION_CSE
-
-/* Section selection. */
-/* WARNING: These section names also appear in dwarfout.c. */
-
-/* The names of the text, data, and readonly-data sections are runtime
- selectable. */
-
-#define ARC_SECTION_FORMAT "\t.section %s"
-#define ARC_DEFAULT_TEXT_SECTION ".text"
-#define ARC_DEFAULT_DATA_SECTION ".data"
-#define ARC_DEFAULT_RODATA_SECTION ".rodata"
-
-extern const char *arc_text_section, *arc_data_section, *arc_rodata_section;
-
-/* initfini.c uses this in an asm. */
-#if defined (CRT_INIT) || defined (CRT_FINI)
-#define TEXT_SECTION_ASM_OP "\t.section .text"
-#else
-#define TEXT_SECTION_ASM_OP arc_text_section
-#endif
-#define DATA_SECTION_ASM_OP arc_data_section
-
-#undef READONLY_DATA_SECTION_ASM_OP
-#define READONLY_DATA_SECTION_ASM_OP arc_rodata_section
-
-#define BSS_SECTION_ASM_OP "\t.section .bss"
-
-/* Define this macro if jump tables (for tablejump insns) should be
- output in the text section, along with the assembler instructions.
- Otherwise, the readonly data section is used.
- This macro is irrelevant if there is no separate readonly data section. */
-/*#define JUMP_TABLES_IN_TEXT_SECTION*/
-
-/* For DWARF. Marginally different than default so output is "prettier"
- (and consistent with above). */
-#define PUSHSECTION_ASM_OP "\t.section "
-
-/* Tell crtstuff.c we're using ELF. */
-#define OBJECT_FORMAT_ELF
-
-/* PIC */
-
-/* The register number of the register used to address a table of static
- data addresses in memory. In some cases this register is defined by a
- processor's ``application binary interface'' (ABI). When this macro
- is defined, RTL is generated for this register once, as with the stack
- pointer and frame pointer registers. If this macro is not defined, it
- is up to the machine-dependent files to allocate such a register (if
- necessary). */
-#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 26 : INVALID_REGNUM)
-
-/* Define this macro if the register defined by PIC_OFFSET_TABLE_REGNUM is
- clobbered by calls. Do not define this macro if PIC_OFFSET_TABLE_REGNUM
- is not defined. */
-/* This register is call-saved on the ARC. */
-/*#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED*/
-
-/* A C expression that is nonzero if X is a legitimate immediate
- operand on the target machine when generating position independent code.
- You can assume that X satisfies CONSTANT_P, so you need not
- check this. You can also assume `flag_pic' is true, so you need not
- check it either. You need not define this macro if all constants
- (including SYMBOL_REF) can be immediate operands when generating
- position independent code. */
-/*#define LEGITIMATE_PIC_OPERAND_P(X)*/
-
-/* Control the assembler format that we output. */
-
-/* A C string constant describing how to begin a comment in the target
- assembler language. The compiler assumes that the comment will
- end at the end of the line. */
-#define ASM_COMMENT_START ";"
-
-/* Output to assembler file text saying following lines
- may contain character constants, extra white space, comments, etc. */
-#define ASM_APP_ON ""
-
-/* Output to assembler file text saying following lines
- no longer contain unusual constructs. */
-#define ASM_APP_OFF ""
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.global\t"
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-/* We mangle all user labels to provide protection from linking code
- compiled for different cpus. */
-/* We work around a dwarfout.c deficiency by watching for labels from it and
- not adding the '_' prefix nor the cpu suffix. There is a comment in
- dwarfout.c that says it should be using (*targetm.asm_out.internal_label). */
-extern const char *arc_mangle_cpu;
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
-do { \
- if ((NAME)[0] == '.' && (NAME)[1] == 'L') \
- fprintf (FILE, "%s", NAME); \
- else \
- { \
- fputc ('_', FILE); \
- if (TARGET_MANGLE_CPU && arc_mangle_cpu != NULL) \
- fprintf (FILE, "%s_", arc_mangle_cpu); \
- fprintf (FILE, "%s", NAME); \
- } \
-} while (0)
-
-/* Assembler pseudo-op to equate one value with another. */
-/* ??? This is needed because dwarfout.c provides a default definition too
- late for defaults.h (which contains the default definition of ASM_OUTPUT_DEF
- that we use). */
-#define SET_ASM_OP "\t.set\t"
-
-/* How to refer to registers in assembler output.
- This sequence is indexed by compiler's hard-register-number (see above). */
-#define REGISTER_NAMES \
-{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
- "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \
- "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \
- "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \
- "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \
- "r56", "r57", "r58", "r59", "lp_count", "cc"}
-
-/* Entry to the insn conditionalizer. */
-#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
-arc_final_prescan_insn (INSN, OPVEC, NOPERANDS)
-
-/* A C expression which evaluates to true if CODE is a valid
- punctuation character for use in the `PRINT_OPERAND' macro. */
-extern char arc_punct_chars[256];
-#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
-arc_punct_chars[(unsigned char) (CHAR)]
-
-/* Print operand X (an rtx) in assembler syntax to file FILE.
- CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-#define PRINT_OPERAND(FILE, X, CODE) \
-arc_print_operand (FILE, X, CODE)
-
-/* A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand that is a memory
- reference whose address is ADDR. ADDR is an RTL expression. */
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
-arc_print_operand_address (FILE, ADDR)
-
-/* This is how to output an element of a case-vector that is absolute. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
-do { \
- char label[30]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- fprintf (FILE, "\t.word %%st("); \
- assemble_name (FILE, label); \
- fprintf (FILE, ")\n"); \
-} while (0)
-
-/* This is how to output an element of a case-vector that is relative. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
-do { \
- char label[30]; \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", VALUE); \
- fprintf (FILE, "\t.word %%st("); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- ASM_GENERATE_INTERNAL_LABEL (label, "L", REL); \
- assemble_name (FILE, label); \
- fprintf (FILE, ")\n"); \
-} while (0)
-
-/* The desired alignment for the location counter at the beginning
- of a loop. */
-/* On the ARC, align loops to 32 byte boundaries (cache line size)
- if -malign-loops. */
-#define LOOP_ALIGN(LABEL) (TARGET_ALIGN_LOOPS ? 5 : 0)
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
-do { if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); } while (0)
-
-/* Debugging information. */
-
-/* Generate DBX and DWARF debugging information. */
-#define DBX_DEBUGGING_INFO 1
-
-/* Prefer STABS (for now). */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-/* Turn off splitting of long stabs. */
-#define DBX_CONTIN_LENGTH 0
-
-/* Miscellaneous. */
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
-
-/* Define if operations between registers always perform the operation
- on the full register even if a narrower mode is specified. */
-#define WORD_REGISTER_OPERATIONS
-
-/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
- will either zero-extend or sign-extend. The value of this macro should
- be the code that says which one of the two operations is implicitly
- done, UNKNOWN if none. */
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-/* Max number of bytes we can move from memory to memory
- in one reasonably fast instruction. */
-#define MOVE_MAX 4
-
-/* Define this to be nonzero if shift instructions ignore all but the low-order
- few bits. */
-#define SHIFT_COUNT_TRUNCATED 1
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-/* Specify the machine mode that pointers have.
- After generation of rtl, the compiler makes no further distinction
- between pointers and any other objects of this machine mode. */
-/* ??? The arc doesn't have full 32-bit pointers, but making this PSImode has
- its own problems (you have to add extendpsisi2 and trucnsipsi2 but how does
- one do it without getting excess code?). Try to avoid it. */
-#define Pmode SImode
-
-/* A function address in a call instruction. */
-#define FUNCTION_MODE SImode
-
-/* alloca should avoid clobbering the old register save area. */
-/* ??? Not defined in tm.texi. */
-#define SETJMP_VIA_SAVE_AREA
-
-/* ARC function types. */
-enum arc_function_type {
- ARC_FUNCTION_UNKNOWN, ARC_FUNCTION_NORMAL,
- /* These are interrupt handlers. The name corresponds to the register
- name that contains the return address. */
- ARC_FUNCTION_ILINK1, ARC_FUNCTION_ILINK2
-};
-#define ARC_INTERRUPT_P(TYPE) \
-((TYPE) == ARC_FUNCTION_ILINK1 || (TYPE) == ARC_FUNCTION_ILINK2)
-/* Compute the type of a function from its DECL. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
deleted file mode 100644
index 09e47daf1d1..00000000000
--- a/gcc/config/arc/arc.md
+++ /dev/null
@@ -1,1376 +0,0 @@
-;; Machine description of the Argonaut ARC cpu for GNU C compiler
-;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008
-;; Free Software Foundation, Inc.
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
-
-;; ??? This is an old port, and is undoubtedly suffering from bit rot.
-
-;; Insn type. Used to default other attribute values.
-
-(define_attr "type"
- "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
- (const_string "binary"))
-
-;; Length (in # of insns, long immediate constants counted too).
-;; ??? There's a nasty interaction between the conditional execution fsm
-;; and insn lengths: insns with shimm values cannot be conditionally executed.
-(define_attr "length" ""
- (cond [(eq_attr "type" "load")
- (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "store")
- (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "move,unary,compare")
- (if_then_else (match_operand 1 "long_immediate_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "binary,mul")
- (if_then_else (match_operand 2 "long_immediate_operand" "")
- (const_int 2) (const_int 1))
-
- (eq_attr "type" "cmove")
- (if_then_else (match_operand 2 "register_operand" "")
- (const_int 1) (const_int 2))
-
- (eq_attr "type" "multi") (const_int 2)
- ]
-
- (const_int 1)))
-
-;; The length here is the length of a single asm. Unfortunately it might be
-;; 1 or 2 so we must allow for 2. That's ok though. How often will users
-;; lament asm's not being put in delay slots?
-(define_asm_attributes
- [(set_attr "length" "2")
- (set_attr "type" "multi")])
-
-;; Condition codes: this one is used by final_prescan_insn to speed up
-;; conditionalizing instructions. It saves having to scan the rtl to see if
-;; it uses or alters the condition codes.
-
-;; USE: This insn uses the condition codes (e.g.: a conditional branch).
-;; CANUSE: This insn can use the condition codes (for conditional execution).
-;; SET: All condition codes are set by this insn.
-;; SET_ZN: the Z and N flags are set by this insn.
-;; SET_ZNC: the Z, N, and C flags are set by this insn.
-;; CLOB: The condition codes are set to unknown values by this insn.
-;; NOCOND: This insn can't use and doesn't affect the condition codes.
-
-(define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
- (cond [(and (eq_attr "type" "unary,binary,move")
- (eq_attr "length" "1"))
- (const_string "canuse")
-
- (eq_attr "type" "compare")
- (const_string "set")
-
- (eq_attr "type" "cmove,branch")
- (const_string "use")
-
- (eq_attr "type" "multi,misc")
- (const_string "clob")
- ]
-
- (const_string "nocond")))
-
-;; Delay slots.
-
-(define_attr "in_delay_slot" "false,true"
- (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
- (const_string "false")
- ]
-
- (if_then_else (eq_attr "length" "1")
- (const_string "true")
- (const_string "false"))))
-
-(define_delay (eq_attr "type" "call")
- [(eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")])
-
-(define_delay (eq_attr "type" "branch,uncond_branch")
- [(eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")
- (eq_attr "in_delay_slot" "true")])
-
-;; Scheduling description for the ARC
-
-(define_cpu_unit "branch")
-
-(define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
- "nothing")
-
-;; 1) A conditional jump cannot immediately follow the insn setting the flags.
-;; This isn't a complete solution as it doesn't come with guarantees. That
-;; is done in the branch patterns and in arc_print_operand. This exists to
-;; avoid inserting a nop when we can.
-
-(define_insn_reservation "compare" 1 (eq_attr "type" "compare")
- "nothing,branch")
-
-(define_insn_reservation "branch" 1 (eq_attr "type" "branch")
- "branch")
-
-;; 2) References to loaded registers should wait a cycle.
-
-;; Memory with load-delay of 1 (i.e., 2 cycle load).
-
-(define_insn_reservation "memory" 2 (eq_attr "type" "load")
- "nothing")
-
-;; Move instructions.
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
-;; ??? Needed?
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- mov%? %0,%1
- mov%? %0,%1
- ldb%U1%V1 %0,%1
- stb%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-;; ??? This may never match since there's no cmpqi insn.
-
-(define_insn "*movqi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
- (const_int 0)))
- (set (match_operand:QI 0 "move_dest_operand" "=r")
- (match_dup 1))]
- ""
- "mov%?.f %0,%1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- mov%? %0,%1
- mov%? %0,%1
- ldw%U1%V1 %0,%1
- stw%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-;; ??? Will this ever match?
-
-(define_insn "*movhi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
- (const_int 0)))
- (set (match_operand:HI 0 "move_dest_operand" "=r")
- (match_dup 1))]
-;; ??? Needed?
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "mov%?.f %0,%1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SImode, operands[1]);
-}")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- mov%? %0,%1
- mov%? %0,%S1
- ld%U1%V1 %0,%1
- st%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-(define_insn "*movsi_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (match_operand:SI 1 "move_src_operand" "rIJi")
- (const_int 0)))
- (set (match_operand:SI 0 "move_dest_operand" "=r")
- (match_dup 1))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "mov%?.f %0,%S1"
- [(set_attr "type" "move")
- (set_attr "cond" "set_zn")])
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DImode, operands[1]);
-}")
-
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0 :
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register of
- operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mov %R0,%R1\;mov %0,%1\";
- else
- return \"mov %0,%1\;mov %R0,%R1\";
- case 1 :
- return \"mov %0,%L1\;mov %R0,%H1\";
- case 2 :
- /* If the low-address word is used in the address, we must load it
- last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is known to be
- dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands [1], 0))
- return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
- else
- return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
- case 3 :
- return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
- default:
- gcc_unreachable ();
- }
-}"
- [(set_attr "type" "move,move,load,store")
- ;; ??? The ld/st values could be 4 if it's [reg,bignum].
- (set_attr "length" "2,4,2,2")])
-
-;(define_expand "movdi"
-; [(set (match_operand:DI 0 "general_operand" "")
-; (match_operand:DI 1 "general_operand" ""))]
-; ""
-; "
-;{
-; /* Flow doesn't understand that this is effectively a DFmode move.
-; It doesn't know that all of `operands[0]' is set. */
-; emit_clobber (operands[0]);
-;
-; /* Emit insns that movsi_insn can handle. */
-; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
-; operand_subword (operands[1], 0, 0, DImode)));
-; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
-; operand_subword (operands[1], 1, 0, DImode)));
-; DONE;
-;}")
-
-;; Floating point move insns.
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (SFmode, operands[1]);
-}")
-
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- mov%? %0,%1
- mov%? %0,%1 ; %A1
- ld%U1%V1 %0,%1
- st%U0%V0 %1,%0"
- [(set_attr "type" "move,move,load,store")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
-{
- /* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DFmode, operands[1]);
-}")
-
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
- (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
-{
- switch (which_alternative)
- {
- case 0 :
- /* We normally copy the low-numbered register first. However, if
- the first register operand 0 is the same as the second register of
- operand 1, we must copy in the opposite order. */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"mov %R0,%R1\;mov %0,%1\";
- else
- return \"mov %0,%1\;mov %R0,%R1\";
- case 1 :
- return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
- case 2 :
- /* If the low-address word is used in the address, we must load it
- last. Otherwise, load it first. Note that we cannot have
- auto-increment in that case since the address register is known to be
- dead. */
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands [1], 0))
- return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
- else
- return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
- case 3 :
- return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
- default:
- gcc_unreachable ();
- }
-}"
- [(set_attr "type" "move,move,load,store")
- ;; ??? The ld/st values could be 4 if it's [reg,bignum].
- (set_attr "length" "2,4,2,2")])
-
-;(define_expand "movdf"
-; [(set (match_operand:DF 0 "general_operand" "")
-; (match_operand:DF 1 "general_operand" ""))]
-; ""
-; "
-;{
-; /* Flow doesn't understand that this is effectively a DFmode move.
-; It doesn't know that all of `operands[0]' is set. */
-; emit_clobber (operands[0]);
-;
-; /* Emit insns that movsi_insn can handle. */
-; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode),
-; operand_subword (operands[1], 0, 0, DFmode)));
-; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode),
-; operand_subword (operands[1], 1, 0, DFmode)));
-; DONE;
-;}")
-
-;; Load/Store with update instructions.
-;;
-;; Some of these we can get by using pre-decrement or pre-increment, but the
-;; hardware can also do cases where the increment is not the size of the
-;; object.
-;;
-;; In all these cases, we use operands 0 and 1 for the register being
-;; incremented because those are the operands that local-alloc will
-;; tie and these are the pair most likely to be tieable (and the ones
-;; that will benefit the most).
-;;
-;; We use match_operator here because we need to know whether the memory
-;; object is volatile or not.
-
-(define_insn "*loadqi_update"
- [(set (match_operand:QI 3 "register_operand" "=r,r")
- (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_zeroextendqisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (zero_extend:SI (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_signextendqisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (sign_extend:SI (match_operator:QI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldb.x.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storeqi_update"
- [(set (match_operator:QI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:QI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "stb.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadhi_update"
- [(set (match_operand:HI 3 "register_operand" "=r,r")
- (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_zeroextendhisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (zero_extend:SI (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*load_signextendhisi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (sign_extend:SI (match_operator:HI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ldw.x.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storehi_update"
- [(set (match_operator:HI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:HI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "stw.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadsi_update"
- [(set (match_operand:SI 3 "register_operand" "=r,r")
- (match_operator:SI 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ld.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storesi_update"
- [(set (match_operator:SI 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:SI 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "st.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-(define_insn "*loadsf_update"
- [(set (match_operand:SF 3 "register_operand" "=r,r")
- (match_operator:SF 4 "load_update_operand"
- [(match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
- (set (match_operand:SI 0 "register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "ld.a%V4 %3,[%0,%2]"
- [(set_attr "type" "load,load")
- (set_attr "length" "1,2")])
-
-(define_insn "*storesf_update"
- [(set (match_operator:SF 4 "store_update_operand"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "short_immediate_operand" "I")])
- (match_operand:SF 3 "register_operand" "r"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- ""
- "st.a%V4 %3,[%0,%2]"
- [(set_attr "type" "store")
- (set_attr "length" "1")])
-
-;; Conditional move instructions.
-
-(define_expand "movsicc"
- [(set (match_operand:SI 0 "register_operand" "")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "nonmemory_operand" "")
- (match_operand:SI 3 "register_operand" "")))]
- ""
- "
-{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
- XEXP (operands[1], 1));
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
-}")
-
-(define_expand "movsfcc"
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "nonmemory_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
- ""
- "
-{
- enum rtx_code code = GET_CODE (operands[1]);
- rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
- XEXP (operands[1], 1));
- operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
-}")
-
-(define_insn "*movsicc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else:SI (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "nonmemory_operand" "rJi")
- (match_operand:SI 3 "register_operand" "0")))]
- ""
- "mov.%d1 %0,%S2"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsfcc_insn"
- [(set (match_operand:SF 0 "register_operand" "=r,r")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "nonmemory_operand" "r,E")
- (match_operand:SF 3 "register_operand" "0,0")))]
- ""
- "@
- mov.%d1 %0,%2
- mov.%d1 %0,%2 ; %A2"
- [(set_attr "type" "cmove,cmove")])
-
-
-;; Zero extension instructions.
-;; ??? We don't support volatile memrefs here, but I'm not sure why.
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extb%? %0,%1
- ldb%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendqihi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:HI 0 "register_operand" "=r")
- (zero_extend:HI (match_dup 1)))]
- ""
- "extb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extb%? %0,%1
- ldb%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendqisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (match_dup 1)))]
- ""
- "extb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- extw%? %0,%1
- ldw%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*zero_extendhisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (match_dup 1)))]
- ""
- "extw%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-;; Sign extension instructions.
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
- (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexb%? %0,%1
- ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendqihi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:HI 0 "register_operand" "=r")
- (sign_extend:HI (match_dup 1)))]
- ""
- "sexb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexb%? %0,%1
- ldb.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendqisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_dup 1)))]
- ""
- "sexb%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
- ""
- "@
- sexw%? %0,%1
- ldw.x%U1 %0,%1"
- [(set_attr "type" "unary,load")])
-
-(define_insn "*extendhisi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_dup 1)))]
- ""
- "sexw%?.f %0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-;; Arithmetic instructions.
-
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "add%? %0,%1,%2")
-
-(define_insn "*addsi3_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (plus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "add%?.f %0,%1,%2"
- [(set_attr "cond" "set")])
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
- (match_operand:DI 2 "nonmemory_operand" "ri")))
- (clobber (reg:CC 61))]
- ""
- "*
-{
- rtx op2 = operands[2];
-
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
- else
- return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
- }
- else
- return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
-}"
- [(set_attr "length" "2")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "sub%? %0,%1,%2")
-
-(define_insn "*subsi3_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (minus:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "sub%?.f %0,%1,%2"
- [(set_attr "cond" "set")])
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
- (match_operand:DI 2 "nonmemory_operand" "ri")))
- (clobber (reg:CC 61))]
- ""
- "*
-{
- rtx op2 = operands[2];
-
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
- else
- return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
- }
- else
- return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
-}"
- [(set_attr "length" "2")])
-
-;; Boolean instructions.
-;;
-;; We don't define the DImode versions as expand_binop does a good enough job.
-
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "and%? %0,%1,%2")
-
-(define_insn "*andsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "and%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "*bicsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
- ""
- "bic%? %0,%1,%2"
- [(set_attr "length" "1,2,1,2")])
-
-(define_insn "*bicsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (and:SI (match_operand:SI 1 "register_operand" "%r")
- (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (and:SI (match_dup 1)
- (not:SI (match_dup 2))))]
- ""
- "bic%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "or%? %0,%1,%2")
-
-(define_insn "*iorsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (ior:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "or%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
- ""
- "xor%? %0,%1,%2")
-
-(define_insn "*xorsi3_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (xor:SI (match_operand:SI 1 "register_operand" "%r")
- (match_operand:SI 2 "nonmemory_operand" "rIJ"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (xor:SI (match_dup 1)
- (match_dup 2)))]
- ""
- "xor%?.f %0,%1,%2"
- [(set_attr "cond" "set_zn")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "sub%? %0,0,%1"
- [(set_attr "type" "unary")])
-
-(define_insn "*negsi2_set_cc_insn"
- [(set (reg:CC 61) (compare:CC
- (neg:SI (match_operand:SI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_dup 1)))]
- ""
- "sub%?.f %0,0,%1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set")])
-
-(define_insn "negdi2"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (neg:DI (match_operand:DI 1 "register_operand" "r")))
- (clobber (reg:SI 61))]
- ""
- "sub.f %L0,0,%L1\;sbc %H0,0,%H1"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operand:SI 1 "register_operand" "r")))]
- ""
- "xor%? %0,%1,-1"
- [(set_attr "type" "unary")])
-
-(define_insn "*one_cmplsi2_set_cc_insn"
- [(set (reg:CCZN 61) (compare:CCZN
- (not:SI (match_operand:SI 1 "register_operand" "r"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_dup 1)))]
- ""
- "xor%?.f %0,%1,-1"
- [(set_attr "type" "unary")
- (set_attr "cond" "set_zn")])
-
-;; Shift instructions.
-
-(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFT (SImode, operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_expand "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ASHIFTRT (SImode,
- operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_expand "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- if (! TARGET_SHIFTER)
- {
- emit_insn (gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_LSHIFTRT (SImode,
- operands[1],
- operands[2])),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (SImode)))));
- DONE;
- }
-}")
-
-(define_insn "*ashlsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "asl%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*ashrsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "asr%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*lshrsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
- (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
- "TARGET_SHIFTER"
- "lsr%? %0,%1,%2"
- [(set_attr "type" "shift")
- (set_attr "length" "1,2,1,2")])
-
-(define_insn "*shift_si3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
- (clobber (match_scratch:SI 4 "=&r"))]
- "! TARGET_SHIFTER"
- "* return output_shift (operands);"
- [(set_attr "type" "shift")
- (set_attr "length" "8")])
-
-;; Compare instructions.
-;; This controls RTL generation and register allocation.
-
-;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
-;; This assumes sub.f 0,symbol,0 is a valid insn.
-;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
-;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
-;; if it's a small constant.
-
-(define_insn "*cmpsi_cc_insn"
- [(set (reg:CC 61)
- (compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpsi_cczn_insn"
- [(set (reg:CCZN 61)
- (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-(define_insn "*cmpsi_ccznc_insn"
- [(set (reg:CCZNC 61)
- (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
- (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
- ""
- "@
- sub.f 0,%0,%1
- sub.f %1,%0,%1
- sub.f 0,%0,%1"
- [(set_attr "type" "compare,compare,compare")])
-
-;; Next come the scc insn and its expander.
-
-(define_expand "cstoresi4"
- [(set (match_dup 4)
- (match_op_dup 5
- [(match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "nonmemory_operand" "")]))
- (set (match_operand:SI 0 "register_operand")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(match_dup 4)
- (const_int 0)]))]
- ""
- "
-{
- operands[4] = gen_compare_reg (GET_CODE (operands[1]),
- operands[2], operands[3]);
- operands[5] = gen_rtx_fmt_ee (COMPARE,
- GET_MODE (operands[4]),
- operands[2], operands[3]);
-}")
-
-(define_insn "*scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
- ""
- "mov %0,1\;sub.%D1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-;; ??? Look up negscc insn. See pa.md for example.
-(define_insn "*neg_scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (neg:SI (match_operator:SI 1 "comparison_operator"
- [(reg 61) (const_int 0)])))]
- ""
- "mov %0,-1\;sub.%D1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-(define_insn "*not_scc_insn"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operator:SI 1 "comparison_operator"
- [(reg 61) (const_int 0)])))]
- ""
- "mov %0,1\;sub.%d1 %0,%0,%0"
- [(set_attr "type" "unary")
- (set_attr "length" "2")])
-
-;; These control RTL generation for conditional jump insns
-
-(define_expand "cbranchsi4"
- [(set (match_dup 4)
- (match_op_dup 5
- [(match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")]))
- (set (pc)
- (if_then_else
- (match_operator 0 "ordered_comparison_operator"
- [(match_dup 4)
- (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- operands[4] = gen_compare_reg (GET_CODE (operands[0]),
- operands[1], operands[2]);
- operands[5] = gen_rtx_fmt_ee (COMPARE,
- GET_MODE (operands[4]),
- operands[1], operands[2]);
-}")
-
-;; Now match both normal and inverted jump.
-
-(define_insn "*branch_insn"
- [(set (pc)
- (if_then_else (match_operator 1 "proper_comparison_operator"
- [(reg 61) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (arc_ccfsm_branch_deleted_p ())
- {
- arc_ccfsm_record_branch_deleted ();
- return \"; branch deleted, next insns conditionalized\";
- }
- else
- return \"%~b%d1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-(define_insn "*rev_branch_insn"
- [(set (pc)
- (if_then_else (match_operator 1 "proper_comparison_operator"
- [(reg 61) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
- "*
-{
- if (arc_ccfsm_branch_deleted_p ())
- {
- arc_ccfsm_record_branch_deleted ();
- return \"; branch deleted, next insns conditionalized\";
- }
- else
- return \"%~b%D1%# %l0\";
-}"
- [(set_attr "type" "branch")])
-
-;; Unconditional and other jump instructions.
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "b%* %l0"
- [(set_attr "type" "uncond_branch")])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
- ""
- "j%* %a0"
- [(set_attr "type" "uncond_branch")])
-
-;; Implement a switch statement.
-;; This wouldn't be necessary in the non-pic case if we could distinguish
-;; label refs of the jump table from other label refs. The problem is that
-;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
-;; the real address since it's the address of the table.
-
-(define_expand "casesi"
- [(set (match_dup 5)
- (minus:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))
- (set (reg:CC 61)
- (compare:CC (match_dup 5)
- (match_operand:SI 2 "nonmemory_operand" "")))
- (set (pc)
- (if_then_else (gtu (reg:CC 61)
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (mem:SI (plus:SI (mult:SI (match_dup 5)
- (const_int 4))
- (label_ref (match_operand 3 "" "")))))
- (clobber (match_scratch:SI 6 ""))
- (clobber (match_scratch:SI 7 ""))])]
- ""
- "
-{
- operands[5] = gen_reg_rtx (SImode);
-}")
-
-(define_insn "*casesi_insn"
- [(set (pc)
- (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
- (const_int 4))
- (label_ref (match_operand 1 "" "")))))
- (clobber (match_scratch:SI 2 "=r"))
- (clobber (match_scratch:SI 3 "=r"))]
- ""
- "*
-{
- output_asm_insn (\"mov %2,%1\", operands);
- if (TARGET_SHIFTER)
- output_asm_insn (\"asl %3,%0,2\", operands);
- else
- output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
- output_asm_insn (\"ld %2,[%2,%3]\", operands);
- output_asm_insn (\"j.nd %a2\", operands);
- return \"\";
-}"
- [(set_attr "type" "uncond_branch")
- (set_attr "length" "6")])
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "address_operand" "p"))
- (use (label_ref (match_operand 1 "" "")))]
- "0 /* disabled -> using casesi now */"
- "j%* %a0"
- [(set_attr "type" "uncond_branch")])
-
-(define_expand "call"
- ;; operands[1] is stack_size_rtx
- ;; operands[2] is next_arg_register
- [(parallel [(call (match_operand:SI 0 "call_operand" "")
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))])]
- ""
- "")
-
-(define_insn "*call_via_reg"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))]
- ""
- "lr blink,[status]\;j.d %0\;add blink,blink,2"
- [(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "3")])
-
-(define_insn "*call_via_label"
- [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
- (match_operand 1 "" ""))
- (clobber (reg:SI 31))]
- ""
- ; The %~ is necessary in case this insn gets conditionalized and the previous
- ; insn is the cc setter.
- "%~bl%!%* %0"
- [(set_attr "type" "call")
- (set_attr "cond" "canuse")])
-
-(define_expand "call_value"
- ;; operand 2 is stack_size_rtx
- ;; operand 3 is next_arg_register
- [(parallel [(set (match_operand 0 "register_operand" "=r")
- (call (match_operand:SI 1 "call_operand" "")
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))])]
- ""
- "")
-
-(define_insn "*call_value_via_reg"
- [(set (match_operand 0 "register_operand" "=r")
- (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))]
- ""
- "lr blink,[status]\;j.d %1\;add blink,blink,2"
- [(set_attr "type" "call_no_delay_slot")
- (set_attr "length" "3")])
-
-(define_insn "*call_value_via_label"
- [(set (match_operand 0 "register_operand" "=r")
- (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
- (match_operand 2 "" "")))
- (clobber (reg:SI 31))]
- ""
- ; The %~ is necessary in case this insn gets conditionalized and the previous
- ; insn is the cc setter.
- "%~bl%!%* %1"
- [(set_attr "type" "call")
- (set_attr "cond" "canuse")])
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop"
- [(set_attr "type" "misc")])
-
-;; Special pattern to flush the icache.
-;; ??? Not sure what to do here. Some ARC's are known to support this.
-
-(define_insn "flush_icache"
- [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
- ""
- "* return \"\";"
- [(set_attr "type" "misc")])
-
-;; Split up troublesome insns for better scheduling.
-
-;; Peepholes go at the end.
diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt
deleted file mode 100644
index e5381f95afc..00000000000
--- a/gcc/config/arc/arc.opt
+++ /dev/null
@@ -1,60 +0,0 @@
-; Options for the Argonaut ARC port of the compiler
-;
-; Copyright (C) 2005, 2007, 2011 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT
-; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-; License for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-EB
-Driver
-
-EL
-Driver
-
-malign-loops
-Target Undocumented Report Mask(ALIGN_LOOPS)
-
-mbig-endian
-Target Undocumented Report RejectNegative Mask(BIG_ENDIAN)
-
-mlittle-endian
-Target Undocumented Report RejectNegative InverseMask(BIG_ENDIAN)
-
-mmangle-cpu
-Target Report Mask(MANGLE_CPU)
-Prepend the name of the cpu to all public symbol names
-
-; mmangle-cpu-libgcc
-; Target Undocumented Mask(MANGLE_CPU_LIBGC)
-
-mno-cond-exec
-Target Undocumented Report RejectNegative Mask(NO_COND_EXEC)
-
-mcpu=
-Target RejectNegative Joined Var(arc_cpu_string) Init("base")
--mcpu=CPU Compile code for ARC variant CPU
-
-mtext=
-Target RejectNegative Joined Var(arc_text_string) Init(ARC_DEFAULT_TEXT_SECTION)
--mtext=SECTION Put functions in SECTION
-
-mdata=
-Target RejectNegative Joined Var(arc_data_string) Init(ARC_DEFAULT_DATA_SECTION)
--mdata=SECTION Put data in SECTION
-
-mrodata=
-Target RejectNegative Joined Var(arc_rodata_string) Init(ARC_DEFAULT_RODATA_SECTION)
--mrodata=SECTION Put read-only data in SECTION
diff --git a/gcc/config/arc/initfini.c b/gcc/config/arc/initfini.c
deleted file mode 100644
index d7514133a36..00000000000
--- a/gcc/config/arc/initfini.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* .init/.fini section handling + C++ global constructor/destructor handling.
- This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
-
-Copyright (C) 1995, 1997, 1998, 2009 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Declare a pointer to void function type. */
-typedef void (*func_ptr) (void);
-
-#ifdef CRT_INIT
-
-/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
- to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
- __DTOR_END__ } per root executable and also one set of these symbols
- per shared library. So in any given whole process image, we may have
- multiple definitions of each of these symbols. In order to prevent
- these definitions from conflicting with one another, and in order to
- ensure that the proper lists are used for the initialization/finalization
- of each individual shared library (respectively), we give these symbols
- only internal (i.e. `static') linkage, and we also make it a point to
- refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
- symbol in crtinit.o, where they are defined. */
-
-static func_ptr __CTOR_LIST__[1] __attribute__ ((section (".ctors")))
- = { (func_ptr) (-1) };
-
-static func_ptr __DTOR_LIST__[1] __attribute__ ((section (".dtors")))
- = { (func_ptr) (-1) };
-
-/* Run all the global destructors on exit from the program. */
-
-/* Some systems place the number of pointers in the first word of the
- table. On SVR4 however, that word is -1. In all cases, the table is
- null-terminated. On SVR4, we start from the beginning of the list and
- invoke each per-compilation-unit destructor routine in order
- until we find that null.
-
- Note that this function MUST be static. There will be one of these
- functions in each root executable and one in each shared library, but
- although they all have the same code, each one is unique in that it
- refers to one particular associated `__DTOR_LIST__' which belongs to the
- same particular root executable or shared library file. */
-
-static void __do_global_dtors (void)
-asm ("__do_global_dtors") __attribute__ ((section (".text")));
-
-static void
-__do_global_dtors (void)
-{
- func_ptr *p;
- for (p = __DTOR_LIST__ + 1; *p; p++)
- (*p) ();
-}
-
-/* .init section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .init\n\
- .global init\n\
- .word 0\n\
-init:\n\
- st blink,[sp,4]\n\
- st fp,[sp]\n\
- mov fp,sp\n\
- sub sp,sp,16\n\
-");
-
-/* .fini section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .fini\n\
- .global fini\n\
- .word 0\n\
-fini:\n\
- st blink,[sp,4]\n\
- st fp,[sp]\n\
- mov fp,sp\n\
- sub sp,sp,16\n\
- bl.nd __do_global_dtors\n\
-");
-
-#endif /* CRT_INIT */
-
-#ifdef CRT_FINI
-
-/* Put a word containing zero at the end of each of our two lists of function
- addresses. Note that the words defined here go into the .ctors and .dtors
- sections of the crtend.o file, and since that file is always linked in
- last, these words naturally end up at the very ends of the two lists
- contained in these two sections. */
-
-static func_ptr __CTOR_END__[1] __attribute__ ((section (".ctors")))
- = { (func_ptr) 0 };
-
-static func_ptr __DTOR_END__[1] __attribute__ ((section (".dtors")))
- = { (func_ptr) 0 };
-
-/* Run all global constructors for the program.
- Note that they are run in reverse order. */
-
-static void __do_global_ctors (void)
-asm ("__do_global_ctors") __attribute__ ((section (".text")));
-
-static void
-__do_global_ctors (void)
-{
- func_ptr *p;
- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
- (*p) ();
-}
-
-/* .init section end.
- This must live at the end of the .init section. */
-
-asm ("\n\
- .section .init\n\
- bl.nd __do_global_ctors\n\
- ld blink,[fp,4]\n\
- j.d blink\n\
- ld.a fp,[sp,16]\n\
-");
-
-/* .fini section end.
- This must live at the end of the .fini section. */
-
-asm ("\n\
- .section .fini\n\
- ld blink,[fp,4]\n\
- j.d blink\n\
- ld.a fp,[sp,16]\n\
-");
-
-#endif /* CRT_FINI */
diff --git a/gcc/config/arc/lib1funcs.asm b/gcc/config/arc/lib1funcs.asm
deleted file mode 100644
index c61f39a5ca7..00000000000
--- a/gcc/config/arc/lib1funcs.asm
+++ /dev/null
@@ -1,266 +0,0 @@
-; libgcc routines for ARC cpu.
-
-/* Copyright (C) 1995, 1997,2004, 2009 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef L_mulsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___mulsi3
-___mulsi3:
-
-/* This the simple version.
-
- while (a)
- {
- if (a & 1)
- r += b;
- a >>= 1;
- b <<= 1;
- }
-*/
- mov r2,0 ; Accumulate result here.
-.Lloop:
- sub.f 0,r0,0 ; while (a)
- nop
- beq.nd .Ldone
- and.f 0,r0,1 ; if (a & 1)
- add.nz r2,r2,r1 ; r += b
- lsr r0,r0 ; a >>= 1
- b.d .Lloop
- lsl r1,r1 ; b <<= 1
-.Ldone:
- j.d blink
- mov r0,r2
-#endif
-
-#endif /* L_mulsi3 */
-
-#ifdef L_umulsidi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___umulsidi3
-___umulsidi3:
-
-/* This the simple version.
-
- while (a)
- {
- if (a & 1)
- r += b;
- a >>= 1;
- b <<= 1;
- }
-*/
- mov r2,0 ; Top part of b.
- mov r3,0 ; Accumulate result here.
- mov r4,0
-.Lloop:
- sub.f 0,r0,0 ; while (a)
- nop
- beq.nd .Ldone
- and.f 0,r0,1 ; if (a & 1)
- sub.f 0,r0,0
- nop
- beq .Ldontadd
- add.f r4,r4,r1 ; r += b
- adc r3,r3,r2
-.Ldontadd:
- lsr r0,r0 ; a >>= 1
- lsl.f r1,r1 ; b <<= 1
- b.d .Lloop
- rlc r2,r2
-.Ldone:
-#ifdef __big_endian__
- mov r1,r4
- j.d blink
- mov r0,r3
-#else
- mov r0,r4
- j.d blink
- mov r1,r3
-#endif
-#endif
-
-#endif /* L_umulsidi3 */
-
-#ifdef L_divmod_tools
-
-; Utilities used by all routines.
-
- .section .text
- .align 4
-
-; inputs: r0 = numerator, r1 = denominator
-; outputs: positive r0/r1,
-; r6.bit1 = sign of numerator, r6.bit0 = sign of result
-
- .global ___divnorm
-___divnorm:
- mov r6,0 ; keep sign in r6
- sub.f 0,r0,0 ; is numerator -ve?
- sub.lt r0,0,r0 ; negate numerator
- mov.lt r6,3 ; sign is -ve
- sub.f 0,r1,0 ; is denominator -ve?
- sub.lt r1,0,r1 ; negate denominator
- xor.lt r6,r6,1 ; toggle sign
- j.nd blink
-
-/*
-unsigned long
-udivmodsi4(int modwanted, unsigned long num, unsigned long den)
-{
- unsigned long bit = 1;
- unsigned long res = 0;
-
- while (den < num && bit && !(den & (1L<<31)))
- {
- den <<=1;
- bit <<=1;
- }
- while (bit)
- {
- if (num >= den)
- {
- num -= den;
- res |= bit;
- }
- bit >>=1;
- den >>=1;
- }
- if (modwanted) return num;
- return res;
-}
-*/
-
-; inputs: r0 = numerator, r1 = denominator
-; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed
-
- .global ___udivmodsi4
-___udivmodsi4:
- mov r2,1 ; bit = 1
- mov r3,0 ; res = 0
-.Lloop1:
- sub.f 0,r1,r0 ; while (den < num
- nop
- bnc.nd .Lloop2
- sub.f 0,r2,0 ; && bit
- nop
- bz.nd .Lloop2
- lsl.f 0,r1 ; && !(den & (1<<31))
- nop
- bc.nd .Lloop2
- lsl r1,r1 ; den <<= 1
- b.d .Lloop1
- lsl r2,r2 ; bit <<= 1
-.Lloop2:
- sub.f 0,r2,0 ; while (bit)
- nop
- bz.nd .Ldivmodend
- sub.f 0,r0,r1 ; if (num >= den)
- nop
- bc.nd .Lshiftdown
- sub r0,r0,r1 ; num -= den
- or r3,r3,r2 ; res |= bit
-.Lshiftdown:
- lsr r2,r2 ; bit >>= 1
- b.d .Lloop2
- lsr r1,r1 ; den >>= 1
-.Ldivmodend:
- mov r1,r0 ; r1 = mod
- j.d blink
- mov r0,r3 ; r0 = res
-
-#endif
-
-#ifdef L_udivsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___udivsi3
-___udivsi3:
- mov r7,blink
- bl.nd ___udivmodsi4
- j.nd r7
-#endif
-
-#endif /* L_udivsi3 */
-
-#ifdef L_divsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___divsi3
-___divsi3:
- mov r7,blink
- bl.nd ___divnorm
- bl.nd ___udivmodsi4
- and.f 0,r6,1
- sub.nz r0,0,r0 ; cannot go in delay slot, has limm value
- j.nd r7
-#endif
-
-#endif /* L_divsi3 */
-
-#ifdef L_umodsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___umodsi3
-___umodsi3:
- mov r7,blink
- bl.nd ___udivmodsi4
- j.d r7
- mov r0,r1
-#endif
-
-#endif /* L_umodsi3 */
-
-#ifdef L_modsi3
- .section .text
- .align 4
-
-#ifdef __base__
- .cpu base
- .global ___modsi3
-___modsi3:
- mov r7,blink
- bl.nd ___divnorm
- bl.nd ___udivmodsi4
- and.f 0,r6,2
- sub.nz r1,0,r1
- j.d r7
- mov r0,r1
-#endif
-
-#endif /* L_modsi3 */
diff --git a/gcc/config/arc/t-arc b/gcc/config/arc/t-arc
deleted file mode 100644
index a923479ca09..00000000000
--- a/gcc/config/arc/t-arc
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003,
-# 2004 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = arc/lib1funcs.asm
-LIB1ASMFUNCS = _mulsi3 _umulsidi3 _udivsi3 _divsi3 _umodsi3 _modsi3 _divmod_tools
-
-# We need libgcc routines to be mangled according to which cpu they
-# were compiled for.
-# ??? -mmangle-cpu passed by default for now.
-#LIBGCC2_CFLAGS = -g1 -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -mmangle-cpu
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifndef __big_endian__' > dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
- echo '#endif' >> dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- echo '#ifndef __big_endian__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-# .init/.fini section routines
-
-$(T)crtinit.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
- $(MULTILIB_CFLAGS) -DCRT_INIT -finhibit-size-directive -fno-inline-functions \
- -g0 -c $(srcdir)/config/arc/initfini.c -o $(T)crtinit.o
-
-$(T)crtfini.o: $(srcdir)/config/arc/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
- -DCRT_FINI $(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
- -g0 -c $(srcdir)/config/arc/initfini.c -o $(T)crtfini.o
-
-MULTILIB_OPTIONS = EB
-MULTILIB_DIRNAMES = be
-EXTRA_MULTILIB_PARTS = crtinit.o crtfini.o
diff --git a/gcc/config/arm/netbsd.h b/gcc/config/arm/netbsd.h
deleted file mode 100644
index 4a1adbae991..00000000000
--- a/gcc/config/arm/netbsd.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/* NetBSD/arm a.out version.
- Copyright (C) 1993, 1994, 1997, 1998, 2003, 2004, 2005, 2007, 2008, 2010
- Free Software Foundation, Inc.
- Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* Run-time Target Specification. */
-#undef TARGET_VERSION
-#define TARGET_VERSION fputs (" (ARM/NetBSD)", stderr);
-
-/* Unsigned chars produces much better code than signed. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Since we always use GAS as our assembler we support stabs. */
-#define DBX_DEBUGGING_INFO 1
-
-/*#undef ASM_DECLARE_FUNCTION_NAME*/
-
-/* ARM6 family default cpu. */
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_APCS_FRAME)
-
-/* Some defines for CPP.
- arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
-#define TARGET_OS_CPP_BUILTINS() \
- do { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- builtin_define_std ("arm32"); \
- builtin_define_std ("unix"); \
- builtin_define_std ("riscbsd"); \
- } while (0)
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
- { "netbsd_link_spec", NETBSD_LINK_SPEC_AOUT },
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
-"
-
-/* Because TARGET_DEFAULT sets MASK_SOFT_FLOAT */
-#undef CPP_FLOAT_DEFAULT_SPEC
-#define CPP_FLOAT_DEFAULT_SPEC "-D__SOFTFP__"
-
-/* Pass -X to the linker so that it will strip symbols starting with 'L' */
-#undef LINK_SPEC
-#define LINK_SPEC "-X %(netbsd_link_spec)"
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-/* We don't have any limit on the length as out debugger is GDB. */
-#undef DBX_CONTIN_LENGTH
-
-/* NetBSD does its profiling differently to the Acorn compiler. We
- don't need a word following the mcount call; and to skip it
- requires either an assembly stub or use of fomit-frame-pointer when
- compiling the profiling functions. Since we break Acorn CC
- compatibility below a little more won't hurt. */
-
-#undef ARM_FUNCTION_PROFILER
-#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
-{ \
- fprintf(STREAM, "\tmov\t%sip, %slr\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf(STREAM, "\tbl\tmcount\n"); \
-}
-
-/* On the ARM `@' introduces a comment, so we must use something else
- for .type directives. */
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%%%s"
-
-/* NetBSD uses the old PCC style aggregate returning conventions. */
-#undef DEFAULT_PCC_STRUCT_RETURN
-#define DEFAULT_PCC_STRUCT_RETURN 1
-
-/* Although not normally relevant (since by default, all aggregates
- are returned in memory) compiling some parts of libc requires
- non-APCS style struct returns. */
-#undef TARGET_RETURN_IN_MEMORY
-
-/* VERY BIG NOTE : Change of structure alignment for RiscBSD.
- There are consequences you should be aware of...
-
- Normally GCC/arm uses a structure alignment of 32 for compatibility
- with armcc. This means that structures are padded to a word
- boundary. However this causes problems with bugged NetBSD kernel
- code (possibly userland code as well - I have not checked every
- binary). The nature of this bugged code is to rely on sizeof()
- returning the correct size of various structures rounded to the
- nearest byte (SCSI and ether code are two examples, the vm system
- is another). This code breaks when the structure alignment is 32
- as sizeof() will report a word=rounded size. By changing the
- structure alignment to 8. GCC will conform to what is expected by
- NetBSD.
-
- This has several side effects that should be considered.
- 1. Structures will only be aligned to the size of the largest member.
- i.e. structures containing only bytes will be byte aligned.
- structures containing shorts will be half word aligned.
- structures containing ints will be word aligned.
-
- This means structures should be padded to a word boundary if
- alignment of 32 is required for byte structures etc.
-
- 2. A potential performance penalty may exist if strings are no longer
- word aligned. GCC will not be able to use word load/stores to copy
- short strings.
-
- This modification is not encouraged but with the present state of the
- NetBSD source tree it is currently the only solution that meets the
- requirements. */
-#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
-#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-
-/* Clear the instruction cache from `BEG' to `END'. This makes a
- call to the ARM32_SYNC_ICACHE architecture specific syscall. */
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- extern int sysarch(int number, void *args); \
- struct { \
- unsigned int addr; \
- int len; \
- } s; \
- s.addr = (unsigned int)(BEG); \
- s.len = (END) - (BEG); \
- (void)sysarch(0, &s); \
-}
diff --git a/gcc/config/arm/t-pe b/gcc/config/arm/t-pe
deleted file mode 100644
index 626b1d29a12..00000000000
--- a/gcc/config/arm/t-pe
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2008, 2009,
-# 2010
-# Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- echo '#ifndef __ARMEB__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#ifndef __ARMEB__' > dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
- echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
- echo '#endif' >> dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/arm/pe.c
-
-MULTILIB_OPTIONS = mhard-float mthumb
-MULTILIB_DIRNAMES = fpu thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS =
diff --git a/gcc/config/crx/crx-protos.h b/gcc/config/crx/crx-protos.h
deleted file mode 100644
index aeb4bdd594a..00000000000
--- a/gcc/config/crx/crx-protos.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Prototypes for exported functions defined in crx.c
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_CRX_PROTOS_H
-#define GCC_CRX_PROTOS_H
-
-
-/* Register usage. */
-extern enum reg_class crx_regno_reg_class (int);
-extern int crx_hard_regno_mode_ok (int regno, enum machine_mode);
-#ifdef RTX_CODE
-extern enum reg_class crx_secondary_reload_class (enum reg_class, enum machine_mode, rtx);
-#endif /* RTX_CODE */
-
-/* Passing function arguments. */
-extern int crx_function_arg_regno_p (int);
-#ifdef TREE_CODE
-#ifdef RTX_CODE
-extern void crx_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
-#endif /* RTX_CODE */
-#endif /* TREE_CODE */
-
-#ifdef RTX_CODE
-/* Addressing Modes. */
-struct crx_address
-{
- rtx base, index, disp, side_effect;
- int scale;
-};
-
-enum crx_addrtype
-{
- CRX_INVALID, CRX_REG_REL, CRX_POST_INC, CRX_SCALED_INDX, CRX_ABSOLUTE
-};
-
-extern enum crx_addrtype crx_decompose_address (rtx addr, struct crx_address *out);
-
-extern int crx_const_double_ok (rtx op);
-
-/* Instruction output. */
-extern void crx_print_operand (FILE *, rtx, int);
-extern void crx_print_operand_address (FILE *, rtx);
-
-/* Misc functions called from crx.md. */
-extern void crx_expand_movmem_single (rtx, rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT *);
-extern int crx_expand_movmem (rtx, rtx, rtx, rtx);
-#endif /* RTX_CODE */
-
-/* Routines to compute costs. */
-extern int crx_memory_move_cost (enum machine_mode, enum reg_class, int);
-
-/* Prologue/Epilogue functions. */
-extern int crx_initial_elimination_offset (int, int);
-extern char *crx_prepare_push_pop_string (int);
-extern void crx_expand_prologue (void);
-extern void crx_expand_epilogue (void);
-
-
-/* Handling the "interrupt" attribute */
-extern int crx_interrupt_function_p (void);
-
-#endif /* GCC_CRX_PROTOS_H */
diff --git a/gcc/config/crx/crx.c b/gcc/config/crx/crx.c
deleted file mode 100644
index 8f635d5a171..00000000000
--- a/gcc/config/crx/crx.c
+++ /dev/null
@@ -1,1466 +0,0 @@
-/* Output routines for GCC for CRX.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/*****************************************************************************/
-/* HEADER INCLUDES */
-/*****************************************************************************/
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-codes.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "except.h"
-#include "function.h"
-#include "recog.h"
-#include "expr.h"
-#include "optabs.h"
-#include "diagnostic-core.h"
-#include "basic-block.h"
-#include "df.h"
-#include "target.h"
-#include "target-def.h"
-
-/*****************************************************************************/
-/* DEFINITIONS */
-/*****************************************************************************/
-
-/* Maximum number of register used for passing parameters. */
-#define MAX_REG_FOR_PASSING_ARGS 6
-
-/* Minimum number register used for passing parameters. */
-#define MIN_REG_FOR_PASSING_ARGS 2
-
-/* The maximum count of words supported in the assembly of the architecture in
- * a push/pop instruction. */
-#define MAX_COUNT 8
-
-/* Predicate is true if the current function is a 'noreturn' function, i.e. it
- * is qualified as volatile. */
-#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
-
-/* The following macros are used in crx_decompose_address () */
-
-/* Returns the factor of a scaled index address or -1 if invalid. */
-#define SCALE_FOR_INDEX_P(X) \
- (GET_CODE (X) == CONST_INT ? \
- (INTVAL (X) == 1 ? 1 : \
- INTVAL (X) == 2 ? 2 : \
- INTVAL (X) == 4 ? 4 : \
- INTVAL (X) == 8 ? 8 : \
- -1) : \
- -1)
-
-/* Nonzero if the rtx X is a signed const int of n bits */
-#define RTX_SIGNED_INT_FITS_N_BITS(X,n) \
- ((GET_CODE (X) == CONST_INT \
- && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
-
-/* Nonzero if the rtx X is an unsigned const int of n bits. */
-#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
- ((GET_CODE (X) == CONST_INT \
- && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
-
-/*****************************************************************************/
-/* STATIC VARIABLES */
-/*****************************************************************************/
-
-/* Nonzero if the last param processed is passed in a register. */
-static int last_parm_in_reg;
-
-/* Will hold the number of the last register the prologue saves, -1 if no
- * register is saved. */
-static int last_reg_to_save;
-
-/* Each object in the array is a register number. Mark 1 for registers that
- * need to be saved. */
-static int save_regs[FIRST_PSEUDO_REGISTER];
-
-/* Number of bytes saved on the stack for non-scratch registers */
-static int sum_regs = 0;
-
-/* Number of bytes saved on the stack for local variables. */
-static int local_vars_size;
-
-/* The sum of 2 sizes: locals vars and padding byte for saving the registers.
- * Used in expand_prologue () and expand_epilogue (). */
-static int size_for_adjusting_sp;
-
-/* In case of a POST_INC or POST_DEC memory reference, we must report the mode
- * of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */
-static enum machine_mode output_memory_reference_mode;
-
-/*****************************************************************************/
-/* TARGETM FUNCTION PROTOTYPES */
-/*****************************************************************************/
-
-static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *);
-static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED);
-static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
-static int crx_address_cost (rtx, bool);
-static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
-static bool crx_can_eliminate (const int, const int);
-static rtx crx_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-static void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- const_tree, bool);
-
-/*****************************************************************************/
-/* RTL VALIDITY */
-/*****************************************************************************/
-
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P crx_legitimate_address_p
-
-#undef TARGET_CAN_ELIMINATE
-#define TARGET_CAN_ELIMINATE crx_can_eliminate
-
-/*****************************************************************************/
-/* STACK LAYOUT AND CALLING CONVENTIONS */
-/*****************************************************************************/
-
-#undef TARGET_FIXED_CONDITION_CODE_REGS
-#define TARGET_FIXED_CONDITION_CODE_REGS crx_fixed_condition_code_regs
-
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX crx_struct_value_rtx
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY crx_return_in_memory
-
-/*****************************************************************************/
-/* PASSING FUNCTION ARGUMENTS */
-/*****************************************************************************/
-
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG crx_function_arg
-
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE crx_function_arg_advance
-
-/*****************************************************************************/
-/* RELATIVE COSTS OF OPERATIONS */
-/*****************************************************************************/
-
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST crx_address_cost
-
-/*****************************************************************************/
-/* TARGET-SPECIFIC USES OF `__attribute__' */
-/*****************************************************************************/
-
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE crx_attribute_table
-
-static const struct attribute_spec crx_attribute_table[] = {
- /* ISRs have special prologue and epilogue requirements. */
- {"interrupt", 0, 0, false, true, true, NULL, false},
- {NULL, 0, 0, false, false, false, NULL, false}
-};
-
-/* Option handling. */
-
-#undef TARGET_OPTION_OPTIMIZATION_TABLE
-#define TARGET_OPTION_OPTIMIZATION_TABLE crx_option_optimization_table
-
-static const struct default_options crx_option_optimization_table[] =
- {
- /* Put each function in its own section so that PAGE-instruction
- relaxation can do its best. */
- { OPT_LEVELS_1_PLUS, OPT_ffunction_sections, NULL, 1 },
- { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
- { OPT_LEVELS_NONE, 0, NULL, 0 }
- };
-
-/* Initialize 'targetm' variable which contains pointers to functions and data
- * relating to the target machine. */
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-
-/*****************************************************************************/
-/* TARGET HOOK IMPLEMENTATIONS */
-/*****************************************************************************/
-
-/* Return the fixed registers used for condition codes. */
-
-static bool
-crx_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
-{
- *p1 = CC_REGNUM;
- *p2 = INVALID_REGNUM;
- return true;
-}
-
-/* Implements hook TARGET_STRUCT_VALUE_RTX. */
-
-static rtx
-crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED)
-{
- return gen_rtx_REG (Pmode, CRX_STRUCT_VALUE_REGNUM);
-}
-
-/* Implements hook TARGET_RETURN_IN_MEMORY. */
-
-static bool
-crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (TYPE_MODE (type) == BLKmode)
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 8);
- }
- else
- return false;
-}
-
-
-/*****************************************************************************/
-/* MACRO IMPLEMENTATIONS */
-/*****************************************************************************/
-
-/* STACK LAYOUT AND CALLING CONVENTIONS ROUTINES */
-/* --------------------------------------------- */
-
-/* Return nonzero if the current function being compiled is an interrupt
- * function as specified by the "interrupt" attribute. */
-
-int
-crx_interrupt_function_p (void)
-{
- tree attributes;
-
- attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- return lookup_attribute ("interrupt", attributes) != NULL_TREE;
-}
-
-/* Compute values for the array save_regs and the variable sum_regs. The index
- * of save_regs is numbers of register, each will get 1 if we need to save it
- * in the current function, 0 if not. sum_regs is the total sum of the
- * registers being saved. */
-
-static void
-crx_compute_save_regs (void)
-{
- unsigned int regno;
-
- /* initialize here so in case the function is no-return it will be -1. */
- last_reg_to_save = -1;
-
- /* No need to save any registers if the function never returns. */
- if (FUNC_IS_NORETURN_P (current_function_decl))
- return;
-
- /* Initialize the number of bytes to be saved. */
- sum_regs = 0;
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- {
- if (fixed_regs[regno])
- {
- save_regs[regno] = 0;
- continue;
- }
-
- /* If this reg is used and not call-used (except RA), save it. */
- if (crx_interrupt_function_p ())
- {
- if (!current_function_is_leaf && call_used_regs[regno])
- /* this is a volatile reg in a non-leaf interrupt routine - save it
- * for the sake of its sons. */
- save_regs[regno] = 1;
-
- else if (df_regs_ever_live_p (regno))
- /* This reg is used - save it. */
- save_regs[regno] = 1;
- else
- /* This reg is not used, and is not a volatile - don't save. */
- save_regs[regno] = 0;
- }
- else
- {
- /* If this reg is used and not call-used (except RA), save it. */
- if (df_regs_ever_live_p (regno)
- && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
- save_regs[regno] = 1;
- else
- save_regs[regno] = 0;
- }
- }
-
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (save_regs[regno] == 1)
- {
- last_reg_to_save = regno;
- sum_regs += UNITS_PER_WORD;
- }
-}
-
-/* Compute the size of the local area and the size to be adjusted by the
- * prologue and epilogue. */
-
-static void
-crx_compute_frame (void)
-{
- /* For aligning the local variables. */
- int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
- int padding_locals;
-
- /* Padding needed for each element of the frame. */
- local_vars_size = get_frame_size ();
-
- /* Align to the stack alignment. */
- padding_locals = local_vars_size % stack_alignment;
- if (padding_locals)
- padding_locals = stack_alignment - padding_locals;
-
- local_vars_size += padding_locals;
-
- size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0);
-}
-
-/* Worker function for TARGET_CAN_ELIMINATE. */
-
-bool
-crx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
-{
- return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
-}
-
-/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
-
-int
-crx_initial_elimination_offset (int from, int to)
-{
- /* Compute this since we need to use sum_regs. */
- crx_compute_save_regs ();
-
- /* Compute this since we need to use local_vars_size. */
- crx_compute_frame ();
-
- if ((from) == FRAME_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
- return (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0);
- else if ((from) == ARG_POINTER_REGNUM && (to) == FRAME_POINTER_REGNUM)
- return (sum_regs + local_vars_size);
- else if ((from) == ARG_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
- return (sum_regs + local_vars_size +
- (ACCUMULATE_OUTGOING_ARGS ?
- crtl->outgoing_args_size : 0));
- else
- abort ();
-}
-
-/* REGISTER USAGE */
-/* -------------- */
-
-/* Return the class number of the smallest class containing reg number REGNO.
- * This could be a conditional expression or could index an array. */
-
-enum reg_class
-crx_regno_reg_class (int regno)
-{
- if (regno >= 0 && regno < SP_REGNUM)
- return NOSP_REGS;
-
- if (regno == SP_REGNUM)
- return GENERAL_REGS;
-
- if (regno == LO_REGNUM)
- return LO_REGS;
- if (regno == HI_REGNUM)
- return HI_REGS;
-
- return NO_REGS;
-}
-
-/* Transfer between HILO_REGS and memory via secondary reloading. */
-
-enum reg_class
-crx_secondary_reload_class (enum reg_class rclass,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx x ATTRIBUTE_UNUSED)
-{
- if (reg_classes_intersect_p (rclass, HILO_REGS)
- && true_regnum (x) == -1)
- return GENERAL_REGS;
-
- return NO_REGS;
-}
-
-/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
-
-int
-crx_hard_regno_mode_ok (int regno, enum machine_mode mode)
-{
- /* CC can only hold CCmode values. */
- if (regno == CC_REGNUM)
- return GET_MODE_CLASS (mode) == MODE_CC;
- if (GET_MODE_CLASS (mode) == MODE_CC)
- return 0;
- /* HILO registers can only hold SImode and DImode */
- if (HILO_REGNO_P (regno))
- return mode == SImode || mode == DImode;
- return 1;
-}
-
-/* PASSING FUNCTION ARGUMENTS */
-/* -------------------------- */
-
-/* If enough param regs are available for passing the param of type TYPE return
- * the number of registers needed else 0. */
-
-static int
-enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
- enum machine_mode mode)
-{
- int type_size;
- int remaining_size;
-
- if (mode != BLKmode)
- type_size = GET_MODE_BITSIZE (mode);
- else
- type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
-
- remaining_size =
- BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS -
- (MIN_REG_FOR_PASSING_ARGS + cum->ints) + 1);
-
- /* Any variable which is too big to pass in two registers, will pass on
- * stack. */
- if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
- return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
-
- return 0;
-}
-
-/* Implements TARGET_FUNCTION_ARG. */
-
-static rtx
-crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- last_parm_in_reg = 0;
-
- /* Function_arg () is called with this type just after all the args have had
- * their registers assigned. The rtx that function_arg returns from this type
- * is supposed to pass to 'gen_call' but currently it is not implemented (see
- * macro GEN_CALL). */
- if (type == void_type_node)
- return NULL_RTX;
-
- if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
- return NULL_RTX;
-
- if (mode == BLKmode)
- {
- /* Enable structures that need padding bytes at the end to pass to a
- * function in registers. */
- if (enough_regs_for_param (cum, type, mode) != 0)
- {
- last_parm_in_reg = 1;
- return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
- }
- }
-
- if (MIN_REG_FOR_PASSING_ARGS + cum->ints > MAX_REG_FOR_PASSING_ARGS)
- return NULL_RTX;
- else
- {
- if (enough_regs_for_param (cum, type, mode) != 0)
- {
- last_parm_in_reg = 1;
- return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
- }
- }
-
- return NULL_RTX;
-}
-
-/* Implements the macro INIT_CUMULATIVE_ARGS defined in crx.h. */
-
-void
-crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
- rtx libfunc ATTRIBUTE_UNUSED)
-{
- tree param, next_param;
-
- cum->ints = 0;
-
- /* Determine if this function has variable arguments. This is indicated by
- * the last argument being 'void_type_mode' if there are no variable
- * arguments. Change here for a different vararg. */
- for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
- param != (tree) 0; param = next_param)
- {
- next_param = TREE_CHAIN (param);
- if (next_param == (tree) 0 && TREE_VALUE (param) != void_type_node)
- {
- cum->ints = -1;
- return;
- }
- }
-}
-
-/* Implements TARGET_FUNCTION_ARG_ADVANCE. */
-
-static void
-crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- /* l holds the number of registers required */
- int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
-
- /* If the parameter isn't passed on a register don't advance cum. */
- if (!last_parm_in_reg)
- return;
-
- if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
- return;
-
- if (mode == SImode || mode == HImode || mode == QImode || mode == DImode)
- {
- if (l <= 1)
- cum->ints += 1;
- else
- cum->ints += l;
- }
- else if (mode == SFmode || mode == DFmode)
- cum->ints += l;
- else if ((mode) == BLKmode)
- {
- if ((l = enough_regs_for_param (cum, type, mode)) != 0)
- cum->ints += l;
- }
-
-}
-
-/* Implements the macro FUNCTION_ARG_REGNO_P defined in crx.h. Return nonzero
- * if N is a register used for passing parameters. */
-
-int
-crx_function_arg_regno_p (int n)
-{
- return (n <= MAX_REG_FOR_PASSING_ARGS && n >= MIN_REG_FOR_PASSING_ARGS);
-}
-
-/* ADDRESSING MODES */
-/* ---------------- */
-
-/* Implements the hook for TARGET_LEGITIMATE_ADDRESS_P defined in crx.h.
- * The following addressing modes are supported on CRX:
- *
- * Relocations --> const | symbol_ref | label_ref
- * Absolute address --> 32-bit absolute
- * Post increment --> reg + 12-bit disp.
- * Post modify --> reg + 12-bit disp.
- * Register relative --> reg | 32-bit disp. + reg | 4 bit + reg
- * Scaled index --> reg + reg | 22-bit disp. + reg + reg |
- * 22-disp. + reg + reg + (2 | 4 | 8) */
-
-static rtx
-crx_addr_reg (rtx addr_reg)
-{
- if (GET_MODE (addr_reg) != Pmode)
- return NULL_RTX;
-
- if (REG_P (addr_reg))
- return addr_reg;
- else if (GET_CODE (addr_reg) == SUBREG
- && REG_P (SUBREG_REG (addr_reg))
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
- <= UNITS_PER_WORD))
- return SUBREG_REG (addr_reg);
- else
- return NULL_RTX;
-}
-
-enum crx_addrtype
-crx_decompose_address (rtx addr, struct crx_address *out)
-{
- rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
- rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX;
- int scale = -1;
-
- enum crx_addrtype retval = CRX_INVALID;
-
- switch (GET_CODE (addr))
- {
- case CONST_INT:
- /* Absolute address (known at compile time) */
- retval = CRX_ABSOLUTE;
- disp = addr;
- if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode)))
- return CRX_INVALID;
- break;
-
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- /* Absolute address (known at link time) */
- retval = CRX_ABSOLUTE;
- disp = addr;
- break;
-
- case REG:
- case SUBREG:
- /* Register relative address */
- retval = CRX_REG_REL;
- base = addr;
- break;
-
- case PLUS:
- switch (GET_CODE (XEXP (addr, 0)))
- {
- case REG:
- case SUBREG:
- if (REG_P (XEXP (addr, 1)))
- {
- /* Scaled index with scale = 1 and disp. = 0 */
- retval = CRX_SCALED_INDX;
- base = XEXP (addr, 1);
- index = XEXP (addr, 0);
- scale = 1;
- }
- else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28))
- {
- /* Register relative address and <= 28-bit disp. */
- retval = CRX_REG_REL;
- base = XEXP (addr, 0);
- disp = XEXP (addr, 1);
- }
- else
- return CRX_INVALID;
- break;
-
- case PLUS:
- /* Scaled index and <= 22-bit disp. */
- retval = CRX_SCALED_INDX;
- base = XEXP (XEXP (addr, 0), 1);
- disp = XEXP (addr, 1);
- if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22))
- return CRX_INVALID;
- switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
- {
- case REG:
- /* Scaled index with scale = 0 and <= 22-bit disp. */
- index = XEXP (XEXP (addr, 0), 0);
- scale = 1;
- break;
-
- case MULT:
- /* Scaled index with scale >= 0 and <= 22-bit disp. */
- index = XEXP (XEXP (XEXP (addr, 0), 0), 0);
- scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1);
- if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
- return CRX_INVALID;
- break;
-
- default:
- return CRX_INVALID;
- }
- break;
-
- case MULT:
- /* Scaled index with scale >= 0 */
- retval = CRX_SCALED_INDX;
- base = XEXP (addr, 1);
- index = XEXP (XEXP (addr, 0), 0);
- scale_rtx = XEXP (XEXP (addr, 0), 1);
- /* Scaled index with scale >= 0 and <= 22-bit disp. */
- if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
- return CRX_INVALID;
- break;
-
- default:
- return CRX_INVALID;
- }
- break;
-
- case POST_INC:
- case POST_DEC:
- /* Simple post-increment */
- retval = CRX_POST_INC;
- base = XEXP (addr, 0);
- side_effect = addr;
- break;
-
- case POST_MODIFY:
- /* Generic post-increment with <= 12-bit disp. */
- retval = CRX_POST_INC;
- base = XEXP (addr, 0);
- side_effect = XEXP (addr, 1);
- if (base != XEXP (side_effect, 0))
- return CRX_INVALID;
- switch (GET_CODE (side_effect))
- {
- case PLUS:
- case MINUS:
- disp = XEXP (side_effect, 1);
- if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12))
- return CRX_INVALID;
- break;
-
- default:
- /* CRX only supports PLUS and MINUS */
- return CRX_INVALID;
- }
- break;
-
- default:
- return CRX_INVALID;
- }
-
- if (base)
- {
- base = crx_addr_reg (base);
- if (!base)
- return CRX_INVALID;
- }
- if (index)
- {
- index = crx_addr_reg (index);
- if (!index)
- return CRX_INVALID;
- }
-
- out->base = base;
- out->index = index;
- out->disp = disp;
- out->scale = scale;
- out->side_effect = side_effect;
-
- return retval;
-}
-
-bool
-crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx addr, bool strict)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr,
- "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
- GET_MODE_NAME (mode), strict);
- debug_rtx (addr);
- }
-
- addrtype = crx_decompose_address (addr, &address);
-
- if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
- return FALSE;
-
- if (TARGET_DEBUG_ADDR)
- {
- const char *typestr;
- switch (addrtype)
- {
- case CRX_INVALID:
- typestr = "Invalid";
- break;
- case CRX_REG_REL:
- typestr = "Register relative";
- break;
- case CRX_POST_INC:
- typestr = "Post-increment";
- break;
- case CRX_SCALED_INDX:
- typestr = "Scaled index";
- break;
- case CRX_ABSOLUTE:
- typestr = "Absolute";
- break;
- default:
- abort ();
- }
- fprintf (stderr, "CRX Address type: %s\n", typestr);
- }
-
- if (addrtype == CRX_INVALID)
- return FALSE;
-
- if (strict)
- {
- if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base)))
- {
- if (TARGET_DEBUG_ADDR)
- fprintf (stderr, "Base register not strict\n");
- return FALSE;
- }
- if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
- {
- if (TARGET_DEBUG_ADDR)
- fprintf (stderr, "Index register not strict\n");
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-/* ROUTINES TO COMPUTE COSTS */
-/* ------------------------- */
-
-/* Return cost of the memory address x. */
-
-static int
-crx_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- int cost = 2;
-
- addrtype = crx_decompose_address (addr, &address);
-
- gcc_assert (addrtype != CRX_INVALID);
-
- /* An absolute address causes a 3-word instruction */
- if (addrtype == CRX_ABSOLUTE)
- cost+=2;
-
- /* Post-modifying addresses are more powerful. */
- if (addrtype == CRX_POST_INC)
- cost-=2;
-
- /* Attempt to minimize number of registers in the address. */
- if (address.base)
- cost++;
-
- if (address.index && address.scale == 1)
- cost+=5;
-
- if (address.disp && !INT_CST4 (INTVAL (address.disp)))
- cost+=2;
-
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
- debug_rtx (addr);
- }
-
- return cost;
-}
-
-/* Return the cost of moving data of mode MODE between a register of class
- * RCLASS and memory; IN is zero if the value is to be written to memory,
- * nonzero if it is to be read in. This cost is relative to those in
- * REGISTER_MOVE_COST. */
-
-int
-crx_memory_move_cost (enum machine_mode mode,
- enum reg_class rclass ATTRIBUTE_UNUSED,
- int in ATTRIBUTE_UNUSED)
-{
- /* One LD or ST takes twice the time of a simple reg-reg move */
- if (reg_classes_intersect_p (rclass, GENERAL_REGS))
- {
- /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
- return 4 * HARD_REGNO_NREGS (0, mode);
- }
- else if (reg_classes_intersect_p (rclass, HILO_REGS))
- {
- /* HILO to memory and vice versa */
- /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
- (REGISTER_MOVE_COST (mode,
- in ? GENERAL_REGS : HILO_REGS,
- in ? HILO_REGS : GENERAL_REGS) + 4)
- * HARD_REGNO_NREGS (0, mode)); */
- return (REGISTER_MOVE_COST (mode,
- in ? GENERAL_REGS : HILO_REGS,
- in ? HILO_REGS : GENERAL_REGS) + 4)
- * HARD_REGNO_NREGS (0, mode);
- }
- else /* default (like in i386) */
- {
- /* printf ("ANYREGS = 100\n"); */
- return 100;
- }
-}
-
-/* INSTRUCTION OUTPUT */
-/* ------------------ */
-
-/* Check if a const_double is ok for crx store-immediate instructions */
-
-int
-crx_const_double_ok (rtx op)
-{
- if (GET_MODE (op) == DFmode)
- {
- REAL_VALUE_TYPE r;
- long l[2];
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
- return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) &&
- UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0;
- }
-
- if (GET_MODE (op) == SFmode)
- {
- REAL_VALUE_TYPE r;
- long l;
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
- return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
- }
-
- return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) &&
- UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0;
-}
-
-/* Implements the macro PRINT_OPERAND defined in crx.h. */
-
-void
-crx_print_operand (FILE * file, rtx x, int code)
-{
- switch (code)
- {
- case 'p' :
- if (GET_CODE (x) == REG) {
- if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
- {
- int regno = REGNO (x);
- if (regno + 1 >= SP_REGNUM) abort ();
- fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]);
- return;
- }
- else
- {
- if (REGNO (x) >= SP_REGNUM) abort ();
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
- }
- }
-
- case 'd' :
- {
- const char *crx_cmp_str;
- switch (GET_CODE (x))
- { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg)
- * -> swap all non symmetric ops */
- case EQ : crx_cmp_str = "eq"; break;
- case NE : crx_cmp_str = "ne"; break;
- case GT : crx_cmp_str = "lt"; break;
- case GTU : crx_cmp_str = "lo"; break;
- case LT : crx_cmp_str = "gt"; break;
- case LTU : crx_cmp_str = "hi"; break;
- case GE : crx_cmp_str = "le"; break;
- case GEU : crx_cmp_str = "ls"; break;
- case LE : crx_cmp_str = "ge"; break;
- case LEU : crx_cmp_str = "hs"; break;
- default : abort ();
- }
- fprintf (file, "%s", crx_cmp_str);
- return;
- }
-
- case 'H':
- /* Print high part of a double precision value. */
- switch (GET_CODE (x))
- {
- case CONST_DOUBLE:
- if (GET_MODE (x) == SFmode) abort ();
- if (GET_MODE (x) == DFmode)
- {
- /* High part of a DF const. */
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-
- fprintf (file, "$0x%lx", l[1]);
- return;
- }
-
- /* -- Fallthrough to handle DI consts -- */
-
- case CONST_INT:
- {
- rtx high, low;
- split_double (x, &low, &high);
- putc ('$', file);
- output_addr_const (file, high);
- return;
- }
-
- case REG:
- if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort ();
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
- return;
-
- case MEM:
- /* Adjust memory address to high part. */
- {
- rtx adj_mem = x;
- adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4);
-
- output_memory_reference_mode = GET_MODE (adj_mem);
- output_address (XEXP (adj_mem, 0));
- return;
- }
-
- default:
- abort ();
- }
-
- case 'L':
- /* Print low part of a double precision value. */
- switch (GET_CODE (x))
- {
- case CONST_DOUBLE:
- if (GET_MODE (x) == SFmode) abort ();
- if (GET_MODE (x) == DFmode)
- {
- /* High part of a DF const. */
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
-
- fprintf (file, "$0x%lx", l[0]);
- return;
- }
-
- /* -- Fallthrough to handle DI consts -- */
-
- case CONST_INT:
- {
- rtx high, low;
- split_double (x, &low, &high);
- putc ('$', file);
- output_addr_const (file, low);
- return;
- }
-
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
-
- case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
- return;
-
- default:
- abort ();
- }
-
- case 0 : /* default */
- switch (GET_CODE (x))
- {
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- return;
-
- case MEM:
- output_memory_reference_mode = GET_MODE (x);
- output_address (XEXP (x, 0));
- return;
-
- case CONST_DOUBLE:
- {
- REAL_VALUE_TYPE r;
- long l;
-
- /* Always use H and L for double precision - see above */
- gcc_assert (GET_MODE (x) == SFmode);
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
-
- fprintf (file, "$0x%lx", l);
- return;
- }
-
- default:
- putc ('$', file);
- output_addr_const (file, x);
- return;
- }
-
- default:
- output_operand_lossage ("invalid %%xn code");
- }
-
- abort ();
-}
-
-/* Implements the macro PRINT_OPERAND_ADDRESS defined in crx.h. */
-
-void
-crx_print_operand_address (FILE * file, rtx addr)
-{
- enum crx_addrtype addrtype;
- struct crx_address address;
-
- int offset;
-
- addrtype = crx_decompose_address (addr, &address);
-
- if (address.disp)
- offset = INTVAL (address.disp);
- else
- offset = 0;
-
- switch (addrtype)
- {
- case CRX_REG_REL:
- fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]);
- return;
-
- case CRX_POST_INC:
- switch (GET_CODE (address.side_effect))
- {
- case PLUS:
- break;
- case MINUS:
- offset = -offset;
- break;
- case POST_INC:
- offset = GET_MODE_SIZE (output_memory_reference_mode);
- break;
- case POST_DEC:
- offset = -GET_MODE_SIZE (output_memory_reference_mode);
- break;
- default:
- abort ();
- }
- fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]);
- return;
-
- case CRX_SCALED_INDX:
- fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)],
- reg_names[REGNO (address.index)], address.scale);
- return;
-
- case CRX_ABSOLUTE:
- output_addr_const (file, address.disp);
- return;
-
- default:
- abort ();
- }
-}
-
-
-/*****************************************************************************/
-/* MACHINE DESCRIPTION HELPER-FUNCTIONS */
-/*****************************************************************************/
-
-void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
- rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p)
-{
- rtx addr, mem;
- unsigned HOST_WIDE_INT offset = *offset_p;
-
- /* Load */
- addr = plus_constant (src, offset);
- mem = adjust_automodify_address (srcbase, SImode, addr, offset);
- emit_move_insn (tmp_reg, mem);
-
- /* Store */
- addr = plus_constant (dst, offset);
- mem = adjust_automodify_address (dstbase, SImode, addr, offset);
- emit_move_insn (mem, tmp_reg);
-
- *offset_p = offset + 4;
-}
-
-int
-crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
-{
- unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
- HOST_WIDE_INT align = 0;
-
- rtx src, dst;
- rtx tmp_reg;
-
- if (GET_CODE (align_exp) == CONST_INT)
- { /* Only if aligned */
- align = INTVAL (align_exp);
- if (align & 3)
- return 0;
- }
-
- if (GET_CODE (count_exp) == CONST_INT)
- { /* No more than 16 SImode moves */
- count = INTVAL (count_exp);
- if (count > 64)
- return 0;
- }
-
- tmp_reg = gen_reg_rtx (SImode);
-
- /* Create psrs for the src and dest pointers */
- dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
- if (dst != XEXP (dstbase, 0))
- dstbase = replace_equiv_address_nv (dstbase, dst);
- src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
- if (src != XEXP (srcbase, 0))
- srcbase = replace_equiv_address_nv (srcbase, src);
-
- offset = 0;
-
- /* Emit SImode moves */
- si_moves = count >> 2;
- for (i = 0; i < si_moves; i++)
- crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
-
- /* Special cases */
- if (count & 3)
- {
- offset = count - 4;
- crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
- }
-
- gcc_assert (offset == count);
-
- return 1;
-}
-
-static void
-mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
-{
- if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */
- sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask);
- else /* single word instruction */
- sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask);
-}
-
-/* Called from crx.md. The return value depends on the parameter push_or_pop:
- * When push_or_pop is zero -> string for push instructions of prologue.
- * When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
- * Relies on the assumptions:
- * 1. RA is the last register to be saved.
- * 2. The maximal value of the counter is MAX_COUNT. */
-
-char *
-crx_prepare_push_pop_string (int push_or_pop)
-{
- /* j is the number of registers being saved, takes care that there won't be
- * more than 8 in one push/pop instruction */
-
- /* For the register mask string */
- static char mask_str[50];
-
- /* i is the index of save_regs[], going from 0 until last_reg_to_save */
- int i = 0;
-
- int ra_in_bitmask = 0;
-
- char *return_str;
-
- /* For reversing on the push instructions if there are more than one. */
- char *temp_str;
-
- return_str = (char *) xmalloc (120);
- temp_str = (char *) xmalloc (120);
-
- /* Initialize */
- memset (return_str, 0, 3);
-
- while (i <= last_reg_to_save)
- {
- /* Prepare mask for one instruction. */
- mask_str[0] = 0;
-
- if (i <= SP_REGNUM)
- { /* Add regs unit full or SP register reached */
- int j = 0;
- while (j < MAX_COUNT && i <= SP_REGNUM)
- {
- if (save_regs[i])
- {
- /* TODO to use ra_in_bitmask for detecting last pop is not
- * smart it prevents things like: popret r5 */
- if (i == RETURN_ADDRESS_REGNUM) ra_in_bitmask = 1;
- if (j > 0) strcat (mask_str, ", ");
- strcat (mask_str, reg_names[i]);
- ++j;
- }
- ++i;
- }
- }
- else
- {
- /* Handle hi/lo savings */
- while (i <= last_reg_to_save)
- {
- if (save_regs[i])
- {
- strcat (mask_str, "lo, hi");
- i = last_reg_to_save + 1;
- break;
- }
- ++i;
- }
- }
-
- if (strlen (mask_str) == 0) continue;
-
- if (push_or_pop == 1)
- {
- if (crx_interrupt_function_p ())
- mpushpop_str (temp_str, "popx", mask_str);
- else
- {
- if (ra_in_bitmask)
- {
- mpushpop_str (temp_str, "popret", mask_str);
- ra_in_bitmask = 0;
- }
- else mpushpop_str (temp_str, "pop", mask_str);
- }
-
- strcat (return_str, temp_str);
- }
- else
- {
- /* push - We need to reverse the order of the instructions if there
- * are more than one. (since the pop will not be reversed in the
- * epilogue */
- if (crx_interrupt_function_p ())
- mpushpop_str (temp_str, "pushx", mask_str);
- else
- mpushpop_str (temp_str, "push", mask_str);
- strcat (temp_str, return_str);
- strcpy (strcat (return_str, "\t"), temp_str);
- }
-
- }
-
- if (push_or_pop == 1)
- {
- /* pop */
- if (crx_interrupt_function_p ())
- strcat (return_str, "\n\tretx\n");
-
- else if (!FUNC_IS_NORETURN_P (current_function_decl)
- && !save_regs[RETURN_ADDRESS_REGNUM])
- strcat (return_str, "\n\tjump\tra\n");
- }
-
- /* Skip the newline and the tab in the start of return_str. */
- return_str += 2;
- return return_str;
-}
-
-/* CompactRISC CRX Architecture stack layout:
-
- 0 +---------------------
- |
- .
- .
- |
- +==================== Sp(x)=Ap(x+1)
- A | Args for functions
- | | called by X and Dynamically
- | | Dynamic allocations allocated and
- | | (alloca, variable deallocated
- Stack | length arrays).
- grows +-------------------- Fp(x)
- down| | Local variables of X
- ward| +--------------------
- | | Regs saved for X-1
- | +==================== Sp(x-1)=Ap(x)
- | Args for func X
- | pushed by X-1
- +-------------------- Fp(x-1)
- |
- |
- V
-
-*/
-
-void
-crx_expand_prologue (void)
-{
- crx_compute_frame ();
- crx_compute_save_regs ();
-
- /* If there is no need in push and adjustment to sp, return. */
- if (size_for_adjusting_sp + sum_regs == 0)
- return;
-
- if (last_reg_to_save != -1)
- /* If there are registers to push. */
- emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));
-
- if (size_for_adjusting_sp > 0)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-size_for_adjusting_sp)));
-
- if (frame_pointer_needed)
- /* Initialize the frame pointer with the value of the stack pointer
- * pointing now to the locals. */
- emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-}
-
-/* Generate insn that updates the stack for local variables and padding for
- * registers we save. - Generate the appropriate return insn. */
-
-void
-crx_expand_epilogue (void)
-{
- /* Nonzero if we need to return and pop only RA. This will generate a
- * different insn. This differentiate is for the peepholes for call as last
- * statement in function. */
- int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
- && (sum_regs == UNITS_PER_WORD));
-
- if (frame_pointer_needed)
- /* Restore the stack pointer with the frame pointers value */
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
-
- if (size_for_adjusting_sp > 0)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (size_for_adjusting_sp)));
-
- if (crx_interrupt_function_p ())
- emit_jump_insn (gen_interrupt_return ());
- else if (last_reg_to_save == -1)
- /* Nothing to pop */
- /* Don't output jump for interrupt routine, only retx. */
- emit_jump_insn (gen_indirect_jump_return ());
- else if (only_popret_RA)
- emit_jump_insn (gen_popret_RA_return ());
- else
- emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
-}
diff --git a/gcc/config/crx/crx.h b/gcc/config/crx/crx.h
deleted file mode 100644
index da6e263ca52..00000000000
--- a/gcc/config/crx/crx.h
+++ /dev/null
@@ -1,478 +0,0 @@
-/* Definitions of target machine for GNU compiler, for CRX.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_CRX_H
-#define GCC_CRX_H
-
-/*****************************************************************************/
-/* CONTROLLING THE DRIVER */
-/*****************************************************************************/
-
-#define CC1PLUS_SPEC "%{!frtti:-fno-rtti} \
- %{!fenforce-eh-specs:-fno-enforce-eh-specs} \
- %{!fexceptions:-fno-exceptions} \
- %{!fthreadsafe-statics:-fno-threadsafe-statics}"
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crti.o%s crtbegin.o%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtend.o%s crtn.o%s"
-
-#undef MATH_LIBRARY
-#define MATH_LIBRARY ""
-
-/*****************************************************************************/
-/* RUN-TIME TARGET SPECIFICATION */
-/*****************************************************************************/
-
-#ifndef TARGET_CPU_CPP_BUILTINS
-#define TARGET_CPU_CPP_BUILTINS() \
-do { \
- builtin_define("__CRX__"); \
- builtin_define("__CR__"); \
-} while (0)
-#endif
-
-#define TARGET_VERSION fputs (" (CRX/ELF)", stderr);
-
-/*****************************************************************************/
-/* STORAGE LAYOUT */
-/*****************************************************************************/
-
-#define BITS_BIG_ENDIAN 0
-
-#define BYTES_BIG_ENDIAN 0
-
-#define WORDS_BIG_ENDIAN 0
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PARM_BOUNDARY 32
-
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-#define BIGGEST_ALIGNMENT 32
-
-/* In CRX arrays of chars are word-aligned, so strcpy() will be faster. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TREE_CODE (TYPE) == ARRAY_TYPE && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
- && (ALIGN) < BITS_PER_WORD \
- ? (BITS_PER_WORD) : (ALIGN))
-
-/* In CRX strings are word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(CONSTANT, ALIGN) \
- (TREE_CODE (CONSTANT) == STRING_CST && (ALIGN) < BITS_PER_WORD \
- ? (BITS_PER_WORD) : (ALIGN))
-
-#define STRICT_ALIGNMENT 0
-
-#define PCC_BITFIELD_TYPE_MATTERS 1
-
-/*****************************************************************************/
-/* LAYOUT OF SOURCE LANGUAGE DATA TYPES */
-/*****************************************************************************/
-
-#define INT_TYPE_SIZE 32
-
-#define SHORT_TYPE_SIZE 16
-
-#define LONG_TYPE_SIZE 32
-
-#define LONG_LONG_TYPE_SIZE 64
-
-#define FLOAT_TYPE_SIZE 32
-
-#define DOUBLE_TYPE_SIZE 64
-
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-#define DEFAULT_SIGNED_CHAR 1
-
-#define SIZE_TYPE "unsigned int"
-
-#define PTRDIFF_TYPE "int"
-
-/*****************************************************************************/
-/* REGISTER USAGE. */
-/*****************************************************************************/
-
-#define FIRST_PSEUDO_REGISTER 19
-
-/* On the CRX, only the stack pointer (r15) is such. */
-#define FIXED_REGISTERS \
- { \
- /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 */ \
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- /* r11 r12 r13 ra sp r16 r17 cc */ \
- 0, 0, 0, 0, 1, 0, 0, 1 \
- }
-
-/* On the CRX, calls clobbers r0-r6 (scratch registers), ra (the return address)
- * and sp - (the stack pointer which is fixed). */
-#define CALL_USED_REGISTERS \
- { \
- /* r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 */ \
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
- /* r11 r12 r13 ra sp r16 r17 cc */ \
- 0, 0, 0, 1, 1, 1, 1, 1 \
- }
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-
-/* On the CRX architecture, HILO regs can only hold SI mode. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) crx_hard_regno_mode_ok(REGNO, MODE)
-
-/* So far no patterns for moving CCMODE data are available */
-#define AVOID_CCMODE_COPIES
-
-/* Interrupt functions can only use registers that have already been saved by
- * the prologue, even if they would normally be call-clobbered. */
-#define HARD_REGNO_RENAME_OK(SRC, DEST) \
- (!crx_interrupt_function_p () || df_regs_ever_live_p (DEST))
-
-#define MODES_TIEABLE_P(MODE1, MODE2) 1
-
-enum reg_class
-{
- NO_REGS,
- LO_REGS,
- HI_REGS,
- HILO_REGS,
- NOSP_REGS,
- GENERAL_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
-#define REG_CLASS_NAMES \
- { \
- "NO_REGS", \
- "LO_REGS", \
- "HI_REGS", \
- "HILO_REGS", \
- "NOSP_REGS", \
- "GENERAL_REGS", \
- "ALL_REGS" \
- }
-
-#define REG_CLASS_CONTENTS \
- { \
- {0x00000000}, /* NO_REGS */ \
- {0x00010000}, /* LO_REGS : 16 */ \
- {0x00020000}, /* HI_REGS : 17 */ \
- {0x00030000}, /* HILO_REGS : 16, 17 */ \
- {0x00007fff}, /* NOSP_REGS : 0 - 14 */ \
- {0x0000ffff}, /* GENERAL_REGS : 0 - 15 */ \
- {0x0007ffff} /* ALL_REGS : 0 - 18 */ \
- }
-
-#define REGNO_REG_CLASS(REGNO) crx_regno_reg_class(REGNO)
-
-#define BASE_REG_CLASS GENERAL_REGS
-
-#define INDEX_REG_CLASS GENERAL_REGS
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'b' ? NOSP_REGS : \
- (C) == 'l' ? LO_REGS : \
- (C) == 'h' ? HI_REGS : \
- (C) == 'k' ? HILO_REGS : \
- NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 16 \
- || (reg_renumber && (unsigned)reg_renumber[REGNO] < 16))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
-
-#define SECONDARY_RELOAD_CLASS(CLASS, MODE, X) \
- crx_secondary_reload_class (CLASS, MODE, X)
-
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD
-
-#define SIGNED_INT_FITS_N_BITS(imm, N) \
- ((((imm) < ((long long)1<<((N)-1))) && ((imm) >= -((long long)1<<((N)-1)))) ? 1 : 0)
-
-#define UNSIGNED_INT_FITS_N_BITS(imm, N) \
- (((imm) < ((long long)1<<(N)) && (imm) >= (long long)0) ? 1 : 0)
-
-#define HILO_REGNO_P(regno) \
- (reg_classes_intersect_p(REGNO_REG_CLASS(regno), HILO_REGS))
-
-#define INT_CST4(VALUE) \
- (((VALUE) >= -1 && (VALUE) <= 4) || (VALUE) == -4 \
- || (VALUE) == 7 || (VALUE) == 8 || (VALUE) == 16 || (VALUE) == 32 \
- || (VALUE) == 20 || (VALUE) == 12 || (VALUE) == 48)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- /* Legal const for store immediate instructions */ \
- ((C) == 'I' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 3) : \
- (C) == 'J' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 4) : \
- (C) == 'K' ? UNSIGNED_INT_FITS_N_BITS(VALUE, 5) : \
- (C) == 'L' ? INT_CST4(VALUE) : \
- 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? crx_const_double_ok (VALUE) : \
- 0)
-
-/*****************************************************************************/
-/* STACK LAYOUT AND CALLING CONVENTIONS. */
-/*****************************************************************************/
-
-#define STACK_GROWS_DOWNWARD
-
-#define STARTING_FRAME_OFFSET 0
-
-#define STACK_POINTER_REGNUM 15
-
-#define FRAME_POINTER_REGNUM 13
-
-#define ARG_POINTER_REGNUM 12
-
-#define STATIC_CHAIN_REGNUM 1
-
-#define RETURN_ADDRESS_REGNUM 14
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-#define ELIMINABLE_REGS \
- { \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
- }
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- do { \
- (OFFSET) = crx_initial_elimination_offset ((FROM), (TO)); \
- } while (0)
-
-/*****************************************************************************/
-/* PASSING FUNCTION ARGUMENTS */
-/*****************************************************************************/
-
-#define ACCUMULATE_OUTGOING_ARGS (TARGET_NO_PUSH_ARGS)
-
-#define PUSH_ARGS (!TARGET_NO_PUSH_ARGS)
-
-#define PUSH_ROUNDING(BYTES) (((BYTES) + 3) & ~3)
-
-#ifndef CUMULATIVE_ARGS
-struct cumulative_args
-{
- int ints;
-};
-
-#define CUMULATIVE_ARGS struct cumulative_args
-#endif
-
-/* On the CRX architecture, Varargs routines should receive their parameters on
- * the stack. */
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- crx_init_cumulative_args(&(CUM), (FNTYPE), (LIBNAME))
-
-#define FUNCTION_ARG_REGNO_P(REGNO) crx_function_arg_regno_p(REGNO)
-
-/*****************************************************************************/
-/* RETURNING FUNCTION VALUE */
-/*****************************************************************************/
-
-/* On the CRX, the return value is in R0 */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG(TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, 0)
-
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
-
-#define CRX_STRUCT_VALUE_REGNUM 0
-
-/*****************************************************************************/
-/* GENERATING CODE FOR PROFILING - NOT IMPLEMENTED */
-/*****************************************************************************/
-
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- sorry ("profiler support for CRX"); \
-}
-
-/*****************************************************************************/
-/* TRAMPOLINES FOR NESTED FUNCTIONS - NOT SUPPORTED */
-/*****************************************************************************/
-
-#define TRAMPOLINE_SIZE 32
-
-/*****************************************************************************/
-/* ADDRESSING MODES */
-/*****************************************************************************/
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST \
- || GET_CODE (X) == CONST_INT)
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#define HAVE_POST_INCREMENT 1
-#define HAVE_POST_DECREMENT 1
-#define HAVE_POST_MODIFY_DISP 1
-#define HAVE_POST_MODIFY_REG 0
-
-#ifdef REG_OK_STRICT
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-#else
-#define REG_OK_FOR_BASE_P(X) 1
-#define REG_OK_FOR_INDEX_P(X) 1
-#endif /* REG_OK_STRICT */
-
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-/*****************************************************************************/
-/* CONDITION CODE STATUS */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/* RELATIVE COSTS OF OPERATIONS */
-/*****************************************************************************/
-
-#define MEMORY_MOVE_COST(MODE, CLASS, IN) crx_memory_move_cost(MODE, CLASS, IN)
-/* Moving to processor register flushes pipeline - thus asymmetric */
-#define REGISTER_MOVE_COST(MODE, FROM, TO) ((TO != GENERAL_REGS) ? 8 : 2)
-/* Assume best case (branch predicted) */
-#define BRANCH_COST(speed_p, predictable_p) 2
-
-#define SLOW_BYTE_ACCESS 1
-
-/*****************************************************************************/
-/* DIVIDING THE OUTPUT INTO SECTIONS */
-/*****************************************************************************/
-
-#define TEXT_SECTION_ASM_OP "\t.section\t.text"
-
-#define DATA_SECTION_ASM_OP "\t.section\t.data"
-
-#define BSS_SECTION_ASM_OP "\t.section\t.bss"
-
-/*****************************************************************************/
-/* POSITION INDEPENDENT CODE */
-/*****************************************************************************/
-
-#define PIC_OFFSET_TABLE_REGNUM 12
-
-#define LEGITIMATE_PIC_OPERAND_P(X) 1
-
-/*****************************************************************************/
-/* ASSEMBLER FORMAT */
-/*****************************************************************************/
-
-#define GLOBAL_ASM_OP "\t.globl\t"
-
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
- asm_fprintf (STREAM, "%U%s", (*targetm.strip_name_encoding) (NAME));
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/*****************************************************************************/
-/* INSTRUCTION OUTPUT */
-/*****************************************************************************/
-
-#define REGISTER_NAMES \
- { \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp", \
- "lo", "hi", "cc" \
- }
-
-#define PRINT_OPERAND(STREAM, X, CODE) \
- crx_print_operand(STREAM, X, CODE)
-
-#define PRINT_OPERAND_ADDRESS(STREAM, ADDR) \
- crx_print_operand_address(STREAM, ADDR)
-
-/*****************************************************************************/
-/* OUTPUT OF DISPATCH TABLES */
-/*****************************************************************************/
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- asm_fprintf ((STREAM), "\t.long\t.L%d\n", (VALUE))
-
-/*****************************************************************************/
-/* ALIGNMENT IN ASSEMBLER FILE */
-/*****************************************************************************/
-
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- asm_fprintf ((STREAM), "\t.align\t%d\n", 1 << (POWER))
-
-/*****************************************************************************/
-/* MISCELLANEOUS PARAMETERS */
-/*****************************************************************************/
-
-#define CASE_VECTOR_MODE Pmode
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE QImode
-
-#endif /* ! GCC_CRX_H */
diff --git a/gcc/config/crx/crx.md b/gcc/config/crx/crx.md
deleted file mode 100644
index 229e345d32f..00000000000
--- a/gcc/config/crx/crx.md
+++ /dev/null
@@ -1,899 +0,0 @@
-;; GCC machine description for CRX.
-;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2007
-;; Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>. */
-
-;; Register numbers
-
-(define_constants
- [(SP_REGNUM 15) ; Stack pointer
- (RA_REGNUM 14) ; Return address
- (LO_REGNUM 16) ; LO register
- (HI_REGNUM 17) ; HI register
- (CC_REGNUM 18) ; Condition code register
- ]
-)
-
-(define_attr "length" "" ( const_int 6 ))
-
-(define_asm_attributes
- [(set_attr "length" "6")]
-)
-
-;; Predicates
-
-(define_predicate "u4bits_operand"
- (match_code "const_int,const_double")
- {
- if (GET_CODE (op) == CONST_DOUBLE)
- return crx_const_double_ok (op);
- return (UNSIGNED_INT_FITS_N_BITS(INTVAL(op), 4)) ? 1 : 0;
- }
-)
-
-(define_predicate "cst4_operand"
- (and (match_code "const_int")
- (match_test "INT_CST4(INTVAL(op))")))
-
-(define_predicate "reg_or_u4bits_operand"
- (ior (match_operand 0 "u4bits_operand")
- (match_operand 0 "register_operand")))
-
-(define_predicate "reg_or_cst4_operand"
- (ior (match_operand 0 "cst4_operand")
- (match_operand 0 "register_operand")))
-
-(define_predicate "reg_or_sym_operand"
- (ior (match_code "symbol_ref")
- (match_operand 0 "register_operand")))
-
-(define_predicate "cc_reg_operand"
- (and (match_code "reg")
- (match_test "REGNO (op) == CC_REGNUM")))
-
-(define_predicate "nosp_reg_operand"
- (and (match_operand 0 "register_operand")
- (match_test "REGNO (op) != SP_REGNUM")))
-
-(define_predicate "store_operand"
- (and (match_operand 0 "memory_operand")
- (not (match_operand 0 "push_operand"))))
-
-;; Mode Macro Definitions
-
-(define_mode_iterator ALLMT [QI HI SI SF DI DF])
-(define_mode_iterator CRXMM [QI HI SI SF])
-(define_mode_iterator CRXIM [QI HI SI])
-(define_mode_iterator DIDFM [DI DF])
-(define_mode_iterator SISFM [SI SF])
-(define_mode_iterator SHORT [QI HI])
-
-(define_mode_attr tIsa [(QI "b") (HI "w") (SI "d") (SF "d")])
-(define_mode_attr lImmArith [(QI "4") (HI "4") (SI "6")])
-(define_mode_attr lImmRotl [(QI "2") (HI "2") (SI "4")])
-(define_mode_attr IJK [(QI "I") (HI "J") (SI "K")])
-(define_mode_attr iF [(QI "i") (HI "i") (SI "i") (DI "i") (SF "F") (DF "F")])
-(define_mode_attr JG [(QI "J") (HI "J") (SI "J") (DI "J") (SF "G") (DF "G")])
-; In HI or QI mode we push 4 bytes.
-(define_mode_attr pushCnstr [(QI "X") (HI "X") (SI "<") (SF "<") (DI "<") (DF "<")])
-(define_mode_attr tpush [(QI "") (HI "") (SI "") (SF "") (DI "sp, ") (DF "sp, ")])
-(define_mode_attr lpush [(QI "2") (HI "2") (SI "2") (SF "2") (DI "4") (DF "4")])
-
-
-;; Code Macro Definitions
-
-(define_code_iterator sz_xtnd [sign_extend zero_extend])
-(define_code_attr sIsa [(sign_extend "") (zero_extend "u")])
-(define_code_attr sPat [(sign_extend "s") (zero_extend "u")])
-(define_code_attr szPat [(sign_extend "") (zero_extend "zero_")])
-(define_code_attr szIsa [(sign_extend "s") (zero_extend "z")])
-
-(define_code_iterator sh_oprnd [ashift ashiftrt lshiftrt])
-(define_code_attr shIsa [(ashift "ll") (ashiftrt "ra") (lshiftrt "rl")])
-(define_code_attr shPat [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr")])
-
-(define_code_iterator mima_oprnd [smax umax smin umin])
-(define_code_attr mimaIsa [(smax "maxs") (umax "maxu") (smin "mins") (umin "minu")])
-
-;; Addition Instructions
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (plus:DI (match_operand:DI 1 "register_operand" "%0,0")
- (match_operand:DI 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "addd\t%L2, %L1\;addcd\t%H2, %H1"
- [(set_attr "length" "4,12")]
-)
-
-(define_insn "add<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (plus:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "add<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Subtract Instructions
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "subd\t%L2, %L1\;subcd\t%H2, %H1"
- [(set_attr "length" "4,12")]
-)
-
-(define_insn "sub<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (minus:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "sub<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Multiply Instructions
-
-(define_insn "mul<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (mult:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Widening-multiplication Instructions
-
-(define_insn "<sIsa>mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=k")
- (mult:DI (sz_xtnd:DI (match_operand:SI 1 "register_operand" "%r"))
- (sz_xtnd:DI (match_operand:SI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mull<sPat>d\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sIsa>mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "%0"))
- (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<sPat>wd\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sIsa>mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (mult:HI (sz_xtnd:HI (match_operand:QI 1 "register_operand" "%0"))
- (sz_xtnd:HI (match_operand:QI 2 "register_operand" "r"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mul<sPat>bw\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; Logical Instructions - and
-
-(define_insn "and<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (and:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "and<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Logical Instructions - or
-
-(define_insn "ior<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (ior:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "or<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Logical Instructions - xor
-
-(define_insn "xor<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (xor:CRXIM (match_operand:CRXIM 1 "register_operand" "%0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,i")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "xor<tIsa>\t%2, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-;; Sign and Zero Extend Instructions
-
-(define_insn "<szPat>extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sz_xtnd:SI (match_operand:HI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extwd\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<szPat>extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sz_xtnd:SI (match_operand:QI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extbd\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<szPat>extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (sz_xtnd:HI (match_operand:QI 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "<szIsa>extbw\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Negation Instructions
-
-(define_insn "neg<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (neg:CRXIM (match_operand:CRXIM 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "neg<tIsa>\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Absolute Instructions
-
-(define_insn "abs<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (abs:CRXIM (match_operand:CRXIM 1 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "abs<tIsa>\t%1, %0"
- [(set_attr "length" "4")]
-)
-
-;; Max and Min Instructions
-
-(define_insn "<code><mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (mima_oprnd:CRXIM (match_operand:CRXIM 1 "register_operand" "%0")
- (match_operand:CRXIM 2 "register_operand" "r")))]
- ""
- "<mimaIsa><tIsa>\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; One's Complement
-
-(define_insn "one_cmpl<mode>2"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (not:CRXIM (match_operand:CRXIM 1 "register_operand" "0")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "xor<tIsa>\t$-1, %0"
- [(set_attr "length" "2")]
-)
-
-;; Rotate Instructions
-
-(define_insn "rotl<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (rotate:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:CRXIM 2 "nonmemory_operand" "r,<IJK>")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- rotl<tIsa>\t%2, %0
- rot<tIsa>\t%2, %0"
- [(set_attr "length" "4,<lImmRotl>")]
-)
-
-(define_insn "rotr<mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r")
- (rotatert:CRXIM (match_operand:CRXIM 1 "register_operand" "0")
- (match_operand:CRXIM 2 "register_operand" "r")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "rotr<tIsa>\t%2, %0"
- [(set_attr "length" "4")]
-)
-
-;; Arithmetic Left and Right Shift Instructions
-
-(define_insn "<shPat><mode>3"
- [(set (match_operand:CRXIM 0 "register_operand" "=r,r")
- (sh_oprnd:CRXIM (match_operand:CRXIM 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "r,<IJK>")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "s<shIsa><tIsa>\t%2, %0"
- [(set_attr "length" "2,2")]
-)
-
-;; Bit Set Instructions
-
-(define_insn "extv"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- ""
- {
- static char buf[100];
- int strpntr;
- int size = INTVAL (operands[2]);
- int pos = INTVAL (operands[3]);
- strpntr = sprintf (buf, "ram\t$%d, $31, $%d, %%1, %%0\;",
- BITS_PER_WORD - (size + pos), BITS_PER_WORD - size);
- sprintf (buf + strpntr, "srad\t$%d, %%0", BITS_PER_WORD - size);
- return buf;
- }
- [(set_attr "length" "6")]
-)
-
-(define_insn "extzv"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")
- (match_operand:SI 3 "const_int_operand" "n")))]
- ""
- {
- static char buf[40];
- int size = INTVAL (operands[2]);
- int pos = INTVAL (operands[3]);
- sprintf (buf, "ram\t$%d, $%d, $0, %%1, %%0",
- (BITS_PER_WORD - pos) % BITS_PER_WORD, size - 1);
- return buf;
- }
- [(set_attr "length" "4")]
-)
-
-(define_insn "insv"
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (match_operand:SI 3 "register_operand" "r"))]
- ""
- {
- static char buf[40];
- int size = INTVAL (operands[1]);
- int pos = INTVAL (operands[2]);
- sprintf (buf, "rim\t$%d, $%d, $%d, %%3, %%0",
- pos, size + pos - 1, pos);
- return buf;
- }
- [(set_attr "length" "4")]
-)
-
-;; Move Instructions
-
-(define_expand "mov<mode>"
- [(set (match_operand:ALLMT 0 "nonimmediate_operand" "")
- (match_operand:ALLMT 1 "general_operand" ""))]
- ""
- {
- if (!(reload_in_progress || reload_completed))
- {
- if (!register_operand (operands[0], <MODE>mode))
- {
- if (push_operand (operands[0], <MODE>mode) ?
- !nosp_reg_operand (operands[1], <MODE>mode) :
- !reg_or_u4bits_operand (operands[1], <MODE>mode))
- {
- operands[1] = copy_to_mode_reg (<MODE>mode, operands[1]);
- }
- }
- }
- }
-)
-
-(define_insn "push<mode>_internal"
- [(set (match_operand:ALLMT 0 "push_operand" "=<pushCnstr>")
- (match_operand:ALLMT 1 "nosp_reg_operand" "b"))]
- ""
- "push\t<tpush>%p1"
- [(set_attr "length" "<lpush>")]
-)
-
-(define_insn "mov<mode>_regs"
- [(set (match_operand:SISFM 0 "register_operand" "=r, r, r, k")
- (match_operand:SISFM 1 "nonmemory_operand" "r, <iF>, k, r"))]
- ""
- "@
- movd\t%1, %0
- movd\t%1, %0
- mfpr\t%1, %0
- mtpr\t%1, %0"
- [(set_attr "length" "2,6,4,4")]
-)
-
-(define_insn "mov<mode>_regs"
- [(set (match_operand:DIDFM 0 "register_operand" "=r, r, r, k")
- (match_operand:DIDFM 1 "nonmemory_operand" "r, <iF>, k, r"))]
- ""
- {
- switch (which_alternative)
- {
- case 0: if (REGNO (operands[0]) > REGNO (operands[1]))
- return "movd\t%H1, %H0\;movd\t%L1, %L0";
- else
- return "movd\t%L1, %L0\;movd\t%H1, %H0";
- case 1: return "movd\t%H1, %H0\;movd\t%L1, %L0";
- case 2: return "mfpr\t%H1, %H0\;mfpr\t%L1, %L0";
- case 3: return "mtpr\t%H1, %H0\;mtpr\t%L1, %L0";
- default: gcc_unreachable ();
- }
- }
- [(set_attr "length" "4,12,8,8")]
-)
-
-(define_insn "mov<mode>_regs" ; no HI/QI mode in HILO regs
- [(set (match_operand:SHORT 0 "register_operand" "=r, r")
- (match_operand:SHORT 1 "nonmemory_operand" "r, i"))]
- ""
- "mov<tIsa>\t%1, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-(define_insn "mov<mode>_load"
- [(set (match_operand:CRXMM 0 "register_operand" "=r")
- (match_operand:CRXMM 1 "memory_operand" "m"))]
- ""
- "load<tIsa>\t%1, %0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "mov<mode>_load"
- [(set (match_operand:DIDFM 0 "register_operand" "=r")
- (match_operand:DIDFM 1 "memory_operand" "m"))]
- ""
- {
- rtx first_dest_reg = gen_rtx_REG (SImode, REGNO (operands[0]));
- if (reg_overlap_mentioned_p (first_dest_reg, operands[1]))
- return "loadd\t%H1, %H0\;loadd\t%L1, %L0";
- return "loadd\t%L1, %L0\;loadd\t%H1, %H0";
- }
- [(set_attr "length" "12")]
-)
-
-(define_insn "mov<mode>_store"
- [(set (match_operand:CRXMM 0 "store_operand" "=m, m")
- (match_operand:CRXMM 1 "reg_or_u4bits_operand" "r, <JG>"))]
- ""
- "stor<tIsa>\t%1, %0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "mov<mode>_store"
- [(set (match_operand:DIDFM 0 "store_operand" "=m, m")
- (match_operand:DIDFM 1 "reg_or_u4bits_operand" "r, <JG>"))]
- ""
- "stord\t%H1, %H0\;stord\t%L1, %L0"
- [(set_attr "length" "12")]
-)
-
-;; Movmem Instruction
-
-(define_expand "movmemsi"
- [(use (match_operand:BLK 0 "memory_operand" ""))
- (use (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:SI 2 "nonmemory_operand" ""))
- (use (match_operand:SI 3 "const_int_operand" ""))]
- ""
- {
- if (crx_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
- DONE;
- else
- FAIL;
- }
-)
-
-;; Compare and Branch Instructions
-
-(define_insn "cbranchcc4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:CC 1 "cc_reg_operand" "r")
- (match_operand 2 "cst4_operand" "L")])
- (label_ref (match_operand 3 ""))
- (pc)))]
- ""
- "b%d0\t%l3"
- [(set_attr "length" "6")]
-)
-
-(define_insn "cbranch<mode>4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:CRXIM 1 "register_operand" "r")
- (match_operand:CRXIM 2 "reg_or_cst4_operand" "rL")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "cmpb%d0<tIsa>\t%2, %1, %l3"
- [(set_attr "length" "6")]
-)
-
-
-;; Scond Instructions
-
-(define_expand "cstore<mode>4"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:CRXIM 2 "register_operand" "")
- (match_operand:CRXIM 3 "nonmemory_operand" "")))
- (set (match_operand:SI 0 "register_operand")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(reg:CC CC_REGNUM) (const_int 0)]))]
- ""
- ""
-)
-
-(define_insn "cmp<mode>_internal"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:CRXIM 0 "register_operand" "r,r")
- (match_operand:CRXIM 1 "nonmemory_operand" "r,i")))]
- ""
- "cmp<tIsa>\t%1, %0"
- [(set_attr "length" "2,<lImmArith>")]
-)
-
-(define_insn "sCOND_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "ordered_comparison_operator"
- [(reg:CC CC_REGNUM) (const_int 0)]))]
- ""
- "s%d1\t%0"
- [(set_attr "length" "2")]
-)
-
-;; Jumps and Branches
-
-(define_insn "indirect_jump_return"
- [(parallel
- [(set (pc)
- (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- "jump\tra"
- [(set_attr "length" "2")]
-)
-
-(define_insn "indirect_jump"
- [(set (pc)
- (match_operand:SI 0 "reg_or_sym_operand" "r,i"))]
- ""
- "@
- jump\t%0
- br\t%a0"
- [(set_attr "length" "2,6")]
-)
-
-(define_insn "interrupt_return"
- [(parallel
- [(unspec_volatile [(const_int 0)] 0)
- (return)])]
- ""
- {
- return crx_prepare_push_pop_string (1);
- }
- [(set_attr "length" "14")]
-)
-
-(define_insn "jump_to_imm"
- [(set (pc)
- (match_operand 0 "immediate_operand" "i"))]
- ""
- "br\t%c0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "br\t%l0"
- [(set_attr "length" "6")]
-)
-
-;; Function Prologue and Epilogue
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- {
- crx_expand_prologue ();
- DONE;
- }
-)
-
-(define_insn "push_for_prologue"
- [(parallel
- [(set (reg:SI SP_REGNUM)
- (minus:SI (reg:SI SP_REGNUM)
- (match_operand:SI 0 "immediate_operand" "i")))])]
- "reload_completed"
- {
- return crx_prepare_push_pop_string (0);
- }
- [(set_attr "length" "4")]
-)
-
-(define_expand "epilogue"
- [(return)]
- ""
- {
- crx_expand_epilogue ();
- DONE;
- }
-)
-
-(define_insn "pop_and_popret_return"
- [(parallel
- [(set (reg:SI SP_REGNUM)
- (plus:SI (reg:SI SP_REGNUM)
- (match_operand:SI 0 "immediate_operand" "i")))
- (use (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- {
- return crx_prepare_push_pop_string (1);
- }
- [(set_attr "length" "4")]
-)
-
-(define_insn "popret_RA_return"
- [(parallel
- [(use (reg:SI RA_REGNUM))
- (return)])
- ]
- "reload_completed"
- "popret\tra"
- [(set_attr "length" "2")]
-)
-
-;; Table Jump
-
-(define_insn "tablejump"
- [(set (pc)
- (match_operand:SI 0 "register_operand" "r"))
- (use (label_ref:SI (match_operand 1 "" "" )))]
- ""
- "jump\t%0"
- [(set_attr "length" "2")]
-)
-
-;; Call Instructions
-
-(define_expand "call"
- [(call (match_operand:QI 0 "memory_operand" "")
- (match_operand 1 "" ""))]
- ""
- {
- emit_call_insn (gen_crx_call (operands[0], operands[1]));
- DONE;
- }
-)
-
-(define_expand "crx_call"
- [(parallel
- [(call (match_operand:QI 0 "memory_operand" "")
- (match_operand 1 "" ""))
- (clobber (reg:SI RA_REGNUM))])]
- ""
- ""
-)
-
-(define_insn "crx_call_insn_branch"
- [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
- (match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "register_operand" "+r"))]
- ""
- "bal\tra, %a0"
- [(set_attr "length" "6")]
-)
-
-(define_insn "crx_call_insn_jump"
- [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
- (match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "register_operand" "+r"))]
- ""
- "jal\t%0"
- [(set_attr "length" "2")]
-)
-
-(define_insn "crx_call_insn_jalid"
- [(call (mem:QI (mem:SI (plus:SI
- (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "register_operand" "r"))))
- (match_operand 2 "" ""))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "jalid\t%0, %1"
- [(set_attr "length" "4")]
-)
-
-;; Call Value Instructions
-
-(define_expand "call_value"
- [(set (match_operand 0 "general_operand" "")
- (call (match_operand:QI 1 "memory_operand" "")
- (match_operand 2 "" "")))]
- ""
- {
- emit_call_insn (gen_crx_call_value (operands[0], operands[1], operands[2]));
- DONE;
- }
-)
-
-(define_expand "crx_call_value"
- [(parallel
- [(set (match_operand 0 "general_operand" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "" "")))
- (clobber (reg:SI RA_REGNUM))])]
- ""
- ""
-)
-
-(define_insn "crx_call_value_insn_branch"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
- (match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "bal\tra, %a1"
- [(set_attr "length" "6")]
-)
-
-(define_insn "crx_call_value_insn_jump"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "register_operand" "+r"))]
- ""
- "jal\t%1"
- [(set_attr "length" "2")]
-)
-
-(define_insn "crx_call_value_insn_jalid"
- [(set (match_operand 0 "" "=g")
- (call (mem:QI (mem:SI (plus:SI
- (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "register_operand" "r"))))
- (match_operand 3 "" "")))
- (clobber (match_operand:SI 4 "register_operand" "+r"))]
- ""
- "jalid\t%0, %1"
- [(set_attr "length" "4")]
-)
-
-;; Nop
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- ""
-)
-
-;; Multiply and Accumulate Instructions
-
-(define_insn "<sPat>madsidi3"
- [(set (match_operand:DI 0 "register_operand" "+k")
- (plus:DI
- (mult:DI (sz_xtnd:DI (match_operand:SI 1 "register_operand" "%r"))
- (sz_xtnd:DI (match_operand:SI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>d\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sPat>madhisi3"
- [(set (match_operand:SI 0 "register_operand" "+l")
- (plus:SI
- (mult:SI (sz_xtnd:SI (match_operand:HI 1 "register_operand" "%r"))
- (sz_xtnd:SI (match_operand:HI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>w\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-(define_insn "<sPat>madqihi3"
- [(set (match_operand:HI 0 "register_operand" "+l")
- (plus:HI
- (mult:HI (sz_xtnd:HI (match_operand:QI 1 "register_operand" "%r"))
- (sz_xtnd:HI (match_operand:QI 2 "register_operand" "r")))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_MAC"
- "mac<sPat>b\t%2, %1"
- [(set_attr "length" "4")]
-)
-
-;; Loop Instructions
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- ""
- {
- if (INTVAL (operands[3]) > crx_loop_nesting)
- FAIL;
- switch (GET_MODE (operands[0]))
- {
- case SImode:
- emit_jump_insn (gen_doloop_end_si (operands[4], operands[0]));
- break;
- case HImode:
- emit_jump_insn (gen_doloop_end_hi (operands[4], operands[0]));
- break;
- case QImode:
- emit_jump_insn (gen_doloop_end_qi (operands[4], operands[0]));
- break;
- default:
- FAIL;
- }
- DONE;
- }
-)
-
-; CRX dbnz[bwd] used explicitly (see above) but also by the combiner.
-
-(define_insn "doloop_end_<mode>"
- [(set (pc)
- (if_then_else (ne (match_operand:CRXIM 1 "register_operand" "+r,!m")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_dup 1) (plus:CRXIM (match_dup 1) (const_int -1)))
- (clobber (match_scratch:CRXIM 2 "=X,r"))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- dbnz<tIsa>\t%1, %l0
- load<tIsa>\t%1, %2\;add<tIsa>\t$-1, %2\;stor<tIsa>\t%2, %1\;bne\t%l0"
- [(set_attr "length" "6, 12")]
-)
diff --git a/gcc/config/crx/crx.opt b/gcc/config/crx/crx.opt
deleted file mode 100644
index 7ff0be0e3a9..00000000000
--- a/gcc/config/crx/crx.opt
+++ /dev/null
@@ -1,34 +0,0 @@
-; Options for the National Semiconductor CRX port of the compiler.
-
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-mmac
-Target Report Mask(MAC)
-Support multiply accumulate instructions
-
-mno-push-args
-Target Report RejectNegative Mask(NO_PUSH_ARGS)
-Do not use push to store function arguments
-
-mloop-nesting=
-Common RejectNegative Joined UInteger Var(crx_loop_nesting) Init(12)
-Restrict doloop to the given nesting level
-
-mdebug-addr
-Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
diff --git a/gcc/config/crx/t-crx b/gcc/config/crx/t-crx
deleted file mode 100644
index 8bb62c6525f..00000000000
--- a/gcc/config/crx/t-crx
+++ /dev/null
@@ -1,37 +0,0 @@
-# CRX Target Makefile
-#
-# Copyright (C) 2005 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Mingw specific compilation fixes
-USE_COLLECT2 =
-STMP_FIXINC =
-
-# Software emulation for integer div and mod
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmodsi4.c $(srcdir)/config/udivmod.c $(srcdir)/config/divmod.c
-
-# Build the floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- cat $(srcdir)/config/fp-bit.c > dp-bit.c
diff --git a/gcc/config/i386/netbsd.h b/gcc/config/i386/netbsd.h
deleted file mode 100644
index 318951a770a..00000000000
--- a/gcc/config/i386/netbsd.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2004 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- } \
- while (0)
-
-#define TARGET_VERSION fprintf (stderr, " (NetBSD/i386 a.out)");
-
-/* This goes away when the math-emulator is fixed */
-#undef TARGET_SUBTARGET_DEFAULT
-#define TARGET_SUBTARGET_DEFAULT \
- (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
-
-#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "netbsd_cpp_spec", NETBSD_CPP_SPEC },
-
-#undef CPP_SPEC
-#define CPP_SPEC "%(netbsd_cpp_spec)"
-
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-
-/* Don't default to pcc-struct-return, because gcc is the only compiler, and
- we want to retain compatibility with older gcc versions. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-/* i386 netbsd still uses old binutils that don't insert nops by default
- when the .align directive demands to insert extra space in the text
- segment. */
-#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG))
-
-/* Profiling routines, partially copied from i386/osfrose.h. */
-
-/* Redefine this to use %eax instead of %edx. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-{ \
- if (flag_pic) \
- { \
- fprintf (FILE, "\tcall mcount@PLT\n"); \
- } \
- else \
- { \
- fprintf (FILE, "\tcall mcount\n"); \
- } \
-}
-
-/* Until they use ELF or something that handles dwarf2 unwinds
- and initialization stuff better. */
-#define DWARF2_UNWIND_INFO 0
-
-/* Redefine this so that it becomes "_GLOBAL_OFFSET_TABLE_" when the label
- prefix is added. */
-#undef GOT_SYMBOL_NAME
-#define GOT_SYMBOL_NAME "GLOBAL_OFFSET_TABLE_"
-
-/* Attempt to enable execute permissions on the stack. */
-#define ENABLE_EXECUTE_STACK NETBSD_ENABLE_EXECUTE_STACK
diff --git a/gcc/config/m68hc11/larith.asm b/gcc/config/m68hc11/larith.asm
deleted file mode 100644
index 09f946cbf90..00000000000
--- a/gcc/config/m68hc11/larith.asm
+++ /dev/null
@@ -1,1333 +0,0 @@
-/* libgcc routines for M68HC11 & M68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2008, 2009
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifdef __HAVE_SHORT_INT__
- .mode mshort
-#else
- .mode mlong
-#endif
-
- .macro declare_near name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
-\name:
- .endm
-
-#if defined(__USE_RTC__)
-# define ARG(N) N+1
-
- .macro ret
-#if defined(mc68hc12)
- rtc
-#else
- jmp __return_32
-#endif
- .endm
-
- .macro declare name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
- .far \name
-\name:
- .endm
-
- .macro farsym name
- .far NAME
- .endm
-
-#else
-# define ARG(N) N
-
- .macro ret
- rts
- .endm
-
- .macro farsym name
- .endm
-
- .macro declare name
- .globl \name
- .type \name,@function
- .size \name,.Lend-\name
-\name:
- .endm
-
-#endif
-
- .sect .text
-
-
-#define REG(NAME) \
-NAME: .dc.w 1; \
- .type NAME,@object ; \
- .size NAME,2
-
-#ifdef L_regs_min
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
-
- .sect .softregs
- .globl _.tmp
- .globl _.z,_.xy
-REG(_.tmp)
-REG(_.z)
-REG(_.xy)
-
-#endif
-
-#ifdef L_regs_frame
- .sect .softregs
- .globl _.frame
-REG(_.frame)
-#endif
-
-#ifdef L_regs_d1_2
- .sect .softregs
- .globl _.d1,_.d2
-REG(_.d1)
-REG(_.d2)
-#endif
-
-#ifdef L_regs_d3_4
- .sect .softregs
- .globl _.d3,_.d4
-REG(_.d3)
-REG(_.d4)
-#endif
-
-#ifdef L_regs_d5_6
- .sect .softregs
- .globl _.d5,_.d6
-REG(_.d5)
-REG(_.d6)
-#endif
-
-#ifdef L_regs_d7_8
- .sect .softregs
- .globl _.d7,_.d8
-REG(_.d7)
-REG(_.d8)
-#endif
-
-#ifdef L_regs_d9_16
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
- .sect .softregs
- .globl _.d9,_.d10,_.d11,_.d12,_.d13,_.d14
- .globl _.d15,_.d16
-REG(_.d9)
-REG(_.d10)
-REG(_.d11)
-REG(_.d12)
-REG(_.d13)
-REG(_.d14)
-REG(_.d15)
-REG(_.d16)
-
-#endif
-
-#ifdef L_regs_d17_32
-/* Pseudo hard registers used by gcc.
- They should be located in page0. */
- .sect .softregs
- .globl _.d17,_.d18,_.d19,_.d20,_.d21,_.d22
- .globl _.d23,_.d24,_.d25,_.d26,_.d27,_.d28
- .globl _.d29,_.d30,_.d31,_.d32
-REG(_.d17)
-REG(_.d18)
-REG(_.d19)
-REG(_.d20)
-REG(_.d21)
-REG(_.d22)
-REG(_.d23)
-REG(_.d24)
-REG(_.d25)
-REG(_.d26)
-REG(_.d27)
-REG(_.d28)
-REG(_.d29)
-REG(_.d30)
-REG(_.d31)
-REG(_.d32)
-#endif
-
-#ifdef L_premain
-;;
-;; Specific initialization for 68hc11 before the main.
-;; Nothing special for a generic routine; Just enable interrupts.
-;;
- declare_near __premain
- clra
- tap ; Clear both I and X.
- rts
-#endif
-
-#ifdef L__exit
-;;
-;; Exit operation. Just loop forever and wait for interrupts.
-;; (no other place to go)
-;; This operation is split in several pieces collected together by
-;; the linker script. This allows to support destructors at the
-;; exit stage while not impacting program sizes when there is no
-;; destructors.
-;;
-;; _exit:
-;; *(.fini0) /* Beginning of finish code (_exit symbol). */
-;; *(.fini1) /* Place holder for applications. */
-;; *(.fini2) /* C++ destructors. */
-;; *(.fini3) /* Place holder for applications. */
-;; *(.fini4) /* Runtime exit. */
-;;
- .sect .fini0,"ax",@progbits
- .globl _exit
- .globl exit
- .weak exit
- farsym exit
- farsym _exit
-exit:
-_exit:
-
- .sect .fini4,"ax",@progbits
-fatal:
- cli
- wai
- bra fatal
-#endif
-
-#ifdef L_abort
-;;
-;; Abort operation. This is defined for the GCC testsuite.
-;;
- declare abort
-
- ldd #255 ;
-#ifdef mc68hc12
- trap #0x30
-#else
- .byte 0xCD ; Generate an illegal instruction trap
- .byte 0x03 ; The simulator catches this and stops.
-#endif
- jmp _exit
-#endif
-
-#ifdef L_cleanup
-;;
-;; Cleanup operation used by exit().
-;;
- declare _cleanup
-
- ret
-#endif
-
-;-----------------------------------------
-; required gcclib code
-;-----------------------------------------
-#ifdef L_memcpy
- declare memcpy
- declare __memcpy
-
- .weak memcpy
-;;;
-;;; void* memcpy(void*, const void*, size_t)
-;;;
-;;; D = dst Pmode
-;;; 2,sp = src Pmode
-;;; 4,sp = size HImode (size_t)
-;;;
-#ifdef mc68hc12
- ldx ARG(2),sp
- ldy ARG(4),sp
- pshd
- xgdy
- lsrd
- bcc Start
- movb 1,x+,1,y+
-Start:
- beq Done
-Loop:
- movw 2,x+,2,y+
- dbne d,Loop
-Done:
- puld
- ret
-#else
- xgdy
- tsx
- ldd ARG(4),x
- ldx ARG(2),x ; SRC = X, DST = Y
- cpd #0
- beq End
- pshy
- inca ; Correction for the deca below
-L0:
- psha ; Save high-counter part
-L1:
- ldaa 0,x ; Copy up to 256 bytes
- staa 0,y
- inx
- iny
- decb
- bne L1
- pula
- deca
- bne L0
- puly ; Restore Y to return the DST
-End:
- xgdy
- ret
-#endif
-#endif
-
-#ifdef L_memset
- declare memset
- declare __memset
-;;;
-;;; void* memset(void*, int value, size_t)
-;;;
-#ifndef __HAVE_SHORT_INT__
-;;; D = dst Pmode
-;;; 2,sp = src SImode
-;;; 6,sp = size HImode (size_t)
- val = ARG(5)
- size = ARG(6)
-#else
-;;; D = dst Pmode
-;;; 2,sp = src SImode
-;;; 6,sp = size HImode (size_t)
- val = ARG(3)
- size = ARG(4)
-#endif
-#ifdef mc68hc12
- xgdx
- ldab val,sp
- ldy size,sp
- pshx
- beq End
-Loop:
- stab 1,x+
- dbne y,Loop
-End:
- puld
- ret
-#else
- xgdx
- tsy
- ldab val,y
- ldy size,y ; DST = X, CNT = Y
- beq End
- pshx
-L0:
- stab 0,x ; Fill up to 256 bytes
- inx
- dey
- bne L0
- pulx ; Restore X to return the DST
-End:
- xgdx
- ret
-#endif
-#endif
-
-#ifdef L_adddi3
- declare ___adddi3
-
- tsx
- xgdy
- ldd ARG(8),x ; Add LSB
- addd ARG(16),x
- std 6,y ; Save (carry preserved)
-
- ldd ARG(6),x
- adcb ARG(15),x
- adca ARG(14),x
- std 4,y
-
- ldd ARG(4),x
- adcb ARG(13),x
- adca ARG(12),x
- std 2,y
-
- ldd ARG(2),x
- adcb ARG(11),x ; Add MSB
- adca ARG(10),x
- std 0,y
-
- xgdy
- ret
-#endif
-
-#ifdef L_subdi3
- declare ___subdi3
-
- tsx
- xgdy
- ldd ARG(8),x ; Subtract LSB
- subd ARG(16),x
- std 6,y ; Save, borrow preserved
-
- ldd ARG(6),x
- sbcb ARG(15),x
- sbca ARG(14),x
- std 4,y
-
- ldd ARG(4),x
- sbcb ARG(13),x
- sbca ARG(12),x
- std 2,y
-
- ldd ARG(2),x ; Subtract MSB
- sbcb ARG(11),x
- sbca ARG(10),x
- std 0,y
-
- xgdy ;
- ret
-#endif
-
-#ifdef L_notdi2
- declare ___notdi2
-
- tsy
- xgdx
- ldd ARG(8),y
- coma
- comb
- std 6,x
-
- ldd ARG(6),y
- coma
- comb
- std 4,x
-
- ldd ARG(4),y
- coma
- comb
- std 2,x
-
- ldd ARG(2),y
- coma
- comb
- std 0,x
- xgdx
- ret
-#endif
-
-#ifdef L_negsi2
- declare_near ___negsi2
-
- comb
- coma
- xgdx
- comb
- coma
- inx
- xgdx
- bne done
- inx
-done:
- rts
-#endif
-
-#ifdef L_one_cmplsi2
- declare_near ___one_cmplsi2
-
- comb
- coma
- xgdx
- comb
- coma
- xgdx
- rts
-#endif
-
-#ifdef L_ashlsi3
- declare_near ___ashlsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- lsld
- xgdx
- rolb
- rola
- xgdx
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_ashrsi3
- declare_near ___ashrsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- xgdx
- asra
- rorb
- xgdx
- rora
- rorb
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_lshrsi3
- declare_near ___lshrsi3
-
- xgdy
- clra
- andb #0x1f
- xgdy
- beq Return
-Loop:
- xgdx
- lsrd
- xgdx
- rora
- rorb
- dey
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_lshrhi3
- declare_near ___lshrhi3
-
- cpx #16
- bge Return_zero
- cpx #0
- beq Return
-Loop:
- lsrd
- dex
- bne Loop
-Return:
- rts
-Return_zero:
- clra
- clrb
- rts
-#endif
-
-#ifdef L_lshlhi3
- declare_near ___lshlhi3
-
- cpx #16
- bge Return_zero
- cpx #0
- beq Return
-Loop:
- lsld
- dex
- bne Loop
-Return:
- rts
-Return_zero:
- clra
- clrb
- rts
-#endif
-
-#ifdef L_rotrhi3
- declare_near ___rotrhi3
-
-___rotrhi3:
- xgdx
- clra
- andb #0x0f
- xgdx
- beq Return
-Loop:
- tap
- rorb
- rora
- dex
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_rotlhi3
- declare_near ___rotlhi3
-
-___rotlhi3:
- xgdx
- clra
- andb #0x0f
- xgdx
- beq Return
-Loop:
- asrb
- rolb
- rola
- rolb
- dex
- bne Loop
-Return:
- rts
-#endif
-
-#ifdef L_ashrhi3
- declare_near ___ashrhi3
-
- cpx #16
- bge Return_minus_1_or_zero
- cpx #0
- beq Return
-Loop:
- asra
- rorb
- dex
- bne Loop
-Return:
- rts
-Return_minus_1_or_zero:
- clrb
- tsta
- bpl Return_zero
- comb
-Return_zero:
- tba
- rts
-#endif
-
-#ifdef L_ashrqi3
- declare_near ___ashrqi3
-
- cmpa #8
- bge Return_minus_1_or_zero
- tsta
- beq Return
-Loop:
- asrb
- deca
- bne Loop
-Return:
- rts
-Return_minus_1_or_zero:
- clrb
- tstb
- bpl Return_zero
- coma
-Return_zero:
- tab
- rts
-#endif
-
-#ifdef L_lshlqi3
- declare_near ___lshlqi3
-
- cmpa #8
- bge Return_zero
- tsta
- beq Return
-Loop:
- lslb
- deca
- bne Loop
-Return:
- rts
-Return_zero:
- clrb
- rts
-#endif
-
-#ifdef L_divmodhi4
-#ifndef mc68hc12
-/* 68HC12 signed divisions are generated inline (idivs). */
-
- declare_near __divmodhi4
-
-;
-;; D = numerator
-;; X = denominator
-;;
-;; Result: D = D / X
-;; X = D % X
-;;
- tsta
- bpl Numerator_pos
- comb ; D = -D <=> D = (~D) + 1
- coma
- xgdx
- inx
- tsta
- bpl Numerator_neg_denominator_pos
-Numerator_neg_denominator_neg:
- comb ; X = -X
- coma
- addd #1
- xgdx
- idiv
- coma
- comb
- xgdx ; Remainder <= 0 and result >= 0
- inx
- rts
-
-Numerator_pos_denominator_pos:
- xgdx
- idiv
- xgdx ; Both values are >= 0
- rts
-
-Numerator_pos:
- xgdx
- tsta
- bpl Numerator_pos_denominator_pos
-Numerator_pos_denominator_neg:
- coma ; X = -X
- comb
- xgdx
- inx
- idiv
- xgdx ; Remainder >= 0 but result <= 0
- coma
- comb
- addd #1
- rts
-
-Numerator_neg_denominator_pos:
- xgdx
- idiv
- coma ; One value is > 0 and the other < 0
- comb ; Change the sign of result and remainder
- xgdx
- inx
- coma
- comb
- addd #1
- rts
-#endif /* !mc68hc12 */
-#endif
-
-#ifdef L_mulqi3
- declare_near ___mulqi3
-
-;
-; short __mulqi3(signed char a, signed char b);
-;
-; signed char a -> register A
-; signed char b -> register B
-;
-; returns the signed result of A * B in register D.
-;
- tsta
- bmi A_neg
- tstb
- bmi B_neg
- mul
- rts
-B_neg:
- negb
- bra A_or_B_neg
-A_neg:
- nega
- tstb
- bmi AB_neg
-A_or_B_neg:
- mul
- coma
- comb
- addd #1
- rts
-AB_neg:
- negb
- mul
- rts
-#endif
-
-#ifdef L_mulhi3
- declare_near ___mulhi3
-
-;
-;
-; unsigned short ___mulhi3(unsigned short a, unsigned short b)
-;
-; a = register D
-; b = register X
-;
-#ifdef mc68hc12
- pshx ; Preserve X
- exg x,y
- emul
- exg x,y
- pulx
- rts
-#else
-#ifdef NO_TMP
- ;
- ; 16-bit multiplication without temp memory location.
- ; (smaller but slower)
- ;
- pshx ; (4)
- ins ; (3)
- pshb ; (3)
- psha ; (3)
- pshx ; (4)
- pula ; (4)
- pulx ; (5)
- mul ; (10) B.high * A.low
- xgdx ; (3)
- mul ; (10) B.low * A.high
- abx ; (3)
- pula ; (4)
- pulb ; (4)
- mul ; (10) B.low * A.low
- pshx ; (4)
- tsx ; (3)
- adda 1,x ; (4)
- pulx ; (5)
- rts ; (5) 20 bytes
- ; ---
- ; 91 cycles
-#else
- stx *_.tmp ; (4)
- pshb ; (3)
- ldab *_.tmp+1 ; (3)
- mul ; (10) A.high * B.low
- ldaa *_.tmp ; (3)
- stab *_.tmp ; (3)
- pulb ; (4)
- pshb ; (4)
- mul ; (10) A.low * B.high
- addb *_.tmp ; (4)
- stab *_.tmp ; (3)
- ldaa *_.tmp+1 ; (3)
- pulb ; (4)
- mul ; (10) A.low * B.low
- adda *_.tmp ; (4)
- rts ; (5) 24/32 bytes
- ; 77/85 cycles
-#endif
-#endif
-#endif
-
-#ifdef L_mulhi32
-
-;
-;
-; unsigned long __mulhi32(unsigned short a, unsigned short b)
-;
-; a = register D
-; b = value on stack
-;
-; +---------------+
-; | B low | <- 7,x
-; +---------------+
-; | B high | <- 6,x
-; +---------------+
-; | PC low |
-; +---------------+
-; | PC high |
-; +---------------+
-; | Tmp low |
-; +---------------+
-; | Tmp high |
-; +---------------+
-; | A low |
-; +---------------+
-; | A high |
-; +---------------+ <- 0,x
-;
-;
-; <B-low> 5,x
-; <B-high> 4,x
-; <ret> 2,x
-; <A-low> 1,x
-; <A-high> 0,x
-;
- declare_near __mulhi32
-
-#ifdef mc68hc12
- ldy 2,sp
- emul
- exg x,y
- rts
-#else
- pshx ; Room for temp value
- pshb
- psha
- tsx
- ldab 6,x
- mul
- xgdy ; A.high * B.high
- ldab 7,x
- pula
- mul ; A.high * B.low
- std 2,x
- ldaa 1,x
- ldab 6,x
- mul ; A.low * B.high
- addd 2,x
- stab 2,x
- tab
- aby
- bcc N
- ldab #0xff
- aby
- iny
-N:
- ldab 7,x
- pula
- mul ; A.low * B.low
- adda 2,x
- pulx ; Drop temp location
- pshy ; Put high part in X
- pulx
- bcc Ret
- inx
-Ret:
- rts
-#endif
-#endif
-
-#ifdef L_mulsi3
-
-;
-; <B-low> 8,y
-; <B-high> 6,y
-; <ret> 4,y
-; <tmp> 2,y
-; <A-low> 0,y
-;
-; D,X -> A
-; Stack -> B
-;
-; The result is:
-;
-; (((A.low * B.high) + (A.high * B.low)) << 16) + (A.low * B.low)
-;
-;
-;
-
- declare __mulsi3
-
-#ifdef mc68hc12
- pshd ; Save A.low
- ldy ARG(4),sp
- emul ; A.low * B.high
- ldy ARG(6),sp
- exg x,d
- emul ; A.high * B.low
- leax d,x
- ldy ARG(6),sp
- puld
- emul ; A.low * B.low
- exg d,y
- leax d,x
- exg d,y
- ret
-#else
-B_low = ARG(8)
-B_high = ARG(6)
-A_low = 0
-A_high = 2
- pshx
- pshb
- psha
- tsy
-;
-; If B.low is 0, optimize into: (A.low * B.high) << 16
-;
- ldd B_low,y
- beq B_low_zero
-;
-; If A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
-;
- cpx #0
- beq A_high_zero
- bsr ___mulhi3 ; A.high * B.low
-;
-; If A.low is 0, optimize into: (A.high * B.low) << 16
-;
- ldx A_low,y
- beq A_low_zero ; X = 0, D = A.high * B.low
- std 2,y
-;
-; If B.high is 0, we can avoid the (A.low * B.high) << 16 term.
-;
- ldd B_high,y
- beq B_high_zero
- bsr ___mulhi3 ; A.low * B.high
- addd 2,y
- std 2,y
-;
-; Here, we know that A.low and B.low are not 0.
-;
-B_high_zero:
- ldd B_low,y ; A.low is on the stack
- bsr __mulhi32 ; A.low * B.low
- xgdx
- tsy ; Y was clobbered, get it back
- addd 2,y
-A_low_zero: ; See A_low_zero_non_optimized below
- xgdx
-Return:
- ins
- ins
- ins
- ins
- ret
-;
-;
-; A_low_zero_non_optimized:
-;
-; At this step, X = 0 and D = (A.high * B.low)
-; Optimize into: (A.high * B.low) << 16
-;
-; xgdx
-; clra ; Since X was 0, clearing D is superfuous.
-; clrb
-; bra Return
-; ----------------
-; B.low == 0, the result is: (A.low * B.high) << 16
-;
-; At this step:
-; D = B.low = 0
-; X = A.high ?
-; A.low is at A_low,y ?
-; B.low is at B_low,y ?
-;
-B_low_zero:
- ldd A_low,y
- beq Zero1
- ldx B_high,y
- beq Zero2
- bsr ___mulhi3
-Zero1:
- xgdx
-Zero2:
- clra
- clrb
- bra Return
-; ----------------
-; A.high is 0, optimize into: (A.low * B.high) << 16 + (A.low * B.low)
-;
-; At this step:
-; D = B.low != 0
-; X = A.high = 0
-; A.low is at A_low,y ?
-; B.low is at B_low,y ?
-;
-A_high_zero:
- ldd A_low,y ; A.low
- beq Zero1
- ldx B_high,y ; B.high
- beq A_low_B_low
- bsr ___mulhi3
- std 2,y
- bra B_high_zero ; Do the (A.low * B.low) and the add.
-
-; ----------------
-; A.high and B.high are 0 optimize into: (A.low * B.low)
-;
-; At this step:
-; D = B.high = 0
-; X = A.low != 0
-; A.low is at A_low,y != 0
-; B.high is at B_high,y = 0
-;
-A_low_B_low:
- ldd B_low,y ; A.low is on the stack
- bsr __mulhi32
- bra Return
-#endif
-#endif
-
-#ifdef L_map_data
-
- .sect .install2,"ax",@progbits
- .globl __map_data_section
- .globl __data_image
-#ifdef mc68hc12
- .globl __data_section_size
-#endif
-__map_data_section:
-#ifdef mc68hc12
- ldx #__data_image
- ldy #__data_section_start
- ldd #__data_section_size
- beq Done
-Loop:
- movb 1,x+,1,y+
- dbne d,Loop
-#else
- ldx #__data_image
- ldy #__data_section_start
- bra Start_map
-Loop:
- ldaa 0,x
- staa 0,y
- inx
- iny
-Start_map:
- cpx #__data_image_end
- blo Loop
-#endif
-Done:
-
-#endif
-
-#ifdef L_init_bss
-
- .sect .install2,"ax",@progbits
- .globl __init_bss_section
-
-__init_bss_section:
- ldd #__bss_size
- beq Done
- ldx #__bss_start
-Loop:
-#ifdef mc68hc12
- clr 1,x+
- dbne d,Loop
-#else
- clr 0,x
- inx
- subd #1
- bne Loop
-#endif
-Done:
-
-#endif
-
-#ifdef L_ctor
-
-; End of constructor table
- .sect .install3,"ax",@progbits
- .globl __do_global_ctors
-
-__do_global_ctors:
- ; Start from the end - sizeof(void*)
- ldx #__CTOR_END__-2
-ctors_loop:
- cpx #__CTOR_LIST__
- blo ctors_done
- pshx
- ldx 0,x
- jsr 0,x
- pulx
- dex
- dex
- bra ctors_loop
-ctors_done:
-
-#endif
-
-#ifdef L_dtor
-
- .sect .fini3,"ax",@progbits
- .globl __do_global_dtors
-
-;;
-;; This piece of code is inserted in the _exit() code by the linker.
-;;
-__do_global_dtors:
- pshb ; Save exit code
- psha
- ldx #__DTOR_LIST__
-dtors_loop:
- cpx #__DTOR_END__
- bhs dtors_done
- pshx
- ldx 0,x
- jsr 0,x
- pulx
- inx
- inx
- bra dtors_loop
-dtors_done:
- pula ; Restore exit code
- pulb
-
-#endif
-
-#ifdef L_far_tramp
-#ifdef mc68hc12
- .sect .tramp,"ax",@progbits
- .globl __far_trampoline
-
-;; This is a trampoline used by the linker to invoke a function
-;; using rtc to return and being called with jsr/bsr.
-;; The trampoline generated is:
-;;
-;; foo_tramp:
-;; ldy #foo
-;; call __far_trampoline,page(foo)
-;;
-;; The linker transforms:
-;;
-;; jsr foo
-;;
-;; into
-;; jsr foo_tramp
-;;
-;; The linker generated trampoline and _far_trampoline must be in
-;; non-banked memory.
-;;
-__far_trampoline:
- movb 0,sp, 2,sp ; Copy page register below the caller's return
- leas 2,sp ; address.
- jmp 0,y ; We have a 'call/rtc' stack layout now
- ; and can jump to the far handler
- ; (whose memory bank is mapped due to the
- ; call to the trampoline).
-#endif
-
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __far_trampoline
-
-;; Trampoline generated by gcc for 68HC11:
-;;
-;; pshb
-;; ldab #%page(func)
-;; ldy #%addr(func)
-;; jmp __far_trampoline
-;;
-__far_trampoline:
- psha ; (2) Save function parameter (high)
- ;; <Read current page in A>
- psha ; (2)
- ;; <Set currenge page from B>
- pshx ; (4)
- tsx ; (3)
- ldab 4,x ; (4) Restore function parameter (low)
- ldaa 2,x ; (4) Get saved page number
- staa 4,x ; (4) Save it below return PC
- pulx ; (5)
- pula ; (3)
- pula ; (3) Restore function parameter (high)
- jmp 0,y ; (4)
-#endif
-#endif
-
-#ifdef L_call_far
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __call_a16
- .globl __call_a32
-;;
-;; The call methods are used for 68HC11 to support memory bank switching.
-;; Every far call is redirected to these call methods. Its purpose is to:
-;;
-;; 1/ Save the current page on the stack (1 byte to follow 68HC12 call frame)
-;; 2/ Install the new page
-;; 3/ Jump to the real function
-;;
-;; The page switching (get/save) is board dependent. The default provided
-;; here does nothing (just create the appropriate call frame).
-;;
-;; Call sequence (10 bytes, 13 cycles):
-;;
-;; ldx #page ; (3)
-;; ldy #func ; (4)
-;; jsr __call_a16 ; (6)
-;;
-;; Call trampoline (11 bytes, 19 cycles):
-;;
-__call_a16:
- ;; xgdx ; (3)
- ;; <Read current page in A> ; (3) ldaa _current_page
- psha ; (2)
- ;; <Set current page from B> ; (4) staa _current_page
- ;; xgdx ; (3)
- jmp 0,y ; (4)
-
-;;
-;; Call sequence (10 bytes, 14 cycles):
-;;
-;; pshb ; (2)
-;; ldab #page ; (2)
-;; ldy #func ; (4)
-;; jsr __call_a32 ; (6)
-;;
-;; Call trampoline (87 bytes, 57 cycles):
-;;
-__call_a32:
- pshx ; (4)
- psha ; (2)
- ;; <Read current page in A> ; (3) ldaa _current_page
- psha ; (2)
- ;; <Set current page from B> ; (4) staa _current_page
- tsx ; (3)
- ldab 6,x ; (4) Restore function parameter
- ldaa 5,x ; (4) Move PC return at good place
- staa 6,x ; (4)
- ldaa 4,x ; (4)
- staa 5,x ; (4)
- pula ; (3)
- staa 4,x ; (4)
- pula ; (3)
- pulx ; (5)
- jmp 0,y ; (4)
-#endif
-#endif
-
-#ifdef L_return_far
-#ifdef mc68hc11
- .sect .tramp,"ax",@progbits
- .globl __return_void
- .globl __return_16
- .globl __return_32
-
-__return_void:
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; rts
-__return_16:
- ;; xgdx
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; xgdx
- ;; rts
-__return_32:
- ;; xgdy
- ;; pulb
- ;; <Set current page from B> (Board specific)
- ;; xgdy
- ;; rts
- ins
- rts
-#endif
-#endif
-.Lend:
-;-----------------------------------------
-; end required gcclib code
-;-----------------------------------------
diff --git a/gcc/config/m68hc11/m68hc11-crt0.S b/gcc/config/m68hc11/m68hc11-crt0.S
deleted file mode 100644
index 429ab0f270d..00000000000
--- a/gcc/config/m68hc11/m68hc11-crt0.S
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Startup code for M68HC11.
- Copyright (C) 1999, 2000, 2002, 2008, 2009 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-;-----------------------------------------
-; startup code
-;-----------------------------------------
-
-#ifdef __HAVE_SHORT_INT__
- .mode mshort
-#else
- .mode mlong
-#endif
-
-#if defined(__USE_RTC__) && defined(mc68hc12)
- .macro jsr name
- call \name
- .endm
-#endif
-;;
-;;
-;; The linker concatenate the .install* sections in the following order:
-;;
-;; .install0 Setup the stack pointer
-;; .install1 Place holder for applications
-;; .install2 Optional installation of data section in memory
-;; .install3 Place holder for applications
-;; .install4 Invokes the main
-;;
- .sect .install0,"ax",@progbits
- .globl _start
-
-_start:
-;;
-;; At this step, the stack is not initialized and interrupts are masked.
-;; Applications only have 64 cycles to initialize some registers.
-;;
-;; To have a generic/configurable startup, initialize the stack to
-;; the end of some memory region. The _stack symbol is defined by
-;; the linker.
-;;
- lds #_stack
-
- .sect .install2,"ax",@progbits
-;;
-;; Call a specific initialization operation. The default is empty.
-;; It can be overridden by applications. It is intended to initialize
-;; the 68hc11 registers. Function prototype is:
-;;
-;; int __premain(void);
-;;
- jsr __premain
-
-;;
-;;
-;;
- .sect .install4,"ax",@progbits
- jsr main
-fatal:
- jsr exit
- bra fatal
-
-;-----------------------------------------
-; end startup code
-;-----------------------------------------
-;; Force loading of data section mapping and bss clear
- .2byte __map_data_section
- .2byte __init_bss_section
diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h
deleted file mode 100644
index 76b6659379e..00000000000
--- a/gcc/config/m68hc11/m68hc11-protos.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* Prototypes for exported functions defined in m68hc11.c
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-extern int hard_regno_mode_ok (int, enum machine_mode);
-extern int m68hc11_hard_regno_rename_ok (int, int);
-
-extern int m68hc11_total_frame_size (void);
-extern int m68hc11_initial_frame_pointer_offset (void);
-extern int m68hc11_initial_elimination_offset (int, int);
-
-extern void expand_prologue (void);
-extern void expand_epilogue (void);
-
-#ifdef RTX_CODE
-extern int m68hc11_auto_inc_p (rtx);
-
-extern rtx m68hc11_expand_compare_and_branch (enum rtx_code, rtx, rtx, rtx);
-extern enum reg_class preferred_reload_class (rtx, enum reg_class);
-
-extern void m68hc11_notice_update_cc (rtx, rtx);
-extern void m68hc11_notice_keep_cc (rtx);
-
-extern void m68hc11_gen_movqi (rtx, rtx*);
-extern void m68hc11_gen_movhi (rtx, rtx*);
-extern void m68hc11_gen_rotate (enum rtx_code, rtx, rtx*);
-
-extern void m68hc11_output_swap (rtx, rtx*);
-
-extern int next_insn_test_reg (rtx, rtx);
-
-extern int m68hc11_reload_operands (rtx*);
-
-extern int dead_register_here (rtx, rtx);
-
-extern int push_pop_operand_p (rtx);
-extern void m68hc11_split_move (rtx, rtx, rtx);
-extern void m68hc11_split_compare_and_branch (enum rtx_code,
- rtx, rtx, rtx);
-
-extern rtx m68hc11_gen_lowpart (enum machine_mode, rtx);
-extern rtx m68hc11_gen_highpart (enum machine_mode, rtx);
-
-#ifdef HAVE_MACHINE_MODES
-extern int m68hc11_memory_move_cost (enum machine_mode, enum reg_class, int);
-extern int m68hc11_register_move_cost (enum machine_mode,
- enum reg_class, enum reg_class);
-
-extern void m68hc11_emit_libcall (const char*, enum rtx_code,
- enum machine_mode, enum machine_mode,
- int, rtx*);
-extern int m68hc11_small_indexed_indirect_p (rtx, enum machine_mode);
-extern int m68hc11_symbolic_p (rtx, enum machine_mode);
-extern int m68hc11_indirect_p (rtx, enum machine_mode);
-extern int go_if_legitimate_address2 (rtx, enum machine_mode, int);
-
-extern int reg_or_indexed_operand (rtx,enum machine_mode);
-extern int memory_indexed_operand (rtx, enum machine_mode);
-
-#ifdef RTX_CODE
-extern void m68hc11_split_logical (enum machine_mode, enum rtx_code, rtx*);
-#endif
-
-extern int m68hc11_register_indirect_p (rtx, enum machine_mode);
-extern int m68hc11_valid_addressing_p (rtx, enum machine_mode, int);
-
-extern int symbolic_memory_operand (rtx, enum machine_mode);
-
-extern int memory_reload_operand (rtx, enum machine_mode);
-extern int arith_src_operand (rtx, enum machine_mode);
-extern int soft_reg_operand (rtx, enum machine_mode);
-
-extern void m68hc11_init_cumulative_args (CUMULATIVE_ARGS*, tree, rtx);
-
-#ifdef ARGS_SIZE_RTX
-extern enum direction m68hc11_function_arg_padding (enum machine_mode,
- const_tree);
-#endif
-
-extern void m68hc11_function_epilogue (FILE*,int);
-
-extern int m68hc11_is_far_symbol (rtx);
-extern int m68hc11_is_trap_symbol (rtx);
-extern int m68hc11_page0_symbol_p (rtx x);
-
-extern HOST_WIDE_INT m68hc11_min_offset;
-extern HOST_WIDE_INT m68hc11_max_offset;
-extern int m68hc11_addr_mode;
-
-#endif /* HAVE_MACHINE_MODES */
-#endif /* RTX_CODE */
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
deleted file mode 100644
index 1e414102c3f..00000000000
--- a/gcc/config/m68hc11/m68hc11.c
+++ /dev/null
@@ -1,5588 +0,0 @@
-/* Subroutines for code generation on Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009, 2010 Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>.
-
-Note:
- A first 68HC11 port was made by Otto Lind (otto@coactive.com)
- on gcc 2.6.3. I have used it as a starting point for this port.
- However, this new port is a complete re-write. Its internal
- design is completely different. The generated code is not
- compatible with the gcc 2.6.3 port.
-
- The gcc 2.6.3 port is available at:
-
- ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-
-*/
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "recog.h"
-#include "expr.h"
-#include "libfuncs.h"
-#include "diagnostic-core.h"
-#include "basic-block.h"
-#include "function.h"
-#include "ggc.h"
-#include "reload.h"
-#include "target.h"
-#include "target-def.h"
-#include "df.h"
-
-static void m68hc11_option_override (void);
-static void emit_move_after_reload (rtx, rtx, rtx);
-static rtx simplify_logical (enum machine_mode, int, rtx, rtx *);
-static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *);
-static void m68hc11_reorg (void);
-static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool);
-static bool m68hc11_legitimate_address_p (enum machine_mode, rtx, bool);
-static rtx m68hc11_expand_compare (enum rtx_code, rtx, rtx);
-static int must_parenthesize (rtx);
-static int m68hc11_address_cost (rtx, bool);
-static int m68hc11_shift_cost (enum machine_mode, rtx, int);
-static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
-static bool m68hc11_rtx_costs (rtx, int, int, int *, bool);
-static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *);
-static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *);
-static bool m68hc11_class_likely_spilled_p (reg_class_t);
-
-void create_regs_rtx (void);
-
-static void asm_print_register (FILE *, int);
-static void m68hc11_print_operand (FILE *, rtx, int);
-static void m68hc11_print_operand_address (FILE *, rtx);
-static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void m68hc11_asm_out_constructor (rtx, int);
-static void m68hc11_asm_out_destructor (rtx, int);
-static void m68hc11_file_start (void);
-static void m68hc11_encode_section_info (tree, rtx, int);
-static const char *m68hc11_strip_name_encoding (const char* str);
-static unsigned int m68hc11_section_type_flags (tree, const char*, int);
-static int autoinc_mode (rtx);
-static int m68hc11_make_autoinc_notes (rtx *, void *);
-static void m68hc11_init_libfuncs (void);
-static rtx m68hc11_struct_value_rtx (tree, int);
-static bool m68hc11_return_in_memory (const_tree, const_tree);
-static bool m68hc11_can_eliminate (const int, const int);
-static void m68hc11_conditional_register_usage (void);
-static void m68hc11_trampoline_init (rtx, tree, rtx);
-
-static rtx m68hc11_function_arg (CUMULATIVE_ARGS*, enum machine_mode,
- const_tree, bool);
-static void m68hc11_function_arg_advance (CUMULATIVE_ARGS*, enum machine_mode,
- const_tree, bool);
-
-/* Must be set to 1 to produce debug messages. */
-int debug_m6811 = 0;
-
-extern FILE *asm_out_file;
-
-rtx ix_reg;
-rtx iy_reg;
-rtx d_reg;
-rtx m68hc11_soft_tmp_reg;
-static GTY(()) rtx stack_push_word;
-static GTY(()) rtx stack_pop_word;
-static GTY(()) rtx z_reg;
-static GTY(()) rtx z_reg_qi;
-static int regs_inited = 0;
-
-/* Set to 1 by expand_prologue() when the function is an interrupt handler. */
-int current_function_interrupt;
-
-/* Set to 1 by expand_prologue() when the function is a trap handler. */
-int current_function_trap;
-
-/* Set to 1 when the current function is placed in 68HC12 banked
- memory and must return with rtc. */
-int current_function_far;
-
-/* Min offset that is valid for the indirect addressing mode. */
-HOST_WIDE_INT m68hc11_min_offset = 0;
-
-/* Max offset that is valid for the indirect addressing mode. */
-HOST_WIDE_INT m68hc11_max_offset = 256;
-
-/* The class value for base registers. */
-enum reg_class m68hc11_base_reg_class = A_REGS;
-
-/* The class value for index registers. This is NO_REGS for 68HC11. */
-enum reg_class m68hc11_index_reg_class = NO_REGS;
-
-enum reg_class m68hc11_tmp_regs_class = NO_REGS;
-
-/* Tables that tell whether a given hard register is valid for
- a base or an index register. It is filled at init time depending
- on the target processor. */
-unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
-unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
-
-/* A correction offset which is applied to the stack pointer.
- This is 1 for 68HC11 and 0 for 68HC12. */
-int m68hc11_sp_correction;
-
-int m68hc11_addr_mode;
-int m68hc11_mov_addr_mode;
-
-
-const struct processor_costs *m68hc11_cost;
-
-/* Costs for a 68HC11. */
-static const struct processor_costs m6811_cost = {
- /* add */
- COSTS_N_INSNS (2),
- /* logical */
- COSTS_N_INSNS (2),
- /* non-constant shift */
- COSTS_N_INSNS (20),
- /* shiftQI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
- COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
- COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
-
- /* shiftHI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
- COSTS_N_INSNS (4), COSTS_N_INSNS (2),
- COSTS_N_INSNS (2), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (10),
- COSTS_N_INSNS (8), COSTS_N_INSNS (6), COSTS_N_INSNS (4)
- },
- /* mulQI */
- COSTS_N_INSNS (20),
- /* mulHI */
- COSTS_N_INSNS (20 * 4),
- /* mulSI */
- COSTS_N_INSNS (20 * 16),
- /* divQI */
- COSTS_N_INSNS (20),
- /* divHI */
- COSTS_N_INSNS (80),
- /* divSI */
- COSTS_N_INSNS (100)
-};
-
-/* Costs for a 68HC12. */
-static const struct processor_costs m6812_cost = {
- /* add */
- COSTS_N_INSNS (2),
- /* logical */
- COSTS_N_INSNS (2),
- /* non-constant shift */
- COSTS_N_INSNS (20),
- /* shiftQI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (2),
- COSTS_N_INSNS (3), COSTS_N_INSNS (4), COSTS_N_INSNS (3),
- COSTS_N_INSNS (2), COSTS_N_INSNS (1) },
-
- /* shiftHI const */
- { COSTS_N_INSNS (0), COSTS_N_INSNS (1), COSTS_N_INSNS (4),
- COSTS_N_INSNS (6), COSTS_N_INSNS (8), COSTS_N_INSNS (6),
- COSTS_N_INSNS (4), COSTS_N_INSNS (2),
- COSTS_N_INSNS (2), COSTS_N_INSNS (4), COSTS_N_INSNS (6),
- COSTS_N_INSNS (8), COSTS_N_INSNS (10), COSTS_N_INSNS (8),
- COSTS_N_INSNS (6), COSTS_N_INSNS (4)
- },
- /* mulQI */
- COSTS_N_INSNS (3),
- /* mulHI */
- COSTS_N_INSNS (3),
- /* mulSI */
- COSTS_N_INSNS (3 * 4),
- /* divQI */
- COSTS_N_INSNS (12),
- /* divHI */
- COSTS_N_INSNS (12),
- /* divSI */
- COSTS_N_INSNS (100)
-};
-
-/* M68HC11 specific attributes. */
-
-static const struct attribute_spec m68hc11_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "interrupt", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "trap", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "far", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "near", 0, 0, false, true, true, m68hc11_handle_fntype_attribute,
- false },
- { "page0", 0, 0, false, false, false, m68hc11_handle_page0_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
-
-/* Initialize the GCC target structure. */
-#undef TARGET_ATTRIBUTE_TABLE
-#define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table
-
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
-
-#undef TARGET_PRINT_OPERAND
-#define TARGET_PRINT_OPERAND m68hc11_print_operand
-#undef TARGET_PRINT_OPERAND_ADDRESS
-#define TARGET_PRINT_OPERAND_ADDRESS m68hc11_print_operand_address
-
-#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue
-
-#undef TARGET_ASM_FILE_START
-#define TARGET_ASM_FILE_START m68hc11_file_start
-#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-#undef TARGET_DEFAULT_TARGET_FLAGS
-#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO m68hc11_encode_section_info
-
-#undef TARGET_SECTION_TYPE_FLAGS
-#define TARGET_SECTION_TYPE_FLAGS m68hc11_section_type_flags
-
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS m68hc11_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST m68hc11_address_cost
-
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg
-
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs
-
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG m68hc11_function_arg
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE m68hc11_function_arg_advance
-
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory
-#undef TARGET_CALLEE_COPIES
-#define TARGET_CALLEE_COPIES hook_callee_copies_named
-
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING m68hc11_strip_name_encoding
-
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P m68hc11_legitimate_address_p
-
-#undef TARGET_CAN_ELIMINATE
-#define TARGET_CAN_ELIMINATE m68hc11_can_eliminate
-
-#undef TARGET_CONDITIONAL_REGISTER_USAGE
-#define TARGET_CONDITIONAL_REGISTER_USAGE m68hc11_conditional_register_usage
-
-#undef TARGET_CLASS_LIKELY_SPILLED_P
-#define TARGET_CLASS_LIKELY_SPILLED_P m68hc11_class_likely_spilled_p
-
-#undef TARGET_TRAMPOLINE_INIT
-#define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init
-
-#undef TARGET_OPTION_OVERRIDE
-#define TARGET_OPTION_OVERRIDE m68hc11_option_override
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-static void
-m68hc11_option_override (void)
-{
- memset (m68hc11_reg_valid_for_index, 0,
- sizeof (m68hc11_reg_valid_for_index));
- memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base));
-
- /* Compilation with -fpic generates a wrong code. */
- if (flag_pic)
- {
- warning (0, "-f%s ignored for 68HC11/68HC12 (not supported)",
- (flag_pic > 1) ? "PIC" : "pic");
- flag_pic = 0;
- }
-
- /* Do not enable -fweb because it breaks the 32-bit shift patterns
- by breaking the match_dup of those patterns. The shift patterns
- will no longer be recognized after that. */
- flag_web = 0;
-
- /* Configure for a 68hc11 processor. */
- if (TARGET_M6811)
- {
- target_flags &= ~(TARGET_AUTO_INC_DEC | TARGET_MIN_MAX);
- m68hc11_cost = &m6811_cost;
- m68hc11_min_offset = 0;
- m68hc11_max_offset = 256;
- m68hc11_index_reg_class = NO_REGS;
- m68hc11_base_reg_class = A_REGS;
- m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
- m68hc11_sp_correction = 1;
- m68hc11_tmp_regs_class = D_REGS;
- m68hc11_addr_mode = ADDR_OFFSET;
- m68hc11_mov_addr_mode = 0;
- if (m68hc11_soft_reg_count < 0)
- m68hc11_soft_reg_count = 4;
- }
-
- /* Configure for a 68hc12 processor. */
- if (TARGET_M6812)
- {
- m68hc11_cost = &m6812_cost;
- m68hc11_min_offset = -65536;
- m68hc11_max_offset = 65536;
- m68hc11_index_reg_class = D_REGS;
- m68hc11_base_reg_class = A_OR_SP_REGS;
- m68hc11_reg_valid_for_base[HARD_X_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Y_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
- m68hc11_reg_valid_for_base[HARD_SP_REGNUM] = 1;
- m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1;
- m68hc11_sp_correction = 0;
- m68hc11_tmp_regs_class = TMP_REGS;
- m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST
- | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
- m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST
- | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
- target_flags |= MASK_NO_DIRECT_MODE;
- if (m68hc11_soft_reg_count < 0)
- m68hc11_soft_reg_count = 0;
-
- if (TARGET_LONG_CALLS)
- current_function_far = 1;
- }
-}
-
-
-/* The soft-registers are disabled or enabled according to the
- -msoft-reg-count=<n> option. */
-
-static void
-m68hc11_conditional_register_usage (void)
-{
- int i;
-
- if (m68hc11_soft_reg_count > SOFT_REG_LAST - SOFT_REG_FIRST)
- m68hc11_soft_reg_count = SOFT_REG_LAST - SOFT_REG_FIRST;
-
- for (i = SOFT_REG_FIRST + m68hc11_soft_reg_count; i < SOFT_REG_LAST; i++)
- {
- fixed_regs[i] = 1;
- call_used_regs[i] = 1;
- }
-
- /* For 68HC12, the Z register emulation is not necessary when the
- frame pointer is not used. The frame pointer is eliminated and
- replaced by the stack register (which is a BASE_REG_CLASS). */
- if (TARGET_M6812 && flag_omit_frame_pointer && optimize)
- {
- fixed_regs[HARD_Z_REGNUM] = 1;
- }
-}
-
-
-/* Reload and register operations. */
-
-
-void
-create_regs_rtx (void)
-{
- /* regs_inited = 1; */
- ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
- iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
- d_reg = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_soft_tmp_reg = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
-
- stack_push_word = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- stack_pop_word = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
-
-}
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- - 8-bit values are stored anywhere (except the SP register).
- - 16-bit values can be stored in any register whose mode is 16
- - 32-bit values can be stored in D, X registers or in a soft register
- (except the last one because we need 2 soft registers)
- - Values whose size is > 32 bit are not stored in real hard
- registers. They may be stored in soft registers if there are
- enough of them. */
-int
-hard_regno_mode_ok (int regno, enum machine_mode mode)
-{
- switch (GET_MODE_SIZE (mode))
- {
- case 8:
- return S_REGNO_P (regno) && m68hc11_soft_reg_count >= 4;
-
- case 4:
- return (X_REGNO_P (regno)
- || (S_REGNO_P (regno) && m68hc11_soft_reg_count >= 2));
-
- case 2:
- return G_REGNO_P (regno);
-
- case 1:
- /* We have to accept a QImode in X or Y registers. Otherwise, the
- reload pass will fail when some (SUBREG:QI (REG:HI X)) are defined
- in the insns. Reload fails if the insn rejects the register class 'a'
- as well as if it accepts it. Patterns that failed were
- zero_extend_qihi2 and iorqi3. */
-
- return G_REGNO_P (regno) && !SP_REGNO_P (regno);
-
- default:
- return 0;
- }
-}
-
-int
-m68hc11_hard_regno_rename_ok (int reg1, int reg2)
-{
- /* Don't accept renaming to Z register. We will replace it to
- X,Y or D during machine reorg pass. */
- if (reg2 == HARD_Z_REGNUM)
- return 0;
-
- /* Don't accept renaming D,X to Y register as the code will be bigger. */
- if (TARGET_M6811 && reg2 == HARD_Y_REGNUM
- && (D_REGNO_P (reg1) || X_REGNO_P (reg1)))
- return 0;
-
- return 1;
-}
-
-enum reg_class
-preferred_reload_class (rtx operand, enum reg_class rclass)
-{
- enum machine_mode mode;
-
- mode = GET_MODE (operand);
-
- if (debug_m6811)
- {
- printf ("Preferred reload: (class=%s): ", reg_class_names[rclass]);
- }
-
- if (rclass == D_OR_A_OR_S_REGS && SP_REG_P (operand))
- return m68hc11_base_reg_class;
-
- if (rclass >= S_REGS && (GET_CODE (operand) == MEM
- || GET_CODE (operand) == CONST_INT))
- {
- /* S_REGS class must not be used. The movhi template does not
- work to move a memory to a soft register.
- Restrict to a hard reg. */
- switch (rclass)
- {
- default:
- case G_REGS:
- case D_OR_A_OR_S_REGS:
- rclass = A_OR_D_REGS;
- break;
- case A_OR_S_REGS:
- rclass = A_REGS;
- break;
- case D_OR_SP_OR_S_REGS:
- rclass = D_OR_SP_REGS;
- break;
- case D_OR_Y_OR_S_REGS:
- rclass = D_OR_Y_REGS;
- break;
- case D_OR_X_OR_S_REGS:
- rclass = D_OR_X_REGS;
- break;
- case SP_OR_S_REGS:
- rclass = SP_REGS;
- break;
- case Y_OR_S_REGS:
- rclass = Y_REGS;
- break;
- case X_OR_S_REGS:
- rclass = X_REGS;
- break;
- case D_OR_S_REGS:
- rclass = D_REGS;
- }
- }
- else if (rclass == Y_REGS && GET_CODE (operand) == MEM)
- {
- rclass = Y_REGS;
- }
- else if (rclass == A_OR_D_REGS && GET_MODE_SIZE (mode) == 4)
- {
- rclass = D_OR_X_REGS;
- }
- else if (rclass >= S_REGS && S_REG_P (operand))
- {
- switch (rclass)
- {
- default:
- case G_REGS:
- case D_OR_A_OR_S_REGS:
- rclass = A_OR_D_REGS;
- break;
- case A_OR_S_REGS:
- rclass = A_REGS;
- break;
- case D_OR_SP_OR_S_REGS:
- rclass = D_OR_SP_REGS;
- break;
- case D_OR_Y_OR_S_REGS:
- rclass = D_OR_Y_REGS;
- break;
- case D_OR_X_OR_S_REGS:
- rclass = D_OR_X_REGS;
- break;
- case SP_OR_S_REGS:
- rclass = SP_REGS;
- break;
- case Y_OR_S_REGS:
- rclass = Y_REGS;
- break;
- case X_OR_S_REGS:
- rclass = X_REGS;
- break;
- case D_OR_S_REGS:
- rclass = D_REGS;
- }
- }
- else if (rclass >= S_REGS)
- {
- if (debug_m6811)
- {
- printf ("Class = %s for: ", reg_class_names[rclass]);
- fflush (stdout);
- debug_rtx (operand);
- }
- }
-
- if (debug_m6811)
- {
- printf (" => class=%s\n", reg_class_names[rclass]);
- fflush (stdout);
- debug_rtx (operand);
- }
-
- return rclass;
-}
-
-/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
-
-static bool
-m68hc11_class_likely_spilled_p (reg_class_t rclass)
-{
- switch (rclass)
- {
- case D_REGS:
- case X_REGS:
- case Y_REGS:
- case A_REGS:
- case SP_REGS:
- case D_OR_X_REGS:
- case D_OR_Y_REGS:
- case X_OR_SP_REGS:
- case Y_OR_SP_REGS:
- case D_OR_SP_REGS:
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-/* Return 1 if the operand is a valid indexed addressing mode.
- For 68hc11: n,r with n in [0..255] and r in A_REGS class
- For 68hc12: n,r no constraint on the constant, r in A_REGS class. */
-int
-m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode)
-{
- rtx base, offset;
-
- switch (GET_CODE (operand))
- {
- case MEM:
- if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
- return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
- addr_mode & (ADDR_STRICT | ADDR_OFFSET));
- return 0;
-
- case POST_INC:
- case PRE_INC:
- case POST_DEC:
- case PRE_DEC:
- if (addr_mode & ADDR_INCDEC)
- return m68hc11_valid_addressing_p (XEXP (operand, 0), mode,
- addr_mode & ADDR_STRICT);
- return 0;
-
- case PLUS:
- base = XEXP (operand, 0);
- if (GET_CODE (base) == MEM)
- return 0;
-
- offset = XEXP (operand, 1);
- if (GET_CODE (offset) == MEM)
- return 0;
-
- /* Indexed addressing mode with 2 registers. */
- if (GET_CODE (base) == REG && GET_CODE (offset) == REG)
- {
- if (!(addr_mode & ADDR_INDEXED))
- return 0;
-
- addr_mode &= ADDR_STRICT;
- if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode)
- && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode))
- return 1;
-
- if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode)
- && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode))
- return 1;
-
- return 0;
- }
-
- if (!(addr_mode & ADDR_OFFSET))
- return 0;
-
- if (GET_CODE (base) == REG)
- {
- if (!VALID_CONSTANT_OFFSET_P (offset, mode))
- return 0;
-
- if (!(addr_mode & ADDR_STRICT))
- return 1;
-
- return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1);
- }
-
- if (GET_CODE (offset) == REG)
- {
- if (!VALID_CONSTANT_OFFSET_P (base, mode))
- return 0;
-
- if (!(addr_mode & ADDR_STRICT))
- return 1;
-
- return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1);
- }
- return 0;
-
- case REG:
- return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT);
-
- case CONST_INT:
- if (addr_mode & ADDR_CONST)
- return VALID_CONSTANT_OFFSET_P (operand, mode);
- return 0;
-
- default:
- return 0;
- }
-}
-
-/* Returns 1 if the operand fits in a 68HC11 indirect mode or in
- a 68HC12 1-byte index addressing mode. */
-int
-m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
-{
- rtx base, offset;
- int addr_mode;
-
- if (GET_CODE (operand) == REG && reload_in_progress
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (operand)])
- {
- operand = reg_equiv_memory_loc[REGNO (operand)];
- operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
- }
-
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- if (CONSTANT_ADDRESS_P (operand))
- return 1;
-
- if (PUSH_POP_ADDRESS_P (operand))
- return 1;
-
- addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- if (!m68hc11_valid_addressing_p (operand, mode, addr_mode))
- return 0;
-
- if (TARGET_M6812 && GET_CODE (operand) == PLUS
- && (reload_completed | reload_in_progress))
- {
- base = XEXP (operand, 0);
- offset = XEXP (operand, 1);
-
- /* The offset can be a symbol address and this is too big
- for the operand constraint. */
- if (GET_CODE (base) != CONST_INT && GET_CODE (offset) != CONST_INT)
- return 0;
-
- if (GET_CODE (base) == CONST_INT)
- offset = base;
-
- switch (GET_MODE_SIZE (mode))
- {
- case 8:
- if (INTVAL (offset) < -16 + 6 || INTVAL (offset) > 15 - 6)
- return 0;
- break;
-
- case 4:
- if (INTVAL (offset) < -16 + 2 || INTVAL (offset) > 15 - 2)
- return 0;
- break;
-
- default:
- if (INTVAL (offset) < -16 || INTVAL (offset) > 15)
- return 0;
- break;
- }
- }
- return 1;
-}
-
-int
-m68hc11_register_indirect_p (rtx operand, enum machine_mode mode)
-{
- int addr_mode;
-
- if (GET_CODE (operand) == REG && reload_in_progress
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (operand)])
- {
- operand = reg_equiv_memory_loc[REGNO (operand)];
- operand = eliminate_regs (operand, VOIDmode, NULL_RTX);
- }
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return m68hc11_valid_addressing_p (operand, mode, addr_mode);
-}
-
-static bool
-m68hc11_legitimate_address_p_1 (enum machine_mode mode, rtx operand,
- bool strict)
-{
- int addr_mode;
-
- if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812)
- {
- /* Reject the global variables if they are too wide. This forces
- a load of their address in a register and generates smaller code. */
- if (GET_MODE_SIZE (mode) == 8)
- return 0;
-
- return 1;
- }
- addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
- if (m68hc11_valid_addressing_p (operand, mode, addr_mode))
- {
- return 1;
- }
- if (PUSH_POP_ADDRESS_P (operand))
- {
- return 1;
- }
- if (symbolic_memory_operand (operand, mode))
- {
- return 1;
- }
- return 0;
-}
-
-bool
-m68hc11_legitimate_address_p (enum machine_mode mode, rtx operand,
- bool strict)
-{
- int result;
-
- if (debug_m6811)
- {
- printf ("Checking: ");
- fflush (stdout);
- debug_rtx (operand);
- }
-
- result = m68hc11_legitimate_address_p_1 (mode, operand, strict);
-
- if (debug_m6811)
- {
- printf (" -> %s\n", result == 0 ? "NO" : "YES");
- }
-
- if (result == 0)
- {
- if (debug_m6811)
- {
- printf ("go_if_legitimate%s, ret 0: %d:",
- (strict ? "_strict" : ""), mode);
- fflush (stdout);
- debug_rtx (operand);
- }
- }
- return result;
-}
-
-
-int
-m68hc11_reload_operands (rtx operands[])
-{
- enum machine_mode mode;
-
- if (regs_inited == 0)
- create_regs_rtx ();
-
- mode = GET_MODE (operands[1]);
-
- /* Input reload of indirect addressing (MEM (PLUS (REG) (CONST))). */
- if (A_REG_P (operands[0]) && memory_reload_operand (operands[1], mode))
- {
- rtx big_offset = XEXP (XEXP (operands[1], 0), 1);
- rtx base = XEXP (XEXP (operands[1], 0), 0);
-
- if (GET_CODE (base) != REG)
- {
- rtx tmp = base;
- base = big_offset;
- big_offset = tmp;
- }
-
- /* If the offset is out of range, we have to compute the address
- with a separate add instruction. We try to do this with an 8-bit
- add on the A register. This is possible only if the lowest part
- of the offset (i.e., big_offset % 256) is a valid constant offset
- with respect to the mode. If it's not, we have to generate a
- 16-bit add on the D register. From:
-
- (SET (REG X (MEM (PLUS (REG X) (CONST_INT 1000)))))
-
- we generate:
-
- [(SET (REG D) (REG X)) (SET (REG X) (REG D))]
- (SET (REG A) (PLUS (REG A) (CONST_INT 1000 / 256)))
- [(SET (REG D) (REG X)) (SET (REG X) (REG D))]
- (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256)))
-
- (SET (REG X) (PLUS (REG X) (CONST_INT 1000 / 256 * 256)))
- (SET (REG X) (MEM (PLUS (REG X) (CONST_INT 1000 % 256))))
-
- */
- if (!VALID_CONSTANT_OFFSET_P (big_offset, mode))
- {
- int vh, vl;
- rtx reg = operands[0];
- rtx offset;
- int val = INTVAL (big_offset);
-
-
- /* We use the 'operands[0]' as a scratch register to compute the
- address. Make sure 'base' is in that register. */
- if (!rtx_equal_p (base, operands[0]))
- {
- emit_move_insn (reg, base);
- }
-
- if (val > 0)
- {
- vh = val >> 8;
- vl = val & 0x0FF;
- }
- else
- {
- vh = (val >> 8) & 0x0FF;
- vl = val & 0x0FF;
- }
-
- /* Create the lowest part offset that still remains to be added.
- If it's not a valid offset, do a 16-bit add. */
- offset = GEN_INT (vl);
- if (!VALID_CONSTANT_OFFSET_P (offset, mode))
- {
- emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx_PLUS (HImode, reg, big_offset)));
- offset = const0_rtx;
- }
- else
- {
- emit_insn (gen_rtx_SET (VOIDmode, reg,
- gen_rtx_PLUS (HImode, reg,
- GEN_INT (vh << 8))));
- }
- emit_move_insn (operands[0],
- gen_rtx_MEM (GET_MODE (operands[1]),
- gen_rtx_PLUS (Pmode, reg, offset)));
- return 1;
- }
- }
-
- /* Use the normal gen_movhi pattern. */
- return 0;
-}
-
-void
-m68hc11_emit_libcall (const char *name, enum rtx_code code,
- enum machine_mode dmode, enum machine_mode smode,
- int noperands, rtx *operands)
-{
- rtx ret;
- rtx insns;
- rtx libcall;
- rtx equiv;
-
- start_sequence ();
- libcall = gen_rtx_SYMBOL_REF (Pmode, name);
- switch (noperands)
- {
- case 2:
- ret = emit_library_call_value (libcall, NULL_RTX, LCT_CONST,
- dmode, 1, operands[1], smode);
- equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
- break;
-
- case 3:
- ret = emit_library_call_value (libcall, NULL_RTX,
- LCT_CONST, dmode, 2,
- operands[1], smode, operands[2],
- smode);
- equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret, equiv);
-}
-
-/* Returns true if X is a PRE/POST increment decrement
- (same as auto_inc_p() in rtlanal.c but do not take into
- account the stack). */
-int
-m68hc11_auto_inc_p (rtx x)
-{
- return GET_CODE (x) == PRE_DEC
- || GET_CODE (x) == POST_INC
- || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_INC;
-}
-
-
-/* Predicates for machine description. */
-
-int
-memory_reload_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (operand) == MEM
- && GET_CODE (XEXP (operand, 0)) == PLUS
- && ((GET_CODE (XEXP (XEXP (operand, 0), 0)) == REG
- && GET_CODE (XEXP (XEXP (operand, 0), 1)) == CONST_INT)
- || (GET_CODE (XEXP (XEXP (operand, 0), 1)) == REG
- && GET_CODE (XEXP (XEXP (operand, 0), 0)) == CONST_INT));
-}
-
-int
-m68hc11_symbolic_p (rtx operand, enum machine_mode mode)
-{
- if (GET_CODE (operand) == MEM)
- {
- rtx op = XEXP (operand, 0);
-
- if (symbolic_memory_operand (op, mode))
- return 1;
- }
- return 0;
-}
-
-int
-m68hc11_indirect_p (rtx operand, enum machine_mode mode)
-{
- if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode)
- {
- rtx op = XEXP (operand, 0);
- int addr_mode;
-
- if (m68hc11_page0_symbol_p (op))
- return 1;
-
- if (symbolic_memory_operand (op, mode))
- return TARGET_M6812;
-
- if (reload_in_progress)
- return 1;
-
- operand = XEXP (operand, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- return m68hc11_valid_addressing_p (operand, mode, addr_mode);
- }
- return 0;
-}
-
-int
-memory_indexed_operand (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (operand) != MEM)
- return 0;
-
- operand = XEXP (operand, 0);
- if (GET_CODE (operand) == PLUS)
- {
- if (GET_CODE (XEXP (operand, 0)) == REG)
- operand = XEXP (operand, 0);
- else if (GET_CODE (XEXP (operand, 1)) == REG)
- operand = XEXP (operand, 1);
- }
- return GET_CODE (operand) == REG
- && (REGNO (operand) >= FIRST_PSEUDO_REGISTER
- || A_REGNO_P (REGNO (operand)));
-}
-
-int
-push_pop_operand_p (rtx operand)
-{
- if (GET_CODE (operand) != MEM)
- {
- return 0;
- }
- operand = XEXP (operand, 0);
- return PUSH_POP_ADDRESS_P (operand);
-}
-
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-symbolic_memory_operand (rtx op, enum machine_mode mode)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- case CONST:
- op = XEXP (op, 0);
- return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
-
- /* ??? This clause seems to be irrelevant. */
- case CONST_DOUBLE:
- return GET_MODE (op) == mode;
-
- case PLUS:
- return symbolic_memory_operand (XEXP (op, 0), mode)
- && symbolic_memory_operand (XEXP (op, 1), mode);
-
- default:
- return 0;
- }
-}
-
-/* Emit the code to build the trampoline used to call a nested function.
-
- 68HC11 68HC12
-
- ldy #&CXT movw #&CXT,*_.d1
- sty *_.d1 jmp FNADDR
- jmp FNADDR
-
-*/
-static void
-m68hc11_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
-{
- const char *static_chain_reg = reg_names[STATIC_CHAIN_REGNUM];
- rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
- rtx mem;
-
- /* Skip the '*'. */
- if (*static_chain_reg == '*')
- static_chain_reg++;
- if (TARGET_M6811)
- {
- mem = adjust_address (m_tramp, HImode, 0);
- emit_move_insn (mem, GEN_INT (0x18ce));
- mem = adjust_address (m_tramp, HImode, 2);
- emit_move_insn (mem, cxt);
- mem = adjust_address (m_tramp, HImode, 4);
- emit_move_insn (mem, GEN_INT (0x18df));
- mem = adjust_address (m_tramp, QImode, 6);
- emit_move_insn (mem,
- gen_rtx_CONST (QImode,
- gen_rtx_SYMBOL_REF (Pmode,
- static_chain_reg)));
- mem = adjust_address (m_tramp, QImode, 7);
- emit_move_insn (mem, GEN_INT (0x7e));
- mem = adjust_address (m_tramp, HImode, 8);
- emit_move_insn (mem, fnaddr);
- }
- else
- {
- mem = adjust_address (m_tramp, HImode, 0);
- emit_move_insn (mem, GEN_INT (0x1803));
- mem = adjust_address (m_tramp, HImode, 2);
- emit_move_insn (mem, cxt);
- mem = adjust_address (m_tramp, HImode, 4);
- emit_move_insn (mem,
- gen_rtx_CONST (HImode,
- gen_rtx_SYMBOL_REF (Pmode,
- static_chain_reg)));
- mem = adjust_address (m_tramp, QImode, 6);
- emit_move_insn (mem, GEN_INT (0x06));
- mem = adjust_address (m_tramp, HImode, 7);
- emit_move_insn (mem, fnaddr);
- }
-}
-
-/* Declaration of types. */
-
-/* Handle an "tiny_data" attribute; arguments as in
- struct attribute_spec.handler. */
-static tree
-m68hc11_handle_page0_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
-{
- tree decl = *node;
-
- if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
- {
- DECL_SECTION_NAME (decl) = build_string (6, ".page0");
- }
- else
- {
- warning (OPT_Wattributes, "%qE attribute ignored",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-
-/* Keep track of the symbol which has a `trap' attribute and which uses
- the `swi' calling convention. Since there is only one trap, we only
- record one such symbol. If there are several, a warning is reported. */
-static rtx trap_handler_symbol = 0;
-
-/* Handle an attribute requiring a FUNCTION_TYPE, FIELD_DECL or TYPE_DECL;
- arguments as in struct attribute_spec.handler. */
-static tree
-m68hc11_handle_fntype_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
- bool *no_add_attrs)
-{
- if (TREE_CODE (*node) != FUNCTION_TYPE
- && TREE_CODE (*node) != METHOD_TYPE
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
- {
- warning (OPT_Wattributes, "%qE attribute only applies to functions",
- name);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
-}
-/* Undo the effects of the above. */
-
-static const char *
-m68hc11_strip_name_encoding (const char *str)
-{
- return str + (*str == '*' || *str == '@' || *str == '&');
-}
-
-static void
-m68hc11_encode_label (tree decl)
-{
- const char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
- int len = strlen (str);
- char *newstr = XALLOCAVEC (char, len + 2);
-
- newstr[0] = '@';
- strcpy (&newstr[1], str);
-
- XSTR (XEXP (DECL_RTL (decl), 0), 0) = ggc_alloc_string (newstr, len + 1);
-}
-
-/* Return 1 if this is a symbol in page0 */
-int
-m68hc11_page0_symbol_p (rtx x)
-{
- switch (GET_CODE (x))
- {
- case SYMBOL_REF:
- return XSTR (x, 0) != 0 && XSTR (x, 0)[0] == '@';
-
- case CONST:
- return m68hc11_page0_symbol_p (XEXP (x, 0));
-
- case PLUS:
- if (!m68hc11_page0_symbol_p (XEXP (x, 0)))
- return 0;
-
- return GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) < 256
- && INTVAL (XEXP (x, 1)) >= 0;
-
- default:
- return 0;
- }
-}
-
-/* We want to recognize trap handlers so that we handle calls to traps
- in a special manner (by issuing the trap). This information is stored
- in SYMBOL_REF_FLAG. */
-
-static void
-m68hc11_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
-{
- tree func_attr;
- int trap_handler;
- int is_far = 0;
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- if (lookup_attribute ("page0", DECL_ATTRIBUTES (decl)) != 0)
- m68hc11_encode_label (decl);
- return;
- }
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- return;
-
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-
-
- if (lookup_attribute ("far", func_attr) != NULL_TREE)
- is_far = 1;
- else if (lookup_attribute ("near", func_attr) == NULL_TREE)
- is_far = TARGET_LONG_CALLS != 0;
-
- trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
- if (trap_handler && is_far)
- {
- warning (OPT_Wattributes, "%<trap%> and %<far%> attributes are "
- "not compatible, ignoring %<far%>");
- trap_handler = 0;
- }
- if (trap_handler)
- {
- if (trap_handler_symbol != 0)
- warning (OPT_Wattributes, "%<trap%> attribute is already used");
- else
- trap_handler_symbol = XEXP (rtl, 0);
- }
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = is_far;
-}
-
-static unsigned int
-m68hc11_section_type_flags (tree decl, const char *name, int reloc)
-{
- unsigned int flags = default_section_type_flags (decl, name, reloc);
-
- if (strncmp (name, ".eeprom", 7) == 0)
- {
- flags |= SECTION_WRITE | SECTION_CODE | SECTION_OVERRIDE;
- }
-
- return flags;
-}
-
-int
-m68hc11_is_far_symbol (rtx sym)
-{
- if (GET_CODE (sym) == MEM)
- sym = XEXP (sym, 0);
-
- return SYMBOL_REF_FLAG (sym);
-}
-
-int
-m68hc11_is_trap_symbol (rtx sym)
-{
- if (GET_CODE (sym) == MEM)
- sym = XEXP (sym, 0);
-
- return trap_handler_symbol != 0 && rtx_equal_p (trap_handler_symbol, sym);
-}
-
-
-/* Argument support functions. */
-
-/* Given FROM and TO register numbers, say whether this elimination is
- allowed. Frame pointer elimination is automatically handled.
-
- All other eliminations are valid. */
-
-bool
-m68hc11_can_eliminate (const int from, const int to)
-{
- return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
- ? ! frame_pointer_needed
- : true);
-}
-
-/* Define the offset between two registers, one to be eliminated, and the
- other its replacement, at the start of a routine. */
-int
-m68hc11_initial_elimination_offset (int from, int to)
-{
- int trap_handler;
- tree func_attr;
- int size;
- int regno;
-
- /* For a trap handler, we must take into account the registers which
- are pushed on the stack during the trap (except the PC). */
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- current_function_interrupt = lookup_attribute ("interrupt",
- func_attr) != NULL_TREE;
- trap_handler = lookup_attribute ("trap", func_attr) != NULL_TREE;
-
- if (lookup_attribute ("far", func_attr) != 0)
- current_function_far = 1;
- else if (lookup_attribute ("near", func_attr) != 0)
- current_function_far = 0;
- else
- current_function_far = (TARGET_LONG_CALLS != 0
- && !current_function_interrupt
- && !trap_handler);
-
- if (trap_handler && from == ARG_POINTER_REGNUM)
- size = 7;
-
- /* For a function using 'call/rtc' we must take into account the
- page register which is pushed in the call. */
- else if (current_function_far && from == ARG_POINTER_REGNUM)
- size = 1;
- else
- size = 0;
-
- if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
- {
- /* 2 is for the saved frame.
- 1 is for the 'sts' correction when creating the frame. */
- return get_frame_size () + 2 + m68hc11_sp_correction + size;
- }
-
- if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
- {
- return m68hc11_sp_correction;
- }
-
- /* Push any 2 byte pseudo hard registers that we need to save. */
- for (regno = SOFT_REG_FIRST; regno < SOFT_REG_LAST; regno++)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- size += 2;
- }
- }
-
- if (from == ARG_POINTER_REGNUM && to == HARD_SP_REGNUM)
- {
- return get_frame_size () + size;
- }
-
- if (from == FRAME_POINTER_REGNUM && to == HARD_SP_REGNUM)
- {
- return size;
- }
- return 0;
-}
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0. */
-
-void
-m68hc11_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
-{
- tree ret_type;
-
- z_replacement_completed = 0;
- cum->words = 0;
- cum->nregs = 0;
-
- /* For a library call, we must find out the type of the return value.
- When the return value is bigger than 4 bytes, it is returned in
- memory. In that case, the first argument of the library call is a
- pointer to the memory location. Because the first argument is passed in
- register D, we have to identify this, so that the first function
- parameter is not passed in D either. */
- if (fntype == 0)
- {
- const char *name;
- size_t len;
-
- if (libname == 0 || GET_CODE (libname) != SYMBOL_REF)
- return;
-
- /* If the library ends in 'di' or in 'df', we assume it's
- returning some DImode or some DFmode which are 64-bit wide. */
- name = XSTR (libname, 0);
- len = strlen (name);
- if (len > 3
- && ((name[len - 2] == 'd'
- && (name[len - 1] == 'f' || name[len - 1] == 'i'))
- || (name[len - 3] == 'd'
- && (name[len - 2] == 'i' || name[len - 2] == 'f'))))
- {
- /* We are in. Mark the first parameter register as already used. */
- cum->words = 1;
- cum->nregs = 1;
- }
- return;
- }
-
- ret_type = TREE_TYPE (fntype);
-
- if (ret_type && aggregate_value_p (ret_type, fntype))
- {
- cum->words = 1;
- cum->nregs = 1;
- }
-}
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-
-static void
-m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- if (mode != BLKmode)
- {
- if (cum->words == 0 && GET_MODE_SIZE (mode) == 4)
- {
- cum->nregs = 2;
- cum->words = GET_MODE_SIZE (mode);
- }
- else
- {
- cum->words += GET_MODE_SIZE (mode);
- if (cum->words <= HARD_REG_SIZE)
- cum->nregs = 1;
- }
- }
- else
- {
- cum->words += int_size_in_bytes (type);
- }
- return;
-}
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis). */
-
-static rtx
-m68hc11_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- const_tree type ATTRIBUTE_UNUSED,
- bool named ATTRIBUTE_UNUSED)
-{
- if (cum->words != 0)
- {
- return NULL_RTX;
- }
-
- if (mode != BLKmode)
- {
- if (GET_MODE_SIZE (mode) == 2 * HARD_REG_SIZE)
- return gen_rtx_REG (mode, HARD_X_REGNUM);
-
- if (GET_MODE_SIZE (mode) > HARD_REG_SIZE)
- {
- return NULL_RTX;
- }
- return gen_rtx_REG (mode, HARD_D_REGNUM);
- }
- return NULL_RTX;
-}
-
-/* If defined, a C expression which determines whether, and in which direction,
- to pad out an argument with extra space. The value should be of type
- `enum direction': either `upward' to pad above the argument,
- `downward' to pad below, or `none' to inhibit padding.
-
- Structures are stored left shifted in their argument slot. */
-enum direction
-m68hc11_function_arg_padding (enum machine_mode mode, const_tree type)
-{
- if (type != 0 && AGGREGATE_TYPE_P (type))
- return upward;
-
- /* Fall back to the default. */
- return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
-}
-
-
-/* Function prologue and epilogue. */
-
-/* Emit a move after the reload pass has completed. This is used to
- emit the prologue and epilogue. */
-static void
-emit_move_after_reload (rtx to, rtx from, rtx scratch)
-{
- rtx insn;
-
- if (TARGET_M6812 || H_REG_P (to) || H_REG_P (from))
- {
- insn = emit_move_insn (to, from);
- }
- else
- {
- emit_move_insn (scratch, from);
- insn = emit_move_insn (to, scratch);
- }
-
- /* Put a REG_INC note to tell the flow analysis that the instruction
- is necessary. */
- if (IS_STACK_PUSH (to))
- add_reg_note (insn, REG_INC, XEXP (XEXP (to, 0), 0));
- else if (IS_STACK_POP (from))
- add_reg_note (insn, REG_INC, XEXP (XEXP (from, 0), 0));
-
- /* For 68HC11, put a REG_INC note on `sts _.frame' to prevent the cse-reg
- to think that sp == _.frame and later replace a x = sp with x = _.frame.
- The problem is that we are lying to gcc and use `txs' for x = sp
- (which is not really true because txs is really x = sp + 1). */
- else if (TARGET_M6811 && SP_REG_P (from))
- add_reg_note (insn, REG_INC, from);
-}
-
-int
-m68hc11_total_frame_size (void)
-{
- int size;
- int regno;
-
- size = get_frame_size ();
- if (current_function_interrupt)
- {
- size += 3 * HARD_REG_SIZE;
- }
- if (frame_pointer_needed)
- size += HARD_REG_SIZE;
-
- for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- size += HARD_REG_SIZE;
-
- return size;
-}
-
-static void
-m68hc11_output_function_epilogue (FILE *out ATTRIBUTE_UNUSED,
- HOST_WIDE_INT size ATTRIBUTE_UNUSED)
-{
- /* We catch the function epilogue generation to have a chance
- to clear the z_replacement_completed flag. */
- z_replacement_completed = 0;
-}
-
-void
-expand_prologue (void)
-{
- tree func_attr;
- int size;
- int regno;
- rtx scratch;
-
- gcc_assert (reload_completed == 1);
-
- size = get_frame_size ();
-
- create_regs_rtx ();
-
- /* Generate specific prologue for interrupt handlers. */
- func_attr = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- current_function_interrupt = lookup_attribute ("interrupt",
- func_attr) != NULL_TREE;
- current_function_trap = lookup_attribute ("trap", func_attr) != NULL_TREE;
- if (lookup_attribute ("far", func_attr) != NULL_TREE)
- current_function_far = 1;
- else if (lookup_attribute ("near", func_attr) != NULL_TREE)
- current_function_far = 0;
- else
- current_function_far = (TARGET_LONG_CALLS != 0
- && !current_function_interrupt
- && !current_function_trap);
-
- /* Get the scratch register to build the frame and push registers.
- If the first argument is a 32-bit quantity, the D+X registers
- are used. Use Y to compute the frame. Otherwise, X is cheaper.
- For 68HC12, this scratch register is not used. */
- if (crtl->args.info.nregs == 2)
- scratch = iy_reg;
- else
- scratch = ix_reg;
-
- /* Save current stack frame. */
- if (frame_pointer_needed)
- emit_move_after_reload (stack_push_word, hard_frame_pointer_rtx, scratch);
-
- /* For an interrupt handler, we must preserve _.tmp, _.z and _.xy.
- Other soft registers in page0 need not to be saved because they
- will be restored by C functions. For a trap handler, we don't
- need to preserve these registers because this is a synchronous call. */
- if (current_function_interrupt)
- {
- emit_move_after_reload (stack_push_word, m68hc11_soft_tmp_reg, scratch);
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, SOFT_Z_REGNUM), scratch);
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
- scratch);
- }
-
- /* Allocate local variables. */
- if (TARGET_M6812 && (size > 4 || size == 3))
- {
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (-size)));
- }
- else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
- {
- rtx insn;
-
- insn = gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (HImode,
- stack_pointer_rtx,
- GEN_INT (-size))),
- gen_rtx_CLOBBER (VOIDmode, scratch)));
- emit_insn (insn);
- }
- else
- {
- int i;
-
- /* Allocate by pushing scratch values. */
- for (i = 2; i <= size; i += 2)
- emit_move_after_reload (stack_push_word, ix_reg, 0);
-
- if (size & 1)
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, constm1_rtx));
- }
-
- /* Create the frame pointer. */
- if (frame_pointer_needed)
- emit_move_after_reload (hard_frame_pointer_rtx,
- stack_pointer_rtx, scratch);
-
- /* Push any 2 byte pseudo hard registers that we need to save. */
- for (regno = SOFT_REG_FIRST; regno <= SOFT_REG_LAST; regno++)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- emit_move_after_reload (stack_push_word,
- gen_rtx_REG (HImode, regno), scratch);
- }
- }
-}
-
-void
-expand_epilogue (void)
-{
- int size;
- register int regno;
- int return_size;
- rtx scratch;
-
- gcc_assert (reload_completed == 1);
-
- size = get_frame_size ();
-
- /* If we are returning a value in two registers, we have to preserve the
- X register and use the Y register to restore the stack and the saved
- registers. Otherwise, use X because it's faster (and smaller). */
- if (crtl->return_rtx == 0)
- return_size = 0;
- else if (GET_CODE (crtl->return_rtx) == MEM)
- return_size = HARD_REG_SIZE;
- else
- return_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- if (return_size > HARD_REG_SIZE && return_size <= 2 * HARD_REG_SIZE)
- scratch = iy_reg;
- else
- scratch = ix_reg;
-
- /* Pop any 2 byte pseudo hard registers that we saved. */
- for (regno = SOFT_REG_LAST; regno >= SOFT_REG_FIRST; regno--)
- {
- if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
- {
- emit_move_after_reload (gen_rtx_REG (HImode, regno),
- stack_pop_word, scratch);
- }
- }
-
- /* de-allocate auto variables */
- if (TARGET_M6812 && (size > 4 || size == 3))
- {
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (size)));
- }
- else if ((!optimize_size && size > 8) || (optimize_size && size > 10))
- {
- rtx insn;
-
- insn = gen_rtx_PARALLEL
- (VOIDmode,
- gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- stack_pointer_rtx,
- gen_rtx_PLUS (HImode,
- stack_pointer_rtx,
- GEN_INT (size))),
- gen_rtx_CLOBBER (VOIDmode, scratch)));
- emit_insn (insn);
- }
- else
- {
- int i;
-
- for (i = 2; i <= size; i += 2)
- emit_move_after_reload (scratch, stack_pop_word, scratch);
- if (size & 1)
- emit_insn (gen_addhi3 (stack_pointer_rtx,
- stack_pointer_rtx, const1_rtx));
- }
-
- /* For an interrupt handler, restore ZTMP, ZREG and XYREG. */
- if (current_function_interrupt)
- {
- emit_move_after_reload (gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM),
- stack_pop_word, scratch);
- emit_move_after_reload (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
- stack_pop_word, scratch);
- emit_move_after_reload (m68hc11_soft_tmp_reg, stack_pop_word, scratch);
- }
-
- /* Restore previous frame pointer. */
- if (frame_pointer_needed)
- emit_move_after_reload (hard_frame_pointer_rtx, stack_pop_word, scratch);
-
- /* If the trap handler returns some value, copy the value
- in D, X onto the stack so that the rti will pop the return value
- correctly. */
- else if (current_function_trap && return_size != 0)
- {
- rtx addr_reg = stack_pointer_rtx;
-
- if (!TARGET_M6812)
- {
- emit_move_after_reload (scratch, stack_pointer_rtx, 0);
- addr_reg = scratch;
- }
- emit_move_after_reload (gen_rtx_MEM (HImode,
- gen_rtx_PLUS (HImode, addr_reg,
- const1_rtx)), d_reg, 0);
- if (return_size > HARD_REG_SIZE)
- emit_move_after_reload (gen_rtx_MEM (HImode,
- gen_rtx_PLUS (HImode, addr_reg,
- GEN_INT (3))), ix_reg, 0);
- }
-
- emit_jump_insn (gen_return ());
-}
-
-
-/* Low and High part extraction for 68HC11. These routines are
- similar to gen_lowpart and gen_highpart but they have been
- fixed to work for constants and 68HC11 specific registers. */
-
-rtx
-m68hc11_gen_lowpart (enum machine_mode mode, rtx x)
-{
- /* We assume that the low part of an auto-inc mode is the same with
- the mode changed and that the caller split the larger mode in the
- correct order. */
- if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
- {
- return gen_rtx_MEM (mode, XEXP (x, 0));
- }
-
- /* Note that a CONST_DOUBLE rtx could represent either an integer or a
- floating-point constant. A CONST_DOUBLE is used whenever the
- constant requires more than one word in order to be adequately
- represented. */
- if (GET_CODE (x) == CONST_DOUBLE)
- {
- long l[2];
-
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- REAL_VALUE_TYPE r;
-
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l[0]);
- }
- else
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- return second;
- }
- if (mode == SImode)
- return GEN_INT (l[0]);
-
- return gen_int_mode (l[0], HImode);
- }
- else
- {
- l[0] = CONST_DOUBLE_LOW (x);
- }
- switch (mode)
- {
- case SImode:
- return GEN_INT (l[0]);
- case HImode:
- gcc_assert (GET_MODE (x) == SFmode);
- return gen_int_mode (l[0], HImode);
- default:
- gcc_unreachable ();
- }
- }
-
- if (mode == QImode && D_REG_P (x))
- return gen_rtx_REG (mode, HARD_B_REGNUM);
-
- /* gen_lowpart crashes when it is called with a SUBREG. */
- if (GET_CODE (x) == SUBREG && SUBREG_BYTE (x) != 0)
- {
- switch (mode)
- {
- case SImode:
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 4);
- case HImode:
- return gen_rtx_SUBREG (mode, SUBREG_REG (x), SUBREG_BYTE (x) + 2);
- default:
- gcc_unreachable ();
- }
- }
- x = gen_lowpart (mode, x);
-
- /* Return a different rtx to avoid to share it in several insns
- (when used by a split pattern). Sharing addresses within
- a MEM breaks the Z register replacement (and reloading). */
- if (GET_CODE (x) == MEM)
- x = copy_rtx (x);
- return x;
-}
-
-rtx
-m68hc11_gen_highpart (enum machine_mode mode, rtx x)
-{
- /* We assume that the high part of an auto-inc mode is the same with
- the mode changed and that the caller split the larger mode in the
- correct order. */
- if (GET_CODE (x) == MEM && m68hc11_auto_inc_p (XEXP (x, 0)))
- {
- return gen_rtx_MEM (mode, XEXP (x, 0));
- }
-
- /* Note that a CONST_DOUBLE rtx could represent either an integer or a
- floating-point constant. A CONST_DOUBLE is used whenever the
- constant requires more than one word in order to be adequately
- represented. */
- if (GET_CODE (x) == CONST_DOUBLE)
- {
- long l[2];
-
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
- {
- REAL_VALUE_TYPE r;
-
- if (GET_MODE (x) == SFmode)
- {
- REAL_VALUE_FROM_CONST_DOUBLE (r, x);
- REAL_VALUE_TO_TARGET_SINGLE (r, l[1]);
- }
- else
- {
- rtx first, second;
-
- split_double (x, &first, &second);
- return first;
- }
- if (mode == SImode)
- return GEN_INT (l[1]);
-
- return gen_int_mode ((l[1] >> 16), HImode);
- }
- else
- {
- l[1] = CONST_DOUBLE_HIGH (x);
- }
-
- switch (mode)
- {
- case SImode:
- return GEN_INT (l[1]);
- case HImode:
- gcc_assert (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
- return gen_int_mode ((l[0] >> 16), HImode);
- default:
- gcc_unreachable ();
- }
- }
- if (GET_CODE (x) == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (x);
-
- if (mode == QImode)
- {
- return gen_int_mode (val >> 8, QImode);
- }
- else if (mode == HImode)
- {
- return gen_int_mode (val >> 16, HImode);
- }
- else if (mode == SImode)
- {
- return gen_int_mode ((val >> 16) >> 16, SImode);
- }
- }
- if (mode == QImode && D_REG_P (x))
- return gen_rtx_REG (mode, HARD_A_REGNUM);
-
- /* There is no way in GCC to represent the upper part of a word register.
- To obtain the 8-bit upper part of a soft register, we change the
- reg into a mem rtx. This is possible because they are physically
- located in memory. There is no offset because we are big-endian. */
- if (mode == QImode && S_REG_P (x))
- {
- int pos;
-
- /* Avoid the '*' for direct addressing mode when this
- addressing mode is disabled. */
- pos = TARGET_NO_DIRECT_MODE ? 1 : 0;
- return gen_rtx_MEM (QImode,
- gen_rtx_SYMBOL_REF (Pmode,
- &reg_names[REGNO (x)][pos]));
- }
-
- /* gen_highpart crashes when it is called with a SUBREG. */
- switch (GET_CODE (x))
- {
- case SUBREG:
- return gen_rtx_SUBREG (mode, XEXP (x, 0), XINT (x, 1));
- case REG:
- if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- return gen_rtx_REG (mode, REGNO (x));
- else
- return gen_rtx_SUBREG (mode, x, 0);
- case MEM:
- x = change_address (x, mode, 0);
-
- /* Return a different rtx to avoid to share it in several insns
- (when used by a split pattern). Sharing addresses within
- a MEM breaks the Z register replacement (and reloading). */
- if (GET_CODE (x) == MEM)
- x = copy_rtx (x);
- return x;
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Obscure register manipulation. */
-
-/* Finds backward in the instructions to see if register 'reg' is
- dead. This is used when generating code to see if we can use 'reg'
- as a scratch register. This allows us to choose a better generation
- of code when we know that some register dies or can be clobbered. */
-
-int
-dead_register_here (rtx x, rtx reg)
-{
- rtx x_reg;
- rtx p;
-
- if (D_REG_P (reg))
- x_reg = gen_rtx_REG (SImode, HARD_X_REGNUM);
- else
- x_reg = 0;
-
- for (p = PREV_INSN (x); p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p))
- if (INSN_P (p))
- {
- rtx body;
-
- body = PATTERN (p);
-
- if (GET_CODE (body) == CALL_INSN)
- break;
- if (GET_CODE (body) == JUMP_INSN)
- break;
-
- if (GET_CODE (body) == SET)
- {
- rtx dst = XEXP (body, 0);
-
- if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg))
- break;
- if (x_reg && rtx_equal_p (dst, x_reg))
- break;
-
- if (find_regno_note (p, REG_DEAD, REGNO (reg)))
- return 1;
- }
- else if (reg_mentioned_p (reg, p)
- || (x_reg && reg_mentioned_p (x_reg, p)))
- break;
- }
-
- /* Scan forward to see if the register is set in some insns and never
- used since then. */
- for (p = x /*NEXT_INSN (x) */ ; p; p = NEXT_INSN (p))
- {
- rtx body;
-
- if (GET_CODE (p) == CODE_LABEL
- || GET_CODE (p) == JUMP_INSN
- || GET_CODE (p) == CALL_INSN || GET_CODE (p) == BARRIER)
- break;
-
- if (GET_CODE (p) != INSN)
- continue;
-
- body = PATTERN (p);
- if (GET_CODE (body) == SET)
- {
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- if (GET_CODE (dst) == REG
- && REGNO (dst) == REGNO (reg) && !reg_mentioned_p (reg, src))
- return 1;
- }
-
- /* Register is used (may be in source or in dest). */
- if (reg_mentioned_p (reg, p)
- || (x_reg != 0 && GET_MODE (p) == SImode
- && reg_mentioned_p (x_reg, p)))
- break;
- }
- return p == 0 ? 1 : 0;
-}
-
-
-/* Code generation operations called from machine description file. */
-
-/* Print the name of register 'regno' in the assembly file. */
-static void
-asm_print_register (FILE *file, int regno)
-{
- const char *name = reg_names[regno];
-
- if (TARGET_NO_DIRECT_MODE && name[0] == '*')
- name++;
-
- fprintf (file, "%s", name);
-}
-
-/* A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand X. X is an RTL
- expression.
-
- CODE is a value that can be used to specify one of several ways
- of printing the operand. It is used when identical operands
- must be printed differently depending on the context. CODE
- comes from the `%' specification that was used to request
- printing of the operand. If the specification was just `%DIGIT'
- then CODE is 0; if the specification was `%LTR DIGIT' then CODE
- is the ASCII code for LTR.
-
- If X is a register, this macro should print the register's name.
- The names can be found in an array `reg_names' whose type is
- `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
-
- When the machine description has a specification `%PUNCT' (a `%'
- followed by a punctuation character), this macro is called with
- a null pointer for X and the punctuation character for CODE.
-
- The M68HC11 specific codes are:
-
- 'b' for the low part of the operand.
- 'h' for the high part of the operand
- The 'b' or 'h' modifiers have no effect if the operand has
- the QImode and is not a S_REG_P (soft register). If the
- operand is a hard register, these two modifiers have no effect.
- 't' generate the temporary scratch register. The operand is
- ignored.
- 'T' generate the low-part temporary scratch register. The operand is
- ignored. */
-
-static void
-m68hc11_print_operand (FILE *file, rtx op, int letter)
-{
- if (letter == 't')
- {
- asm_print_register (file, SOFT_TMP_REGNUM);
- return;
- }
- else if (letter == 'T')
- {
- asm_print_register (file, SOFT_TMP_REGNUM);
- fprintf (file, "+1");
- return;
- }
- else if (letter == '#')
- {
- asm_fprintf (file, "%I");
- }
-
- if (GET_CODE (op) == REG)
- {
- if (letter == 'b' && S_REG_P (op))
- {
- asm_print_register (file, REGNO (op));
- fprintf (file, "+1");
- }
- else if (letter == 'b' && D_REG_P (op))
- {
- asm_print_register (file, HARD_B_REGNUM);
- }
- else
- {
- asm_print_register (file, REGNO (op));
- }
- return;
- }
-
- if (GET_CODE (op) == SYMBOL_REF && (letter == 'b' || letter == 'h'))
- {
- if (letter == 'b')
- asm_fprintf (file, "%I%%lo(");
- else
- asm_fprintf (file, "%I%%hi(");
-
- output_addr_const (file, op);
- fprintf (file, ")");
- return;
- }
-
- /* Get the low or high part of the operand when 'b' or 'h' modifiers
- are specified. If we already have a QImode, there is nothing to do. */
- if (GET_MODE (op) == HImode || GET_MODE (op) == VOIDmode)
- {
- if (letter == 'b')
- {
- op = m68hc11_gen_lowpart (QImode, op);
- }
- else if (letter == 'h')
- {
- op = m68hc11_gen_highpart (QImode, op);
- }
- }
-
- if (GET_CODE (op) == MEM)
- {
- rtx base = XEXP (op, 0);
- switch (GET_CODE (base))
- {
- case PRE_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "-");
- break;
-
- case POST_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "+");
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case MEM:
- gcc_assert (TARGET_M6812);
- fprintf (file, "[");
- m68hc11_print_operand_address (file, XEXP (base, 0));
- fprintf (file, "]");
- break;
-
- default:
- if (m68hc11_page0_symbol_p (base))
- fprintf (file, "*");
-
- output_address (base);
- break;
- }
- }
- else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)
- {
- REAL_VALUE_TYPE r;
- long l;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- REAL_VALUE_TO_TARGET_SINGLE (r, l);
- asm_fprintf (file, "%I0x%lx", l);
- }
- else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == DFmode)
- {
- char dstr[30];
-
- real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (op),
- sizeof (dstr), 0, 1);
- asm_fprintf (file, "%I0r%s", dstr);
- }
- else
- {
- int need_parenthesize = 0;
-
- if (letter != 'i')
- asm_fprintf (file, "%I");
- else
- need_parenthesize = must_parenthesize (op);
-
- if (need_parenthesize)
- fprintf (file, "(");
-
- output_addr_const (file, op);
- if (need_parenthesize)
- fprintf (file, ")");
- }
-}
-
-/* Returns true if the operand 'op' must be printed with parenthesis
- around it. This must be done only if there is a symbol whose name
- is a processor register. */
-static int
-must_parenthesize (rtx op)
-{
- const char *name;
-
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- name = XSTR (op, 0);
- /* Avoid a conflict between symbol name and a possible
- register. */
- return (strcasecmp (name, "a") == 0
- || strcasecmp (name, "b") == 0
- || strcasecmp (name, "d") == 0
- || strcasecmp (name, "x") == 0
- || strcasecmp (name, "y") == 0
- || strcasecmp (name, "ix") == 0
- || strcasecmp (name, "iy") == 0
- || strcasecmp (name, "pc") == 0
- || strcasecmp (name, "sp") == 0
- || strcasecmp (name, "ccr") == 0) ? 1 : 0;
-
- case PLUS:
- case MINUS:
- return must_parenthesize (XEXP (op, 0))
- || must_parenthesize (XEXP (op, 1));
-
- case MEM:
- case CONST:
- case ZERO_EXTEND:
- case SIGN_EXTEND:
- return must_parenthesize (XEXP (op, 0));
-
- case CONST_DOUBLE:
- case CONST_INT:
- case LABEL_REF:
- case CODE_LABEL:
- default:
- return 0;
- }
-}
-
-/* A C compound statement to output to stdio stream STREAM the
- assembler syntax for an instruction operand that is a memory
- reference whose address is ADDR. ADDR is an RTL expression. */
-
-static void
-m68hc11_print_operand_address (FILE *file, rtx addr)
-{
- rtx base;
- rtx offset;
- int need_parenthesis = 0;
-
- switch (GET_CODE (addr))
- {
- case REG:
- gcc_assert (REG_P (addr) && REG_OK_FOR_BASE_STRICT_P (addr));
-
- fprintf (file, "0,");
- asm_print_register (file, REGNO (addr));
- break;
-
- case MEM:
- base = XEXP (addr, 0);
- switch (GET_CODE (base))
- {
- case PRE_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- case POST_DEC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "-");
- break;
-
- case POST_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- fprintf (file, "+");
- break;
-
- case PRE_INC:
- gcc_assert (TARGET_M6812);
- fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));
- asm_print_register (file, REGNO (XEXP (base, 0)));
- break;
-
- default:
- need_parenthesis = must_parenthesize (base);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, base);
- if (need_parenthesis)
- fprintf (file, ")");
- break;
- }
- break;
-
- case PLUS:
- base = XEXP (addr, 0);
- offset = XEXP (addr, 1);
- if (!G_REG_P (base) && G_REG_P (offset))
- {
- base = XEXP (addr, 1);
- offset = XEXP (addr, 0);
- }
- if (CONSTANT_ADDRESS_P (base))
- {
- need_parenthesis = must_parenthesize (addr);
-
- gcc_assert (CONSTANT_ADDRESS_P (offset));
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, base);
- fprintf (file, "+");
- output_addr_const (file, offset);
- if (need_parenthesis)
- fprintf (file, ")");
- }
- else
- {
- gcc_assert (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base));
- if (REG_P (offset))
- {
- gcc_assert (TARGET_M6812);
- asm_print_register (file, REGNO (offset));
- fprintf (file, ",");
- asm_print_register (file, REGNO (base));
- }
- else
- {
- need_parenthesis = must_parenthesize (offset);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, offset);
- if (need_parenthesis)
- fprintf (file, ")");
- fprintf (file, ",");
- asm_print_register (file, REGNO (base));
- }
- }
- break;
-
- default:
- if (GET_CODE (addr) == CONST_INT
- && INTVAL (addr) < 0x8000 && INTVAL (addr) >= -0x8000)
- {
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
- }
- else
- {
- need_parenthesis = must_parenthesize (addr);
- if (need_parenthesis)
- fprintf (file, "(");
-
- output_addr_const (file, addr);
- if (need_parenthesis)
- fprintf (file, ")");
- }
- break;
- }
-}
-
-
-/* Splitting of some instructions. */
-
-static rtx
-m68hc11_expand_compare (enum rtx_code code, rtx op0, rtx op1)
-{
- rtx ret = 0;
-
- gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) != MODE_FLOAT);
- emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
- gen_rtx_COMPARE (VOIDmode, op0, op1)));
- ret = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
-
- return ret;
-}
-
-rtx
-m68hc11_expand_compare_and_branch (enum rtx_code code, rtx op0, rtx op1,
- rtx label)
-{
- rtx tmp;
-
- switch (GET_MODE (op0))
- {
- case QImode:
- case HImode:
- tmp = m68hc11_expand_compare (code, op0, op1);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));
- return 0;
-#if 0
-
- /* SCz: from i386.c */
- case SFmode:
- case DFmode:
- /* Don't expand the comparison early, so that we get better code
- when jump or whoever decides to reverse the comparison. */
- {
- rtvec vec;
- int use_fcomi;
-
- code = m68hc11_prepare_fp_compare_args (code, &m68hc11_compare_op0,
- &m68hc11_compare_op1);
-
- tmp = gen_rtx_fmt_ee (code, m68hc11_fp_compare_mode (code),
- m68hc11_compare_op0, m68hc11_compare_op1);
- tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- tmp = gen_rtx_SET (VOIDmode, pc_rtx, tmp);
-
- use_fcomi = ix86_use_fcomi_compare (code);
- vec = rtvec_alloc (3 + !use_fcomi);
- RTVEC_ELT (vec, 0) = tmp;
- RTVEC_ELT (vec, 1)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 18));
- RTVEC_ELT (vec, 2)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCFPmode, 17));
- if (!use_fcomi)
- RTVEC_ELT (vec, 3)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (HImode));
-
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, vec));
- return;
- }
-#endif
-
- case SImode:
- /* Expand SImode branch into multiple compare+branch. */
- {
- rtx lo[2], hi[2], label2;
- enum rtx_code code1, code2, code3;
-
- if (CONSTANT_P (op0) && !CONSTANT_P (op1))
- {
- tmp = op0;
- op0 = op1;
- op1 = tmp;
- code = swap_condition (code);
- }
- lo[0] = m68hc11_gen_lowpart (HImode, op0);
- lo[1] = m68hc11_gen_lowpart (HImode, op1);
- hi[0] = m68hc11_gen_highpart (HImode, op0);
- hi[1] = m68hc11_gen_highpart (HImode, op1);
-
- /* Otherwise, if we are doing less-than, op1 is a constant and the
- low word is zero, then we can just examine the high word. */
-
- if (GET_CODE (hi[1]) == CONST_INT && lo[1] == const0_rtx
- && (code == LT || code == LTU))
- {
- return m68hc11_expand_compare_and_branch (code, hi[0], hi[1],
- label);
- }
-
- /* Otherwise, we need two or three jumps. */
-
- label2 = gen_label_rtx ();
-
- code1 = code;
- code2 = swap_condition (code);
- code3 = unsigned_condition (code);
-
- switch (code)
- {
- case LT:
- case GT:
- case LTU:
- case GTU:
- break;
-
- case LE:
- code1 = LT;
- code2 = GT;
- break;
- case GE:
- code1 = GT;
- code2 = LT;
- break;
- case LEU:
- code1 = LTU;
- code2 = GTU;
- break;
- case GEU:
- code1 = GTU;
- code2 = LTU;
- break;
-
- case EQ:
- code1 = UNKNOWN;
- code2 = NE;
- break;
- case NE:
- code2 = UNKNOWN;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /*
- * a < b =>
- * if (hi(a) < hi(b)) goto true;
- * if (hi(a) > hi(b)) goto false;
- * if (lo(a) < lo(b)) goto true;
- * false:
- */
- if (code1 != UNKNOWN)
- m68hc11_expand_compare_and_branch (code1, hi[0], hi[1], label);
- if (code2 != UNKNOWN)
- m68hc11_expand_compare_and_branch (code2, hi[0], hi[1], label2);
-
- m68hc11_expand_compare_and_branch (code3, lo[0], lo[1], label);
-
- if (code2 != UNKNOWN)
- emit_label (label2);
- return 0;
- }
-
- default:
- gcc_unreachable ();
- }
- return 0;
-}
-
-/* Return the increment/decrement mode of a MEM if it is such.
- Return CONST if it is anything else. */
-static int
-autoinc_mode (rtx x)
-{
- if (GET_CODE (x) != MEM)
- return CONST;
-
- x = XEXP (x, 0);
- if (GET_CODE (x) == PRE_INC
- || GET_CODE (x) == PRE_DEC
- || GET_CODE (x) == POST_INC
- || GET_CODE (x) == POST_DEC)
- return GET_CODE (x);
-
- return CONST;
-}
-
-static int
-m68hc11_make_autoinc_notes (rtx *x, void *data)
-{
- rtx insn;
-
- switch (GET_CODE (*x))
- {
- case PRE_DEC:
- case PRE_INC:
- case POST_DEC:
- case POST_INC:
- insn = (rtx) data;
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, XEXP (*x, 0),
- REG_NOTES (insn));
- return -1;
-
- default:
- return 0;
- }
-}
-
-/* Split a DI, SI or HI move into several smaller move operations.
- The scratch register 'scratch' is used as a temporary to load
- store intermediate values. It must be a hard register. */
-void
-m68hc11_split_move (rtx to, rtx from, rtx scratch)
-{
- rtx low_to, low_from;
- rtx high_to, high_from;
- rtx insn;
- enum machine_mode mode;
- int offset = 0;
- int autoinc_from = autoinc_mode (from);
- int autoinc_to = autoinc_mode (to);
-
- mode = GET_MODE (to);
-
- /* If the TO and FROM contain autoinc modes that are not compatible
- together (one pop and the other a push), we must change one to
- an offsetable operand and generate an appropriate add at the end. */
- if (TARGET_M6812 && GET_MODE_SIZE (mode) > 2)
- {
- rtx reg;
- int code;
-
- /* The source uses an autoinc mode which is not compatible with
- a split (this would result in a word swap). */
- if (autoinc_from == PRE_INC || autoinc_from == POST_DEC)
- {
- code = GET_CODE (XEXP (from, 0));
- reg = XEXP (XEXP (from, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (from));
- if (code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
- if (code == POST_DEC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- return;
- }
-
- /* Likewise for destination. */
- if (autoinc_to == PRE_INC || autoinc_to == POST_DEC)
- {
- code = GET_CODE (XEXP (to, 0));
- reg = XEXP (XEXP (to, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (to));
- if (code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
- if (code == POST_DEC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- return;
- }
-
- /* The source and destination auto increment modes must be compatible
- with each other: same direction. */
- if ((autoinc_to != autoinc_from
- && autoinc_to != CONST && autoinc_from != CONST)
- /* The destination address register must not be used within
- the source operand because the source address would change
- while doing the copy. */
- || (autoinc_to != CONST
- && reg_mentioned_p (XEXP (XEXP (to, 0), 0), from)
- && !IS_STACK_PUSH (to)))
- {
- /* Must change the destination. */
- code = GET_CODE (XEXP (to, 0));
- reg = XEXP (XEXP (to, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (to));
- if (code == PRE_DEC || code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_DEC || code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- m68hc11_split_move (gen_rtx_MEM (GET_MODE (to), reg), from, scratch);
- if (code == POST_DEC || code == POST_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- return;
- }
-
- /* Likewise, the source address register must not be used within
- the destination operand. */
- if (autoinc_from != CONST
- && reg_mentioned_p (XEXP (XEXP (from, 0), 0), to)
- && !IS_STACK_PUSH (to))
- {
- /* Must change the source. */
- code = GET_CODE (XEXP (from, 0));
- reg = XEXP (XEXP (from, 0), 0);
- offset = GET_MODE_SIZE (GET_MODE (from));
- if (code == PRE_DEC || code == POST_DEC)
- offset = -offset;
-
- if (code == PRE_DEC || code == PRE_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
- m68hc11_split_move (to, gen_rtx_MEM (GET_MODE (from), reg), scratch);
- if (code == POST_DEC || code == POST_INC)
- emit_insn (gen_addhi3 (reg, reg, GEN_INT (offset)));
-
- return;
- }
- }
-
- if (GET_MODE_SIZE (mode) == 8)
- mode = SImode;
- else if (GET_MODE_SIZE (mode) == 4)
- mode = HImode;
- else
- mode = QImode;
-
- if (TARGET_M6812
- && IS_STACK_PUSH (to)
- && reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM), from))
- {
- if (mode == SImode)
- {
- offset = 4;
- }
- else if (mode == HImode)
- {
- offset = 2;
- }
- else
- offset = 0;
- }
-
- low_to = m68hc11_gen_lowpart (mode, to);
- high_to = m68hc11_gen_highpart (mode, to);
-
- low_from = m68hc11_gen_lowpart (mode, from);
- high_from = m68hc11_gen_highpart (mode, from);
-
- if (offset)
- {
- high_from = adjust_address (high_from, mode, offset);
- low_from = high_from;
- }
-
- /* When copying with a POST_INC mode, we must copy the
- high part and then the low part to guarantee a correct
- 32/64-bit copy. */
- if (TARGET_M6812
- && GET_MODE_SIZE (mode) >= 2
- && autoinc_from != autoinc_to
- && (autoinc_from == POST_INC || autoinc_to == POST_INC))
- {
- rtx swap;
-
- swap = low_to;
- low_to = high_to;
- high_to = swap;
-
- swap = low_from;
- low_from = high_from;
- high_from = swap;
- }
- if (mode == SImode)
- {
- m68hc11_split_move (low_to, low_from, scratch);
- m68hc11_split_move (high_to, high_from, scratch);
- }
- else if (H_REG_P (to) || H_REG_P (from)
- || (low_from == const0_rtx
- && high_from == const0_rtx
- && ! push_operand (to, GET_MODE (to))
- && ! H_REG_P (scratch))
- || (TARGET_M6812
- && (!m68hc11_register_indirect_p (from, GET_MODE (from))
- || m68hc11_small_indexed_indirect_p (from,
- GET_MODE (from)))
- && (!m68hc11_register_indirect_p (to, GET_MODE (to))
- || m68hc11_small_indexed_indirect_p (to, GET_MODE (to)))))
- {
- insn = emit_move_insn (low_to, low_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
-
- insn = emit_move_insn (high_to, high_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- }
- else
- {
- insn = emit_move_insn (scratch, low_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- insn = emit_move_insn (low_to, scratch);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
-
- insn = emit_move_insn (scratch, high_from);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- insn = emit_move_insn (high_to, scratch);
- for_each_rtx (&PATTERN (insn), m68hc11_make_autoinc_notes, insn);
- }
-}
-
-static rtx
-simplify_logical (enum machine_mode mode, int code, rtx operand, rtx *result)
-{
- int val;
- int mask;
-
- *result = 0;
- if (GET_CODE (operand) != CONST_INT)
- return operand;
-
- if (mode == HImode)
- mask = 0x0ffff;
- else
- mask = 0x0ff;
-
- val = INTVAL (operand);
- switch (code)
- {
- case IOR:
- if ((val & mask) == 0)
- return 0;
- if ((val & mask) == mask)
- *result = constm1_rtx;
- break;
-
- case AND:
- if ((val & mask) == 0)
- *result = const0_rtx;
- if ((val & mask) == mask)
- return 0;
- break;
-
- case XOR:
- if ((val & mask) == 0)
- return 0;
- break;
- }
- return operand;
-}
-
-static void
-m68hc11_emit_logical (enum machine_mode mode, enum rtx_code code, rtx *operands)
-{
- rtx result;
- int need_copy;
-
- need_copy = (rtx_equal_p (operands[0], operands[1])
- || rtx_equal_p (operands[0], operands[2])) ? 0 : 1;
-
- operands[1] = simplify_logical (mode, code, operands[1], &result);
- operands[2] = simplify_logical (mode, code, operands[2], &result);
-
- if (result && GET_CODE (result) == CONST_INT)
- {
- if (!H_REG_P (operands[0]) && operands[3]
- && (INTVAL (result) != 0 || IS_STACK_PUSH (operands[0])))
- {
- emit_move_insn (operands[3], result);
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_move_insn (operands[0], result);
- }
- }
- else if (operands[1] != 0 && operands[2] != 0)
- {
- if (!H_REG_P (operands[0]) && operands[3])
- {
- emit_move_insn (operands[3], operands[1]);
- emit_insn (gen_rtx_SET (mode,
- operands[3],
- gen_rtx_fmt_ee (code, mode,
- operands[3], operands[2])));
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_insn (gen_rtx_SET (mode, operands[0],
- gen_rtx_fmt_ee (code, mode,
- operands[0], operands[2])));
- }
- }
-
- /* The logical operation is similar to a copy. */
- else if (need_copy)
- {
- rtx src;
-
- if (GET_CODE (operands[1]) == CONST_INT)
- src = operands[2];
- else
- src = operands[1];
-
- if (!H_REG_P (operands[0]) && !H_REG_P (src))
- {
- emit_move_insn (operands[3], src);
- emit_move_insn (operands[0], operands[3]);
- }
- else
- {
- emit_move_insn (operands[0], src);
- }
- }
-}
-
-void
-m68hc11_split_logical (enum machine_mode mode, enum rtx_code code,
- rtx *operands)
-{
- rtx low[4];
- rtx high[4];
-
- low[0] = m68hc11_gen_lowpart (mode, operands[0]);
- low[1] = m68hc11_gen_lowpart (mode, operands[1]);
- low[2] = m68hc11_gen_lowpart (mode, operands[2]);
-
- high[0] = m68hc11_gen_highpart (mode, operands[0]);
- high[1] = m68hc11_gen_highpart (mode, operands[1]);
- high[2] = m68hc11_gen_highpart (mode, operands[2]);
-
- low[3] = operands[3];
- high[3] = operands[3];
- if (mode == SImode)
- {
- m68hc11_split_logical (HImode, code, low);
- m68hc11_split_logical (HImode, code, high);
- return;
- }
-
- m68hc11_emit_logical (mode, code, low);
- m68hc11_emit_logical (mode, code, high);
-}
-
-
-/* Code generation. */
-
-void
-m68hc11_output_swap (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
-{
- /* We have to be careful with the cc_status. An address register swap
- is generated for some comparison. The comparison is made with D
- but the branch really uses the address register. See the split
- pattern for compare. The xgdx/xgdy preserve the flags but after
- the exchange, the flags will reflect to the value of X and not D.
- Tell this by setting the cc_status according to the cc_prev_status. */
- if (X_REG_P (operands[1]) || X_REG_P (operands[0]))
- {
- if (cc_prev_status.value1 != 0
- && (D_REG_P (cc_prev_status.value1)
- || X_REG_P (cc_prev_status.value1)))
- {
- cc_status = cc_prev_status;
- if (D_REG_P (cc_status.value1))
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_X_REGNUM);
- else
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_D_REGNUM);
- }
- else
- CC_STATUS_INIT;
-
- output_asm_insn ("xgdx", operands);
- }
- else
- {
- if (cc_prev_status.value1 != 0
- && (D_REG_P (cc_prev_status.value1)
- || Y_REG_P (cc_prev_status.value1)))
- {
- cc_status = cc_prev_status;
- if (D_REG_P (cc_status.value1))
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_Y_REGNUM);
- else
- cc_status.value1 = gen_rtx_REG (GET_MODE (cc_status.value1),
- HARD_D_REGNUM);
- }
- else
- CC_STATUS_INIT;
-
- output_asm_insn ("xgdy", operands);
- }
-}
-
-/* Returns 1 if the next insn after 'insn' is a test of the register 'reg'.
- This is used to decide whether a move that set flags should be used
- instead. */
-int
-next_insn_test_reg (rtx insn, rtx reg)
-{
- rtx body;
-
- insn = next_nonnote_insn (insn);
- if (GET_CODE (insn) != INSN)
- return 0;
-
- body = PATTERN (insn);
- if (sets_cc0_p (body) != 1)
- return 0;
-
- if (rtx_equal_p (XEXP (body, 1), reg) == 0)
- return 0;
-
- return 1;
-}
-
-/* Generate the code to move a 16-bit operand into another one. */
-
-void
-m68hc11_gen_movhi (rtx insn, rtx *operands)
-{
- int reg;
-
- /* Move a register or memory to the same location.
- This is possible because such insn can appear
- in a non-optimizing mode. */
- if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
- {
- cc_status = cc_prev_status;
- return;
- }
-
- if (TARGET_M6812)
- {
- rtx from = operands[1];
- rtx to = operands[0];
-
- if (IS_STACK_PUSH (to) && H_REG_P (from))
- {
- cc_status = cc_prev_status;
- switch (REGNO (from))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- case HARD_D_REGNUM:
- output_asm_insn ("psh%1", operands);
- break;
- case HARD_SP_REGNUM:
- output_asm_insn ("sts\t2,-sp", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- if (IS_STACK_POP (from) && H_REG_P (to))
- {
- cc_status = cc_prev_status;
- switch (REGNO (to))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- case HARD_D_REGNUM:
- output_asm_insn ("pul%0", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("tfr\t%1,%0", operands);
- }
- else if (H_REG_P (operands[0]))
- {
- if (SP_REG_P (operands[0]))
- output_asm_insn ("lds\t%1", operands);
- else
- output_asm_insn ("ld%0\t%1", operands);
- }
- else if (H_REG_P (operands[1]))
- {
- if (SP_REG_P (operands[1]))
- output_asm_insn ("sts\t%0", operands);
- else
- output_asm_insn ("st%1\t%0", operands);
- }
-
- /* The 68hc12 does not support (MEM:HI (MEM:HI)) with the movw
- instruction. We have to use a scratch register as temporary location.
- Trying to use a specific pattern or constrain failed. */
- else if (GET_CODE (to) == MEM && GET_CODE (XEXP (to, 0)) == MEM)
- {
- rtx ops[4];
-
- ops[0] = to;
- ops[2] = from;
- ops[3] = 0;
- if (dead_register_here (insn, d_reg))
- ops[1] = d_reg;
- else if (dead_register_here (insn, ix_reg))
- ops[1] = ix_reg;
- else if (dead_register_here (insn, iy_reg))
- ops[1] = iy_reg;
- else
- {
- ops[1] = d_reg;
- ops[3] = d_reg;
- output_asm_insn ("psh%3", ops);
- }
-
- ops[0] = to;
- ops[2] = from;
- output_asm_insn ("ld%1\t%2", ops);
- output_asm_insn ("st%1\t%0", ops);
- if (ops[3])
- output_asm_insn ("pul%3", ops);
- }
-
- /* Use movw for non-null constants or when we are clearing
- a volatile memory reference. However, this is possible
- only if the memory reference has a small offset or is an
- absolute address. */
- else if (GET_CODE (from) == CONST_INT
- && INTVAL (from) == 0
- && (MEM_VOLATILE_P (to) == 0
- || m68hc11_small_indexed_indirect_p (to, HImode) == 0))
- {
- output_asm_insn ("clr\t%h0", operands);
- output_asm_insn ("clr\t%b0", operands);
- }
- else
- {
- if ((m68hc11_register_indirect_p (from, GET_MODE (from))
- && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
- || (m68hc11_register_indirect_p (to, GET_MODE (to))
- && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
- {
- rtx ops[3];
-
- if (operands[2])
- {
- ops[0] = operands[2];
- ops[1] = from;
- ops[2] = 0;
- m68hc11_gen_movhi (insn, ops);
- ops[0] = to;
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- return;
- }
- else
- {
- /* !!!! SCz wrong here. */
- fatal_insn ("move insn not handled", insn);
- }
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("movw\t%1,%0", operands);
- }
- }
- return;
- }
-
- if (IS_STACK_POP (operands[1]) && H_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- switch (REGNO (operands[0]))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- output_asm_insn ("pul%0", operands);
- break;
- case HARD_D_REGNUM:
- output_asm_insn ("pula", operands);
- output_asm_insn ("pulb", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
- /* Some moves to a hard register are special. Not all of them
- are really supported and we have to use a temporary
- location to provide them (either the stack of a temp var). */
- if (H_REG_P (operands[0]))
- {
- switch (REGNO (operands[0]))
- {
- case HARD_D_REGNUM:
- if (X_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else if (next_insn_test_reg (insn, operands[0]))
- {
- output_asm_insn ("stx\t%t0\n\tldd\t%t0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("pshx\n\tpula\n\tpulb", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- /* %t means *ZTMP scratch register. */
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldd\t%t1", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- CC_STATUS_INIT;
- if (ix_reg == 0)
- create_regs_rtx ();
- if (optimize == 0 || dead_register_here (insn, ix_reg) == 0)
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (IS_STACK_POP (operands[1]))
- {
- output_asm_insn ("pula\n\tpulb", operands);
- }
- else if (GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) == 0)
- {
- output_asm_insn ("clra\n\tclrb", operands);
- }
- else
- {
- output_asm_insn ("ldd\t%1", operands);
- }
- break;
-
- case HARD_X_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else if (next_insn_test_reg (insn, operands[0]))
- {
- output_asm_insn ("std\t%t0\n\tldx\t%t0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("pshb", operands);
- output_asm_insn ("psha", operands);
- output_asm_insn ("pulx", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- /* When both D and Y are dead, use the sequence xgdy, xgdx
- to move Y into X. The D and Y registers are modified. */
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM)
- && dead_register_here (insn, d_reg))
- {
- output_asm_insn ("xgdy", operands);
- output_asm_insn ("xgdx", operands);
- CC_STATUS_INIT;
- }
- else if (!optimize_size)
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- }
- else
- {
- CC_STATUS_INIT;
- output_asm_insn ("pshy", operands);
- output_asm_insn ("pulx", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- /* tsx, tsy preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tsx", operands);
- }
- else
- {
- output_asm_insn ("ldx\t%1", operands);
- }
- break;
-
- case HARD_Y_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("std\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- }
- }
- else if (X_REG_P (operands[1]))
- {
- /* When both D and X are dead, use the sequence xgdx, xgdy
- to move X into Y. The D and X registers are modified. */
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM)
- && dead_register_here (insn, d_reg))
- {
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("xgdy", operands);
- CC_STATUS_INIT;
- }
- else if (!optimize_size)
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- }
- else
- {
- CC_STATUS_INIT;
- output_asm_insn ("pshx", operands);
- output_asm_insn ("puly", operands);
- }
- }
- else if (SP_REG_P (operands[1]))
- {
- /* tsx, tsy preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tsy", operands);
- }
- else
- {
- output_asm_insn ("ldy\t%1", operands);
- }
- break;
-
- case HARD_SP_REGNUM:
- if (D_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("txs", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (X_REG_P (operands[1]))
- {
- /* tys, txs preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("txs", operands);
- }
- else if (Y_REG_P (operands[1]))
- {
- /* tys, txs preserve the flags */
- cc_status = cc_prev_status;
- output_asm_insn ("tys", operands);
- }
- else
- {
- /* lds sets the flags but the des does not. */
- CC_STATUS_INIT;
- output_asm_insn ("lds\t%1", operands);
- output_asm_insn ("des", operands);
- }
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
- return;
- }
- if (SP_REG_P (operands[1]) && REG_P (operands[0])
- && REGNO (operands[0]) == HARD_FRAME_POINTER_REGNUM)
- {
- output_asm_insn ("sts\t%0", operands);
- return;
- }
-
- if (IS_STACK_PUSH (operands[0]) && H_REG_P (operands[1]))
- {
- cc_status = cc_prev_status;
- switch (REGNO (operands[1]))
- {
- case HARD_X_REGNUM:
- case HARD_Y_REGNUM:
- output_asm_insn ("psh%1", operands);
- break;
- case HARD_D_REGNUM:
- output_asm_insn ("pshb", operands);
- output_asm_insn ("psha", operands);
- break;
- default:
- gcc_unreachable ();
- }
- return;
- }
-
- /* Operand 1 must be a hard register. */
- if (!H_REG_P (operands[1]))
- {
- fatal_insn ("invalid operand in the instruction", insn);
- }
-
- reg = REGNO (operands[1]);
- switch (reg)
- {
- case HARD_D_REGNUM:
- output_asm_insn ("std\t%0", operands);
- break;
-
- case HARD_X_REGNUM:
- output_asm_insn ("stx\t%0", operands);
- break;
-
- case HARD_Y_REGNUM:
- output_asm_insn ("sty\t%0", operands);
- break;
-
- case HARD_SP_REGNUM:
- if (ix_reg == 0)
- create_regs_rtx ();
-
- if (REG_P (operands[0]) && REGNO (operands[0]) == SOFT_TMP_REGNUM)
- {
- output_asm_insn ("pshx", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("inx", operands);
- output_asm_insn ("inx", operands);
- output_asm_insn ("stx\t%0", operands);
- output_asm_insn ("pulx", operands);
- }
-
- else if (reg_mentioned_p (ix_reg, operands[0]))
- {
- output_asm_insn ("sty\t%t0", operands);
- output_asm_insn ("tsy", operands);
- output_asm_insn ("sty\t%0", operands);
- output_asm_insn ("ldy\t%t0", operands);
- }
- else
- {
- output_asm_insn ("stx\t%t0", operands);
- output_asm_insn ("tsx", operands);
- output_asm_insn ("stx\t%0", operands);
- output_asm_insn ("ldx\t%t0", operands);
- }
- CC_STATUS_INIT;
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
-}
-
-void
-m68hc11_gen_movqi (rtx insn, rtx *operands)
-{
- /* Move a register or memory to the same location.
- This is possible because such insn can appear
- in a non-optimizing mode. */
- if (operands[0] == operands[1] || rtx_equal_p (operands[0], operands[1]))
- {
- cc_status = cc_prev_status;
- return;
- }
-
- if (TARGET_M6812)
- {
-
- if (H_REG_P (operands[0]) && H_REG_P (operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("tfr\t%1,%0", operands);
- }
- else if (H_REG_P (operands[0]))
- {
- if (IS_STACK_POP (operands[1]))
- output_asm_insn ("pul%b0", operands);
- else if (Q_REG_P (operands[0]))
- output_asm_insn ("lda%0\t%b1", operands);
- else if (D_REG_P (operands[0]))
- output_asm_insn ("ldab\t%b1", operands);
- else
- goto m6811_move;
- }
- else if (H_REG_P (operands[1]))
- {
- if (Q_REG_P (operands[1]))
- output_asm_insn ("sta%1\t%b0", operands);
- else if (D_REG_P (operands[1]))
- output_asm_insn ("stab\t%b0", operands);
- else
- goto m6811_move;
- }
- else
- {
- rtx from = operands[1];
- rtx to = operands[0];
-
- if ((m68hc11_register_indirect_p (from, GET_MODE (from))
- && !m68hc11_small_indexed_indirect_p (from, GET_MODE (from)))
- || (m68hc11_register_indirect_p (to, GET_MODE (to))
- && !m68hc11_small_indexed_indirect_p (to, GET_MODE (to))))
- {
- rtx ops[3];
-
- if (operands[2])
- {
- ops[0] = operands[2];
- ops[1] = from;
- ops[2] = 0;
- m68hc11_gen_movqi (insn, ops);
- ops[0] = to;
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- }
- else
- {
- /* !!!! SCz wrong here. */
- fatal_insn ("move insn not handled", insn);
- }
- }
- else
- {
- if (GET_CODE (from) == CONST_INT && INTVAL (from) == 0)
- {
- output_asm_insn ("clr\t%b0", operands);
- }
- else
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn ("movb\t%b1,%b0", operands);
- }
- }
- }
- return;
- }
-
- m6811_move:
- if (H_REG_P (operands[0]))
- {
- switch (REGNO (operands[0]))
- {
- case HARD_B_REGNUM:
- case HARD_D_REGNUM:
- if (X_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_X_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldab\t%T0", operands);
- }
- }
- else if (Y_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_Y_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldab\t%T0", operands);
- }
- }
- else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
- && !DA_REG_P (operands[1]))
- {
- output_asm_insn ("ldab\t%b1", operands);
- }
- else if (DA_REG_P (operands[1]))
- {
- output_asm_insn ("tab", operands);
- }
- else
- {
- cc_status = cc_prev_status;
- return;
- }
- break;
-
- case HARD_A_REGNUM:
- if (X_REG_P (operands[1]))
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldaa\t%T0", operands);
- }
- else if (Y_REG_P (operands[1]))
- {
- output_asm_insn ("sty\t%t1", operands);
- output_asm_insn ("ldaa\t%T0", operands);
- }
- else if (!DB_REG_P (operands[1]) && !D_REG_P (operands[1])
- && !DA_REG_P (operands[1]))
- {
- output_asm_insn ("ldaa\t%b1", operands);
- }
- else if (!DA_REG_P (operands[1]))
- {
- output_asm_insn ("tba", operands);
- }
- else
- {
- cc_status = cc_prev_status;
- }
- break;
-
- case HARD_X_REGNUM:
- if (D_REG_P (operands[1]))
- {
- if (optimize && find_regno_note (insn, REG_DEAD, HARD_D_REGNUM))
- {
- m68hc11_output_swap (insn, operands);
- }
- else
- {
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- }
- CC_STATUS_INIT;
- }
- else if (Y_REG_P (operands[1]))
- {
- output_asm_insn ("sty\t%t0", operands);
- output_asm_insn ("ldx\t%t0", operands);
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- output_asm_insn ("ldx\t%1", operands);
- }
- else if (dead_register_here (insn, d_reg))
- {
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdx", operands);
- }
- else if (!reg_mentioned_p (operands[0], operands[1]))
- {
- output_asm_insn ("xgdx", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdx", operands);
- }
- else
- {
- output_asm_insn ("pshb", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldx\t%t1", operands);
- output_asm_insn ("pulb", operands);
- CC_STATUS_INIT;
- }
- break;
-
- case HARD_Y_REGNUM:
- if (D_REG_P (operands[1]))
- {
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- CC_STATUS_INIT;
- }
- else if (X_REG_P (operands[1]))
- {
- output_asm_insn ("stx\t%t1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- CC_STATUS_INIT;
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- output_asm_insn ("ldy\t%1", operands);
- }
- else if (dead_register_here (insn, d_reg))
- {
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdy", operands);
- }
- else if (!reg_mentioned_p (operands[0], operands[1]))
- {
- output_asm_insn ("xgdy", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("xgdy", operands);
- }
- else
- {
- output_asm_insn ("pshb", operands);
- output_asm_insn ("ldab\t%b1", operands);
- output_asm_insn ("stab\t%T1", operands);
- output_asm_insn ("ldy\t%t1", operands);
- output_asm_insn ("pulb", operands);
- CC_STATUS_INIT;
- }
- break;
-
- default:
- fatal_insn ("invalid register in the instruction", insn);
- break;
- }
- }
- else if (H_REG_P (operands[1]))
- {
- switch (REGNO (operands[1]))
- {
- case HARD_D_REGNUM:
- case HARD_B_REGNUM:
- output_asm_insn ("stab\t%b0", operands);
- break;
-
- case HARD_A_REGNUM:
- output_asm_insn ("staa\t%b0", operands);
- break;
-
- case HARD_X_REGNUM:
- output_asm_insn ("xgdx\n\tstab\t%b0\n\txgdx", operands);
- break;
-
- case HARD_Y_REGNUM:
- output_asm_insn ("xgdy\n\tstab\t%b0\n\txgdy", operands);
- break;
-
- default:
- fatal_insn ("invalid register in the move instruction", insn);
- break;
- }
- return;
- }
- else
- {
- fatal_insn ("operand 1 must be a hard register", insn);
- }
-}
-
-/* Generate the code for a ROTATE or ROTATERT on a QI or HI mode.
- The source and destination must be D or A and the shift must
- be a constant. */
-void
-m68hc11_gen_rotate (enum rtx_code code, rtx insn, rtx operands[])
-{
- int val;
-
- if (GET_CODE (operands[2]) != CONST_INT
- || (!D_REG_P (operands[0]) && !DA_REG_P (operands[0])))
- fatal_insn ("invalid rotate insn", insn);
-
- val = INTVAL (operands[2]);
- if (code == ROTATERT)
- val = GET_MODE_SIZE (GET_MODE (operands[0])) * BITS_PER_UNIT - val;
-
- if (GET_MODE (operands[0]) != QImode)
- CC_STATUS_INIT;
-
- /* Rotate by 8-bits if the shift is within [5..11]. */
- if (val >= 5 && val <= 11)
- {
- if (TARGET_M6812)
- output_asm_insn ("exg\ta,b", operands);
- else
- {
- output_asm_insn ("psha", operands);
- output_asm_insn ("tba", operands);
- output_asm_insn ("pulb", operands);
- }
- val -= 8;
- }
-
- /* If the shift is big, invert the rotation. */
- else if (val >= 12)
- {
- val = val - 16;
- }
-
- if (val > 0)
- {
- while (--val >= 0)
- {
- /* Set the carry to bit-15, but don't change D yet. */
- if (GET_MODE (operands[0]) != QImode)
- {
- output_asm_insn ("asra", operands);
- output_asm_insn ("rola", operands);
- }
-
- /* Rotate B first to move the carry to bit-0. */
- if (D_REG_P (operands[0]))
- output_asm_insn ("rolb", operands);
-
- if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
- output_asm_insn ("rola", operands);
- }
- }
- else
- {
- while (++val <= 0)
- {
- /* Set the carry to bit-8 of D. */
- if (GET_MODE (operands[0]) != QImode)
- output_asm_insn ("tap", operands);
-
- /* Rotate B first to move the carry to bit-7. */
- if (D_REG_P (operands[0]))
- output_asm_insn ("rorb", operands);
-
- if (GET_MODE (operands[0]) != QImode || DA_REG_P (operands[0]))
- output_asm_insn ("rora", operands);
- }
- }
-}
-
-
-
-/* Store in cc_status the expressions that the condition codes will
- describe after execution of an instruction whose pattern is EXP.
- Do not alter them if the instruction would not alter the cc's. */
-
-void
-m68hc11_notice_update_cc (rtx exp, rtx insn ATTRIBUTE_UNUSED)
-{
- /* recognize SET insn's. */
- if (GET_CODE (exp) == SET)
- {
- /* Jumps do not alter the cc's. */
- if (SET_DEST (exp) == pc_rtx)
- ;
-
- /* NOTE: most instructions don't affect the carry bit, but the
- bhi/bls/bhs/blo instructions use it. This isn't mentioned in
- the conditions.h header. */
-
- /* Function calls clobber the cc's. */
- else if (GET_CODE (SET_SRC (exp)) == CALL)
- {
- CC_STATUS_INIT;
- }
-
- /* Tests and compares set the cc's in predictable ways. */
- else if (SET_DEST (exp) == cc0_rtx)
- {
- cc_status.flags = 0;
- cc_status.value1 = XEXP (exp, 0);
- if (GET_CODE (XEXP (exp, 1)) == COMPARE
- && XEXP (XEXP (exp, 1), 1) == CONST0_RTX (GET_MODE (XEXP (XEXP (exp, 1), 0))))
- cc_status.value2 = XEXP (XEXP (exp, 1), 0);
- else
- cc_status.value2 = XEXP (exp, 1);
- }
- else
- {
- /* All other instructions affect the condition codes. */
- cc_status.flags = 0;
- cc_status.value1 = XEXP (exp, 0);
- cc_status.value2 = XEXP (exp, 1);
- }
- }
- else
- {
- /* Default action if we haven't recognized something
- and returned earlier. */
- CC_STATUS_INIT;
- }
-
- if (cc_status.value2 != 0)
- switch (GET_CODE (cc_status.value2))
- {
- /* These logical operations can generate several insns.
- The flags are setup according to what is generated. */
- case IOR:
- case XOR:
- case AND:
- break;
-
- /* The (not ...) generates several 'com' instructions for
- non QImode. We have to invalidate the flags. */
- case NOT:
- if (GET_MODE (cc_status.value2) != QImode)
- CC_STATUS_INIT;
- break;
-
- case PLUS:
- case MINUS:
- case MULT:
- case DIV:
- case UDIV:
- case MOD:
- case UMOD:
- case NEG:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- /* The asl sets the overflow bit in such a way that this
- makes the flags unusable for a next compare insn. */
- case ASHIFT:
- case ROTATE:
- case ROTATERT:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- /* A load/store instruction does not affect the carry. */
- case MEM:
- case SYMBOL_REF:
- case REG:
- case CONST_INT:
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
-
- default:
- break;
- }
- if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
-
- else if (cc_status.value1 && side_effects_p (cc_status.value1))
- cc_status.value1 = 0;
-
- else if (cc_status.value2 && side_effects_p (cc_status.value2))
- cc_status.value2 = 0;
-}
-
-/* The current instruction does not affect the flags but changes
- the register 'reg'. See if the previous flags can be kept for the
- next instruction to avoid a comparison. */
-void
-m68hc11_notice_keep_cc (rtx reg)
-{
- if (reg == 0
- || cc_prev_status.value1 == 0
- || rtx_equal_p (reg, cc_prev_status.value1)
- || (cc_prev_status.value2
- && reg_mentioned_p (reg, cc_prev_status.value2)))
- CC_STATUS_INIT;
- else
- cc_status = cc_prev_status;
-}
-
-
-
-/* Machine Specific Reorg. */
-
-/* Z register replacement:
-
- GCC treats the Z register as an index base address register like
- X or Y. In general, it uses it during reload to compute the address
- of some operand. This helps the reload pass to avoid to fall into the
- register spill failure.
-
- The Z register is in the A_REGS class. In the machine description,
- the 'A' constraint matches it. The 'x' or 'y' constraints do not.
-
- It can appear everywhere an X or Y register can appear, except for
- some templates in the clobber section (when a clobber of X or Y is asked).
- For a given instruction, the template must ensure that no more than
- 2 'A' registers are used. Otherwise, the register replacement is not
- possible.
-
- To replace the Z register, the algorithm is not terrific:
- 1. Insns that do not use the Z register are not changed
- 2. When a Z register is used, we scan forward the insns to see
- a potential register to use: either X or Y and sometimes D.
- We stop when a call, a label or a branch is seen, or when we
- detect that both X and Y are used (probably at different times, but it does
- not matter).
- 3. The register that will be used for the replacement of Z is saved
- in a .page0 register or on the stack. If the first instruction that
- used Z, uses Z as an input, the value is loaded from another .page0
- register. The replacement register is pushed on the stack in the
- rare cases where a compare insn uses Z and we couldn't find if X/Y
- are dead.
- 4. The Z register is replaced in all instructions until we reach
- the end of the Z-block, as detected by step 2.
- 5. If we detect that Z is still alive, its value is saved.
- If the replacement register is alive, its old value is loaded.
-
- The Z register can be disabled with -ffixed-z.
-*/
-
-struct replace_info
-{
- rtx first;
- rtx replace_reg;
- int need_save_z;
- int must_load_z;
- int must_save_reg;
- int must_restore_reg;
- rtx last;
- int regno;
- int x_used;
- int y_used;
- int can_use_d;
- int found_call;
- int z_died;
- int z_set_count;
- rtx z_value;
- int must_push_reg;
- int save_before_last;
- int z_loaded_with_sp;
-};
-
-static int m68hc11_check_z_replacement (rtx, struct replace_info *);
-static void m68hc11_find_z_replacement (rtx, struct replace_info *);
-static void m68hc11_z_replacement (rtx);
-static void m68hc11_reassign_regs (rtx);
-
-int z_replacement_completed = 0;
-
-/* Analyze the insn to find out which replacement register to use and
- the boundaries of the replacement.
- Returns 0 if we reached the last insn to be replaced, 1 if we can
- continue replacement in next insns. */
-
-static int
-m68hc11_check_z_replacement (rtx insn, struct replace_info *info)
-{
- int this_insn_uses_ix;
- int this_insn_uses_iy;
- int this_insn_uses_z;
- int this_insn_uses_z_in_dst;
- int this_insn_uses_d;
- rtx body;
- int z_dies_here;
-
- /* A call is said to clobber the Z register, we don't need
- to save the value of Z. We also don't need to restore
- the replacement register (unless it is used by the call). */
- if (GET_CODE (insn) == CALL_INSN)
- {
- body = PATTERN (insn);
-
- info->can_use_d = 0;
-
- /* If the call is an indirect call with Z, we have to use the
- Y register because X can be used as an input (D+X).
- We also must not save Z nor restore Y. */
- if (reg_mentioned_p (z_reg, body))
- {
- insn = NEXT_INSN (insn);
- info->x_used = 1;
- info->y_used = 0;
- info->found_call = 1;
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- info->need_save_z = 0;
- return 0;
- }
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == BARRIER || GET_CODE (insn) == ASM_INPUT)
- return 0;
-
- if (GET_CODE (insn) == JUMP_INSN)
- {
- if (reg_mentioned_p (z_reg, insn) == 0)
- return 0;
-
- info->can_use_d = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->need_save_z = 0;
- info->last = NEXT_INSN (insn);
- return 0;
- }
- if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
- {
- return 1;
- }
-
- /* Z register dies here. */
- z_dies_here = find_regno_note (insn, REG_DEAD, HARD_Z_REGNUM) != NULL;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == SET)
- {
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- /* Condition code is set here. We have to restore the X/Y and
- save into Z before any test/compare insn because once we save/restore
- we can change the condition codes. When the compare insn uses Z and
- we can't use X/Y, the comparison is made with the *ZREG soft register
- (this is supported by cmphi, cmpqi, tsthi, tstqi patterns). */
- if (dst == cc0_rtx)
- {
- if ((GET_CODE (src) == REG && REGNO (src) == HARD_Z_REGNUM)
- || (GET_CODE (src) == COMPARE &&
- ((rtx_equal_p (XEXP (src, 0), z_reg)
- && H_REG_P (XEXP (src, 1)))
- || (rtx_equal_p (XEXP (src, 1), z_reg)
- && H_REG_P (XEXP (src, 0))))))
- {
- if (insn == info->first)
- {
- info->must_load_z = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->need_save_z = 0;
- info->found_call = 1;
- info->regno = SOFT_Z_REGNUM;
- info->last = NEXT_INSN (insn);
- }
- return 0;
- }
- if (reg_mentioned_p (z_reg, src) == 0)
- {
- info->can_use_d = 0;
- return 0;
- }
-
- if (insn != info->first)
- return 0;
-
- /* Compare insn which uses Z. We have to save/restore the X/Y
- register without modifying the condition codes. For this
- we have to use a push/pop insn. */
- info->must_push_reg = 1;
- info->last = insn;
- }
-
- /* Z reg is set to something new. We don't need to load it. */
- if (Z_REG_P (dst))
- {
- if (!reg_mentioned_p (z_reg, src))
- {
- /* Z reg is used before being set. Treat this as
- a new sequence of Z register replacement. */
- if (insn != info->first)
- {
- return 0;
- }
- info->must_load_z = 0;
- }
- info->z_set_count++;
- info->z_value = src;
- if (SP_REG_P (src))
- info->z_loaded_with_sp = 1;
- }
- else if (reg_mentioned_p (z_reg, dst))
- info->can_use_d = 0;
-
- this_insn_uses_d = reg_mentioned_p (d_reg, src)
- | reg_mentioned_p (d_reg, dst);
- this_insn_uses_ix = reg_mentioned_p (ix_reg, src)
- | reg_mentioned_p (ix_reg, dst);
- this_insn_uses_iy = reg_mentioned_p (iy_reg, src)
- | reg_mentioned_p (iy_reg, dst);
- this_insn_uses_z = reg_mentioned_p (z_reg, src);
-
- /* If z is used as an address operand (like (MEM (reg z))),
- we can't replace it with d. */
- if (this_insn_uses_z && !Z_REG_P (src)
- && !(m68hc11_arith_operator (src, GET_MODE (src))
- && Z_REG_P (XEXP (src, 0))
- && !reg_mentioned_p (z_reg, XEXP (src, 1))
- && insn == info->first
- && dead_register_here (insn, d_reg)))
- info->can_use_d = 0;
-
- this_insn_uses_z_in_dst = reg_mentioned_p (z_reg, dst);
- if (TARGET_M6812 && !z_dies_here
- && ((this_insn_uses_z && side_effects_p (src))
- || (this_insn_uses_z_in_dst && side_effects_p (dst))))
- {
- info->need_save_z = 1;
- info->z_set_count++;
- }
- this_insn_uses_z |= this_insn_uses_z_in_dst;
-
- if (this_insn_uses_z && this_insn_uses_ix && this_insn_uses_iy)
- {
- fatal_insn ("registers IX, IY and Z used in the same INSN", insn);
- }
-
- if (this_insn_uses_d)
- info->can_use_d = 0;
-
- /* IX and IY are used at the same time, we have to restore
- the value of the scratch register before this insn. */
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- return 0;
- }
-
- if (this_insn_uses_ix && X_REG_P (dst) && GET_MODE (dst) == SImode)
- info->can_use_d = 0;
-
- if (info->x_used == 0 && this_insn_uses_ix)
- {
- if (info->y_used)
- {
- /* We have a (set (REG:HI X) (REG:HI Z)).
- Since we use Z as the replacement register, this insn
- is no longer necessary. We turn it into a note. We must
- not reload the old value of X. */
- if (X_REG_P (dst) && rtx_equal_p (src, z_reg))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- info->can_use_d = 0;
- SET_INSN_DELETED (insn);
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (X_REG_P (dst)
- && (rtx_equal_p (src, z_reg)
- || (z_dies_here && !reg_mentioned_p (ix_reg, src))))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->last = NEXT_INSN (insn);
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (X_REG_P (dst) && reg_mentioned_p (z_reg, src)
- && !reg_mentioned_p (ix_reg, src))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- else if (TARGET_M6812 && side_effects_p (src))
- {
- info->last = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- else
- {
- info->save_before_last = 1;
- }
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- else if (info->can_use_d)
- {
- info->last = NEXT_INSN (insn);
- info->x_used = 1;
- }
- return 0;
- }
- info->x_used = 1;
- if (z_dies_here && !reg_mentioned_p (ix_reg, src)
- && GET_CODE (dst) == REG && REGNO (dst) == HARD_X_REGNUM)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- info->last = NEXT_INSN (insn);
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, ix_reg))
- {
- info->regno = HARD_X_REGNUM;
- info->must_restore_reg = 0;
- info->must_save_reg = 0;
- return 0;
- }
- }
- if (info->y_used == 0 && this_insn_uses_iy)
- {
- if (info->x_used)
- {
- if (Y_REG_P (dst) && rtx_equal_p (src, z_reg))
- {
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- }
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- info->can_use_d = 0;
- SET_INSN_DELETED (insn);
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (Y_REG_P (dst)
- && (rtx_equal_p (src, z_reg)
- || (z_dies_here && !reg_mentioned_p (iy_reg, src))))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- info->last = NEXT_INSN (insn);
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (Y_REG_P (dst) && reg_mentioned_p (z_reg, src)
- && !reg_mentioned_p (iy_reg, src))
- {
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- else if (TARGET_M6812 && side_effects_p (src))
- {
- info->last = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- else
- {
- info->save_before_last = 1;
- }
- info->must_restore_reg = 0;
- info->last = NEXT_INSN (insn);
- }
- else if (info->can_use_d)
- {
- info->last = NEXT_INSN (insn);
- info->y_used = 1;
- }
-
- return 0;
- }
- info->y_used = 1;
- if (z_dies_here && !reg_mentioned_p (iy_reg, src)
- && GET_CODE (dst) == REG && REGNO (dst) == HARD_Y_REGNUM)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- info->last = NEXT_INSN (insn);
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- return 0;
- }
- if (rtx_equal_p (src, z_reg) && rtx_equal_p (dst, iy_reg))
- {
- info->regno = HARD_Y_REGNUM;
- info->must_restore_reg = 0;
- info->must_save_reg = 0;
- return 0;
- }
- }
- if (z_dies_here)
- {
- info->need_save_z = 0;
- info->z_died = 1;
- if (info->last == 0)
- info->last = NEXT_INSN (insn);
- return 0;
- }
- return info->last != NULL_RTX ? 0 : 1;
- }
- if (GET_CODE (body) == PARALLEL)
- {
- int i;
- char ix_clobber = 0;
- char iy_clobber = 0;
- char z_clobber = 0;
- this_insn_uses_iy = 0;
- this_insn_uses_ix = 0;
- this_insn_uses_z = 0;
-
- for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
- {
- rtx x;
- int uses_ix, uses_iy, uses_z;
-
- x = XVECEXP (body, 0, i);
-
- if (info->can_use_d && reg_mentioned_p (d_reg, x))
- info->can_use_d = 0;
-
- uses_ix = reg_mentioned_p (ix_reg, x);
- uses_iy = reg_mentioned_p (iy_reg, x);
- uses_z = reg_mentioned_p (z_reg, x);
- if (GET_CODE (x) == CLOBBER)
- {
- ix_clobber |= uses_ix;
- iy_clobber |= uses_iy;
- z_clobber |= uses_z;
- }
- else
- {
- this_insn_uses_ix |= uses_ix;
- this_insn_uses_iy |= uses_iy;
- this_insn_uses_z |= uses_z;
- }
- if (uses_z && GET_CODE (x) == SET)
- {
- rtx dst = XEXP (x, 0);
-
- if (Z_REG_P (dst))
- info->z_set_count++;
- }
- if (TARGET_M6812 && uses_z && side_effects_p (x))
- info->need_save_z = 1;
-
- if (z_clobber)
- info->need_save_z = 0;
- }
- if (debug_m6811)
- {
- printf ("Uses X:%d Y:%d Z:%d CX:%d CY:%d CZ:%d\n",
- this_insn_uses_ix, this_insn_uses_iy,
- this_insn_uses_z, ix_clobber, iy_clobber, z_clobber);
- debug_rtx (insn);
- }
- if (this_insn_uses_z)
- info->can_use_d = 0;
-
- if (z_clobber && info->first != insn)
- {
- info->need_save_z = 0;
- info->last = insn;
- return 0;
- }
- if (z_clobber && info->x_used == 0 && info->y_used == 0)
- {
- if (this_insn_uses_z == 0 && insn == info->first)
- {
- info->must_load_z = 0;
- }
- if (dead_register_here (insn, d_reg))
- {
- info->regno = HARD_D_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (dead_register_here (insn, ix_reg))
- {
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- else if (dead_register_here (insn, iy_reg))
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- if (info->regno >= 0)
- {
- info->last = NEXT_INSN (insn);
- return 0;
- }
- if (this_insn_uses_ix == 0)
- {
- info->regno = HARD_X_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- else if (this_insn_uses_iy == 0)
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- else
- {
- info->regno = HARD_D_REGNUM;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- }
- info->last = NEXT_INSN (insn);
- return 0;
- }
-
- if (((info->x_used || this_insn_uses_ix) && iy_clobber)
- || ((info->y_used || this_insn_uses_iy) && ix_clobber))
- {
- if (this_insn_uses_z)
- {
- if (info->y_used == 0 && iy_clobber)
- {
- info->regno = HARD_Y_REGNUM;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- if (info->first != insn
- && ((info->y_used && ix_clobber)
- || (info->x_used && iy_clobber)))
- info->last = insn;
- else
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- }
- return 0;
- }
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- if (this_insn_uses_z)
- {
- fatal_insn ("cannot do z-register replacement", insn);
- }
- return 0;
- }
- if (info->x_used == 0 && (this_insn_uses_ix || ix_clobber))
- {
- if (info->y_used)
- {
- return 0;
- }
- info->x_used = 1;
- if (iy_clobber || z_clobber)
- {
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- return 0;
- }
- }
-
- if (info->y_used == 0 && (this_insn_uses_iy || iy_clobber))
- {
- if (info->x_used)
- {
- return 0;
- }
- info->y_used = 1;
- if (ix_clobber || z_clobber)
- {
- info->last = NEXT_INSN (insn);
- info->save_before_last = 1;
- return 0;
- }
- }
- if (z_dies_here)
- {
- info->z_died = 1;
- info->need_save_z = 0;
- }
- return 1;
- }
- if (GET_CODE (body) == CLOBBER)
- {
- rtx dst = XEXP (body, 0);
-
- this_insn_uses_ix = reg_mentioned_p (ix_reg, dst);
- this_insn_uses_iy = reg_mentioned_p (iy_reg, dst);
-
- /* IX and IY are used at the same time, we have to restore
- the value of the scratch register before this insn. */
- if (this_insn_uses_ix && this_insn_uses_iy)
- {
- return 0;
- }
- if (info->x_used == 0 && this_insn_uses_ix)
- {
- if (info->y_used)
- {
- return 0;
- }
- info->x_used = 1;
- }
- if (info->y_used == 0 && this_insn_uses_iy)
- {
- if (info->x_used)
- {
- return 0;
- }
- info->y_used = 1;
- }
- return 1;
- }
- return 1;
-}
-
-static void
-m68hc11_find_z_replacement (rtx insn, struct replace_info *info)
-{
- int reg;
-
- info->replace_reg = NULL_RTX;
- info->must_load_z = 1;
- info->need_save_z = 1;
- info->must_save_reg = 1;
- info->must_restore_reg = 1;
- info->first = insn;
- info->x_used = 0;
- info->y_used = 0;
- info->can_use_d = TARGET_M6811 ? 1 : 0;
- info->found_call = 0;
- info->z_died = 0;
- info->last = 0;
- info->regno = -1;
- info->z_set_count = 0;
- info->z_value = NULL_RTX;
- info->must_push_reg = 0;
- info->save_before_last = 0;
- info->z_loaded_with_sp = 0;
-
- /* Scan the insn forward to find an address register that is not used.
- Stop when:
- - the flow of the program changes,
- - when we detect that both X and Y are necessary,
- - when the Z register dies,
- - when the condition codes are set. */
-
- for (; insn && info->z_died == 0; insn = NEXT_INSN (insn))
- {
- if (m68hc11_check_z_replacement (insn, info) == 0)
- break;
- }
-
- /* May be we can use Y or X if they contain the same value as Z.
- This happens very often after the reload. */
- if (info->z_set_count == 1)
- {
- rtx p = info->first;
- rtx v = 0;
-
- if (info->x_used)
- {
- v = find_last_value (iy_reg, &p, insn, 1);
- }
- else if (info->y_used)
- {
- v = find_last_value (ix_reg, &p, insn, 1);
- }
- if (v && (v != iy_reg && v != ix_reg) && rtx_equal_p (v, info->z_value))
- {
- if (info->x_used)
- info->regno = HARD_Y_REGNUM;
- else
- info->regno = HARD_X_REGNUM;
- info->must_load_z = 0;
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- info->found_call = 1;
- }
- }
- if (info->z_set_count == 0)
- info->need_save_z = 0;
-
- if (insn == 0)
- info->need_save_z = 0;
-
- if (info->last == 0)
- info->last = insn;
-
- if (info->regno >= 0)
- {
- reg = info->regno;
- info->replace_reg = gen_rtx_REG (HImode, reg);
- }
- else if (info->can_use_d)
- {
- reg = HARD_D_REGNUM;
- info->replace_reg = d_reg;
- }
- else if (info->x_used)
- {
- reg = HARD_Y_REGNUM;
- info->replace_reg = iy_reg;
- }
- else
- {
- reg = HARD_X_REGNUM;
- info->replace_reg = ix_reg;
- }
- info->regno = reg;
-
- if (info->must_save_reg && info->must_restore_reg)
- {
- if (insn && dead_register_here (insn, info->replace_reg))
- {
- info->must_save_reg = 0;
- info->must_restore_reg = 0;
- }
- }
-}
-
-/* The insn uses the Z register. Find a replacement register for it
- (either X or Y) and replace it in the insn and the next ones until
- the flow changes or the replacement register is used. Instructions
- are emitted before and after the Z-block to preserve the value of
- Z and of the replacement register. */
-
-static void
-m68hc11_z_replacement (rtx insn)
-{
- rtx replace_reg_qi;
- rtx replace_reg;
- struct replace_info info;
-
- /* Find trivial case where we only need to replace z with the
- equivalent soft register. */
- if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx body = PATTERN (insn);
- rtx src = XEXP (body, 1);
- rtx dst = XEXP (body, 0);
-
- if (Z_REG_P (dst) && (H_REG_P (src) && !SP_REG_P (src)))
- {
- XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
- return;
- }
- else if (Z_REG_P (src)
- && ((H_REG_P (dst) && !SP_REG_P (src)) || dst == cc0_rtx))
- {
- XEXP (body, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
- return;
- }
- else if (D_REG_P (dst)
- && m68hc11_arith_operator (src, GET_MODE (src))
- && D_REG_P (XEXP (src, 0)) && Z_REG_P (XEXP (src, 1)))
- {
- XEXP (src, 1) = gen_rtx_REG (GET_MODE (src), SOFT_Z_REGNUM);
- return;
- }
- else if (Z_REG_P (dst) && GET_CODE (src) == CONST_INT
- && INTVAL (src) == 0)
- {
- XEXP (body, 0) = gen_rtx_REG (GET_MODE (dst), SOFT_Z_REGNUM);
- /* Force it to be re-recognized. */
- INSN_CODE (insn) = -1;
- return;
- }
- }
-
- m68hc11_find_z_replacement (insn, &info);
-
- replace_reg = info.replace_reg;
- replace_reg_qi = NULL_RTX;
-
- /* Save the X register in a .page0 location. */
- if (info.must_save_reg && !info.must_push_reg)
- {
- rtx dst;
-
- if (info.must_push_reg && 0)
- dst = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
-
- emit_insn_before (gen_movhi (dst,
- gen_rtx_REG (HImode, info.regno)), insn);
- }
- if (info.must_load_z && !info.must_push_reg)
- {
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, info.regno),
- gen_rtx_REG (HImode, SOFT_Z_REGNUM)),
- insn);
- }
-
-
- /* Replace all occurrence of Z by replace_reg.
- Stop when the last instruction to replace is reached.
- Also stop when we detect a change in the flow (but it's not
- necessary; just safeguard). */
-
- for (; insn && insn != info.last; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
- break;
-
- if (GET_CODE (insn) != INSN
- && GET_CODE (insn) != CALL_INSN && GET_CODE (insn) != JUMP_INSN)
- continue;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
- || GET_CODE (body) == ASM_OPERANDS
- || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- {
- rtx note;
-
- if (debug_m6811 && reg_mentioned_p (replace_reg, body))
- {
- printf ("Reg mentioned here...:\n");
- fflush (stdout);
- debug_rtx (insn);
- }
-
- /* Stack pointer was decremented by 2 due to the push.
- Correct that by adding 2 to the destination. */
- if (info.must_push_reg
- && info.z_loaded_with_sp && GET_CODE (body) == SET)
- {
- rtx src, dst;
-
- src = SET_SRC (body);
- dst = SET_DEST (body);
- if (SP_REG_P (src) && Z_REG_P (dst))
- emit_insn_after (gen_addhi3 (dst, dst, const2_rtx), insn);
- }
-
- /* Replace any (REG:HI Z) occurrence by either X or Y. */
- if (!validate_replace_rtx (z_reg, replace_reg, insn))
- {
- INSN_CODE (insn) = -1;
- if (!validate_replace_rtx (z_reg, replace_reg, insn))
- fatal_insn ("cannot do z-register replacement", insn);
- }
-
- /* Likewise for (REG:QI Z). */
- if (reg_mentioned_p (z_reg, insn))
- {
- if (replace_reg_qi == NULL_RTX)
- replace_reg_qi = gen_rtx_REG (QImode, REGNO (replace_reg));
- validate_replace_rtx (z_reg_qi, replace_reg_qi, insn);
- }
-
- /* If there is a REG_INC note on Z, replace it with a
- REG_INC note on the replacement register. This is necessary
- to make sure that the flow pass will identify the change
- and it will not remove a possible insn that saves Z. */
- for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
- {
- if (REG_NOTE_KIND (note) == REG_INC
- && GET_CODE (XEXP (note, 0)) == REG
- && REGNO (XEXP (note, 0)) == REGNO (z_reg))
- {
- XEXP (note, 0) = replace_reg;
- }
- }
- }
- if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- break;
- }
-
- /* Save Z before restoring the old value. */
- if (insn && info.need_save_z && !info.must_push_reg)
- {
- rtx save_pos_insn = insn;
-
- /* If Z is clobber by the last insn, we have to save its value
- before the last instruction. */
- if (info.save_before_last)
- save_pos_insn = PREV_INSN (save_pos_insn);
-
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, SOFT_Z_REGNUM),
- gen_rtx_REG (HImode, info.regno)),
- save_pos_insn);
- }
-
- if (info.must_push_reg && info.last)
- {
- rtx new_body, body;
-
- body = PATTERN (info.last);
- new_body = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (3, body,
- gen_rtx_USE (VOIDmode,
- replace_reg),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (HImode,
- SOFT_Z_REGNUM))));
- PATTERN (info.last) = new_body;
-
- /* Force recognition on insn since we changed it. */
- INSN_CODE (insn) = -1;
-
- if (!validate_replace_rtx (z_reg, replace_reg, info.last))
- {
- fatal_insn ("invalid Z register replacement for insn", insn);
- }
- insn = NEXT_INSN (info.last);
- }
-
- /* Restore replacement register unless it was died. */
- if (insn && info.must_restore_reg && !info.must_push_reg)
- {
- rtx dst;
-
- if (info.must_push_reg && 0)
- dst = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- dst = gen_rtx_REG (HImode, SOFT_SAVED_XY_REGNUM);
-
- emit_insn_before (gen_movhi (gen_rtx_REG (HImode, info.regno),
- dst), insn);
- }
-
-}
-
-
-/* Scan all the insn and re-affects some registers
- - The Z register (if it was used), is affected to X or Y depending
- on the instruction. */
-
-static void
-m68hc11_reassign_regs (rtx first)
-{
- rtx insn;
-
- ix_reg = gen_rtx_REG (HImode, HARD_X_REGNUM);
- iy_reg = gen_rtx_REG (HImode, HARD_Y_REGNUM);
- z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
- z_reg_qi = gen_rtx_REG (QImode, HARD_Z_REGNUM);
-
- /* Scan all insns to replace Z by X or Y preserving the old value
- of X/Y and restoring it afterward. */
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER)
- continue;
-
- if (!INSN_P (insn))
- continue;
-
- body = PATTERN (insn);
- if (GET_CODE (body) == CLOBBER || GET_CODE (body) == USE)
- continue;
-
- if (GET_CODE (body) == CONST_INT || GET_CODE (body) == ASM_INPUT
- || GET_CODE (body) == ASM_OPERANDS
- || GET_CODE (body) == UNSPEC || GET_CODE (body) == UNSPEC_VOLATILE)
- continue;
-
- if (GET_CODE (body) == SET || GET_CODE (body) == PARALLEL
- || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- {
-
- /* If Z appears in this insn, replace it in the current insn
- and the next ones until the flow changes or we have to
- restore back the replacement register. */
-
- if (reg_mentioned_p (z_reg, body))
- {
- m68hc11_z_replacement (insn);
- }
- }
- else
- {
- printf ("insn not handled by Z replacement:\n");
- fflush (stdout);
- debug_rtx (insn);
- }
- }
-}
-
-
-/* Machine-dependent reorg pass.
- Specific optimizations are defined here:
- - this pass changes the Z register into either X or Y
- (it preserves X/Y previous values in a memory slot in page0).
-
- When this pass is finished, the global variable
- 'z_replacement_completed' is set to 2. */
-
-static void
-m68hc11_reorg (void)
-{
- int split_done = 0;
- rtx first;
-
- z_replacement_completed = 0;
- z_reg = gen_rtx_REG (HImode, HARD_Z_REGNUM);
- first = get_insns ();
-
- /* Some RTX are shared at this point. This breaks the Z register
- replacement, unshare everything. */
- unshare_all_rtl_again (first);
-
- /* Force a split of all splittable insn. This is necessary for the
- Z register replacement mechanism because we end up with basic insns. */
- split_all_insns_noflow ();
- split_done = 1;
-
- z_replacement_completed = 1;
- m68hc11_reassign_regs (first);
-
- if (optimize)
- compute_bb_for_insn ();
-
- /* After some splitting, there are some opportunities for CSE pass.
- This happens quite often when 32-bit or above patterns are split. */
- if (optimize > 0 && split_done)
- {
- reload_cse_regs (first);
- }
-
- /* Re-create the REG_DEAD notes. These notes are used in the machine
- description to use the best assembly directives. */
- if (optimize)
- {
- df_note_add_problem ();
- df_analyze ();
- df_remove_problem (df_note);
- }
-
- z_replacement_completed = 2;
-
- /* If optimizing, then go ahead and split insns that must be
- split after Z register replacement. This gives more opportunities
- for peephole (in particular for consecutives xgdx/xgdy). */
- if (optimize > 0)
- split_all_insns_noflow ();
-
- /* Once insns are split after the z_replacement_completed == 2,
- we must not re-run the life_analysis. The xgdx/xgdy patterns
- are not recognized and the life_analysis pass removes some
- insns because it thinks some (SETs) are noops or made to dead
- stores (which is false due to the swap).
-
- Do a simple pass to eliminate the noop set that the final
- split could generate (because it was easier for split definition). */
- {
- rtx insn;
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- rtx body;
-
- if (INSN_DELETED_P (insn))
- continue;
- if (!INSN_P (insn))
- continue;
-
- /* Remove the (set (R) (R)) insns generated by some splits. */
- body = PATTERN (insn);
- if (GET_CODE (body) == SET
- && rtx_equal_p (SET_SRC (body), SET_DEST (body)))
- {
- SET_INSN_DELETED (insn);
- continue;
- }
- }
- }
-}
-
-/* Override memcpy */
-
-static void
-m68hc11_init_libfuncs (void)
-{
- memcpy_libfunc = init_one_libfunc ("__memcpy");
- memcmp_libfunc = init_one_libfunc ("__memcmp");
- memset_libfunc = init_one_libfunc ("__memset");
-}
-
-
-
-/* Cost functions. */
-
-/* Cost of moving memory. */
-int
-m68hc11_memory_move_cost (enum machine_mode mode, enum reg_class rclass,
- int in ATTRIBUTE_UNUSED)
-{
- if (rclass <= H_REGS && rclass > NO_REGS)
- {
- if (GET_MODE_SIZE (mode) <= 2)
- return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
- else
- return COSTS_N_INSNS (2) + (reload_completed | reload_in_progress);
- }
- else
- {
- if (GET_MODE_SIZE (mode) <= 2)
- return COSTS_N_INSNS (3);
- else
- return COSTS_N_INSNS (4);
- }
-}
-
-
-/* Cost of moving data from a register of class 'from' to on in class 'to'.
- Reload does not check the constraint of set insns when the two registers
- have a move cost of 2. Setting a higher cost will force reload to check
- the constraints. */
-int
-m68hc11_register_move_cost (enum machine_mode mode, enum reg_class from,
- enum reg_class to)
-{
- /* All costs are symmetric, so reduce cases by putting the
- lower number class as the destination. */
- if (from < to)
- {
- enum reg_class tmp = to;
- to = from, from = tmp;
- }
- if (to >= S_REGS)
- return m68hc11_memory_move_cost (mode, S_REGS, 0);
- else if (from <= S_REGS)
- return COSTS_N_INSNS (1) + (reload_completed | reload_in_progress);
- else
- return COSTS_N_INSNS (2);
-}
-
-
-/* Provide the costs of an addressing mode that contains ADDR.
- If ADDR is not a valid address, its cost is irrelevant. */
-
-static int
-m68hc11_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- int cost = 4;
-
- switch (GET_CODE (addr))
- {
- case REG:
- /* Make the cost of hard registers and specially SP, FP small. */
- if (REGNO (addr) < FIRST_PSEUDO_REGISTER)
- cost = 0;
- else
- cost = 1;
- break;
-
- case SYMBOL_REF:
- cost = 8;
- break;
-
- case LABEL_REF:
- case CONST:
- cost = 0;
- break;
-
- case PLUS:
- {
- register rtx plus0 = XEXP (addr, 0);
- register rtx plus1 = XEXP (addr, 1);
-
- if (GET_CODE (plus0) != REG)
- break;
-
- switch (GET_CODE (plus1))
- {
- case CONST_INT:
- if (INTVAL (plus1) >= 2 * m68hc11_max_offset
- || INTVAL (plus1) < m68hc11_min_offset)
- cost = 3;
- else if (INTVAL (plus1) >= m68hc11_max_offset)
- cost = 2;
- else
- cost = 1;
- if (REGNO (plus0) < FIRST_PSEUDO_REGISTER)
- cost += 0;
- else
- cost += 1;
- break;
-
- case SYMBOL_REF:
- cost = 8;
- break;
-
- case CONST:
- case LABEL_REF:
- cost = 0;
- break;
-
- default:
- break;
- }
- break;
- }
- case PRE_DEC:
- case PRE_INC:
- if (SP_REG_P (XEXP (addr, 0)))
- cost = 1;
- break;
-
- default:
- break;
- }
- if (debug_m6811)
- {
- printf ("Address cost: %d for :", cost);
- fflush (stdout);
- debug_rtx (addr);
- }
-
- return cost;
-}
-
-static int
-m68hc11_shift_cost (enum machine_mode mode, rtx x, int shift)
-{
- int total;
-
- total = rtx_cost (x, SET, !optimize_size);
- if (mode == QImode)
- total += m68hc11_cost->shiftQI_const[shift % 8];
- else if (mode == HImode)
- total += m68hc11_cost->shiftHI_const[shift % 16];
- else if (shift == 8 || shift == 16 || shift == 32)
- total += m68hc11_cost->shiftHI_const[8];
- else if (shift != 0 && shift != 16 && shift != 32)
- {
- total += m68hc11_cost->shiftHI_const[1] * shift;
- }
-
- /* For SI and others, the cost is higher. */
- if (GET_MODE_SIZE (mode) > 2 && (shift % 16) != 0)
- total *= GET_MODE_SIZE (mode) / 2;
-
- /* When optimizing for size, make shift more costly so that
- multiplications are preferred. */
- if (optimize_size && (shift % 8) != 0)
- total *= 2;
-
- return total;
-}
-
-static int
-m68hc11_rtx_costs_1 (rtx x, enum rtx_code code,
- enum rtx_code outer_code ATTRIBUTE_UNUSED)
-{
- enum machine_mode mode = GET_MODE (x);
- int extra_cost = 0;
- int total;
-
- switch (code)
- {
- case ROTATE:
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- return m68hc11_shift_cost (mode, XEXP (x, 0), INTVAL (XEXP (x, 1)));
- }
-
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->shift_var;
- return total;
-
- case AND:
- case XOR:
- case IOR:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->logical;
-
- /* Logical instructions are byte instructions only. */
- total *= GET_MODE_SIZE (mode);
- return total;
-
- case MINUS:
- case PLUS:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- total += m68hc11_cost->add;
- if (GET_MODE_SIZE (mode) > 2)
- {
- total *= GET_MODE_SIZE (mode) / 2;
- }
- return total;
-
- case UDIV:
- case DIV:
- case MOD:
- total = rtx_cost (XEXP (x, 0), code, !optimize_size) + rtx_cost (XEXP (x, 1), code, !optimize_size);
- switch (mode)
- {
- case QImode:
- total += m68hc11_cost->divQI;
- break;
-
- case HImode:
- total += m68hc11_cost->divHI;
- break;
-
- case SImode:
- default:
- total += m68hc11_cost->divSI;
- break;
- }
- return total;
-
- case MULT:
- /* mul instruction produces 16-bit result. */
- if (mode == HImode && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
- return m68hc11_cost->multQI
- + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
- + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
-
- /* emul instruction produces 32-bit result for 68HC12. */
- if (TARGET_M6812 && mode == SImode
- && GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND)
- return m68hc11_cost->multHI
- + rtx_cost (XEXP (XEXP (x, 0), 0), code, !optimize_size)
- + rtx_cost (XEXP (XEXP (x, 1), 0), code, !optimize_size);
-
- total = rtx_cost (XEXP (x, 0), code, !optimize_size)
- + rtx_cost (XEXP (x, 1), code, !optimize_size);
- switch (mode)
- {
- case QImode:
- total += m68hc11_cost->multQI;
- break;
-
- case HImode:
- total += m68hc11_cost->multHI;
- break;
-
- case SImode:
- default:
- total += m68hc11_cost->multSI;
- break;
- }
- return total;
-
- case NEG:
- case SIGN_EXTEND:
- extra_cost = COSTS_N_INSNS (2);
-
- /* Fall through */
- case NOT:
- case COMPARE:
- case ABS:
- case ZERO_EXTEND:
- case ZERO_EXTRACT:
- total = extra_cost + rtx_cost (XEXP (x, 0), code, !optimize_size);
- if (mode == QImode)
- {
- return total + COSTS_N_INSNS (1);
- }
- if (mode == HImode)
- {
- return total + COSTS_N_INSNS (2);
- }
- if (mode == SImode)
- {
- return total + COSTS_N_INSNS (4);
- }
- return total + COSTS_N_INSNS (8);
-
- case IF_THEN_ELSE:
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- return COSTS_N_INSNS (1);
-
- return COSTS_N_INSNS (1);
-
- default:
- return COSTS_N_INSNS (4);
- }
-}
-
-static bool
-m68hc11_rtx_costs (rtx x, int codearg, int outer_code_arg, int *total,
- bool speed ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = (enum rtx_code) codearg;
- enum rtx_code outer_code = (enum rtx_code) outer_code_arg;
-
- switch (code)
- {
- /* Constants are cheap. Moving them in registers must be avoided
- because most instructions do not handle two register operands. */
- case CONST_INT:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_DOUBLE:
- /* Logical and arithmetic operations with a constant operand are
- better because they are not supported with two registers. */
- /* 'clr' is slow */
- if (outer_code == SET && x == const0_rtx)
- /* After reload, the reload_cse pass checks the cost to change
- a SET into a PLUS. Make const0 cheap then. */
- *total = 1 - reload_completed;
- else
- *total = 0;
- return true;
-
- case ZERO_EXTRACT:
- if (outer_code != COMPARE)
- return false;
-
- case ROTATE:
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- case MINUS:
- case PLUS:
- case AND:
- case XOR:
- case IOR:
- case UDIV:
- case DIV:
- case MOD:
- case MULT:
- case NEG:
- case SIGN_EXTEND:
- case NOT:
- case COMPARE:
- case ZERO_EXTEND:
- case IF_THEN_ELSE:
- *total = m68hc11_rtx_costs_1 (x, code, outer_code);
- return true;
-
- default:
- return false;
- }
-}
-
-
-/* Worker function for TARGET_ASM_FILE_START. */
-
-static void
-m68hc11_file_start (void)
-{
- default_file_start ();
-
- fprintf (asm_out_file, "\t.mode %s\n", TARGET_SHORT ? "mshort" : "mlong");
-}
-
-
-/* Worker function for TARGET_ASM_CONSTRUCTOR. */
-
-static void
-m68hc11_asm_out_constructor (rtx symbol, int priority)
-{
- default_ctor_section_asm_out_constructor (symbol, priority);
- fprintf (asm_out_file, "\t.globl\t__do_global_ctors\n");
-}
-
-/* Worker function for TARGET_ASM_DESTRUCTOR. */
-
-static void
-m68hc11_asm_out_destructor (rtx symbol, int priority)
-{
- default_dtor_section_asm_out_destructor (symbol, priority);
- fprintf (asm_out_file, "\t.globl\t__do_global_dtors\n");
-}
-
-/* Worker function for TARGET_STRUCT_VALUE_RTX. */
-
-static rtx
-m68hc11_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
- int incoming ATTRIBUTE_UNUSED)
-{
- return gen_rtx_REG (Pmode, HARD_D_REGNUM);
-}
-
-/* Return true if type TYPE should be returned in memory.
- Blocks and data types largers than 4 bytes cannot be returned
- in the register (D + X = 4). */
-
-static bool
-m68hc11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
-{
- if (TYPE_MODE (type) == BLKmode)
- {
- HOST_WIDE_INT size = int_size_in_bytes (type);
- return (size == -1 || size > 4);
- }
- else
- return GET_MODE_SIZE (TYPE_MODE (type)) > 4;
-}
-
-#include "gt-m68hc11.h"
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
deleted file mode 100644
index 8f6d06867ee..00000000000
--- a/gcc/config/m68hc11/m68hc11.h
+++ /dev/null
@@ -1,1382 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- Motorola 68HC11 and 68HC12.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
- Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>.
-
-Note:
- A first 68HC11 port was made by Otto Lind (otto@coactive.com)
- on gcc 2.6.3. I have used it as a starting point for this port.
- However, this new port is a complete re-write. Its internal
- design is completely different. The generated code is not
- compatible with the gcc 2.6.3 port.
-
- The gcc 2.6.3 port is available at:
-
- ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-
-*/
-
-/*****************************************************************************
-**
-** Controlling the Compilation Driver, `gcc'
-**
-*****************************************************************************/
-
-#undef ENDFILE_SPEC
-
-/* Compile and assemble for a 68hc11 unless there is a -m68hc12 option. */
-#ifndef ASM_SPEC
-#define ASM_SPEC \
-"%{m68hc12:-m68hc12}" \
-"%{m68hcs12:-m68hcs12}" \
-"%{!m68hc12:%{!m68hcs12:-m68hc11}} " \
-"%{mshort:-mshort}%{!mshort:-mlong} " \
-"%{fshort-double:-mshort-double}%{!fshort-double:-mlong-double}"
-#endif
-
-/* We need to tell the linker the target elf format. Just pass an
- emulation option. This can be overridden by -Wl option of gcc. */
-#ifndef LINK_SPEC
-#define LINK_SPEC \
-"%{m68hc12:-m m68hc12elf}" \
-"%{m68hcs12:-m m68hc12elf}" \
-"%{!m68hc12:%{!m68hcs12:-m m68hc11elf}} " \
-"%{!mnorelax:%{!m68hc12:%{!m68hcs12:-relax}}}"
-#endif
-
-#ifndef LIB_SPEC
-#define LIB_SPEC ""
-#endif
-
-#ifndef CC1_SPEC
-#define CC1_SPEC ""
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC \
-"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16}\
- %{!mshort:-D__INT__=32}\
- %{m68hc12:-Dmc6812 -DMC6812 -Dmc68hc12}\
- %{m68hcs12:-Dmc6812 -DMC6812 -Dmc68hcs12}\
- %{!m68hc12:%{!m68hcs12:-Dmc6811 -DMC6811 -Dmc68hc11}}\
- %{fshort-double:-D__HAVE_SHORT_DOUBLE__}\
- %{mlong-calls:-D__USE_RTC__}"
-#endif
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "crt1%O%s"
-
-/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("mc68hc1x"); \
- } \
- while (0)
-
-/* As an embedded target, we have no libc. */
-#ifndef inhibit_libc
-# define inhibit_libc
-#endif
-
-/* Forward type declaration for prototypes definitions.
- rtx_ptr is equivalent to rtx. Can't use the same name. */
-struct rtx_def;
-typedef struct rtx_def *rtx_ptr;
-
-union tree_node;
-typedef union tree_node *tree_ptr;
-
-/* We can't declare enum machine_mode forward nor include 'machmode.h' here.
- Prototypes defined here will use an int instead. It's better than no
- prototype at all. */
-typedef int enum_machine_mode;
-
-/*****************************************************************************
-**
-** Run-time Target Specification
-**
-*****************************************************************************/
-
-/* Run-time compilation parameters selecting different hardware subsets. */
-
-extern short *reg_renumber; /* def in local_alloc.c */
-
-#define TARGET_OP_TIME (optimize && optimize_size == 0)
-#define TARGET_RELAX (TARGET_NO_DIRECT_MODE)
-
-/* Default target_flags if no switches specified. */
-#ifndef TARGET_DEFAULT
-# define TARGET_DEFAULT 0
-#endif
-
-/* Define this macro as a C expression for the initializer of an
- array of string to tell the driver program which options are
- defaults for this target and thus do not need to be handled
- specially when using `MULTILIB_OPTIONS'. */
-#ifndef MULTILIB_DEFAULTS
-# if TARGET_DEFAULT & MASK_M6811
-# define MULTILIB_DEFAULTS { "m68hc11" }
-# else
-# define MULTILIB_DEFAULTS { "m68hc12" }
-# endif
-#endif
-
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (MC68HC11/MC68HC12/MC68HCS12)")
-
-
-/* Define cost parameters for a given processor variant. */
-struct processor_costs {
- const int add; /* cost of an add instruction */
- const int logical; /* cost of a logical instruction */
- const int shift_var;
- const int shiftQI_const[8];
- const int shiftHI_const[16];
- const int multQI;
- const int multHI;
- const int multSI;
- const int divQI;
- const int divHI;
- const int divSI;
-};
-
-/* Costs for the current processor. */
-extern const struct processor_costs *m68hc11_cost;
-
-
-/* target machine storage layout */
-
-/* Define this if most significant byte of a word is the lowest numbered. */
-#define BYTES_BIG_ENDIAN 1
-
-/* Define this if most significant bit is lowest numbered
- in instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant word of a multiword number is numbered. */
-#define WORDS_BIG_ENDIAN 1
-
-/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD 2
-
-/* Definition of size_t. This is really an unsigned short as the
- 68hc11 only handles a 64K address space. */
-#define SIZE_TYPE "short unsigned int"
-
-/* A C expression for a string describing the name of the data type
- to use for the result of subtracting two pointers. The typedef
- name `ptrdiff_t' is defined using the contents of the string.
- The 68hc11 only has a 64K address space. */
-#define PTRDIFF_TYPE "short int"
-
-/* Allocation boundary (bits) for storing pointers in memory. */
-#define POINTER_BOUNDARY 8
-
-/* Normal alignment required for function parameters on the stack, in bits.
- This can't be less than BITS_PER_WORD */
-#define PARM_BOUNDARY (BITS_PER_WORD)
-
-/* Boundary (bits) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY 8
-
-/* Allocation boundary (bits) for the code of a function. */
-#define FUNCTION_BOUNDARY 8
-
-#define BIGGEST_ALIGNMENT 8
-
-/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY 8
-
-/* Every structure's size must be a multiple of this. */
-#define STRUCTURE_SIZE_BOUNDARY 8
-
-/* Define this if instructions will fail to work if given data not
- on the nominal alignment. If instructions will merely go slower
- in that case, do not define this macro. */
-#define STRICT_ALIGNMENT 0
-
-/* An integer expression for the size in bits of the largest integer
- machine mode that should actually be used. All integer machine modes of
- this size or smaller can be used for structures and unions with the
- appropriate sizes. */
-#define MAX_FIXED_MODE_SIZE 64
-
-/* target machine storage layout */
-
-/* Size (bits) of the type "int" on target machine
- (If undefined, default is BITS_PER_WORD). */
-#define INT_TYPE_SIZE (TARGET_SHORT ? 16 : 32)
-
-/* Size (bits) of the type "short" on target machine */
-#define SHORT_TYPE_SIZE 16
-
-/* Size (bits) of the type "long" on target machine */
-#define LONG_TYPE_SIZE 32
-
-/* Size (bits) of the type "long long" on target machine */
-#define LONG_LONG_TYPE_SIZE 64
-
-/* A C expression for the size in bits of the type `float' on the
- target machine. If you don't define this, the default is one word.
- Don't use default: a word is only 16. */
-#define FLOAT_TYPE_SIZE 32
-
-/* A C expression for the size in bits of the type double on the target
- machine. If you don't define this, the default is two words.
- Be IEEE compliant. */
-#define DOUBLE_TYPE_SIZE 64
-
-#define LONG_DOUBLE_TYPE_SIZE 64
-
-/* Define this as 1 if `char' should by default be signed; else as 0. */
-#define DEFAULT_SIGNED_CHAR 0
-
-/* Define these to avoid dependence on meaning of `int'.
- Note that WCHAR_TYPE_SIZE is used in cexp.y,
- where TARGET_SHORT is not available. */
-#define WCHAR_TYPE "short int"
-#define WCHAR_TYPE_SIZE 16
-
-
-/* Standard register usage. */
-
-#define HARD_REG_SIZE (UNITS_PER_WORD)
-
-/* Assign names to real MC68HC11 registers.
- A and B registers are not really used (A+B = D)
- X register is first so that GCC allocates X+D for 32-bit integers and
- the lowpart of that integer will be D. Having the lower part in D is
- better for 32<->16bit conversions and for many arithmetic operations. */
-#define HARD_X_REGNUM 0
-#define HARD_D_REGNUM 1
-#define HARD_Y_REGNUM 2
-#define HARD_SP_REGNUM 3
-#define HARD_PC_REGNUM 4
-#define HARD_A_REGNUM 5
-#define HARD_B_REGNUM 6
-#define HARD_CCR_REGNUM 7
-
-/* The Z register does not really exist in the 68HC11. This a fake register
- for GCC. It is treated exactly as an index register (X or Y). It is only
- in the A_REGS class, which is the BASE_REG_CLASS for GCC. Defining this
- register helps the reload pass of GCC. Otherwise, the reload often dies
- with register spill failures.
-
- The Z register is replaced by either X or Y during the machine specific
- reorg (m68hc11_reorg). It is saved in the SOFT_Z_REGNUM soft-register
- when this is necessary.
-
- It's possible to tell GCC not to use this register with -ffixed-z. */
-#define HARD_Z_REGNUM 8
-
-/* The frame pointer is a soft-register. It's treated as such by GCC:
- it is not and must not be part of the BASE_REG_CLASS. */
-#define DEFAULT_HARD_FP_REGNUM (9)
-#define HARD_FP_REGNUM (9)
-#define HARD_AP_REGNUM (HARD_FP_REGNUM)
-
-/* Temporary soft-register used in some cases when an operand came
- up into a bad register class (D, X, Y, SP) and gcc failed to
- recognize this. This register is never allocated by GCC. */
-#define SOFT_TMP_REGNUM 10
-
-/* The soft-register which is used to save the Z register
- (see Z register replacement notes in m68hc11.c). */
-#define SOFT_Z_REGNUM 11
-
-/* The soft-register which is used to save either X or Y. */
-#define SOFT_SAVED_XY_REGNUM 12
-
-/* A fake clobber register for 68HC12 patterns. */
-#define FAKE_CLOBBER_REGNUM (13)
-
-/* Define 32 soft-registers of 16-bit each. By default,
- only 12 of them are enabled and can be used by GCC. The
- -msoft-reg-count=<n> option allows to control the number of valid
- soft-registers. GCC can put 32-bit values in them
- by allocating consecutive registers. The first 3 soft-registers
- are never allocated by GCC. They are used in case the insn template needs
- a temporary register, or for the Z register replacement. */
-
-#define MAX_SOFT_REG_COUNT (32)
-#define SOFT_REG_FIXED 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1
-#define SOFT_REG_USED 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1, \
- 1, 1, 1, 1, 1, 1, 1, 1
-#define SOFT_REG_ORDER \
-SOFT_REG_FIRST, SOFT_REG_FIRST+1,SOFT_REG_FIRST+2,SOFT_REG_FIRST+3,\
-SOFT_REG_FIRST+4, SOFT_REG_FIRST+5,SOFT_REG_FIRST+6,SOFT_REG_FIRST+7,\
-SOFT_REG_FIRST+8, SOFT_REG_FIRST+9,SOFT_REG_FIRST+10,SOFT_REG_FIRST+11,\
-SOFT_REG_FIRST+12, SOFT_REG_FIRST+13,SOFT_REG_FIRST+14,SOFT_REG_FIRST+15,\
-SOFT_REG_FIRST+16, SOFT_REG_FIRST+17,SOFT_REG_FIRST+18,SOFT_REG_FIRST+19,\
-SOFT_REG_FIRST+20, SOFT_REG_FIRST+21,SOFT_REG_FIRST+22,SOFT_REG_FIRST+23,\
-SOFT_REG_FIRST+24, SOFT_REG_FIRST+25,SOFT_REG_FIRST+26,SOFT_REG_FIRST+27,\
-SOFT_REG_FIRST+28, SOFT_REG_FIRST+29,SOFT_REG_FIRST+30,SOFT_REG_FIRST+31
-
-#define SOFT_REG_NAMES \
-"*_.d1", "*_.d2", "*_.d3", "*_.d4", \
-"*_.d5", "*_.d6", "*_.d7", "*_.d8", \
-"*_.d9", "*_.d10", "*_.d11", "*_.d12", \
-"*_.d13", "*_.d14", "*_.d15", "*_.d16", \
-"*_.d17", "*_.d18", "*_.d19", "*_.d20", \
-"*_.d21", "*_.d22", "*_.d23", "*_.d24", \
-"*_.d25", "*_.d26", "*_.d27", "*_.d28", \
-"*_.d29", "*_.d30", "*_.d31", "*_.d32"
-
-/* First available soft-register for GCC. */
-#define SOFT_REG_FIRST (SOFT_SAVED_XY_REGNUM+2)
-
-/* Last available soft-register for GCC. */
-#define SOFT_REG_LAST (SOFT_REG_FIRST+MAX_SOFT_REG_COUNT)
-#define SOFT_FP_REGNUM (SOFT_REG_LAST)
-#define SOFT_AP_REGNUM (SOFT_FP_REGNUM+1)
-
-/* Number of actual hardware registers. The hardware registers are assigned
- numbers for the compiler from 0 to just below FIRST_PSEUDO_REGISTER.
- All registers that the compiler knows about must be given numbers, even
- those that are not normally considered general registers. */
-#define FIRST_PSEUDO_REGISTER (SOFT_REG_LAST+2)
-
-/* 1 for registers that have pervasive standard uses and are not available
- for the register allocator. */
-#define FIXED_REGISTERS \
- {0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1,1, 1, SOFT_REG_FIXED, 1, 1}
-/* X, D, Y, SP,PC,A, B, CCR, Z, FP,ZTMP,ZR,XYR, FK, D1 - D32, SOFT-FP, AP */
-
-/* 1 for registers not available across function calls. For our pseudo
- registers, all are available. */
-#define CALL_USED_REGISTERS \
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1, 1, SOFT_REG_USED, 1, 1}
-/* X, D, Y, SP,PC,A, B, CCR, Z, FP, ZTMP,ZR,XYR, D1 - 32, SOFT-FP, AP */
-
-
-/* List the order in which to allocate registers. Each register must be
- listed once, even those in FIXED_REGISTERS. */
-#define REG_ALLOC_ORDER \
-{ HARD_D_REGNUM, HARD_X_REGNUM, HARD_Y_REGNUM, \
- SOFT_REG_ORDER, HARD_Z_REGNUM, HARD_PC_REGNUM, HARD_A_REGNUM, \
- HARD_B_REGNUM, HARD_CCR_REGNUM, HARD_FP_REGNUM, SOFT_FP_REGNUM, \
- HARD_SP_REGNUM, SOFT_TMP_REGNUM, SOFT_Z_REGNUM, SOFT_SAVED_XY_REGNUM, \
- SOFT_AP_REGNUM, FAKE_CLOBBER_REGNUM }
-
-/* A C expression for the number of consecutive hard registers,
- starting at register number REGNO, required to hold a value of
- mode MODE. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
-((Q_REGNO_P (REGNO)) ? (GET_MODE_SIZE (MODE)) : \
- ((GET_MODE_SIZE (MODE) + HARD_REG_SIZE - 1) / HARD_REG_SIZE))
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- - 8-bit values are stored anywhere (except the SP register).
- - 16-bit values can be stored in any register whose mode is 16
- - 32-bit values can be stored in D, X registers or in a soft register
- (except the last one because we need 2 soft registers)
- - Values whose size is > 32 bit are not stored in real hard
- registers. They may be stored in soft registers if there are
- enough of them. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- hard_regno_mode_ok (REGNO,MODE)
-
-/* Value is 1 if it is a good idea to tie two pseudo registers when one has
- mode MODE1 and one has mode MODE2. If HARD_REGNO_MODE_OK could produce
- different values for MODE1 and MODE2, for any hard reg, then this must be
- 0 for correct output.
-
- All modes are tieable except QImode. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- (((MODE1) == (MODE2)) \
- || ((MODE1) != QImode && (MODE2) != QImode))
-
-
-/* Define the classes of registers for register constraints in the
- machine description. Also define ranges of constants.
-
- One of the classes must always be named ALL_REGS and include all hard regs.
- If there is more than one class, another class must be named NO_REGS
- and contain no registers.
-
- The name GENERAL_REGS must be the name of a class (or an alias for
- another name such as ALL_REGS). This is the class of registers
- that is allowed by "g" or "r" in a register constraint.
- Also, registers outside this class are allocated only when
- instructions express preferences for them.
-
- The classes must be numbered in nondecreasing order; that is,
- a larger-numbered class must never be contained completely
- in a smaller-numbered class.
-
- For any two classes, it is very desirable that there be another
- class that represents their union. */
-
-/* The M68hc11 has so few registers that it's not possible for GCC to
- do any register allocation without breaking. We extend the processor
- registers by having soft registers. These registers are treated as
- hard registers by GCC but they are located in memory and accessed by page0
- accesses (IND mode). */
-enum reg_class
-{
- NO_REGS,
- D_REGS, /* 16-bit data register */
- X_REGS, /* 16-bit X register */
- Y_REGS, /* 16-bit Y register */
- SP_REGS, /* 16-bit stack pointer */
- DA_REGS, /* 8-bit A reg. */
- DB_REGS, /* 8-bit B reg. */
- Z_REGS, /* 16-bit fake Z register */
- D8_REGS, /* 8-bit A or B reg. */
- Q_REGS, /* 8-bit (byte (QI)) data (A, B or D) */
- D_OR_X_REGS, /* D or X register */
- D_OR_Y_REGS, /* D or Y register */
- D_OR_SP_REGS, /* D or SP register */
- X_OR_Y_REGS, /* IX or Y register */
- A_REGS, /* 16-bit address register (X, Y, Z) */
- X_OR_SP_REGS, /* X or SP register */
- Y_OR_SP_REGS, /* Y or SP register */
- X_OR_Y_OR_D_REGS, /* X, Y or D */
- A_OR_D_REGS, /* X, Y, Z or D */
- A_OR_SP_REGS, /* X, Y, Z or SP */
- H_REGS, /* 16-bit hard register (D, X, Y, Z, SP) */
- S_REGS, /* 16-bit soft register */
- D_OR_S_REGS, /* 16-bit soft register or D register */
- X_OR_S_REGS, /* 16-bit soft register or X register */
- Y_OR_S_REGS, /* 16-bit soft register or Y register */
- Z_OR_S_REGS, /* 16-bit soft register or Z register */
- SP_OR_S_REGS, /* 16-bit soft register or SP register */
- D_OR_X_OR_S_REGS, /* 16-bit soft register or D or X register */
- D_OR_Y_OR_S_REGS, /* 16-bit soft register or D or Y register */
- D_OR_SP_OR_S_REGS, /* 16-bit soft register or D or SP register */
- A_OR_S_REGS, /* 16-bit soft register or X, Y registers */
- D_OR_A_OR_S_REGS, /* 16-bit soft register or D, X, Y registers */
- TMP_REGS, /* 16-bit fake scratch register */
- D_OR_A_OR_TMP_REGS, /* General scratch register */
- G_REGS, /* 16-bit general register
- (H_REGS + soft registers) */
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-/* alias GENERAL_REGS to G_REGS. */
-#define GENERAL_REGS G_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-/* Give names of register classes as strings for dump file. */
-#define REG_CLASS_NAMES \
-{ "NO_REGS", \
- "D_REGS", \
- "X_REGS", \
- "Y_REGS", \
- "SP_REGS", \
- "DA_REGS", \
- "DB_REGS", \
- "D8_REGS", \
- "Z_REGS", \
- "Q_REGS", \
- "D_OR_X_REGS", \
- "D_OR_Y_REGS", \
- "D_OR_SP_REGS", \
- "X_OR_Y_REGS", \
- "A_REGS", \
- "X_OR_SP_REGS", \
- "Y_OR_SP_REGS", \
- "X_OR_Y_OR_D_REGS", \
- "A_OR_D_REGS", \
- "A_OR_SP_REGS", \
- "H_REGS", \
- "S_REGS", \
- "D_OR_S_REGS", \
- "X_OR_S_REGS", \
- "Y_OR_S_REGS", \
- "Z_OR_S_REGS", \
- "SP_OR_S_REGS", \
- "D_OR_X_OR_S_REGS", \
- "D_OR_Y_OR_S_REGS", \
- "D_OR_SP_OR_S_REGS", \
- "A_OR_S_REGS", \
- "D_OR_A_OR_S_REGS", \
- "TMP_REGS", \
- "D_OR_A_OR_TMP_REGS", \
- "G_REGS", \
- "ALL_REGS" }
-
-/* An initializer containing the contents of the register classes,
- as integers which are bit masks. The Nth integer specifies the
- contents of class N. The way the integer MASK is interpreted is
- that register R is in the class if `MASK & (1 << R)' is 1. */
-
-/*--------------------------------------------------------------
- X 0x00000001
- D 0x00000002
- Y 0x00000004
- SP 0x00000008
- PC 0x00000010
- A 0x00000020
- B 0x00000040
- CCR 0x00000080
- Z 0x00000100
- FRAME 0x00000200
- ZTMP 0x00000400
- ZREG 0x00000800
- XYREG 0x00001000
- FAKE 0x00002000
- Di 0xFFFFc000, 0x03FFF
- SFRAME 0x00000000, 0x04000
- AP 0x00000000, 0x08000
-
- D_OR_X_REGS represents D+X. It is used for 32-bits numbers.
- A_REGS represents a valid base register for indexing. It represents
- X,Y and the Z register.
- S_REGS represents the soft-registers. This includes the hard frame
- and soft frame registers.
---------------------------------------------------------------*/
-
-#define REG_CLASS_CONTENTS \
-/* NO_REGS */ {{ 0x00000000, 0x00000000 }, \
-/* D_REGS */ { 0x00000002, 0x00000000 }, /* D */ \
-/* X_REGS */ { 0x00000001, 0x00000000 }, /* X */ \
-/* Y_REGS */ { 0x00000004, 0x00000000 }, /* Y */ \
-/* SP_REGS */ { 0x00000008, 0x00000000 }, /* SP */ \
-/* DA_REGS */ { 0x00000020, 0x00000000 }, /* A */ \
-/* DB_REGS */ { 0x00000040, 0x00000000 }, /* B */ \
-/* Z_REGS */ { 0x00000100, 0x00000000 }, /* Z */ \
-/* D8_REGS */ { 0x00000060, 0x00000000 }, /* A B */ \
-/* Q_REGS */ { 0x00000062, 0x00000000 }, /* A B D */ \
-/* D_OR_X_REGS */ { 0x00000003, 0x00000000 }, /* D X */ \
-/* D_OR_Y_REGS */ { 0x00000006, 0x00000000 }, /* D Y */ \
-/* D_OR_SP_REGS */ { 0x0000000A, 0x00000000 }, /* D SP */ \
-/* X_OR_Y_REGS */ { 0x00000005, 0x00000000 }, /* X Y */ \
-/* A_REGS */ { 0x00000105, 0x00000000 }, /* X Y Z */ \
-/* X_OR_SP_REGS */ { 0x00000009, 0x00000000 }, /* X SP */ \
-/* Y_OR_SP_REGS */ { 0x0000000C, 0x00000000 }, /* Y SP */ \
-/* X_OR_Y_OR_D_REGS */ { 0x00000007, 0x00000000 }, /* D X Y */ \
-/* A_OR_D_REGS */ { 0x00000107, 0x00000000 }, /* D X Y Z */ \
-/* A_OR_SP_REGS */ { 0x0000010D, 0x00000000 }, /* X Y SP */ \
-/* H_REGS */ { 0x0000010F, 0x00000000 }, /* D X Y SP */ \
-/* S_REGS */ { 0xFFFFDE00, 0x00007FFF }, /* _.D,..,FP,Z* */ \
-/* D_OR_S_REGS */ { 0xFFFFDE02, 0x00007FFF }, /* D _.D */ \
-/* X_OR_S_REGS */ { 0xFFFFDE01, 0x00007FFF }, /* X _.D */ \
-/* Y_OR_S_REGS */ { 0xFFFFDE04, 0x00007FFF }, /* Y _.D */ \
-/* Z_OR_S_REGS */ { 0xFFFFDF00, 0x00007FFF }, /* Z _.D */ \
-/* SP_OR_S_REGS */ { 0xFFFFDE08, 0x00007FFF }, /* SP _.D */ \
-/* D_OR_X_OR_S_REGS */ { 0xFFFFDE03, 0x00007FFF }, /* D X _.D */ \
-/* D_OR_Y_OR_S_REGS */ { 0xFFFFDE06, 0x00007FFF }, /* D Y _.D */ \
-/* D_OR_SP_OR_S_REGS */ { 0xFFFFDE0A, 0x00007FFF }, /* D SP _.D */ \
-/* A_OR_S_REGS */ { 0xFFFFDF05, 0x00007FFF }, /* X Y _.D */ \
-/* D_OR_A_OR_S_REGS */ { 0xFFFFDF07, 0x00007FFF }, /* D X Y _.D */ \
-/* TMP_REGS */ { 0x00002000, 0x00000000 }, /* FAKE */ \
-/* D_OR_A_OR_TMP_REGS*/ { 0x00002107, 0x00000000 }, /* D X Y Z Fake */ \
-/* G_REGS */ { 0xFFFFFF1F, 0x00007FFF }, /* ? _.D D X Y */ \
-/* ALL_REGS*/ { 0xFFFFFFFF, 0x00007FFF }}
-
-
-/* set up a C expression whose value is a register class containing hard
- register REGNO */
-#define Q_REGNO_P(REGNO) ((REGNO) == HARD_A_REGNUM \
- || (REGNO) == HARD_B_REGNUM)
-#define Q_REG_P(X) (REG_P (X) && Q_REGNO_P (REGNO (X)))
-
-#define D_REGNO_P(REGNO) ((REGNO) == HARD_D_REGNUM)
-#define D_REG_P(X) (REG_P (X) && D_REGNO_P (REGNO (X)))
-
-#define DB_REGNO_P(REGNO) ((REGNO) == HARD_B_REGNUM)
-#define DB_REG_P(X) (REG_P (X) && DB_REGNO_P (REGNO (X)))
-#define DA_REGNO_P(REGNO) ((REGNO) == HARD_A_REGNUM)
-#define DA_REG_P(X) (REG_P (X) && DA_REGNO_P (REGNO (X)))
-
-#define X_REGNO_P(REGNO) ((REGNO) == HARD_X_REGNUM)
-#define X_REG_P(X) (REG_P (X) && X_REGNO_P (REGNO (X)))
-
-#define Y_REGNO_P(REGNO) ((REGNO) == HARD_Y_REGNUM)
-#define Y_REG_P(X) (REG_P (X) && Y_REGNO_P (REGNO (X)))
-
-#define Z_REGNO_P(REGNO) ((REGNO) == HARD_Z_REGNUM)
-#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X)))
-
-#define SP_REGNO_P(REGNO) ((REGNO) == HARD_SP_REGNUM)
-#define SP_REG_P(X) (REG_P (X) && SP_REGNO_P (REGNO (X)))
-
-/* Address register. */
-#define A_REGNO_P(REGNO) ((REGNO) == HARD_X_REGNUM \
- || (REGNO) == HARD_Y_REGNUM \
- || (REGNO) == HARD_Z_REGNUM)
-#define A_REG_P(X) (REG_P (X) && A_REGNO_P (REGNO (X)))
-
-/* M68hc11 hard registers. */
-#define H_REGNO_P(REGNO) (D_REGNO_P (REGNO) || A_REGNO_P (REGNO) \
- || SP_REGNO_P (REGNO) || Q_REGNO_P (REGNO))
-#define H_REG_P(X) (REG_P (X) && H_REGNO_P (REGNO (X)))
-
-#define FAKE_REGNO_P(REGNO) ((REGNO) == FAKE_CLOBBER_REGNUM)
-#define FAKE_REG_P(X) (REG_P (X) && FAKE_REGNO_P (REGNO (X)))
-
-/* Soft registers (or register emulation for gcc). The temporary register
- used by insn template must be part of the S_REGS class so that it
- matches the 'u' constraint. */
-#define S_REGNO_P(REGNO) ((REGNO) >= SOFT_TMP_REGNUM \
- && (REGNO) <= SOFT_REG_LAST \
- && (REGNO) != FAKE_CLOBBER_REGNUM)
-#define S_REG_P(X) (REG_P (X) && S_REGNO_P (REGNO (X)))
-
-#define Z_REGNO_P(REGNO) ((REGNO) == HARD_Z_REGNUM)
-#define Z_REG_P(X) (REG_P (X) && Z_REGNO_P (REGNO (X)))
-
-/* General register. */
-#define G_REGNO_P(REGNO) (H_REGNO_P (REGNO) || S_REGNO_P (REGNO) \
- || ((REGNO) == HARD_PC_REGNUM) \
- || ((REGNO) == HARD_FP_REGNUM) \
- || ((REGNO) == SOFT_FP_REGNUM) \
- || ((REGNO) == FAKE_CLOBBER_REGNUM) \
- || ((REGNO) == SOFT_AP_REGNUM))
-
-#define G_REG_P(X) (REG_P (X) && G_REGNO_P (REGNO (X)))
-
-#define REGNO_REG_CLASS(REGNO) \
- (D_REGNO_P (REGNO) ? D_REGS : \
- (X_REGNO_P (REGNO) ? X_REGS : \
- (Y_REGNO_P (REGNO) ? Y_REGS : \
- (SP_REGNO_P (REGNO) ? SP_REGS : \
- (Z_REGNO_P (REGNO) ? Z_REGS : \
- (H_REGNO_P (REGNO) ? H_REGS : \
- (FAKE_REGNO_P (REGNO) ? TMP_REGS : \
- (S_REGNO_P (REGNO) ? S_REGS : \
- (DA_REGNO_P (REGNO) ? DA_REGS: \
- (DB_REGNO_P (REGNO) ? DB_REGS: \
- (G_REGNO_P (REGNO) ? G_REGS : ALL_REGS)))))))))))
-
-
-/* Get reg_class from a letter in the machine description. */
-
-extern enum reg_class m68hc11_tmp_regs_class;
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'a' ? DA_REGS : \
- (C) == 'A' ? A_REGS : \
- (C) == 'b' ? DB_REGS : \
- (C) == 'B' ? X_OR_Y_REGS : \
- (C) == 'd' ? D_REGS : \
- (C) == 'D' ? D_OR_X_REGS : \
- (C) == 'q' ? Q_REGS : \
- (C) == 'h' ? H_REGS : \
- (C) == 't' ? TMP_REGS : \
- (C) == 'u' ? S_REGS : \
- (C) == 'v' ? m68hc11_tmp_regs_class : \
- (C) == 'w' ? SP_REGS : \
- (C) == 'x' ? X_REGS : \
- (C) == 'y' ? Y_REGS : \
- (C) == 'z' ? Z_REGS : NO_REGS)
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS) preferred_reload_class(X,CLASS)
-
-#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
-
-/* A C expression that is nonzero if hard register number REGNO2 can be
- considered for use as a rename register for REGNO1 */
-
-#define HARD_REGNO_RENAME_OK(REGNO1,REGNO2) \
- m68hc11_hard_regno_rename_ok ((REGNO1), (REGNO2))
-
-/* Return the maximum number of consecutive registers needed to represent
- mode MODE in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
-(((CLASS) == DA_REGS || (CLASS) == DB_REGS \
- || (CLASS) == D8_REGS || (CLASS) == Q_REGS) ? GET_MODE_SIZE (MODE) \
- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
-/* The letters I, J, K, L and M in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- This macro defines what the ranges are.
- C is the letter, and VALUE is a constant value.
- Return 1 if VALUE is in the range specified by C.
-
- `K' is for 0.
- `L' is for range -65536 to 65536
- `M' is for values whose 16-bit low part is 0
- 'N' is for +1 or -1.
- 'O' is for 16 (for rotate using swap).
- 'P' is for range -8 to 2 (used by addhi_sp)
-
- 'I', 'J' are not used. */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'K' ? (VALUE) == 0 : \
- (C) == 'L' ? ((VALUE) >= -65536 && (VALUE) <= 65535) : \
- (C) == 'M' ? ((VALUE) & 0x0ffffL) == 0 : \
- (C) == 'N' ? ((VALUE) == 1 || (VALUE) == -1) : \
- (C) == 'I' ? ((VALUE) >= -2 && (VALUE) <= 2) : \
- (C) == 'O' ? (VALUE) == 16 : \
- (C) == 'P' ? ((VALUE) <= 2 && (VALUE) >= -8) : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-
- `G' is for 0.0. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
- && VALUE == CONST0_RTX (GET_MODE (VALUE))) : 0)
-
-/* 'U' represents certain kind of memory indexed operand for 68HC12.
- and any memory operand for 68HC11.
- 'R' represents indexed addressing mode or access to page0 for 68HC11.
- For 68HC12, it represents any memory operand. */
-#define EXTRA_CONSTRAINT(OP, C) \
-((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) \
- : (C) == 'Q' ? m68hc11_symbolic_p (OP, GET_MODE (OP)) \
- : (C) == 'R' ? m68hc11_indirect_p (OP, GET_MODE (OP)) \
- : (C) == 'S' ? (memory_operand (OP, GET_MODE (OP)) \
- && non_push_operand (OP, GET_MODE (OP))) : 0)
-
-
-/* Stack layout; function entry, exit and calling. */
-
-/* Define this if pushing a word on the stack
- makes the stack pointer a smaller address. */
-#define STACK_GROWS_DOWNWARD
-
-/* Define this to nonzero if the nominal address of the stack frame
- is at the high-address end of the local variables;
- that is, each additional local variable allocated
- goes at a more negative offset in the frame.
-
- Define to 0 for 68HC11, the frame pointer is the bottom
- of local variables. */
-#define FRAME_GROWS_DOWNWARD 0
-
-/* Define this if successive arguments to a function occupy decreasing
- addresses in the stack. */
-/* #define ARGS_GROW_DOWNWARD */
-
-/* Offset within stack frame to start allocating local variables at.
- If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
- first local allocated. Otherwise, it is the offset to the BEGINNING
- of the first local allocated. */
-#define STARTING_FRAME_OFFSET 0
-
-/* Offset of first parameter from the argument pointer register value. */
-
-#define FIRST_PARM_OFFSET(FNDECL) 2
-
-/* After the prologue, RA is at 0(AP) in the current frame. */
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
- ((COUNT) == 0 \
- ? gen_rtx_MEM (Pmode, arg_pointer_rtx) \
- : 0)
-
-/* Before the prologue, the top of the frame is at 2(sp). */
-#define INCOMING_FRAME_SP_OFFSET 2
-
-/* Define this if functions should assume that stack space has been
- allocated for arguments even when their values are passed in
- registers.
-
- The value of this macro is the size, in bytes, of the area reserved for
- arguments passed in registers.
-
- This space can either be allocated by the caller or be a part of the
- machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE'
- says which. */
-/* #define REG_PARM_STACK_SPACE(FNDECL) 2 */
-
-/* Define this macro if REG_PARM_STACK_SPACE is defined but stack
- parameters don't skip the area specified by REG_PARM_STACK_SPACE.
- Normally, when a parameter is not passed in registers, it is placed on
- the stack beyond the REG_PARM_STACK_SPACE area. Defining this macro
- suppresses this behavior and causes the parameter to be passed on the
- stack in its natural location. */
-/* #define STACK_PARMS_IN_REG_PARM_AREA */
-
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM HARD_SP_REGNUM
-
-/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM SOFT_FP_REGNUM
-
-#define HARD_FRAME_POINTER_REGNUM HARD_FP_REGNUM
-
-/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM SOFT_AP_REGNUM
-
-/* Register in which static-chain is passed to a function. */
-#define STATIC_CHAIN_REGNUM SOFT_Z_REGNUM
-
-
-/* Definitions for register eliminations.
-
- This is an array of structures. Each structure initializes one pair
- of eliminable registers. The "from" register number is given first,
- followed by "to". Eliminations of the same "from" register are listed
- in order of preference.
-
- We have two registers that are eliminated on the 6811. The pseudo arg
- pointer and pseudo frame pointer registers can always be eliminated;
- they are replaced with either the stack or the real frame pointer. */
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
-
-/* Define the offset between two registers, one to be eliminated, and the other
- its replacement, at the start of a routine. */
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- { OFFSET = m68hc11_initial_elimination_offset (FROM, TO); }
-
-
-/* Passing Function Arguments on the Stack. */
-
-/* If we generate an insn to push BYTES bytes, this says how many the
- stack pointer really advances by. No rounding or alignment needed
- for MC6811. */
-#define PUSH_ROUNDING(BYTES) (BYTES)
-
-/* Passing Arguments in Registers. */
-
-/* Define a data type for recording info about an argument list
- during the scan of that argument list. This data type should
- hold all necessary information about the function itself
- and about the args processed so far, enough to enable macros
- such as FUNCTION_ARG to determine where the next arg should go. */
-
-typedef struct m68hc11_args
-{
- int words;
- int nregs;
-} CUMULATIVE_ARGS;
-
-/* If defined, a C expression which determines whether, and in which direction,
- to pad out an argument with extra space. The value should be of type
- `enum direction': either `upward' to pad above the argument,
- `downward' to pad below, or `none' to inhibit padding.
-
- Structures are stored left shifted in their argument slot. */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- m68hc11_function_arg_padding ((MODE), (TYPE))
-
-#undef PAD_VARARGS_DOWN
-#define PAD_VARARGS_DOWN \
- (m68hc11_function_arg_padding (TYPE_MODE (type), type) == downward)
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a
- function whose data type is FNTYPE. For a library call, FNTYPE is 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
- (m68hc11_init_cumulative_args (&CUM, FNTYPE, LIBNAME))
-
-/* Define the profitability of saving registers around calls.
-
- Disable this because the saving instructions generated by
- caller-save need a reload and the way it is implemented,
- it forbids all spill registers at that point. Enabling
- caller saving results in spill failure. */
-#define CALLER_SAVE_PROFITABLE(REFS,CALLS) 0
-
-/* 1 if N is a possible register number for function argument passing.
- D is for 16-bit values, X is for 32-bit (X+D). */
-#define FUNCTION_ARG_REGNO_P(N) \
- (((N) == HARD_D_REGNUM) || ((N) == HARD_X_REGNUM))
-
-/* All return values are in the D or X+D registers:
- - 8 and 16-bit values are returned in D.
- BLKmode are passed in D as pointer.
- - 32-bit values are returned in X + D.
- The high part is passed in X and the low part in D.
- For GCC, the register number must be HARD_X_REGNUM. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG (TYPE_MODE (VALTYPE), \
- ((TYPE_MODE (VALTYPE) == BLKmode \
- || GET_MODE_SIZE (TYPE_MODE (VALTYPE)) <= 2) \
- ? HARD_D_REGNUM : HARD_X_REGNUM))
-
-#define LIBCALL_VALUE(MODE) \
- gen_rtx_REG (MODE, \
- (((MODE) == BLKmode || GET_MODE_SIZE (MODE) <= 2) \
- ? HARD_D_REGNUM : HARD_X_REGNUM))
-
-/* 1 if N is a possible register number for a function value. */
-#define FUNCTION_VALUE_REGNO_P(N) \
- ((N) == HARD_D_REGNUM || (N) == HARD_X_REGNUM)
-
-/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
- the stack pointer does not matter. The value is tested only in functions
- that have frame pointers. No definition is equivalent to always zero. */
-#define EXIT_IGNORE_STACK 0
-
-
-/* Generating Code for Profiling. */
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- fprintf (FILE, "\tldy\t.LP%d\n\tjsr mcount\n", (LABELNO))
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE (TARGET_M6811 ? 11 : 9)
-
-
-/* Addressing modes, and classification of registers for them. */
-
-#define ADDR_STRICT 0x01 /* Accept only registers in class A_REGS */
-#define ADDR_INCDEC 0x02 /* Post/Pre inc/dec */
-#define ADDR_INDEXED 0x04 /* D-reg index */
-#define ADDR_OFFSET 0x08
-#define ADDR_INDIRECT 0x10 /* Accept (mem (mem ...)) for [n,X] */
-#define ADDR_CONST 0x20 /* Accept const and symbol_ref */
-
-/* The 68HC12 has all the post/pre increment/decrement modes. */
-#define HAVE_POST_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_PRE_INCREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_POST_DECREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-#define HAVE_PRE_DECREMENT (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-
-/* The class value for base registers. This depends on the target:
- A_REGS for 68HC11 and A_OR_SP_REGS for 68HC12. The class value
- is stored at init time. */
-extern enum reg_class m68hc11_base_reg_class;
-#define BASE_REG_CLASS m68hc11_base_reg_class
-
-/* The class value for index registers. This is NO_REGS for 68HC11. */
-
-extern enum reg_class m68hc11_index_reg_class;
-#define INDEX_REG_CLASS m68hc11_index_reg_class
-
-/* These assume that REGNO is a hard or pseudo reg number. They give nonzero
- only if REGNO is a hard reg of the suitable class or a pseudo reg currently
- allocated to a suitable hard reg. Since they use reg_renumber, they are
- safe only once reg_renumber has been allocated, which happens in
- local-alloc.c. */
-
-
-extern unsigned char m68hc11_reg_valid_for_base[FIRST_PSEUDO_REGISTER];
-#define REG_VALID_FOR_BASE_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER \
- && m68hc11_reg_valid_for_base[REGNO])
-
-/* Internal macro, return 1 if REGNO is a valid index register. */
-extern unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
-#define REG_VALID_FOR_INDEX_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER \
- && m68hc11_reg_valid_for_index[REGNO])
-
-/* Internal macro, the nonstrict definition for REGNO_OK_FOR_BASE_P. */
-#define REGNO_OK_FOR_BASE_NONSTRICT_P(REGNO) \
- ((REGNO) >= FIRST_PSEUDO_REGISTER \
- || REG_VALID_FOR_BASE_P (REGNO) \
- || (REGNO) == FRAME_POINTER_REGNUM \
- || (REGNO) == HARD_FRAME_POINTER_REGNUM \
- || (REGNO) == ARG_POINTER_REGNUM \
- || (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
-
-/* Internal macro, the nonstrict definition for REGNO_OK_FOR_INDEX_P. */
-#define REGNO_OK_FOR_INDEX_NONSTRICT_P(REGNO) \
- (TARGET_M6812 \
- && ((REGNO) >= FIRST_PSEUDO_REGISTER \
- || REG_VALID_FOR_INDEX_P (REGNO) \
- || (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))))
-
-/* Internal macro, the strict definition for REGNO_OK_FOR_BASE_P. */
-#define REGNO_OK_FOR_BASE_STRICT_P(REGNO) \
- ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_BASE_P (REGNO) \
- : (reg_renumber && REG_VALID_FOR_BASE_P (reg_renumber[REGNO])))
-
-/* Internal macro, the strict definition for REGNO_OK_FOR_INDEX_P. */
-#define REGNO_OK_FOR_INDEX_STRICT_P(REGNO) \
- (TARGET_M6812 \
- && ((REGNO) < FIRST_PSEUDO_REGISTER ? REG_VALID_FOR_INDEX_P (REGNO) \
- : (reg_renumber && REG_VALID_FOR_INDEX_P (reg_renumber[REGNO]))))
-
-#define REGNO_OK_FOR_BASE_P2(REGNO,STRICT) \
- ((STRICT) ? (REGNO_OK_FOR_BASE_STRICT_P (REGNO)) \
- : (REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO)))
-
-#define REGNO_OK_FOR_INDEX_P2(REGNO,STRICT) \
- ((STRICT) ? (REGNO_OK_FOR_INDEX_STRICT_P (REGNO)) \
- : (REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO)))
-
-#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_BASE_STRICT_P (REGNO)
-#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_INDEX_STRICT_P (REGNO)
-
-#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_STRICT_P (REGNO (X))
-#define REG_OK_FOR_BASE_NONSTRICT_P(X) REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (X))
-#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_STRICT_P (REGNO (X))
-#define REG_OK_FOR_INDEX_NONSTRICT_P(X) REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (X))
-
-/* see PUSH_POP_ADDRESS_P() below for an explanation of this. */
-#define IS_STACK_PUSH(operand) \
- ((GET_CODE (operand) == MEM) \
- && (GET_CODE (XEXP (operand, 0)) == PRE_DEC) \
- && (SP_REG_P (XEXP (XEXP (operand, 0), 0))))
-
-#define IS_STACK_POP(operand) \
- ((GET_CODE (operand) == MEM) \
- && (GET_CODE (XEXP (operand, 0)) == POST_INC) \
- && (SP_REG_P (XEXP (XEXP (operand, 0), 0))))
-
-/* Maximum number of registers that can appear in a valid memory address */
-#define MAX_REGS_PER_ADDRESS 2
-
-/* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression that is a
- valid memory address for an instruction. The MODE argument is the
- machine mode for the MEM expression that wants to use this address. */
-
-/*--------------------------------------------------------------
- Valid addresses are either direct or indirect (MEM) versions
- of the following forms:
- constant N
- register ,X
- indexed N,X
---------------------------------------------------------------*/
-
-/* The range of index that is allowed by indirect addressing. */
-
-#define VALID_MIN_OFFSET m68hc11_min_offset
-#define VALID_MAX_OFFSET m68hc11_max_offset
-
-/* The offset values which are allowed by the n,x and n,y addressing modes.
- Take into account the size of the mode because we may have to add
- a mode offset to access the lowest part of the data.
- (For example, for an SImode, the last valid offset is 252.) */
-#define VALID_CONSTANT_OFFSET_P(X,MODE) \
-(((GET_CODE (X) == CONST_INT) && \
- ((INTVAL (X) >= VALID_MIN_OFFSET) \
- && ((INTVAL (X) <= VALID_MAX_OFFSET \
- - (HOST_WIDE_INT) (GET_MODE_SIZE (MODE) + 1))))) \
-|| (TARGET_M6812 \
- && ((GET_CODE (X) == SYMBOL_REF) \
- || GET_CODE (X) == LABEL_REF \
- || GET_CODE (X) == CONST)))
-
-/* This is included to allow stack push/pop operations. Special hacks in the
- md and m6811.c files exist to support this. */
-#define PUSH_POP_ADDRESS_P(X) \
- (((GET_CODE (X) == PRE_DEC) || (GET_CODE (X) == POST_INC)) \
- && SP_REG_P (XEXP (X, 0)))
-
-/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx and check its
- validity for a certain class. We have two alternate definitions for each
- of them. The usual definition accepts all pseudo regs; the other rejects
- them unless they have been allocated suitable hard regs. The symbol
- REG_OK_STRICT causes the latter definition to be used.
-
- Most source files want to accept pseudo regs in the hope that they will
- get allocated to the class that the insn wants them to be in. Source files
- for reload pass need to be strict. After reload, it makes no difference,
- since pseudo regs have been eliminated by then. */
-
-#ifndef REG_OK_STRICT
-/* Nonzero if X is a hard reg that can be used as a base reg. */
-#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P(X)
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P(X)
-#else
-#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P(X)
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P(X)
-#endif
-
-
-/* Nonzero if the constant value X is a legitimate general operand.
- It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-#define LEGITIMATE_CONSTANT_P(X) 1
-
-
-/* Tell final.c how to eliminate redundant test instructions. */
-
-#define NOTICE_UPDATE_CC(EXP, INSN) \
- m68hc11_notice_update_cc ((EXP), (INSN))
-
-/* Move costs between classes of registers */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
- (m68hc11_register_move_cost (MODE, CLASS1, CLASS2))
-
-/* Move cost between register and memory.
- - Move to a 16-bit register is reasonable,
- - Move to a soft register can be expensive. */
-#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
- m68hc11_memory_move_cost ((MODE),(CLASS),(IN))
-
-/* A C expression for the cost of a branch instruction. A value of 1
- is the default; other values are interpreted relative to that.
-
- Pretend branches are cheap because GCC generates sub-optimal code
- for the default value. */
-#define BRANCH_COST(speed_p, predictable_p) 0
-
-/* Nonzero if access to memory by bytes is slow and undesirable. */
-#define SLOW_BYTE_ACCESS 0
-
-/* It is as good to call a constant function address as to call an address
- kept in a register. */
-#define NO_FUNCTION_CSE
-
-/* Try a machine-dependent way of reloading an illegitimate address
- operand. If we find one, push the reload and jump to WIN. This
- macro is used in only one place: `find_reloads_address' in reload.c.
-
- For M68HC11, we handle large displacements of a base register
- by splitting the addend across an addhi3 insn.
-
- For M68HC12, the 64K offset range is available.
- */
-
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-do { \
- /* We must recognize output that we have already generated ourselves. */ \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
- && GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- if (GET_CODE (X) == PLUS \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && !VALID_CONSTANT_OFFSET_P (XEXP (X, 1), MODE)) \
- { \
- HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
- HOST_WIDE_INT low, high; \
- high = val & (~0x0FF); \
- low = val & 0x00FF; \
- if (low >= 256-15) { high += 16; low -= 16; } \
- /* Reload the high part into a base reg; leave the low part \
- in the mem directly. */ \
- \
- X = gen_rtx_PLUS (Pmode, \
- gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- GEN_INT (high)), \
- GEN_INT (low)); \
- \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
-} while (0)
-
-
-/* Defining the Output Assembler Language. */
-
-/* A default list of other sections which we might be "in" at any given
- time. For targets that use additional sections (e.g. .tdesc) you
- should override this definition in the target-specific file which
- includes this file. */
-
-/* Output before read-only data. */
-#define TEXT_SECTION_ASM_OP ("\t.sect\t.text")
-
-/* Output before writable data. */
-#define DATA_SECTION_ASM_OP ("\t.sect\t.data")
-
-/* Output before uninitialized data. */
-#define BSS_SECTION_ASM_OP ("\t.sect\t.bss")
-
-/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
-
- Same as config/elfos.h but don't mark these section SHF_WRITE since
- there is no shared library problem. */
-#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"a\""
-
-#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"a\""
-
-#define TARGET_ASM_CONSTRUCTOR m68hc11_asm_out_constructor
-#define TARGET_ASM_DESTRUCTOR m68hc11_asm_out_destructor
-
-/* Comment character */
-#define ASM_COMMENT_START ";"
-
-/* Output to assembler file text saying following lines
- may contain character constants, extra white space, comments, etc. */
-#define ASM_APP_ON "; Begin inline assembler code\n#APP\n"
-
-/* Output to assembler file text saying following lines
- no longer contain unusual constructs. */
-#define ASM_APP_OFF "; End of inline assembler code\n#NO_APP\n"
-
-/* Write the extra assembler code needed to declare a function properly.
- Some svr4 assemblers need to also have something extra said about the
- function's return value. We allow for that here.
-
- For 68HC12 we mark functions that return with 'rtc'. The linker
- will ensure that a 'call' is really made (instead of 'jsr').
- The debugger needs this information to correctly compute the stack frame.
-
- For 68HC11/68HC12 we also mark interrupt handlers for gdb to
- compute the correct stack frame. */
-
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- \
- if (current_function_far) \
- { \
- fprintf (FILE, "\t.far\t"); \
- assemble_name (FILE, NAME); \
- putc ('\n', FILE); \
- } \
- else if (current_function_interrupt \
- || current_function_trap) \
- { \
- fprintf (FILE, "\t.interrupt\t"); \
- assemble_name (FILE, NAME); \
- putc ('\n', FILE); \
- } \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
- while (0)
-
-/* Output #ident as a .ident. */
-
-/* output external reference */
-#undef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) \
- {fputs ("\t; extern\t", FILE); \
- assemble_name (FILE, NAME); \
- fputs ("\n", FILE);}
-
-/* How to refer to registers in assembler output. This sequence is indexed
- by compiler's hard-register-number (see above). */
-#define REGISTER_NAMES \
-{ "x", "d", "y", "sp", "pc", "a", "b", "ccr", "z", \
- "*_.frame", "*_.tmp", "*_.z", "*_.xy", "*fake clobber", \
- SOFT_REG_NAMES, "*sframe", "*ap"}
-
-/* This is how to output an insn to push/pop a register on the stack.
- It need not be very fast code.
-
- Don't define because we don't know how to handle that with
- the STATIC_CHAIN_REGNUM (soft register). Saving the static
- chain must be made inside FUNCTION_PROFILER. */
-
-#undef ASM_OUTPUT_REG_PUSH
-#undef ASM_OUTPUT_REG_POP
-
-/* This is how to output an element of a case-vector that is relative. */
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- fprintf (FILE, "\t%s\tL%d-L%d\n", integer_asm_op (2, TRUE), VALUE, REL)
-
-/* This is how to output an element of a case-vector that is absolute. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "\t%s\t.L%d\n", integer_asm_op (2, TRUE), VALUE)
-
-/* This is how to output an assembler line that says to advance the
- location counter to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- do { \
- if ((LOG) > 1) \
- fprintf ((FILE), "%s\n", ALIGN_ASM_OP); \
- } while (0)
-
-
-/* Assembler Commands for Exception Regions. */
-
-/* Default values provided by GCC should be ok. Assuming that DWARF-2
- frame unwind info is ok for this platform. */
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-/* For the support of memory banks we need addresses that indicate
- the page number. */
-#define DWARF2_ADDR_SIZE 4
-
-/* SCz 2003-07-08: Don't use as dwarf2 .file/.loc directives because
- the linker is doing relaxation and it does not adjust the debug_line
- sections when it shrinks the code. This results in invalid addresses
- when debugging. This does not bless too much the HC11/HC12 as most
- applications are embedded and small, hence a reasonable debug info.
- This problem is known for binutils 2.13, 2.14 and mainline. */
-#undef HAVE_AS_DWARF2_DEBUG_LINE
-
-/* The prefix for local labels. You should be able to define this as
- an empty string, or any arbitrary string (such as ".", ".L%", etc)
- without having to make any other changes to account for the specific
- definition. Note it is a string literal, not interpreted by printf
- and friends. */
-#define LOCAL_LABEL_PREFIX "."
-
-/* The prefix for immediate operands. */
-#define IMMEDIATE_PREFIX "#"
-#define GLOBAL_ASM_OP "\t.globl\t"
-
-
-/* Miscellaneous Parameters. */
-
-/* Specify the machine mode that this machine uses
- for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE Pmode
-
-/* This flag, if defined, says the same insns that convert to a signed fixnum
- also convert validly to an unsigned one. */
-#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
-
-/* Max number of bytes we can move from memory to memory in one
- reasonably fast instruction. */
-#define MOVE_MAX 2
-
-/* MOVE_RATIO is the number of move instructions that is better than a
- block move. Make this small on 6811, since the code size grows very
- large with each move. */
-#define MOVE_RATIO(speed) 3
-
-/* Define if shifts truncate the shift count which implies one can omit
- a sign-extension or zero-extension of a shift count. */
-#define SHIFT_COUNT_TRUNCATED 1
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-/* Specify the machine mode that pointers have. After generation of rtl, the
- compiler makes no further distinction between pointers and any other
- objects of this machine mode. */
-#define Pmode HImode
-
-/* A function address in a call instruction is a byte address (for indexing
- purposes) so give the MEM rtx a byte's mode. */
-#define FUNCTION_MODE QImode
-
-extern int debug_m6811;
-extern int z_replacement_completed;
-extern int current_function_interrupt;
-extern int current_function_trap;
-extern int current_function_far;
-
-extern GTY(()) rtx m68hc11_soft_tmp_reg;
-extern GTY(()) rtx ix_reg;
-extern GTY(()) rtx iy_reg;
-extern GTY(()) rtx d_reg;
diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md
deleted file mode 100644
index f4ff3ebbb4c..00000000000
--- a/gcc/config/m68hc11/m68hc11.md
+++ /dev/null
@@ -1,7579 +0,0 @@
-;;- Machine description file for Motorola 68HC11 and 68HC12.
-;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
-;;- Free Software Foundation, Inc.
-;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; Note:
-;; A first 68HC11 port was made by Otto Lind (otto@coactive.com)
-;; on gcc 2.6.3. I have used it as a starting point for this port.
-;; However, this new port is a complete re-write. Its internal
-;; design is completely different. The generated code is not
-;; compatible with the gcc 2.6.3 port.
-;;
-;; The gcc 2.6.3 port is available at:
-;;
-;; ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
-;;
-
-;;- Instruction patterns. When multiple patterns apply,
-;;- the first one in the file is chosen.
-;;-
-;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
-;;-
-;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
-;;- updates for most instructions.
-
-;;
-;; The following constraints are used:
-;;
-;; Single pair registers:
-;; a register 'a' 8-bit
-;; b register 'b' 8-bit
-;; d register 'd' 16-bit
-;; t pseudo soft register 'TMP' 16-bit
-;; v register 'd' for 68hc11, 16-bit
-;; NO_REG for 68hc12
-;; (used for scratch register)
-;; w register 'sp' 16-bit
-;; x register 'x' 16-bit
-;; y register 'y' 16-bit
-;; z register 'z' 16-bit (fake r for 68HC11 and 68HC12)
-;; D register 'd+x' 32-bit
-;;
-;; Group of registers:
-;; q register 'a' or 'b' or 'd' 8-bit
-;; u pseudo soft register 16-bit
-;; A register 'x', 'y', 'z' 16-bit
-;; B register 'x', 'y' 16-bit
-;; h register 'd', 'x', 'y', 'z' 16-bit
-;;
-;; Other constraints:
-;;
-;; Q an operand which is in memory but whose address is constant
-;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by
-;; bset/bclr instructions together with linker relaxation. The
-;; operand can be translated to a page0 addressing mode if the
-;; symbol address is in page0 (0..255).
-;;
-;; R an operand which is in memory and whose address is expressed
-;; with 68HC11/68HC12 indexed addressing mode. In general this
-;; is any valid (MEM) except a (MEM (SYMBOL_REF x)).
-;;
-;; U an operand which is in memory and if it uses the 68HC12 indexed
-;; addressing mode, the offset is in the range -16..+15. This is
-;; used by 68HC12 movb/movw instructions since they do not accept
-;; the full 16-bit offset range (as other insn do).
-;;
-;;
-;; Immediate integer operand constraints:
-;; `L' is for range -65536 to 65536
-;; `M' is for values whose 16-bit low part is 0
-;; 'N' is for +1 or -1.
-;; 'O' is for 16 (for rotate using swap).
-;; 'P' is for range -8 to 2 (used by addhi_sp)
-;;
-;; In many cases, it's not possible to use the 'g' or 'r' constraints.
-;;
-;; Operands modifiers:
-;;
-;; %b Get the low part of the operand (to obtain a QImode)
-;; This modifier must always be used for QImode operations
-;; because a correction must be applied when the operand
-;; is a soft register (ex: *ZD1). Otherwise, we generate
-;; *ZD1 and this is the high part of the register. For other
-;; kinds of operands, if the operand is already QImode, no
-;; additional correction is made.
-;; %h Get the high part of the operand (to obtain a QImode)
-;; %t Represents the temporary/scratch register *_.tmp
-;; The scratch register is used in some cases when GCC puts
-;; some values in bad registers.
-;;
-;; 32/64-bit Patterns:
-;; The 68HC11 does not support 32/64-bit operations. Most of the
-;; 32/64-bit patterns are defined to split the instruction in
-;; 16-bits patterns. Providing split patterns generates better code
-;; than letting GCC implement the 32/64-bit operation itself.
-;;
-;;
-;; Notes:
-;;
-;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
-;; otherwise some insn are not satisfied.
-;;
-;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
-;; be valid only when z_replacement_completed == 2 because once these
-;; swap instructions are generated, a flow/cse pass fails to handle
-;; them correctly (it would treat the X, Y or D register as dead sometimes).
-;;
-;; o Some split pattern generate instructions that operate on 'a' or 'b'
-;; register directly (high part and low part of D respectively).
-;; Such split pattern must also be valid when z_replacement_completed == 2
-;; because flow/cse is not aware that D is composed of {a, b}.
-;;
-;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
-;; the high part of a soft register must be expanded after z_replacement
-;; pass.
-;;
-;;---------------------------------------------------------------------------
-;; Constants
-
-(define_constants [
- ;; Register numbers
- (X_REGNUM 0) ; Index X register
- (D_REGNUM 1) ; Data register
- (Y_REGNUM 2) ; Index Y register
- (SP_REGNUM 3) ; Stack pointer
- (PC_REGNUM 4) ; Program counter
- (A_REGNUM 5) ; A (high part of D)
- (B_REGNUM 6) ; B (low part of D)
- (CC_REGNUM 7) ; Condition code register
- (SOFT_TMP_REGNUM 10) ; TMP soft register
- (SOFT_Z_REGNUM 11) ; Z soft register
- (SOFT_XY_REGNUM 12) ; XY soft register
-])
-
-(include "predicates.md")
-
-;;--------------------------------------------------------------------
-;;- Test
-;;--------------------------------------------------------------------
-;;
-;; The test and compare insn must not accept a memory operand with
-;; an auto-inc mode. If we do this, the reload can emit move insns
-;; after the test or compare. Such move will set the flags and therefore
-;; break the comparison. This can happen if the auto-inc register
-;; does not happen to be a hard register (i.e., reloading occurs).
-;; An offsetable memory operand should be ok. The 'tst_operand' and
-;; 'cmp_operand' predicates take care of this rule.
-;;
-
-(define_insn "tsthi_1"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "dx,*y")
- (const_int 0)))]
- ""
- "*
-{
- if (D_REG_P (operands[0]) && !TARGET_M6812)
- return \"std\\t%t0\";
- else
- return \"cp%0\\t#0\";
-}")
-
-;;
-;; Split pattern for (tst:QI) on an address register.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
- (const_int 0)))]
- "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 1) (reg:HI D_REGNUM))])
- (set (cc0) (compare (reg:QI D_REGNUM)
- (const_int 0)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 1) (reg:HI D_REGNUM))])]
- "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-(define_insn "tstqi_1"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "m,d,*A,!u")
- (const_int 0)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- else if (D_REG_P (operands[0]))
- return \"tstb\";
-
- else if (dead_register_here (insn, d_reg))
- return \"ldab\\t%b0\";
-
- else
- return \"tst\\t%b0\";
-}")
-
-;;
-;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
-;; during the Z register replacement. They are used when an operand
-;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
-;; In that case, we have to preserve the values of the replacement
-;; register (as well as the CC0 since the insns are compare insns).
-;; To do this, the replacement register is pushed on the stack and
-;; restored after the real compare. A pattern+split is defined to
-;; avoid problems with the flow+cse register pass which are made
-;; after Z register replacement.
-;;
-(define_insn_and_split "tstqi_z_used"
- [(set (cc0) (compare (match_operand:QI 0 "tst_operand" "m")
- (const_int 0)))
- (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
- (set (match_dup 1) (match_dup 2))
- (set (cc0) (compare (match_dup 0)
- (const_int 0)))
- (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-
-;;--------------------------------------------------------------------
-;;- Compare
-;;--------------------------------------------------------------------
-
-;;
-;; Comparison of a hard register with another one is provided because
-;; it helps GCC to avoid to spill a pseudo hard register.
-;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
-;; (except that we loose the information that the value is saved in it).
-;;
-;; The split pattern transforms the comparison into a save of one hard
-;; register and a comparison with the temporary.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" "")))]
- "TARGET_M6811
- && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
- [(set (match_dup 2) (match_dup 1))
- (set (cc0)
- (compare (match_dup 0) (match_dup 2)))]
- "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
-
-(define_split
- [(set (cc0)
- (compare (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" "")))]
- "0 && TARGET_M6812
- && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
- (set (cc0)
- (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
- "")
-
-(define_insn "cmphi_1_hc12"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand"
- "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
- (match_operand:HI 1 "general_operand"
- "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
- "TARGET_M6812"
- "*
-{
- if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
- {
- cc_status.flags |= CC_REVERSED;
- return \"cp%1\\t%0\";
- }
- else if (SP_REG_P (operands[1]))
- return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
- else if (H_REG_P (operands[1]))
- return \"psh%1\n\\tcp%0\\t2,sp+\";
- else
- return \"cp%0\\t%1\";
-}")
-
-(define_insn "cmphi_1_hc11"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand"
- "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
- (match_operand:HI 1 "cmp_operand"
- "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
- "TARGET_M6811"
- "*
-{
- if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
- {
- cc_status.flags |= CC_REVERSED;
- return \"cp%1\\t%0\";
- }
- else if (H_REG_P (operands[1]))
- return \"#\";
- else
- return \"cp%0\\t%1\";
-}")
-
-(define_insn_and_split "cmphi_z_used"
- [(set (cc0)
- (compare (match_operand:HI 0 "tst_operand" "dxy,m")
- (match_operand:HI 1 "cmp_operand" "mi,dxy")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (compare (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-;;
-;; 8-bit comparison with address register.
-;; There is no such comparison instruction, we have to temporarily switch
-;; the address register and the D register and do the comparison with D.
-;; The xgdx and xgdy instructions preserve the flags.
-;;
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operand:QI 1 "cmp_operand" "")))]
- "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (cc0)
- (compare (reg:QI D_REGNUM) (match_dup 1)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-(define_split
- [(set (cc0)
- (compare (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "hard_reg_operand" "")))]
- "reload_completed"
- [(set (match_dup 3) (match_dup 4))
- (set (cc0)
- (compare (match_dup 0) (match_dup 2)))]
- "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-
-(define_insn "bitcmpqi"
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
- (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d"))
- (const_int 0)))]
- ""
- "@
- bitb\\t%b1
- #
- bitb\\t%b1
- bitb\\t%b0
- bitb\\t%b0")
-
-(define_split /* "bitcmpqi" */
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "")
- (match_operand:QI 1 "hard_addr_reg_operand" ""))
- (const_int 0)))]
- "z_replacement_completed == 2"
- [(set (match_dup 3) (match_dup 2))
- (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
- operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
-
-(define_insn_and_split "bitcmpqi_z_used"
- [(set (cc0)
- (compare (and:QI (match_operand:QI 0 "tst_operand" "d,m")
- (match_operand:QI 1 "cmp_operand" "m,d"))
- (const_int 0)))
- (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-(define_insn "bitcmphi"
- [(set (cc0)
- (compare (and:HI (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i"))
- (const_int 0)))]
- "(INTVAL (operands[1]) & 0x0ff) == 0
- || (INTVAL (operands[1]) & 0x0ff00) == 0"
- "*
-{
- if ((INTVAL (operands[1]) & 0x0ff) == 0)
- return \"bita\\t%h1\";
- else
- return \"bitb\\t%1\";
-}")
-
-(define_insn "bitcmpqi_12"
- [(set (cc0)
- (compare (zero_extract:HI (match_operand:HI 0 "tst_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i")
- (match_operand:HI 2 "const_int_operand" "i"))
- (const_int 0)))]
- "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
- || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
- && (unsigned) INTVAL (operands[2]) >= 8)"
- "*
-{
- rtx ops[1];
- int mask;
- int startpos = INTVAL (operands[2]);
- int bitsize = INTVAL (operands[1]);
-
- if (startpos >= 8)
- {
- startpos -= 8;
- mask = (1 << (startpos + bitsize)) - 1;
- mask &= ~((1 << startpos) - 1);
-
- ops[0] = GEN_INT (mask);
- output_asm_insn (\"bita\\t%0\", ops);
- }
- else
- {
- mask = (1 << (startpos + bitsize)) - 1;
- mask &= ~((1 << startpos) - 1);
-
- ops[0] = GEN_INT (mask);
- output_asm_insn (\"bitb\\t%0\", ops);
- }
- return \"\";
-}")
-
-(define_insn "cmpqi_1"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
- (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
- {
- return \"#\";
- }
- else if (D_REG_P (operands[0]))
- {
- return \"cmpb\\t%b1\";
- }
- cc_status.flags |= CC_REVERSED;
- return \"cmpb\\t%b0\";
-}")
-
-(define_insn_and_split "cmpqi_z_used"
- [(set (cc0)
- (compare (match_operand:QI 0 "tst_operand" "dxy,m")
- (match_operand:QI 1 "cmp_operand" "m,dxy")))
- (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
- (use (reg:HI SOFT_Z_REGNUM))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
- (set (match_dup 2) (match_dup 3))
- (set (cc0) (compare (match_dup 0) (match_dup 1)))
- (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
-
-;;--------------------------------------------------------------------
-;;- Move strict_low_part
-;;--------------------------------------------------------------------
-;;
-;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
-;; The replacement must be made at the very end because we loose the
-;; (strict_low_part ...) information. This is correct for our machine
-;; description but not for GCC optimization passes.
-;;
-(define_insn_and_split "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
- (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_insn_and_split "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
- (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_insn_and_split "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
- (match_operand:QI 1 "general_operand" "d,imudA"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-;;--------------------------------------------------------------------
-;;- 64-bit Move Operations.
-;; The movdi and movdf patterns are identical except for the mode.
-;; They are also very similar to those for movsi and movsf.
-;;
-;; For 68HC11, we need a scratch register (either D, X, Y)
-;; because there is no memory->memory moves. It must be defined with
-;; earlyclobber (&) so that it does not appear in the source or destination
-;; address. Providing patterns for movdi/movdf allows GCC to generate
-;; better code. [Until now, the scratch register is limited to D because
-;; otherwise we can run out of registers in the A_REGS class for reload].
-;;
-;; For 68HC12, the scratch register is not necessary. To use the same
-;; pattern and same split, we use the 'v' constraint. This tells the
-;; reload to use the _.tmp register (which is not used at all).
-;; The insn will be split in one or several memory moves (movw).
-;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
-;;--------------------------------------------------------------------
-(define_expand "movdi"
- [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-;; Separate push from normal moves to avoid reloading problems
-;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
-;; We can also accept more scratch registers.
-(define_insn_and_split "*pushdi_internal"
- [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
- (match_operand:DI 1 "general_operand" "i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movdi_internal"
- [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
- (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
- (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_expand "movdf"
- [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (match_operand:DF 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-;; See pushdi_internal
-(define_insn_and_split "*pushdf_internal"
- [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
- (match_operand:DF 1 "general_operand" "i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movdf_internal"
- [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
- (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
- (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-;;--------------------------------------------------------------------
-;;- 32-bit Move Operations.
-;; The movsi and movsf patterns are identical except for the mode.
-;; When we move to/from a hard register (d+x), we don't need a scratch.
-;; Otherwise, a scratch register is used as intermediate register for
-;; the move. The '&' constraint is necessary to make sure the reload
-;; pass does not give us a register that dies in the insn and is used
-;; for input/output operands.
-;;--------------------------------------------------------------------
-(define_expand "movsi"
- [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-(define_insn_and_split "*pushsi_internal"
- [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
- (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
- (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
- (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_expand "movsf"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (match_operand:SF 1 "general_operand" ""))
- (clobber (match_scratch:HI 2 ""))])]
- ""
- "/* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-")
-
-(define_insn_and_split "*pushsf_internal"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
- (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
- (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-(define_insn_and_split "movsf_internal"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
- (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
- (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (operands[0], operands[1], operands[2]);
- DONE;")
-
-
-;;--------------------------------------------------------------------
-;;- 16-bit Move Operations.
-;; We don't need a scratch register.
-;;--------------------------------------------------------------------
-
-(define_insn "*movhi2_push"
- [(set (match_operand:HI 0 "push_operand" "=<,<,<")
- (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
- "TARGET_M6811 && !TARGET_M6812"
- "*
-{
- cc_status = cc_prev_status;
- if (D_REG_P (operands[1]))
- {
- output_asm_insn (\"pshb\", operands);
- return \"psha\";
- }
- else if (X_REG_P (operands[1]))
- {
- return \"pshx\";
- }
- else if (Y_REG_P (operands[1]))
- {
- return \"pshy\";
- }
- fatal_insn (\"Invalid register in the instruction\", insn);
-}")
-
-(define_insn "*movhi2_pop"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
- (match_operand:HI 1 "pop_operand" ">,>"))]
- "TARGET_M6811"
- "*
-{
- cc_status = cc_prev_status;
- if (D_REG_P (operands[0]))
- {
- output_asm_insn (\"pula\", operands);
- return \"pulb\";
- }
- else if (X_REG_P (operands[0]))
- {
- return \"pulx\";
- }
- else if (Y_REG_P (operands[0]))
- {
- return \"puly\";
- }
- fatal_insn (\"Invalid register in the instruction\", insn);
-}")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (reload_in_progress)
- {
- if (m68hc11_reload_operands (operands))
- {
- DONE;
- }
- }
- if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
- {
- if (GET_CODE (operands[0]) == MEM &&
- (GET_CODE (operands[1]) == MEM
- || GET_CODE (operands[1]) == CONST_INT))
- {
- operands[1] = force_reg (HImode, operands[1]);
- }
- else if (IS_STACK_PUSH (operands[0])
- && GET_CODE (operands[1]) != REG)
- {
- operands[1] = force_reg (HImode, operands[1]);
- }
- }
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-}")
-
-(define_insn "*movhi_68hc12"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
- (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
- "TARGET_M6812"
- "*
-{
- m68hc11_gen_movhi (insn, operands);
- return \"\";
-}")
-
-(define_insn "movhi_const0"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
- (const_int 0))]
- "TARGET_M6811"
- "@
- clra\\n\\tclrb
- ld%0\\t#0
- clr\\t%b0\\n\\tclr\\t%h0")
-
-(define_insn "*movhi_m68hc11"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
- (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
- "TARGET_M6811"
- "*
-{
- m68hc11_gen_movhi (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- 8-bit Move Operations.
-;; We don't need a scratch register.
-;;--------------------------------------------------------------------
-;;
-;; The *a alternative also clears the high part of the register.
-;; This should be ok since this is not the (strict_low_part) set.
-;;
-(define_insn "movqi_const0"
- [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
- (const_int 0))]
- ""
- "@
- clrb
- clr\\t%b0
- clr\\t%b0
- ld%0\\t#0
- clr%0")
-
-;;
-;; 8-bit operations on address registers.
-;;
-;; Switch temporary to the D register and load the value in B.
-;; This is possible as long as the address register does not
-;; appear in the source operand.
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- "z_replacement_completed == 2
- && !reg_mentioned_p (operands[0], operands[1])
- && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
-
-;;
-;; 8-bit operations on address registers.
-;;
-(define_split
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "hard_addr_reg_operand" ""))]
- "z_replacement_completed == 2
- && !reg_mentioned_p (operands[1], operands[0])
- && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])
- (set (match_dup 0) (reg:QI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
- (set (match_dup 2) (reg:HI D_REGNUM))])]
- "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
-
-(define_insn "*movqi2_push"
- [(set (match_operand:QI 0 "push_operand" "=<,<")
- (match_operand:QI 1 "general_operand" "d,!*A"))]
- ""
- "*
-{
- if (A_REG_P (operands[1]))
- return \"#\";
-
- cc_status = cc_prev_status;
- return \"pshb\";
-}")
-
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (reload_in_progress)
- {
- if (m68hc11_reload_operands (operands))
- {
- DONE;
- }
- }
- if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
- {
- if (GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM
- || GET_CODE (operands[1]) == CONST_INT))
- {
- operands[1] = force_reg (QImode, operands[1]);
- }
- else if (IS_STACK_PUSH (operands[0])
- && GET_CODE (operands[1]) != REG)
- {
- operands[1] = force_reg (QImode, operands[1]);
- }
- }
- /* For push/pop, emit a REG_INC note to make sure the reload
- inheritance and reload CSE pass notice the change of the stack
- pointer. */
- if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
- {
- rtx insn;
-
- insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
- REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
- stack_pointer_rtx,
- REG_NOTES (insn));
- DONE;
- }
-}")
-
-(define_insn "*movqi_68hc12"
- [(set (match_operand:QI 0 "nonimmediate_operand"
- "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
- (match_operand:QI 1 "general_operand"
- "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
- "TARGET_M6812"
- "*
-{
- m68hc11_gen_movqi (insn, operands);
- return \"\";
-}")
-
-(define_insn "*movqi_m68hc11"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
- (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
- "TARGET_M6811"
- "*
-{
- m68hc11_gen_movqi (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Swap registers
-;;--------------------------------------------------------------------
-;; Swapping registers is used for split patterns.
-(define_insn "swap_areg"
- [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
- (match_operand:HI 1 "hard_reg_operand" "=A,d"))
- (set (match_dup 1) (match_dup 0))]
- ""
- "*
-{
- m68hc11_output_swap (insn, operands);
- return \"\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Truncation insns.
-;;--------------------------------------------------------------------
-;;
-;; Truncation are not necessary because GCC knows how to truncate,
-;; specially when values lie in consecutive registers.
-;;
-
-(define_expand "floatunssisf2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
- SFmode, SImode, 2, operands);
- DONE;")
-
-(define_expand "floatunssidf2"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
- (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
- DFmode, SImode, 2, operands);
- DONE;")
-
-;;--------------------------------------------------------------------
-;;- Zero extension insns.
-;;--------------------------------------------------------------------
-
-;;
-;; 64-bit extend. The insn will be split into 16-bit instructions just
-;; before the final pass. We need a scratch register for the split.
-;; The final value can be generated on the stack directly. This is more
-;; efficient and useful for conversions made during parameter passing rules.
-;;
-(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
- (zero_extend:DI
- (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
- (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "push_operand" "")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 "=&dB"))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx push = m68hc11_gen_lowpart (HImode, low);
- rtx src = operands[1];
-
- /* Source operand must be in a hard register. */
- if (!H_REG_P (src))
- {
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (src, operands[1]);
- }
-
- /* Source is in D, we can push B then one word of 0 and we do
- a correction on the stack pointer. */
- if (D_REG_P (src))
- {
- emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
- emit_move_insn (operands[2], const0_rtx);
- if (D_REG_P (operands[2]))
- {
- emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
- }
- else
- {
- emit_move_insn (push, operands[2]);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- }
- }
- else
- {
- /* Source is in X or Y. It's better to push the 16-bit register
- and then to some stack adjustment. */
- src = gen_rtx_REG (HImode, REGNO (src));
- emit_move_insn (push, src);
- emit_move_insn (operands[2], const0_rtx);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- emit_move_insn (push, operands[2]);
- emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- gen_rtx_REG (HImode, HARD_SP_REGNUM),
- const1_rtx));
- }
- emit_move_insn (push, operands[2]);
- emit_move_insn (push, operands[2]);
- emit_move_insn (push, operands[2]);
- DONE;
-}")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 "=&dB"))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx low2 = m68hc11_gen_lowpart (HImode, low);
- rtx src = operands[1];
-
- /* Source operand must be in a hard register. */
- if (!H_REG_P (src))
- {
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (src, operands[1]);
- }
-
- emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
- emit_move_insn (operands[2], const0_rtx);
- src = gen_rtx_REG (QImode, REGNO (operands[2]));
- emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
-
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- low = m68hc11_gen_highpart (SImode, operands[0]);
- emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- DONE;
-}")
-
-(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
- (zero_extend:DI
- (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
- (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "non_push_operand" "")
- (zero_extend:DI
- (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx high = m68hc11_gen_highpart (SImode, operands[0]);
- rtx src = operands[1];
-
- /* Make sure the source is in a hard register. */
- if (!H_REG_P (src))
- {
- src = operands[2];
- emit_move_insn (src, operands[1]);
- }
-
- /* Move the low part first for the push. */
- emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
-
- /* Now, use the scratch register to fill in the zeros. */
- emit_move_insn (operands[2], const0_rtx);
- emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
- emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
- DONE;
-}")
-
-(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
- (zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
- (clobber (match_scratch:HI 2 "=d,d,d,d"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "z_replacement_completed == 2"
- [(const_int 0)]
- "
-{
- rtx low = m68hc11_gen_lowpart (SImode, operands[0]);
- rtx high = m68hc11_gen_highpart (SImode, operands[0]);
-
- /* Move the low part first so that this is ok for a push. */
- m68hc11_split_move (low, operands[1], operands[2]);
-
- /* Use the scratch register to clear the high part of the destination. */
- emit_move_insn (operands[2], const0_rtx);
- emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
- emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
- DONE;
-}")
-
-;;
-;; For 16->32bit unsigned extension, we don't allow generation on the stack
-;; because it's less efficient.
-;;
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:HI 2 ""))]
- "reload_completed"
- [(const_int 0)]
- "
-{
- rtx src = operands[1];
-
- if (!H_REG_P (src) && !H_REG_P (operands[0]))
- {
- src = operands[2];
- emit_move_insn (src, operands[1]);
- }
- emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
- emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
- DONE;
-}")
-
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
- (zero_extend:SI
- (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- "reload_completed && !X_REG_P (operands[0])"
- [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
- (set (match_dup 3) (const_int 0))]
- "
- operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-(define_split
- [(set (match_operand:SI 0 "hard_reg_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- "z_replacement_completed == 2 && X_REG_P (operands[0])"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))
- (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
- "
- if (X_REG_P (operands[1]))
- {
- emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (HImode, HARD_X_REGNUM)));
- emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (QImode, HARD_D_REGNUM)));
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
- const0_rtx);
- DONE;
- }
-
- if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
- {
- emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
- operands[0]),
- operands[1]));
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
- DONE;
- }
- operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
- if (A_REG_P (operands[1]))
- {
- operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
- operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- else
- {
- operands[5] = operands[2] =
- operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = operands[1];
- }
-")
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
- (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (H_REG_P (operands[0]))
- {
- output_asm_insn (\"clra\", operands);
- if (operands[0] != operands[1]
- && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
- {
- if (X_REG_P (operands[1])
- || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
- {
- output_asm_insn (\"stx\\t%t1\", operands);
- output_asm_insn (\"ldab\\t%T0\", operands);
- }
- else if (Y_REG_P (operands[1])
- || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldab\\t%T0\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- /* Status refers to the clra insn. Status is ok for others
- * since we have loaded the value in B.
- */
- CC_STATUS_INIT;
- }
- return \"\";
- }
-
- if (A_REG_P (operands[1]))
- {
- output_asm_insn (\"st%1\\t%0\", operands);
- output_asm_insn (\"clr\\t%h0\", operands);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"clr\\t%h0\", operands);
- output_asm_insn (\"stab\\t%b0\", operands);
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
-
- return \"\";
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Sign extension insns.
-;;--------------------------------------------------------------------
-
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
- ""
- "*
-{
- rtx ops[3];
- int need_tst = 0;
-
- /* The 68HC12 has a sign-extension instruction. Use it when the
- destination is the register (X,D). First sign-extend the low
- part and fill X with the sign-extension of the high part. */
- if (TARGET_M6812 && X_REG_P (operands[0]))
- {
- if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"sex\\tb,d\\n\\tsex\\ta,x\";
- }
-
- ops[2] = gen_label_rtx ();
-
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", operands);
- need_tst = 1;
- }
- else if (X_REG_P (operands[0]))
- {
- /* X can be used as an indexed addressing in the source.
- Get the value before clearing it. */
- if (reg_mentioned_p (ix_reg, operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- need_tst = 1;
- }
- output_asm_insn (\"ldx\\t#0\", operands);
- }
-
- output_asm_insn (\"clra\", operands);
- if (!X_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
-
- if (IS_STACK_PUSH (operands[0]))
- {
- output_asm_insn (\"pshb\", ops);
- output_asm_insn (\"tstb\", ops);
- }
- else
- {
- output_asm_insn (\"stab\\t%b1\", ops);
- }
- }
- else if (D_REG_P (operands[1]) || need_tst)
- {
- output_asm_insn (\"tstb\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- output_asm_insn (\"bpl\\t%l2\", ops);
- output_asm_insn (\"deca\", operands);
- if (X_REG_P (operands[0]))
- output_asm_insn (\"dex\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
-
- if (!X_REG_P (operands[0]))
- {
- if (IS_STACK_PUSH (operands[0]))
- {
- output_asm_insn (\"psha\", ops);
- output_asm_insn (\"psha\", ops);
- output_asm_insn (\"psha\", ops);
- }
- else
- {
- output_asm_insn (\"staa\\t%h0\", ops);
-
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- if (dead_register_here (insn, d_reg))
- {
- output_asm_insn (\"tab\", ops);
- output_asm_insn (\"std\\t%0\", ops);
- }
- else
- {
- output_asm_insn (\"staa\\t%b0\", ops);
- output_asm_insn (\"staa\\t%h0\", ops);
- }
- }
- }
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
- (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_label_rtx ();
- if (D_REG_P (operands[0]))
- {
- if (TARGET_M6812)
- {
- if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"sex\\tb,d\";
- }
- output_asm_insn (\"clra\", operands);
- if (H_REG_P (operands[1]))
- {
- output_asm_insn (\"tstb\", operands);
- }
- else
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- output_asm_insn (\"bpl\\t%l0\", ops);
- output_asm_insn (\"deca\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- }
- else
- {
- output_asm_insn (\"clr\\t%h0\", operands);
- if (m68hc11_register_indirect_p (operands[1], HImode))
- {
- ops[1] = operands[1];
- output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"tst\\t%b1\", operands);
- output_asm_insn (\"bpl\\t%l0\", ops);
- }
- output_asm_insn (\"dec\\t%h0\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- }
-
- return \"\";
-}")
-
-;;
-;; Split the special case where the source of the sign extend is
-;; either Y or Z. In that case, we can't move the source in the D
-;; register directly. The movhi pattern handles this move by using
-;; a temporary scratch memory location.
-;;
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
- "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
- [(set (reg:HI D_REGNUM) (match_dup 1))
- (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
- "")
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
- ""
- "*
-{
- rtx ops[2];
- int x_reg_used;
-
- if (Y_REG_P (operands[1]))
- return \"#\";
-
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", operands);
- x_reg_used = 1;
- }
- else
- {
- /* X can be used as an indexed addressing in the source.
- Get the value before clearing it. */
- x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
- if (x_reg_used)
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- }
-
- CC_STATUS_INIT;
- if (TARGET_M6812 && 0)
- {
- /* This sequence of code is larger than the one for 68HC11.
- Don't use it; keep it for documentation. */
- if (!D_REG_P (operands[1]) && !x_reg_used)
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- output_asm_insn (\"sex\\ta,x\", operands);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"sex\\ta,d\", operands);
- return \"xgdx\";
- }
-
- output_asm_insn (\"ldx\\t#0\", operands);
- if (D_REG_P (operands[1]) || x_reg_used)
- {
- output_asm_insn (\"tsta\", operands);
- }
- else
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
-
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"bpl\\t%l0\", ops);
- output_asm_insn (\"dex\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
-
- return \"\";
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Min and Max instructions (68HC12).
-;;--------------------------------------------------------------------
-(define_insn "uminqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
- (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:QI (operand 1) (operand2)).
- The mina/minm use A as the source or destination. This is the
- high part of D. There is no way to express that in the pattern
- so we must use 'exg a,b' to put the operand in the good register. */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
- }
- else
- {
- return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
- }
-}")
-
-(define_insn "umaxqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
- (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:QI (operand 1) (operand2)).
- The maxa/maxm use A as the source or destination. This is the
- high part of D. There is no way to express that in the pattern
- so we must use 'exg a,b' to put the operand in the good register. */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
- }
- else
- {
- return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
- }
-}")
-
-(define_insn "uminhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
- (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:HI (operand 1) (operand2)). */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"emind\\t%2\";
- }
- else
- {
- return \"eminm\\t%0\";
- }
-}")
-
-(define_insn "umaxhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
- (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "m,d")))]
- "TARGET_M6812 && TARGET_MIN_MAX"
- "*
-{
- /* Flags are set according to (sub:HI (operand 1) (operand2)). */
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"emaxd\\t%2\";
- }
- else
- {
- return \"emaxm\\t%0\";
- }
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Add instructions.
-;;--------------------------------------------------------------------
-;; 64-bit: Use a library call because what GCC generates is huge.
-;;
-(define_expand "adddi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (plus:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
- DONE;")
-
-;;
-;; - 32-bit Add.
-;;
-(define_expand "addsi3"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "*addsi3_zero_extendhi"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
- (plus:SI (zero_extend:SI
- (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
- (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
- (clobber (match_scratch:HI 3 "=X,X,X,X"))]
- ""
- "*
-{
- rtx ops[3];
-
- if (X_REG_P (operands[2]))
- {
- ops[0] = operands[1];
- }
- else
- {
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", ops);
- }
- else if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- }
- ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
- ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- ops[2] = gen_label_rtx ();
-
- /* ldx preserves the carry, propagate it by incrementing X directly. */
- output_asm_insn (\"addd\\t%0\", ops);
- if (!X_REG_P (operands[2]))
- output_asm_insn (\"ldx\\t%1\", ops);
-
- output_asm_insn (\"bcc\\t%l2\", ops);
- output_asm_insn (\"inx\", ops);
-
- CC_STATUS_INIT;
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
- return \"\";
-}")
-
-
-(define_split /* "*addsi3_zero_extendqi" */
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (zero_extend:SI
- (match_operand:QI 1 "general_operand" ""))
- (match_operand:SI 2 "memory_operand" "")))
- (clobber (match_scratch:HI 3 "=X,X"))]
- "reload_completed"
- [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
- (parallel [(set (match_dup 0)
- (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
- (clobber (match_dup 3))])]
- "")
-
-(define_insn "*addsi3_zero_extendqi"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (plus:SI (zero_extend:SI
- (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
- (match_operand:SI 2 "general_operand" "miD,!muiD")))
- (clobber (match_scratch:HI 3 "=X,X"))]
- ""
- "*
-{
- rtx ops[4];
-
- if (GET_CODE (operands[2]) == MEM)
- return \"#\";
-
- if (X_REG_P (operands[2]))
- {
- if (H_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- ops[0] = operands[1];
- }
- ops[1] = const0_rtx;
- }
- else
- {
- if (X_REG_P (operands[1]))
- {
- output_asm_insn (\"xgdx\", ops);
- }
- else if (!D_REG_P (operands[1]))
- {
- ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- ops[1] = operands[1];
- m68hc11_gen_movqi (insn, ops);
- }
-
- ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
- ops[1] = ops[0];
- ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
- output_asm_insn (\"clra\", ops);
- }
-
- /* ldx preserves the carry, propagate it by incrementing X directly. */
- output_asm_insn (\"addb\\t%b0\", ops);
- output_asm_insn (\"adca\\t%h1\", ops);
- if (!X_REG_P (operands[2]))
- output_asm_insn (\"ldx\\t%2\", ops);
-
- /* If the above adca was adding some constant, we don't need to propagate
- the carry unless the constant was 0xff. */
- if (X_REG_P (operands[2])
- || GET_CODE (ops[1]) != CONST_INT
- || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
- {
- ops[3] = gen_label_rtx ();
-
- output_asm_insn (\"bcc\\t%l3\", ops);
- output_asm_insn (\"inx\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[3]));
- }
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*addsi3"
- [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
- (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
- (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
- ""
- "*
-{
- rtx ops[3];
- const char* add_insn;
- const char* inc_insn;
- const char* incb_mem;
- const char* inch_mem;
- HOST_WIDE_INT val;
-
- if (which_alternative > 2)
- {
- return \"#\";
- }
-
- val = INTVAL (operands[2]);
- if ((val & 0x0ffffL) == 0)
- {
- if (!H_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
- output_asm_insn (\"ldd\\t%0\", ops);
- output_asm_insn (\"addd\\t%1\", ops);
- output_asm_insn (\"std\\t%0\", ops);
- return \"\";
- }
- else if (val == 1)
- {
- return \"inx\";
- }
- else
- {
- return \"#\";
- }
- }
- if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
- {
- return \"#\";
- }
-
- if (val >= 0)
- {
- ops[1] = operands[2];
- add_insn = \"addd\\t%1\";
- inc_insn = \"inx\\t\";
- incb_mem = \"inc\\t%b1\";
- inch_mem = \"inc\\t%h1\";
- }
- else
- {
- ops[1] = GEN_INT (- val);
- add_insn = \"subd\\t%1\";
- inc_insn = \"dex\";
- incb_mem = \"dec\\t%b1\";
- inch_mem = \"dec\\t%h1\";
- }
-
- ops[2] = gen_label_rtx ();
- if (!H_REG_P (operands[0]))
- {
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- output_asm_insn (\"ldd\\t%0\", ops);
- }
- output_asm_insn (add_insn, ops);
- if (!H_REG_P (operands[0]))
- {
- output_asm_insn (\"std\\t%0\", ops);
- }
- output_asm_insn (\"bcc\\t%l2\", ops);
- if (H_REG_P (operands[0]))
- {
- output_asm_insn (inc_insn, ops);
- }
- else
- {
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- ops[1] = ops[0];
- if (INTVAL (operands[2]) < 0)
- {
- output_asm_insn (\"ldd\\t%1\", ops);
- output_asm_insn (\"addd\\t#-1\", ops);
- output_asm_insn (\"std\\t%1\", ops);
- }
- else
- {
- output_asm_insn (incb_mem, ops);
- output_asm_insn (\"bne\\t%l2\", ops);
- output_asm_insn (inch_mem, ops);
- }
- }
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 ""))]
- "reload_completed && z_replacement_completed == 2
- && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
- [(set (match_dup 5) (match_dup 6))
- (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
- (set (match_dup 6) (match_dup 5))]
- "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- if (X_REG_P (operands[0]))
- {
- operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- }
- else
- {
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[5] = operands[3];
- }
- ")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && (GET_CODE (operands[2]) != CONST_INT ||
- (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
- (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
- (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
- (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-;;
-;; Instruction generated to propagate the carry of a 16-bit add
-;; to the upper 16-bit part (in register X).
-;;
-(define_insn "*addsi_carry"
- [(set (match_operand:HI 0 "register_operand" "=x")
- (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"in%0\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-;;
-;; - 16-bit Add.
-;;
-(define_expand "addhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (plus:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (TARGET_M6811 && SP_REG_P (operands[0]))
- {
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
- gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_PLUS (HImode,
- operand1, operand2)),
- gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_SCRATCH (HImode)))));
- DONE;
- }
-}")
-
-(define_insn "*addhi3_68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
- (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
- "TARGET_M6812"
- "*
-{
- int val;
- const char* insn_code;
-
- if (which_alternative >= 4)
- {
- if (A_REG_P (operands[2]))
- {
- CC_STATUS_INIT;
- output_asm_insn (\"xgd%2\", operands);
- output_asm_insn (\"lea%0 d,%0\", operands);
- return \"xgd%2\";
- }
- return \"#\";
- }
-
- if (D_REG_P (operands[0]))
- {
- if (X_REG_P (operands[2]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"leax\\td,%2\", operands);
- return \"xgdx\";
- }
- else if (Y_REG_P (operands[2]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- output_asm_insn (\"xgdy\", operands);
- output_asm_insn (\"leay\\td,%2\", operands);
- return \"xgdy\";
- }
- else if (SP_REG_P (operands[2]))
- {
- output_asm_insn (\"sts\\t%t0\", operands);
- return \"addd\\t%t0\";
- }
- return \"addd\\t%2\";
- }
-
- if (GET_CODE (operands[2]) == CONST_INT)
- val = INTVAL (operands[2]);
- else
- val = 1000;
-
- if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
- {
- m68hc11_notice_keep_cc (operands[0]);
- switch (REGNO (operands[0]))
- {
- case HARD_X_REGNUM:
- return \"leax\\t%i2,%1\";
-
- case HARD_Y_REGNUM:
- return \"leay\\t%i2,%1\";
-
- case HARD_SP_REGNUM:
- return \"leas\\t%i2,%1\";
-
- default:
- fatal_insn (\"Invalid operands in the instruction\", insn);
- }
- }
- if (val > 0)
- {
- insn_code = X_REG_P (operands[0]) ? \"inx\"
- : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
- }
- else
- {
- val = -val;
- insn_code = X_REG_P (operands[0]) ? \"dex\"
- : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
- }
-
- /* For X and Y increment, the flags are not complete. Only the Z flag
- is updated. For SP increment, flags are not changed. */
- if (SP_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- if (INTVAL (operands[2]) < 0)
- {
- while (val > 2)
- {
- output_asm_insn (\"pshx\", operands);
- val -= 2;
- }
- if (val == 0)
- return \"\";
- }
- }
- else
- {
- CC_STATUS_INIT;
- }
-
- while (val)
- {
- output_asm_insn (insn_code, operands);
- val--;
- }
- return \"\";
-}")
-
-;;
-;; Specific pattern to add to the stack pointer.
-;; We also take care of the clobbering of the IY register.
-;;
-(define_insn "addhi_sp"
- [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
- (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
- (match_operand:HI 2 "general_operand" "P,im,u,im")))
- (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
- "!TARGET_M6812"
- "*
-{
- HOST_WIDE_INT val;
-
- if (optimize && Y_REG_P (operands[3])
- && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
- operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
-
- if (GET_CODE (operands[2]) == CONST_INT
- && (val = INTVAL (operands[2])) != 0
- && (CONST_OK_FOR_LETTER_P (val, 'P')
- || (val > 0 && val <= 8)))
- {
- while (val > 1 || val < -1)
- {
- if (val > 0)
- {
- if (!H_REG_P (operands[3]))
- break;
-
- output_asm_insn (\"pul%3\", operands);
- val -= 2;
- }
- else
- {
- output_asm_insn (\"pshx\", operands);
- val += 2;
- }
- }
- while (val != 0)
- {
- if (val > 0)
- {
- output_asm_insn (\"ins\", operands);
- val--;
- }
- else
- {
- output_asm_insn (\"des\", operands);
- val++;
- }
- }
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* Need to transfer to SP to X/Y and then to D register.
- Register X/Y is lost, this is specified by the (clobber) statement. */
- output_asm_insn (\"ts%3\", operands);
- if (GET_CODE (operands[2]) == CONST_INT
- && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
- && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
- {
- output_asm_insn (\"ldab\\t%2\", operands);
- output_asm_insn (\"ab%3\", operands);
- CC_STATUS_INIT;
- }
- else
- {
- output_asm_insn (\"xgd%3\", operands);
- output_asm_insn (\"addd\\t%2\", operands);
- output_asm_insn (\"xgd%3\", operands);
- }
-
- /* The status flags correspond to the addd. xgdy and tys do not
- modify the flags. */
- return \"t%3s\";
-}")
-
-(define_insn "*addhi3"
- [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
- (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
- (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
- "TARGET_M6811"
- "*
-{
- const char* insn_code;
- int val;
-
- if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
- {
- output_asm_insn (\"sts\\t%t0\", operands);
- output_asm_insn (\"addd\\t%t0\", operands);
- return \"addd\\t#1\";
- }
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- /* Adding to an address register or with another/same register
- is not possible. This must be replaced. */
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- return \"addd\\t%2\";
- }
- val = INTVAL (operands[2]);
- if (!SP_REG_P (operands[0]))
- {
- if (D_REG_P (operands[0]))
- {
- if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
- {
- CC_STATUS_INIT;
- return \"adda\\t%h2\";
- }
- else
- {
- return \"addd\\t%2\";
- }
- }
- else if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) < -4
- || INTVAL (operands[2]) > 4)
- return \"#\";
- }
- if (val > 0)
- {
- insn_code = X_REG_P (operands[0]) ? \"inx\"
- : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
- }
- else
- {
- val = -val;
- insn_code = X_REG_P (operands[0]) ? \"dex\"
- : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
- }
-
- /* For X and Y increment, the flags are not complete. Only the Z flag
- is updated. For SP increment, flags are not changed. */
- if (SP_REG_P (operands[0]))
- {
- cc_status = cc_prev_status;
- if (INTVAL (operands[2]) < 0)
- {
- while (val >= 2)
- {
- output_asm_insn (\"pshx\", operands);
- val -= 2;
- }
- }
- else if (optimize && dead_register_here (insn, ix_reg))
- {
- while (val >= 2)
- {
- output_asm_insn (\"pulx\", operands);
- val -= 2;
- }
- }
- }
- else
- {
- CC_STATUS_INIT;
- }
-
- while (val)
- {
- output_asm_insn (insn_code, operands);
- val--;
- }
- return \"\";
-}")
-
-(define_insn "*addhi3_zext"
- [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
- (plus:HI (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
- (match_operand:HI 2 "general_operand" "0,0")))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (A_REG_P (operands[0]))
- return \"ab%0\";
- else if (A_REG_P (operands[1]))
- return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
- else
- return \"addb\\t%b1\\n\\tadca\\t#0\";
-}")
-
-;;
-;; Translate d = d + d into d = << 1
-;; We have to do this because adding a register to itself is not possible.
-;; ??? It's not clear whether this is really necessary.
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (plus:QI (match_dup 0)
- (match_dup 0)))]
- "0 && reload_completed"
- [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
- "")
-
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
- (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
- ""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) == 1)
- {
- if (DA_REG_P (operands[0]))
- {
- return \"inca\";
- }
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- {
- return \"incb\";
-
- }
- else if (A_REG_P (operands[0]))
- {
- /* This applies on the 16-bit register. This should be ok since
- this is not a strict_low_part increment. */
- return \"in%0\";
- }
- else
- {
- return \"inc\\t%b0\";
- }
- }
- else if (INTVAL (operands[2]) == -1)
- {
- if (DA_REG_P (operands[0]))
- {
- return \"deca\";
- }
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- {
- return \"decb\";
- }
- else if (A_REG_P (operands[0]))
- {
- /* This applies on the 16-bit register. This should be ok since
- this is not a strict_low_part decrement. */
- return \"de%0\";
- }
- else
- {
- return \"dec\\t%b0\";
- }
- }
- }
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"addb\\t%b2\";
- else
- return \"adda\\t%b2\";
-}")
-
-;;
-;; add with carry is used for 32-bit add.
-;;
-(define_insn "*adcq"
- [(set (match_operand:QI 0 "register_operand" "=q")
- (plus:QI (plus:QI (reg:QI CC_REGNUM)
- (match_operand:QI 1 "register_operand" "%0"))
- (match_operand:QI 2 "general_operand" "ium")))]
- ""
- "adc%0\\t%b2")
-
-;;--------------------------------------------------------------------
-;;- Subtract instructions.
-;;--------------------------------------------------------------------
-
-(define_expand "subdi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
- DONE;")
-
-;;
-;; 32-bit Subtract (see addsi3)
-;; Subtract with a constant are handled by addsi3.
-;;
-;;
-;; - 32-bit Add.
-;;
-(define_expand "subsi3"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "*subsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
- (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
- (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
- (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
- ""
- "#")
-
-(define_insn "*subsi3_zero_extendhi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
- (clobber (match_scratch:HI 3 "=X"))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[2]))
- {
- if (TARGET_M6812)
- ops[0] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
-
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- if (TARGET_M6812)
- operands[2] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- else
- operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- }
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"dex\", ops);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*subsi3_zero_extendqi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (minus:SI (match_operand:SI 1 "register_operand" "0")
- (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
- (clobber (match_scratch:HI 3 "=X"))]
- ""
- "*
-{
- rtx ops[2];
-
- if (A_REG_P (operands[2]))
- {
- ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"subb\\t%b2\", operands);
- output_asm_insn (\"sbca\\t#0\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"dex\", ops);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- CC_STATUS_INIT;
- return \"\";
-}")
-
-;;
-;; reg:HI 1 -> d reg:QI 6 -> B
-;; reg:QI 7 -> ccr reg:QI 5 -> A
-;;
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "register_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "reload_completed && z_replacement_completed == 2
- && X_REG_P (operands[2])"
- [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
- (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
- (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
- (set (reg:SI 0) (neg:SI (reg:SI 0)))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
-
-(define_split /* "*subsi3" */
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (minus:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "reload_completed && z_replacement_completed == 2
- && !X_REG_P (operands[0])"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
- (set (match_dup 4) (match_dup 3))
- (set (match_dup 3) (match_dup 6))
- (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
- (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
- (set (match_dup 6) (match_dup 3))]
- "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
- operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
- operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
-
-;;
-;; - 16-bit Subtract.
-;;
-(define_expand "subhi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (minus:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "general_operand" "g")))]
- ""
- "")
-
-;;
-;; Subtract from stack. This is better if we provide a pattern.
-;;
-(define_insn "*subhi3_sp"
- [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "im*d,!u*A")))
- (clobber (match_scratch:HI 3 "=A*d,A*d"))]
- ""
- "*
-{
- if (X_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"stx\\t%2\", operands);
- }
- else if (Y_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"sty\\t%2\", operands);
- }
- else if (D_REG_P (operands[2]))
- {
- operands[2] = m68hc11_soft_tmp_reg;
- output_asm_insn (\"std\\t%2\", operands);
- }
-
- if (D_REG_P (operands[3]))
- {
- int save_x;
-
- save_x = !dead_register_here (insn, ix_reg);
- if (save_x)
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"tsx\", operands);
- output_asm_insn (\"xgdx\", operands);
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"xgdx\", operands);
-
- /* The status flags correspond to the addd. xgdx/y and tx/ys do not
- modify the flags. */
- output_asm_insn (\"txs\", operands);
- if (save_x)
- return \"xgdx\";
- else
- return \"\";
- }
-
- /* Need to transfer to SP to X,Y and then to D register.
- Register X,Y is lost, this is specified by the (clobber) statement. */
- output_asm_insn (\"ts%3\", operands);
- output_asm_insn (\"xgd%3\", operands);
- output_asm_insn (\"subd\\t%2\", operands);
- output_asm_insn (\"xgd%3\", operands);
-
- /* The status flags correspond to the addd. xgdx/y and tx/ys do not
- modify the flags. */
- return \"t%3s\";
-}")
-
-
-(define_insn "*subhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
- (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
- ""
- "*
-{
- /* Adding to an address register or with another/same register
- is not possible. This must be replaced. */
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- return \"subd\\t%2\";
-}")
-
-(define_insn "*subhi3_zext"
- [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0")
- (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (A_REG_P (operands[2]))
- {
- rtx ops[2];
-
- ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- return \"subb\\t%T0\\n\\tsbca\\t#0\";
- }
- return \"subb\\t%b2\\n\\tsbca\\t#0\";
-}")
-
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
- (minus:QI (match_operand:QI 1 "general_operand" "0,0")
- (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
- else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"subb\\t%b2\";
- else
- return \"suba\\t%b2\";
-}")
-
-;;
-;; subtract with carry is used for 32-bit subtract.
-;;
-(define_insn "*subcq"
- [(set (match_operand:QI 0 "register_operand" "=q")
- (minus:QI (minus:QI (reg:QI CC_REGNUM)
- (match_operand:QI 1 "register_operand" "0"))
- (match_operand:QI 2 "general_operand" "ium")))]
- ""
- "sbc%0\\t%b2")
-
-;;--------------------------------------------------------------------
-;;- Multiply instructions.
-;;--------------------------------------------------------------------
-;;
-;; 32 and 64-bit multiply are handled by the library
-;;
-
-(define_expand "mulsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (mult:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
- DONE;")
-
-(define_expand "mulhi3"
- [(parallel [(set (match_operand:HI 0 "register_operand" "")
- (mult:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "register_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "")
-
-(define_insn "mulhi3_m68hc11"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (mult:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "register_operand" "x")))
- (clobber (match_scratch:HI 3 "=X"))]
- "TARGET_M6811"
- "*
-{
- CC_STATUS_INIT;
- /* D * X -> D (X and Y are preserved by this function call). */
- return \"jsr\\t___mulhi3\";
-}")
-
-(define_insn "mulhi3_m68hc12"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "register_operand" "y,x")))
- (clobber (match_scratch:HI 3 "=2,2"))]
- "TARGET_M6812"
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[2]))
- return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
- else
- return \"emul\";
-}")
-
-(define_insn "umulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (mult:SI (zero_extend:SI
- (match_operand:HI 1 "register_operand" "%d,d"))
- (zero_extend:SI
- (match_operand:HI 2 "register_operand" "y,x"))))
- (clobber (match_scratch:HI 3 "=2,X"))]
- "TARGET_M6812"
- "*
-{
- if (X_REG_P (operands [2]))
- output_asm_insn (\"exg\\tx,y\", operands);
-
- /* Can't use the carry after that; other flags are ok when testing
- the 32-bit result. */
- cc_status.flags |= CC_NO_OVERFLOW;
- return \"emul\\n\\texg\\tx,y\";
-}")
-
-(define_insn "mulhisi3"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (mult:SI (sign_extend:SI
- (match_operand:HI 1 "register_operand" "%d,d"))
- (sign_extend:SI
- (match_operand:HI 2 "register_operand" "y,x"))))
- (clobber (match_scratch:HI 3 "=2,X"))]
- "TARGET_M6812"
- "*
-{
- if (X_REG_P (operands [2]))
- output_asm_insn (\"exg\\tx,y\", operands);
-
- /* Can't use the carry after that; other flags are ok when testing
- the 32-bit result. */
- cc_status.flags |= CC_NO_OVERFLOW;
- return \"emuls\\n\\texg\\tx,y\";
-}")
-
-(define_insn "umulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (mult:HI (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
- (zero_extend:HI
- (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
- ""
- "*
-{
- if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- }
- else
- {
- rtx ops[2];
-
- if (D_REG_P (operands[2]))
- {
- rtx temp = operands[2];
- operands[2] = operands[1];
- operands[1] = temp;
- }
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- if (!D_REG_P (operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- }
-
- CC_STATUS_INIT;
- return \"mul\";
-}")
-
-(define_insn "mulqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
- (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
- (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- }
- else
- {
- if (D_REG_P (operands[2]))
- {
- rtx temp = operands[2];
- operands[2] = operands[1];
- operands[1] = temp;
- }
-
- output_asm_insn (\"ldaa\\t%b2\", operands);
-
- if (!D_REG_P (operands[1]))
- {
- output_asm_insn (\"ldab\\t%b1\", operands);
- }
- }
-
- CC_STATUS_INIT;
- return \"mul\";
-}")
-
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (mult:QI (match_operand:QI 1 "general_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- "z_replacement_completed == 2"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
- if (A_REG_P (operands[1]))
- operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- else
- operands[5] = operands[1];
- if (A_REG_P (operands[2]))
- operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- else
- operands[6] = operands[2];
- ")
-
-(define_insn "mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,d")
- (mult:HI (sign_extend:HI
- (match_operand:QI 1 "register_operand" "%0,0,0"))
- (sign_extend:HI
- (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
- ""
- "*
-{
- CC_STATUS_INIT;
-
- /* Special case when multiplying the register with itself. */
- if (D_REG_P (operands[2]))
- {
- output_asm_insn (\"tba\", operands);
- return \"mul\";
- }
-
- if (!H_REG_P (operands[2]))
- {
- output_asm_insn (\"ldaa\\t%b2\", operands);
- }
- else
- {
- rtx ops[2];
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
- }
- return \"jsr\\t___mulqi3\";
-}")
-
-;;--------------------------------------------------------------------
-;;- Divide instructions.
-;;--------------------------------------------------------------------
-
-(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (div:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "A,ium")))
- (set (match_operand:HI 3 "register_operand" "=&x,&x")
- (mod:HI (match_dup 1) (match_dup 2)))]
- ""
- "*
-{
- if (!X_REG_P (operands[2]))
- {
- if (Y_REG_P (operands[2]))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldx\\t%t1\", operands);
- }
- else
- {
- output_asm_insn (\"ldx\\t%2\", operands);
- }
- }
- if (TARGET_M6812)
- {
- /* Flags are ok after that. */
- return \"idivs\\n\\txgdx\";
- }
- else
- {
- CC_STATUS_INIT;
- return \"bsr\\t__divmodhi4\";
- }
-}")
-
-(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "A,ium")))
- (set (match_operand:HI 3 "register_operand" "=x,x")
- (umod:HI (match_dup 1) (match_dup 2)))]
- ""
- "*
-{
- if (!X_REG_P (operands[2]))
- {
- if (Y_REG_P (operands[2]))
- {
- output_asm_insn (\"sty\\t%t1\", operands);
- output_asm_insn (\"ldx\\t%t1\", operands);
- }
- else
- {
- output_asm_insn (\"ldx\\t%2\", operands);
- }
- }
-
- /* Z V and C flags are set but N is unchanged.
- Since this is an unsigned divide, we can probably keep the flags
- and indicate this. */
- cc_status.flags |= CC_NOT_NEGATIVE;
- return \"idiv\\n\\txgdx\";
-}")
-
-;;--------------------------------------------------------------------
-;;- and instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "anddi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, AND, operands);
- DONE;")
-
-(define_insn_and_split "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (and:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, AND, operands);
- DONE;")
-
-(define_expand "andhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (and:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*andhi3_mem"
- [(set (match_operand:HI 0 "memory_operand" "=R,Q")
- (and:HI (match_dup 0)
- (match_operand:HI 1 "immediate_operand" "i,i")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FFFF;
-
- if (val == 0x0ffff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- CC_STATUS_INIT;
-
- /* The bclr instruction uses an inverted mask. */
- operands[1] = GEN_INT ((~val) & 0x0FFFF);
-
- /* When destination is a global variable, generate a .relax instruction
- and load the address in the clobber register. That load can be
- eliminated by the linker if the address is in page0. */
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- if ((val & 0x0FF) != 0x0FF)
- output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
-
- if ((val & 0x0FF00) != 0x0FF00)
- output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
-
- if ((val & 0x0FF) != 0x0FF)
- output_asm_insn (\"bclr\\t%b0, %b1\", operands);
-
- if ((val & 0x0FF00) != 0x0FF00)
- output_asm_insn (\"bclr\\t%h0, %h1\", operands);
-
- return \"\";
-}")
-
-(define_insn "*andhi3_const"
- [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
- (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FFFF;
- int lowpart_zero = 0;
- int highpart_zero = 0;
- int lowpart_unknown = 0;
- int highpart_unknown = 0;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0x0ffff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* First, try to clear the low and high part.
- If that's possible, the second 'and' will give
- the good status flags and we can avoid a tsthi. */
- if ((val & 0x0FF) == 0)
- {
- if (D_REG_P (operands[0]))
- output_asm_insn (\"clrb\", operands);
- else
- output_asm_insn (\"clr\\t%b0\", operands);
- lowpart_zero = 1;
- }
- if ((val & 0x0FF00) == 0)
- {
- if (D_REG_P (operands[0]))
- output_asm_insn (\"clra\", operands);
- else
- output_asm_insn (\"clr\\t%h0\", operands);
- highpart_zero = 1;
- }
-
- if ((val & 0x0FF) == 0x0FF)
- {
- lowpart_unknown = 1;
- }
- else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT ((~val) & 0x0FF);
- output_asm_insn (\"bclr\\t%b0, %1\", ops);
- }
- else if ((val & 0x0FF) != 0)
- {
- output_asm_insn (\"andb\\t%b2\", operands);
- }
-
- if ((val & 0x0FF00) == 0x0FF00)
- {
- highpart_unknown = 1;
- }
- else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
- output_asm_insn (\"bclr\\t%h0, %1\", ops);
- }
- else if ((val & 0x0FF00) != 0)
- {
- output_asm_insn (\"anda\\t%h2\", operands);
- }
-
- if (highpart_unknown || lowpart_unknown)
- CC_STATUS_INIT;
- else if (highpart_zero == 0 && lowpart_zero == 0)
- CC_STATUS_INIT;
-
- return \"\";
-}")
-
-(define_insn "*andhi3_gen"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"anda\\t%h2\\n\\tandb\\t%b2\";
-}")
-
-(define_expand "andqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (and:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*andqi3_mem"
- [(set (match_operand:QI 0 "memory_operand" "=R,Q")
- (and:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "i,i")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FF;
-
- if (val == 0x0ff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- /* The bclr instruction uses an inverted mask. */
- operands[1] = GEN_INT ((~val) & 0x0FF);
-
- /* When destination is a global variable, generate a .relax instruction
- and load the address in the clobber register. That load can be
- eliminated by the linker if the address is in page0. */
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"bclr\\t0,%2, %1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
- return \"bclr\\t%b0, %1\";
-}")
-
-(define_insn "*andqi3_const"
- [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
- (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0x0ff)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (!H_REG_P (operands[0]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = GEN_INT ((~val) & 0x0FF);
- output_asm_insn (\"bclr\\t%b0, %b1\", ops);
- return \"\";
- }
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"andb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"anda\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-(define_insn "*andqi3_gen"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"andb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"anda\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-;;--------------------------------------------------------------------
-;;- Bit set or instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "iordi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, IOR, operands);
- DONE;")
-
-(define_insn_and_split "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, IOR, operands);
- DONE;")
-
-(define_expand "iorhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ior:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "splitable_operand" "")))]
- ""
- "")
-
-(define_insn "*iorhi3_mem"
- [(set (match_operand:HI 0 "memory_operand" "=R,Q")
- (ior:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FFFF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- CC_STATUS_INIT;
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- if ((val & 0x0FF) != 0)
- output_asm_insn (\"bset\\t1,%2, %b1\", operands);
-
- if ((val & 0x0FF00) != 0)
- output_asm_insn (\"bset\\t0,%2, %h1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
-
- if ((val & 0x0FF) != 0)
- output_asm_insn (\"bset\\t%b0, %b1\", operands);
-
- if ((val & 0x0FF00) != 0)
- output_asm_insn (\"bset\\t%h0, %h1\", operands);
-
- return \"\";
-}")
-
-(define_insn "*iorhi3_const"
- [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
- (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FFFF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
-
- if ((val & 0x0FF) != 0)
- {
- if (!H_REG_P (operands[0]))
- output_asm_insn (\"bset\\t%b0, %b2\", operands);
- else
- output_asm_insn (\"orab\\t%b2\", operands);
- }
-
- if ((val & 0x0FF00) != 0)
- {
- if (!H_REG_P (operands[0]))
- output_asm_insn (\"bset\\t%h0, %h2\", operands);
- else
- output_asm_insn (\"oraa\\t%h2\", operands);
- }
-
- CC_STATUS_INIT;
- return \"\";
-}")
-
-(define_insn "*iorhi3_gen"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"oraa\\t%h2\\n\\torab\\t%b2\";
-}")
-
-(define_expand "iorqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ior:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*iorqi3_mem"
- [(set (match_operand:QI 0 "memory_operand" "=R,Q")
- (ior:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=X,xy"))]
- "TARGET_RELAX && !TARGET_M6812"
- "*
-{
- int val = INTVAL (operands[1]) & 0x0FF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (which_alternative == 1)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = XEXP (operands[0], 0);
- ops[2] = gen_label_rtx ();
- output_asm_insn (\".relax\\t%l2\", ops);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"bset\\t0,%2, %1\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[2]));
- return \"\";
- }
- return \"bset\\t%b0, %1\";
-}")
-
-(define_insn "*iorqi3_const"
- [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
- (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (!H_REG_P (operands[0]))
- {
- return \"bset\\t%b0, %2\";
- }
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"orab\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"oraa\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-(define_insn "*iorqi3_gen"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"orab\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"oraa\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-
-;;--------------------------------------------------------------------
-;;- xor instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "xordi3"
- [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
- (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
- (match_operand:DI 2 "general_operand" "imu,imu")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (SImode, XOR, operands);
- DONE;")
-
-(define_insn_and_split "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=D,!u")
- (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "Dimu,imu")))
- (clobber (match_scratch:HI 3 "=X,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_logical (HImode, XOR, operands);
- DONE;")
-
-(define_insn "xorhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
- (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
- (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int val = INTVAL (operands[2]) & 0x0FFFF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if ((val & 0x0FF) != 0)
- {
- output_asm_insn (\"eorb\\t%b2\", operands);
- }
- else if ((val & 0x0FF) == 0x0FF)
- {
- output_asm_insn (\"comb\", operands);
- }
-
- if ((val & 0x0FF00) != 0)
- {
- output_asm_insn (\"eora\\t%h2\", operands);
- }
- else if ((val & 0x0FF00) == 0x0FF00)
- {
- output_asm_insn (\"coma\", operands);
- }
-
- CC_STATUS_INIT;
- return \"\";
- }
-
- CC_STATUS_INIT;
- return \"eora\\t%h2\\n\\teorb\\t%b2\";
-}")
-
-(define_insn "xorqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
- (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
- ""
- "*
-{
- if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
- return \"#\";
-
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int val = INTVAL (operands[2]) & 0x0FF;
-
- if (val == 0)
- {
- cc_status = cc_prev_status;
- return \"\";
- }
- if (val == 0x0FF)
- {
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"comb\";
- else
- return \"coma\";
- }
- }
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- return \"eorb\\t%b2\";
- else if (DA_REG_P (operands[0]))
- return \"eora\\t%b2\";
- else
- fatal_insn (\"Invalid operand in the instruction\", insn);
-}")
-
-;;--------------------------------------------------------------------
-;;- Bit set or instructions.
-;;--------------------------------------------------------------------
-
-(define_insn_and_split "*logicalsi3_zexthi"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(zero_extend:SI
- (match_operand:HI 1 "general_operand" "imudA"))
- (match_operand:SI 2 "general_operand" "Dimu")]))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "PUT_MODE (operands[3], HImode);
- if (X_REG_P (operands[2]))
- {
- operands[5] = operands[1];
- /* Make all the (set (REG:x) (REG:y)) a nop set. */
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = operands[1];
- operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- /* For an AND, make sure the high 16-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[6] = const0_rtx;
- }
- ")
-
-(define_insn_and_split "*logicalsi3_zextqi"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(zero_extend:SI
- (match_operand:QI 1 "general_operand" "d,*A,imu"))
- (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI D_REGNUM) (match_dup 7))
- (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "PUT_MODE (operands[3], QImode);
- if (X_REG_P (operands[2]))
- {
- operands[5] = operands[1];
- /* Make all the (set (REG:x) (REG:y)) a nop set. */
- operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[7] = operands[1];
- operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
- operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- /* For an AND, make sure the high 24-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[4] = const0_rtx;
- operands[6] = const0_rtx;
- }
- ")
-
-(define_insn_and_split "*logicalhi3_zexthi_ashift8"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (match_operator:HI 3 "m68hc11_logical_operator"
- [(zero_extend:HI
- (match_operand:QI 1 "general_operand" "imud*A"))
- (ashift:HI
- (match_operand:HI 2 "general_operand" "imud*A")
- (const_int 8))]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI B_REGNUM) (match_dup 5))]
- "
- if (GET_CODE (operands[3]) == AND)
- {
- emit_insn (gen_movhi (operands[0], const0_rtx));
- DONE;
- }
- else
- {
- operands[5] = operands[1];
- if (D_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
- }
- }
- ")
-
-(define_insn_and_split "*logicalhi3_zexthi"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (match_operator:HI 3 "m68hc11_logical_operator"
- [(zero_extend:HI
- (match_operand:QI 1 "general_operand" "imd*A,?u"))
- (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:QI B_REGNUM) (match_dup 6))
- (set (reg:QI A_REGNUM) (match_dup 4))
- (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
- "
- PUT_MODE (operands[3], QImode);
- if (D_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- operands[5] = operands[1];
- operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
- operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
- if (D_REG_P (operands[1]))
- operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
- else
- operands[6] = operands[1];
- }
- /* For an AND, make sure the high 8-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[4] = const0_rtx;
- }
- ")
-
-
-(define_insn_and_split "*logicalsi3_silshr16"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(lshiftrt:SI
- (match_operand:SI 1 "general_operand" "uim,uim,0,0")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
- (set (reg:HI X_REGNUM) (match_dup 6))]
- "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
- if (X_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
- }
- PUT_MODE (operands[3], HImode);
-
- /* For an AND, make sure the high 16-bit part is cleared. */
- if (GET_CODE (operands[3]) == AND)
- {
- operands[6] = const0_rtx;
- }
-")
-
-(define_insn_and_split "*logicalsi3_silshl16"
- [(set (match_operand:SI 0 "register_operand" "=D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(ashift:SI
- (match_operand:SI 1 "general_operand" "uim,?D")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "0,0")]))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
- (set (reg:HI D_REGNUM) (match_dup 5))]
- "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
- PUT_MODE (operands[3], HImode);
-
- if (GET_CODE (operands[3]) == AND)
- operands[5] = const0_rtx;
- else
- operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- ")
-
-(define_insn_and_split "*logicalsi3_silshl16_zext"
- [(set (match_operand:SI 0 "register_operand" "=D,D,D")
- (match_operator:SI 3 "m68hc11_logical_operator"
- [(ashift:SI
- (zero_extend:SI
- (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
- (const_int 16))
- (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
- ""
- "#"
- ;; Must split before z register replacement
- "reload_completed"
- [(set (match_dup 4) (match_dup 5))
- (set (match_dup 6) (match_dup 7))]
- "
- /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
- if (GET_CODE (operands[1]) == HARD_D_REGNUM
- && GET_CODE (operands[3]) != AND)
- {
- /* This particular case is too early to be split before
- Z register replacement because the cse-reg pass we do
- does not recognize the 'swap_areg'. It is ok to handle
- this case after. */
- if (z_replacement_completed != 2)
- {
- FAIL;
- }
- emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
- emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
- gen_rtx_REG (HImode, HARD_X_REGNUM)));
- }
- operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- operands[5] = operands[2];
- operands[7] = operands[1];
-
- if (GET_CODE (operands[3]) == AND)
- operands[5] = operands[7] = const0_rtx;
- ")
-
-;;--------------------------------------------------------------------
-;; 16-bit Arithmetic and logical operations on X and Y:
-;;
-;; PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-;;
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_arith_operator"
- [(match_operand:HI 1 "hard_addr_reg_operand" "")
- (match_operand:HI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* If we are adding a small constant to X or Y, it's
- better to use one or several inx/iny instructions. */
- && !(GET_CODE (operands[3]) == PLUS
- && ((TARGET_M6812
- && (immediate_operand (operands[2], HImode)
- || hard_reg_operand (operands[2], HImode)))
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >= -4
- && INTVAL (operands[2]) <= 4)))"
- [(set (match_dup 9) (match_dup 0))
- (set (match_dup 4) (match_dup 5))
- (set (match_dup 8) (match_dup 7))
- (set (match_dup 0) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
- operands[9] = operands[0];
- /* For 68HC12, push the value on the stack and do the operation
- with a pop. */
- if (TARGET_M6812
- && m68hc11_non_shift_operator (operands[3], HImode)
- && (H_REG_P (operands[2])
- || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
- && reg_mentioned_p (operands[0], operands[2]))))
- {
- operands[4] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[6] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[5] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- /* Save the operand2 in a temporary location and use it. */
- else if ((H_REG_P (operands[2])
- || reg_mentioned_p (operands[0], operands[2]))
- && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
- {
- if (GET_CODE (operands[3]) == MINUS
- && reg_mentioned_p (operands[0], operands[2]))
- {
- operands[9] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[4] = operands[7] = operands[0];
- operands[6] = operands[8];
- operands[5] = operands[2];
- }
- else
- {
- operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = operands[4];
- if (!H_REG_P (operands[2]))
- {
- operands[5] = operands[0];
- operands[7] = operands[2];
- operands[8] = operands[0];
- }
- else
- {
- operands[5] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- }
- }
- else
- {
- operands[4] = operands[5] = operands[0];
- operands[6] = operands[2];
- operands[8] = operands[7] = operands[0];
- }
- ")
-
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_arith_operator"
- [(match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* If we are adding a small constant to X or Y, it's
- better to use one or several inx/iny instructions. */
- && !(GET_CODE (operands[3]) == PLUS
- && ((TARGET_M6812
- && (immediate_operand (operands[2], HImode)
- || hard_reg_operand (operands[2], HImode)))
- || (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >= -4
- && INTVAL (operands[2]) <= 4)))"
- [(set (match_dup 0) (match_dup 1))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
- ")
-
-;;
-;; Next split handles the logical operations on D register with
-;; another hard register for the second operand. For this, we
-;; have to save the second operand in a scratch location and use
-;; it instead. This must be supported because in some (rare) cases
-;; the second operand can come in a hard register and the reload
-;; pass doesn't know how to reload it in a memory location.
-;;
-;; PLUS MINUS AND IOR XOR
-;;
-;; The shift operators are special and must not appear here.
-;;
-(define_split
- [(set (match_operand:HI 0 "d_register_operand" "")
- (match_operator:HI 3 "m68hc11_non_shift_operator"
- [(match_operand:HI 1 "d_register_operand" "")
- (match_operand:HI 2 "hard_reg_operand" "")]))]
- "TARGET_M6811
- && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
- [(set (match_dup 4) (match_dup 2))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
- "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
-
-;;
-;; For 68HC12, push the operand[2] value on the stack and do the
-;; logical/arithmetic operation with a pop.
-;;
-(define_split
- [(set (match_operand:HI 0 "d_register_operand" "")
- (match_operator:HI 3 "m68hc11_non_shift_operator"
- [(match_operand:HI 1 "d_register_operand" "")
- (match_operand:HI 2 "hard_reg_operand" "")]))]
- "TARGET_M6812
- && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
- [(set (match_dup 4) (match_dup 2))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
- "operands[4] = gen_rtx_MEM (HImode,
- gen_rtx_PRE_DEC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- operands[5] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));
- ")
-
-;;--------------------------------------------------------------------
-;; 16-bit Unary operations on X and Y:
-;;
-;; NOT NEG
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-(define_split
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 2 "m68hc11_unary_operator"
- [(match_operand 1 "general_operand" "")]))]
- "z_replacement_completed == 2"
- [(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "
-{
- if ((H_REG_P (operands[1])
- && !rtx_equal_p (operands[0], operands[1]))
- || reg_mentioned_p (operands[0], operands[1]))
- {
- /* Move to the destination register, before the xgdx. */
- operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
- REGNO (operands[0]));
- operands[5] = operands[1];
-
- /* Apply the operation on D. */
- operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
- }
- else
- {
- /* Generate a copy to same register (nop). */
- operands[4] = operands[5] = operands[0];
- operands[3] = operands[1];
- }
-}")
-
-;;
-;; 8-bit operations on address registers.
-;;
-;; We have to take care that the address register is not used for the
-;; source of operand2. If operand2 is the D register, we have to save
-;; that register in a temporary location.
-;;
-;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operator:QI 3 "m68hc11_arith_operator"
- [(match_operand:QI 1 "hard_addr_reg_operand" "")
- (match_operand:QI 2 "general_operand" "")]))]
- "z_replacement_completed == 2
- /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
- incqi pattern generates a better code. */
- && !(GET_CODE (operands[3]) == PLUS
- && GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
- [(set (match_dup 5) (match_dup 6))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (match_dup 4) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
- (set (match_dup 4) (reg:HI D_REGNUM))])]
- "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
-
- /* For the second operand is a hard register or if the address
- register appears in the source, we have to save the operand[2]
- value in a temporary location and then use that temp.
- Otherwise, it's ok and we generate a (set (D) (D)) that
- will result in a nop. */
- if (H_REG_P (operands[2]))
- {
- operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
- operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- }
- else if (reg_mentioned_p (operands[0], operands[2]))
- {
- operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[6] = operands[2];
- operands[7] = operands[5];
- }
- else
- {
- operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- operands[7] = operands[2];
- }
- ")
-
-;;
-;; Next split handles the logical operations on D register with
-;; another hard register for the second operand. For this, we
-;; have to save the second operand in a scratch location and use
-;; it instead. This must be supported because in some (rare) cases
-;; the second operand can come in a hard register and the reload
-;; pass doesn't know how to reload it in a memory location.
-;;
-;; PLUS MINUS AND IOR XOR
-;;
-;; The shift operators are special and must not appear here.
-;;
-(define_split
- [(set (match_operand:QI 0 "d_register_operand" "")
- (match_operator:QI 3 "m68hc11_non_shift_operator"
- [(match_operand:QI 1 "d_register_operand" "")
- (match_operand:QI 2 "hard_reg_operand" "")]))]
- "reload_completed"
- [(set (match_dup 5) (match_dup 6))
- (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
- "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
- operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
- operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
-
-;;--------------------------------------------------------------------
-;; 8-bit Unary operations on X and Y:
-;;
-;; NOT NEG
-;;
-;; Operations on X or Y registers are split here. Instructions are
-;; changed into:
-;; - xgdx/xgdy instruction pattern,
-;; - The same operation on register D,
-;; - xgdx/xgdy instruction pattern.
-;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
-;; We also handle the case were the address register is used in both source
-;; operands, such as:
-;;
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
-;; or
-;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
-;;
-(define_split
- [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
- (match_operator:QI 2 "m68hc11_unary_operator"
- [(match_operand:QI 1 "general_operand" "")]))]
- "z_replacement_completed == 2"
- [(set (match_dup 4) (match_dup 5))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
- (set (match_dup 3) (reg:HI D_REGNUM))])]
- "
-{
- operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
- if ((H_REG_P (operands[1])
- && !rtx_equal_p (operands[0], operands[1]))
- || reg_mentioned_p (operands[0], operands[1]))
- {
- /* Move to the destination register, before the xgdx. */
- operands[4] = operands[0];
- operands[5] = operands[1];
-
- /* Apply the operation on D. */
- operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
- }
- else
- {
- operands[4] = operands[5] = operands[0];
- operands[6] = operands[1];
- }
-}")
-
-
-;;--------------------------------------------------------------------
-;;- Complements
-;;--------------------------------------------------------------------
-
-(define_expand "negdi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (neg:DI (match_operand:DI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
- DONE;")
-
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (neg:SI (match_operand:SI 1 "general_operand" "0")))]
- ""
- "*
-{
- rtx ops[1];
-
- CC_STATUS_INIT;
-
- /* With -Os or without -O, use a special library call. */
- if (optimize_size || optimize == 0)
- return \"bsr\\t___negsi2\";
-
- ops[0] = gen_label_rtx ();
-
- /* 32-bit complement and add 1. */
- output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
- output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
- output_asm_insn (\"bne\\t%l0\", ops);
- output_asm_insn (\"inx\", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
- return \"\";
-}")
-
-(define_insn "neghi2"
- [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
- (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
- ""
- "@
- coma\\n\\tcomb\\n\\taddd\\t#1
- clra\\n\\tclrb\\n\\tsubd\\t%1
- xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
-
-(define_insn "negqi2"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
- (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
- ""
- "@
- negb
- neg\\t%b0
- neg\\t%b0
- #")
-
-;;
-;; - 32-bit complement. GCC knows how to translate them but providing a
-;; pattern generates better/smaller code.
-;;
-(define_expand "one_cmpldi2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (not:DI (match_operand:DI 1 "general_operand" "")))]
- ""
- "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
- DONE;")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
- (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
- (clobber (match_scratch:HI 2 "=X,d,X"))]
- ""
- "@
- bsr\\t___one_cmplsi2
- #
- #")
-
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
- (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
- ""
- "@
- comb\\n\\tcoma
- com\\t%b0\\n\\tcom\\t%h0
- #
- com\\t%b0\\n\\tcom\\t%h0")
-
-(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
- (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
- ""
- "@
- comb
- com\\t%b0
- #
- com\\t%b0")
-
-(define_split /* "*one_cmplsi2" */
- [(set (match_operand:SI 0 "non_push_operand" "")
- (not:SI (match_dup 0)))
- (clobber (match_scratch:HI 1 ""))]
- "z_replacement_completed == 2
- && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
- [(set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 3) (not:HI (match_dup 3)))]
- "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-(define_split /* "*one_cmplsi2" */
- [(set (match_operand:SI 0 "non_push_operand" "")
- (not:SI (match_operand:SI 1 "non_push_operand" "")))
- (clobber (match_operand:HI 2 "d_register_operand" ""))]
- "z_replacement_completed == 2
- && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 4) (match_dup 2))
- (set (match_dup 2) (match_dup 5))
- (set (match_dup 2) (not:HI (match_dup 2)))
- (set (match_dup 6) (match_dup 2))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
-
-;;--------------------------------------------------------------------
-;;- arithmetic shifts
-;;--------------------------------------------------------------------
-;;
-;; Provide some 64-bit shift patterns.
-(define_expand "ashldi3"
- [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (ashift:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
- {
- FAIL;
- }
-}")
-
-(define_insn_and_split "*ashldi3_const32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
- (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
- (const_int 32)))
- (clobber (match_scratch:HI 2 "=&A,d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "/* Move the lowpart in the highpart first in case the shift
- is applied on the source. */
- if (IS_STACK_PUSH (operands[0]))
- {
- m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- const0_rtx, operands[2]);
-
- /* Adjust first operand if it uses SP so that we take into
- account the above push. Can occur only for 68HC12. */
- if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
- operands[1]))
- operands[1] = adjust_address (operands[1],
- GET_MODE (operands[0]), 4);
- }
- m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
- m68hc11_gen_lowpart (SImode, operands[1]),
- operands[2]);
- if (!IS_STACK_PUSH (operands[0]))
- {
- m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- const0_rtx, operands[2]);
- }
- DONE;")
-
-(define_insn_and_split "*ashldi3_const1"
- [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
- (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=d,d,d"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
- (set (match_dup 4) (match_dup 2))
-
- (set (match_dup 2) (match_dup 5))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 6) (match_dup 2))
-
- (set (match_dup 2) (match_dup 7))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 8) (match_dup 2))
-
- (set (match_dup 2) (match_dup 9))
- (parallel [(set (match_dup 2)
- (rotate:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 10) (match_dup 2))]
- "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
- operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
-
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
- operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
-
- operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
- operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
-
-(define_insn "addsi_silshr16"
- [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
- ""
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "")))]
- "z_replacement_completed == 2 && !X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16))
- (match_operand:SI 2 "general_operand" "")))]
- "z_replacement_completed == 2 && X_REG_P (operands[1])"
- [(set (reg:HI D_REGNUM) (match_dup 5))
- (set (reg:HI X_REGNUM) (match_dup 3))
- (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
- (const_int 0))
- (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
- if (X_REG_P (operands[2]))
- {
- operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- }
- else
- {
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
- operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- }
-")
-
-(define_insn "addsi_ashift16"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI
- (mult:SI (match_operand:SI 2 "general_operand" "uim")
- (const_int 65536))
- (match_operand:SI 1 "general_operand" "0")))
- (clobber (match_scratch:HI 3 "=X"))]
- "0"
- "#")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI
- (mult:SI (match_operand:SI 2 "general_operand" "")
- (const_int 65536))
- (match_operand:SI 1 "general_operand" "")))
- (clobber (match_scratch:HI 3 "=X"))]
- "0 && reload_completed && z_replacement_completed == 2"
- [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
- "
-{
- operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
-}")
-
-(define_insn_and_split "addsi_andshr16"
- [(set (match_operand:SI 0 "register_operand" "=D")
- (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
- (const_int 65535))
- (match_operand:SI 2 "general_operand" "0")))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
- (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
- "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
-
-;;
-;; 32-bit shifts are made by a small library routine that uses
-;; a specific passing convention for parameters (for efficiency reasons).
-;;
-;; [D + X] -> Value to be shifted
-;; Y -> Shift count
-;;
-;; The shift count is clobbered by the routine.
-;;
-(define_expand "ashlsi3"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_dup 0) (ashift:SI (match_dup 0)
- (match_operand:HI 2 "nonmemory_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_split
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (ashift:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16)))
- (clobber (match_scratch:HI 3 ""))]
- ""
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))]
- "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
-
-(define_insn "*ashlsi3_const16"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
- (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X,X,X"))]
- ""
- "#")
-
-(define_insn_and_split "*ashlsi3_const16_zexthi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
- (ashift:SI (zero_extend:HI
- (match_operand:HI 1 "general_operand" "duim*A"))
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X"))]
- ""
- "#"
- "reload_completed"
- [(set (reg:HI X_REGNUM) (match_dup 1))
- (set (reg:HI D_REGNUM) (const_int 0))]
- "")
-
-(define_insn "*ashlsi3_const1"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[1]))
- {
- return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
- }
- else
- {
- rtx ops[2];
-
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"lsld\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- ops[0] = ops[1];
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- /* Load the high part in X in case the source operand
- uses X as a memory pointer. */
- ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgdx\", ops);
- }
- output_asm_insn (\"rolb\", ops);
- output_asm_insn (\"rola\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- output_asm_insn (\"xgdx\", ops);
- }
- return \"\";
- }
-}")
-
-(define_insn "*ashlsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (ashift:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *ashlsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
-}")
-
-(define_insn "*ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (ashift:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
-
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___ashlsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___ashlsi3\";
-}")
-
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ashift:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ASHIFT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "*ashlhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[0]))
- {
- return \"asld\";
- }
-
- output_asm_insn (\"asl\\t%b0\", operands);
- output_asm_insn (\"rol\\t%h0\", operands);
- CC_STATUS_INIT;
- return \"\";
-}")
-
-
-(define_insn "*ashlhi3_2"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- return \"bsr\\t___lshlhi3\";
-}")
-
-(define_insn "*ashlhi3"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
- (ashift:HI (match_dup 0)
- (match_operand:HI 1 "register_operand" "+x")))
- (clobber (match_dup 1))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"bsr\\t___lshlhi3\";
-}")
-
-(define_insn "*ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,!*A")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- CC_STATUS_INIT;
- output_asm_insn (\"tba\", operands);
- if (i == 15)
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"anda\\t#0\", operands);
- output_asm_insn (\"rora\", operands);
- }
- else
- while (i != 8 )
- {
- output_asm_insn (\"asla\", operands);
- i--;
- }
- return \"clrb\";
- }
- for (i = 0; i < INTVAL (operands[2]) - 1; i++)
- {
- output_asm_insn (\"asld\", operands);
- }
- return \"asld\";
-}")
-
-(define_expand "ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ashift:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*ashlqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- aslb
- asl\\t%b0
- asl\\t%b0
- asl%0
- #")
-
-(define_insn "*ashlqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"aslb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"asla\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- if (DA_REG_P (operands[0]))
- return \"clra\";
- else
- return \"clrb\";
- }
- else if (i == 7)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"ldaa\\t#0\", operands);
- return \"rora\";
- }
- else
- {
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"ldab\\t#0\", operands);
- return \"rorb\";
- }
- }
- else if (i == 6)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"rora\", operands);
- output_asm_insn (\"rora\", operands);
- return \"anda\\t#0xC0\";
- }
- else
- {
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"rorb\", operands);
- output_asm_insn (\"rorb\", operands);
- return \"andb\\t#0xC0\";
- }
- }
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*ashlqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- CC_STATUS_INIT;
- return \"bsr\\t___lshlqi3\";
-}")
-
-(define_expand "ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ASHIFTRT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "*ashrhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (D_REG_P (operands[0]))
- {
- return \"asra\\n\\trorb\";
- }
-
- output_asm_insn (\"asr\\t%h0\", operands);
- output_asm_insn (\"ror\\t%b0\", operands);
- return \"\";
-}")
-
-
-(define_insn "*ashrhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d,!*A")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "const_int_operand" "")))]
- ""
- "*
-{
- rtx ops[2];
- int val = INTVAL (operands[2]);
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (val >= 15)
- {
- ops[0] = gen_label_rtx ();
-
- output_asm_insn (\"clrb\", operands);
- output_asm_insn (\"rola\", operands);
-
- /* Clear A without clearing the carry flag. */
- output_asm_insn (\"tba\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"coma\", operands);
- output_asm_insn (\"comb\", operands);
-
- CC_STATUS_INIT;
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- return \"\";
- }
- if (val >= 8)
- {
- ops[0] = gen_label_rtx ();
-
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"clra\", operands);
- output_asm_insn (\"tstb\", operands);
- output_asm_insn (\"bge\\t%l0\", ops);
- output_asm_insn (\"deca\", operands);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
-
- val -= 8;
-
- while (val > 0)
- {
- output_asm_insn (\"asrb\", operands);
- val--;
- }
- /* Status is ok. */
- return \"\";
- }
- if (val == 7)
- {
- ops[0] = gen_label_rtx ();
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"anda\\t#0\", operands);
- output_asm_insn (\"bcc\\t%l0\", ops);
- output_asm_insn (\"coma\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
- return \"\";
- }
- while (val > 0)
- {
- output_asm_insn (\"asra\", operands);
- output_asm_insn (\"rorb\", operands);
- val--;
- }
- CC_STATUS_INIT;
-
- return \"\";
-}")
-
-(define_insn "*ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- output_asm_insn (\"bsr\\t___ashrhi3\", operands);
- return \"\";
-}")
-
-(define_expand "ashrsi3"
- [(parallel
- [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_insn "*ashrsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *ashrsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
-}")
-
-(define_insn "*ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (ashiftrt:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___ashrsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___ashrsi3\";
-}")
-
-(define_expand "ashrqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*ashrqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- asrb
- asr\\t%b0
- asr\\t%b0
- asr%0
- #")
-
-(define_insn "*ashrqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"asrb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"asra\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i > 8)
- i = 8;
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*ashrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- CC_STATUS_INIT;
- return \"bsr\\t___ashrqi3\";
-}")
-
-;;--------------------------------------------------------------------
-;; logical shift instructions
-;;--------------------------------------------------------------------
-(define_expand "lshrdi3"
- [(parallel [(set (match_operand:DI 0 "general_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))
- (clobber (match_scratch:HI 3 ""))])]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
- && INTVAL (operands[2]) != 1))
- {
- FAIL;
- }
-}")
-
-(define_insn_and_split "*lshrdi3_const32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
- (const_int 32)))
- (clobber (match_scratch:HI 2 "=&A,d,d"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
- "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
- m68hc11_gen_highpart (SImode, operands[1]),
- operands[2]);
- m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
- const0_rtx, operands[2]);
- DONE;")
-
-(define_insn "*lshrdi3_const63"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d,d"))]
- "INTVAL (operands[2]) >= 48"
- "#")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "z_replacement_completed && INTVAL (operands[2]) >= 56"
- [(set (reg:QI D_REGNUM) (match_dup 9))
- (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
- (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
- (set (match_dup 4) (reg:HI D_REGNUM))
- (set (reg:QI D_REGNUM) (const_int 0))
- (set (match_dup 5) (reg:HI D_REGNUM))
- (set (match_dup 6) (reg:HI D_REGNUM))
- (set (match_dup 7) (reg:HI D_REGNUM))]
- "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
- operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
-
- operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "const_int_operand" "")))
- (clobber (match_scratch:HI 3 "=d"))]
- "z_replacement_completed && INTVAL (operands[2]) >= 48
- && INTVAL (operands[2]) < 56"
- [(set (reg:HI D_REGNUM) (match_dup 9))
- (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
- (set (match_dup 4) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (const_int 0))
- (set (match_dup 5) (reg:HI D_REGNUM))
- (set (match_dup 6) (reg:HI D_REGNUM))
- (set (match_dup 7) (reg:HI D_REGNUM))]
- "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
- operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
-
- operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
- operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
-
-(define_insn_and_split "*lshrdi_const1"
- [(set (match_operand:DI 0 "non_push_operand" "=m,u")
- (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=d,d"))]
- ""
- "#"
- "z_replacement_completed == 2"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
- (set (match_dup 4) (match_dup 2))
-
- (set (match_dup 2) (match_dup 5))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 6) (match_dup 2))
-
- (set (match_dup 2) (match_dup 7))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 8) (match_dup 2))
-
- (set (match_dup 2) (match_dup 9))
- (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 10) (match_dup 2))]
- "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
- operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
-
- operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
- operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
- operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
-
- operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
- operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
- operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
-
- operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
- operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
- operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
-
-(define_expand "lshrsi3"
- [(parallel
- [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
- (clobber (scratch:HI))])
- (parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (clobber (scratch:HI))])]
- ""
- "")
-
-(define_split
- [(set (match_operand:SI 0 "non_push_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (const_int 16)))
- (clobber (match_scratch:HI 3 ""))]
- "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (const_int 0))]
- "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
- operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
- operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-(define_insn "*lshrsi3_const16"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
- (const_int 16)))
- (clobber (match_scratch:HI 2 "=X,X,X,X"))]
- ""
- "@
- #
- xgdx\\n\\tldx\\t#0
- #
- #")
-
-(define_insn "*lshrsi3_const1"
- [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
- (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
- (const_int 1)))
- (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- if (X_REG_P (operands[1]))
- {
- return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
- }
- else
- {
- rtx ops[2];
-
- ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
- ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"lsrd\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- ops[0] = ops[1];
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- }
- else
- {
- /* Load the lowpart in X in case the operands is some N,x. */
- ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
- ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgdx\", ops);
- }
- output_asm_insn (\"rora\", ops);
- output_asm_insn (\"rorb\", ops);
- if (!X_REG_P (operands[0]))
- {
- ops[1] = ops[0];
- ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
- m68hc11_gen_movhi (insn, ops);
- }
- return \"\";
- }
-}")
-
-(define_insn "*lshrsi3_const"
- [(set (match_operand:SI 0 "register_operand" "+D")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (clobber (match_scratch:HI 2 "=y"))]
- "TARGET_M6811 /* See *lshrsi3 note. */"
- "*
-{
- CC_STATUS_INIT;
- return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
-}")
-
-(define_insn "*lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "+D,D")
- (lshiftrt:SI (match_dup 0)
- (match_operand:HI 1 "general_operand" "y,mi")))
- (clobber (match_scratch:HI 2 "=1,X"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- /* There is a reload problem if we don't accept 'm' for the shift value.
- A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
- and this conflicts with all reloads. Since X, Y, Z are used there
- is not enough register in class A_REGS.
-
- Assuming that 'operands[1]' does not refer to the stack (which
- is true for 68hc11 only, we save temporary the value of Y.
-
- For 68HC12 we must also accept a constant because Z register is
- disabled when compiling with -fomit-frame-pointer. We can come up
- with a reload problem and the *lshrsi3_const pattern was disabled
- for that reason. */
- if (!Y_REG_P (operands[2]))
- {
- rtx ops[1];
- int y_dead = dead_register_here (insn, iy_reg);
-
- ops[0] = operands[1];
- if (y_dead == 0)
- {
- output_asm_insn (\"pshy\", operands);
- if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
- ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
- }
- output_asm_insn (\"ldy\\t%0\", ops);
- output_asm_insn (\"bsr\\t___lshrsi3\", operands);
- return y_dead == 0 ? \"puly\" : \"\";
- }
- return \"bsr\\t___lshrsi3\";
-}")
-
-(define_expand "lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_LSHIFTRT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "lshrhi3_const1"
- [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
- (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
- (const_int 1)))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (D_REG_P (operands[0]))
- return \"lsrd\";
-
- CC_STATUS_INIT;
- return \"lsr\\t%h0\\n\\tror\\t%b0\";
-}")
-
-(define_insn "lshrhi3_const"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
- (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
- ""
- "*
-{
- int val = INTVAL (operands[2]);
-
- if (A_REG_P (operands[0]))
- return \"#\";
-
- if (val >= 8)
- {
- if (val == 8)
- CC_STATUS_INIT;
-
- if (!H_REG_P (operands[1]))
- {
- output_asm_insn (\"clra\", operands);
- output_asm_insn (\"ldab\\t%h1\", operands);
- }
- else if (A_REG_P (operands[1]))
- {
- output_asm_insn (\"st%1\\t%t0\", operands);
- output_asm_insn (\"ldab\\t%t0\", operands);
- output_asm_insn (\"clra\", operands);
- }
- else
- {
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"clra\", operands);
- }
- val -= 8;
- switch (val)
- {
- case 7:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"rolb\", operands);
- break;
-
- case 6:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"andb\\t#3\", operands);
- break;
-
- default:
- while (val > 0)
- {
- val --;
- output_asm_insn (\"lsrb\", operands);
- }
- break;
- }
- return \"\";
- }
-
- if (!D_REG_P (operands[1]))
- m68hc11_gen_movhi (insn, operands);
- switch (val)
- {
- case 7:
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"tab\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"anda\\t#1\", operands);
- CC_STATUS_INIT;
- break;
-
- default:
- while (val > 0)
- {
- val --;
- output_asm_insn (\"lsrd\", operands);
- }
- }
- return \"\";
-}")
-
-(define_insn "*lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "register_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___lshrhi3\";
-}")
-
-(define_expand "lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
- (match_operand:QI 2 "general_operand" "")))]
- ""
- "")
-
-(define_insn "*lshrqi3_const1"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
- (const_int 1)))]
- ""
- "@
- lsr\\t%b0
- lsrb
- lsr\\t%b0
- lsr%0
- #")
-
-(define_insn "*lshrqi3_const"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "const_int_operand" "")))]
- ""
- "*
-{
- int i;
- const char* insn_code;
-
- if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
- insn_code = \"lsrb\";
- else if (DA_REG_P (operands[0]))
- insn_code = \"lsra\";
- else
- return \"#\";
-
- i = INTVAL (operands[2]);
- if (i >= 8)
- {
- if (DA_REG_P (operands[0]))
- return \"clra\";
- else
- return \"clrb\";
- }
- else if (i == 7)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"ldaa\\t#0\", operands);
- return \"rola\";
- }
- else
- {
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"ldab\\t#0\", operands);
- return \"rolb\";
- }
- }
- else if (i == 6)
- {
- if (DA_REG_P (operands[0]))
- {
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- output_asm_insn (\"rola\", operands);
- return \"anda\\t#3\";
- }
- else
- {
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- output_asm_insn (\"rolb\", operands);
- return \"andb\\t#3\";
- }
- }
- while (--i >= 0)
- {
- output_asm_insn (insn_code, operands);
- }
- return \"\";
-}")
-
-(define_insn "*lshrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
- (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
- (match_operand:QI 2 "nonimmediate_operand"
- "m*u*d*A,m*u*d*A,m*u")))]
- ""
- "*
-{
- rtx ops[2];
-
- if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
- ops[1] = operands[2];
- m68hc11_gen_movqi (insn, ops);
-
- if (!optimize || optimize_size)
- {
- return \"bsr\\t___lshrqi3\";
- }
-
- ops[0] = gen_label_rtx ();
- ops[1] = gen_label_rtx ();
- output_asm_insn (\"ble\\t%l1\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[0]));
-
- output_asm_insn (\"lsrb\", operands);
- output_asm_insn (\"deca\", operands);
- output_asm_insn (\"bne\\t%l0\", ops);
-
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (ops[1]));
- return \"\";
-}")
-
-(define_insn "*rotlqi3_with_carry"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
- (reg:QI CC_REGNUM)))]
- ""
- "*
-{
- if (DA_REG_P (operands[0]))
- return \"rola\";
- else
- return \"rolb\";
-}")
-
-(define_insn "*rotlhi3_with_carry"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotate:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))
- (clobber (reg:HI CC_REGNUM))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"rolb\\n\\trola\";
-}")
-
-(define_insn "*rotrhi3_with_carry"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0")
- (const_int 1)))
- (clobber (reg:HI CC_REGNUM))]
- ""
- "*
-{
- CC_STATUS_INIT;
- return \"rora\\n\\trorb\";
-}")
-
-(define_insn "rotlqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "const_int_operand" "i,i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATE, insn, operands);
- return \"\";
-}")
-
-(define_insn "rotrqi3"
- [(set (match_operand:QI 0 "register_operand" "=d,!q")
- (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "const_int_operand" "i,i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATERT, insn, operands);
- return \"\";
-}")
-
-(define_expand "rotlhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (rotate:HI (match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ROTATE (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "rotlhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotate:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "const_int_operand" "i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATE, insn, operands);
- return \"\";
-}")
-
-(define_insn "*rotlhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___rotlhi3\";
-}")
-
-(define_expand "rotrhi3"
- [(set (match_operand:HI 0 "register_operand" "")
- (rotatert:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT)
- {
- rtx scratch = gen_reg_rtx (HImode);
- operand1 = force_reg (HImode, operand1);
-
- emit_move_insn (scratch, operands[2]);
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_SET (VOIDmode,
- operand0,
- gen_rtx_ROTATERT (HImode,
- operand1, scratch)),
- gen_rtx_CLOBBER (VOIDmode, scratch))));
- DONE;
- }
-}")
-
-(define_insn "rotrhi3_const"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "const_int_operand" "i")))]
- ""
- "*
-{
- m68hc11_gen_rotate (ROTATERT, insn, operands);
- return \"\";
-}")
-
-(define_insn "*rotrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,*x")
- (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:HI 2 "general_operand" "+x,+d")))
- (clobber (match_dup 2))]
- ""
- "*
-{
- if (A_REG_P (operands[0]))
- return \"#\";
-
- return \"bsr\\t___rotrhi3\";
-}")
-
-;; Split a shift operation on an address register in a shift
-;; on D_REGNUM.
-(define_split /* "*rotrhi3_addr" */
- [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
- (match_operator:HI 3 "m68hc11_shift_operator"
- [(match_operand:HI 1 "register_operand" "")
- (match_operand:HI 2 "register_operand" "")]))
- (clobber (match_dup 2))]
- "z_replacement_completed == 2"
- [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (parallel [(set (reg:HI D_REGNUM)
- (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
- (clobber (match_dup 0))])
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "")
-
-;;--------------------------------------------------------------------
-;;- 68HC12 Decrement/Increment and branch
-;;--------------------------------------------------------------------
-;; These patterns are used by loop optimization as well as peephole2
-;; They must handle reloading themselves and the scratch register
-;; is used for that. Even if we accept memory operand, we must not
-;; accept them on the predicate because it might create too many reloads.
-;; (specially on HC12 due to its auto-incdec addressing modes).
-;;
-(define_expand "decrement_and_branch_until_zero"
- [(parallel [(set (pc)
- (if_then_else
- (ne (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int 0))
- (const_int 1))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:HI 2 ""))])]
- "TARGET_M6812"
- "")
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- "TARGET_M6812"
- "
-{
- /* Reject non-constant loops as it generates bigger code due to
- the handling of the loop register. We can do better by using
- the peephole2 dbcc/ibcc patterns. */
- if (INTVAL (operands[1]) == 0)
- {
- FAIL;
- }
-
- /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
- the operator and its operands are not relevant. */
- if (GET_MODE (operands[0]) == HImode)
- {
- emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
- gen_rtx_NE (HImode,
- operands[0],
- const1_rtx),
- operands[4]));
- DONE;
- }
- if (GET_MODE (operands[0]) == QImode)
- {
- emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
- gen_rtx_NE (QImode,
- operands[0],
- const1_rtx),
- operands[4]));
- DONE;
- }
-
- FAIL;
-}")
-
-;; Decrement-and-branch insns.
-(define_insn "m68hc12_dbcc_dec_hi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
- (const_int 1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (const_int -1)))
- (clobber (match_scratch:HI 3 "=X,dxy"))]
- "TARGET_M6812"
- "*
-{
- if (!H_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"dbeq\\t%0,%l2\";
- else
- return \"dbne\\t%0,%l2\";
-}")
-
-;; Decrement-and-branch insns.
-(define_insn "m68hc12_dbcc_inc_hi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
- (const_int -1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (const_int 1)))
- (clobber (match_scratch:HI 3 "=X,dxy"))]
- "TARGET_M6812"
- "*
-{
- if (!H_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"ibeq\\t%0,%l2\";
- else
- return \"ibeq\\t%0,%l2\";
-}")
-
-;; Decrement-and-branch (QImode).
-(define_insn "m68hc12_dbcc_dec_qi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "register_operand" "+d,m*u*A")
- (const_int 1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (const_int -1)))
- (clobber (match_scratch:QI 3 "=X,d"))]
- "TARGET_M6812"
- "*
-{
- if (!D_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"dbeq\\tb,%l2\";
- else
- return \"dbne\\tb,%l2\";
-}")
-
-;; Increment-and-branch (QImode).
-(define_insn "m68hc12_dbcc_inc_qi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "register_operand" "+d,m*u*A")
- (const_int -1)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (const_int 1)))
- (clobber (match_scratch:QI 3 "=X,d"))]
- "TARGET_M6812"
- "*
-{
- if (!D_REG_P (operands[0]))
- return \"#\";
-
- CC_STATUS_INIT;
- if (GET_CODE (operands[1]) == EQ)
- return \"ibeq\\tb,%l2\";
- else
- return \"ibeq\\tb,%l2\";
-}")
-
-;; Split the above to handle the case where operand 0 is in memory
-;; (a register that couldn't get a hard register)
-(define_split
- [(set (pc)
- (if_then_else
- (match_operator 3 "m68hc11_eq_compare_operator"
- [(match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "const_int_operand" "")])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
- (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
- "TARGET_M6812 && reload_completed"
- [(set (match_dup 5) (match_dup 0))
- (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
- (set (match_dup 0) (match_dup 5))
- (set (pc)
- (if_then_else (match_op_dup 3
- [(match_dup 5) (const_int 0)])
- (label_ref (match_dup 4)) (pc)))]
- "")
-
-;; Split the above to handle the case where operand 0 is in memory
-;; (a register that couldn't get a hard register)
-(define_split
- [(set (pc)
- (if_then_else
- (match_operator 3 "m68hc11_eq_compare_operator"
- [(match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "const_int_operand" "")])
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
- (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
- "TARGET_M6812 && reload_completed"
- [(set (match_dup 5) (match_dup 0))
- (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
- (set (match_dup 0) (match_dup 5))
- (set (pc)
- (if_then_else (match_op_dup 3
- [(match_dup 5) (const_int 0)])
- (label_ref (match_dup 4)) (pc)))]
- "")
-
-;;--------------------------------------------------------------------
-;;- Jumps and transfers
-;;--------------------------------------------------------------------
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "bra\\t%l0")
-
-(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "tst_operand" "")
- (match_operand:SI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (SImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "tst_operand" "")
- (match_operand:HI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-(define_expand "cbranchqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "tst_operand" "")
- (match_operand:QI 2 "cmp_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "
-{
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[2]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
-
- m68hc11_expand_compare_and_branch (GET_CODE (operands[0]), operands[1],
- operands[2], operands[3]);
- DONE;
-}")
-
-
-;;
-;; Test and branch instructions for 68HC12 for EQ and NE.
-;; 'z' must not appear in the constraints because the z replacement
-;; pass does not know how to restore the replacement register.
-;;
-(define_insn "*tbeq"
- [(set (pc)
- (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- /* If the flags are already set correctly, use 'bne/beq' which are
- smaller and a little bit faster. This happens quite often due
- to reloading of operands[0]. In that case, flags are set correctly
- due to the load instruction. */
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"beq\\t%l1\";
- else
- return \"tbeq\\t%0,%l1\";
-}")
-
-(define_insn "*tbne"
- [(set (pc)
- (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"bne\\t%l1\";
- else
- return \"tbne\\t%0,%l1\";
-}")
-
-;;
-;; Test and branch with 8-bit register. Register must be B (or A).
-;;
-(define_insn "*tbeq8"
- [(set (pc)
- (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"beq\\t%l1\";
- else
- return \"tbeq\\tb,%l1\";
-}")
-
-(define_insn "*tbne8"
- [(set (pc)
- (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- "TARGET_M6812"
- "*
-{
- if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
- || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
- return \"bne\\t%l1\";
- else
- return \"tbne\\tb,%l1\";
-}")
-
-(define_insn "*beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "beq\\t%l0")
-
-(define_insn "*bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bne\\t%l0")
-
-(define_insn "*bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bgt\\t%l0")
-
-(define_insn "*bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bhi\\t%l0")
-
-(define_insn "*blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\";
- else
- return \"blt\\t%l0\";
-}")
-
-(define_insn "*bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "blo\\t%l0")
-
-(define_insn "*bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bpl\\t%l0\";
- else
- return \"bge\\t%l0\";
-}")
-
-(define_insn "*bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bhs\\t%l0")
-
-(define_insn "*ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
- else
- return \"ble\\t%l0\";
-}")
-
-(define_insn "*bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "bls\\t%l0")
-
-;;--------------------------------------------------------------------
-;;- Negative test and branch
-;;--------------------------------------------------------------------
-(define_insn ""
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bne\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "beq\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
- else
- return \"ble\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bls\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bpl\\t%l0\";
- else
- return \"bge\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhs\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if (cc_prev_status.flags & CC_NO_OVERFLOW)
- return \"bmi\\t%l0\";
- else
- return \"blt\\t%l0\";
-}")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "blo\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bgt\\t%l0")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "bhi\\t%l0")
-
-;;--------------------------------------------------------------------
-;;- Calls
-;;--------------------------------------------------------------------
-;;
-;;- Call a function that returns no value.
-(define_insn "call"
- [(call (match_operand:QI 0 "memory_operand" "m")
- (match_operand:SI 1 "general_operand" "g"))]
- ;; Operand 1 not really used on the m68hc11.
- ""
- "*
-{
- if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
- {
- if (m68hc11_is_far_symbol (operands[0]))
- {
- if (TARGET_M6812)
- {
- output_asm_insn (\"call\\t%0\", operands);
- return \"\";
- }
- else
- {
- output_asm_insn (\"pshb\", operands);
- output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
- output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
- return \"jsr\\t__call_a32\";
- }
- }
- if (m68hc11_is_trap_symbol (operands[0]))
- return \"swi\";
- else
- return \"bsr\\t%0\";
- }
- else
- {
- return \"jsr\\t%0\";
- }
-}")
-
-(define_insn "call_value"
- [(set (match_operand 0 "" "=g")
- (call (match_operand:QI 1 "memory_operand" "m")
- (match_operand:SI 2 "general_operand" "g")))]
- ""
- "*
-{
- if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
- {
- if (m68hc11_is_far_symbol (operands[1]))
- {
- if (TARGET_M6812)
- {
- output_asm_insn (\"call\\t%1\", operands);
- return \"\";
- }
- else
- {
- output_asm_insn (\"pshb\", operands);
- output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
- output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
- return \"jsr\\t__call_a32\";
- }
- }
- if (m68hc11_is_trap_symbol (operands[1]))
- return \"swi\";
- else
- return \"bsr\\t%1\";
- }
- else
- {
- return \"jsr\\t%1\";
- }
-}")
-
-;; Call subroutine returning any type.
-
-(define_expand "untyped_call"
- [(parallel [(call (match_operand 0 "" "")
- (const_int 0))
- (match_operand 1 "" "")
- (match_operand 2 "" "")])]
- ""
- "
-{
- int i;
-
- emit_call_insn (gen_call (operands[0], const0_rtx));
-
- for (i = 0; i < XVECLEN (operands[2], 0); i++)
- {
- rtx set = XVECEXP (operands[2], 0, i);
- emit_move_insn (SET_DEST (set), SET_SRC (set));
- }
-
- /* The optimizer does not know that the call sets the function value
- registers we stored in the result block. We avoid problems by
- claiming that all hard registers are used and clobbered at this
- point. */
- emit_insn (gen_blockage ());
-
- DONE;
-}")
-
-;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
-;; all of memory. This blocks insns from being moved across this point.
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- "")
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop")
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
-{
- expand_prologue ();
- DONE;
-}")
-
-(define_expand "epilogue"
- [(return)]
- ""
- "
-{
- expand_epilogue ();
- DONE;
-}")
-
-;; Used for frameless functions which save no regs and allocate no locals.
-(define_expand "return"
- [(return)]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "
-{
- int ret_size = 0;
-
- if (crtl->return_rtx)
- ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- /* Emit use notes only when HAVE_return is true. */
- if (m68hc11_total_frame_size () != 0)
- ret_size = 0;
-
- if (ret_size && ret_size <= 2)
- {
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (HImode, 1)))));
- DONE;
- }
- if (ret_size)
- {
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
- gen_rtx_USE (VOIDmode,
- gen_rtx_REG (SImode, 0)))));
- DONE;
- }
-}")
-
-(define_insn "*return_void"
- [(return)]
- "reload_completed"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- {
- int ret_size = 0;
-
- if (crtl->return_rtx)
- ret_size = GET_MODE_SIZE (GET_MODE (crtl->return_rtx));
-
- if (ret_size == 0)
- return \"jmp\\t__return_void\";
- if (ret_size <= 2)
- return \"jmp\\t__return_16\";
- if (ret_size <= 4)
- return \"jmp\\t__return_32\";
- return \"jmp\\t__return_16\";
- }
-}")
-
-(define_insn "*return_16bit"
- [(return)
- (use (reg:HI D_REGNUM))]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- return \"jmp\\t__return_16\";
-}")
-
-(define_insn "*return_32bit"
- [(return)
- (use (reg:SI 0))]
- "reload_completed && m68hc11_total_frame_size () == 0"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- if (current_function_interrupt || current_function_trap)
- return \"rti\";
- else if (!current_function_far)
- return \"rts\";
- else if (TARGET_M6812)
- return \"rtc\";
- else
- return \"jmp\\t__return_32\";
-}")
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
- ""
- "jmp\\t0,%0")
-
-;;--------------------------------------------------------------------
-;;- Table jump
-;;--------------------------------------------------------------------
-;;
-;; Operand 0 is the address of the table element to use
-;; operand 1 is the CODE_LABEL for the table
-;;--------------------------------------------------------------------
-(define_expand "tablejump"
- [(parallel [(set (pc) (match_operand 0 "" ""))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- "")
-
-(define_insn "*jump_indirect"
- [(parallel [
- (set (pc) (match_operand:HI 0 "register_operand" "xy"))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- "jmp\\t0,%0")
-
-;;--------------------------------------------------------------------
-;;- Peepholes
-;;--------------------------------------------------------------------
-
-;;--------------------------------------------------------------------
-;;- 68HC12 dbcc/ibcc peepholes
-;;--------------------------------------------------------------------
-;;
-;; Replace: "addd #-1; bne L1" into "dbne d,L1"
-;; "addd #-1; beq L1" into "dbeq d,L1"
-;; "addd #1; bne L1" into "ibne d,L1"
-;; "addd #1; beq L1" into "ibeq d,L1"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (pc)
- (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
- [(match_dup 0)
- (const_int 0)])
- (label_ref (match_operand 3 "" "")) (pc)))]
- "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
- [(parallel [
- (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
- (label_ref (match_dup 3)) (pc)))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
- (clobber (match_dup 4))])]
- "operands[4] = gen_rtx_SCRATCH(HImode);
- operands[5] = GEN_INT (-INTVAL (operands[1]));")
-
-
-;;
-;; Replace: "addb #-1; bne L1" into "dbne b,L1"
-;; "addb #-1; beq L1" into "dbeq b,L1"
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (plus:QI (match_dup 0)
- (match_operand:QI 1 "const_int_operand" "")))
- (set (pc)
- (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
- [(match_dup 0)
- (const_int 0)])
- (label_ref (match_operand 3 "" "")) (pc)))]
- "TARGET_M6812 && D_REG_P (operands[0])
- && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
- [(parallel [
- (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
- (label_ref (match_dup 3)) (pc)))
- (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
- (clobber (match_dup 4))])]
- "operands[4] = gen_rtx_SCRATCH(QImode);
- operands[5] = GEN_INT (-INTVAL (operands[1]));")
-
-
-;;--------------------------------------------------------------------
-;;- Move peephole2
-;;--------------------------------------------------------------------
-
-;;
-;; Replace "leas 2,sp" with a "pulx" or a "puly".
-;; On 68HC12, this is one cycle slower but one byte smaller.
-;; pr target/6899: This peephole was not valid because a register CSE
-;; pass removes the pulx/puly. The 'use' clause ensure that the pulx is
-;; not removed.
-;;
-(define_peephole2
- [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
- (match_scratch:HI 0 "xy")]
- "TARGET_M6812 && optimize_size"
- [(set (match_dup 0) (match_dup 1))
- (use (match_dup 0))]
- "operands[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode,
- gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
-
-;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
-;;
-;; PR 14542: emit a use to pretend we need the value of initial register.
-;; Otherwise verify_local_live_at_start will die due to a live change
-;; of that register.
-;;
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (match_dup 0)
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (mem:HI (reg:HI SP_REGNUM))
- (match_dup 0))]
- "TARGET_M6812"
- [(use (match_dup 0))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_dup 1))
- (set (match_dup 0) (match_dup 1))]
- "")
-
-;;
-;; Change: "ldd 0,sp; pulx" into "puld"
-;; This sequence usually appears at end a functions.
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (mem:HI (reg:HI SP_REGNUM)))
- (use (match_dup 0))
- (set (match_operand:HI 1 "hard_reg_operand" "")
- (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
- "peep2_reg_dead_p (2, operands[1])"
- [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
- (use (match_dup 0))]
- "")
-
-;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
-;; Appears to allocate local variables.
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
- (const_int 0))
- (set (mem:QI (reg:HI SP_REGNUM))
- (const_int 0))]
- "TARGET_M6812"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (const_int 0))]
- "")
-
-;; Likewise for HI mode
-(define_peephole2
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_operand:HI 0 "hard_reg_operand" ""))
- (set (mem:HI (reg:HI SP_REGNUM))
- (const_int 0))]
- "TARGET_M6812"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (const_int 0))]
- "")
-;;--------------------------------------------------------------------
-;;-
-;;--------------------------------------------------------------------
-;;
-;; Optimize memory<->memory moves when the value is also loaded in
-;; a register.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "memory_operand" "")
- (match_operand:QI 1 "memory_operand" ""))
- (set (reg:QI D_REGNUM)
- (match_operand:QI 2 "memory_operand" ""))]
- "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
- || (GET_CODE (XEXP (operands[0], 0)) == REG
- && GET_CODE (XEXP (operands[2], 0)) == POST_INC
- && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
- [(set (reg:QI D_REGNUM) (match_dup 1))
- (set (match_dup 2) (reg:QI D_REGNUM))]
- "")
-
-;;
-;; Remove a possible move before a compare instruction when that
-;; move will go in a dead register. Compare with the source then.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (cc0)
- (compare (match_dup 0)
- (match_operand:HI 2 "cmp_operand" "")))]
- "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
- && peep2_reg_dead_p (2, operands[0])
- && !reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
- "")
-
-;;
-;; Optimize loading a constant to memory when that same constant
-;; is loaded to a hard register. Switch the two to use the register
-;; for memory initialization. In most cases, the constant is 0.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "immediate_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (match_dup 1))]
- "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
- && !reg_mentioned_p (operands[2], operands[0])"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (match_dup 2))]
- "")
-
-;;
-;; Reorganize to optimize address computations.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))
- (match_scratch:QI 3 "d")]
- "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
- [(set (match_dup 3) (match_dup 4))
- (set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
- "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
-
-;;
-;; Replace: "ldx #N; xgdx; addd <var>; xgdx" by "ldab #N; ldx <var>; abx"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "TARGET_M6812"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Optimize an address register increment and a compare to use
-;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
-;; before reload, but can be enabled after).
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "memory_operand" "")
- (const_int 0)))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0)
- (compare (match_dup 3)
- (const_int 0)))]
- "if (INTVAL (operands[1]) == 1)
- operands[3] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[3] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-;;
-;; Likewise for compare.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "hard_reg_operand" "")
- (match_operand:QI 3 "memory_operand" "")))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[3])"
- [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
- "if (INTVAL (operands[1]) == 1)
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (plus:HI (match_dup 0)
- (match_operand:HI 1 "const_int_operand" "")))
- (set (cc0)
- (compare (match_operand:QI 2 "memory_operand" "")
- (match_operand:QI 3 "hard_reg_operand" "")))]
- "TARGET_AUTO_INC_DEC
- && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
- && reg_mentioned_p (operands[0], operands[2])"
- [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
- "if (INTVAL (operands[1]) == 1)
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_INC (HImode, operands[0]));
- else
- operands[4] = gen_rtx_MEM (QImode,
- gen_rtx_PRE_DEC (HImode, operands[0]));
- ")
-
-;;
-;; Replace a "ldx #N; addx <sp>" with a "ldx <sp>; addx #n"
-;; (avoids many temporary moves because we can't add sp to another reg easily)
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
- ""
- [(set (match_dup 0) (reg:HI SP_REGNUM))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "const_int_operand" ""))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (match_operand:HI 2 "general_operand" "")))]
- "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
- [(set (match_dup 0) (match_dup 2))
- (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
- "")
-
-;;
-;;
-;;
-(define_peephole2
- [(parallel
- [(set (match_operand:SI 0 "hard_reg_operand" "")
- (ashift:SI (match_operand:SI 1 "general_operand" "")
- (const_int 1)))
- (clobber (match_scratch:HI 2 ""))])
- (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
- (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
- "!X_REG_P (operands[1])
- && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
- && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
- [(set (reg:HI D_REGNUM) (match_dup 5))
- (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
- (set (match_dup 3) (reg:HI D_REGNUM))
- (set (reg:HI D_REGNUM) (match_dup 6))
- (parallel [(set (reg:HI D_REGNUM)
- (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
- (clobber (reg:HI CC_REGNUM))])
- (set (match_dup 4) (reg:HI D_REGNUM))]
- "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
- operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
-
-;;
-;; Replace a "ldd <mem>; psha; pshb" with a "ldx <mem>; pshx".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
- (match_dup 0))
- (match_scratch:HI 2 "x")]
- "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
- [(set (match_dup 2) (match_dup 1))
- (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
- "")
-
-;;
-;; Remove one load when copying a value to/from memory and also
-;; to a register. Take care not clobbering a possible register used
-;; by operand 2.
-;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "general_operand" ""))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
- (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
- "peep2_reg_dead_p (2, operands[0])
- && !side_effects_p (operands[1])
- && !side_effects_p (operands[2])
- && !reg_mentioned_p (operands[3], operands[2])"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 2) (match_dup 3))]
- "")
-
-;;
-;; Replace a "ldd <mem>; addd #N; std <mem>" into a
-;; "ldx <mem>; leax; stx <mem>" if we have a free X/Y register
-;; and the constant is small.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "general_operand" ""))
- (set (match_dup 0) (plus:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_operand:HI 3 "nonimmediate_operand" "")
- (match_dup 0))
- (match_scratch:HI 4 "xy")]
- "D_REG_P (operands[0])
- && (TARGET_M6812
- || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 4) (match_dup 1))
- (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
- (set (match_dup 3) (match_dup 4))]
- "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
- if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
-
-;;--------------------------------------------------------------------
-;;- Bset peephole2
-;;--------------------------------------------------------------------
-;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
-;;
-;; Replace 'ldab <mem>; orab #N; stab <mem>' by 'bset <mem> #N'.
-;; Register D must be dead and there must be no register side effects for mem.
-;; The <mem> *can* be volatile this is why we must not use 'side_effects_p'.
-;; The good side effect is that it makes the sequence atomic.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (ior:QI (match_dup 0)
- (match_operand:QI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (ior:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
- "")
-
-;;--------------------------------------------------------------------
-;;- Bclr peephole2
-;;--------------------------------------------------------------------
-;; Replace 'ldab <mem>; andab #N; stab <mem>' by 'bclr <mem> #N'.
-;; See Bset peephole2.
-;;
-(define_peephole2
- [(set (match_operand:QI 0 "hard_reg_operand" "")
- (match_operand:QI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (and:QI (match_dup 0)
- (match_operand:QI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "nonimmediate_operand" ""))
- (set (match_dup 0) (and:HI (match_dup 0)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (match_dup 1) (match_dup 0))]
- "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
- && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
- && peep2_reg_dead_p (3, operands[0])"
- [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
- "")
-
-
-;;--------------------------------------------------------------------
-;;- Compare peephole2
-;;--------------------------------------------------------------------
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (match_dup 1) (plus:HI (match_dup 1)
- (match_operand:HI 2 "const_int_operand" "")))
- (set (cc0) (compare (match_dup 0)
- (const_int 0)))]
- "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
- [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
- (set (cc0) (compare (match_dup 1) (match_dup 2)))]
- "")
-
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "hard_reg_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (plus:HI (match_dup 2)
- (match_operand:HI 3 "const_int_operand" "")))
- (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
- (set (cc0) (compare (match_operand:HI 5 "hard_reg_operand" "")
- (const_int 0)))]
- "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
- && !reg_mentioned_p (operands[2], operands[4])
-
- && ((rtx_equal_p (operands[5], operands[0])
- && rtx_equal_p (operands[2], operands[1]))
-
- || (rtx_equal_p (operands[5], operands[1])
- && rtx_equal_p (operands[2], operands[0])))"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
- (set (match_dup 4) (match_dup 2))
- (set (cc0) (compare (match_dup 2) (match_dup 3)))]
- "")
-
-
-;;--------------------------------------------------------------------
-;;- Load peephole2
-;;--------------------------------------------------------------------
-;;
-;; Optimize initialization of 2 hard regs from the same memory location
-;; Since we can't copy easily X, Y and D to each other, load the 2 registers
-;; from the same memory location.
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
- "TARGET_M6811
- && !side_effects_p (operands[1])
- && !reg_mentioned_p (operands[0], operands[1])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (match_dup 1))]
- "")
-
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
- (match_scratch:HI 4 "d")]
- ""
- [(set (match_dup 4) (const_int 0))
- (set (match_dup 0) (match_dup 4))
- (set (match_dup 1) (match_dup 4))
- (set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 4))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
- (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
- (match_scratch:HI 3 "d")]
- ""
- [(set (match_dup 3) (const_int 0))
- (set (match_dup 0) (match_dup 3))
- (set (match_dup 1) (match_dup 3))
- (set (match_dup 2) (match_dup 3))]
- "")
-
-;;
-;; Replace "ldd #N; addd <op>" with "ldd <op>; addd #N".
-;;
-(define_peephole2
- [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
- (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
- (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
- (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
- (match_scratch:HI 4 "x")]
- "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
- [(set (match_dup 4) (const_int 0))
- (set (match_dup 1) (match_dup 4))
- (set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 4))]
- "")
-
-;;
-;; This peephole catches the address computations generated by the reload
-;; pass.
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "xy")
- (match_operand:HI 1 "const_int_operand" ""))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM)
- (plus (reg:HI D_REGNUM)
- (match_operand:HI 2 "general_operand" "")))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "(INTVAL (operands[1]) & 0x0FF) == 0"
- "*
-{
- int value_loaded = 1;
-
- if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- output_asm_insn (\"xgd%0\", operands);
- }
- else if (Y_REG_P (operands[0]))
- {
- if (reg_mentioned_p (iy_reg, operands[2]))
- output_asm_insn (\"ldy\\t%2\", operands);
- else
- value_loaded = 0;
- output_asm_insn (\"xgdy\", operands);
- }
- else
- {
- output_asm_insn (\"ldd\\t%2\", operands);
- }
-
- if (value_loaded == 0)
- output_asm_insn (\"ldd\\t%2\", operands);
- if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
- output_asm_insn (\"inca\", operands);
- else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
- output_asm_insn (\"deca\", operands);
- else if (INTVAL (operands[1]) != 0)
- output_asm_insn (\"adda\\t%h1\", operands);
-
- if (X_REG_P (operands[0]))
- return \"xgdx\";
- else if (Y_REG_P (operands[0]))
- return \"xgdy\";
- else
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "h")
- (match_operand:HI 1 "non_push_operand" "g"))
- (set (match_operand:HI 2 "hard_reg_operand" "h")
- (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
- && !S_REG_P (operands[2])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "h")
- (match_operand:HI 1 "hard_reg_operand" "h"))
- (set (match_operand:HI 2 "non_push_operand" "g")
- (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
- && !S_REG_P (operands[2])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;
-;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
-;; the set, so we don't need to emit anything. 'ins1' refers to the
-;; (set ...) insn.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;; Same as above but due to some split, there may be a noop set
-;; between the two.
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (set (match_dup 0) (match_dup 0))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;
-;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
-;; and we must, at least, setup X/Y with value of D.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_dup 0))]
- "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
- "REGNO (operands[0]) == REGNO (operands[1])
- && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-;;;
-;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
-;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:HI D_REGNUM) (match_dup 0))]
- ""
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Same peephole with a QI set. The copy is made as 16-bit to comply
-;;; with the xgdx.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
- "REGNO (operands[0]) == REGNO (operands[1])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;;
-;;; Catch two consecutive xgdx or xgdy, emit nothing.
-;;;
-(define_peephole
- [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
- (set (match_dup 0) (reg:HI D_REGNUM))])
- (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
- (set (match_dup 0) (reg:HI D_REGNUM))])]
- ""
- "*
-{
- cc_status = cc_prev_status;
- return \"\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "stack_register_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "")
- (match_operand:HI 3 "memory_operand" "m"))
- (set (match_dup 0)
- (match_operand:HI 4 "memory_operand" "m"))]
- "IS_STACK_POP (operands[4])
- && (GET_CODE (operands[3]) == MEM &&
- rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[2];
- ops[1] = gen_rtx_MEM (HImode,
- gen_rtx_POST_INC (HImode, stack_pointer_rtx));
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}
-")
-
-;;
-;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
-;;
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
- (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
- "TARGET_M6811"
- "*
-{
- return \"sts\\t%t0\\n\\tld%0\\t%t0\";
-}
-")
-
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "")
- (match_operand:HI 1 "memory_operand" ""))
- (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
- "TARGET_M6811
- && !side_effects_p (operands[1])
- && !reg_mentioned_p (operands[0], operands[1])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- ops[0] = operands[2];
- m68hc11_gen_movhi (insn, ops);
- return \"\";
-}")
-
-;; Peephole for Z register replacement.
-;; Avoid to use _.tmp register when comparing D and X if we can compare
-;; with soft register
-(define_peephole
- [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
- (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
- (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
- (reg:HI SOFT_TMP_REGNUM)))]
- "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
- "*
-{
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = operands[1];
- m68hc11_gen_movhi (insn, ops);
- return \"cp%2\\t%1\";
-}")
diff --git a/gcc/config/m68hc11/m68hc11.opt b/gcc/config/m68hc11/m68hc11.opt
deleted file mode 100644
index f0f29f2a7a1..00000000000
--- a/gcc/config/m68hc11/m68hc11.opt
+++ /dev/null
@@ -1,94 +0,0 @@
-; Options for the Motorola 68HC11 and 68HC12 port of the compiler.
-
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-m6811
-Target RejectNegative InverseMask(M6812, M6811)
-Compile for a 68HC11
-
-m6812
-Target RejectNegative Mask(M6812)
-Compile for a 68HC12
-
-m68hc11
-Target RejectNegative InverseMask(M6812)
-Compile for a 68HC11
-
-m68hc12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HC12
-
-; At the moment, there is no difference between the code generated
-; for -m68hc12 and -m68hcs12.
-m68hcs12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HCS12
-
-m68s12
-Target RejectNegative Mask(M6812) MaskExists
-Compile for a 68HCS12
-
-mauto-incdec
-Target RejectNegative Report Mask(AUTO_INC_DEC)
-Auto pre/post decrement increment allowed
-
-minmax
-Target RejectNegative Report Mask(MIN_MAX)
-Min/max instructions allowed
-
-mlong-calls
-Target RejectNegative Report Mask(LONG_CALLS)
-Use call and rtc for function calls and returns
-
-mnoauto-incdec
-Target RejectNegative Report InverseMask(AUTO_INC_DEC)
-Auto pre/post decrement increment not allowed
-
-mnolong-calls
-Target RejectNegative Report InverseMask(LONG_CALLS)
-Use jsr and rts for function calls and returns
-
-mnominmax
-Target RejectNegative Report InverseMask(MIN_MAX)
-Min/max instructions not allowed
-
-mnorelax
-Target RejectNegative Report InverseMask(NO_DIRECT_MODE)
-Use direct addressing mode for soft registers
-
-mnoshort
-Target RejectNegative Report InverseMask(SHORT)
-Compile with 32-bit integer mode
-
-; Currently ignored.
-mreg-alloc=
-Target RejectNegative Joined
-Specify the register allocation order
-
-mrelax
-Target RejectNegative Report Mask(NO_DIRECT_MODE)
-Do not use direct addressing mode for soft registers
-
-mshort
-Target RejectNegative Report Mask(SHORT)
-Compile with 16-bit integer mode
-
-msoft-reg-count=
-Target RejectNegative Joined UInteger Var(m68hc11_soft_reg_count) Init(-1)
-Indicate the number of soft registers available
diff --git a/gcc/config/m68hc11/m68hc12.h b/gcc/config/m68hc11/m68hc12.h
deleted file mode 100644
index 22bdc008c57..00000000000
--- a/gcc/config/m68hc11/m68hc12.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Definitions of target machine for GNU compiler, for m68hc12.
- Copyright (C) 1999, 2000, 2001, 2003, 2007 Free Software Foundation, Inc.
- Contributed by Stephane Carrez (stcarrez@nerim.fr).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Compile and assemble for a 68hc12 unless there is a -m68hc11 option. */
-#define ASM_SPEC \
-"%{m68hc11:-m68hc11}" \
-"%{m68hcs12:-m68hcs12}" \
-"%{!m68hc11:%{!m68hcs12:-m68hc12}}"
-#define LIB_SPEC ""
-#define CC1_SPEC ""
-
-/* We need to tell the linker the target elf format. Just pass an
- emulation option. This can be overridden by -Wl option of gcc. */
-#define LINK_SPEC \
-"%{m68hc11:-m m68hc11elf}" \
-"%{m68hcs12:-m m68hc12elf}" \
-"%{!m68hc11:%{!m68hcs12:-m m68hc11elf}} %{mrelax:-relax}"
-
-#define CPP_SPEC \
-"%{mshort:-D__HAVE_SHORT_INT__ -D__INT__=16}\
- %{!mshort:-D__INT__=32}\
- %{m68hc11:-Dmc6811 -DMC6811 -Dmc68hc11}\
- %{!m68hc11:%{!m68hc12:-Dmc6812 -DMC6812 -Dmc68hc12}}\
- %{m68hcs12:-Dmc6812 -DMC6812 -Dmc68hcs12}\
- %{fshort-double:-D__HAVE_SHORT_DOUBLE__}"
-
-/* Default target_flags if no switches specified. */
-#define TARGET_DEFAULT (MASK_M6812)
diff --git a/gcc/config/m68hc11/predicates.md b/gcc/config/m68hc11/predicates.md
deleted file mode 100644
index 77a524a0e1e..00000000000
--- a/gcc/config/m68hc11/predicates.md
+++ /dev/null
@@ -1,228 +0,0 @@
-;; Predicate definitions for Motorola 68HC11 and 68HC12.
-;; Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; TODO: Add a comment here.
-
-(define_predicate "stack_register_operand"
- (match_code "subreg,reg")
-{
- return SP_REG_P (op);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "d_register_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO (op) == HARD_D_REGNUM
- || (mode == QImode && REGNO (op) == HARD_B_REGNUM));
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "hard_addr_reg_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) == HARD_X_REGNUM
- || REGNO (op) == HARD_Y_REGNUM
- || REGNO (op) == HARD_Z_REGNUM);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "hard_reg_operand"
- (match_code "subreg,reg")
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = XEXP (op, 0);
-
- return GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || H_REGNO_P (REGNO (op)));
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_logical_operator"
- (match_code "and,ior,xor")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_arith_operator"
- (match_code "and,ior,xor,plus,minus,ashift,ashiftrt,lshiftrt,rotate,rotatert")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
- || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS
- || GET_CODE (op) == ASHIFT || GET_CODE (op) == ASHIFTRT
- || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ROTATE
- || GET_CODE (op) == ROTATERT;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_non_shift_operator"
- (match_code "and,ior,xor,plus,minus")
-{
- return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR
- || GET_CODE (op) == PLUS || GET_CODE (op) == MINUS;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_unary_operator"
- (match_code "neg,not,sign_extend,zero_extend")
-{
- return GET_CODE (op) == NEG || GET_CODE (op) == NOT
- || GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
-})
-
-;; Return true if op is a shift operator.
-
-(define_predicate "m68hc11_shift_operator"
- (match_code "ashift,ashiftrt,lshiftrt,rotate,rotatert")
-{
- return GET_CODE (op) == ROTATE || GET_CODE (op) == ROTATERT
- || GET_CODE (op) == LSHIFTRT || GET_CODE (op) == ASHIFT
- || GET_CODE (op) == ASHIFTRT;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "m68hc11_eq_compare_operator"
- (match_code "eq,ne")
-{
- return GET_CODE (op) == EQ || GET_CODE (op) == NE;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "non_push_operand"
- (match_code "subreg,reg,mem")
-{
- if (general_operand (op, mode) == 0)
- return 0;
-
- if (push_operand (op, mode) == 1)
- return 0;
- return 1;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "splitable_operand"
- (match_code "subreg,reg,mem,symbol_ref,label_ref,const_int,const_double")
-{
- if (general_operand (op, mode) == 0)
- return 0;
-
- if (push_operand (op, mode) == 1)
- return 0;
-
- /* Reject a (MEM (MEM X)) because the patterns that use non_push_operand
- need to split such addresses to access the low and high part but it
- is not possible to express a valid address for the low part. */
- if (mode != QImode && GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == MEM)
- return 0;
- return 1;
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "reg_or_some_mem_operand"
- (match_code "subreg,reg,mem")
-{
- if (GET_CODE (op) == MEM)
- {
- rtx op0 = XEXP (op, 0);
- int addr_mode;
-
- if (symbolic_memory_operand (op0, mode))
- return 1;
-
- if (IS_STACK_PUSH (op))
- return 1;
-
- if (GET_CODE (op) == REG && reload_in_progress
- && REGNO (op) >= FIRST_PSEUDO_REGISTER
- && reg_equiv_memory_loc[REGNO (op)])
- {
- op = reg_equiv_memory_loc[REGNO (op)];
- op = eliminate_regs (op, VOIDmode, NULL_RTX);
- }
- if (GET_CODE (op) != MEM)
- return 0;
-
- op0 = XEXP (op, 0);
- addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
- addr_mode &= ~ADDR_INDIRECT;
- return m68hc11_valid_addressing_p (op0, mode, addr_mode);
- }
-
- return register_operand (op, mode);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "tst_operand"
- (match_code "subreg,reg,mem")
-{
- if (GET_CODE (op) == MEM && reload_completed == 0)
- {
- rtx addr = XEXP (op, 0);
- if (m68hc11_auto_inc_p (addr))
- return 0;
- }
- return nonimmediate_operand (op, mode);
-})
-
-;; TODO: Add a comment here.
-
-(define_predicate "cmp_operand"
- (match_code "subreg,reg,mem,symbol_ref,label_ref,const_int,const_double")
-{
- if (GET_CODE (op) == MEM)
- {
- rtx addr = XEXP (op, 0);
- if (m68hc11_auto_inc_p (addr))
- return 0;
- }
- return general_operand (op, mode);
-})
diff --git a/gcc/config/m68hc11/t-m68hc11 b/gcc/config/m68hc11/t-m68hc11
deleted file mode 100644
index 5a8e6ade476..00000000000
--- a/gcc/config/m68hc11/t-m68hc11
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright (C) 2000, 2001, 2002, 2003, 2005,
-# 2008 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-RANLIB_FOR_TARGET = ` \
- if [ -f $(objdir)/../binutils/ranlib ] ; then \
- echo $(objdir)/../binutils/ranlib ; \
- else \
- if [ "$(host)" = "$(target)" ] ; then \
- echo ranlib; \
- else \
- if [ -f $(bindir)/$(target_noncanonical)-ranlib ] ; then \
- echo $(bindir)/$(target_noncanonical)-ranlib ; \
- else \
- t='$(program_transform_cross_name)'; echo ranlib | sed -e $$t ; \
- fi; \
- fi; \
- fi`
-
-LIB1ASMSRC = m68hc11/larith.asm
-LIB1ASMFUNCS = _mulsi3 \
- _mulqi3 _ashlsi3 _ashrsi3 _lshrsi3 \
- _divmodhi4 _mulhi3 _mulhi32 \
- _memcpy _memset _negsi2 _one_cmplsi2 \
- _regs_min _regs_frame _regs_d1_2 \
- _regs_d3_4 _regs_d5_6 _regs_d7_8 _regs_d9_16 _regs_d17_32 \
- _premain __exit _abort _cleanup \
- _adddi3 _subdi3 _notdi2 _rotlhi3 _rotrhi3 \
- _ashrhi3 _lshrhi3 _lshlhi3 _ashrqi3 _lshlqi3 _map_data _init_bss \
- _ctor _dtor _far_tramp _call_far _return_far
-
-TARGET_LIBGCC2_CFLAGS = -DUSE_GAS -DIN_GCC -Dinhibit_libc
-
-# C implementation of 32-bit div/mod.
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmodsi4.c \
- $(srcdir)/config/divmod.c $(srcdir)/config/udivmod.c
-
-# Don't compile with -g1 this reduces the size of some sections (.eh_frame).
-LIBGCC2_DEBUG_CFLAGS =-g
-LIBGCC2_CFLAGS = -Os -mrelax $(LIBGCC2_INCLUDES) $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) $(GTHREAD_FLAGS) -DIN_LIBGCC2
-
-MULTILIB_OPTIONS = m68hc11/m68hc12 mshort fshort-double
-MULTILIB_DIRNAMES =
-MULTILIB_MATCHES = m68hc11=m6811 m68hc12=m6812 m68hc12=m68hcs12
-MULTILIB_EXCEPTIONS = -mnoshort -mno68hc11
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define SMALL_MACHINE' >> dp-bit.c
- echo '#define CMPtype HItype' >> dp-bit.c
- echo '#ifdef __LITTLE_ENDIAN__' >> dp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >>dp-bit.c
- echo '#endif' >> dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- echo '#define CMPtype HItype' >> fp-bit.c
- echo '#define SMALL_MACHINE' >> fp-bit.c
- echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c
- echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
- echo '#endif' >> fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-CRT0_S = $(srcdir)/config/m68hc11/m68hc11-crt0.S
-MCRT0_S= $(srcdir)/config/m68hc11/m68hc11-crt0.S
-
-CRT0STUFF_T_CFLAGS =
-
-# Assemble startup files.
-$(T)crt1.o: $(CRT0_S) $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(CRT0_S)
-
-EXTRA_MULTILIB_PARTS = crt1.o
diff --git a/gcc/config/m68k/uclinux-oldabi.h b/gcc/config/m68k/uclinux-oldabi.h
deleted file mode 100644
index 7ef202efbac..00000000000
--- a/gcc/config/m68k/uclinux-oldabi.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Definitions of target machine for GCC. m68k/ColdFire based uClinux system
- using ELF objects with special linker post-processing to produce FLAT
- executables.
-
- Copyright (C) 2003, 2007 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-/* The old uClinux ABI used 80-byte "long double"s for ColdFire too. */
-#undef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 80
-#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
-
-/* Undo the definition of STARTFILE_SPEC from m68kelf.h so we'll
- pick the default from gcc.c (just link crt0.o from multilib dir). */
-#undef STARTFILE_SPEC
-
-/* Override the default LIB_SPEC from gcc.c. We don't currently support
- profiling, or libg.a. */
-#undef LIB_SPEC
-#define LIB_SPEC "\
-%{mid-shared-library:-R libc.gdb%s -elf2flt -shared-lib-id 0} -lc \
-"
-
-/* we don't want a .eh_frame section. */
-#define EH_FRAME_IN_DATA_SECTION
-
-/* ??? Quick hack to get constructors working. Make this look more like a
- COFF target, so the existing dejagnu/libgloss support works. A better
- solution would be to make the necessary dejagnu and libgloss changes so
- that we can use normal the ELF constructor mechanism. */
-#undef INIT_SECTION_ASM_OP
-#undef FINI_SECTION_ASM_OP
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
-
-/* Bring in standard linux defines */
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("mc68000"); \
- builtin_define ("__uClinux__"); \
- builtin_define_std ("linux"); \
- builtin_define_std ("unix"); \
- builtin_define ("__gnu_linux__"); \
- builtin_assert ("system=linux"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=posix"); \
- if (TARGET_ID_SHARED_LIBRARY) \
- builtin_define ("__ID_SHARED_LIBRARY__"); \
- } \
- while (0)
-
diff --git a/gcc/config/mcore/mcore-pe.h b/gcc/config/mcore/mcore-pe.h
deleted file mode 100644
index ccd34e9c70d..00000000000
--- a/gcc/config/mcore/mcore-pe.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Definitions of target machine for GNU compiler, for MCore using COFF/PE.
- Copyright (C) 1994, 1999, 2000, 2002, 2003, 2004, 2007
- Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@cygnus.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Run-time Target Specification. */
-#define TARGET_VERSION fputs (" (MCORE/pe)", stderr)
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__pe__"); \
- } \
- while (0)
-
-/* The MCore ABI says that bitfields are unsigned by default. */
-/* The EPOC C++ environment does not support exceptions. */
-#undef CC1_SPEC
-#define CC1_SPEC "-funsigned-bitfields %{!DIN_GCC:-fno-rtti} %{!DIN_GCC:-fno-exceptions}"
-
-#undef SDB_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO 1
-
-/* Computed in toplev.c. */
-#undef PREFERRED_DEBUGGING_TYPE
-
-#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
-
-#define MCORE_EXPORT_NAME(STREAM, NAME) \
- do \
- { \
- fprintf (STREAM, "\t.section .drectve\n"); \
- fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
- (* targetm.strip_name_encoding) (NAME)); \
- in_section = NULL; \
- } \
- while (0);
-
-/* Output the label for an initialized variable. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (mcore_dllexport_name_p (NAME)) \
- { \
- section *save_section = in_section; \
- MCORE_EXPORT_NAME (STREAM, NAME); \
- switch_to_section (save_section); \
- } \
- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
- } \
- while (0)
-
-/* Output a function label definition. */
-#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
- do \
- { \
- if (mcore_dllexport_name_p (NAME)) \
- { \
- MCORE_EXPORT_NAME (STREAM, NAME); \
- switch_to_section (function_section (DECL)); \
- } \
- ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
- } \
- while (0);
-
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-#define DBX_LINES_FUNCTION_RELATIVE 1
-
-#define STARTFILE_SPEC "crt0.o%s"
-#define ENDFILE_SPEC "%{!mno-lsim:-lsim}"
-
-/* __CTOR_LIST__ and __DTOR_LIST__ must be defined by the linker script. */
-#define CTOR_LISTS_DEFINED_EXTERNALLY
-
-#undef DO_GLOBAL_CTORS_BODY
-#undef DO_GLOBAL_DTORS_BODY
-#undef INIT_SECTION_ASM_OP
-#undef DTORS_SECTION_ASM_OP
-
-#define SUPPORTS_ONE_ONLY 1
-
-/* Switch into a generic section. */
-#undef TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION default_pe_asm_named_section
diff --git a/gcc/config/mcore/t-mcore-pe b/gcc/config/mcore/t-mcore-pe
deleted file mode 100644
index 37ad3b6f947..00000000000
--- a/gcc/config/mcore/t-mcore-pe
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2000, 2001, 2002, 2008 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = mcore/lib1.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/mcore/t-mcore
- rm -f dp-bit.c
- echo '' > dp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c $(srcdir)/config/mcore/t-mcore
- rm -f fp-bit.c
- echo '' > fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-# could use -msifilter to be safe from interrupt/jmp interactions and others.
-TARGET_LIBGCC2_CFLAGS=-O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
-
-# We have values for float.h.
-CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
-
-MULTILIB_OPTIONS = mbig-endian/mlittle-endian m210/m340
-MULTILIB_DIRNAMES = big little m210 m340
-MULTILIB_MATCHES =
-MULTILIB_EXTRA_OPTS =
-MULTILIB_EXCEPTIONS =
-
-# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# If EXTRA_MULTILIB_PARTS is not defined above then define EXTRA_PARTS here
-# EXTRA_PARTS = crtbegin.o crtend.o
-
diff --git a/gcc/config/netbsd-aout.h b/gcc/config/netbsd-aout.h
deleted file mode 100644
index 7306c156e68..00000000000
--- a/gcc/config/netbsd-aout.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Common configuration file for NetBSD a.out targets.
- Copyright (C) 2002, 2007, 2010 Free Software Foundation, Inc.
- Contributed by Wasabi Systems, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* TARGET_OS_CPP_BUILTINS() common to all NetBSD a.out targets. */
-#define NETBSD_OS_CPP_BUILTINS_AOUT() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_COMMON(); \
- } \
- while (0)
-
-
-/* Provide an ASM_SPEC appropriate for NetBSD. Currently we only deal
- with the options for generating PIC code. */
-
-#undef ASM_SPEC
-#define ASM_SPEC "%{fpic|fpie:-k} %{fPIC|fPIE:-k -K}"
-
-#define AS_NEEDS_DASH_FOR_PIPED_INPUT
-
-
-/* Provide a STARTFILE_SPEC appropriate for NetBSD a.out. Here we
- provide support for the special GCC option -static. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt0%O%s} \
- %{!pg: \
- %{p:mcrt0%O%s} \
- %{!p: \
- %{!static:crt0%O%s} \
- %{static:scrt0%O%s}}}}"
-
-/* Provide a LINK_SPEC appropriate for NetBSD a.out. Here we provide
- support for the special GCC options -static, -assert, and -nostdlib. */
-
-#undef NETBSD_LINK_SPEC_AOUT
-#define NETBSD_LINK_SPEC_AOUT \
- "%{nostdlib:-nostdlib} \
- %{!shared: \
- %{!nostdlib: \
- %{!r: \
- %{!e*:-e start}}} \
- -dc -dp \
- %{static:-Bstatic}} \
- %{shared:-Bshareable} \
- %{R*} \
- %{assert*}"
-
-/* Default LINK_SPEC. */
-#undef LINK_SPEC
-#define LINK_SPEC NETBSD_LINK_SPEC_AOUT
-
-/* Define the strings used for the .type, .size, and .set directives.
- These strings generally do not vary from one system running NetBSD
- to another, but if a given system needs to use different pseudo-op
- names for these, they may be overridden in the file included after
- this one. */
-
-#undef TYPE_ASM_OP
-#undef SIZE_ASM_OP
-#undef SET_ASM_OP
-#define TYPE_ASM_OP "\t.type\t"
-#define SIZE_ASM_OP "\t.size\t"
-#define SET_ASM_OP "\t.set\t"
-
-
-/* This is how we tell the assembler that a symbol is weak. */
-
-#undef ASM_WEAKEN_LABEL
-#define ASM_WEAKEN_LABEL(FILE,NAME) \
- do \
- { \
- fputs ("\t.globl\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
- fputc ('\n', FILE); \
- } \
- while (0)
-
-
-/* The following macro defines the format used to output the second
- operand of the .type assembler directive. Different svr4 assemblers
- expect various different forms of this operand. The one given here
- is just a default. You may need to override it in your machine-
- specific tm.h file (depending on the particulars of your assembler). */
-
-#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "@%s"
-
-
-/* Write the extra assembler code needed to declare a function's result.
- Most svr4 assemblers don't require any special declaration of the
- result value, but there are exceptions. */
-
-#ifndef ASM_DECLARE_RESULT
-#define ASM_DECLARE_RESULT(FILE, RESULT)
-#endif
-
-
-/* These macros generate the special .type and .size directives which
- are used to set the corresponding fields of the linker symbol table
- entries in an ELF object file under SVR4 (and a.out on NetBSD).
- These macros also output the starting labels for the relevant
- functions/objects. */
-
-/* Write the extra assembler code needed to declare a function properly.
- Some svr4 assemblers need to also have something extra said about the
- function's return value. We allow for that here. */
-
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL); \
- } \
- while (0)
-
-
-/* Write the extra assembler code needed to declare an object properly. */
-
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- HOST_WIDE_INT size; \
- \
- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
- \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive \
- && (DECL) && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
- } \
- \
- ASM_OUTPUT_LABEL (FILE, NAME); \
- } \
- while (0)
-
-/* Output the size directive for a decl in rest_of_decl_compilation
- in the case where we did not do so before the initializer.
- Once we find the error_mark_node, we know that the value of
- size_directive_output was set
- by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
-
-#undef ASM_FINISH_DECLARE_OBJECT
-#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
- do \
- { \
- const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
- HOST_WIDE_INT size; \
- if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
- && ! AT_END && TOP_LEVEL \
- && DECL_INITIAL (DECL) == error_mark_node \
- && !size_directive_output) \
- { \
- size_directive_output = 1; \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
- } \
- } \
- while (0)
-
-
-/* This is how to declare the size of a function. */
-
-#undef ASM_DECLARE_FUNCTION_SIZE
-#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- do \
- { \
- if (!flag_inhibit_size_directive) \
- ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
- } \
- while (0)
diff --git a/gcc/config/rs6000/gnu.h b/gcc/config/rs6000/gnu.h
deleted file mode 100644
index 0f329e53f10..00000000000
--- a/gcc/config/rs6000/gnu.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Definitions of target machine for GNU compiler,
- for PowerPC machines running GNU.
- Copyright (C) 2001, 2003, 2007 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#undef CPP_OS_DEFAULT_SPEC
-#define CPP_OS_DEFAULT_SPEC "%(cpp_os_gnu)"
-
-#undef STARTFILE_DEFAULT_SPEC
-#define STARTFILE_DEFAULT_SPEC "%(startfile_gnu)"
-
-#undef ENDFILE_DEFAULT_SPEC
-#define ENDFILE_DEFAULT_SPEC "%(endfile_gnu)"
-
-#undef LINK_START_DEFAULT_SPEC
-#define LINK_START_DEFAULT_SPEC "%(link_start_gnu)"
-
-#undef LINK_OS_DEFAULT_SPEC
-#define LINK_OS_DEFAULT_SPEC "%(link_os_gnu)"
-
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (PowerPC GNU)");
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index e6840d63e80..04913f29df4 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -172,10 +172,6 @@ extern int dot_symbols;
#undef ASM_SPEC
#undef LINK_OS_LINUX_SPEC
-/* FIXME: This will quite possibly choose the wrong dynamic linker. */
-#undef LINK_OS_GNU_SPEC
-#define LINK_OS_GNU_SPEC LINK_OS_LINUX_SPEC
-
#ifndef RS6000_BI_ARCH
#define ASM_DEFAULT_SPEC "-mppc64"
#define ASM_SPEC "%(asm_spec64) %(asm_spec_common)"
@@ -199,7 +195,6 @@ extern int dot_symbols;
%{mcall-freebsd: -mbig} \
%{mcall-i960-old: -mlittle} \
%{mcall-linux: -mbig} \
- %{mcall-gnu: -mbig} \
%{mcall-netbsd: -mbig} \
}}}}"
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index aeb934f6ed5..5ba1253fd2c 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -98,8 +98,6 @@ do { \
else \
rs6000_current_abi = ABI_V4; \
} \
- else if (!strcmp (rs6000_abi_name, "gnu")) \
- rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "netbsd")) \
rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "openbsd")) \
@@ -556,8 +554,7 @@ extern int fixuplabelno;
mcall-freebsd | \
mcall-netbsd | \
mcall-openbsd | \
- mcall-linux | \
- mcall-gnu :-mbig; \
+ mcall-linux :-mbig; \
mcall-i960-old :-mlittle}"
#define CC1_ENDIAN_BIG_SPEC ""
@@ -583,8 +580,7 @@ extern int fixuplabelno;
mcall-freebsd | \
mcall-netbsd | \
mcall-openbsd | \
- mcall-linux | \
- mcall-gnu : -mbig %(cc1_endian_big); \
+ mcall-linux : -mbig %(cc1_endian_big); \
mcall-i960-old : -mlittle %(cc1_endian_little); \
: %(cc1_endian_default)} \
%{meabi: %{!mcall-*: -mcall-sysv }} \
@@ -593,7 +589,6 @@ extern int fixuplabelno;
%{mcall-freebsd: -mno-eabi } \
%{mcall-i960-old: -meabi } \
%{mcall-linux: -mno-eabi } \
- %{mcall-gnu: -mno-eabi } \
%{mcall-netbsd: -mno-eabi } \
%{mcall-openbsd: -mno-eabi }}} \
%{msdata: -msdata=default} \
@@ -609,7 +604,6 @@ extern int fixuplabelno;
msim : %(link_start_sim) ; \
mcall-freebsd: %(link_start_freebsd) ; \
mcall-linux : %(link_start_linux) ; \
- mcall-gnu : %(link_start_gnu) ; \
mcall-netbsd : %(link_start_netbsd) ; \
mcall-openbsd: %(link_start_openbsd) ; \
: %(link_start_default) }"
@@ -647,7 +641,6 @@ extern int fixuplabelno;
msim : %(link_os_sim) ; \
mcall-freebsd: %(link_os_freebsd) ; \
mcall-linux : %(link_os_linux) ; \
- mcall-gnu : %(link_os_gnu) ; \
mcall-netbsd : %(link_os_netbsd) ; \
mcall-openbsd: %(link_os_openbsd) ; \
: %(link_os_default) }"
@@ -666,7 +659,6 @@ extern int fixuplabelno;
msim : %(cpp_os_sim) ; \
mcall-freebsd: %(cpp_os_freebsd) ; \
mcall-linux : %(cpp_os_linux) ; \
- mcall-gnu : %(cpp_os_gnu) ; \
mcall-netbsd : %(cpp_os_netbsd) ; \
mcall-openbsd: %(cpp_os_openbsd) ; \
: %(cpp_os_default) }"
@@ -681,7 +673,6 @@ extern int fixuplabelno;
msim : %(startfile_sim) ; \
mcall-freebsd: %(startfile_freebsd) ; \
mcall-linux : %(startfile_linux) ; \
- mcall-gnu : %(startfile_gnu) ; \
mcall-netbsd : %(startfile_netbsd) ; \
mcall-openbsd: %(startfile_openbsd) ; \
: %(startfile_default) }"
@@ -696,7 +687,6 @@ extern int fixuplabelno;
msim : %(lib_sim) ; \
mcall-freebsd: %(lib_freebsd) ; \
mcall-linux : %(lib_linux) ; \
- mcall-gnu : %(lib_gnu) ; \
mcall-netbsd : %(lib_netbsd) ; \
mcall-openbsd: %(lib_openbsd) ; \
: %(lib_default) }"
@@ -711,7 +701,6 @@ extern int fixuplabelno;
msim : %(endfile_sim) ; \
mcall-freebsd: %(endfile_freebsd) ; \
mcall-linux : %(endfile_linux) ; \
- mcall-gnu : %(endfile_gnu) ; \
mcall-netbsd : %(endfile_netbsd) ; \
mcall-openbsd: %(endfile_openbsd) ; \
: %(crtsavres_default) %(endfile_default) }"
@@ -845,31 +834,6 @@ extern int fixuplabelno;
%{std=gnu*:-Dunix -D__unix -Dlinux -D__linux}}} \
-Asystem=linux -Asystem=unix -Asystem=posix %{pthread:-D_REENTRANT}"
-/* GNU/Hurd support. */
-#define LIB_GNU_SPEC "%{mnewlib: --start-group -lgnu -lc --end-group } \
-%{!mnewlib: %{shared:-lc} %{!shared: %{pthread:-lpthread } \
-%{profile:-lc_p} %{!profile:-lc}}}"
-
-#define STARTFILE_GNU_SPEC "\
-%{!shared: %{!static: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}} \
-%{static: %{pg:gcrt0.o%s} %{!pg:%{p:gcrt0.o%s} %{!p:crt0.o%s}}} \
-%{mnewlib: ecrti.o%s} %{!mnewlib: crti.o%s} \
-%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-
-#define ENDFILE_GNU_SPEC "%{!shared:crtend.o%s} %{shared:crtendS.o%s} \
-%{mnewlib: ecrtn.o%s} %{!mnewlib: crtn.o%s}"
-
-#define LINK_START_GNU_SPEC ""
-
-#define LINK_OS_GNU_SPEC "-m elf32ppclinux %{!shared: %{!static: \
- %{rdynamic:-export-dynamic} \
- -dynamic-linker /lib/ld.so.1}}"
-
-#define CPP_OS_GNU_SPEC "-D__unix__ -D__gnu_hurd__ -D__GNU__ \
-%{!undef: \
- %{!ansi: -Dunix -D__unix}} \
--Asystem=gnu -Asystem=unix -Asystem=posix %{pthread:-D_REENTRANT}"
-
/* NetBSD support. */
#define LIB_NETBSD_SPEC "\
-lc"
@@ -931,7 +895,6 @@ ncrtn.o%s"
{ "lib_mvme", LIB_MVME_SPEC }, \
{ "lib_sim", LIB_SIM_SPEC }, \
{ "lib_freebsd", LIB_FREEBSD_SPEC }, \
- { "lib_gnu", LIB_GNU_SPEC }, \
{ "lib_linux", LIB_LINUX_SPEC }, \
{ "lib_netbsd", LIB_NETBSD_SPEC }, \
{ "lib_openbsd", LIB_OPENBSD_SPEC }, \
@@ -941,7 +904,6 @@ ncrtn.o%s"
{ "startfile_mvme", STARTFILE_MVME_SPEC }, \
{ "startfile_sim", STARTFILE_SIM_SPEC }, \
{ "startfile_freebsd", STARTFILE_FREEBSD_SPEC }, \
- { "startfile_gnu", STARTFILE_GNU_SPEC }, \
{ "startfile_linux", STARTFILE_LINUX_SPEC }, \
{ "startfile_netbsd", STARTFILE_NETBSD_SPEC }, \
{ "startfile_openbsd", STARTFILE_OPENBSD_SPEC }, \
@@ -951,7 +913,6 @@ ncrtn.o%s"
{ "endfile_mvme", ENDFILE_MVME_SPEC }, \
{ "endfile_sim", ENDFILE_SIM_SPEC }, \
{ "endfile_freebsd", ENDFILE_FREEBSD_SPEC }, \
- { "endfile_gnu", ENDFILE_GNU_SPEC }, \
{ "endfile_linux", ENDFILE_LINUX_SPEC }, \
{ "endfile_netbsd", ENDFILE_NETBSD_SPEC }, \
{ "endfile_openbsd", ENDFILE_OPENBSD_SPEC }, \
@@ -964,7 +925,6 @@ ncrtn.o%s"
{ "link_start_mvme", LINK_START_MVME_SPEC }, \
{ "link_start_sim", LINK_START_SIM_SPEC }, \
{ "link_start_freebsd", LINK_START_FREEBSD_SPEC }, \
- { "link_start_gnu", LINK_START_GNU_SPEC }, \
{ "link_start_linux", LINK_START_LINUX_SPEC }, \
{ "link_start_netbsd", LINK_START_NETBSD_SPEC }, \
{ "link_start_openbsd", LINK_START_OPENBSD_SPEC }, \
@@ -976,7 +936,6 @@ ncrtn.o%s"
{ "link_os_sim", LINK_OS_SIM_SPEC }, \
{ "link_os_freebsd", LINK_OS_FREEBSD_SPEC }, \
{ "link_os_linux", LINK_OS_LINUX_SPEC }, \
- { "link_os_gnu", LINK_OS_GNU_SPEC }, \
{ "link_os_netbsd", LINK_OS_NETBSD_SPEC }, \
{ "link_os_openbsd", LINK_OS_OPENBSD_SPEC }, \
{ "link_os_default", LINK_OS_DEFAULT_SPEC }, \
@@ -989,7 +948,6 @@ ncrtn.o%s"
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
{ "cpp_os_sim", CPP_OS_SIM_SPEC }, \
{ "cpp_os_freebsd", CPP_OS_FREEBSD_SPEC }, \
- { "cpp_os_gnu", CPP_OS_GNU_SPEC }, \
{ "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
{ "cpp_os_netbsd", CPP_OS_NETBSD_SPEC }, \
{ "cpp_os_openbsd", CPP_OS_OPENBSD_SPEC }, \
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index d29147c9837..947ec04281f 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003,
- 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
@@ -170,17 +170,3 @@ extern int sh2a_is_function_vector_call (rtx);
extern void sh_fix_range (const char *);
extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode);
#endif /* ! GCC_SH_PROTOS_H */
-
-#ifdef SYMBIAN
-extern const char * sh_symbian_strip_name_encoding (const char *);
-extern bool sh_symbian_is_dllexported_name (const char *);
-#ifdef TREE_CODE
-extern bool sh_symbian_is_dllexported (tree);
-extern int sh_symbian_import_export_class (tree, int);
-extern tree sh_symbian_handle_dll_attribute (tree *, tree, tree, int, bool *);
-#ifdef RTX_CODE
-extern void sh_symbian_encode_section_info (tree, rtx, int);
-#endif
-#endif
-#endif /* SYMBIAN */
-
diff --git a/gcc/config/sh/sh-symbian.h b/gcc/config/sh/sh-symbian.h
deleted file mode 100644
index 2e37d2bbcac..00000000000
--- a/gcc/config/sh/sh-symbian.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* header file for GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* A unique character to encode declspec encoded objects. */
-#define SH_SYMBIAN_FLAG_CHAR "$"
-
-/* Unique strings to prefix exported and imported objects. */
-#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
-#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
-
-/* Select the level of debugging information to display.
- 0 for no debugging.
- 1 for informative messages about decisions to add attributes
- 2 for verbose information about what is being done. */
-#define SYMBIAN_DEBUG 0
-/* #define SYMBIAN_DEBUG 1 */
-/* #define SYMBIAN_DEBUG 2 */
-
-/* Functions exported from symbian-base.c. */
-extern tree sh_symbian_associated_type (tree);
-
-/* Functions exported from symbian-[c|c++].c. */
-extern bool sh_symbian_is_dllimported (tree);
-
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index ee52c32a422..70bff999fc7 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -324,19 +324,6 @@ static const struct attribute_spec sh_attribute_table[] =
sh_handle_resbank_handler_attribute, false },
{ "function_vector", 1, 1, true, false, false,
sh2a_handle_function_vector_handler_attribute, false },
-#ifdef SYMBIAN
- /* Symbian support adds three new attributes:
- dllexport - for exporting a function/variable that will live in a dll
- dllimport - for importing a function/variable from a dll
-
- Microsoft allows multiple declspecs in one __declspec, separating
- them with spaces. We do NOT support this. Instead, use __declspec
- multiple times. */
- { "dllimport", 0, 0, true, false, false,
- sh_symbian_handle_dll_attribute, false },
- { "dllexport", 0, 0, true, false, false,
- sh_symbian_handle_dll_attribute, false },
-#endif
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -592,17 +579,6 @@ static const struct default_options sh_option_optimization_table[] =
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO sh_encode_section_info
-#ifdef SYMBIAN
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO sh_symbian_encode_section_info
-#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING sh_symbian_strip_name_encoding
-#undef TARGET_CXX_IMPORT_EXPORT_CLASS
-#define TARGET_CXX_IMPORT_EXPORT_CLASS sh_symbian_import_export_class
-
-#endif /* SYMBIAN */
-
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD sh_secondary_reload
@@ -2823,12 +2799,6 @@ sh_file_start (void)
{
default_file_start ();
-#ifdef SYMBIAN
- /* Declare the .directive section before it is used. */
- fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);
- fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);
-#endif
-
if (TARGET_ELF)
/* We need to show the text section with the proper
attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
diff --git a/gcc/config/sh/symbian-base.c b/gcc/config/sh/symbian-base.c
deleted file mode 100644
index f8e678be3d2..00000000000
--- a/gcc/config/sh/symbian-base.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* Routines for GCC for a Symbian OS targeted SH backend, shared by
- both the C and C++ compilers.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-/* Return nonzero if SYMBOL is marked as being dllexport'd. */
-
-bool
-sh_symbian_is_dllexported_name (const char *symbol)
-{
- return strncmp (DLL_EXPORT_PREFIX, symbol,
- strlen (DLL_EXPORT_PREFIX)) == 0;
-}
-
-/* Return nonzero if SYMBOL is marked as being dllimport'd. */
-
-static bool
-sh_symbian_is_dllimported_name (const char *symbol)
-{
- return strncmp (DLL_IMPORT_PREFIX, symbol,
- strlen (DLL_IMPORT_PREFIX)) == 0;
-}
-
-/* Return nonzero if DECL is a dllexport'd object. */
-
-bool
-sh_symbian_is_dllexported (tree decl)
-{
- tree exp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
-
- /* Class members get the dllexport status of their class. */
- if (exp == NULL)
- {
- tree class = sh_symbian_associated_type (decl);
-
- if (class)
- exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
- }
-#if SYMBIAN_DEBUG
- if (exp)
- {
- print_node_brief (stderr, "dllexport:", decl, 0);
- fprintf (stderr, "\n");
- }
- else
-#if SYMBIAN_DEBUG < 2
- if (TREE_CODE (decl) != FUNCTION_DECL)
-#endif
- {
- print_node_brief (stderr, "no dllexport:", decl, 0);
- fprintf (stderr, "\n");
- }
-#endif
- return exp ? true : false;
-}
-
-/* Mark a DECL as being dllimport'd. */
-
-static void
-sh_symbian_mark_dllimport (tree decl)
-{
- const char *oldname;
- char *newname;
- tree idp;
- rtx rtlname;
- rtx newrtl;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- if (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (sh_symbian_is_dllexported_name (oldname))
- {
- error ("%qE declared as both exported to and imported from a DLL",
- DECL_NAME (decl));
- }
- else if (sh_symbian_is_dllimported_name (oldname))
- {
- /* Already done, but do a sanity check to prevent assembler errors. */
- if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
- error ("failure in redeclaration of %q+D: dllimport%'d symbol lacks external linkage",
- decl);
- }
- else
- {
- newname = (char *) alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
- newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
- XEXP (DECL_RTL (decl), 0) = newrtl;
- }
-}
-
-/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (e.g.: dllimport). */
-
-static void
-sh_symbian_mark_dllexport (tree decl)
-{
- const char *oldname;
- char *newname;
- rtx rtlname;
- tree idp;
-
- rtlname = XEXP (DECL_RTL (decl), 0);
- if (MEM_P (rtlname))
- rtlname = XEXP (rtlname, 0);
- gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
- oldname = XSTR (rtlname, 0);
-
- if (sh_symbian_is_dllimported_name (oldname))
- {
- /* Remove DLL_IMPORT_PREFIX.
- Note - we do not issue a warning here. In Symbian's environment it
- is legitimate for a prototype to be marked as dllimport and the
- corresponding definition to be marked as dllexport. The prototypes
- are in headers used everywhere and the definition is in a translation
- unit which has included the header in order to ensure argument
- correctness. */
- oldname += strlen (DLL_IMPORT_PREFIX);
- DECL_DLLIMPORT_P (decl) = 0;
- }
- else if (sh_symbian_is_dllexported_name (oldname))
- return; /* Already done. */
-
- newname = (char *) alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
- sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
-
- /* We pass newname through get_identifier to ensure it has a unique
- address. RTL processing can sometimes peek inside the symbol ref
- and compare the string's addresses to see if two symbols are
- identical. */
- idp = get_identifier (newname);
-
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-}
-
-void
-sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
-{
- default_encode_section_info (decl, rtl, first);
-
- /* Mark the decl so we can tell from the rtl whether
- the object is dllexport'd or dllimport'd. */
- if (sh_symbian_is_dllexported (decl))
- sh_symbian_mark_dllexport (decl);
- else if (sh_symbian_is_dllimported (decl))
- sh_symbian_mark_dllimport (decl);
- /* It might be that DECL has already been marked as dllimport, but a
- subsequent definition nullified that. The attribute is gone but
- DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
- that. Ditto for the DECL_DLLIMPORT_P flag. */
- else if ( (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && DECL_RTL (decl) != NULL_RTX
- && MEM_P (DECL_RTL (decl))
- && MEM_P (XEXP (DECL_RTL (decl), 0))
- && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
- && sh_symbian_is_dllimported_name (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
- {
- const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
- /* Remove DLL_IMPORT_PREFIX. */
- tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
- rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-
- warning (0, "%s %q+D %s after being referenced with dllimport linkage",
- TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
- decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
- ? "defined locally" : "redeclared without dllimport attribute");
-
- XEXP (DECL_RTL (decl), 0) = newrtl;
-
- DECL_DLLIMPORT_P (decl) = 0;
- }
-}
-
-/* Return the length of a function name prefix
- that starts with the character 'c'. */
-
-static int
-sh_symbian_get_strip_length (int c)
-{
- /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
- return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
-}
-
-/* Return a pointer to a function's name with any
- and all prefix encodings stripped from it. */
-
-const char *
-sh_symbian_strip_name_encoding (const char *name)
-{
- int skip;
-
- while ((skip = sh_symbian_get_strip_length (*name)))
- name += skip;
-
- return name;
-}
-
diff --git a/gcc/config/sh/symbian-c.c b/gcc/config/sh/symbian-c.c
deleted file mode 100644
index c93922a3911..00000000000
--- a/gcc/config/sh/symbian-c.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* Routines for C compiler part of GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-
-/* Return the type that we should use to determine if DECL is
- imported or exported. */
-
-tree
-sh_symbian_associated_type (tree decl)
-{
- tree t = NULL_TREE;
-
- /* We can just take the DECL_CONTEXT as normal. */
- if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- t = DECL_CONTEXT (decl);
-
- return t;
-}
-
-/* Return nonzero if DECL is a dllimport'd object. */
-
-bool
-sh_symbian_is_dllimported (tree decl)
-{
- tree imp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- if (imp)
- return true;
-
- /* Class members get the dllimport status of their class. */
- imp = sh_symbian_associated_type (decl);
- if (! imp)
- return false;
-
- imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
- if (!imp)
- return false;
-
- /* Don't mark defined functions as dllimport. If the definition itself
- was marked with dllimport, then sh_symbian_handle_dll_attribute reports
- an error. This handles the case when the definition overrides an
- earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl)
- && ! DECL_DECLARED_INLINE_P (decl))
- {
- warning (OPT_Wattributes, "function %q+D is defined after prior "
- "declaration as dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* Don't allow definitions of static data members in dllimport
- class. Just ignore the attribute for vtable data. */
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && !DECL_EXTERNAL (decl))
- {
- error ("definition of static data member %q+D of dllimport%'d class",
- decl);
- return false;
- }
-
- return true;
-}
-
-/* Handle a "dllimport" or "dllexport" attribute;
- arguments as in struct attribute_spec.handler. */
-
-tree
-sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
- int flags, bool *no_add_attrs)
-{
- tree node = *pnode;
- const char *attr = IDENTIFIER_POINTER (name);
-
- /* These attributes may apply to structure and union types being
- created, but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
-
- if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
- /* Report error on dllimport ambiguities
- seen now before they cause any damage. */
- else if (is_attribute_p ("dllimport", name))
- {
- if (TREE_CODE (node) == VAR_DECL)
- {
- if (DECL_INITIAL (node))
- {
- error ("variable %q+D definition is marked dllimport",
- node);
- *no_add_attrs = true;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- DECL_EXTERNAL (node) = 1;
- /* Also, implicitly give dllimport'd variables declared within
- a function global scope, unless declared static. */
- if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
- TREE_PUBLIC (node) = 1;
- }
- }
-
- /* Report error if symbol is not accessible at global scope. */
- if (!TREE_PUBLIC (node)
- && ( TREE_CODE (node) == VAR_DECL
- || TREE_CODE (node) == FUNCTION_DECL))
- {
- error ("external linkage required for symbol %q+D because of %qE attribute",
- node, name);
- *no_add_attrs = true;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "mark node", node, 0);
- fprintf (stderr, " as %s\n", attr);
-#endif
-
- return NULL_TREE;
-}
-
-int
-sh_symbian_import_export_class (tree ctype ATTRIBUTE_UNUSED, int import_export)
-{
- return import_export;
-}
diff --git a/gcc/config/sh/symbian-cxx.c b/gcc/config/sh/symbian-cxx.c
deleted file mode 100644
index c0f8b71f626..00000000000
--- a/gcc/config/sh/symbian-cxx.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/* Routines for C++ support for GCC for a Symbian OS targeted SH backend.
- Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
- Contributed by RedHat.
- Most of this code is stolen from i386/winnt.c.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "output.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-#include "tm_p.h"
-#include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
-#include "diagnostic-core.h"
-#include "sh-symbian.h"
-
-
-/* Return the type that we should use to determine if DECL is
- imported or exported. */
-
-tree
-sh_symbian_associated_type (tree decl)
-{
- tree t = NULL_TREE;
-
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- /* Methods now inherit their dllimport/dllexport attributes correctly
- so there is no need to check their class. In fact it is wrong to
- check their class since a method can remain unexported from an
- exported class. */
- return t;
-
- /* Otherwise we can just take the DECL_CONTEXT as normal. */
- if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
- t = DECL_CONTEXT (decl);
-
- return t;
-}
-
-
-/* Return nonzero if DECL is a dllimport'd object. */
-
-bool
-sh_symbian_is_dllimported (tree decl)
-{
- tree imp;
-
- if ( TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return false;
-
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
- if (imp)
- return true;
-
- /* Class members get the dllimport status of their class. */
- imp = sh_symbian_associated_type (decl);
- if (! imp)
- return false;
-
- imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
- if (!imp)
- return false;
-
- /* Don't mark defined functions as dllimport. If the definition itself
- was marked with dllimport, then sh_symbian_handle_dll_attribute reports
- an error. This handles the case when the definition overrides an
- earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INITIAL (decl)
- && ! DECL_DECLARED_INLINE_P (decl))
- {
- /* Don't warn about artificial methods. */
- if (!DECL_ARTIFICIAL (decl))
- warning (OPT_Wattributes, "function %q+D is defined after prior "
- "declaration as dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* We ignore the dllimport attribute for inline member functions.
- This differs from MSVC behavior which treats it like GNUC
- 'extern inline' extension. */
- else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
- {
- if (extra_warnings)
- warning (OPT_Wattributes, "inline function %q+D is declared as "
- "dllimport: attribute ignored",
- decl);
- return false;
- }
-
- /* Don't allow definitions of static data members in dllimport
- class. Just ignore the attribute for vtable data. */
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl)
- && TREE_PUBLIC (decl)
- && !DECL_EXTERNAL (decl))
- {
- if (!DECL_VIRTUAL_P (decl))
- error ("definition of static data member %q+D of dllimport%'d class",
- decl);
- return false;
- }
-
- /* Since we can't treat a pointer to a dllimport'd symbol as a
- constant address, we turn off the attribute on C++ virtual
- methods to allow creation of vtables using thunks. Don't mark
- artificial methods either (in sh_symbian_associated_type, only
- COMDAT artificial method get import status from class context). */
- else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
- return false;
-
- return true;
-}
-
-
-/* This code implements a specification for exporting the vtable and rtti of
- classes that have members with the dllexport or dllexport attributes.
- This specification is defined here:
-
- http://www.armdevzone.com/EABI/exported_class.txt
-
- Basically it says that a class's vtable and rtti should be exported if
- the following rules apply:
-
- - If it has any non-inline non-pure virtual functions,
- at least one of these need to be declared dllimport
- OR any of the constructors is declared dllimport.
-
- AND
-
- - The class has an inline constructor/destructor and
- a key-function (placement of vtable uniquely defined) that
- is defined in this translation unit.
-
- The specification also says that for classes which will have their
- vtables and rtti exported that their base class(es) might also need a
- similar exporting if:
-
- - Every base class needs to have its vtable & rtti exported
- as well, if the following the conditions hold true:
- + The base class has a non-inline declared non-pure virtual function
- + The base class is polymorphic (has or inherits any virtual functions)
- or the base class has any virtual base classes. */
-
-/* Decide if a base class of a class should
- also have its vtable and rtti exported. */
-
-static void
-sh_symbian_possibly_export_base_class (tree base_class)
-{
- VEC(tree,gc) *method_vec;
- int len;
-
- if (! (TYPE_CONTAINS_VPTR_P (base_class)))
- return;
-
- method_vec = CLASSTYPE_METHOD_VEC (base_class);
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (DECL_DECLARED_INLINE_P (member))
- continue;
-
- break;
- }
-
- if (member)
- break;
- }
-
- if (len < 0)
- return;
-
- /* FIXME: According to the spec this base class should be exported, but
- a) how do we do this ? and
- b) it does not appear to be necessary for compliance with the Symbian
- OS which so far is the only consumer of this code. */
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", base_class, 0);
- fprintf (stderr, " EXPORTed [base class of exported class]\n");
-#endif
-}
-
-/* Add the named attribute to the given node. Copes with both DECLs and
- TYPEs. Will only add the attribute if it is not already present. */
-
-static void
-sh_symbian_add_attribute (tree node, const char *attr_name)
-{
- tree attrs;
- tree attr;
-
- attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
-
- if (lookup_attribute (attr_name, attrs) != NULL_TREE)
- return;
-
- attr = get_identifier (attr_name);
-
- if (DECL_P (node))
- DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
- else
- TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
-
-#if SYMBIAN_DEBUG
- fprintf (stderr, "propagate %s attribute", attr_name);
- print_node_brief (stderr, " to", node, 0);
- fprintf (stderr, "\n");
-#endif
-}
-
-/* Add the named attribute to a class and its vtable and rtti. */
-
-static void
-sh_symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
-{
- sh_symbian_add_attribute (ctype, attr_name);
-
- /* If the vtable exists then they need annotating as well. */
- if (CLASSTYPE_VTABLES (ctype))
- /* XXX - Do we need to annotate any vtables other than the primary ? */
- sh_symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
-
- /* If the rtti exists then it needs annotating as well. */
- if (TYPE_MAIN_VARIANT (ctype)
- && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
- sh_symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
- attr_name);
-}
-
-/* Decide if a class needs to have an attribute because
- one of its member functions has the attribute. */
-
-static bool
-sh_symbian_class_needs_attribute (tree ctype, const char *attribute_name)
-{
- VEC(tree,gc) *method_vec;
-
- method_vec = CLASSTYPE_METHOD_VEC (ctype);
-
- /* If the key function has the attribute then the class needs it too. */
- if (TYPE_POLYMORPHIC_P (ctype)
- && method_vec
- && tree_contains_struct [TREE_CODE (ctype), TS_DECL_COMMON] == 1
- && lookup_attribute (attribute_name,
- DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
- return true;
-
- /* Check the class's member functions. */
- if (TREE_CODE (ctype) == RECORD_TYPE)
- {
- unsigned int len;
-
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member);
- member;
- member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " inherits %s because", attribute_name);
- print_node_brief (stderr, "", member, 0);
- fprintf (stderr, " has it.\n");
-#endif
- return true;
- }
- }
- }
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does not inherit %s\n", attribute_name);
-#endif
- return false;
-}
-
-/* Decide if a class needs its vtable and rtti exporting. */
-
-static bool
-symbian_export_vtable_and_rtti_p (tree ctype)
-{
- bool inline_ctor_dtor;
- bool dllimport_ctor_dtor;
- bool dllimport_member;
- tree binfo, base_binfo;
- VEC(tree,gc) *method_vec;
- tree key;
- int i;
- int len;
-
- /* Make sure that we are examining a class... */
- if (TREE_CODE (ctype) != RECORD_TYPE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
-#endif
- return false;
- }
-
- /* If the class does not have a key function it
- does not need to have its vtable exported. */
- if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
-#endif
- return false;
- }
-
- /* If the key fn has not been defined
- then the class should not be exported. */
- if (! TREE_ASM_WRITTEN (key))
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
-#endif
- return false;
- }
-
- /* Check the class's member functions. */
- inline_ctor_dtor = false;
- dllimport_ctor_dtor = false;
- dllimport_member = false;
-
- method_vec = CLASSTYPE_METHOD_VEC (ctype);
- len = method_vec ? VEC_length (tree, method_vec) : 0;
-
- for (;len --;)
- {
- tree member = VEC_index (tree, method_vec, len);
-
- if (! member)
- continue;
-
- for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
- {
- if (TREE_CODE (member) != FUNCTION_DECL)
- continue;
-
- if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
- {
- if (DECL_DECLARED_INLINE_P (member)
- /* Ignore C++ backend created inline ctors/dtors. */
- && ( DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
- || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
- inline_ctor_dtor = true;
-
- if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
- dllimport_ctor_dtor = true;
- }
- else
- {
- if (DECL_PURE_VIRTUAL_P (member))
- continue;
-
- if (! DECL_VIRTUAL_P (member))
- continue;
-
- if (DECL_DECLARED_INLINE_P (member))
- continue;
-
- if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
- dllimport_member = true;
- }
- }
- }
-
- if (! dllimport_member && ! dllimport_ctor_dtor)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr,
- " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
-#endif
- return false;
- }
-
- if (! inline_ctor_dtor)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr,
- " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
-#endif
- return false;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "", ctype, 0);
- fprintf (stderr, " DOES need to be EXPORTed\n");
-#endif
-
- /* Now we must check and possibly export the base classes. */
- for (i = 0, binfo = TYPE_BINFO (ctype);
- BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- sh_symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
-
- return true;
-}
-
-/* Possibly override the decision to export class TYPE. Upon entry
- IMPORT_EXPORT will contain 1 if the class is going to be exported,
- -1 if it is going to be imported and 0 otherwise. This function
- should return the modified value and perform any other actions
- necessary to support the backend's targeted operating system. */
-
-int
-sh_symbian_import_export_class (tree ctype, int import_export)
-{
- const char *attr_name = NULL;
-
- /* If we are exporting the class but it does not have the dllexport
- attribute then we may need to add it. Similarly imported classes
- may need the dllimport attribute. */
- switch (import_export)
- {
- case 1: attr_name = "dllexport"; break;
- case -1: attr_name = "dllimport"; break;
- default: break;
- }
-
- if (attr_name
- && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
- {
- if (sh_symbian_class_needs_attribute (ctype, attr_name))
- sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
-
- /* Classes can be forced to export their
- vtable and rtti under certain conditions. */
- if (symbian_export_vtable_and_rtti_p (ctype))
- {
- sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
-
- /* Make sure that the class and its vtable are exported. */
- import_export = 1;
-
- if (CLASSTYPE_VTABLES (ctype))
- DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
-
- /* Check to make sure that if the class has a key method that
- it is now on the list of keyed classes. That way its vtable
- will be emitted. */
- if (CLASSTYPE_KEY_METHOD (ctype))
- {
- tree class;
-
- for (class = keyed_classes; class; class = TREE_CHAIN (class))
- if (class == ctype)
- break;
-
- if (class == NULL_TREE)
- {
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "Add node", ctype, 0);
- fprintf (stderr, " to the keyed classes list\n");
-#endif
- keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
- }
- }
-
- /* Make sure that the typeinfo will be emitted as well. */
- if (CLASS_TYPE_P (ctype))
- TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
- }
- }
-
- return import_export;
-}
-
-/* Handle a "dllimport" or "dllexport" attribute;
- arguments as in struct attribute_spec.handler. */
-
-tree
-sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
- int flags, bool *no_add_attrs)
-{
- tree thunk;
- tree node = *pnode;
- const char *attr = IDENTIFIER_POINTER (name);
-
- /* These attributes may apply to structure and union types being
- created, but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT
- | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
-
- if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
- {
- warning (OPT_Wattributes, "%qs attribute ignored", attr);
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
- /* Report error on dllimport ambiguities
- seen now before they cause any damage. */
- else if (is_attribute_p ("dllimport", name))
- {
- if (TREE_CODE (node) == VAR_DECL)
- {
- if (DECL_INITIAL (node))
- {
- error ("variable %q+D definition is marked dllimport",
- node);
- *no_add_attrs = true;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- DECL_EXTERNAL (node) = 1;
- /* Also, implicitly give dllimport'd variables declared within
- a function global scope, unless declared static. */
- if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
- TREE_PUBLIC (node) = 1;
- }
- }
-
- /* If the node is an overloaded constructor or destructor, then we must
- make sure that the attribute is propagated along the overload chain,
- as it is these overloaded functions which will be emitted, rather than
- the user declared constructor itself. */
- if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
- && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
- {
- tree overload;
-
- for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
- {
- tree node_args;
- tree func_args;
- tree function = OVL_CURRENT (overload);
-
- if (! function
- || ! DECL_P (function)
- || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
- || (DECL_DESTRUCTOR_P (node) && ! DECL_DESTRUCTOR_P (function)))
- continue;
-
- /* The arguments must match as well. */
- for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
- node_args && func_args;
- node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
- if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
- break;
-
- if (node_args || func_args)
- {
- /* We can ignore an extraneous __in_chrg arguments in the node.
- GCC generated destructors, for example, will have this. */
- if ((node_args == NULL_TREE
- || func_args != NULL_TREE)
- && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
- continue;
- }
-
- sh_symbian_add_attribute (function, attr);
-
- /* Propagate the attribute to any function thunks as well. */
- for (thunk = DECL_THUNKS (function); thunk; thunk = DECL_CHAIN (thunk))
- if (TREE_CODE (thunk) == FUNCTION_DECL)
- sh_symbian_add_attribute (thunk, attr);
- }
- }
-
- if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
- {
- /* Propagate the attribute to any thunks of this function. */
- for (thunk = DECL_THUNKS (node); thunk; thunk = DECL_CHAIN (thunk))
- if (TREE_CODE (thunk) == FUNCTION_DECL)
- sh_symbian_add_attribute (thunk, attr);
- }
-
- /* Report error if symbol is not accessible at global scope. */
- if (!TREE_PUBLIC (node)
- && ( TREE_CODE (node) == VAR_DECL
- || TREE_CODE (node) == FUNCTION_DECL))
- {
- error ("external linkage required for symbol %q+D because of %qE attribute",
- node, name);
- *no_add_attrs = true;
- }
-
-#if SYMBIAN_DEBUG
- print_node_brief (stderr, "mark node", node, 0);
- fprintf (stderr, " as %s\n", attr);
-#endif
-
- return NULL_TREE;
-}
diff --git a/gcc/config/sh/symbian-post.h b/gcc/config/sh/symbian-post.h
deleted file mode 100644
index a4497b96994..00000000000
--- a/gcc/config/sh/symbian-post.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Definitions for the Symbian OS running on an SH part.
- This file is included after all the other target specific headers.
-
- Copyright (C) 2004, 2007 Free Software Foundation, Inc.
- Contributed by Red Hat.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#undef TARGET_VERSION
-#define TARGET_VERSION \
- fputs (" (Renesas SH for Symbian OS)", stderr);
-
-#undef LINK_EMUL_PREFIX
-#define LINK_EMUL_PREFIX "shlsymbian"
-
-
-#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL) \
- do \
- { \
- if ((DECL && sh_symbian_is_dllexported (DECL)) \
- || sh_symbian_is_dllexported_name (NAME)) \
- { \
- fprintf ((FILE), "\t.pushsection .directive\n"); \
- fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n", \
- sh_symbian_strip_name_encoding (NAME)); \
- fprintf ((FILE), "\t.popsection\n"); \
- } \
- } \
- while (0)
-
-/* Output a function definition label. */
-#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
- ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "function"); \
- ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL ((FILE), (NAME)); \
- } \
- while (0)
-
-/* Output the label for an initialized variable. */
-#undef ASM_DECLARE_OBJECT_NAME
-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
- do \
- { \
- HOST_WIDE_INT size; \
- \
- SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
- ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "object"); \
- \
- size_directive_output = 0; \
- if (!flag_inhibit_size_directive \
- && (DECL) \
- && DECL_SIZE (DECL)) \
- { \
- size_directive_output = 1; \
- size = int_size_in_bytes (TREE_TYPE (DECL)); \
- ASM_OUTPUT_SIZE_DIRECTIVE ((FILE), (NAME), size); \
- } \
- \
- ASM_OUTPUT_LABEL ((FILE), (NAME)); \
- } \
- while (0)
-
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- do \
- { \
- asm_fprintf ((FILE), "%U%s", \
- sh_symbian_strip_name_encoding (NAME)); \
- } \
- while (0)
diff --git a/gcc/config/sh/symbian-pre.h b/gcc/config/sh/symbian-pre.h
deleted file mode 100644
index d2229e071f2..00000000000
--- a/gcc/config/sh/symbian-pre.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Definitions for the Symbian OS running on an SH part.
- This file is included before any other target specific headers.
-
- Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
- Contributed by Red Hat.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-/* Enable Symbian specific code. */
-#define SYMBIAN 1
-
-/* Default to using the Renesas ABI. */
-#define TARGET_ABI_DEFAULT MASK_HITACHI
-
-#define SUBTARGET_CPP_SPEC ""
-
-/* Get tree.c to declare merge_dllimport_decl_attributes(). */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-
-/* The Symbian OS currently does not support exception handling. */
-#define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions"
-
-/* Create constructor/destructor sections without the writable flag.
- Symbian puts them into the text segment and munges them later on. */
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"ax\",@progbits"
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"ax\",@progbits"
diff --git a/gcc/config/sh/t-symbian b/gcc/config/sh/t-symbian
deleted file mode 100644
index f0b7dabd4e5..00000000000
--- a/gcc/config/sh/t-symbian
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright (C) 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
-#
-# This file is part of GCC.
-#
-# GCC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-sh-c.o: $(srcdir)/config/sh/sh-c.c \
- $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/sh/sh-c.c
-
-symbian-cxx.o: \
- $(srcdir)/config/sh/symbian-cxx.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-symbian-c.o: \
- $(srcdir)/config/sh/symbian-c.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-symbian-base.o: \
- $(srcdir)/config/sh/symbian-base.c \
- $(srcdir)/config/sh/sh-symbian.h \
- $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) $(RTL_H) \
- toplev.h output.h coretypes.h flags.h expr.h
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-
-LIB1ASMSRC = sh/lib1funcs.asm
-LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
- _movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
- $(LIB1ASMFUNCS_CACHE)
-
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
-$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
-$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
-$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
-
-$(out_object_file): gt-sh.h
-gt-sh.h : s-gtype ; @true
-
-symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/sh/symbian.c
-
-
-# Local Variables:
-# mode: Makefile
-# End:
diff --git a/gcc/config/svr3.h b/gcc/config/svr3.h
deleted file mode 100644
index 243206245a6..00000000000
--- a/gcc/config/svr3.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Operating system specific defines to be used when targeting GCC for
- generic System V Release 3 system.
- Copyright (C) 1991, 1996, 2000, 2002, 2004, 2007, 2010
- Free Software Foundation, Inc.
- Contributed by Ron Guilmette (rfg@monkeys.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* Define a symbol indicating that we are using svr3.h. */
-#define USING_SVR3_H
-
-/* Define a symbol so that libgcc* can know what sort of operating
- environment and assembler syntax we are targeting for. */
-#define SVR3_target
-
-/* Assembler, linker, library, and startfile spec's. */
-
-/* The .file command should always begin the output. */
-#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-
-/* This says how to output an assembler line
- to define a global common symbol. */
-/* We don't use ROUNDED because the standard compiler doesn't,
- and the linker gives error messages if a common symbol
- has more than one length value. */
-
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
-( fputs (".comm ", (FILE)), \
- assemble_name ((FILE), (NAME)), \
- fprintf ((FILE), ",%lu\n", (unsigned long)(SIZE)))
-
-/* This says how to output an assembler line
- to define a local common symbol. */
-
-/* Note that using bss_section here caused errors
- in building shared libraries on system V.3. */
-#undef ASM_OUTPUT_LOCAL
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- do { \
- int align = exact_log2 (ROUNDED); \
- if (align > 2) align = 2; \
- switch_to_section (data_section); \
- ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \
- ASM_OUTPUT_LABEL ((FILE), (NAME)); \
- fprintf ((FILE), "\t.set .,.+%u\n", (int)(ROUNDED)); \
- } while (0)
-
-/* Output #ident as a .ident. */
-
-#undef ASM_OUTPUT_IDENT
-#define ASM_OUTPUT_IDENT(FILE, NAME) \
- fprintf (FILE, "\t.ident \"%s\"\n", NAME);
-
-/* Use periods rather than dollar signs in special g++ assembler names. */
-
-#define NO_DOLLAR_IN_LABEL
-
-/* System V Release 3 uses COFF debugging info. */
-
-#define SDB_DEBUGGING_INFO 1
-
-/* We don't want to output DBX debugging information. */
-
-#undef DBX_DEBUGGING_INFO
-
-/* The prefix to add to user-visible assembler symbols.
-
- For System V Release 3 the convention is to prepend a leading
- underscore onto user-level symbol names. */
-
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX "_"
-
-/* This is how to store into the string LABEL
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'.
-
- For most svr3 systems, the convention is that any symbol which begins
- with a period is not put into the linker symbol table by the assembler. */
-
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*%s%s%ld", LOCAL_LABEL_PREFIX, PREFIX, (long)(NUM))
-
-/* We want local labels to start with period if made with asm_fprintf. */
-#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "."
-
-/* Support const sections and the ctors and dtors sections for g++. */
-
-/* Define a few machine-specific details of the implementation of
- constructors.
-
- The __CTORS_LIST__ goes in the .init section. Define CTOR_LIST_BEGIN
- and CTOR_LIST_END to contribute to the .init section an instruction to
- push a word containing 0 (or some equivalent of that).
-
- Define TARGET_ASM_CONSTRUCTOR to push the address of the constructor. */
-
-#define INIT_SECTION_ASM_OP "\t.section\t.init"
-#define FINI_SECTION_ASM_OP "\t.section .fini,\"x\""
-#define DTORS_SECTION_ASM_OP FINI_SECTION_ASM_OP
-
-/* CTOR_LIST_BEGIN and CTOR_LIST_END are machine-dependent
- because they push on the stack. */
-
-#ifndef STACK_GROWS_DOWNWARD
-
-/* Constructor list on stack is in reverse order. Go to the end of the
- list and go backwards to call constructors in the right order. */
-#define DO_GLOBAL_CTORS_BODY \
-do { \
- func_ptr *p, *beg = alloca (0); \
- for (p = beg; *p; p++) \
- ; \
- while (p != beg) \
- (*--p) (); \
-} while (0)
-
-#else
-
-/* Constructor list on stack is in correct order. Just call them. */
-#define DO_GLOBAL_CTORS_BODY \
-do { \
- func_ptr *p, *beg = alloca (0); \
- for (p = beg; *p; ) \
- (*p++) (); \
-} while (0)
-
-#endif /* STACK_GROWS_DOWNWARD */
diff --git a/gcc/config/vax/netbsd.h b/gcc/config/vax/netbsd.h
deleted file mode 100644
index 51c32f7346e..00000000000
--- a/gcc/config/vax/netbsd.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Definitions of target machine for GNU compiler.
- NetBSD/vax a.out version.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2007
- Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- NETBSD_OS_CPP_BUILTINS_AOUT(); \
- } \
- while (0)
-
-#undef CPP_SPEC
-#define CPP_SPEC NETBSD_CPP_SPEC
-
-/* Make gcc agree with <machine/ansi.h> */
-
-#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
-
-/* Until they use ELF or something that handles dwarf2 unwinds
- and initialization stuff better. Use sjlj exceptions. */
-#undef DWARF2_UNWIND_INFO
-
-/* We use gas, not the UNIX assembler. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0