diff options
Diffstat (limited to 'utils/ka/l.s')
| -rw-r--r-- | utils/ka/l.s | 696 |
1 files changed, 696 insertions, 0 deletions
diff --git a/utils/ka/l.s b/utils/ka/l.s new file mode 100644 index 00000000..b982e553 --- /dev/null +++ b/utils/ka/l.s @@ -0,0 +1,696 @@ +/* + * 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 */ + +/* + * PSR bits + */ +#define PSREC 0x00002000 +#define PSREF 0x00001000 +#define PSRSUPER 0x00000080 +#define PSRPSUPER 0x00000040 +#define PSRET 0x00000020 +#define SPL(n) (n<<8) + +/* + * Magic registers + */ + +#define MACH 6 /* R6 is m-> */ +#define USER 5 /* R5 is u-> */ + +/* + * Fundamental addresses + */ + +#define USERADDR 0xE0000000 +#define UREGADDR (USERADDR+BY2PG-((32+6)*BY2WD)) +#define BOOTSTACK (KTZERO-0*BY2PG) +#define TRAPS (KTZERO-2*BY2PG) + +/* + * MMU + */ + +#define VAMASK 0x3FFFFFFF +#define NPMEG (1<<12) +#define BY2SEGM (1<<18) +#define PG2SEGM (1<<6) +#define NTLBPID (1+NCONTEXT) /* TLBPID 0 is unallocated */ +#define NCONTEXT 8 +#define CONTEXT 0x30000000 /* in ASI 2 */ + +/* + * MMU regions + */ +#define INVALIDSEGM 0xFFFC0000 /* highest seg of VA reserved as invalid */ +#define INVALIDPMEG 0x7F +#define SCREENSEGM 0xFFF80000 +#define SCREENPMEG 0x7E +#define ROMSEGM 0xFFE80000 +#define ROMEND 0xFFEA0000 +#define PG2ROM ((ROMEND-ROMSEGM)/BY2PG) +#define IOSEGM0 ROMSEGM /* see mmuinit() */ +#define NIOSEGM ((SCREENSEGM-ROMSEGM)/BY2SEGM) +#define IOPMEG0 (SCREENPMEG-NIOSEGM) +#define IOSEGM ROMEND +#define IOEND SCREENSEGM +#define TOPPMEG IOPMEG0 + +/* + * MMU entries + */ +#define PTEVALID (1<<31) +#define PTERONLY (0<<30) +#define PTEWRITE (1<<30) +#define PTEKERNEL (1<<29) +#define PTENOCACHE (1<<28) +#define PTEMAINMEM (0<<26) +#define PTEIO (1<<26) +#define PTEACCESS (1<<25) +#define PTEMODIFY (1<<24) +#define PTEUNCACHED 0 +#define PTEMAPMEM (1024*1024) +#define PTEPERTAB (PTEMAPMEM/BY2PG) +#define SEGMAPSIZE 16 + +#define INVALIDPTE 0 +#define PPN(pa) ((pa>>12)&0xFFFF) + +/* + * Weird addresses in various ASI's + */ +#define CACHETAGS 0x80000000 /* ASI 2 */ +#define CACHEDATA 0x90000000 /* ASI 2 */ +#define SER 0x60000000 /* ASI 2 */ +#define SEVAR 0x60000004 /* ASI 2 */ +#define ASER 0x60000008 /* ASI 2 */ +#define ASEVAR 0x6000000C /* ASI 2 */ +#define ENAB 0x40000000 /* ASI 2 */ +#define ENABCACHE 0x10 +#define ENABRESET 0x04 + +/* + * Virtual addresses + */ +#define VTAG(va) ((va>>22)&0x03F) +#define VPN(va) ((va>>13)&0x1FF) + +#define PARAM ((char*)0x40500000) +#define TLBFLUSH_ 0x01 + +/* + * Address spaces + */ + +#define UZERO 0x00000000 /* base of user address space */ +#define UTZERO (UZERO+BY2PG) /* first address in user text */ +#define TSTKTOP 0x10000000 /* end of new stack in sysexec */ +#define TSTKSIZ 32 +#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */ +#define KZERO 0xE0000000 /* base of kernel address space */ +#define KTZERO (KZERO+4*BY2PG) /* first address in kernel text */ +#define USTKSIZE (4*1024*1024) /* size of user stack */ + +#define MACHSIZE 4096 + +#define isphys(x) (((ulong)(x)&0xF0000000) == KZERO) + +#define SYSPSR (SPL(0x0)|PSREF|PSRSUPER|0) +#define NOOP OR R0, R0; OR R0, R0; OR R0, R0 + +TEXT start(SB), $-4 + + /* get virtual, fast */ + /* we are executing in segment 0, mapped to pmeg 0. stack is there too */ + /* get virtual by mapping segment(KZERO) to pmeg 0., and next to 1 */ + MOVW $KZERO, R7 + MOVB R0, (R7, 3) + MOVW $(KZERO+BY2SEGM), R7 + MOVW $1, R8 + MOVB R8, (R7, 3) + /* now mapped correctly. jmpl to where we want to be */ + MOVW $setSB(SB), R2 + MOVW $startvirt(SB), R7 + JMPL (R7) + MOVW $_mul(SB), R0 /* touch _mul etc.; doesn't need to execute */ + RETURN /* can't get here */ + +TEXT startvirt(SB), $-4 + + MOVW $BOOTSTACK, R1 + + MOVW $(SPL(0xF)|PSREF|PSRSUPER), R7 + MOVW R7, PSR + + MOVW $(0x35<<22), R7 /* NVM OFM DZM AU */ + MOVW R7, fsr+0(SB) + MOVW fsr+0(SB), FSR + FMOVD $0.5, F26 /* 0.5 -> F26 */ + FSUBD F26, F26, F24 /* 0.0 -> F24 */ + FADDD F26, F26, F28 /* 1.0 -> F28 */ + FADDD F28, F28, F30 /* 2.0 -> F30 */ + + FMOVD F24, F0 + FMOVD F24, F2 + FMOVD F24, F4 + FMOVD F24, F6 + FMOVD F24, F8 + FMOVD F24, F10 + FMOVD F24, F12 + FMOVD F24, F14 + FMOVD F24, F16 + FMOVD F24, F18 + FMOVD F24, F20 + FMOVD F24, F22 + + MOVW $mach0(SB), R(MACH) +/* MOVW $0x8, R7 /**/ + MOVW R0, WIM + JMPL main(SB) + MOVW (R0), R0 + RETURN + +TEXT swap1(SB), $0 + + TAS (R7), R7 /* LDSTUB, thank you ken */ + RETURN + +TEXT swap1_should_work(SB), $0 + + MOVW R7, R8 + MOVW $1, R7 + SWAP (R8), R7 + RETURN + +TEXT swap1x(SB), $0 + + MOVW PSR, R9 + MOVW R9, R10 + AND $~PSRET, R10 /* BUG: book says this is buggy */ + MOVW R10, PSR + NOOP + MOVW (R7), R7 + CMP R7, R0 + BNE was1 + MOVW $1, R10 + MOVW R10, (R8) +was1: + MOVW R9, PSR + RETURN + +TEXT spllo(SB), $0 + + MOVW PSR, R7 + MOVW R7, R10 + OR $PSRET, R10 + MOVW R10, PSR + NOOP + RETURN + +TEXT splhi(SB), $0 + + MOVW R15, 4(R(MACH)) /* save PC in m->splpc */ + MOVW PSR, R7 + MOVW R7, R10 + AND $~PSRET, R10 /* BUG: book says this is buggy */ + MOVW R10, PSR + NOOP + RETURN + +TEXT splx(SB), $0 + + MOVW R15, 4(R(MACH)) /* save PC in m->splpc */ + MOVW R7, PSR /* BUG: book says this is buggy */ + NOOP + RETURN + +TEXT spldone(SB), $0 + + RETURN + +TEXT touser(SB), $0 + MOVW $(SYSPSR&~PSREF), R8 + MOVW R8, PSR + NOOP + + MOVW R7, R1 + SAVE R0, R0 /* RETT is implicit RESTORE */ + MOVW $(UTZERO+32), R7 /* PC; header appears in text */ + MOVW $(UTZERO+32+4), R8 /* nPC */ + RETT R7, R8 + +TEXT rfnote(SB), $0 + + MOVW R7, R1 /* 1st arg is &uregpointer */ + ADD $4, R1 /* point at ureg */ + JMP restore + +TEXT traplink(SB), $-4 + + /* R8 to R23 are free to play with */ + /* R17 contains PC, R18 contains nPC */ + /* R19 has PSR loaded from vector code */ + + ANDCC $PSRPSUPER, R19, R0 + BE usertrap + +kerneltrap: + /* + * Interrupt or fault from kernel + */ + ANDN $7, R1, R20 /* dbl aligned */ + MOVW R1, (0-(4*(32+6))+(4*1))(R20) /* save R1=SP */ + /* really clumsy: store these in Ureg so can be restored below */ + MOVW R2, (0-(4*(32+6))+(4*2))(R20) /* SB */ + MOVW R5, (0-(4*(32+6))+(4*5))(R20) /* USER */ + MOVW R6, (0-(4*(32+6))+(4*6))(R20) /* MACH */ + SUB $(4*(32+6)), R20, R1 + +trap1: + MOVW Y, R20 + MOVW R20, (4*(32+0))(R1) /* Y */ + MOVW TBR, R20 + MOVW R20, (4*(32+1))(R1) /* TBR */ + AND $~0x1F, R19 /* force CWP=0 */ + MOVW R19, (4*(32+2))(R1) /* PSR */ + MOVW R18, (4*(32+3))(R1) /* nPC */ + MOVW R17, (4*(32+4))(R1) /* PC */ + MOVW R0, (4*0)(R1) + MOVW R3, (4*3)(R1) + MOVW R4, (4*4)(R1) + MOVW R7, (4*7)(R1) + RESTORE R0, R0 + /* now our registers R8-R31 are same as before trap */ + /* save registers two at a time */ + MOVD R8, (4*8)(R1) + MOVD R10, (4*10)(R1) + MOVD R12, (4*12)(R1) + MOVD R14, (4*14)(R1) + MOVD R16, (4*16)(R1) + MOVD R18, (4*18)(R1) + MOVD R20, (4*20)(R1) + MOVD R22, (4*22)(R1) + MOVD R24, (4*24)(R1) + MOVD R26, (4*26)(R1) + MOVD R28, (4*28)(R1) + MOVD R30, (4*30)(R1) + /* SP and SB and u and m are already set; away we go */ + MOVW R1, R7 /* pointer to Ureg */ + SUB $8, R1 + MOVW $SYSPSR, R8 + MOVW R8, PSR + NOOP + JMPL trap(SB) + + ADD $8, R1 +restore: + MOVW (4*(32+2))(R1), R8 /* PSR */ + MOVW R8, PSR + NOOP + + MOVD (4*30)(R1), R30 + MOVD (4*28)(R1), R28 + MOVD (4*26)(R1), R26 + MOVD (4*24)(R1), R24 + MOVD (4*22)(R1), R22 + MOVD (4*20)(R1), R20 + MOVD (4*18)(R1), R18 + MOVD (4*16)(R1), R16 + MOVD (4*14)(R1), R14 + MOVD (4*12)(R1), R12 + MOVD (4*10)(R1), R10 + MOVD (4*8)(R1), R8 + SAVE R0, R0 + MOVD (4*6)(R1), R6 + MOVD (4*4)(R1), R4 + MOVD (4*2)(R1), R2 + MOVW (4*(32+0))(R1), R20 /* Y */ + MOVW R20, Y + MOVW (4*(32+4))(R1), R17 /* PC */ + MOVW (4*(32+3))(R1), R18 /* nPC */ + MOVW (4*1)(R1), R1 /* restore R1=SP */ + RETT R17, R18 + +usertrap: + /* + * Interrupt or fault from user + */ + MOVW R1, R8 + MOVW R2, R9 + MOVW $setSB(SB), R2 + MOVW $(USERADDR+BY2PG), R1 + MOVW R8, (0-(4*(32+6))+(4*1))(R1) /* save R1=SP */ + MOVW R9, (0-(4*(32+6))+(4*2))(R1) /* save R2=SB */ + MOVW R5, (0-(4*(32+6))+(4*5))(R1) /* save R5=USER */ + MOVW R6, (0-(4*(32+6))+(4*6))(R1) /* save R6=MACH */ + MOVW $USERADDR, R(USER) + MOVW $mach0(SB), R(MACH) + SUB $(4*(32+6)), R1 + JMP trap1 + +TEXT syslink(SB), $-4 + + /* R8 to R23 are free to play with */ + /* R17 contains PC, R18 contains nPC */ + /* R19 has PSR loaded from vector code */ + /* assume user did it; syscall checks */ + + MOVW R1, R8 + MOVW R2, R9 + MOVW $setSB(SB), R2 + MOVW $(USERADDR+BY2PG), R1 + MOVW R8, (0-(4*(32+6))+4)(R1) /* save R1=SP */ + SUB $(4*(32+6)), R1 + MOVW R9, (4*2)(R1) /* save R2=SB */ + MOVW R3, (4*3)(R1) /* global register */ + MOVD R4, (4*4)(R1) /* global register, R5=USER */ + MOVD R6, (4*6)(R1) /* save R6=MACH, R7=syscall# */ + MOVW $USERADDR, R(USER) + MOVW $mach0(SB), R(MACH) + MOVW TBR, R20 + MOVW R20, (4*(32+1))(R1) /* TBR */ + AND $~0x1F, R19 + MOVW R19, (4*(32+2))(R1) /* PSR */ + MOVW R18, (4*(32+3))(R1) /* nPC */ + MOVW R17, (4*(32+4))(R1) /* PC */ + RESTORE R0, R0 + /* now our registers R8-R31 are same as before trap */ + MOVW R15, (4*15)(R1) + /* SP and SB and u and m are already set; away we go */ + MOVW R1, R7 /* pointer to Ureg */ + SUB $8, R1 + MOVW $SYSPSR, R8 + MOVW R8, PSR + JMPL syscall(SB) + /* R7 contains return value from syscall */ + + ADD $8, R1 + MOVW (4*(32+2))(R1), R8 /* PSR */ + MOVW R8, PSR + NOOP + + MOVW (4*15)(R1), R15 + SAVE R0, R0 + MOVW (4*6)(R1), R6 + MOVD (4*4)(R1), R4 + MOVD (4*2)(R1), R2 + MOVW (4*(32+4))(R1), R17 /* PC */ + MOVW (4*(32+3))(R1), R18 /* nPC */ + MOVW (4*1)(R1), R1 /* restore R1=SP */ + RETT R17, R18 + +TEXT puttbr(SB), $0 + + MOVW R7, TBR + NOOP + RETURN + +TEXT gettbr(SB), $0 + + MOVW TBR, R7 + RETURN + +TEXT r1(SB), $0 + + MOVW R1, R7 + RETURN + +TEXT getwim(SB), $0 + + MOVW WIM, R7 + RETURN + +TEXT setlabel(SB), $0 + + MOVW R1, (R7) + MOVW R15, 4(R7) + MOVW $0, R7 + RETURN + +TEXT gotolabel(SB), $0 + + MOVW (R7), R1 + MOVW 4(R7), R15 + MOVW $1, R7 + RETURN + +TEXT putcxsegm(SB), $0 + + MOVW R7, R8 /* context */ + MOVW 4(FP), R9 /* segment addr */ + MOVW 8(FP), R10 /* segment value */ + MOVW $0xFFE80118, R7 + JMPL (R7) + RETURN + +TEXT getpsr(SB), $0 + + MOVW PSR, R7 + RETURN + +TEXT putcxreg(SB), $0 + + MOVW $CONTEXT, R8 + MOVB R7, (R8, 2) + RETURN + +TEXT putb2(SB), $0 + + MOVW 4(FP), R8 + MOVB R8, (R7, 2) + RETURN + +TEXT getb2(SB), $0 + + MOVB (R7, 2), R7 + RETURN + +TEXT getw2(SB), $0 + + MOVW (R7, 2), R7 + RETURN + +TEXT putw2(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 2) + RETURN + +TEXT putw4(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 4) + RETURN + +TEXT getw4(SB), $0 + + MOVW (R7, 4), R7 + RETURN + +TEXT putwC(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 0xC) + RETURN + +TEXT putwD(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 0xD) + RETURN + +TEXT putwD16(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xD) + RETURN + +TEXT putwE(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 0xE) + RETURN + +TEXT putwE16(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + ADD $(1<<4), R7 + MOVW R8, (R7, 0xE) + RETURN + +TEXT putsegm(SB), $0 + + MOVW 4(FP), R8 + MOVW R8, (R7, 3) + RETURN + +/* + * in savefpregs and restfpregs, incoming R7 points to doubleword + * below where F0 will go; doubleword align in and backfill FSR + */ +TEXT savefpregs(SB), $0 + + ADD $8, R7 + ANDN $7, R7 /* now MOVD-aligned */ + MOVW FSR, -4(R7) + + MOVD F0, (0*4)(R7) + MOVD F2, (2*4)(R7) + MOVD F4, (4*4)(R7) + MOVD F6, (6*4)(R7) + MOVD F8, (8*4)(R7) + MOVD F10, (10*4)(R7) + MOVD F12, (12*4)(R7) + MOVD F14, (14*4)(R7) + MOVD F16, (16*4)(R7) + MOVD F18, (18*4)(R7) + MOVD F20, (20*4)(R7) + MOVD F22, (22*4)(R7) + MOVD F24, (24*4)(R7) + MOVD F26, (26*4)(R7) + MOVD F28, (28*4)(R7) + MOVD F30, (30*4)(R7) + + MOVW PSR, R8 + ANDN $PSREF, R8 + MOVW R8, PSR + RETURN + +TEXT restfpregs(SB), $0 + + MOVW PSR, R8 + OR $PSREF, R8 + MOVW R8, PSR + + ADD $8, R7 + ANDN $7, R7 /* now MOVD-aligned */ + OR R0, R0 + + MOVW -4(R7), FSR + + MOVD (0*4)(R7), F0 + MOVD (2*4)(R7), F2 + MOVD (4*4)(R7), F4 + MOVD (6*4)(R7), F6 + MOVD (8*4)(R7), F8 + MOVD (10*4)(R7), F10 + MOVD (12*4)(R7), F12 + MOVD (14*4)(R7), F14 + MOVD (16*4)(R7), F16 + MOVD (18*4)(R7), F18 + MOVD (20*4)(R7), F20 + MOVD (22*4)(R7), F22 + MOVD (24*4)(R7), F24 + MOVD (26*4)(R7), F26 + MOVD (28*4)(R7), F28 + MOVD (30*4)(R7), F30 + + ANDN $PSREF, R8 + MOVW R8, PSR + RETURN + +TEXT clearfpintr(SB), $0 + + MOVW $fpq+BY2WD(SB), R7 + ANDN $0x7, R7 /* must be D aligned */ + MOVW $fsr+0(SB), R9 +clrq: + MOVD FQ, (R7) + MOVW FSR, (R9) + MOVW (R9), R8 + AND $(1<<13), R8 /* queue not empty? */ + BNE clrq + RETURN + +TEXT getfsr(SB), $0 + MOVW $fsr+0(SB), R7 + MOVW FSR, (R7) + MOVW (R7), R7 + RETURN + +GLOBL mach0+0(SB), $MACHSIZE +GLOBL fpq+0(SB), $(3*BY2WD) +GLOBL fsr+0(SB), $BY2WD |
