summaryrefslogtreecommitdiffstats
path: root/arch/s390/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/lib')
-rw-r--r--arch/s390/lib/Makefile12
-rw-r--r--arch/s390/lib/checksum.c56
-rw-r--r--arch/s390/lib/delay.c45
-rw-r--r--arch/s390/lib/memset.S30
-rw-r--r--arch/s390/lib/strcmp.S27
-rw-r--r--arch/s390/lib/strncpy.S30
6 files changed, 200 insertions, 0 deletions
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
new file mode 100644
index 000000000..aa8b0e5da
--- /dev/null
+++ b/arch/s390/lib/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for s390-specific library files..
+#
+
+.S.o:
+ $(CC) $(AFLAGS) -traditional -c $< -o $*.o
+
+L_TARGET = lib.a
+L_OBJS = checksum.o delay.o memset.o strcmp.o strncpy.o
+
+include $(TOPDIR)/Rules.make
+
diff --git a/arch/s390/lib/checksum.c b/arch/s390/lib/checksum.c
new file mode 100644
index 000000000..9411e1c5e
--- /dev/null
+++ b/arch/s390/lib/checksum.c
@@ -0,0 +1,56 @@
+/*
+ * arch/s390/lib/checksum.c
+ * S390 fast network checksum routines
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Ulrich Hild (first version),
+ * Martin Schwidefsky (schwidefsky@de.ibm.com),
+ * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ * This file contains network checksum routines
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+#include <asm/checksum.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+unsigned int
+csum_partial (const unsigned char *buff, int len, unsigned int sum)
+{
+ /*
+ * Experiments with ethernet and slip connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary.
+ */
+ __asm__ __volatile__ (
+ " lr 2,%1\n" /* address in gpr 2 */
+ " lr 3,%2\n" /* length in gpr 3 */
+ "0: cksm %0,2\n" /* do checksum on longs */
+ " jo 0b\n"
+ : "+&d" (sum)
+ : "d" (buff), "d" (len)
+ : "cc", "2", "3" );
+ return sum;
+}
+
+/*
+ * Fold a partial checksum without adding pseudo headers
+ */
+unsigned short csum_fold(unsigned int sum)
+{
+ __asm__ __volatile__ (
+ " sr 3,3\n" /* %0 = H*65536 + L */
+ " lr 2,%0\n" /* %0 = H L, R2/R3 = H L / 0 0 */
+ " srdl 2,16\n" /* %0 = H L, R2/R3 = 0 H / L 0 */
+ " alr 2,3\n" /* %0 = H L, R2/R3 = L H / L 0 */
+ " alr %0,2\n" /* %0 = H+L+C L+H */
+ " srl %0,16\n" /* %0 = H+L+C */
+ : "+d" (sum) : : "cc", "2", "3");
+ return ((unsigned short) ~sum);
+}
+
diff --git a/arch/s390/lib/delay.c b/arch/s390/lib/delay.c
new file mode 100644
index 000000000..ec3274487
--- /dev/null
+++ b/arch/s390/lib/delay.c
@@ -0,0 +1,45 @@
+/*
+ * arch/s390/kernel/delay.c
+ * Precise Delay Loops for S390
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ * Derived from "arch/i386/lib/delay.c"
+ * Copyright (C) 1993 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+void __delay(unsigned long loops)
+{
+ __asm__ __volatile__(
+ "0: ahi %0,-1\n"
+ " jnm 0b"
+ : /* no outputs */ : "r" (loops) );
+}
+
+inline void __const_udelay(unsigned long xloops)
+{
+
+ __asm__("LR 3,%1\n\t"
+ "MR 2,%2\n\t"
+ "LR %0,2\n\t"
+ : "=r" (xloops)
+ : "r" (xloops) , "r" (loops_per_sec)
+ : "2" , "3");
+ __delay(xloops);
+}
+
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * 0x000010c6); /* 2**32 / 1000000 */
+}
diff --git a/arch/s390/lib/memset.S b/arch/s390/lib/memset.S
new file mode 100644
index 000000000..447af53f8
--- /dev/null
+++ b/arch/s390/lib/memset.S
@@ -0,0 +1,30 @@
+/*
+ * arch/s390/lib/memset.S
+ * S390 fast memset routine
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address to memory area
+ * R3 = byte to fill memory with
+ * R4 = number of bytes to fill
+ */
+ .globl memset
+memset:
+ LTR 4,4
+ JZ memset_end
+ LR 0,2 # save pointer to memory area
+ LR 1,3 # move pad byte to R1
+ LR 3,4
+ SR 4,4 # no source for MVCLE, only a pad byte
+ SR 5,5
+ MVCLE 2,4,0(1) # thats it, MVCLE is your friend
+ JO .-4
+ LR 2,0 # return pointer to mem.
+memset_end:
+ BR 14
+
+
diff --git a/arch/s390/lib/strcmp.S b/arch/s390/lib/strcmp.S
new file mode 100644
index 000000000..d3f63942f
--- /dev/null
+++ b/arch/s390/lib/strcmp.S
@@ -0,0 +1,27 @@
+/*
+ * arch/s390/lib/strcmp.S
+ * S390 strcmp routine
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of compare string
+ * R3 = address of test string
+ */
+ .globl strcmp
+strcmp:
+ SR 0,0
+ SR 1,1
+ CLST 2,3
+ JO .-4
+ JE strcmp_equal
+ IC 0,0(0,3)
+ IC 1,0(0,2)
+ SR 1,0
+strcmp_equal:
+ LR 2,1
+ BR 14
+
diff --git a/arch/s390/lib/strncpy.S b/arch/s390/lib/strncpy.S
new file mode 100644
index 000000000..83578909c
--- /dev/null
+++ b/arch/s390/lib/strncpy.S
@@ -0,0 +1,30 @@
+/*
+ * arch/s390/kernel/strncpy.S
+ * S390 strncpy routine
+ *
+ * S390 version
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of destination
+ * R3 = address of source string
+ * R4 = max number of bytes to copy
+ */
+ .globl strncpy
+strncpy:
+ LR 1,2 # don't touch address in R2
+ LTR 4,4
+ JZ strncpy_exit # 0 bytes -> nothing to do
+ SR 0,0
+strncpy_loop:
+ ICM 0,1,0(3) # ICM sets the cc, IC does not
+ LA 3,1(0,3)
+ STC 0,0(0,1)
+ LA 1,1(0,1)
+ JZ strncpy_exit # ICM inserted a 0x00
+ BRCT 4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0
+strncpy_exit:
+ BR 14
+