| // Inferno utils/8a/l.s | |
| // http://code.google.com/p/inferno-os/source/browse/utils/8a/l.s | |
| // | |
| // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. | |
| // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) | |
| // Portions Copyright © 1997-1999 Vita Nuova Limited | |
| // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) | |
| // Portions Copyright © 2004,2006 Bruce Ellis | |
| // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) | |
| // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others | |
| // Portions Copyright © 2009 The Go Authors. All rights reserved. | |
| // | |
| // Permission is hereby granted, free of charge, to any person obtaining a copy | |
| // of this software and associated documentation files (the "Software"), to deal | |
| // in the Software without restriction, including without limitation the rights | |
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| // copies of the Software, and to permit persons to whom the Software is | |
| // furnished to do so, subject to the following conditions: | |
| // | |
| // The above copyright notice and this permission notice shall be included in | |
| // all copies or substantial portions of the Software. | |
| // | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
| // THE SOFTWARE. | |
| /* | |
| * Memory and machine-specific definitions. Used in C and assembler. | |
| */ | |
| /* | |
| * Sizes | |
| */ | |
| #define BI2BY 8 /* bits per byte */ | |
| #define BI2WD 32 /* bits per word */ | |
| #define BY2WD 4 /* bytes per word */ | |
| #define BY2PG 4096 /* bytes per page */ | |
| #define WD2PG (BY2PG/BY2WD) /* words per page */ | |
| #define PGSHIFT 12 /* log(BY2PG) */ | |
| #define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1)) | |
| #define MAXMACH 1 /* max # cpus system can run */ | |
| /* | |
| * Time | |
| */ | |
| #define HZ (20) /* clock frequency */ | |
| #define MS2HZ (1000/HZ) /* millisec per clock tick */ | |
| #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ | |
| #define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */ | |
| #define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */ | |
| /* | |
| * Fundamental addresses | |
| */ | |
| /* | |
| * Address spaces | |
| * | |
| * User is at 0-2GB | |
| * Kernel is at 2GB-4GB | |
| * | |
| * To avoid an extra page map, both the user stack (USTKTOP) and | |
| * the temporary user stack (TSTKTOP) should be in the the same | |
| * 4 meg. | |
| */ | |
| #define UZERO 0 /* base of user address space */ | |
| #define UTZERO (UZERO+BY2PG) /* first address in user text */ | |
| #define KZERO 0x80000000 /* base of kernel address space */ | |
| #define KTZERO KZERO /* first address in kernel text */ | |
| #define USERADDR 0xC0000000 /* struct User */ | |
| #define UREGADDR (USERADDR+BY2PG-4*19) | |
| #define TSTKTOP USERADDR /* end of new stack in sysexec */ | |
| #define TSTKSIZ 10 | |
| #define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */ | |
| #define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */ | |
| #define ROMBIOS (KZERO|0xF0000) | |
| #define MACHSIZE 4096 | |
| #define isphys(x) (((ulong)x)&KZERO) | |
| /* | |
| * known 80386 segments (in GDT) and their selectors | |
| */ | |
| #define NULLSEG 0 /* null segment */ | |
| #define KDSEG 1 /* kernel data/stack */ | |
| #define KESEG 2 /* kernel executable */ | |
| #define UDSEG 3 /* user data/stack */ | |
| #define UESEG 4 /* user executable */ | |
| #define TSSSEG 5 /* task segment */ | |
| #define SELGDT (0<<3) /* selector is in gdt */ | |
| #define SELLDT (1<<3) /* selector is in ldt */ | |
| #define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) | |
| #define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) | |
| #define KESEL SELECTOR(KESEG, SELGDT, 0) | |
| #define KDSEL SELECTOR(KDSEG, SELGDT, 0) | |
| #define UESEL SELECTOR(UESEG, SELGDT, 3) | |
| #define UDSEL SELECTOR(UDSEG, SELGDT, 3) | |
| #define TSSSEL SELECTOR(TSSSEG, SELGDT, 0) | |
| /* | |
| * fields in segment descriptors | |
| */ | |
| #define SEGDATA (0x10<<8) /* data/stack segment */ | |
| #define SEGEXEC (0x18<<8) /* executable segment */ | |
| #define SEGTSS (0x9<<8) /* TSS segment */ | |
| #define SEGCG (0x0C<<8) /* call gate */ | |
| #define SEGIG (0x0E<<8) /* interrupt gate */ | |
| #define SEGTG (0x0F<<8) /* task gate */ | |
| #define SEGTYPE (0x1F<<8) | |
| #define SEGP (1<<15) /* segment present */ | |
| #define SEGPL(x) ((x)<<13) /* priority level */ | |
| #define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ | |
| #define SEGG (1<<23) /* granularity 1==4k (for other) */ | |
| #define SEGE (1<<10) /* expand down */ | |
| #define SEGW (1<<9) /* writable (for data/stack) */ | |
| #define SEGR (1<<9) /* readable (for code) */ | |
| #define SEGD (1<<22) /* default 1==32bit (for code) */ | |
| /* | |
| * virtual MMU | |
| */ | |
| #define PTEMAPMEM (1024*1024) /* ??? */ | |
| #define SEGMAPSIZE 16 /* ??? */ | |
| #define PTEPERTAB (PTEMAPMEM/BY2PG) /* ??? */ | |
| #define PPN(x) ((x)&~(BY2PG-1)) | |
| /* | |
| * physical MMU | |
| */ | |
| #define PTEVALID (1<<0) | |
| #define PTEUNCACHED 0 /* everything is uncached */ | |
| #define PTEWRITE (1<<1) | |
| #define PTERONLY (0<<1) | |
| #define PTEKERNEL (0<<2) | |
| #define PTEUSER (1<<2) | |
| /* | |
| * flag register bits that we care about | |
| */ | |
| #define IFLAG 0x200 | |
| #define OP16 BYTE $0x66 | |
| /* | |
| * about to walk all over ms/dos - turn off interrupts | |
| */ | |
| TEXT origin(SB),$0 | |
| CLI | |
| #ifdef BOOT | |
| /* | |
| * This part of l.s is used only in the boot kernel. | |
| * It assumes that we are in real address mode, i.e., | |
| * that we look like an 8086. | |
| */ | |
| /* | |
| * relocate everything to a half meg and jump there | |
| * - looks wierd because it is being assembled by a 32 bit | |
| * assembler for a 16 bit world | |
| */ | |
| MOVL $0,BX | |
| INCL BX | |
| SHLL $15,BX | |
| MOVL BX,CX | |
| MOVW BX,ES | |
| MOVL $0,SI | |
| MOVL SI,DI | |
| CLD; REP; MOVSL | |
| /* JMPFAR 0X8000:$lowcore(SB) /**/ | |
| BYTE $0xEA | |
| WORD $lowcore(SB) | |
| WORD $0X8000 | |
| TEXT lowcore(SB),$0 | |
| /* | |
| * now that we're in low core, update the DS | |
| */ | |
| MOVW BX,DS | |
| /* | |
| * goto protected mode | |
| */ | |
| /* MOVL tgdtptr(SB),GDTR /**/ | |
| BYTE $0x0f | |
| BYTE $0x01 | |
| BYTE $0x16 | |
| WORD $tgdtptr(SB) | |
| MOVL CR0,AX | |
| ORL $1,AX | |
| MOVL AX,CR0 | |
| /* | |
| * clear prefetch queue (wierd code to avoid optimizations) | |
| */ | |
| CLC | |
| JCC flush | |
| MOVL AX,AX | |
| flush: | |
| /* | |
| * set all segs | |
| */ | |
| /* MOVW $SELECTOR(1, SELGDT, 0),AX /**/ | |
| BYTE $0xc7 | |
| BYTE $0xc0 | |
| WORD $SELECTOR(1, SELGDT, 0) | |
| MOVW AX,DS | |
| MOVW AX,SS | |
| MOVW AX,ES | |
| MOVW AX,FS | |
| MOVW AX,GS | |
| /* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/ | |
| BYTE $0x66 | |
| BYTE $0xEA | |
| LONG $mode32bit-KZERO(SB) | |
| WORD $SELECTOR(2, SELGDT, 0) | |
| TEXT mode32bit(SB),$0 | |
| #endif BOOT | |
| /* | |
| * Clear BSS | |
| */ | |
| LEAL edata-KZERO(SB),SI | |
| MOVL SI,DI | |
| ADDL $4,DI | |
| MOVL $0,AX | |
| MOVL AX,(SI) | |
| LEAL end-KZERO(SB),CX | |
| SUBL DI,CX | |
| SHRL $2,CX | |
| CLD; REP; MOVSL | |
| /* | |
| * make a bottom level page table page that maps the first | |
| * 16 meg of physical memory | |
| */ | |
| LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */ | |
| ADDL $(BY2PG-1),AX /* must be page alligned */ | |
| ANDL $(~(BY2PG-1)),AX /* ... */ | |
| MOVL $(4*1024),CX /* pte's per page */ | |
| MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX | |
| setpte: | |
| MOVL BX,-4(AX)(CX*4) | |
| SUBL $(1<<PGSHIFT),BX | |
| LOOP setpte | |
| /* | |
| * make a top level page table page that maps the first | |
| * 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg | |
| */ | |
| MOVL AX,BX | |
| ADDL $(4*BY2PG),AX | |
| ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX | |
| MOVL BX,0(AX) | |
| MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX) | |
| ADDL $BY2PG,BX | |
| MOVL BX,4(AX) | |
| MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX) | |
| ADDL $BY2PG,BX | |
| MOVL BX,8(AX) | |
| MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX) | |
| ADDL $BY2PG,BX | |
| MOVL BX,12(AX) | |
| MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX) | |
| /* | |
| * point processor to top level page & turn on paging | |
| */ | |
| MOVL AX,CR3 | |
| MOVL CR0,AX | |
| ORL $0X80000000,AX | |
| ANDL $~(0x8|0x2),AX /* TS=0, MP=0 */ | |
| MOVL AX,CR0 | |
| /* | |
| * use a jump to an absolute location to get the PC into | |
| * KZERO. | |
| */ | |
| LEAL tokzero(SB),AX | |
| JMP* AX | |
| TEXT tokzero(SB),$0 | |
| /* | |
| * stack and mach | |
| */ | |
| MOVL $mach0(SB),SP | |
| MOVL SP,m(SB) | |
| MOVL $0,0(SP) | |
| ADDL $(MACHSIZE-4),SP /* start stack under machine struct */ | |
| MOVL $0, u(SB) | |
| /* | |
| * clear flags | |
| */ | |
| MOVL $0,AX | |
| PUSHL AX | |
| POPFL | |
| CALL main(SB) | |
| loop: | |
| JMP loop | |
| GLOBL mach0+0(SB), $MACHSIZE | |
| GLOBL u(SB), $4 | |
| GLOBL m(SB), $4 | |
| GLOBL tpt(SB), $(BY2PG*6) | |
| /* | |
| * gdt to get us to 32-bit/segmented/unpaged mode | |
| */ | |
| TEXT tgdt(SB),$0 | |
| /* null descriptor */ | |
| LONG $0 | |
| LONG $0 | |
| /* data segment descriptor for 4 gigabytes (PL 0) */ | |
| LONG $(0xFFFF) | |
| LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW) | |
| /* exec segment descriptor for 4 gigabytes (PL 0) */ | |
| LONG $(0xFFFF) | |
| LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR) | |
| /* | |
| * pointer to initial gdt | |
| */ | |
| TEXT tgdtptr(SB),$0 | |
| WORD $(3*8) | |
| LONG $tgdt-KZERO(SB) | |
| /* | |
| * input a byte | |
| */ | |
| TEXT inb(SB),$0 | |
| MOVL p+0(FP),DX | |
| XORL AX,AX | |
| INB | |
| RET | |
| /* | |
| * output a byte | |
| */ | |
| TEXT outb(SB),$0 | |
| MOVL p+0(FP),DX | |
| MOVL b+4(FP),AX | |
| OUTB | |
| RET | |
| /* | |
| * input a string of shorts from a port | |
| */ | |
| TEXT inss(SB),$0 | |
| MOVL p+0(FP),DX | |
| MOVL a+4(FP),DI | |
| MOVL c+8(FP),CX | |
| CLD; REP; OP16; INSL | |
| RET | |
| /* | |
| * output a string of shorts to a port | |
| */ | |
| TEXT outss(SB),$0 | |
| MOVL p+0(FP),DX | |
| MOVL a+4(FP),SI | |
| MOVL c+8(FP),CX | |
| CLD; REP; OP16; OUTSL | |
| RET | |
| /* | |
| * test and set | |
| */ | |
| TEXT tas(SB),$0 | |
| MOVL $0xdeadead,AX | |
| MOVL l+0(FP),BX | |
| XCHGL AX,(BX) | |
| RET | |
| /* | |
| * routines to load/read various system registers | |
| */ | |
| GLOBL idtptr(SB),$6 | |
| TEXT putidt(SB),$0 /* interrupt descriptor table */ | |
| MOVL t+0(FP),AX | |
| MOVL AX,idtptr+2(SB) | |
| MOVL l+4(FP),AX | |
| MOVW AX,idtptr(SB) | |
| MOVL idtptr(SB),IDTR | |
| RET | |
| GLOBL gdtptr(SB),$6 | |
| TEXT putgdt(SB),$0 /* global descriptor table */ | |
| MOVL t+0(FP),AX | |
| MOVL AX,gdtptr+2(SB) | |
| MOVL l+4(FP),AX | |
| MOVW AX,gdtptr(SB) | |
| MOVL gdtptr(SB),GDTR | |
| RET | |
| TEXT putcr3(SB),$0 /* top level page table pointer */ | |
| MOVL t+0(FP),AX | |
| MOVL AX,CR3 | |
| RET | |
| TEXT puttr(SB),$0 /* task register */ | |
| MOVL t+0(FP),AX | |
| MOVW AX,TASK | |
| RET | |
| TEXT getcr0(SB),$0 /* coprocessor bits */ | |
| MOVL CR0,AX | |
| RET | |
| TEXT getcr2(SB),$0 /* fault address */ | |
| MOVL CR2,AX | |
| RET | |
| #define FPOFF\ | |
| WAIT;\ | |
| MOVL CR0,AX;\ | |
| ORL $0x4,AX /* EM=1 */;\ | |
| MOVL AX,CR0 | |
| #define FPON\ | |
| MOVL CR0,AX;\ | |
| ANDL $~0x4,AX /* EM=0 */;\ | |
| MOVL AX,CR0 | |
| TEXT fpoff(SB),$0 /* turn off floating point */ | |
| FPOFF | |
| RET | |
| TEXT fpinit(SB),$0 /* turn on & init the floating point */ | |
| FPON | |
| FINIT | |
| WAIT | |
| PUSHW $0x0330 | |
| FLDCW 0(SP) /* ignore underflow/precision, signal others */ | |
| POPW AX | |
| WAIT | |
| RET | |
| TEXT fpsave(SB),$0 /* save floating point state and turn off */ | |
| MOVL p+0(FP),AX | |
| WAIT | |
| FSAVE 0(AX) | |
| FPOFF | |
| RET | |
| TEXT fprestore(SB),$0 /* turn on floating point and restore regs */ | |
| FPON | |
| MOVL p+0(FP),AX | |
| FRSTOR 0(AX) | |
| WAIT | |
| RET | |
| TEXT fpstatus(SB),$0 /* get floating point status */ | |
| FSTSW AX | |
| RET | |
| /* | |
| * special traps | |
| */ | |
| TEXT intr0(SB),$0 | |
| PUSHL $0 | |
| PUSHL $0 | |
| JMP intrcommon | |
| TEXT intr1(SB),$0 | |
| PUSHL $0 | |
| PUSHL $1 | |
| JMP intrcommon | |
| TEXT intr2(SB),$0 | |
| PUSHL $0 | |
| PUSHL $2 | |
| JMP intrcommon | |
| TEXT intr3(SB),$0 | |
| PUSHL $0 | |
| PUSHL $3 | |
| JMP intrcommon | |
| TEXT intr4(SB),$0 | |
| PUSHL $0 | |
| PUSHL $4 | |
| JMP intrcommon | |
| TEXT intr5(SB),$0 | |
| PUSHL $0 | |
| PUSHL $5 | |
| JMP intrcommon | |
| TEXT intr6(SB),$0 | |
| PUSHL $0 | |
| PUSHL $6 | |
| JMP intrcommon | |
| TEXT intr7(SB),$0 | |
| PUSHL $0 | |
| PUSHL $7 | |
| JMP intrcommon | |
| TEXT intr8(SB),$0 | |
| PUSHL $8 | |
| JMP intrscommon | |
| TEXT intr9(SB),$0 | |
| PUSHL $0 | |
| PUSHL $9 | |
| JMP intrcommon | |
| TEXT intr10(SB),$0 | |
| PUSHL $10 | |
| JMP intrscommon | |
| TEXT intr11(SB),$0 | |
| PUSHL $11 | |
| JMP intrscommon | |
| TEXT intr12(SB),$0 | |
| PUSHL $12 | |
| JMP intrscommon | |
| TEXT intr13(SB),$0 | |
| PUSHL $13 | |
| JMP intrscommon | |
| TEXT intr14(SB),$0 | |
| PUSHL $14 | |
| JMP intrscommon | |
| TEXT intr15(SB),$0 | |
| PUSHL $0 | |
| PUSHL $15 | |
| JMP intrcommon | |
| TEXT intr16(SB),$0 | |
| PUSHL $0 | |
| PUSHL $16 | |
| JMP intrcommon | |
| TEXT intr24(SB),$0 | |
| PUSHL $0 | |
| PUSHL $24 | |
| JMP intrcommon | |
| TEXT intr25(SB),$0 | |
| PUSHL $0 | |
| PUSHL $25 | |
| JMP intrcommon | |
| TEXT intr26(SB),$0 | |
| PUSHL $0 | |
| PUSHL $26 | |
| JMP intrcommon | |
| TEXT intr27(SB),$0 | |
| PUSHL $0 | |
| PUSHL $27 | |
| JMP intrcommon | |
| TEXT intr28(SB),$0 | |
| PUSHL $0 | |
| PUSHL $28 | |
| JMP intrcommon | |
| TEXT intr29(SB),$0 | |
| PUSHL $0 | |
| PUSHL $29 | |
| JMP intrcommon | |
| TEXT intr30(SB),$0 | |
| PUSHL $0 | |
| PUSHL $30 | |
| JMP intrcommon | |
| TEXT intr31(SB),$0 | |
| PUSHL $0 | |
| PUSHL $31 | |
| JMP intrcommon | |
| TEXT intr32(SB),$0 | |
| PUSHL $0 | |
| PUSHL $16 | |
| JMP intrcommon | |
| TEXT intr33(SB),$0 | |
| PUSHL $0 | |
| PUSHL $33 | |
| JMP intrcommon | |
| TEXT intr34(SB),$0 | |
| PUSHL $0 | |
| PUSHL $34 | |
| JMP intrcommon | |
| TEXT intr35(SB),$0 | |
| PUSHL $0 | |
| PUSHL $35 | |
| JMP intrcommon | |
| TEXT intr36(SB),$0 | |
| PUSHL $0 | |
| PUSHL $36 | |
| JMP intrcommon | |
| TEXT intr37(SB),$0 | |
| PUSHL $0 | |
| PUSHL $37 | |
| JMP intrcommon | |
| TEXT intr38(SB),$0 | |
| PUSHL $0 | |
| PUSHL $38 | |
| JMP intrcommon | |
| TEXT intr39(SB),$0 | |
| PUSHL $0 | |
| PUSHL $39 | |
| JMP intrcommon | |
| TEXT intr64(SB),$0 | |
| PUSHL $0 | |
| PUSHL $64 | |
| JMP intrcommon | |
| TEXT intrbad(SB),$0 | |
| PUSHL $0 | |
| PUSHL $0x1ff | |
| JMP intrcommon | |
| intrcommon: | |
| PUSHL DS | |
| PUSHL ES | |
| PUSHL FS | |
| PUSHL GS | |
| PUSHAL | |
| MOVL $(KDSEL),AX | |
| MOVW AX,DS | |
| MOVW AX,ES | |
| LEAL 0(SP),AX | |
| PUSHL AX | |
| CALL trap(SB) | |
| POPL AX | |
| POPAL | |
| POPL GS | |
| POPL FS | |
| POPL ES | |
| POPL DS | |
| ADDL $8,SP /* error code and trap type */ | |
| IRETL | |
| intrscommon: | |
| PUSHL DS | |
| PUSHL ES | |
| PUSHL FS | |
| PUSHL GS | |
| PUSHAL | |
| MOVL $(KDSEL),AX | |
| MOVW AX,DS | |
| MOVW AX,ES | |
| LEAL 0(SP),AX | |
| PUSHL AX | |
| CALL trap(SB) | |
| POPL AX | |
| POPAL | |
| POPL GS | |
| POPL FS | |
| POPL ES | |
| POPL DS | |
| ADDL $8,SP /* error code and trap type */ | |
| IRETL | |
| /* | |
| * interrupt level is interrupts on or off | |
| */ | |
| TEXT spllo(SB),$0 | |
| PUSHFL | |
| POPL AX | |
| STI | |
| RET | |
| TEXT splhi(SB),$0 | |
| PUSHFL | |
| POPL AX | |
| CLI | |
| RET | |
| TEXT splx(SB),$0 | |
| MOVL s+0(FP),AX | |
| PUSHL AX | |
| POPFL | |
| RET | |
| /* | |
| * do nothing whatsoever till interrupt happens | |
| */ | |
| TEXT idle(SB),$0 | |
| HLT | |
| RET | |
| /* | |
| * label consists of a stack pointer and a PC | |
| */ | |
| TEXT gotolabel(SB),$0 | |
| MOVL l+0(FP),AX | |
| MOVL 0(AX),SP /* restore sp */ | |
| MOVL 4(AX),AX /* put return pc on the stack */ | |
| MOVL AX,0(SP) | |
| MOVL $1,AX /* return 1 */ | |
| RET | |
| TEXT setlabel(SB),$0 | |
| MOVL l+0(FP),AX | |
| MOVL SP,0(AX) /* store sp */ | |
| MOVL 0(SP),BX /* store return pc */ | |
| MOVL BX,4(AX) | |
| MOVL $0,AX /* return 0 */ | |
| RET | |
| /* | |
| * Used to get to the first process. | |
| * Set up an interrupt return frame and IRET to user level. | |
| */ | |
| TEXT touser(SB),$0 | |
| PUSHL $(UDSEL) /* old ss */ | |
| PUSHL $(USTKTOP) /* old sp */ | |
| PUSHFL /* old flags */ | |
| PUSHL $(UESEL) /* old cs */ | |
| PUSHL $(UTZERO+32) /* old pc */ | |
| MOVL $(UDSEL),AX | |
| MOVW AX,DS | |
| MOVW AX,ES | |
| MOVW AX,GS | |
| MOVW AX,FS | |
| IRETL | |
| /* | |
| * set configuration register | |
| */ | |
| TEXT config(SB),$0 | |
| MOVL l+0(FP),AX | |
| MOVL $0x3F3,DX | |
| OUTB | |
| OUTB | |
| RET |