1 | ******************************************************************************
|
---|
2 | *
|
---|
3 | * diamelst.s -- startup code for the C runtime library, aesbind, vdibind
|
---|
4 | * Version 3 -- 1988-05-03 -- D.N. Lynx Crowe
|
---|
5 | *
|
---|
6 | * "It's not a diamond, it's a Diamel!", and this isn't Gem, either...
|
---|
7 | * it just looks a lot like it.
|
---|
8 | *
|
---|
9 | * Adds __cmdsz and __cmdln for access to raw command tail
|
---|
10 | *
|
---|
11 | * IMPORTANT: SEE THE DESCRIPTION OF THE "STACK" VARIABLE, BELOW.
|
---|
12 | *
|
---|
13 | * This is the startup code for any application running on the Atari ST.
|
---|
14 | * This includes gemlib, vdi, and the aes bindings.
|
---|
15 | *
|
---|
16 | * Look carefully at the comments below; they will determine the nature
|
---|
17 | * of this startup code (stack size, AES & VDI usage, etc.).
|
---|
18 | *
|
---|
19 | * This must be the first object file in a LINK command. When the
|
---|
20 | * operating system gives it control, our process has ALL of memory
|
---|
21 | * allocated to it, and our stack pointer is at the top.
|
---|
22 | * This code (conditionally) gives some of that memory back
|
---|
23 | * to the operating system, places its stack pointer at the top
|
---|
24 | * of the memory it still owns, sets up some global variables,
|
---|
25 | * and calls __main, the run-time library startup routine (which
|
---|
26 | * parses the command line into argc/argv, opens stdin and stdout,
|
---|
27 | * etc., before calling the programmer's _main).
|
---|
28 | *
|
---|
29 | * This object file also includes __exit, which is the procedure the
|
---|
30 | * runtime library calls to exit back to the operating system.
|
---|
31 | * As a new feature with this release, the argument passed to __exit
|
---|
32 | * is NOT ignored; it is passed to the operating system using the Pterm
|
---|
33 | * function call, which returns it as the value of the Pexec() call
|
---|
34 | * which invoked this process.
|
---|
35 | *
|
---|
36 | ******************************************************************************
|
---|
37 |
|
---|
38 | STACK=4 * CHANGE THIS VARIABLE TO CHOOSE A MEMORY MODEL
|
---|
39 |
|
---|
40 | MINSTACK=4096 * minimum stack+heap size. (used if __STKSIZ undefined)
|
---|
41 |
|
---|
42 | * NOTE: STACK was =-8192
|
---|
43 |
|
---|
44 | ******************************************************************************
|
---|
45 | *
|
---|
46 | * STACK variable summary:
|
---|
47 | *
|
---|
48 | * -1=keep all available memory
|
---|
49 | * 0=keep MINSTACK bytes
|
---|
50 | * 1=keep 1/4 of free memory
|
---|
51 | * 2=keep 2/4
|
---|
52 | * 3=keep 3/4
|
---|
53 | * 4=use _STKSIZ: keep (if >0) or give up (if <0) _STKSIZ bytes.
|
---|
54 | * other=keep that many bytes (positive) or give back that many (negative)
|
---|
55 | *
|
---|
56 | ******************************************************************************
|
---|
57 | *
|
---|
58 | * CONFIGURING THIS STARTUP FILE
|
---|
59 | *
|
---|
60 | * There are several memory models which this startup file will
|
---|
61 | * assemble for, selected by the assembly variable STACK.
|
---|
62 | *
|
---|
63 | * When your process gets control, it owns its basepage, its text
|
---|
64 | * (program) segment, its data segment, its bss segment (uninitialized
|
---|
65 | * data), and all the "free memory" from there to the top of the TPA.
|
---|
66 | * A process can choose to keep all that free memory for its stack
|
---|
67 | * (used by function calls and local variables) and heap (used by
|
---|
68 | * malloc()), or it can return some or all of that space to the
|
---|
69 | * operating system.
|
---|
70 | *
|
---|
71 | * The memory between the top of your bss segment and your stack pointer
|
---|
72 | * is used both for a heap and for the stack. The line between heap
|
---|
73 | * and stack is called the "break". When malloc() uses up all the
|
---|
74 | * memory below the break, it calls _brk() (in this file) to move the
|
---|
75 | * break up. If the break gets too close to the stack, _brk() returns
|
---|
76 | * an error code, and malloc() will return NULL because it couldn't
|
---|
77 | * satisfy the request. If the stack actually overflows the break,
|
---|
78 | * _brk() prints an error message and exits, returning 1 to its parent.
|
---|
79 | *
|
---|
80 | * If you are using the AES or VDI, you must return at least a little of
|
---|
81 | * the free memory to the operating system, because they need it.
|
---|
82 | * About 8K should be enough. The AES uses this memory for blt buffers,
|
---|
83 | * and the VDI uses it for virtual workstation data.
|
---|
84 | * Also, if your program uses the Pexec() call, you will need to return
|
---|
85 | * some space to make room for the child process.
|
---|
86 | *
|
---|
87 | * It is usually a good idea to keep only as much memory as you will
|
---|
88 | * use, because some programs depend on processes returning some
|
---|
89 | * memory to the operating system.
|
---|
90 | *
|
---|
91 | *************************************************************************
|
---|
92 | *
|
---|
93 | * Here are the memory models you can set up with the STACK variable:
|
---|
94 | *
|
---|
95 | * STACK
|
---|
96 | * value Meaning
|
---|
97 | * ------ ---------------------------------------------------------
|
---|
98 | * -1 Keep all the memory for this process. Return NONE of it
|
---|
99 | * to the operating system. This model gives you the most
|
---|
100 | * memory.
|
---|
101 | *
|
---|
102 | * WARNING: IF YOU REQUEST ALL OF MEMORY (with STACK = -1),
|
---|
103 | * YOU MUST NOT USE THE AES, THE VDI, OR THE BIOS PEXEC()
|
---|
104 | * FUNCTION. PEXEC WILL RETURN A CORRECT ERROR CODE (-39,
|
---|
105 | * ENSMEM), BUT IT WILL ALSO BREAK THE MEMORY MANAGEMENT SYSTEM.
|
---|
106 | *
|
---|
107 | * 0 Return all but a minimal amount (MINSTACK) of the free
|
---|
108 | * space to the operating system. This is a good idea if
|
---|
109 | * you know you won't be using malloc() much, or if you
|
---|
110 | * will be using Pexec() and your program doesn't need much
|
---|
111 | * stack space. Remember, though, that some library functions,
|
---|
112 | * especially fopen(), use malloc() and will use your heap
|
---|
113 | * space.
|
---|
114 | *
|
---|
115 | * 1 Keep 1/4 of the free space. This is a good model if
|
---|
116 | * you will be using malloc() a lot, but also want to use
|
---|
117 | * Pexec() to spawn subprocesses.
|
---|
118 | *
|
---|
119 | * 2 Keep 2/4 (1/2) of the free space. This is good if you
|
---|
120 | * use malloc() a lot, but don't want to be too much of a
|
---|
121 | * memory hog.
|
---|
122 | *
|
---|
123 | * 3 Keep 3/4 of the free space. This is a good choice for
|
---|
124 | * programs which use the AES or VDI, because it gives you plenty
|
---|
125 | * of room for using malloc(), but leaves enough for the
|
---|
126 | * AES and VDI to allocate their buffers, too.
|
---|
127 | *
|
---|
128 | * 4 This is a special value which means "Keep the number of
|
---|
129 | * bytes in the LONG global variable __STKSIZ." You must declare
|
---|
130 | * a variable in your program called "_STKSIZ" and initialize
|
---|
131 | * it to the number of bytes you want for your stack and heap.
|
---|
132 | * If __STKSIZ is negative, it means "Keep all BUT the number
|
---|
133 | * of bytes in __STKSIZ." As a safeguard, if __STKSIZ is
|
---|
134 | * undefined, you will get MINSTACK bytes of stack/heap.
|
---|
135 | *
|
---|
136 | * An example using __STKSIZ in C is:
|
---|
137 | *
|
---|
138 | * /* outside all function blocks */
|
---|
139 | *
|
---|
140 | * unsigned long _STKSIZ = 32767; /* 32K stack+heap */
|
---|
141 | * or
|
---|
142 | * unsigned long _STKSIZ = -8192; /* keep all but 8K */
|
---|
143 | *
|
---|
144 | * Note that in C, all variables get an underscore stuck on
|
---|
145 | * the front, so you just use one underscore in your program.
|
---|
146 | * Note also that it has to be all upper-case.
|
---|
147 | *
|
---|
148 | * Any other POSITIVE value of STACK will be taken as the number of
|
---|
149 | * bytes you want to KEEP for your stack and heap.
|
---|
150 | *
|
---|
151 | * Any other NEGATIVE value of STACK will be taken as the number of
|
---|
152 | * bytes you want to give back to the operating system.
|
---|
153 | *
|
---|
154 | * Note that if you give back less than 512 bytes, you still shouldn't
|
---|
155 | * use Pexec(), and if you give back less than (about) 4K, you shouldn't
|
---|
156 | * use the AES or VDI.
|
---|
157 | *
|
---|
158 | * In all cases, a minimum stack size is enforced. This minimum is
|
---|
159 | * set by the variable MINSTACK in this assembly file. This value
|
---|
160 | * should be at least 256 bytes, but should be more like 4K. If
|
---|
161 | * the stack size from the STACK model you choose or the _STKSIZ
|
---|
162 | * variable in your program is less than MINSTACK, you'll get
|
---|
163 | * MINSTACK bytes. If there aren't MINSTACK bytes free past the end
|
---|
164 | * of your BSS, the program will abort with an error message.
|
---|
165 | *
|
---|
166 | *************************************************************************
|
---|
167 |
|
---|
168 | FUDGE=512 * minimum space to leave ABOVE our stack
|
---|
169 |
|
---|
170 | * BASEPAGE ADDRESSES:
|
---|
171 | p_lowtpa=$0 * Low TPA address (basepage address)
|
---|
172 | p_hitpa=$4 * High TPA address (and initial stack pointer)
|
---|
173 | p_tbase=$8 * ptr to Code segment start
|
---|
174 | p_tlen=$c * Code segment length
|
---|
175 | p_dbase=$10 * ptr to Data segment start
|
---|
176 | p_dlen=$14 * Data segment length
|
---|
177 | p_bbase=$18 * ptr to Bss segment start
|
---|
178 | p_blen=$1c * Bss segment length
|
---|
179 | p_dta=$20 * ptr to process's initial DTA
|
---|
180 | p_parent=$24 * ptr to process's parent's basepage
|
---|
181 | p_reserved=$28 * reserved pointer
|
---|
182 | p_env=$2c * ptr to environment string for process
|
---|
183 | p_cmdlin=$80 * Command line image
|
---|
184 |
|
---|
185 | *
|
---|
186 | * CONTROL VARIABLES (used in stack computations)
|
---|
187 | *
|
---|
188 | * GOTSTACK: a boolean which is set TRUE if STACK in [-1..4], meaning "don't
|
---|
189 | * assemble the code keeping or returning STACK bytes."
|
---|
190 | *
|
---|
191 | * DOSHRINK: a boolean which is set FALSE if STACK is -1, meaning "don't
|
---|
192 | * shrink any memory back to the operating system."
|
---|
193 | *
|
---|
194 | gotstack .equ 0 * set to 1 if STACK in [-1..4]
|
---|
195 | doshrink .equ 1 * default is 1; set to 0 if STACK = -1
|
---|
196 |
|
---|
197 | * GEMDOS functions:
|
---|
198 | cconws=$09 * Cconws(string): write to console
|
---|
199 | mshrink=$4a * Mshrink(newsize): shrink a block to a new size
|
---|
200 | pterm=$4c * Pterm(code): exit, return code to parent
|
---|
201 |
|
---|
202 | .globl __start
|
---|
203 | .globl __main
|
---|
204 | .globl __exit
|
---|
205 | .globl _brk
|
---|
206 | .globl __break
|
---|
207 | .globl ___cpmrv
|
---|
208 | .globl __base
|
---|
209 | .globl __sovf
|
---|
210 | .globl _crystal
|
---|
211 | .globl _ctrl_cnts
|
---|
212 |
|
---|
213 | .globl __cmdsz * Command line length in __cmdln
|
---|
214 | .globl __cmdln * Command line image before __main gets it
|
---|
215 |
|
---|
216 | .text
|
---|
217 | *
|
---|
218 | * Must be first object file in link statement
|
---|
219 | *
|
---|
220 |
|
---|
221 | __start:
|
---|
222 | move.l sp,a1 * save our initial sp (used by ABORT)
|
---|
223 | move.l 4(sp),a0 * a0 = basepage address
|
---|
224 | move.l a0,__base * base = a0
|
---|
225 | move.l p_bbase(a0),d0 * d0 = bss seg start
|
---|
226 | add.l p_blen(a0),d0 * d0 += bss length (d0 now = start of heap)
|
---|
227 | move.l d0,__break * __break = first byte of heap
|
---|
228 |
|
---|
229 | *************************************************************************
|
---|
230 | * *
|
---|
231 | * Compute stack size based on MINSTACK, p_hitpa(a0), STACK, *
|
---|
232 | * and __STKSIZ, as appropriate. Place the SP where you want *
|
---|
233 | * your stack to be. Note that a0 == __base, d0 == __break *
|
---|
234 | * *
|
---|
235 | * At most one of the STACK code fragments will be assembled. *
|
---|
236 | * If none of them are, then `gotstack' will still be 0, and *
|
---|
237 | * the final block, saving STACK bytes, is used. Finally, if *
|
---|
238 | * STACK wasn't -1 (meaning don't shrink at all), DOSHRINK *
|
---|
239 | * gets control. See doshrink for more. *
|
---|
240 | * *
|
---|
241 | *************************************************************************
|
---|
242 |
|
---|
243 | *************************************************************************
|
---|
244 | * STACK = -1: keep all of memory *
|
---|
245 | *************************************************************************
|
---|
246 |
|
---|
247 | .ifeq STACK+1 * if (STACK == -1)
|
---|
248 | gotstack .equ 1
|
---|
249 | doshrink .equ 0 * this PREVENTS doshrink from assembling.
|
---|
250 | move.l p_hitpa(a0),sp * place stack at top of tpa.
|
---|
251 | move.l d0,d1 * check against MINSTACK
|
---|
252 | add.l #MINSTACK,d1 * d1 = __break + MINSTACK;
|
---|
253 | cmp.l sp,d1 * if (sp < __break + MINSTACK)
|
---|
254 | bhi abort * goto abort;
|
---|
255 | .endc * (this falls through to the __main call)
|
---|
256 |
|
---|
257 | *************************************************************************
|
---|
258 | * STACK = 0: keep only MINSTACK bytes *
|
---|
259 | *************************************************************************
|
---|
260 |
|
---|
261 | .ifeq STACK
|
---|
262 | gotstack .equ 1
|
---|
263 | move.l #MINSTACK,sp * sp = __break+MINSTACK;
|
---|
264 | add.l d0,sp
|
---|
265 | .endc * (this falls through to doshrink)
|
---|
266 |
|
---|
267 | *************************************************************************
|
---|
268 | * STACK = 1: keep 1/4 of available memory *
|
---|
269 | *************************************************************************
|
---|
270 |
|
---|
271 | .ifeq STACK-1
|
---|
272 | gotstack .equ 1 * /* keep 1/4 of available RAM */
|
---|
273 | move.l p_hitpa(a0),d1 * d1 = p_hitpa;
|
---|
274 | sub.l d0,d1 * d1 -= __break; /* d1 = free ram size */
|
---|
275 | lsr.l #2,d1 * d1 /= 4;
|
---|
276 | add.l d0,d1 * d1 += __break; /* d1 = new sp */
|
---|
277 | move.l d1,sp * sp = d1;
|
---|
278 | .endc * } (this falls through to doshrink)
|
---|
279 |
|
---|
280 | *************************************************************************
|
---|
281 | * STACK = 2: keep 2/4 of available memory *
|
---|
282 | *************************************************************************
|
---|
283 |
|
---|
284 | .ifeq STACK-2 * if (STACK == 2) { /* keep 1/2 */
|
---|
285 | gotstack .equ 1
|
---|
286 | move.l p_hitpa(a0),d1 * d1 = p_hitpa;
|
---|
287 | sub.l d0,d1 * d1 -= __break; /* d1 = free ram size */
|
---|
288 | lsr.l #1,d1 * d1 /= 2;
|
---|
289 | add.l d0,d1 * d1 += __break; /* d1 = new sp */
|
---|
290 | move.l d1,sp * sp = d1;
|
---|
291 | .endc * this falls through to doshrink
|
---|
292 |
|
---|
293 | *************************************************************************
|
---|
294 | * STACK = 3: keep 3/4 of available memory *
|
---|
295 | *************************************************************************
|
---|
296 |
|
---|
297 | .ifeq STACK-3 * if (STACK == 3) { /* keep 3/4 */
|
---|
298 | gotstack .equ 1
|
---|
299 | move.l p_hitpa(a0),d1 * d1 = p_hitpa;
|
---|
300 | sub.l d0,d1 * d1 -= __break; /* d1 = free ram size */
|
---|
301 | lsr.l #2,d1 * d1 /= 4;
|
---|
302 | move.l d1,d2 * d2 = d1
|
---|
303 | add.l d2,d1 * d1 += d2;
|
---|
304 | add.l d2,d1 * d1 += d2; /* now d1 = 3*(d1/4) */
|
---|
305 | add.l d0,d1 * d1 += __break; /* d1 = new sp */
|
---|
306 | move.l d1,sp * sp = d1;
|
---|
307 | .endc * this falls through to doshrink
|
---|
308 |
|
---|
309 | *************************************************************************
|
---|
310 | * STACK = 4: keep or give up __STKSIZ bytes of memory. *
|
---|
311 | *************************************************************************
|
---|
312 |
|
---|
313 | .ifeq STACK-4 * if (STACK == 4) { /* keep __STKSIZ */
|
---|
314 | .globl __STKSIZ * global variable holding stack size
|
---|
315 | gotstack .equ 1
|
---|
316 | move.l #__STKSIZ,a1 * Check to see if __STKSIZ was undefined.
|
---|
317 | beq keepmin * if it's zero, keep the minimum stack.
|
---|
318 | *
|
---|
319 | move.l (a1),d1
|
---|
320 | bmi giveback * if (__STKSIZ < 0) goto giveback;
|
---|
321 | *
|
---|
322 | add.l d0,d1 * d1 = __base+__STKSIZ; /* new sp */
|
---|
323 | bra gotd1
|
---|
324 |
|
---|
325 | keepmin: * __STKSIZ was undefined; keep minimum.
|
---|
326 | move.l #MINSTACK,d1
|
---|
327 | add.l d0,d1 * d1 = __base + MINSTACK;
|
---|
328 | bra gotd1 * goto gotd1;
|
---|
329 |
|
---|
330 | giveback:
|
---|
331 | add.l p_hitpa(a0),d1 * d1 += hitpa;
|
---|
332 |
|
---|
333 | gotd1: move.l d1,sp * gotd1: sp = d1;
|
---|
334 | .endc
|
---|
335 |
|
---|
336 | *************************************************************************
|
---|
337 | * STACK is something else: keep (if STACK>0) or give *
|
---|
338 | * back (if STACK<0) STACK bytes *
|
---|
339 | *************************************************************************
|
---|
340 |
|
---|
341 | .ifeq gotstack * it's a constant stack value (+ or -)
|
---|
342 |
|
---|
343 | move.l #STACK,d1 * /* if neg, give back STACK bytes */
|
---|
344 | bmi giveback * if (STACK < 0) goto giveback;
|
---|
345 | *
|
---|
346 | add.l d0,d1 * d1 = __STKSIZ + __base; /* new sp */
|
---|
347 | bra gotd1 * goto gotd1;
|
---|
348 |
|
---|
349 | giveback: * giveback:
|
---|
350 | add.l p_hitpa(a0),d1 * d1 += hitpa; /* d1 = new sp */
|
---|
351 | gotd1: * gotd1:
|
---|
352 | move.l d1,sp * sp = d1;
|
---|
353 | .endc
|
---|
354 |
|
---|
355 | *************************************************************************
|
---|
356 | * *
|
---|
357 | * DOSHRINK: take SP as a requested stack pointer. Place it *
|
---|
358 | * between (__break+MINSTACK) and (p_hitpa(a0)-FUDGE). If we can't, *
|
---|
359 | * abort. Otherwise, we return the remaining memory back to the o.s. *
|
---|
360 | * The reason we always shrink by at least FUDGE bytes is to work around *
|
---|
361 | * a BUG in the XBIOS Malloc() routine: when there are fewer than 512 *
|
---|
362 | * bytes in the largest free block, attempting a Pexec() breaks the *
|
---|
363 | * memory management system. Since all models except -1 permit Pexec() *
|
---|
364 | * calls, we have to make sure they don't break, even if the Pexec() *
|
---|
365 | * fails. Thus, FUDGE must be at least 512. *
|
---|
366 | * *
|
---|
367 | *************************************************************************
|
---|
368 | *
|
---|
369 | * PSEUDOCODE:
|
---|
370 | * doshrink(sp)
|
---|
371 | * {
|
---|
372 | * /* if too low, bump it up */
|
---|
373 | * if (sp < (__break + MINSTACK))
|
---|
374 | * sp = (__break + MINSTACK);
|
---|
375 | *
|
---|
376 | * /* if too high, bump it down */
|
---|
377 | * if (sp > (hitpa - FUDGE)) {
|
---|
378 | * sp = (hitpa - FUDGE);
|
---|
379 | *
|
---|
380 | * /* if now too low, there's not enough memory */
|
---|
381 | * if (sp < (__break + MINSTACK))
|
---|
382 | * goto abort;
|
---|
383 | * }
|
---|
384 | * Mshrink(0,__base,(sp - __base));
|
---|
385 | * }
|
---|
386 | *
|
---|
387 | *************************************************************************
|
---|
388 |
|
---|
389 | .ifne doshrink * assemble this only if STACK != -1
|
---|
390 | move.l d0,d1 * d1 = __break;
|
---|
391 | add.l #MINSTACK,d1 * d1 += MINSTACK;
|
---|
392 | cmp.l d1,sp * if ((__break+MINSTACK) < sp)
|
---|
393 | bhi minok * goto minok;
|
---|
394 | move.l d1,sp * else sp = (__break+MINSTACK)
|
---|
395 | minok: * minok:
|
---|
396 | move.l p_hitpa(a0),d2 * d2 = hitpa;
|
---|
397 | sub.l #FUDGE,d2 * d2 -= FUDGE;
|
---|
398 | cmp.l d2,sp * if ((hitpa - FUDGE) > sp)
|
---|
399 | bcs maxok * goto maxok;
|
---|
400 | * * else {
|
---|
401 | move.l d2,sp * sp = (hitpa - FUDGE);
|
---|
402 | cmp.l d1,d2 * if ((__break+MINSTACK) > (hitpa-FUDGE))
|
---|
403 | bcs abort * goto abort; /* BAD NEWS */
|
---|
404 | * * }
|
---|
405 | maxok:
|
---|
406 |
|
---|
407 | *************************************************************************
|
---|
408 | * STACK LOCATION HAS BEEN DETERMINED. Return unused memory to the o.s. *
|
---|
409 | *************************************************************************
|
---|
410 |
|
---|
411 | move.l sp,d1 * d1 = sp;
|
---|
412 | and.l #-2,d1 * /* ensure d1 is even */
|
---|
413 | move.l d1,sp * sp = d1;
|
---|
414 | sub.l a0,d1 * d1 -= __base; /* d1 == size to keep */
|
---|
415 |
|
---|
416 | move.l d1,-(sp) * push the size to keep
|
---|
417 | move.l a0,-(sp) * and start of this block (our basepage)
|
---|
418 | clr.w -(sp) * and a junk word
|
---|
419 | move #mshrink,-(sp) * and the function code
|
---|
420 | trap #1 * Mshrink(0,__base,(sp-base))
|
---|
421 | add.l #12,sp * clean the stack after ourselves
|
---|
422 | .endc
|
---|
423 |
|
---|
424 | *************************************************************************
|
---|
425 | * *
|
---|
426 | * Finally, the stack is set up. Now call _main(cmdline, length). *
|
---|
427 | * *
|
---|
428 | *************************************************************************
|
---|
429 |
|
---|
430 | move.l __base,a0 * set up _main(cmdline,length)
|
---|
431 | lea.l p_cmdlin(a0),a2 * a2 now points to command line
|
---|
432 | move.b (a2)+,d0 * d0 = length; a2++;
|
---|
433 | ext.w d0 * extend byte count into d0.w
|
---|
434 | move.w d0,-(a7) * push length
|
---|
435 | move.l a2,-(a7) * Push commnd
|
---|
436 | *
|
---|
437 | move.w d0,__cmdsz * Save length
|
---|
438 | lea.l __cmdln,a1 * Setup move to address
|
---|
439 | bra LynxL1 * Enter the loop
|
---|
440 | *
|
---|
441 | LynxL2: move.b (a2)+,(a1)+ * Move a byte
|
---|
442 | *
|
---|
443 | LynxL1: dbf d0,LynxL2 * Loop until they're moved
|
---|
444 | *
|
---|
445 | clr.l a6 * Clear frame pointer
|
---|
446 | jsr __main * call main routine NEVER RETURNS
|
---|
447 |
|
---|
448 | ***********************************************************************
|
---|
449 | *
|
---|
450 | * _exit(code) Terminate process, return code to the parent.
|
---|
451 | *
|
---|
452 | ***********************************************************************
|
---|
453 |
|
---|
454 | __exit:
|
---|
455 | tst.l (a7)+ * drop return PC off the stack, leaving code
|
---|
456 | move.w #pterm,-(a7) * push function number
|
---|
457 | trap #1 * and trap.
|
---|
458 |
|
---|
459 | *
|
---|
460 | * abort: used if the stack setup above fails. Restores the initial sp,
|
---|
461 | * prints a message, and quits with the error ENSMEM.
|
---|
462 | *
|
---|
463 | abort: * print an abortive message and quit
|
---|
464 | move.l a1,sp * restore initial sp
|
---|
465 | pea.l abortmsg * push string address
|
---|
466 | move.w #cconws,-(a7) * and function code
|
---|
467 | trap #1 * and trap to print message
|
---|
468 | addq.l #6,a7 * clean off stack
|
---|
469 | move.w #-39,-(a7) * push error number -39: ENSMEM
|
---|
470 | jsr __exit * and exit with it.
|
---|
471 | *
|
---|
472 | * brk() -- set system break
|
---|
473 | *
|
---|
474 | _brk:
|
---|
475 | cmp.l __break,sp * compare current break with current stack
|
---|
476 | bcs __sovf * actual stack overflow!
|
---|
477 | *
|
---|
478 | movea.l 4(sp),a0 * get new break
|
---|
479 | move.l a0,d0 * compare with stack, including 256-byte
|
---|
480 | adda.l #$100,a0 * chicken factor
|
---|
481 | cmpa.l a0,sp * if (sp < a0+256)
|
---|
482 | bcs badbrk * bad break;
|
---|
483 | *
|
---|
484 | move.l d0,__break * OK break: save the break
|
---|
485 | clr.l d0 * Set OK return
|
---|
486 | rts * return
|
---|
487 |
|
---|
488 | badbrk:
|
---|
489 | move.l #-1,d0 * Load return reg
|
---|
490 | rts * Return
|
---|
491 | *
|
---|
492 | *
|
---|
493 | .globl ___BDOS
|
---|
494 | ___BDOS:
|
---|
495 | link a6,#0 * link
|
---|
496 | move.w 8(sp),d0 * Load func code
|
---|
497 | move.l 10(sp),d1 * Load Paramter
|
---|
498 | trap #2 * Enter BDOS
|
---|
499 | cmpa.l __break,sp * Check for stack ovf
|
---|
500 | bcs __sovf * overflow! print msg and abort
|
---|
501 | *
|
---|
502 | unlk a6 * no error; return
|
---|
503 | rts * Back to caller
|
---|
504 |
|
---|
505 | *
|
---|
506 | * stack overflow! This external is called by salloc in gemlib as well as above
|
---|
507 | *
|
---|
508 | __sovf:
|
---|
509 | move.l #ovf,-(sp) * push message address
|
---|
510 | move.w #cconws,-(sp) * push fn code
|
---|
511 | trap #1 * Issue message
|
---|
512 |
|
---|
513 | move.w #1,-(a7) * push return code (1)
|
---|
514 | move.w #pterm,d0 * push function code (Pterm)
|
---|
515 | trap #1 * call Pterm(1) (never returns)
|
---|
516 |
|
---|
517 | *
|
---|
518 | * Block Fill function:
|
---|
519 | *
|
---|
520 | * blkfill(dest,char,cnt);
|
---|
521 | *
|
---|
522 | * BYTE *dest; * -> area to be filled
|
---|
523 | * BYTE char; * = char to fill
|
---|
524 | * WORD cnt; * = # bytes to fill
|
---|
525 | *
|
---|
526 | .globl _blkfill
|
---|
527 | _blkfill:
|
---|
528 | move.l 4(a7),a0 * -> Output area
|
---|
529 | move.w 8(a7),d1 * = output char
|
---|
530 | move.w 10(a7),d0 * = output count
|
---|
531 | ext.l d0 * make it long
|
---|
532 | subq.l #1,d0 * decrement
|
---|
533 | ble filldone * Done if le
|
---|
534 | *
|
---|
535 | fillit: move.b d1,(a0)+ * move a byte
|
---|
536 | dbra d0,fillit * Continue
|
---|
537 | *
|
---|
538 | filldone: clr.l d0 * always return 0
|
---|
539 | rts *
|
---|
540 |
|
---|
541 | *
|
---|
542 | * Index function to find out if a particular character is in a string.
|
---|
543 | *
|
---|
544 | .globl _index
|
---|
545 | .globl _strchr
|
---|
546 | _index:
|
---|
547 | _strchr:
|
---|
548 | move.l 4(a7),a0 * a0 -> String
|
---|
549 | move.w 8(a7),d0 * D0 = desired character
|
---|
550 | *
|
---|
551 | xindex: tst.b (a0) * EOS?
|
---|
552 | bne notend * No, continue to look
|
---|
553 | *
|
---|
554 | clr.l d0 * Not found
|
---|
555 | rts * Quit
|
---|
556 | *
|
---|
557 | notend: cmp.b (a0)+,d0 * check for character
|
---|
558 | bne xindex *
|
---|
559 | *
|
---|
560 | move.l a0,d0 * Found it
|
---|
561 | subq.l #1,d0 * set return pointer
|
---|
562 | rts
|
---|
563 |
|
---|
564 | *
|
---|
565 | * For GEMAES calls from AESBIND.ARC or cryslib.o
|
---|
566 | *
|
---|
567 | _crystal:
|
---|
568 | move.l 4(a7),d1
|
---|
569 | move.w #200,d0
|
---|
570 | trap #2
|
---|
571 | rts
|
---|
572 |
|
---|
573 | *
|
---|
574 | * Data area
|
---|
575 | *
|
---|
576 | .data
|
---|
577 | .globl ___pname * Program Name
|
---|
578 | .globl ___tname * Terminal Name
|
---|
579 | .globl ___lname * List device name
|
---|
580 | .globl ___xeof * ^Z byte
|
---|
581 | *
|
---|
582 | ovf: .dc.b 'Stack Overflow',13,10,0 * Overflow message
|
---|
583 | *
|
---|
584 | ___pname: .dc.b 'Diamel',0 * Program name
|
---|
585 | ___tname: .dc.b 'CON:',0 * Console name
|
---|
586 | ___lname: .dc.b 'LST:',0 * List device name
|
---|
587 | ___xeof: .dc.b $1a * Control-Z
|
---|
588 | *
|
---|
589 | abortmsg: .dc.b 'Cannot initialize stack',13,10,0 * abort message
|
---|
590 |
|
---|
591 | **********************************************************************
|
---|
592 | *
|
---|
593 | * BSS AREA
|
---|
594 | **********************************************************************
|
---|
595 | .bss
|
---|
596 | .even
|
---|
597 | __base: .ds.l 1 * -> Base Page
|
---|
598 | __break: .ds.l 1 * Break location
|
---|
599 | ___cpmrv: .ds.w 1 * Last CP/M return val
|
---|
600 | *
|
---|
601 | __cmdsz: .ds.w 1 * Length of command line in __cmdln
|
---|
602 | __cmdln: .ds.w 128 * Command line image before __main gets it
|
---|
603 | *
|
---|
604 | * control array for vdibind
|
---|
605 | *
|
---|
606 | .data
|
---|
607 | .even
|
---|
608 | _ctrl_cnts: * Application Manager
|
---|
609 | .dc.b 0, 1, 0 * func 010
|
---|
610 | .dc.b 2, 1, 1 * func 011
|
---|
611 | .dc.b 2, 1, 1 * func 012
|
---|
612 | .dc.b 0, 1, 1 * func 013
|
---|
613 | .dc.b 2, 1, 1 * func 014
|
---|
614 | .dc.b 1, 1, 1 * func 015
|
---|
615 | .dc.b 0, 0, 0 * func 016
|
---|
616 | .dc.b 0, 0, 0 * func 017
|
---|
617 | .dc.b 0, 0, 0 * func 008
|
---|
618 | .dc.b 0, 1, 0 * func 019
|
---|
619 | * Event Manager
|
---|
620 | .dc.b 0, 1, 0 * func 020
|
---|
621 | .dc.b 3, 5, 0 * func 021
|
---|
622 | .dc.b 5, 5, 0 * func 022
|
---|
623 | .dc.b 0, 1, 1 * func 023
|
---|
624 | .dc.b 2, 1, 0 * func 024
|
---|
625 | .dc.b 16, 7, 1 * func 025
|
---|
626 | .dc.b 2, 1, 0 * func 026
|
---|
627 | .dc.b 0, 0, 0 * func 027
|
---|
628 | .dc.b 0, 0, 0 * func 028
|
---|
629 | .dc.b 0, 0, 0 * func 009
|
---|
630 | * Menu Manager
|
---|
631 | .dc.b 1, 1, 1 * func 030
|
---|
632 | .dc.b 2, 1, 1 * func 031
|
---|
633 | .dc.b 2, 1, 1 * func 032
|
---|
634 | .dc.b 2, 1, 1 * func 033
|
---|
635 | .dc.b 1, 1, 2 * func 034
|
---|
636 | .dc.b 1, 1, 1 * func 005
|
---|
637 | .dc.b 0, 0, 0 * func 006
|
---|
638 | .dc.b 0, 0, 0 * func 007
|
---|
639 | .dc.b 0, 0, 0 * func 008
|
---|
640 | .dc.b 0, 0, 0 * func 009
|
---|
641 | * Object Manager
|
---|
642 | .dc.b 2, 1, 1 * func 040
|
---|
643 | .dc.b 1, 1, 1 * func 041
|
---|
644 | .dc.b 6, 1, 1 * func 042
|
---|
645 | .dc.b 4, 1, 1 * func 043
|
---|
646 | .dc.b 1, 3, 1 * func 044
|
---|
647 | .dc.b 2, 1, 1 * func 045
|
---|
648 | .dc.b 4, 2, 1 * func 046
|
---|
649 | .dc.b 8, 1, 1 * func 047
|
---|
650 | .dc.b 0, 0, 0 * func 048
|
---|
651 | .dc.b 0, 0, 0 * func 049
|
---|
652 | * Form Manager
|
---|
653 | .dc.b 1, 1, 1 * func 050
|
---|
654 | .dc.b 9, 1, 1 * func 051
|
---|
655 | .dc.b 1, 1, 1 * func 002
|
---|
656 | .dc.b 1, 1, 0 * func 003
|
---|
657 | .dc.b 0, 5, 1 * func 004
|
---|
658 | .dc.b 0, 0, 0 * func 005
|
---|
659 | .dc.b 0, 0, 0 * func 006
|
---|
660 | .dc.b 0, 0, 0 * func 007
|
---|
661 | .dc.b 0, 0, 0 * func 008
|
---|
662 | .dc.b 0, 0, 0 * func 009
|
---|
663 | * Dialog Manager
|
---|
664 | .dc.b 0, 0, 0 * func 060
|
---|
665 | .dc.b 0, 0, 0 * func 061
|
---|
666 | .dc.b 0, 0, 0 * func 062
|
---|
667 | .dc.b 0, 0, 0 * func 003
|
---|
668 | .dc.b 0, 0, 0 * func 004
|
---|
669 | .dc.b 0, 0, 0 * func 005
|
---|
670 | .dc.b 0, 0, 0 * func 006
|
---|
671 | .dc.b 0, 0, 0 * func 007
|
---|
672 | .dc.b 0, 0, 0 * func 008
|
---|
673 | .dc.b 0, 0, 0 * func 009
|
---|
674 | * Graphics Manager
|
---|
675 | .dc.b 4, 3, 0 * func 070
|
---|
676 | .dc.b 8, 3, 0 * func 071
|
---|
677 | .dc.b 6, 1, 0 * func 072
|
---|
678 | .dc.b 8, 1, 0 * func 073
|
---|
679 | .dc.b 8, 1, 0 * func 074
|
---|
680 | .dc.b 4, 1, 1 * func 075
|
---|
681 | .dc.b 3, 1, 1 * func 076
|
---|
682 | .dc.b 0, 5, 0 * func 077
|
---|
683 | .dc.b 1, 1, 1 * func 078
|
---|
684 | .dc.b 0, 5, 0 * func 009
|
---|
685 | * Scrap Manager
|
---|
686 | .dc.b 0, 1, 1 * func 080
|
---|
687 | .dc.b 0, 1, 1 * func 081
|
---|
688 | .dc.b 0, 0, 0 * func 082
|
---|
689 | .dc.b 0, 0, 0 * func 083
|
---|
690 | .dc.b 0, 0, 0 * func 084
|
---|
691 | .dc.b 0, 0, 0 * func 005
|
---|
692 | .dc.b 0, 0, 0 * func 006
|
---|
693 | .dc.b 0, 0, 0 * func 007
|
---|
694 | .dc.b 0, 0, 0 * func 008
|
---|
695 | .dc.b 0, 0, 0 * func 009
|
---|
696 | * fseler Manager
|
---|
697 | .dc.b 0, 2, 2 * func 090
|
---|
698 | .dc.b 0, 0, 0 * func 091
|
---|
699 | .dc.b 0, 0, 0 * func 092
|
---|
700 | .dc.b 0, 0, 0 * func 003
|
---|
701 | .dc.b 0, 0, 0 * func 004
|
---|
702 | .dc.b 0, 0, 0 * func 005
|
---|
703 | .dc.b 0, 0, 0 * func 006
|
---|
704 | .dc.b 0, 0, 0 * func 007
|
---|
705 | .dc.b 0, 0, 0 * func 008
|
---|
706 | .dc.b 0, 0, 0 * func 009
|
---|
707 | * Window Manager
|
---|
708 | .dc.b 5, 1, 0 * func 100
|
---|
709 | .dc.b 5, 1, 0 * func 101
|
---|
710 | .dc.b 1, 1, 0 * func 102
|
---|
711 | .dc.b 1, 1, 0 * func 103
|
---|
712 | .dc.b 2, 5, 0 * func 104
|
---|
713 | .dc.b 6, 1, 0 * func 105
|
---|
714 | .dc.b 2, 1, 0 * func 106
|
---|
715 | .dc.b 1, 1, 0 * func 107
|
---|
716 | .dc.b 6, 5, 0 * func 108
|
---|
717 | .dc.b 0, 0, 0 * func 009
|
---|
718 | * Resource Manger
|
---|
719 | .dc.b 0, 1, 1 * func 110
|
---|
720 | .dc.b 0, 1, 0 * func 111
|
---|
721 | .dc.b 2, 1, 0 * func 112
|
---|
722 | .dc.b 2, 1, 1 * func 113
|
---|
723 | .dc.b 1, 1, 1 * func 114
|
---|
724 | .dc.b 0, 0, 0 * func 115
|
---|
725 | .dc.b 0, 0, 0 * func 006
|
---|
726 | .dc.b 0, 0, 0 * func 007
|
---|
727 | .dc.b 0, 0, 0 * func 008
|
---|
728 | .dc.b 0, 0, 0 * func 009
|
---|
729 | * Shell Manager
|
---|
730 | .dc.b 0, 1, 2 * func 120
|
---|
731 | .dc.b 3, 1, 2 * func 121
|
---|
732 | .dc.b 1, 1, 1 * func 122
|
---|
733 | .dc.b 1, 1, 1 * func 123
|
---|
734 | .dc.b 0, 1, 1 * func 124
|
---|
735 | .dc.b 0, 1, 2 * func 125
|
---|
736 |
|
---|
737 | .end
|
---|