:Title[Lisp0]; * * Edit History * March 29, 1985 2:20 PM, Masinter, formatting * March 20, 1985, Masinter, move UPCTRACE to 374 * March 15, 1985 10:59 AM, Masinter, bum out unused cases * (e.g., Alto display) * March 12, 1985 6:52 PM, Masinter, SAVEUCODESTATE was smashing color CSB * got rid of it * February 2, 1985 10:34 PM, Masinter, Def2BR was set wrong! * January 22, 1985 12:24 AM, Masinter, remove Altomode instructions no * longer used * January 5, 1985 11:39 PM, JonL, Flush ZeroBR; setup Val2BR and Def2BR * for 64K Litatoms scheme * February 18, 1984 4:54 PM, JonL, SAVEUCODESTATE uses SubrArgArea * instead of statsBuffer * January 31, 1984 7:31 PM, JonL, embellish SAVEUCODESTATE * January 31, 1984 5:05 PM, Masinter, add SAVEUCODESTATE as subroutine * January 23, 1984 6:51 PM, JonL, debugging previous change * January 20, 1984 6:26 AM, JonL, added check for BLT in pageFault * January 4, 1983 2:48 PM, Masinter :insert[DisplayDefs.mc]; mc[max.pvar.for.fault, 3000]; * Code for Interface with BCPL KnowRBase[LTEMP0]; TOP LEVEL; InsSet[LispInsSet, 1]; mc[UCODE.CHECK, 0]; mc[STKOV.PUNT, sub[0,SubovFXP!]]; * says context switch to Subov mc[NWW.INTERRUPT, 2]; mc[PAGE.FAULT, sub[0,FAULTFXP!]]; mc[STATS.PUNT, 4]; *-------------------------------------------------------------------- opSUBR: *-------------------------------------------------------------------- LTEMP0_ Id; T_ LTEMP2_ Id; * Beta byte is # args T_ T + T; T_ TSP_ (TSP) - (Cnt_ T); * Move args from stack LTEMP1_ SubrArgArea, Branch[.subr1]; .subr0: T_ (fetch_ T) + 1; * Tight loop to move args memBase_ MDS; * from stackframe to the LTEMP1_ (store_ LTEMP1)+ 1, dbuf_ Md; * BCPL subr arg area .subr1: memBase_ StackBR, branch[.subr0, Cnt#0&-1]; LTEMP1_ (Id) - (PCX') - 1, branch[.storepuntpc]; IFUpause[175, 3, StackBR, 0, opSUBR, noNData, 0, 0]; *SUBRCALL *-------------------------------------------------------------------- opCNTXTSWITCH: *-------------------------------------------------------------------- T_ (TSP) - 1; TSP_ (fetch_ T) - 1; * fetch arg rbase_ rbase[NWW]; T_ Md, NWW_ (NWW) and not (100000c); * turn on interrupts pd_ NWW, rbase_ rbase[LTEMP0]; branch[.+2, alu=0], LTEMP0_ (0s) - T; * LTEMP0_ - (context#) pd_ LTEMP0, RescheduleNow; * reschedule if int pending... LTEMP1_ (Id) - (PCX') - 1, branch[.storepuntpc]; IFUpause[176, 1, StackBR, 0, opCNTXTSWITCH, noNData, 0, 0]; *CNTXTSWITCH *-------------------------------------------------------------------- UCODECHECKPUNT: GLOBAL, *-------------------------------------------------------------------- * call: SaveLink_ Link, Branch[uCodeCheckPunt]; LTEMP4_ SubrArgArea; * set up ucode LTEMP4_ (store_ LTEMP4) + 1, dbuf_ SmallHi; * address of punter LTEMP4_ (store_ LTEMP4) + 1, dbuf_ T; * as arg to BCPL subr LTEMP2_ 1c; LTEMP0_ UCODE.CHECK, branch[BCPLEXIT]; % got rid of SAVEUCODESTATE -- it smashes the color Core Status Buffer *-------------------------------------------------------------------- SUBROUTINE; SAVEUCODESTATE: GLOBAL, *-------------------------------------------------------------------- * Clobbers LTEMP4 and BR * Called by * rbase_ rbase[LTEMP0]; * KnowRBase[LTEMP0]; * LTEMP3_ T, T_ Link, Call[SAVEUCODESTATE]; memBase_ MDS; * Save some volatile Q_ LTEMP4; * ucode regs in stats LTEMP4_ (XXXX); LTEMP4_ (store_ LTEMP4) + 1, dbuf_ (125377c);* 0 PassWord LTEMP4_ (store_ LTEMP4) + 1, dbuf_ T; * 1 Link at call here T_ Link; T_ (store_ LTEMP4) + 1, dbuf_ T; * 2 ucode.addr + 1 of RBase_rbase[FLTEMUPC]; * of call to here T_(store_ T) + 1, dbuf_ FLTEMUPC; * 3 PC at fault RBase_rbase[LTEMP0]; T_ (store_ T) + 1, dbuf_ SaveLink; * 4 maybe saved link T_ (store_ T) + 1, dbuf_ LTEMP3; * 5 T register T_ (store_ T) + 1, dbuf_ LTEMP0; * 6 LTEMP0 T_ (store_ T) + 1, dbuf_ LTEMP1; * 7 LTEMP1 T_ (store_ T) + 1, dbuf_ PVAR; * 10 PVAR T_ (store_ T) + 1, dbuf_ TSP; * 11 TSP T_ (store_ T) + 1, dbuf_ PSTATE; * 12 PSTATE T_ (store_ T) + 1, dbuf_ DEFLO; * 13 DEFLO T_ (store_ T) + 1, dbuf_ NARGS; * 14 NARGS T_ (store_ T) + 1, dbuf_ Q; * 15 LTEMP4 LTEMP0_ TIOA&StkP; T_ (Store_ T) + 1, dbuf_ LTEMP0; * 16 stackp LTEMP0_ 1c; StkP_ LTEMP0; T_ (Store_ T) + 1, dbuf_ Stack&+1; T_ (Store_ T) + 1, dbuf_ Stack&+1; T_ (Store_ T) + 1, dbuf_ Stack&+1; T_ (Store_ T) + 1, dbuf_ Stack&+1; T_ (Store_ T) + 1, dbuf_ Stack&+1; T_ LTEMP3, Return; % TOP LEVEL; *-------------------------------------------------------------------- RAIDPUNT: *-------------------------------------------------------------------- * like UCODEPUNT, but registers are OK; RBase_ rbase[LTEMP0]; memBase_ MDS; LTEMP0_ SubrArgArea; LTEMP0_ (store_ LTEMP0) + 1, dbuf_ SmallHi; store_ LTEMP0, dbuf_ 0c; LTEMP2_ 1c; LTEMP0_ UCODE.CHECK, Branch[PUNT]; *-------------------------------------------------------------------- STKOVPUNT: *-------------------------------------------------------------------- LTEMP0_ STKOV.PUNT, branch[.puntz]; *-------------------------------------------------------------------- STATSPUNT: *-------------------------------------------------------------------- LTEMP0_ STATS.PUNT, branch[.puntz]; *-------------------------------------------------------------------- NWWPUNT:* old NWW: exit to BCPL w/reschedule still set *-------------------------------------------------------------------- rbase_ rbase[LTEMP0]; LTEMP0_ NWW.INTERRUPT, branch[.puntz]; *-------------------------------------------------------------------- KEYPUNT: KnowRBase[NWW]; * new NWW: context switch to KBD context *-------------------------------------------------------------------- NWW_ (100000c); * turn off interrupts rbase_ rbase[LTEMP0]; LTEMP0_ sub[0, KbdFXP!]c, branch[.puntz]; .puntz: LTEMP2_ A0, branch[PUNT]; *-------------------------------------------------------------------- PAGEFAULTPUNT: *-------------------------------------------------------------------- rbase_ rbase[FltPipe0]; memBase_ InterfaceBR; T_ IFPFAULTHI; T_ (store_ T) + 1, dbuf_ FltPipe0; store_ T, dbuf_ FltPipe1; rbase_ rbase[LTEMP0]; * Check first for pagefault while "in function call" (which is OK). :if[Debugging]; Branch[.+2, R>=0], pd_ (PSTATE) and (PS.PFOK); Branch[.pfp1]; * OK to fault in fn call. No constraint on .pfp1 Branch[.+2, alu#0], pd_ (PSTATE) and (add[PS.INBITBLT!, PS.INBLT!]c); uCodeCheck[PageFaultWhenNotOK]; :else; pd_ (PSTATE) and (add[PS.INBITBLT!, PS.INBLT!]c), * PSTATE is -1 Branch[.+2, R>=0]; * in fn call Branch[.pfp1]; * OK to fault in fn call. No constraint on .pfp1 :endif; * Check also for fault in BLT or BITBLT (which need stack patchup). Branch[.pfp1, alu=0], PSTATE, pd_ (PSTATE) and (PS.INBLT); Branch[.+2, alu=0], memBase_ StackBR, T_ (TSP) - 1; stack_ (stack) + 1; PSTATE_ A0, store_ T, dbuf_ Stack, Branch[.pfp1]; .pfp1: ** check for page fault in page fault context pd_ (PVAR) - (max.pvar.for.fault); Branch[.+2, carry], LTEMP0_ PAGE.FAULT; uCodeCheck[PageFaultRecursion]; :if[Debugging]; rbase_ rbase[NWW]; Branch[.+2, R>=0], NWW, rbase_ rbase[LTEMP0]; uCodeCheck[NWW?]; :endif; .pfp2: LTEMP2_ A0, branch[PUNT]; *-------------------------------------------------------------------- * common punt code *-------------------------------------------------------------------- PUNT: T_ (PVAR) - (FXBACK[FLAGS]); memBase_ StackBR, PSTATE, branch[.normalpunt, R>=0]; * punt in call fetch_ T, LTEMP1_ FXInCall; LTEMP1_ (LTEMP1) or Md; store_ T, dbuf_ LTEMP1; T_ (store_ TSP) + 1, dbuf_ SmallHi; T_ (store_ T) + 1, dbuf_ NARGS; T_ (store_ T) + 1, dbuf_ 0c; * can't fault if DEFHI nonzero TSP_ (store_ T) + 1, dbuf_ DEFLO, branch[.puntfixstack]; .normalpunt: fetch_ T, LTEMP1_ FXNoPushReturn; LTEMP1_ (LTEMP1) or Md; store_ T, dbuf_ LTEMP1; LTEMP1_ not (PCX'); .storepuntpc: * from SUBR and context switch, too T_ (PVAR) - (FXBACK[PC]); store_ T, dbuf_ LTEMP1; .puntfixstack: T_ (PVAR) - (FXBACK[NEXT]); store_ T, T_ dbuf_ TSP; * store NEXT T_ (ESP) - T; branch[.+2, carry], TSP_ (store_ TSP) + 1, dbuf_ FreeStackBlock; uCodeCheck[NoStackAtPunt]; store_ TSP, dbuf_ T; * LTEMP0 = punt or subr#, or else (- context#) * LTEMP2 = number of args * PVAR ok BCPLEXIT: memBase_ interfaceBR; PVAR_ (PVAR) - (FX.PVAR); branch[.ctxswitch, R<0], Q_ LTEMP0; :if[Debugging]; PSTATE_ (PS.INBCPL); :endif; store_ add[CurrentFXP!]s, dbuf_ PVAR; :if[FNStats]; branch[.+2, R>=0], FnStatsPtr; branch[.bcplxend]; nop; * Following Call constrains addresses DEFLO_ Q, Call[.subrstat]; memBase_ MDS; T_ StatsBufferPtr; store_ T, dbuf_ FnStatsPtr, Branch[.bcplxend]; :endif; * FNStats .bcplxend: T_ LTEMP2, rbase_ rbase[spAC0]; StkP_ spAC2; Stack&+1_ Q; * value for AC2 Punt or subr # Stack&-1_ T; * # of args T_ AemuRestartLoc, branch[start]; KnowRBase[LTEMP0]; .ctxswitch: T_ (0s) - (LTEMP0); * context# fetch_ T; :if[Debugging]; PSTATE_ (PS.PCXBAD); :else; PSTATE_ A0; :endif; PVAR_ Md, store_ T, dbuf_ PVAR; PVAR_ (PVAR) + (FX.PVAR), branch[RTN2]; :if[FNStats]; SUBROUTINE; *-------------------------------------------------------------------- * Stats writing *-------------------------------------------------------------------- .subrstat: DEFHI_ A0; T_ LSH[LTEMP2, 10]; T_ T or (CALL.EVENT), branch[.storestat]; FNSTAT: * fn in LTEMP0, 1, NARGS set. T_ LTEMP0, memBase_ MDS; T_ LCY[T, NARGS, 10]; T_ T or (CALL.EVENT); T_ (store_ FnStatsPtr) + 1, dbuf_ T; T_ (store_ T) + 1, dbuf_ LTEMP1, branch[.stattail]; .storeretstat: T_ (RETURN.EVENT), branch[.storestat]; .storestat: T_ T or (DEFHI), memBase_ MDS; T_ (store_ FnStatsPtr) + 1, dbuf_ T; T_ (store_ T) + 1, dbuf_ DEFLO; .stattail: FnStatsPtr_ T; T_ 30c; T_ T + (400c); TaskingOFF; fetch_ T; T_ (store_ FnStatsPtr) + 1, dbuf_ Md; RBase_ RBase[RTClock]; T_ (store_ T) + 1, dbuf_ RTClock; TaskingON; RBase_ RBase[FnStatsPtr]; FnStatsPtr_ T; pd_ T - (StatsBufferBoundary); branch[.+2, alu<=0]; ReSchedule; Return; TOP LEVEL; :endif; * FNStats *-------------------------------------------------------------------- KnowRBase[AEmRegs]; m[MBXI, KnowRBase[AEmRegs] Top level]; LTrap: ETEMP2_ Id, call[GetPC]; branch[.+2, alu<0], ETEMP4_ T + 1; BigBdispatch_ ETEMP2; branch[LTrapDispatch], StkP_ spAC0; EmuNext: rbase_ rbase[AEmRegs], global; T_ ETEMP4, branch[start]; EmuSkip: rbase_ rbase[AEmRegs]; T_ (ETEMP4) + 1, branch[start]; *-------------------------------------------------------------------- * arrive at the Lisp dispatch locations with StkP_ spAC0 *-------------------------------------------------------------------- * vanMelle claims 0,1,2,4,5,6,10,11 are used LTrapDispatch: branch[MBIX], dispTable[20]; * 00 branch[ReadFlags]; * 01 branch[SetFlags]; * 02 branch[NPTrap]; * 03 was XferPage branch[BGetBase]; * 04 branch[BPutBase]; * 05 branch[BGetBase32]; * 06 branch[NPTrap]; * 07 was BGetBasePtr branch[BPutBase32]; * 10 branch[InitLispRegs]; * 11 MBXI; *-------------------------------------------------------------- MBIX: rbase_ rbase[LTEMP1]; LTEMP0_ Stack&+1; * AC0: hi part of return value LTEMP1_ Stack; * AC1: lo part of return value :if[Debugging]; PSTATE_ (PS.PCXBAD); :else; PSTATE_ A0; :endif; :if[FNStats]; rbase_ rbase[PVAR]; T_ StatsBufferPtr; memBase_ MDS; fetch_ T; FnStatsPtr_ Md; pd_ FnStatsPtr; branch[.+2, alu#0]; FnStatsPtr_ -1c; :else; FnStatsPtr_ T-T-1; memBase_ MDS; :endif; * memBase=MDS rbase_ rbase[NWW]; T_ (R400) + (52C); * WW (= 452B) fetch_ T, T_ (100000C); T_ (Md) and not (T); NWW _ (NWW) or T; branch[.+2, alu=0], rbase_ rbase[LTEMP0]; Reschedule; T_ add[100000, LShift[LispInsSet, 10]]c; * set InsSet InsSetOrEvent_ T; MemBX_ 0s; * SET MemBX T_ StackEmpty; * set StkP StkP_ T; memBase_ interfaceBR; fetch_ add[CurrentFXP!]s; PVAR_ Md; PVAR_ (PVAR) + (FX.PVAR), branch[RTN2]; MBXI; *-------------------------------------------------------------- ReadFlags: call[flushVp], T_ Stack; RMap_ ETEMP3, call[waitforMapBuf]; * uses T only Stack&+1_ not (Map'); T_ not (Pipe4'); Stack&-1_ T and (m1pipe4.wpdref), * wp, d, & ref from pipe4 branch[EmuNext]; KnowRBase[LTEMP0]; *-------------------------------------------------------------- opREADFLAGS: T_ (TSP) - 1; fetch_ T; call[flushVp], T_ Md, rbase_rbase[ETEMP3]; RMap_ ETEMP3, call[waitforMapBuf]; pd_ Id, rbase_ rbase[TSP]; branch[.+2, alu=0], LTEMP0_ not (Pipe4'); LTEMP0_ not (Map'), branch[.readtail]; LTEMP0_ (LTEMP0) and (m1pipe4.wpdref), branch[.readtail]; .readtail: T_ (Id) - (PCX') - 1; PCF_ T; * restart IFU T_ (TSP) - 1, memBase_ StackBR; store_ T, dbuf_ LTEMP0, NextOpCode; regOP1[161, StackBR, opREADFLAGS, 0]; * readflags regOP1[162, StackBR, opREADFLAGS, 1]; * readrp MBXI; *-------------------------------------------------------------- SetFlags: StkP_ spAC2; T_ (Stack&-2) + (3c); fetch_ T; * fetch flags ETEMP2_ Md, T_ Stack&+1, call[flushVP]; *flush cache T_ lsh [ETEMP2, 2]; * position the wp&dirty bits T_ T and (TIOAvacantMapEntry); * mask out any extra bits T_ Stack&-1, TIOA_ T; B_ T, TASKINGOFF; * get bmux stable for Map_ Map_ ETEMP3, B_ T; * write the map TASKINGON; call[waitforMapBuf], TIOA_ ETEMP3; * clear TIOA * flushVp did one IFUReset, must do a second branch[.+2, R>=0], ETEMP2, IFUReset; * check for ref bit fetch_ ETEMP3; * reference it branch[EmuNext]; *-------------------------------------------------------------------- SUBROUTINE; FlushVP: * vp is in T, uses ETEMP3, sets memBase memBase_ LScratchBR, B_ Md; * finish any stores IFUreset; * stop IFU from making refs ETEMP3_ lsh[T, 10]; T_ rsh[T, 10]; BrHi_ T; BrLo_ ETEMP3; T_ 360C; FlushVPLoop: flush_ T; T_ T - (20C); branch[FlushVPLoop, alu>=0]; B_ Md, ETEMP3_ A0, return; TOP LEVEL; MBXI; *-------------------------------------------------------------- BGetBase: call[BFetch]; Stack_ Md, branch[EmuSkip]; MBXI; *-------------------------------------------------------------- BGetBase32: call[BFetch]; Stack&+1_ Md; fetch_ 1s; Stack_ Md, branch[EmuSkip]; SUBROUTINE; BFetch: memBase_ LScratchBR; BrHi_ Stack&+1; BrLo_ Stack&-1; fetch_ 0s, return; TOP LEVEL; MBXI; *-------------------------------------------------------------- BPutBase: StkP_ spAC2; T_ (Stack&-2) + (3c); fetch_ T; T_ Md, call[BStore], memBase_ LScratchBR; B_ Md, branch[EmuSkip]; MBXI; *-------------------------------------------------------------- BPutBase32: StkP_ spAC2; T_ (Stack&-2) + (3c); fetch_ T; T_ Md; T_ (fetch_ T) + 1; T_ Md, fetch_ T; call[BStore], ETEMP2_ Md, memBase_ LScratchBR; T_ ETEMP2; store_ 1s, dbuf_ T, branch[EmuSkip]; *-------------------------------------------------------------------- SUBROUTINE; BStore: BrHi_ Stack&+1; BrLo_ Stack&-1; * restore to AC0 store_ 0s, dbuf_ T, return; TOP LEVEL; MBXI; *-------------------------------------------------------------- InitLispRegs: rbase_ rbase[RMForIFU]; MemBX_ 0s; * SET MemBX AllOnes_ T-T-1; :if[Debugging]; PSTATE_ (PS.INBCPL); :endif; T_ stackHI; LTEMP0 _ A0, memBase_ StackBR, call[setBR]; LTEMP0_ (LTEMP0) - (2c); T_ T - 1, memBase_ StackM2BR, call[setBR]; T_ VALspace; LTEMP0_ A0, memBase_ ValSpaceBR, call[setBR]; T_ T + 1, memBase_ Val2BR, call[setBR]; T_ LTEMP0_ A0, memBase_ ScratchLZBR, call[setBR]; T_ DEFspace; LTEMP0_ A0, memBase_ DefBR, call[setBR]; T_ T + 1, memBase_ Def2Br, call[setBR]; T_ HTMAINspace; LTEMP0_ HTMAINbase; memBase_ htMainBR, call[setBR]; LTEMP0_ HTOVERFLOWbase; memBase_ HTOfloBR, call[setBR]; * Note that it is required that * DTDspace = MDSTYPEspace = UFNspace = INTERFACEspace T_ INTERFACEspace; LTEMP0_ INTERFACEbase; memBase_ interfaceBR, call[setBR]; LTEMP0_ DTDbase; memBase_ dtdBR, call[setBR]; LTEMP0_ (LTEMP0) + (lshift[ListType!, 4]c); memBase_ ListpDTDBR, call[setBR]; LTEMP0 _ MDSTYPEbase; memBase_ tybaseBR, call[setBR]; LTEMP0 _ UFNTablebase; memBase_ ufnBR, call[setBR]; memBase_ MDS; T_ and[RamVersion, 177400]c; T_ T + (and[RamVersion, 377]c); Stack_ (store_ Stack) + 1, dbuf_ T; T_ and[RamMinBcplVersion, 177400]c; T_ T + (and[RamMinBcplVersion, 377]c); Stack_ (store_ Stack) + 1, dbuf_ T; T_ and[RamMinLispVersion, 177400]c; T_ T + (and[RamMinLispVersion, 377]c); Stack_ (store_ Stack) + 1, dbuf_ T; * now initialize display width rbase_ rbase[DisplayConfig]; DisplayConfig_ (DisplayConfig) OR (2C); T_ Or[177400, MaxWidthWordsLF!]C; MaxWidthWords_ T; Stack_ (store_ Stack) + 1, dbuf_ MaxWidthWordsLF; rbase_ rbase[RealPages]; T_ RealPages; Stack_ (store_ Stack) + 1, dbuf_ T; * # pages T_ 2000c; * "dummy" #pages/module Stack_ (store_ Stack) + 1, dbuf_ T, * (doesn't matter) branch[EmuNext]; SUBROUTINE; KnowRBase[LTEMP0]; setBR: BrHi_ T; BrLo_ LTEMP0, return; TOP LEVEL; *-------------------------------------------------------------- TOP LEVEL; knowrbase[LTEMP0]; InsSet[LispInsSet, 1]; opUPCTRACE: T_ (fetch_ TSP) + 1; T_ Md, fetch_ T; rbase_ rbase[Events]; Q_ Md, call[SetPCHistAddr]; NextOpCode; regOP1[374, StackM2BR, opUPCTRACE, noNData]; * op 374 reserved on Dolphin *-------------------------------------------------------------- * Memory system initialization stubs for lisp InitMapWarm: Branch[ResumeEmulator]; * i.e., don't do anything *----------------------------------------------------------- WaitForMapBuf: * Wait for map operation to complete * Clobbers nothing *----------------------------------------------------------- Subroutine; PD_ T-T-1; PD_ PRef, Branch[., ALU<0]; * MapBufBusy is sign bit Return;