summaryrefslogtreecommitdiff
path: root/doselks/coroutine.c
blob: fa72becf13eca44c665aca8634aa1b664c6d23fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

#include "doselks.h"

int in_process = 0;
int intr_pending = 0;
unsigned int current_ds, current_stack;
struct process * proc;

/***************************************************************************
 * These two routines to make doselks and the user program into co-routines.
 *
 * The Server calls run_cpu which runs the client.
 * The client then does an int $80 which calls elks_int.
 * Elks_int then returns to the caller of run_cpu.
 *
 * The return value is the value of AX when the int $80 occured.
 * On return ES is set to the DS of the client program.
 *
 * The instruction times are for the 286
 *
 * If we were using a 486 then using mov's would be faster on the 286 they
 * are the same speed but push/pop is smaller.
 */

#asm
  .data
bx_temp:	! Tempoary storage for BX.
  .word	0
  .text		! The is where we store the current_ds in the _TEXT_ segment
cs_current_ds: 	! for the elks_int routine
  .word	0
#endasm

unsigned int run_cpu()
{
#asm
  mov	ax,ds								; 2
  seg	cs			! Store ds for return
  mov	[cs_current_ds],ax						; 5

  cli				! We`re messing!			; 3
  test	[_intr_pending],#$FFFF	! Last chance ...
  jz	skp
  sti
  xor	ax,ax
  ret
skp:
  push	bp								; 3
  push	si								; 3
  push	di								; 3
  mov	[_current_stack],sp						; 5
  mov	ax,#1								; 2
  mov	[_in_process],ax						; 5
  mov	sp,[_proc]							; 5
  pop	ax			! pppop					; 5
  pop	[bx_temp]							; 5
  pop	cx								; 5
  pop	dx								; 5
  pop	di								; 5
  pop	si								; 5
  pop	bp								; 5
  pop	es								; 5
  mov	bx,sp			! Switch to client stack		; 2
  mov	ss,[bx+8]		! SS					; 5
  mov	sp,[bx+10]		! SP					; 5
  push	[bx+6]			! flags					; 5
  push	[bx+4]			! CS					; 5
  push	[bx+2]			! PC					; 5
  push	[bx+0]			! DS					; 5
  mov	bx,[bx_temp]							; 5
  pop	ds								; 5
  iret									; 17
#endasm
}

unsigned int elks_int()
{
#asm
.text
  cli									; 3
  push	ds								; 3
  push	cs								; 3
  pop	ds								; 5
  mov	ds,[cs_current_ds]						; 5
  mov	[bx_temp],bx							; 3
  mov	bx,[_proc]							; 5
  add	bx,#16								; 2
  pop	[bx+0]			! DS					; 5
  pop	[bx+2]			! PC					; 5
  pop	[bx+4]			! CS					; 5
  pop	[bx+6]			! flags					; 5
  mov	[bx+8],ss		! SS					; 3
  mov	[bx+10],sp		! SP					; 3

  mov	sp,bx			! Ready for pppppush			; 2
  mov	bx,ds								; 2
  mov	ss,bx								; 2

  push	es			! wheeee				; 3
  push	bp								; 3
  push	si								; 3
  push	di								; 3
  push	dx								; 3
  push	cx								; 3
  push	[bx_temp]							; 5
  push	ax			! This is the return value, handy	; 3

  mov	sp,[_current_stack]						; 5
  mov	bx,#1								; 2
  mov	[_in_process],bx						; 5
  sti				! Finished F**** around with the stack	; 2

  mov	bx,[_proc]							; 5
  mov	es,[bx+16]		! Set ES to the client`s DS		; 5
  pop	di								; 5
  pop	si								; 5
  pop	bp								; 5
#endasm
}