Previous 199869 Revisions Next

r26200 Saturday 16th November, 2013 at 17:22:55 UTC by Jürgen Buchmüller
For reference and bug tracking, add the micro code source as comment (altoIIcode3.mu)
[/branches/alto2/src/emu/cpu/alto2]alto2.c
[/branches/alto2/src/lib/util]unicode.c

branches/alto2/src/emu/cpu/alto2/alto2.c
r26199r26200
15451545   {0177020, 0177023,   "XBUS       Utility input bus (Alto II Std. Hardware)"},
15461546   {0177024, 0177024,   "MEAR       Memory Error Address Register (Alto II Std. Hardware)"},
15471547   {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)"},
15491549   {0177030, 0177033,   "UTILIN     Printer status, mouse, keyset (all 4 locations return same thing)"},
15501550   {0177034, 0177037,   "KBDAD      Undecoded keyboard (Std. Hardware)"},
15511551   {0177740, 0177757,   "BANKREGS   Extended memory option bank registers"},
r26199r26200
15791579   offset %= ALTO2_IO_PAGE_SIZE;
15801580   offset += ALTO2_IO_PAGE_BASE;
15811581
1582   /* binary search in table of unicode ranges */
1582   /* binary search in table of memory ranges */
15831583   while (_max >= _min)
15841584   {
15851585      _mid = (_min + _max) / 2;
r26199r26200
32133213
32143214   return m_next_task;      // return next task (?)
32153215}
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
3292DVT:   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
3304DVT1:   L← BIAS-T-1, TASK, :DVT2;   BIAS THE Y COORDINATE
3305DVT11:   L← BIAS-T, TASK;
3306
3307DVT2:   YPOS← L, :DVT;
3308
3309;Display Horizontal Task.
3310;11 cycles if no block change, 17 if new control block.
3311
3312DHT:   MAR← CBA-1;
3313   L← SLC -1, BUS=0;
3314   SLC← L, :DHT0;
3315
3316DHT0:   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
3321NORMODE:L← T← 377 . T;
3322   AECL← L, :REST;
3323
3324HALFMODE: L← T←  377 . T;
3325   AECL← L, :REST, T← 0;
3326
3327REST:   L← DWA + T,TASK;   INCREMENT DWA BY 0 OR NWRDS
3328NDNX:   DWA← L, :DHT;
3329
3330DHT1:   L← T← MD+1, BUS=0;
3331   CBA← L, MAR← T, :MOREB;
3332
3333NOMORE:   BLOCK, :DNX;
3334MOREB:   T← 37400;
3335   L← T← MD AND T, SETMODE;
3336   MAR← CBA+1, :NORMX, EVENFIELD;
3337
3338NORMX:   HTAB← L LCY 8, :NODD;
3339HALFX:   HTAB← L LCY 8, :NEVEN;
3340
3341NODD:   L←T← 377 . T;
3342   AECL← L, :XREST;   ODD FIELD, FULL RESOLUTION
3343
3344NEVEN:   L← 377 AND T;      EVEN FIELD OR HALF RESOLUTION
3345   AECL←L, T←0;
3346
3347XREST:   L← MD+T;
3348   T←MD-1;
3349DNX:   DWA←L, L←T, TASK;
3350   SLC←L, :DHT;
3351
3352;Display Word Task
3353
3354DWT:   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
3359DWTY:   BLOCK;
3360   TASK, :DWTF;
3361
3362DWTZ:   L←HTAB-1, BUS=0,TASK;
3363   HTAB←L, :DOTAB;
3364
3365DOTAB:   DDR←0, :DWTZ;
3366NOTAB:   MAR←T←DWA;
3367   L←AECL-T-1;
3368   ALUCY, L←2+T;
3369   DWA←L, :XNOMORE;
3370
3371DOMORE:   DDR←MD, TASK;
3372   DDR←MD, :NOTAB;
3373
3374XNOMORE:DDR← MD, BLOCK;
3375   DDR← MD, TASK;
3376
3377DWTF:   :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
3468EREST:   L← 0,ERBFCT;      What's happening ?
3469   EPNTR← L,:ENOCMD;   [ENOCMD,EOREST,EIREST,ERBRES]
3470
3471ENOCMD:   L← ESNEVR,:EPOST;   Shouldn't happen
3472ERBRES:   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
3481EPOST:   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
3496ESETUP:   NOP;
3497   L← MD,BUS=0;      check for zero length
3498   T← MD-1,:ECNTOK;   [ECNTOK,ECNTZR] start-1
3499
3500ECNTZR:   L← ESCZER,:EPOST;   Zero word count.  Abort
3501
3502;Ether Countdown Branch Function - ECBFCT.
3503;NEXT7 = Interface buffer not empty.
3504
3505ECNTOK:   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
3513EIREST:   :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
3534EIFRST:   MAR← EHLOC;      Get Ethernet address
3535   T← 377,EBFCT;      What's happening?
3536   L← MD AND T,BUS=0,:EIFOK;[EIFOK,EIFBAD] promiscuous?
3537
3538EIFOK:   MTEMP← LLCY8,:EIFCHK;   [EIFCHK,EIFPRM] Data wakeup
3539
3540EIFBAD:   ERBFCT,TASK,:EIFB1;   [EIFB1] POST wakeup; xCMD FF set?
3541EIFB1:   :EIFB00;      [EIFB00,EIFB01,EIFB10,EIFB11]
3542
3543EIFB00:   :EIFIGN;      IDL or INGONE, restart rcvr
3544EIFB01:   L← ESABRT,:EPOST;   OCMD, abort
3545EIFB10:   L← ESABRT,:EPOST;   ICMD, abort
3546EIFB11:   L← ESABRT,:EPOST;   ICMD and OCMD, abort
3547
3548EIFPRM:   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
3553EIFCHK:   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
3557EIFNBC:   :EIFIGN;      [EIFIGN,EISET]
3558
3559EIFBC:   :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
3565EIFIGN:   SINK← EPNTR,BUS=0,EPFCT;Reset; Called from output?
3566   EISFCT,TASK,:EOCDWX;   [EOCDWX,EIGO] Restart rcvr
3567
3568EOCDWX:   EWFCT,:EOCDWT;      Return to countdown wait loop
3569
3570EISET:   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
3591EIDATA:   T← ECNTR-1, BUS=0;
3592   MAR← L← EPNTR+1, EBFCT;   [EIDMOR,EIDPST] What's happening
3593EIDMOR:   EPNTR← L, L← T, ECBFCT;   [EIDOK,EIDPST] Guaranteed to branch
3594EIDOK:   MD← EIDFCT, TASK;   [EIDZ4] Read a word from the interface
3595EIDZ4:   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".
3604EIDPST:   L← ESIDON, :EIDFUL;   [EIDFUL,EPOST] Presumed to be INGONE
3605EIDFUL:   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
3615EOREST:   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
3622EOLDBD:   L← ESLOAD,:EPOST;   Load overlow
3623
3624EOLDOK:   L← MTEMP+1;      Write updated load
3625   MAR← ELLOC;
3626   MTEMP← L,TASK;
3627   MD← MTEMP,:EORST1;   New load = (old lshift 1) + 1
3628
3629EORST1:   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
3637EORST2:   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
3643EOINPR:   EISFCT,:EOCDWT;      [EOCDWT,EOCDGO] Enable in under out
3644
3645EOINPN:   :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
3656EOCDWT:   L← 177400,EBFCT;   What's happening?
3657   EPNTR← L,ECBFCT,:EOCDW0;[EOCDW0,EOCDRS] Packet coming in?
3658EOCDW0:   L← ECNTR-1,BUS=0,TASK,:EOCDW1; [EOCDW1,EIGO]
3659EOCDW1:   ECNTR← L,EWFCT,:EOCDWT;   [EOCDWT,EOCDGO]
3660
3661EOCDRS:   L← ESABRT,:EPOST;   [EPOST] POST event
3662
3663EIGO:   :EIFRST;      [EIFRST] Input under output
3664
3665;Output main loop setup
3666
3667EOCDGO:   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
3682EODATA:   L← MAR← EPNTR+1,EBFCT;   What's happening?
3683   T← ECNTR-1,BUS=0,:EODOK; [EODOK,EODPST,EODCOL,EODUGH]
3684EODOK:   EPNTR← L,L← T,:EODMOR;   [EODMOR,EODEND]
3685EODMOR:   ECNTR← L,TASK;
3686   EODFCT← MD,:EODATA;   Output word to transmitter
3687
3688EODPST:   L← ESABRT,:EPOST;   [EPOST] POST event
3689
3690EODCOL:   EPFCT,:EOREST;      [EOREST] Collision
3691
3692EODUGH:   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
3699EODEND:   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
3706EOEOT:   EBFCT;         What's happening?
3707   :EOEOK;         [EOEOK,EOEPST,EOECOL,EOEUGH]
3708
3709EOEOK:   L← ESNEVR,:EPOST;   Runaway Transmitter. Never Never.
3710
3711EOEPST:   L← ESODON,:EPOST;   POST event.  Output done
3712
3713EOECOL:   EPFCT,:EOREST;      Collision
3714
3715EOEUGH:   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
3750CLOCK:   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
3757DOCUR:   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
3761WAITC:   YPOS← L, L← 0, TASK, :MRTLAST;   SQUASHES PENDING BRANCH
3762SHOWC:   MAR← CLOCKLOC+T+1, :CNOTLAST;
3763
3764CNOTLAST: T← CURX, :CURF;
3765CLAST:   T← 0;
3766CURF:   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
3773TX1:   L← T← ONE +T, :M00;      Y=0, X=1
3774TX2:   L← T← ALLONES, :M00;      Y=0, X=-1
3775TX3:   L← T← 0, :M00;         Y=1, X=0
3776TX4:   L← T← ONE AND T, :M00;      Y=1, X=1
3777TX5:   L← T← ALLONES XOR T, :M00;   Y=1, X=-1
3778TX6:   T← 0, :M00;         Y=-1, X=0
3779TX7:   T← ONE, :M00;         Y=-1, X=1
3780TX8:   T← ALLONES, :M00;      Y=-1, X=-1
3781
3782M00:   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
3800CURT:   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
3820NOVEM:   IR←L←MAR←0, :INXB,SAD← L;  LOAD SAD TO ZERO THE BUS. STORE PC AT 0
3821Q0:   L← ONE, :INXA;      EXECUTED TWICE
3822Q1:   L← TOTUWC, :INXA;
3823Q2:   L←402, :INXA;      FIRST READ HEADER INTO 402, THEN
3824Q3:   L← 402, :INXA;      STORE LABEL AT 402
3825Q4:   L← ONE, :INXA;      STORE DATA PAGE STARTING AT 1
3826Q5:   L←377+1, :INXE;      Store Ethernet Input Buffer Length ***X21.
3827Q6:   L←ONE, :INXE;      Store Ethernet Input Buffer Pointer ***X21.
3828Q7:   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
3838DiskBoot: 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
3847EtherBoot: L←EthNovaGo, :EReRead; [EReRead, FINJMP]
3848
3849EReRead: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
3857EContRead: 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
3862EReadDone: 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
3872INXA:   T←ONE, :INXCom;      ***X21 change.
3873INXE:   T←EIOffset, :INXCom;   ***X21 addition.
3874
3875INXCom: MAR←T←IR← SAD+T;   *** X21 addition.
3876   PC← L, L← 0+T+1;   *** X21 change.
3877INXB:   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
3909START:   T← MAR←PC+SKIP;
3910START1:   L← NWW, BUS=0;   BUS# 0 MEANS DISABLED OR SOMETHING TO DO
3911   :MAYBE, SH<0, L← 0+T+1;     SH<0 MEANS DISABLED
3912MAYBE:   PC← L, L← T, :DOINT;
3913NOINT:   PC← L, :DIS0;
3914
3915DOINT:   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
3920DIS0:   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
3925DIS1:   T← ACSOURCE, :GETAD;
3926
3927;GETAD MUST BE 0 MOD 20
3928GETAD: T← 0, :DOINS;         PAGE 0
3929G1:   T← PC -1, :DOINS;      RELATIVE
3930G2:   T← AC2, :DOINS;         AC2 RELATIVE
3931G3:   T← AC3, :DOINS;         AC3 RELATIVE
3932G4:   T← 0, :DOINS;         PAGE 0 INDIRECT
3933G5:   T← PC -1, :DOINS;      RELATIVE INDIRECT
3934G6:   T← AC2, :DOINS;         AC2 RELATIVE INDIRECT
3935G7:   T← AC3, :DOINS;         AC3 RELATIVE INDIRECT
3936G10:   L← 0-T-1, TASK, :SHIFT;      COMPLEMENT
3937G11:   L← 0-T, TASK, :SHIFT;      NEGATE
3938G12:   L← 0+T, TASK, :SHIFT;      MOVE
3939G13:   L← 0+T+1, TASK, :SHIFT;      INCREMENT
3940G14:   L← ACDEST-T-1, TASK, :SHIFT;   ADD COMPLEMENT
3941G15:   L← ACDEST-T, TASK, :SHIFT;   SUBTRACT
3942G16:   L← ACDEST+T, TASK, :SHIFT;   ADD
3943G17:   L← ACDEST AND T, TASK, :SHIFT;
3944
3945SHIFT:   DNS← L LCY 8, :START;    SWAP BYTES
3946SH1:   DNS← L RSH 1, :START;   RIGHT 1
3947SH2:   DNS← L LSH 1, :START;   LEFT 1
3948SH3:   DNS← L, :START;      NO SHIFT
3949
3950DOINS:   L← DISP + T, TASK, :SAVAD, IDISP;   DIRECT INSTRUCTIONS
3951DOIND:   L← MAR← DISP+T;            INDIRECT INSTRUCTIONS
3952   XREG← L;
3953   L← MD, TASK, IDISP, :SAVAD;
3954
3955BRI:   L← MAR← PCLOC   ;INTERRUPT RETURN BRANCH
3956BRI0:   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
3962EIR0:   L← MD, :DOINT;
3963EIR1:   L← PC, :DOINT;
3964
3965;***X21 addition
3966; DIRS - 61013 - Disable Interrupts and Skip if they were On
3967DIRS:   T←100000;
3968   L←NWW AND T;
3969   L←PC+1, SH=0;
3970
3971; DIR - 61000 - Disable Interrupts
3972DIR:   T← 100000, :INTSOFF;
3973INTSOFF: L← NWW OR T, TASK, :INTZ;
3974
3975INTSON: PC←L, :INTSOFF;
3976
3977;EIR - 61001 - Enable Interrupts
3978EIR:   L← 100000, :BRI0;
3979
3980;SIT - 61007 - Start Interval Timer
3981SIT:   T← AC0;
3982   L← R37 OR T, TASK;
3983   R37← L, :START;
3984
3985
3986FINJSR:   L← PC;
3987   AC3← L, L← T, TASK;
3988FINJMP:   PC← L, :START;
3989SAVAD:   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
3993JSRII:   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.
4000TRAP:   XREG← L LCY 8;   THE INSTRUCTION
4001TRAP1:   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
4009RAMTRAP: SWMODE, :TRAP;
4010
4011; Parameterless operations come here for dispatch.
4012
4013!1,2,NPNOTRAP,NPTRAP;
4014
4015NOPAR:   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
4021NPNOTRAP: :DIR;
4022
4023NPTRAP: :TRAP1;
4024
4025;***X21 addition for debugging w/ expanded DISP Prom
4026U5:   :RAMTRAP;
4027U6:   :RAMTRAP;
4028U7:   :RAMTRAP;
4029
4030;MAIN INSTRUCTION TABLE.  GET HERE:
4031;      (1) AFTER AN INDIRECTION
4032;      (2) ON DIRECT INSTRUCTIONS
4033
4034XCTAB:   L← SAD, TASK, :FINJMP;   JMP
4035XJSR:   T← SAD, :FINJSR;   JSR
4036XISZ:   MAR← SAD, :ISZ1;   ISZ
4037XDSZ:   MAR← SAD, :DSZ1;   DSZ
4038XLDA:   MAR← SAD, :FINLOAD;   LDA 0-3
4039XSTA:   MAR← SAD;      /*NORMAL
4040XSTA1:   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
4059DSZ1:   T← ALLONES, :FINISZ;
4060ISZ1:   T← ONE, :FINISZ;
4061
4062FINSTO:   SAD← L,TASK;
4063FINST1:   MD←SAD, :START;
4064
4065FINLOAD: NOP;
4066LOADX:   L← MD, TASK;
4067LOADD:   ACDEST← L, :START;
4068
4069FINISZ:   L← MD+T;
4070   MAR← SAD, SH=0;
4071   SAD← L, :FINSTO;
4072
4073INCPC:   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
4087DIV:   T← AC2;
4088DIVX:   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
4092NODIV:   :FINBLT;      ***X21 change.
4093DODIV:   L← AC0, :DIV1;
4094
4095DIVL:   L← AC0;
4096DIV1:   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
4099OVF:   AC1← L LSH 1, L← 0+INCT, :NOV1;      L← 1. SHIFT OVERFLOWED
4100NOOVF:   AC1← L LSH 1 , L← T;         L← 0. SHIFT OK
4101
4102NOV1:   T← AC2, SH=0;
4103   L← AC0-T, :DX0;
4104
4105DX1:   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
4110DX0:   :DOSUB, T← AC1;
4111
4112DOSUB:   AC0← L, L← 0+INCT;   DO THE SUBTRACT
4113   AC1← L;         AND PUT A 1 IN THE QUOTIENT
4114
4115NOSUB:   L← SAD, BUS=0, TASK;
4116   SAD← L LSH 1, :DIVL;
4117
4118ENDDIV:   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
4134MUL:   L← AC2-1, BUS=0;
4135MPYX:   XREG←L,L← 0, :DOMUL;   GET HERE WITH AC2-1 IN L. DON'T MUL IF AC2=0
4136DOMUL:   TASK, L← -10+1;
4137   SAD← L;      COUNT THE LOOP IN SAD
4138
4139MPYL:   L← AC1, BUSODD;
4140   T← AC0, :NOADDIER;
4141
4142NOADDIER: AC1← L MRSH 1, L← T, T← 0, :NOSPILL;
4143ADDIER:   L← T← XREG+INCT;
4144   L← AC1, ALUCY, :NOADDIER;
4145
4146SPILL:   T← ONE;
4147NOSPILL: AC0← L MRSH 1;
4148   L← AC1, BUSODD;
4149   T← AC0, :NOADDX;
4150
4151NOADDX:   AC1← L MRSH 1, L← T, T← 0, :NOSPILLX;
4152ADDX:   L← T← XREG+ INCT;
4153   L← AC1,ALUCY, :NOADDX;
4154
4155SPILLX:   T← ONE;
4156NOSPILLX: AC0← L MRSH 1;
4157   L← SAD+1, BUS=0, TASK;
4158   SAD← L, :MPYL;
4159
4160NOMUL:   T← AC0;
4161   AC0← L, L← T, TASK;   CLEAR AC0
4162   AC1← L;         AND REPLACE AC1 WITH AC0
4163MPYA:   :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
4180EMCYCLE: L← DISP, SINK← X17, BUS=0;   CONSTANT WITH BS=7
4181CYCP:   T← AC0, :EMCYCX;
4182
4183ACCYCLE: T← AC1;
4184   L← 17 AND T, :CYCP;
4185
4186EMCYCX: CYCOUT←L, L←0, :RETCYCX;
4187
4188RAMCYCX: CYCOUT←L, L←0+1;
4189
4190RETCYCX: CYRET←L, L←0+T;
4191   SINK←CYCOUT, BUS;
4192   TASK, :L0;
4193
4194;TABLE FOR CYCLE
4195R4:   CYCOUT← L MRSH 1;
4196Y3:   L← T← CYCOUT, TASK;
4197R3X:   CYCOUT← L MRSH 1;
4198Y2:   L← T← CYCOUT, TASK;
4199R2X:   CYCOUT← L MRSH 1;
4200Y1:   L← T← CYCOUT, TASK;
4201R1X:   CYCOUT← L MRSH 1, :ENDCYCLE;
4202
4203L4:   CYCOUT← L MLSH 1;
4204Z3:   L← T← CYCOUT, TASK;
4205L3:   CYCOUT← L MLSH 1;
4206Z2:   L← T← CYCOUT, TASK;
4207L2:   CYCOUT← L MLSH 1;
4208Z1:   L← T← CYCOUT, TASK;
4209L1:   CYCOUT← L MLSH 1, :ENDCYCLE;
4210L0:   CYCOUT← L, :ENDCYCLE;
4211
4212L8:   CYCOUT← L LCY 8, :ENDCYCLE;
4213L7:   CYCOUT← L LCY 8, :Y1;
4214L6:   CYCOUT← L LCY 8, :Y2;
4215L5:   CYCOUT← L LCY 8, :Y3;
4216
4217R7:   CYCOUT← L LCY 8, :Z1;
4218R6:   CYCOUT← L LCY 8, :Z2;
4219R5:   CYCOUT← L LCY 8, :Z3;
4220
4221ENDCYCLE: SINK← CYRET, BUS, TASK;
4222   :EMCYCRET;
4223
4224EMCYCRET: L←CYCOUT, TASK, :LOADD;
4225
4226RAMCYCRET: 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
4242CONVERT: 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&#17
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
4256ODDCX:   L←AC0, :HDENTER;
4257
4258HDLOOP: T←SAD;         (really NWRDS)
4259   L←DWAX+T;
4260
4261HDENTER: DWAX←L;      DWAX ← AC0+HD*NWRDS
4262   L←XH-1, BUS=0, TASK;
4263   XH←L, :HDLOOP;
4264
4265HDEXIT:   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&#17)+1
4272
4273   L←5;         ***X21. Calling conventions changed.
4274   IR←SAD, TASK;
4275   CYRET←L, :MOVELOOP;   CYRET←CALL5
4276
4277MOVELOOP: L←T←XH-1, BUS=0;
4278   MAR←AC3-T-1, :NFIN;   Fetch next source word
4279NFIN:   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
4286CONVCYCRET: 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.
4292MERGE:   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
4301DOBOTH: MAR←DWAX+1;
4302   T←XREG;
4303   L←MD OR T;
4304   MAR←DWAX+1;
4305   XREG←L, TASK;      ***X21. TASK added.
4306STORE:   MD←XREG, :MOVELOOP;
4307
4308FIN:   L←AC1-1;      ***X21. Return AC1 to DBA&#17.
4309   AC1←L;         *** ... bletch ...
4310   IR←SH3CONST;
4311   L←MD, TASK, :SH1;
4312
4313;RCLK - 61003 - Read the Real Time Clock into AC0,AC1
4314RCLK:   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.
4320SIO:   L← AC0, STARTF;
4321   T← 77777;      ***X21 sets AC0[0] to 0
4322   L← RSNF AND T;
4323LTOAC0:   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.
4333VERS:   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
4338XMLDA:   XMAR← AC1, :FINLOAD;   ***V3 change
4339
4340;XMSTA - Extended Memory Store Accumulator
4341;   @AC1 ← AC0 in the alternate bank
4342XMSTA:   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
4363BLT:   L← MAR← AC0+1;
4364   AC0← L;
4365   L← MD, :BLKSA;
4366
4367BLKS:   L← AC0;
4368BLKSA:   T← AC3+1, BUS=0;
4369   MAR← AC1+T, :MOREBLT;
4370
4371MOREBLT: 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
4377NO:   SINK← DISP, SINK← M7, BUS, :DISABLED;
4378
4379PERHAPS: SINK← DISP, SINK← M7, BUS, :DOIT;
4380
4381DOIT:   PC←L, :FINBLT;   ***X21. Reset PC, terminate instruction.
4382
4383DISABLED: :DIR;   GOES TO BLT OR BLKS
4384
4385FINBLT:   T←777;   ***X21. PC in [177000-177777] means Ram return
4386   L←PC+T+1;
4387   L←PC AND T, TASK, ALUCY;
4388TOSTART: XREG←L, :START;
4389
4390RAMRET: T←XREG, BUS, SWMODE;
4391TORAM:   :NOVEM;
4392
4393;PARAMETERLESS INSTRUCTIONS FOR DIDDLING THE WCS.
4394
4395;JMPRAM - 61010 - JUMP TO THE RAM ADDRESS SPECIFIED BY AC1
4396JMPR:   T←AC1, BUS, SWMODE, :TORAM;
4397
4398
4399;RDRAM - 61011 - READ THE RAM WORD ADDRESSED BY AC1 INTO AC0
4400RDRM:   T← AC1, RDRAM;
4401   L← ALLONES, TASK, :LOADD;
4402
4403
4404;WRTRAM - 61012 - WRITE AC0,AC3 INTO THE RAM LOCATION ADDRESSED BY AC1
4405WTRM:   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
4414DREAD:   MAR← AC3;      START MEMORY CYCLE
4415   NOP;         DELAY
4416DREAD1:   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
4425DWRITE:   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
4435DEXCH:   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
4447DIOG1:   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
4455DIOG2:   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
4467INTCODE: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
4474NOACTIVE: MAR← WWLOC;      RESTORE WW TO CORE
4475   L← SAD;         AND REPLACE IT WITH SAD IN NWW
4476   MD← NWW, TASK;
4477INTZ:   NWW← L, :START;
4478
4479SOMEACTIVE: MAR← PCLOC;   STORE PC AND SET UP TO FIND HIGHEST PRIORITY REQUEST
4480   XREG← L, L← 0;
4481   MD← PC, TASK;
4482
4483ILPA:   PC← L;
4484ILP:   T← SAD;
4485   L← T← XREG AND T;
4486   SH=0, L← T, T← PC;
4487   :IEXIT, XREG← L LSH 1;
4488
4489NIEXIT:   L← 0+T+1, TASK, :ILPA;
4490IEXIT:   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
4565BITBLT:   L← 0;
4566   SINK←LREG, BUSODD;   SINK← -1 IFF NO RAM
4567   L← T← DWOFF, :FDBL;
4568BBNORAM: TASK, :NPTRAP;      TRAP IF NO RAM
4569;
4570FDW:   T← MD;         PICK UP WIDTH, HEIGHT
4571   WIDTH← L, L← T, TASK, :NZWID;
4572NZWID:   NLINES← L;
4573   T← AC1;
4574   L← NLINES-T;
4575   NLINES← L, SH<0, TASK;
4576   :FDDX;
4577;
4578FDDX:   L← T← DXOFF, :FDBL;   PICK UP DEST X AND Y
4579FDX:   T← MD;
4580   DESTX← L, L← T, TASK;
4581   DESTY← L;
4582;
4583   L← T← SXOFF, :FDBL;   PICK UP SOURCE X AND Y
4584FSX:   T← MD;
4585   SRCX← L, L← T, TASK;
4586   SRCY← L, :CSHI;
4587;
4588;   /* FETCH DOUBLEWORD FROM TABLE (L← T← OFFSET, :FDBL)
4589FDBL:   MAR← AC2+T;
4590   SINK← LREG, BUS;
4591FDBX:   L← MD, :FDBX;
4592;
4593;   /* CALCULATE SKEW AND HINC
4594   !1,2,LTOR,RTOL;
4595CSHI:   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
4599RTOL:   SKEW← L, L← 0-1, :AH, TASK;   HINC ← -1
4600LTOR:   SKEW← L, L← 0+1, :AH, TASK;   HINC ← +1
4601AH:   HINC← L;
4602;
4603;   CALCULATE MASK1 AND MASK2
4604   !1,2,IFRTOL,LNWORDS;
4605   !1,2,POSWID,NEGWID;
4606CMASKS:   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;
4616POSWID:   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
4623IFRTOL:   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;
4638LNWORDS:T← STARTBITSM1+1;
4639   L← WIDTH-T-1;
4640   T← 177760, SH<0;
4641   T← LREG.T, :LNW1;
4642LNW1:   L← CALL4;      NWORDS ← (WIDTH-STARTBITS)/16
4643   CYRET← L, L← T, :R4, TASK; CYRET←CALL4
4644;   **WIDTH REG NOW FREE**
4645CYX4:   L← CYCOUT, :LNW2;
4646THIN:   T← MASK1;   SPECIAL CASE OF THIN SLICE
4647   L←MASK2.T;
4648   MASK1← L, L← 0-1;   MASK1 ← MASK1.MASK2, NWORDS ← -1
4649LNW2:   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
4658BTOT:   L← ALLONES;   ELSE -1
4659BTOT1:   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;
4666TTOB:   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
4670CWA:   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**
4675DOSWA:   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
4685CYX3:   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;
4694MULLP:   L← PLIER, BUSODD;      MULTIPLY RASTER BY Y
4695   PLIER← L RSH 1, :NOADD;
4696NOADD:   L← YMUL, SH=0, TASK;   TEST NO MORE MULTIPLIER BITS
4697SHIFTB:   YMUL← L LSH 1, :MULLP;
4698DOADD:   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]
4706CDELT:   L← T← HINC-1;   (NOTE T← -2 OR 0)
4707   L← T← NWORDS-T, SH=0;   (L←NWORDS+2 OR T←NWORDS)
4708CD1:   SINK← VINC, BUSODD, :HNEG;
4709HNEG:   T← RAST2, :VPOS;
4710HPOS:   L← -2-T, :CD1;   (MAKES L←-(NWORDS+2))
4711VPOS:   L← LREG+T, :GDELT, TASK;   BY NOW, LREG = +-(NWORDS+2)
4712VNEG:   L← LREG-T, :GDELT, TASK;   AND T = RASTER
4713GDELT:   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
4720ONEMORE:   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;
4733CTOPL:   L← SKEW, BUS=0, TASK;   IF SKEW=0 THEN 0, ELSE
4734CTX:   IR← 0, :CTOP1;
4735CTOP1:   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;
4739H1:   T← HINC, SH<0;
4740   L← SWA+T, :NOTOPL;
4741HM1:   T← LREG;      IF HINC=-1, THEN FLIP
4742   L← 0-T-1, :H1;   THE POLARITY OF THE TEST
4743NOTOPL:   SINK← HINC, BUSODD, TASK, :CTX;   HINC FORCES BUSODD
4744TOPL:   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;
4751CSKEW:   T← SKEW, BUS=0;   IF SKEW=0, THEN COMP
4752   MAR← LASTMASKP1-T-1, :THINC;
4753THINC:   L←HINC-1;
4754   SH=0;         IF HINC=-1, THEN COMP
4755BCOM1:   T← ALLONES, :COMSK;
4756COMSK:   L← MD XOR T, :GFN;
4757NOCOM:   L← MD, :GFN;
4758;
4759;   /* GET FUNCTION
4760GFN:   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;
4772VLOOP:   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;
4784BENTR:   L← T← NLINES-1;      DECR NLINES AND CHECK IF DONE
4785   NLINES← L, SH<0;
4786   L← NWW, BUS=0, :MOREV;   CHECK FOR INTERRUPTS
4787MOREV:   L← 3.T, :BMAYBE, SH<0;   CHECK DISABLED   ***V3 change
4788BNOINT:   SINK← DISP, SINK← lgm10, BUS=0, :BDIS0, TASK;
4789BMAYBE:   SINK← DISP, SINK← lgm10, BUS=0, :BDOINT, TASK;   TEST IF NEED GRAY(FUNC=8,12)
4790BDIS0:   CONST← L, :DOGRAY;   ***V3 change
4791;
4792;   /* INTERRUPT SUSPENSION (POSSIBLY)
4793   !1,1,DOI1;   MAY GET AN OR-1
4794BDOINT:   :DOI1;   TASK HERE
4795DOI1:   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;
4804DOGRAY:   T← CONST-1;
4805   T← GRAYOFF+T+1;
4806   MAR← AC2+T;
4807   NOP;   UGH
4808   L← MD;
4809NOGRAY:   SINK← DISP, SINK← lgm100, BUS=0, TASK;   TEST TOPLD
4810   CONST← L, :PRELD;
4811;
4812;   /* NORMAL COMPLETION
4813NEGWID:   L← 0, :BLITX, TASK;
4814DONEV:   L← 0, :BLITX, TASK;   MAY BE AN OR-1 HERE!
4815BLITX:   AC1← L, :FINBLT;
4816;
4817;   /* PRELOAD OF FIRST SOURCE WORD (DEPENDING ON ALIGNMENT)
4818   !1,2,AB1,NB1;
4819PRELD:   SINK← DISP, SINK← lgm40, BUS=0;   WHICH BANK
4820   T← HINC, :AB1;
4821NB1:   MAR← SWA-T, :XB1;   (NORMAL BANK)
4822AB1:   XMAR← SWA-T, :XB1;   (ALTERNATE BANK)
4823XB1:   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
4833NOPLD:   L← 3, :FDISP;      CALL #3 IS FIRST WORD
4834DON3:   L← NWORDS;
4835   HCNT← L, SH<0;      HCNT COUNTS WHOLE WORDS
4836DON0:   L← HCNT-1, :DO0;   IF NEG, THEN NO MIDDLE OR LAST
4837DO0:   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)
4840LASTH:   :LH1;   TASK AND BUS PENDING
4841LH1:   L← 2, :FDISP;      CALL #2 IS LAST WORD
4842DON2:   :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;
4850FDISP:   SINK← DISP, SINK←lgm14, BUS, TASK;
4851FDISPA:   RETN← L, :F0;
4852F0:   SINK← DISP, SINK← lgm40, BUS=0, :WIND;   FUNC 0 - WINDOW
4853F1:   SINK← DISP, SINK← lgm40, BUS=0, :WIND;   FUNC 1 - NOT WINDOW
4854F1A:   T← CYCOUT;
4855   L← ALLONES XOR T, TASK, :F3A;
4856F2:   SINK← DISP, SINK← lgm40, BUS=0, :WIND;   FUNC 2 - WINDOW .AND. GRAY
4857F2A:   T← CYCOUT;
4858   L← ALLONES XOR T;
4859   SINK← DISP, SINK← lgm20, BUS=0;   WHICH BANK
4860   TEMP← L, :AB2;      TEMP ← NOT WINDOW
4861NB2:   MAR← DWAX, :XB2;   (NORMAL BANK)
4862AB2:   XMAR← DWAX, :XB2;   (ALTERNATE BANK)
4863XB2:   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)
4867F3:   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;
4872F3A:   CYCOUT← L;   (TASK HERE)
4873F0A:   SINK← DISP, SINK← lgm20, BUS=0;   WHICH BANK
4874   SINK← DISP, SINK← lgm3, BUS, :AB3;   DISPATCH ON OP
4875NB3:   T← MAR← DWAX, :OP0;   (NORMAL BANK)
4876AB3:   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
4882OP0:   SINK← RETN, BUS;   TEST IF UNMASKED
4883OP0A:   L← HINC+T, :STFULL;   ELSE :STMSK
4884OP1:   T← CYCOUT;      OP 1 - SOURCE .OR. DEST
4885   L← MD OR T, :OPN;
4886OP2:   T← CYCOUT;      OP 2 - SOURCE .XOR. DEST
4887   L← MD XOR T, :OPN;
4888OP3:   T← CYCOUT;      OP 3 - (NOT SOURCE) .AND. DEST
4889   L← 0-T-1;
4890   T← LREG;
4891   L← MD AND T, :OPN;
4892OPN:   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;
4899STMSK:   L← MD;
4900   SINK← RETN, BUSODD, TASK;   DETERMINE MASK FROM CALL INDEX
4901   TEMP← L, :STM2;      STACHE DEST WORD IN TEMP
4902STM1:   T←MASK1, :STM3;
4903STM2:   T←MASK2, :STM3;
4904STM3:   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;
4911NB4:   T← MAR← DWAX, :OP0A;   (NORMAL BANK)
4912AB4:   T← XMAR← DWAX, :OP0A;   (ALTERNATE BANK)
4913;
4914;   /* STORE UNMASKED FROM CYCOUT (L=NEXT DWAX)
4915STFULL:   MD← CYCOUT;
4916STFUL1:   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;
4926WIND:   L← T← SKMSK, :AB5;   ENTER HERE (8 INST TO TASK)
4927NB5:   MAR← SWA, :XB5;      (NORMAL BANK)
4928AB5:   XMAR← SWA, :XB5;   (ALTERNATE BANK)
4929XB5:   L← WORD2.T, SH=0;
4930   CYCOUT← L, L← 0-T-1, :NZSK;   CYCOUT← OLD WORD .AND. MSK
4931ZESK:   L← MD, TASK;   ZERO SKEW BYPASSES LOTS
4932   CYCOUT← L, :NOCY;
4933NZSK:   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;
4941DOCY:   CYRET← L LSH 1, L← T, :L0;   CYCLE BY SKEW ***X21.
4942NOCY:   T← SWA, :WIA;   (MAY HAVE OR-17 FROM BUS)
4943CYX2:   T← SWA;
4944WIA:   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
4996KSEC:   MAR← KBLKADR2;
4997KPOQ:   CLRSTAT;   RESET THE STORED DISK ADDRESS
4998   MD←L←ALLONES+1, :GCOM2;   ALSO CLEAR DCB POINTER
4999
5000GETCOM:   MAR←KBLKADR;   GET FIRST DCB POINTER
5001GCOM1:   NOP;
5002   L←MD;
5003GCOM2:   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
5021COMM:   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
5029COMM2:   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
5038INVERT:   L←2 XOR T, TASK, :BADCOMM;
5039NOINVERT: L←T, TASK, :BADCOMM;
5040
5041;   SH=0 MAPS BADCOMM TO COMM3
5042
5043COMM3:   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
5053COMM4:   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
5061COMM5:   MD←KNMAR;   COMPLETE THE WRITE
5062   SH=0,TASK;
5063   :STROB;
5064
5065;   SH=0 MAPS STROB TO CKSECT
5066
5067CKSECT:   T←KNMAR,NFER;
5068   L←KSTAT XOR T, :STALL;
5069
5070;   NFER MAPS STALL TO CKSECT1
5071
5072CKSECT1: CKSUMR←L,XFRDAT;
5073   T←CKSUMR, :KSFINI;
5074
5075;   XFRDAT MAPS KSFINI TO CKSECT2
5076
5077CKSECT2: L←SECTMSK AND T;
5078KSLAST:   BLOCK,SH=0;
5079GASP:   TASK, :IDLE2;
5080
5081;   SH=0 MAPS IDLE2 TO TRANSFER
5082
5083TRANSFER: KCOMM←TOTUWC;   TURN ON THE TRANSFER
5084
5085!1,2,ERRFND,NOERRFND;
5086!1,2,EF1,NEF1;
5087
5088DMPSTAT: 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
5096NOERRFND: T←6;   PICK UP NO-ERROR INTERRUPT WORD
5097
5098INTCOM:   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
5106NEF1:   MAR←DCBR,:GCOM1;   FETCH ADDRESS OF NEXT CONTROL BLOCK
5107
5108ERRFND:   T←7,:INTCOM;   PICK UP ERROR INTERRUPT WORD
5109
5110EF1:   :KSEC;
5111
5112NOCOMM:   L←ALLONES,CLRSTAT,:KSLAST;
5113
5114IDLE1:   L←ALLONES,:KSLAST;
5115
5116IDLE2:   KSTAT←LOW14, :GETCOM;   NO ACTIVITY THIS SECTOR
5117
5118BADCOMM: KSTAT←7;   ILLEGAL COMMAND ONLY NOTED IN KBLK STAT
5119   BLOCK;
5120   TASK,:EF1;
5121
5122WHYNRDY: NFER;
5123STALL:   BLOCK, :STALL2;
5124
5125;   NFER MAPS STALL2 TO GASP
5126
5127STALL2:   TASK;
5128   :DMPSTAT;
5129
5130ILLSEC:   KSTAT←7, :STALL;   ILLEGAL SECTOR SPECIFIED
5131
5132STROB:   CLRSTAT;
5133   L←ALLONES,STROBE,:CKSECT1;
5134
5135KSFINI:   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
5150KWD:   BLOCK,:REC0;
5151
5152;   SH<0 MAPS REC0 TO REC0
5153;   ANYTHING=INIT MAPS REC0 TO KWD
5154
5155REC0:   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
5164REC0RC:   T←MFRRDL,BLOCK, :REC12A;   FIRST RECORD READ DELAY
5165REC0W:   T←MFR0BL,BLOCK, :REC12A;   FIRST RECORD 0'S BLOCK LENGTH
5166
5167REC1:   L←10, INCRECNO;    LENGTH OF RECORD 1
5168   T←4, :REC12;
5169REC2:   L←PAGE1, INCRECNO;    LENGTH OF RECORD 2
5170   T←5, :REC12;
5171REC12:   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
5177RDCK0:   T←MIRRDL, :REC12A;
5178WRT0:   T←MIR0BL, :REC12A;
5179
5180REC12A:   L←MD;
5181   KWDCTW←L, L←T;
5182COM1:   KCOMM← STUWC, :INPREF0;
5183
5184INPREF:   L←CKSUMRW+1, INIT, BLOCK;
5185INPREF0: CKSUMRW←L, SH<0, TASK, :INPREF1;
5186
5187;   INIT MAPS INPREF1 TO KWD
5188
5189INPREF1: KDATA←0, :PREFDONE;
5190
5191;   SH<0 MAPS PREFDONE TO INPREF
5192
5193PREFDONE: T←KNMARW;   COMPUTE TOP OF BLOCK TO TRANSFER
5194KWDX:   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
5201RP0:   KCOMM←STRCWFS,:WP1;
5202
5203CKP0:   L←KWDCTW-1;   ADJUST FINISHING CONDITION BY 1 FOR CHECKING ONLY
5204   KWDCTW←L,:RP0;
5205
5206WP0:   KDATA←ONE;   WRITE THE SYNC PATTERN
5207WP1:   L←KBLKADR,TASK,:RW1;   INITIALIZE THE CHECKSUM AND ENTER XFER LOOP
5208
5209
5210XFLP:   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
5219R0:   T←CKSUMRW,SH=0,BLOCK;
5220   MD←L←KDATA XOR T,TASK,:RW1;
5221
5222;   SH=0 MAPS RW1 TO RW2
5223
5224RW1:   CKSUMRW←L,:XFLP;
5225
5226W0:   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
5232CK0:   T←KDATA,BLOCK,SH=0;
5233   L←MD XOR T,BUS=0,:CK1;
5234
5235;   SH=0 MAPS CK1 TO CK2
5236
5237CK1:   L←CKSUMRW XOR T,SH=0,:CK3;
5238
5239;   BUS=0 MAPS CK3 TO CK4
5240
5241CK3:   TASK,:CKERR;
5242
5243;   SH=0 MAPS CKERR TO CK5
5244
5245CK5:   CKSUMRW←L,:XFLP;
5246
5247CK4:   MAR←KNMARW, :CK6;
5248
5249;   SH=0 MAPS CK6 TO CK6
5250
5251CK6:   CKSUMRW←L,L←0+T;
5252   MTEMP←L,TASK;
5253   MD←MTEMP,:XFLP;
5254
5255CK2:   L←CKSUMRW-T,:R2;
5256
5257;   BUS=0 MAPS R2 TO R2
5258
5259RW2:   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
5268R2:   L←MRPAL, SH=0;   SET READ POSTAMBLE LENGTH, CHECK CKSUM
5269   KCOMM←TOTUWC, :CKSMERR;
5270
5271;   SH=0 MAPS CKSMERR TO PXFLP0
5272
5273W2:   L←MWPAL, TASK;   SET WRITE POSTAMBLE LENGTH
5274   CKSUMRW←L, :PXFLP;
5275
5276CKSMERR: KSTAT←0,:PXFLP0;   0 MEANS CHECKSUM ERROR .. CONTINUE
5277
5278PXFLP:   L←CKSUMRW+1, INIT, BLOCK;
5279PXFLP0:   CKSUMRW←L, TASK, SH=0, :PXFLP1;
5280
5281;   INIT MAPS PXFLP1 TO KWD
5282
5283PXFLP1:   KDATA←0,:PXFLP;
5284
5285;   SH=0 MAPS PXFLP TO PXF2
5286
5287PXF2:   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
5294REC3:   KSTAT←4,:PXFLP;   4 MEANS SUCCESS!!!
5295
5296CKERR:   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
5309PART:   T← 10;
5310   L← ALLONES;      TURN OFF MEMORY INTERRUPTS
5311   MAR← ERRCTRL, :PX1;
5312PR8:   L← SAD, :PX;
5313PR7:   L← PC, :PX;
5314PR6:   L← CBA, :PX;
5315PR5:   L← DWA, :PX;
5316PR4:   L← KNMAR, :PX;
5317PR3:   L← DCBR, :PX;
5318PR2:   L← NWW OR T, TASK;   T CONTAINS 1 AT THIS POINT
5319PR0:   NWW← L, :PART;
5320
5321PX:   MAR← 612+T;
5322PX1:   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
5338MRT:   SINK← MOUSE, BUS;   MOUSE DATA IS ANDED WITH 17B
5339MRTA:   L← T← -2, :TX0;      DISPATCH ON MOUSE CHANGE
5340TX0:   L← T← R37 AND NOT T;   UPDATE REFRESH ADDRESS
5341   T← 3+T+1, SH=0;
5342   L← REFIIMSK ANDT, :DOTIMER;
5343NOTIMER:R37← L;       STORE UPDATED REFRESH ADDRESS
5344TIMERTN:L← REFZERO AND T;
5345   SH=0;         TEST FOR CLOCK TICK
5346   :NOCLK;
5347NOCLK:   MAR← R37;      FIRST FEFRESH CYCLE
5348   L← CURX;
5349   T← 2, SH=0;
5350   MAR← R37 XORT, :DOCUR;  SECOND REFRESH CYCLE
5351NOCUR:   CURDATA← L, TASK;
5352MRTLAST:CURDATA← L, :MRT;
5353
5354DOTIMER: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
5360SPCHK:   SINK←MD, BUS=0, TASK;   CHECK FOR EIA LINE SPACING
5361SPIA:   :NOTIMERINT, CLOCKTEMP←L;
5362
5363NOSPCHK: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
5369TIMERINT: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
5377NOTIMERINT: 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
5403MRT:   MAR← R37;      **FIRST REFRESH CYCLE**
5404   SINK← MOUSE, BUS;   MOUSE DATA IS ANDED WITH 17B
5405MRTA:   L← T← -2, :TX0;      DISPATCH ON MOUSE CHANGE
5406TX0:   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
5409NOTIMER: R37← L;       STORE UPDATED CLOCK
5410NOTIMERINT: 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]
5415NOCLK:   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**
5420NOCUR:   CURDATA← L, TASK;
5421MRTLAST:CURDATA← L, :MRT;   END OF MAIN LOOP
5422
5423DOTIMER: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
5429SPCHK:   SINK← MD, BUS=0, TASK;   CHECK FOR EIA LINE SPACING
5430SPIA:   :NOTIMERINT, CLOCKTEMP← L;
5431
5432NOSPCHK: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
5438TIMERINT: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**************************************************************************************************/
branches/alto2/src/lib/util/unicode.c
r26199r26200
547547   unicode_char* result = (unicode_char *)calloc(sizeof(unicode_char), size + 1);
548548   unicode_char* dst = result;
549549   while (*utf8src) {
550      unicode_char uchar;
550      unicode_char uchar = 0;
551551      int len = uchar_from_utf8(&uchar, utf8src, available);
552552      utf8src += len;
553553      available -= len;
r26199r26200
570570   unicode_char* result = (unicode_char *)calloc(sizeof(unicode_char), size + 1);
571571   unicode_char* dst = result;
572572   while (*utf16src) {
573      unicode_char uchar;
573      unicode_char uchar = 0;
574574      int len = uchar_from_utf16(&uchar, utf16src, available);
575575      utf16src += len;
576576      available -= len;

Previous 199869 Revisions Next


© 1997-2024 The MAME Team