ref: f9096fcdfd46f5bf566e87107675bfd439771a44
dir: /sys/src/9/pc/apmjump.s/
/* * 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