1;
2; Copyright (c) 1988 Regents of the University of California.
3; All rights reserved.
4;
5; Redistribution and use in source and binary forms are permitted
6; provided that this notice is preserved and that due credit is given
7; to the University of California at Berkeley. The name of the University
8; may not be used to endorse or promote products derived from this
9; software without specific prior written permission. This software
10; is provided ``as is'' without express or implied warranty.
11;
12;	@(#)spintasm.asm	3.2 (Berkeley) 03/28/88
13;
14; The code in this file complete the spint calls
15;
16
17spint	struc
18; union REGS
19spint_ax	dw	1
20spint_bx	dw	1
21spint_cx	dw	1
22spint_dx	dw	1
23spint_si	dw	1
24spint_di	dw	1
25spint_cflag	dw	1
26; struct SREGS
27spint_es	dw	1
28spint_cs	dw	1
29spint_ss	dw	1
30spint_ds	dw	1
31; int intno
32spint_intno	dw	1
33; int done
34spint_done	dw	1
35; int rc
36spint_rc	dw	1
37;
38spint	ends
39
40
41ENTER	MACRO
42	; Begin enter
43	push	bp
44	mov	bp,sp
45
46	push	ax
47	push	bx
48	push	cx
49	push	dx
50	push	bp
51	push	di
52	push	si
53	push	ds
54	push	es
55	pushf
56
57	mov	cs:start_sp, sp
58	mov	cs:start_ss, ss
59	; End enter
60	ENDM
61
62LEAVE	MACRO
63	; Begin leave
64	cli
65	mov	sp, cs:start_sp
66	mov	ss, cs:start_ss
67	sti
68
69	popf
70	pop	es
71	pop	ds
72	pop	si
73	pop	di
74	pop	bp
75	pop	dx
76	pop	cx
77	pop	bx
78	pop	ax
79
80	mov	sp,bp
81	pop	bp
82	ret
83	; End leave
84	ENDM
85
86GETREGS	MACRO	wherefrom
87	mov	si, wherefrom
88	mov	spint_segment, ds
89	mov	spint_offset, si
90
91	mov	ax, spint_ax[si]
92	mov	bx, spint_bx[si]
93	mov	cx, spint_cx[si]
94	mov	dx, spint_dx[si]
95	; XXX mov	si, spint_si[si]
96	mov	di, spint_di[si]
97	mov	es, spint_es[si]
98	; Now, need to do DS, SI
99	push	spint_ds[si]
100	mov	si, spint_si[si]
101	pop	ds
102	ENDM
103
104
105SETREGS	MACRO
106	mov	cs:old_si, si
107	mov	cs:old_ds, ds
108
109	mov	ds, cs:spint_segment
110	mov	si, cs:spint_offset
111
112	mov	spint_ax[si], ax
113	mov	spint_bx[si], bx
114	mov	spint_cx[si], cx
115	mov	spint_dx[si], dx
116
117	mov	spint_si[si], si
118	mov	spint_di[si], di
119
120	mov	spint_cs[si], cs
121	mov	spint_ds[si], ds
122	mov	spint_es[si], es
123	mov	spint_ss[si], ss
124	; now, need to do SI, DS
125	mov	ax, old_si
126	mov	spint_si[si], ax
127	mov	ax, old_ds
128	mov	spint_ds[si], ax
129	ENDM
130
131
132_TEXT	segment	byte public 'CODE'
133_TEXT	ends
134
135_DATA	segment	word public 'DATA'
136_DATA	ends
137
138CONST	segment	word public 'CONST'
139CONST	ends
140
141_BSS	segment word public 'BSS'
142_BSS	ends
143
144DGROUP	group	CONST, _BSS, _DATA
145
146	assume	cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP
147
148_TEXT	segment
149
150start_sp	dw	1 dup (?)	; For use in our 'longjmp'
151start_ss	dw	1 dup (?)	; For use in our 'longjmp'
152
153spint_segment	dw	1 dup (?)	; Segment of spawn control block
154spint_offset	dw	1 dup (?)	; Offset of spawn control block
155
156old_si		dw	1 dup (?)	; SI of interrupt issuer (temporary)
157old_ds		dw	1 dup (?)	; DS of interrupt issuer (temporary)
158
159issuer_ss	dw	1 dup (?)	; ss of person who called us (permanent)
160issuer_sp	dw	1 dup (?)	; sp of person who called us (permanent)
161
162int21_stack	db	100 dup (?)	; Stack for int21.
163
164;
165; _spint_int gets control on an interrupt.  It switches the stack
166; and does a 'return' from _spint_start.
167;
168	public	__spint_int
169
170__spint_int	proc	near
171	mov	cs:issuer_sp, sp
172	mov	cs:issuer_ss, ss
173	sti
174
175	SETREGS
176
177	LEAVE
178__spint_int	endp
179
180;
181; _spint_start issues the dos interrupt after setting up the passed
182; registers.  When control returns to it, it sets spint->done to non-zero.
183;
184	public	__spint_start
185
186__spint_start	proc	near
187	ENTER
188
189	GETREGS	4[bp]
190
191	; Now, switch to a different (short) stack.  This is so
192	; that our games won't mess up the stack int 21 (hardware and,
193	; possibly, software) stores things on.
194
195	cli
196	mov	cs:int21_stack, cs
197	mov	ss, cs:int21_stack
198	mov	sp, offset int21_stack
199	add	sp, (length int21_stack) - 4
200	sti
201
202	int	21H		; Issue DOS interrupt
203
204	SETREGS
205
206	mov	ds, cs:spint_segment
207	mov	si, cs:spint_offset
208	mov	spint_done[si], 1	; We are done
209
210	LEAVE
211__spint_start	endp
212
213;
214; After _spint_int has faked a return from start_spawn, we come here to
215; return to the interrupt issuer.
216;
217	public	__spint_continue
218
219__spint_continue	proc	near
220	ENTER
221
222	GETREGS	4[bp]
223
224	mov	sp, cs:issuer_sp		; Restore SP
225	mov	ss, cs:issuer_ss		; Restore SS
226
227	iret
228__spint_continue	endp
229
230_TEXT	ends
231
232	end
233