From patchwork Thu Aug 16 04:49:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958094 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-483756-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="jadd2qdz"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="bZ/lSBYC"; 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 41rYnY1rtpz9s4c for ; Thu, 16 Aug 2018 14:51:12 +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:in-reply-to:references; q=dns; s= default; b=dXRjY2c4YzMhCElTJrTftdnMbzCxhet1ls6KufJGq0FBrz1sFB6sf ToK1duFE4kJwHm7miswND9sYiQNOlbq1HkqtZb4f4cDI1NC/Yua3WA1/HIcRF02b hg9fk4/ovsNR8x40mE1AjCr4ABWPyaZ5kT4/HLRQ7AE3AHq8EN+tT8= 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:in-reply-to:references; s= default; bh=/q/bnbFxn92YmzicMzUkTPp3QqA=; b=jadd2qdzQp/GbTiryQsE DKZJECOQp9hiBjv1xdQgJCpiJEfuBHXsr6UtvnU38h5XxNlVS1C7nZ/hydeBeQy2 oEScIyBVzCQxho0ejpQkFpalWq9WIz8Oy9o+9rwldDdTBkR7EasLivFKacnt/9nw awLs6BMJz72PJ85Pzmeb6AE= Received: (qmail 98500 invoked by alias); 16 Aug 2018 04:50:33 -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 98288 invoked by uid 89); 16 Aug 2018 04:50:32 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.0 required=5.0 tests=GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS, TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=Limited, 2020, anticipation, Quick X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:21 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEj-0004cC-If for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:17 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=U2glJoMlxXgYUS1sYn6tEJ2MfmXjUINmA3E9WCcs6MM=; b=bZ/lSBYCe3+yQrObRrs0UpMbDY HTGWqK0bgJfV3+uDNLGt0OPTeKlNzxetamWm8uoy4t2XvJmjlMXDZZDhwVqD33k8bYGcYF1W04o6u Lt4xjYxSm7AzPqglYfXwHRzdii4ceGNm+4gYVKYaB5iapab73YyrWFlsJXGrCdtrXJbERwUUk/Qbm 57Kh/S7BL6q4nvWdvDe2auxNRCN65LnMW2JenSXGrJXveK5f4WM4cRBlAtFmG7/zpwrmWzEovDkJz qbq8AXDzLHUF9fxOI5g3x1tb6zxbFnBxvqyA0Rj0euIbQ4JYjjZYnFxpizulKrAYxUO9xSxki9fEm TfofBWJA==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEc-0004j3-6w; Thu, 16 Aug 2018 07:50:17 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 01/10] Initial TI PRU GCC port Date: Thu, 16 Aug 2018 07:49:50 +0300 Message-Id: <20180816044959.12320-2-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=0.5 X-IsSubscribed: yes ChangeLog: 2018-07-27 Dimitar Dimitrov * configure: Regenerate. * configure.ac: Add PRU target. gcc/ChangeLog: 2018-07-27 Dimitar Dimitrov * common/config/pru/pru-common.c: New file. * config.gcc: Add PRU target. * config/pru/alu-zext.md: New file. * config/pru/constraints.md: New file. * config/pru/predicates.md: New file. * config/pru/pru-opts.h: New file. * config/pru/pru-passes.c: New file. * config/pru/pru-pragma.c: New file. * config/pru/pru-protos.h: New file. * config/pru/pru.c: New file. * config/pru/pru.h: New file. * config/pru/pru.md: New file. * config/pru/pru.opt: New file. * config/pru/t-pru: New file. * doc/extend.texi: Document PRU pragmas. * doc/invoke.texi: Document PRU-specific options. * doc/md.texi: Document PRU asm constraints. Signed-off-by: Dimitar Dimitrov Signed-off-by: Dimitar Dimitrov --- configure.ac | 7 + gcc/common/config/pru/pru-common.c | 36 + gcc/config.gcc | 9 + gcc/config/pru/alu-zext.md | 178 +++ gcc/config/pru/constraints.md | 88 ++ gcc/config/pru/predicates.md | 224 +++ gcc/config/pru/pru-opts.h | 31 + gcc/config/pru/pru-passes.c | 234 +++ gcc/config/pru/pru-pragma.c | 90 ++ gcc/config/pru/pru-protos.h | 72 + gcc/config/pru/pru.c | 3001 ++++++++++++++++++++++++++++++++++++ gcc/config/pru/pru.h | 551 +++++++ gcc/config/pru/pru.md | 956 ++++++++++++ gcc/config/pru/pru.opt | 53 + gcc/config/pru/t-pru | 31 + gcc/doc/extend.texi | 21 + gcc/doc/invoke.texi | 55 + gcc/doc/md.texi | 22 + 18 files changed, 5659 insertions(+) create mode 100644 gcc/common/config/pru/pru-common.c create mode 100644 gcc/config/pru/alu-zext.md create mode 100644 gcc/config/pru/constraints.md create mode 100644 gcc/config/pru/predicates.md create mode 100644 gcc/config/pru/pru-opts.h create mode 100644 gcc/config/pru/pru-passes.c create mode 100644 gcc/config/pru/pru-pragma.c create mode 100644 gcc/config/pru/pru-protos.h create mode 100644 gcc/config/pru/pru.c create mode 100644 gcc/config/pru/pru.h create mode 100644 gcc/config/pru/pru.md create mode 100644 gcc/config/pru/pru.opt create mode 100644 gcc/config/pru/t-pru diff --git a/configure.ac b/configure.ac index a0b0917dd55..11c9f72fc64 100644 --- a/configure.ac +++ b/configure.ac @@ -640,6 +640,10 @@ case "${target}" in powerpc-*-aix* | rs6000-*-aix*) noconfigdirs="$noconfigdirs target-libssp" ;; + pru-*-*) + # No hosted I/O support. + noconfigdirs="$noconfigdirs target-libssp" + ;; rl78-*-*) # libssp uses a misaligned load to trigger a fault, but the RL78 # doesn't fault for those - instead, it gives a build-time error @@ -824,6 +828,9 @@ case "${target}" in powerpc*-*-*) libgloss_dir=rs6000 ;; + pru-*-*) + libgloss_dir=pru + ;; sparc*-*-*) libgloss_dir=sparc ;; diff --git a/gcc/common/config/pru/pru-common.c b/gcc/common/config/pru/pru-common.c new file mode 100644 index 00000000000..e87d70ce9ca --- /dev/null +++ b/gcc/common/config/pru/pru-common.c @@ -0,0 +1,36 @@ +/* Common hooks for TI PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "diagnostic-core.h" +#include "tm.h" +#include "common/common-target.h" +#include "common/common-target-def.h" +#include "opts.h" +#include "flags.h" + +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_OPT_LOOP) + +#undef TARGET_EXCEPT_UNWIND_INFO +#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info + +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; diff --git a/gcc/config.gcc b/gcc/config.gcc index 17ca0cf0615..abf64b289c2 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -493,6 +493,9 @@ powerpc*-*-*) esac extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt" ;; +pru-*-*) + cpu_type=pru + ;; riscv*) cpu_type=riscv extra_objs="riscv-builtins.o riscv-c.o" @@ -2635,6 +2638,12 @@ powerpcle-*-eabi*) extra_options="${extra_options} rs6000/sysv4.opt" use_gcc_stdint=wrap ;; +pru*-*-*) + tm_file="elfos.h newlib-stdint.h ${tm_file}" + tmake_file="${tmake_file} pru/t-pru" + extra_objs="pru-pragma.o pru-passes.o" + use_gcc_stdint=wrap + ;; rs6000-ibm-aix6.* | powerpc-ibm-aix6.*) tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h" tmake_file="rs6000/t-aix52 t-slibgcc" diff --git a/gcc/config/pru/alu-zext.md b/gcc/config/pru/alu-zext.md new file mode 100644 index 00000000000..2112b08d3f4 --- /dev/null +++ b/gcc/config/pru/alu-zext.md @@ -0,0 +1,178 @@ +;; ALU operations with zero extensions +;; +;; Copyright (C) 2015-2018 Free Software Foundation, Inc. +;; Contributed by Dimitar Dimitrov +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_subst_attr "alu2_zext" "alu2_zext_subst" "_z" "_noz") + +(define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1") +(define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2") +(define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz") + +(define_subst_attr "bitalu_zext" "bitalu_zext_subst" "_z" "_noz") + +(define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt]) +(define_code_iterator ALUOP2 [neg not]) + +;; Arithmetic Operations + +(define_insn "add_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r,r,r") + (plus:EQD + (zero_extend:EQD + (match_operand:EQS0 1 "register_operand" "%r,r,r")) + (zero_extend:EQD + (match_operand:EQS1 2 "nonmemory_operand" "r,I,M"))))] + "" + "@ + add\\t%0, %1, %2 + add\\t%0, %1, %2 + sub\\t%0, %1, %n2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "sub_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r,r,r") + (minus:EQD + (zero_extend:EQD + (match_operand:EQS0 1 "reg_or_ubyte_operand" "r,r,I")) + (zero_extend:EQD + (match_operand:EQS1 2 "reg_or_ubyte_operand" "r,I,r"))))] + "" + "@ + sub\\t%0, %1, %2 + sub\\t%0, %1, %2 + rsb\\t%0, %2, %1" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +(define_insn "neg_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r") + (neg:EQD + (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))] + "" + "rsb\\t%0, %1, 0" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +(define_insn "one_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r") + (not:EQD + (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))] + "" + "not\\t%0, %1" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +; Specialized IOR/AND patterns for matching setbit/clearbit instructions. +; +; TODO - allow clrbit and setbit to support (1 << REG) constructs + +(define_insn "clearbit__" + [(set (match_operand:EQD 0 "register_operand" "=r") + (and:EQD + (zero_extend:EQD + (match_operand:EQS0 1 "register_operand" "r")) + (match_operand:EQD 2 "single_zero_operand" "n")))] + "" + "clr\\t%0, %1, %V2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "setbit__" + [(set (match_operand:EQD 0 "register_operand" "=r") + (ior:EQD + (zero_extend:EQD + (match_operand:EQS0 1 "register_operand" "r")) + (match_operand:EQD 2 "single_one_operand" "n")))] + "" + "set\\t%0, %1, %T2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +; Regular ALU ops +(define_insn "_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r") + (LOGICAL:EQD + (zero_extend:EQD + (match_operand:EQS0 1 "register_operand" "%r")) + (zero_extend:EQD + (match_operand:EQS1 2 "reg_or_ubyte_operand" "rI"))))] + "" + "\\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +; Shift ALU ops +(define_insn "_impl_" + [(set (match_operand:EQD 0 "register_operand" "=r") + (SHIFT:EQD + (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r")) + (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))] + "" + "\\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +;; Substitutions + +(define_subst "alu2_zext_subst" + [(set (match_operand:EQD 0 "" "") + (ALUOP2:EQD (zero_extend:EQD (match_operand:EQD 1 "" ""))))] + "" + [(set (match_dup 0) + (ALUOP2:EQD (match_dup 1)))]) + +(define_subst "bitalu_zext_subst" + [(set (match_operand:EQD 0 "" "") + (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1 "" "")) + (match_operand:EQD 2 "" "")))] + "" + [(set (match_dup 0) + (ALUOP3:EQD (match_dup 1) + (match_dup 2)))]) + +(define_subst "alu3_zext_subst" + [(set (match_operand:EQD 0 "" "") + (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1 "" "")) + (zero_extend:EQD (match_operand:EQD 2 "" ""))))] + "" + [(set (match_dup 0) + (ALUOP3:EQD (match_dup 1) + (match_dup 2)))]) + +(define_subst "alu3_zext_op1_subst" + [(set (match_operand:EQD 0 "" "") + (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1 "" "")) + (zero_extend:EQD (match_operand:EQS1 2 "" ""))))] + "" + [(set (match_dup 0) + (ALUOP3:EQD (match_dup 1) + (zero_extend:EQD (match_dup 2))))]) + +(define_subst "alu3_zext_op2_subst" + [(set (match_operand:EQD 0 "" "") + (ALUOP3:EQD (zero_extend:EQD (match_operand:EQS0 1 "" "")) + (zero_extend:EQD (match_operand:EQD 2 "" ""))))] + "" + [(set (match_dup 0) + (ALUOP3:EQD (zero_extend:EQD (match_dup 1)) + (match_dup 2)))]) diff --git a/gcc/config/pru/constraints.md b/gcc/config/pru/constraints.md new file mode 100644 index 00000000000..326c8e9907c --- /dev/null +++ b/gcc/config/pru/constraints.md @@ -0,0 +1,88 @@ +;; Constraint definitions for TI PRU. +;; Copyright (C) 2014-2018 Free Software Foundation, Inc. +;; Contributed by Dimitar Dimitrov +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +;; We use the following constraint letters for constants: +;; +;; I: 0 to 255. +;; J: 0 to 65535. +;; L: 0 to 31 (for shift counts). +;; M: -255 to 0 (for converting ADD to SUB with suitable UBYTE OP2). +;; N: -32768 to 32767 (16-bit signed integer) +;; P: 1 +;; T: Text segment label. Needed to know when to select %pmem relocation. +;; Z: Constant integer zero. +;; +;; We use the following built-in register classes: +;; +;; r: general purpose register (r0..r31) +;; m: memory operand +;; +;; The following constraints are intended for internal use only: +;; j: jump address register suitable for sibling calls +;; l: the internal counter register used by LOOP instructions + +;; Register constraints. + +(define_register_constraint "j" "SIB_REGS" + "A register suitable for an indirect sibcall.") + +(define_register_constraint "l" "LOOPCNTR_REGS" + "The internal counter register used by the LOOP instruction.") + +;; Integer constraints. + +(define_constraint "I" + "An unsigned 8-bit constant." + (and (match_code "const_int") + (match_test "UBYTE_INT (ival)"))) + +(define_constraint "J" + "An unsigned 16-bit constant." + (and (match_code "const_int") + (match_test "UHWORD_INT (ival)"))) + +(define_constraint "L" + "An unsigned 5-bit constant (for shift counts)." + (and (match_code "const_int") + (match_test "ival >= 0 && ival <= 31"))) + +(define_constraint "M" + "A constant in the range [-255;0]." + (and (match_code "const_int") + (match_test "UBYTE_INT (-ival)"))) + +(define_constraint "N" + "A constant in the range [-32768;32767]." + (and (match_code "const_int") + (match_test "SHWORD_INT (ival)"))) + +(define_constraint "P" + "A constant 1." + (and (match_code "const_int") + (match_test "ival == 1"))) + +(define_constraint "T" + "A text segment (program memory) constant label." + (match_test "text_segment_operand (op, VOIDmode)")) + +(define_constraint "Z" + "An integer constant zero." + (and (match_code "const_int") + (match_test "ival == 0"))) diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md new file mode 100644 index 00000000000..78fdb8a25b7 --- /dev/null +++ b/gcc/config/pru/predicates.md @@ -0,0 +1,224 @@ +;; Predicate definitions for TI PRU. +;; Copyright (C) 2014-2018 Free Software Foundation, Inc. +;; Contributed by Dimitar Dimitrov +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_predicate "const_1_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 1, 1)"))) + +(define_predicate "const_ubyte_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 0xff)"))) + +(define_predicate "const_uhword_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 0xffff)"))) + +; TRUE for comparisons we support. +(define_predicate "pru_cmp_operator" + (match_code "eq,ne,leu,ltu,geu,gtu")) + +; TRUE for signed comparisons that need special handling for PRU. +(define_predicate "pru_signed_cmp_operator" + (match_code "ge,gt,le,lt")) + +;; FP Comparisons handled by pru_expand_pru_compare. +(define_predicate "pru_fp_comparison_operator" + (match_code "eq,lt,gt,le,ge")) + +;; Return true if OP is a constant that contains only one 1 in its +;; binary representation. +(define_predicate "single_one_operand" + (and (match_code "const_int") + (match_test "exact_log2 (INTVAL (op) & GET_MODE_MASK (mode)) >= 0"))) + +;; Return true if OP is a constant that contains only one 0 in its +;; binary representation. +(define_predicate "single_zero_operand" + (and (match_code "const_int") + (match_test "exact_log2 (~INTVAL (op) & GET_MODE_MASK (mode)) >= 0"))) + + +(define_predicate "reg_or_ubyte_operand" + (ior (match_operand 0 "const_ubyte_operand") + (match_operand 0 "register_operand"))) + +(define_predicate "reg_or_const_1_operand" + (ior (match_operand 0 "const_1_operand") + (match_operand 0 "register_operand"))) + +(define_predicate "const_shift_operand" + (and (match_code "const_int") + (match_test "SHIFT_INT (INTVAL (op))"))) + +(define_predicate "shift_operand" + (ior (match_operand 0 "const_shift_operand") + (match_operand 0 "register_operand"))) + +(define_predicate "ctable_addr_operand" + (and (match_code "const_int") + (match_test ("(pru_get_ctable_base_index (INTVAL (op)) >= 0)")))) + +(define_predicate "ctable_base_operand" + (and (match_code "const_int") + (match_test ("(pru_get_ctable_exact_base_index (INTVAL (op)) >= 0)")))) + +;; Ideally we should enforce a restriction to all text labels to fit in +;; 16bits, as required by the PRU ISA. But for the time being we'll rely on +;; binutils to catch text segment overflows. +(define_predicate "call_operand" + (ior (match_operand 0 "immediate_operand") + (match_operand 0 "register_operand"))) + +;; Return true if OP is a text segment reference. +;; This is needed for program memory address expressions. Borrowed from AVR. +(define_predicate "text_segment_operand" + (match_code "code_label,label_ref,symbol_ref,plus,minus,const") +{ + switch (GET_CODE (op)) + { + case CODE_LABEL: + return true; + case LABEL_REF : + return true; + case SYMBOL_REF : + return SYMBOL_REF_FUNCTION_P (op); + case PLUS : + case MINUS : + /* Assume canonical format of symbol + constant. + Fall through. */ + case CONST : + return text_segment_operand (XEXP (op, 0), VOIDmode); + default : + return false; + } +}) + +;; Return true if OP is a load multiple operation. It is known to be a +;; PARALLEL and the first section will be tested. + +(define_special_predicate "load_multiple_operation" + (match_code "parallel") +{ + machine_mode elt_mode; + int count = XVECLEN (op, 0); + unsigned int dest_regno; + rtx src_addr; + int i, off; + + /* Perform a quick check so we don't blow up below. */ + if (GET_CODE (XVECEXP (op, 0, 0)) != SET + || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG + || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) + return false; + + dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); + src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); + elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0))); + + /* Check, is base, or base + displacement. */ + + if (GET_CODE (src_addr) == REG) + off = 0; + else if (GET_CODE (src_addr) == PLUS + && GET_CODE (XEXP (src_addr, 0)) == REG + && GET_CODE (XEXP (src_addr, 1)) == CONST_INT) + { + off = INTVAL (XEXP (src_addr, 1)); + src_addr = XEXP (src_addr, 0); + } + else + return false; + + for (i = 1; i < count; i++) + { + rtx elt = XVECEXP (op, 0, i); + + if (GET_CODE (elt) != SET + || GET_CODE (SET_DEST (elt)) != REG + || GET_MODE (SET_DEST (elt)) != elt_mode + || REGNO (SET_DEST (elt)) != dest_regno + i + || GET_CODE (SET_SRC (elt)) != MEM + || GET_MODE (SET_SRC (elt)) != elt_mode + || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS + || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) + || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT + || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) + != off + i * GET_MODE_SIZE (elt_mode)) + return false; + } + + return true; +}) + +;; Return true if OP is a store multiple operation. It is known to be a +;; PARALLEL and the first section will be tested. + +(define_special_predicate "store_multiple_operation" + (match_code "parallel") +{ + machine_mode elt_mode; + int count = XVECLEN (op, 0); + unsigned int src_regno; + rtx dest_addr; + int i, off; + + /* Perform a quick check so we don't blow up below. */ + if (GET_CODE (XVECEXP (op, 0, 0)) != SET + || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM + || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) + return false; + + src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); + dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); + elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0))); + + /* Check, is base, or base + displacement. */ + + if (GET_CODE (dest_addr) == REG) + off = 0; + else if (GET_CODE (dest_addr) == PLUS + && GET_CODE (XEXP (dest_addr, 0)) == REG + && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT) + { + off = INTVAL (XEXP (dest_addr, 1)); + dest_addr = XEXP (dest_addr, 0); + } + else + return false; + + for (i = 1; i < count; i++) + { + rtx elt = XVECEXP (op, 0, i); + + if (GET_CODE (elt) != SET + || GET_CODE (SET_SRC (elt)) != REG + || GET_MODE (SET_SRC (elt)) != elt_mode + || REGNO (SET_SRC (elt)) != src_regno + i + || GET_CODE (SET_DEST (elt)) != MEM + || GET_MODE (SET_DEST (elt)) != elt_mode + || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS + || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) + || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT + || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) + != off + i * GET_MODE_SIZE (elt_mode)) + return false; + } + return true; +}) diff --git a/gcc/config/pru/pru-opts.h b/gcc/config/pru/pru-opts.h new file mode 100644 index 00000000000..1c1514cb2a3 --- /dev/null +++ b/gcc/config/pru/pru-opts.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2017-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +/* Definitions for option handling for PRU. */ + +#ifndef GCC_PRU_OPTS_H +#define GCC_PRU_OPTS_H + +/* ABI variant for code generation. */ +enum pru_abi { + PRU_ABI_GNU, + PRU_ABI_TI +}; + +#endif diff --git a/gcc/config/pru/pru-passes.c b/gcc/config/pru/pru-passes.c new file mode 100644 index 00000000000..c95dc877722 --- /dev/null +++ b/gcc/config/pru/pru-passes.c @@ -0,0 +1,234 @@ +/* PRU target specific passes + Copyright (C) 2017-2018 Free Software Foundation, Inc. + Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "context.h" +#include "tm.h" +#include "alias.h" +#include "symtab.h" +#include "tree.h" +#include "diagnostic-core.h" +#include "function.h" +#include "gimple.h" +#include "gimple-iterator.h" +#include "gimple-walk.h" +#include "gimple-expr.h" +#include "tree-pass.h" +#include "gimple-pretty-print.h" + +#include "pru-protos.h" + +namespace { + +/* Scan the tree to ensure that the compiled code by GCC + conforms to the TI ABI specification. If GCC cannot + output a conforming code, raise an error. */ +const pass_data pass_data_tiabi_check = +{ + GIMPLE_PASS, /* type */ + "*tiabi_check", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + PROP_gimple_any, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +/* Implementation class for the TI ABI compliance-check pass. */ +class pass_tiabi_check : public gimple_opt_pass +{ +public: + pass_tiabi_check (gcc::context *ctxt) + : gimple_opt_pass (pass_data_tiabi_check, ctxt) + {} + + /* opt_pass methods: */ + virtual unsigned int execute (function *); + + virtual bool gate (function *fun ATTRIBUTE_UNUSED) + { + return pru_current_abi == PRU_ABI_TI; + } + +}; // class pass_tiabi_check + +/* Return 1 if type TYPE is a pointer to function type or a + structure having a pointer to function type as one of its fields. + Otherwise return 0. */ +static bool +chkp_type_has_function_pointer (const_tree type) +{ + bool res = false; + + if (POINTER_TYPE_P (type) && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type))) + res = true; + else if (RECORD_OR_UNION_TYPE_P (type)) + { + tree field; + + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL) + res = res || chkp_type_has_function_pointer (TREE_TYPE (field)); + } + else if (TREE_CODE (type) == ARRAY_TYPE) + res = chkp_type_has_function_pointer (TREE_TYPE (type)); + + return res; +} + +/* Check the function declaration FNTYPE for TI ABI compatibility. */ +static void +chk_function_decl (const_tree fntype, location_t call_location) +{ + /* GCC does not check if the RETURN VALUE pointer is NULL, + so do not allow GCC functions with large return values. */ + if (!VOID_TYPE_P (TREE_TYPE (fntype)) + && pru_return_in_memory (TREE_TYPE (fntype), fntype)) + error_at (call_location, + "large return values not supported with %<-mabi=ti%> option"); + + /* Check this function's arguments. */ + for (tree p = TYPE_ARG_TYPES (fntype); p; p = TREE_CHAIN (p)) + { + tree arg_type = TREE_VALUE (p); + if (chkp_type_has_function_pointer (arg_type)) + { + error_at (call_location, + "function pointers not supported with %<-mabi=ti%> option"); + } + } +} + +/* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance. */ +static tree +check_op_callback (tree *tp, int *walk_subtrees, void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; + + if (RECORD_OR_UNION_TYPE_P (*tp) || TREE_CODE (*tp) == ENUMERAL_TYPE) + { + /* Forward declarations have NULL tree type. Skip them. */ + if (TREE_TYPE (*tp) == NULL) + return NULL; + } + + /* TODO - why C++ leaves INTEGER_TYPE forward declarations around? */ + if (TREE_TYPE (*tp) == NULL) + return NULL; + + const tree type = TREE_TYPE (*tp); + + /* Direct function calls are allowed, obviously. */ + if (TREE_CODE (*tp) == ADDR_EXPR && TREE_CODE (type) == POINTER_TYPE) + { + const tree ptype = TREE_TYPE (type); + if (TREE_CODE (ptype) == FUNCTION_TYPE) + return NULL; + } + + switch (TREE_CODE (type)) + { + case FUNCTION_TYPE: + case METHOD_TYPE: + { + /* Note: Do not enforce a small return value. It is safe to + call any TI ABI function from GCC, since GCC will + never pass NULL. */ + + /* Check arguments for function pointers. */ + for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p)) + { + tree arg_type = TREE_VALUE (p); + if (chkp_type_has_function_pointer (arg_type)) + { + error_at (gimple_location (wi->stmt), "function pointers " + "not supported with %<-mabi=ti%> option"); + } + } + break; + } + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + case POINTER_TYPE: + { + if (chkp_type_has_function_pointer (type)) + { + error_at (gimple_location (wi->stmt), + "function pointers not supported with " + "%<-mabi=ti%> option"); + *walk_subtrees = false; + } + break; + } + default: + break; + } + return NULL; +} + +/* Pass implementation. */ +unsigned +pass_tiabi_check::execute (function *fun) +{ + struct walk_stmt_info wi; + const_tree fntype = TREE_TYPE (fun->decl); + + gimple_seq body = gimple_body (current_function_decl); + + memset (&wi, 0, sizeof (wi)); + wi.info = NULL; + wi.want_locations = true; + + /* Check the function body. */ + walk_gimple_seq (body, NULL, check_op_callback, &wi); + + /* Check the function declaration. */ + chk_function_decl (fntype, fun->function_start_locus); + + return 0; +} + +} // anon namespace + +gimple_opt_pass * +make_pass_tiabi_check (gcc::context *ctxt) +{ + return new pass_tiabi_check (ctxt); +} + +/* Register as early as possible. */ +void +pru_register_abicheck_pass (void) +{ + opt_pass *tiabi_check = make_pass_tiabi_check (g); + struct register_pass_info tiabi_check_info + = { tiabi_check, "*warn_unused_result", + 1, PASS_POS_INSERT_AFTER + }; + register_pass (&tiabi_check_info); +} diff --git a/gcc/config/pru/pru-pragma.c b/gcc/config/pru/pru-pragma.c new file mode 100644 index 00000000000..11cb5bd625c --- /dev/null +++ b/gcc/config/pru/pru-pragma.c @@ -0,0 +1,90 @@ +/* PRU target specific pragmas + Copyright (C) 2015-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "alias.h" +#include "symtab.h" +#include "tree.h" +#include "c-family/c-pragma.h" +#include "c-family/c-common.h" +#include "diagnostic-core.h" +#include "cpplib.h" +#include "pru-protos.h" + + +/* Implements the "pragma CTABLE_ENTRY" pragma. This pragma takes a + CTABLE index and an address, and instructs the compiler that + LBCO/SBCO can be used on that base address. + + WARNING: Only immediate constant addresses are currently supported. */ +static void +pru_pragma_ctable_entry (cpp_reader * reader ATTRIBUTE_UNUSED) +{ + tree ctable_index, base_addr; + enum cpp_ttype type; + + type = pragma_lex (&ctable_index); + if (type == CPP_NUMBER) + { + type = pragma_lex (&base_addr); + if (type == CPP_NUMBER) + { + unsigned int i = tree_to_uhwi (ctable_index); + unsigned HOST_WIDE_INT base = tree_to_uhwi (base_addr); + + type = pragma_lex (&base_addr); + if (type != CPP_EOF) + { + error ("junk at end of %<#pragma CTABLE_ENTRY%>"); + } + else if (i >= ARRAY_SIZE (pru_ctable)) + { + error ("% index %d is not valid", i); + } + else if (pru_ctable[i].valid && pru_ctable[i].base != base) + { + error ("redefinition of %", i); + } + else + { + if (base & 0xff) + warning (0, "% base address is not " + "a multiple of 256"); + pru_ctable[i].base = base; + pru_ctable[i].valid = true; + } + return; + } + } + error ("malformed %<#pragma CTABLE_ENTRY%> variable address"); +} + +/* Implements REGISTER_TARGET_PRAGMAS. */ +void +pru_register_pragmas (void) +{ + c_register_pragma (NULL, "ctable_entry", pru_pragma_ctable_entry); + c_register_pragma (NULL, "CTABLE_ENTRY", pru_pragma_ctable_entry); +} diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h new file mode 100644 index 00000000000..73ab76e076c --- /dev/null +++ b/gcc/config/pru/pru-protos.h @@ -0,0 +1,72 @@ +/* Subroutine declarations for TI PRU target support. + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#ifndef GCC_PRU_PROTOS_H +#define GCC_PRU_PROTOS_H + +struct pru_ctable_entry { + bool valid; + unsigned HOST_WIDE_INT base; +}; + +extern struct pru_ctable_entry pru_ctable[32]; + +extern int pru_initial_elimination_offset (int, int); +extern int pru_can_use_return_insn (void); +extern void pru_expand_prologue (void); +extern void pru_expand_epilogue (bool); +extern void pru_function_profiler (FILE *, int); + +void pru_register_pragmas (void); + +#ifdef RTX_CODE +extern rtx pru_get_return_address (int); +extern int pru_hard_regno_rename_ok (unsigned int, unsigned int); + +extern const char * pru_output_sign_extend (rtx *); +extern const char * pru_output_signed_cbranch (rtx *, bool); +extern const char * pru_output_signed_cbranch_ubyteop2 (rtx *, bool); +extern const char * pru_output_signed_cbranch_zeroop2 (rtx *, bool); + +extern rtx pru_expand_fp_compare (rtx comparison, machine_mode mode); + +extern void pru_emit_doloop (rtx *, int); + +extern bool pru_regno_ok_for_base_p (int, bool); + +static inline bool +pru_regno_ok_for_index_p (int regno, bool strict_p) +{ + /* Selection logic is the same - PRU instructions are quite orthogonal. */ + return pru_regno_ok_for_base_p (regno, strict_p); +} + +extern int pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr); +extern int pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr); +extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr); + +extern void pru_register_abicheck_pass (void); +#endif /* RTX_CODE */ + +#ifdef TREE_CODE +bool pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED); +#endif /* TREE_CODE */ + +#endif /* GCC_PRU_PROTOS_H */ diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c new file mode 100644 index 00000000000..de72d22278e --- /dev/null +++ b/gcc/config/pru/pru.c @@ -0,0 +1,3001 @@ +/* Target machine subroutines for TI PRU. + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#define IN_TARGET_CODE 1 + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "target.h" +#include "rtl.h" +#include "tree.h" +#include "stringpool.h" +#include "attribs.h" +#include "df.h" +#include "memmodel.h" +#include "tm_p.h" +#include "optabs.h" +#include "regs.h" +#include "emit-rtl.h" +#include "recog.h" +#include "diagnostic-core.h" +#include "output.h" +#include "insn-attr.h" +#include "flags.h" +#include "explow.h" +#include "calls.h" +#include "varasm.h" +#include "expr.h" +#include "toplev.h" +#include "langhooks.h" +#include "cfgrtl.h" +#include "stor-layout.h" +#include "dumpfile.h" +#include "builtins.h" +#include "pru-protos.h" + +/* This file should be included last. */ +#include "target-def.h" + +#define INIT_ARRAY_ENTRY_BYTES 2 + +/* Global PRU CTABLE entries, filled in by pragmas, and used for fast + addressing via LBCO/SBCO instructions. */ +struct pru_ctable_entry pru_ctable[32]; + +/* Forward function declarations. */ +static bool prologue_saved_reg_p (int); +static void pru_reorg_loop (rtx_insn *); + +struct GTY (()) machine_function +{ + /* Current frame information, to be filled in by pru_compute_frame_layout + with register save masks, and offsets for the current function. */ + + /* Mask of registers to save. */ + HARD_REG_SET save_mask; + /* Number of bytes that the entire frame takes up. */ + int total_size; + /* Number of bytes that variables take up. */ + int var_size; + /* Number of bytes that outgoing arguments take up. */ + int args_size; + /* Number of bytes needed to store registers in frame. */ + int save_reg_size; + /* Offset from new stack pointer to store registers. */ + int save_regs_offset; + /* Offset from save_regs_offset to store frame pointer register. */ + int fp_save_offset; + /* != 0 if frame layout already calculated. */ + int initialized; + /* Number of doloop tags used so far. */ + int doloop_tags; + /* True if the last tag was allocated to a doloop_end. */ + bool doloop_tag_from_end; +}; + +/* Stack layout and calling conventions. */ + +#define PRU_STACK_ALIGN(LOC) ROUND_UP((LOC), STACK_BOUNDARY / BITS_PER_UNIT) + +/* Return the bytes needed to compute the frame pointer from the current + stack pointer. */ +static int +pru_compute_frame_layout (void) +{ + int regno; + HARD_REG_SET *save_mask; + int total_size; + int var_size; + int out_args_size; + int save_reg_size; + + if (cfun->machine->initialized) + return cfun->machine->total_size; + + save_mask = &cfun->machine->save_mask; + CLEAR_HARD_REG_SET (*save_mask); + + var_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) get_frame_size ()); + out_args_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) crtl->outgoing_args_size); + total_size = var_size + out_args_size; + + /* Calculate space needed for gp registers. */ + save_reg_size = 0; + for (regno = 0; regno <= LAST_GP_REG; regno++) + if (prologue_saved_reg_p (regno)) + { + SET_HARD_REG_BIT (*save_mask, regno); + save_reg_size += 1; + } + + cfun->machine->fp_save_offset = 0; + if (TEST_HARD_REG_BIT (*save_mask, HARD_FRAME_POINTER_REGNUM)) + { + int fp_save_offset = 0; + for (regno = 0; regno < HARD_FRAME_POINTER_REGNUM; regno++) + if (TEST_HARD_REG_BIT (*save_mask, regno)) + fp_save_offset += 1; + + cfun->machine->fp_save_offset = fp_save_offset; + } + + save_reg_size = PRU_STACK_ALIGN (save_reg_size); + total_size += save_reg_size; + total_size += PRU_STACK_ALIGN (crtl->args.pretend_args_size); + + /* Save other computed information. */ + cfun->machine->total_size = total_size; + cfun->machine->var_size = var_size; + cfun->machine->args_size = out_args_size; + cfun->machine->save_reg_size = save_reg_size; + cfun->machine->initialized = reload_completed; + cfun->machine->save_regs_offset = out_args_size + var_size; + + return total_size; +} + +/* Emit efficient RTL equivalent of ADD3 with the given const_int for + frame-related registers. + op0 - Destination register. + op1 - First addendum operand (a register). + addendum - Second addendum operand (a constant). + kind - Note kind. REG_NOTE_MAX if no note must be added. + reg_note_rtx - Reg note RTX. NULL if it should be computed automatically. + */ +static rtx +pru_add3_frame_adjust (rtx op0, rtx op1, int addendum, + const enum reg_note kind, rtx reg_note_rtx) +{ + rtx insn; + + rtx op0_adjust = gen_rtx_SET (op0, plus_constant (Pmode, op1, addendum)); + + if (UBYTE_INT (addendum) || UBYTE_INT (-addendum)) + insn = emit_insn (op0_adjust); + else + { + /* Help the compiler to cope with an arbitrary integer constant. + Reload has finished so we can't expect the compiler to + auto-allocate a temporary register. But we know that call-saved + registers are not live yet, so we utilize them. */ + rtx tmpreg = gen_rtx_REG (Pmode, PROLOGUE_TEMP_REGNO); + if (addendum < 0) + { + emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (-addendum, Pmode))); + insn = emit_insn (gen_sub3_insn (op0, op1, tmpreg)); + } + else + { + emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (addendum, Pmode))); + insn = emit_insn (gen_add3_insn (op0, op1, tmpreg)); + } + } + + /* Attach a note indicating what happened. */ + if (reg_note_rtx == NULL_RTX) + reg_note_rtx = copy_rtx (op0_adjust); + if (kind != REG_NOTE_MAX) + add_reg_note (insn, kind, reg_note_rtx); + + RTX_FRAME_RELATED_P (insn) = 1; + + return insn; +} + +/* Add a const_int to the stack pointer register. */ +static rtx +pru_add_to_sp (int addendum, const enum reg_note kind) +{ + return pru_add3_frame_adjust (stack_pointer_rtx, stack_pointer_rtx, + addendum, kind, NULL_RTX); +} + +/* Helper function used during prologue/epilogue. Emits a single LBBO/SBBO + instruction for load/store of the next group of consecutive registers. */ +static int +xbbo_next_reg_cluster (int regno_start, int *sp_offset, bool do_store) +{ + int regno, nregs, i; + rtx addr; + rtx_insn *insn; + + nregs = 0; + + /* Skip the empty slots. */ + for (; regno_start <= LAST_GP_REG;) + if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno_start)) + break; + else + regno_start++; + + /* Find the largest consecutive group of registers to save. */ + for (regno = regno_start; regno <= LAST_GP_REG;) + if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno)) + { + regno++; + nregs++; + } + else + break; + + if (!nregs) + return -1; + + gcc_assert (UBYTE_INT (*sp_offset)); + + /* Ok, save this bunch. */ + addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, + gen_int_mode (*sp_offset, Pmode)); + + if (do_store) + insn = targetm.gen_store_multiple (gen_frame_mem (BLKmode, addr), + gen_rtx_REG (QImode, regno_start), + GEN_INT (nregs)); + else + insn = targetm.gen_load_multiple (gen_rtx_REG (QImode, regno_start), + gen_frame_mem (BLKmode, addr), + GEN_INT (nregs)); + + gcc_assert (reload_completed); + gcc_assert (insn); + emit_insn (insn); + + /* Tag as frame-related. */ + RTX_FRAME_RELATED_P (insn) = 1; + + if (!do_store) + { + /* Tag epilogue unwind notes. */ + for (i = regno_start; i < (regno_start + nregs); i++) + add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (QImode, i)); + } + + /* Increment and save offset in anticipation of the next register group. */ + *sp_offset += nregs * UNITS_PER_WORD; + + return regno_start + nregs; +} + +/* Emit function prologue. */ +void +pru_expand_prologue (void) +{ + int regno_start; + int total_frame_size; + int sp_offset; /* Offset from base_reg to final stack value. */ + int save_regs_base; /* Offset from base_reg to register save area. */ + int save_offset; /* Temporary offset to currently saved register group. */ + rtx insn; + + total_frame_size = pru_compute_frame_layout (); + + if (flag_stack_usage_info) + current_function_static_stack_size = total_frame_size; + + /* Decrement the stack pointer. */ + if (!UBYTE_INT (total_frame_size)) + { + /* We need an intermediary point, this will point at the spill block. */ + insn = pru_add_to_sp (cfun->machine->save_regs_offset + - total_frame_size, + REG_NOTE_MAX); + save_regs_base = 0; + sp_offset = -cfun->machine->save_regs_offset; + } + else if (total_frame_size) + { + insn = emit_insn (gen_sub2_insn (stack_pointer_rtx, + gen_int_mode (total_frame_size, + Pmode))); + RTX_FRAME_RELATED_P (insn) = 1; + save_regs_base = cfun->machine->save_regs_offset; + sp_offset = 0; + } + else + save_regs_base = sp_offset = 0; + + regno_start = 0; + save_offset = save_regs_base; + do { + regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, true); + } while (regno_start >= 0); + + if (frame_pointer_needed) + { + int fp_save_offset = save_regs_base + cfun->machine->fp_save_offset; + pru_add3_frame_adjust (hard_frame_pointer_rtx, + stack_pointer_rtx, + fp_save_offset, + REG_NOTE_MAX, + NULL_RTX); + } + + if (sp_offset) + pru_add_to_sp (sp_offset, REG_FRAME_RELATED_EXPR); + + /* If we are profiling, make sure no instructions are scheduled before + the call to mcount. */ + if (crtl->profile) + emit_insn (gen_blockage ()); +} + +/* Emit function epilogue. */ +void +pru_expand_epilogue (bool sibcall_p) +{ + rtx cfa_adj; + int total_frame_size; + int sp_adjust, save_offset; + int regno_start; + + if (!sibcall_p && pru_can_use_return_insn ()) + { + emit_jump_insn (gen_return ()); + return; + } + + emit_insn (gen_blockage ()); + + total_frame_size = pru_compute_frame_layout (); + if (frame_pointer_needed) + { + /* Recover the stack pointer. */ + cfa_adj = plus_constant (Pmode, stack_pointer_rtx, + (total_frame_size + - cfun->machine->save_regs_offset)); + pru_add3_frame_adjust (stack_pointer_rtx, + hard_frame_pointer_rtx, + -cfun->machine->fp_save_offset, + REG_CFA_DEF_CFA, + cfa_adj); + + save_offset = 0; + sp_adjust = total_frame_size - cfun->machine->save_regs_offset; + } + else if (!UBYTE_INT (total_frame_size)) + { + pru_add_to_sp (cfun->machine->save_regs_offset, + REG_CFA_ADJUST_CFA); + save_offset = 0; + sp_adjust = total_frame_size - cfun->machine->save_regs_offset; + } + else + { + save_offset = cfun->machine->save_regs_offset; + sp_adjust = total_frame_size; + } + + regno_start = 0; + do { + regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, false); + } while (regno_start >= 0); + + if (sp_adjust) + pru_add_to_sp (sp_adjust, REG_CFA_ADJUST_CFA); + + if (!sibcall_p) + emit_jump_insn (gen_simple_return ()); +} + +/* Implement RETURN_ADDR_RTX. Note, we do not support moving + back to a previous frame. */ +rtx +pru_get_return_address (int count) +{ + if (count != 0) + return NULL_RTX; + + /* Return r3.w2. */ + return get_hard_reg_initial_val (HImode, RA_REGNO); +} + +/* Implement FUNCTION_PROFILER macro. */ +void +pru_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) +{ + fprintf (file, "\tmov\tr1, ra\n"); + fprintf (file, "\tcall\t_mcount\n"); + fprintf (file, "\tmov\tra, r1\n"); +} + +/* Dump stack layout. */ +static void +pru_dump_frame_layout (FILE *file) +{ + fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START); + fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START, + cfun->machine->total_size); + fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START, + cfun->machine->var_size); + fprintf (file, "\t%s args_size = %d\n", ASM_COMMENT_START, + cfun->machine->args_size); + fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START, + cfun->machine->save_reg_size); + fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START, + cfun->machine->initialized); + fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START, + cfun->machine->save_regs_offset); + fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START, + crtl->is_leaf); + fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START, + frame_pointer_needed); + fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START, + crtl->args.pretend_args_size); +} + +/* Return true if REGNO should be saved in the prologue. */ +static bool +prologue_saved_reg_p (int regno) +{ + gcc_assert (GP_REG_P (regno)); + + if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) + return true; + + /* 32-bit FP. */ + if (frame_pointer_needed + && regno >= HARD_FRAME_POINTER_REGNUM + && regno < HARD_FRAME_POINTER_REGNUM + GET_MODE_SIZE (Pmode)) + return true; + + /* 16-bit RA. */ + if (regno == RA_REGNO && df_regs_ever_live_p (RA_REGNO)) + return true; + if (regno == RA_REGNO + 1 && df_regs_ever_live_p (RA_REGNO + 1)) + return true; + + return false; +} + +/* Implement TARGET_CAN_ELIMINATE. */ +static bool +pru_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) +{ + if (to == STACK_POINTER_REGNUM) + return !frame_pointer_needed; + return true; +} + +/* Implement INITIAL_ELIMINATION_OFFSET macro. */ +int +pru_initial_elimination_offset (int from, int to) +{ + int offset; + + pru_compute_frame_layout (); + + /* Set OFFSET to the offset from the stack pointer. */ + switch (from) + { + case FRAME_POINTER_REGNUM: + offset = cfun->machine->args_size; + break; + + case ARG_POINTER_REGNUM: + offset = cfun->machine->total_size; + offset -= crtl->args.pretend_args_size; + break; + + default: + gcc_unreachable (); + } + + /* If we are asked for the frame pointer offset, then adjust OFFSET + by the offset from the frame pointer to the stack pointer. */ + if (to == HARD_FRAME_POINTER_REGNUM) + offset -= (cfun->machine->save_regs_offset + + cfun->machine->fp_save_offset); + + return offset; +} + +/* Return nonzero if this function is known to have a null epilogue. + This allows the optimizer to omit jumps to jumps if no stack + was created. */ +int +pru_can_use_return_insn (void) +{ + if (!reload_completed || crtl->profile) + return 0; + + return pru_compute_frame_layout () == 0; +} + +/* Implement TARGET_MODES_TIEABLE_P. */ + +static bool +pru_modes_tieable_p (machine_mode mode1, machine_mode mode2) +{ + return (mode1 == mode2 + || (GET_MODE_SIZE (mode1) <= 4 && GET_MODE_SIZE (mode2) <= 4)); +} + +/* Implement TARGET_HARD_REGNO_MODE_OK. */ + +static bool +pru_hard_regno_mode_ok (unsigned int regno, machine_mode mode) +{ + switch (GET_MODE_SIZE (mode)) + { + case 1: return true; + case 2: return (regno % 4) <= 2; + case 4: return (regno % 4) == 0; + default: return (regno % 4) == 0; /* Not sure why VOIDmode is passed. */ + } +} + +/* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. + Returns true if REGNO is safe to be allocated as a scratch + register (for a define_peephole2) in the current function. */ + +static bool +pru_hard_regno_scratch_ok (unsigned int regno) +{ + /* Don't allow hard registers that might be part of the frame pointer. + Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM + and don't handle a frame pointer that spans more than one register. */ + + if ((!reload_completed || frame_pointer_needed) + && ((regno >= HARD_FRAME_POINTER_REGNUM + && regno <= HARD_FRAME_POINTER_REGNUM + 3) + || (regno >= FRAME_POINTER_REGNUM + && regno <= FRAME_POINTER_REGNUM + 3))) + { + return false; + } + + return true; +} + + +/* Worker function for `HARD_REGNO_RENAME_OK'. + Return nonzero if register OLD_REG can be renamed to register NEW_REG. */ + +int +pru_hard_regno_rename_ok (unsigned int old_reg, + unsigned int new_reg) +{ + /* Don't allow hard registers that might be part of the frame pointer. + Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM + and don't care for a frame pointer that spans more than one register. */ + if ((!reload_completed || frame_pointer_needed) + && ((old_reg >= HARD_FRAME_POINTER_REGNUM + && old_reg <= HARD_FRAME_POINTER_REGNUM + 3) + || (old_reg >= FRAME_POINTER_REGNUM + && old_reg <= FRAME_POINTER_REGNUM + 3) + || (new_reg >= HARD_FRAME_POINTER_REGNUM + && new_reg <= HARD_FRAME_POINTER_REGNUM + 3) + || (new_reg >= FRAME_POINTER_REGNUM + && new_reg <= FRAME_POINTER_REGNUM + 3))) + { + return 0; + } + + return 1; +} + +/* Allocate a chunk of memory for per-function machine-dependent data. */ +static struct machine_function * +pru_init_machine_status (void) +{ + return ggc_cleared_alloc (); +} + +/* Implement TARGET_OPTION_OVERRIDE. */ +static void +pru_option_override (void) +{ +#ifdef SUBTARGET_OVERRIDE_OPTIONS + SUBTARGET_OVERRIDE_OPTIONS; +#endif + + /* Check for unsupported options. */ + if (flag_pic == 1) + warning (OPT_fpic, "%<-fpic%> is not supported"); + if (flag_pic == 2) + warning (OPT_fPIC, "%<-fPIC%> is not supported"); + if (flag_pie == 1) + warning (OPT_fpie, "%<-fpie%> is not supported"); + if (flag_pie == 2) + warning (OPT_fPIE, "%<-fPIE%> is not supported"); + + /* QBxx conditional branching cannot cope with block reordering. */ + if (flag_reorder_blocks_and_partition) + { + inform (input_location, "%<-freorder-blocks-and-partition%> " + "not supported on this architecture"); + flag_reorder_blocks_and_partition = 0; + flag_reorder_blocks = 1; + } + + /* Function to allocate machine-dependent function status. */ + init_machine_status = &pru_init_machine_status; + + /* Save the initial options in case the user does function specific + options. */ + target_option_default_node = target_option_current_node + = build_target_option_node (&global_options); + + /* Due to difficulties in implementing the TI ABI with GCC, + at least check and error-out if GCC cannot compile a + compliant output. */ + pru_register_abicheck_pass (); +} + +/* Compute a (partial) cost for rtx X. Return true if the complete + cost has been computed, and false if subexpressions should be + scanned. In either case, *TOTAL contains the cost result. */ +static bool +pru_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, + int outer_code, int opno ATTRIBUTE_UNUSED, + int *total, bool speed ATTRIBUTE_UNUSED) +{ + const int code = GET_CODE (x); + + switch (code) + { + case CONST_INT: + if (UBYTE_INT (INTVAL (x))) + { + *total = COSTS_N_INSNS (0); + return true; + } + else if (outer_code == MEM && ctable_addr_operand (x, VOIDmode)) + { + *total = COSTS_N_INSNS (0); + return true; + } + else if (UHWORD_INT (INTVAL (x))) + { + *total = COSTS_N_INSNS (1); + return true; + } + else + { + *total = COSTS_N_INSNS (2); + return true; + } + + case LABEL_REF: + case SYMBOL_REF: + case CONST: + case CONST_DOUBLE: + { + *total = COSTS_N_INSNS (1); + return true; + } + case SET: + { + /* A SET doesn't have a mode, so let's look at the SET_DEST to get + the mode for the factor. */ + mode = GET_MODE (SET_DEST (x)); + + if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (SImode) + && (GET_CODE (SET_SRC (x)) == ZERO_EXTEND + || outer_code == ZERO_EXTEND)) + { + *total = 0; + } + else + { + /* SI move has the same cost as a QI move. */ + int factor = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode); + if (factor == 0) + factor = 1; + *total = factor * COSTS_N_INSNS (1); + } + + return false; + } + + case MULT: + { + *total = COSTS_N_INSNS (8); + return false; + } + case PLUS: + { + rtx op0 = XEXP (x, 0); + rtx op1 = XEXP (x, 1); + if (outer_code == MEM + && ((REG_P (op0) && reg_or_ubyte_operand (op1, VOIDmode)) + || (REG_P (op1) && reg_or_ubyte_operand (op0, VOIDmode)) + || (ctable_addr_operand (op0, VOIDmode) && op1 == NULL_RTX) + || (ctable_addr_operand (op1, VOIDmode) && op0 == NULL_RTX) + || (ctable_base_operand (op0, VOIDmode) && REG_P (op1)) + || (ctable_base_operand (op1, VOIDmode) && REG_P (op0)))) + { + /* CTABLE or REG base addressing - PLUS comes for free. */ + *total = COSTS_N_INSNS (0); + return true; + } + else + { + *total = COSTS_N_INSNS (1); + return false; + } + } + case SIGN_EXTEND: + { + *total = COSTS_N_INSNS (3); + return false; + } + case ASHIFTRT: + { + rtx op1 = XEXP (x, 1); + if (const_1_operand (op1, VOIDmode)) + *total = COSTS_N_INSNS (2); + else + *total = COSTS_N_INSNS (6); + return false; + } + case ZERO_EXTRACT: + { + rtx op2 = XEXP (x, 2); + if ((outer_code == EQ || outer_code == NE) + && CONST_INT_P (op2) + && INTVAL (op2) == 1) + { + /* Branch if bit is set/clear is a single instruction. */ + *total = COSTS_N_INSNS (0); + return true; + } + else + { + *total = COSTS_N_INSNS (2); + return false; + } + } + + case ZERO_EXTEND: + { + *total = COSTS_N_INSNS (0); + return false; + } + + default: + { + /* Do not factor mode size in the cost. */ + *total = COSTS_N_INSNS (1); + return false; + } + } +} + +/* Implement TARGET_PREFERRED_RELOAD_CLASS. */ +static reg_class_t +pru_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t regclass) +{ + return regclass == NO_REGS ? GENERAL_REGS : regclass; +} + +static GTY(()) rtx eqdf_libfunc; +static GTY(()) rtx nedf_libfunc; +static GTY(()) rtx ledf_libfunc; +static GTY(()) rtx ltdf_libfunc; +static GTY(()) rtx gedf_libfunc; +static GTY(()) rtx gtdf_libfunc; +static GTY(()) rtx eqsf_libfunc; +static GTY(()) rtx nesf_libfunc; +static GTY(()) rtx lesf_libfunc; +static GTY(()) rtx ltsf_libfunc; +static GTY(()) rtx gesf_libfunc; +static GTY(()) rtx gtsf_libfunc; + +/* Implement the TARGET_INIT_LIBFUNCS macro. We use this to rename library + functions to match the PRU ABI. */ + +static void +pru_init_libfuncs (void) +{ + /* Double-precision floating-point arithmetic. */ + set_optab_libfunc (add_optab, DFmode, "__pruabi_addd"); + set_optab_libfunc (sdiv_optab, DFmode, "__pruabi_divd"); + set_optab_libfunc (smul_optab, DFmode, "__pruabi_mpyd"); + set_optab_libfunc (neg_optab, DFmode, "__pruabi_negd"); + set_optab_libfunc (sub_optab, DFmode, "__pruabi_subd"); + + /* Single-precision floating-point arithmetic. */ + set_optab_libfunc (add_optab, SFmode, "__pruabi_addf"); + set_optab_libfunc (sdiv_optab, SFmode, "__pruabi_divf"); + set_optab_libfunc (smul_optab, SFmode, "__pruabi_mpyf"); + set_optab_libfunc (neg_optab, SFmode, "__pruabi_negf"); + set_optab_libfunc (sub_optab, SFmode, "__pruabi_subf"); + + /* Floating-point comparisons. */ + eqsf_libfunc = init_one_libfunc ("__pruabi_eqf"); + nesf_libfunc = init_one_libfunc ("__pruabi_neqf"); + lesf_libfunc = init_one_libfunc ("__pruabi_lef"); + ltsf_libfunc = init_one_libfunc ("__pruabi_ltf"); + gesf_libfunc = init_one_libfunc ("__pruabi_gef"); + gtsf_libfunc = init_one_libfunc ("__pruabi_gtf"); + eqdf_libfunc = init_one_libfunc ("__pruabi_eqd"); + nedf_libfunc = init_one_libfunc ("__pruabi_neqd"); + ledf_libfunc = init_one_libfunc ("__pruabi_led"); + ltdf_libfunc = init_one_libfunc ("__pruabi_ltd"); + gedf_libfunc = init_one_libfunc ("__pruabi_ged"); + gtdf_libfunc = init_one_libfunc ("__pruabi_gtd"); + + set_optab_libfunc (eq_optab, SFmode, NULL); + set_optab_libfunc (ne_optab, SFmode, "__pruabi_neqf"); + set_optab_libfunc (gt_optab, SFmode, NULL); + set_optab_libfunc (ge_optab, SFmode, NULL); + set_optab_libfunc (lt_optab, SFmode, NULL); + set_optab_libfunc (le_optab, SFmode, NULL); + set_optab_libfunc (unord_optab, SFmode, "__pruabi_unordf"); + set_optab_libfunc (eq_optab, DFmode, NULL); + set_optab_libfunc (ne_optab, DFmode, "__pruabi_neqd"); + set_optab_libfunc (gt_optab, DFmode, NULL); + set_optab_libfunc (ge_optab, DFmode, NULL); + set_optab_libfunc (lt_optab, DFmode, NULL); + set_optab_libfunc (le_optab, DFmode, NULL); + set_optab_libfunc (unord_optab, DFmode, "__pruabi_unordd"); + + /* Floating-point to integer conversions. */ + set_conv_libfunc (sfix_optab, SImode, DFmode, "__pruabi_fixdi"); + set_conv_libfunc (ufix_optab, SImode, DFmode, "__pruabi_fixdu"); + set_conv_libfunc (sfix_optab, DImode, DFmode, "__pruabi_fixdlli"); + set_conv_libfunc (ufix_optab, DImode, DFmode, "__pruabi_fixdull"); + set_conv_libfunc (sfix_optab, SImode, SFmode, "__pruabi_fixfi"); + set_conv_libfunc (ufix_optab, SImode, SFmode, "__pruabi_fixfu"); + set_conv_libfunc (sfix_optab, DImode, SFmode, "__pruabi_fixflli"); + set_conv_libfunc (ufix_optab, DImode, SFmode, "__pruabi_fixfull"); + + /* Conversions between floating types. */ + set_conv_libfunc (trunc_optab, SFmode, DFmode, "__pruabi_cvtdf"); + set_conv_libfunc (sext_optab, DFmode, SFmode, "__pruabi_cvtfd"); + + /* Integer to floating-point conversions. */ + set_conv_libfunc (sfloat_optab, DFmode, SImode, "__pruabi_fltid"); + set_conv_libfunc (ufloat_optab, DFmode, SImode, "__pruabi_fltud"); + set_conv_libfunc (sfloat_optab, DFmode, DImode, "__pruabi_fltllid"); + set_conv_libfunc (ufloat_optab, DFmode, DImode, "__pruabi_fltulld"); + set_conv_libfunc (sfloat_optab, SFmode, SImode, "__pruabi_fltif"); + set_conv_libfunc (ufloat_optab, SFmode, SImode, "__pruabi_fltuf"); + set_conv_libfunc (sfloat_optab, SFmode, DImode, "__pruabi_fltllif"); + set_conv_libfunc (ufloat_optab, SFmode, DImode, "__pruabi_fltullf"); + + /* Long long. */ + set_optab_libfunc (ashr_optab, DImode, "__pruabi_asrll"); + set_optab_libfunc (smul_optab, DImode, "__pruabi_mpyll"); + set_optab_libfunc (ashl_optab, DImode, "__pruabi_lslll"); + set_optab_libfunc (lshr_optab, DImode, "__pruabi_lsrll"); + + set_optab_libfunc (sdiv_optab, SImode, "__pruabi_divi"); + set_optab_libfunc (udiv_optab, SImode, "__pruabi_divu"); + set_optab_libfunc (smod_optab, SImode, "__pruabi_remi"); + set_optab_libfunc (umod_optab, SImode, "__pruabi_remu"); + set_optab_libfunc (sdivmod_optab, SImode, "__pruabi_divremi"); + set_optab_libfunc (udivmod_optab, SImode, "__pruabi_divremu"); + set_optab_libfunc (sdiv_optab, DImode, "__pruabi_divlli"); + set_optab_libfunc (udiv_optab, DImode, "__pruabi_divull"); + set_optab_libfunc (smod_optab, DImode, "__pruabi_remlli"); + set_optab_libfunc (umod_optab, DImode, "__pruabi_remull"); + set_optab_libfunc (udivmod_optab, DImode, "__pruabi_divremull"); +} + + +/* Emit comparison instruction if necessary, returning the expression + that holds the compare result in the proper mode. Return the comparison + that should be used in the jump insn. */ + +rtx +pru_expand_fp_compare (rtx comparison, machine_mode mode) +{ + enum rtx_code code = GET_CODE (comparison); + rtx op0 = XEXP (comparison, 0); + rtx op1 = XEXP (comparison, 1); + rtx cmp; + enum rtx_code jump_code = code; + machine_mode op_mode = GET_MODE (op0); + rtx_insn *insns; + rtx libfunc; + + gcc_assert (op_mode == DFmode || op_mode == SFmode); + + if (code == UNGE) + { + code = LT; + jump_code = EQ; + } + else if (code == UNLE) + { + code = GT; + jump_code = EQ; + } + else + jump_code = NE; + + switch (code) + { + case EQ: + libfunc = op_mode == DFmode ? eqdf_libfunc : eqsf_libfunc; + break; + case NE: + libfunc = op_mode == DFmode ? nedf_libfunc : nesf_libfunc; + break; + case GT: + libfunc = op_mode == DFmode ? gtdf_libfunc : gtsf_libfunc; + break; + case GE: + libfunc = op_mode == DFmode ? gedf_libfunc : gesf_libfunc; + break; + case LT: + libfunc = op_mode == DFmode ? ltdf_libfunc : ltsf_libfunc; + break; + case LE: + libfunc = op_mode == DFmode ? ledf_libfunc : lesf_libfunc; + break; + default: + gcc_unreachable (); + } + start_sequence (); + + cmp = emit_library_call_value (libfunc, 0, LCT_CONST, SImode, + op0, op_mode, op1, op_mode); + insns = get_insns (); + end_sequence (); + + emit_libcall_block (insns, cmp, cmp, + gen_rtx_fmt_ee (code, SImode, op0, op1)); + + return gen_rtx_fmt_ee (jump_code, mode, cmp, const0_rtx); +} + +/* Return the sign bit position for given OP's mode. */ +static int +sign_bit_position (const rtx op) +{ + const int sz = GET_MODE_SIZE (GET_MODE (op)); + + return sz * 8 - 1; +} + +/* Output asm code for sign_extend operation. */ +const char * +pru_output_sign_extend (rtx *operands) +{ + static char buf[512]; + int bufi; + const int dst_sz = GET_MODE_SIZE (GET_MODE (operands[0])); + const int src_sz = GET_MODE_SIZE (GET_MODE (operands[1])); + char ext_start; + + switch (src_sz) + { + case 1: ext_start = 'y'; break; + case 2: ext_start = 'z'; break; + default: gcc_unreachable (); + } + + gcc_assert (dst_sz > src_sz); + + /* Note that src and dst can be different parts of the same + register, e.g. "r7, r7.w1". */ + bufi = snprintf (buf, sizeof (buf), + "mov\t%%0, %%1\n\t" /* Copy AND make positive. */ + "qbbc\t.+8, %%0, %d\n\t" /* Check sign bit. */ + "fill\t%%%c0, %d", /* Make negative. */ + sign_bit_position (operands[1]), + ext_start, + dst_sz - src_sz); + + gcc_assert (bufi > 0); + gcc_assert ((unsigned int)bufi < sizeof (buf)); + + return buf; +} + +/* Branches and compares. */ + +/* PRU's ALU does not support signed comparison operations. That's why we + emulate them. By first checking the sign bit and handling every possible + operand sign combination, we can simulate signed comparisons in just + 5 instructions. See table below. + +.-------------------.---------------------------------------------------. +| Operand sign bit | Mapping the signed comparison to an unsigned one | +|---------+---------+------------+------------+------------+------------| +| OP1.b31 | OP2.b31 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 | +|---------+---------+------------+------------+------------+------------| +| 0 | 0 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 | +|---------+---------+------------+------------+------------+------------| +| 0 | 1 | false | false | true | true | +|---------+---------+------------+------------+------------+------------| +| 1 | 0 | true | true | false | false | +|---------+---------+------------+------------+------------+------------| +| 1 | 1 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 | +`---------'---------'------------'------------'------------+------------' + + +Given the table above, here is an example for a concrete op: + LT: + qbbc OP1_POS, OP1, 31 + OP1_NEG: qbbc BRANCH_TAKEN_LABEL, OP2, 31 + OP1_NEG_OP2_NEG: qblt BRANCH_TAKEN_LABEL, OP2, OP1 + ; jmp OUT -> can be eliminated because we'll take the + ; following branch. OP2.b31 is guaranteed to be 1 + ; by the time we get here. + OP1_POS: qbbs OUT, OP2, 31 + OP1_POS_OP2_POS: qblt BRANCH_TAKEN_LABEL, OP2, OP1 +#if FAR_JUMP + jmp OUT +BRANCH_TAKEN_LABEL: jmp REAL_BRANCH_TAKEN_LABEL +#endif + OUT: + +*/ + +/* Output asm code for a signed-compare LT/LE conditional branch. */ +static const char * +pru_output_ltle_signed_cbranch (rtx *operands, bool is_near) +{ + static char buf[1024]; + enum rtx_code code = GET_CODE (operands[0]); + rtx op1; + rtx op2; + const char *cmp_opstr; + int bufi = 0; + + op1 = operands[1]; + op2 = operands[2]; + + gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG); + + /* Determine the comparison operators for positive and negative operands. */ + if (code == LT) + cmp_opstr = "qblt"; + else if (code == LE) + cmp_opstr = "qble"; + else + gcc_unreachable (); + + if (is_near) + { + bufi = snprintf (buf, sizeof (buf), + "qbbc\t.+12, %%1, %d\n\t" + "qbbc\t%%l3, %%2, %d\n\t" /* OP1_NEG. */ + "%s\t%%l3, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */ + "qbbs\t.+8, %%2, %d\n\t" /* OP1_POS. */ + "%s\t%%l3, %%2, %%1", /* OP1_POS_OP2_POS. */ + sign_bit_position (op1), + sign_bit_position (op2), + cmp_opstr, + sign_bit_position (op2), + cmp_opstr); + } + else + { + bufi = snprintf (buf, sizeof (buf), + "qbbc\t.+12, %%1, %d\n\t" + "qbbc\t.+20, %%2, %d\n\t" /* OP1_NEG. */ + "%s\t.+16, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */ + "qbbs\t.+16, %%2, %d\n\t" /* OP1_POS. */ + "%s\t.+8, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */ + "jmp\t.+8\n\t" /* jmp OUT. */ + "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */ + sign_bit_position (op1), + sign_bit_position (op2), + cmp_opstr, + sign_bit_position (op2), + cmp_opstr); + } + + gcc_assert (bufi > 0); + gcc_assert ((unsigned int)bufi < sizeof (buf)); + + return buf; +} + +/* Output asm code for a signed-compare GT/GE conditional branch. */ +static const char * +pru_output_gtge_signed_cbranch (rtx *operands, bool is_near) +{ + static char buf[1024]; + enum rtx_code code = GET_CODE (operands[0]); + rtx op1; + rtx op2; + const char *cmp_opstr; + int bufi = 0; + + op1 = operands[1]; + op2 = operands[2]; + + gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG); + + /* Determine the comparison operators for positive and negative operands. */ + if (code == GT) + cmp_opstr = "qbgt"; + else if (code == GE) + cmp_opstr = "qbge"; + else + gcc_unreachable (); + + if (is_near) + { + bufi = snprintf (buf, sizeof (buf), + "qbbs\t.+12, %%1, %d\n\t" + "qbbs\t%%l3, %%2, %d\n\t" /* OP1_POS. */ + "%s\t%%l3, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */ + "qbbc\t.+8, %%2, %d\n\t" /* OP1_NEG. */ + "%s\t%%l3, %%2, %%1", /* OP1_NEG_OP2_NEG. */ + sign_bit_position (op1), + sign_bit_position (op2), + cmp_opstr, + sign_bit_position (op2), + cmp_opstr); + } + else + { + bufi = snprintf (buf, sizeof (buf), + "qbbs\t.+12, %%1, %d\n\t" + "qbbs\t.+20, %%2, %d\n\t" /* OP1_POS. */ + "%s\t.+16, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */ + "qbbc\t.+16, %%2, %d\n\t" /* OP1_NEG. */ + "%s\t.+8, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */ + "jmp\t.+8\n\t" /* jmp OUT. */ + "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */ + sign_bit_position (op1), + sign_bit_position (op2), + cmp_opstr, + sign_bit_position (op2), + cmp_opstr); + } + + gcc_assert (bufi > 0); + gcc_assert ((unsigned int)bufi < sizeof (buf)); + + return buf; +} + +/* Output asm code for a signed-compare conditional branch. + + If IS_NEAR is true, then QBBx instructions may be used for reaching + the destination label. Otherwise JMP is used, at the expense of + increased code size. */ +const char * +pru_output_signed_cbranch (rtx *operands, bool is_near) +{ + enum rtx_code code = GET_CODE (operands[0]); + + if (code == LT || code == LE) + return pru_output_ltle_signed_cbranch (operands, is_near); + else if (code == GT || code == GE) + return pru_output_gtge_signed_cbranch (operands, is_near); + else + gcc_unreachable (); +} + +/* + Optimized version of pru_output_signed_cbranch for constant second + operand. */ + +const char * +pru_output_signed_cbranch_ubyteop2 (rtx *operands, bool is_near) +{ + static char buf[1024]; + enum rtx_code code = GET_CODE (operands[0]); + int regop_sign_bit_pos = sign_bit_position (operands[1]); + const char *cmp_opstr; + const char *rcmp_opstr; + + /* We must swap operands due to PRU's demand OP1 to be the immediate. */ + code = swap_condition (code); + + /* Determine normal and reversed comparison operators for both positive + operands. This enables us to go completely unsigned. + + NOTE: We cannot use the R print modifier because we convert signed + comparison operators to unsigned ones. */ + switch (code) + { + case LT: cmp_opstr = "qblt"; rcmp_opstr = "qbge"; break; + case LE: cmp_opstr = "qble"; rcmp_opstr = "qbgt"; break; + case GT: cmp_opstr = "qbgt"; rcmp_opstr = "qble"; break; + case GE: cmp_opstr = "qbge"; rcmp_opstr = "qblt"; break; + default: gcc_unreachable (); + } + + /* OP2 is a constant unsigned byte - utilize this info to generate + optimized code. We can "remove half" of the op table above because + we know that OP2.b31 = 0 (remember that 0 <= OP2 <= 255). */ + if (code == LT || code == LE) + { + if (is_near) + snprintf (buf, sizeof (buf), + "qbbs\t.+8, %%1, %d\n\t" + "%s\t%%l3, %%1, %%2", + regop_sign_bit_pos, + cmp_opstr); + else + snprintf (buf, sizeof (buf), + "qbbs\t.+12, %%1, %d\n\t" + "%s\t.+8, %%1, %%2\n\t" + "jmp\t%%%%label(%%l3)", + regop_sign_bit_pos, + rcmp_opstr); + } + else if (code == GT || code == GE) + { + if (is_near) + snprintf (buf, sizeof (buf), + "qbbs\t%%l3, %%1, %d\n\t" + "%s\t%%l3, %%1, %%2", + regop_sign_bit_pos, + cmp_opstr); + else + snprintf (buf, sizeof (buf), + "qbbs\t.+8, %%1, %d\n\t" + "%s\t.+8, %%1, %%2\n\t" + "jmp\t%%%%label(%%l3)", + regop_sign_bit_pos, + rcmp_opstr); + } + else + gcc_unreachable (); + + return buf; +} + +/* + Optimized version of pru_output_signed_cbranch_ubyteop2 for constant + zero second operand. */ + +const char * +pru_output_signed_cbranch_zeroop2 (rtx *operands, bool is_near) +{ + static char buf[1024]; + enum rtx_code code = GET_CODE (operands[0]); + int regop_sign_bit_pos = sign_bit_position (operands[1]); + + /* OP2 is a constant zero - utilize this info to simply check the + OP1 sign bit when comparing for LT or GE. */ + if (code == LT) + { + if (is_near) + snprintf (buf, sizeof (buf), + "qbbs\t%%l3, %%1, %d\n\t", + regop_sign_bit_pos); + else + snprintf (buf, sizeof (buf), + "qbbc\t.+8, %%1, %d\n\t" + "jmp\t%%%%label(%%l3)", + regop_sign_bit_pos); + } + else if (code == GE) + { + if (is_near) + snprintf (buf, sizeof (buf), + "qbbc\t%%l3, %%1, %d\n\t", + regop_sign_bit_pos); + else + snprintf (buf, sizeof (buf), + "qbbs\t.+8, %%1, %d\n\t" + "jmp\t%%%%label(%%l3)", + regop_sign_bit_pos); + } + else + gcc_unreachable (); + + return buf; +} + +/* Addressing Modes. */ + +/* Return true if register REGNO is a valid base register. + STRICT_P is true if REG_OK_STRICT is in effect. */ + +bool +pru_regno_ok_for_base_p (int regno, bool strict_p) +{ + if (!HARD_REGISTER_NUM_P (regno)) + { + if (!strict_p) + return true; + + if (!reg_renumber) + return false; + + regno = reg_renumber[regno]; + } + + /* The fake registers will be eliminated to either the stack or + hard frame pointer, both of which are usually valid base registers. + Reload deals with the cases where the eliminated form isn't valid. */ + return (GP_REG_P (regno) + || regno == FRAME_POINTER_REGNUM + || regno == ARG_POINTER_REGNUM); +} + +/* Return true if given xbbo constant OFFSET is valid. */ +static bool +pru_valid_const_ubyte_offset (machine_mode mode, HOST_WIDE_INT offset) +{ + bool valid = UBYTE_INT (offset); + + /* Reload can split multi word accesses, so make sure we can address + the second word in a DI. */ + if (valid && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode)) + valid = UBYTE_INT (offset + GET_MODE_SIZE (mode) - 1); + + return valid; +} + +/* Recognize a CTABLE base address. Return CTABLE entry index, or -1 if + * base was not found in the pragma-filled pru_ctable. */ +int +pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (pru_ctable); i++) + { + if (pru_ctable[i].valid && pru_ctable[i].base == caddr) + return i; + } + return -1; +} + + +/* Check if the given address can be addressed via CTABLE_BASE + UBYTE_OFFS, + and return the base CTABLE index if possible. */ +int +pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (pru_ctable); i++) + { + if (pru_ctable[i].valid && IN_RANGE (caddr, + pru_ctable[i].base, + pru_ctable[i].base + 0xff)) + return i; + } + return -1; +} + + +/* Return the offset from some CTABLE base for this address. */ +int +pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr) +{ + int i; + + i = pru_get_ctable_base_index (caddr); + gcc_assert (i >= 0); + + return caddr - pru_ctable[i].base; +} + +/* Return true if the address expression formed by BASE + OFFSET is + valid. */ +static bool +pru_valid_addr_expr_p (machine_mode mode, rtx base, rtx offset, bool strict_p) +{ + if (!strict_p && base != NULL_RTX && GET_CODE (base) == SUBREG) + base = SUBREG_REG (base); + if (!strict_p && offset != NULL_RTX && GET_CODE (offset) == SUBREG) + offset = SUBREG_REG (offset); + + if (REG_P (base) + && pru_regno_ok_for_base_p (REGNO (base), strict_p) + && (offset == NULL_RTX + || (CONST_INT_P (offset) + && pru_valid_const_ubyte_offset (mode, INTVAL (offset))) + || (REG_P (offset) + && pru_regno_ok_for_index_p (REGNO (offset), strict_p)))) + { + /* base register + register offset + * OR base register + UBYTE constant offset. */ + return true; + } + else if (REG_P (base) + && pru_regno_ok_for_index_p (REGNO (base), strict_p) + && (offset != NULL_RTX && ctable_base_operand (offset, VOIDmode))) + { + /* base CTABLE constant base + register offset + * Note: GCC always puts the register as a first operand of PLUS. */ + return true; + } + else if (CONST_INT_P (base) + && offset == NULL_RTX + && (ctable_addr_operand (base, VOIDmode))) + { + /* base CTABLE constant base + UBYTE constant offset. */ + return true; + } + else + { + return false; + } +} + +/* Implement TARGET_LEGITIMATE_ADDRESS_P. */ +static bool +pru_legitimate_address_p (machine_mode mode, + rtx operand, bool strict_p) +{ + switch (GET_CODE (operand)) + { + /* Direct. */ + case SYMBOL_REF: + case LABEL_REF: + case CONST: + case CONST_DOUBLE: + return false; + + case CONST_INT: + return ctable_addr_operand (operand, VOIDmode); + + /* Register indirect. */ + case REG: + return pru_regno_ok_for_base_p (REGNO (operand), strict_p); + + /* Register indirect with displacement. */ + case PLUS: + { + rtx op0 = XEXP (operand, 0); + rtx op1 = XEXP (operand, 1); + + return (pru_valid_addr_expr_p (mode, op0, op1, strict_p) + || pru_valid_addr_expr_p (mode, op1, op0, strict_p)); + } + + default: + break; + } + return false; +} + +/* Output assembly language related definitions. */ + +/* Implement TARGET_ASM_CONSTRUCTOR. */ +static void +pru_elf_asm_constructor (rtx symbol, int priority) +{ + char buf[23]; + section *s; + + if (priority == DEFAULT_INIT_PRIORITY) + snprintf (buf, sizeof (buf), ".init_array"); + else + { + /* While priority is known to be in range [0, 65535], so 18 bytes + would be enough, the compiler might not know that. To avoid + -Wformat-truncation false positive, use a larger size. */ + snprintf (buf, sizeof (buf), ".init_array.%.5u", priority); + } + s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL); + switch_to_section (s); + assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol); +} + +/* Implement TARGET_ASM_DESTRUCTOR. */ +static void +pru_elf_asm_destructor (rtx symbol, int priority) +{ + char buf[23]; + section *s; + + if (priority == DEFAULT_INIT_PRIORITY) + snprintf (buf, sizeof (buf), ".fini_array"); + else + { + /* While priority is known to be in range [0, 65535], so 18 bytes + would be enough, the compiler might not know that. To avoid + -Wformat-truncation false positive, use a larger size. */ + snprintf (buf, sizeof (buf), ".fini_array.%.5u", priority); + } + s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL); + switch_to_section (s); + assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol); +} + +/* Map rtx_code to unsigned PRU branch op suffix. Callers must + handle sign comparison themselves for signed operations. */ +static const char * +pru_comparison_str (enum rtx_code cond) +{ + switch (cond) + { + case NE: return "ne"; + case EQ: return "eq"; + case GEU: return "ge"; + case GTU: return "gt"; + case LEU: return "le"; + case LTU: return "lt"; + default: gcc_unreachable (); + } +} + +/* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get + the bit representation of X by "casting" it to CONST_INT. */ + +static rtx +pru_to_int_mode (rtx x) +{ + machine_mode mode = GET_MODE (x); + + return VOIDmode == mode + ? x + : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0); +} + +/* Translate between the MachineDescription notion + of 8-bit consecutive registers, to the PRU + assembler syntax of REGWORD[.SUBREG]. */ +static const char * +pru_asm_regname (rtx op) +{ + static char canon_reg_names[3][LAST_GP_REG][8]; + int speci, regi; + + gcc_assert (REG_P (op)); + + if (!canon_reg_names[0][0][0]) + { + for (regi = 0; regi < LAST_GP_REG; regi++) + for (speci = 0; speci < 3; speci++) + { + const int sz = (speci == 0) ? 1 : ((speci == 1) ? 2 : 4); + if ((regi + sz) > (32 * 4)) + continue; /* Invalid entry. */ + + /* Construct the lookup table. */ + const char *suffix = ""; + + switch ((sz << 8) | (regi % 4)) + { + case (1 << 8) | 0: suffix = ".b0"; break; + case (1 << 8) | 1: suffix = ".b1"; break; + case (1 << 8) | 2: suffix = ".b2"; break; + case (1 << 8) | 3: suffix = ".b3"; break; + case (2 << 8) | 0: suffix = ".w0"; break; + case (2 << 8) | 1: suffix = ".w1"; break; + case (2 << 8) | 2: suffix = ".w2"; break; + case (4 << 8) | 0: suffix = ""; break; + default: + /* Invalid entry. */ + continue; + } + sprintf (&canon_reg_names[speci][regi][0], + "r%d%s", regi / 4, suffix); + } + } + + switch (GET_MODE_SIZE (GET_MODE (op))) + { + case 1: speci = 0; break; + case 2: speci = 1; break; + case 4: speci = 2; break; + case 8: speci = 2; break; /* Existing GCC test cases are not using %F. */ + default: gcc_unreachable (); + } + regi = REGNO (op); + gcc_assert (regi < LAST_GP_REG); + gcc_assert (canon_reg_names[speci][regi][0]); + + return &canon_reg_names[speci][regi][0]; +} + +/* Print the operand OP to file stream FILE modified by LETTER. + LETTER can be one of: + + b: prints the register byte start (used by LBBO/SBBO) + B: prints 'c' or 'b' for CTABLE or REG base in a memory address + F: Full 32-bit register. + H: Higher 16-bits of a const_int operand + L: Lower 16-bits of a const_int operand + N: prints next 32-bit register (upper 32bits of a 64bit REG couple) + P: prints swapped condition. + Q: prints swapped and reversed condition. + R: prints reversed condition. + S: print operand mode size (but do not print the operand itself) + T: print exact_log2 () for const_int operands + V: print exact_log2 () of negated const_int operands + w: Lower 32-bits of a const_int operand + W: Upper 32-bits of a const_int operand + y: print the next 8-bit register (regardless of op size) + z: print the second next 8-bit register (regardless of op size) +*/ +static void +pru_print_operand (FILE *file, rtx op, int letter) +{ + + switch (letter) + { + case 'S': + fprintf (file, "%d", GET_MODE_SIZE (GET_MODE (op))); + return; + + default: + break; + } + + if (comparison_operator (op, VOIDmode)) + { + enum rtx_code cond = GET_CODE (op); + gcc_assert (!pru_signed_cmp_operator (op, VOIDmode)); + + switch (letter) + { + case 0: + fprintf (file, "%s", pru_comparison_str (cond)); + return; + case 'P': + fprintf (file, "%s", pru_comparison_str (swap_condition (cond))); + return; + case 'Q': + cond = swap_condition (cond); + /* Fall through to reverse. */ + case 'R': + fprintf (file, "%s", pru_comparison_str (reverse_condition (cond))); + return; + } + } + + switch (GET_CODE (op)) + { + case REG: + if (letter == 0) + { + fprintf (file, "%s", pru_asm_regname (op)); + return; + } + else if (letter == 'b') + { + gcc_assert (REGNO (op) <= LAST_NONIO_GP_REG); + fprintf (file, "r%d.b%d", REGNO (op) / 4, REGNO (op) % 4); + return; + } + else if (letter == 'F') + { + gcc_assert (REGNO (op) <= LAST_NONIO_GP_REG); + gcc_assert (REGNO (op) % 4 == 0); + fprintf (file, "r%d", REGNO (op) / 4); + return; + } + else if (letter == 'N') + { + gcc_assert (REGNO (op) <= LAST_NONIO_GP_REG); + gcc_assert (REGNO (op) % 4 == 0); + fprintf (file, "r%d", REGNO (op) / 4 + 1); + return; + } + else if (letter == 'y') + { + gcc_assert (REGNO (op) <= LAST_NONIO_GP_REG - 1); + fprintf (file, "%s", reg_names[REGNO (op) + 1]); + return; + } + else if (letter == 'z') + { + gcc_assert (REGNO (op) <= LAST_NONIO_GP_REG - 2); + fprintf (file, "%s", reg_names[REGNO (op) + 2]); + return; + } + break; + + case CONST_INT: + if (letter == 'H') + { + HOST_WIDE_INT val = INTVAL (op); + val = (val >> 16) & 0xFFFF; + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + else if (letter == 'L') + { + HOST_WIDE_INT val = INTVAL (op); + val &= 0xFFFF; + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + else if (letter == 'T') + { + /* The predicate should have already validated the 1-high-bit + requirement. Use CTZ here to deal with constant's sign + extension. */ + HOST_WIDE_INT val = wi::ctz (INTVAL (op)); + gcc_assert (val >= 0 && val <= 31); + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + else if (letter == 'V') + { + HOST_WIDE_INT val = wi::ctz (~INTVAL (op)); + gcc_assert (val >= 0 && val <= 31); + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + else if (letter == 'w') + { + HOST_WIDE_INT val = INTVAL (op) & 0xffffffff; + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + else if (letter == 'W') + { + HOST_WIDE_INT val = (INTVAL (op) >> 32) & 0xffffffff; + output_addr_const (file, gen_int_mode (val, SImode)); + return; + } + /* Else, fall through. */ + + case CONST: + case LABEL_REF: + case SYMBOL_REF: + if (letter == 0) + { + output_addr_const (file, op); + return; + } + break; + + case CONST_FIXED: + { + HOST_WIDE_INT ival = INTVAL (pru_to_int_mode (op)); + if (letter != 0) + output_operand_lossage ("Unsupported code '%c' for fixed-point:", + letter); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival); + return; + } + break; + + case CONST_DOUBLE: + if (letter == 0) + { + long val; + + if (GET_MODE (op) != SFmode) + fatal_insn ("internal compiler error. Unknown mode:", op); + REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), val); + fprintf (file, "0x%lx", val); + return; + } + else if (letter == 'w' || letter == 'W') + { + long t[2]; + REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), t); + fprintf (file, "0x%lx", t[letter == 'w' ? 0 : 1]); + return; + } + else + { + gcc_unreachable (); + } + break; + + case SUBREG: + case MEM: + if (letter == 0) + { + output_address (VOIDmode, op); + return; + } + else if (letter == 'B') + { + rtx base = XEXP (op, 0); + if (GET_CODE (base) == PLUS) + { + rtx op0 = XEXP (base, 0); + rtx op1 = XEXP (base, 1); + + /* PLUS cannot have two constant operands, so one + of them must be a REG, hence we must check for an + exact base address. */ + if (ctable_base_operand (op0, VOIDmode) + || ctable_base_operand (op1, VOIDmode)) + { + fprintf (file, "c"); + return; + } + else if (REG_P (op0) || REG_P (op1)) + { + fprintf (file, "b"); + return; + } + else + gcc_unreachable (); + } + else if (REG_P (base)) + { + fprintf (file, "b"); + return; + } + else if (ctable_addr_operand (base, VOIDmode)) + { + fprintf (file, "c"); + return; + } + else + gcc_unreachable (); + } + break; + + case CODE_LABEL: + if (letter == 0) + { + output_addr_const (file, op); + return; + } + break; + + default: + break; + } + + output_operand_lossage ("Unsupported operand %s for code '%c'", + GET_RTX_NAME (GET_CODE (op)), letter); + gcc_unreachable (); +} + +/* Implement TARGET_PRINT_OPERAND_ADDRESS. */ +static void +pru_print_operand_address (FILE *file, machine_mode mode, rtx op) +{ + if (GET_CODE (op) != REG && CONSTANT_ADDRESS_P (op) + && text_segment_operand (op, VOIDmode)) + { + fprintf (stderr, "Unexpectred text address?\n"); + debug_rtx (op); + gcc_unreachable (); + } + + switch (GET_CODE (op)) + { + case CONST: + case LABEL_REF: + case CONST_DOUBLE: + case SYMBOL_REF: + break; + + case CONST_INT: + { + unsigned HOST_WIDE_INT caddr = INTVAL (op); + int base = pru_get_ctable_base_index (caddr); + int offs = pru_get_ctable_base_offset (caddr); + gcc_assert (base >= 0); + fprintf (file, "%d, %d", base, offs); + return; + } + break; + + case PLUS: + { + int base; + rtx op0 = XEXP (op, 0); + rtx op1 = XEXP (op, 1); + + if (REG_P (op0) && CONST_INT_P (op1) + && pru_get_ctable_exact_base_index (INTVAL (op1)) >= 0) + { + base = pru_get_ctable_exact_base_index (INTVAL (op1)); + fprintf (file, "%d, %s", base, pru_asm_regname (op0)); + return; + } + else if (REG_P (op1) && CONST_INT_P (op0) + && pru_get_ctable_exact_base_index (INTVAL (op0)) >= 0) + { + base = pru_get_ctable_exact_base_index (INTVAL (op0)); + fprintf (file, "%d, %s", base, pru_asm_regname (op1)); + return; + } + else if (REG_P (op0) && CONSTANT_P (op1)) + { + fprintf (file, "%s, ", pru_asm_regname (op0)); + output_addr_const (file, op1); + return; + } + else if (REG_P (op1) && CONSTANT_P (op0)) + { + fprintf (file, "%s, ", pru_asm_regname (op1)); + output_addr_const (file, op0); + return; + } + else if (REG_P (op1) && REG_P (op0)) + { + fprintf (file, "%s, %s", pru_asm_regname (op0), + pru_asm_regname (op1)); + return; + } + } + break; + + case REG: + fprintf (file, "%s, 0", pru_asm_regname (op)); + return; + + case MEM: + { + rtx base = XEXP (op, 0); + pru_print_operand_address (file, mode, base); + return; + } + default: + break; + } + + fprintf (stderr, "Missing way to print address\n"); + debug_rtx (op); + gcc_unreachable (); +} + +/* Implement TARGET_ASM_FUNCTION_PROLOGUE. */ +static void +pru_asm_function_prologue (FILE *file) +{ + if (flag_verbose_asm || flag_debug_asm) + { + pru_compute_frame_layout (); + pru_dump_frame_layout (file); + } +} + +/* Implement `TARGET_ASM_INTEGER'. + Target hook for assembling integer objects. PRU version needs + special handling for references to pmem. Code copied from AVR. */ + +static bool +pru_assemble_integer (rtx x, unsigned int size, int aligned_p) +{ + if (size == POINTER_SIZE / BITS_PER_UNIT + && aligned_p + && text_segment_operand (x, VOIDmode)) + { + fputs ("\t.4byte\t%pmem(", asm_out_file); + output_addr_const (asm_out_file, x); + fputs (")\n", asm_out_file); + + return true; + } + else if (size == INIT_ARRAY_ENTRY_BYTES + && aligned_p + && text_segment_operand (x, VOIDmode)) + { + fputs ("\t.2byte\t%pmem(", asm_out_file); + output_addr_const (asm_out_file, x); + fputs (")\n", asm_out_file); + + return true; + } + else + { + return default_assemble_integer (x, size, aligned_p); + } +} + +/* Implement TARGET_ASM_FILETARGET_ASM_FILE_START_START. */ + +static void +pru_file_start (void) +{ + default_file_start (); + + /* Compiler will take care of placing %label, so there is no + need to confuse users with this warning. */ + fprintf (asm_out_file, "\t.set no_warn_regname_label\n"); +} + +/* Function argument related. */ + +/* Return the number of bytes needed for storing an argument with + the given MODE and TYPE. */ +static int +pru_function_arg_size (machine_mode mode, const_tree type) +{ + HOST_WIDE_INT param_size; + + if (mode == BLKmode) + param_size = int_size_in_bytes (type); + else + param_size = GET_MODE_SIZE (mode); + + /* Convert to words (round up). */ + param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD; + gcc_assert (param_size >= 0); + + return param_size; +} + +/* Check if argument with the given size must be + passed/returned in a register. + + Reference: + https://e2e.ti.com/support/development_tools/compiler/f/343/p/650176/2393029 + + Arguments other than 8/16/24/32/64bits are passed on stack. */ +static bool +pru_arg_in_reg_bysize (size_t sz) +{ + return sz == 1 || sz == 2 || sz == 3 || sz == 4 || sz == 8; +} + +/* Helper function to get the starting storage HW register for an argument, + or -1 if it must be passed on stack. The cum_v state is not changed. */ +static int +pru_function_arg_regi (cumulative_args_t cum_v, + machine_mode mode, const_tree type, + bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + size_t argsize = pru_function_arg_size (mode, type); + size_t i, bi; + int regi = -1; + + if (!pru_arg_in_reg_bysize (argsize)) + return -1; + + if (!named) + return -1; + + /* Find the first available slot that fits. Yes, that's the PRU ABI. */ + for (i = 0; regi < 0 && i < ARRAY_SIZE (cum->regs_used); i++) + { + if (mode == BLKmode) + { + /* Structs are passed, beginning at a full register. */ + if ((i % 4) != 0) + continue; + } + else + { + /* Scalar arguments. */ + + /* Ensure SI and DI arguments are stored in full registers only. */ + if ((argsize >= 4) && (i % 4) != 0) + continue; + + /* rX.w0/w1/w2 are OK. But avoid spreading the second byte + into a different full register. */ + if (argsize == 2 && (i % 4) == 3) + continue; + } + + for (bi = 0; + bi < argsize && (bi + i) < ARRAY_SIZE (cum->regs_used); + bi++) + { + if (cum->regs_used[bi + i]) + break; + } + if (bi == argsize) + regi = FIRST_ARG_REGNO + i; + } + + return regi; +} + +/* Mark CUM_V that a function argument will occupy HW register slot starting + at REGI. The number of consecutive 8-bit HW registers marked as occupied + depends on the MODE and TYPE of the argument. */ +static void +pru_function_arg_regi_mark_slot (int regi, + cumulative_args_t cum_v, + machine_mode mode, const_tree type, + bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + HOST_WIDE_INT param_size = pru_function_arg_size (mode, type); + + gcc_assert (named); + + /* Mark all byte sub-registers occupied by argument as used. */ + while (param_size--) + { + gcc_assert (regi >= FIRST_ARG_REGNO && regi <= LAST_ARG_REGNO); + gcc_assert (!cum->regs_used[regi - FIRST_ARG_REGNO]); + cum->regs_used[regi - FIRST_ARG_REGNO] = true; + regi++; + } +} + +/* Define where to put the arguments to a function. Value is zero to + push the argument on the stack, or a hard register in which to + store the argument. + + MODE is the argument's machine mode. + TYPE is the data type of the argument (as a tree). + This is null for libcalls where that information may + not be available. + CUM is a variable of type CUMULATIVE_ARGS which gives info about + the preceding args and about the function being called. + NAMED is nonzero if this argument is a named parameter + (otherwise it is an extra parameter matching an ellipsis). */ + +static rtx +pru_function_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree type, + bool named) +{ + rtx return_rtx = NULL_RTX; + int regi = pru_function_arg_regi (cum_v, mode, type, named); + + if (regi >= 0) + return_rtx = gen_rtx_REG (mode, regi); + + return return_rtx; +} + +/* Return number of bytes, at the beginning of the argument, that must be + put in registers. 0 is the argument is entirely in registers or entirely + in memory. */ + +static int +pru_arg_partial_bytes (cumulative_args_t cum_v ATTRIBUTE_UNUSED, + machine_mode mode ATTRIBUTE_UNUSED, + tree type ATTRIBUTE_UNUSED, + bool named ATTRIBUTE_UNUSED) +{ + return 0; +} + +/* Update the data in CUM to advance over an argument of mode MODE + and data type TYPE; TYPE is null for libcalls where that information + may not be available. */ + +static void +pru_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, + const_tree type, + bool named) +{ + int regi = pru_function_arg_regi (cum_v, mode, type, named); + + if (regi >= 0) + pru_function_arg_regi_mark_slot (regi, cum_v, mode, type, named); +} + +/* Implement TARGET_FUNCTION_VALUE. */ +static rtx +pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED, + bool outgoing ATTRIBUTE_UNUSED) +{ + return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNO); +} + +/* Implement TARGET_LIBCALL_VALUE. */ +static rtx +pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) +{ + return gen_rtx_REG (mode, FIRST_RETVAL_REGNO); +} + +/* Implement TARGET_FUNCTION_VALUE_REGNO_P. */ +static bool +pru_function_value_regno_p (const unsigned int regno) +{ + return regno == FIRST_RETVAL_REGNO; +} + +/* Implement TARGET_RETURN_IN_MEMORY. */ +bool +pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) +{ + bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type)) + || int_size_in_bytes (type) == -1); + + return in_memory; +} + +/* Implement TARGET_CAN_USE_DOLOOP_P. */ + +static bool +pru_can_use_doloop_p (const widest_int &, const widest_int &iterations_max, + unsigned int loop_depth, bool) +{ + /* Considering limitations in the hardware, only use doloop + for innermost loops which must be entered from the top. */ + if (loop_depth > 1) + return false; + /* PRU internal loop counter is 16bits wide. Remember that iterations_max + holds the maximum number of loop latch executions, while PRU loop + instruction needs the count of loop body executions. */ + if (iterations_max == 0 || wi::geu_p (iterations_max, 0xffff)) + return false; + + return true; +} + +/* NULL if INSN insn is valid within a low-overhead loop. + Otherwise return why doloop cannot be applied. */ + +static const char * +pru_invalid_within_doloop (const rtx_insn *insn) +{ + if (CALL_P (insn)) + return "Function call in the loop."; + + if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return) + return "Return from a call instruction in the loop."; + + if (NONDEBUG_INSN_P (insn) + && INSN_CODE (insn) < 0 + && (GET_CODE (PATTERN (insn)) == ASM_INPUT + || asm_noperands (PATTERN (insn)) >= 0)) + return "Loop contains asm statement."; + + return NULL; +} + + +/* Figure out where to put LABEL, which is the label for a repeat loop. + The loop ends just before LAST_INSN. If SHARED, insns other than the + "repeat" might use LABEL to jump to the loop's continuation point. + + Return the last instruction in the adjusted loop. */ + +static rtx_insn * +pru_insert_loop_label_last (rtx_insn *last_insn, rtx_code_label *label, + bool shared) +{ + rtx_insn *next, *prev; + int count = 0, code, icode; + + if (dump_file) + fprintf (dump_file, "considering end of repeat loop at insn %d\n", + INSN_UID (last_insn)); + + /* Set PREV to the last insn in the loop. */ + prev = PREV_INSN (last_insn); + + /* Set NEXT to the next insn after the loop label. */ + next = last_insn; + if (!shared) + while (prev != 0) + { + code = GET_CODE (prev); + if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER) + break; + + if (INSN_P (prev)) + { + if (GET_CODE (PATTERN (prev)) == SEQUENCE) + prev = as_a (XVECEXP (PATTERN (prev), 0, 1)); + + /* Other insns that should not be in the last two opcodes. */ + icode = recog_memoized (prev); + if (icode < 0 + || icode == CODE_FOR_pruloophi + || icode == CODE_FOR_pruloopsi) + break; + + count++; + next = prev; + if (dump_file) + print_rtl_single (dump_file, next); + if (count == 2) + break; + } + prev = PREV_INSN (prev); + } + + /* Insert the nops. */ + if (dump_file && count < 2) + fprintf (dump_file, "Adding %d nop%s inside loop\n\n", + 2 - count, count == 1 ? "" : "s"); + + for (; count < 2; count++) + emit_insn_before (gen_nop (), last_insn); + + /* Insert the label. */ + emit_label_before (label, last_insn); + + return last_insn; +} + +/* If IS_END is false, expand a canonical doloop_begin RTL into the + PRU-specific doloop_begin_internal. Otherwise expand doloop_end to + doloop_end_internal. */ +void +pru_emit_doloop (rtx *operands, int is_end) +{ + rtx tag; + + if (cfun->machine->doloop_tags == 0 + || cfun->machine->doloop_tag_from_end == is_end) + { + cfun->machine->doloop_tags++; + cfun->machine->doloop_tag_from_end = is_end; + } + + tag = GEN_INT (cfun->machine->doloop_tags - 1); + machine_mode opmode = GET_MODE (operands[0]); + if (is_end) + { + if (opmode == HImode) + emit_jump_insn (gen_doloop_end_internalhi (operands[0], + operands[1], tag)); + else if (opmode == SImode) + emit_jump_insn (gen_doloop_end_internalsi (operands[0], + operands[1], tag)); + else + gcc_unreachable (); + } + else + { + if (opmode == HImode) + emit_insn (gen_doloop_begin_internalhi (operands[0], operands[0], tag)); + else if (opmode == SImode) + emit_insn (gen_doloop_begin_internalsi (operands[0], operands[0], tag)); + else + gcc_unreachable (); + } +} + + +/* Code for converting doloop_begins and doloop_ends into valid + PRU instructions. Idea and code snippets borrowed from mep port. + + A doloop_begin is just a placeholder: + + $count = unspec ($count) + + where $count is initially the number of iterations. + doloop_end has the form: + + if (--$count == 0) goto label + + The counter variable is private to the doloop insns, nothing else + relies on its value. + + There are three cases, in decreasing order of preference: + + 1. A loop has exactly one doloop_begin and one doloop_end. + The doloop_end branches to the first instruction after + the doloop_begin. + + In this case we can replace the doloop_begin with a LOOP + instruction and remove the doloop_end. I.e.: + + $count1 = unspec ($count1) + label: + ... + if (--$count2 != 0) goto label + + becomes: + + LOOP end_label,$count1 + label: + ... + end_label: + # end loop + + 2. As for (1), except there are several doloop_ends. One of them + (call it X) falls through to a label L. All the others fall + through to branches to L. + + In this case, we remove X and replace the other doloop_ends + with branches to the LOOP label. For example: + + $count1 = unspec ($count1) + label: + ... + if (--$count1 != 0) goto label + end_label: + ... + if (--$count2 != 0) goto label + goto end_label + + becomes: + + LOOP end_label,$count1 + label: + ... + end_label: + # end repeat + ... + goto end_label + + 3. The fallback case. Replace doloop_begins with: + + $count = $count + + Replace doloop_ends with the equivalent of: + + $count = $count - 1 + if ($count != 0) goto loop_label + + */ + +/* A structure describing one doloop_begin. */ +struct pru_doloop_begin { + /* The next doloop_begin with the same tag. */ + struct pru_doloop_begin *next; + + /* The instruction itself. */ + rtx_insn *insn; + + /* The initial counter value. */ + rtx loop_count; + + /* The counter register. */ + rtx counter; +}; + +/* A structure describing a doloop_end. */ +struct pru_doloop_end { + /* The next doloop_end with the same loop tag. */ + struct pru_doloop_end *next; + + /* The instruction itself. */ + rtx_insn *insn; + + /* The first instruction after INSN when the branch isn't taken. */ + rtx_insn *fallthrough; + + /* The location of the counter value. Since doloop_end_internal is a + jump instruction, it has to allow the counter to be stored anywhere + (any non-fixed register). */ + rtx counter; + + /* The target label (the place where the insn branches when the counter + isn't zero). */ + rtx label; + + /* A scratch register. Only available when COUNTER isn't stored + in a general register. */ + rtx scratch; +}; + + +/* One do-while loop. */ +struct pru_doloop { + /* All the doloop_begins for this loop (in no particular order). */ + struct pru_doloop_begin *begin; + + /* All the doloop_ends. When there is more than one, arrange things + so that the first one is the most likely to be X in case (2) above. */ + struct pru_doloop_end *end; +}; + + +/* Return true if LOOP can be converted into LOOP form + (that is, if it matches cases (1) or (2) above). */ + +static bool +pru_repeat_loop_p (struct pru_doloop *loop) +{ + struct pru_doloop_end *end; + rtx_insn *fallthrough; + + /* There must be exactly one doloop_begin and at least one doloop_end. */ + if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0) + return false; + + /* The first doloop_end (X) must branch back to the insn after + the doloop_begin. */ + if (prev_real_insn (as_a (loop->end->label)) != loop->begin->insn) + return false; + + /* Check that the first doloop_end (X) can actually reach + doloop_begin () with U8_PCREL relocation for LOOP instruction. */ + if (get_attr_length (loop->end->insn) != 4) + return false; + + /* All the other doloop_ends must branch to the same place as X. + When the branch isn't taken, they must jump to the instruction + after X. */ + fallthrough = loop->end->fallthrough; + for (end = loop->end->next; end != 0; end = end->next) + if (end->label != loop->end->label + || !simplejump_p (end->fallthrough) + || fallthrough + != next_real_insn (JUMP_LABEL_AS_INSN (end->fallthrough))) + return false; + + return true; +} + + +/* The main repeat reorg function. See comment above for details. */ + +static void +pru_reorg_loop (rtx_insn *insns) +{ + rtx_insn *insn; + struct pru_doloop *loops, *loop; + struct pru_doloop_begin *begin; + struct pru_doloop_end *end; + size_t tmpsz; + + /* Quick exit if we haven't created any loops. */ + if (cfun->machine->doloop_tags == 0) + return; + + /* Create an array of pru_doloop structures. */ + tmpsz = sizeof (loops[0]) * cfun->machine->doloop_tags; + loops = (struct pru_doloop *) alloca (tmpsz); + memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags); + + /* Search the function for do-while insns and group them by loop tag. */ + for (insn = insns; insn; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + switch (recog_memoized (insn)) + { + case CODE_FOR_doloop_begin_internalhi: + case CODE_FOR_doloop_begin_internalsi: + insn_extract (insn); + loop = &loops[INTVAL (recog_data.operand[2])]; + + tmpsz = sizeof (struct pru_doloop_begin); + begin = (struct pru_doloop_begin *) alloca (tmpsz); + begin->next = loop->begin; + begin->insn = insn; + begin->loop_count = recog_data.operand[1]; + begin->counter = recog_data.operand[0]; + + loop->begin = begin; + break; + + case CODE_FOR_doloop_end_internalhi: + case CODE_FOR_doloop_end_internalsi: + insn_extract (insn); + loop = &loops[INTVAL (recog_data.operand[2])]; + + tmpsz = sizeof (struct pru_doloop_end); + end = (struct pru_doloop_end *) alloca (tmpsz); + end->insn = insn; + end->fallthrough = next_real_insn (insn); + end->counter = recog_data.operand[0]; + end->label = recog_data.operand[1]; + end->scratch = recog_data.operand[3]; + + /* If this insn falls through to an unconditional jump, + give it a lower priority than the others. */ + if (loop->end != 0 && simplejump_p (end->fallthrough)) + { + end->next = loop->end->next; + loop->end->next = end; + } + else + { + end->next = loop->end; + loop->end = end; + } + break; + } + + /* Convert the insns for each loop in turn. */ + for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++) + if (pru_repeat_loop_p (loop)) + { + /* Case (1) or (2). */ + rtx_code_label *repeat_label; + rtx label_ref; + + /* Create a new label for the repeat insn. */ + repeat_label = gen_label_rtx (); + + /* Replace the doloop_begin with a repeat. We get rid + of the iteration register because LOOP instruction + will utilize an internal for the PRU core LOOP register. */ + label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label); + machine_mode loop_mode = GET_MODE (loop->begin->loop_count); + if (loop_mode == HImode) + emit_insn_before (gen_pruloophi (loop->begin->loop_count, label_ref), + loop->begin->insn); + else if (loop_mode == SImode) + { + rtx loop_rtx = gen_pruloopsi (loop->begin->loop_count, label_ref); + emit_insn_before (loop_rtx, loop->begin->insn); + } + else if (loop_mode == VOIDmode) + { + gcc_assert (CONST_INT_P (loop->begin->loop_count)); + gcc_assert (UBYTE_INT ( INTVAL (loop->begin->loop_count))); + rtx loop_rtx = gen_pruloopsi (loop->begin->loop_count, label_ref); + emit_insn_before (loop_rtx, loop->begin->insn); + } + else + gcc_unreachable (); + delete_insn (loop->begin->insn); + + /* Insert the repeat label before the first doloop_end. + Fill the gap with nops if LOOP insn is less than 2 + instructions away than loop->end. */ + pru_insert_loop_label_last (loop->end->insn, repeat_label, + loop->end->next != 0); + + /* Emit a pruloop_end (to improve the readability of the output). */ + emit_insn_before (gen_pruloop_end (), loop->end->insn); + + /* HACK: TODO: This is usually not needed, but is required for + a few rare cases where a JUMP that breaks the loop + references the LOOP_END address. In other words, since + we're missing a real "loop_end" instruction, a loop "break" + may accidentally reference the loop end itself, and thus + continuing the cycle. */ + for (insn = NEXT_INSN (loop->end->insn); + insn != next_real_insn (loop->end->insn); + insn = NEXT_INSN (insn)) + { + if (LABEL_P (insn) && LABEL_NUSES (insn) > 0) + emit_insn_before (gen_nop_loop_guard (), loop->end->insn); + } + + /* Delete the first doloop_end. */ + delete_insn (loop->end->insn); + + /* Replace the others with branches to REPEAT_LABEL. */ + for (end = loop->end->next; end != 0; end = end->next) + { + rtx_insn *newjmp; + newjmp = emit_jump_insn_before (gen_jump (repeat_label), end->insn); + JUMP_LABEL (newjmp) = repeat_label; + delete_insn (end->insn); + delete_insn (end->fallthrough); + } + } + else + { + /* Case (3). First replace all the doloop_begins with setting + the HW register used for loop counter. */ + for (begin = loop->begin; begin != 0; begin = begin->next) + { + insn = gen_move_insn (copy_rtx (begin->counter), + copy_rtx (begin->loop_count)); + emit_insn_before (insn, begin->insn); + delete_insn (begin->insn); + } + + /* Replace all the doloop_ends with decrement-and-branch sequences. */ + for (end = loop->end; end != 0; end = end->next) + { + rtx reg; + + start_sequence (); + + /* Load the counter value into a general register. */ + reg = end->counter; + if (!REG_P (reg) || REGNO (reg) > LAST_NONIO_GP_REG) + { + reg = end->scratch; + emit_move_insn (copy_rtx (reg), copy_rtx (end->counter)); + } + + /* Decrement the counter. */ + emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg), + constm1_rtx)); + + /* Copy it back to its original location. */ + if (reg != end->counter) + emit_move_insn (copy_rtx (end->counter), copy_rtx (reg)); + + /* Jump back to the start label. */ + insn = emit_jump_insn (gen_cbranchsi4 (gen_rtx_NE (VOIDmode, reg, + const0_rtx), + reg, + const0_rtx, + end->label)); + + JUMP_LABEL (insn) = end->label; + LABEL_NUSES (end->label)++; + + /* Emit the whole sequence before the doloop_end. */ + insn = get_insns (); + end_sequence (); + emit_insn_before (insn, end->insn); + + /* Delete the doloop_end. */ + delete_insn (end->insn); + } + } +} + +/* Implement TARGET_MACHINE_DEPENDENT_REORG. */ +static void +pru_reorg (void) +{ + rtx_insn *insns = get_insns (); + + compute_bb_for_insn (); + df_analyze (); + + /* Need correct insn lengths for allowing LOOP instruction + emitting due to U8_PCREL limitations. */ + shorten_branches (get_insns ()); + + /* The generic reorg_loops () is not suitable for PRU because + it doesn't handle doloop_begin/end tying. And we need our + doloop_begin emitted before reload. It is difficult to coalesce + UBYTE constant initial loop values into the LOOP insn during + machine reorg phase. */ + pru_reorg_loop (insns); + + df_finish_pass (false); +} + +/* Enumerate all PRU-specific builtins. */ +enum pru_builtin +{ + PRU_BUILTIN_DELAY_CYCLES, + PRU_BUILTIN_max +}; + +static GTY(()) tree pru_builtins [(int) PRU_BUILTIN_max]; + +/* Implement TARGET_INIT_BUILTINS. */ + +static void +pru_init_builtins (void) +{ + tree void_ftype_longlong + = build_function_type_list (void_type_node, + long_long_integer_type_node, + NULL); + + pru_builtins[PRU_BUILTIN_DELAY_CYCLES] + = add_builtin_function ( "__delay_cycles", void_ftype_longlong, + PRU_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, + NULL_TREE); +} + +/* Implement TARGET_BUILTIN_DECL. */ + +static tree +pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) +{ + switch (code) + { + case PRU_BUILTIN_DELAY_CYCLES: + return pru_builtins[code]; + default: + return error_mark_node; + } +} + +/* Emit a sequence of one or more delay_cycles_X insns, in order to generate + code that delays exactly ARG cycles. */ + +static rtx +pru_expand_delay_cycles (rtx arg) +{ + HOST_WIDE_INT c, n; + + if (GET_CODE (arg) != CONST_INT) + { + error ("%<__delay_cycles%> only takes constant arguments"); + return NULL_RTX; + } + + c = INTVAL (arg); + + if (HOST_BITS_PER_WIDE_INT > 32) + { + if (c < 0) + { + error ("%<__delay_cycles%> only takes non-negative cycle counts"); + return NULL_RTX; + } + } + + emit_insn (gen_delay_cycles_start (arg)); + + /* For 32-bit loops, there's 2 + 2x cycles. */ + if (c > 2 * 0xffff + 1) + { + n = (c - 2) / 2; + c -= (n * 2) + 2; + if ((unsigned long long) n > 0xffffffffULL) + { + error ("%<__delay_cycles%> is limited to 32-bit loop counts"); + return NULL_RTX; + } + emit_insn (gen_delay_cycles_2x_plus2_si (GEN_INT (n))); + } + + /* For 16-bit loops, there's 1 + 2x cycles. */ + if (c > 2) + { + n = (c - 1) / 2; + c -= (n * 2) + 1; + + emit_insn (gen_delay_cycles_2x_plus1_hi (GEN_INT (n))); + } + + while (c > 0) + { + emit_insn (gen_delay_cycles_1 ()); + c -= 1; + } + + emit_insn (gen_delay_cycles_end (arg)); + + return NULL_RTX; +} + + +/* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls + a built-in function, with result going to TARGET if that's convenient + (and in mode MODE if that's convenient). + SUBTARGET may be used as the target for computing one of EXP's operands. + IGNORE is nonzero if the value is to be ignored. */ + +static rtx +pru_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, + rtx subtarget ATTRIBUTE_UNUSED, + machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); + + if (fcode == PRU_BUILTIN_DELAY_CYCLES) + return pru_expand_delay_cycles (arg1); + + internal_error ("bad builtin code"); + + return NULL_RTX; +} + +/* Remember the last target of pru_set_current_function. */ +static GTY(()) tree pru_previous_fndecl; + +/* Establish appropriate back-end context for processing the function + FNDECL. The argument might be NULL to indicate processing at top + level, outside of any function scope. */ +static void +pru_set_current_function (tree fndecl) +{ + tree old_tree = (pru_previous_fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (pru_previous_fndecl) + : NULL_TREE); + + tree new_tree = (fndecl + ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl) + : NULL_TREE); + + if (fndecl && fndecl != pru_previous_fndecl) + { + pru_previous_fndecl = fndecl; + if (old_tree == new_tree) + ; + + else if (new_tree) + { + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + target_reinit (); + } + + else if (old_tree) + { + struct cl_target_option *def + = TREE_TARGET_OPTION (target_option_current_node); + + cl_target_option_restore (&global_options, def); + target_reinit (); + } + } +} + +/* Implement TARGET_UNWIND_WORD_MODE. + + Since PRU is really a 32-bit CPU, the default word_mode is not suitable. */ +static scalar_int_mode +pru_unwind_word_mode (void) +{ + return SImode; +} + + +/* Initialize the GCC target structure. */ +#undef TARGET_ASM_FUNCTION_PROLOGUE +#define TARGET_ASM_FUNCTION_PROLOGUE pru_asm_function_prologue +#undef TARGET_ASM_INTEGER +#define TARGET_ASM_INTEGER pru_assemble_integer + +#undef TARGET_ASM_FILE_START +#define TARGET_ASM_FILE_START pru_file_start + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS pru_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN pru_expand_builtin +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL pru_builtin_decl + +#undef TARGET_FUNCTION_OK_FOR_SIBCALL +#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true + +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE pru_can_eliminate + +#undef TARGET_MODES_TIEABLE_P +#define TARGET_MODES_TIEABLE_P pru_modes_tieable_p + +#undef TARGET_HARD_REGNO_MODE_OK +#define TARGET_HARD_REGNO_MODE_OK pru_hard_regno_mode_ok + +#undef TARGET_HARD_REGNO_SCRATCH_OK +#define TARGET_HARD_REGNO_SCRATCH_OK pru_hard_regno_scratch_ok + +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG pru_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE pru_function_arg_advance + +#undef TARGET_ARG_PARTIAL_BYTES +#define TARGET_ARG_PARTIAL_BYTES pru_arg_partial_bytes + +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE pru_function_value + +#undef TARGET_LIBCALL_VALUE +#define TARGET_LIBCALL_VALUE pru_libcall_value + +#undef TARGET_FUNCTION_VALUE_REGNO_P +#define TARGET_FUNCTION_VALUE_REGNO_P pru_function_value_regno_p + +#undef TARGET_RETURN_IN_MEMORY +#define TARGET_RETURN_IN_MEMORY pru_return_in_memory + +#undef TARGET_MUST_PASS_IN_STACK +#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size + +#undef TARGET_LEGITIMATE_ADDRESS_P +#define TARGET_LEGITIMATE_ADDRESS_P pru_legitimate_address_p + +#undef TARGET_PREFERRED_RELOAD_CLASS +#define TARGET_PREFERRED_RELOAD_CLASS pru_preferred_reload_class + +#undef TARGET_INIT_LIBFUNCS +#define TARGET_INIT_LIBFUNCS pru_init_libfuncs +#undef TARGET_LIBFUNC_GNU_PREFIX +#define TARGET_LIBFUNC_GNU_PREFIX true + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS pru_rtx_costs + +#undef TARGET_PRINT_OPERAND +#define TARGET_PRINT_OPERAND pru_print_operand + +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS pru_print_operand_address + +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE pru_option_override + +#undef TARGET_SET_CURRENT_FUNCTION +#define TARGET_SET_CURRENT_FUNCTION pru_set_current_function + +#undef TARGET_MACHINE_DEPENDENT_REORG +#define TARGET_MACHINE_DEPENDENT_REORG pru_reorg + +#undef TARGET_CAN_USE_DOLOOP_P +#define TARGET_CAN_USE_DOLOOP_P pru_can_use_doloop_p + +#undef TARGET_INVALID_WITHIN_DOLOOP +#define TARGET_INVALID_WITHIN_DOLOOP pru_invalid_within_doloop + +#undef TARGET_UNWIND_WORD_MODE +#define TARGET_UNWIND_WORD_MODE pru_unwind_word_mode + +#undef TARGET_HAVE_SPECULATION_SAFE_VALUE +#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed + +struct gcc_target targetm = TARGET_INITIALIZER; + +#include "gt-pru.h" diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h new file mode 100644 index 00000000000..de1b9100209 --- /dev/null +++ b/gcc/config/pru/pru.h @@ -0,0 +1,551 @@ +/* Definitions of target machine for TI PRU. + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +#ifndef GCC_PRU_H +#define GCC_PRU_H + +#include "config/pru/pru-opts.h" + +/* Define built-in preprocessor macros. */ +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + builtin_define_std ("__PRU__"); \ + builtin_define_std ("__pru__"); \ + builtin_define_std ("__PRU_V3__"); \ + builtin_define_std ("__LITTLE_ENDIAN__"); \ + builtin_define_std ("__little_endian__"); \ + /* Trampolines are disabled for now. */ \ + builtin_define_std ("NO_TRAMPOLINES"); \ + } \ + while (0) + +/* TI ABI implementation is not feature enough (e.g. function pointers are + not supported), so we cannot list it as a multilib variant. To prevent + misuse from users, do not link any of the standard libraries. */ +#define DRIVER_SELF_SPECS \ + "%{mabi=ti:-nodefaultlibs} " \ + "%{mmcu=*:-specs=device-specs/%*%s %= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO ? SIB_REGS \ + : (REGNO) == STATIC_CHAIN_REGNUM ? SIB_REGS \ + : (REGNO) == LOOPCNTR_REG ? LOOPCNTR_REGS \ + : (REGNO) <= LAST_NONIO_GP_REG ? GP_REGS \ + : ALL_REGS) + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) + +/* Arbitrarily set to a non-argument register. Not defined by TI ABI. */ +#define STATIC_CHAIN_REGNUM 0 /* r0 */ + +/* Tests for various kinds of constants used in the PRU port. */ +#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31) + +#define UHWORD_INT(X) (IN_RANGE ((X), 0, 0xffff)) +#define SHWORD_INT(X) (IN_RANGE ((X), -32768, 32767)) +#define UBYTE_INT(X) (IN_RANGE ((X), 0, 0xff)) + +/* Say that the epilogue uses the return address register. Note that + in the case of sibcalls, the values "used by the epilogue" are + considered live at the start of the called function. */ +#define EPILOGUE_USES(REGNO) (epilogue_completed && \ + (((REGNO) == RA_REGNO) \ + || (REGNO) == (RA_REGNO + 1))) + +/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, + the stack pointer does not matter. The value is tested only in + functions that have frame pointers. + No definition is equivalent to always zero. */ + +#define EXIT_IGNORE_STACK 1 + +/* Trampolines are not supported, but put a define to keep the build. */ +#define TRAMPOLINE_SIZE 4 + +/* Stack layout. */ +#define STACK_GROWS_DOWNWARD 1 +#undef FRAME_GROWS_DOWNWARD +#define FIRST_PARM_OFFSET(FUNDECL) 0 + +/* Before the prologue, RA lives in r3.w2. */ +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (HImode, RA_REGNO) + +#define RETURN_ADDR_RTX(C,F) pru_get_return_address (C) + +#define DWARF_FRAME_RETURN_COLUMN RA_REGNO + +/* The CFA includes the pretend args. */ +#define ARG_POINTER_CFA_OFFSET(FNDECL) \ + (gcc_assert ((FNDECL) == current_function_decl), \ + FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size) + +/* Frame/arg pointer elimination settings. */ +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ + (OFFSET) = pru_initial_elimination_offset ((FROM), (TO)) + +#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \ + pru_hard_regno_rename_ok (OLD_REG, NEW_REG) + +/* Calling convention definitions. */ +#if !defined(IN_LIBGCC2) + +#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1) + +typedef struct pru_args +{ + bool regs_used[NUM_ARG_REGS]; +} CUMULATIVE_ARGS; + +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ + do { \ + memset ((CUM).regs_used, 0, sizeof ((CUM).regs_used)); \ + } while (0) + +#define FUNCTION_ARG_REGNO_P(REGNO) \ + ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO) + +/* Passing function arguments on stack. */ +#define PUSH_ARGS 0 +#define ACCUMULATE_OUTGOING_ARGS 1 + +/* We define TARGET_RETURN_IN_MEMORY, so set to zero. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Profiling. */ +#define PROFILE_BEFORE_PROLOGUE +#define NO_PROFILE_COUNTERS 1 +#define FUNCTION_PROFILER(FILE, LABELNO) \ + pru_function_profiler ((FILE), (LABELNO)) + +#endif /* IN_LIBGCC2 */ + +/* Addressing modes. */ + +#define CONSTANT_ADDRESS_P(X) \ + (CONSTANT_P (X) && memory_address_p (SImode, X)) + +#define MAX_REGS_PER_ADDRESS 2 +#define BASE_REG_CLASS ALL_REGS +#define INDEX_REG_CLASS ALL_REGS + +#define REGNO_OK_FOR_BASE_P(REGNO) pru_regno_ok_for_base_p ((REGNO), true) +#define REGNO_OK_FOR_INDEX_P(REGNO) pru_regno_ok_for_index_p ((REGNO), true) + +/* Limited by the insns in pru-ldst-multiple.md. */ +#define MOVE_MAX 8 +#define SLOW_BYTE_ACCESS 1 + +/* It is as good to call a constant function address as to call an address + kept in a register. */ +#define NO_FUNCTION_CSE 1 + +/* Define output assembler language. */ + +#define ASM_APP_ON "#APP\n" +#define ASM_APP_OFF "#NO_APP\n" + +#define ASM_COMMENT_START "# " + +#define GLOBAL_ASM_OP "\t.global\t" + +#define __pru_name_R(X) X".b0", X".b1", X".b2", X".b3" +#define REGISTER_NAMES \ + { \ + __pru_name_R ("r0"), \ + __pru_name_R ("r1"), \ + __pru_name_R ("r2"), \ + __pru_name_R ("r3"), \ + __pru_name_R ("r4"), \ + __pru_name_R ("r5"), \ + __pru_name_R ("r6"), \ + __pru_name_R ("r7"), \ + __pru_name_R ("r8"), \ + __pru_name_R ("r9"), \ + __pru_name_R ("r10"), \ + __pru_name_R ("r11"), \ + __pru_name_R ("r12"), \ + __pru_name_R ("r13"), \ + __pru_name_R ("r14"), \ + __pru_name_R ("r15"), \ + __pru_name_R ("r16"), \ + __pru_name_R ("r17"), \ + __pru_name_R ("r18"), \ + __pru_name_R ("r19"), \ + __pru_name_R ("r20"), \ + __pru_name_R ("r21"), \ + __pru_name_R ("r22"), \ + __pru_name_R ("r23"), \ + __pru_name_R ("r24"), \ + __pru_name_R ("r25"), \ + __pru_name_R ("r26"), \ + __pru_name_R ("r27"), \ + __pru_name_R ("r28"), \ + __pru_name_R ("r29"), \ + __pru_name_R ("r30"), \ + __pru_name_R ("r31"), \ + __pru_name_R ("loopcntr_reg"), \ + __pru_name_R ("pc"), \ + __pru_name_R ("fake_fp"), \ + __pru_name_R ("fake_ap"), \ +} + +#define __pru_overlap_R(X) \ + { "r" #X , X * 4 , 4 }, \ + { "r" #X ".w0", X * 4 + 0 , 2 }, \ + { "r" #X ".w1", X * 4 + 1 , 2 }, \ + { "r" #X ".w2", X * 4 + 2 , 2 } + +#define OVERLAPPING_REGISTER_NAMES \ + { \ + /* Aliases. */ \ + { "sp", 2 * 4, 4 }, \ + { "ra", 3 * 4, 2 }, \ + { "fp", 4 * 4, 4 }, \ + __pru_overlap_R (0), \ + __pru_overlap_R (1), \ + __pru_overlap_R (2), \ + __pru_overlap_R (3), \ + __pru_overlap_R (4), \ + __pru_overlap_R (5), \ + __pru_overlap_R (6), \ + __pru_overlap_R (7), \ + __pru_overlap_R (8), \ + __pru_overlap_R (9), \ + __pru_overlap_R (10), \ + __pru_overlap_R (11), \ + __pru_overlap_R (12), \ + __pru_overlap_R (13), \ + __pru_overlap_R (14), \ + __pru_overlap_R (15), \ + __pru_overlap_R (16), \ + __pru_overlap_R (17), \ + __pru_overlap_R (18), \ + __pru_overlap_R (19), \ + __pru_overlap_R (20), \ + __pru_overlap_R (21), \ + __pru_overlap_R (22), \ + __pru_overlap_R (23), \ + __pru_overlap_R (24), \ + __pru_overlap_R (25), \ + __pru_overlap_R (26), \ + __pru_overlap_R (27), \ + __pru_overlap_R (28), \ + __pru_overlap_R (29), \ + __pru_overlap_R (30), \ + __pru_overlap_R (31), \ +} + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + do \ + { \ + fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \ + fprintf (FILE, "%%pmem(.L%u)\n", (unsigned) (VALUE)); \ + } \ + while (0) + +#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \ + do \ + { \ + fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), STREAM); \ + fprintf (STREAM, "%%pmem(.L%u-.L%u)\n", (unsigned) (VALUE), \ + (unsigned) (REL)); \ + } \ + while (0) + +/* Section directives. */ + +/* Output before read-only data. */ +#define TEXT_SECTION_ASM_OP "\t.section\t.text" + +/* Output before writable data. */ +#define DATA_SECTION_ASM_OP "\t.section\t.data" + +/* Output before uninitialized data. */ +#define BSS_SECTION_ASM_OP "\t.section\t.bss" + +#define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\"aw\",%init_array" +#define DTORS_SECTION_ASM_OP "\t.section\t.fini_array,\"aw\",%fini_array" + +#undef INIT_SECTION_ASM_OP +#undef FINI_SECTION_ASM_OP +#define INIT_ARRAY_SECTION_ASM_OP CTORS_SECTION_ASM_OP +#define FINI_ARRAY_SECTION_ASM_OP DTORS_SECTION_ASM_OP + +/* Since we use .init_array/.fini_array we don't need the markers at + the start and end of the ctors/dtors arrays. */ +#define CTOR_LIST_BEGIN asm (CTORS_SECTION_ASM_OP) +#define CTOR_LIST_END /* empty */ +#define DTOR_LIST_BEGIN asm (DTORS_SECTION_ASM_OP) +#define DTOR_LIST_END /* empty */ + +#undef TARGET_ASM_CONSTRUCTOR +#define TARGET_ASM_CONSTRUCTOR pru_elf_asm_constructor + +#undef TARGET_ASM_DESTRUCTOR +#define TARGET_ASM_DESTRUCTOR pru_elf_asm_destructor + +#define ASM_OUTPUT_ALIGN(FILE, LOG) \ + do { \ + fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \ + } while (0) + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do \ + { \ + fprintf ((FILE), "%s", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", (SIZE), \ + (ALIGN) / BITS_PER_UNIT); \ + } \ +while (0) + + +/* This says how to output assembler code to declare an + uninitialized internal linkage data object. Under SVR4, + the linker seems to want the alignment of data objects + to depend on their types. We do exactly that here. */ + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + switch_to_section (bss_section); \ + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \ + if (!flag_inhibit_size_directive) \ + ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \ + ASM_OUTPUT_ALIGN ((FILE), exact_log2 ((ALIGN) / BITS_PER_UNIT)); \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + ASM_OUTPUT_SKIP ((FILE), (SIZE) ? (SIZE) : 1); \ +} while (0) + +/* Misc parameters. */ + +#define STORE_FLAG_VALUE 1 +#define Pmode SImode +#define FUNCTION_MODE Pmode + +#define CASE_VECTOR_MODE Pmode + +/* Jumps are cheap on PRU. */ +#define LOGICAL_OP_NON_SHORT_CIRCUIT 0 + +/* Unfortunately the LBBO instruction does not zero-extend data. */ +#undef LOAD_EXTEND_OP + +#undef WORD_REGISTER_OPERATIONS + +#define HAS_LONG_UNCOND_BRANCH 1 +#define HAS_LONG_COND_BRANCH 1 + +#define REGISTER_TARGET_PRAGMAS() pru_register_pragmas () + +#endif /* GCC_PRU_H */ diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md new file mode 100644 index 00000000000..4be1958e6c9 --- /dev/null +++ b/gcc/config/pru/pru.md @@ -0,0 +1,956 @@ +;; Machine Description for TI PRU. +;; Copyright (C) 2014-2018 Free Software Foundation, Inc. +;; Contributed by Dimitar Dimitrov +;; Based on the NIOS2 GCC port. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. +;; +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +;; Register numbers. +(define_constants + [ + (FIRST_ARG_REGNO 56) ; Argument registers. + (LAST_ARG_REGNO 119) ; + (FIRST_RETVAL_REGNO 56) ; Return value registers. + (LAST_RETVAL_REGNO 60) ; + (PROLOGUE_TEMP_REGNO 4) ; Temporary register to use in prologue. + + (RA_REGNO 14) ; Return address register r3.w2. + (FP_REGNO 16) ; Frame pointer register. + (LAST_NONIO_GP_REG 119) ; Last non-I/O general purpose register. + (LOOPCNTR_REG 128) ; internal LOOP counter register + (LAST_GP_REG 132) ; Last general purpose register. + + ;; Target register definitions. + (STACK_POINTER_REGNUM 8) + (HARD_FRAME_POINTER_REGNUM FP_REGNO) + (PC_REGNUM 132) + (FRAME_POINTER_REGNUM 136) + (ARG_POINTER_REGNUM 140) + (FIRST_PSEUDO_REGISTER 144) + ] +) + +;; Enumeration of UNSPECs. + +(define_c_enum "unspecv" [ + UNSPECV_DELAY_CYCLES_START + UNSPECV_DELAY_CYCLES_END + UNSPECV_DELAY_CYCLES_2X_HI + UNSPECV_DELAY_CYCLES_2X_SI + UNSPECV_DELAY_CYCLES_1 + + UNSPECV_LOOP_BEGIN + UNSPECV_LOOP_END + + UNSPECV_BLOCKAGE +]) + +; Length of an instruction (in bytes). +(define_attr "length" "" (const_int 4)) +(define_attr "type" + "unknown,complex,control,alu,cond_alu,st,ld,shift" + (const_string "complex")) + +(define_asm_attributes + [(set_attr "length" "4") + (set_attr "type" "complex")]) + +; There is no pipeline, so our scheduling description is simple. +(define_automaton "pru") +(define_cpu_unit "cpu" "pru") + +(define_insn_reservation "everything" 1 (match_test "true") "cpu") + +(include "predicates.md") +(include "constraints.md") + +;; All supported direct move-modes +(define_mode_iterator MOVMODE [QI QQ UQQ + HI HQ UHQ HA UHA + SI SQ USQ SA USA + SF]) + +(define_mode_iterator MOV32 [SI SF SD SQ USQ]) +(define_mode_iterator MOV64 [DI DF DD DQ UDQ]) +(define_mode_iterator QISI [QI HI SI]) +(define_mode_iterator HISI [HI SI]) +(define_mode_iterator QIHI [QI HI]) +(define_mode_iterator SFDF [SF DF]) + +;; EQS0/0 for extension source 0/1 and EQD for extension destination patterns. +(define_mode_iterator EQS0 [QI HI SI]) +(define_mode_iterator EQS1 [QI HI SI]) +(define_mode_iterator EQD [QI HI SI]) + +; Not recommended. Please use %0 instead! +(define_mode_attr regwidth [(QI ".b0") (HI ".w0") (SI "")]) + +;; Move instructions + +(define_expand "mov" + [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "") + (match_operand:MOVMODE 1 "general_operand" ""))] + "" + " + { + /* It helps to split constant loading and memory access + early, so that the LDI/LDI32 instructions can be hoisted + outside a loop body. */ + if (MEM_P (operands[0])) + operands[1] = force_reg (mode, operands[1]); + } + " +) + +;; Leave mem and reg operands in the same insn. Otherwise LRA gets +;; confused, and gcc.target/pru/pr64366.c triggers infinite loops in reload. +(define_insn "prumov" + [(set (match_operand:MOVMODE 0 "nonimmediate_operand" "=m,r,r") + (match_operand:MOVMODE 1 "nonimmediate_operand" "r,m,r"))] + "" + "@ + sb%B0o\\t%b1, %0, %S0 + lb%B1o\\t%b0, %1, %S1 + mov\\t%0, %1" + [(set_attr "type" "st,ld,alu") + (set_attr "length" "4,4,4")]) + + +;; Split loading of integer constants into a distinct pattern, in order to +;; prevent CSE from considering "SET (MEM, CONST_INT)" as a valid insn +;; selection. This fixes an abnormally long compile time exposed by +;; gcc.dg/pr48141.c +;; +;; Note: Assume that Program Mem (T constraint) can fit in 16 bits! +(define_insn "prumov_ldi" + [(set (match_operand:QIHI 0 "register_operand" "=r,r,r") + (match_operand:VOID 1 "immediate_operand" "T,J,N"))] + "" + "@ + ldi\\t%0, %%pmem(%1) + ldi\\t%0, %1 + ldi\\t%0, (%1) & 0xffff" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" "4,4,4")]) + +(define_insn "prumov_ldisisf" + [(set (match_operand:MOV32 0 "register_operand" "=r,r,r") + (match_operand:MOV32 1 "immediate_operand" "T,J,iF"))] + "" + "@ + ldi\\t%F0, %%pmem(%1) + ldi\\t%F0, %1 + ldi32\\t%F0, %1" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" "4,4,8")]) + +; I cannot think of any reason for the core to pass a 64-bit symbolic +; constants. Hence simplify the rule and handle only numeric constants. +; +; Note: Unlike the arithmetics, here we cannot use "&" output modifier. +; GCC expects to be able to move registers around "no matter what". +; Forcing DI reg alignment (akin to microblaze's HARD_REGNO_MODE_OK) +; does not seem efficient, and will violate TI ABI. +(define_insn "mov" + [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r") + (match_operand:MOV64 1 "general_operand" "r,m,r,T,J,nF"))] + "" + { + switch (which_alternative) + { + case 0: + return "sb%B0o\\t%b1, %0, %S0"; + case 1: + return "lb%B1o\\t%b0, %1, %S1"; + case 2: + /* careful with overlapping source and destination regs. */ + gcc_assert (GP_REG_P (REGNO (operands[0]))); + gcc_assert (GP_REG_P (REGNO (operands[1]))); + if (REGNO (operands[0]) == (REGNO (operands[1]) + 4)) + return "mov\\t%N0, %N1\;mov\\t%F0, %F1"; + else + return "mov\\t%F0, %F1\;mov\\t%N0, %N1"; + case 3: + return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0"; + case 4: + return "ldi\\t%F0, %1\;ldi\\t%N0, 0"; + case 5: + return "ldi32\\t%F0, %w1\;" + "ldi32\\t%N0, %W1"; + default: + gcc_unreachable (); + } + } + [(set_attr "type" "st,ld,alu,alu,alu,alu") + (set_attr "length" "4,4,8,8,8,16")]) + +; +; load_multiple pattern(s). +; +; ??? Due to reload problems with replacing registers inside match_parallel +; we currently support load_multiple/store_multiple only after reload. +; +; Idea taken from the s390 port. + +(define_expand "load_multiple" + [(match_par_dup 3 [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))])] + "reload_completed" +{ + machine_mode mode; + int regno; + int count; + rtx from; + int i, off; + + /* Support only loading a constant number of fixed-point registers from + memory. */ + if (GET_CODE (operands[2]) != CONST_INT + || GET_CODE (operands[1]) != MEM + || GET_CODE (operands[0]) != REG) + FAIL; + + count = INTVAL (operands[2]); + regno = REGNO (operands[0]); + mode = GET_MODE (operands[0]); + if (mode != QImode) + FAIL; + + operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + if (!can_create_pseudo_p ()) + { + if (GET_CODE (XEXP (operands[1], 0)) == REG) + { + from = XEXP (operands[1], 0); + off = 0; + } + else if (GET_CODE (XEXP (operands[1], 0)) == PLUS + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG + && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT) + { + from = XEXP (XEXP (operands[1], 0), 0); + off = INTVAL (XEXP (XEXP (operands[1], 0), 1)); + } + else + FAIL; + } + else + { + from = force_reg (Pmode, XEXP (operands[1], 0)); + off = 0; + } + + for (i = 0; i < count; i++) + XVECEXP (operands[3], 0, i) + = gen_rtx_SET (gen_rtx_REG (mode, regno + i), + change_address (operands[1], mode, + plus_constant (Pmode, from, + off + i * GET_MODE_SIZE (mode)))); +}) + +(define_insn "*pru_load_multiple" + [(match_parallel 0 "load_multiple_operation" + [(set (match_operand:QI 1 "register_operand" "=r") + (match_operand:QI 2 "memory_operand" "m"))])] + "reload_completed" +{ + int nregs = XVECLEN (operands[0], 0); + operands[0] = GEN_INT (nregs); + return "lb%B2o\\t%b1, %2, %0"; +} + [(set_attr "type" "ld") + (set_attr "length" "4")]) + +; +; store multiple pattern(s). +; + +(define_expand "store_multiple" + [(match_par_dup 3 [(set (match_operand 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))])] + "reload_completed" +{ + machine_mode mode; + int regno; + int count; + rtx to; + int i, off; + + /* Support only storing a constant number of fixed-point registers to + memory. */ + if (GET_CODE (operands[2]) != CONST_INT + || GET_CODE (operands[0]) != MEM + || GET_CODE (operands[1]) != REG) + FAIL; + + count = INTVAL (operands[2]); + regno = REGNO (operands[1]); + mode = GET_MODE (operands[1]); + if (mode != QImode) + FAIL; + + operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + + if (!can_create_pseudo_p ()) + { + if (GET_CODE (XEXP (operands[0], 0)) == REG) + { + to = XEXP (operands[0], 0); + off = 0; + } + else if (GET_CODE (XEXP (operands[0], 0)) == PLUS + && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG + && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT) + { + to = XEXP (XEXP (operands[0], 0), 0); + off = INTVAL (XEXP (XEXP (operands[0], 0), 1)); + } + else + FAIL; + } + else + { + to = force_reg (Pmode, XEXP (operands[0], 0)); + off = 0; + } + + for (i = 0; i < count; i++) + XVECEXP (operands[3], 0, i) + = gen_rtx_SET (change_address (operands[0], mode, + plus_constant (Pmode, to, + off + i * GET_MODE_SIZE (mode))), + gen_rtx_REG (mode, regno + i)); +}) + +(define_insn "*pru_store_multiple" + [(match_parallel 0 "store_multiple_operation" + [(set (match_operand:QI 1 "memory_operand" "=m") + (match_operand:QI 2 "register_operand" "r"))])] + "reload_completed" +{ + int nregs = XVECLEN (operands[0], 0); + operands[0] = GEN_INT (nregs); + return "sb%B1o\\t%b2, %1, %0"; +} + [(set_attr "type" "st") + (set_attr "length" "4")]) + +;; Zero extension patterns +;; +;; Unfortunately we cannot use lbbo to load AND zero-extent a value. +;; The burst length parameter of the LBBO instruction designates not only +;; the number of memory data bytes fetched, but also the number of register +;; byte fields written. +(define_expand "zero_extend2" + [(set (match_operand:EQD 0 "register_operand" "=r") + (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r")))] + "" + "" + [(set_attr "type" "alu")]) + +(define_insn "*zero_extend2" + [(set (match_operand:EQD 0 "register_operand" "=r") + (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r")))] + "" + "mov\\t%0, %1" + [(set_attr "type" "alu")]) + +;; Sign extension patterns. We have to emulate them due to lack of +;; signed operations in PRU's ALU. + +(define_insn "extend2" + [(set (match_operand:EQD 0 "register_operand" "=r") + (sign_extend:EQD (match_operand:EQS0 1 "register_operand" "r")))] + "" + { + return pru_output_sign_extend (operands); + } + [(set_attr "type" "complex") + (set_attr "length" "12")]) + +;; Bit extraction +;; We define it solely to allow combine to choose SImode +;; for word mode when trying to match our cbranch_qbbx_* insn. +;; +;; Check how combine.c:make_extraction() uses +;; get_best_reg_extraction_insn() to select the op size. +(define_insn "extzv" + [(set (match_operand:QISI 0 "register_operand" "=r") + (zero_extract:QISI + (match_operand:QISI 1 "register_operand" "r") + (match_operand:QISI 2 "const_int_operand" "i") + (match_operand:QISI 3 "const_int_operand" "i")))] + "" + "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)" + [(set_attr "type" "complex") + (set_attr "length" "8")]) + + + +;; Arithmetic Operations + +(define_expand "add3" + [(set (match_operand:QISI 0 "register_operand" "=r,r,r") + (plus:QISI (match_operand:QISI 1 "register_operand" "%r,r,r") + (match_operand:QISI 2 "nonmemory_operand" "r,I,M")))] + "" + "" + [(set_attr "type" "alu")]) + +(define_insn "adddi3" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r") + (plus:DI (match_operand:DI 1 "register_operand" "%r,r,r") + (match_operand:DI 2 "reg_or_ubyte_operand" "r,I,M")))] + "" + "@ + add\\t%F0, %F1, %F2\;adc\\t%N0, %N1, %N2 + add\\t%F0, %F1, %2\;adc\\t%N0, %N1, 0 + sub\\t%F0, %F1, %n2\;suc\\t%N0, %N1, 0" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" "8,8,8")]) + +(define_expand "sub3" + [(set (match_operand:QISI 0 "register_operand" "=r,r,r") + (minus:QISI (match_operand:QISI 1 "reg_or_ubyte_operand" "r,r,I") + (match_operand:QISI 2 "reg_or_ubyte_operand" "r,I,r")))] + "" + "" + [(set_attr "type" "alu")]) + +(define_insn "subdi3" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r") + (minus:DI (match_operand:DI 1 "register_operand" "r,r,I") + (match_operand:DI 2 "reg_or_ubyte_operand" "r,I,r")))] + "" + "@ + sub\\t%F0, %F1, %F2\;suc\\t%N0, %N1, %N2 + sub\\t%F0, %F1, %2\;suc\\t%N0, %N1, 0 + rsb\\t%F0, %F2, %1\;rsc\\t%N0, %N2, 0" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" "8,8,8")]) + +;; Negate and ones complement + +(define_expand "neg2" + [(set (match_operand:QISI 0 "register_operand" "=r") + (neg:QISI (match_operand:QISI 1 "register_operand" "r")))] + "" + "" + [(set_attr "type" "alu")]) + +(define_expand "one_cmpl2" + [(set (match_operand:QISI 0 "register_operand" "=r") + (not:QISI (match_operand:QISI 1 "register_operand" "r")))] + "" + "" + [(set_attr "type" "alu")]) + +;; Integer logical Operations +;; +;; TODO - add optimized cases that exploit the fact that we can get away +;; with a single machine op for special constants, e.g. UBYTE << (0/8/16/24) + +(define_code_iterator LOGICAL [and ior xor umin umax]) +(define_code_attr logical_asm [(and "and") (ior "or") (xor "xor") (umin "min") (umax "max")]) + +(define_code_iterator LOGICAL_BITOP [and ior xor]) +(define_code_attr logical_bitop_asm [(and "and") (ior "or") (xor "xor")]) + +(define_expand "3" + [(set (match_operand:QISI 0 "register_operand" "=r") + (LOGICAL:QISI (match_operand:QISI 1 "register_operand" "%r") + (match_operand:QISI 2 "reg_or_ubyte_operand" "rI")))] + "" + "" + [(set_attr "type" "alu")]) + + +;; Shift instructions + +(define_code_iterator SHIFT [ashift lshiftrt]) +(define_code_attr shift_op [(ashift "ashl") (lshiftrt "lshr")]) +(define_code_attr shift_asm [(ashift "lsl") (lshiftrt "lsr")]) + +(define_expand "3" + [(set (match_operand:QISI 0 "register_operand" "=r") + (SHIFT:QISI (match_operand:QISI 1 "register_operand" "r") + (match_operand:QISI 2 "shift_operand" "rL")))] + "" + "" + [(set_attr "type" "shift")]) + +; LRA cannot cope with clobbered op2, hence the scratch register. +(define_insn "ashr3" + [(set (match_operand:QISI 0 "register_operand" "=&r,r") + (ashiftrt:QISI + (match_operand:QISI 1 "register_operand" "0,r") + (match_operand:QISI 2 "reg_or_const_1_operand" "r,P"))) + (clobber (match_scratch:QISI 3 "=r,X"))] + "" + "@ + mov %3, %2\;ASHRLP%=:\;qbeq ASHREND%=, %3, 0\; sub %3, %3, 1\; lsr\\t%0, %0, 1\; qbbc ASHRLP%=, %0, (%S0 * 8) - 2\; set %0, %0, (%S0 * 8) - 1\; jmp ASHRLP%=\;ASHREND%=: + lsr\\t%0, %1, 1\;qbbc LSIGN%=, %0, (%S0 * 8) - 2\;set %0, %0, (%S0 * 8) - 1\;LSIGN%=:" + [(set_attr "type" "complex,alu") + (set_attr "length" "28,4")]) + + +;; Include ALU patterns with zero-extension of operands. That's where +;; the real insns are defined. + +(include "alu-zext.md") + +(define_insn "di3" + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (LOGICAL_BITOP:DI + (match_operand:DI 1 "register_operand" "%r,r") + (match_operand:DI 2 "reg_or_ubyte_operand" "r,I")))] + "" + "@ + \\t%F0, %F1, %F2\;\\t%N0, %N1, %N2 + \\t%F0, %F1, %2\;\\t%N0, %N1, 0" + [(set_attr "type" "alu,alu") + (set_attr "length" "8,8")]) + + +(define_insn "one_cmpldi2" + [(set (match_operand:DI 0 "register_operand" "=r") + (not:DI (match_operand:DI 1 "register_operand" "r")))] + "" + { + /* careful with overlapping source and destination regs. */ + gcc_assert (GP_REG_P (REGNO (operands[0]))); + gcc_assert (GP_REG_P (REGNO (operands[1]))); + if (REGNO (operands[0]) == (REGNO (operands[1]) + 4)) + return "not\\t%N0, %N1\;not\\t%F0, %F1"; + else + return "not\\t%F0, %F1\;not\\t%N0, %N1"; + } + [(set_attr "type" "alu") + (set_attr "length" "8")]) + +;; Multiply instruction. Idea for fixing registers comes from the AVR backend. + +(define_expand "mulsi3" + [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "register_operand" "")))] + "" + { + emit_insn (gen_mulsi3_fixinp (operands[0], operands[1], operands[2])); + DONE; + }) + + +(define_expand "mulsi3_fixinp" + [(set (reg:SI 112) (match_operand:SI 1 "register_operand" "")) + (set (reg:SI 116) (match_operand:SI 2 "register_operand" "")) + (set (reg:SI 104) (mult:SI (reg:SI 112) (reg:SI 116))) + (set (match_operand:SI 0 "register_operand" "") (reg:SI 104))] + "" + { + }) + +(define_insn "*mulsi3_prumac" + [(set (reg:SI 104) (mult:SI (reg:SI 112) (reg:SI 116)))] + "" + "nop\;xin\\t0, r26, 4" + [(set_attr "type" "alu") + (set_attr "length" "8")]) + +;; Prologue, Epilogue and Return + +(define_expand "prologue" + [(const_int 1)] + "" +{ + pru_expand_prologue (); + DONE; +}) + +(define_expand "epilogue" + [(return)] + "" +{ + pru_expand_epilogue (false); + DONE; +}) + +(define_expand "sibcall_epilogue" + [(return)] + "" +{ + pru_expand_epilogue (true); + DONE; +}) + +(define_insn "return" + [(simple_return)] + "pru_can_use_return_insn ()" + "ret") + +(define_insn "simple_return" + [(simple_return)] + "" + "ret") + +;; Block any insns from being moved before this point, since the +;; profiling call to mcount can use various registers that aren't +;; saved or used to pass arguments. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] + "" + "" + [(set_attr "type" "unknown") + (set_attr "length" "0")]) + +;; Jumps and calls + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "r"))] + "" + "jmp\\t%0" + [(set_attr "type" "control")]) + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jmp\\t%%label(%l0)" + [(set_attr "type" "control") + (set_attr "length" "4")]) + + +(define_expand "call" + [(parallel [(call (match_operand 0 "" "") + (match_operand 1 "" "")) + (clobber (reg:HI RA_REGNO))])] + "" + "") + +(define_expand "call_value" + [(parallel [(set (match_operand 0 "" "") + (call (match_operand 1 "" "") + (match_operand 2 "" ""))) + (clobber (reg:HI RA_REGNO))])] + "" + "") + +(define_insn "*call" + [(call (mem:SI (match_operand:SI 0 "call_operand" "i,r")) + (match_operand 1 "" "")) + (clobber (reg:HI RA_REGNO))] + "" + "@ + call\\t%%label(%0) + call\\t%0" + [(set_attr "type" "control")]) + +(define_insn "*call_value" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:SI 1 "call_operand" "i,r")) + (match_operand 2 "" ""))) + (clobber (reg:HI RA_REGNO))] + "" + "@ + call\\t%%label(%1) + call\\t%1" + [(set_attr "type" "control")]) + +(define_expand "sibcall" + [(parallel [(call (match_operand 0 "" "") + (match_operand 1 "" "")) + (return)])] + "" + "") + +(define_expand "sibcall_value" + [(parallel [(set (match_operand 0 "" "") + (call (match_operand 1 "" "") + (match_operand 2 "" ""))) + (return)])] + "" + "") + +(define_insn "*sibcall" + [(call (mem:SI (match_operand:SI 0 "call_operand" "i,j")) + (match_operand 1 "" "")) + (return)] + "SIBLING_CALL_P (insn)" + "@ + jmp\\t%%label(%0) + jmp\\t%0" + [(set_attr "type" "control")]) + +(define_insn "*sibcall_value" + [(set (match_operand 0 "register_operand" "") + (call (mem:SI (match_operand:SI 1 "call_operand" "i,j")) + (match_operand 2 "" ""))) + (return)] + "SIBLING_CALL_P (insn)" + "@ + jmp\\t%%label(%1) + jmp\\t%1" + [(set_attr "type" "control")]) + +(define_insn "*tablejump" + [(set (pc) + (match_operand:SI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "" + "jmp\\t%0" + [(set_attr "type" "control")]) + +;; cbranch pattern. +;; +;; NOTE: The short branch check has no typo! We must be conservative and take +;; into account the worst case of having a signed comparison with a +;; "far taken branch" label, which amounts to 7 instructions. + +(define_insn "cbranch4" + [(set (pc) + (if_then_else + (match_operator 0 "ordered_comparison_operator" + [(match_operand:QISI 1 "register_operand" "r,r,r") + (match_operand:QISI 2 "reg_or_ubyte_operand" "r,Z,I")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + const int length = (get_attr_length (insn)); + const bool is_near = (length == 20 || length == 4); + + if (pru_signed_cmp_operator (operands[0], VOIDmode)) + { + enum rtx_code code = GET_CODE (operands[0]); + + if (which_alternative == 0) + return pru_output_signed_cbranch (operands, is_near); + else if (which_alternative == 1 && (code == LT || code == GE)) + return pru_output_signed_cbranch_zeroop2 (operands, is_near); + else + return pru_output_signed_cbranch_ubyteop2 (operands, is_near); + } + else + { + /* PRU demands OP1 to be immediate, so swap operands. */ + if (is_near) + return "qb%P0\t%l3, %1, %2"; + else + return "qb%Q0\t.+8, %1, %2\;jmp\t%%label(%l3)"; + } +} + [(set_attr "type" "control") + (set (attr "length") + (if_then_else + (and (ge (minus (match_dup 3) (pc)) (const_int -2020)) + (le (minus (match_dup 3) (pc)) (const_int 2016))) + (if_then_else + (match_test "pru_signed_cmp_operator (operands[0], VOIDmode)") + (const_int 20) + (const_int 4)) + (if_then_else + (match_test "pru_signed_cmp_operator (operands[0], VOIDmode)") + (const_int 28) + (const_int 8))))]) + + +(define_expand "cbranch4" + [(set (pc) + (if_then_else (match_operator 0 "pru_fp_comparison_operator" + [(match_operand:SFDF 1 "register_operand" "") + (match_operand:SFDF 2 "register_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + rtx t = pru_expand_fp_compare (operands[0], VOIDmode); + operands[0] = t; + operands[1] = XEXP (t, 0); + operands[2] = XEXP (t, 1); +}) + +; +; Bit test branch + +(define_code_iterator BIT_TEST [eq ne]) +(define_code_attr qbbx_op [(eq "qbbc") (ne "qbbs")]) +(define_code_attr qbbx_negop [(eq "qbbs") (ne "qbbc")]) + +(define_insn "cbranch_qbbx_4" + [(set (pc) + (if_then_else + (BIT_TEST (zero_extract:EQD + (match_operand:EQS0 0 "register_operand" "r") + (const_int 1) + (match_operand:EQS1 1 "reg_or_ubyte_operand" "rI")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" +{ + const int length = (get_attr_length (insn)); + const bool is_near = (length == 4); + if (is_near) + return "\\t%l2, %0, %1"; + else + return "\\t.+8, %0, %1\;jmp\\t%%label(%l2)"; +} + [(set_attr "type" "control") + (set (attr "length") + (if_then_else + (and (ge (minus (match_dup 2) (pc)) (const_int -2048)) + (le (minus (match_dup 2) (pc)) (const_int 2044))) + (const_int 4) + (const_int 8)))]) + +;; :::::::::::::::::::: +;; :: +;; :: Low Overhead Looping - idea "borrowed" from MEP +;; :: +;; :::::::::::::::::::: + +;; This insn is volatile because we'd like it to stay in its original +;; position, just before the loop header. If it stays there, we might +;; be able to convert it into a "loop" insn. +(define_insn "doloop_begin_internal" + [(set (match_operand:HISI 0 "register_operand" "=r") + (unspec_volatile:HISI + [(match_operand:HISI 1 "reg_or_ubyte_operand" "rI") + (match_operand 2 "const_int_operand" "")] UNSPECV_LOOP_BEGIN))] + "" + { gcc_unreachable (); } + [(set_attr "length" "4")]) + +(define_expand "doloop_begin" + [(use (match_operand 0 "register_operand" "")) + (use (match_operand 1 "" ""))] + "TARGET_OPT_LOOP" + "pru_emit_doloop (operands, 0); + DONE; + ") + +; Note: "JUMP_INSNs and CALL_INSNs are not allowed to have any output +; reloads;". Hence this insn must be prepared for a counter that is +; not a register. +(define_insn "doloop_end_internal" + [(set (pc) + (if_then_else (ne (match_operand:HISI 0 "nonimmediate_operand" "+r,*m") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HISI (match_dup 0) + (const_int -1))) + (unspec [(match_operand 2 "const_int_operand" "")] UNSPECV_LOOP_END) + (clobber (match_scratch:HISI 3 "=X,&r"))] + "" + { gcc_unreachable (); } + ;; Worst case length: + ;; + ;; sub , 1 4 + ;; qbeq .+8, , 0 4 + ;; jmp 4 + [(set (attr "length") + (if_then_else + (and (ge (minus (pc) (match_dup 1)) (const_int 0)) + (le (minus (pc) (match_dup 1)) (const_int 1020))) + (const_int 4) + (const_int 12)))]) + +(define_expand "doloop_end" + [(use (match_operand 0 "nonimmediate_operand" "")) + (use (label_ref (match_operand 1 "" "")))] + "TARGET_OPT_LOOP" + "if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) == QImode) + FAIL; + pru_emit_doloop (operands, 1); + DONE; + ") + +(define_insn "pruloop" + [(set (reg:HISI LOOPCNTR_REG) + (unspec:HISI [(match_operand:HISI 0 "reg_or_ubyte_operand" "rI") + (label_ref (match_operand 1 "" ""))] + UNSPECV_LOOP_BEGIN))] + "" + "loop\\t%l1, %0" + [(set_attr "length" "4")]) + +(define_insn "pruloop_end" + [(unspec [(const_int 0)] UNSPECV_LOOP_END)] + "" + "# loop end" + [(set_attr "length" "0")]) + + +;; Misc patterns + +(define_insn "delay_cycles_start" + [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] + UNSPECV_DELAY_CYCLES_START)] + "" + "/* Begin %0 cycle delay. */" +) + +(define_insn "delay_cycles_end" + [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] + UNSPECV_DELAY_CYCLES_END)] + "" + "/* End %0 cycle delay. */" +) + + +(define_insn "delay_cycles_2x_plus1_hi" + [(unspec_volatile [(match_operand 0 "const_uhword_operand" "J")] + UNSPECV_DELAY_CYCLES_2X_HI) + (clobber (match_scratch:SI 1 "=&r"))] + "" + "ldi\\t%1, %0\;sub\\t%1, %1, 1\;qbne\\t.-4, %1, 0" + [(set_attr "length" "12")]) + + +; Do not use LDI32 here because we do not want +; to accidentally loose one instruction cycle. +(define_insn "delay_cycles_2x_plus2_si" + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")] + UNSPECV_DELAY_CYCLES_2X_SI) + (clobber (match_scratch:SI 1 "=&r"))] + "" + "ldi\\t%1.w0, %L0\;ldi\\t%1.w2, %H0\;sub\\t%1, %1, 1\;qbne\\t.-4, %1, 0" + [(set_attr "length" "16")]) + +(define_insn "delay_cycles_1" + [(unspec_volatile [(const_int 0) ] UNSPECV_DELAY_CYCLES_1)] + "" + "nop\\t# delay_cycles_1" +) + + +(define_insn "nop" + [(const_int 0)] + "" + "nop" + [(set_attr "type" "alu")]) + +(define_insn "nop_loop_guard" + [(const_int 0)] + "" + "nop\\t# Loop end guard" + [(set_attr "type" "alu")]) diff --git a/gcc/config/pru/pru.opt b/gcc/config/pru/pru.opt new file mode 100644 index 00000000000..e17d92fe1d3 --- /dev/null +++ b/gcc/config/pru/pru.opt @@ -0,0 +1,53 @@ +; Options for the TI PRU port of the compiler. +; Copyright (C) 2018 Free Software Foundation, Inc. +; Contributed by Dimitar Dimitrov +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation; either version 3, or (at your option) +; any later version. +; +; GCC is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; . + +HeaderInclude +config/pru/pru-opts.h + +minrt +Target Report Mask(MINRT) RejectNegative +Use a minimum runtime (no static initializers or ctors) for memory-constrained +devices. + +mmcu= +Target RejectNegative Joined +-mmcu=MCU Select the target System-On-Chip variant that embeds this PRU. + +mno-relax +Target Report +Prevent relaxation of LDI32 relocations. + +mloop +Target Mask(OPT_LOOP) +Allow (or do not allow) gcc to use the LOOP instruction. + +mabi= +Target RejectNegative Report Joined Enum(pru_abi_t) Var(pru_current_abi) Init(PRU_ABI_GNU) Save +Select target ABI variant. + +Enum +Name(pru_abi_t) Type(enum pru_abi) +ABI variant code generation (for use with -mabi= option): + +EnumValue +Enum(pru_abi_t) String(gnu) Value(PRU_ABI_GNU) + +EnumValue +Enum(pru_abi_t) String(ti) Value(PRU_ABI_TI) diff --git a/gcc/config/pru/t-pru b/gcc/config/pru/t-pru new file mode 100644 index 00000000000..ab29e443882 --- /dev/null +++ b/gcc/config/pru/t-pru @@ -0,0 +1,31 @@ +# Makefile fragment for building GCC for the TI PRU target. +# Copyright (C) 2012-2018 Free Software Foundation, Inc. +# Contributed by Dimitar Dimitrov +# Based on the t-nios2 +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with GCC; see the file COPYING3. If not see +# . + +# Unfortunately mabi=ti is not feature-complete enough to build newlib. +# Hence we cannot present mabi=gnu/ti as a multilib option. + +pru-pragma.o: $(srcdir)/config/pru/pru-pragma.c $(RTL_H) $(TREE_H) \ + $(CONFIG_H) $(TM_H) $(srcdir)/config/pru/pru-protos.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + +pru-passes.o: $(srcdir)/config/pru/pru-passes.c $(RTL_H) $(TREE_H) \ + $(CONFIG_H) $(TM_H) $(srcdir)/config/pru/pru-protos.h + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 130f6a671ce..3ffe5d6694b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -21748,6 +21748,7 @@ for further explanation. * ARM Pragmas:: * M32C Pragmas:: * MeP Pragmas:: +* PRU Pragmas:: * RS/6000 and PowerPC Pragmas:: * S/390 Pragmas:: * Darwin Pragmas:: @@ -21899,6 +21900,26 @@ extern int foo (); @end table +@node PRU Pragmas +@subsection PRU Pragmas + +@table @code + +@item ctable_entry @var{index} @var{constant_address} +@cindex pragma, ctable_entry +Specifies that the given PRU CTABLE entry at @var{index} has a value +@var{constant_address}. This enables GCC to emit LBCO/SBCO instructions +when the load/store address is known and can be addressed with some CTABLE +entry. Example: + +@smallexample +/* will compile to "lbco Rx, 2, 0x10, 4" */ +#pragma ctable_entry 2 0x4802a000 +*(unsigned int *)0x4802a010 = val; +@end smallexample + +@end table + @node RS/6000 and PowerPC Pragmas @subsection RS/6000 and PowerPC Pragmas diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 586af1787c7..92d9cd50d29 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1043,6 +1043,10 @@ See RS/6000 and PowerPC Options. -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol -mstack-protector-guard-offset=@var{offset}} +@emph{PRU Options} +@gccoptlist{-mmcu=@var{mcu} -minrt -mno-relax -mloop @gol +-mabi=@var{variant} @gol} + @emph{RISC-V Options} @gccoptlist{-mbranch-cost=@var{N-instruction} @gol -mplt -mno-plt @gol @@ -14661,6 +14665,7 @@ platform. * picoChip Options:: * PowerPC Options:: * PowerPC SPE Options:: +* PRU Options:: * RISC-V Options:: * RL78 Options:: * RS/6000 and PowerPC Options:: @@ -23142,6 +23147,56 @@ the offset with a symbol reference to a canary in the TLS block. @end table +@node PRU Options +@subsection PRU Options +@cindex PRU Options + +These command-line options are defined for PRU target: + +@table @gcctabopt +@item -minrt +@opindex minrt +Enable the use of a minimum runtime environment---no static +initializers or constructors. Results in significant code size +reduction of final ELF binaries. + +@item -mmcu=@var{mcu} +@opindex mmcu +Specify the PRU MCU variant to use. Check Newlib for exact list of options. + +@item -mno-relax +@opindex mno-relax +Pass on (or do not pass on) the @option{-mrelax} command-line option +to the linker. + +@item -mloop +@opindex mloop +Allow (or do not allow) GCC to use the LOOP instruction. + +@item -mabi=@var{variant} +@opindex mabi +Specify the ABI variant to output code for. Permissible values are @samp{gnu} +for GCC, and @samp{ti} for fully conformant TI ABI. These are the differences: + +@table @samp +@item Function Pointer Size +TI ABI specifies that function (code) pointers are 16-bit, whereas GCC +supports only 32-bit data and code pointers. + +@item Optional Return Value Pointer +Function return values larger than 64 bits are passed by using a hidden +pointer as the first argument of the function. TI ABI, though, mandates that +the pointer can be NULL in case the caller is not using the returned value. +GCC always passes and expects a valid return value pointer. + +@end table + +The current @samp{mabi=ti} implementation simply raises a compile error +when any of the above code constructs is detected. + +@end table + + @node RISC-V Options @subsection RISC-V Options @cindex RISC-V Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 02f9e1e4320..434bf5131ec 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3317,6 +3317,28 @@ Vector constant that is all zeros. @end table +@item PRU---@file{config/pru/constraints.md} +@table @code +@item I +An unsigned 8-bit integer constant. + +@item J +An unsigned 16-bit integer constant. + +@item L +An unsigned 5-bit integer constant (for shift counts). + +@item M +An integer constant in the range [-255;0]. + +@item T +A text segment (program memory) constant label. + +@item Z +Integer constant zero. + +@end table + @item RL78---@file{config/rl78/constraints.md} @table @code From patchwork Thu Aug 16 04:49:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958095 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-483757-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="v9mN0ija"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="Wi5Vpg3x"; 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 41rYp14Mkxz9s4c for ; Thu, 16 Aug 2018 14:51:37 +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:in-reply-to:references; q=dns; s= default; b=utTPVVgX/IwvjJeRUz45h8MfiZ19y+JeKDdRfm3Tdh8NzlaXMJhED QUo+HZnqnqU44ydqEhHlTsKFWjIQrXmTy3EgEFDPlFZej/dxi20OxhTjnMcJ5UpZ VAOvG6sdltSKA5KfZL+IK9v3Kh5yX7Ly0gMdnMbxfzsb3lpCxgZp8E= 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:in-reply-to:references; s= default; bh=LBek4FZq5icXxOl5JOocFqxRhfg=; b=v9mN0ija0HhyQa2Zv2As Db9VqBWnysESkVQcJkfGuCvGcegZgLqVG6bJ0uAtlWR79sT0vxXxc+m+sGM/IrVS NaCDFRcj2rFV8yPhJZGk8mXzk6UQ8PWm77+SkMTz+6MHW8iiXYgi2CQ85Pxn4C/8 9m+1CrYwK6YF+XCcf0P8U1s= Received: (qmail 98710 invoked by alias); 16 Aug 2018 04:50:35 -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 98553 invoked by uid 89); 16 Aug 2018 04:50:34 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-21.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SEM_URI, SEM_URIRED, SPF_PASS autolearn=ham version=3.3.2 spammy=unlimited, (unknown), telf, D*eu X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:24 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEn-0004cL-Cz for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:21 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=a3OFvfVEYlQaOHrFTk3MlIbGpLKDYikS9AcT679UUZk=; b=Wi5Vpg3xUscJWnVCwfHPCqOQRy XZ/7qMJYvwisUpWS5J+mxTyU55El8dqKFQgkurWNXY3e1OGcWesGlT8bSwEEKTzAJMrbD3VJPU8Aq 3RLtbKRVR06+w0YxrVxVliwTUrbRm1xVZX7xfr6SBZGczk6ZRudbh1mnMQBL7tjdUxTPTeNRp88Lu 6YM7yJY1J8uu3ixd/+2UENBPeTt1Qh2W7IMtK3prvyuYViJDVjbskq87cEbuRx8Xprn1sLGvP/TAD gRwLmHDuSHJYJ5qMLxe/wPOwt+dHk1LscizvonDCvtlBAopYRKCzjHVmtqfPsuoKallHEZxQpFIvT 7tBOQ9qg==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEj-0004j3-Fn; Thu, 16 Aug 2018 07:50:21 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 02/10] Initial TI PRU libgcc port Date: Thu, 16 Aug 2018 07:49:51 +0300 Message-Id: <20180816044959.12320-3-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-IsSubscribed: yes The floating point support has been borrowed from C6X libgcc port to help with TI PRU toolchain ABI compatibility. libgcc/ChangeLog: 2018-07-27 Dimitar Dimitrov * config.host: Add PRU target. * config/pru/asri.c: New file. * config/pru/eqd.c: New file. * config/pru/eqf.c: New file. * config/pru/ged.c: New file. * config/pru/gef.c: New file. * config/pru/gtd.c: New file. * config/pru/gtf.c: New file. * config/pru/led.c: New file. * config/pru/lef.c: New file. * config/pru/lib2bitcountHI.c: New file. * config/pru/lib2divHI.c: New file. * config/pru/lib2divQI.c: New file. * config/pru/lib2divSI.c: New file. * config/pru/libgcc-eabi.ver: New file. * config/pru/ltd.c: New file. * config/pru/ltf.c: New file. * config/pru/mpyll.S: New file. * config/pru/pru-abi.h: New file. * config/pru/pru-asm.h: New file. * config/pru/pru-divmod.h: New file. * config/pru/sfp-machine.h: New file. * config/pru/t-pru: New file. Signed-off-by: Dimitar Dimitrov --- libgcc/config.host | 7 +++ libgcc/config/pru/asri.c | 33 ++++++++++ libgcc/config/pru/eqd.c | 45 +++++++++++++ libgcc/config/pru/eqf.c | 45 +++++++++++++ libgcc/config/pru/ged.c | 45 +++++++++++++ libgcc/config/pru/gef.c | 45 +++++++++++++ libgcc/config/pru/gtd.c | 45 +++++++++++++ libgcc/config/pru/gtf.c | 45 +++++++++++++ libgcc/config/pru/led.c | 45 +++++++++++++ libgcc/config/pru/lef.c | 45 +++++++++++++ libgcc/config/pru/lib2bitcountHI.c | 43 +++++++++++++ libgcc/config/pru/lib2divHI.c | 42 +++++++++++++ libgcc/config/pru/lib2divQI.c | 42 +++++++++++++ libgcc/config/pru/lib2divSI.c | 48 ++++++++++++++ libgcc/config/pru/libgcc-eabi.ver | 88 ++++++++++++++++++++++++++ libgcc/config/pru/ltd.c | 45 +++++++++++++ libgcc/config/pru/ltf.c | 45 +++++++++++++ libgcc/config/pru/mpyll.S | 57 +++++++++++++++++ libgcc/config/pru/pru-abi.h | 109 ++++++++++++++++++++++++++++++++ libgcc/config/pru/pru-asm.h | 35 +++++++++++ libgcc/config/pru/pru-divmod.h | 117 ++++++++++++++++++++++++++++++++++ libgcc/config/pru/sfp-machine.h | 125 +++++++++++++++++++++++++++++++++++++ libgcc/config/pru/t-pru | 50 +++++++++++++++ 23 files changed, 1246 insertions(+) create mode 100644 libgcc/config/pru/asri.c create mode 100644 libgcc/config/pru/eqd.c create mode 100644 libgcc/config/pru/eqf.c create mode 100644 libgcc/config/pru/ged.c create mode 100644 libgcc/config/pru/gef.c create mode 100644 libgcc/config/pru/gtd.c create mode 100644 libgcc/config/pru/gtf.c create mode 100644 libgcc/config/pru/led.c create mode 100644 libgcc/config/pru/lef.c create mode 100644 libgcc/config/pru/lib2bitcountHI.c create mode 100644 libgcc/config/pru/lib2divHI.c create mode 100644 libgcc/config/pru/lib2divQI.c create mode 100644 libgcc/config/pru/lib2divSI.c create mode 100644 libgcc/config/pru/libgcc-eabi.ver create mode 100644 libgcc/config/pru/ltd.c create mode 100644 libgcc/config/pru/ltf.c create mode 100644 libgcc/config/pru/mpyll.S create mode 100644 libgcc/config/pru/pru-abi.h create mode 100644 libgcc/config/pru/pru-asm.h create mode 100644 libgcc/config/pru/pru-divmod.h create mode 100644 libgcc/config/pru/sfp-machine.h create mode 100644 libgcc/config/pru/t-pru diff --git a/libgcc/config.host b/libgcc/config.host index 18cabaf24f6..ff229c38f0c 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -165,6 +165,9 @@ nios2*-*-*) powerpc*-*-*) cpu_type=rs6000 ;; +pru-*-*) + cpu_type=pru + ;; rs6000*-*-*) ;; riscv*-*-*) @@ -1145,6 +1148,10 @@ powerpcle-*-eabi*) tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit" extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o" ;; +pru-*-*) + tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp t-gnu-prefix pru/t-pru" + tm_file="$tm_file pru/pru-abi.h" + ;; riscv*-*-linux*) tmake_file="${tmake_file} riscv/t-softfp${host_address} t-softfp riscv/t-elf riscv/t-elf${host_address}" extra_parts="$extra_parts crtbegin.o crtend.o crti.o crtn.o crtendS.o crtbeginT.o" diff --git a/libgcc/config/pru/asri.c b/libgcc/config/pru/asri.c new file mode 100644 index 00000000000..591d660f227 --- /dev/null +++ b/libgcc/config/pru/asri.c @@ -0,0 +1,33 @@ +/* PRU ABI compatibility functions + Arithmetic right shift + Copyright (C) 2017-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +int __pruabi_asri(int a, unsigned char shift) +{ + /* GCC has a built-in op. */ + return a >> shift; +} diff --git a/libgcc/config/pru/eqd.c b/libgcc/config/pru/eqd.c new file mode 100644 index 00000000000..cce5c9ec119 --- /dev/null +++ b/libgcc/config/pru/eqd.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a == b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_eqd(DFtype a, DFtype b) +{ + FP_DECL_EX; + FP_DECL_D(A); FP_DECL_D(B); + CMPtype r; + + FP_UNPACK_RAW_D(A, a); + FP_UNPACK_RAW_D(B, b); + FP_CMP_EQ_D(r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return !r; +} diff --git a/libgcc/config/pru/eqf.c b/libgcc/config/pru/eqf.c new file mode 100644 index 00000000000..701b54e06ba --- /dev/null +++ b/libgcc/config/pru/eqf.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a == b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_eqf(SFtype a, SFtype b) +{ + FP_DECL_EX; + FP_DECL_S(A); FP_DECL_S(B); + CMPtype r; + + FP_UNPACK_RAW_S(A, a); + FP_UNPACK_RAW_S(B, b); + FP_CMP_EQ_S(r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return !r; +} diff --git a/libgcc/config/pru/ged.c b/libgcc/config/pru/ged.c new file mode 100644 index 00000000000..91b84ea2639 --- /dev/null +++ b/libgcc/config/pru/ged.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a >= b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_ged(DFtype a, DFtype b) +{ + FP_DECL_EX; + FP_DECL_D(A); FP_DECL_D(B); + CMPtype r; + + FP_UNPACK_RAW_D(A, a); + FP_UNPACK_RAW_D(B, b); + FP_CMP_D(r, A, B, -2, 2); + FP_HANDLE_EXCEPTIONS; + + return r >= 0; +} diff --git a/libgcc/config/pru/gef.c b/libgcc/config/pru/gef.c new file mode 100644 index 00000000000..042786a459d --- /dev/null +++ b/libgcc/config/pru/gef.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a >= b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_gef(SFtype a, SFtype b) +{ + FP_DECL_EX; + FP_DECL_S(A); FP_DECL_S(B); + CMPtype r; + + FP_UNPACK_RAW_S(A, a); + FP_UNPACK_RAW_S(B, b); + FP_CMP_S(r, A, B, -2, 2); + FP_HANDLE_EXCEPTIONS; + + return r >= 0; +} diff --git a/libgcc/config/pru/gtd.c b/libgcc/config/pru/gtd.c new file mode 100644 index 00000000000..3f536254dde --- /dev/null +++ b/libgcc/config/pru/gtd.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a > b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_gtd(DFtype a, DFtype b) +{ + FP_DECL_EX; + FP_DECL_D(A); FP_DECL_D(B); + CMPtype r; + + FP_UNPACK_RAW_D(A, a); + FP_UNPACK_RAW_D(B, b); + FP_CMP_D(r, A, B, -2, 2); + FP_HANDLE_EXCEPTIONS; + + return r > 0; +} diff --git a/libgcc/config/pru/gtf.c b/libgcc/config/pru/gtf.c new file mode 100644 index 00000000000..ae5b734fbbb --- /dev/null +++ b/libgcc/config/pru/gtf.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a > b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_gtf(SFtype a, SFtype b) +{ + FP_DECL_EX; + FP_DECL_S(A); FP_DECL_S(B); + CMPtype r; + + FP_UNPACK_RAW_S(A, a); + FP_UNPACK_RAW_S(B, b); + FP_CMP_S(r, A, B, -2, 2); + FP_HANDLE_EXCEPTIONS; + + return r > 0; +} diff --git a/libgcc/config/pru/led.c b/libgcc/config/pru/led.c new file mode 100644 index 00000000000..d7d1a51ddc3 --- /dev/null +++ b/libgcc/config/pru/led.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a <= b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_led(DFtype a, DFtype b) +{ + FP_DECL_EX; + FP_DECL_D(A); FP_DECL_D(B); + CMPtype r; + + FP_UNPACK_RAW_D(A, a); + FP_UNPACK_RAW_D(B, b); + FP_CMP_D(r, A, B, 2, 2); + FP_HANDLE_EXCEPTIONS; + + return r <= 0; +} diff --git a/libgcc/config/pru/lef.c b/libgcc/config/pru/lef.c new file mode 100644 index 00000000000..b50e624f62f --- /dev/null +++ b/libgcc/config/pru/lef.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a <= b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_lef(SFtype a, SFtype b) +{ + FP_DECL_EX; + FP_DECL_S(A); FP_DECL_S(B); + CMPtype r; + + FP_UNPACK_RAW_S(A, a); + FP_UNPACK_RAW_S(B, b); + FP_CMP_S(r, A, B, 2, 2); + FP_HANDLE_EXCEPTIONS; + + return r <= 0; +} diff --git a/libgcc/config/pru/lib2bitcountHI.c b/libgcc/config/pru/lib2bitcountHI.c new file mode 100644 index 00000000000..7f07069152a --- /dev/null +++ b/libgcc/config/pru/lib2bitcountHI.c @@ -0,0 +1,43 @@ +/* libgcc routines for PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Based on lib2bitcountHI.c from MSP430 port. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +typedef int sint32_type __attribute__ ((mode (SI))); +typedef unsigned int uint32_type __attribute__ ((mode (SI))); +typedef int sint16_type __attribute__ ((mode (HI))); +typedef unsigned int uint16_type __attribute__ ((mode (HI))); +typedef int sint08_type __attribute__ ((mode (QI))); +typedef unsigned int uint08_type __attribute__ ((mode (QI))); +typedef int word_type __attribute__ ((mode (__word__))); + +#define C3B(a,b,c) a##b##c +#define C3(a,b,c) C3B(a,b,c) + +#define L_clzsi2 +#define L_ctzsi2 +#define L_ffssi2 +#define L_paritysi2 +#define L_popcountsi2 + +#include "libgcc2.c" diff --git a/libgcc/config/pru/lib2divHI.c b/libgcc/config/pru/lib2divHI.c new file mode 100644 index 00000000000..ae99db718f0 --- /dev/null +++ b/libgcc/config/pru/lib2divHI.c @@ -0,0 +1,42 @@ +/* HI mode divide routines for libgcc for PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Based on lib2divHI.c from MSP430 port. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +typedef int sint32_type __attribute__ ((mode (SI))); +typedef unsigned int uint32_type __attribute__ ((mode (SI))); +typedef int sint16_type __attribute__ ((mode (HI))); +typedef unsigned int uint16_type __attribute__ ((mode (HI))); +typedef int sint08_type __attribute__ ((mode (QI))); +typedef unsigned int uint08_type __attribute__ ((mode (QI))); +typedef int word_type __attribute__ ((mode (__word__))); + +#define C3B(a,b,c) a##b##c +#define C3(a,b,c) C3B(a,b,c) + +#define UINT_TYPE uint16_type +#define SINT_TYPE sint16_type +#define BITS_MINUS_1 15 +#define NAME_MODE hi + +#include "pru-divmod.h" diff --git a/libgcc/config/pru/lib2divQI.c b/libgcc/config/pru/lib2divQI.c new file mode 100644 index 00000000000..b271d483dcb --- /dev/null +++ b/libgcc/config/pru/lib2divQI.c @@ -0,0 +1,42 @@ +/* QI mode divide routines for libgcc for PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Based on lib2divQI.c from MSP430 port. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +typedef int sint32_type __attribute__ ((mode (SI))); +typedef unsigned int uint32_type __attribute__ ((mode (SI))); +typedef int sint16_type __attribute__ ((mode (HI))); +typedef unsigned int uint16_type __attribute__ ((mode (HI))); +typedef int sint08_type __attribute__ ((mode (QI))); +typedef unsigned int uint08_type __attribute__ ((mode (QI))); +typedef int word_type __attribute__ ((mode (__word__))); + +#define C3B(a,b,c) a##b##c +#define C3(a,b,c) C3B(a,b,c) + +#define UINT_TYPE uint08_type +#define SINT_TYPE sint08_type +#define BITS_MINUS_1 7 +#define NAME_MODE qi + +#include "pru-divmod.h" diff --git a/libgcc/config/pru/lib2divSI.c b/libgcc/config/pru/lib2divSI.c new file mode 100644 index 00000000000..6b49649a62d --- /dev/null +++ b/libgcc/config/pru/lib2divSI.c @@ -0,0 +1,48 @@ +/* SI mode divide routines for libgcc for PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Based on lib2divSI.c from MSP430 port. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +typedef int sint32_type __attribute__ ((mode (SI))); +typedef unsigned int uint32_type __attribute__ ((mode (SI))); +typedef int sint16_type __attribute__ ((mode (HI))); +typedef unsigned int uint16_type __attribute__ ((mode (HI))); +typedef int sint08_type __attribute__ ((mode (QI))); +typedef unsigned int uint08_type __attribute__ ((mode (QI))); +typedef int word_type __attribute__ ((mode (__word__))); + +#define C3B(a,b,c) a##b##c +#define C3(a,b,c) C3B(a,b,c) + +/* PRU ABI dictates the library function names. */ +#define __gnu_divsi3 __pruabi_divi +#define __gnu_modsi3 __pruabi_remi +#define __gnu_udivsi3 __pruabi_divu +#define __gnu_umodsi3 __pruabi_remu + +#define UINT_TYPE uint32_type +#define SINT_TYPE sint32_type +#define BITS_MINUS_1 31 +#define NAME_MODE si + +#include "pru-divmod.h" diff --git a/libgcc/config/pru/libgcc-eabi.ver b/libgcc/config/pru/libgcc-eabi.ver new file mode 100644 index 00000000000..969d35fe18c --- /dev/null +++ b/libgcc/config/pru/libgcc-eabi.ver @@ -0,0 +1,88 @@ +# Copyright (C) 2017-2018 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +GCC_9.0.0 { + __pruabi_asri + __pruabi_asrll + __pruabi_mpyll + __pruabi_negll + __pruabi_lslll + __pruabi_lsrll + __pruabi_fixfu + __pruabi_fixdu + __pruabi_fixflli + __pruabi_fixdlli + __pruabi_fixfull + __pruabi_fixdull + __pruabi_fltllif + __pruabi_fltllid + __pruabi_fltullf + __pruabi_fltulld + __pruabi_divlli + __pruabi_remlli + __pruabi_divull + __pruabi_remull + __pruabi_divremull + __pruabi_gef + __pruabi_gtf + __pruabi_lef + __pruabi_ltf + __pruabi_eqf + __pruabi_ged + __pruabi_gtd + __pruabi_led + __pruabi_ltd + __pruabi_eqd + __pruabi_addf + __pruabi_divf + __pruabi_neqf + __pruabi_cmpf + __pruabi_mpyf + __pruabi_negf + __pruabi_subf + __pruabi_unordf + __pruabi_fixfi + __pruabi_fltif + __pruabi_fltuf + __pruabi_addd + __pruabi_divd + __pruabi_neqd + __pruabi_cmpd + __pruabi_mpyd + __pruabi_negd + __pruabi_subd + __pruabi_unordd + __pruabi_fixdi + __pruabi_fltid + __pruabi_fltud + __pruabi_cvtfd + __pruabi_cvtdf + __pruabi_mulcf + __pruabi_mulcd + __pruabi_divcf + __pruabi_divcd + + __gnu_ltsf2 + __gnu_ltdf2 + __gnu_gesf2 + __gnu_gedf2 + __gnu_gtsf2 + __gnu_gtdf2 + __gnu_eqsf2 + __gnu_eqdf2 +} diff --git a/libgcc/config/pru/ltd.c b/libgcc/config/pru/ltd.c new file mode 100644 index 00000000000..7be20686e1a --- /dev/null +++ b/libgcc/config/pru/ltd.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a < b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_ltd(DFtype a, DFtype b) +{ + FP_DECL_EX; + FP_DECL_D(A); FP_DECL_D(B); + CMPtype r; + + FP_UNPACK_RAW_D(A, a); + FP_UNPACK_RAW_D(B, b); + FP_CMP_D(r, A, B, 2, 2); + FP_HANDLE_EXCEPTIONS; + + return r < 0; +} diff --git a/libgcc/config/pru/ltf.c b/libgcc/config/pru/ltf.c new file mode 100644 index 00000000000..7b81dbd2ca1 --- /dev/null +++ b/libgcc/config/pru/ltf.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return 1 iff a < b, 0 otherwise. + Copyright (C) 1997-2018 Free Software Foundation, Inc. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + This file is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#include +#include + +CMPtype __pruabi_ltf(SFtype a, SFtype b) +{ + FP_DECL_EX; + FP_DECL_S(A); FP_DECL_S(B); + CMPtype r; + + FP_UNPACK_RAW_S(A, a); + FP_UNPACK_RAW_S(B, b); + FP_CMP_S(r, A, B, 2, 2); + FP_HANDLE_EXCEPTIONS; + + return r < 0; +} diff --git a/libgcc/config/pru/mpyll.S b/libgcc/config/pru/mpyll.S new file mode 100644 index 00000000000..d384b54515a --- /dev/null +++ b/libgcc/config/pru/mpyll.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2014-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . + + (al + C * ah) * (bl + C * bh) = al * bl + + C * ah * bl + + C * al * bh + + C * C * ah * bh -> discard, overflow + Where C=(1 << 32) + */ + +#include "pru-asm.h" + + .global SYM(__pruabi_mpyll) + FUNC(__pruabi_mpyll) +SYM(__pruabi_mpyll): + /* + C * ah * bl */ + mov r28, r15 + mov r29, r16 + nop + xin 0, r26, 8 + + /* + C * al * bh */ + mov r28, r14 + mov r29, r17 + mov r15, r26 /* "Loose" ah, record only reslo. */ + xin 0, r26, 8 + + /* + al * bl */ + /* mov r28, r14 -> No need, already loaded. */ + mov r29, r16 + add r15, r15, r26 + xin 0, r26, 8 + mov r14, r26 + add r15, r15, r27 + + ret + + ENDFUNC(__pruabi_mpyll) diff --git a/libgcc/config/pru/pru-abi.h b/libgcc/config/pru/pru-abi.h new file mode 100644 index 00000000000..79d7be76a5d --- /dev/null +++ b/libgcc/config/pru/pru-abi.h @@ -0,0 +1,109 @@ +/* Header file for PRU ABI versions of libgcc functions. + Copyright (C) 2011-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + Based on c6x/c6x-abi.h + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +/* Make __pruabi_AEABI_NAME an alias for __GCC_NAME. */ +#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) \ + __asm__ (".globl\t__pruabi_" #AEABI_NAME "\n" \ + ".set\t__pruabi_" #AEABI_NAME \ + ", __gnu_" #GCC_NAME "\n"); + +/* Rename helper functions to the names specified in the PRU ELF ABI. */ +#ifdef L_divsi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (divsi3, divi) +#endif +#ifdef L_divdi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (divdi3, divlli) +#endif +#ifdef L_udivsi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (udivsi3, divu) +#endif +#ifdef L_udivdi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (udivdi3, divull) +#endif +#ifdef L_udivmoddi4 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (udivmoddi4, divremull) +#endif +#ifdef L_modsi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (modsi3, remi) +#endif +#ifdef L_moddi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (moddi3, remlli) +#endif +#ifdef L_umodsi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (umodsi3, remu) +#endif +#ifdef L_umoddi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (umoddi3, remull) +#endif +#ifdef L_negdi2 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (negdi2, negll) +#endif +#ifdef L_muldi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, mpyll) +#endif +#ifdef L_ashrdi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashrdi3, asrll) +#endif +#ifdef L_lshrdi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (lshrdi3, lsrll) +#endif +#ifdef L_ashldi3 +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashldi3, lslll) +#endif + +/* The following are excluded from softfp due to softfp_exclude_libgcc2, + so we rename them here rather than in sfp-machine.h. */ +#ifdef L_fixdfdi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, fixdlli) +#endif +#ifdef L_fixunsdfsi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfsi, fixdu) +#endif +#ifdef L_fixunsdfdi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, fixdull) +#endif +#ifdef L_fixsfdi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, fixflli) +#endif +#ifdef L_fixunssfsi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfsi, fixfu) +#endif +#ifdef L_fixunssfdi +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, fixfull) +#endif +#ifdef L_floatdidf +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, fltllid) +#endif +#ifdef L_floatundidf +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatundidf, fltulld) +#endif +#ifdef L_floatdisf +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, fltllif) +#endif +#ifdef L_floatundisf +#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatundisf, fltullf) +#endif + +#define LIBGCC2_GNU_PREFIX diff --git a/libgcc/config/pru/pru-asm.h b/libgcc/config/pru/pru-asm.h new file mode 100644 index 00000000000..28272a13937 --- /dev/null +++ b/libgcc/config/pru/pru-asm.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2014-2018 Free Software Foundation, Inc. + Contributed by Dimitar Dimitrov + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3, or (at your option) any + later version. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +#define FUNC(X) .type SYM(X),@function +#define HIDDEN_FUNC(X) FUNC(X)` .hidden SYM(X) +#define ENDFUNC0(X) CONCAT1(.Lfe_,X): .size X,CONCAT1(.Lfe_,X)-X +#define ENDFUNC(X) ENDFUNC0(SYM(X)) diff --git a/libgcc/config/pru/pru-divmod.h b/libgcc/config/pru/pru-divmod.h new file mode 100644 index 00000000000..40577eaa956 --- /dev/null +++ b/libgcc/config/pru/pru-divmod.h @@ -0,0 +1,117 @@ +/* libgcc routines for PRU + Copyright (C) 2014-2018 Free Software Foundation, Inc. + Based on msp430-divmod.h from MSP430 port. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + . */ + +UINT_TYPE C3(udivmod,NAME_MODE,4) (UINT_TYPE, UINT_TYPE, word_type); +SINT_TYPE C3(__gnu_div,NAME_MODE,3) (SINT_TYPE, SINT_TYPE); +SINT_TYPE C3(__gnu_mod,NAME_MODE,3) (SINT_TYPE, SINT_TYPE); +UINT_TYPE C3(__gnu_udiv,NAME_MODE,3) (UINT_TYPE, UINT_TYPE); +UINT_TYPE C3(__gnu_umod,NAME_MODE,3) (UINT_TYPE, UINT_TYPE); + +UINT_TYPE +C3(udivmod,NAME_MODE,4) (UINT_TYPE num, UINT_TYPE den, word_type modwanted) +{ + UINT_TYPE bit = 1; + UINT_TYPE res = 0; + + while (den < num && bit && !(den & (1L << BITS_MINUS_1))) + { + den <<= 1; + bit <<= 1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>= 1; + den >>= 1; + } + if (modwanted) + return num; + return res; +} + +SINT_TYPE +C3(__gnu_div,NAME_MODE,3) (SINT_TYPE a, SINT_TYPE b) +{ + word_type neg = 0; + SINT_TYPE res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = C3(udivmod,NAME_MODE,4) (a, b, 0); + + if (neg) + res = -res; + + return res; +} + +SINT_TYPE +C3(__gnu_mod,NAME_MODE,3) (SINT_TYPE a, SINT_TYPE b) +{ + word_type neg = 0; + SINT_TYPE res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = C3(udivmod,NAME_MODE,4) (a, b, 1); + + if (neg) + res = -res; + + return res; +} + +UINT_TYPE +C3(__gnu_udiv,NAME_MODE,3) (UINT_TYPE a, UINT_TYPE b) +{ + return C3(udivmod,NAME_MODE,4) (a, b, 0); +} + +UINT_TYPE +C3(__gnu_umod,NAME_MODE,3) (UINT_TYPE a, UINT_TYPE b) +{ + return C3(udivmod,NAME_MODE,4) (a, b, 1); +} diff --git a/libgcc/config/pru/sfp-machine.h b/libgcc/config/pru/sfp-machine.h new file mode 100644 index 00000000000..0079823d425 --- /dev/null +++ b/libgcc/config/pru/sfp-machine.h @@ -0,0 +1,125 @@ +/* Soft-FP definitions for TI PRU. + Copyright (C) 2010-2018 Free Software Foundation, Inc. + Based on C6X soft-fp header. + + This files is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with GCC; see the file COPYING.LIB. If not see + . */ + +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_H ((_FP_QNANBIT_H << 1) - 1) +#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANSIGN_H 0 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + +/* Someone please check this. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \ + && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#if defined _BIG_ENDIAN +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* Not checked. */ +#define _FP_TININESS_AFTER_ROUNDING 0 + + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +/* Rename helper functions to the names specified in the PRU ELF ABI. */ +#define __fixdfsi __pruabi_fixdi +#define __fixsfsi __pruabi_fixfi +#define __floatsidf __pruabi_fltid +#define __floatunsidf __pruabi_fltud +#define __floatsisf __pruabi_fltif +#define __floatunsisf __pruabi_fltuf +#define __truncdfsf2 __pruabi_cvtdf +#define __extendsfdf2 __pruabi_cvtfd +#define __adddf3 __pruabi_addd +#define __subdf3 __pruabi_subd +#define __muldf3 __pruabi_mpyd +#define __divdf3 __pruabi_divd +#define __negdf2 __pruabi_negd +#define __absdf2 __pruabi_absd +#define __addsf3 __pruabi_addf +#define __subsf3 __pruabi_subf +#define __mulsf3 __pruabi_mpyf +#define __divsf3 __pruabi_divf +#define __negsf2 __pruabi_negf +#define __abssf2 __pruabi_absf +#define __lesf2 __pruabi_cmpf +#define __ledf2 __pruabi_cmpd +#define __ltsf2 __gnu_ltsf2 +#define __ltdf2 __gnu_ltdf2 +#define __gesf2 __gnu_gesf2 +#define __gedf2 __gnu_gedf2 +#define __gtsf2 __gnu_gtsf2 +#define __gtdf2 __gnu_gtdf2 +#define __eqsf2 __gnu_eqsf2 +#define __eqdf2 __gnu_eqdf2 +#define __nesf2 __pruabi_neqf +#define __nedf2 __pruabi_neqd +#define __unordsf2 __pruabi_unordf +#define __unorddf2 __pruabi_unordd diff --git a/libgcc/config/pru/t-pru b/libgcc/config/pru/t-pru new file mode 100644 index 00000000000..35ae44f719b --- /dev/null +++ b/libgcc/config/pru/t-pru @@ -0,0 +1,50 @@ +# Makefile fragment for building LIBGCC for the TI PRU processor. +# Copyright (C) 2014-2018 Free Software Foundation, Inc. +# Contributed by Dimitar Dimitrov +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GCC is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with GCC; see the file COPYING3. If not see +# . + +# Note - we have separate versions of the lib2div files +# as the functions are quite large and we do not want to pull +# in unneeded division routines. + +LIB2ADD += \ + $(srcdir)/config/pru/lib2divQI.c \ + $(srcdir)/config/pru/lib2divHI.c \ + $(srcdir)/config/pru/lib2divSI.c \ + $(srcdir)/config/pru/lib2bitcountHI.c \ + $(srcdir)/config/pru/mpyll.S \ + $(srcdir)/config/pru/gef.c \ + $(srcdir)/config/pru/gtf.c \ + $(srcdir)/config/pru/lef.c \ + $(srcdir)/config/pru/ltf.c \ + $(srcdir)/config/pru/eqf.c \ + $(srcdir)/config/pru/ged.c \ + $(srcdir)/config/pru/gtd.c \ + $(srcdir)/config/pru/led.c \ + $(srcdir)/config/pru/ltd.c \ + $(srcdir)/config/pru/eqd.c \ + $(srcdir)/config/pru/asri.c + +HOST_LIBGCC2_CFLAGS += -Os -ffunction-sections -fdata-sections + +LIB2FUNCS_EXCLUDE = _muldi3 + +SHLIB_MAPFILES += $(srcdir)/config/pru/libgcc-eabi.ver +# Local Variables: +# mode: Makefile +# End: From patchwork Thu Aug 16 04:49:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958098 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-483760-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="F623r4CC"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="Na6af7eO"; 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 41rYpn4JBQz9s4v for ; Thu, 16 Aug 2018 14:52:17 +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:in-reply-to:references; q=dns; s= default; b=VDfxdx5BtpaHqsblMxTs9q3mGkKyjQNSyAjwnhPOXVXFbVy7G8GKP tbKCnNVWzRsyq+lv3EBpczWBJ5lI2wLqgY8ikAKrC8aKBKbKF1qC5/qZxjyRLt3K Olx19o2b2Dv4ZfvTPGZAswrWgxWJEofFepQKtN388JOXZ9w+RkGxo4= 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:in-reply-to:references; s= default; bh=XPfbxh0tq4llGeQRUwh1k33ZbiY=; b=F623r4CCP3Ey/L4CeD4J 0aVNPrEwtHbXEco4M2MR+u6HcQ9dYXXuK/qOahrmouxcaARWQqPvVxOmC+0Sy4pP WviShl2NGAxaqXe7GiWC62zq6rtOnHhJ5Re4H9tbuHOpWIaZSunz9sq/rxF/ggqE JVxYK80JthowogY7Vf3A5tE= Received: (qmail 100004 invoked by alias); 16 Aug 2018 04:50:52 -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 99075 invoked by uid 89); 16 Aug 2018 04:50:38 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, SPF_PASS autolearn=ham version=3.3.2 spammy=bodies, UD:L, 1001, UD:r X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:28 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEr-0004cU-46 for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:25 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=VlaO8ruhJnE3V27yhSqr2HF9pttN0STmCA6KwVlgRek=; b=Na6af7eOS38KK/t/Y0FtDKGHtT GAb51Ik8VFm3OOGGbdf4fKlS0m7j3C0VLYfq73hsoMTh/me2tQD9Up3CreC5ffae3ey59IM6OoZbe 5D9ynVqrGZruhegg07bQueGV3x43QcEKhJoo1eiEv+XSJrtM6yiyTRDonHHJOnh3Tp+UfNxuLNuwl NB18gFpH9/o2XZQ2P/1yDFgiAl9jf/Bgaw3WAr3VlANTQXNJ6B9i1WKv4SReMaPUIedddRetuugzL iig17eTzwXc/bGX+BmBPFigVh3qbIOHQtzS8KV5jY+zUEp51Mk50QTMuETccTlU2YV1UY2x+c9kzZ mpSeOUWQ==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEn-0004j3-8J; Thu, 16 Aug 2018 07:50:24 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 03/10] testsuite: Add PRU tests Date: Thu, 16 Aug 2018 07:49:52 +0300 Message-Id: <20180816044959.12320-4-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-IsSubscribed: yes gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * gcc.target/pru/abi-arg-struct.c: New test. * gcc.target/pru/ashiftrt.c: New test. * gcc.target/pru/builtins-1.c: New test. * gcc.target/pru/builtins-error.c: New test. * gcc.target/pru/clearbit.c: New test. * gcc.target/pru/loop-asm.c: New test. * gcc.target/pru/loop-dowhile.c: New test. * gcc.target/pru/loop-hi-1.c: New test. * gcc.target/pru/loop-hi-2.c: New test. * gcc.target/pru/loop-qi-1.c: New test. * gcc.target/pru/loop-qi-2.c: New test. * gcc.target/pru/loop-short-1.c: New test. * gcc.target/pru/loop-short-2.c: New test. * gcc.target/pru/loop-si-1.c: New test. * gcc.target/pru/loop-si-2.c: New test. * gcc.target/pru/loop-u8_pcrel_overflow.c: New test. * gcc.target/pru/loop-ubyte-1.c: New test. * gcc.target/pru/loop-ubyte-2.c: New test. * gcc.target/pru/lra-framepointer-fragmentation-1.c: New test. * gcc.target/pru/lra-framepointer-fragmentation-2.c: New test. * gcc.target/pru/mabi-ti-1.c: New test. * gcc.target/pru/mabi-ti-2.c: New test. * gcc.target/pru/mabi-ti-3.c: New test. * gcc.target/pru/mabi-ti-4.c: New test. * gcc.target/pru/mabi-ti-5.c: New test. * gcc.target/pru/mabi-ti-6.c: New test. * gcc.target/pru/mabi-ti-7.c: New test. * gcc.target/pru/pr64366.c: New test. * gcc.target/pru/pragma-ctable_entry.c: New test. * gcc.target/pru/pru.exp: New file. * gcc.target/pru/qbbc-1.c: New test. * gcc.target/pru/qbbc-2.c: New test. * gcc.target/pru/qbbc-3.c: New test. * gcc.target/pru/qbbs-1.c: New test. * gcc.target/pru/qbbs-2.c: New test. * gcc.target/pru/setbit.c: New test. * gcc.target/pru/zero_extend-and-hisi.c: New test. * gcc.target/pru/zero_extend-and-qihi.c: New test. * gcc.target/pru/zero_extend-and-qisi.c: New test. * gcc.target/pru/zero_extend-hisi.c: New test. * gcc.target/pru/zero_extend-qihi.c: New test. * gcc.target/pru/zero_extend-qisi.c: New test. * lib/target-supports.exp: Add PRU to feature filters. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/gcc.target/pru/abi-arg-struct.c | 164 +++++++++++++++++++++ gcc/testsuite/gcc.target/pru/ashiftrt.c | 13 ++ gcc/testsuite/gcc.target/pru/builtins-1.c | 12 ++ gcc/testsuite/gcc.target/pru/builtins-error.c | 6 + gcc/testsuite/gcc.target/pru/clearbit.c | 13 ++ gcc/testsuite/gcc.target/pru/loop-asm.c | 19 +++ gcc/testsuite/gcc.target/pru/loop-dowhile.c | 45 ++++++ gcc/testsuite/gcc.target/pru/loop-hi-1.c | 38 +++++ gcc/testsuite/gcc.target/pru/loop-hi-2.c | 17 +++ gcc/testsuite/gcc.target/pru/loop-qi-1.c | 38 +++++ gcc/testsuite/gcc.target/pru/loop-qi-2.c | 17 +++ gcc/testsuite/gcc.target/pru/loop-short-1.c | 53 +++++++ gcc/testsuite/gcc.target/pru/loop-short-2.c | 21 +++ gcc/testsuite/gcc.target/pru/loop-si-1.c | 41 ++++++ gcc/testsuite/gcc.target/pru/loop-si-2.c | 20 +++ .../gcc.target/pru/loop-u8_pcrel_overflow.c | 42 ++++++ gcc/testsuite/gcc.target/pru/loop-ubyte-1.c | 30 ++++ gcc/testsuite/gcc.target/pru/loop-ubyte-2.c | 18 +++ .../pru/lra-framepointer-fragmentation-1.c | 33 +++++ .../pru/lra-framepointer-fragmentation-2.c | 61 ++++++++ gcc/testsuite/gcc.target/pru/mabi-ti-1.c | 10 ++ gcc/testsuite/gcc.target/pru/mabi-ti-2.c | 15 ++ gcc/testsuite/gcc.target/pru/mabi-ti-3.c | 12 ++ gcc/testsuite/gcc.target/pru/mabi-ti-4.c | 14 ++ gcc/testsuite/gcc.target/pru/mabi-ti-5.c | 33 +++++ gcc/testsuite/gcc.target/pru/mabi-ti-6.c | 12 ++ gcc/testsuite/gcc.target/pru/mabi-ti-7.c | 21 +++ gcc/testsuite/gcc.target/pru/pr64366.c | 128 ++++++++++++++++ gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c | 22 +++ gcc/testsuite/gcc.target/pru/pru.exp | 41 ++++++ gcc/testsuite/gcc.target/pru/qbbc-1.c | 29 ++++ gcc/testsuite/gcc.target/pru/qbbc-2.c | 15 ++ gcc/testsuite/gcc.target/pru/qbbc-3.c | 15 ++ gcc/testsuite/gcc.target/pru/qbbs-1.c | 29 ++++ gcc/testsuite/gcc.target/pru/qbbs-2.c | 15 ++ gcc/testsuite/gcc.target/pru/setbit.c | 13 ++ .../gcc.target/pru/zero_extend-and-hisi.c | 16 ++ .../gcc.target/pru/zero_extend-and-qihi.c | 16 ++ .../gcc.target/pru/zero_extend-and-qisi.c | 16 ++ gcc/testsuite/gcc.target/pru/zero_extend-hisi.c | 43 ++++++ gcc/testsuite/gcc.target/pru/zero_extend-qihi.c | 43 ++++++ gcc/testsuite/gcc.target/pru/zero_extend-qisi.c | 43 ++++++ gcc/testsuite/lib/target-supports.exp | 7 +- 43 files changed, 1307 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/pru/abi-arg-struct.c create mode 100644 gcc/testsuite/gcc.target/pru/ashiftrt.c create mode 100644 gcc/testsuite/gcc.target/pru/builtins-1.c create mode 100644 gcc/testsuite/gcc.target/pru/builtins-error.c create mode 100644 gcc/testsuite/gcc.target/pru/clearbit.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-asm.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-dowhile.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-hi-1.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-hi-2.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-qi-1.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-qi-2.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-short-1.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-short-2.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-si-1.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-si-2.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-ubyte-1.c create mode 100644 gcc/testsuite/gcc.target/pru/loop-ubyte-2.c create mode 100644 gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c create mode 100644 gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-1.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-2.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-3.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-4.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-5.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-6.c create mode 100644 gcc/testsuite/gcc.target/pru/mabi-ti-7.c create mode 100644 gcc/testsuite/gcc.target/pru/pr64366.c create mode 100644 gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c create mode 100644 gcc/testsuite/gcc.target/pru/pru.exp create mode 100644 gcc/testsuite/gcc.target/pru/qbbc-1.c create mode 100644 gcc/testsuite/gcc.target/pru/qbbc-2.c create mode 100644 gcc/testsuite/gcc.target/pru/qbbc-3.c create mode 100644 gcc/testsuite/gcc.target/pru/qbbs-1.c create mode 100644 gcc/testsuite/gcc.target/pru/qbbs-2.c create mode 100644 gcc/testsuite/gcc.target/pru/setbit.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-hisi.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-qihi.c create mode 100644 gcc/testsuite/gcc.target/pru/zero_extend-qisi.c diff --git a/gcc/testsuite/gcc.target/pru/abi-arg-struct.c b/gcc/testsuite/gcc.target/pru/abi-arg-struct.c new file mode 100644 index 00000000000..186074b16f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/abi-arg-struct.c @@ -0,0 +1,164 @@ +/* Test call argument ABI: passing structs */ + +/* { dg-do run } */ + +#include + +extern void abort (void); + +struct S3 { char a[3]; }; +struct S7 { char a[7]; }; +struct S8 { char a[8]; }; + +struct S3 gs3 = {{11, 22, 33}}; +struct S7 gs7 = {{1, 2, 3, 4, 5, 6, 7}}; +struct S8 gs8 = {{1, 2, 3, 4, 5, 6, 7, 8}}; + +int test3_struct(char a0, char a1, char a2, char a3, + char a4, char a5, char a6, char a7, + char a8, char a9, char a10, char a11, + int ai) +{ + if (a0 != 11) return 1; + if (a1 != 22) return 2; + if (a2 != 33) return 3; + if (a4 != 101) return 4; + if (a5 != 111) return 5; + if (a6 != 121) return 6; + if (a8 != 55) return 8; + if (a9 != 66) return 9; + if (a10 != 77) return 10; + + if (ai != 55443322) return 100; + + return 0; +} + +void test3(void) +{ + struct S3 s3x = { {101, 111, 121} }; + struct S3 s3y = { {55, 66, 77} }; + + int (* volatile f)(struct S3, struct S3, struct S3, int) = + (int (* volatile)(struct S3, struct S3, struct S3, int)) test3_struct; + + if (f(gs3, s3x, s3y, 55443322)) + abort(); +} + +int test7_struct(unsigned ai, struct S7 a0, ...) +{ + va_list ap; + struct S7 s[3]; + int i; + + va_start (ap, a0); + + s[0] = a0; + for (i = 1; i < 3; i++) { + s[i] = va_arg (ap, struct S7); + } + + va_end (ap); + + if (ai != 0xaabbccdd) + return 1; + + if (s[0].a[0] != 1) return 1; + if (s[0].a[1] != 2) return 1; + if (s[0].a[2] != 3) return 1; + if (s[0].a[3] != 4) return 1; + if (s[0].a[4] != 5) return 1; + if (s[0].a[5] != 6) return 1; + if (s[0].a[6] != 7) return 1; + + if (s[1].a[0] != 11) return 1; + if (s[1].a[1] != 12) return 1; + if (s[1].a[2] != 13) return 1; + if (s[1].a[3] != 14) return 1; + if (s[1].a[4] != 15) return 1; + if (s[1].a[5] != 16) return 1; + if (s[1].a[6] != 17) return 1; + + if (s[2].a[0] != 22) return 1; + if (s[2].a[1] != 23) return 1; + if (s[2].a[2] != 24) return 1; + if (s[2].a[3] != 25) return 1; + if (s[2].a[4] != 26) return 1; + if (s[2].a[5] != 27) return 1; + if (s[2].a[6] != 28) return 1; + + return 0; +} + +void test7(void) +{ + struct S7 s7x = { {11, 12, 13, 14, 15, 16, 17} }; + struct S7 s7y = { {22, 23, 24, 25, 26, 27, 28} }; + + int (* volatile f)(unsigned, struct S7, struct S7, struct S7) = + (int (* volatile)(unsigned, struct S7, struct S7, struct S7)) test7_struct; + + if (f(0xaabbccdd, gs7, s7x, s7y)) + abort(); +} + +int test8_struct(char a0, char a1, char a2, char a3, + char a4, char a5, char a6, char a7, + char a8, char a9, char a10, char a11, + char a12, char a13, char a14, char a15, + char a16, char a17, char a18, char a19, + char a20, char a21, char a22, char a23) +{ + if (a0 != 1) return 1; + if (a1 != 2) return 1; + if (a2 != 3) return 1; + if (a3 != 4) return 1; + if (a4 != 5) return 1; + if (a5 != 6) return 1; + if (a6 != 7) return 1; + if (a7 != 8) return 1; + + if (a8 != 11) return 1; + if (a9 != 12) return 1; + if (a10 != 13) return 1; + if (a11 != 14) return 1; + if (a12 != 15) return 1; + if (a13 != 16) return 1; + if (a14 != 17) return 1; + if (a15 != 18) return 1; + + if (a16 != 22) return 1; + if (a17 != 23) return 1; + if (a18 != 24) return 1; + if (a19 != 25) return 1; + if (a20 != 26) return 1; + if (a21 != 27) return 1; + if (a22 != 28) return 1; + if (a23 != 29) return 1; + + return 0; +} + +void test8(void) +{ + struct S8 s8x = { {11, 12, 13, 14, 15, 16, 17, 18} }; + struct S8 s8y = { {22, 23, 24, 25, 26, 27, 28, 29} }; + + int (* volatile f)(struct S8, struct S8, struct S8) = + (int (* volatile)(struct S8, struct S8, struct S8)) test8_struct; + + if (f(gs8, s8x, s8y)) + abort(); +} + +int +main (int argc, char** argv) +{ + test3(); + test7(); + test8(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/ashiftrt.c b/gcc/testsuite/gcc.target/pru/ashiftrt.c new file mode 100644 index 00000000000..ee8d55d60e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/ashiftrt.c @@ -0,0 +1,13 @@ +/* Test shift optimization */ + +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. */ + +extern void func2(unsigned char); + +void test(unsigned char v) +{ + /* { dg-final { scan-assembler "lsl\tr14.b0, r14.b0, .\+\n\tlsr\tr14.b0, r14.b0" } } */ + func2((v & 2) ? 1 : 0); +} diff --git a/gcc/testsuite/gcc.target/pru/builtins-1.c b/gcc/testsuite/gcc.target/pru/builtins-1.c new file mode 100644 index 00000000000..7b7472bbbd5 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/builtins-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +void delay0 (void) { __delay_cycles (0); } +void delay1 (void) { __delay_cycles (1); } +void delay2 (void) { __delay_cycles (2); } +void delay3 (void) { __delay_cycles (3); } + +void delay_1 (void) { __delay_cycles (44); } +void delay_2 (void) { __delay_cycles (0x1234); } +void delay_3 (void) { __delay_cycles (0x123456); } + +/* { dg-final { scan-assembler-not "__delay_cycles" } } */ diff --git a/gcc/testsuite/gcc.target/pru/builtins-error.c b/gcc/testsuite/gcc.target/pru/builtins-error.c new file mode 100644 index 00000000000..a856872a0a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/builtins-error.c @@ -0,0 +1,6 @@ +/* { dg-do assemble } */ + +void delay (long a) +{ + __delay_cycles (a); /* { dg-error "'__delay_cycles' only takes constant arguments" } */ +} diff --git a/gcc/testsuite/gcc.target/pru/clearbit.c b/gcc/testsuite/gcc.target/pru/clearbit.c new file mode 100644 index 00000000000..cc24b3bb1b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/clearbit.c @@ -0,0 +1,13 @@ +/* clearbit instruction generation */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +unsigned int +test_clearbit (unsigned int val) +{ + /* { dg-final { scan-assembler "clr\\tr14, r14, 19" } } */ + val &= ~(1u << 19); + return val; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-asm.c b/gcc/testsuite/gcc.target/pru/loop-asm.c new file mode 100644 index 00000000000..7b737a09803 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-asm.c @@ -0,0 +1,19 @@ +/* Test that LOOP will not be generated when body contains asm statement */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop (unsigned int n) +{ + unsigned i; + /* { dg-final { scan-assembler-not "loop\t.\+" } } */ + for (i = 0; i < 10; i++) { + n <<= 2; + asm volatile ("nop" : : ); + } + return n; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-dowhile.c b/gcc/testsuite/gcc.target/pru/loop-dowhile.c new file mode 100644 index 00000000000..0926b98a953 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-dowhile.c @@ -0,0 +1,45 @@ +/* Test LOOP generation for do while. + Ensure the post-condition "do while" is correctly translated + to a pre-condition PRU LOOP instruction. */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +volatile unsigned int int_12345 = 12345; +volatile unsigned int int_0 = 0; +volatile unsigned int int_1 = 1; + +unsigned int +test_loop (unsigned int n) +{ + unsigned int i = 0; + volatile unsigned int s = 0; + + if (n >= 0x7fff) return 0; + + do { + s++; + i++; + } while (i < n); + return s; +} + + +int +main (int argc, char** argv) +{ + if (test_loop (int_0) != 1) + abort(); + if (test_loop (int_1) != 1) + abort(); + if (test_loop (int_12345) != 12345) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-hi-1.c b/gcc/testsuite/gcc.target/pru/loop-hi-1.c new file mode 100644 index 00000000000..23caf20f674 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-hi-1.c @@ -0,0 +1,38 @@ +/* Test LOOP recognition - short ints*/ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +volatile unsigned short short_12345 = 12345; +volatile unsigned short short_0 = 0; +volatile unsigned short short_1 = 1; + +unsigned int +test_loop_short (unsigned short n) +{ + unsigned short i; + volatile unsigned int s = 0; + + for (i = 0; i < n; i++) + s++; + return s; +} + +int +main (int argc, char** argv) +{ + if (test_loop_short (short_0) != 0) + abort(); + if (test_loop_short (short_1) != 1) + abort(); + if (test_loop_short (short_12345) != 12345) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-hi-2.c b/gcc/testsuite/gcc.target/pru/loop-hi-2.c new file mode 100644 index 00000000000..0ef4ec76481 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-hi-2.c @@ -0,0 +1,17 @@ +/* Test LOOP recognition - short ints*/ + +/* { dg-options "-O2 -mloop" } */ + +/* -O2 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop_short (int x, short n) +{ + int i; + + /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9w.\]*" } } */ + for (i = 0; i < n; i++) + x <<= 3; + return x; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-qi-1.c b/gcc/testsuite/gcc.target/pru/loop-qi-1.c new file mode 100644 index 00000000000..a4bb7d6d803 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-qi-1.c @@ -0,0 +1,38 @@ +/* Test LOOP recognition */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +volatile unsigned char char_123 = 123; +volatile unsigned char char_0 = 0; +volatile unsigned char char_1 = 1; + +unsigned int +test_loop_char (unsigned char n) +{ + unsigned char i; + volatile unsigned int s = 0; + + for (i = 0; i < n; i++) + s++; + return s; +} + +int +main (int argc, char** argv) +{ + if (test_loop_char (char_0) != 0) + abort(); + if (test_loop_char (char_1) != 1) + abort(); + if (test_loop_char (char_123) != 123) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-qi-2.c b/gcc/testsuite/gcc.target/pru/loop-qi-2.c new file mode 100644 index 00000000000..24a343d579e --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-qi-2.c @@ -0,0 +1,17 @@ +/* Test LOOP recognition */ + +/* { dg-options "-O2 -mloop" } */ + +/* -O2 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop_char (unsigned int x, char n) +{ + int i; + + /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9b.\]*" } } */ + for (i = 0; i < n; i++) + x <<= 2; + return x; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-short-1.c b/gcc/testsuite/gcc.target/pru/loop-short-1.c new file mode 100644 index 00000000000..14d75300301 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-short-1.c @@ -0,0 +1,53 @@ +/* Test LOOP generation for very short loops. */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +volatile unsigned int int_12345 = 12345; +volatile unsigned int int_0 = 0; +volatile unsigned int int_1 = 1; + +unsigned int +test_loop_sum (unsigned int n) +{ + unsigned i; + volatile unsigned int s = 0; + for (i = 0; i < n; i++) { + s++; + } + return s; +} + +unsigned int +test_loop_shift20 (unsigned int n) +{ + unsigned i; + for (i = 0; i < 10; i++) { + n <<= 2; + } + return n; +} + +int +main (int argc, char** argv) +{ + if (test_loop_sum (int_0) != 0) + abort(); + if (test_loop_sum (int_1) != 1) + abort(); + if (test_loop_sum (int_12345) != 12345) + abort(); + + if (test_loop_shift20 (int_0) != 0) + abort(); + if (test_loop_shift20 (int_1) != (1u << 20)) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-short-2.c b/gcc/testsuite/gcc.target/pru/loop-short-2.c new file mode 100644 index 00000000000..b0e1986bad3 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-short-2.c @@ -0,0 +1,21 @@ +/* Test LOOP generation for very short loops. */ + +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop (unsigned int n, unsigned int x) +{ + unsigned int i; + + if (n >= 0x10000) return 0; + if (!n) return 0; + + /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9\]*" } } */ + /* { dg-final { scan-assembler "nop" } } */ + for (i = 0; i < n; i++) + x <<= 2; + return x; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-si-1.c b/gcc/testsuite/gcc.target/pru/loop-si-1.c new file mode 100644 index 00000000000..84087bf7160 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-si-1.c @@ -0,0 +1,41 @@ +/* Test LOOP recognition */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +volatile unsigned int int_12345 = 12345; +volatile unsigned int int_0 = 0; +volatile unsigned int int_1 = 1; + +unsigned int +test_loop (unsigned int n) +{ + unsigned int i; + volatile unsigned int s = 0; + + if (n >= 0x10000) return 0; + + for (i = 0; i < n; i++) + s++; + return s; +} + + +int +main (int argc, char** argv) +{ + if (test_loop (int_0) != 0) + abort(); + if (test_loop (int_1) != 1) + abort(); + if (test_loop (int_12345) != 12345) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-si-2.c b/gcc/testsuite/gcc.target/pru/loop-si-2.c new file mode 100644 index 00000000000..1e8a9d1ff9b --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-si-2.c @@ -0,0 +1,20 @@ +/* Test LOOP recognition */ + +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop (unsigned int n) +{ + unsigned int i; + volatile unsigned int s = 0; + + if (n >= 0x10000) return 0; + + /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9\]*" } } */ + for (i = 0; i < n; i++) + s++; + return s; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c b/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c new file mode 100644 index 00000000000..8ae91c6edb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c @@ -0,0 +1,42 @@ +/* Test large loop bodies where U8_PCREL would overflow */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +#define OP do { i1 <<= 2; i1 >>= 2; i2 *= 3; i2 /= 2; } while(0) +#define OP4 OP; OP; OP; OP +#define OP16 OP4; OP4; OP4; OP4 +#define OP64 OP16; OP16; OP16; OP16 +#define OP256 OP64; OP64; OP64; OP64 + +unsigned int +test_loop (unsigned int i1, unsigned i2) +{ + unsigned int i; + volatile unsigned int s = 0; + + for (i = 0; i < 100; i++) { + /* cannot use ASM NOP because it will prevent + GCC from issuing a LOOP instruction. */ + OP256; + s++; + } + return s + i1 + i2; +} + +volatile unsigned int I1 = 0; +volatile unsigned int I2 = 0; + +int +main (int argc, char** argv) +{ + if (test_loop (I1, I2) != 100) + abort(); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c b/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c new file mode 100644 index 00000000000..8444f81bba7 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c @@ -0,0 +1,30 @@ +/* Test LOOP recognition */ + +/* { dg-do run } */ +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +extern void abort (void); + +unsigned int +test_loop_ubyte_101 (void) +{ + unsigned int i; + volatile unsigned int s = 0; + + for (i = 0; i < 101; i++) + s++; + return s; +} + +int +main (int argc, char** argv) +{ + if (test_loop_ubyte_101 () != 101) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c b/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c new file mode 100644 index 00000000000..058cbb08bda --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c @@ -0,0 +1,18 @@ +/* Test LOOP recognition */ + +/* { dg-options "-O1 -mloop" } */ + +/* -O1 in the options is significant. Without it do-loop will not be + run. */ + +unsigned int +test_loop_ubyte_101 (void) +{ + unsigned int i; + volatile unsigned int s = 0; + + /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, 101" } } */ + for (i = 0; i < 101; i++) + s++; + return s; +} diff --git a/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c new file mode 100644 index 00000000000..ee1288fc2ae --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c @@ -0,0 +1,33 @@ +/* { dg-do assemble } */ +/* { dg-options "-O1 -fno-omit-frame-pointer" } */ +#include + +extern uint64_t global; + +uint64_t __attribute__((noinline)) test(uint64_t a, uint64_t b, + uint64_t c, uint64_t d, + uint64_t e, uint64_t f, + uint64_t g, uint64_t h) +{ + uint64_t l1 = 0x12345678, l2 = 0x87654321, l3 = 1001, l4 = 1002; + uint64_t l5 = 1004; + uint32_t l6 = 2005; + uint8_t c1 = 101, c2 = 102; + + /* The numerous dummy asm input operands create just + * enough register pressure to resort to using + * FP.b1 (r4.b1). + */ + + asm ("nop" /* { dg-error "'asm' operand has impossible constraints" } */ + : "=r" (l1) + : "0" (l1), "r" (a), "r"(b), + "r"(c), "r"(d), "r"(e), "r"(f), + "r"(g), "r"(h), "r"(l2), + "r"(c1), "r"(c2), + "r"(l3), "r"(l4), "r"(l5), "r"(l6)); + + global = a+b+c+d+e+f+g+h + c1+c2 + l2; + + return l1; +} diff --git a/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c new file mode 100644 index 00000000000..6c98e9bf13b --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c @@ -0,0 +1,61 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -fomit-frame-pointer" } */ +#include + +extern void abort (void); + +uint64_t global = 5; + +uint64_t __attribute__((noinline)) test(uint64_t a, uint64_t b, + uint64_t c, uint64_t d, + uint64_t e, uint64_t f, + uint64_t g, uint64_t h) +{ + uint64_t l1 = 0x12345678, l2 = 0x87654321, l3 = 1001, l4 = 1002; + uint64_t l5 = 1004; + uint32_t l6 = 2005; + uint8_t c1 = 101, c2 = 102; + + /* The numerous dummy asm input operands create just + * enough register pressure to resort to using FP (r4). + */ + + asm ("ldi32 %0, 0x11223344\n\t" + "add %0, %0, %2\n\t" + "add %0, %0, %3\n\t" + "add %0, %0, %4\n\t" + "add %0, %0, %5\n\t" + "add %0, %0, %6\n\t" + "add %0, %0, %7\n\t" + "add %0, %0, %8\n\t" + "add %0, %0, %9\n\t" + "add %0, %0, %10\n\t" + "add %0, %0, %11\n\t" + "add %0, %0, %12\n\t" + "add %0, %0, %13\n\t" + "add %0, %0, %14\n\t" + "add %0, %0, %15\n\t" + "add %0, %0, %16\n\t" + : "=r" (l1) + : "0" (l1), "r" (a), "r"(b), + "r"(c), "r"(d), "r"(e), "r"(f), + "r"(g), "r"(h), "r"(c1), "r"(c2), + "r"(l2), "r"(l3), "r"(l4), "r"(l5), "r"(l6)); + + global = a+b+c+d+e+f+g+h + c1+c2 + l2+l3+l4+l5+l6; + + return l1; +} + +int main() +{ + uint64_t a = test(1, 2, 3, 4, 5, 6, 7, 8); + + if (a != 0x98878ae8) { + abort(); + } + if (global != 0x876557a4) { + abort(); + } + return 0; +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-1.c b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c new file mode 100644 index 00000000000..117ae8fd176 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c @@ -0,0 +1,10 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + + +int test(int a, int b, void (*fp)(void)) +{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ + return a+b; +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-2.c b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c new file mode 100644 index 00000000000..d4a3aff546c --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c @@ -0,0 +1,15 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + + +struct big { + char c[9]; +}; + +struct big test(void) +{ /* { dg-error "large return values not supported with '-mabi=ti' option" } */ + static struct big b; + return b; +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-3.c b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c new file mode 100644 index 00000000000..c49f6653589 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c @@ -0,0 +1,12 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + + +extern void extfunc(void (*fp)(void)); + +void test(void) +{ + extfunc(test); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-4.c b/gcc/testsuite/gcc.target/pru/mabi-ti-4.c new file mode 100644 index 00000000000..0110e6ce290 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-4.c @@ -0,0 +1,14 @@ +/* Test TI ABI with supported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + + +extern void extfunc1(long long); +extern long long extfunc2(long long); + +long long test(void) +{ + extfunc1(3); + return extfunc2(1); +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-5.c b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c new file mode 100644 index 00000000000..38eeaa4435d --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c @@ -0,0 +1,33 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + +struct s1 { + void (*f)(void); + int a; +}; + +struct s2 { + union { + void (*f)(void); + int a; + long b; + } u; +}; + +int test1(struct s1 *p) +{ + return p->a; /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ + return 1; +} + +int test1_unused_arg(struct s1 p, int a) +{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ + return a; +} + +int test2(struct s2 v) +{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ + return 2; +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-6.c b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c new file mode 100644 index 00000000000..c8aa018a21e --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c @@ -0,0 +1,12 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + + +extern void (*extfuncp)(int); + +void test(void) +{ + extfuncp(1); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ +} diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-7.c b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c new file mode 100644 index 00000000000..cc095facf64 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c @@ -0,0 +1,21 @@ +/* Test TI ABI unsupported constructs */ + +/* { dg-do assemble } */ +/* { dg-options "-O1 -mabi=ti" } */ + +struct s1 { + int (*f)(void); + int a; +}; + +extern struct s1 s; + +int test1(void) +{ + return s.f(); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ +} + +int test2(void) +{ + return s.a; /* { dg-error "function pointers not supported with '-mabi=ti' option" } */ +} diff --git a/gcc/testsuite/gcc.target/pru/pr64366.c b/gcc/testsuite/gcc.target/pru/pr64366.c new file mode 100644 index 00000000000..1608d469499 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pr64366.c @@ -0,0 +1,128 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef int int8_t __attribute__ ((__mode__ (__QI__))); +typedef int int16_t __attribute__ ((__mode__ (__HI__))); +typedef int int32_t __attribute__ ((__mode__ (__SI__))); +typedef int int64_t __attribute__ ((__mode__ (__DI__))); +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +__extension__ typedef unsigned long long int uint64_t; +typedef int intptr_t; +typedef struct BigStruct{ + uint8_t a; + int8_t b; + uint16_t c; + int16_t d; + uint32_t e; + int32_t f; + uint64_t g; + int64_t h; + float i; + double j; + long double k; + char* l; + uint8_t m; + int8_t n; + uint16_t o; + int16_t p; + uint32_t q; + int32_t r; + uint64_t s; + int64_t t; + float u; + double v; + long double w; + char* x; + uint8_t y; + int8_t z; + uint16_t aa; + int16_t bb; + uint32_t cc; + int32_t dd; + uint64_t ee; + int64_t ff; + float gg; + double hh; + long double ii; + char* jj; + uint8_t kk; + int8_t ll; + uint16_t mm; + int16_t nn; + uint32_t oo; + int32_t pp; + uint64_t qq; + int64_t rr; + float ss; + double tt; + long double uu; + char* vv; + uint8_t ww; + int8_t xx; +} BigStruct; + +extern void foobar(); + +void +test_large_fn (uint8_t ui8_1, int8_t si8_1, uint16_t ui16_1, int16_t si16_1, + uint32_t ui32_1, int32_t si32_1, uint64_t ui64_1, int64_t si64_1, + float f_1, double d_1, long double ld_1, char* p_1, + uint8_t ui8_2, int8_t si8_2, uint16_t ui16_2, int16_t si16_2, + uint32_t ui32_2, int32_t si32_2, uint64_t ui64_2, int64_t si64_2, + float f_2, double d_2, long double ld_2, char* p_2, + uint8_t ui8_3, int8_t si8_3, uint16_t ui16_3, int16_t si16_3, + uint32_t ui32_3, int32_t si32_3, uint64_t ui64_3, int64_t si64_3, + float f_3, double d_3, long double ld_3, char* p_3, + uint8_t ui8_4, int8_t si8_4, uint16_t ui16_4, int16_t si16_4, + uint32_t ui32_4, int32_t si32_4, uint64_t ui64_4, int64_t si64_4, + float f_4, double d_4, long double ld_4, char* p_4, + uint8_t ui8_5, int8_t si8_5) +{ + BigStruct retVal = + { + ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, + ui32_1 + 1, si32_1 + 1, ui64_1 + 1, si64_1 + 1, + f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((intptr_t)p_1 + 1), + ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, + ui32_2 + 2, si32_2 + 2, ui64_2 + 2, si64_2 + 2, + f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((intptr_t)p_2 + 2), + ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, + ui32_3 + 3, si32_3 + 3, ui64_3 + 3, si64_3 + 3, + f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((intptr_t)p_3 + 3), + ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, + ui32_4 + 4, si32_4 + 4, ui64_4 + 4, si64_4 + 4, + f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4), + ui8_5 + 5, si8_5 + 5 + }; + + foobar ("%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d" + " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %" + "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx " "%" "u" + " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d" + " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %" + "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx %" "u" " %" + "d" ": " "%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %" + "ll" "d" " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" + " %hu %hd %u %d %" "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx " + "%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d" + " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %" + "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx %" "u" " %" "d" "\n", + ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, + f_1, d_1, ld_1, (unsigned long)p_1, ui8_2, si8_2, ui16_2, si16_2, + ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2, + ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, + d_3, ld_3, (unsigned long)p_3, ui8_4, si8_4, ui16_4, si16_4, ui32_4, + si32_4, ui64_4, si64_4, f_4, d_4, ld_4, (unsigned long)p_4, ui8_5, + si8_5, retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f, + retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, + (unsigned long)retVal.l, retVal.m, retVal.n, retVal.o, retVal.p, + retVal.q, retVal.r, retVal.s, retVal.t, retVal.u, retVal.v, + retVal.w, (unsigned long)retVal.x, retVal.y, retVal.z, retVal.aa, + retVal.bb, retVal.cc, retVal.dd, retVal.ee, retVal.ff, retVal.gg, + retVal.hh, retVal.ii, (unsigned long)retVal.jj, retVal.kk, + retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp, retVal.qq, + retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, + retVal.ww, retVal.xx); +} diff --git a/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c new file mode 100644 index 00000000000..2c5ea375505 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c @@ -0,0 +1,22 @@ +/* Test specification of custom instructions via command-line options. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it LBCO/SBCO operations may + not be optimized to the respective instructions. */ + + +#pragma ctable_entry 12 0x48040000 + +unsigned int +test_ctable (unsigned int val1, unsigned int val2) +{ + ((volatile unsigned short int *)0x48040000)[0] = val2; + ((volatile unsigned int *)0x48040000)[val1] = val2; + return ((volatile unsigned int *)0x48040000)[4]; +} + +/* { dg-final { scan-assembler "sbco\\tr15.b\[012\]?, 12, 0, 2" } } */ +/* { dg-final { scan-assembler "sbco\\tr15.b0, 12, r14, 4" } } */ +/* { dg-final { scan-assembler "lbco\\tr14.b0, 12, 16, 4" } } */ diff --git a/gcc/testsuite/gcc.target/pru/pru.exp b/gcc/testsuite/gcc.target/pru/pru.exp new file mode 100644 index 00000000000..966620d78ec --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/pru.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2015-2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a PRU target. +if ![istarget pru*-*-*] then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/pru/qbbc-1.c b/gcc/testsuite/gcc.target/pru/qbbc-1.c new file mode 100644 index 00000000000..1a891907561 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/qbbc-1.c @@ -0,0 +1,29 @@ +/* Test QBBC recognition */ + +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it bit-check-and-branch + operation may not be optimized to QBBC. */ + +extern void abort (void); + +unsigned int +test_qbbc_reg (unsigned int a, unsigned int b, unsigned int val) +{ + if (!(val & (1 << 19))) + return a; + return b; +} + +int +main (int argc, char** argv) +{ + if (test_qbbc_reg (101, 505, (1u << 19)) != 505) + abort(); + if (test_qbbc_reg (101, 505, (1u << 18)) != 101) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/qbbc-2.c b/gcc/testsuite/gcc.target/pru/qbbc-2.c new file mode 100644 index 00000000000..208e039afa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/qbbc-2.c @@ -0,0 +1,15 @@ +/* Test QBBC recognition */ + +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it bit-check-and-branch + operation may not be optimized to QBBC. */ + +unsigned int +test_qbbc_reg (unsigned int a, unsigned int b, unsigned int val) +{ + /* { dg-final { scan-assembler "qbbc\\t.L\[0-9\]*, r16, 19" } } */ + if (!(val & (1 << 19))) + return a; + return b; +} diff --git a/gcc/testsuite/gcc.target/pru/qbbc-3.c b/gcc/testsuite/gcc.target/pru/qbbc-3.c new file mode 100644 index 00000000000..7fb7e1a9742 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/qbbc-3.c @@ -0,0 +1,15 @@ +/* Test QBBC recognition */ + +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it bit-check-and-branch + operation may not be optimized to QBBC. */ + +unsigned int +test_qbbc_reg (unsigned int a, unsigned int b, unsigned short val) +{ + /* { dg-final { scan-assembler "qbbc\\t.L\[0-9\]*, r16.w0, 12" } } */ + if (!(val & (1 << 12))) + return a; + return b; +} diff --git a/gcc/testsuite/gcc.target/pru/qbbs-1.c b/gcc/testsuite/gcc.target/pru/qbbs-1.c new file mode 100644 index 00000000000..01f8187d64f --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/qbbs-1.c @@ -0,0 +1,29 @@ +/* Test QBBS recognition */ + +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it bit-check-and-branch + operation may not be optimized to QBBS. */ + +extern void abort (void); + +unsigned int +test_qbbs_reg (unsigned int a, unsigned int b, unsigned int val) +{ + if (val & (1 << 19)) + return a; + return b; +} + +int +main (int argc, char** argv) +{ + if (test_qbbs_reg (101, 505, (1u << 19)) != 101) + abort(); + if (test_qbbs_reg (101, 505, (1u << 18)) != 505) + abort(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/pru/qbbs-2.c b/gcc/testsuite/gcc.target/pru/qbbs-2.c new file mode 100644 index 00000000000..fea7f202659 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/qbbs-2.c @@ -0,0 +1,15 @@ +/* Test QBBS recognition */ + +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it bit-check-and-branch + operation may not be optimized to QBBS. */ + +unsigned int +test_qbbs_reg (unsigned int a, unsigned int b, unsigned int val) +{ + /* { dg-final { scan-assembler "qbbs\\t.L\[0-9\]*, r16, 19" } } */ + if (val & (1 << 19)) + return a; + return b; +} diff --git a/gcc/testsuite/gcc.target/pru/setbit.c b/gcc/testsuite/gcc.target/pru/setbit.c new file mode 100644 index 00000000000..6e63b736206 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/setbit.c @@ -0,0 +1,13 @@ +/* setbit instruction generation */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +unsigned int +test_setbit (unsigned int val) +{ + /* { dg-final { scan-assembler "set\\tr14, r14, 31" } } */ + val |= (1u << 31); + return val; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c new file mode 100644 index 00000000000..716043cf071 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c @@ -0,0 +1,16 @@ +/* AND with zero extension of operands. + It is matched slightly different than rest of ALU ops. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_and_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "and\\tr14, r14.w0, r15" } } */ + return val1 & val2; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c new file mode 100644 index 00000000000..06f58459720 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c @@ -0,0 +1,16 @@ +/* AND with zero extension of operands. + It is matched slightly different than rest of ALU ops. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_and_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "and\\tr14, r14.b0, r15" } } */ + return val1 & val2; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c new file mode 100644 index 00000000000..06f58459720 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c @@ -0,0 +1,16 @@ +/* AND with zero extension of operands. + It is matched slightly different than rest of ALU ops. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_and_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "and\\tr14, r14.b0, r15" } } */ + return val1 & val2; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c new file mode 100644 index 00000000000..eddd4298169 --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c @@ -0,0 +1,43 @@ +/* ALU operations with zero extended operands. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_plus_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "add\\tr14, r14.w0, r15" } } */ + return val1 + val2; +} + +unsigned int +test_zext_minus_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "sub\\tr14, r14.w0, r15" } } */ + return val1 - val2; +} + +unsigned int +test_zext_xor_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "xor\\tr14, r14.w0, r15" } } */ + return val1 ^ val2; +} + +unsigned int +test_zext_or_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "or\\tr14, r14.w0, r15" } } */ + return val1 | val2; +} + +unsigned int +test_zext_ashl_hi (unsigned short val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "lsl\\tr14, r14.w0, r15" } } */ + return val1 << val2; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c b/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c new file mode 100644 index 00000000000..62e81f8a4cc --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c @@ -0,0 +1,43 @@ +/* ALU operations with zero extended operands. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_plus_hi (unsigned char val1, unsigned short val2) +{ + /* { dg-final { scan-assembler "add\\tr14, r14.b0, r14.w1" } } */ + return val1 + val2; +} + +unsigned int +test_zext_minus_hi (unsigned char val1, unsigned short val2) +{ + /* { dg-final { scan-assembler "sub\\tr14, r14.b0, r14.w1" } } */ + return val1 - val2; +} + +unsigned int +test_zext_xor_hi (unsigned char val1, unsigned short val2) +{ + /* { dg-final { scan-assembler "xor\\tr14, r14.b0, r14.w1" } } */ + return val1 ^ val2; +} + +unsigned int +test_zext_or_hi (unsigned char val1, unsigned short val2) +{ + /* { dg-final { scan-assembler "or\\tr14, r14.b0, r14.w1" } } */ + return val1 | val2; +} + +unsigned int +test_zext_ashl_hi (unsigned char val1, unsigned short val2) +{ + /* { dg-final { scan-assembler "lsl\\tr14, r14.b0, r14.w1" } } */ + return val1 << val2; +} + diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c new file mode 100644 index 00000000000..0e9ae4cf01e --- /dev/null +++ b/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c @@ -0,0 +1,43 @@ +/* ALU operations with zero extended operands. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* -O1 in the options is significant. Without it the zero extension might not + be coalesced into the ALU instruction. */ + +unsigned int +test_zext_plus_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "add\\tr14, r14.b0, r15" } } */ + return val1 + val2; +} + +unsigned int +test_zext_minus_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "sub\\tr14, r14.b0, r15" } } */ + return val1 - val2; +} + +unsigned int +test_zext_xor_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "xor\\tr14, r14.b0, r15" } } */ + return val1 ^ val2; +} + +unsigned int +test_zext_or_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "or\\tr14, r14.b0, r15" } } */ + return val1 | val2; +} + +unsigned int +test_zext_ashl_hi (unsigned char val1, unsigned int val2) +{ + /* { dg-final { scan-assembler "lsl\\tr14, r14.b0, r15" } } */ + return val1 << val2; +} + diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index c2d814cf8c6..60105eb9fd7 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -512,7 +512,8 @@ proc check_effective_target_trampolines { } { || [istarget msp430-*-*] || [istarget nvptx-*-*] || [istarget hppa2.0w-hp-hpux11.23] - || [istarget hppa64-hp-hpux11.23] } { + || [istarget hppa64-hp-hpux11.23] + || [istarget pru-*-*] } { return 0; } return 1 @@ -685,6 +686,7 @@ proc check_profiling_available { test_what } { || [istarget nvptx-*-*] || [istarget powerpc-*-eabi*] || [istarget powerpc-*-elf] + || [istarget pru-*-*] || [istarget rx-*-*] || [istarget tic6x-*-elf] || [istarget visium-*-*] @@ -880,7 +882,7 @@ proc check_effective_target_tls_emulated {} { proc check_effective_target_tls_runtime {} { # The runtime does not have TLS support, but just # running the test below is insufficient to show this. - if { [istarget msp430-*-*] || [istarget visium-*-*] } { + if { [istarget msp430-*-*] || [istarget visium-*-*] || [istarget pru-*-*] } { return 0 } return [check_runtime tls_runtime { @@ -8850,6 +8852,7 @@ proc check_effective_target_logical_op_short_circuit {} { || [istarget riscv*-*-*] || [istarget v850*-*-*] || [istarget visium-*-*] + || [istarget pru*-*-*] || [check_effective_target_arm_cortex_m] } { return 1 } From patchwork Thu Aug 16 04:49:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958093 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-483755-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="vYHifwlx"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="Y/up902t"; 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 41rYn00jFTz9s4c for ; Thu, 16 Aug 2018 14:50:43 +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:in-reply-to:references; q=dns; s= default; b=azB0mpT+Q0rOvbvNHZDUn2EoRUxqLgAKSVkxZJYvKLgfvbs53X70x QmH52E01bHjxDcKqYvJ2dCXqu4cSa2omGSrk3f0YLZC9tLqLDjWdaGI3yiCfX0kb wE54S/k3vAKu8QKRrJG1BraeYBLu6P09o7y1SFDSCIvAFssRpFIRZA= 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:in-reply-to:references; s= default; bh=izeO9qHf7YfrhSE5N74OM2Xknm0=; b=vYHifwlxebSFMYNoOCpi yM03emir9zV+TG/jcBQyV3tpukCndxH4TMuKjEI0viyY6M4le8cs9QXWWyv7/lRT FOiKK3x3F1Rfd23tVAeyLi5eGBygGMz1F/fhyKjuaKP17r69+xTvMc1Y93fn3xbg gEiMdsAwys0Tlp3oqxgZo6U= Received: (qmail 98309 invoked by alias); 16 Aug 2018 04:50:32 -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 98142 invoked by uid 89); 16 Aug 2018 04:50:31 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=istarget, D*eu, HX-Get-Message-Sender-Via:sk:authent X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:29 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEt-0004dR-7m for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:27 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=wRg+mLMGpMijQ3bjthwa4k/FwKIVhtFMo0uuaYDvUtA=; b=Y/up902tI2SNVE4a852YIgrUzU XXYvPyBCD2QjcaBBzoxHzOyKdcQGdqWSmwu9M2GjfI32sa/JwboaGfV2/w4AXJu5m2bz2nzbO8fGg MUd5FWZXgycBXqTz+4xAYzevtwbe3aDlow5w0iC3TxNd0VQo1vNcYIGMTdhyKE+L9D3jsI1YYYkc3 ROduog2b0e4apKEwVoI9lsXh3shReQykqNdRPjKp3Jw3Flb/7yh5hoNLaQlBtozEhtoytrW64NdUk vqO3Xr/oHv9XOLUFb3gFliXxsnRElp4Znqhm5/SuYMOGIE3UKpRzJZs3FstY2AY+AFtGuz+Y8xKEx bg3LWkxA==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEq-0004j3-Vy; Thu, 16 Aug 2018 07:50:27 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 04/10] testsuite: Add check for overflowed IMEM region to testsuite Date: Thu, 16 Aug 2018 07:49:53 +0300 Message-Id: <20180816044959.12320-5-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-IsSubscribed: yes PRU architecture supports maximum 256k program memory (IMEM). Some GCC test cases manage to produce executables bigger than that. gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * lib/gcc-dg.exp: Bail on region overflow for tiny targets. * lib/target-utils.exp: Ditto. * lib/target-supports.exp: Declare PRU target as tiny. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/lib/gcc-dg.exp | 5 +++++ gcc/testsuite/lib/target-supports.exp | 5 +++++ gcc/testsuite/lib/target-utils.exp | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index f5e6bef5dd9..c26d1c73aa0 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -392,6 +392,11 @@ proc gcc-dg-prune { system text } { return "::unsupported::memory full" } + if { [regexp "(^|\n)\[^\n\]*: region \[^\n\]* overflowed" $text] + && [check_effective_target_tiny] } { + return "::unsupported::memory full" + } + # Likewise, if we see ".text exceeds local store range" or # similar. if {[string match "spu-*" $system] && \ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 60105eb9fd7..5299aaefcc3 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -8833,6 +8833,11 @@ proc check_effective_target_tiny {} { && [check_effective_target_avr_tiny] } { set et_target_tiny_saved 1 } + # PRU Program Counter is 16-bits, and trampolines are not supported. + # Hence directly declare as a tiny target. + if [istarget pru-*-*] { + set et_target_tiny_saved 1 + } } return $et_target_tiny_saved diff --git a/gcc/testsuite/lib/target-utils.exp b/gcc/testsuite/lib/target-utils.exp index bd39cc5bc79..732a1827a02 100644 --- a/gcc/testsuite/lib/target-utils.exp +++ b/gcc/testsuite/lib/target-utils.exp @@ -35,6 +35,10 @@ proc ${tool}_check_unsupported_p { output } { && [check_effective_target_tiny] } { return "memory full" } + if { [regexp "(^|\n)\[^\n\]*: region \[^\n\]* overflowed" $output] + && [check_effective_target_tiny] } { + return "memory full" + } if { [istarget spu-*-*] && \ [string match "*exceeds local store*" $output] } { From patchwork Thu Aug 16 04:49:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958102 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-483764-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="oxKmaWd3"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="oH9bFdJy"; 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 41rYqf6V2rz9s4v for ; Thu, 16 Aug 2018 14:53:02 +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:in-reply-to:references; q=dns; s= default; b=BeJCKondRJgPNhxVfELGIOyXx0kYqf+gsRujBtCoTgrRMB6qedsB1 NMRwyBY3Nzfdb/BoExHSU8z9JXq82SMDSUmj84DOKWCNDDMlU4Y/lpmsztO+bk9s cZy444h//S5HMLzVDu5IeB3d58kVegyg+pZMp9KXx3ZHGXmPew+prY= 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:in-reply-to:references; s= default; bh=YtOtZwk1BBHCKfKhvC24D4ukYJQ=; b=oxKmaWd3b5nJ7KcAn8PK NrHDGe0k6/k+hk1ePhJKeohm1q5+F4LyhZ29BaEaoamkDZ7QlfFsFvfAvEgsGS4H NnUzhTp/V/JaKzR5AiLyM2wXwGRQHB5/A2sFLlCuzxFOL9vt+Jcj4LR0jd0CqTmv KQEE5pv39d1zcPPIQNvSsTs= Received: (qmail 100654 invoked by alias); 16 Aug 2018 04:50:56 -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 99788 invoked by uid 89); 16 Aug 2018 04:50:44 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy= X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:42 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqAF2-0004lO-Pb for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:38 -0400 Received: from smtp-out1.superhosting.bg ([91.196.127.170]:56311) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqAF0-0004jI-Ob for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:36 -0400 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEv-0004da-Cf for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:29 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=2925pr+UE/UtwvGcuzWgwKByu8iKJOPgqKGM5Bri02c=; b=oH9bFdJy0xrYuo/zwvQ1djA7D7 RdLo8XWybuk1wghkurrhhxNrXCkki3cvFEPk3Dv5g5QWaV2JvvDZqUg9dC8oAAA5GzezQJ5CwL5AG 20H1EcVZkYPrES1GSNyskpZdOAZ+8LwnlBLZRc3/e1UldQ9QbiUhNLu1TJ9gq5QGwyUjyJd6oobZh IXb9MFaRODqyZNw9TM1LDcU22WEthEB/NfLhBa91+VnDrFhjuTn1cOHhIqUpF94Bv0b+NWRCoWCVl aiHYRzN4wHXXGq2aUWZ4GwNRGqkbI3ACAABMy4mfEVATSxCnsmtaPqPDWTS1eoLw18Dc33eygj0mt RMNci9EA==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEt-0004j3-2M; Thu, 16 Aug 2018 07:50:29 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 05/10] testsuite: Add check for unsupported TI ABI PRU features to testsuite Date: Thu, 16 Aug 2018 07:49:54 +0300 Message-Id: <20180816044959.12320-6-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 91.196.127.170 X-IsSubscribed: yes Not all C language features are supported when -mabi=ti option is used for PRU target. gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * lib/gcc-dg.exp: Filter unsupported features in PRU's TI ABI mode. * lib/target-utils.exp: Ditto. * lib/target-supports.exp (check_effective_target_function_pointers, check_effective_target_large_return_values): New. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/lib/gcc-dg.exp | 11 +++++++++++ gcc/testsuite/lib/target-supports.exp | 26 ++++++++++++++++++++++++++ gcc/testsuite/lib/target-utils.exp | 8 ++++++++ 3 files changed, 45 insertions(+) diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index c26d1c73aa0..c061c152f16 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -405,6 +405,17 @@ proc gcc-dg-prune { system text } { return "::unsupported::memory full" } + if { [string match "*error: function pointers not supported*" $text] + && ![check_effective_target_function_pointers] } { + # The format here is important. See dg.exp. + return "::unsupported::funcptr" + } + if { [string match "*error: large return values not supported*" $text] + && ![check_effective_target_large_return_values] } { + # The format here is important. See dg.exp. + return "::unsupported::large return values" + } + return $text } diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 5299aaefcc3..711a6db1e97 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2608,6 +2608,32 @@ proc check_effective_target_ptr32plus { } { }] } +# Return 1 if target supports function pointers, 0 otherwise. + +proc check_effective_target_function_pointers { } { + if { [istarget pru-*-*] } { + return [check_no_compiler_messages func_ptr_avail assembly { + #ifdef __PRU_EABI_GNU__ + #error unsupported + #endif + }] + } + return 1 +} + +# Return 1 if target supports arbitrarily large return values, 0 otherwise. + +proc check_effective_target_large_return_values { } { + if { [istarget pru-*-*] } { + return [check_no_compiler_messages func_ptr_avail assembly { + #ifdef __PRU_EABI_GNU__ + #error unsupported + #endif + }] + } + return 1 +} + # Return 1 if we support 32-bit or larger array and structure sizes # using default options, 0 otherwise. Avoid false positive on # targets with 20 or 24 bit address spaces. diff --git a/gcc/testsuite/lib/target-utils.exp b/gcc/testsuite/lib/target-utils.exp index 732a1827a02..f636be2cb01 100644 --- a/gcc/testsuite/lib/target-utils.exp +++ b/gcc/testsuite/lib/target-utils.exp @@ -44,5 +44,13 @@ proc ${tool}_check_unsupported_p { output } { [string match "*exceeds local store*" $output] } { return "memory full" } + if { [string match "*error: function pointers not supported*" $output] + && ![check_effective_target_function_pointers] } { + return "function pointers not supported" + } + if { [string match "*error: large return values not supported*" $output] + && ![check_effective_target_large_return_values] } { + return "large return values not supported" + } return "" } From patchwork Thu Aug 16 04:49:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958100 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-483762-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ivHhdl1M"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="A+zHTaUR"; 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 41rYqF2gmbz9s4c for ; Thu, 16 Aug 2018 14:52:41 +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:in-reply-to:references; q=dns; s= default; b=RPT5YIYBwZMSNVwFQPiQrhlHO852FymARdkRGnenvKxeFPV5ehT+6 8n8gj3XNzJy0xroY4wzZYwIy4F45fJQtHtHXC4kJ3RIvnIAEK9Ps5r0TUV7kTDwP Yxy1p/sttPaeGWuUF1Ie03HmwGrsmmasgH73rVDim/xN39ZXUc6YIU= 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:in-reply-to:references; s= default; bh=QjLN7+DVWNG7fh47CM1gkVScilA=; b=ivHhdl1MRbHEoTOi7XSM jkoLa/6SpBUZjzg0FMQm0QlktN7NlNgGDfOrqFkh14ljKfV43u81WKqdLrcn9Wip m6kT4de6fCQH+gBuk+obkFS5OwsIGQNkJN12rbq7d8Xo48grB7ano52EcwY4jb9d j2dVcJrOsd+DT8ABBg5dQk0= Received: (qmail 100455 invoked by alias); 16 Aug 2018 04:50:55 -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 99785 invoked by uid 89); 16 Aug 2018 04:50:44 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy=HX-Get-Message-Sender-Via:sk:authent X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:42 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqAF2-0004lU-QG for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:37 -0400 Received: from smtp-out1.superhosting.bg ([91.196.127.170]:33589) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqAF1-0004jc-0h for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:36 -0400 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEx-0004e3-C0 for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:31 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=uLrjdogsviGkQoYZI+0DtJY8yqCcFF/xEaMD46aeXVI=; b=A+zHTaURr8s5OQ8tQ1OmX2/uO4 GA8GGqQio1sKWUewsva3V2H7zfmlHYlAQubrW46+p3LxfJSUAv87nnlMJqeAAWCE25qxcTdLJFAzR 3uh7MzXr5Xbg5eQXIKcfV6hOoK893RKdq12lO8z3sudTeBumYboBfaYzlqixWFRwOHBh5R/MzhA78 7ELw0R5PHnx062/l5YMTnXaRnZMh5W59StfizVPCSwShqy9kvOc5UbaHXZdlamSXcczB7ufsRNK1x nR29M/KGfj7UQ6ecbicDqkUljq+g04Q38W0kDYvWBftZQPg2a2j+L8hXity375yiV5cxbjGA1ZNAJ 9WLc+16g==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEv-0004j3-85; Thu, 16 Aug 2018 07:50:31 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 06/10] testsuite: Remove PRU from test cases requiring hosted environment Date: Thu, 16 Aug 2018 07:49:55 +0300 Message-Id: <20180816044959.12320-7-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 91.196.127.170 X-IsSubscribed: yes gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * gcc.c-torture/execute/20101011-1.c: Define DO_TEST to 0 for PRU. * gcc.dg/20020312-2.c: No PIC register for PRU. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/gcc.c-torture/execute/20101011-1.c | 3 +++ gcc/testsuite/gcc.dg/20020312-2.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c index dda49a59852..7f8d14d617c 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c @@ -93,6 +93,9 @@ __aeabi_idiv0 (int return_value) #elif defined (__nvptx__) /* There isn't even a signal function. */ # define DO_TEST 0 +#elif defined (__pru__) +/* There isn't even a signal function. */ +# define DO_TEST 0 #else # define DO_TEST 1 #endif diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index f5929e0b057..209ef67e263 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -111,6 +111,8 @@ extern void abort (void); /* No pic register. */ #elif defined (__nvptx__) /* No pic register. */ +#elif defined(__PRU__) +/* No pic register. */ #else # error "Modify the test for your target." #endif From patchwork Thu Aug 16 04:49:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958096 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-483758-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="VDIzkLIc"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="KaiOYNsm"; 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 41rYpJ2gRkz9s4c for ; Thu, 16 Aug 2018 14:51:52 +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:in-reply-to:references; q=dns; s= default; b=UdVomJlFoiHdRhQpquLVW5UPkOJi4ZdsGW5nM4ookFCfXkQXrTGYD ayv7ZacPrkVFv5MW4FQhIXBmGT4MVdM0nt14XHiXKJP3T20U09E2HDO9n71RkLYS Ug5FMkNdTiUfwcrzX51lTCXX+ARSvML18lcbqZs+5T8sX5kGTgVC2g= 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:in-reply-to:references; s= default; bh=RKifnXYT38LvMUfrhhouGwfElrg=; b=VDIzkLIcZmO130+2Abyv +NSwJQ3U2HgsSpRaCR5d1PLdsodBXK9XuPLS8aQbUKpNOgM/2KZNOfRccYijpiTp BiYvZG3dQPostQbuihOMOLQ7wwf3QoSAQk5TivNHLXNIbdXTjSLwn1Bm4UQg2N6Z s0SjYnCmBkVCfmd1SAEQdaM= Received: (qmail 99844 invoked by alias); 16 Aug 2018 04:50:45 -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 99017 invoked by uid 89); 16 Aug 2018 04:50:38 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=HX-Get-Message-Sender-Via:sk:authent X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:36 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAEz-0004eF-HI for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:34 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=M531EofDidRA7ba9kN/S8G1LrTtN+ey7rU1/7JBY2Jo=; b=KaiOYNsm1tWVk7GYzCQWqs3TYm p9C2WlCaeeb5c6q3ocedmPN1+vjWXij8jroCyp/UR3OCWqMktA2UOM8+mA4ANb+t1sUtcTLfR6ir+ FoAJEslIVFQ8LkFdjNkF8Fx9O43mKvxnORRTwoOpYesE/TcFQfr5wjBqNuIfIwXRdcQD9PDJAtKR3 2lASCrGlR+wEejbQtCQ7YkvKl5wqTqdS4kqUp8toLsM1+ZfArmGEEQJxA+X2PPcP1gSpW0Li+zAC5 VzvUytl2+eU7gNUB4ikESFlNmfsHr30aHGvmhF91euNSD6iRFw6JL8HWia0AUFZOSuQMaA9EACtpS DWD51OKQ==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEx-0004j3-7X; Thu, 16 Aug 2018 07:50:33 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 07/10] testsuite: Define PRU stack usage Date: Thu, 16 Aug 2018 07:49:56 +0300 Message-Id: <20180816044959.12320-8-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-IsSubscribed: yes gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * gcc.dg/stack-usage-1.c: Define PRU stack usage. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/gcc.dg/stack-usage-1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c index 038bd4ec05c..ffa97da6c32 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-1.c +++ b/gcc/testsuite/gcc.dg/stack-usage-1.c @@ -93,6 +93,8 @@ # define SIZE 254 #elif defined (__nios2__) # define SIZE 252 +#elif defined (__PRU__) +# define SIZE 252 #elif defined (__v850__) #define SIZE 260 #elif defined (__mn10300__) From patchwork Thu Aug 16 04:49:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958097 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-483759-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="KKoKZ67M"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="GpOCISY+"; 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 41rYpW6JV8z9s4c for ; Thu, 16 Aug 2018 14:52:03 +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:in-reply-to:references; q=dns; s= default; b=W0pTQPsTE+u3EUxzelT4eqYOdEZ055wCvVvJWBk1GRdANI7BNfxuJ wb9pXVmJWJHdaWEWAB98RcjPHNLm0EJ/UYvd3KtLOYiOWDyIh9CdV4lLeP043qTI HUmjJ1OkzuTs3QXbgzHAJLuGtpHuvEn3euDz5t9rkTk0i1yv2PiSqU= 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:in-reply-to:references; s= default; bh=aCxf03B9Fz3NTzLOQEBo7x87pQ8=; b=KKoKZ67Mv1sT6zwMANF6 Xw24/R0Ls9VCFhuDPTQeOJrUeXfKXWbLpZvrCnC4n3kJaDOBdFaQYCioyNZiHOAK lEBM3oQ2eDNm+OH/MywYz9fRkQzFKNYOaliwhXZ/pn0nFE3pcGad4ugi1xpAabvb JE82NQoRbpdFNxd4la52lYU= Received: (qmail 99914 invoked by alias); 16 Aug 2018 04:50:50 -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 99556 invoked by uid 89); 16 Aug 2018 04:50:42 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_PASS autolearn=ham version=3.3.2 spammy=dom, x86_64**, x86_64-*-* X-HELO: smtp-out1.superhosting.bg Received: from smtp-out1.superhosting.bg (HELO smtp-out1.superhosting.bg) (91.196.127.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:38 +0000 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAF1-0004eT-Mv for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:35 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=DNO4Ox6UV655gq9oLn/je0jKLF7HniCSnfwo/UP9j7g=; b=GpOCISY+PLlZXJnQ+TR5e6OHOL rU++uxMVtSorOYZotX66FpF3mKLfm9bD9xhRF57SdzFcufB+wGc8w1l01RecYFN8yHf5KsTk9KXJr yKYXfuZ2SsTY/36sH1RkMdVj6fiSSFU8cX4mjRVrJ7M/S8JZNt7KCeprszn+dFpErwNQKoY8ewT+y e7ucgnV62wJ4mfMPefz2eRecpV7mfa6Eo3ks7bKH9/0WgHLCYNXbmM5pOqusT/ooMuYCGuuuBQ7Ih air1Lrple1MHX7UwJVo4uhi2W4U1zdqHRv01/G/IKEkMSP0BPYpfq7F/SklZrKr+D31wgf5pghX33 xSmRb5Tw==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAEz-0004j3-Cj; Thu, 16 Aug 2018 07:50:35 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 08/10] testsuite: Mark that PRU has one-cycle jumps Date: Thu, 16 Aug 2018 07:49:57 +0300 Message-Id: <20180816044959.12320-9-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-IsSubscribed: yes gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * gcc.dg/tree-ssa/20040204-1.c: XFAIL on pru. * gcc.dg/tree-ssa/reassoc-33.c: Ditto. * gcc.dg/tree-ssa/reassoc-34.c: Ditto. * gcc.dg/tree-ssa/reassoc-35.c: Ditto. * gcc.dg/tree-ssa/reassoc-36.c: Ditto. * gcc.dg/tree-ssa/ssa-thread-14.c: Ditto. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c index a1237cf839b..06b83029fd3 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c @@ -33,4 +33,4 @@ void test55 (int x, int y) that the && should be emitted (based on BRANCH_COST). Fix this by teaching dom to look through && and register all components as true. */ -/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* aarch64*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* nds32*-*-* s390*-*-* sh*-*-* sparc*-*-* spu-*-* visium-*-* x86_64-*-* riscv*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* aarch64*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* nds32*-*-* s390*-*-* sh*-*-* sparc*-*-* spu-*-* visium-*-* x86_64-*-* riscv*-*-* pru*-*-*" } } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c index 5572df4ae24..5e1cd1a6fa7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* pru*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ /* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c index 9b45f1cd9be..a59df6a7244 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* pru*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ /* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c index 9ee3abca04e..21239372709 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* pru*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ /* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c index ac3a04291b7..f8eb0954ae7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c @@ -1,4 +1,4 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* pru*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ /* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c index f12fb07e604..71e299578cc 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-14.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* riscv*-*-* } } } } } */ +/* { dg-do compile { target { ! { logical_op_short_circuit || { m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* riscv*-*-* pru*-*-* } } } } } */ /* { dg-additional-options "-O2 -fdump-tree-vrp-details" } */ /* { dg-additional-options "-mbranch-cost=2" { target i?86-*-* x86_64-*-* } } */ /* { dg-final { scan-tree-dump-times "Threaded jump" 8 "vrp1" } } */ From patchwork Thu Aug 16 04:49:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958099 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-483761-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="YO6UQwGY"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="fP8zBiIQ"; 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 41rYq26pkBz9s4c for ; Thu, 16 Aug 2018 14:52:30 +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:in-reply-to:references; q=dns; s= default; b=hJjxVAKsg7fOLFr1afMgBJm3QjXghp8ASTLf3TcOD+D/mQejf32sB pSXPjapQHy3AIix1b/EnFjOY/jb9ydqqfDZ4krQP9UpV5ONyaWTxXYqx2njaqomP nuJyP/BkCe2og8W4hP99pATyhMnInqEhizbOyuLH9PiXGduDZs+MXs= 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:in-reply-to:references; s= default; bh=2EBcEqM+yiU2QUrIrpjk3VNkpnw=; b=YO6UQwGY1xBqNU+eYTj9 zK2WJvHkVojr+eHnjF0eKCCW+aBl5ouRlwnZYpUo2pM1Lr9bf8F+nto+TFt56szG PfNOk8S1yQqyQSR45iuH+l44JkgSAxaR6znNnUnxlpGxDvnOCSYI84f96ntTAchA 8SLQzt1XfVGKrgvydDSpQnc= Received: (qmail 100081 invoked by alias); 16 Aug 2018 04:50:52 -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 99791 invoked by uid 89); 16 Aug 2018 04:50:45 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy=HX-Get-Message-Sender-Via:sk:authent X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:44 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqAF6-0004ml-T7 for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:42 -0400 Received: from smtp-out1.superhosting.bg ([91.196.127.170]:38819) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqAF5-0004ll-3D for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:39 -0400 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAF3-0004ec-UK for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:37 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=TnIG2XJ1qSn3zZ9sPuEJhF9JT+fegxGdTrj9k7KDwas=; b=fP8zBiIQr4R5DodDm+rNusaCST J+uv3wR1GF+CuSrUt905drMfRVBzHQ5YnToQ/0awIaC8hR5UFkMfYaHSS5QeiyEDnZUivQ+KGXMxi ssSZ4NzY2kWbjvtHFSdIp0tte1zDV3HV0xlAo6paKgWdFpYv2SxHmtZLtfpHjAyVfJzX6vc8a+FKK I5aVhqtMNLTCwHot6KwWa7Azl7tPGOaPv2BlfAC+gNtloS5EjpwADOGbUZOVVgdO+dmi9B6Sx8FWY 71hiNY74nS+Urbc4u7fL4dluJS+RefhOeGawIq2UNiHZCf8VVWdmQQuNRYcUaCmszDFCVw835e/iS 5PcWeo6A==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAF1-0004j3-MR; Thu, 16 Aug 2018 07:50:37 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 09/10] testsuite: Mark that PRU uses all function pointer bits Date: Thu, 16 Aug 2018 07:49:58 +0300 Message-Id: <20180816044959.12320-10-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 91.196.127.170 X-IsSubscribed: yes gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * g++.old-deja/g++.abi/ptrmem.C: Add PRU to list. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C index 341735879c5..bda7960d8a2 100644 --- a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C +++ b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C @@ -7,7 +7,7 @@ function. However, some platforms use all bits to encode a function pointer. Such platforms use the lowest bit of the delta, that is shifted left by one bit. */ -#if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__ || defined __aarch64__ +#if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__ || defined __aarch64__ || defined __PRU__ #define ADJUST_PTRFN(func, virt) ((void (*)())(func)) #define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt)) #else From patchwork Thu Aug 16 04:49:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dimitar Dimitrov X-Patchwork-Id: 958101 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-483763-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=dinux.eu Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="QB/opxmM"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=dinux.eu header.i=@dinux.eu header.b="gbQ/BdcB"; 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 41rYqS2WMdz9s4c for ; Thu, 16 Aug 2018 14:52:52 +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:in-reply-to:references; q=dns; s= default; b=QoivHDoOPQy28CpO6MKrkgbSdcWiIexC0nNcZpip1F7nw+pGizriP rb3azs8t6jg661/irmoH7QSoOfxSBpk3ln0Cq2Jx14xF74bxXgtVNWt/oBdVjSO1 4+gW9n77OqfXtQvR4vC6wuMqupPQ2s5hzScYFlzmNdW/4vqSn2WSAI= 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:in-reply-to:references; s= default; bh=8MZj5eEQGJsg4898vM0drxCp9qk=; b=QB/opxmMV6w5gRL5m+QM 48BND8zLXohoHl5GK1I7I2qIaBMDCTW8wbY5Mrxomvelrh47pLBzIDTYFlVx8nKW hQBaj7TxjYxmwITseZ1ZMrGVtYIm1Y8TVANoJP9bX3QoZZAz7nVGXPrsVjOvmqOF dtBDrbof9H04LMiw4hK7RH4= Received: (qmail 100509 invoked by alias); 16 Aug 2018 04:50:55 -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 99877 invoked by uid 89); 16 Aug 2018 04:50:48 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_SOFTFAIL autolearn=ham version=3.3.2 spammy=HX-Get-Message-Sender-Via:sk:authent X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (208.118.235.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 16 Aug 2018 04:50:46 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fqAF8-0004os-TB for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:44 -0400 Received: from smtp-out1.superhosting.bg ([91.196.127.170]:59165) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fqAF8-0004mV-1m for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 00:50:42 -0400 Received: from server28.superhosting.bg ([193.107.36.199]) by smtp-out1.superhosting.bg with esmtps (TLSv1:AES256-SHA:256) (Exim 4.63) (envelope-from ) id 1fqAF6-0004el-7C for gcc-patches@gcc.gnu.org; Thu, 16 Aug 2018 07:50:40 +0300 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dinux.eu; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=KUhH8fvUIGFM6F7CZbqm8Vx/HX1bEaTkGfTpTSzkU+Y=; b=gbQ/BdcBIaJ1auBb1hIFCaeJXV IKAoshmnXFDG1VnJEHbuzI7OWFIq40ojlLfI5vUqDjy4rfxMJ29sYzee2b6Ekqq9xwJdRckCUVxRK sC/L9H06TTG1h6A1uF3KjAPFOVktrF78g29H2HYGBPqqZoaKyJU+2O1nv4yyWrW5V5JhTsiHHUsYH d5kl1+MGzJmypgv9GA37EhxTHlHBTNCdd4QzOl4DpgKCpFiZkVoRS5bSd4JXXtEgt9vBUXUqGgu9u X+zor1AOhfrvXrIJN2vbVJ24grFmb1shBQyGHYTU+9GOEqX+gvf+yEksQac2tcvlFMHP+T7dzwVPG 63PPBb+Q==; Received: from [95.87.234.74] (port=43018 helo=localhost.localdomain) by server28.superhosting.bg with esmtpsa (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.91) (envelope-from ) id 1fqAF3-0004j3-UM; Thu, 16 Aug 2018 07:50:40 +0300 From: Dimitar Dimitrov To: gcc-patches@gcc.gnu.org Cc: Dimitar Dimitrov Subject: [PATCH v3 10/10] testsuite: Mark testsuite that PRU has different calling convention Date: Thu, 16 Aug 2018 07:49:59 +0300 Message-Id: <20180816044959.12320-11-dimitar@dinux.eu> In-Reply-To: <20180816044959.12320-1-dimitar@dinux.eu> References: <20180816044959.12320-1-dimitar@dinux.eu> X-OutGoing-Spam-Status: No, score=-1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 91.196.127.170 X-IsSubscribed: yes For variadic functions, the last named and all anonymous arguments are passed on stack. Regular functions pass arguments in registers. gcc/testsuite/ChangeLog: 2018-07-27 Dimitar Dimitrov * gcc.dg/builtin-apply2.c: Skip for PRU. * gcc.dg/torture/stackalign/builtin-apply-2.c: Ditto. Signed-off-by: Dimitar Dimitrov --- gcc/testsuite/gcc.dg/builtin-apply2.c | 2 +- gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c index 3768caa5d5a..6ede0f3054b 100644 --- a/gcc/testsuite/gcc.dg/builtin-apply2.c +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c @@ -1,7 +1,7 @@ /* { dg-do run } */ /* { dg-require-effective-target untyped_assembly } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-*" } } */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-*" } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-* pru-*-*" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } } */ /* PR target/12503 */ diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c index d033010dc7c..8b6e693c0f2 100644 --- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c +++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c @@ -9,7 +9,7 @@ /* arm_hf_eabi: Variadic funcs use Base AAPCS. Normal funcs use VFP variant. avr: Variadic funcs don't pass arguments in registers, while normal funcs do. */ -/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* } } } */ +/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* pru-*-* } } } */ /* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } } */ /* { dg-require-effective-target untyped_assembly } */