summaryrefslogtreecommitdiff
path: root/arch/arc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/Kconfig128
-rw-r--r--arch/arc/config.mk27
-rw-r--r--arch/arc/cpu/arcv1/config.mk7
-rw-r--r--arch/arc/cpu/arcv2/Makefile7
-rw-r--r--arch/arc/cpu/arcv2/start.S254
-rw-r--r--arch/arc/include/asm/arcregs.h6
-rw-r--r--arch/arc/include/asm/cache.h23
-rw-r--r--arch/arc/include/asm/config.h2
-rw-r--r--arch/arc/lib/Makefile2
-rw-r--r--arch/arc/lib/_millicodethunk.S226
-rw-r--r--arch/arc/lib/cache.c7
-rw-r--r--arch/arc/lib/libgcc2.c161
-rw-r--r--arch/arc/lib/libgcc2.h132
-rw-r--r--arch/arc/lib/memcmp.S2
14 files changed, 959 insertions, 25 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index c6b1efe..24f5c02 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -4,8 +4,131 @@ menu "ARC architecture"
config SYS_ARCH
default "arc"
+config USE_PRIVATE_LIBGCC
+ default y
+
config SYS_CPU
- default "arcv1"
+ default "arcv1" if ISA_ARCOMPACT
+ default "arcv2" if ISA_ARCV2
+
+choice
+ prompt "ARC Instruction Set"
+ default ISA_ARCOMPACT
+
+config ISA_ARCOMPACT
+ bool "ARCompact ISA"
+ help
+ The original ARC ISA of ARC600/700 cores
+
+config ISA_ARCV2
+ bool "ARC ISA v2"
+ help
+ ISA for the Next Generation ARC-HS cores
+
+endchoice
+
+choice
+ prompt "CPU selection"
+ default CPU_ARC770D if ISA_ARCOMPACT
+ default CPU_ARCHS38 if ISA_ARCV2
+
+config CPU_ARC750D
+ bool "ARC 750D"
+ select ARC_MMU_V2
+ depends on ISA_ARCOMPACT
+ help
+ Choose this option to build an U-Boot for ARC750D CPU.
+
+config CPU_ARC770D
+ bool "ARC 770D"
+ select ARC_MMU_V3
+ depends on ISA_ARCOMPACT
+ help
+ Choose this option to build an U-Boot for ARC770D CPU.
+
+config CPU_ARCEM6
+ bool "ARC EM6"
+ select ARC_MMU_ABSENT
+ depends on ISA_ARCV2
+ help
+ Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS36
+ bool "ARC HS36"
+ select ARC_MMU_ABSENT
+ depends on ISA_ARCV2
+ help
+ Next Generation ARC Core based on ISA-v2 ISA without MMU.
+
+config CPU_ARCHS38
+ bool "ARC HS38"
+ select ARC_MMU_V4
+ depends on ISA_ARCV2
+ help
+ Next Generation ARC Core based on ISA-v2 ISA with MMU.
+
+endchoice
+
+choice
+ prompt "MMU Version"
+ default ARC_MMU_V3 if CPU_ARC770D
+ default ARC_MMU_V2 if CPU_ARC750D
+ default ARC_MMU_ABSENT if CPU_ARCEM6
+ default ARC_MMU_ABSENT if CPU_ARCHS36
+ default ARC_MMU_V4 if CPU_ARCHS38
+
+config ARC_MMU_ABSENT
+ bool "No MMU"
+ help
+ No MMU
+
+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)
+
+config ARC_MMU_V4
+ bool "MMU v4"
+ depends on CPU_ARCHS38
+ help
+ Introduced as a part of ARC HS38 release.
+
+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
+
+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"
@@ -16,9 +139,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 5321987..4fcd407 100644
--- a/arch/arc/config.mk
+++ b/arch/arc/config.mk
@@ -4,17 +4,22 @@
# 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
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),)
@@ -25,6 +30,26 @@ ifdef CONFIG_ARC_MMU_VER
CONFIG_MMU = 1
endif
+ifdef CONFIG_CPU_ARC750D
+PLATFORM_CPPFLAGS += -marc700
+endif
+
+ifdef CONFIG_CPU_ARC770D
+PLATFORM_CPPFLAGS += -marc700 -mlock -mswape
+endif
+
+ifdef CONFIG_CPU_ARCEM6
+PLATFORM_CPPFLAGS += -marcem
+endif
+
+ifdef CONFIG_CPU_ARCHS34
+PLATFORM_CPPFLAGS += -marchs
+endif
+
+ifdef CONFIG_CPU_ARCHS38
+PLATFORM_CPPFLAGS += -marchs
+endif
+
PLATFORM_CPPFLAGS += -ffixed-r25 -D__ARC__ -gdwarf-2
# Needed for relocation
diff --git a/arch/arc/cpu/arcv1/config.mk b/arch/arc/cpu/arcv1/config.mk
deleted file mode 100644
index 3206ff4..0000000
--- 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
diff --git a/arch/arc/cpu/arcv2/Makefile b/arch/arc/cpu/arcv2/Makefile
new file mode 100644
index 0000000..cc69e5a
--- /dev/null
+++ b/arch/arc/cpu/arcv2/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y += start.o
diff --git a/arch/arc/cpu/arcv2/start.S b/arch/arc/cpu/arcv2/start.S
new file mode 100644
index 0000000..3ce6896
--- /dev/null
+++ b/arch/arc/cpu/arcv2/start.S
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2013-2015 Synopsys, Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm-offsets.h>
+#include <config.h>
+#include <asm/arcregs.h>
+
+/*
+ * Note on the LD/ST addressing modes with address register write-back
+ *
+ * LD.a same as LD.aw
+ *
+ * LD.a reg1, [reg2, x] => Pre Incr
+ * Eff Addr for load = [reg2 + x]
+ *
+ * LD.ab reg1, [reg2, x] => Post Incr
+ * Eff Addr for load = [reg2]
+ */
+
+.macro PUSH reg
+ st.a \reg, [%sp, -4]
+.endm
+
+.macro PUSHAX aux
+ lr %r9, [\aux]
+ PUSH %r9
+.endm
+
+.macro SAVE_R1_TO_R24
+ PUSH %r1
+ PUSH %r2
+ PUSH %r3
+ PUSH %r4
+ PUSH %r5
+ PUSH %r6
+ PUSH %r7
+ PUSH %r8
+ PUSH %r9
+ PUSH %r10
+ PUSH %r11
+ PUSH %r12
+ PUSH %r13
+ PUSH %r14
+ PUSH %r15
+ PUSH %r16
+ PUSH %r17
+ PUSH %r18
+ PUSH %r19
+ PUSH %r20
+ PUSH %r21
+ PUSH %r22
+ PUSH %r23
+ PUSH %r24
+.endm
+
+.macro SAVE_ALL_SYS
+ /* saving %r0 to reg->r0 in advance since weread %ecr into it */
+ st %r0, [%sp, -8]
+ lr %r0, [%ecr] /* all stack addressing is manual so far */
+ st %r0, [%sp]
+ st %sp, [%sp, -4]
+ /* now move %sp to reg->r0 position so we can do "push" automatically */
+ sub %sp, %sp, 8
+
+ SAVE_R1_TO_R24
+ PUSH %r25
+ PUSH %gp
+ PUSH %fp
+ PUSH %blink
+ PUSHAX %eret
+ PUSHAX %erstatus
+ PUSH %lp_count
+ PUSHAX %lp_end
+ PUSHAX %lp_start
+ PUSHAX %erbta
+.endm
+
+.macro SAVE_EXCEPTION_SOURCE
+#ifdef CONFIG_MMU
+ /* If MMU exists exception faulting address is loaded in EFA reg */
+ lr %r0, [%efa]
+#else
+ /* Otherwise in ERET (exception return) reg */
+ lr %r0, [%eret]
+#endif
+.endm
+
+.section .ivt, "a",@progbits
+.align 4
+ /* Critical system events */
+.word _start /* 0 - 0x000 */
+.word memory_error /* 1 - 0x008 */
+.word instruction_error /* 2 - 0x010 */
+
+ /* Exceptions */
+.word EV_MachineCheck /* 0x100, Fatal Machine check (0x20) */
+.word EV_TLBMissI /* 0x108, Intruction TLB miss (0x21) */
+.word EV_TLBMissD /* 0x110, Data TLB miss (0x22) */
+.word EV_TLBProtV /* 0x118, Protection Violation (0x23)
+ or Misaligned Access */
+.word EV_PrivilegeV /* 0x120, Privilege Violation (0x24) */
+.word EV_Trap /* 0x128, Trap exception (0x25) */
+.word EV_Extension /* 0x130, Extn Intruction Excp (0x26) */
+
+ /* Device interrupts */
+.rept 29
+ j interrupt_handler /* 3:31 - 0x018:0xF8 */
+.endr
+
+.text
+.globl _start
+_start:
+ /* Setup interrupt vector base that matches "__text_start" */
+ sr __ivt_start, [ARC_AUX_INTR_VEC_BASE]
+
+ /* Setup stack pointer */
+ mov %sp, CONFIG_SYS_INIT_SP_ADDR
+ mov %fp, %sp
+
+ /* Clear bss */
+ mov %r0, __bss_start
+ mov %r1, __bss_end
+
+clear_bss:
+ st.ab 0, [%r0, 4]
+ brlt %r0, %r1, clear_bss
+
+ /* Zero the one and only argument of "board_init_f" */
+ mov_s %r0, 0
+ j board_init_f
+
+memory_error:
+ SAVE_ALL_SYS
+ SAVE_EXCEPTION_SOURCE
+ mov %r1, %sp
+ j do_memory_error
+
+instruction_error:
+ SAVE_ALL_SYS
+ SAVE_EXCEPTION_SOURCE
+ mov %r1, %sp
+ j do_instruction_error
+
+interrupt_handler:
+ /* Todo - save and restore CPU context when interrupts will be in use */
+ bl do_interrupt_handler
+ rtie
+
+EV_MachineCheck:
+ SAVE_ALL_SYS
+ SAVE_EXCEPTION_SOURCE
+ mov %r1, %sp
+ j do_machine_check_fault
+
+EV_TLBMissI:
+ SAVE_ALL_SYS
+ mov %r0, %sp
+ j do_itlb_miss
+
+EV_TLBMissD:
+ SAVE_ALL_SYS
+ mov %r0, %sp
+ j do_dtlb_miss
+
+EV_TLBProtV:
+ SAVE_ALL_SYS
+ SAVE_EXCEPTION_SOURCE
+ mov %r1, %sp
+ j do_tlb_prot_violation
+
+EV_PrivilegeV:
+ SAVE_ALL_SYS
+ mov %r0, %sp
+ j do_privilege_violation
+
+EV_Trap:
+ SAVE_ALL_SYS
+ mov %r0, %sp
+ j do_trap
+
+EV_Extension:
+ SAVE_ALL_SYS
+ mov %r0, %sp
+ j do_extension
+
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r0 = start_addr_sp
+ * r1 = new__gd
+ * r2 = relocaddr
+ */
+.align 4
+.globl relocate_code
+relocate_code:
+ /*
+ * r0-r12 might be clobbered by C functions
+ * so we use r13-r16 for storage here
+ */
+ mov %r13, %r0 /* save addr_sp */
+ mov %r14, %r1 /* save addr of gd */
+ mov %r15, %r2 /* save addr of destination */
+
+ mov %r16, %r2 /* %r9 - relocation offset */
+ sub %r16, %r16, __image_copy_start
+
+/* Set up the stack */
+stack_setup:
+ mov %sp, %r13
+ mov %fp, %sp
+
+/* Check if monitor is loaded right in place for relocation */
+ mov %r0, __image_copy_start
+ cmp %r0, %r15 /* skip relocation if code loaded */
+ bz do_board_init_r /* in target location already */
+
+/* Copy data (__image_copy_start - __image_copy_end) to new location */
+ mov %r1, %r15
+ mov %r2, __image_copy_end
+ sub %r2, %r2, %r0 /* r3 <- amount of bytes to copy */
+ asr %r2, %r2, 2 /* r3 <- amount of words to copy */
+ mov %lp_count, %r2
+ lp copy_end
+ ld.ab %r2,[%r0,4]
+ st.ab %r2,[%r1,4]
+copy_end:
+
+/* Fix relocations related issues */
+ bl do_elf_reloc_fixups
+#ifndef CONFIG_SYS_ICACHE_OFF
+ bl invalidate_icache_all
+#endif
+#ifndef CONFIG_SYS_DCACHE_OFF
+ bl flush_dcache_all
+#endif
+
+/* Update position of intterupt vector table */
+ lr %r0, [ARC_AUX_INTR_VEC_BASE] /* Read current position */
+ add %r0, %r0, %r16 /* Update address */
+ sr %r0, [ARC_AUX_INTR_VEC_BASE] /* Write new position */
+
+do_board_init_r:
+/* Prepare for exection of "board_init_r" in relocated monitor */
+ mov %r2, board_init_r /* old address of "board_init_r()" */
+ add %r2, %r2, %r16 /* new address of "board_init_r()" */
+ mov %r0, %r14 /* 1-st parameter: gd_t */
+ mov %r1, %r15 /* 2-nd parameter: dest_addr */
+ j [%r2]
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 8ace87f..6a36a81 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 <asm/cache.h>
+
/*
* ARC architecture has additional address space - auxiliary registers.
* These registers are mostly used for configuration purposes.
@@ -21,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
@@ -40,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/include/asm/cache.h b/arch/arc/include/asm/cache.h
index 16e7568..8a77cd9 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -9,15 +9,22 @@
#include <config.h>
-/*
- * 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(ARC_MMU_ABSENT)
+#define CONFIG_ARC_MMU_VER 0
+#elif defined(CONFIG_ARC_MMU_V2)
+#define CONFIG_ARC_MMU_VER 2
+#elif defined(CONFIG_ARC_MMU_V3)
+#define CONFIG_ARC_MMU_VER 3
+#elif defined(CONFIG_ARC_MMU_V4)
+#define CONFIG_ARC_MMU_VER 4
#endif
#endif /* __ASM_ARC_CACHE_H */
diff --git a/arch/arc/include/asm/config.h b/arch/arc/include/asm/config.h
index e5be078..b4e9099 100644
--- a/arch/arc/include/asm/config.h
+++ b/arch/arc/include/asm/config.h
@@ -7,8 +7,10 @@
#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
+#define CONFIG_ARCH_EARLY_INIT_R
#define CONFIG_LMB
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
index bae4419..b8028c9 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 0000000..b332416
--- /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/cache.c b/arch/arc/lib/cache.c
index fa19a13..a227723 100644
--- a/arch/arc/lib/cache.c
+++ b/arch/arc/lib/cache.c
@@ -6,6 +6,7 @@
#include <config.h>
#include <asm/arcregs.h>
+#include <asm/cache.h>
/* Bit values in IC_CTRL */
#define IC_CTRL_CACHE_DISABLE (1 << 0)
@@ -101,7 +102,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 +116,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 +146,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);
diff --git a/arch/arc/lib/libgcc2.c b/arch/arc/lib/libgcc2.c
new file mode 100644
index 0000000..d5ad327
--- /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 0000000..8813c3b
--- /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 */
diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S
index fa5aac5..87bccab 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