1/* 2 * Far call, absolute indirect. 3 * The argument is the offset. 4 * We use a global structure for the jump params, 5 * so this is *not* reentrant or thread safe. 6 */ 7 8#include "mem.h" 9 10#define SSOVERRIDE BYTE $0x36 11#define CSOVERRIDE BYTE $0x2E 12#define RETF BYTE $0xCB 13 14GLOBL apmjumpstruct+0(SB), $8 15 16TEXT fortytwo(SB), $0 17 MOVL $42, AX 18 RETF 19 20TEXT getcs(SB), $0 21 PUSHL CS 22 POPL AX 23 RET 24 25TEXT apmfarcall(SB), $0 26 /* 27 * We call push and pop ourselves. 28 * As soon as we do the first push or pop, 29 * we can't use FP anymore. 30 */ 31 MOVL off+4(FP), BX 32 MOVL seg+0(FP), CX 33 MOVL BX, apmjumpstruct+0(SB) 34 MOVL CX, apmjumpstruct+4(SB) 35 36 /* load necessary registers from Ureg */ 37 MOVL ureg+8(FP), DI 38 MOVL 28(DI), AX 39 MOVL 16(DI), BX 40 MOVL 24(DI), CX 41 MOVL 20(DI), DX 42 43 /* save registers, segments */ 44 PUSHL DS 45 PUSHL ES 46 PUSHL FS 47 PUSHL GS 48 PUSHL BP 49 PUSHL DI 50 51 /* 52 * paranoia: zero the segments, since it's the 53 * BIOS's responsibility to initialize them. 54 * (trick picked up from Linux driver). 55 PUSHL DX 56 XORL DX, DX 57 PUSHL DX 58 POPL DS 59 PUSHL DX 60 POPL ES 61 PUSHL DX 62 POPL FS 63 PUSHL DX 64 POPL GS 65 POPL DX 66 */ 67 68 PUSHL $APMDSEG 69 POPL DS 70 71 /* 72 * The actual call. 73 */ 74 CSOVERRIDE; BYTE $0xFF; BYTE $0x1D 75 LONG $apmjumpstruct+0(SB) 76 77 /* restore segments, registers */ 78 POPL DI 79 POPL BP 80 POPL GS 81 POPL FS 82 POPL ES 83 POPL DS 84 85 PUSHFL 86 POPL 64(DI) 87 88 /* store interesting registers back in Ureg */ 89 MOVL AX, 28(DI) 90 MOVL BX, 16(DI) 91 MOVL CX, 24(DI) 92 MOVL DX, 20(DI) 93 MOVL SI, 4(DI) 94 95 PUSHFL 96 POPL AX 97 ANDL $1, AX /* carry flag */ 98 RET 99