[SeaBIOS] [PATCH 2/3] vgabios: Emulate "leal" instruction

Kevin O'Connor kevin at koconnor.net
Fri Apr 10 17:07:13 CEST 2015


Emulate the "leal" instruction so that the vgabios can run on older
versions of x86emu.  (This removes the previous "leal" trap.)

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 scripts/vgafixup.py | 36 +++++++++++++++++++++++++++++++++---
 vgasrc/vgaentry.S   | 45 +++++++++++++++++++++++----------------------
 2 files changed, 56 insertions(+), 25 deletions(-)

diff --git a/scripts/vgafixup.py b/scripts/vgafixup.py
index a981bbf..e144382 100644
--- a/scripts/vgafixup.py
+++ b/scripts/vgafixup.py
@@ -7,8 +7,8 @@
 
 # The x86emu code widely used in Linux distributions when running Xorg
 # in vesamode is known to have issues with "retl", "leavel", "entryl",
-# and some variants of "calll".  This code modifies those instructions
-# (ret and leave) that are known to be generated by gcc to avoid
+# "leal", and some variants of "calll".  This code modifies those
+# instructions that are known to be generated by gcc to avoid
 # triggering the x86emu bugs.
 
 # It is also known that the Windows vgabios emulator has issues with
@@ -16,7 +16,35 @@
 # worked around by not using the gcc parameter "-fomit-frame-pointer"
 # when compiling.
 
-import sys
+import sys, re
+
+# leal parameter regex - example string: -3(%edx,%eax,8), %eax
+re_leal = re.compile(
+    r'^\s*(?P<offset>[^(]*?)\s*'
+    r'\(\s*(?P<base>[^,)]*?)\s*(?:,\s*(?P<index>[^,)]*?)\s*)?'
+    r'(?:,\s*(?P<scale>[^,)]*?)\s*)?\)\s*'
+    r',\s*(?P<dest>.*?)\s*$')
+
+# Find an alternate set of instructions for a given "leal" instruction
+def handle_leal(sline):
+    m = re_leal.match(sline[5:])
+    if m is None or m.group('index') == '%esp':
+        print("Invalid leal instruction: %s" % (sline,))
+        sys.exit(-1)
+    offset, base, index, scale, dest = m.group(
+        'offset', 'base', 'index', 'scale', 'dest')
+    if not offset:
+        offset = '0'
+    if not base:
+        base = '$0'
+    if not index:
+        index = '$0'
+    if not scale:
+        scale = '1'
+    scale = {'1': 0, '2': 1, '4': 2, '8': 3}[scale]
+    return ('pushl %s ; pushl %s ; pushl $%s ; pushw $%d'
+            ' ; callw emulate_leal ; popl %s\n' % (
+                base, index, offset, scale, dest))
 
 def main():
     infilename, outfilename = sys.argv[1:]
@@ -30,6 +58,8 @@ def main():
             out.append('movl %ebp, %esp ; popl %ebp\n')
         elif sline.startswith('call'):
             out.append('pushw %ax ; callw' + sline[4:] + '\n')
+        elif sline.startswith('leal'):
+            out.append(handle_leal(sline))
         else:
             out.append(line)
     infile.close()
diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S
index 7ca550d..8b84f36 100644
--- a/vgasrc/vgaentry.S
+++ b/vgasrc/vgaentry.S
@@ -45,33 +45,34 @@ _rom_header_signature:
  * Entry points
  ****************************************************************/
 
-        // Force a fault if found to be running on broken x86emu versions.
-        DECLFUNC x86emu_fault
-msg:    .ascii "SeaVGABIOS: x86emu leal trap!\n"
-x86emu_fault:
-#if CONFIG_DEBUG_IO
-        movw %cs:DebugOutputPort, %dx
-        movw $msg, %si
-1:      movb %cs:(%si), %al
-        outb %al, (%dx)
-        incw %si
-        cmpw $x86emu_fault, %si
-        jl 1b
-#endif
-1:      hlt
-        jmp 1b
+        // Emulate a leal instruction (see scripts/vgafixup.py)
+        // On entry stack contains: base, index, offset, scale
+        DECLFUNC emulate_leal
+        .global emulate_leal
+emulate_leal:
+        pushl %ebp
+        movl %esp, %ebp
+        pushfl
+        pushl %eax
+        pushl %ecx
+
+        movb 6(%ebp), %cl
+        movl 12(%ebp), %eax
+        shll %cl, %eax
+        addl 8(%ebp), %eax
+        addl %eax, 16(%ebp)
+
+        popl %ecx
+        popl %eax
+        popfl
+        popl %ebp
+        retw $10
 
         // This macro implements a call while avoiding instructions
         // that old versions of x86emu have problems with.
         .macro VGA_CALLL cfunc
 #if CONFIG_VGA_FIXUP_ASM
-        // Make sure leal instruction works.
-        movl $0x8000, %ecx
-        leal (%ecx, %ecx, 1), %ecx
-        cmpl $0x10000, %ecx
-        jne x86emu_fault
-        // Use callw instead of calll
-        push %ax
+        pushw %ax
         callw \cfunc
 #else
         calll \cfunc
-- 
1.9.3




More information about the SeaBIOS mailing list