Force use of indirect function calls in inline assembler.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 21 Mar 2010 00:41:38 +0000 (20:41 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 21 Mar 2010 00:41:38 +0000 (20:41 -0400)
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.

src/block.c
src/stacks.c
src/util.h

index d485c41e7395e9934ccab926884d1b5c1a1fda4a..ddf441f9a570c588a2e53a261f2e68b6858fca4c 100644 (file)
@@ -324,7 +324,7 @@ send_disk_op(struct disk_op_s *op)
     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);
 }
 
 
index 4a30b3d82ebb43471c5546b972430718d6880bfa..570948a4982a27063952ff22fe93cf0b22eca258 100644 (file)
@@ -40,7 +40,6 @@ call32(void *func)
     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
@@ -54,7 +53,7 @@ call32(void *func)
         "  pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n"
         "  jmp transition32\n"
         "  .code32\n"
-        "1:calll %2\n"
+        "1:calll *%2\n"
         "  pushl $2f\n"
         "  jmp transition16big\n"
 
@@ -64,7 +63,7 @@ call32(void *func)
         "  movl %0, %%ss\n"
         "  movl %1, %%esp\n"
         : "=&r" (bkup_ss), "=&r" (bkup_esp)
-        : "m" (*(u8*)func)
+        : "r" (func)
         : "eax", "ecx", "edx", "cc", "memory");
 
     // Restore gdt and fs/gs
@@ -85,7 +84,7 @@ call32(void *func)
 
 // 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;
@@ -99,13 +98,13 @@ stack_hop(u32 eax, u32 edx, u32 ecx, void *func)
         "movw %w6, %%ss\n"
         "movl %5, %%esp\n"
         // Call func
-        "calll %7\n"
+        "calll *%2\n"
         // 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;
 }
index d2ac08a5917e1d6fe36eabaea3bde9e9a3b627a6..e47860f953561d3903c621a8922dc5a9176a0839 100644 (file)
@@ -204,7 +204,7 @@ void biosusleep(u32 usec);
 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);