summaryrefslogtreecommitdiff
path: root/src/cmd/8a/l.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/8a/l.s')
-rw-r--r--src/cmd/8a/l.s734
1 files changed, 734 insertions, 0 deletions
diff --git a/src/cmd/8a/l.s b/src/cmd/8a/l.s
new file mode 100644
index 0000000000..94479b8928
--- /dev/null
+++ b/src/cmd/8a/l.s
@@ -0,0 +1,734 @@
+// 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