Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96cf5185 authored by GuanXuetao's avatar GuanXuetao
Browse files

unicore32 additional architecture files: low-level lib: misc



This patch implements the rest low-level libraries.

Signed-off-by: default avatarGuan Xuetao <gxt@mprc.pku.edu.cn>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
parent 77c93b2f
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
/*
 * linux/arch/unicore32/include/asm/assembler.h
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Do not include any C declarations in this file - it is included by
 *  assembler source.
 */
#ifndef __ASSEMBLY__
#error "Only include this from assembly code"
#endif

#include <asm/ptrace.h>

/*
 * Little Endian independent macros for shifting bytes within registers.
 */
#define pull            >>
#define push            <<
#define get_byte_0      << #0
#define get_byte_1	>> #8
#define get_byte_2	>> #16
#define get_byte_3	>> #24
#define put_byte_0      << #0
#define put_byte_1	<< #8
#define put_byte_2	<< #16
#define put_byte_3	<< #24

#define cadd		cmpadd
#define cand		cmpand
#define csub		cmpsub
#define cxor		cmpxor

/*
 * Enable and disable interrupts
 */
	.macro disable_irq, temp
	mov	\temp, asr
	andn     \temp, \temp, #0xFF
	or	\temp, \temp, #PSR_I_BIT | PRIV_MODE
	mov.a	asr, \temp
	.endm

	.macro enable_irq, temp
	mov	\temp, asr
	andn     \temp, \temp, #0xFF
	or	\temp, \temp, #PRIV_MODE
	mov.a	asr, \temp
	.endm

#define USER(x...)				\
9999:	x;					\
	.pushsection __ex_table, "a";		\
	.align	3;				\
	.long	9999b, 9001f;			\
	.popsection

	.macro	notcond, cond, nexti = .+8
	.ifc	\cond, eq
		bne	\nexti
	.else;	.ifc	\cond, ne
		beq	\nexti
	.else;	.ifc	\cond, ea
		bub	\nexti
	.else;	.ifc	\cond, ub
		bea	\nexti
	.else;	.ifc	\cond, fs
		bns	\nexti
	.else;	.ifc	\cond, ns
		bfs	\nexti
	.else;	.ifc	\cond, fv
		bnv	\nexti
	.else;	.ifc	\cond, nv
		bfv	\nexti
	.else;	.ifc	\cond, ua
		beb	\nexti
	.else;	.ifc	\cond, eb
		bua	\nexti
	.else;	.ifc	\cond, eg
		bsl	\nexti
	.else;	.ifc	\cond, sl
		beg	\nexti
	.else;	.ifc	\cond, sg
		bel	\nexti
	.else;	.ifc	\cond, el
		bsg	\nexti
	.else;	.ifnc	\cond, al
		.error  "Unknown cond in notcond macro argument"
	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
	.endif
	.endm

	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
	.rept	\rept
	notcond	\cond, .+8
9999 :
	.if	\inc == 1
	\instr\()b.u \reg, [\ptr], #\inc
	.elseif	\inc == 4
	\instr\()w.u \reg, [\ptr], #\inc
	.else
	.error	"Unsupported inc macro argument"
	.endif

	.pushsection __ex_table, "a"
	.align	3
	.long	9999b, \abort
	.popsection
	.endr
	.endm

	.macro	strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
	usracc	st, \reg, \ptr, \inc, \cond, \rept, \abort
	.endm

	.macro	ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
	usracc	ld, \reg, \ptr, \inc, \cond, \rept, \abort
	.endm

	.macro	nop8
	.rept	8
		nop
	.endr
	.endm
+47 −0
Original line number Diff line number Diff line
/*
 * linux/arch/unicore32/include/asm/bitops.h
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __UNICORE_BITOPS_H__
#define __UNICORE_BITOPS_H__

#define find_next_bit		__uc32_find_next_bit
#define find_next_zero_bit	__uc32_find_next_zero_bit

#define find_first_bit		__uc32_find_first_bit
#define find_first_zero_bit	__uc32_find_first_zero_bit

#define _ASM_GENERIC_BITOPS_FLS_H_
#define _ASM_GENERIC_BITOPS___FLS_H_
#define _ASM_GENERIC_BITOPS_FFS_H_
#define _ASM_GENERIC_BITOPS___FFS_H_
/*
 * On UNICORE, those functions can be implemented around
 * the cntlz instruction for much better code efficiency.
 */

static inline int fls(int x)
{
	int ret;

	asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
	ret = 32 - ret;

	return ret;
}

#define __fls(x) (fls(x) - 1)
#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
#define __ffs(x) (ffs(x) - 1)

#include <asm-generic/bitops.h>

#endif /* __UNICORE_BITOPS_H__ */
+41 −0
Original line number Diff line number Diff line
/*
 * linux/arch/unicore32/include/asm/checksum.h
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * IP checksum routines
 */
#ifndef __UNICORE_CHECKSUM_H__
#define __UNICORE_CHECKSUM_H__

/*
 * computes the checksum of the TCP/UDP pseudo-header
 * returns a 16-bit checksum, already complemented
 */

static inline __wsum
csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
		   unsigned short proto, __wsum sum)
{
	__asm__(
	"add.a	%0, %1, %2\n"
	"addc.a	%0, %0, %3\n"
	"addc.a	%0, %0, %4 << #8\n"
	"addc.a	%0, %0, %5\n"
	"addc	%0, %0, #0\n"
	: "=&r"(sum)
	: "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
	: "cc");
	return sum;
}
#define csum_tcpudp_nofold	csum_tcpudp_nofold

#include <asm-generic/checksum.h>

#endif
+52 −0
Original line number Diff line number Diff line
/*
 * linux/arch/unicore32/include/asm/delay.h
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Delay routines, using a pre-computed "loops_per_second" value.
 */
#ifndef __UNICORE_DELAY_H__
#define __UNICORE_DELAY_H__

#include <asm/param.h>	/* HZ */

extern void __delay(int loops);

/*
 * This function intentionally does not exist; if you see references to
 * it, it means that you're calling udelay() with an out of range value.
 *
 * With currently imposed limits, this means that we support a max delay
 * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
 */
extern void __bad_udelay(void);

/*
 * division by multiplication: you don't have to worry about
 * loss of precision.
 *
 * Use only for very small delays ( < 1 msec).  Should probably use a
 * lookup table, really, as the multiplications take much too long with
 * short delays.  This is a "reasonable" implementation, though (and the
 * first constant multiplications gets optimized away if the delay is
 * a constant)
 */
extern void __udelay(unsigned long usecs);
extern void __const_udelay(unsigned long);

#define MAX_UDELAY_MS 2

#define udelay(n)							\
	(__builtin_constant_p(n) ?					\
	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\
			__const_udelay((n) * ((2199023U*HZ)>>11))) :	\
	  __udelay(n))

#endif /* __UNICORE_DELAY_H__ */
+143 −0
Original line number Diff line number Diff line
/*
 * linux/arch/unicore32/include/asm/futex.h
 *
 * Code specific to PKUnity SoC and UniCore ISA
 *
 * Copyright (C) 2001-2010 GUAN Xue-tao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __UNICORE_FUTEX_H__
#define __UNICORE_FUTEX_H__

#ifdef __KERNEL__

#include <linux/futex.h>
#include <linux/preempt.h>
#include <linux/uaccess.h>
#include <linux/errno.h>

#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
	__asm__ __volatile__(					\
	"1:	ldw.u	%1, [%2]\n"				\
	"	" insn "\n"					\
	"2:	stw.u	%0, [%2]\n"				\
	"	mov	%0, #0\n"				\
	"3:\n"							\
	"	.pushsection __ex_table,\"a\"\n"		\
	"	.align	3\n"					\
	"	.long	1b, 4f, 2b, 4f\n"			\
	"	.popsection\n"					\
	"	.pushsection .fixup,\"ax\"\n"			\
	"4:	mov	%0, %4\n"				\
	"	b	3b\n"					\
	"	.popsection"					\
	: "=&r" (ret), "=&r" (oldval)				\
	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
	: "cc", "memory")

static inline int
futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
{
	int op = (encoded_op >> 28) & 7;
	int cmp = (encoded_op >> 24) & 15;
	int oparg = (encoded_op << 8) >> 20;
	int cmparg = (encoded_op << 20) >> 20;
	int oldval = 0, ret;

	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
		oparg = 1 << oparg;

	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
		return -EFAULT;

	pagefault_disable();	/* implies preempt_disable() */

	switch (op) {
	case FUTEX_OP_SET:
		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_ADD:
		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_OR:
		__futex_atomic_op("or	%0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	case FUTEX_OP_ANDN:
		__futex_atomic_op("and	%0, %1, %3",
				ret, oldval, uaddr, ~oparg);
		break;
	case FUTEX_OP_XOR:
		__futex_atomic_op("xor	%0, %1, %3", ret, oldval, uaddr, oparg);
		break;
	default:
		ret = -ENOSYS;
	}

	pagefault_enable();	/* subsumes preempt_enable() */

	if (!ret) {
		switch (cmp) {
		case FUTEX_OP_CMP_EQ:
			ret = (oldval == cmparg);
			break;
		case FUTEX_OP_CMP_NE:
			ret = (oldval != cmparg);
			break;
		case FUTEX_OP_CMP_LT:
			ret = (oldval <  cmparg);
			break;
		case FUTEX_OP_CMP_GE:
			ret = (oldval >= cmparg);
			break;
		case FUTEX_OP_CMP_LE:
			ret = (oldval <= cmparg);
			break;
		case FUTEX_OP_CMP_GT:
			ret = (oldval >  cmparg);
			break;
		default:
			ret = -ENOSYS;
		}
	}
	return ret;
}

static inline int
futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
{
	int val;

	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
		return -EFAULT;

	pagefault_disable();	/* implies preempt_disable() */

	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
	"1:	ldw.u	%0, [%3]\n"
	"	cmpxor.a	%0, %1\n"
	"	bne	3f\n"
	"2:	stw.u	%2, [%3]\n"
	"3:\n"
	"	.pushsection __ex_table,\"a\"\n"
	"	.align	3\n"
	"	.long	1b, 4f, 2b, 4f\n"
	"	.popsection\n"
	"	.pushsection .fixup,\"ax\"\n"
	"4:	mov	%0, %4\n"
	"	b	3b\n"
	"	.popsection"
	: "=&r" (val)
	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
	: "cc", "memory");

	pagefault_enable();	/* subsumes preempt_enable() */

	return val;
}

#endif /* __KERNEL__ */
#endif /* __UNICORE_FUTEX_H__ */
Loading