fpsim.3100644 144 31 3133 6504376006 10756 0ustar wktpupsarc.TH FPSIM 3E local .DA 25 March 1981 .SH NAME fpsim \- floating-point simulation .SH DESCRIPTION This system provides for software emulation of floating-point instructions if floating-point hardware is not present. The kernel code in question simulates an FP11 floating-point processor by intercepting illegal-instruction traps and decoding and interpreting the floating-point opcodes. .SH HISTORY This simulator is derived from Bell's, which used .IR signal (2) and was compiled into the user program. Mike Tilson of HCR thought of and did the original kernel-mode simulator; this improved variant by Henry Spencer. .SH BUGS The floating-point status register is incompletely supported; only the float/double mode, int/long mode, and condition-code bits work. Other bits read and write properly but have no effect. In particular, there are no traps except for invalid opcode. .PP Divide by zero is not detected. .PP Rounding mode is not supported. .PP The presence of \-0 is not noticed or trapped. .PP The STST instruction is not supported (it is in any event impossible to support properly in a multiprogramming system), and the error registers don't exist. .PP Long-int conversions with the long int in registers don't work. .PP Certain valid but bizarre combinations of opcode and addressing mode/register are treated as illegal opcodes. .PP Roundoff errors probably don't match any existing FP11. .PP Behavior at extremes of the number range is suspect. .PP Checking for segmentation violations etc. is sloppy; an error will probably result but it may be delayed. .PP Compared to a real FP11, it's excruciatingly slow. fpsim.s100444 144 31 31422 6504375674 11110 0ustar wktpupsarc/ fpsim -- kernel floating point simulator / Usage: fpsim(u.u_ar0, ®loc, &u.u_fps.u_fpsr, &u.u_fps.u_fpregs) / Returns nonzero if unable to interpret an instruction. / Henry Spencer, UofT March 1981. / Modification of BTL user-mode fptrap, after similar mods done by / Mike Tilson at HCR. .data <@(#)fpsim.s 1.2 of 24 March 81\0> .text m.ext = 200 / long mode bit m.lngi = 100 / long integer mode .globl _fpsim .globl csv, cret, fuiword, fuword, suword, _grow, _runrun _fpsim: jsr r5,csv mov r5,fsavr5 mov 4(r5),ur0 mov 6(r5),regloc mov 8.(r5),ufpsr mov 10.(r5),r0 mov r0,uac0 add $8.,r0 mov r0,uac1 add $16.,r0 mov r0,uac3 mov regloc,r0 mov $sr0,r1 1: movb (r0)+,r2 asl r2 add ur0,r2 mov (r2),(r1)+ cmp r1,$sps blos 1b mov spc,r5 / pick up the trapped opcode sub $2,r5 mov r5,r1 jsr pc,fuiword mov r0,r5 again: clr trapins clr inuspace mov r5,r4 mov fsavr5,r5 mov ssp,(sp) sub $8,(sp) / room for double push jsr pc,_grow mov r4,r5 / mov r5,r4 bic $7777,r4 cmp r4,$170000 beq 1f jmp badins 1: bic $100000,*ufpsr / clear fp error bic $170000,r5 mov r5,r4 bit $7000,r4 bne class3 bit $700,r4 bne class2 cmp r4,$12 blos 1f jmp badins 1: asl r4 jmp *1f(r4) .data 1: i.cfcc / 170000 i.setf / 170001 i.seti / 170002 badins badins badins badins badins badins i.setd / 170011 i.setl / 170012 .text class2: cmp r5,$400 bge 1f jsr r1,fsrc; jmp mod0rx; jmp mod242 / status manipulation br 2f 1: jsr r1,fsrc; jmp mod0f; jmp mod24f / ordinary op 2: mov r3,r5 asl r4 asl r4 clrb r4 swab r4 asl r4 jsr pc,*1f(r4) jmp sret .data 1: badins / 1700xx i.ldfps / 1701xx i.stfps / 1702xx badins / 1703xx - stst i.clrx / 1704xx i.tstx / 1705xx i.absx / 1706xx i.negx / 1707xx .text class3: cmp r5,$5000 blt 1f mov r5,r2 clrb r2 cmp r2,$6400 blt 2f sub $1400,r2 2: cmp r2,$5000 bne 2f jsr r1,fsrc; jmp mod0rx; jmp mod242 / exponent op br 3f 2: cmp r2,$5400 bne 2f jsr r1,fsrc; jmp mod0ra; jmp mod24i / int convert br 3f 2: jsr r1,fsrc; jmp mod0f; jmp mod24d / float convert br 3f 1: jsr r1,fsrc; jmp mod0f; jmp mod24f / ordinary op 3: jsr pc,freg mov r2,r5 clrb r4 swab r4 asl r4 jsr pc,*1f(r4) clr inuspace br sret .data 1: badins / 1700xx badins / 1704xx i.mulx / 1710xx i.modx / 1714xx i.addx / 1720xx i.ldx / 1724xx i.subx / 1730xx i.cmpx / 1734xx i.stx / 1740xx i.divx / 1744xx i.stexp / 1750xx i.stcxj / 1754xx i.stcxy / 1760xx i.ldexp / 1764xx i.ldcjx / 1770xx i.ldcyx / 1774xx .text i.cfcc: mov *ufpsr,r0 bic $!17,r0 movb r0,sps br ret i.setf: bic $m.ext,*ufpsr br ret i.setd: bis $m.ext,*ufpsr br ret i.seti: bic $m.lngi,*ufpsr br ret i.setl: bis $m.lngi,*ufpsr br ret badins: inc trapins br ret1 sret: mov ufpsr,r0 bic $17,(r0) mov r0,(sp) mov r5,r3 jsr pc,fget tst r0 bpl 1f mov (sp),r0 bis $10,(r0) br ret 1: bit $77600,r0 / test whole exponent bne ret mov (sp),r0 bis $4,(r0) ret: tstb _runrun bne ret1 / really should save state and qswtch() instead mov spc,r1 jsr pc,fuiword mov r0,r5 cmp r5,$170000 blo ret1 add $2,spc jbr again / if another fp, save trap ret1: mov regloc,r0 mov $sr0,r1 1: movb (r0)+,r2 asl r2 add ur0,r2 mov (r1)+,(r2) cmp r1,$sps blos 1b mov trapins,r0 mov fsavr5,r5 jmp cret freg: mov r5,r2 bic $!300,r2 asr r2 asr r2 asr r2 add uac0,r2 rts pc fsrc: mov r5,r3 bic $!7,r3 / register asl r3 add $sr0,r3 mov r5,r0 bic $!70,r0 / mode asr r0 asr r0 jmp *1f(r0) .data 1: mod0 mod1 mod2 mod3 mod4 mod5 mod6 mod7 .text mod24f: mov $4,r0 bit $m.ext,*ufpsr beq 1f add $4,r0 1: rts pc mod24d: mov $8,r0 bit $m.ext,*ufpsr beq 1f sub $4,r0 1: rts pc mod242: mov $2,r0 rts pc mod24i: mov $2,r0 bit $m.lngi,*ufpsr beq 1f add $2,r0 1: rts pc mod0: add $4,r1 jmp -4(r1) mod0f: sub $sr0,r3 / get fp ac cmp r3,$6*2 jhis badi1 asl r3 asl r3 add uac0,r3 add $4,r1 rts r1 mod0ra: bit $m.lngi,*ufpsr bne badi1 mod0r: cmp r3,$ssp bhis badi1 mod0rx: add $4,r1 rts r1 mod1: cmp r3,$spc beq badi1 mov (r3),r3 inc inuspace br check mod2: mov (r3),-(sp) jsr pc,4(r1) inc inuspace cmp r3,$spc bne 1f mov $2,r0 mov r0,-(sp) mov r1,-(sp) mov (r3),r1 jsr pc,fuiword mov r0,pctmp mov (sp)+,r1 mov (sp)+,r0 mov $pctmp,(sp) clr inuspace 1: add r0,(r3) mov (sp)+,r3 br check mod3: clr -(sp) mov r0,-(sp) mov r1,-(sp) mov (r3),r1 cmp r3,$spc beq 1f jsr pc,fuword br 2f 1: jsr pc,fuiword 2: mov r0,4(sp) mov (sp)+,r1 mov (sp)+,r0 add $2,(r3) mov (sp)+,r3 inc inuspace br check mod4: cmp r3,$spc / test pc beq badi1 jsr pc,4(r1) sub r0,(r3) mov (r3),r3 inc inuspace br check mod5: cmp r3,$spc beq badi1 sub $2,(r3) mov r0,-(sp) mov r1,-(sp) mov (r3),r1 jsr pc,fuword mov r0,r3 mov (sp)+,r1 mov (sp)+,r0 inc inuspace br check mod6: clr -(sp) mov r0,-(sp) mov r1,-(sp) mov spc,r1 jsr pc,fuiword mov r0,4(sp) mov (sp)+,r1 mov (sp)+,r0 add $2,spc add (r3),(sp) mov (sp)+,r3 inc inuspace br check mod7: jsr r1,mod6; jmp badins; jmp badins mov r0,-(sp) mov r1,-(sp) mov r3,r1 jsr pc,fuword mov r0,r3 mov (sp)+,r1 mov (sp)+,r0 br check badi1: jmp badins check: bit $1,r3 bne badi1 add $8,r1 rts r1 setab: mov $asign,r0 jsr pc,seta jsr pc,fget mov r0,ftemp jsr pc,fget mov r0,ftemp+2 jsr pc,fget mov r0,ftemp+4 jsr pc,fget mov r0,ftemp+6 mov $ftemp,r2 mov $bsign,r0 seta: clr (r0) mov (r2)+,r1 mov r1,-(sp) beq 1f blt 2f inc (r0)+ br 3f 2: dec (r0)+ 3: bic $!177,r1 bis $200,r1 br 2f 1: clr (r0)+ 2: mov r1,(r0)+ mov (r2)+,(r0)+ bit $m.ext,*ufpsr beq 2f mov (r2)+,(r0)+ mov (r2)+,(r0)+ br 3f 2: clr (r0)+ clr (r0)+ 3: mov (sp)+,r1 asl r1 clrb r1 swab r1 sub $200,r1 mov r1,(r0)+ / exp rts pc norm: mov $areg,r0 mov (r0)+,r1 mov r1,-(sp) mov (r0)+,r2 bis r2,(sp) mov (r0)+,r3 bis r3,(sp) mov (r0)+,r4 bis r4,(sp)+ bne 1f clr asign rts pc 1: bit $!377,r1 beq 1f clc ror r1 ror r2 ror r3 ror r4 inc (r0) br 1b 1: bit $200,r1 bne 1f asl r4 rol r3 rol r2 rol r1 dec (r0) br 1b 1: mov r4,-(r0) mov r3,-(r0) mov r2,-(r0) mov r1,-(r0) rts pc / fp2 -- floating point simulation i.ldx: jsr pc,fget mov r0,(r2)+ jsr pc,fget mov r0,(r2)+ bit $m.ext,*ufpsr beq 1f jsr pc,fget mov r0,(r2)+ jsr pc,fget mov r0,(r2)+ rts pc 1: clr (r2)+ clr (r2)+ rts pc i.stx: mov (r2)+,r0 jsr pc,fput mov (r2)+,r0 jsr pc,fput bit $m.ext,*ufpsr beq 1f mov (r2)+,r0 jsr pc,fput mov (r2)+,r0 jsr pc,fput 1: jmp ret / does not set cc's i.clrx: clr r0 jsr pc,fput clr r0 jsr pc,fput bit $m.ext,*ufpsr beq 1f clr r0 jsr pc,fput clr r0 jsr pc,fput 1: rts pc i.negx: jsr pc,fget sub $2,r3 tst r0 beq 1f add $100000,r0 jsr pc,fput 1: rts pc i.absx: jsr pc,fget sub $2,r3 bic $!77777,r0 jsr pc,fput rts pc i.tstx: rts pc i.cmpx: mov $areg,r5 tst (r2) bge 1f jsr pc,fget sub $2,r3 tst r0 bge 1f cmp (r2),r0 bgt 4f blt 3f 1: jsr pc,fget cmp (r2)+,r0 bgt 3f blt 4f jsr pc,fget cmp (r2)+,r0 bne 1f bit $m.ext,*ufpsr beq 2f jsr pc,fget cmp (r2)+,r0 bne 1f jsr pc,fget cmp (r2)+,r0 beq 2f 1: bhi 3f 4: mov $400,(r5) / low bit of exponent rts pc 3: mov $-1,(r5) rts pc 2: clr (r5) rts pc i.ldcyx: jsr pc,fget mov r0,(r2)+ jsr pc,fget mov r0,(r2)+ bit $m.ext,*ufpsr bne 1f jsr pc,fget mov r0,(r2)+ jsr pc,fget mov r0,(r2)+ rts pc 1: clr (r2)+ clr (r2)+ rts pc i.stcxy: mov (r2)+,r0 jsr pc,fput mov (r2)+,r0 jsr pc,fput bit $m.ext,*ufpsr bne 1f clr r0 jsr pc,fput clr r0 jsr pc,fput 1: rts pc i.ldcjx: mov $asign,r0 mov $1,(r0)+ mov r0,-(sp) jsr pc,fget mov r0,r1 mov (sp)+,r0 mov r1,(r0)+ bit $m.lngi,*ufpsr beq 1f mov r0,-(sp) jsr pc,fget mov r0,r1 mov (sp)+,r0 mov r1,(r0)+ clr (r0)+ clr (r0)+ mov $32.-8,(r0)+ jmp saret 1: clr (r0)+ clr (r0)+ clr (r0)+ mov $16.-8,(r0) jmp saret i.stcxj: mov r3,r5 mov $asign,r0 jsr pc,seta clr r4 mov $areg,r0 mov (r0)+,r1 mov (r0)+,r2 mov (r0)+,r3 mov aexp,r0 1: cmp r0,$48.-8 bge 1f clc ror r1 ror r2 ror r3 inc r0 br 1b 1: bgt 7f tst r1 beq 1f 7: bis $1,r4 / C-bit 1: bit $m.lngi,*ufpsr beq 1f tst asign bge 2f neg r3 adc r2 bcs 2f neg r2 bis $10,r4 / N-bit 2: mov r4,-(sp) mov r2,-(sp) mov r3,-(sp) mov r5,r3 mov r2,r0 jsr pc,fput mov (sp),r0 jsr pc,fput mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r4 bis r2,r3 br 8f 1: tst r2 beq 1f bis $1,r4 / C-bit 1: tst asign bge 2f neg r3 bis $10,r4 / N-bit 2: mov r4,-(sp) mov r3,-(sp) mov r5,r3 mov (sp),r0 jsr pc,fput mov (sp)+,r3 mov (sp)+,r4 tst r3 8: bne 1f bis $4,r4 / Z-bit 1: bic $17,sps bic $17,*ufpsr bis r4,sps bis r4,*ufpsr jmp ret i.ldexp: mov $asign,r0 jsr pc,seta jsr pc,fget mov r0,aexp jsr pc,reta jmp sret i.stexp: mov $asign,r0 jsr pc,seta mov aexp,r0 jsr pc,fput sub $2,r3 mov r3,r5 bic $17,sps tst aexp bmi 1f bne 2f bis $4,sps / Z-bit br 2f 1: bis $10,sps / N-bit 2: jmp sret i.ldfps: jsr pc,fget mov r0,*ufpsr jmp ret i.stfps: mov *ufpsr,r0 jsr pc,fput jmp ret / fp3 -- floating simulation i.addx: jsr pc,setab br 1f i.subx: jsr pc,setab neg bsign 1: tst bsign beq reta tst asign beq retb mov areg+8,r1 sub breg+8,r1 blt 1f beq 2f cmp r1,$56. bge reta mov $breg,r0 br 4f 1: neg r1 cmp r1,$56. bge retb mov $areg,r0 4: mov r1,-(sp) mov (r0)+,r1 mov (r0)+,r2 mov (r0)+,r3 mov (r0)+,r4 add (sp),(r0) 1: clc ror r1 ror r2 ror r3 ror r4 dec (sp) bgt 1b mov r4,-(r0) mov r3,-(r0) mov r2,-(r0) mov r1,-(r0) tst (sp)+ 2: mov $areg+8,r1 mov $breg+8,r2 mov $4,r0 cmp asign,bsign bne 4f clc 1: adc -(r1) bcs 3f add -(r2),(r1) 2: dec r0 bne 1b br 5f 3: add -(r2),(r1) sec br 2b br 5f 4: clc 1: sbc -(r1) bcs 3f sub -(r2),(r1) 2: dec r0 bne 1b br 5f 3: sub -(r2),(r1) sec br 2b saret: mov $areg,r1 5: tst (r1) bge 3f mov $areg+8,r1 mov $4,r0 clc 1: adc -(r1) bcs 2f neg (r1) 2: dec r0 bne 1b neg -(r1) 3: jsr pc,norm br reta retb: mov $bsign,r1 mov $asign,r2 mov $6,r0 1: mov (r1)+,(r2)+ dec r0 bne 1b reta: mov r5,r2 mov $asign,r0 tst (r0) beq unflo mov aexp,r1 cmp r1,$177 bgt ovflo cmp r1,$-177 blt unflo add $200,r1 swab r1 clc ror r1 tst (r0)+ bge 1f bis $100000,r1 1: bic $!177,(r0) bis (r0)+,r1 mov r1,(r2)+ mov (r0)+,(r2)+ bit $m.ext,*ufpsr beq 1f mov (r0)+,(r2)+ mov (r0)+,(r2)+ 1: rts pc unflo: clr (r2)+ clr (r2)+ bit $m.ext,*ufpsr beq 1f clr (r2)+ clr (r2)+ 1: rts pc ovflo: bis $2,*ufpsr / set v-bit (overflow) jmp ret i.mulx: jsr pc,i.mul br saret i.modx: jsr pc,i.mul jsr pc,norm mov $asign,r0 mov $bsign,r1 mov $6,r2 1: mov (r0)+,(r1)+ dec r2 bne 1b clr r0 / count mov $200,r1 / bit clr r2 / reg offset 1: cmp r0,aexp bge 2f / in fraction bic r1,areg(r2) br 3f 2: bic r1,breg(r2) 3: inc r0 clc ror r1 bne 1b mov $100000,r1 add $2,r2 cmp r2,$8 blt 1b jsr pc,norm jsr pc,reta cmp r5,uac1 beq 1f cmp r5,uac3 beq 1f bit $200,breg bne 2f clr bsign 2: add $8,r5 jsr pc,retb sub $8,r5 1: rts pc i.divx: jsr pc,setab tst bsign beq ovflo sub bexp,aexp jsr pc,xorsign mov r5,-(sp) mov $areg,r0 mov (r0),r1 clr (r0)+ mov (r0),r2 clr (r0)+ mov (r0),r3 clr (r0)+ mov (r0),r4 clr (r0)+ mov $areg,r5 mov $400,-(sp) 1: mov $breg,r0 cmp (r0)+,r1 blt 2f bgt 3f cmp (r0)+,r2 blo 2f bhi 3f cmp (r0)+,r3 blo 2f bhi 3f cmp (r0)+,r4 bhi 3f 2: mov $breg,r0 sub (r0)+,r1 clr -(sp) sub (r0)+,r2 adc (sp) clr -(sp) sub (r0)+,r3 adc (sp) sub (r0)+,r4 sbc r3 adc (sp) sub (sp)+,r2 adc (sp) sub (sp)+,r1 bis (sp),(r5) 3: asl r4 rol r3 rol r2 rol r1 clc ror (sp) bne 1b mov $100000,(sp) add $2,r5 cmp r5,$areg+8 blo 1b tst (sp)+ mov (sp)+,r5 jmp saret i.mul: jsr pc,setab add bexp,aexp dec aexp jsr pc,xorsign mov r5,-(sp) mov $breg+4,r5 bit $m.ext,*ufpsr beq 1f add $4,r5 1: clr r0 clr r1 clr r2 clr r3 clr r4 1: asl r0 bne 2f inc r0 tst -(r5) 2: cmp r0,$400 bne 2f cmp r5,$breg bhi 2f mov $areg,r0 mov r1,(r0)+ mov r2,(r0)+ mov r3,(r0)+ mov r4,(r0)+ mov (sp)+,r5 rts pc 2: clc ror r1 ror r2 ror r3 ror r4 bit r0,(r5) beq 1b mov r0,-(sp) mov $areg,r0 add (r0)+,r1 clr -(sp) add (r0)+,r2 adc (sp) clr -(sp) add (r0)+,r3 adc (sp) add (r0)+,r4 adc r3 adc (sp) add (sp)+,r2 adc (sp) add (sp)+,r1 mov (sp)+,r0 br 1b xorsign: cmp asign,bsign beq 1f mov $-1,asign rts pc 1: mov $1,asign rts pc fget: tst inuspace beq 1f mov r3,r1 add $2,r3 jsr pc,fuword rts pc 1: mov (r3)+,r0 rts pc fput: tst inuspace beq 1f mov r3,r1 add $2,r3 jsr pc,suword rts pc 1: mov r0,(r3)+ rts pc / fpx -- floating point simulation .bss asign: .=.+2 areg: .=.+8 aexp: .=.+2 bsign: .=.+2 breg: .=.+8 bexp: .=.+2 trapins: .=.+2 sr0: .=.+2 sr1: .=.+2 .=.+2 .=.+2 .=.+2 .=.+2 ssp: .=.+2 spc: .=.+2 sps: .=.+2 pctmp: .=.+8 fsavr5: .=.+2 ftemp: .=.+8. inuspace: .=.+2 / Pointers. ur0: .=.+2 regloc: .=.+2 ufpsr: .=.+2 uac0: .=.+2 uac1: .=.+2 uac3: .=.+2 trap.c100444 144 31 17552 6504375674 10730 0ustar wktpupsarc/* * Basic C-level trap handling, mostly panicing and dispatching system calls. */ /* * Impossible to avoid some minor lint complaints about unknown structs * without including every .h in sight. This is a fairly minimal set. */ #include #include #include #include #include #include #include static char Sccsid[] = "@(#)trap.c 1.7 of 14 March 85"; /* * Hardware bits and suchlike. */ #define EBIT 1 /* user error bit in PS: C-bit */ #define FPINST 0170000 /* floating-point opcode prefix */ #define SYS 0104400 /* sys (trap) instruction */ #define USER 020 /* user-mode flag added to dev */ #define CACHE ((physadr)0177744) /* 11/44 cache registers */ #define CPUERR ((physadr)0177766) /* cpu error register */ /* * Offsets of the user's registers relative to * the saved r0. See reg.h */ char regloc[9] = { R0, R1, R2, R3, R4, R5, R6, R7, RPS }; /* * Called from mch.s when a processor trap occurs. * The arguments are the words saved on the system stack * by the hardware and software during the trap processing. * Their order is dictated by the hardware and the details * of C's calling sequence. They are peculiar in that * this call is not 'by value' and changed user registers * get copied back on return. * dev is the kind of trap that occurred. */ /* ARGSUSED */ trap(dev, sp, r1, nps, r0, pc, ps) dev_t dev; int sp, r1, nps, r0; int *pc; int ps; { register int i; /* Signal #; also misc temporary. */ register int *addr; /* Address of call and arguments. */ register struct sysent *callp; /* sysent struct for this call. */ int oldfpsaved; /* For saving+restoring u.u_fpsaved. */ int *oldar0; /* For saving+restoring u.u_ar0. */ int (*fetch)(); /* Arg fetcher: fuword or fuiword. */ time_t syst; /* Initial u.u_stime, for profiling. */ syst = u.u_stime; /* * Save the elements of the user structure which are about to be * modified. This is vital because things like imprecise floating- * point exceptions can cause recursive calls of trap(). */ oldfpsaved = u.u_fpsaved; oldar0 = u.u_ar0; /* * We don't actually save the floating-point registers here * because we may not have to (if we return without having to * yield the CPU), but we note that they need to be saved. */ u.u_fpsaved = 0; if ((ps&UMODE) == UMODE) dev |= USER; u.u_ar0 = &r0; /* So other code can find registers. */ switch (minor(dev)) { /* * Trap not expected. * Usually a kernel mode bus error. * The numbers printed are used to * find the hardware PS/PC as follows. * (all numbers in octal 18 bits) * address_of_saved_ps = * (ka6*0100) + aps - 0140000; * address_of_saved_pc = * address_of_saved_ps - 2; */ default: printf("ka6 = 0%o\n", ka6->r[0]); printf("aps = 0%o\n", &ps); printf("pc = 0%o ps = 0%o\n", pc, ps); if (cputype == 70) printf("CPU err = 0%o\n", CPUERR->r[0]); printf("trap type 0%o\n", dev); panic("trap"); /* NOTREACHED */ case 0+USER: /* bus error */ i = SIGBUS; break; /* * Illegal instructions that look like floating-point are tried out * on the floating-point simulator first. */ case 1+USER: /* illegal instruction */ if ((fuiword((caddr_t)(pc-1))&FPINST) == FPINST) { /* * Fpsim is in assembler, hence it is passed various * things to avoid having to hard-wire them in the * awful assembler code. */ if (fpsim(u.u_ar0, regloc, &u.u_fps.u_fpsr, u.u_fps.u_fpregs) == 0) goto out; i = SIGFPT; /* Fpsim didn't like it. */ } else i = SIGINS; break; case 2+USER: /* bpt or trace */ i = SIGTRC; ps &= ~TBIT; /* Turn single-stepping off if on. */ break; case 3+USER: /* iot */ i = SIGIOT; break; case 5+USER: /* emt */ i = SIGEMT; break; case 6+USER: /* sys call */ u.u_error = 0; ps &= ~EBIT; /* * First, which call is it, and which fetch routine * should be used? */ addr = pc; callp = &sysent[fuiword((caddr_t)(addr-1))&077]; if (callp == sysent) { /* indirect */ addr = (int *)fuiword((caddr_t)(addr)); pc++; i = fuword((caddr_t)addr); addr++; if ((i & ~077) != SYS) i = 077; /* illegal */ callp = &sysent[i&077]; fetch = fuword; } else { pc += callp->sy_narg - callp->sy_nrarg; fetch = fuiword; } /* * Second, fetch the arguments. */ for (i=0; isy_nrarg; i++) u.u_arg[i] = u.u_ar0[regloc[i]]; for (; isy_narg; i++) u.u_arg[i] = (*fetch)((caddr_t)addr++); /* * Third, set up some standardized pointers. */ u.u_dirp = (caddr_t)u.u_arg[0]; u.u_r.r_val1 = u.u_ar0[R0]; u.u_r.r_val2 = u.u_ar0[R1]; u.u_ap = u.u_arg; /* * Fourth, prepare for abnormal returns. */ if (save(u.u_qsav)) { /* Abnormal return, user interrupt if nothing else. */ if (u.u_error == 0) u.u_error = EINTR; } else { /* * Fifth, do the call. */ (*callp->sy_call)(); } /* * Sixth, set up returned value(s). */ if (u.u_error) { ps |= EBIT; u.u_ar0[R0] = u.u_error; } else { u.u_ar0[R0] = u.u_r.r_val1; u.u_ar0[R1] = u.u_r.r_val2; } goto out; /* * Since the floating exception is an * imprecise trap, a user generated * trap may actually come from kernel * mode. In this case, a signal is sent * to the current process to be picked * up later, so as not to interfere with * current activities. */ case 8: /* floating exception */ stst(&u.u_fper); /* save error code */ psignal(u.u_procp, SIGFPT); u.u_fpsaved = oldfpsaved; u.u_ar0 = oldar0; return; case 8+USER: i = SIGFPT; stst(&u.u_fper); /* save error code */ break; /* * If the user SP is below the stack segment, * grow the stack automatically. * This relies on the ability of the hardware * to restart a half executed instruction. * On the 11/40 this is not the case and * the routine backup in mch.s may fail. * The classic example is on the instruction * cmp -(sp),-(sp) */ case 9+USER: /* segmentation exception */ { int osp; osp = sp; /* * If restartable, and stack was indeed overflowed * but could be grown further, then all ok. */ if (backup(u.u_ar0) == 0) if (grow((unsigned)osp)) goto out; i = SIGSEG; /* One or more conditions not met. */ break; } /* * The code here is a half-hearted * attempt to do something with all * of the 11/44 cache registers. * In fact, there is little that * can be done. */ case 10: case 10+USER: printf("cache "); if (cputype == 70) { for (i=0; i<5; i++) printf("0%o ", CACHE->r[i]); printf("\n"); CACHE->r[0] = -1; /* clear error bits */ if (dev & USER) { i = SIGBUS; break; } } panic("cache"); /* NOTREACHED */ /* * Allow process switch (see mch.s/call() for invocation). */ case USER+12: goto out; /* * Locations 0-2 specify this style trap, since * DEC hardware often generates spurious * traps through location 0. This is a * symptom of hardware problems and may * represent a real interrupt that got * sent to the wrong place. Watch out * for hangs on disk completion if this message appears. */ case 15: case 15+USER: printf("Random interrupt ignored\n"); u.u_fpsaved = oldfpsaved; u.u_ar0 = oldar0; return; } /* * The switch has spoken. Send whatever signal is appropriate. */ psignal(u.u_procp, i); out: /* * Clean up and leave. */ if (ISSIG()) /* Have we been signalled? */ psig(); curpri = setpri(u.u_procp); /* Recompute priority. */ if (runrun) /* Should we yield cpu? */ qswtch(); /* Returns when rescheduled. */ if (u.u_prof.pr_scale) /* If profiling, add call's time. */ addupc((caddr_t)pc, &u.u_prof, (int)(u.u_stime-syst)); if (u.u_fpsaved) /* Restore fp regs if got saved. */ restfp(&u.u_fps); u.u_fpsaved = oldfpsaved; u.u_ar0 = oldar0; } /* * Nonexistent system call -- set fatal error code. */ nosys() { u.u_error = EINVAL; } /* * Ignored system call */ nullsys() { }