[3ae31e9] | 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
|
---|