summaryrefslogtreecommitdiff
path: root/os/pc/apmjump.s
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/apmjump.s
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/pc/apmjump.s')
-rw-r--r--os/pc/apmjump.s98
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