* 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/82559_eeprom.c b/examples/82559_eeprom.c
index d66b3dd..1a121d4 100644
--- a/examples/82559_eeprom.c
+++ b/examples/82559_eeprom.c
@@ -22,7 +22,7 @@
 #define _LINUX_STRING_H_	/* avoid unnecessary str/mem functions */
 
 #include <common.h>
-#include <syscall.h>
+#include <exports.h>
 #include <asm/io.h>
 
 
@@ -96,7 +96,7 @@
 	long ee_addr = ioaddr + EE_OFFSET;
 
 	if (debug > 1)
-		mon_printf(" EEPROM op 0x%x: ", cmd);
+		printf(" EEPROM op 0x%x: ", cmd);
 
 	outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
 
@@ -106,7 +106,7 @@
 		outw(dataval, ee_addr);
 		eeprom_delay(ee_addr);
 		if (debug > 2)
-			mon_printf("%X", inw(ee_addr) & 15);
+			printf("%X", inw(ee_addr) & 15);
 		outw(dataval | EE_SHIFT_CLK, ee_addr);
 		eeprom_delay(ee_addr);
 		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
@@ -117,7 +117,7 @@
 	/* Terminate the EEPROM access. */
 	outw(EE_ENB & ~EE_CS, ee_addr);
 	if (debug > 1)
-		mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
+		printf(" EEPROM result is 0x%5.5x.\n", retval);
 	return retval;
 }
 
@@ -143,7 +143,7 @@
 	/* Poll for write finished. */
 	i = eeprom_busy_poll(ee_ioaddr);			/* Typical 2000 ticks */
 	if (debug)
-		mon_printf(" Write finished after %d ticks.\n", i);
+		printf(" Write finished after %d ticks.\n", i);
 	/* Disable programming. This command is not instantaneous, so we check
 	   for busy before the next op. */
 	do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
@@ -156,7 +156,7 @@
 	int size_test;
 	int i;
 
-	mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
+	printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
 
 	size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
 	eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
@@ -177,11 +177,11 @@
 
 	for (i = 0; i < eeprom_size; i++)
 		if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
-			mon_printf("failed\n");
+			printf("failed\n");
 			return 1;
 		}
 
-	mon_printf("done\n");
+	printf("done\n");
 	return 0;
 }
 
@@ -308,19 +308,20 @@
 	char buf[6];
 	int instance;
 
+	app_startup(argv);
 	if (argc != 2) {
-		mon_printf ("call with base Ethernet address\n");
+		printf ("call with base Ethernet address\n");
 		return 1;
 	}
 
 
 	eth_addr = gethwaddr(argv[1], buf);
 	if (NULL == eth_addr) {
-		mon_printf ("Can not parse ethernet address\n");
+		printf ("Can not parse ethernet address\n");
 		return 1;
 	}
 	if (eth_addr[5] & 0x01) {
-		mon_printf("Base Ethernet address must be even\n");
+		printf("Base Ethernet address must be even\n");
 	}
 
 
@@ -329,22 +330,22 @@
 		unsigned char mac[6];
 		int bar1 = read_config_dword(0, 6+instance, 0, 0x14);
 		if (! (bar1 & 1)) {
-			mon_printf("ETH%d is disabled %x\n", instance, bar1);
+			printf("ETH%d is disabled %x\n", instance, bar1);
 		} else {
-			mon_printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
+			printf("ETH%d IO=0x%04x\n", instance, bar1 & ~3);
 		}
 		io_addr = (bar1 & (~3L));
 
 
 		write_config_word(0, 6+instance, 0, 4,
 				  read_config_word(0, 6+instance, 0, 4) | 1);
-		mon_printf("ETH%d CMD %04x\n", instance,
+		printf("ETH%d CMD %04x\n", instance,
 			   read_config_word(0, 6+instance, 0, 4));
 
 		memcpy(mac, eth_addr, 6);
 		mac[5] += instance;
 
-		mon_printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
+		printf("got io=%04x, ha=%02x:%02x:%02x:%02x:%02x:%02x\n",
 			   io_addr, mac[0], mac[1], mac[2],
 			   mac[3], mac[4], mac[5]);
 		reset_eeprom(io_addr, mac);
diff --git a/examples/Makefile b/examples/Makefile
index 9abff63..7975df5 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -21,7 +21,21 @@
 # MA 02111-1307 USA
 #
 
+ifeq ($(ARCH),ppc)
 LOAD_ADDR = 0x40000
+endif
+
+ifeq ($(ARCH),i386)
+LOAD_ADDR = 0x40000
+endif
+
+ifeq ($(ARCH),arm)
+LOAD_ADDR = 0xc100000
+endif
+
+ifeq ($(ARCH),mips)
+LOAD_ADDR = 0x80200000 -T mips.lds
+endif
 
 include $(TOPDIR)/config.mk
 
@@ -38,11 +52,6 @@
 BIN    += sched.bin
 endif
 
-ifeq ($(ARCH),mips)
-SREC =
-BIN =
-endif
-
 # The following example is pretty 8xx specific...
 ifeq ($(CPU),mpc8xx)
 SREC   += timer.srec
@@ -62,12 +71,12 @@
 
 OBJS	= $(SREC:.srec=.o)
 
-LIB	= libsyscall.a
-LIBAOBJS= syscall.o
+LIB	= libstubs.a
+LIBAOBJS=
 ifeq ($(ARCH),ppc)
 LIBAOBJS+= $(ARCH)_longjmp.o $(ARCH)_setjmp.o
 endif
-LIBCOBJS=
+LIBCOBJS= stubs.o
 LIBOBJS	= $(LIBAOBJS) $(LIBCOBJS)
 
 CPPFLAGS += -I..
diff --git a/examples/eepro100_eeprom.c b/examples/eepro100_eeprom.c
index 2302003..60b937e 100644
--- a/examples/eepro100_eeprom.c
+++ b/examples/eepro100_eeprom.c
@@ -21,17 +21,19 @@
 #define _LINUX_STRING_H_	/* avoid unnecessary str/mem functions */
 
 #include <common.h>
-#include <syscall.h>
+#include <exports.h>
 
 static int reset_eeprom(unsigned long ioaddr, unsigned char *hwaddr);
 
-int eepro100_eeprom(void)
+int eepro100_eeprom(int argc, char *argv[])
 {
 	int ret = 0;
 
 	unsigned char hwaddr1[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x05 };
 	unsigned char hwaddr2[6] = { 0x00, 0x00, 0x02, 0x03, 0x04, 0x06 };
 
+	app_startup(argv);
+
 #if defined(CONFIG_OXC)
 	ret |= reset_eeprom(0x80000000, hwaddr1);
 	ret |= reset_eeprom(0x81000000, hwaddr2);
@@ -119,7 +121,7 @@
 	long ee_addr = ioaddr + EE_OFFSET;
 
 	if (debug > 1)
-		mon_printf(" EEPROM op 0x%x: ", cmd);
+		printf(" EEPROM op 0x%x: ", cmd);
 
 	outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
 
@@ -129,7 +131,7 @@
 		outw(dataval, ee_addr);
 		eeprom_delay(ee_addr);
 		if (debug > 2)
-			mon_printf("%X", inw(ee_addr) & 15);
+			printf("%X", inw(ee_addr) & 15);
 		outw(dataval | EE_SHIFT_CLK, ee_addr);
 		eeprom_delay(ee_addr);
 		retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
@@ -140,7 +142,7 @@
 	/* Terminate the EEPROM access. */
 	outw(EE_ENB & ~EE_CS, ee_addr);
 	if (debug > 1)
-		mon_printf(" EEPROM result is 0x%5.5x.\n", retval);
+		printf(" EEPROM result is 0x%5.5x.\n", retval);
 	return retval;
 }
 
@@ -166,7 +168,7 @@
 	/* Poll for write finished. */
 	i = eeprom_busy_poll(ee_ioaddr);			/* Typical 2000 ticks */
 	if (debug)
-		mon_printf(" Write finished after %d ticks.\n", i);
+		printf(" Write finished after %d ticks.\n", i);
 	/* Disable programming. This command is not instantaneous, so we check
 	   for busy before the next op. */
 	do_eeprom_cmd(ioaddr, (0x40 << (addr_len-4)), 3 + addr_len);
@@ -179,7 +181,7 @@
 	int size_test;
 	int i;
 
-	mon_printf("Resetting i82559 EEPROM @ 0x%08x ... ", ioaddr);
+	printf("Resetting i82559 EEPROM @ 0x%08lX ... ", ioaddr);
 
 	size_test = do_eeprom_cmd(ioaddr, (EE_READ_CMD << 8) << 16, 27);
 	eeprom_addr_size = (size_test & 0xffe0000) == 0xffe0000 ? 8 : 6;
@@ -200,10 +202,10 @@
 
 	for (i = 0; i < eeprom_size; i++)
 		if (read_eeprom(ioaddr, i, eeprom_addr_size) != eeprom[i]) {
-			mon_printf("failed\n");
+			printf("failed\n");
 			return 1;
 		}
 
-	mon_printf("done\n");
+	printf("done\n");
 	return 0;
 }
diff --git a/examples/hello_world.c b/examples/hello_world.c
index 96204c4..9317f6d 100644
--- a/examples/hello_world.c
+++ b/examples/hello_world.c
@@ -22,28 +22,33 @@
  */
 
 #include <common.h>
-#include <syscall.h>
+#include <exports.h>
 
 int hello_world (int argc, char *argv[])
 {
 	int i;
 
-	mon_printf ("Hello World\n");
+	/* Print the ABI version */
+	app_startup(argv);
+	printf ("Example expects ABI version %d\n", XF_VERSION);
+	printf ("Actual U-Boot ABI version %d\n", (int)get_version());
 
-	mon_printf ("argc = %d\n", argc);
+	printf ("Hello World\n");
+
+	printf ("argc = %d\n", argc);
 
 	for (i=0; i<=argc; ++i) {
-		mon_printf ("argv[%d] = \"%s\"\n",
+		printf ("argv[%d] = \"%s\"\n",
 			i,
 			argv[i] ? argv[i] : "<NULL>");
 	}
 
-	mon_printf ("Hit any key to exit ... ");
-	while (!mon_tstc())
+	printf ("Hit any key to exit ... ");
+	while (!tstc())
 		;
 	/* consume input */
-	(void) mon_getc();
+	(void) getc();
 
-	mon_printf ("\n\n");
+	printf ("\n\n");
 	return (0);
 }
diff --git a/examples/mem_to_mem_idma2intr.c b/examples/mem_to_mem_idma2intr.c
index 3f0fd37..3a269c9 100644
--- a/examples/mem_to_mem_idma2intr.c
+++ b/examples/mem_to_mem_idma2intr.c
@@ -28,7 +28,7 @@
 
 
 #include <common.h>
-#include <syscall.h>
+#include <exports.h>
 
 #define STANDALONE
 
@@ -36,13 +36,6 @@
 #include <command.h>
 #include <watchdog.h>
 #else					/* Standalone app of PPCBoot */
-#include <syscall.h>
-#define printf	mon_printf
-#define tstc	mon_tstc
-#define getc	mon_getc
-#define putc	mon_putc
-#define udelay	mon_udelay
-#define malloc	mon_malloc
 #define WATCHDOG_RESET() {						\
 			*(ushort *)(CFG_IMMR + 0x1000E) = 0x556c;	\
 			*(ushort *)(CFG_IMMR + 0x1000E) = 0xaa39;	\
@@ -180,8 +173,8 @@
 #ifdef STANDALONE
 int ctrlc (void)
 {
-	if (mon_tstc()) {
-		switch (mon_getc ()) {
+	if (tstc()) {
+		switch (getc ()) {
 		case 0x03:		/* ^C - Control C */
 			return 1;
 		default:
@@ -209,19 +202,20 @@
 #endif	/* STANDALONE */
 
 #ifdef STANDALONE
-int mem_to_mem_idma2intr (bd_t * bd, int argc, char *argv[])
+int mem_to_mem_idma2intr (int argc, char *argv[])
 #else
 int do_idma (bd_t * bd, int argc, char *argv[])
 #endif	/* STANDALONE */
 {
 	int i;
 
+	app_startup(argv);
 	dpinit_done = 0;
 
 	idma_init ();
 
 	DEBUG ("Installing dma handler\n");
-	mon_install_hdlr (7, dmadone_handler, (void *) bdf);
+	install_hdlr (7, dmadone_handler, (void *) bdf);
 
 	memset ((void *) 0x100000, 'a', 512);
 	memset ((void *) 0x200000, 'b', 512);
@@ -232,7 +226,7 @@
 	}
 
 	DEBUG ("Uninstalling dma handler\n");
-	mon_free_hdlr (7);
+	free_hdlr (7);
 
 	return 0;
 }
diff --git a/examples/mips.lds b/examples/mips.lds
new file mode 100644
index 0000000..8ed01c4
--- /dev/null
+++ b/examples/mips.lds
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2003
+ * Wolfgang Denk 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
+ */
+
+/*
+OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips")
+*/
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips")
+OUTPUT_ARCH(mips)
+SECTIONS
+{
+	.text       :
+	{
+	  *(.text)
+	}
+
+	. = ALIGN(4);
+	.rodata  : { *(.rodata) }
+
+	. = ALIGN(4);
+	.data  : { *(.data) }
+
+	. = ALIGN(4);
+	.sdata  : { *(.sdata) }
+
+	_gp = ALIGN(16);
+
+	__got_start = .;
+	.got  : { *(.got) }
+	__got_end = .;
+
+	.sdata  : { *(.sdata) }
+
+	. = ALIGN(4);
+	.sbss  : { *(.sbss) }
+	.bss  : { *(.bss) }
+}
diff --git a/examples/sched.c b/examples/sched.c
index ceb5c1f..6b78f69 100644
--- a/examples/sched.c
+++ b/examples/sched.c
@@ -16,7 +16,7 @@
  */
 
 #include <common.h>
-#include <syscall.h>
+#include <exports.h>
 
 /*
  * Author: Arun Dharankar <ADharankar@ATTBI.Com>
@@ -76,9 +76,9 @@
 
 #define PDEBUG(fmt, args...)	 {					\
 	if(dbg != 0) {							\
-		mon_printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\
-		mon_printf(fmt, ##args);				\
-		mon_printf("\n");					\
+		printf("[%s %d %s]: ",__FILE__,__LINE__,__FUNCTION__);\
+		printf(fmt, ##args);				\
+		printf("\n");					\
 	}								\
 }
 
@@ -97,41 +97,43 @@
 /* An example of schedular test */
 
 #define NUMTHREADS 7
-int sched (bd_t * bd, int ac, char *av[])
+int sched (int ac, char *av[])
 {
 	int i, j;
 	int tid[NUMTHREADS];
 	int names[NUMTHREADS];
 
+	app_startup(av);
+
 	sched_init ();
 
 	for (i = 0; i < NUMTHREADS; i++) {
 		names[i] = i;
 		j = thread_create (testthread, (void *) &names[i]);
 		if (j == RC_FAILURE)
-			mon_printf ("schedtest: Failed to create thread %d\n", i);
+			printf ("schedtest: Failed to create thread %d\n", i);
 		if (j > 0) {
-			mon_printf ("schedtest: Created thread with id %d, name %d\n",
+			printf ("schedtest: Created thread with id %d, name %d\n",
 						j, i);
 			tid[i] = j;
 		}
 	}
-	mon_printf ("schedtest: Threads created\n");
+	printf ("schedtest: Threads created\n");
 
-	mon_printf ("sched_test: function=0x%08x\n", testthread);
+	printf ("sched_test: function=0x%08x\n", (unsigned)testthread);
 	for (i = 0; i < NUMTHREADS; i++) {
-		mon_printf ("schedtest: Setting thread %d runnable\n", tid[i]);
+		printf ("schedtest: Setting thread %d runnable\n", tid[i]);
 		thread_start (tid[i]);
 		thread_yield ();
 	}
-	mon_printf ("schedtest: Started %d threads\n", NUMTHREADS);
+	printf ("schedtest: Started %d threads\n", NUMTHREADS);
 
 	while (1) {
-		mon_printf ("schedtest: Waiting for threads to complete\n");
-		if (mon_tstc () && mon_getc () == 0x3) {
-			mon_printf ("schedtest: Aborting threads...\n");
+		printf ("schedtest: Waiting for threads to complete\n");
+		if (tstc () && getc () == 0x3) {
+			printf ("schedtest: Aborting threads...\n");
 			for (i = 0; i < NUMTHREADS; i++) {
-				mon_printf ("schedtest: Deleting thread %d\n", tid[i]);
+				printf ("schedtest: Deleting thread %d\n", tid[i]);
 				thread_delete (tid[i]);
 			}
 			return RC_SUCCESS;
@@ -139,11 +141,11 @@
 		j = -1;
 		i = thread_join (&j);
 		if (i == RC_FAILURE) {
-			mon_printf ("schedtest: No threads pending, "
+			printf ("schedtest: No threads pending, "
 						"exiting schedular test\n");
 			return RC_SUCCESS;
 		}
-		mon_printf ("schedtest: thread is %d returned %d\n", i, j);
+		printf ("schedtest: thread is %d returned %d\n", i, j);
 		thread_yield ();
 	}
 
@@ -154,14 +156,14 @@
 {
 	int i;
 
-	mon_printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
-			 *(int *) name, &i);
+	printf ("testthread: Begin executing thread, myname %d, &i=0x%08x\n",
+		*(int *) name, (unsigned)&i);
 
-	mon_printf ("Thread %02d, i=%d\n", *(int *) name);
+	printf ("Thread %02d, i=%d\n", *(int *) name, i);
 
 	for (i = 0; i < 0xffff * (*(int *) name + 1); i++) {
-		if (mon_tstc () && mon_getc () == 0x3) {
-			mon_printf ("testthread: myname %d terminating.\n",
+		if (tstc () && getc () == 0x3) {
+			printf ("testthread: myname %d terminating.\n",
 						*(int *) name);
 			return *(int *) name + 1;
 		}
@@ -170,7 +172,7 @@
 			thread_yield ();
 	}
 
-	mon_printf ("testthread: returning %d, i=0x%x\n",
+	printf ("testthread: returning %d, i=0x%x\n",
 				*(int *) name + 1, i);
 
 	return *(int *) name + 1;
@@ -187,7 +189,7 @@
 	current_tid = MASTER_THREAD;
 	lthreads[current_tid].state = STATE_RUNNABLE;
 	PDEBUG ("sched_init: master context = 0x%08x",
-		   lthreads[current_tid].context);
+		(unsigned)lthreads[current_tid].context);
 	return;
 }
 
@@ -200,7 +202,8 @@
 #define SWITCH(new) 							\
 	if(lthreads[new].state == STATE_RUNNABLE) {			\
 		PDEBUG("thread_yield: %d match, ctx=0x%08x",		\
-			new, lthreads[current_tid].context); 		\
+			new,						\
+			(unsigned)lthreads[current_tid].context);	\
 		if(setjmp(lthreads[current_tid].context) == 0) {	\
 			current_tid = new;				\
 			PDEBUG("thread_yield: tid %d returns 0",	\
@@ -260,7 +263,7 @@
 static void thread_launcher (void)
 {
 	PDEBUG ("thread_launcher: invoking func=0x%08x",
-		   lthreads[current_tid].func);
+		   (unsigned)lthreads[current_tid].func);
 
 	lthreads[current_tid].retval =
 			lthreads[current_tid].func (lthreads[current_tid].arg);
@@ -269,7 +272,7 @@
 
 	lthreads[current_tid].state = STATE_TERMINATED;
 	thread_yield ();
-	mon_printf ("thread_launcher: should NEVER get here!\n");
+	printf ("thread_launcher: should NEVER get here!\n");
 
 	return;
 }
@@ -287,7 +290,8 @@
 	if (setjmp (lthreads[current_tid].context) == 0) {
 		lthreads[id].state = STATE_RUNNABLE;
 		current_tid = id;
-		PDEBUG ("thread_start: to be stack=0%08x", lthreads[id].stack);
+		PDEBUG ("thread_start: to be stack=0%08x",
+			(unsigned)lthreads[id].stack);
 		setctxsp (&lthreads[id].stack[STK_SIZE]);
 		thread_launcher ();
 	}
@@ -297,7 +301,7 @@
 	return RC_SUCCESS;
 }
 
-#if 0							/* not used so far */
+#if 0	/* not used so far */
 static int thread_stop (int id)
 {
 	if (id <= MASTER_THREAD || id >= MAX_THREADS)
@@ -309,7 +313,7 @@
 	lthreads[id].state = STATE_STOPPED;
 	return RC_SUCCESS;
 }
-#endif							/* not used so far */
+#endif	/* not used so far */
 
 static int thread_join (int *ret)
 {
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
diff --git a/examples/syscall.S b/examples/syscall.S
deleted file mode 100644
index f319409..0000000
--- a/examples/syscall.S
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <ppc_asm.tmpl>
-#include <ppc_defs.h>
-#include <syscall.h>
-
-#ifdef CONFIG_ARM /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#warning ARM version not implemented yet /* XXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-	.global	mon_getc
-	.type	mon_getc,function
-mon_getc:
-	.global	mon_tstc
-	.type	mon_tstc,function
-mon_tstc:
-	.global	mon_putc
-	.type	mon_putc,function
-mon_putc:
-	.global	mon_puts
-	.type	mon_puts,function
-mon_puts:
-	.global	mon_printf
-	.type	mon_printf,function
-mon_printf:
-	.global	mon_install_hdlr
-	.type	mon_install_hdlr,function
-mon_install_hdlr:
-	.global	mon_free_hdlr
-	.type	mon_free_hdlr,function
-mon_free_hdlr:
-	.global	mon_malloc
-	.type	mon_malloc,function
-mon_malloc:
-	.global	mon_free
-	.type	mon_free,function
-mon_free:
-	@ args = 0, pretend = 0, frame = 0
-	@ frame_needed = 1, current_function_anonymous_args = 0
-	mov     ip, sp
-	stmfd   sp!, {fp, ip, lr, pc}
-	sub     fp, ip, #4
-	ldmea   fp, {fp, sp, pc}
-#elif defined(CONFIG_MIPS)/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#warning MIPS version not implemented yet
-	.global	mon_getc
-	.type	mon_getc,function
-mon_getc:
-	.global	mon_tstc
-	.type	mon_tstc,function
-mon_tstc:
-	.global	mon_putc
-	.type	mon_putc,function
-mon_putc:
-	.global	mon_puts
-	.type	mon_puts,function
-mon_puts:
-	.global	mon_printf
-	.type	mon_printf,function
-mon_printf:
-	.global	mon_install_hdlr
-	.type	mon_install_hdlr,function
-mon_install_hdlr:
-	.global	mon_free_hdlr
-	.type	mon_free_hdlr,function
-mon_free_hdlr:
-	.global	mon_malloc
-	.type	mon_malloc,function
-mon_malloc:
-	.global	mon_free
-	.type	mon_free,function
-mon_free:
-
-#else
-
-#ifdef CONFIG_I386 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-#define SYMBOL_NAME(X) 	X
-#define SYMBOL_NAME_LABEL(X) 	X##:
-
-#define SYSCALL(name,n) \
-	.globl SYMBOL_NAME(name) ; \
-SYMBOL_NAME_LABEL(name)     		 ; \
-	movl    $n, %eax ;\
-	pushl   %ebx; \
-	pushl   %ecx; \
-	int     $0x40 ;\
-
-
-#endif	/* CONFIG_I386 */
-
-#ifdef CONFIG_PPC
-#define SYSCALL(name,n) \
-	.globl name		; \
-name:				; \
-	li r0,n			; \
-	sc			; \
-	blr
-#endif	/* CONFIG_PPC */
-
-	.text
-
-	/*
-	 * Make sure these functions are in the same order as they
-	 * appear in the "include/syscall.h" header file !!!
-	 */
-
-	SYSCALL(mon_getc,SYSCALL_GETC)
-	SYSCALL(mon_tstc,SYSCALL_TSTC)
-	SYSCALL(mon_putc,SYSCALL_PUTC)
-	SYSCALL(mon_puts,SYSCALL_PUTS)
-	SYSCALL(mon_printf,SYSCALL_PRINTF)
-	SYSCALL(mon_install_hdlr,SYSCALL_INSTALL_HDLR)
-	SYSCALL(mon_free_hdlr,SYSCALL_FREE_HDLR)
-	SYSCALL(mon_malloc,SYSCALL_MALLOC)
-	SYSCALL(mon_free,SYSCALL_FREE)
-	SYSCALL(mon_udelay,SYSCALL_UDELAY)
-	SYSCALL(mon_get_timer,SYSCALL_GET_TIMER)
-#endif /* CONFIG_ARM XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
diff --git a/examples/timer.c b/examples/timer.c
index bfe3d66..037fdfd 100644
--- a/examples/timer.c
+++ b/examples/timer.c
@@ -24,7 +24,7 @@
 #include <common.h>
 #include <commproc.h>
 #include <mpc8xx_irq.h>
-#include <syscall.h>
+#include <exports.h>
 
 #undef	DEBUG
 
@@ -123,10 +123,12 @@
 	int c;
 	int running;
 
+	app_startup(argv);
+
 	/* Pointer to CPM Timer structure */
 	cpmtimerp = &((immap_t *) gd->bd->bi_immr_base)->im_cpmtimer;
 
-	mon_printf ("TIMERS=0x%x\n", (unsigned) cpmtimerp);
+	printf ("TIMERS=0x%x\n", (unsigned) cpmtimerp);
 
 	/* Initialize pointers depending on which timer we use */
 	switch (TID_TIMER_ID) {
@@ -166,7 +168,7 @@
 
 	hwp->tgcrp = &cpmtimerp->cpmt_tgcr;
 
-	mon_printf ("Using timer %d\n"
+	printf ("Using timer %d\n"
 			"tgcr @ 0x%x, tmr @ 0x%x, trr @ 0x%x,"
 			" tcr @ 0x%x, tcn @ 0x%x, ter @ 0x%x\n",
 			TID_TIMER_ID + 1,
@@ -184,24 +186,24 @@
 	/* clear all events */
 	*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);
 
-	mon_printf (usage);
+	printf (usage);
 	running = 0;
-	while ((c = mon_getc()) != 'q') {
+	while ((c = getc()) != 'q') {
 	    if (c == 'b') {
 
 		setPeriod (hwp, TIMER_PERIOD);	/* Set period and start ticking */
 
 		/* Install interrupt handler (enable timer in CIMR) */
-		mon_install_hdlr (hwp->cpm_vec, timer_handler, hwp);
+		install_hdlr (hwp->cpm_vec, timer_handler, hwp);
 
-		mon_printf ("Enabling timer\n");
+		printf ("Enabling timer\n");
 
 		/* enable timer */
 		*hwp->tgcrp |= (CPMT_GCR_RST << TID_TIMER_ID);
 		running = 1;
 
 #ifdef	DEBUG
-		mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+		printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
 			" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
 				*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
 				*hwp->tcrp,  *hwp->tcnp, *hwp->terp
@@ -209,20 +211,20 @@
 #endif
 	    } else if (c == 'e') {
 
-		mon_printf ("Stopping timer\n");
+		printf ("Stopping timer\n");
 
 		*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
 		running = 0;
 
 #ifdef	DEBUG
-		mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+		printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
 			" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
 				*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
 				*hwp->tcrp,  *hwp->tcnp, *hwp->terp
 			);
 #endif
 		/* Uninstall interrupt handler */
-		mon_free_hdlr (hwp->cpm_vec);
+		free_hdlr (hwp->cpm_vec);
 
 	    } else if (c == '?') {
 #ifdef	DEBUG
@@ -230,13 +232,13 @@
 		sysconf8xx_t *siup = &((immap_t *) gd->bd->bi_immr_base)->im_siu_conf;
 #endif
 
-		mon_printf ("\ntgcr=0x%x, tmr=0x%x, trr=0x%x,"
+		printf ("\ntgcr=0x%x, tmr=0x%x, trr=0x%x,"
 			" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
 				*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
 				*hwp->tcrp,  *hwp->tcnp, *hwp->terp
 			);
 #ifdef	DEBUG
-		mon_printf ("SIUMCR=0x%08lx, SYPCR=0x%08lx,"
+		printf ("SIUMCR=0x%08lx, SYPCR=0x%08lx,"
 			" SIMASK=0x%08lx, SIPEND=0x%08lx\n",
 				siup->sc_siumcr,
 				siup->sc_sypcr,
@@ -244,21 +246,21 @@
 				siup->sc_sipend
 			);
 
-		mon_printf ("CIMR=0x%08lx, CICR=0x%08lx, CIPR=0x%08lx\n",
+		printf ("CIMR=0x%08lx, CICR=0x%08lx, CIPR=0x%08lx\n",
 			cpm_icp->cpic_cimr,
 			cpm_icp->cpic_cicr,
 			cpm_icp->cpic_cipr
 			);
 #endif
 	    } else {
-	    	mon_printf ("\nEnter: q - quit, b - start timer, e - stop timer, ? - get status\n");
+	    	printf ("\nEnter: q - quit, b - start timer, e - stop timer, ? - get status\n");
 	    }
-	    mon_printf (usage);
+	    printf (usage);
 	}
 	if (running) {
-		mon_printf ("Stopping timer\n");
+		printf ("Stopping timer\n");
 		*hwp->tgcrp &= ~(CPMT_GCR_MASK << TID_TIMER_ID);
-		mon_free_hdlr (hwp->cpm_vec);
+		free_hdlr (hwp->cpm_vec);
 	}
 
 	return (0);
@@ -274,11 +276,11 @@
 	unsigned short prescaler;
 	unsigned long ticks;
 
-	mon_printf ("Set interval %ld us\n", interval);
+	printf ("Set interval %ld us\n", interval);
 
 	/* Warn if requesting longer period than possible */
 	if (interval > CPMT_MAX_INTERVAL) {
-		mon_printf ("Truncate interval %ld to maximum (%d)\n",
+		printf ("Truncate interval %ld to maximum (%d)\n",
 				interval, CPMT_MAX_INTERVAL);
 		interval = CPMT_MAX_INTERVAL;
 	}
@@ -303,7 +305,7 @@
 	}
 
 #ifdef	DEBUG
-	mon_printf ("clock/%d, prescale factor %d, reference %ld, ticks %ld\n",
+	printf ("clock/%d, prescale factor %d, reference %ld, ticks %ld\n",
 			(ticks > CPMT_MAX_TICKS) ? CPMT_CLOCK_DIV : 1,
 			CPMT_PRESCALER,
 			(ticks / CPMT_PRESCALER),
@@ -321,7 +323,7 @@
 	*hwp->trrp = (unsigned short) (ticks / CPMT_PRESCALER);
 
 #ifdef	DEBUG
-	mon_printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
+	printf ("tgcr=0x%x, tmr=0x%x, trr=0x%x,"
 		" tcr=0x%x, tcn=0x%x, ter=0x%x\n",
 			*hwp->tgcrp, *hwp->tmrp, *hwp->trrp,
 			*hwp->tcrp,  *hwp->tcnp, *hwp->terp
@@ -340,7 +342,7 @@
 	/* printf ("** TER1=%04x ** ", *hwp->terp); */
 
 	/* just for demonstration */
-	mon_printf (".");
+	printf (".");
 
 	/* clear all possible events: Ref. and Cap. */
 	*hwp->terp = (CPMT_EVENT_CAP | CPMT_EVENT_REF);