branches/alto2/src/emu/cpu/alto2/alto2.c
| r26199 | r26200 | |
| 1545 | 1545 | {0177020, 0177023, "XBUS Utility input bus (Alto II Std. Hardware)"}, |
| 1546 | 1546 | {0177024, 0177024, "MEAR Memory Error Address Register (Alto II Std. Hardware)"}, |
| 1547 | 1547 | {0177025, 0177025, "MESR Memory error status register (Alto II Std. Hardware)"}, |
| 1548 | | {0177026, 0177026, "MECR Memory error control register (Alto II Std. Hardware)"}, |
| 1548 | {0177026, 0177026, "MECR Memory error control register (Alto II Std. Hardware)"}, |
| 1549 | 1549 | {0177030, 0177033, "UTILIN Printer status, mouse, keyset (all 4 locations return same thing)"}, |
| 1550 | 1550 | {0177034, 0177037, "KBDAD Undecoded keyboard (Std. Hardware)"}, |
| 1551 | 1551 | {0177740, 0177757, "BANKREGS Extended memory option bank registers"}, |
| r26199 | r26200 | |
| 1579 | 1579 | offset %= ALTO2_IO_PAGE_SIZE; |
| 1580 | 1580 | offset += ALTO2_IO_PAGE_BASE; |
| 1581 | 1581 | |
| 1582 | | /* binary search in table of unicode ranges */ |
| 1582 | /* binary search in table of memory ranges */ |
| 1583 | 1583 | while (_max >= _min) |
| 1584 | 1584 | { |
| 1585 | 1585 | _mid = (_min + _max) / 2; |
| r26199 | r26200 | |
| 3213 | 3213 | |
| 3214 | 3214 | return m_next_task; // return next task (?) |
| 3215 | 3215 | } |
| 3216 | |
| 3217 | /************************************************************************************************** |
| 3218 | ; A L T O I I C O D E 3 . M U |
| 3219 | ; Copyright Xerox Corporation 1979 |
| 3220 | |
| 3221 | ;***Derived from ALTOIICODE2.MU, as last modified by |
| 3222 | ;***Tobol, August 5, 1976 12:13 PM -- fix DIOG2 bug |
| 3223 | ;***modified by Ingalls, September 6, 1977 |
| 3224 | ; BitBLT fixed (LREG bug) and extended for new memory |
| 3225 | ;***modified by Boggs and Taft September 15, 1977 10:10 PM |
| 3226 | ; Modified MRT to refresh 16K chips and added XMSTA and XMLDA. |
| 3227 | ; Fixed two bugs in DEXCH and a bug in the interval timer. |
| 3228 | ; Moved symbol and constant definitions into AltoConsts23.mu. |
| 3229 | ; MRT split and moved into two 'get' files. |
| 3230 | ;***modified by Boggs and Taft November 21, 1977 5:10 PM |
| 3231 | ; Fixed a bug in the Ethernet input main loop. |
| 3232 | ;***modified by Boggs November 28, 1977 3:53 PM |
| 3233 | ; Mess with the information returned by VERS |
| 3234 | |
| 3235 | ;Get the symbol and constant definitions |
| 3236 | #AltoConsts23.mu; |
| 3237 | |
| 3238 | ;LABEL PREDEFINITIONS |
| 3239 | |
| 3240 | ;The reset locations of the tasks: |
| 3241 | |
| 3242 | !17,20,NOVEM,,,,KSEC,,,EREST,MRT,DWT,CURT,DHT,DVT,PART,KWDX,; |
| 3243 | |
| 3244 | ;Locations which may need to be accessible from the Ram, or Ram |
| 3245 | ; locations which are accessed from the Rom (TRAP1): |
| 3246 | !37,20,START,RAMRET,RAMCYCX,,,,,,,,,,,,,TRAP1; |
| 3247 | |
| 3248 | ;Macro-op dispatch table: |
| 3249 | !37,20,DOINS,DOIND,EMCYCLE,NOPAR,JSRII,U5,U6,U7,,,,,,,RAMTRAP,TRAP; |
| 3250 | |
| 3251 | ;Parameterless macro-op sub-table: |
| 3252 | !37,40,DIR,EIR,BRI,RCLK,SIO,BLT,BLKS,SIT,JMPR,RDRM,WTRM,DIRS,VERS,DREAD,DWRITE,DEXCH,MUL,DIV,DIOG1,DIOG2,BITBLT,XMLDA,XMSTA,,,,,,,,,; |
| 3253 | |
| 3254 | ;Cycle dispatch table: |
| 3255 | !37,20,L0,L1,L2,L3,L4,L5,L6,L7,L8,R7,R6,R5,R4,R3X,R2X,R1X; |
| 3256 | |
| 3257 | ;some global R-Registers |
| 3258 | $NWW $R4; State of interrupt system |
| 3259 | $R37 $R37; Used by MRT, interval timer and EIA |
| 3260 | $MTEMP $R25; Public temporary R-Register |
| 3261 | |
| 3262 | |
| 3263 | ;The Display Controller |
| 3264 | |
| 3265 | ; its R-Registers: |
| 3266 | $CBA $R22; |
| 3267 | $AECL $R23; |
| 3268 | $SLC $R24; |
| 3269 | $HTAB $R26; |
| 3270 | $YPOS $R27; |
| 3271 | $DWA $R30; |
| 3272 | $CURX $R20; |
| 3273 | $CURDATA $R21; |
| 3274 | |
| 3275 | ; its task specific functions: |
| 3276 | $EVENFIELD $L024010,000000,000000; F2 = 10 DHT DVT |
| 3277 | $SETMODE $L024011,000000,000000; F2 = 11 DHT |
| 3278 | $DDR $L026010,000000,124100; F2 = 10 DWT |
| 3279 | |
| 3280 | !1,2,DVT1,DVT11; |
| 3281 | !1,2,MOREB,NOMORE; |
| 3282 | !1,2,NORMX,HALFX; |
| 3283 | !1,2,NODD,NEVEN; |
| 3284 | !1,2,DHT0,DHT1; |
| 3285 | !1,2,NORMODE,HALFMODE; |
| 3286 | !1,2,DWTZ,DWTY; |
| 3287 | !1,2,DOTAB,NOTAB; |
| 3288 | !1,2,XNOMORE,DOMORE; |
| 3289 | |
| 3290 | ;Display Vertical Task |
| 3291 | |
| 3292 | DVT: MAR← L← DASTART+1; |
| 3293 | CBA← L, L← 0; |
| 3294 | CURDATA← L; |
| 3295 | SLC← L; |
| 3296 | T← MD; CAUSE A VERTICAL FIELD INTERRUPT |
| 3297 | L← NWW OR T; |
| 3298 | MAR← CURLOC; SET UP THE CURSOR |
| 3299 | NWW← L, T← 0-1; |
| 3300 | L← MD XOR T; HARDWARE EXPECTS X COMPLEMENTED |
| 3301 | T← MD, EVENFIELD; |
| 3302 | CURX← L, :DVT1; |
| 3303 | |
| 3304 | DVT1: L← BIAS-T-1, TASK, :DVT2; BIAS THE Y COORDINATE |
| 3305 | DVT11: L← BIAS-T, TASK; |
| 3306 | |
| 3307 | DVT2: YPOS← L, :DVT; |
| 3308 | |
| 3309 | ;Display Horizontal Task. |
| 3310 | ;11 cycles if no block change, 17 if new control block. |
| 3311 | |
| 3312 | DHT: MAR← CBA-1; |
| 3313 | L← SLC -1, BUS=0; |
| 3314 | SLC← L, :DHT0; |
| 3315 | |
| 3316 | DHT0: T← 37400; MORE TO DO IN THIS BLOCK |
| 3317 | SINK← MD; |
| 3318 | L← T← MD AND T, SETMODE; |
| 3319 | HTAB← L LCY 8, :NORMODE; |
| 3320 | |
| 3321 | NORMODE:L← T← 377 . T; |
| 3322 | AECL← L, :REST; |
| 3323 | |
| 3324 | HALFMODE: L← T← 377 . T; |
| 3325 | AECL← L, :REST, T← 0; |
| 3326 | |
| 3327 | REST: L← DWA + T,TASK; INCREMENT DWA BY 0 OR NWRDS |
| 3328 | NDNX: DWA← L, :DHT; |
| 3329 | |
| 3330 | DHT1: L← T← MD+1, BUS=0; |
| 3331 | CBA← L, MAR← T, :MOREB; |
| 3332 | |
| 3333 | NOMORE: BLOCK, :DNX; |
| 3334 | MOREB: T← 37400; |
| 3335 | L← T← MD AND T, SETMODE; |
| 3336 | MAR← CBA+1, :NORMX, EVENFIELD; |
| 3337 | |
| 3338 | NORMX: HTAB← L LCY 8, :NODD; |
| 3339 | HALFX: HTAB← L LCY 8, :NEVEN; |
| 3340 | |
| 3341 | NODD: L←T← 377 . T; |
| 3342 | AECL← L, :XREST; ODD FIELD, FULL RESOLUTION |
| 3343 | |
| 3344 | NEVEN: L← 377 AND T; EVEN FIELD OR HALF RESOLUTION |
| 3345 | AECL←L, T←0; |
| 3346 | |
| 3347 | XREST: L← MD+T; |
| 3348 | T←MD-1; |
| 3349 | DNX: DWA←L, L←T, TASK; |
| 3350 | SLC←L, :DHT; |
| 3351 | |
| 3352 | ;Display Word Task |
| 3353 | |
| 3354 | DWT: T← DWA; |
| 3355 | T←-3+T+1; |
| 3356 | L← AECL+T,BUS=0,TASK; AECL CONTAINS NWRDS AT THIS TIME |
| 3357 | AECL←L, :DWTZ; |
| 3358 | |
| 3359 | DWTY: BLOCK; |
| 3360 | TASK, :DWTF; |
| 3361 | |
| 3362 | DWTZ: L←HTAB-1, BUS=0,TASK; |
| 3363 | HTAB←L, :DOTAB; |
| 3364 | |
| 3365 | DOTAB: DDR←0, :DWTZ; |
| 3366 | NOTAB: MAR←T←DWA; |
| 3367 | L←AECL-T-1; |
| 3368 | ALUCY, L←2+T; |
| 3369 | DWA←L, :XNOMORE; |
| 3370 | |
| 3371 | DOMORE: DDR←MD, TASK; |
| 3372 | DDR←MD, :NOTAB; |
| 3373 | |
| 3374 | XNOMORE:DDR← MD, BLOCK; |
| 3375 | DDR← MD, TASK; |
| 3376 | |
| 3377 | DWTF: :DWT; |
| 3378 | |
| 3379 | ;Alto Ethernet Microcode, Version III, Boggs and Metcalfe |
| 3380 | |
| 3381 | ;4-way branches using NEXT6 and NEXT7 |
| 3382 | !17,20,EIFB00,EODOK,EOEOK,ENOCMD,EIFB01,EODPST,EOEPST,EOREST,EIFB10,EODCOL,EOECOL,EIREST,EIFB11,EODUGH,EOEUGH,ERBRES; |
| 3383 | |
| 3384 | ;2-way branches using NEXT7 |
| 3385 | ;EOCDW1, EOCDWX, and EIGO are all related. Be careful! |
| 3386 | !7,10,,EIFOK,,EOCDW1,,EIFBAD,EOCDWX,EIGO; |
| 3387 | |
| 3388 | ;Miscellaneous address constraints |
| 3389 | !7,10,,EOCDW0,EODATA,EIDFUL,EIDZ4,EOCDRS,EIDATA,EPOST; |
| 3390 | !7,10,,EIDOK,,,EIDMOR,EIDPST; |
| 3391 | !1,1,EIFB1; |
| 3392 | !1,1,EIFRST; |
| 3393 | |
| 3394 | ;2-way branches using NEXT9 |
| 3395 | !1,2,EOINPR,EOINPN; |
| 3396 | !1,2,EODMOR,EODEND; |
| 3397 | !1,2,EOLDOK,EOLDBD; |
| 3398 | !1,2,EIFCHK,EIFPRM; |
| 3399 | !1,2,EOCDWT,EOCDGO; |
| 3400 | !1,2,ECNTOK,ECNTZR; |
| 3401 | !1,2,EIFIGN,EISET; |
| 3402 | !1,2,EIFNBC,EIFBC; |
| 3403 | |
| 3404 | ;R Memory Locations |
| 3405 | |
| 3406 | $ECNTR $R12; Remaining words in buffer |
| 3407 | $EPNTR $R13; points BEFORE next word in buffer |
| 3408 | |
| 3409 | ;Ethernet microcode Status codes |
| 3410 | |
| 3411 | $ESIDON $377; Input Done |
| 3412 | $ESODON $777; Output Done |
| 3413 | $ESIFUL $1377; Input Buffer full - words lost from tail of packet |
| 3414 | $ESLOAD $1777; Load location overflowed |
| 3415 | $ESCZER $2377; Zero word count for input or output command |
| 3416 | $ESABRT $2777; Abort - usually caused by reset command |
| 3417 | $ESNEVR $3377; Never Happen - Very bad if it does |
| 3418 | |
| 3419 | ;Main memory locations in page 1 reserved for Ethernet |
| 3420 | |
| 3421 | $EPLOC $600; Post location |
| 3422 | $EBLOC $601; Interrupt bit mask |
| 3423 | |
| 3424 | $EELOC $602; Ending count location |
| 3425 | $ELLOC $603; Load location |
| 3426 | |
| 3427 | $EICLOC $604; Input buffer Count |
| 3428 | $EIPLOC $605; Input buffer Pointer |
| 3429 | |
| 3430 | $EOCLOC $606; Output buffer Count |
| 3431 | $EOPLOC $607; Output buffer Pointer |
| 3432 | |
| 3433 | $EHLOC $610; Host Address |
| 3434 | |
| 3435 | ;Function Definitions |
| 3436 | |
| 3437 | $EIDFCT $L000000,014004,000100; BS = 4, Input data |
| 3438 | $EILFCT $L016013,070013,000100; F1 = 13, Input Look |
| 3439 | $EPFCT $L016014,070014,000100; F1 = 14, Post |
| 3440 | $EWFCT $L016015,000000,000000; F1 = 15, Wake-Up |
| 3441 | |
| 3442 | $EODFCT $L026010,000000,124000; F2 = 10, Output data |
| 3443 | $EOSFCT $L024011,000000,000000; F2 = 11, Start output |
| 3444 | $ERBFCT $L024012,000000,000000; F2 = 12, Rest branch |
| 3445 | $EEFCT $L024013,000000,000000; F2 = 13, End of output |
| 3446 | $EBFCT $L024014,000000,000000; F2 = 14, Branch |
| 3447 | $ECBFCT $L024015,000000,000000; F2 = 15, Countdown branch |
| 3448 | $EISFCT $L024016,000000,000000; F2 = 16, Start input |
| 3449 | |
| 3450 | ; - Whenever a label has a pending branch, the list of possible |
| 3451 | ; destination addresses is shown in brackets in the comment field. |
| 3452 | ; - Special functions are explained in a comment near their first use. |
| 3453 | ; - To avoid naming conflicts, all labels and special functions |
| 3454 | ; have "E" as the first letter. |
| 3455 | |
| 3456 | ;Top of Ethernet Task loop |
| 3457 | |
| 3458 | ;Ether Rest Branch Function - ERBFCT |
| 3459 | ;merge ICMD and OCMD Flip Flops into NEXT6 and NEXT7 |
| 3460 | ;ICMD and OCMD are set from AC0 [14:15] by the SIO instruction |
| 3461 | ; 00 neither |
| 3462 | ; 01 OCMD - Start output |
| 3463 | ; 10 ICMD - Start input |
| 3464 | ; 11 Both - Reset interface |
| 3465 | |
| 3466 | ;in preparation for a hack at EIREST, zero EPNTR |
| 3467 | |
| 3468 | EREST: L← 0,ERBFCT; What's happening ? |
| 3469 | EPNTR← L,:ENOCMD; [ENOCMD,EOREST,EIREST,ERBRES] |
| 3470 | |
| 3471 | ENOCMD: L← ESNEVR,:EPOST; Shouldn't happen |
| 3472 | ERBRES: L← ESABRT,:EPOST; Reset Command |
| 3473 | |
| 3474 | ;Post status and halt. Microcode status in L. |
| 3475 | ;Put microstatus,,hardstatus in EPLOC, merge c(EBLOC) into NWW. |
| 3476 | ;Note that we write EPLOC and read EBLOC in one operation |
| 3477 | |
| 3478 | ;Ether Post Function - EPFCT. Gate the hardware status |
| 3479 | ;(LOW TRUE) to Bus [10:15], reset interface. |
| 3480 | |
| 3481 | EPOST: MAR← EELOC; |
| 3482 | EPNTR← L,TASK; Save microcode status in EPNTR |
| 3483 | MD← ECNTR; Save ending count |
| 3484 | |
| 3485 | MAR← EPLOC; double word reference |
| 3486 | T← NWW; |
| 3487 | MD← EPNTR,EPFCT; BUS AND EPNTR with Status |
| 3488 | L← MD OR T,TASK; NWW OR c(EBLOC) |
| 3489 | NWW← L,:EREST; Done. Wait for next command |
| 3490 | |
| 3491 | ;This is a subroutine called from both input and output (EOCDGO |
| 3492 | ;and EISET). The return address is determined by testing ECBFCT, |
| 3493 | ;which will branch if the buffer has any words in it, which can |
| 3494 | ;only happen during input. |
| 3495 | |
| 3496 | ESETUP: NOP; |
| 3497 | L← MD,BUS=0; check for zero length |
| 3498 | T← MD-1,:ECNTOK; [ECNTOK,ECNTZR] start-1 |
| 3499 | |
| 3500 | ECNTZR: L← ESCZER,:EPOST; Zero word count. Abort |
| 3501 | |
| 3502 | ;Ether Countdown Branch Function - ECBFCT. |
| 3503 | ;NEXT7 = Interface buffer not empty. |
| 3504 | |
| 3505 | ECNTOK: ECNTR← L,L← T,ECBFCT,TASK; |
| 3506 | EPNTR← L,:EODATA; [EODATA,EIDATA] |
| 3507 | |
| 3508 | ;Ethernet Input |
| 3509 | |
| 3510 | ;It turns out that starting the receiver for the first time and |
| 3511 | ;restarting it after ignoring a packet do the same things. |
| 3512 | |
| 3513 | EIREST: :EIFIGN; Hack |
| 3514 | |
| 3515 | ;Address filtering code. |
| 3516 | |
| 3517 | ;When the first word of a packet is available in the interface |
| 3518 | ;buffer, a wakeup request is generated. The microcode then |
| 3519 | ;decides whether to accept the packet. Decision must be reached |
| 3520 | ;before the buffer overflows, within about 14*5.44 usec. |
| 3521 | ;if EHLOC is zero, machine is 'promiscuous' - accept all packets |
| 3522 | ;if destination byte is zero, it is a 'broadcast' packet, accept. |
| 3523 | ;if destination byte equals EHLOC, packet is for us, accept. |
| 3524 | |
| 3525 | ;EIFRST is really a subroutine that can be called from EIREST |
| 3526 | ;or from EIGO, output countdown wait. If a packet is ignored |
| 3527 | ;and EPNTR is zero, EIFRST loops back and waits for more |
| 3528 | ;packets, else it returns to the countdown code. |
| 3529 | |
| 3530 | ;Ether Branch Function - EBFCT |
| 3531 | ;NEXT7 = IDL % OCMD % ICMD % OUTGONE % INGONE (also known as POST) |
| 3532 | ;NEXT6 = COLLision - Can't happen during input |
| 3533 | |
| 3534 | EIFRST: MAR← EHLOC; Get Ethernet address |
| 3535 | T← 377,EBFCT; What's happening? |
| 3536 | L← MD AND T,BUS=0,:EIFOK;[EIFOK,EIFBAD] promiscuous? |
| 3537 | |
| 3538 | EIFOK: MTEMP← LLCY8,:EIFCHK; [EIFCHK,EIFPRM] Data wakeup |
| 3539 | |
| 3540 | EIFBAD: ERBFCT,TASK,:EIFB1; [EIFB1] POST wakeup; xCMD FF set? |
| 3541 | EIFB1: :EIFB00; [EIFB00,EIFB01,EIFB10,EIFB11] |
| 3542 | |
| 3543 | EIFB00: :EIFIGN; IDL or INGONE, restart rcvr |
| 3544 | EIFB01: L← ESABRT,:EPOST; OCMD, abort |
| 3545 | EIFB10: L← ESABRT,:EPOST; ICMD, abort |
| 3546 | EIFB11: L← ESABRT,:EPOST; ICMD and OCMD, abort |
| 3547 | |
| 3548 | EIFPRM: TASK,:EIFBC; Promiscuous. Accept |
| 3549 | |
| 3550 | ;Ether Look Function - EILFCT. Gate the first word of the |
| 3551 | ;data buffer to the bus, but do not increment the read pointer. |
| 3552 | |
| 3553 | EIFCHK: L← T← 177400,EILFCT; Mask off src addr byte (BUS AND) |
| 3554 | L← MTEMP-T,SH=0; Broadcast? |
| 3555 | SH=0,TASK,:EIFNBC; [EIFNBC,EIFBC] Our Address? |
| 3556 | |
| 3557 | EIFNBC: :EIFIGN; [EIFIGN,EISET] |
| 3558 | |
| 3559 | EIFBC: :EISET; [EISET] Enter input main loop |
| 3560 | |
| 3561 | ;Ether Input Start Function - EISFCT. Start receiver. Interface |
| 3562 | ;will generate a data wakeup when the first word of the next |
| 3563 | ;packet arrives, ignoring any packet currently passing. |
| 3564 | |
| 3565 | EIFIGN: SINK← EPNTR,BUS=0,EPFCT;Reset; Called from output? |
| 3566 | EISFCT,TASK,:EOCDWX; [EOCDWX,EIGO] Restart rcvr |
| 3567 | |
| 3568 | EOCDWX: EWFCT,:EOCDWT; Return to countdown wait loop |
| 3569 | |
| 3570 | EISET: MAR← EICLOC,:ESETUP; Double word reference |
| 3571 | |
| 3572 | ;Input Main Loop |
| 3573 | |
| 3574 | ;Ether Input Data Function - EIDFCT. Gate a word of data to |
| 3575 | ;the bus from the interface data buffer, increment the read ptr. |
| 3576 | ; * * * * * W A R N I N G * * * * * |
| 3577 | ;The delay from decoding EIDFCT to gating data to the bus is |
| 3578 | ;marginal. Some logic in the interface detects the situation |
| 3579 | ;(which only happens occasionally) and stops SysClk for one cycle. |
| 3580 | ;Since memory data must be available during cycle 4, and SysClk |
| 3581 | ;may stop for one cycle, this means that the MD← EIDFCT must |
| 3582 | ;happen in cycle 3. There is a bug in this logic which occasionally |
| 3583 | ;stops the clock in the instruction following the EIDFCT, so |
| 3584 | ;the EIDFCT instruction should not be the last one of the task, |
| 3585 | ;or it may screw up someone else (such as RDRAM). |
| 3586 | |
| 3587 | ;EIDOK, EIDMOR, and EIDPST must have address bits in the pattern: |
| 3588 | ;xxx1 xxx4 xxx5 |
| 3589 | ;ECBFCT is used to force an unconditional branch on NEXT7 |
| 3590 | |
| 3591 | EIDATA: T← ECNTR-1, BUS=0; |
| 3592 | MAR← L← EPNTR+1, EBFCT; [EIDMOR,EIDPST] What's happening |
| 3593 | EIDMOR: EPNTR← L, L← T, ECBFCT; [EIDOK,EIDPST] Guaranteed to branch |
| 3594 | EIDOK: MD← EIDFCT, TASK; [EIDZ4] Read a word from the interface |
| 3595 | EIDZ4: ECNTR← L, :EIDATA; |
| 3596 | |
| 3597 | ; We get to EIDPST for one of two reasons: |
| 3598 | ; (1) The buffer is full. In this case, an EBFCT (NEXT[7]) is pending. |
| 3599 | ; We want to post "full" if this is a normal data wakeup (no branch) |
| 3600 | ; but just "input done" if hardware input terminated (branch). |
| 3601 | ; (2) Hardware input terminated while the buffer was not full. |
| 3602 | ; In this case, an unconditional branch on NEXT[7] is pending, so |
| 3603 | ; we always terminate with "input done". |
| 3604 | EIDPST: L← ESIDON, :EIDFUL; [EIDFUL,EPOST] Presumed to be INGONE |
| 3605 | EIDFUL: L← ESIFUL, :EPOST; Input buffer overrun |
| 3606 | |
| 3607 | ;Ethernet output |
| 3608 | |
| 3609 | ;It is possible to get here due to a collision. If a collision |
| 3610 | ;happened, the interface was reset (EPFCT) to shut off the |
| 3611 | ;transmitter. EOSFCT is issued to guarantee more wakeups while |
| 3612 | ;generating the countdown. When this is done, the interface is |
| 3613 | ;again reset, without really doing an output. |
| 3614 | |
| 3615 | EOREST: MAR← ELLOC; Get load |
| 3616 | L← R37; Use clock as random # gen |
| 3617 | EPNTR← LRSH1; Use bits [6:13] |
| 3618 | L← MD,EOSFCT; L← current load |
| 3619 | SH<0,ECNTR← L; Overflowed? |
| 3620 | MTEMP← LLSH1,:EOLDOK; [EOLDOK,EOLDBD] |
| 3621 | |
| 3622 | EOLDBD: L← ESLOAD,:EPOST; Load overlow |
| 3623 | |
| 3624 | EOLDOK: L← MTEMP+1; Write updated load |
| 3625 | MAR← ELLOC; |
| 3626 | MTEMP← L,TASK; |
| 3627 | MD← MTEMP,:EORST1; New load = (old lshift 1) + 1 |
| 3628 | |
| 3629 | EORST1: L← EPNTR; Continue making random # |
| 3630 | EPNTR← LRSH1; |
| 3631 | T← 377; |
| 3632 | L← EPNTR AND T,TASK; |
| 3633 | EPNTR← L,:EORST2; |
| 3634 | |
| 3635 | ;At this point, EPNTR has 0,,random number, ENCTR has old load. |
| 3636 | |
| 3637 | EORST2: MAR← EICLOC; Has an input buffer been set up? |
| 3638 | T← ECNTR; |
| 3639 | L← EPNTR AND T; L← Random & Load |
| 3640 | SINK← MD,BUS=0; |
| 3641 | ECNTR← L,SH=0,EPFCT,:EOINPR;[EOINPR,EOINPN] |
| 3642 | |
| 3643 | EOINPR: EISFCT,:EOCDWT; [EOCDWT,EOCDGO] Enable in under out |
| 3644 | |
| 3645 | EOINPN: :EOCDWT; [EOCDWT,EOCDGO] No input. |
| 3646 | |
| 3647 | ;Countdown wait loop. MRT will generate a wakeup every |
| 3648 | ;37 usec which will decrement ECNTR. When it is zero, start |
| 3649 | ;the transmitter. |
| 3650 | |
| 3651 | ;Ether Wake Function - EWFCT. Sets a flip flop which will cause |
| 3652 | ;a wakeup to this task the next time MRT wakes up (every 37 usec). |
| 3653 | ;Wakeup is cleared when Ether task next runs. EWFCT must be |
| 3654 | ;issued in the instruction AFTER a task. |
| 3655 | |
| 3656 | EOCDWT: L← 177400,EBFCT; What's happening? |
| 3657 | EPNTR← L,ECBFCT,:EOCDW0;[EOCDW0,EOCDRS] Packet coming in? |
| 3658 | EOCDW0: L← ECNTR-1,BUS=0,TASK,:EOCDW1; [EOCDW1,EIGO] |
| 3659 | EOCDW1: ECNTR← L,EWFCT,:EOCDWT; [EOCDWT,EOCDGO] |
| 3660 | |
| 3661 | EOCDRS: L← ESABRT,:EPOST; [EPOST] POST event |
| 3662 | |
| 3663 | EIGO: :EIFRST; [EIFRST] Input under output |
| 3664 | |
| 3665 | ;Output main loop setup |
| 3666 | |
| 3667 | EOCDGO: MAR← EOCLOC; Double word reference |
| 3668 | EPFCT; Reset interface |
| 3669 | EOSFCT,:ESETUP; Start Transmitter |
| 3670 | |
| 3671 | ;Ether Output Start Function - EOSFCT. The interface will generate |
| 3672 | ;a burst of data requests until the interface buffer is full or the |
| 3673 | ;memory buffer is empty, wait for silence on the Ether, and begin |
| 3674 | ;transmitting. Thereafter it will request a word every 5.44 us. |
| 3675 | |
| 3676 | ;Ether Output Data Function - EODFCT. Copy the bus into the |
| 3677 | ;interface data buffer, increment the write pointer, clears wakeup |
| 3678 | ;request if the buffer is now nearly full (one slot available). |
| 3679 | |
| 3680 | ;Output main loop |
| 3681 | |
| 3682 | EODATA: L← MAR← EPNTR+1,EBFCT; What's happening? |
| 3683 | T← ECNTR-1,BUS=0,:EODOK; [EODOK,EODPST,EODCOL,EODUGH] |
| 3684 | EODOK: EPNTR← L,L← T,:EODMOR; [EODMOR,EODEND] |
| 3685 | EODMOR: ECNTR← L,TASK; |
| 3686 | EODFCT← MD,:EODATA; Output word to transmitter |
| 3687 | |
| 3688 | EODPST: L← ESABRT,:EPOST; [EPOST] POST event |
| 3689 | |
| 3690 | EODCOL: EPFCT,:EOREST; [EOREST] Collision |
| 3691 | |
| 3692 | EODUGH: L← ESABRT,:EPOST; [EPOST] POST + Collision |
| 3693 | |
| 3694 | ;Ether EOT Function - EEFCT. Stop generating output data wakeups, |
| 3695 | ;the interface has all of the packet. When the data buffer runs |
| 3696 | ;dry, the interface will append the CRC and then generate an |
| 3697 | ;OUTGONE post wakeup. |
| 3698 | |
| 3699 | EODEND: EEFCT; Disable data wakeups |
| 3700 | TASK; Wait for EEFCT to take |
| 3701 | :EOEOT; Wait for Outgone |
| 3702 | |
| 3703 | ;Output completion. We are waiting for the interface buffer to |
| 3704 | ;empty, and the interface to generate an OUTGONE Post wakeup. |
| 3705 | |
| 3706 | EOEOT: EBFCT; What's happening? |
| 3707 | :EOEOK; [EOEOK,EOEPST,EOECOL,EOEUGH] |
| 3708 | |
| 3709 | EOEOK: L← ESNEVR,:EPOST; Runaway Transmitter. Never Never. |
| 3710 | |
| 3711 | EOEPST: L← ESODON,:EPOST; POST event. Output done |
| 3712 | |
| 3713 | EOECOL: EPFCT,:EOREST; Collision |
| 3714 | |
| 3715 | EOEUGH: L← ESABRT,:EPOST; POST + Collision |
| 3716 | |
| 3717 | |
| 3718 | ;Memory Refresh Task, |
| 3719 | ;Mouse Handler, |
| 3720 | ;EIA Handler, |
| 3721 | ;Interval Timer, |
| 3722 | ;Calender Clock, and |
| 3723 | ;part of the cursor. |
| 3724 | |
| 3725 | !17,20,TX0,TX6,TX3,TX2,TX8,TX5,TX1,TX7,TX4,,,,,,,; |
| 3726 | !1,2,DOTIMER,NOTIMER; |
| 3727 | !1,2,NOTIMERINT,TIMERINT; |
| 3728 | !1,2,DOCUR,NOCUR; |
| 3729 | !1,2,SHOWC,WAITC; |
| 3730 | !1,2,SPCHK,NOSPCHK; |
| 3731 | |
| 3732 | !1,2,NOCLK,CLOCK; |
| 3733 | !1,1,MRTLAST; |
| 3734 | !1,2,CNOTLAST,CLAST; |
| 3735 | |
| 3736 | $CLOCKTEMP $R11; |
| 3737 | $REFIIMSK $7777; |
| 3738 | |
| 3739 | ; * * * A T T E N T I O N * * * |
| 3740 | ;There are two versions of the Memory refresh code: |
| 3741 | ; AltoIIMRT4K.mu for refreshing 4K chips |
| 3742 | ; AltoIIMRT16K.mu for refreshing 16K chips |
| 3743 | ;You must name one or the other 'AltoIIMRT.mu'. |
| 3744 | ;I suggest the following convention for naming the resulting .MB file: |
| 3745 | ; AltoIICode3.MB for the 4K version |
| 3746 | ; AltoIICode3XM.MB for the 16K version |
| 3747 | |
| 3748 | #AltoIIMRT.mu; |
| 3749 | |
| 3750 | CLOCK: MAR← CLOCKLOC; R37 OVERFLOWED. |
| 3751 | NOP; |
| 3752 | L← MD+1; INCREMENT CLOCK IM MEMORY |
| 3753 | MAR← CLOCKLOC; |
| 3754 | MTEMP← L, TASK; |
| 3755 | MD← MTEMP, :NOCLK; |
| 3756 | |
| 3757 | DOCUR: L← T← YPOS; CHECK FOR VISIBLE CURSOR ON THIS SCAN |
| 3758 | SH<0, L← 20-T-1; ***x13 change: the constant 20 was 17 |
| 3759 | SH<0, L← 2+T, :SHOWC; [SHOWC,WAITC] |
| 3760 | |
| 3761 | WAITC: YPOS← L, L← 0, TASK, :MRTLAST; SQUASHES PENDING BRANCH |
| 3762 | SHOWC: MAR← CLOCKLOC+T+1, :CNOTLAST; |
| 3763 | |
| 3764 | CNOTLAST: T← CURX, :CURF; |
| 3765 | CLAST: T← 0; |
| 3766 | CURF: YPOS← L, L← T; |
| 3767 | CURX← L; |
| 3768 | L← MD, TASK; |
| 3769 | CURDATA← L, :MRT; |
| 3770 | |
| 3771 | ;AFTER THIS DISPATCH, T WILL CONTAIN XCHANGE, L WILL CONTAIN YCHANGE-1 |
| 3772 | |
| 3773 | TX1: L← T← ONE +T, :M00; Y=0, X=1 |
| 3774 | TX2: L← T← ALLONES, :M00; Y=0, X=-1 |
| 3775 | TX3: L← T← 0, :M00; Y=1, X=0 |
| 3776 | TX4: L← T← ONE AND T, :M00; Y=1, X=1 |
| 3777 | TX5: L← T← ALLONES XOR T, :M00; Y=1, X=-1 |
| 3778 | TX6: T← 0, :M00; Y=-1, X=0 |
| 3779 | TX7: T← ONE, :M00; Y=-1, X=1 |
| 3780 | TX8: T← ALLONES, :M00; Y=-1, X=-1 |
| 3781 | |
| 3782 | M00: MAR← MOUSELOC; START THE FETCH OF THE COORDINATES |
| 3783 | MTEMP← L; YCHANGE -1 |
| 3784 | L← MD+ T; X+ XCHANGE |
| 3785 | T← MD; Y |
| 3786 | T← MTEMP+ T+1; Y+ (YCHANGE-1) + 1 |
| 3787 | MTEMP← L, L← T; |
| 3788 | MAR← MOUSELOC; NOW RESTORE THE UPDATED COORDINATES |
| 3789 | CLOCKTEMP← L; |
| 3790 | MD← MTEMP, TASK; |
| 3791 | MD← CLOCKTEMP, :MRTA; |
| 3792 | |
| 3793 | |
| 3794 | ;CURSOR TASK |
| 3795 | |
| 3796 | ;Cursor task specific functions |
| 3797 | $XPREG $L026010,000000,124000; F2 = 10 |
| 3798 | $CSR $L026011,000000,124000; F2 = 11 |
| 3799 | |
| 3800 | CURT: XPREG← CURX, TASK; |
| 3801 | CSR← CURDATA, :CURT; |
| 3802 | |
| 3803 | |
| 3804 | ;PREDEFINITION FOR PARITY TASK. |
| 3805 | ;THE CODE IS AT THE END OF THE FILE |
| 3806 | !17,20,PR0,,PR2,PR3,PR4,PR5,PR6,PR7,PR8,,,,,,,; |
| 3807 | |
| 3808 | ;NOVA EMULATOR |
| 3809 | |
| 3810 | $SAD $R5; |
| 3811 | $PC $R6; USED BY MEMORY INIT |
| 3812 | |
| 3813 | |
| 3814 | !7,10,Q0,Q1,Q2,Q3,Q4,Q5,Q6,Q7; |
| 3815 | !1,2,FINSTO,INCPC; |
| 3816 | !1,2,EReRead,FINJMP; ***X21 addition. |
| 3817 | !1,2,EReadDone,EContRead; ***X21 addition. |
| 3818 | !1,2,EtherBoot,DiskBoot; ***X21 addition. |
| 3819 | |
| 3820 | NOVEM: IR←L←MAR←0, :INXB,SAD← L; LOAD SAD TO ZERO THE BUS. STORE PC AT 0 |
| 3821 | Q0: L← ONE, :INXA; EXECUTED TWICE |
| 3822 | Q1: L← TOTUWC, :INXA; |
| 3823 | Q2: L←402, :INXA; FIRST READ HEADER INTO 402, THEN |
| 3824 | Q3: L← 402, :INXA; STORE LABEL AT 402 |
| 3825 | Q4: L← ONE, :INXA; STORE DATA PAGE STARTING AT 1 |
| 3826 | Q5: L←377+1, :INXE; Store Ethernet Input Buffer Length ***X21. |
| 3827 | Q6: L←ONE, :INXE; Store Ethernet Input Buffer Pointer ***X21. |
| 3828 | Q7: MAR← DASTART; CLEAR THE DISPLAY POINTER |
| 3829 | L← 0; |
| 3830 | R37← L; |
| 3831 | MD← 0; |
| 3832 | MAR← 177034; FETCH KEYBOARD |
| 3833 | L← 100000; |
| 3834 | NWW← L, T← 0-1; |
| 3835 | L← MD XOR T, BUSODD; *** X21 change. |
| 3836 | MAR← BDAD, :EtherBoot; [EtherBoot, DiskBoot] *** X21 change. |
| 3837 | ; BOOT DISK ADDRESS GOES IN LOCATION 12 |
| 3838 | DiskBoot: SAD← L, L← 0+1; |
| 3839 | MD← SAD; |
| 3840 | MAR← KBLKADR, :FINSTO; |
| 3841 | |
| 3842 | |
| 3843 | ; Ethernet boot section added in X21. |
| 3844 | $NegBreathM1 $177175; |
| 3845 | $EthNovaGo $3; First data location of incoming packet |
| 3846 | |
| 3847 | EtherBoot: L←EthNovaGo, :EReRead; [EReRead, FINJMP] |
| 3848 | |
| 3849 | EReRead:MAR← EHLOC; Set the host address to 377 for breath packets |
| 3850 | TASK; |
| 3851 | MD← 377; |
| 3852 | |
| 3853 | MAR← EPLOC; Zero the status word and start 'er up |
| 3854 | SINK← 2, STARTF; |
| 3855 | MD ← 0; |
| 3856 | |
| 3857 | EContRead: MAR← EPLOC; See if status is still 0 |
| 3858 | T← 377; Status for correct read |
| 3859 | L← MD XOR T, TASK, BUS=0; |
| 3860 | SAD← L, :EReadDone; [EReadDone, EContRead] |
| 3861 | |
| 3862 | EReadDone: MAR← 2; Check the packet type |
| 3863 | T← NegBreathM1; -(Breath-of-life)-1 |
| 3864 | T←MD+T+1; |
| 3865 | L←SAD OR T; |
| 3866 | SH=0, :EtherBoot; |
| 3867 | |
| 3868 | |
| 3869 | ; SUBROUTINE USED BY INITIALIZATION TO SET UP BLOCKS OF MEMORY |
| 3870 | $EIOffset $576; |
| 3871 | |
| 3872 | INXA: T←ONE, :INXCom; ***X21 change. |
| 3873 | INXE: T←EIOffset, :INXCom; ***X21 addition. |
| 3874 | |
| 3875 | INXCom: MAR←T←IR← SAD+T; *** X21 addition. |
| 3876 | PC← L, L← 0+T+1; *** X21 change. |
| 3877 | INXB: MD← PC; |
| 3878 | SINK← DISP, BUS,TASK; |
| 3879 | SAD← L, :Q0; |
| 3880 | |
| 3881 | |
| 3882 | ;REGISTERS USED BY NOVA EMULATOR |
| 3883 | $AC0 $R3; AC'S ARE BACKWARDS BECAUSE THE HARDWARE SUPPLIES THE |
| 3884 | $AC1 $R2; COMPLEMENT ADDRESS WHEN ADDRESSING FROM IR |
| 3885 | $AC2 $R1; |
| 3886 | $AC3 $R0; |
| 3887 | $XREG $R7; |
| 3888 | |
| 3889 | |
| 3890 | ;PREDEFINITIONS FOR NOVA |
| 3891 | |
| 3892 | !17,20,GETAD,G1,G2,G3,G4,G5,G6,G7,G10,G11,G12,G13,G14,G15,G16,G17; |
| 3893 | !17,20,XCTAB,XJSR,XISZ,XDSZ,XLDA,XSTA,CONVERT,,,,,,,,,; |
| 3894 | !3,4,SHIFT,SH1,SH2,SH3; |
| 3895 | !1,2,MAYBE,NOINT; |
| 3896 | !1,2,DOINT,DIS0; |
| 3897 | !1,2,SOMEACTIVE,NOACTIVE; |
| 3898 | !1,2,IEXIT,NIEXIT; |
| 3899 | !17,1,ODDCX; |
| 3900 | !1,2,EIR0,EIR1; |
| 3901 | !7,1,INTCODE; |
| 3902 | !1,2,INTSOFF,INTSON; ***X21 addition for DIRS |
| 3903 | !7,10,EMCYCRET,RAMCYCRET,CYX2,CYX3,CYX4,CONVCYCRET,,; |
| 3904 | !7,2,MOREBLT,FINBLT; |
| 3905 | !1,2,DOIT,DISABLED; |
| 3906 | |
| 3907 | ; ALL INSTRUCTIONS RETURN TO START WHEN DONE |
| 3908 | |
| 3909 | START: T← MAR←PC+SKIP; |
| 3910 | START1: L← NWW, BUS=0; BUS# 0 MEANS DISABLED OR SOMETHING TO DO |
| 3911 | :MAYBE, SH<0, L← 0+T+1; SH<0 MEANS DISABLED |
| 3912 | MAYBE: PC← L, L← T, :DOINT; |
| 3913 | NOINT: PC← L, :DIS0; |
| 3914 | |
| 3915 | DOINT: MAR← WWLOC, :INTCODE; TRY TO CAUSE AN INTERRUPT |
| 3916 | |
| 3917 | ;DISPATCH ON FUNCTION FIELD IF ARITHMETIC INSTRUCTION, |
| 3918 | ;OTHERWISE ON INDIRECT BIT AND INDEX FIELD |
| 3919 | |
| 3920 | DIS0: L← T← IR← MD; SKIP CLEARED HERE |
| 3921 | |
| 3922 | ;DISPATCH ON SHIFT FIELD IF ARITHMETIC INSTRUCTION, |
| 3923 | ;OTHERWISE ON THE INDIRECT BIT OR IR[3-7] |
| 3924 | |
| 3925 | DIS1: T← ACSOURCE, :GETAD; |
| 3926 | |
| 3927 | ;GETAD MUST BE 0 MOD 20 |
| 3928 | GETAD: T← 0, :DOINS; PAGE 0 |
| 3929 | G1: T← PC -1, :DOINS; RELATIVE |
| 3930 | G2: T← AC2, :DOINS; AC2 RELATIVE |
| 3931 | G3: T← AC3, :DOINS; AC3 RELATIVE |
| 3932 | G4: T← 0, :DOINS; PAGE 0 INDIRECT |
| 3933 | G5: T← PC -1, :DOINS; RELATIVE INDIRECT |
| 3934 | G6: T← AC2, :DOINS; AC2 RELATIVE INDIRECT |
| 3935 | G7: T← AC3, :DOINS; AC3 RELATIVE INDIRECT |
| 3936 | G10: L← 0-T-1, TASK, :SHIFT; COMPLEMENT |
| 3937 | G11: L← 0-T, TASK, :SHIFT; NEGATE |
| 3938 | G12: L← 0+T, TASK, :SHIFT; MOVE |
| 3939 | G13: L← 0+T+1, TASK, :SHIFT; INCREMENT |
| 3940 | G14: L← ACDEST-T-1, TASK, :SHIFT; ADD COMPLEMENT |
| 3941 | G15: L← ACDEST-T, TASK, :SHIFT; SUBTRACT |
| 3942 | G16: L← ACDEST+T, TASK, :SHIFT; ADD |
| 3943 | G17: L← ACDEST AND T, TASK, :SHIFT; |
| 3944 | |
| 3945 | SHIFT: DNS← L LCY 8, :START; SWAP BYTES |
| 3946 | SH1: DNS← L RSH 1, :START; RIGHT 1 |
| 3947 | SH2: DNS← L LSH 1, :START; LEFT 1 |
| 3948 | SH3: DNS← L, :START; NO SHIFT |
| 3949 | |
| 3950 | DOINS: L← DISP + T, TASK, :SAVAD, IDISP; DIRECT INSTRUCTIONS |
| 3951 | DOIND: L← MAR← DISP+T; INDIRECT INSTRUCTIONS |
| 3952 | XREG← L; |
| 3953 | L← MD, TASK, IDISP, :SAVAD; |
| 3954 | |
| 3955 | BRI: L← MAR← PCLOC ;INTERRUPT RETURN BRANCH |
| 3956 | BRI0: T← 77777; |
| 3957 | L← NWW AND T, SH < 0; |
| 3958 | NWW← L, :EIR0; BOTH EIR AND BRI MUST CHECK FOR INTERRUPT |
| 3959 | ; REQUESTS WHICH MAY HAVE COME IN WHILE |
| 3960 | ; INTERRUPTS WERE OFF |
| 3961 | |
| 3962 | EIR0: L← MD, :DOINT; |
| 3963 | EIR1: L← PC, :DOINT; |
| 3964 | |
| 3965 | ;***X21 addition |
| 3966 | ; DIRS - 61013 - Disable Interrupts and Skip if they were On |
| 3967 | DIRS: T←100000; |
| 3968 | L←NWW AND T; |
| 3969 | L←PC+1, SH=0; |
| 3970 | |
| 3971 | ; DIR - 61000 - Disable Interrupts |
| 3972 | DIR: T← 100000, :INTSOFF; |
| 3973 | INTSOFF: L← NWW OR T, TASK, :INTZ; |
| 3974 | |
| 3975 | INTSON: PC←L, :INTSOFF; |
| 3976 | |
| 3977 | ;EIR - 61001 - Enable Interrupts |
| 3978 | EIR: L← 100000, :BRI0; |
| 3979 | |
| 3980 | ;SIT - 61007 - Start Interval Timer |
| 3981 | SIT: T← AC0; |
| 3982 | L← R37 OR T, TASK; |
| 3983 | R37← L, :START; |
| 3984 | |
| 3985 | |
| 3986 | FINJSR: L← PC; |
| 3987 | AC3← L, L← T, TASK; |
| 3988 | FINJMP: PC← L, :START; |
| 3989 | SAVAD: SAD← L, :XCTAB; |
| 3990 | |
| 3991 | ;JSRII - 64400 - JSR double indirect, PC relative. Must have X=1 in opcode |
| 3992 | ;JSRIS - 65000 - JSR double indirect, AC2 relative. Must have X=2 in opcode |
| 3993 | JSRII: MAR← DISP+T; FIRST LEVEL |
| 3994 | IR← JSRCX; <JSR 0> |
| 3995 | T← MD, :DOIND; THE IR← INSTRUCTION WILL NOT BRANCH |
| 3996 | |
| 3997 | |
| 3998 | ;TRAP ON UNIMPLEMENTED OPCODES. SAVES PC AT |
| 3999 | ;TRAPPC, AND DOES A JMP@ TRAPVEC ! OPCODE. |
| 4000 | TRAP: XREG← L LCY 8; THE INSTRUCTION |
| 4001 | TRAP1: MAR← TRAPPC;***X13 CHANGE: TAG 'TRAP1' ADDED |
| 4002 | IR← T← 37; |
| 4003 | MD← PC; |
| 4004 | T← XREG.T; |
| 4005 | T← TRAPCON+T+1, :DOIND; T NOW CONTAINS 471+OPCODE |
| 4006 | ; THIS WILL DO JMP@ 530+OPCODE |
| 4007 | |
| 4008 | ;***X21 CHANGE: ADDED TAG RAMTRAP |
| 4009 | RAMTRAP: SWMODE, :TRAP; |
| 4010 | |
| 4011 | ; Parameterless operations come here for dispatch. |
| 4012 | |
| 4013 | !1,2,NPNOTRAP,NPTRAP; |
| 4014 | |
| 4015 | NOPAR: XREG←L LCY 8; ***X21 change. Checks < 27. |
| 4016 | T←27; ***IIX3. Greatest defined op is 26. |
| 4017 | L←DISP-T; |
| 4018 | ALUCY; |
| 4019 | SINK←DISP, SINK←X37, BUS, TASK, :NPNOTRAP; |
| 4020 | |
| 4021 | NPNOTRAP: :DIR; |
| 4022 | |
| 4023 | NPTRAP: :TRAP1; |
| 4024 | |
| 4025 | ;***X21 addition for debugging w/ expanded DISP Prom |
| 4026 | U5: :RAMTRAP; |
| 4027 | U6: :RAMTRAP; |
| 4028 | U7: :RAMTRAP; |
| 4029 | |
| 4030 | ;MAIN INSTRUCTION TABLE. GET HERE: |
| 4031 | ; (1) AFTER AN INDIRECTION |
| 4032 | ; (2) ON DIRECT INSTRUCTIONS |
| 4033 | |
| 4034 | XCTAB: L← SAD, TASK, :FINJMP; JMP |
| 4035 | XJSR: T← SAD, :FINJSR; JSR |
| 4036 | XISZ: MAR← SAD, :ISZ1; ISZ |
| 4037 | XDSZ: MAR← SAD, :DSZ1; DSZ |
| 4038 | XLDA: MAR← SAD, :FINLOAD; LDA 0-3 |
| 4039 | XSTA: MAR← SAD; /*NORMAL |
| 4040 | XSTA1: L← ACDEST, :FINSTO; /*NORMAL |
| 4041 | |
| 4042 | ; BOUNDS-CHECKING VERSION OF STORE |
| 4043 | ; SUBST ";**<CR>" TO "<CR>;**" TO ENABLE THIS CODE: |
| 4044 | ;** !1,2,XSTA1,XSTA2; |
| 4045 | ;** !1,2,DOSTA,TRAPSTA; |
| 4046 | ;**XSTA: MAR← 10; LOCS 10,11 CONTAINS HI,LO BOUNDS |
| 4047 | ;** T← SAD |
| 4048 | ;** L← MD-T; HIGHBOUND-ADDR |
| 4049 | ;** T← MD, ALUCY; |
| 4050 | ;** L← SAD-T, :XSTA1; ADDR-LOWBOUND |
| 4051 | ;**XSTA1: TASK, :XSTA3; |
| 4052 | ;**XSTA2: ALUCY, TASK; |
| 4053 | ;**XSTA3: L← 177, :DOSTA; |
| 4054 | ;**TRAPSTA: XREG← L, :TRAP1; CAUSE A SWAT |
| 4055 | ;**DOSTA: MAR← SAD; DO THE STORE NORMALLY |
| 4056 | ;** L← ACDEST, :FINSTO; |
| 4057 | ;** |
| 4058 | |
| 4059 | DSZ1: T← ALLONES, :FINISZ; |
| 4060 | ISZ1: T← ONE, :FINISZ; |
| 4061 | |
| 4062 | FINSTO: SAD← L,TASK; |
| 4063 | FINST1: MD←SAD, :START; |
| 4064 | |
| 4065 | FINLOAD: NOP; |
| 4066 | LOADX: L← MD, TASK; |
| 4067 | LOADD: ACDEST← L, :START; |
| 4068 | |
| 4069 | FINISZ: L← MD+T; |
| 4070 | MAR← SAD, SH=0; |
| 4071 | SAD← L, :FINSTO; |
| 4072 | |
| 4073 | INCPC: MD← SAD; |
| 4074 | L← PC+1, TASK; |
| 4075 | PC← L, :START; |
| 4076 | |
| 4077 | ;DIVIDE. THIS DIVIDE IS IDENTICAL TO THE NOVA DIVIDE EXCEPT THAT |
| 4078 | ;IF THE DIVIDE CANNOT BE DONE, THE INSTRUCTION FAILS TO SKIP, OTHERWISE |
| 4079 | ;IT DOES. CARRY IS UNDISTURBED. |
| 4080 | |
| 4081 | !1,2,DODIV,NODIV; |
| 4082 | !1,2,DIVL,ENDDIV; |
| 4083 | !1,2,NOOVF,OVF; |
| 4084 | !1,2,DX0,DX1; |
| 4085 | !1,2,NOSUB,DOSUB; |
| 4086 | |
| 4087 | DIV: T← AC2; |
| 4088 | DIVX: L← AC0 - T; DO THE DIVIDE ONLY IF AC2>AC0 |
| 4089 | ALUCY, TASK, SAD← L, L← 0+1; |
| 4090 | :DODIV, SAD← L LSH 1; SAD← 2. COUNT THE LOOP BY SHIFTING |
| 4091 | |
| 4092 | NODIV: :FINBLT; ***X21 change. |
| 4093 | DODIV: L← AC0, :DIV1; |
| 4094 | |
| 4095 | DIVL: L← AC0; |
| 4096 | DIV1: SH<0, T← AC1; WILL THE LEFT SHIFT OF THE DIVIDEND OVERFLOW? |
| 4097 | :NOOVF, AC0← L MLSH 1, L← T← 0+T; L← AC1, T← 0 |
| 4098 | |
| 4099 | OVF: AC1← L LSH 1, L← 0+INCT, :NOV1; L← 1. SHIFT OVERFLOWED |
| 4100 | NOOVF: AC1← L LSH 1 , L← T; L← 0. SHIFT OK |
| 4101 | |
| 4102 | NOV1: T← AC2, SH=0; |
| 4103 | L← AC0-T, :DX0; |
| 4104 | |
| 4105 | DX1: ALUCY; DO THE TEST ONLY IF THE SHIFT DIDN'T OVERFLOW. IF |
| 4106 | ; IT DID, L IS STILL CORRECT, BUT THE TEST WOULD GO |
| 4107 | ; THE WRONG WAY. |
| 4108 | :NOSUB, T← AC1; |
| 4109 | |
| 4110 | DX0: :DOSUB, T← AC1; |
| 4111 | |
| 4112 | DOSUB: AC0← L, L← 0+INCT; DO THE SUBTRACT |
| 4113 | AC1← L; AND PUT A 1 IN THE QUOTIENT |
| 4114 | |
| 4115 | NOSUB: L← SAD, BUS=0, TASK; |
| 4116 | SAD← L LSH 1, :DIVL; |
| 4117 | |
| 4118 | ENDDIV: L← PC+1, TASK, :DOIT; ***X21 change. Skip if divide was done. |
| 4119 | |
| 4120 | |
| 4121 | ;MULTIPLY. THIS IS AN EXACT EMULATION OF NOVA HARDWARE MULTIPLY. |
| 4122 | ;AC2 IS THE MULTIPLIER, AC1 IS THE MULTIPLICAND. |
| 4123 | ;THE PRODUCT IS IN AC0 (HIGH PART), AND AC1 (LOW PART). |
| 4124 | ;PRECISELY: AC0,AC1 ← AC1*AC2 + AC0 |
| 4125 | |
| 4126 | !1,2,DOMUL,NOMUL; |
| 4127 | !1,2,MPYL,MPYA; |
| 4128 | !1,2,NOADDIER,ADDIER; |
| 4129 | !1,2,NOSPILL,SPILL; |
| 4130 | !1,2,NOADDX,ADDX; |
| 4131 | !1,2,NOSPILLX,SPILLX; |
| 4132 | |
| 4133 | |
| 4134 | MUL: L← AC2-1, BUS=0; |
| 4135 | MPYX: XREG←L,L← 0, :DOMUL; GET HERE WITH AC2-1 IN L. DON'T MUL IF AC2=0 |
| 4136 | DOMUL: TASK, L← -10+1; |
| 4137 | SAD← L; COUNT THE LOOP IN SAD |
| 4138 | |
| 4139 | MPYL: L← AC1, BUSODD; |
| 4140 | T← AC0, :NOADDIER; |
| 4141 | |
| 4142 | NOADDIER: AC1← L MRSH 1, L← T, T← 0, :NOSPILL; |
| 4143 | ADDIER: L← T← XREG+INCT; |
| 4144 | L← AC1, ALUCY, :NOADDIER; |
| 4145 | |
| 4146 | SPILL: T← ONE; |
| 4147 | NOSPILL: AC0← L MRSH 1; |
| 4148 | L← AC1, BUSODD; |
| 4149 | T← AC0, :NOADDX; |
| 4150 | |
| 4151 | NOADDX: AC1← L MRSH 1, L← T, T← 0, :NOSPILLX; |
| 4152 | ADDX: L← T← XREG+ INCT; |
| 4153 | L← AC1,ALUCY, :NOADDX; |
| 4154 | |
| 4155 | SPILLX: T← ONE; |
| 4156 | NOSPILLX: AC0← L MRSH 1; |
| 4157 | L← SAD+1, BUS=0, TASK; |
| 4158 | SAD← L, :MPYL; |
| 4159 | |
| 4160 | NOMUL: T← AC0; |
| 4161 | AC0← L, L← T, TASK; CLEAR AC0 |
| 4162 | AC1← L; AND REPLACE AC1 WITH AC0 |
| 4163 | MPYA: :FINBLT; ***X21 change. |
| 4164 | |
| 4165 | ;CYCLE AC0 LEFT BY DISP MOD 20B, UNLESS DISP=0, IN WHICH |
| 4166 | ;CASE CYCLE BY AC1 MOD 20B |
| 4167 | ;LEAVES AC1=CYCLE COUNT-1 MOD 20B |
| 4168 | |
| 4169 | $CYRET $R5; Shares space with SAD. |
| 4170 | $CYCOUT $R7; Shares space with XREG. |
| 4171 | |
| 4172 | !1,2,EMCYCX,ACCYCLE; |
| 4173 | !1,1,Y1; |
| 4174 | !1,1,Y2; |
| 4175 | !1,1,Y3; |
| 4176 | !1,1,Z1; |
| 4177 | !1,1,Z2; |
| 4178 | !1,1,Z3; |
| 4179 | |
| 4180 | EMCYCLE: L← DISP, SINK← X17, BUS=0; CONSTANT WITH BS=7 |
| 4181 | CYCP: T← AC0, :EMCYCX; |
| 4182 | |
| 4183 | ACCYCLE: T← AC1; |
| 4184 | L← 17 AND T, :CYCP; |
| 4185 | |
| 4186 | EMCYCX: CYCOUT←L, L←0, :RETCYCX; |
| 4187 | |
| 4188 | RAMCYCX: CYCOUT←L, L←0+1; |
| 4189 | |
| 4190 | RETCYCX: CYRET←L, L←0+T; |
| 4191 | SINK←CYCOUT, BUS; |
| 4192 | TASK, :L0; |
| 4193 | |
| 4194 | ;TABLE FOR CYCLE |
| 4195 | R4: CYCOUT← L MRSH 1; |
| 4196 | Y3: L← T← CYCOUT, TASK; |
| 4197 | R3X: CYCOUT← L MRSH 1; |
| 4198 | Y2: L← T← CYCOUT, TASK; |
| 4199 | R2X: CYCOUT← L MRSH 1; |
| 4200 | Y1: L← T← CYCOUT, TASK; |
| 4201 | R1X: CYCOUT← L MRSH 1, :ENDCYCLE; |
| 4202 | |
| 4203 | L4: CYCOUT← L MLSH 1; |
| 4204 | Z3: L← T← CYCOUT, TASK; |
| 4205 | L3: CYCOUT← L MLSH 1; |
| 4206 | Z2: L← T← CYCOUT, TASK; |
| 4207 | L2: CYCOUT← L MLSH 1; |
| 4208 | Z1: L← T← CYCOUT, TASK; |
| 4209 | L1: CYCOUT← L MLSH 1, :ENDCYCLE; |
| 4210 | L0: CYCOUT← L, :ENDCYCLE; |
| 4211 | |
| 4212 | L8: CYCOUT← L LCY 8, :ENDCYCLE; |
| 4213 | L7: CYCOUT← L LCY 8, :Y1; |
| 4214 | L6: CYCOUT← L LCY 8, :Y2; |
| 4215 | L5: CYCOUT← L LCY 8, :Y3; |
| 4216 | |
| 4217 | R7: CYCOUT← L LCY 8, :Z1; |
| 4218 | R6: CYCOUT← L LCY 8, :Z2; |
| 4219 | R5: CYCOUT← L LCY 8, :Z3; |
| 4220 | |
| 4221 | ENDCYCLE: SINK← CYRET, BUS, TASK; |
| 4222 | :EMCYCRET; |
| 4223 | |
| 4224 | EMCYCRET: L←CYCOUT, TASK, :LOADD; |
| 4225 | |
| 4226 | RAMCYCRET: T←PC, BUS, SWMODE, :TORAM; |
| 4227 | |
| 4228 | ; Scan convert instruction for characters. Takes DWAX (Destination |
| 4229 | ; word address)-NWRDS in AC0, and a pointer to a .AL-format font |
| 4230 | ; in AC3. AC2+displacement contains a pointer to a two-word block |
| 4231 | ; containing NWRDS and DBA (Destination Bit Address). |
| 4232 | |
| 4233 | $XH $R10; |
| 4234 | $DWAX $R35; |
| 4235 | $MASK $R36; |
| 4236 | |
| 4237 | !1,2,HDLOOP,HDEXIT; |
| 4238 | !1,2,MERGE,STORE; |
| 4239 | !1,2,NFIN,FIN; |
| 4240 | !17,2,DOBOTH,MOVELOOP; |
| 4241 | |
| 4242 | CONVERT: MAR←XREG+1; Got here via indirect mechanism which |
| 4243 | ; left first arg in SAD, its address in XREG. |
| 4244 | T←17; |
| 4245 | L←MD AND T; |
| 4246 | |
| 4247 | T←MAR←AC3; |
| 4248 | AC1←L; AC1←DBA |
| 4249 | L←MD+T, TASK; |
| 4250 | AC3←L; AC3←Character descriptor block address(Char) |
| 4251 | |
| 4252 | MAR←AC3+1; |
| 4253 | T←177400; |
| 4254 | IR←L←MD AND T; IR←XH |
| 4255 | XH←L LCY 8, :ODDCX; XH register temporarily contains HD |
| 4256 | ODDCX: L←AC0, :HDENTER; |
| 4257 | |
| 4258 | HDLOOP: T←SAD; (really NWRDS) |
| 4259 | L←DWAX+T; |
| 4260 | |
| 4261 | HDENTER: DWAX←L; DWAX ← AC0+HD*NWRDS |
| 4262 | L←XH-1, BUS=0, TASK; |
| 4263 | XH←L, :HDLOOP; |
| 4264 | |
| 4265 | HDEXIT: T←MASKTAB; |
| 4266 | MAR←T←AC1+T; Fetch the mask. |
| 4267 | L←DISP; |
| 4268 | XH←L; XH register now contains XH |
| 4269 | L←MD; |
| 4270 | MASK←L, L←0+T+1, TASK; |
| 4271 | AC1←L; ***X21. AC1 ← (DBA)+1 |
| 4272 | |
| 4273 | L←5; ***X21. Calling conventions changed. |
| 4274 | IR←SAD, TASK; |
| 4275 | CYRET←L, :MOVELOOP; CYRET←CALL5 |
| 4276 | |
| 4277 | MOVELOOP: L←T←XH-1, BUS=0; |
| 4278 | MAR←AC3-T-1, :NFIN; Fetch next source word |
| 4279 | NFIN: XH←L; |
| 4280 | T←DISP; (really NWRDS) |
| 4281 | L←DWAX+T; Update destination address |
| 4282 | T←MD; |
| 4283 | SINK←AC1, BUS; |
| 4284 | DWAX←L, L←T, TASK, :L0; Call Cycle subroutine |
| 4285 | |
| 4286 | CONVCYCRET: MAR←DWAX; |
| 4287 | T←MASK, BUS=0; |
| 4288 | T←CYCOUT.T, :MERGE; Data for first word. If MASK=0 |
| 4289 | ; then store the word rather than |
| 4290 | ; merging, and do not disturb the |
| 4291 | ; second word. |
| 4292 | MERGE: L←XREG AND NOT T; Data for second word. |
| 4293 | T←MD OR T; First word now merged, |
| 4294 | XREG←L, L←T; |
| 4295 | MTEMP←L; |
| 4296 | MAR←DWAX; restore it. |
| 4297 | SINK←XREG, BUS=0, TASK; |
| 4298 | MD←MTEMP, :DOBOTH; XREG=0 means only one word |
| 4299 | ; is involved. |
| 4300 | |
| 4301 | DOBOTH: MAR←DWAX+1; |
| 4302 | T←XREG; |
| 4303 | L←MD OR T; |
| 4304 | MAR←DWAX+1; |
| 4305 | XREG←L, TASK; ***X21. TASK added. |
| 4306 | STORE: MD←XREG, :MOVELOOP; |
| 4307 | |
| 4308 | FIN: L←AC1-1; ***X21. Return AC1 to DBA. |
| 4309 | AC1←L; *** ... bletch ... |
| 4310 | IR←SH3CONST; |
| 4311 | L←MD, TASK, :SH1; |
| 4312 | |
| 4313 | ;RCLK - 61003 - Read the Real Time Clock into AC0,AC1 |
| 4314 | RCLK: MAR← CLOCKLOC; |
| 4315 | L← R37; |
| 4316 | AC1← L, :LOADX; |
| 4317 | |
| 4318 | ;SIO - 61004 - Put AC0 on the bus, issue STARTF to get device attention, |
| 4319 | ;Read Host address from Ethernet interface into AC0. |
| 4320 | SIO: L← AC0, STARTF; |
| 4321 | T← 77777; ***X21 sets AC0[0] to 0 |
| 4322 | L← RSNF AND T; |
| 4323 | LTOAC0: AC0← L, TASK, :TOSTART; |
| 4324 | |
| 4325 | ;EngNumber is a constant returned by VERS that contains a discription |
| 4326 | ;of the Alto and it's Microcode. The composition of EngNumber is: |
| 4327 | ; bits 0-3 Alto engineering number |
| 4328 | ; bits 4-7 Alto build |
| 4329 | ; bits 8-15 Version number of Microcode |
| 4330 | ;Use of the Alto Build number has been abandoned. |
| 4331 | ;the engineering number (EngNumber) is in the MRT files because it |
| 4332 | ; it different for Altos with and without Extended memory. |
| 4333 | VERS: T← EngNumber; ***V3 change |
| 4334 | L← 3+T, :LTOAC0; ***V3 change |
| 4335 | |
| 4336 | ;XMLDA - Extended Memory Load Accumulator. |
| 4337 | ; AC0 ← @AC1 in the alternate bank |
| 4338 | XMLDA: XMAR← AC1, :FINLOAD; ***V3 change |
| 4339 | |
| 4340 | ;XMSTA - Extended Memory Store Accumulator |
| 4341 | ; @AC1 ← AC0 in the alternate bank |
| 4342 | XMSTA: XMAR← AC1, :XSTA1; ***V3 change |
| 4343 | |
| 4344 | ;BLT - 61005 - Block Transfer |
| 4345 | ;BLKS - 61006 - Block Store |
| 4346 | ; Accepts in |
| 4347 | ; AC0/ BLT: Address of first word of source block-1 |
| 4348 | ; BLKS: Data to be stored |
| 4349 | ; AC1/ Address of last word of destination block |
| 4350 | ; AC3/ NEGATIVE word count |
| 4351 | ; Leaves |
| 4352 | ; AC0/ BLT: Address of last word of source block+1 |
| 4353 | ; BLKS: Unchanged |
| 4354 | ; AC1/ Unchanged |
| 4355 | ; AC2/ Unchanged |
| 4356 | ; AC3/ 0 |
| 4357 | ; These instructions are interruptable. If an interrupt occurs, |
| 4358 | ; the PC is decremented by one, and the ACs contain the intermediate |
| 4359 | ; so the instruction can be restarted when the interrupt is dismissed. |
| 4360 | |
| 4361 | !1,2,PERHAPS, NO; |
| 4362 | |
| 4363 | BLT: L← MAR← AC0+1; |
| 4364 | AC0← L; |
| 4365 | L← MD, :BLKSA; |
| 4366 | |
| 4367 | BLKS: L← AC0; |
| 4368 | BLKSA: T← AC3+1, BUS=0; |
| 4369 | MAR← AC1+T, :MOREBLT; |
| 4370 | |
| 4371 | MOREBLT: XREG← L, L← T; |
| 4372 | AC3← L, TASK; |
| 4373 | MD← XREG; STORE |
| 4374 | L← NWW, BUS=0; CHECK FOR INTERRUPT |
| 4375 | SH<0, :PERHAPS, L← PC-1; Prepare to back up PC. |
| 4376 | |
| 4377 | NO: SINK← DISP, SINK← M7, BUS, :DISABLED; |
| 4378 | |
| 4379 | PERHAPS: SINK← DISP, SINK← M7, BUS, :DOIT; |
| 4380 | |
| 4381 | DOIT: PC←L, :FINBLT; ***X21. Reset PC, terminate instruction. |
| 4382 | |
| 4383 | DISABLED: :DIR; GOES TO BLT OR BLKS |
| 4384 | |
| 4385 | FINBLT: T←777; ***X21. PC in [177000-177777] means Ram return |
| 4386 | L←PC+T+1; |
| 4387 | L←PC AND T, TASK, ALUCY; |
| 4388 | TOSTART: XREG←L, :START; |
| 4389 | |
| 4390 | RAMRET: T←XREG, BUS, SWMODE; |
| 4391 | TORAM: :NOVEM; |
| 4392 | |
| 4393 | ;PARAMETERLESS INSTRUCTIONS FOR DIDDLING THE WCS. |
| 4394 | |
| 4395 | ;JMPRAM - 61010 - JUMP TO THE RAM ADDRESS SPECIFIED BY AC1 |
| 4396 | JMPR: T←AC1, BUS, SWMODE, :TORAM; |
| 4397 | |
| 4398 | |
| 4399 | ;RDRAM - 61011 - READ THE RAM WORD ADDRESSED BY AC1 INTO AC0 |
| 4400 | RDRM: T← AC1, RDRAM; |
| 4401 | L← ALLONES, TASK, :LOADD; |
| 4402 | |
| 4403 | |
| 4404 | ;WRTRAM - 61012 - WRITE AC0,AC3 INTO THE RAM LOCATION ADDRESSED BY AC1 |
| 4405 | WTRM: T← AC1; |
| 4406 | L← AC0, WRTRAM; |
| 4407 | L← AC3, :FINBLT; |
| 4408 | |
| 4409 | ;DOUBLE WORD INSTRUCTIONS |
| 4410 | |
| 4411 | ;DREAD - 61015 |
| 4412 | ; AC0← rv(AC3); AC1← rv(AC3 xor 1) |
| 4413 | |
| 4414 | DREAD: MAR← AC3; START MEMORY CYCLE |
| 4415 | NOP; DELAY |
| 4416 | DREAD1: L← MD; FIRST READ |
| 4417 | T←MD; SECOND READ |
| 4418 | AC0← L, L←T, TASK; STORE MSW |
| 4419 | AC1← L, :START; STORE LSW |
| 4420 | |
| 4421 | |
| 4422 | ;DWRITE - 61016 |
| 4423 | ; rv(AC3)← AC0; rv(AC3 xor 1)← AC1 |
| 4424 | |
| 4425 | DWRITE: MAR← AC3; START MEMORY CYCLE |
| 4426 | NOP; DELAY |
| 4427 | MD← AC0, TASK; FIRST WRITE |
| 4428 | MD← AC1, :START; SECOND WRITE |
| 4429 | |
| 4430 | |
| 4431 | ;DEXCH - 61017 |
| 4432 | ; t← rv(AC3); rv(AC3)← AC0; AC0← t |
| 4433 | ; t← rv(AC3 xor 1); rv(AC3 xor 1)← AC1; AC1← t |
| 4434 | |
| 4435 | DEXCH: MAR← AC3; START MEMORY CYCLE |
| 4436 | NOP; DELAY |
| 4437 | MD← AC0; FIRST WRITE |
| 4438 | MD← AC1,:DREAD1; SECOND WRITE, GO TO READ |
| 4439 | |
| 4440 | |
| 4441 | ;DIOGNOSE INSTRUCTIONS |
| 4442 | |
| 4443 | ;DIOG1 - 61022 |
| 4444 | ; Hamming Code← AC2 |
| 4445 | ; rv(AC3)← AC0; rv(AC3 xor 1)← AC1 |
| 4446 | |
| 4447 | DIOG1: MAR← ERRCTRL; START WRITE TO ERROR CONTROL |
| 4448 | NOP; DELAY |
| 4449 | MD← AC2,:DWRITE; WRITE HAMMING CODE, GO TO DWRITE |
| 4450 | |
| 4451 | ;DIOG2 - 61023 |
| 4452 | ; rv(AC3)← AC0 |
| 4453 | ; rv(AC3)← AC0 xor AC1 |
| 4454 | |
| 4455 | DIOG2: MAR← AC3; START MEMORY CYCLE |
| 4456 | T← AC0; SETUP FOR XOR |
| 4457 | L← AC1 XORT; DO XOR |
| 4458 | MD← AC0; FIRST WRITE |
| 4459 | MAR← AC3; START MEMORY CYCLE |
| 4460 | AC0← L, TASK; STORE XOR WORD |
| 4461 | MD← AC0, :START; SECOND WRITE |
| 4462 | |
| 4463 | ;INTERRUPT SYSTEM. TIMING IS 0 CYCLES IF DISABLED, 18 CYCLES |
| 4464 | ;IF THE INTERRUPTING CHANEL IS INACTIVE, AND 36+6N CYCLES TO CAUSE |
| 4465 | ;AN INTERRUPT ON CHANNEL N |
| 4466 | |
| 4467 | INTCODE:PC← L, IR← 0; |
| 4468 | T← NWW; |
| 4469 | T← MD OR T; |
| 4470 | L← MD AND T; |
| 4471 | SAD← L, L← T, SH=0; SAD HAD POTENTIAL INTERRUPTS |
| 4472 | NWW← L, L←0+1, :SOMEACTIVE; NWW HAS NEW WW |
| 4473 | |
| 4474 | NOACTIVE: MAR← WWLOC; RESTORE WW TO CORE |
| 4475 | L← SAD; AND REPLACE IT WITH SAD IN NWW |
| 4476 | MD← NWW, TASK; |
| 4477 | INTZ: NWW← L, :START; |
| 4478 | |
| 4479 | SOMEACTIVE: MAR← PCLOC; STORE PC AND SET UP TO FIND HIGHEST PRIORITY REQUEST |
| 4480 | XREG← L, L← 0; |
| 4481 | MD← PC, TASK; |
| 4482 | |
| 4483 | ILPA: PC← L; |
| 4484 | ILP: T← SAD; |
| 4485 | L← T← XREG AND T; |
| 4486 | SH=0, L← T, T← PC; |
| 4487 | :IEXIT, XREG← L LSH 1; |
| 4488 | |
| 4489 | NIEXIT: L← 0+T+1, TASK, :ILPA; |
| 4490 | IEXIT: MAR← PCLOC+T+1; FETCH NEW PC. T HAS CHANNEL #, L HAS MASK |
| 4491 | |
| 4492 | XREG← L; |
| 4493 | T← XREG; |
| 4494 | L← NWW XOR T; TURN OFF BIT IN WW FOR INTERRUPT ABOUT TO HAPPEN |
| 4495 | T← MD; |
| 4496 | NWW← L, L← T; |
| 4497 | PC← L, L← T← 0+1, TASK; |
| 4498 | SAD← L MRSH 1, :NOACTIVE; SAD← 1B5 TO DISABLE INTERRUPTS |
| 4499 | |
| 4500 | ; |
| 4501 | ; ************************ |
| 4502 | ; * BIT-BLT - 61024 * |
| 4503 | ; ************************ |
| 4504 | ; Modified September 1977 to support Alternate memory banks |
| 4505 | ; Last modified Sept 6, 1977 by Dan Ingalls |
| 4506 | ; |
| 4507 | ; /* NOVA REGS |
| 4508 | ; AC2 -> BLT DESCRIPTOR TABLE, AND IS PRESERVED |
| 4509 | ; AC1 CARRIES LINE COUNT FOR RESUMING AFTER AN |
| 4510 | ; INTERRUPT. MUST BE 0 AT INITIAL CALL |
| 4511 | ; AC0 AND AC3 ARE SMASHED TO SAVE S-REGS |
| 4512 | ; |
| 4513 | ; /* ALTO REGISTER USAGE |
| 4514 | ;DISP CARRIES: TOPLD(100), SOURCEBANK(40), DESTBANK(20), |
| 4515 | ; SOURCE(14), OP(3) |
| 4516 | $MASK1 $R0; |
| 4517 | $YMUL $R2; HAS TO BE AN R-REG FOR SHIFTS |
| 4518 | $RETN $R2; |
| 4519 | $SKEW $R3; |
| 4520 | $TEMP $R5; |
| 4521 | $WIDTH $R7; |
| 4522 | $PLIER $R7; HAS TO BE AN R-REG FOR SHIFTS |
| 4523 | $DESTY $R10; |
| 4524 | $WORD2 $R10; |
| 4525 | $STARTBITSM1 $R35; |
| 4526 | $SWA $R36; |
| 4527 | $DESTX $R36; |
| 4528 | $LREG $R40; HAS TO BE R40 (COPY OF L-REG) |
| 4529 | $NLINES $R41; |
| 4530 | $RAST1 $R42; |
| 4531 | $SRCX $R43; |
| 4532 | $SKMSK $R43; |
| 4533 | $SRCY $R44; |
| 4534 | $RAST2 $R44; |
| 4535 | $CONST $R45; |
| 4536 | $TWICE $R45; |
| 4537 | $HCNT $R46; |
| 4538 | $VINC $R46; |
| 4539 | $HINC $R47; |
| 4540 | $NWORDS $R50; |
| 4541 | $MASK2 $R51; WAS $R46; |
| 4542 | ; |
| 4543 | $LASTMASKP1 $500; MASKTABLE+021 |
| 4544 | $170000 $170000; |
| 4545 | $CALL3 $3; SUBROUTINE CALL INDICES |
| 4546 | $CALL4 $4; |
| 4547 | $DWAOFF $2; BLT TABLE OFFSETS |
| 4548 | $DXOFF $4; |
| 4549 | $DWOFF $6; |
| 4550 | $DHOFF $7; |
| 4551 | $SWAOFF $10; |
| 4552 | $SXOFF $12; |
| 4553 | $GRAYOFF $14; GRAY IN WORDS 14-17 |
| 4554 | $LASTMASK $477; MASKTABLE+020 **NOT IN EARLIER PROMS! |
| 4555 | |
| 4556 | |
| 4557 | ; BITBLT SETUP - CALCULATE RAM STATE FROM AC2'S TABLE |
| 4558 | ;---------------------------------------------------------- |
| 4559 | ; |
| 4560 | ; /* FETCH COORDINATES FROM TABLE |
| 4561 | !1,2,FDDX,BLITX; |
| 4562 | !1,2,FDBL,BBNORAM; |
| 4563 | !17,20,FDBX,,,,FDX,,FDW,,,,FSX,,,,,; FDBL RETURNS (BASED ON OFFSET) |
| 4564 | ; (0) 4 6 12 |
| 4565 | BITBLT: L← 0; |
| 4566 | SINK←LREG, BUSODD; SINK← -1 IFF NO RAM |
| 4567 | L← T← DWOFF, :FDBL; |
| 4568 | BBNORAM: TASK, :NPTRAP; TRAP IF NO RAM |
| 4569 | ; |
| 4570 | FDW: T← MD; PICK UP WIDTH, HEIGHT |
| 4571 | WIDTH← L, L← T, TASK, :NZWID; |
| 4572 | NZWID: NLINES← L; |
| 4573 | T← AC1; |
| 4574 | L← NLINES-T; |
| 4575 | NLINES← L, SH<0, TASK; |
| 4576 | :FDDX; |
| 4577 | ; |
| 4578 | FDDX: L← T← DXOFF, :FDBL; PICK UP DEST X AND Y |
| 4579 | FDX: T← MD; |
| 4580 | DESTX← L, L← T, TASK; |
| 4581 | DESTY← L; |
| 4582 | ; |
| 4583 | L← T← SXOFF, :FDBL; PICK UP SOURCE X AND Y |
| 4584 | FSX: T← MD; |
| 4585 | SRCX← L, L← T, TASK; |
| 4586 | SRCY← L, :CSHI; |
| 4587 | ; |
| 4588 | ; /* FETCH DOUBLEWORD FROM TABLE (L← T← OFFSET, :FDBL) |
| 4589 | FDBL: MAR← AC2+T; |
| 4590 | SINK← LREG, BUS; |
| 4591 | FDBX: L← MD, :FDBX; |
| 4592 | ; |
| 4593 | ; /* CALCULATE SKEW AND HINC |
| 4594 | !1,2,LTOR,RTOL; |
| 4595 | CSHI: T← DESTX; |
| 4596 | L← SRCX-T-1; |
| 4597 | T← LREG+1, SH<0; TEST HORIZONTAL DIRECTION |
| 4598 | L← 17.T, :LTOR; SKEW ← (SRCX - DESTX) MOD 16 |
| 4599 | RTOL: SKEW← L, L← 0-1, :AH, TASK; HINC ← -1 |
| 4600 | LTOR: SKEW← L, L← 0+1, :AH, TASK; HINC ← +1 |
| 4601 | AH: HINC← L; |
| 4602 | ; |
| 4603 | ; CALCULATE MASK1 AND MASK2 |
| 4604 | !1,2,IFRTOL,LNWORDS; |
| 4605 | !1,2,POSWID,NEGWID; |
| 4606 | CMASKS: T← DESTX; |
| 4607 | T← 17.T; |
| 4608 | MAR← LASTMASKP1-T-1; |
| 4609 | L← 17-T; STARTBITS ← 16 - (DESTX.17) |
| 4610 | STARTBITSM1← L; |
| 4611 | L← MD, TASK; |
| 4612 | MASK1← L; MASK1 ← @(MASKLOC+STARTBITS) |
| 4613 | L← WIDTH-1; |
| 4614 | T← LREG-1, SH<0; |
| 4615 | T← DESTX+T+1, :POSWID; |
| 4616 | POSWID: T← 17.T; |
| 4617 | MAR← LASTMASK-T-1; |
| 4618 | T← ALLONES; MASK2 ← NOT |
| 4619 | L← HINC-1; |
| 4620 | L← MD XOR T, SH=0, TASK; @(MASKLOC+(15-((DESTX+WIDTH-1).17))) |
| 4621 | MASK2← L, :IFRTOL; |
| 4622 | ; /* IF RIGHT TO LEFT, ADD WIDTH TO X'S AND EXCH MASK1, MASK2 |
| 4623 | IFRTOL: T← WIDTH-1; WIDTH-1 |
| 4624 | L← SRCX+T; |
| 4625 | SRCX← L; SRCX ← SCRX + (WIDTH-1) |
| 4626 | L← DESTX+T; |
| 4627 | DESTX← L; DESTX ← DESTX + (WIDTH-1) |
| 4628 | T← DESTX; |
| 4629 | L← 17.T, TASK; |
| 4630 | STARTBITSM1← L; STARTBITS ← (DESTX.17) + 1 |
| 4631 | T← MASK1; |
| 4632 | L← MASK2; |
| 4633 | MASK1← L, L← T,TASK; EXCHANGE MASK1 AND MASK2 |
| 4634 | MASK2←L; |
| 4635 | ; |
| 4636 | ; /* CALCULATE NWORDS |
| 4637 | !1,2,LNW1,THIN; |
| 4638 | LNWORDS:T← STARTBITSM1+1; |
| 4639 | L← WIDTH-T-1; |
| 4640 | T← 177760, SH<0; |
| 4641 | T← LREG.T, :LNW1; |
| 4642 | LNW1: L← CALL4; NWORDS ← (WIDTH-STARTBITS)/16 |
| 4643 | CYRET← L, L← T, :R4, TASK; CYRET←CALL4 |
| 4644 | ; **WIDTH REG NOW FREE** |
| 4645 | CYX4: L← CYCOUT, :LNW2; |
| 4646 | THIN: T← MASK1; SPECIAL CASE OF THIN SLICE |
| 4647 | L←MASK2.T; |
| 4648 | MASK1← L, L← 0-1; MASK1 ← MASK1.MASK2, NWORDS ← -1 |
| 4649 | LNW2: NWORDS← L; LOAD NWORDS |
| 4650 | ; **STARTBITSM1 REG NOW FREE** |
| 4651 | ; |
| 4652 | ; /* DETERMINE VERTICAL DIRECTION |
| 4653 | !1,2,BTOT,TTOB; |
| 4654 | T← SRCY; |
| 4655 | L← DESTY-T; |
| 4656 | T← NLINES-1, SH<0; |
| 4657 | L← 0, :BTOT; VINC ← 0 IFF TOP-TO-BOTTOM |
| 4658 | BTOT: L← ALLONES; ELSE -1 |
| 4659 | BTOT1: VINC← L; |
| 4660 | L← SRCY+T; GOING BOTTOM TO TOP |
| 4661 | SRCY← L; ADD NLINES TO STARTING Y'S |
| 4662 | L← DESTY+T; |
| 4663 | DESTY← L, L← 0+1, TASK; |
| 4664 | TWICE←L, :CWA; |
| 4665 | ; |
| 4666 | TTOB: T← AC1, :BTOT1; TOP TO BOT, ADD NDONE TO STARTING Y'S |
| 4667 | ; **AC1 REG NOW FREE**; |
| 4668 | ; |
| 4669 | ; /* CALCULATE WORD ADDRESSES - DO ONCE FOR SWA, THEN FOR DWAX |
| 4670 | CWA: L← SRCY; Y HAS TO GO INTO AN R-REG FOR SHIFTING |
| 4671 | YMUL← L; |
| 4672 | T← SWAOFF; FIRST TIME IS FOR SWA, SRCX |
| 4673 | L← SRCX; |
| 4674 | ; **SRCX, SRCY REG NOW FREE** |
| 4675 | DOSWA: MAR← AC2+T; FETCH BITMAP ADDR AND RASTER |
| 4676 | XREG← L; |
| 4677 | L←CALL3; |
| 4678 | CYRET← L; CYRET←CALL3 |
| 4679 | L← MD; |
| 4680 | T← MD; |
| 4681 | DWAX← L, L←T, TASK; |
| 4682 | RAST2← L; |
| 4683 | T← 177760; |
| 4684 | L← T← XREG.T, :R4, TASK; SWA ← SWA + SRCX/16 |
| 4685 | CYX3: T← CYCOUT; |
| 4686 | L← DWAX+T; |
| 4687 | DWAX← L; |
| 4688 | ; |
| 4689 | !1,2,NOADD,DOADD; |
| 4690 | !1,2,MULLP,CDELT; SWA ← SWA + SRCY*RAST1 |
| 4691 | L← RAST2; |
| 4692 | SINK← YMUL, BUS=0, TASK; NO MULT IF STARTING Y=0 |
| 4693 | PLIER← L, :MULLP; |
| 4694 | MULLP: L← PLIER, BUSODD; MULTIPLY RASTER BY Y |
| 4695 | PLIER← L RSH 1, :NOADD; |
| 4696 | NOADD: L← YMUL, SH=0, TASK; TEST NO MORE MULTIPLIER BITS |
| 4697 | SHIFTB: YMUL← L LSH 1, :MULLP; |
| 4698 | DOADD: T← YMUL; |
| 4699 | L← DWAX+T; |
| 4700 | DWAX← L, L←T, :SHIFTB, TASK; |
| 4701 | ; **PLIER, YMUL REG NOW FREE** |
| 4702 | ; |
| 4703 | !1,2,HNEG,HPOS; |
| 4704 | !1,2,VPOS,VNEG; |
| 4705 | !1,1,CD1; CALCULATE DELTAS = +-(NWORDS+2)[HINC] +-RASTER[VINC] |
| 4706 | CDELT: L← T← HINC-1; (NOTE T← -2 OR 0) |
| 4707 | L← T← NWORDS-T, SH=0; (L←NWORDS+2 OR T←NWORDS) |
| 4708 | CD1: SINK← VINC, BUSODD, :HNEG; |
| 4709 | HNEG: T← RAST2, :VPOS; |
| 4710 | HPOS: L← -2-T, :CD1; (MAKES L←-(NWORDS+2)) |
| 4711 | VPOS: L← LREG+T, :GDELT, TASK; BY NOW, LREG = +-(NWORDS+2) |
| 4712 | VNEG: L← LREG-T, :GDELT, TASK; AND T = RASTER |
| 4713 | GDELT: RAST2← L; |
| 4714 | ; |
| 4715 | ; /* END WORD ADDR LOOP |
| 4716 | !1,2,ONEMORE,CTOPL; |
| 4717 | L← TWICE-1; |
| 4718 | TWICE← L, SH<0; |
| 4719 | L← RAST2, :ONEMORE; USE RAST2 2ND TIME THRU |
| 4720 | ONEMORE: RAST1← L; |
| 4721 | L← DESTY, TASK; USE DESTY 2ND TIME THRU |
| 4722 | YMUL← L; |
| 4723 | L← DWAX; USE DWAX 2ND TIME THRU |
| 4724 | T← DESTX; CAREFUL - DESTX=SWA!! |
| 4725 | SWA← L, L← T; USE DESTX 2ND TIME THRU |
| 4726 | T← DWAOFF, :DOSWA; AND DO IT AGAIN FOR DWAX, DESTX |
| 4727 | ; **TWICE, VINC REGS NOW FREE** |
| 4728 | ; |
| 4729 | ; /* CALCULATE TOPLD |
| 4730 | !1,2,CTOP1,CSKEW; |
| 4731 | !1,2,HM1,H1; |
| 4732 | !1,2,NOTOPL,TOPL; |
| 4733 | CTOPL: L← SKEW, BUS=0, TASK; IF SKEW=0 THEN 0, ELSE |
| 4734 | CTX: IR← 0, :CTOP1; |
| 4735 | CTOP1: T← SRCX; (SKEW GR SRCX.17) XOR (HINC EQ 0) |
| 4736 | L← HINC-1; |
| 4737 | T← 17.T, SH=0; TEST HINC |
| 4738 | L← SKEW-T-1, :HM1; |
| 4739 | H1: T← HINC, SH<0; |
| 4740 | L← SWA+T, :NOTOPL; |
| 4741 | HM1: T← LREG; IF HINC=-1, THEN FLIP |
| 4742 | L← 0-T-1, :H1; THE POLARITY OF THE TEST |
| 4743 | NOTOPL: SINK← HINC, BUSODD, TASK, :CTX; HINC FORCES BUSODD |
| 4744 | TOPL: SWA← L, TASK; (DISP ← 100 FOR TOPLD) |
| 4745 | IR← 100, :CSKEW; |
| 4746 | ; **HINC REG NOW FREE** |
| 4747 | ; |
| 4748 | ; /* CALCULATE SKEW MASK |
| 4749 | !1,2,THINC,BCOM1; |
| 4750 | !1,2,COMSK,NOCOM; |
| 4751 | CSKEW: T← SKEW, BUS=0; IF SKEW=0, THEN COMP |
| 4752 | MAR← LASTMASKP1-T-1, :THINC; |
| 4753 | THINC: L←HINC-1; |
| 4754 | SH=0; IF HINC=-1, THEN COMP |
| 4755 | BCOM1: T← ALLONES, :COMSK; |
| 4756 | COMSK: L← MD XOR T, :GFN; |
| 4757 | NOCOM: L← MD, :GFN; |
| 4758 | ; |
| 4759 | ; /* GET FUNCTION |
| 4760 | GFN: MAR← AC2; |
| 4761 | SKMSK← L; |
| 4762 | |
| 4763 | T← MD; |
| 4764 | L← DISP+T, TASK; |
| 4765 | IR← LREG, :BENTR; DISP ← DISP .OR. FUNCTION |
| 4766 | |
| 4767 | ; BITBLT WORK - VERT AND HORIZ LOOPS WITH 4 SOURCES, 4 FUNCTIONS |
| 4768 | ;----------------------------------------------------------------------- |
| 4769 | ; |
| 4770 | ; /* VERTICAL LOOP: UPDATE SWA, DWAX |
| 4771 | !1,2,DO0,VLOOP; |
| 4772 | VLOOP: T← SWA; |
| 4773 | L← RAST1+T; INC SWA BY DELTA |
| 4774 | SWA← L; |
| 4775 | T← DWAX; |
| 4776 | L← RAST2+T, TASK; INC DWAX BY DELTA |
| 4777 | DWAX← L; |
| 4778 | ; |
| 4779 | ; /* TEST FOR DONE, OR NEED GRAY |
| 4780 | !1,2,MOREV,DONEV; |
| 4781 | !1,2,BMAYBE,BNOINT; |
| 4782 | !1,2,BDOINT,BDIS0; |
| 4783 | !1,2,DOGRAY,NOGRAY; |
| 4784 | BENTR: L← T← NLINES-1; DECR NLINES AND CHECK IF DONE |
| 4785 | NLINES← L, SH<0; |
| 4786 | L← NWW, BUS=0, :MOREV; CHECK FOR INTERRUPTS |
| 4787 | MOREV: L← 3.T, :BMAYBE, SH<0; CHECK DISABLED ***V3 change |
| 4788 | BNOINT: SINK← DISP, SINK← lgm10, BUS=0, :BDIS0, TASK; |
| 4789 | BMAYBE: SINK← DISP, SINK← lgm10, BUS=0, :BDOINT, TASK; TEST IF NEED GRAY(FUNC=8,12) |
| 4790 | BDIS0: CONST← L, :DOGRAY; ***V3 change |
| 4791 | ; |
| 4792 | ; /* INTERRUPT SUSPENSION (POSSIBLY) |
| 4793 | !1,1,DOI1; MAY GET AN OR-1 |
| 4794 | BDOINT: :DOI1; TASK HERE |
| 4795 | DOI1: T← AC2; |
| 4796 | MAR← DHOFF+T; NLINES DONE = HT-NLINES-1 |
| 4797 | T← NLINES; |
| 4798 | L← PC-1; BACK UP THE PC, SO WE GET RESTARTED |
| 4799 | PC← L; |
| 4800 | L← MD-T-1, :BLITX, TASK; ...WITH NO LINES DONE IN AC1 |
| 4801 | ; |
| 4802 | ; /* LOAD GRAY FOR THIS LINE (IF FUNCTION NEEDS IT) |
| 4803 | !1,2,PRELD,NOPLD; |
| 4804 | DOGRAY: T← CONST-1; |
| 4805 | T← GRAYOFF+T+1; |
| 4806 | MAR← AC2+T; |
| 4807 | NOP; UGH |
| 4808 | L← MD; |
| 4809 | NOGRAY: SINK← DISP, SINK← lgm100, BUS=0, TASK; TEST TOPLD |
| 4810 | CONST← L, :PRELD; |
| 4811 | ; |
| 4812 | ; /* NORMAL COMPLETION |
| 4813 | NEGWID: L← 0, :BLITX, TASK; |
| 4814 | DONEV: L← 0, :BLITX, TASK; MAY BE AN OR-1 HERE! |
| 4815 | BLITX: AC1← L, :FINBLT; |
| 4816 | ; |
| 4817 | ; /* PRELOAD OF FIRST SOURCE WORD (DEPENDING ON ALIGNMENT) |
| 4818 | !1,2,AB1,NB1; |
| 4819 | PRELD: SINK← DISP, SINK← lgm40, BUS=0; WHICH BANK |
| 4820 | T← HINC, :AB1; |
| 4821 | NB1: MAR← SWA-T, :XB1; (NORMAL BANK) |
| 4822 | AB1: XMAR← SWA-T, :XB1; (ALTERNATE BANK) |
| 4823 | XB1: NOP; |
| 4824 | L← MD, TASK; |
| 4825 | WORD2← L, :NOPLD; |
| 4826 | ; |
| 4827 | ; |
| 4828 | ; /* HORIZONTAL LOOP - 3 CALLS FOR 1ST, MIDDLE AND LAST WORDS |
| 4829 | !1,2,FDISPA,LASTH; |
| 4830 | %17,17,14,DON0,,DON2,DON3; CALLERS OF HORIZ LOOP |
| 4831 | ; NOTE THIS IGNORES 14-BITS, SO lgm14 WORKS LIKE L←0 FOR RETN |
| 4832 | !14,1,LH1; IGNORE RESULTING BUS |
| 4833 | NOPLD: L← 3, :FDISP; CALL #3 IS FIRST WORD |
| 4834 | DON3: L← NWORDS; |
| 4835 | HCNT← L, SH<0; HCNT COUNTS WHOLE WORDS |
| 4836 | DON0: L← HCNT-1, :DO0; IF NEG, THEN NO MIDDLE OR LAST |
| 4837 | DO0: HCNT← L, SH<0; CALL #0 (OR-14!) IS MIDDLE WORDS |
| 4838 | ; UGLY HACK SQUEEZES 2 INSTRS OUT OF INNER LOOP: |
| 4839 | L← DISP, SINK← lgm14, BUS, TASK, :FDISPA; (WORKS LIKE L←0) |
| 4840 | LASTH: :LH1; TASK AND BUS PENDING |
| 4841 | LH1: L← 2, :FDISP; CALL #2 IS LAST WORD |
| 4842 | DON2: :VLOOP; |
| 4843 | ; |
| 4844 | ; |
| 4845 | ; /* HERE ARE THE SOURCE FUNCTIONS |
| 4846 | !17,20,,,,F0,,,,F1,,,,F2,,,,F3; IGNORE OP BITS IN FUNCTION CODE |
| 4847 | !17,20,,,,F0A,,,,F1A,,,,F2A,,,, ; SAME FOR WINDOW RETURNS |
| 4848 | !3,4,OP0,OP1,OP2,OP3; |
| 4849 | !1,2,AB2,NB2; |
| 4850 | FDISP: SINK← DISP, SINK←lgm14, BUS, TASK; |
| 4851 | FDISPA: RETN← L, :F0; |
| 4852 | F0: SINK← DISP, SINK← lgm40, BUS=0, :WIND; FUNC 0 - WINDOW |
| 4853 | F1: SINK← DISP, SINK← lgm40, BUS=0, :WIND; FUNC 1 - NOT WINDOW |
| 4854 | F1A: T← CYCOUT; |
| 4855 | L← ALLONES XOR T, TASK, :F3A; |
| 4856 | F2: SINK← DISP, SINK← lgm40, BUS=0, :WIND; FUNC 2 - WINDOW .AND. GRAY |
| 4857 | F2A: T← CYCOUT; |
| 4858 | L← ALLONES XOR T; |
| 4859 | SINK← DISP, SINK← lgm20, BUS=0; WHICH BANK |
| 4860 | TEMP← L, :AB2; TEMP ← NOT WINDOW |
| 4861 | NB2: MAR← DWAX, :XB2; (NORMAL BANK) |
| 4862 | AB2: XMAR← DWAX, :XB2; (ALTERNATE BANK) |
| 4863 | XB2: L← CONST AND T; WINDOW .AND. GRAY |
| 4864 | T← TEMP; |
| 4865 | T← MD .T; DEST.AND.NOT WINDOW |
| 4866 | L← LREG OR T, TASK, :F3A; (TRANSPARENT) |
| 4867 | F3: L← CONST, TASK, :F3A; FUNC 3 - CONSTANT (COLOR) |
| 4868 | ; |
| 4869 | ; |
| 4870 | ; /* AFTER GETTING SOURCE, START MEMORY AND DISPATCH ON OP |
| 4871 | !1,2,AB3,NB3; |
| 4872 | F3A: CYCOUT← L; (TASK HERE) |
| 4873 | F0A: SINK← DISP, SINK← lgm20, BUS=0; WHICH BANK |
| 4874 | SINK← DISP, SINK← lgm3, BUS, :AB3; DISPATCH ON OP |
| 4875 | NB3: T← MAR← DWAX, :OP0; (NORMAL BANK) |
| 4876 | AB3: T← XMAR← DWAX, :OP0; (ALTERNATE BANK) |
| 4877 | ; |
| 4878 | ; |
| 4879 | ; /* HERE ARE THE OPERATIONS - ENTER WITH SOURCE IN CYCOUT |
| 4880 | %16,17,15,STFULL,STMSK; MASKED OR FULL STORE (LOOK AT 2-BIT) |
| 4881 | ; OP 0 - SOURCE |
| 4882 | OP0: SINK← RETN, BUS; TEST IF UNMASKED |
| 4883 | OP0A: L← HINC+T, :STFULL; ELSE :STMSK |
| 4884 | OP1: T← CYCOUT; OP 1 - SOURCE .OR. DEST |
| 4885 | L← MD OR T, :OPN; |
| 4886 | OP2: T← CYCOUT; OP 2 - SOURCE .XOR. DEST |
| 4887 | L← MD XOR T, :OPN; |
| 4888 | OP3: T← CYCOUT; OP 3 - (NOT SOURCE) .AND. DEST |
| 4889 | L← 0-T-1; |
| 4890 | T← LREG; |
| 4891 | L← MD AND T, :OPN; |
| 4892 | OPN: SINK← DISP, SINK← lgm20, BUS=0, TASK; WHICH BANK |
| 4893 | CYCOUT← L, :AB3; |
| 4894 | ; |
| 4895 | ; |
| 4896 | ; /* STORE MASKED INTO DESTINATION |
| 4897 | !1,2,STM2,STM1; |
| 4898 | !1,2,AB4,NB4; |
| 4899 | STMSK: L← MD; |
| 4900 | SINK← RETN, BUSODD, TASK; DETERMINE MASK FROM CALL INDEX |
| 4901 | TEMP← L, :STM2; STACHE DEST WORD IN TEMP |
| 4902 | STM1: T←MASK1, :STM3; |
| 4903 | STM2: T←MASK2, :STM3; |
| 4904 | STM3: L← CYCOUT AND T; ***X24. Removed TASK clause. |
| 4905 | CYCOUT← L, L← 0-T-1; AND INTO SOURCE |
| 4906 | T← LREG; T← MASK COMPLEMENTED |
| 4907 | T← TEMP .T; AND INTO DEST |
| 4908 | L← CYCOUT OR T; OR TOGETHER THEN GO STORE |
| 4909 | SINK← DISP, SINK← lgm20, BUS=0, TASK; WHICH BANK |
| 4910 | CYCOUT← L, :AB4; |
| 4911 | NB4: T← MAR← DWAX, :OP0A; (NORMAL BANK) |
| 4912 | AB4: T← XMAR← DWAX, :OP0A; (ALTERNATE BANK) |
| 4913 | ; |
| 4914 | ; /* STORE UNMASKED FROM CYCOUT (L=NEXT DWAX) |
| 4915 | STFULL: MD← CYCOUT; |
| 4916 | STFUL1: SINK← RETN, BUS, TASK; |
| 4917 | DWAX← L, :DON0; |
| 4918 | ; |
| 4919 | ; |
| 4920 | ; /* WINDOW SOURCE FUNCTION |
| 4921 | ; TASKS UPON RETURN, RESULT IN CYCOUT |
| 4922 | !1,2,DOCY,NOCY; |
| 4923 | !17,1,WIA; |
| 4924 | !1,2,NZSK,ZESK; |
| 4925 | !1,2,AB5,NB5; |
| 4926 | WIND: L← T← SKMSK, :AB5; ENTER HERE (8 INST TO TASK) |
| 4927 | NB5: MAR← SWA, :XB5; (NORMAL BANK) |
| 4928 | AB5: XMAR← SWA, :XB5; (ALTERNATE BANK) |
| 4929 | XB5: L← WORD2.T, SH=0; |
| 4930 | CYCOUT← L, L← 0-T-1, :NZSK; CYCOUT← OLD WORD .AND. MSK |
| 4931 | ZESK: L← MD, TASK; ZERO SKEW BYPASSES LOTS |
| 4932 | CYCOUT← L, :NOCY; |
| 4933 | NZSK: T← MD; |
| 4934 | L← LREG.T; |
| 4935 | TEMP← L, L←T, TASK; TEMP← NEW WORD .AND. NOTMSK |
| 4936 | WORD2← L; |
| 4937 | T← TEMP; |
| 4938 | L← T← CYCOUT OR T; OR THEM TOGETHER |
| 4939 | CYCOUT← L, L← 0+1, SH=0; DONT CYCLE A ZERO ***X21. |
| 4940 | SINK← SKEW, BUS, :DOCY; |
| 4941 | DOCY: CYRET← L LSH 1, L← T, :L0; CYCLE BY SKEW ***X21. |
| 4942 | NOCY: T← SWA, :WIA; (MAY HAVE OR-17 FROM BUS) |
| 4943 | CYX2: T← SWA; |
| 4944 | WIA: L← HINC+T; |
| 4945 | SINK← DISP, SINK← lgm14, BUS, TASK; DISPATCH TO CALLER |
| 4946 | SWA← L, :F0A; |
| 4947 | |
| 4948 | ; THE DISK CONTROLLER |
| 4949 | |
| 4950 | ; ITS REGISTERS: |
| 4951 | $DCBR $R34; |
| 4952 | $KNMAR $R33; |
| 4953 | $CKSUMR $R32; |
| 4954 | $KWDCT $R31; |
| 4955 | $KNMARW $R33; |
| 4956 | $CKSUMRW $R32; |
| 4957 | $KWDCTW $R31; |
| 4958 | |
| 4959 | ; ITS TASK SPECIFIC FUNCTIONS AND BUS SOURCES: |
| 4960 | $KSTAT $L020012,014003,124100; DF1 = 12 (LHS) BS = 3 (RHS) |
| 4961 | $RWC $L024011,000000,000000; NDF2 = 11 |
| 4962 | $RECNO $L024012,000000,000000; NDF2 = 12 |
| 4963 | $INIT $L024010,000000,000000; NDF2 = 10 |
| 4964 | $CLRSTAT $L016014,000000,000000; NDF1 = 14 |
| 4965 | $KCOMM $L020015,000000,124000; DF1 = 15 (LHS only) Requires bus def |
| 4966 | $SWRNRDY $L024014,000000,000000; NDF2 = 14 |
| 4967 | $KADR $L020016,000000,124000; DF1 = 16 (LHS only) Requires bus def |
| 4968 | $KDATA $L020017,014004,124100; DF1 = 17 (LHS) BS = 4 (RHS) |
| 4969 | $STROBE $L016011,000000,000000; NDF1 = 11 |
| 4970 | $NFER $L024015,000000,000000; NDF2 = 15 |
| 4971 | $STROBON $L024016,000000,000000; NDF2 = 16 |
| 4972 | $XFRDAT $L024013,000000,000000; NDF2 = 13 |
| 4973 | $INCRECNO $L016013,000000,000000; NDF1 = 13 |
| 4974 | |
| 4975 | ; THE DISK CONTROLLER COMES IN TWO PARTS. THE SECTOR |
| 4976 | ; TASK HANDLES DEVICE CONTROL AND COMMAND UNDERSTANDING |
| 4977 | ; AND STATUS REPORTING AND THE LIKE. THE WORD TASK ONLY |
| 4978 | ; RUNS AFTER BEING ENABLED BY THE SECTOR TASK AND |
| 4979 | ; ACTUALLY MOVES DATA WORDS TO AND FRO. |
| 4980 | |
| 4981 | ; THE SECTOR TASK |
| 4982 | |
| 4983 | ; LABEL PREDEFINITIONS: |
| 4984 | !1,2,COMM,NOCOMM; |
| 4985 | !1,2,COMM2,IDLE1; |
| 4986 | !1,2,BADCOMM,COMM3; |
| 4987 | !1,2,COMM4,ILLSEC; |
| 4988 | !1,2,COMM5,WHYNRDY; |
| 4989 | !1,2,STROB,CKSECT; |
| 4990 | !1,2,STALL,CKSECT1; |
| 4991 | !1,2,KSFINI,CKSECT2; |
| 4992 | !1,2,IDLE2,TRANSFER; |
| 4993 | !1,2,STALL2,GASP; |
| 4994 | !1,2,INVERT,NOINVERT; |
| 4995 | |
| 4996 | KSEC: MAR← KBLKADR2; |
| 4997 | KPOQ: CLRSTAT; RESET THE STORED DISK ADDRESS |
| 4998 | MD←L←ALLONES+1, :GCOM2; ALSO CLEAR DCB POINTER |
| 4999 | |
| 5000 | GETCOM: MAR←KBLKADR; GET FIRST DCB POINTER |
| 5001 | GCOM1: NOP; |
| 5002 | L←MD; |
| 5003 | GCOM2: DCBR←L,TASK; |
| 5004 | KCOMM←TOWTT; IDLE ALL DATA TRANSFERS |
| 5005 | |
| 5006 | MAR←KBLKADR3; GENERATE A SECTOR INTERRUPT |
| 5007 | T←NWW; |
| 5008 | L←MD OR T; |
| 5009 | |
| 5010 | MAR←KBLKADR+1; STORE THE STATUS |
| 5011 | NWW←L, TASK; |
| 5012 | MD←KSTAT; |
| 5013 | |
| 5014 | MAR←KBLKADR; WRITE THE CURRENT DCB POINTER |
| 5015 | KSTAT←5; INITIAL STATUS IS INCOMPLETE |
| 5016 | L←DCBR,TASK,BUS=0; |
| 5017 | MD←DCBR, :COMM; |
| 5018 | |
| 5019 | ; BUS=0 MAPS COMM TO NOCOMM |
| 5020 | |
| 5021 | COMM: T←2; GET THE DISK COMMAND |
| 5022 | MAR←DCBR+T; |
| 5023 | T←TOTUWC; |
| 5024 | L←MD XOR T, TASK, STROBON; |
| 5025 | KWDCT←L, :COMM2; |
| 5026 | |
| 5027 | ; STROBON MAPS COMM2 TO IDLE1 |
| 5028 | |
| 5029 | COMM2: T←10; READ NEW DISK ADDRESS |
| 5030 | MAR←DCBR+T+1; |
| 5031 | T←KWDCT; |
| 5032 | L←ONE AND T; |
| 5033 | L←-400 AND T, SH=0; |
| 5034 | T←MD, SH=0, :INVERT; |
| 5035 | |
| 5036 | ; SH=0 MAPS INVERT TO NOINVERT |
| 5037 | |
| 5038 | INVERT: L←2 XOR T, TASK, :BADCOMM; |
| 5039 | NOINVERT: L←T, TASK, :BADCOMM; |
| 5040 | |
| 5041 | ; SH=0 MAPS BADCOMM TO COMM3 |
| 5042 | |
| 5043 | COMM3: KNMAR←L; |
| 5044 | |
| 5045 | MAR←KBLKADR2; WRITE THE NEW DISK ADDRESS |
| 5046 | T←SECT2CM; CHECK FOR SECTOR > 13 |
| 5047 | L←T←KDATA←KNMAR+T; NEW DISK ADDRESS TO HARDWARE |
| 5048 | KADR←KWDCT,ALUCY; DISK COMMAND TO HARDWARE |
| 5049 | L←MD XOR T,TASK, :COMM4; COMPARE OLD AND NEW DISK ADDRESSES |
| 5050 | |
| 5051 | ; ALUCY MAPS COMM4 TO ILLSEC |
| 5052 | |
| 5053 | COMM4: CKSUMR←L; |
| 5054 | |
| 5055 | MAR←KBLKADR2; WRITE THE NEW DISK ADDRESS |
| 5056 | T←CADM,SWRNRDY; SEE IF DISK IS READY |
| 5057 | L←CKSUMR AND T, :COMM5; |
| 5058 | |
| 5059 | ; SWRNRDY MAPS COMM5 TO WHYNRDY |
| 5060 | |
| 5061 | COMM5: MD←KNMAR; COMPLETE THE WRITE |
| 5062 | SH=0,TASK; |
| 5063 | :STROB; |
| 5064 | |
| 5065 | ; SH=0 MAPS STROB TO CKSECT |
| 5066 | |
| 5067 | CKSECT: T←KNMAR,NFER; |
| 5068 | L←KSTAT XOR T, :STALL; |
| 5069 | |
| 5070 | ; NFER MAPS STALL TO CKSECT1 |
| 5071 | |
| 5072 | CKSECT1: CKSUMR←L,XFRDAT; |
| 5073 | T←CKSUMR, :KSFINI; |
| 5074 | |
| 5075 | ; XFRDAT MAPS KSFINI TO CKSECT2 |
| 5076 | |
| 5077 | CKSECT2: L←SECTMSK AND T; |
| 5078 | KSLAST: BLOCK,SH=0; |
| 5079 | GASP: TASK, :IDLE2; |
| 5080 | |
| 5081 | ; SH=0 MAPS IDLE2 TO TRANSFER |
| 5082 | |
| 5083 | TRANSFER: KCOMM←TOTUWC; TURN ON THE TRANSFER |
| 5084 | |
| 5085 | !1,2,ERRFND,NOERRFND; |
| 5086 | !1,2,EF1,NEF1; |
| 5087 | |
| 5088 | DMPSTAT: T←COMERR1; SEE IF STATUS REPRESENTS ERROR |
| 5089 | L←KSTAT AND T; |
| 5090 | MAR←DCBR+1; WRITE FINAL STATUS |
| 5091 | KWDCT←L,TASK,SH=0; |
| 5092 | MD←KSTAT,:ERRFND; |
| 5093 | |
| 5094 | ; SH=0 MAPS ERRFND TO NOERRFND |
| 5095 | |
| 5096 | NOERRFND: T←6; PICK UP NO-ERROR INTERRUPT WORD |
| 5097 | |
| 5098 | INTCOM: MAR←DCBR+T; |
| 5099 | T←NWW; |
| 5100 | L←MD OR T; |
| 5101 | SINK←KWDCT,BUS=0,TASK; |
| 5102 | NWW←L,:EF1; |
| 5103 | |
| 5104 | ; BUS=0 MAPS EF1 TO NEF1 |
| 5105 | |
| 5106 | NEF1: MAR←DCBR,:GCOM1; FETCH ADDRESS OF NEXT CONTROL BLOCK |
| 5107 | |
| 5108 | ERRFND: T←7,:INTCOM; PICK UP ERROR INTERRUPT WORD |
| 5109 | |
| 5110 | EF1: :KSEC; |
| 5111 | |
| 5112 | NOCOMM: L←ALLONES,CLRSTAT,:KSLAST; |
| 5113 | |
| 5114 | IDLE1: L←ALLONES,:KSLAST; |
| 5115 | |
| 5116 | IDLE2: KSTAT←LOW14, :GETCOM; NO ACTIVITY THIS SECTOR |
| 5117 | |
| 5118 | BADCOMM: KSTAT←7; ILLEGAL COMMAND ONLY NOTED IN KBLK STAT |
| 5119 | BLOCK; |
| 5120 | TASK,:EF1; |
| 5121 | |
| 5122 | WHYNRDY: NFER; |
| 5123 | STALL: BLOCK, :STALL2; |
| 5124 | |
| 5125 | ; NFER MAPS STALL2 TO GASP |
| 5126 | |
| 5127 | STALL2: TASK; |
| 5128 | :DMPSTAT; |
| 5129 | |
| 5130 | ILLSEC: KSTAT←7, :STALL; ILLEGAL SECTOR SPECIFIED |
| 5131 | |
| 5132 | STROB: CLRSTAT; |
| 5133 | L←ALLONES,STROBE,:CKSECT1; |
| 5134 | |
| 5135 | KSFINI: KSTAT←4, :STALL; COMMAND FINISHED CORRECTLY |
| 5136 | |
| 5137 | |
| 5138 | ;DISK WORD TASK |
| 5139 | ;WORD TASK PREDEFINITIONS |
| 5140 | !37,37,,,,RP0,INPREF1,CKP0,WP0,,PXFLP1,RDCK0,WRT0,REC1,,REC2,REC3,,,REC0RC,REC0W,R0,,CK0,W0,,R2,,W2,,REC0,,KWD; |
| 5141 | !1,2,RW1,RW2; |
| 5142 | !1,2,CK1,CK2; |
| 5143 | !1,2,CK3,CK4; |
| 5144 | !1,2,CKERR,CK5; |
| 5145 | !1,2,PXFLP,PXF2; |
| 5146 | !1,2,PREFDONE,INPREF; |
| 5147 | !1,2,,CK6; |
| 5148 | !1,2,CKSMERR,PXFLP0; |
| 5149 | |
| 5150 | KWD: BLOCK,:REC0; |
| 5151 | |
| 5152 | ; SH<0 MAPS REC0 TO REC0 |
| 5153 | ; ANYTHING=INIT MAPS REC0 TO KWD |
| 5154 | |
| 5155 | REC0: L←2, TASK; LENGTH OF RECORD 0 (ALLOW RELEASE IF BLOCKED) |
| 5156 | KNMARW←L; |
| 5157 | |
| 5158 | T←KNMARW, BLOCK, RWC; GET ADDR OF MEMORY BLOCK TO TRANSFER |
| 5159 | MAR←DCBR+T+1, :REC0RC; |
| 5160 | |
| 5161 | ; WRITE MAPS REC0RC TO REC0W |
| 5162 | ; INIT MAPS REC0RC TO KWD |
| 5163 | |
| 5164 | REC0RC: T←MFRRDL,BLOCK, :REC12A; FIRST RECORD READ DELAY |
| 5165 | REC0W: T←MFR0BL,BLOCK, :REC12A; FIRST RECORD 0'S BLOCK LENGTH |
| 5166 | |
| 5167 | REC1: L←10, INCRECNO; LENGTH OF RECORD 1 |
| 5168 | T←4, :REC12; |
| 5169 | REC2: L←PAGE1, INCRECNO; LENGTH OF RECORD 2 |
| 5170 | T←5, :REC12; |
| 5171 | REC12: MAR←DCBR+T, RWC; MEM BLK ADDR FOR RECORD |
| 5172 | KNMARW←L, :RDCK0; |
| 5173 | |
| 5174 | ; RWC=WRITE MAPS RDCK0 INTO WRT0 |
| 5175 | ; RWC=INIT MAPS RDCK0 INTO KWD |
| 5176 | |
| 5177 | RDCK0: T←MIRRDL, :REC12A; |
| 5178 | WRT0: T←MIR0BL, :REC12A; |
| 5179 | |
| 5180 | REC12A: L←MD; |
| 5181 | KWDCTW←L, L←T; |
| 5182 | COM1: KCOMM← STUWC, :INPREF0; |
| 5183 | |
| 5184 | INPREF: L←CKSUMRW+1, INIT, BLOCK; |
| 5185 | INPREF0: CKSUMRW←L, SH<0, TASK, :INPREF1; |
| 5186 | |
| 5187 | ; INIT MAPS INPREF1 TO KWD |
| 5188 | |
| 5189 | INPREF1: KDATA←0, :PREFDONE; |
| 5190 | |
| 5191 | ; SH<0 MAPS PREFDONE TO INPREF |
| 5192 | |
| 5193 | PREFDONE: T←KNMARW; COMPUTE TOP OF BLOCK TO TRANSFER |
| 5194 | KWDX: L←KWDCTW+T,RWC; (ALSO USED FOR RESET) |
| 5195 | KNMARW←L,BLOCK,:RP0; |
| 5196 | |
| 5197 | ; RWC=CHECK MAPS RP0 TO CKP0 |
| 5198 | ; RWC=WRITE MAPS RP0 AND CKP0 TO WP0 |
| 5199 | ; RWC=INIT MAPS RP0, CKP0, AND WP0 TO KWD |
| 5200 | |
| 5201 | RP0: KCOMM←STRCWFS,:WP1; |
| 5202 | |
| 5203 | CKP0: L←KWDCTW-1; ADJUST FINISHING CONDITION BY 1 FOR CHECKING ONLY |
| 5204 | KWDCTW←L,:RP0; |
| 5205 | |
| 5206 | WP0: KDATA←ONE; WRITE THE SYNC PATTERN |
| 5207 | WP1: L←KBLKADR,TASK,:RW1; INITIALIZE THE CHECKSUM AND ENTER XFER LOOP |
| 5208 | |
| 5209 | |
| 5210 | XFLP: T←L←KNMARW-1; BEGINNING OF MAIN XFER LOOP |
| 5211 | KNMARW←L; |
| 5212 | MAR←KNMARW,RWC; |
| 5213 | L←KWDCTW-T,:R0; |
| 5214 | |
| 5215 | ; RWC=CHECK MAPS R0 TO CK0 |
| 5216 | ; RWC=WRITE MAPS R0 AND CK0 TO W0 |
| 5217 | ; RWC=INIT MAPS R0, CK0, AND W0 TO KWD |
| 5218 | |
| 5219 | R0: T←CKSUMRW,SH=0,BLOCK; |
| 5220 | MD←L←KDATA XOR T,TASK,:RW1; |
| 5221 | |
| 5222 | ; SH=0 MAPS RW1 TO RW2 |
| 5223 | |
| 5224 | RW1: CKSUMRW←L,:XFLP; |
| 5225 | |
| 5226 | W0: T←CKSUMRW,BLOCK; |
| 5227 | KDATA←L←MD XOR T,SH=0; |
| 5228 | TASK,:RW1; |
| 5229 | |
| 5230 | ; AS ALREADY NOTED, SH=0 MAPS RW1 TO RW2 |
| 5231 | |
| 5232 | CK0: T←KDATA,BLOCK,SH=0; |
| 5233 | L←MD XOR T,BUS=0,:CK1; |
| 5234 | |
| 5235 | ; SH=0 MAPS CK1 TO CK2 |
| 5236 | |
| 5237 | CK1: L←CKSUMRW XOR T,SH=0,:CK3; |
| 5238 | |
| 5239 | ; BUS=0 MAPS CK3 TO CK4 |
| 5240 | |
| 5241 | CK3: TASK,:CKERR; |
| 5242 | |
| 5243 | ; SH=0 MAPS CKERR TO CK5 |
| 5244 | |
| 5245 | CK5: CKSUMRW←L,:XFLP; |
| 5246 | |
| 5247 | CK4: MAR←KNMARW, :CK6; |
| 5248 | |
| 5249 | ; SH=0 MAPS CK6 TO CK6 |
| 5250 | |
| 5251 | CK6: CKSUMRW←L,L←0+T; |
| 5252 | MTEMP←L,TASK; |
| 5253 | MD←MTEMP,:XFLP; |
| 5254 | |
| 5255 | CK2: L←CKSUMRW-T,:R2; |
| 5256 | |
| 5257 | ; BUS=0 MAPS R2 TO R2 |
| 5258 | |
| 5259 | RW2: CKSUMRW←L; |
| 5260 | |
| 5261 | T←KDATA←CKSUMRW,RWC; THIS CODE HANDLES THE FINAL CHECKSUM |
| 5262 | L←KDATA-T,BLOCK,:R2; |
| 5263 | |
| 5264 | ; RWC=CHECK NEVER GETS HERE |
| 5265 | ; RWC=WRITE MAPS R2 TO W2 |
| 5266 | ; RWC=INIT MAPS R2 AND W2 TO KWD |
| 5267 | |
| 5268 | R2: L←MRPAL, SH=0; SET READ POSTAMBLE LENGTH, CHECK CKSUM |
| 5269 | KCOMM←TOTUWC, :CKSMERR; |
| 5270 | |
| 5271 | ; SH=0 MAPS CKSMERR TO PXFLP0 |
| 5272 | |
| 5273 | W2: L←MWPAL, TASK; SET WRITE POSTAMBLE LENGTH |
| 5274 | CKSUMRW←L, :PXFLP; |
| 5275 | |
| 5276 | CKSMERR: KSTAT←0,:PXFLP0; 0 MEANS CHECKSUM ERROR .. CONTINUE |
| 5277 | |
| 5278 | PXFLP: L←CKSUMRW+1, INIT, BLOCK; |
| 5279 | PXFLP0: CKSUMRW←L, TASK, SH=0, :PXFLP1; |
| 5280 | |
| 5281 | ; INIT MAPS PXFLP1 TO KWD |
| 5282 | |
| 5283 | PXFLP1: KDATA←0,:PXFLP; |
| 5284 | |
| 5285 | ; SH=0 MAPS PXFLP TO PXF2 |
| 5286 | |
| 5287 | PXF2: RECNO, BLOCK; DISPATCH BASED ON RECORD NUMBER |
| 5288 | :REC1; |
| 5289 | |
| 5290 | ; RECNO=2 MAPS REC1 INTO REC2 |
| 5291 | ; RECNO=3 MAPS REC1 INTO REC3 |
| 5292 | ; RECNO=INIT MAPS REC1 INTO KWD |
| 5293 | |
| 5294 | REC3: KSTAT←4,:PXFLP; 4 MEANS SUCCESS!!! |
| 5295 | |
| 5296 | CKERR: KCOMM←TOTUWC; TURN OFF DATA TRANSFER |
| 5297 | L←KSTAT←6, :PXFLP1; SHOW CHECK ERROR AND LOOP |
| 5298 | |
| 5299 | ;The Parity Error Task |
| 5300 | ;Its label predefinition is way earlier |
| 5301 | ;It dumps the following interesting registers: |
| 5302 | ;614/ DCBR Disk control block |
| 5303 | ;615/ KNMAR Disk memory address |
| 5304 | ;616/ DWA Display memory address |
| 5305 | ;617/ CBA Display control block |
| 5306 | ;620/ PC Emulator program counter |
| 5307 | ;621/ SAD Emulator temporary register for indirection |
| 5308 | |
| 5309 | PART: T← 10; |
| 5310 | L← ALLONES; TURN OFF MEMORY INTERRUPTS |
| 5311 | MAR← ERRCTRL, :PX1; |
| 5312 | PR8: L← SAD, :PX; |
| 5313 | PR7: L← PC, :PX; |
| 5314 | PR6: L← CBA, :PX; |
| 5315 | PR5: L← DWA, :PX; |
| 5316 | PR4: L← KNMAR, :PX; |
| 5317 | PR3: L← DCBR, :PX; |
| 5318 | PR2: L← NWW OR T, TASK; T CONTAINS 1 AT THIS POINT |
| 5319 | PR0: NWW← L, :PART; |
| 5320 | |
| 5321 | PX: MAR← 612+T; |
| 5322 | PX1: MTEMP← L, L← T; |
| 5323 | MD← MTEMP; |
| 5324 | CURDATA← L; THIS CLOBBERS THE CURSOR FOR ONE |
| 5325 | T← CURDATA-1, BUS; FRAME WHEN AN ERROR OCCURS |
| 5326 | :PR0; |
| 5327 | |
| 5328 | ; AltoIIMRT4K.mu |
| 5329 | ; |
| 5330 | ; last modified December 1, 1977 1:14 AM |
| 5331 | ; |
| 5332 | ; This is the part of the Memory Refresh Task which |
| 5333 | ; is specific to Alto IIs WITHOUT Extended memory. |
| 5334 | ; |
| 5335 | ; Copyright Xerox Corporation 1979 |
| 5336 | $EngNumber $20000; ALTO 2 WITHOUT EXTENDED MEMORY |
| 5337 | |
| 5338 | MRT: SINK← MOUSE, BUS; MOUSE DATA IS ANDED WITH 17B |
| 5339 | MRTA: L← T← -2, :TX0; DISPATCH ON MOUSE CHANGE |
| 5340 | TX0: L← T← R37 AND NOT T; UPDATE REFRESH ADDRESS |
| 5341 | T← 3+T+1, SH=0; |
| 5342 | L← REFIIMSK ANDT, :DOTIMER; |
| 5343 | NOTIMER:R37← L; STORE UPDATED REFRESH ADDRESS |
| 5344 | TIMERTN:L← REFZERO AND T; |
| 5345 | SH=0; TEST FOR CLOCK TICK |
| 5346 | :NOCLK; |
| 5347 | NOCLK: MAR← R37; FIRST FEFRESH CYCLE |
| 5348 | L← CURX; |
| 5349 | T← 2, SH=0; |
| 5350 | MAR← R37 XORT, :DOCUR; SECOND REFRESH CYCLE |
| 5351 | NOCUR: CURDATA← L, TASK; |
| 5352 | MRTLAST:CURDATA← L, :MRT; |
| 5353 | |
| 5354 | DOTIMER:R37← L; SAVE REFRESH ADDRESS |
| 5355 | MAR←EIALOC; INTERVAL TIMER/EIA INTERFACE |
| 5356 | L←2 AND T; |
| 5357 | SH=0, L←T←REFZERO.T; ***V3 CHANGE (USED TO BE BIAS) |
| 5358 | CURDATA←L, :SPCHK; CURDATA←CURRENT TIME WITHOUT CONTROL BITS |
| 5359 | |
| 5360 | SPCHK: SINK←MD, BUS=0, TASK; CHECK FOR EIA LINE SPACING |
| 5361 | SPIA: :NOTIMERINT, CLOCKTEMP←L; |
| 5362 | |
| 5363 | NOSPCHK:L←MD; CHECK FOR TIME=NOW |
| 5364 | MAR←TRAPDISP-1; CONTAINS TIME AT WHICH INTERRUPT SHOULD HAPPEN |
| 5365 | MTEMP←L; IF INTERRUPT IS CAUSED, |
| 5366 | L← MD-T; LINE STATE WILL BE STORED |
| 5367 | SH=0, TASK, L←MTEMP, :SPIA; |
| 5368 | |
| 5369 | TIMERINT:MAR← ITQUAN; STORE THE THING IN CLOCKTEMP AT ITQUAN |
| 5370 | L← CURDATA; |
| 5371 | R37← L; |
| 5372 | T←NWW; AND CAUSE AN INTERRUPT ON THE CHANNELS |
| 5373 | MD←CLOCKTEMP; SPECIFIED BY ITQUAN+1 |
| 5374 | L←MD OR T, TASK; |
| 5375 | NWW←L; |
| 5376 | |
| 5377 | NOTIMERINT: T←R37, :TIMERTN; |
| 5378 | |
| 5379 | ;The rest of MRT, starting at the label CLOCK is unchanged |
| 5380 | |
| 5381 | ; AltoIIMRT16K.mu |
| 5382 | ; |
| 5383 | ; last modified December 1, 1977 1:13 AM |
| 5384 | ; |
| 5385 | ; This is the part of the Memory Refresh Task which |
| 5386 | ; is specific to Alto IIs with Extended memory. |
| 5387 | ; |
| 5388 | ; Copyright Xerox Corporation 1979 |
| 5389 | $EngNumber $30000; ALTO II WITH EXTENDED MEMORY |
| 5390 | ; |
| 5391 | ; This version assumes MRTACT is cleared by BLOCK, not MAR← R37 |
| 5392 | ; R37 [4-13] are the low bits of the TOD clock |
| 5393 | ; R37 [8-14] are the refresh address bits |
| 5394 | ; Each time MRT runs, four refresh addresses are generated, though |
| 5395 | ; R37 is incremented only once. Sprinkled throughout the execution |
| 5396 | ; of this code are the following operations having to do with refresh: |
| 5397 | ; MAR← R37 |
| 5398 | ; R37← R37 +4 NOTE THAT R37 [14] DOES NOT CHANGE |
| 5399 | ; MAR← R37 XOR 2 TOGGLES BIT 14 |
| 5400 | ; MAR← R37 XOR 200 TOGGLES BIT 8 |
| 5401 | ; MAR← R37 XOR 202 TOGGLES BITS 8 AND 14 |
| 5402 | |
| 5403 | MRT: MAR← R37; **FIRST REFRESH CYCLE** |
| 5404 | SINK← MOUSE, BUS; MOUSE DATA IS ANDED WITH 17B |
| 5405 | MRTA: L← T← -2, :TX0; DISPATCH ON MOUSE CHANGE |
| 5406 | TX0: L← R37 AND NOT T, T← R37;INCREMENT CLOCK |
| 5407 | T← 3+T+1, SH=0; IE. T← T +4. IS INTV TIMER ON? |
| 5408 | L← REFIIMSK AND T, :DOTIMER; [DOTIMER,NOTIMER] ZERO HIGH 4 BITS |
| 5409 | NOTIMER: R37← L; STORE UPDATED CLOCK |
| 5410 | NOTIMERINT: T← 2; NO STATE AT THIS POINT IN PUBLIC REGS |
| 5411 | MAR← R37 XOR T,T← R37; **SECOND REFRESH CYCLE** |
| 5412 | L← REFZERO AND T; ONLY THE CLOKCK BITS, PLEASE |
| 5413 | SH=0, TASK; TEST FOR CLOCK OVERFLOW |
| 5414 | :NOCLK; [NOCLK,CLOCK] |
| 5415 | NOCLK: T ← 200; |
| 5416 | MAR← R37 XOR T; **THIRD FEFRESH CYCLE** |
| 5417 | L← CURX, BLOCK; CLEARS WAKEUP REQUEST FF |
| 5418 | T← 2 OR T, SH=0; NEED TO CHECK CURSOR? |
| 5419 | MAR← R37 XOR T, :DOCUR; **FOURTH REFRESH CYCLE** |
| 5420 | NOCUR: CURDATA← L, TASK; |
| 5421 | MRTLAST:CURDATA← L, :MRT; END OF MAIN LOOP |
| 5422 | |
| 5423 | DOTIMER:R37← L; STORE UPDATED CLOCK |
| 5424 | MAR← EIALOC; INTERVAL TIMER/EIA INTERFACE |
| 5425 | L← 2 AND T; |
| 5426 | SH=0, L← T← REFZERO.T; ***V3 CHANGE (USED TO BE BIAS) |
| 5427 | CURDATA←L, :SPCHK; CURDATA← CURRENT TIME WITHOUT CONTROL BITS |
| 5428 | |
| 5429 | SPCHK: SINK← MD, BUS=0, TASK; CHECK FOR EIA LINE SPACING |
| 5430 | SPIA: :NOTIMERINT, CLOCKTEMP← L; |
| 5431 | |
| 5432 | NOSPCHK:L←MD; CHECK FOR TIME = NOW |
| 5433 | MAR←TRAPDISP-1; CONTAINS TIME AT WHICH INTERRUPT SHOULD HAPPEN |
| 5434 | MTEMP←L; IF INTERRUPT IS CAUSED, |
| 5435 | L← MD-T; LINE STATE WILL BE STORED |
| 5436 | SH=0, TASK, L←MTEMP, :SPIA; |
| 5437 | |
| 5438 | TIMERINT:MAR← ITQUAN; STORE THE THING IN CLOCKTEMP AT ITQUAN |
| 5439 | L← CURDATA; |
| 5440 | R37← L; |
| 5441 | T←NWW; AND CAUSE AN INTERRUPT ON THE CHANNELS |
| 5442 | MD←CLOCKTEMP; SPECIFIED BY ITQUAN+1 |
| 5443 | L←MD OR T, TASK; |
| 5444 | NWW←L,:NOTIMERINT; |
| 5445 | |
| 5446 | ;The rest of MRT, starting at the label CLOCK is unchanged |
| 5447 | **************************************************************************************************/ |