📄 locore.s
字号:
* 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) movl sp@(4),d0 | new USTP moveq #PGSHIFT,d1 lsll d1,d0 | convert to addr#if defined(LUNA2) 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 rtsENTRY(ploadw) movl sp@(4),a0 | address to load ploadw #1,a0@ | pre-load translation 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 lsrl #2,d1 | convert to longwords jeq Lcfbyte | no longwords, copy bytes subql #1,d1 | set up for dbfLcflloop: movl a0@+,a1@+ | copy longwords dbf d1,Lcflloop | til done andl #3,d0 | get remaining count jeq Lcpyexit | done if noneLcfbyte: subql #1,d0 | set up for dbfLcfbloop: movb a0@+,a1@+ | copy bytes dbf d0,Lcfbloop | til doneLcpyexit: rtsLcpyback: addl d0,a0 | add count to src addl d0,a1 | add count to dest movl a0,d1 btst #0,d1 | src address odd? jeq Lcbeven | no, go check dest movb a0@-,a1@- | yes, copy a byte subql #1,d0 | update count jeq Lcpyexit | exit if doneLcbeven: movl a1,d1 btst #0,d1 | dest address odd? jne Lcbbyte | yes, must copy by bytes movl d0,d1 | no, get count lsrl #2,d1 | convert to longwords jeq Lcbbyte | no longwords, copy bytes subql #1,d1 | set up for dbfLcblloop: movl a0@-,a1@- | copy longwords dbf d1,Lcblloop | til done andl #3,d0 | get remaining count jeq Lcpyexit | done if noneLcbbyte: subql #1,d0 | set up for dbfLcbbloop: movb a0@-,a1@- | copy bytes dbf d0,Lcbbloop | til done rts/* * Emulate fancy VAX string operations: * scanc(count, startc, table, mask) * skpc(mask, count, startc) * locc(mask, count, startc) */ENTRY(scanc) movl sp@(4),d0 | get length jeq Lscdone | nothing to do, return movl sp@(8),a0 | start of scan movl sp@(12),a1 | table to compare with movb sp@(19),d1 | and mask to use movw d2,sp@- | need a scratch register clrw d2 | clear it out subqw #1,d0 | adjust for dbraLscloop: movb a0@+,d2 | get character movb a1@(0,d2:w),d2 | get table entry andb d1,d2 | mask it dbne d0,Lscloop | keep going til no more or non-zero addqw #1,d0 | overshot by one movw sp@+,d2 | restore scratchLscdone: rtsENTRY(skpc) movl sp@(8),d0 | get length jeq Lskdone | nothing to do, return movb sp@(7),d1 | mask to use movl sp@(12),a0 | where to start subqw #1,d0 | adjust for dbccLskloop: cmpb a0@+,d1 | compate with mask dbne d0,Lskloop | keep going til no more or zero addqw #1,d0 | overshot by oneLskdone: rtsENTRY(locc) movl sp@(8),d0 | get length jeq Llcdone | nothing to do, return movb sp@(7),d1 | mask to use movl sp@(12),a0 | where to start subqw #1,d0 | adjust for dbccLlcloop: cmpb a0@+,d1 | compate with mask dbeq d0,Llcloop | keep going til no more or non-zero addqw #1,d0 | overshot by oneLlcdone: rts/* * Emulate VAX FFS (find first set) instruction. */ENTRY(ffs) moveq #-1,d0 movl sp@(4),d1 jeq LffsdoneLffsloop: addql #1,d0 btst d0,d1 jeq LffsloopLffsdone: addql #1,d0 rts#ifdef FPCOPROC/* * Save and restore 68881 state. * Pretty awful looking since our assembler does not * recognize FP mnemonics. */ENTRY(m68881_save) movl sp@(4),a0 | save area pointer fsave a0@ | save state tstb a0@ | null state frame? jeq Lm68881sdone | yes, all done fmovem fp0-fp7,a0@(216) | save FP general registers fmovem fpcr/fpsr/fpi,a0@(312) | save FP control registersLm68881sdone: rtsENTRY(m68881_restore) movl sp@(4),a0 | save area pointer tstb a0@ | null state frame? jeq Lm68881rdone | yes, easy fmovem a0@(312),fpcr/fpsr/fpi | restore FP control registers fmovem a0@(216),fp0-fp7 | restore FP general registersLm68881rdone: frestore a0@ | restore state rts/* LUNA */ .globl _fpp_svarea/* Fpp is MC68882 ? */ENTRY(is_68882) frestore _fppnull | initialize fpp movl #2,d0 fmovecr #0,fp1 fsinx fp1,fp2 lea _fpp_svarea,a0 | save area movw sr,d1 | save status reg. movw #0x2700,sr | mask intrrupt fsave a0@ | save fpp context movw d1,sr | restore status reg. movl a0@,d1 andl #0x00ff0000,d1 | check status field cmpl #0x00180000,d1 | 68881(idle)? beq _is81 cmpl #0x00b40000,d1 | 68881(busy)? beq _is81 cmpl #0x00380000,d1 | 68882(idle)? beq _is82 cmpl #0x00d40000,d1 | 68882(busy)? beq _is82 bra _is82out | default 68881_is81: clrl d0 bra _is82out_is82: movl #1,d0_is82out: frestore a0@ rts#ifdef OLD_LUNA/* We have fpp ? */ENTRY(havefpp) movl a2,sp@- clrl d0 movl vb,a2 movl a2@(FLINE_VEC),a0 | save vectors movl a2@(COPRO_VEC),a1 movl sp,d1 movl #_fpvec,a2@(FLINE_VEC) | change vectors movl #_fpvec,a2@(COPRO_VEC) fnop | cause exception ? movl #1,d0_fpvec: movl a0,a2@(FLINE_VEC) | restore vectors movl a1,a2@(COPRO_VEC) movl d1,sp movl sp@+,a2 rts#endif#endif/* * Handle the nitty-gritty of rebooting the machine. * Basically we just turn off the MMU and jump to the appropriate ROM routine. * Note that we must be running in an address range that is mapped one-to-one * logical to physical so that the PC is still valid immediately after the MMU * is turned off. We have conveniently mapped the last page of physical * memory this way. */ .globl _doboot_doboot: movl #0x41000004,a0 movl a0@,a1 | get PROM restart entry address#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne LmotommuF | no, skip movw #PSL_HIGHIPL,sr | no interrupts movl #0x41000000,a0 movl a0@,d0 movc d0,isp | set ISP .word 0xf4f8 | cpusha bc movl #0,d0 movc d0,cacr | caches off movql #0,d0 .long 0x4e7b0004 | movc d0,itt0 .long 0x4e7b0005 | movc d0,itt1 .long 0x4e7b0006 | movc d0,dtt0 .long 0x4e7b0007 | movc d0,dtt1 .long 0x4e7b0003 | movc d0,tc jmp a1@ | goto REBOOTLmotommuF:#endif movl #CACHE_OFF,d0 movc d0,cacr | disable on-chip cache(s) movl #_tcroff,a0 | value for pmove to TC (turn off MMU) pmove a0@,tc | disable MMU jmp a1@ | goto REBOOT .data .globl _machineid,_mmutype_machineid: .long 1 | default to LUNA-I_mmutype: .long -1 | default to 68030 PMMU .globl _protorp,_protott0,_protott1_protorp: .long 0,0 | prototype root pointer_protott0: .long 0x403f8543 | tt0 (for LUNA1 kernel 0x40000000-0x7fffffff)_protott1: .long 0x807F8543 | tt1 (for LUNA1 kernel 0x80000000-0xffffffff)_mapping_tc: .long 0 .globl _cold_cold: .long 1 | cold start flag .globl _want_resched_want_resched: .long 0 .globl _proc0paddr_proc0paddr: .long 0 | KVA of proc0 u-area .globl _tcroff_tcroff: .long 0 | TC reg. reset flag#ifdef FPCOPROC .globl _fppnull_fppnull: .long 0#endif .globl _clock_on_clock_on: .long 0 | clock is enable ? .globl _dipswitch_dipswitch: .word 0 | dipsw(front panel) value .globl _KernInter_KernInter: | Kernel InterFace Field .space KIFF_SIZE#ifdef DEBUG .globl fulltflush, fullcflushfulltflush: .long 0fullcflush: .long 0#endif#ifdef HPFPLIB/* * Undefined symbols from hpux_float.o: * * kdb_printf: A kernel debugger print routine, we just use printf instead. * processor: HP-UX equiv. of machineid, set to 3 if it is a 68040. * u: Ye ole u-area. The code wants to grab the first longword * indirect off of that and clear the 0x40000 bit there. * Oddly enough this was incorrect even in HP-UX! * runrun: Old name for want_resched. */ .globl _kdb_printf,_processor,_u,_runrun_kdb_printf: .long _printf_processor: .long 0_u: .long .+4 .long 0 .set _runrun,_want_resched#endif/* interrupt counters */ .globl _intrcnt,_eintrcnt,_intrnames,_eintrnames_intrnames: .asciz "spur" .asciz "lev1" .asciz "lev2" .asciz "lev3" .asciz "lev4" .asciz "clock" .asciz "lev7" .asciz "nmi"_eintrnames: .even_intrcnt: .long 0,0,0,0,0,0,0,0,0_eintrcnt:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -