// // Alto microprocessor simulator // last edited November 13, 1978 5:29 PM // // Copyright Xerox Corporation 1979 get "ami.d" get "asim.d" structure IR: // fields in IR for Nova F2's [ bit0 bit 1 z bit 7 = [ opf bit 2 = acs bit 2 opx bit 5 = [ funct bit 2 = acd bit 2 bit567 bit 3 = [ ind bit 1; idx bit 2 ] ] ] = [ blank bit 3 adrp bit 4 ] disp bit 8 = [ shift bit 2 carry bit 2 noload bit 1 skip bit 3 = [ skc bit 2 skp bit 1 ] ] ] static // the microprocessor state, comments are in Asim.d [ @t; @tu; @l; @lu @ir @carry @bus @alu @sh @skip @alucy @mar; @altbank; @mstate @marmod @md; @mdx; @mdu @nmod @pc @waiting @ramadr ] external // memory access procedures [ ReadR; WriteR ReadCON ReadRAM; WriteRAM ReadMEM; WriteMEM ] manifest // memory states [ mQUIET = 0 // memory idle mMAR1 = 1 // 1 instr. after MAR_ mMAR2 = 2 // 2 instr.s after MAR_ mMAR3 = 3 // 3 instr.s after MAR_ mMAR4 = 4 // 4 instr.s after MAR_ mMD1 = 5 // 1 instr. after fetch done in MAR2 mMD2 = 6 // 1 instr. after fetch done in MAR3-4 mST1 = 7 // 1 instr. after store done in MAR2 mST2 = 8 // 1 instr. after store done in MAR3 ] manifest msbusymask = b1+b2+b3 // mstates illegal at task switch manifest // other manifests [ MOUSELOC = #177030 // mouse data EMBANKS = #177740 // memory bank #s ] static // configuration flags [ @AltoType // 0 = must run on both Alto I and II // 1 = Alto I // 2 = Alto II ExtendedMemory ExtraROM ] static // other statics [ idlenms // mstate transition table when idle marnms // ditto for MAR_ fetchnms // ditto for _MD storenms // ditto for MD_ @cy // temp. for ALU carry @wptr // pointer to list of planned writes ] let InitAsim(atype, xrom, xm, dws; numargs na) be [ switchon na into [ case 0: atype = 0 case 1: xrom = false case 2: xm = false case 3: dws = false ] AltoType = atype ExtraROM = xrom ExtendedMemory = xm idlenms = table[ mQUIET; mMAR2; mMAR3; mMAR4; mQUIET mQUIET; mQUIET; mQUIET; mQUIET ] marnms = table[ mMAR1; -1; mMAR1; mMAR1; mMAR1 mMAR1; mMAR1; mMAR1; mMAR1 ] switchon AltoType into [ case 2: setmem2(); endcase case 1: setmem1(dws); endcase case 0: setmem0(dws); endcase ] waiting = -1 lu, tu = true, true mstate = mQUIET mdu = true marmod, md, mdx = 0, 0, 0 t, l, ir = 0, 0, 0 skip, alucy, carry = 0, 0, 0 nmod = 0 ] and setmem0(dws) be [ setmem1(dws) // Alto I timing is compatible almost everywhere storenms = table[ -1; -1; mST1; mST2; -1 mST2; -1; -1; -1 ] // store timing like Alto II storenms!mST1 = (dws? mQUIET, -1) ] and setmem1(dws) be [ marnms!mMAR1 = -1 // requires 1-cycle wait for MAR_ after MAR_ fetchnms = table[ -1; -1; mMD1; mMD2; mMD2 mQUIET; mQUIET; mQUIET; mQUIET ] // memory data is not latched test dws ifso storenms = table[ -1; -1; mST1; mST2; mST2 mST2; mQUIET; mQUIET; mQUIET ] // store as late as MAR4 ifnot storenms = table[ -1; -1; mST1; mST2; mST2 mST2; mQUIET; -1; -1 ] // store as late as MAR4 ] and setmem2() be [ marnms!mMAR1 = mMAR1 // doesn't require 1-cycle wait for MAR_ after MAR_ fetchnms = table[ mQUIET; -1; mMD1; mMD2; mMD2 mQUIET; mQUIET; mQUIET; mQUIET ] // memory data is latched storenms = table[ -1; -1; mST1; mST2; -1 mST2; -1; mQUIET; -1 ] // store no later than MAR3, double store must start at MAR2 ] let Asim() = valof // returns 0 or error string [ let ins = vec 1 ins!0 = ReadRAM(pc % #2000) ins!1 = ReadRAM(pc) let next = ins>>MI.next % nmod let nms = idlenms let nwait = -1 // Unpack instruction let rsel, aluf, bs, f1x, f2x, lt, ll = ins>>MI.rsel, ins>>MI.aluf, ins>>MI.bs, ins>>MI.f1x, ins>>MI.f2x, ins>>MI.loadt ne 0, ins>>MI.loadlx eq 0 let csel = rsel lshift 3 + bs let buscon = (f1x eq f1CONST) % (f2x eq f2CONST) let wlist = vec 8 wptr = wlist // Do most error checks if lu then if (ldef2mask lshift f2x ls 0) % (waiting eq f1WRTRAM) then resultis "L undefined" if tu then if (f2x eq f2MAGIC) % ((tdefalumask lshift aluf ls 0) & (ll % (f1x eq f1MARGETS) % (lt & (ltalumask lshift aluf ls 0)))) then resultis "T undefined" if waiting eq f1TASK then [ if nmf2mask lshift f2x ls 0 then unless (f2x eq f2IRGETS) & buscon & ((ReadCON(csel) & #107000) eq 0) do resultis "Branch modifier following TASK" if waitf1mask lshift f1x ls 0 then resultis "Delayed F1 following TASK" if (msbusymask lshift mstate ls 0) & (bs ne bsMD) & (f2x ne f2STORE) then resultis "TASK with memory running" ] if aluf ne 0 then if (not ll) & (f1x ne f1MARGETS) & ((ltalumask lshift aluf ge 0) % (not lt)) then resultis "ALU output discarded" switchon f2x into [ case f2DNS: [ if bs ne bsLOADR then resultis "DNS with BS#R_" endcase ] case f2STORE: [ if (f1x eq f1MARGETS) & ExtendedMemory endcase // not a real store if storenms!mstate eq -1 then resultis "MD_ at wrong time" nms = storenms endcase ] ] // Modify low bits of rsel let rsel1 = selecton f2x into [ case f2ACSOURCE: (rsel%3)-ir<