On Thu, Apr 9, 2015 at 6:54 PM, Kevin O'Connor <[email protected]> wrote: > On Thu, Apr 09, 2015 at 09:56:07AM -0400, Kevin O'Connor wrote: >> On Wed, Apr 08, 2015 at 10:32:23PM -0400, Kevin O'Connor wrote: >> > The problem is not with leal in hand written assembler - the problem >> > is with leal instructions generated by gcc. To see the assembler gcc >> > produces for the vgabios one can look at out/vgaccode16.raw.s . Or, >> > alternatively, one can run: >> > objdump -m i386 -M i8086 -M suffix -ldr out/vgarom.o >> > >> > We've fixed up gcc assembler in the past (see scripts/vgafixup.py) to >> > work around x86emu. However, the leal instruction seems painful to >> > patch out - particularly so when %esp is one of the registers read or >> > written in the leal instruction. If anyone wants to take a stab >> > at a workaround, feel free to submit a patch. >> >> It occurred to me that it might be possible to replace the leal >> instruction with a function call. The generic form of leal is: >> >> leal $offset(%base, %index, $scale), %destination >> >> which does: >> >> %destination = $offset + %base + (%index * $scale) >> >> if the above is found in the gcc assembler it could be replaced with >> something like: >> >> pushl %base >> pushl %index >> pushl $offset >> pushl $scale >> callw fake_leal >> popl %destination >> >> (The fake_leal assembler function that performs the actual calculation >> would also need to be written.) The above wouldn't work if %index is >> %esp, but I don't think that would happen in practice. >> >> I'm not going to tackle the above right now, but maybe someone else is >> interested in attempting it. A word of caution though - I know leal >> doesn't work in very old x86emu versions, but it's unclear if any >> other gcc produced instructions are also broken. The leal instruction >> might just be one of many instructions that don't work. > > I gave it a shot anyway - seabios patch is below. > > It's incredibly ugly. But, it does allow FC11 and FC12 to boot into > graphics which wasn't possible before. Also, I don't see any > indication in the x86emu commit logs ( > http://anongit.freedesktop.org/git/xorg/xserver.git ) that any other > instructions besides leal will present a problem. > > -Kevin > > > commit c900162603f19552ec8ad3648bbb71f2effc227d > Author: Kevin O'Connor <[email protected]> > Date: Thu Apr 9 11:59:41 2015 -0400 > > vgabios: Hack for leal emulation > > Signed-off-by: Kevin O'Connor <[email protected]> > > diff --git a/scripts/vgafixup.py b/scripts/vgafixup.py > index a981bbf..f32c055 100644 > --- a/scripts/vgafixup.py > +++ b/scripts/vgafixup.py > @@ -8,19 +8,26 @@ > # 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 > -# triggering the x86emu bugs. > +# that are known to be generated by gcc to avoid triggering the x86emu > +# bugs. It also translates "leal" instructions into a function call > +# that emulates it at runtime. > > # It is also known that the Windows vgabios emulator has issues with > # addressing negative offsets to the %esp register. That has been > # worked around by not using the gcc parameter "-fomit-frame-pointer" > # when compiling. > > -import sys > +import sys, re > > def main(): > infilename, outfilename = sys.argv[1:] > infile = open(infilename, 'r') > + re_leal = re.compile( > + r'^(?P<offset>[^(]*)\(' > + r'(?P<base>[^,)]*)' > + r'(?:,(?P<index>[^,)]*))?' > + r'(?:,(?P<scale>[^,)]*))?\)' > + r', (?P<dest>.*)$') > out = [] > for line in infile: > sline = line.strip() > @@ -30,6 +37,25 @@ 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'): > + 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] > + out.append('pushl %s ; pushl %s ; pushl $%s ; pushw $%d' > + ' ; callw fake_leal ; popl %s\n' % ( > + base, index, offset, scale, dest)) > else: > out.append(line) > infile.close() > diff --git a/vgasrc/vgaentry.S b/vgasrc/vgaentry.S > index e0ab954..21128c5 100644 > --- a/vgasrc/vgaentry.S > +++ b/vgasrc/vgaentry.S > @@ -45,31 +45,32 @@ _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 fake_leal > + .global fake_leal > +fake_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 > - // 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 > callw \cfunc > .endm
I can report that this patch also works for FreeBSD 8.2's VESA console. There seems to be some unrelated problem when running 1.8-stable so I applied it to rel-1.7.5.2 _______________________________________________ SeaBIOS mailing list [email protected] http://www.seabios.org/mailman/listinfo/seabios
