increase size of malloc arena
[unix-history] / usr / src / sys / tahoe / tahoe / locore.s
CommitLineData
430f81c3
MK
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
278eb892 6 * @(#)locore.s 7.13 (Berkeley) %G%
430f81c3 7 */
57a0bdb5
SL
8
9#include "../tahoe/mtpr.h"
10#include "../tahoe/trap.h"
11#include "../tahoe/psl.h"
12#include "../tahoe/pte.h"
13#include "../tahoe/cp.h"
14#include "../tahoe/mem.h"
a55e280b 15#include "../tahoe/SYS.h"
430f81c3 16
a55e280b 17#include "../tahoemath/fp.h"
57a0bdb5 18
a55e280b
SL
19#include "errno.h"
20#include "syscall.h"
21#include "cmap.h"
57a0bdb5 22
56ad8000
SL
23 .set HIGH,0x1f # mask for total disable
24 .set NISP,3 # number of interrupt stack pages
25 .set SYSTEM,0xC0000000 # virtual address of system start
26 .set PPAGES,0x100000 # possible pages in P0,P1, etc.
57a0bdb5
SL
27
28/* ACBL for non-negative '_add' */
29#define ACBL(_limit,_add,_index,_displ) \
30 addl2 _add,_index; \
31 cmpl _index,_limit; \
32 bleq _displ
33
34/* _ACBL for negative '_add' */
35#define _ACBL(_limit,_add,_index,_displ) \
36 addl2 _add,_index; \
37 cmpl _index,_limit; \
38 bgeq _displ
39
a55e280b 40#define MOVC3(_srcaddr,_dstaddr,_len) \
57a0bdb5
SL
41 movl _srcaddr,r0; \
42 movl _dstaddr,r1; \
43 movl _len,r2; \
44 movblk
45
a55e280b 46/* keep address of psl if coming from user mode */
57a0bdb5
SL
47#define CHECK_SFE(_delta) \
48 bitl $PSL_CURMOD,_delta(sp); \
49 jeql 1f; \
50 moval _delta(sp),_user_psl; \
511:
52
53/*
54 * User structure is UPAGES at top of user space.
55 */
56 .globl _u
57 .set _u,SYSTEM - UPAGES*NBPG
58
59/*
60 * Restart stack. Used on power recovery or panic.
61 * Takes a core-dump and then halts.
62 */
63 .globl _rsstk
57a0bdb5 64 .globl pwfl_stk
a55e280b
SL
65_rsstk:
66 .space 1024-8
67pwfl_stk:
68 .space 4
69dumpflag:
70 .space 4
57a0bdb5
SL
71
72 .globl _intstack
73_intstack:
74 .space NISP*NBPG
75eintstack:
76
a55e280b
SL
77/*
78 * Power failure storage block and
79 * macros for saving and restoring.
80 */
81#define POWERFAIL(id,longs) \
82 .globl pwfl_/**/id \
83pwfl_/**/id: .space longs*4
57a0bdb5 84 .data
a55e280b
SL
85 POWERFAIL(r0, 14) # r0-r13
86 POWERFAIL(sp, 1) # r14
87 POWERFAIL(SCBB, 1) # system control block base
88 POWERFAIL(SBR, 1) # system pte base
89 POWERFAIL(SLR, 1) # system pte length
90 POWERFAIL(P0BR, 1) # p0 pte base
91 POWERFAIL(P0LR, 1) # p0 pte length
92 POWERFAIL(P1BR, 1) # p1 pte base
93 POWERFAIL(P1LR, 1) # p1 pte length
94 POWERFAIL(P2BR, 1) # p2 pte base
95 POWERFAIL(P2LR, 1) # p2 pte length
96 POWERFAIL(IPL, 1) # interrupt priority level
97 POWERFAIL(DCK, 1) # data cache key
98 POWERFAIL(CCK, 1) # code cache key
99 POWERFAIL(PCBB, 1) # process control block base
100 POWERFAIL(ISP, 1) # interrupt stack pointer
101 POWERFAIL(KSP, 1) # kernel mode stack pointer
102 POWERFAIL(USP, 1) # user mode stack pointer
103 POWERFAIL(MME, 1) # memory management enable
104 POWERFAIL(PSL, 1) # processor status longword
105
106/*
107 * Save current state in power fail storage block.
108 */
109#define SAVEpwfl() \
110 movpsl pwfl_PSL # Keeps all flags, etc. \
111 storer $0x3fff,pwfl_r0 # Saves r0-r13 \
112 moval 0(sp),pwfl_sp # Saves sp (=r14) \
113 mfpr $SBR,pwfl_SBR # Save all re_loadable registers \
114 mfpr $SLR,pwfl_SLR \
115 mfpr $P0BR,pwfl_P0BR \
116 mfpr $P0LR,pwfl_P0LR \
117 mfpr $P1BR,pwfl_P1BR \
118 mfpr $P1LR,pwfl_P1LR \
119 mfpr $P2BR,pwfl_P2BR \
120 mfpr $P2LR,pwfl_P2LR \
121 mfpr $IPL,pwfl_IPL \
122 mfpr $MME,pwfl_MME \
123 mfpr $DCK,pwfl_DCK \
124 mfpr $CCK,pwfl_CCK \
125 mfpr $PCBB,pwfl_PCBB \
126 mfpr $ISP,pwfl_ISP \
127 mfpr $SCBB,pwfl_SCBB \
128 mfpr $KSP,pwfl_KSP \
129 mfpr $USP,pwfl_USP
130
131/*
132 * Restore state saved in power fail block and
133 * jmp to location specified after (possibly)
134 * enabling memory management.
135 */
136#define RESTOREpwfl(loc) \
137 loadr $0x3fff,pwfl_r0 # Restore r0-r13 \
138 movl pwfl_sp,sp # Restore sp (=r14) \
139 mtpr pwfl_SCBB,$SCBB \
140 mtpr pwfl_SBR,$SBR # Restore all re_loadable registers \
141 mtpr pwfl_SLR,$SLR \
142 mtpr pwfl_P0BR,$P0BR \
143 mtpr pwfl_P0LR,$P0LR \
144 mtpr pwfl_P1BR,$P1BR \
145 mtpr pwfl_P1LR,$P1LR \
146 mtpr pwfl_P2BR,$P2BR \
147 mtpr pwfl_P2LR,$P2LR \
148 mtpr pwfl_IPL,$IPL \
149 mtpr pwfl_DCK,$DCK \
150 mtpr pwfl_CCK,$CCK \
151 mtpr pwfl_PCBB,$PCBB \
152 mtpr pwfl_ISP,$ISP \
153 mtpr pwfl_KSP,$KSP \
154 mtpr pwfl_USP,$USP \
155\
156 bicpsw $0xff # Restore PSW. \
157 bispsw pwfl_PSL+2 # Set original bits back (just in case..) \
158# now go to mapped mode \
159# Have to change PC to system addresses \
160 mtpr $1,$PACC # Thoroughly clean up caches. \
161 mtpr $1,$PADC \
162 mtpr $1,$TBIA \
163 mtpr pwfl_MME,$MME # Restore MME. Last thing to be done. \
164 jmp loc
57a0bdb5
SL
165
166/*
167 * Do a dump.
168 * Called by auto-restart.
169 * May be called manually.
170 */
171 .align 2
172 .text
173 .globl _Xdoadump
174 .globl _doadump
a55e280b
SL
175_Xdoadump: # CP comes here after power fail
176 RESTOREpwfl(*0f) # restore state
57a0bdb5
SL
177_doadump:
178 .word 0
a55e280b
SL
1790: mtpr $HIGH,$IPL
180#define _rsstkmap _Sysmap+12 # powerfail storage, scb, rsstk, int stack
57a0bdb5
SL
181 tstl dumpflag # dump only once!
182 bneq 1f
04d1fc31
MK
183 andl2 $~PG_PROT,_rsstkmap
184 orl2 $PG_KW,_rsstkmap # Make dump stack r/w
57a0bdb5 185 mtpr $0,$TBIA
04d1fc31 186 movl $1,dumpflag
57a0bdb5
SL
187 movab dumpflag,sp
188 callf $4,_dumpsys
1891:
190 halt
191
192/*
193 * Interrupt vector routines
194 */
195 .globl _waittime
57a0bdb5
SL
196#define SCBVEC(name) \
197 .align 2; \
198 .globl _X/**/name; \
199_X/**/name
a55e280b
SL
200#define PANIC(msg) \
201 clrl _waittime; pushab 1f; callf $8,_panic; 1: .asciz msg
202#define PRINTF(n,msg) \
203 pushab 1f; callf $(n+2)*4,_printf; MSG(msg)
204#define MSG(msg) .data; 1: .asciz msg; .text
205/*
07f28727 206 * r0-r5 are saved across all faults and interrupts.
56ad8000 207 * Routines below and those hidden in vbglue.s (device
a55e280b
SL
208 * interrupts) invoke the PUSHR/POPR macros to execute
209 * this. Also, certain stack frame offset calculations
07f28727 210 * use this, using the REGSPC definition (and FPSPC defined below).
a55e280b 211 */
07f28727
MK
212#define REGSPC 6*4
213#define PUSHR movab -REGSPC(sp),sp; storer $0x3f,(sp)
214#define POPR loadr $0x3f,(sp); movab REGSPC(sp),sp
a55e280b
SL
215
216/*
217 * Floating point state is saved across faults and
218 * interrupts. The state occupies 4 longwords on
219 * the stack:
220 * precision indicator (single = 0/double = 1)
221 * double representation of accumulator
222 * save accumulator status flag (pcb_savacc)
223 */
224#define FPSPC (4*4)
225
226#define SAVE_FPSTAT(_delta) \
227 bitl $PSL_DBL,_delta(sp); \
228 beql 1f; \
229 pushl $1; \
230 pushd; \
231 jmp 2f; \
2321: pushl $0; \
233 pushl $0; \
234 stf -(sp); \
2352: tstl _u+PCB_SAVACC; \
236 bneq 3f; \
237 moval 0(sp),_u+PCB_SAVACC; \
238 orl2 $2,8(sp);\
2393: pushl $0;
240
241#define REST_FPSTAT \
242 tstl (sp)+; \
243 bitl $2,8(sp);\
244 beql 1f;\
245 movl $0,_u+PCB_SAVACC; \
2461: bitl $1,8(sp); \
247 beql 2f; \
248 ldd (sp); \
249 jmp 3f; \
2502: ldf (sp); \
2513: moval 12(sp),sp;
252
253#define REST_ACC \
254 tstl _u+PCB_SAVACC; \
255 beql 2f; \
256 movl _u+PCB_SAVACC,r1; \
257 andl3 $(EXPMASK|SIGNBIT),(r1),-(sp); \
258 cmpl $0x80000000,(sp)+; \
259 bneq 3f; \
260 clrl (r1); \
2613: bitl $1,8(r1); \
262 beql 1f; \
263 ldd (r1); \
264 jmp 2f; \
2651: ldf (r1); \
2662: ;
267
268 .data
269nofault: .space 4 # bus error non-local goto label
57a0bdb5 270
a55e280b 271 .text
57a0bdb5
SL
272SCBVEC(buserr):
273 CHECK_SFE(12)
a55e280b 274 SAVE_FPSTAT(12)
af0b6351 275 incl _intrcnt+I_BUSERR # keep stats...
a55e280b
SL
276 pushl r0 # must save
277 andl3 24(sp),$ERRCD,r0 # grab pushed MER value
278 cmpl r0,$APE # address parity error?
57a0bdb5 279 jneq 1f
a55e280b
SL
280 halt
2811: cmpl r0,$VBE # versabus error?
282 jneq 2f
283 halt
2842:
285 movl (sp)+,r0 # restore r0 and...
286 bitl $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode?
287 jeql 3f # yes, then shift stack up for trap...
288 movl 12(sp),16(sp) # sorry, no space for which-buss...
289 movl 8(sp),12(sp)
290 movl 4(sp),8(sp)
291 movl 0(sp),4(sp)
292 movl $T_BUSERR,0(sp) # push trap type code and...
293 jbr alltraps # ...merge with all other traps
2943: # kernel mode, check to see if...
295 tstl nofault # ...doing peek/poke?
296 jeql 4f # nofault set? if so, jump to it...
297 movl nofault,4*4+2*4(sp) # ...setup for non-local goto
298 clrl nofault
299 jbr 5f
3004:
301 PUSHR
07f28727 302 pushab 4*4+REGSPC(sp) # address of bus error parameters
57a0bdb5
SL
303 callf $8,_buserror
304 POPR
a55e280b
SL
3055:
306 REST_FPSTAT
307 movab 8(sp),sp # remove bus error parameters
57a0bdb5
SL
308 rei
309
a55e280b
SL
310SCBVEC(powfail): # We should be on interrupt stack now.
311 SAVEpwfl() # save machine state
56ad8000 312 moval _Xdoadump-SYSTEM,_scb+SCB_DOADUMP
57a0bdb5
SL
313 halt
314
315SCBVEC(stray):
44622fe3 316 incl _cnt+V_INTR # add to statistics
57a0bdb5
SL
317 rei
318
319#include "../net/netisr.h"
320 .globl _netisr
321SCBVEC(netintr):
322 CHECK_SFE(4)
56ad8000
SL
323 SAVE_FPSTAT(4); PUSHR
324#include "imp.h"
325#if NIMP > 0
326 bbc $NETISR_IMP,_netisr,1f;
327 andl2 $~(1<<NETISR_IMP),_netisr
328 callf $4,_impintr;
57a0bdb5 3291:
56ad8000 330#endif
57a0bdb5 331#ifdef INET
57a0bdb5 332 bbc $NETISR_IP,_netisr,1f
a55e280b 333 andl2 $~(1<<NETISR_IP),_netisr
57a0bdb5
SL
334 callf $4,_ipintr
3351:
336#endif
337#ifdef NS
338 bbc $NETISR_NS,_netisr,1f
a55e280b 339 andl2 $~(1<<NETISR_NS),_netisr
57a0bdb5
SL
340 callf $4,_nsintr
3411:
342#endif
9994fc90
MK
343#ifdef ISO
344 bbc $NETISR_ISO,_netisr,1f
345 andl2 $~(1<<NETISR_ISO),_netisr
346 callf $4,_clnlintr
56ad8000 3471:
9994fc90 348#endif
56ad8000
SL
349 incl _cnt+V_SOFT
350 POPR; REST_FPSTAT
57a0bdb5
SL
351 rei
352
57a0bdb5
SL
353SCBVEC(cnrint):
354 CHECK_SFE(4)
a55e280b 355 SAVE_FPSTAT(4); PUSHR;
af0b6351
SL
356 pushl $CPCONS; callf $8,_cnrint;
357 incl _intrcnt+I_CNR
358 incl _cnt+V_INTR
a55e280b
SL
359 POPR; REST_FPSTAT;
360 rei
57a0bdb5
SL
361SCBVEC(cnxint):
362 CHECK_SFE(4)
a55e280b 363 SAVE_FPSTAT(4); PUSHR;
af0b6351
SL
364 pushl $CPCONS; callf $8,_cnxint;
365 incl _intrcnt+I_CNX
366 incl _cnt+V_INTR
a55e280b
SL
367 POPR; REST_FPSTAT;
368 rei
57a0bdb5
SL
369SCBVEC(rmtrint):
370 CHECK_SFE(4)
371 SAVE_FPSTAT(4); PUSHR;
af0b6351
SL
372 pushl $CPREMOT; callf $8,_cnrint;
373 incl _intrcnt+I_RMTR
374 incl _cnt+V_INTR
a55e280b
SL
375 POPR; REST_FPSTAT;
376 rei
57a0bdb5
SL
377SCBVEC(rmtxint):
378 CHECK_SFE(4)
379 SAVE_FPSTAT(4); PUSHR;
af0b6351
SL
380 pushl $CPREMOT; callf $8,_cnxint;
381 incl _intrcnt+I_RMTX
382 incl _cnt+V_INTR
a55e280b
SL
383 POPR; REST_FPSTAT;
384 rei
57a0bdb5 385
a55e280b 386#define PUSHPCPSL pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp);
57a0bdb5
SL
387
388SCBVEC(hardclock):
a55e280b
SL
389 tstl _clk_enable
390 bneq 1f
391 rei
3921:
57a0bdb5 393 CHECK_SFE(4)
a55e280b
SL
394 SAVE_FPSTAT(4); PUSHR
395 PUSHPCPSL # push pc and psl
396 callf $12,_hardclock # hardclock(pc,psl)
af0b6351 397 incl _intrcnt+I_CLOCK
57a0bdb5 398 incl _cnt+V_INTR ## temp so not to break vmstat -= HZ
a55e280b 399 POPR; REST_FPSTAT
57a0bdb5
SL
400 rei
401SCBVEC(softclock):
402 CHECK_SFE(4)
a55e280b 403 SAVE_FPSTAT(4); PUSHR;
57a0bdb5 404 PUSHPCPSL # push pc and psl
a55e280b 405 callf $12,_softclock # softclock(pc,psl)
af0b6351 406 incl _cnt+V_SOFT
a55e280b 407 POPR; REST_FPSTAT
57a0bdb5
SL
408 rei
409
56ad8000
SL
410/*
411 * Stray VERSAbus interrupt catch routines
412 */
413 .data
414#define PJ .align 2; callf $4,_Xvstray
415 .globl _catcher
416_catcher:
417 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
418 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
419 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
420 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
421 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
422 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
423 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
424 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
425 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
426 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
427 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
428 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
429
430 .align 2
431 .globl _cold
432_cold: .long 0x3
433
434 .text
435SCBVEC(vstray):
436 .word 0
437 bbc $0,_cold,2f # system running?
438 bbc $1,_cold,1f # doing autoconfig?
439 jbr 3f # random interrupt, ignore
4401:
441 mfpr $IPL,r12 # ...setup br and cvec
442 subl3 $_catcher+7,-8(fp),r11; shar $3,r11,r11
443 addl2 $SCB_DEVBASE,r11
444 jbr 3f
4452:
446 PUSHR
447 subl3 $_catcher+7,-8(fp),r0; shar $3,r0,r0
448 addl3 $SCB_DEVBASE,r0,-(sp);
449 mfpr $IPL,-(sp)
450 PRINTF(2, "stray intr ipl %x vec %x\n")
451 POPR
4523: moval 0f,-8(fp); ret # pop callf frame...
4530: rei # ...and return
454
57a0bdb5
SL
455/*
456 * Trap and fault vector routines
457 */
458#define TRAP(a) pushl $T_/**/a; jbr alltraps
459
460/*
461 * Ast delivery (profiling and/or reschedule)
462 */
57a0bdb5
SL
463
464SCBVEC(kspnotval):
465 CHECK_SFE(4)
466 pushl $0;
467 SAVE_FPSTAT(8)
468 TRAP(KSPNOTVAL)
469SCBVEC(privinflt):
470 CHECK_SFE(4)
471 pushl $0;
472 SAVE_FPSTAT(8)
473 TRAP(PRIVINFLT)
474SCBVEC(resopflt):
475 CHECK_SFE(4)
476 pushl $0;
477 SAVE_FPSTAT(8)
478 TRAP(RESOPFLT)
479SCBVEC(resadflt):
480 CHECK_SFE(4)
481 pushl $0;
482 SAVE_FPSTAT(8)
483 TRAP(RESADFLT)
484SCBVEC(bptflt):
485 CHECK_SFE(4)
486 pushl $0;
487 SAVE_FPSTAT(8)
488 TRAP(BPTFLT)
11b6ca93
SL
489SCBVEC(kdbintr):
490 CHECK_SFE(4);
491 pushl $0;
492 SAVE_FPSTAT(8);
493 TRAP(KDBTRAP);
57a0bdb5
SL
494SCBVEC(tracep):
495 CHECK_SFE(4)
496 pushl $0;
497 SAVE_FPSTAT(8)
498 TRAP(TRCTRAP)
499SCBVEC(alignflt):
82bf8967 500#ifdef ALIGN
44622fe3
SL
501 bitl $PSL_CURMOD,4(sp)
502 jeql align_excp # Can't emulate for kernel mode !
503 jbr non_aligned # Only emulated for user mode.
504align_excp:
505#else
57a0bdb5 506 CHECK_SFE(4)
44622fe3 507#endif
57a0bdb5
SL
508 pushl $0;
509 SAVE_FPSTAT(8)
510 TRAP(ALIGNFLT)
511SCBVEC(arithtrap):
512 CHECK_SFE(8)
513 SAVE_FPSTAT(8)
514 TRAP(ARITHTRAP)
515
516SCBVEC(protflt):
517 CHECK_SFE(12)
518 bitl $1,(sp)+
519 jneq segflt
520 SAVE_FPSTAT(8)
521 TRAP(PROTFLT)
522segflt:
523 SAVE_FPSTAT(8)
524 TRAP(SEGFLT)
525
a55e280b 526SCBVEC(fpm): # Floating Point Emulation
82bf8967 527#ifdef FPE
57a0bdb5
SL
528 CHECK_SFE(16)
529 SAVE_FPSTAT(16)
44622fe3 530 incl _cnt+V_FPE # count emulation traps
57a0bdb5
SL
531 callf $4,_fpemulate
532 REST_FPSTAT
82bf8967 533#endif
57a0bdb5
SL
534 moval 8(sp),sp # Pop operand
535 tstl (sp) # Stack= PSL, PC, return_code
536 jneq _Xarithtrap # If not OK, emulate F.P. exception
537 movab 4(sp),sp # Else remove return_code and
538 rei
539
540SCBVEC(sfexcep):
541 CHECK_SFE(4)
542 pushl $0
543 SAVE_FPSTAT(8)
544 TRAP(ASTFLT)
545
546SCBVEC(transflt):
547 CHECK_SFE(12)
23f9abf2 548 bitl $2,(sp)+
57a0bdb5
SL
549 bneq tableflt
550pageflt:
551 SAVE_FPSTAT(8)
552 TRAP(PAGEFLT)
553tableflt:
554 SAVE_FPSTAT(8)
555 TRAP(TABLEFLT)
556
557#define REST_STACK movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp
558
559alltraps:
560 mfpr $USP,-(sp);
a55e280b
SL
561 callf $4,_trap;
562 mtpr (sp)+,$USP
57a0bdb5 563 incl _cnt+V_TRAP
a55e280b 564 REST_STACK # pop type, code, and fp stuff
57a0bdb5
SL
565 mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
566 rei
567
568SCBVEC(syscall):
569 CHECK_SFE(8)
570 SAVE_FPSTAT(8)
571 pushl $T_SYSCALL
a55e280b
SL
572 mfpr $USP,-(sp);
573 callf $4,_syscall;
574 mtpr (sp)+,$USP
57a0bdb5 575 incl _cnt+V_SYSCALL
a55e280b 576 REST_STACK # pop type, code, and fp stuff
57a0bdb5
SL
577 mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT)
578 rei
579
580/*
741dff62
SL
581 * System page table.
582 *
56ad8000
SL
583 * Mbmap and Usrptmap are enlarged by CLSIZE entries
584 * as they are managed by resource maps starting with index 1 or CLSIZE.
57a0bdb5
SL
585 */
586#define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM)
587#define SYSMAP(mname, vname, npte) \
588_/**/mname: .globl _/**/mname; \
56ad8000 589 .space (npte)*4; \
57a0bdb5
SL
590 .globl _/**/vname; \
591 .set _/**/vname,vaddr(_/**/mname)
bd08bc0f 592#define ADDMAP(npte) .space (npte)*4
57a0bdb5
SL
593
594 .data
595 .align 2
596 SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE )
57a0bdb5
SL
597 SYSMAP(Forkmap ,forkutl ,UPAGES )
598 SYSMAP(Xswapmap ,xswaputl ,UPAGES )
599 SYSMAP(Xswap2map,xswap2utl ,UPAGES )
600 SYSMAP(Swapmap ,swaputl ,UPAGES )
601 SYSMAP(Pushmap ,pushutl ,UPAGES )
602 SYSMAP(Vfmap ,vfutl ,UPAGES )
57a0bdb5
SL
603 SYSMAP(CMAP1 ,CADDR1 ,1 )
604 SYSMAP(CMAP2 ,CADDR2 ,1 )
605 SYSMAP(mmap ,vmmap ,1 )
56ad8000 606 SYSMAP(alignmap ,alignutl ,1 ) /* XXX */
57a0bdb5 607 SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT )
fe52348b 608 SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
f4ce19c1
KM
609#ifdef MFS
610#include "../ufs/mfsiom.h"
611 /*
612 * Used by the mfs_doio() routine for physical I/O
613 */
614 SYSMAP(Mfsiomap ,mfsiobuf ,MFS_MAPREG )
615#endif /* MFS */
660fb61d 616#ifdef NFS
f4ce19c1 617#include "../nfs/nfsiom.h"
660fb61d 618 /*
f4ce19c1 619 * Used by the nfs_doio() routine for physical I/O
660fb61d 620 */
f4ce19c1 621 SYSMAP(Nfsiomap ,nfsiobuf ,NFS_MAPREG )
660fb61d 622#endif /* NFS */
1a2ba97f
KM
623 /*
624 * This is the map used by the kernel memory allocator.
625 * It is expanded as necessary by the special features
626 * that use it.
627 */
278eb892 628 SYSMAP(kmempt ,kmembase ,1000*CLSIZE )
1a2ba97f
KM
629#ifdef GPROF
630 ADDMAP( 600*CLSIZE )
631#endif
220741c6
KM
632 /*
633 * Enlarge kmempt as needed for bounce buffers allocated
634 * by tahoe controllers.
635 */
fe52348b
KB
636#include "hd.h"
637#if NHD > 0
638 ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
639#endif
220741c6 640#include "dk.h"
fe52348b 641#if NDK > 0
bd08bc0f 642 ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
fe52348b 643#endif
34544495 644#include "yc.h"
220741c6 645#include "yc.h"
fe52348b 646#if NYC > 0
bd08bc0f 647 ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
fe52348b 648#endif
4eaa1510 649#include "mp.h"
bd08bc0f 650 ADDMAP( NMP*14 )
34544495 651 SYSMAP(ecamap ,calimit ,0 )
220741c6 652 SYSMAP(ekmempt ,kmemlimit ,0 )
4eaa1510 653
56ad8000 654 SYSMAP(VMEMbeg ,vmembeg ,0 )
741dff62 655 SYSMAP(VMEMmap ,vmem ,VBIOSIZE )
220741c6
KM
656 SYSMAP(VMEMmap1 ,vmem1 ,0 )
657#include "ace.h"
6b2dc957 658#if NACE > 0
bd08bc0f 659 ADDMAP( NACE*32 )
6b2dc957
KB
660#endif
661#if NHD > 0
662 ADDMAP( NHDC )
9994fc90
MK
663#endif
664#include "vx.h"
665#if NVX > 0
666 ADDMAP( NVX * 16384/NBPG )
6b2dc957 667#endif
56ad8000 668 SYSMAP(VMEMend ,vmemend ,0 )
4eaa1510 669
23f9abf2 670 SYSMAP(VBmap ,vbbase ,CLSIZE )
fe52348b
KB
671#if NHD > 0
672 ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
673#endif
674#if NDK > 0
bd08bc0f 675 ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
fe52348b
KB
676#endif
677#if NYC > 0
bd08bc0f 678 ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
fe52348b 679#endif
bd08bc0f 680 ADDMAP( NMP*14 )
741dff62 681 SYSMAP(eVBmap ,vbend ,0 )
4eaa1510 682
56ad8000 683 SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE )
57a0bdb5
SL
684eSysmap:
685 .globl _Syssize
686 .set _Syssize,(eSysmap-_Sysmap)/4
687
688 .text
689/*
690 * Initialization
691 *
692 * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set
57a0bdb5 693 */
57a0bdb5
SL
694 .align 2
695 .globl start
696start:
697 .word 0
57a0bdb5 698/* set system control block base and system page table params */
57a0bdb5
SL
699 mtpr $_scb-SYSTEM,$SCBB
700 mtpr $_Sysmap-SYSTEM,$SBR
701 mtpr $_Syssize,$SLR
57a0bdb5 702/* double map the kernel into the virtual user addresses of phys mem */
57a0bdb5
SL
703 mtpr $_Sysmap,$P0BR
704 mtpr $_Syssize,$P0LR
a55e280b 705 mtpr $_Sysmap,$P1BR # against Murphy
57a0bdb5 706 mtpr $_Syssize,$P1LR
57a0bdb5 707/* set ISP */
a55e280b 708 movl $_intstack-SYSTEM+NISP*NBPG,sp # still physical
57a0bdb5 709 mtpr $_intstack+NISP*NBPG,$ISP
9994fc90 710/* count up memory; _physmem contains limit */
57a0bdb5 711 clrl r7
9994fc90
MK
712 shll $PGSHIFT,_physmem,r8
713 decl r8
57a0bdb5 7141: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f
9994fc90 715 ACBL(r8,$64*1024,r7,1b)
57a0bdb5
SL
7169:
717/* clear memory from kernel bss and pages for proc 0 u. and page table */
11b6ca93
SL
718 movab _edata,r6; andl2 $~SYSTEM,r6
719 movab _end,r5; andl2 $~SYSTEM,r5
c8d6c8bc 720#ifdef KADB
11b6ca93
SL
721 subl2 $4,r5
7221: clrl (r6); ACBL(r5,$4,r6,1b) # clear just bss
723 addl2 $4,r5
724 bbc $6,r11,0f # check RB_KDB
725 andl3 $~SYSTEM,r9,r5 # skip symbol & string tables
726 andl3 $~SYSTEM,r9,r6
727#endif
7280: orl3 $SYSTEM,r5,r9 # convert to virtual address
729 addl2 $NBPG-1,r9 # roundup to next page
57a0bdb5 730 addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5
a55e280b
SL
7311: clrl (r6); ACBL(r5,$4,r6,1b)
732/* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */
57a0bdb5
SL
733 orw2 $0x01fff,_trap
734 orw2 $0x01fff,_syscall
82bf8967 735#ifdef FPE
57a0bdb5 736 orw2 $0x01fff,_fpemulate
82bf8967 737#endif
a55e280b 738 orw2 $0x01ffc,_panic # for debugging (no r0|r1)
56ad8000 739 callf $4,_fixctlrmask # setup for autoconfig
57a0bdb5
SL
740/* initialize system page table: scb and int stack writeable */
741 clrl r2
742 movab eintstack,r1
a55e280b
SL
743 andl2 $~SYSTEM,r1
744 shrl $PGSHIFT,r1,r1 # r1-page number of eintstack
04d1fc31 745/* make 1st page processor storage read/only, 2nd read/write */
57a0bdb5 746 orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2;
04d1fc31 747 orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; incl r2;
a55e280b
SL
748/* other parts of the system are read/write for kernel */
7491: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write+phys=virtual
57a0bdb5 750 aoblss r1,r2,1b
57a0bdb5 751/* make rsstk read-only as red zone for interrupt stack */
a55e280b
SL
752 andl2 $~PG_PROT,_rsstkmap
753 orl2 $PG_V|PG_KR,_rsstkmap
57a0bdb5 754/* make kernel text space read-only */
57a0bdb5 755 movab _etext+NBPG-1,r1
a55e280b 756 andl2 $~SYSTEM,r1
57a0bdb5
SL
757 shrl $PGSHIFT,r1,r1
7581: orl3 $PG_V|PG_KR,r2,_Sysmap[r2]
759 aoblss r1,r2,1b
57a0bdb5 760/* make kernel data, bss, read-write */
11b6ca93 761 andl3 $~SYSTEM,r9,r1
57a0bdb5
SL
762 shrl $PGSHIFT,r1,r1
7631: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]
764 aoblss r1,r2,1b
a55e280b 765/* go to mapped mode, have to change both pc and sp to system addresses */
57a0bdb5 766 mtpr $1,$TBIA
a55e280b
SL
767 mtpr $1,$PADC # needed by HW parity&ECC logic
768 mtpr $1,$PACC # just in case
57a0bdb5
SL
769 mtpr $1,$MME
770 movab SYSTEM(sp),sp
57a0bdb5
SL
771 jmp *$0f
7720:
57a0bdb5
SL
773/* disable any interrupts */
774 movl $0,_intenable
775/* init mem sizes */
9994fc90 776 shrl $PGSHIFT,r7,_physmem
a55e280b 777/* setup context for proc[0] == scheduler */
11b6ca93 778 andl3 $~SYSTEM,r9,r6 # convert to physical
a55e280b 779 andl2 $~(NBPG-1),r6 # make page boundary
57a0bdb5
SL
780/* setup page table for proc[0] */
781 shrl $PGSHIFT,r6,r3 # r3 = btoc(r6)
782 orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry
783 incl r3 # r3 - next page
784 movab _usrpt,r0 # r0 - first user page
785 mtpr r0,$TBIS
57a0bdb5 786/* init p0br, p0lr */
a55e280b 787 mtpr r0,$P0BR # no p0 for proc[0]
57a0bdb5 788 mtpr $0,$P0LR
a55e280b 789 mtpr r0,$P1BR # no p1 either
57a0bdb5 790 mtpr $0,$P1LR
57a0bdb5
SL
791/* init p2br, p2lr */
792 movab NBPG(r0),r0
793 movl $PPAGES-UPAGES,r1
794 mtpr r1,$P2LR
795 moval -4*PPAGES(r0),r2
796 mtpr r2,$P2BR
57a0bdb5 797/* setup mapping for UPAGES of _u */
a55e280b 798 clrl r2
57a0bdb5
SL
799 movl $SYSTEM,r1
800 addl2 $UPAGES,r3
801 jbr 2f
8021: decl r3
a55e280b 803 moval -NBPG(r1),r1 # r1 = virtual add of next (downward) _u page
57a0bdb5
SL
804 subl2 $4,r0 # r0 = pte address
805 orl3 $PG_V|PG_URKW,r3,(r0)
806 mtpr r1,$TBIS
8072: aobleq $UPAGES,r2,1b
57a0bdb5
SL
808/* initialize (slightly) the pcb */
809 movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u
810 movl r1,PCB_USP(r1) # USP starts just below _u
811 mfpr $P0BR,PCB_P0BR(r1)
812 mfpr $P0LR,PCB_P0LR(r1)
813 mfpr $P1BR,PCB_P1BR(r1)
814 mfpr $P1LR,PCB_P1LR(r1)
815 mfpr $P2BR,PCB_P2BR(r1)
816 mfpr $P2LR,PCB_P2LR(r1)
817 movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt
11b6ca93
SL
818 movl r9,PCB_R9(r1) # r9 obtained from boot
819 movl r10,PCB_R10(r1) # r10 obtained from boot
57a0bdb5
SL
820 movl r11,PCB_R11(r1) # r11 obtained from CP on boot
821 movab 1f,PCB_PC(r1) # initial pc
822 clrl PCB_PSL(r1) # kernel mode, ipl=0
57a0bdb5 823 shll $PGSHIFT,r3,r3
a55e280b
SL
824 mtpr r3,$PCBB # first pcbb (physical)
825/* go to kernel mode */
57a0bdb5 826 ldpctx
a55e280b 827 rei # Actually next instruction:
57a0bdb5 828/* put signal trampoline code in u. area */
a55e280b
SL
8291: movab sigcode,r0
830 movab _u+PCB_SIGC,r1
831 movl $19,r2
832 movblk
1e20e4cf
SL
833/* save boot device in global _bootdev */
834 movl r10,_bootdev
57a0bdb5
SL
835/* save reboot flags in global _boothowto */
836 movl r11,_boothowto
5c56ac01 837#ifdef KADB
11b6ca93
SL
838/* save end of symbol & string table in global _bootesym */
839 subl3 $NBPG-1,r9,_bootesym
5c56ac01 840#endif
57a0bdb5 841/* calculate firstaddr, and call main() */
11b6ca93 842 andl3 $~SYSTEM,r9,r0
57a0bdb5 843 shrl $PGSHIFT,r0,-(sp)
a55e280b 844 addl2 $UPAGES+1,(sp) # first physical unused page
57a0bdb5 845 callf $8,_main
57a0bdb5 846/* proc[1] == /etc/init now running here in kernel mode; run icode */
a55e280b
SL
847 pushl $PSL_CURMOD # User mode PSL
848 pushl $0 # PC = 0 (virtual now)
57a0bdb5
SL
849 rei
850
a55e280b
SL
851/*
852 * Mask for saving/restoring registers on entry to
853 * a user signal handler. Space for the registers
854 * is reserved in sendsig, so beware if you want
855 * to change the mask.
856 */
857#define SIGREGS (R0|R1|R2|R3|R4|R5)
858 .align 2
859 .globl sigcode
860sigcode:
861 storer $SIGREGS,16(sp) # save volatile registers
862 calls $4*3+4,*12(sp) # params pushed by sendsig for handler
863 loadr $SIGREGS,4(sp) # restore volatile registers
864 movab 24(sp),fp # use parameter list set up in sendsig
865 kcall $SYS_sigreturn # cleanup mask and onsigstack
866 halt # sigreturn does not return!
867
868 .globl _icode
869 .globl _initflags
870 .globl _szicode
871/*
872 * Icode is copied out to process 1 to exec /etc/init.
873 * If the exec fails, process 1 exits.
874 */
57a0bdb5 875 .align 2
a55e280b 876_icode:
59d74239
KB
877 /* try /sbin/init */
878 pushab b`argv1-l0(pc)
879l0: pushab b`init1-l1(pc)
a55e280b
SL
880l1: pushl $2
881 movab (sp),fp
882 kcall $SYS_execv
59d74239
KB
883 /* try /etc/init */
884 pushab b`argv2-l2(pc)
885l2: pushab b`init2-l3(pc)
886l3: pushl $2
887 movab (sp),fp
888 kcall $SYS_execv
889 /* give up */
9f1a98cd 890 pushl r0
59d74239
KB
891 pushl $1
892 movab (sp),fp
a55e280b
SL
893 kcall $SYS_exit
894
59d74239
KB
895init1: .asciz "/sbin/init"
896init2: .asciz "/etc/init"
a55e280b
SL
897 .align 2
898_initflags:
899 .long 0
59d74239
KB
900argv1: .long init1+6-_icode
901 .long _initflags-_icode
902 .long 0
903argv2: .long init2+5-_icode
a55e280b
SL
904 .long _initflags-_icode
905 .long 0
906_szicode:
907 .long _szicode-_icode
57a0bdb5
SL
908
909/*
910 * Primitives
911 */
912
913/*
914 * badaddr(addr, len)
915 * see if access addr with a len type instruction causes a machine check
916 * len is length of access (1=byte, 2=short, 4=long)
917 * r0 = 0 means good(exists); r0 =1 means does not exist.
918 */
a55e280b 919ENTRY(badaddr, R3|R4)
57a0bdb5
SL
920 mfpr $IPL,r1
921 mtpr $HIGH,$IPL
56ad8000 922 movl _scb+SCB_BUSERR,r2
57a0bdb5
SL
923 movl 4(fp),r3
924 movl 8(fp),r4
56ad8000 925 movab 9f,_scb+SCB_BUSERR
57a0bdb5
SL
926 bbc $0,r4,1f; tstb (r3)
9271: bbc $1,r4,1f; tstw (r3)
9281: bbc $2,r4,1f; tstl (r3)
a55e280b 9291: clrl r0
e05cf6d8
KB
9302: movl r2,_scb+SCB_BUSERR
931 mtpr r1,$IPL
932 ret
933
934/*
935 * wbadaddr(addr, len, value)
936 * see if write of value to addr with a len type instruction causes
937 * a machine check
938 * len is length of access (1=byte, 2=short, 4=long)
939 * r0 = 0 means good(exists); r0 =1 means does not exist.
940 */
941ENTRY(wbadaddr, R3|R4)
942 mfpr $IPL,r1
943 mtpr $HIGH,$IPL
944 movl _scb+SCB_BUSERR,r2
945 movl 4(fp),r3
946 movl 8(fp),r4
947 movab 9f,_scb+SCB_BUSERR
948 bbc $0,r4,1f; movb 15(fp), (r3)
9491: bbc $1,r4,1f; movw 14(fp), (r3)
9501: bbc $2,r4,1f; movl 12(fp), (r3)
9994fc90
MK
9511: movl $30000,r0 # delay for error interrupt
9521: decl r0
953 jneq 1b
9542: movl r2,_scb+SCB_BUSERR # made it w/o machine checks; r0 is 0
57a0bdb5
SL
955 mtpr r1,$IPL
956 ret
957
958 .align 2
a55e280b 9599: # catch buss error (if it comes)
57a0bdb5
SL
960 andl3 4(sp),$ERRCD,r0
961 cmpl r0,$APE
962 jneq 1f
a55e280b 963 halt # address parity error
57a0bdb5
SL
9641: cmpl r0,$VBE
965 jneq 1f
966 halt # Versabus error
9671:
968 movl $1,r0 # Anything else = bad address
969 movab 8(sp),sp # discard buss error trash
970 movab 2b,(sp) # new program counter on stack.
971 rei
972
57a0bdb5
SL
973/*
974 * badcyaddr(addr)
975 * see if access tape master controller addr causes a bus error
976 * r0 = 0: no error; r0 = 1: timeout error.
977 */
a55e280b 978ENTRY(badcyaddr, 0)
57a0bdb5
SL
979 mfpr $IPL,r1
980 mtpr $HIGH,$IPL
a55e280b
SL
981 clrl r2
982 movab 2f,nofault
57a0bdb5 983 movob $-1, *4(fp)
a55e280b
SL
9841: aobleq $1000, r2, 1b
985 clrl nofault # made it w/o bus error
986 clrl r0
987 jbr 3f
9882: movl $1,r0
9893: mtpr r1,$IPL
57a0bdb5
SL
990 ret
991
a55e280b
SL
992/*
993 * peek(addr)
994 * fetch word and catch any bus error
995 */
996ENTRY(peek, 0)
997 mfpr $IPL,r1
998 mtpr $0x18,$IPL # not reentrant
999 movl 4(fp),r2
1000 movab 1f,nofault
1001 movw (r2),r0
1002 clrl nofault
1003 andl2 $0xffff,r0
1004 jbr 2f
10051: movl $-1,r0 # bus error
10062: mtpr r1,$IPL
1007 ret
57a0bdb5 1008
a55e280b
SL
1009/*
1010 * poke(addr, val)
1011 * write word and catch any bus error
1012 */
1013ENTRY(poke, R3)
1014 mfpr $IPL,r1
1015 mtpr $0x18,$IPL # not reentrant
1016 movl 4(fp),r2
1017 movl 8(fp),r3
1018 clrl r0
1019 movab 1f,nofault
1020 movw r3,(r2)
1021 clrl nofault
1022 jbr 2f
10231: movl $-1,r0 # bus error
10242: mtpr r1,$IPL
57a0bdb5
SL
1025 ret
1026
a55e280b
SL
1027/*
1028 * Copy a potentially overlapping block of memory.
1029 *
1030 * ovbcopy(src, dst, count)
1031 * caddr_t src, dst; unsigned count;
1032 */
1033ENTRY(ovbcopy, R3|R4)
57a0bdb5
SL
1034 movl 4(fp),r0
1035 movl 8(fp),r1
1036 movl 12(fp),r2
1037 cmpl r0,r1
a55e280b
SL
1038 bgtru 1f # normal forward case
1039 beql 2f # equal, nothing to do
1040 addl2 r2,r0 # may be overlapping
57a0bdb5
SL
1041 cmpl r0,r1
1042 bgtru 3f
a55e280b 1043 subl2 r2,r0 # normal forward case
57a0bdb5
SL
10441:
1045 movblk
10462:
1047 ret
10483:
a55e280b 1049 addl2 r2,r1 # overlapping, must do backwards
57a0bdb5
SL
1050 subl3 r0,r1,r3
1051 movl r2,r4
1052 jbr 5f
10534:
1054 subl2 r3,r0
1055 subl2 r3,r1
1056 movl r3,r2
1057 movblk
1058 subl2 r3,r0
1059 subl2 r3,r1
1060 subl2 r3,r4
10615:
1062 cmpl r4,r3
1063 jgtr 4b
1064 movl r4,r2
1065 subl2 r2,r0
1066 subl2 r2,r1
1067 movblk
1068 ret
1069
1070/*
a55e280b
SL
1071 * Copy a null terminated string from the user address space into
1072 * the kernel address space.
1073 *
1074 * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
57a0bdb5 1075 */
36d595e6 1076ENTRY(copyinstr, 0)
a55e280b 1077 movl 12(fp),r5 # r5 = max length
36d595e6
KM
1078 jlss 5f
1079 movl 8(fp),r4 # r4 = kernel address
a55e280b 1080 movl 4(fp),r0 # r0 = user address
a55e280b
SL
1081 andl3 $(NBPG*CLSIZE-1),r0,r2 # r2 = bytes on first page
1082 subl3 r2,$(NBPG*CLSIZE),r2
a55e280b
SL
10831:
1084 cmpl r5,r2 # r2 = min(bytes on page, length left);
1085 jgeq 2f
1086 movl r5,r2
10872:
1088 prober $1,(r0),r2 # bytes accessible?
36d595e6 1089 jeql 5f
a55e280b 1090 subl2 r2,r5 # update bytes left count
36d595e6
KM
1091 movl r2,r3 # r3 = saved count
1092 movl r0,r1
1093 cmps3 # check for null
1094 tstl r2
a55e280b 1095 jneq 3f
36d595e6
KM
1096 subl2 r3,r0 # back up r0
1097 movl r4,r1
1098 movl r3,r2
1099 movblk # copy in next piece
1100 movl r1,r4
a55e280b
SL
1101 movl $(NBPG*CLSIZE),r2 # check next page
1102 tstl r5 # run out of space?
1103 jneq 1b
1104 movl $ENOENT,r0 # set error code and return
36d595e6 1105 jbr 6f
a55e280b
SL
11063:
1107 tstl 16(fp) # return length?
1108 beql 4f
1109 subl3 r5,12(fp),r5 # actual len = maxlen - unused pages
1110 subl2 r2,r5 # - unused on this page
1111 addl3 $1,r5,*16(fp) # + the null byte
11124:
36d595e6
KM
1113 movl r4,r1
1114 subl3 r2,r3,r2 # calc char cnt
1115 subl2 r2,r0 # back up r0
1116 incl r2 # add on null byte
1117 movblk # copy last piece
a55e280b 1118 clrl r0
57a0bdb5 1119 ret
36d595e6 11205:
a55e280b 1121 movl $EFAULT,r0
36d595e6 11226:
a55e280b 1123 tstl 16(fp)
36d595e6 1124 beql 7f
a55e280b 1125 subl3 r5,12(fp),*16(fp)
36d595e6 11267:
a55e280b
SL
1127 ret
1128
1129/*
1130 * Copy a null terminated string from the kernel
1131 * address space to the user address space.
1132 *
1133 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
1134 */
36d595e6 1135ENTRY(copyoutstr, 0)
a55e280b 1136 movl 12(fp),r5 # r5 = max length
b224cc0b 1137 jlss 5f
a55e280b 1138 movl 4(fp),r0 # r0 = kernel address
36d595e6
KM
1139 movl 8(fp),r4 # r4 = user address
1140 andl3 $(NBPG*CLSIZE-1),r4,r2 # r2 = bytes on first page
a55e280b 1141 subl3 r2,$(NBPG*CLSIZE),r2
57a0bdb5 11421:
a55e280b
SL
1143 cmpl r5,r2 # r2 = min(bytes on page, length left);
1144 jgeq 2f
1145 movl r5,r2
11462:
36d595e6 1147 probew $1,(r4),r2 # bytes accessible?
b224cc0b 1148 jeql 5f
a55e280b 1149 subl2 r2,r5 # update bytes left count
36d595e6
KM
1150 movl r2,r3 # r3 = saved count
1151 movl r0,r1
dc4c1de6
MK
1152/*
1153 * This is a workaround for a microcode bug that causes
1154 * a trap type 9 when cmps3/movs3 touches the last byte
1155 * on a valid page immediately followed by an invalid page.
1156 */
36d595e6
KM
1157#ifdef good_cmps3
1158 cmps3 # check for null
a55e280b 1159 tstl r2
a55e280b 1160 jneq 3b
36d595e6
KM
1161#else
1162 decl r2
35f6fda7 1163 beql 9f # cannot handle case of r2 == 0!
36d595e6 1164 cmps3 # check for null up to last byte
35f6fda7 11659:
36d595e6
KM
1166 incl r2
1167 cmpl $1,r2 # get to last byte on page?
1168 bneq 3b
1169 tstb (r0) # last byte on page null?
35f6fda7 1170 beql 3b
36d595e6 1171 incl r0 # not null, so bump pointer
35f6fda7 1172#endif not good_cmps3
36d595e6
KM
1173 subl2 r3,r0 # back up r0
1174 movl r4,r1
1175 movl r3,r2
1176 movblk # copy out next piece
1177 movl r1,r4
a55e280b
SL
1178 movl $(NBPG*CLSIZE),r2 # check next page
1179 tstl r5 # run out of space?
1180 jneq 1b
1181 movl $ENOENT,r0 # set error code and return
36d595e6 1182 jbr 6b
b224cc0b
KM
11835:
1184 clrl *$0 # this should never execute, if it does
1185 movl $EFAULT,r0 # save me a core dump (mkm - 9/87)
11866:
1187 tstl 16(fp)
1188 beql 7f
1189 subl3 r5,12(fp),*16(fp)
11907:
1191 ret
1192
57a0bdb5 1193
a55e280b
SL
1194/*
1195 * Copy a null terminated string from one point to another in
1196 * the kernel address space.
1197 *
1198 * copystr(fromaddr, toaddr, maxlength, &lencopied)
1199 */
36d595e6
KM
1200ENTRY(copystr, 0)
1201 movl 12(fp),r3 # r3 = max length
1202 jlss 5b
a55e280b 1203 movl 4(fp),r0 # r0 = src address
36d595e6
KM
1204 movl 8(fp),r4 # r4 = dest address
1205 clrl r5 # r5 = bytes left
1206 movl r3,r2 # r2 = max bytes to copy
1207 movl r0,r1
1208 cmps3 # check for null
1209 tstl r2
a55e280b 1210 jneq 3b
36d595e6
KM
1211 subl2 r3,r0 # back up r0
1212 movl r4,r1
1213 movl r3,r2
1214 movblk # copy next piece
a55e280b 1215 movl $ENOENT,r0 # set error code and return
36d595e6 1216 jbr 6b
57a0bdb5 1217
a55e280b
SL
1218/*
1219 * Copy a block of data from the user address space into
1220 * the kernel address space.
1221 *
1222 * copyin(fromaddr, toaddr, count)
1223 */
1224ENTRY(copyin, 0)
57a0bdb5 1225 movl 12(fp),r0 # copy length
a55e280b 1226 blss 9f
57a0bdb5 1227 movl 4(fp),r1 # copy user address
a55e280b
SL
1228 cmpl $(CLSIZE*NBPG),r0 # probing one page or less ?
1229 bgeq 2f # yes
12301:
1231 prober $1,(r1),$(CLSIZE*NBPG) # bytes accessible ?
1232 beql 9f # no
1233 addl2 $(CLSIZE*NBPG),r1 # incr user address ptr
1234 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop
12352:
57a0bdb5 1236 prober $1,(r1),r0 # bytes accessible ?
a55e280b
SL
1237 beql 9f # no
1238 MOVC3(4(fp),8(fp),12(fp))
57a0bdb5
SL
1239 clrl r0
1240 ret
a55e280b 12419:
57a0bdb5
SL
1242 movl $EFAULT,r0
1243 ret
1244
a55e280b
SL
1245/*
1246 * Copy a block of data from the kernel
1247 * address space to the user address space.
1248 *
1249 * copyout(fromaddr, toaddr, count)
1250 */
1251ENTRY(copyout, 0)
57a0bdb5 1252 movl 12(fp),r0 # get count
a55e280b 1253 blss 9b
57a0bdb5 1254 movl 8(fp),r1 # get user address
a55e280b
SL
1255 cmpl $(CLSIZE*NBPG),r0 # can do in one probew?
1256 bgeq 2f # yes
12571:
1258 probew $1,(r1),$(CLSIZE*NBPG) # bytes accessible?
1259 beql 9b # no
1260 addl2 $(CLSIZE*NBPG),r1 # increment user address
1261 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop
12622:
57a0bdb5 1263 probew $1,(r1),r0 # bytes accessible?
a55e280b
SL
1264 beql 9b # no
1265 MOVC3(4(fp),8(fp),12(fp))
57a0bdb5
SL
1266 clrl r0
1267 ret
1268
1269/*
4615bc77 1270 * savectx is like setjmp but saves all registers.
a55e280b
SL
1271 * Called before swapping out the u. area, restored by resume()
1272 * below.
1273 */
1274ENTRY(savectx, 0)
1275 movl 4(fp),r2
1276 storer $0x1ff8,(r2); addl2 $40,r2 # r3-r12
1277 movl (fp),(r2); addl2 $4,r2 # fp
1278 movab 8(fp),(r2); addl2 $4,r2 # sp
1279 movl -8(fp),(r2) # pc
1280 clrl r0
1281 ret
57a0bdb5 1282
c8d6c8bc 1283#ifdef KADB
11b6ca93 1284/*
4615bc77 1285 * C library -- reset, setexit -- XXX
11b6ca93
SL
1286 *
1287 * reset(x)
1288 * will generate a "return" from
1289 * the last call to
1290 * setexit()
1291 * by restoring r2 - r12, fp
1292 * and doing a return.
1293 * The returned value is x; on the original
1294 * call the returned value is 0.
1295 */
1296ENTRY(setexit, 0)
1297 movab setsav,r0
1298 storer $0x1ffc, (r0)
1299 movl (fp),44(r0) # fp
1300 moval 4(fp),48(r0) # sp
1301 movl -8(fp),52(r0) # pc
1302 clrl r0
1303 ret
1304
1305ENTRY(reset, 0)
1306 movl 4(fp),r0 # returned value
1307 movab setsav,r1
1308 loadr $0x1ffc,(r1)
1309 movl 44(r1),fp
1310 movl 48(r1),sp
1311 jmp *52(r1)
1312
1313 .data
1314 .align 2
1315setsav: .space 14*4
1316 .text
1317#endif
1318
57a0bdb5
SL
1319 .globl _whichqs
1320 .globl _qs
1321 .globl _cnt
1322
1323 .globl _noproc
1324 .comm _noproc,4
1325 .globl _runrun
1326 .comm _runrun,4
57a0bdb5
SL
1327/*
1328 * The following primitives use the fancy TAHOE instructions.
1329 * _whichqs tells which of the 32 queues _qs
1330 * have processes in them. setrq puts processes into queues, remrq
1331 * removes them from queues. The running process is on no queue,
1332 * other processes are on a queue related to p->p_pri, divided by 4
1333 * actually to shrink the 0-127 range of priorities into the 32 available
1334 * queues.
1335 */
1336
1337/*
1338 * setrq(p), using fancy TAHOE instructions.
1339 *
1340 * Call should be made at spl8(), and p->p_stat should be SRUN
1341 */
a55e280b 1342ENTRY(setrq, 0)
57a0bdb5
SL
1343 movl 4(fp),r0
1344 tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0
1345 beql set1 ##
1346 pushab set3 ##
1347 callf $8,_panic ##
1348set1:
1349 movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4
1350 shar $2,r1,r1
1351 shal $1,r1,r2
1352 moval _qs[r2],r2
1353 insque (r0),*4(r2) # at end of queue
1354 shal r1,$1,r1
1355 orl2 r1,_whichqs # mark queue non-empty
1356 ret
1357
1358set3: .asciz "setrq"
1359
1360/*
1361 * remrq(p), using fancy TAHOE instructions
1362 *
1363 * Call should be made at spl8().
1364 */
a55e280b 1365ENTRY(remrq, 0)
57a0bdb5
SL
1366 movl 4(fp),r0
1367 movzbl P_PRI(r0),r1
1368 shar $2,r1,r1
1369 bbs r1,_whichqs,rem1
1370 pushab rem3 # it wasn't recorded to be on its q
1371 callf $8,_panic
1372rem1:
1373 remque (r0)
1374 bneq rem2 # q not empty yet
1375 shal r1,$1,r1
1376 mcoml r1,r1
1377 andl2 r1,_whichqs # mark queue empty
1378rem2:
1379 clrl P_RLINK(r0) ## for firewall checking
1380 ret
1381
1382rem3: .asciz "remrq"
1383
57a0bdb5
SL
1384/*
1385 * Masterpaddr is the p->p_addr of the running process on the master
1386 * processor. When a multiprocessor system, the slave processors will have
1387 * an array of slavepaddr's.
1388 */
1389 .globl _masterpaddr
1390 .data
11b6ca93 1391 .align 2
a55e280b 1392_masterpaddr: .long 0
57a0bdb5
SL
1393
1394 .text
1395sw0: .asciz "swtch"
04d1fc31
MK
1396
1397/*
1398 * When no processes are on the runq, swtch branches to idle
1399 * to wait for something to come ready.
1400 */
1401 .globl Idle
1402Idle: idle:
10946d75 1403 movl $1,_noproc
04d1fc31
MK
1404 mtpr $0,$IPL # must allow interrupts here
14051:
1406 tstl _whichqs # look for non-empty queue
1407 bneq sw1
1408 brb 1b
1409
1410badsw: pushab sw0
1411 callf $8,_panic
1412 /* NOTREACHED */
1413
1414 .align 2
57a0bdb5 1415/*
a55e280b 1416 * swtch(), using fancy tahoe instructions
57a0bdb5 1417 */
a55e280b 1418ENTRY(swtch, 0)
57a0bdb5
SL
1419 movl (fp),fp # prepare for rei
1420 movl (sp),4(sp) # saved pc
1421 tstl (sp)+
1422 movpsl 4(sp)
04d1fc31 1423 incl _cnt+V_SWTCH
57a0bdb5 1424sw1: ffs _whichqs,r0 # look for non-empty queue
04d1fc31
MK
1425 blss idle # if none, idle
1426 mtpr $0x18,$IPL # lock out all so _whichqs==_qs
1427 bbc r0,_whichqs,sw1 # proc moved via interrupt
57a0bdb5
SL
1428 shal $1,r0,r1
1429 moval _qs[r1],r1
1430 movl (r1),r2 # r2 = p = highest pri process
1431 remque *(r1)
04d1fc31
MK
1432 bvs badsw # make sure something was there
1433 bneq sw2
57a0bdb5
SL
1434 shal r0,$1,r1
1435 mcoml r1,r1
1436 andl2 r1,_whichqs # no more procs in this queue
04d1fc31 1437sw2:
57a0bdb5 1438 clrl _noproc
04d1fc31 1439 clrl _runrun
10946d75 1440#ifdef notdef
57a0bdb5 1441 tstl P_WCHAN(r2) ## firewalls
04d1fc31 1442 bneq badsw ##
a2f6e980 1443 cmpb P_STAT(r2),$SRUN ##
04d1fc31 1444 bneq badsw ##
10946d75 1445#endif
57a0bdb5
SL
1446 clrl P_RLINK(r2) ##
1447 movl *P_ADDR(r2),r0
a55e280b 1448#ifdef notdef
04d1fc31 1449 cmpl r0,_masterpaddr # resume of current proc is easy
a55e280b
SL
1450 beql res0
1451#endif
04d1fc31
MK
1452 movl r0,_masterpaddr
1453 shal $PGSHIFT,r0,r0 # r0 = pcbb(p)
57a0bdb5 1454 brb swresume
57a0bdb5 1455
57a0bdb5
SL
1456/*
1457 * resume(pf)
1458 */
a55e280b
SL
1459ENTRY(resume, 0)
1460 shal $PGSHIFT,4(fp),r0 # r0 = pcbb(pf)
57a0bdb5
SL
1461 movl (fp),fp # prepare for rei
1462 movl (sp)+,4(sp) # saved pc
1463 tstl (sp)+
1464 movpsl 4(sp)
1465swresume:
a55e280b 1466 mtpr $0x18,$IPL # no interrupts, please
57a0bdb5
SL
1467 movl _CMAP2,_u+PCB_CMAP2 # yech
1468 REST_ACC # restore original accumulator
1469 svpctx
1470 mtpr r0,$PCBB
1471 ldpctx
1472 movl _u+PCB_CMAP2,_CMAP2 # yech
1473 mtpr $_CADDR2,$TBIS
1474res0:
a55e280b
SL
1475 movl _u+U_PROCP,r2 # r2 = u.u_procp
1476 tstl P_CKEY(r2) # does proc have code key?
1477 bneq 1f
1478 callf $4,_getcodekey # no, give him one
a2f6e980 1479 movl _u+U_PROCP,r2 # r2 = u.u_procp
a55e280b
SL
1480 movl r0,P_CKEY(r2)
14811:
a55e280b
SL
1482 tstl P_DKEY(r2) # does proc have data key?
1483 bneq 1f
1484 callf $4,_getdatakey # no, give him one
a2f6e980 1485 movl _u+U_PROCP,r2 # r2 = u.u_procp
a55e280b
SL
1486 movl r0,P_DKEY(r2)
14871:
1488 mtpr P_CKEY(r2),$CCK # set code cache key
1489 mtpr P_DKEY(r2),$DCK # set data cache key
57a0bdb5 1490 tstl _u+PCB_SSWAP
a55e280b
SL
1491 bneq res1
1492 rei
4615bc77 1493res1: # restore alternate saved context
57a0bdb5
SL
1494 movl _u+PCB_SSWAP,r2
1495 clrl _u+PCB_SSWAP
a55e280b
SL
1496 loadr $0x3ff8,(r2); addl2 $44,r2 # restore r3-r13 (r13=fp)
1497 movl (r2),r1; addl2 $4,r2 # fetch previous sp ...
1498 movab (sp),r0 # ... and current sp and
1499 cmpl r1,r0 # check for credibility,
1500 bgequ 1f # if further up stack ...
1501 pushab 2f; callf $8,_panic # ... panic
1502 /*NOTREACHED*/
15031: # sp ok, complete return
1504 movl r1,sp # restore sp
7cceb27c
KM
1505 pushl $PSL_PRVMOD # kernel mode, ipl 0
1506 pushl (r2) # return address
57a0bdb5 1507 rei
a55e280b 15082: .asciz "ldctx"
57a0bdb5
SL
1509
1510/*
1511 * {fu,su},{byte,word}
1512 */
a55e280b 1513ENTRY(fuword, 0)
57a0bdb5
SL
1514 movl 4(fp), r1
1515 prober $1,(r1),$4 # check access
1516 beql fserr # page unreadable
1517 bitl $1,r1 # check byte alignment
1518 bneq 2f # odd, do byte-word-byte
1519 bitl $2,r1 # check word alignment
1520 bneq 1f # odd, do in 2 words
1521 movl (r1),r0 # move longword
1522 ret
15231:
1524 movw (r1),r0 # move two words
1525 shal $16,r0,r0
1526 movzwl 2(r1),r1 # orw2 sign extends
1527 orl2 r1,r0
1528 ret
15292:
1530 movb (r1),r0 # move byte-word-byte
1531 shal $24,r0,r0
1532 movzwl 1(r1),r2 # orw2 sign extends
1533 shal $8,r2,r2
1534 movzbl 3(r1),r1 # orb2 sign extends
1535 orl2 r2,r1
1536 orl2 r1,r0
1537 ret
1538fserr:
1539 mnegl $1,r0
1540 ret
1541
a55e280b 1542ENTRY(fubyte, 0)
57a0bdb5
SL
1543 prober $1,*4(fp),$1
1544 beql fserr
1545 movzbl *4(fp),r0
1546 ret
1547
a55e280b 1548ENTRY(suword, 0)
57a0bdb5
SL
1549 movl 4(fp), r0
1550 probew $1,(r0),$4 # check access
1551 beql fserr # page unwritable
1552 bitl $1,r0 # check byte alignment
1553 bneq 1f # odd byte boundary
1554 bitl $2,r0 # check word alignment
1555 beql 2f # longword aligned
1556 movw 8(fp),(r0) # move two words
1557 movw 10(fp),2(r0)
1558 jbr 3f
15591:
1560 movb 8(fp),(r0)
1561 movb 9(fp),1(r0)
1562 movb 10(fp),2(r0)
1563 movb 11(fp),3(r0)
1564 jbr 3f
15652:
1566 movl 8(fp),(r0)
15673:
1568 clrl r0
1569 ret
1570
a55e280b 1571ENTRY(subyte, 0)
57a0bdb5
SL
1572 probew $1,*4(fp),$1
1573 beql fserr
1574 movb 11(fp),*4(fp)
1575 clrl r0
1576 ret
1577
1578/*
1579 * Copy 1 relocation unit (NBPG bytes)
1580 * from user virtual address to physical address
1581 */
a55e280b 1582ENTRY(copyseg, 0)
57a0bdb5
SL
1583 orl3 $PG_V|PG_KW,8(fp),_CMAP2
1584 mtpr $_CADDR2,$TBIS # invalidate entry for copy
a55e280b 1585 MOVC3(4(fp),$_CADDR2,$NBPG)
57a0bdb5
SL
1586 ret
1587
1588/*
a55e280b 1589 * Clear a page of memory. The page frame is specified.
57a0bdb5 1590 *
a55e280b 1591 * clearseg(pf);
57a0bdb5 1592 */
a55e280b 1593ENTRY(clearseg, 0)
57a0bdb5
SL
1594 orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1
1595 mtpr $_CADDR1,$TBIS
1596 movl $255,r0 # r0 = limit
1597 clrl r1 # r1 = index of cleared long
15981:
1599 clrl _CADDR1[r1]
1600 aobleq r0,r1,1b
1601 ret
1602
1603/*
a55e280b
SL
1604 * Check user mode read/write access.
1605 *
1606 * useracc(addr, count, mode)
1607 * caddr_t addr; int count, mode;
1608 * mode = 0 write access
1609 * mode = 1 read access
57a0bdb5 1610 */
a55e280b 1611ENTRY(useracc, 0)
57a0bdb5
SL
1612 movl $1,r2 # r2 = 'user mode' for probew/probew
1613probes:
1614 movl 4(fp),r0 # get va
1615 movl 8(fp),r1 # count
1616 tstl 12(fp) # test for read access ?
1617 bneq userar # yes
a55e280b 1618 cmpl $(CLSIZE*NBPG),r1 # can we do it in one probe ?
57a0bdb5
SL
1619 bgeq uaw2 # yes
1620uaw1:
a55e280b 1621 probew r2,(r0),$(CLSIZE*NBPG)
57a0bdb5 1622 beql uaerr # no access
a55e280b
SL
1623 addl2 $(CLSIZE*NBPG),r0
1624 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1)
57a0bdb5
SL
1625uaw2:
1626 probew r2,(r0),r1
1627 beql uaerr
1628 movl $1,r0
1629 ret
57a0bdb5 1630userar:
a55e280b 1631 cmpl $(CLSIZE*NBPG),r1
57a0bdb5
SL
1632 bgeq uar2
1633uar1:
a55e280b 1634 prober r2,(r0),$(CLSIZE*NBPG)
57a0bdb5 1635 beql uaerr
a55e280b
SL
1636 addl2 $(CLSIZE*NBPG),r0
1637 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1)
57a0bdb5
SL
1638uar2:
1639 prober r2,(r0),r1
1640 beql uaerr
1641 movl $1,r0
1642 ret
1643uaerr:
1644 clrl r0
1645 ret
1646
1647/*
a55e280b
SL
1648 * Check kernel mode read/write access.
1649 *
1650 * kernacc(addr, count, mode)
1651 * caddr_t addr; int count, mode;
1652 * mode = 0 write access
1653 * mode = 1 read access
57a0bdb5 1654 */
a55e280b 1655ENTRY(kernacc, 0)
57a0bdb5
SL
1656 clrl r2 # r2 = 0 means kernel mode probe.
1657 jbr probes # Dijkstra would get gastric distress here.
1658
1659/*
1660 * addupc - increment some histogram counter
1661 * in the profiling buffer
1662 *
a55e280b
SL
1663 * addupc(pc, prof, delta)
1664 * long pc; short delta; struct uprof *prof;
57a0bdb5
SL
1665 *
1666 * struct uprof { # profile arguments
1667 * short *r_base; # buffer base
1668 * unsigned pr_size; # buffer size
1669 * unsigned pr_off; # pc offset
1670 * unsigned pr_scale; # pc scaling
1671 * }
1672 */
a55e280b
SL
1673ENTRY(addupc, 0)
1674 movl 8(fp),r2 # r2 points to structure
1675 subl3 8(r2),4(fp),r0 # r0 = PC - lowpc
1676 jlss 9f # PC < lowpc , out of range !
1677 shrl $1,r0,r0 # the unit is words
1678 shrl $1,12(r2),r1 # ditto for scale
57a0bdb5
SL
1679 emul r1,r0,$0,r0
1680 shrq $14,r0,r0
a55e280b 1681 tstl r0 # too big
57a0bdb5 1682 jneq 9f
a55e280b 1683 cmpl r1,4(r2) # Check buffer overflow
57a0bdb5
SL
1684 jgequ 9f
1685 probew $1,*0(r2)[r1],$2 # counter accessible?
1686 jeql 9f
a55e280b 1687 shrl $1,r1,r1 # make r1 word index
57a0bdb5
SL
1688 addw2 14(fp),*0(r2)[r1]
16899: ret
a55e280b
SL
1690
1691/*
1692 * scanc(size, cp, table, mask)
1693 */
1694ENTRY(scanc, R3|R4)
1695 movl 8(fp),r0 # r0 = cp
1696 addl3 4(fp),r0,r2 # end = &cp[size]
1697 movl 12(fp),r1 # r1 = table
1698 movb 19(fp),r4 # r4 = mask
1699 decl r0 # --cp
1700 jbr 0f # just like Fortran...
17011: # do {
1702 movzbl (r0),r3
1703 bitb r4,(r1)[r3] # if (table[*cp] & mask)
1704 jneq 2f # break;
17050: aoblss r2,r0,1b # } while (++cp < end);
17062:
1707 subl3 r0,r2,r0; ret # return (end - cp);
1708
1709/*
1710 * skpc(mask, size, cp)
1711 */
1712ENTRY(skpc, 0)
1713 movl 12(fp),r0 # r0 = cp
1714 addl3 8(fp),r0,r1 # r1 = end = &cp[size];
1715 movb 7(fp),r2 # r2 = mask
1716 decl r0 # --cp;
1717 jbr 0f
17181: # do
1719 cmpb (r0),r2 # if (*cp != mask)
1720 jneq 2f # break;
17210: aoblss r1,r0,1b # while (++cp < end);
17222:
1723 subl3 r0,r1,r0; ret # return (end - cp);
1724
a55e280b
SL
1725/*
1726 * locc(mask, size, cp)
1727 */
1728ENTRY(locc, 0)
1729 movl 12(fp),r0 # r0 = cp
1730 addl3 8(fp),r0,r1 # r1 = end = &cp[size]
1731 movb 7(fp),r2 # r2 = mask
1732 decl r0 # --cp;
1733 jbr 0f
17341: # do
1735 cmpb (r0),r2 # if (*cp == mask)
1736 jeql 2f # break;
17370: aoblss r1,r0,1b # while (++cp < end);
17382:
1739 subl3 r0,r1,r0; ret # return (end - cp);
44622fe3 1740
82bf8967 1741#ifdef ALIGN
44622fe3
SL
1742#include "../tahoealign/align.h"
1743
1744 .globl _alignment
1745/*
1746 * There's an intimate relationship between this piece of code
1747 * and the alignment emulation code (especially the layout
1748 * of local variables in alignment.c! Don't change unless
1749 * you update both this, alignment.h and alignment.c !!
1750 */
1751non_aligned:
1752 orb2 $EMULATEALIGN,_u+U_EOSYS
1753 incl _cnt+V_TRAP
1754 incl _cnt+V_ALIGN # count emulated alignment traps
1755 moval 4(sp),_user_psl
1756 SAVE_FPSTAT(4) # Also zeroes out ret_exception !
1757 pushl $0 # ret_addr
1758 pushl $0 # ret_code
1759 mfpr $USP,-(sp) # user sp
1760 callf $4,_alignment # call w/o parms so regs may be modified
1761 /*
1762 * We return here after a successful emulation or an exception.
1763 * The registers have been restored and we must not alter them
1764 * before returning to the user.
1765 */
17662: mtpr (sp)+,$USP # restore user sp
1767 tstl 8(sp) # Any exception ?
1768 bneq got_excp # Yes, reflect it back to user.
1769 moval 8(sp),sp # pop 2 zeroes pushed above
1770 REST_FPSTAT
1771 xorb2 $EMULATEALIGN,_u+U_EOSYS
1772
1773 bitl $PSL_T,4(sp) # check for trace bit set
1774 beql 9f
1775 CHECK_SFE(4)
1776 pushl $0
1777 SAVE_FPSTAT(8)
1778 TRAP(TRCTRAP)
17799: rei
1780
1781got_excp: # decode exception
1782 casel 8(sp),$ILL_ADDRMOD,$ALIGNMENT
1783 .align 1
1784L1:
1785 .word ill_addrmod-L1
1786 .word ill_access-L1
1787 .word ill_oprnd-L1
1788 .word arithmetic-L1
1789 .word alignment-L1
1790 brw alignment # default - shouldn't come here at all !
1791
1792ill_addrmod: # No other parameters. Set up stack as
1793 moval 8(sp),sp # the HW would do it in a real case.
1794 REST_FPSTAT
1795 jbr _Xresadflt
1796ill_oprnd:
1797 moval 8(sp),sp
1798 REST_FPSTAT
1799 jbr _Xresopflt
1800alignment:
1801 moval 8(sp),sp
1802 REST_FPSTAT
1803 jbr align_excp # NB: going to _Xalignflt would cause loop
1804ill_access:
1805 /*
1806 * Must restore accumulator w/o modifying sp and w/o using
1807 * registers. Solution: copy things needed by REST_FPSTAT.
1808 */
1809 pushl 20(sp) # The flags longword
1810 pushl 20(sp) # acc_low
1811 pushl 20(sp) # acc_high
1812 pushl 20(sp) # ret_exception ignored by REST_FPSTAT
1813 REST_FPSTAT # Back where we were with the sp !
1814 movl (sp),16(sp) # code for illegal access
1815 movl 4(sp),20(sp) # original virtual address
1816 moval 16(sp),sp # Just like the HW would set it up
1817 jbr _Xprotflt
1818arithmetic: # same trickery as above
1819 pushl 20(sp) # The flags longword
1820 pushl 20(sp) # acc_low
1821 pushl 20(sp) # acc_high
1822 pushl 20(sp) # ret_exception ignored by REST_FPSTAT
1823 REST_FPSTAT # Back where we were with the sp !
1824 movl (sp),20(sp) # code for arithmetic exception
1825 moval 20(sp),sp # Just like the HW would set it up
1826 jbr _Xarithtrap
1827#endif