diff options
Diffstat (limited to 'arch/h8300/lib')
-rw-r--r-- | arch/h8300/lib/Makefile | 8 | ||||
-rw-r--r-- | arch/h8300/lib/abs.S | 21 | ||||
-rw-r--r-- | arch/h8300/lib/ashrdi3.c | 63 | ||||
-rw-r--r-- | arch/h8300/lib/checksum.c | 159 | ||||
-rw-r--r-- | arch/h8300/lib/memcpy.S | 84 | ||||
-rw-r--r-- | arch/h8300/lib/memset.S | 61 | ||||
-rw-r--r-- | arch/h8300/lib/romfs.S | 58 |
7 files changed, 454 insertions, 0 deletions
diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile new file mode 100644 index 00000000000..98272b66f4e --- /dev/null +++ b/arch/h8300/lib/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for H8/300-specific library files.. +# + +.S.o: + $(CC) $(AFLAGS) -D__ASSEMBLY__ -c $< -o $@ + +lib-y = ashrdi3.o checksum.o memcpy.o memset.o abs.o romfs.o diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S new file mode 100644 index 00000000000..cabdd46b41d --- /dev/null +++ b/arch/h8300/lib/abs.S @@ -0,0 +1,21 @@ +;;; abs.S + +#include <asm/linkage.h> + +#if defined(__H8300H__) + .h8300h +#endif +#if defined(__H8300S__) + .h8300s +#endif + .text +.global SYMBOL_NAME(abs) + +;;; int abs(int n) +SYMBOL_NAME_LABEL(abs) + mov.l er0,er0 + bpl 1f + neg.l er0 +1: + rts + diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c new file mode 100644 index 00000000000..78efb65e315 --- /dev/null +++ b/arch/h8300/lib/ashrdi3.c @@ -0,0 +1,63 @@ +/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff --git a/arch/h8300/lib/checksum.c b/arch/h8300/lib/checksum.c new file mode 100644 index 00000000000..5aa688d9242 --- /dev/null +++ b/arch/h8300/lib/checksum.c @@ -0,0 +1,159 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, <jorge@laser.satlink.net> + * Arnt Gulbrandsen, <agulbra@nvg.unit.no> + * Tom May, <ftom@netcom.com> + * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: + * Fixed some nasty bugs, causing some horrible crashes. + * A: At some points, the sum (%0) was used as + * length-counter instead of the length counter + * (%1). Thanks to Roman Hodek for pointing this out. + * B: GCC seems to mess up if one uses too many + * data-registers to hold input values and one tries to + * specify d0 and d1 as scratch registers. Letting gcc choose these + * registers itself solves the problem. + * + * 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 + * 2 of the License, or (at your option) any later version. + */ + +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most + of the assembly has to go. */ + +#include <net/checksum.h> +#include <linux/module.h> + +static inline unsigned short from32to16(unsigned long x) +{ + /* add up 16-bit and 16-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static unsigned long do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) +{ + return ~do_csum(iph,ihl*4); +} + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) +{ + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + /* 16+c bits -> 16 bits */ + result = (result & 0xffff) + (result >> 16); + return result; +} + +EXPORT_SYMBOL(csum_partial); + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +unsigned short ip_compute_csum(const unsigned char * buff, int len) +{ + return ~do_csum(buff,len); +} + +/* + * copy from fs while checksumming, otherwise like csum_partial + */ + +unsigned int +csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err) +{ + if (csum_err) *csum_err = 0; + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} + +/* + * copy from ds while checksumming, otherwise like csum_partial + */ + +unsigned int +csum_partial_copy(const char *src, char *dst, int len, int sum) +{ + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S new file mode 100644 index 00000000000..fdcbc1ee673 --- /dev/null +++ b/arch/h8300/lib/memcpy.S @@ -0,0 +1,84 @@ +;;; memcpy.S + +#include <asm/linkage.h> + +#if defined(__H8300H__) + .h8300h +#endif +#if defined(__H8300S__) + .h8300s +#endif + + .text +.global SYMBOL_NAME(memcpy) + +;;; void *memcpy(void *to, void *from, size_t n) +SYMBOL_NAME_LABEL(memcpy) + mov.l er2,er2 + bne 1f + rts +1: + ;; address check + bld #0,r0l + bxor #0,r1l + bcs 4f + mov.l er4,@-sp + mov.l er0,@-sp + btst #0,r0l + beq 1f + ;; (aligned even) odd address + mov.b @er1,r3l + mov.b r3l,@er0 + adds #1,er1 + adds #1,er0 + dec.l #1,er2 + beq 3f +1: + ;; n < sizeof(unsigned long) check + sub.l er4,er4 + adds #4,er4 ; loop count check value + cmp.l er4,er2 + blo 2f + ;; unsigned long copy +1: + mov.l @er1,er3 + mov.l er3,@er0 + adds #4,er0 + adds #4,er1 + subs #4,er2 + cmp.l er4,er2 + bcc 1b + ;; rest +2: + mov.l er2,er2 + beq 3f +1: + mov.b @er1,r3l + mov.b r3l,@er0 + adds #1,er1 + adds #1,er0 + dec.l #1,er2 + bne 1b +3: + mov.l @sp+,er0 + mov.l @sp+,er4 + rts + + ;; odd <- even / even <- odd +4: + mov.l er4,er3 + mov.l er2,er4 + mov.l er5,er2 + mov.l er1,er5 + mov.l er6,er1 + mov.l er0,er6 +1: + eepmov.w + mov.w r4,r4 + bne 1b + dec.w #1,e4 + bpl 1b + mov.l er1,er6 + mov.l er2,er5 + mov.l er3,er4 + rts diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S new file mode 100644 index 00000000000..59abdf9485a --- /dev/null +++ b/arch/h8300/lib/memset.S @@ -0,0 +1,61 @@ +/* memset.S */ + +#include <asm/linkage.h> + +#if defined(__H8300H__) + .h8300h +#endif +#if defined(__H8300S__) + .h8300s +#endif + .text + +.global SYMBOL_NAME(memset) + +;;void *memset(*ptr, int c, size_t count) +;; ptr = er0 +;; c = er1(r1l) +;; count = er2 +SYMBOL_NAME_LABEL(memset) + btst #0,r0l + beq 2f + + ;; odd address +1: + mov.b r1l,@er0 + adds #1,er0 + dec.l #1,er2 + beq 6f + + ;; even address +2: + mov.l er2,er3 + cmp.l #4,er2 + blo 4f + ;; count>=4 -> count/4 +#if defined(__H8300H__) + shlr.l er2 + shlr.l er2 +#endif +#if defined(__H8300S__) + shlr.l #2,er2 +#endif + ;; byte -> long + mov.b r1l,r1h + mov.w r1,e1 +3: + mov.l er1,@er0 + adds #4,er0 + dec.l #1,er2 + bne 3b +4: + ;; count % 4 + and.b #3,r3l + beq 6f +5: + mov.b r1l,@er0 + adds #1,er0 + dec.b r3l + bne 5b +6: + rts diff --git a/arch/h8300/lib/romfs.S b/arch/h8300/lib/romfs.S new file mode 100644 index 00000000000..b72f93a47e3 --- /dev/null +++ b/arch/h8300/lib/romfs.S @@ -0,0 +1,58 @@ +/* romfs move to __ebss */ + +#include <asm/linkage.h> +#include <linux/config.h> + +#if defined(__H8300H__) + .h8300h +#endif +#if defined(__H8300S__) + .h8300s +#endif + +#define BLKOFFSET 512 + + .text +.globl __move_romfs +_romfs_sig_len = 8 + +__move_romfs: + mov.l #__sbss,er0 + mov.l #_romfs_sig,er1 + mov.b #_romfs_sig_len,r3l +1: /* check romfs image */ + mov.b @er0+,r2l + mov.b @er1+,r2h + cmp.b r2l,r2h + bne 2f + dec.b r3l + bne 1b + + /* find romfs image */ + mov.l @__sbss+8,er0 /* romfs length(be) */ + mov.l #__sbss,er1 + add.l er0,er1 /* romfs image end */ + mov.l #__ebss,er2 + add.l er0,er2 /* distination address */ +#if defined(CONFIG_INTELFLASH) + add.l #BLKOFFSET,er2 +#endif + adds #2,er0 + adds #1,er0 + shlr er0 + shlr er0 /* transfer length */ +1: + mov.l @er1,er3 /* copy image */ + mov.l er3,@er2 + subs #4,er1 + subs #4,er2 + dec.l #1,er0 + bpl 1b +2: + rts + + .section .rodata +_romfs_sig: + .ascii "-rom1fs-" + + .end |