blob: c0ef65048e92a82d53bbe2dc0d395b43b1f47457 [file] [log] [blame]
wdenk27b207f2003-07-24 23:38:38 +00001#include <exports.h>
2
3#if defined(CONFIG_I386)
4/*
5 * x86 does not have a dedicated register to store the pointer to
6 * the global_data. Thus the jump table address is stored in a
7 * global variable, but such approach does not allow for execution
8 * from flash memory. The global_data address is passed as argv[-1]
9 * to the application program.
10 */
11static void **jt;
12
13#define EXPORT_FUNC(x) \
14 asm volatile ( \
15" .globl " #x "\n" \
16#x ":\n" \
17" movl %0, %%eax\n" \
18" movl jt, %%ecx\n" \
19" jmp *(%%ecx, %%eax)\n" \
20 : : "i"(XF_ ## x * sizeof(void *)) : "eax", "ecx");
21#elif defined(CONFIG_PPC)
22/*
23 * r29 holds the pointer to the global_data, r11 is a call-clobbered
24 * register
25 */
26#define EXPORT_FUNC(x) \
27 asm volatile ( \
28" .globl " #x "\n" \
29#x ":\n" \
30" lwz %%r11, %0(%%r29)\n" \
31" lwz %%r11, %1(%%r11)\n" \
32" mtctr %%r11\n" \
33" bctr\n" \
34 : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r11");
35#elif defined(CONFIG_ARM)
36/*
37 * r8 holds the pointer to the global_data, ip is a call-clobbered
38 * register
39 */
40#define EXPORT_FUNC(x) \
41 asm volatile ( \
42" .globl " #x "\n" \
43#x ":\n" \
44" ldr ip, [r8, %0]\n" \
45" ldr pc, [ip, %1]\n" \
46 : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "ip");
47#elif defined(CONFIG_MIPS)
48/*
49 * k0 ($26) holds the pointer to the global_data; t9 ($25) is a call-
50 * clobbered register that is also used to set gp ($26). Note that the
51 * jr instruction also executes the instruction immediately following
52 * it; however, GCC/mips generates an additional `nop' after each asm
53 * statement
54 */
55#define EXPORT_FUNC(x) \
56 asm volatile ( \
57" .globl " #x "\n" \
58#x ":\n" \
59" lw $25, %0($26)\n" \
60" lw $25, %1($25)\n" \
61" jr $25\n" \
62 : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "t9");
63#else
64#error stubs definition missing for this architecture
65#endif
66
67/* This function is necessary to prevent the compiler from
68 * generating prologue/epilogue, preparing stack frame etc.
69 * The stub functions are special, they do not use the stack
70 * frame passed to them, but pass it intact to the actual
71 * implementation. On the other hand, asm() statements with
72 * arguments can be used only inside the functions (gcc limitation)
73 */
74static void __attribute__((unused)) dummy(void)
75{
76#include <_exports.h>
77}
78
79void app_startup(char **argv)
80{
81#if defined(CONFIG_I386)
82 /* x86 does not have a dedicated register for passing global_data */
83 jt = ((gd_t *)argv[-1])->jt;
84#endif
85}
86
87#undef EXPORT_FUNC