;; Constraint definitions for Synopsys DesignWare ARC. ;; Copyright (C) 2007-2021 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 constraints

; Most instructions accept arbitrary core registers for their inputs, even ; if the core register in question cannot be written to, like the multiply ; result registers of ARC600. ; First, define a class for core registers that can be read cheaply. This ; is most or all core registers for ARC600, but only r0-r31 for ARC700 (define_register_constraint “c” “GENERAL_REGS” “Legacy, core register @code{r0}-@code{r31}, @code{ap},@code{pcl}”)

; All core regs - e.g. for when we must have a way to reload a register. (define_register_constraint “Rac” “GENERAL_REGS” “Legacy, core register @code{r0}-@code{r60}, @code{ap},@code{pcl}”)

; Some core registers (.e.g lp_count) aren‘t general registers because they ; can’t be used as the destination of a multi-cycle operation like ; load and/or multiply, yet they are still writable in the sense that ; register-register moves and single-cycle arithmetic (e.g “add”, “and”, ; but not “mpy”) can write to them. (define_register_constraint “w” “GENERAL_REGS” “Legacy, writable core register: @code{r0}-@code{r31}, @code{r60}, nonfixed core register”)

(define_register_constraint “W” “GENERAL_REGS” “Legacy, writable core register except @code{LP_COUNT} (@code{r60}): @code{r0}-@code{r31}, nonfixed core register”)

(define_constraint “l” “@internal Loop count register @code{r60}” (and (match_code “reg”) (match_test “REGNO (op) == LP_COUNT”)))

(define_register_constraint “x” “R0_REGS” “@code{R0} register.”)

(define_register_constraint “q” “ARCOMPACT16_REGS” “Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}”)

; NPS400 bitfield instructions require registers from the r0-r3,r12-r15 ; range, and thus we need a register class and constraint that works ; independently of size optimization. (define_register_constraint “Rrq” “TARGET_RRQ_CLASS ? ARCOMPACT16_REGS : NO_REGS” “Registers usable in NPS400 bitfield instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}”)

(define_register_constraint “D” “DOUBLE_REGS” “ARC FPX (dpfp) 64-bit registers. @code{D0}, @code{D1}”)

(define_register_constraint “d” “SIMD_DMA_CONFIG_REGS” “@internal ARC SIMD DMA configuration registers @code{di0}-@code{di7}, @code{do0}-@code{do7}”)

(define_register_constraint “v” “SIMD_VR_REGS” “ARC SIMD 128-bit registers @code{VR0}-@code{VR23}”)

; We could allow call-saved registers for sibling calls if we restored them ; in the delay slot of the call. However, that would not allow to adjust the ; stack pointer afterwards, so the call-saved register would have to be ; restored from a call-used register that was just loaded with the value ; before. So sticking to call-used registers for sibcalls will likely ; generate better code overall. (define_register_constraint “Rsc” “SIBCALL_REGS” “@internal Sibling call register”)

;; Integer constraints

(define_constraint “I” “@internal A signed 12-bit integer constant.” (and (match_code “const_int”) (match_test “SIGNED_INT12 (ival)”)))

(define_constraint “K” “@internal A 3-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT3 (ival)”)))

(define_constraint “L” “@internal A 6-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT6 (ival)”)))

(define_constraint “CnL” “@internal One's complement of a 6-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT6 (~ival)”)))

(define_constraint “CmL” “@internal Two's complement of a 6-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT6 (-ival)”)))

(define_constraint “C16” “@internal A 16-bit signed integer constant” (and (match_code “const_int”) (match_test “SIGNED_INT16 (ival)”)))

(define_constraint “M” “@internal A 5-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT5 (ival)”)))

(define_constraint “N” “@internal Integer constant 1” (and (match_code “const_int”) (match_test “IS_ONE (ival)”)))

(define_constraint “O” “@internal A 7-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT7 (ival)”)))

(define_constraint “P” “@internal An 8-bit unsigned integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT8 (ival)”)))

(define_constraint “C_0” “@internal Zero” (and (match_code “const_int”) (match_test “ival == 0”)))

(define_constraint “Cn0” “@internal Negative or zero” (and (match_code “const_int”) (match_test “ival <= 0”)))

(define_constraint “Cca” “@internal Conditional or three-address add / sub constant” (and (match_code “const_int”) (match_test “ival == (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 31) || (ival >= -0x1f8 && ival <= 0x1f8 && ((ival >= 0 ? ival : -ival) <= 0x3f * (ival & -ival)))”)))

; intersection of “O” and “Cca”. (define_constraint “CL2” “@internal A 6-bit unsigned integer constant times 2” (and (match_code “const_int”) (match_test “!(ival & ~126)”)))

(define_constraint “CM4” “@internal A 5-bit unsigned integer constant times 4” (and (match_code “const_int”) (match_test “!(ival & ~124)”)))

(define_constraint “Csp” “@internal A valid stack pointer offset for a short add” (and (match_code “const_int”) (match_test “!(ival & ~124) || !(-ival & ~124)”)))

(define_constraint “C2a” “@internal Unconditional two-address add / sub constant” (and (match_code “const_int”) (match_test “ival == (HOST_WIDE_INT) (HOST_WIDE_INT_M1U << 31) || (ival >= -0x4000 && ival <= 0x4000 && ((ival >= 0 ? ival : -ival) <= 0x7ff * (ival & -ival)))”)))

(define_constraint “C0p” “@internal power of two” (and (match_code “const_int”) (match_test “IS_POWEROF2_P (ival & 0xffffffff)”)))

(define_constraint “C1p” “@internal constant such that x+1 is a power of two, and x != 0” (and (match_code “const_int”) (match_test “ival && IS_POWEROF2_P (ival + 1)”)))

(define_constraint “C2p” “@internal constant such that (~x)+1 is a power of two, and x < -1” (and (match_code “const_int”) (match_test “TARGET_V2 && (ival < -1) && IS_POWEROF2_P ((~ival) + 1)”)))

(define_constraint “C3p” “@internal constant int used to select xbfu a,b,u6 instruction. The values accepted are 1 and 2.” (and (match_code “const_int”) (match_test “((ival == 1) || (ival == 2))”)))

(define_constraint “Ccp” “@internal constant such that ~x (one's Complement) is a power of two” (and (match_code “const_int”) (match_test “IS_POWEROF2_P (~ival)”)))

(define_constraint “Cux” “@internal constant such that AND gives an unsigned extension” (and (match_code “const_int”) (match_test “ival == 0xff || ival == 0xffff”)))

(define_constraint “Chs” “@internal constant for a highpart that can be checked with a shift (asr.f 0,rn,m)” (and (match_code “const_int”) (match_test “IS_POWEROF2_P (-ival)”) (match_test “TARGET_BARREL_SHIFTER”)))

(define_constraint “Clo” “@internal constant that fits into 16 lower bits, for movl” (and (match_code “const_int”) (match_test “TARGET_NPS_BITOPS”) (match_test “(ival & ~0xffffU) == 0”)))

(define_constraint “Chi” “@internal constant that fits into 16 higher bits, for movh_i” (and (match_code “const_int”) (match_test “TARGET_NPS_BITOPS”) (match_test “trunc_int_for_mode (ival >> 16, HImode) << 16 == ival”)))

(define_constraint “Cbf” “@internal a mask for a bit field, for AND using movb_i” (and (match_code “const_int”) (match_test “TARGET_NPS_BITOPS”) (match_test “IS_POWEROF2_OR_0_P (ival + (ival & -ival))”)))

(define_constraint “Cbn” “@internal a constant integer, valid only if TARGET_NPS_BITOPS is true” (and (match_code “const_int”) (match_test “TARGET_NPS_BITOPS”)))

(define_constraint “C18” “@internal 1,2,4 or 8” (and (match_code “const_int”) (match_test “ival == 1 || ival == 2 || ival == 4 || ival == 8”)))

(define_constraint “Cbi” “@internal constant that can be loaded with movbi.cl” (and (match_code “const_int”) (match_test “TARGET_NPS_BITOPS”) (match_test “!ival || ((ival & 0xffffffffUL) >> exact_log2 (ival & -ival) <= 0xff)”)))

(define_constraint “C0x” “@internal special const_int pattern used to split ior insns” (and (match_code “const_int”) (match_test “optimize_size”) (match_test “arc_check_ior_const (ival)”)))

(define_constraint “Cax” “@internal special const_int pattern used to split mov insns” (and (match_code “const_int”) (match_test “optimize_size”) (match_test “arc_check_mov_const (ival)”)))

;; Floating-point constraints

(define_constraint “G” “@internal A 32-bit constant double value” (and (match_code “const_double”) (match_test “arc_double_limm_p (op)”)))

(define_constraint “H” “@internal All const_double values (including 64-bit values)” (and (match_code “const_double”) (match_test “1”)))

(define_constraint “CfZ” “@internal Match a floating-point zero” (and (match_code “const_double”) (match_test “op == CONST0_RTX (SFmode)”)))

;; Memory constraints (define_memory_constraint “T” “@internal A valid memory operand for ARCompact load instructions” (and (match_code “mem”) (match_test “compact_memory_operand_p (op, mode, false, false)”)))

(define_memory_constraint “Uts” “@internal A valid memory operand for ARCompact load instructions scaled” (and (match_code “mem”) (match_test “compact_memory_operand_p (op, mode, false, TARGET_CODE_DENSITY)”)))

(define_memory_constraint “S” “@internal A valid memory operand for ARCompact store instructions” (and (match_code “mem”) (match_test “compact_store_memory_operand (op, VOIDmode)”)))

(define_memory_constraint “Uex” “@internal A valid memory operand for limm-free extend instructions” (and (match_code “mem”) (match_test “!cmem_address (XEXP (op, 0), SImode)”) (not (match_operand 0 “long_immediate_loadstore_operand”))))

(define_memory_constraint “Usd” “@internal A valid small-data memory operand for ARCompact instructions” (and (match_code “mem”) (match_test “compact_sda_memory_operand (op, VOIDmode, true)”)))

; Usc constant is only used for storing long constants, hence we can ; have only [b,s9], and [b] types of addresses. (define_memory_constraint “Usc” “@internal A valid memory operand for storing constants” (and (match_code “mem”) (match_test “!CONSTANT_P (XEXP (op,0))”)))

(define_constraint “Us<” “@internal Stack pre-decrement” (and (match_code “mem”) (match_test “GET_CODE (XEXP (op, 0)) == PRE_DEC”) (match_test “REG_P (XEXP (XEXP (op, 0), 0))”) (match_test “REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG”)))

(define_constraint “Us>” “@internal Stack post-increment” (and (match_code “mem”) (match_test “GET_CODE (XEXP (op, 0)) == POST_INC”) (match_test “REG_P (XEXP (XEXP (op, 0), 0))”) (match_test “REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG”)))

(define_constraint “Ucm” “@internal cmem access” (and (match_code “mem”) (match_test “TARGET_NPS_CMEM && cmem_address (XEXP (op, 0), VOIDmode)”)))

;; General constraints

(define_constraint “Cbr” “Branch destination” (ior (and (match_code “symbol_ref”) (match_test “!arc_is_longcall_p (op)”)) (match_code “label_ref”)))

(define_constraint “Cbp” “predicable branch/call destination” (ior (and (match_code “symbol_ref”) (match_test “arc_is_shortcall_p (op)”)) (match_code “label_ref”)))

(define_constraint “Cji” “JLI call” (and (match_code “symbol_ref”) (match_test “TARGET_CODE_DENSITY”) (match_test “arc_is_jli_call_p (op)”)))

(define_constraint “Csc” “Secure call” (and (match_code “symbol_ref”) (match_test “TARGET_CODE_DENSITY”) (match_test “TARGET_EM”) (match_test “arc_is_secure_call_p (op)”)))

(define_constraint “Cpc” “pc-relative constant” (match_test “arc_legitimate_pic_addr_p (op)”))

(define_constraint “Clb” “label” (and (match_code “label_ref”) (match_test “arc_text_label (as_a <rtx_insn *> (XEXP (op, 0)))”)))

(define_constraint “Cal” “constant for arithmetic/logical operations” (match_test “immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op)”))

(define_constraint “C32” “32 bit constant for arithmetic/logical operations” (match_test “immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op) && !satisfies_constraint_I (op)”))

(define_constraint “Csz” “a 32 bit constant avoided when compiling for size.” (match_test “immediate_operand (op, VOIDmode) && !arc_legitimate_pic_addr_p (op) && !(satisfies_constraint_I (op) && optimize_size)”))

; Note that the ‘cryptic’ register constraints will not make reload use the ; associated class to reload into, but this will not penalize reloading of any ; other operands, or using an alternate part of the same alternative.

; Rcq is different in three important ways from a register class constraint: ; - It does not imply a register class, hence reload will not use it to drive ; reloads. ; - It matches even when there is no register class to describe its accepted ; set; not having such a set again lessens the impact on register allocation. ; - It won't match when the instruction is conditionalized by the ccfsm. (define_constraint “Rcq” “@internal Cryptic q - for short insn generation while not affecting register allocation Registers usable in ARCompact 16-bit instructions: @code{r0}-@code{r3}, @code{r12}-@code{r15}” (and (match_code “reg”) (match_test “TARGET_Rcq && !arc_ccfsm_cond_exec_p () && IN_RANGE (REGNO (op) ^ 4, 4, 11)”)))

; If we need a reload, we generally want to steer reload to use three-address ; alternatives in preference of two-address alternatives, unless the ; three-address alternative introduces a LIMM that is unnecessary for the ; two-address alternative. (define_constraint “Rcw” “@internal Cryptic w - for use in early alternatives with matching constraint” (and (match_code “reg”) (match_test “TARGET_Rcw && REGNO (op) < FIRST_PSEUDO_REGISTER && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], REGNO (op))”)))

(define_constraint “Rcr” “@internal Cryptic r - for use in early alternatives with matching constraint” (and (match_code “reg”) (match_test “TARGET_Rcw && REGNO (op) < FIRST_PSEUDO_REGISTER && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], REGNO (op))”)))

(define_constraint “Rcb” “@internal Stack Pointer register @code{r28} - do not reload into its class” (and (match_code “reg”) (match_test “REGNO (op) == 28”)))

(define_constraint “Rck” “@internal blink (usful for push_s / pop_s)” (and (match_code “reg”) (match_test “REGNO (op) == 31”)))

(define_constraint “Rcc” “@internal Condition Codes” (and (match_code “reg”) (match_test “cc_register (op, VOIDmode)”)))

(define_constraint “Ral” “@internal Accumulator register @code{ACCL} - do not reload into its class” (and (match_code “reg”) (match_test “REGNO (op) == ACCL_REGNO”)))

(define_constraint “Q” “@internal Integer constant zero” (and (match_code “const_int”) (match_test “IS_ZERO (ival)”)))

(define_constraint “Cm1” “@internal Integer signed constant in the interval [-1,6]” (and (match_code “const_int”) (match_test “(ival >= -1) && (ival <=6)”) (match_test “TARGET_V2”)))

(define_constraint “Cm2” “@internal A signed 9-bit integer constant.” (and (match_code “const_int”) (match_test “(ival >= -256) && (ival <=255)”)))

(define_constraint “Cm3” “@internal A signed 6-bit integer constant.” (and (match_code “const_int”) (match_test “(ival >= -32) && (ival <=31)”) (match_test “TARGET_V2”)))

(define_constraint “C62” “@internal An unsigned 6-bit integer constant, up to 62.” (and (match_code “const_int”) (match_test “UNSIGNED_INT6 (ival - 1)”)))

;; Memory constraint used for atomic ops. (define_memory_constraint “ATO” “A memory with only a base register” (match_operand 0 “mem_noofs_operand”))

(define_constraint “J12” “@internal An unsigned 12-bit integer constant.” (and (match_code “const_int”) (match_test “UNSIGNED_INT12 (ival)”)))

(define_constraint “J16” “@internal An unsigned 16-bit integer constant” (and (match_code “const_int”) (match_test “UNSIGNED_INT16 (ival)”)))

; Memory addresses suited for code density load ops (define_memory_constraint “Ucd” “@internal A valid memory operand for use with code density load ops” (and (match_code “mem”) (match_test “compact_memory_operand_p (op, mode, true, false)”) (match_test “TARGET_V2”)))

(define_register_constraint “h” “TARGET_V2 ? AC16_H_REGS : NO_REGS” “5-bit h register set except @code{r30} and @code{r29}: @code{r0}-@code{r31}, nonfixed core register”)

; Code density registers (define_register_constraint “Rcd” “TARGET_CODE_DENSITY ? R0R3_CD_REGS : NO_REGS” “@internal core register @code{r0}-@code{r3}”)

(define_register_constraint “Rsd” “TARGET_CODE_DENSITY ? R0R1_CD_REGS : NO_REGS” “@internal core register @code{r0}-@code{r1}”)

(define_register_constraint “Rzd” “TARGET_CODE_DENSITY ? R0_REGS : NO_REGS” “@internal @code{r0} register for code density instructions.”)