xref: /plan9/sys/src/9/pc/apmjump.s (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
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