Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / examples / standalone / stubs.c
index 2d2e7098b7b3cb701ea8de9460483afb66fa0230..0d62067e03be4cbf97e1cd8c38adf503f9120700 100644 (file)
@@ -1,10 +1,10 @@
+#include <common.h>
 #include <exports.h>
+#include <linux/compiler.h>
 
-#ifndef GCC_VERSION
-#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
-#endif /* GCC_VERSION */
+#define FO(x) offsetof(struct jt_funcs, x)
 
-#if defined(CONFIG_I386)
+#if defined(CONFIG_X86)
 /*
  * x86 does not have a dedicated register to store the pointer to
  * the global_data. Thus the jump table address is stored in a
  * from flash memory. The global_data address is passed as argv[-1]
  * to the application program.
  */
-static void **jt;
+static struct jt_funcs *jt;
 gd_t *global_data;
 
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
 "      movl    %0, %%eax\n"            \
 "      movl    jt, %%ecx\n"            \
 "      jmp     *(%%ecx, %%eax)\n"      \
-       : : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
+       : : "i"(FO(x)) : "eax", "ecx");
 #elif defined(CONFIG_PPC)
 /*
  * r2 holds the pointer to the global_data, r11 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
@@ -36,20 +36,52 @@ gd_t *global_data;
 "      lwz     %%r11, %1(%%r11)\n"     \
 "      mtctr   %%r11\n"                \
 "      bctr\n"                         \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r11");
 #elif defined(CONFIG_ARM)
+#ifdef CONFIG_ARM64
 /*
- * r8 holds the pointer to the global_data, ip is a call-clobbered
+ * x18 holds the pointer to the global_data, x9 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
-"      ldr     ip, [r8, %0]\n"         \
+"      ldr     x9, [x18, %0]\n"                \
+"      ldr     x9, [x9, %1]\n"         \
+"      br      x9\n"           \
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "x9");
+#else
+/*
+ * r9 holds the pointer to the global_data, ip is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(f, a, x, ...) \
+       asm volatile (                  \
+"      .globl " #x "\n"                \
+#x ":\n"                               \
+"      ldr     ip, [r9, %0]\n"         \
 "      ldr     pc, [ip, %1]\n"         \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "ip");
+#endif
 #elif defined(CONFIG_MIPS)
+#ifdef CONFIG_CPU_MIPS64
+/*
+ * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
+ * clobbered register that is also used to set gp ($26). Note that the
+ * jr instruction also executes the instruction immediately following
+ * it; however, GCC/mips generates an additional `nop' after each asm
+ * statement
+ */
+#define EXPORT_FUNC(f, a, x, ...) \
+       asm volatile (                  \
+"      .globl " #x "\n"                \
+#x ":\n"                               \
+"      ld      $25, %0($26)\n"         \
+"      ld      $25, %1($25)\n"         \
+"      jr      $25\n"                  \
+        : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9");
+#else
 /*
  * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
  * clobbered register that is also used to set gp ($26). Note that the
@@ -57,19 +89,20 @@ gd_t *global_data;
  * it; however, GCC/mips generates an additional `nop' after each asm
  * statement
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
 "      lw      $25, %0($26)\n"         \
 "      lw      $25, %1($25)\n"         \
 "      jr      $25\n"                  \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "t9");
+#endif
 #elif defined(CONFIG_NIOS2)
 /*
  * gp holds the pointer to the global_data, r8 is call-clobbered
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
@@ -79,13 +112,13 @@ gd_t *global_data;
 "      ldw     r8, 0(r8)\n"            \
 "      ldw     r8, %1(r8)\n"           \
 "      jmp     r8\n"                   \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "gp");
 #elif defined(CONFIG_M68K)
 /*
  * d7 holds the pointer to the global_data, a0 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x) \
+#define EXPORT_FUNC(f, a, x, ...) \
        asm volatile (                  \
 "      .globl " #x "\n"                \
 #x ":\n"                               \
@@ -95,50 +128,50 @@ gd_t *global_data;
 "      adda.l  %1, %%a0\n"             \
 "      move.l  (%%a0), %%a0\n"         \
 "      jmp     (%%a0)\n"                       \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "a0");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "a0");
 #elif defined(CONFIG_MICROBLAZE)
 /*
  * r31 holds the pointer to the global_data. r5 is a call-clobbered.
  */
-#define EXPORT_FUNC(x)                         \
+#define EXPORT_FUNC(f, a, x, ...)                              \
        asm volatile (                          \
 "      .globl " #x "\n"                        \
 #x ":\n"                                       \
 "      lwi     r5, r31, %0\n"                  \
 "      lwi     r5, r5, %1\n"                   \
 "      bra     r5\n"                           \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r5");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r5");
 #elif defined(CONFIG_BLACKFIN)
 /*
  * P3 holds the pointer to the global_data, P0 is a call-clobbered
  * register
  */
-#define EXPORT_FUNC(x)                 \
+#define EXPORT_FUNC(f, a, x, ...)                      \
        asm volatile (                  \
 "      .globl _" #x "\n_"              \
 #x ":\n"                               \
 "      P0 = [P3 + %0]\n"               \
 "      P0 = [P0 + %1]\n"               \
 "      JUMP (P0)\n"                    \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "P0");
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "P0");
 #elif defined(CONFIG_AVR32)
 /*
  * r6 holds the pointer to the global_data. r8 is call clobbered.
  */
-#define EXPORT_FUNC(x)                                 \
+#define EXPORT_FUNC(f, a, x, ...)                                      \
        asm volatile(                                   \
                "       .globl\t" #x "\n"               \
                #x ":\n"                                \
                "       ld.w    r8, r6[%0]\n"           \
                "       ld.w    pc, r8[%1]\n"           \
                :                                       \
-               : "i"(offsetof(gd_t, jt)), "i"(XF_ ##x) \
+               : "i"(offsetof(gd_t, jt)), "i"(FO(x))   \
                : "r8");
 #elif defined(CONFIG_SH)
 /*
  * r13 holds the pointer to the global_data. r1 is a call clobbered.
  */
-#define EXPORT_FUNC(x)                                 \
+#define EXPORT_FUNC(f, a, x, ...)                                      \
        asm volatile (                                  \
                "       .align  2\n"                    \
                "       .globl " #x "\n"                \
@@ -151,12 +184,12 @@ gd_t *global_data;
                "       jmp     @r1\n"                  \
                "       nop\n"                          \
                "       nop\n"                          \
-               : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r1", "r2");
+               : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r1", "r2");
 #elif defined(CONFIG_SPARC)
 /*
  * g7 holds the pointer to the global_data. g1 is call clobbered.
  */
-#define EXPORT_FUNC(x)                                 \
+#define EXPORT_FUNC(f, a, x, ...)                                      \
        asm volatile(                                   \
 "      .globl\t" #x "\n"                               \
 #x ":\n"                                               \
@@ -166,9 +199,51 @@ gd_t *global_data;
 "      ld [%%g1 + %1], %%g1\n"                         \
 "      jmp %%g1\n"                                     \
 "      nop\n"                                          \
-       : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "g1" );
-
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "g1");
+#elif defined(CONFIG_NDS32)
+/*
+ * r16 holds the pointer to the global_data. gp is call clobbered.
+ * not support reduced register (16 GPR).
+ */
+#define EXPORT_FUNC(f, a, x, ...) \
+       asm volatile (                  \
+"      .globl " #x "\n"                \
+#x ":\n"                               \
+"      lwi     $r16, [$gp + (%0)]\n"   \
+"      lwi     $r16, [$r16 + (%1)]\n"  \
+"      jr      $r16\n"                 \
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "$r16");
+#elif defined(CONFIG_OPENRISC)
+/*
+ * r10 holds the pointer to the global_data, r13 is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(f, a, x, ...) \
+       asm volatile (                  \
+"      .globl " #x "\n"                \
+#x ":\n"                               \
+"      l.lwz   r13, %0(r10)\n" \
+"      l.lwz   r13, %1(r13)\n" \
+"      l.jr    r13\n"          \
+"      l.nop\n"                                \
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r13");
+#elif defined(CONFIG_ARC)
+/*
+ * r25 holds the pointer to the global_data. r10 is call clobbered.
+  */
+#define EXPORT_FUNC(f, a, x, ...) \
+       asm volatile( \
+"      .align 4\n" \
+"      .globl " #x "\n" \
+#x ":\n" \
+"      ld      r10, [r25, %0]\n" \
+"      ld      r10, [r10, %1]\n" \
+"      j       [r10]\n" \
+       : : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
 #else
+/*"    addi    $sp, $sp, -24\n"        \
+"      br      $r16\n"                 \*/
+
 #error stubs definition missing for this architecture
 #endif
 
@@ -179,7 +254,7 @@ gd_t *global_data;
  * implementation. On the other hand, asm() statements with
  * arguments can be used only inside the functions (gcc limitation)
  */
-#if GCC_VERSION < 3004
+#if GCC_VERSION < 30400
 static
 #endif /* GCC_VERSION */
 void __attribute__((unused)) dummy(void)
@@ -187,18 +262,17 @@ void __attribute__((unused)) dummy(void)
 #include <_exports.h>
 }
 
-extern unsigned long __bss_start, _end;
+#include <asm/sections.h>
 
 void app_startup(char * const *argv)
 {
-       unsigned char * cp = (unsigned char *) &__bss_start;
+       char *cp = __bss_start;
 
        /* Zero out BSS */
-       while (cp < (unsigned char *)&_end) {
+       while (cp < _end)
                *cp++ = 0;
-       }
 
-#if defined(CONFIG_I386)
+#if defined(CONFIG_X86)
        /* x86 does not have a dedicated register for passing global_data */
        global_data = (gd_t *)argv[-1];
        jt = global_data->jt;