blob: 55ad1895e5031fb24695c3fe0f36416459f5464b [file] [log] [blame]
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001--- original-gcc/config.sub
2+++ gcc-5.2.0/config.sub
3@@ -340,6 +340,9 @@ case $basic_machine in
Patrick Georgif0bbc952015-03-07 10:57:25 +01004 ms1)
5 basic_machine=mt-unknown
6 ;;
7+ riscv)
8+ basic_machine=riscv-ucb
9+ ;;
10
11 strongarm | thumb | xscale)
12 basic_machine=arm-unknown
Patrick Georgiaf473ed2015-07-17 23:35:54 +020013--- original-gcc/gcc/config.gcc
14+++ gcc-5.2.0/gcc/config.gcc
15@@ -439,6 +439,10 @@ powerpc*-*-*)
16 esac
17 extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
18 ;;
19+riscv*)
20+ cpu_type=riscv
21+ need_64bit_hwint=yes
22+ ;;
23 rs6000*-*-*)
24 extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
25 ;;
26@@ -1976,6 +1980,27 @@ microblaze*-*-elf)
27 cxx_target_objs="${cxx_target_objs} microblaze-c.o"
28 tmake_file="${tmake_file} microblaze/t-microblaze"
29 ;;
30+riscv32*-*-linux*) # Linux RISC-V
31+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h riscv/default-32.h ${tm_file} riscv/linux.h riscv/linux64.h"
32+ tmake_file="${tmake_file} riscv/t-linux64"
33+ gnu_ld=yes
34+ gas=yes
35+ gcc_cv_initfini_array=yes
36+ ;;
37+riscv*-*-linux*) # Linux RISC-V
38+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} riscv/linux.h riscv/linux64.h"
39+ tmake_file="${tmake_file} riscv/t-linux64"
40+ gnu_ld=yes
41+ gas=yes
42+ gcc_cv_initfini_array=yes
43+ ;;
44+riscv*-*-elf*) # Linux RISC-V
45+ tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
46+ tmake_file="${tmake_file} riscv/t-elf"
47+ gnu_ld=yes
48+ gas=yes
49+ gcc_cv_initfini_array=yes
50+ ;;
51 mips*-*-netbsd*) # NetBSD/mips, either endian.
52 target_cpu_default="MASK_ABICALLS"
53 tm_file="elfos.h ${tm_file} mips/elf.h netbsd.h netbsd-elf.h mips/netbsd.h"
54@@ -3851,6 +3876,31 @@ case "${target}" in
55 done
56 ;;
57
58+ riscv*-*-*)
59+ supported_defaults="abi arch arch_32 arch_64 float tune tune_32 tune_64"
60+
61+ case ${with_float} in
62+ "" | soft | hard)
63+ # OK
64+ ;;
65+ *)
66+ echo "Unknown floating point type used in --with-float=$with_float" 1>&2
67+ exit 1
68+ ;;
69+ esac
70+
71+ case ${with_abi} in
72+ "" | 32 | 64)
73+ # OK
74+ ;;
75+ *)
76+ echo "Unknown ABI used in --with-abi=$with_abi" 1>&2
77+ exit 1
78+ ;;
79+ esac
80+
81+ ;;
82+
83 mips*-*-*)
84 supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci"
85
86--- original-gcc/gcc/configure
87+++ gcc-5.2.0/gcc/configure
88@@ -23708,6 +23708,25 @@ x3: .space 4
89 tls_first_minor=14
90 tls_as_opt="-a32 --fatal-warnings"
91 ;;
92+ riscv*-*-*)
93+ conftest_s='
94+ .section .tdata,"awT",@progbits
95+x:
96+ .word 2
97+ .text
98+ la.tls.gd a0,x
99+ la.tls.ie a1,x
100+ lui a0,%tls_ie_pcrel_hi(x)
101+ lw a0,%pcrel_lo(x)(a0)
102+ add a0,a0,tp
103+ lw a0,0(a0)
104+ lui a0,%tprel_hi(x)
105+ add a0,a0,tp,%tprel_add(x)
106+ lw a0,%tprel_lo(x)(a0)'
107+ tls_first_major=2
108+ tls_first_minor=21
109+ tls_as_opt='-m32 --fatal-warnings'
110+ ;;
111 s390-*-*)
112 conftest_s='
113 .section ".tdata","awT",@progbits
114--- original-gcc/gcc/configure.ac
115+++ gcc-5.2.0/gcc/configure.ac
116@@ -3263,6 +3263,25 @@ x3: .space 4
117 tls_first_minor=14
118 tls_as_opt="-a32 --fatal-warnings"
119 ;;
120+ riscv*-*-*)
121+ conftest_s='
122+ .section .tdata,"awT",@progbits
123+x:
124+ .word 2
125+ .text
126+ la.tls.gd a0,x
127+ la.tls.ie a1,x
128+ lui a0,%tls_ie_pcrel_hi(x)
129+ lw a0,%pcrel_lo(x)(a0)
130+ add a0,a0,tp
131+ lw a0,0(a0)
132+ lui a0,%tprel_hi(x)
133+ add a0,a0,tp,%tprel_add(x)
134+ lw a0,%tprel_lo(x)(a0)'
135+ tls_first_major=2
136+ tls_first_minor=21
137+ tls_as_opt='-m32 --fatal-warnings'
138+ ;;
139 s390-*-*)
140 conftest_s='
141 .section ".tdata","awT",@progbits
142--- original-gcc/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
143+++ gcc-5.2.0/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
144@@ -6,6 +6,9 @@
145 #elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (__POWERPC__) || defined (__ppc)
146 /* On PPC division by zero does not trap. */
147 # define DO_TEST 0
148+#elif defined (__riscv__)
149+ /* On RISC-V division by zero does not trap. */
150+# define DO_TEST 0
151 #elif defined (__SPU__)
152 /* On SPU division by zero does not trap. */
153 # define DO_TEST 0
154--- original-gcc/gcc/testsuite/gcc.dg/20020312-2.c
155+++ gcc-5.2.0/gcc/testsuite/gcc.dg/20020312-2.c
156@@ -66,6 +66,8 @@ extern void abort (void);
157 # else
158 # define PIC_REG "30"
159 # endif
160+#elif defined(__riscv__)
161+/* No pic register. */
162 #elif defined(__RX__)
163 /* No pic register. */
164 #elif defined(__s390__)
165--- original-gcc/gcc/testsuite/gcc.dg/20040813-1.c
166+++ gcc-5.2.0/gcc/testsuite/gcc.dg/20040813-1.c
167@@ -2,7 +2,7 @@
168 /* Contributed by Devang Patel <dpatel@apple.com> */
169
170 /* { dg-do compile } */
171-/* { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* *-*-aix* alpha*-*-* hppa*64*-*-* ia64-*-* tile*-*-* nios2-*-* *-*-vxworks* nvptx-*-* } { "*" } { "" } } */
172+/* { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* *-*-aix* alpha*-*-* hppa*64*-*-* ia64-*-* riscv*-*-* tile*-*-* nios2-*-* *-*-vxworks* nvptx-*-* } { "*" } { "" } } */
173 /* { dg-options "-gstabs" } */
174
175 int
176--- original-gcc/gcc/testsuite/gcc.dg/stack-usage-1.c
177+++ gcc-5.2.0/gcc/testsuite/gcc.dg/stack-usage-1.c
178@@ -61,6 +61,8 @@
179 # else
180 # define SIZE 240
181 # endif
182+#elif defined (__riscv__)
183+# define SIZE 240
184 #elif defined (__AVR__)
185 # define SIZE 254
186 #elif defined (__s390x__)
187--- original-gcc/libatomic/configure.tgt
188+++ gcc-5.2.0/libatomic/configure.tgt
189@@ -33,6 +33,7 @@ case "${target_cpu}" in
190 ARCH=alpha
191 ;;
192 rs6000 | powerpc*) ARCH=powerpc ;;
193+ riscv*) ARCH=riscv ;;
194 sh*) ARCH=sh ;;
195
196 arm*)
197--- original-gcc/libgcc/config.host
198+++ gcc-5.2.0/libgcc/config.host
199@@ -167,6 +167,9 @@ powerpc*-*-*)
200 ;;
201 rs6000*-*-*)
202 ;;
203+riscv*)
204+ cpu_type=riscv
205+ ;;
206 sparc64*-*-*)
207 cpu_type=sparc
208 ;;
209@@ -1057,6 +1060,18 @@ powerpcle-*-eabi*)
210 tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
211 extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
212 ;;
213+riscv32*-*-linux*)
214+ tmake_file="${tmake_file} riscv/t-fpbit riscv/t-dpbit riscv/t-tpbit riscv/t-elf riscv/t-elf32"
215+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o"
216+ ;;
217+riscv*-*-linux*)
218+ tmake_file="${tmake_file} riscv/t-fpbit riscv/t-dpbit riscv/t-tpbit riscv/t-elf"
219+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o"
220+ ;;
221+riscv*-*-*)
222+ tmake_file="${tmake_file} riscv/t-fpbit riscv/t-dpbit riscv/t-elf"
223+ extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o"
224+ ;;
225 rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
226 md_unwind_header=rs6000/aix-unwind.h
227 tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble"
228--- original-gcc/libsanitizer/asan/asan_linux.cc
229+++ gcc-5.2.0/libsanitizer/asan/asan_linux.cc
230@@ -213,6 +213,11 @@ void GetPcSpBp(void *context, uptr *pc,
231 *pc = ucontext->uc_mcontext.gregs[31];
232 *bp = ucontext->uc_mcontext.gregs[30];
233 *sp = ucontext->uc_mcontext.gregs[29];
234+# elif defined(__riscv__)
235+ ucontext_t *ucontext = (ucontext_t*)context;
236+ *pc = ucontext->uc_mcontext.gregs[REG_PC];
237+ *bp = ucontext->uc_mcontext.gregs[REG_S0];
238+ *sp = ucontext->uc_mcontext.gregs[REG_SP];
239 #else
240 # error "Unsupported arch"
241 #endif
242--- original-gcc/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
243+++ gcc-5.2.0/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc
244@@ -61,7 +61,8 @@ namespace __sanitizer {
245 } // namespace __sanitizer
246
247 #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\
248- && !defined(__mips__) && !defined(__sparc__)
249+ && !defined(__mips__) && !defined(__sparc__)\
250+ && !defined(__riscv__)
251 COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat));
252 #endif
253
254--- original-gcc/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
255+++ gcc-5.2.0/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
256@@ -72,6 +72,10 @@ namespace __sanitizer {
257 const unsigned struct_kernel_stat_sz = 144;
258 #endif
259 const unsigned struct_kernel_stat64_sz = 104;
260+#elif defined(__riscv__)
261+ const unsigned struct___old_kernel_stat_sz = 0;
262+ const unsigned struct_kernel_stat_sz = 128;
263+ const unsigned struct_kernel_stat64_sz = 128;
264 #elif defined(__sparc__) && defined(__arch64__)
265 const unsigned struct___old_kernel_stat_sz = 0;
266 const unsigned struct_kernel_stat_sz = 104;
267@@ -511,7 +515,7 @@ namespace __sanitizer {
268 typedef long __sanitizer___kernel_off_t;
269 #endif
270
271-#if defined(__powerpc__) || defined(__mips__)
272+#if defined(__powerpc__) || defined(__mips__) || defined(__riscv__)
273 typedef unsigned int __sanitizer___kernel_old_uid_t;
274 typedef unsigned int __sanitizer___kernel_old_gid_t;
275 #else
276diff -ru gcc-5.1.0.orig/libsanitizer/sanitizer_common/sanitizer_platform.h gcc-5.1.0/libsanitizer/sanitizer_common/sanitizer_platform.h
277--- gcc-5.1.0.orig/libsanitizer/sanitizer_common/sanitizer_platform.h 2015-05-13 19:36:27.061421043 -0700
278+++ gcc-5.2.0/libsanitizer/sanitizer_common/sanitizer_platform.h 2015-05-13 19:44:19.274355577 -0700
279@@ -98,9 +98,9 @@
280
281 // The AArch64 linux port uses the canonical syscall set as mandated by
282 // the upstream linux community for all new ports. Other ports may still
283-// use legacy syscalls.
284+// use legacy syscalls. The RISC-V port also does this.
285 #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
286-# if defined(__aarch64__) && SANITIZER_LINUX
287+# if (defined(__aarch64__) || defined(__riscv__)) && SANITIZER_LINUX
288 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
289 # else
290 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
291diff -ru gcc-5.1.0.orig/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h gcc-5.1.0/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
292--- gcc-5.1.0.orig/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h 2015-05-13 19:36:27.061421043 -0700
293+++ gcc-5.2.0/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h 2015-05-13 19:39:13.515487834 -0700
294@@ -73,7 +73,6 @@
295 #endif
296 const unsigned struct_kernel_stat64_sz = 104;
297 #elif defined(__riscv__)
298- const unsigned struct___old_kernel_stat_sz = 0;
299 const unsigned struct_kernel_stat_sz = 128;
300 const unsigned struct_kernel_stat64_sz = 128;
301 #elif defined(__sparc__) && defined(__arch64__)
302@@ -104,7 +103,7 @@
303
304 #if SANITIZER_LINUX || SANITIZER_FREEBSD
305
306-#if defined(__powerpc64__)
307+#if defined(__powerpc64__) || defined(__riscv__)
308 const unsigned struct___old_kernel_stat_sz = 0;
309 #elif !defined(__sparc__)
310 const unsigned struct___old_kernel_stat_sz = 32;
311diff -urN empty/gcc/common/config/riscv/riscv-common.c gcc-5.2.0/gcc/common/config/riscv/riscv-common.c
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200312--- gcc-5.2.0/gcc/common/config/riscv/riscv-common.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200313+++ gcc-5.2.0/gcc/common/config/riscv/riscv-common.c 2015-07-17 22:36:52.315705931 +0200
314@@ -0,0 +1,140 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +0100315+/* Common hooks for RISC-V.
316+ Copyright (C) 1989-2014 Free Software Foundation, Inc.
317+
318+This file is part of GCC.
319+
320+GCC is free software; you can redistribute it and/or modify
321+it under the terms of the GNU General Public License as published by
322+the Free Software Foundation; either version 3, or (at your option)
323+any later version.
324+
325+GCC is distributed in the hope that it will be useful,
326+but WITHOUT ANY WARRANTY; without even the implied warranty of
327+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
328+GNU General Public License for more details.
329+
330+You should have received a copy of the GNU General Public License
331+along with GCC; see the file COPYING3. If not see
332+<http://www.gnu.org/licenses/>. */
333+
334+#include "config.h"
335+#include "system.h"
336+#include "coretypes.h"
337+#include "tm.h"
338+#include "common/common-target.h"
339+#include "common/common-target-def.h"
340+#include "opts.h"
341+#include "flags.h"
342+#include "errors.h"
343+
344+/* Parse a RISC-V ISA string into an option mask. */
345+
346+static void
347+riscv_parse_arch_string (const char *isa, int *flags)
348+{
349+ const char *p = isa;
350+
351+ if (strncmp (p, "RV32", 4) == 0)
352+ *flags |= MASK_32BIT, p += 4;
353+ else if (strncmp (p, "RV64", 4) == 0)
354+ *flags &= ~MASK_32BIT, p += 4;
355+
356+ if (*p++ != 'I')
357+ {
358+ error ("-march=%s: ISA strings must begin with I, RV32I, or RV64I", isa);
359+ return;
360+ }
361+
362+ *flags &= ~MASK_MULDIV;
363+ if (*p == 'M')
364+ *flags |= MASK_MULDIV, p++;
365+
366+ *flags &= ~MASK_ATOMIC;
367+ if (*p == 'A')
368+ *flags |= MASK_ATOMIC, p++;
369+
370+ *flags |= MASK_SOFT_FLOAT_ABI;
371+ if (*p == 'F')
372+ *flags &= ~MASK_SOFT_FLOAT_ABI, p++;
373+
374+ if (*p == 'D')
375+ {
376+ p++;
377+ if (!TARGET_HARD_FLOAT)
378+ {
379+ error ("-march=%s: the D extension requires the F extension", isa);
380+ return;
381+ }
382+ }
383+ else if (TARGET_HARD_FLOAT)
384+ {
385+ error ("-march=%s: single-precision-only is not yet supported", isa);
386+ return;
387+ }
388+
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200389+ *flags &= ~MASK_RVC;
390+ if (*p == 'C')
391+ *flags |= MASK_RVC, p++;
392+
393+ /* FIXME: For now we just stop parsing when faced with a
394+ non-standard RISC-V ISA extension, partially becauses of a
395+ problem with the naming scheme. */
396+ if (*p == 'X')
397+ return;
398+
Patrick Georgif0bbc952015-03-07 10:57:25 +0100399+ if (*p)
400+ {
401+ error ("-march=%s: unsupported ISA substring %s", isa, p);
402+ return;
403+ }
404+}
405+
406+static int
407+riscv_flags_from_arch_string (const char *isa)
408+{
409+ int flags = 0;
410+ riscv_parse_arch_string (isa, &flags);
411+ return flags;
412+}
413+
414+/* Implement TARGET_HANDLE_OPTION. */
415+
416+static bool
417+riscv_handle_option (struct gcc_options *opts,
418+ struct gcc_options *opts_set ATTRIBUTE_UNUSED,
419+ const struct cl_decoded_option *decoded,
420+ location_t loc ATTRIBUTE_UNUSED)
421+{
422+ switch (decoded->opt_index)
423+ {
424+ case OPT_march_:
425+ riscv_parse_arch_string (decoded->arg, &opts->x_target_flags);
426+ return true;
427+
428+ default:
429+ return true;
430+ }
431+}
432+
433+/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */
434+static const struct default_options riscv_option_optimization_table[] =
435+ {
436+ { OPT_LEVELS_1_PLUS, OPT_fsection_anchors, NULL, 1 },
437+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200438+ { OPT_LEVELS_SIZE, OPT_msave_restore, NULL, 1 },
Patrick Georgif0bbc952015-03-07 10:57:25 +0100439+ { OPT_LEVELS_NONE, 0, NULL, 0 }
440+ };
441+
442+#undef TARGET_OPTION_OPTIMIZATION_TABLE
443+#define TARGET_OPTION_OPTIMIZATION_TABLE riscv_option_optimization_table
444+
445+#undef TARGET_DEFAULT_TARGET_FLAGS
446+#define TARGET_DEFAULT_TARGET_FLAGS \
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200447+ (TARGET_DEFAULT \
448+ | riscv_flags_from_arch_string (RISCV_ARCH_STRING_DEFAULT) \
Patrick Georgif0bbc952015-03-07 10:57:25 +0100449+ | (TARGET_64BIT_DEFAULT ? 0 : MASK_32BIT))
450+
451+#undef TARGET_HANDLE_OPTION
452+#define TARGET_HANDLE_OPTION riscv_handle_option
453+
454+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200455diff -urN empty/gcc/config/riscv/constraints.md gcc-5.2.0/gcc/config/riscv/constraints.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200456--- gcc-5.2.0/gcc/config/riscv/constraints.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200457+++ gcc-5.2.0/gcc/config/riscv/constraints.md 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100458@@ -0,0 +1,90 @@
459+;; Constraint definitions for RISC-V target.
460+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
461+;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
462+;; Based on MIPS target for GNU compiler.
463+;;
464+;; This file is part of GCC.
465+;;
466+;; GCC is free software; you can redistribute it and/or modify
467+;; it under the terms of the GNU General Public License as published by
468+;; the Free Software Foundation; either version 3, or (at your option)
469+;; any later version.
470+;;
471+;; GCC is distributed in the hope that it will be useful,
472+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
473+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
474+;; GNU General Public License for more details.
475+;;
476+;; You should have received a copy of the GNU General Public License
477+;; along with GCC; see the file COPYING3. If not see
478+;; <http://www.gnu.org/licenses/>.
479+
480+;; Register constraints
481+
482+(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
483+ "A floating-point register (if available).")
484+
485+(define_register_constraint "b" "ALL_REGS"
486+ "@internal")
487+
488+(define_register_constraint "j" "T_REGS"
489+ "@internal")
490+
491+;; Integer constraints
492+
493+(define_constraint "Z"
494+ "@internal"
495+ (and (match_code "const_int")
496+ (match_test "1")))
497+
498+(define_constraint "I"
499+ "An I-type 12-bit signed immediate."
500+ (and (match_code "const_int")
501+ (match_test "SMALL_OPERAND (ival)")))
502+
503+(define_constraint "J"
504+ "Integer zero."
505+ (and (match_code "const_int")
506+ (match_test "ival == 0")))
507+
508+;; Floating-point constraints
509+
510+(define_constraint "G"
511+ "Floating-point zero."
512+ (and (match_code "const_double")
513+ (match_test "op == CONST0_RTX (mode)")))
514+
515+;; General constraints
516+
517+(define_constraint "Q"
518+ "@internal"
519+ (match_operand 0 "const_arith_operand"))
520+
521+(define_memory_constraint "A"
522+ "An address that is held in a general-purpose register."
523+ (and (match_code "mem")
524+ (match_test "GET_CODE(XEXP(op,0)) == REG")))
525+
526+(define_constraint "S"
527+ "@internal
528+ A constant call address."
529+ (and (match_operand 0 "call_insn_operand")
530+ (match_test "CONSTANT_P (op)")))
531+
532+(define_constraint "T"
533+ "@internal
534+ A constant @code{move_operand}."
535+ (and (match_operand 0 "move_operand")
536+ (match_test "CONSTANT_P (op)")))
537+
538+(define_memory_constraint "W"
539+ "@internal
540+ A memory address based on a member of @code{BASE_REG_CLASS}."
541+ (and (match_code "mem")
542+ (match_operand 0 "memory_operand")))
543+
544+(define_constraint "YG"
545+ "@internal
546+ A vector zero."
547+ (and (match_code "const_vector")
548+ (match_test "op == CONST0_RTX (mode)")))
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200549diff -urN empty/gcc/config/riscv/default-32.h gcc-5.2.0/gcc/config/riscv/default-32.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200550--- gcc-5.2.0/gcc/config/riscv/default-32.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200551+++ gcc-5.2.0/gcc/config/riscv/default-32.h 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100552@@ -0,0 +1,22 @@
553+/* Definitions of target machine for GCC, for RISC-V,
554+ defaulting to 32-bit code generation.
555+
556+ Copyright (C) 1999-2014 Free Software Foundation, Inc.
557+
558+This file is part of GCC.
559+
560+GCC is free software; you can redistribute it and/or modify
561+it under the terms of the GNU General Public License as published by
562+the Free Software Foundation; either version 3, or (at your option)
563+any later version.
564+
565+GCC is distributed in the hope that it will be useful,
566+but WITHOUT ANY WARRANTY; without even the implied warranty of
567+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
568+GNU General Public License for more details.
569+
570+You should have received a copy of the GNU General Public License
571+along with GCC; see the file COPYING3. If not see
572+<http://www.gnu.org/licenses/>. */
573+
574+#define TARGET_64BIT_DEFAULT 0
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200575diff -urN empty/gcc/config/riscv/elf.h gcc-5.2.0/gcc/config/riscv/elf.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200576--- gcc-5.2.0/gcc/config/riscv/elf.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200577+++ gcc-5.2.0/gcc/config/riscv/elf.h 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100578@@ -0,0 +1,31 @@
579+/* Target macros for riscv*-elf targets.
580+ Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004, 2007, 2010
581+ Free Software Foundation, Inc.
582+
583+This file is part of GCC.
584+
585+GCC is free software; you can redistribute it and/or modify
586+it under the terms of the GNU General Public License as published by
587+the Free Software Foundation; either version 3, or (at your option)
588+any later version.
589+
590+GCC is distributed in the hope that it will be useful,
591+but WITHOUT ANY WARRANTY; without even the implied warranty of
592+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
593+GNU General Public License for more details.
594+
595+You should have received a copy of the GNU General Public License
596+along with GCC; see the file COPYING3. If not see
597+<http://www.gnu.org/licenses/>. */
598+
599+/* Leave the linker script to choose the appropriate libraries. */
600+#undef LIB_SPEC
601+#define LIB_SPEC ""
602+
603+#undef STARTFILE_SPEC
604+#define STARTFILE_SPEC "crt0%O%s crtbegin%O%s"
605+
606+#undef ENDFILE_SPEC
607+#define ENDFILE_SPEC "crtend%O%s"
608+
609+#define NO_IMPLICIT_EXTERN_C 1
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200610diff -urN empty/gcc/config/riscv/generic.md gcc-5.2.0/gcc/config/riscv/generic.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200611--- gcc-5.2.0/gcc/config/riscv/generic.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200612+++ gcc-5.2.0/gcc/config/riscv/generic.md 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100613@@ -0,0 +1,98 @@
614+;; Generic DFA-based pipeline description for RISC-V targets.
615+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
616+;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
617+;; Based on MIPS target for GNU compiler.
618+
619+;; This file is part of GCC.
620+
621+;; GCC is free software; you can redistribute it and/or modify it
622+;; under the terms of the GNU General Public License as published
623+;; by the Free Software Foundation; either version 3, or (at your
624+;; option) any later version.
625+
626+;; GCC is distributed in the hope that it will be useful, but WITHOUT
627+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
628+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
629+;; License for more details.
630+
631+;; You should have received a copy of the GNU General Public License
632+;; along with GCC; see the file COPYING3. If not see
633+;; <http://www.gnu.org/licenses/>.
634+
635+
636+;; This file is derived from the old define_function_unit description.
637+;; Each reservation can be overridden on a processor-by-processor basis.
638+
639+(define_insn_reservation "generic_alu" 1
640+ (eq_attr "type" "unknown,const,arith,shift,slt,multi,nop,logical,move")
641+ "alu")
642+
643+(define_insn_reservation "generic_load" 3
644+ (eq_attr "type" "load,fpload,fpidxload")
645+ "alu")
646+
647+(define_insn_reservation "generic_store" 1
648+ (eq_attr "type" "store,fpstore,fpidxstore")
649+ "alu")
650+
651+(define_insn_reservation "generic_xfer" 2
652+ (eq_attr "type" "mfc,mtc")
653+ "alu")
654+
655+(define_insn_reservation "generic_branch" 1
656+ (eq_attr "type" "branch,jump,call")
657+ "alu")
658+
659+(define_insn_reservation "generic_imul" 17
660+ (eq_attr "type" "imul")
661+ "imuldiv*17")
662+
663+(define_insn_reservation "generic_idiv" 38
664+ (eq_attr "type" "idiv")
665+ "imuldiv*38")
666+
667+(define_insn_reservation "generic_fcvt" 1
668+ (eq_attr "type" "fcvt")
669+ "alu")
670+
671+(define_insn_reservation "generic_fmove" 2
672+ (eq_attr "type" "fmove")
673+ "alu")
674+
675+(define_insn_reservation "generic_fcmp" 3
676+ (eq_attr "type" "fcmp")
677+ "alu")
678+
679+(define_insn_reservation "generic_fadd" 4
680+ (eq_attr "type" "fadd")
681+ "alu")
682+
683+(define_insn_reservation "generic_fmul_single" 7
684+ (and (eq_attr "type" "fmul,fmadd")
685+ (eq_attr "mode" "SF"))
686+ "alu")
687+
688+(define_insn_reservation "generic_fmul_double" 8
689+ (and (eq_attr "type" "fmul,fmadd")
690+ (eq_attr "mode" "DF"))
691+ "alu")
692+
693+(define_insn_reservation "generic_fdiv_single" 23
694+ (and (eq_attr "type" "fdiv")
695+ (eq_attr "mode" "SF"))
696+ "alu")
697+
698+(define_insn_reservation "generic_fdiv_double" 36
699+ (and (eq_attr "type" "fdiv")
700+ (eq_attr "mode" "DF"))
701+ "alu")
702+
703+(define_insn_reservation "generic_fsqrt_single" 54
704+ (and (eq_attr "type" "fsqrt")
705+ (eq_attr "mode" "SF"))
706+ "alu")
707+
708+(define_insn_reservation "generic_fsqrt_double" 112
709+ (and (eq_attr "type" "fsqrt")
710+ (eq_attr "mode" "DF"))
711+ "alu")
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200712diff -urN empty/gcc/config/riscv/linux.h gcc-5.2.0/gcc/config/riscv/linux.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200713--- gcc-5.2.0/gcc/config/riscv/linux.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200714+++ gcc-5.2.0/gcc/config/riscv/linux.h 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100715@@ -0,0 +1,60 @@
716+/* Definitions for RISC-V GNU/Linux systems with ELF format.
717+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
718+ 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
719+
720+This file is part of GCC.
721+
722+GCC is free software; you can redistribute it and/or modify
723+it under the terms of the GNU General Public License as published by
724+the Free Software Foundation; either version 3, or (at your option)
725+any later version.
726+
727+GCC is distributed in the hope that it will be useful,
728+but WITHOUT ANY WARRANTY; without even the implied warranty of
729+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
730+GNU General Public License for more details.
731+
732+You should have received a copy of the GNU General Public License
733+along with GCC; see the file COPYING3. If not see
734+<http://www.gnu.org/licenses/>. */
735+
736+#undef WCHAR_TYPE
737+#define WCHAR_TYPE "int"
738+
739+#undef WCHAR_TYPE_SIZE
740+#define WCHAR_TYPE_SIZE 32
741+
742+#define TARGET_OS_CPP_BUILTINS() \
743+ do { \
744+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \
745+ /* The GNU C++ standard library requires this. */ \
746+ if (c_dialect_cxx ()) \
747+ builtin_define ("_GNU_SOURCE"); \
748+ } while (0)
749+
750+#undef SUBTARGET_CPP_SPEC
751+#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
752+
753+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
754+
755+/* Borrowed from sparc/linux.h */
756+#undef LINK_SPEC
757+#define LINK_SPEC \
758+ "%{shared:-shared} \
759+ %{!shared: \
760+ %{!static: \
761+ %{rdynamic:-export-dynamic} \
762+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER "} \
763+ %{static:-static}}"
764+
765+#undef LIB_SPEC
766+#define LIB_SPEC "\
767+%{pthread:-lpthread} \
768+%{shared:-lc} \
769+%{!shared: \
770+ %{profile:-lc_p} %{!profile:-lc}}"
771+
772+/* Similar to standard Linux, but adding -ffast-math support. */
773+#undef ENDFILE_SPEC
774+#define ENDFILE_SPEC \
775+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200776diff -urN empty/gcc/config/riscv/linux64.h gcc-5.2.0/gcc/config/riscv/linux64.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200777--- gcc-5.2.0/gcc/config/riscv/linux64.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200778+++ gcc-5.2.0/gcc/config/riscv/linux64.h 2015-07-17 22:36:52.319705931 +0200
779@@ -0,0 +1,43 @@
780+/* Definitions for 64-bit RISC-V GNU/Linux systems with ELF format.
781+ Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011
782+ Free Software Foundation, Inc.
783+
784+This file is part of GCC.
785+
786+GCC is free software; you can redistribute it and/or modify
787+it under the terms of the GNU General Public License as published by
788+the Free Software Foundation; either version 3, or (at your option)
789+any later version.
790+
791+GCC is distributed in the hope that it will be useful,
792+but WITHOUT ANY WARRANTY; without even the implied warranty of
793+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
794+GNU General Public License for more details.
795+
796+You should have received a copy of the GNU General Public License
797+along with GCC; see the file COPYING3. If not see
798+<http://www.gnu.org/licenses/>. */
799+
800+/* Force the default ABI flags onto the command line
801+ in order to make the other specs easier to write. */
802+#undef LIB_SPEC
803+#define LIB_SPEC "\
804+%{pthread:-lpthread} \
805+%{shared:-lc} \
806+%{!shared: \
807+ %{profile:-lc_p} %{!profile:-lc}}"
808+
809+#define GLIBC_DYNAMIC_LINKER32 "/lib32/ld.so.1"
810+#define GLIBC_DYNAMIC_LINKER64 "/lib/ld.so.1"
811+
812+#undef LINK_SPEC
813+#define LINK_SPEC "\
814+%{shared} \
815+ %{!shared: \
816+ %{!static: \
817+ %{rdynamic:-export-dynamic} \
818+ %{" OPT_ARCH64 ": -dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "} \
819+ %{" OPT_ARCH32 ": -dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "}} \
820+ %{static:-static}} \
821+%{" OPT_ARCH64 ":-melf64lriscv} \
822+%{" OPT_ARCH32 ":-melf32lriscv}"
823diff -urN empty/gcc/config/riscv/opcode-riscv.h gcc-5.2.0/gcc/config/riscv/opcode-riscv.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200824--- gcc-5.2.0/gcc/config/riscv/opcode-riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200825+++ gcc-5.2.0/gcc/config/riscv/opcode-riscv.h 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100826@@ -0,0 +1,149 @@
827+/* RISC-V ISA encoding.
828+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
829+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
830+ Based on MIPS target for GNU compiler.
831+
832+This file is part of GDB, GAS, and the GNU binutils.
833+
834+GDB, GAS, and the GNU binutils are free software; you can redistribute
835+them and/or modify them under the terms of the GNU General Public
836+License as published by the Free Software Foundation; either version
837+1, or (at your option) any later version.
838+
839+GDB, GAS, and the GNU binutils are distributed in the hope that they
840+will be useful, but WITHOUT ANY WARRANTY; without even the implied
841+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
842+the GNU General Public License for more details.
843+
844+You should have received a copy of the GNU General Public License
845+along with this file; see the file COPYING. If not, write to the Free
846+Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
847+
848+#ifndef _RISCV_H_
849+#define _RISCV_H_
850+
851+#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1))
852+#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
853+
854+#define EXTRACT_ITYPE_IMM(x) \
855+ (RV_X(x, 20, 12) | (RV_IMM_SIGN(x) << 12))
856+#define EXTRACT_STYPE_IMM(x) \
857+ (RV_X(x, 7, 5) | (RV_X(x, 25, 7) << 5) | (RV_IMM_SIGN(x) << 12))
858+#define EXTRACT_SBTYPE_IMM(x) \
859+ ((RV_X(x, 8, 4) << 1) | (RV_X(x, 25, 6) << 5) | (RV_X(x, 7, 1) << 11) | (RV_IMM_SIGN(x) << 12))
860+#define EXTRACT_UTYPE_IMM(x) \
861+ ((RV_X(x, 12, 20) << 20) | (RV_IMM_SIGN(x) << 32))
862+#define EXTRACT_UJTYPE_IMM(x) \
863+ ((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
864+
865+#define ENCODE_ITYPE_IMM(x) \
866+ (RV_X(x, 0, 12) << 20)
867+#define ENCODE_STYPE_IMM(x) \
868+ ((RV_X(x, 0, 5) << 7) | (RV_X(x, 5, 7) << 25))
869+#define ENCODE_SBTYPE_IMM(x) \
870+ ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31))
871+#define ENCODE_UTYPE_IMM(x) \
872+ (RV_X(x, 12, 20) << 12)
873+#define ENCODE_UJTYPE_IMM(x) \
874+ ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
875+
876+#define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
877+#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
878+#define VALID_SBTYPE_IMM(x) (EXTRACT_SBTYPE_IMM(ENCODE_SBTYPE_IMM(x)) == (x))
879+#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x))
880+#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x))
881+
882+#define RISCV_RTYPE(insn, rd, rs1, rs2) \
883+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
884+#define RISCV_ITYPE(insn, rd, rs1, imm) \
885+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ENCODE_ITYPE_IMM(imm))
886+#define RISCV_STYPE(insn, rs1, rs2, imm) \
887+ ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_STYPE_IMM(imm))
888+#define RISCV_SBTYPE(insn, rs1, rs2, target) \
889+ ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_SBTYPE_IMM(target))
890+#define RISCV_UTYPE(insn, rd, bigimm) \
891+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UTYPE_IMM(bigimm))
892+#define RISCV_UJTYPE(insn, rd, target) \
893+ ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UJTYPE_IMM(target))
894+
895+#define RISCV_NOP RISCV_ITYPE(ADDI, 0, 0, 0)
896+
897+#define RISCV_CONST_HIGH_PART(VALUE) \
898+ (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
899+#define RISCV_CONST_LOW_PART(VALUE) ((VALUE) - RISCV_CONST_HIGH_PART (VALUE))
900+
901+/* RV fields */
902+
903+#define OP_MASK_OP 0x7f
904+#define OP_SH_OP 0
905+#define OP_MASK_RS2 0x1f
906+#define OP_SH_RS2 20
907+#define OP_MASK_RS1 0x1f
908+#define OP_SH_RS1 15
909+#define OP_MASK_RS3 0x1f
910+#define OP_SH_RS3 27
911+#define OP_MASK_RD 0x1f
912+#define OP_SH_RD 7
913+#define OP_MASK_SHAMT 0x3f
914+#define OP_SH_SHAMT 20
915+#define OP_MASK_SHAMTW 0x1f
916+#define OP_SH_SHAMTW 20
917+#define OP_MASK_RM 0x7
918+#define OP_SH_RM 12
919+#define OP_MASK_PRED 0xf
920+#define OP_SH_PRED 24
921+#define OP_MASK_SUCC 0xf
922+#define OP_SH_SUCC 20
923+#define OP_MASK_AQ 0x1
924+#define OP_SH_AQ 26
925+#define OP_MASK_RL 0x1
926+#define OP_SH_RL 25
927+
928+#define OP_MASK_VRD 0x1f
929+#define OP_SH_VRD 7
930+#define OP_MASK_VRS 0x1f
931+#define OP_SH_VRS 15
932+#define OP_MASK_VRT 0x1f
933+#define OP_SH_VRT 20
934+#define OP_MASK_VRR 0x1f
935+#define OP_SH_VRR 25
936+
937+#define OP_MASK_VFD 0x1f
938+#define OP_SH_VFD 7
939+#define OP_MASK_VFS 0x1f
940+#define OP_SH_VFS 15
941+#define OP_MASK_VFT 0x1f
942+#define OP_SH_VFT 20
943+#define OP_MASK_VFR 0x1f
944+#define OP_SH_VFR 25
945+
946+#define OP_MASK_IMMNGPR 0x3f
947+#define OP_SH_IMMNGPR 20
948+#define OP_MASK_IMMNFPR 0x3f
949+#define OP_SH_IMMNFPR 26
950+#define OP_MASK_IMMSEGNELM 0x1f
951+#define OP_SH_IMMSEGNELM 17
952+#define OP_MASK_IMMSEGSTNELM 0x1f
953+#define OP_SH_IMMSEGSTNELM 12
954+#define OP_MASK_CUSTOM_IMM 0x7f
955+#define OP_SH_CUSTOM_IMM 25
956+
957+#define LINK_REG 1
958+
959+#define RISCV_JUMP_BITS RISCV_BIGIMM_BITS
960+#define RISCV_JUMP_ALIGN_BITS 1
961+#define RISCV_JUMP_ALIGN (1 << RISCV_JUMP_ALIGN_BITS)
962+#define RISCV_JUMP_REACH ((1ULL<<RISCV_JUMP_BITS)*RISCV_JUMP_ALIGN)
963+
964+#define RISCV_IMM_BITS 12
965+#define RISCV_BIGIMM_BITS (32-RISCV_IMM_BITS)
966+#define RISCV_IMM_REACH (1LL<<RISCV_IMM_BITS)
967+#define RISCV_BIGIMM_REACH (1LL<<RISCV_BIGIMM_BITS)
968+#define RISCV_BRANCH_BITS RISCV_IMM_BITS
969+#define RISCV_BRANCH_ALIGN_BITS RISCV_JUMP_ALIGN_BITS
970+#define RISCV_BRANCH_ALIGN (1 << RISCV_BRANCH_ALIGN_BITS)
971+#define RISCV_BRANCH_REACH (RISCV_IMM_REACH*RISCV_BRANCH_ALIGN)
972+
973+#include "riscv-opc.h"
974+
975+#endif /* _RISCV_H_ */
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200976diff -urN empty/gcc/config/riscv/peephole.md gcc-5.2.0/gcc/config/riscv/peephole.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +0200977--- gcc-5.2.0/gcc/config/riscv/peephole.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +0200978+++ gcc-5.2.0/gcc/config/riscv/peephole.md 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +0100979@@ -0,0 +1,100 @@
980+;;........................
981+;; DI -> SI optimizations
982+;;........................
983+
984+;; Simplify (int)(a + 1), etc.
985+(define_peephole2
986+ [(set (match_operand:DI 0 "register_operand")
987+ (match_operator:DI 4 "modular_operator"
988+ [(match_operand:DI 1 "register_operand")
989+ (match_operand:DI 2 "arith_operand")]))
990+ (set (match_operand:SI 3 "register_operand")
991+ (truncate:SI (match_dup 0)))]
992+ "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))
993+ && (GET_CODE (operands[4]) != ASHIFT || (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 32))"
994+ [(set (match_dup 3)
995+ (truncate:SI
996+ (match_op_dup:DI 4
997+ [(match_operand:DI 1 "register_operand")
998+ (match_operand:DI 2 "arith_operand")])))])
999+
1000+;; Simplify (int)a + 1, etc.
1001+(define_peephole2
1002+ [(set (match_operand:SI 0 "register_operand")
1003+ (truncate:SI (match_operand:DI 1 "register_operand")))
1004+ (set (match_operand:SI 3 "register_operand")
1005+ (match_operator:SI 4 "modular_operator"
1006+ [(match_dup 0)
1007+ (match_operand:SI 2 "arith_operand")]))]
1008+ "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))"
1009+ [(set (match_dup 3)
1010+ (match_op_dup:SI 4 [(match_dup 1) (match_dup 2)]))])
1011+
1012+;; Simplify -(int)a, etc.
1013+(define_peephole2
1014+ [(set (match_operand:SI 0 "register_operand")
1015+ (truncate:SI (match_operand:DI 2 "register_operand")))
1016+ (set (match_operand:SI 3 "register_operand")
1017+ (match_operator:SI 4 "modular_operator"
1018+ [(match_operand:SI 1 "reg_or_0_operand")
1019+ (match_dup 0)]))]
1020+ "TARGET_64BIT && (REGNO (operands[0]) == REGNO (operands[3]) || peep2_reg_dead_p (2, operands[0]))"
1021+ [(set (match_dup 3)
1022+ (match_op_dup:SI 4 [(match_dup 1) (match_dup 2)]))])
1023+
1024+;; Simplify PIC loads to static variables.
1025+;; These will go away once we figure out how to emit auipc discretely.
1026+(define_insn "*local_pic_load<mode>"
1027+ [(set (match_operand:ANYI 0 "register_operand" "=r")
1028+ (mem:ANYI (match_operand 1 "absolute_symbolic_operand" "")))]
1029+ "flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
1030+ "<load>\t%0,%1"
1031+ [(set (attr "length") (const_int 8))])
1032+(define_insn "*local_pic_load<mode>"
1033+ [(set (match_operand:ANYF 0 "register_operand" "=f")
1034+ (mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
1035+ (clobber (match_scratch:DI 2 "=&r"))]
1036+ "TARGET_HARD_FLOAT && TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
1037+ "<load>\t%0,%1,%2"
1038+ [(set (attr "length") (const_int 8))])
1039+(define_insn "*local_pic_load<mode>"
1040+ [(set (match_operand:ANYF 0 "register_operand" "=f")
1041+ (mem:ANYF (match_operand 1 "absolute_symbolic_operand" "")))
1042+ (clobber (match_scratch:SI 2 "=&r"))]
1043+ "TARGET_HARD_FLOAT && !TARGET_64BIT && flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
1044+ "<load>\t%0,%1,%2"
1045+ [(set (attr "length") (const_int 8))])
1046+(define_insn "*local_pic_loadu<mode>"
1047+ [(set (match_operand:SUPERQI 0 "register_operand" "=r")
1048+ (zero_extend:SUPERQI (mem:SUBDI (match_operand 1 "absolute_symbolic_operand" ""))))]
1049+ "flag_pic && SYMBOL_REF_LOCAL_P (operands[1])"
1050+ "<load>u\t%0,%1"
1051+ [(set (attr "length") (const_int 8))])
1052+(define_insn "*local_pic_storedi<mode>"
1053+ [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
1054+ (match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
1055+ (clobber (match_scratch:DI 2 "=&r"))]
1056+ "TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
1057+ "<store>\t%z1,%0,%2"
1058+ [(set (attr "length") (const_int 8))])
1059+(define_insn "*local_pic_storesi<mode>"
1060+ [(set (mem:ANYI (match_operand 0 "absolute_symbolic_operand" ""))
1061+ (match_operand:ANYI 1 "reg_or_0_operand" "rJ"))
1062+ (clobber (match_scratch:SI 2 "=&r"))]
1063+ "!TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
1064+ "<store>\t%z1,%0,%2"
1065+ [(set (attr "length") (const_int 8))])
1066+(define_insn "*local_pic_storedi<mode>"
1067+ [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
1068+ (match_operand:ANYF 1 "register_operand" "f"))
1069+ (clobber (match_scratch:DI 2 "=&r"))]
1070+ "TARGET_HARD_FLOAT && TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
1071+ "<store>\t%1,%0,%2"
1072+ [(set (attr "length") (const_int 8))])
1073+(define_insn "*local_pic_storesi<mode>"
1074+ [(set (mem:ANYF (match_operand 0 "absolute_symbolic_operand" ""))
1075+ (match_operand:ANYF 1 "register_operand" "f"))
1076+ (clobber (match_scratch:SI 2 "=&r"))]
1077+ "TARGET_HARD_FLOAT && !TARGET_64BIT && (flag_pic && SYMBOL_REF_LOCAL_P (operands[0]))"
1078+ "<store>\t%1,%0,%2"
1079+ [(set (attr "length") (const_int 8))])
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001080diff -urN empty/gcc/config/riscv/predicates.md gcc-5.2.0/gcc/config/riscv/predicates.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +02001081--- gcc-5.2.0/gcc/config/riscv/predicates.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001082+++ gcc-5.2.0/gcc/config/riscv/predicates.md 2015-07-17 22:36:52.319705931 +0200
1083@@ -0,0 +1,187 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01001084+;; Predicate description for RISC-V target.
1085+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
1086+;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
1087+;; Based on MIPS target for GNU compiler.
1088+;;
1089+;; This file is part of GCC.
1090+;;
1091+;; GCC is free software; you can redistribute it and/or modify
1092+;; it under the terms of the GNU General Public License as published by
1093+;; the Free Software Foundation; either version 3, or (at your option)
1094+;; any later version.
1095+;;
1096+;; GCC is distributed in the hope that it will be useful,
1097+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1098+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1099+;; GNU General Public License for more details.
1100+;;
1101+;; You should have received a copy of the GNU General Public License
1102+;; along with GCC; see the file COPYING3. If not see
1103+;; <http://www.gnu.org/licenses/>.
1104+
1105+(define_predicate "const_arith_operand"
1106+ (and (match_code "const_int")
1107+ (match_test "SMALL_OPERAND (INTVAL (op))")))
1108+
1109+(define_predicate "arith_operand"
1110+ (ior (match_operand 0 "const_arith_operand")
1111+ (match_operand 0 "register_operand")))
1112+
1113+(define_predicate "sle_operand"
1114+ (and (match_code "const_int")
1115+ (match_test "SMALL_OPERAND (INTVAL (op) + 1)")))
1116+
1117+(define_predicate "sleu_operand"
1118+ (and (match_operand 0 "sle_operand")
1119+ (match_test "INTVAL (op) + 1 != 0")))
1120+
1121+(define_predicate "const_0_operand"
1122+ (and (match_code "const_int,const_double,const_vector")
1123+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
1124+
1125+(define_predicate "reg_or_0_operand"
1126+ (ior (match_operand 0 "const_0_operand")
1127+ (match_operand 0 "register_operand")))
1128+
1129+(define_predicate "const_1_operand"
1130+ (and (match_code "const_int,const_double,const_vector")
1131+ (match_test "op == CONST1_RTX (GET_MODE (op))")))
1132+
1133+(define_predicate "reg_or_1_operand"
1134+ (ior (match_operand 0 "const_1_operand")
1135+ (match_operand 0 "register_operand")))
1136+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001137+;; Only use branch-on-bit sequences when the mask is not an ANDI immediate.
1138+(define_predicate "branch_on_bit_operand"
1139+ (and (match_code "const_int")
1140+ (match_test "INTVAL (op) >= RISCV_IMM_BITS - 1")))
1141+
Patrick Georgif0bbc952015-03-07 10:57:25 +01001142+;; This is used for indexing into vectors, and hence only accepts const_int.
1143+(define_predicate "const_0_or_1_operand"
1144+ (and (match_code "const_int")
1145+ (ior (match_test "op == CONST0_RTX (GET_MODE (op))")
1146+ (match_test "op == CONST1_RTX (GET_MODE (op))"))))
1147+
1148+(define_special_predicate "pc_or_label_operand"
1149+ (match_code "pc,label_ref"))
1150+
1151+;; A legitimate CONST_INT operand that takes more than one instruction
1152+;; to load.
1153+(define_predicate "splittable_const_int_operand"
1154+ (match_code "const_int")
1155+{
1156+ /* Don't handle multi-word moves this way; we don't want to introduce
1157+ the individual word-mode moves until after reload. */
1158+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
1159+ return false;
1160+
1161+ /* Otherwise check whether the constant can be loaded in a single
1162+ instruction. */
1163+ return !LUI_INT (op) && !SMALL_INT (op);
1164+})
1165+
1166+(define_predicate "move_operand"
1167+ (match_operand 0 "general_operand")
1168+{
1169+ enum riscv_symbol_type symbol_type;
1170+
1171+ /* The thinking here is as follows:
1172+
1173+ (1) The move expanders should split complex load sequences into
1174+ individual instructions. Those individual instructions can
1175+ then be optimized by all rtl passes.
1176+
1177+ (2) The target of pre-reload load sequences should not be used
1178+ to store temporary results. If the target register is only
1179+ assigned one value, reload can rematerialize that value
1180+ on demand, rather than spill it to the stack.
1181+
1182+ (3) If we allowed pre-reload passes like combine and cse to recreate
1183+ complex load sequences, we would want to be able to split the
1184+ sequences before reload as well, so that the pre-reload scheduler
1185+ can see the individual instructions. This falls foul of (2);
1186+ the splitter would be forced to reuse the target register for
1187+ intermediate results.
1188+
1189+ (4) We want to define complex load splitters for combine. These
1190+ splitters can request a temporary scratch register, which avoids
1191+ the problem in (2). They allow things like:
1192+
1193+ (set (reg T1) (high SYM))
1194+ (set (reg T2) (low (reg T1) SYM))
1195+ (set (reg X) (plus (reg T2) (const_int OFFSET)))
1196+
1197+ to be combined into:
1198+
1199+ (set (reg T3) (high SYM+OFFSET))
1200+ (set (reg X) (lo_sum (reg T3) SYM+OFFSET))
1201+
1202+ if T2 is only used this once. */
1203+ switch (GET_CODE (op))
1204+ {
1205+ case CONST_INT:
1206+ return !splittable_const_int_operand (op, mode);
1207+
1208+ case CONST:
1209+ case SYMBOL_REF:
1210+ case LABEL_REF:
1211+ return (riscv_symbolic_constant_p (op, &symbol_type)
1212+ && !riscv_hi_relocs[symbol_type]);
1213+
1214+ case HIGH:
1215+ op = XEXP (op, 0);
1216+ return riscv_symbolic_constant_p (op, &symbol_type);
1217+
1218+ default:
1219+ return true;
1220+ }
1221+})
1222+
1223+(define_predicate "consttable_operand"
1224+ (match_test "CONSTANT_P (op)"))
1225+
1226+(define_predicate "symbolic_operand"
1227+ (match_code "const,symbol_ref,label_ref")
1228+{
1229+ enum riscv_symbol_type type;
1230+ return riscv_symbolic_constant_p (op, &type);
1231+})
1232+
1233+(define_predicate "absolute_symbolic_operand"
1234+ (match_code "const,symbol_ref,label_ref")
1235+{
1236+ enum riscv_symbol_type type;
1237+ return (riscv_symbolic_constant_p (op, &type)
1238+ && type == SYMBOL_ABSOLUTE);
1239+})
1240+
1241+(define_predicate "plt_symbolic_operand"
1242+ (match_code "const,symbol_ref,label_ref")
1243+{
1244+ enum riscv_symbol_type type;
1245+ return (riscv_symbolic_constant_p (op, &type)
1246+ && type == SYMBOL_GOT_DISP && !SYMBOL_REF_WEAK (op) && TARGET_PLT);
1247+})
1248+
1249+(define_predicate "call_insn_operand"
1250+ (ior (match_operand 0 "absolute_symbolic_operand")
1251+ (match_operand 0 "plt_symbolic_operand")
1252+ (match_operand 0 "register_operand")))
1253+
1254+(define_predicate "symbol_ref_operand"
1255+ (match_code "symbol_ref"))
1256+
1257+(define_predicate "modular_operator"
1258+ (match_code "plus,minus,mult,ashift"))
1259+
1260+(define_predicate "equality_operator"
1261+ (match_code "eq,ne"))
1262+
1263+(define_predicate "order_operator"
1264+ (match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu"))
1265+
1266+(define_predicate "fp_order_operator"
1267+ (match_code "eq,lt,le,gt,ge"))
1268+
1269+(define_predicate "fp_unorder_operator"
1270+ (match_code "ordered,unordered"))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001271diff -urN empty/gcc/config/riscv/riscv-ftypes.def gcc-5.2.0/gcc/config/riscv/riscv-ftypes.def
Patrick Georgi410f9ad2015-08-23 21:07:46 +02001272--- gcc-5.2.0/gcc/config/riscv/riscv-ftypes.def 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001273+++ gcc-5.2.0/gcc/config/riscv/riscv-ftypes.def 2015-07-17 22:36:52.319705931 +0200
1274@@ -0,0 +1,39 @@
1275+/* Definitions of prototypes for RISC-V built-in functions.
1276+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
1277+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
1278+ Based on MIPS target for GNU compiler.
1279+
1280+This file is part of GCC.
1281+
1282+GCC is free software; you can redistribute it and/or modify
1283+it under the terms of the GNU General Public License as published by
1284+the Free Software Foundation; either version 3, or (at your option)
1285+any later version.
1286+
1287+GCC is distributed in the hope that it will be useful,
1288+but WITHOUT ANY WARRANTY; without even the implied warranty of
1289+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1290+GNU General Public License for more details.
1291+
1292+You should have received a copy of the GNU General Public License
1293+along with GCC; see the file COPYING3. If not see
1294+<http://www.gnu.org/licenses/>. */
1295+
1296+/* Invoke DEF_RISCV_FTYPE (NARGS, LIST) for each prototype used by
1297+ MIPS built-in functions, where:
1298+
1299+ NARGS is the number of arguments.
1300+ LIST contains the return-type code followed by the codes for each
1301+ argument type.
1302+
1303+ Argument- and return-type codes are either modes or one of the following:
1304+
1305+ VOID for void_type_node
1306+ INT for integer_type_node
1307+ POINTER for ptr_type_node
1308+
1309+ (we don't use PTR because that's a ANSI-compatibillity macro).
1310+
1311+ Please keep this list lexicographically sorted by the LIST argument. */
1312+
1313+DEF_RISCV_FTYPE (1, (VOID, VOID))
1314diff -urN empty/gcc/config/riscv/riscv-modes.def gcc-5.2.0/gcc/config/riscv/riscv-modes.def
Patrick Georgi410f9ad2015-08-23 21:07:46 +02001315--- gcc-5.2.0/gcc/config/riscv/riscv-modes.def 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001316+++ gcc-5.2.0/gcc/config/riscv/riscv-modes.def 2015-07-17 22:36:52.319705931 +0200
1317@@ -0,0 +1,26 @@
1318+/* Extra machine modes for RISC-V target.
1319+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
1320+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
1321+ Based on MIPS target for GNU compiler.
1322+
1323+This file is part of GCC.
1324+
1325+GCC is free software; you can redistribute it and/or modify
1326+it under the terms of the GNU General Public License as published by
1327+the Free Software Foundation; either version 3, or (at your option)
1328+any later version.
1329+
1330+GCC is distributed in the hope that it will be useful,
1331+but WITHOUT ANY WARRANTY; without even the implied warranty of
1332+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1333+GNU General Public License for more details.
1334+
1335+You should have received a copy of the GNU General Public License
1336+along with GCC; see the file COPYING3. If not see
1337+<http://www.gnu.org/licenses/>. */
1338+
1339+FLOAT_MODE (TF, 16, ieee_quad_format);
1340+
1341+/* Vector modes. */
1342+VECTOR_MODES (INT, 4); /* V8QI V4HI V2SI */
1343+VECTOR_MODES (FLOAT, 4); /* V4HF V2SF */
1344diff -urN empty/gcc/config/riscv/riscv-opc.h gcc-5.2.0/gcc/config/riscv/riscv-opc.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +02001345--- gcc-5.2.0/gcc/config/riscv/riscv-opc.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02001346+++ gcc-5.2.0/gcc/config/riscv/riscv-opc.h 2015-07-17 22:36:52.319705931 +0200
1347@@ -0,0 +1,1348 @@
1348+/* Automatically generated by parse-opcodes */
1349+#ifndef RISCV_ENCODING_H
1350+#define RISCV_ENCODING_H
1351+#define MATCH_ADD 0x33
1352+#define MASK_ADD 0xfe00707f
1353+#define MATCH_ADDI 0x13
1354+#define MASK_ADDI 0x707f
1355+#define MATCH_ADDIW 0x1b
1356+#define MASK_ADDIW 0x707f
1357+#define MATCH_ADDW 0x3b
1358+#define MASK_ADDW 0xfe00707f
1359+#define MATCH_AMOADD_D 0x302f
1360+#define MASK_AMOADD_D 0xf800707f
1361+#define MATCH_AMOADD_W 0x202f
1362+#define MASK_AMOADD_W 0xf800707f
1363+#define MATCH_AMOAND_D 0x6000302f
1364+#define MASK_AMOAND_D 0xf800707f
1365+#define MATCH_AMOAND_W 0x6000202f
1366+#define MASK_AMOAND_W 0xf800707f
1367+#define MATCH_AMOMAX_D 0xa000302f
1368+#define MASK_AMOMAX_D 0xf800707f
1369+#define MATCH_AMOMAX_W 0xa000202f
1370+#define MASK_AMOMAX_W 0xf800707f
1371+#define MATCH_AMOMAXU_D 0xe000302f
1372+#define MASK_AMOMAXU_D 0xf800707f
1373+#define MATCH_AMOMAXU_W 0xe000202f
1374+#define MASK_AMOMAXU_W 0xf800707f
1375+#define MATCH_AMOMIN_D 0x8000302f
1376+#define MASK_AMOMIN_D 0xf800707f
1377+#define MATCH_AMOMIN_W 0x8000202f
1378+#define MASK_AMOMIN_W 0xf800707f
1379+#define MATCH_AMOMINU_D 0xc000302f
1380+#define MASK_AMOMINU_D 0xf800707f
1381+#define MATCH_AMOMINU_W 0xc000202f
1382+#define MASK_AMOMINU_W 0xf800707f
1383+#define MATCH_AMOOR_D 0x4000302f
1384+#define MASK_AMOOR_D 0xf800707f
1385+#define MATCH_AMOOR_W 0x4000202f
1386+#define MASK_AMOOR_W 0xf800707f
1387+#define MATCH_AMOSWAP_D 0x800302f
1388+#define MASK_AMOSWAP_D 0xf800707f
1389+#define MATCH_AMOSWAP_W 0x800202f
1390+#define MASK_AMOSWAP_W 0xf800707f
1391+#define MATCH_AMOXOR_D 0x2000302f
1392+#define MASK_AMOXOR_D 0xf800707f
1393+#define MATCH_AMOXOR_W 0x2000202f
1394+#define MASK_AMOXOR_W 0xf800707f
1395+#define MATCH_AND 0x7033
1396+#define MASK_AND 0xfe00707f
1397+#define MATCH_ANDI 0x7013
1398+#define MASK_ANDI 0x707f
1399+#define MATCH_AUIPC 0x17
1400+#define MASK_AUIPC 0x7f
1401+#define MATCH_BEQ 0x63
1402+#define MASK_BEQ 0x707f
1403+#define MATCH_BGE 0x5063
1404+#define MASK_BGE 0x707f
1405+#define MATCH_BGEU 0x7063
1406+#define MASK_BGEU 0x707f
1407+#define MATCH_BLT 0x4063
1408+#define MASK_BLT 0x707f
1409+#define MATCH_BLTU 0x6063
1410+#define MASK_BLTU 0x707f
1411+#define MATCH_BNE 0x1063
1412+#define MASK_BNE 0x707f
1413+#define MATCH_C_ADD 0x1000
1414+#define MASK_C_ADD 0xf003
1415+#define MATCH_C_ADD3 0xa000
1416+#define MASK_C_ADD3 0xe063
1417+#define MATCH_C_ADDI 0xc002
1418+#define MASK_C_ADDI 0xe003
1419+#define MATCH_C_ADDI16SP 0xc002
1420+#define MASK_C_ADDI16SP 0xef83
1421+#define MATCH_C_ADDI4SPN 0xa001
1422+#define MASK_C_ADDI4SPN 0xe003
1423+#define MATCH_C_ADDIN 0x8001
1424+#define MASK_C_ADDIN 0xe063
1425+#define MATCH_C_ADDIW 0xe002
1426+#define MASK_C_ADDIW 0xe003
1427+#define MATCH_C_ADDW 0x9000
1428+#define MASK_C_ADDW 0xf003
1429+#define MATCH_C_AND3 0xa060
1430+#define MASK_C_AND3 0xe063
1431+#define MATCH_C_ANDI 0xe002
1432+#define MASK_C_ANDI 0xe003
1433+#define MATCH_C_ANDIN 0x8061
1434+#define MASK_C_ANDIN 0xe063
1435+#define MATCH_C_BEQZ 0x4002
1436+#define MASK_C_BEQZ 0xe003
1437+#define MATCH_C_BGEZ 0xe001
1438+#define MASK_C_BGEZ 0xe003
1439+#define MATCH_C_BLTZ 0x6001
1440+#define MASK_C_BLTZ 0xe003
1441+#define MATCH_C_BNEZ 0x6002
1442+#define MASK_C_BNEZ 0xe003
1443+#define MATCH_C_EBREAK 0x1000
1444+#define MASK_C_EBREAK 0xffff
1445+#define MATCH_C_J 0x2
1446+#define MASK_C_J 0xe003
1447+#define MATCH_C_JAL 0x2002
1448+#define MASK_C_JAL 0xe003
1449+#define MATCH_C_JALR 0xa002
1450+#define MASK_C_JALR 0xf07f
1451+#define MATCH_C_JR 0x8002
1452+#define MASK_C_JR 0xf07f
1453+#define MATCH_C_LD 0xe000
1454+#define MASK_C_LD 0xe003
1455+#define MATCH_C_LDSP 0xe001
1456+#define MASK_C_LDSP 0xe003
1457+#define MATCH_C_LI 0x8002
1458+#define MASK_C_LI 0xe003
1459+#define MATCH_C_LUI 0xa002
1460+#define MASK_C_LUI 0xe003
1461+#define MATCH_C_LW 0xc000
1462+#define MASK_C_LW 0xe003
1463+#define MATCH_C_LWSP 0xc001
1464+#define MASK_C_LWSP 0xe003
1465+#define MATCH_C_MV 0x0
1466+#define MASK_C_MV 0xf003
1467+#define MATCH_C_OR3 0xa040
1468+#define MASK_C_OR3 0xe063
1469+#define MATCH_C_ORIN 0x8041
1470+#define MASK_C_ORIN 0xe063
1471+#define MATCH_C_SD 0x6000
1472+#define MASK_C_SD 0xe003
1473+#define MATCH_C_SDSP 0x6001
1474+#define MASK_C_SDSP 0xe003
1475+#define MATCH_C_SLL 0x6400
1476+#define MASK_C_SLL 0xfc63
1477+#define MATCH_C_SLLI 0x1
1478+#define MASK_C_SLLI 0xe003
1479+#define MATCH_C_SLLIW 0x8001
1480+#define MASK_C_SLLIW 0xe003
1481+#define MATCH_C_SLLR 0x6c00
1482+#define MASK_C_SLLR 0xfc63
1483+#define MATCH_C_SLT 0x6440
1484+#define MASK_C_SLT 0xfc63
1485+#define MATCH_C_SLTR 0x6c40
1486+#define MASK_C_SLTR 0xfc63
1487+#define MATCH_C_SLTU 0x6460
1488+#define MASK_C_SLTU 0xfc63
1489+#define MATCH_C_SLTUR 0x6c60
1490+#define MASK_C_SLTUR 0xfc63
1491+#define MATCH_C_SRA 0x6020
1492+#define MASK_C_SRA 0xfc63
1493+#define MATCH_C_SRAI 0x2000
1494+#define MASK_C_SRAI 0xe003
1495+#define MATCH_C_SRL 0x6420
1496+#define MASK_C_SRL 0xfc63
1497+#define MATCH_C_SRLI 0x2001
1498+#define MASK_C_SRLI 0xe003
1499+#define MATCH_C_SRLR 0x6c20
1500+#define MASK_C_SRLR 0xfc63
1501+#define MATCH_C_SUB 0x8000
1502+#define MASK_C_SUB 0xf003
1503+#define MATCH_C_SUB3 0xa020
1504+#define MASK_C_SUB3 0xe063
1505+#define MATCH_C_SW 0x4000
1506+#define MASK_C_SW 0xe003
1507+#define MATCH_C_SWSP 0x4001
1508+#define MASK_C_SWSP 0xe003
1509+#define MATCH_C_XOR 0x6000
1510+#define MASK_C_XOR 0xfc63
1511+#define MATCH_C_XORIN 0x8021
1512+#define MASK_C_XORIN 0xe063
1513+#define MATCH_CSRRC 0x3073
1514+#define MASK_CSRRC 0x707f
1515+#define MATCH_CSRRCI 0x7073
1516+#define MASK_CSRRCI 0x707f
1517+#define MATCH_CSRRS 0x2073
1518+#define MASK_CSRRS 0x707f
1519+#define MATCH_CSRRSI 0x6073
1520+#define MASK_CSRRSI 0x707f
1521+#define MATCH_CSRRW 0x1073
1522+#define MASK_CSRRW 0x707f
1523+#define MATCH_CSRRWI 0x5073
1524+#define MASK_CSRRWI 0x707f
1525+#define MATCH_CUSTOM0 0xb
1526+#define MASK_CUSTOM0 0x707f
1527+#define MATCH_CUSTOM0_RD 0x400b
1528+#define MASK_CUSTOM0_RD 0x707f
1529+#define MATCH_CUSTOM0_RD_RS1 0x600b
1530+#define MASK_CUSTOM0_RD_RS1 0x707f
1531+#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
1532+#define MASK_CUSTOM0_RD_RS1_RS2 0x707f
1533+#define MATCH_CUSTOM0_RS1 0x200b
1534+#define MASK_CUSTOM0_RS1 0x707f
1535+#define MATCH_CUSTOM0_RS1_RS2 0x300b
1536+#define MASK_CUSTOM0_RS1_RS2 0x707f
1537+#define MATCH_CUSTOM1 0x2b
1538+#define MASK_CUSTOM1 0x707f
1539+#define MATCH_CUSTOM1_RD 0x402b
1540+#define MASK_CUSTOM1_RD 0x707f
1541+#define MATCH_CUSTOM1_RD_RS1 0x602b
1542+#define MASK_CUSTOM1_RD_RS1 0x707f
1543+#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
1544+#define MASK_CUSTOM1_RD_RS1_RS2 0x707f
1545+#define MATCH_CUSTOM1_RS1 0x202b
1546+#define MASK_CUSTOM1_RS1 0x707f
1547+#define MATCH_CUSTOM1_RS1_RS2 0x302b
1548+#define MASK_CUSTOM1_RS1_RS2 0x707f
1549+#define MATCH_CUSTOM2 0x5b
1550+#define MASK_CUSTOM2 0x707f
1551+#define MATCH_CUSTOM2_RD 0x405b
1552+#define MASK_CUSTOM2_RD 0x707f
1553+#define MATCH_CUSTOM2_RD_RS1 0x605b
1554+#define MASK_CUSTOM2_RD_RS1 0x707f
1555+#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
1556+#define MASK_CUSTOM2_RD_RS1_RS2 0x707f
1557+#define MATCH_CUSTOM2_RS1 0x205b
1558+#define MASK_CUSTOM2_RS1 0x707f
1559+#define MATCH_CUSTOM2_RS1_RS2 0x305b
1560+#define MASK_CUSTOM2_RS1_RS2 0x707f
1561+#define MATCH_CUSTOM3 0x7b
1562+#define MASK_CUSTOM3 0x707f
1563+#define MATCH_CUSTOM3_RD 0x407b
1564+#define MASK_CUSTOM3_RD 0x707f
1565+#define MATCH_CUSTOM3_RD_RS1 0x607b
1566+#define MASK_CUSTOM3_RD_RS1 0x707f
1567+#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
1568+#define MASK_CUSTOM3_RD_RS1_RS2 0x707f
1569+#define MATCH_CUSTOM3_RS1 0x207b
1570+#define MASK_CUSTOM3_RS1 0x707f
1571+#define MATCH_CUSTOM3_RS1_RS2 0x307b
1572+#define MASK_CUSTOM3_RS1_RS2 0x707f
1573+#define MATCH_DIV 0x2004033
1574+#define MASK_DIV 0xfe00707f
1575+#define MATCH_DIVU 0x2005033
1576+#define MASK_DIVU 0xfe00707f
1577+#define MATCH_DIVUW 0x200503b
1578+#define MASK_DIVUW 0xfe00707f
1579+#define MATCH_DIVW 0x200403b
1580+#define MASK_DIVW 0xfe00707f
1581+#define MATCH_EBREAK 0x100073
1582+#define MASK_EBREAK 0xffffffff
1583+#define MATCH_ECALL 0x73
1584+#define MASK_ECALL 0xffffffff
1585+#define MATCH_ERET 0x10000073
1586+#define MASK_ERET 0xffffffff
1587+#define MATCH_FADD_D 0x2000053
1588+#define MASK_FADD_D 0xfe00007f
1589+#define MATCH_FADD_H 0x4000053
1590+#define MASK_FADD_H 0xfe00007f
1591+#define MATCH_FADD_S 0x53
1592+#define MASK_FADD_S 0xfe00007f
1593+#define MATCH_FCLASS_D 0xe2001053
1594+#define MASK_FCLASS_D 0xfff0707f
1595+#define MATCH_FCLASS_S 0xe0001053
1596+#define MASK_FCLASS_S 0xfff0707f
1597+#define MATCH_FCVT_D_H 0x8c000053
1598+#define MASK_FCVT_D_H 0xfff0007f
1599+#define MATCH_FCVT_D_L 0xd2200053
1600+#define MASK_FCVT_D_L 0xfff0007f
1601+#define MATCH_FCVT_D_LU 0xd2300053
1602+#define MASK_FCVT_D_LU 0xfff0007f
1603+#define MATCH_FCVT_D_S 0x42000053
1604+#define MASK_FCVT_D_S 0xfff0007f
1605+#define MATCH_FCVT_D_W 0xd2000053
1606+#define MASK_FCVT_D_W 0xfff0007f
1607+#define MATCH_FCVT_D_WU 0xd2100053
1608+#define MASK_FCVT_D_WU 0xfff0007f
1609+#define MATCH_FCVT_H_D 0x92000053
1610+#define MASK_FCVT_H_D 0xfff0007f
1611+#define MATCH_FCVT_H_L 0x64000053
1612+#define MASK_FCVT_H_L 0xfff0007f
1613+#define MATCH_FCVT_H_LU 0x6c000053
1614+#define MASK_FCVT_H_LU 0xfff0007f
1615+#define MATCH_FCVT_H_S 0x90000053
1616+#define MASK_FCVT_H_S 0xfff0007f
1617+#define MATCH_FCVT_H_W 0x74000053
1618+#define MASK_FCVT_H_W 0xfff0007f
1619+#define MATCH_FCVT_H_WU 0x7c000053
1620+#define MASK_FCVT_H_WU 0xfff0007f
1621+#define MATCH_FCVT_L_D 0xc2200053
1622+#define MASK_FCVT_L_D 0xfff0007f
1623+#define MATCH_FCVT_L_H 0x44000053
1624+#define MASK_FCVT_L_H 0xfff0007f
1625+#define MATCH_FCVT_L_S 0xc0200053
1626+#define MASK_FCVT_L_S 0xfff0007f
1627+#define MATCH_FCVT_LU_D 0xc2300053
1628+#define MASK_FCVT_LU_D 0xfff0007f
1629+#define MATCH_FCVT_LU_H 0x4c000053
1630+#define MASK_FCVT_LU_H 0xfff0007f
1631+#define MATCH_FCVT_LU_S 0xc0300053
1632+#define MASK_FCVT_LU_S 0xfff0007f
1633+#define MATCH_FCVT_S_D 0x40100053
1634+#define MASK_FCVT_S_D 0xfff0007f
1635+#define MATCH_FCVT_S_H 0x84000053
1636+#define MASK_FCVT_S_H 0xfff0007f
1637+#define MATCH_FCVT_S_L 0xd0200053
1638+#define MASK_FCVT_S_L 0xfff0007f
1639+#define MATCH_FCVT_S_LU 0xd0300053
1640+#define MASK_FCVT_S_LU 0xfff0007f
1641+#define MATCH_FCVT_S_W 0xd0000053
1642+#define MASK_FCVT_S_W 0xfff0007f
1643+#define MATCH_FCVT_S_WU 0xd0100053
1644+#define MASK_FCVT_S_WU 0xfff0007f
1645+#define MATCH_FCVT_W_D 0xc2000053
1646+#define MASK_FCVT_W_D 0xfff0007f
1647+#define MATCH_FCVT_W_H 0x54000053
1648+#define MASK_FCVT_W_H 0xfff0007f
1649+#define MATCH_FCVT_W_S 0xc0000053
1650+#define MASK_FCVT_W_S 0xfff0007f
1651+#define MATCH_FCVT_WU_D 0xc2100053
1652+#define MASK_FCVT_WU_D 0xfff0007f
1653+#define MATCH_FCVT_WU_H 0x5c000053
1654+#define MASK_FCVT_WU_H 0xfff0007f
1655+#define MATCH_FCVT_WU_S 0xc0100053
1656+#define MASK_FCVT_WU_S 0xfff0007f
1657+#define MATCH_FDIV_D 0x1a000053
1658+#define MASK_FDIV_D 0xfe00007f
1659+#define MATCH_FDIV_H 0x1c000053
1660+#define MASK_FDIV_H 0xfe00007f
1661+#define MATCH_FDIV_S 0x18000053
1662+#define MASK_FDIV_S 0xfe00007f
1663+#define MATCH_FENCE 0xf
1664+#define MASK_FENCE 0x707f
1665+#define MATCH_FENCE_I 0x100f
1666+#define MASK_FENCE_I 0x707f
1667+#define MATCH_FEQ_D 0xa2002053
1668+#define MASK_FEQ_D 0xfe00707f
1669+#define MATCH_FEQ_H 0xac000053
1670+#define MASK_FEQ_H 0xfe00707f
1671+#define MATCH_FEQ_S 0xa0002053
1672+#define MASK_FEQ_S 0xfe00707f
1673+#define MATCH_FLD 0x3007
1674+#define MASK_FLD 0x707f
1675+#define MATCH_FLE_D 0xa2000053
1676+#define MASK_FLE_D 0xfe00707f
1677+#define MATCH_FLE_H 0xbc000053
1678+#define MASK_FLE_H 0xfe00707f
1679+#define MATCH_FLE_S 0xa0000053
1680+#define MASK_FLE_S 0xfe00707f
1681+#define MATCH_FLH 0x1007
1682+#define MASK_FLH 0x707f
1683+#define MATCH_FLT_D 0xa2001053
1684+#define MASK_FLT_D 0xfe00707f
1685+#define MATCH_FLT_H 0xb4000053
1686+#define MASK_FLT_H 0xfe00707f
1687+#define MATCH_FLT_S 0xa0001053
1688+#define MASK_FLT_S 0xfe00707f
1689+#define MATCH_FLW 0x2007
1690+#define MASK_FLW 0x707f
1691+#define MATCH_FMADD_D 0x2000043
1692+#define MASK_FMADD_D 0x600007f
1693+#define MATCH_FMADD_H 0x4000043
1694+#define MASK_FMADD_H 0x600007f
1695+#define MATCH_FMADD_S 0x43
1696+#define MASK_FMADD_S 0x600007f
1697+#define MATCH_FMAX_D 0x2a001053
1698+#define MASK_FMAX_D 0xfe00707f
1699+#define MATCH_FMAX_H 0xcc000053
1700+#define MASK_FMAX_H 0xfe00707f
1701+#define MATCH_FMAX_S 0x28001053
1702+#define MASK_FMAX_S 0xfe00707f
1703+#define MATCH_FMIN_D 0x2a000053
1704+#define MASK_FMIN_D 0xfe00707f
1705+#define MATCH_FMIN_H 0xc4000053
1706+#define MASK_FMIN_H 0xfe00707f
1707+#define MATCH_FMIN_S 0x28000053
1708+#define MASK_FMIN_S 0xfe00707f
1709+#define MATCH_FMOVN 0x6007077
1710+#define MASK_FMOVN 0xfe00707f
1711+#define MATCH_FMOVZ 0x4007077
1712+#define MASK_FMOVZ 0xfe00707f
1713+#define MATCH_FMSUB_D 0x2000047
1714+#define MASK_FMSUB_D 0x600007f
1715+#define MATCH_FMSUB_H 0x4000047
1716+#define MASK_FMSUB_H 0x600007f
1717+#define MATCH_FMSUB_S 0x47
1718+#define MASK_FMSUB_S 0x600007f
1719+#define MATCH_FMUL_D 0x12000053
1720+#define MASK_FMUL_D 0xfe00007f
1721+#define MATCH_FMUL_H 0x14000053
1722+#define MASK_FMUL_H 0xfe00007f
1723+#define MATCH_FMUL_S 0x10000053
1724+#define MASK_FMUL_S 0xfe00007f
1725+#define MATCH_FMV_D_X 0xf2000053
1726+#define MASK_FMV_D_X 0xfff0707f
1727+#define MATCH_FMV_H_X 0xf4000053
1728+#define MASK_FMV_H_X 0xfff0707f
1729+#define MATCH_FMV_S_X 0xf0000053
1730+#define MASK_FMV_S_X 0xfff0707f
1731+#define MATCH_FMV_X_D 0xe2000053
1732+#define MASK_FMV_X_D 0xfff0707f
1733+#define MATCH_FMV_X_H 0xe4000053
1734+#define MASK_FMV_X_H 0xfff0707f
1735+#define MATCH_FMV_X_S 0xe0000053
1736+#define MASK_FMV_X_S 0xfff0707f
1737+#define MATCH_FNMADD_D 0x200004f
1738+#define MASK_FNMADD_D 0x600007f
1739+#define MATCH_FNMADD_H 0x400004f
1740+#define MASK_FNMADD_H 0x600007f
1741+#define MATCH_FNMADD_S 0x4f
1742+#define MASK_FNMADD_S 0x600007f
1743+#define MATCH_FNMSUB_D 0x200004b
1744+#define MASK_FNMSUB_D 0x600007f
1745+#define MATCH_FNMSUB_H 0x400004b
1746+#define MASK_FNMSUB_H 0x600007f
1747+#define MATCH_FNMSUB_S 0x4b
1748+#define MASK_FNMSUB_S 0x600007f
1749+#define MATCH_FRCSR 0x302073
1750+#define MASK_FRCSR 0xfffff07f
1751+#define MATCH_FRFLAGS 0x102073
1752+#define MASK_FRFLAGS 0xfffff07f
1753+#define MATCH_FRRM 0x202073
1754+#define MASK_FRRM 0xfffff07f
1755+#define MATCH_FSCSR 0x301073
1756+#define MASK_FSCSR 0xfff0707f
1757+#define MATCH_FSD 0x3027
1758+#define MASK_FSD 0x707f
1759+#define MATCH_FSFLAGS 0x101073
1760+#define MASK_FSFLAGS 0xfff0707f
1761+#define MATCH_FSFLAGSI 0x105073
1762+#define MASK_FSFLAGSI 0xfff0707f
1763+#define MATCH_FSGNJ_D 0x22000053
1764+#define MASK_FSGNJ_D 0xfe00707f
1765+#define MATCH_FSGNJ_H 0x2c000053
1766+#define MASK_FSGNJ_H 0xfe00707f
1767+#define MATCH_FSGNJ_S 0x20000053
1768+#define MASK_FSGNJ_S 0xfe00707f
1769+#define MATCH_FSGNJN_D 0x22001053
1770+#define MASK_FSGNJN_D 0xfe00707f
1771+#define MATCH_FSGNJN_H 0x34000053
1772+#define MASK_FSGNJN_H 0xfe00707f
1773+#define MATCH_FSGNJN_S 0x20001053
1774+#define MASK_FSGNJN_S 0xfe00707f
1775+#define MATCH_FSGNJX_D 0x22002053
1776+#define MASK_FSGNJX_D 0xfe00707f
1777+#define MATCH_FSGNJX_H 0x3c000053
1778+#define MASK_FSGNJX_H 0xfe00707f
1779+#define MATCH_FSGNJX_S 0x20002053
1780+#define MASK_FSGNJX_S 0xfe00707f
1781+#define MATCH_FSH 0x1027
1782+#define MASK_FSH 0x707f
1783+#define MATCH_FSQRT_D 0x5a000053
1784+#define MASK_FSQRT_D 0xfff0007f
1785+#define MATCH_FSQRT_H 0x24000053
1786+#define MASK_FSQRT_H 0xfff0007f
1787+#define MATCH_FSQRT_S 0x58000053
1788+#define MASK_FSQRT_S 0xfff0007f
1789+#define MATCH_FSRM 0x201073
1790+#define MASK_FSRM 0xfff0707f
1791+#define MATCH_FSRMI 0x205073
1792+#define MASK_FSRMI 0xfff0707f
1793+#define MATCH_FSUB_D 0xa000053
1794+#define MASK_FSUB_D 0xfe00007f
1795+#define MATCH_FSUB_H 0xc000053
1796+#define MASK_FSUB_H 0xfe00007f
1797+#define MATCH_FSUB_S 0x8000053
1798+#define MASK_FSUB_S 0xfe00007f
1799+#define MATCH_FSW 0x2027
1800+#define MASK_FSW 0x707f
1801+#define MATCH_HRTS 0x20500073
1802+#define MASK_HRTS 0xffffffff
1803+#define MATCH_JAL 0x6f
1804+#define MASK_JAL 0x7f
1805+#define MATCH_JALR 0x67
1806+#define MASK_JALR 0x707f
1807+#define MATCH_LB 0x3
1808+#define MASK_LB 0x707f
1809+#define MATCH_LBU 0x4003
1810+#define MASK_LBU 0x707f
1811+#define MATCH_LD 0x3003
1812+#define MASK_LD 0x707f
1813+#define MATCH_LH 0x1003
1814+#define MASK_LH 0x707f
1815+#define MATCH_LHU 0x5003
1816+#define MASK_LHU 0x707f
1817+#define MATCH_LR_D 0x1000302f
1818+#define MASK_LR_D 0xf9f0707f
1819+#define MATCH_LR_W 0x1000202f
1820+#define MASK_LR_W 0xf9f0707f
1821+#define MATCH_LUI 0x37
1822+#define MASK_LUI 0x7f
1823+#define MATCH_LW 0x2003
1824+#define MASK_LW 0x707f
1825+#define MATCH_LWU 0x6003
1826+#define MASK_LWU 0x707f
1827+#define MATCH_MOVN 0x2007077
1828+#define MASK_MOVN 0xfe00707f
1829+#define MATCH_MOVZ 0x7077
1830+#define MASK_MOVZ 0xfe00707f
1831+#define MATCH_MRTH 0x30600073
1832+#define MASK_MRTH 0xffffffff
1833+#define MATCH_MRTS 0x30500073
1834+#define MASK_MRTS 0xffffffff
1835+#define MATCH_MUL 0x2000033
1836+#define MASK_MUL 0xfe00707f
1837+#define MATCH_MULH 0x2001033
1838+#define MASK_MULH 0xfe00707f
1839+#define MATCH_MULHSU 0x2002033
1840+#define MASK_MULHSU 0xfe00707f
1841+#define MATCH_MULHU 0x2003033
1842+#define MASK_MULHU 0xfe00707f
1843+#define MATCH_MULW 0x200003b
1844+#define MASK_MULW 0xfe00707f
1845+#define MATCH_OR 0x6033
1846+#define MASK_OR 0xfe00707f
1847+#define MATCH_ORI 0x6013
1848+#define MASK_ORI 0x707f
1849+#define MATCH_RDCYCLE 0xc0002073
1850+#define MASK_RDCYCLE 0xfffff07f
1851+#define MATCH_RDCYCLEH 0xc8002073
1852+#define MASK_RDCYCLEH 0xfffff07f
1853+#define MATCH_RDINSTRET 0xc0202073
1854+#define MASK_RDINSTRET 0xfffff07f
1855+#define MATCH_RDINSTRETH 0xc8202073
1856+#define MASK_RDINSTRETH 0xfffff07f
1857+#define MATCH_RDTIME 0xc0102073
1858+#define MASK_RDTIME 0xfffff07f
1859+#define MATCH_RDTIMEH 0xc8102073
1860+#define MASK_RDTIMEH 0xfffff07f
1861+#define MATCH_REM 0x2006033
1862+#define MASK_REM 0xfe00707f
1863+#define MATCH_REMU 0x2007033
1864+#define MASK_REMU 0xfe00707f
1865+#define MATCH_REMUW 0x200703b
1866+#define MASK_REMUW 0xfe00707f
1867+#define MATCH_REMW 0x200603b
1868+#define MASK_REMW 0xfe00707f
1869+#define MATCH_SB 0x23
1870+#define MASK_SB 0x707f
1871+#define MATCH_SBREAK 0x100073
1872+#define MASK_SBREAK 0xffffffff
1873+#define MATCH_SC_D 0x1800302f
1874+#define MASK_SC_D 0xf800707f
1875+#define MATCH_SC_W 0x1800202f
1876+#define MASK_SC_W 0xf800707f
1877+#define MATCH_SCALL 0x73
1878+#define MASK_SCALL 0xffffffff
1879+#define MATCH_SD 0x3023
1880+#define MASK_SD 0x707f
1881+#define MATCH_SFENCE_VM 0x10100073
1882+#define MASK_SFENCE_VM 0xfff07fff
1883+#define MATCH_SH 0x1023
1884+#define MASK_SH 0x707f
1885+#define MATCH_SLL 0x1033
1886+#define MASK_SLL 0xfe00707f
1887+#define MATCH_SLLI 0x1013
1888+#define MASK_SLLI 0xfc00707f
1889+#define MATCH_SLLI_RV32 0x1013
1890+#define MASK_SLLI_RV32 0xfe00707f
1891+#define MATCH_SLLIW 0x101b
1892+#define MASK_SLLIW 0xfe00707f
1893+#define MATCH_SLLW 0x103b
1894+#define MASK_SLLW 0xfe00707f
1895+#define MATCH_SLT 0x2033
1896+#define MASK_SLT 0xfe00707f
1897+#define MATCH_SLTI 0x2013
1898+#define MASK_SLTI 0x707f
1899+#define MATCH_SLTIU 0x3013
1900+#define MASK_SLTIU 0x707f
1901+#define MATCH_SLTU 0x3033
1902+#define MASK_SLTU 0xfe00707f
1903+#define MATCH_SRA 0x40005033
1904+#define MASK_SRA 0xfe00707f
1905+#define MATCH_SRAI 0x40005013
1906+#define MASK_SRAI 0xfc00707f
1907+#define MATCH_SRAI_RV32 0x40005013
1908+#define MASK_SRAI_RV32 0xfe00707f
1909+#define MATCH_SRAIW 0x4000501b
1910+#define MASK_SRAIW 0xfe00707f
1911+#define MATCH_SRAW 0x4000503b
1912+#define MASK_SRAW 0xfe00707f
1913+#define MATCH_SRET 0x10000073
1914+#define MASK_SRET 0xffffffff
1915+#define MATCH_SRL 0x5033
1916+#define MASK_SRL 0xfe00707f
1917+#define MATCH_SRLI 0x5013
1918+#define MASK_SRLI 0xfc00707f
1919+#define MATCH_SRLI_RV32 0x5013
1920+#define MASK_SRLI_RV32 0xfe00707f
1921+#define MATCH_SRLIW 0x501b
1922+#define MASK_SRLIW 0xfe00707f
1923+#define MATCH_SRLW 0x503b
1924+#define MASK_SRLW 0xfe00707f
1925+#define MATCH_STOP 0x5077
1926+#define MASK_STOP 0xffffffff
1927+#define MATCH_SUB 0x40000033
1928+#define MASK_SUB 0xfe00707f
1929+#define MATCH_SUBW 0x4000003b
1930+#define MASK_SUBW 0xfe00707f
1931+#define MATCH_SW 0x2023
1932+#define MASK_SW 0x707f
1933+#define MATCH_UTIDX 0x6077
1934+#define MASK_UTIDX 0xfffff07f
1935+#define MATCH_VENQCMD 0xa00302b
1936+#define MASK_VENQCMD 0xfe007fff
1937+#define MATCH_VENQCNT 0x1000302b
1938+#define MASK_VENQCNT 0xfe007fff
1939+#define MATCH_VENQIMM1 0xc00302b
1940+#define MASK_VENQIMM1 0xfe007fff
1941+#define MATCH_VENQIMM2 0xe00302b
1942+#define MASK_VENQIMM2 0xfe007fff
1943+#define MATCH_VF 0x10202b
1944+#define MASK_VF 0x1f0707f
1945+#define MATCH_VFLD 0x1600205b
1946+#define MASK_VFLD 0xfff0707f
1947+#define MATCH_VFLSEGD 0x1600205b
1948+#define MASK_VFLSEGD 0x1ff0707f
1949+#define MATCH_VFLSEGSTD 0x1600305b
1950+#define MASK_VFLSEGSTD 0x1e00707f
1951+#define MATCH_VFLSEGSTW 0x1400305b
1952+#define MASK_VFLSEGSTW 0x1e00707f
1953+#define MATCH_VFLSEGW 0x1400205b
1954+#define MASK_VFLSEGW 0x1ff0707f
1955+#define MATCH_VFLSTD 0x1600305b
1956+#define MASK_VFLSTD 0xfe00707f
1957+#define MATCH_VFLSTW 0x1400305b
1958+#define MASK_VFLSTW 0xfe00707f
1959+#define MATCH_VFLW 0x1400205b
1960+#define MASK_VFLW 0xfff0707f
1961+#define MATCH_VFMSV_D 0x1200202b
1962+#define MASK_VFMSV_D 0xfff0707f
1963+#define MATCH_VFMSV_S 0x1000202b
1964+#define MASK_VFMSV_S 0xfff0707f
1965+#define MATCH_VFMVV 0x1000002b
1966+#define MASK_VFMVV 0xfff0707f
1967+#define MATCH_VFSD 0x1600207b
1968+#define MASK_VFSD 0xfff0707f
1969+#define MATCH_VFSSEGD 0x1600207b
1970+#define MASK_VFSSEGD 0x1ff0707f
1971+#define MATCH_VFSSEGSTD 0x1600307b
1972+#define MASK_VFSSEGSTD 0x1e00707f
1973+#define MATCH_VFSSEGSTW 0x1400307b
1974+#define MASK_VFSSEGSTW 0x1e00707f
1975+#define MATCH_VFSSEGW 0x1400207b
1976+#define MASK_VFSSEGW 0x1ff0707f
1977+#define MATCH_VFSSTD 0x1600307b
1978+#define MASK_VFSSTD 0xfe00707f
1979+#define MATCH_VFSSTW 0x1400307b
1980+#define MASK_VFSSTW 0xfe00707f
1981+#define MATCH_VFSW 0x1400207b
1982+#define MASK_VFSW 0xfff0707f
1983+#define MATCH_VGETCFG 0x400b
1984+#define MASK_VGETCFG 0xfffff07f
1985+#define MATCH_VGETVL 0x200400b
1986+#define MASK_VGETVL 0xfffff07f
1987+#define MATCH_VLB 0x205b
1988+#define MASK_VLB 0xfff0707f
1989+#define MATCH_VLBU 0x800205b
1990+#define MASK_VLBU 0xfff0707f
1991+#define MATCH_VLD 0x600205b
1992+#define MASK_VLD 0xfff0707f
1993+#define MATCH_VLH 0x200205b
1994+#define MASK_VLH 0xfff0707f
1995+#define MATCH_VLHU 0xa00205b
1996+#define MASK_VLHU 0xfff0707f
1997+#define MATCH_VLSEGB 0x205b
1998+#define MASK_VLSEGB 0x1ff0707f
1999+#define MATCH_VLSEGBU 0x800205b
2000+#define MASK_VLSEGBU 0x1ff0707f
2001+#define MATCH_VLSEGD 0x600205b
2002+#define MASK_VLSEGD 0x1ff0707f
2003+#define MATCH_VLSEGH 0x200205b
2004+#define MASK_VLSEGH 0x1ff0707f
2005+#define MATCH_VLSEGHU 0xa00205b
2006+#define MASK_VLSEGHU 0x1ff0707f
2007+#define MATCH_VLSEGSTB 0x305b
2008+#define MASK_VLSEGSTB 0x1e00707f
2009+#define MATCH_VLSEGSTBU 0x800305b
2010+#define MASK_VLSEGSTBU 0x1e00707f
2011+#define MATCH_VLSEGSTD 0x600305b
2012+#define MASK_VLSEGSTD 0x1e00707f
2013+#define MATCH_VLSEGSTH 0x200305b
2014+#define MASK_VLSEGSTH 0x1e00707f
2015+#define MATCH_VLSEGSTHU 0xa00305b
2016+#define MASK_VLSEGSTHU 0x1e00707f
2017+#define MATCH_VLSEGSTW 0x400305b
2018+#define MASK_VLSEGSTW 0x1e00707f
2019+#define MATCH_VLSEGSTWU 0xc00305b
2020+#define MASK_VLSEGSTWU 0x1e00707f
2021+#define MATCH_VLSEGW 0x400205b
2022+#define MASK_VLSEGW 0x1ff0707f
2023+#define MATCH_VLSEGWU 0xc00205b
2024+#define MASK_VLSEGWU 0x1ff0707f
2025+#define MATCH_VLSTB 0x305b
2026+#define MASK_VLSTB 0xfe00707f
2027+#define MATCH_VLSTBU 0x800305b
2028+#define MASK_VLSTBU 0xfe00707f
2029+#define MATCH_VLSTD 0x600305b
2030+#define MASK_VLSTD 0xfe00707f
2031+#define MATCH_VLSTH 0x200305b
2032+#define MASK_VLSTH 0xfe00707f
2033+#define MATCH_VLSTHU 0xa00305b
2034+#define MASK_VLSTHU 0xfe00707f
2035+#define MATCH_VLSTW 0x400305b
2036+#define MASK_VLSTW 0xfe00707f
2037+#define MATCH_VLSTWU 0xc00305b
2038+#define MASK_VLSTWU 0xfe00707f
2039+#define MATCH_VLW 0x400205b
2040+#define MASK_VLW 0xfff0707f
2041+#define MATCH_VLWU 0xc00205b
2042+#define MASK_VLWU 0xfff0707f
2043+#define MATCH_VMSV 0x200202b
2044+#define MASK_VMSV 0xfff0707f
2045+#define MATCH_VMVV 0x200002b
2046+#define MASK_VMVV 0xfff0707f
2047+#define MATCH_VSB 0x207b
2048+#define MASK_VSB 0xfff0707f
2049+#define MATCH_VSD 0x600207b
2050+#define MASK_VSD 0xfff0707f
2051+#define MATCH_VSETCFG 0x200b
2052+#define MASK_VSETCFG 0x7fff
2053+#define MATCH_VSETVL 0x600b
2054+#define MASK_VSETVL 0xfff0707f
2055+#define MATCH_VSH 0x200207b
2056+#define MASK_VSH 0xfff0707f
2057+#define MATCH_VSSEGB 0x207b
2058+#define MASK_VSSEGB 0x1ff0707f
2059+#define MATCH_VSSEGD 0x600207b
2060+#define MASK_VSSEGD 0x1ff0707f
2061+#define MATCH_VSSEGH 0x200207b
2062+#define MASK_VSSEGH 0x1ff0707f
2063+#define MATCH_VSSEGSTB 0x307b
2064+#define MASK_VSSEGSTB 0x1e00707f
2065+#define MATCH_VSSEGSTD 0x600307b
2066+#define MASK_VSSEGSTD 0x1e00707f
2067+#define MATCH_VSSEGSTH 0x200307b
2068+#define MASK_VSSEGSTH 0x1e00707f
2069+#define MATCH_VSSEGSTW 0x400307b
2070+#define MASK_VSSEGSTW 0x1e00707f
2071+#define MATCH_VSSEGW 0x400207b
2072+#define MASK_VSSEGW 0x1ff0707f
2073+#define MATCH_VSSTB 0x307b
2074+#define MASK_VSSTB 0xfe00707f
2075+#define MATCH_VSSTD 0x600307b
2076+#define MASK_VSSTD 0xfe00707f
2077+#define MATCH_VSSTH 0x200307b
2078+#define MASK_VSSTH 0xfe00707f
2079+#define MATCH_VSSTW 0x400307b
2080+#define MASK_VSSTW 0xfe00707f
2081+#define MATCH_VSW 0x400207b
2082+#define MASK_VSW 0xfff0707f
2083+#define MATCH_VXCPTAUX 0x200402b
2084+#define MASK_VXCPTAUX 0xfffff07f
2085+#define MATCH_VXCPTCAUSE 0x402b
2086+#define MASK_VXCPTCAUSE 0xfffff07f
2087+#define MATCH_VXCPTEVAC 0x600302b
2088+#define MASK_VXCPTEVAC 0xfff07fff
2089+#define MATCH_VXCPTHOLD 0x800302b
2090+#define MASK_VXCPTHOLD 0xfff07fff
2091+#define MATCH_VXCPTKILL 0x400302b
2092+#define MASK_VXCPTKILL 0xffffffff
2093+#define MATCH_VXCPTRESTORE 0x200302b
2094+#define MASK_VXCPTRESTORE 0xfff07fff
2095+#define MATCH_VXCPTSAVE 0x302b
2096+#define MASK_VXCPTSAVE 0xfff07fff
2097+#define MATCH_WFI 0x10200073
2098+#define MASK_WFI 0xffffffff
2099+#define MATCH_XOR 0x4033
2100+#define MASK_XOR 0xfe00707f
2101+#define MATCH_XORI 0x4013
2102+#define MASK_XORI 0x707f
2103+#define CSR_FFLAGS 0x1
2104+#define CSR_FRM 0x2
2105+#define CSR_FCSR 0x3
2106+#define CSR_CYCLE 0xc00
2107+#define CSR_TIME 0xc01
2108+#define CSR_INSTRET 0xc02
2109+#define CSR_STATS 0xc0
2110+#define CSR_UARCH0 0xcc0
2111+#define CSR_UARCH1 0xcc1
2112+#define CSR_UARCH2 0xcc2
2113+#define CSR_UARCH3 0xcc3
2114+#define CSR_UARCH4 0xcc4
2115+#define CSR_UARCH5 0xcc5
2116+#define CSR_UARCH6 0xcc6
2117+#define CSR_UARCH7 0xcc7
2118+#define CSR_UARCH8 0xcc8
2119+#define CSR_UARCH9 0xcc9
2120+#define CSR_UARCH10 0xcca
2121+#define CSR_UARCH11 0xccb
2122+#define CSR_UARCH12 0xccc
2123+#define CSR_UARCH13 0xccd
2124+#define CSR_UARCH14 0xcce
2125+#define CSR_UARCH15 0xccf
2126+#define CSR_SSTATUS 0x100
2127+#define CSR_STVEC 0x101
2128+#define CSR_SIE 0x104
2129+#define CSR_SSCRATCH 0x140
2130+#define CSR_SEPC 0x141
2131+#define CSR_SIP 0x144
2132+#define CSR_SPTBR 0x180
2133+#define CSR_SASID 0x181
2134+#define CSR_CYCLEW 0x900
2135+#define CSR_TIMEW 0x901
2136+#define CSR_INSTRETW 0x902
2137+#define CSR_STIME 0xd01
2138+#define CSR_SCAUSE 0xd42
2139+#define CSR_SBADADDR 0xd43
2140+#define CSR_STIMEW 0xa01
2141+#define CSR_MSTATUS 0x300
2142+#define CSR_MTVEC 0x301
2143+#define CSR_MTDELEG 0x302
2144+#define CSR_MIE 0x304
2145+#define CSR_MTIMECMP 0x321
2146+#define CSR_MSCRATCH 0x340
2147+#define CSR_MEPC 0x341
2148+#define CSR_MCAUSE 0x342
2149+#define CSR_MBADADDR 0x343
2150+#define CSR_MIP 0x344
2151+#define CSR_MTIME 0x701
2152+#define CSR_MCPUID 0xf00
2153+#define CSR_MIMPID 0xf01
2154+#define CSR_MHARTID 0xf10
2155+#define CSR_MTOHOST 0x780
2156+#define CSR_MFROMHOST 0x781
2157+#define CSR_MRESET 0x782
2158+#define CSR_SEND_IPI 0x783
2159+#define CSR_CYCLEH 0xc80
2160+#define CSR_TIMEH 0xc81
2161+#define CSR_INSTRETH 0xc82
2162+#define CSR_CYCLEHW 0x980
2163+#define CSR_TIMEHW 0x981
2164+#define CSR_INSTRETHW 0x982
2165+#define CSR_STIMEH 0xd81
2166+#define CSR_STIMEHW 0xa81
2167+#define CSR_MTIMECMPH 0x361
2168+#define CSR_MTIMEH 0x741
2169+#define CAUSE_MISALIGNED_FETCH 0x0
2170+#define CAUSE_FAULT_FETCH 0x1
2171+#define CAUSE_ILLEGAL_INSTRUCTION 0x2
2172+#define CAUSE_BREAKPOINT 0x3
2173+#define CAUSE_MISALIGNED_LOAD 0x4
2174+#define CAUSE_FAULT_LOAD 0x5
2175+#define CAUSE_MISALIGNED_STORE 0x6
2176+#define CAUSE_FAULT_STORE 0x7
2177+#define CAUSE_USER_ECALL 0x8
2178+#define CAUSE_SUPERVISOR_ECALL 0x9
2179+#define CAUSE_HYPERVISOR_ECALL 0xa
2180+#define CAUSE_MACHINE_ECALL 0xb
2181+#endif
2182+#ifdef DECLARE_INSN
2183+DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
2184+DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
2185+DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
2186+DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
2187+DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
2188+DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
2189+DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
2190+DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
2191+DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
2192+DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
2193+DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
2194+DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
2195+DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
2196+DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
2197+DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
2198+DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
2199+DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
2200+DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
2201+DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
2202+DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
2203+DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
2204+DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
2205+DECLARE_INSN(and, MATCH_AND, MASK_AND)
2206+DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
2207+DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
2208+DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
2209+DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
2210+DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
2211+DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
2212+DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
2213+DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
2214+DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
2215+DECLARE_INSN(c_add3, MATCH_C_ADD3, MASK_C_ADD3)
2216+DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
2217+DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
2218+DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
2219+DECLARE_INSN(c_addin, MATCH_C_ADDIN, MASK_C_ADDIN)
2220+DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
2221+DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
2222+DECLARE_INSN(c_and3, MATCH_C_AND3, MASK_C_AND3)
2223+DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
2224+DECLARE_INSN(c_andin, MATCH_C_ANDIN, MASK_C_ANDIN)
2225+DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
2226+DECLARE_INSN(c_bgez, MATCH_C_BGEZ, MASK_C_BGEZ)
2227+DECLARE_INSN(c_bltz, MATCH_C_BLTZ, MASK_C_BLTZ)
2228+DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
2229+DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
2230+DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
2231+DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
2232+DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
2233+DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
2234+DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
2235+DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
2236+DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
2237+DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
2238+DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
2239+DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
2240+DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
2241+DECLARE_INSN(c_or3, MATCH_C_OR3, MASK_C_OR3)
2242+DECLARE_INSN(c_orin, MATCH_C_ORIN, MASK_C_ORIN)
2243+DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
2244+DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
2245+DECLARE_INSN(c_sll, MATCH_C_SLL, MASK_C_SLL)
2246+DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
2247+DECLARE_INSN(c_slliw, MATCH_C_SLLIW, MASK_C_SLLIW)
2248+DECLARE_INSN(c_sllr, MATCH_C_SLLR, MASK_C_SLLR)
2249+DECLARE_INSN(c_slt, MATCH_C_SLT, MASK_C_SLT)
2250+DECLARE_INSN(c_sltr, MATCH_C_SLTR, MASK_C_SLTR)
2251+DECLARE_INSN(c_sltu, MATCH_C_SLTU, MASK_C_SLTU)
2252+DECLARE_INSN(c_sltur, MATCH_C_SLTUR, MASK_C_SLTUR)
2253+DECLARE_INSN(c_sra, MATCH_C_SRA, MASK_C_SRA)
2254+DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
2255+DECLARE_INSN(c_srl, MATCH_C_SRL, MASK_C_SRL)
2256+DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
2257+DECLARE_INSN(c_srlr, MATCH_C_SRLR, MASK_C_SRLR)
2258+DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
2259+DECLARE_INSN(c_sub3, MATCH_C_SUB3, MASK_C_SUB3)
2260+DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
2261+DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
2262+DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
2263+DECLARE_INSN(c_xorin, MATCH_C_XORIN, MASK_C_XORIN)
2264+DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
2265+DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
2266+DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
2267+DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
2268+DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
2269+DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
2270+DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
2271+DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
2272+DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
2273+DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
2274+DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
2275+DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
2276+DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
2277+DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
2278+DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
2279+DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
2280+DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
2281+DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
2282+DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
2283+DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
2284+DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
2285+DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
2286+DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
2287+DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
2288+DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
2289+DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
2290+DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
2291+DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
2292+DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
2293+DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
2294+DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
2295+DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
2296+DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
2297+DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
2298+DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
2299+DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
2300+DECLARE_INSN(eret, MATCH_ERET, MASK_ERET)
2301+DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
2302+DECLARE_INSN(fadd_h, MATCH_FADD_H, MASK_FADD_H)
2303+DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
2304+DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
2305+DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
2306+DECLARE_INSN(fcvt_d_h, MATCH_FCVT_D_H, MASK_FCVT_D_H)
2307+DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
2308+DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
2309+DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
2310+DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
2311+DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
2312+DECLARE_INSN(fcvt_h_d, MATCH_FCVT_H_D, MASK_FCVT_H_D)
2313+DECLARE_INSN(fcvt_h_l, MATCH_FCVT_H_L, MASK_FCVT_H_L)
2314+DECLARE_INSN(fcvt_h_lu, MATCH_FCVT_H_LU, MASK_FCVT_H_LU)
2315+DECLARE_INSN(fcvt_h_s, MATCH_FCVT_H_S, MASK_FCVT_H_S)
2316+DECLARE_INSN(fcvt_h_w, MATCH_FCVT_H_W, MASK_FCVT_H_W)
2317+DECLARE_INSN(fcvt_h_wu, MATCH_FCVT_H_WU, MASK_FCVT_H_WU)
2318+DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
2319+DECLARE_INSN(fcvt_l_h, MATCH_FCVT_L_H, MASK_FCVT_L_H)
2320+DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
2321+DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
2322+DECLARE_INSN(fcvt_lu_h, MATCH_FCVT_LU_H, MASK_FCVT_LU_H)
2323+DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
2324+DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
2325+DECLARE_INSN(fcvt_s_h, MATCH_FCVT_S_H, MASK_FCVT_S_H)
2326+DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
2327+DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
2328+DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
2329+DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
2330+DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
2331+DECLARE_INSN(fcvt_w_h, MATCH_FCVT_W_H, MASK_FCVT_W_H)
2332+DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
2333+DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
2334+DECLARE_INSN(fcvt_wu_h, MATCH_FCVT_WU_H, MASK_FCVT_WU_H)
2335+DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
2336+DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
2337+DECLARE_INSN(fdiv_h, MATCH_FDIV_H, MASK_FDIV_H)
2338+DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
2339+DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
2340+DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
2341+DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
2342+DECLARE_INSN(feq_h, MATCH_FEQ_H, MASK_FEQ_H)
2343+DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
2344+DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
2345+DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
2346+DECLARE_INSN(fle_h, MATCH_FLE_H, MASK_FLE_H)
2347+DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
2348+DECLARE_INSN(flh, MATCH_FLH, MASK_FLH)
2349+DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
2350+DECLARE_INSN(flt_h, MATCH_FLT_H, MASK_FLT_H)
2351+DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
2352+DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
2353+DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
2354+DECLARE_INSN(fmadd_h, MATCH_FMADD_H, MASK_FMADD_H)
2355+DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
2356+DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
2357+DECLARE_INSN(fmax_h, MATCH_FMAX_H, MASK_FMAX_H)
2358+DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
2359+DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
2360+DECLARE_INSN(fmin_h, MATCH_FMIN_H, MASK_FMIN_H)
2361+DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
2362+DECLARE_INSN(fmovn, MATCH_FMOVN, MASK_FMOVN)
2363+DECLARE_INSN(fmovz, MATCH_FMOVZ, MASK_FMOVZ)
2364+DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
2365+DECLARE_INSN(fmsub_h, MATCH_FMSUB_H, MASK_FMSUB_H)
2366+DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
2367+DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
2368+DECLARE_INSN(fmul_h, MATCH_FMUL_H, MASK_FMUL_H)
2369+DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
2370+DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
2371+DECLARE_INSN(fmv_h_x, MATCH_FMV_H_X, MASK_FMV_H_X)
2372+DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
2373+DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
2374+DECLARE_INSN(fmv_x_h, MATCH_FMV_X_H, MASK_FMV_X_H)
2375+DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
2376+DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
2377+DECLARE_INSN(fnmadd_h, MATCH_FNMADD_H, MASK_FNMADD_H)
2378+DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
2379+DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
2380+DECLARE_INSN(fnmsub_h, MATCH_FNMSUB_H, MASK_FNMSUB_H)
2381+DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
2382+DECLARE_INSN(frcsr, MATCH_FRCSR, MASK_FRCSR)
2383+DECLARE_INSN(frflags, MATCH_FRFLAGS, MASK_FRFLAGS)
2384+DECLARE_INSN(frrm, MATCH_FRRM, MASK_FRRM)
2385+DECLARE_INSN(fscsr, MATCH_FSCSR, MASK_FSCSR)
2386+DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
2387+DECLARE_INSN(fsflags, MATCH_FSFLAGS, MASK_FSFLAGS)
2388+DECLARE_INSN(fsflagsi, MATCH_FSFLAGSI, MASK_FSFLAGSI)
2389+DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
2390+DECLARE_INSN(fsgnj_h, MATCH_FSGNJ_H, MASK_FSGNJ_H)
2391+DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
2392+DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
2393+DECLARE_INSN(fsgnjn_h, MATCH_FSGNJN_H, MASK_FSGNJN_H)
2394+DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
2395+DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
2396+DECLARE_INSN(fsgnjx_h, MATCH_FSGNJX_H, MASK_FSGNJX_H)
2397+DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
2398+DECLARE_INSN(fsh, MATCH_FSH, MASK_FSH)
2399+DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
2400+DECLARE_INSN(fsqrt_h, MATCH_FSQRT_H, MASK_FSQRT_H)
2401+DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
2402+DECLARE_INSN(fsrm, MATCH_FSRM, MASK_FSRM)
2403+DECLARE_INSN(fsrmi, MATCH_FSRMI, MASK_FSRMI)
2404+DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
2405+DECLARE_INSN(fsub_h, MATCH_FSUB_H, MASK_FSUB_H)
2406+DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
2407+DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
2408+DECLARE_INSN(hrts, MATCH_HRTS, MASK_HRTS)
2409+DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
2410+DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
2411+DECLARE_INSN(lb, MATCH_LB, MASK_LB)
2412+DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
2413+DECLARE_INSN(ld, MATCH_LD, MASK_LD)
2414+DECLARE_INSN(lh, MATCH_LH, MASK_LH)
2415+DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
2416+DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
2417+DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
2418+DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
2419+DECLARE_INSN(lw, MATCH_LW, MASK_LW)
2420+DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
2421+DECLARE_INSN(movn, MATCH_MOVN, MASK_MOVN)
2422+DECLARE_INSN(movz, MATCH_MOVZ, MASK_MOVZ)
2423+DECLARE_INSN(mrth, MATCH_MRTH, MASK_MRTH)
2424+DECLARE_INSN(mrts, MATCH_MRTS, MASK_MRTS)
2425+DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
2426+DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
2427+DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
2428+DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
2429+DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
2430+DECLARE_INSN(or, MATCH_OR, MASK_OR)
2431+DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
2432+DECLARE_INSN(rdcycle, MATCH_RDCYCLE, MASK_RDCYCLE)
2433+DECLARE_INSN(rdcycleh, MATCH_RDCYCLEH, MASK_RDCYCLEH)
2434+DECLARE_INSN(rdinstret, MATCH_RDINSTRET, MASK_RDINSTRET)
2435+DECLARE_INSN(rdinstreth, MATCH_RDINSTRETH, MASK_RDINSTRETH)
2436+DECLARE_INSN(rdtime, MATCH_RDTIME, MASK_RDTIME)
2437+DECLARE_INSN(rdtimeh, MATCH_RDTIMEH, MASK_RDTIMEH)
2438+DECLARE_INSN(rem, MATCH_REM, MASK_REM)
2439+DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
2440+DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
2441+DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
2442+DECLARE_INSN(sb, MATCH_SB, MASK_SB)
2443+DECLARE_INSN(sbreak, MATCH_SBREAK, MASK_SBREAK)
2444+DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
2445+DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
2446+DECLARE_INSN(scall, MATCH_SCALL, MASK_SCALL)
2447+DECLARE_INSN(sd, MATCH_SD, MASK_SD)
2448+DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
2449+DECLARE_INSN(sh, MATCH_SH, MASK_SH)
2450+DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
2451+DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
2452+DECLARE_INSN(slli_rv32, MATCH_SLLI_RV32, MASK_SLLI_RV32)
2453+DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
2454+DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
2455+DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
2456+DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
2457+DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
2458+DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
2459+DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
2460+DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
2461+DECLARE_INSN(srai_rv32, MATCH_SRAI_RV32, MASK_SRAI_RV32)
2462+DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
2463+DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
2464+DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
2465+DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
2466+DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
2467+DECLARE_INSN(srli_rv32, MATCH_SRLI_RV32, MASK_SRLI_RV32)
2468+DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
2469+DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
2470+DECLARE_INSN(stop, MATCH_STOP, MASK_STOP)
2471+DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
2472+DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
2473+DECLARE_INSN(sw, MATCH_SW, MASK_SW)
2474+DECLARE_INSN(utidx, MATCH_UTIDX, MASK_UTIDX)
2475+DECLARE_INSN(venqcmd, MATCH_VENQCMD, MASK_VENQCMD)
2476+DECLARE_INSN(venqcnt, MATCH_VENQCNT, MASK_VENQCNT)
2477+DECLARE_INSN(venqimm1, MATCH_VENQIMM1, MASK_VENQIMM1)
2478+DECLARE_INSN(venqimm2, MATCH_VENQIMM2, MASK_VENQIMM2)
2479+DECLARE_INSN(vf, MATCH_VF, MASK_VF)
2480+DECLARE_INSN(vfld, MATCH_VFLD, MASK_VFLD)
2481+DECLARE_INSN(vflsegd, MATCH_VFLSEGD, MASK_VFLSEGD)
2482+DECLARE_INSN(vflsegstd, MATCH_VFLSEGSTD, MASK_VFLSEGSTD)
2483+DECLARE_INSN(vflsegstw, MATCH_VFLSEGSTW, MASK_VFLSEGSTW)
2484+DECLARE_INSN(vflsegw, MATCH_VFLSEGW, MASK_VFLSEGW)
2485+DECLARE_INSN(vflstd, MATCH_VFLSTD, MASK_VFLSTD)
2486+DECLARE_INSN(vflstw, MATCH_VFLSTW, MASK_VFLSTW)
2487+DECLARE_INSN(vflw, MATCH_VFLW, MASK_VFLW)
2488+DECLARE_INSN(vfmsv_d, MATCH_VFMSV_D, MASK_VFMSV_D)
2489+DECLARE_INSN(vfmsv_s, MATCH_VFMSV_S, MASK_VFMSV_S)
2490+DECLARE_INSN(vfmvv, MATCH_VFMVV, MASK_VFMVV)
2491+DECLARE_INSN(vfsd, MATCH_VFSD, MASK_VFSD)
2492+DECLARE_INSN(vfssegd, MATCH_VFSSEGD, MASK_VFSSEGD)
2493+DECLARE_INSN(vfssegstd, MATCH_VFSSEGSTD, MASK_VFSSEGSTD)
2494+DECLARE_INSN(vfssegstw, MATCH_VFSSEGSTW, MASK_VFSSEGSTW)
2495+DECLARE_INSN(vfssegw, MATCH_VFSSEGW, MASK_VFSSEGW)
2496+DECLARE_INSN(vfsstd, MATCH_VFSSTD, MASK_VFSSTD)
2497+DECLARE_INSN(vfsstw, MATCH_VFSSTW, MASK_VFSSTW)
2498+DECLARE_INSN(vfsw, MATCH_VFSW, MASK_VFSW)
2499+DECLARE_INSN(vgetcfg, MATCH_VGETCFG, MASK_VGETCFG)
2500+DECLARE_INSN(vgetvl, MATCH_VGETVL, MASK_VGETVL)
2501+DECLARE_INSN(vlb, MATCH_VLB, MASK_VLB)
2502+DECLARE_INSN(vlbu, MATCH_VLBU, MASK_VLBU)
2503+DECLARE_INSN(vld, MATCH_VLD, MASK_VLD)
2504+DECLARE_INSN(vlh, MATCH_VLH, MASK_VLH)
2505+DECLARE_INSN(vlhu, MATCH_VLHU, MASK_VLHU)
2506+DECLARE_INSN(vlsegb, MATCH_VLSEGB, MASK_VLSEGB)
2507+DECLARE_INSN(vlsegbu, MATCH_VLSEGBU, MASK_VLSEGBU)
2508+DECLARE_INSN(vlsegd, MATCH_VLSEGD, MASK_VLSEGD)
2509+DECLARE_INSN(vlsegh, MATCH_VLSEGH, MASK_VLSEGH)
2510+DECLARE_INSN(vlseghu, MATCH_VLSEGHU, MASK_VLSEGHU)
2511+DECLARE_INSN(vlsegstb, MATCH_VLSEGSTB, MASK_VLSEGSTB)
2512+DECLARE_INSN(vlsegstbu, MATCH_VLSEGSTBU, MASK_VLSEGSTBU)
2513+DECLARE_INSN(vlsegstd, MATCH_VLSEGSTD, MASK_VLSEGSTD)
2514+DECLARE_INSN(vlsegsth, MATCH_VLSEGSTH, MASK_VLSEGSTH)
2515+DECLARE_INSN(vlsegsthu, MATCH_VLSEGSTHU, MASK_VLSEGSTHU)
2516+DECLARE_INSN(vlsegstw, MATCH_VLSEGSTW, MASK_VLSEGSTW)
2517+DECLARE_INSN(vlsegstwu, MATCH_VLSEGSTWU, MASK_VLSEGSTWU)
2518+DECLARE_INSN(vlsegw, MATCH_VLSEGW, MASK_VLSEGW)
2519+DECLARE_INSN(vlsegwu, MATCH_VLSEGWU, MASK_VLSEGWU)
2520+DECLARE_INSN(vlstb, MATCH_VLSTB, MASK_VLSTB)
2521+DECLARE_INSN(vlstbu, MATCH_VLSTBU, MASK_VLSTBU)
2522+DECLARE_INSN(vlstd, MATCH_VLSTD, MASK_VLSTD)
2523+DECLARE_INSN(vlsth, MATCH_VLSTH, MASK_VLSTH)
2524+DECLARE_INSN(vlsthu, MATCH_VLSTHU, MASK_VLSTHU)
2525+DECLARE_INSN(vlstw, MATCH_VLSTW, MASK_VLSTW)
2526+DECLARE_INSN(vlstwu, MATCH_VLSTWU, MASK_VLSTWU)
2527+DECLARE_INSN(vlw, MATCH_VLW, MASK_VLW)
2528+DECLARE_INSN(vlwu, MATCH_VLWU, MASK_VLWU)
2529+DECLARE_INSN(vmsv, MATCH_VMSV, MASK_VMSV)
2530+DECLARE_INSN(vmvv, MATCH_VMVV, MASK_VMVV)
2531+DECLARE_INSN(vsb, MATCH_VSB, MASK_VSB)
2532+DECLARE_INSN(vsd, MATCH_VSD, MASK_VSD)
2533+DECLARE_INSN(vsetcfg, MATCH_VSETCFG, MASK_VSETCFG)
2534+DECLARE_INSN(vsetvl, MATCH_VSETVL, MASK_VSETVL)
2535+DECLARE_INSN(vsh, MATCH_VSH, MASK_VSH)
2536+DECLARE_INSN(vssegb, MATCH_VSSEGB, MASK_VSSEGB)
2537+DECLARE_INSN(vssegd, MATCH_VSSEGD, MASK_VSSEGD)
2538+DECLARE_INSN(vssegh, MATCH_VSSEGH, MASK_VSSEGH)
2539+DECLARE_INSN(vssegstb, MATCH_VSSEGSTB, MASK_VSSEGSTB)
2540+DECLARE_INSN(vssegstd, MATCH_VSSEGSTD, MASK_VSSEGSTD)
2541+DECLARE_INSN(vssegsth, MATCH_VSSEGSTH, MASK_VSSEGSTH)
2542+DECLARE_INSN(vssegstw, MATCH_VSSEGSTW, MASK_VSSEGSTW)
2543+DECLARE_INSN(vssegw, MATCH_VSSEGW, MASK_VSSEGW)
2544+DECLARE_INSN(vsstb, MATCH_VSSTB, MASK_VSSTB)
2545+DECLARE_INSN(vsstd, MATCH_VSSTD, MASK_VSSTD)
2546+DECLARE_INSN(vssth, MATCH_VSSTH, MASK_VSSTH)
2547+DECLARE_INSN(vsstw, MATCH_VSSTW, MASK_VSSTW)
2548+DECLARE_INSN(vsw, MATCH_VSW, MASK_VSW)
2549+DECLARE_INSN(vxcptaux, MATCH_VXCPTAUX, MASK_VXCPTAUX)
2550+DECLARE_INSN(vxcptcause, MATCH_VXCPTCAUSE, MASK_VXCPTCAUSE)
2551+DECLARE_INSN(vxcptevac, MATCH_VXCPTEVAC, MASK_VXCPTEVAC)
2552+DECLARE_INSN(vxcpthold, MATCH_VXCPTHOLD, MASK_VXCPTHOLD)
2553+DECLARE_INSN(vxcptkill, MATCH_VXCPTKILL, MASK_VXCPTKILL)
2554+DECLARE_INSN(vxcptrestore, MATCH_VXCPTRESTORE, MASK_VXCPTRESTORE)
2555+DECLARE_INSN(vxcptsave, MATCH_VXCPTSAVE, MASK_VXCPTSAVE)
2556+DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
2557+DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
2558+DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
2559+#endif
2560+#ifdef DECLARE_CSR
2561+DECLARE_CSR(fflags, CSR_FFLAGS)
2562+DECLARE_CSR(frm, CSR_FRM)
2563+DECLARE_CSR(fcsr, CSR_FCSR)
2564+DECLARE_CSR(cycle, CSR_CYCLE)
2565+DECLARE_CSR(time, CSR_TIME)
2566+DECLARE_CSR(instret, CSR_INSTRET)
2567+DECLARE_CSR(stats, CSR_STATS)
2568+DECLARE_CSR(uarch0, CSR_UARCH0)
2569+DECLARE_CSR(uarch1, CSR_UARCH1)
2570+DECLARE_CSR(uarch2, CSR_UARCH2)
2571+DECLARE_CSR(uarch3, CSR_UARCH3)
2572+DECLARE_CSR(uarch4, CSR_UARCH4)
2573+DECLARE_CSR(uarch5, CSR_UARCH5)
2574+DECLARE_CSR(uarch6, CSR_UARCH6)
2575+DECLARE_CSR(uarch7, CSR_UARCH7)
2576+DECLARE_CSR(uarch8, CSR_UARCH8)
2577+DECLARE_CSR(uarch9, CSR_UARCH9)
2578+DECLARE_CSR(uarch10, CSR_UARCH10)
2579+DECLARE_CSR(uarch11, CSR_UARCH11)
2580+DECLARE_CSR(uarch12, CSR_UARCH12)
2581+DECLARE_CSR(uarch13, CSR_UARCH13)
2582+DECLARE_CSR(uarch14, CSR_UARCH14)
2583+DECLARE_CSR(uarch15, CSR_UARCH15)
2584+DECLARE_CSR(sstatus, CSR_SSTATUS)
2585+DECLARE_CSR(stvec, CSR_STVEC)
2586+DECLARE_CSR(sie, CSR_SIE)
2587+DECLARE_CSR(sscratch, CSR_SSCRATCH)
2588+DECLARE_CSR(sepc, CSR_SEPC)
2589+DECLARE_CSR(sip, CSR_SIP)
2590+DECLARE_CSR(sptbr, CSR_SPTBR)
2591+DECLARE_CSR(sasid, CSR_SASID)
2592+DECLARE_CSR(cyclew, CSR_CYCLEW)
2593+DECLARE_CSR(timew, CSR_TIMEW)
2594+DECLARE_CSR(instretw, CSR_INSTRETW)
2595+DECLARE_CSR(stime, CSR_STIME)
2596+DECLARE_CSR(scause, CSR_SCAUSE)
2597+DECLARE_CSR(sbadaddr, CSR_SBADADDR)
2598+DECLARE_CSR(stimew, CSR_STIMEW)
2599+DECLARE_CSR(mstatus, CSR_MSTATUS)
2600+DECLARE_CSR(mtvec, CSR_MTVEC)
2601+DECLARE_CSR(mtdeleg, CSR_MTDELEG)
2602+DECLARE_CSR(mie, CSR_MIE)
2603+DECLARE_CSR(mtimecmp, CSR_MTIMECMP)
2604+DECLARE_CSR(mscratch, CSR_MSCRATCH)
2605+DECLARE_CSR(mepc, CSR_MEPC)
2606+DECLARE_CSR(mcause, CSR_MCAUSE)
2607+DECLARE_CSR(mbadaddr, CSR_MBADADDR)
2608+DECLARE_CSR(mip, CSR_MIP)
2609+DECLARE_CSR(mtime, CSR_MTIME)
2610+DECLARE_CSR(mcpuid, CSR_MCPUID)
2611+DECLARE_CSR(mimpid, CSR_MIMPID)
2612+DECLARE_CSR(mhartid, CSR_MHARTID)
2613+DECLARE_CSR(mtohost, CSR_MTOHOST)
2614+DECLARE_CSR(mfromhost, CSR_MFROMHOST)
2615+DECLARE_CSR(mreset, CSR_MRESET)
2616+DECLARE_CSR(send_ipi, CSR_SEND_IPI)
2617+DECLARE_CSR(cycleh, CSR_CYCLEH)
2618+DECLARE_CSR(timeh, CSR_TIMEH)
2619+DECLARE_CSR(instreth, CSR_INSTRETH)
2620+DECLARE_CSR(cyclehw, CSR_CYCLEHW)
2621+DECLARE_CSR(timehw, CSR_TIMEHW)
2622+DECLARE_CSR(instrethw, CSR_INSTRETHW)
2623+DECLARE_CSR(stimeh, CSR_STIMEH)
2624+DECLARE_CSR(stimehw, CSR_STIMEHW)
2625+DECLARE_CSR(mtimecmph, CSR_MTIMECMPH)
2626+DECLARE_CSR(mtimeh, CSR_MTIMEH)
2627+#endif
2628+#ifdef DECLARE_CAUSE
2629+DECLARE_CAUSE("fflags", CAUSE_FFLAGS)
2630+DECLARE_CAUSE("frm", CAUSE_FRM)
2631+DECLARE_CAUSE("fcsr", CAUSE_FCSR)
2632+DECLARE_CAUSE("cycle", CAUSE_CYCLE)
2633+DECLARE_CAUSE("time", CAUSE_TIME)
2634+DECLARE_CAUSE("instret", CAUSE_INSTRET)
2635+DECLARE_CAUSE("stats", CAUSE_STATS)
2636+DECLARE_CAUSE("uarch0", CAUSE_UARCH0)
2637+DECLARE_CAUSE("uarch1", CAUSE_UARCH1)
2638+DECLARE_CAUSE("uarch2", CAUSE_UARCH2)
2639+DECLARE_CAUSE("uarch3", CAUSE_UARCH3)
2640+DECLARE_CAUSE("uarch4", CAUSE_UARCH4)
2641+DECLARE_CAUSE("uarch5", CAUSE_UARCH5)
2642+DECLARE_CAUSE("uarch6", CAUSE_UARCH6)
2643+DECLARE_CAUSE("uarch7", CAUSE_UARCH7)
2644+DECLARE_CAUSE("uarch8", CAUSE_UARCH8)
2645+DECLARE_CAUSE("uarch9", CAUSE_UARCH9)
2646+DECLARE_CAUSE("uarch10", CAUSE_UARCH10)
2647+DECLARE_CAUSE("uarch11", CAUSE_UARCH11)
2648+DECLARE_CAUSE("uarch12", CAUSE_UARCH12)
2649+DECLARE_CAUSE("uarch13", CAUSE_UARCH13)
2650+DECLARE_CAUSE("uarch14", CAUSE_UARCH14)
2651+DECLARE_CAUSE("uarch15", CAUSE_UARCH15)
2652+DECLARE_CAUSE("sstatus", CAUSE_SSTATUS)
2653+DECLARE_CAUSE("stvec", CAUSE_STVEC)
2654+DECLARE_CAUSE("sie", CAUSE_SIE)
2655+DECLARE_CAUSE("sscratch", CAUSE_SSCRATCH)
2656+DECLARE_CAUSE("sepc", CAUSE_SEPC)
2657+DECLARE_CAUSE("sip", CAUSE_SIP)
2658+DECLARE_CAUSE("sptbr", CAUSE_SPTBR)
2659+DECLARE_CAUSE("sasid", CAUSE_SASID)
2660+DECLARE_CAUSE("cyclew", CAUSE_CYCLEW)
2661+DECLARE_CAUSE("timew", CAUSE_TIMEW)
2662+DECLARE_CAUSE("instretw", CAUSE_INSTRETW)
2663+DECLARE_CAUSE("stime", CAUSE_STIME)
2664+DECLARE_CAUSE("scause", CAUSE_SCAUSE)
2665+DECLARE_CAUSE("sbadaddr", CAUSE_SBADADDR)
2666+DECLARE_CAUSE("stimew", CAUSE_STIMEW)
2667+DECLARE_CAUSE("mstatus", CAUSE_MSTATUS)
2668+DECLARE_CAUSE("mtvec", CAUSE_MTVEC)
2669+DECLARE_CAUSE("mtdeleg", CAUSE_MTDELEG)
2670+DECLARE_CAUSE("mie", CAUSE_MIE)
2671+DECLARE_CAUSE("mtimecmp", CAUSE_MTIMECMP)
2672+DECLARE_CAUSE("mscratch", CAUSE_MSCRATCH)
2673+DECLARE_CAUSE("mepc", CAUSE_MEPC)
2674+DECLARE_CAUSE("mcause", CAUSE_MCAUSE)
2675+DECLARE_CAUSE("mbadaddr", CAUSE_MBADADDR)
2676+DECLARE_CAUSE("mip", CAUSE_MIP)
2677+DECLARE_CAUSE("mtime", CAUSE_MTIME)
2678+DECLARE_CAUSE("mcpuid", CAUSE_MCPUID)
2679+DECLARE_CAUSE("mimpid", CAUSE_MIMPID)
2680+DECLARE_CAUSE("mhartid", CAUSE_MHARTID)
2681+DECLARE_CAUSE("mtohost", CAUSE_MTOHOST)
2682+DECLARE_CAUSE("mfromhost", CAUSE_MFROMHOST)
2683+DECLARE_CAUSE("mreset", CAUSE_MRESET)
2684+DECLARE_CAUSE("send_ipi", CAUSE_SEND_IPI)
2685+DECLARE_CAUSE("cycleh", CAUSE_CYCLEH)
2686+DECLARE_CAUSE("timeh", CAUSE_TIMEH)
2687+DECLARE_CAUSE("instreth", CAUSE_INSTRETH)
2688+DECLARE_CAUSE("cyclehw", CAUSE_CYCLEHW)
2689+DECLARE_CAUSE("timehw", CAUSE_TIMEHW)
2690+DECLARE_CAUSE("instrethw", CAUSE_INSTRETHW)
2691+DECLARE_CAUSE("stimeh", CAUSE_STIMEH)
2692+DECLARE_CAUSE("stimehw", CAUSE_STIMEHW)
2693+DECLARE_CAUSE("mtimecmph", CAUSE_MTIMECMPH)
2694+DECLARE_CAUSE("mtimeh", CAUSE_MTIMEH)
2695+#endif
2696diff -urN empty/gcc/config/riscv/riscv-protos.h gcc-5.2.0/gcc/config/riscv/riscv-protos.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +02002697--- gcc-5.2.0/gcc/config/riscv/riscv-protos.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002698+++ gcc-5.2.0/gcc/config/riscv/riscv-protos.h 2015-07-17 22:36:52.319705931 +0200
2699@@ -0,0 +1,96 @@
2700+/* Definition of RISC-V target for GNU compiler.
2701+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
2702+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
2703+ Based on MIPS target for GNU compiler.
2704+
2705+This file is part of GCC.
2706+
2707+GCC is free software; you can redistribute it and/or modify
2708+it under the terms of the GNU General Public License as published by
2709+the Free Software Foundation; either version 3, or (at your option)
2710+any later version.
2711+
2712+GCC is distributed in the hope that it will be useful,
2713+but WITHOUT ANY WARRANTY; without even the implied warranty of
2714+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2715+GNU General Public License for more details.
2716+
2717+You should have received a copy of the GNU General Public License
2718+along with GCC; see the file COPYING3. If not see
2719+<http://www.gnu.org/licenses/>. */
2720+
2721+#ifndef GCC_RISCV_PROTOS_H
2722+#define GCC_RISCV_PROTOS_H
2723+
2724+enum riscv_symbol_type {
2725+ SYMBOL_ABSOLUTE,
2726+ SYMBOL_GOT_DISP,
2727+ SYMBOL_TLS,
2728+ SYMBOL_TLS_LE,
2729+ SYMBOL_TLS_IE,
2730+ SYMBOL_TLS_GD
2731+};
2732+#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
2733+
2734+enum riscv_code_model {
2735+ CM_MEDLOW,
2736+ CM_MEDANY,
2737+ CM_PIC
2738+};
2739+extern enum riscv_code_model riscv_cmodel;
2740+
2741+extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
2742+extern int riscv_regno_mode_ok_for_base_p (int, enum machine_mode, bool);
2743+extern int riscv_address_insns (rtx, enum machine_mode, bool);
2744+extern int riscv_const_insns (rtx);
2745+extern int riscv_split_const_insns (rtx);
2746+extern int riscv_load_store_insns (rtx, rtx_insn *);
2747+extern rtx riscv_emit_move (rtx, rtx);
2748+extern bool riscv_split_symbol (rtx, rtx, enum machine_mode, rtx *);
2749+extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
2750+extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT);
2751+extern bool riscv_legitimize_move (enum machine_mode, rtx, rtx);
2752+extern bool riscv_legitimize_vector_move (enum machine_mode, rtx, rtx);
2753+
2754+extern rtx riscv_subword (rtx, bool);
2755+extern bool riscv_split_64bit_move_p (rtx, rtx);
2756+extern void riscv_split_doubleword_move (rtx, rtx);
2757+extern const char *riscv_output_move (rtx, rtx);
2758+extern const char *riscv_output_gpr_save (unsigned);
2759+#ifdef RTX_CODE
2760+extern void riscv_expand_scc (rtx *);
2761+extern void riscv_expand_conditional_branch (rtx *);
2762+#endif
2763+extern rtx riscv_expand_call (bool, rtx, rtx, rtx);
2764+extern void riscv_expand_fcc_reload (rtx, rtx, rtx);
2765+extern void riscv_set_return_address (rtx, rtx);
2766+extern bool riscv_expand_block_move (rtx, rtx, rtx);
2767+extern void riscv_expand_synci_loop (rtx, rtx);
2768+
2769+extern bool riscv_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
2770+ HOST_WIDE_INT);
2771+extern bool riscv_expand_ins_as_unaligned_store (rtx, rtx, HOST_WIDE_INT,
2772+ HOST_WIDE_INT);
2773+extern void riscv_order_regs_for_local_alloc (void);
2774+
2775+extern rtx riscv_return_addr (int, rtx);
2776+extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
2777+extern void riscv_expand_prologue (void);
2778+extern void riscv_expand_epilogue (bool);
2779+extern bool riscv_can_use_return_insn (void);
2780+extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
2781+
2782+extern enum reg_class riscv_secondary_reload_class (enum reg_class,
2783+ enum machine_mode,
2784+ rtx, bool);
2785+extern int riscv_class_max_nregs (enum reg_class, enum machine_mode);
2786+
2787+extern unsigned int riscv_hard_regno_nregs (int, enum machine_mode);
2788+
2789+extern void irix_asm_output_align (FILE *, unsigned);
2790+extern const char *current_section_name (void);
2791+extern unsigned int current_section_flags (void);
2792+
2793+extern void riscv_expand_vector_init (rtx, rtx);
2794+
2795+#endif /* ! GCC_RISCV_PROTOS_H */
2796diff -urN empty/gcc/config/riscv/riscv.c gcc-5.2.0/gcc/config/riscv/riscv.c
Patrick Georgi410f9ad2015-08-23 21:07:46 +02002797--- gcc-5.2.0/gcc/config/riscv/riscv.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002798+++ gcc-5.2.0/gcc/config/riscv/riscv.c 2015-07-17 22:36:52.319705931 +0200
2799@@ -0,0 +1,4439 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01002800+/* Subroutines used for code generation for RISC-V.
2801+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
2802+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
2803+ Based on MIPS target for GNU compiler.
2804+
2805+This file is part of GCC.
2806+
2807+GCC is free software; you can redistribute it and/or modify
2808+it under the terms of the GNU General Public License as published by
2809+the Free Software Foundation; either version 3, or (at your option)
2810+any later version.
2811+
2812+GCC is distributed in the hope that it will be useful,
2813+but WITHOUT ANY WARRANTY; without even the implied warranty of
2814+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2815+GNU General Public License for more details.
2816+
2817+You should have received a copy of the GNU General Public License
2818+along with GCC; see the file COPYING3. If not see
2819+<http://www.gnu.org/licenses/>. */
2820+
2821+#include "config.h"
2822+#include "system.h"
2823+#include "coretypes.h"
2824+#include "tm.h"
2825+#include "rtl.h"
2826+#include "regs.h"
2827+#include "hard-reg-set.h"
2828+#include "insn-config.h"
2829+#include "conditions.h"
2830+#include "insn-attr.h"
2831+#include "recog.h"
2832+#include "output.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002833+#include "hash-set.h"
2834+#include "machmode.h"
2835+#include "vec.h"
2836+#include "double-int.h"
2837+#include "input.h"
2838+#include "alias.h"
2839+#include "symtab.h"
2840+#include "wide-int.h"
2841+#include "inchash.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002842+#include "tree.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002843+#include "fold-const.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002844+#include "varasm.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002845+#include "stringpool.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002846+#include "stor-layout.h"
2847+#include "calls.h"
2848+#include "function.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002849+#include "hashtab.h"
2850+#include "flags.h"
2851+#include "statistics.h"
2852+#include "real.h"
2853+#include "fixed-value.h"
2854+#include "expmed.h"
2855+#include "dojump.h"
2856+#include "explow.h"
2857+#include "emit-rtl.h"
2858+#include "stmt.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002859+#include "expr.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002860+#include "insn-codes.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002861+#include "optabs.h"
2862+#include "libfuncs.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002863+#include "reload.h"
2864+#include "tm_p.h"
2865+#include "ggc.h"
2866+#include "gstab.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002867+#include "hash-table.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002868+#include "debug.h"
2869+#include "target.h"
2870+#include "target-def.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002871+#include "common/common-target.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002872+#include "langhooks.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002873+#include "dominance.h"
2874+#include "cfg.h"
2875+#include "cfgrtl.h"
2876+#include "cfganal.h"
2877+#include "lcm.h"
2878+#include "cfgbuild.h"
2879+#include "cfgcleanup.h"
2880+#include "predict.h"
2881+#include "basic-block.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002882+#include "sched-int.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002883+#include "tree-ssa-alias.h"
2884+#include "internal-fn.h"
2885+#include "gimple-fold.h"
2886+#include "tree-eh.h"
2887+#include "gimple-expr.h"
2888+#include "is-a.h"
2889+#include "gimple.h"
2890+#include "gimplify.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002891+#include "bitmap.h"
2892+#include "diagnostic.h"
2893+#include "target-globals.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002894+#include "opts.h"
2895+#include "tree-pass.h"
2896+#include "context.h"
2897+#include "hash-map.h"
2898+#include "plugin-api.h"
2899+#include "ipa-ref.h"
2900+#include "cgraph.h"
2901+#include "builtins.h"
2902+#include "rtl-iter.h"
Patrick Georgif0bbc952015-03-07 10:57:25 +01002903+#include <stdint.h>
2904+
2905+/* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */
2906+#define UNSPEC_ADDRESS_P(X) \
2907+ (GET_CODE (X) == UNSPEC \
2908+ && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \
2909+ && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
2910+
2911+/* Extract the symbol or label from UNSPEC wrapper X. */
2912+#define UNSPEC_ADDRESS(X) \
2913+ XVECEXP (X, 0, 0)
2914+
2915+/* Extract the symbol type from UNSPEC wrapper X. */
2916+#define UNSPEC_ADDRESS_TYPE(X) \
2917+ ((enum riscv_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
2918+
2919+/* The maximum distance between the top of the stack frame and the
2920+ value sp has when we save and restore registers. This is set by the
2921+ range of load/store offsets and must also preserve stack alignment. */
2922+#define RISCV_MAX_FIRST_STACK_STEP (RISCV_IMM_REACH/2 - 16)
2923+
2924+/* True if INSN is a riscv.md pattern or asm statement. */
2925+#define USEFUL_INSN_P(INSN) \
2926+ (NONDEBUG_INSN_P (INSN) \
2927+ && GET_CODE (PATTERN (INSN)) != USE \
2928+ && GET_CODE (PATTERN (INSN)) != CLOBBER \
2929+ && GET_CODE (PATTERN (INSN)) != ADDR_VEC \
2930+ && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC)
2931+
2932+/* True if bit BIT is set in VALUE. */
2933+#define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0)
2934+
2935+/* Classifies an address.
2936+
2937+ ADDRESS_REG
2938+ A natural register + offset address. The register satisfies
2939+ riscv_valid_base_register_p and the offset is a const_arith_operand.
2940+
2941+ ADDRESS_LO_SUM
2942+ A LO_SUM rtx. The first operand is a valid base register and
2943+ the second operand is a symbolic address.
2944+
2945+ ADDRESS_CONST_INT
2946+ A signed 16-bit constant address.
2947+
2948+ ADDRESS_SYMBOLIC:
2949+ A constant symbolic address. */
2950+enum riscv_address_type {
2951+ ADDRESS_REG,
2952+ ADDRESS_LO_SUM,
2953+ ADDRESS_CONST_INT,
2954+ ADDRESS_SYMBOLIC
2955+};
2956+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002957+enum riscv_code_model riscv_cmodel = TARGET_DEFAULT_CMODEL;
2958+
Patrick Georgif0bbc952015-03-07 10:57:25 +01002959+/* Macros to create an enumeration identifier for a function prototype. */
2960+#define RISCV_FTYPE_NAME1(A, B) RISCV_##A##_FTYPE_##B
2961+#define RISCV_FTYPE_NAME2(A, B, C) RISCV_##A##_FTYPE_##B##_##C
2962+#define RISCV_FTYPE_NAME3(A, B, C, D) RISCV_##A##_FTYPE_##B##_##C##_##D
2963+#define RISCV_FTYPE_NAME4(A, B, C, D, E) RISCV_##A##_FTYPE_##B##_##C##_##D##_##E
2964+
2965+/* Classifies the prototype of a built-in function. */
2966+enum riscv_function_type {
2967+#define DEF_RISCV_FTYPE(NARGS, LIST) RISCV_FTYPE_NAME##NARGS LIST,
2968+#include "config/riscv/riscv-ftypes.def"
2969+#undef DEF_RISCV_FTYPE
2970+ RISCV_MAX_FTYPE_MAX
2971+};
2972+
2973+/* Specifies how a built-in function should be converted into rtl. */
2974+enum riscv_builtin_type {
2975+ /* The function corresponds directly to an .md pattern. The return
2976+ value is mapped to operand 0 and the arguments are mapped to
2977+ operands 1 and above. */
2978+ RISCV_BUILTIN_DIRECT,
2979+
2980+ /* The function corresponds directly to an .md pattern. There is no return
2981+ value and the arguments are mapped to operands 0 and above. */
2982+ RISCV_BUILTIN_DIRECT_NO_TARGET
2983+};
2984+
2985+/* Information about a function's frame layout. */
2986+struct GTY(()) riscv_frame_info {
2987+ /* The size of the frame in bytes. */
2988+ HOST_WIDE_INT total_size;
2989+
2990+ /* Bit X is set if the function saves or restores GPR X. */
2991+ unsigned int mask;
2992+
2993+ /* Likewise FPR X. */
2994+ unsigned int fmask;
2995+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02002996+ /* How much the GPR save/restore routines adjust sp (or 0 if unused). */
2997+ unsigned save_libcall_adjustment;
2998+
Patrick Georgif0bbc952015-03-07 10:57:25 +01002999+ /* Offsets of fixed-point and floating-point save areas from frame bottom */
3000+ HOST_WIDE_INT gp_sp_offset;
3001+ HOST_WIDE_INT fp_sp_offset;
3002+
3003+ /* Offset of virtual frame pointer from stack pointer/frame bottom */
3004+ HOST_WIDE_INT frame_pointer_offset;
3005+
3006+ /* Offset of hard frame pointer from stack pointer/frame bottom */
3007+ HOST_WIDE_INT hard_frame_pointer_offset;
3008+
3009+ /* The offset of arg_pointer_rtx from the bottom of the frame. */
3010+ HOST_WIDE_INT arg_pointer_offset;
3011+};
3012+
3013+struct GTY(()) machine_function {
3014+ /* The number of extra stack bytes taken up by register varargs.
3015+ This area is allocated by the callee at the very top of the frame. */
3016+ int varargs_size;
3017+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003018+ /* Cached return value of leaf_function_p. <0 if false, >0 if true. */
3019+ int is_leaf;
3020+
Patrick Georgif0bbc952015-03-07 10:57:25 +01003021+ /* The current frame information, calculated by riscv_compute_frame_info. */
3022+ struct riscv_frame_info frame;
3023+};
3024+
3025+/* Information about a single argument. */
3026+struct riscv_arg_info {
3027+ /* True if the argument is passed in a floating-point register, or
3028+ would have been if we hadn't run out of registers. */
3029+ bool fpr_p;
3030+
3031+ /* The number of words passed in registers, rounded up. */
3032+ unsigned int reg_words;
3033+
3034+ /* For EABI, the offset of the first register from GP_ARG_FIRST or
3035+ FP_ARG_FIRST. For other ABIs, the offset of the first register from
3036+ the start of the ABI's argument structure (see the CUMULATIVE_ARGS
3037+ comment for details).
3038+
3039+ The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely
3040+ on the stack. */
3041+ unsigned int reg_offset;
3042+
3043+ /* The number of words that must be passed on the stack, rounded up. */
3044+ unsigned int stack_words;
3045+
3046+ /* The offset from the start of the stack overflow area of the argument's
3047+ first stack word. Only meaningful when STACK_WORDS is nonzero. */
3048+ unsigned int stack_offset;
3049+};
3050+
3051+/* Information about an address described by riscv_address_type.
3052+
3053+ ADDRESS_CONST_INT
3054+ No fields are used.
3055+
3056+ ADDRESS_REG
3057+ REG is the base register and OFFSET is the constant offset.
3058+
3059+ ADDRESS_LO_SUM
3060+ REG and OFFSET are the operands to the LO_SUM and SYMBOL_TYPE
3061+ is the type of symbol it references.
3062+
3063+ ADDRESS_SYMBOLIC
3064+ SYMBOL_TYPE is the type of symbol that the address references. */
3065+struct riscv_address_info {
3066+ enum riscv_address_type type;
3067+ rtx reg;
3068+ rtx offset;
3069+ enum riscv_symbol_type symbol_type;
3070+};
3071+
3072+/* One stage in a constant building sequence. These sequences have
3073+ the form:
3074+
3075+ A = VALUE[0]
3076+ A = A CODE[1] VALUE[1]
3077+ A = A CODE[2] VALUE[2]
3078+ ...
3079+
3080+ where A is an accumulator, each CODE[i] is a binary rtl operation
3081+ and each VALUE[i] is a constant integer. CODE[0] is undefined. */
3082+struct riscv_integer_op {
3083+ enum rtx_code code;
3084+ unsigned HOST_WIDE_INT value;
3085+};
3086+
3087+/* The largest number of operations needed to load an integer constant.
3088+ The worst case is LUI, ADDI, SLLI, ADDI, SLLI, ADDI, SLLI, ADDI,
3089+ but we may attempt and reject even worse sequences. */
3090+#define RISCV_MAX_INTEGER_OPS 32
3091+
3092+/* Costs of various operations on the different architectures. */
3093+
3094+struct riscv_tune_info
3095+{
3096+ unsigned short fp_add[2];
3097+ unsigned short fp_mul[2];
3098+ unsigned short fp_div[2];
3099+ unsigned short int_mul[2];
3100+ unsigned short int_div[2];
3101+ unsigned short issue_rate;
3102+ unsigned short branch_cost;
3103+ unsigned short fp_to_int_cost;
3104+ unsigned short memory_cost;
3105+};
3106+
3107+/* Information about one CPU we know about. */
3108+struct riscv_cpu_info {
3109+ /* This CPU's canonical name. */
3110+ const char *name;
3111+
3112+ /* The RISC-V ISA and extensions supported by this CPU. */
3113+ const char *isa;
3114+
3115+ /* Tuning parameters for this CPU. */
3116+ const struct riscv_tune_info *tune_info;
3117+};
3118+
3119+/* Global variables for machine-dependent things. */
3120+
3121+/* Which tuning parameters to use. */
3122+static const struct riscv_tune_info *tune_info;
3123+
3124+/* Index [M][R] is true if register R is allowed to hold a value of mode M. */
3125+bool riscv_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
3126+
3127+/* riscv_lo_relocs[X] is the relocation to use when a symbol of type X
3128+ appears in a LO_SUM. It can be null if such LO_SUMs aren't valid or
3129+ if they are matched by a special .md file pattern. */
3130+const char *riscv_lo_relocs[NUM_SYMBOL_TYPES];
3131+
3132+/* Likewise for HIGHs. */
3133+const char *riscv_hi_relocs[NUM_SYMBOL_TYPES];
3134+
3135+/* Index R is the smallest register class that contains register R. */
3136+const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
3137+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3138+ GR_REGS, T_REGS, T_REGS, T_REGS,
3139+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3140+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3141+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3142+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3143+ GR_REGS, GR_REGS, GR_REGS, GR_REGS,
3144+ T_REGS, T_REGS, T_REGS, T_REGS,
3145+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3146+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3147+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3148+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3149+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3150+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3151+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3152+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
3153+ FRAME_REGS, FRAME_REGS,
3154+};
3155+
3156+/* Costs to use when optimizing for size. */
3157+static const struct riscv_tune_info rocket_tune_info = {
3158+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */
3159+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */
3160+ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */
3161+ {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */
3162+ {COSTS_N_INSNS (6), COSTS_N_INSNS (6)}, /* int_div */
3163+ 1, /* issue_rate */
3164+ 3, /* branch_cost */
3165+ COSTS_N_INSNS (2), /* fp_to_int_cost */
3166+ 5 /* memory_cost */
3167+};
3168+
3169+/* Costs to use when optimizing for size. */
3170+static const struct riscv_tune_info optimize_size_tune_info = {
3171+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_add */
3172+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_mul */
3173+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* fp_div */
3174+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_mul */
3175+ {COSTS_N_INSNS (1), COSTS_N_INSNS (1)}, /* int_div */
3176+ 1, /* issue_rate */
3177+ 1, /* branch_cost */
3178+ COSTS_N_INSNS (1), /* fp_to_int_cost */
3179+ 1 /* memory_cost */
3180+};
3181+
3182+/* A table describing all the processors GCC knows about. */
3183+static const struct riscv_cpu_info riscv_cpu_info_table[] = {
3184+ /* Entries for generic ISAs. */
3185+ { "rocket", "IMAFD", &rocket_tune_info },
3186+};
3187+
3188+/* Return the riscv_cpu_info entry for the given name string. */
3189+
3190+static const struct riscv_cpu_info *
3191+riscv_parse_cpu (const char *cpu_string)
3192+{
3193+ unsigned int i;
3194+
3195+ for (i = 0; i < ARRAY_SIZE (riscv_cpu_info_table); i++)
3196+ if (strcmp (riscv_cpu_info_table[i].name, cpu_string) == 0)
3197+ return riscv_cpu_info_table + i;
3198+
3199+ error ("unknown cpu `%s'", cpu_string);
3200+ return riscv_cpu_info_table;
3201+}
3202+
3203+/* Fill CODES with a sequence of rtl operations to load VALUE.
3204+ Return the number of operations needed. */
3205+
3206+static int
3207+riscv_build_integer_1 (struct riscv_integer_op *codes, HOST_WIDE_INT value,
3208+ enum machine_mode mode)
3209+{
3210+ HOST_WIDE_INT low_part = RISCV_CONST_LOW_PART (value);
3211+ int cost = INT_MAX, alt_cost;
3212+ struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS];
3213+
3214+ if (SMALL_OPERAND (value) || LUI_OPERAND (value))
3215+ {
3216+ /* Simply ADDI or LUI */
3217+ codes[0].code = UNKNOWN;
3218+ codes[0].value = value;
3219+ return 1;
3220+ }
3221+
3222+ /* End with ADDI */
3223+ if (low_part != 0
3224+ && !(mode == HImode && (int16_t)(value - low_part) != (value - low_part)))
3225+ {
3226+ cost = 1 + riscv_build_integer_1 (codes, value - low_part, mode);
3227+ codes[cost-1].code = PLUS;
3228+ codes[cost-1].value = low_part;
3229+ }
3230+
3231+ /* End with XORI */
3232+ if (cost > 2 && (low_part < 0 || mode == HImode))
3233+ {
3234+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, value ^ low_part, mode);
3235+ alt_codes[alt_cost-1].code = XOR;
3236+ alt_codes[alt_cost-1].value = low_part;
3237+ if (alt_cost < cost)
3238+ cost = alt_cost, memcpy (codes, alt_codes, sizeof(alt_codes));
3239+ }
3240+
3241+ /* Eliminate trailing zeros and end with SLLI */
3242+ if (cost > 2 && (value & 1) == 0)
3243+ {
3244+ int shift = 0;
3245+ while ((value & 1) == 0)
3246+ shift++, value >>= 1;
3247+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, value, mode);
3248+ alt_codes[alt_cost-1].code = ASHIFT;
3249+ alt_codes[alt_cost-1].value = shift;
3250+ if (alt_cost < cost)
3251+ cost = alt_cost, memcpy (codes, alt_codes, sizeof(alt_codes));
3252+ }
3253+
3254+ gcc_assert (cost <= RISCV_MAX_INTEGER_OPS);
3255+ return cost;
3256+}
3257+
3258+static int
3259+riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value,
3260+ enum machine_mode mode)
3261+{
3262+ int cost = riscv_build_integer_1 (codes, value, mode);
3263+
3264+ /* Eliminate leading zeros and end with SRLI */
3265+ if (value > 0 && cost > 2)
3266+ {
3267+ struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS];
3268+ int alt_cost, shift = 0;
3269+ HOST_WIDE_INT shifted_val;
3270+
3271+ /* Try filling trailing bits with 1s */
3272+ while ((value << shift) >= 0)
3273+ shift++;
3274+ shifted_val = (value << shift) | ((((HOST_WIDE_INT) 1) << shift) - 1);
3275+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode);
3276+ alt_codes[alt_cost-1].code = LSHIFTRT;
3277+ alt_codes[alt_cost-1].value = shift;
3278+ if (alt_cost < cost)
3279+ cost = alt_cost, memcpy (codes, alt_codes, sizeof (alt_codes));
3280+
3281+ /* Try filling trailing bits with 0s */
3282+ shifted_val = value << shift;
3283+ alt_cost = 1 + riscv_build_integer_1 (alt_codes, shifted_val, mode);
3284+ alt_codes[alt_cost-1].code = LSHIFTRT;
3285+ alt_codes[alt_cost-1].value = shift;
3286+ if (alt_cost < cost)
3287+ cost = alt_cost, memcpy (codes, alt_codes, sizeof (alt_codes));
3288+ }
3289+
3290+ return cost;
3291+}
3292+
3293+static int
3294+riscv_split_integer_cost (HOST_WIDE_INT val)
3295+{
3296+ int cost;
3297+ int32_t loval = val, hival = (val - (int32_t)val) >> 32;
3298+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
3299+
3300+ cost = 2 + riscv_build_integer (codes, loval, VOIDmode);
3301+ if (loval != hival)
3302+ cost += riscv_build_integer (codes, hival, VOIDmode);
3303+
3304+ return cost;
3305+}
3306+
3307+static int
3308+riscv_integer_cost (HOST_WIDE_INT val)
3309+{
3310+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
3311+ return MIN (riscv_build_integer (codes, val, VOIDmode),
3312+ riscv_split_integer_cost (val));
3313+}
3314+
3315+/* Try to split a 64b integer into 32b parts, then reassemble. */
3316+
3317+static rtx
3318+riscv_split_integer (HOST_WIDE_INT val, enum machine_mode mode)
3319+{
3320+ int32_t loval = val, hival = (val - (int32_t)val) >> 32;
3321+ rtx hi = gen_reg_rtx (mode), lo = gen_reg_rtx (mode);
3322+
3323+ riscv_move_integer (hi, hi, hival);
3324+ riscv_move_integer (lo, lo, loval);
3325+
3326+ hi = gen_rtx_fmt_ee (ASHIFT, mode, hi, GEN_INT (32));
3327+ hi = force_reg (mode, hi);
3328+
3329+ return gen_rtx_fmt_ee (PLUS, mode, hi, lo);
3330+}
3331+
3332+/* Return true if X is a thread-local symbol. */
3333+
3334+static bool
3335+riscv_tls_symbol_p (const_rtx x)
3336+{
3337+ return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
3338+}
3339+
3340+static bool
3341+riscv_symbol_binds_local_p (const_rtx x)
3342+{
3343+ return (SYMBOL_REF_DECL (x)
3344+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
3345+ : SYMBOL_REF_LOCAL_P (x));
3346+}
3347+
3348+/* Return the method that should be used to access SYMBOL_REF or
3349+ LABEL_REF X in context CONTEXT. */
3350+
3351+static enum riscv_symbol_type
3352+riscv_classify_symbol (const_rtx x)
3353+{
3354+ if (riscv_tls_symbol_p (x))
3355+ return SYMBOL_TLS;
3356+
3357+ if (GET_CODE (x) == LABEL_REF)
3358+ {
3359+ if (LABEL_REF_NONLOCAL_P (x))
3360+ return SYMBOL_GOT_DISP;
3361+ return SYMBOL_ABSOLUTE;
3362+ }
3363+
3364+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
3365+
3366+ if (flag_pic && !riscv_symbol_binds_local_p (x))
3367+ return SYMBOL_GOT_DISP;
3368+
3369+ return SYMBOL_ABSOLUTE;
3370+}
3371+
3372+/* Classify the base of symbolic expression X, given that X appears in
3373+ context CONTEXT. */
3374+
3375+static enum riscv_symbol_type
3376+riscv_classify_symbolic_expression (rtx x)
3377+{
3378+ rtx offset;
3379+
3380+ split_const (x, &x, &offset);
3381+ if (UNSPEC_ADDRESS_P (x))
3382+ return UNSPEC_ADDRESS_TYPE (x);
3383+
3384+ return riscv_classify_symbol (x);
3385+}
3386+
3387+/* Return true if X is a symbolic constant that can be used in context
3388+ CONTEXT. If it is, store the type of the symbol in *SYMBOL_TYPE. */
3389+
3390+bool
3391+riscv_symbolic_constant_p (rtx x, enum riscv_symbol_type *symbol_type)
3392+{
3393+ rtx offset;
3394+
3395+ split_const (x, &x, &offset);
3396+ if (UNSPEC_ADDRESS_P (x))
3397+ {
3398+ *symbol_type = UNSPEC_ADDRESS_TYPE (x);
3399+ x = UNSPEC_ADDRESS (x);
3400+ }
3401+ else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
3402+ *symbol_type = riscv_classify_symbol (x);
3403+ else
3404+ return false;
3405+
3406+ if (offset == const0_rtx)
3407+ return true;
3408+
3409+ /* Check whether a nonzero offset is valid for the underlying
3410+ relocations. */
3411+ switch (*symbol_type)
3412+ {
3413+ case SYMBOL_ABSOLUTE:
3414+ case SYMBOL_TLS_LE:
3415+ return (int32_t) INTVAL (offset) == INTVAL (offset);
3416+
3417+ default:
3418+ return false;
3419+ }
3420+ gcc_unreachable ();
3421+}
3422+
3423+/* Returns the number of instructions necessary to reference a symbol. */
3424+
3425+static int riscv_symbol_insns (enum riscv_symbol_type type)
3426+{
3427+ switch (type)
3428+ {
3429+ case SYMBOL_TLS: return 0; /* Depends on the TLS model. */
3430+ case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference itself */
3431+ case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference itself */
3432+ case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference itself */
3433+ default: gcc_unreachable();
3434+ }
3435+}
3436+
Patrick Georgif0bbc952015-03-07 10:57:25 +01003437+/* Implement TARGET_LEGITIMATE_CONSTANT_P. */
3438+
3439+static bool
3440+riscv_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
3441+{
3442+ return riscv_const_insns (x) > 0;
3443+}
3444+
3445+/* Implement TARGET_CANNOT_FORCE_CONST_MEM. */
3446+
3447+static bool
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003448+riscv_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
Patrick Georgif0bbc952015-03-07 10:57:25 +01003449+{
3450+ enum riscv_symbol_type type;
3451+ rtx base, offset;
3452+
3453+ /* There is no assembler syntax for expressing an address-sized
3454+ high part. */
3455+ if (GET_CODE (x) == HIGH)
3456+ return true;
3457+
Patrick Georgif0bbc952015-03-07 10:57:25 +01003458+ split_const (x, &base, &offset);
3459+ if (riscv_symbolic_constant_p (base, &type))
3460+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003461+ /* As an optimization, don't spill symbolic constants that are as
3462+ cheap to rematerialize as to access in the constant pool. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01003463+ if (SMALL_INT (offset) && riscv_symbol_insns (type) > 0)
3464+ return true;
3465+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003466+ /* As an optimization, avoid needlessly generate dynamic relocations. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01003467+ if (flag_pic)
3468+ return true;
3469+ }
3470+
3471+ /* TLS symbols must be computed by riscv_legitimize_move. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003472+ if (tls_referenced_p (x))
Patrick Georgif0bbc952015-03-07 10:57:25 +01003473+ return true;
3474+
3475+ return false;
3476+}
3477+
3478+/* Return true if register REGNO is a valid base register for mode MODE.
3479+ STRICT_P is true if REG_OK_STRICT is in effect. */
3480+
3481+int
3482+riscv_regno_mode_ok_for_base_p (int regno, enum machine_mode mode ATTRIBUTE_UNUSED,
3483+ bool strict_p)
3484+{
3485+ if (!HARD_REGISTER_NUM_P (regno))
3486+ {
3487+ if (!strict_p)
3488+ return true;
3489+ regno = reg_renumber[regno];
3490+ }
3491+
3492+ /* These fake registers will be eliminated to either the stack or
3493+ hard frame pointer, both of which are usually valid base registers.
3494+ Reload deals with the cases where the eliminated form isn't valid. */
3495+ if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
3496+ return true;
3497+
3498+ return GP_REG_P (regno);
3499+}
3500+
3501+/* Return true if X is a valid base register for mode MODE.
3502+ STRICT_P is true if REG_OK_STRICT is in effect. */
3503+
3504+static bool
3505+riscv_valid_base_register_p (rtx x, enum machine_mode mode, bool strict_p)
3506+{
3507+ if (!strict_p && GET_CODE (x) == SUBREG)
3508+ x = SUBREG_REG (x);
3509+
3510+ return (REG_P (x)
3511+ && riscv_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p));
3512+}
3513+
3514+/* Return true if, for every base register BASE_REG, (plus BASE_REG X)
3515+ can address a value of mode MODE. */
3516+
3517+static bool
3518+riscv_valid_offset_p (rtx x, enum machine_mode mode)
3519+{
3520+ /* Check that X is a signed 12-bit number. */
3521+ if (!const_arith_operand (x, Pmode))
3522+ return false;
3523+
3524+ /* We may need to split multiword moves, so make sure that every word
3525+ is accessible. */
3526+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
3527+ && !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD))
3528+ return false;
3529+
3530+ return true;
3531+}
3532+
3533+/* Return true if a LO_SUM can address a value of mode MODE when the
3534+ LO_SUM symbol has type SYMBOL_TYPE. */
3535+
3536+static bool
3537+riscv_valid_lo_sum_p (enum riscv_symbol_type symbol_type, enum machine_mode mode)
3538+{
3539+ /* Check that symbols of type SYMBOL_TYPE can be used to access values
3540+ of mode MODE. */
3541+ if (riscv_symbol_insns (symbol_type) == 0)
3542+ return false;
3543+
3544+ /* Check that there is a known low-part relocation. */
3545+ if (riscv_lo_relocs[symbol_type] == NULL)
3546+ return false;
3547+
3548+ /* We may need to split multiword moves, so make sure that each word
3549+ can be accessed without inducing a carry. This is mainly needed
3550+ for o64, which has historically only guaranteed 64-bit alignment
3551+ for 128-bit types. */
3552+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
3553+ && GET_MODE_BITSIZE (mode) > GET_MODE_ALIGNMENT (mode))
3554+ return false;
3555+
3556+ return true;
3557+}
3558+
3559+/* Return true if X is a valid address for machine mode MODE. If it is,
3560+ fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in
3561+ effect. */
3562+
3563+static bool
3564+riscv_classify_address (struct riscv_address_info *info, rtx x,
3565+ enum machine_mode mode, bool strict_p)
3566+{
3567+ switch (GET_CODE (x))
3568+ {
3569+ case REG:
3570+ case SUBREG:
3571+ info->type = ADDRESS_REG;
3572+ info->reg = x;
3573+ info->offset = const0_rtx;
3574+ return riscv_valid_base_register_p (info->reg, mode, strict_p);
3575+
3576+ case PLUS:
3577+ info->type = ADDRESS_REG;
3578+ info->reg = XEXP (x, 0);
3579+ info->offset = XEXP (x, 1);
3580+ return (riscv_valid_base_register_p (info->reg, mode, strict_p)
3581+ && riscv_valid_offset_p (info->offset, mode));
3582+
3583+ case LO_SUM:
3584+ info->type = ADDRESS_LO_SUM;
3585+ info->reg = XEXP (x, 0);
3586+ info->offset = XEXP (x, 1);
3587+ /* We have to trust the creator of the LO_SUM to do something vaguely
3588+ sane. Target-independent code that creates a LO_SUM should also
3589+ create and verify the matching HIGH. Target-independent code that
3590+ adds an offset to a LO_SUM must prove that the offset will not
3591+ induce a carry. Failure to do either of these things would be
3592+ a bug, and we are not required to check for it here. The RISCV
3593+ backend itself should only create LO_SUMs for valid symbolic
3594+ constants, with the high part being either a HIGH or a copy
3595+ of _gp. */
3596+ info->symbol_type
3597+ = riscv_classify_symbolic_expression (info->offset);
3598+ return (riscv_valid_base_register_p (info->reg, mode, strict_p)
3599+ && riscv_valid_lo_sum_p (info->symbol_type, mode));
3600+
3601+ case CONST_INT:
3602+ /* Small-integer addresses don't occur very often, but they
3603+ are legitimate if $0 is a valid base register. */
3604+ info->type = ADDRESS_CONST_INT;
3605+ return SMALL_INT (x);
3606+
3607+ default:
3608+ return false;
3609+ }
3610+}
3611+
3612+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
3613+
3614+static bool
3615+riscv_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p)
3616+{
3617+ struct riscv_address_info addr;
3618+
3619+ return riscv_classify_address (&addr, x, mode, strict_p);
3620+}
3621+
3622+/* Return the number of instructions needed to load or store a value
3623+ of mode MODE at address X. Return 0 if X isn't valid for MODE.
3624+ Assume that multiword moves may need to be split into word moves
3625+ if MIGHT_SPLIT_P, otherwise assume that a single load or store is
3626+ enough. */
3627+
3628+int
3629+riscv_address_insns (rtx x, enum machine_mode mode, bool might_split_p)
3630+{
3631+ struct riscv_address_info addr;
3632+ int n = 1;
3633+
3634+ if (!riscv_classify_address (&addr, x, mode, false))
3635+ return 0;
3636+
3637+ /* BLKmode is used for single unaligned loads and stores and should
3638+ not count as a multiword mode. */
3639+ if (mode != BLKmode && might_split_p)
3640+ n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
3641+
3642+ if (addr.type == ADDRESS_LO_SUM)
3643+ n += riscv_symbol_insns (addr.symbol_type) - 1;
3644+
3645+ return n;
3646+}
3647+
3648+/* Return the number of instructions needed to load constant X.
3649+ Return 0 if X isn't a valid constant. */
3650+
3651+int
3652+riscv_const_insns (rtx x)
3653+{
3654+ enum riscv_symbol_type symbol_type;
3655+ rtx offset;
3656+
3657+ switch (GET_CODE (x))
3658+ {
3659+ case HIGH:
3660+ if (!riscv_symbolic_constant_p (XEXP (x, 0), &symbol_type)
3661+ || !riscv_hi_relocs[symbol_type])
3662+ return 0;
3663+
3664+ /* This is simply an LUI. */
3665+ return 1;
3666+
3667+ case CONST_INT:
3668+ {
3669+ int cost = riscv_integer_cost (INTVAL (x));
3670+ /* Force complicated constants to memory. */
3671+ return cost < 4 ? cost : 0;
3672+ }
3673+
3674+ case CONST_DOUBLE:
3675+ case CONST_VECTOR:
3676+ /* Allow zeros for normal mode, where we can use x0. */
3677+ return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0;
3678+
3679+ case CONST:
3680+ /* See if we can refer to X directly. */
3681+ if (riscv_symbolic_constant_p (x, &symbol_type))
3682+ return riscv_symbol_insns (symbol_type);
3683+
3684+ /* Otherwise try splitting the constant into a base and offset.
3685+ If the offset is a 16-bit value, we can load the base address
3686+ into a register and then use (D)ADDIU to add in the offset.
3687+ If the offset is larger, we can load the base and offset
3688+ into separate registers and add them together with (D)ADDU.
3689+ However, the latter is only possible before reload; during
3690+ and after reload, we must have the option of forcing the
3691+ constant into the pool instead. */
3692+ split_const (x, &x, &offset);
3693+ if (offset != 0)
3694+ {
3695+ int n = riscv_const_insns (x);
3696+ if (n != 0)
3697+ {
3698+ if (SMALL_INT (offset))
3699+ return n + 1;
3700+ else if (!targetm.cannot_force_const_mem (GET_MODE (x), x))
3701+ return n + 1 + riscv_integer_cost (INTVAL (offset));
3702+ }
3703+ }
3704+ return 0;
3705+
3706+ case SYMBOL_REF:
3707+ case LABEL_REF:
3708+ return riscv_symbol_insns (riscv_classify_symbol (x));
3709+
3710+ default:
3711+ return 0;
3712+ }
3713+}
3714+
3715+/* X is a doubleword constant that can be handled by splitting it into
3716+ two words and loading each word separately. Return the number of
3717+ instructions required to do this. */
3718+
3719+int
3720+riscv_split_const_insns (rtx x)
3721+{
3722+ unsigned int low, high;
3723+
3724+ low = riscv_const_insns (riscv_subword (x, false));
3725+ high = riscv_const_insns (riscv_subword (x, true));
3726+ gcc_assert (low > 0 && high > 0);
3727+ return low + high;
3728+}
3729+
3730+/* Return the number of instructions needed to implement INSN,
3731+ given that it loads from or stores to MEM. */
3732+
3733+int
Patrick Georgiaf473ed2015-07-17 23:35:54 +02003734+riscv_load_store_insns (rtx mem, rtx_insn *insn)
Patrick Georgif0bbc952015-03-07 10:57:25 +01003735+{
3736+ enum machine_mode mode;
3737+ bool might_split_p;
3738+ rtx set;
3739+
3740+ gcc_assert (MEM_P (mem));
3741+ mode = GET_MODE (mem);
3742+
3743+ /* Try to prove that INSN does not need to be split. */
3744+ might_split_p = true;
3745+ if (GET_MODE_BITSIZE (mode) == 64)
3746+ {
3747+ set = single_set (insn);
3748+ if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set)))
3749+ might_split_p = false;
3750+ }
3751+
3752+ return riscv_address_insns (XEXP (mem, 0), mode, might_split_p);
3753+}
3754+
3755+/* Emit a move from SRC to DEST. Assume that the move expanders can
3756+ handle all moves if !can_create_pseudo_p (). The distinction is
3757+ important because, unlike emit_move_insn, the move expanders know
3758+ how to force Pmode objects into the constant pool even when the
3759+ constant pool address is not itself legitimate. */
3760+
3761+rtx
3762+riscv_emit_move (rtx dest, rtx src)
3763+{
3764+ return (can_create_pseudo_p ()
3765+ ? emit_move_insn (dest, src)
3766+ : emit_move_insn_1 (dest, src));
3767+}
3768+
3769+/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
3770+
3771+static void
3772+riscv_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
3773+{
3774+ emit_insn (gen_rtx_SET (VOIDmode, target,
3775+ gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
3776+}
3777+
3778+/* Compute (CODE OP0 OP1) and store the result in a new register
3779+ of mode MODE. Return that new register. */
3780+
3781+static rtx
3782+riscv_force_binary (enum machine_mode mode, enum rtx_code code, rtx op0, rtx op1)
3783+{
3784+ rtx reg;
3785+
3786+ reg = gen_reg_rtx (mode);
3787+ riscv_emit_binary (code, reg, op0, op1);
3788+ return reg;
3789+}
3790+
3791+/* Copy VALUE to a register and return that register. If new pseudos
3792+ are allowed, copy it into a new register, otherwise use DEST. */
3793+
3794+static rtx
3795+riscv_force_temporary (rtx dest, rtx value)
3796+{
3797+ if (can_create_pseudo_p ())
3798+ return force_reg (Pmode, value);
3799+ else
3800+ {
3801+ riscv_emit_move (dest, value);
3802+ return dest;
3803+ }
3804+}
3805+
3806+/* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE,
3807+ then add CONST_INT OFFSET to the result. */
3808+
3809+static rtx
3810+riscv_unspec_address_offset (rtx base, rtx offset,
3811+ enum riscv_symbol_type symbol_type)
3812+{
3813+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
3814+ UNSPEC_ADDRESS_FIRST + symbol_type);
3815+ if (offset != const0_rtx)
3816+ base = gen_rtx_PLUS (Pmode, base, offset);
3817+ return gen_rtx_CONST (Pmode, base);
3818+}
3819+
3820+/* Return an UNSPEC address with underlying address ADDRESS and symbol
3821+ type SYMBOL_TYPE. */
3822+
3823+rtx
3824+riscv_unspec_address (rtx address, enum riscv_symbol_type symbol_type)
3825+{
3826+ rtx base, offset;
3827+
3828+ split_const (address, &base, &offset);
3829+ return riscv_unspec_address_offset (base, offset, symbol_type);
3830+}
3831+
3832+/* If OP is an UNSPEC address, return the address to which it refers,
3833+ otherwise return OP itself. */
3834+
3835+static rtx
3836+riscv_strip_unspec_address (rtx op)
3837+{
3838+ rtx base, offset;
3839+
3840+ split_const (op, &base, &offset);
3841+ if (UNSPEC_ADDRESS_P (base))
3842+ op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset));
3843+ return op;
3844+}
3845+
3846+/* If riscv_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the
3847+ high part to BASE and return the result. Just return BASE otherwise.
3848+ TEMP is as for riscv_force_temporary.
3849+
3850+ The returned expression can be used as the first operand to a LO_SUM. */
3851+
3852+static rtx
3853+riscv_unspec_offset_high (rtx temp, rtx addr, enum riscv_symbol_type symbol_type)
3854+{
3855+ addr = gen_rtx_HIGH (Pmode, riscv_unspec_address (addr, symbol_type));
3856+ return riscv_force_temporary (temp, addr);
3857+}
3858+
3859+/* Load an entry from the GOT. */
3860+static rtx riscv_got_load_tls_gd(rtx dest, rtx sym)
3861+{
3862+ return (Pmode == DImode ? gen_got_load_tls_gddi(dest, sym) : gen_got_load_tls_gdsi(dest, sym));
3863+}
3864+
3865+static rtx riscv_got_load_tls_ie(rtx dest, rtx sym)
3866+{
3867+ return (Pmode == DImode ? gen_got_load_tls_iedi(dest, sym) : gen_got_load_tls_iesi(dest, sym));
3868+}
3869+
3870+static rtx riscv_tls_add_tp_le(rtx dest, rtx base, rtx sym)
3871+{
3872+ rtx tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
3873+ return (Pmode == DImode ? gen_tls_add_tp_ledi(dest, base, tp, sym) : gen_tls_add_tp_lesi(dest, base, tp, sym));
3874+}
3875+
3876+/* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise
3877+ it appears in a MEM of that mode. Return true if ADDR is a legitimate
3878+ constant in that context and can be split into high and low parts.
3879+ If so, and if LOW_OUT is nonnull, emit the high part and store the
3880+ low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise.
3881+
3882+ TEMP is as for riscv_force_temporary and is used to load the high
3883+ part into a register.
3884+
3885+ When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be
3886+ a legitimize SET_SRC for an .md pattern, otherwise the low part
3887+ is guaranteed to be a legitimate address for mode MODE. */
3888+
3889+bool
3890+riscv_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *low_out)
3891+{
3892+ enum riscv_symbol_type symbol_type;
3893+ rtx high;
3894+
3895+ if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE)
3896+ || !riscv_symbolic_constant_p (addr, &symbol_type)
3897+ || riscv_symbol_insns (symbol_type) == 0
3898+ || !riscv_hi_relocs[symbol_type])
3899+ return false;
3900+
3901+ if (low_out)
3902+ {
3903+ switch (symbol_type)
3904+ {
3905+ case SYMBOL_ABSOLUTE:
3906+ high = gen_rtx_HIGH (Pmode, copy_rtx (addr));
3907+ high = riscv_force_temporary (temp, high);
3908+ *low_out = gen_rtx_LO_SUM (Pmode, high, addr);
3909+ break;
3910+
3911+ default:
3912+ gcc_unreachable ();
3913+ }
3914+ }
3915+
3916+ return true;
3917+}
3918+
3919+/* Return a legitimate address for REG + OFFSET. TEMP is as for
3920+ riscv_force_temporary; it is only needed when OFFSET is not a
3921+ SMALL_OPERAND. */
3922+
3923+static rtx
3924+riscv_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
3925+{
3926+ if (!SMALL_OPERAND (offset))
3927+ {
3928+ rtx high;
3929+
3930+ /* Leave OFFSET as a 16-bit offset and put the excess in HIGH.
3931+ The addition inside the macro CONST_HIGH_PART may cause an
3932+ overflow, so we need to force a sign-extension check. */
3933+ high = gen_int_mode (RISCV_CONST_HIGH_PART (offset), Pmode);
3934+ offset = RISCV_CONST_LOW_PART (offset);
3935+ high = riscv_force_temporary (temp, high);
3936+ reg = riscv_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
3937+ }
3938+ return plus_constant (Pmode, reg, offset);
3939+}
3940+
3941+/* The __tls_get_attr symbol. */
3942+static GTY(()) rtx riscv_tls_symbol;
3943+
3944+/* Return an instruction sequence that calls __tls_get_addr. SYM is
3945+ the TLS symbol we are referencing and TYPE is the symbol type to use
3946+ (either global dynamic or local dynamic). RESULT is an RTX for the
3947+ return value location. */
3948+
3949+static rtx
3950+riscv_call_tls_get_addr (rtx sym, rtx result)
3951+{
3952+ rtx insn, a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
3953+
3954+ if (!riscv_tls_symbol)
3955+ riscv_tls_symbol = init_one_libfunc ("__tls_get_addr");
3956+
3957+ start_sequence ();
3958+
3959+ emit_insn (riscv_got_load_tls_gd (a0, sym));
3960+ insn = riscv_expand_call (false, result, riscv_tls_symbol, const0_rtx);
3961+ RTL_CONST_CALL_P (insn) = 1;
3962+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
3963+ insn = get_insns ();
3964+
3965+ end_sequence ();
3966+
3967+ return insn;
3968+}
3969+
3970+/* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
3971+ its address. The return value will be both a valid address and a valid
3972+ SET_SRC (either a REG or a LO_SUM). */
3973+
3974+static rtx
3975+riscv_legitimize_tls_address (rtx loc)
3976+{
3977+ rtx dest, insn, tp, tmp1;
3978+ enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
3979+
3980+ /* Since we support TLS copy relocs, non-PIC TLS accesses may all use LE. */
3981+ if (!flag_pic)
3982+ model = TLS_MODEL_LOCAL_EXEC;
3983+
3984+ switch (model)
3985+ {
3986+ case TLS_MODEL_LOCAL_DYNAMIC:
3987+ /* Rely on section anchors for the optimization that LDM TLS
3988+ provides. The anchor's address is loaded with GD TLS. */
3989+ case TLS_MODEL_GLOBAL_DYNAMIC:
3990+ tmp1 = gen_rtx_REG (Pmode, GP_RETURN);
3991+ insn = riscv_call_tls_get_addr (loc, tmp1);
3992+ dest = gen_reg_rtx (Pmode);
3993+ emit_libcall_block (insn, dest, tmp1, loc);
3994+ break;
3995+
3996+ case TLS_MODEL_INITIAL_EXEC:
3997+ /* la.tls.ie; tp-relative add */
3998+ tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
3999+ tmp1 = gen_reg_rtx (Pmode);
4000+ emit_insn (riscv_got_load_tls_ie (tmp1, loc));
4001+ dest = gen_reg_rtx (Pmode);
4002+ emit_insn (gen_add3_insn (dest, tmp1, tp));
4003+ break;
4004+
4005+ case TLS_MODEL_LOCAL_EXEC:
4006+ tmp1 = riscv_unspec_offset_high (NULL, loc, SYMBOL_TLS_LE);
4007+ dest = gen_reg_rtx (Pmode);
4008+ emit_insn (riscv_tls_add_tp_le (dest, tmp1, loc));
4009+ dest = gen_rtx_LO_SUM (Pmode, dest,
4010+ riscv_unspec_address (loc, SYMBOL_TLS_LE));
4011+ break;
4012+
4013+ default:
4014+ gcc_unreachable ();
4015+ }
4016+ return dest;
4017+}
4018+
4019+/* If X is not a valid address for mode MODE, force it into a register. */
4020+
4021+static rtx
4022+riscv_force_address (rtx x, enum machine_mode mode)
4023+{
4024+ if (!riscv_legitimate_address_p (mode, x, false))
4025+ x = force_reg (Pmode, x);
4026+ return x;
4027+}
4028+
4029+/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
4030+ be legitimized in a way that the generic machinery might not expect,
4031+ return a new address, otherwise return NULL. MODE is the mode of
4032+ the memory being accessed. */
4033+
4034+static rtx
4035+riscv_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
4036+ enum machine_mode mode)
4037+{
4038+ rtx addr;
4039+
4040+ if (riscv_tls_symbol_p (x))
4041+ return riscv_legitimize_tls_address (x);
4042+
4043+ /* See if the address can split into a high part and a LO_SUM. */
4044+ if (riscv_split_symbol (NULL, x, mode, &addr))
4045+ return riscv_force_address (addr, mode);
4046+
4047+ /* Handle BASE + OFFSET using riscv_add_offset. */
4048+ if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))
4049+ && INTVAL (XEXP (x, 1)) != 0)
4050+ {
4051+ rtx base = XEXP (x, 0);
4052+ HOST_WIDE_INT offset = INTVAL (XEXP (x, 1));
4053+
4054+ if (!riscv_valid_base_register_p (base, mode, false))
4055+ base = copy_to_mode_reg (Pmode, base);
4056+ addr = riscv_add_offset (NULL, base, offset);
4057+ return riscv_force_address (addr, mode);
4058+ }
4059+
4060+ return x;
4061+}
4062+
4063+/* Load VALUE into DEST. TEMP is as for riscv_force_temporary. */
4064+
4065+void
4066+riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value)
4067+{
4068+ struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS];
4069+ enum machine_mode mode;
4070+ int i, num_ops;
4071+ rtx x;
4072+
4073+ mode = GET_MODE (dest);
4074+ num_ops = riscv_build_integer (codes, value, mode);
4075+
4076+ if (can_create_pseudo_p () && num_ops > 2 /* not a simple constant */
4077+ && num_ops >= riscv_split_integer_cost (value))
4078+ x = riscv_split_integer (value, mode);
4079+ else
4080+ {
4081+ /* Apply each binary operation to X. */
4082+ x = GEN_INT (codes[0].value);
4083+
4084+ for (i = 1; i < num_ops; i++)
4085+ {
4086+ if (!can_create_pseudo_p ())
4087+ {
4088+ emit_insn (gen_rtx_SET (VOIDmode, temp, x));
4089+ x = temp;
4090+ }
4091+ else
4092+ x = force_reg (mode, x);
4093+
4094+ x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value));
4095+ }
4096+ }
4097+
4098+ emit_insn (gen_rtx_SET (VOIDmode, dest, x));
4099+}
4100+
4101+/* Subroutine of riscv_legitimize_move. Move constant SRC into register
4102+ DEST given that SRC satisfies immediate_operand but doesn't satisfy
4103+ move_operand. */
4104+
4105+static void
4106+riscv_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
4107+{
4108+ rtx base, offset;
4109+
4110+ /* Split moves of big integers into smaller pieces. */
4111+ if (splittable_const_int_operand (src, mode))
4112+ {
4113+ riscv_move_integer (dest, dest, INTVAL (src));
4114+ return;
4115+ }
4116+
4117+ /* Split moves of symbolic constants into high/low pairs. */
4118+ if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src))
4119+ {
4120+ emit_insn (gen_rtx_SET (VOIDmode, dest, src));
4121+ return;
4122+ }
4123+
4124+ /* Generate the appropriate access sequences for TLS symbols. */
4125+ if (riscv_tls_symbol_p (src))
4126+ {
4127+ riscv_emit_move (dest, riscv_legitimize_tls_address (src));
4128+ return;
4129+ }
4130+
4131+ /* If we have (const (plus symbol offset)), and that expression cannot
4132+ be forced into memory, load the symbol first and add in the offset. Also
4133+ prefer to do this even if the constant _can_ be forced into memory, as it
4134+ usually produces better code. */
4135+ split_const (src, &base, &offset);
4136+ if (offset != const0_rtx
4137+ && (targetm.cannot_force_const_mem (mode, src) || can_create_pseudo_p ()))
4138+ {
4139+ base = riscv_force_temporary (dest, base);
4140+ riscv_emit_move (dest, riscv_add_offset (NULL, base, INTVAL (offset)));
4141+ return;
4142+ }
4143+
4144+ src = force_const_mem (mode, src);
4145+
4146+ /* When using explicit relocs, constant pool references are sometimes
4147+ not legitimate addresses. */
4148+ riscv_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0));
4149+ riscv_emit_move (dest, src);
4150+}
4151+
4152+/* If (set DEST SRC) is not a valid move instruction, emit an equivalent
4153+ sequence that is valid. */
4154+
4155+bool
4156+riscv_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
4157+{
4158+ if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
4159+ {
4160+ riscv_emit_move (dest, force_reg (mode, src));
4161+ return true;
4162+ }
4163+
4164+ /* We need to deal with constants that would be legitimate
4165+ immediate_operands but aren't legitimate move_operands. */
4166+ if (CONSTANT_P (src) && !move_operand (src, mode))
4167+ {
4168+ riscv_legitimize_const_move (mode, dest, src);
4169+ set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
4170+ return true;
4171+ }
4172+ return false;
4173+}
4174+
4175+/* Return true if there is an instruction that implements CODE and accepts
4176+ X as an immediate operand. */
4177+
4178+static int
4179+riscv_immediate_operand_p (int code, HOST_WIDE_INT x)
4180+{
4181+ switch (code)
4182+ {
4183+ case ASHIFT:
4184+ case ASHIFTRT:
4185+ case LSHIFTRT:
4186+ /* All shift counts are truncated to a valid constant. */
4187+ return true;
4188+
4189+ case AND:
4190+ case IOR:
4191+ case XOR:
4192+ case PLUS:
4193+ case LT:
4194+ case LTU:
4195+ /* These instructions take 12-bit signed immediates. */
4196+ return SMALL_OPERAND (x);
4197+
4198+ case LE:
4199+ /* We add 1 to the immediate and use SLT. */
4200+ return SMALL_OPERAND (x + 1);
4201+
4202+ case LEU:
4203+ /* Likewise SLTU, but reject the always-true case. */
4204+ return SMALL_OPERAND (x + 1) && x + 1 != 0;
4205+
4206+ case GE:
4207+ case GEU:
4208+ /* We can emulate an immediate of 1 by using GT/GTU against x0. */
4209+ return x == 1;
4210+
4211+ default:
4212+ /* By default assume that x0 can be used for 0. */
4213+ return x == 0;
4214+ }
4215+}
4216+
4217+/* Return the cost of binary operation X, given that the instruction
4218+ sequence for a word-sized or smaller operation takes SIGNLE_INSNS
4219+ instructions and that the sequence of a double-word operation takes
4220+ DOUBLE_INSNS instructions. */
4221+
4222+static int
4223+riscv_binary_cost (rtx x, int single_insns, int double_insns)
4224+{
4225+ if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
4226+ return COSTS_N_INSNS (double_insns);
4227+ return COSTS_N_INSNS (single_insns);
4228+}
4229+
4230+/* Return the cost of sign-extending OP to mode MODE, not including the
4231+ cost of OP itself. */
4232+
4233+static int
4234+riscv_sign_extend_cost (enum machine_mode mode, rtx op)
4235+{
4236+ if (MEM_P (op))
4237+ /* Extended loads are as cheap as unextended ones. */
4238+ return 0;
4239+
4240+ if (TARGET_64BIT && mode == DImode && GET_MODE (op) == SImode)
4241+ /* A sign extension from SImode to DImode in 64-bit mode is free. */
4242+ return 0;
4243+
4244+ /* We need to use a shift left and a shift right. */
4245+ return COSTS_N_INSNS (2);
4246+}
4247+
4248+/* Return the cost of zero-extending OP to mode MODE, not including the
4249+ cost of OP itself. */
4250+
4251+static int
4252+riscv_zero_extend_cost (enum machine_mode mode, rtx op)
4253+{
4254+ if (MEM_P (op))
4255+ /* Extended loads are as cheap as unextended ones. */
4256+ return 0;
4257+
4258+ if ((TARGET_64BIT && mode == DImode && GET_MODE (op) == SImode) ||
4259+ ((mode == DImode || mode == SImode) && GET_MODE (op) == HImode))
4260+ /* We need a shift left by 32 bits and a shift right by 32 bits. */
4261+ return COSTS_N_INSNS (2);
4262+
4263+ /* We can use ANDI. */
4264+ return COSTS_N_INSNS (1);
4265+}
4266+
4267+/* Implement TARGET_RTX_COSTS. */
4268+
4269+static bool
4270+riscv_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
4271+ int *total, bool speed)
4272+{
4273+ enum machine_mode mode = GET_MODE (x);
4274+ bool float_mode_p = FLOAT_MODE_P (mode);
4275+ int cost;
4276+
4277+ switch (code)
4278+ {
4279+ case CONST_INT:
4280+ if (riscv_immediate_operand_p (outer_code, INTVAL (x)))
4281+ {
4282+ *total = 0;
4283+ return true;
4284+ }
4285+ /* Fall through. */
4286+
4287+ case SYMBOL_REF:
4288+ case LABEL_REF:
4289+ case CONST_DOUBLE:
4290+ case CONST:
4291+ if (speed)
4292+ *total = 1;
4293+ else if ((cost = riscv_const_insns (x)) > 0)
4294+ *total = COSTS_N_INSNS (cost);
4295+ else /* The instruction will be fetched from the constant pool. */
4296+ *total = COSTS_N_INSNS (riscv_symbol_insns (SYMBOL_ABSOLUTE));
4297+ return true;
4298+
4299+ case MEM:
4300+ /* If the address is legitimate, return the number of
4301+ instructions it needs. */
4302+ if ((cost = riscv_address_insns (XEXP (x, 0), mode, true)) > 0)
4303+ {
4304+ *total = COSTS_N_INSNS (cost + tune_info->memory_cost);
4305+ return true;
4306+ }
4307+ /* Otherwise use the default handling. */
4308+ return false;
4309+
4310+ case NOT:
4311+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
4312+ return false;
4313+
4314+ case AND:
4315+ case IOR:
4316+ case XOR:
4317+ /* Double-word operations use two single-word operations. */
4318+ *total = riscv_binary_cost (x, 1, 2);
4319+ return false;
4320+
4321+ case ASHIFT:
4322+ case ASHIFTRT:
4323+ case LSHIFTRT:
4324+ *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9);
4325+ return false;
4326+
4327+ case ABS:
4328+ *total = COSTS_N_INSNS (float_mode_p ? 1 : 3);
4329+ return false;
4330+
4331+ case LO_SUM:
4332+ *total = set_src_cost (XEXP (x, 0), speed);
4333+ return true;
4334+
4335+ case LT:
4336+ case LTU:
4337+ case LE:
4338+ case LEU:
4339+ case GT:
4340+ case GTU:
4341+ case GE:
4342+ case GEU:
4343+ case EQ:
4344+ case NE:
4345+ case UNORDERED:
4346+ case LTGT:
4347+ /* Branch comparisons have VOIDmode, so use the first operand's
4348+ mode instead. */
4349+ mode = GET_MODE (XEXP (x, 0));
4350+ if (float_mode_p)
4351+ *total = tune_info->fp_add[mode == DFmode];
4352+ else
4353+ *total = riscv_binary_cost (x, 1, 3);
4354+ return false;
4355+
4356+ case MINUS:
4357+ if (float_mode_p
4358+ && !HONOR_NANS (mode)
4359+ && !HONOR_SIGNED_ZEROS (mode))
4360+ {
4361+ /* See if we can use NMADD or NMSUB. See riscv.md for the
4362+ associated patterns. */
4363+ rtx op0 = XEXP (x, 0);
4364+ rtx op1 = XEXP (x, 1);
4365+ if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
4366+ {
4367+ *total = (tune_info->fp_mul[mode == DFmode]
4368+ + set_src_cost (XEXP (XEXP (op0, 0), 0), speed)
4369+ + set_src_cost (XEXP (op0, 1), speed)
4370+ + set_src_cost (op1, speed));
4371+ return true;
4372+ }
4373+ if (GET_CODE (op1) == MULT)
4374+ {
4375+ *total = (tune_info->fp_mul[mode == DFmode]
4376+ + set_src_cost (op0, speed)
4377+ + set_src_cost (XEXP (op1, 0), speed)
4378+ + set_src_cost (XEXP (op1, 1), speed));
4379+ return true;
4380+ }
4381+ }
4382+ /* Fall through. */
4383+
4384+ case PLUS:
4385+ if (float_mode_p)
4386+ *total = tune_info->fp_add[mode == DFmode];
4387+ else
4388+ *total = riscv_binary_cost (x, 1, 4);
4389+ return false;
4390+
4391+ case NEG:
4392+ if (float_mode_p
4393+ && !HONOR_NANS (mode)
4394+ && HONOR_SIGNED_ZEROS (mode))
4395+ {
4396+ /* See if we can use NMADD or NMSUB. See riscv.md for the
4397+ associated patterns. */
4398+ rtx op = XEXP (x, 0);
4399+ if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
4400+ && GET_CODE (XEXP (op, 0)) == MULT)
4401+ {
4402+ *total = (tune_info->fp_mul[mode == DFmode]
4403+ + set_src_cost (XEXP (XEXP (op, 0), 0), speed)
4404+ + set_src_cost (XEXP (XEXP (op, 0), 1), speed)
4405+ + set_src_cost (XEXP (op, 1), speed));
4406+ return true;
4407+ }
4408+ }
4409+
4410+ if (float_mode_p)
4411+ *total = tune_info->fp_add[mode == DFmode];
4412+ else
4413+ *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
4414+ return false;
4415+
4416+ case MULT:
4417+ if (float_mode_p)
4418+ *total = tune_info->fp_mul[mode == DFmode];
4419+ else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
4420+ *total = 3 * tune_info->int_mul[0] + COSTS_N_INSNS (2);
4421+ else if (!speed)
4422+ *total = COSTS_N_INSNS (1);
4423+ else
4424+ *total = tune_info->int_mul[mode == DImode];
4425+ return false;
4426+
4427+ case DIV:
4428+ case SQRT:
4429+ case MOD:
4430+ if (float_mode_p)
4431+ {
4432+ *total = tune_info->fp_div[mode == DFmode];
4433+ return false;
4434+ }
4435+ /* Fall through. */
4436+
4437+ case UDIV:
4438+ case UMOD:
4439+ if (speed)
4440+ *total = tune_info->int_div[mode == DImode];
4441+ else
4442+ *total = COSTS_N_INSNS (1);
4443+ return false;
4444+
4445+ case SIGN_EXTEND:
4446+ *total = riscv_sign_extend_cost (mode, XEXP (x, 0));
4447+ return false;
4448+
4449+ case ZERO_EXTEND:
4450+ *total = riscv_zero_extend_cost (mode, XEXP (x, 0));
4451+ return false;
4452+
4453+ case FLOAT:
4454+ case UNSIGNED_FLOAT:
4455+ case FIX:
4456+ case FLOAT_EXTEND:
4457+ case FLOAT_TRUNCATE:
4458+ *total = tune_info->fp_add[mode == DFmode];
4459+ return false;
4460+
4461+ default:
4462+ return false;
4463+ }
4464+}
4465+
4466+/* Implement TARGET_ADDRESS_COST. */
4467+
4468+static int
4469+riscv_address_cost (rtx addr, enum machine_mode mode,
4470+ addr_space_t as ATTRIBUTE_UNUSED,
4471+ bool speed ATTRIBUTE_UNUSED)
4472+{
4473+ return riscv_address_insns (addr, mode, false);
4474+}
4475+
4476+/* Return one word of double-word value OP. HIGH_P is true to select the
4477+ high part or false to select the low part. */
4478+
4479+rtx
4480+riscv_subword (rtx op, bool high_p)
4481+{
4482+ unsigned int byte;
4483+ enum machine_mode mode;
4484+
4485+ mode = GET_MODE (op);
4486+ if (mode == VOIDmode)
4487+ mode = TARGET_64BIT ? TImode : DImode;
4488+
4489+ byte = high_p ? UNITS_PER_WORD : 0;
4490+
4491+ if (FP_REG_RTX_P (op))
4492+ return gen_rtx_REG (word_mode, REGNO (op) + high_p);
4493+
4494+ if (MEM_P (op))
4495+ return adjust_address (op, word_mode, byte);
4496+
4497+ return simplify_gen_subreg (word_mode, op, mode, byte);
4498+}
4499+
4500+/* Return true if a 64-bit move from SRC to DEST should be split into two. */
4501+
4502+bool
4503+riscv_split_64bit_move_p (rtx dest, rtx src)
4504+{
4505+ /* All 64b moves are legal in 64b mode. All 64b FPR <-> FPR and
4506+ FPR <-> MEM moves are legal in 32b mode, too. Although
4507+ FPR <-> GPR moves are not available in general in 32b mode,
4508+ we can at least load 0 into an FPR with fcvt.d.w fpr, x0. */
4509+ return !(TARGET_64BIT
4510+ || (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
4511+ || (FP_REG_RTX_P (dest) && MEM_P (src))
4512+ || (FP_REG_RTX_P (src) && MEM_P (dest))
4513+ || (FP_REG_RTX_P(dest) && src == CONST0_RTX(GET_MODE(src))));
4514+}
4515+
4516+/* Split a doubleword move from SRC to DEST. On 32-bit targets,
4517+ this function handles 64-bit moves for which riscv_split_64bit_move_p
4518+ holds. For 64-bit targets, this function handles 128-bit moves. */
4519+
4520+void
4521+riscv_split_doubleword_move (rtx dest, rtx src)
4522+{
4523+ rtx low_dest;
4524+
4525+ /* The operation can be split into two normal moves. Decide in
4526+ which order to do them. */
4527+ low_dest = riscv_subword (dest, false);
4528+ if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src))
4529+ {
4530+ riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true));
4531+ riscv_emit_move (low_dest, riscv_subword (src, false));
4532+ }
4533+ else
4534+ {
4535+ riscv_emit_move (low_dest, riscv_subword (src, false));
4536+ riscv_emit_move (riscv_subword (dest, true), riscv_subword (src, true));
4537+ }
4538+}
4539+
4540+/* Return the appropriate instructions to move SRC into DEST. Assume
4541+ that SRC is operand 1 and DEST is operand 0. */
4542+
4543+const char *
4544+riscv_output_move (rtx dest, rtx src)
4545+{
4546+ enum rtx_code dest_code, src_code;
4547+ enum machine_mode mode;
4548+ bool dbl_p;
4549+
4550+ dest_code = GET_CODE (dest);
4551+ src_code = GET_CODE (src);
4552+ mode = GET_MODE (dest);
4553+ dbl_p = (GET_MODE_SIZE (mode) == 8);
4554+
4555+ if (dbl_p && riscv_split_64bit_move_p (dest, src))
4556+ return "#";
4557+
4558+ if ((src_code == REG && GP_REG_P (REGNO (src)))
4559+ || (src == CONST0_RTX (mode)))
4560+ {
4561+ if (dest_code == REG)
4562+ {
4563+ if (GP_REG_P (REGNO (dest)))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02004564+ return "mv\t%0,%z1";
Patrick Georgif0bbc952015-03-07 10:57:25 +01004565+
4566+ if (FP_REG_P (REGNO (dest)))
4567+ {
4568+ if (!dbl_p)
4569+ return "fmv.s.x\t%0,%z1";
4570+ if (TARGET_64BIT)
4571+ return "fmv.d.x\t%0,%z1";
4572+ /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
4573+ gcc_assert (src == CONST0_RTX (mode));
4574+ return "fcvt.d.w\t%0,x0";
4575+ }
4576+ }
4577+ if (dest_code == MEM)
4578+ switch (GET_MODE_SIZE (mode))
4579+ {
4580+ case 1: return "sb\t%z1,%0";
4581+ case 2: return "sh\t%z1,%0";
4582+ case 4: return "sw\t%z1,%0";
4583+ case 8: return "sd\t%z1,%0";
4584+ }
4585+ }
4586+ if (dest_code == REG && GP_REG_P (REGNO (dest)))
4587+ {
4588+ if (src_code == REG)
4589+ {
4590+ if (FP_REG_P (REGNO (src)))
4591+ return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.s\t%0,%1";
4592+ }
4593+
4594+ if (src_code == MEM)
4595+ switch (GET_MODE_SIZE (mode))
4596+ {
4597+ case 1: return "lbu\t%0,%1";
4598+ case 2: return "lhu\t%0,%1";
4599+ case 4: return "lw\t%0,%1";
4600+ case 8: return "ld\t%0,%1";
4601+ }
4602+
4603+ if (src_code == CONST_INT)
4604+ return "li\t%0,%1";
4605+
4606+ if (src_code == HIGH)
4607+ return "lui\t%0,%h1";
4608+
4609+ if (symbolic_operand (src, VOIDmode))
4610+ switch (riscv_classify_symbolic_expression (src))
4611+ {
4612+ case SYMBOL_GOT_DISP: return "la\t%0,%1";
4613+ case SYMBOL_ABSOLUTE: return "lla\t%0,%1";
4614+ default: gcc_unreachable();
4615+ }
4616+ }
4617+ if (src_code == REG && FP_REG_P (REGNO (src)))
4618+ {
4619+ if (dest_code == REG && FP_REG_P (REGNO (dest)))
4620+ return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1";
4621+
4622+ if (dest_code == MEM)
4623+ return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0";
4624+ }
4625+ if (dest_code == REG && FP_REG_P (REGNO (dest)))
4626+ {
4627+ if (src_code == MEM)
4628+ return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1";
4629+ }
4630+ gcc_unreachable ();
4631+}
4632+
4633+/* Return true if CMP1 is a suitable second operand for integer ordering
4634+ test CODE. See also the *sCC patterns in riscv.md. */
4635+
4636+static bool
4637+riscv_int_order_operand_ok_p (enum rtx_code code, rtx cmp1)
4638+{
4639+ switch (code)
4640+ {
4641+ case GT:
4642+ case GTU:
4643+ return reg_or_0_operand (cmp1, VOIDmode);
4644+
4645+ case GE:
4646+ case GEU:
4647+ return cmp1 == const1_rtx;
4648+
4649+ case LT:
4650+ case LTU:
4651+ return arith_operand (cmp1, VOIDmode);
4652+
4653+ case LE:
4654+ return sle_operand (cmp1, VOIDmode);
4655+
4656+ case LEU:
4657+ return sleu_operand (cmp1, VOIDmode);
4658+
4659+ default:
4660+ gcc_unreachable ();
4661+ }
4662+}
4663+
4664+/* Return true if *CMP1 (of mode MODE) is a valid second operand for
4665+ integer ordering test *CODE, or if an equivalent combination can
4666+ be formed by adjusting *CODE and *CMP1. When returning true, update
4667+ *CODE and *CMP1 with the chosen code and operand, otherwise leave
4668+ them alone. */
4669+
4670+static bool
4671+riscv_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1,
4672+ enum machine_mode mode)
4673+{
4674+ HOST_WIDE_INT plus_one;
4675+
4676+ if (riscv_int_order_operand_ok_p (*code, *cmp1))
4677+ return true;
4678+
4679+ if (CONST_INT_P (*cmp1))
4680+ switch (*code)
4681+ {
4682+ case LE:
4683+ plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
4684+ if (INTVAL (*cmp1) < plus_one)
4685+ {
4686+ *code = LT;
4687+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
4688+ return true;
4689+ }
4690+ break;
4691+
4692+ case LEU:
4693+ plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode);
4694+ if (plus_one != 0)
4695+ {
4696+ *code = LTU;
4697+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
4698+ return true;
4699+ }
4700+ break;
4701+
4702+ default:
4703+ break;
4704+ }
4705+ return false;
4706+}
4707+
4708+/* Compare CMP0 and CMP1 using ordering test CODE and store the result
4709+ in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR
4710+ is nonnull, it's OK to set TARGET to the inverse of the result and
4711+ flip *INVERT_PTR instead. */
4712+
4713+static void
4714+riscv_emit_int_order_test (enum rtx_code code, bool *invert_ptr,
4715+ rtx target, rtx cmp0, rtx cmp1)
4716+{
4717+ enum machine_mode mode;
4718+
4719+ /* First see if there is a RISCV instruction that can do this operation.
4720+ If not, try doing the same for the inverse operation. If that also
4721+ fails, force CMP1 into a register and try again. */
4722+ mode = GET_MODE (cmp0);
4723+ if (riscv_canonicalize_int_order_test (&code, &cmp1, mode))
4724+ riscv_emit_binary (code, target, cmp0, cmp1);
4725+ else
4726+ {
4727+ enum rtx_code inv_code = reverse_condition (code);
4728+ if (!riscv_canonicalize_int_order_test (&inv_code, &cmp1, mode))
4729+ {
4730+ cmp1 = force_reg (mode, cmp1);
4731+ riscv_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1);
4732+ }
4733+ else if (invert_ptr == 0)
4734+ {
4735+ rtx inv_target;
4736+
4737+ inv_target = riscv_force_binary (GET_MODE (target),
4738+ inv_code, cmp0, cmp1);
4739+ riscv_emit_binary (XOR, target, inv_target, const1_rtx);
4740+ }
4741+ else
4742+ {
4743+ *invert_ptr = !*invert_ptr;
4744+ riscv_emit_binary (inv_code, target, cmp0, cmp1);
4745+ }
4746+ }
4747+}
4748+
4749+/* Return a register that is zero iff CMP0 and CMP1 are equal.
4750+ The register will have the same mode as CMP0. */
4751+
4752+static rtx
4753+riscv_zero_if_equal (rtx cmp0, rtx cmp1)
4754+{
4755+ if (cmp1 == const0_rtx)
4756+ return cmp0;
4757+
4758+ return expand_binop (GET_MODE (cmp0), sub_optab,
4759+ cmp0, cmp1, 0, 0, OPTAB_DIRECT);
4760+}
4761+
4762+/* Return false if we can easily emit code for the FP comparison specified
4763+ by *CODE. If not, set *CODE to its inverse and return true. */
4764+
4765+static bool
4766+riscv_reversed_fp_cond (enum rtx_code *code)
4767+{
4768+ switch (*code)
4769+ {
4770+ case EQ:
4771+ case LT:
4772+ case LE:
4773+ case GT:
4774+ case GE:
4775+ case LTGT:
4776+ case ORDERED:
4777+ /* We know how to emit code for these cases... */
4778+ return false;
4779+
4780+ default:
4781+ /* ...but we must invert these and rely on the others. */
4782+ *code = reverse_condition_maybe_unordered (*code);
4783+ return true;
4784+ }
4785+}
4786+
4787+/* Convert a comparison into something that can be used in a branch or
4788+ conditional move. On entry, *OP0 and *OP1 are the values being
4789+ compared and *CODE is the code used to compare them.
4790+
4791+ Update *CODE, *OP0 and *OP1 so that they describe the final comparison. */
4792+
4793+static void
4794+riscv_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1)
4795+{
4796+ rtx cmp_op0 = *op0;
4797+ rtx cmp_op1 = *op1;
4798+
4799+ if (GET_MODE_CLASS (GET_MODE (*op0)) == MODE_INT)
4800+ {
4801+ if (splittable_const_int_operand (cmp_op1, VOIDmode))
4802+ {
4803+ HOST_WIDE_INT rhs = INTVAL (cmp_op1), new_rhs;
4804+ enum rtx_code new_code;
4805+
4806+ switch (*code)
4807+ {
4808+ case LTU: new_rhs = rhs - 1; new_code = LEU; goto try_new_rhs;
4809+ case LEU: new_rhs = rhs + 1; new_code = LTU; goto try_new_rhs;
4810+ case GTU: new_rhs = rhs + 1; new_code = GEU; goto try_new_rhs;
4811+ case GEU: new_rhs = rhs - 1; new_code = GTU; goto try_new_rhs;
4812+ case LT: new_rhs = rhs - 1; new_code = LE; goto try_new_rhs;
4813+ case LE: new_rhs = rhs + 1; new_code = LT; goto try_new_rhs;
4814+ case GT: new_rhs = rhs + 1; new_code = GE; goto try_new_rhs;
4815+ case GE: new_rhs = rhs - 1; new_code = GT;
4816+ try_new_rhs:
4817+ /* Convert e.g. OP0 > 4095 into OP0 >= 4096. */
4818+ if ((rhs < 0) == (new_rhs < 0)
4819+ && riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs))
4820+ {
4821+ *op1 = GEN_INT (new_rhs);
4822+ *code = new_code;
4823+ }
4824+ break;
4825+
4826+ case EQ:
4827+ case NE:
4828+ /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */
4829+ if (SMALL_OPERAND (-rhs))
4830+ {
4831+ *op0 = gen_reg_rtx (GET_MODE (cmp_op0));
4832+ riscv_emit_binary (PLUS, *op0, cmp_op0, GEN_INT (-rhs));
4833+ *op1 = const0_rtx;
4834+ }
4835+ default:
4836+ break;
4837+ }
4838+ }
4839+
4840+ if (*op1 != const0_rtx)
4841+ *op1 = force_reg (GET_MODE (cmp_op0), *op1);
4842+ }
4843+ else
4844+ {
4845+ /* For FP comparisons, set an integer register with the result of the
4846+ comparison, then branch on it. */
4847+ rtx tmp0, tmp1, final_op;
4848+ enum rtx_code fp_code = *code;
4849+ *code = riscv_reversed_fp_cond (&fp_code) ? EQ : NE;
4850+
4851+ switch (fp_code)
4852+ {
4853+ case ORDERED:
4854+ /* a == a && b == b */
4855+ tmp0 = gen_reg_rtx (SImode);
4856+ riscv_emit_binary (EQ, tmp0, cmp_op0, cmp_op0);
4857+ tmp1 = gen_reg_rtx (SImode);
4858+ riscv_emit_binary (EQ, tmp1, cmp_op1, cmp_op1);
4859+ final_op = gen_reg_rtx (SImode);
4860+ riscv_emit_binary (AND, final_op, tmp0, tmp1);
4861+ break;
4862+
4863+ case LTGT:
4864+ /* a < b || a > b */
4865+ tmp0 = gen_reg_rtx (SImode);
4866+ riscv_emit_binary (LT, tmp0, cmp_op0, cmp_op1);
4867+ tmp1 = gen_reg_rtx (SImode);
4868+ riscv_emit_binary (GT, tmp1, cmp_op0, cmp_op1);
4869+ final_op = gen_reg_rtx (SImode);
4870+ riscv_emit_binary (IOR, final_op, tmp0, tmp1);
4871+ break;
4872+
4873+ case EQ:
4874+ case LE:
4875+ case LT:
4876+ case GE:
4877+ case GT:
4878+ /* We have instructions for these cases. */
4879+ final_op = gen_reg_rtx (SImode);
4880+ riscv_emit_binary (fp_code, final_op, cmp_op0, cmp_op1);
4881+ break;
4882+
4883+ default:
4884+ gcc_unreachable ();
4885+ }
4886+
4887+ /* Compare the binary result against 0. */
4888+ *op0 = final_op;
4889+ *op1 = const0_rtx;
4890+ }
4891+}
4892+
4893+/* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2]
4894+ and OPERAND[3]. Store the result in OPERANDS[0].
4895+
4896+ On 64-bit targets, the mode of the comparison and target will always be
4897+ SImode, thus possibly narrower than that of the comparison's operands. */
4898+
4899+void
4900+riscv_expand_scc (rtx operands[])
4901+{
4902+ rtx target = operands[0];
4903+ enum rtx_code code = GET_CODE (operands[1]);
4904+ rtx op0 = operands[2];
4905+ rtx op1 = operands[3];
4906+
4907+ gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT);
4908+
4909+ if (code == EQ || code == NE)
4910+ {
4911+ rtx zie = riscv_zero_if_equal (op0, op1);
4912+ riscv_emit_binary (code, target, zie, const0_rtx);
4913+ }
4914+ else
4915+ riscv_emit_int_order_test (code, 0, target, op0, op1);
4916+}
4917+
4918+/* Compare OPERANDS[1] with OPERANDS[2] using comparison code
4919+ CODE and jump to OPERANDS[3] if the condition holds. */
4920+
4921+void
4922+riscv_expand_conditional_branch (rtx *operands)
4923+{
4924+ enum rtx_code code = GET_CODE (operands[0]);
4925+ rtx op0 = operands[1];
4926+ rtx op1 = operands[2];
4927+ rtx condition;
4928+
4929+ riscv_emit_compare (&code, &op0, &op1);
4930+ condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
4931+ emit_jump_insn (gen_condjump (condition, operands[3]));
4932+}
4933+
4934+/* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at
4935+ least PARM_BOUNDARY bits of alignment, but will be given anything up
4936+ to STACK_BOUNDARY bits if the type requires it. */
4937+
4938+static unsigned int
4939+riscv_function_arg_boundary (enum machine_mode mode, const_tree type)
4940+{
4941+ unsigned int alignment;
4942+
4943+ alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
4944+ if (alignment < PARM_BOUNDARY)
4945+ alignment = PARM_BOUNDARY;
4946+ if (alignment > STACK_BOUNDARY)
4947+ alignment = STACK_BOUNDARY;
4948+ return alignment;
4949+}
4950+
4951+/* Fill INFO with information about a single argument. CUM is the
4952+ cumulative state for earlier arguments. MODE is the mode of this
4953+ argument and TYPE is its type (if known). NAMED is true if this
4954+ is a named (fixed) argument rather than a variable one. */
4955+
4956+static void
4957+riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
4958+ enum machine_mode mode, const_tree type, bool named)
4959+{
4960+ bool doubleword_aligned_p;
4961+ unsigned int num_bytes, num_words, max_regs;
4962+
4963+ /* Work out the size of the argument. */
4964+ num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
4965+ num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4966+
4967+ /* Scalar, complex and vector floating-point types are passed in
4968+ floating-point registers, as long as this is a named rather
4969+ than a variable argument. */
4970+ info->fpr_p = (named
4971+ && (type == 0 || FLOAT_TYPE_P (type))
4972+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
4973+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
4974+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
4975+ && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE);
4976+
4977+ /* Complex floats should only go into FPRs if there are two FPRs free,
4978+ otherwise they should be passed in the same way as a struct
4979+ containing two floats. */
4980+ if (info->fpr_p
4981+ && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
4982+ && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE)
4983+ {
4984+ if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1)
4985+ info->fpr_p = false;
4986+ else
4987+ num_words = 2;
4988+ }
4989+
4990+ /* See whether the argument has doubleword alignment. */
4991+ doubleword_aligned_p = (riscv_function_arg_boundary (mode, type)
4992+ > BITS_PER_WORD);
4993+
4994+ /* Set REG_OFFSET to the register count we're interested in.
4995+ The EABI allocates the floating-point registers separately,
4996+ but the other ABIs allocate them like integer registers. */
4997+ info->reg_offset = cum->num_gprs;
4998+
4999+ /* Advance to an even register if the argument is doubleword-aligned. */
5000+ if (doubleword_aligned_p)
5001+ info->reg_offset += info->reg_offset & 1;
5002+
5003+ /* Work out the offset of a stack argument. */
5004+ info->stack_offset = cum->stack_words;
5005+ if (doubleword_aligned_p)
5006+ info->stack_offset += info->stack_offset & 1;
5007+
5008+ max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset;
5009+
5010+ /* Partition the argument between registers and stack. */
5011+ info->reg_words = MIN (num_words, max_regs);
5012+ info->stack_words = num_words - info->reg_words;
5013+}
5014+
5015+/* INFO describes a register argument that has the normal format for the
5016+ argument's mode. Return the register it uses, assuming that FPRs are
5017+ available if HARD_FLOAT_P. */
5018+
5019+static unsigned int
5020+riscv_arg_regno (const struct riscv_arg_info *info, bool hard_float_p)
5021+{
5022+ if (!info->fpr_p || !hard_float_p)
5023+ return GP_ARG_FIRST + info->reg_offset;
5024+ else
5025+ return FP_ARG_FIRST + info->reg_offset;
5026+}
5027+
5028+/* Implement TARGET_FUNCTION_ARG. */
5029+
5030+static rtx
5031+riscv_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
5032+ const_tree type, bool named)
5033+{
5034+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
5035+ struct riscv_arg_info info;
5036+
5037+ if (mode == VOIDmode)
5038+ return NULL;
5039+
5040+ riscv_get_arg_info (&info, cum, mode, type, named);
5041+
5042+ /* Return straight away if the whole argument is passed on the stack. */
5043+ if (info.reg_offset == MAX_ARGS_IN_REGISTERS)
5044+ return NULL;
5045+
5046+ /* The n32 and n64 ABIs say that if any 64-bit chunk of the structure
5047+ contains a double in its entirety, then that 64-bit chunk is passed
5048+ in a floating-point register. */
5049+ if (TARGET_HARD_FLOAT
5050+ && named
5051+ && type != 0
5052+ && TREE_CODE (type) == RECORD_TYPE
5053+ && TYPE_SIZE_UNIT (type)
5054+ && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
5055+ {
5056+ tree field;
5057+
5058+ /* First check to see if there is any such field. */
5059+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
5060+ if (TREE_CODE (field) == FIELD_DECL
5061+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))
5062+ && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
5063+ && tree_fits_shwi_p (bit_position (field))
5064+ && int_bit_position (field) % BITS_PER_WORD == 0)
5065+ break;
5066+
5067+ if (field != 0)
5068+ {
5069+ /* Now handle the special case by returning a PARALLEL
5070+ indicating where each 64-bit chunk goes. INFO.REG_WORDS
5071+ chunks are passed in registers. */
5072+ unsigned int i;
5073+ HOST_WIDE_INT bitpos;
5074+ rtx ret;
5075+
5076+ /* assign_parms checks the mode of ENTRY_PARM, so we must
5077+ use the actual mode here. */
5078+ ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
5079+
5080+ bitpos = 0;
5081+ field = TYPE_FIELDS (type);
5082+ for (i = 0; i < info.reg_words; i++)
5083+ {
5084+ rtx reg;
5085+
5086+ for (; field; field = DECL_CHAIN (field))
5087+ if (TREE_CODE (field) == FIELD_DECL
5088+ && int_bit_position (field) >= bitpos)
5089+ break;
5090+
5091+ if (field
5092+ && int_bit_position (field) == bitpos
5093+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field))
5094+ && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
5095+ reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i);
5096+ else
5097+ reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i);
5098+
5099+ XVECEXP (ret, 0, i)
5100+ = gen_rtx_EXPR_LIST (VOIDmode, reg,
5101+ GEN_INT (bitpos / BITS_PER_UNIT));
5102+
5103+ bitpos += BITS_PER_WORD;
5104+ }
5105+ return ret;
5106+ }
5107+ }
5108+
5109+ /* Handle the n32/n64 conventions for passing complex floating-point
5110+ arguments in FPR pairs. The real part goes in the lower register
5111+ and the imaginary part goes in the upper register. */
5112+ if (info.fpr_p
5113+ && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
5114+ {
5115+ rtx real, imag;
5116+ enum machine_mode inner;
5117+ unsigned int regno;
5118+
5119+ inner = GET_MODE_INNER (mode);
5120+ regno = FP_ARG_FIRST + info.reg_offset;
5121+ if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner))
5122+ {
5123+ /* Real part in registers, imaginary part on stack. */
5124+ gcc_assert (info.stack_words == info.reg_words);
5125+ return gen_rtx_REG (inner, regno);
5126+ }
5127+ else
5128+ {
5129+ gcc_assert (info.stack_words == 0);
5130+ real = gen_rtx_EXPR_LIST (VOIDmode,
5131+ gen_rtx_REG (inner, regno),
5132+ const0_rtx);
5133+ imag = gen_rtx_EXPR_LIST (VOIDmode,
5134+ gen_rtx_REG (inner,
5135+ regno + info.reg_words / 2),
5136+ GEN_INT (GET_MODE_SIZE (inner)));
5137+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
5138+ }
5139+ }
5140+
5141+ return gen_rtx_REG (mode, riscv_arg_regno (&info, TARGET_HARD_FLOAT));
5142+}
5143+
5144+/* Implement TARGET_FUNCTION_ARG_ADVANCE. */
5145+
5146+static void
5147+riscv_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
5148+ const_tree type, bool named)
5149+{
5150+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
5151+ struct riscv_arg_info info;
5152+
5153+ riscv_get_arg_info (&info, cum, mode, type, named);
5154+
5155+ /* Advance the register count. This has the effect of setting
5156+ num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned
5157+ argument required us to skip the final GPR and pass the whole
5158+ argument on the stack. */
5159+ cum->num_gprs = info.reg_offset + info.reg_words;
5160+
5161+ /* Advance the stack word count. */
5162+ if (info.stack_words > 0)
5163+ cum->stack_words = info.stack_offset + info.stack_words;
5164+}
5165+
5166+/* Implement TARGET_ARG_PARTIAL_BYTES. */
5167+
5168+static int
5169+riscv_arg_partial_bytes (cumulative_args_t cum,
5170+ enum machine_mode mode, tree type, bool named)
5171+{
5172+ struct riscv_arg_info info;
5173+
5174+ riscv_get_arg_info (&info, get_cumulative_args (cum), mode, type, named);
5175+ return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
5176+}
5177+
5178+/* See whether VALTYPE is a record whose fields should be returned in
5179+ floating-point registers. If so, return the number of fields and
5180+ list them in FIELDS (which should have two elements). Return 0
5181+ otherwise.
5182+
5183+ For n32 & n64, a structure with one or two fields is returned in
5184+ floating-point registers as long as every field has a floating-point
5185+ type. */
5186+
5187+static int
5188+riscv_fpr_return_fields (const_tree valtype, tree *fields)
5189+{
5190+ tree field;
5191+ int i;
5192+
5193+ if (TREE_CODE (valtype) != RECORD_TYPE)
5194+ return 0;
5195+
5196+ i = 0;
5197+ for (field = TYPE_FIELDS (valtype); field != 0; field = DECL_CHAIN (field))
5198+ {
5199+ if (TREE_CODE (field) != FIELD_DECL)
5200+ continue;
5201+
5202+ if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (field)))
5203+ return 0;
5204+
5205+ if (i == 2)
5206+ return 0;
5207+
5208+ fields[i++] = field;
5209+ }
5210+ return i;
5211+}
5212+
5213+/* Return true if the function return value MODE will get returned in a
5214+ floating-point register. */
5215+
5216+static bool
5217+riscv_return_mode_in_fpr_p (enum machine_mode mode)
5218+{
5219+ return ((GET_MODE_CLASS (mode) == MODE_FLOAT
5220+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
5221+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
5222+ && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_HWFPVALUE);
5223+}
5224+
5225+/* Return the representation of an FPR return register when the
5226+ value being returned in FP_RETURN has mode VALUE_MODE and the
5227+ return type itself has mode TYPE_MODE. On NewABI targets,
5228+ the two modes may be different for structures like:
5229+
5230+ struct __attribute__((packed)) foo { float f; }
5231+
5232+ where we return the SFmode value of "f" in FP_RETURN, but where
5233+ the structure itself has mode BLKmode. */
5234+
5235+static rtx
5236+riscv_return_fpr_single (enum machine_mode type_mode,
5237+ enum machine_mode value_mode)
5238+{
5239+ rtx x;
5240+
5241+ x = gen_rtx_REG (value_mode, FP_RETURN);
5242+ if (type_mode != value_mode)
5243+ {
5244+ x = gen_rtx_EXPR_LIST (VOIDmode, x, const0_rtx);
5245+ x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x));
5246+ }
5247+ return x;
5248+}
5249+
5250+/* Return a composite value in a pair of floating-point registers.
5251+ MODE1 and OFFSET1 are the mode and byte offset for the first value,
5252+ likewise MODE2 and OFFSET2 for the second. MODE is the mode of the
5253+ complete value.
5254+
5255+ For n32 & n64, $f0 always holds the first value and $f2 the second.
5256+ Otherwise the values are packed together as closely as possible. */
5257+
5258+static rtx
5259+riscv_return_fpr_pair (enum machine_mode mode,
5260+ enum machine_mode mode1, HOST_WIDE_INT offset1,
5261+ enum machine_mode mode2, HOST_WIDE_INT offset2)
5262+{
5263+ return gen_rtx_PARALLEL
5264+ (mode,
5265+ gen_rtvec (2,
5266+ gen_rtx_EXPR_LIST (VOIDmode,
5267+ gen_rtx_REG (mode1, FP_RETURN),
5268+ GEN_INT (offset1)),
5269+ gen_rtx_EXPR_LIST (VOIDmode,
5270+ gen_rtx_REG (mode2, FP_RETURN + 1),
5271+ GEN_INT (offset2))));
5272+
5273+}
5274+
5275+/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
5276+ VALTYPE is the return type and MODE is VOIDmode. For libcalls,
5277+ VALTYPE is null and MODE is the mode of the return value. */
5278+
5279+rtx
5280+riscv_function_value (const_tree valtype, const_tree func, enum machine_mode mode)
5281+{
5282+ if (valtype)
5283+ {
5284+ tree fields[2];
5285+ int unsigned_p;
5286+
5287+ mode = TYPE_MODE (valtype);
5288+ unsigned_p = TYPE_UNSIGNED (valtype);
5289+
5290+ /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes,
5291+ return values, promote the mode here too. */
5292+ mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1);
5293+
5294+ /* Handle structures whose fields are returned in $f0/$f2. */
5295+ switch (riscv_fpr_return_fields (valtype, fields))
5296+ {
5297+ case 1:
5298+ return riscv_return_fpr_single (mode,
5299+ TYPE_MODE (TREE_TYPE (fields[0])));
5300+
5301+ case 2:
5302+ return riscv_return_fpr_pair (mode,
5303+ TYPE_MODE (TREE_TYPE (fields[0])),
5304+ int_byte_position (fields[0]),
5305+ TYPE_MODE (TREE_TYPE (fields[1])),
5306+ int_byte_position (fields[1]));
5307+ }
5308+
5309+ /* Only use FPRs for scalar, complex or vector types. */
5310+ if (!FLOAT_TYPE_P (valtype))
5311+ return gen_rtx_REG (mode, GP_RETURN);
5312+ }
5313+
5314+ /* Handle long doubles for n32 & n64. */
5315+ if (mode == TFmode)
5316+ return riscv_return_fpr_pair (mode,
5317+ DImode, 0,
5318+ DImode, GET_MODE_SIZE (mode) / 2);
5319+
5320+ if (riscv_return_mode_in_fpr_p (mode))
5321+ {
5322+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
5323+ return riscv_return_fpr_pair (mode,
5324+ GET_MODE_INNER (mode), 0,
5325+ GET_MODE_INNER (mode),
5326+ GET_MODE_SIZE (mode) / 2);
5327+ else
5328+ return gen_rtx_REG (mode, FP_RETURN);
5329+ }
5330+
5331+ return gen_rtx_REG (mode, GP_RETURN);
5332+}
5333+
5334+/* Implement TARGET_RETURN_IN_MEMORY. Scalars and small structures
5335+ that fit in two registers are returned in a0/a1. */
5336+
5337+static bool
5338+riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED)
5339+{
5340+ return !IN_RANGE (int_size_in_bytes (type), 0, 2 * UNITS_PER_WORD);
5341+}
5342+
5343+/* Implement TARGET_PASS_BY_REFERENCE. */
5344+
5345+static bool
5346+riscv_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
5347+ enum machine_mode mode, const_tree type,
5348+ bool named ATTRIBUTE_UNUSED)
5349+{
5350+ if (type && riscv_return_in_memory (type, NULL_TREE))
5351+ return true;
5352+ return targetm.calls.must_pass_in_stack (mode, type);
5353+}
5354+
5355+/* Implement TARGET_SETUP_INCOMING_VARARGS. */
5356+
5357+static void
5358+riscv_setup_incoming_varargs (cumulative_args_t cum, enum machine_mode mode,
5359+ tree type, int *pretend_size ATTRIBUTE_UNUSED,
5360+ int no_rtl)
5361+{
5362+ CUMULATIVE_ARGS local_cum;
5363+ int gp_saved;
5364+
5365+ /* The caller has advanced CUM up to, but not beyond, the last named
5366+ argument. Advance a local copy of CUM past the last "real" named
5367+ argument, to find out how many registers are left over. */
5368+ local_cum = *get_cumulative_args (cum);
5369+ riscv_function_arg_advance (pack_cumulative_args (&local_cum), mode, type, 1);
5370+
5371+ /* Found out how many registers we need to save. */
5372+ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
5373+
5374+ if (!no_rtl && gp_saved > 0)
5375+ {
5376+ rtx ptr, mem;
5377+
5378+ ptr = plus_constant (Pmode, virtual_incoming_args_rtx,
5379+ REG_PARM_STACK_SPACE (cfun->decl)
5380+ - gp_saved * UNITS_PER_WORD);
5381+ mem = gen_frame_mem (BLKmode, ptr);
5382+ set_mem_alias_set (mem, get_varargs_alias_set ());
5383+
5384+ move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST,
5385+ mem, gp_saved);
5386+ }
5387+ if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
5388+ cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD;
5389+}
5390+
5391+/* Implement TARGET_EXPAND_BUILTIN_VA_START. */
5392+
5393+static void
5394+riscv_va_start (tree valist, rtx nextarg)
5395+{
5396+ nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size);
5397+ std_expand_builtin_va_start (valist, nextarg);
5398+}
5399+
5400+/* Expand a call of type TYPE. RESULT is where the result will go (null
5401+ for "call"s and "sibcall"s), ADDR is the address of the function,
5402+ ARGS_SIZE is the size of the arguments and AUX is the value passed
5403+ to us by riscv_function_arg. Return the call itself. */
5404+
5405+rtx
5406+riscv_expand_call (bool sibcall_p, rtx result, rtx addr, rtx args_size)
5407+{
5408+ rtx pattern;
5409+
5410+ if (!call_insn_operand (addr, VOIDmode))
5411+ {
5412+ rtx reg = RISCV_EPILOGUE_TEMP (Pmode);
5413+ riscv_emit_move (reg, addr);
5414+ addr = reg;
5415+ }
5416+
5417+ if (result == 0)
5418+ {
5419+ rtx (*fn) (rtx, rtx);
5420+
5421+ if (sibcall_p)
5422+ fn = gen_sibcall_internal;
5423+ else
5424+ fn = gen_call_internal;
5425+
5426+ pattern = fn (addr, args_size);
5427+ }
5428+ else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2)
5429+ {
5430+ /* Handle return values created by riscv_return_fpr_pair. */
5431+ rtx (*fn) (rtx, rtx, rtx, rtx);
5432+ rtx reg1, reg2;
5433+
5434+ if (sibcall_p)
5435+ fn = gen_sibcall_value_multiple_internal;
5436+ else
5437+ fn = gen_call_value_multiple_internal;
5438+
5439+ reg1 = XEXP (XVECEXP (result, 0, 0), 0);
5440+ reg2 = XEXP (XVECEXP (result, 0, 1), 0);
5441+ pattern = fn (reg1, addr, args_size, reg2);
5442+ }
5443+ else
5444+ {
5445+ rtx (*fn) (rtx, rtx, rtx);
5446+
5447+ if (sibcall_p)
5448+ fn = gen_sibcall_value_internal;
5449+ else
5450+ fn = gen_call_value_internal;
5451+
5452+ /* Handle return values created by riscv_return_fpr_single. */
5453+ if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 1)
5454+ result = XEXP (XVECEXP (result, 0, 0), 0);
5455+ pattern = fn (result, addr, args_size);
5456+ }
5457+
5458+ return emit_call_insn (pattern);
5459+}
5460+
5461+/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
5462+ Assume that the areas do not overlap. */
5463+
5464+static void
5465+riscv_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
5466+{
5467+ HOST_WIDE_INT offset, delta;
5468+ unsigned HOST_WIDE_INT bits;
5469+ int i;
5470+ enum machine_mode mode;
5471+ rtx *regs;
5472+
5473+ bits = MAX( BITS_PER_UNIT,
5474+ MIN( BITS_PER_WORD, MIN( MEM_ALIGN(src),MEM_ALIGN(dest) ) ) );
5475+
5476+ mode = mode_for_size (bits, MODE_INT, 0);
5477+ delta = bits / BITS_PER_UNIT;
5478+
5479+ /* Allocate a buffer for the temporary registers. */
5480+ regs = XALLOCAVEC (rtx, length / delta);
5481+
5482+ /* Load as many BITS-sized chunks as possible. Use a normal load if
5483+ the source has enough alignment, otherwise use left/right pairs. */
5484+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
5485+ {
5486+ regs[i] = gen_reg_rtx (mode);
5487+ riscv_emit_move (regs[i], adjust_address (src, mode, offset));
5488+ }
5489+
5490+ /* Copy the chunks to the destination. */
5491+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
5492+ riscv_emit_move (adjust_address (dest, mode, offset), regs[i]);
5493+
5494+ /* Mop up any left-over bytes. */
5495+ if (offset < length)
5496+ {
5497+ src = adjust_address (src, BLKmode, offset);
5498+ dest = adjust_address (dest, BLKmode, offset);
5499+ move_by_pieces (dest, src, length - offset,
5500+ MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
5501+ }
5502+}
5503+
5504+/* Helper function for doing a loop-based block operation on memory
5505+ reference MEM. Each iteration of the loop will operate on LENGTH
5506+ bytes of MEM.
5507+
5508+ Create a new base register for use within the loop and point it to
5509+ the start of MEM. Create a new memory reference that uses this
5510+ register. Store them in *LOOP_REG and *LOOP_MEM respectively. */
5511+
5512+static void
5513+riscv_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
5514+ rtx *loop_reg, rtx *loop_mem)
5515+{
5516+ *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
5517+
5518+ /* Although the new mem does not refer to a known location,
5519+ it does keep up to LENGTH bytes of alignment. */
5520+ *loop_mem = change_address (mem, BLKmode, *loop_reg);
5521+ set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
5522+}
5523+
5524+/* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER
5525+ bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that
5526+ the memory regions do not overlap. */
5527+
5528+static void
5529+riscv_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
5530+ HOST_WIDE_INT bytes_per_iter)
5531+{
5532+ rtx label, src_reg, dest_reg, final_src, test;
5533+ HOST_WIDE_INT leftover;
5534+
5535+ leftover = length % bytes_per_iter;
5536+ length -= leftover;
5537+
5538+ /* Create registers and memory references for use within the loop. */
5539+ riscv_adjust_block_mem (src, bytes_per_iter, &src_reg, &src);
5540+ riscv_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest);
5541+
5542+ /* Calculate the value that SRC_REG should have after the last iteration
5543+ of the loop. */
5544+ final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
5545+ 0, 0, OPTAB_WIDEN);
5546+
5547+ /* Emit the start of the loop. */
5548+ label = gen_label_rtx ();
5549+ emit_label (label);
5550+
5551+ /* Emit the loop body. */
5552+ riscv_block_move_straight (dest, src, bytes_per_iter);
5553+
5554+ /* Move on to the next block. */
5555+ riscv_emit_move (src_reg, plus_constant (Pmode, src_reg, bytes_per_iter));
5556+ riscv_emit_move (dest_reg, plus_constant (Pmode, dest_reg, bytes_per_iter));
5557+
5558+ /* Emit the loop condition. */
5559+ test = gen_rtx_NE (VOIDmode, src_reg, final_src);
5560+ if (Pmode == DImode)
5561+ emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label));
5562+ else
5563+ emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
5564+
5565+ /* Mop up any left-over bytes. */
5566+ if (leftover)
5567+ riscv_block_move_straight (dest, src, leftover);
5568+}
5569+
5570+/* Expand a movmemsi instruction, which copies LENGTH bytes from
5571+ memory reference SRC to memory reference DEST. */
5572+
5573+bool
5574+riscv_expand_block_move (rtx dest, rtx src, rtx length)
5575+{
5576+ if (CONST_INT_P (length))
5577+ {
5578+ HOST_WIDE_INT factor, align;
5579+
5580+ align = MIN (MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), BITS_PER_WORD);
5581+ factor = BITS_PER_WORD / align;
5582+
5583+ if (INTVAL (length) <= RISCV_MAX_MOVE_BYTES_STRAIGHT / factor)
5584+ {
5585+ riscv_block_move_straight (dest, src, INTVAL (length));
5586+ return true;
5587+ }
5588+ else if (optimize && align >= BITS_PER_WORD)
5589+ {
5590+ riscv_block_move_loop (dest, src, INTVAL (length),
5591+ RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER / factor);
5592+ return true;
5593+ }
5594+ }
5595+ return false;
5596+}
5597+
5598+/* (Re-)Initialize riscv_lo_relocs and riscv_hi_relocs. */
5599+
5600+static void
5601+riscv_init_relocs (void)
5602+{
5603+ memset (riscv_hi_relocs, '\0', sizeof (riscv_hi_relocs));
5604+ memset (riscv_lo_relocs, '\0', sizeof (riscv_lo_relocs));
5605+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005606+ if (!flag_pic && riscv_cmodel == CM_MEDLOW)
Patrick Georgif0bbc952015-03-07 10:57:25 +01005607+ {
5608+ riscv_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
5609+ riscv_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
5610+ }
5611+
5612+ if (!flag_pic || flag_pie)
5613+ {
5614+ riscv_hi_relocs[SYMBOL_TLS_LE] = "%tprel_hi(";
5615+ riscv_lo_relocs[SYMBOL_TLS_LE] = "%tprel_lo(";
5616+ }
5617+}
5618+
5619+/* Print symbolic operand OP, which is part of a HIGH or LO_SUM
5620+ in context CONTEXT. RELOCS is the array of relocations to use. */
5621+
5622+static void
5623+riscv_print_operand_reloc (FILE *file, rtx op, const char **relocs)
5624+{
5625+ enum riscv_symbol_type symbol_type;
5626+ const char *p;
5627+
5628+ symbol_type = riscv_classify_symbolic_expression (op);
5629+ gcc_assert (relocs[symbol_type]);
5630+
5631+ fputs (relocs[symbol_type], file);
5632+ output_addr_const (file, riscv_strip_unspec_address (op));
5633+ for (p = relocs[symbol_type]; *p != 0; p++)
5634+ if (*p == '(')
5635+ fputc (')', file);
5636+}
5637+
5638+static const char *
5639+riscv_memory_model_suffix (enum memmodel model)
5640+{
5641+ switch (model)
5642+ {
5643+ case MEMMODEL_ACQ_REL:
5644+ case MEMMODEL_SEQ_CST:
5645+ return ".sc";
5646+ case MEMMODEL_ACQUIRE:
5647+ case MEMMODEL_CONSUME:
5648+ return ".aq";
5649+ case MEMMODEL_RELEASE:
5650+ return ".rl";
5651+ case MEMMODEL_RELAXED:
5652+ return "";
5653+ default: gcc_unreachable();
5654+ }
5655+}
5656+
5657+/* Implement TARGET_PRINT_OPERAND. The RISCV-specific operand codes are:
5658+
5659+ 'h' Print the high-part relocation associated with OP, after stripping
5660+ any outermost HIGH.
5661+ 'R' Print the low-part relocation associated with OP.
5662+ 'C' Print the integer branch condition for comparison OP.
5663+ 'A' Print the atomic operation suffix for memory model OP.
5664+ 'z' Print $0 if OP is zero, otherwise print OP normally. */
5665+
5666+static void
5667+riscv_print_operand (FILE *file, rtx op, int letter)
5668+{
5669+ enum rtx_code code;
5670+
5671+ gcc_assert (op);
5672+ code = GET_CODE (op);
5673+
5674+ switch (letter)
5675+ {
5676+ case 'h':
5677+ if (code == HIGH)
5678+ op = XEXP (op, 0);
5679+ riscv_print_operand_reloc (file, op, riscv_hi_relocs);
5680+ break;
5681+
5682+ case 'R':
5683+ riscv_print_operand_reloc (file, op, riscv_lo_relocs);
5684+ break;
5685+
5686+ case 'C':
5687+ /* The RTL names match the instruction names. */
5688+ fputs (GET_RTX_NAME (code), file);
5689+ break;
5690+
5691+ case 'A':
5692+ fputs (riscv_memory_model_suffix ((enum memmodel)INTVAL (op)), file);
5693+ break;
5694+
5695+ default:
5696+ switch (code)
5697+ {
5698+ case REG:
5699+ if (letter && letter != 'z')
5700+ output_operand_lossage ("invalid use of '%%%c'", letter);
5701+ fprintf (file, "%s", reg_names[REGNO (op)]);
5702+ break;
5703+
5704+ case MEM:
5705+ if (letter == 'y')
5706+ fprintf (file, "%s", reg_names[REGNO(XEXP(op, 0))]);
5707+ else if (letter && letter != 'z')
5708+ output_operand_lossage ("invalid use of '%%%c'", letter);
5709+ else
5710+ output_address (XEXP (op, 0));
5711+ break;
5712+
5713+ default:
5714+ if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
5715+ fputs (reg_names[GP_REG_FIRST], file);
5716+ else if (letter && letter != 'z')
5717+ output_operand_lossage ("invalid use of '%%%c'", letter);
5718+ else
5719+ output_addr_const (file, riscv_strip_unspec_address (op));
5720+ break;
5721+ }
5722+ }
5723+}
5724+
5725+/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
5726+
5727+static void
5728+riscv_print_operand_address (FILE *file, rtx x)
5729+{
5730+ struct riscv_address_info addr;
5731+
5732+ if (riscv_classify_address (&addr, x, word_mode, true))
5733+ switch (addr.type)
5734+ {
5735+ case ADDRESS_REG:
5736+ riscv_print_operand (file, addr.offset, 0);
5737+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
5738+ return;
5739+
5740+ case ADDRESS_LO_SUM:
5741+ riscv_print_operand_reloc (file, addr.offset, riscv_lo_relocs);
5742+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
5743+ return;
5744+
5745+ case ADDRESS_CONST_INT:
5746+ output_addr_const (file, x);
5747+ fprintf (file, "(%s)", reg_names[GP_REG_FIRST]);
5748+ return;
5749+
5750+ case ADDRESS_SYMBOLIC:
5751+ output_addr_const (file, riscv_strip_unspec_address (x));
5752+ return;
5753+ }
5754+ gcc_unreachable ();
5755+}
5756+
5757+static bool
5758+riscv_size_ok_for_small_data_p (int size)
5759+{
5760+ return g_switch_value && IN_RANGE (size, 1, g_switch_value);
5761+}
5762+
5763+/* Return true if EXP should be placed in the small data section. */
5764+
5765+static bool
5766+riscv_in_small_data_p (const_tree x)
5767+{
5768+ if (TREE_CODE (x) == STRING_CST || TREE_CODE (x) == FUNCTION_DECL)
5769+ return false;
5770+
5771+ if (TREE_CODE (x) == VAR_DECL && DECL_SECTION_NAME (x))
5772+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005773+ const char *sec = DECL_SECTION_NAME (x);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005774+ return strcmp (sec, ".sdata") == 0 || strcmp (sec, ".sbss") == 0;
5775+ }
5776+
5777+ return riscv_size_ok_for_small_data_p (int_size_in_bytes (TREE_TYPE (x)));
5778+}
5779+
5780+/* Return a section for X, handling small data. */
5781+
5782+static section *
5783+riscv_elf_select_rtx_section (enum machine_mode mode, rtx x,
5784+ unsigned HOST_WIDE_INT align)
5785+{
5786+ section *s = default_elf_select_rtx_section (mode, x, align);
5787+
5788+ if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode)))
5789+ {
5790+ if (strncmp (s->named.name, ".rodata.cst", strlen (".rodata.cst")) == 0)
5791+ {
5792+ /* Rename .rodata.cst* to .srodata.cst*. */
5793+ char name[32];
5794+ sprintf (name, ".s%s", s->named.name + 1);
5795+ return get_section (name, s->named.common.flags, NULL);
5796+ }
5797+
5798+ if (s == data_section)
5799+ return sdata_section;
5800+ }
5801+
5802+ return s;
5803+}
5804+
5805+/* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */
5806+
5807+static void ATTRIBUTE_UNUSED
5808+riscv_output_dwarf_dtprel (FILE *file, int size, rtx x)
5809+{
5810+ switch (size)
5811+ {
5812+ case 4:
5813+ fputs ("\t.dtprelword\t", file);
5814+ break;
5815+
5816+ case 8:
5817+ fputs ("\t.dtpreldword\t", file);
5818+ break;
5819+
5820+ default:
5821+ gcc_unreachable ();
5822+ }
5823+ output_addr_const (file, x);
5824+ fputs ("+0x800", file);
5825+}
5826+
5827+/* Make the last instruction frame-related and note that it performs
5828+ the operation described by FRAME_PATTERN. */
5829+
5830+static void
5831+riscv_set_frame_expr (rtx frame_pattern)
5832+{
5833+ rtx insn;
5834+
5835+ insn = get_last_insn ();
5836+ RTX_FRAME_RELATED_P (insn) = 1;
5837+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
5838+ frame_pattern,
5839+ REG_NOTES (insn));
5840+}
5841+
5842+/* Return a frame-related rtx that stores REG at MEM.
5843+ REG must be a single register. */
5844+
5845+static rtx
5846+riscv_frame_set (rtx mem, rtx reg)
5847+{
5848+ rtx set;
5849+
5850+ set = gen_rtx_SET (VOIDmode, mem, reg);
5851+ RTX_FRAME_RELATED_P (set) = 1;
5852+
5853+ return set;
5854+}
5855+
5856+/* Return true if the current function must save register REGNO. */
5857+
5858+static bool
5859+riscv_save_reg_p (unsigned int regno)
5860+{
5861+ bool call_saved = !global_regs[regno] && !call_really_used_regs[regno];
5862+ bool might_clobber = crtl->saves_all_registers
5863+ || df_regs_ever_live_p (regno)
5864+ || (regno == HARD_FRAME_POINTER_REGNUM
5865+ && frame_pointer_needed);
5866+
5867+ return (call_saved && might_clobber)
5868+ || (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return);
5869+}
5870+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005871+/* Determine whether to call GPR save/restore routines. */
5872+static bool
5873+riscv_use_save_libcall (const struct riscv_frame_info *frame)
5874+{
5875+ if (!TARGET_SAVE_RESTORE || crtl->calls_eh_return || frame_pointer_needed)
5876+ return false;
5877+
5878+ return frame->save_libcall_adjustment != 0;
5879+}
5880+
5881+/* Determine which GPR save/restore routine to call. */
5882+
5883+static unsigned
5884+riscv_save_libcall_count (unsigned mask)
5885+{
5886+ for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--)
5887+ if (BITSET_P (mask, n))
5888+ return CALLEE_SAVED_REG_NUMBER (n) + 1;
5889+ abort ();
5890+}
5891+
Patrick Georgif0bbc952015-03-07 10:57:25 +01005892+/* Populate the current function's riscv_frame_info structure.
5893+
5894+ RISC-V stack frames grown downward. High addresses are at the top.
5895+
5896+ +-------------------------------+
5897+ | |
5898+ | incoming stack arguments |
5899+ | |
5900+ +-------------------------------+ <-- incoming stack pointer
5901+ | |
5902+ | callee-allocated save area |
5903+ | for arguments that are |
5904+ | split between registers and |
5905+ | the stack |
5906+ | |
5907+ +-------------------------------+ <-- arg_pointer_rtx
5908+ | |
5909+ | callee-allocated save area |
5910+ | for register varargs |
5911+ | |
5912+ +-------------------------------+ <-- hard_frame_pointer_rtx;
5913+ | | stack_pointer_rtx + gp_sp_offset
5914+ | GPR save area | + UNITS_PER_WORD
5915+ | |
5916+ +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
5917+ | | + UNITS_PER_HWVALUE
5918+ | FPR save area |
5919+ | |
5920+ +-------------------------------+ <-- frame_pointer_rtx (virtual)
5921+ | |
5922+ | local variables |
5923+ | |
5924+ P +-------------------------------+
5925+ | |
5926+ | outgoing stack arguments |
5927+ | |
5928+ +-------------------------------+ <-- stack_pointer_rtx
5929+
5930+ Dynamic stack allocations such as alloca insert data at point P.
5931+ They decrease stack_pointer_rtx but leave frame_pointer_rtx and
5932+ hard_frame_pointer_rtx unchanged. */
5933+
5934+static void
5935+riscv_compute_frame_info (void)
5936+{
5937+ struct riscv_frame_info *frame;
5938+ HOST_WIDE_INT offset;
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005939+ unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005940+
5941+ frame = &cfun->machine->frame;
5942+ memset (frame, 0, sizeof (*frame));
5943+
5944+ /* Find out which GPRs we need to save. */
5945+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
5946+ if (riscv_save_reg_p (regno))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005947+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005948+
5949+ /* If this function calls eh_return, we must also save and restore the
5950+ EH data registers. */
5951+ if (crtl->calls_eh_return)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005952+ for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
5953+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005954+
5955+ /* Find out which FPRs we need to save. This loop must iterate over
5956+ the same space as its companion in riscv_for_each_saved_gpr_and_fpr. */
5957+ if (TARGET_HARD_FLOAT)
5958+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
5959+ if (riscv_save_reg_p (regno))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005960+ frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005961+
5962+ /* At the bottom of the frame are any outgoing stack arguments. */
5963+ offset = crtl->outgoing_args_size;
5964+ /* Next are local stack variables. */
5965+ offset += RISCV_STACK_ALIGN (get_frame_size ());
5966+ /* The virtual frame pointer points above the local variables. */
5967+ frame->frame_pointer_offset = offset;
5968+ /* Next are the callee-saved FPRs. */
5969+ if (frame->fmask)
5970+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005971+ offset += RISCV_STACK_ALIGN (num_f_saved * UNITS_PER_FPREG);
Patrick Georgif0bbc952015-03-07 10:57:25 +01005972+ frame->fp_sp_offset = offset - UNITS_PER_HWFPVALUE;
5973+ }
5974+ /* Next are the callee-saved GPRs. */
5975+ if (frame->mask)
5976+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005977+ unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD);
5978+ unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask);
5979+
5980+ /* Only use save/restore routines if they don't alter the stack size. */
5981+ if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size)
5982+ frame->save_libcall_adjustment = x_save_size;
5983+
5984+ offset += x_save_size;
Patrick Georgif0bbc952015-03-07 10:57:25 +01005985+ frame->gp_sp_offset = offset - UNITS_PER_WORD;
5986+ }
5987+ /* The hard frame pointer points above the callee-saved GPRs. */
5988+ frame->hard_frame_pointer_offset = offset;
5989+ /* Above the hard frame pointer is the callee-allocated varags save area. */
5990+ offset += RISCV_STACK_ALIGN (cfun->machine->varargs_size);
5991+ frame->arg_pointer_offset = offset;
5992+ /* Next is the callee-allocated area for pretend stack arguments. */
5993+ offset += crtl->args.pretend_args_size;
5994+ frame->total_size = offset;
5995+ /* Next points the incoming stack pointer and any incoming arguments. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02005996+
5997+ /* Only use save/restore routines when the GPRs are atop the frame. */
5998+ if (frame->hard_frame_pointer_offset != frame->total_size)
5999+ frame->save_libcall_adjustment = 0;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006000+}
6001+
6002+/* Make sure that we're not trying to eliminate to the wrong hard frame
6003+ pointer. */
6004+
6005+static bool
6006+riscv_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
6007+{
6008+ return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM);
6009+}
6010+
6011+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer
6012+ or argument pointer. TO is either the stack pointer or hard frame
6013+ pointer. */
6014+
6015+HOST_WIDE_INT
6016+riscv_initial_elimination_offset (int from, int to)
6017+{
6018+ HOST_WIDE_INT src, dest;
6019+
6020+ riscv_compute_frame_info ();
6021+
6022+ if (to == HARD_FRAME_POINTER_REGNUM)
6023+ dest = cfun->machine->frame.hard_frame_pointer_offset;
6024+ else if (to == STACK_POINTER_REGNUM)
6025+ dest = 0; /* this is the base of all offsets */
6026+ else
6027+ gcc_unreachable ();
6028+
6029+ if (from == FRAME_POINTER_REGNUM)
6030+ src = cfun->machine->frame.frame_pointer_offset;
6031+ else if (from == ARG_POINTER_REGNUM)
6032+ src = cfun->machine->frame.arg_pointer_offset;
6033+ else
6034+ gcc_unreachable ();
6035+
6036+ return src - dest;
6037+}
6038+
6039+/* Implement RETURN_ADDR_RTX. We do not support moving back to a
6040+ previous frame. */
6041+
6042+rtx
6043+riscv_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
6044+{
6045+ if (count != 0)
6046+ return const0_rtx;
6047+
6048+ return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
6049+}
6050+
6051+/* Emit code to change the current function's return address to
6052+ ADDRESS. SCRATCH is available as a scratch register, if needed.
6053+ ADDRESS and SCRATCH are both word-mode GPRs. */
6054+
6055+void
6056+riscv_set_return_address (rtx address, rtx scratch)
6057+{
6058+ rtx slot_address;
6059+
6060+ gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM));
6061+ slot_address = riscv_add_offset (scratch, stack_pointer_rtx,
6062+ cfun->machine->frame.gp_sp_offset);
6063+ riscv_emit_move (gen_frame_mem (GET_MODE (address), slot_address), address);
6064+}
6065+
6066+/* A function to save or store a register. The first argument is the
6067+ register and the second is the stack slot. */
6068+typedef void (*riscv_save_restore_fn) (rtx, rtx);
6069+
6070+/* Use FN to save or restore register REGNO. MODE is the register's
6071+ mode and OFFSET is the offset of its save slot from the current
6072+ stack pointer. */
6073+
6074+static void
6075+riscv_save_restore_reg (enum machine_mode mode, int regno,
6076+ HOST_WIDE_INT offset, riscv_save_restore_fn fn)
6077+{
6078+ rtx mem;
6079+
6080+ mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset));
6081+ fn (gen_rtx_REG (mode, regno), mem);
6082+}
6083+
6084+/* Call FN for each register that is saved by the current function.
6085+ SP_OFFSET is the offset of the current stack pointer from the start
6086+ of the frame. */
6087+
6088+static void
6089+riscv_for_each_saved_gpr_and_fpr (HOST_WIDE_INT sp_offset,
6090+ riscv_save_restore_fn fn)
6091+{
6092+ HOST_WIDE_INT offset;
6093+ int regno;
6094+
6095+ /* Save the link register and s-registers. */
6096+ offset = cfun->machine->frame.gp_sp_offset - sp_offset;
6097+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST-1; regno++)
6098+ if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
6099+ {
6100+ riscv_save_restore_reg (word_mode, regno, offset, fn);
6101+ offset -= UNITS_PER_WORD;
6102+ }
6103+
6104+ /* This loop must iterate over the same space as its companion in
6105+ riscv_compute_frame_info. */
6106+ offset = cfun->machine->frame.fp_sp_offset - sp_offset;
6107+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
6108+ if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
6109+ {
6110+ riscv_save_restore_reg (DFmode, regno, offset, fn);
6111+ offset -= GET_MODE_SIZE (DFmode);
6112+ }
6113+}
6114+
6115+/* Emit a move from SRC to DEST, given that one of them is a register
6116+ save slot and that the other is a register. TEMP is a temporary
6117+ GPR of the same mode that is available if need be. */
6118+
6119+static void
6120+riscv_emit_save_slot_move (rtx dest, rtx src, rtx temp)
6121+{
6122+ unsigned int regno;
6123+ rtx mem;
6124+ enum reg_class rclass;
6125+
6126+ if (REG_P (src))
6127+ {
6128+ regno = REGNO (src);
6129+ mem = dest;
6130+ }
6131+ else
6132+ {
6133+ regno = REGNO (dest);
6134+ mem = src;
6135+ }
6136+
6137+ rclass = riscv_secondary_reload_class (REGNO_REG_CLASS (regno),
6138+ GET_MODE (mem), mem, mem == src);
6139+
6140+ if (rclass == NO_REGS)
6141+ riscv_emit_move (dest, src);
6142+ else
6143+ {
6144+ gcc_assert (!reg_overlap_mentioned_p (dest, temp));
6145+ riscv_emit_move (temp, src);
6146+ riscv_emit_move (dest, temp);
6147+ }
6148+ if (MEM_P (dest))
6149+ riscv_set_frame_expr (riscv_frame_set (dest, src));
6150+}
6151+
6152+/* Save register REG to MEM. Make the instruction frame-related. */
6153+
6154+static void
6155+riscv_save_reg (rtx reg, rtx mem)
6156+{
6157+ riscv_emit_save_slot_move (mem, reg, RISCV_PROLOGUE_TEMP (GET_MODE (reg)));
6158+}
6159+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006160+/* Return the code to invoke the GPR save routine. */
6161+
6162+const char *
6163+riscv_output_gpr_save (unsigned mask)
6164+{
6165+ static char buf[GP_REG_NUM * 32];
6166+ size_t len = 0;
6167+ unsigned n = riscv_save_libcall_count (mask), i;
6168+ unsigned frame_size = RISCV_STACK_ALIGN ((n + 1) * UNITS_PER_WORD);
6169+
6170+ len += sprintf (buf + len, "call\tt0,__riscv_save_%u", n);
6171+
6172+#ifdef DWARF2_UNWIND_INFO
6173+ /* Describe the effect of the call to __riscv_save_X. */
6174+ if (dwarf2out_do_cfi_asm ())
6175+ {
6176+ len += sprintf (buf + len, "\n\t.cfi_def_cfa_offset %u", frame_size);
6177+
6178+ for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
6179+ if (BITSET_P (cfun->machine->frame.mask, i))
6180+ len += sprintf (buf + len, "\n\t.cfi_offset %u,%d", i,
6181+ (CALLEE_SAVED_REG_NUMBER (i) + 2) * -UNITS_PER_WORD);
6182+ }
6183+#endif
6184+
6185+ return buf;
6186+}
Patrick Georgif0bbc952015-03-07 10:57:25 +01006187+
6188+/* Expand the "prologue" pattern. */
6189+
6190+void
6191+riscv_expand_prologue (void)
6192+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006193+ struct riscv_frame_info *frame = &cfun->machine->frame;
6194+ HOST_WIDE_INT size = frame->total_size;
6195+ unsigned mask = frame->mask;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006196+ rtx insn;
6197+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006198+ if (flag_stack_usage_info)
6199+ current_function_static_stack_size = size;
6200+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006201+ /* When optimizing for size, call a subroutine to save the registers. */
6202+ if (riscv_use_save_libcall (frame))
6203+ {
6204+ frame->mask = 0; /* Temporarily fib that we need not save GPRs. */
6205+ size -= frame->save_libcall_adjustment;
6206+ emit_insn (gen_gpr_save (GEN_INT (mask)));
6207+ }
6208+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006209+ /* Save the registers. Allocate up to RISCV_MAX_FIRST_STACK_STEP
6210+ bytes beforehand; this is enough to cover the register save area
6211+ without going out of range. */
6212+ if ((frame->mask | frame->fmask) != 0)
6213+ {
6214+ HOST_WIDE_INT step1;
6215+
6216+ step1 = MIN (size, RISCV_MAX_FIRST_STACK_STEP);
6217+ insn = gen_add3_insn (stack_pointer_rtx,
6218+ stack_pointer_rtx,
6219+ GEN_INT (-step1));
6220+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
6221+ size -= step1;
6222+ riscv_for_each_saved_gpr_and_fpr (size, riscv_save_reg);
6223+ }
6224+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006225+ frame->mask = mask; /* Undo the above fib. */
6226+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006227+ /* Set up the frame pointer, if we're using one. */
6228+ if (frame_pointer_needed)
6229+ {
6230+ insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
6231+ GEN_INT (frame->hard_frame_pointer_offset - size));
6232+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
6233+ }
6234+
6235+ /* Allocate the rest of the frame. */
6236+ if (size > 0)
6237+ {
6238+ if (SMALL_OPERAND (-size))
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006239+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
6240+ GEN_INT (-size)));
Patrick Georgif0bbc952015-03-07 10:57:25 +01006241+ else
6242+ {
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006243+ riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), GEN_INT (-size));
6244+ emit_insn (gen_add3_insn (stack_pointer_rtx,
Patrick Georgif0bbc952015-03-07 10:57:25 +01006245+ stack_pointer_rtx,
6246+ RISCV_PROLOGUE_TEMP (Pmode)));
Patrick Georgif0bbc952015-03-07 10:57:25 +01006247+ }
6248+ }
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006249+
6250+ if (frame->total_size > 0)
6251+ {
6252+ /* Describe the effect of the instructions that adjusted sp. */
6253+ insn = plus_constant (Pmode, stack_pointer_rtx, -frame->total_size);
6254+ insn = gen_rtx_SET (VOIDmode, stack_pointer_rtx, insn);
6255+ riscv_set_frame_expr (insn);
6256+ }
Patrick Georgif0bbc952015-03-07 10:57:25 +01006257+}
6258+
6259+/* Emit instructions to restore register REG from slot MEM. */
6260+
6261+static void
6262+riscv_restore_reg (rtx reg, rtx mem)
6263+{
6264+ riscv_emit_save_slot_move (reg, mem, RISCV_EPILOGUE_TEMP (GET_MODE (reg)));
6265+}
6266+
6267+/* Expand an "epilogue" or "sibcall_epilogue" pattern; SIBCALL_P
6268+ says which. */
6269+
6270+void
6271+riscv_expand_epilogue (bool sibcall_p)
6272+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006273+ /* Split the frame into two. STEP1 is the amount of stack we should
6274+ deallocate before restoring the registers. STEP2 is the amount we
6275+ should deallocate afterwards.
6276+
6277+ Start off by assuming that no registers need to be restored. */
6278+ struct riscv_frame_info *frame = &cfun->machine->frame;
6279+ unsigned mask = frame->mask;
6280+ HOST_WIDE_INT step1 = frame->total_size;
6281+ HOST_WIDE_INT step2 = 0;
6282+ bool use_restore_libcall = !sibcall_p && riscv_use_save_libcall (frame);
6283+ rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
Patrick Georgif0bbc952015-03-07 10:57:25 +01006284+
6285+ if (!sibcall_p && riscv_can_use_return_insn ())
6286+ {
6287+ emit_jump_insn (gen_return ());
6288+ return;
6289+ }
6290+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006291+ /* Move past any dynamic stack allocations. */
Patrick Georgif0bbc952015-03-07 10:57:25 +01006292+ if (cfun->calls_alloca)
6293+ {
6294+ rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset);
6295+ if (!SMALL_INT (adjust))
6296+ {
6297+ riscv_emit_move (RISCV_EPILOGUE_TEMP (Pmode), adjust);
6298+ adjust = RISCV_EPILOGUE_TEMP (Pmode);
6299+ }
6300+
6301+ emit_insn (gen_add3_insn (stack_pointer_rtx, hard_frame_pointer_rtx, adjust));
6302+ }
6303+
6304+ /* If we need to restore registers, deallocate as much stack as
6305+ possible in the second step without going out of range. */
6306+ if ((frame->mask | frame->fmask) != 0)
6307+ {
6308+ step2 = MIN (step1, RISCV_MAX_FIRST_STACK_STEP);
6309+ step1 -= step2;
6310+ }
6311+
6312+ /* Set TARGET to BASE + STEP1. */
6313+ if (step1 > 0)
6314+ {
6315+ /* Get an rtx for STEP1 that we can add to BASE. */
6316+ rtx adjust = GEN_INT (step1);
6317+ if (!SMALL_OPERAND (step1))
6318+ {
6319+ riscv_emit_move (RISCV_EPILOGUE_TEMP (Pmode), adjust);
6320+ adjust = RISCV_EPILOGUE_TEMP (Pmode);
6321+ }
6322+
6323+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, adjust));
6324+ }
6325+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006326+ if (use_restore_libcall)
6327+ frame->mask = 0; /* Temporarily fib that we need not save GPRs. */
6328+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006329+ /* Restore the registers. */
6330+ riscv_for_each_saved_gpr_and_fpr (frame->total_size - step2,
6331+ riscv_restore_reg);
6332+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006333+ if (use_restore_libcall)
6334+ {
6335+ frame->mask = mask; /* Undo the above fib. */
6336+ gcc_assert (step2 >= frame->save_libcall_adjustment);
6337+ step2 -= frame->save_libcall_adjustment;
6338+ }
6339+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006340+ /* Deallocate the final bit of the frame. */
6341+ if (step2 > 0)
6342+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
6343+ GEN_INT (step2)));
6344+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006345+ if (use_restore_libcall)
6346+ {
6347+ emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask))));
6348+ emit_jump_insn (gen_gpr_restore_return (ra));
6349+ return;
6350+ }
6351+
Patrick Georgif0bbc952015-03-07 10:57:25 +01006352+ /* Add in the __builtin_eh_return stack adjustment. */
6353+ if (crtl->calls_eh_return)
6354+ emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
6355+ EH_RETURN_STACKADJ_RTX));
6356+
6357+ if (!sibcall_p)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006358+ emit_jump_insn (gen_simple_return_internal (ra));
Patrick Georgif0bbc952015-03-07 10:57:25 +01006359+}
6360+
6361+/* Return nonzero if this function is known to have a null epilogue.
6362+ This allows the optimizer to omit jumps to jumps if no stack
6363+ was created. */
6364+
6365+bool
6366+riscv_can_use_return_insn (void)
6367+{
6368+ return reload_completed && cfun->machine->frame.total_size == 0;
6369+}
6370+
6371+/* Return true if register REGNO can store a value of mode MODE.
6372+ The result of this function is cached in riscv_hard_regno_mode_ok. */
6373+
6374+static bool
6375+riscv_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
6376+{
6377+ unsigned int size = GET_MODE_SIZE (mode);
6378+ enum mode_class mclass = GET_MODE_CLASS (mode);
6379+
6380+ /* This is hella bogus but ira_build segfaults on RV32 without it. */
6381+ if (VECTOR_MODE_P (mode))
6382+ return true;
6383+
6384+ if (GP_REG_P (regno))
6385+ {
6386+ if (size <= UNITS_PER_WORD)
6387+ return true;
6388+
6389+ /* Double-word values must be even-register-aligned. */
6390+ if (size <= 2 * UNITS_PER_WORD)
6391+ return regno % 2 == 0;
6392+ }
6393+
6394+ if (FP_REG_P (regno))
6395+ {
6396+ if (mclass == MODE_FLOAT
6397+ || mclass == MODE_COMPLEX_FLOAT
6398+ || mclass == MODE_VECTOR_FLOAT)
6399+ return size <= UNITS_PER_FPVALUE;
6400+ }
6401+
6402+ return false;
6403+}
6404+
6405+/* Implement HARD_REGNO_NREGS. */
6406+
6407+unsigned int
6408+riscv_hard_regno_nregs (int regno, enum machine_mode mode)
6409+{
6410+ if (FP_REG_P (regno))
6411+ return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
6412+
6413+ /* All other registers are word-sized. */
6414+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
6415+}
6416+
6417+/* Implement CLASS_MAX_NREGS, taking the maximum of the cases
6418+ in riscv_hard_regno_nregs. */
6419+
6420+int
6421+riscv_class_max_nregs (enum reg_class rclass, enum machine_mode mode)
6422+{
6423+ int size;
6424+ HARD_REG_SET left;
6425+
6426+ size = 0x8000;
6427+ COPY_HARD_REG_SET (left, reg_class_contents[(int) rclass]);
6428+ if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS]))
6429+ {
6430+ size = MIN (size, UNITS_PER_FPREG);
6431+ AND_COMPL_HARD_REG_SET (left, reg_class_contents[(int) FP_REGS]);
6432+ }
6433+ if (!hard_reg_set_empty_p (left))
6434+ size = MIN (size, UNITS_PER_WORD);
6435+ return (GET_MODE_SIZE (mode) + size - 1) / size;
6436+}
6437+
6438+/* Implement TARGET_PREFERRED_RELOAD_CLASS. */
6439+
6440+static reg_class_t
6441+riscv_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass)
6442+{
6443+ return reg_class_subset_p (FP_REGS, rclass) ? FP_REGS :
6444+ reg_class_subset_p (GR_REGS, rclass) ? GR_REGS :
6445+ rclass;
6446+}
6447+
6448+/* RCLASS is a class involved in a REGISTER_MOVE_COST calculation.
6449+ Return a "canonical" class to represent it in later calculations. */
6450+
6451+static reg_class_t
6452+riscv_canonicalize_move_class (reg_class_t rclass)
6453+{
6454+ if (reg_class_subset_p (rclass, GENERAL_REGS))
6455+ rclass = GENERAL_REGS;
6456+
6457+ return rclass;
6458+}
6459+
6460+/* Implement TARGET_REGISTER_MOVE_COST. Return 0 for classes that are the
6461+ maximum of the move costs for subclasses; regclass will work out
6462+ the maximum for us. */
6463+
6464+static int
6465+riscv_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
6466+ reg_class_t from, reg_class_t to)
6467+{
6468+ from = riscv_canonicalize_move_class (from);
6469+ to = riscv_canonicalize_move_class (to);
6470+
6471+ if ((from == GENERAL_REGS && to == GENERAL_REGS)
6472+ || (from == GENERAL_REGS && to == FP_REGS)
6473+ || (from == FP_REGS && to == FP_REGS))
6474+ return COSTS_N_INSNS (1);
6475+
6476+ if (from == FP_REGS && to == GENERAL_REGS)
6477+ return tune_info->fp_to_int_cost;
6478+
6479+ return 0;
6480+}
6481+
6482+/* Implement TARGET_MEMORY_MOVE_COST. */
6483+
6484+static int
6485+riscv_memory_move_cost (enum machine_mode mode, reg_class_t rclass, bool in)
6486+{
6487+ return (tune_info->memory_cost
6488+ + memory_move_secondary_cost (mode, rclass, in));
6489+}
6490+
6491+/* Return the register class required for a secondary register when
6492+ copying between one of the registers in RCLASS and value X, which
6493+ has mode MODE. X is the source of the move if IN_P, otherwise it
6494+ is the destination. Return NO_REGS if no secondary register is
6495+ needed. */
6496+
6497+enum reg_class
6498+riscv_secondary_reload_class (enum reg_class rclass,
6499+ enum machine_mode mode, rtx x,
6500+ bool in_p ATTRIBUTE_UNUSED)
6501+{
6502+ int regno;
6503+
6504+ regno = true_regnum (x);
6505+
6506+ if (reg_class_subset_p (rclass, FP_REGS))
6507+ {
6508+ if (MEM_P (x) && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8))
6509+ /* We can use flw/fld/fsw/fsd. */
6510+ return NO_REGS;
6511+
6512+ if (GP_REG_P (regno) || x == CONST0_RTX (mode))
6513+ /* We can use fmv or go through memory when mode > Pmode. */
6514+ return NO_REGS;
6515+
6516+ if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x))
6517+ /* We can force the constant to memory and use flw/fld. */
6518+ return NO_REGS;
6519+
6520+ if (FP_REG_P (regno))
6521+ /* We can use fmv.fmt. */
6522+ return NO_REGS;
6523+
6524+ /* Otherwise, we need to reload through an integer register. */
6525+ return GR_REGS;
6526+ }
6527+ if (FP_REG_P (regno))
6528+ return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS;
6529+
6530+ return NO_REGS;
6531+}
6532+
6533+/* Implement TARGET_MODE_REP_EXTENDED. */
6534+
6535+static int
6536+riscv_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep)
6537+{
6538+ /* On 64-bit targets, SImode register values are sign-extended to DImode. */
6539+ if (TARGET_64BIT && mode == SImode && mode_rep == DImode)
6540+ return SIGN_EXTEND;
6541+
6542+ return UNKNOWN;
6543+}
6544+
6545+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
6546+
6547+static bool
6548+riscv_scalar_mode_supported_p (enum machine_mode mode)
6549+{
6550+ if (ALL_FIXED_POINT_MODE_P (mode)
6551+ && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
6552+ return true;
6553+
6554+ return default_scalar_mode_supported_p (mode);
6555+}
6556+
6557+/* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output
6558+ dependencies have no cost. */
6559+
6560+static int
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006561+riscv_adjust_cost (rtx_insn *insn ATTRIBUTE_UNUSED, rtx link,
6562+ rtx_insn *dep ATTRIBUTE_UNUSED, int cost)
Patrick Georgif0bbc952015-03-07 10:57:25 +01006563+{
6564+ if (REG_NOTE_KIND (link) != 0)
6565+ return 0;
6566+ return cost;
6567+}
6568+
6569+/* Return the number of instructions that can be issued per cycle. */
6570+
6571+static int
6572+riscv_issue_rate (void)
6573+{
6574+ return tune_info->issue_rate;
6575+}
6576+
6577+/* This structure describes a single built-in function. */
6578+struct riscv_builtin_description {
6579+ /* The code of the main .md file instruction. See riscv_builtin_type
6580+ for more information. */
6581+ enum insn_code icode;
6582+
6583+ /* The name of the built-in function. */
6584+ const char *name;
6585+
6586+ /* Specifies how the function should be expanded. */
6587+ enum riscv_builtin_type builtin_type;
6588+
6589+ /* The function's prototype. */
6590+ enum riscv_function_type function_type;
6591+
6592+ /* Whether the function is available. */
6593+ unsigned int (*avail) (void);
6594+};
6595+
6596+static unsigned int
6597+riscv_builtin_avail_riscv (void)
6598+{
6599+ return 1;
6600+}
6601+
6602+/* Construct a riscv_builtin_description from the given arguments.
6603+
6604+ INSN is the name of the associated instruction pattern, without the
6605+ leading CODE_FOR_riscv_.
6606+
6607+ CODE is the floating-point condition code associated with the
6608+ function. It can be 'f' if the field is not applicable.
6609+
6610+ NAME is the name of the function itself, without the leading
6611+ "__builtin_riscv_".
6612+
6613+ BUILTIN_TYPE and FUNCTION_TYPE are riscv_builtin_description fields.
6614+
6615+ AVAIL is the name of the availability predicate, without the leading
6616+ riscv_builtin_avail_. */
6617+#define RISCV_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \
6618+ { CODE_FOR_ ## INSN, "__builtin_riscv_" NAME, \
6619+ BUILTIN_TYPE, FUNCTION_TYPE, riscv_builtin_avail_ ## AVAIL }
6620+
6621+/* Define __builtin_riscv_<INSN>, which is a RISCV_BUILTIN_DIRECT function
6622+ mapped to instruction CODE_FOR_<INSN>, FUNCTION_TYPE and AVAIL
6623+ are as for RISCV_BUILTIN. */
6624+#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
6625+ RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT, FUNCTION_TYPE, AVAIL)
6626+
6627+/* Define __builtin_riscv_<INSN>, which is a RISCV_BUILTIN_DIRECT_NO_TARGET
6628+ function mapped to instruction CODE_FOR_<INSN>, FUNCTION_TYPE
6629+ and AVAIL are as for RISCV_BUILTIN. */
6630+#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
6631+ RISCV_BUILTIN (INSN, #INSN, RISCV_BUILTIN_DIRECT_NO_TARGET, \
6632+ FUNCTION_TYPE, AVAIL)
6633+
6634+static const struct riscv_builtin_description riscv_builtins[] = {
6635+ DIRECT_NO_TARGET_BUILTIN (nop, RISCV_VOID_FTYPE_VOID, riscv),
6636+};
6637+
6638+/* Index I is the function declaration for riscv_builtins[I], or null if the
6639+ function isn't defined on this target. */
6640+static GTY(()) tree riscv_builtin_decls[ARRAY_SIZE (riscv_builtins)];
6641+
6642+
6643+/* Source-level argument types. */
6644+#define RISCV_ATYPE_VOID void_type_node
6645+#define RISCV_ATYPE_INT integer_type_node
6646+#define RISCV_ATYPE_POINTER ptr_type_node
6647+#define RISCV_ATYPE_CPOINTER const_ptr_type_node
6648+
6649+/* Standard mode-based argument types. */
6650+#define RISCV_ATYPE_UQI unsigned_intQI_type_node
6651+#define RISCV_ATYPE_SI intSI_type_node
6652+#define RISCV_ATYPE_USI unsigned_intSI_type_node
6653+#define RISCV_ATYPE_DI intDI_type_node
6654+#define RISCV_ATYPE_UDI unsigned_intDI_type_node
6655+#define RISCV_ATYPE_SF float_type_node
6656+#define RISCV_ATYPE_DF double_type_node
6657+
6658+/* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
6659+ their associated RISCV_ATYPEs. */
6660+#define RISCV_FTYPE_ATYPES1(A, B) \
6661+ RISCV_ATYPE_##A, RISCV_ATYPE_##B
6662+
6663+#define RISCV_FTYPE_ATYPES2(A, B, C) \
6664+ RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C
6665+
6666+#define RISCV_FTYPE_ATYPES3(A, B, C, D) \
6667+ RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C, RISCV_ATYPE_##D
6668+
6669+#define RISCV_FTYPE_ATYPES4(A, B, C, D, E) \
6670+ RISCV_ATYPE_##A, RISCV_ATYPE_##B, RISCV_ATYPE_##C, RISCV_ATYPE_##D, \
6671+ RISCV_ATYPE_##E
6672+
6673+/* Return the function type associated with function prototype TYPE. */
6674+
6675+static tree
6676+riscv_build_function_type (enum riscv_function_type type)
6677+{
6678+ static tree types[(int) RISCV_MAX_FTYPE_MAX];
6679+
6680+ if (types[(int) type] == NULL_TREE)
6681+ switch (type)
6682+ {
6683+#define DEF_RISCV_FTYPE(NUM, ARGS) \
6684+ case RISCV_FTYPE_NAME##NUM ARGS: \
6685+ types[(int) type] \
6686+ = build_function_type_list (RISCV_FTYPE_ATYPES##NUM ARGS, \
6687+ NULL_TREE); \
6688+ break;
6689+#include "config/riscv/riscv-ftypes.def"
6690+#undef DEF_RISCV_FTYPE
6691+ default:
6692+ gcc_unreachable ();
6693+ }
6694+
6695+ return types[(int) type];
6696+}
6697+
6698+/* Implement TARGET_INIT_BUILTINS. */
6699+
6700+static void
6701+riscv_init_builtins (void)
6702+{
6703+ const struct riscv_builtin_description *d;
6704+ unsigned int i;
6705+
6706+ /* Iterate through all of the bdesc arrays, initializing all of the
6707+ builtin functions. */
6708+ for (i = 0; i < ARRAY_SIZE (riscv_builtins); i++)
6709+ {
6710+ d = &riscv_builtins[i];
6711+ if (d->avail ())
6712+ riscv_builtin_decls[i]
6713+ = add_builtin_function (d->name,
6714+ riscv_build_function_type (d->function_type),
6715+ i, BUILT_IN_MD, NULL, NULL);
6716+ }
6717+}
6718+
6719+/* Implement TARGET_BUILTIN_DECL. */
6720+
6721+static tree
6722+riscv_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
6723+{
6724+ if (code >= ARRAY_SIZE (riscv_builtins))
6725+ return error_mark_node;
6726+ return riscv_builtin_decls[code];
6727+}
6728+
6729+/* Take argument ARGNO from EXP's argument list and convert it into a
6730+ form suitable for input operand OPNO of instruction ICODE. Return the
6731+ value. */
6732+
6733+static rtx
6734+riscv_prepare_builtin_arg (enum insn_code icode,
6735+ unsigned int opno, tree exp, unsigned int argno)
6736+{
6737+ tree arg;
6738+ rtx value;
6739+ enum machine_mode mode;
6740+
6741+ arg = CALL_EXPR_ARG (exp, argno);
6742+ value = expand_normal (arg);
6743+ mode = insn_data[icode].operand[opno].mode;
6744+ if (!insn_data[icode].operand[opno].predicate (value, mode))
6745+ {
6746+ /* We need to get the mode from ARG for two reasons:
6747+
6748+ - to cope with address operands, where MODE is the mode of the
6749+ memory, rather than of VALUE itself.
6750+
6751+ - to cope with special predicates like pmode_register_operand,
6752+ where MODE is VOIDmode. */
6753+ value = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (arg)), value);
6754+
6755+ /* Check the predicate again. */
6756+ if (!insn_data[icode].operand[opno].predicate (value, mode))
6757+ {
6758+ error ("invalid argument to built-in function");
6759+ return const0_rtx;
6760+ }
6761+ }
6762+
6763+ return value;
6764+}
6765+
6766+/* Return an rtx suitable for output operand OP of instruction ICODE.
6767+ If TARGET is non-null, try to use it where possible. */
6768+
6769+static rtx
6770+riscv_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
6771+{
6772+ enum machine_mode mode;
6773+
6774+ mode = insn_data[icode].operand[op].mode;
6775+ if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
6776+ target = gen_reg_rtx (mode);
6777+
6778+ return target;
6779+}
6780+
6781+/* Expand a RISCV_BUILTIN_DIRECT or RISCV_BUILTIN_DIRECT_NO_TARGET function;
6782+ HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function
6783+ and ICODE is the code of the associated .md pattern. TARGET, if nonnull,
6784+ suggests a good place to put the result. */
6785+
6786+static rtx
6787+riscv_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
6788+ bool has_target_p)
6789+{
6790+ rtx ops[MAX_RECOG_OPERANDS];
6791+ int opno, argno;
6792+
6793+ /* Map any target to operand 0. */
6794+ opno = 0;
6795+ if (has_target_p)
6796+ {
6797+ target = riscv_prepare_builtin_target (icode, opno, target);
6798+ ops[opno] = target;
6799+ opno++;
6800+ }
6801+
6802+ /* Map the arguments to the other operands. The n_operands value
6803+ for an expander includes match_dups and match_scratches as well as
6804+ match_operands, so n_operands is only an upper bound on the number
6805+ of arguments to the expander function. */
6806+ gcc_assert (opno + call_expr_nargs (exp) <= insn_data[icode].n_operands);
6807+ for (argno = 0; argno < call_expr_nargs (exp); argno++, opno++)
6808+ ops[opno] = riscv_prepare_builtin_arg (icode, opno, exp, argno);
6809+
6810+ switch (opno)
6811+ {
6812+ case 2:
6813+ emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
6814+ break;
6815+
6816+ case 3:
6817+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
6818+ break;
6819+
6820+ case 4:
6821+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
6822+ break;
6823+
6824+ default:
6825+ gcc_unreachable ();
6826+ }
6827+ return target;
6828+}
6829+
6830+/* Implement TARGET_EXPAND_BUILTIN. */
6831+
6832+static rtx
6833+riscv_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
6834+ enum machine_mode mode ATTRIBUTE_UNUSED,
6835+ int ignore ATTRIBUTE_UNUSED)
6836+{
6837+ tree fndecl;
6838+ unsigned int fcode, avail;
6839+ const struct riscv_builtin_description *d;
6840+
6841+ fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6842+ fcode = DECL_FUNCTION_CODE (fndecl);
6843+ gcc_assert (fcode < ARRAY_SIZE (riscv_builtins));
6844+ d = &riscv_builtins[fcode];
6845+ avail = d->avail ();
6846+ gcc_assert (avail != 0);
6847+ switch (d->builtin_type)
6848+ {
6849+ case RISCV_BUILTIN_DIRECT:
6850+ return riscv_expand_builtin_direct (d->icode, target, exp, true);
6851+
6852+ case RISCV_BUILTIN_DIRECT_NO_TARGET:
6853+ return riscv_expand_builtin_direct (d->icode, target, exp, false);
6854+ }
6855+ gcc_unreachable ();
6856+}
6857+
6858+/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
6859+ in order to avoid duplicating too much logic from elsewhere. */
6860+
6861+static void
6862+riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
6863+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
6864+ tree function)
6865+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006866+ rtx this_rtx, temp1, temp2, fnaddr;
6867+ rtx_insn *insn;
Patrick Georgif0bbc952015-03-07 10:57:25 +01006868+ bool use_sibcall_p;
6869+
6870+ /* Pretend to be a post-reload pass while generating rtl. */
6871+ reload_completed = 1;
6872+
6873+ /* Mark the end of the (empty) prologue. */
6874+ emit_note (NOTE_INSN_PROLOGUE_END);
6875+
6876+ /* Determine if we can use a sibcall to call FUNCTION directly. */
6877+ fnaddr = XEXP (DECL_RTL (function), 0);
6878+ use_sibcall_p = absolute_symbolic_operand (fnaddr, Pmode);
6879+
6880+ /* We need two temporary registers in some cases. */
6881+ temp1 = gen_rtx_REG (Pmode, GP_TEMP_FIRST);
6882+ temp2 = gen_rtx_REG (Pmode, GP_TEMP_FIRST + 1);
6883+
6884+ /* Find out which register contains the "this" pointer. */
6885+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
6886+ this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
6887+ else
6888+ this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST);
6889+
6890+ /* Add DELTA to THIS_RTX. */
6891+ if (delta != 0)
6892+ {
6893+ rtx offset = GEN_INT (delta);
6894+ if (!SMALL_OPERAND (delta))
6895+ {
6896+ riscv_emit_move (temp1, offset);
6897+ offset = temp1;
6898+ }
6899+ emit_insn (gen_add3_insn (this_rtx, this_rtx, offset));
6900+ }
6901+
6902+ /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */
6903+ if (vcall_offset != 0)
6904+ {
6905+ rtx addr;
6906+
6907+ /* Set TEMP1 to *THIS_RTX. */
6908+ riscv_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx));
6909+
6910+ /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */
6911+ addr = riscv_add_offset (temp2, temp1, vcall_offset);
6912+
6913+ /* Load the offset and add it to THIS_RTX. */
6914+ riscv_emit_move (temp1, gen_rtx_MEM (Pmode, addr));
6915+ emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1));
6916+ }
6917+
6918+ /* Jump to the target function. Use a sibcall if direct jumps are
6919+ allowed, otherwise load the address into a register first. */
6920+ if (use_sibcall_p)
6921+ {
6922+ insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
6923+ SIBLING_CALL_P (insn) = 1;
6924+ }
6925+ else
6926+ {
6927+ riscv_emit_move(temp1, fnaddr);
6928+ emit_jump_insn (gen_indirect_jump (temp1));
6929+ }
6930+
6931+ /* Run just enough of rest_of_compilation. This sequence was
6932+ "borrowed" from alpha.c. */
6933+ insn = get_insns ();
6934+ split_all_insns_noflow ();
6935+ shorten_branches (insn);
6936+ final_start_function (insn, file, 1);
6937+ final (insn, file, 1);
6938+ final_end_function ();
6939+
6940+ /* Clean up the vars set above. Note that final_end_function resets
6941+ the global pointer for us. */
6942+ reload_completed = 0;
6943+}
6944+
6945+/* Allocate a chunk of memory for per-function machine-dependent data. */
6946+
6947+static struct machine_function *
6948+riscv_init_machine_status (void)
6949+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006950+ return ggc_cleared_alloc<machine_function> ();
Patrick Georgif0bbc952015-03-07 10:57:25 +01006951+}
6952+
6953+/* Implement TARGET_OPTION_OVERRIDE. */
6954+
6955+static void
6956+riscv_option_override (void)
6957+{
6958+ int regno, mode;
6959+ const struct riscv_cpu_info *cpu;
6960+
6961+#ifdef SUBTARGET_OVERRIDE_OPTIONS
6962+ SUBTARGET_OVERRIDE_OPTIONS;
6963+#endif
6964+
6965+ flag_pcc_struct_return = 0;
6966+
6967+ if (flag_pic)
6968+ g_switch_value = 0;
6969+
6970+ /* Prefer a call to memcpy over inline code when optimizing for size,
6971+ though see MOVE_RATIO in riscv.h. */
6972+ if (optimize_size && (target_flags_explicit & MASK_MEMCPY) == 0)
6973+ target_flags |= MASK_MEMCPY;
6974+
6975+ /* Handle -mtune. */
6976+ cpu = riscv_parse_cpu (riscv_tune_string ? riscv_tune_string :
6977+ RISCV_TUNE_STRING_DEFAULT);
6978+ tune_info = optimize_size ? &optimize_size_tune_info : cpu->tune_info;
6979+
6980+ /* If the user hasn't specified a branch cost, use the processor's
6981+ default. */
6982+ if (riscv_branch_cost == 0)
6983+ riscv_branch_cost = tune_info->branch_cost;
6984+
6985+ /* Set up riscv_hard_regno_mode_ok. */
6986+ for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
6987+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
6988+ riscv_hard_regno_mode_ok[mode][regno]
6989+ = riscv_hard_regno_mode_ok_p (regno, (enum machine_mode) mode);
6990+
6991+ /* Function to allocate machine-dependent function status. */
6992+ init_machine_status = &riscv_init_machine_status;
6993+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02006994+ if (riscv_cmodel_string)
6995+ {
6996+ if (strcmp (riscv_cmodel_string, "medlow") == 0)
6997+ riscv_cmodel = CM_MEDLOW;
6998+ else if (strcmp (riscv_cmodel_string, "medany") == 0)
6999+ riscv_cmodel = CM_MEDANY;
7000+ else
7001+ error ("unsupported code model: %s", riscv_cmodel_string);
7002+ }
7003+
7004+ if (flag_pic)
7005+ riscv_cmodel = CM_PIC;
7006+
Patrick Georgif0bbc952015-03-07 10:57:25 +01007007+ riscv_init_relocs ();
7008+}
7009+
7010+/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
7011+
7012+static void
7013+riscv_conditional_register_usage (void)
7014+{
7015+ int regno;
7016+
7017+ if (!TARGET_HARD_FLOAT)
7018+ {
7019+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
7020+ fixed_regs[regno] = call_used_regs[regno] = 1;
7021+ }
7022+}
7023+
7024+/* Implement TARGET_TRAMPOLINE_INIT. */
7025+
7026+static void
7027+riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
7028+{
7029+ rtx addr, end_addr, mem;
7030+ rtx trampoline[4];
7031+ unsigned int i;
7032+ HOST_WIDE_INT static_chain_offset, target_function_offset;
7033+
7034+ /* Work out the offsets of the pointers from the start of the
7035+ trampoline code. */
7036+ gcc_assert (ARRAY_SIZE (trampoline) * 4 == TRAMPOLINE_CODE_SIZE);
7037+ static_chain_offset = TRAMPOLINE_CODE_SIZE;
7038+ target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode);
7039+
7040+ /* Get pointers to the beginning and end of the code block. */
7041+ addr = force_reg (Pmode, XEXP (m_tramp, 0));
7042+ end_addr = riscv_force_binary (Pmode, PLUS, addr, GEN_INT (TRAMPOLINE_CODE_SIZE));
7043+
7044+#define OP(X) gen_int_mode (X, SImode)
7045+#define MATCH_LREG ((Pmode) == DImode ? MATCH_LD : MATCH_LW)
7046+
7047+ /* auipc t0, 0
7048+ l[wd] t1, target_function_offset(t0)
7049+ l[wd] $static_chain, static_chain_offset(t0)
7050+ jr t1
7051+ */
7052+
7053+ trampoline[0] = OP (RISCV_UTYPE (AUIPC, STATIC_CHAIN_REGNUM, 0));
7054+ trampoline[1] = OP (RISCV_ITYPE (LREG, RISCV_PROLOGUE_TEMP_REGNUM,
7055+ STATIC_CHAIN_REGNUM, target_function_offset));
7056+ trampoline[2] = OP (RISCV_ITYPE (LREG, STATIC_CHAIN_REGNUM,
7057+ STATIC_CHAIN_REGNUM, static_chain_offset));
7058+ trampoline[3] = OP (RISCV_ITYPE (JALR, 0, RISCV_PROLOGUE_TEMP_REGNUM, 0));
7059+
7060+#undef MATCH_LREG
7061+#undef OP
7062+
7063+ /* Copy the trampoline code. Leave any padding uninitialized. */
7064+ for (i = 0; i < ARRAY_SIZE (trampoline); i++)
7065+ {
7066+ mem = adjust_address (m_tramp, SImode, i * GET_MODE_SIZE (SImode));
7067+ riscv_emit_move (mem, trampoline[i]);
7068+ }
7069+
7070+ /* Set up the static chain pointer field. */
7071+ mem = adjust_address (m_tramp, ptr_mode, static_chain_offset);
7072+ riscv_emit_move (mem, chain_value);
7073+
7074+ /* Set up the target function field. */
7075+ mem = adjust_address (m_tramp, ptr_mode, target_function_offset);
7076+ riscv_emit_move (mem, XEXP (DECL_RTL (fndecl), 0));
7077+
7078+ /* Flush the code part of the trampoline. */
7079+ emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE)));
7080+ emit_insn (gen_clear_cache (addr, end_addr));
7081+}
7082+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007083+/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */
7084+
7085+static bool
7086+riscv_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
7087+{
7088+ if (TARGET_SAVE_RESTORE)
7089+ {
7090+ /* When optimzing for size, don't use sibcalls in non-leaf routines */
7091+ if (cfun->machine->is_leaf == 0)
7092+ cfun->machine->is_leaf = leaf_function_p () ? 1 : -1;
7093+
7094+ return cfun->machine->is_leaf > 0;
7095+ }
7096+
7097+ return true;
7098+}
7099+
Patrick Georgif0bbc952015-03-07 10:57:25 +01007100+static bool
7101+riscv_lra_p (void)
7102+{
7103+ return riscv_lra_flag;
7104+}
7105+
7106+/* Initialize the GCC target structure. */
7107+#undef TARGET_ASM_ALIGNED_HI_OP
7108+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
7109+#undef TARGET_ASM_ALIGNED_SI_OP
7110+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
7111+#undef TARGET_ASM_ALIGNED_DI_OP
7112+#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
7113+
7114+#undef TARGET_OPTION_OVERRIDE
7115+#define TARGET_OPTION_OVERRIDE riscv_option_override
7116+
7117+#undef TARGET_LEGITIMIZE_ADDRESS
7118+#define TARGET_LEGITIMIZE_ADDRESS riscv_legitimize_address
7119+
7120+#undef TARGET_SCHED_ADJUST_COST
7121+#define TARGET_SCHED_ADJUST_COST riscv_adjust_cost
7122+#undef TARGET_SCHED_ISSUE_RATE
7123+#define TARGET_SCHED_ISSUE_RATE riscv_issue_rate
7124+
7125+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007126+#define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall
Patrick Georgif0bbc952015-03-07 10:57:25 +01007127+
7128+#undef TARGET_REGISTER_MOVE_COST
7129+#define TARGET_REGISTER_MOVE_COST riscv_register_move_cost
7130+#undef TARGET_MEMORY_MOVE_COST
7131+#define TARGET_MEMORY_MOVE_COST riscv_memory_move_cost
7132+#undef TARGET_RTX_COSTS
7133+#define TARGET_RTX_COSTS riscv_rtx_costs
7134+#undef TARGET_ADDRESS_COST
7135+#define TARGET_ADDRESS_COST riscv_address_cost
7136+
7137+#undef TARGET_PREFERRED_RELOAD_CLASS
7138+#define TARGET_PREFERRED_RELOAD_CLASS riscv_preferred_reload_class
7139+
7140+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
7141+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
7142+
7143+#undef TARGET_EXPAND_BUILTIN_VA_START
7144+#define TARGET_EXPAND_BUILTIN_VA_START riscv_va_start
7145+
7146+#undef TARGET_PROMOTE_FUNCTION_MODE
7147+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
7148+
7149+#undef TARGET_RETURN_IN_MEMORY
7150+#define TARGET_RETURN_IN_MEMORY riscv_return_in_memory
7151+
7152+#undef TARGET_ASM_OUTPUT_MI_THUNK
7153+#define TARGET_ASM_OUTPUT_MI_THUNK riscv_output_mi_thunk
7154+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
7155+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
7156+
7157+#undef TARGET_PRINT_OPERAND
7158+#define TARGET_PRINT_OPERAND riscv_print_operand
7159+#undef TARGET_PRINT_OPERAND_ADDRESS
7160+#define TARGET_PRINT_OPERAND_ADDRESS riscv_print_operand_address
7161+
7162+#undef TARGET_SETUP_INCOMING_VARARGS
7163+#define TARGET_SETUP_INCOMING_VARARGS riscv_setup_incoming_varargs
7164+#undef TARGET_STRICT_ARGUMENT_NAMING
7165+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
7166+#undef TARGET_MUST_PASS_IN_STACK
7167+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
7168+#undef TARGET_PASS_BY_REFERENCE
7169+#define TARGET_PASS_BY_REFERENCE riscv_pass_by_reference
7170+#undef TARGET_ARG_PARTIAL_BYTES
7171+#define TARGET_ARG_PARTIAL_BYTES riscv_arg_partial_bytes
7172+#undef TARGET_FUNCTION_ARG
7173+#define TARGET_FUNCTION_ARG riscv_function_arg
7174+#undef TARGET_FUNCTION_ARG_ADVANCE
7175+#define TARGET_FUNCTION_ARG_ADVANCE riscv_function_arg_advance
7176+#undef TARGET_FUNCTION_ARG_BOUNDARY
7177+#define TARGET_FUNCTION_ARG_BOUNDARY riscv_function_arg_boundary
7178+
7179+#undef TARGET_MODE_REP_EXTENDED
7180+#define TARGET_MODE_REP_EXTENDED riscv_mode_rep_extended
7181+
7182+#undef TARGET_SCALAR_MODE_SUPPORTED_P
7183+#define TARGET_SCALAR_MODE_SUPPORTED_P riscv_scalar_mode_supported_p
7184+
7185+#undef TARGET_INIT_BUILTINS
7186+#define TARGET_INIT_BUILTINS riscv_init_builtins
7187+#undef TARGET_BUILTIN_DECL
7188+#define TARGET_BUILTIN_DECL riscv_builtin_decl
7189+#undef TARGET_EXPAND_BUILTIN
7190+#define TARGET_EXPAND_BUILTIN riscv_expand_builtin
7191+
7192+#undef TARGET_HAVE_TLS
7193+#define TARGET_HAVE_TLS HAVE_AS_TLS
7194+
7195+#undef TARGET_CANNOT_FORCE_CONST_MEM
7196+#define TARGET_CANNOT_FORCE_CONST_MEM riscv_cannot_force_const_mem
7197+
7198+#undef TARGET_LEGITIMATE_CONSTANT_P
7199+#define TARGET_LEGITIMATE_CONSTANT_P riscv_legitimate_constant_p
7200+
7201+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
7202+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
7203+
7204+#ifdef HAVE_AS_DTPRELWORD
7205+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
7206+#define TARGET_ASM_OUTPUT_DWARF_DTPREL riscv_output_dwarf_dtprel
7207+#endif
7208+
7209+#undef TARGET_LEGITIMATE_ADDRESS_P
7210+#define TARGET_LEGITIMATE_ADDRESS_P riscv_legitimate_address_p
7211+
7212+#undef TARGET_CAN_ELIMINATE
7213+#define TARGET_CAN_ELIMINATE riscv_can_eliminate
7214+
7215+#undef TARGET_CONDITIONAL_REGISTER_USAGE
7216+#define TARGET_CONDITIONAL_REGISTER_USAGE riscv_conditional_register_usage
7217+
7218+#undef TARGET_TRAMPOLINE_INIT
7219+#define TARGET_TRAMPOLINE_INIT riscv_trampoline_init
7220+
7221+#undef TARGET_IN_SMALL_DATA_P
7222+#define TARGET_IN_SMALL_DATA_P riscv_in_small_data_p
7223+
7224+#undef TARGET_ASM_SELECT_RTX_SECTION
7225+#define TARGET_ASM_SELECT_RTX_SECTION riscv_elf_select_rtx_section
7226+
7227+#undef TARGET_MIN_ANCHOR_OFFSET
7228+#define TARGET_MIN_ANCHOR_OFFSET (-RISCV_IMM_REACH/2)
7229+
7230+#undef TARGET_MAX_ANCHOR_OFFSET
7231+#define TARGET_MAX_ANCHOR_OFFSET (RISCV_IMM_REACH/2-1)
7232+
7233+#undef TARGET_LRA_P
7234+#define TARGET_LRA_P riscv_lra_p
7235+
7236+struct gcc_target targetm = TARGET_INITIALIZER;
7237+
7238+#include "gt-riscv.h"
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007239diff -urN empty/gcc/config/riscv/riscv.h gcc-5.2.0/gcc/config/riscv/riscv.h
Patrick Georgi410f9ad2015-08-23 21:07:46 +02007240--- gcc-5.2.0/gcc/config/riscv/riscv.h 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007241+++ gcc-5.2.0/gcc/config/riscv/riscv.h 2015-07-17 22:36:52.319705931 +0200
7242@@ -0,0 +1,1109 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01007243+/* Definition of RISC-V target for GNU compiler.
7244+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
7245+ Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
7246+ Based on MIPS target for GNU compiler.
7247+
7248+This file is part of GCC.
7249+
7250+GCC is free software; you can redistribute it and/or modify
7251+it under the terms of the GNU General Public License as published by
7252+the Free Software Foundation; either version 3, or (at your option)
7253+any later version.
7254+
7255+GCC is distributed in the hope that it will be useful,
7256+but WITHOUT ANY WARRANTY; without even the implied warranty of
7257+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7258+GNU General Public License for more details.
7259+
7260+You should have received a copy of the GNU General Public License
7261+along with GCC; see the file COPYING3. If not see
7262+<http://www.gnu.org/licenses/>. */
7263+
7264+/* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is
7265+ directly accessible, while the command-line options select
7266+ TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI to reflect the ABI
7267+ in use. */
7268+#define TARGET_HARD_FLOAT TARGET_HARD_FLOAT_ABI
7269+#define TARGET_SOFT_FLOAT TARGET_SOFT_FLOAT_ABI
7270+
7271+/* Target CPU builtins. */
7272+#define TARGET_CPU_CPP_BUILTINS() \
7273+ do \
7274+ { \
7275+ builtin_assert ("machine=riscv"); \
7276+ \
7277+ builtin_assert ("cpu=riscv"); \
7278+ builtin_define ("__riscv__"); \
7279+ builtin_define ("__riscv"); \
7280+ builtin_define ("_riscv"); \
7281+ \
7282+ if (TARGET_64BIT) \
7283+ { \
7284+ builtin_define ("__riscv64"); \
7285+ builtin_define ("_RISCV_SIM=_ABI64"); \
7286+ } \
7287+ else \
7288+ builtin_define ("_RISCV_SIM=_ABI32"); \
7289+ \
7290+ builtin_define ("_ABI32=1"); \
7291+ builtin_define ("_ABI64=3"); \
7292+ \
7293+ \
7294+ builtin_define_with_int_value ("_RISCV_SZINT", INT_TYPE_SIZE); \
7295+ builtin_define_with_int_value ("_RISCV_SZLONG", LONG_TYPE_SIZE); \
7296+ builtin_define_with_int_value ("_RISCV_SZPTR", POINTER_SIZE); \
7297+ builtin_define_with_int_value ("_RISCV_FPSET", 32); \
7298+ \
7299+ if (TARGET_ATOMIC) { \
7300+ builtin_define ("__riscv_atomic"); \
7301+ } \
7302+ \
7303+ /* These defines reflect the ABI in use, not whether the \
7304+ FPU is directly accessible. */ \
7305+ if (TARGET_HARD_FLOAT_ABI) { \
7306+ builtin_define ("__riscv_hard_float"); \
7307+ if (TARGET_FDIV) { \
7308+ builtin_define ("__riscv_fdiv"); \
7309+ builtin_define ("__riscv_fsqrt"); \
7310+ } \
7311+ } else \
7312+ builtin_define ("__riscv_soft_float"); \
7313+ \
7314+ /* The base RISC-V ISA is always little-endian. */ \
7315+ builtin_define_std ("RISCVEL"); \
7316+ builtin_define ("_RISCVEL"); \
7317+ \
7318+ /* Macros dependent on the C dialect. */ \
7319+ if (preprocessing_asm_p ()) \
7320+ { \
7321+ builtin_define_std ("LANGUAGE_ASSEMBLY"); \
7322+ builtin_define ("_LANGUAGE_ASSEMBLY"); \
7323+ } \
7324+ else if (c_dialect_cxx ()) \
7325+ { \
7326+ builtin_define ("_LANGUAGE_C_PLUS_PLUS"); \
7327+ builtin_define ("__LANGUAGE_C_PLUS_PLUS"); \
7328+ builtin_define ("__LANGUAGE_C_PLUS_PLUS__"); \
7329+ } \
7330+ else \
7331+ { \
7332+ builtin_define_std ("LANGUAGE_C"); \
7333+ builtin_define ("_LANGUAGE_C"); \
7334+ } \
7335+ if (c_dialect_objc ()) \
7336+ { \
7337+ builtin_define ("_LANGUAGE_OBJECTIVE_C"); \
7338+ builtin_define ("__LANGUAGE_OBJECTIVE_C"); \
7339+ /* Bizarre, but needed at least for Irix. */ \
7340+ builtin_define_std ("LANGUAGE_C"); \
7341+ builtin_define ("_LANGUAGE_C"); \
7342+ } \
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007343+ if (riscv_cmodel == CM_MEDANY) \
7344+ builtin_define ("_RISCV_CMODEL_MEDANY"); \
Patrick Georgif0bbc952015-03-07 10:57:25 +01007345+ } \
7346+ while (0)
7347+
7348+/* Default target_flags if no switches are specified */
7349+
7350+#ifndef TARGET_DEFAULT
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007351+#define TARGET_DEFAULT 0
Patrick Georgif0bbc952015-03-07 10:57:25 +01007352+#endif
7353+
7354+#ifndef RISCV_ARCH_STRING_DEFAULT
7355+#define RISCV_ARCH_STRING_DEFAULT "IMAFD"
7356+#endif
7357+
7358+#ifndef RISCV_TUNE_STRING_DEFAULT
7359+#define RISCV_TUNE_STRING_DEFAULT "rocket"
7360+#endif
7361+
7362+#ifndef TARGET_64BIT_DEFAULT
7363+#define TARGET_64BIT_DEFAULT 1
7364+#endif
7365+
7366+#if TARGET_64BIT_DEFAULT
7367+# define MULTILIB_ARCH_DEFAULT "m64"
7368+# define OPT_ARCH64 "!m32"
7369+# define OPT_ARCH32 "m32"
7370+#else
7371+# define MULTILIB_ARCH_DEFAULT "m32"
7372+# define OPT_ARCH64 "m64"
7373+# define OPT_ARCH32 "!m64"
7374+#endif
7375+
7376+#ifndef MULTILIB_DEFAULTS
7377+#define MULTILIB_DEFAULTS \
7378+ { MULTILIB_ARCH_DEFAULT }
7379+#endif
7380+
7381+
7382+/* Support for a compile-time default CPU, et cetera. The rules are:
7383+ --with-arch is ignored if -march is specified.
7384+ --with-tune is ignored if -mtune is specified.
7385+ --with-float is ignored if -mhard-float or -msoft-float are specified. */
7386+#define OPTION_DEFAULT_SPECS \
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007387+ {"arch", "%{!march=*:-march=%(VALUE)}"}, \
Patrick Georgif0bbc952015-03-07 10:57:25 +01007388+ {"arch_32", "%{" OPT_ARCH32 ":%{m32}}" }, \
7389+ {"arch_64", "%{" OPT_ARCH64 ":%{m64}}" }, \
7390+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
7391+ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
7392+
7393+#define DRIVER_SELF_SPECS ""
7394+
7395+#ifdef IN_LIBGCC2
7396+#undef TARGET_64BIT
7397+/* Make this compile time constant for libgcc2 */
7398+#ifdef __riscv64
7399+#define TARGET_64BIT 1
7400+#else
7401+#define TARGET_64BIT 0
7402+#endif
7403+#endif /* IN_LIBGCC2 */
7404+
7405+/* Tell collect what flags to pass to nm. */
7406+#ifndef NM_FLAGS
7407+#define NM_FLAGS "-Bn"
7408+#endif
7409+
7410+#undef ASM_SPEC
7411+#define ASM_SPEC "\
7412+%(subtarget_asm_debugging_spec) \
7413+%{m32} %{m64} %{!m32:%{!m64: %(asm_abi_default_spec)}} \
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007414+%{mrvc} \
Patrick Georgif0bbc952015-03-07 10:57:25 +01007415+%{fPIC|fpic|fPIE|fpie:-fpic} \
7416+%{march=*} \
7417+%(subtarget_asm_spec)"
7418+
7419+/* Extra switches sometimes passed to the linker. */
7420+
7421+#ifndef LINK_SPEC
7422+#define LINK_SPEC "\
7423+%{!T:-dT riscv.ld} \
7424+%{m64:-melf64lriscv} \
7425+%{m32:-melf32lriscv} \
7426+%{shared}"
7427+#endif /* LINK_SPEC defined */
7428+
7429+/* This macro defines names of additional specifications to put in the specs
7430+ that can be used in various specifications like CC1_SPEC. Its definition
7431+ is an initializer with a subgrouping for each command option.
7432+
7433+ Each subgrouping contains a string constant, that defines the
7434+ specification name, and a string constant that used by the GCC driver
7435+ program.
7436+
7437+ Do not define this macro if it does not need to do anything. */
7438+
7439+#define EXTRA_SPECS \
7440+ { "asm_abi_default_spec", "-" MULTILIB_ARCH_DEFAULT }, \
7441+ SUBTARGET_EXTRA_SPECS
7442+
7443+#ifndef SUBTARGET_EXTRA_SPECS
7444+#define SUBTARGET_EXTRA_SPECS
7445+#endif
7446+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007447+#define TARGET_DEFAULT_CMODEL CM_MEDLOW
7448+
Patrick Georgif0bbc952015-03-07 10:57:25 +01007449+/* By default, turn on GDB extensions. */
7450+#define DEFAULT_GDB_EXTENSIONS 1
7451+
7452+#define LOCAL_LABEL_PREFIX "."
7453+#define USER_LABEL_PREFIX ""
7454+
7455+#define DWARF2_DEBUGGING_INFO 1
7456+#define DWARF2_ASM_LINE_DEBUG_INFO 0
7457+
7458+/* The mapping from gcc register number to DWARF 2 CFA column number. */
7459+#define DWARF_FRAME_REGNUM(REGNO) \
7460+ (GP_REG_P (REGNO) || FP_REG_P (REGNO) ? REGNO : INVALID_REGNUM)
7461+
7462+/* The DWARF 2 CFA column which tracks the return address. */
7463+#define DWARF_FRAME_RETURN_COLUMN RETURN_ADDR_REGNUM
7464+
7465+/* Don't emit .cfi_sections, as it does not work */
7466+#undef HAVE_GAS_CFI_SECTIONS_DIRECTIVE
7467+#define HAVE_GAS_CFI_SECTIONS_DIRECTIVE 0
7468+
7469+/* Before the prologue, RA lives in r31. */
7470+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RETURN_ADDR_REGNUM)
7471+
7472+/* Describe how we implement __builtin_eh_return. */
7473+#define EH_RETURN_DATA_REGNO(N) \
7474+ ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
7475+
7476+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_ARG_FIRST + 4)
7477+
7478+/* Target machine storage layout */
7479+
7480+#define BITS_BIG_ENDIAN 0
7481+#define BYTES_BIG_ENDIAN 0
7482+#define WORDS_BIG_ENDIAN 0
7483+
7484+#define MAX_BITS_PER_WORD 64
7485+
7486+/* Width of a word, in units (bytes). */
7487+#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
7488+#ifndef IN_LIBGCC2
7489+#define MIN_UNITS_PER_WORD 4
7490+#endif
7491+
7492+/* We currently require both or neither of the `F' and `D' extensions. */
7493+#define UNITS_PER_FPREG 8
7494+
7495+/* If FP regs aren't wide enough for a given FP argument, it is passed in
7496+ integer registers. */
7497+#define MIN_FPRS_PER_FMT 1
7498+
7499+/* The largest size of value that can be held in floating-point
7500+ registers and moved with a single instruction. */
7501+#define UNITS_PER_HWFPVALUE \
7502+ (TARGET_SOFT_FLOAT_ABI ? 0 : UNITS_PER_FPREG)
7503+
7504+/* The largest size of value that can be held in floating-point
7505+ registers. */
7506+#define UNITS_PER_FPVALUE \
7507+ (TARGET_SOFT_FLOAT_ABI ? 0 \
7508+ : LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)
7509+
7510+/* The number of bytes in a double. */
7511+#define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
7512+
7513+/* Set the sizes of the core types. */
7514+#define SHORT_TYPE_SIZE 16
7515+#define INT_TYPE_SIZE 32
7516+#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
7517+#define LONG_LONG_TYPE_SIZE 64
7518+
7519+#define FLOAT_TYPE_SIZE 32
7520+#define DOUBLE_TYPE_SIZE 64
7521+/* XXX The ABI says long doubles are IEEE-754-2008 float128s. */
7522+#define LONG_DOUBLE_TYPE_SIZE 64
7523+
7524+#ifdef IN_LIBGCC2
7525+# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
7526+#endif
7527+
7528+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
7529+#define PARM_BOUNDARY BITS_PER_WORD
7530+
7531+/* Allocation boundary (in *bits*) for the code of a function. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007532+#define FUNCTION_BOUNDARY (TARGET_RVC ? 16 : 32)
Patrick Georgif0bbc952015-03-07 10:57:25 +01007533+
7534+/* There is no point aligning anything to a rounder boundary than this. */
7535+#define BIGGEST_ALIGNMENT 128
7536+
7537+/* All accesses must be aligned. */
7538+#define STRICT_ALIGNMENT 1
7539+
7540+/* Define this if you wish to imitate the way many other C compilers
7541+ handle alignment of bitfields and the structures that contain
7542+ them.
7543+
7544+ The behavior is that the type written for a bit-field (`int',
7545+ `short', or other integer type) imposes an alignment for the
7546+ entire structure, as if the structure really did contain an
7547+ ordinary field of that type. In addition, the bit-field is placed
7548+ within the structure so that it would fit within such a field,
7549+ not crossing a boundary for it.
7550+
7551+ Thus, on most machines, a bit-field whose type is written as `int'
7552+ would not cross a four-byte boundary, and would force four-byte
7553+ alignment for the whole structure. (The alignment used may not
7554+ be four bytes; it is controlled by the other alignment
7555+ parameters.)
7556+
7557+ If the macro is defined, its definition should be a C expression;
7558+ a nonzero value for the expression enables this behavior. */
7559+
7560+#define PCC_BITFIELD_TYPE_MATTERS 1
7561+
7562+/* If defined, a C expression to compute the alignment given to a
7563+ constant that is being placed in memory. CONSTANT is the constant
7564+ and ALIGN is the alignment that the object would ordinarily have.
7565+ The value of this macro is used instead of that alignment to align
7566+ the object.
7567+
7568+ If this macro is not defined, then ALIGN is used.
7569+
7570+ The typical use of this macro is to increase alignment for string
7571+ constants to be word aligned so that `strcpy' calls that copy
7572+ constants can be done inline. */
7573+
7574+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
7575+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
7576+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
7577+
7578+/* If defined, a C expression to compute the alignment for a static
7579+ variable. TYPE is the data type, and ALIGN is the alignment that
7580+ the object would ordinarily have. The value of this macro is used
7581+ instead of that alignment to align the object.
7582+
7583+ If this macro is not defined, then ALIGN is used.
7584+
7585+ One use of this macro is to increase alignment of medium-size
7586+ data to make it all fit in fewer cache lines. Another is to
7587+ cause character arrays to be word-aligned so that `strcpy' calls
7588+ that copy constants to character arrays can be done inline. */
7589+
7590+#undef DATA_ALIGNMENT
7591+#define DATA_ALIGNMENT(TYPE, ALIGN) \
7592+ ((((ALIGN) < BITS_PER_WORD) \
7593+ && (TREE_CODE (TYPE) == ARRAY_TYPE \
7594+ || TREE_CODE (TYPE) == UNION_TYPE \
7595+ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
7596+
7597+/* We need this for the same reason as DATA_ALIGNMENT, namely to cause
7598+ character arrays to be word-aligned so that `strcpy' calls that copy
7599+ constants to character arrays can be done inline, and 'strcmp' can be
7600+ optimised to use word loads. */
7601+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
7602+ DATA_ALIGNMENT (TYPE, ALIGN)
7603+
7604+/* Define if operations between registers always perform the operation
7605+ on the full register even if a narrower mode is specified. */
7606+#define WORD_REGISTER_OPERATIONS
7607+
7608+/* When in 64-bit mode, move insns will sign extend SImode and CCmode
7609+ moves. All other references are zero extended. */
7610+#define LOAD_EXTEND_OP(MODE) \
7611+ (TARGET_64BIT && ((MODE) == SImode || (MODE) == CCmode) \
7612+ ? SIGN_EXTEND : ZERO_EXTEND)
7613+
7614+/* Define this macro if it is advisable to hold scalars in registers
7615+ in a wider mode than that declared by the program. In such cases,
7616+ the value is constrained to be within the bounds of the declared
7617+ type, but kept valid in the wider mode. The signedness of the
7618+ extension may differ from that of the type. */
7619+
7620+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
7621+ if (GET_MODE_CLASS (MODE) == MODE_INT \
7622+ && GET_MODE_SIZE (MODE) < 4) \
7623+ { \
7624+ (MODE) = Pmode; \
7625+ }
7626+
7627+/* Pmode is always the same as ptr_mode, but not always the same as word_mode.
7628+ Extensions of pointers to word_mode must be signed. */
7629+#define POINTERS_EXTEND_UNSIGNED false
7630+
7631+/* RV32 double-precision FP <-> integer moves go through memory */
7632+#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
7633+ (!TARGET_64BIT && GET_MODE_SIZE (MODE) == 8 && \
7634+ (((CLASS1) == FP_REGS && (CLASS2) != FP_REGS) \
7635+ || ((CLASS2) == FP_REGS && (CLASS1) != FP_REGS)))
7636+
7637+/* Define if loading short immediate values into registers sign extends. */
7638+#define SHORT_IMMEDIATES_SIGN_EXTEND
7639+
7640+/* Standard register usage. */
7641+
7642+/* Number of hardware registers. We have:
7643+
7644+ - 32 integer registers
7645+ - 32 floating point registers
7646+ - 32 vector integer registers
7647+ - 32 vector floating point registers
7648+ - 2 fake registers:
7649+ - ARG_POINTER_REGNUM
7650+ - FRAME_POINTER_REGNUM */
7651+
7652+#define FIRST_PSEUDO_REGISTER 66
7653+
7654+/* x0, sp, gp, and tp are fixed. */
7655+
7656+#define FIXED_REGISTERS \
7657+{ /* General registers. */ \
7658+ 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
7659+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
7660+ /* Floating-point registers. */ \
7661+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
7662+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
7663+ /* Others. */ \
7664+ 1, 1 \
7665+}
7666+
7667+
7668+/* a0-a7, t0-a6, fa0-fa7, and ft0-ft11 are volatile across calls.
7669+ The call RTLs themselves clobber ra. */
7670+
7671+#define CALL_USED_REGISTERS \
7672+{ /* General registers. */ \
7673+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
7674+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
7675+ /* Floating-point registers. */ \
7676+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
7677+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
7678+ /* Others. */ \
7679+ 1, 1 \
7680+}
7681+
7682+#define CALL_REALLY_USED_REGISTERS \
7683+{ /* General registers. */ \
7684+ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
7685+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
7686+ /* Floating-point registers. */ \
7687+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, \
7688+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, \
7689+ /* Others. */ \
7690+ 1, 1 \
7691+}
7692+
7693+/* Internal macros to classify an ISA register's type. */
7694+
7695+#define GP_REG_FIRST 0
7696+#define GP_REG_LAST 31
7697+#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
7698+
7699+#define FP_REG_FIRST 32
7700+#define FP_REG_LAST 63
7701+#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1)
7702+
7703+/* The DWARF 2 CFA column which tracks the return address from a
7704+ signal handler context. This means that to maintain backwards
7705+ compatibility, no hard register can be assigned this column if it
7706+ would need to be handled by the DWARF unwinder. */
7707+#define DWARF_ALT_FRAME_RETURN_COLUMN 64
7708+
7709+#define GP_REG_P(REGNO) \
7710+ ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
7711+#define FP_REG_P(REGNO) \
7712+ ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
7713+
7714+#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
7715+
7716+/* Return coprocessor number from register number. */
7717+
7718+#define COPNUM_AS_CHAR_FROM_REGNUM(REGNO) \
7719+ (COP0_REG_P (REGNO) ? '0' : COP2_REG_P (REGNO) ? '2' \
7720+ : COP3_REG_P (REGNO) ? '3' : '?')
7721+
7722+
7723+#define HARD_REGNO_NREGS(REGNO, MODE) riscv_hard_regno_nregs (REGNO, MODE)
7724+
7725+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
7726+ riscv_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ]
7727+
7728+#define MODES_TIEABLE_P(MODE1, MODE2) \
7729+ ((MODE1) == (MODE2) || (GET_MODE_CLASS (MODE1) == MODE_INT \
7730+ && GET_MODE_CLASS (MODE2) == MODE_INT))
7731+
7732+/* Use s0 as the frame pointer if it is so requested. */
7733+#define HARD_FRAME_POINTER_REGNUM 8
7734+#define STACK_POINTER_REGNUM 2
7735+#define THREAD_POINTER_REGNUM 4
7736+
7737+/* These two registers don't really exist: they get eliminated to either
7738+ the stack or hard frame pointer. */
7739+#define ARG_POINTER_REGNUM 64
7740+#define FRAME_POINTER_REGNUM 65
7741+
7742+#define HARD_FRAME_POINTER_IS_FRAME_POINTER 0
7743+#define HARD_FRAME_POINTER_IS_ARG_POINTER 0
7744+
7745+/* Register in which static-chain is passed to a function. */
7746+#define STATIC_CHAIN_REGNUM GP_TEMP_FIRST
7747+
7748+/* Registers used as temporaries in prologue/epilogue code.
7749+
7750+ The prologue registers mustn't conflict with any
7751+ incoming arguments, the static chain pointer, or the frame pointer.
7752+ The epilogue temporary mustn't conflict with the return registers,
7753+ the frame pointer, the EH stack adjustment, or the EH data registers. */
7754+
7755+#define RISCV_PROLOGUE_TEMP_REGNUM (GP_TEMP_FIRST + 1)
7756+#define RISCV_EPILOGUE_TEMP_REGNUM RISCV_PROLOGUE_TEMP_REGNUM
7757+
7758+#define RISCV_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_PROLOGUE_TEMP_REGNUM)
7759+#define RISCV_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, RISCV_EPILOGUE_TEMP_REGNUM)
7760+
7761+#define FUNCTION_PROFILER(STREAM, LABELNO) \
7762+{ \
7763+ sorry ("profiler support for RISC-V"); \
7764+}
7765+
7766+/* Define this macro if it is as good or better to call a constant
7767+ function address than to call an address kept in a register. */
7768+#define NO_FUNCTION_CSE 1
7769+
7770+/* Define the classes of registers for register constraints in the
7771+ machine description. Also define ranges of constants.
7772+
7773+ One of the classes must always be named ALL_REGS and include all hard regs.
7774+ If there is more than one class, another class must be named NO_REGS
7775+ and contain no registers.
7776+
7777+ The name GENERAL_REGS must be the name of a class (or an alias for
7778+ another name such as ALL_REGS). This is the class of registers
7779+ that is allowed by "g" or "r" in a register constraint.
7780+ Also, registers outside this class are allocated only when
7781+ instructions express preferences for them.
7782+
7783+ The classes must be numbered in nondecreasing order; that is,
7784+ a larger-numbered class must never be contained completely
7785+ in a smaller-numbered class.
7786+
7787+ For any two classes, it is very desirable that there be another
7788+ class that represents their union. */
7789+
7790+enum reg_class
7791+{
7792+ NO_REGS, /* no registers in set */
7793+ T_REGS, /* registers used by indirect sibcalls */
7794+ GR_REGS, /* integer registers */
7795+ FP_REGS, /* floating point registers */
7796+ FRAME_REGS, /* $arg and $frame */
7797+ ALL_REGS, /* all registers */
7798+ LIM_REG_CLASSES /* max value + 1 */
7799+};
7800+
7801+#define N_REG_CLASSES (int) LIM_REG_CLASSES
7802+
7803+#define GENERAL_REGS GR_REGS
7804+
7805+/* An initializer containing the names of the register classes as C
7806+ string constants. These names are used in writing some of the
7807+ debugging dumps. */
7808+
7809+#define REG_CLASS_NAMES \
7810+{ \
7811+ "NO_REGS", \
7812+ "T_REGS", \
7813+ "GR_REGS", \
7814+ "FP_REGS", \
7815+ "FRAME_REGS", \
7816+ "ALL_REGS" \
7817+}
7818+
7819+/* An initializer containing the contents of the register classes,
7820+ as integers which are bit masks. The Nth integer specifies the
7821+ contents of class N. The way the integer MASK is interpreted is
7822+ that register R is in the class if `MASK & (1 << R)' is 1.
7823+
7824+ When the machine has more than 32 registers, an integer does not
7825+ suffice. Then the integers are replaced by sub-initializers,
7826+ braced groupings containing several integers. Each
7827+ sub-initializer must be suitable as an initializer for the type
7828+ `HARD_REG_SET' which is defined in `hard-reg-set.h'. */
7829+
7830+#define REG_CLASS_CONTENTS \
7831+{ \
7832+ { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
7833+ { 0xf00000e0, 0x00000000, 0x00000000 }, /* T_REGS */ \
7834+ { 0xffffffff, 0x00000000, 0x00000000 }, /* GR_REGS */ \
7835+ { 0x00000000, 0xffffffff, 0x00000000 }, /* FP_REGS */ \
7836+ { 0x00000000, 0x00000000, 0x00000003 }, /* FRAME_REGS */ \
7837+ { 0xffffffff, 0xffffffff, 0x00000003 } /* ALL_REGS */ \
7838+}
7839+
7840+/* A C expression whose value is a register class containing hard
7841+ register REGNO. In general there is more that one such class;
7842+ choose a class which is "minimal", meaning that no smaller class
7843+ also contains the register. */
7844+
7845+#define REGNO_REG_CLASS(REGNO) riscv_regno_to_class[ (REGNO) ]
7846+
7847+/* A macro whose definition is the name of the class to which a
7848+ valid base register must belong. A base register is one used in
7849+ an address which is the register value plus a displacement. */
7850+
7851+#define BASE_REG_CLASS GR_REGS
7852+
7853+/* A macro whose definition is the name of the class to which a
7854+ valid index register must belong. An index register is one used
7855+ in an address where its value is either multiplied by a scale
7856+ factor or added to another register (as well as added to a
7857+ displacement). */
7858+
7859+#define INDEX_REG_CLASS NO_REGS
7860+
7861+/* We generally want to put call-clobbered registers ahead of
7862+ call-saved ones. (IRA expects this.) */
7863+
7864+#define REG_ALLOC_ORDER \
7865+{ \
7866+ /* Call-clobbered GPRs. */ \
7867+ 15, 14, 13, 12, 11, 10, 16, 17, 5, 6, 7, 28, 29, 30, 31, 1, \
7868+ /* Call-saved GPRs. */ \
7869+ 8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, \
7870+ /* GPRs that can never be exposed to the register allocator. */ \
7871+ 0, 2, 3, 4, \
7872+ /* Call-clobbered FPRs. */ \
7873+ 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49, \
7874+ 60, 61, 62, 63, \
7875+ /* Call-saved FPRs. */ \
7876+ 40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, \
7877+ /* None of the remaining classes have defined call-saved \
7878+ registers. */ \
7879+ 64, 65 \
7880+}
7881+
7882+/* True if VALUE is a signed 16-bit number. */
7883+
7884+#include "opcode-riscv.h"
7885+#define SMALL_OPERAND(VALUE) \
7886+ ((unsigned HOST_WIDE_INT) (VALUE) + RISCV_IMM_REACH/2 < RISCV_IMM_REACH)
7887+
7888+/* True if VALUE can be loaded into a register using LUI. */
7889+
7890+#define LUI_OPERAND(VALUE) \
7891+ (((VALUE) | ((1UL<<31) - RISCV_IMM_REACH)) == ((1UL<<31) - RISCV_IMM_REACH) \
7892+ || ((VALUE) | ((1UL<<31) - RISCV_IMM_REACH)) + RISCV_IMM_REACH == 0)
7893+
7894+/* Return a value X with the low 16 bits clear, and such that
7895+ VALUE - X is a signed 16-bit value. */
7896+
7897+#define SMALL_INT(X) SMALL_OPERAND (INTVAL (X))
7898+#define LUI_INT(X) LUI_OPERAND (INTVAL (X))
7899+
7900+/* The HI and LO registers can only be reloaded via the general
7901+ registers. Condition code registers can only be loaded to the
7902+ general registers, and from the floating point registers. */
7903+
7904+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
7905+ riscv_secondary_reload_class (CLASS, MODE, X, true)
7906+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
7907+ riscv_secondary_reload_class (CLASS, MODE, X, false)
7908+
7909+/* Return the maximum number of consecutive registers
7910+ needed to represent mode MODE in a register of class CLASS. */
7911+
7912+#define CLASS_MAX_NREGS(CLASS, MODE) riscv_class_max_nregs (CLASS, MODE)
7913+
7914+/* It is undefined to interpret an FP register in a different format than
7915+ that which it was created to be. */
7916+
7917+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
7918+ reg_classes_intersect_p (FP_REGS, CLASS)
7919+
7920+/* Stack layout; function entry, exit and calling. */
7921+
7922+#define STACK_GROWS_DOWNWARD
7923+
7924+#define FRAME_GROWS_DOWNWARD 1
7925+
7926+#define STARTING_FRAME_OFFSET 0
7927+
7928+#define RETURN_ADDR_RTX riscv_return_addr
7929+
7930+#define ELIMINABLE_REGS \
7931+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
7932+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
7933+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
7934+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
7935+
7936+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
7937+ (OFFSET) = riscv_initial_elimination_offset (FROM, TO)
7938+
7939+/* Allocate stack space for arguments at the beginning of each function. */
7940+#define ACCUMULATE_OUTGOING_ARGS 1
7941+
7942+/* The argument pointer always points to the first argument. */
7943+#define FIRST_PARM_OFFSET(FNDECL) 0
7944+
7945+#define REG_PARM_STACK_SPACE(FNDECL) 0
7946+
7947+/* Define this if it is the responsibility of the caller to
7948+ allocate the area reserved for arguments passed in registers.
7949+ If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
7950+ of this macro is to determine whether the space is included in
7951+ `crtl->outgoing_args_size'. */
7952+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
7953+
7954+#define STACK_BOUNDARY 128
7955+
7956+/* Symbolic macros for the registers used to return integer and floating
7957+ point values. */
7958+
7959+#define GP_RETURN GP_ARG_FIRST
7960+#define FP_RETURN ((TARGET_SOFT_FLOAT) ? GP_RETURN : FP_ARG_FIRST)
7961+
7962+#define MAX_ARGS_IN_REGISTERS 8
7963+
7964+/* Symbolic macros for the first/last argument registers. */
7965+
7966+#define GP_ARG_FIRST (GP_REG_FIRST + 10)
7967+#define GP_ARG_LAST (GP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
7968+#define GP_TEMP_FIRST (GP_REG_FIRST + 5)
7969+#define FP_ARG_FIRST (FP_REG_FIRST + 10)
7970+#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
7971+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02007972+#define CALLEE_SAVED_REG_NUMBER(REGNO) \
7973+ ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 : \
7974+ (REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1)
7975+
Patrick Georgif0bbc952015-03-07 10:57:25 +01007976+#define LIBCALL_VALUE(MODE) \
7977+ riscv_function_value (NULL_TREE, NULL_TREE, MODE)
7978+
7979+#define FUNCTION_VALUE(VALTYPE, FUNC) \
7980+ riscv_function_value (VALTYPE, FUNC, VOIDmode)
7981+
7982+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
7983+
7984+/* 1 if N is a possible register number for function argument passing.
7985+ We have no FP argument registers when soft-float. When FP registers
7986+ are 32 bits, we can't directly reference the odd numbered ones. */
7987+
7988+/* Accept arguments in a0-a7 and/or fa0-fa7. */
7989+#define FUNCTION_ARG_REGNO_P(N) \
7990+ (IN_RANGE((N), GP_ARG_FIRST, GP_ARG_LAST) \
7991+ || IN_RANGE((N), FP_ARG_FIRST, FP_ARG_LAST))
7992+
7993+/* The ABI views the arguments as a structure, of which the first 8
7994+ words go in registers and the rest go on the stack. If I < 8, N, the Ith
7995+ word might go in the Ith integer argument register or the Ith
7996+ floating-point argument register. */
7997+
7998+typedef struct {
7999+ /* Number of integer registers used so far, up to MAX_ARGS_IN_REGISTERS. */
8000+ unsigned int num_gprs;
8001+
8002+ /* Number of words passed on the stack. */
8003+ unsigned int stack_words;
8004+} CUMULATIVE_ARGS;
8005+
8006+/* Initialize a variable CUM of type CUMULATIVE_ARGS
8007+ for a call to a function whose data type is FNTYPE.
8008+ For a library call, FNTYPE is 0. */
8009+
8010+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
8011+ memset (&(CUM), 0, sizeof (CUM))
8012+
8013+#define EPILOGUE_USES(REGNO) ((REGNO) == RETURN_ADDR_REGNUM)
8014+
8015+/* ABI requires 16-byte alignment, even on ven on RV32. */
8016+#define RISCV_STACK_ALIGN(LOC) (((LOC) + 15) & -16)
8017+
8018+#define NO_PROFILE_COUNTERS 1
8019+
8020+/* Define this macro if the code for function profiling should come
8021+ before the function prologue. Normally, the profiling code comes
8022+ after. */
8023+
8024+/* #define PROFILE_BEFORE_PROLOGUE */
8025+
8026+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
8027+ the stack pointer does not matter. The value is tested only in
8028+ functions that have frame pointers.
8029+ No definition is equivalent to always zero. */
8030+
8031+#define EXIT_IGNORE_STACK 1
8032+
8033+
8034+/* Trampolines are a block of code followed by two pointers. */
8035+
8036+#define TRAMPOLINE_CODE_SIZE 16
8037+#define TRAMPOLINE_SIZE (TRAMPOLINE_CODE_SIZE + POINTER_SIZE * 2)
8038+#define TRAMPOLINE_ALIGNMENT POINTER_SIZE
8039+
8040+/* Addressing modes, and classification of registers for them. */
8041+
8042+#define REGNO_OK_FOR_INDEX_P(REGNO) 0
8043+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
8044+ riscv_regno_mode_ok_for_base_p (REGNO, MODE, 1)
8045+
8046+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
8047+ and check its validity for a certain class.
8048+ We have two alternate definitions for each of them.
8049+ The usual definition accepts all pseudo regs; the other rejects them all.
8050+ The symbol REG_OK_STRICT causes the latter definition to be used.
8051+
8052+ Most source files want to accept pseudo regs in the hope that
8053+ they will get allocated to the class that the insn wants them to be in.
8054+ Some source files that are used after register allocation
8055+ need to be strict. */
8056+
8057+#ifndef REG_OK_STRICT
8058+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
8059+ riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 0)
8060+#else
8061+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
8062+ riscv_regno_mode_ok_for_base_p (REGNO (X), MODE, 1)
8063+#endif
8064+
8065+#define REG_OK_FOR_INDEX_P(X) 0
8066+
8067+
8068+/* Maximum number of registers that can appear in a valid memory address. */
8069+
8070+#define MAX_REGS_PER_ADDRESS 1
8071+
8072+#define CONSTANT_ADDRESS_P(X) \
8073+ (CONSTANT_P (X) && memory_address_p (SImode, X))
8074+
8075+/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
8076+ 'the start of the function that this code is output in'. */
8077+
8078+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
8079+ if (strcmp (NAME, "..CURRENT_FUNCTION") == 0) \
8080+ asm_fprintf ((FILE), "%U%s", \
8081+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
8082+ else \
8083+ asm_fprintf ((FILE), "%U%s", (NAME))
8084+
8085+/* This flag marks functions that cannot be lazily bound. */
8086+#define SYMBOL_FLAG_BIND_NOW (SYMBOL_FLAG_MACH_DEP << 1)
8087+#define SYMBOL_REF_BIND_NOW_P(RTX) \
8088+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_BIND_NOW) != 0)
8089+
8090+#define JUMP_TABLES_IN_TEXT_SECTION 0
8091+#define CASE_VECTOR_MODE SImode
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008092+#define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW)
Patrick Georgif0bbc952015-03-07 10:57:25 +01008093+
8094+/* Define this as 1 if `char' should by default be signed; else as 0. */
8095+#define DEFAULT_SIGNED_CHAR 0
8096+
8097+/* Consider using fld/fsd to move 8 bytes at a time for RV32IFD. */
8098+#define MOVE_MAX UNITS_PER_WORD
8099+#define MAX_MOVE_MAX 8
8100+
8101+#define SLOW_BYTE_ACCESS 0
8102+
8103+#define SHIFT_COUNT_TRUNCATED 1
8104+
8105+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
8106+ is done just by pretending it is already truncated. */
8107+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \
8108+ (TARGET_64BIT ? ((INPREC) <= 32 || (OUTPREC) < 32) : 1)
8109+
8110+/* Specify the machine mode that pointers have.
8111+ After generation of rtl, the compiler makes no further distinction
8112+ between pointers and any other objects of this machine mode. */
8113+
8114+#ifndef Pmode
8115+#define Pmode (TARGET_64BIT ? DImode : SImode)
8116+#endif
8117+
8118+/* Give call MEMs SImode since it is the "most permissive" mode
8119+ for both 32-bit and 64-bit targets. */
8120+
8121+#define FUNCTION_MODE SImode
8122+
8123+/* A C expression for the cost of a branch instruction. A value of 2
8124+ seems to minimize code size. */
8125+
8126+#define BRANCH_COST(speed_p, predictable_p) \
8127+ ((!(speed_p) || (predictable_p)) ? 2 : riscv_branch_cost)
8128+
8129+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
8130+
8131+/* Control the assembler format that we output. */
8132+
8133+/* Output to assembler file text saying following lines
8134+ may contain character constants, extra white space, comments, etc. */
8135+
8136+#ifndef ASM_APP_ON
8137+#define ASM_APP_ON " #APP\n"
8138+#endif
8139+
8140+/* Output to assembler file text saying following lines
8141+ no longer contain unusual constructs. */
8142+
8143+#ifndef ASM_APP_OFF
8144+#define ASM_APP_OFF " #NO_APP\n"
8145+#endif
8146+
8147+#define REGISTER_NAMES \
8148+{ "zero","ra", "sp", "gp", "tp", "t0", "t1", "t2", \
8149+ "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", \
8150+ "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", \
8151+ "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", \
8152+ "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", \
8153+ "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \
8154+ "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \
8155+ "fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \
8156+ "arg", "frame", }
8157+
8158+#define ADDITIONAL_REGISTER_NAMES \
8159+{ \
8160+ { "x0", 0 + GP_REG_FIRST }, \
8161+ { "x1", 1 + GP_REG_FIRST }, \
8162+ { "x2", 2 + GP_REG_FIRST }, \
8163+ { "x3", 3 + GP_REG_FIRST }, \
8164+ { "x4", 4 + GP_REG_FIRST }, \
8165+ { "x5", 5 + GP_REG_FIRST }, \
8166+ { "x6", 6 + GP_REG_FIRST }, \
8167+ { "x7", 7 + GP_REG_FIRST }, \
8168+ { "x8", 8 + GP_REG_FIRST }, \
8169+ { "x9", 9 + GP_REG_FIRST }, \
8170+ { "x10", 10 + GP_REG_FIRST }, \
8171+ { "x11", 11 + GP_REG_FIRST }, \
8172+ { "x12", 12 + GP_REG_FIRST }, \
8173+ { "x13", 13 + GP_REG_FIRST }, \
8174+ { "x14", 14 + GP_REG_FIRST }, \
8175+ { "x15", 15 + GP_REG_FIRST }, \
8176+ { "x16", 16 + GP_REG_FIRST }, \
8177+ { "x17", 17 + GP_REG_FIRST }, \
8178+ { "x18", 18 + GP_REG_FIRST }, \
8179+ { "x19", 19 + GP_REG_FIRST }, \
8180+ { "x20", 20 + GP_REG_FIRST }, \
8181+ { "x21", 21 + GP_REG_FIRST }, \
8182+ { "x22", 22 + GP_REG_FIRST }, \
8183+ { "x23", 23 + GP_REG_FIRST }, \
8184+ { "x24", 24 + GP_REG_FIRST }, \
8185+ { "x25", 25 + GP_REG_FIRST }, \
8186+ { "x26", 26 + GP_REG_FIRST }, \
8187+ { "x27", 27 + GP_REG_FIRST }, \
8188+ { "x28", 28 + GP_REG_FIRST }, \
8189+ { "x29", 29 + GP_REG_FIRST }, \
8190+ { "x30", 30 + GP_REG_FIRST }, \
8191+ { "x31", 31 + GP_REG_FIRST }, \
8192+ { "f0", 0 + FP_REG_FIRST }, \
8193+ { "f1", 1 + FP_REG_FIRST }, \
8194+ { "f2", 2 + FP_REG_FIRST }, \
8195+ { "f3", 3 + FP_REG_FIRST }, \
8196+ { "f4", 4 + FP_REG_FIRST }, \
8197+ { "f5", 5 + FP_REG_FIRST }, \
8198+ { "f6", 6 + FP_REG_FIRST }, \
8199+ { "f7", 7 + FP_REG_FIRST }, \
8200+ { "f8", 8 + FP_REG_FIRST }, \
8201+ { "f9", 9 + FP_REG_FIRST }, \
8202+ { "f10", 10 + FP_REG_FIRST }, \
8203+ { "f11", 11 + FP_REG_FIRST }, \
8204+ { "f12", 12 + FP_REG_FIRST }, \
8205+ { "f13", 13 + FP_REG_FIRST }, \
8206+ { "f14", 14 + FP_REG_FIRST }, \
8207+ { "f15", 15 + FP_REG_FIRST }, \
8208+ { "f16", 16 + FP_REG_FIRST }, \
8209+ { "f17", 17 + FP_REG_FIRST }, \
8210+ { "f18", 18 + FP_REG_FIRST }, \
8211+ { "f19", 19 + FP_REG_FIRST }, \
8212+ { "f20", 20 + FP_REG_FIRST }, \
8213+ { "f21", 21 + FP_REG_FIRST }, \
8214+ { "f22", 22 + FP_REG_FIRST }, \
8215+ { "f23", 23 + FP_REG_FIRST }, \
8216+ { "f24", 24 + FP_REG_FIRST }, \
8217+ { "f25", 25 + FP_REG_FIRST }, \
8218+ { "f26", 26 + FP_REG_FIRST }, \
8219+ { "f27", 27 + FP_REG_FIRST }, \
8220+ { "f28", 28 + FP_REG_FIRST }, \
8221+ { "f29", 29 + FP_REG_FIRST }, \
8222+ { "f30", 30 + FP_REG_FIRST }, \
8223+ { "f31", 31 + FP_REG_FIRST }, \
8224+}
8225+
8226+/* Globalizing directive for a label. */
8227+#define GLOBAL_ASM_OP "\t.globl\t"
8228+
8229+/* This is how to store into the string LABEL
8230+ the symbol_ref name of an internal numbered label where
8231+ PREFIX is the class of label and NUM is the number within the class.
8232+ This is suitable for output with `assemble_name'. */
8233+
8234+#undef ASM_GENERATE_INTERNAL_LABEL
8235+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
8236+ sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
8237+
8238+/* This is how to output an element of a case-vector that is absolute. */
8239+
8240+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
8241+ fprintf (STREAM, "\t.word\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
8242+
8243+/* This is how to output an element of a PIC case-vector. */
8244+
8245+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
8246+ fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n", \
8247+ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL)
8248+
8249+/* This is how to output an assembler line
8250+ that says to advance the location counter
8251+ to a multiple of 2**LOG bytes. */
8252+
8253+#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
8254+ fprintf (STREAM, "\t.align\t%d\n", (LOG))
8255+
8256+/* Define the strings to put out for each section in the object file. */
8257+#define TEXT_SECTION_ASM_OP "\t.text" /* instructions */
8258+#define DATA_SECTION_ASM_OP "\t.data" /* large data */
8259+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
8260+#define BSS_SECTION_ASM_OP "\t.bss"
8261+#define SBSS_SECTION_ASM_OP "\t.section\t.sbss,\"aw\",@nobits"
8262+#define SDATA_SECTION_ASM_OP "\t.section\t.sdata,\"aw\",@progbits"
8263+
8264+#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
8265+do \
8266+ { \
8267+ fprintf (STREAM, "\taddi\t%s,%s,-8\n\t%s\t%s,0(%s)\n", \
8268+ reg_names[STACK_POINTER_REGNUM], \
8269+ reg_names[STACK_POINTER_REGNUM], \
8270+ TARGET_64BIT ? "sd" : "sw", \
8271+ reg_names[REGNO], \
8272+ reg_names[STACK_POINTER_REGNUM]); \
8273+ } \
8274+while (0)
8275+
8276+#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
8277+do \
8278+ { \
8279+ fprintf (STREAM, "\t%s\t%s,0(%s)\n\taddi\t%s,%s,8\n", \
8280+ TARGET_64BIT ? "ld" : "lw", \
8281+ reg_names[REGNO], \
8282+ reg_names[STACK_POINTER_REGNUM], \
8283+ reg_names[STACK_POINTER_REGNUM], \
8284+ reg_names[STACK_POINTER_REGNUM]); \
8285+ } \
8286+while (0)
8287+
8288+#define ASM_COMMENT_START "#"
8289+
8290+#undef SIZE_TYPE
8291+#define SIZE_TYPE (POINTER_SIZE == 64 ? "long unsigned int" : "unsigned int")
8292+
8293+#undef PTRDIFF_TYPE
8294+#define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int")
8295+
8296+/* The maximum number of bytes that can be copied by one iteration of
8297+ a movmemsi loop; see riscv_block_move_loop. */
8298+#define RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER (UNITS_PER_WORD * 4)
8299+
8300+/* The maximum number of bytes that can be copied by a straight-line
8301+ implementation of movmemsi; see riscv_block_move_straight. We want
8302+ to make sure that any loop-based implementation will iterate at
8303+ least twice. */
8304+#define RISCV_MAX_MOVE_BYTES_STRAIGHT (RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER * 2)
8305+
8306+/* The base cost of a memcpy call, for MOVE_RATIO and friends. */
8307+
8308+#define RISCV_CALL_RATIO 6
8309+
8310+/* Any loop-based implementation of movmemsi will have at least
8311+ RISCV_MAX_MOVE_BYTES_STRAIGHT / UNITS_PER_WORD memory-to-memory
8312+ moves, so allow individual copies of fewer elements.
8313+
8314+ When movmemsi is not available, use a value approximating
8315+ the length of a memcpy call sequence, so that move_by_pieces
8316+ will generate inline code if it is shorter than a function call.
8317+ Since move_by_pieces_ninsns counts memory-to-memory moves, but
8318+ we'll have to generate a load/store pair for each, halve the
8319+ value of RISCV_CALL_RATIO to take that into account. */
8320+
8321+#define MOVE_RATIO(speed) \
8322+ (HAVE_movmemsi \
8323+ ? RISCV_MAX_MOVE_BYTES_STRAIGHT / MOVE_MAX \
8324+ : RISCV_CALL_RATIO / 2)
8325+
Patrick Georgif0bbc952015-03-07 10:57:25 +01008326+/* For CLEAR_RATIO, when optimizing for size, give a better estimate
8327+ of the length of a memset call, but use the default otherwise. */
8328+
8329+#define CLEAR_RATIO(speed)\
8330+ ((speed) ? 15 : RISCV_CALL_RATIO)
8331+
8332+/* This is similar to CLEAR_RATIO, but for a non-zero constant, so when
8333+ optimizing for size adjust the ratio to account for the overhead of
8334+ loading the constant and replicating it across the word. */
8335+
8336+#define SET_RATIO(speed) \
8337+ ((speed) ? 15 : RISCV_CALL_RATIO - 2)
8338+
Patrick Georgif0bbc952015-03-07 10:57:25 +01008339+#ifndef HAVE_AS_TLS
8340+#define HAVE_AS_TLS 0
8341+#endif
8342+
8343+#ifndef USED_FOR_TARGET
8344+
8345+extern const enum reg_class riscv_regno_to_class[];
8346+extern bool riscv_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
8347+extern const char* riscv_hi_relocs[];
8348+#endif
8349+
8350+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
8351+ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008352diff -urN empty/gcc/config/riscv/riscv.md gcc-5.2.0/gcc/config/riscv/riscv.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +02008353--- gcc-5.2.0/gcc/config/riscv/riscv.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008354+++ gcc-5.2.0/gcc/config/riscv/riscv.md 2015-07-17 22:36:52.319705931 +0200
8355@@ -0,0 +1,2448 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +01008356+;; Machine description for RISC-V for GNU compiler.
8357+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
8358+;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
8359+;; Based on MIPS target for GNU compiler.
8360+
8361+;; This file is part of GCC.
8362+
8363+;; GCC is free software; you can redistribute it and/or modify
8364+;; it under the terms of the GNU General Public License as published by
8365+;; the Free Software Foundation; either version 3, or (at your option)
8366+;; any later version.
8367+
8368+;; GCC is distributed in the hope that it will be useful,
8369+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
8370+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8371+;; GNU General Public License for more details.
8372+
8373+;; You should have received a copy of the GNU General Public License
8374+;; along with GCC; see the file COPYING3. If not see
8375+;; <http://www.gnu.org/licenses/>.
8376+
8377+(define_c_enum "unspec" [
8378+ ;; Floating-point moves.
8379+ UNSPEC_LOAD_LOW
8380+ UNSPEC_LOAD_HIGH
8381+ UNSPEC_STORE_WORD
8382+
8383+ ;; GP manipulation.
8384+ UNSPEC_EH_RETURN
8385+
8386+ ;; Symbolic accesses.
8387+ UNSPEC_ADDRESS_FIRST
8388+ UNSPEC_LOAD_GOT
8389+ UNSPEC_TLS
8390+ UNSPEC_TLS_LE
8391+ UNSPEC_TLS_IE
8392+ UNSPEC_TLS_GD
8393+
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008394+ ;; Register save and restore.
8395+ UNSPEC_GPR_SAVE
8396+ UNSPEC_GPR_RESTORE
8397+
Patrick Georgif0bbc952015-03-07 10:57:25 +01008398+ ;; Blockage and synchronisation.
8399+ UNSPEC_BLOCKAGE
8400+ UNSPEC_FENCE
8401+ UNSPEC_FENCE_I
8402+])
8403+
8404+(define_constants
8405+ [(RETURN_ADDR_REGNUM 1)
Patrick Georgiaf473ed2015-07-17 23:35:54 +02008406+ (T0_REGNUM 5)
8407+ (T1_REGNUM 6)
Patrick Georgif0bbc952015-03-07 10:57:25 +01008408+])
8409+
8410+(include "predicates.md")
8411+(include "constraints.md")
8412+
8413+;; ....................
8414+;;
8415+;; Attributes
8416+;;
8417+;; ....................
8418+
8419+(define_attr "got" "unset,xgot_high,load"
8420+ (const_string "unset"))
8421+
8422+;; For jal instructions, this attribute is DIRECT when the target address
8423+;; is symbolic and INDIRECT when it is a register.
8424+(define_attr "jal" "unset,direct,indirect"
8425+ (const_string "unset"))
8426+
8427+;; Classification of moves, extensions and truncations. Most values
8428+;; are as for "type" (see below) but there are also the following
8429+;; move-specific values:
8430+;;
8431+;; andi a single ANDI instruction
8432+;; shift_shift a shift left followed by a shift right
8433+;;
8434+;; This attribute is used to determine the instruction's length and
8435+;; scheduling type. For doubleword moves, the attribute always describes
8436+;; the split instructions; in some cases, it is more appropriate for the
8437+;; scheduling type to be "multi" instead.
8438+(define_attr "move_type"
8439+ "unknown,load,fpload,store,fpstore,mtc,mfc,move,fmove,
8440+ const,logical,arith,andi,shift_shift"
8441+ (const_string "unknown"))
8442+
8443+(define_attr "alu_type" "unknown,add,sub,and,or,xor"
8444+ (const_string "unknown"))
8445+
8446+;; Main data type used by the insn
8447+(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF,FPSW"
8448+ (const_string "unknown"))
8449+
8450+;; True if the main data type is twice the size of a word.
8451+(define_attr "dword_mode" "no,yes"
8452+ (cond [(and (eq_attr "mode" "DI,DF")
8453+ (eq (symbol_ref "TARGET_64BIT") (const_int 0)))
8454+ (const_string "yes")
8455+
8456+ (and (eq_attr "mode" "TI,TF")
8457+ (ne (symbol_ref "TARGET_64BIT") (const_int 0)))
8458+ (const_string "yes")]
8459+ (const_string "no")))
8460+
8461+;; Classification of each insn.
8462+;; branch conditional branch
8463+;; jump unconditional jump
8464+;; call unconditional call
8465+;; load load instruction(s)
8466+;; fpload floating point load
8467+;; fpidxload floating point indexed load
8468+;; store store instruction(s)
8469+;; fpstore floating point store
8470+;; fpidxstore floating point indexed store
8471+;; mtc transfer to coprocessor
8472+;; mfc transfer from coprocessor
8473+;; const load constant
8474+;; arith integer arithmetic instructions
8475+;; logical integer logical instructions
8476+;; shift integer shift instructions
8477+;; slt set less than instructions
8478+;; imul integer multiply
8479+;; idiv integer divide
8480+;; move integer register move (addi rd, rs1, 0)
8481+;; fmove floating point register move
8482+;; fadd floating point add/subtract
8483+;; fmul floating point multiply
8484+;; fmadd floating point multiply-add
8485+;; fdiv floating point divide
8486+;; fcmp floating point compare
8487+;; fcvt floating point convert
8488+;; fsqrt floating point square root
8489+;; multi multiword sequence (or user asm statements)
8490+;; nop no operation
8491+;; ghost an instruction that produces no real code
8492+(define_attr "type"
8493+ "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,
8494+ mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
8495+ fmadd,fdiv,fcmp,fcvt,fsqrt,multi,nop,ghost"
8496+ (cond [(eq_attr "jal" "!unset") (const_string "call")
8497+ (eq_attr "got" "load") (const_string "load")
8498+
8499+ (eq_attr "alu_type" "add,sub") (const_string "arith")
8500+
8501+ (eq_attr "alu_type" "and,or,xor") (const_string "logical")
8502+
8503+ ;; If a doubleword move uses these expensive instructions,
8504+ ;; it is usually better to schedule them in the same way
8505+ ;; as the singleword form, rather than as "multi".
8506+ (eq_attr "move_type" "load") (const_string "load")
8507+ (eq_attr "move_type" "fpload") (const_string "fpload")
8508+ (eq_attr "move_type" "store") (const_string "store")
8509+ (eq_attr "move_type" "fpstore") (const_string "fpstore")
8510+ (eq_attr "move_type" "mtc") (const_string "mtc")
8511+ (eq_attr "move_type" "mfc") (const_string "mfc")
8512+
8513+ ;; These types of move are always single insns.
8514+ (eq_attr "move_type" "fmove") (const_string "fmove")
8515+ (eq_attr "move_type" "arith") (const_string "arith")
8516+ (eq_attr "move_type" "logical") (const_string "logical")
8517+ (eq_attr "move_type" "andi") (const_string "logical")
8518+
8519+ ;; These types of move are always split.
8520+ (eq_attr "move_type" "shift_shift")
8521+ (const_string "multi")
8522+
8523+ ;; These types of move are split for doubleword modes only.
8524+ (and (eq_attr "move_type" "move,const")
8525+ (eq_attr "dword_mode" "yes"))
8526+ (const_string "multi")
8527+ (eq_attr "move_type" "move") (const_string "move")
8528+ (eq_attr "move_type" "const") (const_string "const")]
8529+ (const_string "unknown")))
8530+
8531+;; Mode for conversion types (fcvt)
8532+;; I2S integer to float single (SI/DI to SF)
8533+;; I2D integer to float double (SI/DI to DF)
8534+;; S2I float to integer (SF to SI/DI)
8535+;; D2I float to integer (DF to SI/DI)
8536+;; D2S double to float single
8537+;; S2D float single to double
8538+
8539+(define_attr "cnv_mode" "unknown,I2S,I2D,S2I,D2I,D2S,S2D"
8540+ (const_string "unknown"))
8541+
8542+;; Length of instruction in bytes.
8543+(define_attr "length" ""
8544+ (cond [
8545+ ;; Direct branch instructions have a range of [-0x1000,0xffc],
8546+ ;; relative to the address of the delay slot. If a branch is
8547+ ;; outside this range, convert a branch like:
8548+ ;;
8549+ ;; bne r1,r2,target
8550+ ;;
8551+ ;; to:
8552+ ;;
8553+ ;; beq r1,r2,1f
8554+ ;; j target
8555+ ;; 1:
8556+ ;;
8557+ (eq_attr "type" "branch")
8558+ (if_then_else (and (le (minus (match_dup 0) (pc)) (const_int 4088))
8559+ (le (minus (pc) (match_dup 0)) (const_int 4092)))
8560+ (const_int 4)
8561+ (const_int 8))
8562+
8563+ ;; Conservatively assume calls take two instructions, as in:
8564+ ;; auipc t0, %pcrel_hi(target)
8565+ ;; jalr ra, t0, %lo(target)
8566+ ;; The linker will relax these into JAL when appropriate.
8567+ (eq_attr "type" "call")
8568+ (const_int 8)
8569+
8570+ ;; "Ghost" instructions occupy no space.
8571+ (eq_attr "type" "ghost")
8572+ (const_int 0)
8573+
8574+ (eq_attr "got" "load") (const_int 8)
8575+
8576+ ;; SHIFT_SHIFTs are decomposed into two separate instructions.
8577+ (eq_attr "move_type" "shift_shift")
8578+ (const_int 8)
8579+
8580+ ;; Check for doubleword moves that are decomposed into two
8581+ ;; instructions.
8582+ (and (eq_attr "move_type" "mtc,mfc,move")
8583+ (eq_attr "dword_mode" "yes"))
8584+ (const_int 8)
8585+
8586+ ;; Doubleword CONST{,N} moves are split into two word
8587+ ;; CONST{,N} moves.
8588+ (and (eq_attr "move_type" "const")
8589+ (eq_attr "dword_mode" "yes"))
8590+ (symbol_ref "riscv_split_const_insns (operands[1]) * 4")
8591+
8592+ ;; Otherwise, constants, loads and stores are handled by external
8593+ ;; routines.
8594+ (eq_attr "move_type" "load,fpload")
8595+ (symbol_ref "riscv_load_store_insns (operands[1], insn) * 4")
8596+ (eq_attr "move_type" "store,fpstore")
8597+ (symbol_ref "riscv_load_store_insns (operands[0], insn) * 4")
8598+ ] (const_int 4)))
8599+
8600+;; Describe a user's asm statement.
8601+(define_asm_attributes
8602+ [(set_attr "type" "multi")])
8603+
8604+;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
8605+;; from the same template.
8606+(define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
8607+(define_mode_iterator SUPERQI [HI SI (DI "TARGET_64BIT")])
8608+
8609+;; A copy of GPR that can be used when a pattern has two independent
8610+;; modes.
8611+(define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")])
8612+
8613+;; This mode iterator allows :P to be used for patterns that operate on
8614+;; pointer-sized quantities. Exactly one of the two alternatives will match.
8615+(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
8616+
8617+;; 32-bit integer moves for which we provide move patterns.
8618+(define_mode_iterator IMOVE32 [SI])
8619+
8620+;; 64-bit modes for which we provide move patterns.
8621+(define_mode_iterator MOVE64 [DI DF])
8622+
8623+;; 128-bit modes for which we provide move patterns on 64-bit targets.
8624+(define_mode_iterator MOVE128 [TI TF])
8625+
8626+;; This mode iterator allows the QI and HI extension patterns to be
8627+;; defined from the same template.
8628+(define_mode_iterator SHORT [QI HI])
8629+
8630+;; Likewise the 64-bit truncate-and-shift patterns.
8631+(define_mode_iterator SUBDI [QI HI SI])
8632+(define_mode_iterator HISI [HI SI])
8633+(define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
8634+
8635+;; This mode iterator allows :ANYF to be used wherever a scalar or vector
8636+;; floating-point mode is allowed.
8637+(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
8638+ (DF "TARGET_HARD_FLOAT")])
8639+(define_mode_iterator ANYIF [QI HI SI (DI "TARGET_64BIT")
8640+ (SF "TARGET_HARD_FLOAT")
8641+ (DF "TARGET_HARD_FLOAT")])
8642+
8643+;; Like ANYF, but only applies to scalar modes.
8644+(define_mode_iterator SCALARF [(SF "TARGET_HARD_FLOAT")
8645+ (DF "TARGET_HARD_FLOAT")])
8646+
8647+;; A floating-point mode for which moves involving FPRs may need to be split.
8648+(define_mode_iterator SPLITF
8649+ [(DF "!TARGET_64BIT")
8650+ (DI "!TARGET_64BIT")
8651+ (TF "TARGET_64BIT")])
8652+
8653+;; This attribute gives the length suffix for a sign- or zero-extension
8654+;; instruction.
8655+(define_mode_attr size [(QI "b") (HI "h")])
8656+
8657+;; Mode attributes for loads.
8658+(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
8659+
8660+;; Instruction names for stores.
8661+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
8662+
8663+;; This attribute gives the best constraint to use for registers of
8664+;; a given mode.
8665+(define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
8666+
8667+;; This attribute gives the format suffix for floating-point operations.
8668+(define_mode_attr fmt [(SF "s") (DF "d")])
8669+
8670+;; This attribute gives the format suffix for atomic memory operations.
8671+(define_mode_attr amo [(SI "w") (DI "d")])
8672+
8673+;; This attribute gives the upper-case mode name for one unit of a
8674+;; floating-point mode.
8675+(define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
8676+
8677+;; This attribute gives the integer mode that has half the size of
8678+;; the controlling mode.
8679+(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
8680+
8681+;; This code iterator allows signed and unsigned widening multiplications
8682+;; to use the same template.
8683+(define_code_iterator any_extend [sign_extend zero_extend])
8684+
8685+;; This code iterator allows the two right shift instructions to be
8686+;; generated from the same template.
8687+(define_code_iterator any_shiftrt [ashiftrt lshiftrt])
8688+
8689+;; This code iterator allows the three shift instructions to be generated
8690+;; from the same template.
8691+(define_code_iterator any_shift [ashift ashiftrt lshiftrt])
8692+
8693+;; This code iterator allows unsigned and signed division to be generated
8694+;; from the same template.
8695+(define_code_iterator any_div [div udiv])
8696+
8697+;; This code iterator allows unsigned and signed modulus to be generated
8698+;; from the same template.
8699+(define_code_iterator any_mod [mod umod])
8700+
8701+;; These code iterators allow the signed and unsigned scc operations to use
8702+;; the same template.
8703+(define_code_iterator any_gt [gt gtu])
8704+(define_code_iterator any_ge [ge geu])
8705+(define_code_iterator any_lt [lt ltu])
8706+(define_code_iterator any_le [le leu])
8707+
8708+;; <u> expands to an empty string when doing a signed operation and
8709+;; "u" when doing an unsigned operation.
8710+(define_code_attr u [(sign_extend "") (zero_extend "u")
8711+ (div "") (udiv "u")
8712+ (mod "") (umod "u")
8713+ (gt "") (gtu "u")
8714+ (ge "") (geu "u")
8715+ (lt "") (ltu "u")
8716+ (le "") (leu "u")])
8717+
8718+;; <su> is like <u>, but the signed form expands to "s" rather than "".
8719+(define_code_attr su [(sign_extend "s") (zero_extend "u")])
8720+
8721+;; <optab> expands to the name of the optab for a particular code.
8722+(define_code_attr optab [(ashift "ashl")
8723+ (ashiftrt "ashr")
8724+ (lshiftrt "lshr")
8725+ (ior "ior")
8726+ (xor "xor")
8727+ (and "and")
8728+ (plus "add")
8729+ (minus "sub")])
8730+
8731+;; <insn> expands to the name of the insn that implements a particular code.
8732+(define_code_attr insn [(ashift "sll")
8733+ (ashiftrt "sra")
8734+ (lshiftrt "srl")
8735+ (ior "or")
8736+ (xor "xor")
8737+ (and "and")
8738+ (plus "add")
8739+ (minus "sub")])
8740+
8741+;; Pipeline descriptions.
8742+;;
8743+;; generic.md provides a fallback for processors without a specific
8744+;; pipeline description. It is derived from the old define_function_unit
8745+;; version and uses the "alu" and "imuldiv" units declared below.
8746+;;
8747+;; Some of the processor-specific files are also derived from old
8748+;; define_function_unit descriptions and simply override the parts of
8749+;; generic.md that don't apply. The other processor-specific files
8750+;; are self-contained.
8751+(define_automaton "alu,imuldiv")
8752+
8753+(define_cpu_unit "alu" "alu")
8754+(define_cpu_unit "imuldiv" "imuldiv")
8755+
8756+;; Ghost instructions produce no real code and introduce no hazards.
8757+;; They exist purely to express an effect on dataflow.
8758+(define_insn_reservation "ghost" 0
8759+ (eq_attr "type" "ghost")
8760+ "nothing")
8761+
8762+(include "generic.md")
8763+
8764+;;
8765+;; ....................
8766+;;
8767+;; ADDITION
8768+;;
8769+;; ....................
8770+;;
8771+
8772+(define_insn "add<mode>3"
8773+ [(set (match_operand:ANYF 0 "register_operand" "=f")
8774+ (plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
8775+ (match_operand:ANYF 2 "register_operand" "f")))]
8776+ ""
8777+ "fadd.<fmt>\t%0,%1,%2"
8778+ [(set_attr "type" "fadd")
8779+ (set_attr "mode" "<UNITMODE>")])
8780+
8781+(define_expand "add<mode>3"
8782+ [(set (match_operand:GPR 0 "register_operand")
8783+ (plus:GPR (match_operand:GPR 1 "register_operand")
8784+ (match_operand:GPR 2 "arith_operand")))]
8785+ "")
8786+
8787+(define_insn "*addsi3"
8788+ [(set (match_operand:SI 0 "register_operand" "=r,r")
8789+ (plus:SI (match_operand:GPR 1 "register_operand" "r,r")
8790+ (match_operand:GPR2 2 "arith_operand" "r,Q")))]
8791+ ""
8792+ { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
8793+ [(set_attr "type" "arith")
8794+ (set_attr "mode" "SI")])
8795+
8796+(define_insn "*adddi3"
8797+ [(set (match_operand:DI 0 "register_operand" "=r,r")
8798+ (plus:DI (match_operand:DI 1 "register_operand" "r,r")
8799+ (match_operand:DI 2 "arith_operand" "r,Q")))]
8800+ "TARGET_64BIT"
8801+ "add\t%0,%1,%2"
8802+ [(set_attr "type" "arith")
8803+ (set_attr "mode" "DI")])
8804+
8805+(define_insn "*addsi3_extended"
8806+ [(set (match_operand:DI 0 "register_operand" "=r,r")
8807+ (sign_extend:DI
8808+ (plus:SI (match_operand:SI 1 "register_operand" "r,r")
8809+ (match_operand:SI 2 "arith_operand" "r,Q"))))]
8810+ "TARGET_64BIT"
8811+ "addw\t%0,%1,%2"
8812+ [(set_attr "type" "arith")
8813+ (set_attr "mode" "SI")])
8814+
8815+(define_insn "*adddisi3"
8816+ [(set (match_operand:SI 0 "register_operand" "=r,r")
8817+ (plus:SI (truncate:SI (match_operand:DI 1 "register_operand" "r,r"))
8818+ (truncate:SI (match_operand:DI 2 "arith_operand" "r,Q"))))]
8819+ "TARGET_64BIT"
8820+ "addw\t%0,%1,%2"
8821+ [(set_attr "type" "arith")
8822+ (set_attr "mode" "SI")])
8823+
8824+(define_insn "*adddisisi3"
8825+ [(set (match_operand:SI 0 "register_operand" "=r,r")
8826+ (plus:SI (truncate:SI (match_operand:DI 1 "register_operand" "r,r"))
8827+ (match_operand:SI 2 "arith_operand" "r,Q")))]
8828+ "TARGET_64BIT"
8829+ "addw\t%0,%1,%2"
8830+ [(set_attr "type" "arith")
8831+ (set_attr "mode" "SI")])
8832+
8833+(define_insn "*adddi3_truncsi"
8834+ [(set (match_operand:SI 0 "register_operand" "=r,r")
8835+ (truncate:SI
8836+ (plus:DI (match_operand:DI 1 "register_operand" "r,r")
8837+ (match_operand:DI 2 "arith_operand" "r,Q"))))]
8838+ "TARGET_64BIT"
8839+ "addw\t%0,%1,%2"
8840+ [(set_attr "type" "arith")
8841+ (set_attr "mode" "SI")])
8842+
8843+;;
8844+;; ....................
8845+;;
8846+;; SUBTRACTION
8847+;;
8848+;; ....................
8849+;;
8850+
8851+(define_insn "sub<mode>3"
8852+ [(set (match_operand:ANYF 0 "register_operand" "=f")
8853+ (minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
8854+ (match_operand:ANYF 2 "register_operand" "f")))]
8855+ ""
8856+ "fsub.<fmt>\t%0,%1,%2"
8857+ [(set_attr "type" "fadd")
8858+ (set_attr "mode" "<UNITMODE>")])
8859+
8860+(define_expand "sub<mode>3"
8861+ [(set (match_operand:GPR 0 "register_operand")
8862+ (minus:GPR (match_operand:GPR 1 "reg_or_0_operand")
8863+ (match_operand:GPR 2 "register_operand")))]
8864+ "")
8865+
8866+(define_insn "*subdi3"
8867+ [(set (match_operand:DI 0 "register_operand" "=r")
8868+ (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
8869+ (match_operand:DI 2 "register_operand" "r")))]
8870+ "TARGET_64BIT"
8871+ "sub\t%0,%z1,%2"
8872+ [(set_attr "type" "arith")
8873+ (set_attr "mode" "DI")])
8874+
8875+(define_insn "*subsi3"
8876+ [(set (match_operand:SI 0 "register_operand" "=r")
8877+ (minus:SI (match_operand:GPR 1 "reg_or_0_operand" "rJ")
8878+ (match_operand:GPR2 2 "register_operand" "r")))]
8879+ ""
8880+ { return TARGET_64BIT ? "subw\t%0,%z1,%2" : "sub\t%0,%z1,%2"; }
8881+ [(set_attr "type" "arith")
8882+ (set_attr "mode" "SI")])
8883+
8884+(define_insn "*subsi3_extended"
8885+ [(set (match_operand:DI 0 "register_operand" "=r")
8886+ (sign_extend:DI
8887+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
8888+ (match_operand:SI 2 "register_operand" "r"))))]
8889+ "TARGET_64BIT"
8890+ "subw\t%0,%z1,%2"
8891+ [(set_attr "type" "arith")
8892+ (set_attr "mode" "DI")])
8893+
8894+(define_insn "*subdisi3"
8895+ [(set (match_operand:SI 0 "register_operand" "=r")
8896+ (minus:SI (truncate:SI (match_operand:DI 1 "reg_or_0_operand" "rJ"))
8897+ (truncate:SI (match_operand:DI 2 "register_operand" "r"))))]
8898+ "TARGET_64BIT"
8899+ "subw\t%0,%z1,%2"
8900+ [(set_attr "type" "arith")
8901+ (set_attr "mode" "SI")])
8902+
8903+(define_insn "*subdisisi3"
8904+ [(set (match_operand:SI 0 "register_operand" "=r")
8905+ (minus:SI (truncate:SI (match_operand:DI 1 "reg_or_0_operand" "rJ"))
8906+ (match_operand:SI 2 "register_operand" "r")))]
8907+ "TARGET_64BIT"
8908+ "subw\t%0,%z1,%2"
8909+ [(set_attr "type" "arith")
8910+ (set_attr "mode" "SI")])
8911+
8912+(define_insn "*subsidisi3"
8913+ [(set (match_operand:SI 0 "register_operand" "=r")
8914+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
8915+ (truncate:SI (match_operand:DI 2 "register_operand" "r"))))]
8916+ "TARGET_64BIT"
8917+ "subw\t%0,%z1,%2"
8918+ [(set_attr "type" "arith")
8919+ (set_attr "mode" "SI")])
8920+
8921+(define_insn "*subdi3_truncsi"
8922+ [(set (match_operand:SI 0 "register_operand" "=r,r")
8923+ (truncate:SI
8924+ (minus:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,r")
8925+ (match_operand:DI 2 "arith_operand" "r,Q"))))]
8926+ "TARGET_64BIT"
8927+ "subw\t%0,%z1,%2"
8928+ [(set_attr "type" "arith")
8929+ (set_attr "mode" "SI")])
8930+
8931+;;
8932+;; ....................
8933+;;
8934+;; MULTIPLICATION
8935+;;
8936+;; ....................
8937+;;
8938+
8939+(define_insn "mul<mode>3"
8940+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
8941+ (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
8942+ (match_operand:SCALARF 2 "register_operand" "f")))]
8943+ ""
8944+ "fmul.<fmt>\t%0,%1,%2"
8945+ [(set_attr "type" "fmul")
8946+ (set_attr "mode" "<UNITMODE>")])
8947+
8948+(define_expand "mul<mode>3"
8949+ [(set (match_operand:GPR 0 "register_operand")
8950+ (mult:GPR (match_operand:GPR 1 "reg_or_0_operand")
8951+ (match_operand:GPR 2 "register_operand")))]
8952+ "TARGET_MULDIV")
8953+
8954+(define_insn "*mulsi3"
8955+ [(set (match_operand:SI 0 "register_operand" "=r")
8956+ (mult:SI (match_operand:GPR 1 "register_operand" "r")
8957+ (match_operand:GPR2 2 "register_operand" "r")))]
8958+ "TARGET_MULDIV"
8959+ { return TARGET_64BIT ? "mulw\t%0,%1,%2" : "mul\t%0,%1,%2"; }
8960+ [(set_attr "type" "imul")
8961+ (set_attr "mode" "SI")])
8962+
8963+(define_insn "*muldisi3"
8964+ [(set (match_operand:SI 0 "register_operand" "=r")
8965+ (mult:SI (truncate:SI (match_operand:DI 1 "register_operand" "r"))
8966+ (truncate:SI (match_operand:DI 2 "register_operand" "r"))))]
8967+ "TARGET_MULDIV && TARGET_64BIT"
8968+ "mulw\t%0,%1,%2"
8969+ [(set_attr "type" "imul")
8970+ (set_attr "mode" "SI")])
8971+
8972+(define_insn "*muldi3_truncsi"
8973+ [(set (match_operand:SI 0 "register_operand" "=r")
8974+ (truncate:SI
8975+ (mult:DI (match_operand:DI 1 "register_operand" "r")
8976+ (match_operand:DI 2 "register_operand" "r"))))]
8977+ "TARGET_MULDIV && TARGET_64BIT"
8978+ "mulw\t%0,%1,%2"
8979+ [(set_attr "type" "imul")
8980+ (set_attr "mode" "SI")])
8981+
8982+(define_insn "*muldi3"
8983+ [(set (match_operand:DI 0 "register_operand" "=r")
8984+ (mult:DI (match_operand:DI 1 "register_operand" "r")
8985+ (match_operand:DI 2 "register_operand" "r")))]
8986+ "TARGET_MULDIV && TARGET_64BIT"
8987+ "mul\t%0,%1,%2"
8988+ [(set_attr "type" "imul")
8989+ (set_attr "mode" "DI")])
8990+
8991+;;
8992+;; ........................
8993+;;
8994+;; MULTIPLICATION HIGH-PART
8995+;;
8996+;; ........................
8997+;;
8998+
8999+
9000+;; Using a clobber here is ghetto, but I'm not smart enough to do better. '
9001+(define_insn_and_split "<u>mulditi3"
9002+ [(set (match_operand:TI 0 "register_operand" "=r")
9003+ (mult:TI (any_extend:TI
9004+ (match_operand:DI 1 "register_operand" "r"))
9005+ (any_extend:TI
9006+ (match_operand:DI 2 "register_operand" "r"))))
9007+ (clobber (match_scratch:DI 3 "=r"))]
9008+ "TARGET_MULDIV && TARGET_64BIT"
9009+ "#"
9010+ "reload_completed"
9011+ [
9012+ (set (match_dup 3) (mult:DI (match_dup 1) (match_dup 2)))
9013+ (set (match_dup 4) (truncate:DI
9014+ (lshiftrt:TI
9015+ (mult:TI (any_extend:TI (match_dup 1))
9016+ (any_extend:TI (match_dup 2)))
9017+ (const_int 64))))
9018+ (set (match_dup 5) (match_dup 3))
9019+ ]
9020+{
9021+ operands[4] = riscv_subword (operands[0], true);
9022+ operands[5] = riscv_subword (operands[0], false);
9023+}
9024+ )
9025+
9026+(define_insn "<u>muldi3_highpart"
9027+ [(set (match_operand:DI 0 "register_operand" "=r")
9028+ (truncate:DI
9029+ (lshiftrt:TI
9030+ (mult:TI (any_extend:TI
9031+ (match_operand:DI 1 "register_operand" "r"))
9032+ (any_extend:TI
9033+ (match_operand:DI 2 "register_operand" "r")))
9034+ (const_int 64))))]
9035+ "TARGET_MULDIV && TARGET_64BIT"
9036+ "mulh<u>\t%0,%1,%2"
9037+ [(set_attr "type" "imul")
9038+ (set_attr "mode" "DI")])
9039+
9040+
9041+(define_insn_and_split "usmulditi3"
9042+ [(set (match_operand:TI 0 "register_operand" "=r")
9043+ (mult:TI (zero_extend:TI
9044+ (match_operand:DI 1 "register_operand" "r"))
9045+ (sign_extend:TI
9046+ (match_operand:DI 2 "register_operand" "r"))))
9047+ (clobber (match_scratch:DI 3 "=r"))]
9048+ "TARGET_MULDIV && TARGET_64BIT"
9049+ "#"
9050+ "reload_completed"
9051+ [
9052+ (set (match_dup 3) (mult:DI (match_dup 1) (match_dup 2)))
9053+ (set (match_dup 4) (truncate:DI
9054+ (lshiftrt:TI
9055+ (mult:TI (zero_extend:TI (match_dup 1))
9056+ (sign_extend:TI (match_dup 2)))
9057+ (const_int 64))))
9058+ (set (match_dup 5) (match_dup 3))
9059+ ]
9060+{
9061+ operands[4] = riscv_subword (operands[0], true);
9062+ operands[5] = riscv_subword (operands[0], false);
9063+}
9064+ )
9065+
9066+(define_insn "usmuldi3_highpart"
9067+ [(set (match_operand:DI 0 "register_operand" "=r")
9068+ (truncate:DI
9069+ (lshiftrt:TI
9070+ (mult:TI (zero_extend:TI
9071+ (match_operand:DI 1 "register_operand" "r"))
9072+ (sign_extend:TI
9073+ (match_operand:DI 2 "register_operand" "r")))
9074+ (const_int 64))))]
9075+ "TARGET_MULDIV && TARGET_64BIT"
9076+ "mulhsu\t%0,%2,%1"
9077+ [(set_attr "type" "imul")
9078+ (set_attr "mode" "DI")])
9079+
9080+(define_expand "<u>mulsidi3"
9081+ [(set (match_operand:DI 0 "register_operand" "=r")
9082+ (mult:DI (any_extend:DI
9083+ (match_operand:SI 1 "register_operand" "r"))
9084+ (any_extend:DI
9085+ (match_operand:SI 2 "register_operand" "r"))))
9086+ (clobber (match_scratch:SI 3 "=r"))]
9087+ "TARGET_MULDIV && !TARGET_64BIT"
9088+{
9089+ rtx temp = gen_reg_rtx (SImode);
9090+ emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
9091+ emit_insn (gen_<u>mulsi3_highpart (riscv_subword (operands[0], true),
9092+ operands[1], operands[2]));
9093+ emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
9094+ DONE;
9095+}
9096+ )
9097+
9098+(define_insn "<u>mulsi3_highpart"
9099+ [(set (match_operand:SI 0 "register_operand" "=r")
9100+ (truncate:SI
9101+ (lshiftrt:DI
9102+ (mult:DI (any_extend:DI
9103+ (match_operand:SI 1 "register_operand" "r"))
9104+ (any_extend:DI
9105+ (match_operand:SI 2 "register_operand" "r")))
9106+ (const_int 32))))]
9107+ "TARGET_MULDIV && !TARGET_64BIT"
9108+ "mulh<u>\t%0,%1,%2"
9109+ [(set_attr "type" "imul")
9110+ (set_attr "mode" "SI")])
9111+
9112+
9113+(define_expand "usmulsidi3"
9114+ [(set (match_operand:DI 0 "register_operand" "=r")
9115+ (mult:DI (zero_extend:DI
9116+ (match_operand:SI 1 "register_operand" "r"))
9117+ (sign_extend:DI
9118+ (match_operand:SI 2 "register_operand" "r"))))
9119+ (clobber (match_scratch:SI 3 "=r"))]
9120+ "TARGET_MULDIV && !TARGET_64BIT"
9121+{
9122+ rtx temp = gen_reg_rtx (SImode);
9123+ emit_insn (gen_mulsi3 (temp, operands[1], operands[2]));
9124+ emit_insn (gen_usmulsi3_highpart (riscv_subword (operands[0], true),
9125+ operands[1], operands[2]));
9126+ emit_insn (gen_movsi (riscv_subword (operands[0], false), temp));
9127+ DONE;
9128+}
9129+ )
9130+
9131+(define_insn "usmulsi3_highpart"
9132+ [(set (match_operand:SI 0 "register_operand" "=r")
9133+ (truncate:SI
9134+ (lshiftrt:DI
9135+ (mult:DI (zero_extend:DI
9136+ (match_operand:SI 1 "register_operand" "r"))
9137+ (sign_extend:DI
9138+ (match_operand:SI 2 "register_operand" "r")))
9139+ (const_int 32))))]
9140+ "TARGET_MULDIV && !TARGET_64BIT"
9141+ "mulhsu\t%0,%2,%1"
9142+ [(set_attr "type" "imul")
9143+ (set_attr "mode" "SI")])
9144+
9145+;;
9146+;; ....................
9147+;;
9148+;; DIVISION and REMAINDER
9149+;;
9150+;; ....................
9151+;;
9152+
9153+(define_insn "<u>divsi3"
9154+ [(set (match_operand:SI 0 "register_operand" "=r")
9155+ (any_div:SI (match_operand:SI 1 "register_operand" "r")
9156+ (match_operand:SI 2 "register_operand" "r")))]
9157+ "TARGET_MULDIV"
9158+ { return TARGET_64BIT ? "div<u>w\t%0,%1,%2" : "div<u>\t%0,%1,%2"; }
9159+ [(set_attr "type" "idiv")
9160+ (set_attr "mode" "SI")])
9161+
9162+(define_insn "<u>divdi3"
9163+ [(set (match_operand:DI 0 "register_operand" "=r")
9164+ (any_div:DI (match_operand:DI 1 "register_operand" "r")
9165+ (match_operand:DI 2 "register_operand" "r")))]
9166+ "TARGET_MULDIV && TARGET_64BIT"
9167+ "div<u>\t%0,%1,%2"
9168+ [(set_attr "type" "idiv")
9169+ (set_attr "mode" "DI")])
9170+
9171+(define_insn "<u>modsi3"
9172+ [(set (match_operand:SI 0 "register_operand" "=r")
9173+ (any_mod:SI (match_operand:SI 1 "register_operand" "r")
9174+ (match_operand:SI 2 "register_operand" "r")))]
9175+ "TARGET_MULDIV"
9176+ { return TARGET_64BIT ? "rem<u>w\t%0,%1,%2" : "rem<u>\t%0,%1,%2"; }
9177+ [(set_attr "type" "idiv")
9178+ (set_attr "mode" "SI")])
9179+
9180+(define_insn "<u>moddi3"
9181+ [(set (match_operand:DI 0 "register_operand" "=r")
9182+ (any_mod:DI (match_operand:DI 1 "register_operand" "r")
9183+ (match_operand:DI 2 "register_operand" "r")))]
9184+ "TARGET_MULDIV && TARGET_64BIT"
9185+ "rem<u>\t%0,%1,%2"
9186+ [(set_attr "type" "idiv")
9187+ (set_attr "mode" "DI")])
9188+
9189+(define_insn "div<mode>3"
9190+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9191+ (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
9192+ (match_operand:ANYF 2 "register_operand" "f")))]
9193+ "TARGET_HARD_FLOAT && TARGET_FDIV"
9194+ "fdiv.<fmt>\t%0,%1,%2"
9195+ [(set_attr "type" "fdiv")
9196+ (set_attr "mode" "<UNITMODE>")])
9197+
9198+;;
9199+;; ....................
9200+;;
9201+;; SQUARE ROOT
9202+;;
9203+;; ....................
9204+
9205+(define_insn "sqrt<mode>2"
9206+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9207+ (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
9208+ "TARGET_HARD_FLOAT && TARGET_FDIV"
9209+{
9210+ return "fsqrt.<fmt>\t%0,%1";
9211+}
9212+ [(set_attr "type" "fsqrt")
9213+ (set_attr "mode" "<UNITMODE>")])
9214+
9215+;; Floating point multiply accumulate instructions.
9216+
9217+(define_insn "fma<mode>4"
9218+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9219+ (fma:ANYF
9220+ (match_operand:ANYF 1 "register_operand" "f")
9221+ (match_operand:ANYF 2 "register_operand" "f")
9222+ (match_operand:ANYF 3 "register_operand" "f")))]
9223+ "TARGET_HARD_FLOAT"
9224+ "fmadd.<fmt>\t%0,%1,%2,%3"
9225+ [(set_attr "type" "fmadd")
9226+ (set_attr "mode" "<UNITMODE>")])
9227+
9228+(define_insn "fms<mode>4"
9229+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9230+ (fma:ANYF
9231+ (match_operand:ANYF 1 "register_operand" "f")
9232+ (match_operand:ANYF 2 "register_operand" "f")
9233+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))]
9234+ "TARGET_HARD_FLOAT"
9235+ "fmsub.<fmt>\t%0,%1,%2,%3"
9236+ [(set_attr "type" "fmadd")
9237+ (set_attr "mode" "<UNITMODE>")])
9238+
9239+(define_insn "nfma<mode>4"
9240+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9241+ (neg:ANYF
9242+ (fma:ANYF
9243+ (match_operand:ANYF 1 "register_operand" "f")
9244+ (match_operand:ANYF 2 "register_operand" "f")
9245+ (match_operand:ANYF 3 "register_operand" "f"))))]
9246+ "TARGET_HARD_FLOAT"
9247+ "fnmadd.<fmt>\t%0,%1,%2,%3"
9248+ [(set_attr "type" "fmadd")
9249+ (set_attr "mode" "<UNITMODE>")])
9250+
9251+(define_insn "nfms<mode>4"
9252+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9253+ (neg:ANYF
9254+ (fma:ANYF
9255+ (match_operand:ANYF 1 "register_operand" "f")
9256+ (match_operand:ANYF 2 "register_operand" "f")
9257+ (neg:ANYF (match_operand:ANYF 3 "register_operand" "f")))))]
9258+ "TARGET_HARD_FLOAT"
9259+ "fnmsub.<fmt>\t%0,%1,%2,%3"
9260+ [(set_attr "type" "fmadd")
9261+ (set_attr "mode" "<UNITMODE>")])
9262+
9263+;; modulo signed zeros, -(a*b+c) == -c-a*b
9264+(define_insn "*nfma<mode>4_fastmath"
9265+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9266+ (minus:ANYF
9267+ (match_operand:ANYF 3 "register_operand" "f")
9268+ (mult:ANYF
9269+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
9270+ (match_operand:ANYF 2 "register_operand" "f"))))]
9271+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
9272+ "fnmadd.<fmt>\t%0,%1,%2,%3"
9273+ [(set_attr "type" "fmadd")
9274+ (set_attr "mode" "<UNITMODE>")])
9275+
9276+;; modulo signed zeros, -(a*b-c) == c-a*b
9277+(define_insn "*nfms<mode>4_fastmath"
9278+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9279+ (minus:ANYF
9280+ (match_operand:ANYF 3 "register_operand" "f")
9281+ (mult:ANYF
9282+ (match_operand:ANYF 1 "register_operand" "f")
9283+ (match_operand:ANYF 2 "register_operand" "f"))))]
9284+ "TARGET_HARD_FLOAT && !HONOR_SIGNED_ZEROS (<MODE>mode)"
9285+ "fnmsub.<fmt>\t%0,%1,%2,%3"
9286+ [(set_attr "type" "fmadd")
9287+ (set_attr "mode" "<UNITMODE>")])
9288+
9289+;;
9290+;; ....................
9291+;;
9292+;; ABSOLUTE VALUE
9293+;;
9294+;; ....................
9295+
9296+(define_insn "abs<mode>2"
9297+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9298+ (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
9299+ "TARGET_HARD_FLOAT"
9300+ "fabs.<fmt>\t%0,%1"
9301+ [(set_attr "type" "fmove")
9302+ (set_attr "mode" "<UNITMODE>")])
9303+
9304+
9305+;;
9306+;; ....................
9307+;;
9308+;; MIN/MAX
9309+;;
9310+;; ....................
9311+
9312+(define_insn "smin<mode>3"
9313+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9314+ (smin:ANYF (match_operand:ANYF 1 "register_operand" "f")
9315+ (match_operand:ANYF 2 "register_operand" "f")))]
9316+ "TARGET_HARD_FLOAT"
9317+ "fmin.<fmt>\t%0,%1,%2"
9318+ [(set_attr "type" "fmove")
9319+ (set_attr "mode" "<UNITMODE>")])
9320+
9321+(define_insn "smax<mode>3"
9322+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9323+ (smax:ANYF (match_operand:ANYF 1 "register_operand" "f")
9324+ (match_operand:ANYF 2 "register_operand" "f")))]
9325+ "TARGET_HARD_FLOAT"
9326+ "fmax.<fmt>\t%0,%1,%2"
9327+ [(set_attr "type" "fmove")
9328+ (set_attr "mode" "<UNITMODE>")])
9329+
9330+
9331+;;
9332+;; ....................
9333+;;
9334+;; NEGATION and ONE'S COMPLEMENT '
9335+;;
9336+;; ....................
9337+
9338+(define_insn "neg<mode>2"
9339+ [(set (match_operand:ANYF 0 "register_operand" "=f")
9340+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
9341+ "TARGET_HARD_FLOAT"
9342+ "fneg.<fmt>\t%0,%1"
9343+ [(set_attr "type" "fmove")
9344+ (set_attr "mode" "<UNITMODE>")])
9345+
9346+(define_insn "one_cmpl<mode>2"
9347+ [(set (match_operand:GPR 0 "register_operand" "=r")
9348+ (not:GPR (match_operand:GPR 1 "register_operand" "r")))]
9349+ ""
9350+ "not\t%0,%1"
9351+ [(set_attr "type" "logical")
9352+ (set_attr "mode" "<MODE>")])
9353+
9354+;;
9355+;; ....................
9356+;;
9357+;; LOGICAL
9358+;;
9359+;; ....................
9360+;;
9361+
9362+(define_insn "and<mode>3"
9363+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
9364+ (and:GPR (match_operand:GPR 1 "register_operand" "%r,r")
9365+ (match_operand:GPR 2 "arith_operand" "r,Q")))]
9366+ ""
9367+ "and\t%0,%1,%2"
9368+ [(set_attr "type" "logical")
9369+ (set_attr "mode" "<MODE>")])
9370+
9371+(define_insn "ior<mode>3"
9372+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
9373+ (ior:GPR (match_operand:GPR 1 "register_operand" "%r,r")
9374+ (match_operand:GPR 2 "arith_operand" "r,Q")))]
9375+ ""
9376+ "or\t%0,%1,%2"
9377+ [(set_attr "type" "logical")
9378+ (set_attr "mode" "<MODE>")])
9379+
9380+(define_insn "xor<mode>3"
9381+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
9382+ (xor:GPR (match_operand:GPR 1 "register_operand" "%r,r")
9383+ (match_operand:GPR 2 "arith_operand" "r,Q")))]
9384+ ""
9385+ "xor\t%0,%1,%2"
9386+ [(set_attr "type" "logical")
9387+ (set_attr "mode" "<MODE>")])
9388+
9389+;;
9390+;; ....................
9391+;;
9392+;; TRUNCATION
9393+;;
9394+;; ....................
9395+
9396+(define_insn "truncdfsf2"
9397+ [(set (match_operand:SF 0 "register_operand" "=f")
9398+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
9399+ "TARGET_HARD_FLOAT"
9400+ "fcvt.s.d\t%0,%1"
9401+ [(set_attr "type" "fcvt")
9402+ (set_attr "cnv_mode" "D2S")
9403+ (set_attr "mode" "SF")])
9404+
9405+;; Integer truncation patterns. Truncating to HImode/QImode is a no-op.
9406+;; Truncating from DImode to SImode is not, because we always keep SImode
9407+;; values sign-extended in a register so we can safely use DImode branches
9408+;; and comparisons on SImode values.
9409+
9410+(define_insn "truncdisi2"
9411+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
9412+ (truncate:SI (match_operand:DI 1 "register_operand" "r,r")))]
9413+ "TARGET_64BIT"
9414+ "@
9415+ sext.w\t%0,%1
9416+ sw\t%1,%0"
9417+ [(set_attr "move_type" "arith,store")
9418+ (set_attr "mode" "SI")])
9419+
9420+;; Combiner patterns to optimize shift/truncate combinations.
9421+
9422+(define_insn "*ashr_trunc<mode>"
9423+ [(set (match_operand:SUBDI 0 "register_operand" "=r")
9424+ (truncate:SUBDI
9425+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
9426+ (match_operand:DI 2 "const_arith_operand" ""))))]
9427+ "TARGET_64BIT && IN_RANGE (INTVAL (operands[2]), 32, 63)"
9428+ "sra\t%0,%1,%2"
9429+ [(set_attr "type" "shift")
9430+ (set_attr "mode" "<MODE>")])
9431+
9432+(define_insn "*lshr32_trunc<mode>"
9433+ [(set (match_operand:SUBDI 0 "register_operand" "=r")
9434+ (truncate:SUBDI
9435+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
9436+ (const_int 32))))]
9437+ "TARGET_64BIT"
9438+ "sra\t%0,%1,32"
9439+ [(set_attr "type" "shift")
9440+ (set_attr "mode" "<MODE>")])
9441+
9442+;;
9443+;; ....................
9444+;;
9445+;; ZERO EXTENSION
9446+;;
9447+;; ....................
9448+
9449+;; Extension insns.
9450+
9451+(define_insn_and_split "zero_extendsidi2"
9452+ [(set (match_operand:DI 0 "register_operand" "=r,r")
9453+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,W")))]
9454+ "TARGET_64BIT"
9455+ "@
9456+ #
9457+ lwu\t%0,%1"
9458+ "&& reload_completed && REG_P (operands[1])"
9459+ [(set (match_dup 0)
9460+ (ashift:DI (match_dup 1) (const_int 32)))
9461+ (set (match_dup 0)
9462+ (lshiftrt:DI (match_dup 0) (const_int 32)))]
9463+ { operands[1] = gen_lowpart (DImode, operands[1]); }
9464+ [(set_attr "move_type" "shift_shift,load")
9465+ (set_attr "mode" "DI")])
9466+
9467+;; Combine is not allowed to convert this insn into a zero_extendsidi2
9468+;; because of TRULY_NOOP_TRUNCATION.
9469+
9470+(define_insn_and_split "*clear_upper32"
9471+ [(set (match_operand:DI 0 "register_operand" "=r,r")
9472+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "r,W")
9473+ (const_int 4294967295)))]
9474+ "TARGET_64BIT"
9475+{
9476+ if (which_alternative == 0)
9477+ return "#";
9478+
9479+ operands[1] = gen_lowpart (SImode, operands[1]);
9480+ return "lwu\t%0,%1";
9481+}
9482+ "&& reload_completed && REG_P (operands[1])"
9483+ [(set (match_dup 0)
9484+ (ashift:DI (match_dup 1) (const_int 32)))
9485+ (set (match_dup 0)
9486+ (lshiftrt:DI (match_dup 0) (const_int 32)))]
9487+ ""
9488+ [(set_attr "move_type" "shift_shift,load")
9489+ (set_attr "mode" "DI")])
9490+
9491+(define_insn_and_split "zero_extendhi<GPR:mode>2"
9492+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
9493+ (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
9494+ ""
9495+ "@
9496+ #
9497+ lhu\t%0,%1"
9498+ "&& reload_completed && REG_P (operands[1])"
9499+ [(set (match_dup 0)
9500+ (ashift:GPR (match_dup 1) (match_dup 2)))
9501+ (set (match_dup 0)
9502+ (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
9503+ {
9504+ operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
9505+ operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
9506+ }
9507+ [(set_attr "move_type" "shift_shift,load")
9508+ (set_attr "mode" "<GPR:MODE>")])
9509+
9510+(define_insn "zero_extendqi<SUPERQI:mode>2"
9511+ [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
9512+ (zero_extend:SUPERQI
9513+ (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
9514+ ""
9515+ "@
9516+ and\t%0,%1,0xff
9517+ lbu\t%0,%1"
9518+ [(set_attr "move_type" "andi,load")
9519+ (set_attr "mode" "<SUPERQI:MODE>")])
9520+
9521+;;
9522+;; ....................
9523+;;
9524+;; SIGN EXTENSION
9525+;;
9526+;; ....................
9527+
9528+;; Extension insns.
9529+;; Those for integer source operand are ordered widest source type first.
9530+
9531+;; When TARGET_64BIT, all SImode integer registers should already be in
9532+;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can
9533+;; therefore get rid of register->register instructions if we constrain
9534+;; the source to be in the same register as the destination.
9535+;;
9536+;; The register alternative has type "arith" so that the pre-reload
9537+;; scheduler will treat it as a move. This reflects what happens if
9538+;; the register alternative needs a reload.
9539+(define_insn_and_split "extendsidi2"
9540+ [(set (match_operand:DI 0 "register_operand" "=r,r")
9541+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
9542+ "TARGET_64BIT"
9543+ "@
9544+ #
9545+ lw\t%0,%1"
9546+ "&& reload_completed && register_operand (operands[1], VOIDmode)"
9547+ [(set (match_dup 0) (match_dup 1))]
9548+{
9549+ if (REGNO (operands[0]) == REGNO (operands[1]))
9550+ {
9551+ emit_note (NOTE_INSN_DELETED);
9552+ DONE;
9553+ }
9554+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
9555+}
9556+ [(set_attr "move_type" "move,load")
9557+ (set_attr "mode" "DI")])
9558+
9559+(define_insn_and_split "extend<SHORT:mode><SUPERQI:mode>2"
9560+ [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
9561+ (sign_extend:SUPERQI
9562+ (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))]
9563+ ""
9564+ "@
9565+ #
9566+ l<SHORT:size>\t%0,%1"
9567+ "&& reload_completed && REG_P (operands[1])"
9568+ [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
9569+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
9570+{
9571+ operands[0] = gen_lowpart (SImode, operands[0]);
9572+ operands[1] = gen_lowpart (SImode, operands[1]);
9573+ operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
9574+ - GET_MODE_BITSIZE (<SHORT:MODE>mode));
9575+}
9576+ [(set_attr "move_type" "shift_shift,load")
9577+ (set_attr "mode" "SI")])
9578+
9579+(define_insn "extendsfdf2"
9580+ [(set (match_operand:DF 0 "register_operand" "=f")
9581+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
9582+ "TARGET_HARD_FLOAT"
9583+ "fcvt.d.s\t%0,%1"
9584+ [(set_attr "type" "fcvt")
9585+ (set_attr "cnv_mode" "S2D")
9586+ (set_attr "mode" "DF")])
9587+
9588+;;
9589+;; ....................
9590+;;
9591+;; CONVERSIONS
9592+;;
9593+;; ....................
9594+
9595+(define_insn "fix_truncdfsi2"
9596+ [(set (match_operand:SI 0 "register_operand" "=r")
9597+ (fix:SI (match_operand:DF 1 "register_operand" "f")))]
9598+ "TARGET_HARD_FLOAT"
9599+ "fcvt.w.d %0,%1,rtz"
9600+ [(set_attr "type" "fcvt")
9601+ (set_attr "mode" "DF")
9602+ (set_attr "cnv_mode" "D2I")])
9603+
9604+
9605+(define_insn "fix_truncsfsi2"
9606+ [(set (match_operand:SI 0 "register_operand" "=r")
9607+ (fix:SI (match_operand:SF 1 "register_operand" "f")))]
9608+ "TARGET_HARD_FLOAT"
9609+ "fcvt.w.s %0,%1,rtz"
9610+ [(set_attr "type" "fcvt")
9611+ (set_attr "mode" "SF")
9612+ (set_attr "cnv_mode" "S2I")])
9613+
9614+
9615+(define_insn "fix_truncdfdi2"
9616+ [(set (match_operand:DI 0 "register_operand" "=r")
9617+ (fix:DI (match_operand:DF 1 "register_operand" "f")))]
9618+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9619+ "fcvt.l.d %0,%1,rtz"
9620+ [(set_attr "type" "fcvt")
9621+ (set_attr "mode" "DF")
9622+ (set_attr "cnv_mode" "D2I")])
9623+
9624+
9625+(define_insn "fix_truncsfdi2"
9626+ [(set (match_operand:DI 0 "register_operand" "=r")
9627+ (fix:DI (match_operand:SF 1 "register_operand" "f")))]
9628+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9629+ "fcvt.l.s %0,%1,rtz"
9630+ [(set_attr "type" "fcvt")
9631+ (set_attr "mode" "SF")
9632+ (set_attr "cnv_mode" "S2I")])
9633+
9634+
9635+(define_insn "floatsidf2"
9636+ [(set (match_operand:DF 0 "register_operand" "=f")
9637+ (float:DF (match_operand:SI 1 "reg_or_0_operand" "rJ")))]
9638+ "TARGET_HARD_FLOAT"
9639+ "fcvt.d.w\t%0,%z1"
9640+ [(set_attr "type" "fcvt")
9641+ (set_attr "mode" "DF")
9642+ (set_attr "cnv_mode" "I2D")])
9643+
9644+
9645+(define_insn "floatdidf2"
9646+ [(set (match_operand:DF 0 "register_operand" "=f")
9647+ (float:DF (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
9648+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9649+ "fcvt.d.l\t%0,%z1"
9650+ [(set_attr "type" "fcvt")
9651+ (set_attr "mode" "DF")
9652+ (set_attr "cnv_mode" "I2D")])
9653+
9654+
9655+(define_insn "floatsisf2"
9656+ [(set (match_operand:SF 0 "register_operand" "=f")
9657+ (float:SF (match_operand:SI 1 "reg_or_0_operand" "rJ")))]
9658+ "TARGET_HARD_FLOAT"
9659+ "fcvt.s.w\t%0,%z1"
9660+ [(set_attr "type" "fcvt")
9661+ (set_attr "mode" "SF")
9662+ (set_attr "cnv_mode" "I2S")])
9663+
9664+
9665+(define_insn "floatdisf2"
9666+ [(set (match_operand:SF 0 "register_operand" "=f")
9667+ (float:SF (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
9668+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9669+ "fcvt.s.l\t%0,%z1"
9670+ [(set_attr "type" "fcvt")
9671+ (set_attr "mode" "SF")
9672+ (set_attr "cnv_mode" "I2S")])
9673+
9674+
9675+(define_insn "floatunssidf2"
9676+ [(set (match_operand:DF 0 "register_operand" "=f")
9677+ (unsigned_float:DF (match_operand:SI 1 "reg_or_0_operand" "rJ")))]
9678+ "TARGET_HARD_FLOAT"
9679+ "fcvt.d.wu\t%0,%z1"
9680+ [(set_attr "type" "fcvt")
9681+ (set_attr "mode" "DF")
9682+ (set_attr "cnv_mode" "I2D")])
9683+
9684+
9685+(define_insn "floatunsdidf2"
9686+ [(set (match_operand:DF 0 "register_operand" "=f")
9687+ (unsigned_float:DF (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
9688+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9689+ "fcvt.d.lu\t%0,%z1"
9690+ [(set_attr "type" "fcvt")
9691+ (set_attr "mode" "DF")
9692+ (set_attr "cnv_mode" "I2D")])
9693+
9694+
9695+(define_insn "floatunssisf2"
9696+ [(set (match_operand:SF 0 "register_operand" "=f")
9697+ (unsigned_float:SF (match_operand:SI 1 "reg_or_0_operand" "rJ")))]
9698+ "TARGET_HARD_FLOAT"
9699+ "fcvt.s.wu\t%0,%z1"
9700+ [(set_attr "type" "fcvt")
9701+ (set_attr "mode" "SF")
9702+ (set_attr "cnv_mode" "I2S")])
9703+
9704+
9705+(define_insn "floatunsdisf2"
9706+ [(set (match_operand:SF 0 "register_operand" "=f")
9707+ (unsigned_float:SF (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
9708+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9709+ "fcvt.s.lu\t%0,%z1"
9710+ [(set_attr "type" "fcvt")
9711+ (set_attr "mode" "SF")
9712+ (set_attr "cnv_mode" "I2S")])
9713+
9714+
9715+(define_insn "fixuns_truncdfsi2"
9716+ [(set (match_operand:SI 0 "register_operand" "=r")
9717+ (unsigned_fix:SI (match_operand:DF 1 "register_operand" "f")))]
9718+ "TARGET_HARD_FLOAT"
9719+ "fcvt.wu.d %0,%1,rtz"
9720+ [(set_attr "type" "fcvt")
9721+ (set_attr "mode" "DF")
9722+ (set_attr "cnv_mode" "D2I")])
9723+
9724+
9725+(define_insn "fixuns_truncsfsi2"
9726+ [(set (match_operand:SI 0 "register_operand" "=r")
9727+ (unsigned_fix:SI (match_operand:SF 1 "register_operand" "f")))]
9728+ "TARGET_HARD_FLOAT"
9729+ "fcvt.wu.s %0,%1,rtz"
9730+ [(set_attr "type" "fcvt")
9731+ (set_attr "mode" "SF")
9732+ (set_attr "cnv_mode" "S2I")])
9733+
9734+
9735+(define_insn "fixuns_truncdfdi2"
9736+ [(set (match_operand:DI 0 "register_operand" "=r")
9737+ (unsigned_fix:DI (match_operand:DF 1 "register_operand" "f")))]
9738+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9739+ "fcvt.lu.d %0,%1,rtz"
9740+ [(set_attr "type" "fcvt")
9741+ (set_attr "mode" "DF")
9742+ (set_attr "cnv_mode" "D2I")])
9743+
9744+
9745+(define_insn "fixuns_truncsfdi2"
9746+ [(set (match_operand:DI 0 "register_operand" "=r")
9747+ (unsigned_fix:DI (match_operand:SF 1 "register_operand" "f")))]
9748+ "TARGET_HARD_FLOAT && TARGET_64BIT"
9749+ "fcvt.lu.s %0,%1,rtz"
9750+ [(set_attr "type" "fcvt")
9751+ (set_attr "mode" "SF")
9752+ (set_attr "cnv_mode" "S2I")])
9753+
9754+;;
9755+;; ....................
9756+;;
9757+;; DATA MOVEMENT
9758+;;
9759+;; ....................
9760+
9761+;; Lower-level instructions for loading an address from the GOT.
9762+;; We could use MEMs, but an unspec gives more optimization
9763+;; opportunities.
9764+
9765+(define_insn "got_load<mode>"
9766+ [(set (match_operand:P 0 "register_operand" "=r")
9767+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
9768+ UNSPEC_LOAD_GOT))]
9769+ "flag_pic"
9770+ "la\t%0,%1"
9771+ [(set_attr "got" "load")
9772+ (set_attr "mode" "<MODE>")])
9773+
9774+(define_insn "tls_add_tp_le<mode>"
9775+ [(set (match_operand:P 0 "register_operand" "=r")
9776+ (unspec:P [(match_operand:P 1 "register_operand" "r")
9777+ (match_operand:P 2 "register_operand" "r")
9778+ (match_operand:P 3 "symbolic_operand" "")]
9779+ UNSPEC_TLS_LE))]
9780+ "!flag_pic || flag_pie"
9781+ "add\t%0,%1,%2,%%tprel_add(%3)"
9782+ [(set_attr "type" "arith")
9783+ (set_attr "mode" "<MODE>")])
9784+
9785+(define_insn "got_load_tls_gd<mode>"
9786+ [(set (match_operand:P 0 "register_operand" "=r")
9787+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
9788+ UNSPEC_TLS_GD))]
9789+ "flag_pic"
9790+ "la.tls.gd\t%0,%1"
9791+ [(set_attr "got" "load")
9792+ (set_attr "mode" "<MODE>")])
9793+
9794+(define_insn "got_load_tls_ie<mode>"
9795+ [(set (match_operand:P 0 "register_operand" "=r")
9796+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
9797+ UNSPEC_TLS_IE))]
9798+ "flag_pic"
9799+ "la.tls.ie\t%0,%1"
9800+ [(set_attr "got" "load")
9801+ (set_attr "mode" "<MODE>")])
9802+
9803+;; Instructions for adding the low 16 bits of an address to a register.
9804+;; Operand 2 is the address: riscv_print_operand works out which relocation
9805+;; should be applied.
9806+
9807+(define_insn "*low<mode>"
9808+ [(set (match_operand:P 0 "register_operand" "=r")
9809+ (lo_sum:P (match_operand:P 1 "register_operand" "r")
9810+ (match_operand:P 2 "immediate_operand" "")))]
9811+ ""
9812+ "add\t%0,%1,%R2"
9813+ [(set_attr "alu_type" "add")
9814+ (set_attr "mode" "<MODE>")])
9815+
9816+;; Allow combine to split complex const_int load sequences, using operand 2
9817+;; to store the intermediate results. See move_operand for details.
9818+(define_split
9819+ [(set (match_operand:GPR 0 "register_operand")
9820+ (match_operand:GPR 1 "splittable_const_int_operand"))
9821+ (clobber (match_operand:GPR 2 "register_operand"))]
9822+ ""
9823+ [(const_int 0)]
9824+{
9825+ riscv_move_integer (operands[2], operands[0], INTVAL (operands[1]));
9826+ DONE;
9827+})
9828+
9829+;; Likewise, for symbolic operands.
9830+(define_split
9831+ [(set (match_operand:P 0 "register_operand")
9832+ (match_operand:P 1))
9833+ (clobber (match_operand:P 2 "register_operand"))]
9834+ "riscv_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
9835+ [(set (match_dup 0) (match_dup 3))]
9836+{
9837+ riscv_split_symbol (operands[2], operands[1],
9838+ MAX_MACHINE_MODE, &operands[3]);
9839+})
9840+
9841+;; 64-bit integer moves
9842+
9843+;; Unlike most other insns, the move insns can't be split with '
9844+;; different predicates, because register spilling and other parts of
9845+;; the compiler, have memoized the insn number already.
9846+
9847+(define_expand "movdi"
9848+ [(set (match_operand:DI 0 "")
9849+ (match_operand:DI 1 ""))]
9850+ ""
9851+{
9852+ if (riscv_legitimize_move (DImode, operands[0], operands[1]))
9853+ DONE;
9854+})
9855+
9856+(define_insn "*movdi_32bit"
9857+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m")
9858+ (match_operand:DI 1 "move_operand" "r,i,m,r,*J*r,*m,*f,*f"))]
9859+ "!TARGET_64BIT
9860+ && (register_operand (operands[0], DImode)
9861+ || reg_or_0_operand (operands[1], DImode))"
9862+ { return riscv_output_move (operands[0], operands[1]); }
9863+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
9864+ (set_attr "mode" "DI")])
9865+
9866+(define_insn "*movdi_64bit"
9867+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m")
9868+ (match_operand:DI 1 "move_operand" "r,T,m,rJ,*r*J,*m,*f,*f"))]
9869+ "TARGET_64BIT
9870+ && (register_operand (operands[0], DImode)
9871+ || reg_or_0_operand (operands[1], DImode))"
9872+ { return riscv_output_move (operands[0], operands[1]); }
9873+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
9874+ (set_attr "mode" "DI")])
9875+
9876+;; 32-bit Integer moves
9877+
9878+;; Unlike most other insns, the move insns can't be split with
9879+;; different predicates, because register spilling and other parts of
9880+;; the compiler, have memoized the insn number already.
9881+
9882+(define_expand "mov<mode>"
9883+ [(set (match_operand:IMOVE32 0 "")
9884+ (match_operand:IMOVE32 1 ""))]
9885+ ""
9886+{
9887+ if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
9888+ DONE;
9889+})
9890+
Patrick Georgif0bbc952015-03-07 10:57:25 +01009891+(define_insn "*mov<mode>_internal"
9892+ [(set (match_operand:IMOVE32 0 "nonimmediate_operand" "=r,r,r,m,*f,*f,*r,*m")
9893+ (match_operand:IMOVE32 1 "move_operand" "r,T,m,rJ,*r*J,*m,*f,*f"))]
9894+ "(register_operand (operands[0], <MODE>mode)
9895+ || reg_or_0_operand (operands[1], <MODE>mode))"
9896+ { return riscv_output_move (operands[0], operands[1]); }
9897+ [(set_attr "move_type" "move,const,load,store,mtc,fpload,mfc,fpstore")
9898+ (set_attr "mode" "SI")])
9899+
9900+;; 16-bit Integer moves
9901+
9902+;; Unlike most other insns, the move insns can't be split with
9903+;; different predicates, because register spilling and other parts of
9904+;; the compiler, have memoized the insn number already.
9905+;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
9906+
9907+(define_expand "movhi"
9908+ [(set (match_operand:HI 0 "")
9909+ (match_operand:HI 1 ""))]
9910+ ""
9911+{
9912+ if (riscv_legitimize_move (HImode, operands[0], operands[1]))
9913+ DONE;
9914+})
9915+
9916+(define_insn "*movhi_internal"
9917+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
9918+ (match_operand:HI 1 "move_operand" "r,T,m,rJ,*r*J,*f"))]
9919+ "(register_operand (operands[0], HImode)
9920+ || reg_or_0_operand (operands[1], HImode))"
9921+ { return riscv_output_move (operands[0], operands[1]); }
9922+ [(set_attr "move_type" "move,const,load,store,mtc,mfc")
9923+ (set_attr "mode" "HI")])
9924+
9925+;; HImode constant generation; see riscv_move_integer for details.
9926+;; si+si->hi without truncation is legal because of TRULY_NOOP_TRUNCATION.
9927+
9928+(define_insn "add<mode>hi3"
9929+ [(set (match_operand:HI 0 "register_operand" "=r,r")
9930+ (plus:HI (match_operand:HISI 1 "register_operand" "r,r")
9931+ (match_operand:HISI 2 "arith_operand" "r,Q")))]
9932+ ""
9933+ { return TARGET_64BIT ? "addw\t%0,%1,%2" : "add\t%0,%1,%2"; }
9934+ [(set_attr "type" "arith")
9935+ (set_attr "mode" "HI")])
9936+
9937+(define_insn "xor<mode>hi3"
9938+ [(set (match_operand:HI 0 "register_operand" "=r,r")
9939+ (xor:HI (match_operand:HISI 1 "register_operand" "r,r")
9940+ (match_operand:HISI 2 "arith_operand" "r,Q")))]
9941+ ""
9942+ "xor\t%0,%1,%2"
9943+ [(set_attr "type" "logical")
9944+ (set_attr "mode" "HI")])
9945+
9946+;; 8-bit Integer moves
9947+
9948+(define_expand "movqi"
9949+ [(set (match_operand:QI 0 "")
9950+ (match_operand:QI 1 ""))]
9951+ ""
9952+{
9953+ if (riscv_legitimize_move (QImode, operands[0], operands[1]))
9954+ DONE;
9955+})
9956+
9957+(define_insn "*movqi_internal"
9958+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m,*f,*r")
9959+ (match_operand:QI 1 "move_operand" "r,I,m,rJ,*r*J,*f"))]
9960+ "(register_operand (operands[0], QImode)
9961+ || reg_or_0_operand (operands[1], QImode))"
9962+ { return riscv_output_move (operands[0], operands[1]); }
9963+ [(set_attr "move_type" "move,const,load,store,mtc,mfc")
9964+ (set_attr "mode" "QI")])
9965+
9966+;; 32-bit floating point moves
9967+
9968+(define_expand "movsf"
9969+ [(set (match_operand:SF 0 "")
9970+ (match_operand:SF 1 ""))]
9971+ ""
9972+{
9973+ if (riscv_legitimize_move (SFmode, operands[0], operands[1]))
9974+ DONE;
9975+})
9976+
9977+(define_insn "*movsf_hardfloat"
9978+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m")
9979+ (match_operand:SF 1 "move_operand" "f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
9980+ "TARGET_HARD_FLOAT
9981+ && (register_operand (operands[0], SFmode)
9982+ || reg_or_0_operand (operands[1], SFmode))"
9983+ { return riscv_output_move (operands[0], operands[1]); }
9984+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
9985+ (set_attr "mode" "SF")])
9986+
9987+(define_insn "*movsf_softfloat"
9988+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
9989+ (match_operand:SF 1 "move_operand" "Gr,m,r"))]
9990+ "TARGET_SOFT_FLOAT
9991+ && (register_operand (operands[0], SFmode)
9992+ || reg_or_0_operand (operands[1], SFmode))"
9993+ { return riscv_output_move (operands[0], operands[1]); }
9994+ [(set_attr "move_type" "move,load,store")
9995+ (set_attr "mode" "SF")])
9996+
9997+;; 64-bit floating point moves
9998+
9999+(define_expand "movdf"
10000+ [(set (match_operand:DF 0 "")
10001+ (match_operand:DF 1 ""))]
10002+ ""
10003+{
10004+ if (riscv_legitimize_move (DFmode, operands[0], operands[1]))
10005+ DONE;
10006+})
10007+
10008+;; In RV32, we lack mtf.d/mff.d. Go through memory instead.
10009+;; (except for moving a constant 0 to an FPR. for that we use fcvt.d.w.)
10010+(define_insn "*movdf_hardfloat_rv32"
10011+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*r,*r,*m")
10012+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r*G,*m,*r"))]
10013+ "!TARGET_64BIT && TARGET_HARD_FLOAT
10014+ && (register_operand (operands[0], DFmode)
10015+ || reg_or_0_operand (operands[1], DFmode))"
10016+ { return riscv_output_move (operands[0], operands[1]); }
10017+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store")
10018+ (set_attr "mode" "DF")])
10019+
10020+(define_insn "*movdf_hardfloat_rv64"
10021+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,*r,*r,*m")
10022+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*r,*f,*r*G,*m,*r"))]
10023+ "TARGET_64BIT && TARGET_HARD_FLOAT
10024+ && (register_operand (operands[0], DFmode)
10025+ || reg_or_0_operand (operands[1], DFmode))"
10026+ { return riscv_output_move (operands[0], operands[1]); }
10027+ [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
10028+ (set_attr "mode" "DF")])
10029+
10030+(define_insn "*movdf_softfloat"
10031+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
10032+ (match_operand:DF 1 "move_operand" "rG,m,rG"))]
10033+ "TARGET_SOFT_FLOAT
10034+ && (register_operand (operands[0], DFmode)
10035+ || reg_or_0_operand (operands[1], DFmode))"
10036+ { return riscv_output_move (operands[0], operands[1]); }
10037+ [(set_attr "move_type" "move,load,store")
10038+ (set_attr "mode" "DF")])
10039+
10040+;; 128-bit integer moves
10041+
10042+(define_expand "movti"
10043+ [(set (match_operand:TI 0)
10044+ (match_operand:TI 1))]
10045+ "TARGET_64BIT"
10046+{
10047+ if (riscv_legitimize_move (TImode, operands[0], operands[1]))
10048+ DONE;
10049+})
10050+
10051+(define_insn "*movti"
10052+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,r,m")
10053+ (match_operand:TI 1 "move_operand" "r,i,m,rJ"))]
10054+ "TARGET_64BIT
10055+ && (register_operand (operands[0], TImode)
10056+ || reg_or_0_operand (operands[1], TImode))"
10057+ "#"
10058+ [(set_attr "move_type" "move,const,load,store")
10059+ (set_attr "mode" "TI")])
10060+
10061+(define_split
10062+ [(set (match_operand:MOVE64 0 "nonimmediate_operand")
10063+ (match_operand:MOVE64 1 "move_operand"))]
10064+ "reload_completed && !TARGET_64BIT
10065+ && riscv_split_64bit_move_p (operands[0], operands[1])"
10066+ [(const_int 0)]
10067+{
10068+ riscv_split_doubleword_move (operands[0], operands[1]);
10069+ DONE;
10070+})
10071+
10072+(define_split
10073+ [(set (match_operand:MOVE128 0 "nonimmediate_operand")
10074+ (match_operand:MOVE128 1 "move_operand"))]
10075+ "TARGET_64BIT && reload_completed"
10076+ [(const_int 0)]
10077+{
10078+ riscv_split_doubleword_move (operands[0], operands[1]);
10079+ DONE;
10080+})
10081+
10082+;; 64-bit paired-single floating point moves
10083+
10084+;; Load the low word of operand 0 with operand 1.
10085+(define_insn "load_low<mode>"
10086+ [(set (match_operand:SPLITF 0 "register_operand" "=f,f")
10087+ (unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "rJ,m")]
10088+ UNSPEC_LOAD_LOW))]
10089+ "TARGET_HARD_FLOAT"
10090+{
10091+ operands[0] = riscv_subword (operands[0], 0);
10092+ return riscv_output_move (operands[0], operands[1]);
10093+}
10094+ [(set_attr "move_type" "mtc,fpload")
10095+ (set_attr "mode" "<HALFMODE>")])
10096+
10097+;; Load the high word of operand 0 from operand 1, preserving the value
10098+;; in the low word.
10099+(define_insn "load_high<mode>"
10100+ [(set (match_operand:SPLITF 0 "register_operand" "=f,f")
10101+ (unspec:SPLITF [(match_operand:<HALFMODE> 1 "general_operand" "rJ,m")
10102+ (match_operand:SPLITF 2 "register_operand" "0,0")]
10103+ UNSPEC_LOAD_HIGH))]
10104+ "TARGET_HARD_FLOAT"
10105+{
10106+ operands[0] = riscv_subword (operands[0], 1);
10107+ return riscv_output_move (operands[0], operands[1]);
10108+}
10109+ [(set_attr "move_type" "mtc,fpload")
10110+ (set_attr "mode" "<HALFMODE>")])
10111+
10112+;; Store one word of operand 1 in operand 0. Operand 2 is 1 to store the
10113+;; high word and 0 to store the low word.
10114+(define_insn "store_word<mode>"
10115+ [(set (match_operand:<HALFMODE> 0 "nonimmediate_operand" "=r,m")
10116+ (unspec:<HALFMODE> [(match_operand:SPLITF 1 "register_operand" "f,f")
10117+ (match_operand 2 "const_int_operand")]
10118+ UNSPEC_STORE_WORD))]
10119+ "TARGET_HARD_FLOAT"
10120+{
10121+ operands[1] = riscv_subword (operands[1], INTVAL (operands[2]));
10122+ return riscv_output_move (operands[0], operands[1]);
10123+}
10124+ [(set_attr "move_type" "mfc,fpstore")
10125+ (set_attr "mode" "<HALFMODE>")])
10126+
10127+;; Expand in-line code to clear the instruction cache between operand[0] and
10128+;; operand[1].
10129+(define_expand "clear_cache"
10130+ [(match_operand 0 "pmode_register_operand")
10131+ (match_operand 1 "pmode_register_operand")]
10132+ ""
10133+ "
10134+{
10135+ emit_insn(gen_fence_i());
10136+ DONE;
10137+}")
10138+
10139+(define_insn "fence"
10140+ [(unspec_volatile [(const_int 0)] UNSPEC_FENCE)]
10141+ ""
10142+ "%|fence%-")
10143+
10144+(define_insn "fence_i"
10145+ [(unspec_volatile [(const_int 0)] UNSPEC_FENCE_I)]
10146+ ""
10147+ "fence.i")
10148+
10149+;; Block moves, see riscv.c for more details.
10150+;; Argument 0 is the destination
10151+;; Argument 1 is the source
10152+;; Argument 2 is the length
10153+;; Argument 3 is the alignment
10154+
10155+(define_expand "movmemsi"
10156+ [(parallel [(set (match_operand:BLK 0 "general_operand")
10157+ (match_operand:BLK 1 "general_operand"))
10158+ (use (match_operand:SI 2 ""))
10159+ (use (match_operand:SI 3 "const_int_operand"))])]
10160+ "!TARGET_MEMCPY"
10161+{
10162+ if (riscv_expand_block_move (operands[0], operands[1], operands[2]))
10163+ DONE;
10164+ else
10165+ FAIL;
10166+})
10167+
10168+;;
10169+;; ....................
10170+;;
10171+;; SHIFTS
10172+;;
10173+;; ....................
10174+
10175+(define_insn "<optab>si3"
10176+ [(set (match_operand:SI 0 "register_operand" "=r")
10177+ (any_shift:SI (match_operand:SI 1 "register_operand" "r")
10178+ (match_operand:SI 2 "arith_operand" "rI")))]
10179+ ""
10180+{
10181+ if (GET_CODE (operands[2]) == CONST_INT)
10182+ operands[2] = GEN_INT (INTVAL (operands[2])
10183+ & (GET_MODE_BITSIZE (SImode) - 1));
10184+
10185+ return TARGET_64BIT ? "<insn>w\t%0,%1,%2" : "<insn>\t%0,%1,%2";
10186+}
10187+ [(set_attr "type" "shift")
10188+ (set_attr "mode" "SI")])
10189+
10190+(define_insn "*<optab>disi3"
10191+ [(set (match_operand:SI 0 "register_operand" "=r")
10192+ (any_shift:SI (truncate:SI (match_operand:DI 1 "register_operand" "r"))
10193+ (truncate:SI (match_operand:DI 2 "arith_operand" "rI"))))]
10194+ "TARGET_64BIT"
10195+ "<insn>w\t%0,%1,%2"
10196+ [(set_attr "type" "shift")
10197+ (set_attr "mode" "SI")])
10198+
10199+(define_insn "*ashldi3_truncsi"
10200+ [(set (match_operand:SI 0 "register_operand" "=r")
10201+ (truncate:SI
10202+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
10203+ (match_operand:DI 2 "const_arith_operand" "I"))))]
10204+ "TARGET_64BIT && INTVAL (operands[2]) < 32"
10205+ "sllw\t%0,%1,%2"
10206+ [(set_attr "type" "shift")
10207+ (set_attr "mode" "SI")])
10208+
10209+(define_insn "*ashldisi3"
10210+ [(set (match_operand:SI 0 "register_operand" "=r")
10211+ (ashift:SI (match_operand:GPR 1 "register_operand" "r")
10212+ (match_operand:GPR2 2 "arith_operand" "rI")))]
10213+ "TARGET_64BIT && (GET_CODE (operands[2]) == CONST_INT ? INTVAL (operands[2]) < 32 : 1)"
10214+ "sllw\t%0,%1,%2"
10215+ [(set_attr "type" "shift")
10216+ (set_attr "mode" "SI")])
10217+
10218+(define_insn "<optab>di3"
10219+ [(set (match_operand:DI 0 "register_operand" "=r")
10220+ (any_shift:DI (match_operand:DI 1 "register_operand" "r")
10221+ (match_operand:DI 2 "arith_operand" "rI")))]
10222+ "TARGET_64BIT"
10223+{
10224+ if (GET_CODE (operands[2]) == CONST_INT)
10225+ operands[2] = GEN_INT (INTVAL (operands[2])
10226+ & (GET_MODE_BITSIZE (DImode) - 1));
10227+
10228+ return "<insn>\t%0,%1,%2";
10229+}
10230+ [(set_attr "type" "shift")
10231+ (set_attr "mode" "DI")])
10232+
10233+(define_insn "<optab>si3_extend"
10234+ [(set (match_operand:DI 0 "register_operand" "=r")
10235+ (sign_extend:DI
10236+ (any_shift:SI (match_operand:SI 1 "register_operand" "r")
10237+ (match_operand:SI 2 "arith_operand" "rI"))))]
10238+ "TARGET_64BIT"
10239+{
10240+ if (GET_CODE (operands[2]) == CONST_INT)
10241+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
10242+
10243+ return "<insn>w\t%0,%1,%2";
10244+}
10245+ [(set_attr "type" "shift")
10246+ (set_attr "mode" "SI")])
10247+
10248+;;
10249+;; ....................
10250+;;
10251+;; CONDITIONAL BRANCHES
10252+;;
10253+;; ....................
10254+
10255+;; Conditional branches
10256+
10257+(define_insn "*branch_order<mode>"
10258+ [(set (pc)
10259+ (if_then_else
10260+ (match_operator 1 "order_operator"
10261+ [(match_operand:GPR 2 "register_operand" "r")
10262+ (match_operand:GPR 3 "reg_or_0_operand" "rJ")])
10263+ (label_ref (match_operand 0 "" ""))
10264+ (pc)))]
10265+ ""
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010266+{
10267+ if (GET_CODE (operands[3]) == CONST_INT)
10268+ return "b%C1z\t%2,%0";
10269+ return "b%C1\t%2,%3,%0";
10270+}
Patrick Georgif0bbc952015-03-07 10:57:25 +010010271+ [(set_attr "type" "branch")
10272+ (set_attr "mode" "none")])
10273+
10274+;; Used to implement built-in functions.
10275+(define_expand "condjump"
10276+ [(set (pc)
10277+ (if_then_else (match_operand 0)
10278+ (label_ref (match_operand 1))
10279+ (pc)))])
10280+
10281+(define_expand "cbranch<mode>4"
10282+ [(set (pc)
10283+ (if_then_else (match_operator 0 "comparison_operator"
10284+ [(match_operand:GPR 1 "register_operand")
10285+ (match_operand:GPR 2 "nonmemory_operand")])
10286+ (label_ref (match_operand 3 ""))
10287+ (pc)))]
10288+ ""
10289+{
10290+ riscv_expand_conditional_branch (operands);
10291+ DONE;
10292+})
10293+
10294+(define_expand "cbranch<mode>4"
10295+ [(set (pc)
10296+ (if_then_else (match_operator 0 "comparison_operator"
10297+ [(match_operand:SCALARF 1 "register_operand")
10298+ (match_operand:SCALARF 2 "register_operand")])
10299+ (label_ref (match_operand 3 ""))
10300+ (pc)))]
10301+ ""
10302+{
10303+ riscv_expand_conditional_branch (operands);
10304+ DONE;
10305+})
10306+
10307+(define_insn_and_split "*branch_on_bit<GPR:mode>"
10308+ [(set (pc)
10309+ (if_then_else
10310+ (match_operator 0 "equality_operator"
10311+ [(zero_extract:GPR (match_operand:GPR 2 "register_operand" "r")
10312+ (const_int 1)
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010313+ (match_operand 3 "branch_on_bit_operand"))
Patrick Georgif0bbc952015-03-07 10:57:25 +010010314+ (const_int 0)])
10315+ (label_ref (match_operand 1))
10316+ (pc)))
10317+ (clobber (match_scratch:GPR 4 "=&r"))]
10318+ ""
10319+ "#"
10320+ "reload_completed"
10321+ [(set (match_dup 4)
10322+ (ashift:GPR (match_dup 2) (match_dup 3)))
10323+ (set (pc)
10324+ (if_then_else
10325+ (match_op_dup 0 [(match_dup 4) (const_int 0)])
10326+ (label_ref (match_operand 1))
10327+ (pc)))]
10328+{
10329+ int shift = GET_MODE_BITSIZE (<MODE>mode) - 1 - INTVAL (operands[3]);
10330+ operands[3] = GEN_INT (shift);
10331+
10332+ if (GET_CODE (operands[0]) == EQ)
10333+ operands[0] = gen_rtx_GE (<MODE>mode, operands[4], const0_rtx);
10334+ else
10335+ operands[0] = gen_rtx_LT (<MODE>mode, operands[4], const0_rtx);
10336+})
10337+
10338+(define_insn_and_split "*branch_on_bit_range<GPR:mode>"
10339+ [(set (pc)
10340+ (if_then_else
10341+ (match_operator 0 "equality_operator"
10342+ [(zero_extract:GPR (match_operand:GPR 2 "register_operand" "r")
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010343+ (match_operand 3 "branch_on_bit_operand")
Patrick Georgif0bbc952015-03-07 10:57:25 +010010344+ (const_int 0))
10345+ (const_int 0)])
10346+ (label_ref (match_operand 1))
10347+ (pc)))
10348+ (clobber (match_scratch:GPR 4 "=&r"))]
10349+ ""
10350+ "#"
10351+ "reload_completed"
10352+ [(set (match_dup 4)
10353+ (ashift:GPR (match_dup 2) (match_dup 3)))
10354+ (set (pc)
10355+ (if_then_else
10356+ (match_op_dup 0 [(match_dup 4) (const_int 0)])
10357+ (label_ref (match_operand 1))
10358+ (pc)))]
10359+{
10360+ operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]));
10361+})
10362+
10363+;;
10364+;; ....................
10365+;;
10366+;; SETTING A REGISTER FROM A COMPARISON
10367+;;
10368+;; ....................
10369+
10370+;; Destination is always set in SI mode.
10371+
10372+(define_expand "cstore<mode>4"
10373+ [(set (match_operand:SI 0 "register_operand")
10374+ (match_operator:SI 1 "order_operator"
10375+ [(match_operand:GPR 2 "register_operand")
10376+ (match_operand:GPR 3 "nonmemory_operand")]))]
10377+ ""
10378+{
10379+ riscv_expand_scc (operands);
10380+ DONE;
10381+})
10382+
10383+(define_insn "cstore<mode>4"
10384+ [(set (match_operand:SI 0 "register_operand" "=r")
10385+ (match_operator:SI 1 "fp_order_operator"
10386+ [(match_operand:SCALARF 2 "register_operand" "f")
10387+ (match_operand:SCALARF 3 "register_operand" "f")]))]
10388+ "TARGET_HARD_FLOAT"
10389+ "f%C1.<fmt>\t%0,%2,%3"
10390+ [(set_attr "type" "fcmp")
10391+ (set_attr "mode" "<UNITMODE>")])
10392+
10393+(define_insn "*seq_zero_<GPR:mode><GPR2:mode>"
10394+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10395+ (eq:GPR2 (match_operand:GPR 1 "register_operand" "r")
10396+ (const_int 0)))]
10397+ ""
10398+ "seqz\t%0,%1"
10399+ [(set_attr "type" "slt")
10400+ (set_attr "mode" "<GPR:MODE>")])
10401+
10402+(define_insn "*sne_zero_<GPR:mode><GPR2:mode>"
10403+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10404+ (ne:GPR2 (match_operand:GPR 1 "register_operand" "r")
10405+ (const_int 0)))]
10406+ ""
10407+ "snez\t%0,%1"
10408+ [(set_attr "type" "slt")
10409+ (set_attr "mode" "<GPR:MODE>")])
10410+
10411+(define_insn "*sgt<u>_<GPR:mode><GPR2:mode>"
10412+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10413+ (any_gt:GPR2 (match_operand:GPR 1 "register_operand" "r")
10414+ (match_operand:GPR 2 "reg_or_0_operand" "rJ")))]
10415+ ""
10416+ "slt<u>\t%0,%z2,%1"
10417+ [(set_attr "type" "slt")
10418+ (set_attr "mode" "<GPR:MODE>")])
10419+
10420+(define_insn "*sge<u>_<GPR:mode><GPR2:mode>"
10421+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10422+ (any_ge:GPR2 (match_operand:GPR 1 "register_operand" "r")
10423+ (const_int 1)))]
10424+ ""
10425+ "slt<u>\t%0,zero,%1"
10426+ [(set_attr "type" "slt")
10427+ (set_attr "mode" "<GPR:MODE>")])
10428+
10429+(define_insn "*slt<u>_<GPR:mode><GPR2:mode>"
10430+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10431+ (any_lt:GPR2 (match_operand:GPR 1 "register_operand" "r")
10432+ (match_operand:GPR 2 "arith_operand" "rI")))]
10433+ ""
10434+ "slt<u>\t%0,%1,%2"
10435+ [(set_attr "type" "slt")
10436+ (set_attr "mode" "<GPR:MODE>")])
10437+
10438+(define_insn "*sle<u>_<GPR:mode><GPR2:mode>"
10439+ [(set (match_operand:GPR2 0 "register_operand" "=r")
10440+ (any_le:GPR2 (match_operand:GPR 1 "register_operand" "r")
10441+ (match_operand:GPR 2 "sle_operand" "")))]
10442+ ""
10443+{
10444+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
10445+ return "slt<u>\t%0,%1,%2";
10446+}
10447+ [(set_attr "type" "slt")
10448+ (set_attr "mode" "<GPR:MODE>")])
10449+
10450+;;
10451+;; ....................
10452+;;
10453+;; UNCONDITIONAL BRANCHES
10454+;;
10455+;; ....................
10456+
10457+;; Unconditional branches.
10458+
10459+(define_insn "jump"
10460+ [(set (pc)
10461+ (label_ref (match_operand 0 "" "")))]
10462+ ""
10463+ "j\t%l0"
10464+ [(set_attr "type" "jump")
10465+ (set_attr "mode" "none")])
10466+
10467+(define_expand "indirect_jump"
10468+ [(set (pc) (match_operand 0 "register_operand"))]
10469+ ""
10470+{
10471+ operands[0] = force_reg (Pmode, operands[0]);
10472+ if (Pmode == SImode)
10473+ emit_jump_insn (gen_indirect_jumpsi (operands[0]));
10474+ else
10475+ emit_jump_insn (gen_indirect_jumpdi (operands[0]));
10476+ DONE;
10477+})
10478+
10479+(define_insn "indirect_jump<mode>"
10480+ [(set (pc) (match_operand:P 0 "register_operand" "r"))]
10481+ ""
10482+ "jr\t%0"
10483+ [(set_attr "type" "jump")
10484+ (set_attr "mode" "none")])
10485+
10486+(define_expand "tablejump"
10487+ [(set (pc) (match_operand 0 "register_operand" ""))
10488+ (use (label_ref (match_operand 1 "" "")))]
10489+ ""
10490+{
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010491+ if (CASE_VECTOR_PC_RELATIVE)
Patrick Georgif0bbc952015-03-07 10:57:25 +010010492+ operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
10493+ gen_rtx_LABEL_REF (Pmode, operands[1]),
10494+ NULL_RTX, 0, OPTAB_DIRECT);
10495+
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010496+ if (CASE_VECTOR_PC_RELATIVE && Pmode == DImode)
Patrick Georgif0bbc952015-03-07 10:57:25 +010010497+ emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
10498+ else
10499+ emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
10500+ DONE;
10501+})
10502+
10503+(define_insn "tablejump<mode>"
10504+ [(set (pc) (match_operand:GPR 0 "register_operand" "r"))
10505+ (use (label_ref (match_operand 1 "" "")))]
10506+ ""
10507+ "jr\t%0"
10508+ [(set_attr "type" "jump")
10509+ (set_attr "mode" "none")])
10510+
10511+;;
10512+;; ....................
10513+;;
10514+;; Function prologue/epilogue
10515+;;
10516+;; ....................
10517+;;
10518+
10519+(define_expand "prologue"
10520+ [(const_int 1)]
10521+ ""
10522+{
10523+ riscv_expand_prologue ();
10524+ DONE;
10525+})
10526+
10527+;; Block any insns from being moved before this point, since the
10528+;; profiling call to mcount can use various registers that aren't
10529+;; saved or used to pass arguments.
10530+
10531+(define_insn "blockage"
10532+ [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
10533+ ""
10534+ ""
10535+ [(set_attr "type" "ghost")
10536+ (set_attr "mode" "none")])
10537+
10538+(define_expand "epilogue"
10539+ [(const_int 2)]
10540+ ""
10541+{
10542+ riscv_expand_epilogue (false);
10543+ DONE;
10544+})
10545+
10546+(define_expand "sibcall_epilogue"
10547+ [(const_int 2)]
10548+ ""
10549+{
10550+ riscv_expand_epilogue (true);
10551+ DONE;
10552+})
10553+
10554+;; Trivial return. Make it look like a normal return insn as that
10555+;; allows jump optimizations to work better.
10556+
10557+(define_expand "return"
10558+ [(simple_return)]
10559+ "riscv_can_use_return_insn ()"
10560+ "")
10561+
10562+(define_insn "simple_return"
10563+ [(simple_return)]
10564+ ""
10565+ "ret"
10566+ [(set_attr "type" "jump")
10567+ (set_attr "mode" "none")])
10568+
10569+;; Normal return.
10570+
10571+(define_insn "simple_return_internal"
10572+ [(simple_return)
10573+ (use (match_operand 0 "pmode_register_operand" ""))]
10574+ ""
10575+ "jr\t%0"
10576+ [(set_attr "type" "jump")
10577+ (set_attr "mode" "none")])
10578+
10579+;; This is used in compiling the unwind routines.
10580+(define_expand "eh_return"
10581+ [(use (match_operand 0 "general_operand"))]
10582+ ""
10583+{
10584+ if (GET_MODE (operands[0]) != word_mode)
10585+ operands[0] = convert_to_mode (word_mode, operands[0], 0);
10586+ if (TARGET_64BIT)
10587+ emit_insn (gen_eh_set_lr_di (operands[0]));
10588+ else
10589+ emit_insn (gen_eh_set_lr_si (operands[0]));
10590+ DONE;
10591+})
10592+
10593+;; Clobber the return address on the stack. We can't expand this
10594+;; until we know where it will be put in the stack frame.
10595+
10596+(define_insn "eh_set_lr_si"
10597+ [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
10598+ (clobber (match_scratch:SI 1 "=&r"))]
10599+ "! TARGET_64BIT"
10600+ "#")
10601+
10602+(define_insn "eh_set_lr_di"
10603+ [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
10604+ (clobber (match_scratch:DI 1 "=&r"))]
10605+ "TARGET_64BIT"
10606+ "#")
10607+
10608+(define_split
10609+ [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
10610+ (clobber (match_scratch 1))]
10611+ "reload_completed"
10612+ [(const_int 0)]
10613+{
10614+ riscv_set_return_address (operands[0], operands[1]);
10615+ DONE;
10616+})
10617+
10618+;;
10619+;; ....................
10620+;;
10621+;; FUNCTION CALLS
10622+;;
10623+;; ....................
10624+
10625+;; Sibling calls. All these patterns use jump instructions.
10626+
10627+;; call_insn_operand will only accept constant
10628+;; addresses if a direct jump is acceptable. Since the 'S' constraint
10629+;; is defined in terms of call_insn_operand, the same is true of the
10630+;; constraints.
10631+
10632+;; When we use an indirect jump, we need a register that will be
10633+;; preserved by the epilogue (constraint j).
10634+
10635+(define_expand "sibcall"
10636+ [(parallel [(call (match_operand 0 "")
10637+ (match_operand 1 ""))
10638+ (use (match_operand 2 "")) ;; next_arg_reg
10639+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx
10640+ ""
10641+{
10642+ riscv_expand_call (true, NULL_RTX, XEXP (operands[0], 0), operands[1]);
10643+ DONE;
10644+})
10645+
10646+(define_insn "sibcall_internal"
10647+ [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
10648+ (match_operand 1 "" ""))]
10649+ "SIBLING_CALL_P (insn)"
10650+ { return REG_P (operands[0]) ? "jr\t%0"
10651+ : absolute_symbolic_operand (operands[0], VOIDmode) ? "tail\t%0"
10652+ : "tail\t%0@"; }
10653+ [(set_attr "type" "call")])
10654+
10655+(define_expand "sibcall_value"
10656+ [(parallel [(set (match_operand 0 "")
10657+ (call (match_operand 1 "")
10658+ (match_operand 2 "")))
10659+ (use (match_operand 3 ""))])] ;; next_arg_reg
10660+ ""
10661+{
10662+ riscv_expand_call (true, operands[0], XEXP (operands[1], 0), operands[2]);
10663+ DONE;
10664+})
10665+
10666+(define_insn "sibcall_value_internal"
10667+ [(set (match_operand 0 "register_operand" "")
10668+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
10669+ (match_operand 2 "" "")))]
10670+ "SIBLING_CALL_P (insn)"
10671+ { return REG_P (operands[1]) ? "jr\t%1"
10672+ : absolute_symbolic_operand (operands[1], VOIDmode) ? "tail\t%1"
10673+ : "tail\t%1@"; }
10674+ [(set_attr "type" "call")])
10675+
10676+(define_insn "sibcall_value_multiple_internal"
10677+ [(set (match_operand 0 "register_operand" "")
10678+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
10679+ (match_operand 2 "" "")))
10680+ (set (match_operand 3 "register_operand" "")
10681+ (call (mem:SI (match_dup 1))
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010682+ (match_dup 2)))]
Patrick Georgif0bbc952015-03-07 10:57:25 +010010683+ "SIBLING_CALL_P (insn)"
10684+ { return REG_P (operands[1]) ? "jr\t%1"
10685+ : absolute_symbolic_operand (operands[1], VOIDmode) ? "tail\t%1"
10686+ : "tail\t%1@"; }
10687+ [(set_attr "type" "call")])
10688+
10689+(define_expand "call"
10690+ [(parallel [(call (match_operand 0 "")
10691+ (match_operand 1 ""))
10692+ (use (match_operand 2 "")) ;; next_arg_reg
10693+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx
10694+ ""
10695+{
10696+ riscv_expand_call (false, NULL_RTX, XEXP (operands[0], 0), operands[1]);
10697+ DONE;
10698+})
10699+
10700+(define_insn "call_internal"
10701+ [(call (mem:SI (match_operand 0 "call_insn_operand" "r,S"))
10702+ (match_operand 1 "" ""))
10703+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
10704+ ""
10705+ { return REG_P (operands[0]) ? "jalr\t%0"
10706+ : absolute_symbolic_operand (operands[0], VOIDmode) ? "call\t%0"
10707+ : "call\t%0@"; }
10708+ [(set_attr "jal" "indirect,direct")])
10709+
10710+(define_expand "call_value"
10711+ [(parallel [(set (match_operand 0 "")
10712+ (call (match_operand 1 "")
10713+ (match_operand 2 "")))
10714+ (use (match_operand 3 ""))])] ;; next_arg_reg
10715+ ""
10716+{
10717+ riscv_expand_call (false, operands[0], XEXP (operands[1], 0), operands[2]);
10718+ DONE;
10719+})
10720+
10721+;; See comment for call_internal.
10722+(define_insn "call_value_internal"
10723+ [(set (match_operand 0 "register_operand" "")
10724+ (call (mem:SI (match_operand 1 "call_insn_operand" "r,S"))
10725+ (match_operand 2 "" "")))
10726+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
10727+ ""
10728+ { return REG_P (operands[1]) ? "jalr\t%1"
10729+ : absolute_symbolic_operand (operands[1], VOIDmode) ? "call\t%1"
10730+ : "call\t%1@"; }
10731+ [(set_attr "jal" "indirect,direct")])
10732+
10733+;; See comment for call_internal.
10734+(define_insn "call_value_multiple_internal"
10735+ [(set (match_operand 0 "register_operand" "")
10736+ (call (mem:SI (match_operand 1 "call_insn_operand" "r,S"))
10737+ (match_operand 2 "" "")))
10738+ (set (match_operand 3 "register_operand" "")
10739+ (call (mem:SI (match_dup 1))
10740+ (match_dup 2)))
10741+ (clobber (reg:SI RETURN_ADDR_REGNUM))]
10742+ ""
10743+ { return REG_P (operands[1]) ? "jalr\t%1"
10744+ : absolute_symbolic_operand (operands[1], VOIDmode) ? "call\t%1"
10745+ : "call\t%1@"; }
10746+ [(set_attr "jal" "indirect,direct")])
10747+
10748+;; Call subroutine returning any type.
10749+
10750+(define_expand "untyped_call"
10751+ [(parallel [(call (match_operand 0 "")
10752+ (const_int 0))
10753+ (match_operand 1 "")
10754+ (match_operand 2 "")])]
10755+ ""
10756+{
10757+ int i;
10758+
10759+ emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
10760+
10761+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
10762+ {
10763+ rtx set = XVECEXP (operands[2], 0, i);
10764+ riscv_emit_move (SET_DEST (set), SET_SRC (set));
10765+ }
10766+
10767+ emit_insn (gen_blockage ());
10768+ DONE;
10769+})
10770+
10771+(define_insn "nop"
10772+ [(const_int 0)]
10773+ ""
10774+ "nop"
10775+ [(set_attr "type" "nop")
10776+ (set_attr "mode" "none")])
10777+
10778+(define_insn "trap"
10779+ [(trap_if (const_int 1) (const_int 0))]
10780+ ""
10781+ "sbreak")
10782+
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010783+(define_insn "gpr_save"
10784+ [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPEC_GPR_SAVE)
10785+ (clobber (reg:SI T0_REGNUM))
10786+ (clobber (reg:SI T1_REGNUM))]
10787+ ""
10788+ { return riscv_output_gpr_save (INTVAL (operands[0])); })
10789+
10790+(define_insn "gpr_restore"
10791+ [(unspec_volatile [(match_operand 0 "const_int_operand")] UNSPEC_GPR_RESTORE)]
10792+ ""
10793+ "tail\t__riscv_restore_%0")
10794+
10795+(define_insn "gpr_restore_return"
10796+ [(return)
10797+ (use (match_operand 0 "pmode_register_operand" ""))
10798+ (const_int 0)]
10799+ ""
10800+ "")
10801+
Patrick Georgif0bbc952015-03-07 10:57:25 +010010802+(include "sync.md")
10803+(include "peephole.md")
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010804diff -urN empty/gcc/config/riscv/riscv.opt gcc-5.2.0/gcc/config/riscv/riscv.opt
Patrick Georgi410f9ad2015-08-23 21:07:46 +020010805--- gcc-5.2.0/gcc/config/riscv/riscv.opt 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010806+++ gcc-5.2.0/gcc/config/riscv/riscv.opt 2015-07-17 22:36:52.319705931 +0200
10807@@ -0,0 +1,87 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +010010808+; Options for the MIPS port of the compiler
10809+;
10810+; Copyright (C) 2005, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
10811+;
10812+; This file is part of GCC.
10813+;
10814+; GCC is free software; you can redistribute it and/or modify it under
10815+; the terms of the GNU General Public License as published by the Free
10816+; Software Foundation; either version 3, or (at your option) any later
10817+; version.
10818+;
10819+; GCC is distributed in the hope that it will be useful, but WITHOUT
10820+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10821+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10822+; License for more details.
10823+;
10824+; You should have received a copy of the GNU General Public License
10825+; along with GCC; see the file COPYING3. If not see
10826+; <http://www.gnu.org/licenses/>.
10827+
10828+m32
10829+Target RejectNegative Mask(32BIT)
10830+Generate RV32 code
10831+
10832+m64
10833+Target RejectNegative InverseMask(32BIT, 64BIT)
10834+Generate RV64 code
10835+
10836+mbranch-cost=
10837+Target RejectNegative Joined UInteger Var(riscv_branch_cost)
10838+-mbranch-cost=COST Set the cost of branches to roughly COST instructions
10839+
10840+mhard-float
10841+Target Report RejectNegative InverseMask(SOFT_FLOAT_ABI, HARD_FLOAT_ABI)
10842+Allow the use of hardware floating-point ABI and instructions
10843+
10844+mmemcpy
10845+Target Report Mask(MEMCPY)
10846+Don't optimize block moves
10847+
10848+mplt
10849+Target Report Var(TARGET_PLT) Init(1)
10850+When generating -fpic code, allow the use of PLTs. Ignored for fno-pic.
10851+
10852+msoft-float
10853+Target Report RejectNegative Mask(SOFT_FLOAT_ABI)
10854+Prevent the use of all hardware floating-point instructions
10855+
10856+mfdiv
10857+Target Report RejectNegative Mask(FDIV)
10858+Use hardware floating-point divide and square root instructions
10859+
10860+march=
10861+Target RejectNegative Joined Var(riscv_arch_string)
10862+-march= Generate code for given RISC-V ISA (e.g. RV64IM)
10863+
10864+mtune=
10865+Target RejectNegative Joined Var(riscv_tune_string)
10866+-mtune=PROCESSOR Optimize the output for PROCESSOR
10867+
10868+msmall-data-limit=
10869+Target Joined Separate UInteger Var(g_switch_value) Init(8)
10870+-msmall-data-limit=<number> Put global and static data smaller than <number> bytes into a special section (on some targets)
10871+
10872+matomic
10873+Target Report Mask(ATOMIC)
10874+Use hardware atomic memory instructions.
10875+
10876+mmuldiv
10877+Target Report Mask(MULDIV)
10878+Use hardware instructions for integer multiplication and division.
10879+
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010880+mrvc
10881+Target Report Mask(RVC)
10882+Use compressed instruction encoding
10883+
10884+msave-restore
10885+Target Report Mask(SAVE_RESTORE)
10886+Use smaller but slower prologue and epilogue code
10887+
Patrick Georgif0bbc952015-03-07 10:57:25 +010010888+mlra
10889+Target Report Var(riscv_lra_flag) Init(0) Save
10890+Use LRA instead of reload
Patrick Georgif0bbc952015-03-07 10:57:25 +010010891+
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010892+mcmodel=
10893+Target RejectNegative Joined Var(riscv_cmodel_string)
10894+Use given RISC-V code model (medlow or medany)
10895diff -urN empty/gcc/config/riscv/sync.md gcc-5.2.0/gcc/config/riscv/sync.md
Patrick Georgi410f9ad2015-08-23 21:07:46 +020010896--- gcc-5.2.0/gcc/config/riscv/sync.md 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020010897+++ gcc-5.2.0/gcc/config/riscv/sync.md 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010010898@@ -0,0 +1,198 @@
10899+;; Machine description for RISC-V atomic operations.
10900+;; Copyright (C) 2011-2014 Free Software Foundation, Inc.
10901+;; Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
10902+;; Based on MIPS target for GNU compiler.
10903+
10904+;; This file is part of GCC.
10905+
10906+;; GCC is free software; you can redistribute it and/or modify
10907+;; it under the terms of the GNU General Public License as published by
10908+;; the Free Software Foundation; either version 3, or (at your option)
10909+;; any later version.
10910+
10911+;; GCC is distributed in the hope that it will be useful,
10912+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10913+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10914+;; GNU General Public License for more details.
10915+
10916+;; You should have received a copy of the GNU General Public License
10917+;; along with GCC; see the file COPYING3. If not see
10918+;; <http://www.gnu.org/licenses/>.
10919+
10920+(define_c_enum "unspec" [
10921+ UNSPEC_COMPARE_AND_SWAP
10922+ UNSPEC_SYNC_OLD_OP
10923+ UNSPEC_SYNC_EXCHANGE
10924+ UNSPEC_ATOMIC_STORE
10925+ UNSPEC_MEMORY_BARRIER
10926+])
10927+
10928+(define_code_iterator any_atomic [plus ior xor and])
10929+(define_code_attr atomic_optab
10930+ [(plus "add") (ior "or") (xor "xor") (and "and")])
10931+
10932+;; Memory barriers.
10933+
10934+(define_expand "mem_thread_fence"
10935+ [(match_operand:SI 0 "const_int_operand" "")] ;; model
10936+ ""
10937+{
10938+ if (INTVAL (operands[0]) != MEMMODEL_RELAXED)
10939+ {
10940+ rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
10941+ MEM_VOLATILE_P (mem) = 1;
10942+ emit_insn (gen_mem_thread_fence_1 (mem, operands[0]));
10943+ }
10944+ DONE;
10945+})
10946+
10947+(define_insn "mem_thread_fence_1"
10948+ [(set (match_operand:BLK 0 "" "")
10949+ (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
10950+ (match_operand:SI 1 "const_int_operand" "")] ;; model
10951+ ""
10952+{
10953+ switch (INTVAL (operands[1]))
10954+ {
10955+ case MEMMODEL_SEQ_CST:
10956+ case MEMMODEL_ACQ_REL:
10957+ return "fence rw,rw";
10958+ case MEMMODEL_ACQUIRE:
10959+ case MEMMODEL_CONSUME:
10960+ return "fence r,rw";
10961+ case MEMMODEL_RELEASE:
10962+ return "fence rw,w";
10963+ default:
10964+ gcc_unreachable();
10965+ }
10966+})
10967+
10968+;; Atomic memory operations.
10969+
10970+;; Implement atomic stores with amoswap. Fall back to fences for atomic loads.
10971+(define_insn "atomic_store<mode>"
10972+ [(set (match_operand:GPR 0 "memory_operand" "=A")
10973+ (unspec_volatile:GPR
10974+ [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
10975+ (match_operand:SI 2 "const_int_operand")] ;; model
10976+ UNSPEC_ATOMIC_STORE))]
10977+ "TARGET_ATOMIC"
10978+ "amoswap.<amo>%A2 zero,%z1,%0")
10979+
10980+(define_insn "atomic_<atomic_optab><mode>"
10981+ [(set (match_operand:GPR 0 "memory_operand" "+A")
10982+ (unspec_volatile:GPR
10983+ [(any_atomic:GPR (match_dup 0)
10984+ (match_operand:GPR 1 "reg_or_0_operand" "rJ"))
10985+ (match_operand:SI 2 "const_int_operand")] ;; model
10986+ UNSPEC_SYNC_OLD_OP))]
10987+ "TARGET_ATOMIC"
10988+ "amo<insn>.<amo>%A2 zero,%z1,%0")
10989+
10990+(define_insn "atomic_fetch_<atomic_optab><mode>"
10991+ [(set (match_operand:GPR 0 "register_operand" "=&r")
10992+ (match_operand:GPR 1 "memory_operand" "+A"))
10993+ (set (match_dup 1)
10994+ (unspec_volatile:GPR
10995+ [(any_atomic:GPR (match_dup 1)
10996+ (match_operand:GPR 2 "reg_or_0_operand" "rJ"))
10997+ (match_operand:SI 3 "const_int_operand")] ;; model
10998+ UNSPEC_SYNC_OLD_OP))]
10999+ "TARGET_ATOMIC"
11000+ "amo<insn>.<amo>%A3 %0,%z2,%1")
11001+
11002+(define_insn "atomic_exchange<mode>"
11003+ [(set (match_operand:GPR 0 "register_operand" "=&r")
11004+ (unspec_volatile:GPR
11005+ [(match_operand:GPR 1 "memory_operand" "+A")
11006+ (match_operand:SI 3 "const_int_operand")] ;; model
11007+ UNSPEC_SYNC_EXCHANGE))
11008+ (set (match_dup 1)
11009+ (match_operand:GPR 2 "register_operand" "0"))]
11010+ "TARGET_ATOMIC"
11011+ "amoswap.<amo>%A3 %0,%z2,%1")
11012+
11013+(define_insn "atomic_cas_value_strong<mode>"
11014+ [(set (match_operand:GPR 0 "register_operand" "=&r")
11015+ (match_operand:GPR 1 "memory_operand" "+A"))
11016+ (set (match_dup 1)
11017+ (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
11018+ (match_operand:GPR 3 "reg_or_0_operand" "rJ")
11019+ (match_operand:SI 4 "const_int_operand") ;; mod_s
11020+ (match_operand:SI 5 "const_int_operand")] ;; mod_f
11021+ UNSPEC_COMPARE_AND_SWAP))
11022+ (clobber (match_scratch:GPR 6 "=&r"))]
11023+ "TARGET_ATOMIC"
11024+ "1: lr.<amo>%A5 %0,%1; bne %0,%z2,1f; sc.<amo>%A4 %6,%z3,%1; bnez %6,1b; 1:"
11025+ [(set (attr "length") (const_int 16))])
11026+
11027+(define_expand "atomic_compare_and_swap<mode>"
11028+ [(match_operand:SI 0 "register_operand" "") ;; bool output
11029+ (match_operand:GPR 1 "register_operand" "") ;; val output
11030+ (match_operand:GPR 2 "memory_operand" "") ;; memory
11031+ (match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
11032+ (match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
11033+ (match_operand:SI 5 "const_int_operand" "") ;; is_weak
11034+ (match_operand:SI 6 "const_int_operand" "") ;; mod_s
11035+ (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
11036+ "TARGET_ATOMIC"
11037+{
11038+ emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
11039+ operands[3], operands[4],
11040+ operands[6], operands[7]));
11041+
11042+ rtx compare = operands[1];
11043+ if (operands[3] != const0_rtx)
11044+ {
11045+ rtx difference = gen_rtx_MINUS (<MODE>mode, operands[1], operands[3]);
11046+ compare = gen_reg_rtx (<MODE>mode);
11047+ emit_insn (gen_rtx_SET (VOIDmode, compare, difference));
11048+ }
11049+
11050+ rtx eq = gen_rtx_EQ (<MODE>mode, compare, const0_rtx);
11051+ rtx result = gen_reg_rtx (<MODE>mode);
11052+ emit_insn (gen_rtx_SET (VOIDmode, result, eq));
11053+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_lowpart (SImode, result)));
11054+ DONE;
11055+})
11056+
11057+(define_expand "atomic_test_and_set"
11058+ [(match_operand:QI 0 "register_operand" "") ;; bool output
11059+ (match_operand:QI 1 "memory_operand" "+A") ;; memory
11060+ (match_operand:SI 2 "const_int_operand" "")] ;; model
11061+ "TARGET_ATOMIC"
11062+{
11063+ /* We have no QImode atomics, so use the address LSBs to form a mask,
11064+ then use an aligned SImode atomic. */
11065+ rtx result = operands[0];
11066+ rtx mem = operands[1];
11067+ rtx model = operands[2];
11068+ rtx addr = force_reg (Pmode, XEXP (mem, 0));
11069+
11070+ rtx aligned_addr = gen_reg_rtx (Pmode);
11071+ emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-4)));
11072+
11073+ rtx aligned_mem = change_address (mem, SImode, aligned_addr);
11074+ set_mem_alias_set (aligned_mem, 0);
11075+
11076+ rtx offset = gen_reg_rtx (SImode);
11077+ emit_move_insn (offset, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
11078+ GEN_INT (3)));
11079+
11080+ rtx tmp = gen_reg_rtx (SImode);
11081+ emit_move_insn (tmp, GEN_INT (1));
11082+
11083+ rtx shmt = gen_reg_rtx (SImode);
11084+ emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3)));
11085+
11086+ rtx word = gen_reg_rtx (SImode);
11087+ emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp, shmt));
11088+
11089+ tmp = gen_reg_rtx (SImode);
11090+ emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model));
11091+
11092+ emit_move_insn (gen_lowpart (SImode, result),
11093+ gen_rtx_LSHIFTRT (SImode, tmp,
11094+ gen_lowpart (SImode, shmt)));
11095+ DONE;
11096+})
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011097diff -urN empty/gcc/config/riscv/t-elf gcc-5.2.0/gcc/config/riscv/t-elf
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011098--- gcc-5.2.0/gcc/config/riscv/t-elf 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011099+++ gcc-5.2.0/gcc/config/riscv/t-elf 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011100@@ -0,0 +1,4 @@
11101+# Build the libraries for both hard and soft floating point
11102+
11103+MULTILIB_OPTIONS = msoft-float m64/m32 mno-atomic
11104+MULTILIB_DIRNAMES = soft-float 64 32 no-atomic
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011105diff -urN empty/gcc/config/riscv/t-linux64 gcc-5.2.0/gcc/config/riscv/t-linux64
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011106--- gcc-5.2.0/gcc/config/riscv/t-linux64 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011107+++ gcc-5.2.0/gcc/config/riscv/t-linux64 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011108@@ -0,0 +1,5 @@
11109+# Build the libraries for both hard and soft floating point
11110+
11111+MULTILIB_OPTIONS = m64/m32 msoft-float mno-atomic
11112+MULTILIB_DIRNAMES = 64 32 soft-float no-atomic
11113+MULTILIB_OSDIRNAMES = ../lib ../lib32
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011114diff -urN empty/libgcc/config/riscv/crti.S gcc-5.2.0/libgcc/config/riscv/crti.S
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011115--- gcc-5.2.0/libgcc/config/riscv/crti.S 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011116+++ gcc-5.2.0/libgcc/config/riscv/crti.S 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011117@@ -0,0 +1 @@
11118+/* crti.S is empty because .init_array/.fini_array are used exclusively. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011119diff -urN empty/libgcc/config/riscv/crtn.S gcc-5.2.0/libgcc/config/riscv/crtn.S
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011120--- gcc-5.2.0/libgcc/config/riscv/crtn.S 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011121+++ gcc-5.2.0/libgcc/config/riscv/crtn.S 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011122@@ -0,0 +1 @@
11123+/* crtn.S is empty because .init_array/.fini_array are used exclusively. */
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011124diff -urN empty/libgcc/config/riscv/div.S gcc-5.2.0/libgcc/config/riscv/div.S
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011125--- gcc-5.2.0/libgcc/config/riscv/div.S 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011126+++ gcc-5.2.0/libgcc/config/riscv/div.S 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011127@@ -0,0 +1,121 @@
11128+ .text
11129+ .align 2
11130+
11131+#ifndef __riscv64
11132+/* Our RV64 64-bit routines are equivalent to our RV32 32-bit routines. */
11133+# define __udivdi3 __udivsi3
11134+# define __umoddi3 __umodsi3
11135+# define __divdi3 __divsi3
11136+# define __moddi3 __modsi3
11137+#else
11138+ .globl __udivsi3
11139+__udivsi3:
11140+ /* Compute __udivdi3(a0 << 32, a1 << 32); cast result to uint32_t. */
11141+ sll a0, a0, 32
11142+ sll a1, a1, 32
11143+ move t0, ra
11144+ jal __udivdi3
11145+ sext.w a0, a0
11146+ jr t0
11147+
11148+ .globl __umodsi3
11149+__umodsi3:
11150+ /* Compute __udivdi3((uint32_t)a0, (uint32_t)a1); cast a1 to uint32_t. */
11151+ sll a0, a0, 32
11152+ sll a1, a1, 32
11153+ srl a0, a0, 32
11154+ srl a1, a1, 32
11155+ move t0, ra
11156+ jal __udivdi3
11157+ sext.w a0, a1
11158+ jr t0
11159+
11160+ .globl __modsi3
11161+ __modsi3 = __moddi3
11162+
11163+ .globl __divsi3
11164+__divsi3:
11165+ /* Check for special case of INT_MIN/-1. Otherwise, fall into __divdi3. */
11166+ li t0, -1
11167+ beq a1, t0, .L20
11168+#endif
11169+
11170+ .globl __divdi3
11171+__divdi3:
11172+ bltz a0, .L10
11173+ bltz a1, .L11
11174+ /* Since the quotient is positive, fall into __udivdi3. */
11175+
11176+ .globl __udivdi3
11177+__udivdi3:
11178+ mv a2, a1
11179+ mv a1, a0
11180+ li a0, -1
11181+ beqz a2, .L5
11182+ li a3, 1
11183+ bgeu a2, a1, .L2
11184+.L1:
11185+ blez a2, .L2
11186+ slli a2, a2, 1
11187+ slli a3, a3, 1
11188+ bgtu a1, a2, .L1
11189+.L2:
11190+ li a0, 0
11191+.L3:
11192+ bltu a1, a2, .L4
11193+ sub a1, a1, a2
11194+ or a0, a0, a3
11195+.L4:
11196+ srli a3, a3, 1
11197+ srli a2, a2, 1
11198+ bnez a3, .L3
11199+.L5:
11200+ ret
11201+
11202+ .globl __umoddi3
11203+__umoddi3:
11204+ /* Call __udivdi3(a0, a1), then return the remainder, which is in a1. */
11205+ move t0, ra
11206+ jal __udivdi3
11207+ move a0, a1
11208+ jr t0
11209+
11210+ /* Handle negative arguments to __divdi3. */
11211+.L10:
11212+ neg a0, a0
11213+ bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */
11214+ neg a1, a1
11215+ j __divdi3 /* Compute __udivdi3(-a0, -a1). */
11216+.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */
11217+ neg a1, a1
11218+.L12:
11219+ move t0, ra
11220+ jal __divdi3
11221+ neg a0, a0
11222+ jr t0
11223+
11224+ .globl __moddi3
11225+__moddi3:
11226+ move t0, ra
11227+ bltz a1, .L31
11228+ bltz a0, .L32
11229+.L30:
11230+ jal __udivdi3 /* The dividend is not negative. */
11231+ move a0, a1
11232+ jr t0
11233+.L31:
11234+ neg a1, a1
11235+ bgez a0, .L30
11236+.L32:
11237+ neg a0, a0
11238+ jal __udivdi3 /* The dividend is hella negative. */
11239+ neg a0, a1
11240+ jr t0
11241+
11242+#ifdef __riscv64
11243+ /* continuation of __divsi3 */
11244+.L20:
11245+ sll t0, t0, 31
11246+ bne a0, t0, __divdi3
11247+ ret
11248+#endif
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011249diff -urN empty/libgcc/config/riscv/mul.S gcc-5.2.0/libgcc/config/riscv/mul.S
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011250--- gcc-5.2.0/libgcc/config/riscv/mul.S 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011251+++ gcc-5.2.0/libgcc/config/riscv/mul.S 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011252@@ -0,0 +1,21 @@
11253+ .text
11254+ .align 2
11255+
11256+#ifndef __riscv64
11257+/* Our RV64 64-bit routine is equivalent to our RV32 32-bit routine. */
11258+# define __muldi3 __mulsi3
11259+#endif
11260+
11261+ .globl __muldi3
11262+__muldi3:
11263+ mv a2, a0
11264+ li a0, 0
11265+.L1:
11266+ slli a3, a1, _RISCV_SZPTR-1
11267+ bgez a3, .L2
11268+ add a0, a0, a2
11269+.L2:
11270+ srli a1, a1, 1
11271+ slli a2, a2, 1
11272+ bnez a1, .L1
11273+ ret
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011274diff -urN empty/libgcc/config/riscv/riscv-fp.c gcc-5.2.0/libgcc/config/riscv/riscv-fp.c
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011275--- gcc-5.2.0/libgcc/config/riscv/riscv-fp.c 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011276+++ gcc-5.2.0/libgcc/config/riscv/riscv-fp.c 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011277@@ -0,0 +1,178 @@
11278+/* Functions needed for soft-float on riscv-linux. Based on
11279+ rs6000/ppc64-fp.c with TF types removed.
11280+
11281+ Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
11282+ 2000, 2001, 2002, 2003, 2004, 2006, 2009 Free Software Foundation,
11283+ Inc.
11284+
11285+This file is part of GCC.
11286+
11287+GCC is free software; you can redistribute it and/or modify it under
11288+the terms of the GNU General Public License as published by the Free
11289+Software Foundation; either version 3, or (at your option) any later
11290+version.
11291+
11292+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11293+WARRANTY; without even the implied warranty of MERCHANTABILITY or
11294+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11295+for more details.
11296+
11297+Under Section 7 of GPL version 3, you are granted additional
11298+permissions described in the GCC Runtime Library Exception, version
11299+3.1, as published by the Free Software Foundation.
11300+
11301+You should have received a copy of the GNU General Public License and
11302+a copy of the GCC Runtime Library Exception along with this program;
11303+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
11304+<http://www.gnu.org/licenses/>. */
11305+
11306+#if defined(__riscv64)
11307+#include "fp-bit.h"
11308+
11309+extern DItype __fixdfdi (DFtype);
11310+extern DItype __fixsfdi (SFtype);
11311+extern USItype __fixunsdfsi (DFtype);
11312+extern USItype __fixunssfsi (SFtype);
11313+extern DFtype __floatdidf (DItype);
11314+extern DFtype __floatundidf (UDItype);
11315+extern SFtype __floatdisf (DItype);
11316+extern SFtype __floatundisf (UDItype);
11317+
11318+static DItype local_fixunssfdi (SFtype);
11319+static DItype local_fixunsdfdi (DFtype);
11320+
11321+DItype
11322+__fixdfdi (DFtype a)
11323+{
11324+ if (a < 0)
11325+ return - local_fixunsdfdi (-a);
11326+ return local_fixunsdfdi (a);
11327+}
11328+
11329+DItype
11330+__fixsfdi (SFtype a)
11331+{
11332+ if (a < 0)
11333+ return - local_fixunssfdi (-a);
11334+ return local_fixunssfdi (a);
11335+}
11336+
11337+USItype
11338+__fixunsdfsi (DFtype a)
11339+{
11340+ if (a >= - (DFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
11341+ return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
11342+ - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1);
11343+ return (SItype) a;
11344+}
11345+
11346+USItype
11347+__fixunssfsi (SFtype a)
11348+{
11349+ if (a >= - (SFtype) (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
11350+ return (SItype) (a + (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1))
11351+ - (- ((SItype)(((USItype)1 << ((4 * 8) - 1)) - 1)) - 1);
11352+ return (SItype) a;
11353+}
11354+
11355+DFtype
11356+__floatdidf (DItype u)
11357+{
11358+ DFtype d;
11359+
11360+ d = (SItype) (u >> (sizeof (SItype) * 8));
11361+ d *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
11362+ d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
11363+
11364+ return d;
11365+}
11366+
11367+DFtype
11368+__floatundidf (UDItype u)
11369+{
11370+ DFtype d;
11371+
11372+ d = (USItype) (u >> (sizeof (SItype) * 8));
11373+ d *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
11374+ d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
11375+
11376+ return d;
11377+}
11378+
11379+SFtype
11380+__floatdisf (DItype u)
11381+{
11382+ DFtype f;
11383+
11384+ if (53 < (sizeof (DItype) * 8)
11385+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
11386+ {
11387+ if (! (- ((DItype) 1 << 53) < u
11388+ && u < ((DItype) 1 << 53)))
11389+ {
11390+ if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1))
11391+ {
11392+ u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1);
11393+ u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53));
11394+ }
11395+ }
11396+ }
11397+ f = (SItype) (u >> (sizeof (SItype) * 8));
11398+ f *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
11399+ f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
11400+
11401+ return (SFtype) f;
11402+}
11403+
11404+SFtype
11405+__floatundisf (UDItype u)
11406+{
11407+ DFtype f;
11408+
11409+ if (53 < (sizeof (DItype) * 8)
11410+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
11411+ {
11412+ if (u >= ((UDItype) 1 << 53))
11413+ {
11414+ if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1))
11415+ {
11416+ u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1);
11417+ u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53));
11418+ }
11419+ }
11420+ }
11421+ f = (USItype) (u >> (sizeof (SItype) * 8));
11422+ f *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
11423+ f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
11424+
11425+ return (SFtype) f;
11426+}
11427+
11428+/* This version is needed to prevent recursion; fixunsdfdi in libgcc
11429+ calls fixdfdi, which in turn calls calls fixunsdfdi. */
11430+
11431+static DItype
11432+local_fixunsdfdi (DFtype a)
11433+{
11434+ USItype hi, lo;
11435+
11436+ hi = a / (((UDItype) 1) << (sizeof (SItype) * 8));
11437+ lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8)));
11438+ return ((UDItype) hi << (sizeof (SItype) * 8)) | lo;
11439+}
11440+
11441+/* This version is needed to prevent recursion; fixunssfdi in libgcc
11442+ calls fixsfdi, which in turn calls calls fixunssfdi. */
11443+
11444+static DItype
11445+local_fixunssfdi (SFtype original_a)
11446+{
11447+ DFtype a = original_a;
11448+ USItype hi, lo;
11449+
11450+ hi = a / (((UDItype) 1) << (sizeof (SItype) * 8));
11451+ lo = (a - ((DFtype) hi) * (((UDItype) 1) << (sizeof (SItype) * 8)));
11452+ return ((UDItype) hi << (sizeof (SItype) * 8)) | lo;
11453+}
11454+
11455+#endif
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011456diff -urN empty/libgcc/config/riscv/save-restore.S gcc-5.2.0/libgcc/config/riscv/save-restore.S
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011457--- gcc-5.2.0/libgcc/config/riscv/save-restore.S 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011458+++ gcc-5.2.0/libgcc/config/riscv/save-restore.S 2015-07-17 22:36:52.319705931 +0200
11459@@ -0,0 +1,220 @@
11460+ .text
11461+
11462+ .globl __riscv_save_12
11463+ .globl __riscv_save_11
11464+ .globl __riscv_save_10
11465+ .globl __riscv_save_9
11466+ .globl __riscv_save_8
11467+ .globl __riscv_save_7
11468+ .globl __riscv_save_6
11469+ .globl __riscv_save_5
11470+ .globl __riscv_save_4
11471+ .globl __riscv_save_3
11472+ .globl __riscv_save_2
11473+ .globl __riscv_save_1
11474+ .globl __riscv_save_0
11475+
11476+ .globl __riscv_restore_12
11477+ .globl __riscv_restore_11
11478+ .globl __riscv_restore_10
11479+ .globl __riscv_restore_9
11480+ .globl __riscv_restore_8
11481+ .globl __riscv_restore_7
11482+ .globl __riscv_restore_6
11483+ .globl __riscv_restore_5
11484+ .globl __riscv_restore_4
11485+ .globl __riscv_restore_3
11486+ .globl __riscv_restore_2
11487+ .globl __riscv_restore_1
11488+ .globl __riscv_restore_0
11489+
11490+#ifdef __riscv64
11491+
11492+__riscv_save_12:
11493+ addi sp, sp, -112
11494+ li t1, 0
11495+ sd s11, 8(sp)
11496+ j .Ls10
11497+
11498+__riscv_save_11:
11499+__riscv_save_10:
11500+ addi sp, sp, -112
11501+ li t1, -16
11502+.Ls10:
11503+ sd s10, 16(sp)
11504+ sd s9, 24(sp)
11505+ j .Ls8
11506+
11507+__riscv_save_9:
11508+__riscv_save_8:
11509+ addi sp, sp, -112
11510+ li t1, -32
11511+.Ls8:
11512+ sd s8, 32(sp)
11513+ sd s7, 40(sp)
11514+ j .Ls6
11515+
11516+__riscv_save_7:
11517+__riscv_save_6:
11518+ addi sp, sp, -112
11519+ li t1, -48
11520+.Ls6:
11521+ sd s6, 48(sp)
11522+ sd s5, 56(sp)
11523+ j .Ls4
11524+
11525+__riscv_save_5:
11526+__riscv_save_4:
11527+ addi sp, sp, -112
11528+ li t1, -64
11529+.Ls4:
11530+ sd s4, 64(sp)
11531+ sd s3, 72(sp)
11532+ j .Ls2
11533+
11534+__riscv_save_3:
11535+__riscv_save_2:
11536+ addi sp, sp, -112
11537+ li t1, -80
11538+.Ls2:
11539+ sd s2, 80(sp)
11540+ sd s1, 88(sp)
11541+ sd s0, 96(sp)
11542+ sd ra, 104(sp)
11543+ sub sp, sp, t1
11544+ jr t0
11545+
11546+__riscv_save_1:
11547+__riscv_save_0:
11548+ addi sp, sp, -16
11549+ sd s0, 0(sp)
11550+ sd ra, 8(sp)
11551+ jr t0
11552+
11553+__riscv_restore_12:
11554+ ld s11, 8(sp)
11555+ addi sp, sp, 16
11556+
11557+__riscv_restore_11:
11558+__riscv_restore_10:
11559+ ld s10, 0(sp)
11560+ ld s9, 8(sp)
11561+ addi sp, sp, 16
11562+
11563+__riscv_restore_9:
11564+__riscv_restore_8:
11565+ ld s8, 0(sp)
11566+ ld s7, 8(sp)
11567+ addi sp, sp, 16
11568+
11569+__riscv_restore_7:
11570+__riscv_restore_6:
11571+ ld s6, 0(sp)
11572+ ld s5, 8(sp)
11573+ addi sp, sp, 16
11574+
11575+__riscv_restore_5:
11576+__riscv_restore_4:
11577+ ld s4, 0(sp)
11578+ ld s3, 8(sp)
11579+ addi sp, sp, 16
11580+
11581+__riscv_restore_3:
11582+__riscv_restore_2:
11583+ ld s2, 0(sp)
11584+ ld s1, 8(sp)
11585+ addi sp, sp, 16
11586+
11587+__riscv_restore_1:
11588+__riscv_restore_0:
11589+ ld s0, 0(sp)
11590+ ld ra, 8(sp)
11591+ addi sp, sp, 16
11592+ ret
11593+
11594+#else
11595+
11596+__riscv_save_12:
11597+ addi sp, sp, -64
11598+ li t1, 0
11599+ sw s11, 12(sp)
11600+ j .Ls10
11601+
11602+__riscv_save_11:
11603+__riscv_save_10:
11604+__riscv_save_9:
11605+__riscv_save_8:
11606+ addi sp, sp, -64
11607+ li t1, -16
11608+.Ls10:
11609+ sw s10, 16(sp)
11610+ sw s9, 20(sp)
11611+ sw s8, 24(sp)
11612+ sw s7, 28(sp)
11613+ j .Ls6
11614+
11615+__riscv_save_7:
11616+__riscv_save_6:
11617+__riscv_save_5:
11618+__riscv_save_4:
11619+ addi sp, sp, -64
11620+ li t1, -32
11621+.Ls6:
11622+ sw s6, 32(sp)
11623+ sw s5, 36(sp)
11624+ sw s4, 40(sp)
11625+ sw s3, 44(sp)
11626+ sw s2, 48(sp)
11627+ sw s1, 52(sp)
11628+ sw s0, 56(sp)
11629+ sw ra, 60(sp)
11630+ sub sp, sp, t1
11631+ jr t0
11632+
11633+__riscv_save_3:
11634+__riscv_save_2:
11635+__riscv_save_1:
11636+__riscv_save_0:
11637+ addi sp, sp, -16
11638+ sw s2, 0(sp)
11639+ sw s1, 4(sp)
11640+ sw s0, 8(sp)
11641+ sw ra, 12(sp)
11642+ jr t0
11643+
11644+__riscv_restore_12:
11645+ lw s11, 12(sp)
11646+ addi sp, sp, 16
11647+
11648+__riscv_restore_11:
11649+__riscv_restore_10:
11650+__riscv_restore_9:
11651+__riscv_restore_8:
11652+ lw s10, 0(sp)
11653+ lw s9, 4(sp)
11654+ lw s8, 8(sp)
11655+ lw s7, 12(sp)
11656+ addi sp, sp, 16
11657+
11658+__riscv_restore_7:
11659+__riscv_restore_6:
11660+__riscv_restore_5:
11661+__riscv_restore_4:
11662+ lw s6, 0(sp)
11663+ lw s5, 4(sp)
11664+ lw s4, 8(sp)
11665+ lw s3, 12(sp)
11666+ addi sp, sp, 16
11667+
11668+__riscv_restore_3:
11669+__riscv_restore_2:
11670+__riscv_restore_1:
11671+__riscv_restore_0:
11672+ lw s2, 0(sp)
11673+ lw s1, 4(sp)
11674+ lw s0, 8(sp)
11675+ lw ra, 12(sp)
11676+ addi sp, sp, 16
11677+ ret
11678+
11679+#endif
11680diff -urN empty/libgcc/config/riscv/t-dpbit gcc-5.2.0/libgcc/config/riscv/t-dpbit
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011681--- gcc-5.2.0/libgcc/config/riscv/t-dpbit 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011682+++ gcc-5.2.0/libgcc/config/riscv/t-dpbit 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011683@@ -0,0 +1,4 @@
11684+LIB2ADD += dp-bit.c
11685+
11686+dp-bit.c: $(srcdir)/fp-bit.c
11687+ cat $(srcdir)/fp-bit.c > dp-bit.c
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011688diff -urN empty/libgcc/config/riscv/t-elf gcc-5.2.0/libgcc/config/riscv/t-elf
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011689--- gcc-5.2.0/libgcc/config/riscv/t-elf 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011690+++ gcc-5.2.0/libgcc/config/riscv/t-elf 2015-07-17 22:36:52.319705931 +0200
11691@@ -0,0 +1,4 @@
Patrick Georgif0bbc952015-03-07 10:57:25 +010011692+LIB2ADD += $(srcdir)/config/riscv/riscv-fp.c \
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011693+ $(srcdir)/config/riscv/save-restore.S \
Patrick Georgif0bbc952015-03-07 10:57:25 +010011694+ $(srcdir)/config/riscv/mul.S \
11695+ $(srcdir)/config/riscv/div.S
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011696diff -urN empty/libgcc/config/riscv/t-elf32 gcc-5.2.0/libgcc/config/riscv/t-elf32
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011697--- gcc-5.2.0/libgcc/config/riscv/t-elf32 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011698+++ gcc-5.2.0/libgcc/config/riscv/t-elf32 2015-07-17 22:36:52.319705931 +0200
11699@@ -0,0 +1,2 @@
11700+HOST_LIBGCC2_CFLAGS += -m32
11701+CRTSTUFF_CFLAGS += -m32
11702diff -urN empty/libgcc/config/riscv/t-fpbit gcc-5.2.0/libgcc/config/riscv/t-fpbit
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011703--- gcc-5.2.0/libgcc/config/riscv/t-fpbit 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011704+++ gcc-5.2.0/libgcc/config/riscv/t-fpbit 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011705@@ -0,0 +1,5 @@
11706+LIB2ADD += fp-bit.c
11707+
11708+fp-bit.c: $(srcdir)/fp-bit.c
11709+ echo '#define FLOAT' > fp-bit.c
11710+ cat $(srcdir)/fp-bit.c >> fp-bit.c
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011711diff -urN empty/libgcc/config/riscv/t-tpbit gcc-5.2.0/libgcc/config/riscv/t-tpbit
Patrick Georgi410f9ad2015-08-23 21:07:46 +020011712--- gcc-5.2.0/libgcc/config/riscv/t-tpbit 1970-01-01 01:00:00.000000000 +0100
Patrick Georgiaf473ed2015-07-17 23:35:54 +020011713+++ gcc-5.2.0/libgcc/config/riscv/t-tpbit 2015-07-17 22:36:52.319705931 +0200
Patrick Georgif0bbc952015-03-07 10:57:25 +010011714@@ -0,0 +1,10 @@
11715+LIB2ADD += tp-bit.c
11716+
11717+tp-bit.c: $(srcdir)/fp-bit.c
11718+ echo '#ifdef _RISCVEL' > tp-bit.c
11719+ echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
11720+ echo '#endif' >> tp-bit.c
11721+ echo '#if __LDBL_MANT_DIG__ == 113' >> tp-bit.c
11722+ echo '# define TFLOAT' >> tp-bit.c
11723+ cat $(srcdir)/fp-bit.c >> tp-bit.c
11724+ echo '#endif' >> tp-bit.c