📄 locore.s
字号:
pflusha | flush entire TLB#if defined(HP360) || defined(HP370) jpl Lmc68851a | 68851 implies no d-cache movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cacheLmc68851a:#endif rtsLhpmmu6:#endif#if defined(HP320) || defined(HP350) MMUADDR(a0) movl a0@(MMUTBINVAL),sp@- | do not ask me, this addql #4,sp | is how hpux does it#ifdef DEBUG tstl fullcflush jne __DCIA | XXX: invalidate entire cache#endif#endif rts/* * Invalidate any TLB entry for given VA (TB Invalidate Single) */ENTRY(TBIS)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush entire TLB#endif#if defined(HP380) cmpl #-2,_mmutype | 68040? jne Lmotommu4 | no, skip movl sp@(4),a0 movc dfc,d1 moveq #1,d0 | user space movc d0,dfc .word 0xf508 | pflush a0@ moveq #5,d0 | super space movc d0,dfc .word 0xf508 | pflush a0@ movc d1,dfc rtsLmotommu4:#endif#if defined(HP330) || defined(HP360) || defined(HP370) tstl _mmutype | HP MMU? jeq Lhpmmu5 | yes, skip movl sp@(4),a0 | get addr to flush#if defined(HP360) || defined(HP370) jpl Lmc68851b | is 68851? pflush #0,#0,a0@ | flush address from both sides movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip data cache rtsLmc68851b:#endif pflushs #0,#0,a0@ | flush address from both sides rtsLhpmmu5:#endif#if defined(HP320) || defined(HP350) movl sp@(4),d0 | VA to invalidate bclr #0,d0 | ensure even movl d0,a0 movw sr,d1 | go critical movw #PSL_HIGHIPL,sr | while in purge space moveq #FC_PURGE,d0 | change address space movc d0,dfc | for destination moveq #0,d0 | zero to invalidate? movsl d0,a0@ | hit it moveq #FC_USERD,d0 | back to old movc d0,dfc | address space movw d1,sr | restore IPL#endif rts/* * Invalidate supervisor side of TLB */ENTRY(TBIAS)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush everything#endif#if defined(HP380) cmpl #-2,_mmutype | 68040? jne Lmotommu5 | no, skip .word 0xf518 | yes, pflusha (for now) XXX rtsLmotommu5:#endif#if defined(HP330) || defined(HP360) || defined(HP370) tstl _mmutype | HP MMU? jeq Lhpmmu7 | yes, skip#if defined(HP360) || defined(HP370) jpl Lmc68851c | 68851? pflush #4,#4 | flush supervisor TLB entries movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rtsLmc68851c:#endif pflushs #4,#4 | flush supervisor TLB entries rtsLhpmmu7:#endif#if defined(HP320) || defined(HP350) MMUADDR(a0) movl #0x8000,d0 | more movl d0,a0@(MMUTBINVAL) | HP magic#ifdef DEBUG tstl fullcflush jne __DCIS | XXX: invalidate entire sup. cache#endif#endif rts/* * Invalidate user side of TLB */ENTRY(TBIAU)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush everything#endif#if defined(HP380) cmpl #-2,_mmutype | 68040? jne Lmotommu6 | no, skip .word 0xf518 | yes, pflusha (for now) XXX rtsLmotommu6:#endif#if defined(HP330) || defined(HP360) || defined(HP370) tstl _mmutype | HP MMU? jeq Lhpmmu8 | yes, skip#if defined(HP360) || defined(HP370) jpl Lmc68851d | 68851? pflush #0,#4 | flush user TLB entries movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rtsLmc68851d:#endif pflushs #0,#4 | flush user TLB entries rtsLhpmmu8:#endif#if defined(HP320) || defined(HP350) MMUADDR(a0) moveq #0,d0 | more movl d0,a0@(MMUTBINVAL) | HP magic#ifdef DEBUG tstl fullcflush jne __DCIU | XXX: invalidate entire user cache#endif#endif rts/* * Invalidate instruction cache */ENTRY(ICIA)#if defined(HP380)ENTRY(ICPA) cmpl #-2,_mmutype | 68040 jne Lmotommu7 | no, skip .word 0xf498 | cinva ic rtsLmotommu7:#endif movl #IC_CLEAR,d0 movc d0,cacr | invalidate i-cache rts/* * Invalidate data cache. * HP external cache allows for invalidation of user/supervisor portions. * NOTE: we do not flush 68030 on-chip cache as there are no aliasing * problems with DC_WA. The only cases we have to worry about are context * switch and TLB changes, both of which are handled "in-line" in resume * and TBI*. */ENTRY(DCIA)__DCIA:#if defined(HP380) cmpl #-2,_mmutype | 68040 jne Lmotommu8 | no, skip /* XXX implement */ rtsLmotommu8:#endif#if defined(HP320) || defined(HP350) tstl _ectype | got external VAC? jle Lnocache2 | no, all done MMUADDR(a0) andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control regLnocache2:#endif rtsENTRY(DCIS)__DCIS:#if defined(HP380) cmpl #-2,_mmutype | 68040 jne Lmotommu9 | no, skip /* XXX implement */ rtsLmotommu9:#endif#if defined(HP320) || defined(HP350) tstl _ectype | got external VAC? jle Lnocache3 | no, all done MMUADDR(a0) movl a0@(MMUSSTP),d0 | read the supervisor STP movl d0,a0@(MMUSSTP) | write it backLnocache3:#endif rtsENTRY(DCIU)__DCIU:#if defined(HP380) cmpl #-2,_mmutype | 68040 jne LmotommuA | no, skip /* XXX implement */ rtsLmotommuA:#endif#if defined(HP320) || defined(HP350) tstl _ectype | got external VAC? jle Lnocache4 | no, all done MMUADDR(a0) movl a0@(MMUUSTP),d0 | read the user STP movl d0,a0@(MMUUSTP) | write it backLnocache4:#endif rts#if defined(HP380)ENTRY(ICPL) movl sp@(4),a0 | address .word 0xf488 | cinvl ic,a0@ rtsENTRY(ICPP) movl sp@(4),a0 | address .word 0xf490 | cinvp ic,a0@ rtsENTRY(DCPL) movl sp@(4),a0 | address .word 0xf448 | cinvl dc,a0@ rtsENTRY(DCPP) movl sp@(4),a0 | address .word 0xf450 | cinvp dc,a0@ rtsENTRY(DCPA) .word 0xf458 | cinva dc rtsENTRY(DCFL) movl sp@(4),a0 | address .word 0xf468 | cpushl dc,a0@ rtsENTRY(DCFP) movl sp@(4),a0 | address .word 0xf470 | cpushp dc,a0@ rts#endifENTRY(PCIA)#if defined(HP380)ENTRY(DCFA) cmpl #-2,_mmutype | 68040 jne LmotommuB | no, skip .word 0xf478 | cpusha dc rtsLmotommuB:#endif#if defined(HP360) || defined(HP370) movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache tstl _ectype | got external PAC? jge Lnocache6 | no, all done MMUADDR(a0) andl #~MMU_CEN,a0@(MMUCMD) | disable cache in MMU control reg orl #MMU_CEN,a0@(MMUCMD) | reenable cache in MMU control regLnocache6:#endif rtsENTRY(ecacheon) tstl _ectype jeq Lnocache7 MMUADDR(a0) orl #MMU_CEN,a0@(MMUCMD)Lnocache7: rtsENTRY(ecacheoff) tstl _ectype jeq Lnocache8 MMUADDR(a0) andl #~MMU_CEN,a0@(MMUCMD)Lnocache8: rts/* * Get callers current SP value. * Note that simply taking the address of a local variable in a C function * doesn't work because callee saved registers may be outside the stack frame * defined by A6 (e.g. GCC generated code). */ .globl _getsp_getsp: movl sp,d0 | get current SP addql #4,d0 | compensate for return address rts .globl _getsfc, _getdfc_getsfc: movc sfc,d0 rts_getdfc: movc dfc,d0 rts/* * Load a new user segment table pointer. */ENTRY(loadustp)#if defined(HP330) || defined(HP360) || defined(HP370) || defined(HP380) tstl _mmutype | HP MMU? jeq Lhpmmu9 | yes, skip movl sp@(4),d0 | new USTP moveq #PGSHIFT,d1 lsll d1,d0 | convert to addr#if defined(HP380) cmpl #-2,_mmutype | 68040? jne LmotommuC | no, skip .long 0x4e7b0806 | movc d0,urp rtsLmotommuC:#endif lea _protorp,a0 | CRP prototype movl d0,a0@(4) | stash USTP pmove a0@,crp | load root pointer movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rts | since pmove flushes TLBLhpmmu9:#endif#if defined(HP320) || defined(HP350) MMUADDR(a0) movl sp@(4),a0@(MMUUSTP) | load a new USTP#endif rtsENTRY(ploadw)#if defined(HP330) || defined(HP360) || defined(HP370) movl sp@(4),a0 | address to load ploadw #1,a0@ | pre-load translation#endif rts/* * Set processor priority level calls. Most are implemented with * inline asm expansions. However, spl0 requires special handling * as we need to check for our emulated software interrupts. */ENTRY(spl0) moveq #0,d0 movw sr,d0 | get old SR for return movw #PSL_LOWIPL,sr | restore new SR tstb _ssir | software interrupt pending? jeq Lspldone | no, all done subql #4,sp | make room for RTE frame movl sp@(4),sp@(2) | position return address clrw sp@(6) | set frame type 0 movw #PSL_LOWIPL,sp@ | and new SR jra Lgotsir | go handle itLspldone: rtsENTRY(_insque) movw sr,d0 movw #PSL_HIGHIPL,sr | atomic movl sp@(8),a0 | where to insert (after) movl sp@(4),a1 | element to insert (e) movl a0@,a1@ | e->next = after->next movl a0,a1@(4) | e->prev = after movl a1,a0@ | after->next = e movl a1@,a0 movl a1,a0@(4) | e->next->prev = e movw d0,sr rtsENTRY(_remque) movw sr,d0 movw #PSL_HIGHIPL,sr | atomic movl sp@(4),a0 | element to remove (e) movl a0@,a1 movl a0@(4),a0 movl a0,a1@(4) | e->next->prev = e->prev movl a1,a0@ | e->prev->next = e->next movw d0,sr rts/* * bzero(addr, count) */ALTENTRY(blkclr, _bzero)ENTRY(bzero) movl sp@(4),a0 | address movl sp@(8),d0 | count jeq Lbzdone | if zero, nothing to do movl a0,d1 btst #0,d1 | address odd? jeq Lbzeven | no, can copy words clrb a0@+ | yes, zero byte to get to even boundary subql #1,d0 | decrement count jeq Lbzdone | none left, all doneLbzeven: movl d0,d1 andl #31,d0 lsrl #5,d1 | convert count to 8*longword count jeq Lbzbyte | no such blocks, zero byte at a timeLbzloop: clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; clrl a0@+; subql #1,d1 | one more block zeroed jne Lbzloop | more to go, do it tstl d0 | partial block left? jeq Lbzdone | no, all doneLbzbyte: clrb a0@+ subql #1,d0 | one more byte cleared jne Lbzbyte | more to go, do itLbzdone: rts/* * strlen(str) */ENTRY(strlen) moveq #-1,d0 movl sp@(4),a0 | stringLslloop: addql #1,d0 | increment count tstb a0@+ | null? jne Lslloop | no, keep going rts/* * bcmp(s1, s2, len) * * WARNING! This guy only works with counts up to 64K */ENTRY(bcmp) movl sp@(4),a0 | string 1 movl sp@(8),a1 | string 2 moveq #0,d0 movw sp@(14),d0 | length jeq Lcmpdone | if zero, nothing to do subqw #1,d0 | set up for DBcc loopLcmploop: cmpmb a0@+,a1@+ | equal? dbne d0,Lcmploop | yes, keep going addqw #1,d0 | +1 gives zero on matchLcmpdone: rts /* * {ov}bcopy(from, to, len) * * Works for counts up to 128K. */ALTENTRY(ovbcopy, _bcopy)ENTRY(bcopy) movl sp@(12),d0 | get count jeq Lcpyexit | if zero, return movl sp@(4),a0 | src address movl sp@(8),a1 | dest address cmpl a1,a0 | src before dest? jlt Lcpyback | yes, copy backwards (avoids overlap) movl a0,d1 btst #0,d1 | src address odd? jeq Lcfeven | no, go check dest movb a0@+,a1@+ | yes, copy a byte subql #1,d0 | update count jeq Lcpyexit | exit if doneLcfeven: movl a1,d1 btst #0,d1 | dest address odd? jne Lcfbyte | yes, must copy by bytes movl d0,d1 | no, get count l
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -