
C6X (C6000) is Texas Instruments architecture of fixed and floating-point DSPs. This patch add basic support. Many of code in arch/c6x/include/asm come from c6x-linux project (http://linux-c6x.org)
Signed-off-by: Dmitry Bondar bond@inmys.ru Cc: Tom Rini trini@ti.com --- arch/c6x/config.mk | 1 + arch/c6x/include/asm/bitops.h | 88 ++++++++ arch/c6x/include/asm/byteorder.h | 1 + arch/c6x/include/asm/cache.h | 29 +++ arch/c6x/include/asm/config.h | 3 + arch/c6x/include/asm/errno.h | 1 + arch/c6x/include/asm/global_data.h | 96 +++++++++ arch/c6x/include/asm/gpio.h | 2 + arch/c6x/include/asm/io.h | 68 ++++++ arch/c6x/include/asm/posix_types.h | 72 +++++++ arch/c6x/include/asm/processor.h | 4 + arch/c6x/include/asm/ptrace.h | 310 +++++++++++++++++++++++++++ arch/c6x/include/asm/sizes.h | 51 +++++ arch/c6x/include/asm/string.h | 26 +++ arch/c6x/include/asm/types.h | 53 +++++ arch/c6x/include/asm/u-boot-c6x.h | 14 ++ arch/c6x/include/asm/u-boot.h | 57 +++++ arch/c6x/include/asm/unaligned.h | 1 + arch/c6x/lib/Makefile | 51 +++++ arch/c6x/lib/board.c | 196 +++++++++++++++++ arch/c6x/lib/bootm.c | 60 ++++++ arch/c6x/lib/csum_64plus.S | 408 ++++++++++++++++++++++++++++++++++++ arch/c6x/lib/delay.S | 39 ++++ arch/c6x/lib/divi.S | 54 +++++ arch/c6x/lib/divremi.S | 61 ++++++ arch/c6x/lib/divremu.S | 86 ++++++++ arch/c6x/lib/divu.S | 100 +++++++++ arch/c6x/lib/divull.c | 336 +++++++++++++++++++++++++++++ arch/c6x/lib/llshl.S | 36 ++++ arch/c6x/lib/llshr.S | 36 ++++ arch/c6x/lib/llshru.S | 36 ++++ arch/c6x/lib/memcmp.c | 24 ++ arch/c6x/lib/memcpy_64plus.S | 45 ++++ arch/c6x/lib/memmove.c | 30 +++ arch/c6x/lib/memset.c | 20 ++ arch/c6x/lib/mpyll.S | 47 ++++ arch/c6x/lib/negll.S | 29 +++ arch/c6x/lib/pop_rts.S | 30 +++ arch/c6x/lib/push_rts.S | 28 +++ arch/c6x/lib/remi.S | 78 +++++++ arch/c6x/lib/remu.S | 81 +++++++ arch/c6x/lib/strasgi.S | 88 ++++++++ arch/c6x/lib/strasgi_64plus.S | 37 ++++ arch/c6x/lib/unaligned.S | 117 ++++++++++ common/cmd_bdinfo.c | 5 + common/image.c | 4 + examples/standalone/stubs.c | 15 ++ 47 files changed, 3054 insertions(+), 0 deletions(-) create mode 100644 arch/c6x/config.mk create mode 100644 arch/c6x/include/asm/bitops.h create mode 100644 arch/c6x/include/asm/byteorder.h create mode 100644 arch/c6x/include/asm/cache.h create mode 100644 arch/c6x/include/asm/config.h create mode 100644 arch/c6x/include/asm/errno.h create mode 100644 arch/c6x/include/asm/global_data.h create mode 100644 arch/c6x/include/asm/gpio.h create mode 100644 arch/c6x/include/asm/io.h create mode 100644 arch/c6x/include/asm/posix_types.h create mode 100644 arch/c6x/include/asm/processor.h create mode 100644 arch/c6x/include/asm/ptrace.h create mode 100644 arch/c6x/include/asm/sizes.h create mode 100644 arch/c6x/include/asm/string.h create mode 100644 arch/c6x/include/asm/types.h create mode 100644 arch/c6x/include/asm/u-boot-c6x.h create mode 100644 arch/c6x/include/asm/u-boot.h create mode 100644 arch/c6x/include/asm/unaligned.h create mode 100644 arch/c6x/lib/Makefile create mode 100644 arch/c6x/lib/board.c create mode 100644 arch/c6x/lib/bootm.c create mode 100644 arch/c6x/lib/csum_64plus.S create mode 100644 arch/c6x/lib/delay.S create mode 100644 arch/c6x/lib/divi.S create mode 100644 arch/c6x/lib/divremi.S create mode 100644 arch/c6x/lib/divremu.S create mode 100644 arch/c6x/lib/divu.S create mode 100644 arch/c6x/lib/divull.c create mode 100644 arch/c6x/lib/llshl.S create mode 100644 arch/c6x/lib/llshr.S create mode 100644 arch/c6x/lib/llshru.S create mode 100644 arch/c6x/lib/memcmp.c create mode 100644 arch/c6x/lib/memcpy_64plus.S create mode 100644 arch/c6x/lib/memmove.c create mode 100644 arch/c6x/lib/memset.c create mode 100644 arch/c6x/lib/mpyll.S create mode 100644 arch/c6x/lib/negll.S create mode 100644 arch/c6x/lib/pop_rts.S create mode 100644 arch/c6x/lib/push_rts.S create mode 100644 arch/c6x/lib/remi.S create mode 100644 arch/c6x/lib/remu.S create mode 100644 arch/c6x/lib/strasgi.S create mode 100644 arch/c6x/lib/strasgi_64plus.S create mode 100644 arch/c6x/lib/unaligned.S
diff --git a/arch/c6x/config.mk b/arch/c6x/config.mk new file mode 100644 index 0000000..9cbddbc --- /dev/null +++ b/arch/c6x/config.mk @@ -0,0 +1 @@ +CROSS_COMPILE ?= c6x-uclinux- diff --git a/arch/c6x/include/asm/bitops.h b/arch/c6x/include/asm/bitops.h new file mode 100644 index 0000000..5896b5e --- /dev/null +++ b/arch/c6x/include/asm/bitops.h @@ -0,0 +1,88 @@ +/* + * linux/include/asm-c6x/bitops.h + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009, 2010 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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 __ASM_C6X_BITOPS_H_ +#define __ASM_C6X_BITOPS_H_ + +#ifdef __KERNEL__ + +#include <linux/bitops.h> +#include <asm/byteorder.h> + +/* + * We are lucky, DSP is perfect for bitops: do it in 3 cycles + */ + +/** + * __ffs - find first bit in word. + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + * Note __ffs(0) = undef, __ffs(1) = 0, __ffs(0x80000000) = 31. + * + */ +static inline unsigned long __ffs(unsigned long x) +{ + asm (" bitr .M1 %0,%0\n" + " nop\n" + " lmbd .L1 1,%0,%0\n" + : "+a"(x)); + + return x; +} + +/* + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +#define ffz(x) __ffs(~(x)) + +/** + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +static inline unsigned long fls(unsigned long x) +{ + if (!x) + return 0; + + asm (" lmbd .L1 1,%0,%0\n" : "+a"(x)); + + return 32 - x; +} + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + * Note ffs(0) = 0, ffs(1) = 1, ffs(0x80000000) = 32. + */ +static inline int ffs(int x) +{ + if (!x) + return 0; + + return __ffs(x) + 1; +} + +#define hweight8(x) generic_hweight8(x) + +#endif /* __KERNEL__ */ +#endif /* __ASM_C6X_BITOPS_H */ diff --git a/arch/c6x/include/asm/byteorder.h b/arch/c6x/include/asm/byteorder.h new file mode 100644 index 0000000..9558416 --- /dev/null +++ b/arch/c6x/include/asm/byteorder.h @@ -0,0 +1 @@ +#include <linux/byteorder/little_endian.h> diff --git a/arch/c6x/include/asm/cache.h b/arch/c6x/include/asm/cache.h new file mode 100644 index 0000000..75b2043 --- /dev/null +++ b/arch/c6x/include/asm/cache.h @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2011, Stefan Kristiansson stefan.kristiansson@saunalahti.fi + * + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_C6X_CACHE_H_ +#define __ASM_C6X_CACHE_H_ + +#ifdef CONFIG_SYS_CACHELINE_SIZE +#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE +#else +#define ARCH_DMA_MINALIGN 128 +#endif + +#endif /* __ASM_C6X_CACHE_H_ */ diff --git a/arch/c6x/include/asm/config.h b/arch/c6x/include/asm/config.h new file mode 100644 index 0000000..db59e8a --- /dev/null +++ b/arch/c6x/include/asm/config.h @@ -0,0 +1,3 @@ +#ifndef _ASM_CONFIG_H_ +#define _ASM_CONFIG_H_ +#endif diff --git a/arch/c6x/include/asm/errno.h b/arch/c6x/include/asm/errno.h new file mode 100644 index 0000000..4c82b50 --- /dev/null +++ b/arch/c6x/include/asm/errno.h @@ -0,0 +1 @@ +#include <asm-generic/errno.h> diff --git a/arch/c6x/include/asm/global_data.h b/arch/c6x/include/asm/global_data.h new file mode 100644 index 0000000..a8e0766 --- /dev/null +++ b/arch/c6x/include/asm/global_data.h @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2002-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_GBL_DATA_H +#define __ASM_GBL_DATA_H +/* + * The following data structure is placed in some memory which is + * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or + * some locked parts of the data cache) to allow for a minimum set of + * global variables during system initialization (until we have set + * up the memory controller so that we can use RAM). + * + * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t) + */ + +typedef struct global_data { + bd_t *bd; + unsigned long flags; + unsigned long baudrate; + unsigned long have_console; /* serial_init() was called */ +#ifdef CONFIG_PRE_CONSOLE_BUFFER + unsigned long precon_buf_idx; /* Pre-Console buffer index */ +#endif + unsigned long env_addr; /* Address of Environment struct */ + unsigned long env_valid; /* Checksum of Environment valid? */ + unsigned long fb_base; /* base address of frame buffer */ + + /* "static data" needed by most of timer.c (like on ARM platform) */ + unsigned long timer_rate_hz; + unsigned long tbl; + unsigned long tbu; + unsigned long long timer_reset_value; + unsigned long lastinc; + + phys_size_t ram_size; /* RAM size */ +#if 0 + unsigned long relocaddr; /* Start address of U-Boot in RAM */ + phys_size_t ram_size; /* RAM size */ + unsigned long mon_len; /* monitor len */ + unsigned long irq_sp; /* irq stack pointer */ + unsigned long start_addr_sp; /* start_addr_stackpointer */ + unsigned long reloc_off; +#endif + + void **jt; /* jump table */ + char env_buf[32]; /* buffer for getenv() before reloc. */ +#if defined(CONFIG_POST) || defined(CONFIG_LOGBUFFER) + unsigned long post_log_word; /* Record POST activities */ + unsigned long post_log_res; /* success of POST test */ + unsigned long post_init_f_time; /* When post_init_f started */ +#endif +} gd_t; + +/* + * Global Data Flags + */ +/* Code was relocated to RAM */ +#define GD_FLG_RELOC 0x00001 +/* Devices have been initialized */ +#define GD_FLG_DEVINIT 0x00002 +/* Silent mode */ +#define GD_FLG_SILENT 0x00004 +/* Critical POST test failed */ +#define GD_FLG_POSTFAIL 0x00008 +/* POST seqeunce aborted */ +#define GD_FLG_POSTSTOP 0x00010 +/* Log Buffer has been initialized */ +#define GD_FLG_LOGINIT 0x00020 +/* Disable console (in & out) */ +#define GD_FLG_DISABLE_CONSOLE 0x00040 +/* Environment imported into hash table */ +#define GD_FLG_ENV_READY 0x00080 + +#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("B31") + +#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/c6x/include/asm/gpio.h b/arch/c6x/include/asm/gpio.h new file mode 100644 index 0000000..d49ad08 --- /dev/null +++ b/arch/c6x/include/asm/gpio.h @@ -0,0 +1,2 @@ +#include <asm/arch/gpio.h> +#include <asm-generic/gpio.h> diff --git a/arch/c6x/include/asm/io.h b/arch/c6x/include/asm/io.h new file mode 100644 index 0000000..7c4ab87 --- /dev/null +++ b/arch/c6x/include/asm/io.h @@ -0,0 +1,68 @@ +/* + * linux/include/asm-c6x/io.h + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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. + */ + +#define __arch_getb(a) (*(volatile unsigned char *)(a)) +#define __arch_getw(a) (*(volatile unsigned short *)(a)) +#define __arch_getl(a) (*(volatile unsigned int *)(a)) + +#define __arch_putb(v, a) (*(volatile unsigned char *)(a) = (v)) +#define __arch_putw(v, a) (*(volatile unsigned short *)(a) = (v)) +#define __arch_putl(v, a) (*(volatile unsigned int *)(a) = (v)) + +#define __raw_writeb(v, a) __arch_putb(v, a) +#define __raw_writew(v, a) __arch_putw(v, a) +#define __raw_writel(v, a) __arch_putl(v, a) + +#define __raw_readb(a) __arch_getb(a) +#define __raw_readw(a) __arch_getw(a) +#define __raw_readl(a) __arch_getl(a) + +#define dmb() __asm__ __volatile__ ("" : : : "memory") +#define __iormb() dmb() +#define __iowmb() dmb() + +#define writeb(v, c) ({ u8 __v = v; __iowmb(); __arch_putb(__v, c); __v; }) +#define writew(v, c) ({ u16 __v = v; __iowmb(); __arch_putw(__v, c); __v; }) +#define writel(v, c) ({ u32 __v = v; __iowmb(); __arch_putl(__v, c); __v; }) + +#define readb(c) ({ u8 __v = __arch_getb(c); __iormb(); __v; }) +#define readw(c) ({ u16 __v = __arch_getw(c); __iormb(); __v; }) +#define readl(c) ({ u32 __v = __arch_getl(c); __iormb(); __v; }) + + +#define in_le16(addr) \ + ({ \ + unsigned short __v = le16_to_cpu(readw(addr)); \ + __v; \ + }) +#define in_le32(addr) \ + ({ \ + unsigned int __v = le32_to_cpu(readl(addr)); \ + __v; \ + }) +#define out_le16(addr, w) (writew(cpu_to_le16(w), addr)) +#define out_le32(addr, l) (writel(cpu_to_le32(l), addr)) + +#define clrbits(type, addr, clear) \ + out_##type((addr), in_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + out_##type((addr), in_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + out_##type((addr), (in_##type(addr) & ~(clear)) | (set)) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + diff --git a/arch/c6x/include/asm/posix_types.h b/arch/c6x/include/asm/posix_types.h new file mode 100644 index 0000000..d1fffe0 --- /dev/null +++ b/arch/c6x/include/asm/posix_types.h @@ -0,0 +1,72 @@ +/* + * Based on microblaze implementation: + * Copyright (C) 2003 John Williams jwilliams@itee.uq.edu.au + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader miles@gnu.org + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + * + * Written by Miles Bader miles@gnu.org + * Microblaze port by John Williams + */ + +#ifndef __ASM_OPENRISC_POSIX_TYPES_H +#define __ASM_OPENRISC_POSIX_TYPES_H + +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char *__kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; + + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +#define __FD_SET(fd, fd_set) \ + __set_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits) +#undef __FD_CLR +#define __FD_CLR(fd, fd_set) \ + __clear_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits) +#undef __FD_ISSET +#define __FD_ISSET(fd, fd_set) \ + __test_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits) +#undef __FD_ZERO +#define __FD_ZERO(fd_set) \ + memset(fd_set, 0, sizeof(*(fd_set *)fd_set)) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* __ASM_OPENRISC_POSIX_TYPES_H */ diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h new file mode 100644 index 0000000..ec98171 --- /dev/null +++ b/arch/c6x/include/asm/processor.h @@ -0,0 +1,4 @@ +#ifndef __ASM_C6X_PROCESSOR_H +#define __ASM_C6X_PROCESSOR_H + +#endif diff --git a/arch/c6x/include/asm/ptrace.h b/arch/c6x/include/asm/ptrace.h new file mode 100644 index 0000000..2eaeb11 --- /dev/null +++ b/arch/c6x/include/asm/ptrace.h @@ -0,0 +1,310 @@ +/* + * linux/include/asm-c6x/ptrace.h + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * Updated for 2.6.34: Mark Salter msalter@redhat.com + * + * 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 __ASM_C6X_PTRACE_H +#define __ASM_C6X_PTRACE_H + +#if defined(__TMS320C6XPLUS__) || defined(_TMS320C6400_PLUS) \ + || defined(__TMS320C66X__) +#define BKPT_OPCODE 0x56454314 /* illegal opcode */ +#else +#define BKPT_OPCODE 0x0000a122 /* BNOP .S2 0,5 */ +#endif + +#ifdef _BIG_ENDIAN +#define PT_LO(odd, even) odd +#define PT_HI(odd, even) even +#else +#define PT_LO(odd, even) even +#define PT_HI(odd, even) odd +#endif + +#if defined(__TMS320C6XPLUS__) || defined(_TMS320C6400_PLUS) || \ + defined(__TMS320C66X__) + +#define PT_A4_ORG PT_LO(1, 0) +#define PT_TSR PT_HI(1, 0) +#define PT_ILC PT_LO(3, 2) +#define PT_RILC PT_HI(3, 2) +#define PT_CSR PT_LO(5, 4) +#define PT_PC PT_HI(5, 4) +#define PT_B16 PT_LO(7, 6) +#define PT_B17 PT_HI(7, 6) +#define PT_B18 PT_LO(9, 8) +#define PT_B19 PT_HI(9, 8) +#define PT_B20 PT_LO(11, 10) +#define PT_B21 PT_HI(11, 10) +#define PT_B22 PT_LO(13, 12) +#define PT_B23 PT_HI(13, 12) +#define PT_B24 PT_LO(15, 14) +#define PT_B25 PT_HI(15, 14) +#define PT_B26 PT_LO(17, 16) +#define PT_B27 PT_HI(17, 16) +#define PT_B28 PT_LO(19, 18) +#define PT_B29 PT_HI(19, 18) +#define PT_B30 PT_LO(21, 20) +#define PT_B31 PT_HI(21, 20) +#define PT_B0 PT_LO(23, 22) +#define PT_B1 PT_HI(23, 22) +#define PT_B2 PT_LO(25, 24) +#define PT_B3 PT_HI(25, 24) +#define PT_B4 PT_LO(27, 26) +#define PT_B5 PT_HI(27, 26) +#define PT_B6 PT_LO(29, 28) +#define PT_B7 PT_HI(29, 28) +#define PT_B8 PT_LO(31, 30) +#define PT_B9 PT_HI(31, 30) +#define PT_B10 PT_LO(33, 32) +#define PT_B11 PT_HI(33, 32) +#define PT_B12 PT_LO(35, 34) +#define PT_B13 PT_HI(35, 34) +#define PT_A16 PT_LO(37, 36) +#define PT_A17 PT_HI(37, 36) +#define PT_A18 PT_LO(39, 38) +#define PT_A19 PT_HI(39, 38) +#define PT_A20 PT_LO(41, 40) +#define PT_A21 PT_HI(41, 40) +#define PT_A22 PT_LO(43, 42) +#define PT_A23 PT_HI(43, 42) +#define PT_A24 PT_LO(45, 44) +#define PT_A25 PT_HI(45, 44) +#define PT_A26 PT_LO(47, 46) +#define PT_A27 PT_HI(47, 46) +#define PT_A28 PT_LO(49, 48) +#define PT_A29 PT_HI(49, 48) +#define PT_A30 PT_LO(51, 50) +#define PT_A31 PT_HI(51, 50) +#define PT_A0 PT_LO(53, 52) +#define PT_A1 PT_HI(53, 52) +#define PT_A2 PT_LO(55, 54) +#define PT_A3 PT_HI(55, 54) +#define PT_A4 PT_LO(57, 56) +#define PT_A5 PT_HI(57, 56) +#define PT_A6 PT_LO(59, 58) +#define PT_A7 PT_HI(59, 58) +#define PT_A8 PT_LO(61, 60) +#define PT_A9 PT_HI(61, 60) +#define PT_A10 PT_LO(63, 62) +#define PT_A11 PT_HI(63, 62) +#define PT_A12 PT_LO(65, 64) +#define PT_A13 PT_HI(65, 64) +#define PT_A14 PT_LO(67, 66) +#define PT_A15 PT_HI(67, 66) +#define PT_B14 PT_LO(69, 68) +#define PT_B15 PT_HI(69, 68) + +#else /* defined(__TMS320C6XPLUS__) */ + +#define PT_A4_ORG PT_LO(1, 0) +#define PT_STKADJ PT_HI(1, 0) +#define PT_CSR PT_LO(3, 2) +#define PT_PC PT_HI(3, 2) +#if defined(_TMS320C6400) +#define PT_B16 PT_LO(5, 4) +#define PT_B17 PT_HI(5, 4) +#define PT_B18 PT_LO(7, 6) +#define PT_B19 PT_HI(7, 6) +#define PT_B20 PT_LO(9, 8) +#define PT_B21 PT_HI(9, 8) +#define PT_B22 PT_LO(11, 10) +#define PT_B23 PT_HI(11, 10) +#define PT_B24 PT_LO(13, 12) +#define PT_B25 PT_HI(13, 12) +#define PT_B26 PT_LO(15, 14) +#define PT_B27 PT_HI(15, 14) +#define PT_B28 PT_LO(17, 16) +#define PT_B29 PT_HI(17, 16) +#define PT_B30 PT_LO(19, 18) +#define PT_B31 PT_HI(19, 18) +#endif /* defined(_TMS320C6400) */ +#define PT_B0 PT_LO(21, 20) +#define PT_B1 PT_HI(21, 20) +#define PT_B2 PT_LO(23, 22) +#define PT_B3 PT_HI(23, 22) +#define PT_B4 PT_LO(25, 24) +#define PT_B5 PT_HI(25, 24) +#define PT_B6 PT_LO(27, 26) +#define PT_B7 PT_HI(27, 26) +#define PT_B8 PT_LO(29, 28) +#define PT_B9 PT_HI(29, 28) +#define PT_B10 PT_LO(31, 30) +#define PT_B11 PT_HI(31, 30) +#define PT_B12 PT_LO(33, 32) +#define PT_B13 PT_HI(33, 32) +#if defined(_TMS320C6400) +#define PT_A16 PT_LO(35, 34) +#define PT_A17 PT_HI(35, 34) +#define PT_A18 PT_LO(37, 36) +#define PT_A19 PT_HI(37, 36) +#define PT_A20 PT_LO(39, 38) +#define PT_A21 PT_HI(39, 38) +#define PT_A22 PT_LO(41, 40) +#define PT_A23 PT_HI(41, 40) +#define PT_A24 PT_LO(43, 42) +#define PT_A25 PT_HI(43, 42) +#define PT_A26 PT_LO(45, 44) +#define PT_A27 PT_HI(45, 44) +#define PT_A28 PT_LO(47, 46) +#define PT_A29 PT_HI(47, 46) +#define PT_A30 PT_LO(49, 48) +#define PT_A31 PT_HI(49, 48) +#endif /* defined(_TMS320C6400) */ +#define PT_A0 PT_LO(51, 50) +#define PT_A1 PT_HI(51, 50) +#define PT_A2 PT_LO(53, 52) +#define PT_A3 PT_HI(53, 52) +#define PT_A4 PT_LO(55, 54) +#define PT_A5 PT_HI(55, 54) +#define PT_A6 PT_LO(57, 56) +#define PT_A7 PT_HI(57, 56) +#define PT_A8 PT_LO(59, 58) +#define PT_A9 PT_HI(59, 58) +#define PT_A10 PT_LO(61, 60) +#define PT_A11 PT_HI(61, 60) +#define PT_A12 PT_LO(63, 62) +#define PT_A13 PT_HI(63, 62) +#define PT_A14 PT_LO(65, 64) +#define PT_A15 PT_HI(65, 64) +#define PT_B14 PT_LO(67, 66) +#define PT_B15 PT_HI(67, 66) + +#endif /* defined(__TMS320C6XPLUS__) */ + +#define PT_DP PT_B14 /* Data Segment Pointer (B14) */ +#define PT_SP PT_B15 /* Stack Pointer (B15) */ + +#ifndef __ASSEMBLY__ + +#ifdef _BIG_ENDIAN +#define REG_PAIR(odd, even) unsigned long odd; unsigned long even +#else +#define REG_PAIR(odd, even) unsigned long even; unsigned long odd +#endif + +/* + * this struct defines the way the registers are stored on the + * stack during a system call. fields defined with REG_PAIR + * are saved and restored using double-word memory operations + * which means the word ordering of the pair depends on endianess. + */ +struct pt_regs { +#if defined(__TMS320C6XPLUS__) || defined(_TMS320C6400_PLUS) || \ + defined(__TMS320C66X__) + REG_PAIR(tsr, orig_a4); + REG_PAIR(rilc, ilc); +#else + REG_PAIR(stkadj, orig_a4); +#endif + REG_PAIR(pc, csr); + +#if defined(_TMS320C6400) + REG_PAIR(b17, b16); + REG_PAIR(b19, b18); + REG_PAIR(b21, b20); + REG_PAIR(b23, b22); + REG_PAIR(b25, b24); + REG_PAIR(b27, b26); + REG_PAIR(b29, b28); + REG_PAIR(b31, b30); +#endif /* defined(_TMS320C6400) */ + + REG_PAIR(b1, b0); + REG_PAIR(b3, b2); + REG_PAIR(b5, b4); + REG_PAIR(b7, b6); + REG_PAIR(b9, b8); + REG_PAIR(b11, b10); + REG_PAIR(b13, b12); + +#if defined(_TMS320C6400) + REG_PAIR(a17, a16); + REG_PAIR(a19, a18); + REG_PAIR(a21, a20); + REG_PAIR(a23, a22); + REG_PAIR(a25, a24); + REG_PAIR(a27, a26); + REG_PAIR(a29, a28); + REG_PAIR(a31, a30); +#endif /* defined(_TMS320C6400) */ + + REG_PAIR(a1, a0); + REG_PAIR(a3, a2); + REG_PAIR(a5, a4); + REG_PAIR(a7, a6); + REG_PAIR(a9, a8); + REG_PAIR(a11, a10); + REG_PAIR(a13, a12); + + REG_PAIR(a15, a14); + REG_PAIR(sp, dp); +}; + +/* + * This is the extended stack used by the context switcher + */ +struct switch_stack { +#if defined(__TMS320C6XPLUS__) || defined(_TMS320C6400_PLUS) || \ + defined(__TMS320C66X__) + REG_PAIR(rilc, ilc); +#endif + REG_PAIR(a11, a10); + REG_PAIR(a13, a12); + REG_PAIR(a15, a14); + REG_PAIR(b11, b10); + REG_PAIR(b13, b12); + + unsigned long retpc; + unsigned long pad; +}; + +/* + * These are 'magic' values for PTRACE_PEEKUSR that return info about where a + * process is located in memory. + */ +#define PT_TEXT_ADDR 0x10000 +#define PT_DATA_ADDR 0x10004 +#define PT_TEXT_END_ADDR 0x10008 + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 + +/* get the ELF DSBT loadmap address */ +#define PTRACE_GETDSBT 31 +/* [addr] request the executable loadmap */ +#define PTRACE_GETDSBT_EXEC 0 +/* [addr] request the interpreter loadmap */ +#define PTRACE_GETDSBT_INTERP 1 + +#ifdef __KERNEL__ + +/* interrupt enable by default */ +/* used in /include/asm/processor.h*/ +#define DEFAULT_CSR 0x0001 + +#if !defined(CONFIG_TMS320C64XPLUS) && !defined(CONFIG_TMS320C66X) +extern unsigned long current_ksp; +#define user_mode(regs) (((((regs)->sp) ^ current_ksp) >> PAGE_SHIFT) != 0) +#else +#define user_mode(regs) ((((regs)->tsr) & 0x40) != 0) +#endif +#define instruction_pointer(regs) ((regs)->pc) +#define profile_pc(regs) instruction_pointer(regs) +extern void show_regs(struct pt_regs *); + +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_C6X_PTRACE_H */ diff --git a/arch/c6x/include/asm/sizes.h b/arch/c6x/include/asm/sizes.h new file mode 100644 index 0000000..b0b4f6a --- /dev/null +++ b/arch/c6x/include/asm/sizes.h @@ -0,0 +1,51 @@ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* Size defintions + * Copyright (C) ARM Limited 1998. All rights reserved. + */ + +#ifndef __sizes_h +#define __sizes_h 1 + +/* handy sizes */ +#define SZ_1K 0x00000400 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_32K 0x00008000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_31M 0x01F00000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + +#endif + +/* END */ diff --git a/arch/c6x/include/asm/string.h b/arch/c6x/include/asm/string.h new file mode 100644 index 0000000..98e26ed --- /dev/null +++ b/arch/c6x/include/asm/string.h @@ -0,0 +1,26 @@ +/* + * linux/include/asm-c6x/string.h + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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 __ASM_C6X_STRING_H +#define __ASM_C6X_STRING_H + +extern void *memcpy(void *to, const void *from, size_t n); +extern void *memset(void *s, int c, size_t count); +extern int memcmp(const void *cs, const void *ct, size_t count); +extern void *memmove(void *s1, const void *s2, size_t n); + +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCMP + +#endif /* __ASM_C6X_STRING_H */ diff --git a/arch/c6x/include/asm/types.h b/arch/c6x/include/asm/types.h new file mode 100644 index 0000000..857c792 --- /dev/null +++ b/arch/c6x/include/asm/types.h @@ -0,0 +1,53 @@ +#ifndef __ASM_C6X_TYPES_H +#define __ASM_C6X_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +typedef unsigned long phys_addr_t; +typedef unsigned long phys_size_t; + +#endif /* __KERNEL__ */ + +#endif diff --git a/arch/c6x/include/asm/u-boot-c6x.h b/arch/c6x/include/asm/u-boot-c6x.h new file mode 100644 index 0000000..2367516 --- /dev/null +++ b/arch/c6x/include/asm/u-boot-c6x.h @@ -0,0 +1,14 @@ +/* (C) Copyright 2012 Dmitry Bondar bond@inmys.ru + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. +*/ + +#ifndef _U_BOOT_C6X_H_ +#define _U_BOOT_C6X_H_ 1 + +extern ulong __bss_start; +extern ulong __bss_end__; + +#endif /* _U_BOOT_C6X_H_ */ + diff --git a/arch/c6x/include/asm/u-boot.h b/arch/c6x/include/asm/u-boot.h new file mode 100644 index 0000000..759d976 --- /dev/null +++ b/arch/c6x/include/asm/u-boot.h @@ -0,0 +1,57 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger mgroeger@sysgo.de + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke azu@sysgo.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ******************************************************************** + * NOTE: This header file defines an interface to U-Boot. Including + * this (unmodified) header file in another file is considered normal + * use of U-Boot, and does *not* fall under the heading of "derived + * work". + ******************************************************************** + */ + +#ifndef _U_BOOT_H_ +#define _U_BOOT_H_ 1 + +typedef struct bd_info { + int bi_baudrate; /* serial console baudrate */ + unsigned long bi_ip_addr; /* IP Address */ + ulong bi_arch_number; /* unique id for this board */ + ulong bi_boot_params; /* where this board expects params */ + unsigned long bi_arm_freq; /* arm frequency */ + unsigned long bi_dsp_freq; /* dsp core frequency */ + unsigned long bi_ddr_freq; /* ddr frequency */ + struct /* RAM configuration */ + { + ulong start; + ulong size; + } bi_dram[CONFIG_NR_DRAM_BANKS]; +} bd_t; + +/* For image.h:image_check_target_arch() */ +#define IH_ARCH_DEFAULT IH_ARCH_ARM + +#endif /* _U_BOOT_H_ */ diff --git a/arch/c6x/include/asm/unaligned.h b/arch/c6x/include/asm/unaligned.h new file mode 100644 index 0000000..6cecbbb --- /dev/null +++ b/arch/c6x/include/asm/unaligned.h @@ -0,0 +1 @@ +#include <asm-generic/unaligned.h> diff --git a/arch/c6x/lib/Makefile b/arch/c6x/lib/Makefile new file mode 100644 index 0000000..8214df7 --- /dev/null +++ b/arch/c6x/lib/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(ARCH).o + +SOBJS-y += csum_64plus.o memcpy_64plus.o strasgi_64plus.o +SOBJS-y += unaligned.o divu.o divi.o pop_rts.o push_rts.o remi.o remu.o \ + strasgi.o llshru.o llshr.o llshl.o negll.o mpyll.o \ + divremi.o divremu.o delay.o + +COBJS-y += memcmp.o memmove.o memset.o divull.o + +COBJS-y += board.o +COBJS-y += bootm.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/c6x/lib/board.c b/arch/c6x/lib/board.c new file mode 100644 index 0000000..00a5a49 --- /dev/null +++ b/arch/c6x/lib/board.c @@ -0,0 +1,196 @@ +/* + * (C) Copyright 2012 Dmitry Bondar bond@inmys.ru + * + * (C) Copyright 2011 + * Julius Baxter, julius@opencores.org + * + * (C) Copyright 2003, Psyent Corporation <www.psyent.com> + * Scott McNutt smcnutt@psyent.com + * + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <stdio_dev.h> +#include <watchdog.h> +#include <malloc.h> +#include <mmc.h> +#include <net.h> +#ifdef CONFIG_STATUS_LED +#include <status_led.h> +#endif +#ifdef CONFIG_CMD_NAND +#include <nand.h> /* cannot even include nand.h if it isnt configured */ +#endif + +#include <timestamp.h> +#include <version.h> +#include <asm/u-boot-c6x.h> + +DECLARE_GLOBAL_DATA_PTR; + +static int display_banner(void) +{ + printf("\n\n%s\n\n", version_string); + return 0; +} + +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) +static int init_func_i2c(void) +{ + puts("I2C: "); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + puts("ready\n"); + return 0; +} +#endif + + +/* + * Initialization sequence + */ +static int (* const init_sequence[])(void) = { +#if defined(CONFIG_ARCH_CPU_INIT) + arch_cpu_init, /* basic arch cpu dependent setup */ +#endif +#if defined(CONFIG_BOARD_EARLY_INIT_F) + board_early_init_f, +#endif + timer_init, /* initialize timer */ + env_init, + serial_init, + console_init_f, + + display_banner, /* say that we are here */ +#if defined(CONFIG_DISPLAY_BOARDINFO) + checkboard, /* display board info */ +#endif +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) + init_func_i2c, +#endif +}; + + +static int clear_bss(void) +{ + ulong dst_addr = (ulong)&__bss_start; + size_t len = (size_t)&__bss_end__ - (size_t)&__bss_start; + memset((void *)dst_addr, 0x00, len); + return 0; +} + +/***********************************************************************/ +void board_init_f(ulong bootflag) +{ + bd_t *bd; + int i; + + clear_bss(); + + gd = (gd_t *)CONFIG_SYS_GBL_DATA_ADDR; + __asm__ __volatile__("" : : : "memory"); + memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE); + + gd->bd = (bd_t *)(gd+1); /* At end of global data */ + gd->baudrate = CONFIG_BAUDRATE; + + bd = gd->bd; +#ifndef CONFIG_SYS_NO_FLASH + bd->bi_flashstart = CONFIG_SYS_FLASH_BASE; +#endif + bd->bi_baudrate = CONFIG_BAUDRATE; + + for (i = 0; i < ARRAY_SIZE(init_sequence); i++) { + WATCHDOG_RESET(); + if (init_sequence[i]()) + hang(); + } + + WATCHDOG_RESET(); + + /* The Malloc area is immediately below the monitor copy in RAM */ + mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN); + + board_init(); + +#ifndef CONFIG_SYS_NO_FLASH + WATCHDOG_RESET(); + bd->bi_flashsize = flash_init(); +#endif + +#ifdef CONFIG_CMD_NAND + puts("NAND: "); + nand_init(); +#endif + +#ifdef CONFIG_GENERIC_MMC + puts("MMC: "); + mmc_initialize(bd); +#endif + + WATCHDOG_RESET(); + env_relocate(); + + WATCHDOG_RESET(); + stdio_init(); + jumptable_init(); + console_init_r(); + + WATCHDOG_RESET(); +/* interrupt_init();*/ + +#if defined(CONFIG_BOARD_LATE_INIT) + board_late_init(); +#endif + +#if defined(CONFIG_CMD_NET) + puts("NET: "); + eth_initialize(bd); +#endif + + /* main_loop */ + for (;;) { + WATCHDOG_RESET(); + main_loop(); + } +} + + +/***********************************************************************/ + +void hang(void) +{ + disable_interrupts(); + puts("### ERROR ### Please reset board ###\n"); + + while (1) + /*nothing*/; +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + reset_cpu(0); + return 0; +} + diff --git a/arch/c6x/lib/bootm.c b/arch/c6x/lib/bootm.c new file mode 100644 index 0000000..4bafacf --- /dev/null +++ b/arch/c6x/lib/bootm.c @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2003, Psyent Corporation <www.psyent.com> + * Scott McNutt smcnutt@psyent.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> + +int disable_interrupts() +{ + return 0; +} + +void enable_interrupts() +{ +} + +int do_bootm_linux(int flag, int argc, char * const argv[], + bootm_headers_t *images) +{ + void (*kernel)() = (void *)images->ep; + char *commandline = getenv("bootargs"); + if (commandline) { + char *dst = (char *)images->ep + 0x1000; + strncpy(dst, commandline, 1023); + dst[1023] = 0; + } + { + unsigned int *ptr = (unsigned int *)0xc1f00000; + ptr[0] = 0x64000001; /*TAG_SOL*/ + ptr[1] = 0; /*size SOL*/ + ptr[2] = 0x64000002; /*TAG_EOL*/ + ptr[3] = 0; + } + asm("MVKL .S1 0x54694265,A4"); + asm("MVKH .S1 0x54694265,A4"); + asm("MVKL .S2 0xc1f00000,B4"); + asm("MVKH .S2 0xc1f00000,B4"); + kernel(); + printf("after kernel\n"); + return 1; +} diff --git a/arch/c6x/lib/csum_64plus.S b/arch/c6x/lib/csum_64plus.S new file mode 100644 index 0000000..db26ed4 --- /dev/null +++ b/arch/c6x/lib/csum_64plus.S @@ -0,0 +1,408 @@ +; +; linux/arch/c6x/lib/csum_64plus.s +; +; Port on Texas Instruments TMS320C6x architecture +; +; Copyright (C) 2006, 2009, 2010 Texas Instruments Incorporated +; Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) +; +; 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. +; + +; +;unsigned int csum_partial_copy(const char *src, char * dst, +; int len, int sum) +; +; A4: src +; B4: dst +; A6: len +; B6: sum +; return csum in A4 +; + + .global csum_partial_copy + .text + +csum_partial_copy: + MVC .S2 ILC,B30 + + MV .D1X B6,A31 ; given csum + ZERO .D1 A9 ; csum (a side) +|| ZERO .D2 B9 ; csum (b side) +|| SHRU .S2X A6,2,B5 ; len / 4 + + ;; Check alignment and size + AND .S1 3,A4,A1 +|| AND .S2 3,B4,B0 + OR .L2X B0,A1,B0 ; non aligned condition +|| MVC .S2 B5,ILC +|| MVK .D2 1,B2 +|| MV .D1X B5,A1 ; words condition + [!A1] B .S1 L8 + [B0] BNOP .S1 L6,5 + + SPLOOP 1 + + ;; Main loop for aligned words + LDW .D1T1 *A4++,A7 + NOP 4 + MV .S2X A7,B7 +|| EXTU .S1 A7,0,16,A16 + STW .D2T2 B7,*B4++ +|| MPYU .M2 B7,B2,B8 +|| ADD .L1 A16,A9,A9 + NOP + SPKERNEL 8,0 +|| ADD .L2 B8,B9,B9 + + ZERO .D1 A1 +|| ADD .L1X A9,B9,A9 ; add csum from a and b sides + +L6: + [!A1] BNOP .S1 L8,5 + + ;; Main loop for non-aligned words + SPLOOP 2 + || MVK .L1 1,A2 + + LDNW .D1T1 *A4++,A7 + NOP 3 + + NOP + MV .S2X A7,B7 + || EXTU .S1 A7,0,16,A16 + || MPYU .M1 A7,A2,A8 + + ADD .L1 A16,A9,A9 + SPKERNEL 6,0 + || STNW .D2T2 B7,*B4++ + || ADD .L1 A8,A9,A9 + +L8: AND .S2X 2,A6,B5 + CMPGT .L2 B5,0,B0 + [!B0] BNOP .S1 L82,4 + + ;; Manage half-word + ZERO .L1 A7 +|| ZERO .D1 A8 + +#ifdef CONFIG_CPU_BIG_ENDIAN + + LDBU .D1T1 *A4++,A7 + LDBU .D1T1 *A4++,A8 + NOP 3 + SHL .S1 A7,8,A0 + ADD .S1 A8,A9,A9 + STB .D2T1 A7,*B4++ +|| ADD .S1 A0,A9,A9 + STB .D2T1 A8,*B4++ + +#else + + LDBU .D1T1 *A4++,A7 + LDBU .D1T1 *A4++,A8 + NOP 3 + ADD .S1 A7,A9,A9 + SHL .S1 A8,8,A0 + + STB .D2T1 A7,*B4++ +|| ADD .S1 A0,A9,A9 + STB .D2T1 A8,*B4++ + +#endif + + ;; Manage eventually the last byte +L82: AND .S2X 1,A6,B0 + [!B0] BNOP .S1 L9,5 + +|| ZERO .L1 A7 + +L83: LDBU .D1T1 *A4++,A7 + NOP 4 + + MV .L2X A7,B7 + +#ifdef CONFIG_CPU_BIG_ENDIAN + + STB .D2T2 B7,*B4++ +|| SHL .S1 A7,8,A7 + ADD .S1 A7,A9,A9 + +#else + + STB .D2T2 B7,*B4++ +|| ADD .S1 A7,A9,A9 + +#endif + + ;; Fold the csum +L9: SHRU .S2X A9,16,B0 + [!B0] BNOP .S1 L10,5 + +L91: SHRU .S2X A9,16,B4 +|| EXTU .S1 A9,16,16,A3 + ADD .D1X A3,B4,A9 + + SHRU .S1 A9,16,A0 + [A0] BNOP .S1 L91,5 + +L10: ADD .D1 A31,A9,A9 + MV .D1 A9,A4 + + BNOP .S2 B3,4 + MVC .S2 B30,ILC + + .global csum_partial_copy_old + .text + +; +;unsigned short +;ip_fast_csum(unsigned char *iph, unsigned int ihl) +;{ +; unsigned int checksum = 0; +; unsigned short *tosum = (unsigned short *) iph; +; int len; +; +; len = ihl*4; +; +; if (len <= 0) +; return 0; +; +; while(len) { +; len -= 2; +; checksum += *tosum++; +; } +; if (len & 1) +; checksum += *(unsigned char*) tosum; +; +; while(checksum >> 16) +; checksum = (checksum & 0xffff) + (checksum >> 16); +; +; return ~checksum; +;} +; +; A4: iph +; B4: ihl +; return checksum in A4 +; + + .global ip_fast_csum + .text + +ip_fast_csum: + ZERO .D1 A5 + || MVC .S2 ILC,B30 + SHL .S2 B4,2,B0 + CMPGT .L2 B0,0,B1 + [!B1] BNOP .S1 L15,4 + [!B1] ZERO .D1 A3 + + [!B0] B .S1 L12 + SHRU .S2 B0,1,B0 + MVC .S2 B0,ILC + NOP 3 + + SPLOOP 1 + LDHU .D1T1 *A4++,A3 + NOP 3 + NOP + SPKERNEL 5,0 + || ADD .L1 A3,A5,A5 + +L12: SHRU .S1 A5,16,A0 + [!A0] BNOP .S1 L14,5 + +L13: SHRU .S2X A5,16,B4 + EXTU .S1 A5,16,16,A3 + ADD .D1X A3,B4,A5 + SHRU .S1 A5,16,A0 + [A0] BNOP .S1 L13,5 + +L14: NOT .D1 A5,A3 + EXTU .S1 A3,16,16,A3 + +L15: BNOP .S2 B3,3 + MVC .S2 B30,ILC + MV .D1 A3,A4 + +; +;unsigned short +;do_csum(unsigned char *buff, unsigned int len) +;{ +; int odd, count; +; unsigned int result = 0; +; +; if (len <= 0) +; goto out; +; odd = 1 & (unsigned long) buff; +; if (odd) { +;#ifdef __LITTLE_ENDIAN +; result += (*buff << 8); +;#else +; result = *buff; +;#endif +; 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 int carry = 0; +; do { +; unsigned int w = *(unsigned int *) 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) +;#ifdef __LITTLE_ENDIAN +; result += *buff; +;#else +; result += (*buff << 8); +;#endif +; result = (result & 0xffff) + (result >> 16); +; /* add up carry.. */ +; result = (result & 0xffff) + (result >> 16); +; if (odd) +; result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +;out: +; return result; +;} +; +; A4: buff +; B4: len +; return checksum in A4 +; + .global do_csum + .text +do_csum: + CMPGT .L2 B4,0,B0 + [!B0] BNOP .S1 L26,3 + EXTU .S1 A4,31,31,A0 + + MV .L1 A0,A3 +|| MV .S1X B3,A5 +|| MV .L2 B4,B3 +|| ZERO .D1 A1 + +#ifdef CONFIG_CPU_BIG_ENDIAN + [A0] SUB .L2 B3,1,B3 +|| [A0] LDBU .D1T1 *A4++,A1 +#else + [!A0] BNOP .S1 L21,5 +|| [A0] LDBU .D1T1 *A4++,A0 + SUB .L2 B3,1,B3 +|| SHL .S1 A0,8,A1 +L21: +#endif + SHR .S2 B3,1,B0 + [!B0] BNOP .S1 L24,3 + MVK .L1 2,A0 + AND .L1 A4,A0,A0 + + [!A0] BNOP .S1 L22,5 +|| [A0] LDHU .D1T1 *A4++,A0 + SUB .L2 B0,1,B0 +|| SUB .S2 B3,2,B3 +|| ADD .L1 A0,A1,A1 +L22: + SHR .S2 B0,1,B0 +|| ZERO .L1 A0 + + [!B0] BNOP .S1 L23,5 +|| [B0] MVC .S2 B0,ILC + + SPLOOP 3 + SPMASK L1 +|| MV .L1 A1,A2 +|| LDW .D1T1 *A4++,A1 + + NOP 4 + ADD .L1 A0,A1,A0 + ADD .L1 A2,A0,A2 + + SPKERNEL 1,2 +|| CMPGTU .L1 A1,A2,A0 + + ADD .L1 A0,A2,A6 + EXTU .S1 A6,16,16,A7 + SHRU .S2X A6,16,B0 + NOP 1 + ADD .L1X A7,B0,A1 +L23: + MVK .L2 2,B0 + AND .L2 B3,B0,B0 + [B0] LDHU .D1T1 *A4++,A0 + NOP 4 + [B0] ADD .L1 A0,A1,A1 +L24: + EXTU .S2 B3,31,31,B0 +#ifdef CONFIG_CPU_BIG_ENDIAN + [!B0] BNOP .S1 L25,4 +|| [B0] LDBU .D1T1 *A4,A0 + SHL .S1 A0,8,A0 + ADD .L1 A0,A1,A1 +L25: +#else + [B0] LDBU .D1T1 *A4,A0 + NOP 4 + [B0] ADD .L1 A0,A1,A1 +#endif + EXTU .S1 A1,16,16,A0 + SHRU .S2X A1,16,B0 + NOP 1 + ADD .L1X A0,B0,A0 + SHRU .S1 A0,16,A1 + ADD .L1 A0,A1,A0 + EXTU .S1 A0,16,16,A1 + EXTU .S1 A1,16,24,A2 + + EXTU .S1 A1,24,16,A0 +|| MV .L2X A3,B0 + + [B0] OR .L1 A0,A2,A1 +L26: + NOP 1 + BNOP .S2X A5,4 + MV .L1 A1,A4 + +;__wsum csum_partial(const void *buff, int len, __wsum wsum) +;{ +; unsigned int sum = (__force unsigned int)wsum; +; unsigned int result = do_csum(buff, len); +; +; /* add in old sum, and carry.. */ +; result += sum; +; if (sum > result) +; result += 1; +; return (__force __wsum)result; +;} +; + .global csum_partial +csum_partial: + MV .L1X B3,A9 +|| CALLP .S2 do_csum,B3 +|| MV .S1 A6,A8 + BNOP .S2X A9,2 + ADD .L1 A8,A4,A1 + CMPGTU .L1 A8,A1,A0 + ADD .L1 A1,A0,A4 diff --git a/arch/c6x/lib/delay.S b/arch/c6x/lib/delay.S new file mode 100644 index 0000000..44f2a7f --- /dev/null +++ b/arch/c6x/lib/delay.S @@ -0,0 +1,39 @@ +; +; linux/arch/c6x/lib/delay.s +; +; Port on Texas Instruments TMS320C6x architecture +; +; Copyright (C) 2004, 2009, 2010 Texas Instruments Incorporated +; Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) +; +; 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. +; + .sect ".text" + .global _c6x_delay + +_c6x_delay: + bdec .s1 _c6x_delay,A4 + nop 5 + b .s2 B3 + nop 5 + +#ifdef CONFIG_TI_C6X_COMPILER + ;; this is inlined with gcc + + .global _c6x_tickdelay +_c6x_tickdelay: + mvc .s2 TSCL,B1 + add .s2x B1,A4,B1 + || mvk .l2 1,B0 +$0: + [B0] b .s2 $0 + mvc .s2 TSCL,B0 + sub .s2 B0,B1,B0 + cmpgt .l2 0,B0,B0 + nop + nop + b .s2 B3 + nop 5 +#endif diff --git a/arch/c6x/lib/divi.S b/arch/c6x/lib/divi.S new file mode 100644 index 0000000..cfa1e4c --- /dev/null +++ b/arch/c6x/lib/divi.S @@ -0,0 +1,54 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ;; ABI considerations for the divide functions + ;; The following registers are call-used: + ;; __c6xabi_divi A0,A1,A2,A4,A6,B0,B1,B2,B4,B5 + ;; __c6xabi_divu A0,A1,A2,A4,A6,B0,B1,B2,B4 + ;; __c6xabi_remi A1,A2,A4,A5,A6,B0,B1,B2,B4 + ;; __c6xabi_remu A1,A4,A5,A7,B0,B1,B2,B4 + ;; + ;; In our implementation, divu and remu are leaf functions, + ;; while both divi and remi call into divu. + ;; A0 is not clobbered by any of the functions. + ;; divu does not clobber B2 either, which is taken advantage of + ;; in remi. + ;; divi uses B5 to hold the original return address during + ;; the call to divu. + ;; remi uses B2 and A5 to hold the input values during the + ;; call to divu. It stores B3 in on the stack. + +#ifdef CONFIG_TI_C6X_COMPILER + .ref __c6xabi_divu +#endif + .text + .global __c6xabi_divi +__c6xabi_divi: + call .s2 __c6xabi_divu +|| mv .d2 B3, B5 +|| cmpgt .l1 0, A4, A1 +|| cmpgt .l2 0, B4, B1 + + [A1] neg .l1 A4, A4 +|| [B1] neg .l2 B4, B4 +|| xor .s1x A1, B1, A1 + [A1] addkpc .s2 _divu_ret, B3, 4 +_divu_ret: + neg .l1 A4, A4 +|| mv .l2 B3,B5 +|| ret .s2 B5 + nop 5 diff --git a/arch/c6x/lib/divremi.S b/arch/c6x/lib/divremi.S new file mode 100644 index 0000000..b7664c3 --- /dev/null +++ b/arch/c6x/lib/divremi.S @@ -0,0 +1,61 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifdef CONFIG_TI_C6X_COMPILER + .ref __c6xabi_divu +#endif + .text + .global __c6xabi_divremi + +__c6xabi_divremi: + stw .d2t2 B3, *B15--[2] +|| cmpgt .l1 0, A4, A1 +|| cmpgt .l2 0, B4, B2 +|| mv .s1 A4, A5 +|| call .s2 __c6xabi_divu + + [A1] neg .l1 A4, A4 +|| [B2] neg .l2 B4, B4 +|| xor .s2x B2, A1, B0 +|| mv .d2 B4, B2 + + [B0] addkpc .s2 _divu_ret_1, B3, 1 + [!B0] addkpc .s2 _divu_ret_2, B3, 1 + nop 2 +_divu_ret_1: + neg .l1 A4, A4 +_divu_ret_2: + ldw .d2t2 *++B15[2], B3 + +#if defined(CONFIG_TMS320C64XPLUS) || defined(CONFIG_TMS320C66X) + mpy32 .m1x A4, B2, A6 + nop 3 + ret .s2 B3 + sub .l1 A5, A6, A5 + nop 4 +#else + mpyu .m1x A4, B2, A1 + nop 1 + mpylhu .m1x A4, B2, A6 +|| mpylhu .m2x B2, A4, B2 +|| ret .s2 B3 + nop 1 + add .l1x A6, B2, A6 + shl .s1 A6, 16, A6 + add .d1 A6, A1, A6 + sub .l1 A5, A6, A5 +#endif diff --git a/arch/c6x/lib/divremu.S b/arch/c6x/lib/divremu.S new file mode 100644 index 0000000..83e2bb7 --- /dev/null +++ b/arch/c6x/lib/divremu.S @@ -0,0 +1,86 @@ +;; Copyright 2011 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + .text + .global __c6xabi_divremu + +__c6xabi_divremu: + ;; We use a series of up to 31 subc instructions. First, we find + ;; out how many leading zero bits there are in the divisor. This + ;; gives us both a shift count for aligning (shifting) the divisor + ;; to the, and the number of times we have to execute subc. + + ;; At the end, we have both the remainder and most of the quotient + ;; in A4. The top bit of the quotient is computed first and is + ;; placed in A2. + + ;; Return immediately if the dividend is zero. Setting B4 to 1 + ;; is a trick to allow us to leave the following insns in the jump + ;; delay slot without affecting the result. + mv .s2x A4, B1 + +[b1] lmbd .l2 1, B4, B1 +||[!b1] b .s2 B3 ; RETURN A +||[!b1] mvk .d2 1, B4 + +||[!b1] zero .s1 A5 + mv .l1x B1, A6 +|| shl .s2 B4, B1, B4 + + ;; The loop performs a maximum of 28 steps, so we do the + ;; first 3 here. + cmpltu .l1x A4, B4, A2 +[!A2] sub .l1x A4, B4, A4 +|| shru .s2 B4, 1, B4 +|| xor .s1 1, A2, A2 + + shl .s1 A2, 31, A2 +|| [b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 + + ;; RETURN A may happen here (note: must happen before the next branch) +0: + cmpgt .l2 B1, 7, B0 +|| [b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +|| [b0] b .s1 0b +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 +[b1] subc .l1x A4,B4,A4 +|| [b1] add .s2 -1, B1, B1 + ;; loop backwards branch happens here + + ret .s2 B3 +|| mvk .s1 32, A1 + sub .l1 A1, A6, A6 +|| extu .s1 A4, A6, A5 + shl .s1 A4, A6, A4 + shru .s1 A4, 1, A4 +|| sub .l1 A6, 1, A6 + or .l1 A2, A4, A4 + shru .s1 A4, A6, A4 + nop diff --git a/arch/c6x/lib/divu.S b/arch/c6x/lib/divu.S new file mode 100644 index 0000000..340b536 --- /dev/null +++ b/arch/c6x/lib/divu.S @@ -0,0 +1,100 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ;; ABI considerations for the divide functions + ;; The following registers are call-used: + ;; __c6xabi_divi A0,A1,A2,A4,A6,B0,B1,B2,B4,B5 + ;; __c6xabi_divu A0,A1,A2,A4,A6,B0,B1,B2,B4 + ;; __c6xabi_remi A1,A2,A4,A5,A6,B0,B1,B2,B4 + ;; __c6xabi_remu A1,A4,A5,A7,B0,B1,B2,B4 + ;; + ;; In our implementation, divu and remu are leaf functions, + ;; while both divi and remi call into divu. + ;; A0 is not clobbered by any of the functions. + ;; divu does not clobber B2 either, which is taken advantage of + ;; in remi. + ;; divi uses B5 to hold the original return address during + ;; the call to divu. + ;; remi uses B2 and A5 to hold the input values during the + ;; call to divu. It stores B3 in on the stack. + +#ifdef CONFIG_TI_C6X_COMPILER + .def __c6xabi_divu +#endif + .text + .global __c6xabi_divu +__c6xabi_divu: + ;; We use a series of up to 31 subc instructions. First, we find + ;; out how many leading zero bits there are in the divisor. This + ;; gives us both a shift count for aligning (shifting) the divisor + ;; to the, and the number of times we have to execute subc. + + ;; At the end, we have both the remainder and most of the quotient + ;; in A4. The top bit of the quotient is computed first and is + ;; placed in A2. + + ;; Return immediately if the dividend is zero. + mv .s2x A4, B1 + [B1] lmbd .l2 1, B4, B1 +|| [!B1] b .s2 B3 ; RETURN A +|| [!B1] mvk .d2 1, B4 + mv .l1x B1, A6 +|| shl .s2 B4, B1, B4 + + ;; The loop performs a maximum of 28 steps, so we do the + ;; first 3 here. + cmpltu .l1x A4, B4, A2 + [!A2] sub .l1x A4, B4, A4 +|| shru .s2 B4, 1, B4 +|| xor .s1 1, A2, A2 + + shl .s1 A2, 31, A2 +|| [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + + ;; RETURN A may happen here (note: must happen before the next branch) +_divu_loop: + cmpgt .l2 B1, 7, B0 +|| [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 +|| [B0] b .s1 _divu_loop + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + ;; loop backwards branch happens here + + ret .s2 B3 +|| mvk .s1 32, A1 + sub .l1 A1, A6, A6 + shl .s1 A4, A6, A4 + shru .s1 A4, 1, A4 +|| sub .l1 A6, 1, A6 + or .l1 A2, A4, A4 + shru .s1 A4, A6, A4 + nop + diff --git a/arch/c6x/lib/divull.c b/arch/c6x/lib/divull.c new file mode 100644 index 0000000..8c00edc --- /dev/null +++ b/arch/c6x/lib/divull.c @@ -0,0 +1,336 @@ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002 Free Software Foundation, Inc. + +This code was pulled from an old (GPLv2) libgcc. + +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, or (at your option) any later version. + +In addition to the permissions in the GNU General Public License, 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 License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This program 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 GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +#include <linux/types.h> +#include <linux/bitops.h> + +#ifdef CONFIG_TI_C6X_COMPILER +#define count_leading_zeros(count, x) (count) = _lmbd(1, (x)) +#else +static inline unsigned __clz(unsigned x) +{ + asm(" lmbd .l1 1,%0,%0\n" : "+a"(x)); + return x; +} +#define count_leading_zeros(count, x) (count) = __clz(x) +#endif + +#define W_TYPE_SIZE 32 + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((uint32_t) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((uint32_t) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((uint32_t) (t) >> (W_TYPE_SIZE / 2)) + + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + uint32_t __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + uint32_t __x0, __x1, __x2, __x3; \ + uint16_t __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart(u); \ + __uh = __ll_highpart(u); \ + __vl = __ll_lowpart(v); \ + __vh = __ll_highpart(v); \ + \ + __x0 = (uint32_t) __ul * __vl; \ + __x1 = (uint32_t) __ul * __vh; \ + __x2 = (uint32_t) __uh * __vl; \ + __x3 = (uint32_t) __uh * __vh; \ + \ + __x1 += __ll_highpart(__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart(__x1); \ + (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0); \ + } while (0) + +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + uint32_t __d1, __d0, __q1, __q0; \ + uint32_t __r1, __r0, __m; \ + __d1 = __ll_highpart(d); \ + __d0 = __ll_lowpart(d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (uint32_t) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart(n0); \ + if (__r1 < __m) { \ + __q1--, __r1 += (d); \ + /* i.e. we didn't get carry when adding to __r1 */ \ + if (__r1 >= (d)) \ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (uint32_t) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart(n0); \ + if (__r0 < __m) { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (uint32_t) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c + +struct llstruct { +#ifdef CONFIG_CPU_BIG_ENDIAN + uint32_t high; + uint32_t low; +#else + uint32_t low; + uint32_t high; +#endif +}; + +typedef union { + struct llstruct s; + int64_t ll; +} llunion_t; + +static inline uint64_t __udivmoddi4(uint64_t n, uint64_t d, uint64_t *rp) +{ + llunion_t ww; + llunion_t nn, dd; + llunion_t rr; + uint32_t d0, d1, n0, n1, n2; + uint32_t q0, q1; + uint32_t b, bm; + + nn.ll = n; + dd.ll = d; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !UDIV_NEEDS_NORMALIZATION + if (d1 == 0) { + if (d0 > n1) { + /* 0q = nn / 0D */ + + udiv_qrnnd(q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } else { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd(q1, n1, 0, n1, d0); + udiv_qrnnd(q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) { + if (d0 > n1) { + /* 0q = nn / 0D */ + + count_leading_zeros(bm, d0); + + if (bm != 0) { + /* Normalize, i.e. make the most significant + bit of the denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd(q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } else { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros(bm, d0); + + if (bm == 0) { + /* From (n1 >= d0) /\ (the most significant bit + of d0 is set), conclude (the most significant + bit of n1 is set) /\ (the leading quotient + digit q1 = 1). + + This special case is necessary, not an + optimization. (Shifts counts of W_TYPE_SIZE + are undefined.) */ + + n1 -= d0; + q1 = 1; + } else { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd(q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd(q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else { + if (d1 > n1) { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } else { + /* 0q = NN / dd */ + + count_leading_zeros(bm, d1); + if (bm == 0) { + /* From (n1 >= d1) /\ (the most significant bit + of d1 is set), conclude (the most significant + bit of n1 is set) /\ (the quotient digit + q0 = 0 or 1). + + This special case is necessary, not an + optimization. */ + + /* The condition on the next line takes + advantage of that n1 >= d1 (true due to + program flow). */ + if (n1 > d1 || n0 >= d0) { + q0 = 1; + sub_ddmmss(n1, n0, n1, n0, d1, d0); + } else + q0 = 0; + + q1 = 0; + + if (rp != 0) { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } else { + uint32_t m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd(q0, n1, n2, n1, d1); + umul_ppmm(m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) { + q0--; + sub_ddmmss(m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) { + sub_ddmmss(n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + ww.s.low = q0; + ww.s.high = q1; + return ww.ll; +} + +uint64_t +__c6xabi_divull(uint64_t n, uint64_t d) +{ + return __udivmoddi4(n, d, (uint64_t *)0); +} + diff --git a/arch/c6x/lib/llshl.S b/arch/c6x/lib/llshl.S new file mode 100644 index 0000000..99b739e --- /dev/null +++ b/arch/c6x/lib/llshl.S @@ -0,0 +1,36 @@ +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Contributed by Mark Salter msalter@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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;; uint64_t __c6xabi_llshl(uint64_t val, uint shift) + + .text + .global __c6xabi_llshl +__c6xabi_llshl: + mv .l1x B4,A1 + [!A1] b .s2 B3 ; just return if zero shift + mvk .s1 32,A0 + sub .d1 A0,A1,A0 + cmplt .l1 0,A0,A2 + [A2] shru .s1 A4,A0,A0 + [!A2] neg .l1 A0,A5 +|| [A2] shl .s1 A5,A1,A5 + [!A2] shl .s1 A4,A5,A5 +|| [A2] or .d1 A5,A0,A5 +|| [!A2] mvk .l1 0,A4 + [A2] shl .s1 A4,A1,A4 + bnop .s2 B3,5 + diff --git a/arch/c6x/lib/llshr.S b/arch/c6x/lib/llshr.S new file mode 100644 index 0000000..989feed --- /dev/null +++ b/arch/c6x/lib/llshr.S @@ -0,0 +1,36 @@ +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Contributed by Mark Salter msalter@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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;; uint64_t __c6xabi_llshr(uint64_t val, uint shift) + + .text + .global __c6xabi_llshr +__c6xabi_llshr: + mv .l1x B4,A1 + [!A1] b .s2 B3 ; return if zero shift count + mvk .s1 32,A0 + sub .d1 A0,A1,A0 + cmplt .l1 0,A0,A2 + [A2] shl .s1 A5,A0,A0 + nop + [!A2] neg .l1 A0,A4 +|| [A2] shru .s1 A4,A1,A4 + [!A2] shr .s1 A5,A4,A4 +|| [A2] or .d1 A4,A0,A4 + [!A2] shr .s1 A5,0x1f,A5 + [A2] shr .s1 A5,A1,A5 + bnop .s2 B3,5 diff --git a/arch/c6x/lib/llshru.S b/arch/c6x/lib/llshru.S new file mode 100644 index 0000000..07a4631 --- /dev/null +++ b/arch/c6x/lib/llshru.S @@ -0,0 +1,36 @@ +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Contributed by Mark Salter msalter@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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;; uint64_t __c6xabi_llshru(uint64_t val, uint shift) + + .text + .global __c6xabi_llshru +__c6xabi_llshru: + mv .l1x B4,A1 + [!A1] b .s2 B3 ; return if zero shift count + mvk .s1 32,A0 + sub .d1 A0,A1,A0 + cmplt .l1 0,A0,A2 + [A2] shl .s1 A5,A0,A0 + nop + [!A2] neg .l1 A0,A4 +|| [A2] shru .s1 A4,A1,A4 + [!A2] shru .s1 A5,A4,A4 +|| [A2] or .d1 A4,A0,A4 +|| [!A2] mvk .l1 0,A5 + [A2] shru .s1 A5,A1,A5 + bnop .s2 B3,5 diff --git a/arch/c6x/lib/memcmp.c b/arch/c6x/lib/memcmp.c new file mode 100644 index 0000000..e3a98bc --- /dev/null +++ b/arch/c6x/lib/memcmp.c @@ -0,0 +1,24 @@ +/* + * linux/arch/c6x/lib/memcmp.c + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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. + */ +#include <linux/types.h> + +int memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if (*su1 != *su2) + return (*su1 < *su2) ? -1 : 1; + return 0; +} + diff --git a/arch/c6x/lib/memcpy_64plus.S b/arch/c6x/lib/memcpy_64plus.S new file mode 100644 index 0000000..ce1d7c6 --- /dev/null +++ b/arch/c6x/lib/memcpy_64plus.S @@ -0,0 +1,45 @@ +; Port on Texas Instruments TMS320C6x architecture +; +; Copyright (C) 2006, 2009, 2010 Texas Instruments Incorporated +; Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) +; +; 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. +; + + .global memcpy + .text + +memcpy: + AND .L1 0x1,A6,A0 + || AND .S1 0x2,A6,A1 + || AND .L2X 0x4,A6,B0 + || MV .D1 A4,A3 + || MVC .S2 ILC,B2 + + [A0] LDB .D2T1 *B4++,A5 + [A1] LDB .D2T1 *B4++,A7 + [A1] LDB .D2T1 *B4++,A8 + [B0] LDNW .D2T1 *B4++,A9 + || SHRU .S2X A6,0x3,B1 + [!B1] BNOP .S2 B3,1 + + [A0] STB .D1T1 A5,*A3++ + ||[B1] MVC .S2 B1,ILC + [A1] STB .D1T1 A7,*A3++ + [A1] STB .D1T1 A8,*A3++ + [B0] STNW .D1T1 A9,*A3++ ; return when len < 8 + + SPLOOP 2 + + LDNDW .D2T1 *B4++,A9:A8 + NOP 3 + + NOP + SPKERNEL 0,0 + || STNDW .D1T1 A9:A8,*A3++ + + BNOP .S2 B3,4 + MVC .S2 B2,ILC + diff --git a/arch/c6x/lib/memmove.c b/arch/c6x/lib/memmove.c new file mode 100644 index 0000000..5672937 --- /dev/null +++ b/arch/c6x/lib/memmove.c @@ -0,0 +1,30 @@ +/* + * linux/arch/c6x/lib/memmove.c + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2005, 2009 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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. + */ +#include <linux/types.h> +#include <linux/string.h> + +void *memmove(void *s1, const void *s2, size_t n) +{ + register char *s = (char *) s1; + register const char *p = (const char *) s2; + + if (p >= s) { + return memcpy(s, p, n); + } else { + while (n) { + --n; + s[n] = p[n]; + } + } + return s1; +} diff --git a/arch/c6x/lib/memset.c b/arch/c6x/lib/memset.c new file mode 100644 index 0000000..da4275b --- /dev/null +++ b/arch/c6x/lib/memset.c @@ -0,0 +1,20 @@ +/* + * linux/arch/c6x/lib/memcmp.c + * + * Port on Texas Instruments TMS320C6x architecture + * + * Copyright (C) 2004, 2009 Texas Instruments Incorporated + * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) + * + * 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. + */ +#include <linux/types.h> +void *memset(void *mem, register int ch, register size_t length) +{ + register char *m = (char *)mem - 1; + while (length--) + *++m = ch; + return mem; +} diff --git a/arch/c6x/lib/mpyll.S b/arch/c6x/lib/mpyll.S new file mode 100644 index 0000000..8da8417 --- /dev/null +++ b/arch/c6x/lib/mpyll.S @@ -0,0 +1,47 @@ +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Contributed by Mark Salter msalter@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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ;; uint64_t __c6xabi_mpyll(uint64_t x, uint64_t y) + ;; + ;; 64x64 multiply + ;; First compute partial results using 32-bit parts of x and y: + ;; + ;; b63 b32 b31 b0 + ;; ----------------------------- + ;; | 1 | 0 | + ;; ----------------------------- + ;; + ;; P0 = X0*Y0 + ;; P1 = X0*Y1 + X1*Y0 + ;; P2 = X1*Y1 + ;; + ;; result = (P2 << 64) + (P1 << 32) + P0 + ;; + ;; Since the result is also 64-bit, we can skip the P2 term. + + .text + .global __c6xabi_mpyll +__c6xabi_mpyll: + mpy32u .m1x A4,B4,A1:A0 ; X0*Y0 + b .s2 B3 + || mpy32u .m2x B5,A4,B1:B0 ; X0*Y1 (don't need upper 32-bits) + || mpy32u .m1x A5,B4,A3:A2 ; X1*Y0 (don't need upper 32-bits) + nop + nop + mv .s1 A0,A4 + add .l1x A2,B0,A5 + add .s1 A1,A5,A5 diff --git a/arch/c6x/lib/negll.S b/arch/c6x/lib/negll.S new file mode 100644 index 0000000..7747521 --- /dev/null +++ b/arch/c6x/lib/negll.S @@ -0,0 +1,29 @@ +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Contributed by Mark Salter msalter@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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +;; int64_t __c6xabi_negll(int64_t val) + + .text + .global __c6xabi_negll +__c6xabi_negll: + b .s2 B3 + mvk .l1 0,A0 + subu .l1 A0,A4,A3:A2 + sub .l1 A0,A5,A0 +|| ext .s1 A3,24,24,A5 + add .l1 A5,A0,A5 + mv .s1 A2,A4 diff --git a/arch/c6x/lib/pop_rts.S b/arch/c6x/lib/pop_rts.S new file mode 100644 index 0000000..e1847fb --- /dev/null +++ b/arch/c6x/lib/pop_rts.S @@ -0,0 +1,30 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + .text + .global __c6xabi_pop_rts + +__c6xabi_pop_rts: + lddw .d2t2 *++B15, B3:B2 + lddw .d2t1 *++B15, A11:A10 + lddw .d2t2 *++B15, B11:B10 + lddw .d2t1 *++B15, A13:A12 + lddw .d2t2 *++B15, B13:B12 + lddw .d2t1 *++B15, A15:A14 +|| b .s2 B3 + ldw .d2t2 *++B15[2], B14 + nop 4 diff --git a/arch/c6x/lib/push_rts.S b/arch/c6x/lib/push_rts.S new file mode 100644 index 0000000..637d56a --- /dev/null +++ b/arch/c6x/lib/push_rts.S @@ -0,0 +1,28 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + .text + .global __c6xabi_push_rts +__c6xabi_push_rts: + stw .d2t2 B14, *B15--[2] + stdw .d2t1 A15:A14, *B15-- +|| b .s2x A3 + stdw .d2t2 B13:B12, *B15-- + stdw .d2t1 A13:A12, *B15-- + stdw .d2t2 B11:B10, *B15-- + stdw .d2t1 A11:A10, *B15-- + stdw .d2t2 B3:B2, *B15-- diff --git a/arch/c6x/lib/remi.S b/arch/c6x/lib/remi.S new file mode 100644 index 0000000..2760d77 --- /dev/null +++ b/arch/c6x/lib/remi.S @@ -0,0 +1,78 @@ +;; Copyright 2010, 2011 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ;; ABI considerations for the divide functions + ;; The following registers are call-used: + ;; __c6xabi_divi A0,A1,A2,A4,A6,B0,B1,B2,B4,B5 + ;; __c6xabi_divu A0,A1,A2,A4,A6,B0,B1,B2,B4 + ;; __c6xabi_remi A1,A2,A4,A5,A6,B0,B1,B2,B4 + ;; __c6xabi_remu A1,A4,A5,A7,B0,B1,B2,B4 + ;; + ;; In our implementation, divu and remu are leaf functions, + ;; while both divi and remi call into divu. + ;; A0 is not clobbered by any of the functions. + ;; divu does not clobber B2 either, which is taken advantage of + ;; in remi. + ;; divi uses B5 to hold the original return address during + ;; the call to divu. + ;; remi uses B2 and A5 to hold the input values during the + ;; call to divu. It stores B3 in on the stack. + +#ifdef CONFIG_TI_C6X_COMPILER + .ref __c6xabi_divu +#endif + .text + .global __c6xabi_remi + +__c6xabi_remi: + stw .d2t2 B3, *B15--[2] +|| cmpgt .l1 0, A4, A1 +|| cmpgt .l2 0, B4, B2 +|| mv .s1 A4, A5 +|| call .s2 __c6xabi_divu + + [A1] neg .l1 A4, A4 +|| [B2] neg .l2 B4, B4 +|| xor .s2x B2, A1, B0 +|| mv .d2 B4, B2 + + [B0] addkpc .s2 _divu_ret_1, B3, 1 + [!B0] addkpc .s2 _divu_ret_2, B3, 1 + nop 2 +_divu_ret_1: + neg .l1 A4, A4 +_divu_ret_2: + ldw .d2t2 *++B15[2], B3 + +#if defined(CONFIG_TMS320C64XPLUS) || defined(CONFIG_TMS320C66X) + mpy32 .m1x A4, B2, A6 + nop 3 + ret .s2 B3 + sub .l1 A5, A6, A4 + nop 4 +#else + mpyu .m1x A4, B2, A1 + nop 1 + mpylhu .m1x A4, B2, A6 +|| mpylhu .m2x B2, A4, B2 +|| ret .s2 B3 + nop 1 + add .l1x A6, B2, A6 + shl .s1 A6, 16, A6 + add .d1 A6, A1, A6 + sub .l1 A5, A6, A4 +#endif diff --git a/arch/c6x/lib/remu.S b/arch/c6x/lib/remu.S new file mode 100644 index 0000000..e1d9f30 --- /dev/null +++ b/arch/c6x/lib/remu.S @@ -0,0 +1,81 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ;; ABI considerations for the divide functions + ;; The following registers are call-used: + ;; __c6xabi_divi A0,A1,A2,A4,A6,B0,B1,B2,B4,B5 + ;; __c6xabi_divu A0,A1,A2,A4,A6,B0,B1,B2,B4 + ;; __c6xabi_remi A1,A2,A4,A5,A6,B0,B1,B2,B4 + ;; __c6xabi_remu A1,A4,A5,A7,B0,B1,B2,B4 + ;; + ;; In our implementation, divu and remu are leaf functions, + ;; while both divi and remi call into divu. + ;; A0 is not clobbered by any of the functions. + ;; divu does not clobber B2 either, which is taken advantage of + ;; in remi. + ;; divi uses B5 to hold the original return address during + ;; the call to divu. + ;; remi uses B2 and A5 to hold the input values during the + ;; call to divu. It stores B3 in on the stack. + + + .text + .global __c6xabi_remu + +__c6xabi_remu: + ;; The ABI seems designed to prevent these functions calling each other, + ;; so we duplicate most of the divsi3 code here. + mv .s2x A4, B1 + lmbd .l2 1, B4, B1 +|| [!B1] b .s2 B3 ; RETURN A +|| [!B1] mvk .d2 1, B4 + + mv .l1x B1, A7 +|| shl .s2 B4, B1, B4 + + cmpltu .l1x A4, B4, A1 + [!A1] sub .l1x A4, B4, A4 + shru .s2 B4, 1, B4 + +_remu_loop: + cmpgt .l2 B1, 7, B0 +|| [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + ;; RETURN A may happen here (note: must happen before the next branch) + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 +|| [B0] b .s1 _remu_loop + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + ;; loop backwards branch happens here + + ret .s2 B3 + [B1] subc .l1x A4,B4,A4 +|| [B1] add .s2 -1, B1, B1 + [B1] subc .l1x A4,B4,A4 + + extu .s1 A4, A7, A4 + nop 2 + diff --git a/arch/c6x/lib/strasgi.S b/arch/c6x/lib/strasgi.S new file mode 100644 index 0000000..6861e25 --- /dev/null +++ b/arch/c6x/lib/strasgi.S @@ -0,0 +1,88 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + .text + .global __c6xabi_strasgi + +__c6xabi_strasgi: + + ;; This is essentially memcpy, with alignment known to be at least + ;; 4, and the size a multiple of 4 greater than or equal to 28. + ldw .d2t1 *B4++, A0 +|| mvk .s2 16, B1 + ldw .d2t1 *B4++, A1 +|| mvk .s2 20, B2 +|| sub .d1 A6, 24, A6 + ldw .d2t1 *B4++, A5 + ldw .d2t1 *B4++, A7 +|| mv .l2x A6, B7 + ldw .d2t1 *B4++, A8 + ldw .d2t1 *B4++, A9 +|| mv .s2x A0, B5 +|| cmpltu .l2 B2, B7, B0 + +_strasgi_loop: + stw .d1t2 B5, *A4++ +|| [B0] ldw .d2t1 *B4++, A0 +|| mv .s2x A1, B5 +|| mv .l2 B7, B6 + + [B0] sub .d2 B6, 24, B7 +|| [B0] b .s2 _strasgi_loop +|| cmpltu .l2 B1, B6, B0 + + [B0] ldw .d2t1 *B4++, A1 +|| stw .d1t2 B5, *A4++ +|| mv .s2x A5, B5 +|| cmpltu .l2 12, B6, B0 + + [B0] ldw .d2t1 *B4++, A5 +|| stw .d1t2 B5, *A4++ +|| mv .s2x A7, B5 +|| cmpltu .l2 8, B6, B0 + + [B0] ldw .d2t1 *B4++, A7 +|| stw .d1t2 B5, *A4++ +|| mv .s2x A8, B5 +|| cmpltu .l2 4, B6, B0 + + [B0] ldw .d2t1 *B4++, A8 +|| stw .d1t2 B5, *A4++ +|| mv .s2x A9, B5 +|| cmpltu .l2 0, B6, B0 + + [B0] ldw .d2t1 *B4++, A9 +|| stw .d1t2 B5, *A4++ +|| mv .s2x A0, B5 +|| cmpltu .l2 B2, B7, B0 + + ;; loop back branch happens here + + cmpltu .l2 B1, B6, B0 +|| ret .s2 b3 + + [B0] stw .d1t1 A1, *A4++ +|| cmpltu .l2 12, B6, B0 + [B0] stw .d1t1 A5, *A4++ +|| cmpltu .l2 8, B6, B0 + [B0] stw .d1t1 A7, *A4++ +|| cmpltu .l2 4, B6, B0 + [B0] stw .d1t1 A8, *A4++ +|| cmpltu .l2 0, B6, B0 + [B0] stw .d1t1 A9, *A4++ + + ;; return happens here diff --git a/arch/c6x/lib/strasgi_64plus.S b/arch/c6x/lib/strasgi_64plus.S new file mode 100644 index 0000000..cbeab22 --- /dev/null +++ b/arch/c6x/lib/strasgi_64plus.S @@ -0,0 +1,37 @@ +;; Copyright 2010 Free Software Foundation, Inc. +;; Contributed by Bernd Schmidt bernds@codesourcery.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. +;; +;; This program 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 this program; if not, write to the Free Software +;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + .text + .global __c6xabi_strasgi_64plus + +__c6xabi_strasgi_64plus: + shru .s2x a6, 2, b31 +|| mv .s1 a4, a30 +|| mv .d2 b4, b30 + + add .s2 -4, b31, b31 + + sploopd 1 +|| mvc .s2 b31, ilc + ldw .d2t2 *b30++, b31 + nop 4 + mv .s1x b31,a31 + spkernel 6, 0 +|| stw .d1t1 a31, *a30++ + + ret .s2 b3 + nop 5 diff --git a/arch/c6x/lib/unaligned.S b/arch/c6x/lib/unaligned.S new file mode 100644 index 0000000..a825b4d --- /dev/null +++ b/arch/c6x/lib/unaligned.S @@ -0,0 +1,117 @@ +; +; arch/c6x/kernel/unaligned.S +; +; Port on Texas Instruments TMS320C6x architecture +; +; Copyright (C) 2010 Texas Instruments Incorporated +; Author: Mark Salter (msalter@redhat.com) +; +; 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. +; + + .text + .global get_unaligned_le64 + .global get_unaligned_be64 + .global get_unaligned_le32 + .global get_unaligned_be32 + .global put_unaligned_le64 + .global put_unaligned_be64 + .global put_unaligned_le32 + .global put_unaligned_be32 + +; u64 get_unaligned_le64(void *ptr); +; u64 get_unaligned_be64(void *ptr); +; +#ifdef CONFIG_CPU_BIG_ENDIAN +get_unaligned_le64: +#else +get_unaligned_be64: +#endif + LDNDW .D1T1 *A4,A5:A4 + NOP 2 + BNOP .S2 B3,1 + MV .D2X A4,B0 + SWAP2 .S2 B0,B1 + || SWAP2 .S1 A5,A0 + SWAP4 .L2 B1,B0 + || SWAP4 .L1 A0,A4 + MV .D1X B0,A5 + +#ifdef CONFIG_CPU_BIG_ENDIAN +get_unaligned_be64: +#else +get_unaligned_le64: +#endif + BNOP .S2 B3,5 + || LDNDW .D1T1 *A4,A5:A4 + +; u32 get_unaligned_le32(void *ptr, int size); +; u32 get_unaligned_be32(void *ptr, int size); +; +#ifdef CONFIG_CPU_BIG_ENDIAN +get_unaligned_le32: +#else +get_unaligned_be32: +#endif + LDNW .D1T1 *A4,A4 + BNOP .S2 B3,3 + SWAP2 .S1 A4,A0 + SWAP4 .L1 A0,A4 + +#ifdef CONFIG_CPU_BIG_ENDIAN +get_unaligned_be32: +#else +get_unaligned_le32: +#endif + BNOP .S2 B3,5 + || LDNW .D1T1 *A4,A4 + + +; void put_unaligned_le64(u64 val, void *ptr); +; void put_unaligned_be64(u64 val, void *ptr); +; +#ifdef CONFIG_CPU_BIG_ENDIAN +put_unaligned_le64: +#else +put_unaligned_be64: +#endif + B .S2 B3 + MV .D2X A4,B0 + SWAP2 .S2 B0,B1 + || SWAP2 .S1 A5,A0 + SWAP4 .L2 B1,B0 + || SWAP4 .L1 A0,A4 + MV .D1X B0,A5 + STNDW .D2T1 A5:A4,*B4 + +#ifdef CONFIG_CPU_BIG_ENDIAN +put_unaligned_be64: +#else +put_unaligned_le64: +#endif + BNOP .S2 B3,5 + || STNDW .D2T1 A5:A4,*B4 + +; void put_unaligned_le32(u32 val, void *ptr); +; void put_unaligned_be32(u32 val, void *ptr); +; +#ifdef CONFIG_CPU_BIG_ENDIAN +put_unaligned_le32: +#else +put_unaligned_be32: +#endif + BNOP .S2 B3,2 + SWAP2 .S1 A4,A5 + SWAP4 .L1 A5,A4 + STNW .D2T1 A4,*B4 + +#ifdef CONFIG_CPU_BIG_ENDIAN +put_unaligned_be32: +#else +put_unaligned_le32: +#endif + BNOP .S2 B3,5 + || STNW .D2T1 A4,*B4 + diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 42f08fd..faf534b 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -513,6 +513,11 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0; } +#elif defined(CONFIG_C6X) +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return 0; +}
#else #error "a case for this architecture does not exist!" diff --git a/common/image.c b/common/image.c index 91954ac..0fff687 100644 --- a/common/image.c +++ b/common/image.c @@ -456,8 +456,12 @@ phys_size_t getenv_bootm_size(void) #if defined(CONFIG_ARM) return gd->bd->bi_dram[0].size - tmp; #else +#if defined(CONFIG_C6X) + return gd->bd->bi_dram[0].size - tmp; +#else return gd->bd->bi_memsize - tmp; #endif +#endif }
phys_size_t getenv_bootm_mapsize(void) diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index 15e9afc..c9e0819 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -195,6 +195,21 @@ gd_t *global_data; " l.jr r13\n" \ " l.nop\n" \ : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r13"); + +#elif defined(CONFIG_C6X) +/* + * b31 holds the pointer to the global_data, a0 is a call-clobbered + * register + */ +#define EXPORT_FUNC(x) \ + asm volatile ( \ +" .globl " #x "\n" \ +#x ":\n" \ +" B .S2X A0\n" \ +" NOP 3\n" \ + : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "A0"); + + #else /*" addi $sp, $sp, -24\n" \ " br $r16\n" */