aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2015-04-09 17:20:16 -0400
committerKevin O'Connor <kevin@koconnor.net>2015-04-11 14:36:59 -0400
commit0b2165d191f51ed2a522142c3ed3db55bc852627 (patch)
tree093520f9874c86a6c6d7ee39d568848dfc72f3fb /scripts
parent799b20b0db45891845e2d820368a66af538d5664 (diff)
downloadseabios-hppa-0b2165d191f51ed2a522142c3ed3db55bc852627.zip
seabios-hppa-0b2165d191f51ed2a522142c3ed3db55bc852627.tar.gz
seabios-hppa-0b2165d191f51ed2a522142c3ed3db55bc852627.tar.bz2
vgabios: Emulate "leal" instruction
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>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/vgafixup.py61
1 files changed, 58 insertions, 3 deletions
diff --git a/scripts/vgafixup.py b/scripts/vgafixup.py
index a981bbf..2053cd5 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,59 @@
# 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("Unable to fixup leal instruction: %s" % (sline,))
+ sys.exit(-1)
+ offset, base, index, scale, dest = m.group(
+ 'offset', 'base', 'index', 'scale', 'dest')
+ if dest == '%esp':
+ # If destination is %esp then just use 16bit leaw instead
+ return 'leaw %s\n' % (sline[5:].replace('%e', '%'),)
+ if not scale:
+ scale = '1'
+ scale = {1: 0, 2: 1, 4: 2, 8: 3}[int(scale, 0)]
+ # Try to rearrange arguments to simplify 'base' (to improve code gen)
+ if not scale and base == index:
+ base, index, scale = '', index, 1
+ elif not index or (not scale and base in (dest, '%esp') and index != dest):
+ base, index, scale = index, base, 0
+ # Produce instructions to calculate "leal"
+ insns = ['pushfw']
+ if base != dest:
+ # Calculate "leal" directly in dest register
+ if index != dest:
+ insns.insert(0, 'movl %s, %s' % (index, dest))
+ if scale:
+ insns.append('shll $%d, %s' % (scale, dest))
+ if base:
+ if base == '%esp':
+ offset += '+2'
+ insns.append('addl %s, %s' % (base, dest))
+ elif base == index:
+ # Use "imull" method
+ insns.append('imull $%d, %s' % ((1<<scale)+1, dest))
+ else:
+ # Backup/restore index register and do scaling in index register
+ insns.append('pushl %s' % (index,))
+ insns.append('shll $%d, %s' % (scale, index))
+ insns.append('addl %s, %s' % (index, dest))
+ insns.append('popl %s' % (index,))
+ if offset and offset != '0':
+ insns.append('addl $%s, %s' % (offset, dest))
+ insns.append('popfw\n')
+ return ' ; '.join(insns)
def main():
infilename, outfilename = sys.argv[1:]
@@ -30,6 +82,9 @@ 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))
+ #print("-> %s\n %s" % (sline, out[-1].strip()))
else:
out.append(line)
infile.close()