[SeaBIOS] [PATCH 09/12] Move call16() functions from romlayout.S to inline assembler in stacks.c

Kevin O'Connor kevin at koconnor.net
Tue Sep 30 20:38:43 CEST 2014


Use inline assembler in call16 type functions instead of using
__call16() in romlayout.S.

Since call16() and call16big() are now only called with %ss==0 they do
not need to update the stack pointer.  Only call16_sloppy() requires
the stack manipulation code.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/romlayout.S | 42 ------------------------------
 src/stacks.c    | 81 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 69 insertions(+), 54 deletions(-)

diff --git a/src/romlayout.S b/src/romlayout.S
index 028d1e8..0651112 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -129,48 +129,6 @@ transition16big:
         movl %ecx, %eax
         jmpl *%edx
 
-// Call a 16bit SeaBIOS function from SeaBIOS 32bit C code.
-// %ecx = calling function
-// Clobbers: %ecx, %edx, flags, segment registers, idt/gdt
-        DECLFUNC __call16
-        .global __call16big
-        .code32
-__call16:
-        pushl %edx
-        pushl %ecx
-        movl $1f, %edx
-        jmp transition16
-__call16big:
-        pushl %edx
-        pushl %ecx
-        movl $1f, %edx
-        jmp transition16big
-
-        // Make call.
-        .code16
-1:      movl $_zonelow_seg, %edx        // Adjust %ds, %ss, and %esp
-        movl %edx, %ds
-        movzwl StackSeg, %edx
-        movl %edx, %ecx
-        shll $4, %ecx
-        movl %edx, %ss
-        subl %ecx, %esp
-        movl %edx, %ds
-
-        popl %ecx                       // Call function
-        popl %edx
-        calll *%ecx
-
-        movl %ss, %edx                  // Readjust %esp
-        shll $4, %edx
-        addl %edx, %esp
-
-        // Return via transition32
-        movl $(2f + BUILD_BIOS_ADDR), %edx
-        jmp transition32
-        .code32
-2:      retl
-
 
 /****************************************************************
  * External calling trampolines
diff --git a/src/stacks.c b/src/stacks.c
index 9c0001c..82d1c5c 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -1,6 +1,6 @@
 // Code for manipulating stack locations.
 //
-// Copyright (C) 2009-2010  Kevin O'Connor <kevin at koconnor.net>
+// Copyright (C) 2009-2014  Kevin O'Connor <kevin at koconnor.net>
 //
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
@@ -89,35 +89,92 @@ call32(void *func, u32 eax, u32 errret)
 }
 
 // Call a 16bit SeaBIOS function from a 32bit SeaBIOS function.
-static inline u32
+u32 FUNCFSEG
 call16(u32 eax, u32 edx, void *func)
 {
     ASSERT32FLAT();
-    if (getesp() > MAIN_STACK_MAX)
+    if (getesp() > BUILD_STACK_ADDR)
         panic("call16 with invalid stack\n");
-    extern u32 __call16(u32 eax, u32 edx, void *func);
-    return __call16(eax, edx, func - BUILD_BIOS_ADDR);
+    func -= BUILD_BIOS_ADDR;
+    asm volatile(
+        // Transition to 16bit mode
+        "  movl $(1f - " __stringify(BUILD_BIOS_ADDR) "), %%edx\n"
+        "  jmp transition16\n"
+        // Call func
+        "  .code16\n"
+        "1:movl %2, %%edx\n"
+        "  calll *%1\n"
+        // Return to 32bit
+        "  movl $2f, %%edx\n"
+        "  jmp transition32\n"
+        "  .code32\n"
+        "2:\n"
+        : "+a" (eax)
+        : "r" (func), "r" (edx)
+        : "edx", "ecx", "cc", "memory");
+    return eax;
 }
 
 // Call a 16bit SeaBIOS function in "big real" mode.
-static inline u32
+u32 FUNCFSEG
 call16big(u32 eax, u32 edx, void *func)
 {
     ASSERT32FLAT();
-    if (getesp() > MAIN_STACK_MAX)
+    if (getesp() > BUILD_STACK_ADDR)
         panic("call16big with invalid stack\n");
-    extern u32 __call16big(u32 eax, u32 edx, void *func);
-    return __call16big(eax, edx, func - BUILD_BIOS_ADDR);
+    func -= BUILD_BIOS_ADDR;
+    asm volatile(
+        // Transition to 16bit mode
+        "  movl $(1f - " __stringify(BUILD_BIOS_ADDR) "), %%edx\n"
+        "  jmp transition16big\n"
+        // Call func
+        "  .code16\n"
+        "1:movl %2, %%edx\n"
+        "  calll *%1\n"
+        // Return to 32bit
+        "  movl $2f, %%edx\n"
+        "  jmp transition32\n"
+        "  .code32\n"
+        "2:\n"
+        : "+a" (eax)
+        : "r" (func), "r" (edx)
+        : "edx", "ecx", "cc", "memory");
+    return eax;
 }
 
 // Jump back to 16bit mode while in 32bit mode from call32()
-static u32
+u32 FUNCFSEG
 call16_sloppy(u32 eax, u32 edx, void *func)
 {
+    ASSERT32FLAT();
+    if (getesp() > MAIN_STACK_MAX)
+        panic("call16_sloppy with invalid stack\n");
+    func -= BUILD_BIOS_ADDR;
     Call32Method = 0;
-    u32 ret = call16big(eax, edx, func);
+    u32 stackseg = GET_LOW(StackSeg);
+    asm volatile(
+        // Transition to 16bit mode
+        "  movl $(1f - " __stringify(BUILD_BIOS_ADDR) "), %%edx\n"
+        "  jmp transition16big\n"
+        // Setup ss/esp and call func
+        "  .code16\n"
+        "1:movl %3, %%ecx\n"
+        "  shll $4, %3\n"
+        "  movw %%cx, %%ss\n"
+        "  subl %3, %%esp\n"
+        "  movw %%cx, %%ds\n"
+        "  movl %2, %%edx\n"
+        "  calll *%1\n"
+        // Return to 32bit and restore esp
+        "  movl $2f, %%edx\n"
+        "  jmp transition32\n"
+        "  .code32\n"
+        "2:addl %3, %%esp\n"
+        : "+a" (eax)
+        : "r" (func), "r" (edx), "r" (stackseg)
+        : "edx", "ecx", "cc", "memory");
     Call32Method = C32_SLOPPY;
-    return ret;
+    return eax;
 }
 
 // Call a 16bit SeaBIOS function, restoring the mode from last call32().
-- 
1.9.3




More information about the SeaBIOS mailing list