[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