diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/apmjump.s | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/pc/apmjump.s')
| -rw-r--r-- | os/pc/apmjump.s | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/os/pc/apmjump.s b/os/pc/apmjump.s new file mode 100644 index 00000000..6dbd19d0 --- /dev/null +++ b/os/pc/apmjump.s @@ -0,0 +1,98 @@ +/* + * 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 +#define RETF BYTE $0xCB + +GLOBL apmjumpstruct+0(SB), $8 + +TEXT fortytwo(SB), $0 + MOVL $42, AX + RETF + +TEXT getcs(SB), $0 + PUSHL CS + POPL AX + RET + +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 + */ + + PUSHL $APMDSEG + POPL DS + + /* + * 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 |
