···11+/*22+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>33+ * Copyright (C) 2004 Microtronix Datacom Ltd.44+ *55+ * This file is subject to the terms and conditions of the GNU General Public66+ * License. See the file "COPYING" in the main directory of this archive77+ * for more details.88+ */99+1010+#ifndef _ASM_NIOS_CHECKSUM_H1111+#define _ASM_NIOS_CHECKSUM_H1212+1313+/* Take these from lib/checksum.c */1414+extern __wsum csum_partial(const void *buff, int len, __wsum sum);1515+extern __wsum csum_partial_copy(const void *src, void *dst, int len,1616+ __wsum sum);1717+extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst,1818+ int len, __wsum sum, int *csum_err);1919+#define csum_partial_copy_nocheck(src, dst, len, sum) \2020+ csum_partial_copy((src), (dst), (len), (sum))2121+2222+extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl);2323+extern __sum16 ip_compute_csum(const void *buff, int len);2424+2525+/*2626+ * Fold a partial checksum2727+ */2828+static inline __sum16 csum_fold(__wsum sum)2929+{3030+ __asm__ __volatile__(3131+ "add %0, %1, %0\n"3232+ "cmpltu r8, %0, %1\n"3333+ "srli %0, %0, 16\n"3434+ "add %0, %0, r8\n"3535+ "nor %0, %0, %0\n"3636+ : "=r" (sum)3737+ : "r" (sum << 16), "0" (sum)3838+ : "r8");3939+ return (__force __sum16) sum;4040+}4141+4242+/*4343+ * computes the checksum of the TCP/UDP pseudo-header4444+ * returns a 16-bit checksum, already complemented4545+ */4646+#define csum_tcpudp_nofold csum_tcpudp_nofold4747+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,4848+ unsigned short len,4949+ unsigned short proto,5050+ __wsum sum)5151+{5252+ __asm__ __volatile__(5353+ "add %0, %1, %0\n"5454+ "cmpltu r8, %0, %1\n"5555+ "add %0, %0, r8\n" /* add carry */5656+ "add %0, %2, %0\n"5757+ "cmpltu r8, %0, %2\n"5858+ "add %0, %0, r8\n" /* add carry */5959+ "add %0, %3, %0\n"6060+ "cmpltu r8, %0, %3\n"6161+ "add %0, %0, r8\n" /* add carry */6262+ : "=r" (sum), "=r" (saddr)6363+ : "r" (daddr), "r" ((ntohs(len) << 16) + (proto * 256)),6464+ "0" (sum),6565+ "1" (saddr)6666+ : "r8");6767+6868+ return sum;6969+}7070+7171+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,7272+ unsigned short len,7373+ unsigned short proto, __wsum sum)7474+{7575+ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));7676+}7777+7878+#endif /* _ASM_NIOS_CHECKSUM_H */
+24
arch/nios2/include/asm/string.h
···11+/*22+ * Copyright (C) 2004 Microtronix Datacom Ltd33+ *44+ * This file is subject to the terms and conditions of the GNU General Public55+ * License. See the file "COPYING" in the main directory of this archive66+ * for more details.77+ */88+99+#ifndef _ASM_NIOS2_STRING_H1010+#define _ASM_NIOS2_STRING_H1111+1212+#ifdef __KERNEL__1313+1414+#define __HAVE_ARCH_MEMSET1515+#define __HAVE_ARCH_MEMCPY1616+#define __HAVE_ARCH_MEMMOVE1717+1818+extern void *memset(void *s, int c, size_t count);1919+extern void *memcpy(void *d, const void *s, size_t count);2020+extern void *memmove(void *d, const void *s, size_t count);2121+2222+#endif /* __KERNEL__ */2323+2424+#endif /* _ASM_NIOS2_STRING_H */
+202
arch/nios2/lib/memcpy.c
···11+/* Extracted from GLIBC memcpy.c and memcopy.h, which is:22+ Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc.33+ This file is part of the GNU C Library.44+ Contributed by Torbjorn Granlund (tege@sics.se).55+66+ The GNU C Library is free software; you can redistribute it and/or77+ modify it under the terms of the GNU Lesser General Public88+ License as published by the Free Software Foundation; either99+ version 2.1 of the License, or (at your option) any later version.1010+1111+ The GNU C Library is distributed in the hope that it will be useful,1212+ but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU1414+ Lesser General Public License for more details.1515+1616+ You should have received a copy of the GNU Lesser General Public1717+ License along with the GNU C Library; if not, see1818+ <http://www.gnu.org/licenses/>. */1919+2020+#include <linux/types.h>2121+2222+/* Type to use for aligned memory operations.2323+ This should normally be the biggest type supported by a single load2424+ and store. */2525+#define op_t unsigned long int2626+#define OPSIZ (sizeof(op_t))2727+2828+/* Optimal type for storing bytes in registers. */2929+#define reg_char char3030+3131+#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))3232+3333+/* Copy exactly NBYTES bytes from SRC_BP to DST_BP,3434+ without any assumptions about alignment of the pointers. */3535+#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \3636+do { \3737+ size_t __nbytes = (nbytes); \3838+ while (__nbytes > 0) { \3939+ unsigned char __x = ((unsigned char *) src_bp)[0]; \4040+ src_bp += 1; \4141+ __nbytes -= 1; \4242+ ((unsigned char *) dst_bp)[0] = __x; \4343+ dst_bp += 1; \4444+ } \4545+} while (0)4646+4747+/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with4848+ the assumption that DST_BP is aligned on an OPSIZ multiple. If4949+ not all bytes could be easily copied, store remaining number of bytes5050+ in NBYTES_LEFT, otherwise store 0. */5151+/* extern void _wordcopy_fwd_aligned __P ((long int, long int, size_t)); */5252+/* extern void _wordcopy_fwd_dest_aligned __P ((long int, long int, size_t)); */5353+#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \5454+do { \5555+ if (src_bp % OPSIZ == 0) \5656+ _wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);\5757+ else \5858+ _wordcopy_fwd_dest_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);\5959+ src_bp += (nbytes) & -OPSIZ; \6060+ dst_bp += (nbytes) & -OPSIZ; \6161+ (nbytes_left) = (nbytes) % OPSIZ; \6262+} while (0)6363+6464+6565+/* Threshold value for when to enter the unrolled loops. */6666+#define OP_T_THRES 166767+6868+/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to6969+ block beginning at DSTP with LEN `op_t' words (not LEN bytes!).7070+ Both SRCP and DSTP should be aligned for memory operations on `op_t's. */7171+/* stream-lined (read x8 + write x8) */7272+static void _wordcopy_fwd_aligned(long int dstp, long int srcp, size_t len)7373+{7474+ while (len > 7) {7575+ register op_t a0, a1, a2, a3, a4, a5, a6, a7;7676+7777+ a0 = ((op_t *) srcp)[0];7878+ a1 = ((op_t *) srcp)[1];7979+ a2 = ((op_t *) srcp)[2];8080+ a3 = ((op_t *) srcp)[3];8181+ a4 = ((op_t *) srcp)[4];8282+ a5 = ((op_t *) srcp)[5];8383+ a6 = ((op_t *) srcp)[6];8484+ a7 = ((op_t *) srcp)[7];8585+ ((op_t *) dstp)[0] = a0;8686+ ((op_t *) dstp)[1] = a1;8787+ ((op_t *) dstp)[2] = a2;8888+ ((op_t *) dstp)[3] = a3;8989+ ((op_t *) dstp)[4] = a4;9090+ ((op_t *) dstp)[5] = a5;9191+ ((op_t *) dstp)[6] = a6;9292+ ((op_t *) dstp)[7] = a7;9393+9494+ srcp += 8 * OPSIZ;9595+ dstp += 8 * OPSIZ;9696+ len -= 8;9797+ }9898+ while (len > 0) {9999+ *(op_t *)dstp = *(op_t *)srcp;100100+101101+ srcp += OPSIZ;102102+ dstp += OPSIZ;103103+ len -= 1;104104+ }105105+}106106+107107+/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to108108+ block beginning at DSTP with LEN `op_t' words (not LEN bytes!).109109+ DSTP should be aligned for memory operations on `op_t's, but SRCP must110110+ *not* be aligned. */111111+/* stream-lined (read x4 + write x4) */112112+static void _wordcopy_fwd_dest_aligned(long int dstp, long int srcp,113113+ size_t len)114114+{115115+ op_t ap;116116+ int sh_1, sh_2;117117+118118+ /* Calculate how to shift a word read at the memory operation119119+ aligned srcp to make it aligned for copy. */120120+121121+ sh_1 = 8 * (srcp % OPSIZ);122122+ sh_2 = 8 * OPSIZ - sh_1;123123+124124+ /* Make SRCP aligned by rounding it down to the beginning of the `op_t'125125+ it points in the middle of. */126126+ srcp &= -OPSIZ;127127+ ap = ((op_t *) srcp)[0];128128+ srcp += OPSIZ;129129+130130+ while (len > 3) {131131+ op_t a0, a1, a2, a3;132132+133133+ a0 = ((op_t *) srcp)[0];134134+ a1 = ((op_t *) srcp)[1];135135+ a2 = ((op_t *) srcp)[2];136136+ a3 = ((op_t *) srcp)[3];137137+ ((op_t *) dstp)[0] = MERGE(ap, sh_1, a0, sh_2);138138+ ((op_t *) dstp)[1] = MERGE(a0, sh_1, a1, sh_2);139139+ ((op_t *) dstp)[2] = MERGE(a1, sh_1, a2, sh_2);140140+ ((op_t *) dstp)[3] = MERGE(a2, sh_1, a3, sh_2);141141+142142+ ap = a3;143143+ srcp += 4 * OPSIZ;144144+ dstp += 4 * OPSIZ;145145+ len -= 4;146146+ }147147+ while (len > 0) {148148+ register op_t a0;149149+150150+ a0 = ((op_t *) srcp)[0];151151+ ((op_t *) dstp)[0] = MERGE(ap, sh_1, a0, sh_2);152152+153153+ ap = a0;154154+ srcp += OPSIZ;155155+ dstp += OPSIZ;156156+ len -= 1;157157+ }158158+}159159+160160+void *memcpy(void *dstpp, const void *srcpp, size_t len)161161+{162162+ unsigned long int dstp = (long int) dstpp;163163+ unsigned long int srcp = (long int) srcpp;164164+165165+ /* Copy from the beginning to the end. */166166+167167+ /* If there not too few bytes to copy, use word copy. */168168+ if (len >= OP_T_THRES) {169169+ /* Copy just a few bytes to make DSTP aligned. */170170+ len -= (-dstp) % OPSIZ;171171+ BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ);172172+173173+ /* Copy whole pages from SRCP to DSTP by virtual address174174+ manipulation, as much as possible. */175175+176176+ /* PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); */177177+178178+ /* Copy from SRCP to DSTP taking advantage of the known179179+ alignment of DSTP. Number of bytes remaining is put in the180180+ third argument, i.e. in LEN. This number may vary from181181+ machine to machine. */182182+183183+ WORD_COPY_FWD(dstp, srcp, len, len);184184+185185+ /* Fall out and copy the tail. */186186+ }187187+188188+ /* There are just a few bytes to copy. Use byte memory operations. */189189+ BYTE_COPY_FWD(dstp, srcp, len);190190+191191+ return dstpp;192192+}193193+194194+void *memcpyb(void *dstpp, const void *srcpp, unsigned len)195195+{196196+ unsigned long int dstp = (long int) dstpp;197197+ unsigned long int srcp = (long int) srcpp;198198+199199+ BYTE_COPY_FWD(dstp, srcp, len);200200+201201+ return dstpp;202202+}
+82
arch/nios2/lib/memmove.c
···11+/*22+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>33+ * Copyright (C) 2004 Microtronix Datacom Ltd44+ *55+ * This file is subject to the terms and conditions of the GNU General Public66+ * License. See the file "COPYING" in the main directory of this archive77+ * for more details.88+ */99+1010+#include <linux/types.h>1111+#include <linux/string.h>1212+1313+#ifdef __HAVE_ARCH_MEMMOVE1414+void *memmove(void *d, const void *s, size_t count)1515+{1616+ unsigned long dst, src;1717+1818+ if (!count)1919+ return d;2020+2121+ if (d < s) {2222+ dst = (unsigned long) d;2323+ src = (unsigned long) s;2424+2525+ if ((count < 8) || ((dst ^ src) & 3))2626+ goto restup;2727+2828+ if (dst & 1) {2929+ *(char *)dst++ = *(char *)src++;3030+ count--;3131+ }3232+ if (dst & 2) {3333+ *(short *)dst = *(short *)src;3434+ src += 2;3535+ dst += 2;3636+ count -= 2;3737+ }3838+ while (count > 3) {3939+ *(long *)dst = *(long *)src;4040+ src += 4;4141+ dst += 4;4242+ count -= 4;4343+ }4444+restup:4545+ while (count--)4646+ *(char *)dst++ = *(char *)src++;4747+ } else {4848+ dst = (unsigned long) d + count;4949+ src = (unsigned long) s + count;5050+5151+ if ((count < 8) || ((dst ^ src) & 3))5252+ goto restdown;5353+5454+ if (dst & 1) {5555+ src--;5656+ dst--;5757+ count--;5858+ *(char *)dst = *(char *)src;5959+ }6060+ if (dst & 2) {6161+ src -= 2;6262+ dst -= 2;6363+ count -= 2;6464+ *(short *)dst = *(short *)src;6565+ }6666+ while (count > 3) {6767+ src -= 4;6868+ dst -= 4;6969+ count -= 4;7070+ *(long *)dst = *(long *)src;7171+ }7272+restdown:7373+ while (count--) {7474+ src--;7575+ dst--;7676+ *(char *)dst = *(char *)src;7777+ }7878+ }7979+8080+ return d;8181+}8282+#endif /* __HAVE_ARCH_MEMMOVE */
+81
arch/nios2/lib/memset.c
···11+/*22+ * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>33+ * Copyright (C) 2004 Microtronix Datacom Ltd44+ *55+ * This file is subject to the terms and conditions of the GNU General Public66+ * License. See the file "COPYING" in the main directory of this archive77+ * for more details.88+ */99+1010+#include <linux/types.h>1111+#include <linux/string.h>1212+1313+#ifdef __HAVE_ARCH_MEMSET1414+void *memset(void *s, int c, size_t count)1515+{1616+ int destptr, charcnt, dwordcnt, fill8reg, wrkrega;1717+1818+ if (!count)1919+ return s;2020+2121+ c &= 0xFF;2222+2323+ if (count <= 8) {2424+ char *xs = (char *) s;2525+2626+ while (count--)2727+ *xs++ = c;2828+ return s;2929+ }3030+3131+ __asm__ __volatile__ (3232+ /* fill8 %3, %5 (c & 0xff) */3333+ " slli %4, %5, 8\n"3434+ " or %4, %4, %5\n"3535+ " slli %3, %4, 16\n"3636+ " or %3, %3, %4\n"3737+ /* Word-align %0 (s) if necessary */3838+ " andi %4, %0, 0x01\n"3939+ " beq %4, zero, 1f\n"4040+ " addi %1, %1, -1\n"4141+ " stb %3, 0(%0)\n"4242+ " addi %0, %0, 1\n"4343+ "1: mov %2, %1\n"4444+ /* Dword-align %0 (s) if necessary */4545+ " andi %4, %0, 0x02\n"4646+ " beq %4, zero, 2f\n"4747+ " addi %1, %1, -2\n"4848+ " sth %3, 0(%0)\n"4949+ " addi %0, %0, 2\n"5050+ " mov %2, %1\n"5151+ /* %1 and %2 are how many more bytes to set */5252+ "2: srli %2, %2, 2\n"5353+ /* %2 is how many dwords to set */5454+ "3: stw %3, 0(%0)\n"5555+ " addi %0, %0, 4\n"5656+ " addi %2, %2, -1\n"5757+ " bne %2, zero, 3b\n"5858+ /* store residual word and/or byte if necessary */5959+ " andi %4, %1, 0x02\n"6060+ " beq %4, zero, 4f\n"6161+ " sth %3, 0(%0)\n"6262+ " addi %0, %0, 2\n"6363+ /* store residual byte if necessary */6464+ "4: andi %4, %1, 0x01\n"6565+ " beq %4, zero, 5f\n"6666+ " stb %3, 0(%0)\n"6767+ "5:\n"6868+ : "=r" (destptr), /* %0 Output */6969+ "=r" (charcnt), /* %1 Output */7070+ "=r" (dwordcnt), /* %2 Output */7171+ "=r" (fill8reg), /* %3 Output */7272+ "=r" (wrkrega) /* %4 Output */7373+ : "r" (c), /* %5 Input */7474+ "0" (s), /* %0 Input/Output */7575+ "1" (count) /* %1 Input/Output */7676+ : "memory" /* clobbered */7777+ );7878+7979+ return s;8080+}8181+#endif /* __HAVE_ARCH_MEMSET */