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)"))) + ;---------------------------------------------------------