From patchwork Sun Jul 14 07:55:00 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chung-Lin Tang X-Patchwork-Id: 258885 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 5092D2C00FA for ; Sun, 14 Jul 2013 17:56:06 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:content-type; q=dns; s=default; b=tPYIcg1D0Cgp6PEYnHNUInR99W2Ci+ug+dpe5A7EeAi v4cHdLorZO1rnXd51CYnkOoLmP4J/yL3VilQURkrPPP2jdS76sZLn/Us+HzFS632 +kdniqoD51Tejq6T6cay/1uD2yki9cPVJvP617vRudkjV1dJ6ZSMlEf/fdyLUSog = 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 :message-id:date:from:mime-version:to:cc:subject:content-type; s=default; bh=ZG1UD8WggwW2hTmmGBIjy51MuQw=; b=tgqIopgEUb/XXvp8d eUCVRhRaKGZMs2RbaRT8qbT43vb6fNc0AeaXuJepNepdA5ocfQhyhApdUMA9bJAE HTsVSc5N4Tuq1hSWsA1EFwWDPHx/tqCQplCrNQIWVkKfjy3jTVBU6mJCdieHTqxa ImTWmPdMZ66OSRScEYW80teOCA= Received: (qmail 22240 invoked by alias); 14 Jul 2013 07:55:19 -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 22175 invoked by uid 89); 14 Jul 2013 07:55:18 -0000 X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_50, KHOP_RCVD_UNTRUST, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RDNS_NONE, TW_DP, TW_IV, TW_OV, TW_VH, TW_XD, TW_XF, TW_XS, TW_XT autolearn=no version=3.3.1 Received: from Unknown (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Sun, 14 Jul 2013 07:55:12 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1UyH96-0004J2-Nm from ChungLin_Tang@mentor.com ; Sun, 14 Jul 2013 00:55:04 -0700 Received: from SVR-ORW-FEM-04.mgc.mentorg.com ([147.34.97.41]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Sun, 14 Jul 2013 00:55:04 -0700 Received: from air.local (147.34.91.1) by svr-orw-fem-04.mgc.mentorg.com (147.34.97.41) with Microsoft SMTP Server id 14.2.247.3; Sun, 14 Jul 2013 00:55:02 -0700 Message-ID: <51E25954.8060904@codesourcery.com> Date: Sun, 14 Jul 2013 15:55:00 +0800 From: Chung-Lin Tang User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:17.0) Gecko/20130620 Thunderbird/17.0.7 MIME-Version: 1.0 To: gcc-patches CC: Sandra Loosemore , "Sidwell, Nathan" , "Joseph S. Myers" , Richard Henderson Subject: [PATCH][3/3] Re-submission of Altera Nios II port, libgcc parts X-Virus-Found: No nios2 libgcc parts. Since the original post, the only main change has been the fdpbit vs soft-fp issue raised by Joseph, which has been resolved. Other parts are mostly the same. Thanks, Chung-Lin 2013-07-14 Sandra Loosemore Chung-Lin Tang Based on patches from Altera Corporation * config.host (nios2-*-*,nios2-*-linux*): Add nios2 host cases. * config/nios2/lib2-nios2.h: New file. * config/nios2/lib2-divmod-hi.c: New file. * config/nios2/linux-unwind.h: New file. * config/nios2/lib2-divmod.c: New file. * config/nios2/linux-atomic.c: New file. * config/nios2/t-nios2: New file. * config/nios2/crti.asm: New file. * config/nios2/t-linux: New file. * config/nios2/lib2-divtable.c: New file. * config/nios2/lib2-mul.c: New file. * config/nios2/tramp.c: New file. * config/nios2/crtn.asm: New file. Index: libgcc/config/nios2/lib2-nios2.h =================================================================== --- libgcc/config/nios2/lib2-nios2.h (revision 0) +++ libgcc/config/nios2/lib2-nios2.h (revision 0) @@ -0,0 +1,49 @@ +/* Integer arithmetic support for Altera Nios II. + + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + + 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 + . */ + +#ifndef LIB2_NIOS2_H +#define LIB2_NIOS2_H + +/* Types. */ + +typedef char QItype __attribute__ ((mode (QI))); +typedef unsigned char UQItype __attribute__ ((mode (QI))); +typedef short HItype __attribute__ ((mode (HI))); +typedef unsigned short UHItype __attribute__ ((mode (HI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int word_type __attribute__ ((mode (__word__))); + +/* Exported functions. */ +extern SItype __divsi3 (SItype, SItype); +extern SItype __modsi3 (SItype, SItype); +extern SItype __udivsi3 (SItype, SItype); +extern SItype __umodsi3 (SItype, SItype); +extern HItype __divhi3 (HItype, HItype); +extern HItype __modhi3 (HItype, HItype); +extern UHItype __udivhi3 (UHItype, UHItype); +extern UHItype __umodhi3 (UHItype, UHItype); +extern SItype __mulsi3 (SItype, SItype); + +#endif /* LIB2_NIOS2_H */ Index: libgcc/config/nios2/crtn.S =================================================================== --- libgcc/config/nios2/crtn.S (revision 0) +++ libgcc/config/nios2/crtn.S (revision 0) @@ -0,0 +1,60 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Jonah Graham (jgraham@altera.com). + Contributed by Mentor Graphics, Inc. + +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 +. */ + + +/* This file just makes sure that the .fini and .init sections do in +fact return. Users may put any desired instructions in those sections. +This file is the last thing linked into any executable. +*/ + .file "crtn.asm" + + + + .section ".init" + ldw ra, 44(sp) + ldw r23, 40(sp) + ldw r22, 36(sp) + ldw r21, 32(sp) + ldw r20, 28(sp) + ldw r19, 24(sp) + ldw r18, 20(sp) + ldw r17, 16(sp) + ldw r16, 12(sp) + ldw fp, 8(sp) + addi sp, sp, 48 + ret + + .section ".fini" + ldw ra, 44(sp) + ldw r23, 40(sp) + ldw r22, 36(sp) + ldw r21, 32(sp) + ldw r20, 28(sp) + ldw r19, 24(sp) + ldw r18, 20(sp) + ldw r17, 16(sp) + ldw r16, 12(sp) + ldw fp, 8(sp) + addi sp, sp, 48 + ret + Index: libgcc/config/nios2/linux-unwind.h =================================================================== --- libgcc/config/nios2/linux-unwind.h (revision 0) +++ libgcc/config/nios2/linux-unwind.h (revision 0) @@ -0,0 +1,179 @@ +/* DWARF2 EH unwinding support for Nios II Linux. + Copyright (C) 2008-2013 Free Software Foundation, Inc. + +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 +. */ + +#ifndef inhibit_libc + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. + The corresponding bits in the Linux kernel are in + arch/nios2/kernel/signal.c. */ + +#include +#include + +/* Exactly the same layout as the kernel structures, unique names. */ +struct nios2_mcontext { + int version; +#ifdef __uClinux__ + int status_extension; +#endif + int gregs[32]; +}; + +struct nios2_ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct nios2_mcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#define MD_FALLBACK_FRAME_STATE_FOR nios2_fallback_frame_state + +static _Unwind_Reason_Code +nios2_fallback_frame_state (struct _Unwind_Context *context, + _Unwind_FrameState *fs) +{ + u_int32_t *pc = (u_int32_t *) context->ra; + _Unwind_Ptr new_cfa; + + /* The expected sequence of instructions for regular Linux is: + movi r2,(sigreturn/rt_sigreturn) + trap + On uClinux, we expect: + movi r3,(sigreturn/rt_sigreturn) + mov r2, r0 + trap + Check for the trap first. */ + if (1 +#ifndef __uClinux__ + && pc[1] != 0x003b683a +#else + && pc[2] != 0x003b683a +#endif + ) + return _URC_END_OF_STACK; + +#define NIOS2_REG(NUM,NAME) \ + (fs->regs.reg[NUM].how = REG_SAVED_OFFSET, \ + fs->regs.reg[NUM].loc.offset = (_Unwind_Ptr)&(regs->NAME) - new_cfa) + + if (1 +#ifndef __uClinux__ + && pc[0] == (0x00800004 | (__NR_sigreturn << 6)) +#else + && pc[0] == (0x00c00004 | (__NR_sigreturn << 6)) + && pc[1] == 0x0005883a +#endif + ) + { + struct sigframe { + char retcode[12]; + unsigned long extramask[1]; + struct sigcontext sc; + } *rt_ = context->ra; + struct pt_regs *regs = &rt_->sc.regs; + + /* The CFA is the user's incoming stack pointer value. */ + new_cfa = (_Unwind_Ptr)(regs->sp); + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; + + /* Regs 1..15. */ + NIOS2_REG (1, r1); + NIOS2_REG (2, r2); + NIOS2_REG (3, r3); + NIOS2_REG (4, r4); + NIOS2_REG (5, r5); + NIOS2_REG (6, r6); + NIOS2_REG (7, r7); + NIOS2_REG (8, r8); + NIOS2_REG (9, r9); + NIOS2_REG (10, r10); + NIOS2_REG (11, r11); + NIOS2_REG (12, r12); + NIOS2_REG (13, r13); + NIOS2_REG (14, r14); + NIOS2_REG (15, r15); + + /* Regs 16..23 are not saved here. They are callee saved or + special. */ + + /* The random registers. */ + NIOS2_REG (RA_REGNO, ra); + NIOS2_REG (FP_REGNO, fp); + NIOS2_REG (GP_REGNO, gp); + NIOS2_REG (EA_REGNO, ea); + + fs->retaddr_column = EA_REGNO; + fs->signal_frame = 1; + + return _URC_NO_REASON; + } + else if (1 +#ifndef __uClinux__ + && pc[0] == (0x00800004 | (__NR_rt_sigreturn << 6)) +#else + && pc[0] == (0x00c00004 | (__NR_rt_sigreturn << 6)) + && pc[1] == 0x0005883a +#endif + ) + { + struct rt_sigframe { + char retcode[12]; + siginfo_t info; + struct nios2_ucontext uc; + } *rt_ = context->ra; + struct nios2_mcontext *regs = &rt_->uc.uc_mcontext; + int i; + + /* MCONTEXT_VERSION is defined to 2 in the kernel. */ + if (regs->version != 2) + return _URC_END_OF_STACK; + + /* The CFA is the user's incoming stack pointer value. */ + new_cfa = (_Unwind_Ptr)regs->gregs[28]; + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = STACK_POINTER_REGNUM; + fs->regs.cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa; + + /* The sequential registers. */ + for (i = 1; i < 24; i++) + NIOS2_REG (i, gregs[i-1]); + + /* The random registers. The kernel stores these in a funny order + in the gregs array. */ + NIOS2_REG (RA_REGNO, gregs[23]); + NIOS2_REG (FP_REGNO, gregs[24]); + NIOS2_REG (GP_REGNO, gregs[25]); + NIOS2_REG (EA_REGNO, gregs[27]); + + fs->retaddr_column = EA_REGNO; + fs->signal_frame = 1; + + return _URC_NO_REASON; + } +#undef NIOS2_REG + return _URC_END_OF_STACK; +} +#endif Index: libgcc/config/nios2/lib2-divmod-hi.c =================================================================== --- libgcc/config/nios2/lib2-divmod-hi.c (revision 0) +++ libgcc/config/nios2/lib2-divmod-hi.c (revision 0) @@ -0,0 +1,117 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + +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 +. */ + +#include "lib2-nios2.h" + +/* 16-bit HI divide and modulo as used in Nios II. */ + +static UHItype +udivmodhi4 (UHItype num, UHItype den, word_type modwanted) +{ + UHItype bit = 1; + UHItype res = 0; + + while (den < num && bit && !(den & (1L<<15))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) + return num; + return res; +} + + +HItype +__divhi3 (HItype a, HItype b) +{ + word_type neg = 0; + HItype res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodhi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + + +HItype +__modhi3 (HItype a, HItype b) +{ + word_type neg = 0; + HItype res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodhi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} + + +UHItype +__udivhi3 (UHItype a, UHItype b) +{ + return udivmodhi4 (a, b, 0); +} + + +UHItype +__umodhi3 (UHItype a, UHItype b) +{ + return udivmodhi4 (a, b, 1); +} + Index: libgcc/config/nios2/lib2-divmod.c =================================================================== --- libgcc/config/nios2/lib2-divmod.c (revision 0) +++ libgcc/config/nios2/lib2-divmod.c (revision 0) @@ -0,0 +1,117 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + +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 +. */ + +#include "lib2-nios2.h" + +/* 32-bit SI divide and modulo as used in Nios II. */ + +static USItype +udivmodsi4 (USItype num, USItype den, word_type modwanted) +{ + USItype bit = 1; + USItype res = 0; + + while (den < num && bit && !(den & (1L<<31))) + { + den <<=1; + bit <<=1; + } + while (bit) + { + if (num >= den) + { + num -= den; + res |= bit; + } + bit >>=1; + den >>=1; + } + if (modwanted) + return num; + return res; +} + + +SItype +__divsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = !neg; + } + + if (b < 0) + { + b = -b; + neg = !neg; + } + + res = udivmodsi4 (a, b, 0); + + if (neg) + res = -res; + + return res; +} + + +SItype +__modsi3 (SItype a, SItype b) +{ + word_type neg = 0; + SItype res; + + if (a < 0) + { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4 (a, b, 1); + + if (neg) + res = -res; + + return res; +} + + +SItype +__udivsi3 (SItype a, SItype b) +{ + return udivmodsi4 (a, b, 0); +} + + +SItype +__umodsi3 (SItype a, SItype b) +{ + return udivmodsi4 (a, b, 1); +} + Index: libgcc/config/nios2/linux-atomic.c =================================================================== --- libgcc/config/nios2/linux-atomic.c (revision 0) +++ libgcc/config/nios2/linux-atomic.c (revision 0) @@ -0,0 +1,302 @@ +/* Linux-specific atomic operations for Nios II Linux. + Copyright (C) 2008-2013 Free Software Foundation, Inc. + +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 +. */ + +#include +#define EFAULT 14 +#define EBUSY 16 +#define ENOSYS 38 + +/* We implement byte, short and int versions of each atomic operation + using the kernel helper defined below. There is no support for + 64-bit operations yet. */ + +/* Crash a userspace program with SIGSEV. */ +#define ABORT_INSTRUCTION asm ("stw zero, 0(zero)") + +/* Kernel helper for compare-and-exchange a 32-bit value. */ +static inline long +__kernel_cmpxchg (int oldval, int newval, int *mem) +{ + register int r2 asm ("r2") = __NR_nios2cmpxchg; + register unsigned long lws_mem asm ("r4") = (unsigned long) (mem); + register int lws_old asm ("r5") = oldval; + register int lws_new asm ("r6") = newval; + register int err asm ("r7"); + asm volatile ("trap" + : "=r" (r2), "=r" (err) + : "r" (r2), "r" (lws_mem), "r" (lws_old), "r" (lws_new) + : "r1", "r3", "r8", "r9", "r10", "r11", "r12", "r13", "r14", + "r15", "r29", "memory"); + + /* If the kernel LWS call succeeded (err == 0), r2 contains the old value + from memory. If this value is equal to OLDVAL, the new value was written + to memory. If not, return EBUSY. */ + if (__builtin_expect (err, 0)) + { + if (__builtin_expect (r2 == EFAULT || r2 == ENOSYS, 0)) + ABORT_INSTRUCTION; + } + else + { + if (__builtin_expect (r2 != oldval, 0)) + r2 = EBUSY; + else + r2 = 0; + } + + return r2; +} + +#define HIDDEN __attribute__ ((visibility ("hidden"))) + +#ifdef __nios2_little_endian__ +#define INVERT_MASK_1 0 +#define INVERT_MASK_2 0 +#else +#define INVERT_MASK_1 24 +#define INVERT_MASK_2 16 +#endif + +#define MASK_1 0xffu +#define MASK_2 0xffffu + +#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \ + int HIDDEN \ + __sync_fetch_and_##OP##_4 (int *ptr, int val) \ + { \ + int failure, tmp; \ + \ + do { \ + tmp = *ptr; \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ + } while (failure != 0); \ + \ + return tmp; \ + } + +FETCH_AND_OP_WORD (add, , +) +FETCH_AND_OP_WORD (sub, , -) +FETCH_AND_OP_WORD (or, , |) +FETCH_AND_OP_WORD (and, , &) +FETCH_AND_OP_WORD (xor, , ^) +FETCH_AND_OP_WORD (nand, ~, &) + +#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH +#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH + +/* Implement both __sync__and_fetch and __sync_fetch_and_ for + subword-sized quantities. */ + +#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \ + TYPE HIDDEN \ + NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val) \ + { \ + int *wordptr = (int *) ((unsigned long) ptr & ~3); \ + unsigned int mask, shift, oldval, newval; \ + int failure; \ + \ + shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + do { \ + oldval = *wordptr; \ + newval = ((PFX_OP (((oldval & mask) >> shift) \ + INF_OP (unsigned int) val)) << shift) & mask; \ + newval |= oldval & ~mask; \ + failure = __kernel_cmpxchg (oldval, newval, wordptr); \ + } while (failure != 0); \ + \ + return (RETURN & mask) >> shift; \ + } + +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval) + +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval) + +#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \ + int HIDDEN \ + __sync_##OP##_and_fetch_4 (int *ptr, int val) \ + { \ + int tmp, failure; \ + \ + do { \ + tmp = *ptr; \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ + } while (failure != 0); \ + \ + return PFX_OP (tmp INF_OP val); \ + } + +OP_AND_FETCH_WORD (add, , +) +OP_AND_FETCH_WORD (sub, , -) +OP_AND_FETCH_WORD (or, , |) +OP_AND_FETCH_WORD (and, , &) +OP_AND_FETCH_WORD (xor, , ^) +OP_AND_FETCH_WORD (nand, ~, &) + +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval) + +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval) + +int HIDDEN +__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) +{ + int actual_oldval, fail; + + while (1) + { + actual_oldval = *ptr; + + if (oldval != actual_oldval) + return actual_oldval; + + fail = __kernel_cmpxchg (actual_oldval, newval, ptr); + + if (!fail) + return oldval; + } +} + +#define SUBWORD_VAL_CAS(TYPE, WIDTH) \ + TYPE HIDDEN \ + __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ + TYPE newval) \ + { \ + int *wordptr = (int *)((unsigned long) ptr & ~3), fail; \ + unsigned int mask, shift, actual_oldval, actual_newval; \ + \ + shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + while (1) \ + { \ + actual_oldval = *wordptr; \ + \ + if (((actual_oldval & mask) >> shift) != (unsigned int) oldval) \ + return (actual_oldval & mask) >> shift; \ + \ + actual_newval = (actual_oldval & ~mask) \ + | (((unsigned int) newval << shift) & mask); \ + \ + fail = __kernel_cmpxchg (actual_oldval, actual_newval, \ + wordptr); \ + \ + if (!fail) \ + return oldval; \ + } \ + } + +SUBWORD_VAL_CAS (unsigned short, 2) +SUBWORD_VAL_CAS (unsigned char, 1) + +typedef unsigned char bool; + +bool HIDDEN +__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) +{ + int failure = __kernel_cmpxchg (oldval, newval, ptr); + return (failure == 0); +} + +#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \ + bool HIDDEN \ + __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ + TYPE newval) \ + { \ + TYPE actual_oldval \ + = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \ + return (oldval == actual_oldval); \ + } + +SUBWORD_BOOL_CAS (unsigned short, 2) +SUBWORD_BOOL_CAS (unsigned char, 1) + +int HIDDEN +__sync_lock_test_and_set_4 (int *ptr, int val) +{ + int failure, oldval; + + do { + oldval = *ptr; + failure = __kernel_cmpxchg (oldval, val, ptr); + } while (failure != 0); + + return oldval; +} + +#define SUBWORD_TEST_AND_SET(TYPE, WIDTH) \ + TYPE HIDDEN \ + __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \ + { \ + int failure; \ + unsigned int oldval, newval, shift, mask; \ + int *wordptr = (int *) ((unsigned long) ptr & ~3); \ + \ + shift = (((unsigned long) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + do { \ + oldval = *wordptr; \ + newval = (oldval & ~mask) \ + | (((unsigned int) val << shift) & mask); \ + failure = __kernel_cmpxchg (oldval, newval, wordptr); \ + } while (failure != 0); \ + \ + return (oldval & mask) >> shift; \ + } + +SUBWORD_TEST_AND_SET (unsigned short, 2) +SUBWORD_TEST_AND_SET (unsigned char, 1) + +#define SYNC_LOCK_RELEASE(TYPE, WIDTH) \ + void HIDDEN \ + __sync_lock_release_##WIDTH (TYPE *ptr) \ + { \ + /* All writes before this point must be seen before we release \ + the lock itself. */ \ + __builtin_sync (); \ + *ptr = 0; \ + } + +SYNC_LOCK_RELEASE (int, 4) +SYNC_LOCK_RELEASE (short, 2) +SYNC_LOCK_RELEASE (char, 1) Index: libgcc/config/nios2/t-nios2 =================================================================== --- libgcc/config/nios2/t-nios2 (revision 0) +++ libgcc/config/nios2/t-nios2 (revision 0) @@ -0,0 +1,5 @@ +LIB2ADD += $(srcdir)/config/nios2/lib2-divmod.c \ + $(srcdir)/config/nios2/lib2-divmod-hi.c \ + $(srcdir)/config/nios2/lib2-divtable.c \ + $(srcdir)/config/nios2/lib2-mul.c \ + $(srcdir)/config/nios2/tramp.c Index: libgcc/config/nios2/t-linux =================================================================== --- libgcc/config/nios2/t-linux (revision 0) +++ libgcc/config/nios2/t-linux (revision 0) @@ -0,0 +1,7 @@ +# Soft-float functions go in glibc only, to facilitate the possible +# future addition of exception and rounding mode support integrated +# with . + +LIB2FUNCS_EXCLUDE = _floatdidf _floatdisf _fixunsdfsi _fixunssfsi \ + _fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _floatundidf _floatundisf +LIB2ADD += $(srcdir)/config/nios2/linux-atomic.c Index: libgcc/config/nios2/lib2-divtable.c =================================================================== --- libgcc/config/nios2/lib2-divtable.c (revision 0) +++ libgcc/config/nios2/lib2-divtable.c (revision 0) @@ -0,0 +1,60 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + +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 +. */ + +#include "lib2-nios2.h" + +UQItype __divsi3_table[] = +{ + 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, + 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15, + 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, + 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15, + 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, + 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15, + 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, + 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15, + 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, + 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15, + 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, + 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15, + 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, + 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15, + 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, + 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15, + 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, + 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15, + 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, + 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15, + 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, + 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15, + 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, + 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15, + 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, + 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15, + 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, + 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15, + 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, + 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15, + 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, + 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15, +}; + Index: libgcc/config/nios2/crti.S =================================================================== --- libgcc/config/nios2/crti.S (revision 0) +++ libgcc/config/nios2/crti.S (revision 0) @@ -0,0 +1,88 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Jonah Graham (jgraham@altera.com). + Contributed by Mentor Graphics, Inc. + +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 +. */ + + +/* This file just make a stack frame for the contents of the .fini and +.init sections. Users may put any desired instructions in those +sections. + +While technically any code can be put in the init and fini sections +most stuff will not work other than stuff which obeys the call frame +and ABI. All the call-preserved registers are saved, the call clobbered +registers should have been saved by the code calling init and fini. + +See crtstuff.c for an example of code that inserts itself in the +init and fini sections. + +See crt0.s for the code that calls init and fini. +*/ + + .file "crti.asm" + + .section ".init" + .align 2 + .global _init +_init: + addi sp, sp, -48 + stw ra, 44(sp) + stw r23, 40(sp) + stw r22, 36(sp) + stw r21, 32(sp) + stw r20, 28(sp) + stw r19, 24(sp) + stw r18, 20(sp) + stw r17, 16(sp) + stw r16, 12(sp) + stw fp, 8(sp) + addi fp, sp, 8 +#ifdef linux + nextpc r22 +1: movhi r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b) + addi r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b) + add r22, r22, r2 +#endif + + + .section ".fini" + .align 2 + .global _fini +_fini: + addi sp, sp, -48 + stw ra, 44(sp) + stw r23, 40(sp) + stw r22, 36(sp) + stw r21, 32(sp) + stw r20, 28(sp) + stw r19, 24(sp) + stw r18, 20(sp) + stw r17, 16(sp) + stw r16, 12(sp) + stw fp, 8(sp) + addi fp, sp, 8 +#ifdef linux + nextpc r22 +1: movhi r2, %hiadj(_GLOBAL_OFFSET_TABLE_ - 1b) + addi r2, r2, %lo(_GLOBAL_OFFSET_TABLE_ - 1b) + add r22, r22, r2 +#endif + Index: libgcc/config/nios2/tramp.c =================================================================== --- libgcc/config/nios2/tramp.c (revision 0) +++ libgcc/config/nios2/tramp.c (revision 0) @@ -0,0 +1,61 @@ +/* Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + +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 +. */ + +/* Set up trampolines. + R12 is the static chain register. + R2 is AT, the assembler temporary. + The trampoline code looks like: + movhi r12,%hi(chain) + ori r12,%lo(chain) + movhi r2,%hi(fn) + ori r2,%lo(fn) + jmp r2 +*/ + +#define SC_REGNO 12 + +#define MOVHI(reg,imm16) \ + (((reg) << 22) | ((imm16) << 6) | 0x34) +#define ORI(reg,imm16) \ + (((reg) << 27) | ((reg) << 22) | ((imm16) << 6) | 0x14) +#define JMP(reg) \ + (((reg) << 27) | (0x0d << 11) | 0x3a) + +void +__trampoline_setup (unsigned int *addr, void *fnptr, void *chainptr) +{ + unsigned int fn = (unsigned int) fnptr; + unsigned int chain = (unsigned int) chainptr; + int i; + + addr[0] = MOVHI (SC_REGNO, ((chain >> 16) & 0xffff)); + addr[1] = ORI (SC_REGNO, (chain & 0xffff)); + addr[2] = MOVHI (2, ((fn >> 16) & 0xffff)); + addr[3] = ORI (2, (fn & 0xffff)); + addr[4] = JMP (2); + + /* Flush the caches. + See Example 9-4 in the Nios II Software Developer's Handbook. */ + for (i = 0; i < 5; i++) + asm volatile ("flushd 0(%0); flushi %0" :: "r"(addr + i) : "memory"); + asm volatile ("flushp" ::: "memory"); +} Index: libgcc/config/nios2/lib2-mul.c =================================================================== --- libgcc/config/nios2/lib2-mul.c (revision 0) +++ libgcc/config/nios2/lib2-mul.c (revision 0) @@ -0,0 +1,42 @@ +/* Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Altera and Mentor Graphics, Inc. + +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 +. */ + +#include "lib2-nios2.h" + +/* 32-bit SI multiply for Nios II. */ + +SItype +__mulsi3 (SItype a, SItype b) +{ + SItype res = 0; + USItype cnt = a; + + while (cnt) + { + if (cnt & 1) + res += b; + b <<= 1; + cnt >>= 1; + } + + return res; +} Index: libgcc/config.host =================================================================== --- libgcc/config.host (revision 200946) +++ libgcc/config.host (working copy) @@ -137,6 +137,9 @@ mips*-*-*) cpu_type=mips tmake_file=mips/t-mips ;; +nios2*-*-*) + cpu_type=nios2 + ;; powerpc*-*-*) cpu_type=rs6000 ;; @@ -832,6 +835,15 @@ moxie-*-rtems*) # Don't use default. extra_parts= ;; +nios2-*-linux*) + tmake_file="$tmake_file nios2/t-nios2 nios2/t-linux t-libgcc-pic t-slibgcc-libgcc" + extra_parts="$extra_parts crti.o crtn.o" + md_unwind_header=nios2/linux-unwind.h + ;; +nios2-*-*) + tmake_file="$tmake_file nios2/t-nios2 t-softfp-sfdf t-softfp-excl t-softfp" + extra_parts="$extra_parts crti.o crtn.o" + ;; pdp11-*-*) tmake_file="pdp11/t-pdp11 t-fdpbit" ;;