* Implement new mechanism to export U-Boot's functions to standalone
  applications: instead of using (PPC-specific) system calls we now
  use a jump table; please see doc/README.standalone for details

* Patch by Dave Westwood, 24 Jul 2003:
  added support for Unity OS (a proprietary OS)
diff --git a/examples/stubs.c b/examples/stubs.c
new file mode 100644
index 0000000..c0ef650
--- /dev/null
+++ b/examples/stubs.c
@@ -0,0 +1,87 @@
+#include <exports.h>
+
+#if defined(CONFIG_I386)
+/*
+ * x86 does not have a dedicated register to store the pointer to
+ * the global_data. Thus the jump table address is stored in a
+ * global variable, but such approach does not allow for execution
+ * from flash memory. The global_data address is passed as argv[-1]
+ * to the application program.
+ */
+static void **jt;
+
+#define EXPORT_FUNC(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");
+#elif defined(CONFIG_PPC)
+/*
+ * r29 holds the pointer to the global_data, r11 is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+	asm volatile (			\
+"	.globl " #x "\n"		\
+#x ":\n"				\
+"	lwz	%%r11, %0(%%r29)\n"	\
+"	lwz	%%r11, %1(%%r11)\n"	\
+"	mtctr	%%r11\n"		\
+"	bctr\n"				\
+	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
+#elif defined(CONFIG_ARM)
+/*
+ * r8 holds the pointer to the global_data, ip is a call-clobbered
+ * register
+ */
+#define EXPORT_FUNC(x) \
+	asm volatile (			\
+"	.globl " #x "\n"		\
+#x ":\n"				\
+"	ldr	ip, [r8, %0]\n"		\
+"	ldr	pc, [ip, %1]\n"		\
+	: : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
+#elif defined(CONFIG_MIPS)
+/*
+ * 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(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");
+#else
+#error stubs definition missing for this architecture
+#endif
+
+/* This function is necessary to prevent the compiler from
+ * generating prologue/epilogue, preparing stack frame etc.
+ * The stub functions are special, they do not use the stack
+ * frame passed to them, but pass it intact to the actual
+ * implementation. On the other hand, asm() statements with
+ * arguments can be used only inside the functions (gcc limitation)
+ */
+static void __attribute__((unused)) dummy(void)
+{
+#include <_exports.h>
+}
+
+void app_startup(char **argv)
+{
+#if defined(CONFIG_I386)
+	/* x86 does not have a dedicated register for passing global_data */
+	jt = ((gd_t *)argv[-1])->jt;
+#endif
+}
+
+#undef EXPORT_FUNC