From patchwork Fri May 18 22:54:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Wilson X-Patchwork-Id: 916650 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-477975-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vJOiAuM/"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40nk5d4Tz8z9s33 for ; Sat, 19 May 2018 08:54:59 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; q=dns; s=default; b=mcpPCAfhWZs8 Ku0V7Qb34LoZ9LEfg5h7vFxrVwTyfCX/7Tkre9b0axEtuOwvWL26CIuz5Tjirr/r cHf0ZqMDa08WHCmEgqMrFyGz3GTeOQcFfnL7H2QL2CcfuSizEV4IJw3idGy6KnVM 4krBWA6y794Ch1Yzg8XHgqvRyfGVujM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id; s=default; bh=tfIhT25EJGYDNRBTz+ Ncpqsbs0o=; b=vJOiAuM/6d0l4wJxYcudGurfDNdICVJziogh7W/lIEXRNrZOLL WNqaKHvYy+L1rNvlQeUJ9q3aB7Jg72BV6Pm7y76cNqrlrbgDlSgY3zzWKVvebyHY u67mAA5v0wc8RVZCodfchZPZ0lF9pcZHBv13Ln2mtKmg9GKAnt0RL/5eQ= Received: (qmail 63410 invoked by alias); 18 May 2018 22:54:51 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 63397 invoked by uid 89); 18 May 2018 22:54:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=H*r:sk:v24-v6s, saves, cfi_startproc, HX-Received:1347 X-HELO: mail-pl0-f66.google.com Received: from mail-pl0-f66.google.com (HELO mail-pl0-f66.google.com) (209.85.160.66) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 May 2018 22:54:48 +0000 Received: by mail-pl0-f66.google.com with SMTP id v24-v6so5383506plo.3 for ; Fri, 18 May 2018 15:54:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=KeIP4jftWodeeIv0rhkJTPWANuApQZabf0BAabfSXJ8=; b=kQqHYMj4EYYbnj2yAOmIy/ESu8pLlFgjeCPb4X9JxKhL16t/tzNKsEHQIagbz4I85u b5WZ6tT2JF9JkdiVS6QXkWP0M8+VrJrEpf6gdrVnjS/zsItGemtPaFdaOFC2XBcZt2bK ZUpyPr0EAUG70s1Uhg9DRv6M6CbKpVdwEPgRJyD3RVhgrY05bSUkvE7O8gXxira5M8qR mMqOxUpD6XAuCjbg8VNfWaKIXvdkwHhFCZ+jlR3Q9zCUqqmuA1wQc5jJgp2DcEjhExDS fGPLzjzG99uTZoYI0bXe3FgZraBlpKt714/Wzu97QfU15ry8/akeMTOp1tlCgCtA8Xu4 VKCg== X-Gm-Message-State: ALKqPwcy+Z0ej0xOhns9OSzUboJMSzAqIZWDigXBRKCQemgIieSpd9Hl dh4nfFAW2kfDyivG+jP/aI0zER/JIPU= X-Google-Smtp-Source: AB8JxZpNLocx6XApaURj0IGFkC5xhT7RY585eAIh1XpUA5k8lbZRFyRPKF3pryIZlIqRyMObf5biwA== X-Received: by 2002:a17:902:1347:: with SMTP id r7-v6mr11180785ple.62.1526684086309; Fri, 18 May 2018 15:54:46 -0700 (PDT) Received: from rohan.internal.sifive.com ([12.206.222.5]) by smtp.gmail.com with ESMTPSA id b3-v6sm14312260pff.132.2018.05.18.15.54.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 15:54:44 -0700 (PDT) From: Jim Wilson To: gcc-patches@gcc.gnu.org Cc: Jim Wilson Subject: [PATCH] RISC-V: Add RV32E support. Date: Fri, 18 May 2018 15:54:41 -0700 Message-Id: <20180518225441.31684-1-jimw@sifive.com> This adds support for -march=rv32e and -mabi=ilp32e. This is mostly the work of Kito Cheng and Monk Chiang. I forward ported the patch to current sources, which needed a few fixes. I fixed the mask clearing/setting so that using multiple -march/-mabi options works right. I added some docs for the new options. This was tested with binutils/gcc builds and make checks, both with and without the RV32E support enabled. There were no regressions. Committed. Jim Kito Cheng Monk Chiang gcc/ * common/config/riscv/riscv-common.c (riscv_parse_arch_string): Add support to parse rv32e*. Clear MASK_RVE for rv32i and rv64i. * config.gcc (riscv*-*-*): Add support for rv32e* and ilp32e. * config/riscv/riscv-c.c (riscv_cpu_cpp_builtins): Define __riscv_32e when TARGET_RVE. Handle ABI_ILP32E as soft-float ABI. * config/riscv/riscv-opts.h (riscv_abi_type): Add ABI_ILP32E. * config/riscv/riscv.c (riscv_compute_frame_info): When TARGET_RVE, compute save_libcall_adjustment properly. (riscv_option_override): Call error if TARGET_RVE and not ABI_ILP32E. (riscv_conditional_register_usage): Handle TARGET_RVE and ABI_ILP32E. * config/riscv/riscv.h (UNITS_PER_FP_ARG): Handle ABI_ILP32E. (STACK_BOUNDARY, ABI_STACK_BOUNDARY): Handle TARGET_RVE. (GP_REG_LAST, MAX_ARGS_IN_REGISTERS): Likewise. (ABI_SPEC): Handle mabi=ilp32e. * config/riscv/riscv.opt (abi_type): Add ABI_ILP32E. (RVE): Add RVE mask. * doc/invoke.texi (RISC-V options) <-mabi>: Add ilp32e info. <-march>: Add rv32e as an example. gcc/testsuite/ * gcc.dg/stack-usage-1.c: Add support for rv32e. libgcc/ * config/riscv/save-restore.S: Add support for rv32e. --- gcc/common/config/riscv/riscv-common.c | 29 ++++++++++++++++++++- gcc/config.gcc | 10 +++++--- gcc/config/riscv/riscv-c.c | 4 +++ gcc/config/riscv/riscv-opts.h | 1 + gcc/config/riscv/riscv.c | 25 +++++++++++++++++- gcc/config/riscv/riscv.h | 17 +++++++------ gcc/config/riscv/riscv.opt | 5 ++++ gcc/doc/invoke.texi | 7 ++++-- gcc/testsuite/gcc.dg/stack-usage-1.c | 6 ++++- libgcc/config/riscv/save-restore.S | 46 +++++++++++++++++++++++++++++++++- 10 files changed, 133 insertions(+), 17 deletions(-) diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c index 9db83015aed..8a78aebc320 100644 --- a/gcc/common/config/riscv/riscv-common.c +++ b/gcc/common/config/riscv/riscv-common.c @@ -27,7 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "diagnostic-core.h" -/* Parse a RISC-V ISA string into an option mask. */ +/* Parse a RISC-V ISA string into an option mask. Must clear or set all arch + dependent mask bits, in case more than one -march string is passed. */ static void riscv_parse_arch_string (const char *isa, int *flags, location_t loc) @@ -48,6 +49,8 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) { p++; + *flags &= ~MASK_RVE; + *flags |= MASK_MUL; *flags |= MASK_ATOMIC; *flags |= MASK_HARD_FLOAT; @@ -57,6 +60,8 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) { p++; + *flags &= ~MASK_RVE; + *flags &= ~MASK_MUL; if (*p == 'm') *flags |= MASK_MUL, p++; @@ -77,6 +82,28 @@ riscv_parse_arch_string (const char *isa, int *flags, location_t loc) } } } + else if (*p == 'e') + { + p++; + + *flags |= MASK_RVE; + + if (*flags & MASK_64BIT) + { + error ("RV64E is not a valid base ISA"); + return; + } + + *flags &= ~MASK_MUL; + if (*p == 'm') + *flags |= MASK_MUL, p++; + + *flags &= ~MASK_ATOMIC; + if (*p == 'a') + *flags |= MASK_ATOMIC, p++; + + *flags &= ~(MASK_HARD_FLOAT | MASK_DOUBLE_FLOAT); + } else { error_at (loc, "-march=%s: invalid ISA string", isa); diff --git a/gcc/config.gcc b/gcc/config.gcc index 8edd0cdbaed..96ae6a88a0d 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -4077,19 +4077,20 @@ case "${target}" in # Infer arch from --with-arch, --target, and --with-abi. case "${with_arch}" in - rv32i* | rv32g* | rv64i* | rv64g*) + rv32e* | rv32i* | rv32g* | rv64i* | rv64g*) # OK. ;; "") # Infer XLEN, but otherwise assume GC. case "${with_abi}" in + ilp32e) with_arch="rv32e" ;; ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;; lp64 | lp64f | lp64d) with_arch="rv64gc" ;; *) with_arch="rv${xlen}gc" ;; esac ;; *) - echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32i, rv32g, rv64i, or rv64g." 1>&2 + echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32e, rv32i, rv32g, rv64i, or rv64g." 1>&2 exit 1 ;; esac @@ -4098,11 +4099,12 @@ case "${target}" in # pick a default based on the ISA, preferring soft-float # unless the D extension is present. case "${with_abi}" in - ilp32 | ilp32f | ilp32d | lp64 | lp64f | lp64d) + ilp32 | ilp32e | ilp32f | ilp32d | lp64 | lp64f | lp64d) ;; "") case "${with_arch}" in rv32*d* | rv32g*) with_abi=ilp32d ;; + rv32e*) with_abi=ilp32e ;; rv32*) with_abi=ilp32 ;; rv64*d* | rv64g*) with_abi=lp64d ;; rv64*) with_abi=lp64 ;; @@ -4116,7 +4118,7 @@ case "${target}" in # Make sure ABI and ISA are compatible. case "${with_abi},${with_arch}" in - ilp32,rv32* \ + ilp32,rv32* | ilp32e,rv32e* \ | ilp32f,rv32*f* | ilp32f,rv32g* \ | ilp32d,rv32*d* | ilp32d,rv32g* \ | lp64,rv64* \ diff --git a/gcc/config/riscv/riscv-c.c b/gcc/config/riscv/riscv-c.c index 391b5eefc5c..513f974d9aa 100644 --- a/gcc/config/riscv/riscv-c.c +++ b/gcc/config/riscv/riscv-c.c @@ -39,6 +39,9 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) if (TARGET_RVC) builtin_define ("__riscv_compressed"); + if (TARGET_RVE) + builtin_define ("__riscv_32e"); + if (TARGET_ATOMIC) builtin_define ("__riscv_atomic"); @@ -62,6 +65,7 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) switch (riscv_abi) { case ABI_ILP32: + case ABI_ILP32E: case ABI_LP64: builtin_define ("__riscv_float_abi_soft"); break; diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 3e10ab339a5..b7ed72ebb75 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see enum riscv_abi_type { ABI_ILP32, + ABI_ILP32E, ABI_ILP32F, ABI_ILP32D, ABI_LP64, diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index b4975888bbb..9a9d9e1befe 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -3334,7 +3334,14 @@ riscv_compute_frame_info (void) /* Only use save/restore routines if they don't alter the stack size. */ if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) - frame->save_libcall_adjustment = x_save_size; + { + /* Libcall saves/restores 3 registers at once, so we need to + allocate 12 bytes for callee-saved register. */ + if (TARGET_RVE) + x_save_size = 3 * UNITS_PER_WORD; + + frame->save_libcall_adjustment = x_save_size; + } offset += x_save_size; } @@ -4147,6 +4154,9 @@ riscv_option_override (void) error ("requested ABI requires -march to subsume the %qc extension", UNITS_PER_FP_ARG > 8 ? 'Q' : (UNITS_PER_FP_ARG > 4 ? 'D' : 'F')); + if (TARGET_RVE && riscv_abi != ABI_ILP32E) + error ("rv32e requires ilp32e ABI"); + /* We do not yet support ILP32 on RV64. */ if (BITS_PER_WORD != POINTER_SIZE) error ("ABI requires -march=rv%d", POINTER_SIZE); @@ -4171,6 +4181,19 @@ riscv_option_override (void) static void riscv_conditional_register_usage (void) { + /* We have only x0~x15 on RV32E. */ + if (TARGET_RVE) + { + for (int r = 16; r <= 31; r++) + fixed_regs[r] = 1; + } + + if (riscv_abi == ABI_ILP32E) + { + for (int r = 16; r <= 31; r++) + call_used_regs[r] = 1; + } + if (!TARGET_HARD_FLOAT) { for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 62279ff2cde..a9111a483ab 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -102,9 +102,11 @@ along with GCC; see the file COPYING3. If not see #define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4) /* The largest type that can be passed in floating-point registers. */ -#define UNITS_PER_FP_ARG \ - (riscv_abi == ABI_ILP32 || riscv_abi == ABI_LP64 ? 0 : \ - riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : 8) \ +#define UNITS_PER_FP_ARG \ + ((riscv_abi == ABI_ILP32 || riscv_abi == ABI_ILP32E \ + || riscv_abi == ABI_LP64) \ + ? 0 \ + : ((riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F) ? 4 : 8)) /* Set the sizes of the core types. */ #define SHORT_TYPE_SIZE 16 @@ -124,10 +126,10 @@ along with GCC; see the file COPYING3. If not see #define FUNCTION_BOUNDARY (TARGET_RVC ? 16 : 32) /* The smallest supported stack boundary the calling convention supports. */ -#define STACK_BOUNDARY (2 * BITS_PER_WORD) +#define STACK_BOUNDARY (TARGET_RVE ? BITS_PER_WORD : 2 * BITS_PER_WORD) /* The ABI stack alignment. */ -#define ABI_STACK_BOUNDARY 128 +#define ABI_STACK_BOUNDARY (TARGET_RVE ? BITS_PER_WORD : 128) /* There is no point aligning anything to a rounder boundary than this. */ #define BIGGEST_ALIGNMENT 128 @@ -260,7 +262,7 @@ along with GCC; see the file COPYING3. If not see /* Internal macros to classify an ISA register's type. */ #define GP_REG_FIRST 0 -#define GP_REG_LAST 31 +#define GP_REG_LAST (TARGET_RVE ? 15 : 31) #define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1) #define FP_REG_FIRST 32 @@ -490,7 +492,7 @@ enum reg_class #define GP_RETURN GP_ARG_FIRST #define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST) -#define MAX_ARGS_IN_REGISTERS 8 +#define MAX_ARGS_IN_REGISTERS (TARGET_RVE ? 6 : 8) /* Symbolic macros for the first/last argument registers. */ @@ -870,6 +872,7 @@ extern unsigned riscv_stack_boundary; #define ABI_SPEC \ "%{mabi=ilp32:ilp32}" \ + "%{mabi=ilp32e:ilp32e}" \ "%{mabi=ilp32f:ilp32f}" \ "%{mabi=ilp32d:ilp32d}" \ "%{mabi=lp64:lp64}" \ diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index b37ac75d9bb..13693221d26 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -44,6 +44,9 @@ Supported ABIs (for use with the -mabi= option): EnumValue Enum(abi_type) String(ilp32) Value(ABI_ILP32) +EnumValue +Enum(abi_type) String(ilp32e) Value(ABI_ILP32E) + EnumValue Enum(abi_type) String(ilp32f) Value(ABI_ILP32F) @@ -122,3 +125,5 @@ Mask(HARD_FLOAT) Mask(DOUBLE_FLOAT) Mask(RVC) + +Mask(RVE) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 44b043384d9..beba295bef5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -23025,7 +23025,9 @@ conventions are: @samp{ilp32}, @samp{ilp32f}, @samp{ilp32d}, @samp{lp64}, @samp{lp64f}, and @samp{lp64d}. Some calling conventions are impossible to implement on some ISAs: for example, @samp{-march=rv32if -mabi=ilp32d} is invalid because the ABI requires 64-bit values be passed in F registers, but F -registers are only 32 bits wide. +registers are only 32 bits wide. There is also the @samp{ilp32e} ABI that can +only be used with the @samp{rv32e} architecture. This ABI is not well +specified at present, and is subject to change. @item -mfdiv @itemx -mno-fdiv @@ -23044,7 +23046,8 @@ these instructions. @item -march=@var{ISA-string} @opindex march Generate code for given RISC-V ISA (e.g.@ @samp{rv64im}). ISA strings must be -lower-case. Examples include @samp{rv64i}, @samp{rv32g}, and @samp{rv32imaf}. +lower-case. Examples include @samp{rv64i}, @samp{rv32g}, @samp{rv32e}, and +@samp{rv32imaf}. @item -mtune=@var{processor-string} @opindex mtune diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c index 45d2c7b6aae..038bd4ec05c 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-1.c +++ b/gcc/testsuite/gcc.dg/stack-usage-1.c @@ -64,7 +64,11 @@ # define SIZE 240 # endif #elif defined (__riscv) -# define SIZE 240 +# if defined (__riscv_32e) +# define SIZE 252 +# else +# define SIZE 240 +# endif #elif defined (__AVR__) #if defined (__AVR_3_BYTE_PC__ ) # define SIZE 251 /* 256 - 2 bytes for Y - 3 bytes for return address */ diff --git a/libgcc/config/riscv/save-restore.S b/libgcc/config/riscv/save-restore.S index 9a6d0c9fcfc..a76c9780902 100644 --- a/libgcc/config/riscv/save-restore.S +++ b/libgcc/config/riscv/save-restore.S @@ -294,6 +294,48 @@ FUNC_END (__riscv_restore_0) #else +#ifdef __riscv_32e +FUNC_BEGIN(__riscv_save_2) +FUNC_BEGIN(__riscv_save_1) +FUNC_BEGIN(__riscv_save_0) + .cfi_startproc + # __riscv_save_* routine use t0/x5 as return address + .cfi_return_column 5 + addi sp, sp, -12 + .cfi_def_cfa_offset 12 + sw s1, 0(sp) + .cfi_offset 9, -12 + sw s0, 4(sp) + .cfi_offset 8, -8 + sw ra, 8(sp) + .cfi_offset 1, 0 + jr t0 + .cfi_endproc +FUNC_END(__riscv_save_2) +FUNC_END(__riscv_save_1) +FUNC_END(__riscv_save_0) + +FUNC_BEGIN(__riscv_restore_2) +FUNC_BEGIN(__riscv_restore_1) +FUNC_BEGIN(__riscv_restore_0) + .cfi_startproc + .cfi_def_cfa_offset 14 + lw s1, 0(sp) + .cfi_restore 9 + lw s0, 4(sp) + .cfi_restore 8 + lw ra, 8(sp) + .cfi_restore 1 + addi sp, sp, 12 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +FUNC_END(__riscv_restore_2) +FUNC_END(__riscv_restore_1) +FUNC_END(__riscv_restore_0) + +#else + FUNC_BEGIN (__riscv_save_12) .cfi_startproc # __riscv_save_* routine use t0/x5 as return address @@ -486,4 +528,6 @@ FUNC_END (__riscv_restore_2) FUNC_END (__riscv_restore_1) FUNC_END (__riscv_restore_0) -#endif +#endif /* __riscv_32e */ + +#endif /* __riscv_xlen == 64 */