1 1.1 mrg /* Subroutines used for LoongArch code generation. 2 1.1 mrg Copyright (C) 2021-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Loongson Ltd. 4 1.1 mrg Based on MIPS and RISC-V target for GNU compiler. 5 1.1 mrg 6 1.1 mrg This file is part of GCC. 7 1.1 mrg 8 1.1 mrg GCC is free software; you can redistribute it and/or modify 9 1.1 mrg it under the terms of the GNU General Public License as published by 10 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 11 1.1 mrg any later version. 12 1.1 mrg 13 1.1 mrg GCC is distributed in the hope that it will be useful, 14 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 mrg GNU General Public License for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU General Public License 19 1.1 mrg along with GCC; see the file COPYING3. If not see 20 1.1 mrg <http://www.gnu.org/licenses/>. */ 21 1.1 mrg 22 1.1 mrg #define IN_TARGET_CODE 1 23 1.1 mrg 24 1.1 mrg #include "config.h" 25 1.1 mrg #include "system.h" 26 1.1 mrg #include "coretypes.h" 27 1.1 mrg #include "backend.h" 28 1.1 mrg #include "target.h" 29 1.1 mrg #include "rtl.h" 30 1.1 mrg #include "tree.h" 31 1.1 mrg #include "memmodel.h" 32 1.1 mrg #include "gimple.h" 33 1.1 mrg #include "cfghooks.h" 34 1.1 mrg #include "df.h" 35 1.1 mrg #include "tm_p.h" 36 1.1 mrg #include "stringpool.h" 37 1.1 mrg #include "attribs.h" 38 1.1 mrg #include "optabs.h" 39 1.1 mrg #include "regs.h" 40 1.1 mrg #include "emit-rtl.h" 41 1.1 mrg #include "recog.h" 42 1.1 mrg #include "cgraph.h" 43 1.1 mrg #include "diagnostic.h" 44 1.1 mrg #include "insn-attr.h" 45 1.1 mrg #include "output.h" 46 1.1 mrg #include "alias.h" 47 1.1 mrg #include "fold-const.h" 48 1.1 mrg #include "varasm.h" 49 1.1 mrg #include "stor-layout.h" 50 1.1 mrg #include "calls.h" 51 1.1 mrg #include "explow.h" 52 1.1 mrg #include "expr.h" 53 1.1 mrg #include "libfuncs.h" 54 1.1 mrg #include "reload.h" 55 1.1 mrg #include "common/common-target.h" 56 1.1 mrg #include "langhooks.h" 57 1.1 mrg #include "cfgrtl.h" 58 1.1 mrg #include "cfganal.h" 59 1.1 mrg #include "sched-int.h" 60 1.1 mrg #include "gimplify.h" 61 1.1 mrg #include "target-globals.h" 62 1.1 mrg #include "tree-pass.h" 63 1.1 mrg #include "context.h" 64 1.1 mrg #include "builtins.h" 65 1.1 mrg #include "rtl-iter.h" 66 1.1 mrg 67 1.1 mrg /* This file should be included last. */ 68 1.1 mrg #include "target-def.h" 69 1.1 mrg 70 1.1 mrg /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ 71 1.1 mrg #define UNSPEC_ADDRESS_P(X) \ 72 1.1 mrg (GET_CODE (X) == UNSPEC \ 73 1.1 mrg && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ 74 1.1 mrg && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) 75 1.1 mrg 76 1.1 mrg /* Extract the symbol or label from UNSPEC wrapper X. */ 77 1.1 mrg #define UNSPEC_ADDRESS(X) XVECEXP (X, 0, 0) 78 1.1 mrg 79 1.1 mrg /* Extract the symbol type from UNSPEC wrapper X. */ 80 1.1 mrg #define UNSPEC_ADDRESS_TYPE(X) \ 81 1.1 mrg ((enum loongarch_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) 82 1.1 mrg 83 1.1 mrg /* True if INSN is a loongarch.md pattern or asm statement. */ 84 1.1 mrg /* ??? This test exists through the compiler, perhaps it should be 85 1.1 mrg moved to rtl.h. */ 86 1.1 mrg #define USEFUL_INSN_P(INSN) \ 87 1.1 mrg (NONDEBUG_INSN_P (INSN) \ 88 1.1 mrg && GET_CODE (PATTERN (INSN)) != USE \ 89 1.1 mrg && GET_CODE (PATTERN (INSN)) != CLOBBER) 90 1.1 mrg 91 1.1 mrg /* True if bit BIT is set in VALUE. */ 92 1.1 mrg #define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0) 93 1.1 mrg 94 1.1 mrg /* Classifies an address. 95 1.1 mrg 96 1.1 mrg ADDRESS_REG 97 1.1 mrg A natural register + offset address. The register satisfies 98 1.1 mrg loongarch_valid_base_register_p and the offset is a const_arith_operand. 99 1.1 mrg 100 1.1 mrg ADDRESS_REG_REG 101 1.1 mrg A base register indexed by (optionally scaled) register. 102 1.1 mrg 103 1.1 mrg ADDRESS_CONST_INT 104 1.1 mrg A signed 16-bit constant address. 105 1.1 mrg 106 1.1 mrg ADDRESS_SYMBOLIC: 107 1.1 mrg A constant symbolic address. */ 108 1.1 mrg enum loongarch_address_type 109 1.1 mrg { 110 1.1 mrg ADDRESS_REG, 111 1.1 mrg ADDRESS_REG_REG, 112 1.1 mrg ADDRESS_CONST_INT, 113 1.1 mrg ADDRESS_SYMBOLIC 114 1.1 mrg }; 115 1.1 mrg 116 1.1 mrg 117 1.1 mrg /* Information about an address described by loongarch_address_type. 118 1.1 mrg 119 1.1 mrg ADDRESS_CONST_INT 120 1.1 mrg No fields are used. 121 1.1 mrg 122 1.1 mrg ADDRESS_REG 123 1.1 mrg REG is the base register and OFFSET is the constant offset. 124 1.1 mrg 125 1.1 mrg ADDRESS_REG_REG 126 1.1 mrg A base register indexed by (optionally scaled) register. 127 1.1 mrg 128 1.1 mrg ADDRESS_SYMBOLIC 129 1.1 mrg SYMBOL_TYPE is the type of symbol that the address references. */ 130 1.1 mrg struct loongarch_address_info 131 1.1 mrg { 132 1.1 mrg enum loongarch_address_type type; 133 1.1 mrg rtx reg; 134 1.1 mrg rtx offset; 135 1.1 mrg enum loongarch_symbol_type symbol_type; 136 1.1 mrg }; 137 1.1 mrg 138 1.1 mrg /* Method of loading instant numbers: 139 1.1 mrg 140 1.1 mrg METHOD_NORMAL: 141 1.1 mrg Load 0-31 bit of the immediate number. 142 1.1 mrg 143 1.1 mrg METHOD_LU32I: 144 1.1 mrg Load 32-51 bit of the immediate number. 145 1.1 mrg 146 1.1 mrg METHOD_LU52I: 147 1.1 mrg Load 52-63 bit of the immediate number. 148 1.1 mrg 149 1.1 mrg METHOD_INSV: 150 1.1 mrg immediate like 0xfff00000fffffxxx 151 1.1 mrg */ 152 1.1 mrg enum loongarch_load_imm_method 153 1.1 mrg { 154 1.1 mrg METHOD_NORMAL, 155 1.1 mrg METHOD_LU32I, 156 1.1 mrg METHOD_LU52I, 157 1.1 mrg METHOD_INSV 158 1.1 mrg }; 159 1.1 mrg 160 1.1 mrg struct loongarch_integer_op 161 1.1 mrg { 162 1.1 mrg enum rtx_code code; 163 1.1 mrg HOST_WIDE_INT value; 164 1.1 mrg enum loongarch_load_imm_method method; 165 1.1 mrg }; 166 1.1 mrg 167 1.1 mrg /* The largest number of operations needed to load an integer constant. 168 1.1 mrg The worst accepted case for 64-bit constants is LU12I.W,LU32I.D,LU52I.D,ORI 169 1.1 mrg or LU12I.W,LU32I.D,LU52I.D,ADDI.D DECL_ASSEMBLER_NAME. */ 170 1.1 mrg #define LARCH_MAX_INTEGER_OPS 4 171 1.1 mrg 172 1.1 mrg /* Arrays that map GCC register numbers to debugger register numbers. */ 173 1.1 mrg int loongarch_dwarf_regno[FIRST_PSEUDO_REGISTER]; 174 1.1 mrg 175 1.1 mrg /* Index [M][R] is true if register R is allowed to hold a value of mode M. */ 176 1.1 mrg static bool loongarch_hard_regno_mode_ok_p[MAX_MACHINE_MODE] 177 1.1 mrg [FIRST_PSEUDO_REGISTER]; 178 1.1 mrg 179 1.1 mrg /* Index C is true if character C is a valid PRINT_OPERAND punctation 180 1.1 mrg character. */ 181 1.1 mrg static bool loongarch_print_operand_punct[256]; 182 1.1 mrg 183 1.1 mrg /* Cached value of can_issue_more. This is cached in loongarch_variable_issue 184 1.1 mrg hook and returned from loongarch_sched_reorder2. */ 185 1.1 mrg static int cached_can_issue_more; 186 1.1 mrg 187 1.1 mrg /* Index R is the smallest register class that contains register R. */ 188 1.1 mrg const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = { 189 1.1 mrg GR_REGS, GR_REGS, GR_REGS, GR_REGS, 190 1.1 mrg JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 191 1.1 mrg JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 192 1.1 mrg SIBCALL_REGS, JIRL_REGS, SIBCALL_REGS, SIBCALL_REGS, 193 1.1 mrg SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, 194 1.1 mrg SIBCALL_REGS, GR_REGS, GR_REGS, JIRL_REGS, 195 1.1 mrg JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 196 1.1 mrg JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 197 1.1 mrg 198 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 199 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 200 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 201 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 202 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 203 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 204 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 205 1.1 mrg FP_REGS, FP_REGS, FP_REGS, FP_REGS, 206 1.1 mrg FCC_REGS, FCC_REGS, FCC_REGS, FCC_REGS, 207 1.1 mrg FCC_REGS, FCC_REGS, FCC_REGS, FCC_REGS, 208 1.1 mrg FRAME_REGS, FRAME_REGS 209 1.1 mrg }; 210 1.1 mrg 211 1.1 mrg /* Which cost information to use. */ 212 1.1 mrg static const struct loongarch_rtx_cost_data *loongarch_cost; 213 1.1 mrg 214 1.1 mrg /* Information about a single argument. */ 215 1.1 mrg struct loongarch_arg_info 216 1.1 mrg { 217 1.1 mrg /* True if the argument is at least partially passed on the stack. */ 218 1.1 mrg bool stack_p; 219 1.1 mrg 220 1.1 mrg /* The number of integer registers allocated to this argument. */ 221 1.1 mrg unsigned int num_gprs; 222 1.1 mrg 223 1.1 mrg /* The offset of the first register used, provided num_gprs is nonzero. 224 1.1 mrg If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS. */ 225 1.1 mrg unsigned int gpr_offset; 226 1.1 mrg 227 1.1 mrg /* The number of floating-point registers allocated to this argument. */ 228 1.1 mrg unsigned int num_fprs; 229 1.1 mrg 230 1.1 mrg /* The offset of the first register used, provided num_fprs is nonzero. */ 231 1.1 mrg unsigned int fpr_offset; 232 1.1 mrg }; 233 1.1 mrg 234 1.1 mrg /* Invoke MACRO (COND) for each fcmp.cond.{s/d} condition. */ 235 1.1 mrg #define LARCH_FP_CONDITIONS(MACRO) \ 236 1.1 mrg MACRO (f), \ 237 1.1 mrg MACRO (un), \ 238 1.1 mrg MACRO (eq), \ 239 1.1 mrg MACRO (ueq), \ 240 1.1 mrg MACRO (olt), \ 241 1.1 mrg MACRO (ult), \ 242 1.1 mrg MACRO (ole), \ 243 1.1 mrg MACRO (ule), \ 244 1.1 mrg MACRO (sf), \ 245 1.1 mrg MACRO (ngle), \ 246 1.1 mrg MACRO (seq), \ 247 1.1 mrg MACRO (ngl), \ 248 1.1 mrg MACRO (lt), \ 249 1.1 mrg MACRO (nge), \ 250 1.1 mrg MACRO (le), \ 251 1.1 mrg MACRO (ngt) 252 1.1 mrg 253 1.1 mrg /* Enumerates the codes above as LARCH_FP_COND_<X>. */ 254 1.1 mrg #define DECLARE_LARCH_COND(X) LARCH_FP_COND_##X 255 1.1 mrg enum loongarch_fp_condition 256 1.1 mrg { 257 1.1 mrg LARCH_FP_CONDITIONS (DECLARE_LARCH_COND) 258 1.1 mrg }; 259 1.1 mrg #undef DECLARE_LARCH_COND 260 1.1 mrg 261 1.1 mrg /* Index X provides the string representation of LARCH_FP_COND_<X>. */ 262 1.1 mrg #define STRINGIFY(X) #X 263 1.1 mrg const char *const 264 1.1 mrg loongarch_fp_conditions[16]= {LARCH_FP_CONDITIONS (STRINGIFY)}; 265 1.1 mrg #undef STRINGIFY 266 1.1 mrg 267 1.1 mrg /* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at 268 1.1 mrg least PARM_BOUNDARY bits of alignment, but will be given anything up 269 1.1 mrg to PREFERRED_STACK_BOUNDARY bits if the type requires it. */ 270 1.1 mrg 271 1.1 mrg static unsigned int 272 1.1 mrg loongarch_function_arg_boundary (machine_mode mode, const_tree type) 273 1.1 mrg { 274 1.1 mrg unsigned int alignment; 275 1.1 mrg 276 1.1 mrg /* Use natural alignment if the type is not aggregate data. */ 277 1.1 mrg if (type && !AGGREGATE_TYPE_P (type)) 278 1.1 mrg alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); 279 1.1 mrg else 280 1.1 mrg alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); 281 1.1 mrg 282 1.1 mrg return MIN (PREFERRED_STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment)); 283 1.1 mrg } 284 1.1 mrg 285 1.1 mrg /* If MODE represents an argument that can be passed or returned in 286 1.1 mrg floating-point registers, return the number of registers, else 0. */ 287 1.1 mrg 288 1.1 mrg static unsigned 289 1.1 mrg loongarch_pass_mode_in_fpr_p (machine_mode mode) 290 1.1 mrg { 291 1.1 mrg if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG) 292 1.1 mrg { 293 1.1 mrg if (GET_MODE_CLASS (mode) == MODE_FLOAT) 294 1.1 mrg return 1; 295 1.1 mrg 296 1.1 mrg if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) 297 1.1 mrg return 2; 298 1.1 mrg } 299 1.1 mrg 300 1.1 mrg return 0; 301 1.1 mrg } 302 1.1 mrg 303 1.1 mrg typedef struct 304 1.1 mrg { 305 1.1 mrg const_tree type; 306 1.1 mrg HOST_WIDE_INT offset; 307 1.1 mrg } loongarch_aggregate_field; 308 1.1 mrg 309 1.1 mrg /* Identify subfields of aggregates that are candidates for passing in 310 1.1 mrg floating-point registers. */ 311 1.1 mrg 312 1.1 mrg static int 313 1.1 mrg loongarch_flatten_aggregate_field (const_tree type, 314 1.1 mrg loongarch_aggregate_field fields[2], int n, 315 1.1 mrg HOST_WIDE_INT offset) 316 1.1 mrg { 317 1.1 mrg switch (TREE_CODE (type)) 318 1.1 mrg { 319 1.1 mrg case RECORD_TYPE: 320 1.1 mrg /* Can't handle incomplete types nor sizes that are not fixed. */ 321 1.1 mrg if (!COMPLETE_TYPE_P (type) 322 1.1 mrg || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST 323 1.1 mrg || !tree_fits_uhwi_p (TYPE_SIZE (type))) 324 1.1 mrg return -1; 325 1.1 mrg 326 1.1 mrg for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f)) 327 1.1 mrg if (TREE_CODE (f) == FIELD_DECL) 328 1.1 mrg { 329 1.1 mrg if (!TYPE_P (TREE_TYPE (f))) 330 1.1 mrg return -1; 331 1.1 mrg 332 1.1 mrg if (DECL_SIZE (f) && integer_zerop (DECL_SIZE (f))) 333 1.1 mrg continue; 334 1.1 mrg 335 1.1 mrg HOST_WIDE_INT pos = offset + int_byte_position (f); 336 1.1 mrg n = loongarch_flatten_aggregate_field (TREE_TYPE (f), fields, n, 337 1.1 mrg pos); 338 1.1 mrg if (n < 0) 339 1.1 mrg return -1; 340 1.1 mrg } 341 1.1 mrg return n; 342 1.1 mrg 343 1.1 mrg case ARRAY_TYPE: 344 1.1 mrg { 345 1.1 mrg HOST_WIDE_INT n_elts; 346 1.1 mrg loongarch_aggregate_field subfields[2]; 347 1.1 mrg tree index = TYPE_DOMAIN (type); 348 1.1 mrg tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); 349 1.1 mrg int n_subfields = loongarch_flatten_aggregate_field (TREE_TYPE (type), 350 1.1 mrg subfields, 0, 351 1.1 mrg offset); 352 1.1 mrg 353 1.1 mrg /* Can't handle incomplete types nor sizes that are not fixed. */ 354 1.1 mrg if (n_subfields <= 0 355 1.1 mrg || !COMPLETE_TYPE_P (type) 356 1.1 mrg || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST 357 1.1 mrg || !index 358 1.1 mrg || !TYPE_MAX_VALUE (index) 359 1.1 mrg || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) 360 1.1 mrg || !TYPE_MIN_VALUE (index) 361 1.1 mrg || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) 362 1.1 mrg || !tree_fits_uhwi_p (elt_size)) 363 1.1 mrg return -1; 364 1.1 mrg 365 1.1 mrg n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) 366 1.1 mrg - tree_to_uhwi (TYPE_MIN_VALUE (index)); 367 1.1 mrg gcc_assert (n_elts >= 0); 368 1.1 mrg 369 1.1 mrg for (HOST_WIDE_INT i = 0; i < n_elts; i++) 370 1.1 mrg for (int j = 0; j < n_subfields; j++) 371 1.1 mrg { 372 1.1 mrg if (n >= 2) 373 1.1 mrg return -1; 374 1.1 mrg 375 1.1 mrg fields[n] = subfields[j]; 376 1.1 mrg fields[n++].offset += i * tree_to_uhwi (elt_size); 377 1.1 mrg } 378 1.1 mrg 379 1.1 mrg return n; 380 1.1 mrg } 381 1.1 mrg 382 1.1 mrg case COMPLEX_TYPE: 383 1.1 mrg { 384 1.1 mrg /* Complex type need consume 2 field, so n must be 0. */ 385 1.1 mrg if (n != 0) 386 1.1 mrg return -1; 387 1.1 mrg 388 1.1 mrg HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type))); 389 1.1 mrg 390 1.1 mrg if (elt_size <= UNITS_PER_FP_ARG) 391 1.1 mrg { 392 1.1 mrg fields[0].type = TREE_TYPE (type); 393 1.1 mrg fields[0].offset = offset; 394 1.1 mrg fields[1].type = TREE_TYPE (type); 395 1.1 mrg fields[1].offset = offset + elt_size; 396 1.1 mrg 397 1.1 mrg return 2; 398 1.1 mrg } 399 1.1 mrg 400 1.1 mrg return -1; 401 1.1 mrg } 402 1.1 mrg 403 1.1 mrg default: 404 1.1 mrg if (n < 2 405 1.1 mrg && ((SCALAR_FLOAT_TYPE_P (type) 406 1.1 mrg && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG) 407 1.1 mrg || (INTEGRAL_TYPE_P (type) 408 1.1 mrg && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD))) 409 1.1 mrg { 410 1.1 mrg fields[n].type = type; 411 1.1 mrg fields[n].offset = offset; 412 1.1 mrg return n + 1; 413 1.1 mrg } 414 1.1 mrg else 415 1.1 mrg return -1; 416 1.1 mrg } 417 1.1 mrg } 418 1.1 mrg 419 1.1 mrg /* Identify candidate aggregates for passing in floating-point registers. 420 1.1 mrg Candidates have at most two fields after flattening. */ 421 1.1 mrg 422 1.1 mrg static int 423 1.1 mrg loongarch_flatten_aggregate_argument (const_tree type, 424 1.1 mrg loongarch_aggregate_field fields[2]) 425 1.1 mrg { 426 1.1 mrg if (!type || TREE_CODE (type) != RECORD_TYPE) 427 1.1 mrg return -1; 428 1.1 mrg 429 1.1 mrg return loongarch_flatten_aggregate_field (type, fields, 0, 0); 430 1.1 mrg } 431 1.1 mrg 432 1.1 mrg /* See whether TYPE is a record whose fields should be returned in one or 433 1.1 mrg two floating-point registers. If so, populate FIELDS accordingly. */ 434 1.1 mrg 435 1.1 mrg static unsigned 436 1.1 mrg loongarch_pass_aggregate_num_fpr (const_tree type, 437 1.1 mrg loongarch_aggregate_field fields[2]) 438 1.1 mrg { 439 1.1 mrg int n = loongarch_flatten_aggregate_argument (type, fields); 440 1.1 mrg 441 1.1 mrg for (int i = 0; i < n; i++) 442 1.1 mrg if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) 443 1.1 mrg return 0; 444 1.1 mrg 445 1.1 mrg return n > 0 ? n : 0; 446 1.1 mrg } 447 1.1 mrg 448 1.1 mrg /* See whether TYPE is a record whose fields should be returned in one 449 1.1 mrg floating-point register and one integer register. If so, populate 450 1.1 mrg FIELDS accordingly. */ 451 1.1 mrg 452 1.1 mrg static bool 453 1.1 mrg loongarch_pass_aggregate_in_fpr_and_gpr_p (const_tree type, 454 1.1 mrg loongarch_aggregate_field fields[2]) 455 1.1 mrg { 456 1.1 mrg unsigned num_int = 0, num_float = 0; 457 1.1 mrg int n = loongarch_flatten_aggregate_argument (type, fields); 458 1.1 mrg 459 1.1 mrg for (int i = 0; i < n; i++) 460 1.1 mrg { 461 1.1 mrg num_float += SCALAR_FLOAT_TYPE_P (fields[i].type); 462 1.1 mrg num_int += INTEGRAL_TYPE_P (fields[i].type); 463 1.1 mrg } 464 1.1 mrg 465 1.1 mrg return num_int == 1 && num_float == 1; 466 1.1 mrg } 467 1.1 mrg 468 1.1 mrg /* Return the representation of an argument passed or returned in an FPR 469 1.1 mrg when the value has mode VALUE_MODE and the type has TYPE_MODE. The 470 1.1 mrg two modes may be different for structures like: 471 1.1 mrg 472 1.1 mrg struct __attribute__((packed)) foo { float f; } 473 1.1 mrg 474 1.1 mrg where the SFmode value "f" is passed in REGNO but the struct itself 475 1.1 mrg has mode BLKmode. */ 476 1.1 mrg 477 1.1 mrg static rtx 478 1.1 mrg loongarch_pass_fpr_single (machine_mode type_mode, unsigned regno, 479 1.1 mrg machine_mode value_mode, 480 1.1 mrg HOST_WIDE_INT offset) 481 1.1 mrg { 482 1.1 mrg rtx x = gen_rtx_REG (value_mode, regno); 483 1.1 mrg 484 1.1 mrg if (type_mode != value_mode) 485 1.1 mrg { 486 1.1 mrg x = gen_rtx_EXPR_LIST (VOIDmode, x, GEN_INT (offset)); 487 1.1 mrg x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x)); 488 1.1 mrg } 489 1.1 mrg return x; 490 1.1 mrg } 491 1.1 mrg 492 1.1 mrg /* Pass or return a composite value in the FPR pair REGNO and REGNO + 1. 493 1.1 mrg MODE is the mode of the composite. MODE1 and OFFSET1 are the mode and 494 1.1 mrg byte offset for the first value, likewise MODE2 and OFFSET2 for the 495 1.1 mrg second value. */ 496 1.1 mrg 497 1.1 mrg static rtx 498 1.1 mrg loongarch_pass_fpr_pair (machine_mode mode, unsigned regno1, 499 1.1 mrg machine_mode mode1, HOST_WIDE_INT offset1, 500 1.1 mrg unsigned regno2, machine_mode mode2, 501 1.1 mrg HOST_WIDE_INT offset2) 502 1.1 mrg { 503 1.1 mrg return gen_rtx_PARALLEL ( 504 1.1 mrg mode, gen_rtvec (2, 505 1.1 mrg gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode1, regno1), 506 1.1 mrg GEN_INT (offset1)), 507 1.1 mrg gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode2, regno2), 508 1.1 mrg GEN_INT (offset2)))); 509 1.1 mrg } 510 1.1 mrg 511 1.1 mrg /* Fill INFO with information about a single argument, and return an 512 1.1 mrg RTL pattern to pass or return the argument. CUM is the cumulative 513 1.1 mrg state for earlier arguments. MODE is the mode of this argument and 514 1.1 mrg TYPE is its type (if known). NAMED is true if this is a named 515 1.1 mrg (fixed) argument rather than a variable one. RETURN_P is true if 516 1.1 mrg returning the argument, or false if passing the argument. */ 517 1.1 mrg 518 1.1 mrg static rtx 519 1.1 mrg loongarch_get_arg_info (struct loongarch_arg_info *info, 520 1.1 mrg const CUMULATIVE_ARGS *cum, machine_mode mode, 521 1.1 mrg const_tree type, bool named, bool return_p) 522 1.1 mrg { 523 1.1 mrg unsigned num_bytes, num_words; 524 1.1 mrg unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST; 525 1.1 mrg unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST; 526 1.1 mrg unsigned alignment = loongarch_function_arg_boundary (mode, type); 527 1.1 mrg 528 1.1 mrg memset (info, 0, sizeof (*info)); 529 1.1 mrg info->gpr_offset = cum->num_gprs; 530 1.1 mrg info->fpr_offset = cum->num_fprs; 531 1.1 mrg 532 1.1 mrg if (named) 533 1.1 mrg { 534 1.1 mrg loongarch_aggregate_field fields[2]; 535 1.1 mrg unsigned fregno = fpr_base + info->fpr_offset; 536 1.1 mrg unsigned gregno = gpr_base + info->gpr_offset; 537 1.1 mrg 538 1.1 mrg /* Pass one- or two-element floating-point aggregates in FPRs. */ 539 1.1 mrg if ((info->num_fprs 540 1.1 mrg = loongarch_pass_aggregate_num_fpr (type, fields)) 541 1.1 mrg && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) 542 1.1 mrg switch (info->num_fprs) 543 1.1 mrg { 544 1.1 mrg case 1: 545 1.1 mrg return loongarch_pass_fpr_single (mode, fregno, 546 1.1 mrg TYPE_MODE (fields[0].type), 547 1.1 mrg fields[0].offset); 548 1.1 mrg 549 1.1 mrg case 2: 550 1.1 mrg return loongarch_pass_fpr_pair (mode, fregno, 551 1.1 mrg TYPE_MODE (fields[0].type), 552 1.1 mrg fields[0].offset, 553 1.1 mrg fregno + 1, 554 1.1 mrg TYPE_MODE (fields[1].type), 555 1.1 mrg fields[1].offset); 556 1.1 mrg 557 1.1 mrg default: 558 1.1 mrg gcc_unreachable (); 559 1.1 mrg } 560 1.1 mrg 561 1.1 mrg /* Pass real and complex floating-point numbers in FPRs. */ 562 1.1 mrg if ((info->num_fprs = loongarch_pass_mode_in_fpr_p (mode)) 563 1.1 mrg && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) 564 1.1 mrg switch (GET_MODE_CLASS (mode)) 565 1.1 mrg { 566 1.1 mrg case MODE_FLOAT: 567 1.1 mrg return gen_rtx_REG (mode, fregno); 568 1.1 mrg 569 1.1 mrg case MODE_COMPLEX_FLOAT: 570 1.1 mrg return loongarch_pass_fpr_pair (mode, fregno, 571 1.1 mrg GET_MODE_INNER (mode), 0, 572 1.1 mrg fregno + 1, GET_MODE_INNER (mode), 573 1.1 mrg GET_MODE_UNIT_SIZE (mode)); 574 1.1 mrg 575 1.1 mrg default: 576 1.1 mrg gcc_unreachable (); 577 1.1 mrg } 578 1.1 mrg 579 1.1 mrg /* Pass structs with one float and one integer in an FPR and a GPR. */ 580 1.1 mrg if (loongarch_pass_aggregate_in_fpr_and_gpr_p (type, fields) 581 1.1 mrg && info->gpr_offset < MAX_ARGS_IN_REGISTERS 582 1.1 mrg && info->fpr_offset < MAX_ARGS_IN_REGISTERS) 583 1.1 mrg { 584 1.1 mrg info->num_gprs = 1; 585 1.1 mrg info->num_fprs = 1; 586 1.1 mrg 587 1.1 mrg if (!SCALAR_FLOAT_TYPE_P (fields[0].type)) 588 1.1 mrg std::swap (fregno, gregno); 589 1.1 mrg 590 1.1 mrg return loongarch_pass_fpr_pair (mode, fregno, 591 1.1 mrg TYPE_MODE (fields[0].type), 592 1.1 mrg fields[0].offset, gregno, 593 1.1 mrg TYPE_MODE (fields[1].type), 594 1.1 mrg fields[1].offset); 595 1.1 mrg } 596 1.1 mrg } 597 1.1 mrg 598 1.1 mrg /* Work out the size of the argument. */ 599 1.1 mrg num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); 600 1.1 mrg num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 601 1.1 mrg 602 1.1 mrg /* Doubleword-aligned varargs start on an even register boundary. */ 603 1.1 mrg if (!named && num_bytes != 0 && alignment > BITS_PER_WORD) 604 1.1 mrg info->gpr_offset += info->gpr_offset & 1; 605 1.1 mrg 606 1.1 mrg /* Partition the argument between registers and stack. */ 607 1.1 mrg info->num_fprs = 0; 608 1.1 mrg info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset); 609 1.1 mrg info->stack_p = (num_words - info->num_gprs) != 0; 610 1.1 mrg 611 1.1 mrg if (info->num_gprs || return_p) 612 1.1 mrg return gen_rtx_REG (mode, gpr_base + info->gpr_offset); 613 1.1 mrg 614 1.1 mrg return NULL_RTX; 615 1.1 mrg } 616 1.1 mrg 617 1.1 mrg /* Implement TARGET_FUNCTION_ARG. */ 618 1.1 mrg 619 1.1 mrg static rtx 620 1.1 mrg loongarch_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) 621 1.1 mrg { 622 1.1 mrg CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 623 1.1 mrg struct loongarch_arg_info info; 624 1.1 mrg 625 1.1 mrg if (arg.end_marker_p ()) 626 1.1 mrg return NULL; 627 1.1 mrg 628 1.1 mrg return loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, 629 1.1 mrg false); 630 1.1 mrg } 631 1.1 mrg 632 1.1 mrg /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ 633 1.1 mrg 634 1.1 mrg static void 635 1.1 mrg loongarch_function_arg_advance (cumulative_args_t cum_v, 636 1.1 mrg const function_arg_info &arg) 637 1.1 mrg { 638 1.1 mrg CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 639 1.1 mrg struct loongarch_arg_info info; 640 1.1 mrg 641 1.1 mrg loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false); 642 1.1 mrg 643 1.1 mrg /* Advance the register count. This has the effect of setting 644 1.1 mrg num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned 645 1.1 mrg argument required us to skip the final GPR and pass the whole 646 1.1 mrg argument on the stack. */ 647 1.1 mrg cum->num_fprs = info.fpr_offset + info.num_fprs; 648 1.1 mrg cum->num_gprs = info.gpr_offset + info.num_gprs; 649 1.1 mrg } 650 1.1 mrg 651 1.1 mrg /* Implement TARGET_ARG_PARTIAL_BYTES. */ 652 1.1 mrg 653 1.1 mrg static int 654 1.1 mrg loongarch_arg_partial_bytes (cumulative_args_t cum, 655 1.1 mrg const function_arg_info &generic_arg) 656 1.1 mrg { 657 1.1 mrg struct loongarch_arg_info arg; 658 1.1 mrg 659 1.1 mrg loongarch_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode, 660 1.1 mrg generic_arg.type, generic_arg.named, false); 661 1.1 mrg return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0; 662 1.1 mrg } 663 1.1 mrg 664 1.1 mrg /* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, 665 1.1 mrg VALTYPE is the return type and MODE is VOIDmode. For libcalls, 666 1.1 mrg VALTYPE is null and MODE is the mode of the return value. */ 667 1.1 mrg 668 1.1 mrg static rtx 669 1.1 mrg loongarch_function_value_1 (const_tree type, const_tree func, 670 1.1 mrg machine_mode mode) 671 1.1 mrg { 672 1.1 mrg struct loongarch_arg_info info; 673 1.1 mrg CUMULATIVE_ARGS args; 674 1.1 mrg 675 1.1 mrg if (type) 676 1.1 mrg { 677 1.1 mrg int unsigned_p = TYPE_UNSIGNED (type); 678 1.1 mrg 679 1.1 mrg mode = TYPE_MODE (type); 680 1.1 mrg 681 1.1 mrg /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, 682 1.1 mrg return values, promote the mode here too. */ 683 1.1 mrg mode = promote_function_mode (type, mode, &unsigned_p, func, 1); 684 1.1 mrg } 685 1.1 mrg 686 1.1 mrg memset (&args, 0, sizeof (args)); 687 1.1 mrg return loongarch_get_arg_info (&info, &args, mode, type, true, true); 688 1.1 mrg } 689 1.1 mrg 690 1.1 mrg 691 1.1 mrg /* Implement TARGET_FUNCTION_VALUE. */ 692 1.1 mrg 693 1.1 mrg static rtx 694 1.1 mrg loongarch_function_value (const_tree valtype, const_tree fn_decl_or_type, 695 1.1 mrg bool outgoing ATTRIBUTE_UNUSED) 696 1.1 mrg { 697 1.1 mrg return loongarch_function_value_1 (valtype, fn_decl_or_type, VOIDmode); 698 1.1 mrg } 699 1.1 mrg 700 1.1 mrg /* Implement TARGET_LIBCALL_VALUE. */ 701 1.1 mrg 702 1.1 mrg static rtx 703 1.1 mrg loongarch_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) 704 1.1 mrg { 705 1.1 mrg return loongarch_function_value_1 (NULL_TREE, NULL_TREE, mode); 706 1.1 mrg } 707 1.1 mrg 708 1.1 mrg 709 1.1 mrg /* Implement TARGET_PASS_BY_REFERENCE. */ 710 1.1 mrg 711 1.1 mrg static bool 712 1.1 mrg loongarch_pass_by_reference (cumulative_args_t cum_v, 713 1.1 mrg const function_arg_info &arg) 714 1.1 mrg { 715 1.1 mrg HOST_WIDE_INT size = arg.type_size_in_bytes (); 716 1.1 mrg struct loongarch_arg_info info; 717 1.1 mrg CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 718 1.1 mrg 719 1.1 mrg /* ??? std_gimplify_va_arg_expr passes NULL for cum. Fortunately, we 720 1.1 mrg never pass variadic arguments in floating-point registers, so we can 721 1.1 mrg avoid the call to loongarch_get_arg_info in this case. */ 722 1.1 mrg if (cum != NULL) 723 1.1 mrg { 724 1.1 mrg /* Don't pass by reference if we can use a floating-point register. */ 725 1.1 mrg loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, 726 1.1 mrg false); 727 1.1 mrg if (info.num_fprs) 728 1.1 mrg return false; 729 1.1 mrg } 730 1.1 mrg 731 1.1 mrg /* Pass by reference if the data do not fit in two integer registers. */ 732 1.1 mrg return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD); 733 1.1 mrg } 734 1.1 mrg 735 1.1 mrg /* Implement TARGET_RETURN_IN_MEMORY. */ 736 1.1 mrg 737 1.1 mrg static bool 738 1.1 mrg loongarch_return_in_memory (const_tree type, 739 1.1 mrg const_tree fndecl ATTRIBUTE_UNUSED) 740 1.1 mrg { 741 1.1 mrg CUMULATIVE_ARGS args; 742 1.1 mrg cumulative_args_t cum = pack_cumulative_args (&args); 743 1.1 mrg 744 1.1 mrg /* The rules for returning in memory are the same as for passing the 745 1.1 mrg first named argument by reference. */ 746 1.1 mrg memset (&args, 0, sizeof (args)); 747 1.1 mrg function_arg_info arg (const_cast<tree> (type), /*named=*/true); 748 1.1 mrg return loongarch_pass_by_reference (cum, arg); 749 1.1 mrg } 750 1.1 mrg 751 1.1 mrg /* Implement TARGET_SETUP_INCOMING_VARARGS. */ 752 1.1 mrg 753 1.1 mrg static void 754 1.1 mrg loongarch_setup_incoming_varargs (cumulative_args_t cum, 755 1.1 mrg const function_arg_info &arg, 756 1.1 mrg int *pretend_size ATTRIBUTE_UNUSED, 757 1.1 mrg int no_rtl) 758 1.1 mrg { 759 1.1 mrg CUMULATIVE_ARGS local_cum; 760 1.1 mrg int gp_saved; 761 1.1 mrg 762 1.1 mrg /* The caller has advanced CUM up to, but not beyond, the last named 763 1.1 mrg argument. Advance a local copy of CUM past the last "real" named 764 1.1 mrg argument, to find out how many registers are left over. */ 765 1.1 mrg local_cum = *get_cumulative_args (cum); 766 1.1 mrg loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg); 767 1.1 mrg 768 1.1 mrg /* Found out how many registers we need to save. */ 769 1.1 mrg gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; 770 1.1 mrg 771 1.1 mrg if (!no_rtl && gp_saved > 0) 772 1.1 mrg { 773 1.1 mrg rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx, 774 1.1 mrg REG_PARM_STACK_SPACE (cfun->decl) 775 1.1 mrg - gp_saved * UNITS_PER_WORD); 776 1.1 mrg rtx mem = gen_frame_mem (BLKmode, ptr); 777 1.1 mrg set_mem_alias_set (mem, get_varargs_alias_set ()); 778 1.1 mrg 779 1.1 mrg move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, mem, gp_saved); 780 1.1 mrg } 781 1.1 mrg if (REG_PARM_STACK_SPACE (cfun->decl) == 0) 782 1.1 mrg cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; 783 1.1 mrg } 784 1.1 mrg 785 1.1 mrg /* Make the last instruction frame-related and note that it performs 786 1.1 mrg the operation described by FRAME_PATTERN. */ 787 1.1 mrg 788 1.1 mrg static void 789 1.1 mrg loongarch_set_frame_expr (rtx frame_pattern) 790 1.1 mrg { 791 1.1 mrg rtx insn; 792 1.1 mrg 793 1.1 mrg insn = get_last_insn (); 794 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 795 1.1 mrg REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, frame_pattern, 796 1.1 mrg REG_NOTES (insn)); 797 1.1 mrg } 798 1.1 mrg 799 1.1 mrg /* Return a frame-related rtx that stores REG at MEM. 800 1.1 mrg REG must be a single register. */ 801 1.1 mrg 802 1.1 mrg static rtx 803 1.1 mrg loongarch_frame_set (rtx mem, rtx reg) 804 1.1 mrg { 805 1.1 mrg rtx set = gen_rtx_SET (mem, reg); 806 1.1 mrg RTX_FRAME_RELATED_P (set) = 1; 807 1.1 mrg return set; 808 1.1 mrg } 809 1.1 mrg 810 1.1 mrg /* Return true if the current function must save register REGNO. */ 811 1.1 mrg 812 1.1 mrg static bool 813 1.1 mrg loongarch_save_reg_p (unsigned int regno) 814 1.1 mrg { 815 1.1 mrg bool call_saved = !global_regs[regno] && !call_used_regs[regno]; 816 1.1 mrg bool might_clobber 817 1.1 mrg = crtl->saves_all_registers || df_regs_ever_live_p (regno); 818 1.1 mrg 819 1.1 mrg if (call_saved && might_clobber) 820 1.1 mrg return true; 821 1.1 mrg 822 1.1 mrg if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) 823 1.1 mrg return true; 824 1.1 mrg 825 1.1 mrg if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return) 826 1.1 mrg return true; 827 1.1 mrg 828 1.1 mrg return false; 829 1.1 mrg } 830 1.1 mrg 831 1.1 mrg /* Determine which GPR save/restore routine to call. */ 832 1.1 mrg 833 1.1 mrg static unsigned 834 1.1 mrg loongarch_save_libcall_count (unsigned mask) 835 1.1 mrg { 836 1.1 mrg for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--) 837 1.1 mrg if (BITSET_P (mask, n)) 838 1.1 mrg return CALLEE_SAVED_REG_NUMBER (n) + 1; 839 1.1 mrg abort (); 840 1.1 mrg } 841 1.1 mrg 842 1.1 mrg /* Populate the current function's loongarch_frame_info structure. 843 1.1 mrg 844 1.1 mrg LoongArch stack frames grown downward. High addresses are at the top. 845 1.1 mrg 846 1.1 mrg +-------------------------------+ 847 1.1 mrg | | 848 1.1 mrg | incoming stack arguments | 849 1.1 mrg | | 850 1.1 mrg +-------------------------------+ <-- incoming stack pointer 851 1.1 mrg | | 852 1.1 mrg | callee-allocated save area | 853 1.1 mrg | for arguments that are | 854 1.1 mrg | split between registers and | 855 1.1 mrg | the stack | 856 1.1 mrg | | 857 1.1 mrg +-------------------------------+ <-- arg_pointer_rtx (virtual) 858 1.1 mrg | | 859 1.1 mrg | callee-allocated save area | 860 1.1 mrg | for register varargs | 861 1.1 mrg | | 862 1.1 mrg +-------------------------------+ <-- hard_frame_pointer_rtx; 863 1.1 mrg | | stack_pointer_rtx + gp_sp_offset 864 1.1 mrg | GPR save area | + UNITS_PER_WORD 865 1.1 mrg | | 866 1.1 mrg +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset 867 1.1 mrg | | + UNITS_PER_HWVALUE 868 1.1 mrg | FPR save area | 869 1.1 mrg | | 870 1.1 mrg +-------------------------------+ <-- frame_pointer_rtx (virtual) 871 1.1 mrg | | 872 1.1 mrg | local variables | 873 1.1 mrg | | 874 1.1 mrg P +-------------------------------+ 875 1.1 mrg | | 876 1.1 mrg | outgoing stack arguments | 877 1.1 mrg | | 878 1.1 mrg +-------------------------------+ <-- stack_pointer_rtx 879 1.1 mrg 880 1.1 mrg Dynamic stack allocations such as alloca insert data at point P. 881 1.1 mrg They decrease stack_pointer_rtx but leave frame_pointer_rtx and 882 1.1 mrg hard_frame_pointer_rtx unchanged. */ 883 1.1 mrg 884 1.1 mrg static void 885 1.1 mrg loongarch_compute_frame_info (void) 886 1.1 mrg { 887 1.1 mrg struct loongarch_frame_info *frame; 888 1.1 mrg HOST_WIDE_INT offset; 889 1.1 mrg unsigned int regno, i, num_x_saved = 0, num_f_saved = 0; 890 1.1 mrg 891 1.1 mrg frame = &cfun->machine->frame; 892 1.1 mrg memset (frame, 0, sizeof (*frame)); 893 1.1 mrg 894 1.1 mrg /* Find out which GPRs we need to save. */ 895 1.1 mrg for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 896 1.1 mrg if (loongarch_save_reg_p (regno)) 897 1.1 mrg frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; 898 1.1 mrg 899 1.1 mrg /* If this function calls eh_return, we must also save and restore the 900 1.1 mrg EH data registers. */ 901 1.1 mrg if (crtl->calls_eh_return) 902 1.1 mrg for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) 903 1.1 mrg frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; 904 1.1 mrg 905 1.1 mrg /* Find out which FPRs we need to save. This loop must iterate over 906 1.1 mrg the same space as its companion in loongarch_for_each_saved_reg. */ 907 1.1 mrg if (TARGET_HARD_FLOAT) 908 1.1 mrg for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 909 1.1 mrg if (loongarch_save_reg_p (regno)) 910 1.1 mrg frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; 911 1.1 mrg 912 1.1 mrg /* At the bottom of the frame are any outgoing stack arguments. */ 913 1.1 mrg offset = LARCH_STACK_ALIGN (crtl->outgoing_args_size); 914 1.1 mrg /* Next are local stack variables. */ 915 1.1 mrg offset += LARCH_STACK_ALIGN (get_frame_size ()); 916 1.1 mrg /* The virtual frame pointer points above the local variables. */ 917 1.1 mrg frame->frame_pointer_offset = offset; 918 1.1 mrg /* Next are the callee-saved FPRs. */ 919 1.1 mrg if (frame->fmask) 920 1.1 mrg { 921 1.1 mrg offset += LARCH_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG); 922 1.1 mrg frame->fp_sp_offset = offset - UNITS_PER_FP_REG; 923 1.1 mrg } 924 1.1 mrg else 925 1.1 mrg frame->fp_sp_offset = offset; 926 1.1 mrg /* Next are the callee-saved GPRs. */ 927 1.1 mrg if (frame->mask) 928 1.1 mrg { 929 1.1 mrg unsigned x_save_size = LARCH_STACK_ALIGN (num_x_saved * UNITS_PER_WORD); 930 1.1 mrg unsigned num_save_restore 931 1.1 mrg = 1 + loongarch_save_libcall_count (frame->mask); 932 1.1 mrg 933 1.1 mrg /* Only use save/restore routines if they don't alter the stack size. */ 934 1.1 mrg if (LARCH_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) 935 1.1 mrg frame->save_libcall_adjustment = x_save_size; 936 1.1 mrg 937 1.1 mrg offset += x_save_size; 938 1.1 mrg frame->gp_sp_offset = offset - UNITS_PER_WORD; 939 1.1 mrg } 940 1.1 mrg else 941 1.1 mrg frame->gp_sp_offset = offset; 942 1.1 mrg /* The hard frame pointer points above the callee-saved GPRs. */ 943 1.1 mrg frame->hard_frame_pointer_offset = offset; 944 1.1 mrg /* Above the hard frame pointer is the callee-allocated varags save area. */ 945 1.1 mrg offset += LARCH_STACK_ALIGN (cfun->machine->varargs_size); 946 1.1 mrg /* Next is the callee-allocated area for pretend stack arguments. */ 947 1.1 mrg offset += LARCH_STACK_ALIGN (crtl->args.pretend_args_size); 948 1.1 mrg /* Arg pointer must be below pretend args, but must be above alignment 949 1.1 mrg padding. */ 950 1.1 mrg frame->arg_pointer_offset = offset - crtl->args.pretend_args_size; 951 1.1 mrg frame->total_size = offset; 952 1.1 mrg /* Next points the incoming stack pointer and any incoming arguments. */ 953 1.1 mrg 954 1.1 mrg /* Only use save/restore routines when the GPRs are atop the frame. */ 955 1.1 mrg if (frame->hard_frame_pointer_offset != frame->total_size) 956 1.1 mrg frame->save_libcall_adjustment = 0; 957 1.1 mrg } 958 1.1 mrg 959 1.1 mrg /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer 960 1.1 mrg or argument pointer. TO is either the stack pointer or hard frame 961 1.1 mrg pointer. */ 962 1.1 mrg 963 1.1 mrg HOST_WIDE_INT 964 1.1 mrg loongarch_initial_elimination_offset (int from, int to) 965 1.1 mrg { 966 1.1 mrg HOST_WIDE_INT src, dest; 967 1.1 mrg 968 1.1 mrg loongarch_compute_frame_info (); 969 1.1 mrg 970 1.1 mrg if (to == HARD_FRAME_POINTER_REGNUM) 971 1.1 mrg dest = cfun->machine->frame.hard_frame_pointer_offset; 972 1.1 mrg else if (to == STACK_POINTER_REGNUM) 973 1.1 mrg dest = 0; /* The stack pointer is the base of all offsets, hence 0. */ 974 1.1 mrg else 975 1.1 mrg gcc_unreachable (); 976 1.1 mrg 977 1.1 mrg if (from == FRAME_POINTER_REGNUM) 978 1.1 mrg src = cfun->machine->frame.frame_pointer_offset; 979 1.1 mrg else if (from == ARG_POINTER_REGNUM) 980 1.1 mrg src = cfun->machine->frame.arg_pointer_offset; 981 1.1 mrg else 982 1.1 mrg gcc_unreachable (); 983 1.1 mrg 984 1.1 mrg return src - dest; 985 1.1 mrg } 986 1.1 mrg 987 1.1 mrg /* A function to save or store a register. The first argument is the 988 1.1 mrg register and the second is the stack slot. */ 989 1.1 mrg typedef void (*loongarch_save_restore_fn) (rtx, rtx); 990 1.1 mrg 991 1.1 mrg /* Use FN to save or restore register REGNO. MODE is the register's 992 1.1 mrg mode and OFFSET is the offset of its save slot from the current 993 1.1 mrg stack pointer. */ 994 1.1 mrg 995 1.1 mrg static void 996 1.1 mrg loongarch_save_restore_reg (machine_mode mode, int regno, HOST_WIDE_INT offset, 997 1.1 mrg loongarch_save_restore_fn fn) 998 1.1 mrg { 999 1.1 mrg rtx mem; 1000 1.1 mrg 1001 1.1 mrg mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset)); 1002 1.1 mrg fn (gen_rtx_REG (mode, regno), mem); 1003 1.1 mrg } 1004 1.1 mrg 1005 1.1 mrg /* Call FN for each register that is saved by the current function. 1006 1.1 mrg SP_OFFSET is the offset of the current stack pointer from the start 1007 1.1 mrg of the frame. */ 1008 1.1 mrg 1009 1.1 mrg static void 1010 1.1 mrg loongarch_for_each_saved_reg (HOST_WIDE_INT sp_offset, 1011 1.1 mrg loongarch_save_restore_fn fn, 1012 1.1 mrg bool skip_eh_data_regs_p) 1013 1.1 mrg { 1014 1.1 mrg HOST_WIDE_INT offset; 1015 1.1 mrg 1016 1.1 mrg /* Save the link register and s-registers. */ 1017 1.1 mrg offset = cfun->machine->frame.gp_sp_offset - sp_offset; 1018 1.1 mrg for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 1019 1.1 mrg if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) 1020 1.1 mrg { 1021 1.1 mrg /* Special care needs to be taken for $r4-$r7 (EH_RETURN_DATA_REGNO) 1022 1.1 mrg when returning normally from a function that calls 1023 1.1 mrg __builtin_eh_return. In this case, these registers are saved but 1024 1.1 mrg should not be restored, or the return value may be clobbered. */ 1025 1.1 mrg 1026 1.1 mrg if (!(skip_eh_data_regs_p 1027 1.1 mrg && GP_ARG_FIRST <= regno && regno < GP_ARG_FIRST + 4)) 1028 1.1 mrg loongarch_save_restore_reg (word_mode, regno, offset, fn); 1029 1.1 mrg 1030 1.1 mrg offset -= UNITS_PER_WORD; 1031 1.1 mrg } 1032 1.1 mrg 1033 1.1 mrg /* This loop must iterate over the same space as its companion in 1034 1.1 mrg loongarch_compute_frame_info. */ 1035 1.1 mrg offset = cfun->machine->frame.fp_sp_offset - sp_offset; 1036 1.1 mrg for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 1037 1.1 mrg if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) 1038 1.1 mrg { 1039 1.1 mrg machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; 1040 1.1 mrg 1041 1.1 mrg loongarch_save_restore_reg (mode, regno, offset, fn); 1042 1.1 mrg offset -= GET_MODE_SIZE (mode); 1043 1.1 mrg } 1044 1.1 mrg } 1045 1.1 mrg 1046 1.1 mrg /* Emit a move from SRC to DEST. Assume that the move expanders can 1047 1.1 mrg handle all moves if !can_create_pseudo_p (). The distinction is 1048 1.1 mrg important because, unlike emit_move_insn, the move expanders know 1049 1.1 mrg how to force Pmode objects into the constant pool even when the 1050 1.1 mrg constant pool address is not itself legitimate. */ 1051 1.1 mrg 1052 1.1 mrg rtx 1053 1.1 mrg loongarch_emit_move (rtx dest, rtx src) 1054 1.1 mrg { 1055 1.1 mrg return (can_create_pseudo_p () ? emit_move_insn (dest, src) 1056 1.1 mrg : emit_move_insn_1 (dest, src)); 1057 1.1 mrg } 1058 1.1 mrg 1059 1.1 mrg /* Save register REG to MEM. Make the instruction frame-related. */ 1060 1.1 mrg 1061 1.1 mrg static void 1062 1.1 mrg loongarch_save_reg (rtx reg, rtx mem) 1063 1.1 mrg { 1064 1.1 mrg loongarch_emit_move (mem, reg); 1065 1.1 mrg loongarch_set_frame_expr (loongarch_frame_set (mem, reg)); 1066 1.1 mrg } 1067 1.1 mrg 1068 1.1 mrg /* Restore register REG from MEM. */ 1069 1.1 mrg 1070 1.1 mrg static void 1071 1.1 mrg loongarch_restore_reg (rtx reg, rtx mem) 1072 1.1 mrg { 1073 1.1 mrg rtx insn = loongarch_emit_move (reg, mem); 1074 1.1 mrg rtx dwarf = NULL_RTX; 1075 1.1 mrg dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); 1076 1.1 mrg REG_NOTES (insn) = dwarf; 1077 1.1 mrg 1078 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 1079 1.1 mrg } 1080 1.1 mrg 1081 1.1 mrg /* For stack frames that can't be allocated with a single ADDI instruction, 1082 1.1 mrg compute the best value to initially allocate. It must at a minimum 1083 1.1 mrg allocate enough space to spill the callee-saved registers. */ 1084 1.1 mrg 1085 1.1 mrg static HOST_WIDE_INT 1086 1.1 mrg loongarch_first_stack_step (struct loongarch_frame_info *frame) 1087 1.1 mrg { 1088 1.1 mrg if (IMM12_OPERAND (frame->total_size)) 1089 1.1 mrg return frame->total_size; 1090 1.1 mrg 1091 1.1 mrg HOST_WIDE_INT min_first_step 1092 1.1 mrg = LARCH_STACK_ALIGN (frame->total_size - frame->fp_sp_offset); 1093 1.1 mrg HOST_WIDE_INT max_first_step = IMM_REACH / 2 - PREFERRED_STACK_BOUNDARY / 8; 1094 1.1 mrg HOST_WIDE_INT min_second_step = frame->total_size - max_first_step; 1095 1.1 mrg gcc_assert (min_first_step <= max_first_step); 1096 1.1 mrg 1097 1.1 mrg /* As an optimization, use the least-significant bits of the total frame 1098 1.1 mrg size, so that the second adjustment step is just LU12I + ADD. */ 1099 1.1 mrg if (!IMM12_OPERAND (min_second_step) 1100 1.1 mrg && frame->total_size % IMM_REACH < IMM_REACH / 2 1101 1.1 mrg && frame->total_size % IMM_REACH >= min_first_step) 1102 1.1 mrg return frame->total_size % IMM_REACH; 1103 1.1 mrg 1104 1.1 mrg return max_first_step; 1105 1.1 mrg } 1106 1.1 mrg 1107 1.1 mrg static void 1108 1.1 mrg loongarch_emit_stack_tie (void) 1109 1.1 mrg { 1110 1.1 mrg emit_insn (gen_stack_tie (Pmode, stack_pointer_rtx, 1111 1.1 mrg frame_pointer_needed ? hard_frame_pointer_rtx 1112 1.1 mrg : stack_pointer_rtx)); 1113 1.1 mrg } 1114 1.1 mrg 1115 1.1 mrg #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP) 1116 1.1 mrg 1117 1.1 mrg #if PROBE_INTERVAL > 16384 1118 1.1 mrg #error Cannot use indexed addressing mode for stack probing 1119 1.1 mrg #endif 1120 1.1 mrg 1121 1.1 mrg /* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE, 1122 1.1 mrg inclusive. These are offsets from the current stack pointer. */ 1123 1.1 mrg 1124 1.1 mrg static void 1125 1.1 mrg loongarch_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size) 1126 1.1 mrg { 1127 1.1 mrg /* See if we have a constant small number of probes to generate. If so, 1128 1.1 mrg that's the easy case. */ 1129 1.1 mrg if ((TARGET_64BIT && (first + size <= 32768)) 1130 1.1 mrg || (!TARGET_64BIT && (first + size <= 2048))) 1131 1.1 mrg { 1132 1.1 mrg HOST_WIDE_INT i; 1133 1.1 mrg 1134 1.1 mrg /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until 1135 1.1 mrg it exceeds SIZE. If only one probe is needed, this will not 1136 1.1 mrg generate any code. Then probe at FIRST + SIZE. */ 1137 1.1 mrg for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL) 1138 1.1 mrg emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, 1139 1.1 mrg -(first + i))); 1140 1.1 mrg 1141 1.1 mrg emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, 1142 1.1 mrg -(first + size))); 1143 1.1 mrg } 1144 1.1 mrg 1145 1.1 mrg /* Otherwise, do the same as above, but in a loop. Note that we must be 1146 1.1 mrg extra careful with variables wrapping around because we might be at 1147 1.1 mrg the very top (or the very bottom) of the address space and we have 1148 1.1 mrg to be able to handle this case properly; in particular, we use an 1149 1.1 mrg equality test for the loop condition. */ 1150 1.1 mrg else 1151 1.1 mrg { 1152 1.1 mrg HOST_WIDE_INT rounded_size; 1153 1.1 mrg rtx r13 = LARCH_PROLOGUE_TEMP (Pmode); 1154 1.1 mrg rtx r12 = LARCH_PROLOGUE_TEMP2 (Pmode); 1155 1.1 mrg rtx r14 = LARCH_PROLOGUE_TEMP3 (Pmode); 1156 1.1 mrg 1157 1.1 mrg /* Sanity check for the addressing mode we're going to use. */ 1158 1.1 mrg gcc_assert (first <= 16384); 1159 1.1 mrg 1160 1.1 mrg 1161 1.1 mrg /* Step 1: round SIZE to the previous multiple of the interval. */ 1162 1.1 mrg 1163 1.1 mrg rounded_size = ROUND_DOWN (size, PROBE_INTERVAL); 1164 1.1 mrg 1165 1.1 mrg /* TEST_ADDR = SP + FIRST */ 1166 1.1 mrg if (first != 0) 1167 1.1 mrg { 1168 1.1 mrg emit_move_insn (r14, GEN_INT (first)); 1169 1.1 mrg emit_insn (gen_rtx_SET (r13, gen_rtx_MINUS (Pmode, 1170 1.1 mrg stack_pointer_rtx, 1171 1.1 mrg r14))); 1172 1.1 mrg } 1173 1.1 mrg else 1174 1.1 mrg emit_move_insn (r13, stack_pointer_rtx); 1175 1.1 mrg 1176 1.1 mrg /* Step 2: compute initial and final value of the loop counter. */ 1177 1.1 mrg 1178 1.1 mrg emit_move_insn (r14, GEN_INT (PROBE_INTERVAL)); 1179 1.1 mrg /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */ 1180 1.1 mrg if (rounded_size == 0) 1181 1.1 mrg emit_move_insn (r12, r13); 1182 1.1 mrg else 1183 1.1 mrg { 1184 1.1 mrg emit_move_insn (r12, GEN_INT (rounded_size)); 1185 1.1 mrg emit_insn (gen_rtx_SET (r12, gen_rtx_MINUS (Pmode, r13, r12))); 1186 1.1 mrg /* Step 3: the loop 1187 1.1 mrg 1188 1.1 mrg do 1189 1.1 mrg { 1190 1.1 mrg TEST_ADDR = TEST_ADDR + PROBE_INTERVAL 1191 1.1 mrg probe at TEST_ADDR 1192 1.1 mrg } 1193 1.1 mrg while (TEST_ADDR != LAST_ADDR) 1194 1.1 mrg 1195 1.1 mrg probes at FIRST + N * PROBE_INTERVAL for values of N from 1 1196 1.1 mrg until it is equal to ROUNDED_SIZE. */ 1197 1.1 mrg 1198 1.1 mrg emit_insn (gen_probe_stack_range (Pmode, r13, r13, r12, r14)); 1199 1.1 mrg } 1200 1.1 mrg 1201 1.1 mrg /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time 1202 1.1 mrg that SIZE is equal to ROUNDED_SIZE. */ 1203 1.1 mrg 1204 1.1 mrg if (size != rounded_size) 1205 1.1 mrg { 1206 1.1 mrg if (TARGET_64BIT) 1207 1.1 mrg emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size)); 1208 1.1 mrg else 1209 1.1 mrg { 1210 1.1 mrg HOST_WIDE_INT i; 1211 1.1 mrg for (i = 2048; i < (size - rounded_size); i += 2048) 1212 1.1 mrg { 1213 1.1 mrg emit_stack_probe (plus_constant (Pmode, r12, -i)); 1214 1.1 mrg emit_insn (gen_rtx_SET (r12, 1215 1.1 mrg plus_constant (Pmode, r12, -2048))); 1216 1.1 mrg } 1217 1.1 mrg rtx r1 = plus_constant (Pmode, r12, 1218 1.1 mrg -(size - rounded_size - i + 2048)); 1219 1.1 mrg emit_stack_probe (r1); 1220 1.1 mrg } 1221 1.1 mrg } 1222 1.1 mrg } 1223 1.1 mrg 1224 1.1 mrg /* Make sure nothing is scheduled before we are done. */ 1225 1.1 mrg emit_insn (gen_blockage ()); 1226 1.1 mrg } 1227 1.1 mrg 1228 1.1 mrg /* Probe a range of stack addresses from REG1 to REG2 inclusive. These are 1229 1.1 mrg absolute addresses. */ 1230 1.1 mrg const char * 1231 1.1 mrg loongarch_output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3) 1232 1.1 mrg { 1233 1.1 mrg static int labelno = 0; 1234 1.1 mrg char loop_lab[32], tmp[64]; 1235 1.1 mrg rtx xops[3]; 1236 1.1 mrg 1237 1.1 mrg ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++); 1238 1.1 mrg 1239 1.1 mrg /* Loop. */ 1240 1.1 mrg ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab); 1241 1.1 mrg 1242 1.1 mrg /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */ 1243 1.1 mrg xops[0] = reg1; 1244 1.1 mrg xops[1] = GEN_INT (-PROBE_INTERVAL); 1245 1.1 mrg xops[2] = reg3; 1246 1.1 mrg if (TARGET_64BIT) 1247 1.1 mrg output_asm_insn ("sub.d\t%0,%0,%2", xops); 1248 1.1 mrg else 1249 1.1 mrg output_asm_insn ("sub.w\t%0,%0,%2", xops); 1250 1.1 mrg 1251 1.1 mrg /* Probe at TEST_ADDR, test if TEST_ADDR == LAST_ADDR and branch. */ 1252 1.1 mrg xops[1] = reg2; 1253 1.1 mrg strcpy (tmp, "bne\t%0,%1,"); 1254 1.1 mrg if (TARGET_64BIT) 1255 1.1 mrg output_asm_insn ("st.d\t$r0,%0,0", xops); 1256 1.1 mrg else 1257 1.1 mrg output_asm_insn ("st.w\t$r0,%0,0", xops); 1258 1.1 mrg output_asm_insn (strcat (tmp, &loop_lab[1]), xops); 1259 1.1 mrg 1260 1.1 mrg return ""; 1261 1.1 mrg } 1262 1.1 mrg 1263 1.1 mrg /* Expand the "prologue" pattern. */ 1264 1.1 mrg 1265 1.1 mrg void 1266 1.1 mrg loongarch_expand_prologue (void) 1267 1.1 mrg { 1268 1.1 mrg struct loongarch_frame_info *frame = &cfun->machine->frame; 1269 1.1 mrg HOST_WIDE_INT size = frame->total_size; 1270 1.1 mrg HOST_WIDE_INT tmp; 1271 1.1 mrg rtx insn; 1272 1.1 mrg 1273 1.1 mrg if (flag_stack_usage_info) 1274 1.1 mrg current_function_static_stack_size = size; 1275 1.1 mrg 1276 1.1 mrg if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK 1277 1.1 mrg || flag_stack_clash_protection) 1278 1.1 mrg { 1279 1.1 mrg if (crtl->is_leaf && !cfun->calls_alloca) 1280 1.1 mrg { 1281 1.1 mrg if (size > PROBE_INTERVAL && size > get_stack_check_protect ()) 1282 1.1 mrg { 1283 1.1 mrg tmp = size - get_stack_check_protect (); 1284 1.1 mrg loongarch_emit_probe_stack_range (get_stack_check_protect (), 1285 1.1 mrg tmp); 1286 1.1 mrg } 1287 1.1 mrg } 1288 1.1 mrg else if (size > 0) 1289 1.1 mrg loongarch_emit_probe_stack_range (get_stack_check_protect (), size); 1290 1.1 mrg } 1291 1.1 mrg 1292 1.1 mrg /* Save the registers. */ 1293 1.1 mrg if ((frame->mask | frame->fmask) != 0) 1294 1.1 mrg { 1295 1.1 mrg HOST_WIDE_INT step1 = MIN (size, loongarch_first_stack_step (frame)); 1296 1.1 mrg 1297 1.1 mrg insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1298 1.1 mrg GEN_INT (-step1)); 1299 1.1 mrg RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1300 1.1 mrg size -= step1; 1301 1.1 mrg loongarch_for_each_saved_reg (size, loongarch_save_reg, false); 1302 1.1 mrg } 1303 1.1 mrg 1304 1.1 mrg 1305 1.1 mrg /* Set up the frame pointer, if we're using one. */ 1306 1.1 mrg if (frame_pointer_needed) 1307 1.1 mrg { 1308 1.1 mrg insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, 1309 1.1 mrg GEN_INT (frame->hard_frame_pointer_offset - size)); 1310 1.1 mrg RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1311 1.1 mrg 1312 1.1 mrg loongarch_emit_stack_tie (); 1313 1.1 mrg } 1314 1.1 mrg 1315 1.1 mrg /* Allocate the rest of the frame. */ 1316 1.1 mrg if (size > 0) 1317 1.1 mrg { 1318 1.1 mrg if (IMM12_OPERAND (-size)) 1319 1.1 mrg { 1320 1.1 mrg insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1321 1.1 mrg GEN_INT (-size)); 1322 1.1 mrg RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1323 1.1 mrg } 1324 1.1 mrg else 1325 1.1 mrg { 1326 1.1 mrg loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), GEN_INT (-size)); 1327 1.1 mrg emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1328 1.1 mrg LARCH_PROLOGUE_TEMP (Pmode))); 1329 1.1 mrg 1330 1.1 mrg /* Describe the effect of the previous instructions. */ 1331 1.1 mrg insn = plus_constant (Pmode, stack_pointer_rtx, -size); 1332 1.1 mrg insn = gen_rtx_SET (stack_pointer_rtx, insn); 1333 1.1 mrg loongarch_set_frame_expr (insn); 1334 1.1 mrg } 1335 1.1 mrg } 1336 1.1 mrg } 1337 1.1 mrg 1338 1.1 mrg /* Return nonzero if this function is known to have a null epilogue. 1339 1.1 mrg This allows the optimizer to omit jumps to jumps if no stack 1340 1.1 mrg was created. */ 1341 1.1 mrg 1342 1.1 mrg bool 1343 1.1 mrg loongarch_can_use_return_insn (void) 1344 1.1 mrg { 1345 1.1 mrg return reload_completed && cfun->machine->frame.total_size == 0; 1346 1.1 mrg } 1347 1.1 mrg 1348 1.1 mrg /* Expand function epilogue using the following insn patterns: 1349 1.1 mrg "epilogue" (style == NORMAL_RETURN) 1350 1.1 mrg "sibcall_epilogue" (style == SIBCALL_RETURN) 1351 1.1 mrg "eh_return" (style == EXCEPTION_RETURN) */ 1352 1.1 mrg 1353 1.1 mrg void 1354 1.1 mrg loongarch_expand_epilogue (int style) 1355 1.1 mrg { 1356 1.1 mrg /* Split the frame into two. STEP1 is the amount of stack we should 1357 1.1 mrg deallocate before restoring the registers. STEP2 is the amount we 1358 1.1 mrg should deallocate afterwards. 1359 1.1 mrg 1360 1.1 mrg Start off by assuming that no registers need to be restored. */ 1361 1.1 mrg struct loongarch_frame_info *frame = &cfun->machine->frame; 1362 1.1 mrg HOST_WIDE_INT step1 = frame->total_size; 1363 1.1 mrg HOST_WIDE_INT step2 = 0; 1364 1.1 mrg rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); 1365 1.1 mrg rtx insn; 1366 1.1 mrg 1367 1.1 mrg /* We need to add memory barrier to prevent read from deallocated stack. */ 1368 1.1 mrg bool need_barrier_p 1369 1.1 mrg = (get_frame_size () + cfun->machine->frame.arg_pointer_offset) != 0; 1370 1.1 mrg 1371 1.1 mrg /* Handle simple returns. */ 1372 1.1 mrg if (style == NORMAL_RETURN && loongarch_can_use_return_insn ()) 1373 1.1 mrg { 1374 1.1 mrg emit_jump_insn (gen_return ()); 1375 1.1 mrg return; 1376 1.1 mrg } 1377 1.1 mrg 1378 1.1 mrg /* Move past any dynamic stack allocations. */ 1379 1.1 mrg if (cfun->calls_alloca) 1380 1.1 mrg { 1381 1.1 mrg /* Emit a barrier to prevent loads from a deallocated stack. */ 1382 1.1 mrg loongarch_emit_stack_tie (); 1383 1.1 mrg need_barrier_p = false; 1384 1.1 mrg 1385 1.1 mrg rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset); 1386 1.1 mrg if (!IMM12_OPERAND (INTVAL (adjust))) 1387 1.1 mrg { 1388 1.1 mrg loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust); 1389 1.1 mrg adjust = LARCH_PROLOGUE_TEMP (Pmode); 1390 1.1 mrg } 1391 1.1 mrg 1392 1.1 mrg insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1393 1.1 mrg hard_frame_pointer_rtx, 1394 1.1 mrg adjust)); 1395 1.1 mrg 1396 1.1 mrg rtx dwarf = NULL_RTX; 1397 1.1 mrg rtx minus_offset = GEN_INT (-frame->hard_frame_pointer_offset); 1398 1.1 mrg rtx cfa_adjust_value = gen_rtx_PLUS (Pmode, 1399 1.1 mrg hard_frame_pointer_rtx, 1400 1.1 mrg minus_offset); 1401 1.1 mrg 1402 1.1 mrg rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value); 1403 1.1 mrg dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf); 1404 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 1405 1.1 mrg 1406 1.1 mrg REG_NOTES (insn) = dwarf; 1407 1.1 mrg } 1408 1.1 mrg 1409 1.1 mrg /* If we need to restore registers, deallocate as much stack as 1410 1.1 mrg possible in the second step without going out of range. */ 1411 1.1 mrg if ((frame->mask | frame->fmask) != 0) 1412 1.1 mrg { 1413 1.1 mrg step2 = loongarch_first_stack_step (frame); 1414 1.1 mrg step1 -= step2; 1415 1.1 mrg } 1416 1.1 mrg 1417 1.1 mrg /* Set TARGET to BASE + STEP1. */ 1418 1.1 mrg if (step1 > 0) 1419 1.1 mrg { 1420 1.1 mrg /* Emit a barrier to prevent loads from a deallocated stack. */ 1421 1.1 mrg loongarch_emit_stack_tie (); 1422 1.1 mrg need_barrier_p = false; 1423 1.1 mrg 1424 1.1 mrg /* Get an rtx for STEP1 that we can add to BASE. */ 1425 1.1 mrg rtx adjust = GEN_INT (step1); 1426 1.1 mrg if (!IMM12_OPERAND (step1)) 1427 1.1 mrg { 1428 1.1 mrg loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust); 1429 1.1 mrg adjust = LARCH_PROLOGUE_TEMP (Pmode); 1430 1.1 mrg } 1431 1.1 mrg 1432 1.1 mrg insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1433 1.1 mrg stack_pointer_rtx, 1434 1.1 mrg adjust)); 1435 1.1 mrg 1436 1.1 mrg rtx dwarf = NULL_RTX; 1437 1.1 mrg rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 1438 1.1 mrg GEN_INT (step2)); 1439 1.1 mrg 1440 1.1 mrg dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); 1441 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 1442 1.1 mrg 1443 1.1 mrg REG_NOTES (insn) = dwarf; 1444 1.1 mrg } 1445 1.1 mrg 1446 1.1 mrg /* Restore the registers. */ 1447 1.1 mrg loongarch_for_each_saved_reg (frame->total_size - step2, 1448 1.1 mrg loongarch_restore_reg, 1449 1.1 mrg crtl->calls_eh_return 1450 1.1 mrg && style != EXCEPTION_RETURN); 1451 1.1 mrg 1452 1.1 mrg if (need_barrier_p) 1453 1.1 mrg loongarch_emit_stack_tie (); 1454 1.1 mrg 1455 1.1 mrg /* Deallocate the final bit of the frame. */ 1456 1.1 mrg if (step2 > 0) 1457 1.1 mrg { 1458 1.1 mrg insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1459 1.1 mrg stack_pointer_rtx, 1460 1.1 mrg GEN_INT (step2))); 1461 1.1 mrg 1462 1.1 mrg rtx dwarf = NULL_RTX; 1463 1.1 mrg rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx); 1464 1.1 mrg dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); 1465 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 1466 1.1 mrg 1467 1.1 mrg REG_NOTES (insn) = dwarf; 1468 1.1 mrg } 1469 1.1 mrg 1470 1.1 mrg /* Add in the __builtin_eh_return stack adjustment. */ 1471 1.1 mrg if (crtl->calls_eh_return && style == EXCEPTION_RETURN) 1472 1.1 mrg emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1473 1.1 mrg EH_RETURN_STACKADJ_RTX)); 1474 1.1 mrg 1475 1.1 mrg /* Emit return unless doing sibcall. */ 1476 1.1 mrg if (style != SIBCALL_RETURN) 1477 1.1 mrg emit_jump_insn (gen_simple_return_internal (ra)); 1478 1.1 mrg } 1479 1.1 mrg 1480 1.1 mrg #define LU32I_B (0xfffffULL << 32) 1481 1.1 mrg #define LU52I_B (0xfffULL << 52) 1482 1.1 mrg 1483 1.1 mrg /* Fill CODES with a sequence of rtl operations to load VALUE. 1484 1.1 mrg Return the number of operations needed. */ 1485 1.1 mrg 1486 1.1 mrg static unsigned int 1487 1.1 mrg loongarch_build_integer (struct loongarch_integer_op *codes, 1488 1.1 mrg HOST_WIDE_INT value) 1489 1.1 mrg 1490 1.1 mrg { 1491 1.1 mrg unsigned int cost = 0; 1492 1.1 mrg 1493 1.1 mrg /* Get the lower 32 bits of the value. */ 1494 1.1 mrg HOST_WIDE_INT low_part = (int32_t)value; 1495 1.1 mrg 1496 1.1 mrg if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part)) 1497 1.1 mrg { 1498 1.1 mrg /* The value of the lower 32 bit be loaded with one instruction. 1499 1.1 mrg lu12i.w. */ 1500 1.1 mrg codes[0].code = UNKNOWN; 1501 1.1 mrg codes[0].method = METHOD_NORMAL; 1502 1.1 mrg codes[0].value = low_part; 1503 1.1 mrg cost++; 1504 1.1 mrg } 1505 1.1 mrg else 1506 1.1 mrg { 1507 1.1 mrg /* lu12i.w + ior. */ 1508 1.1 mrg codes[0].code = UNKNOWN; 1509 1.1 mrg codes[0].method = METHOD_NORMAL; 1510 1.1 mrg codes[0].value = low_part & ~(IMM_REACH - 1); 1511 1.1 mrg cost++; 1512 1.1 mrg HOST_WIDE_INT iorv = low_part & (IMM_REACH - 1); 1513 1.1 mrg if (iorv != 0) 1514 1.1 mrg { 1515 1.1 mrg codes[1].code = IOR; 1516 1.1 mrg codes[1].method = METHOD_NORMAL; 1517 1.1 mrg codes[1].value = iorv; 1518 1.1 mrg cost++; 1519 1.1 mrg } 1520 1.1 mrg } 1521 1.1 mrg 1522 1.1 mrg if (TARGET_64BIT) 1523 1.1 mrg { 1524 1.1 mrg bool lu32i[2] = {(value & LU32I_B) == 0, (value & LU32I_B) == LU32I_B}; 1525 1.1 mrg bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B}; 1526 1.1 mrg 1527 1.1 mrg int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31; 1528 1.1 mrg int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51; 1529 1.1 mrg /* Determine whether the upper 32 bits are sign-extended from the lower 1530 1.1 mrg 32 bits. If it is, the instructions to load the high order can be 1531 1.1 mrg ommitted. */ 1532 1.1 mrg if (lu32i[sign31] && lu52i[sign31]) 1533 1.1 mrg return cost; 1534 1.1 mrg /* Determine whether bits 32-51 are sign-extended from the lower 32 1535 1.1 mrg bits. If so, directly load 52-63 bits. */ 1536 1.1 mrg else if (lu32i[sign31]) 1537 1.1 mrg { 1538 1.1 mrg codes[cost].method = METHOD_LU52I; 1539 1.1 mrg codes[cost].value = value & LU52I_B; 1540 1.1 mrg return cost + 1; 1541 1.1 mrg } 1542 1.1 mrg 1543 1.1 mrg codes[cost].method = METHOD_LU32I; 1544 1.1 mrg codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0); 1545 1.1 mrg cost++; 1546 1.1 mrg 1547 1.1 mrg /* Determine whether the 52-61 bits are sign-extended from the low order, 1548 1.1 mrg and if not, load the 52-61 bits. */ 1549 1.1 mrg if (!lu52i[(value & (HOST_WIDE_INT_1U << 51)) >> 51]) 1550 1.1 mrg { 1551 1.1 mrg codes[cost].method = METHOD_LU52I; 1552 1.1 mrg codes[cost].value = value & LU52I_B; 1553 1.1 mrg cost++; 1554 1.1 mrg } 1555 1.1 mrg } 1556 1.1 mrg 1557 1.1 mrg gcc_assert (cost <= LARCH_MAX_INTEGER_OPS); 1558 1.1 mrg 1559 1.1 mrg return cost; 1560 1.1 mrg } 1561 1.1 mrg 1562 1.1 mrg /* Fill CODES with a sequence of rtl operations to load VALUE. 1563 1.1 mrg Return the number of operations needed. 1564 1.1 mrg Split interger in loongarch_output_move. */ 1565 1.1 mrg 1566 1.1 mrg static unsigned int 1567 1.1 mrg loongarch_integer_cost (HOST_WIDE_INT value) 1568 1.1 mrg { 1569 1.1 mrg struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS]; 1570 1.1 mrg return loongarch_build_integer (codes, value); 1571 1.1 mrg } 1572 1.1 mrg 1573 1.1 mrg /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ 1574 1.1 mrg 1575 1.1 mrg static bool 1576 1.1 mrg loongarch_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) 1577 1.1 mrg { 1578 1.1 mrg return loongarch_const_insns (x) > 0; 1579 1.1 mrg } 1580 1.1 mrg 1581 1.1 mrg /* Return true if X is a thread-local symbol. */ 1582 1.1 mrg 1583 1.1 mrg static bool 1584 1.1 mrg loongarch_tls_symbol_p (rtx x) 1585 1.1 mrg { 1586 1.1 mrg return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0; 1587 1.1 mrg } 1588 1.1 mrg 1589 1.1 mrg /* Return true if SYMBOL_REF X is associated with a global symbol 1590 1.1 mrg (in the STB_GLOBAL sense). */ 1591 1.1 mrg 1592 1.1 mrg bool 1593 1.1 mrg loongarch_global_symbol_p (const_rtx x) 1594 1.1 mrg { 1595 1.1 mrg if (LABEL_REF_P (x)) 1596 1.1 mrg return false; 1597 1.1 mrg 1598 1.1 mrg const_tree decl = SYMBOL_REF_DECL (x); 1599 1.1 mrg 1600 1.1 mrg if (!decl) 1601 1.1 mrg return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x); 1602 1.1 mrg 1603 1.1 mrg /* Weakref symbols are not TREE_PUBLIC, but their targets are global 1604 1.1 mrg or weak symbols. Relocations in the object file will be against 1605 1.1 mrg the target symbol, so it's that symbol's binding that matters here. */ 1606 1.1 mrg return DECL_P (decl) && (TREE_PUBLIC (decl) || DECL_WEAK (decl)); 1607 1.1 mrg } 1608 1.1 mrg 1609 1.1 mrg bool 1610 1.1 mrg loongarch_global_symbol_noweak_p (const_rtx x) 1611 1.1 mrg { 1612 1.1 mrg if (LABEL_REF_P (x)) 1613 1.1 mrg return false; 1614 1.1 mrg 1615 1.1 mrg const_tree decl = SYMBOL_REF_DECL (x); 1616 1.1 mrg 1617 1.1 mrg if (!decl) 1618 1.1 mrg return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x); 1619 1.1 mrg 1620 1.1 mrg return DECL_P (decl) && TREE_PUBLIC (decl); 1621 1.1 mrg } 1622 1.1 mrg 1623 1.1 mrg bool 1624 1.1 mrg loongarch_weak_symbol_p (const_rtx x) 1625 1.1 mrg { 1626 1.1 mrg const_tree decl; 1627 1.1 mrg if (LABEL_REF_P (x) || !(decl = SYMBOL_REF_DECL (x))) 1628 1.1 mrg return false; 1629 1.1 mrg return DECL_P (decl) && DECL_WEAK (decl); 1630 1.1 mrg } 1631 1.1 mrg 1632 1.1 mrg /* Return true if SYMBOL_REF X binds locally. */ 1633 1.1 mrg 1634 1.1 mrg bool 1635 1.1 mrg loongarch_symbol_binds_local_p (const_rtx x) 1636 1.1 mrg { 1637 1.1 mrg if (LABEL_REF_P (x)) 1638 1.1 mrg return false; 1639 1.1 mrg 1640 1.1 mrg return (SYMBOL_REF_DECL (x) ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) 1641 1.1 mrg : SYMBOL_REF_LOCAL_P (x)); 1642 1.1 mrg } 1643 1.1 mrg 1644 1.1 mrg /* Return true if rtx constants of mode MODE should be put into a small 1645 1.1 mrg data section. */ 1646 1.1 mrg 1647 1.1 mrg static bool 1648 1.1 mrg loongarch_rtx_constant_in_small_data_p (machine_mode mode) 1649 1.1 mrg { 1650 1.1 mrg return (GET_MODE_SIZE (mode) <= g_switch_value); 1651 1.1 mrg } 1652 1.1 mrg 1653 1.1 mrg /* Return the method that should be used to access SYMBOL_REF or 1654 1.1 mrg LABEL_REF X. */ 1655 1.1 mrg 1656 1.1 mrg static enum loongarch_symbol_type 1657 1.1 mrg loongarch_classify_symbol (const_rtx x) 1658 1.1 mrg { 1659 1.1 mrg if (LABEL_REF_P (x)) 1660 1.1 mrg return SYMBOL_GOT_DISP; 1661 1.1 mrg 1662 1.1 mrg gcc_assert (SYMBOL_REF_P (x)); 1663 1.1 mrg 1664 1.1 mrg if (SYMBOL_REF_TLS_MODEL (x)) 1665 1.1 mrg return SYMBOL_TLS; 1666 1.1 mrg 1667 1.1 mrg if (SYMBOL_REF_P (x)) 1668 1.1 mrg return SYMBOL_GOT_DISP; 1669 1.1 mrg 1670 1.1 mrg return SYMBOL_GOT_DISP; 1671 1.1 mrg } 1672 1.1 mrg 1673 1.1 mrg /* Return true if X is a symbolic constant. If it is, 1674 1.1 mrg store the type of the symbol in *SYMBOL_TYPE. */ 1675 1.1 mrg 1676 1.1 mrg bool 1677 1.1 mrg loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type) 1678 1.1 mrg { 1679 1.1 mrg rtx offset; 1680 1.1 mrg 1681 1.1 mrg split_const (x, &x, &offset); 1682 1.1 mrg if (UNSPEC_ADDRESS_P (x)) 1683 1.1 mrg { 1684 1.1 mrg *symbol_type = UNSPEC_ADDRESS_TYPE (x); 1685 1.1 mrg x = UNSPEC_ADDRESS (x); 1686 1.1 mrg } 1687 1.1 mrg else if (SYMBOL_REF_P (x) || LABEL_REF_P (x)) 1688 1.1 mrg { 1689 1.1 mrg *symbol_type = loongarch_classify_symbol (x); 1690 1.1 mrg if (*symbol_type == SYMBOL_TLS) 1691 1.1 mrg return true; 1692 1.1 mrg } 1693 1.1 mrg else 1694 1.1 mrg return false; 1695 1.1 mrg 1696 1.1 mrg if (offset == const0_rtx) 1697 1.1 mrg return true; 1698 1.1 mrg 1699 1.1 mrg /* Check whether a nonzero offset is valid for the underlying 1700 1.1 mrg relocations. */ 1701 1.1 mrg switch (*symbol_type) 1702 1.1 mrg { 1703 1.1 mrg case SYMBOL_GOT_DISP: 1704 1.1 mrg case SYMBOL_TLSGD: 1705 1.1 mrg case SYMBOL_TLSLDM: 1706 1.1 mrg case SYMBOL_TLS: 1707 1.1 mrg return false; 1708 1.1 mrg } 1709 1.1 mrg gcc_unreachable (); 1710 1.1 mrg } 1711 1.1 mrg 1712 1.1 mrg /* Returns the number of instructions necessary to reference a symbol. */ 1713 1.1 mrg 1714 1.1 mrg static int 1715 1.1 mrg loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode) 1716 1.1 mrg { 1717 1.1 mrg switch (type) 1718 1.1 mrg { 1719 1.1 mrg case SYMBOL_GOT_DISP: 1720 1.1 mrg /* The constant will have to be loaded from the GOT before it 1721 1.1 mrg is used in an address. */ 1722 1.1 mrg if (mode != MAX_MACHINE_MODE) 1723 1.1 mrg return 0; 1724 1.1 mrg 1725 1.1 mrg return 3; 1726 1.1 mrg 1727 1.1 mrg case SYMBOL_TLSGD: 1728 1.1 mrg case SYMBOL_TLSLDM: 1729 1.1 mrg return 1; 1730 1.1 mrg 1731 1.1 mrg case SYMBOL_TLS: 1732 1.1 mrg /* We don't treat a bare TLS symbol as a constant. */ 1733 1.1 mrg return 0; 1734 1.1 mrg } 1735 1.1 mrg gcc_unreachable (); 1736 1.1 mrg } 1737 1.1 mrg 1738 1.1 mrg /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ 1739 1.1 mrg 1740 1.1 mrg static bool 1741 1.1 mrg loongarch_cannot_force_const_mem (machine_mode mode, rtx x) 1742 1.1 mrg { 1743 1.1 mrg enum loongarch_symbol_type type; 1744 1.1 mrg rtx base, offset; 1745 1.1 mrg 1746 1.1 mrg /* As an optimization, reject constants that loongarch_legitimize_move 1747 1.1 mrg can expand inline. 1748 1.1 mrg 1749 1.1 mrg Suppose we have a multi-instruction sequence that loads constant C 1750 1.1 mrg into register R. If R does not get allocated a hard register, and 1751 1.1 mrg R is used in an operand that allows both registers and memory 1752 1.1 mrg references, reload will consider forcing C into memory and using 1753 1.1 mrg one of the instruction's memory alternatives. Returning false 1754 1.1 mrg here will force it to use an input reload instead. */ 1755 1.1 mrg if (CONST_INT_P (x) && loongarch_legitimate_constant_p (mode, x)) 1756 1.1 mrg return true; 1757 1.1 mrg 1758 1.1 mrg split_const (x, &base, &offset); 1759 1.1 mrg if (loongarch_symbolic_constant_p (base, &type)) 1760 1.1 mrg { 1761 1.1 mrg /* The same optimization as for CONST_INT. */ 1762 1.1 mrg if (IMM12_INT (offset) 1763 1.1 mrg && loongarch_symbol_insns (type, MAX_MACHINE_MODE) > 0) 1764 1.1 mrg return true; 1765 1.1 mrg } 1766 1.1 mrg 1767 1.1 mrg /* TLS symbols must be computed by loongarch_legitimize_move. */ 1768 1.1 mrg if (tls_referenced_p (x)) 1769 1.1 mrg return true; 1770 1.1 mrg 1771 1.1 mrg return false; 1772 1.1 mrg } 1773 1.1 mrg 1774 1.1 mrg /* Return true if register REGNO is a valid base register for mode MODE. 1775 1.1 mrg STRICT_P is true if REG_OK_STRICT is in effect. */ 1776 1.1 mrg 1777 1.1 mrg int 1778 1.1 mrg loongarch_regno_mode_ok_for_base_p (int regno, 1779 1.1 mrg machine_mode mode ATTRIBUTE_UNUSED, 1780 1.1 mrg bool strict_p) 1781 1.1 mrg { 1782 1.1 mrg if (!HARD_REGISTER_NUM_P (regno)) 1783 1.1 mrg { 1784 1.1 mrg if (!strict_p) 1785 1.1 mrg return true; 1786 1.1 mrg regno = reg_renumber[regno]; 1787 1.1 mrg } 1788 1.1 mrg 1789 1.1 mrg /* These fake registers will be eliminated to either the stack or 1790 1.1 mrg hard frame pointer, both of which are usually valid base registers. 1791 1.1 mrg Reload deals with the cases where the eliminated form isn't valid. */ 1792 1.1 mrg if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) 1793 1.1 mrg return true; 1794 1.1 mrg 1795 1.1 mrg return GP_REG_P (regno); 1796 1.1 mrg } 1797 1.1 mrg 1798 1.1 mrg /* Return true if X is a valid base register for mode MODE. 1799 1.1 mrg STRICT_P is true if REG_OK_STRICT is in effect. */ 1800 1.1 mrg 1801 1.1 mrg static bool 1802 1.1 mrg loongarch_valid_base_register_p (rtx x, machine_mode mode, bool strict_p) 1803 1.1 mrg { 1804 1.1 mrg if (!strict_p && SUBREG_P (x)) 1805 1.1 mrg x = SUBREG_REG (x); 1806 1.1 mrg 1807 1.1 mrg return (REG_P (x) 1808 1.1 mrg && loongarch_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); 1809 1.1 mrg } 1810 1.1 mrg 1811 1.1 mrg /* Return true if, for every base register BASE_REG, (plus BASE_REG X) 1812 1.1 mrg can address a value of mode MODE. */ 1813 1.1 mrg 1814 1.1 mrg static bool 1815 1.1 mrg loongarch_valid_offset_p (rtx x, machine_mode mode) 1816 1.1 mrg { 1817 1.1 mrg /* Check that X is a signed 12-bit number, 1818 1.1 mrg or check that X is a signed 16-bit number 1819 1.1 mrg and offset 4 byte aligned. */ 1820 1.1 mrg if (!(const_arith_operand (x, Pmode) 1821 1.1 mrg || ((mode == E_SImode || mode == E_DImode) 1822 1.1 mrg && const_imm16_operand (x, Pmode) 1823 1.1 mrg && (loongarch_signed_immediate_p (INTVAL (x), 14, 2))))) 1824 1.1 mrg return false; 1825 1.1 mrg 1826 1.1 mrg /* We may need to split multiword moves, so make sure that every word 1827 1.1 mrg is accessible. */ 1828 1.1 mrg if (GET_MODE_SIZE (mode) > UNITS_PER_WORD 1829 1.1 mrg && !IMM12_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) 1830 1.1 mrg return false; 1831 1.1 mrg 1832 1.1 mrg return true; 1833 1.1 mrg } 1834 1.1 mrg 1835 1.1 mrg static bool 1836 1.1 mrg loongarch_valid_index_p (struct loongarch_address_info *info, rtx x, 1837 1.1 mrg machine_mode mode, bool strict_p) 1838 1.1 mrg { 1839 1.1 mrg rtx index; 1840 1.1 mrg 1841 1.1 mrg if ((REG_P (x) || SUBREG_P (x)) 1842 1.1 mrg && GET_MODE (x) == Pmode) 1843 1.1 mrg { 1844 1.1 mrg index = x; 1845 1.1 mrg } 1846 1.1 mrg else 1847 1.1 mrg return false; 1848 1.1 mrg 1849 1.1 mrg if (!strict_p 1850 1.1 mrg && SUBREG_P (index) 1851 1.1 mrg && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))]) 1852 1.1 mrg index = SUBREG_REG (index); 1853 1.1 mrg 1854 1.1 mrg if (loongarch_valid_base_register_p (index, mode, strict_p)) 1855 1.1 mrg { 1856 1.1 mrg info->type = ADDRESS_REG_REG; 1857 1.1 mrg info->offset = index; 1858 1.1 mrg return true; 1859 1.1 mrg } 1860 1.1 mrg 1861 1.1 mrg return false; 1862 1.1 mrg } 1863 1.1 mrg 1864 1.1 mrg /* Return true if X is a valid address for machine mode MODE. If it is, 1865 1.1 mrg fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in 1866 1.1 mrg effect. */ 1867 1.1 mrg 1868 1.1 mrg static bool 1869 1.1 mrg loongarch_classify_address (struct loongarch_address_info *info, rtx x, 1870 1.1 mrg machine_mode mode, bool strict_p) 1871 1.1 mrg { 1872 1.1 mrg switch (GET_CODE (x)) 1873 1.1 mrg { 1874 1.1 mrg case REG: 1875 1.1 mrg case SUBREG: 1876 1.1 mrg info->type = ADDRESS_REG; 1877 1.1 mrg info->reg = x; 1878 1.1 mrg info->offset = const0_rtx; 1879 1.1 mrg return loongarch_valid_base_register_p (info->reg, mode, strict_p); 1880 1.1 mrg 1881 1.1 mrg case PLUS: 1882 1.1 mrg if (loongarch_valid_base_register_p (XEXP (x, 0), mode, strict_p) 1883 1.1 mrg && loongarch_valid_index_p (info, XEXP (x, 1), mode, strict_p)) 1884 1.1 mrg { 1885 1.1 mrg info->reg = XEXP (x, 0); 1886 1.1 mrg return true; 1887 1.1 mrg } 1888 1.1 mrg 1889 1.1 mrg if (loongarch_valid_base_register_p (XEXP (x, 1), mode, strict_p) 1890 1.1 mrg && loongarch_valid_index_p (info, XEXP (x, 0), mode, strict_p)) 1891 1.1 mrg { 1892 1.1 mrg info->reg = XEXP (x, 1); 1893 1.1 mrg return true; 1894 1.1 mrg } 1895 1.1 mrg 1896 1.1 mrg info->type = ADDRESS_REG; 1897 1.1 mrg info->reg = XEXP (x, 0); 1898 1.1 mrg info->offset = XEXP (x, 1); 1899 1.1 mrg return (loongarch_valid_base_register_p (info->reg, mode, strict_p) 1900 1.1 mrg && loongarch_valid_offset_p (info->offset, mode)); 1901 1.1 mrg default: 1902 1.1 mrg return false; 1903 1.1 mrg } 1904 1.1 mrg } 1905 1.1 mrg 1906 1.1 mrg /* Implement TARGET_LEGITIMATE_ADDRESS_P. */ 1907 1.1 mrg 1908 1.1 mrg static bool 1909 1.1 mrg loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p) 1910 1.1 mrg { 1911 1.1 mrg struct loongarch_address_info addr; 1912 1.1 mrg 1913 1.1 mrg return loongarch_classify_address (&addr, x, mode, strict_p); 1914 1.1 mrg } 1915 1.1 mrg 1916 1.1 mrg /* Return true if ADDR matches the pattern for the indexed address 1917 1.1 mrg instruction. */ 1918 1.1 mrg 1919 1.1 mrg static bool 1920 1.1 mrg loongarch_index_address_p (rtx addr, machine_mode mode ATTRIBUTE_UNUSED) 1921 1.1 mrg { 1922 1.1 mrg if (GET_CODE (addr) != PLUS 1923 1.1 mrg || !REG_P (XEXP (addr, 0)) 1924 1.1 mrg || !REG_P (XEXP (addr, 1))) 1925 1.1 mrg return false; 1926 1.1 mrg return true; 1927 1.1 mrg } 1928 1.1 mrg 1929 1.1 mrg /* Return the number of instructions needed to load or store a value 1930 1.1 mrg of mode MODE at address X. Return 0 if X isn't valid for MODE. 1931 1.1 mrg Assume that multiword moves may need to be split into word moves 1932 1.1 mrg if MIGHT_SPLIT_P, otherwise assume that a single load or store is 1933 1.1 mrg enough. */ 1934 1.1 mrg 1935 1.1 mrg int 1936 1.1 mrg loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p) 1937 1.1 mrg { 1938 1.1 mrg struct loongarch_address_info addr; 1939 1.1 mrg int factor; 1940 1.1 mrg 1941 1.1 mrg if (!loongarch_classify_address (&addr, x, mode, false)) 1942 1.1 mrg return 0; 1943 1.1 mrg 1944 1.1 mrg /* BLKmode is used for single unaligned loads and stores and should 1945 1.1 mrg not count as a multiword mode. (GET_MODE_SIZE (BLKmode) is pretty 1946 1.1 mrg meaningless, so we have to single it out as a special case one way 1947 1.1 mrg or the other.) */ 1948 1.1 mrg if (mode != BLKmode && might_split_p) 1949 1.1 mrg factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 1950 1.1 mrg else 1951 1.1 mrg factor = 1; 1952 1.1 mrg 1953 1.1 mrg if (loongarch_classify_address (&addr, x, mode, false)) 1954 1.1 mrg switch (addr.type) 1955 1.1 mrg { 1956 1.1 mrg case ADDRESS_REG: 1957 1.1 mrg return factor; 1958 1.1 mrg 1959 1.1 mrg case ADDRESS_REG_REG: 1960 1.1 mrg return factor; 1961 1.1 mrg 1962 1.1 mrg case ADDRESS_CONST_INT: 1963 1.1 mrg return factor; 1964 1.1 mrg 1965 1.1 mrg case ADDRESS_SYMBOLIC: 1966 1.1 mrg return factor * loongarch_symbol_insns (addr.symbol_type, mode); 1967 1.1 mrg } 1968 1.1 mrg return 0; 1969 1.1 mrg } 1970 1.1 mrg 1971 1.1 mrg /* Return true if X fits within an unsigned field of BITS bits that is 1972 1.1 mrg shifted left SHIFT bits before being used. */ 1973 1.1 mrg 1974 1.1 mrg bool 1975 1.1 mrg loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits, 1976 1.1 mrg int shift = 0) 1977 1.1 mrg { 1978 1.1 mrg return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits)); 1979 1.1 mrg } 1980 1.1 mrg 1981 1.1 mrg /* Return true if X fits within a signed field of BITS bits that is 1982 1.1 mrg shifted left SHIFT bits before being used. */ 1983 1.1 mrg 1984 1.1 mrg bool 1985 1.1 mrg loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits, 1986 1.1 mrg int shift = 0) 1987 1.1 mrg { 1988 1.1 mrg x += 1 << (bits + shift - 1); 1989 1.1 mrg return loongarch_unsigned_immediate_p (x, bits, shift); 1990 1.1 mrg } 1991 1.1 mrg 1992 1.1 mrg /* Return true if X is a legitimate address with a 12-bit offset. 1993 1.1 mrg MODE is the mode of the value being accessed. */ 1994 1.1 mrg 1995 1.1 mrg bool 1996 1.1 mrg loongarch_12bit_offset_address_p (rtx x, machine_mode mode) 1997 1.1 mrg { 1998 1.1 mrg struct loongarch_address_info addr; 1999 1.1 mrg 2000 1.1 mrg return (loongarch_classify_address (&addr, x, mode, false) 2001 1.1 mrg && addr.type == ADDRESS_REG 2002 1.1 mrg && CONST_INT_P (addr.offset) 2003 1.1 mrg && LARCH_U12BIT_OFFSET_P (INTVAL (addr.offset))); 2004 1.1 mrg } 2005 1.1 mrg 2006 1.1 mrg /* Return true if X is a legitimate address with a 14-bit offset shifted 2. 2007 1.1 mrg MODE is the mode of the value being accessed. */ 2008 1.1 mrg 2009 1.1 mrg bool 2010 1.1 mrg loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode) 2011 1.1 mrg { 2012 1.1 mrg struct loongarch_address_info addr; 2013 1.1 mrg 2014 1.1 mrg return (loongarch_classify_address (&addr, x, mode, false) 2015 1.1 mrg && addr.type == ADDRESS_REG 2016 1.1 mrg && CONST_INT_P (addr.offset) 2017 1.1 mrg && LARCH_16BIT_OFFSET_P (INTVAL (addr.offset)) 2018 1.1 mrg && LARCH_SHIFT_2_OFFSET_P (INTVAL (addr.offset))); 2019 1.1 mrg } 2020 1.1 mrg 2021 1.1 mrg bool 2022 1.1 mrg loongarch_base_index_address_p (rtx x, machine_mode mode) 2023 1.1 mrg { 2024 1.1 mrg struct loongarch_address_info addr; 2025 1.1 mrg 2026 1.1 mrg return (loongarch_classify_address (&addr, x, mode, false) 2027 1.1 mrg && addr.type == ADDRESS_REG_REG 2028 1.1 mrg && REG_P (addr.offset)); 2029 1.1 mrg } 2030 1.1 mrg 2031 1.1 mrg /* Return the number of instructions needed to load constant X, 2032 1.1 mrg Return 0 if X isn't a valid constant. */ 2033 1.1 mrg 2034 1.1 mrg int 2035 1.1 mrg loongarch_const_insns (rtx x) 2036 1.1 mrg { 2037 1.1 mrg enum loongarch_symbol_type symbol_type; 2038 1.1 mrg rtx offset; 2039 1.1 mrg 2040 1.1 mrg switch (GET_CODE (x)) 2041 1.1 mrg { 2042 1.1 mrg case CONST_INT: 2043 1.1 mrg return loongarch_integer_cost (INTVAL (x)); 2044 1.1 mrg 2045 1.1 mrg case CONST_VECTOR: 2046 1.1 mrg /* Fall through. */ 2047 1.1 mrg case CONST_DOUBLE: 2048 1.1 mrg return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; 2049 1.1 mrg 2050 1.1 mrg case CONST: 2051 1.1 mrg /* See if we can refer to X directly. */ 2052 1.1 mrg if (loongarch_symbolic_constant_p (x, &symbol_type)) 2053 1.1 mrg return loongarch_symbol_insns (symbol_type, MAX_MACHINE_MODE); 2054 1.1 mrg 2055 1.1 mrg /* Otherwise try splitting the constant into a base and offset. 2056 1.1 mrg If the offset is a 12-bit value, we can load the base address 2057 1.1 mrg into a register and then use ADDI.{W/D} to add in the offset. 2058 1.1 mrg If the offset is larger, we can load the base and offset 2059 1.1 mrg into separate registers and add them together with ADD.{W/D}. 2060 1.1 mrg However, the latter is only possible before reload; during 2061 1.1 mrg and after reload, we must have the option of forcing the 2062 1.1 mrg constant into the pool instead. */ 2063 1.1 mrg split_const (x, &x, &offset); 2064 1.1 mrg if (offset != 0) 2065 1.1 mrg { 2066 1.1 mrg int n = loongarch_const_insns (x); 2067 1.1 mrg if (n != 0) 2068 1.1 mrg { 2069 1.1 mrg if (IMM12_INT (offset)) 2070 1.1 mrg return n + 1; 2071 1.1 mrg else if (!targetm.cannot_force_const_mem (GET_MODE (x), x)) 2072 1.1 mrg return n + 1 + loongarch_integer_cost (INTVAL (offset)); 2073 1.1 mrg } 2074 1.1 mrg } 2075 1.1 mrg return 0; 2076 1.1 mrg 2077 1.1 mrg case SYMBOL_REF: 2078 1.1 mrg case LABEL_REF: 2079 1.1 mrg return loongarch_symbol_insns ( 2080 1.1 mrg loongarch_classify_symbol (x), MAX_MACHINE_MODE); 2081 1.1 mrg 2082 1.1 mrg default: 2083 1.1 mrg return 0; 2084 1.1 mrg } 2085 1.1 mrg } 2086 1.1 mrg 2087 1.1 mrg /* X is a doubleword constant that can be handled by splitting it into 2088 1.1 mrg two words and loading each word separately. Return the number of 2089 1.1 mrg instructions required to do this. */ 2090 1.1 mrg 2091 1.1 mrg int 2092 1.1 mrg loongarch_split_const_insns (rtx x) 2093 1.1 mrg { 2094 1.1 mrg unsigned int low, high; 2095 1.1 mrg 2096 1.1 mrg low = loongarch_const_insns (loongarch_subword (x, false)); 2097 1.1 mrg high = loongarch_const_insns (loongarch_subword (x, true)); 2098 1.1 mrg gcc_assert (low > 0 && high > 0); 2099 1.1 mrg return low + high; 2100 1.1 mrg } 2101 1.1 mrg 2102 1.1 mrg /* Return the number of instructions needed to implement INSN, 2103 1.1 mrg given that it loads from or stores to MEM. */ 2104 1.1 mrg 2105 1.1 mrg int 2106 1.1 mrg loongarch_load_store_insns (rtx mem, rtx_insn *insn) 2107 1.1 mrg { 2108 1.1 mrg machine_mode mode; 2109 1.1 mrg bool might_split_p; 2110 1.1 mrg rtx set; 2111 1.1 mrg 2112 1.1 mrg gcc_assert (MEM_P (mem)); 2113 1.1 mrg mode = GET_MODE (mem); 2114 1.1 mrg 2115 1.1 mrg /* Try to prove that INSN does not need to be split. */ 2116 1.1 mrg might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD; 2117 1.1 mrg if (might_split_p) 2118 1.1 mrg { 2119 1.1 mrg set = single_set (insn); 2120 1.1 mrg if (set 2121 1.1 mrg && !loongarch_split_move_insn_p (SET_DEST (set), SET_SRC (set))) 2122 1.1 mrg might_split_p = false; 2123 1.1 mrg } 2124 1.1 mrg 2125 1.1 mrg return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p); 2126 1.1 mrg } 2127 1.1 mrg 2128 1.1 mrg /* Return true if we need to trap on division by zero. */ 2129 1.1 mrg 2130 1.1 mrg static bool 2131 1.1 mrg loongarch_check_zero_div_p (void) 2132 1.1 mrg { 2133 1.1 mrg /* if -m[no-]check-zero-division is given explicitly. */ 2134 1.1 mrg if (target_flags_explicit & MASK_CHECK_ZERO_DIV) 2135 1.1 mrg return TARGET_CHECK_ZERO_DIV; 2136 1.1 mrg 2137 1.1 mrg /* if not, don't trap for optimized code except -Og. */ 2138 1.1 mrg return !optimize || optimize_debug; 2139 1.1 mrg } 2140 1.1 mrg 2141 1.1 mrg /* Return the number of instructions needed for an integer division. */ 2142 1.1 mrg 2143 1.1 mrg int 2144 1.1 mrg loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED) 2145 1.1 mrg { 2146 1.1 mrg int count; 2147 1.1 mrg 2148 1.1 mrg count = 1; 2149 1.1 mrg if (loongarch_check_zero_div_p ()) 2150 1.1 mrg count += 2; 2151 1.1 mrg 2152 1.1 mrg return count; 2153 1.1 mrg } 2154 1.1 mrg 2155 1.1 mrg /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */ 2156 1.1 mrg 2157 1.1 mrg void 2158 1.1 mrg loongarch_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1) 2159 1.1 mrg { 2160 1.1 mrg emit_insn (gen_rtx_SET (target, gen_rtx_fmt_ee (code, GET_MODE (target), 2161 1.1 mrg op0, op1))); 2162 1.1 mrg } 2163 1.1 mrg 2164 1.1 mrg /* Compute (CODE OP0 OP1) and store the result in a new register 2165 1.1 mrg of mode MODE. Return that new register. */ 2166 1.1 mrg 2167 1.1 mrg static rtx 2168 1.1 mrg loongarch_force_binary (machine_mode mode, enum rtx_code code, rtx op0, 2169 1.1 mrg rtx op1) 2170 1.1 mrg { 2171 1.1 mrg rtx reg; 2172 1.1 mrg 2173 1.1 mrg reg = gen_reg_rtx (mode); 2174 1.1 mrg loongarch_emit_binary (code, reg, op0, op1); 2175 1.1 mrg return reg; 2176 1.1 mrg } 2177 1.1 mrg 2178 1.1 mrg /* Copy VALUE to a register and return that register. If new pseudos 2179 1.1 mrg are allowed, copy it into a new register, otherwise use DEST. */ 2180 1.1 mrg 2181 1.1 mrg static rtx 2182 1.1 mrg loongarch_force_temporary (rtx dest, rtx value) 2183 1.1 mrg { 2184 1.1 mrg if (can_create_pseudo_p ()) 2185 1.1 mrg return force_reg (Pmode, value); 2186 1.1 mrg else 2187 1.1 mrg { 2188 1.1 mrg loongarch_emit_move (dest, value); 2189 1.1 mrg return dest; 2190 1.1 mrg } 2191 1.1 mrg } 2192 1.1 mrg 2193 1.1 mrg /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE, 2194 1.1 mrg then add CONST_INT OFFSET to the result. */ 2195 1.1 mrg 2196 1.1 mrg static rtx 2197 1.1 mrg loongarch_unspec_address_offset (rtx base, rtx offset, 2198 1.1 mrg enum loongarch_symbol_type symbol_type) 2199 1.1 mrg { 2200 1.1 mrg base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 2201 1.1 mrg UNSPEC_ADDRESS_FIRST + symbol_type); 2202 1.1 mrg if (offset != const0_rtx) 2203 1.1 mrg base = gen_rtx_PLUS (Pmode, base, offset); 2204 1.1 mrg return gen_rtx_CONST (Pmode, base); 2205 1.1 mrg } 2206 1.1 mrg 2207 1.1 mrg /* Return an UNSPEC address with underlying address ADDRESS and symbol 2208 1.1 mrg type SYMBOL_TYPE. */ 2209 1.1 mrg 2210 1.1 mrg rtx 2211 1.1 mrg loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type) 2212 1.1 mrg { 2213 1.1 mrg rtx base, offset; 2214 1.1 mrg 2215 1.1 mrg split_const (address, &base, &offset); 2216 1.1 mrg return loongarch_unspec_address_offset (base, offset, symbol_type); 2217 1.1 mrg } 2218 1.1 mrg 2219 1.1 mrg /* If OP is an UNSPEC address, return the address to which it refers, 2220 1.1 mrg otherwise return OP itself. */ 2221 1.1 mrg 2222 1.1 mrg rtx 2223 1.1 mrg loongarch_strip_unspec_address (rtx op) 2224 1.1 mrg { 2225 1.1 mrg rtx base, offset; 2226 1.1 mrg 2227 1.1 mrg split_const (op, &base, &offset); 2228 1.1 mrg if (UNSPEC_ADDRESS_P (base)) 2229 1.1 mrg op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset)); 2230 1.1 mrg return op; 2231 1.1 mrg } 2232 1.1 mrg 2233 1.1 mrg /* Return a legitimate address for REG + OFFSET. TEMP is as for 2234 1.1 mrg loongarch_force_temporary; it is only needed when OFFSET is not a 2235 1.1 mrg IMM12_OPERAND. */ 2236 1.1 mrg 2237 1.1 mrg static rtx 2238 1.1 mrg loongarch_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) 2239 1.1 mrg { 2240 1.1 mrg if (!IMM12_OPERAND (offset)) 2241 1.1 mrg { 2242 1.1 mrg rtx high; 2243 1.1 mrg 2244 1.1 mrg /* Leave OFFSET as a 12-bit offset and put the excess in HIGH. 2245 1.1 mrg The addition inside the macro CONST_HIGH_PART may cause an 2246 1.1 mrg overflow, so we need to force a sign-extension check. */ 2247 1.1 mrg high = gen_int_mode (CONST_HIGH_PART (offset), Pmode); 2248 1.1 mrg offset = CONST_LOW_PART (offset); 2249 1.1 mrg high = loongarch_force_temporary (temp, high); 2250 1.1 mrg reg = loongarch_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); 2251 1.1 mrg } 2252 1.1 mrg return plus_constant (Pmode, reg, offset); 2253 1.1 mrg } 2254 1.1 mrg 2255 1.1 mrg /* The __tls_get_attr symbol. */ 2256 1.1 mrg static GTY (()) rtx loongarch_tls_symbol; 2257 1.1 mrg 2258 1.1 mrg /* Load an entry from the GOT for a TLS GD access. */ 2259 1.1 mrg 2260 1.1 mrg static rtx 2261 1.1 mrg loongarch_got_load_tls_gd (rtx dest, rtx sym) 2262 1.1 mrg { 2263 1.1 mrg return gen_got_load_tls_gd (Pmode, dest, sym); 2264 1.1 mrg } 2265 1.1 mrg 2266 1.1 mrg /* Load an entry from the GOT for a TLS LD access. */ 2267 1.1 mrg 2268 1.1 mrg static rtx 2269 1.1 mrg loongarch_got_load_tls_ld (rtx dest, rtx sym) 2270 1.1 mrg { 2271 1.1 mrg return gen_got_load_tls_ld (Pmode, dest, sym); 2272 1.1 mrg } 2273 1.1 mrg 2274 1.1 mrg /* Load an entry from the GOT for a TLS IE access. */ 2275 1.1 mrg 2276 1.1 mrg static rtx 2277 1.1 mrg loongarch_got_load_tls_ie (rtx dest, rtx sym) 2278 1.1 mrg { 2279 1.1 mrg return gen_got_load_tls_ie (Pmode, dest, sym); 2280 1.1 mrg } 2281 1.1 mrg 2282 1.1 mrg /* Add in the thread pointer for a TLS LE access. */ 2283 1.1 mrg 2284 1.1 mrg static rtx 2285 1.1 mrg loongarch_got_load_tls_le (rtx dest, rtx sym) 2286 1.1 mrg { 2287 1.1 mrg return gen_got_load_tls_le (Pmode, dest, sym); 2288 1.1 mrg } 2289 1.1 mrg 2290 1.1 mrg /* Return an instruction sequence that calls __tls_get_addr. SYM is 2291 1.1 mrg the TLS symbol we are referencing and TYPE is the symbol type to use 2292 1.1 mrg (either global dynamic or local dynamic). V0 is an RTX for the 2293 1.1 mrg return value location. */ 2294 1.1 mrg 2295 1.1 mrg static rtx_insn * 2296 1.1 mrg loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0) 2297 1.1 mrg { 2298 1.1 mrg rtx loc, a0; 2299 1.1 mrg rtx_insn *insn; 2300 1.1 mrg 2301 1.1 mrg a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); 2302 1.1 mrg 2303 1.1 mrg if (!loongarch_tls_symbol) 2304 1.1 mrg loongarch_tls_symbol = init_one_libfunc ("__tls_get_addr"); 2305 1.1 mrg 2306 1.1 mrg loc = loongarch_unspec_address (sym, type); 2307 1.1 mrg 2308 1.1 mrg start_sequence (); 2309 1.1 mrg 2310 1.1 mrg if (type == SYMBOL_TLSLDM) 2311 1.1 mrg emit_insn (loongarch_got_load_tls_ld (a0, loc)); 2312 1.1 mrg else if (type == SYMBOL_TLSGD) 2313 1.1 mrg emit_insn (loongarch_got_load_tls_gd (a0, loc)); 2314 1.1 mrg else 2315 1.1 mrg gcc_unreachable (); 2316 1.1 mrg 2317 1.1 mrg insn = emit_call_insn (gen_call_value_internal (v0, loongarch_tls_symbol, 2318 1.1 mrg const0_rtx)); 2319 1.1 mrg RTL_CONST_CALL_P (insn) = 1; 2320 1.1 mrg use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); 2321 1.1 mrg insn = get_insns (); 2322 1.1 mrg 2323 1.1 mrg end_sequence (); 2324 1.1 mrg 2325 1.1 mrg return insn; 2326 1.1 mrg } 2327 1.1 mrg 2328 1.1 mrg /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return 2329 1.1 mrg its address. The return value will be both a valid address and a valid 2330 1.1 mrg SET_SRC (either a REG or a LO_SUM). */ 2331 1.1 mrg 2332 1.1 mrg static rtx 2333 1.1 mrg loongarch_legitimize_tls_address (rtx loc) 2334 1.1 mrg { 2335 1.1 mrg rtx dest, tp, tmp; 2336 1.1 mrg enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); 2337 1.1 mrg rtx_insn *insn; 2338 1.1 mrg 2339 1.1 mrg switch (model) 2340 1.1 mrg { 2341 1.1 mrg case TLS_MODEL_LOCAL_DYNAMIC: 2342 1.1 mrg tmp = gen_rtx_REG (Pmode, GP_RETURN); 2343 1.1 mrg dest = gen_reg_rtx (Pmode); 2344 1.1 mrg insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp); 2345 1.1 mrg emit_libcall_block (insn, dest, tmp, loc); 2346 1.1 mrg break; 2347 1.1 mrg 2348 1.1 mrg case TLS_MODEL_GLOBAL_DYNAMIC: 2349 1.1 mrg tmp = gen_rtx_REG (Pmode, GP_RETURN); 2350 1.1 mrg dest = gen_reg_rtx (Pmode); 2351 1.1 mrg insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp); 2352 1.1 mrg emit_libcall_block (insn, dest, tmp, loc); 2353 1.1 mrg break; 2354 1.1 mrg 2355 1.1 mrg case TLS_MODEL_INITIAL_EXEC: 2356 1.1 mrg /* la.tls.ie; tp-relative add */ 2357 1.1 mrg tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); 2358 1.1 mrg tmp = gen_reg_rtx (Pmode); 2359 1.1 mrg emit_insn (loongarch_got_load_tls_ie (tmp, loc)); 2360 1.1 mrg dest = gen_reg_rtx (Pmode); 2361 1.1 mrg emit_insn (gen_add3_insn (dest, tmp, tp)); 2362 1.1 mrg break; 2363 1.1 mrg 2364 1.1 mrg case TLS_MODEL_LOCAL_EXEC: 2365 1.1 mrg /* la.tls.le; tp-relative add */ 2366 1.1 mrg tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); 2367 1.1 mrg tmp = gen_reg_rtx (Pmode); 2368 1.1 mrg emit_insn (loongarch_got_load_tls_le (tmp, loc)); 2369 1.1 mrg dest = gen_reg_rtx (Pmode); 2370 1.1 mrg emit_insn (gen_add3_insn (dest, tmp, tp)); 2371 1.1 mrg break; 2372 1.1 mrg 2373 1.1 mrg default: 2374 1.1 mrg gcc_unreachable (); 2375 1.1 mrg } 2376 1.1 mrg return dest; 2377 1.1 mrg } 2378 1.1 mrg 2379 1.1 mrg rtx 2380 1.1 mrg loongarch_legitimize_call_address (rtx addr) 2381 1.1 mrg { 2382 1.1 mrg if (!call_insn_operand (addr, VOIDmode)) 2383 1.1 mrg { 2384 1.1 mrg rtx reg = gen_reg_rtx (Pmode); 2385 1.1 mrg loongarch_emit_move (reg, addr); 2386 1.1 mrg return reg; 2387 1.1 mrg } 2388 1.1 mrg return addr; 2389 1.1 mrg } 2390 1.1 mrg 2391 1.1 mrg /* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR 2392 1.1 mrg and *OFFSET_PTR. Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise. */ 2393 1.1 mrg 2394 1.1 mrg static void 2395 1.1 mrg loongarch_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr) 2396 1.1 mrg { 2397 1.1 mrg if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))) 2398 1.1 mrg { 2399 1.1 mrg *base_ptr = XEXP (x, 0); 2400 1.1 mrg *offset_ptr = INTVAL (XEXP (x, 1)); 2401 1.1 mrg } 2402 1.1 mrg else 2403 1.1 mrg { 2404 1.1 mrg *base_ptr = x; 2405 1.1 mrg *offset_ptr = 0; 2406 1.1 mrg } 2407 1.1 mrg } 2408 1.1 mrg 2409 1.1 mrg /* If X is not a valid address for mode MODE, force it into a register. */ 2410 1.1 mrg 2411 1.1 mrg static rtx 2412 1.1 mrg loongarch_force_address (rtx x, machine_mode mode) 2413 1.1 mrg { 2414 1.1 mrg if (!loongarch_legitimate_address_p (mode, x, false)) 2415 1.1 mrg x = force_reg (Pmode, x); 2416 1.1 mrg return x; 2417 1.1 mrg } 2418 1.1 mrg 2419 1.1 mrg /* This function is used to implement LEGITIMIZE_ADDRESS. If X can 2420 1.1 mrg be legitimized in a way that the generic machinery might not expect, 2421 1.1 mrg return a new address, otherwise return NULL. MODE is the mode of 2422 1.1 mrg the memory being accessed. */ 2423 1.1 mrg 2424 1.1 mrg static rtx 2425 1.1 mrg loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, 2426 1.1 mrg machine_mode mode) 2427 1.1 mrg { 2428 1.1 mrg rtx base, addr; 2429 1.1 mrg HOST_WIDE_INT offset; 2430 1.1 mrg 2431 1.1 mrg if (loongarch_tls_symbol_p (x)) 2432 1.1 mrg return loongarch_legitimize_tls_address (x); 2433 1.1 mrg 2434 1.1 mrg /* Handle BASE + OFFSET using loongarch_add_offset. */ 2435 1.1 mrg loongarch_split_plus (x, &base, &offset); 2436 1.1 mrg if (offset != 0) 2437 1.1 mrg { 2438 1.1 mrg if (!loongarch_valid_base_register_p (base, mode, false)) 2439 1.1 mrg base = copy_to_mode_reg (Pmode, base); 2440 1.1 mrg addr = loongarch_add_offset (NULL, base, offset); 2441 1.1 mrg return loongarch_force_address (addr, mode); 2442 1.1 mrg } 2443 1.1 mrg 2444 1.1 mrg return x; 2445 1.1 mrg } 2446 1.1 mrg 2447 1.1 mrg /* Load VALUE into DEST. TEMP is as for loongarch_force_temporary. */ 2448 1.1 mrg 2449 1.1 mrg void 2450 1.1 mrg loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) 2451 1.1 mrg { 2452 1.1 mrg struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS]; 2453 1.1 mrg machine_mode mode; 2454 1.1 mrg unsigned int i, num_ops; 2455 1.1 mrg rtx x; 2456 1.1 mrg 2457 1.1 mrg mode = GET_MODE (dest); 2458 1.1 mrg num_ops = loongarch_build_integer (codes, value); 2459 1.1 mrg 2460 1.1 mrg /* Apply each binary operation to X. Invariant: X is a legitimate 2461 1.1 mrg source operand for a SET pattern. */ 2462 1.1 mrg x = GEN_INT (codes[0].value); 2463 1.1 mrg for (i = 1; i < num_ops; i++) 2464 1.1 mrg { 2465 1.1 mrg if (!can_create_pseudo_p ()) 2466 1.1 mrg { 2467 1.1 mrg emit_insn (gen_rtx_SET (temp, x)); 2468 1.1 mrg x = temp; 2469 1.1 mrg } 2470 1.1 mrg else 2471 1.1 mrg x = force_reg (mode, x); 2472 1.1 mrg 2473 1.1 mrg switch (codes[i].method) 2474 1.1 mrg { 2475 1.1 mrg case METHOD_NORMAL: 2476 1.1 mrg x = gen_rtx_fmt_ee (codes[i].code, mode, x, 2477 1.1 mrg GEN_INT (codes[i].value)); 2478 1.1 mrg break; 2479 1.1 mrg case METHOD_LU32I: 2480 1.1 mrg emit_insn ( 2481 1.1 mrg gen_rtx_SET (x, 2482 1.1 mrg gen_rtx_IOR (DImode, 2483 1.1 mrg gen_rtx_ZERO_EXTEND ( 2484 1.1 mrg DImode, gen_rtx_SUBREG (SImode, x, 0)), 2485 1.1 mrg GEN_INT (codes[i].value)))); 2486 1.1 mrg break; 2487 1.1 mrg case METHOD_LU52I: 2488 1.1 mrg emit_insn (gen_lu52i_d (x, x, GEN_INT (0xfffffffffffff), 2489 1.1 mrg GEN_INT (codes[i].value))); 2490 1.1 mrg break; 2491 1.1 mrg case METHOD_INSV: 2492 1.1 mrg emit_insn ( 2493 1.1 mrg gen_rtx_SET (gen_rtx_ZERO_EXTRACT (DImode, x, GEN_INT (20), 2494 1.1 mrg GEN_INT (32)), 2495 1.1 mrg gen_rtx_REG (DImode, 0))); 2496 1.1 mrg break; 2497 1.1 mrg default: 2498 1.1 mrg gcc_unreachable (); 2499 1.1 mrg } 2500 1.1 mrg } 2501 1.1 mrg 2502 1.1 mrg emit_insn (gen_rtx_SET (dest, x)); 2503 1.1 mrg } 2504 1.1 mrg 2505 1.1 mrg /* Subroutine of loongarch_legitimize_move. Move constant SRC into register 2506 1.1 mrg DEST given that SRC satisfies immediate_operand but doesn't satisfy 2507 1.1 mrg move_operand. */ 2508 1.1 mrg 2509 1.1 mrg static void 2510 1.1 mrg loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src) 2511 1.1 mrg { 2512 1.1 mrg rtx base, offset; 2513 1.1 mrg 2514 1.1 mrg /* Split moves of big integers into smaller pieces. */ 2515 1.1 mrg if (splittable_const_int_operand (src, mode)) 2516 1.1 mrg { 2517 1.1 mrg loongarch_move_integer (dest, dest, INTVAL (src)); 2518 1.1 mrg return; 2519 1.1 mrg } 2520 1.1 mrg 2521 1.1 mrg /* Generate the appropriate access sequences for TLS symbols. */ 2522 1.1 mrg if (loongarch_tls_symbol_p (src)) 2523 1.1 mrg { 2524 1.1 mrg loongarch_emit_move (dest, loongarch_legitimize_tls_address (src)); 2525 1.1 mrg return; 2526 1.1 mrg } 2527 1.1 mrg 2528 1.1 mrg /* If we have (const (plus symbol offset)), and that expression cannot 2529 1.1 mrg be forced into memory, load the symbol first and add in the offset. 2530 1.1 mrg prefer to do this even if the constant _can_ be forced into memory, 2531 1.1 mrg as it usually produces better code. */ 2532 1.1 mrg split_const (src, &base, &offset); 2533 1.1 mrg if (offset != const0_rtx 2534 1.1 mrg && (targetm.cannot_force_const_mem (mode, src) 2535 1.1 mrg || (can_create_pseudo_p ()))) 2536 1.1 mrg { 2537 1.1 mrg base = loongarch_force_temporary (dest, base); 2538 1.1 mrg loongarch_emit_move (dest, 2539 1.1 mrg loongarch_add_offset (NULL, base, INTVAL (offset))); 2540 1.1 mrg return; 2541 1.1 mrg } 2542 1.1 mrg 2543 1.1 mrg src = force_const_mem (mode, src); 2544 1.1 mrg 2545 1.1 mrg loongarch_emit_move (dest, src); 2546 1.1 mrg } 2547 1.1 mrg 2548 1.1 mrg /* If (set DEST SRC) is not a valid move instruction, emit an equivalent 2549 1.1 mrg sequence that is valid. */ 2550 1.1 mrg 2551 1.1 mrg bool 2552 1.1 mrg loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src) 2553 1.1 mrg { 2554 1.1 mrg if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) 2555 1.1 mrg { 2556 1.1 mrg loongarch_emit_move (dest, force_reg (mode, src)); 2557 1.1 mrg return true; 2558 1.1 mrg } 2559 1.1 mrg 2560 1.1 mrg /* Both src and dest are non-registers; one special case is supported where 2561 1.1 mrg the source is (const_int 0) and the store can source the zero register. 2562 1.1 mrg */ 2563 1.1 mrg if (!register_operand (dest, mode) && !register_operand (src, mode) 2564 1.1 mrg && !const_0_operand (src, mode)) 2565 1.1 mrg { 2566 1.1 mrg loongarch_emit_move (dest, force_reg (mode, src)); 2567 1.1 mrg return true; 2568 1.1 mrg } 2569 1.1 mrg 2570 1.1 mrg /* We need to deal with constants that would be legitimate 2571 1.1 mrg immediate_operands but aren't legitimate move_operands. */ 2572 1.1 mrg if (CONSTANT_P (src) && !move_operand (src, mode)) 2573 1.1 mrg { 2574 1.1 mrg loongarch_legitimize_const_move (mode, dest, src); 2575 1.1 mrg set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); 2576 1.1 mrg return true; 2577 1.1 mrg } 2578 1.1 mrg 2579 1.1 mrg return false; 2580 1.1 mrg } 2581 1.1 mrg 2582 1.1 mrg /* Return true if OP refers to small data symbols directly. */ 2583 1.1 mrg 2584 1.1 mrg static int 2585 1.1 mrg loongarch_small_data_pattern_1 (rtx x) 2586 1.1 mrg { 2587 1.1 mrg subrtx_var_iterator::array_type array; 2588 1.1 mrg FOR_EACH_SUBRTX_VAR (iter, array, x, ALL) 2589 1.1 mrg { 2590 1.1 mrg rtx x = *iter; 2591 1.1 mrg 2592 1.1 mrg /* We make no particular guarantee about which symbolic constants are 2593 1.1 mrg acceptable as asm operands versus which must be forced into a GPR. */ 2594 1.1 mrg if (GET_CODE (x) == ASM_OPERANDS) 2595 1.1 mrg iter.skip_subrtxes (); 2596 1.1 mrg else if (MEM_P (x)) 2597 1.1 mrg { 2598 1.1 mrg if (loongarch_small_data_pattern_1 (XEXP (x, 0))) 2599 1.1 mrg return true; 2600 1.1 mrg iter.skip_subrtxes (); 2601 1.1 mrg } 2602 1.1 mrg } 2603 1.1 mrg return false; 2604 1.1 mrg } 2605 1.1 mrg 2606 1.1 mrg /* Return true if OP refers to small data symbols directly. */ 2607 1.1 mrg 2608 1.1 mrg bool 2609 1.1 mrg loongarch_small_data_pattern_p (rtx op) 2610 1.1 mrg { 2611 1.1 mrg return loongarch_small_data_pattern_1 (op); 2612 1.1 mrg } 2613 1.1 mrg 2614 1.1 mrg /* Rewrite *LOC so that it refers to small data using explicit 2615 1.1 mrg relocations. */ 2616 1.1 mrg 2617 1.1 mrg static void 2618 1.1 mrg loongarch_rewrite_small_data_1 (rtx *loc) 2619 1.1 mrg { 2620 1.1 mrg subrtx_ptr_iterator::array_type array; 2621 1.1 mrg FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL) 2622 1.1 mrg { 2623 1.1 mrg rtx *loc = *iter; 2624 1.1 mrg if (MEM_P (*loc)) 2625 1.1 mrg { 2626 1.1 mrg loongarch_rewrite_small_data_1 (&XEXP (*loc, 0)); 2627 1.1 mrg iter.skip_subrtxes (); 2628 1.1 mrg } 2629 1.1 mrg } 2630 1.1 mrg } 2631 1.1 mrg 2632 1.1 mrg /* Rewrite instruction pattern PATTERN so that it refers to small data 2633 1.1 mrg using explicit relocations. */ 2634 1.1 mrg 2635 1.1 mrg rtx 2636 1.1 mrg loongarch_rewrite_small_data (rtx pattern) 2637 1.1 mrg { 2638 1.1 mrg pattern = copy_insn (pattern); 2639 1.1 mrg loongarch_rewrite_small_data_1 (&pattern); 2640 1.1 mrg return pattern; 2641 1.1 mrg } 2642 1.1 mrg 2643 1.1 mrg /* The cost of loading values from the constant pool. It should be 2644 1.1 mrg larger than the cost of any constant we want to synthesize inline. */ 2645 1.1 mrg #define CONSTANT_POOL_COST COSTS_N_INSNS (8) 2646 1.1 mrg 2647 1.1 mrg /* Return true if there is a instruction that implements CODE 2648 1.1 mrg and if that instruction accepts X as an immediate operand. */ 2649 1.1 mrg 2650 1.1 mrg static int 2651 1.1 mrg loongarch_immediate_operand_p (int code, HOST_WIDE_INT x) 2652 1.1 mrg { 2653 1.1 mrg switch (code) 2654 1.1 mrg { 2655 1.1 mrg case ASHIFT: 2656 1.1 mrg case ASHIFTRT: 2657 1.1 mrg case LSHIFTRT: 2658 1.1 mrg /* All shift counts are truncated to a valid constant. */ 2659 1.1 mrg return true; 2660 1.1 mrg 2661 1.1 mrg case ROTATE: 2662 1.1 mrg case ROTATERT: 2663 1.1 mrg return true; 2664 1.1 mrg 2665 1.1 mrg case AND: 2666 1.1 mrg case IOR: 2667 1.1 mrg case XOR: 2668 1.1 mrg /* These instructions take 12-bit unsigned immediates. */ 2669 1.1 mrg return IMM12_OPERAND_UNSIGNED (x); 2670 1.1 mrg 2671 1.1 mrg case PLUS: 2672 1.1 mrg case LT: 2673 1.1 mrg case LTU: 2674 1.1 mrg /* These instructions take 12-bit signed immediates. */ 2675 1.1 mrg return IMM12_OPERAND (x); 2676 1.1 mrg 2677 1.1 mrg case EQ: 2678 1.1 mrg case NE: 2679 1.1 mrg case GT: 2680 1.1 mrg case GTU: 2681 1.1 mrg /* The "immediate" forms of these instructions are really 2682 1.1 mrg implemented as comparisons with register 0. */ 2683 1.1 mrg return x == 0; 2684 1.1 mrg 2685 1.1 mrg case GE: 2686 1.1 mrg case GEU: 2687 1.1 mrg /* Likewise, meaning that the only valid immediate operand is 1. */ 2688 1.1 mrg return x == 1; 2689 1.1 mrg 2690 1.1 mrg case LE: 2691 1.1 mrg /* We add 1 to the immediate and use SLT. */ 2692 1.1 mrg return IMM12_OPERAND (x + 1); 2693 1.1 mrg 2694 1.1 mrg case LEU: 2695 1.1 mrg /* Likewise SLTU, but reject the always-true case. */ 2696 1.1 mrg return IMM12_OPERAND (x + 1) && x + 1 != 0; 2697 1.1 mrg 2698 1.1 mrg case SIGN_EXTRACT: 2699 1.1 mrg case ZERO_EXTRACT: 2700 1.1 mrg /* The bit position and size are immediate operands. */ 2701 1.1 mrg return 1; 2702 1.1 mrg 2703 1.1 mrg default: 2704 1.1 mrg /* By default assume that $0 can be used for 0. */ 2705 1.1 mrg return x == 0; 2706 1.1 mrg } 2707 1.1 mrg } 2708 1.1 mrg 2709 1.1 mrg /* Return the cost of binary operation X, given that the instruction 2710 1.1 mrg sequence for a word-sized or smaller operation has cost SINGLE_COST 2711 1.1 mrg and that the sequence of a double-word operation has cost DOUBLE_COST. 2712 1.1 mrg If SPEED is true, optimize for speed otherwise optimize for size. */ 2713 1.1 mrg 2714 1.1 mrg static int 2715 1.1 mrg loongarch_binary_cost (rtx x, int single_cost, int double_cost, bool speed) 2716 1.1 mrg { 2717 1.1 mrg int cost; 2718 1.1 mrg 2719 1.1 mrg if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2) 2720 1.1 mrg cost = double_cost; 2721 1.1 mrg else 2722 1.1 mrg cost = single_cost; 2723 1.1 mrg return (cost 2724 1.1 mrg + set_src_cost (XEXP (x, 0), GET_MODE (x), speed) 2725 1.1 mrg + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed)); 2726 1.1 mrg } 2727 1.1 mrg 2728 1.1 mrg /* Return the cost of floating-point multiplications of mode MODE. */ 2729 1.1 mrg 2730 1.1 mrg static int 2731 1.1 mrg loongarch_fp_mult_cost (machine_mode mode) 2732 1.1 mrg { 2733 1.1 mrg return mode == DFmode ? loongarch_cost->fp_mult_df 2734 1.1 mrg : loongarch_cost->fp_mult_sf; 2735 1.1 mrg } 2736 1.1 mrg 2737 1.1 mrg /* Return the cost of floating-point divisions of mode MODE. */ 2738 1.1 mrg 2739 1.1 mrg static int 2740 1.1 mrg loongarch_fp_div_cost (machine_mode mode) 2741 1.1 mrg { 2742 1.1 mrg return mode == DFmode ? loongarch_cost->fp_div_df 2743 1.1 mrg : loongarch_cost->fp_div_sf; 2744 1.1 mrg } 2745 1.1 mrg 2746 1.1 mrg /* Return the cost of sign-extending OP to mode MODE, not including the 2747 1.1 mrg cost of OP itself. */ 2748 1.1 mrg 2749 1.1 mrg static int 2750 1.1 mrg loongarch_sign_extend_cost (rtx op) 2751 1.1 mrg { 2752 1.1 mrg if (MEM_P (op)) 2753 1.1 mrg /* Extended loads are as cheap as unextended ones. */ 2754 1.1 mrg return 0; 2755 1.1 mrg 2756 1.1 mrg return COSTS_N_INSNS (1); 2757 1.1 mrg } 2758 1.1 mrg 2759 1.1 mrg /* Return the cost of zero-extending OP to mode MODE, not including the 2760 1.1 mrg cost of OP itself. */ 2761 1.1 mrg 2762 1.1 mrg static int 2763 1.1 mrg loongarch_zero_extend_cost (rtx op) 2764 1.1 mrg { 2765 1.1 mrg if (MEM_P (op)) 2766 1.1 mrg /* Extended loads are as cheap as unextended ones. */ 2767 1.1 mrg return 0; 2768 1.1 mrg 2769 1.1 mrg /* We can use ANDI. */ 2770 1.1 mrg return COSTS_N_INSNS (1); 2771 1.1 mrg } 2772 1.1 mrg 2773 1.1 mrg /* Return the cost of moving between two registers of mode MODE, 2774 1.1 mrg assuming that the move will be in pieces of at most UNITS bytes. */ 2775 1.1 mrg 2776 1.1 mrg static int 2777 1.1 mrg loongarch_set_reg_reg_piece_cost (machine_mode mode, unsigned int units) 2778 1.1 mrg { 2779 1.1 mrg return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units); 2780 1.1 mrg } 2781 1.1 mrg 2782 1.1 mrg /* Return the cost of moving between two registers of mode MODE. */ 2783 1.1 mrg 2784 1.1 mrg static int 2785 1.1 mrg loongarch_set_reg_reg_cost (machine_mode mode) 2786 1.1 mrg { 2787 1.1 mrg switch (GET_MODE_CLASS (mode)) 2788 1.1 mrg { 2789 1.1 mrg case MODE_CC: 2790 1.1 mrg return loongarch_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode)); 2791 1.1 mrg 2792 1.1 mrg case MODE_FLOAT: 2793 1.1 mrg case MODE_COMPLEX_FLOAT: 2794 1.1 mrg case MODE_VECTOR_FLOAT: 2795 1.1 mrg if (TARGET_HARD_FLOAT) 2796 1.1 mrg return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_HWFPVALUE); 2797 1.1 mrg /* Fall through. */ 2798 1.1 mrg 2799 1.1 mrg default: 2800 1.1 mrg return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_WORD); 2801 1.1 mrg } 2802 1.1 mrg } 2803 1.1 mrg 2804 1.1 mrg /* Implement TARGET_RTX_COSTS. */ 2805 1.1 mrg 2806 1.1 mrg static bool 2807 1.1 mrg loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code, 2808 1.1 mrg int opno ATTRIBUTE_UNUSED, int *total, bool speed) 2809 1.1 mrg { 2810 1.1 mrg int code = GET_CODE (x); 2811 1.1 mrg bool float_mode_p = FLOAT_MODE_P (mode); 2812 1.1 mrg int cost; 2813 1.1 mrg rtx addr; 2814 1.1 mrg 2815 1.1 mrg if (outer_code == COMPARE) 2816 1.1 mrg { 2817 1.1 mrg gcc_assert (CONSTANT_P (x)); 2818 1.1 mrg *total = 0; 2819 1.1 mrg return true; 2820 1.1 mrg } 2821 1.1 mrg 2822 1.1 mrg switch (code) 2823 1.1 mrg { 2824 1.1 mrg case CONST_INT: 2825 1.1 mrg if (TARGET_64BIT && outer_code == AND && UINTVAL (x) == 0xffffffff) 2826 1.1 mrg { 2827 1.1 mrg *total = 0; 2828 1.1 mrg return true; 2829 1.1 mrg } 2830 1.1 mrg 2831 1.1 mrg /* When not optimizing for size, we care more about the cost 2832 1.1 mrg of hot code, and hot code is often in a loop. If a constant 2833 1.1 mrg operand needs to be forced into a register, we will often be 2834 1.1 mrg able to hoist the constant load out of the loop, so the load 2835 1.1 mrg should not contribute to the cost. */ 2836 1.1 mrg if (speed || loongarch_immediate_operand_p (outer_code, INTVAL (x))) 2837 1.1 mrg { 2838 1.1 mrg *total = 0; 2839 1.1 mrg return true; 2840 1.1 mrg } 2841 1.1 mrg /* Fall through. */ 2842 1.1 mrg 2843 1.1 mrg case CONST: 2844 1.1 mrg case SYMBOL_REF: 2845 1.1 mrg case LABEL_REF: 2846 1.1 mrg case CONST_DOUBLE: 2847 1.1 mrg cost = loongarch_const_insns (x); 2848 1.1 mrg if (cost > 0) 2849 1.1 mrg { 2850 1.1 mrg if (cost == 1 && outer_code == SET 2851 1.1 mrg && !(float_mode_p && TARGET_HARD_FLOAT)) 2852 1.1 mrg cost = 0; 2853 1.1 mrg else if ((outer_code == SET || GET_MODE (x) == VOIDmode)) 2854 1.1 mrg cost = 1; 2855 1.1 mrg *total = COSTS_N_INSNS (cost); 2856 1.1 mrg return true; 2857 1.1 mrg } 2858 1.1 mrg /* The value will need to be fetched from the constant pool. */ 2859 1.1 mrg *total = CONSTANT_POOL_COST; 2860 1.1 mrg return true; 2861 1.1 mrg 2862 1.1 mrg case MEM: 2863 1.1 mrg /* If the address is legitimate, return the number of 2864 1.1 mrg instructions it needs. */ 2865 1.1 mrg addr = XEXP (x, 0); 2866 1.1 mrg /* Check for a scaled indexed address. */ 2867 1.1 mrg if (loongarch_index_address_p (addr, mode)) 2868 1.1 mrg { 2869 1.1 mrg *total = COSTS_N_INSNS (2); 2870 1.1 mrg return true; 2871 1.1 mrg } 2872 1.1 mrg cost = loongarch_address_insns (addr, mode, true); 2873 1.1 mrg if (cost > 0) 2874 1.1 mrg { 2875 1.1 mrg *total = COSTS_N_INSNS (cost + 1); 2876 1.1 mrg return true; 2877 1.1 mrg } 2878 1.1 mrg /* Otherwise use the default handling. */ 2879 1.1 mrg return false; 2880 1.1 mrg 2881 1.1 mrg case FFS: 2882 1.1 mrg *total = COSTS_N_INSNS (6); 2883 1.1 mrg return false; 2884 1.1 mrg 2885 1.1 mrg case NOT: 2886 1.1 mrg *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1); 2887 1.1 mrg return false; 2888 1.1 mrg 2889 1.1 mrg case AND: 2890 1.1 mrg /* Check for a *clear_upper32 pattern and treat it like a zero 2891 1.1 mrg extension. See the pattern's comment for details. */ 2892 1.1 mrg if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1)) 2893 1.1 mrg && UINTVAL (XEXP (x, 1)) == 0xffffffff) 2894 1.1 mrg { 2895 1.1 mrg *total = (loongarch_zero_extend_cost (XEXP (x, 0)) 2896 1.1 mrg + set_src_cost (XEXP (x, 0), mode, speed)); 2897 1.1 mrg return true; 2898 1.1 mrg } 2899 1.1 mrg /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in 2900 1.1 mrg a single instruction. */ 2901 1.1 mrg if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT) 2902 1.1 mrg { 2903 1.1 mrg cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1; 2904 1.1 mrg *total = (COSTS_N_INSNS (cost) 2905 1.1 mrg + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed) 2906 1.1 mrg + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed)); 2907 1.1 mrg return true; 2908 1.1 mrg } 2909 1.1 mrg 2910 1.1 mrg /* Fall through. */ 2911 1.1 mrg 2912 1.1 mrg case IOR: 2913 1.1 mrg case XOR: 2914 1.1 mrg /* Double-word operations use two single-word operations. */ 2915 1.1 mrg *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (2), 2916 1.1 mrg speed); 2917 1.1 mrg return true; 2918 1.1 mrg 2919 1.1 mrg case ASHIFT: 2920 1.1 mrg case ASHIFTRT: 2921 1.1 mrg case LSHIFTRT: 2922 1.1 mrg case ROTATE: 2923 1.1 mrg case ROTATERT: 2924 1.1 mrg if (CONSTANT_P (XEXP (x, 1))) 2925 1.1 mrg *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), 2926 1.1 mrg COSTS_N_INSNS (4), speed); 2927 1.1 mrg else 2928 1.1 mrg *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), 2929 1.1 mrg COSTS_N_INSNS (12), speed); 2930 1.1 mrg return true; 2931 1.1 mrg 2932 1.1 mrg case ABS: 2933 1.1 mrg if (float_mode_p) 2934 1.1 mrg *total = loongarch_cost->fp_add; 2935 1.1 mrg else 2936 1.1 mrg *total = COSTS_N_INSNS (4); 2937 1.1 mrg return false; 2938 1.1 mrg 2939 1.1 mrg case LT: 2940 1.1 mrg case LTU: 2941 1.1 mrg case LE: 2942 1.1 mrg case LEU: 2943 1.1 mrg case GT: 2944 1.1 mrg case GTU: 2945 1.1 mrg case GE: 2946 1.1 mrg case GEU: 2947 1.1 mrg case EQ: 2948 1.1 mrg case NE: 2949 1.1 mrg case UNORDERED: 2950 1.1 mrg case LTGT: 2951 1.1 mrg case UNGE: 2952 1.1 mrg case UNGT: 2953 1.1 mrg case UNLE: 2954 1.1 mrg case UNLT: 2955 1.1 mrg /* Branch comparisons have VOIDmode, so use the first operand's 2956 1.1 mrg mode instead. */ 2957 1.1 mrg mode = GET_MODE (XEXP (x, 0)); 2958 1.1 mrg if (FLOAT_MODE_P (mode)) 2959 1.1 mrg { 2960 1.1 mrg *total = loongarch_cost->fp_add; 2961 1.1 mrg return false; 2962 1.1 mrg } 2963 1.1 mrg *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4), 2964 1.1 mrg speed); 2965 1.1 mrg return true; 2966 1.1 mrg 2967 1.1 mrg case MINUS: 2968 1.1 mrg case PLUS: 2969 1.1 mrg if (float_mode_p) 2970 1.1 mrg { 2971 1.1 mrg *total = loongarch_cost->fp_add; 2972 1.1 mrg return false; 2973 1.1 mrg } 2974 1.1 mrg 2975 1.1 mrg /* If it's an add + mult (which is equivalent to shift left) and 2976 1.1 mrg it's immediate operand satisfies const_immalsl_operand predicate. */ 2977 1.1 mrg if ((mode == SImode || (TARGET_64BIT && mode == DImode)) 2978 1.1 mrg && GET_CODE (XEXP (x, 0)) == MULT) 2979 1.1 mrg { 2980 1.1 mrg rtx op2 = XEXP (XEXP (x, 0), 1); 2981 1.1 mrg if (const_immalsl_operand (op2, mode)) 2982 1.1 mrg { 2983 1.1 mrg *total = (COSTS_N_INSNS (1) 2984 1.1 mrg + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed) 2985 1.1 mrg + set_src_cost (XEXP (x, 1), mode, speed)); 2986 1.1 mrg return true; 2987 1.1 mrg } 2988 1.1 mrg } 2989 1.1 mrg 2990 1.1 mrg /* Double-word operations require three single-word operations and 2991 1.1 mrg an SLTU. */ 2992 1.1 mrg *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4), 2993 1.1 mrg speed); 2994 1.1 mrg return true; 2995 1.1 mrg 2996 1.1 mrg case NEG: 2997 1.1 mrg if (float_mode_p) 2998 1.1 mrg *total = loongarch_cost->fp_add; 2999 1.1 mrg else 3000 1.1 mrg *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); 3001 1.1 mrg return false; 3002 1.1 mrg 3003 1.1 mrg case FMA: 3004 1.1 mrg *total = loongarch_fp_mult_cost (mode); 3005 1.1 mrg return false; 3006 1.1 mrg 3007 1.1 mrg case MULT: 3008 1.1 mrg if (float_mode_p) 3009 1.1 mrg *total = loongarch_fp_mult_cost (mode); 3010 1.1 mrg else if (mode == DImode && !TARGET_64BIT) 3011 1.1 mrg *total = (speed 3012 1.1 mrg ? loongarch_cost->int_mult_si * 3 + 6 3013 1.1 mrg : COSTS_N_INSNS (7)); 3014 1.1 mrg else if (!speed) 3015 1.1 mrg *total = COSTS_N_INSNS (1) + 1; 3016 1.1 mrg else if (mode == DImode) 3017 1.1 mrg *total = loongarch_cost->int_mult_di; 3018 1.1 mrg else 3019 1.1 mrg *total = loongarch_cost->int_mult_si; 3020 1.1 mrg return false; 3021 1.1 mrg 3022 1.1 mrg case DIV: 3023 1.1 mrg /* Check for a reciprocal. */ 3024 1.1 mrg if (float_mode_p 3025 1.1 mrg && flag_unsafe_math_optimizations 3026 1.1 mrg && XEXP (x, 0) == CONST1_RTX (mode)) 3027 1.1 mrg { 3028 1.1 mrg if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT) 3029 1.1 mrg /* An rsqrt<mode>a or rsqrt<mode>b pattern. Count the 3030 1.1 mrg division as being free. */ 3031 1.1 mrg *total = set_src_cost (XEXP (x, 1), mode, speed); 3032 1.1 mrg else 3033 1.1 mrg *total = (loongarch_fp_div_cost (mode) 3034 1.1 mrg + set_src_cost (XEXP (x, 1), mode, speed)); 3035 1.1 mrg return true; 3036 1.1 mrg } 3037 1.1 mrg /* Fall through. */ 3038 1.1 mrg 3039 1.1 mrg case SQRT: 3040 1.1 mrg case MOD: 3041 1.1 mrg if (float_mode_p) 3042 1.1 mrg { 3043 1.1 mrg *total = loongarch_fp_div_cost (mode); 3044 1.1 mrg return false; 3045 1.1 mrg } 3046 1.1 mrg /* Fall through. */ 3047 1.1 mrg 3048 1.1 mrg case UDIV: 3049 1.1 mrg case UMOD: 3050 1.1 mrg if (!speed) 3051 1.1 mrg { 3052 1.1 mrg *total = COSTS_N_INSNS (loongarch_idiv_insns (mode)); 3053 1.1 mrg } 3054 1.1 mrg else if (mode == DImode) 3055 1.1 mrg *total = loongarch_cost->int_div_di; 3056 1.1 mrg else 3057 1.1 mrg *total = loongarch_cost->int_div_si; 3058 1.1 mrg return false; 3059 1.1 mrg 3060 1.1 mrg case SIGN_EXTEND: 3061 1.1 mrg *total = loongarch_sign_extend_cost (XEXP (x, 0)); 3062 1.1 mrg return false; 3063 1.1 mrg 3064 1.1 mrg case ZERO_EXTEND: 3065 1.1 mrg *total = loongarch_zero_extend_cost (XEXP (x, 0)); 3066 1.1 mrg return false; 3067 1.1 mrg case TRUNCATE: 3068 1.1 mrg /* Costings for highpart multiplies. Matching patterns of the form: 3069 1.1 mrg 3070 1.1 mrg (lshiftrt:DI (mult:DI (sign_extend:DI (...) 3071 1.1 mrg (sign_extend:DI (...)) 3072 1.1 mrg (const_int 32) 3073 1.1 mrg */ 3074 1.1 mrg if ((GET_CODE (XEXP (x, 0)) == ASHIFTRT 3075 1.1 mrg || GET_CODE (XEXP (x, 0)) == LSHIFTRT) 3076 1.1 mrg && CONST_INT_P (XEXP (XEXP (x, 0), 1)) 3077 1.1 mrg && ((INTVAL (XEXP (XEXP (x, 0), 1)) == 32 3078 1.1 mrg && GET_MODE (XEXP (x, 0)) == DImode) 3079 1.1 mrg || (TARGET_64BIT 3080 1.1 mrg && INTVAL (XEXP (XEXP (x, 0), 1)) == 64 3081 1.1 mrg && GET_MODE (XEXP (x, 0)) == TImode)) 3082 1.1 mrg && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT 3083 1.1 mrg && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND 3084 1.1 mrg && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND) 3085 1.1 mrg || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND 3086 1.1 mrg && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) 3087 1.1 mrg == ZERO_EXTEND)))) 3088 1.1 mrg { 3089 1.1 mrg if (!speed) 3090 1.1 mrg *total = COSTS_N_INSNS (1) + 1; 3091 1.1 mrg else if (mode == DImode) 3092 1.1 mrg *total = loongarch_cost->int_mult_di; 3093 1.1 mrg else 3094 1.1 mrg *total = loongarch_cost->int_mult_si; 3095 1.1 mrg 3096 1.1 mrg /* Sign extension is free, zero extension costs for DImode when 3097 1.1 mrg on a 64bit core / when DMUL is present. */ 3098 1.1 mrg for (int i = 0; i < 2; ++i) 3099 1.1 mrg { 3100 1.1 mrg rtx op = XEXP (XEXP (XEXP (x, 0), 0), i); 3101 1.1 mrg if (TARGET_64BIT 3102 1.1 mrg && GET_CODE (op) == ZERO_EXTEND 3103 1.1 mrg && GET_MODE (op) == DImode) 3104 1.1 mrg *total += rtx_cost (op, DImode, MULT, i, speed); 3105 1.1 mrg else 3106 1.1 mrg *total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op), 0, 3107 1.1 mrg speed); 3108 1.1 mrg } 3109 1.1 mrg 3110 1.1 mrg return true; 3111 1.1 mrg } 3112 1.1 mrg return false; 3113 1.1 mrg 3114 1.1 mrg case FLOAT: 3115 1.1 mrg case UNSIGNED_FLOAT: 3116 1.1 mrg case FIX: 3117 1.1 mrg case FLOAT_EXTEND: 3118 1.1 mrg case FLOAT_TRUNCATE: 3119 1.1 mrg *total = loongarch_cost->fp_add; 3120 1.1 mrg return false; 3121 1.1 mrg 3122 1.1 mrg case SET: 3123 1.1 mrg if (register_operand (SET_DEST (x), VOIDmode) 3124 1.1 mrg && reg_or_0_operand (SET_SRC (x), VOIDmode)) 3125 1.1 mrg { 3126 1.1 mrg *total = loongarch_set_reg_reg_cost (GET_MODE (SET_DEST (x))); 3127 1.1 mrg return true; 3128 1.1 mrg } 3129 1.1 mrg return false; 3130 1.1 mrg 3131 1.1 mrg default: 3132 1.1 mrg return false; 3133 1.1 mrg } 3134 1.1 mrg } 3135 1.1 mrg 3136 1.1 mrg /* Implement TARGET_ADDRESS_COST. */ 3137 1.1 mrg 3138 1.1 mrg static int 3139 1.1 mrg loongarch_address_cost (rtx addr, machine_mode mode, 3140 1.1 mrg addr_space_t as ATTRIBUTE_UNUSED, 3141 1.1 mrg bool speed ATTRIBUTE_UNUSED) 3142 1.1 mrg { 3143 1.1 mrg return loongarch_address_insns (addr, mode, false); 3144 1.1 mrg } 3145 1.1 mrg 3146 1.1 mrg /* Return one word of double-word value OP, taking into account the fixed 3147 1.1 mrg endianness of certain registers. HIGH_P is true to select the high part, 3148 1.1 mrg false to select the low part. */ 3149 1.1 mrg 3150 1.1 mrg rtx 3151 1.1 mrg loongarch_subword (rtx op, bool high_p) 3152 1.1 mrg { 3153 1.1 mrg unsigned int byte; 3154 1.1 mrg machine_mode mode; 3155 1.1 mrg 3156 1.1 mrg byte = high_p ? UNITS_PER_WORD : 0; 3157 1.1 mrg mode = GET_MODE (op); 3158 1.1 mrg if (mode == VOIDmode) 3159 1.1 mrg mode = TARGET_64BIT ? TImode : DImode; 3160 1.1 mrg 3161 1.1 mrg if (FP_REG_RTX_P (op)) 3162 1.1 mrg return gen_rtx_REG (word_mode, REGNO (op) + high_p); 3163 1.1 mrg 3164 1.1 mrg if (MEM_P (op)) 3165 1.1 mrg return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte)); 3166 1.1 mrg 3167 1.1 mrg return simplify_gen_subreg (word_mode, op, mode, byte); 3168 1.1 mrg } 3169 1.1 mrg 3170 1.1 mrg /* Return true if a move from SRC to DEST should be split into two. 3171 1.1 mrg SPLIT_TYPE describes the split condition. */ 3172 1.1 mrg 3173 1.1 mrg bool 3174 1.1 mrg loongarch_split_move_p (rtx dest, rtx src) 3175 1.1 mrg { 3176 1.1 mrg /* FPR-to-FPR moves can be done in a single instruction, if they're 3177 1.1 mrg allowed at all. */ 3178 1.1 mrg unsigned int size = GET_MODE_SIZE (GET_MODE (dest)); 3179 1.1 mrg if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) 3180 1.1 mrg return false; 3181 1.1 mrg 3182 1.1 mrg /* Check for floating-point loads and stores. */ 3183 1.1 mrg if (size == 8) 3184 1.1 mrg { 3185 1.1 mrg if (FP_REG_RTX_P (dest) && MEM_P (src)) 3186 1.1 mrg return false; 3187 1.1 mrg if (FP_REG_RTX_P (src) && MEM_P (dest)) 3188 1.1 mrg return false; 3189 1.1 mrg } 3190 1.1 mrg /* Otherwise split all multiword moves. */ 3191 1.1 mrg return size > UNITS_PER_WORD; 3192 1.1 mrg } 3193 1.1 mrg 3194 1.1 mrg /* Split a move from SRC to DEST, given that loongarch_split_move_p holds. 3195 1.1 mrg SPLIT_TYPE describes the split condition. */ 3196 1.1 mrg 3197 1.1 mrg void 3198 1.1 mrg loongarch_split_move (rtx dest, rtx src, rtx insn_) 3199 1.1 mrg { 3200 1.1 mrg rtx low_dest; 3201 1.1 mrg 3202 1.1 mrg gcc_checking_assert (loongarch_split_move_p (dest, src)); 3203 1.1 mrg if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src)) 3204 1.1 mrg { 3205 1.1 mrg if (!TARGET_64BIT && GET_MODE (dest) == DImode) 3206 1.1 mrg emit_insn (gen_move_doubleword_fprdi (dest, src)); 3207 1.1 mrg else if (!TARGET_64BIT && GET_MODE (dest) == DFmode) 3208 1.1 mrg emit_insn (gen_move_doubleword_fprdf (dest, src)); 3209 1.1 mrg else if (TARGET_64BIT && GET_MODE (dest) == TFmode) 3210 1.1 mrg emit_insn (gen_move_doubleword_fprtf (dest, src)); 3211 1.1 mrg else 3212 1.1 mrg gcc_unreachable (); 3213 1.1 mrg } 3214 1.1 mrg else 3215 1.1 mrg { 3216 1.1 mrg /* The operation can be split into two normal moves. Decide in 3217 1.1 mrg which order to do them. */ 3218 1.1 mrg low_dest = loongarch_subword (dest, false); 3219 1.1 mrg if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src)) 3220 1.1 mrg { 3221 1.1 mrg loongarch_emit_move (loongarch_subword (dest, true), 3222 1.1 mrg loongarch_subword (src, true)); 3223 1.1 mrg loongarch_emit_move (low_dest, loongarch_subword (src, false)); 3224 1.1 mrg } 3225 1.1 mrg else 3226 1.1 mrg { 3227 1.1 mrg loongarch_emit_move (low_dest, loongarch_subword (src, false)); 3228 1.1 mrg loongarch_emit_move (loongarch_subword (dest, true), 3229 1.1 mrg loongarch_subword (src, true)); 3230 1.1 mrg } 3231 1.1 mrg } 3232 1.1 mrg 3233 1.1 mrg /* This is a hack. See if the next insn uses DEST and if so, see if we 3234 1.1 mrg can forward SRC for DEST. This is most useful if the next insn is a 3235 1.1 mrg simple store. */ 3236 1.1 mrg rtx_insn *insn = (rtx_insn *) insn_; 3237 1.1 mrg struct loongarch_address_info addr = {}; 3238 1.1 mrg if (insn) 3239 1.1 mrg { 3240 1.1 mrg rtx_insn *next = next_nonnote_nondebug_insn_bb (insn); 3241 1.1 mrg if (next) 3242 1.1 mrg { 3243 1.1 mrg rtx set = single_set (next); 3244 1.1 mrg if (set && SET_SRC (set) == dest) 3245 1.1 mrg { 3246 1.1 mrg if (MEM_P (src)) 3247 1.1 mrg { 3248 1.1 mrg rtx tmp = XEXP (src, 0); 3249 1.1 mrg loongarch_classify_address (&addr, tmp, GET_MODE (tmp), 3250 1.1 mrg true); 3251 1.1 mrg if (addr.reg && !reg_overlap_mentioned_p (dest, addr.reg)) 3252 1.1 mrg validate_change (next, &SET_SRC (set), src, false); 3253 1.1 mrg } 3254 1.1 mrg else 3255 1.1 mrg validate_change (next, &SET_SRC (set), src, false); 3256 1.1 mrg } 3257 1.1 mrg } 3258 1.1 mrg } 3259 1.1 mrg } 3260 1.1 mrg 3261 1.1 mrg /* Return true if a move from SRC to DEST in INSN should be split. */ 3262 1.1 mrg 3263 1.1 mrg bool 3264 1.1 mrg loongarch_split_move_insn_p (rtx dest, rtx src) 3265 1.1 mrg { 3266 1.1 mrg return loongarch_split_move_p (dest, src); 3267 1.1 mrg } 3268 1.1 mrg 3269 1.1 mrg /* Split a move from SRC to DEST in INSN, given that 3270 1.1 mrg loongarch_split_move_insn_p holds. */ 3271 1.1 mrg 3272 1.1 mrg void 3273 1.1 mrg loongarch_split_move_insn (rtx dest, rtx src, rtx insn) 3274 1.1 mrg { 3275 1.1 mrg loongarch_split_move (dest, src, insn); 3276 1.1 mrg } 3277 1.1 mrg 3278 1.1 mrg /* Implement TARGET_CONSTANT_ALIGNMENT. */ 3279 1.1 mrg 3280 1.1 mrg static HOST_WIDE_INT 3281 1.1 mrg loongarch_constant_alignment (const_tree exp, HOST_WIDE_INT align) 3282 1.1 mrg { 3283 1.1 mrg if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) 3284 1.1 mrg return MAX (align, BITS_PER_WORD); 3285 1.1 mrg return align; 3286 1.1 mrg } 3287 1.1 mrg 3288 1.1 mrg const char * 3289 1.1 mrg loongarch_output_move_index (rtx x, machine_mode mode, bool ldr) 3290 1.1 mrg { 3291 1.1 mrg int index = exact_log2 (GET_MODE_SIZE (mode)); 3292 1.1 mrg if (!IN_RANGE (index, 0, 3)) 3293 1.1 mrg return NULL; 3294 1.1 mrg 3295 1.1 mrg struct loongarch_address_info info; 3296 1.1 mrg if ((loongarch_classify_address (&info, x, mode, false) 3297 1.1 mrg && !(info.type == ADDRESS_REG_REG)) 3298 1.1 mrg || !loongarch_legitimate_address_p (mode, x, false)) 3299 1.1 mrg return NULL; 3300 1.1 mrg 3301 1.1 mrg const char *const insn[][4] = 3302 1.1 mrg { 3303 1.1 mrg { 3304 1.1 mrg "stx.b\t%z1,%0", 3305 1.1 mrg "stx.h\t%z1,%0", 3306 1.1 mrg "stx.w\t%z1,%0", 3307 1.1 mrg "stx.d\t%z1,%0", 3308 1.1 mrg }, 3309 1.1 mrg { 3310 1.1 mrg "ldx.bu\t%0,%1", 3311 1.1 mrg "ldx.hu\t%0,%1", 3312 1.1 mrg "ldx.w\t%0,%1", 3313 1.1 mrg "ldx.d\t%0,%1", 3314 1.1 mrg } 3315 1.1 mrg }; 3316 1.1 mrg 3317 1.1 mrg return insn[ldr][index]; 3318 1.1 mrg } 3319 1.1 mrg 3320 1.1 mrg const char * 3321 1.1 mrg loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr) 3322 1.1 mrg { 3323 1.1 mrg int index = exact_log2 (GET_MODE_SIZE (mode)); 3324 1.1 mrg if (!IN_RANGE (index, 2, 3)) 3325 1.1 mrg return NULL; 3326 1.1 mrg 3327 1.1 mrg struct loongarch_address_info info; 3328 1.1 mrg if ((loongarch_classify_address (&info, x, mode, false) 3329 1.1 mrg && !(info.type == ADDRESS_REG_REG)) 3330 1.1 mrg || !loongarch_legitimate_address_p (mode, x, false)) 3331 1.1 mrg return NULL; 3332 1.1 mrg 3333 1.1 mrg const char *const insn[][2] = 3334 1.1 mrg { 3335 1.1 mrg { 3336 1.1 mrg "fstx.s\t%1,%0", 3337 1.1 mrg "fstx.d\t%1,%0" 3338 1.1 mrg }, 3339 1.1 mrg { 3340 1.1 mrg "fldx.s\t%0,%1", 3341 1.1 mrg "fldx.d\t%0,%1" 3342 1.1 mrg }, 3343 1.1 mrg }; 3344 1.1 mrg 3345 1.1 mrg return insn[ldr][index-2]; 3346 1.1 mrg } 3347 1.1 mrg 3348 1.1 mrg /* Return the appropriate instructions to move SRC into DEST. Assume 3349 1.1 mrg that SRC is operand 1 and DEST is operand 0. */ 3350 1.1 mrg 3351 1.1 mrg const char * 3352 1.1 mrg loongarch_output_move (rtx dest, rtx src) 3353 1.1 mrg { 3354 1.1 mrg enum rtx_code dest_code = GET_CODE (dest); 3355 1.1 mrg enum rtx_code src_code = GET_CODE (src); 3356 1.1 mrg machine_mode mode = GET_MODE (dest); 3357 1.1 mrg bool dbl_p = (GET_MODE_SIZE (mode) == 8); 3358 1.1 mrg 3359 1.1 mrg if (loongarch_split_move_p (dest, src)) 3360 1.1 mrg return "#"; 3361 1.1 mrg 3362 1.1 mrg if ((src_code == REG && GP_REG_P (REGNO (src))) 3363 1.1 mrg || (src == CONST0_RTX (mode))) 3364 1.1 mrg { 3365 1.1 mrg if (dest_code == REG) 3366 1.1 mrg { 3367 1.1 mrg if (GP_REG_P (REGNO (dest))) 3368 1.1 mrg return "or\t%0,%z1,$r0"; 3369 1.1 mrg 3370 1.1 mrg if (FP_REG_P (REGNO (dest))) 3371 1.1 mrg return dbl_p ? "movgr2fr.d\t%0,%z1" : "movgr2fr.w\t%0,%z1"; 3372 1.1 mrg } 3373 1.1 mrg if (dest_code == MEM) 3374 1.1 mrg { 3375 1.1 mrg const char *insn = NULL; 3376 1.1 mrg insn = loongarch_output_move_index (XEXP (dest, 0), GET_MODE (dest), 3377 1.1 mrg false); 3378 1.1 mrg if (insn) 3379 1.1 mrg return insn; 3380 1.1 mrg 3381 1.1 mrg rtx offset = XEXP (dest, 0); 3382 1.1 mrg if (GET_CODE (offset) == PLUS) 3383 1.1 mrg offset = XEXP (offset, 1); 3384 1.1 mrg switch (GET_MODE_SIZE (mode)) 3385 1.1 mrg { 3386 1.1 mrg case 1: 3387 1.1 mrg return "st.b\t%z1,%0"; 3388 1.1 mrg case 2: 3389 1.1 mrg return "st.h\t%z1,%0"; 3390 1.1 mrg case 4: 3391 1.1 mrg if (const_arith_operand (offset, Pmode)) 3392 1.1 mrg return "st.w\t%z1,%0"; 3393 1.1 mrg else 3394 1.1 mrg return "stptr.w\t%z1,%0"; 3395 1.1 mrg case 8: 3396 1.1 mrg if (const_arith_operand (offset, Pmode)) 3397 1.1 mrg return "st.d\t%z1,%0"; 3398 1.1 mrg else 3399 1.1 mrg return "stptr.d\t%z1,%0"; 3400 1.1 mrg default: 3401 1.1 mrg gcc_unreachable (); 3402 1.1 mrg } 3403 1.1 mrg } 3404 1.1 mrg } 3405 1.1 mrg if (dest_code == REG && GP_REG_P (REGNO (dest))) 3406 1.1 mrg { 3407 1.1 mrg if (src_code == REG) 3408 1.1 mrg if (FP_REG_P (REGNO (src))) 3409 1.1 mrg return dbl_p ? "movfr2gr.d\t%0,%1" : "movfr2gr.s\t%0,%1"; 3410 1.1 mrg 3411 1.1 mrg if (src_code == MEM) 3412 1.1 mrg { 3413 1.1 mrg const char *insn = NULL; 3414 1.1 mrg insn = loongarch_output_move_index (XEXP (src, 0), GET_MODE (src), 3415 1.1 mrg true); 3416 1.1 mrg if (insn) 3417 1.1 mrg return insn; 3418 1.1 mrg 3419 1.1 mrg rtx offset = XEXP (src, 0); 3420 1.1 mrg if (GET_CODE (offset) == PLUS) 3421 1.1 mrg offset = XEXP (offset, 1); 3422 1.1 mrg switch (GET_MODE_SIZE (mode)) 3423 1.1 mrg { 3424 1.1 mrg case 1: 3425 1.1 mrg return "ld.bu\t%0,%1"; 3426 1.1 mrg case 2: 3427 1.1 mrg return "ld.hu\t%0,%1"; 3428 1.1 mrg case 4: 3429 1.1 mrg if (const_arith_operand (offset, Pmode)) 3430 1.1 mrg return "ld.w\t%0,%1"; 3431 1.1 mrg else 3432 1.1 mrg return "ldptr.w\t%0,%1"; 3433 1.1 mrg case 8: 3434 1.1 mrg if (const_arith_operand (offset, Pmode)) 3435 1.1 mrg return "ld.d\t%0,%1"; 3436 1.1 mrg else 3437 1.1 mrg return "ldptr.d\t%0,%1"; 3438 1.1 mrg default: 3439 1.1 mrg gcc_unreachable (); 3440 1.1 mrg } 3441 1.1 mrg } 3442 1.1 mrg 3443 1.1 mrg if (src_code == CONST_INT) 3444 1.1 mrg { 3445 1.1 mrg if (LU12I_INT (src)) 3446 1.1 mrg return "lu12i.w\t%0,%1>>12\t\t\t# %X1"; 3447 1.1 mrg else if (IMM12_INT (src)) 3448 1.1 mrg return "addi.w\t%0,$r0,%1\t\t\t# %X1"; 3449 1.1 mrg else if (IMM12_INT_UNSIGNED (src)) 3450 1.1 mrg return "ori\t%0,$r0,%1\t\t\t# %X1"; 3451 1.1 mrg else if (LU52I_INT (src)) 3452 1.1 mrg return "lu52i.d\t%0,$r0,%X1>>52\t\t\t# %1"; 3453 1.1 mrg else 3454 1.1 mrg gcc_unreachable (); 3455 1.1 mrg } 3456 1.1 mrg 3457 1.1 mrg if (symbolic_operand (src, VOIDmode)) 3458 1.1 mrg { 3459 1.1 mrg if ((TARGET_CMODEL_TINY && (!loongarch_global_symbol_p (src) 3460 1.1 mrg || loongarch_symbol_binds_local_p (src))) 3461 1.1 mrg || (TARGET_CMODEL_TINY_STATIC && !loongarch_weak_symbol_p (src))) 3462 1.1 mrg { 3463 1.1 mrg /* The symbol must be aligned to 4 byte. */ 3464 1.1 mrg unsigned int align; 3465 1.1 mrg 3466 1.1 mrg if (LABEL_REF_P (src)) 3467 1.1 mrg align = 32 /* Whatever. */; 3468 1.1 mrg else if (CONSTANT_POOL_ADDRESS_P (src)) 3469 1.1 mrg align = GET_MODE_ALIGNMENT (get_pool_mode (src)); 3470 1.1 mrg else if (TREE_CONSTANT_POOL_ADDRESS_P (src)) 3471 1.1 mrg { 3472 1.1 mrg tree exp = SYMBOL_REF_DECL (src); 3473 1.1 mrg align = TYPE_ALIGN (TREE_TYPE (exp)); 3474 1.1 mrg align = loongarch_constant_alignment (exp, align); 3475 1.1 mrg } 3476 1.1 mrg else if (SYMBOL_REF_DECL (src)) 3477 1.1 mrg align = DECL_ALIGN (SYMBOL_REF_DECL (src)); 3478 1.1 mrg else if (SYMBOL_REF_HAS_BLOCK_INFO_P (src) 3479 1.1 mrg && SYMBOL_REF_BLOCK (src) != NULL) 3480 1.1 mrg align = SYMBOL_REF_BLOCK (src)->alignment; 3481 1.1 mrg else 3482 1.1 mrg align = BITS_PER_UNIT; 3483 1.1 mrg 3484 1.1 mrg if (align % (4 * 8) == 0) 3485 1.1 mrg return "pcaddi\t%0,%%pcrel(%1)>>2"; 3486 1.1 mrg } 3487 1.1 mrg if (TARGET_CMODEL_TINY 3488 1.1 mrg || TARGET_CMODEL_TINY_STATIC 3489 1.1 mrg || TARGET_CMODEL_NORMAL 3490 1.1 mrg || TARGET_CMODEL_LARGE) 3491 1.1 mrg { 3492 1.1 mrg if (!loongarch_global_symbol_p (src) 3493 1.1 mrg || loongarch_symbol_binds_local_p (src)) 3494 1.1 mrg return "la.local\t%0,%1"; 3495 1.1 mrg else 3496 1.1 mrg return "la.global\t%0,%1"; 3497 1.1 mrg } 3498 1.1 mrg if (TARGET_CMODEL_EXTREME) 3499 1.1 mrg { 3500 1.1 mrg sorry ("Normal symbol loading not implemented in extreme mode."); 3501 1.1 mrg gcc_unreachable (); 3502 1.1 mrg } 3503 1.1 mrg 3504 1.1 mrg } 3505 1.1 mrg } 3506 1.1 mrg if (src_code == REG && FP_REG_P (REGNO (src))) 3507 1.1 mrg { 3508 1.1 mrg if (dest_code == REG && FP_REG_P (REGNO (dest))) 3509 1.1 mrg return dbl_p ? "fmov.d\t%0,%1" : "fmov.s\t%0,%1"; 3510 1.1 mrg 3511 1.1 mrg if (dest_code == MEM) 3512 1.1 mrg { 3513 1.1 mrg const char *insn = NULL; 3514 1.1 mrg insn = loongarch_output_move_index_float (XEXP (dest, 0), 3515 1.1 mrg GET_MODE (dest), 3516 1.1 mrg false); 3517 1.1 mrg if (insn) 3518 1.1 mrg return insn; 3519 1.1 mrg 3520 1.1 mrg return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0"; 3521 1.1 mrg } 3522 1.1 mrg } 3523 1.1 mrg if (dest_code == REG && FP_REG_P (REGNO (dest))) 3524 1.1 mrg { 3525 1.1 mrg if (src_code == MEM) 3526 1.1 mrg { 3527 1.1 mrg const char *insn = NULL; 3528 1.1 mrg insn = loongarch_output_move_index_float (XEXP (src, 0), 3529 1.1 mrg GET_MODE (src), 3530 1.1 mrg true); 3531 1.1 mrg if (insn) 3532 1.1 mrg return insn; 3533 1.1 mrg 3534 1.1 mrg return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1"; 3535 1.1 mrg } 3536 1.1 mrg } 3537 1.1 mrg gcc_unreachable (); 3538 1.1 mrg } 3539 1.1 mrg 3540 1.1 mrg /* Return true if CMP1 is a suitable second operand for integer ordering 3541 1.1 mrg test CODE. */ 3542 1.1 mrg 3543 1.1 mrg static bool 3544 1.1 mrg loongarch_int_order_operand_ok_p (enum rtx_code code, rtx cmp1) 3545 1.1 mrg { 3546 1.1 mrg switch (code) 3547 1.1 mrg { 3548 1.1 mrg case GT: 3549 1.1 mrg case GTU: 3550 1.1 mrg return reg_or_0_operand (cmp1, VOIDmode); 3551 1.1 mrg 3552 1.1 mrg case GE: 3553 1.1 mrg case GEU: 3554 1.1 mrg return cmp1 == const1_rtx; 3555 1.1 mrg 3556 1.1 mrg case LT: 3557 1.1 mrg case LTU: 3558 1.1 mrg return arith_operand (cmp1, VOIDmode); 3559 1.1 mrg 3560 1.1 mrg case LE: 3561 1.1 mrg return sle_operand (cmp1, VOIDmode); 3562 1.1 mrg 3563 1.1 mrg case LEU: 3564 1.1 mrg return sleu_operand (cmp1, VOIDmode); 3565 1.1 mrg 3566 1.1 mrg default: 3567 1.1 mrg gcc_unreachable (); 3568 1.1 mrg } 3569 1.1 mrg } 3570 1.1 mrg 3571 1.1 mrg /* Return true if *CMP1 (of mode MODE) is a valid second operand for 3572 1.1 mrg integer ordering test *CODE, or if an equivalent combination can 3573 1.1 mrg be formed by adjusting *CODE and *CMP1. When returning true, update 3574 1.1 mrg *CODE and *CMP1 with the chosen code and operand, otherwise leave 3575 1.1 mrg them alone. */ 3576 1.1 mrg 3577 1.1 mrg static bool 3578 1.1 mrg loongarch_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1, 3579 1.1 mrg machine_mode mode) 3580 1.1 mrg { 3581 1.1 mrg HOST_WIDE_INT plus_one; 3582 1.1 mrg 3583 1.1 mrg if (loongarch_int_order_operand_ok_p (*code, *cmp1)) 3584 1.1 mrg return true; 3585 1.1 mrg 3586 1.1 mrg if (CONST_INT_P (*cmp1)) 3587 1.1 mrg switch (*code) 3588 1.1 mrg { 3589 1.1 mrg case LE: 3590 1.1 mrg plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); 3591 1.1 mrg if (INTVAL (*cmp1) < plus_one) 3592 1.1 mrg { 3593 1.1 mrg *code = LT; 3594 1.1 mrg *cmp1 = force_reg (mode, GEN_INT (plus_one)); 3595 1.1 mrg return true; 3596 1.1 mrg } 3597 1.1 mrg break; 3598 1.1 mrg 3599 1.1 mrg case LEU: 3600 1.1 mrg plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); 3601 1.1 mrg if (plus_one != 0) 3602 1.1 mrg { 3603 1.1 mrg *code = LTU; 3604 1.1 mrg *cmp1 = force_reg (mode, GEN_INT (plus_one)); 3605 1.1 mrg return true; 3606 1.1 mrg } 3607 1.1 mrg break; 3608 1.1 mrg 3609 1.1 mrg default: 3610 1.1 mrg break; 3611 1.1 mrg } 3612 1.1 mrg return false; 3613 1.1 mrg } 3614 1.1 mrg 3615 1.1 mrg /* Compare CMP0 and CMP1 using ordering test CODE and store the result 3616 1.1 mrg in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR 3617 1.1 mrg is nonnull, it's OK to set TARGET to the inverse of the result and 3618 1.1 mrg flip *INVERT_PTR instead. */ 3619 1.1 mrg 3620 1.1 mrg static void 3621 1.1 mrg loongarch_emit_int_order_test (enum rtx_code code, bool *invert_ptr, 3622 1.1 mrg rtx target, rtx cmp0, rtx cmp1) 3623 1.1 mrg { 3624 1.1 mrg machine_mode mode; 3625 1.1 mrg 3626 1.1 mrg /* First see if there is a LoongArch instruction that can do this operation. 3627 1.1 mrg If not, try doing the same for the inverse operation. If that also 3628 1.1 mrg fails, force CMP1 into a register and try again. */ 3629 1.1 mrg mode = GET_MODE (cmp0); 3630 1.1 mrg if (loongarch_canonicalize_int_order_test (&code, &cmp1, mode)) 3631 1.1 mrg loongarch_emit_binary (code, target, cmp0, cmp1); 3632 1.1 mrg else 3633 1.1 mrg { 3634 1.1 mrg enum rtx_code inv_code = reverse_condition (code); 3635 1.1 mrg if (!loongarch_canonicalize_int_order_test (&inv_code, &cmp1, mode)) 3636 1.1 mrg { 3637 1.1 mrg cmp1 = force_reg (mode, cmp1); 3638 1.1 mrg loongarch_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1); 3639 1.1 mrg } 3640 1.1 mrg else if (invert_ptr == 0) 3641 1.1 mrg { 3642 1.1 mrg rtx inv_target; 3643 1.1 mrg 3644 1.1 mrg inv_target = loongarch_force_binary (GET_MODE (target), 3645 1.1 mrg inv_code, cmp0, cmp1); 3646 1.1 mrg loongarch_emit_binary (XOR, target, inv_target, const1_rtx); 3647 1.1 mrg } 3648 1.1 mrg else 3649 1.1 mrg { 3650 1.1 mrg *invert_ptr = !*invert_ptr; 3651 1.1 mrg loongarch_emit_binary (inv_code, target, cmp0, cmp1); 3652 1.1 mrg } 3653 1.1 mrg } 3654 1.1 mrg } 3655 1.1 mrg 3656 1.1 mrg /* Return a register that is zero if CMP0 and CMP1 are equal. 3657 1.1 mrg The register will have the same mode as CMP0. */ 3658 1.1 mrg 3659 1.1 mrg static rtx 3660 1.1 mrg loongarch_zero_if_equal (rtx cmp0, rtx cmp1) 3661 1.1 mrg { 3662 1.1 mrg if (cmp1 == const0_rtx) 3663 1.1 mrg return cmp0; 3664 1.1 mrg 3665 1.1 mrg if (uns_arith_operand (cmp1, VOIDmode)) 3666 1.1 mrg return expand_binop (GET_MODE (cmp0), xor_optab, cmp0, cmp1, 0, 0, 3667 1.1 mrg OPTAB_DIRECT); 3668 1.1 mrg 3669 1.1 mrg return expand_binop (GET_MODE (cmp0), sub_optab, cmp0, cmp1, 0, 0, 3670 1.1 mrg OPTAB_DIRECT); 3671 1.1 mrg } 3672 1.1 mrg 3673 1.1 mrg /* Allocate a floating-point condition-code register of mode MODE. */ 3674 1.1 mrg 3675 1.1 mrg static rtx 3676 1.1 mrg loongarch_allocate_fcc (machine_mode mode) 3677 1.1 mrg { 3678 1.1 mrg unsigned int regno, count; 3679 1.1 mrg 3680 1.1 mrg gcc_assert (TARGET_HARD_FLOAT); 3681 1.1 mrg 3682 1.1 mrg if (mode == FCCmode) 3683 1.1 mrg count = 1; 3684 1.1 mrg else 3685 1.1 mrg gcc_unreachable (); 3686 1.1 mrg 3687 1.1 mrg cfun->machine->next_fcc += -cfun->machine->next_fcc & (count - 1); 3688 1.1 mrg if (cfun->machine->next_fcc > FCC_REG_LAST - FCC_REG_FIRST) 3689 1.1 mrg cfun->machine->next_fcc = 0; 3690 1.1 mrg 3691 1.1 mrg regno = FCC_REG_FIRST + cfun->machine->next_fcc; 3692 1.1 mrg cfun->machine->next_fcc += count; 3693 1.1 mrg return gen_rtx_REG (mode, regno); 3694 1.1 mrg } 3695 1.1 mrg 3696 1.1 mrg /* Sign- or zero-extend OP0 and OP1 for integer comparisons. */ 3697 1.1 mrg 3698 1.1 mrg static void 3699 1.1 mrg loongarch_extend_comparands (rtx_code code, rtx *op0, rtx *op1) 3700 1.1 mrg { 3701 1.1 mrg /* Comparisons consider all XLEN bits, so extend sub-XLEN values. */ 3702 1.1 mrg if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0))) 3703 1.1 mrg { 3704 1.1 mrg /* TODO: checkout It is more profitable to zero-extend QImode values. */ 3705 1.1 mrg if (unsigned_condition (code) == code && GET_MODE (*op0) == QImode) 3706 1.1 mrg { 3707 1.1 mrg *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0); 3708 1.1 mrg if (CONST_INT_P (*op1)) 3709 1.1 mrg *op1 = GEN_INT ((uint8_t) INTVAL (*op1)); 3710 1.1 mrg else 3711 1.1 mrg *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1); 3712 1.1 mrg } 3713 1.1 mrg else 3714 1.1 mrg { 3715 1.1 mrg *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0); 3716 1.1 mrg if (*op1 != const0_rtx) 3717 1.1 mrg *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1); 3718 1.1 mrg } 3719 1.1 mrg } 3720 1.1 mrg } 3721 1.1 mrg 3722 1.1 mrg /* Convert a comparison into something that can be used in a branch. On 3723 1.1 mrg entry, *OP0 and *OP1 are the values being compared and *CODE is the code 3724 1.1 mrg used to compare them. Update them to describe the final comparison. */ 3725 1.1 mrg 3726 1.1 mrg static void 3727 1.1 mrg loongarch_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1) 3728 1.1 mrg { 3729 1.1 mrg static const enum rtx_code 3730 1.1 mrg mag_comparisons[][2] = {{LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE}}; 3731 1.1 mrg 3732 1.1 mrg if (splittable_const_int_operand (*op1, VOIDmode)) 3733 1.1 mrg { 3734 1.1 mrg HOST_WIDE_INT rhs = INTVAL (*op1); 3735 1.1 mrg 3736 1.1 mrg if (*code == EQ || *code == NE) 3737 1.1 mrg { 3738 1.1 mrg /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */ 3739 1.1 mrg if (IMM12_OPERAND (-rhs)) 3740 1.1 mrg { 3741 1.1 mrg *op0 = loongarch_force_binary (GET_MODE (*op0), PLUS, *op0, 3742 1.1 mrg GEN_INT (-rhs)); 3743 1.1 mrg *op1 = const0_rtx; 3744 1.1 mrg } 3745 1.1 mrg } 3746 1.1 mrg else 3747 1.1 mrg { 3748 1.1 mrg /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000). */ 3749 1.1 mrg for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++) 3750 1.1 mrg { 3751 1.1 mrg HOST_WIDE_INT new_rhs; 3752 1.1 mrg bool increment = *code == mag_comparisons[i][0]; 3753 1.1 mrg bool decrement = *code == mag_comparisons[i][1]; 3754 1.1 mrg if (!increment && !decrement) 3755 1.1 mrg continue; 3756 1.1 mrg 3757 1.1 mrg new_rhs = rhs + (increment ? 1 : -1); 3758 1.1 mrg if (loongarch_integer_cost (new_rhs) 3759 1.1 mrg < loongarch_integer_cost (rhs) 3760 1.1 mrg && (rhs < 0) == (new_rhs < 0)) 3761 1.1 mrg { 3762 1.1 mrg *op1 = GEN_INT (new_rhs); 3763 1.1 mrg *code = mag_comparisons[i][increment]; 3764 1.1 mrg } 3765 1.1 mrg break; 3766 1.1 mrg } 3767 1.1 mrg } 3768 1.1 mrg } 3769 1.1 mrg 3770 1.1 mrg loongarch_extend_comparands (*code, op0, op1); 3771 1.1 mrg 3772 1.1 mrg *op0 = force_reg (word_mode, *op0); 3773 1.1 mrg if (*op1 != const0_rtx) 3774 1.1 mrg *op1 = force_reg (word_mode, *op1); 3775 1.1 mrg } 3776 1.1 mrg 3777 1.1 mrg /* Like loongarch_emit_int_compare, but for floating-point comparisons. */ 3778 1.1 mrg 3779 1.1 mrg static void 3780 1.1 mrg loongarch_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) 3781 1.1 mrg { 3782 1.1 mrg rtx cmp_op0 = *op0; 3783 1.1 mrg rtx cmp_op1 = *op1; 3784 1.1 mrg 3785 1.1 mrg /* Floating-point tests use a separate FCMP.cond.fmt 3786 1.1 mrg comparison to set a register. The branch or conditional move will 3787 1.1 mrg then compare that register against zero. 3788 1.1 mrg 3789 1.1 mrg Set CMP_CODE to the code of the comparison instruction and 3790 1.1 mrg *CODE to the code that the branch or move should use. */ 3791 1.1 mrg enum rtx_code cmp_code = *code; 3792 1.1 mrg /* Three FP conditions cannot be implemented by reversing the 3793 1.1 mrg operands for FCMP.cond.fmt, instead a reversed condition code is 3794 1.1 mrg required and a test for false. */ 3795 1.1 mrg *code = NE; 3796 1.1 mrg *op0 = loongarch_allocate_fcc (FCCmode); 3797 1.1 mrg 3798 1.1 mrg *op1 = const0_rtx; 3799 1.1 mrg loongarch_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); 3800 1.1 mrg } 3801 1.1 mrg 3802 1.1 mrg /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2] 3803 1.1 mrg and OPERAND[3]. Store the result in OPERANDS[0]. 3804 1.1 mrg 3805 1.1 mrg On 64-bit targets, the mode of the comparison and target will always be 3806 1.1 mrg SImode, thus possibly narrower than that of the comparison's operands. */ 3807 1.1 mrg 3808 1.1 mrg void 3809 1.1 mrg loongarch_expand_scc (rtx operands[]) 3810 1.1 mrg { 3811 1.1 mrg rtx target = operands[0]; 3812 1.1 mrg enum rtx_code code = GET_CODE (operands[1]); 3813 1.1 mrg rtx op0 = operands[2]; 3814 1.1 mrg rtx op1 = operands[3]; 3815 1.1 mrg 3816 1.1 mrg loongarch_extend_comparands (code, &op0, &op1); 3817 1.1 mrg op0 = force_reg (word_mode, op0); 3818 1.1 mrg 3819 1.1 mrg gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT); 3820 1.1 mrg 3821 1.1 mrg if (code == EQ || code == NE) 3822 1.1 mrg { 3823 1.1 mrg rtx zie = loongarch_zero_if_equal (op0, op1); 3824 1.1 mrg loongarch_emit_binary (code, target, zie, const0_rtx); 3825 1.1 mrg } 3826 1.1 mrg else 3827 1.1 mrg loongarch_emit_int_order_test (code, 0, target, op0, op1); 3828 1.1 mrg } 3829 1.1 mrg 3830 1.1 mrg /* Compare OPERANDS[1] with OPERANDS[2] using comparison code 3831 1.1 mrg CODE and jump to OPERANDS[3] if the condition holds. */ 3832 1.1 mrg 3833 1.1 mrg void 3834 1.1 mrg loongarch_expand_conditional_branch (rtx *operands) 3835 1.1 mrg { 3836 1.1 mrg enum rtx_code code = GET_CODE (operands[0]); 3837 1.1 mrg rtx op0 = operands[1]; 3838 1.1 mrg rtx op1 = operands[2]; 3839 1.1 mrg rtx condition; 3840 1.1 mrg 3841 1.1 mrg if (FLOAT_MODE_P (GET_MODE (op1))) 3842 1.1 mrg loongarch_emit_float_compare (&code, &op0, &op1); 3843 1.1 mrg else 3844 1.1 mrg loongarch_emit_int_compare (&code, &op0, &op1); 3845 1.1 mrg 3846 1.1 mrg condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 3847 1.1 mrg emit_jump_insn (gen_condjump (condition, operands[3])); 3848 1.1 mrg } 3849 1.1 mrg 3850 1.1 mrg /* Perform the comparison in OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] 3851 1.1 mrg if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ 3852 1.1 mrg 3853 1.1 mrg void 3854 1.1 mrg loongarch_expand_conditional_move (rtx *operands) 3855 1.1 mrg { 3856 1.1 mrg enum rtx_code code = GET_CODE (operands[1]); 3857 1.1 mrg rtx op0 = XEXP (operands[1], 0); 3858 1.1 mrg rtx op1 = XEXP (operands[1], 1); 3859 1.1 mrg 3860 1.1 mrg if (FLOAT_MODE_P (GET_MODE (op1))) 3861 1.1 mrg loongarch_emit_float_compare (&code, &op0, &op1); 3862 1.1 mrg else 3863 1.1 mrg { 3864 1.1 mrg loongarch_extend_comparands (code, &op0, &op1); 3865 1.1 mrg 3866 1.1 mrg op0 = force_reg (word_mode, op0); 3867 1.1 mrg 3868 1.1 mrg if (code == EQ || code == NE) 3869 1.1 mrg { 3870 1.1 mrg op0 = loongarch_zero_if_equal (op0, op1); 3871 1.1 mrg op1 = const0_rtx; 3872 1.1 mrg } 3873 1.1 mrg else 3874 1.1 mrg { 3875 1.1 mrg /* The comparison needs a separate scc instruction. Store the 3876 1.1 mrg result of the scc in *OP0 and compare it against zero. */ 3877 1.1 mrg bool invert = false; 3878 1.1 mrg rtx target = gen_reg_rtx (GET_MODE (op0)); 3879 1.1 mrg loongarch_emit_int_order_test (code, &invert, target, op0, op1); 3880 1.1 mrg code = invert ? EQ : NE; 3881 1.1 mrg op0 = target; 3882 1.1 mrg op1 = const0_rtx; 3883 1.1 mrg } 3884 1.1 mrg } 3885 1.1 mrg 3886 1.1 mrg rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); 3887 1.1 mrg /* There is no direct support for general conditional GP move involving 3888 1.1 mrg two registers using SEL. */ 3889 1.1 mrg if (INTEGRAL_MODE_P (GET_MODE (operands[2])) 3890 1.1 mrg && register_operand (operands[2], VOIDmode) 3891 1.1 mrg && register_operand (operands[3], VOIDmode)) 3892 1.1 mrg { 3893 1.1 mrg machine_mode mode = GET_MODE (operands[0]); 3894 1.1 mrg rtx temp = gen_reg_rtx (mode); 3895 1.1 mrg rtx temp2 = gen_reg_rtx (mode); 3896 1.1 mrg 3897 1.1 mrg emit_insn (gen_rtx_SET (temp, 3898 1.1 mrg gen_rtx_IF_THEN_ELSE (mode, cond, 3899 1.1 mrg operands[2], const0_rtx))); 3900 1.1 mrg 3901 1.1 mrg /* Flip the test for the second operand. */ 3902 1.1 mrg cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1); 3903 1.1 mrg 3904 1.1 mrg emit_insn (gen_rtx_SET (temp2, 3905 1.1 mrg gen_rtx_IF_THEN_ELSE (mode, cond, 3906 1.1 mrg operands[3], const0_rtx))); 3907 1.1 mrg 3908 1.1 mrg /* Merge the two results, at least one is guaranteed to be zero. */ 3909 1.1 mrg emit_insn (gen_rtx_SET (operands[0], gen_rtx_IOR (mode, temp, temp2))); 3910 1.1 mrg } 3911 1.1 mrg else 3912 1.1 mrg emit_insn (gen_rtx_SET (operands[0], 3913 1.1 mrg gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond, 3914 1.1 mrg operands[2], operands[3]))); 3915 1.1 mrg } 3916 1.1 mrg 3917 1.1 mrg /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ 3918 1.1 mrg 3919 1.1 mrg static void 3920 1.1 mrg loongarch_va_start (tree valist, rtx nextarg) 3921 1.1 mrg { 3922 1.1 mrg nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size); 3923 1.1 mrg std_expand_builtin_va_start (valist, nextarg); 3924 1.1 mrg } 3925 1.1 mrg 3926 1.1 mrg /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */ 3927 1.1 mrg 3928 1.1 mrg static bool 3929 1.1 mrg loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, 3930 1.1 mrg tree exp ATTRIBUTE_UNUSED) 3931 1.1 mrg { 3932 1.1 mrg /* Always OK. */ 3933 1.1 mrg return true; 3934 1.1 mrg } 3935 1.1 mrg 3936 1.1 mrg /* Emit straight-line code to move LENGTH bytes from SRC to DEST. 3937 1.1 mrg Assume that the areas do not overlap. */ 3938 1.1 mrg 3939 1.1 mrg static void 3940 1.1 mrg loongarch_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) 3941 1.1 mrg { 3942 1.1 mrg HOST_WIDE_INT offset, delta; 3943 1.1 mrg unsigned HOST_WIDE_INT bits; 3944 1.1 mrg int i; 3945 1.1 mrg machine_mode mode; 3946 1.1 mrg rtx *regs; 3947 1.1 mrg 3948 1.1 mrg bits = MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest))); 3949 1.1 mrg 3950 1.1 mrg mode = int_mode_for_size (bits, 0).require (); 3951 1.1 mrg delta = bits / BITS_PER_UNIT; 3952 1.1 mrg 3953 1.1 mrg /* Allocate a buffer for the temporary registers. */ 3954 1.1 mrg regs = XALLOCAVEC (rtx, length / delta); 3955 1.1 mrg 3956 1.1 mrg /* Load as many BITS-sized chunks as possible. Use a normal load if 3957 1.1 mrg the source has enough alignment, otherwise use left/right pairs. */ 3958 1.1 mrg for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) 3959 1.1 mrg { 3960 1.1 mrg regs[i] = gen_reg_rtx (mode); 3961 1.1 mrg loongarch_emit_move (regs[i], adjust_address (src, mode, offset)); 3962 1.1 mrg } 3963 1.1 mrg 3964 1.1 mrg for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) 3965 1.1 mrg loongarch_emit_move (adjust_address (dest, mode, offset), regs[i]); 3966 1.1 mrg 3967 1.1 mrg /* Mop up any left-over bytes. */ 3968 1.1 mrg if (offset < length) 3969 1.1 mrg { 3970 1.1 mrg src = adjust_address (src, BLKmode, offset); 3971 1.1 mrg dest = adjust_address (dest, BLKmode, offset); 3972 1.1 mrg move_by_pieces (dest, src, length - offset, 3973 1.1 mrg MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 3974 1.1 mrg (enum memop_ret) 0); 3975 1.1 mrg } 3976 1.1 mrg } 3977 1.1 mrg 3978 1.1 mrg /* Helper function for doing a loop-based block operation on memory 3979 1.1 mrg reference MEM. Each iteration of the loop will operate on LENGTH 3980 1.1 mrg bytes of MEM. 3981 1.1 mrg 3982 1.1 mrg Create a new base register for use within the loop and point it to 3983 1.1 mrg the start of MEM. Create a new memory reference that uses this 3984 1.1 mrg register. Store them in *LOOP_REG and *LOOP_MEM respectively. */ 3985 1.1 mrg 3986 1.1 mrg static void 3987 1.1 mrg loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg, 3988 1.1 mrg rtx *loop_mem) 3989 1.1 mrg { 3990 1.1 mrg *loop_reg = copy_addr_to_reg (XEXP (mem, 0)); 3991 1.1 mrg 3992 1.1 mrg /* Although the new mem does not refer to a known location, 3993 1.1 mrg it does keep up to LENGTH bytes of alignment. */ 3994 1.1 mrg *loop_mem = change_address (mem, BLKmode, *loop_reg); 3995 1.1 mrg set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT)); 3996 1.1 mrg } 3997 1.1 mrg 3998 1.1 mrg /* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER 3999 1.1 mrg bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that 4000 1.1 mrg the memory regions do not overlap. */ 4001 1.1 mrg 4002 1.1 mrg static void 4003 1.1 mrg loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, 4004 1.1 mrg HOST_WIDE_INT bytes_per_iter) 4005 1.1 mrg { 4006 1.1 mrg rtx_code_label *label; 4007 1.1 mrg rtx src_reg, dest_reg, final_src, test; 4008 1.1 mrg HOST_WIDE_INT leftover; 4009 1.1 mrg 4010 1.1 mrg leftover = length % bytes_per_iter; 4011 1.1 mrg length -= leftover; 4012 1.1 mrg 4013 1.1 mrg /* Create registers and memory references for use within the loop. */ 4014 1.1 mrg loongarch_adjust_block_mem (src, bytes_per_iter, &src_reg, &src); 4015 1.1 mrg loongarch_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest); 4016 1.1 mrg 4017 1.1 mrg /* Calculate the value that SRC_REG should have after the last iteration 4018 1.1 mrg of the loop. */ 4019 1.1 mrg final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), 0, 4020 1.1 mrg 0, OPTAB_WIDEN); 4021 1.1 mrg 4022 1.1 mrg /* Emit the start of the loop. */ 4023 1.1 mrg label = gen_label_rtx (); 4024 1.1 mrg emit_label (label); 4025 1.1 mrg 4026 1.1 mrg /* Emit the loop body. */ 4027 1.1 mrg loongarch_block_move_straight (dest, src, bytes_per_iter); 4028 1.1 mrg 4029 1.1 mrg /* Move on to the next block. */ 4030 1.1 mrg loongarch_emit_move (src_reg, 4031 1.1 mrg plus_constant (Pmode, src_reg, bytes_per_iter)); 4032 1.1 mrg loongarch_emit_move (dest_reg, 4033 1.1 mrg plus_constant (Pmode, dest_reg, bytes_per_iter)); 4034 1.1 mrg 4035 1.1 mrg /* Emit the loop condition. */ 4036 1.1 mrg test = gen_rtx_NE (VOIDmode, src_reg, final_src); 4037 1.1 mrg if (Pmode == DImode) 4038 1.1 mrg emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label)); 4039 1.1 mrg else 4040 1.1 mrg emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); 4041 1.1 mrg 4042 1.1 mrg /* Mop up any left-over bytes. */ 4043 1.1 mrg if (leftover) 4044 1.1 mrg loongarch_block_move_straight (dest, src, leftover); 4045 1.1 mrg else 4046 1.1 mrg /* Temporary fix for PR79150. */ 4047 1.1 mrg emit_insn (gen_nop ()); 4048 1.1 mrg } 4049 1.1 mrg 4050 1.1 mrg /* Expand a cpymemsi instruction, which copies LENGTH bytes from 4051 1.1 mrg memory reference SRC to memory reference DEST. */ 4052 1.1 mrg 4053 1.1 mrg bool 4054 1.1 mrg loongarch_expand_block_move (rtx dest, rtx src, rtx length) 4055 1.1 mrg { 4056 1.1 mrg int max_move_bytes = LARCH_MAX_MOVE_BYTES_STRAIGHT; 4057 1.1 mrg 4058 1.1 mrg if (CONST_INT_P (length) 4059 1.1 mrg && INTVAL (length) <= loongarch_max_inline_memcpy_size) 4060 1.1 mrg { 4061 1.1 mrg if (INTVAL (length) <= max_move_bytes) 4062 1.1 mrg { 4063 1.1 mrg loongarch_block_move_straight (dest, src, INTVAL (length)); 4064 1.1 mrg return true; 4065 1.1 mrg } 4066 1.1 mrg else if (optimize) 4067 1.1 mrg { 4068 1.1 mrg loongarch_block_move_loop (dest, src, INTVAL (length), 4069 1.1 mrg LARCH_MAX_MOVE_BYTES_PER_LOOP_ITER); 4070 1.1 mrg return true; 4071 1.1 mrg } 4072 1.1 mrg } 4073 1.1 mrg return false; 4074 1.1 mrg } 4075 1.1 mrg 4076 1.1 mrg /* Return true if loongarch_expand_block_move is the preferred 4077 1.1 mrg implementation of the 'cpymemsi' template. */ 4078 1.1 mrg 4079 1.1 mrg bool 4080 1.1 mrg loongarch_do_optimize_block_move_p (void) 4081 1.1 mrg { 4082 1.1 mrg /* if -m[no-]memcpy is given explicitly. */ 4083 1.1 mrg if (target_flags_explicit & MASK_MEMCPY) 4084 1.1 mrg return !TARGET_MEMCPY; 4085 1.1 mrg 4086 1.1 mrg /* if not, don't optimize under -Os. */ 4087 1.1 mrg return !optimize_size; 4088 1.1 mrg } 4089 1.1 mrg 4090 1.1 mrg /* Expand a QI or HI mode atomic memory operation. 4091 1.1 mrg 4092 1.1 mrg GENERATOR contains a pointer to the gen_* function that generates 4093 1.1 mrg the SI mode underlying atomic operation using masks that we 4094 1.1 mrg calculate. 4095 1.1 mrg 4096 1.1 mrg RESULT is the return register for the operation. Its value is NULL 4097 1.1 mrg if unused. 4098 1.1 mrg 4099 1.1 mrg MEM is the location of the atomic access. 4100 1.1 mrg 4101 1.1 mrg OLDVAL is the first operand for the operation. 4102 1.1 mrg 4103 1.1 mrg NEWVAL is the optional second operand for the operation. Its value 4104 1.1 mrg is NULL if unused. */ 4105 1.1 mrg 4106 1.1 mrg void 4107 1.1 mrg loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator, 4108 1.1 mrg rtx result, rtx mem, rtx oldval, rtx newval, 4109 1.1 mrg rtx model) 4110 1.1 mrg { 4111 1.1 mrg rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask; 4112 1.1 mrg rtx unshifted_mask_reg, mask, inverted_mask, si_op; 4113 1.1 mrg rtx res = NULL; 4114 1.1 mrg machine_mode mode; 4115 1.1 mrg 4116 1.1 mrg mode = GET_MODE (mem); 4117 1.1 mrg 4118 1.1 mrg /* Compute the address of the containing SImode value. */ 4119 1.1 mrg orig_addr = force_reg (Pmode, XEXP (mem, 0)); 4120 1.1 mrg memsi_addr = loongarch_force_binary (Pmode, AND, orig_addr, 4121 1.1 mrg force_reg (Pmode, GEN_INT (-4))); 4122 1.1 mrg 4123 1.1 mrg /* Create a memory reference for it. */ 4124 1.1 mrg memsi = gen_rtx_MEM (SImode, memsi_addr); 4125 1.1 mrg set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER); 4126 1.1 mrg MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem); 4127 1.1 mrg 4128 1.1 mrg /* Work out the byte offset of the QImode or HImode value, 4129 1.1 mrg counting from the least significant byte. */ 4130 1.1 mrg shift = loongarch_force_binary (Pmode, AND, orig_addr, GEN_INT (3)); 4131 1.1 mrg /* Multiply by eight to convert the shift value from bytes to bits. */ 4132 1.1 mrg loongarch_emit_binary (ASHIFT, shift, shift, GEN_INT (3)); 4133 1.1 mrg 4134 1.1 mrg /* Make the final shift an SImode value, so that it can be used in 4135 1.1 mrg SImode operations. */ 4136 1.1 mrg shiftsi = force_reg (SImode, gen_lowpart (SImode, shift)); 4137 1.1 mrg 4138 1.1 mrg /* Set MASK to an inclusive mask of the QImode or HImode value. */ 4139 1.1 mrg unshifted_mask = GEN_INT (GET_MODE_MASK (mode)); 4140 1.1 mrg unshifted_mask_reg = force_reg (SImode, unshifted_mask); 4141 1.1 mrg mask = loongarch_force_binary (SImode, ASHIFT, unshifted_mask_reg, shiftsi); 4142 1.1 mrg 4143 1.1 mrg /* Compute the equivalent exclusive mask. */ 4144 1.1 mrg inverted_mask = gen_reg_rtx (SImode); 4145 1.1 mrg emit_insn (gen_rtx_SET (inverted_mask, gen_rtx_NOT (SImode, mask))); 4146 1.1 mrg 4147 1.1 mrg /* Shift the old value into place. */ 4148 1.1 mrg if (oldval != const0_rtx) 4149 1.1 mrg { 4150 1.1 mrg oldval = convert_modes (SImode, mode, oldval, true); 4151 1.1 mrg oldval = force_reg (SImode, oldval); 4152 1.1 mrg oldval = loongarch_force_binary (SImode, ASHIFT, oldval, shiftsi); 4153 1.1 mrg } 4154 1.1 mrg 4155 1.1 mrg /* Do the same for the new value. */ 4156 1.1 mrg if (newval && newval != const0_rtx) 4157 1.1 mrg { 4158 1.1 mrg newval = convert_modes (SImode, mode, newval, true); 4159 1.1 mrg newval = force_reg (SImode, newval); 4160 1.1 mrg newval = loongarch_force_binary (SImode, ASHIFT, newval, shiftsi); 4161 1.1 mrg } 4162 1.1 mrg 4163 1.1 mrg /* Do the SImode atomic access. */ 4164 1.1 mrg if (result) 4165 1.1 mrg res = gen_reg_rtx (SImode); 4166 1.1 mrg 4167 1.1 mrg if (newval) 4168 1.1 mrg si_op = generator.fn_7 (res, memsi, mask, inverted_mask, oldval, newval, 4169 1.1 mrg model); 4170 1.1 mrg else if (result) 4171 1.1 mrg si_op = generator.fn_6 (res, memsi, mask, inverted_mask, oldval, model); 4172 1.1 mrg else 4173 1.1 mrg si_op = generator.fn_5 (memsi, mask, inverted_mask, oldval, model); 4174 1.1 mrg 4175 1.1 mrg emit_insn (si_op); 4176 1.1 mrg 4177 1.1 mrg if (result) 4178 1.1 mrg { 4179 1.1 mrg /* Shift and convert the result. */ 4180 1.1 mrg loongarch_emit_binary (AND, res, res, mask); 4181 1.1 mrg loongarch_emit_binary (LSHIFTRT, res, res, shiftsi); 4182 1.1 mrg loongarch_emit_move (result, gen_lowpart (GET_MODE (result), res)); 4183 1.1 mrg } 4184 1.1 mrg } 4185 1.1 mrg 4186 1.1 mrg /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the 4187 1.1 mrg source of an "ext" instruction or the destination of an "ins" 4188 1.1 mrg instruction. OP must be a register operand and the following 4189 1.1 mrg conditions must hold: 4190 1.1 mrg 4191 1.1 mrg 0 <= BITPOS < GET_MODE_BITSIZE (GET_MODE (op)) 4192 1.1 mrg 0 < WIDTH <= GET_MODE_BITSIZE (GET_MODE (op)) 4193 1.1 mrg 0 < BITPOS + WIDTH <= GET_MODE_BITSIZE (GET_MODE (op)) 4194 1.1 mrg 4195 1.1 mrg Also reject lengths equal to a word as they are better handled 4196 1.1 mrg by the move patterns. */ 4197 1.1 mrg 4198 1.1 mrg bool 4199 1.1 mrg loongarch_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos) 4200 1.1 mrg { 4201 1.1 mrg if (!register_operand (op, VOIDmode) 4202 1.1 mrg || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD) 4203 1.1 mrg return false; 4204 1.1 mrg 4205 1.1 mrg if (!IN_RANGE (width, 1, GET_MODE_BITSIZE (GET_MODE (op)) - 1)) 4206 1.1 mrg return false; 4207 1.1 mrg 4208 1.1 mrg if (bitpos < 0 || bitpos + width > GET_MODE_BITSIZE (GET_MODE (op))) 4209 1.1 mrg return false; 4210 1.1 mrg 4211 1.1 mrg return true; 4212 1.1 mrg } 4213 1.1 mrg 4214 1.1 mrg /* Print the text for PRINT_OPERAND punctation character CH to FILE. 4215 1.1 mrg The punctuation characters are: 4216 1.1 mrg 4217 1.1 mrg '.' Print the name of the register with a hard-wired zero (zero or $r0). 4218 1.1 mrg '$' Print the name of the stack pointer register (sp or $r3). 4219 1.1 mrg 4220 1.1 mrg See also loongarch_init_print_operand_punct. */ 4221 1.1 mrg 4222 1.1 mrg static void 4223 1.1 mrg loongarch_print_operand_punctuation (FILE *file, int ch) 4224 1.1 mrg { 4225 1.1 mrg switch (ch) 4226 1.1 mrg { 4227 1.1 mrg case '.': 4228 1.1 mrg fputs (reg_names[GP_REG_FIRST + 0], file); 4229 1.1 mrg break; 4230 1.1 mrg 4231 1.1 mrg case '$': 4232 1.1 mrg fputs (reg_names[STACK_POINTER_REGNUM], file); 4233 1.1 mrg break; 4234 1.1 mrg 4235 1.1 mrg default: 4236 1.1 mrg gcc_unreachable (); 4237 1.1 mrg break; 4238 1.1 mrg } 4239 1.1 mrg } 4240 1.1 mrg 4241 1.1 mrg /* Initialize loongarch_print_operand_punct. */ 4242 1.1 mrg 4243 1.1 mrg static void 4244 1.1 mrg loongarch_init_print_operand_punct (void) 4245 1.1 mrg { 4246 1.1 mrg const char *p; 4247 1.1 mrg 4248 1.1 mrg for (p = ".$"; *p; p++) 4249 1.1 mrg loongarch_print_operand_punct[(unsigned char) *p] = true; 4250 1.1 mrg } 4251 1.1 mrg 4252 1.1 mrg /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction 4253 1.1 mrg associated with condition CODE. Print the condition part of the 4254 1.1 mrg opcode to FILE. */ 4255 1.1 mrg 4256 1.1 mrg static void 4257 1.1 mrg loongarch_print_int_branch_condition (FILE *file, enum rtx_code code, 4258 1.1 mrg int letter) 4259 1.1 mrg { 4260 1.1 mrg switch (code) 4261 1.1 mrg { 4262 1.1 mrg case EQ: 4263 1.1 mrg case NE: 4264 1.1 mrg case GT: 4265 1.1 mrg case GE: 4266 1.1 mrg case LT: 4267 1.1 mrg case LE: 4268 1.1 mrg case GTU: 4269 1.1 mrg case GEU: 4270 1.1 mrg case LTU: 4271 1.1 mrg case LEU: 4272 1.1 mrg /* Conveniently, the LoongArch names for these conditions are the same 4273 1.1 mrg as their RTL equivalents. */ 4274 1.1 mrg fputs (GET_RTX_NAME (code), file); 4275 1.1 mrg break; 4276 1.1 mrg 4277 1.1 mrg default: 4278 1.1 mrg output_operand_lossage ("'%%%c' is not a valid operand prefix", letter); 4279 1.1 mrg break; 4280 1.1 mrg } 4281 1.1 mrg } 4282 1.1 mrg 4283 1.1 mrg /* Likewise floating-point branches. */ 4284 1.1 mrg 4285 1.1 mrg static void 4286 1.1 mrg loongarch_print_float_branch_condition (FILE *file, enum rtx_code code, 4287 1.1 mrg int letter) 4288 1.1 mrg { 4289 1.1 mrg switch (code) 4290 1.1 mrg { 4291 1.1 mrg case EQ: 4292 1.1 mrg fputs ("ceqz", file); 4293 1.1 mrg break; 4294 1.1 mrg 4295 1.1 mrg case NE: 4296 1.1 mrg fputs ("cnez", file); 4297 1.1 mrg break; 4298 1.1 mrg 4299 1.1 mrg default: 4300 1.1 mrg output_operand_lossage ("'%%%c' is not a valid operand prefix", letter); 4301 1.1 mrg break; 4302 1.1 mrg } 4303 1.1 mrg } 4304 1.1 mrg 4305 1.1 mrg /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */ 4306 1.1 mrg 4307 1.1 mrg static bool 4308 1.1 mrg loongarch_print_operand_punct_valid_p (unsigned char code) 4309 1.1 mrg { 4310 1.1 mrg return loongarch_print_operand_punct[code]; 4311 1.1 mrg } 4312 1.1 mrg 4313 1.1 mrg /* Return true if a FENCE should be emitted to before a memory access to 4314 1.1 mrg implement the release portion of memory model MODEL. */ 4315 1.1 mrg 4316 1.1 mrg static bool 4317 1.1 mrg loongarch_memmodel_needs_rel_acq_fence (enum memmodel model) 4318 1.1 mrg { 4319 1.1 mrg switch (model) 4320 1.1 mrg { 4321 1.1 mrg case MEMMODEL_ACQ_REL: 4322 1.1 mrg case MEMMODEL_SEQ_CST: 4323 1.1 mrg case MEMMODEL_SYNC_SEQ_CST: 4324 1.1 mrg case MEMMODEL_RELEASE: 4325 1.1 mrg case MEMMODEL_SYNC_RELEASE: 4326 1.1 mrg case MEMMODEL_ACQUIRE: 4327 1.1 mrg case MEMMODEL_CONSUME: 4328 1.1 mrg case MEMMODEL_SYNC_ACQUIRE: 4329 1.1 mrg return true; 4330 1.1 mrg 4331 1.1 mrg case MEMMODEL_RELAXED: 4332 1.1 mrg return false; 4333 1.1 mrg 4334 1.1 mrg default: 4335 1.1 mrg gcc_unreachable (); 4336 1.1 mrg } 4337 1.1 mrg } 4338 1.1 mrg 4339 1.1 mrg /* Return true if a FENCE should be emitted after a failed CAS to 4340 1.1 mrg implement the acquire semantic of failure_memorder. */ 4341 1.1 mrg 4342 1.1 mrg static bool 4343 1.1 mrg loongarch_cas_failure_memorder_needs_acquire (enum memmodel model) 4344 1.1 mrg { 4345 1.1 mrg switch (memmodel_base (model)) 4346 1.1 mrg { 4347 1.1 mrg case MEMMODEL_ACQUIRE: 4348 1.1 mrg case MEMMODEL_ACQ_REL: 4349 1.1 mrg case MEMMODEL_SEQ_CST: 4350 1.1 mrg return true; 4351 1.1 mrg 4352 1.1 mrg case MEMMODEL_RELAXED: 4353 1.1 mrg case MEMMODEL_RELEASE: 4354 1.1 mrg return false; 4355 1.1 mrg 4356 1.1 mrg /* MEMMODEL_CONSUME is deliberately not handled because it's always 4357 1.1 mrg replaced by MEMMODEL_ACQUIRE as at now. If you see an ICE caused by 4358 1.1 mrg MEMMODEL_CONSUME, read the change (re)introducing it carefully and 4359 1.1 mrg decide what to do. See PR 59448 and get_memmodel in builtins.cc. */ 4360 1.1 mrg default: 4361 1.1 mrg gcc_unreachable (); 4362 1.1 mrg } 4363 1.1 mrg } 4364 1.1 mrg 4365 1.1 mrg /* Implement TARGET_PRINT_OPERAND. The LoongArch-specific operand codes are: 4366 1.1 mrg 4367 1.1 mrg 'X' Print CONST_INT OP in hexadecimal format. 4368 1.1 mrg 'x' Print the low 16 bits of CONST_INT OP in hexadecimal format. 4369 1.1 mrg 'd' Print CONST_INT OP in decimal. 4370 1.1 mrg 'm' Print one less than CONST_INT OP in decimal. 4371 1.1 mrg 'y' Print exact log2 of CONST_INT OP in decimal. 4372 1.1 mrg 'C' Print the integer branch condition for comparison OP. 4373 1.1 mrg 'N' Print the inverse of the integer branch condition for comparison OP. 4374 1.1 mrg 'F' Print the FPU branch condition for comparison OP. 4375 1.1 mrg 'W' Print the inverse of the FPU branch condition for comparison OP. 4376 1.1 mrg 'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...), 4377 1.1 mrg 'z' for (eq:?I ...), 'n' for (ne:?I ...). 4378 1.1 mrg 't' Like 'T', but with the EQ/NE cases reversed 4379 1.1 mrg 'Y' Print loongarch_fp_conditions[INTVAL (OP)] 4380 1.1 mrg 'Z' Print OP and a comma for 8CC, otherwise print nothing. 4381 1.1 mrg 'z' Print $0 if OP is zero, otherwise print OP normally. 4382 1.1 mrg 'b' Print the address of a memory operand, without offset. 4383 1.1 mrg 'V' Print exact log2 of CONST_INT OP element 0 of a replicated 4384 1.1 mrg CONST_VECTOR in decimal. 4385 1.1 mrg 'A' Print a _DB suffix if the memory model requires a release. 4386 1.1 mrg 'G' Print a DBAR insn for CAS failure (with an acquire semantic if 4387 1.1 mrg needed, otherwise a simple load-load barrier). 4388 1.1 mrg 'i' Print i if the operand is not a register. */ 4389 1.1 mrg 4390 1.1 mrg static void 4391 1.1 mrg loongarch_print_operand (FILE *file, rtx op, int letter) 4392 1.1 mrg { 4393 1.1 mrg enum rtx_code code; 4394 1.1 mrg 4395 1.1 mrg if (loongarch_print_operand_punct_valid_p (letter)) 4396 1.1 mrg { 4397 1.1 mrg loongarch_print_operand_punctuation (file, letter); 4398 1.1 mrg return; 4399 1.1 mrg } 4400 1.1 mrg 4401 1.1 mrg gcc_assert (op); 4402 1.1 mrg code = GET_CODE (op); 4403 1.1 mrg 4404 1.1 mrg switch (letter) 4405 1.1 mrg { 4406 1.1 mrg case 'X': 4407 1.1 mrg if (CONST_INT_P (op)) 4408 1.1 mrg fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op)); 4409 1.1 mrg else 4410 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4411 1.1 mrg break; 4412 1.1 mrg 4413 1.1 mrg case 'x': 4414 1.1 mrg if (CONST_INT_P (op)) 4415 1.1 mrg fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff); 4416 1.1 mrg else 4417 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4418 1.1 mrg break; 4419 1.1 mrg 4420 1.1 mrg case 'd': 4421 1.1 mrg if (CONST_INT_P (op)) 4422 1.1 mrg fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); 4423 1.1 mrg else 4424 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4425 1.1 mrg break; 4426 1.1 mrg 4427 1.1 mrg case 'm': 4428 1.1 mrg if (CONST_INT_P (op)) 4429 1.1 mrg fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1); 4430 1.1 mrg else 4431 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4432 1.1 mrg break; 4433 1.1 mrg 4434 1.1 mrg case 'y': 4435 1.1 mrg if (CONST_INT_P (op)) 4436 1.1 mrg { 4437 1.1 mrg int val = exact_log2 (INTVAL (op)); 4438 1.1 mrg if (val != -1) 4439 1.1 mrg fprintf (file, "%d", val); 4440 1.1 mrg else 4441 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4442 1.1 mrg } 4443 1.1 mrg else 4444 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4445 1.1 mrg break; 4446 1.1 mrg 4447 1.1 mrg case 'V': 4448 1.1 mrg if (CONST_VECTOR_P (op)) 4449 1.1 mrg { 4450 1.1 mrg machine_mode mode = GET_MODE_INNER (GET_MODE (op)); 4451 1.1 mrg unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0)); 4452 1.1 mrg int vlog2 = exact_log2 (val & GET_MODE_MASK (mode)); 4453 1.1 mrg if (vlog2 != -1) 4454 1.1 mrg fprintf (file, "%d", vlog2); 4455 1.1 mrg else 4456 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4457 1.1 mrg } 4458 1.1 mrg else 4459 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4460 1.1 mrg break; 4461 1.1 mrg 4462 1.1 mrg case 'C': 4463 1.1 mrg loongarch_print_int_branch_condition (file, code, letter); 4464 1.1 mrg break; 4465 1.1 mrg 4466 1.1 mrg case 'N': 4467 1.1 mrg loongarch_print_int_branch_condition (file, reverse_condition (code), 4468 1.1 mrg letter); 4469 1.1 mrg break; 4470 1.1 mrg 4471 1.1 mrg case 'F': 4472 1.1 mrg loongarch_print_float_branch_condition (file, code, letter); 4473 1.1 mrg break; 4474 1.1 mrg 4475 1.1 mrg case 'W': 4476 1.1 mrg loongarch_print_float_branch_condition (file, reverse_condition (code), 4477 1.1 mrg letter); 4478 1.1 mrg break; 4479 1.1 mrg 4480 1.1 mrg case 'T': 4481 1.1 mrg case 't': 4482 1.1 mrg { 4483 1.1 mrg int truth = (code == NE) == (letter == 'T'); 4484 1.1 mrg fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file); 4485 1.1 mrg } 4486 1.1 mrg break; 4487 1.1 mrg 4488 1.1 mrg case 'Y': 4489 1.1 mrg if (code == CONST_INT 4490 1.1 mrg && UINTVAL (op) < ARRAY_SIZE (loongarch_fp_conditions)) 4491 1.1 mrg fputs (loongarch_fp_conditions[UINTVAL (op)], file); 4492 1.1 mrg else 4493 1.1 mrg output_operand_lossage ("'%%%c' is not a valid operand prefix", 4494 1.1 mrg letter); 4495 1.1 mrg break; 4496 1.1 mrg 4497 1.1 mrg case 'Z': 4498 1.1 mrg loongarch_print_operand (file, op, 0); 4499 1.1 mrg fputc (',', file); 4500 1.1 mrg break; 4501 1.1 mrg 4502 1.1 mrg case 'A': 4503 1.1 mrg if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op))) 4504 1.1 mrg fputs ("_db", file); 4505 1.1 mrg break; 4506 1.1 mrg 4507 1.1 mrg case 'G': 4508 1.1 mrg if (loongarch_cas_failure_memorder_needs_acquire ( 4509 1.1 mrg memmodel_from_int (INTVAL (op)))) 4510 1.1 mrg fputs ("dbar\t0b10100", file); 4511 1.1 mrg else 4512 1.1 mrg fputs ("dbar\t0x700", file); 4513 1.1 mrg break; 4514 1.1 mrg 4515 1.1 mrg case 'i': 4516 1.1 mrg if (code != REG) 4517 1.1 mrg fputs ("i", file); 4518 1.1 mrg break; 4519 1.1 mrg 4520 1.1 mrg default: 4521 1.1 mrg switch (code) 4522 1.1 mrg { 4523 1.1 mrg case REG: 4524 1.1 mrg { 4525 1.1 mrg unsigned int regno = REGNO (op); 4526 1.1 mrg if (letter && letter != 'z') 4527 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4528 1.1 mrg fprintf (file, "%s", reg_names[regno]); 4529 1.1 mrg } 4530 1.1 mrg break; 4531 1.1 mrg 4532 1.1 mrg case MEM: 4533 1.1 mrg if (letter == 'D') 4534 1.1 mrg output_address (GET_MODE (op), 4535 1.1 mrg plus_constant (Pmode, XEXP (op, 0), 4)); 4536 1.1 mrg else if (letter == 'b') 4537 1.1 mrg { 4538 1.1 mrg gcc_assert (REG_P (XEXP (op, 0))); 4539 1.1 mrg loongarch_print_operand (file, XEXP (op, 0), 0); 4540 1.1 mrg } 4541 1.1 mrg else if (letter && letter != 'z') 4542 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4543 1.1 mrg else 4544 1.1 mrg output_address (GET_MODE (op), XEXP (op, 0)); 4545 1.1 mrg break; 4546 1.1 mrg 4547 1.1 mrg default: 4548 1.1 mrg if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) 4549 1.1 mrg fputs (reg_names[GP_REG_FIRST], file); 4550 1.1 mrg else if (letter && letter != 'z') 4551 1.1 mrg output_operand_lossage ("invalid use of '%%%c'", letter); 4552 1.1 mrg else 4553 1.1 mrg output_addr_const (file, loongarch_strip_unspec_address (op)); 4554 1.1 mrg break; 4555 1.1 mrg } 4556 1.1 mrg } 4557 1.1 mrg } 4558 1.1 mrg 4559 1.1 mrg /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ 4560 1.1 mrg 4561 1.1 mrg static void 4562 1.1 mrg loongarch_print_operand_address (FILE *file, machine_mode /* mode */, rtx x) 4563 1.1 mrg { 4564 1.1 mrg struct loongarch_address_info addr; 4565 1.1 mrg 4566 1.1 mrg if (loongarch_classify_address (&addr, x, word_mode, true)) 4567 1.1 mrg switch (addr.type) 4568 1.1 mrg { 4569 1.1 mrg case ADDRESS_REG: 4570 1.1 mrg fprintf (file, "%s,", reg_names[REGNO (addr.reg)]); 4571 1.1 mrg loongarch_print_operand (file, addr.offset, 0); 4572 1.1 mrg return; 4573 1.1 mrg 4574 1.1 mrg case ADDRESS_REG_REG: 4575 1.1 mrg fprintf (file, "%s,%s", reg_names[REGNO (addr.reg)], 4576 1.1 mrg reg_names[REGNO (addr.offset)]); 4577 1.1 mrg return; 4578 1.1 mrg 4579 1.1 mrg case ADDRESS_CONST_INT: 4580 1.1 mrg fprintf (file, "%s,", reg_names[GP_REG_FIRST]); 4581 1.1 mrg output_addr_const (file, x); 4582 1.1 mrg return; 4583 1.1 mrg 4584 1.1 mrg case ADDRESS_SYMBOLIC: 4585 1.1 mrg output_addr_const (file, loongarch_strip_unspec_address (x)); 4586 1.1 mrg return; 4587 1.1 mrg } 4588 1.1 mrg if (CONST_INT_P (x)) 4589 1.1 mrg output_addr_const (file, x); 4590 1.1 mrg else 4591 1.1 mrg gcc_unreachable (); 4592 1.1 mrg } 4593 1.1 mrg 4594 1.1 mrg /* Implement TARGET_ASM_SELECT_RTX_SECTION. */ 4595 1.1 mrg 4596 1.1 mrg static section * 4597 1.1 mrg loongarch_select_rtx_section (machine_mode mode, rtx x, 4598 1.1 mrg unsigned HOST_WIDE_INT align) 4599 1.1 mrg { 4600 1.1 mrg /* ??? Consider using mergeable small data sections. */ 4601 1.1 mrg if (loongarch_rtx_constant_in_small_data_p (mode)) 4602 1.1 mrg return get_named_section (NULL, ".sdata", 0); 4603 1.1 mrg 4604 1.1 mrg return default_elf_select_rtx_section (mode, x, align); 4605 1.1 mrg } 4606 1.1 mrg 4607 1.1 mrg /* Implement TARGET_ASM_FUNCTION_RODATA_SECTION. 4608 1.1 mrg 4609 1.1 mrg The complication here is that jump tables will use absolute addresses, 4610 1.1 mrg and should therefore not be included in the read-only part of a DSO. 4611 1.1 mrg Handle such cases by selecting a normal data section instead of a 4612 1.1 mrg read-only one. The logic apes that in default_function_rodata_section. */ 4613 1.1 mrg 4614 1.1 mrg static section * 4615 1.1 mrg loongarch_function_rodata_section (tree decl, bool) 4616 1.1 mrg { 4617 1.1 mrg return default_function_rodata_section (decl, false); 4618 1.1 mrg } 4619 1.1 mrg 4620 1.1 mrg /* Implement TARGET_IN_SMALL_DATA_P. */ 4621 1.1 mrg 4622 1.1 mrg static bool 4623 1.1 mrg loongarch_in_small_data_p (const_tree decl) 4624 1.1 mrg { 4625 1.1 mrg int size; 4626 1.1 mrg 4627 1.1 mrg if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) 4628 1.1 mrg return false; 4629 1.1 mrg 4630 1.1 mrg if (VAR_P (decl) && DECL_SECTION_NAME (decl) != 0) 4631 1.1 mrg { 4632 1.1 mrg const char *name; 4633 1.1 mrg 4634 1.1 mrg /* Reject anything that isn't in a known small-data section. */ 4635 1.1 mrg name = DECL_SECTION_NAME (decl); 4636 1.1 mrg if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0) 4637 1.1 mrg return false; 4638 1.1 mrg 4639 1.1 mrg /* If a symbol is defined externally, the assembler will use the 4640 1.1 mrg usual -G rules when deciding how to implement macros. */ 4641 1.1 mrg if (!DECL_EXTERNAL (decl)) 4642 1.1 mrg return true; 4643 1.1 mrg } 4644 1.1 mrg 4645 1.1 mrg /* We have traditionally not treated zero-sized objects as small data, 4646 1.1 mrg so this is now effectively part of the ABI. */ 4647 1.1 mrg size = int_size_in_bytes (TREE_TYPE (decl)); 4648 1.1 mrg return size > 0 && size <= g_switch_value; 4649 1.1 mrg } 4650 1.1 mrg 4651 1.1 mrg /* The LoongArch debug format wants all automatic variables and arguments 4652 1.1 mrg to be in terms of the virtual frame pointer (stack pointer before 4653 1.1 mrg any adjustment in the function), while the LoongArch linker wants 4654 1.1 mrg the frame pointer to be the stack pointer after the initial 4655 1.1 mrg adjustment. So, we do the adjustment here. The arg pointer (which 4656 1.1 mrg is eliminated) points to the virtual frame pointer, while the frame 4657 1.1 mrg pointer (which may be eliminated) points to the stack pointer after 4658 1.1 mrg the initial adjustments. */ 4659 1.1 mrg 4660 1.1 mrg HOST_WIDE_INT 4661 1.1 mrg loongarch_debugger_offset (rtx addr, HOST_WIDE_INT offset) 4662 1.1 mrg { 4663 1.1 mrg rtx offset2 = const0_rtx; 4664 1.1 mrg rtx reg = eliminate_constant_term (addr, &offset2); 4665 1.1 mrg 4666 1.1 mrg if (offset == 0) 4667 1.1 mrg offset = INTVAL (offset2); 4668 1.1 mrg 4669 1.1 mrg if (reg == stack_pointer_rtx 4670 1.1 mrg || reg == frame_pointer_rtx 4671 1.1 mrg || reg == hard_frame_pointer_rtx) 4672 1.1 mrg { 4673 1.1 mrg offset -= cfun->machine->frame.total_size; 4674 1.1 mrg if (reg == hard_frame_pointer_rtx) 4675 1.1 mrg offset += cfun->machine->frame.hard_frame_pointer_offset; 4676 1.1 mrg } 4677 1.1 mrg 4678 1.1 mrg return offset; 4679 1.1 mrg } 4680 1.1 mrg 4681 1.1 mrg /* Implement ASM_OUTPUT_EXTERNAL. */ 4682 1.1 mrg 4683 1.1 mrg void 4684 1.1 mrg loongarch_output_external (FILE *file, tree decl, const char *name) 4685 1.1 mrg { 4686 1.1 mrg default_elf_asm_output_external (file, decl, name); 4687 1.1 mrg 4688 1.1 mrg /* We output the name if and only if TREE_SYMBOL_REFERENCED is 4689 1.1 mrg set in order to avoid putting out names that are never really 4690 1.1 mrg used. */ 4691 1.1 mrg if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 4692 1.1 mrg { 4693 1.1 mrg if (loongarch_in_small_data_p (decl)) 4694 1.1 mrg { 4695 1.1 mrg /* When using assembler macros, emit .extern directives for 4696 1.1 mrg all small-data externs so that the assembler knows how 4697 1.1 mrg big they are. 4698 1.1 mrg 4699 1.1 mrg In most cases it would be safe (though pointless) to emit 4700 1.1 mrg .externs for other symbols too. One exception is when an 4701 1.1 mrg object is within the -G limit but declared by the user to 4702 1.1 mrg be in a section other than .sbss or .sdata. */ 4703 1.1 mrg fputs ("\t.extern\t", file); 4704 1.1 mrg assemble_name (file, name); 4705 1.1 mrg fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC "\n", 4706 1.1 mrg int_size_in_bytes (TREE_TYPE (decl))); 4707 1.1 mrg } 4708 1.1 mrg } 4709 1.1 mrg } 4710 1.1 mrg 4711 1.1 mrg /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */ 4712 1.1 mrg 4713 1.1 mrg static void ATTRIBUTE_UNUSED 4714 1.1 mrg loongarch_output_dwarf_dtprel (FILE *file, int size, rtx x) 4715 1.1 mrg { 4716 1.1 mrg switch (size) 4717 1.1 mrg { 4718 1.1 mrg case 4: 4719 1.1 mrg fputs ("\t.dtprelword\t", file); 4720 1.1 mrg break; 4721 1.1 mrg 4722 1.1 mrg case 8: 4723 1.1 mrg fputs ("\t.dtpreldword\t", file); 4724 1.1 mrg break; 4725 1.1 mrg 4726 1.1 mrg default: 4727 1.1 mrg gcc_unreachable (); 4728 1.1 mrg } 4729 1.1 mrg output_addr_const (file, x); 4730 1.1 mrg fputs ("+0x8000", file); 4731 1.1 mrg } 4732 1.1 mrg 4733 1.1 mrg /* Implement ASM_OUTPUT_ASCII. */ 4734 1.1 mrg 4735 1.1 mrg void 4736 1.1 mrg loongarch_output_ascii (FILE *stream, const char *string, size_t len) 4737 1.1 mrg { 4738 1.1 mrg size_t i; 4739 1.1 mrg int cur_pos; 4740 1.1 mrg 4741 1.1 mrg cur_pos = 17; 4742 1.1 mrg fprintf (stream, "\t.ascii\t\""); 4743 1.1 mrg for (i = 0; i < len; i++) 4744 1.1 mrg { 4745 1.1 mrg int c; 4746 1.1 mrg 4747 1.1 mrg c = (unsigned char) string[i]; 4748 1.1 mrg if (ISPRINT (c)) 4749 1.1 mrg { 4750 1.1 mrg if (c == '\\' || c == '\"') 4751 1.1 mrg { 4752 1.1 mrg putc ('\\', stream); 4753 1.1 mrg cur_pos++; 4754 1.1 mrg } 4755 1.1 mrg putc (c, stream); 4756 1.1 mrg cur_pos++; 4757 1.1 mrg } 4758 1.1 mrg else 4759 1.1 mrg { 4760 1.1 mrg fprintf (stream, "\\%03o", c); 4761 1.1 mrg cur_pos += 4; 4762 1.1 mrg } 4763 1.1 mrg 4764 1.1 mrg if (cur_pos > 72 && i + 1 < len) 4765 1.1 mrg { 4766 1.1 mrg cur_pos = 17; 4767 1.1 mrg fprintf (stream, "\"\n\t.ascii\t\""); 4768 1.1 mrg } 4769 1.1 mrg } 4770 1.1 mrg fprintf (stream, "\"\n"); 4771 1.1 mrg } 4772 1.1 mrg 4773 1.1 mrg /* Implement TARGET_FRAME_POINTER_REQUIRED. */ 4774 1.1 mrg 4775 1.1 mrg static bool 4776 1.1 mrg loongarch_frame_pointer_required (void) 4777 1.1 mrg { 4778 1.1 mrg /* If the function contains dynamic stack allocations, we need to 4779 1.1 mrg use the frame pointer to access the static parts of the frame. */ 4780 1.1 mrg if (cfun->calls_alloca) 4781 1.1 mrg return true; 4782 1.1 mrg 4783 1.1 mrg return false; 4784 1.1 mrg } 4785 1.1 mrg 4786 1.1 mrg /* Implement TARGET_CAN_ELIMINATE. Make sure that we're not trying 4787 1.1 mrg to eliminate to the wrong hard frame pointer. */ 4788 1.1 mrg 4789 1.1 mrg static bool 4790 1.1 mrg loongarch_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) 4791 1.1 mrg { 4792 1.1 mrg return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM); 4793 1.1 mrg } 4794 1.1 mrg 4795 1.1 mrg /* Implement RETURN_ADDR_RTX. We do not support moving back to a 4796 1.1 mrg previous frame. */ 4797 1.1 mrg 4798 1.1 mrg rtx 4799 1.1 mrg loongarch_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) 4800 1.1 mrg { 4801 1.1 mrg if (count != 0) 4802 1.1 mrg return const0_rtx; 4803 1.1 mrg 4804 1.1 mrg return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); 4805 1.1 mrg } 4806 1.1 mrg 4807 1.1 mrg /* Emit code to change the current function's return address to 4808 1.1 mrg ADDRESS. SCRATCH is available as a scratch register, if needed. 4809 1.1 mrg ADDRESS and SCRATCH are both word-mode GPRs. */ 4810 1.1 mrg 4811 1.1 mrg void 4812 1.1 mrg loongarch_set_return_address (rtx address, rtx scratch) 4813 1.1 mrg { 4814 1.1 mrg rtx slot_address; 4815 1.1 mrg 4816 1.1 mrg gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM)); 4817 1.1 mrg 4818 1.1 mrg if (frame_pointer_needed) 4819 1.1 mrg slot_address = loongarch_add_offset (scratch, hard_frame_pointer_rtx, 4820 1.1 mrg -UNITS_PER_WORD); 4821 1.1 mrg else 4822 1.1 mrg slot_address = loongarch_add_offset (scratch, stack_pointer_rtx, 4823 1.1 mrg cfun->machine->frame.gp_sp_offset); 4824 1.1 mrg 4825 1.1 mrg loongarch_emit_move (gen_frame_mem (GET_MODE (address), slot_address), 4826 1.1 mrg address); 4827 1.1 mrg } 4828 1.1 mrg 4829 1.1 mrg /* Return true if register REGNO can store a value of mode MODE. 4830 1.1 mrg The result of this function is cached in loongarch_hard_regno_mode_ok. */ 4831 1.1 mrg 4832 1.1 mrg static bool 4833 1.1 mrg loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode) 4834 1.1 mrg { 4835 1.1 mrg unsigned int size; 4836 1.1 mrg enum mode_class mclass; 4837 1.1 mrg 4838 1.1 mrg if (mode == FCCmode) 4839 1.1 mrg return FCC_REG_P (regno); 4840 1.1 mrg 4841 1.1 mrg size = GET_MODE_SIZE (mode); 4842 1.1 mrg mclass = GET_MODE_CLASS (mode); 4843 1.1 mrg 4844 1.1 mrg if (GP_REG_P (regno)) 4845 1.1 mrg return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD; 4846 1.1 mrg 4847 1.1 mrg if (FP_REG_P (regno)) 4848 1.1 mrg { 4849 1.1 mrg if (mclass == MODE_FLOAT 4850 1.1 mrg || mclass == MODE_COMPLEX_FLOAT 4851 1.1 mrg || mclass == MODE_VECTOR_FLOAT) 4852 1.1 mrg return size <= UNITS_PER_FPVALUE; 4853 1.1 mrg 4854 1.1 mrg /* Allow integer modes that fit into a single register. We need 4855 1.1 mrg to put integers into FPRs when using instructions like CVT 4856 1.1 mrg and TRUNC. There's no point allowing sizes smaller than a word, 4857 1.1 mrg because the FPU has no appropriate load/store instructions. */ 4858 1.1 mrg if (mclass == MODE_INT) 4859 1.1 mrg return size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FPREG; 4860 1.1 mrg } 4861 1.1 mrg 4862 1.1 mrg return false; 4863 1.1 mrg } 4864 1.1 mrg 4865 1.1 mrg /* Implement TARGET_HARD_REGNO_MODE_OK. */ 4866 1.1 mrg 4867 1.1 mrg static bool 4868 1.1 mrg loongarch_hard_regno_mode_ok (unsigned int regno, machine_mode mode) 4869 1.1 mrg { 4870 1.1 mrg return loongarch_hard_regno_mode_ok_p[mode][regno]; 4871 1.1 mrg } 4872 1.1 mrg 4873 1.1 mrg /* Implement TARGET_HARD_REGNO_NREGS. */ 4874 1.1 mrg 4875 1.1 mrg static unsigned int 4876 1.1 mrg loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode) 4877 1.1 mrg { 4878 1.1 mrg if (FCC_REG_P (regno)) 4879 1.1 mrg /* The size of FP status registers is always 4, because they only hold 4880 1.1 mrg FCCmode values, and FCCmode is always considered to be 4 bytes wide. */ 4881 1.1 mrg return (GET_MODE_SIZE (mode) + 3) / 4; 4882 1.1 mrg 4883 1.1 mrg if (FP_REG_P (regno)) 4884 1.1 mrg return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG; 4885 1.1 mrg 4886 1.1 mrg /* All other registers are word-sized. */ 4887 1.1 mrg return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 4888 1.1 mrg } 4889 1.1 mrg 4890 1.1 mrg /* Implement CLASS_MAX_NREGS, taking the maximum of the cases 4891 1.1 mrg in loongarch_hard_regno_nregs. */ 4892 1.1 mrg 4893 1.1 mrg int 4894 1.1 mrg loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode) 4895 1.1 mrg { 4896 1.1 mrg int size; 4897 1.1 mrg HARD_REG_SET left; 4898 1.1 mrg 4899 1.1 mrg size = 0x8000; 4900 1.1 mrg left = reg_class_contents[rclass]; 4901 1.1 mrg if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FCC_REGS])) 4902 1.1 mrg { 4903 1.1 mrg if (loongarch_hard_regno_mode_ok (FCC_REG_FIRST, mode)) 4904 1.1 mrg size = MIN (size, 4); 4905 1.1 mrg 4906 1.1 mrg left &= ~reg_class_contents[FCC_REGS]; 4907 1.1 mrg } 4908 1.1 mrg if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS])) 4909 1.1 mrg { 4910 1.1 mrg if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode)) 4911 1.1 mrg size = MIN (size, UNITS_PER_FPREG); 4912 1.1 mrg 4913 1.1 mrg left &= ~reg_class_contents[FP_REGS]; 4914 1.1 mrg } 4915 1.1 mrg if (!hard_reg_set_empty_p (left)) 4916 1.1 mrg size = MIN (size, UNITS_PER_WORD); 4917 1.1 mrg return (GET_MODE_SIZE (mode) + size - 1) / size; 4918 1.1 mrg } 4919 1.1 mrg 4920 1.1 mrg /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */ 4921 1.1 mrg 4922 1.1 mrg static bool 4923 1.1 mrg loongarch_can_change_mode_class (machine_mode, machine_mode, 4924 1.1 mrg reg_class_t rclass) 4925 1.1 mrg { 4926 1.1 mrg return !reg_classes_intersect_p (FP_REGS, rclass); 4927 1.1 mrg } 4928 1.1 mrg 4929 1.1 mrg /* Return true if moves in mode MODE can use the FPU's fmov.fmt instruction, 4930 1.1 mrg */ 4931 1.1 mrg 4932 1.1 mrg static bool 4933 1.1 mrg loongarch_mode_ok_for_mov_fmt_p (machine_mode mode) 4934 1.1 mrg { 4935 1.1 mrg switch (mode) 4936 1.1 mrg { 4937 1.1 mrg case E_FCCmode: 4938 1.1 mrg case E_SFmode: 4939 1.1 mrg return TARGET_HARD_FLOAT; 4940 1.1 mrg 4941 1.1 mrg case E_DFmode: 4942 1.1 mrg return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT; 4943 1.1 mrg 4944 1.1 mrg default: 4945 1.1 mrg return 0; 4946 1.1 mrg } 4947 1.1 mrg } 4948 1.1 mrg 4949 1.1 mrg /* Implement TARGET_MODES_TIEABLE_P. */ 4950 1.1 mrg 4951 1.1 mrg static bool 4952 1.1 mrg loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2) 4953 1.1 mrg { 4954 1.1 mrg /* FPRs allow no mode punning, so it's not worth tying modes if we'd 4955 1.1 mrg prefer to put one of them in FPRs. */ 4956 1.1 mrg return (mode1 == mode2 4957 1.1 mrg || (!loongarch_mode_ok_for_mov_fmt_p (mode1) 4958 1.1 mrg && !loongarch_mode_ok_for_mov_fmt_p (mode2))); 4959 1.1 mrg } 4960 1.1 mrg 4961 1.1 mrg /* Implement TARGET_PREFERRED_RELOAD_CLASS. */ 4962 1.1 mrg 4963 1.1 mrg static reg_class_t 4964 1.1 mrg loongarch_preferred_reload_class (rtx x, reg_class_t rclass) 4965 1.1 mrg { 4966 1.1 mrg if (reg_class_subset_p (FP_REGS, rclass) 4967 1.1 mrg && loongarch_mode_ok_for_mov_fmt_p (GET_MODE (x))) 4968 1.1 mrg return FP_REGS; 4969 1.1 mrg 4970 1.1 mrg if (reg_class_subset_p (GR_REGS, rclass)) 4971 1.1 mrg rclass = GR_REGS; 4972 1.1 mrg 4973 1.1 mrg return rclass; 4974 1.1 mrg } 4975 1.1 mrg 4976 1.1 mrg /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation. 4977 1.1 mrg Return a "canonical" class to represent it in later calculations. */ 4978 1.1 mrg 4979 1.1 mrg static reg_class_t 4980 1.1 mrg loongarch_canonicalize_move_class (reg_class_t rclass) 4981 1.1 mrg { 4982 1.1 mrg if (reg_class_subset_p (rclass, GENERAL_REGS)) 4983 1.1 mrg rclass = GENERAL_REGS; 4984 1.1 mrg 4985 1.1 mrg return rclass; 4986 1.1 mrg } 4987 1.1 mrg 4988 1.1 mrg /* Return the cost of moving a value from a register of class FROM to a GPR. 4989 1.1 mrg Return 0 for classes that are unions of other classes handled by this 4990 1.1 mrg function. */ 4991 1.1 mrg 4992 1.1 mrg static int 4993 1.1 mrg loongarch_move_to_gpr_cost (reg_class_t from) 4994 1.1 mrg { 4995 1.1 mrg switch (from) 4996 1.1 mrg { 4997 1.1 mrg case GENERAL_REGS: 4998 1.1 mrg /* MOVE macro. */ 4999 1.1 mrg return 2; 5000 1.1 mrg 5001 1.1 mrg case FP_REGS: 5002 1.1 mrg /* MOVFR2GR, etc. */ 5003 1.1 mrg return 4; 5004 1.1 mrg 5005 1.1 mrg default: 5006 1.1 mrg return 0; 5007 1.1 mrg } 5008 1.1 mrg } 5009 1.1 mrg 5010 1.1 mrg /* Return the cost of moving a value from a GPR to a register of class TO. 5011 1.1 mrg Return 0 for classes that are unions of other classes handled by this 5012 1.1 mrg function. */ 5013 1.1 mrg 5014 1.1 mrg static int 5015 1.1 mrg loongarch_move_from_gpr_cost (reg_class_t to) 5016 1.1 mrg { 5017 1.1 mrg switch (to) 5018 1.1 mrg { 5019 1.1 mrg case GENERAL_REGS: 5020 1.1 mrg /*MOVE macro. */ 5021 1.1 mrg return 2; 5022 1.1 mrg 5023 1.1 mrg case FP_REGS: 5024 1.1 mrg /* MOVGR2FR, etc. */ 5025 1.1 mrg return 4; 5026 1.1 mrg 5027 1.1 mrg default: 5028 1.1 mrg return 0; 5029 1.1 mrg } 5030 1.1 mrg } 5031 1.1 mrg 5032 1.1 mrg /* Implement TARGET_REGISTER_MOVE_COST. Return 0 for classes that are the 5033 1.1 mrg maximum of the move costs for subclasses; regclass will work out 5034 1.1 mrg the maximum for us. */ 5035 1.1 mrg 5036 1.1 mrg static int 5037 1.1 mrg loongarch_register_move_cost (machine_mode mode, reg_class_t from, 5038 1.1 mrg reg_class_t to) 5039 1.1 mrg { 5040 1.1 mrg reg_class_t dregs; 5041 1.1 mrg int cost1, cost2; 5042 1.1 mrg 5043 1.1 mrg from = loongarch_canonicalize_move_class (from); 5044 1.1 mrg to = loongarch_canonicalize_move_class (to); 5045 1.1 mrg 5046 1.1 mrg /* Handle moves that can be done without using general-purpose registers. */ 5047 1.1 mrg if (from == FP_REGS) 5048 1.1 mrg { 5049 1.1 mrg if (to == FP_REGS && loongarch_mode_ok_for_mov_fmt_p (mode)) 5050 1.1 mrg /* FMOV.FMT. */ 5051 1.1 mrg return 4; 5052 1.1 mrg } 5053 1.1 mrg 5054 1.1 mrg /* Handle cases in which only one class deviates from the ideal. */ 5055 1.1 mrg dregs = GENERAL_REGS; 5056 1.1 mrg if (from == dregs) 5057 1.1 mrg return loongarch_move_from_gpr_cost (to); 5058 1.1 mrg if (to == dregs) 5059 1.1 mrg return loongarch_move_to_gpr_cost (from); 5060 1.1 mrg 5061 1.1 mrg /* Handles cases that require a GPR temporary. */ 5062 1.1 mrg cost1 = loongarch_move_to_gpr_cost (from); 5063 1.1 mrg if (cost1 != 0) 5064 1.1 mrg { 5065 1.1 mrg cost2 = loongarch_move_from_gpr_cost (to); 5066 1.1 mrg if (cost2 != 0) 5067 1.1 mrg return cost1 + cost2; 5068 1.1 mrg } 5069 1.1 mrg 5070 1.1 mrg return 0; 5071 1.1 mrg } 5072 1.1 mrg 5073 1.1 mrg /* Implement TARGET_MEMORY_MOVE_COST. */ 5074 1.1 mrg 5075 1.1 mrg static int 5076 1.1 mrg loongarch_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) 5077 1.1 mrg { 5078 1.1 mrg return (loongarch_cost->memory_latency 5079 1.1 mrg + memory_move_secondary_cost (mode, rclass, in)); 5080 1.1 mrg } 5081 1.1 mrg 5082 1.1 mrg /* Return the register class required for a secondary register when 5083 1.1 mrg copying between one of the registers in RCLASS and value X, which 5084 1.1 mrg has mode MODE. X is the source of the move if IN_P, otherwise it 5085 1.1 mrg is the destination. Return NO_REGS if no secondary register is 5086 1.1 mrg needed. */ 5087 1.1 mrg 5088 1.1 mrg static reg_class_t 5089 1.1 mrg loongarch_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, 5090 1.1 mrg reg_class_t rclass, machine_mode mode, 5091 1.1 mrg secondary_reload_info *sri ATTRIBUTE_UNUSED) 5092 1.1 mrg { 5093 1.1 mrg int regno; 5094 1.1 mrg 5095 1.1 mrg regno = true_regnum (x); 5096 1.1 mrg 5097 1.1 mrg if (reg_class_subset_p (rclass, FP_REGS)) 5098 1.1 mrg { 5099 1.1 mrg if (regno < 0 5100 1.1 mrg || (MEM_P (x) 5101 1.1 mrg && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8))) 5102 1.1 mrg /* In this case we can use fld.s, fst.s, fld.d or fst.d. */ 5103 1.1 mrg return NO_REGS; 5104 1.1 mrg 5105 1.1 mrg if (GP_REG_P (regno) || x == CONST0_RTX (mode)) 5106 1.1 mrg /* In this case we can use movgr2fr.s, movfr2gr.s, movgr2fr.d or 5107 1.1 mrg * movfr2gr.d. */ 5108 1.1 mrg return NO_REGS; 5109 1.1 mrg 5110 1.1 mrg if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x)) 5111 1.1 mrg /* We can force the constant to memory and use fld.s 5112 1.1 mrg and fld.d. As above, we will use pairs of lwc1s if 5113 1.1 mrg ldc1 is not supported. */ 5114 1.1 mrg return NO_REGS; 5115 1.1 mrg 5116 1.1 mrg if (FP_REG_P (regno) && loongarch_mode_ok_for_mov_fmt_p (mode)) 5117 1.1 mrg /* In this case we can use fmov.{s/d}. */ 5118 1.1 mrg return NO_REGS; 5119 1.1 mrg 5120 1.1 mrg /* Otherwise, we need to reload through an integer register. */ 5121 1.1 mrg return GR_REGS; 5122 1.1 mrg } 5123 1.1 mrg if (FP_REG_P (regno)) 5124 1.1 mrg return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS; 5125 1.1 mrg 5126 1.1 mrg return NO_REGS; 5127 1.1 mrg } 5128 1.1 mrg 5129 1.1 mrg /* Implement TARGET_VALID_POINTER_MODE. */ 5130 1.1 mrg 5131 1.1 mrg static bool 5132 1.1 mrg loongarch_valid_pointer_mode (scalar_int_mode mode) 5133 1.1 mrg { 5134 1.1 mrg return mode == SImode || (TARGET_64BIT && mode == DImode); 5135 1.1 mrg } 5136 1.1 mrg 5137 1.1 mrg /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ 5138 1.1 mrg 5139 1.1 mrg static bool 5140 1.1 mrg loongarch_scalar_mode_supported_p (scalar_mode mode) 5141 1.1 mrg { 5142 1.1 mrg if (ALL_FIXED_POINT_MODE_P (mode) 5143 1.1 mrg && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD) 5144 1.1 mrg return true; 5145 1.1 mrg 5146 1.1 mrg return default_scalar_mode_supported_p (mode); 5147 1.1 mrg } 5148 1.1 mrg 5149 1.1 mrg /* Return the assembly code for INSN, which has the operands given by 5150 1.1 mrg OPERANDS, and which branches to OPERANDS[0] if some condition is true. 5151 1.1 mrg BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0] 5152 1.1 mrg is in range of a direct branch. BRANCH_IF_FALSE is an inverted 5153 1.1 mrg version of BRANCH_IF_TRUE. */ 5154 1.1 mrg 5155 1.1 mrg const char * 5156 1.1 mrg loongarch_output_conditional_branch (rtx_insn *insn, rtx *operands, 5157 1.1 mrg const char *branch_if_true, 5158 1.1 mrg const char *branch_if_false) 5159 1.1 mrg { 5160 1.1 mrg unsigned int length; 5161 1.1 mrg rtx taken; 5162 1.1 mrg 5163 1.1 mrg gcc_assert (LABEL_P (operands[0])); 5164 1.1 mrg 5165 1.1 mrg length = get_attr_length (insn); 5166 1.1 mrg if (length <= 4) 5167 1.1 mrg { 5168 1.1 mrg return branch_if_true; 5169 1.1 mrg } 5170 1.1 mrg 5171 1.1 mrg /* Generate a reversed branch around a direct jump. */ 5172 1.1 mrg rtx_code_label *not_taken = gen_label_rtx (); 5173 1.1 mrg taken = operands[0]; 5174 1.1 mrg 5175 1.1 mrg /* Generate the reversed branch to NOT_TAKEN. */ 5176 1.1 mrg operands[0] = not_taken; 5177 1.1 mrg output_asm_insn (branch_if_false, operands); 5178 1.1 mrg 5179 1.1 mrg output_asm_insn ("b\t%0", &taken); 5180 1.1 mrg 5181 1.1 mrg /* Output NOT_TAKEN. */ 5182 1.1 mrg targetm.asm_out.internal_label (asm_out_file, "L", 5183 1.1 mrg CODE_LABEL_NUMBER (not_taken)); 5184 1.1 mrg return ""; 5185 1.1 mrg } 5186 1.1 mrg 5187 1.1 mrg /* Return the assembly code for INSN, which branches to OPERANDS[0] 5188 1.1 mrg if some equality condition is true. The condition is given by 5189 1.1 mrg OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of 5190 1.1 mrg OPERANDS[1]. OPERANDS[2] is the comparison's first operand; 5191 1.1 mrg OPERANDS[3] is the second operand and may be zero or a register. */ 5192 1.1 mrg 5193 1.1 mrg const char * 5194 1.1 mrg loongarch_output_equal_conditional_branch (rtx_insn *insn, rtx *operands, 5195 1.1 mrg bool inverted_p) 5196 1.1 mrg { 5197 1.1 mrg const char *branch[2]; 5198 1.1 mrg if (operands[3] == const0_rtx) 5199 1.1 mrg { 5200 1.1 mrg branch[!inverted_p] = LARCH_BRANCH ("b%C1z", "%2,%0"); 5201 1.1 mrg branch[inverted_p] = LARCH_BRANCH ("b%N1z", "%2,%0"); 5202 1.1 mrg } 5203 1.1 mrg else 5204 1.1 mrg { 5205 1.1 mrg branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%z3,%0"); 5206 1.1 mrg branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%z3,%0"); 5207 1.1 mrg } 5208 1.1 mrg 5209 1.1 mrg return loongarch_output_conditional_branch (insn, operands, branch[1], 5210 1.1 mrg branch[0]); 5211 1.1 mrg } 5212 1.1 mrg 5213 1.1 mrg /* Return the assembly code for INSN, which branches to OPERANDS[0] 5214 1.1 mrg if some ordering condition is true. The condition is given by 5215 1.1 mrg OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of 5216 1.1 mrg OPERANDS[1]. OPERANDS[2] is the comparison's first operand; 5217 1.1 mrg OPERANDS[3] is the second operand and may be zero or a register. */ 5218 1.1 mrg 5219 1.1 mrg const char * 5220 1.1 mrg loongarch_output_order_conditional_branch (rtx_insn *insn, rtx *operands, 5221 1.1 mrg bool inverted_p) 5222 1.1 mrg { 5223 1.1 mrg const char *branch[2]; 5224 1.1 mrg 5225 1.1 mrg /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true. 5226 1.1 mrg Make BRANCH[0] branch on the inverse condition. */ 5227 1.1 mrg if (operands[3] != const0_rtx) 5228 1.1 mrg { 5229 1.1 mrg /* Handle degenerate cases that should not, but do, occur. */ 5230 1.1 mrg if (REGNO (operands[2]) == REGNO (operands[3])) 5231 1.1 mrg { 5232 1.1 mrg switch (GET_CODE (operands[1])) 5233 1.1 mrg { 5234 1.1 mrg case LT: 5235 1.1 mrg case LTU: 5236 1.1 mrg case GT: 5237 1.1 mrg case GTU: 5238 1.1 mrg inverted_p = !inverted_p; 5239 1.1 mrg /* Fall through. */ 5240 1.1 mrg case LE: 5241 1.1 mrg case LEU: 5242 1.1 mrg case GE: 5243 1.1 mrg case GEU: 5244 1.1 mrg branch[!inverted_p] = LARCH_BRANCH ("b", "%0"); 5245 1.1 mrg branch[inverted_p] = "\t# branch never"; 5246 1.1 mrg break; 5247 1.1 mrg default: 5248 1.1 mrg gcc_unreachable (); 5249 1.1 mrg } 5250 1.1 mrg } 5251 1.1 mrg else 5252 1.1 mrg { 5253 1.1 mrg switch (GET_CODE (operands[1])) 5254 1.1 mrg { 5255 1.1 mrg case LE: 5256 1.1 mrg case LEU: 5257 1.1 mrg case GT: 5258 1.1 mrg case GTU: 5259 1.1 mrg case LT: 5260 1.1 mrg case LTU: 5261 1.1 mrg case GE: 5262 1.1 mrg case GEU: 5263 1.1 mrg branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%3,%0"); 5264 1.1 mrg branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%3,%0"); 5265 1.1 mrg break; 5266 1.1 mrg default: 5267 1.1 mrg gcc_unreachable (); 5268 1.1 mrg } 5269 1.1 mrg } 5270 1.1 mrg } 5271 1.1 mrg else 5272 1.1 mrg { 5273 1.1 mrg switch (GET_CODE (operands[1])) 5274 1.1 mrg { 5275 1.1 mrg /* These cases are equivalent to comparisons against zero. */ 5276 1.1 mrg case LEU: 5277 1.1 mrg case GTU: 5278 1.1 mrg case LTU: 5279 1.1 mrg case GEU: 5280 1.1 mrg case LE: 5281 1.1 mrg case GT: 5282 1.1 mrg case LT: 5283 1.1 mrg case GE: 5284 1.1 mrg branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,$r0,%0"); 5285 1.1 mrg branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,$r0,%0"); 5286 1.1 mrg break; 5287 1.1 mrg default: 5288 1.1 mrg gcc_unreachable (); 5289 1.1 mrg } 5290 1.1 mrg } 5291 1.1 mrg return loongarch_output_conditional_branch (insn, operands, branch[1], 5292 1.1 mrg branch[0]); 5293 1.1 mrg } 5294 1.1 mrg 5295 1.1 mrg /* Return the assembly code for DIV.{W/D} instruction DIVISION, which has 5296 1.1 mrg the operands given by OPERANDS. Add in a divide-by-zero check if needed. 5297 1.1 mrg */ 5298 1.1 mrg 5299 1.1 mrg const char * 5300 1.1 mrg loongarch_output_division (const char *division, rtx *operands) 5301 1.1 mrg { 5302 1.1 mrg const char *s; 5303 1.1 mrg 5304 1.1 mrg s = division; 5305 1.1 mrg if (loongarch_check_zero_div_p ()) 5306 1.1 mrg { 5307 1.1 mrg output_asm_insn (s, operands); 5308 1.1 mrg s = "bne\t%2,%.,1f\n\tbreak\t7\n1:"; 5309 1.1 mrg } 5310 1.1 mrg return s; 5311 1.1 mrg } 5312 1.1 mrg 5313 1.1 mrg /* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output 5314 1.1 mrg dependencies have no cost. */ 5315 1.1 mrg 5316 1.1 mrg static int 5317 1.1 mrg loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost, 5318 1.1 mrg unsigned int) 5319 1.1 mrg { 5320 1.1 mrg if (dep_type != 0 && (dep_type != REG_DEP_OUTPUT)) 5321 1.1 mrg return 0; 5322 1.1 mrg return cost; 5323 1.1 mrg } 5324 1.1 mrg 5325 1.1 mrg /* Return the number of instructions that can be issued per cycle. */ 5326 1.1 mrg 5327 1.1 mrg static int 5328 1.1 mrg loongarch_issue_rate (void) 5329 1.1 mrg { 5330 1.1 mrg if ((unsigned long) LARCH_ACTUAL_TUNE < N_TUNE_TYPES) 5331 1.1 mrg return loongarch_cpu_issue_rate[LARCH_ACTUAL_TUNE]; 5332 1.1 mrg else 5333 1.1 mrg return 1; 5334 1.1 mrg } 5335 1.1 mrg 5336 1.1 mrg /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should 5337 1.1 mrg be as wide as the scheduling freedom in the DFA. */ 5338 1.1 mrg 5339 1.1 mrg static int 5340 1.1 mrg loongarch_multipass_dfa_lookahead (void) 5341 1.1 mrg { 5342 1.1 mrg if ((unsigned long) LARCH_ACTUAL_TUNE < N_ARCH_TYPES) 5343 1.1 mrg return loongarch_cpu_multipass_dfa_lookahead[LARCH_ACTUAL_TUNE]; 5344 1.1 mrg else 5345 1.1 mrg return 0; 5346 1.1 mrg } 5347 1.1 mrg 5348 1.1 mrg /* Implement TARGET_SCHED_REORDER. */ 5349 1.1 mrg 5350 1.1 mrg static int 5351 1.1 mrg loongarch_sched_reorder (FILE *file ATTRIBUTE_UNUSED, 5352 1.1 mrg int verbose ATTRIBUTE_UNUSED, 5353 1.1 mrg rtx_insn **ready ATTRIBUTE_UNUSED, 5354 1.1 mrg int *nreadyp ATTRIBUTE_UNUSED, 5355 1.1 mrg int cycle ATTRIBUTE_UNUSED) 5356 1.1 mrg { 5357 1.1 mrg return loongarch_issue_rate (); 5358 1.1 mrg } 5359 1.1 mrg 5360 1.1 mrg /* Implement TARGET_SCHED_REORDER2. */ 5361 1.1 mrg 5362 1.1 mrg static int 5363 1.1 mrg loongarch_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED, 5364 1.1 mrg int verbose ATTRIBUTE_UNUSED, 5365 1.1 mrg rtx_insn **ready ATTRIBUTE_UNUSED, 5366 1.1 mrg int *nreadyp ATTRIBUTE_UNUSED, 5367 1.1 mrg int cycle ATTRIBUTE_UNUSED) 5368 1.1 mrg { 5369 1.1 mrg return cached_can_issue_more; 5370 1.1 mrg } 5371 1.1 mrg 5372 1.1 mrg /* Implement TARGET_SCHED_INIT. */ 5373 1.1 mrg 5374 1.1 mrg static void 5375 1.1 mrg loongarch_sched_init (FILE *file ATTRIBUTE_UNUSED, 5376 1.1 mrg int verbose ATTRIBUTE_UNUSED, 5377 1.1 mrg int max_ready ATTRIBUTE_UNUSED) 5378 1.1 mrg {} 5379 1.1 mrg 5380 1.1 mrg /* Implement TARGET_SCHED_VARIABLE_ISSUE. */ 5381 1.1 mrg 5382 1.1 mrg static int 5383 1.1 mrg loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED, 5384 1.1 mrg int verbose ATTRIBUTE_UNUSED, rtx_insn *insn, 5385 1.1 mrg int more) 5386 1.1 mrg { 5387 1.1 mrg /* Ignore USEs and CLOBBERs; don't count them against the issue rate. */ 5388 1.1 mrg if (USEFUL_INSN_P (insn)) 5389 1.1 mrg { 5390 1.1 mrg if (get_attr_type (insn) != TYPE_GHOST) 5391 1.1 mrg more--; 5392 1.1 mrg } 5393 1.1 mrg 5394 1.1 mrg /* Instructions of type 'multi' should all be split before 5395 1.1 mrg the second scheduling pass. */ 5396 1.1 mrg gcc_assert (!reload_completed 5397 1.1 mrg || recog_memoized (insn) < 0 5398 1.1 mrg || get_attr_type (insn) != TYPE_MULTI); 5399 1.1 mrg 5400 1.1 mrg cached_can_issue_more = more; 5401 1.1 mrg return more; 5402 1.1 mrg } 5403 1.1 mrg 5404 1.1 mrg /* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY), 5405 1.1 mrg return the first operand of the associated PREF or PREFX insn. */ 5406 1.1 mrg 5407 1.1 mrg rtx 5408 1.1 mrg loongarch_prefetch_cookie (rtx write, rtx locality) 5409 1.1 mrg { 5410 1.1 mrg /* store_streamed / load_streamed. */ 5411 1.1 mrg if (INTVAL (locality) <= 0) 5412 1.1 mrg return GEN_INT (INTVAL (write) + 4); 5413 1.1 mrg 5414 1.1 mrg /* store / load. */ 5415 1.1 mrg if (INTVAL (locality) <= 2) 5416 1.1 mrg return write; 5417 1.1 mrg 5418 1.1 mrg /* store_retained / load_retained. */ 5419 1.1 mrg return GEN_INT (INTVAL (write) + 6); 5420 1.1 mrg } 5421 1.1 mrg 5422 1.1 mrg /* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text 5423 1.1 mrg in order to avoid duplicating too much logic from elsewhere. */ 5424 1.1 mrg 5425 1.1 mrg static void 5426 1.1 mrg loongarch_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, 5427 1.1 mrg HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, 5428 1.1 mrg tree function) 5429 1.1 mrg { 5430 1.1 mrg const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); 5431 1.1 mrg rtx this_rtx, temp1, temp2, fnaddr; 5432 1.1 mrg rtx_insn *insn; 5433 1.1 mrg bool use_sibcall_p; 5434 1.1 mrg 5435 1.1 mrg /* Pretend to be a post-reload pass while generating rtl. */ 5436 1.1 mrg reload_completed = 1; 5437 1.1 mrg 5438 1.1 mrg /* Mark the end of the (empty) prologue. */ 5439 1.1 mrg emit_note (NOTE_INSN_PROLOGUE_END); 5440 1.1 mrg 5441 1.1 mrg /* Determine if we can use a sibcall to call FUNCTION directly. */ 5442 1.1 mrg fnaddr = XEXP (DECL_RTL (function), 0); 5443 1.1 mrg use_sibcall_p = const_call_insn_operand (fnaddr, Pmode); 5444 1.1 mrg 5445 1.1 mrg /* We need two temporary registers in some cases. */ 5446 1.1 mrg temp1 = gen_rtx_REG (Pmode, 12); 5447 1.1 mrg temp2 = gen_rtx_REG (Pmode, 13); 5448 1.1 mrg 5449 1.1 mrg /* Find out which register contains the "this" pointer. */ 5450 1.1 mrg if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) 5451 1.1 mrg this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1); 5452 1.1 mrg else 5453 1.1 mrg this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST); 5454 1.1 mrg 5455 1.1 mrg /* Add DELTA to THIS_RTX. */ 5456 1.1 mrg if (delta != 0) 5457 1.1 mrg { 5458 1.1 mrg rtx offset = GEN_INT (delta); 5459 1.1 mrg if (!IMM12_OPERAND (delta)) 5460 1.1 mrg { 5461 1.1 mrg loongarch_emit_move (temp1, offset); 5462 1.1 mrg offset = temp1; 5463 1.1 mrg } 5464 1.1 mrg emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); 5465 1.1 mrg } 5466 1.1 mrg 5467 1.1 mrg /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ 5468 1.1 mrg if (vcall_offset != 0) 5469 1.1 mrg { 5470 1.1 mrg rtx addr; 5471 1.1 mrg 5472 1.1 mrg /* Set TEMP1 to *THIS_RTX. */ 5473 1.1 mrg loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx)); 5474 1.1 mrg 5475 1.1 mrg /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */ 5476 1.1 mrg addr = loongarch_add_offset (temp2, temp1, vcall_offset); 5477 1.1 mrg 5478 1.1 mrg /* Load the offset and add it to THIS_RTX. */ 5479 1.1 mrg loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, addr)); 5480 1.1 mrg emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1)); 5481 1.1 mrg } 5482 1.1 mrg 5483 1.1 mrg /* Jump to the target function. Use a sibcall if direct jumps are 5484 1.1 mrg allowed, otherwise load the address into a register first. */ 5485 1.1 mrg if (use_sibcall_p) 5486 1.1 mrg { 5487 1.1 mrg insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx)); 5488 1.1 mrg SIBLING_CALL_P (insn) = 1; 5489 1.1 mrg } 5490 1.1 mrg else 5491 1.1 mrg { 5492 1.1 mrg loongarch_emit_move (temp1, fnaddr); 5493 1.1 mrg emit_jump_insn (gen_indirect_jump (temp1)); 5494 1.1 mrg } 5495 1.1 mrg 5496 1.1 mrg /* Run just enough of rest_of_compilation. This sequence was 5497 1.1 mrg "borrowed" from alpha.c. */ 5498 1.1 mrg insn = get_insns (); 5499 1.1 mrg split_all_insns_noflow (); 5500 1.1 mrg shorten_branches (insn); 5501 1.1 mrg assemble_start_function (thunk_fndecl, fnname); 5502 1.1 mrg final_start_function (insn, file, 1); 5503 1.1 mrg final (insn, file, 1); 5504 1.1 mrg final_end_function (); 5505 1.1 mrg assemble_end_function (thunk_fndecl, fnname); 5506 1.1 mrg 5507 1.1 mrg /* Stop pretending to be a post-reload pass. */ 5508 1.1 mrg reload_completed = 0; 5509 1.1 mrg } 5510 1.1 mrg 5511 1.1 mrg /* Allocate a chunk of memory for per-function machine-dependent data. */ 5512 1.1 mrg 5513 1.1 mrg static struct machine_function * 5514 1.1 mrg loongarch_init_machine_status (void) 5515 1.1 mrg { 5516 1.1 mrg return ggc_cleared_alloc<machine_function> (); 5517 1.1 mrg } 5518 1.1 mrg 5519 1.1 mrg static void 5520 1.1 mrg loongarch_option_override_internal (struct gcc_options *opts, 5521 1.1 mrg struct gcc_options *opts_set) 5522 1.1 mrg { 5523 1.1 mrg int i, regno, mode; 5524 1.1 mrg 5525 1.1 mrg if (flag_pic) 5526 1.1 mrg g_switch_value = 0; 5527 1.1 mrg 5528 1.1 mrg /* Handle target-specific options: compute defaults/conflicts etc. */ 5529 1.1 mrg loongarch_config_target (&la_target, la_opt_switches, 5530 1.1 mrg la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu, 5531 1.1 mrg la_opt_abi_base, la_opt_abi_ext, la_opt_cmodel, 0); 5532 1.1 mrg 5533 1.1 mrg loongarch_update_gcc_opt_status (&la_target, opts, opts_set); 5534 1.1 mrg 5535 1.1 mrg if (TARGET_ABI_LP64) 5536 1.1 mrg flag_pcc_struct_return = 0; 5537 1.1 mrg 5538 1.1 mrg /* Decide which rtx_costs structure to use. */ 5539 1.1 mrg if (optimize_size) 5540 1.1 mrg loongarch_cost = &loongarch_rtx_cost_optimize_size; 5541 1.1 mrg else 5542 1.1 mrg loongarch_cost = &loongarch_cpu_rtx_cost_data[LARCH_ACTUAL_TUNE]; 5543 1.1 mrg 5544 1.1 mrg /* If the user hasn't specified a branch cost, use the processor's 5545 1.1 mrg default. */ 5546 1.1 mrg if (loongarch_branch_cost == 0) 5547 1.1 mrg loongarch_branch_cost = loongarch_cost->branch_cost; 5548 1.1 mrg 5549 1.1 mrg 5550 1.1 mrg switch (la_target.cmodel) 5551 1.1 mrg { 5552 1.1 mrg case CMODEL_TINY_STATIC: 5553 1.1 mrg case CMODEL_EXTREME: 5554 1.1 mrg if (opts->x_flag_plt) 5555 1.1 mrg error ("code model %qs and %qs not support %s mode", 5556 1.1 mrg "tiny-static", "extreme", "plt"); 5557 1.1 mrg break; 5558 1.1 mrg 5559 1.1 mrg case CMODEL_NORMAL: 5560 1.1 mrg case CMODEL_TINY: 5561 1.1 mrg case CMODEL_LARGE: 5562 1.1 mrg break; 5563 1.1 mrg 5564 1.1 mrg default: 5565 1.1 mrg gcc_unreachable (); 5566 1.1 mrg } 5567 1.1 mrg 5568 1.1 mrg loongarch_init_print_operand_punct (); 5569 1.1 mrg 5570 1.1 mrg /* Set up array to map GCC register number to debug register number. 5571 1.1 mrg Ignore the special purpose register numbers. */ 5572 1.1 mrg 5573 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 5574 1.1 mrg { 5575 1.1 mrg if (GP_REG_P (i) || FP_REG_P (i)) 5576 1.1 mrg loongarch_dwarf_regno[i] = i; 5577 1.1 mrg else 5578 1.1 mrg loongarch_dwarf_regno[i] = INVALID_REGNUM; 5579 1.1 mrg } 5580 1.1 mrg 5581 1.1 mrg /* Set up loongarch_hard_regno_mode_ok. */ 5582 1.1 mrg for (mode = 0; mode < MAX_MACHINE_MODE; mode++) 5583 1.1 mrg for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 5584 1.1 mrg loongarch_hard_regno_mode_ok_p[mode][regno] 5585 1.1 mrg = loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode); 5586 1.1 mrg 5587 1.1 mrg /* Function to allocate machine-dependent function status. */ 5588 1.1 mrg init_machine_status = &loongarch_init_machine_status; 5589 1.1 mrg } 5590 1.1 mrg 5591 1.1 mrg 5592 1.1 mrg /* Implement TARGET_OPTION_OVERRIDE. */ 5593 1.1 mrg 5594 1.1 mrg static void 5595 1.1 mrg loongarch_option_override (void) 5596 1.1 mrg { 5597 1.1 mrg loongarch_option_override_internal (&global_options, &global_options_set); 5598 1.1 mrg } 5599 1.1 mrg 5600 1.1 mrg /* Implement TARGET_OPTION_SAVE. */ 5601 1.1 mrg static void 5602 1.1 mrg loongarch_option_save (struct cl_target_option *, 5603 1.1 mrg struct gcc_options *opts, 5604 1.1 mrg struct gcc_options *opts_set) 5605 1.1 mrg { 5606 1.1 mrg loongarch_update_gcc_opt_status (&la_target, opts, opts_set); 5607 1.1 mrg } 5608 1.1 mrg 5609 1.1 mrg /* Implement TARGET_OPTION_RESTORE. */ 5610 1.1 mrg static void 5611 1.1 mrg loongarch_option_restore (struct gcc_options *, 5612 1.1 mrg struct gcc_options *, 5613 1.1 mrg struct cl_target_option *ptr) 5614 1.1 mrg { 5615 1.1 mrg la_target.cpu_arch = ptr->x_la_opt_cpu_arch; 5616 1.1 mrg la_target.cpu_tune = ptr->x_la_opt_cpu_tune; 5617 1.1 mrg 5618 1.1 mrg la_target.isa.fpu = ptr->x_la_opt_fpu; 5619 1.1 mrg 5620 1.1 mrg la_target.cmodel = ptr->x_la_opt_cmodel; 5621 1.1 mrg } 5622 1.1 mrg 5623 1.1 mrg /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ 5624 1.1 mrg 5625 1.1 mrg static void 5626 1.1 mrg loongarch_conditional_register_usage (void) 5627 1.1 mrg { 5628 1.1 mrg if (!TARGET_HARD_FLOAT) 5629 1.1 mrg accessible_reg_set &= ~(reg_class_contents[FP_REGS] 5630 1.1 mrg | reg_class_contents[FCC_REGS]); 5631 1.1 mrg } 5632 1.1 mrg 5633 1.1 mrg /* Implement EH_USES. */ 5634 1.1 mrg 5635 1.1 mrg bool 5636 1.1 mrg loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED) 5637 1.1 mrg { 5638 1.1 mrg return false; 5639 1.1 mrg } 5640 1.1 mrg 5641 1.1 mrg /* Implement EPILOGUE_USES. */ 5642 1.1 mrg 5643 1.1 mrg bool 5644 1.1 mrg loongarch_epilogue_uses (unsigned int regno) 5645 1.1 mrg { 5646 1.1 mrg /* Say that the epilogue uses the return address register. Note that 5647 1.1 mrg in the case of sibcalls, the values "used by the epilogue" are 5648 1.1 mrg considered live at the start of the called function. */ 5649 1.1 mrg if (regno == RETURN_ADDR_REGNUM) 5650 1.1 mrg return true; 5651 1.1 mrg 5652 1.1 mrg return false; 5653 1.1 mrg } 5654 1.1 mrg 5655 1.1 mrg bool 5656 1.1 mrg loongarch_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p) 5657 1.1 mrg { 5658 1.1 mrg rtx reg1, reg2, mem1, mem2, base1, base2; 5659 1.1 mrg enum reg_class rc1, rc2; 5660 1.1 mrg HOST_WIDE_INT offset1, offset2; 5661 1.1 mrg 5662 1.1 mrg if (load_p) 5663 1.1 mrg { 5664 1.1 mrg reg1 = operands[0]; 5665 1.1 mrg reg2 = operands[2]; 5666 1.1 mrg mem1 = operands[1]; 5667 1.1 mrg mem2 = operands[3]; 5668 1.1 mrg } 5669 1.1 mrg else 5670 1.1 mrg { 5671 1.1 mrg reg1 = operands[1]; 5672 1.1 mrg reg2 = operands[3]; 5673 1.1 mrg mem1 = operands[0]; 5674 1.1 mrg mem2 = operands[2]; 5675 1.1 mrg } 5676 1.1 mrg 5677 1.1 mrg if (loongarch_address_insns (XEXP (mem1, 0), mode, false) == 0 5678 1.1 mrg || loongarch_address_insns (XEXP (mem2, 0), mode, false) == 0) 5679 1.1 mrg return false; 5680 1.1 mrg 5681 1.1 mrg loongarch_split_plus (XEXP (mem1, 0), &base1, &offset1); 5682 1.1 mrg loongarch_split_plus (XEXP (mem2, 0), &base2, &offset2); 5683 1.1 mrg 5684 1.1 mrg /* Base regs do not match. */ 5685 1.1 mrg if (!REG_P (base1) || !rtx_equal_p (base1, base2)) 5686 1.1 mrg return false; 5687 1.1 mrg 5688 1.1 mrg /* Either of the loads is clobbering base register. It is legitimate to bond 5689 1.1 mrg loads if second load clobbers base register. However, hardware does not 5690 1.1 mrg support such bonding. */ 5691 1.1 mrg if (load_p 5692 1.1 mrg && (REGNO (reg1) == REGNO (base1) || (REGNO (reg2) == REGNO (base1)))) 5693 1.1 mrg return false; 5694 1.1 mrg 5695 1.1 mrg /* Loading in same registers. */ 5696 1.1 mrg if (load_p && REGNO (reg1) == REGNO (reg2)) 5697 1.1 mrg return false; 5698 1.1 mrg 5699 1.1 mrg /* The loads/stores are not of same type. */ 5700 1.1 mrg rc1 = REGNO_REG_CLASS (REGNO (reg1)); 5701 1.1 mrg rc2 = REGNO_REG_CLASS (REGNO (reg2)); 5702 1.1 mrg if (rc1 != rc2 && !reg_class_subset_p (rc1, rc2) 5703 1.1 mrg && !reg_class_subset_p (rc2, rc1)) 5704 1.1 mrg return false; 5705 1.1 mrg 5706 1.1 mrg if (abs (offset1 - offset2) != GET_MODE_SIZE (mode)) 5707 1.1 mrg return false; 5708 1.1 mrg 5709 1.1 mrg return true; 5710 1.1 mrg } 5711 1.1 mrg 5712 1.1 mrg /* Implement TARGET_TRAMPOLINE_INIT. */ 5713 1.1 mrg 5714 1.1 mrg static void 5715 1.1 mrg loongarch_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) 5716 1.1 mrg { 5717 1.1 mrg rtx addr, end_addr, mem; 5718 1.1 mrg rtx trampoline[8]; 5719 1.1 mrg unsigned int i, j; 5720 1.1 mrg HOST_WIDE_INT end_addr_offset, static_chain_offset, target_function_offset; 5721 1.1 mrg 5722 1.1 mrg /* Work out the offsets of the pointers from the start of the 5723 1.1 mrg trampoline code. */ 5724 1.1 mrg end_addr_offset = TRAMPOLINE_CODE_SIZE; 5725 1.1 mrg static_chain_offset = end_addr_offset; 5726 1.1 mrg target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode); 5727 1.1 mrg 5728 1.1 mrg /* Get pointers to the beginning and end of the code block. */ 5729 1.1 mrg addr = force_reg (Pmode, XEXP (m_tramp, 0)); 5730 1.1 mrg end_addr 5731 1.1 mrg = loongarch_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset)); 5732 1.1 mrg 5733 1.1 mrg #define OP(X) gen_int_mode (X, SImode) 5734 1.1 mrg 5735 1.1 mrg /* Build up the code in TRAMPOLINE. */ 5736 1.1 mrg i = 0; 5737 1.1 mrg /*pcaddi $static_chain,0 5738 1.1 mrg ld.[dw] $tmp,$static_chain,target_function_offset 5739 1.1 mrg ld.[dw] $static_chain,$static_chain,static_chain_offset 5740 1.1 mrg jirl $r0,$tmp,0 */ 5741 1.1 mrg trampoline[i++] = OP (0x18000000 | (STATIC_CHAIN_REGNUM - GP_REG_FIRST)); 5742 1.1 mrg trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000) 5743 1.1 mrg | 19 /* $t7 */ 5744 1.1 mrg | ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5) 5745 1.1 mrg | ((target_function_offset & 0xfff) << 10)); 5746 1.1 mrg trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000) 5747 1.1 mrg | (STATIC_CHAIN_REGNUM - GP_REG_FIRST) 5748 1.1 mrg | ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5) 5749 1.1 mrg | ((static_chain_offset & 0xfff) << 10)); 5750 1.1 mrg trampoline[i++] = OP (0x4c000000 | (19 << 5)); 5751 1.1 mrg #undef OP 5752 1.1 mrg 5753 1.1 mrg for (j = 0; j < i; j++) 5754 1.1 mrg { 5755 1.1 mrg mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode)); 5756 1.1 mrg loongarch_emit_move (mem, trampoline[j]); 5757 1.1 mrg } 5758 1.1 mrg 5759 1.1 mrg /* Set up the static chain pointer field. */ 5760 1.1 mrg mem = adjust_address (m_tramp, ptr_mode, static_chain_offset); 5761 1.1 mrg loongarch_emit_move (mem, chain_value); 5762 1.1 mrg 5763 1.1 mrg /* Set up the target function field. */ 5764 1.1 mrg mem = adjust_address (m_tramp, ptr_mode, target_function_offset); 5765 1.1 mrg loongarch_emit_move (mem, XEXP (DECL_RTL (fndecl), 0)); 5766 1.1 mrg 5767 1.1 mrg /* Flush the code part of the trampoline. */ 5768 1.1 mrg emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE))); 5769 1.1 mrg emit_insn (gen_clear_cache (addr, end_addr)); 5770 1.1 mrg } 5771 1.1 mrg 5772 1.1 mrg /* Implement HARD_REGNO_CALLER_SAVE_MODE. */ 5773 1.1 mrg 5774 1.1 mrg machine_mode 5775 1.1 mrg loongarch_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs, 5776 1.1 mrg machine_mode mode) 5777 1.1 mrg { 5778 1.1 mrg /* For performance, avoid saving/restoring upper parts of a register 5779 1.1 mrg by returning MODE as save mode when the mode is known. */ 5780 1.1 mrg if (mode == VOIDmode) 5781 1.1 mrg return choose_hard_reg_mode (regno, nregs, NULL); 5782 1.1 mrg else 5783 1.1 mrg return mode; 5784 1.1 mrg } 5785 1.1 mrg 5786 1.1 mrg /* Implement TARGET_SPILL_CLASS. */ 5787 1.1 mrg 5788 1.1 mrg static reg_class_t 5789 1.1 mrg loongarch_spill_class (reg_class_t rclass ATTRIBUTE_UNUSED, 5790 1.1 mrg machine_mode mode ATTRIBUTE_UNUSED) 5791 1.1 mrg { 5792 1.1 mrg return NO_REGS; 5793 1.1 mrg } 5794 1.1 mrg 5795 1.1 mrg /* Implement TARGET_PROMOTE_FUNCTION_MODE. */ 5796 1.1 mrg 5797 1.1 mrg /* This function is equivalent to default_promote_function_mode_always_promote 5798 1.1 mrg except that it returns a promoted mode even if type is NULL_TREE. This is 5799 1.1 mrg needed by libcalls which have no type (only a mode) such as fixed conversion 5800 1.1 mrg routines that take a signed or unsigned char/short argument and convert it 5801 1.1 mrg to a fixed type. */ 5802 1.1 mrg 5803 1.1 mrg static machine_mode 5804 1.1 mrg loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, 5805 1.1 mrg machine_mode mode, 5806 1.1 mrg int *punsignedp ATTRIBUTE_UNUSED, 5807 1.1 mrg const_tree fntype ATTRIBUTE_UNUSED, 5808 1.1 mrg int for_return ATTRIBUTE_UNUSED) 5809 1.1 mrg { 5810 1.1 mrg int unsignedp; 5811 1.1 mrg 5812 1.1 mrg if (type != NULL_TREE) 5813 1.1 mrg return promote_mode (type, mode, punsignedp); 5814 1.1 mrg 5815 1.1 mrg unsignedp = *punsignedp; 5816 1.1 mrg PROMOTE_MODE (mode, unsignedp, type); 5817 1.1 mrg *punsignedp = unsignedp; 5818 1.1 mrg return mode; 5819 1.1 mrg } 5820 1.1 mrg 5821 1.1 mrg /* Implement TARGET_STARTING_FRAME_OFFSET. See loongarch_compute_frame_info 5822 1.1 mrg for details about the frame layout. */ 5823 1.1 mrg 5824 1.1 mrg static HOST_WIDE_INT 5825 1.1 mrg loongarch_starting_frame_offset (void) 5826 1.1 mrg { 5827 1.1 mrg if (FRAME_GROWS_DOWNWARD) 5828 1.1 mrg return 0; 5829 1.1 mrg return crtl->outgoing_args_size; 5830 1.1 mrg } 5831 1.1 mrg 5832 1.1 mrg /* Initialize the GCC target structure. */ 5833 1.1 mrg #undef TARGET_ASM_ALIGNED_HI_OP 5834 1.1 mrg #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" 5835 1.1 mrg #undef TARGET_ASM_ALIGNED_SI_OP 5836 1.1 mrg #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 5837 1.1 mrg #undef TARGET_ASM_ALIGNED_DI_OP 5838 1.1 mrg #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" 5839 1.1 mrg 5840 1.1 mrg #undef TARGET_OPTION_OVERRIDE 5841 1.1 mrg #define TARGET_OPTION_OVERRIDE loongarch_option_override 5842 1.1 mrg #define TARGET_OPTION_SAVE loongarch_option_save 5843 1.1 mrg #undef TARGET_OPTION_RESTORE 5844 1.1 mrg #define TARGET_OPTION_RESTORE loongarch_option_restore 5845 1.1 mrg 5846 1.1 mrg 5847 1.1 mrg #undef TARGET_LEGITIMIZE_ADDRESS 5848 1.1 mrg #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address 5849 1.1 mrg 5850 1.1 mrg #undef TARGET_ASM_SELECT_RTX_SECTION 5851 1.1 mrg #define TARGET_ASM_SELECT_RTX_SECTION loongarch_select_rtx_section 5852 1.1 mrg #undef TARGET_ASM_FUNCTION_RODATA_SECTION 5853 1.1 mrg #define TARGET_ASM_FUNCTION_RODATA_SECTION loongarch_function_rodata_section 5854 1.1 mrg 5855 1.1 mrg #undef TARGET_SCHED_INIT 5856 1.1 mrg #define TARGET_SCHED_INIT loongarch_sched_init 5857 1.1 mrg #undef TARGET_SCHED_REORDER 5858 1.1 mrg #define TARGET_SCHED_REORDER loongarch_sched_reorder 5859 1.1 mrg #undef TARGET_SCHED_REORDER2 5860 1.1 mrg #define TARGET_SCHED_REORDER2 loongarch_sched_reorder2 5861 1.1 mrg #undef TARGET_SCHED_VARIABLE_ISSUE 5862 1.1 mrg #define TARGET_SCHED_VARIABLE_ISSUE loongarch_variable_issue 5863 1.1 mrg #undef TARGET_SCHED_ADJUST_COST 5864 1.1 mrg #define TARGET_SCHED_ADJUST_COST loongarch_adjust_cost 5865 1.1 mrg #undef TARGET_SCHED_ISSUE_RATE 5866 1.1 mrg #define TARGET_SCHED_ISSUE_RATE loongarch_issue_rate 5867 1.1 mrg #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD 5868 1.1 mrg #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ 5869 1.1 mrg loongarch_multipass_dfa_lookahead 5870 1.1 mrg 5871 1.1 mrg #undef TARGET_FUNCTION_OK_FOR_SIBCALL 5872 1.1 mrg #define TARGET_FUNCTION_OK_FOR_SIBCALL loongarch_function_ok_for_sibcall 5873 1.1 mrg 5874 1.1 mrg #undef TARGET_VALID_POINTER_MODE 5875 1.1 mrg #define TARGET_VALID_POINTER_MODE loongarch_valid_pointer_mode 5876 1.1 mrg #undef TARGET_REGISTER_MOVE_COST 5877 1.1 mrg #define TARGET_REGISTER_MOVE_COST loongarch_register_move_cost 5878 1.1 mrg #undef TARGET_MEMORY_MOVE_COST 5879 1.1 mrg #define TARGET_MEMORY_MOVE_COST loongarch_memory_move_cost 5880 1.1 mrg #undef TARGET_RTX_COSTS 5881 1.1 mrg #define TARGET_RTX_COSTS loongarch_rtx_costs 5882 1.1 mrg #undef TARGET_ADDRESS_COST 5883 1.1 mrg #define TARGET_ADDRESS_COST loongarch_address_cost 5884 1.1 mrg 5885 1.1 mrg #undef TARGET_IN_SMALL_DATA_P 5886 1.1 mrg #define TARGET_IN_SMALL_DATA_P loongarch_in_small_data_p 5887 1.1 mrg 5888 1.1 mrg #undef TARGET_PREFERRED_RELOAD_CLASS 5889 1.1 mrg #define TARGET_PREFERRED_RELOAD_CLASS loongarch_preferred_reload_class 5890 1.1 mrg 5891 1.1 mrg #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE 5892 1.1 mrg #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true 5893 1.1 mrg 5894 1.1 mrg #undef TARGET_EXPAND_BUILTIN_VA_START 5895 1.1 mrg #define TARGET_EXPAND_BUILTIN_VA_START loongarch_va_start 5896 1.1 mrg 5897 1.1 mrg #undef TARGET_PROMOTE_FUNCTION_MODE 5898 1.1 mrg #define TARGET_PROMOTE_FUNCTION_MODE loongarch_promote_function_mode 5899 1.1 mrg #undef TARGET_RETURN_IN_MEMORY 5900 1.1 mrg #define TARGET_RETURN_IN_MEMORY loongarch_return_in_memory 5901 1.1 mrg 5902 1.1 mrg #undef TARGET_FUNCTION_VALUE 5903 1.1 mrg #define TARGET_FUNCTION_VALUE loongarch_function_value 5904 1.1 mrg #undef TARGET_LIBCALL_VALUE 5905 1.1 mrg #define TARGET_LIBCALL_VALUE loongarch_libcall_value 5906 1.1 mrg 5907 1.1 mrg #undef TARGET_ASM_OUTPUT_MI_THUNK 5908 1.1 mrg #define TARGET_ASM_OUTPUT_MI_THUNK loongarch_output_mi_thunk 5909 1.1 mrg #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 5910 1.1 mrg #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ 5911 1.1 mrg hook_bool_const_tree_hwi_hwi_const_tree_true 5912 1.1 mrg 5913 1.1 mrg #undef TARGET_PRINT_OPERAND 5914 1.1 mrg #define TARGET_PRINT_OPERAND loongarch_print_operand 5915 1.1 mrg #undef TARGET_PRINT_OPERAND_ADDRESS 5916 1.1 mrg #define TARGET_PRINT_OPERAND_ADDRESS loongarch_print_operand_address 5917 1.1 mrg #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P 5918 1.1 mrg #define TARGET_PRINT_OPERAND_PUNCT_VALID_P \ 5919 1.1 mrg loongarch_print_operand_punct_valid_p 5920 1.1 mrg 5921 1.1 mrg #undef TARGET_SETUP_INCOMING_VARARGS 5922 1.1 mrg #define TARGET_SETUP_INCOMING_VARARGS loongarch_setup_incoming_varargs 5923 1.1 mrg #undef TARGET_STRICT_ARGUMENT_NAMING 5924 1.1 mrg #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true 5925 1.1 mrg #undef TARGET_MUST_PASS_IN_STACK 5926 1.1 mrg #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size 5927 1.1 mrg #undef TARGET_PASS_BY_REFERENCE 5928 1.1 mrg #define TARGET_PASS_BY_REFERENCE loongarch_pass_by_reference 5929 1.1 mrg #undef TARGET_ARG_PARTIAL_BYTES 5930 1.1 mrg #define TARGET_ARG_PARTIAL_BYTES loongarch_arg_partial_bytes 5931 1.1 mrg #undef TARGET_FUNCTION_ARG 5932 1.1 mrg #define TARGET_FUNCTION_ARG loongarch_function_arg 5933 1.1 mrg #undef TARGET_FUNCTION_ARG_ADVANCE 5934 1.1 mrg #define TARGET_FUNCTION_ARG_ADVANCE loongarch_function_arg_advance 5935 1.1 mrg #undef TARGET_FUNCTION_ARG_BOUNDARY 5936 1.1 mrg #define TARGET_FUNCTION_ARG_BOUNDARY loongarch_function_arg_boundary 5937 1.1 mrg 5938 1.1 mrg #undef TARGET_SCALAR_MODE_SUPPORTED_P 5939 1.1 mrg #define TARGET_SCALAR_MODE_SUPPORTED_P loongarch_scalar_mode_supported_p 5940 1.1 mrg 5941 1.1 mrg #undef TARGET_INIT_BUILTINS 5942 1.1 mrg #define TARGET_INIT_BUILTINS loongarch_init_builtins 5943 1.1 mrg #undef TARGET_BUILTIN_DECL 5944 1.1 mrg #define TARGET_BUILTIN_DECL loongarch_builtin_decl 5945 1.1 mrg #undef TARGET_EXPAND_BUILTIN 5946 1.1 mrg #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin 5947 1.1 mrg 5948 1.1 mrg /* The generic ELF target does not always have TLS support. */ 5949 1.1 mrg #ifdef HAVE_AS_TLS 5950 1.1 mrg #undef TARGET_HAVE_TLS 5951 1.1 mrg #define TARGET_HAVE_TLS HAVE_AS_TLS 5952 1.1 mrg #endif 5953 1.1 mrg 5954 1.1 mrg #undef TARGET_CANNOT_FORCE_CONST_MEM 5955 1.1 mrg #define TARGET_CANNOT_FORCE_CONST_MEM loongarch_cannot_force_const_mem 5956 1.1 mrg 5957 1.1 mrg #undef TARGET_LEGITIMATE_CONSTANT_P 5958 1.1 mrg #define TARGET_LEGITIMATE_CONSTANT_P loongarch_legitimate_constant_p 5959 1.1 mrg 5960 1.1 mrg #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P 5961 1.1 mrg #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true 5962 1.1 mrg 5963 1.1 mrg #ifdef HAVE_AS_DTPRELWORD 5964 1.1 mrg #undef TARGET_ASM_OUTPUT_DWARF_DTPREL 5965 1.1 mrg #define TARGET_ASM_OUTPUT_DWARF_DTPREL loongarch_output_dwarf_dtprel 5966 1.1 mrg #endif 5967 1.1 mrg 5968 1.1 mrg #undef TARGET_LEGITIMATE_ADDRESS_P 5969 1.1 mrg #define TARGET_LEGITIMATE_ADDRESS_P loongarch_legitimate_address_p 5970 1.1 mrg 5971 1.1 mrg #undef TARGET_FRAME_POINTER_REQUIRED 5972 1.1 mrg #define TARGET_FRAME_POINTER_REQUIRED loongarch_frame_pointer_required 5973 1.1 mrg 5974 1.1 mrg #undef TARGET_CAN_ELIMINATE 5975 1.1 mrg #define TARGET_CAN_ELIMINATE loongarch_can_eliminate 5976 1.1 mrg 5977 1.1 mrg #undef TARGET_CONDITIONAL_REGISTER_USAGE 5978 1.1 mrg #define TARGET_CONDITIONAL_REGISTER_USAGE loongarch_conditional_register_usage 5979 1.1 mrg 5980 1.1 mrg #undef TARGET_TRAMPOLINE_INIT 5981 1.1 mrg #define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init 5982 1.1 mrg 5983 1.1 mrg #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV 5984 1.1 mrg #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv 5985 1.1 mrg 5986 1.1 mrg #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS 5987 1.1 mrg #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true 5988 1.1 mrg 5989 1.1 mrg #undef TARGET_SPILL_CLASS 5990 1.1 mrg #define TARGET_SPILL_CLASS loongarch_spill_class 5991 1.1 mrg 5992 1.1 mrg #undef TARGET_HARD_REGNO_NREGS 5993 1.1 mrg #define TARGET_HARD_REGNO_NREGS loongarch_hard_regno_nregs 5994 1.1 mrg #undef TARGET_HARD_REGNO_MODE_OK 5995 1.1 mrg #define TARGET_HARD_REGNO_MODE_OK loongarch_hard_regno_mode_ok 5996 1.1 mrg 5997 1.1 mrg #undef TARGET_MODES_TIEABLE_P 5998 1.1 mrg #define TARGET_MODES_TIEABLE_P loongarch_modes_tieable_p 5999 1.1 mrg 6000 1.1 mrg #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS 6001 1.1 mrg #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2 6002 1.1 mrg 6003 1.1 mrg #undef TARGET_CAN_CHANGE_MODE_CLASS 6004 1.1 mrg #define TARGET_CAN_CHANGE_MODE_CLASS loongarch_can_change_mode_class 6005 1.1 mrg 6006 1.1 mrg #undef TARGET_CONSTANT_ALIGNMENT 6007 1.1 mrg #define TARGET_CONSTANT_ALIGNMENT loongarch_constant_alignment 6008 1.1 mrg 6009 1.1 mrg #undef TARGET_STARTING_FRAME_OFFSET 6010 1.1 mrg #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset 6011 1.1 mrg 6012 1.1 mrg #undef TARGET_SECONDARY_RELOAD 6013 1.1 mrg #define TARGET_SECONDARY_RELOAD loongarch_secondary_reload 6014 1.1 mrg 6015 1.1 mrg #undef TARGET_HAVE_SPECULATION_SAFE_VALUE 6016 1.1 mrg #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed 6017 1.1 mrg 6018 1.1 mrg struct gcc_target targetm = TARGET_INITIALIZER; 6019 1.1 mrg 6020 1.1 mrg #include "gt-loongarch.h" 6021