diff --git a/gcc/config/arc64/arc64-protos.h b/gcc/config/arc64/arc64-protos.h
index d0dd01e372b44..3f435c1c1f493 100644
--- a/gcc/config/arc64/arc64-protos.h
+++ b/gcc/config/arc64/arc64-protos.h
@@ -4,15 +4,18 @@
extern int arc64_epilogue_uses (int);
extern HOST_WIDE_INT arc64_initial_elimination_offset (unsigned, unsigned);
extern void arc64_init_expanders (void);
-extern rtx arc64_return_addr (int, rtx);
-extern HOST_WIDE_INT arc64_regmode_natural_size (machine_mode);
+extern void arc64_cpu_cpp_builtins (cpp_reader *);
#ifdef RTX_CODE
+extern rtx arc64_return_addr (int, rtx);
extern machine_mode arc64_select_cc_mode (enum rtx_code, rtx, rtx);
extern bool arc64_check_mov_const (HOST_WIDE_INT );
extern bool arc64_split_mov_const (rtx *);
extern bool arc64_can_use_return_insn_p (void);
+extern void arc64_expand_call (rtx, rtx, bool);
+extern rtx arc64_gen_compare_reg (enum rtx_code, rtx, rtx);
+extern bool arc64_prepare_move_operands (rtx, rtx, machine_mode);
#endif /* RTX_CODE */
diff --git a/gcc/config/arc64/arc64.c b/gcc/config/arc64/arc64.c
index 93c7531707063..6087291cc0d39 100644
--- a/gcc/config/arc64/arc64.c
+++ b/gcc/config/arc64/arc64.c
@@ -64,62 +64,12 @@ const enum reg_class arc64_regno_to_regclass[FIRST_PSEUDO_REGISTER] =
NO_REGS, NO_REGS, NO_REGS,
};
-/* Return 1 if the register is used by the epilogue. We need to say the
- return register is used, but only after epilogue generation is complete.
- Note that in the case of sibcalls, the values "used by the epilogue" are
- considered live at the start of the called function. */
-
-int
-arc64_epilogue_uses (int regno)
-{
- if (epilogue_completed)
- if (regno == BLINK_REGNUM)
- return 1;
-
- return 0;
-}
-
-/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer
- or argument pointer. TO is either the stack pointer or hard frame
- pointer. */
-
-HOST_WIDE_INT
-arc64_initial_elimination_offset (unsigned from, unsigned to)
-{
- return 0;
-}
-
-void arc64_init_expanders (void)
-{
- /* FIXME! Not sure if I need it. */
-}
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a
- COMPARE, return the mode to be used for the comparison. */
-
-machine_mode
-arc64_select_cc_mode (enum rtx_code op, rtx x, rtx y)
-{
- return CC_Cmode;
-}
-
-/* Implement RETURN_ADDR_RTX. We do not support moving back to a
- previous frame. */
-
-rtx
-arc64_return_addr (int count , rtx frame ATTRIBUTE_UNUSED)
+/* Emit an insn that's a simple single-set. Both the operands must be
+ known to be valid. */
+inline static rtx_insn *
+emit_set_insn (rtx x, rtx y)
{
- if (count != 0)
- return const0_rtx;
- return get_hard_reg_initial_val (Pmode, BLINK_REGNUM);
-}
-
-/* Implement REGMODE_NATURAL_SIZE. */
-
-HOST_WIDE_INT
-arc64_regmode_natural_size (machine_mode mode)
-{
- return UNITS_PER_WORD; /*FIXME! do I need it? */
+ return emit_insn (gen_rtx_SET (x, y));
}
/* Given FROM and TO register numbers, say whether this elimination is allowed.
@@ -140,7 +90,7 @@ arc64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
mode MODE. */
static bool
-arc_legitimate_address_p (machine_mode mode, rtx x, bool strict)
+arc64_legitimate_address_p (machine_mode mode, rtx x, bool strict)
{
return true;
}
@@ -156,6 +106,26 @@ arc64_legitimate_constant_p (machine_mode mode, rtx x)
return false;
}
+/* 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 arc64_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
+{
+ default_internal_label (stream, prefix, labelno);
+}
+
+/* X and Y are two things to compare using CODE. Emit the compare insn and
+ return the rtx for the cc reg in the proper mode. */
+
+rtx
+arc64_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
+{
+ machine_mode mode = SELECT_CC_MODE (code, x, y);
+ rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
+
+ emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
+ return cc_reg;
+}
/* Prepare operands for move in MODE. Return true iff the move has
been emitted. */
@@ -280,6 +250,7 @@ arc64_check_mov_const (HOST_WIDE_INT ival)
return false;
}
+#endif
/* This function is used by the call expanders of the machine description.
RESULT is the register in which the result is returned. It's NULL for
@@ -292,6 +263,7 @@ void
arc64_expand_call (rtx result, rtx mem, bool sibcall)
{
rtx call, callee, tmp;
+ rtvec vec;
machine_mode mode;
gcc_assert (MEM_P (mem));
@@ -302,10 +274,10 @@ arc64_expand_call (rtx result, rtx mem, bool sibcall)
/* Decide if we should generate indirect calls by loading the
address of the callee into a register before performing the
branch-and-link. */
- if (arc64_is_long_call_p (callee) && !REG_P (callee))
- XEXP (mem, 0) = force_reg (mode, callee);
+// FIXME! if (arc64_is_long_call_p (callee) && !REG_P (callee))
+// FIXME! XEXP (mem, 0) = force_reg (mode, callee);
- call = gen_rtx_call (VOIDmode, mem, cont0_rtx);
+ call = gen_rtx_CALL (VOIDmode, mem, const0_rtx);
if (result != NULL_RTX)
call = gen_rtx_SET (result, call);
@@ -320,7 +292,6 @@ arc64_expand_call (rtx result, rtx mem, bool sibcall)
emit_call_insn (call);
}
-#endif
/* Return nonzero if this function is known to have a null epilogue.
This allows the optimizer to omit jumps to jumps if no stack
@@ -332,12 +303,63 @@ arc64_can_use_return_insn_p (void)
return (reload_completed); //FIXME!: && cfun->machine->frame.frame_size == 0);
}
-/* 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 arc64_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
+/* Return 1 if the register is used by the epilogue. We need to say the
+ return register is used, but only after epilogue generation is complete.
+ Note that in the case of sibcalls, the values "used by the epilogue" are
+ considered live at the start of the called function. */
+
+int
+arc64_epilogue_uses (int regno)
{
- default_internal_label (stream, prefix, labelno);
+ if (epilogue_completed)
+ if (regno == BLINK_REGNUM)
+ return 1;
+
+ return 0;
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer
+ or argument pointer. TO is either the stack pointer or hard frame
+ pointer. */
+
+HOST_WIDE_INT
+arc64_initial_elimination_offset (unsigned from, unsigned to)
+{
+ return 0;
+}
+
+void arc64_init_expanders (void)
+{
+ /* FIXME! Not sure if I need it. */
+}
+
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a
+ COMPARE, return the mode to be used for the comparison. */
+
+machine_mode
+arc64_select_cc_mode (enum rtx_code op, rtx x, rtx y)
+{
+ return CC_Cmode;
+}
+
+/* Implement RETURN_ADDR_RTX. We do not support moving back to a
+ previous frame. */
+
+rtx
+arc64_return_addr (int count , rtx frame ATTRIBUTE_UNUSED)
+{
+ if (count != 0)
+ return const0_rtx;
+ return get_hard_reg_initial_val (Pmode, BLINK_REGNUM);
+}
+
+/* Helper for TARGET_CPU_CPP_BUILTINS hook. */
+
+void
+arc64_cpu_cpp_builtins (cpp_reader * pfile)
+{
+ //FIXME! builtin_define ("__arc64__");
}
/* Target hooks. */
@@ -358,8 +380,8 @@ static void arc64_internal_label (FILE *stream, const char *prefix, unsigned lon
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE arc64_can_eliminate
-//#undef TARGET_LEGITIMATE_ADDRESS_P
-//#define TARGET_LEGITIMATE_ADDRESS_P arc64_legitimate_address_p
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P arc64_legitimate_address_p
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P arc64_legitimate_constant_p
diff --git a/gcc/config/arc64/arc64.h b/gcc/config/arc64/arc64.h
index 371e2634f0209..1501bbbb00093 100644
--- a/gcc/config/arc64/arc64.h
+++ b/gcc/config/arc64/arc64.h
@@ -1,3 +1,22 @@
+/* Machine description for ARC64 architecture.
+ Copyright (C) 2019 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
+ . */
+
#ifndef GCC_ARC64_H
#define GCC_ARC64_H
@@ -11,12 +30,13 @@
numbered. */
#define WORDS_BIG_ENDIAN 0
+/* Width of a word, in units (bytes). */
#define UNITS_PER_WORD 8
-
-/* 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
+/* Maximum number of registers that can appear in a valid memory
+ address. N.B. The ld insn allows 2, but the st insn only allows
+ 1. */
+#define MAX_REGS_PER_ADDRESS 2
/* The number of registers used for parameter passing. Local to this file. */
#define MAX_ARC_PARM_REGS 8
@@ -32,9 +52,9 @@
#define EMPTY_FIELD_BOUNDARY 32
#define STRUCTURE_SIZE_BOUNDARY 8
-/* Look at the fundamental type that is used for a bit-field and use
- that to impose alignment on the enclosing structure.
- struct s {int a:8}; should have same alignment as "int", not "char". */
+/* Look at the fundamental type that is used for a bit-field and use
+ that to impose alignment on the enclosing structure. struct s {int
+ a:8}; should have same alignment as "int", not "char". */
#define PCC_BITFIELD_TYPE_MATTERS 1
/* Alignments. */
@@ -50,12 +70,13 @@
#define DATA_ALIGNMENT(EXP, ALIGN) \
ARC_EXPAND_ALIGNMENT (!optimize_size, EXP, ALIGN)
-/* Similarly, make sure that objects on the stack are sensibly aligned. */
+/* Similarly, make sure that objects on the stack are sensibly
+ aligned. */
#define LOCAL_ALIGNMENT(EXP, ALIGN) \
ARC_EXPAND_ALIGNMENT (!flag_conserve_stack, EXP, ALIGN)
#define STRICT_ALIGNMENT 1
-/* Layout of Source Language Data Types */
+/* Layout of Source Language Data Types. */
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE 32
#define LONG_TYPE_SIZE 64
@@ -287,8 +308,6 @@ enum reg_class
low-order few bits. */
#define SHIFT_COUNT_TRUNCATED 1
-#define REGMODE_NATURAL_SIZE(MODE) arc64_regmode_natural_size (MODE)
-
/* Function argument passing. */
/* Define a data type for recording info about an argument list during
@@ -358,7 +377,6 @@ extern const enum reg_class arc64_regno_to_regclass[];
#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P(REGNO)
-
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE 16
@@ -369,73 +387,22 @@ extern const enum reg_class arc64_regno_to_regclass[];
#define TRAMPOLINE_ALIGNMENT 256
/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_CPU_CPP_BUILTINS()
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-/* We work around a dwarfout.c deficiency by watching for labels from it and
- not adding the '_' prefix. There is a comment in
- dwarfout.c that says it should be using ASM_OUTPUT_INTERNAL_LABEL. */
-#define ASM_OUTPUT_LABELREF(FILE, NAME1) \
-do { \
- const char *NAME; \
- NAME = (*targetm.strip_name_encoding)(NAME1); \
- if ((NAME)[0] == '.' && (NAME)[1] == 'L') \
- fprintf (FILE, "%s", NAME); \
- else \
- { \
- if (!ASM_NAME_P (NAME1)) \
- fprintf (FILE, "%s", user_label_prefix); \
- fprintf (FILE, "%s", NAME); \
- } \
-} while (0)
-
-/* This is how to output the definition of a user-level label named NAME,
- such as the label on a static function or variable NAME. */
-#define ASM_OUTPUT_LABEL(FILE, NAME) \
-do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
-
-#define ASM_NAME_P(NAME) ( NAME[0]=='*')
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-/* We work around a dwarfout.c deficiency by watching for labels from it and
- not adding the '_' prefix. There is a comment in
- dwarfout.c that says it should be using ASM_OUTPUT_INTERNAL_LABEL. */
-#define ASM_OUTPUT_LABELREF(FILE, NAME1) \
-do { \
- const char *NAME; \
- NAME = (*targetm.strip_name_encoding)(NAME1); \
- if ((NAME)[0] == '.' && (NAME)[1] == 'L') \
- fprintf (FILE, "%s", NAME); \
- else \
- { \
- if (!ASM_NAME_P (NAME1)) \
- fprintf (FILE, "%s", user_label_prefix); \
- fprintf (FILE, "%s", NAME); \
- } \
-} while (0)
-
-/* This is how to output a reference to a symbol_ref / label_ref as
- (part of) an operand. To disambiguate from register names like
- a1 / a2 / status etc, symbols are preceded by '@'. */
-#define ASM_OUTPUT_SYMBOL_REF(FILE,SYM) \
- ASM_OUTPUT_LABEL_REF ((FILE), XSTR ((SYM), 0))
-#define ASM_OUTPUT_LABEL_REF(FILE,STR) \
- do \
- { \
- fputc ('@', file); \
- assemble_name ((FILE), (STR)); \
- } \
- while (0)
-
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
-do { \
- if ((LOG) != 0) fprintf (FILE, "\t.align %d\n", 1 << (LOG)); \
-} while (0)
+#define TARGET_CPU_CPP_BUILTINS() arc64_cpu_cpp_builtins (pfile)
#define CASE_VECTOR_MODE Pmode
+/* 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 "#"
+
+/* To be used fot "U" options of asm_fprintf. */
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "@"
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ fprintf(FILE, "\t.align\t%d\n", (int)LOG)
+
/* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */
#undef ASM_APP_ON
@@ -446,24 +413,41 @@ do { \
#undef ASM_APP_OFF
#define ASM_APP_OFF ""
+/* Section selection. */
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global\t"
+
+#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"
+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata"
+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss"
+
+/* Expression whose value is a string, including spacing, containing
+ the assembler operation to identify the following data as
+ initialization/termination code. If not defined, GCC will assume
+ such a section does not exist. */
+#define INIT_SECTION_ASM_OP "\t.section\t.init"
+#define FINI_SECTION_ASM_OP "\t.section\t.fini"
+
/* All the work done in PROFILE_HOOK, but still required. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(STREAM, LABELNO) do { } while (0)
#define NO_PROFILE_COUNTERS 1
-/* ASM_OUTPUT_ALIGNED_DECL_LOCAL (STREAM, DECL, NAME, SIZE, ALIGNMENT)
- Define this macro when you need to see the variable's decl in order to
- chose what to output. */
-#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGN) \
- do { \
- ASM_OUTPUT_ALIGN (STREAM, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
- ASM_OUTPUT_TYPE_DIRECTIVE (STREAM, NAME, "object"); \
- ASM_OUTPUT_SIZE_DIRECTIVE (STREAM, NAME, SIZE); \
- ASM_OUTPUT_LABEL (STREAM, NAME); \
- } while (0);
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP "\t.global\t"
+/* Tell crtstuff.c we're using ELF. */
+#define OBJECT_FORMAT_ELF
+
+/* Called by crtstuff.c to make calls to function FUNCTION that are defined in
+ SECTION_OP, and then to switch back to text section. */
+#undef CRT_CALL_STATIC_FUNCTION
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n\t" \
+ "add r12,pcl,@" USER_LABEL_PREFIX #FUNC "@pcl\n\t" \
+ "jl [r12]\n" \
+ TEXT_SECTION_ASM_OP);
#endif /* GCC_ARC64_H */
diff --git a/gcc/config/arc64/arc64.md b/gcc/config/arc64/arc64.md
index 84fbc8aba7f34..cfbbc95e7673e 100644
--- a/gcc/config/arc64/arc64.md
+++ b/gcc/config/arc64/arc64.md
@@ -92,6 +92,19 @@
;; This code iterator allows the shifts supported in arithmetic instructions
(define_code_iterator ASHIFT [ashift ashiftrt lshiftrt])
+;; Iterates over the SETcc instructions.
+(define_code_iterator SETCC [eq ne gt lt ge le ltu geu])
+(define_code_attr cctab [(eq "eq")
+ (ne "ne")
+ (lt "lt")
+ (ge "ge")
+ (le "le")
+ (gt "gt")
+ (ltu "lo")
+ (leu "NA")
+ (geu "hs")
+ (gtu "NA")])
+
;; -------------------------------------------------------------------
;; Code Attributes
;; -------------------------------------------------------------------
@@ -147,7 +160,7 @@
;; -------------------------------------------------------------------
(define_attr "type" "move, jl, bl, jump, branch, branchcc,
-return, compare, nop"
+return, compare, nop, setcc"
(const_string "move"))
(define_attr "iscompact" "yes,no,maybe" (const_string "no"))
@@ -169,8 +182,8 @@ return, compare, nop"
(match_operand:ALLI 1 "general_operand"))]
""
"
-// if (arc64_prepare_move_operands (operands[0], operands[1], mode))
-// DONE;
+ if (arc64_prepare_move_operands (operands[0], operands[1], mode))
+ DONE;
"
)
@@ -281,8 +294,8 @@ return, compare, nop"
(clobber (reg:DI BLINK_REGNUM))])]
""
{
-// arc64_expand_call (NULL_RTX, operands[0], false);
-// DONE;
+ arc64_expand_call (NULL_RTX, operands[0], false);
+ DONE;
}
)
@@ -308,8 +321,8 @@ return, compare, nop"
""
"
{
-// arc64_expand_call (operands[0], operands[1], false);
-// DONE;
+ arc64_expand_call (operands[0], operands[1], false);
+ DONE;
}"
)
@@ -335,8 +348,8 @@ return, compare, nop"
(use (match_operand 2 "" ""))])]
""
{
-// arc64_expand_call (NULL_RTX, operands[0], true);
-// DONE;
+ arc64_expand_call (NULL_RTX, operands[0], true);
+ DONE;
}
)
@@ -348,8 +361,8 @@ return, compare, nop"
(use (match_operand 3 "" ""))])]
""
{
-// arc64_expand_call (operands[0], operands[1], true);
-// DONE;
+ arc64_expand_call (operands[0], operands[1], true);
+ DONE;
}
)
@@ -417,9 +430,9 @@ return, compare, nop"
(pc)))]
""
"
-// operands[1] = arc64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
-// operands[2]);
-// operands[2] = const0_rtx;
+ operands[1] = arc64_gen_compare_reg (GET_CODE (operands[0]), operands[1],
+ operands[2]);
+ operands[2] = const0_rtx;
"
)
@@ -434,19 +447,17 @@ return, compare, nop"
"b%m0%!\\t%l2"
[(set_attr "type" "branchcc")
(set_attr "iscompact" "maybe")
-; (set (attr "length")
-; [(cond
-; [(and (match_operand 1 "equality_comparison_operator" "")
-; (and (ge (minus (match_dup 2) (pc)) (const_int -512))
-; (le (minus (match_dup 2) (pc)) (const_int 506))))
-; (const_int 2)
-;
-; (and (ge (minus (match_dup 2) (pc)) (const_int -62))
-; (le (minus (match_dup 2) (pc)) (const_int 60)))
-; (const_int 2)]
- ; (const_int 4))])]
- ]
- )
+ (set (attr "length")
+ (cond
+ [(and (match_operand 1 "equality_comparison_operator" "")
+ (and (ge (minus (match_dup 2) (pc)) (const_int -512))
+ (le (minus (match_dup 2) (pc)) (const_int 506))))
+ (const_int 2)
+
+ (and (ge (minus (match_dup 2) (pc)) (const_int -62))
+ (le (minus (match_dup 2) (pc)) (const_int 60)))
+ (const_int 2)]
+ (const_int 4)))])
(define_expand "prologue"
[(clobber (const_int 0))]
@@ -602,21 +613,76 @@ return, compare, nop"
;; Store-flag and conditional select insns
;; -------------------------------------------------------------------
-;(define_expand "cstore4"
-; [(set (match_operand:SI 0 "register_operand")
-; (match_operator:SI 1 "arc64_comparison_operator"
-; [(match_operand:GPI 2 "register_operand")
-; (match_operand:GPI 3 "arc64_plus_operand")]))]
-; ""
-; )
-
-;(define_expand "movcc"
-; [(set (match_operand:ALLI 0 "register_operand")
-; (if_then_else:ALLI (match_operand 1 "arc64_comparison_operator")
-; (match_operand:ALLI 2 "register_operand")
-; (match_operand:ALLI 3 "register_operand")))]
-; ""
-; )
+(define_expand "cstore4"
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "comparison_operator"
+ [(match_operand:GPI 2 "nonmemory_operand")
+ (match_operand:GPI 3 "nonmemory_operand")]))]
+ ""
+ {
+ if (!register_operand (operands[2], mode))
+ operands[2] = force_reg (mode, operands[2]);
+ })
+
+;; SETcc instructions
+(define_insn "set"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r, r, r,r,r")
+ (SETCC:SI (match_operand:GPI 1 "register_operand" "0,r, 0, r, 0,0,r")
+ (match_operand:GPI 2 "nonmemory_operand" "r,r,U06S0,U06S0,S12S0,n,n")))]
+ ""
+ "set%?\\t%0,%1,%2"
+ [(set_attr "length" "4,4,4,4,4,8,8")
+ (set_attr "type" "setcc")
+ (set_attr "predicable" "yes,no,yes,no,no,yes,no")])
+
+;; Special cases of SETCC
+(define_insn_and_split "*sethi"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
+ (gtu:SI (match_operand:GPI 1 "register_operand" "r,r, r,r")
+ (match_operand:GPI 2 "nonmemory_operand" "0,r,U06M1,n")))]
+ ""
+ "setlo%?\\t%0,%2,%1"
+ "reload_completed
+ && CONST_INT_P (operands[2])
+ && satisfies_constraint_U06M1 (operands[2])"
+ [(const_int 0)]
+ "{
+ /* sethi a,b,u6 => seths a,b,u6 + 1. */
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ emit_insn (gen_seths (operands[0], operands[1], operands[2]));
+ DONE;
+ }"
+ [(set_attr "length" "4,4,4,8")
+ (set_attr "type" "setcc")
+ (set_attr "predicable" "yes,no,no,no")])
+
+(define_insn_and_split "*setls"
+ [(set (match_operand:SI 0 "register_operand" "=r,r, r,r")
+ (leu:SI (match_operand:GPI 1 "register_operand" "r,r, r,r")
+ (match_operand:GPI 2 "nonmemory_operand" "0,r,U06M1,n")))]
+ ""
+ "seths%?\\t%0,%2,%1"
+ "reload_completed
+ && satisfies_constraint_U06M1 (operands[2])"
+ [(const_int 0)]
+ "{
+ /* setls a,b,u6 => setlo a,b,u6 + 1. */
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ emit_insn (gen_setlo (operands[0], operands[1], operands[2]));
+ DONE;
+ }"
+ [(set_attr "length" "4,4,4,8")
+ (set_attr "type" "setcc")
+ (set_attr "predicable" "yes,no,no,no")])
+
+
+;;(define_expand "movcc"
+;; [(set (match_operand:ALLI 0 "register_operand")
+;; (if_then_else:ALLI (match_operand 1 "comparison_operator")
+;; (match_operand:ALLI 2 "register_operand")
+;; (match_operand:ALLI 3 "register_operand")))]
+;; ""
+;; )
;; -------------------------------------------------------------------
;; Logical operations
diff --git a/gcc/config/arc64/constraints.md b/gcc/config/arc64/constraints.md
index 0307e82ebe7ba..4da6f6fd1c634 100644
--- a/gcc/config/arc64/constraints.md
+++ b/gcc/config/arc64/constraints.md
@@ -80,6 +80,12 @@
is a symbol reference allowed by the BL instruction"
(match_code "symbol_ref"))
+(define_constraint "U06M1"
+ "@internal
+ An unsigned 6-bit integer constant, up to 62."
+ (and (match_code "const_int")
+ (match_test "UNSIGNED_INT6 (ival - 1)")))
+
;---------------------------------------------------------