Initial commit

This commit is contained in:
Ole André Vadla Ravnås 2022-05-07 01:01:45 +02:00
commit 169c65d57e
51358 changed files with 23120455 additions and 0 deletions

View file

@ -0,0 +1,7 @@
#
# Makefile for the MN10300-specific library files..
#
lib-y = delay.o usercopy.o checksum.o bitops.o memcpy.o memmove.o memset.o
lib-y += do_csum.o
lib-y += __ashldi3.o __ashrdi3.o __lshrdi3.o negdi2.o __ucmpdi2.o

View file

@ -0,0 +1,51 @@
/* MN10300 64-bit arithmetic left shift
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.text
.balign L1_CACHE_BYTES
###############################################################################
#
# unsigned long long __ashldi3(unsigned long long value [D1:D0],
# unsigned by [(12,SP)])
#
###############################################################################
.globl __ashldi3
.type __ashldi3,@function
__ashldi3:
mov (12,sp),a0
and +63,a0
beq __ashldi3_zero
cmp +31,a0
bhi __ashldi3_32plus
# the count is in the range 1-31
asl a0,d1
mov +32,a1
sub a0,a1,a1 # a1 = 32 - count
lsr a1,d0,a1 # get overflow from LSW -> MSW
or_asl a1,d1,a0,d0 # insert overflow into MSW and
# shift the LSW
rets
.balign L1_CACHE_BYTES
# the count is in the range 32-63
__ashldi3_32plus:
asl a0,d0,d1
clr d0
__ashldi3_zero:
rets
.size __ashldi3, .-__ashldi3

View file

@ -0,0 +1,52 @@
/* MN10300 64-bit arithmetic right shift
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.text
.balign L1_CACHE_BYTES
###############################################################################
#
# unsigned long long __ashrdi3(unsigned long long value [D1:D0],
# unsigned by [(12,SP)])
#
###############################################################################
.globl __ashrdi3
.type __ashrdi3,@function
__ashrdi3:
mov (12,sp),a0
and +63,a0
beq __ashrdi3_zero
cmp +31,a0
bhi __ashrdi3_32plus
# the count is in the range 1-31
lsr a0,d0
mov +32,a1
sub a0,a1,a1 # a1 = 32 - count
asl a1,d1,a1 # get underflow from MSW -> LSW
or_asr a1,d0,a0,d1 # insert underflow into LSW and
# shift the MSW
rets
.balign L1_CACHE_BYTES
# the count is in the range 32-63
__ashrdi3_32plus:
asr a0,d1,d0
ext d0 # sign-extend result through MDR
mov mdr,d1
__ashrdi3_zero:
rets
.size __ashrdi3, .-__ashrdi3

View file

@ -0,0 +1,52 @@
/* MN10300 64-bit logical right shift
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.text
.balign L1_CACHE_BYTES
###############################################################################
#
# unsigned long long __lshrdi3(unsigned long long value [D1:D0],
# unsigned by [(12,SP)])
#
###############################################################################
.globl __lshrdi3
.type __lshrdi3,@function
__lshrdi3:
mov (12,sp),a0
and +63,a0
beq __lshrdi3_zero
cmp +31,a0
bhi __lshrdi3_32plus
# the count is in the range 1-31
lsr a0,d0
mov +32,a1
sub a0,a1,a1 # a1 = 32 - count
asl a1,d1,a1 # get underflow from MSW -> LSW
or_lsr a1,d0,a0,d1 # insert underflow into LSW and
# shift the MSW
rets
.balign L1_CACHE_BYTES
# the count is in the range 32-63
__lshrdi3_32plus:
lsr a0,d1,d0
clr d1
__lshrdi3_zero:
rets
.size __lshrdi3, .-__lshrdi3

View file

@ -0,0 +1,43 @@
/* __ucmpdi2.S: 64-bit unsigned compare
*
* Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* 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.
*/
.text
.p2align 4
###############################################################################
#
# int __ucmpdi2(unsigned long long a [D0:D1],
# unsigned long long b [(SP,12),(SP,16)])
#
# - returns 0, 1, or 2 as a <, =, > b respectively.
#
###############################################################################
.globl __ucmpdi2
.type __ucmpdi2,@function
__ucmpdi2:
mov (12,sp),a0 # b.lsw
mov (16,sp),a1 # b.msw
sub a0,d0
subc a1,d1 # may clear Z, never sets it
bne __ucmpdi2_differ # a.msw != b.msw
mov +1,d0
rets
__ucmpdi2_differ:
# C flag is set if LE, clear if GE
subc d0,d0 # -1 if LE, 0 if GE
add +1,d0 # 0 if LE, 1 if GE
add d0,d0 # 0 if LE, 2 if GE
rets
.size __ucmpdi2, .-__ucmpdi2

View file

@ -0,0 +1,61 @@
/* 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 Licence 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 Licence for more details.
You should have received a copy of the GNU General Public Licence
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 low;
SItype high;
};
union DIunion {
struct DIstruct s;
DItype ll;
};
DItype __ashrdi3(DItype u, word_type b)
{
union DIunion w;
union DIunion uu;
word_type bm;
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;
}

50
arch/mn10300/lib/bitops.c Normal file
View file

@ -0,0 +1,50 @@
/* MN10300 Non-trivial bit operations
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/module.h>
#include <asm/bitops.h>
/*
* try flipping a bit using BSET and BCLR
*/
void change_bit(unsigned long nr, volatile void *addr)
{
if (test_bit(nr, addr))
goto try_clear_bit;
try_set_bit:
if (!test_and_set_bit(nr, addr))
return;
try_clear_bit:
if (test_and_clear_bit(nr, addr))
return;
goto try_set_bit;
}
/*
* try flipping a bit using BSET and BCLR and returning the old value
*/
int test_and_change_bit(unsigned long nr, volatile void *addr)
{
if (test_bit(nr, addr))
goto try_clear_bit;
try_set_bit:
if (!test_and_set_bit(nr, addr))
return 0;
try_clear_bit:
if (test_and_clear_bit(nr, addr))
return 1;
goto try_set_bit;
}

100
arch/mn10300/lib/checksum.c Normal file
View file

@ -0,0 +1,100 @@
/* MN10300 Optimised checksumming wrappers
*
* Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#include <asm/checksum.h>
#include "internal.h"
static inline unsigned short from32to16(__wsum sum)
{
asm(" add %1,%0 \n"
" addc 0xffff,%0 \n"
: "=r" (sum)
: "r" (sum << 16), "0" (sum & 0xffff0000)
: "cc"
);
return sum >> 16;
}
__sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
return ~do_csum(iph, ihl * 4);
}
EXPORT_SYMBOL(ip_fast_csum);
__wsum csum_partial(const void *buff, int len, __wsum sum)
{
__wsum result;
result = do_csum(buff, len);
result += sum;
if (sum > result)
result++;
return result;
}
EXPORT_SYMBOL(csum_partial);
__sum16 ip_compute_csum(const void *buff, int len)
{
return ~from32to16(do_csum(buff, len));
}
EXPORT_SYMBOL(ip_compute_csum);
__wsum csum_partial_copy(const void *src, void *dst, int len, __wsum sum)
{
copy_from_user(dst, src, len);
return csum_partial(dst, len, sum);
}
EXPORT_SYMBOL(csum_partial_copy);
__wsum csum_partial_copy_nocheck(const void *src, void *dst,
int len, __wsum sum)
{
sum = csum_partial(src, len, sum);
memcpy(dst, src, len);
return sum;
}
EXPORT_SYMBOL(csum_partial_copy_nocheck);
__wsum csum_partial_copy_from_user(const void *src, void *dst,
int len, __wsum sum,
int *err_ptr)
{
int missing;
missing = copy_from_user(dst, src, len);
if (missing) {
memset(dst + len - missing, 0, missing);
*err_ptr = -EFAULT;
}
return csum_partial(dst, len, sum);
}
EXPORT_SYMBOL(csum_partial_copy_from_user);
__wsum csum_and_copy_to_user(const void *src, void *dst,
int len, __wsum sum,
int *err_ptr)
{
int missing;
missing = copy_to_user(dst, src, len);
if (missing) {
memset(dst + len - missing, 0, missing);
*err_ptr = -EFAULT;
}
return csum_partial(src, len, sum);
}
EXPORT_SYMBOL(csum_and_copy_to_user);

51
arch/mn10300/lib/delay.c Normal file
View file

@ -0,0 +1,51 @@
/* MN10300 Short delay interpolation routines
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/div64.h>
/*
* basic delay loop
*/
void __delay(unsigned long loops)
{
int d0;
asm volatile(
" bra 1f \n"
" .align 4 \n"
"1: bra 2f \n"
" .align 4 \n"
"2: add -1,%0 \n"
" bne 2b \n"
: "=&d" (d0)
: "0" (loops)
: "cc");
}
EXPORT_SYMBOL(__delay);
/*
* handle a delay specified in terms of microseconds
*/
void __udelay(unsigned long usecs)
{
unsigned long start, stop, cnt;
/* usecs * CLK / 1E6 */
stop = __muldiv64u(usecs, MN10300_TSCCLK, 1000000);
start = TMTSCBC;
do {
cnt = start - TMTSCBC;
} while (cnt < stop);
}
EXPORT_SYMBOL(__udelay);

157
arch/mn10300/lib/do_csum.S Normal file
View file

@ -0,0 +1,157 @@
/* Optimised simple memory checksum
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.section .text
.balign L1_CACHE_BYTES
###############################################################################
#
# unsigned int do_csum(const unsigned char *buff, int len)
#
###############################################################################
.globl do_csum
.type do_csum,@function
do_csum:
movm [d2,d3],(sp)
mov d1,d2 # count
mov d0,a0 # buff
mov a0,a1
clr d1 # accumulator
cmp +0,d2
ble do_csum_done # check for zero length or negative
# 4-byte align the buffer pointer
btst +3,a0
beq do_csum_now_4b_aligned
btst +1,a0
beq do_csum_addr_not_odd
movbu (a0),d0
inc a0
asl +8,d0
add d0,d1
add -1,d2
do_csum_addr_not_odd:
cmp +2,d2
bcs do_csum_fewer_than_4
btst +2,a0
beq do_csum_now_4b_aligned
movhu (a0+),d0
add d0,d1
add -2,d2
cmp +4,d2
bcs do_csum_fewer_than_4
do_csum_now_4b_aligned:
# we want to checksum as much as we can in chunks of 32 bytes
cmp +31,d2
bls do_csum_remainder # 4-byte aligned remainder
add -32,d2
mov +32,d3
do_csum_loop:
mov (a0+),d0
mov (a0+),e0
mov (a0+),e1
mov (a0+),e3
add d0,d1
addc e0,d1
addc e1,d1
addc e3,d1
mov (a0+),d0
mov (a0+),e0
mov (a0+),e1
mov (a0+),e3
addc d0,d1
addc e0,d1
addc e1,d1
addc e3,d1
addc +0,d1
sub d3,d2
bcc do_csum_loop
add d3,d2
beq do_csum_done
do_csum_remainder:
# cut 16-31 bytes down to 0-15
cmp +16,d2
bcs do_csum_fewer_than_16
mov (a0+),d0
mov (a0+),e0
mov (a0+),e1
mov (a0+),e3
add d0,d1
addc e0,d1
addc e1,d1
addc e3,d1
addc +0,d1
add -16,d2
beq do_csum_done
do_csum_fewer_than_16:
# copy the remaining whole words
cmp +4,d2
bcs do_csum_fewer_than_4
cmp +8,d2
bcs do_csum_one_word
cmp +12,d2
bcs do_csum_two_words
mov (a0+),d0
add d0,d1
addc +0,d1
do_csum_two_words:
mov (a0+),d0
add d0,d1
addc +0,d1
do_csum_one_word:
mov (a0+),d0
add d0,d1
addc +0,d1
do_csum_fewer_than_4:
and +3,d2
beq do_csum_done
xor_cmp d0,d0,+2,d2
bcs do_csum_fewer_than_2
movhu (a0+),d0
and +1,d2
beq do_csum_add_last_bit
do_csum_fewer_than_2:
movbu (a0),d3
add d3,d0
do_csum_add_last_bit:
add d0,d1
addc +0,d1
do_csum_done:
# compress the checksum down to 16 bits
mov +0xffff0000,d0
and d1,d0
asl +16,d1
add d1,d0
addc +0xffff,d0
lsr +16,d0
# flip the halves of the word result if the buffer was oddly aligned
and +1,a1
beq do_csum_not_oddly_aligned
swaph d0,d0 # exchange bits 15:8 with 7:0
do_csum_not_oddly_aligned:
ret [d2,d3],8
.size do_csum, .-do_csum

View file

@ -0,0 +1,15 @@
/* Internal definitions for the arch part of the kernel library
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
/*
* do_csum.S
*/
extern unsigned int do_csum(const unsigned char *, size_t);

View file

@ -0,0 +1,60 @@
/* lshrdi3.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 Licence 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 Licence for more details.
You should have received a copy of the GNU General Public Licence
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 low;
SItype high;
};
union DIunion {
struct DIstruct s;
DItype ll;
};
DItype __lshrdi3(DItype u, word_type b)
{
union DIunion w;
word_type bm;
union DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof(SItype) * BITS_PER_UNIT) - b;
if (bm <= 0) {
w.s.high = 0;
w.s.low = (USItype) uu.s.high >> -bm;
} else {
USItype carries = (USItype) uu.s.high << bm;
w.s.high = (USItype) uu.s.high >> b;
w.s.low = ((USItype) uu.s.low >> b) | carries;
}
return w.ll;
}

135
arch/mn10300/lib/memcpy.S Normal file
View file

@ -0,0 +1,135 @@
/* MN10300 Optimised simple memory to memory copy
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.section .text
.balign L1_CACHE_BYTES
###############################################################################
#
# void *memcpy(void *dst, const void *src, size_t n)
#
###############################################################################
.globl memcpy
.type memcpy,@function
memcpy:
movm [d2,d3],(sp)
mov d0,(12,sp)
mov d1,(16,sp)
mov (20,sp),d2 # count
mov d0,a0 # dst
mov d1,a1 # src
mov d0,e3 # the return value
cmp +0,d2
beq memcpy_done # return if zero-length copy
# see if the three parameters are all four-byte aligned
or d0,d1,d3
or d2,d3
and +3,d3
bne memcpy_1 # jump if not
# we want to transfer as much as we can in chunks of 32 bytes
cmp +31,d2
bls memcpy_4_remainder # 4-byte aligned remainder
movm [exreg1],(sp)
add -32,d2
mov +32,d3
memcpy_4_loop:
mov (a1+),d0
mov (a1+),d1
mov (a1+),e0
mov (a1+),e1
mov (a1+),e4
mov (a1+),e5
mov (a1+),e6
mov (a1+),e7
mov d0,(a0+)
mov d1,(a0+)
mov e0,(a0+)
mov e1,(a0+)
mov e4,(a0+)
mov e5,(a0+)
mov e6,(a0+)
mov e7,(a0+)
sub d3,d2
bcc memcpy_4_loop
movm (sp),[exreg1]
add d3,d2
beq memcpy_4_no_remainder
memcpy_4_remainder:
# cut 4-7 words down to 0-3
cmp +16,d2
bcs memcpy_4_three_or_fewer_words
mov (a1+),d0
mov (a1+),d1
mov (a1+),e0
mov (a1+),e1
mov d0,(a0+)
mov d1,(a0+)
mov e0,(a0+)
mov e1,(a0+)
add -16,d2
beq memcpy_4_no_remainder
# copy the remaining 1, 2 or 3 words
memcpy_4_three_or_fewer_words:
cmp +8,d2
bcs memcpy_4_one_word
beq memcpy_4_two_words
mov (a1+),d0
mov d0,(a0+)
memcpy_4_two_words:
mov (a1+),d0
mov d0,(a0+)
memcpy_4_one_word:
mov (a1+),d0
mov d0,(a0+)
memcpy_4_no_remainder:
# check we copied the correct amount
# TODO: REMOVE CHECK
sub e3,a0,d2
mov (20,sp),d1
cmp d2,d1
beq memcpy_done
break
break
break
memcpy_done:
mov e3,a0
ret [d2,d3],8
# handle misaligned copying
memcpy_1:
add -1,d2
mov +1,d3
setlb # setlb requires the next insns
# to occupy exactly 4 bytes
sub d3,d2
movbu (a1),d0
movbu d0,(a0)
add_add d3,a1,d3,a0
lcc
mov e3,a0
ret [d2,d3],8
memcpy_end:
.size memcpy, memcpy_end-memcpy

160
arch/mn10300/lib/memmove.S Normal file
View file

@ -0,0 +1,160 @@
/* MN10300 Optimised simple memory to memory copy, with support for overlapping
* regions
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.section .text
.balign L1_CACHE_BYTES
###############################################################################
#
# void *memmove(void *dst, const void *src, size_t n)
#
###############################################################################
.globl memmove
.type memmove,@function
memmove:
# fall back to memcpy if dst < src to work bottom up
cmp d1,d0
bcs memmove_memcpy
# work top down
movm [d2,d3],(sp)
mov d0,(12,sp)
mov d1,(16,sp)
mov (20,sp),d2 # count
add d0,d2,a0 # dst end
add d1,d2,a1 # src end
mov d0,e3 # the return value
cmp +0,d2
beq memmove_done # return if zero-length copy
# see if the three parameters are all four-byte aligned
or d0,d1,d3
or d2,d3
and +3,d3
bne memmove_1 # jump if not
# we want to transfer as much as we can in chunks of 32 bytes
add -4,a1
cmp +31,d2
bls memmove_4_remainder # 4-byte aligned remainder
add -32,d2
mov +32,d3
memmove_4_loop:
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
mov (a1),d1
sub_sub +4,a1,+4,a0
mov d1,(a0)
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
mov (a1),d1
sub_sub +4,a1,+4,a0
mov d1,(a0)
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
mov (a1),d1
sub_sub +4,a1,+4,a0
mov d1,(a0)
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
mov (a1),d1
sub_sub +4,a1,+4,a0
mov d1,(a0)
sub d3,d2
bcc memmove_4_loop
add d3,d2
beq memmove_4_no_remainder
memmove_4_remainder:
# cut 4-7 words down to 0-3
cmp +16,d2
bcs memmove_4_three_or_fewer_words
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
mov (a1),d1
sub_sub +4,a1,+4,a0
mov d1,(a0)
mov (a1),e0
sub_sub +4,a1,+4,a0
mov e0,(a0)
mov (a1),e1
sub_sub +4,a1,+4,a0
mov e1,(a0)
add -16,d2
beq memmove_4_no_remainder
# copy the remaining 1, 2 or 3 words
memmove_4_three_or_fewer_words:
cmp +8,d2
bcs memmove_4_one_word
beq memmove_4_two_words
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
memmove_4_two_words:
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
memmove_4_one_word:
mov (a1),d0
sub_sub +4,a1,+4,a0
mov d0,(a0)
memmove_4_no_remainder:
# check we copied the correct amount
# TODO: REMOVE CHECK
sub e3,a0,d2
beq memmove_done
break
break
break
memmove_done:
mov e3,a0
ret [d2,d3],8
# handle misaligned copying
memmove_1:
add -1,a1
add -1,d2
mov +1,d3
setlb # setlb requires the next insns
# to occupy exactly 4 bytes
sub d3,d2
movbu (a1),d0
sub_sub d3,a1,d3,a0
movbu d0,(a0)
lcc
mov e3,a0
ret [d2,d3],8
memmove_memcpy:
jmp memcpy
memmove_end:
.size memmove, memmove_end-memmove

121
arch/mn10300/lib/memset.S Normal file
View file

@ -0,0 +1,121 @@
/* Optimised simple memory fill
*
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/cache.h>
.section .text
.balign L1_CACHE_BYTES
###############################################################################
#
# void *memset(void *dst, int c, size_t n)
#
###############################################################################
.globl memset
.type memset,@function
memset:
movm [d2,d3],(sp)
mov d0,(12,sp)
mov d1,(16,sp)
mov (20,sp),d2 # count
mov d0,a0 # dst
mov d0,e3 # the return value
cmp +0,d2
beq memset_done # return if zero-length fill
# see if the region parameters are four-byte aligned
or d0,d2,d3
and +3,d3
bne memset_1 # jump if not
extbu d1
mov_asl d1,d3,8,d1
or_asl d1,d3,8,d1
or_asl d1,d3,8,d1
or d3,d1
# we want to transfer as much as we can in chunks of 32 bytes
cmp +31,d2
bls memset_4_remainder # 4-byte aligned remainder
add -32,d2
mov +32,d3
memset_4_loop:
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
sub d3,d2
bcc memset_4_loop
add d3,d2
beq memset_4_no_remainder
memset_4_remainder:
# cut 4-7 words down to 0-3
cmp +16,d2
bcs memset_4_three_or_fewer_words
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
mov d1,(a0+)
add -16,d2
beq memset_4_no_remainder
# copy the remaining 1, 2 or 3 words
memset_4_three_or_fewer_words:
cmp +8,d2
bcs memset_4_one_word
beq memset_4_two_words
mov d1,(a0+)
memset_4_two_words:
mov d1,(a0+)
memset_4_one_word:
mov d1,(a0+)
memset_4_no_remainder:
# check we set the correct amount
# TODO: REMOVE CHECK
sub e3,a0,d2
mov (20,sp),d1
cmp d2,d1
beq memset_done
break
break
break
memset_done:
mov e3,a0
ret [d2,d3],8
# handle misaligned copying
memset_1:
add -1,d2
mov +1,d3
setlb # setlb requires the next insns
# to occupy exactly 4 bytes
sub d3,d2
movbu d1,(a0)
inc a0
lcc
mov e3,a0
ret [d2,d3],8
memset_end:
.size memset, memset_end-memset

57
arch/mn10300/lib/negdi2.c Normal file
View file

@ -0,0 +1,57 @@
/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001 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 Licence as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public Licence, 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 General Public Licence restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
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 Licence for more details.
You should have received a copy of the GNU General Public Licence
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. */
/* It is incorrect to include config.h here, because this file is being
compiled for the target, and hence definitions concerning only the host
do not apply. */
#include <linux/types.h>
union DWunion {
s64 ll;
struct {
s32 low;
s32 high;
} s;
};
s64 __negdi2(s64 u)
{
union DWunion w;
union DWunion uu;
uu.ll = u;
w.s.low = -uu.s.low;
w.s.high = -uu.s.high - ((u32) w.s.low > 0);
return w.ll;
}

166
arch/mn10300/lib/usercopy.c Normal file
View file

@ -0,0 +1,166 @@
/* MN10300 Userspace accessor functions
*
* Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/
#include <asm/uaccess.h>
unsigned long
__generic_copy_to_user(void *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
__copy_user(to, from, n);
return n;
}
unsigned long
__generic_copy_from_user(void *to, const void *from, unsigned long n)
{
if (access_ok(VERIFY_READ, from, n))
__copy_user_zeroing(to, from, n);
return n;
}
/*
* Copy a null terminated string from userspace.
*/
#define __do_strncpy_from_user(dst, src, count, res) \
do { \
int w; \
asm volatile( \
" mov %1,%0\n" \
" cmp 0,%1\n" \
" beq 2f\n" \
"0:\n" \
" movbu (%5),%2\n" \
"1:\n" \
" movbu %2,(%6)\n" \
" inc %5\n" \
" inc %6\n" \
" cmp 0,%2\n" \
" beq 2f\n" \
" add -1,%1\n" \
" bne 0b\n" \
"2:\n" \
" sub %1,%0\n" \
"3:\n" \
" .section .fixup,\"ax\"\n" \
"4:\n" \
" mov %3,%0\n" \
" jmp 3b\n" \
" .previous\n" \
" .section __ex_table,\"a\"\n" \
" .balign 4\n" \
" .long 0b,4b\n" \
" .long 1b,4b\n" \
" .previous" \
:"=&r"(res), "=r"(count), "=&r"(w) \
:"i"(-EFAULT), "1"(count), "a"(src), "a"(dst) \
: "memory", "cc"); \
} while (0)
long
__strncpy_from_user(char *dst, const char *src, long count)
{
long res;
__do_strncpy_from_user(dst, src, count, res);
return res;
}
long
strncpy_from_user(char *dst, const char *src, long count)
{
long res = -EFAULT;
if (access_ok(VERIFY_READ, src, 1))
__do_strncpy_from_user(dst, src, count, res);
return res;
}
/*
* Clear a userspace memory
*/
#define __do_clear_user(addr, size) \
do { \
int w; \
asm volatile( \
" cmp 0,%0\n" \
" beq 1f\n" \
" clr %1\n" \
"0: movbu %1,(%3,%2)\n" \
" inc %3\n" \
" cmp %0,%3\n" \
" bne 0b\n" \
"1:\n" \
" sub %3,%0\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .balign 4\n" \
" .long 0b,3b\n" \
".previous\n" \
: "+r"(size), "=&r"(w) \
: "a"(addr), "d"(0) \
: "memory", "cc"); \
} while (0)
unsigned long
__clear_user(void *to, unsigned long n)
{
__do_clear_user(to, n);
return n;
}
unsigned long
clear_user(void *to, unsigned long n)
{
if (access_ok(VERIFY_WRITE, to, n))
__do_clear_user(to, n);
return n;
}
/*
* Return the size of a string (including the ending 0)
*
* Return 0 on exception, a value greater than N if too long
*/
long strnlen_user(const char *s, long n)
{
unsigned long res, w;
if (!__addr_ok(s))
return 0;
if (n < 0 || n + (u_long) s > current_thread_info()->addr_limit.seg)
n = current_thread_info()->addr_limit.seg - (u_long)s;
asm volatile(
"0: cmp %4,%0\n"
" beq 2f\n"
"1: movbu (%0,%3),%1\n"
" inc %0\n"
" cmp 0,%1\n"
" beq 3f\n"
" bra 0b\n"
"2: clr %0\n"
"3:\n"
".section .fixup,\"ax\"\n"
"4: jmp 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
" .balign 4\n"
" .long 1b,4b\n"
".previous\n"
:"=d"(res), "=&r"(w)
:"0"(0), "a"(s), "r"(n)
: "memory", "cc");
return res;
}