663 lines · 17.0 KB · Assembly
RawDownload
/* * non-startup assembly-language assist */ #include "mem.h"#include "/sys/src/boot/pc/x16.h"#undef DELAY #define PADDR(a)	((a) & ~KZERO)#define KADDR(a)	(KZERO|(a)) /* * Some machine instructions not handled by 8[al]. */#define OP16		BYTE $0x66#define DELAY		BYTE $0xEB; BYTE $0x00	/* JMP .+2 */#define CPUID		BYTE $0x0F; BYTE $0xA2	/* CPUID, argument in AX */#define WRMSR		BYTE $0x0F; BYTE $0x30	/* WRMSR, argument in AX/DX (lo/hi) */#define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */#define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */#define HLT		BYTE $0xF4#define INVLPG	BYTE $0x0F; BYTE $0x01; BYTE $0x39	/* INVLPG (%ecx) */#define WBINVD	BYTE $0x0F; BYTE $0x09 /* * Macros for calculating offsets within the page directory base * and page tables. Note that these are assembler-specific hence * the '<<2'. */#define PDO(a)		(((((a))>>22) & 0x03FF)<<2)#define PTO(a)		(((((a))>>12) & 0x03FF)<<2) TEXT pagingoff(SB), $0	DELAY				/* JMP .+2 */ 	/*	 *  use a jump to an absolute location to get the PC out of	 *  KZERO.  first establishes double mapping of first few MB.	 */	MOVL	CR3, CX				/* load address of PDB */	ADDL	$KZERO, CX	MOVL	PDO(KZERO)(CX), DX		/* double-map KZERO at 0 */	MOVL	DX, PDO(0)(CX) 	MOVL	CR3, CX	MOVL	CX, CR3				/* load and flush the mmu */ 	MOVL	  entry+0(FP), DX 	LEAL	_nopaging-KZERO(SB),AX	JMP*	AX				/* jump to identity-map */ TEXT _nopaging(SB), $0	DELAY				/* JMP .+2 */ 	/* switch to low stack */	MOVL	SP, AX	MOVL	$RMSTACK, SP//	PUSHL	AX 	/* change gdt to physical pointer */	MOVL	_gdtptr16r-KZERO(SB), GDTR 	/*	 * turn off paging	 */	MOVL	CR0,AX	ANDL	$~PG, AX	MOVL	AX,CR0	DELAY				/* JMP .+2 */ 	MOVL	$_stop32pg-KZERO(SB), AX	JMP*	AX				/* forward into the past */ TEXT _stop32pg(SB), $0	MOVL	multibootheader-KZERO(SB), BX	/* multiboot data pointer */	MOVL	$0x2badb002, AX			/* multiboot magic */ 	JMP*	DX				/* into the loaded kernel */ _idle:	HLT	JMP	_idle /* * BIOS32. */TEXT bios32call(SB), $0	MOVL	ci+0(FP), BP	MOVL	0(BP), AX	MOVL	4(BP), BX	MOVL	8(BP), CX	MOVL	12(BP), DX	MOVL	16(BP), SI	MOVL	20(BP), DI	PUSHL	BP 	MOVL	12(SP), BP			/* ptr */	BYTE $0xFF; BYTE $0x5D; BYTE $0x00	/* CALL FAR 0(BP) */ 	POPL	BP	MOVL	DI, 20(BP)	MOVL	SI, 16(BP)	MOVL	DX, 12(BP)	MOVL	CX, 8(BP)	MOVL	BX, 4(BP)	MOVL	AX, 0(BP) 	XORL	AX, AX	JCC	_bios32xxret	INCL	AX _bios32xxret:	RET TEXT cgapost2(SB), 0, $16	MOVL	$0xb8000,CX	MOVL	CX,(SP)	CALL	,kaddr+0(SB)	MOVL	code+0(FP),BP	MOVL	AX,BX	MOVL	BP,CX	SARL	$4,CX	ANDL	$15,CX	MOVBLZX	hex(SB)(CX*1),AX	MOVB	AX,3996(BX)	MOVB	$7,3997(BX)	MOVL	BP,DX	ANDL	$15,DX	MOVBLZX	hex(SB)(DX*1),CX	MOVB	CX,3998(BX)	MOVB	$7,3999(BX)	RET /* * Read/write various system registers. * CR4 and the 'model specific registers' should only be read/written * after it has been determined the processor supports them */TEXT ltr(SB), $0				/* TR - task register */	MOVL	tptr+0(FP), AX	MOVW	AX, TASK	RET TEXT invlpg(SB), $0	/* 486+ only */	MOVL	va+0(FP), CX	INVLPG	RET TEXT wbinvd(SB), $0	WBINVD	RET /* * stub for: * time stamp counter; low-order 32 bits of 64-bit cycle counter * Runs at fasthz/4 cycles per second (m->clkin>>3) */TEXT lcycles(SB),1,$0	RDTSC	RET /* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruction can be used * to determine CPU identity and features. First have to check if it's * a 386 (Ac bit can't be set). If it's not a 386 and the Id bit can't be * toggled then it's an older 486 of some kind. * *	cpuid(fun, regs[4]); */TEXT cpuid(SB), $0	MOVL	$0x240000, AX	PUSHL	AX	POPFL					/* set Id|Ac */	PUSHFL	POPL	BX				/* retrieve value */	MOVL	$0, AX	PUSHL	AX	POPFL					/* clear Id|Ac, EFLAGS initialised */	PUSHFL	POPL	AX				/* retrieve value */	XORL	BX, AX	TESTL	$0x040000, AX			/* Ac */	JZ	_cpu386				/* can't set this bit on 386 */	TESTL	$0x200000, AX			/* Id */	JZ	_cpu486				/* can't toggle this bit on some 486 */	MOVL	fn+0(FP), AX	CPUID	JMP	_cpuid_cpu486:	MOVL	$0x400, AX	JMP	_maybezapax_cpu386:	MOVL	$0x300, AX_maybezapax:	CMPL	fn+0(FP), $1	JE	_zaprest	XORL	AX, AX_zaprest:	XORL	BX, BX	XORL	CX, CX	XORL	DX, DX_cpuid:	MOVL	regs+4(FP), BP	MOVL	AX, 0(BP)	MOVL	BX, 4(BP)	MOVL	CX, 8(BP)	MOVL	DX, 12(BP)	RET /* * Floating point. * Note: the encodings for the FCLEX, FINIT, FSAVE, FSTCW, FSENV and FSTSW * instructions do NOT have the WAIT prefix byte (i.e. they act like their * FNxxx variations) so WAIT instructions must be explicitly placed in the * code as necessary. */#define	FPOFF(l)						 ;\	MOVL	CR0, AX 					 ;\	ANDL	$0xC, AX			/* EM, TS */	 ;\	CMPL	AX, $0x8					 ;\	JEQ 	l						 ;\	WAIT							 ;\l:								 ;\	MOVL	CR0, AX						 ;\	ANDL	$~0x4, AX			/* EM=0 */	 ;\	ORL	$0x28, AX			/* NE=1, TS=1 */ ;\	MOVL	AX, CR0 #define	FPON							 ;\	MOVL	CR0, AX						 ;\	ANDL	$~0xC, AX			/* EM=0, TS=0 */ ;\	MOVL	AX, CR0	TEXT fpoff(SB), $0				/* disable */	FPOFF(l1)	RET TEXT fpinit(SB), $0				/* enable and init */	FPON	FINIT	WAIT	/* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */	/* note that low 6 bits are masks, not enables, on this chip */	PUSHW	$0x0232	FLDCW	0(SP)	POPW	AX	WAIT	RET /* * Test-And-Set */TEXT tas(SB), $0	MOVL	$0xDEADDEAD, AX	MOVL	lock+0(FP), BX	XCHGL	AX, (BX)			/* lock->key */	RET TEXT _xinc(SB), $0				/* void _xinc(long*); */	MOVL	l+0(FP), AX	LOCK;	INCL 0(AX)	RET TEXT _xdec(SB), $0				/* long _xdec(long*); */	MOVL	l+0(FP), BX	XORL	AX, AX	LOCK;	DECL 0(BX)	JLT	_xdeclt	JGT	_xdecgt	RET_xdecgt:	INCL	AX	RET_xdeclt:	DECL	AX	RET TEXT xchgw(SB), $0	MOVL	v+4(FP), AX	MOVL	p+0(FP), BX	XCHGW	AX, (BX)	RET TEXT cmpswap486(SB), $0	MOVL	addr+0(FP), BX	MOVL	old+4(FP), AX	MOVL	new+8(FP), CX	LOCK	BYTE $0x0F; BYTE $0xB1; BYTE $0x0B	/* CMPXCHGL CX, (BX) */	JNZ didnt	MOVL	$1, AX	RETdidnt:	XORL	AX,AX	RET TEXT mul64fract(SB), $0/* * Multiply two 64-bit number s and keep the middle 64 bits from the 128-bit result * See ../port/tod.c for motivation. */	MOVL	r+0(FP), CX	XORL	BX, BX				/* BX = 0 */ 	MOVL	a+8(FP), AX	MULL	b+16(FP)			/* a1*b1 */	MOVL	AX, 4(CX)			/* r2 = lo(a1*b1) */ 	MOVL	a+8(FP), AX	MULL	b+12(FP)			/* a1*b0 */	MOVL	AX, 0(CX)			/* r1 = lo(a1*b0) */	ADDL	DX, 4(CX)			/* r2 += hi(a1*b0) */ 	MOVL	a+4(FP), AX	MULL	b+16(FP)			/* a0*b1 */	ADDL	AX, 0(CX)			/* r1 += lo(a0*b1) */	ADCL	DX, 4(CX)			/* r2 += hi(a0*b1) + carry */ 	MOVL	a+4(FP), AX	MULL	b+12(FP)			/* a0*b0 */	ADDL	DX, 0(CX)			/* r1 += hi(a0*b0) */	ADCL	BX, 4(CX)			/* r2 += carry */	RET /* *  label consists of a stack pointer and a PC */TEXT gotolabel(SB), $0	MOVL	label+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	label+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 /* * Attempt at power saving. -rsc */TEXT halt(SB), $0	CLI					/* interrupts off */	CMPL	nrdy(SB), $0	JEQ	_nothingready	STI					/* interrupts on */	RET _nothingready:	STI			/* interrupts on: service before rescheduling */	HLT	RET /* * Interrupt/exception handling. * Each entry in the vector table calls either _strayintr or _strayintrx depending * on whether an error code has been automatically pushed onto the stack * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving * the trap type from the vector table entry and placing it on the stack as part * of the Ureg structure. * The size of each entry in the vector table (6 bytes) is known in trapinit(). */TEXT _strayintr(SB), $0	PUSHL	AX			/* save AX */	MOVL	4(SP), AX		/* return PC from vectortable(SB) */	JMP	intrcommon TEXT _strayintrx(SB), $0	XCHGL	AX, (SP)		/* swap AX with vectortable CALL PC */intrcommon:	PUSHL	DS			/* save DS */	PUSHL	$(KDSEL)	POPL	DS			/* fix up DS */	MOVBLZX	(AX), AX		/* trap type -> AX */	XCHGL	AX, 4(SP)		/* exchange trap type with saved AX */ 	PUSHL	ES			/* save ES */	PUSHL	$(KDSEL)	POPL	ES			/* fix up ES */ 	PUSHL	FS			/* save the rest of the Ureg struct */	PUSHL	GS	PUSHAL 	PUSHL	SP			/* Ureg* argument to trap */	CALL	trap(SB) TEXT forkret(SB), $0	POPL	AX	POPAL	POPL	GS	POPL	FS	POPL	ES	POPL	DS	ADDL	$8, SP			/* pop error code and trap type */	IRETL TEXT vectortable(SB), $0	CALL _strayintr(SB); BYTE $0x00		/* divide error */	CALL _strayintr(SB); BYTE $0x01		/* debug exception */	CALL _strayintr(SB); BYTE $0x02		/* NMI interrupt */	CALL _strayintr(SB); BYTE $0x03		/* breakpoint */	CALL _strayintr(SB); BYTE $0x04		/* overflow */	CALL _strayintr(SB); BYTE $0x05		/* bound */	CALL _strayintr(SB); BYTE $0x06		/* invalid opcode */	CALL _strayintr(SB); BYTE $0x07		/* no coprocessor available */	CALL _strayintrx(SB); BYTE $0x08	/* double fault */	CALL _strayintr(SB); BYTE $0x09		/* coprocessor segment overflow */	CALL _strayintrx(SB); BYTE $0x0A	/* invalid TSS */	CALL _strayintrx(SB); BYTE $0x0B	/* segment not available */	CALL _strayintrx(SB); BYTE $0x0C	/* stack exception */	CALL _strayintrx(SB); BYTE $0x0D	/* general protection error */	CALL _strayintrx(SB); BYTE $0x0E	/* page fault */	CALL _strayintr(SB); BYTE $0x0F		/*  */	CALL _strayintr(SB); BYTE $0x10		/* coprocessor error */	CALL _strayintrx(SB); BYTE $0x11	/* alignment check */	CALL _strayintr(SB); BYTE $0x12		/* machine check */	CALL _strayintr(SB); BYTE $0x13	CALL _strayintr(SB); BYTE $0x14	CALL _strayintr(SB); BYTE $0x15	CALL _strayintr(SB); BYTE $0x16	CALL _strayintr(SB); BYTE $0x17	CALL _strayintr(SB); BYTE $0x18	CALL _strayintr(SB); BYTE $0x19	CALL _strayintr(SB); BYTE $0x1A	CALL _strayintr(SB); BYTE $0x1B	CALL _strayintr(SB); BYTE $0x1C	CALL _strayintr(SB); BYTE $0x1D	CALL _strayintr(SB); BYTE $0x1E	CALL _strayintr(SB); BYTE $0x1F	CALL _strayintr(SB); BYTE $0x20		/* VectorLAPIC */	CALL _strayintr(SB); BYTE $0x21	CALL _strayintr(SB); BYTE $0x22	CALL _strayintr(SB); BYTE $0x23	CALL _strayintr(SB); BYTE $0x24	CALL _strayintr(SB); BYTE $0x25	CALL _strayintr(SB); BYTE $0x26	CALL _strayintr(SB); BYTE $0x27	CALL _strayintr(SB); BYTE $0x28	CALL _strayintr(SB); BYTE $0x29	CALL _strayintr(SB); BYTE $0x2A	CALL _strayintr(SB); BYTE $0x2B	CALL _strayintr(SB); BYTE $0x2C	CALL _strayintr(SB); BYTE $0x2D	CALL _strayintr(SB); BYTE $0x2E	CALL _strayintr(SB); BYTE $0x2F	CALL _strayintr(SB); BYTE $0x30	CALL _strayintr(SB); BYTE $0x31	CALL _strayintr(SB); BYTE $0x32	CALL _strayintr(SB); BYTE $0x33	CALL _strayintr(SB); BYTE $0x34	CALL _strayintr(SB); BYTE $0x35	CALL _strayintr(SB); BYTE $0x36	CALL _strayintr(SB); BYTE $0x37	CALL _strayintr(SB); BYTE $0x38	CALL _strayintr(SB); BYTE $0x39	CALL _strayintr(SB); BYTE $0x3A	CALL _strayintr(SB); BYTE $0x3B	CALL _strayintr(SB); BYTE $0x3C	CALL _strayintr(SB); BYTE $0x3D	CALL _strayintr(SB); BYTE $0x3E	CALL _strayintr(SB); BYTE $0x3F//	CALL _syscallintr(SB); BYTE $0x40	/* VectorSYSCALL */	CALL _strayintr(SB); BYTE $0x40	CALL _strayintr(SB); BYTE $0x41	CALL _strayintr(SB); BYTE $0x42	CALL _strayintr(SB); BYTE $0x43	CALL _strayintr(SB); BYTE $0x44	CALL _strayintr(SB); BYTE $0x45	CALL _strayintr(SB); BYTE $0x46	CALL _strayintr(SB); BYTE $0x47	CALL _strayintr(SB); BYTE $0x48	CALL _strayintr(SB); BYTE $0x49	CALL _strayintr(SB); BYTE $0x4A	CALL _strayintr(SB); BYTE $0x4B	CALL _strayintr(SB); BYTE $0x4C	CALL _strayintr(SB); BYTE $0x4D	CALL _strayintr(SB); BYTE $0x4E	CALL _strayintr(SB); BYTE $0x4F	CALL _strayintr(SB); BYTE $0x50	CALL _strayintr(SB); BYTE $0x51	CALL _strayintr(SB); BYTE $0x52	CALL _strayintr(SB); BYTE $0x53	CALL _strayintr(SB); BYTE $0x54	CALL _strayintr(SB); BYTE $0x55	CALL _strayintr(SB); BYTE $0x56	CALL _strayintr(SB); BYTE $0x57	CALL _strayintr(SB); BYTE $0x58	CALL _strayintr(SB); BYTE $0x59	CALL _strayintr(SB); BYTE $0x5A	CALL _strayintr(SB); BYTE $0x5B	CALL _strayintr(SB); BYTE $0x5C

Lines 1–500 of 663.