📄 locore.s
字号:
.set reorder END(clear_bev)/* * setsoftnet() - make software network interrupt request */EXPORT(setsoftnet) li a0, CAUSE_SW2 j siron/* * acksoftnet() - acknowledge software network interrupt */EXPORT(acksoftnet) li a0, CAUSE_SW2 j siroff/* * setsoftclock() - make software clock interrupt request */EXPORT(setsoftclock) li a0, CAUSE_SW1 j siron/* * acksoftclock() - acknowledge software clock interrupt */EXPORT(acksoftclock) li a0, CAUSE_SW1 j siroff/* * siron(level) -- make software interrupt request */LEAF(siron) .set noreorder mfc0 v0,C0_SR mtc0 zero,C0_SR # disable all interrupts mfc0 v1,C0_CAUSE nop or v1,a0 mtc0 v1,C0_CAUSE mtc0 v0,C0_SR # PE BIT j ra nop .set reorder END(siron)/* * siroff(level) -- acknowledge software interrupt request */LEAF(siroff) .set noreorder mfc0 v0,C0_SR mtc0 zero,C0_SR # disable all interrupts mfc0 v1,C0_CAUSE not a0 and v1,a0 mtc0 v1,C0_CAUSE mtc0 v0,C0_SR # PE BIT j ra nop .set reorder END(siroff)/* * bbadaddr(addr, len) * check for bus error on read access to addr * len is length of access (1=byte, 2=short, 4=long) */BADADDRFRM= (4*4)+4 # 4 arg saves plus a raNESTED(bbadaddr, BADADDRFRM, zero) .set noreorder nop mfc0 t0,C0_SR nop mtc0 zero,C0_SR nop .set reorder subu sp,BADADDRFRM sw ra,BADADDRFRM-4(sp)#ifdef ASSERTIONS lw v0,u+PCB_CPUPTR lw v0,CPU_NOFAULT(v0) beq v0,zero,8f PANIC("recursive nofault")8:#endif ASSERTIONS .set noreorder lw t1,u+PCB_CPUPTR li v0,NF_BADADDR bne a1,1,1f sw v0,CPU_NOFAULT(t1) lb v0,0(a0) b 4f nop1: bne a1,2,2f nop lh v0,0(a0) b 4f nop2: bne a1,4,3f nop lw v0,0(a0) b 4f nop .set reorder3: PANIC("bbaddaddr") .set noreorder4: lw t1,u+PCB_CPUPTR nop sw zero,CPU_NOFAULT(t1) lw ra,BADADDRFRM-4(sp) addu sp,BADADDRFRM mtc0 t0,C0_SR # PE BIT move v0,zero j ra nop .set reorder END(bbadaddr)/* * wbadaddr(addr, len) * check for bus error on write access to addr * len is length of access (1=byte, 2=short, 4=long) */NESTED(wbadaddr, BADADDRFRM, zero) subu sp,BADADDRFRM sw ra,BADADDRFRM-4(sp) .set noreorder nop mfc0 t0,C0_SR nop mtc0 zero,C0_SR nop .set reorder#ifndef SABLE lw zero,SBE_ADDR|K1BASE#endif#ifdef ASSERTIONS lw v0,u+PCB_CPUPTR lw v0,CPU_NOFAULT(v0) beq v0,zero,8f PANIC("recursive nofault")8:#endif ASSERTIONS .set noreorder bne a1,1,1f lw t1,u+PCB_CPUPTR li v0,NF_BADADDR #LDSLOT sw v0,CPU_NOFAULT(t1) sb zero,0(a0) b 4f nop1: bne a1,2,2f nop b 4f sh zero,0(a0)2: bne a1,4,3f nop b 4f sw zero,0(a0) .set reorder3: PANIC("wbaddaddr") .set noreorder4: bc0f 4b # wait for write buffer empty nop lw v0,K1BASE mfc0 t1,C0_CAUSE nop and t1,CAUSE_IP7 # Memory line error bne t1,zero,baerror nop lw t1,u+PCB_CPUPTR nop sw zero,CPU_NOFAULT(t1) mtc0 t0,C0_SR # PE BIT lw ra,BADADDRFRM-4(sp) addu sp,BADADDRFRM j ra move v0,zero .set reorder END(wbadaddr)/* * wbadmemaddr(addr) * check for address error on word access to addr * Assumes addr points to RAM since trap is generated by read-back */ NESTED(wbadmemaddr, BADADDRFRM, zero) .set noreorder nop mfc0 t0,C0_SR nop mtc0 zero,C0_SR nop .set reorder subu sp,BADADDRFRM sw ra,BADADDRFRM-4(sp)#ifdef ASSERTIONS lw v0,u+PCB_CPUPTR lw v0,CPU_NOFAULT(v0) beq v0,zero,8f PANIC("recursive nofault")8:#endif ASSERTIONS .set noreorder lw t1,u+PCB_CPUPTR li v0,NF_BADADDR # LDSLOT sw v0,CPU_NOFAULT(t1) sw zero,0(a0) # store first to generate ECC lw v0,0(a0) # load can cause sync DBE sw zero,CPU_NOFAULT(t1) lw ra,BADADDRFRM-4(sp) addu sp,BADADDRFRM mtc0 t0,C0_SR # PE BIT j ra move v0,zero .set reorder END(wbadmemaddr)/* * trap() nofault code comes here on bus errors when nofault == NF_BADADDR */NESTED(baerror, BADADDRFRM, zero)#ifndef SABLE lw v0, cpu # get cpu bne v0, DS_3100, 1f # only PMAX has SBE lw zero,SBE_ADDR|K1BASE1:#endif .set noreorder nop mtc0 t0,C0_SR # PE BIT nop .set reorder li v0,1 lw ra,BADADDRFRM-4(sp) addu sp,BADADDRFRM j ra END(baerror)/* * ffs(word) * BEWARE: that C version of this routine that is distributed with 4.2 * is incorrect! * * find first bit set in word (a la VAX instruction) * looks at low order bits first, lowest order bit is 1, highest bit is 32 * no bits returns 0 */LEAF(ffs) .set noreorder move v0,zero beq a0,zero,2f # no bits set, return zero1: and v1,a0,1 addu v0,1 beq v1,zero,1b srl a0,1 # BDSLOT: shift right to next bit2: j ra nop .set reorder END(ffs)#ifdef notdefLEAF(ffs) move v1,zero # initial table offset and v0,a0,0xffff # check lower halfword bne v0,zero,1f # bits in lower halfword addu v1,64 # table offset for halfword srl a0,16 # check upper halfword1: and v0,a0,0xff # check lower byte of halfword bne v0,zero,2f # bits in lower byte addu v1,32 # table offset for byte srl a0,8 # check upper byte of halfword2: and v0,a0,0xf # check lower nibble bne v0,zero,3f # bits in lower nibble addu v1,16 # table offset for nibble srl v0,a0,4 # check upper nibble and v0,0xf # isolate lower nibble3: addu v1,v0 # total table offset lbu v0,ffstbl(v1) # load bit number from table j ra END(ffs) .data#define NIBBLE(x) \ .byte 0, 1+(x)*4, 2+(x)*4, 1+(x)*4; \ .byte 3+(x)*4, 1+(x)*4, 2+(x)*4, 1+(x)*4; \ .byte 4+(x)*4, 1+(x)*4, 2+(x)*4, 1+(x)*4; \ .byte 3+(x)*4, 1+(x)*4, 2+(x)*4, 1+(x)*4ffstbl: NIBBLE(0) NIBBLE(1) NIBBLE(2) NIBBLE(3) NIBBLE(4) NIBBLE(5) NIBBLE(6) NIBBLE(7) .text#endif notdef/* * ffintr(cause_register) -- find first bit set in interrupt pending byte * bits are numbered as 8 most significant to 1 least significant, * search starts from most significant end, returns 0 in no bits set */LEAF(ffintr) and v0,a0,CAUSE_IPMASK srl a0,v0,CAUSE_IPSHIFT+4 # shift to high nibble of IPEND bits bne a0,zero,1f # bits set in high nibble srl a0,v0,CAUSE_IPSHIFT # get 2nd nibble right add a0,16 # to get to 2nd half of table1: lbu v0,ffitbl(a0) # get value from table j ra END(ffintr) .dataffitbl: .byte 0,5,6,6,7,7,7,7,8,8,8,8,8,8,8,8 .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 .text/* * scanc(count, cp, table, mask) * Like VAX instruction */LEAF(scanc) move v0,a0 b 2f1: subu v0,1 # decr count2: beq v0,zero,3f # count exhausted lbu v1,0(a1) # get char at cp addu a1,1 # incr cp addu t8,a2,v1 # offset into table lbu t9,0(t8) # load table entry and t9,a3 # mask table entry beq t9,zero,1b # masked bit set3: j ra END(scanc)/* * in_checksum(addr, len, prevcksum) * * Calculates a 16 bit ones-complement checksum. * Note that for a big-endian machine, this routine always adds even * address bytes to the high order 8 bits of the 16 bit checksum and * odd address bytes are added to the low order 8 bits of the 16 bit checksum. * For little-endian machines, this routine always adds even address bytes * to the low order 8 bits of the 16 bit checksum and the odd address bytes * to the high order 8 bits of the 16 bit checksum. */LEAF(in_checksum) move v0,a2 # copy previous checksum beq a1,zero,4f # count exhausted and v1,a0,1 beq v1,zero,2f # already on a halfword boundry lbu t8,0(a0) addu a0,1#ifdef MIPSEL sll t8,8#endif MIPSEL addu v0,t8 subu a1,1 b 2f1: lhu t8,0(a0) addu a0,2 addu v0,t8 subu a1,22: bge a1,2,1b beq a1,zero,3f # no trailing byte lbu t8,0(a0)#ifdef MIPSEB sll t8,8#endif MIPSEB addu v0,t83: srl v1,v0,16 # add in all previous wrap around carries and v0,0xffff addu v0,v1 srl v1,v0,16 # wrap-arounds could cause carry, also addu v0,v1 and v0,0xffff4: j ra END(in_checksum)/* * The XNS checksummer does an add-and-cycle checksum. Odd byte * lengths are dealt with by postpending a garbage byte, which is * carried with the packet forever, and is not assumed to be * zero. Thus, the algorithm is load a half-word, and add it to * the current checksum. Then, shift the whole mess left one bit, * and iterate. All math is ones-complement on 16 bits, so when * we are done, we must fold back all the carry bits that are in * the high 16 bits of our register. The caller is required to * half-word align the packet, since we can't easily, and to * postpend the garbage byte if necessary. */LEAF(ns_checksum) move v0,a2 # copy previous checksum move t0, a1 # save count beq a1,zero,3f # count exhausted and v1,a0,1 beq v1,zero,2f # already on a halfword boundry li v0, 0177777 # error code b 3f1: lhu t8,0(a0) addu a0,2 addu v0,t8 subu a1,22: bge a1,2,1b srl v1,v0,16 # add in all previous wrap around carries and v0,0xffff addu v0,v1 srl v1,v0,16 # wrap-arounds could cause carry, also addu v0,v1 and v0,0xffff sll t0, 1 # divide count by two it - is round rol v0, t0 # now do 32 bit rotate... and v1, v0, 0xffff # and fold it back down to 16 bits and v0, 0xffff0000 or v0, v1 # done, now have 16 bit checksum3: j ra END(ns_checksum)/* * nuxi_s and nuxi_l -- byte swap short and long */LEAF(nuxi_s) # a0 = ??ab srl v0,a0,8 # v0 = 0??a and v0,0xff # v0 = 000a sll v1,a0,8 # v1 = ?ab0 or v0,v1 # v0 = ?aba and v0,0xffff # v0 = 00ba j ra END(nuxi_s)LEAF(nuxi_l) # a0 = abcd sll v0,a0,24 # v0 = d000 srl v1,a0,24 # v1 = 000a or v0,v0,v1 # v0 = d00a and v1,a0,0xff00 # v1 = 00c0 sll v1,v1,8 # v1 = 0c00 or v0,v0,v1 # v0 = dc0a srl v1,a0,8 # v1 = 0abc and v1,v1,0xff00 # v1 = 00b0 or v0,v0,v1 # v0 = dcba j ra END(nuxi_l)/* * Write buffer flush routine. Routine waits until * the write buffer is empty before returning. */LEAF(kn01wbflush) /* WB flush routine for PMAX (R2000a) */1: bc0f 1b j ra END(kn01wbflush)LEAF(kn210wbflush) /* WB flush routine for R3000 */ .set noreorder mfc0 v0,C0_SR /* v0 = status register */ li t0,0x80000000 /* set CU3 bit */ or v1,v0,t0 /* v1 = v0 | 0x80000000 */ nop mtc0 v1,C0_SR /* status register = v1 */ nop /* both these nops are needed */ nop /* both these nops are needed */1: bc3f 1b /* wait till write buffer empty */ nop /* this no op too */ mtc0 v0,C0_SR /* restore old status register */ nop j ra nop .set reorder END(kn210wbflush)#ifdef DS5000_100LEAF(kn02ba_wbflush) /* WB flush routine for 5000_100 */ lw v0, KN02BA_SIRM_K1ADDR /* a read will flush all writes */ j ra END(kn02ba_wbflush)#endifLEAF(kn220wbflush) /* WB flush routine for R3000 */ .set noreorder la t0,kn220wbflush_loc li t1, 0xa0000000 /* Make kseg1 address */ or t0,t1 sw t1,0(t0) lw t1,0(t0) nop j ra nop .set reorder END(kn210wbflush)NESTED(smp_lock_retry,24,zero) .set noreorder#ifndef SMP lw t5,(a0) lw t1,u+PCB_CPUPTR /* get cpudata pointer */ bltz t5,3f lw t2,CPU_HLOCK(t1) /* save off lock list head */ sw a0,CPU_HLOCK(t1) /* put new lock at head */ sw ra,L_PC(a0) /* store off PC lock asserted at */ lui t3,0x8000 lw t4,L_WON(a0) /* get lock won */ or t6,t3,t5 /* set lock bit */ addiu t4,t4,1 /* increment lock won */ sw t6,(a0) sw t4,L_WON(a0) j ra sw t2,L_PLOCK(a0) /* chain old list off new lock */3: addiu sp,sp,-24 /* save stack space */ b 1f sw ra,20(sp) /* save off return */#else 2: lw t6,smp_debug /* read up smp_debug*/ addiu sp,sp,-24 /* save stack space */ bne t6,zero,1f /* branch if debug enabled */ sw ra,20(sp) /* save off return */ jal setlock sw a0,24(sp) /* save off lock pointer */ beq v0,zero,1f /* branch if we failed to get lock */ lw a0,24(sp) /* restore lock pointer */ lw t1,u+PCB_CPUPTR /* get cpudata pointer */ lw ra,20(sp) /* restore return address */ lw t2,CPU_HLOCK(t1) /* save off lock list head */ sw a0,CPU_HLOCK(t1) /* put new lock at head */ lw t4,L_WON(a0) /* get lock won */ sw ra,L_PC(a0) addiu t4,t4,1 /* increment lock won */ addiu sp,sp,24 /* give back stack space */ sw t4,L_WON(a0) j ra sw t2,L_PLOCK(a0); /* chain old list off new lock */#endif1: li a1,LK_RETRY jal smp_lock_long /* smp_lock_long(lk,L
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -