For indirect calls, place function address in a register and call it.
This is less optimal when gcc can inline the code and the destination
address is known at compile time. However, older gcc compilers don't
do as well with inlining, and they then mess up the code generation.
There doesn't seem to be a way to tell gcc how to emit the code
correctly for both immediate addresses and register addresses, so fall
back to a safe way.
Also, reduce params to stack_hop to avoid register assignment issues.
if (! CONFIG_DRIVES)
return -1;
if (! CONFIG_DRIVES)
return -1;
- return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
+ return stack_hop((u32)op, GET_SEG(SS), __send_disk_op);
struct descloc_s gdt;
sgdt(&gdt);
struct descloc_s gdt;
sgdt(&gdt);
- func -= BUILD_BIOS_ADDR;
u32 bkup_ss, bkup_esp;
asm volatile(
// Backup ss/esp / set esp to flat stack location
u32 bkup_ss, bkup_esp;
asm volatile(
// Backup ss/esp / set esp to flat stack location
" pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n"
" jmp transition32\n"
" .code32\n"
" pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n"
" jmp transition32\n"
" .code32\n"
" pushl $2f\n"
" jmp transition16big\n"
" pushl $2f\n"
" jmp transition16big\n"
" movl %0, %%ss\n"
" movl %1, %%esp\n"
: "=&r" (bkup_ss), "=&r" (bkup_esp)
" movl %0, %%ss\n"
" movl %1, %%esp\n"
: "=&r" (bkup_ss), "=&r" (bkup_esp)
: "eax", "ecx", "edx", "cc", "memory");
// Restore gdt and fs/gs
: "eax", "ecx", "edx", "cc", "memory");
// Restore gdt and fs/gs
// Switch to the extra stack in ebda and call a function.
inline u32
// Switch to the extra stack in ebda and call a function.
inline u32
-stack_hop(u32 eax, u32 edx, u32 ecx, void *func)
+stack_hop(u32 eax, u32 edx, void *func)
{
ASSERT16();
u16 ebda_seg = get_ebda_seg(), bkup_ss;
{
ASSERT16();
u16 ebda_seg = get_ebda_seg(), bkup_ss;
"movw %w6, %%ss\n"
"movl %5, %%esp\n"
// Call func
"movw %w6, %%ss\n"
"movl %5, %%esp\n"
// Call func
// Restore segments and stack
"movw %w3, %%ds\n"
"movw %w3, %%ss\n"
"movl %4, %%esp"
// Restore segments and stack
"movw %w3, %%ds\n"
"movw %w3, %%ss\n"
"movl %4, %%esp"
- : "+a" (eax), "+d" (edx), "+c" (ecx), "=&r" (bkup_ss), "=&r" (bkup_esp)
- : "i" (EBDA_OFFSET_TOP_STACK), "r" (ebda_seg), "m" (*(u8*)func)
+ : "+a" (eax), "+d" (edx), "+c" (func), "=&r" (bkup_ss), "=&r" (bkup_esp)
+ : "i" (EBDA_OFFSET_TOP_STACK), "r" (ebda_seg)
: "cc", "memory");
return eax;
}
: "cc", "memory");
return eax;
}
int get_keystroke(int msec);
// stacks.c
int get_keystroke(int msec);
// stacks.c
-inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func);
+inline u32 stack_hop(u32 eax, u32 edx, void *func);
extern struct thread_info MainThread;
void thread_setup(void);
struct thread_info *getCurThread(void);
extern struct thread_info MainThread;
void thread_setup(void);
struct thread_info *getCurThread(void);