Patrick Georgi | f0bbc95 | 2015-03-07 10:57:25 +0100 | [diff] [blame^] | 1 | Created from https://github.com/riscv/riscv-gnu-toolchain, |
| 2 | commit ddce5d17f14831f4957e57c415aca77817c2a82c |
| 3 | |
| 4 | diff -urN original-gcc/config.sub gcc/config.sub |
| 5 | --- original-gcc/config.sub 2013-10-01 18:50:56.000000000 +0200 |
| 6 | +++ gcc-4.9.2/config.sub 2015-03-07 09:57:54.195132741 +0100 |
| 7 | @@ -334,6 +334,9 @@ |
| 8 | ms1) |
| 9 | basic_machine=mt-unknown |
| 10 | ;; |
| 11 | + riscv) |
| 12 | + basic_machine=riscv-ucb |
| 13 | + ;; |
| 14 | |
| 15 | strongarm | thumb | xscale) |
| 16 | basic_machine=arm-unknown |
| 17 | diff -urN original-gcc/gcc/common/config/riscv/riscv-common.c gcc/gcc/common/config/riscv/riscv-common.c |
| 18 | --- original-gcc/gcc/common/config/riscv/riscv-common.c 1970-01-01 01:00:00.000000000 +0100 |
| 19 | +++ gcc-4.9.2/gcc/common/config/riscv/riscv-common.c 2015-03-07 09:51:45.663139025 +0100 |
| 20 | @@ -0,0 +1,128 @@ |
| 21 | +/* Common hooks for RISC-V. |
| 22 | + Copyright (C) 1989-2014 Free Software Foundation, Inc. |
| 23 | + |
| 24 | +This file is part of GCC. |
| 25 | + |
| 26 | +GCC is free software; you can redistribute it and/or modify |
| 27 | +it under the terms of the GNU General Public License as published by |
| 28 | +the Free Software Foundation; either version 3, or (at your option) |
| 29 | +any later version. |
| 30 | + |
| 31 | +GCC is distributed in the hope that it will be useful, |
| 32 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 33 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 34 | +GNU General Public License for more details. |
| 35 | + |
| 36 | +You should have received a copy of the GNU General Public License |
| 37 | +along with GCC; see the file COPYING3. If not see |
| 38 | +<http://www.gnu.org/licenses/>. */ |
| 39 | + |
| 40 | +#include "config.h" |
| 41 | +#include "system.h" |
| 42 | +#include "coretypes.h" |
| 43 | +#include "tm.h" |
| 44 | +#include "common/common-target.h" |
| 45 | +#include "common/common-target-def.h" |
| 46 | +#include "opts.h" |
| 47 | +#include "flags.h" |
| 48 | +#include "errors.h" |
| 49 | + |
| 50 | +/* Parse a RISC-V ISA string into an option mask. */ |
| 51 | + |
| 52 | +static void |
| 53 | +riscv_parse_arch_string (const char *isa, int *flags) |
| 54 | +{ |
| 55 | + const char *p = isa; |
| 56 | + |
| 57 | + if (strncmp (p, "RV32", 4) == 0) |
| 58 | + *flags |= MASK_32BIT, p += 4; |
| 59 | + else if (strncmp (p, "RV64", 4) == 0) |
| 60 | + *flags &= ~MASK_32BIT, p += 4; |
| 61 | + |
| 62 | + if (*p++ != 'I') |
| 63 | + { |
| 64 | + error ("-march=%s: ISA strings must begin with I, RV32I, or RV64I", isa); |
| 65 | + return; |
| 66 | + } |
| 67 | + |
| 68 | + *flags &= ~MASK_MULDIV; |
| 69 | + if (*p == 'M') |
| 70 | + *flags |= MASK_MULDIV, p++; |
| 71 | + |
| 72 | + *flags &= ~MASK_ATOMIC; |
| 73 | + if (*p == 'A') |
| 74 | + *flags |= MASK_ATOMIC, p++; |
| 75 | + |
| 76 | + *flags |= MASK_SOFT_FLOAT_ABI; |
| 77 | + if (*p == 'F') |
| 78 | + *flags &= ~MASK_SOFT_FLOAT_ABI, p++; |
| 79 | + |
| 80 | + if (*p == 'D') |
| 81 | + { |
| 82 | + p++; |
| 83 | + if (!TARGET_HARD_FLOAT) |
| 84 | + { |
| 85 | + error ("-march=%s: the D extension requires the F extension", isa); |
| 86 | + return; |
| 87 | + } |
| 88 | + } |
| 89 | + else if (TARGET_HARD_FLOAT) |
| 90 | + { |
| 91 | + error ("-march=%s: single-precision-only is not yet supported", isa); |
| 92 | + return; |
| 93 | + } |
| 94 | + |
| 95 | + if (*p) |
| 96 | + { |
| 97 | + error ("-march=%s: unsupported ISA substring %s", isa, p); |
| 98 | + return; |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | +static int |
| 103 | +riscv_flags_from_arch_string (const char *isa) |
| 104 | +{ |
| 105 | + int flags = 0; |
| 106 | + riscv_parse_arch_string (isa, &flags); |
| 107 | + return flags; |
| 108 | +} |
| 109 | + |
| 110 | +/* Implement TARGET_HANDLE_OPTION. */ |
| 111 | + |
| 112 | +static bool |
| 113 | +riscv_handle_option (struct gcc_options *opts, |
| 114 | + struct gcc_options *opts_set ATTRIBUTE_UNUSED, |
| 115 | + const struct cl_decoded_option *decoded, |
| 116 | + location_t loc ATTRIBUTE_UNUSED) |
| 117 | +{ |
| 118 | + switch (decoded->opt_index) |
| 119 | + { |
| 120 | + case OPT_march_: |
| 121 | + riscv_parse_arch_string (decoded->arg, &opts->x_target_flags); |
| 122 | + return true; |
| 123 | + |
| 124 | + default: |
| 125 | + return true; |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ |
| 130 | +static const struct default_options riscv_option_optimization_table[] = |
| 131 | + { |
| 132 | + { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 }, |
| 133 | + { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, |
| 134 | + { OPT_LEVELS_NONE, 0, NULL, 0 } |
| 135 | + }; |
| 136 | + |
| 137 | +#undef TARGET_OPTION_OPTIMIZATION_TABLE |
| 138 | +#define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table |
| 139 | + |
| 140 | +#undef TARGET_DEFAULT_TARGET_FLAGS |
| 141 | +#define TARGET_DEFAULT_TARGET_FLAGS \ |
| 142 | + (riscv_flags_from_arch_string (RISCV_ARCH_STRING_DEFAULT) \ |
| 143 | + | (TARGET_64BIT_DEFAULT ? 0 : MASK_32BIT)) |
| 144 | + |
| 145 | +#undef TARGET_HANDLE_OPTION |
| 146 | +#define TARGET_HANDLE_OPTION riscv_handle_option |
| 147 | + |
| 148 | +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; |
| 149 | diff -urN original-gcc/gcc/config/riscv/constraints.md gcc/gcc/config/riscv/constraints.md |
| 150 | --- original-gcc/gcc/config/riscv/constraints.md 1970-01-01 01:00:00.000000000 +0100 |
| 151 | +++ gcc-4.9.2/gcc/config/riscv/constraints.md 2015-03-07 09:51:45.663139025 +0100 |
| 152 | @@ -0,0 +1,90 @@ |
| 153 | +;; Constraint definitions for RISC-V target. |
| 154 | +;; Copyright (C) 2011-2014 Free Software Foundation, Inc. |
| 155 | +;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. |
| 156 | +;; Based on MIPS target for GNU compiler. |
| 157 | +;; |
| 158 | +;; This file is part of GCC. |
| 159 | +;; |
| 160 | +;; GCC is free software; you can redistribute it and/or modify |
| 161 | +;; it under the terms of the GNU General Public License as published by |
| 162 | +;; the Free Software Foundation; either version 3, or (at your option) |
| 163 | +;; any later version. |
| 164 | +;; |
| 165 | +;; GCC is distributed in the hope that it will be useful, |
| 166 | +;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 167 | +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 168 | +;; GNU General Public License for more details. |
| 169 | +;; |
| 170 | +;; You should have received a copy of the GNU General Public License |
| 171 | +;; along with GCC; see the file COPYING3. If not see |
| 172 | +;; <http://www.gnu.org/licenses/>. |
| 173 | + |
| 174 | +;; Register constraints |
| 175 | + |
| 176 | +(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS" |
| 177 | + "A floating-point register (if available).") |
| 178 | + |
| 179 | +(define_register_constraint "b" "ALL_REGS" |
| 180 | + "@internal") |
| 181 | + |
| 182 | +(define_register_constraint "j" "T_REGS" |
| 183 | + "@internal") |
| 184 | + |
| 185 | +;; Integer constraints |
| 186 | + |
| 187 | +(define_constraint "Z" |
| 188 | + "@internal" |
| 189 | + (and (match_code "const_int") |
| 190 | + (match_test "1"))) |
| 191 | + |
| 192 | +(define_constraint "I" |
| 193 | + "An I-type 12-bit signed immediate." |
| 194 | + (and (match_code "const_int") |
| 195 | + (match_test "SMALL_OPERAND (ival)"))) |
| 196 | + |
| 197 | +(define_constraint "J" |
| 198 | + "Integer zero." |
| 199 | + (and (match_code "const_int") |
| 200 | + (match_test "ival == 0"))) |
| 201 | + |
| 202 | +;; Floating-point constraints |
| 203 | + |
| 204 | +(define_constraint "G" |
| 205 | + "Floating-point zero." |
| 206 | + (and (match_code "const_double") |
| 207 | + (match_test "op == CONST0_RTX (mode)"))) |
| 208 | + |
| 209 | +;; General constraints |
| 210 | + |
| 211 | +(define_constraint "Q" |
| 212 | + "@internal" |
| 213 | + (match_operand 0 "const_arith_operand")) |
| 214 | + |
| 215 | +(define_memory_constraint "A" |
| 216 | + "An address that is held in a general-purpose register." |
| 217 | + (and (match_code "mem") |
| 218 | + (match_test "GET_CODE(XEXP(op,0)) == REG"))) |
| 219 | + |
| 220 | +(define_constraint "S" |
| 221 | + "@internal |
| 222 | + A constant call address." |
| 223 | + (and (match_operand 0 "call_insn_operand") |
| 224 | + (match_test "CONSTANT_P (op)"))) |
| 225 | + |
| 226 | +(define_constraint "T" |
| 227 | + "@internal |
| 228 | + A constant @code{move_operand}." |
| 229 | + (and (match_operand 0 "move_operand") |
| 230 | + (match_test "CONSTANT_P (op)"))) |
| 231 | + |
| 232 | +(define_memory_constraint "W" |
| 233 | + "@internal |
| 234 | + A memory address based on a member of @code{BASE_REG_CLASS}." |
| 235 | + (and (match_code "mem") |
| 236 | + (match_operand 0 "memory_operand"))) |
| 237 | + |
| 238 | +(define_constraint "YG" |
| 239 | + "@internal |
| 240 | + A vector zero." |
| 241 | + (and (match_code "const_vector") |
| 242 | + (match_test "op == CONST0_RTX (mode)"))) |
| 243 | diff -urN original-gcc/gcc/config/riscv/default-32.h gcc/gcc/config/riscv/default-32.h |
| 244 | --- original-gcc/gcc/config/riscv/default-32.h 1970-01-01 01:00:00.000000000 +0100 |
| 245 | +++ gcc-4.9.2/gcc/config/riscv/default-32.h 2015-03-07 09:51:45.663139025 +0100 |
| 246 | @@ -0,0 +1,22 @@ |
| 247 | +/* Definitions of target machine for GCC, for RISC-V, |
| 248 | + defaulting to 32-bit code generation. |
| 249 | + |
| 250 | + Copyright (C) 1999-2014 Free Software Foundation, Inc. |
| 251 | + |
| 252 | +This file is part of GCC. |
| 253 | + |
| 254 | +GCC is free software; you can redistribute it and/or modify |
| 255 | +it under the terms of the GNU General Public License as published by |
| 256 | +the Free Software Foundation; either version 3, or (at your option) |
| 257 | +any later version. |
| 258 | + |
| 259 | +GCC is distributed in the hope that it will be useful, |
| 260 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 261 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 262 | +GNU General Public License for more details. |
| 263 | + |
| 264 | +You should have received a copy of the GNU General Public License |
| 265 | +along with GCC; see the file COPYING3. If not see |
| 266 | +<http://www.gnu.org/licenses/>. */ |
| 267 | + |
| 268 | +#define TARGET_64BIT_DEFAULT 0 |
| 269 | diff -urN original-gcc/gcc/config/riscv/elf.h gcc/gcc/config/riscv/elf.h |
| 270 | --- original-gcc/gcc/config/riscv/elf.h 1970-01-01 01:00:00.000000000 +0100 |
| 271 | +++ gcc-4.9.2/gcc/config/riscv/elf.h 2015-03-07 09:51:45.663139025 +0100 |
| 272 | @@ -0,0 +1,31 @@ |
| 273 | +/* Target macros for riscv*-elf targets. |
| 274 | + Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2007, 2010 |
| 275 | + Free Software Foundation, Inc. |
| 276 | + |
| 277 | +This file is part of GCC. |
| 278 | + |
| 279 | +GCC is free software; you can redistribute it and/or modify |
| 280 | +it under the terms of the GNU General Public License as published by |
| 281 | +the Free Software Foundation; either version 3, or (at your option) |
| 282 | +any later version. |
| 283 | + |
| 284 | +GCC is distributed in the hope that it will be useful, |
| 285 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 286 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 287 | +GNU General Public License for more details. |
| 288 | + |
| 289 | +You should have received a copy of the GNU General Public License |
| 290 | +along with GCC; see the file COPYING3. If not see |
| 291 | +<http://www.gnu.org/licenses/>. */ |
| 292 | + |
| 293 | +/* Leave the linker script to choose the appropriate libraries. */ |
| 294 | +#undef LIB_SPEC |
| 295 | +#define LIB_SPEC "" |
| 296 | + |
| 297 | +#undef STARTFILE_SPEC |
| 298 | +#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" |
| 299 | + |
| 300 | +#undef ENDFILE_SPEC |
| 301 | +#define ENDFILE_SPEC "crtend%O%s" |
| 302 | + |
| 303 | +#define NO_IMPLICIT_EXTERN_C 1 |
| 304 | diff -urN original-gcc/gcc/config/riscv/generic.md gcc/gcc/config/riscv/generic.md |
| 305 | --- original-gcc/gcc/config/riscv/generic.md 1970-01-01 01:00:00.000000000 +0100 |
| 306 | +++ gcc-4.9.2/gcc/config/riscv/generic.md 2015-03-07 09:51:45.663139025 +0100 |
| 307 | @@ -0,0 +1,98 @@ |
| 308 | +;; Generic DFA-based pipeline description for RISC-V targets. |
| 309 | +;; Copyright (C) 2011-2014 Free Software Foundation, Inc. |
| 310 | +;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. |
| 311 | +;; Based on MIPS target for GNU compiler. |
| 312 | + |
| 313 | +;; This file is part of GCC. |
| 314 | + |
| 315 | +;; GCC is free software; you can redistribute it and/or modify it |
| 316 | +;; under the terms of the GNU General Public License as published |
| 317 | +;; by the Free Software Foundation; either version 3, or (at your |
| 318 | +;; option) any later version. |
| 319 | + |
| 320 | +;; GCC is distributed in the hope that it will be useful, but WITHOUT |
| 321 | +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| 322 | +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
| 323 | +;; License for more details. |
| 324 | + |
| 325 | +;; You should have received a copy of the GNU General Public License |
| 326 | +;; along with GCC; see the file COPYING3. If not see |
| 327 | +;; <http://www.gnu.org/licenses/>. |
| 328 | + |
| 329 | + |
| 330 | +;; This file is derived from the old define_function_unit description. |
| 331 | +;; Each reservation can be overridden on a processor-by-processor basis. |
| 332 | + |
| 333 | +(define_insn_reservation "generic_alu" 1 |
| 334 | + (eq_attr "type" "unknown,const,arith,shift,slt,multi,nop,logical,move") |
| 335 | + "alu") |
| 336 | + |
| 337 | +(define_insn_reservation "generic_load" 3 |
| 338 | + (eq_attr "type" "load,fpload,fpidxload") |
| 339 | + "alu") |
| 340 | + |
| 341 | +(define_insn_reservation "generic_store" 1 |
| 342 | + (eq_attr "type" "store,fpstore,fpidxstore") |
| 343 | + "alu") |
| 344 | + |
| 345 | +(define_insn_reservation "generic_xfer" 2 |
| 346 | + (eq_attr "type" "mfc,mtc") |
| 347 | + "alu") |
| 348 | + |
| 349 | +(define_insn_reservation "generic_branch" 1 |
| 350 | + (eq_attr "type" "branch,jump,call") |
| 351 | + "alu") |
| 352 | + |
| 353 | +(define_insn_reservation "generic_imul" 17 |
| 354 | + (eq_attr "type" "imul") |
| 355 | + "imuldiv*17") |
| 356 | + |
| 357 | +(define_insn_reservation "generic_idiv" 38 |
| 358 | + (eq_attr "type" "idiv") |
| 359 | + "imuldiv*38") |
| 360 | + |
| 361 | +(define_insn_reservation "generic_fcvt" 1 |
| 362 | + (eq_attr "type" "fcvt") |
| 363 | + "alu") |
| 364 | + |
| 365 | +(define_insn_reservation "generic_fmove" 2 |
| 366 | + (eq_attr "type" "fmove") |
| 367 | + "alu") |
| 368 | + |
| 369 | +(define_insn_reservation "generic_fcmp" 3 |
| 370 | + (eq_attr "type" "fcmp") |
| 371 | + "alu") |
| 372 | + |
| 373 | +(define_insn_reservation "generic_fadd" 4 |
| 374 | + (eq_attr "type" "fadd") |
| 375 | + "alu") |
| 376 | + |
| 377 | +(define_insn_reservation "generic_fmul_single" 7 |
| 378 | + (and (eq_attr "type" "fmul,fmadd") |
| 379 | + (eq_attr "mode" "SF")) |
| 380 | + "alu") |
| 381 | + |
| 382 | +(define_insn_reservation "generic_fmul_double" 8 |
| 383 | + (and (eq_attr "type" "fmul,fmadd") |
| 384 | + (eq_attr "mode" "DF")) |
| 385 | + "alu") |
| 386 | + |
| 387 | +(define_insn_reservation "generic_fdiv_single" 23 |
| 388 | + (and (eq_attr "type" "fdiv") |
| 389 | + (eq_attr "mode" "SF")) |
| 390 | + "alu") |
| 391 | + |
| 392 | +(define_insn_reservation "generic_fdiv_double" 36 |
| 393 | + (and (eq_attr "type" "fdiv") |
| 394 | + (eq_attr "mode" "DF")) |
| 395 | + "alu") |
| 396 | + |
| 397 | +(define_insn_reservation "generic_fsqrt_single" 54 |
| 398 | + (and (eq_attr "type" "fsqrt") |
| 399 | + (eq_attr "mode" "SF")) |
| 400 | + "alu") |
| 401 | + |
| 402 | +(define_insn_reservation "generic_fsqrt_double" 112 |
| 403 | + (and (eq_attr "type" "fsqrt") |
| 404 | + (eq_attr "mode" "DF")) |
| 405 | + "alu") |
| 406 | diff -urN original-gcc/gcc/config/riscv/linux64.h gcc/gcc/config/riscv/linux64.h |
| 407 | --- original-gcc/gcc/config/riscv/linux64.h 1970-01-01 01:00:00.000000000 +0100 |
| 408 | +++ gcc-4.9.2/gcc/config/riscv/linux64.h 2015-03-07 09:51:45.663139025 +0100 |
| 409 | @@ -0,0 +1,43 @@ |
| 410 | +/* Definitions for 64-bit RISC-V GNU/Linux systems with ELF format. |
| 411 | + Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 |
| 412 | + Free Software Foundation, Inc. |
| 413 | + |
| 414 | +This file is part of GCC. |
| 415 | + |
| 416 | +GCC is free software; you can redistribute it and/or modify |
| 417 | +it under the terms of the GNU General Public License as published by |
| 418 | +the Free Software Foundation; either version 3, or (at your option) |
| 419 | +any later version. |
| 420 | + |
| 421 | +GCC is distributed in the hope that it will be useful, |
| 422 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 423 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 424 | +GNU General Public License for more details. |
| 425 | + |
| 426 | +You should have received a copy of the GNU General Public License |
| 427 | +along with GCC; see the file COPYING3. If not see |
| 428 | +<http://www.gnu.org/licenses/>. */ |
| 429 | + |
| 430 | +/* Force the default ABI flags onto the command line |
| 431 | + in order to make the other specs easier to write. */ |
| 432 | +#undef LIB_SPEC |
| 433 | +#define LIB_SPEC "\ |
| 434 | +%{pthread:-lpthread} \ |
| 435 | +%{shared:-lc} \ |
| 436 | +%{!shared: \ |
| 437 | + %{profile:-lc_p} %{!profile:-lc}}" |
| 438 | + |
| 439 | +#define GLIBC_DYNAMIC_LINKER32 "/lib32/ld.so.1" |
| 440 | +#define GLIBC_DYNAMIC_LINKER64 "/lib/ld.so.1" |
| 441 | + |
| 442 | +#undef LINK_SPEC |
| 443 | +#define LINK_SPEC "\ |
| 444 | +%{shared} \ |
| 445 | + %{!shared: \ |
| 446 | + %{!static: \ |
| 447 | + %{rdynamic:-export-dynamic} \ |
| 448 | + %{" OPT_ARCH64 ": -dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "} \ |
| 449 | + %{" OPT_ARCH32 ": -dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "}} \ |
| 450 | + %{static:-static}} \ |
| 451 | +%{" OPT_ARCH64 ":-melf64lriscv} \ |
| 452 | +%{" OPT_ARCH32 ":-melf32lriscv}" |
| 453 | diff -urN original-gcc/gcc/config/riscv/linux.h gcc/gcc/config/riscv/linux.h |
| 454 | --- original-gcc/gcc/config/riscv/linux.h 1970-01-01 01:00:00.000000000 +0100 |
| 455 | +++ gcc-4.9.2/gcc/config/riscv/linux.h 2015-03-07 09:51:45.663139025 +0100 |
| 456 | @@ -0,0 +1,60 @@ |
| 457 | +/* Definitions for RISC-V GNU/Linux systems with ELF format. |
| 458 | + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, |
| 459 | + 2007, 2008, 2010, 2011 Free Software Foundation, Inc. |
| 460 | + |
| 461 | +This file is part of GCC. |
| 462 | + |
| 463 | +GCC is free software; you can redistribute it and/or modify |
| 464 | +it under the terms of the GNU General Public License as published by |
| 465 | +the Free Software Foundation; either version 3, or (at your option) |
| 466 | +any later version. |
| 467 | + |
| 468 | +GCC is distributed in the hope that it will be useful, |
| 469 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 470 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 471 | +GNU General Public License for more details. |
| 472 | + |
| 473 | +You should have received a copy of the GNU General Public License |
| 474 | +along with GCC; see the file COPYING3. If not see |
| 475 | +<http://www.gnu.org/licenses/>. */ |
| 476 | + |
| 477 | +#undef WCHAR_TYPE |
| 478 | +#define WCHAR_TYPE "int" |
| 479 | + |
| 480 | +#undef WCHAR_TYPE_SIZE |
| 481 | +#define WCHAR_TYPE_SIZE 32 |
| 482 | + |
| 483 | +#define TARGET_OS_CPP_BUILTINS() \ |
| 484 | + do { \ |
| 485 | + GNU_USER_TARGET_OS_CPP_BUILTINS(); \ |
| 486 | + /* The GNU C++ standard library requires this. */ \ |
| 487 | + if (c_dialect_cxx ()) \ |
| 488 | + builtin_define ("_GNU_SOURCE"); \ |
| 489 | + } while (0) |
| 490 | + |
| 491 | +#undef SUBTARGET_CPP_SPEC |
| 492 | +#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" |
| 493 | + |
| 494 | +#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1" |
| 495 | + |
| 496 | +/* Borrowed from sparc/linux.h */ |
| 497 | +#undef LINK_SPEC |
| 498 | +#define LINK_SPEC \ |
| 499 | + "%{shared:-shared} \ |
| 500 | + %{!shared: \ |
| 501 | + %{!static: \ |
| 502 | + %{rdynamic:-export-dynamic} \ |
| 503 | + -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \ |
| 504 | + %{static:-static}}" |
| 505 | + |
| 506 | +#undef LIB_SPEC |
| 507 | +#define LIB_SPEC "\ |
| 508 | +%{pthread:-lpthread} \ |
| 509 | +%{shared:-lc} \ |
| 510 | +%{!shared: \ |
| 511 | + %{profile:-lc_p} %{!profile:-lc}}" |
| 512 | + |
| 513 | +/* Similar to standard Linux, but adding -ffast-math support. */ |
| 514 | +#undef ENDFILE_SPEC |
| 515 | +#define ENDFILE_SPEC \ |
| 516 | + "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s" |
| 517 | diff -urN original-gcc/gcc/config/riscv/opcode-riscv.h gcc/gcc/config/riscv/opcode-riscv.h |
| 518 | --- original-gcc/gcc/config/riscv/opcode-riscv.h 1970-01-01 01:00:00.000000000 +0100 |
| 519 | +++ gcc-4.9.2/gcc/config/riscv/opcode-riscv.h 2015-03-07 09:51:45.663139025 +0100 |
| 520 | @@ -0,0 +1,149 @@ |
| 521 | +/* RISC-V ISA encoding. |
| 522 | + Copyright (C) 2011-2014 Free Software Foundation, Inc. |
| 523 | + Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. |
| 524 | + Based on MIPS target for GNU compiler. |
| 525 | + |
| 526 | +This file is part of GDB, GAS, and the GNU binutils. |
| 527 | + |
| 528 | +GDB, GAS, and the GNU binutils are free software; you can redistribute |
| 529 | +them and/or modify them under the terms of the GNU General Public |
| 530 | +License as published by the Free Software Foundation; either version |
| 531 | +1, or (at your option) any later version. |
| 532 | + |
| 533 | +GDB, GAS, and the GNU binutils are distributed in the hope that they |
| 534 | +will be useful, but WITHOUT ANY WARRANTY; without even the implied |
| 535 | +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 536 | +the GNU General Public License for more details. |
| 537 | + |
| 538 | +You should have received a copy of the GNU General Public License |
| 539 | +along with this file; see the file COPYING. If not, write to the Free |
| 540 | +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ |
| 541 | + |
| 542 | +#ifndef _RISCV_H_ |
| 543 | +#define _RISCV_H_ |
| 544 | + |
| 545 | +#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1)) |
| 546 | +#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1)) |
| 547 | + |
| 548 | +#define EXTRACT_ITYPE_IMM(x) \ |
| 549 | + (RV_X(x, 20, 12) | (RV_IMM_SIGN(x) << 12)) |
| 550 | +#define EXTRACT_STYPE_IMM(x) \ |
| 551 | + (RV_X(x, 7, 5) | (RV_X(x, 25, 7) << 5) | (RV_IMM_SIGN(x) << 12)) |
| 552 | +#define EXTRACT_SBTYPE_IMM(x) \ |
| 553 | + ((RV_X(x, 8, 4) << 1) | (RV_X(x, 25, 6) << 5) | (RV_X(x, 7, 1) << 11) | (RV_IMM_SIGN(x) << 12)) |
| 554 | +#define EXTRACT_UTYPE_IMM(x) \ |
| 555 | + ((RV_X(x, 12, 20) << 20) | (RV_IMM_SIGN(x) << 32)) |
| 556 | +#define EXTRACT_UJTYPE_IMM(x) \ |
| 557 | + ((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20)) |
| 558 | + |
| 559 | +#define ENCODE_ITYPE_IMM(x) \ |
| 560 | + (RV_X(x, 0, 12) << 20) |
| 561 | +#define ENCODE_STYPE_IMM(x) \ |
| 562 | + ((RV_X(x, 0, 5) << 7) | (RV_X(x, 5, 7) << 25)) |
| 563 | +#define ENCODE_SBTYPE_IMM(x) \ |
| 564 | + ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31)) |
| 565 | +#define ENCODE_UTYPE_IMM(x) \ |
| 566 | + (RV_X(x, 12, 20) << 12) |
| 567 | +#define ENCODE_UJTYPE_IMM(x) \ |
| 568 | + ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31)) |
| 569 | + |
| 570 | +#define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x)) |
| 571 | +#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x)) |
| 572 | +#define VALID_SBTYPE_IMM(x) (EXTRACT_SBTYPE_IMM(ENCODE_SBTYPE_IMM(x)) == (x)) |
| 573 | +#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x)) |
| 574 | +#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x)) |
| 575 | + |
| 576 | +#define RISCV_RTYPE(insn, rd, rs1, rs2) \ |
| 577 | + ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2)) |
| 578 | +#define RISCV_ITYPE(insn, rd, rs1, imm) \ |
| 579 | + ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ENCODE_ITYPE_IMM(imm)) |
| 580 | +#define RISCV_STYPE(insn, rs1, rs2, imm) \ |
| 581 | + ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_STYPE_IMM(imm)) |
| 582 | +#define RISCV_SBTYPE(insn, rs1, rs2, target) \ |
| 583 | + ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_SBTYPE_IMM(target)) |
| 584 | +#define RISCV_UTYPE(insn, rd, bigimm) \ |
| 585 | + ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UTYPE_IMM(bigimm)) |
| 586 | +#define RISCV_UJTYPE(insn, rd, target) \ |
| 587 | + ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UJTYPE_IMM(target)) |
| 588 | + |
| 589 | +#define RISCV_NOP RISCV_ITYPE(ADDI, 0, 0, 0) |
| 590 | + |
| 591 | +#define RISCV_CONST_HIGH_PART(VALUE) \ |
| 592 | + (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1)) |
| 593 | +#define RISCV_CONST_LOW_PART(VALUE) ((VALUE) - RISCV_CONST_HIGH_PART (VALUE)) |
| 594 | + |
| 595 | +/* RV fields */ |
| 596 | + |
| 597 | +#define OP_MASK_OP 0x7f |
| 598 | +#define OP_SH_OP 0 |
| 599 | +#define OP_MASK_RS2 0x1f |
| 600 | +#define OP_SH_RS2 20 |
| 601 | +#define OP_MASK_RS1 0x1f |
| 602 | +#define OP_SH_RS1 15 |
| 603 | +#define OP_MASK_RS3 0x1f |
| 604 | +#define OP_SH_RS3 27 |
| 605 | +#define OP_MASK_RD 0x1f |
| 606 | +#define OP_SH_RD 7 |
| 607 | +#define OP_MASK_SHAMT 0x3f |
| 608 | +#define OP_SH_SHAMT 20 |
| 609 | +#define OP_MASK_SHAMTW 0x1f |
| 610 | +#define OP_SH_SHAMTW 20 |
| 611 | +#define OP_MASK_RM 0x7 |
| 612 | +#define OP_SH_RM 12 |
| 613 | +#define OP_MASK_PRED 0xf |
| 614 | +#define OP_SH_PRED 24 |
| 615 | +#define OP_MASK_SUCC 0xf |
| 616 | +#define OP_SH_SUCC 20 |
| 617 | +#define OP_MASK_AQ 0x1 |
| 618 | +#define OP_SH_AQ 26 |
| 619 | +#define OP_MASK_RL 0x1 |
| 620 | +#define OP_SH_RL 25 |
| 621 | + |
| 622 | +#define OP_MASK_VRD 0x1f |
| 623 | +#define OP_SH_VRD 7 |
| 624 | +#define OP_MASK_VRS 0x1f |
| 625 | +#define OP_SH_VRS 15 |
| 626 | +#define OP_MASK_VRT 0x1f |
| 627 | +#define OP_SH_VRT 20 |
| 628 | +#define OP_MASK_VRR 0x1f |
| 629 | +#define OP_SH_VRR 25 |
| 630 | + |
| 631 | +#define OP_MASK_VFD 0x1f |
| 632 | +#define OP_SH_VFD 7 |
| 633 | +#define OP_MASK_VFS 0x1f |
| 634 | +#define OP_SH_VFS 15 |
| 635 | +#define OP_MASK_VFT 0x1f |
| 636 | +#define OP_SH_VFT 20 |
| 637 | +#define OP_MASK_VFR 0x1f |
| 638 | +#define OP_SH_VFR 25 |
| 639 | + |
| 640 | +#define OP_MASK_IMMNGPR 0x3f |
| 641 | +#define OP_SH_IMMNGPR 20 |
| 642 | +#define OP_MASK_IMMNFPR 0x3f |
| 643 | +#define OP_SH_IMMNFPR 26 |
| 644 | +#define OP_MASK_IMMSEGNELM 0x1f |
| 645 | +#define OP_SH_IMMSEGNELM 17 |
| 646 | +#define OP_MASK_IMMSEGSTNELM 0x1f |
| 647 | +#define OP_SH_IMMSEGSTNELM 12 |
| 648 | +#define OP_MASK_CUSTOM_IMM 0x7f |
| 649 | +#define OP_SH_CUSTOM_IMM 25 |
| 650 | + |
| 651 | +#define LINK_REG 1 |
| 652 | + |
| 653 | +#define RISCV_JUMP_BITS RISCV_BIGIMM_BITS |
| 654 | +#define RISCV_JUMP_ALIGN_BITS 1 |
| 655 | +#define RISCV_JUMP_ALIGN (1 << RISCV_JUMP_ALIGN_BITS) |
| 656 | +#define RISCV_JUMP_REACH ((1ULL<<RISCV_JUMP_BITS)*RISCV_JUMP_ALIGN) |
| 657 | + |
| 658 | +#define RISCV_IMM_BITS 12 |
| 659 | +#define RISCV_BIGIMM_BITS (32-RISCV_IMM_BITS) |
| 660 | +#define RISCV_IMM_REACH (1LL<<RISCV_IMM_BITS) |
| 661 | +#define RISCV_BIGIMM_REACH (1LL<<RISCV_BIGIMM_BITS) |
| 662 | +#define RISCV_BRANCH_BITS RISCV_IMM_BITS |
| 663 | +#define RISCV_BRANCH_ALIGN_BITS RISCV_JUMP_ALIGN_BITS |
| 664 | +#define RISCV_BRANCH_ALIGN (1 << RISCV_BRANCH_ALIGN_BITS) |
| 665 | +#define RISCV_BRANCH_REACH (RISCV_IMM_REACH*RISCV_BRANCH_ALIGN) |
| 666 | + |
| 667 | +#include "riscv-opc.h" |
| 668 | + |
| 669 | +#endif /* _RISCV_H_ */ |
| 670 | diff -urN original-gcc/gcc/config/riscv/peephole.md gcc/gcc/config/riscv/peephole.md |
| 671 | --- original-gcc/gcc/config/riscv/peephole.md 1970-01-01 01:00:00.000000000 +0100 |
| 672 | +++ gcc-4.9.2/gcc/config/riscv/peephole.md 2015-03-07 09:51:45.663139025 +0100 |
| 673 | @@ -0,0 +1,100 @@ |
| 674 | +;;........................ |
| 675 | +;; DI -> SI optimizations |
| 676 | +;;........................ |
| 677 | + |
| 678 | +;; Simplify (int)(a + 1), etc. |
| 679 | +(define_peephole2 |
| 680 | + [(set (match_operand:DI 0 "register_operand") |
| 681 | + (match_operator:DI 4 "modular_operator" |
| 682 | + [(match_operand:DI 1 "register_operand") |
| 683 | + (match_operand:DI 2 "arith_operand")])) |
| 684 | + (set (match_operand:SI 3 "register_operand") |
| 685 | + (truncate:SI (match_dup 0)))] |
| 686 | + "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0])) |
| 687 | + && (GET_CODE (operands[4]) != ASHIFT || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32))" |
| 688 | + [(set (match_dup 3) |
| 689 | + (truncate:SI |
| 690 | + (match_op_dup:DI 4 |
| 691 | + [(match_operand:DI 1 "register_operand") |
| 692 | + (match_operand:DI 2 "arith_operand")])))]) |
| 693 | + |
| 694 | +;; Simplify (int)a + 1, etc. |
| 695 | +(define_peephole2 |
| 696 | + [(set (match_operand:SI 0 "register_operand") |
| 697 | + (truncate:SI (match_operand:DI 1 "register_operand"))) |
| 698 | + (set (match_operand:SI 3 "register_operand") |
| 699 | + (match_operator:SI 4 "modular_operator" |
| 700 | + [(match_dup 0) |
| 701 | + (match_operand:SI 2 "arith_operand")]))] |
| 702 | + "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))" |
| 703 | + [(set (match_dup 3) |
| 704 | + (match_op_dup:SI 4 [(match_dup 1) (match_dup 2)]))]) |
| 705 | + |
| 706 | +;; Simplify -(int)a, etc. |
| 707 | +(define_peephole2 |
| 708 | + [(set (match_operand:SI 0 "register_operand") |
| 709 | + (truncate:SI (match_operand:DI 2 "register_operand"))) |
| 710 | + (set (match_operand:SI 3 "register_operand") |
| 711 | + (match_operator:SI 4 "modular_operator" |
| 712 | + [(match_operand:SI 1 "reg_or_0_operand") |
| 713 | + (match_dup 0)]))] |
| 714 | + "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))" |
| 715 | + [(set (match_dup 3) |
| 716 | + (match_op_dup:SI 4 [(match_dup 1) (match_dup 2)]))]) |
| 717 | + |
| 718 | +;; Simplify PIC loads to static variables. |
| 719 | +;; These will go away once we figure out how to emit auipc discretely. |
| 720 | +(define_insn "*local_pic_load<mode>" |
| 721 | + [(set (match_operand:ANYI 0 "register_operand" "=r") |
| 722 | + (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))] |
| 723 | + "flag_pic && SYMBOL_REF_LOCAL_P (operands[1])" |
| 724 | + "<load>\t%0,%1" |
| 725 | + [(set (attr "length") (const_int 8))]) |
| 726 | +(define_insn "*local_pic_load<mode>" |
| 727 | + [(set (match_operand:ANYF 0 "register_operand" "=f") |
| 728 | + (mem:ANYF (match_operand 1 "absolute_symbolic_operand" ""))) |
| 729 | + (clobber (match_scratch:DI 2 "=&r"))] |
| 730 | + "TARGET_HARD_FLOAT && TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])" |
| 731 | + "<load>\t%0,%1,%2" |
| 732 | + [(set (attr "length") (const_int 8))]) |
| 733 | +(define_insn "*local_pic_load<mode>" |
| 734 | + [(set (match_operand:ANYF 0 "register_operand" "=f") |
| 735 | + (mem:ANYF (match_operand 1 "absolute_symbolic_operand" ""))) |
| 736 | + (clobber (match_scratch:SI 2 "=&r"))] |
| 737 | + "TARGET_HARD_FLOAT && !TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])" |
| 738 | + "<load>\t%0,%1,%2" |
| 739 | + [(set (attr "length") (const_int 8))]) |
| 740 | +(define_insn "*local_pic_loadu<mode>" |
| 741 | + [(set (match_operand:SUPERQI 0 "register_operand" "=r") |
| 742 | + (zero_extend:SUPERQI (mem:SUBDI (match_operand 1 "absolute_symbolic_operand" ""))))] |
| 743 | + "flag_pic && SYMBOL_REF_LOCAL_P (operands[1])" |
| 744 | + "<load>u\t%0,%1" |
| 745 | + [(set (attr "length") (const_int 8))]) |
| 746 | +(define_insn "*local_pic_storedi<mode>" |
| 747 | + [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" "")) |
| 748 | + (match_operand:ANYI 1 "reg_or_0_operand" "rJ")) |
| 749 | + (clobber (match_scratch:DI 2 "=&r"))] |
| 750 | + "TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))" |
| 751 | + "<store>\t%z1,%0,%2" |
| 752 | + [(set (attr "length") (const_int 8))]) |
| 753 | +(define_insn "*local_pic_storesi<mode>" |
| 754 | + [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" "")) |
| 755 | + (match_operand:ANYI 1 "reg_or_0_operand" "rJ")) |
| 756 | + (clobber (match_scratch:SI 2 "=&r"))] |
| 757 | + "!TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))" |
| 758 | + "<store>\t%z1,%0,%2" |
| 759 | + [(set (attr "length") (const_int 8))]) |
| 760 | +(define_insn "*local_pic_storedi<mode>" |
| 761 | + [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" "")) |
| 762 | + (match_operand:ANYF 1 "register_operand" "f")) |
| 763 | + (clobber (match_scratch:DI 2 "=&r"))] |
| 764 | + "TARGET_HARD_FLOAT && TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))" |
| 765 | + "<store>\t%1,%0,%2" |
| 766 | + [(set (attr "length") (const_int 8))]) |
| 767 | +(define_insn "*local_pic_storesi<mode>" |
| 768 | + [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" "")) |
| 769 | + (match_operand:ANYF 1 "register_operand" "f")) |
| 770 | + (clobber (match_scratch:SI 2 "=&r"))] |
| 771 | + "TARGET_HARD_FLOAT && !TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))" |
| 772 | + "<store>\t%1,%0,%2" |
| 773 | + [(set (attr "length") (const_int 8))]) |
| 774 | diff -urN original-gcc/gcc/config/riscv/predicates.md gcc/gcc/config/riscv/predicates.md |
| 775 | --- original-gcc/gcc/config/riscv/predicates.md 1970-01-01 01:00:00.000000000 +0100 |
| 776 | +++ gcc-4.9.2/gcc/config/riscv/predicates.md 2015-03-07 09:51:45.663139025 +0100 |
| 777 | @@ -0,0 +1,182 @@ |
| 778 | +;; Predicate description for RISC-V target. |
| 779 | +;; Copyright (C) 2011-2014 Free Software Foundation, Inc. |
| 780 | +;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. |
| 781 | +;; Based on MIPS target for GNU compiler. |
| 782 | +;; |
| 783 | +;; This file is part of GCC. |
| 784 | +;; |
| 785 | +;; GCC is free software; you can redistribute it and/or modify |
| 786 | +;; it under the terms of the GNU General Public License as published by |
| 787 | +;; the Free Software Foundation; either version 3, or (at your option) |
| 788 | +;; any later version. |
| 789 | +;; |
| 790 | +;; GCC is distributed in the hope that it will be useful, |
| 791 | +;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 792 | +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 793 | +;; GNU General Public License for more details. |
| 794 | +;; |
| 795 | +;; You should have received a copy of the GNU General Public License |
| 796 | +;; along with GCC; see the file COPYING3. If not see |
| 797 | +;; <http://www.gnu.org/licenses/>. |
| 798 | + |
| 799 | +(define_predicate "const_arith_operand" |
| 800 | + (and (match_code "const_int") |
| 801 | + (match_test "SMALL_OPERAND (INTVAL (op))"))) |
| 802 | + |
| 803 | +(define_predicate "arith_operand" |
| 804 | + (ior (match_operand 0 "const_arith_operand") |
| 805 | + (match_operand 0 "register_operand"))) |
| 806 | + |
| 807 | +(define_predicate "sle_operand" |
| 808 | + (and (match_code "const_int") |
| 809 | + (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) |
| 810 | + |
| 811 | +(define_predicate "sleu_operand" |
| 812 | + (and (match_operand 0 "sle_operand") |
| 813 | + (match_test "INTVAL (op) + 1 != 0"))) |
| 814 | + |
| 815 | +(define_predicate "const_0_operand" |
| 816 | + (and (match_code "const_int,const_double,const_vector") |
| 817 | + (match_test "op == CONST0_RTX (GET_MODE (op))"))) |
| 818 | + |
| 819 | +(define_predicate "reg_or_0_operand" |
| 820 | + (ior (match_operand 0 "const_0_operand") |
| 821 | + (match_operand 0 "register_operand"))) |
| 822 | + |
| 823 | +(define_predicate "const_1_operand" |
| 824 | + (and (match_code "const_int,const_double,const_vector") |
| 825 | + (match_test "op == CONST1_RTX (GET_MODE (op))"))) |
| 826 | + |
| 827 | +(define_predicate "reg_or_1_operand" |
| 828 | + (ior (match_operand 0 "const_1_operand") |
| 829 | + (match_operand 0 "register_operand"))) |
| 830 | + |
| 831 | +;; This is used for indexing into vectors, and hence only accepts const_int. |
| 832 | +(define_predicate "const_0_or_1_operand" |
| 833 | + (and (match_code "const_int") |
| 834 | + (ior (match_test "op == CONST0_RTX (GET_MODE (op))") |
| 835 | + (match_test "op == CONST1_RTX (GET_MODE (op))")))) |
| 836 | + |
| 837 | +(define_special_predicate "pc_or_label_operand" |
| 838 | + (match_code "pc,label_ref")) |
| 839 | + |
| 840 | +;; A legitimate CONST_INT operand that takes more than one instruction |
| 841 | +;; to load. |
| 842 | +(define_predicate "splittable_const_int_operand" |
| 843 | + (match_code "const_int") |
| 844 | +{ |
| 845 | + /* Don't handle multi-word moves this way; we don't want to introduce |
| 846 | + the individual word-mode moves until after reload. */ |
| 847 | + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) |
| 848 | + return false; |
| 849 | + |
| 850 | + /* Otherwise check whether the constant can be loaded in a single |
| 851 | + instruction. */ |
| 852 | + return !LUI_INT (op) && !SMALL_INT (op); |
| 853 | +}) |
| 854 | + |
| 855 | +(define_predicate "move_operand" |
| 856 | + (match_operand 0 "general_operand") |
| 857 | +{ |
| 858 | + enum riscv_symbol_type symbol_type; |
| 859 | + |
| 860 | + /* The thinking here is as follows: |
| 861 | + |
| 862 | + (1) The move expanders should split complex load sequences into |
| 863 | + individual instructions. Those individual instructions can |
| 864 | + then be optimized by all rtl passes. |
| 865 | + |
| 866 | + (2) The target of pre-reload load sequences should not be used |
| 867 | + to store temporary results. If the target register is only |
| 868 | + assigned one value, reload can rematerialize that value |
| 869 | + on demand, rather than spill it to the stack. |
| 870 | + |
| 871 | + (3) If we allowed pre-reload passes like combine and cse to recreate |
| 872 | + complex load sequences, we would want to be able to split the |
| 873 | + sequences before reload as well, so that the pre-reload scheduler |
| 874 | + can see the individual instructions. This falls foul of (2); |
| 875 | + the splitter would be forced to reuse the target register for |
| 876 | + intermediate results. |
| 877 | + |
| 878 | + (4) We want to define complex load splitters for combine. These |
| 879 | + splitters can request a temporary scratch register, which avoids |
| 880 | + the problem in (2). They allow things like: |
| 881 | + |
| 882 | + (set (reg T1) (high SYM)) |
| 883 | + (set (reg T2) (low (reg T1) SYM)) |
| 884 | + (set (reg X) (plus (reg T2) (const_int OFFSET))) |
| 885 | + |
| 886 | + to be combined into: |
| 887 | + |
| 888 | + (set (reg T3) (high SYM+OFFSET)) |
| 889 | + (set (reg X) (lo_sum (reg T3) SYM+OFFSET)) |
| 890 | + |
| 891 | + if T2 is only used this once. */ |
| 892 | + switch (GET_CODE (op)) |
| 893 | + { |
| 894 | + case CONST_INT: |
| 895 | + return !splittable_const_int_operand (op, mode); |
| 896 | + |
| 897 | + case CONST: |
| 898 | + case SYMBOL_REF: |
| 899 | + case LABEL_REF: |
| 900 | + return (riscv_symbolic_constant_p (op, &symbol_type) |
| 901 | + && !riscv_hi_relocs[symbol_type]); |
| 902 | + |
| 903 | + case HIGH: |
| 904 | + op = XEXP (op, 0); |
| 905 | + return riscv_symbolic_constant_p (op, &symbol_type); |
| 906 | + |
| 907 | + default: |
| 908 | + return true; |
| 909 | + } |
| 910 | +}) |
| 911 | + |
| 912 | +(define_predicate "consttable_operand" |
| 913 | + (match_test "CONSTANT_P (op)")) |
| 914 | + |
| 915 | +(define_predicate "symbolic_operand" |
| 916 | + (match_code "const,symbol_ref,label_ref") |
| 917 | +{ |
| 918 | + enum riscv_symbol_type type; |
| 919 | + return riscv_symbolic_constant_p (op, &type); |
| 920 | +}) |
| 921 | + |
| 922 | +(define_predicate "absolute_symbolic_operand" |
| 923 | + (match_code "const,symbol_ref,label_ref") |
| 924 | +{ |
| 925 | + enum riscv_symbol_type type; |
| 926 | + return (riscv_symbolic_constant_p (op, &type) |
| 927 | + && type == SYMBOL_ABSOLUTE); |
| 928 | +}) |
| 929 | + |
| 930 | +(define_predicate "plt_symbolic_operand" |
| 931 | + (match_code "const,symbol_ref,label_ref") |
| 932 | +{ |
| 933 | + enum riscv_symbol_type type; |
| 934 | + return (riscv_symbolic_constant_p (op, &type) |
| 935 | + && type == SYMBOL_GOT_DISP && !SYMBOL_REF_WEAK (op) && TARGET_PLT); |
| 936 | +}) |
| 937 | + |
| 938 | +(define_predicate "call_insn_operand" |
| 939 | + (ior (match_operand 0 "absolute_symbolic_operand") |
| 940 | + (match_operand 0 "plt_symbolic_operand") |
| 941 | + (match_operand 0 "register_operand"))) |
| 942 | + |
| 943 | +(define_predicate "symbol_ref_operand" |
| 944 | + (match_code "symbol_ref")) |
| 945 | + |
| 946 | +(define_predicate "modular_operator" |
| 947 | + (match_code "plus,minus,mult,ashift")) |
| 948 | + |
| 949 | +(define_predicate "equality_operator" |
| 950 | + (match_code "eq,ne")) |
| 951 | + |
| 952 | +(define_predicate "order_operator" |
| 953 | + (match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu")) |
| 954 | + |
| 955 | +(define_predicate "fp_order_operator" |
| 956 | + (match_code "eq,lt,le,gt,ge")) |
| 957 | + |
| 958 | +(define_predicate "fp_unorder_operator" |
| 959 | + (match_code "ordered,unordered")) |
| 960 | diff -urN original-gcc/gcc/config/riscv/riscv.c gcc/gcc/config/riscv/riscv.c |
| 961 | --- original-gcc/gcc/config/riscv/riscv.c 1970-01-01 01:00:00.000000000 +0100 |
| 962 | +++ gcc-4.9.2/gcc/config/riscv/riscv.c 2015-03-07 09:51:45.667139025 +0100 |
| 963 | @@ -0,0 +1,4292 @@ |
| 964 | +/* Subroutines used for code generation for RISC-V. |
| 965 | + Copyright (C) 2011-2014 Free Software Foundation, Inc. |
| 966 | + Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley. |
| 967 | + Based on MIPS target for GNU compiler. |
| 968 | + |
| 969 | +This file is part of GCC. |
| 970 | + |
| 971 | +GCC is free software; you can redistribute it and/or modify |
| 972 | +it under the terms of the GNU General Public License as published by |
| 973 | +the Free Software Foundation; either version 3, or (at your option) |
| 974 | +any later version. |
| 975 | + |
| 976 | +GCC is distributed in the hope that it will be useful, |
| 977 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 978 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 979 | +GNU General Public License for more details. |
| 980 | + |
| 981 | +You should have received a copy of the GNU General Public License |
| 982 | +along with GCC; see the file COPYING3. If not see |
| 983 | +<http://www.gnu.org/licenses/>. */ |
| 984 | + |
| 985 | +#include "config.h" |
| 986 | +#include "system.h" |
| 987 | +#include "coretypes.h" |
| 988 | +#include "tm.h" |
| 989 | +#include "rtl.h" |
| 990 | +#include "regs.h" |
| 991 | +#include "hard-reg-set.h" |
| 992 | +#include "insn-config.h" |
| 993 | +#include "conditions.h" |
| 994 | +#include "insn-attr.h" |
| 995 | +#include "recog.h" |
| 996 | +#include "output.h" |
| 997 | +#include "tree.h" |
| 998 | +#include "varasm.h" |
| 999 | +#include "stor-layout.h" |
| 1000 | +#include "calls.h" |
| 1001 | +#include "function.h" |
| 1002 | +#include "expr.h" |
| 1003 | +#include "optabs.h" |
| 1004 | +#include "libfuncs.h" |
| 1005 | +#include "flags.h" |
| 1006 | +#include "reload.h" |
| 1007 | +#include "tm_p.h" |
| 1008 | +#include "ggc.h" |
| 1009 | +#include "gstab.h" |
| 1010 | +#include "hashtab.h" |
| 1011 | +#include "debug.h" |
| 1012 | +#include "target.h" |
| 1013 | +#include "target-def.h" |
| 1014 | +#include "langhooks.h" |
| 1015 | +#include "sched-int.h" |
| 1016 | +#include "bitmap.h" |
| 1017 | +#include "diagnostic.h" |
| 1018 | +#include "target-globals.h" |
| 1019 | +#include "symcat.h" |
| 1020 | +#include <stdint.h> |
| 1021 | + |
| 1022 | +/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ |
| 1023 | +#define UNSPEC_ADDRESS_P(X) \ |
| 1024 | + (GET_CODE (X) == UNSPEC \ |
| 1025 | + && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ |
| 1026 | + && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) |
| 1027 | + |
| 1028 | +/* Extract the symbol or label from UNSPEC wrapper X. */ |
| 1029 | +#define UNSPEC_ADDRESS(X) \ |
| 1030 | + XVECEXP (X, 0, 0) |
| 1031 | + |
| 1032 | +/* Extract the symbol type from UNSPEC wrapper X. */ |
| 1033 | +#define UNSPEC_ADDRESS_TYPE(X) \ |
| 1034 | + ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) |
| 1035 | + |
| 1036 | +/* The maximum distance between the top of the stack frame and the |
| 1037 | + value sp has when we save and restore registers. This is set by the |
| 1038 | + range of load/store offsets and must also preserve stack alignment. */ |
| 1039 | +#define RISCV_MAX_FIRST_STACK_STEP (RISCV_IMM_REACH/2 - 16) |
| 1040 | + |
| 1041 | +/* True if INSN is a riscv.md pattern or asm statement. */ |
| 1042 | +#define USEFUL_INSN_P(INSN) \ |
| 1043 | + (NONDEBUG_INSN_P (INSN) \ |
| 1044 | + && GET_CODE (PATTERN (INSN)) != USE \ |
| 1045 | + && GET_CODE (PATTERN (INSN)) != CLOBBER \ |
| 1046 | + && GET_CODE (PATTERN (INSN)) != ADDR_VEC \ |
| 1047 | + && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC) |
| 1048 | + |
| 1049 | +/* True if bit BIT is set in VALUE. */ |
| 1050 | +#define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0) |
| 1051 | + |
| 1052 | +/* Classifies an address. |
| 1053 | + |
| 1054 | + ADDRESS_REG |
| 1055 | + A natural register + offset address. The register satisfies |
| 1056 | + riscv_valid_base_register_p and the offset is a const_arith_operand. |
| 1057 | + |
| 1058 | + ADDRESS_LO_SUM |
| 1059 | + A LO_SUM rtx. The first operand is a valid base register and |
| 1060 | + the second operand is a symbolic address. |
| 1061 | + |
| 1062 | + ADDRESS_CONST_INT |
| 1063 | + A signed 16-bit constant address. |
| 1064 | + |
| 1065 | + ADDRESS_SYMBOLIC: |
| 1066 | + A constant symbolic address. */ |
| 1067 | +enum riscv_address_type { |
| 1068 | + ADDRESS_REG, |
| 1069 | + ADDRESS_LO_SUM, |
| 1070 | + ADDRESS_CONST_INT, |
| 1071 | + ADDRESS_SYMBOLIC |
| 1072 | +}; |
| 1073 | + |
| 1074 | +/* Macros to create an enumeration identifier for a function prototype. */ |
| 1075 | +#define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B |
| 1076 | +#define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C |
| 1077 | +#define RISCV_FTYPE_NAME3(A, B, C, D) RISCV_##A##_FTYPE_##B##_##C##_##D |
| 1078 | +#define RISCV_FTYPE_NAME4(A, B, C, D, E) RISCV_##A##_FTYPE_##B##_##C##_##D##_##E |
| 1079 | + |
| 1080 | +/* Classifies the prototype of a built-in function. */ |
| 1081 | +enum riscv_function_type { |
| 1082 | +#define DEF_RISCV_FTYPE(NARGS, LIST) RISCV_FTYPE_NAME##NARGS LIST, |
| 1083 | +#include "config/riscv/riscv-ftypes.def" |
| 1084 | +#undef DEF_RISCV_FTYPE |
| 1085 | + RISCV_MAX_FTYPE_MAX |
| 1086 | +}; |
| 1087 | + |
| 1088 | +/* Specifies how a built-in function should be converted into rtl. */ |
| 1089 | +enum riscv_builtin_type { |
| 1090 | + /* The function corresponds directly to an .md pattern. The return |
| 1091 | + value is mapped to operand 0 and the arguments are mapped to |
| 1092 | + operands 1 and above. */ |
| 1093 | + RISCV_BUILTIN_DIRECT, |
| 1094 | + |
| 1095 | + /* The function corresponds directly to an .md pattern. There is no return |
| 1096 | + value and the arguments are mapped to operands 0 and above. */ |
| 1097 | + RISCV_BUILTIN_DIRECT_NO_TARGET |
| 1098 | +}; |
| 1099 | + |
| 1100 | +/* Information about a function's frame layout. */ |
| 1101 | +struct GTY(()) riscv_frame_info { |
| 1102 | + /* The size of the frame in bytes. */ |
| 1103 | + HOST_WIDE_INT total_size; |
| 1104 | + |
| 1105 | + /* Bit X is set if the function saves or restores GPR X. */ |
| 1106 | + unsigned int mask; |
| 1107 | + |
| 1108 | + /* Likewise FPR X. */ |
| 1109 | + unsigned int fmask; |
| 1110 | + |
| 1111 | + /* Offsets of fixed-point and floating-point save areas from frame bottom */ |
| 1112 | + HOST_WIDE_INT gp_sp_offset; |
| 1113 | + HOST_WIDE_INT fp_sp_offset; |
| 1114 | + |
| 1115 | + /* Offset of virtual frame pointer from stack pointer/frame bottom */ |
| 1116 | + HOST_WIDE_INT frame_pointer_offset; |
| 1117 | + |
| 1118 | + /* Offset of hard frame pointer from stack pointer/frame bottom */ |
| 1119 | + HOST_WIDE_INT hard_frame_pointer_offset; |
| 1120 | + |
| 1121 | + /* The offset of arg_pointer_rtx from the bottom of the frame. */ |
| 1122 | + HOST_WIDE_INT arg_pointer_offset; |
| 1123 | +}; |
| 1124 | + |
| 1125 | +struct GTY(()) machine_function { |
| 1126 | + /* The number of extra stack bytes taken up by register varargs. |
| 1127 | + This area is allocated by the callee at the very top of the frame. */ |
| 1128 | + int varargs_size; |
| 1129 | + |
| 1130 | + /* The current frame information, calculated by riscv_compute_frame_info. */ |
| 1131 | + struct riscv_frame_info frame; |
| 1132 | +}; |
| 1133 | + |
| 1134 | +/* Information about a single argument. */ |
| 1135 | +struct riscv_arg_info { |
| 1136 | + /* True if the argument is passed in a floating-point register, or |
| 1137 | + would have been if we hadn't run out of registers. */ |
| 1138 | + bool fpr_p; |
| 1139 | + |
| 1140 | + /* The number of words passed in registers, rounded up. */ |
| 1141 | + unsigned int reg_words; |
| 1142 | + |
| 1143 | + /* For EABI, the offset of the first register from GP_ARG_FIRST or |
| 1144 | + FP_ARG_FIRST. For other ABIs, the offset of the first register from |
| 1145 | + the start of the ABI's argument structure (see the CUMULATIVE_ARGS |
| 1146 | + comment for details). |
| 1147 | + |
| 1148 | + The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely |
| 1149 | + on the stack. */ |
| 1150 | + unsigned int reg_offset; |
| 1151 | + |
| 1152 | + /* The number of words that must be passed on the stack, rounded up. */ |
| 1153 | + unsigned int stack_words; |
| 1154 | + |
| 1155 | + /* The offset from the start of the stack overflow area of the argument's |
| 1156 | + first stack word. Only meaningful when STACK_WORDS is nonzero. */ |
| 1157 | + unsigned int stack_offset; |
| 1158 | +}; |
| 1159 | + |
| 1160 | +/* Information about an address described by riscv_address_type. |
| 1161 | + |
| 1162 | + ADDRESS_CONST_INT |
| 1163 | + No fields are used. |
| 1164 | + |
| 1165 | + ADDRESS_REG |
| 1166 | + REG is the base register and OFFSET is the constant offset. |
| 1167 | + |
| 1168 | + ADDRESS_LO_SUM |
| 1169 | + REG and OFFSET are the operands to the LO_SUM and SYMBOL_TYPE |
| 1170 | + is the type of symbol it references. |
| 1171 | + |
| 1172 | + ADDRESS_SYMBOLIC |
| 1173 | + SYMBOL_TYPE is the type of symbol that the address references. */ |
| 1174 | +struct riscv_address_info { |
| 1175 | + enum riscv_address_type type; |
| 1176 | + rtx reg; |
| 1177 | + rtx offset; |
| 1178 | + enum riscv_symbol_type symbol_type; |
| 1179 | +}; |
| 1180 | + |
| 1181 | +/* One stage in a constant building sequence. These sequences have |
| 1182 | + the form: |
| 1183 | + |
| 1184 | + A = VALUE[0] |
| 1185 | + A = A CODE[1] VALUE[1] |
| 1186 | + A = A CODE[2] VALUE[2] |
| 1187 | + ... |
| 1188 | + |
| 1189 | + where A is an accumulator, each CODE[i] is a binary rtl operation |
| 1190 | + and each VALUE[i] is a constant integer. CODE[0] is undefined. */ |
| 1191 | +struct riscv_integer_op { |
| 1192 | + enum rtx_code code; |
| 1193 | + unsigned HOST_WIDE_INT value; |
| 1194 | +}; |
| 1195 | + |
| 1196 | +/* The largest number of operations needed to load an integer constant. |
| 1197 | + The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI, |
| 1198 | + but we may attempt and reject even worse sequences. */ |
| 1199 | +#define RISCV_MAX_INTEGER_OPS 32 |
| 1200 | + |
| 1201 | +/* Costs of various operations on the different architectures. */ |
| 1202 | + |
| 1203 | +struct riscv_tune_info |
| 1204 | +{ |
| 1205 | + unsigned short fp_add[2]; |
| 1206 | + unsigned short fp_mul[2]; |
| 1207 | + unsigned short fp_div[2]; |
| 1208 | + unsigned short int_mul[2]; |
| 1209 | + unsigned short int_div[2]; |
| 1210 | + unsigned short issue_rate; |
| 1211 | + unsigned short branch_cost; |
| 1212 | + unsigned short fp_to_int_cost; |
| 1213 | + unsigned short memory_cost; |
| 1214 | +}; |
| 1215 | + |
| 1216 | +/* Information about one CPU we know about. */ |
| 1217 | +struct riscv_cpu_info { |
| 1218 | + /* This CPU's canonical name. */ |
| 1219 | + const char *name; |
| 1220 | + |
| 1221 | + /* The RISC-V ISA and extensions supported by this CPU. */ |
| 1222 | + const char *isa; |
| 1223 | + |
| 1224 | + /* Tuning parameters for this CPU. */ |
| 1225 | + const struct riscv_tune_info *tune_info; |
| 1226 | +}; |
| 1227 | + |
| 1228 | +/* Global variables for machine-dependent things. */ |
| 1229 | + |
| 1230 | +/* Which tuning parameters to use. */ |
| 1231 | +static const struct riscv_tune_info *tune_info; |
| 1232 | + |
| 1233 | +/* Index [M][R] is true if register R is allowed to hold a value of mode M. */ |
| 1234 | +bool riscv_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; |
| 1235 | + |
| 1236 | +/* riscv_lo_relocs[X] is the relocation to use when a symbol of type X |
| 1237 | + appears in a LO_SUM. It can be null if such LO_SUMs aren't valid or |
| 1238 | + if they are matched by a special .md file pattern. */ |
| 1239 | +const char *riscv_lo_relocs[NUM_SYMBOL_TYPES]; |
| 1240 | + |
| 1241 | +/* Likewise for HIGHs. */ |
| 1242 | +const char *riscv_hi_relocs[NUM_SYMBOL_TYPES]; |
| 1243 | + |
| 1244 | +/* Index R is the smallest register class that contains register R. */ |
| 1245 | +const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = { |
| 1246 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1247 | + GR_REGS, T_REGS, T_REGS, T_REGS, |
| 1248 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1249 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1250 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1251 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1252 | + GR_REGS, GR_REGS, GR_REGS, GR_REGS, |
| 1253 | + T_REGS, T_REGS, T_REGS, T_REGS, |
| 1254 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1255 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1256 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1257 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1258 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1259 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1260 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1261 | + FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
| 1262 | + FRAME_REGS, FRAME_REGS, |
| 1263 | +}; |
| 1264 | + |
| 1265 | +/* Costs to use when optimizing for size. */ |
| 1266 | +static const struct riscv_tune_info rocket_tune_info = { |
| 1267 | + {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */ |
| 1268 | + {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */ |
| 1269 | + {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */ |
| 1270 | + {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */ |
| 1271 | + {COSTS_N_INSNS (6), COSTS_N_INSNS (6)}, /* int_div */ |
| 1272 | + 1, /* issue_rate */ |
| 1273 | + 3, /* branch_cost */ |
| 1274 | + COSTS_N_INSNS (2), /* fp_to_int_cost */ |
| 1275 | + 5 /* memory_cost */ |
| 1276 | +}; |
| 1277 | + |
| 1278 | +/* Costs to use when optimizing for size. */ |
| 1279 | +static const struct riscv_tune_info optimize_size_tune_info = { |
| 1280 | + {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */ |
| 1281 | + {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_mul */ |
| 1282 | + {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_div */ |
| 1283 | + {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_mul */ |
| 1284 | + {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_div */ |
| 1285 | + 1, /* issue_rate */ |
| 1286 | + 1, /* branch_cost */ |
| 1287 | + COSTS_N_INSNS (1), /* fp_to_int_cost */ |
| 1288 | + 1 /* memory_cost */ |
| 1289 | +}; |
| 1290 | + |
| 1291 | +/* A table describing all the processors GCC knows about. */ |
| 1292 | +static const struct riscv_cpu_info riscv_cpu_info_table[] = { |
| 1293 | + /* Entries for generic ISAs. */ |
| 1294 | + { "rocket", "IMAFD", &rocket_tune_info }, |
| 1295 | +}; |
| 1296 | + |
| 1297 | +/* Return the riscv_cpu_info entry for the given name string. */ |
| 1298 | + |
| 1299 | +static const struct riscv_cpu_info * |
| 1300 | +riscv_parse_cpu (const char *cpu_string) |
| 1301 | +{ |
| 1302 | + unsigned int i; |
| 1303 | + |
| 1304 | + for (i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++) |
| 1305 | + if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0) |
| 1306 | + return riscv_cpu_info_table + i; |
| 1307 | + |
| 1308 | + error ("unknown cpu `%s'", cpu_string); |
| 1309 | + return riscv_cpu_info_table; |
| 1310 | +} |
| 1311 | + |
| 1312 | +/* Fill CODES with a sequence of rtl operations to load VALUE. |
| 1313 | + Return the number of operations needed. */ |
| 1314 | + |
| 1315 | +static int |
| 1316 | +riscv_build_integer_1 (struct riscv_integer_op *codes, HOST_WIDE_INT value, |
| 1317 | + enum machine_mode mode) |
| 1318 | +{ |
| 1319 | + HOST_WIDE_INT low_part = RISCV_CONST_LOW_PART (value); |
| 1320 | + int cost = INT_MAX, alt_cost; |
| 1321 | + struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; |
| 1322 | + |
| 1323 | + if (SMALL_OPERAND (value) || LUI_OPERAND (value)) |
| 1324 | + { |
| 1325 | + /* Simply ADDI or LUI */ |
| 1326 | + codes[0].code = UNKNOWN; |
| 1327 | + codes[0].value = value; |
| 1328 | + return 1; |
| 1329 | + } |
| 1330 | + |
| 1331 | + /* End with ADDI */ |
| 1332 | + if (low_part != 0 |
| 1333 | + && !(mode == HImode && (int16_t)(value - low_part) != (value - low_part))) |
| 1334 | + { |
| 1335 | + cost = 1 + riscv_build_integer_1 (codes, value - low_part, mode); |
| 1336 | + codes[cost-1].code = PLUS; |
| 1337 | + codes[cost-1].value = low_part; |
| 1338 | + } |
| 1339 | + |
| 1340 | + /* End with XORI */ |
| 1341 | + if (cost > 2 && (low_part < 0 || mode == HImode)) |
| 1342 | + { |
| 1343 | + alt_cost = 1 + riscv_build_integer_1 (alt_codes, value ^ low_part, mode); |
| 1344 | + alt_codes[alt_cost-1].code = XOR; |
| 1345 | + alt_codes[alt_cost-1].value = low_part; |
| 1346 | + if (alt_cost < cost) |
| 1347 | + cost = alt_cost, memcpy (codes, alt_codes, sizeof(alt_codes)); |
| 1348 | + } |
| 1349 | + |
| 1350 | + /* Eliminate trailing zeros and end with SLLI */ |
| 1351 | + if (cost > 2 && (value & 1) == 0) |
| 1352 | + { |
| 1353 | + int shift = 0; |
| 1354 | + while ((value & 1) == 0) |
| 1355 | + shift++, value >>= 1; |
| 1356 | + alt_cost = 1 + riscv_build_integer_1 (alt_codes, value, mode); |
| 1357 | + alt_codes[alt_cost-1].code = ASHIFT; |
| 1358 | + alt_codes[alt_cost-1].value = shift; |
| 1359 | + if (alt_cost < cost) |
| 1360 | + cost = alt_cost, memcpy (codes, alt_codes, sizeof(alt_codes)); |
| 1361 | + } |
| 1362 | + |
| 1363 | + gcc_assert (cost <= RISCV_MAX_INTEGER_OPS); |
| 1364 | + return cost; |
| 1365 | +} |
| 1366 | + |
| 1367 | +static int |
| 1368 | +riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value, |
| 1369 | + enum machine_mode mode) |
| 1370 | +{ |
| 1371 | + int cost = riscv_build_integer_1 (codes, value, mode); |
| 1372 | + |
| 1373 | + /* Eliminate leading zeros and end with SRLI */ |
| 1374 | + if (value > 0 && cost > 2) |
| 1375 | + { |
| 1376 | + struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; |
| 1377 | + int alt_cost, shift = 0; |
| 1378 | + HOST_WIDE_INT shifted_val; |
| 1379 | + |
| 1380 | + /* Try filling trailing bits with 1s */ |
| 1381 | + while ((value << shift) >= 0) |
| 1382 | + shift++; |
| 1383 | + shifted_val = (value << shift) | ((((HOST_WIDE_INT) 1) << shift) - 1); |
| 1384 | + alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); |
| 1385 | + alt_codes[alt_cost-1].code = LSHIFTRT; |
| 1386 | + alt_codes[alt_cost-1].value = shift; |
| 1387 | + if (alt_cost < cost) |
| 1388 | + cost = alt_cost, memcpy (codes, alt_codes, sizeof (alt_codes)); |
| 1389 | + |
| 1390 | + /* Try filling trailing bits with 0s */ |
| 1391 | + shifted_val = value << shift; |
| 1392 | + alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode); |
| 1393 | + alt_codes[alt_cost-1].code = LSHIFTRT; |
| 1394 | + alt_codes[alt_cost-1].value = shift; |
| 1395 | + if (alt_cost < cost) |
| 1396 | + cost = alt_cost, memcpy (codes, alt_codes, sizeof (alt_codes)); |
| 1397 | + } |
| 1398 | + |
| 1399 | + return cost; |
| 1400 | +} |
| 1401 | + |
| 1402 | +static int |
| 1403 | +riscv_split_integer_cost (HOST_WIDE_INT val) |
| 1404 | +{ |
| 1405 | + int cost; |
| 1406 | + int32_t loval = val, hival = (val - (int32_t)val) >> 32; |
| 1407 | + struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; |
| 1408 | + |
| 1409 | + cost = 2 + riscv_build_integer (codes, loval, VOIDmode); |
| 1410 | + if (loval != hival) |
| 1411 | + cost += riscv_build_integer (codes, hival, VOIDmode); |
| 1412 | + |
| 1413 | + return cost; |
| 1414 | +} |
| 1415 | + |
| 1416 | +static int |
| 1417 | +riscv_integer_cost (HOST_WIDE_INT val) |
| 1418 | +{ |
| 1419 | + struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; |
| 1420 | + return MIN (riscv_build_integer (codes, val, VOIDmode), |
| 1421 | + riscv_split_integer_cost (val)); |
| 1422 | +} |
| 1423 | + |
| 1424 | +/* Try to split a 64b integer into 32b parts, then reassemble. */ |
| 1425 | + |
| 1426 | +static rtx |
| 1427 | +riscv_split_integer (HOST_WIDE_INT val, enum machine_mode mode) |
| 1428 | +{ |
| 1429 | + int32_t loval = val, hival = (val - (int32_t)val) >> 32; |
| 1430 | + rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode); |
| 1431 | + |
| 1432 | + riscv_move_integer (hi, hi, hival); |
| 1433 | + riscv_move_integer (lo, lo, loval); |
| 1434 | + |
| 1435 | + hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32)); |
| 1436 | + hi = force_reg (mode, hi); |
| 1437 | + |
| 1438 | + return gen_rtx_fmt_ee (PLUS, mode, hi, lo); |
| 1439 | +} |
| 1440 | + |
| 1441 | +/* Return true if X is a thread-local symbol. */ |
| 1442 | + |
| 1443 | +static bool |
| 1444 | +riscv_tls_symbol_p (const_rtx x) |
| 1445 | +{ |
| 1446 | + return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0; |
| 1447 | +} |
| 1448 | + |
| 1449 | +static bool |
| 1450 | +riscv_symbol_binds_local_p (const_rtx x) |
| 1451 | +{ |
| 1452 | + return (SYMBOL_REF_DECL (x) |
| 1453 | + ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) |
| 1454 | + : SYMBOL_REF_LOCAL_P (x)); |
| 1455 | +} |
| 1456 | + |
| 1457 | +/* Return the method that should be used to access SYMBOL_REF or |
| 1458 | + LABEL_REF X in context CONTEXT. */ |
| 1459 | + |
| 1460 | +static enum riscv_symbol_type |
| 1461 | +riscv_classify_symbol (const_rtx x) |
| 1462 | +{ |
| 1463 | + if (riscv_tls_symbol_p (x)) |
| 1464 | + return SYMBOL_TLS; |
| 1465 | + |
| 1466 | + if (GET_CODE (x) == LABEL_REF) |
| 1467 | + { |
| 1468 | + if (LABEL_REF_NONLOCAL_P (x)) |
| 1469 | + return SYMBOL_GOT_DISP; |
| 1470 | + return SYMBOL_ABSOLUTE; |
| 1471 | + } |
| 1472 | + |
| 1473 | + gcc_assert (GET_CODE (x) == SYMBOL_REF); |
| 1474 | + |
| 1475 | + if (flag_pic && !riscv_symbol_binds_local_p (x)) |
| 1476 | + return SYMBOL_GOT_DISP; |
| 1477 | + |
| 1478 | + return SYMBOL_ABSOLUTE; |
| 1479 | +} |
| 1480 | + |
| 1481 | +/* Classify the base of symbolic expression X, given that X appears in |
| 1482 | + context CONTEXT. */ |
| 1483 | + |
| 1484 | +static enum riscv_symbol_type |
| 1485 | +riscv_classify_symbolic_expression (rtx x) |
| 1486 | +{ |
| 1487 | + rtx offset; |
| 1488 | + |
| 1489 | + split_const (x, &x, &offset); |
| 1490 | + if (UNSPEC_ADDRESS_P (x)) |
| 1491 | + return UNSPEC_ADDRESS_TYPE (x); |
| 1492 | + |
| 1493 | + return riscv_classify_symbol (x); |
| 1494 | +} |
| 1495 | + |
| 1496 | +/* Return true if X is a symbolic constant that can be used in context |
| 1497 | + CONTEXT. If it is, store the type of the symbol in *SYMBOL_TYPE. */ |
| 1498 | + |
| 1499 | +bool |
| 1500 | +riscv_symbolic_constant_p (rtx x, enum riscv_symbol_type *symbol_type) |
| 1501 | +{ |
| 1502 | + rtx offset; |
| 1503 | + |
| 1504 | + split_const (x, &x, &offset); |
| 1505 | + if (UNSPEC_ADDRESS_P (x)) |
| 1506 | + { |
| 1507 | + *symbol_type = UNSPEC_ADDRESS_TYPE (x); |
| 1508 | + x = UNSPEC_ADDRESS (x); |
| 1509 | + } |
| 1510 | + else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) |
| 1511 | + *symbol_type = riscv_classify_symbol (x); |
| 1512 | + else |
| 1513 | + return false; |
| 1514 | + |
| 1515 | + if (offset == const0_rtx) |
| 1516 | + return true; |
| 1517 | + |
| 1518 | + /* Check whether a nonzero offset is valid for the underlying |
| 1519 | + relocations. */ |
| 1520 | + switch (*symbol_type) |
| 1521 | + { |
| 1522 | + case SYMBOL_ABSOLUTE: |
| 1523 | + case SYMBOL_TLS_LE: |
| 1524 | + return (int32_t) INTVAL (offset) == INTVAL (offset); |
| 1525 | + |
| 1526 | + default: |
| 1527 | + return false; |
| 1528 | + } |
| 1529 | + gcc_unreachable (); |
| 1530 | +} |
| 1531 | + |
| 1532 | +/* Returns the number of instructions necessary to reference a symbol. */ |
| 1533 | + |
| 1534 | +static int riscv_symbol_insns (enum riscv_symbol_type type) |
| 1535 | +{ |
| 1536 | + switch (type) |
| 1537 | + { |
| 1538 | + case SYMBOL_TLS: return 0; /* Depends on the TLS model. */ |
| 1539 | + case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference itself */ |
| 1540 | + case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference itself */ |
| 1541 | + case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference itself */ |
| 1542 | + default: gcc_unreachable(); |
| 1543 | + } |
| 1544 | +} |
| 1545 | + |
| 1546 | +/* A for_each_rtx callback. Stop the search if *X references a |
| 1547 | + thread-local symbol. */ |
| 1548 | + |
| 1549 | +static int |
| 1550 | +riscv_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED) |
| 1551 | +{ |
| 1552 | + return riscv_tls_symbol_p (*x); |
| 1553 | +} |
| 1554 | + |
| 1555 | +/* Implement TARGET_LEGITIMATE_CONSTANT_P. */ |
| 1556 | + |
| 1557 | +static bool |
| 1558 | +riscv_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) |
| 1559 | +{ |
| 1560 | + return riscv_const_insns (x) > 0; |
| 1561 | +} |
| 1562 | + |
| 1563 | +/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ |
| 1564 | + |
| 1565 | +static bool |
| 1566 | +riscv_cannot_force_const_mem (enum machine_mode mode, rtx x) |
| 1567 | +{ |
| 1568 | + enum riscv_symbol_type type; |
| 1569 | + rtx base, offset; |
| 1570 | + |
| 1571 | + /* There is no assembler syntax for expressing an address-sized |
| 1572 | + high part. */ |
| 1573 | + if (GET_CODE (x) == HIGH) |
| 1574 | + return true; |
| 1575 | + |
| 1576 | + /* As an optimization, reject constants that riscv_legitimize_move |
| 1577 | + can expand inline. |
| 1578 | + |
| 1579 | + Suppose we have a multi-instruction sequence that loads constant C |
| 1580 | + into register R. If R does not get allocated a hard register, and |
| 1581 | + R is used in an operand that allows both registers and memory |
| 1582 | + references, reload will consider forcing C into memory and using |
| 1583 | + one of the instruction's memory alternatives. Returning false |
| 1584 | + here will force it to use an input reload instead. */ |
| 1585 | + if (CONST_INT_P (x) && riscv_legitimate_constant_p (mode, x)) |
| 1586 | + return true; |
| 1587 | + |
| 1588 | + split_const (x, &base, &offset); |
| 1589 | + if (riscv_symbolic_constant_p (base, &type)) |
| 1590 | + { |
| 1591 | + /* The same optimization as for CONST_INT. */ |
| 1592 | + if (SMALL_INT (offset) && riscv_symbol_insns (type) > 0) |
| 1593 | + return true; |
| 1594 | + |
| 1595 | + /* It's not worth creating additional dynamic relocations. */ |
| 1596 | + if (flag_pic) |
| 1597 | + return true; |
| 1598 | + } |
| 1599 | + |
| 1600 | + /* TLS symbols must be computed by riscv_legitimize_move. */ |
| 1601 | + if (for_each_rtx (&x, &riscv_tls_symbol_ref_1, NULL)) |
| 1602 | + return true; |
| 1603 | + |
| 1604 | + return false; |
| 1605 | +} |
| 1606 | + |
| 1607 | +/* Return true if register REGNO is a valid base register for mode MODE. |
| 1608 | + STRICT_P is true if REG_OK_STRICT is in effect. */ |
| 1609 | + |
| 1610 | +int |
| 1611 | +riscv_regno_mode_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED, |
| 1612 | + bool strict_p) |
| 1613 | +{ |
| 1614 | + if (!HARD_REGISTER_NUM_P (regno)) |
| 1615 | + { |
| 1616 | + if (!strict_p) |
| 1617 | + return true; |
| 1618 | + regno = reg_renumber[regno]; |
| 1619 | + } |
| 1620 | + |
| 1621 | + /* These fake registers will be eliminated to either the stack or |
| 1622 | + hard frame pointer, both of which are usually valid base registers. |
| 1623 | + Reload deals with the cases where the eliminated form isn't valid. */ |
| 1624 | + if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) |
| 1625 | + return true; |
| 1626 | + |
| 1627 | + return GP_REG_P (regno); |
| 1628 | +} |
| 1629 | + |
| 1630 | +/* Return true if X is a valid base register for mode MODE. |
| 1631 | + STRICT_P is true if REG_OK_STRICT is in effect. */ |
| 1632 | + |
| 1633 | +static bool |
| 1634 | +riscv_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p) |
| 1635 | +{ |
| 1636 | + if (!strict_p && GET_CODE (x) == SUBREG) |
| 1637 | + x = SUBREG_REG (x); |
| 1638 | + |
| 1639 | + return (REG_P (x) |
| 1640 | + && riscv_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); |
| 1641 | +} |
| 1642 | + |
| 1643 | +/* Return true if, for every base register BASE_REG, (plus BASE_REG X) |
| 1644 | + can address a value of mode MODE. */ |
| 1645 | + |
| 1646 | +static bool |
| 1647 | +riscv_valid_offset_p (rtx x, enum machine_mode mode) |
| 1648 | +{ |
| 1649 | + /* Check that X is a signed 12-bit number. */ |
| 1650 | + if (!const_arith_operand (x, Pmode)) |
| 1651 | + return false; |
| 1652 | + |
| 1653 | + /* We may need to split multiword moves, so make sure that every word |
| 1654 | + is accessible. */ |
| 1655 | + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD |
| 1656 | + && !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) |
| 1657 | + return false; |
| 1658 | + |
| 1659 | + return true; |
| 1660 | +} |
| 1661 | + |
| 1662 | +/* Return true if a LO_SUM can address a value of mode MODE when the |
| 1663 | + LO_SUM symbol has type SYMBOL_TYPE. */ |
| 1664 | + |
| 1665 | +static bool |
| 1666 | +riscv_valid_lo_sum_p (enum riscv_symbol_type symbol_type, enum machine_mode mode) |
| 1667 | +{ |
| 1668 | + /* Check that symbols of type SYMBOL_TYPE can be used to access values |
| 1669 | + of mode MODE. */ |
| 1670 | + if (riscv_symbol_insns (symbol_type) == 0) |
| 1671 | + return false; |
| 1672 | + |
| 1673 | + /* Check that there is a known low-part relocation. */ |
| 1674 | + if (riscv_lo_relocs[symbol_type] == NULL) |
| 1675 | + return false; |
| 1676 | + |
| 1677 | + /* We may need to split multiword moves, so make sure that each word |
| 1678 | + can be accessed without inducing a carry. This is mainly needed |
| 1679 | + for o64, which has historically only guaranteed 64-bit alignment |
| 1680 | + for 128-bit types. */ |
| 1681 | + if (GET_MODE_SIZE (mode) > UNITS_PER_WORD |
| 1682 | + && GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode)) |
| 1683 | + return false; |
| 1684 | + |
| 1685 | + return true; |
| 1686 | +} |
| 1687 | + |
| 1688 | +/* Return true if X is a valid address for machine mode MODE. If it is, |
| 1689 | + fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in |
| 1690 | + effect. */ |
| 1691 | + |
| 1692 | +static bool |
| 1693 | +riscv_classify_address (struct riscv_address_info *info, rtx x, |
| 1694 | + enum machine_mode mode, bool strict_p) |
| 1695 | +{ |
| 1696 | + switch (GET_CODE (x)) |
| 1697 | + { |
| 1698 | + case REG: |
| 1699 | + case SUBREG: |
| 1700 | + info->type = ADDRESS_REG; |
| 1701 | + info->reg = x; |
| 1702 | + info->offset = const0_rtx; |
| 1703 | + return riscv_valid_base_register_p (info->reg, mode, strict_p); |
| 1704 | + |
| 1705 | + case PLUS: |
| 1706 | + info->type = ADDRESS_REG; |
| 1707 | + info->reg = XEXP (x, 0); |
| 1708 | + info->offset = XEXP (x, 1); |
| 1709 | + return (riscv_valid_base_register_p (info->reg, mode, strict_p) |
| 1710 | + && riscv_valid_offset_p (info->offset, mode)); |
| 1711 | + |
| 1712 | + case LO_SUM: |
| 1713 | + info->type = ADDRESS_LO_SUM; |
| 1714 | + info->reg = XEXP (x, 0); |
| 1715 | + info->offset = XEXP (x, 1); |
| 1716 | + /* We have to trust the creator of the LO_SUM to do something vaguely |
| 1717 | + sane. Target-independent code that creates a LO_SUM should also |
| 1718 | + create and verify the matching HIGH. Target-independent code that |
| 1719 | + adds an offset to a LO_SUM must prove that the offset will not |
| 1720 | + induce a carry. Failure to do either of these things would be |
| 1721 | + a bug, and we are not required to check for it here. The RISCV |
| 1722 | + backend itself should only create LO_SUMs for valid symbolic |
| 1723 | + constants, with the high part being either a HIGH or a copy |
| 1724 | + of _gp. */ |
| 1725 | + info->symbol_type |
| 1726 | + = riscv_classify_symbolic_expression (info->offset); |
| 1727 | + return (riscv_valid_base_register_p (info->reg, mode, strict_p) |
| 1728 | + && riscv_valid_lo_sum_p (info->symbol_type, mode)); |
| 1729 | + |
| 1730 | + case CONST_INT: |
| 1731 | + /* Small-integer addresses don't occur very often, but they |
| 1732 | + are legitimate if $0 is a valid base register. */ |
| 1733 | + info->type = ADDRESS_CONST_INT; |
| 1734 | + return SMALL_INT (x); |
| 1735 | + |
| 1736 | + default: |
| 1737 | + return false; |
| 1738 | + } |
| 1739 | +} |
| 1740 | + |
| 1741 | +/* Implement TARGET_LEGITIMATE_ADDRESS_P. */ |
| 1742 | + |
| 1743 | +static bool |
| 1744 | +riscv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p) |
| 1745 | +{ |
| 1746 | + struct riscv_address_info addr; |
| 1747 | + |
| 1748 | + return riscv_classify_address (&addr, x, mode, strict_p); |
| 1749 | +} |
| 1750 | + |
| 1751 | +/* Return the number of instructions needed to load or store a value |
| 1752 | + of mode MODE at address X. Return 0 if X isn't valid for MODE. |
| 1753 | + Assume that multiword moves may need to be split into word moves |
| 1754 | + if MIGHT_SPLIT_P, otherwise assume that a single load or store is |
| 1755 | + enough. */ |
| 1756 | + |
| 1757 | +int |
| 1758 | +riscv_address_insns (rtx x, enum machine_mode mode, bool might_split_p) |
| 1759 | +{ |
| 1760 | + struct riscv_address_info addr; |
| 1761 | + int n = 1; |
| 1762 | + |
| 1763 | + if (!riscv_classify_address (&addr, x, mode, false)) |
| 1764 | + return 0; |
| 1765 | + |
| 1766 | + /* BLKmode is used for single unaligned loads and stores and should |
| 1767 | + not count as a multiword mode. */ |
| 1768 | + if (mode != BLKmode && might_split_p) |
| 1769 | + n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; |
| 1770 | + |
| 1771 | + if (addr.type == ADDRESS_LO_SUM) |
| 1772 | + n += riscv_symbol_insns (addr.symbol_type) - 1; |
| 1773 | + |
| 1774 | + return n; |
| 1775 | +} |
| 1776 | + |
| 1777 | +/* Return the number of instructions needed to load constant X. |
| 1778 | + Return 0 if X isn't a valid constant. */ |
| 1779 | + |
| 1780 | +int |
| 1781 | +riscv_const_insns (rtx x) |
| 1782 | +{ |
| 1783 | + enum riscv_symbol_type symbol_type; |
| 1784 | + rtx offset; |
| 1785 | + |
| 1786 | + switch (GET_CODE (x)) |
| 1787 | + { |
| 1788 | + case HIGH: |
| 1789 | + if (!riscv_symbolic_constant_p (XEXP (x, 0), &symbol_type) |
| 1790 | + || !riscv_hi_relocs[symbol_type]) |
| 1791 | + return 0; |
| 1792 | + |
| 1793 | + /* This is simply an LUI. */ |
| 1794 | + return 1; |
| 1795 | + |
| 1796 | + case CONST_INT: |
| 1797 | + { |
| 1798 | + int cost = riscv_integer_cost (INTVAL (x)); |
| 1799 | + /* Force complicated constants to memory. */ |
| 1800 | + return cost < 4 ? cost : 0; |
| 1801 | + } |
| 1802 | + |
| 1803 | + case CONST_DOUBLE: |
| 1804 | + case CONST_VECTOR: |
| 1805 | + /* Allow zeros for normal mode, where we can use x0. */ |
| 1806 | + return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; |
| 1807 | + |
| 1808 | + case CONST: |
| 1809 | + /* See if we can refer to X directly. */ |
| 1810 | + if (riscv_symbolic_constant_p (x, &symbol_type)) |
| 1811 | + return riscv_symbol_insns (symbol_type); |
| 1812 | + |
| 1813 | + /* Otherwise try splitting the constant into a base and offset. |
| 1814 | + If the offset is a 16-bit value, we can load the base address |
| 1815 | + into a register and then use (D)ADDIU to add in the offset. |
| 1816 | + If the offset is larger, we can load the base and offset |
| 1817 | + into separate registers and add them together with (D)ADDU. |
| 1818 | + However, the latter is only possible before reload; during |
| 1819 | + and after reload, we must have the option of forcing the |
| 1820 | + constant into the pool instead. */ |
| 1821 | + split_const (x, &x, &offset); |
| 1822 | + if (offset != 0) |
| 1823 | + { |
| 1824 | + int n = riscv_const_insns (x); |
| 1825 | + if (n != 0) |
| 1826 | + { |
| 1827 | + if (SMALL_INT (offset)) |
| 1828 | + return n + 1; |
| 1829 | + else if (!targetm.cannot_force_const_mem (GET_MODE (x), x)) |
| 1830 | + return n + 1 + riscv_integer_cost (INTVAL (offset)); |
| 1831 | + } |
| 1832 | + } |
| 1833 | + return 0; |
| 1834 | + |
| 1835 | + case SYMBOL_REF: |
| 1836 | + case LABEL_REF: |
| 1837 | + return riscv_symbol_insns (riscv_classify_symbol (x)); |
| 1838 | + |
| 1839 | + default: |
| 1840 | + return 0; |
| 1841 | + } |
| 1842 | +} |
| 1843 | + |
| 1844 | +/* X is a doubleword constant that can be handled by splitting it into |
| 1845 | + two words and loading each word separately. Return the number of |
| 1846 | + instructions required to do this. */ |
| 1847 | + |
| 1848 | +int |
| 1849 | +riscv_split_const_insns (rtx x) |
| 1850 | +{ |
| 1851 | + unsigned int low, high; |
| 1852 | + |
| 1853 | + low = riscv_const_insns (riscv_subword (x, false)); |
| 1854 | + high = riscv_const_insns (riscv_subword (x, true)); |
| 1855 | + gcc_assert (low > 0 && high > 0); |
| 1856 | + return low + high; |
| 1857 | +} |
| 1858 | + |
| 1859 | +/* Return the number of instructions needed to implement INSN, |
| 1860 | + given that it loads from or stores to MEM. */ |
| 1861 | + |
| 1862 | +int |
| 1863 | +riscv_load_store_insns (rtx mem, rtx insn) |
| 1864 | +{ |
| 1865 | + enum machine_mode mode; |
| 1866 | + bool might_split_p; |
| 1867 | + rtx set; |
| 1868 | + |
| 1869 | + gcc_assert (MEM_P (mem)); |
| 1870 | + mode = GET_MODE (mem); |
| 1871 | + |
| 1872 | + /* Try to prove that INSN does not need to be split. */ |
| 1873 | + might_split_p = true; |
| 1874 | + if (GET_MODE_BITSIZE (mode) == 64) |
| 1875 | + { |
| 1876 | + set = single_set (insn); |
| 1877 | + if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) |
| 1878 | + might_split_p = false; |
| 1879 | + } |
| 1880 | + |
| 1881 | + return riscv_address_insns (XEXP (mem, 0), mode, might_split_p); |
| 1882 | +} |
| 1883 | + |
| 1884 | +/* Emit a move from SRC to DEST. Assume that the move expanders can |
| 1885 | + handle all moves if !can_create_pseudo_p (). The distinction is |
| 1886 | + important because, unlike emit_move_insn, the move expanders know |
| 1887 | + how to force Pmode objects into the constant pool even when the |
| 1888 | + constant pool address is not itself legitimate. */ |
| 1889 | + |
| 1890 | +rtx |
| 1891 | +riscv_emit_move (rtx dest, rtx src) |
| 1892 | +{ |
| 1893 | + return (can_create_pseudo_p () |
| 1894 | + ? emit_move_insn (dest, src) |
| 1895 | + : emit_move_insn_1 (dest, src)); |
| 1896 | +} |
| 1897 | + |
| 1898 | +/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */ |
| 1899 | + |
| 1900 | +static void |
| 1901 | +riscv_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1) |
| 1902 | +{ |
| 1903 | + emit_insn (gen_rtx_SET (VOIDmode, target, |
| 1904 | + gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1))); |
| 1905 | +} |
| 1906 | + |
| 1907 | +/* Compute (CODE OP0 OP1) and store the result in a new register |
| 1908 | + of mode MODE. Return that new register. */ |
| 1909 | + |
| 1910 | +static rtx |
| 1911 | +riscv_force_binary (enum machine_mode mode, enum rtx_code code, rtx op0, rtx op1) |
| 1912 | +{ |
| 1913 | + rtx reg; |
| 1914 | + |
| 1915 | + reg = gen_reg_rtx (mode); |
| 1916 | + riscv_emit_binary (code, reg, op0, op1); |
| 1917 | + return reg; |
| 1918 | +} |
| 1919 | + |
| 1920 | +/* Copy VALUE to a register and return that register. If new pseudos |
| 1921 | + are allowed, copy it into a new register, otherwise use DEST. */ |
| 1922 | + |
| 1923 | +static rtx |
| 1924 | +riscv_force_temporary (rtx dest, rtx value) |
| 1925 | +{ |
| 1926 | + if (can_create_pseudo_p ()) |
| 1927 | + return force_reg (Pmode, value); |
| 1928 | + else |
| 1929 | + { |
| 1930 | + riscv_emit_move (dest, value); |
| 1931 | + return dest; |
| 1932 | + } |
| 1933 | +} |
| 1934 | + |
| 1935 | +/* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE, |
| 1936 | + then add CONST_INT OFFSET to the result. */ |
| 1937 | + |
| 1938 | +static rtx |
| 1939 | +riscv_unspec_address_offset (rtx base, rtx offset, |
| 1940 | + enum riscv_symbol_type symbol_type) |
| 1941 | +{ |
| 1942 | + base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), |
| 1943 | + UNSPEC_ADDRESS_FIRST + symbol_type); |
| 1944 | + if (offset != const0_rtx) |
| 1945 | + base = gen_rtx_PLUS (Pmode, base, offset); |
| 1946 | + return gen_rtx_CONST (Pmode, base); |
| 1947 | +} |
| 1948 | + |
| 1949 | +/* Return an UNSPEC address with underlying address ADDRESS and symbol |
| 1950 | + type SYMBOL_TYPE. */ |
| 1951 | + |
| 1952 | +rtx |
| 1953 | +riscv_unspec_address (rtx address, enum riscv_symbol_type symbol_type) |
| 1954 | +{ |
| 1955 | + rtx base, offset; |
| 1956 | + |
| 1957 | + split_const (address, &base, &offset); |
| 1958 | + return riscv_unspec_address_offset (base, offset, symbol_type); |
| 1959 | +} |
| 1960 | + |
| 1961 | +/* If OP is an UNSPEC address, return the address to which it refers, |
| 1962 | + otherwise return OP itself. */ |
| 1963 | + |
| 1964 | +static rtx |
| 1965 | +riscv_strip_unspec_address (rtx op) |
| 1966 | +{ |
| 1967 | + rtx base, offset; |
| 1968 | + |
| 1969 | + split_const (op, &base, &offset); |
| 1970 | + if (UNSPEC_ADDRESS_P (base)) |
| 1971 | + op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset)); |
| 1972 | + return op; |
| 1973 | +} |
| 1974 | + |
| 1975 | +/* If riscv_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the |
| 1976 | + high part to BASE and return the result. Just return BASE otherwise. |
| 1977 | + TEMP is as for riscv_force_temporary. |
| 1978 | + |
| 1979 | + The returned expression can be used as the first operand to a LO_SUM. */ |
| 1980 | + |
| 1981 | +static rtx |
| 1982 | +riscv_unspec_offset_high (rtx temp, rtx addr, enum riscv_symbol_type symbol_type) |
| 1983 | +{ |
| 1984 | + addr = gen_rtx_HIGH (Pmode, riscv_unspec_address (addr, symbol_type)); |
| 1985 | + return riscv_force_temporary (temp, addr); |
| 1986 | +} |
| 1987 | + |
| 1988 | +/* Load an entry from the GOT. */ |
| 1989 | +static rtx riscv_got_load_tls_gd(rtx dest, rtx sym) |
| 1990 | +{ |
| 1991 | + return (Pmode == DImode ? gen_got_load_tls_gddi(dest, sym) : gen_got_load_tls_gdsi(dest, sym)); |
| 1992 | +} |
| 1993 | + |
| 1994 | +static rtx riscv_got_load_tls_ie(rtx dest, rtx sym) |
| 1995 | +{ |
| 1996 | + return (Pmode == DImode ? gen_got_load_tls_iedi(dest, sym) : gen_got_load_tls_iesi(dest, sym)); |
| 1997 | +} |
| 1998 | + |
| 1999 | +static rtx riscv_tls_add_tp_le(rtx dest, rtx base, rtx sym) |
| 2000 | +{ |
| 2001 | + rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); |
| 2002 | + return (Pmode == DImode ? gen_tls_add_tp_ledi(dest, base, tp, sym) : gen_tls_add_tp_lesi(dest, base, tp, sym)); |
| 2003 | +} |
| 2004 | + |
| 2005 | +/* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise |
| 2006 | + it appears in a MEM of that mode. Return true if ADDR is a legitimate |
| 2007 | + constant in that context and can be split into high and low parts. |
| 2008 | + If so, and if LOW_OUT is nonnull, emit the high part and store the |
| 2009 | + low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise. |
| 2010 | + |
| 2011 | + TEMP is as for riscv_force_temporary and is used to load the high |
| 2012 | + part into a register. |
| 2013 | + |
| 2014 | + When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be |
| 2015 | + a legitimize SET_SRC for an .md pattern, otherwise the low part |
| 2016 | + is guaranteed to be a legitimate address for mode MODE. */ |
| 2017 | + |
| 2018 | +bool |
| 2019 | +riscv_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *low_out) |
| 2020 | +{ |
| 2021 | + enum riscv_symbol_type symbol_type; |
| 2022 | + rtx high; |
| 2023 | + |
| 2024 | + if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE) |
| 2025 | + || !riscv_symbolic_constant_p (addr, &symbol_type) |
| 2026 | + || riscv_symbol_insns (symbol_type) == 0 |
| 2027 | + || !riscv_hi_relocs[symbol_type]) |
| 2028 | + return false; |
| 2029 | + |
| 2030 | + if (low_out) |
| 2031 | + { |
| 2032 | + switch (symbol_type) |
| 2033 | + { |
| 2034 | + case SYMBOL_ABSOLUTE: |
| 2035 | + high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); |
| 2036 | + high = riscv_force_temporary (temp, high); |
| 2037 | + *low_out = gen_rtx_LO_SUM (Pmode, high, addr); |
| 2038 | + break; |
| 2039 | + |
| 2040 | + default: |
| 2041 | + gcc_unreachable (); |
| 2042 | + } |
| 2043 | + } |
| 2044 | + |
| 2045 | + return true; |
| 2046 | +} |
| 2047 | + |
| 2048 | +/* Return a legitimate address for REG + OFFSET. TEMP is as for |
| 2049 | + riscv_force_temporary; it is only needed when OFFSET is not a |
| 2050 | + SMALL_OPERAND. */ |
| 2051 | + |
| 2052 | +static rtx |
| 2053 | +riscv_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) |
| 2054 | +{ |
| 2055 | + if (!SMALL_OPERAND (offset)) |
| 2056 | + { |
| 2057 | + rtx high; |
| 2058 | + |
| 2059 | + /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. |
| 2060 | + The addition inside the macro CONST_HIGH_PART may cause an |
| 2061 | + overflow, so we need to force a sign-extension check. */ |
| 2062 | + high = gen_int_mode (RISCV_CONST_HIGH_PART (offset), Pmode); |
| 2063 | + offset = RISCV_CONST_LOW_PART (offset); |
| 2064 | + high = riscv_force_temporary (temp, high); |
| 2065 | + reg = riscv_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); |
| 2066 | + } |
| 2067 | + return plus_constant (Pmode, reg, offset); |
| 2068 | +} |
| 2069 | + |
| 2070 | +/* The __tls_get_attr symbol. */ |
| 2071 | +static GTY(()) rtx riscv_tls_symbol; |
| 2072 | + |
| 2073 | +/* Return an instruction sequence that calls __tls_get_addr. SYM is |
| 2074 | + the TLS symbol we are referencing and TYPE is the symbol type to use |
| 2075 | + (either global dynamic or local dynamic). RESULT is an RTX for the |
| 2076 | + return value location. */ |
| 2077 | + |
| 2078 | +static rtx |
| 2079 | +riscv_call_tls_get_addr (rtx sym, rtx result) |
| 2080 | +{ |
| 2081 | + rtx insn, a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); |
| 2082 | + |
| 2083 | + if (!riscv_tls_symbol) |
| 2084 | + riscv_tls_symbol = init_one_libfunc ("__tls_get_addr"); |
| 2085 | + |
| 2086 | + start_sequence (); |
| 2087 | + |
| 2088 | + emit_insn (riscv_got_load_tls_gd (a0, sym)); |
| 2089 | + insn = riscv_expand_call (false, result, riscv_tls_symbol, const0_rtx); |
| 2090 | + RTL_CONST_CALL_P (insn) = 1; |
| 2091 | + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); |
| 2092 | + insn = get_insns (); |
| 2093 | + |
| 2094 | + end_sequence (); |
| 2095 | + |
| 2096 | + return insn; |
| 2097 | +} |
| 2098 | + |
| 2099 | +/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return |
| 2100 | + its address. The return value will be both a valid address and a valid |
| 2101 | + SET_SRC (either a REG or a LO_SUM). */ |
| 2102 | + |
| 2103 | +static rtx |
| 2104 | +riscv_legitimize_tls_address (rtx loc) |
| 2105 | +{ |
| 2106 | + rtx dest, insn, tp, tmp1; |
| 2107 | + enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); |
| 2108 | + |
| 2109 | + /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE. */ |
| 2110 | + if (!flag_pic) |
| 2111 | + model = TLS_MODEL_LOCAL_EXEC; |
| 2112 | + |
| 2113 | + switch (model) |
| 2114 | + { |
| 2115 | + case TLS_MODEL_LOCAL_DYNAMIC: |
| 2116 | + /* Rely on section anchors for the optimization that LDM TLS |
| 2117 | + provides. The anchor's address is loaded with GD TLS. */ |
| 2118 | + case TLS_MODEL_GLOBAL_DYNAMIC: |
| 2119 | + tmp1 = gen_rtx_REG (Pmode, GP_RETURN); |
| 2120 | + insn = riscv_call_tls_get_addr (loc, tmp1); |
| 2121 | + dest = gen_reg_rtx (Pmode); |
| 2122 | + emit_libcall_block (insn, dest, tmp1, loc); |
| 2123 | + break; |
| 2124 | + |
| 2125 | + case TLS_MODEL_INITIAL_EXEC: |
| 2126 | + /* la.tls.ie; tp-relative add */ |
| 2127 | + tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); |
| 2128 | + tmp1 = gen_reg_rtx (Pmode); |
| 2129 | + emit_insn (riscv_got_load_tls_ie (tmp1, loc)); |
| 2130 | + dest = gen_reg_rtx (Pmode); |
| 2131 | + emit_insn (gen_add3_insn (dest, tmp1, tp)); |
| 2132 | + break; |
| 2133 | + |
| 2134 | + case TLS_MODEL_LOCAL_EXEC: |
| 2135 | + tmp1 = riscv_unspec_offset_high (NULL, loc, SYMBOL_TLS_LE); |
| 2136 | + dest = gen_reg_rtx (Pmode); |
| 2137 | + emit_insn (riscv_tls_add_tp_le (dest, tmp1, loc)); |
| 2138 | + dest = gen_rtx_LO_SUM (Pmode, dest, |
| 2139 | + riscv_unspec_address (loc, SYMBOL_TLS_LE)); |
| 2140 | + break; |
| 2141 | + |
| 2142 | + default: |
| 2143 | + gcc_unreachable (); |
| 2144 | + } |
| 2145 | + return dest; |
| 2146 | +} |
| 2147 | + |
| 2148 | +/* If X is not a valid address for mode MODE, force it into a register. */ |
| 2149 | + |
| 2150 | +static rtx |
| 2151 | +riscv_force_address (rtx x, enum machine_mode mode) |
| 2152 | +{ |
| 2153 | + if (!riscv_legitimate_address_p (mode, x, false)) |
| 2154 | + x = force_reg (Pmode, x); |
| 2155 | + return x; |
| 2156 | +} |
| 2157 | + |
| 2158 | +/* This function is used to implement LEGITIMIZE_ADDRESS. If X can |
| 2159 | + be legitimized in a way that the generic machinery might not expect, |
| 2160 | + return a new address, otherwise return NULL. MODE is the mode of |
| 2161 | + the memory being accessed. */ |
| 2162 | + |
| 2163 | +static rtx |
| 2164 | +riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, |
| 2165 | + enum machine_mode mode) |
| 2166 | +{ |
| 2167 | + rtx addr; |
| 2168 | + |
| 2169 | + if (riscv_tls_symbol_p (x)) |
| 2170 | + return riscv_legitimize_tls_address (x); |
| 2171 | + |
| 2172 | + /* See if the address can split into a high part and a LO_SUM. */ |
| 2173 | + if (riscv_split_symbol (NULL, x, mode, &addr)) |
| 2174 | + return riscv_force_address (addr, mode); |
| 2175 | + |
| 2176 | + /* Handle BASE + OFFSET using riscv_add_offset. */ |
| 2177 | + if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)) |
| 2178 | + && INTVAL (XEXP (x, 1)) != 0) |
| 2179 | + { |
| 2180 | + rtx base = XEXP (x, 0); |
| 2181 | + HOST_WIDE_INT offset = INTVAL (XEXP (x, 1)); |
| 2182 | + |
| 2183 | + if (!riscv_valid_base_register_p (base, mode, false)) |
| 2184 | + base = copy_to_mode_reg (Pmode, base); |
| 2185 | + addr = riscv_add_offset (NULL, base, offset); |
| 2186 | + return riscv_force_address (addr, mode); |
| 2187 | + } |
| 2188 | + |
| 2189 | + return x; |
| 2190 | +} |
| 2191 | + |
| 2192 | +/* Load VALUE into DEST. TEMP is as for riscv_force_temporary. */ |
| 2193 | + |
| 2194 | +void |
| 2195 | +riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) |
| 2196 | +{ |
| 2197 | + struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS]; |
| 2198 | + enum machine_mode mode; |
| 2199 | + int i, num_ops; |
| 2200 | + rtx x; |
| 2201 | + |
| 2202 | + mode = GET_MODE (dest); |
| 2203 | + num_ops = riscv_build_integer (codes, value, mode); |
| 2204 | + |
| 2205 | + if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */ |
| 2206 | + && num_ops >= riscv_split_integer_cost (value)) |
| 2207 | + x = riscv_split_integer (value, mode); |
| 2208 | + else |
| 2209 | + { |
| 2210 | + /* Apply each binary operation to X. */ |
| 2211 | + x = GEN_INT (codes[0].value); |
| 2212 | + |
| 2213 | + for (i = 1; i < num_ops; i++) |
| 2214 | + { |
| 2215 | + if (!can_create_pseudo_p ()) |
| 2216 | + { |
| 2217 | + emit_insn (gen_rtx_SET (VOIDmode, temp, x)); |
| 2218 | + x = temp; |
| 2219 | + } |
| 2220 | + else |
| 2221 | + x = force_reg (mode, x); |
| 2222 | + |
| 2223 | + x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); |
| 2224 | + } |
| 2225 | + } |
| 2226 | + |
| 2227 | + emit_insn (gen_rtx_SET (VOIDmode, dest, x)); |
| 2228 | +} |
| 2229 | + |
| 2230 | +/* Subroutine of riscv_legitimize_move. Move constant SRC into register |
| 2231 | + DEST given that SRC satisfies immediate_operand but doesn't satisfy |
| 2232 | + move_operand. */ |
| 2233 | + |
| 2234 | +static void |
| 2235 | +riscv_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) |
| 2236 | +{ |
| 2237 | + rtx base, offset; |
| 2238 | + |
| 2239 | + /* Split moves of big integers into smaller pieces. */ |
| 2240 | + if (splittable_const_int_operand (src, mode)) |
| 2241 | + { |
| 2242 | + riscv_move_integer (dest, dest, INTVAL (src)); |
| 2243 | + return; |
| 2244 | + } |
| 2245 | + |
| 2246 | + /* Split moves of symbolic constants into high/low pairs. */ |
| 2247 | + if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src)) |
| 2248 | + { |
| 2249 | + emit_insn (gen_rtx_SET (VOIDmode, dest, src)); |
| 2250 | + return; |
| 2251 | + } |
| 2252 | + |
| 2253 | + /* Generate the appropriate access sequences for TLS symbols. */ |
| 2254 | + if (riscv_tls_symbol_p (src)) |
| 2255 | + { |
| 2256 | + riscv_emit_move (dest, riscv_legitimize_tls_address (src)); |
| 2257 | + return; |
| 2258 | + } |
| 2259 | + |
| 2260 | + /* If we have (const (plus symbol offset)), and that expression cannot |
| 2261 | + be forced into memory, load the symbol first and add in the offset. Also |
| 2262 | + prefer to do this even if the constant _can_ be forced into memory, as it |
| 2263 | + usually produces better code. */ |
| 2264 | + split_const (src, &base, &offset); |
| 2265 | + if (offset != const0_rtx |
| 2266 | + && (targetm.cannot_force_const_mem (mode, src) || can_create_pseudo_p ())) |
| 2267 | + { |
| 2268 | + base = riscv_force_temporary (dest, base); |
| 2269 | + riscv_emit_move (dest, riscv_add_offset (NULL, base, INTVAL (offset))); |
| 2270 | + return; |
| 2271 | + } |
| 2272 | + |
| 2273 | + src = force_const_mem (mode, src); |
| 2274 | + |
| 2275 | + /* When using explicit relocs, constant pool references are sometimes |
| 2276 | + not legitimate addresses. */ |
| 2277 | + riscv_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0)); |
| 2278 | + riscv_emit_move (dest, src); |
| 2279 | +} |
| 2280 | + |
| 2281 | +/* If (set DEST SRC) is not a valid move instruction, emit an equivalent |
| 2282 | + sequence that is valid. */ |
| 2283 | + |
| 2284 | +bool |
| 2285 | +riscv_legitimize_move (enum machine_mode mode, rtx dest, rtx src) |
| 2286 | +{ |
| 2287 | + if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) |
| 2288 | + { |
| 2289 | + riscv_emit_move (dest, force_reg (mode, src)); |
| 2290 | + return true; |
| 2291 | + } |
| 2292 | + |
| 2293 | + /* We need to deal with constants that would be legitimate |
| 2294 | + immediate_operands but aren't legitimate move_operands. */ |
| 2295 | + if (CONSTANT_P (src) && !move_operand (src, mode)) |
| 2296 | + { |
| 2297 | + riscv_legitimize_const_move (mode, dest, src); |
| 2298 | + set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); |
| 2299 | + return true; |
| 2300 | + } |
| 2301 | + return false; |
| 2302 | +} |
| 2303 | + |
| 2304 | +/* Return true if there is an instruction that implements CODE and accepts |
| 2305 | + X as an immediate operand. */ |
| 2306 | + |
| 2307 | +static int |
| 2308 | +riscv_immediate_operand_p (int code, HOST_WIDE_INT x) |
| 2309 | +{ |
| 2310 | + switch (code) |
| 2311 | + { |
| 2312 | + case ASHIFT: |
| 2313 | + case ASHIFTRT: |
| 2314 | + case LSHIFTRT: |
| 2315 | + /* All shift counts are truncated to a valid constant. */ |
| 2316 | + return true; |
| 2317 | + |
| 2318 | + case AND: |
| 2319 | + case IOR: |
| 2320 | + case XOR: |
| 2321 | + case PLUS: |
| 2322 | + case LT: |
| 2323 | + case LTU: |
| 2324 | + /* These instructions take 12-bit signed immediates. */ |
| 2325 | + return SMALL_OPERAND (x); |
| 2326 | + |
| 2327 | + case LE: |
| 2328 | + /* We add 1 to the immediate and use SLT. */ |
| 2329 | + return SMALL_OPERAND (x + 1); |
| 2330 | + |
| 2331 | + case LEU: |
| 2332 | + /* Likewise SLTU, but reject the always-true case. */ |
| 2333 | + return SMALL_OPERAND (x + 1) && x + 1 != 0; |
| 2334 | + |
| 2335 | + case GE: |
| 2336 | + case GEU: |
| 2337 | + /* We can emulate an immediate of 1 by using GT/GTU against x0. */ |
| 2338 | + return x == 1; |
| 2339 | + |
| 2340 | + default: |
| 2341 | + /* By default assume that x0 can be used for 0. */ |
| 2342 | + return x == 0; |
| 2343 | + } |
| 2344 | +} |
| 2345 | + |
| 2346 | +/* Return the cost of binary operation X, given that the instruction |
| 2347 | + sequence for a word-sized or smaller operation takes SIGNLE_INSNS |
| 2348 | + instructions and that the sequence of a double-word operation takes |
| 2349 | + DOUBLE_INSNS instructions. */ |
| 2350 | + |
| 2351 | +static int |
| 2352 | +riscv_binary_cost (rtx x, int single_insns, int double_insns) |
| 2353 | +{ |
| 2354 | + if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2) |
| 2355 | + return COSTS_N_INSNS (double_insns); |
| 2356 | + return COSTS_N_INSNS (single_insns); |
| 2357 | +} |
| 2358 | + |
| 2359 | +/* Return the cost of sign-extending OP to mode MODE, not including the |
| 2360 | + cost of OP itself. */ |
| 2361 | + |
| 2362 | +static int |
| 2363 | +riscv_sign_extend_cost (enum machine_mode mode, rtx op) |
| 2364 | +{ |
| 2365 | + if (MEM_P (op)) |
| 2366 | + /* Extended loads are as cheap as unextended ones. */ |
| 2367 | + return 0; |
| 2368 | + |
| 2369 | + if (TARGET_64BIT && mode == DImode && GET_MODE (op) == SImode) |
| 2370 | + /* A sign extension from SImode to DImode in 64-bit mode is free. */ |
| 2371 | + return 0; |
| 2372 | + |
| 2373 | + /* We need to use a shift left and a shift right. */ |
| 2374 | + return COSTS_N_INSNS (2); |
| 2375 | +} |
| 2376 | + |
| 2377 | +/* Return the cost of zero-extending OP to mode MODE, not including the |
| 2378 | + cost of OP itself. */ |
| 2379 | + |
| 2380 | +static int |
| 2381 | +riscv_zero_extend_cost (enum machine_mode mode, rtx op) |
| 2382 | +{ |
| 2383 | + if (MEM_P (op)) |
| 2384 | + /* Extended loads are as cheap as unextended ones. */ |
| 2385 | + return 0; |
| 2386 | + |
| 2387 | + if ((TARGET_64BIT && mode == DImode && GET_MODE (op) == SImode) || |
| 2388 | + ((mode == DImode || mode == SImode) && GET_MODE (op) == HImode)) |
| 2389 | + /* We need a shift left by 32 bits and a shift right by 32 bits. */ |
| 2390 | + return COSTS_N_INSNS (2); |
| 2391 | + |
| 2392 | + /* We can use ANDI. */ |
| 2393 | + return COSTS_N_INSNS (1); |
| 2394 | +} |
| 2395 | + |
| 2396 | +/* Implement TARGET_RTX_COSTS. */ |
| 2397 | + |
| 2398 | +static bool |
| 2399 | +riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, |
| 2400 | + int *total, bool speed) |
| 2401 | +{ |
| 2402 | + enum machine_mode mode = GET_MODE (x); |
| 2403 | + bool float_mode_p = FLOAT_MODE_P (mode); |
| 2404 | + int cost; |
| 2405 | + |
| 2406 | + switch (code) |
| 2407 | + { |
| 2408 | + case CONST_INT: |
| 2409 | + if (riscv_immediate_operand_p (outer_code, INTVAL (x))) |
| 2410 | + { |
| 2411 | + *total = 0; |
| 2412 | + return true; |
| 2413 | + } |
| 2414 | + /* Fall through. */ |
| 2415 | + |
| 2416 | + case SYMBOL_REF: |
| 2417 | + case LABEL_REF: |
| 2418 | + case CONST_DOUBLE: |
| 2419 | + case CONST: |
| 2420 | + if (speed) |
| 2421 | + *total = 1; |
| 2422 | + else if ((cost = riscv_const_insns (x)) > 0) |
| 2423 | + *total = COSTS_N_INSNS (cost); |
| 2424 | + else /* The instruction will be fetched from the constant pool. */ |
| 2425 | + *total = COSTS_N_INSNS (riscv_symbol_insns (SYMBOL_ABSOLUTE)); |
| 2426 | + return true; |
| 2427 | + |
| 2428 | + case MEM: |
| 2429 | + /* If the address is legitimate, return the number of |
| 2430 | + instructions it needs. */ |
| 2431 | + if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0) |
| 2432 | + { |
| 2433 | + *total = COSTS_N_INSNS (cost + tune_info->memory_cost); |
| 2434 | + return true; |
| 2435 | + } |
| 2436 | + /* Otherwise use the default handling. */ |
| 2437 | + return false; |
| 2438 | + |
| 2439 | + case NOT: |
| 2440 | + *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1); |
| 2441 | + return false; |
| 2442 | + |
| 2443 | + case AND: |
| 2444 | + case IOR: |
| 2445 | + case XOR: |
| 2446 | + /* Double-word operations use two single-word operations. */ |
| 2447 | + *total = riscv_binary_cost (x, 1, 2); |
| 2448 | + return false; |
| 2449 | + |
| 2450 | + case ASHIFT: |
| 2451 | + case ASHIFTRT: |
| 2452 | + case LSHIFTRT: |
| 2453 | + *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9); |
| 2454 | + return false; |
| 2455 | + |
| 2456 | + case ABS: |
| 2457 | + *total = COSTS_N_INSNS (float_mode_p ? 1 : 3); |
| 2458 | + return false; |
| 2459 | + |
| 2460 | + case LO_SUM: |
| 2461 | + *total = set_src_cost (XEXP (x, 0), speed); |
| 2462 | + return true; |
| 2463 | + |
| 2464 | + case LT: |
| 2465 | + case LTU: |
| 2466 | + case LE: |
| 2467 | + case LEU: |
| 2468 | + case GT: |
| 2469 | + case GTU: |
| 2470 | + case GE: |
| 2471 | + case GEU: |
| 2472 | + case EQ: |
| 2473 | + case NE: |
| 2474 | + case UNORDERED: |
| 2475 | + case LTGT: |
| 2476 | + /* Branch comparisons have VOIDmode, so use the first operand's |
| 2477 | + mode instead. */ |
| 2478 | + mode = GET_MODE (XEXP (x, 0)); |
| 2479 | + if (float_mode_p) |
| 2480 | + *total = tune_info->fp_add[mode == DFmode]; |
| 2481 | + else |
| 2482 | + *total = riscv_binary_cost (x, 1, 3); |
| 2483 | + return false; |
| 2484 | + |
| 2485 | + case MINUS: |
| 2486 | + if (float_mode_p |
| 2487 | + && !HONOR_NANS (mode) |
| 2488 | + && !HONOR_SIGNED_ZEROS (mode)) |
| 2489 | + { |
| 2490 | + /* See if we can use NMADD or NMSUB. See riscv.md for the |
| 2491 | + associated patterns. */ |
| 2492 | + rtx op0 = XEXP (x, 0); |
| 2493 | + rtx op1 = XEXP (x, 1); |
| 2494 | + if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG) |
| 2495 | + { |
| 2496 | + *total = (tune_info->fp_mul[mode == DFmode] |
| 2497 | + + set_src_cost (XEXP (XEXP (op0, 0), 0), speed) |
| 2498 | + + set_src_cost (XEXP (op0, 1), speed) |
| 2499 | + + set_src_cost (op1, speed)); |
| 2500 | + return true; |
| 2501 | + } |
| 2502 | + if (GET_CODE (op1) == MULT) |
| 2503 | + { |
| 2504 | + *total = (tune_info->fp_mul[mode == DFmode] |
| 2505 | + + set_src_cost (op0, speed) |
| 2506 | + + set_src_cost (XEXP (op1, 0), speed) |
| 2507 | + + set_src_cost (XEXP (op1, 1), speed)); |
| 2508 | + return true; |
| 2509 | + } |
| 2510 | + } |
| 2511 | + /* Fall through. */ |
| 2512 | + |
| 2513 | + case PLUS: |
| 2514 | + if (float_mode_p) |
| 2515 | + *total = tune_info->fp_add[mode == DFmode]; |
| 2516 | + else |
| 2517 | + *total = riscv_binary_cost (x, 1, 4); |
| 2518 | + return false; |
| 2519 | + |
| 2520 | + case NEG: |
| 2521 | + if (float_mode_p |
| 2522 | + && !HONOR_NANS (mode) |
| 2523 | + && HONOR_SIGNED_ZEROS (mode)) |
| 2524 | + { |
| 2525 | + /* See if we can use NMADD or NMSUB. See riscv.md for the |
| 2526 | + associated patterns. */ |
| 2527 | + rtx op = XEXP (x, 0); |
| 2528 | + if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS) |
| 2529 | + && GET_CODE (XEXP (op, 0)) == MULT) |
| 2530 | + { |
| 2531 | + *total = (tune_info->fp_mul[mode == DFmode] |
| 2532 | + + set_src_cost (XEXP (XEXP (op, 0), 0), speed) |
| 2533 | + + set_src_cost (XEXP (XEXP (op, 0), 1), speed) |
| 2534 | + + set_src_cost (XEXP (op, 1), speed)); |
| 2535 | + return true; |
| 2536 | + } |
| 2537 | + } |
| 2538 | + |
| 2539 | + if (float_mode_p) |
| 2540 | + *total = tune_info->fp_add[mode == DFmode]; |
| 2541 | + else |
| 2542 | + *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); |
| 2543 | + return false; |
| 2544 | + |
| 2545 | + case MULT: |
| 2546 | + if (float_mode_p) |
| 2547 | + *total = tune_info->fp_mul[mode == DFmode]; |
| 2548 | + else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) |
| 2549 | + *total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2); |
| 2550 | + else if (!speed) |
| 2551 | + *total = COSTS_N_INSNS (1); |
| 2552 | + else |
| 2553 | + *total = tune_info->int_mul[mode == DImode]; |
| 2554 | + return false; |
| 2555 | + |
| 2556 | + case DIV: |
| 2557 | + case SQRT: |
| 2558 | + case MOD: |
| 2559 | + if (float_mode_p) |
| 2560 | + { |
| 2561 | + *total = tune_info->fp_div[mode == DFmode]; |
| 2562 | + return false; |
| 2563 | + } |
| 2564 | + /* Fall through. */ |
| 2565 | + |
| 2566 | + case UDIV: |
| 2567 | + case UMOD: |
| 2568 | + if (speed) |
| 2569 | + *total = tune_info->int_div[mode == DImode]; |
| 2570 | + else |
| 2571 | + *total = COSTS_N_INSNS (1); |
| 2572 | + return false; |
| 2573 | + |
| 2574 | + case SIGN_EXTEND: |
| 2575 | + *total = riscv_sign_extend_cost (mode, XEXP (x, 0)); |
| 2576 | + return false; |
| 2577 | + |
| 2578 | + case ZERO_EXTEND: |
| 2579 | + *total = riscv_zero_extend_cost (mode, XEXP (x, 0)); |
| 2580 | + return false; |
| 2581 | + |
| 2582 | + case FLOAT: |
| 2583 | + case UNSIGNED_FLOAT: |
| 2584 | + case FIX: |
| 2585 | + case FLOAT_EXTEND: |
| 2586 | + case FLOAT_TRUNCATE: |
| 2587 | + *total = tune_info->fp_add[mode == DFmode]; |
| 2588 | + return false; |
| 2589 | + |
| 2590 | + default: |
| 2591 | + return false; |
| 2592 | + } |
| 2593 | +} |
| 2594 | + |
| 2595 | +/* Implement TARGET_ADDRESS_COST. */ |
| 2596 | + |
| 2597 | +static int |
| 2598 | +riscv_address_cost (rtx addr, enum machine_mode mode, |
| 2599 | + addr_space_t as ATTRIBUTE_UNUSED, |
| 2600 | + bool speed ATTRIBUTE_UNUSED) |
| 2601 | +{ |
| 2602 | + return riscv_address_insns (addr, mode, false); |
| 2603 | +} |
| 2604 | + |
| 2605 | +/* Return one word of double-word value OP. HIGH_P is true to select the |
| 2606 | + high part or false to select the low part. */ |
| 2607 | + |
| 2608 | +rtx |
| 2609 | +riscv_subword (rtx op, bool high_p) |
| 2610 | +{ |
| 2611 | + unsigned int byte; |
| 2612 | + enum machine_mode mode; |
| 2613 | + |
| 2614 | + mode = GET_MODE (op); |
| 2615 | + if (mode == VOIDmode) |
| 2616 | + mode = TARGET_64BIT ? TImode : DImode; |
| 2617 | + |
| 2618 | + byte = high_p ? UNITS_PER_WORD : 0; |
| 2619 | + |
| 2620 | + if (FP_REG_RTX_P (op)) |
| 2621 | + return gen_rtx_REG (word_mode, REGNO (op) + high_p); |
| 2622 | + |
| 2623 | + if (MEM_P (op)) |
| 2624 | + return adjust_address (op, word_mode, byte); |
| 2625 | + |
| 2626 | + return simplify_gen_subreg (word_mode, op, mode, byte); |
| 2627 | +} |
| 2628 | + |
| 2629 | +/* Return true if a 64-bit move from SRC to DEST should be split into two. */ |
| 2630 | + |
| 2631 | +bool |
| 2632 | +riscv_split_64bit_move_p (rtx dest, rtx src) |
| 2633 | +{ |
| 2634 | + /* All 64b moves are legal in 64b mode. All 64b FPR <-> FPR and |
| 2635 | + FPR <-> MEM moves are legal in 32b mode, too. Although |
| 2636 | + FPR <-> GPR moves are not available in general in 32b mode, |
| 2637 | + we can at least load 0 into an FPR with fcvt.d.w fpr, x0. */ |
| 2638 | + return !(TARGET_64BIT |
| 2639 | + || (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) |
| 2640 | + || (FP_REG_RTX_P (dest) && MEM_P (src)) |
| 2641 | + || (FP_REG_RTX_P (src) && MEM_P (dest)) |
| 2642 | + || (FP_REG_RTX_P(dest) && src == CONST0_RTX(GET_MODE(src)))); |
| 2643 | +} |
| 2644 | + |
| 2645 | +/* Split a doubleword move from SRC to DEST. On 32-bit targets, |
| 2646 | + this function handles 64-bit moves for which riscv_split_64bit_move_p |
| 2647 | + holds. For 64-bit targets, this function handles 128-bit moves. */ |
| 2648 | + |
| 2649 | +void |
| 2650 | +riscv_split_doubleword_move (rtx dest, rtx src) |
| 2651 | +{ |
| 2652 | + rtx low_dest; |
| 2653 | + |
| 2654 | + /* The operation can be split into two normal moves. Decide in |
| 2655 | + which order to do them. */ |
| 2656 | + low_dest = riscv_subword (dest, false); |
| 2657 | + if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src)) |
| 2658 | + { |
| 2659 | + riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); |
| 2660 | + riscv_emit_move (low_dest, riscv_subword (src, false)); |
| 2661 | + } |
| 2662 | + else |
| 2663 | + { |
| 2664 | + riscv_emit_move (low_dest, riscv_subword (src, false)); |
| 2665 | + riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true)); |
| 2666 | + } |
| 2667 | +} |
| 2668 | + |
| 2669 | +/* Return the appropriate instructions to move SRC into DEST. Assume |
| 2670 | + that SRC is operand 1 and DEST is operand 0. */ |
| 2671 | + |
| 2672 | +const char * |
| 2673 | +riscv_output_move (rtx dest, rtx src) |
| 2674 | +{ |
| 2675 | + enum rtx_code dest_code, src_code; |
| 2676 | + enum machine_mode mode; |
| 2677 | + bool dbl_p; |
| 2678 | + |
| 2679 | + dest_code = GET_CODE (dest); |
| 2680 | + src_code = GET_CODE (src); |
| 2681 | + mode = GET_MODE (dest); |
| 2682 | + dbl_p = (GET_MODE_SIZE (mode) == 8); |
| 2683 | + |
| 2684 | + if (dbl_p && riscv_split_64bit_move_p (dest, src)) |
| 2685 | + return "#"; |
| 2686 | + |
| 2687 | + if ((src_code == REG && GP_REG_P (REGNO (src))) |
| 2688 | + || (src == CONST0_RTX (mode))) |
| 2689 | + { |
| 2690 | + if (dest_code == REG) |
| 2691 | + { |
| 2692 | + if (GP_REG_P (REGNO (dest))) |
| 2693 | + return "move\t%0,%z1"; |
| 2694 | + |
| 2695 | + if (FP_REG_P (REGNO (dest))) |
| 2696 | + { |
| 2697 | + if (!dbl_p) |
| 2698 | + return "fmv.s.x\t%0,%z1"; |
| 2699 | + if (TARGET_64BIT) |
| 2700 | + return "fmv.d.x\t%0,%z1"; |
| 2701 | + /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ |
| 2702 | + gcc_assert (src == CONST0_RTX (mode)); |
| 2703 | + return "fcvt.d.w\t%0,x0"; |
| 2704 | + } |
| 2705 | + } |
| 2706 | + if (dest_code == MEM) |
| 2707 | + switch (GET_MODE_SIZE (mode)) |
| 2708 | + { |
| 2709 | + case 1: return "sb\t%z1,%0"; |
| 2710 | + case 2: return "sh\t%z1,%0"; |
| 2711 | + case 4: return "sw\t%z1,%0"; |
| 2712 | + case 8: return "sd\t%z1,%0"; |
| 2713 | + } |
| 2714 | + } |
| 2715 | + if (dest_code == REG && GP_REG_P (REGNO (dest))) |
| 2716 | + { |
| 2717 | + if (src_code == REG) |
| 2718 | + { |
| 2719 | + if (FP_REG_P (REGNO (src))) |
| 2720 | + return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1"; |
| 2721 | + } |
| 2722 | + |
| 2723 | + if (src_code == MEM) |
| 2724 | + switch (GET_MODE_SIZE (mode)) |
| 2725 | + { |
| 2726 | + case 1: return "lbu\t%0,%1"; |
| 2727 | + case 2: return "lhu\t%0,%1"; |
| 2728 | + case 4: return "lw\t%0,%1"; |
| 2729 | + case 8: return "ld\t%0,%1"; |
| 2730 | + } |
| 2731 | + |
| 2732 | + if (src_code == CONST_INT) |
| 2733 | + return "li\t%0,%1"; |
| 2734 | + |
| 2735 | + if (src_code == HIGH) |
| 2736 | + return "lui\t%0,%h1"; |
| 2737 | + |
| 2738 | + if (symbolic_operand (src, VOIDmode)) |
| 2739 | + switch (riscv_classify_symbolic_expression (src)) |
| 2740 | + { |
| 2741 | + case SYMBOL_GOT_DISP: return "la\t%0,%1"; |
| 2742 | + case SYMBOL_ABSOLUTE: return "lla\t%0,%1"; |
| 2743 | + default: gcc_unreachable(); |
| 2744 | + } |
| 2745 | + } |
| 2746 | + if (src_code == REG && FP_REG_P (REGNO (src))) |
| 2747 | + { |
| 2748 | + if (dest_code == REG && FP_REG_P (REGNO (dest))) |
| 2749 | + return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1"; |
| 2750 | + |
| 2751 | + if (dest_code == MEM) |
| 2752 | + return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; |
| 2753 | + } |
| 2754 | + if (dest_code == REG && FP_REG_P (REGNO (dest))) |
| 2755 | + { |
| 2756 | + if (src_code == MEM) |
| 2757 | + return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1"; |
| 2758 | + } |
| 2759 | + gcc_unreachable (); |
| 2760 | +} |
| 2761 | + |
| 2762 | +/* Return true if CMP1 is a suitable second operand for integer ordering |
| 2763 | + test CODE. See also the *sCC patterns in riscv.md. */ |
| 2764 | + |
| 2765 | +static bool |
| 2766 | +riscv_int_order_operand_ok_p (enum rtx_code code, rtx cmp1) |
| 2767 | +{ |
| 2768 | + switch (code) |
| 2769 | + { |
| 2770 | + case GT: |
| 2771 | + case GTU: |
| 2772 | + return reg_or_0_operand (cmp1, VOIDmode); |
| 2773 | + |
| 2774 | + case GE: |
| 2775 | + case GEU: |
| 2776 | + return cmp1 == const1_rtx; |
| 2777 | + |
| 2778 | + case LT: |
| 2779 | + case LTU: |
| 2780 | + return arith_operand (cmp1, VOIDmode); |
| 2781 | + |
| 2782 | + case LE: |
| 2783 | + return sle_operand (cmp1, VOIDmode); |
| 2784 | + |
| 2785 | + case LEU: |
| 2786 | + return sleu_operand (cmp1, VOIDmode); |
| 2787 | + |
| 2788 | + default: |
| 2789 | + gcc_unreachable (); |
| 2790 | + } |
| 2791 | +} |
| 2792 | + |
| 2793 | +/* Return true if *CMP1 (of mode MODE) is a valid second operand for |
| 2794 | + integer ordering test *CODE, or if an equivalent combination can |
| 2795 | + be formed by adjusting *CODE and *CMP1. When returning true, update |
| 2796 | + *CODE and *CMP1 with the chosen code and operand, otherwise leave |
| 2797 | + them alone. */ |
| 2798 | + |
| 2799 | +static bool |
| 2800 | +riscv_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1, |
| 2801 | + enum machine_mode mode) |
| 2802 | +{ |
| 2803 | + HOST_WIDE_INT plus_one; |
| 2804 | + |
| 2805 | + if (riscv_int_order_operand_ok_p (*code, *cmp1)) |
| 2806 | + return true; |
| 2807 | + |
| 2808 | + if (CONST_INT_P (*cmp1)) |
| 2809 | + switch (*code) |
| 2810 | + { |
| 2811 | + case LE: |
| 2812 | + plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); |
| 2813 | + if (INTVAL (*cmp1) < plus_one) |
| 2814 | + { |
| 2815 | + *code = LT; |
| 2816 | + *cmp1 = force_reg (mode, GEN_INT (plus_one)); |
| 2817 | + return true; |
| 2818 | + } |
| 2819 | + break; |
| 2820 | + |
| 2821 | + case LEU: |
| 2822 | + plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); |
| 2823 | + if (plus_one != 0) |
| 2824 | + { |
| 2825 | + *code = LTU; |
| 2826 | + *cmp1 = force_reg (mode, GEN_INT (plus_one)); |
| 2827 | + return true; |
| 2828 | + } |
| 2829 | + break; |
| 2830 | + |
| 2831 | + default: |
| 2832 | + break; |
| 2833 | + } |
| 2834 | + return false; |
| 2835 | +} |
| 2836 | + |
| 2837 | +/* Compare CMP0 and CMP1 using ordering test CODE and store the result |
| 2838 | + in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR |
| 2839 | + is nonnull, it's OK to set TARGET to the inverse of the result and |
| 2840 | + flip *INVERT_PTR instead. */ |
| 2841 | + |
| 2842 | +static void |
| 2843 | +riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr, |
| 2844 | + rtx target, rtx cmp0, rtx cmp1) |
| 2845 | +{ |
| 2846 | + enum machine_mode mode; |
| 2847 | + |
| 2848 | + /* First see if there is a RISCV instruction that can do this operation. |
| 2849 | + If not, try doing the same for the inverse operation. If that also |
| 2850 | + fails, force CMP1 into a register and try again. */ |
| 2851 | + mode = GET_MODE (cmp0); |
| 2852 | + if (riscv_canonicalize_int_order_test (&code, &cmp1, mode)) |
| 2853 | + riscv_emit_binary (code, target, cmp0, cmp1); |
| 2854 | + else |
| 2855 | + { |
| 2856 | + enum rtx_code inv_code = reverse_condition (code); |
| 2857 | + if (!riscv_canonicalize_int_order_test (&inv_code, &cmp1, mode)) |
| 2858 | + { |
| 2859 | + cmp1 = force_reg (mode, cmp1); |
| 2860 | + riscv_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1); |
| 2861 | + } |
| 2862 | + else if (invert_ptr == 0) |
| 2863 | + { |
| 2864 | + rtx inv_target; |
| 2865 | + |
| 2866 | + inv_target = riscv_force_binary (GET_MODE (target), |
| 2867 | + inv_code, cmp0, cmp1); |
| 2868 | + riscv_emit_binary (XOR, target, inv_target, const1_rtx); |
| 2869 | + } |
| 2870 | + else |
| 2871 | + { |
| 2872 | + *invert_ptr = !*invert_ptr; |
| 2873 | + riscv_emit_binary (inv_code, target, cmp0, cmp1); |
| 2874 | + } |
| 2875 | + } |
| 2876 | +} |
| 2877 | + |
| 2878 | +/* Return a register that is zero iff CMP0 and CMP1 are equal. |
| 2879 | + The register will have the same mode as CMP0. */ |
| 2880 | + |
| 2881 | +static rtx |
| 2882 | +riscv_zero_if_equal (rtx cmp0, rtx cmp1) |
| 2883 | +{ |
| 2884 | + if (cmp1 == const0_rtx) |
| 2885 | + return cmp0; |
| 2886 | + |
| 2887 | + return expand_binop (GET_MODE (cmp0), sub_optab, |
| 2888 | + cmp0, cmp1, 0, 0, OPTAB_DIRECT); |
| 2889 | +} |
| 2890 | + |
| 2891 | +/* Return false if we can easily emit code for the FP comparison specified |
| 2892 | + by *CODE. If not, set *CODE to its inverse and return true. */ |
| 2893 | + |
| 2894 | +static bool |
| 2895 | +riscv_reversed_fp_cond (enum rtx_code *code) |
| 2896 | +{ |
| 2897 | + switch (*code) |
| 2898 | + { |
| 2899 | + case EQ: |
| 2900 | + case LT: |
| 2901 | + case LE: |
| 2902 | + case GT: |
| 2903 | + case GE: |
| 2904 | + case LTGT: |
| 2905 | + case ORDERED: |
| 2906 | + /* We know how to emit code for these cases... */ |
| 2907 | + return false; |
| 2908 | + |
| 2909 | + default: |
| 2910 | + /* ...but we must invert these and rely on the others. */ |
| 2911 | + *code = reverse_condition_maybe_unordered (*code); |
| 2912 | + return true; |
| 2913 | + } |
| 2914 | +} |
| 2915 | + |
| 2916 | +/* Convert a comparison into something that can be used in a branch or |
| 2917 | + conditional move. On entry, *OP0 and *OP1 are the values being |
| 2918 | + compared and *CODE is the code used to compare them. |
| 2919 | + |
| 2920 | + Update *CODE, *OP0 and *OP1 so that they describe the final comparison. */ |
| 2921 | + |
| 2922 | +static void |
| 2923 | +riscv_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1) |
| 2924 | +{ |
| 2925 | + rtx cmp_op0 = *op0; |
| 2926 | + rtx cmp_op1 = *op1; |
| 2927 | + |
| 2928 | + if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT) |
| 2929 | + { |
| 2930 | + if (splittable_const_int_operand (cmp_op1, VOIDmode)) |
| 2931 | + { |
| 2932 | + HOST_WIDE_INT rhs = INTVAL (cmp_op1), new_rhs; |
| 2933 | + enum rtx_code new_code; |
| 2934 | + |
| 2935 | + switch (*code) |
| 2936 | + { |
| 2937 | + case LTU: new_rhs = rhs - 1; new_code = LEU; goto try_new_rhs; |
| 2938 | + case LEU: new_rhs = rhs + 1; new_code = LTU; goto try_new_rhs; |
| 2939 | + case GTU: new_rhs = rhs + 1; new_code = GEU; goto try_new_rhs; |
| 2940 | + case GEU: new_rhs = rhs - 1; new_code = GTU; goto try_new_rhs; |
| 2941 | + case LT: new_rhs = rhs - 1; new_code = LE; goto try_new_rhs; |
| 2942 | + case LE: new_rhs = rhs + 1; new_code = LT; goto try_new_rhs; |
| 2943 | + case GT: new_rhs = rhs + 1; new_code = GE; goto try_new_rhs; |
| 2944 | + case GE: new_rhs = rhs - 1; new_code = GT; |
| 2945 | + try_new_rhs: |
| 2946 | + /* Convert e.g. OP0 > 4095 into OP0 >= 4096. */ |
| 2947 | + if ((rhs < 0) == (new_rhs < 0) |
| 2948 | + && riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs)) |
| 2949 | + { |
| 2950 | + *op1 = GEN_INT (new_rhs); |
| 2951 | + *code = new_code; |
| 2952 | + } |
| 2953 | + break; |
| 2954 | + |
| 2955 | + case EQ: |
| 2956 | + case NE: |
| 2957 | + /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */ |
| 2958 | + if (SMALL_OPERAND (-rhs)) |
| 2959 | + { |
| 2960 | + *op0 = gen_reg_rtx (GET_MODE (cmp_op0)); |
| 2961 | + riscv_emit_binary (PLUS, *op0, cmp_op0, GEN_INT (-rhs)); |
| 2962 | + *op1 = const0_rtx; |
| 2963 | + } |
| 2964 | + default: |
| 2965 | + break; |
| 2966 | + } |
| 2967 | + } |
| 2968 | + |
| 2969 | + if (*op1 != const0_rtx) |
| 2970 | + *op1 = force_reg (GET_MODE (cmp_op0), *op1); |
| 2971 | + } |
| 2972 | + else |
| 2973 | + { |
| 2974 | + /* For FP comparisons, set an integer register with the result of the |
| 2975 | + comparison, then branch on it. */ |
| 2976 | + rtx tmp0, tmp1, final_op; |
| 2977 | + enum rtx_code fp_code = *code; |
| 2978 | + *code = riscv_reversed_fp_cond (&fp_code) ? EQ : NE; |
| 2979 | + |
| 2980 | + switch (fp_code) |
| 2981 | + { |
| 2982 | + case ORDERED: |
| 2983 | + /* a == a && b == b */ |
| 2984 | + tmp0 = gen_reg_rtx (SImode); |
| 2985 | + riscv_emit_binary (EQ, tmp0, cmp_op0, cmp_op0); |
| 2986 | + tmp1 = gen_reg_rtx (SImode); |
| 2987 | + riscv_emit_binary (EQ, tmp1, cmp_op1, cmp_op1); |
| 2988 | + final_op = gen_reg_rtx (SImode); |
| 2989 | + riscv_emit_binary (AND, final_op, tmp0, tmp1); |
| 2990 | + break; |
| 2991 | + |
| 2992 | + case LTGT: |
| 2993 | + /* a < b || a > b */ |
| 2994 | + tmp0 = gen_reg_rtx (SImode); |
| 2995 | + riscv_emit_binary (LT, tmp0, cmp_op0, cmp_op1); |
| 2996 | + tmp1 = gen_reg_rtx (SImode); |
| 2997 | + riscv_emit_binary (GT, tmp1, cmp_op0, cmp_op1); |
| 2998 | + final_op = gen_reg_rtx (SImode); |
| 2999 | + riscv_emit_binary (IOR, final_op, tmp0, tmp1); |
| 3000 | + break; |
| 3001 | + |
| 3002 | + case EQ: |
| 3003 | + case LE: |
| 3004 | + case LT: |
| 3005 | + case GE: |
| 3006 | + case GT: |
| 3007 | + /* We have instructions for these cases. */ |
| 3008 | + final_op = gen_reg_rtx (SImode); |
| 3009 | + riscv_emit_binary (fp_code, final_op, cmp_op0, cmp_op1); |
| 3010 | + break; |
| 3011 | + |
| 3012 | + default: |
| 3013 | + gcc_unreachable (); |
| 3014 | + } |
| 3015 | + |
| 3016 | + /* Compare the binary result against 0. */ |
| 3017 | + *op0 = final_op; |
| 3018 | + *op1 = const0_rtx; |
| 3019 | + } |
| 3020 | +} |
| 3021 | + |
| 3022 | +/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2] |
| 3023 | + and OPERAND[3]. Store the result in OPERANDS[0]. |
| 3024 | + |
| 3025 | + On 64-bit targets, the mode of the comparison and target will always be |
| 3026 | + SImode, thus possibly narrower than that of the comparison's operands. */ |
| 3027 | + |
| 3028 | +void |
| 3029 | +riscv_expand_scc (rtx operands[]) |
| 3030 | +{ |
| 3031 | + rtx target = operands[0]; |
| 3032 | + enum rtx_code code = GET_CODE (operands[1]); |
| 3033 | + rtx op0 = operands[2]; |
| 3034 | + rtx op1 = operands[3]; |
| 3035 | + |
| 3036 | + gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT); |
| 3037 | + |
| 3038 | + if (code == EQ || code == NE) |
| 3039 | + { |
| 3040 | + rtx zie = riscv_zero_if_equal (op0, op1); |
| 3041 | + riscv_emit_binary (code, target, zie, const0_rtx); |
| 3042 | + } |
| 3043 | + else |
| 3044 | + riscv_emit_int_order_test (code, 0, target, op0, op1); |
| 3045 | +} |
| 3046 | + |
| 3047 | +/* Compare OPERANDS[1] with OPERANDS[2] using comparison code |
| 3048 | + CODE and jump to OPERANDS[3] if the condition holds. */ |
| 3049 | + |
| 3050 | +void |
| 3051 | +riscv_expand_conditional_branch (rtx *operands) |
| 3052 | +{ |
| 3053 | + enum rtx_code code = GET_CODE (operands[0]); |
| 3054 | + rtx op0 = operands[1]; |
| 3055 | + rtx op1 = operands[2]; |
| 3056 | + rtx condition; |
| 3057 | + |
| 3058 | + riscv_emit_compare (&code, &op0, &op1); |
| 3059 | + condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); |
| 3060 | + emit_jump_insn (gen_condjump (condition, operands[3])); |
| 3061 | +} |
| 3062 | + |
| 3063 | +/* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at |
| 3064 | + least PARM_BOUNDARY bits of alignment, but will be given anything up |
| 3065 | + to STACK_BOUNDARY bits if the type requires it. */ |
| 3066 | + |
| 3067 | +static unsigned int |
| 3068 | +riscv_function_arg_boundary (enum machine_mode mode, const_tree type) |
| 3069 | +{ |
| 3070 | + unsigned int alignment; |
| 3071 | + |
| 3072 | + alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); |
| 3073 | + if (alignment < PARM_BOUNDARY) |
| 3074 | + alignment = PARM_BOUNDARY; |
| 3075 | + if (alignment > STACK_BOUNDARY) |
| 3076 | + alignment = STACK_BOUNDARY; |
| 3077 | + return alignment; |
| 3078 | +} |
| 3079 | + |
| 3080 | +/* Fill INFO with information about a single argument. CUM is the |
| 3081 | + cumulative state for earlier arguments. MODE is the mode of this |
| 3082 | + argument and TYPE is its type (if known). NAMED is true if this |
| 3083 | + is a named (fixed) argument rather than a variable one. */ |
| 3084 | + |
| 3085 | +static void |
| 3086 | +riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum, |
| 3087 | + enum machine_mode mode, const_tree type, bool named) |
| 3088 | +{ |
| 3089 | + bool doubleword_aligned_p; |
| 3090 | + unsigned int num_bytes, num_words, max_regs; |
| 3091 | + |
| 3092 | + /* Work out the size of the argument. */ |
| 3093 | + num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); |
| 3094 | + num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; |
| 3095 | + |
| 3096 | + /* Scalar, complex and vector floating-point types are passed in |
| 3097 | + floating-point registers, as long as this is a named rather |
| 3098 | + than a variable argument. */ |
| 3099 | + info->fpr_p = (named |
| 3100 | + && (type == 0 || FLOAT_TYPE_P (type)) |
| 3101 | + && (GET_MODE_CLASS (mode) == MODE_FLOAT |
| 3102 | + || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT |
| 3103 | + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) |
| 3104 | + && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE); |
| 3105 | + |
| 3106 | + /* Complex floats should only go into FPRs if there are two FPRs free, |
| 3107 | + otherwise they should be passed in the same way as a struct |
| 3108 | + containing two floats. */ |
| 3109 | + if (info->fpr_p |
| 3110 | + && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT |
| 3111 | + && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE) |
| 3112 | + { |
| 3113 | + if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1) |
| 3114 | + info->fpr_p = false; |
| 3115 | + else |
| 3116 | + num_words = 2; |
| 3117 | + } |
| 3118 | + |
| 3119 | + /* See whether the argument has doubleword alignment. */ |
| 3120 | + doubleword_aligned_p = (riscv_function_arg_boundary (mode, type) |
| 3121 | + > BITS_PER_WORD); |
| 3122 | + |
| 3123 | + /* Set REG_OFFSET to the register count we're interested in. |
| 3124 | + The EABI allocates the floating-point registers separately, |
| 3125 | + but the other ABIs allocate them like integer registers. */ |
| 3126 | + info->reg_offset = cum->num_gprs; |
| 3127 | + |
| 3128 | + /* Advance to an even register if the argument is doubleword-aligned. */ |
| 3129 | + if (doubleword_aligned_p) |
| 3130 | + info->reg_offset += info->reg_offset & 1; |
| 3131 | + |
| 3132 | + /* Work out the offset of a stack argument. */ |
| 3133 | + info->stack_offset = cum->stack_words; |
| 3134 | + if (doubleword_aligned_p) |
| 3135 | + info->stack_offset += info->stack_offset & 1; |
| 3136 | + |
| 3137 | + max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset; |
| 3138 | + |
| 3139 | + /* Partition the argument between registers and stack. */ |
| 3140 | + info->reg_words = MIN (num_words, max_regs); |
| 3141 | + info->stack_words = num_words - info->reg_words; |
| 3142 | +} |
| 3143 | + |
| 3144 | +/* INFO describes a register argument that has the normal format for the |
| 3145 | + argument's mode. Return the register it uses, assuming that FPRs are |
| 3146 | + available if HARD_FLOAT_P. */ |
| 3147 | + |
| 3148 | +static unsigned int |
| 3149 | +riscv_arg_regno (const struct riscv_arg_info *info, bool hard_float_p) |
| 3150 | +{ |
| 3151 | + if (!info->fpr_p || !hard_float_p) |
| 3152 | + return GP_ARG_FIRST + info->reg_offset; |
| 3153 | + else |
| 3154 | + return FP_ARG_FIRST + info->reg_offset; |
| 3155 | +} |
| 3156 | + |
| 3157 | +/* Implement TARGET_FUNCTION_ARG. */ |
| 3158 | + |
| 3159 | +static rtx |
| 3160 | +riscv_function_arg (cumulative_args_t cum_v, enum machine_mode mode, |
| 3161 | + const_tree type, bool named) |
| 3162 | +{ |
| 3163 | + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
| 3164 | + struct riscv_arg_info info; |
| 3165 | + |
| 3166 | + if (mode == VOIDmode) |
| 3167 | + return NULL; |
| 3168 | + |
| 3169 | + riscv_get_arg_info (&info, cum, mode, type, named); |
| 3170 | + |
| 3171 | + /* Return straight away if the whole argument is passed on the stack. */ |
| 3172 | + if (info.reg_offset == MAX_ARGS_IN_REGISTERS) |
| 3173 | + return NULL; |
| 3174 | + |
| 3175 | + /* The n32 and n64 ABIs say that if any 64-bit chunk of the structure |
| 3176 | + contains a double in its entirety, then that 64-bit chunk is passed |
| 3177 | + in a floating-point register. */ |
| 3178 | + if (TARGET_HARD_FLOAT |
| 3179 | + && named |
| 3180 | + && type != 0 |
| 3181 | + && TREE_CODE (type) == RECORD_TYPE |
| 3182 | + && TYPE_SIZE_UNIT (type) |
| 3183 | + && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) |
| 3184 | + { |
| 3185 | + tree field; |
| 3186 | + |
| 3187 | + /* First check to see if there is any such field. */ |
| 3188 | + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) |
| 3189 | + if (TREE_CODE (field) == FIELD_DECL |
| 3190 | + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field)) |
| 3191 | + && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD |
| 3192 | + && tree_fits_shwi_p (bit_position (field)) |
| 3193 | + && int_bit_position (field) % BITS_PER_WORD == 0) |
| 3194 | + break; |
| 3195 | + |
| 3196 | + if (field != 0) |
| 3197 | + { |
| 3198 | + /* Now handle the special case by returning a PARALLEL |
| 3199 | + indicating where each 64-bit chunk goes. INFO.REG_WORDS |
| 3200 | + chunks are passed in registers. */ |
| 3201 | + unsigned int i; |
| 3202 | + HOST_WIDE_INT bitpos; |
| 3203 | + rtx ret; |
| 3204 | + |
| 3205 | + /* assign_parms checks the mode of ENTRY_PARM, so we must |
| 3206 | + use the actual mode here. */ |
| 3207 | + ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words)); |
| 3208 | + |
| 3209 | + bitpos = 0; |
| 3210 | + field = TYPE_FIELDS (type); |
| 3211 | + for (i = 0; i < info.reg_words; i++) |
| 3212 | + { |
| 3213 | + rtx reg; |
| 3214 | + |
| 3215 | + for (; field; field = DECL_CHAIN (field)) |
| 3216 | + if (TREE_CODE (field) == FIELD_DECL |
| 3217 | + && int_bit_position (field) >= bitpos) |
| 3218 | + break; |
| 3219 | + |
| 3220 | + if (field |
| 3221 | + && int_bit_position (field) == bitpos |
| 3222 | + && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field)) |
| 3223 | + && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD) |
| 3224 | + reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i); |
| 3225 | + else |
| 3226 | + reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i); |
| 3227 | + |
| 3228 | + XVECEXP (ret, 0, i) |
| 3229 | + = gen_rtx_EXPR_LIST (VOIDmode, reg, |
| 3230 | + GEN_INT (bitpos / BITS_PER_UNIT)); |
| 3231 | + |
| 3232 | + bitpos += BITS_PER_WORD; |
| 3233 | + } |
| 3234 | + return ret; |
| 3235 | + } |
| 3236 | + } |
| 3237 | + |
| 3238 | + /* Handle the n32/n64 conventions for passing complex floating-point |
| 3239 | + arguments in FPR pairs. The real part goes in the lower register |
| 3240 | + and the imaginary part goes in the upper register. */ |
| 3241 | + if (info.fpr_p |
| 3242 | + && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) |
| 3243 | + { |
| 3244 | + rtx real, imag; |
| 3245 | + enum machine_mode inner; |
| 3246 | + unsigned int regno; |
| 3247 | + |
| 3248 | + inner = GET_MODE_INNER (mode); |
| 3249 | + regno = FP_ARG_FIRST + info.reg_offset; |
| 3250 | + if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner)) |
| 3251 | + { |
| 3252 | + /* Real part in registers, imaginary part on stack. */ |
| 3253 | + gcc_assert (info.stack_words == info.reg_words); |
| 3254 | + return gen_rtx_REG (inner, regno); |
| 3255 | + } |
| 3256 | + else |
| 3257 | + { |
| 3258 | + gcc_assert (info.stack_words == 0); |
| 3259 | + real = gen_rtx_EXPR_LIST (VOIDmode, |
| 3260 | + gen_rtx_REG (inner, regno), |
| 3261 | + const0_rtx); |
| 3262 | + imag = gen_rtx_EXPR_LIST (VOIDmode, |
| 3263 | + gen_rtx_REG (inner, |
| 3264 | + regno + info.reg_words / 2), |
| 3265 | + GEN_INT (GET_MODE_SIZE (inner))); |
| 3266 | + return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag)); |
| 3267 | + } |
| 3268 | + } |
| 3269 | + |
| 3270 | + return gen_rtx_REG (mode, riscv_arg_regno (&info, TARGET_HARD_FLOAT)); |
| 3271 | +} |
| 3272 | + |
| 3273 | +/* Implement TARGET_FUNCTION_ARG_ADVANCE. */ |
| 3274 | + |
| 3275 | +static void |
| 3276 | +riscv_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode, |
| 3277 | + const_tree type, bool named) |
| 3278 | +{ |
| 3279 | + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
| 3280 | + struct riscv_arg_info info; |
| 3281 | + |
| 3282 | + riscv_get_arg_info (&info, cum, mode, type, named); |
| 3283 | + |
| 3284 | + /* Advance the register count. This has the effect of setting |
| 3285 | + num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned |
| 3286 | + argument required us to skip the final GPR and pass the whole |
| 3287 | + argument on the stack. */ |
| 3288 | + cum->num_gprs = info.reg_offset + info.reg_words; |
| 3289 | + |
| 3290 | + /* Advance the stack word count. */ |
| 3291 | + if (info.stack_words > 0) |
| 3292 | + cum->stack_words = info.stack_offset + info.stack_words; |
| 3293 | +} |
| 3294 | + |
| 3295 | +/* Implement TARGET_ARG_PARTIAL_BYTES. */ |
| 3296 | + |
| 3297 | +static int |
| 3298 | +riscv_arg_partial_bytes (cumulative_args_t cum, |
| 3299 | + enum machine_mode mode, tree type, bool named) |
| 3300 | +{ |
| 3301 | + struct riscv_arg_info info; |
| 3302 | + |
| 3303 | + riscv_get_arg_info (&info, get_cumulative_args (cum), mode, type, named); |
| 3304 | + return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0; |
| 3305 | +} |
| 3306 | + |
| 3307 | +/* See whether VALTYPE is a record whose fields should be returned in |
| 3308 | + floating-point registers. If so, return the number of fields and |
| 3309 | + list them in FIELDS (which should have two elements). Return 0 |
| 3310 | + otherwise. |
| 3311 | + |
| 3312 | + For n32 & n64, a structure with one or two fields is returned in |
| 3313 | + floating-point registers as long as every field has a floating-point |
| 3314 | + type. */ |
| 3315 | + |
| 3316 | +static int |
| 3317 | +riscv_fpr_return_fields (const_tree valtype, tree *fields) |
| 3318 | +{ |
| 3319 | + tree field; |
| 3320 | + int i; |
| 3321 | + |
| 3322 | + if (TREE_CODE (valtype) != RECORD_TYPE) |
| 3323 | + return 0; |
| 3324 | + |
| 3325 | + i = 0; |
| 3326 | + for (field = TYPE_FIELDS (valtype); field != 0; field = DECL_CHAIN (field)) |
| 3327 | + { |
| 3328 | + if (TREE_CODE (field) != FIELD_DECL) |
| 3329 | + continue; |
| 3330 | + |
| 3331 | + if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))) |
| 3332 | + return 0; |
| 3333 | + |
| 3334 | + if (i == 2) |
| 3335 | + return 0; |
| 3336 | + |
| 3337 | + fields[i++] = field; |
| 3338 | + } |
| 3339 | + return i; |
| 3340 | +} |
| 3341 | + |
| 3342 | +/* Return true if the function return value MODE will get returned in a |
| 3343 | + floating-point register. */ |
| 3344 | + |
| 3345 | +static bool |
| 3346 | +riscv_return_mode_in_fpr_p (enum machine_mode mode) |
| 3347 | +{ |
| 3348 | + return ((GET_MODE_CLASS (mode) == MODE_FLOAT |
| 3349 | + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT |
| 3350 | + || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) |
| 3351 | + && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_HWFPVALUE); |
| 3352 | +} |
| 3353 | + |
| 3354 | +/* Return the representation of an FPR return register when the |
| 3355 | + value being returned in FP_RETURN has mode VALUE_MODE and the |
| 3356 | + return type itself has mode TYPE_MODE. On NewABI targets, |
| 3357 | + the two modes may be different for structures like: |
| 3358 | + |
| 3359 | + struct __attribute__((packed)) foo { float f; } |
| 3360 | + |
| 3361 | + where we return the SFmode value of "f" in FP_RETURN, but where |
| 3362 | + the structure itself has mode BLKmode. */ |
| 3363 | + |
| 3364 | +static rtx |
| 3365 | +riscv_return_fpr_single (enum machine_mode type_mode, |
| 3366 | + enum machine_mode value_mode) |
| 3367 | +{ |
| 3368 | + rtx x; |
| 3369 | + |
| 3370 | + x = gen_rtx_REG (value_mode, FP_RETURN); |
| 3371 | + if (type_mode != value_mode) |
| 3372 | + { |
| 3373 | + x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx); |
| 3374 | + x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x)); |
| 3375 | + } |
| 3376 | + return x; |
| 3377 | +} |
| 3378 | + |
| 3379 | +/* Return a composite value in a pair of floating-point registers. |
| 3380 | + MODE1 and OFFSET1 are the mode and byte offset for the first value, |
| 3381 | + likewise MODE2 and OFFSET2 for the second. MODE is the mode of the |
| 3382 | + complete value. |
| 3383 | + |
| 3384 | + For n32 & n64, $f0 always holds the first value and $f2 the second. |
| 3385 | + Otherwise the values are packed together as closely as possible. */ |
| 3386 | + |
| 3387 | +static rtx |
| 3388 | +riscv_return_fpr_pair (enum machine_mode mode, |
| 3389 | + enum machine_mode mode1, HOST_WIDE_INT offset1, |
| 3390 | + enum machine_mode mode2, HOST_WIDE_INT offset2) |
| 3391 | +{ |
| 3392 | + return gen_rtx_PARALLEL |
| 3393 | + (mode, |
| 3394 | + gen_rtvec (2, |
| 3395 | + gen_rtx_EXPR_LIST (VOIDmode, |
| 3396 | + gen_rtx_REG (mode1, FP_RETURN), |
| 3397 | + GEN_INT (offset1)), |
| 3398 | + gen_rtx_EXPR_LIST (VOIDmode, |
| 3399 | + gen_rtx_REG (mode2, FP_RETURN + 1), |
| 3400 | + GEN_INT (offset2)))); |
| 3401 | + |
| 3402 | +} |
| 3403 | + |
| 3404 | +/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, |
| 3405 | + VALTYPE is the return type and MODE is VOIDmode. For libcalls, |
| 3406 | + VALTYPE is null and MODE is the mode of the return value. */ |
| 3407 | + |
| 3408 | +rtx |
| 3409 | +riscv_function_value (const_tree valtype, const_tree func, enum machine_mode mode) |
| 3410 | +{ |
| 3411 | + if (valtype) |
| 3412 | + { |
| 3413 | + tree fields[2]; |
| 3414 | + int unsigned_p; |
| 3415 | + |
| 3416 | + mode = TYPE_MODE (valtype); |
| 3417 | + unsigned_p = TYPE_UNSIGNED (valtype); |
| 3418 | + |
| 3419 | + /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, |
| 3420 | + return values, promote the mode here too. */ |
| 3421 | + mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1); |
| 3422 | + |
| 3423 | + /* Handle structures whose fields are returned in $f0/$f2. */ |
| 3424 | + switch (riscv_fpr_return_fields (valtype, fields)) |
| 3425 | + { |
| 3426 | + case 1: |
| 3427 | + return riscv_return_fpr_single (mode, |
| 3428 | + TYPE_MODE (TREE_TYPE (fields[0]))); |
| 3429 | + |
| 3430 | + case 2: |
| 3431 | + return riscv_return_fpr_pair (mode, |
| 3432 | + TYPE_MODE (TREE_TYPE (fields[0])), |
| 3433 | + int_byte_position (fields[0]), |
| 3434 | + TYPE_MODE (TREE_TYPE (fields[1])), |
| 3435 | + int_byte_position (fields[1])); |
| 3436 | + } |
| 3437 | + |
| 3438 | + /* Only use FPRs for scalar, complex or vector types. */ |
| 3439 | + if (!FLOAT_TYPE_P (valtype)) |
| 3440 | + return gen_rtx_REG (mode, GP_RETURN); |
| 3441 | + } |
| 3442 | + |
| 3443 | + /* Handle long doubles for n32 & n64. */ |
| 3444 | + if (mode == TFmode) |
| 3445 | + return riscv_return_fpr_pair (mode, |
| 3446 | + DImode, 0, |
| 3447 | + DImode, GET_MODE_SIZE (mode) / 2); |
| 3448 | + |
| 3449 | + if (riscv_return_mode_in_fpr_p (mode)) |
| 3450 | + { |
| 3451 | + if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) |
| 3452 | + return riscv_return_fpr_pair (mode, |
| 3453 | + GET_MODE_INNER (mode), 0, |
| 3454 | + GET_MODE_INNER (mode), |
| 3455 | + GET_MODE_SIZE (mode) / 2); |
| 3456 | + else |
| 3457 | + return gen_rtx_REG (mode, FP_RETURN); |
| 3458 | + } |
| 3459 | + |
| 3460 | + return gen_rtx_REG (mode, GP_RETURN); |
| 3461 | +} |
| 3462 | + |
| 3463 | +/* Implement TARGET_RETURN_IN_MEMORY. Scalars and small structures |
| 3464 | + that fit in two registers are returned in a0/a1. */ |
| 3465 | + |
| 3466 | +static bool |
| 3467 | +riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) |
| 3468 | +{ |
| 3469 | + return !IN_RANGE (int_size_in_bytes (type), 0, 2 * UNITS_PER_WORD); |
| 3470 | +} |
| 3471 | + |
| 3472 | +/* Implement TARGET_PASS_BY_REFERENCE. */ |
| 3473 | + |
| 3474 | +static bool |
| 3475 | +riscv_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, |
| 3476 | + enum machine_mode mode, const_tree type, |
| 3477 | + bool named ATTRIBUTE_UNUSED) |
| 3478 | +{ |
| 3479 | + if (type && riscv_return_in_memory (type, NULL_TREE)) |
| 3480 | + return true; |
| 3481 | + return targetm.calls.must_pass_in_stack (mode, type); |
| 3482 | +} |
| 3483 | + |
| 3484 | +/* Implement TARGET_SETUP_INCOMING_VARARGS. */ |
| 3485 | + |
| 3486 | +static void |
| 3487 | +riscv_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode, |
| 3488 | + tree type, int *pretend_size ATTRIBUTE_UNUSED, |
| 3489 | + int no_rtl) |
| 3490 | +{ |
| 3491 | + CUMULATIVE_ARGS local_cum; |
| 3492 | + int gp_saved; |
| 3493 | + |
| 3494 | + /* The caller has advanced CUM up to, but not beyond, the last named |
| 3495 | + argument. Advance a local copy of CUM past the last "real" named |
| 3496 | + argument, to find out how many registers are left over. */ |
| 3497 | + local_cum = *get_cumulative_args (cum); |
| 3498 | + riscv_function_arg_advance (pack_cumulative_args (&local_cum), mode, type, 1); |
| 3499 | + |
| 3500 | + /* Found out how many registers we need to save. */ |
| 3501 | + gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; |
| 3502 | + |
| 3503 | + if (!no_rtl && gp_saved > 0) |
| 3504 | + { |
| 3505 | + rtx ptr, mem; |
| 3506 | + |
| 3507 | + ptr = plus_constant (Pmode, virtual_incoming_args_rtx, |
| 3508 | + REG_PARM_STACK_SPACE (cfun->decl) |
| 3509 | + - gp_saved * UNITS_PER_WORD); |
| 3510 | + mem = gen_frame_mem (BLKmode, ptr); |
| 3511 | + set_mem_alias_set (mem, get_varargs_alias_set ()); |
| 3512 | + |
| 3513 | + move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, |
| 3514 | + mem, gp_saved); |
| 3515 | + } |
| 3516 | + if (REG_PARM_STACK_SPACE (cfun->decl) == 0) |
| 3517 | + cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; |
| 3518 | +} |
| 3519 | + |
| 3520 | +/* Implement TARGET_EXPAND_BUILTIN_VA_START. */ |
| 3521 | + |
| 3522 | +static void |
| 3523 | +riscv_va_start (tree valist, rtx nextarg) |
| 3524 | +{ |
| 3525 | + nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size); |
| 3526 | + std_expand_builtin_va_start (valist, nextarg); |
| 3527 | +} |
| 3528 | + |
| 3529 | +/* Expand a call of type TYPE. RESULT is where the result will go (null |
| 3530 | + for "call"s and "sibcall"s), ADDR is the address of the function, |
| 3531 | + ARGS_SIZE is the size of the arguments and AUX is the value passed |
| 3532 | + to us by riscv_function_arg. Return the call itself. */ |
| 3533 | + |
| 3534 | +rtx |
| 3535 | +riscv_expand_call (bool sibcall_p, rtx result, rtx addr, rtx args_size) |
| 3536 | +{ |
| 3537 | + rtx pattern; |
| 3538 | + |
| 3539 | + if (!call_insn_operand (addr, VOIDmode)) |
| 3540 | + { |
| 3541 | + rtx reg = RISCV_EPILOGUE_TEMP (Pmode); |
| 3542 | + riscv_emit_move (reg, addr); |
| 3543 | + addr = reg; |
| 3544 | + } |
| 3545 | + |
| 3546 | + if (result == 0) |
| 3547 | + { |
| 3548 | + rtx (*fn) (rtx, rtx); |
| 3549 | + |
| 3550 | + if (sibcall_p) |
| 3551 | + fn = gen_sibcall_internal; |
| 3552 | + else |
| 3553 | + fn = gen_call_internal; |
| 3554 | + |
| 3555 | + pattern = fn (addr, args_size); |
| 3556 | + } |
| 3557 | + else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2) |
| 3558 | + { |
| 3559 | + /* Handle return values created by riscv_return_fpr_pair. */ |
| 3560 | + rtx (*fn) (rtx, rtx, rtx, rtx); |
| 3561 | + rtx reg1, reg2; |
| 3562 | + |
| 3563 | + if (sibcall_p) |
| 3564 | + fn = gen_sibcall_value_multiple_internal; |
| 3565 | + else |
| 3566 | + fn = gen_call_value_multiple_internal; |
| 3567 | + |
| 3568 | + reg1 = XEXP (XVECEXP (result, 0, 0), 0); |
| 3569 | + reg2 = XEXP (XVECEXP (result, 0, 1), 0); |
| 3570 | + pattern = fn (reg1, addr, args_size, reg2); |
| 3571 | + } |
| 3572 | + else |
| 3573 | + { |
| 3574 | + rtx (*fn) (rtx, rtx, rtx); |
| 3575 | + |
| 3576 | + if (sibcall_p) |
| 3577 | + fn = gen_sibcall_value_internal; |
| 3578 | + else |
| 3579 | + fn = gen_call_value_internal; |
| 3580 | + |
| 3581 | + /* Handle return values created by riscv_return_fpr_single. */ |
| 3582 | + if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 1) |
| 3583 | + result = XEXP (XVECEXP (result, 0, 0), 0); |
| 3584 | + pattern = fn (result, addr, args_size); |
| 3585 | + } |
| 3586 | + |
| 3587 | + return emit_call_insn (pattern); |
| 3588 | +} |
| 3589 | + |
| 3590 | +/* Emit straight-line code to move LENGTH bytes from SRC to DEST. |
| 3591 | + Assume that the areas do not overlap. */ |
| 3592 | + |
| 3593 | +static void |
| 3594 | +riscv_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) |
| 3595 | +{ |
| 3596 | + HOST_WIDE_INT offset, delta; |
| 3597 | + unsigned HOST_WIDE_INT bits; |
| 3598 | + int i; |
| 3599 | + enum machine_mode mode; |
| 3600 | + rtx *regs; |
| 3601 | + |
| 3602 | + bits = MAX( BITS_PER_UNIT, |
| 3603 | + MIN( BITS_PER_WORD, MIN( MEM_ALIGN(src),MEM_ALIGN(dest) ) ) ); |
| 3604 | + |
| 3605 | + mode = mode_for_size (bits, MODE_INT, 0); |
| 3606 | + delta = bits / BITS_PER_UNIT; |
| 3607 | + |
| 3608 | + /* Allocate a buffer for the temporary registers. */ |
| 3609 | + regs = XALLOCAVEC (rtx, length / delta); |
| 3610 | + |
| 3611 | + /* Load as many BITS-sized chunks as possible. Use a normal load if |
| 3612 | + the source has enough alignment, otherwise use left/right pairs. */ |
| 3613 | + for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) |
| 3614 | + { |
| 3615 | + regs[i] = gen_reg_rtx (mode); |
| 3616 | + riscv_emit_move (regs[i], adjust_address (src, mode, offset)); |
| 3617 | + } |
| 3618 | + |
| 3619 | + /* Copy the chunks to the destination. */ |
| 3620 | + for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) |
| 3621 | + riscv_emit_move (adjust_address (dest, mode, offset), regs[i]); |
| 3622 | + |
| 3623 | + /* Mop up any left-over bytes. */ |
| 3624 | + if (offset < length) |
| 3625 | + { |
| 3626 | + src = adjust_address (src, BLKmode, offset); |
| 3627 | + dest = adjust_address (dest, BLKmode, offset); |
| 3628 | + move_by_pieces (dest, src, length - offset, |
| 3629 | + MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0); |
| 3630 | + } |
| 3631 | +} |
| 3632 | + |
| 3633 | +/* Helper function for doing a loop-based block operation on memory |
| 3634 | + reference MEM. Each iteration of the loop will operate on LENGTH |
| 3635 | + bytes of MEM. |
| 3636 | + |
| 3637 | + Create a new base register for use within the loop and point it to |
| 3638 | + the start of MEM. Create a new memory reference that uses this |
| 3639 | + register. Store them in *LOOP_REG and *LOOP_MEM respectively. */ |
| 3640 | + |
| 3641 | +static void |
| 3642 | +riscv_adjust_block_mem (rtx mem, HOST_WIDE_INT length, |
| 3643 | + rtx *loop_reg, rtx *loop_mem) |
| 3644 | +{ |
| 3645 | + *loop_reg = copy_addr_to_reg (XEXP (mem, 0)); |
| 3646 | + |
| 3647 | + /* Although the new mem does not refer to a known location, |
| 3648 | + it does keep up to LENGTH bytes of alignment. */ |
| 3649 | + *loop_mem = change_address (mem, BLKmode, *loop_reg); |
| 3650 | + set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT)); |
| 3651 | +} |
| 3652 | + |
| 3653 | +/* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER |
| 3654 | + bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that |
| 3655 | + the memory regions do not overlap. */ |
| 3656 | + |
| 3657 | +static void |
| 3658 | +riscv_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, |
| 3659 | + HOST_WIDE_INT bytes_per_iter) |
| 3660 | +{ |
| 3661 | + rtx label, src_reg, dest_reg, final_src, test; |
| 3662 | + HOST_WIDE_INT leftover; |
| 3663 | + |
| 3664 | + leftover = length % bytes_per_iter; |
| 3665 | + length -= leftover; |
| 3666 | + |
| 3667 | + /* Create registers and memory references for use within the loop. */ |
| 3668 | + riscv_adjust_block_mem (src, bytes_per_iter, &src_reg, &src); |
| 3669 | + riscv_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest); |
| 3670 | + |
| 3671 | + /* Calculate the value that SRC_REG should have after the last iteration |
| 3672 | + of the loop. */ |
| 3673 | + final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), |
| 3674 | + 0, 0, OPTAB_WIDEN); |
| 3675 | + |
| 3676 | + /* Emit the start of the loop. */ |
| 3677 | + label = gen_label_rtx (); |
| 3678 | + emit_label (label); |
| 3679 | + |
| 3680 | + /* Emit the loop body. */ |
| 3681 | + riscv_block_move_straight (dest, src, bytes_per_iter); |
| 3682 | + |
| 3683 | + /* Move on to the next block. */ |
| 3684 | + riscv_emit_move (src_reg, plus_constant (Pmode, src_reg, bytes_per_iter)); |
| 3685 | + riscv_emit_move (dest_reg, plus_constant (Pmode, dest_reg, bytes_per_iter)); |
| 3686 | + |
| 3687 | + /* Emit the loop condition. */ |
| 3688 | + test = gen_rtx_NE (VOIDmode, src_reg, final_src); |
| 3689 | + if (Pmode == DImode) |
| 3690 | + emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label)); |
| 3691 | + else |
| 3692 | + emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); |
| 3693 | + |
| 3694 | + /* Mop up any left-over bytes. */ |
| 3695 | + if (leftover) |
| 3696 | + riscv_block_move_straight (dest, src, leftover); |
| 3697 | +} |
| 3698 | + |
| 3699 | +/* Expand a movmemsi instruction, which copies LENGTH bytes from |
| 3700 | + memory reference SRC to memory reference DEST. */ |
| 3701 | + |
| 3702 | +bool |
| 3703 | +riscv_expand_block_move (rtx dest, rtx src, rtx length) |
| 3704 | +{ |
| 3705 | + if (CONST_INT_P (length)) |
| 3706 | + { |
| 3707 | + HOST_WIDE_INT factor, align; |
| 3708 | + |
| 3709 | + align = MIN (MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), BITS_PER_WORD); |
| 3710 | + factor = BITS_PER_WORD / align; |
| 3711 | + |
| 3712 | + if (INTVAL (length) <= RISCV_MAX_MOVE_BYTES_STRAIGHT / factor) |
| 3713 | + { |
| 3714 | + riscv_block_move_straight (dest, src, INTVAL (length)); |
| 3715 | + return true; |
| 3716 | + } |
| 3717 | + else if (optimize && align >= BITS_PER_WORD) |
| 3718 | + { |
| 3719 | + riscv_block_move_loop (dest, src, INTVAL (length), |
| 3720 | + RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER / factor); |
| 3721 | + return true; |
| 3722 | + } |
| 3723 | + } |
| 3724 | + return false; |
| 3725 | +} |
| 3726 | + |
| 3727 | +/* (Re-)Initialize riscv_lo_relocs and riscv_hi_relocs. */ |
| 3728 | + |
| 3729 | +static void |
| 3730 | +riscv_init_relocs (void) |
| 3731 | +{ |
| 3732 | + memset (riscv_hi_relocs, '\0', sizeof (riscv_hi_relocs)); |
| 3733 | + memset (riscv_lo_relocs, '\0', sizeof (riscv_lo_relocs)); |
| 3734 | + |
| 3735 | + if (!flag_pic) |
| 3736 | + { |
| 3737 | + riscv_hi_relocs[SYMBOL_ABSOLUTE] = "%hi("; |
| 3738 | + riscv_lo_relocs[SYMBOL_ABSOLUTE] = "%lo("; |
| 3739 | + } |
| 3740 | + |
| 3741 | + if (!flag_pic || flag_pie) |
| 3742 | + { |
| 3743 | + riscv_hi_relocs[SYMBOL_TLS_LE] = "%tprel_hi("; |
| 3744 | + riscv_lo_relocs[SYMBOL_TLS_LE] = "%tprel_lo("; |
| 3745 | + } |
| 3746 | +} |
| 3747 | + |
| 3748 | +/* Print symbolic operand OP, which is part of a HIGH or LO_SUM |
| 3749 | + in context CONTEXT. RELOCS is the array of relocations to use. */ |
| 3750 | + |
| 3751 | +static void |
| 3752 | +riscv_print_operand_reloc (FILE *file, rtx op, const char **relocs) |
| 3753 | +{ |
| 3754 | + enum riscv_symbol_type symbol_type; |
| 3755 | + const char *p; |
| 3756 | + |
| 3757 | + symbol_type = riscv_classify_symbolic_expression (op); |
| 3758 | + gcc_assert (relocs[symbol_type]); |
| 3759 | + |
| 3760 | + fputs (relocs[symbol_type], file); |
| 3761 | + output_addr_const (file, riscv_strip_unspec_address (op)); |
| 3762 | + for (p = relocs[symbol_type]; *p != 0; p++) |
| 3763 | + if (*p == '(') |
| 3764 | + fputc (')', file); |
| 3765 | +} |
| 3766 | + |
| 3767 | +static const char * |
| 3768 | +riscv_memory_model_suffix (enum memmodel model) |
| 3769 | +{ |
| 3770 | + switch (model) |
| 3771 | + { |
| 3772 | + case MEMMODEL_ACQ_REL: |
| 3773 | + case MEMMODEL_SEQ_CST: |
| 3774 | + return ".sc"; |
| 3775 | + case MEMMODEL_ACQUIRE: |
| 3776 | + case MEMMODEL_CONSUME: |
| 3777 | + return ".aq"; |
| 3778 | + case MEMMODEL_RELEASE: |
| 3779 | + return ".rl"; |
| 3780 | + case MEMMODEL_RELAXED: |
| 3781 | + return ""; |
| 3782 | + default: gcc_unreachable(); |
| 3783 | + } |
| 3784 | +} |
| 3785 | + |
| 3786 | +/* Implement TARGET_PRINT_OPERAND. The RISCV-specific operand codes are: |
| 3787 | + |
| 3788 | + 'h' Print the high-part relocation associated with OP, after stripping |
| 3789 | + any outermost HIGH. |
| 3790 | + 'R' Print the low-part relocation associated with OP. |
| 3791 | + 'C' Print the integer branch condition for comparison OP. |
| 3792 | + 'A' Print the atomic operation suffix for memory model OP. |
| 3793 | + 'z' Print $0 if OP is zero, otherwise print OP normally. */ |
| 3794 | + |
| 3795 | +static void |
| 3796 | +riscv_print_operand (FILE *file, rtx op, int letter) |
| 3797 | +{ |
| 3798 | + enum rtx_code code; |
| 3799 | + |
| 3800 | + gcc_assert (op); |
| |