|
|
1.1 ! root 1: .data ! 2: .asciz "@(#)vax.s 1.1 86/02/03 Copyr 1986 Sun Micro" ! 3: .even ! 4: .text ! 5: /* ! 6: * Copyright (c) 1986 by Sun Microsystems, Inc. ! 7: */ ! 8: ! 9: /* ! 10: * Emulate VAX instructions on the 68020. ! 11: */ ! 12: ! 13: #include "../h/param.h" ! 14: #include "../machine/asm_linkage.h" ! 15: #include "../machine/mmu.h" ! 16: #include "../machine/psl.h" ! 17: #include "assym.s" ! 18: ! 19: /* ! 20: * Macro to raise prio level, ! 21: * avoid dropping prio if already at high level. ! 22: * NOTE - Assumes that we are never in "master" mode. ! 23: */ ! 24: #define RAISE(level) \ ! 25: movw sr,d0; \ ! 26: andw #(SR_SMODE+SR_INTPRI),d0; \ ! 27: cmpw #(SR_SMODE+(/**/level*0x100)),d0; \ ! 28: jge 0f; \ ! 29: movw #(SR_SMODE+(/**/level*0x100)),sr; \ ! 30: 0: rts ! 31: ! 32: #define SETPRI(level) \ ! 33: movw sr,d0; \ ! 34: movw #(SR_SMODE+(/**/level*0x100)),sr; \ ! 35: rts ! 36: ! 37: ENTRY(splimp) ! 38: RAISE(3) ! 39: ! 40: ENTRY(splnet) ! 41: RAISE(1) ! 42: ! 43: ENTRY(splie) ! 44: RAISE(3) ! 45: ! 46: ENTRY(splclock) ! 47: RAISE(5) ! 48: ! 49: ENTRY(splzs) ! 50: SETPRI(6) ! 51: ! 52: ENTRY(spl7) ! 53: SETPRI(7) ! 54: ! 55: ENTRY2(spl6,spl5) ! 56: SETPRI(5) ! 57: ! 58: ENTRY(spl4) ! 59: SETPRI(4) ! 60: ! 61: ENTRY(spl3) ! 62: SETPRI(3) ! 63: ! 64: ENTRY(spl2) ! 65: SETPRI(2) ! 66: ! 67: ENTRY(spl1) ! 68: SETPRI(1) ! 69: ! 70: ENTRY(spl0) ! 71: SETPRI(0) ! 72: ! 73: ENTRY(splx) ! 74: movw sr,d0 ! 75: movw sp@(6),sr ! 76: rts ! 77: ! 78: ENTRY(insque) ! 79: movl sp@(4),a0 ! 80: movl sp@(8),a1 ! 81: movl a1@,a0@ ! 82: movl a1,a0@(4) ! 83: movl a0,a1@ ! 84: movl a0@,a1 ! 85: movl a0,a1@(4) ! 86: rts ! 87: ! 88: ENTRY(remque) ! 89: movl sp@(4),a0 ! 90: movl a0@,a1 ! 91: movl a0@(4),a0 ! 92: movl a1,a0@ ! 93: movl a0,a1@(4) ! 94: rts ! 95: ! 96: ENTRY(scanc) ! 97: movl sp@(8),a0 | string ! 98: movl sp@(12),a1 | table ! 99: movl sp@(16),d1 | mask ! 100: movl d2,sp@- ! 101: clrw d2 ! 102: movl sp@(8),d0 | len ! 103: subqw #1,d0 | subtract one for dbxx ! 104: jmi 1f ! 105: 2: ! 106: movb a0@+,d2 | get the byte from the string ! 107: movb a1@(0,d2:w),d2 | get the corresponding table entry ! 108: andb d1,d2 | apply the mask ! 109: dbne d0,2b | check for loop termination ! 110: 1: ! 111: addqw #1,d0 | dbxx off by one ! 112: movl sp@+,d2 ! 113: rts ! 114: ! 115: /* ! 116: * _whichqs tells which of the 32 queues _qs have processes in them ! 117: * setrq puts processes into queues, remrq removes them from queues ! 118: * The running process is on no queue, other processes are on a ! 119: * queue related to p->p_pri, divided by 4 actually to shrink the ! 120: * 0-127 range of priorities into the 32 available queues. ! 121: */ ! 122: ! 123: /* ! 124: * setrq(p), using semi-fancy 68020 instructions. ! 125: * ! 126: * Call should be made at spl6(), and p->p_stat should be SRUN ! 127: */ ! 128: ENTRY(setrq) ! 129: movl sp@(4),a0 | get proc pointer ! 130: tstl a0@(P_RLINK) | firewall: p->p_rlink must be 0 ! 131: jne 1f ! 132: moveq #31,d1 ! 133: clrl d0 ! 134: movb a0@(P_PRI),d0 | get the priority ! 135: lsrl #2,d0 | divide by 4 ! 136: subl d0,d1 ! 137: lea _qs,a1 ! 138: movl a1@(4,d1:l:8),a1| qs[d1].ph_rlink, 8 == sizeof (qs[0]) ! 139: movl a1@,a0@ | insque(p, blah) ! 140: movl a1,a0@(4) ! 141: movl a0,a1@ ! 142: movl a0@,a1 ! 143: movl a0,a1@(4) ! 144: bfset _whichqs{d0:#1} | set appropriate bit in whichqs ! 145: rts ! 146: 1: ! 147: pea 2f ! 148: jsr _panic ! 149: ! 150: 2: .asciz "setrq" ! 151: .even ! 152: ! 153: /* ! 154: * remrq(p), using semi-fancy 68020 instructions ! 155: * ! 156: * Call should be made at spl6(). ! 157: */ ! 158: ENTRY(remrq) ! 159: movl sp@(4),a0 ! 160: clrl d0 ! 161: movb a0@(P_PRI),d0 ! 162: lsrl #2,d0 | divide by 4 ! 163: bftst _whichqs{d0:#1} ! 164: jeq 1f ! 165: movl a0@,a1 | remque(p); ! 166: movl a0@(4),a0 ! 167: movl a1,a0@ ! 168: movl a0,a1@(4) ! 169: cmpl a0,a1 ! 170: jne 2f | queue not empty ! 171: bfclr _whichqs{d0:#1} | queue empty, clear the bit ! 172: 2: ! 173: movl sp@(4),a0 ! 174: clrl a0@(P_RLINK) ! 175: rts ! 176: 1: ! 177: pea 3f ! 178: jsr _panic ! 179: ! 180: 3: .asciz "remrq" ! 181: .even ! 182: ! 183: /* ! 184: * swtch(), using semi-fancy 68020 instructions ! 185: */ ! 186: ENTRY(swtch) ! 187: movw sr,sp@- | save processor priority ! 188: movl #1,_noproc ! 189: clrl _runrun ! 190: bclr #AST_SCHED_BIT-24,_u+PCB_P0LR ! 191: 2: ! 192: bfffo _whichqs{#0:#32},d0 | test if any bit on ! 193: cmpl #32,d0 ! 194: jne 3f | found one ! 195: stop #SR_LOW | must allow interrupts here ! 196: ! 197: .globl idle ! 198: idle: | wait here for interrupts ! 199: jra 2b | try again ! 200: ! 201: 3: ! 202: movw #SR_HIGH,sr | lock out all so _whichqs == _qs ! 203: moveq #31,d1 ! 204: subl d0,d1 ! 205: bfclr _whichqs{d0:#1} ! 206: jeq 2b | proc moved via lbolt interrupt ! 207: lea _qs,a0 ! 208: movl a0@(0,d1:l:8),a0| get qs[d1].ph_link = p = highest pri process ! 209: movl a0,d1 | save it ! 210: movl a0@,a1 | remque(p); ! 211: cmpl a0,a1 | is queue empty? ! 212: jne 4f ! 213: 8: ! 214: pea 9f ! 215: jsr _panic ! 216: 9: ! 217: .asciz "swtch" ! 218: .even ! 219: 4: ! 220: movl a0@(4),a0 ! 221: movl a1,a0@ ! 222: movl a0,a1@(4) ! 223: cmpl a0,a1 ! 224: jeq 5f | queue empty ! 225: bfset _whichqs{d0:#1} | queue not empty, set appropriate bit ! 226: 5: ! 227: movl d1,a0 | restore p ! 228: clrl _noproc ! 229: tstl a0@(P_WCHAN) || firewalls ! 230: jne 8b || ! 231: cmpb #SRUN,a0@(P_STAT) || ! 232: jne 8b || ! 233: clrl a0@(P_RLINK) || ! 234: addql #1,_cnt+V_SWTCH ! 235: movl a0,sp@- ! 236: jsr _resume ! 237: addqw #4,sp ! 238: movw sp@+,sr | restore processor priority ! 239: rts ! 240: ! 241: ! 242: /* ! 243: * fpprocp is the pointer to the proc structure whose external ! 244: * state (i.e. registers) was last loaded into the 68881. ! 245: */ ! 246: .data ! 247: .globl _fpprocp ! 248: _fpprocp: .long 0 | struct proc *fpprocp; ! 249: .text ! 250: ! 251: /* ! 252: * masterprocp is the pointer to the proc structure for the currently ! 253: * mapped u area. It is used to set up the mapping for the u area ! 254: * by the debugger since the u area is not in the Sysmap. ! 255: */ ! 256: .data ! 257: .globl _masterprocp ! 258: _masterprocp: .long 0 | struct proc *masterprocp; ! 259: .text ! 260: ! 261: /* ! 262: * resume(p) ! 263: * ! 264: * Assumes that there is only one real page to worry about (UPAGES = 1), ! 265: * that the kernel stack starts below the u area in the middle of ! 266: * a page, that the redzone is below that and is always marked ! 267: * for no access across all contexts, the default sfc and dfs are ! 268: * set to FC_MAP, and that we are running on the u area kernel stack ! 269: * when we are called. ! 270: */ ! 271: SAVREGS = 0xFCFC ! 272: ENTRY(resume) ! 273: tstw _fppstate | is fpp present and enabled? ! 274: jle 1f | branch if not ! 275: fsave _u+U_FP_ISTATE | save internal state ! 276: tstw _u+U_FP_ISTATE | test for null state ! 277: jeq 1f | branch if so ! 278: fmovem fpc/fps/fpi,_u+U_FPS_CTRL | save control registers ! 279: fmovem fp0-fp7,_u+U_FPS_REGS | save fp data registers ! 280: movl _masterprocp,_fpprocp | remember whose regs are still loaded ! 281: 1: ! 282: movl sp@,_u+PCB_REGS | save return pc in pcb ! 283: movl sp@(4),a0 | a0 contains proc pointer ! 284: movw sr,_u+PCB_SR+2 | save the current psw in u area ! 285: orw #SR_INTPRI,sr | mask interrupts ! 286: moveml #SAVREGS,_u+PCB_REGS+4 | save data/address regs ! 287: movl a0,_masterprocp | set proc pointer for new process ! 288: lea eintstack,sp | use the interrupt stack ! 289: moveq #KCONTEXT,d0 ! 290: movsb d0,CONTEXTBASE | invalidate context ! 291: lea U_MAPVAL,a1 | a1 has address used to access pme for u area ! 292: movl a0@(P_ADDR),a2 | get p_addr (address of pte's), a2 is scratch ! 293: movl a2@,d0 | get u pte ! 294: movsl d0,a1@ | and set pme ! 295: /* ! 296: * Check to see if we already have context. If so and ! 297: * SPTECHG bit is not on then set up the next context. ! 298: */ ! 299: tstl a0@(P_CTX) | check p->p_ctx ! 300: jeq 1f | if zero, skip ahead ! 301: btst #SPTECHG_BIT-24,a0@(P_FLAG) | check (p->p_flag & SPTECHG) ! 302: jne 1f | if SPTECHG bit is on, skip ahead ! 303: movl a0@(P_CTX),a1 ! 304: movw a1@(CTX_CONTEXT),d0 | get context number in d0 ! 305: movsb d0,CONTEXTBASE | set up the context ! 306: 1: ! 307: tstw _fppstate | is fpp present and enabled? ! 308: jle 1f | branch if not ! 309: tstw _u+U_FP_ISTATE | test for null state ! 310: jeq 0f | branch if so ! 311: cmpl _fpprocp,a0 | check if we were last proc using fpp ! 312: beq 0f | if so, jump and skip loading ext regs ! 313: fmovem _u+U_FPS_REGS:w,fp0-fp7 | restore fp data registers ! 314: fmovem _u+U_FPS_CTRL,fpc/fps/fpi | restore control registers ! 315: 0: ! 316: frestore _u+U_FP_ISTATE | restore internal state ! 317: 1: ! 318: moveml _u+PCB_REGS+4,#SAVREGS | restore data/address regs ! 319: | Note: we just changed stacks ! 320: movw _u+PCB_SR+2,sr ! 321: tstl _u+PCB_SSWAP ! 322: jeq 1f ! 323: movl _u+PCB_SSWAP,sp@(4) | blech... ! 324: clrl _u+PCB_SSWAP ! 325: movw #SR_LOW,sr ! 326: jmp _longjmp ! 327: 1: ! 328: rts
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.