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@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