diff options
Diffstat (limited to 'i386/dos/i16/i16_crt0.S')
-rw-r--r-- | i386/dos/i16/i16_crt0.S | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/i386/dos/i16/i16_crt0.S b/i386/dos/i16/i16_crt0.S new file mode 100644 index 0000000..f21c6a6 --- /dev/null +++ b/i386/dos/i16/i16_crt0.S @@ -0,0 +1,274 @@ +/* + * Copyright (c) 1995-1994 The University of Utah and + * the Computer Systems Laboratory at the University of Utah (CSL). + * All rights reserved. + * + * Permission to use, copy, modify and distribute this software is hereby + * granted provided that (1) source code retains these copyright, permission, + * and disclaimer notices, and (2) redistributions including binaries + * reproduce the notices in supporting documentation, and (3) all advertising + * materials mentioning features or use of this software display the following + * acknowledgement: ``This product includes software developed by the + * Computer Systems Laboratory at the University of Utah.'' + * + * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS + * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF + * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * CSL requests users of this software to return to csl-dist@cs.utah.edu any + * improvements that they make and grant CSL redistribution rights. + * + * Author: Bryan Ford, University of Utah CSL + */ + +#include <mach/machine/asm.h> + +#include "config.h" +#include "i16_crt0.h" + + .code16 + .text + +ENTRY(i16_entry) + /* DOS starts us up with our stack pointer pointing + to the very top of our BSS segment. + ds and es point to the PSP. */ + +#define DELAY jmp 1f; 1: jmp 1f; 1: jmp 1f; 1: + + /* Check to make sure we're running on a 386 or higher - + _without_ using any 32-bit instructions of course. + Tricky, since gas doesn't support 16-bit addressing modes. :-) + We can't produce any 16-bit relocations either, + because ELF doesn't support them. + This code is basically straight out of the Pentium manual, + except gassed of coursed. */ + pushfw + DELAY + popw %bx + movw $0xfff,%ax + andw %bx,%ax + pushw %ax + DELAY + popfw + DELAY + pushfw + DELAY + popw %ax + and $0xf000,%ax + cmpw $0xf000,%ax + + je 1f + orw $0xf000,%bx + pushw %bx + DELAY + popfw + DELAY + pushfw + DELAY + popw %ax + andw $0xf000,%ax + jnz 4f +1: + /* Gak! We're running on an 8086/8088/80286! */ + callw 5f + .ascii "This program requires a 386 or better.\r\n\0" +5: popw %si + movw %cs,%ax + movw %ax,%ds + cld +2: lodsb + orb %al,%al + jz 3f + movb $0x02,%ah + movb %al,%dl + int $0x21 + jmp 2b +3: movw $0x4c02,%ax + int $0x21 +4: + /* Now we can use 32-bit instructions all we want. */ + + /* Save the PSP segment address (dx). */ + movw %ds,%dx + + /* Find our real-mode code segment (ax). */ + movw %cs,%ax + +#ifdef ENABLE_PAGE_ALIGNED_KERNEL + /* Move our code and data so that everything is on a page boundary. + Theoretically we _could_ go past the end of available memory, + since we're not checking, but it's enormously unlikely. */ + std + movw %ax,%ds + addw $0xff,%ax + andw $0xff00,%ax + movw %ax,%es + movl $EXT(edata),%ecx + subl $EXT(i16_entry_2),%ecx + movl $EXT(edata)-1,%esi + movw %si,%di + rep + movsb + + /* Start running at the new address. */ + pushl $EXT(i16_entry_2) + movw %ax,2(%esp) + lretw + +ENTRY(i16_entry_2) + /* We're now page aligned. */ +#endif ENABLE_PAGE_ALIGNED_KERNEL + + /* Load the data segment registers appropriately. */ + movw %ax,%es + movw %ax,%ss + + /* Start using a real stack. */ + movl $EXT(crt0_stack)+CRT0_STACK_SIZE,%esp + + /* Clear our BSS segment. */ + movl $EXT(edata),%edi + movl $EXT(end),%ecx + subw %di,%cx + xorb %al,%al + cld + rep + stosb + + /* Find the size of the environment array (si) + and the number of environment variables plus one (bx). + The PSP segment is still in dx. */ + movw %dx,%ds + movw 0x2c,%ds + xorw %si,%si +1: lodsb + orb %al,%al + jnz 1b + lodsb + orb %al,%al + jnz 1b + + /* Allocate space for the environment array on the stack. + Also make sure the top 16 bits of ESP are cleared, + and that the stack pointer is longword aligned. */ + subw %si,%sp + andl $0x0000fffc,%esp + + /* Copy the environment array to the local stack. + We present it backwards, but big deal - shouldn't matter. */ + xorl %edi,%edi + movw %sp,%di + xorl %esi,%esi + pushl %esi + jmp 3f +2: pushl %edi + stosb +1: lodsb + stosb + orb %al,%al + jnz 1b +3: lodsb + orb %al,%al + jnz 2b + movl %esp,%cs:EXT(environ) + + /* Copy the program name to the local stack; + it will be used as argv[0]. */ + lodsw + movw %si,%bx +1: pushw $0 + lodsb + orb %al,%al + jz 2f + lodsb + orb %al,%al + jnz 1b +2: movw %bx,%si + movw %sp,%di +3: lodsb + stosb + orb %al,%al + jnz 3b + movl %esp,%ebp + + /* Build argv[1..n] from the command tail in the PSP. + Count the arguments in ebx. */ + movw %dx,%ds + xorl %ecx,%ecx + xorl %ebx,%ebx + movb 0x80,%cl /* get size of command tail */ + incw %cx /* plus the return character */ + movw $0x80,%si + addw %cx,%si /* si = ptr to return character */ + movw %sp,%di + decw %di + subw %cx,%sp /* allocate space on the stack */ + andw $0xfffc,%sp + pushl %ebx + std +1: xorb %al,%al /* store a null terminator for this arg */ + stosb + incl %ebx +2: cmpw $0x80,%si + je 5f + lodsb /* scan backwards for the end of an arg */ + cmpb $0x20,%al + jbe 2b +3: stosb /* copy the arg */ + cmpw $0x80,%si + je 4f + lodsb + cmpb $0x20,%al + ja 3b +4: movw %di,%cx /* push an arg pointer */ + incw %cx + pushl %ecx + jmp 1b +5: + + /* Push the argv[0] pointer. */ + pushl %ebp + + /* Push the argument and envirnonment parameters on the stack. */ + movl %esp,%eax + pushl %cs:EXT(environ) + pushl %eax + pushl %ebx + + /* Release all conventional memory above the top of our BSS. + The PSP segment is still in dx. */ + movl $EXT(end)+15,%ebx + shrw $4,%bx + movw %cs,%ax + addw %ax,%bx + subw %dx,%bx + movw %dx,%es + movb $0x4a,%ah + int $0x21 + + /* Load the normal data segment registers. */ + movw %cs,%ax + movw %ax,%ds + movw %ax,%es + + /* GCC wants the direction flag cleared at all times. */ + cld + + /* Initialize the bss and run the program. */ + call EXT(i16_main) + + .globl EXT(crt0_stack) + .comm EXT(crt0_stack),CRT0_STACK_SIZE + + .globl EXT(environ) + .comm EXT(environ),4 + + + .data + + .section .anno,"aw",@progbits + P2ALIGN(4) + .globl __ANNO_START__ +__ANNO_START__: + |