From f958a91fa5cefd0cda76c887ee0488fb9158496e Mon Sep 17 00:00:00 2001 From: Igor Guryanov Date: Tue, 3 Feb 2015 13:58:09 +0300 Subject: arc: memcmp - fix zero-delay loop utilization It's prohibited to put branch instruction in the very end of zero-delay loop. On execution this causes "Illegal instruction" exception. Signed-off-by: Alexey Brodkin Signed-off-by: Igor Guryanov --- arch/arc/lib/memcmp.S | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arc') diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S index fa5aac5f67..87bccab51d 100644 --- a/arch/arc/lib/memcmp.S +++ b/arch/arc/lib/memcmp.S @@ -29,6 +29,7 @@ memcmp: ld.a %r4, [%r0, 8] ld.a %r5, [%r1, 8] brne WORD2, %r12, .Lodd + nop .Loop_end: asl_s SHIFT, SHIFT, 3 bhs_s .Last_cmp @@ -105,6 +106,7 @@ memcmp: ldb.a %r4, [%r0, 2] ldb.a %r5, [%r1, 2] brne %r3, %r12, .Lbyte_odd + nop .Lbyte_end: bcc .Lbyte_even brne %r4, %r5, .Lbyte_even -- cgit From 812980bdd6c9112014f3946d1cb2728a2121ba34 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:11 +0300 Subject: arc: add more flavours of ARC700 series CPU Now we may select a particular version of ARC700: * ARC750D or * ARC770D It allows more flexible (or more fine tuned) configuration of U-Boot. Before that change we relied on minimal configuration but now we may use specific features of each CPU. Moreover allows us to escape manual selection of options that exist in both CPUs but may have say different version like MMUv2 in ARC750D vs MMUv3 in ARC770D. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 40 ++++++++++++++++++++++++++++++++++++++++ arch/arc/config.mk | 4 ++++ arch/arc/include/asm/arcregs.h | 2 ++ arch/arc/include/asm/cache.h | 6 ++++++ 4 files changed, 52 insertions(+) (limited to 'arch/arc') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index c6b1efeb8b..f7d2964144 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -7,6 +7,46 @@ config SYS_ARCH config SYS_CPU default "arcv1" +choice + prompt "CPU selection" + default CPU_ARC770D + +config CPU_ARC750D + bool "ARC 750D" + select ARC_MMU_V2 + help + Choose this option to build an U-Boot for ARC750D CPU. + +config CPU_ARC770D + bool "ARC 770D" + select ARC_MMU_V3 + help + Choose this option to build an U-Boot for ARC770D CPU. + +endchoice + +choice + prompt "MMU Version" + default ARC_MMU_V3 if CPU_ARC770D + default ARC_MMU_V2 if CPU_ARC750D + +config ARC_MMU_V2 + bool "MMU v2" + depends on CPU_ARC750D + help + Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio + when 2 D-TLB and 1 I-TLB entries index into same 2way set. + +config ARC_MMU_V3 + bool "MMU v3" + depends on CPU_ARC770D + help + Introduced with ARC700 4.10: New Features + Variable Page size (1k-16k), var JTLB size 128 x (2 or 4) + Shared Address Spaces (SASID) + +endchoice + choice prompt "Target select" diff --git a/arch/arc/config.mk b/arch/arc/config.mk index 5321987a56..dd180ef187 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -25,6 +25,10 @@ ifdef CONFIG_ARC_MMU_VER CONFIG_MMU = 1 endif +ifdef CONFIG_CPU_ARC770D +PLATFORM_CPPFLAGS += -mlock -mswape +endif + PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 # Needed for relocation diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 8ace87fa0f..31627e65b9 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -7,6 +7,8 @@ #ifndef _ASM_ARC_ARCREGS_H #define _ASM_ARC_ARCREGS_H +#include + /* * ARC architecture has additional address space - auxiliary registers. * These registers are mostly used for configuration purposes. diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 16e7568ef0..368d1f016e 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -20,4 +20,10 @@ #define ARCH_DMA_MINALIGN 128 #endif +#if defined(CONFIG_ARC_MMU_V2) +#define CONFIG_ARC_MMU_VER 2 +#elif defined(CONFIG_ARC_MMU_V3) +#define CONFIG_ARC_MMU_VER 3 +#endif + #endif /* __ASM_ARC_CACHE_H */ -- cgit From 5ff40f3d4226d45c78f3bb9db276f6685b24a89a Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:12 +0300 Subject: arc: define and use PTAG AUX regs for MMUv3 only DC_PTAG and IC_PTAG registers only exist in MMUv3. Signed-off-by: Alexey Brodkin --- arch/arc/include/asm/arcregs.h | 4 ++-- arch/arc/lib/cache.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arc') diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 31627e65b9..6a36a81c0f 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -23,7 +23,7 @@ #define ARC_AUX_IC_IVIC 0x10 #define ARC_AUX_IC_CTRL 0x11 #define ARC_AUX_IC_IVIL 0x19 -#if (CONFIG_ARC_MMU_VER > 2) +#if (CONFIG_ARC_MMU_VER == 3) #define ARC_AUX_IC_PTAG 0x1E #endif #define ARC_BCR_IC_BUILD 0x77 @@ -42,7 +42,7 @@ #define ARC_AUX_DC_IVDL 0x4A #define ARC_AUX_DC_FLSH 0x4B #define ARC_AUX_DC_FLDL 0x4C -#if (CONFIG_ARC_MMU_VER > 2) +#if (CONFIG_ARC_MMU_VER == 3) #define ARC_AUX_DC_PTAG 0x5C #endif #define ARC_BCR_DC_BUILD 0x72 diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index fa19a13b7e..fa2a1e77a2 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -101,7 +101,7 @@ void flush_dcache_all(void) #ifndef CONFIG_SYS_DCACHE_OFF static void dcache_flush_line(unsigned addr) { -#if (CONFIG_ARC_MMU_VER > 2) +#if (CONFIG_ARC_MMU_VER == 3) write_aux_reg(ARC_AUX_DC_PTAG, addr); #endif write_aux_reg(ARC_AUX_DC_FLDL, addr); @@ -115,7 +115,7 @@ static void dcache_flush_line(unsigned addr) * Invalidate I$ for addresses range just flushed from D$. * If we try to execute data flushed above it will be valid/correct */ -#if (CONFIG_ARC_MMU_VER > 2) +#if (CONFIG_ARC_MMU_VER == 3) write_aux_reg(ARC_AUX_IC_PTAG, addr); #endif write_aux_reg(ARC_AUX_IC_IVIL, addr); @@ -145,7 +145,7 @@ void invalidate_dcache_range(unsigned long start, unsigned long end) end = end & (~(CONFIG_SYS_CACHELINE_SIZE - 1)); for (addr = start; addr <= end; addr += CONFIG_SYS_CACHELINE_SIZE) { -#if (CONFIG_ARC_MMU_VER > 2) +#if (CONFIG_ARC_MMU_VER == 3) write_aux_reg(ARC_AUX_DC_PTAG, addr); #endif write_aux_reg(ARC_AUX_DC_IVDL, addr); -- cgit From 205e7a7b77726abeff57576e2ecf2c6d4dc07ccf Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:13 +0300 Subject: arc: select cache settings via menuconfig This change allows to keep board description clean and minimalistic. This is especially helpful if one board may house different CPUs with different features. It is applicable to both FPGA-based boards or those that have CPUs mounted on interchnagable daughter-boards. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 19 +++++++++++++++++++ arch/arc/include/asm/cache.h | 13 +++++-------- arch/arc/lib/cache.c | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) (limited to 'arch/arc') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index f7d2964144..397b179198 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -47,6 +47,25 @@ config ARC_MMU_V3 endchoice +config SYS_ICACHE_OFF + bool "Do not use Instruction Cache" + default n + +config SYS_DCACHE_OFF + bool "Do not use Data Cache" + default n + +config ARC_CACHE_LINE_SHIFT + int "Cache Line Length (as power of 2)" + range 5 7 + default "6" + depends on !SYS_DCACHE_OFF || !SYS_DCACHE_OFF + help + Starting with ARC700 4.9, Cache line length is configurable, + This option specifies "N", with Line-len = 2 power N + So line lengths of 32, 64, 128 are specified by 5,6,7, respectively + Linux only supports same line lengths for I and D caches. + choice prompt "Target select" diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 368d1f016e..2725961221 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -9,15 +9,12 @@ #include -/* - * The current upper bound for ARC L1 data cache line sizes is 128 bytes. - * We use that value for aligning DMA buffers unless the board config has - * specified an alternate cache line size. - */ -#ifdef CONFIG_SYS_CACHELINE_SIZE -#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE +#ifdef CONFIG_ARC_CACHE_LINE_SHIFT +#define CONFIG_SYS_CACHELINE_SIZE (1 << CONFIG_ARC_CACHE_LINE_SHIFT) +#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE #else -#define ARCH_DMA_MINALIGN 128 +/* Satisfy users of ARCH_DMA_MINALIGN */ +#define ARCH_DMA_MINALIGN 128 #endif #if defined(CONFIG_ARC_MMU_V2) diff --git a/arch/arc/lib/cache.c b/arch/arc/lib/cache.c index fa2a1e77a2..a2277231ba 100644 --- a/arch/arc/lib/cache.c +++ b/arch/arc/lib/cache.c @@ -6,6 +6,7 @@ #include #include +#include /* Bit values in IC_CTRL */ #define IC_CTRL_CACHE_DISABLE (1 << 0) -- cgit From 1f9ad44546ea872fc6671602eb411377dd424c9e Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:14 +0300 Subject: arc: add selection of endianess in Kconfig This change allows to keep board description clean and minimalistic. This is especially helpful if one board may house different CPUs with different features. It is applicable to both FPGA-based boards or those that have CPUs mounted on interchnagable daughter-boards. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 9 ++++++--- arch/arc/config.mk | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'arch/arc') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 397b179198..04fc7b6ab2 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -47,6 +47,12 @@ config ARC_MMU_V3 endchoice +config CPU_BIG_ENDIAN + bool "Enable Big Endian Mode" + default n + help + Build kernel for Big Endian Mode of ARC CPU + config SYS_ICACHE_OFF bool "Do not use Instruction Cache" default n @@ -75,9 +81,6 @@ config TARGET_TB100 config TARGET_ARCANGEL4 bool "Support arcangel4" -config TARGET_ARCANGEL4_BE - bool "Support arcangel4-be" - config TARGET_AXS101 bool "Support axs101" diff --git a/arch/arc/config.mk b/arch/arc/config.mk index dd180ef187..4f2d31feb3 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -4,8 +4,10 @@ # SPDX-License-Identifier: GPL-2.0+ # -ifndef CONFIG_SYS_BIG_ENDIAN +ifndef CONFIG_CPU_BIG_ENDIAN CONFIG_SYS_LITTLE_ENDIAN = 1 +else +CONFIG_SYS_BIG_ENDIAN = 1 endif ifdef CONFIG_SYS_LITTLE_ENDIAN -- cgit From 6eb651ad29636682067f76de4f40c45119269f8b Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:15 +0300 Subject: arc: hard-code CONFIG_SYS_GENERIC_BOARD into asm/config.h There're no other options for ARC except "generic board" so ther's no point to define CONFIG_SYS_GENERIC_BOARD per board. We now have it set fo all ARC boards. Signed-off-by: Alexey Brodkin --- arch/arc/include/asm/config.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arc') diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h index e5be078c19..c1e9b44239 100644 --- a/arch/arc/include/asm/config.h +++ b/arch/arc/include/asm/config.h @@ -7,6 +7,7 @@ #ifndef __ASM_ARC_CONFIG_H_ #define __ASM_ARC_CONFIG_H_ +#define CONFIG_SYS_GENERIC_BOARD #define CONFIG_SYS_GENERIC_GLOBAL_DATA #define CONFIG_SYS_BOOT_RAMDISK_HIGH -- cgit From a1dbe57d2d45d311e402c357831bbf5c5157a32c Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:17 +0300 Subject: arc: hard-code CONFIG_ARCH_EARLY_INIT_R in asm/config.h Common arch_early_init_r() is used in "arc/lib/cpu.c" for all ARC boards so there's no sense in separate per-board definitions. Signed-off-by: Alexey Brodkin --- arch/arc/include/asm/config.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arc') diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h index c1e9b44239..b4e9099fb1 100644 --- a/arch/arc/include/asm/config.h +++ b/arch/arc/include/asm/config.h @@ -10,6 +10,7 @@ #define CONFIG_SYS_GENERIC_BOARD #define CONFIG_SYS_GENERIC_GLOBAL_DATA #define CONFIG_SYS_BOOT_RAMDISK_HIGH +#define CONFIG_ARCH_EARLY_INIT_R #define CONFIG_LMB -- cgit From 51f4999bc5ad5f8430da0297d12c1abef9c05568 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:19 +0300 Subject: arc: move CPU flags selection to the main "config.mk" As a preparation to ARCv2 port submission we're moving CPU slection flags to a common location. Also it will allow us to have more flexible CPU specification, not only ISA version but CPU family as well checking CONFIG_ARC_CPU_xxx. Signed-off-by: Alexey Brodkin --- arch/arc/config.mk | 6 +++++- arch/arc/cpu/arcv1/config.mk | 7 ------- 2 files changed, 5 insertions(+), 8 deletions(-) delete mode 100644 arch/arc/cpu/arcv1/config.mk (limited to 'arch/arc') diff --git a/arch/arc/config.mk b/arch/arc/config.mk index 4f2d31feb3..3e75e606b3 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -27,8 +27,12 @@ ifdef CONFIG_ARC_MMU_VER CONFIG_MMU = 1 endif +ifdef CONFIG_CPU_ARC750D +PLATFORM_CPPFLAGS += -marc700 +endif + ifdef CONFIG_CPU_ARC770D -PLATFORM_CPPFLAGS += -mlock -mswape +PLATFORM_CPPFLAGS += -marc700 -mlock -mswape endif PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2 diff --git a/arch/arc/cpu/arcv1/config.mk b/arch/arc/cpu/arcv1/config.mk deleted file mode 100644 index 3206ff47e3..0000000000 --- a/arch/arc/cpu/arcv1/config.mk +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -PLATFORM_CPPFLAGS += -mA7 -- cgit From a67ef280f46803e319639f5380ff8da6c6b7fbe7 Mon Sep 17 00:00:00 2001 From: Alexey Brodkin Date: Tue, 3 Feb 2015 13:58:20 +0300 Subject: arc: build libgcc in U-Boot This way we may have very limited set of functions implemented so we save some space. Also it allows us to build U-Boot for any ARC core with the same one toolchain because we don't rely on pre-built libgcc. For example: * we may use little-endian toolchain but build U-Boot for ether endianess * we may use non-multilibbed uClibc toolchain but build U-Boot for whatever ARC CPU flavour that current GCC supports Private libgcc built from generic C implementation contributes only 144 bytes to .text section so we don't see significant degradation of size: --->8--- $ arc-linux-size u-boot.libgcc-prebuilt text data bss dec hex filename 222217 24912 214820 461949 70c7d u-boot.libgcc-prebuilt $ arc-linux-size u-boot.libgcc-private text data bss dec hex filename 222361 24912 214820 462093 70d0d u-boot.libgcc-private --->8--- Also I don't notice visible performance degradation compared to pre-built libgcc (where at least "*div*" functions are had-written in assembly) on typical operations of downloading 10Mb uImage over TFTP and bootm. Signed-off-by: Alexey Brodkin --- arch/arc/Kconfig | 3 + arch/arc/config.mk | 3 + arch/arc/lib/Makefile | 2 + arch/arc/lib/_millicodethunk.S | 226 +++++++++++++++++++++++++++++++++++++++++ arch/arc/lib/libgcc2.c | 161 +++++++++++++++++++++++++++++ arch/arc/lib/libgcc2.h | 132 ++++++++++++++++++++++++ 6 files changed, 527 insertions(+) create mode 100644 arch/arc/lib/_millicodethunk.S create mode 100644 arch/arc/lib/libgcc2.c create mode 100644 arch/arc/lib/libgcc2.h (limited to 'arch/arc') diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 04fc7b6ab2..a8dc4e2336 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -4,6 +4,9 @@ menu "ARC architecture" config SYS_ARCH default "arc" +config USE_PRIVATE_LIBGCC + default y + config SYS_CPU default "arcv1" diff --git a/arch/arc/config.mk b/arch/arc/config.mk index 3e75e606b3..f1e81b6895 100644 --- a/arch/arc/config.mk +++ b/arch/arc/config.mk @@ -12,11 +12,14 @@ endif ifdef CONFIG_SYS_LITTLE_ENDIAN ARC_CROSS_COMPILE := arc-buildroot-linux-uclibc- +PLATFORM_LDFLAGS += -EL +PLATFORM_CPPFLAGS += -mlittle-endian endif ifdef CONFIG_SYS_BIG_ENDIAN ARC_CROSS_COMPILE := arceb-buildroot-linux-uclibc- PLATFORM_LDFLAGS += -EB +PLATFORM_CPPFLAGS += -mbig-endian endif ifeq ($(CROSS_COMPILE),) diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile index bae44199a4..b8028c91e1 100644 --- a/arch/arc/lib/Makefile +++ b/arch/arc/lib/Makefile @@ -20,3 +20,5 @@ obj-y += reset.o obj-y += timer.o obj-$(CONFIG_CMD_BOOTM) += bootm.o + +lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o diff --git a/arch/arc/lib/_millicodethunk.S b/arch/arc/lib/_millicodethunk.S new file mode 100644 index 0000000000..b3324167d4 --- /dev/null +++ b/arch/arc/lib/_millicodethunk.S @@ -0,0 +1,226 @@ +/* + * Copyright (C) 1995, 1997, 2007-2013 Free Software Foundation, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + /* ANSI concatenation macros. */ + + #define CONCAT1(a, b) CONCAT2(a, b) + #define CONCAT2(a, b) a ## b + + /* Use the right prefix for global labels. */ + + #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +#ifndef WORKING_ASSEMBLER +#define abs_l abs +#define asl_l asl +#define mov_l mov +#endif + +#define FUNC(X) .type SYM(X),@function +#define HIDDEN_FUNC(X) FUNC(X)` .hidden X +#define ENDFUNC0(X) .Lfe_##X: .size X,.Lfe_##X-X +#define ENDFUNC(X) ENDFUNC0(X) + + .section .text + .align 4 + .global SYM(__st_r13_to_r15) + .global SYM(__st_r13_to_r16) + .global SYM(__st_r13_to_r17) + .global SYM(__st_r13_to_r18) + .global SYM(__st_r13_to_r19) + .global SYM(__st_r13_to_r20) + .global SYM(__st_r13_to_r21) + .global SYM(__st_r13_to_r22) + .global SYM(__st_r13_to_r23) + .global SYM(__st_r13_to_r24) + .global SYM(__st_r13_to_r25) + HIDDEN_FUNC(__st_r13_to_r15) + HIDDEN_FUNC(__st_r13_to_r16) + HIDDEN_FUNC(__st_r13_to_r17) + HIDDEN_FUNC(__st_r13_to_r18) + HIDDEN_FUNC(__st_r13_to_r19) + HIDDEN_FUNC(__st_r13_to_r20) + HIDDEN_FUNC(__st_r13_to_r21) + HIDDEN_FUNC(__st_r13_to_r22) + HIDDEN_FUNC(__st_r13_to_r23) + HIDDEN_FUNC(__st_r13_to_r24) + HIDDEN_FUNC(__st_r13_to_r25) + .align 4 +SYM(__st_r13_to_r25): + st r25, [sp,48] +SYM(__st_r13_to_r24): + st r24, [sp,44] +SYM(__st_r13_to_r23): + st r23, [sp,40] +SYM(__st_r13_to_r22): + st r22, [sp,36] +SYM(__st_r13_to_r21): + st r21, [sp,32] +SYM(__st_r13_to_r20): + st r20, [sp,28] +SYM(__st_r13_to_r19): + st r19, [sp,24] +SYM(__st_r13_to_r18): + st r18, [sp,20] +SYM(__st_r13_to_r17): + st r17, [sp,16] +SYM(__st_r13_to_r16): + st r16, [sp,12] +SYM(__st_r13_to_r15): +#ifdef __ARC700__ + st r15, [sp,8] ; minimum function size to avoid stall: 6 bytes. +#else + st_s r15, [sp,8] +#endif + st_s r14, [sp,4] + j_s.d [%blink] + st_s r13, [sp,0] + ENDFUNC(__st_r13_to_r15) + ENDFUNC(__st_r13_to_r16) + ENDFUNC(__st_r13_to_r17) + ENDFUNC(__st_r13_to_r18) + ENDFUNC(__st_r13_to_r19) + ENDFUNC(__st_r13_to_r20) + ENDFUNC(__st_r13_to_r21) + ENDFUNC(__st_r13_to_r22) + ENDFUNC(__st_r13_to_r23) + ENDFUNC(__st_r13_to_r24) + ENDFUNC(__st_r13_to_r25) + + .section .text + .align 4 +; ================================== +; the loads + + .global SYM(__ld_r13_to_r15) + .global SYM(__ld_r13_to_r16) + .global SYM(__ld_r13_to_r17) + .global SYM(__ld_r13_to_r18) + .global SYM(__ld_r13_to_r19) + .global SYM(__ld_r13_to_r20) + .global SYM(__ld_r13_to_r21) + .global SYM(__ld_r13_to_r22) + .global SYM(__ld_r13_to_r23) + .global SYM(__ld_r13_to_r24) + .global SYM(__ld_r13_to_r25) + HIDDEN_FUNC(__ld_r13_to_r15) + HIDDEN_FUNC(__ld_r13_to_r16) + HIDDEN_FUNC(__ld_r13_to_r17) + HIDDEN_FUNC(__ld_r13_to_r18) + HIDDEN_FUNC(__ld_r13_to_r19) + HIDDEN_FUNC(__ld_r13_to_r20) + HIDDEN_FUNC(__ld_r13_to_r21) + HIDDEN_FUNC(__ld_r13_to_r22) + HIDDEN_FUNC(__ld_r13_to_r23) + HIDDEN_FUNC(__ld_r13_to_r24) + HIDDEN_FUNC(__ld_r13_to_r25) +SYM(__ld_r13_to_r25): + ld r25, [sp,48] +SYM(__ld_r13_to_r24): + ld r24, [sp,44] +SYM(__ld_r13_to_r23): + ld r23, [sp,40] +SYM(__ld_r13_to_r22): + ld r22, [sp,36] +SYM(__ld_r13_to_r21): + ld r21, [sp,32] +SYM(__ld_r13_to_r20): + ld r20, [sp,28] +SYM(__ld_r13_to_r19): + ld r19, [sp,24] +SYM(__ld_r13_to_r18): + ld r18, [sp,20] +SYM(__ld_r13_to_r17): + ld r17, [sp,16] +SYM(__ld_r13_to_r16): + ld r16, [sp,12] +SYM(__ld_r13_to_r15): +#ifdef __ARC700__ + ld r15, [sp,8] ; minimum function size to avoid stall: 6 bytes. +#else + ld_s r15, [sp,8] +#endif + ld_s r14, [sp,4] + j_s.d [%blink] + ld_s r13, [sp,0] + ENDFUNC(__ld_r13_to_r15) + ENDFUNC(__ld_r13_to_r16) + ENDFUNC(__ld_r13_to_r17) + ENDFUNC(__ld_r13_to_r18) + ENDFUNC(__ld_r13_to_r19) + ENDFUNC(__ld_r13_to_r20) + ENDFUNC(__ld_r13_to_r21) + ENDFUNC(__ld_r13_to_r22) + ENDFUNC(__ld_r13_to_r23) + ENDFUNC(__ld_r13_to_r24) + ENDFUNC(__ld_r13_to_r25) + + .global SYM(__ld_r13_to_r14_ret) + .global SYM(__ld_r13_to_r15_ret) + .global SYM(__ld_r13_to_r16_ret) + .global SYM(__ld_r13_to_r17_ret) + .global SYM(__ld_r13_to_r18_ret) + .global SYM(__ld_r13_to_r19_ret) + .global SYM(__ld_r13_to_r20_ret) + .global SYM(__ld_r13_to_r21_ret) + .global SYM(__ld_r13_to_r22_ret) + .global SYM(__ld_r13_to_r23_ret) + .global SYM(__ld_r13_to_r24_ret) + .global SYM(__ld_r13_to_r25_ret) + HIDDEN_FUNC(__ld_r13_to_r14_ret) + HIDDEN_FUNC(__ld_r13_to_r15_ret) + HIDDEN_FUNC(__ld_r13_to_r16_ret) + HIDDEN_FUNC(__ld_r13_to_r17_ret) + HIDDEN_FUNC(__ld_r13_to_r18_ret) + HIDDEN_FUNC(__ld_r13_to_r19_ret) + HIDDEN_FUNC(__ld_r13_to_r20_ret) + HIDDEN_FUNC(__ld_r13_to_r21_ret) + HIDDEN_FUNC(__ld_r13_to_r22_ret) + HIDDEN_FUNC(__ld_r13_to_r23_ret) + HIDDEN_FUNC(__ld_r13_to_r24_ret) + HIDDEN_FUNC(__ld_r13_to_r25_ret) + .section .text + .align 4 +SYM(__ld_r13_to_r25_ret): + ld r25, [sp,48] +SYM(__ld_r13_to_r24_ret): + ld r24, [sp,44] +SYM(__ld_r13_to_r23_ret): + ld r23, [sp,40] +SYM(__ld_r13_to_r22_ret): + ld r22, [sp,36] +SYM(__ld_r13_to_r21_ret): + ld r21, [sp,32] +SYM(__ld_r13_to_r20_ret): + ld r20, [sp,28] +SYM(__ld_r13_to_r19_ret): + ld r19, [sp,24] +SYM(__ld_r13_to_r18_ret): + ld r18, [sp,20] +SYM(__ld_r13_to_r17_ret): + ld r17, [sp,16] +SYM(__ld_r13_to_r16_ret): + ld r16, [sp,12] +SYM(__ld_r13_to_r15_ret): + ld r15, [sp,8] +SYM(__ld_r13_to_r14_ret): + ld blink,[sp,r12] + ld_s r14, [sp,4] + ld.ab r13, [sp,r12] + j_s.d [%blink] + add_s sp,sp,4 + ENDFUNC(__ld_r13_to_r14_ret) + ENDFUNC(__ld_r13_to_r15_ret) + ENDFUNC(__ld_r13_to_r16_ret) + ENDFUNC(__ld_r13_to_r17_ret) + ENDFUNC(__ld_r13_to_r18_ret) + ENDFUNC(__ld_r13_to_r19_ret) + ENDFUNC(__ld_r13_to_r20_ret) + ENDFUNC(__ld_r13_to_r21_ret) + ENDFUNC(__ld_r13_to_r22_ret) + ENDFUNC(__ld_r13_to_r23_ret) + ENDFUNC(__ld_r13_to_r24_ret) + ENDFUNC(__ld_r13_to_r25_ret) diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c new file mode 100644 index 0000000000..d5ad327f65 --- /dev/null +++ b/arch/arc/lib/libgcc2.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 1989-2013 Free Software Foundation, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "libgcc2.h" + +DWtype +__ashldi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (UWtype)uu.s.low << -bm; + } else { + const UWtype carries = (UWtype) uu.s.low >> bm; + + w.s.low = (UWtype)uu.s.low << b; + w.s.high = ((UWtype)uu.s.high << b) | carries; + } + + return w.ll; +} + +DWtype +__ashrdi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (W_TYPE_SIZE - 1); + w.s.low = uu.s.high >> -bm; + } else { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((UWtype)uu.s.low >> b) | carries; + } + + return w.ll; +} + +DWtype +__lshrdi3(DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (UWtype)uu.s.high >> -bm; + } else { + const UWtype carries = (UWtype)uu.s.high << bm; + + w.s.high = (UWtype)uu.s.high >> b; + w.s.low = ((UWtype)uu.s.low >> b) | carries; + } + + return w.ll; +} + +unsigned long +udivmodsi4(unsigned long num, unsigned long den, int modwanted) +{ + unsigned long bit = 1; + unsigned long res = 0; + + while (den < num && bit && !(den & (1L<<31))) { + den <<= 1; + bit <<= 1; + } + + while (bit) { + if (num >= den) { + num -= den; + res |= bit; + } + bit >>= 1; + den >>= 1; + } + + if (modwanted) + return num; + + return res; +} + +long +__divsi3(long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) { + a = -a; + neg = !neg; + } + + if (b < 0) { + b = -b; + neg = !neg; + } + + res = udivmodsi4(a, b, 0); + + if (neg) + res = -res; + + return res; +} + +long +__modsi3(long a, long b) +{ + int neg = 0; + long res; + + if (a < 0) { + a = -a; + neg = 1; + } + + if (b < 0) + b = -b; + + res = udivmodsi4(a, b, 1); + + if (neg) + res = -res; + + return res; +} + +long +__udivsi3(long a, long b) +{ + return udivmodsi4(a, b, 0); +} + +long +__umodsi3(long a, long b) +{ + return udivmodsi4(a, b, 1); +} diff --git a/arch/arc/lib/libgcc2.h b/arch/arc/lib/libgcc2.h new file mode 100644 index 0000000000..8813c3bf4c --- /dev/null +++ b/arch/arc/lib/libgcc2.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 1989-2013 Free Software Foundation, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#define UNITS_PER_WORD 4 /* for ARC */ +#define BITS_PER_UNIT 8 /* for ARC */ + +#define W_TYPE_SIZE (4 * BITS_PER_UNIT) + +#define MIN_UNITS_PER_WORD UNITS_PER_WORD + +/* Work out the largest "word" size that we can deal with on this target. */ +#if MIN_UNITS_PER_WORD > 4 +# define LIBGCC2_MAX_UNITS_PER_WORD 8 +#elif (MIN_UNITS_PER_WORD > 2 \ + || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4)) +# define LIBGCC2_MAX_UNITS_PER_WORD 4 +#else +# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD +#endif + +/* Work out what word size we are using for this compilation. + The value can be set on the command line. */ +#ifndef LIBGCC2_UNITS_PER_WORD +#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD +#endif + +typedef int QItype __attribute__ ((mode (QI))); +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int HItype __attribute__ ((mode (HI))); +typedef unsigned int UHItype __attribute__ ((mode (HI))); +#if MIN_UNITS_PER_WORD > 1 +/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1. */ +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +#if __SIZEOF_LONG_LONG__ > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2. */ +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#if MIN_UNITS_PER_WORD > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4. */ +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#endif +#endif +#endif + +#if LIBGCC2_UNITS_PER_WORD == 8 +#define W_TYPE_SIZE (8 * BITS_PER_UNIT) +#define Wtype DItype +#define UWtype UDItype +#define HWtype DItype +#define UHWtype UDItype +#define DWtype TItype +#define UDWtype UTItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## di ## b +#define __NDW(a,b) __gnu_ ## a ## ti ## b +#else +#define __NW(a,b) __ ## a ## di ## b +#define __NDW(a,b) __ ## a ## ti ## b +#endif +#elif LIBGCC2_UNITS_PER_WORD == 4 +#define W_TYPE_SIZE (4 * BITS_PER_UNIT) +#define Wtype SItype +#define UWtype USItype +#define HWtype SItype +#define UHWtype USItype +#define DWtype DItype +#define UDWtype UDItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## si ## b +#define __NDW(a,b) __gnu_ ## a ## di ## b +#else +#define __NW(a,b) __ ## a ## si ## b +#define __NDW(a,b) __ ## a ## di ## b +#endif +#elif LIBGCC2_UNITS_PER_WORD == 2 +#define W_TYPE_SIZE (2 * BITS_PER_UNIT) +#define Wtype HItype +#define UWtype UHItype +#define HWtype HItype +#define UHWtype UHItype +#define DWtype SItype +#define UDWtype USItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## hi ## b +#define __NDW(a,b) __gnu_ ## a ## si ## b +#else +#define __NW(a,b) __ ## a ## hi ## b +#define __NDW(a,b) __ ## a ## si ## b +#endif +#else +#define W_TYPE_SIZE BITS_PER_UNIT +#define Wtype QItype +#define UWtype UQItype +#define HWtype QItype +#define UHWtype UQItype +#define DWtype HItype +#define UDWtype UHItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## qi ## b +#define __NDW(a,b) __gnu_ ## a ## hi ## b +#else +#define __NW(a,b) __ ## a ## qi ## b +#define __NDW(a,b) __ ## a ## hi ## b +#endif +#endif + +typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__))); + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + struct DWstruct {Wtype high, low;}; +#else + struct DWstruct {Wtype low, high;}; +#endif + +/* We need this union to unpack/pack DImode values, since we don't have + any arithmetic yet. Incoming DImode parameters are stored into the + `ll' field, and the unpacked result is read from the struct `s'. */ + +typedef union { + struct DWstruct s; + DWtype ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ -- cgit