15c7d856bc
we loaded APMDSEG instead of APMDSEL into DS. (ouch!) its not really clear why we loaded DS (wong) in the first place as bios is supposed to do this. for the machines where this worked it could have no effect anyway because it was wrong so removing the DS load and just zero all segment registers.
86 lines
1.4 KiB
ArmAsm
86 lines
1.4 KiB
ArmAsm
/*
|
|
* Far call, absolute indirect.
|
|
* The argument is the offset.
|
|
* We use a global structure for the jump params,
|
|
* so this is *not* reentrant or thread safe.
|
|
*/
|
|
|
|
#include "mem.h"
|
|
|
|
#define SSOVERRIDE BYTE $0x36
|
|
#define CSOVERRIDE BYTE $0x2E
|
|
|
|
GLOBL apmjumpstruct+0(SB), $8
|
|
|
|
TEXT apmfarcall(SB), $0
|
|
/*
|
|
* We call push and pop ourselves.
|
|
* As soon as we do the first push or pop,
|
|
* we can't use FP anymore.
|
|
*/
|
|
MOVL off+4(FP), BX
|
|
MOVL seg+0(FP), CX
|
|
MOVL BX, apmjumpstruct+0(SB)
|
|
MOVL CX, apmjumpstruct+4(SB)
|
|
|
|
/* load necessary registers from Ureg */
|
|
MOVL ureg+8(FP), DI
|
|
MOVL 28(DI), AX
|
|
MOVL 16(DI), BX
|
|
MOVL 24(DI), CX
|
|
MOVL 20(DI), DX
|
|
|
|
/* save registers, segments */
|
|
PUSHL DS
|
|
PUSHL ES
|
|
PUSHL FS
|
|
PUSHL GS
|
|
PUSHL BP
|
|
PUSHL DI
|
|
|
|
/*
|
|
* paranoia: zero the segments, since it's the
|
|
* BIOS's responsibility to initialize them.
|
|
* (trick picked up from Linux driver).
|
|
*/
|
|
PUSHL DX
|
|
XORL DX, DX
|
|
PUSHL DX
|
|
POPL DS
|
|
PUSHL DX
|
|
POPL ES
|
|
PUSHL DX
|
|
POPL FS
|
|
PUSHL DX
|
|
POPL GS
|
|
POPL DX
|
|
|
|
/*
|
|
* The actual call.
|
|
*/
|
|
CSOVERRIDE; BYTE $0xFF; BYTE $0x1D
|
|
LONG $apmjumpstruct+0(SB)
|
|
|
|
/* restore segments, registers */
|
|
POPL DI
|
|
POPL BP
|
|
POPL GS
|
|
POPL FS
|
|
POPL ES
|
|
POPL DS
|
|
|
|
PUSHFL
|
|
POPL 64(DI)
|
|
|
|
/* store interesting registers back in Ureg */
|
|
MOVL AX, 28(DI)
|
|
MOVL BX, 16(DI)
|
|
MOVL CX, 24(DI)
|
|
MOVL DX, 20(DI)
|
|
MOVL SI, 4(DI)
|
|
|
|
PUSHFL
|
|
POPL AX
|
|
ANDL $1, AX /* carry flag */
|
|
RET
|