You are on page 1of 607

Block I Apollo Guidance Computer (AGC)

How to build one in your basement


Part 1: Overview
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Why build an AGC?


Early com pute rs are interes ting. B ecau se they re simp le, you ca n (if you like) actu ally understand the entire computer, from hardw are to software. The AGC is the most interesting early computer because: a) it flew the first men to the moon; and b) its the worlds first integrated circuit (IC, or microchip) computer. It also has interesting architectural features.

Original AGC:
Designed by M.I.T. in 1964 World's first microchip computer Prototype computer for Apollo moon landing Memory: 12K fixed (ROM), 1K eraseable (RAM) Clock: 1.024 MHz Com pu ting : 11 instru ction s, 16 bit w ord Logic: ~5 000 ICs (3 -input N OR g ates, RTL logic)

My AGC:
Built from origina l M.I.T. desig n do cum ents Started November 2000, completed October 2004 ~1 5K han d-w rapped wire con nec tion s; ~ 35 00 feet of w ire Cost (parts only): $2,980. Lab or: ~ 25 00 hou rs Logic: ~5 00 ICs (LST TL logic) Runs flight software (1969 program name: COLOSSUS 249)

How did I build it?


I collected orig inal d ocum ents from libraries, tech nical se rvices, an d the in ternet. I had to pay for some (~$350.) Mostly, theyre available for free now. I wrot e an AG C so ftwa re sim ula tion (in C ++ ) an d cross-a ssem bler ( to pro gram it). Th en, I wrote test and ch eckout program s in AGC assem bly langu age to check th e simu lator against specifications in the original do cum ents. I downloaded a big chunk of original flight software from M.I.T. and got it running on my sim ula tor. The simulator was my baseline for logic design. I put my logic design into a circuit design tool (CircuitMaker) which captures schematics and (digitally) simulates circuits. Using CircuitMak er, I unit-tested each A GC su bsystem logic design (the re are about 20 ). Then , I assem bled my subs ystem logic sim ulatio ns into one rea lly hu ge dig ital circuit sim ulatio n of the e ntire AG C an d inte gration -tested this for abo ut 6 m onth s. I eventu ally ran my entire suite of AGC test and checkout software on this circuit simulation. (The simu lation wa s extremely slow , running a t about a 50 0,000 : 1 rate, but very detailed). I boug ht pa rts, mos tly from JAM ECO , and w ire-wra ppe d the e ntire com pute r on 15 circuit boards in my basem ent. I built the relay rack out of 1x2 inch pine boards, rails for shelv ing (c an yo u spo t them ?), plexig lass, screw s, and spray p aint.

Three AGCs
To succeed, I had to b uild the AG C three tim es. Or rather, I had to bu ild three AGC s. Each one is a fully functional computer. Each one is a step toward building the next. The last one is the one I wanted. Heres the faces of my three AG Cs:

AG C # 1: m y C+ + A GC sim ula tor. It has eve ry register an d logic signal in the original doc um entation. I use it to develop and debug AG C assem bly lan gu age cod e. When I got this working, I knew I understood the AGC. I knew I could do the rest of the proje ct.

AG C # 2: m y Circu itMa ker dig ital circuit simulator AGC. What you see here are front panel log ic indicators for signals and registers. The remaining pa rt: about 60 or so pages of logic diagrams; the same schem atics youll see in the CTL, PROC, MEM, and IO .pdf files that follow this overview. This AGC literally runs about a half-million times slower than the first! I used it to debug m y log ic de sign . When I got this working, I knew I still had a yea r (14 m onths, a ctua lly) o f tedio us w ork ahead.

AG C # 3: Th is is the final one. My hardware AGC is built into a relay rack to give it th e sa m e prototyped appearance as the original. The dim ens ions are abo ut 3 x 5 feet. The up per le ft m odu le (CT L) is the control logic. The low er left m odu le (PR OC ) is the CPU. The lower right m odu le (ME M) is the memory. The up per le ft module (IO) has the inputs and outputs. The keyboard and display (DSKY) for use r inp ut a re on th e up perm iddle -right. The white KYNAR wires look like cobwebs to me. This was pho tograp hed in my back yard. Can you see the blue sky and tree branch reflections in the upper panels?

Here I am, plugging COLOSSUS 249 flight software EPRO Ms into Z IF sockets. We lugged the AGC out of the basement and took it ou tdoors for th ese ph otogra phs . Its in the bac kya rd, pro pp ed a gainst the b ack of m y house.

A close-up of COLOSSU S EPROM s. I put red tape over the quartz windows to keep them from erasing th em selves. A b oug ht th e tog gle s wit che s a few years ago from a surplus ven dor. They w ere so cheap, I bought a 100 of them. Arent they great?

I really like flashing ligh ts and con trol panels. There s no wa y to deb ug so m ethin g this co mp lex w ith ou t th em . I bought LED s in bulk from the sam e place that sold m e the switches.

AGC Demonstration
Heres a demonstration of my AGC. Its running my version of the COLOSSUS 249 flight software load:

At power-on, the AGC initializes to major mode 00 (POO ).

Display CM clock:
<VERB> <0> <6> <NOUN> <3> <6> <ENTER> The red buttons were from Radio Shack.

The AGC samples and displays the CM clock. 58 hours, 44 m inutes, 34.27 seconds.

Test display lights:


<VERB> <3> <5> <ENTER>

All D SK Y lam ps an d disp lay seg m ents illu m inate for 5 sec. The Verb and Noun displays flash. After 5 sec, the DSKY lamps extinguish. The 88888 displays are left in the registers.

Load component 1 for dataset at octal address 50 with octal 123:


<VERB> <2> < 1> <NOUN> <0> <1> <ENTER>

Verb/no un disp lay flashes: wa iting for address <5> <0> <ENTER>

Verb/noun display flash continues: waiting for data <1> <2> <3> <ENTER>

Octal word from R1 is loaded into memory at address 50.

Start a monitor program to continuously display elapsed time from the CM clock:
<VERB> <1> < 6> <NOUN> <3> <6> <ENTER>

The m onitor p rogram starts to con tinuo usly display the CM clock, updating the display about about 1 second intervals. The time shown is 58 hours, 47 m inutes, and 23.67 secon ds.

Display component 1 of dataset at octal address 50:


<VERB> <0> < 1> The key rel light flashes beca use the CM clock monitor program has been suspended.

<NOUN> <0> <1> <ENTER> verb/nou n display flashe s: waiting for address

<5> <0> <ENTER>

The o ctal w ord from add ress 50 is displa yed in R1 . In a p revio us o pera tion , we had set th e w ord to 123.

Increment the address:


<NOUN> <1> <5> <ENTER>

The octal word in address 51 is displayed in R1, incremented address in R3. <ENTER>

The octal word in address 52 is displayed in R1, incremented address in R3.

Resume the CM clock monitor program:


<KEY REL>

Verb 16, noun 36 reappears, along with the clock d isplay . The ke y release light g oes ou t. (Im not sure wh y the photos suddenly turned darker; I th ink som eon e m ust h ave turn ed o ff a light in an adjoining room)

Terminate the CM clock monitor program:


<VERB> <3> <4> <ENTER>

Change major mode to P00:


<VERB> <3> <7> <ENTER>

Verb/noun display flashes: waiting for major mod e.

Enter major mode P00: <0> <0> <ENTER>

AGC starts POO.

AGC Project Diary


October - November, 2000: Thinking about building a computer. Decided to reproduce a minicomputer from the 196 0's or 70's. Started gath ering te chn ical doc um enta tion on DEC PDP 8 an d Da ta General NOVA. Found a book in the local library (Ceruzzi, A history of Modern Computing) with a page on the AGC. Decided to build a NASA flight computer; Gemini or Apollo. Gemini interests m e m ore, beca use its the e arlier. Dow nloa ded Tom ayko s Com pute rs in Sp acefligh t. December 2000: My search for Gemini computer documentation on CASI and NTIS is fruitless. IBM federal systems division is gone. Found some interesting AGC docum entation. Asked for, and received, E.C. Halls History of the Apollo Guidance Compu ter for Christm as. January - February 2001: Decided to buld an AGC. Ordered about $300. of technical documents from CASI and NTIS. Discovered you cant judge a documen t by its title. Sent e-mail to Goddard Space Flight Center; got a copy of the AGC Basic Training Ma nua l, a progra m m ers ma nua l for the Bloc k II. Wen t to Com pU SA and bou ght a Microsoft C++ compiler. Starting to build a AGC Block II software simulation. Sent an e-mail to Draper Labs (former MIT Instrumentation Lab where AGC was designed) asking for R-393 (Block I Logic Description). This might be the key doc um ent. Draper respo nd s by sendin g R -39 3 (free !). JAC KPO T! Abandoning Block II simulator. I am building a Block I AGC. March - May 2001: Rap id prog ress on th e Block I simu lation . Wrote an A GC cross-asse m bler in C ++ ; it produces object code readable by the AGC simulator. Generating test code to debug AGC basic instructions. Design ed th e sim ula tor to m ap as clo sely as possib le to th e R- 39 3 hardwa re registers, buses, microinstructions, and control signals. Broke the simulation into 20 sub system s that m ap to A GC hard wa re. I will even tually use th e sim ulato r code to guide my hardware logic design. Finished emulation of all 11 normal and extracode instructions. Wrote my first Block I assembly language program! Starting to simulate the priority counters and interrupts. June - August 2001: Finished v1.0 of the Block I simu lator. Wrote a suite of AGC assem bly langu age test and checkout programs: TECO1 checks basic instructions; TECO2 checks extracode instruc tions; T ECO 3 che cks editin g registe rs. Everyth ing w orks, inclu ding interrup ts and cou nters. Found MIT website with AGC history and interesting online documentation.

E-mailed Eldon Hall, designer of the AGC, telling him about my project. His reply was gracious an d encou raging. W rote man y em ails to others asking for Block I source code. I order a 2.048 MHz crystal from D igiKey. My first hardware purchase. September - October 2001: Cant find any original Block I source code, except tiny fragm ents in the docu me nts. Recoded m y own EXEC , WAITLIST, and interrupt handlers using specifications from R-393 and others. Im starting to become a good AGC programmer. Now my simulator can multitask! Dis cove red B lock II flight softw are (C OLOS SU S 2 49 ) is no w d ow nloadable from MIT . 300+ pages of blurry assembler source code listing. Is that an eight, a six, number zero with a slash th roug h it, or th e lette r O, or m ayb e G? Prin ted a hard cop y. I think I can m ake m ost of it out. The second half of COLOSSUS is missing! The missing part has the INTERBANK COMM UNICATION, EXEC, and WAITLIST. E-mailed MIT. Their reply: they dont have the missing portion. November - December 2001: Tried to reproduce DSKY code using flowcharts from Greens Keyboard and Display System Program. Green calls it PINBALL GAME. Very confusing. Started writing a C+ + sim ula tion from Gree ns flow cha rts. Th ing s are b ecom ing clearer. Loca ted P INB ALL in m y CO LOSS US fragm ent. Abandon ed effort to code m y ow n. I will use the real thing. January - February 2002: Rety ped mo st of CO LOS SU S PIN BA LL ba ck into m achin e-read able form . 95% is alread y Block I instruction s; recode d the rem ainin g 5% into Blo ck I equ ivalen t. Finished all the octal display verbs (1-5) and decimal verb (6) and the load verbs (21- 25), b ut the yre only teste d for octal loa ds so far. No un ta bles are stubb ed, bu t I can manually set them for different scaling. Integrated PINBALL into m y EXEC and W AITLIST. Coded up a few missing pieces for interbank com mu nication. Also ha d to code a m ath library (yikes). But it works. The AGC simulator is running at abou t 1/30 the speed of the original. I need to speed it up. March - May 2002: Bought a new , faster PC. The simu lator now runs at about 1/5 speed. Recoded some simulator pieces. Now its 1:1. Finished PINBALL. All regular verbs (0-39) work. Also, normal nouns 1, 2, 3, 9, 15, 26, an d 36 . Very coo l. My fav orites: verb 16, no un 3 6, a m onitor rou tine to con tinu ous ly displa y the AG C clo ck, an d ve rb 35 wh ich d oes th e lam p tes t. Now that I ha ve som e proficien cy, I am reluctan t to leave A GC softwa re, but its tim e to start hardware logic design.

June - December 2002: Decided to use 74LS logic family. Started designing AGC logic, subsystem-bysubsystem, using the C++ simulator code as my guide. Began with MBF. Posted a subsystem block diagram on the w all. Im coloring in blocks as I finish each subsystem design. Entered logic de sign s into th e Circu itMa ker PC tool. Usin g Circu itMa kers digita l circuit sim u la tio n to u nit-test ea ch su bsy stem . Struggling with ALU and read/write bus design. The original AGC ORed everything onto the bus, and the default bus state was logical zero: sometimes, they read the bu s witho ut w riting to clea r registers. O ther tim es, they w rote m ultip le reg isters sim ulta neo usly to OR the d ata. The se trick s wont w ork w ith tri- state bus driv ers. I identify where tricks are used and add ALU logic to handle the cases. My ALU sort-of feeds back on itself. Confusing, but it should work. Logic design the old way: Karnaugh maps, excitation tables, and bubble-pushing. Fun, sort of. Logic design is now finished, except for the DSKY. Un it tests are done. I start ordering pa rts from JAME CO. Th e first order is for more than 2 00 ICs. January 2003: DSKY logic design is now finished and unit tested in CircuitMaker. All blocks on my dia gram are co lored in. W ill the sub syste m s work to geth er? February - May 2003: Using Circu itM ake r to int egra te su bsy stem s. Dia gram s for each su bsy stem are hooked into CircuitMaker macros; rectangular components with all inputs and outp uts for tha t subs ystem . Wired all sub system ma cros toge ther. W ill it run? I call it AG C2 , to differe ntia te it from the C ++ sim ula tor, w hich I now call A GC 1. Now I have two AG Cs! When I build the hardware, that will make three. Started debugging a TC instruction, the simplest, in AGC2. Worked it through, stepby-step, fixing logic and interface errors. Finally, it works. Debugging the remaining 8 basic instructions. Massive snowstorm; snowed in, 3 days straight. Lots of time for AGC2 debugging and testing. I estim ate m y po wer budg et an d ord er a 1 5A 5V sup ply. Mo re ICs a nd sock ets are ordered, too. Sick of hand-assembling test code for AGC2. W rote a version of the cross-assemb ler that produ ces object code for AGC 2. Broke TECO 1 into 8 pa rts; one for each instruction. One-by-one, I get all portions of TECO1 to run on AGC2. Broke TECO2 and TECO3 into pieces and got them to run on AG C2 also. INTEGRATION TESTING IS DONE! How to build it? There are too m any sub system s and interfaces.

June - August 2003 Grouped the 20 subsystems into 4 assemblies (soon to be called modules): I/O, CTL, PROC, and M EM. This is more manag eable. W rote C+ + cod e that ch ecks th e netlists p rodu ced b y Circu itMa ker for fan-ou t. Esta blish ed a lim it of 8 T TL lo ads, an d ad ded buffers w here necessa ry. Ad ded buffers between the 4 modules to make the fan-in for each module/module interface 1 TTL load. Stuffed IC sockets into 13 circuit boards; each board is 13"x5". What connectors and cables to use between boards? Between modules? Should I worry about bus termina tion? W hat kind of chassis? Decided to build each module as a small relay rack. Board-to-board connections inside each module are wire-wrapped--no connectors. Between modules, 40-pin IDE cab les, m atin g to 3 0-p in w ire-w rap con nec tors, are for m odu le/m odu le interfaces. Too lazy to pull 500 IC sockets and redo the boards. Ill work in connectors and additio nal bu ffers w here I can. B etter b uy the lo ng est ID E cab les (3 feet). M ore w orry about bus termination. Mod ule/Mo dule interfaces are now defined: 6 IDE ca bles. Built a rack for the I/O module out of 1x2 pine boards. Spray-painted gray; it looks pretty g ood. H ired m y eng ineerin g stud ent son to wire-w rap som e I/O m odu le logic during su mm er vacation. He w ires most of the DS KY. It lights up an d m ultiplexes, but operation is erratic; set aside for now. September - December 2003: Built control panels for PROC, CTL, and MEM modules by mounting switches on a woo den frame . Used thick styre ne p lastic for a facep late, ha nd- lettered w ith ind elible marker. It doesnt look too bad. Built indicator light panels for PROC, CTL, and MEM by punching holes in styrene plastic with a push-pin and then shoving LEDs through the plastic into the PCB. Hu nd reds of LED s; m y thum b has a bliste r. Built 3 more relay racks for the PROC, CTL, and MEM modules. Laid all the boards out on the racks. Will the IDE cables reach? Yes, but in some cases, barely. Bought an EPR OM program mer. Learned Motorola S-format. Wrote yet another version of the cross-assembler that outputs S-Record (s2f) format object code. Burned EPRO Ms with TECO 1, TECO2, TECO3, and the A GC flight software. Modified the C++ sim ulator (AGC1) so it dumps its microinstructions (subsystem CPM-A ) in Motorola S-format. Burned EPR OMS for CPM-A . Created a special version of AGC1 that reads CPM-A S-format microinstructions to verify the tables and reads AG C ob ject co de in S-form at to v erify th e cross-as sem bler. January - April 2004 Powered up, and started debugging the partly completed I/O module. Corrected a desig n error a nd a few m ino r wirin g errors; cle an ed up som e cold- solder join ts. It now w orks reliably. Finished wiring the I/O modu le. Its difficult to test, but it seems to work.

May - September 2004 Wired the power connections for all sockets on the CTL module; added a bypassing cap acito r for every 2 p ackages, an d a 1 0u f tant alu m cap acito r for each row of ICs. W ired the LED la m ps an d drive rs, and th en th e logic for ea ch su bsyste m . Plugg ed all the CTL ch ips into the sockets. Dis cove red a ll con trol sig nals from CPM -A w ere in verte d: th e EPRO M ta bles we re generated from AGC 1, which uses positive logic. The hardware AGC uses negative logic, because TTL inputs float high; I wanted floating inputs to assume the inactive state during assembly and test. Pried the EPROMs out of their sockets, bit-flipped the tables, erased and reprogram me d the chips, an d reinserted them . Now it wo rks. Completed wiring for the other modules. Now to hook them up. September - October 2004 Built a large rack to hold the 4 modules. Screwed the 4 modules into the rack and hooked up the IDE cables. Powered it on. Everything lights up. No smoke. Amazing! It runs part of TECO1, getting through dozens of instructions including subroutine calls, before b om bing out. Trying to debug the AGC by burning test EPROMs, single-stepping the clock, and comparing the results to the AGC1 C++ simulator. Its acting flaky. Could it be a su pp ly p ro blem ? Tore out m y flimsy pow er distribution; replaced it with heavy alu min um bus bars. Supply lines look cleaner on the scope, but the operation is just as flaky as before. Ma ybe w orse. Its bom bing out in d ifferent plac es. Is there som e com m on elem ent? Com mon element: the problem always involves read bus m icroinstructions. The ALU sets a default state on the read bus if no other subsystem is using it. My bus arbitratio n sch em e stinks : if a read sig nal is a sserted, th e ALU disab les its defau lt state, but propagation delays cause both drivers to enable simultaneously for a brief period. Is this the problem? I kludg e-in log ic to disab le the rea d bu s durin g CL K1 . This giv es the rea d bu s logic tim e to settle. I add propa gation delay to the C LK1 inpu t to TPG so the b us is disabled before the TPG state transition occurs. Will this fix the problem? No. It gets farth er alon g, bu t still bom bs ou t on read bus o peratio ns. Its time to download internet advice on bus termination. I add 220/330 ohm passive termination to the read bus input in the ALU. IT WORKS!! TECO1 and TECO3 run flawlessly. TECO2 bombs out while testing the DV (divide) instruction. It produces different results than the AGC1 simulator in the tests that involve division by zero. Do I care? I decide I do nt. I load the COLOSSUS EPROMs. The AGC flight software hangs at first; but I add some passive termination to the busy bus driver (for the read bus, of course) and then it works flaw lessly too. The project is finished (except, I have to write up th ese reports!)

AGC Block I Diagram


I constructed this diagram in the first months of my project. It shows the AGC subsystem s as b oxe s. I ga ve them thre e-lette r na m es. M y diag ram is deriv ed from a sim ilar blo ck II diagram I found in R-700. I used th is diag ram to organize my simulator and logic d esign s. But, w hen it became time to build the AGC, I felt this diagram had too m any interfaces; too much complexity. To sim plify thin gs, I g ro up ed th e su bsy stem s from this diagram into 4 mo dules. The KBD, INP, OUT, and DS P su bsy stem s were external interfaces, so I gro up ed the m into an IO module. Ill tell you about it in pa rt 5 of this repo rt. The ADR, MEM, MBF, and PAR subs ystem s dealt w ith m em ory, so they wen t into a MEM modu le (described in part 4). The MO N, CLK, SCL, TPG, SEQ, and CPM subsystems generated the timing and control puls es tha t run all th e other su bsyste m s, so I gathe red the m into a C TL (con trol) m odu le (in part 2). What remained? The ALU, CRG, INT, and CTR subsystems. I put them in a PROC (processing) m odule (pa rt 3).

How my AGC differs from the original


For my purposes, the original AGC is described in a M.I.T. document called R-393 (A. Hopkin s, R. Alonso, and H . Blair-Sm ith, "Logical Description for the Apollo G uidan ce Com puter (AG C4)", R-39 3, MIT Instrum entation Lab oratory, Cam bridge, MA , Mar. 1963 ).

Logic Design
The original AGC4 was built almost entirely from 1964-era 3-input NOR gate ICs; about 5,000 of them. Original gate-level logic designs are not available. Log ic for m y rep lica w as rec reate d using spec ifications in R -39 3, an d arc hite cture information/diagrams from R-700. Since R-39 3 defines (in detail) AGC registers, register tran sfers, m icroin struc tion s, an d m ost co ntrol pu lses (l ogic signals), th e arch itectu re of m y replica clo sely m irrors the origin al to a low level. The logic design for my replica uses late 1960's-early 1970's 74LS TTL logic, which affords about a 10-to-1 reduction in package count. Flip-flop and register chips are used instead of constructing ea ch elem ent from N OR g ates. The replica successfully runs those portions of the original COLOSSUS flight software that hav e been loade d on to it.

Clock
The original AGC4 divided its 2.048 MHz clock down into 4-phase 1.024 MHz signals to drive asynch ronous, level-triggered, register logic. My replica d ivides th e 2.04 8 M Hz clo ck into a 2 ph ased , non- overlap ping 1.02 4 M Hz clo ck to drive synchron ous, edge-triggered register logic. Phase 1 of the clock (CLK1 ) steps a sequ encer (T PG), w hich sets up the con trol signa ls. Those signa ls hav e tim e to prop aga te (settle) between phase 1 and phase 2. Phase 2 (CLK2) clocks the registers using the control signals established in phase 1. Data transfer occurs at phase 2.

Timing Pulses and Control States


The original AGC4 operation was controlled by 12 non-overlapping timing pulses (TP1 TP12) generated from a 4-bit gray code counter. Two SR FFs (called R1 and R2) were used to generate 3 states to control standby operation (STANDBY, POWERON, RUN). R-393 iden tifies a start/stop logic su bsyste m wh ich ga tes the tim e pu lse gen erator to run and halt AGC4 for ground test purposes but the internals were not defined. My control states are integrated into one state machine with 16 states. The 12 timing pulses (TP1 - TP12) are implem ented as states along with 2 add itional states for standby operation (STBY, PWR ON). The remaining 2 states (RLSE, WA IT) handle front panel switch inputs for single stepping.

Interpolation of Gaps in Control Logic


R-393 defines control pulses for TP1-TP11, but does not define control pulses for TP12. Interfaces b etwe en in terrupts, in volun tary cou nters, an d the m ain co ntrol log ic are no t well defined. For this reason, logic in the gaps in R-393 had to be interpolated, based upon functional requ iremen ts.

Number and Address of Involuntary Counters


The number of involuntary counters and their address range is ambiguously defined in R-

393. Table 1-1 in R-393 says AG C4 has 20 (base 10 , I assume) counters. This is supported by Figure 2-5 which numbers counters from 1-20. However, Table 3-1 which shows AGC special registers assigns the cou nters to addresses 00 30 throug h 005 6 (base 8 ) which translates to 23 (base 10) counters. And Table 5-1, section D gives the counter addresses from 00 34 for OVC TR throu gh 00 56 for TRK R R, w hich translates to 19 (base 10 ) counters. So, its unclear whether AGC4 had 19, 20, or 23 counters and whether the counter addresses start at 0030 or 0034. To resolv e the a m bigu ity, I set the startin g ad dress for the coun ters to 34 (octal), w hich is the starting address used in the Block II AGC (COLOS SUS p rogram listing). For convenience, I only im plem ented coun ters that w ere used by the AG C EX EC a nd W AITLIS T, the rea l-tim e clock, and the overflow (5 in all). These are: address 34 35 36 37 40 counter OVCTR TIME2 TIME1 TIME3 TIME4

I also used the Block II ordering of TIME1 and TIME2, for compatibility with the COLOSSUS flight software. In the AGC 4, TIME1 is at the low er address.

Address of Interrupt Vectors and GOPROG


In the Block II AGC, GOPRO G (the starting address for execution) is at the bottom of fixed memory at address 4000, and the interrupt vectors follow at 4004, 4010, 4014, etc. By extension, it would seem that the Block I AGC GO PROG would be at the bottom of fixed memory at 2000, followed by interrupt vectors at 2004, 2010, 2014, etc. However, R-393 has the interrupt vectors starting at the bottom of fixed memory at 2000 (according to the RUPT3 sequence on pages 3-67/3-68). R-393 doesnt identify the address for the Block I GOPROG. For compatibility with the COLOSSU S source code (which I translated and cross-assembled for Block I), I set GOPROG to 2000, with the interrupt vectors beginning at 2004.

Number of Interrupts
The original AGC had 5 vectored interrupts: UPRUPT, ERUPT, KEYRUPT, T3RUPT, and DS RU PT. U PR UP T w as u sed for up link ed co m m ands; E RU PT w as g ene rated wh en h ardwa re errors w ere detected. S ince I didn t plan to us e the se in terrupts, I elim ina ted th e ha rdw are that supports them from my replica. My replica implements the remaining 3 interrupts: KEYRUPT, T3RUPT, and DSRUPT (T4RU PT).

Priority Counter sequences


The o rigina l AGC 4 im plem ented 3 sequ ences : PINC , MINC , and S HINC . PINC in crem ents counter locations in mem ory; MINC decrements them. SHINC implem ents a shift operation used to shift telemetry bits into the AGC. After 16 bits were shifted into an AGC word, an interrupt UPRUPT was triggered, so the AGC could pull the telemetry word out of the cou nter. Since Im not receiving telemetry, I didnt implement the SHINC subsequence or the UPRUPT interrup t.

Memory
AG C m em ory is 16 -bit w ords, orga nized into 10 24 w ord ba nks. Th e low est ban k (ba nk 0 ) is erasable mem ory, originally core, but implemented in my replica as static RAM. All banks abo ve ba nk 0 are fixed m em ory (origin ally im plem ented as rope co re, but im plem ented in my replica as EPROM). AGC4 initially had 12K words of fixed memory. My replica has 15K.

Buses
The original AGC ORed everything onto the bus, and the default bus state was logical zero: Registers were som etimes cleared by reading the default state off the bus. Other tim es, seve ral reg isters w ere sim ulta neo usly read to OR the d ata. Beca use thes e tricks wont w ork well w ith tri-state b us driv ers, I identified th ese insta nces a nd a dde d logic to the A LU to h an dle th em .

Flight Software
The orig ina l Blo ck I fligh t softw are is not a vailable (at leas t, to m e). Th e Blo ck II softw are (CO LOS SU S 24 9) is av ailab le. Block II is an exten sion of th e Block I instruction set. However, most of the Block II software was originally coded as Block I, so translating the Block II code bac k to Blo ck I only in volves chan ging abou t 5% of the instru ctions b ack to their Block I equivalents. This is what I did. Back in 2002, only a portion of the COLO SSUS Block II code was available. Some key portions, such as the EXEC and WAITLIST, were missing. I coded these parts in, using inform ation from th e M.I.T. doc um ents a nd th e interface s and function al requ irem ents implied by their use in the portions of COLOSSU S that were available.

Sources
Many of these sources are now (2004) available (free!) online at http://hrst.mit.edu /hrs/apollo/pu blic/ R. Alonso, J. H. Laning , Jr. and H . Blair-Sm ith, "Preliminary M OD 3 C Program me r's Manual", E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961. Useful information on AGC 4's predecessor: AGC 3. AGC 3 had fewer instructions (8 vs. 11) and a shorter instruction cycle (8 vs 12 timing pu lses). It is primarily helpful for its presentation of AGC B lock I program ming techniques a nd exa mp les. A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964. Flowcharts for DSKY software; no source code. Gives input codes for the DSKY keyboa rd and the output cod es for display characters and registers. E. C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA, Reston VA, 1996. Nice information on the AGC development history with photos; R-700 (also by E.C. Hall) is a better technical summary. E. C . Ha ll, "M IT's R ole in P roject A pollo, V olu m e III, Co m pu ter S ub system ", R-700 , MIT Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972. An excellent overview of the AGC; more technical than Hall's "Journey to the Moon" book. It contains an excellent diagram of the Block II register architecture and a n ice diagram of a bit-slice of the register/bus logic. My copy from N TIS is somewhat poor quality. There is also a useful discussion of the AGC test and checkout software. A. H opkin s, "G uid an ce C om pu ter D esign , Part VI" Extracted from som e (unkn own ) larger docum ent. An excellent overview of the B lock II AGC with emp hasis on the I/O circuits. A very useful discussion of numb er rep rese nta tion an d overflow ha nd ling in th e AGC , wh ich is un con ven tion al. A. Hopkin s, R. Alonso, and H . Blair-Sm ith, "Logical Description for the Apollo G uidan ce Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. My prim ary sou rce. It has a n early com plete spe cification of the A GC 4 (Bloc k I) instruction set, register transfers, and control pulses. Information on the logic design is largely absent, however. There are some internal inconsistencies and gaps in the definition of the control logic: particularly at TP12, in the memory cycle, and at the intersection of the control logic with the interrupts an d involuntary cou nters. Unfortun ately, there are few diagram s; its mostly text and tables. There are also som e exam ples of double-precision m ath routines. B. I. S avag e an d A . Dra ke, "AG C4 Ba sic T rain ing Ma nu al, V olu m e I", E-205 2, M IT Instrumentation Laboratory, Cambridge, MA, Jan. 1967. The software manual for the Block II AGC. It has a fairly complete presentation of the instruction set, but lacks example code.

Now, what?
Theres 8 more parts to this report. Download and read the parts youre interested in. Perhaps you want to build your own A GC. You can use m y software and logic designs, or develop your own. Theres lots of room for improvement in my work. You could use it as your sta rting p oint. If you like, you can contact m e at: agcproject@msn .com

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 2: Control (CTL) Module
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
The Control Module (CTL) has 9 subsystems: CMI, MON, CLK, SCL, TPG, SEQ, CPM-A, CPM -B, CPM -C CMI (Control Module external Interface) The CMI interfaces the other control module subsystems (described below) to external AGC modules. 40-pin IDE connectors interface to the PROC, MEM , and IO modules. Inputs from those modules are buffered to 1 LSTTL load. MO N (A GC M onitor) The monitor subsystem has the front-panel switches that control AGC operation, and also implements the pow er-up reset circuit. CLK (Clock) The AGC is controlled by a 2.048 MHz crystal clock . The cloc k is divid ed to produce a 2-phase, non-overlapping 1.024 MH z AGC system clock for nom inal operation. For test purpo ses, a low-frequency RC clock can also be selected, or the clock can be single-stepped. SCL (Scaler) The 1.024 MHz AGC clock is divided by two to produce a 512 kHz signal called the MASTER FREQUENC Y; this signal is further divided through a SCALER, first by five to produce a 102.4 kHz signal. This is then divided by two through 17 successive stages called F1 (51.2 kH z) through F17 (0.78 125 H z). The F10 stage (100 Hz) is fed back into the AGC to increment the real-time clock and other priority counters in the PROC module. The F17 stage is used to intermittently run the AGC when it operates in the STANDBY mode. TPG (Tim e Pu lse Gen erator) AGC instructions are implemented in groups of 12 steps, called timing pulses. The timing pulses, named TP1 through TP12, are produced by the Time Pulse Generator (TPG). Each set of 12 timing pulses is called an instruction subsequence. Simple instructions, such as TC, execute in a single subsequence of 12 pulses. More complex instructions require several subseq uences. SEQ (Seq uen ce Ge nerato r) The sequence generator has the SQ register, which holds the next op-code, and the CTR

register--a counter used to count instruction subsequences during multiplication. The sequence generator also has the branch register (BR) which controls conditional processing during instruction execution, and the STAGE registers (STA and STB) which select the instruction subsequences for complex instructions that have more than one subsequ ence. CPM-A (Control Pulse Matrix A) The CPM-A is the com bina tiona l logic matrix that imp lemen ts most of the control logic. It is driven by inputs from the SQ register (which selects the instruction), the STB stage register (which selects the instruction subsequence), and the BR branch register (which selects conditional steps in a subseq uence). CPM-B (Control Pulse Matrix B) The CP M-B decodes read and write control signals for special me mo ry location associated w ith input/ou tput registers, central registers (A, Q, Z, and LP), and the editing registers used for rotation and shifting. CPM-C (Control Pulse Matrix C) The CPM -C decodes control signals primarily associated with interrupts, the mem ory cycle, and th e selection of new instruction s and instruction subsequ ences.

This is a functiona l diagram show ing the interrelationsh ips betwe en the Tim e Pulse Gen erator (TP G), the Con trol Pulse Ma trix (CPM -A, B, an d C), a nd th e registers th at are in the Sequ ence Generator (SE Q). The d iagram is m ine, bu t the style is borrowed from original AGC documentation: con trol sig nals are represented by diamonds. The arrows show the direction of data flow. When a control signal is asserted, data is allow ed to flow through the diamon d. For example, when WSQ is asserted, the opcode is written from th e Rea d/W rite bus into the SQ regis ter. Registers (LOOPC TR, STA, STB, SQ, BR, and SN I) are represented by rectangles. The lower bit of the 2-bit STA register is set by ST1. The upper bit is set by any one of the 3 control signals flowing into it. The STA register is cleared by CLRSTA. Wh en W STB is asserted, the S TA register is copied to STB . STB an d the SQ register select the instruction subsequence. The instruction subsequence, time pulse generator, BR register, and SNI all feed into the Control Pulse M atrix to select the active control pulses. The diag ram w as develope d by an alyzing th e R-39 3 docum ent. It was one of m y first diagrams; a sort-of conceptual breakthrough that became my gateway for understanding the AGC control modu le.

The instruction subsequences executed by the AGC are shown in this diagram. Each yellow circle is a subseq uence; a set of 12 steps, with each step generating 0-5 control pulses. Eleven steps (TP 1-T P11 ) are in the yellow circle; the 12 th step, which selects the next subseq uence (TP12), is in the orange circle. This is discussed in m ore deta il in the TPG, SEQ, and C PM-A subsystem s.

A late a dditio n to the CTL d esign fixed a p roblem with the read bus lo gic. Du e to propa gation delay s (and som e poor d esign on m y part), th e tri-state bu ffers from m ultiple registers were simultaneously enabled for brief periods causing some transients. I kludged in a design change that suppressed output to the read bus during CLK1, thereby giving the bus control logic time to settle.

CTL Internal Subsystem Interconnections


This diagram show s internal interconnections for the subsystems in the CTL module.

CTL Module External Interfaces


The CTL m odule interfaces to the PROC, MEM, and IO m odules through 40-pin IDE ribbon cables.

J100-CTL: CTL-to-PROC I/F J100 is a 40-pin IDE ribbon cable that connects the CTL m odule to the PROC m odule. OUT PUTS (from CTL): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 signal WA3 WA2 WA1 WA0 RA3 RA2 RA1 RA0 WZ WYx WY WX WQ WOVR WOVI WOVC WLP WB WA LP WA F10X R24 R22 R2 R1C R1 RZ RU RSCT RSB RRPA RQ RLP RC RB14 RB RA KRPT CI fu ll n am e WRITE ADDR 3 (74) WRITE ADDR 2 (73) WRITE ADDR 1 (72) WRITE ADDR 0 (71) READ ADDR 3 (60) READ ADDR 2 (59) READ ADDR 1 (58) READ ADDR 0 (57) WRITE Z (50) WRITE Y NO RESET (49) WRITE Y (48) WRITE X (47) WRITE Q (45) WRITE OVF (41) WRITE OVF RUPT INH (40) WRITE OVF CNTR (39) WRITE LP (38) WRITE B (36) WRITE A/LP (35) WRITE A (34) F10 SCALER ONESHOT READ 24 (25) READ 22 (24) READ 2 (23) READ 1 COMP (22) READ 1 (21) READ Z (20) READ U (19) READ CNTR ADDR (18) READ SIGN (17) READ RUPT ADDR (16) READ Q (15) READ LP (13) READ C (11) READ BIT 14 (10) READ B (9) READ A (8) KNOCK DOW N RUPT (6) SET CARRY IN (1) state definition 0=W rite reg at address 3 (LP) 0=Write reg at address 2 (Z) 0=Write reg at address 1 (Q) 0=Write reg at address 0 (A) 0=Read reg at address 3 (LP) 0=Read reg at address 2 (Z) 0=Read reg at address 1 (Q) 0=Read reg at address 0 (A) 0=W rite Z 0= W rite Y (do n ot reset) 0=W rite Y 0=W rite X 0=W rite Q 0=W rite overflow 0= W rite overflow RU PT inh ibit 0=W rite overflow counter 0=W rite LP 0=W rite B 0=W rite A and LP 0=W rite A 1=timed out (100.0 Hz) 0=Read 24 0=Read 22 0=Read 2 0=R ead 1 comp limented 0=Read 1 0=Read Z 0=Read sum 0=R ead selected cou nter address 0= Rea d sign bit 0=R ead RU PT add ress 0=Read Q 0=R ead LP 0=Read C 0=Read bit 14 0=Read B 0=Read A 0= Kn ock do wn Rup t priority 0= Carry in

J101-CTL: CTL-to-PROC I/F J101 is a 40-pin IDE ribbon cable that connects the CTL m odule to the PROC m odule.

INPU TS (to CTL ): PIN 21 22 23 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 signal SB_01 SB_02 IRQ WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e SUB SEL 01 SUB SEL 02 INT RQST WRITE BUS 01 WRITE BUS 02 WRITE BUS 03 WRITE BUS 04 WRITE BUS 05 WRITE BUS 06 WRITE BUS 07 WRITE BUS 08 WRITE BUS 09 WRITE BUS 10 WRITE BUS 11 WRITE BUS 12 WRITE BUS 13 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16 state definition SB_01 is LSB; SB_02 is MSB 00=no counter; 01=PINC; 10=MINC 0=interrupt requested. (lsb)

US (overflow ) bit SG (sign ) bit

OUT PUTS (from CTL): PIN 1 2 3 4 5 6 7 8 19 20 signal R2000 WPCTR RPT INH CLRP CLINH1 CLINH GENRST CLK1 CLK2 fu ll n am e READ 2000 (101) WRITE PCTR (98) READ RUPT (94) SET INHINT (93) CLEAR RPCELL (92) CLEAR INHINT1 (88) CLEAR INHINT (87) GENERAL RESET (86) CLOCK1 CLOCK2 state definition 0=Read 2000 0=W rite PCTR (latch priority counter sequence) 0=Read RUPT opcode 0=Set INHINT 0=Clear RPCE LL 0=Clear INHINT1 0=Clear INHINT 0=G eneral Reset 1.024 MHz AGC clock 1 (normally low) 1.024 MHz AGC clock 2 (normally low)

J102-CTL: CTL-to-MEM I/F J102 is a 40-pin IDE ribbon cable that connects the CTL m odule to the MEM m odule.

INPU TS (to CTL ): PIN 31 32 33 34 35 36 37 38 38 40 signal EQU_16 EQU_17 GTR_17 EQU_25 GTR_27 GTR_1777 AD_1 AD_2 AD_3 AD_4 fu ll n am e ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS state definition 0=CADR in register S = 016 0=CADR in register S = 017 0=CADR in register S > 017 0=CADR in register S = 025 0=CADR in register S > 027 0=CADR in register S > 01777 where AD_4 is MSB, AD_1 is LSB: (low-order bits of address)

= 016 (1) = 017 (2) > 017 (3) = 025 (4) > 027 (5) > 01777 (6) (1) (2) (3) (4)

OUT PUTS (from CTL): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 signal WE S BW G GENRST W23 W22 W21 W20 WGn WBK RBK WS WP2 WPx WP WGx TP RP2 RG GP CLG CLK2 CLK1 NPURST SW CLK FCLK fu ll n am e WRITE EMEM (97) WRITE G (95) GENERAL RESET (86) WRITE ADDR 23 (85) WRITE ADDR 22 (84) WRITE ADDR 21 (83) WRITE ADDR 20 (82) WRITE G NORMAL (81) WRITE BNK (80) READ BNK (70) WRITE S (46) WRITE P2 (44) WRITE P NO RESET (43) WRITE P (42) WRITE G NO RESET (37) TEST PARITY (30) READ PARITY 2 (14) READ G (12) GEN PARITY (5) CLR G (2) CLOCK2 CLOCK1 POWER U P RESET DEBOUNCE CLOCK CLOCK MODE state definition 0=W rite E-MEM from G 0= W rite G from m em ory 0=G eneral Reset 0=Write into SL 0=W rite into CYL 0=Write into SR 0=W rite into CYR 0=W rite G (norm al gates) 0=W rite BNK reg 0=R ead BNK reg 0=W rite S 0=W rite P2 0= W rite P (do n ot reset) 0=W rite P 0= W rite G (do not reset) 0= Test pa rity 0=Read parity 2 0=Read G 0= Gen erate Pa rity 0= Clear G 1.024 MHz AGC clock 2 (normally low) 1.024 MHz AGC clock 1 (normally low) 0=reset, 1=normal operation. low freq clk for switch debou nce 1= free-runn ing clk mo de; 0= sing le clk mode

J103-CTL: CTL-to-I/O I/F J100 is a 40-pin IDE ribbon cable that connects the CTL m odule to the I/O m odule.

INPU TS (to CTL ): PIN 40 signal OUT1_8 fu ll n am e STANDBY ENA BLED state definition 1=standby enabled; works with STANDBY ALLOW ED sw itch

OUT PUTS (from CTL): PIN 1 2 3 5 6 7 8 9 20 signal CLK1 CLK2 NSA GENRST WA11 WA10 RA11 RA4 STBY fu ll n am e CLOCK1 CLOCK2 STANDBY ALLOW ED GENERAL RESET (86) WRITE OUT1 (76) WRITE OUT0 (75) READ OUT1 (66) READ IN0 (61) STANDBY state definition 1.024 MHz AGC clock 1 (normally low) 1.024 MHz AGC clock 2 (normally low) 0=standb y allowed 0=clear the DSKY, OUT1, and OUT2. 0=write into OUT1 from write bus 0=write into OUT0 (DSKY) from write bus 0=output OUT1 register to read bus 0=output IN0 register to read bus 0= AG C is in th e stan dby state

MON (AGC Monitor)


MON INPUTS:
I/F signal SW-RUN NSW-RUN SW-INS NSW-INS SW-FCL NSW-FCL SW-SA NSW-SA SW-STP NSW -STP SW-MCL NSW-MCL SW-RST fu ll n am e RUN/STEP SELECT SW state definition

STEP MODE SW

CLOCK MODE SW

STANDBY ALLOWED SW

INST STEP SW

CLOCK STEP SW

MASTER RESET SW

MON OUTPUTS:
signal NRUN INST NSTEP NSA MCLK FCLK NPURST SENAB fu ll n am e RUN /HALT INST STEP MODE SINGLE STEP STANDBY ALLOW ED CLOCK STEP CLOCK MODE POWER U P RESET SCALER ENABLE state definition 0=run, 1= step 1=instruction step, 0=sequen ce step 0=step (momentary) 0=standb y allowed 1= step (m om enta ry); trigge rs a sing le clock pulse. Ignored if FCLK is 1. 1=continuous clock output at 1.024 MHz, 0=sin gle clock 0=reset, 1=normal operation. 1= ena ble cou nting ; 0= hold

CTL CONTROL PANEL SWITCHES

Clo ck Co ntrol: RATE Controls the slow clock rate when the 1MHZ/SLOW switch is in the SLOW position. Selects the free-running clock rate when the RUN/STEP switch is in the RUN position. The 1M HZ po sition gates a 2M Hz signa l into the 2-ph ased clock which produces a 1M Hz 2-phased clock rate. The SLOW position gates a low frequency clock; the frequency is controlled by RATE. Selects a free-running (RUN) or a single-stepped (STEP) clock. In the RUN position, the rate is controlled by the 1MHZ/SLOW switch. In the STEP position, the clock steps each time the STEP button is depressed. Manually steps the clock when the RUN/STEP switch is in the STEP position. The clock is 2-phased, so each press steps an alternate phase.

1MHZ/SLOW

RUN/STEP

STEP

Scaler: ENAB/DISAB F10 F13 F17 Enables or disables the SCALER. Manually triggers the F10 stage of the SCALER. Manually triggers the F13 stage of the SCALER. Manually triggers the F17 stage of the SCALER.

Ex ec ution Co ntrol: RUN/STEP In the RU N position, the A GC free-runs at a rate determ ined by th e clock controls. In the STEP position, the AGC single-steps to the next instruction or next sequence when the STEP button is depressed; the rate is determined by the clock controls. Selects whether the AGC single-steps all the way to the next instruction (INST) or just to the next sequence (SEQ). Some instructions, such as TC, have a sin gle sequen ce; on these instructions, the sw itch has the sam e effect in either position. Single-steps the AGC when the RUN/STEP switch is in the STEP position. Reset the entire AGC. Puts the TPG into the standby state.

INST/SEQ

STEP RESET

Standby: ALLOW/DISA The ALLOWED position authorizes the AGC software to put the AGC in standby mode. The AGC is released from standby mode by a signal from F17 in the SCALER. If the scaler switch is in the DISAB position, the scaler is disabled, and the A GC will rem ain in the stan dby state. W hen the stan dby switch is in the DISAB position, the standby mode is inhibited.

Normal Operation: Set the following switch positions for nominal operation: switch 1MHZ/SLOW RUN/STEP ENAB/DISAB RUN/STEP ALLOW/DISA position 1MHZ RU N (cloc k contro l) EN AB (scaler) RU N (ex ecution control) ALLOWED (standby)

CTL CONTROL SWITCH CONNECTIONS


PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 signal BUS# 10, line 1 BUS# 10, line 2 BUS# 10, line 3 BUS# 10, line 4 BUS# 10, line 5 BUS# 10, line 6 BUS# 10, line 7 BUS# 10, line 8 BUS# 10, line 9 BUS#10, line 10 BUS#10, line 11 BUS#10, line 12 BUS#10, line 13 BUS#10, line 14 RATE 1MHZ SLOW F10 F13 F17 state definition Execution control: RUN/STEP

Execution control: INST/SEQ

Clock control: RUN/STEP

STANDBY ALLOW ED/DISABLED

Execution control: STEP

Clock control: STEP

RESET SCALER DISAB (SLOW) CLOCK CO NTROL RATE Clock control: 1MHZ/SLOW

MANUAL TRIGGER F10 MANUAL TRIGGER F13 MANUAL TRIGGER F17

CTL INDICATORS
The CTL module has a panel of indicator lamps (LEDs) to show the state of CTL registers and critical logic signals. These indicator lamps show the curren t state of all registers and some add itiona l, im portan t logic signals produced by the CTL mod ule. The matrix of lamps in the lower portion show active subseq uences. M uch of the con trol logic is negative (active low) where an illu m in ated la m p means that the signal is NOT asserted. At the time the photo was taken the AGC was running the COLOSSUS 249 flight software load, executing Verb 16, Noun 36: a monitor verb which displays the AGC real time clock.

CLK (Clock)
The original AGC used asynchronous logic driven by a 4-phase clock. This recreation uses synchronous logic driven by a 2-phase nonoverlap ping clock. Th e sync hron ous clo ck logic wa s desig ned to produ ce the follow ing sta te transitions: FFA 0 0 1 1 FFB 0 1 1 0

idle state decoded for phase 1 decoded for phase 2

The outputs of FFA and FFB are decoded by combinational logic to produce the nonoverlappin g pha se 1 and phase 2 clock signals. The se que nce is a rrang ed so th ere is a sing le logic lev el transitio n for each state tran sition to prevent transients.

CLK INPUTS:
I/F signal MON: MCLK FCLK NPURST fu ll n am e CLOCK STEP CLOCK MODE POWER U P RESET state definition 1= step (m om enta ry); trigge rs a sing le clock pulse. Ignored if FCLK is 1. 1= con tinu ous clock outp ut at 1.024 MH z, 0=single clock whenever MCLK is 1. 0=pow er up reset

OUTPUTS:
signal CLK1 CLK2 fu ll n am e CLOCK1 CLOCK2 state definition 1.024 MHz AGC clock 1 (normally low) 1.024 MHz AGC clock 2 (normally low)

SCL (Scaler)
The 1 .024 MH z AG C clock is divided by two to produce a 512 kHz signal called the MA STE R FR EQU ENC Y; this signal is further divided through a SCALER, first by five to produce a 102.4 kHz signal. This is then divided by two through 17 successive stages called F1 (51.2 kHz) through F17 (0.78125 Hz). The F10 stage (100 Hz) is fed back into the AGC to increment the real-time clock and other priority counters in the PROC m odu le. The F 17 sta ge is used to intermittently run the A GC wh en it op erates in the STAND BY m ode. The F10, F13, and F17 outputs of the SCALER feed into a synchronous one-shot that produces a short output pulse on the rising edge of the in put.

SCALER (SCL) ONE-SHOT LOGIC DESIGN Boolean operators: * (AN D), + (OR ), ' (NOT) Scale r Divid e-by- 10 E xcitation Table : The divide-by-10 state machine is implemented with a 74161 parallel counter. Control Mode for 74 16 1 Pa rallel Cou nter: NPE 0 1 1 CET x 1 0

LOAD COUNT HOLD

State 0 1 2 3 4 5 6 7 8 9

Current D C B A 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 0 1

Next D C B A 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0

NPE 1 1 1 1 1 1 1 1 1 0

Par In CET D C B A 1 1 1 1 1 1 1 1 1 x 0 0 0 0

NPE = (D * A)' CET = 1

On e-sho t Excitatio n Ta ble: The on e-shot state m achine is im plem ented w ith two J-K F Fs.

JK flip-flop excitation table: J K 0 0 Qn-1 (no chan ge) 0 1 0 1 0 1 1 1 Qn-1' (toggle)

FN is th e one -shot trig ger; Q (A) is th e one -shot o utpu t. Cur B A 0 0 0 0 Inp FN 0 1 Nxt B A 0 0 0 1 ffB J K 0 x 0 x ffA J K 0 x 1 x

State IDLE

HIGH

0 1 0 1 1 0 1 0 1 1 1 1

0 1 0 1 0 1

1 0 1 0 0 0 1 0 x x x x

1 x 1 x x 1 x 0 x x x x

x 1 x 1 0 x 0 x x x x x

LOW

UNUSED

The e xcitation table a nd lo gic eq uatio ns w ere derive d from the CL K su bsyste m state machine which also performs a one-shot function. The CLK subsystems's FCLK signal was factored out by setting it to zero. The MCLK input is the one-shot trigger; it was renamed FN. ff(B) J = QA ff(B) K = FN' ff(A) J = QB' * FN ff(A) K = QA

SCL INPUTS:
I/F CLK: signal CLK1 MON: SW-SEN 0= hold NPURST POWER U P RESET 0=pow er up reset SCALER ENABLE 1=enable counting; fu ll n am e CLOCK1 state definition 1.024 M Hz AG C clock

SCL OUTPUTS:
signal F10X F13X F17X fu ll n am e F10 SCALER ONESHOT F13 SCALER ONESHOT F17 SCALER ONESHOT Hz) SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER SCALER OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT OUT F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 state definition 1=timed out (100.0 Hz) 1=timed out ( 12.5 Hz) 1=timed out ( 0.78125

F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17

51.2 KHz square wave 25.6 KHz square wave 12.8 KHz square wave 6,4 KHz square wave 3.2 KHz square wave 1.6 KHz square wave 0.8 KHz square wave 0.4 KHz square wave 0.2 KHz square wave 0.1 KHz square wave (100 Hz) 50.0 Hz square wave 25.0 Hz square wave 12.5 Hz square wave 6.25 Hz square wave 3.125 Hz square wave 1.5625 Hz square wave 0.78125 Hz square wave

Note: One shot outputs are active for one clock pulse. State transitions occur on the rising edge of CLK1

TPG (Time Pulse Generator)

TIME PULSE GENERATOR (TPG) LOGIC DESIGN


Boolean operators: * (AN D), + (OR ), ' (NOT) TPG Interna l Con trol Sign als: Thes e are loca l to the TP G; if the sig nal is d, TPG m akes a state transition. These signals are the inputs to the excitation TPG_0 = PURST' * ( FCLK' + F17X ) TPG_1 = FCLK' + F13X TPG_2 = RUN + (SNI' * INST) TPG_3 = SNI * OUT1_8 * SA TPG_4 = STEP'

asserte decoded table.

TPG_5 = STEP + RUN TPG Excitatio n Ta ble: Con trol M ode for 74 16 1 Pa rallel Cou nter: NPE 0 1 1 CET x 1 0

LOAD COUNT HOLD

*denotes active low Current D C B A 0 0 0 0 *Current Decoder NSTBY TPG_x 0 1 2 3 4 5 0 x x x x x 1 x x x x x x 0 x x x x x 1 x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x Next D C B A 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 Par In D C B A

State STBY

*NPE 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

CET 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1

PWRON0 0 0 1

NPWRON

TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

0 0 0 0 0 0 1 1 1 1 1

0 0 1 1 1 1 0 0 0 0 1

1 1 0 0 1 1 0 0 1 1 0

0 1 0 1 0 1 0 1 0 1 0

NTP1 NTP2 NTP3 NTP4 NTP5 NTP6 NTP7 NTP8 NTP9 NTP10 NTP11

TP12

1 1 0 1

NTP12

x x x 1 x x x x 1 0 x x x x 0 0 x x x x x x 0 x x x x x 1 x x x x x x 1 x x x x x 0

0 0 0 0 0 0 1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 0 1 0 1 1 1 1

0 0 1 1 1 0 1

x x 1 0 1 x 0

0 0 0 0 0 0 1 0

SRLSE 1 1 1 0

NSRLSE

W AIT

1 1 1 1

NW AIT

0 0 1 0

M ax term s: NP E = (NTP 12 + TPG_ 3') * (NT P1 2 + TPG_ 2' + TPG_ 3) * (NW AIT + TPG_ 5') CET = (NSTBY + TPG_0) * (NPWRON + TPG_1) * (NSRLSE + TPG_4) * (NWAIT + TPG_5)

Par In A,B,C = 0 Par In B = (N TP12 ' * TPG_3 )'

TPG INPUTS:
I/F signal MON: NRUN INST 0=sequen ce step NSTEP FCLK NSA NPURST CLK: CLK1 SEQ: SNI SCL: F17X F13X OUT: OUT1_8 STANDBY ENA BLED 1=standby enabled; works with STANDBY ALLOW ED sw itch F17 SCALER ONESHOT F13 SCALER ONESHOT 1=timed out 1=timed out SELECT NEXT INST 1=select next instruction CLOCK1 1024 MHz AGC clock 1 fu ll n am e RUN /HALT INST STEP MODE SINGLE STEP CLOCK MODE STANDBY ALLOW ED POWER U P RESET state definition 0=run, 1= step 1=instruction step, 0=step (momentary) 1= contin uou s, 0= sing le clock 0=standb y allowed 0=pow er up reset

TPG OUTPUTS:
signal TPG_Q3 TPG_Q2 TPG_Q1 TPG_Q0 fu ll n am e TPG STATE state definition where Q0 is LSB, Q3 is MSB: 00 = STBY 01 = PWRON 02 = TP1 03 = TP2 04 = TP3 05 = TP4 06 = TP5 07 = TP6 08 = TP7 09 = TP8 10 = TP9 11 = TP10 12 = TP11 13 = TP12 14 = SRLSE 15 = W AIT

SEQ (Sequence Generator)


The se que nce g enera tor conta ins the stage reg isters and bran ch regis ters that (a long with the time pulse generator) control execution of the microinstruction sequence.

Som e back-of-the-en velope desig n that w ent into the bran ch register logic is shown in the next few charts. This is the conceptual design for the branch register. It has 2 flip-flops nam ed B R2 and BR1 . The flip-flop s are set by the con trol signa ls shown as diamonds in this diagram.

The J and K inputs to the BR1 flip-flo p are deve loped in this chart.

This chart shows the J an d K in puts to the BR2 flip-flop. Logic to sen se a 1's compliment minus zero from the w rite bus is also developed.

Here are some charts showing the stage register design. This is the conceptual design. Th ere are (2) 2-bit stage registers: ST A and STB .

This is my initial cut at STA and ST B. My initial attempt at CLSTB is scratched out and then developed into the correct solution on the later charts.

This is the J input to the STA2 flipflop. The initial design is at the top. In the m idd le, I D eM org an iz e it u sin g so me bubble-pushing to get the final im p lem en ta tio n a t th e b otto m.

Heres the J and K inp uts to STB1 and STB2. This is the logic that transfers the contents of the STA flipflops to STB.

The J a nd K inpu ts to STB 1 an d ST B2 m ove th roug h a m ulti-step DeM organ izing process in the next 2 charts to reach their final state:

SEQ INPUTS:
I/F CLK: signal CLK2 CPM-C: GENRST WSQ CLISQ CLSTA WSTB CLSTB SETSTB CPM-A: TRSM TSGN TSGN2 ST1 ST2 CLCTR CTR TMZ TOV NISQ fu ll n am e CLOCK 2 state definition data transfer occurs on falling edge

GENERAL RESET WRITE SQ CLEAR SNI CLEAR STA WRITE STB CLEAR STB SET ST1

0=G eneral Reset 0=Write SQ 0=Clear SNI 0= Clear sta te cou nter A (STA) 0= W rite sta ge co un ter B (STB) 0= Clear sta te cou nter B (STB) 0=Set the ST1 bit of STB

TEST RESUME TEST SIGN TEST SIGN 2 SET STAGE 1 SET STAGE 2 CLR LOOP CTR INCR LOOP CTR TEST MINUS ZERO TEST OVF NEW INSTRUCT SQ reg

0=Test for resume 0=Test sign 0=Test sign 2 0=Stag e 1 0=Stag e 2 0=Clear loop counter 0=Loop coun ter 0= Test for m inu s zero 0=Test for overflow 0=New instruction to the

WBUS: WB_01 ... ... WB_14 WB_15 WB_16 ADR: EQU_25 ADDRESS = 025 0=CADR in register S evaluates to = 025 WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16

US (overflow) bit for write bus SG (sign) bit for write bus

SEQ OUTPUTS:
I/F signal CPM-A: BR1 BR2 fu ll n am e BRANCH REG 1 BRANCH REG 2 state definition where BR00 BR01 BR10 BR11 BR1 =0 =1 =2 =3 is MSB, BR1=0, BR1=0, BR1=1, BR1=1, BR2 is LSB BR2=0 BR2=1 BR2=0 BR2=1

SQ_3 SQ_2 SQ_1 SQ_0 STB_1 STB_0 LOOP6 SNI

INST REG

where SQ_3 is MSB, SQ_0 is LSB

STAGE REG

where STB_1 is MSB, STB_0 is LSB

LOOPCNTR EQ 6 SELECT NEXT INST

0=LOOPCNTR is holding the number 6. 1= selec t nex t instruction ( SN I register)

CPM-A (Control Pulse Matrix A)


In th is AG C rep lica, th e CP M- A su bsequ enc es are im plem ented in EPR OM (the y w ere implem ented as a diode matrix in the original). The address into the EPROM is constructed as follows (bit 1 is the LSB ): bit 13,14 9-12: 7,8: 3-6: 2: 1:

CTR subsequence (2) register SQ (4) register STB (2) register SG (4) register BR1 (1) register BR2 (1)

Bits 7-14 (STB, SQ, and CTR ) select the instruction subsequence. Bits 1-6 select the control pulses (control logic signals) that are asserted from that subsequ ence.

SELECTING THE INSTRUCTION SUBSEQUENCE


The 11 AG C in struc tion s, priority coun ter op eratio ns, a nd interrup t ope rations a re im plem ented in 22 instructio n sub sequ ences . Som e instru ctions (T C) h ave a single subseq uence; oth ers have several sub sequen ces. The instruction subsequence is choosen by CTR, SQ, and STB. These form bits 7-14 of the CPM -A EPR OM address.

CTR (EPROM address bits 13-14) The CTR signal has 2 lines: SB_02 is the MSB; SB_01 is the LSB. The signal comes from the CTR subs ystem in the P RO C m odu le. It indicate s wh ether p rocessin g ne eds to b e briefly interrup ted to in sert a PINC or MIN C su bseq uen ce to increm ent or d ecrem ent a p riority cou nter. CTR00: SB_02=0, SB_01=0 no coun ter; do the next sub sequen ce CTR01: SB_02=0, SB_01=1 PINC CTR10: SB_02=1, SB_01=0 MINC CTR11: SB_02=1, SB_01=1 both; they cancel out, so do the next subseq uence

Register SQ (EPROM address bits 9-12) The 4-bit SQ register holds the currently executing instruction. The code in the SQ register is the sam e as the op cod e for these four instructions. NMEM TC CCS INDEX XCH SQ REG 00 01 02 03 OPCODE 00 01 02 03 USAGE TC K CCS K INDEX K XCH K DESCRIPTION CYCLES Transfer Control 1 MCT Count, Compare, Skip 2 MCT Index 2 MCT Exchange 2 MCT

The SQ register code for these four instructions is the op code + 010 (octal). This happens because all of these instructions have bit 15 set (the sign (SG) bit) while in mem ory. When

the instruction is copied from memory to the memory buffer register (G) to register B, the SG bit moves from bit 15 to bit 16 and the sign is copied back into bit 15 (US). Therefore, the CS op code (04) becomes (14), and so on. NMEM CS TS AD MASK SQ REG 014 015 016 017 OPCODE 04 05 06 07 USAGE CS K TS K AD K MASK K DESCRIPTION Clear and Subtract Transfer to Storage Add Bitwise AND CYCLES 2 MCT 2 MCT 2 or 3 MCT 2 MCT

These are the three extended instructions. They are accessed by executing an INDEX 5777 before each instruction. By convention, address 5777 contains 47777. The INDEX instruction adds 47777 to the extended instruction to form the SQ op code. For example, the INDEX adds 4 to the 4 op code for MP to produce the 11 (octal; the addition generates an end-arou nd-carry). SQ reg ister code (the 7777 part is a negative zero). NMEM MP DV SU SQ REG 011 012 013 OPCODE 04 05 06 USAGE MP K DV K SU K DESCRIPTION Multiply Divide Subtract CYCLES 10 MCT 18 MCT 4 or 5 MCT

STB (EPROM address bits 7-8) The stage register B (STB) selects the subsequence for a given instruction. Some instructions have m ultiple subsequences; others (TC) have only one. The sta ge reg ister has 2 bits: ST B2 is th e MS B; S TB1 is the LS B. All in struction s initiallly begin with the stage register set to zero. If an instruction needs more than one subsequ ence, the stage register is incremented to select the next subsequence. STB00: STB2=0, STB1=0 STB01: STB2=0, STB1=1 STB10: STB2=1, STB1=0 STB11: STB2=1, STB1=1

INSTRUCTION SUBSEQUENCES
There are 22 in struction subseq uences: TC0 CCS0 CCS1 NDX0 NDX1 RSM3 XCH0 CS0 TS0 AD0 MASK0 MP0 MP1 0 1 2 3 4 5 6 7 8 9 10 11 12

MP3 DV0 DV1 SU0 RUPT1 RUPT3 STD2 PINC0 MINC0

13 14 15 16 17 18 19 20 21

If the CTR signals are 01 (SB_02=0, SB_01=1) the PINC subsequence is selected. If the CTR signals are 10 (SB_02= 1, SB_01= 0) the MINC subsequen ce is selected. Otherwise, subsequences for each instruction are selected using the 4-bit SQ register and the 2-bit stage register (STB2, STB1, where STB2 is the MSB). Some instructions (TC) have only one subsequence. At the start of each instruction, the stage counter is initially set to zero. The interrupt call and resturn sequences are also stored at SQ=00. SQ 00: 01: 02: 03: 04: 05: 06: 07: 10: MP DV SU CS TS AD MASK 11: 12: 13: 14: 15: 16: 17: STB00 TC0 CCS0 NDX0 XCH0 ---------------MP0 DV0 SU0 CS0 TS0 AD0 MASK0 STB01 RUPT1 CCS1 NDX1 ------------------MP1 DV1 ---------------STB10 STD2 ------STD2 ------------------STD2 STD2 STD2 STD2 STD2 STD2 STB11 RUPT3 ---RSM3 ------------------MP3 -------------------

TC/RUPT CCS INDEX XCH

SELECTING THE CONTROL PULSES


Each subsequence consists of 12 steps (TP1 - TP12), with each step asserting up to 5 control puls es (con trol logic sig nals) . Steps T P1-T P11 are un ique to each subs equ ence; step TP 12 is common to all subsequences. Control pulses for TP12 are discussed in CPM-C. For som e steps, sele ction of th e contro l pulse s is also con dition al on th e state of th e 2-b it branch reg ister (BR1 an d BR 2: BR 1 is the MS B and BR2 is the LSB): BR00 BR1=0, BR2=0 BR01 BR1=0, BR2=1 BR10 BR1=1, BR2=0 BR11 BR1=1, BR2=1 Bits 1-6 of the CPM -A EPR OM address is formed as follows:

3-6: 2: 1:

register SG (4) register BR1 (1) register BR2 (1)

The colu m n on the fa r left is th e step ; colu m ns to the rig ht sp ecify th e con trol pulse s tha t are asserted for that step. Som e steps have n o control pulses.

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

TC0: RB WG RA

WY ---WOVI

WS -------

CI -------

----------

RG RZ RB RU NISQ

RSC WQ WSC WZ ----

WB GP WG -------

WP TP ----------

----------------

subsequence CCS0: TP1 RB TP2 RZ TP3 WG TP4 TP5 TP6 RG TP7 BR00, RC BR01, RC BR10, RB BR11, RB TP8 BR00, GP BR01, R1 BR10, R2 BR11, R1 TP9 RB TP10 BR00, RC BR01, W A BR10, RB BR11, W A TP11 RU

WS WY ----

----------

----------

----------

RSC TMZ TMZ TMZ TMZ TP WX WX R2 WSC WA R1C WA R1C ST1

WB ---------------GP GP WX WG ------------WZ

TSGN ---------------TP TP GP -------------------

WP ---------------------TP, -------------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8

CCS1: RZ WG RU RA RG RU

WY ---WZ WY RSC WB

WS ------CI WB GP

CI ---------WP TP

-------------------

TP9 TP10 TP11

RC RG

WA RSC

WOVI WB

---NISQ

-------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

NDX0: RB WG RA

WS ---WOVI

----------

----------

----------

RG GP RB TRSM ST1

RSC TP WSC -------

WB ---WG -------

WP -------------

----------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

NDX1: RZ WG RU RB RG RB RB RU

WY ---WZ WY RSC WX WSC WB

WS ---------WB GP WG WOVI

CI ---------WP TP ---NISQ

-------------------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

RSM3: R24 WG

WS ----

-------

-------

-------

RG

WZ

----

----

----

NISQ

----

----

----

----

subsequence TP1 TP2 TP3 TP4 TP5 TP6

XCH0: RB RA WG WP2

WS WP -------

-------------

-------------

-------------

TP7 TP8 TP9 TP10 TP11

RG GP RA RB ST2

RSC TP WSC WA ----

WB ---WG WOVI ----

WP, ---RP2 -------

----------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

CS0: RB WG

WS ----

-------

-------

-------

RG GP RB RC ST2

RSC TP WSC WA ----

WB ---WG WOVI ----

WP, -------------

----------------

subsequence TS0: TP1 RB TP2 RA TP3 WG TP4 BR00, ---BR01, RZ BR10, RZ BR11, ---TP5 BR00, ---BR01, R1 BR10, W A BR11, ---TP6 TP7 BR00, ---BR01, RU BR10, RU BR11, ---TP8 GP TP9 RB TP10 RA TP11 ST2 subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 AD0: RB RA WG

WS WB ------WY WY ------WA R1C ------WZ WZ ------WSC WOVI ----

---TOV ------CI CI ------------------------------WG -------

---WP ----------------------------------------------------

----------------------------------------------------------

(overflow) (underflow)

WS WY ----

----------

----------

----------

RG RB RB

RSC WX WSC

WB GP WG

WP TP ----

----------

TP11

RU

WA

WOVC

ST2

WOVI

SU B_ MA SK 0 perform s a log ical A ND usin g D eM orga n's Th eorem : the inp uts a re inv erted , a logica l OR is perform ed, an d the res ult is inv erted. Th e im plem enta tion of the OR (at TP8 ) is somewhat unorthodox: the inverted inputs are in registers U and C. The OR is achieved by gating both registers onto the read/write bus simultaneously. (The bus only transfers logical 1's; register-to-register transfers are performed by clearing the destination register and then transferring the 1's from the sou rce register to th e destin ation ). Wh en th e 1's from both registers are sim ultan eous ly gate d on to the b us, the w ord on the bu s is a logica l OR of both regis ters. subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11 MASK0: RB RA WG RC

WS WB ---WY

-------------

-------------

-------------

RG RU RA RC

RSC RC WB WA

WB WA ---ST2

WP GP ---WOVI

---TP -------

subsequence MP0: TP1 RB TP2 RA TP3 RSC TP4 BR00, RB BR01, RB BR10, RC BR11, RC TP5 RLP TP6 TP7 BR00, RG BR01, RG BR10, RG BR11, RG TP8 BR00, GP BR01, GP BR10, RC BR11, RC TP9 RU TP10 BR00, RA BR01, RA BR10, RA BR11, RA TP11 BR00, ST1 BR01, R1 BR10, RU BR11, RU

WS WB WG WLP WLP WLP WLP WA WY WY WB WB TP TP WY WY WB WLP RB14 WLP RB14 WA LP ST1 ST1 ST1

---TSGN ------------------WP WP WP WP ------GP GP TSGN2 TSGN WLP TSGN WLP ---WA LP WA LP WA LP

------------------------------------------TP TP ------TSGN ---TSGN ---R1C -------

----------------------------------------------------------------------------

subsequence MP1: TP1 RA TP2 RLP TP3 BR00, ---BR01, ---BR10, RB BR11, RB TP4 RA TP5 RLP TP6 RU TP7 RA TP8 BR00, ---BR01, ---BR10, RB BR11, RB TP9 RLP TP10 RA TP11 RU

WY WA ------WX WX WLP TSGN WA LP WY ------WX WX WA WLP ST1

---TSGN ---------------------------------------CTR WA LP

----------------------------------------------------

----------------------------------------------------

subsequence MP3: TP1 RZ TP2 RLP TP3 WG TP4 RU TP5 RA TP6 BR00, ---BR01, ---BR10, RB BR11, RB TP7 RG TP8 RLP TP9 RB TP10 RA TP11 RU

WY TSGN ---WZ WY ------WX WX RSC WA WSC WLP WA LP

WS ------------------------WB GP WG ---NISQ

CI ------------------------WP TP ----------

-------------------------------------------

subsequence DV0: TP1 RB TP2 RA TP3 RSC TP4 BR00, RC BR01, RC BR10, ---BR11, ---TP5 BR00, R1 BR01, R1 BR10, R2 BR11, R2 TP6 RA TP7 RG TP8 RB TP9 BR00, RLP

WS WB WG WA WA ------WLP WLP WLP WLP WQ WB WA R2

---TSGN ------------------------------TSGN GP WB

------------------------------------WP TP ----

----------------------------------------------

TP10

BR01, BR10, BR11, BR00, BR01, BR10, BR11,

TP11

RLP ------RB RB RC RC R1

R2 ------WLP WLP WA WA ST1

WB ------------------WB

-------------------------

-------------------------

subsequence DV1: TP1 R22 TP2 RQ TP3 RG TP4 RA TP5 RLP TP6 TP7 RU TP8 BR00, ---BR01, ---BR10, RU BR11, RU TP9 BR00, RB BR01, RB BR10, RB BR11, RB TP10 RG TP11 BR00, ST1 BR01, ST1 BR10, RC BR11, RB

WS WG WQ WX TSGN2 TSGN ------WQ WQ RSB RSB WG WG WB ------WA WA

------WY ---------------------WG WG ------TSGN ------ST2 ST2

------RSB -------------------------------------------------

----------------------------------------------------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

SU0: RB RA WG

WS WY ----

----------

----------

----------

RG RC RB RU

RSC WX WSC WA

WB GP WG WOVC

WP TP ---ST2

---------WOVI

subsequence RUPT1: TP1 R24 TP2 TP3 WG TP4 TP5 TP6

WY ----

WS ----

CI, ----

-------

TP7 TP8 TP9 TP10 TP11

RZ RU ST1

WG WZ ST2

----------

----------

----------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

RUPT3: RZ RRPA RZ

WS WZ KRPT

------WG

----------

----------

RB ST2

WSC ----

WG ----

-------

-------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

STD2: RZ WG RU

WY ---WZ

WS -------

CI, -------

----------

RG GP RB NISQ

RSC TP WSC ----

WB ---WG ----

WP ----------

-------------

subsequence TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11

PINC: WS WG R1 RG TP WP RU RU

RSCT ---WY WX ------CLG WGx

---------WP ------WPx WOVR

-------------------------

-------------------------

subsequence TP1 TP2 TP3 TP4

MINC: WS, WG WY

RSCT ---R1C

----------

----------

----------

TP5 TP6 TP7 TP8 TP9 TP10 TP11

RG TP WP RU RU

WX ------CLG WGx

WP ------WPx WOVR

----------------

----------------

Heres some of the analysis used to develop the instruction sequence decoder. This decoder takes in the STB and SQ inputs and decodes the instruction sequence for display to the ope rator.

CONTROL SIGNAL DEFINITIONS


SIGNAL CI CLG CLCTR CTR GP KRPT NISQ RA RB RB14 RC RG RLP RP2 RQ RRPA RSB RSCT RU RZ R1 R1C R2 R22 R24 ST1 ST2 TMZ TOV TP TRSM TSGN TSGN2 WA WA LP WB Wgx WLP WOVC WOVI WOVR WP Wpx WP2 WQ WS WX WY Wyx # 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 DESCRIPTION Carry in Clear G Clear loop counter Loop counter Gen erate Pa rity Kn ock do wn Rup t priority New instruction to the SQ register Read A Read B Read bit 14 Read C Read G Read LP Read parity 2 Read Q Read RUP T address Rea d sign bit Read selected counter add ress Read sum Read Z Read 1 Read 1 com plimented Read 2 Read 22 Read 24 Stage 1 Stage 2 Test for m inu s zero Test for overflow Test pa rity Test for resume Test sign Test sign 2 Write A Write A and LP Write B W rite G (do not reset) Write LP Write overflow counter W rite overflow RU PT inh ibit Write overflow Write P W rite P (do n ot reset) Write P2 Write Q Write S Write X Write Y W rite Y (do n ot reset)

WZ

50

Write Z

Control signa l outputs from CPM -A used as inputs to CP M-B only (not used outside of CPM ): SIGNAL RSC WSC WG # 51 52 53 DESCRIPTION Read special and central (output to B only, not outside CPM) Write special and central (output to B only, not outside CPM) Write G (output to B only, not outside CPM)

Control signa l outputs from CPM -A used as inputs to CP M-C only (not used outside of CPM ): SIGNAL SDV1 SMP1 SRSM3 # 54 55 56 DESCRIPTION Subsequence DV1 is currently active Subsequence MP1 is currently active Subsequence RSM3 is currently active

CPM-A INPUTS:
I/F TPG: signal TPG_Q3 TPG_Q2 TPG_Q1 TPG_Q0 fu ll n am e TPG STATE state definition wh ere Q3 is MS B, Q0 is LSB: 00 = STBY 01 = PWRON 02 = TP1 03 = TP2 04 = TP3 05 = TP4 06 = TP5 07 = TP6 08 = TP7 09 = TP8 10 = TP9 11 = TP10 12 = TP11 13 = TP12 14 = SRLSE 15 = W AIT

SEQ: BR1 BR2 BRANCH REG 1 BRANCH REG 2 BR1 is MSB, BR2 BR00=0:BR1=0, BR01=1:BR1=0, BR10=2:BR1=1, BR11=3:BR1=1, is LSB BR2=0 BR2=1 BR2=0 BR2=1

SQ_3 SQ_2 SQ_1 SQ_0

INST REG

where SQ_3 is MSB, SQ_0 is LSB

STB_1 STB_0 LOOP6

STAGE REG

where STB_1 is MSB, STB_0 is LSB

LOOPCNTR EQ 6

0=LOOPCNTR is holding the number 6. 1= selec t nex t instruction ( SN I register)

SNI

SELECT NEXT INST

CTR: SB_01 SB_02 INT: SUB SEL 01 SUB SEL 02 SB_01 is LSB; SB_02 is MSB 00=no counter; 01=PINC; 10=MINC

IRQ MON: NRUN

INT RQST

0=interrupt requested.

RUN /HALT

0=run, 1= step

CPM-A OUTPUTS:
signal CI CLG CLCTR CTR GP KRPT NISQ RA RB RB14 RC RG RLP RP2 RQ RRPA RSB RSCT RU RZ R1 R1C R2 R22 R24 ST1 ST2 TMZ TOV TP TRSM TSGN TSGN2 WA WA LP WB WGx WLP WOVC WOVI WOVR WP WPx WP2 fu ll n am e SE T C AR RY IN CLR G CLR LOOP CTR INCR LOOP CTR GEN PARITY KNOCK DOW N RUPT NEW INSTRUCT READ A READ B READ BIT 14 READ C READ G READ LP READ PARITY 2 READ Q READ RUPT ADDR READ SIGN READ CNTR ADDR READ U READ Z READ 1 READ 1 COMP READ 2 READ 22 READ 24 SET STAGE 1 SET STAGE 2 TEST MINUS ZERO TEST OVF TEST PARITY TEST RESUME TEST SIGN TEST SIGN 2 WRITE A WR ITE A/LP WRITE B WRITE G NO RESET WR ITE LP WRITE OVF CNTR WRITE OVF RUPT INH WRITE OVF WRITE P WRITE P NO RESET WRITE P2 state definition 0= Carry in 0= Clear G 0=Clear loop counter 0=Loop coun ter 0= Gen erate Pa rity 0= Kn ock do wn Rup t priority 0=N ew instruction to the SQ reg 0=Read A 0=Read B 0=Read bit 14 0=Read C 0=Read G 0=R ead LP 0=Read parity 2 0=Read Q 0=R ead RU PT add ress 0= Rea d sign bit 0=R ead selected cou nter address 0=Read sum 0=Read Z 0=Read 1 0=R ead 1 comp limented 0=Read 2 0=Read 22 0=Read 24 0=Stag e 1 0=Stag e 2 0= Test for m inu s zero 0=Test for overflow 0= Test pa rity 0=Test for resume 0=Test sign 0=Test sign 2 0=W rite A 0=W rite A and LP 0=W rite B 0= W rite G (do not reset) 0=W rite LP 0=W rite overflow counter 0= W rite overflow RU PT inh ibit 0=W rite overflow 0=W rite P 0= W rite P (do n ot reset) 0=W rite P2

WQ WS WX WY WYx WZ

WRITE WRITE WRITE WRITE WRITE WRITE

Q S X Y Y NO RESET Z

0=W rite 0=W rite 0=W rite 0=W rite 0= W rite 0=W rite

Q S X Y Y (do n ot reset) Z

OUTPUTS TO CPM -B ONLY; NOT USED OUTS IDE CPM RSC WSC WG READ SPECIAL REG WRITE SPECIAL REG WRITE G 0=Read special and central 0=W rite special and central 0=W rite G

OUTPUTS TO CPM -C ONLY; NOT USED OU TSIDE CPM SDV1 SMP1 SRSM3 SUBSEQ DV1 SUBSEQ M P1 SUBSEQ RSM3 0=Su bsequence DV 1 is selected 0=Su bsequence MP1 is selected 0=Su bsequence RSM 3 is selected

CPM-B (Control Pulse Matrix B)


Som e AGC registers are mapp ed onto low mem ory addresses (00 - 17 octal), so reading or writ ing to tho se ad dresses ca use s da ta to b e read from , or written into, flip-flo p reg isters instead of memory. These addresses include the central registers (A, Q, Z, LP), the bank register (BNK), an d I/O registers. Add resses 16 and 17 a re used in con junc tion w ith the INDE X instru ction to in hibit o r enab le interrupts; this is a trick used to extend the instruction set; to cram m ore instructions into a 3-bit op code. The ad dresses from 20 -23 are in eraseab le mem ory, but any da ta written into those addresses is rotated or shifted. This is implemented through the G register in the MEM mod ule. Add resses 24 -27 a re reserved for saving the cen tral register b efore servicin g an interrup t. Registers Z and B are automatically saved by the interrupt subsequence. Registers A and Q mu st be saved by the interrupt service routine.

SPECIAL REGISTERS
These a dd resses called sp ecia l regis ters. A ll nu m bers are in octal. addr 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 Flip -Flo p reg isters A regis ter (accum ula tor) Q register Z regis ter (p rogra m cou nter) LP register IN0 inp ut reg ister 0 IN1 inp ut reg ister 1 IN2 inp ut reg ister 2 IN3 inp ut reg ister 3 OUT0 outpu t regis ter 0 OUT1 outpu t regis ter 1 OUT2 outpu t regis ter 2 OUT3 outpu t regis ter 3 OUT4 outpu t regis ter 4 BANK bank register RELINT INHINT Eraseab le m em ory reg isters CYR cycle right SR shift right CYL cycle left SL shift le ft ZRUPT BRUPT ARUPT QRUPT save save save save register register register register Z B A Q

20 21 22 23 24 25 26 27

CPM -B tran slates th e W G, RS C, an d W SC signa ls gen erated by S UB SYS TEM A into signa ls that read from o r write to these registers. The logic is given below (all num bers are in octal): if WG is asserted from CPM-A, ...and ...and ...and ...and the the the the address address address address bus bus bus bus = = = = 020: 021: 022: 023: assert:W20 assert:W21 assert:W22 assert:W23

...othe rwis e, if the add ress b us > 17: assert:W Gn (not a cen tral reg ister)

if RSC is asserted from CPM -A ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and the the the the the the the the the the the the the the the the address address address address address address address address address address address address address address address address bus bus bus bus bus bus bus bus bus bus bus bus bus bus bus bus = = = = = = = = = = = = = = = = 00: 01: 02: 03: 04: 05: 06: 07: 010: 011: 012: 013: 014: 015: 016: 017: assert:RA0 assert:RA1 assert:RA2 assert:RA3 assert:RA4 assert:RA5 assert:RA6 assert:RA7 assert:RA10 assert:RA11 assert:RA12 assert:RA13 assert:RA14 assert:RBK do nothing do nothing

if WSC is asserted from CPM-A, ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and ...and the the the the the the the the the the the the address address address address address address address address address address address address bus bus bus bus bus bus bus bus bus bus bus bus = = = = = = = = = = = = 00: 01: 02: 03: 010: 011: 012: 013: 014: 015: 016: 017: assert:WA0 assert:WA1 assert:WA2 assert:WA3 assert:WA10 assert:WA11 assert:WA12 assert:WA13 assert:WA14 assert:WBK do nothing do nothing

Heres a tab le I develo ped to wo rk out th e relation ship s betw een a ddres ses an d CP M-B logic signals:

CPM-B CONTROL SIGNALS


SIGNAL RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7 RA10 RA11 RA12 RA13 RA14 RBK WA0 WA1 WA2 WA3 WA10 WA11 WA12 WA13 WA14 WBK WGn W20 W21 W22 W23 # 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 DESCRIPTION Read register at address 0 (A) Read register at address 1 (Q) Read register at address 2 (Z) Read register at address 3 (LP) Read register at address 4 Read register at address 5 Read register at address 6 Read register at address 7 Rea d registe r at add ress 10 (octal) Rea d registe r at add ress 11 (octal) Rea d registe r at add ress 12 (octal) Rea d registe r at add ress 13 (octal) Rea d registe r at add ress 14 (octal) Read BNK Write register at address 0 (A) Write register at address 1 (Q) Write register at address 2 (Z) Write register at address 3 (LP) W rite register at a ddres s 10 (o ctal) W rite register at a ddres s 11 (o ctal) W rite register at a ddres s 12 (o ctal) W rite register at a ddres s 13 (o ctal) W rite register at a ddres s 14 (o ctal) Write BNK Write G (n orma l gates) Write into CYR Write into SR Write into CYL Write into SL

CPM-B INPUTS:
I/F signal CPM -A RSC WSC WG ADR: AD_4 AD_3 AD_2 AD_1 GTR_17 GTR_27 ADDRESS > 017 ADDRESS > 027 0=CADR in register S > 017 0=CADR in register S > 027 ADDRESS AD_4=MSB, AD_1=LSB: (low -order b its of 14-b it address) fu ll n am e READ SPECIAL REG WRITE SPECIAL REG WRITE G state definition 0=Read special and central 0=W rite special and central 0=W rite G

CPM-B OUTPUTS:
I/F signal RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7 RA10 RA11 RA12 RA13 RA14 RBK WA0 WA1 WA2 WA3 WA10 WA11 WA12 WA13 WA14 WBK fu ll n am e READ ADDR 0 (A) READ ADDR 1 READ ADDR 2 READ ADDR 3 READ ADDR 4 READ ADDR 5 READ ADDR 6 READ ADDR 7 READ ADDR 10 READ ADDR 11 READ ADDR 12 READ ADDR 13 READ ADDR 14 READ BNK WRITE ADDR 0 WRITE ADDR 1 WRITE ADDR 2 WRITE ADDR 3 WRITE ADDR 10 WRITE ADDR 11 WRITE ADDR 12 WRITE ADDR 13 WRITE ADDR 14 WRITE BNK state definition 0=R ead reg at ad dress 0 0=Read reg at address 1 (Q) 0=Read reg at address 2 (Z) 0=Read reg at address 3 (LP) 0=R ead reg at ad dress 4 0=R ead reg at ad dress 5 0=R ead reg at ad dress 6 0=R ead reg at ad dress 7 0= Rea d reg a t add ress 10 (octal) 0= Rea d reg a t add ress 11 (octal) 0= Rea d reg a t add ress 12 (octal) 0= Rea d reg a t add ress 13 (octal) 0= Rea d reg a t add ress 14 (octal) 0=R ead BNK reg 0=Write reg at address 0 (A) 0=Write reg at address 1 (Q) 0=Write reg at address 2 (Z) 0=W rite reg at address 3 (LP) 0= W rite reg at ad dress 1 0 (octa l) 0= W rite reg at ad dress 1 1 (octa l) 0= W rite reg at ad dress 1 2 (octa l) 0= W rite reg at ad dress 1 3 (octa l) 0= W rite reg at ad dress 1 4 (octa l) 0=W rite BNK reg

WGn W20 W21 W22 W23

WRITE WRITE WRITE WRITE WRITE

G NORMAL ADDR 20 ADDR 21 ADDR 22 ADDR 23

0=W rite 0=W rite 0=Write 0=W rite 0=Write

G (norm al gates) into CYR into SR into CYL into SL

CPM-C (Control Pulse Matrix C)


The CPM-C subsystem issues control signals for the memory cycle, selecting the next instruction, and performing priority counter subsequences. These signals are issued at specific points in the 12 -step cycle of the time pu lse generator (TPG ). STBY: PWRON: assert:GENRST assert:R2000 Resets various A GC registers. Put the starting ad dress on the read b us. CPM -A ass erts:W B, wh ich cop ies the d ata into register B, which is the p refetch register for the next instruction. Since the opcod e for a bran ch is 0, th e instru ction in B becom es TC 20 00, wh ich is the first instruction always executed by the AGC. SNI < - 0. Moved from TP12 to TP1 becau se CLIS Q w as g ettin g cle ared in th is ha rdw are AGC replica before TPG was clocked; therefore TPG was not seeing the SNI indication. (no t a cen tral reg ister) (not fixed memory; m ust be erasable) (not a loop counter subsequence) read erasable memory into G by TP6

TP1:

assert:CLISQ

TP5:

if: and and then: if: then: if: then:

the address bus > 17 the address bus < 2000 SDV1 or SMP1 are not asserted a ss ert: SB W G the address bus = 17 assert:INH the address bus = 16 assert:CLINH

INHINT instruction (INDEX 017)

RELINT instruction (INDEX 016)

TP6:

if: and then:

the address bus > 1777 SDV1 or SMP1 are not asserted a ss ert: SB W G

(not eraseable mem ory) (not a loop counter subsequence) read fixed memory into G register by TP7

TP11: if: and and then:

the address bus > 17 the address bus < 2000 SDV1 or SMP1 are not asserted a ss ert: WE

(no t a cen tral reg ister) (not fixed memory; m ust be erasable) (not a loop counter subsequence) G register written to memory beginning at TP11; Memory updates are in G by TP10 for all normal an d extracode instruction s, but th e PINC and MIN C seq uen ces w rite to G in TP10 because they need to update the parity b it. Additional interrupts are inhibited during servicing of an interrupt; Remove the inhibition when RES UME is executed (INDEX 025)

if: then:

SRSM 3 is asserted assert:CLRP

TP12: assert:WPCTR

Check the priority counters; service any waiting inputs on the next mem ory cycle. (if SNI is set, get next instruction) (if interrupt requested (see CPM-A for similar assertion)) Read the in terrupt ve ctor. STB <- 1. Will cause the RUPT1 subsequence to execute. (not an interrupt; a normal instruction) STB < - 0 . The CPM-A will assert RB here, which, when accompanied by WSQ (below), will read the next instruction from register B onto th e bu s. WS Q w ill write it into SQ. W rite the n ext instru ction (o n the write bu s) into the SQ regis ter. Clear STA regis ter.

if: then:

the SNI register = 1 if: then: assert:RPT assert:SETSTB else: assert:CLSTB IRQ is asserted

end if assert:WSQ assert:CLSTA

assert:CLINH1

else: if: CTR00 or CTR11

Clear INHINT1. Removes inhibition of interrupts (if they were) AFTER the next instruction (not a new instruction) if previous sequence was not a PINC or MINC, get next subsequence for same instruction. if the previous sequence was PINC or MINC, we already have the subsequence, but it was interrupted by the cou nter. Copy STB < - STA. Gets next sequence for same instruction. STA <- 0

then: assert:WSTB assert:CLSTA

This tru th tab le show s the log ic needed at TP12 to produce the RPT, SETSTB, CLSTB, CLSTA, WSQ, WSTB, CLISQ, and CLINH1 signals, given the SNI, IRQ, NRU N, and S B inpu ts.

This chart shows the logic for som e of the m ore sim ple control pulses generated by CM P-C. S om e pu lses redu ce to states from the TPG, such as CLISQ, WPCTR, and CLINH1, which reduce to TP12.

This is the logic for RPT and SETSTB.

The desig n for CLSTB is a little more complex. The truth ta ble to th e left is reduced through the Karnaugh map to the Minterm equ ation below the m ap. A little bub ble pushing D eMorganizes the logic to the final solution at the bottom right.

This is the logic for WE and SBWG, two signals that control me mo ry access.

CPM-C CON TROL SIGNALS SIGNAL GENRST CLINH CLINH1 CLSTA CLSTB CLISQ CLRP INH RPT S BW G SETSTB WE WPCTR WSQ WSTB R2000 # 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 DESCRIPTION General Reset Clear INHINT Clear INHINT1 Clear state counter A (STA) Clear state counter B (STB) Clear SNI Clear RPCELL Set INHINT Read RUPT opcode W rite G from m em ory Set the ST1 bit of STB Write E-MEM from G Write PCTR (latch priority counter sequence) Write SQ Write stage counter B (STB) Read 2000

CPM INPUTS:
I/F TPG: signal TPG_Q3 TPG_Q2 TPG_Q1 TPG_Q0 fu ll n am e TPG STATE state definition wh ere Q3 is MS B, Q0 is LSB: 00 = STBY 01 = PWRON 02 = TP1 03 = TP2 04 = TP3 05 = TP4 06 = TP5 07 = TP6 08 = TP7 09 = TP8 10 = TP9 11 = TP10 12 = TP11 13 = TP12 14 = SRLSE 15 = W AIT

ADR: EQU_16 EQU_17 GTR_17 GTR_1777 ADDRESS ADDRESS ADDRESS ADDRESS = = > > 016 017 017 01777 0=CADR 0=CADR 0=CADR 0=CADR in in in in register register register register S S S S = = > > 016 017 017 01777

CPM-A: SDV1 SMP1 SRSM3

SUBSEQ DV1 SUBSEQ M P1 SUBSEQ RSM3

0=Su bsequence DV 1 is selected 0=Su bsequence MP1 is selected 0=Su bsequence RSM 3 is selected

CTR: SB_01 SB_02 SEQ: SNI INT: IRQ MON: NRUN RUN /HALT 0=run, 1= step INT RQST 0=interrupt requested. SELECT NEXT INST 1= selec t nex t instruction ( SN I register) SUB SEL 01 SUB SEL 02 SB_01 is LSB; SB_02 is MSB 00=no counter; 01=PINC; 10=MINC

CPM OUTPUTS:
I/F signal GENRST CLINH CLINH1 CLSTA CLSTB CLISQ CLRP INH RPT S BW G SETSTB WE WPCTR WSQ WSTB R2000 fu ll n am e GENERAL RESET CLEAR INHINT CLEAR INHINT1 CLEAR STA CLEAR STB CLEAR SNI CLEAR R PCELL SET INHINT READ RUPT WRITE G SET ST1 WRITE EMEM WRITE PCTR WRITE SQ WRITE STB READ 2000 state definition 0=G eneral Reset 0=Clear INHINT 0=Clear INHINT1 0=Clear state counter A (STA) 0=Clear state counter B (STB) 0=Clear SNI 0=Clear RPCE LL 0=Set INHINT 0=Read RUPT opcode 0= W rite G from m em ory 0=Set the ST1 bit of STB 0=W rite E-MEM from G 0=W rite PCTR (latch priority counter sequence) 0=Write SQ 0=Write stage counter B (STB) 0=Read 2000

Fabrication
The C TL m odu le is (3) 1 3"x5 " circuit bo ards, an d 1 co ntrol pa nel.

Module Rack
The m odu le fram ewo rk is desig ned to resem ble a rela y rack, bu t scaled to fit the circuit board dimensions. It is constructed out of 1"x2" pine and spray-painted semi-gloss gray. Circu it boards are m oun ted to the ra ck by 2 p hillips sc rew s at either end . Nylon s pacers (1/4") a re used a s stan doffs to hold the b oard edg es ab ove the ra ck. Th e bo ards are m oun ted so th e chip s are in th e back and the pin s are w iring a re visible from the front. Power is distributed by 2 heavy aluminum bus bars mounted vertically, one per side, on the back of the module. Machine screws are mounted through the bus bars at evenly-spaced intervals to provide conn ection points for the boards. Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used on the bus bar side of the connection. On the circuit board size, the wires are soldered directly to the supply rails. Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards
The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with doubleside plated throu gh pa ds on 0.1" cen ters (JAMEC O 21 477C L). ICs are m oun ted in le vel 3 m achin e tooled wire-w rap sock ets: 8, 14 , 16, 20 , 24, an d 28 pin (JAM ECO ). Each socket has the pin-out lab eled with a wire-wrap socket ID ma rker, which slip s on to th e socke t be fore wrap pin g (J AM EC O). Th e part n um ber is w ritte n onto the ID m arke r. Sock ets are arran ged in 4 h orizon tal row s on ea ch bo ard, w ith about 10 sockets per row. Power is distributed on the back-side of each board by bare 24gau ge solid copp er wire su pply rails solde red at eq ual in tervals to Klipwrap terminals: 3-prong terminals with a square tail for wire-wrap ping (JA MEC O 34 163C L). A +5V rail runs above each row o f sockets an d a g roun d rail run s below . Each ra il conn ects directly to th e alum inum mo dule pow er bus u sing a ring ta il con nec tor. On the pin side of the board, all connections are made with 30 AW G Kyn ar wire-wrap wire (JAM ECO ). Red wire is used for direct conn ections to the + 5V su pply rail. Black w ire is used for direct conn ections to grou nd. W hite wire is used for everything else. Power connections from the supply rails to each ICs are double-wrapped. Bypassing capa citors (.1 uf d isc ) are sold ered ac ross the su pply rails at the Klipw rap term inals; abou t 1 capacitor for every 2 IC packag es.

All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As each connection was made, the corresponding line on the schematic was marked with a colored h igh ligh ter. DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current limiting resistors for the panel ind icators.

CTL P rinted Circuit Board (PCB) A The A b oard contain s the clock (CLK ), the scaler (SCL), and th e time pu lse generator (TPG ).

CTL P rinted Circuit Board (PCB) B The B board contains the display indicators, their current-limiting resistor networks, and the open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was used to make holes through the plastic, and the LEDs were inserted in rows. The panel was hand -lette red w ith a n in delible m arke r. A few chip s near the bo ttom righ t of the B bo ard are associated with subsystems on the C board.

CTL P rinted Circuit Board (PCB) C The C board contains the sequence generator (SEQ) and control pulse matrixes (CPM-A, CPM -B, and C PM-C ). The big ICs at the bottom are the EPRO Ms tha t hold the con trol pulse matrix table for CPM-A. Each EPROM holds the tables for 8 control signals. The large ICs at the top are decod ers for the CPM-B a nd CP M-C logic.

Parts (ICs)
74LS00 74LS02 74LS04 74LS06 74LS08 74LS10 74LS20 74LS27 74LS32 74LS74 74LS112 74LS138 74LS154 74LS161 74LS244 74LS273 27C128 4001 555 (14) (9) (15) (11) (2) (4) (8) (3) (3) (1) (8) (1) (7) (8) (10) (1) (7) (1) (1) U74,U26,U27,U25,U79,U78,U55,U54,U53,U48,U13,U42,U34,U28 U4,U77,U9,U73,U45,U43,U3,U38,U32 U62,U29,U76,U69,U64,U57,U71,U59,U58,U56,U49,U41,U40,U39,U33 U22,U21,U20,U23,U14,U17,U18,U19,U16,U15,U1 U65,U10 U12,U70,U52,U51 U67,U68,U66,U63,U75,U61,U60,U6 U7,U44,U2 U72,U11,U5 U24 U8,U50,U47,U46,U35,U36,U37,U31 U99 U81,U82,U83,U98,U100,U101,U106 U104,U107,U108,U109,U110,U111,U112,U113 U80,U84,U85,U93,U94,U95,U96,U97,U102,U103 U105 U86,U87,U88,U89,U90,U91,U92 U30 U114

ICs, sockets, PCBs, resistors, capacitors, wire-wrap wire were purchased from JAMECO. The 2.048 MHz crystal and the IDE wire-wrap were from DigiKey. Wire ties, wire-wrap tools, and copper wire were purchased from Radio Shack. IDE ribbon cables were purchased from an online com pu ter su pp lier.

Power Budget
qty 74LS00 74LS02 74LS04 74LS06 74LS08 74LS10 74LS20 74LS27 74LS32 74LS74 74LS112 74LS138 74LS154 74LS161 74LS244 74LS273 27C128 4001 1 555 1 LED 61 mA (ea) m A (tot) 14 2.4 33 .6 9 2.4 21 .6 15 3.6 54 .0 11 3.6 39 .6 2 4.4 8.8 4 1.8 7.2 8 1.2 9.6 3 3.4 10 .2 3 4.9 14 .7 1 4.0 4.0 8 4.0 32 .0 1 6.3 6.3 7 6.2 43 .4 8 19 .0 15 2.0 10 32 .0 32 0.0 1 17 .0 17 .0 7 25 .0 17 5.0 0.4 0.4 3.0 3.0 20 .0 12 20 .0

------2.2 Amps total 1.0 Am ps (excludin g LEDs)

EPROM generator program


This C+ + p rogra m gen erate s all file s neede d to p rogra m the C PM -A E PR OM s. Th e files a re gen erated in M otorola S -Reco rd form at.
/* * * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * C PM - A E P RO M G E NE R AT O R * * 9 / 1 4 /0 1 * * * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * Versions: D e r iv e d fr o m A G C C + + s i m u la t o r 1 . 1 5 .

O p e r a tio n : Ge ne rates all of the C PM- A EPR OM files in M o t o ro l a s 2 f S -Rec o rd fo rma t suitable for EPROM program me rs. */ # i n clu d e # i n clu d e # i n clu d e # i n clu d e # i n clu d e < s tr in g . h > < s td lib . h > < c ty p e .h > < io s tr e a m . h > < s td io . h >

# d e f in e M A X P U L S E S 1 5 # de fin e M A X _I PU LS ES 5 / / n o m or e t ha n 5 ins tru ct ion -g en er at ed pu lse s a ct ive at an y t im e

enum cpType { // **inferred; not defined in orignal R393 AGC 4 spec. NO_PULSE=0,

/ / O U T PU T S F RO M S U BS Y S TE M A CI =1, // C ar ry in CLG =2, // Clear G CLCTR =3, / / C l e ar lo o p c ou n t e r CTR =4, / / L o o p co u n t e r GP =5, // Gen erate Parity KRP T =6, // Kno ck dow n Ru pt priority NISQ =7, / / N e w i n st r uc t io n t o t h e S Q r e gis t e r RA =8, / / R ead A RB =9, / / R ead B RB14 =10, / / R e a d b it 1 4 RC =11, / / R ead C RG =12, / / R ead G RLP =13, // Read LP RP 2 =14, // Read parity 2 RQ =15, / / R ead Q RRP A =16, // Read RU PT add ress RSB =17, // R ea d s ign bit RSCT =18, // Read selected cou nter addre ss RU =19, // Read sum RZ =20, / / R ead Z R1 =21, / / R ead 1 R1C =22, / / R e a d 1 c om p l im e n t e d R2 =23, / / R ead 2 R22 =24, // Read 22 R24 =25, // Read 24 ST1 =26, // Stage 1 ST2 =27, // Stage 2 TMZ =28, // Test for minus zero TOV =29, / / Test for o verfl o w TP =30, // Test p arity TRSM =31, // T es t fo r r es um e TSGN =32, / / Test sign TSGN2 =33, / / T e s t s ig n 2 WA =34, / / W r i te A

WA LP WB WGx WLP WOVC WOVI WOVR WP WPx WP2 WQ WS WX WY WYx WZ

=35, =36, =37, =38, =39, =40, =41, =42, =43, =44, =45, =46, =47, =48, =49, =50,

// // // // // // // // // // // // // // // //

Write W r i te Write Write W r i te W rite Write W r i te Write Write W r i te W r i te W r i te W r i te Write W r i te

A and LP B G (do no t reset) LP o v e rf lo w c o u n te r ov er flow RU PT inh ibit ove rfl o w P P (do no t reset) P2 Q S X Y Y (do no t reset) Z

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY; // NOT USED OUTS IDE C PM RSC =51, / / R ead spec ia l a n d cen t ra l ( o u t p u t t o B o n ly, n o t o u t s id e C P M ) WSC =52, / / Write spe c ia l a n d cen t ra l ( o u t p u t t o B o n ly, n o t o u t s id e C P M ) WG =53, / / W r it e G (o u tp u t t o B o nly , n o t o u ts id e CP M ) // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY; // NOT USED OUTS IDE C PM SDV1 =54, // Subsequence D V1 is currently active SMP1 =55, // Subsequence M P1 is currently active S R S M3 =56, // Subsequence RS M3 is currently active / / E X TE R NA L OU T PU T S F RO M // RA0 =57, RA1 =58, RA2 =59, RA3 =60, RA4 =61, RA5 =62, RA6 =63, RA7 =64, RA10 =65, RA11 =66, RA12 =67, RA13 =68, RA14 =69, RBK =70, WA0 =71, WA1 =72, WA2 =73, WA3 =74, WA10 =75, WA11 =76, WA12 =77, WA13 =78, WA14 =79, WBK =80, WGn =81, W20 =82, W21 =83, W22 =84, W23 =85, S U BS Y S TE M B // // // // // // // // // // // // // // // // // // // // // // // // // // // // // R e a d re g is te r at a dd r es s 0 ( A ) R e ad re g is te r a t a dd re ss 1 ( Q ) R e a d re g is te r at a dd r es s 2 ( Z ) R ead reg i st er a t a d d res s 3 (L P ) Read reg ister at address 4 Read reg ister at address 5 Read reg ister at address 6 Read reg ister at address 7 R ea d r eg iste r a t a dd re ss 10 (o ct al) R ea d r eg iste r a t a dd re ss 11 (o ct al) R ea d r eg iste r a t a dd re ss 12 (o ct al) R ea d r eg iste r a t a dd re ss 13 (o ct al) R ea d r eg iste r a t a dd re ss 14 (o ct al) R e a d BN K W r it e re g is te r at a dd r es s 0 ( A ) W r it e r eg is te r a t a dd re ss 1 ( Q ) W r it e re g is te r at a dd r es s 2 ( Z ) Write regis t er a t a d d res s 3 (L P ) W rite re gis te r a t a dd re ss 10 (o ct al) W rite re gis te r a t a dd re ss 11 (o ct al) W rite re gis te r a t a dd re ss 12 (o ct al) W rite re gis te r a t a dd re ss 13 (o ct al) W rite re gis te r a t a dd re ss 14 (o ct al) W r it e B NK W r i te G ( n o rm a l g at e s )* * W r i te in t o C Y R W r it e in t o S R W r i te in t o C Y L W r it e in t o S L

/ / T H E SE A RE T H E L EF TO V E RS -- TH E Y 'R E PR O B AB L Y U S ED IN S UB S YS T EM C // GENRST =86, / / G e n e r a l R e s e t* * C L IN H =87, / / C l e ar IN H I N T * * C L IN H 1 =88, / / C l e ar IN H I N T 1 * * CLSTA =89, / / C l e ar s ta t e co u n t e r A ( S T A ) ** CLSTB =90, / / C l e ar s ta t e co u n t e r B ( S T B )* * C L IS Q =91, / / C l e ar S N I ** CLRP =92, / / C l e ar R P C E L L* * INH =93, / / S e t IN H I N T * * RP T =94, / / R e a d R U P T op c o d e ** S BW G =95, // Write G from m em ory SETSTB =96, / / S e t th e S T 1 b it o f S T B

WE WPCTR WSQ WSTB R2000 };

=97, =98, =99, =100, =101,

// // // // //

W r ite W r i te W r it e W r i te Read

E-M E M fr om G P C T R ( la t ch p r io r it y co u n t e r s e q u e n ce ) * * SQ s t ag e c o u n te r B (S T B ) * * 2000 **

s ta t ic cp T y pe g lb l_ c p [M A X P U L S E S] ; / / c u rr e n t s e t o f a s se r te d c on t ro l p u ls e s ( M A X P U LS E S ) e num scTy pe { / / identifies subsequence for a given i n st ru c ti o n SUB0=0, / / S T 2 = 0, ST 1 = 0 SUB1=1, / / S T 2 = 0, ST 1 = 1 SUB2=2, / / S T 2 = 1, ST 1 = 0 S U B 3 =3 / / S T 2 = 1, ST 1 = 1 }; enum brType { BR00 BR01 BR10 BR11 NO_BR };

=0, =1, =2, =3, =4

// // // // //

B R 1 = 0, BR 2 = 0 B R 1 = 0, BR 2 = 1 B R 1 = 1, BR 2 = 0 B R 1 = 1, BR 2 = 1 N O B R A NC H

str uct co ntr o lS ubStep { b r T y pe b r ; / / n o r m a lly n o b ra n c h (N O _ B R ) c p T y pe p u ls e [ M A X _ IP U L S E S ] ; / / c o n ta in s 0 - M A X P U L S E S c o n tr o l p u ls e s }; str uct co ntr o lS tep { c o n tr o lS u b S t e p su b s te p [ 4 ]; // in d e x e d b y b r T y pe ( B R 0 0 , B R 0 1 , B R 1 0, B R 1 1 ) }; s t ru c t su b s e q u e n ce { c o n tr o lS t e p tp [ 1 1 ]; // in d e x e d b y t p T yp e ( T P1 - T P 1 1 ) }; s t ru c t se q u e n c e { subsequence* subseq[4] ; // indexed by sc Typ e }; # d e f in e S T E P _ I N A C T IV E \ NO_BR, {N O_ PU LSE , NO_BR, {N O_ PU LSE , NO_BR, {N O_ PU LSE , NO_BR, {NO_PULSE, #de fine STE P(p1 , p2, p3 , p4, p5 ) NO_BR, { p1 , p2, p 3, NO_BR, {N O_ PU LSE , NO_BR, {N O_ PU LSE , NO_BR, {NO_PULSE,

NO _PU LSE , NO _PU LSE , NO _PU LSE , N O _ P U LS E ,

NO _PU LSE , NO _PU LSE , NO _PU LSE , NO_PULSE,

NO _PU LSE , NO _PU LSE , NO _PU LSE , NO_PULSE,

NO _PU LSE }, \ NO _PU LSE }, \ NO _PU LSE }, \ N O _ P U LS E }

\ p4 , p5} , \ NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \ NO _PU LSE , NO _PU LSE , NO _PU LSE , NO _PU LSE }, \ N O _ P U LS E , N O _ P U L S E , N O _ P U L S E , N O _ P U LS E }

s u bs e qu e n ce S U B _T C 0 = { S TEP ( RB, S TEP _ INAC TIVE, / / TP 2 S TEP ( WG, S TEP ( RA, S TEP _ INAC TIVE, / / TP 5 S TEP _ INAC TIVE, / / TP 6 S TEP ( RG, S TEP ( RZ, S TEP ( RB, S TEP ( RU, S TEP ( N IS Q , }; s u bs e qu e n ce S U B _C C S 0 = { S TEP ( RB, S TEP ( RZ, S TEP ( WG, S TEP _ INAC TIVE, / / TP 4 S TEP _ INAC TIVE, / / TP 5 S TEP ( RG, BR00, RC, BR01, RC,

WY, NO_PULSE, W OV I,

WS, NO_PULSE, NO_PULSE,

CI, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3 ) , // T P 4

RSC, WQ, WSC, WZ, NO_PULSE,

WB, GP, WG, NO_PULSE, NO_PULSE,

WP , TP , NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

), ), ), ), ),

// // // // //

TP TP TP TP TP

7 8 9 10 11

WS, WY, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 ) , // T P 3

RSC, TMZ, TMZ,

WB, NO_PULSE, NO_PULSE,

TSGN, NO_PULSE, NO_PULSE,

WP NO_PULSE, NO_PULSE,

) , // T P 6 // TP 7

BR10, BR11, BR00, BR01, BR10, BR11, S TEP ( BR00, BR01, BR10, BR11, S TEP ( };

RB, RB, GP, R1, R2, R1, RB, RC, WA, RB, WA, RU,

TMZ, TMZ, TP, WX, WX, R2, WSC, WA, R1C, WA, R1C, ST1,

NO_PULSE, NO_PULSE, NO_PULSE, GP, GP, WX, WG, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WZ,

NO_PULSE, NO_PULSE, NO_PULSE, TP , TP , GP, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, TP , N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE

// TP 8

) , // T P 9 // TP 10

) // T P 1 1

s u bs e qu e n ce S U B _C C S 1 = S TEP ( RZ, S TEP _ INAC TIVE, S TEP ( WG, S TEP ( RU, S TEP ( RA, S TEP _ INAC TIVE, S TEP ( RG, S TEP ( RU, S TEP _ INAC TIVE, S TEP ( RC, S TEP ( RG, }; s u bs e qu e n ce S U B _N D X 0 = S TEP ( RB, S TEP _ INAC TIVE, S TEP ( WG, S TEP ( RA, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP ( RG, S TEP ( GP, S TEP ( RB, S TEP ( T R SM , S TEP ( ST1, }; s u bs e qu e n ce S U B _N D X 1 = S TEP ( RZ, S TEP _ INAC TIVE, S TEP ( WG, S TEP ( RU, S TEP _ INAC TIVE, S TEP ( RB, S TEP ( RG, S TEP ( RB, S TEP ( RB, S T E P _ I N A C T IV E , S TEP ( RU, }; s u bs e qu e n ce S U B _R S M 3 = S TEP ( R24, S TEP _ INAC TIVE, S TEP ( WG, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP ( RG, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S T E P _ I N A C T IV E , S TEP ( N IS Q , };

{ WY, / / TP 2 NO_PULSE, WZ, WY, / / TP 6 RSC, WB, / / TP 9 WA, RSC, W OV I, WB, NO_PULSE, N IS Q , N O _ P U L SE N O _ P U L SE ), // TP 10 ) // T P 1 1 WB, GP, WP , TP , N O _ P U L SE N O _ P U L SE ) , // T P 7 ) , // T P 8 NO_PULSE, NO_PULSE, CI, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE ) , // T P 3 ) , // T P 4 ) , // T P 5 WS, CI, N O _ P U L SE ) , // T P 1

{ WS, / / TP 2 NO_PULSE, W OV I, / / TP 5 / / TP 6 RSC, TP, WSC, NO_PULSE, NO_PULSE, WB, NO_PULSE, WG, NO_PULSE, NO_PULSE, WP , NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE ), ), ), ), ), // // // // // TP TP TP TP TP 7 8 9 10 11 NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE ) , // T P 3 ) , // T P 4 NO_PULSE, NO_PULSE, N O _ P U L SE ) , // T P 1

{ WY, / / TP 2 NO_PULSE, WZ, / / TP 5 WY, RSC, WX, WSC, // T P 1 0 WB, W OV I, N IS Q , N O _ P U L SE ), // TP 11 NO_PULSE, WB, GP, WG, NO_PULSE, WP , TP , NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE ), ), ), ), // // // // TP TP TP TP 6 7 8 9 NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE ) , // T P 3 ) , // T P 4 WS, CI, N O _ P U L SE ) , // T P 1

{ WS, / / TP 2 NO_PULSE, / / TP 4 / / TP 5 / / TP 6 WZ, / / TP 8 / / TP 9 // T P 1 0 NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE ), // TP 11 NO_PULSE, NO_PULSE, N O _ P U L SE ) , // T P 7 NO_PULSE, NO_PULSE, N O _ P U L SE ) , // T P 3 NO_PULSE, NO_PULSE, N O _ P U L SE ) , // T P 1

s u bs e qu e n ce S U B _X C H 0 = { S TEP ( RB, S TEP ( RA, S TEP ( WG, S TEP ( WP2, S TEP _ INAC TIVE, / / TP 5

WS, WP, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

), ), ), ),

// // // //

TP TP TP TP

1 2 3 4

S TEP _ INAC TIVE, / / TP 6 S TEP ( RG, S TEP ( GP, S TEP ( RA, S TEP ( RB, S TEP ( ST2, }; s u bs e qu e n ce S U B _C S 0 = { S TEP ( RB, S TEP _ INAC TIVE, S TEP ( WG, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP ( RG, S TEP ( GP, S TEP ( RB, S TEP ( RC, S TEP ( ST2, };

RSC, TP, WSC, WA, NO_PULSE,

WB, NO_PULSE, WG, W OV I, NO_PULSE,

WP , NO_PULSE, RP2, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

), ), ), ), ),

// // // // //

TP TP TP TP TP

7 8 9 10 11

WS, / / TP 2 NO_PULSE, / / TP 4 / / TP 5 / / TP 6 RSC, TP, WSC, WA, NO_PULSE,

NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3

WB, NO_PULSE, WG, W OV I, NO_PULSE,

WP , NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

), ), ), ), ),

// // // // //

TP TP TP TP TP

7 8 9 10 11

s u bs e qu e n ce S U B _T S 0 = { S TEP ( RB, S TEP ( RA, ), // T P 2 S TEP ( WG, BR00, NO_PULSE, BR01, RZ, o v e r flo w BR10, RZ, unde r f lo w BR11, NO_PULSE, BR00, NO_PULSE, BR01, R1, BR10, WA, BR11, NO_PULSE, S TEP _ INAC TIVE, / / TP 6 BR00, NO_PULSE, BR01, RU, BR10, RU, BR11, NO_PULSE, S TEP ( GP, S TEP ( RB, ), // T P 9 S TEP ( RA, S TEP ( ST2, }; s u bs e qu e n ce S U B _A D 0 = { S TEP ( RB, S TEP ( RA, S TEP ( WG, S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP ( RG, S TEP ( RB, S TEP ( RB, S T E P _ I N A C T IV E , // S TEP ( RU, };

WS, WB, NO_PULSE, NO_PULSE, WY, WY, NO_PULSE, NO_PULSE, WA, R1C, NO_PULSE, NO_PULSE, WZ, WZ, NO_PULSE, NO_PULSE, WSC, W OV I, NO_PULSE,

NO_PULSE, TOV, NO_PULSE, NO_PULSE, CI, CI, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WG, NO_PULSE, NO_PULSE,

NO_PULSE, WP , NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE ) , // T P 1 N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, ) , // T P 3 // TP 4 // //

// TP 5

NO_PULSE, NO_PULSE, // TP 7 NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE ) , // T P 8 NO_PULSE, N O _ P U L SE NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE ), // TP 10 ), // TP 11

WS, WY, NO_PULSE, TP 4 TP 5 TP 6 RSC, WX, WSC, TP 10 WA,

NO_PULSE, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 ) , // T P 3

WB, GP, WG, WOVC,

WP , TP , NO_PULSE, ST2,

N O _ P U L SE N O _ P U L SE N O _ P U L SE WOVI

) , // T P 7 ) , // T P 8 ) , // T P 9 ), // TP 11

// No te: A ND is perfo rm ed u sing D eM orga n's T he ore m : the inpu ts are inver ted , a / / lo g ic a l O R i s p e r fo r m e d , a n d t h e r e s u lt is in v e r te d . T he im p l e m e n t at io n o f t h e // OR (at TP8 ) is somewh at unortho dox: the inverted inpu ts are in registers U / / a n d C . T he O R i s a c h ie v e d b y g a t in g b o th r e g is t e rs o n to t h e re a d / w rit e b u s // simu ltaneously. (The bus on ly transfers logical 1's; register-to-register transfers / / a r e p e rf o rm e d b y c le a r in g t h e de s t in a t io n r e g is t e r a n d t h en t ra n s fe r r in g t h e // 1's from the so urce r egister to th e de stination). W hen the 1 's from b oth // re giste r s a re s imultaneously gated onto the bus, th e wo rd o n t h e b u s i s a l og i ca l // OR of both reg isters. s u bs e qu e n ce S U B _M A S K 0 = { S TEP ( RB, WS, NO_PULSE, NO_PULSE, S TEP ( RA, WB, NO_PULSE, NO_PULSE, S TEP ( WG, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 ) , // T P 3

S TEP ( RC, S TEP _ INAC TIVE, / / TP 5 S TEP _ INAC TIVE, / / TP 6 S TEP ( RG, S TEP ( RU, ( C H AN G E D ) S TEP _ INAC TIVE, / / TP 9 S TEP ( RA, ( C H AN G E D ) S TEP ( RC, }; s u bs e qu e n ce S U B _M P 0 = { S TEP ( RB, S TEP ( RA, S TEP ( RSC, BR00, RB, BR01, RB, BR10, RC, BR11, RC, S TEP ( R LP, S TEP _ INAC TIVE, / / TP 6 BR00, RG, BR01, RG, BR10, RG, BR11, RG, BR00, GP, BR01, GP, BR10, RC, BR11, RC, S TEP ( RU, BR00, RA, BR01, RA, BR10, RA, BR11, RA, BR00, ST1, BR01, R1, BR10, RU, BR11, RU, }; s u bs e qu e n ce S U B _M P 1 = { S TEP ( RA, S TEP ( R LP, BR00, NO_PULSE, BR01, NO_PULSE, BR10, RB, BR11, RB, S TEP ( RA, S TEP ( R LP, S TEP ( RU, S TEP ( RA, BR00, NO_PULSE, BR01, NO_PULSE, BR10, RB, BR11, RB, S TEP ( R LP, S TEP ( RA, S TEP ( RU, }; s u bs e qu e n ce S U B _M P 3 = { S TEP ( RZ, S TEP ( R LP, S TEP ( WG, S TEP ( RU, S TEP ( RA, BR00, NO_PULSE, BR01, NO_PULSE, BR10, RB, BR11, RB, S TEP ( RG, S TEP ( R LP, S TEP ( RB, S TEP ( RA, S TEP ( RU,

WY,

NO_PULSE,

NO_PULSE,

N O _ P U L SE

) , // T P 4

RSC, RC,

WB, WA,

WP , GP,

N O _ P U L SE TP

) , // T P 7 ), // TP 8

WB, WA,

NO_PULSE, ST2,

NO_PULSE, W OV I,

N O _ P U L SE N O _ P U L SE

), // TP 10 ), // TP 11

WS, WB, WG, WLP, WLP, WLP, WLP, WA, WY, WY, WB, WB, TP, TP, WY, WY, WB, WLP, RB14, WLP, RB14, WALP, ST1, ST1, ST1,

NO_PULSE, TSGN, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WP , WP , WP , WP , NO_PULSE, NO_PULSE, GP, GP, TSGN2, TSGN, WL P , TSGN, WL P , NO_PULSE, WA L P , WA L P , WA L P ,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, TP , TP , NO_PULSE, NO_PULSE, TSGN, NO_PULSE, TSGN, NO_PULSE, R1C, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

) , // T P ) , // T P ) , // T P // TP

1 2 3 4

) , // T P 5 // TP 7

// TP 8

) , // T P 9 // TP 10

// TP 11

WY, WA, NO_PULSE, NO_PULSE, WX, WX, WLP, TSGN, WALP, WY, NO_PULSE, NO_PULSE, WX, WX, WA, WLP, ST1,

NO_PULSE, TSGN, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, CTR, WA L P ,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 // TP 3

), ), ), ),

// // // // //

TP TP TP TP TP

4 5 6 7 8

) , // T P 9 ), // TP 10 ), // TP 11

WY, TSGN, NO_PULSE, WZ, WY, NO_PULSE, NO_PULSE, WX, WX, RSC, WA, WSC, WLP, WALP,

WS, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WB, GP, WG, NO_PULSE, N IS Q ,

CI, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WP , TP , NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

), ), ), ), ),

// // // // // //

TP TP TP TP TP TP

1 2 3 4 5 6

), ), ), ), ),

// // // // //

TP TP TP TP TP

7 8 9 10 11

}; s u bs e qu e n ce S U B _D V 0 = { S TEP ( RB, S TEP ( RA, S TEP ( RSC, BR00, RC, BR01, RC, BR10, NO_PULSE, BR11, NO_PULSE, BR00, R1, BR01, R1, BR10, R2, BR11, R2, S TEP ( RA, S TEP ( RG, S TEP ( RB, BR00, R LP, BR01, R LP, BR10, NO_PULSE, BR11, NO_PULSE, BR00, RB, BR01, RB, BR10, RC, BR11, RC, S TEP ( R1, }; s u bs e qu e n ce S U B _D V 1 = { S TEP ( R22, S TEP ( RQ, S TEP ( RG, S TEP ( RA, S TEP ( R LP, S TEP _ INAC TIVE, / / TP 6 S TEP ( RU, BR00, NO_PULSE, BR01, NO_PULSE, BR10, RU, BR11, RU, BR00, RB, BR01, RB, BR10, RB, BR11, RB, S TEP ( RG, BR00, ST1, BR01, ST1, BR10, RC, BR11, RB, }; s u bs e qu e n ce S U B _S U 0 = { S TEP ( RB, S TEP ( RA, S TEP ( WG, S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP ( RG, S TEP ( RC, S TEP ( RB, S T E P _ I N A C T IV E , // S TEP ( RU, }; s u bs e qu e n ce S U B _R U P T1 = { S TEP ( R24, S TEP _ INAC TIVE, / / S TEP ( WG, S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP ( RZ, S TEP ( RU,

WS, WB, WG, WA, WA, NO_PULSE, NO_PULSE, WLP, WLP, WLP, WLP, WQ, WB, WA, R2, R2, NO_PULSE, NO_PULSE, WLP, WLP, WA, WA, ST1,

NO_PULSE, TSGN, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, TSGN, GP, WB, WB, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WB,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WP , TP , NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE

) , // T P ) , // T P ) , // T P // TP

1 2 3 4

// TP 5

) , // T P ) , // T P ) , // T P // TP

6 7 8 9

// TP 10

), // TP 11

WS, WG, WQ, WX, TSGN2, TSGN, NO_PULSE, NO_PULSE, WQ, WQ, RSB, RSB, WG, WG, WB, NO_PULSE, NO_PULSE, WA, WA,

NO_PULSE, NO_PULSE, WY, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, WG, WG, NO_PULSE, NO_PULSE, TSGN, NO_PULSE, NO_PULSE, ST2, ST2,

NO_PULSE, NO_PULSE, RSB, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, N O _ P U L SE NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

), ), ), ), ),

// // // // //

TP TP TP TP TP

1 2 3 4 5

) , // T P 7 // TP 8

// TP 9

), // TP 10 // TP 11

WS, WY, NO_PULSE, TP 4 TP 5 TP 6 RSC, WX, WSC, TP 10 WA,

NO_PULSE, NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 ) , // T P 3

WB, GP, WG, WOVC,

WP , TP , NO_PULSE, ST2,

N O _ P U L SE N O _ P U L SE N O _ P U L SE WOVI

) , // T P 7 ) , // T P 8 ) , // T P 9 ), // TP 11

WY, TP 2 NO_PULSE, TP TP TP TP TP 4 5 6 7 8 WG, WZ,

WS, NO_PULSE,

CI, NO_PULSE,

N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3

NO_PULSE, NO_PULSE,

NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE

) , // T P 9 ), // TP 10

S TEP ( };

ST1,

ST2,

NO_PULSE,

NO_PULSE,

N O _ P U L SE

), // TP 11

s u bs e qu e n ce S U B _R U P T3 = { S TEP ( RZ, S TEP ( RRPA, S TEP ( RZ, S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP _ INAC TIVE, / / S TEP ( RB, S T E P _ I N A C T IV E , // S TEP ( ST2, }; s u bs e qu e n ce S U B _S T D 2 = S TEP ( RZ, S TEP _ INAC TIVE, S TEP ( WG, S TEP ( RU, S TEP _ INAC TIVE, S TEP _ INAC TIVE, S TEP ( RG, S TEP ( GP, S TEP ( RB, S T E P _ I N A C T IV E , S TEP ( N IS Q , }; {

WS, WZ, KRPT, TP TP TP TP TP 4 5 6 7 8 WSC, TP 10 NO_PULSE,

NO_PULSE, NO_PULSE, WG,

NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 2 ) , // T P 3

WG, NO_PULSE,

NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE

) , // T P 9 ), // TP 11

WY, / / TP 2 NO_PULSE, WZ, / / TP 5 / / TP 6 RSC, TP, WSC, // T P 1 0 NO_PULSE,

WS, NO_PULSE, NO_PULSE,

CI, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3 ) , // T P

WB, NO_PULSE, WG, NO_PULSE,

WP , NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 7 ) , // T P 8 ) , // T P 9 ), // TP 11

s u bs e qu e n ce S U B _P IN C = { S TEP ( WS, S TEP _ INAC TIVE, / / TP 2 S TEP ( WG, S TEP ( R1, S TEP _ INAC TIVE, / / TP 5 S TEP ( RG, S TEP ( TP, S TEP ( WP, S TEP ( RU, S TEP ( RU, S T E P _ I N A C T IV E , // T P 1 1 }; s u bs e qu e n ce S U B _M I N C = { S TEP ( WS, S TEP _ INAC TIVE, / / TP 2 S TEP ( WG, S TEP ( WY, S TEP _ INAC TIVE, / / TP 5 S TEP ( RG, S TEP ( TP, S TEP ( WP, S TEP ( RU, S TEP ( RU, S T E P _ I N A C T IV E , // T P 1 1 }; s u bs e qu e n ce S U B _S H IN C = { S TEP ( WS, S TEP _ INAC TIVE, / / TP 2 S TEP ( WG, S TEP ( WY, S TEP _ INAC TIVE, / / TP 5 S TEP ( RG, S TEP ( TP, S TEP ( WP, S TEP ( RU, S TEP ( RU, S T E P _ I N A C T IV E , // T P 1 1 }; char* subse qString [] = { "TC0",

RSCT, NO_PULSE, WY, WX, NO_PULSE, NO_PULSE, CLG, WG x,

NO_PULSE, NO_PULSE, NO_PULSE, WP , NO_PULSE, NO_PULSE, WPx, WOVR,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3 ) , // T P 4 ), ), ), ), ), // // // // // TP TP TP TP TP 6 7 8 9 10

RSCT, NO_PULSE, R1C, WX, NO_PULSE, NO_PULSE, CLG, WG x,

NO_PULSE, NO_PULSE, NO_PULSE, WP , NO_PULSE, NO_PULSE, WPx, WOVR,

NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3 ) , // T P 4 ), ), ), ), ), // // // // // TP TP TP TP TP 6 7 8 9 10

RSCT, NO_PULSE, NO_PULSE, WYx, NO_PULSE, NO_PULSE, CLG, WG x,

NO_PULSE, NO_PULSE, NO_PULSE, WX, NO_PULSE, NO_PULSE, WPx, WOVR,

NO_PULSE, NO_PULSE, NO_PULSE, WP , NO_PULSE, NO_PULSE, NO_PULSE, NO_PULSE,

N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE N O _ P U L SE

) , // T P 1 ) , // T P 3 ) , // T P 4 ), ), ), ), ), // // // // // TP TP TP TP TP 6 7 8 9 10

"CCS0 ", "CCS1 ", "NDX0 ", "NDX1 ", "RSM3 ", "XCH 0", "CS0", "TS0", "AD0", "MAS K0", "MP0", "MP1", "MP3", "DV0", "DV1", "SU0", "RUPT1", "RUPT3", "STD2 ", "PINC0", "MINC0", "SHINC0 ", " NO _ S EQ " }; e num subse q { TC0 CCS0 CCS1 NDX0 NDX1 RSM3 XCH0 CS0 TS0 AD0 MASK0 MP0 MP1 MP3 DV0 DV1 SU0 RUPT1 RUPT3 STD2 P IN C 0 M I N C0 S H IN C 0 NO_SEQ };

=0, =1, =2, =3, =4, =5, =6, =7, =8, =9, =10, =11, =12, =13, =14, =15, =16, =17, =18, =19, =20, =21, =22, =23

enum tpType { STBY PWRON TP 1 TP 2 TP 3 TP 4 TP 5 TP 6 TP 7 TP 8 TP 9 TP10 TP11 TP12 SRLSE W AIT };

=0, =1, =2, =3, =4, =5, =6, =7, =8, =9, =10, =11, =12, =13, =14, =15 / / T I M E P U L S E 1 : s t ar t of m e m o r y cy c le t im e ( M C T )

/ / EMEM is a va i la b l e in G reg i st er b y TP 6 / / FMEM is a va il a b le i n G reg is t er b y TP 7

/ / G r e g is t e r w r it te n t o m e m o r y b e g in n in g a t T P1 0 / / T I M E P U L S E 1 1: e n d of m e m o r y cy c le t im e ( M C T ) / / select new s u b s eq u en c e/ sel ect n ew i n st ru c ti o n // step switch release

subseq instructionSu bsequ enceD ecoder( int S B2_field, int SB1_field, int SQ_field, in t S TB _ fiel d )

{ // Com binationa l logic deco des instru ction an d the stage coun t / / t o g et th e in s t ru c t io n s u b se q u e n c e . s ta tic su b se q de c od e [1 6 ][ 4] = { { TC0, RUPT1, STD2, { CCS0, CCS1, N O _ SE Q , { NDX0, NDX1, N O _ SE Q , { XCH0, N O _ SE Q , STD2, { { { { { { { { { { { { }; if (S B 2 _ f ie ld = = 0 & & S B 1 _ f ie ld = = 1 ) r e tu r n P IN C 0 ; e ls e if (S B 2 _ f ie ld = = 1 & & S B 1 _ f ie ld = = 0 ) r e tu r n M I N C 0 ; else return deco de[S Q_ field][STB_ field]; } void clearC ontrolPu lses() { f or (u n sig n e d i= 0 ; i< M A X P UL S E S; i+ + ) g lb l_ c p [i] = N O _ P U L S E ; } v o id a s se r t( c pT y p e * p u ls e ) { in t j= 0 ; f or (u n sig n e d i= 0 ; i< M A X P UL S E S & & j< M A X _ IP U LS E S & & p u ls e [j ] ! = NO _ P U LS E ; i+ + ) { if (g lb l_ c p [i] = = N O _ P U L S E ) { glbl_cp[i] = pu lse[j]; j + +; } } } v o id a s se r t( c pT y p e p u ls e ) { f or (u n sig n e d i= 0 ; i< M A X P UL S E S; i+ + ) { if (g lb l_ c p [i] = = N O _ P U L S E ) { g lb l_ c p [i] = p u ls e ; break; } } } void get_CP M_A (int CPM_A _addre ss) { / / E P R O M a d dr e ss // 1: // 2: // 3-6: r e g is t e r // 7,8: r e g is t e r / / 9 - 1 2 : r e g is t e r // 13: // 14: N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , MP0, DV0, SU0, CS0, TS0, AD0, MASK0, N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , MP1, DV1, N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , N O _ SE Q , STD2, STD2, STD2, STD2, STD2, STD2,

RUPT3 NO_SEQ RSM3 NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ MP3 NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ

}, }, }, }, }, }, }, }, },

// // // // // // // // //

00 01 02 03 04 05 06 07 10

} , // 1 1 } , // 1 2 } , // 1 3 }, }, }, } // // // // 14 15 16 17

b it s ( b it 1 is L SB ) r e g is t e r B R 2 r e g is t e r B R 1 SG (4) STB (2) SQ (4) STB_01 STB_02

/ /* * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * // EP ROM emulator in t S B 2 _ fie ld = ( C P M _ A _ a d d re s s > > 1 3 ) & 0 x 1 ; in t S B 1 _ fie ld = ( C P M _ A _ a d d re s s > > 1 2 ) & 0 x 1 ; int S Q_ field = (C PM _A _a dd res s > > 8 ) & 0 xf; in t S T B _ fie ld = ( C P M _ A _ a d d re s s > > 6 ) & 0 x 3 ; int S G_ field = (C PM _A _a dd res s > > 2 ) & 0 xf; in t B R 1 _ fie ld = ( C P M _ A _ a d d re s s > > 1 ) & 0 x 1 ; in t B R 2 _ fie ld = ( C P M _ A _ a d d re s s ) & 0x1;

// Dec ode the cu rrent instru ction sub sequ ence (glbl_subse q). subse q glbl_sub seq = instructionS ubse que nceD ecod er(SB 2_field, SB 1_field, SQ _field, STB _field); s ta tic su b se q u en c e* s ub sp [] = { &SUB_TC0, &SUB_CCS0, &SUB_XCH0, &SUB_CS0, &SUB_MP1, &SUB_MP3, &SUB_RUPT3, &SUB_STD2, }; // Clear old control pulses. clearCo ntrolPulses (); / / G e t n e w c on t ro l p u ls e s fo r th e c u r re n t in s t ru c t io n s u b se q u e n c e . if( glb l_ su b se q != N O _S E Q && // TH IS T ES T S O U T OK S G _ fie ld > = T P 1 && S G _ f ie ld < = T P 1 1 ) { subse que nce* subse qP = subsp [glbl_subse q]; if( subseqP) { // index t-2 b ecause TP1= 2, but array is indexed from zero contro lStep& csref = s ubse qP-> tp[SG _field-2]; brTyp e b = (brTyp e) ((BR 1_field << 1) | BR 2_field); contro lSubS tep& cssref = csref.sub step[b ]; if (c s sr e f. b r = = N O _ B R ) cssref = csref.sub step[0 ]; c p T y pe * p = c s sr e f. p u ls e ; asser t(p); } } // Impleme nt these h ere, becau se the instruction seque nce de coder / / function is buried in the C PM- A RO M a n d s o , id en t ific a t io n o f // th e se qu en ces is no t av ailab le ou tside CP M -A. CP M -C ne ed s info // on these 3 seque nces. switch ( glbl_subseq) { case DV1: assert(SDV1); break; case MP1: assert(SMP1); break; c a s e RS M 3 : assert(SRSM3); break; } / /* * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * * * * * * * * * * * * ** * *

&SUB_CCS1, &SUB_TS0, &SUB_DV0, & S U B _P IN C ,

&SUB_NDX0, &SUB_AD0, &SUB_DV1, & S U B _M I N C,

&SUB_NDX1, &SUB_MASK0, &SUB_SU0, &S UB _S HIN C,0

&SUB_RSM3, &SUB_MP0, &SUB_RUPT1,

} c h ar * c pT y pe S tr in g [] = { "NO_PU LSE", / / O U T PU T S F RO M S U BS Y S TE M A "CI" , "CL G" , "CL CT R", "C TR ", "G P", "K RPT ", "N ISQ ", "RA ", "RB ", "RB 14 ", "RC ", "RG ", "RL P", "R P2" , "RQ ", "RR PA ", "RS B", " RS CT ", "RU ", "RZ ", "R1 ", "R1 C", " R2 ", "R2 2", "R 24 ", "S T1 ", "S T2 ", "TM Z", "TO V", " TP" , "TR SM ", "TS GN ", "TS GN 2", "W A", " W ALP ", "W B", " W Gx ", "W LP", " W OV C", " W OV I", "W OV R", "W P", "W Px" , "W P2" , "W Q" , "W S", "WX", "W Y", "WYx", "WZ", // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY; // NOT USED OUTS IDE C PM

// "RSC", "WS C", "WG", // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY; // NOT USED OUTS IDE C PM // "SDV1 ", "SMP1", "SRSM 3", / / E X TE R NA L OU T PU T S F RO M S U BS Y S TE M B // "RA 0", "R A1 ", "RA 2", "R A3 ", "RA 4", "R A5 ", "RA 6", "R A7 ", "RA 10 ", "RA 11 ", "RA 12 ", "RA 13 ", "RA 14 ", "RB K", "W A0 ", "W A1 ", "W A2 ", "W A3 ", "W A1 0", "WA1 1", "WA12", "WA 13", "WA14 ", "WBK", "WG n", "W20", "W21 ", "W22", "W23", / / T H E SE A RE T H E L EF TO V E RS -- TH E Y 'R E PR O B AB L Y U S ED IN S UB S YS T EM C // "G EN RS T", "C LINH ", "C LINH 1", "C LST A", " CL ST B", " CL ISQ ", "C LRP ", "IN H" , " R P T " , " S B W G " , " S E T S T B ", "W E " , " W P C T R " , " W S Q " , " W S T B " , " R 2 0 0 0 " }; // f or de bu g p ur po se s o nly char* printCo ntrolPulses () { static char b uf[MA XPU LSE S*6 ]; strcpy(b uf,""); f or (u n sig n e d i= 0 ; i< M A X P UL S E S & & g lb l_ c p[ i] != N O _ PU L S E; i+ + ) { strcat(bu f, cpType String[g lbl_cp[i]]); strcat(bu f," "); } //if(strcmp(bu f,"") == 0) strcat(b uf,"NO NE" ); ret urn bu f; } / / r e tu r n th e E P R O M w o r d c or r e sp o n d in g t o th e p u ls e s // in glbl_cp. unsign ed w riteEPR OM (int lowBit) { un sig ne d E PR O M w or d = 0x 00 ; // no pu lse s; de fa ult f or (u n sig n e d i= 0 ; i< M A X P UL S E S & & g lb l_ c p[ i] != N O _ PU L S E; i+ + ) { int pulse = glbl_cp[i] - lowBit; if (p u ls e < 0 | | p u ls e > 7 ) c o n tin u e ; // p u ls e is n o t in t h is E P R O M E P R O M w o r d | = 0 x0 1 < < p u ls e ; } // printf("% 02X \n",EP RO Mw ord); //re turn EPR OMw ord; // The CPM -A con trol signals are n ega tive logic, so we n eed to // b it-f lip t he w or d. No sig na l is a 1, an d a n a ss er te d s ign al is // a 0: return ((~EP RO Mw ord) & 0xff); }

co nst unsigne d agcMem Size = 0x3fff+1; / / # of cells i n a 1 6 -b i t a d d res s ra n g e void writeE PRO M(FILE * fpO bj, int lowBit) { // Write a n EP RO M file using M otorola's S -Reco rd form at (s2f). / / S o m e p a r a m e t e rs t h at c on t ro l f ile f or m a t . Y o u c a n ch a n g e m a x B y te s / / w ithout affecting anything els e. 'a d d res s B ytes ' is d et ermin ed b y // the ch oose n S-R ecord forma t. const int m axB ytes = 20; // se t limit on record length co nst int addressBytes = 3; // 24- bit addre ss ra n g e c o n s t in t s u m C h e c kB y t e s = 1 ; const int maxd ata = m axBytes - ad dressByte s - sumC heckB ytes; int i=0; // current E PRO M ad dress in t s u m C h e c k = 0 ; w h i le ( i < a g c M e m S i ze ) {

/ / get dataByteC ount; t h e n u mb er o f b ytes o f E P RO M d a t a p er rec o rd . int dataByteC ount = maxdata; if (i + d a t a B yt e C o u n t > = a g c M e m S i ze ) { da ta B yt eC ou nt = ag cM em S ize - i; } / / w r it e re c o rd h e a d e r ( * * * 3 by t e ad d r e ss a s su m e d * * * ) int totalByteC ount = dataByte Coun t + addre ssBytes + sum Che ckBytes; fprintf(fpObj, "S 2% 02X % 06X ", totalByte Cou nt, i); su m Ch eck = t ota lByt eC ou nt & 0x ff; s u m C h e c k = ( su m C h e c k + ( (i & 0 x ff 0 0 0 0) > > 1 6 ) ) % 2 5 6 ; s u m C h e c k = ( su m C h e c k + ( (i & 0 x 0 0 ff 0 0 ) > > 8 ) ) % 2 5 6 ; s u m C h e c k = ( su m C h e c k + ( (i & 0 x 0 0 0 0 ff ) )) % 256; // write data bytes into record f or (in t j =0 ; j <d a ta B yt eC o u nt ; j ++ ) { g e t_ C P M _A ( i+ j ); // ge t C P M -A p u ls e s fo r a d dr e ss i+ j int data = w riteEPR OM ( l o wB it ) ; / / co mvert p u ls es t o E P RO M fo rma t fprintf(fpObj, "% 02X ", data); s u m C h e c k = ( su m C h e c k + d a t a) % 2 5 6 ; } / / t e rm i n a te r e c or d b y a d d in g t h e ch e c k su m a n d a n e w lin e . fprintf(fpObj, "% 02X \n", (~s um Ch eck) & 0xff); i += da taBy teCo unt; } // write an end-of-file record h ere i = 0; // use address ze ro for last record sumCheck = 0x04; // byte count s u m C h e c k = ( su m C h e c k + ( (i & 0 x ff 0 0 0 0) > > 1 6 ) ) % 2 5 6 ; s u m C h e c k = ( su m C h e c k + ( (i & 0 x 0 0 ff 0 0 ) > > 8 ) ) % 2 5 6 ; s u m C h e c k = ( su m C h e c k + ( (i & 0 x 0 0 0 0 ff ) )) % 256; fprintf(fpObj, "S 804 % 06X % 02X ", i, (~sum Ch eck) & 0xff); }

void m ain(int argc, ch ar* a rgv[]) { F I LE * f pO b j = 0 ;

fpOb j = fope n("C PM 1_8 .hex" , "w"); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } writeEP RO M(fpO bj, 1); // pulses 1 -8 fclose(fpOb j);

fpOb j = fope n("C PM 9_1 6.he x", "w" ); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 9 ) ; / / p u ls e s 9 -1 6 fclose(fpOb j);

fpOb j = fope n("C PM 17_ 24.h ex", "w "); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 1 7 ) ; / / p u ls e s 1 7- 2 4 fclose(fpOb j);

fpOb j = fope n("C PM 25_ 32.h ex", "w ");

if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 2 5 ) ; / / p u ls e s 2 5- 3 2 fclose(fpOb j);

fpOb j = fope n("C PM 33_ 40.h ex", "w "); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 3 3 ) ; / / p u ls e s 3 3- 4 0 fclose(fpOb j);

fpOb j = fope n("C PM 41_ 48.h ex", "w "); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 4 1 ) ; / / p u ls e s 4 1- 4 8 fclose(fpOb j);

fpOb j = fope n("C PM 49_ 56.h ex", "w "); if(!fpOb j) { perro r("fopen failed for object file"); exit(-1); } w r it e E P R O M ( fp O b j , 4 9 ) ; / / p u ls e s 4 9- 5 6 fclose(fpOb j); }

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 3: Processing (PROC) Module
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
The Processing Module (PROC) has 5 subsystems: PMI, ALU, CRG, INT, CTR PM I (P roce ssin g M od ule external Interface) The PMI interfaces other p ro cessin g m od ule su bsy stem s to external AG C m odules. 40-pin IDE connectors interface to th e other CT L, M EM , an d IO mo dules. Inputs from those mod ules are buffered to 1 LSTTL load. ALU (Arithm etic Log ic Unit) The A LU co ntain s the 1 6-bit AD DER to p erfo rm 1's complement arithmetic and increment the program counter (Z register). The ALU also contains the B and C registers, and logic to inclusive OR the contents of the them with the AD DE R. Th e inc lusive O R oc curs when the control modu le (CTL) issues signals to READ the conte nts of bo th registe rs onto the READ bus simultaneously. The ALU transfers data from the READ bus to the WRITE bus for regis ter-to -reg ister tra nsfers and can force the data lines of the WRITE bus to specific states to gate variou s consta nts into the AG C reg isters CRG (Cen tral Register) The A GC has fou r 16-b it central registers for general com pu tatio nal use . The se are the accumulator (A) for general computation; the program counter (Z) which contains the address of the next instruction; the Q register holding the remainder in the DV instruction, and the return address after TC instructions; and the LP register used to hold the lower produ ct after MP instructions. INT (Interrupt Priority) The original AGC had five vectored interrupts. This recreation implem ents three of them: RUPT1, also called T3RUPT which is used as general-purpose timer by the AGC WAITLIST software; RUPT3, also called T4RUPT or DSRUPT, which is used to update the DSKY display at regular intervals; and RUPT4, also called KERUPT, which is triggered by a key press from the user's keyboard. The AGC responds to each interrupt by temporarily suspending the current program, executing a short interrupt service routine, and then resuming the

interrupted program. CTR (Priority Cou nter) Tw enty m em ory lo catio ns in the o rigin al A GC function ed a s up /do wn cou nters. Th e cou nters would incremen t (PINC) or decrement (M INC) in response to external inputs. Increment or decrement was ha ndled by one 12-step subsequen ce of microinstructions inserted between any two regular instructions. This replica implemen ts 5 of the counters: OVCTR, an overflow counter increm ented or decrem ented by arithme tic overflow during certain in structions; TIME2 and TIME1, the AGC real-time clock; TIME3, a general purpose timer incremented by a 100Hz signal from the SCALER (SCL); and TIME4, a timer used to update the DSKY display.

The A LU h as a 1 6-bit parallel adder. The addend and augend are supplied by the X and Y registers. The sum, called the U register although it is not really a register at a ll, is gated to the read bus through the RU (read U) control signal. The WX and W Y con trol signa ls copy the contents of the w rite bus in to the X and Y registers.

The B register is loaded from the write bus with the W B (w rite B) sign al. The con tents of B are output to the read bus with the RB (read B) signal. The inv erted outp ut of B can be gated to the read bus with the RC (read C ) sign al.

The A GC has fou r user-acc essible ce ntral reg isters. The A register is the accum ulato r; Z is the program counter; Q stores the return address for jumps (TC instruction), and LP stores the lower product (MP instruction).

Cen tral register con tents can be output to the read bus by asserting the appropriate read control pulse (RA, RQ, RZ, or RLP ). Each register is also mapped to a m em ory locatio n, with register A ma ppe d to address 0, Q to ad dress 1, Z to 2, and LP to 3. The R0, R1, R2, and R3 control pulses output those registers to the read bus.

The w rite bus co nten ts can be loaded into a central register with a w rite co ntro l p uls e. W A and W ALP load the A register; WQ, the Q register; WZ the Z register; and WLP and W ALP the L P reg ister. The W0, W1, W2, and W3 control pulses m apped to m em ory addresses 0,1,2, and 3 also load those registers.

The in terrupt p riority subsystem m anages vectored interrupts. Five inte rrup ts (0-4) are imp lemen ted. Each interrup t is latched by its own RP cell flip-flop. Sign als from all RP cells feed into a priority encoder; a combinational logic arra y that o utpu ts the code of the hig hest priority interrupt in the RP ce lls. Wh en R PT is asserted , the priority code is la tched into RPCELL. This is decoded into an add ress wh ich is the interrupt vector; the address is written to the read b us w hen RR PA is asserted. After the interrupt code has b een loa ded into RPCELL, asserting KRPT (knock-down R PT) causes the RP cell for that interrup t to be reset. Th is causes the n ext highest priority interrupt to be decod ed by the priority enc ode r. The INHINT and INHINT1 flip-flops in hibit interrupts.

The priority counter logic design is similar to the interrupt subsystem. Up (+) and down (-) count inpu t signa ls feed into 20 PCELLs, one PCELL for each counter. The PCELLs feed into the priority encoder wh ich outputs the code of the h ighe st priority PCELL having a up or down input set. The PCELL code is written to the PCELL register wh en W PCT R is asserted. The PC ELL m em ory address, derived from PCE LL, is written to read bus when RSCT is asserted. After the code is la tched into the PCE LL reg ister, the corresponding PCELL is reset by asserting WOVR. The up or down code for the selected PCELL is written to PSEQ when WPCTR is asserted. This code feeds to the control lo gic on the CT L m odu le wh ich selec ts the PIN C (in crem ent) or M INC (d ecrem ent) instruction subsequence to bump the priority counter up or down. The PIN C and MIN C su bsequ enc es are inse rted b etw een norm al in struc tion sub sequen ces. A SHINC subsequence implements a bit-shift which is used to load telemetry bits into the AGC and assemble them into words. SHINC is not implemented in this AGC replica.

PROC Internal Subsystem Interconnections


This diagram show s internal interconnections for the subsystems in the PROC m odule.

PROC Module External Interfaces


The PROC modu le interfaces to the CTL, MEM, and IO m odules through 40-pin IDE ribbon cables.

J100-PROC: PROC-to-CTL I/F J100 is a 40-pin IDE cable that connects the PROC modu le to the CTL m odule. INPU TS (to PR OC): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 signal WA3 WA2 WA1 WA0 RA3 RA2 RA1 RA0 WZ WYx WY WX WQ WOVR WOVI WOVC WLP WB WA LP WA F10X R24 R22 R2 R1C R1 RZ RU RSCT RSB RRPA RQ RLP RC RB14 RB RA KRPT CI fu ll n am e WRITE ADDR 3 (74) WRITE ADDR 2 (73) WRITE ADDR 1 (72) WRITE ADDR 0 (71) READ ADDR 3 (60) READ ADDR 2 (59) READ ADDR 1 (58) READ ADDR 0 (57) WRITE Z (50) WRITE Y NO RESET (49) WRITE Y (48) WRITE X (47) WRITE Q (45) WRITE OVF (41) WRITE OVF RUPT INH (40) WRITE OVF CNTR (39) WRITE LP (38) WRITE B (36) WRITE A/LP (35) WRITE A (34) F10 SCALER ONESHOT READ 24 (25) READ 22 (24) READ 2 (23) READ 1 COMP (22) READ 1 (21) READ Z (20) READ U (19) READ CNTR ADDR (18) READ SIGN (17) READ RUPT ADDR (16) READ Q (15) READ LP (13) READ C (11) READ BIT 14 (10) READ B (9) READ A (8) KNOCK DOW N RUPT (6) SET CARRY IN (1) state definition 0=W rite reg at address 3 (LP) 0=Write reg at address 2 (Z) 0=Write reg at address 1 (Q) 0=Write reg at address 0 (A) 0=Read reg at address 3 (LP) 0=Read reg at address 2 (Z) 0=Read reg at address 1 (Q) 0=Read reg at address 0 (A) 0=W rite Z 0= W rite Y (do n ot reset) 0=W rite Y 0=W rite X 0=W rite Q 0=W rite overflow 0= W rite overflow RU PT inh ibit 0=W rite overflow counter 0=W rite LP 0=W rite B 0=W rite A and LP 0=W rite A 1=timed out (100.0 Hz) 0=Read 24 0=Read 22 0=Read 2 0=R ead 1 comp limented 0=Read 1 0=Read Z 0=Read sum 0=R ead selected cou nter address 0= Rea d sign bit 0=R ead RU PT add ress 0=Read Q 0=R ead LP 0=Read C 0=Read bit 14 0=Read B 0=Read A 0= Kn ock do wn Rup t priority 0= Carry in

J101-PROC: PROC-to-CTL I/F J101 is a 40-pin IDE cable that connects the PROC modu le to the CTL m odule. INPU TS (to PR OC): PIN 1 2 3 4 5 6 7 8 19 20 signal R2000 WPCTR RPT INH CLRP CLINH1 CLINH GENRST CLK1 CLK2 fu ll n am e READ 2000 (101) WRITE PCTR (98) READ RUPT (94) SET INHINT (93) CLEAR RPCELL (92) CLEAR INHINT1 (88) CLEAR INHINT (87) GENERAL RESET (86) CLOCK1 CLOCK2 state definition 0=Read 2000 0=Write PCTR (latch priority counter seq) 0=Read RUPT opcode 0=Set INHINT 0=Clear RPCE LL 0=Clear INHINT1 0=Clear INHINT 0=G eneral Reset 1.024 MHz AGC clock 1 (normally low) 1.024 MHz AGC clock 2 (normally low)

OUT PUTS (from PRO C): PIN 21 22 23 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 signal SB_01 SB_02 IRQ WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e SUB SEL 01 SUB SEL 02 INT RQST WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE WRITE BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS BUS 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 state definition SB_01 is LSB; SB_02 is MSB 00=no counter; 01=PINC; 10=MINC 0=interrupt requested. (lsb)

US (overflow ) bit SG (sign ) bit

J104-PROC: PROC-to-IO I/F J104 is a 40-pin IDE cable that connects the PROC modu le to the IO modu le. INPU TS (to PR OC): PIN 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 22 21 20 signal RB_01 RB_02 RB_03 RB_04 RB_05 RB_06 RB_07 RB_08 RB_09 RB_10 RB_11 RB_12 RB_13 RB_14 RB_15 RB_16 BUSY2 BUSY1 KB_STR fu ll n am e READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit 0=OUT register output to read bus 0=INP register output to read bus 1=key pressed strobe; to KEYRU PT. Key data is valid on the negative edge of KB_STR. Data is latched until the next keypress.

READ BUS BUSY READ BUS BUSY KEY STROBE

OUT PUTS (from PRO C): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 signal WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit

J105-PROC: PROC-to-MEM I/F J105 is a 40-pin IDE cable that connects the PROC modu le to the MEM modu le. INPU TS (to PR OC): PIN 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 22 bus 21 signal RB_01 RB_02 RB_03 RB_04 RB_05 RB_06 RB_07 RB_08 RB_09 RB_10 RB_11 RB_12 RB_13 RB_14 RB_15 RB_16 BUSY7 BUSY5 fu ll n am e READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit 0=BNK register output enabled to read 0=G register output enabled to read bus

READ BUS BUSY READ BUS BUSY

OUT PUTS (from PRO C): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 signal WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit

PROC CONTROL PANEL PUSHBUTTONS

RUPT1 RUPT3

Set the RUPT1 flip-flop (FF). Simulates a TIME3 overflow. Triggers a T3RUPT. Set the RUPT3 flip-flop (FF). Simulates a TIME4 overflow. Triggers a T4RUPT (DSR UPT). Set the RUPT4 flip-flop (FF). Simulates a DSKY keypress. Triggers a KEYRUPT.

RUPT4

TIME1

Set the TIME1 flip-flop (FF). Increments the low-order word of the AGC real-time clock. Set the TIME2 flip-flop (FF). Increments the high-order word of the AGC real-time-clock. Set the T IME 3 flip -flop (FF). Increm ents the gen eral p urp ose tim er. Set the T IME 4 flip -flop (FF). Increm ents the disp lay u pd ate tim er.

TIME2

TIME3 TIME4

PROC CONTROL PANEL CONNECTIONS


PIN 1 2 3 4 5 6 7 8 signal RUPT1 RUPT3 RUPT4 TIME1 TIME2 TIME3 TIME4 GND state definition GND= set RUPT1 FF GND= set RUPT3 FF GND= set RUPT4 FF GND= set GND= set GND= set GND= set TIME1 TIME2 TIME3 TIME4 FF FF FF FF

PROC INDICATORS
The PR OC m odu le ha s a panel of in dica tor lam ps (L ED s) to sh ow the state o f PRO C reg isters and critical logic signals. These indicator lamps show the current state of all registers and some additional, important logic signals produced by the PROC module. AGC num bers are represented in octal, so all register lamps are in groups of three. At the time the photo was taken the AGC was running the COLOSSUS 249 flight software load, executing Verb 16, Noun 36 : a m onitor verb which displays the AGC real time clock.

ALU (Arithmetic Logic Unit)


My earliest architectural representation of the ALU logic is shown below:

Th e A LU con tains th e 16-bit ADDER (co lored ora ng e in the diagram ) w hich perform s 1's com plem ent arith m etic, and increm ents th e prog ram coun ter (Z regis ter). Each orang e box is a 4-bit parallel adder; collectively, they add 16 bits. The ADDER uses the X, Y, and U registers: X: the 1 6-bit e xtens ion reg ister (2 8- bit registe rs in yellow ) that h olds on e of two in puts to the ADDER. the 16-bit extension register (also in yellow) that holds the other input to the ADDER. the AD DER output (the 1 's complem ent sum of the contents of registers X and Y). Outputs to the bus labeled B on the diagram.

Y: U:

The ALU also contains the B and C registers: B: a gen eral-pu rpose b uffer register (sh own as 2 8 -bit registe rs in yellow ), also use d to pre-fetch the next instruction. At the start of the next instruction sequence, the upper bits of B (containing the next op code) are copied to the SQ register (in CTL), and the lower bits (the address) are copied to the S register in (MEM). Output to the bus labeled A on the diagram. not a separate register, but the 1's complement of B.

C:

The ALU contains logic (using 74L S18 1 AL U ch ips, sho wn in green) to do any of the following: select the B register; select the complement of the B register (the C re giste r); sele ct the U reg ister; select the C register ORed with U, or select log ical zero. Th ose log ic functions, needed for AGC operation, are shown in the upper right corner of the diagram. The outpu ts of th e 74 LS1 81 selec tor are gated through a buffer to the read bus. The original AGC could inclusive OR the outputs of any combination of registers onto the bus, but the control m odu le only used this feature for the B/C and U registers. One of the uses involved the MASK instruction, which is a logical AND: DeM organ 's theorem wa s used to im plem ent the e qu ivalent of a logical AND by inverting operands through the C register, performing a logical OR through the bus, and then invertin g the res ult. The 74 LS1 81 logic fun ction s are gated to the read bus through the data selector logic, shown in the adjacent diagram.

The ALU also transfers data from the READ bus to the WRITE bus for register-to- register da ta m oves: D ata is output from the source register onto the READ bu s, then transferred from the READ bus to the WRITE bus through the ALU, and finally loaded from the WRITE bus into the destina tion regis ter. The logic that translates the READ bus to the W RITE bus ca n also force the da ta lines o f the W RITE b us to specific states to gate various arithm etic constants onto the bus. The accompanying diagram shows the the control sig nal on th e left (RB 14, R 1, etc) an d to the right is the bit pattern thats ORed onto the bus when the signal is asserted. The defau lt state of the rea d bu s is logical zero, so if no other read signal is ass erted , the n um ber th at ap pea rs on th e bu s is the con stant; otherwise, its the constant inclusive ORed with the contents of the READ bus. The ALU contains REA D bus control logic. Registers in the MEM modu le, the central registers in the PROC m odu le, and the A LU a ll interface to the R EAD bus th roug h tri-state buffers. Th ese bu ffers are norm ally in the high-impedance state, but the control module (CTL) issues READ control sig nals to outp ut the conten ts of specific registers to the READ bus at certain times. Only one register should be gated onto the READ bus at any given time. When no READ control signals are asserted, the ALU gates its output onto the READ bus by default. When the control module gates a register onto the READ bus, a BUSY signal is sent to the ALU mod ule, which causes the ALU to inhibit its output. Because of propagation delays, the ALU might continue to output to the READ bus for a brief time while another register is also gated to the bus. To prevent this, all output to the read bus is inhibited during CLK1. This gives the control signals, which transition on the leading edge of CLK1, enough setup time to resolve th e conflict.

ALU INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: RB RC RU R1 R1C R2 R22 R24 R2000 RB14 RSB WB CI WY WX WYX READ B READ C READ G READ REA D READ READ READ READ READ RE AD OCTAL 1 OC TAL -1 OCTAL 2 OCTAL 22 OCTAL 24 OCTAL 2000 BIT14 SIG N B IT 0=output B register to write bus 0=output comp of reg B (C) to write bus 0=output U register to write bus 0=incl 0=incl 0=incl 0=incl 0=incl 0=incl 0=incl 0=incl OR OR OR OR OR OR OR OR 000001 177776 000002 000022 000024 002000 020000 100000 w/write w/write w/write w/write w/write w/write w/write w/write bus bus bus bus bus bus bus bus fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus out data transfer occurs on falling edge

WRITE B WRITE CI WRITE Y WRITE X WRITE Y

0= write in to B from write bus 0=set carry register to 1 0=w rite Y 0= write in to X from write bus 0= write in to Y from write bus

RBUS: RB_01 ... RB_14 RB_15 RB_16 INP: OUT: CTR: INT: MBF: CRG: ADR: BUSY1 BUSY2 BUSY3 BUSY4 BUSY5 BUSY6 BUSY7 READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY READ BUS BUSY READ BUS BUSY READ READ READ READ BUS BUS BUS BUS BUSY BUSY BUSY BUSY

US (overflow) bit for read bus SG (sign) bit for read bus 0=valid data read bus 0=valid data read bus 0=valid data read bus 0=valid data 0=valid data 0=valid data 0=valid data from INP on from OU T on from CTR on from from from from INT on read bus MBF on read bus CRG on read bus ADR on read bus

MBF OUTPUTS:
I/F signal fu ll n am e state definition

WBUS: WB_01 ... WB_14 WB_15 WB_16 WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16

US (overflow) bit for write bus SG (sign) bit for write bus

CRG (Central Register)


The AGC has four 16-bit registers for general computational use. These are called the "central registers":

A:

the 16-bit accumulator, used for general computation.

Z:

the 16-bit p rogra m cou nter, which contains the address of the next instruction to be executed.

Q:

the 1 6-bit reg ister used to hold the remainder in the DV instruction, and to hold the return address after TC instructions.

LP:

the 1 6-bit reg ister used to hold the lower product after MP instruction s.

Register A and LP shifters


In addition to normal control pulses that write each line of the write bus into the corresponding bit of the registers, the A and LP registers have special write control pulses that shift bits: The WALP control pulse bit-shifts into the A and LP register. The table below shows how the shifter works. The row of 16 comma-separated entries represent bits in the register. The leftm ost positio n is the register M SB , rightm ost positio n is the LSB . The en try show s the b it of the WRITE bus tha ts m apped onto that regis ter bit by th e shifter. For the WALP pulse, bit 1 of the WRITE bus (B1) is written into bit 14 of the LP register. BX me ans leave tha t bit of the register alone (dont chang e it). The same W ALP pulse causes bit 2 of the WR ITE bus (B2) to be written into the lowest bit of the A register, bit 3 of the WRITE bus (B3) to be written into the next bit, and so forth. US (uncorrected sign) is the overflow bit (bit 15) of the WRITE bus. SG is the 1's complement sign (bit 16) from the W RITE bus. WALP for register LP: BX, BX, B1, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX WALP for register A: SG, SG, US, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

Similarly, the WLP control pulse bit-shifts the WRITE bus into the LP register as follows (D0 on bit 14 of the LP reg ister mean s force the bit to zero): WLP B1, B1, D0, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

The logic design for handling bit 14 of the LP register, which takes control inputs from W ALP , WLP , and W A3 is sh own here. W A3 is identical to WLP.

Depending upon the WALP, WLP, or WA3 inputs, bit 14 of LP will either be set to B1 of the WRITE bus, or forced to zero.

CRG INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: RA RA0 RQ RA1 RZ RA2 RLP RA3 WA WA0 WQ WA1 WZ WA2 WA LP WLP GENRST WBUS: WB_01 ... WB_14 WB_15 WB_16 WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16 READ A READ A READ Q READ Q READ Z READ Z READ LP READ LP WRITE A WRITE A WRITE Q WRITE Q WRITE Z WRITE Z WR ITE A,LP WR ITE LP GENERAL RESET 0=output A to read bus 0=output A to read bus 0=output Q to read bus 0=output Q to read bus 0=output Z to read bus 0=output Zto read bus 0=output LPto read bus 0=output LP to read bus 0=load A from write bus 0=load A from write bus 0=load Q from write bus 0=load Q from write bus 0=load Z from write bus 0=load Z from write bus 0= load A ,LP from write bus 0=load LP from write bus 0=G eneral Reset fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus output data transfer occurs on falling edge

US (overflow) bit for write bus SG (sign) bit for write bus

MBF OUTPUTS:
I/F signal RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY fu ll n am e READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY state definition

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

INT (Interrupt Priority)


The original AGC had five vectored interrupts. This recreation implements the following 3: RUPT1 Also ca lled T3 RU PT be caus e it's triggered by ove rflow of the TIME 3 priority cou nter. Also ca lled T4 RU PT be caus e it's triggered by ove rflow of the TIME 4 priority counter. Because the interrupt is used by software to update the DSKY display at regular intervals, it's sometimes called DSRUPT. Triggered by a key press from the user's keyboard. Also called KEYRUPT.

RUPT3

RUPT4

The AGC software responds to each interrupt by temporarily suspending the current program, executing a short interrupt service routine, and then resuming the interrupted program.

INT INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: GENRST RRPA GENERAL RESET READ RUPT ADDRESS 0= reset IN T reg isters 0=o utput R PCELL ad dress (2004,2010,2014,2020,2024) to read bus 0=load RU PT opcode into RPCELL register 0=reset RUPT latch currently selected by RPCELL register 0=clear RPCELL register 0= test overflow ; if overflow, inhibit interrupt (set INHINT1) 0=clear INHINT1 register 0=set INHINT register 0=clear INHINT register fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus out data transfer occurs on falling edge

RPT KRPT CLRP WOVI

READ RUPT OPCODE KN OC K D OW N R UP T PRIO CLEAR R PCELL WRITE OVF RUPT INH

CLINH1 INH CLINH WBUS: WB_15 WB_16

CLEAR INHINT1 SET INHINT CLEAR INHINT

WRITE BUS 15 WRITE BUS 16

US (overflow ) bit for write bus SG (sign) bit for write bus

CTR/KBD: RUPT1 RUPT3 RUPT4

INTERRUPT 1 INTERRUPT 3 INTERRUPT 4

0=trigger interrupt 1 (2004 octal; TIME3 overflow) 0=trigger interrupt 3 (2014 octal; TIME4 overflow) 0=trigger interrupt 4 (negative edge) (2020 octal; keyboard activity)

Note: interrupt cells above RUPT4 not implemented.

INT OUTPUTS:
I/F SEQ: signal fu ll n am e state definition

IRQ

INT RQST

0=interrupt requested. Active if allof the following are true: a) one or more RUPT FF's are set b) interrupt is not currently being serviced

c) interrupts are not inhibited

RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

CTR (Priority Counter)


The Blo ck I AG C h ad 20 m em ory lo catio ns d edic ated as u p/d ow n co un ters (in volu nta ry counters). The counters would increment or decrement in response to external plus or minus logic signals. Increment (PINC) or decrement (M INC) was hand led by one subsequence of microinstructions inserted between any two regular instruction subsequences when counter inputs occurred. This replica implem ents 5 counters used by the AGC operating system and user interface: Counter OVCTR Addr 34 Description An overflow counter incremented (PINC) or decremented (MINC ) when overflow cond itions occur during certain instructions. The high-order bits of the AGC clock; incremented (PINC) by overflow of TIME1. The low-order bits of the AGC clock; incremented (PINC) by a 100Hz signal from the SCA LER (SC L) in the control m odule (C TL). A general purpose timer incremented by a 100Hz signal from the SCA LER (SC L) in the control m odule (C TL). A special purpose timer used for software update of the DSKY display. Incremented by a 100Hz signal from the SC ALER (SCL) in the control mo dule (CT L).

TIME2

35

TIME1

36

TIME3

37

TIME4

40

INT/CTR interface
This chart shows how counter overflows are handled. F10 (from the scaler) increments TIME1, TIM E3, a nd TIM E4. A positive overflow of TIME1 causes an increment of TIME2. Positive overflow of TIME3 triggers a T3R UPT interrup t. Positive overflow of TIME4 triggers a DSRUPT (T4RUPT) interrup t. The addresses of TIME1 and TIM E2 are reve rsed for Block II. This chart shows the Block I order, but my replica used the Block II order for com patib ility with the COLOSSUS flight software.

CTR Design Problem


During unit testing, I uncovered a bug in my implementation of CTR: The plus inputs set the P-cell which eventually triggers a PINC subsequence and increments the counter. Minus inp uts set the M -cell, w hich trigg ers a M INC sub sequen ce an d de crem ents the cou nter. Nea r-sim ultan eous plus a nd m inus inpu ts shou ld can cel out, p rodu cing no ch ang e in cou nt. As a co nseq uen ce, the cou nter log ic wa s desig ned so that, if the P- an d M -cells are b oth set, no counter sequence (PINC or MINC) is selected. The problem is, the P- and M-cells are reset by WOVR, which only occurs in PINC or MINC. So, if both cells are set--and therefore, no subsequence is selected--WOVR is never issued, the cells never reset, and all counting activ ity is d isab led fo r that cou nter. Here are the options I developed fixing the design: a) Create a new subsequence similar to PINC or MINC that issues WOVR, but does not chan ge the coun ter. Select th is new subs equ ence w hen the P- a nd M -cells are sim ultan eous ly set. b) Allow the P- and M-cells to trigger PINC and MINC sequen ces, resulting in a net change of zero to the cou nter. c) Leave the design as-is, because the M-cell is only used for OVCTR in my implementation, and th erefore , the p roblem can nev er occur. I choose option C to avoid redesign and re-unit-testing of CTR.

CTR INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: GENRST WPCTR RSCT GENERAL RESET WRITE PSEQ READ PCELL ADDRESS 0= reset C TR regis ters 0= write seq uen ce into PSEQ 0=o utput PC ELL address (034-043) to read bus 0=test overflow and inc/dec OVCTR 0=clear selected PCELL and han dle counter overflow (if any) fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus out data transfer occurs on falling edge

WOVC WOVR

WRITE OVRFLOW CNTR WRITE OVERFLOW

WBUS: WB_15 WB_16 WRITE BUS 15 WRITE BUS 16 US (overflow) bit for write bus SG (sign ) bit for write bus

EXTERN AL: P3P

P3 CELL + COUNT

0= cou nt u p P3 cou nter (036 octal; TIME1) 0=coun t up P4 counter (037 octal; TIME3) 0=coun t up P5 counter (040 octal, TIME4) Note: priority cells 6-20 not implemented.

P4P

P4 CELL + COUNT

P5P

P5 CELL + COUNT

CTR OUTPUTS:
I/F signal fu ll n am e C OU N TE R O VE RF LO W : CPO_04 P4 + OVERFLOW state definition

0=P4 cell pos ovf (during WOVR) note: TIME3 + overflow; con nect to INT subsystem to trigger T3RUPT interrup t. 0=P5 cell pos ovf (during WOVR)

CPO_05

P5 + OVERFLOW

note: TIME4 + overflow; con nect to INT subsystem to trigger T4RUPT (DS RU PT) in terrupt.

SEQ: SB_01 SB_02 SUB SEL 01 SUB SEL 02 SB_01 is LSB; SB_02 is MSB 00=no counter; 01=PINC; 10=MINC

RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

Fabrication
The P RO C m odu le is (4) 13"x5 " circuit bo ards, an d 1 co ntrol pa nel.

Module Rack
The m odule framework is designed to resemble a relay rack, but scaled to fit the circuit board dim ensions. It is constructed out of 1"x2" pine and spray-painted semi-gloss gray. Circuit boards are mounted to the rack by 2 phillips screws at either end. Nylon spacers (1/4") are used as sta nd offs to h old the b oard edges above the rack. The boards are mounted so the chips are in the back an d th e pin s are w iring are visible from the front. Power is distributed by 2 heavy aluminu m bu s bars mounted vertically, one per side, on the back of the m odu le. M ach ine screw s are mounted through the bus bars at evenly-spaced intervals to provide connection points for the boards. Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used on the bus bar side of the connection. On the circuit board size, the wires are soldered directly to the supply rails. Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards
The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with doubleside plated throu gh pa ds on 0.1" cen ters (JAMEC O 21 477C L). ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14, 16, 20, 24, and 28 pin (JAMEC O). Each socket has the pin-out labeled wit h a w ire-w rap sock et ID m arke r, wh ich slips o nto the socke t befo re wra pping (JAM ECO). T he p art num ber is writt en o nto the ID m arke r. Sockets are arranged in 4 horizontal rows on each board, with about 10 sockets per row. Power is distributed on the back-side of each board by bare 24-gauge solid copper wire supply rails soldered at equal intervals to Klipwrap terminals: 3-prong terminals with a square tail for wire-wrapping (JAMECO 341 63CL). A +5V rail runs above each row of sockets and a ground rail runs below. Each rail connects directly to the aluminum m odu le po we r bus using a ring tail co nn ector.

On the p in sid e of th e bo ard, all con nec tion s are m ade w ith 3 0 A W G K yna r wire -w rap wire (JAMECO ). Red wire is used for direct connections to the +5V supp ly rail. Black wire is used for direct connections to ground. White wire is used for everything else. Power connections from the supply rails to each ICs are double-wrapped. Bypassing capa citors (.1 uf d isc ) are sold ered ac ross the su pply rails at the Klipw rap term inals; abou t 1 capacitor for every 2 IC packag es. All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As each connection was made, the corresponding line on the schematic was marked with a colored h igh ligh ter. DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current limiting resistors for the panel ind icators.

PROC Printed Circuit Board (PCB) A


The A board conta ins disp lay driv ers for the B b oard (le ft side), bu ffers for the interfaces to external modules (bottom right), and priority counter logic (upper right). Sockets for 3 IDE interface cables to external modules are visible at the bottom.

PROC Printed Circuit Board (PCB) B


The B board contains the display indicators, their current limiting resistor networks, and the open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was used to make holes through the plastic and the LEDs were inserted in rows. The panel was hand -lettered w ith a n in delible m arke r.

PROC Printed Circuit Board (PCB) C


The C board contains the the logic for the interrupt (INT) subsystem (upper half of the board), and the central registers (CRG; low er half of the board).

PROC Printed Circuit Board (PCB) D


The D board contains the ALU logic. The large 74181 ALU chips are at the bottom right. The four chips that form the ADDER are in the bottom ha lf of the board, slightly to the right of the middle.

Parts (ICs)
ICs, sockets, PCBs, resistors, capacitors, wire-wrap wire were purchased from JAMECO. IDE wire-wrap sockets were from DigiKey. W ire ties, wire-wrap tools, and copper wire were from Ra dio Sh ack. IDE rib bon cab les w ere purch ased from an o nlin e com pu ter su pp lier. 74LS00 74LS02 74LS04 74LS06 74LS08 74LS10 74LS20 74LS21 74LS27 74LS32 74LS83 74LS86 74LS112 74LS138 74LS148 74LS151 74LS181 74LS244 (9) (4) (11) (26) (4) (2) (2) (1) (1) (5) (4) (1) (7) (4) (2) (2) (4) (33) U60,U66,U57,U53,U51,U44,U46,U47,U42 U70,U6,U49,U2 U54,U45,U37,U68,U7,U36,U69,U71,U59,U48,U72 U2 8,U 29 ,U3 0,U 31 ,U2 7,U 26 ,U2 3,U 24 ,U2 5,U 22 ,U2 1,U 20 ,U1 8,U 19 ,U1 7,U 16,U15,U12,U13,U14,U11,U10,U35,U34,U33,U32 U63,U61,U56,U52 U50,U43 U67,U73 U1 U9 U4,U41,U40,U39,U38 U134,U135,U136,U137 U5 U65,U64,U62,U58,U55,U8,U3 U84,U85,U86,U94 U93,U97 U87,U88 U130,U131,U132,U133 U74,U75,U76,U77,U78,U79,U80,U81,U82,U83,U89,U90,U95,U96,U101, U102,U104,U105,U108,U111,U112,U115,U116,U117,U118,U119,U120, U121,U122,U124,U125,U128,U129 U91,U92,U98,U99,U100,U103,U106,U107,U109,U110,U113,U114,U123 ,U126,U127,U138,U139,U140,U141

74LS273

(19)

Power Budget
74LS00 74LS02 74LS04 74LS06 74LS08 74LS10 74LS20 74LS21 74LS27 74LS32 74LS83 74LS86 74LS112 74LS138 74LS148 74LS151 74LS181 74LS244 qty 9 4 11 26 4 2 2 1 1 5 4 1 7 4 2 2 4 33 mA (ea) 2.4 2.4 3.6 3.6 4.4 1.8 1.2 2.2 3.4 4.9 22 .0 6.1 4.0 6.3 12 .0 6.0 21 .0 32 .0 m A (tot) 21 .6 9.6 39 .6 93 .6 17 .6 3.6 2.4 2.2 3.4 24 .5 88 .0 6.1 28 .0 25 .2 24 .0 12 .0 84 .0 10 56 .0

74LS273 LED

19 153

17 .0 20 .0

32 3.0 30 60 .0 ----4.9 Amps total 1.9 Am ps (excludin g LEDs)

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 4: Memory (MEM) Module
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
The Memory Module (MEM) has 5 subsystems: MMI, ADR, EMM/FMM, MBF, and PAR

MM I (Mem ory Module external Interface) The M MI in terfaces oth er m em ory module subsystems (ADR, EMM/FMM, MB F, and PAR ; describ ed be low) to external AGC modules. 40-pin IDE connectors interface to the PROC and CTL m odules. Inputs from those modules are buffered to 1 LSTTL load. A 1 -pin con nector int erfaces to th e IO mod ule. EMM /FMM (Eraseable/Fixed Mem ory) The EMM/FMM is the AGC m emory. AGC mem ory is 16-bit word s, organized into 1024 word banks. The lowe st ban k (ba nk 0 ) is erasab le mem ory (EMM), originally implem ented as core, but implemented here as RAM. All banks above bank 0 are fixed mem ory (originally implemented as rope core, but implemented here as EPROM). The Block I AGC initially had 12K word s of fixed m em ory. This implementation has 15K. The MSB (bit 16) in memory is an odd parity b it. The low er 15 b its hold instructions or data. MB F (M em ory Bu ffer Reg ister) The MBF has the 16-bit mem ory buffer register which holds 16-bit data words m oving to and from mem ory. This is also called the G regis ter. The AG C tra nsfers da ta to a nd from m em ory th roug h th e G re giste r during the "m em ory cycle." The memory cycle takes 12 timing pulses (11.72 microseconds). During AGC operation, data w ords cycle continuo usly from m em ory to the G register and the n back again to memory. There are four locations in eraseable memory, at addresses 20-23 (octal), dubbed "editing location s" beca use w hate ver wa s stored th ere wo uld em erge sh ifted or rotated by on e bit position. This shifting is performed in the MBF. PAR (Parity Ge nerate and T est) The PA R g ene rates and tests th e m em ory p arity bit. Th e low er 15 bits o f each m em ory w ord

hold AG C instru ctions o r data. Ea ch w ord is prote cted b y a 16 th "od d pa rity" bit. This bit is set to 1 or 0 by a parity generator circuit so a count of the 1's in each memory word always prod uce s an odd nu m ber. A parity ch ecking circuit tests the p arity bit d urin g ea ch m em ory cycle; if the bit doesn't match the expected value, the memory word is assumed to be corrupted and a PARITY ALARM panel light illum inates on the IO module. ADR (M emo ry Address) The ADR constructs the AGC m emory address. The address is formed from the S register which holds the lower 12-bits that directly address the lowest 4K of memory, and the BANK register, w hich selects hig her m em ory ba nks w hen add ressing is in the fixe d-sw itchab le mod e.

The AGC transfers data to and from memory through the G register in a process called the "m em ory cycle." Th e m em ory cycle ta kes 12 timin g pu lses (11 .72 m icrosecon ds). Th e cycle beg ins at tim ing p ulse 1 (TP1 ) wh en th e AG C load s the m em ory ad dress to b e fetched into the S register in ADR. Memory hardware retrieves the data word from memory at the address specified by the S register. Words from erasable memory are deposited into the G register by timing pulse 6 (TP6); words from fixed memory are deposited by timing pulse 7. The retrieved m em ory w ord is then available in the G register for AGC access during timing pulses 7 through 10. After timing p ulse 10, data in the G register is written back to memory. The m em ory address is formed from the 12-bit S register and the 4-bit BANK register. M em ory in the lowest 4 1K ban ks is directly addressed by the S register. The higher 1K ban ks (5 -12 ) are address through the bank register as described in the ADR subsystem section of this do cum ent. The h igh- order bit in mem ory (bit 15) is an odd parity bit. If the me mo ry word is a data word, the 14 th bit is the sig n, an d bits 13 through 1 hold the magnitude. The num ber rep resen tation is 1's com plem ent. The first half of the mem ory cycle copies data from m em ory to the G register, The sign bit in m em ory (bit 1 4) is copied to bits 1 5 an d 14 of th e G re giste r. Bits 1 3 th roug h 1 in m em ory a re

copied to bits 13 th rough 1 in G. This is performed in the MB F and EMM /FMM subsystem s. The p arity bit (b it 16 in me m ory) is read by the PAR subs ystem and tested a gain st parity gen erate d on the m em ory w ord copied in to G. If the pa rity bits fail to m atch , a pa rity alarm is generated. The 14 th bit in the G register (and the central registers in the AGC) is called the Uncorrected Sign (U S). This extra sign bit is used as an overflow in dication in m ulti-word op erations. Normally, the Sign and Un corrected sign should agree. When overflow or underflow conditions occur, both signs will disagree, and are reconciled by software in an operation at the end of a lon g string of mu lti-word com putations. At the end of the memory cycle, the G register is copied back to memory. The sign bit in G (bit 15 ) is written to the sig n bit (b it 14) in me m ory. Bits 13 throug h 1 in G are w ritten to bits 13 through 1 in memory. A new odd parity bit is computed in the PAR subsystem and written to the 16 th bit in mem ory.

T hese d ia gra m s show the timing of the m em ory cycle. The top chart is a little m ore conceptual; the bottom cha rt show s the clock cycles and control pulses directly associa ted w ith reading erasea ble m em ory (SBEW G) or fixed m em ory (SBFWG) to the G register (the WG part m ean s write to G ) . T he WE pulse w rites G back to memory.

CLK1 steps the sequencer in the CTL module that enables the control signals. The signals have tim e to settle between CLK1 and CLK 2. Da ta tran sfer occ urs on CLK2.

This is a functional diagram of the ADR, EMM/FMM, and MBF subsystems in the MEM modu le. The diagram is m ine, but th e style is borrowed from original AGC documentation: con trol sig nals are represented by diamonds. The arrows show the direction of data flow. When a control signal is asserted, data is allow ed to flow through the diamond. For example, when WE is asserted, the contents of the G register are written into era seab le me mo ry (bank 0 ).

Note the different formats for data and instruc tion w ord in mem ory, shown at the bottom of the d ia gra m .

This is a functional diagram of the PAR subs ystem in the MEM m odule. The diagram was developed during the early stages of my AGC arch itectu re analysis in 2001.

MEM Internal Subsystem Interconnections


This diagram show s internal interconnections for subsystems in the MEM m odule.

MEM Module External Interfaces


The M EM m odule interfaces to the PR OC an d CTL m odules throu gh 40 -pin IDE ribbon cables.

J102-CTL: CTL-to-MEM I/F J102 is a 40-pin IDE cable that connects the MEM modu le to the CTL m odule. INPU TS (to CTL ): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 signal WE S BW G GENRST W23 W22 W21 W20 WGn WBK RBK WS WP2 WPx WP WGx TP RP2 RG GP CLG CLK2 CLK1 NPURST SW CLK FCLK fu ll n am e WRITE EMEM (97) WRITE G (95) GENERAL RESET (86) WRITE ADDR 23 (85) WRITE ADDR 22 (84) WRITE ADDR 21 (83) WRITE ADDR 20 (82) WRITE G NORMAL (81) WRITE BNK (80) READ BNK (70) WRITE S (46) WRITE P2 (44) WRITE P NO RESET (43) WRITE P (42) WRITE G NO RESET (37) TEST PARITY (30) READ PARITY 2 (14) READ G (12) GEN PARITY (5) CLR G (2) CLOCK2 CLOCK1 POWER U P RESET DEBOUNCE CLOCK CLOCK MODE state definition 0=W rite E-MEM from G 0= W rite G from m em ory 0=G eneral Reset 0=Write into SL 0=W rite into CYL 0=Write into SR 0=W rite into CYR 0=W rite G (norm al gates) 0=W rite BNK reg 0=R ead BNK reg 0=W rite S 0=W rite P2 0= W rite P (do n ot reset) 0=W rite P 0= W rite G (do not reset) 0= Test pa rity 0=Read parity 2 0=Read G 0= Gen erate Pa rity 0= Clear G 1.02 4 M Hz A GC clock ph ase 2 (n orm ally low) 1.02 4 M Hz A GC clock ph ase 2 (n orm ally low) 0=reset, 1=normal operation. low freq clk for switch debounce (not used) 1= free-runn ing clk mo de; 0= sing le clk mode

OUT PUTS (from CTL): PIN 31 32 33 34 35 36 37 38 39 40 signal EQU_16 EQU_17 GTR_17 EQU_25 GTR_27 GTR_1777 AD_1 AD_2 AD_3 AD_4 fu ll n am e ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS state definition 0=CADR in register S = 016 0=CADR in register S= 017 0=CADR in register S > 017 0=CADR in register S = 025 0=CADR in register S > 027 0=CADR in register S > 01777 where AD_4 is MSB, AD_1 is LSB

= 016 (1) = 017 (2) > 017 (3) = 025 (4) > 027 (5) > 01777 (6) (1) (2) (3) (4)

J105-MEM: MEM -to-PROC I/F J102 is a 40-pin IDE cable that connects the MEM modu le to the PROC modu le. INPU TS (to M EM): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 signal WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit

OUT PUTS (from ME M): PIN 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 22 21 signal RB_01 RB_02 RB_03 RB_04 RB_05 RB_06 RB_07 RB_08 RB_09 RB_10 RB_11 RB_12 RB_13 RB_14 RB_15 RB_16 BUSY7 BUSY5 fu ll n am e READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit 0=BNK register output to read bus 0=G register output to read bus

READ BUS BUSY READ BUS BUSY

MEM CONTROL PANEL SWITCHES

AGC/MANUAL

Permits memory to be examined and loaded when the switch is in the MANUAL position and the AGC is halted.

EXAM

Loads the address counter with the contents of the switch register. To work, the following switches m ust also be set: AG C/M ANU AL --> MANUAL

NEXT

Steps the address to the next location. To work, the following switches must also be set: AGC/MANUAL --> MANUAL

READ/WR ITE

Displays m em ory contents in the R EAD position; displays sw itch register contents in the WRITE position.

LOAD

Load memory with data manually entered into the switch register. To work, the following switches must also be set prior to LOAD: CLOCK CON TRO L (on CTL m odule) --> STEP; A GC/M ANU AL --> M ANU AL; READ/WR ITE --> WRITE

CLEAR PARITY

Clears a parity alarm indication by resetting the parity alarm (PALM) register. The parity alarm indicator is on the IO modu le.

MEM CONTROL SWITCH CONNECTIONS


PIN 1 2 3 4 5 6 7 signal READ/WR ITE AGC/MANUAL EXAM NEXT CLEAR PARITY LOAD LOAD state definition GND= read GND= manual GND=examine GND= examine next GND= clear LOAD switch conta ct LOAD switch conta ct

PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

signal D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 D14 D15 D16 GND

fu ll n am e DATA1 DATA2 DATA3 DATA4 DATA5 DATA6 DATA7 DATA8 DATA9 DATA10 DATA11 DATA12 DATA13 DATA14 DATA15 DATA16 GND

state definition LSB on switch bus 101

LSB on switch bus 101

MEM INDICATORS
These indicator lamps show the current state of all registers and som e add itiona l, imp ortant lo gic signals produced by the MEM m odu le. AG C n um bers are represen ted in o ctal, so all register lamps are in groups of three. At the time the photo was taken the AGC was running the COLOSSUS 249 flight softw are lo ad, executin g V erb 16 , Nou n 36: a m onitor verb wh ich disp lays th e AG C real tim e clock.

ADR (Memory Address)


The AGC has a 14-bit address range. Memory address is selected by the 12-bit S register and th e 4-b it BA NK regis ter. S: the 12-bit mem ory address register, which holds the lower portion of the m em ory address. BANK: the 4-bit mem ory bank register, which selects the mem ory bank when addressing is in the fixed-switchable mode. Each A GC instru ction has a 12 -bit a dd ress fiel d. Th e low er bits (1-1 0) a dd ress m em ory inside each bank. Bits 11 and 12 select the bank: 00: selects the erasable memory bank; the BANK register is ignored. 01: selects th e low est ban k (ba nk 1 ) of fixed m em ory; the BAN K reg ister is ignored. 10: selects th e nex t ban k (ba nk 2 ) of fixed m em ory; the BAN K reg ister is ignored. 11: selects the BANK register, which is used to address any bank above 2. If the BA NK register con tains 0 , 1, or 2, the B AN K reg ister is overridden and bank 3 is selected. Banks 1 and 2 are called "fixed-fixed" mem ory, because they are always available, regardless of the contents of the BANK register. Banks 3 and above are called "fixed -sw itchable" becau se th e sele cted ban k is determ ined by the B AN K reg ister. Type: E Eraseab le M em ory FF Fixe d-F ixed Me m ory FS Fixe d-S wit cha ble M em ory S R egis ter: bits 12-b it 12,11 address 00 0000 - 1777 01 2000 - 3777 10 4000 - 5777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777 11 6000 - 7777

14-b it address 00000 02000 04000 06000 10000 12000 14000 16000 20000 22000 24000 26000 30000 -

01777 03777 05777 07777 11777 13777 15777 17777 21777 23777 25777 27777 31777

bank 0 1 2 3 4 5 6 7 8 9 10 11 12

BANK type (E) (FF) (FF) (FS) (FS) (FS) (FS) (FS) (FS) (FS) (FS) (FS) (FS)

Reg. ignored ignored ignored 0000 - 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100

BANK B4 X X

register (B) B3 B2 X X X X

B1 X X

+ S register (S) S12 S11 0 0 0 1

Decode s to address: A14 A13 A12 A11 0 0 0 0 0 0 0 1

X 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

X 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1

X 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

X 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

0 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1

1 1 1 1 1 0 0 1 1 0 0 1 1 0 0 1 1

0 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1

X= don t care

This is an early conceptual diagram of ADR architecture. The WRITE bus loads the B NK register or S reg ister. Outp uts from both registers feed into the bank decoder to gen erate the bank address.

The A DR gen erates som e logic signals to test the add ress. Thes e are inte rnally u sed in ME M a nd a lso m ade a vailab le to the external modules. The GTR signals test whether the generated address is greater than 1 777, 27 , or 17 (all octal).

The EQU logic tests whether the gen erated add ress is equ al to a sp ecific value: 14, 16, 17, or 25.

The bank select logic chooses betw een the S regis ter or a combination of the S register and the ba nk reg ister to generate addre ss b its 1 4-11 . It uses S register bits 11 and 12 to make the decision. The selection signa l enab les tristate buffer A or B to produce the correct bank ad dress.

ADR INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: GENRST RBK WBK from write bus WS WBUS: WB_01 ... WB_14 WRITE BUS 01 WRITE BUS 14 GENERAL RESET READ BANK WRITE BANK 0= reset A DR regis ters 0=output BNK register to read bus 0=w rite into BNK register fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus output data transfer occurs on falling edge

WRITE S

0=w rite into S register from write bus

ADR OUTPUTS:
I/F signal MEM: AD_11 ... AD_14 fu ll n am e ADDRESS BUS 11 ADDRESS BUS 14 state definition ban k select bits

AD_1 ... AD_10 various: EQU_16 EQU_17 GTR_17 EQU_25 GTR_27 GTR_1777 RBUS: RB_01 ... RB_16 BUSY

ADDRESS BUS 1 ADDRESS BUS 10

low order add ress

ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS ADDRESS

= = > = > >

016 017 017 025 027 01777

0=CADR 0=CADR 0=CADR 0=CADR 0=CADR 0=CADR

in in in in in in

reg reg reg reg reg reg

S S S S S S

= = > = > >

016 017 017 025 027 01777

READ BUS 01 READ BUS 16 READ BUS BUSY 0=output to read bus

EMM/FMM (Eraseable/Fixed Memory)


MEM INPUTS:
I/F CLK: signal CLK2 fu ll n am e CLOCK 2 state definition data transfer occurs on CLK2

CPM: WE erase able m em ory S BW G WR ITE ERASEABLE WRITE G (MEM) 0= write m em ory bu s to 0=read eraseable or fixed memory onto memory bus

ADR:

GTR_1777 AD_01 ... AD_10

ADDRESS > 01777 ADDRESS BUS 01 ADDRESS BUS 10

0=CADR in reg S > 01777

AD_11 ... AD_14

ADDRESS BUS 11

bank select portion of address bus bank select portion of address bus

ADDRESS BUS 14

BIDIRECTIONAL (IN/OUT):
I/F signal EMM/FMM: MEM_01 ... MEM_15 MEM_16 fu ll n am e MEMORY_BUS 01 MEMORY_BUS 15 MEMORY_BUS 16 state definition Mem ory word form ats: inst: 15-13 :op code; 12 -1:add ress data: 15:S G; 1 4-1 d ata parity (odd) bit for memory bus

MBF (Memory Buffer Register)


The AGC has a 16bit G register for transferring data to and from m emory. WRITE bus data can be w ritten direc tly into the G regis ter, or can be bit-shifted before w riting. D ata from the G register can be copied to the READ bus, or to the me mo ry bus. The following section shows how bits are sh ifted in bus-to-register-tom em ory tra nsfers. The row of 16 comm a-separated entries rep resent b it locations at the destin ation ; the leftm ost entry is the M SB , and th e rightm ost is the LS B. Th e desig natio n in each location identifies source bit location. This will become clearer shortly. In memory, the 16 th bit is the odd parity bit, and the 15th bit is th e sig n. In th e G re giste r, the bits are flipped: the 16 th bit is the sign, and the 15 th bit is the parity. The WE pulse, which writes from the G register to memory, causes the sign bit (SG; bit 16 in G) to be written to bit 15 in m em ory. Parity is written to mem ory from the pa rity generator (PAR ), not from the p arity bit in G. (T he G parity bit holds th e pa rity rea d from m em ory.) WE: BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1

Data is written from m em ory to G b y the S BW G con trol pulse . The sig n in m em ory (SG ; bit 15) is written to bit 16 in G. The parity bit (bit 16 in memory) is written to bit 15 in G by the P AR su bsy stem . SBWG: SG, BX, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1

Data is written into G from the WRITE bus using WG (no shift), or one of the following control pulses that prod uce the followin g shifts: W20: B1, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2

W21: SG, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 W22: B14, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG W23: SG, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG Data is read from G to the READ bus as follows. The parity bit (bit 15 in G) is not transferred to the read bu s; instead, the sign b it is copied onto bits 15 an d 16 of the R EAD bus. RG: SG, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1

Some of the design that went into the combinational logic that sets bit 16 in the G register from the READ bus is shown here. The MB _B1 6 ou tput co ntrols the 16th bit for the W20 and W 21 control pu lses.

The MB_C16 output controls the 16 th bit for the W22 and W23 control pulses.

MBF INPUTS:
I/F CLK: signal CLK1 CLK2 CPM: RG WE GTR_17 S BW G WGN WGX W20 W21 W22 W23 GENRST WBUS: WB_01 ... WB_14 WB_15 WB_16 WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16 READ G WR ITE ERASEABLE ADDRESS > 017 WRITE G (MEM) WRITE G WRITE G WRITE WRITE WRITE WRITE G G G G (SHIFT) (SHIFT) (SHIFT) (SHIFT) 0=output G register to read/write bus 0=output G register to memory bus 0=CADR in register S > 017 0=write G from memory bus 0= write G from rea d/w rite bus (no sh ift) 0= write G from rea d/w rite bus (no sh ift) 0=w rite G 0=w rite G 0=w rite G 0=w rite G 0=G eneral Reset fu ll n am e CLOCK 1 CLOCK 2 state definition 1=read bus setup; inhibit read bus output data transfer occurs on falling edge

GENERAL RESET

US (overflow ) bit for write bus SG (sign) bit for write bus

MBF OUTPUTS:
I/F signal RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY fu ll n am e READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY state definition

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

BIDIRECTIONAL (IN/OUT):
I/F signal EMM/FMM: MEM_01 ... MEM_15 MEM_16 fu ll n am e MEMORY_BUS 01 MEMORY_BUS 15 MEMORY_BUS 16 state definition Mem ory word form ats: inst: 15-13 :op code; 12 -1:add ress data: 15:S G; 1 4-1 d ata parity (odd) bit for memory bus

PAR (Parity Generation and Test)

The PAR subsystem checks the m em ory pa rity bit durin g each me m ory cycle and gen erates an alarm if the parity bit in m em ory does not match the expected odd parity. The PAR subsystem also generates parity from the contents of G and writes this parity back to memory.

This block diagram of the PAR subsystem emerges from the previous diagram.

This is the combinational logic u sed to g enera te the input to the G15 register. Th is is the 1- bit register that holds bit 15 (the parity bit) for the G register. The remainder of the G register (bits 114 and bit 16) is in the M BF su bsy stem . The m interms are written ou t on top . De Morg an s Theo rem and a little bubble-pushing changes the OR gate into a NAND.

PAR INPUTS:
I/F CLK: signal CLK2 fu ll n am e CLOCK 2 state definition data transfer occurs on falling edge

CPM: RG RP2 WP WPX WP2 READ G15 READ P2 WRITE P WRITE P WRITE P2 0=w rite G15 into P 0=write P2 into G15 0=write P (same as WPX) 0=write P (same as WP) 0=write P2 from 1-15 generator 0= writ e G1 5 from m em ory parity b it 0=write G15 from 1-15 generator (same as WGX) 0=write G15 from 1-15 generator (same as GP) 0=clear G15 0=test parity from P-15

S BW G

WRITE G15 (MEM)

GP WGX CLG TP ADR: GTR_27 WBUS: WB_01 ... WB_14 WB_15 WB_16 MON: CLRPLM

WRITE G15 WRITE G15 CLEAR G15 TEST PARITY

ADDRESS > 027

0=CADR in Register S evaluates to > 027

WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16

US (overflow) bit for write bus SG (sign) bit for write bus

CLEAR PA RITY ALM

0= clea r parity ala rm

PAR OUTPUTS:
I/F MON signal PARALM fu ll n am e PARITY ALARM state definition 1= parity alarm

BIDIRECTIONAL (IN/OUT):
I/F signal EMM/FMM: MEM_16 fu ll n am e MEMORY_BUS 16 state definition parity (odd) bit for memory bus

Fabrication
The M EM mo dule is (3) 13 "x5" circu it board s, and 1 con trol pan el.

Module Rack
The m odule framework is designed to resemble a relay rack, but scaled to fit the c ircuit boa rd dimensions. It is constructed out of 1"x2" pine and spray-painted semi-gloss gray. Circuit boards are mounted to the rack by 2 phillips screws at either end . Nylon s pacers (1 /4") are used as standoffs to hold the board edges above the rack. The boards are mounted so the chips are in the b ack and the p ins a re wirin g are visib le from the front. Power is distributed by 2 heavy aluminu m bu s bars mounted vertically, one per side, on the back of the module. Machine screws are mounted through the bus bars at evenly-spaced intervals to provide connection points for the boards. Solid copper wire (24 gauge) connects the boards to the bus bars. Ring terminals are used on the bus bar side of the connection. On the circuit board size, the wires are soldered directly to the supply rails. Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards
The circuit boards are 13 "x5" general p urpose prototypin g boards, epo xy g lass with dou ble- side plated th roug h pads on 0.1" centers (JAM ECO 2147 7CL). ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14, 16, 20, 24, and 28 pin (JAMEC O). Each socket has the pin-out labeled wit h a w ire-w rap sock et ID m arke r, wh ich slips o nto the socke t befo re wra pping (JAM ECO). T he p art num ber is writt en o nto the ID m arke r. Sockets are arranged in 4 horizontal rows on each board, with about 10 sockets per row. Pow er is di stribu ted o n th e ba ck-side o f each boa rd by bare 24-ga ug e solid copp er w ire supply rails soldered at equal intervals to Klipwrap terminals: 3-prong terminals with a squ are tail for w ire-wra ppin g (JA ME CO 341 63C L). A + 5V ra il runs a bove each row of soc kets

and a ground rail runs below. Each rail connects directly to the aluminum module power bus usin g a rin g tail con nec tor. On the p in sid e of th e bo ard, all con nec tion s are m ade w ith 3 0 A W G K yna r wire -w rap wire (JAMECO ). Red wire is used for direct connections to the +5V supp ly rail. Black wire is used for direct connections to ground. White wire is used for everything else. Power connections from the supply rails to each ICs are double-wrapped. Bypassing capacitors (.1 uf disc ) are soldered across the supply rails at the Klipwrap terminals; about 1 capacitor for every 2 IC packag es. All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As each connection was made, the corresponding line on the schematic was marked with a colored h igh ligh ter. DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current limiting resistors for the panel ind icators.

MEM Printed Circuit Board (PCB) A


The A b oard contain s the zero-insertion force (ZIF) sockets for the fixed mem ory EPRO Ms, and the 2 4 0-pin IDE con necto rs that in terface to the other m odu les. The e raseab le me mo ries (U101 , U102 ) are also clearly visible next to the EPRO Ms. The M em ory Address (AD R) an d Erase able/ Fixed Mem ory (EM M/F MM ) sub system s are prim arily loca ted on this board.

MEM Printed Circuit Board (PCB) B


The B board contains the display indicators, their current-limiting resistor networks, and the open collector drivers. The display panel is a sheet of white styrene plastic. A push pin was used to make holes through the plastic and the LEDs were inserted in rows. The panel was

hand -lette red w ith a n in delible m arke r.

MEM Printed Circuit Board (PCB) C


The C b oard prim arily contains the M em ory Buffer (MBF) a nd Parity Ge neration an d Test (PAR ) subsystem s.

Parts (ICs)
74LS00 74LS02 74LS04 74LS06 74LS10 74LS20 74LS27 74LS74 74LS86 74LS154 74LS193 74LS244 (11) (3) (12) (21) (3) (2) (2) (1) (1) (1) (4) (31) U50,U25,U26,U27,U40,U32,U33,U34,U43,U44,U53 U52,U31,U55 U39,U28,U51,U56,U48,U46,U45,U41,U30,U35,U36,U54 U2 0,U 19 ,U1 8,U 15 ,U1 6,U 17 ,U1 4,U 13 ,U1 2,U 10 ,U1 1,U 9,U 6,U 7,U 8,U 5,U 4,U21,U22,U23,U24 U49,U37,U42 U47,U29 U2,U38 U1 U3 U72 U63,U64,U65,U66 U57,U58,U59,U60,U61,U62,U67,U68,U69,U70,U71,U73,U83,U84,U85, U86,U87,U88,U89,U90,U91,U92,U93,U94,U95,U96,U97,U98,U103,U10 4,U105 U74,U75,U76,U79,U80,U81,U82,U106,U107,U108 U77,U78 U99,U100 U101,U102

74LS273 74S280 27C128 2016

(10) (2) (2) (2)

Power Budget
74LS00 74LS02 74LS04 74LS06 74LS10 74LS20 74LS27 74LS74 74LS86 74LS154 74LS193 74LS244 74LS273 74LS280 27C128 2016 LED qty 11 3 12 21 3 2 2 1 1 1 4 31 10 2 2 2 124 mA (ea) 2.4 2.4 3.6 3.6 1.8 1.2 3.4 4.0 6.1 6.2 19 .0 32 .0 17 .0 16 .0 25 .0 25 .0 20 .0 m A (tot) 26 .4 7.2 43 .2 75 .6 5.4 2.4 6.8 4.0 6.1 6.2 76 .0 99 2.0 17 0.0 32 .0 50 .0 50 .0 24 80 .0 ------4.0 Amps total 1.6 Am ps (excludin g LEDs)

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 5: Input/Output (IO) Module
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
The I/O Module (IO) has 5 subsystems: IMI, KBD, INP, OUT, DSP IM I (I/O M od ule external Interface) The IMI interfaces the I/O module to other AG C m odu les. 40-p in IDE con nec tors interface to the PROC and CTL modules. A 1pin connector interfaces to the MEM m odule. Inputs taken those m odu les are bu ffered to 1 LSTTL load. KBD (Keyboard) An 18-button keyboard; the AGCs flight software user input interface. The keyb oard/d isplay unit is called the DSKY. INP (Input Registers) The A GC has 4 16-b it input registers that receive data from the keyb oard a nd d iscrete logic signals. IN0 reads from the keyboard and the STANDBY ALLOWED discrete signal. IN1-IN3 are no t imp lem ented in this replica. OUT (Output Registers) The A GC has 5 16-b it output registers that drive the DSKY display and oth er spa cecra ft subsystems. OUT0 writes to the DSKY display; OUT1 drives the 6 discrete indicator lamps on the AGC DSKY display; OUT2-OUT4 are not implemented in this replica.

DSP (Display) A m atrix of green 7-segment displays; the output side of the AGCs flight software user interface. There are (3) 5-digit displays with +/- signs which can display decimal or octal data, and (3) 2-digit displays to show the current program (PROG), verb, and noun. An ad ditional pan el of 6 indicator lam ps show s AGC status and a larm states.

AGC input registers and control signals that read them onto the b us a re show n in th e diag ram to the righ t. The 5 -bit keyboard code and STA NDB Y ALLO WE D sw itch are read from register 0" (IN0) when the R4 (RA4) con trol pulse is asserted . The sign al is R4 becau se the reg ister is m app ed to memory address 4. The registers are actua lly buffers, not latches. Keyboard codes are latched inte rnally in the k eyb oard su bsy stem . The IN1, IN2, and IN3 registers are not im plem ented in this replica.

AGC output registers are shown in the next figure. OUT0 drives the 7-segment DSKY displays. W10 (WA10) loads data from the write b us into the D SK Y disp lay; th e 10" is because it is mapped onto memory location 10 (octal). Each 16-bit word controls 2 digits on the dis play . The d igit pa ir is selected b y a 4-b it code at the top of the word. OUT1 drives discrete indicator lamps on a panel adjacent to the 7-segment display. W11 (WA11) writes to the register, and R11 (RA11) reads from it. The OUT2 , OUT3, and OU T4 registers are not implemented in this replica.

IO Internal Subsystem Interconnections


This diagram show s internal interconnections for the subsystems in the IO m odule.

IO Module External Interfaces


The IO m odule interfaces to the CT L and PR OC m odules throu gh 40 -pin IDE ribbon cables.

J103-IO: CTL-to-I/O I/F INPU TS (to IO): PIN 1 2 3 5 6 7 8 9 20 signal CLK1 CLK2 NSA GENRST WA11 WA10 RA11 RA4 STBY fu ll n am e CLOCK1 low) CLOCK2 low) STANDBY ALLOW ED GENERAL RESET (86) WRITE OUT1 (76) WRITE OUT0 (75) READ OUT1 (66) READ IN0 (61) STANDBY state definition 1.02 4 M Hz A GC clock ph ase 2 (n orm ally 1.02 4 M Hz A GC clock ph ase 2 (n orm ally 0=standb y allowed 0=clear the DSKY, OUT1, and OUT2. 0=write into OUT1 from write bus 0=write into OUT0 (DSKY) from write bus 0=output OUT1 register to read bus 0=output IN0 register to read bus 0= AG C is in th e stan dby state

OUT PUTS (from IO): PIN 40 signal OUT1_8 fu ll n am e STANDBY ENA BLED state definition 1=standby enabled; works with STANDBY ALLOW ED sw itch

J104-IO: PROC-to-IO I/F INPU TS (to IO): PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 signal WB_01 WB_02 WB_03 WB_04 WB_05 WB_06 WB_07 WB_08 WB_09 WB_10 WB_11 WB_12 WB_13 WB_14 WB_15 WB_16 fu ll n am e WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS WRITE BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit

OUT PUTS (from IO): PIN 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 22 21 20 signal RB_01 RB_02 RB_03 RB_04 RB_05 RB_06 RB_07 RB_08 RB_09 RB_10 RB_11 RB_12 RB_13 RB_14 RB_15 RB_16 BUSY2 BUSY1 KB_STR fu ll n am e READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS READ BUS state definition (lsb)

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16

US (overflow ) bit SG (sign ) bit 0=OUT registers output to read bus 0=INP registers output to read bus 1=key pressed strobe; to KEYRU PT. Key data is valid on the negative edge of KB_STR. Data is latched until the next keypress.

READ BUS BUSY READ BUS BUSY KEY STROBE

IO DISPLAY/KEYBOARD (DSKY)
The keyboard/display portion of the IO module contains a keyboard, a bank of 7-segment displays, a pan el of discrete indicator lamps, an d a board of display drivers.

DSKY KEYBOARD
The DSKY has an 18-button keyboard:

0-9 + VERB

Decim al (or octal) digits. Plus sign for decim al entries. Minu s sign for decima l entries. Tells the AG C the next 2 digits entered will be a VERB. Tells the AG C the next 2 digits entered will be a NOUN. Tells the AG C the data entry is finished. Clears an error in entry. Resets the OPR ERR alarm lamp. Tells the AGC it can have control of the dis play . If the AGC wa nts control of the display, the KEL REL lamp will be flashing.

NOUN

ENTER

CLEAR ERR RST KEY REL

DSKY 7-SEGMENT DISPLAY


COMP ACTY A green indicator lamp that illuminates when the AG C is not idle. The lamp is controlled by the dum m y job, the lowe st priority job in the A GC EX EC softw are s non-preemptive multitasking. When the dummy job is running, the lam p is extinguish ed becau se the AGC is idle. When the dummy job exits because there is a higher priority job running, the lamp illuminates. The light is driven by bit 1 of OUT1. The 2-digit code for the current AGC program. Driven by OUT0. The 2-digit code for the selected VER B. Verbs are actions; directives for the AGC to do something, such as loading or displaying mem ory data. Driven by OUT0. The 2-digit NOUN. The acte d upon mapped to code for the selected noun is the thing by th e verb . Nou ns u sua lly refer to m em ory lo catio ns, w hich are some AGC function. Driven by OUT0.

PROG

VERB

NOUN

R1

Register 1. The uppermost of the three 5-digit displays. Registers R1, R2, and R3 can display data in octal or decimal. Octal data is displayed without a sign. Decimal data is indicated by the presence of a + or - sign in front of the data. The displays I used in my replica cannot display a + sign, so I modified the logic slig htly: d ecim al da ta is represe nted by a leftm ost decim al poin t. Negative decimal numbers have a - sign and the decimal point; positive numbers just have the decimal point. Driven by OUT0. Register 2. The middle of the three 5-digit displays. Driven by OUT0. Register 3. The bottommost of the three 5-digit displays. Driven by OUT0.

R2 R3

IO DISCRETE INDICATORS
The DSKY has a panel of discrete indicator lamps (LEDs) to show status or caution and wa rning signa ls. Four of th e lam ps are d riven b y bits in outp ut registe r 1 (OU T1). Th e parity alarm is driven by a signal from the MEM module. The standby lamp is driven by the standby state of the time pulse generator (TPG) in the CTL module.

UPLINK ACTY

Uplink activity. Illum inates when data is uplinked to the AGC. Driven by bit 3 (UPTL) of OUT1. Operator Error (also called CHECK FAIL). Illuminates when the AGC detects a data entry error. Driven by bit 7 of OUT1. Key Release. Illuminated by the AGC when it needs to use the display, but th e opera tor has ta ken co ntrol of it. The AG C cau ses this la m p to flash to signal the operator to release control of the display by hitting the KEY REL button. Driven by bit 5 (KEY RELS) of OUT1. Program Alarm. Illuminates when the AGC encoun ters an error condition. Driven by bit 8 of OUT1. Standby. Illuminates when the AG C is in the STANDB Y mod e. Illum inates wh en a p arity error is dete cted d uring the m em ory cycle in the MEM m odule.

OPR ERR

KEY REL

PROG

STBY PARITY ALARM

KBD (Keyboard)
The keyboard is an 18-pushbutton unit that gen erates an d latch es a 5-b it code. Th e code is given in Keyboard and Display System Program for AGC (Program Sun rise), A. I. Green and J. J. Rocchio, E-1574, MIT Instrumentation Laboratory, Cambridge, MA, 1964.

The keyboard codes and logic for generating the 5-bit signal is reproduced to the right. The Key Name column identifies the name of the keyb oard k ey; A throug h E are the 5 lo gic signals for the 5-bit code, where A is the MSB.

The 18 switches in the keyboard feed into the combinational logic encoder wh ich ge nerate s the 5 -bit signal. The output of the enco der feeds into a 5 -bit latch. The keys are debounced by generating a keypress sign al wh enev er a key is pushed. The keypress signal feeds through a D flip-flop clocked at around 100Hz. This sam ples the keyp ress signal every 10 mSec and latches the sample. The 10 mSec interval exceeds the contact bounce time of the keyboa rd switches. To give the combinational logic time to settle before the keycode is latched, the output of the keypress D flip-flop is fed into an RC monstable. Latching occurs on the trailing edge of the one-shot pulse. The keyboard codes are fed into input register IN0, which is really just a buffer that gates the codes on to the read bu s when the proper read sign al is asserted. The original design also map s the keypress strobe which generates the keyboard interrupt (KEYRUPT) onto bit 6 of

the register, but I skipped this since there doesnt seem to be any practical reason for doing it an d th e CO LOSS US fligh t softw are d oesn t seem to loo k at th e field . The STANDBY ALLOWED switch (CTL module) maps to be 14.

KBD INPUTS:
I/F CLK: CLK2 CLOCK 2 data transfer occurs on falling edge signal fu ll n am e state definition

CPM: GENRST GENERAL RESET 0=reset KBD register

KBD OUTPUTS:
I/F signal fu ll n am e state definition

KBD: KB_01 ... KB_05 KEYBOARD BUS 01 KEYBOARD BUS 05 Keyboard codes

INT: KB_STR KEY STROBE 1=key pressed strobe; to KEYRU PT. Key data is valid on the negative edge of KB_STR. Data is latched until the next keypress.

INP (Input Registers)


INP INPUTS:
I/F CPM: RA4 RA5 RA6 RA7 READ READ READ READ IN0 IN1 IN2 IN3 0=output 0=output 0=output 0=output IN0 IN1 IN2 IN3 register register register register to to to to read read read read bus bus bus bus signal fu ll n am e state definition

KBD: KB_01 ... KB_05 NSA KEYBOARD BUS 01 KEYBOARD BUS 05 STANDBY ALLOW ED 0=standb y allowed

INP OUTPUTS:
I/F RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY signal fu ll n am e state definition

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

OUT (Output Registers)


OUT INPUTS:
I/F CLK: signal CLK2 CPM: RA11 RA12 RA13 RA14 WA11 WA12 WA13 WA14 READ READ READ READ OUT1 OUT2 OUT3 OUT4 0=OUT1 0=OUT2 0=OUT3 0=OUT4 to to to to read read read read bus bus bus bus fu ll n am e CLOCK 2 state definition data transfer occurs on falling edge

WRITE OUT1 WRITE OUT2 WRITE OUT3 WRITE OUT4

0=load OU T1 write bus 0=load OU T2 write bus 0=load OU T3 write bus 0=load OU T4 write bus

from from from from

GENRST

GENERAL RESET

0=clear DSKY, OUT1, and OUT2.

WBUS: WB_01 ... WB_14 WB_15 WB_16 WRITE BUS 01 WRITE BUS 14 WRITE BUS 15 WRITE BUS 16

US (overflow) bit for write bus SG (sign ) bit for write bus

OUT OUTPUTS:
I/F DSP: OT0_01 ... OT0_16 OUT0 REG 01 OU T0 reg ister outp ut to DSKY signal fu ll n am e state definition

OUT0 REG 16

OT1_01 OT1_03 OT1_05 OT1_07 OT1_08 OT1_09

OUT1 OUT1 OUT1 OUT1 OUT1 OUT1

REG REG REG REG REG REG

01 03 05 07 08 09

COM P panel indicator; 1=on UPTL panel indicator; 1=on KEY RELS p anel indicator; 1=on CHECK FAIL panel indicator 1=on STBY pan el indicator 1=on PROG ALM pan el indicator 1=on

RBUS: RB_01 ... RB_14 RB_15 RB_16 BUSY READ BUS 01 READ BUS 14 READ BUS 15 READ BUS 16 READ BUS BUSY

US (overflow) bit for read/write bus SG (sign) bit for read/write bus 0=output enabled to read bus

DSP (Display)
The 7 -segm ent D SK Y disp lay is driv en b y outp ut registe r 0 (OU T0). Ea ch 16 -bit w rite to OU T0 w rites d ata to a p air of 7 -seg m ent dig its.

Four fields in OUT0 are involved: The relay word (RLYWD ; bits 12-15) field selects the pair of digits; the DSPH field (bits 6-10) contains the 5-bit numerical code for the left digit in the pair, an d DP SL (b its 1-5) has th e code for the righ t digit. Th e 1-b it DPS C (bit 1 1) field controls verb/noun flash (enables 1 Hz blinking of the VERB and NOUN digits) and the plus and minus signs to the left of the three 5-digit registers on the DSKY display. Bits 15-12 R LY W D 1011 1010 1001 1000 0111 0110 0101 0100 0011 0010 0001 Bit 11 DSPC FLASH UPACT +R1S -R1S +R2S -R2S +R3S -R3S Bits 10-6 DSPH MD1 VD1 ND1 R1D2 R1D4 R2D1 R2D3 R2D5 R3D2 R3D4 Bits 5-1 DSPL MD2 VD2 ND2 R1D1 R1D3 R1D5 R2D2 R2D4 R3D1 R3D3 R3D5

Each 7-segment digit on the display has a name (VD1, VD2, etc). The digits are physically arran ged like this: MD1 ND1 R1D3 R2D3 R3D3 R1D4 R2D4 R3D4 MD2 ND2 R1D5 R2D5 R3D5 : major mode (PROG) : NOUN : regi ster 1 : regi ster 2 : regi ster 3

VD1 R1S R2S R3S

VD2 : VERB R1D1 R2D1 R3D1 R1D2 R2D2 R3D2

In m y assem bled unit, th e disp lays w ere in gro ups of 3, so som e digits were not needed and left unwired.

The 5-bit codes that illuminate each digit in the display are given below; these are the codes sent to the DPSH and DPSL fields in OUT0. In my implementation, I translate them into 4-bit binary-coded decimal representation (BCD) and feed them into a 74LS4 7 7-segm ent decoder. The mapping of the AGC digit to my

74LS47 d ecoder code is also given. The AGC digit codes are very peculiar; I suspect they were chosen for easy decoding in to the 7-segm ent displays. Dig it Blank 0 1 2 3 4 5 6 7 8 9 AGC 00000 10101 00011 11001 11011 01111 11110 11100 10011 11101 11111 74LS47 1111 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001

My initial block diagram for the DSP logic is shown here. Two combinational logic code converters changes the 5-bit AGC code (DS PH, DPSL) into 4-bit BCD. The converted codes are la tche d in to 4- bit reg isters b y w rite pu lses d ecod ed b y the rela y w ord (RLY W D) d ecod er. Single b it latches hold the flash an d sign bit code s transm itted by DS PC (bit 11 of OUT0 ). Altho ugh I show separa te deco ders for each digit, I actua lly m ultiple xed th e disp lay to minimize the hardware. In this way, I only needed a pair of 74LS47 decoders; one for DSPH and the other for DSPL.

Some back-of-the-envelope bits and pieces of the logic design are also shown here. One diagram shows the verb/n oun flash log ic. Note th e sim ple Karnaugh map (a graphical method for reducing boolean expressions), and a bit of bubble-pushing (a graphical tec hn ique for a pp lying De Morg an s Theorem to transform logic functions betwee n AN D an d OR ).

The other diagram shows the logic for the +/- signs on registers 1, 2, and 3. The displays I used in my replica cannot display a + sign, so I modified the AGC logic slightly: decimal data is represented by a leftmost decimal point. Negative decimal numbers have a - sign and decim al point; po sitive deci m al n um bers just ha ve the decim al poin t.

The d igit disp lay po rtion of the DS KY u ses green com m on-a nod e LED displa ys grou ped in threes. Like most com ponen ts, these were purcha sed from JA MEC O. Heres the pinouts:

A pan el of discrete indicator LEDs are m apped against bits in ou tput register 1 (OU T1).

DSP INPUTS:
I/F CLK: CLK2 CLOCK 2 data transfer occurs on falling edge signal fu ll n am e state definition

PAR: PARALM PARITY ALARM 1= parity alarm

INP: OT0_01 ... OT0_15 OUT0 REG 01 OUT0 REG 15 OUT0 register output to DSKY

OT1_01 OT1_03 OT1_05 OT1_07 OT1_08 OT1_09

OUT1 REG 01 OUT1 REG 03 OUT1 REG 05 OUT1 REG 07 OUT1 REG 08 OUT1 REG 09

COM P panel indicator; 1=on UP TL p anel indica tor; 1=on KEY RELS p anel indicator; 1=on CHECK FAIL panel indicator 1=on STBY pan el indicator 1=on PROG ALM pan el indicator 1=on

CPM: WA10 WRITE OUT0 0=write into OUT0 (DSKY) from write bus 0=clear the DSKY.

GENRST

GENERAL RESET

DSP OUTPUTS:
I/F none. signal fu ll n am e state definition

Fabrication
The IO modu le is (2) 13"x5" circuit boards, and 1 DSKY panel containing a display driver board, a 7-segment display board, a discrete LED indicator board, and a keyboard.

Module Rack
The m odu le fram ewo rk is desig ned to resemble a relay rack, but scaled to fit the circuit board dimensions. It is constructed out of 1"x 2" pin e and spray- pain ted sem igloss gray. Circuit boards are mounted to the rack by 2 ph illips screw s at either end . Nylon s pacers (1/4") are used as standoffs to hold the boa rd ed ges abo ve th e rack . The boa rds a re mounted so the chips are in the back and the pins are wiring are visible from the front. Power is distributed by 2 heavy aluminum bus bars moun ted vertically, one per side, on the back of the module. Machine screws are mounted through the bus bars at evenly-spaced intervals to provide connection points for the boards. Solid copper wire (24 gauge) connects the boa rds to the b us b ars. R ing term ina ls are used on the bus bar side of the connection. On the circuit board size, the wires are soldered directly to the supply rails. Materials were purchased from Home Depot, ACE Hardware, and Radio Shack.

Circuit Boards
The circuit boards are 13"x5" general purpose prototyping boards, epoxy glass with doubleside plated throu gh pa ds on 0.1" cen ters (JAMEC O 21 477C L). ICs are mounted in level 3 machine tooled wire-wrap sockets: 8, 14, 16, 20, 24, and 28 pin (JAMEC O). Each socket has the pin-out labeled wit h a w ire-w rap sock et ID m arke r, wh ich slips o nto the socke t befo re wra pping (JAM ECO). T he p art num ber is writt en o nto the ID m arke r. Sockets are arranged in 4 horizontal rows on each board, with about 10 sockets per row. Power is distributed on the back-side of each board by bare 24-gauge solid copper wire supply rails soldered at equal intervals to Klipwrap terminals: 3-prong terminals with a square tail for wire-wrapping (JAMECO 341 63CL). A +5V rail runs above each row of sockets and a ground rail runs below. Each rail connects directly to the aluminum m odu le po we r bus using a ring tail co nn ector.

On the p in sid e of th e bo ard, all con nec tion s are m ade w ith 3 0 A W G K yna r wire -w rap wire (JAMECO ). Red wire is used for direct connections to the +5V supp ly rail. Black wire is used for direct connections to ground. White wire is used for everything else. Power connections from the supply rails to each ICs are double-wrapped. Bypassing capa citors (.1 uf d isc ) are sold ered ac ross the su pply rails at the Klipw rap term inals; abou t 1 capacitor for every 2 IC packag es. All connections were stripped and hand-wrapped using a Radio Shack hand-wrap tool. As each connection was made, the corresponding line on the schematic was marked with a colored h igh ligh ter. DIP resistor networks (JAMECO) plugged into 20-pin wire-wrap sockets were used as current limiting resistors for the panel ind icators.

IO Circuit Board A
The A board contains the module interface buffers, input and output registers, and the latches that hold the BCD codes for the 7-segm ent displays.

IO Circuit Board B
The B board conta ins key boa rd an d disp lay log ic. The 4 0-pin IDE con necto rs that in terface to the other modules are visible at the bottom. The 5 red LEDs show the keyboard code latched into the K BD outp ut reg ister.

IO Device Driver Board C


The C b oard con tain s driv er tran sistors an d th eir associa ted re sistors. Th e tran sistors are pla stic m ediu m -po we r com plem entary silicon : NP N tra nsis tors are TIP1 02 , PNP transistors are TIP107. Viewed from the front of the TO-220 case, the base (1) is to the left, collector (2) in th e m idd le, an d em itter (3 ) to th e righ t. The m etal tab (4) is the collec tor.

An empty space at the top of the IO module rack was filled with a plexiglass panel listing verb and noun codes:

Parts (ICs)
ICs, sockets, PCBs, resistors, capacitors, wire-wrap wire were purchased from JAMECO. IDE wire-wrap sockets were from DigiKey. W ire ties, wire-wrap tools, and copper wire were from Ra dio Sh ack. IDE rib bon cab les w ere purch ased from an o nlin e com pu ter su pp lier. 74LS00 74LS02 74LS04 (13) (3) (27) U27, U27B, U27C, U15C, U15B, U15, U14C, U14B, U14, U29D, U29C, U29B, U34B U25,U25,U33C U40E, U40D, U38D, U38C, U40F, U40C, U39E, U39D, U39C, U39B, U41D, U40B, U37F, U39F, U12, U12B, U12C, U12D, U12E, U11F, U11E, U11D, U11C, U11B, U11, U39A, U37 U26F, U26E, U26D, U26C, U26B, U26, U20, U18D, U18C, U18B, U18, U20C, U17E, U17D, U20B, U16F, U16E, U9, U9B, U9C, U9D, U9E, U9F, U10, U10B, U10C, U10D, U7, U7B, U7C, U7D, U7E, U7F, U8, U20, U19F, U19E, U19D, U19C, U19B, U19 U28 U4 U2, U3, U5, U31, U32 U35C, U36 U46, U47, U48, U45 U1 U24C U6A, U23B, U22B, U21B, U30 U50, U67, U68, U69, U70, U73, U74, U75, U76 U65, U66, U71, U72 U51 U49 U101, U100, U52, U53, U77, U78, U81, U82, U83, U84 U79, U80, U44 U54, U55, U56, U57, U58, U59, U60, U61, U62, U63, U64 DISP1, DISP2, DISP3, DISP4,DISP5, DISP6, DISP7, DISP8, DISP9, DISP10, DISP11, DISP12, DISP13, DISP14, DISP15, DISP16, DISP17, DISP18, DISP19, DISP20, DISP21 U85, U42, U43 Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q15, Q16, Q17, Q18, Q19, Q20, Q21, Q32, Q33, Q34, Q35, Q36, Q37, Q38, Q39, Q40, Q41, Q42, Q43, Q44, Q45, Q8, Q9, Q10, Q11, Q12, Q13, Q14 Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31, Q46, Q47, Q48, Q49, Q50, Q51, Q52, Q53, Q54, Q55, Q56, Q57

74LS06

(41)

74LS08 74LS10 74LS20 74LS27 74LS47 74LS74 74LS86 74LS112 74LS138 74LS148 74LS154 74LS161A 74LS244 74LS273 74LS374 GREENCA

(1) (1) (5) (2) (4) (1) (1) (5) (9) (4) (1) (1) (10) (3) (11) (21)

555 NPN3

(3) (35)

PNP3

(22)

Power Budget
74LS00 74LS02 74LS04 74LS06 74LS08 74LS10 74LS20 qty 13 3 27 41 1 1 5 mA (ea) 2.4 2.4 3.6 3.6 4.4 1.8 1.2 m A (tot) 31 .2 7.2 97 .2 14 7.6 4.4 1.8 6.0

74LS27 74LS47 74LS74 74LS86 74LS112 74LS138 74LS148 74LS154 74LS161 74LS244 74LS273 74LS374 555 3 GREENCA LED 25

2 4 1 1 5 9 4 1 1 10 3 11 3.0 21 20 .0

3.4 7.0 4.0 6.1 4.0 6.3 12 .0 6.2 19 .0 32 .0 17 .0 27 .0 9.0 14 0.0 50 0.0

6.8 28 .0 4.0 6.1 20 .0 56 .7 48 .0 6.2 19 .0 32 0.0 51 .0 29 7.0 29 40 .0 ---4.6 4.1

Amps total Am ps (excludin g single LED s)

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 6: Assembler
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
This A GC cross-asse m bler, code d in C ++ , produ ces AG C ob ject code in M otorola S -form at. The code can be burned into EPROM for use by the hardware AGC, or executed by the C++ AG C sim ula tor.

Operation
The assembler reads an AGC source code text file (having a .asm extension). It generates an assembly listing text file (.lst extension) and an two object code text files (_H.hex and _L.hex suffixes). The object code files are readable by the AGC simulator or an EPROM prog ram m er.

Syntax
Sou rce code files are text files con tainin g m ultiple lines of sou rce code . Each lin e is terminated by a newline character. Source code files can be produced by any editor, as long as it doesn't insert any hidden characters or formatting information. Each line of source code consists of one of the following: a) A blank line. b) A com me nt (com me nts m ust begin with a sem icolon (;)). c) A line of assembler code. The assembler ignores blank lines and anything that occurs after a semicolon on any given line. A line of assem bler code consists of the following comp onents: 1) A label (this is optiona l). 2) An op code or assembler directive. 3) An op erand (also op tional). 4) A com me nt (optional; com me nts m ust start with a sem icolon). The comp onents, if present, mu st appear in the order given. Each component is separated from th e nex t by on e or m ore wh ite spac es or tabs . The on ly cons traint is th at the la bel, if present, must start in the 1st colum n of the line. If no label is present, the op code or assembler directive must not start in the 1st column, but may appear in any subsequent column. The operand may consist of one of the following: a) An asterisk (the assembler substitutes in the current value of the location cou nter. b) A symbolic name (the assemble substitutes in the value during the second pass of the assembly. c) A num eric constant. Octal contants must be preceeded by a '%'; hexadecimal consta nts are p receede d by a '$'; anyth ing els e is treated as a de cim al. d) An expression consisting of one or more of the above, separated by the operators: +, -, @ (for multiplication), or / (for division). Unary plus or minus is also allowed. Exam ples: *+2 Location counter plus 2. LABEL +% 10/2 LABEL plus octal number 10 divided by decimal number 2. -5 Negative decimal 5.

Assembler Directives
The following directives are supported: ORG EQU DS CADR Set the location counter to the operand following ORG. Set the label to the operand value. Define a word of storage; set the value to the operand value. Define a word of storage; set the value to the operand value (assumed to be a 14-b it address; this is an alias for CAD R). Define a word of storage; set the value to the operand value (operand is treated as a 12-bit ad dress). Inline include a file; the operand contains the filenam e.

ADRES

INCL

Addressing
The location counter and symbol table always contain the full 14-bit address. AGC instructions require a 12-bit address as an operand. Addressing is implemented in 1K banks (bits 10 throu gh 1). B its 12 and 11 select banks 0 (era sab le m em ory), 1 (fixed -fixed ), or 2 (fixed-fixed). These banks are directly addressable in 12-bits. Banks above 2 are called 'fixed-switchable' and are addressed using the BANK register: bits 12 and 11 of the operand are set to '1' and the bank register provides the high-order 4 bits (bits 14 through 11) of the address. The lower 10 bits of the operand provide the address within the bank.

Errata
a) The assembler ignores the last line of the source (.asm) file. If the last line of your source file contains code, you must add an additional blank line to the end of your source file to ensure that your last line of code is assembled. The symbol table could be sorted before the second pass. The linear search through the sym bol table could be replaced by a mo re efficient m ethod. (Bu t, assembly is so fast, it doesnt m atter). The assembler directives and syntax don't match those of the original block I AGC. A macro definition capability might be handy. Gen erates em pty .lst an d .obj files if the so urce cod e file does n ot exist. Incorrectly a ssign s a zero va lue to la bels th at equ ate to a forw ard referen ced lab el. i.e.: LABEL1 EQU LABEL2 ; assem bler in correc tly sets LA BEL 1 to z ero LABEL2 EQU *

b)

c) d) e) f)

Assembler listing
The assembler produces a list file (.lst) that shows the assembled source code. The format of the file w as des igne d to m im ic (som ewh at) the forma t of the origin al assem bler. You will find a fragment of the original assembler listing reproduced in part 8.

List files from my assem bler ha ve this form at:

Object code
The object code is output to text files in Motorola S-Record format (S2F) suitable for im m edia te us e by EPR OM prog ram m ers, an d also rea dable b y the C+ + sim ula tor. There s lots of docum enta tion on S-R ecord form ats on the inte rnet. The files are pretty big. If you open one up, youll discover they contain many short records that look like these:

This is a fragment of the source code for the lower 8 bits of the TECO1 test and checkout program (described in pa rt 9). The assembler contains C++ code for generating these files; the C++ simu lator has code for rea din g th em .

Assembler v1.6
/* **************************************************************** * * Cross Assembler for Block I Apollo Guidance Computer (AGC4) * THIS VERSION IS MODIFIED TO OUTPUT IN S-RECORD FORMAT SUITABLE FOR * LOADING IN EPROM (s2f format). * Author: John Pultorak * 6/1/2002 * ***************************************************************** Versions: 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.6 First version of the AGC assembler. Added ability to handle simple arithmetic expressions for the operand. Changed label fields to 14 char. Printed symbol table in 3 columns. Corrected wrong implementation of OVSK. Added support for bank addressing. Added capability to inline code with nested includes. Added CADR, ADRES assembler directives. Swapped addresses for TIME1 and TIME2 for compatibility with Block II PINBALL routines. Fixed the parser so it doesn't mangle comments anymore. Added FCADR and ECADR to the assembler directives. Added a check for assembled code that overwrites already used locations. EPROM Assembler outputs to low and high EPROM files.

Operation: The assembler reads an AGC source code file (having a .asm extension). It generates an assembly listing text file (.lst extension) and an object code text file (.obj extension). The object code file is readable by the AGC simulator. Syntax: Source code files are text files containing multiple lines of source code. Each line is terminated by a newline character. Source code files can be produced by any editor, as long as it doesn't insert any hidden characters or formatting information. Each line a) b) c) of assembly code consists of one of the following: a blank line; a comment (comments must begin with a semicolon (;)); or a line of assembler code.

The assembler ignores blank lines and anything that occurs after a semicolon on any given line. A line of 1) 2) 3) 4) assembler code consists of the following components: a label (this is optional); an op code or assembler directive; an operand (also optional); a comment (optional; comments must start with a semicolon)

The components, if present, must appear in the order given. Each component is separated from the next by one or more white spaces or tabs. The only constraint is that the label, if present, must start in the 1st column of the line. If no label is present, the op code or assembler directive must not start in the 1st column, but may appear in any subsequent column. The operand may consist of one of the following: a) an asterisk (the assembler substitutes in the current value of the location counter; b) a symbolic name (the assemble substitutes in the value during the second pass of the assembly; c) a numeric constant. Octal contants must be preceeded by a '%'; hexadecimal constants are preceeded by a '$'; anything else is treated as a decimal. d) an expression consisting of one or more of the above, separated by the operators: +, -, @ (for multiplication), or / (for division). Unary plus or minus is also allowed. examples: *+2 means location counter plus 2 LABEL+%10/2 -5

Assembler Directives: The following directives are supported: ORG - set the location counter to the operand following ORG. EQU - set the label to the operand value. DS - define a word of storage; set the value to the operand value. CADR - define a word of storage; set the value to the operand value (assumed to be a 14-bit address; this is an alias for CADR). ADRES - define a word of storage; set the value to the operand value (operand is treated as a 12-bit address). INCL - inline include a file; the operand contains the filename. Addressing: The location counter and symbol table always contain the full 14-bit address. AGC instructions require a 12-bit address as an operand. Addressing is implemented in 1K banks (bits 10 through 1). Bits 12 and 11 select banks 0 (erasable memory), 1 (fixed-fixed), or 2 (fixed-fixed). These banks are directly addressable in 12-bits. Banks above 2 are called 'fixed-switchable' and are addressed using the BANK register: bits 12 and 11 of the operand are set to '1' and the bank register provides the high-order 4 bits (bits 14 through 11) of the address. The lower 10 bits of the operand provide the address within the bank. Errata: The assembler ignores the last line of the source (.asm) file. If the last line of your source file contains code, you must add an additional blank line to the end of your source file to ensure that your last line of code is assembled. The symbol table should be sorted before the second pass. The linear search through the symbol table should be replaced by a more efficient method. The assembler directives and syntax don't match those of the original block I AGC. A macro definition capability would be handy. Generates empty .lst and .obj files if the source code file does not exist. Incorrectly assigns a zero value to labels that equate to a forward referenced label. i.e.: LABEL1 EQU LABEL2 ; assembler incorrectly sets LABEL1 to zero LABEL2 EQU * The assembler generates object code for eraseable memory addresses. */ #include #include #include #include #include <string.h> <stdlib.h> <ctype.h> <iostream.h> <stdio.h>

// Create a flag for each memory location in a 14-bit address space // These are initialized to false, and then set as the code is assembled. // An attempt to assemble code on top of a previously used location is // flagged as an error. const unsigned agcMemSize = 037777+1; // # of cells in a 14-bit address range bool memoryUsed [agcMemSize]; //*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. // This array represents the fixed memory PROM (14-bit address) int EPROM_H [agcMemSize]; int EPROM_L [agcMemSize]; //*********************************************************************** unsigned pass = 0; unsigned locCntr = 0; // address in 14-bit format unsigned errorCount = 0; FILE* fpList = 0; // output (assembly listing)

//*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. FILE* fpObj_H = 0; // output MSB's (object code in S-RECORD format) FILE* fpObj_L = 0; // output LSB's (object code in S-RECORD format) //*********************************************************************** struct ocode { char* name; unsigned code; bool isOpCode; // true=it is an op code bool addrOpnd; // true=convert operand to 12-bit address format unsigned len; // words }; ocode allcodes[] = { // Block I op codes. { "TC", 0000000, true, { "CCS", 0010000, true, { "INDEX", 0020000, true, { "XCH", 0030000, true, { "CS", 0040000, true, { "TS", 0050000, true, { "AD", 0060000, true, { "MASK", 0070000, true, { "MP", 0040000, true, { "DV", 0050000, true, { "SU", 0060000, true, { { { { { { { { { { { {

true, true, true, true, true, true, true, true, true, true, true,

1 1 1 1 1 1 1 1 1 1 1

}, }, }, }, }, }, }, }, }, }, }, INDEX INDEX INDEX INDEX TC A TC Q XCH A CS A TS Z TS A AD A MP A 25 5777 17 16

// Implied address codes (R393: 3-12) "RESUME", 0020025, true, false, 1 }, // "EXTEND", 0025777, true, false, 1 }, // "INHINT", 0020017, true, false, 1 }, // "RELINT", 0020016, true, false, 1 }, // "XAQ", 0000000, true, false, 1 }, // "RETURN", 0000001, true, false, 1 }, // "NOOP", 0030000, true, false, 1 }, // "COM", 0040000, true, false, 1 }, // "TCAA", 0050002, true, false, 1 }, // "OVSK", 0050000, true, false, 1 }, // "DOUBLE", 0060000, true, false, 1 }, // "SQUARE", 0040000, true, false, 1 }, // "clarity" (R393: 3-12) 0000000, true, true, 1 }, 0030000, true, true, 1 }, 0050000, true, true, 1 }, 1 }, 1 }, 1 }, 1 }, 1 }, 0 }, 0 }, 0 }, 99 } // // // // // // // // //

// For { "TCR", { "CAF", Clear and Add { "OVIND", { { { { { { { { { };

// same as TC; subroutine call with return // same as XCH; address to fixed acts like // same as TS define storage; reserves 1 word of memory define 14-bit addr; reserves 1 word of memory define 14-bit addr; reserves 1 word of memory define 14-bit addr; reserves 1 word of memory define 12-bit addr; reserves 1 word of memory origin; sets location counter to operand value equate; assigns a value to a label include; inline include source code end-of-list flag

// Assembler directives "DS", 0, false, false, "CADR", 0, false, false, "FCADR", 0, false, false, "ECADR", 0, false, false, "ADRES", 0, false, true, "ORG", 0, false, false, "EQU", 0, false, false, "INCL", 0, false, false, "", 0, false, false,

void parse(char* buf, char* labl, char* opcd, char* opnd, char* cmnt) { // strip off newline char. buf[strlen(buf) - 1] = '\0'; // replace any horizontal tabs with spaces for(unsigned i=0; i<strlen(buf); i++) { if(buf[i] == ';') break; // don't edit comments if(buf[i] == '\t') buf[i] = ' '; } strcpy(labl,"");

strcpy(opcd,""); strcpy(opnd,""); strcpy(cmnt,""); char* sp = buf; char* s = 0; enum {_labl=0, _opcd, _opnd, _cmnt } mode = _labl; if(buf[0] == ' ') mode = _opcd; do { s = strtok(sp, " "); sp = 0; if(s) { if(s[0] == ';') { // Copy the remainder of the comment verbatim. strcat(cmnt, s); strcat(cmnt, " "); s += strlen(s) + 1; strcat(cmnt, s); return; } switch(mode) { case _labl: strcat(labl, s); mode = _opcd; break; case _opcd: strcat(opcd, s); mode = _opnd; break; case _opnd: strcat(opnd, s); mode = _cmnt; break; } } } while(s); } struct symbl { char name[20]; unsigned val; }; symbl symTab[5000]; unsigned nSym = 0; // Pre-defined symbols corresponding to architectural // conventions in the block I AGC4. symbl constSymTab[] = { { "A", 00 }, { "Q", 01 }, { "Z", 02 }, { "LP", 03 }, { "IN0", 04 }, { "IN1", 05 }, { "IN2", 06 }, { "IN3", 07 }, { "OUT0", 010 }, { "OUT1", 011 }, { "OUT2", 012 }, { "OUT3", 013 }, { "OUT4", 014 }, { "BANK", 015 }, { "CYR", 020 }, { "SR", 021 }, { "CYL", 022 }, { "SL", 023 }, { "ZRUPT", 024 }, { "BRUPT", 025 }, { "ARUPT", 026 }, { "QRUPT", 027 }, { "OVCTR", 034 }, { "TIME2", 035 }, { "TIME1", 036 }, { "TIME3", 037 }, { "TIME4", 040 }, { "GOPROG", 02000 },

{ { { { { { { { { { { { { { { { { { { { };

"T3RUPT", "ERRUPT", "DSRUPT", "KEYRUPT", "UPRUPT", "EXTENDER", "BANK0", "BANK1", "BANK2", "BANK3", "BANK4", "BANK5", "BANK6", "BANK7", "BANK10", "BANK11", "BANK12", "BANK13", "BANK14", "",

02004 02010 02014 02020 02024 05777 000057 002000 004000 006000 010000 012000 014000 016000 020000 022000 024000 026000 030000 0

}, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }

// // // //

erasable memory, just above the counter assignments fixed-fixed fixed-fixed start of fixed-switchable

void add(char* labl, unsigned value) { // Check whether symbol is already defined. unsigned i; for(i=0; i<nSym; i++) { if(strcmp(symTab[i].name, labl)==0) { fprintf(fpList,"*** ERROR: %s redefined.\n", symTab[i].name); errorCount++; return; } } // Add new symbol to symbol table strcpy(symTab[nSym].name, labl); symTab[nSym].val = value; nSym++; } // Return the int value of the operand string. The string is // assumed to be a simple value (not an expression) int _getopnd(char* opnd) { if(strlen(opnd)==0) return 0; else if(opnd[0] == '$') // hex number return strtol(opnd+1, 0, 16); else if(opnd[0] == '%') // octal number return strtol(opnd+1, 0, 8); else if(isdigit(opnd[0])) // decimal number return strtol(opnd, 0, 10); else if(opnd[0] == '*') return locCntr; else // must be label; look up value { unsigned i; for(i=0; i<nSym; i++) { if(strcmp(symTab[i].name, opnd)==0) return symTab[i].val; } // Not there, so check whether symbol is an // assembler-defined constant. If so, copy it to // the user-defined symbols. for(i=0; strcmp(constSymTab[i].name,"") != 0; i++) { if(strcmp(constSymTab[i].name, opnd)==0) { strcpy(symTab[nSym].name, opnd); symTab[nSym].val = constSymTab[i].val; nSym++;

return constSymTab[i].val; } } if(pass == 1) { fprintf(fpList,"*** ERROR: %s undefined.\n", opnd); errorCount++; } } return 0; } // returns pointer to new position in istr char* getToken(char* istr, char* ostr) { *ostr = '\0'; // bump past any whitespace while(*istr == ' ') istr++; if(*istr == '\0') return istr; bool keepGoing = true; do { *ostr = *istr; if(*ostr == '+' || *ostr == '-' || *ostr == '@' || *ostr == '/') keepGoing = false; ostr++; istr++; } while(keepGoing && *istr != '\0' && *istr != '+' && *istr != '-' && *istr != '@' && *istr != '/'); *ostr = '\0'; return istr; } int _eval(char* sp, int tot) { if(*sp == '\0') return tot; char op[20]; sp = getToken(sp, op); char vstr[20]; int val = 0; sp = getToken(sp,vstr); if(*vstr =='-') // unary minus { sp = getToken(sp, vstr); val = -(_getopnd(vstr)); } else val = _getopnd(vstr); switch(*op) { case '+': tot case '-': tot case '@': tot case '/': tot } } int eval(char* sp) { char op[20]; getToken(sp, op); char sp1[80]; if(*op != '+' && *op != '-') strcpy(sp1,"+"); else strcpy(sp1,"");

+= -= *= /=

val; val; val; val;

break; break; break; break;

return _eval(sp,tot);

strcat(sp1, sp); return _eval(sp1, 0); } // Return the value of the operand string. The string may // be a simple token or an expression consisting of multiple // tokens and operators. Evaluation occurs from left to right; // no parenthesis allowed. Unary minus is allowed and correctly // evaluated. Valid operators are +, -, @, and /. The @ operator // is multiplication (the traditional * operator already is used // to refer to the location counter. unsigned getopnd(char* opnd) { //return _getopnd(opnd); // the old call did not allow for expressions unsigned retval = 0; if(strcmp(opnd,"-0") == 0 || strcmp(opnd,"-%0") == 0 || strcmp(opnd,"-$0") == 0) retval = 077777; // -0 else { // return the int value of the operand int opndVal = eval(opnd); // now, convert the number into 16-bit signed AGC format if(opndVal < 0) { // convert negative values into AGC 16-bit 1's C form. opndVal = 077777 + opndVal; if(opndVal < 0) { fprintf(fpList,"*** ERROR: %s underflowed.\n", opnd); errorCount++; opndVal = 0; } } else if(opndVal > 077777) { fprintf(fpList,"*** ERROR: %s overflowed.\n", opnd); errorCount++; opndVal = 0; } retval = (unsigned) opndVal; } return retval; } bool isDefined(char* opcd) { for(int j=0; allcodes[j].len != 99; j++) { if(strcmp(allcodes[j].name, opcd) == 0) { return true; } } return false; } unsigned getopcode(char* opcd) { for(int j=0; allcodes[j].len != 99; j++) { if(strcmp(allcodes[j].name, opcd) == 0) { return allcodes[j].code; } } fprintf(fpList,"*** ERROR: %s undefined.\n", opcd); errorCount++; return 0; } bool has12bitAddr(char* opcd) { for(int j=0; allcodes[j].len != 99; j++)

{ if(strcmp(allcodes[j].name, opcd) == 0) { return allcodes[j].addrOpnd; } } return false; } bool isOpCode(char* opcd) { for(int j=0; allcodes[j].len != 99; j++) { if(strcmp(allcodes[j].name, opcd) == 0) { return allcodes[j].isOpCode; } } return false; } unsigned getoplen(char* opcd) { for(int j=0; allcodes[j].len != 99; j++) { if(strcmp(allcodes[j].name, opcd) == 0) { return allcodes[j].len; } } return 0; } void updateLocCntr(char* opcd, char* opnd) { unsigned size = 0; for(int i=0; allcodes[i].len != 99; i++) { if(strcmp(allcodes[i].name, opcd) == 0) { size = allcodes[i].len; break; } } locCntr += size; if(strcmp(opcd,"ORG") == 0) { locCntr = getopnd(opnd); } } unsigned genOddParity(unsigned r) { //check the lower 15 bits of 'r' and return the odd parity unsigned evenParity = (1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^ (1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^ (1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^ (1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14)); return ~evenParity & 1; // odd parity } // Read the source file and build the symbol table. void readSourceForPass1(char* fn) { char buf[256]; char labl[100]; // label char opcd[100]; // op code char opnd[100]; // operand char cmnt[100]; // comment // Open the source code file. FILE* fp = fopen(fn, "r"); if(!fp) {

perror("fopen failed for source file"); return; } while(fgets(buf, 256, fp)) { parse(buf, labl, opcd, opnd, cmnt); if(strcmp(opcd,"INCL")==0) readSourceForPass1(opnd); if(strlen(labl)>0) { if(strcmp(opcd,"EQU")==0) add(labl, getopnd(opnd)); else add(labl, locCntr); } updateLocCntr(opcd, opnd); } fclose(fp); } // Read the source file and symbol table and build // the object code void readSourceForPass2(char* fn) { char buf[256]; char labl[100]; // label char opcd[100]; // op code char opnd[100]; // operand char cmnt[100]; // comment // Open the source code file. FILE* fp = fopen(fn, "r"); if(!fp) { perror("fopen failed for source file"); return; } while(fgets(buf,256,fp)) { parse(buf, labl, opcd, opnd, cmnt); if(strcmp(opcd,"INCL")==0) { // Include directive (INCL). fprintf(fpList, " %-14s %-8s %-14s %s\n", labl, opcd, opnd, cmnt); readSourceForPass2(opnd); } else if(strcmp(opcd,"")==0) { // Comment. fprintf(fpList, " %s\n", cmnt); } else if(getoplen(opcd) == 0) { // Must be ORG or EQU assembler directive. fprintf(fpList, " %-14s %-8s %-14s %s\n", labl, opcd, opnd, cmnt); if(!isDefined(opcd)) { fprintf(fpList,"*** ERROR: %s undefined.\n", opcd); errorCount++; } } else { // Since we got this far, we know the assembly line contains a // valid 'opcd' that reserves some storage space. It must be an // instruction or a DS. // Location counter (locCntr) contains 14-bit address; symbol table

// // // // // //

also stores 14-bit addresses. If the operand is an address above bank 3 (05777), it is not directly addressable and needs to be converted into a 12-bit bank address. In bank addressing, bits 12,11 are set and bits 10-1 contain the address inside the bank. (The programmer must set the bank register to select the correct bank.)

// Generate a string containing the address (for the list file). // If the address is erasable, or fixed-fixed, show the 12-bit // address. // If the address is fixed-switchable, show the bank number, // followed by the 10-bit bank address. unsigned locCntrBank = (036000 & locCntr) >> 10; char locCntrString[20]; if(locCntrBank <= 3) sprintf(locCntrString, " %04o", locCntr); else sprintf(locCntrString, "%2o,%04o", locCntrBank, 01777 & locCntr); // Generate the data to be stored at that address. Convert to // 12-bit address format, if necessary. unsigned operValue = getopnd(opnd); unsigned operBank = (036000 & operValue) >> 10; if(has12bitAddr(opcd)) { // Convert operand from a 14-bit address to a 12-bit // address. // First, find bank (bits 14-11). If the bank is <= 03, no // conversion is necessary. if(operBank > 03) { // Bank is not directly addressable, so get 10 bit // bank address and set fixed-switchable flag bits // 12 and 11. operValue = (01777 & operValue) | 06000; } } unsigned data = getopcode(opcd) + operValue; data |= genOddParity(data) << 15; // Generate a string containing the data info for the list file. char dataString[20]; if(isOpCode(opcd)) sprintf(dataString, "%01o %2o,%04o %1o", (getopcode(opcd) & 070000) >> 12, operBank, operValue, genOddParity(data)); else sprintf(dataString, " %05o %1o", operValue, genOddParity(data)); if(memoryUsed[locCntr]) { fprintf(fpList,"*** ERROR: %06o address already in use.\n", locCntr); errorCount++; } memoryUsed[locCntr] = true; fprintf(fpList, "%05o %7s %11s %-14s %-8s %-14s %s\n", locCntr, locCntrString, dataString, labl, opcd, opnd, cmnt); //*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. // Insert the assembled code into an array, indexed by the address. // This has the effect of sorting the data by address, so we can walk // through the addresses and output the code to EPROM later. unsigned dataLow = 0x00ff & data; unsigned dataHigh = (0xff00 & data) >> 8; if(locCntr >=1024) // FIXED MEMORY only; not ERASEABLE { // fixed memory EPROM_H [locCntr] = dataHigh; EPROM_L [locCntr] = dataLow;

} //*********************************************************************** } updateLocCntr(opcd, opnd); } fclose(fp); } //*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. void writeEPROM(FILE* fpObj, int EPROM[]) { // Write an EPROM file using Motorola's S-Record format (s2f). // // // const int const int const int Some parameters that control file format. You can change maxBytes without affecting anything else. 'addressBytes' is determined by the choosen S-Record format. maxBytes = 20; // set limit on record length addressBytes = 3; // 16-bit address range sumCheckBytes = 1;

const int maxdata = maxBytes - addressBytes - sumCheckBytes; int i=0; // current EPROM address int sumCheck = 0; while (i < agcMemSize) { // get dataByteCount; the number of bytes of EPROM data per record. int dataByteCount = maxdata; if(i + dataByteCount >= agcMemSize) { dataByteCount = agcMemSize - i; } // write record header (*** 2 byte address assumed ***) int totalByteCount = dataByteCount + addressBytes + sumCheckBytes; fprintf(fpObj, "S2%02X%06X", totalByteCount, i); sumCheck = totalByteCount & 0xff; sumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256; sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256; sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256; // write data bytes into record for(int j=0; j<dataByteCount; j++) { fprintf(fpObj, "%02X", EPROM [i+j]); sumCheck = (sumCheck + EPROM [i+j]) % 256; } // terminate record by adding the checksum and a newline. fprintf(fpObj, "%02X\n", (~sumCheck) & 0xff); i += dataByteCount; } // write an end-of-file record here i=0; // set address zero for last record sumCheck = 0x04; // byte count sumCheck = (sumCheck + ((i & 0xff0000) >> 16)) % 256; sumCheck = (sumCheck + ((i & 0x00ff00) >> 8)) % 256; sumCheck = (sumCheck + ((i & 0x0000ff) )) % 256; fprintf(fpObj, "S804%06X%02X", i, (~sumCheck) & 0xff); } //*********************************************************************** void main(int argc, char* argv[]) { cout << "AGC Block I assembler" << endl; // // // // The assembler reads an assembly source code file with a .asm extension; i.e.: myProg.asm It writes an assembly listing text file with a .lst extension (myProg.lst) and an object code

// text file with a .obj extension (myProg.obj) #ifdef NOTDEF // use this to enter the source file using command line if(argc != 2) { cout << "*** ERROR: source file name not specified." << endl; exit(-1); } fp = fopen(argv[1], "r"); #endif char sourcefile[80]; cout << "Enter source file: "; cin >> sourcefile; // Valid source files have a .asm extension; strip the // extension off so we can use the prefix for the list // and object files. char prefix[80]; strcpy(prefix, sourcefile); char* p = prefix; while(*p != '\0') { p++; if(*p == '.') break; } if(strcmp(p,".asm") != 0) { cerr << "*** ERROR: Source file not *.asm" << endl; exit(-1); } *p = '\0'; // Open a text file for the assembly listing. The filename // will have a .lst extension. char listfile[80]; sprintf(listfile, "%s.lst", prefix); fpList = fopen(listfile, "w"); if(!fpList) { perror("fopen failed for assembly list file"); exit(-1); } //*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. // Open a two text files for the object code. The filenames // will have a .hex extension char objfile[80]; sprintf(objfile, "%s_H.hex", prefix); fpObj_H = fopen(objfile, "w"); if(!fpObj_H) { perror("fopen failed for object file"); exit(-1); } sprintf(objfile, "%s_L.hex", prefix); fpObj_L = fopen(objfile, "w"); if(!fpObj_L) { perror("fopen failed for object file"); exit(-1); } fprintf(fpList,"Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM\n\n"); // INITIALIZE EPROM for(int k=0; k< agcMemSize; k++) { EPROM_H [k] = 0; EPROM_L [k] = 0; } //*********************************************************************** fprintf(fpList,"First pass: generate symbol table.\n");

readSourceForPass1(sourcefile); locCntr = 0; pass++; // Clear the memory use flags; these are used to catch // any overwriting of already assembled code. memset(memoryUsed, false, sizeof(bool) * agcMemSize); fprintf(fpList,"Second pass: generate object code.\n\n"); readSourceForPass2(sourcefile); //*********************************************************************** // MODIFIED FROM THE ORIGINAL ASSEMBLER HERE. // Write the EPROM data to file writeEPROM(fpObj_H, EPROM_H); writeEPROM(fpObj_L, EPROM_L); fclose(fpObj_H); fclose(fpObj_L); //*********************************************************************** fprintf(fpList,"\nAssembly complete. Errors = %d\n", errorCount); fprintf(fpList,"\nSymbol table:\n"); unsigned j=0; for(unsigned i=0; i<nSym; i++) { fprintf(fpList,"%-14s %06o ", symTab[i].name, symTab[i].val); j = (j+1) % 3; if(j==0) fprintf(fpList,"\n"); } fclose(fpList); }

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 7: C++ Simulator
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
This documen t describes my AG C Block I C++ sim ulator. I developed it almost entirely from detaile d inform ation in this d ocum ent: A. Hopk ins, R. Alonso, and H . Blair-Smith, "Logical Description for the Apollo Guidan ce Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. My simulator reproduces not only the AGC instruction set and user-accessible registers, but all of the registers, all microinstructions, time-pulse generator states, read, write and me mo ry busses, and con trol pulses (logic signals) for all AGC subsystem s. The simulator is a tool I used to capture AGC design from the R-39 3 docum ent. When I got it working well enough to run my test and checkout software suite (described in part 9) and flight software (described in part 8), I knew I understood the AGC well enough to build one. The sim ulato r head er and source co de files be cam e requ irem ents th at gu ided my AG C log ic design (d escribed in parts 2-5 ).

Running the simulator


The simulator is run by keyboard comm ands. The output is a scrolling, formatted text display; the compiler obligingly provides a little DOS window for viewing the output. It looks like this (most of the nu m bers are in octal): The to p line is the revision number of the sim ula tor. I went through lots of versions. The second line sh ow s th e T im e Pulse Generator state (TP11) and some of the important scaler outpu ts. The nex t line shows th e current state of some sm all registers in the SEQ su bsystem , which is part of the AGC control module. STA an d STB stage registers which select instruction sub sequ ences . BR1 and 2 are th e bran ch regis ters. SNI is sele ct next in struction , a 1-bit register that does exactly that. CI is the carry-in bit for the ALU. The loop counter is used for iterating throu gh arithm etic instructions. The n ext line , starting w ith RP CELL , show s im portan t registers ass ociated with interrup ts and the priority counters. The tail-end of the line shows the current instruction (in the SQ register), which is an INDEX instruction. The subsequence is NDX0.

The ne xt lin e (C P) sh ow s curre ntly asse rted c ontrol pu lses (l ogic signals). ST1 a nd WE are being asserted. The left side of the next 4 lines shows the state of registers associated with memory (S, G, P, P2, and C ADR ), the ALU (B , X, Y, U), and the read b us (RB U) and write bus (W BU). The right side of those 4 lines shows control inputs for running, stepping, and clocking the sim ula tor. The bottom part of the display shows AGC m emory. The 2-digit num bers on the left show mem ory addresses from 00-56 . Each mem ory location has a nam e; its shown to the right of the address. Immediately to the right of that is the contents of that location. Add resses 00 -17 a re m app ed to A GC registers, an d are n ot really p art of the A GC eraseab le memory. Addresses 00-03 are the AGC central registers, followed by input and output registers. Addresses 16 and 17 are not storage locations, but a means for enabling and disabling interrupts. The eraseab le mem ory starts at address 20. Add resses 20-23 a re the editing registers. Writing to these causes the data in the registers to be shifted or rotated. Add resses 24-27 a re used for saving the cen tral registers (00-03) wh en an in terrupt occurs. Add resses 34-56 a re priority counter locations. The AG C will increm ent or decrem ent these based on + pr - logic signa ls to the priority counter cells. The lower right of the simulator is the DSKY: the display/keyboard user interface for the astron auts. Th e sim ulato r is runn ing th e CO LOS SU S 24 9 fligh t softwa re load, a nd is curren tly execu ting m ajor m ode 0 (P00 ), verb 16 , noun 36, w hich is a m onitor p rogram to continuously display the command module elapsed time clock. The clock, displayed in R1, R2, and R3, shows 0 hours, 1 minute, and 54.23 seconds. It updates about once a second but, of course, you cant see that here.

Compiler
The simulator was compiled with Microsoft Visual C++ 6.0 Standard Edition.

Commands
Heres the comp lete list of com ma nds the sim ulator know s. The keyboa rd key you h it is: {Q}, and the name of the command is: <QUIT>.

Simulator commands
{q} {l} <QUIT> <LOAD> Exits the sim ula tor. The comm and is a lower case L, not a 1". Load fixed m em ory w ith objec t cod e pro du ced by th e ass em bler. The object code files are in Motorola S-Record format (compatible with EPROM programmers). The command will ask for a filenam e. Intended to be a useful menu of simulator command, but I ne ver got a roun d to it.

{m}

<MENU>

Hardware reset commands


{p} <POW ER UP RESET> Asserts the PURST control signal. This is a power-up reset sign al tha t is supp osed to be au tom atically generated when the AGC initially powers on. Asserts th e GEN RS T con trol signa l.

{h}

<RESET>

Clock controls
{F1} {F2} <CLK> <MCLK> Single-step the AGC clock. Only works when MCLK <F2> has been selected. Asserts the MCLK control signal. Disables the freerunning 1MHz clock. When MCLK is selected, you can single-step the clock by by pressing <F1>. Asserts the FCLK control signal. Causes the simu lator clock to free-run at 1MHz. This is the normal operational mod e.

{F4}

<FCLK>

Time pulse generator (TPG) controls


{r} <RUN> Toggles b etween the run (1) an d step (0) m odes. Run mak es the AG C free-run (the norm al mo de). Step single-steps the AGC, either by instruction or by instruction subsequence. Steps the AGC to the next instruction or instruction sequence when <R> is toggled to the step mode. Toggles whether the AGC steps by instruction (1) or instruction subsequence (0). Each instruction contains one or more subsequences. Each subsequence is 12 steps or timing pulses long.

{s} {n}

<STEP> <INST>

Debugger commands
{e} <EXAM INE> Examines the contents of memory. The comman d asks for a sta rting add ress a nd then disp lays the m em ory data at that ad dress and follow ing locations. Halts the AGC wh en any instruction changes a watched m em ory lo catio n. Th e com m and as ks for a m em ory address (CADR) to watch. Toggles a breakpoint on/off. When the breakpoint is on, it halts the AGC when instruction execution hits that address. Displays or refreshes the standard AGC register display. Displays the currently executing AGC source code. You can single step with this display and watch the AGC move through the source code. Very useful for debugging. A > arrow shows the next instruction to be executed in the listing.

{y}

<WATCH>

{b}

<BREAK POINT>

{d} {f}

<DISPLAY> <DEBUG>

Scaler controls
{z} <F17> Manu ally generates the <F17 > scaler pulse. Useful for testing when the scaler has been toggled to off <C>, or when youre single-stepping the AGC. Manu ally generates the <F13 > scaler pulse. Useful for testing when the scaler has been toggled to off <C>, or when youre single-stepping the AGC. Toggle the scaler on/off. When the scaler is off, the F13 and F17 signals are not automatically generated.

{x}

<F13>

{c}

<TOGGLE SCALER>

Priority counter controls


{[} {]} <-CNTR> <+CNTR> Ma nua lly assert a m inus inpu t to a prority co unte r cell. The com m and w ill ask for the cell n um ber. Ma nua lly assert a p lus inp ut to a p riority coun ter cell. The com m and w ill ask for the cell n um ber.

Interrupt controls
{i} <INTERRUPT> Generates an AGC interrupt. The comm and will ask you for an interrupt num ber (1-5).

Other AGC controls


{a} {;} <STANDBY ALLOWED> <CLEAR PARITY ALARM> The standby allowed switch lets the AGC software put the AGC in a standby m ode. Clears the parity alarm. The alarm is generated when an error oc curs (odd pa rity) in m em ory.

DSKY controls
{/} {*} {-} {+} {.} {j} {g} <VERB> <NOUN> <MINUS> <PLUS> <CLEAR> <ENTER> <KEY R EL> The The The The The The The VERB key on the DSKY display. NOUN key on the DSKY display. MINUS key on the DSKY display. PLUS key on the DSKY display. CLEAR key on the DSKY display. ENTER key on the DSKY display. KEY RELEASE key on the DSKY display.

Simulator demonstration
Heres the sim ulato r, dem onstra ting so m e CO LOS SU S 24 9 fligh t softwa re functio ns. Th is is the same scenario I ran in Part 1 using my hardware AGC.

Initialization
At startup, the simulator loads the microinstructions from the EPROM tables. These are the sam e tables I eventually use d to program the hardw are AGC EPRO Ms. Reading Reading Reading Reading Reading Reading Reading EPR OM: EPR OM: EPR OM: EPR OM: EPR OM: EPR OM: EPR OM: CP M1_8 .hex CP M9_1 6.hex CP M17_ 24.hex CP M25_ 32.hex CP M33_ 40.hex CP M41_ 48.hex CP M49_ 56.hex

The simulator is now initialized and read y for comm ands.

<LOAD> The simulator asks, and I enter the name of object files containing the COLOSSUS flight software.

<POWER UP RESET> <RUN> <FCLK> I tell the sim ula tor to start running, and enable the freerunn ing clo ck. The AG C starts running in real-time with the 1MHz clock. The DSK Y shows m ajor mo de 00 (P0 0).

Display elapsed time from the CM clock


<VERB> <0> < 6> <NOUN> <3> <6> <ENTER>

Test display lights


<VERB> <3> <5> <ENTER> All DSKY lamps and display segm ents illum inate for 5 sec; after 5 sec, the DSKY lamps extinguish.

Load component 1 for dataset at octal address 50 with octal 123


<VERB> <2> < 1> <NOUN> <0> <1> <ENTER> Verb/noun display flashes: waiting for address. Flashing is indicated by the asterisk to the right of the NOUN display.

<5> <0> <ENTER> Verb/no un disp lay flash continu es: waiting for data.

<1> <2> <3> <ENTER> Octal word from R1 is loaded at address 50.

Start a monitor program to continuously display elapsed time from the CM clock
<VERB> <1> < 6> <NOUN> <3> <6> <ENTER>

Display component 1 of dataset at octal address 50


<VERB> <0> < 1> The key rel light flashes be cause the CM clock monitor program has been suspended. This is indicated by an asterisk in the KR display above the DSKY.

<NOUN> <0> <1> <ENTER> Verb/noun display flashes: waiting for address.

<5> <0> <ENTER> Octa l word from a ddres s 50 is displayed in R1.

Increment the address


<NOUN> <1> <5> <ENTER> Octa l word from a ddres s 51 is displayed in R1, address in R3.

<ENTER> Octa l word from a ddres s 52 is displayed in R1, address in R3.

Resume the CM clock monitor program


<KEY R EL> Verb 16, noun 36 reappears, along with the clock display. Notice that the K R ligh t (asterisk) g oes ou t.

Terminate the CM clock monitor program


<VERB> <3> <4> <ENTER>

Change major mode to P00


<VERB> <3> <7> <ENTER> Verb/no un disp lay flashes: waiting for major mode.

<0> <0> <ENTER>

The 20 -or-so subsystems in the AGC are represented by C++ classes. There are some additional classes for registers and other things. I wanted a simulator architec ture I could develop quickly that wou ld easily and directly m ap to a hard wa re logic design. I went through 16 versions of the sim ula tor; th eyre discussed at the top of the A GC Ma in.cpp file wh ich contains, unsurprisingly, the ma in(). If you want to run the simulator, you can compile it from the source code given here. To run it, youll also need the assembler (discussed in part 6), some AGC software (parts 8 and 9), and the EPROM tables in Motorola S-Record format. The C++ code to generate these tables is given at the end of part 2. Here it is, warts a nd all...

Main (AGCMain.cpp)
/**************************************************************************** * AGC4 (Apollo Guidance Computer) BLOCK I Simulator * * AUTHOR: John Pultorak * DATE: 07/29/02 * FILE: AGCmain.cpp * * VERSIONS: * 1.0 - initial version. * 1.1 - fixed minor bugs; passed automated test and checkout programs: * teco1.asm, teco2.asm, and teco3.asm to test basic instructions, * extended instructions, and editing registers. * 1.2 - decomposed architecture into subsystems; fixed minor bug in DSKY * keyboard logic (not tested in current teco*.asm suite). * Implemented scaler pulses F17, F13, F10. Tied scaler output to * involuntary counters and interrupts. Implemented counter overflow * logic and tied it to interrupts and other counters. Added simple * set/clear breakpoint. Fixed a bug in bank addressing. * 1.3 - fixed bugs in the DSKY. Added 14-bit effective address (CADR) to the * simulator display output. Inhibited interrupts when the operator * single-steps the AGC. * 1.4 - performance enhancements. Recoded the control pulse execution code * for better simulator performance. Also changed the main loop so it * polls the keyboard and system clock less often for better performance. * 1.5 - reversed the addresses of TIME1 and TIME2 so TIME2 occurs first. * This is the way its done in Block II so that a common routine (READLO) * can be used to read the double word for AGC time. * 1.6 - added indicators for 'CHECK FAIL' and 'KEY RELS'. Mapped them to OUT1, * bits 5 and 7. Added a function to display the current location in * the source code list file using the current CADR. * 1.7 - increased length of 'examine' function display. Any changes in DSKY now * force the simulator to update the display immediately. Added a 'watch' * function that looks for changes in a memory location and halts the * AGC. Added the 'UPTL', 'COMP', and "PROG ALM" lights to the DSKY. * 1.8 - started reorganizing the simulator in preparation for H/W logic design. * Eliminated slow (1Hz) clock capability. Removed BUS REQUEST feature. * Eliminated SWRST switch. * 1.9 - eliminated the inclusive 'OR' of the output for all registers onto the * R/W bus. The real AGC OR'ed all register output onto the bus; normally * only one register was enabled at a time, but for some functions several * were simultaneously enabled to take advantage of the 'OR' function (i.e.: * for the MASK instruction). The updated logic will use tristate outputs * to the bus except for the few places where the 'OR' function is actually * needed. Moved the parity bit out of the G register into a 1-bit G15 * register. This was done for convenience because the parity bit in G * is set independently from the rest of the register. * 1.10 - moved the G15 parity register from MBF to the PAR subsystem. Merged SBFWG * and SBEWG pulses into a single SBWG pulse. Deleted the CLG pulse for MBF * (not needed). Separated the ALU read pulses from all others so they can * be executed last to implement the ALU inclusive OR functions. Implemented * separate read and write busses, linked through the ALU. Implemented test * parity (TP) signal in PAR; added parity alarm (PALM) FF to latch PARITY * ALARM indicator in PAR. * 1.11 - consolidated address testing signals and moved them to ADR. Moved memory * read/write functions from MBF to MEM. Merged EMM and FMM subsystems into * MEM. Fixed a bad logic bug in writeMemory() that was causing the load of * the fixed memory to overwrite array boundaries and clobber the CPM table. * Added a memory bus (MEM_DATA_BUS, MEM_PARITY_BUS). * 1.12 - reduced the number of involuntary counters (CTR) from 20 to 8. Eliminated * the SHINC subsequence. Changed the (CTR) sequence and priority registers into * a single synchronization register clocked by WPCTR. Eliminated the fifth * interrupt (UPRUPT; INT). Eliminated (OUT) the signal to read from output * register 0 (the DSKY register), since it was not used and did not provide * any useful function, anyway. Deleted register OUT0 (OUT) which shadowed * the addressed DSKY register and did not provide any useful function. * Eliminated the unused logic that sets the parity bit in OUT2 for downlink * telemetry. * 1.13 - reorganized the CPM control pulses into CPM-A, CPM-B, and CPM-C groups. * Added the SDV1, SMP1, and SRSM3 control pulses to CPM-A to indicate when * those subsequences are active; these signals are input to CPM-C. Moved the * ISD function into CPM-A. Fixed a minor bug causing subsequence RSM3 to be * displayed as RSM0. Added GENRST to clear most registers during STBY. * 1.14 - Moved CLISQ to TP1 to fix a problem in the hardware AGC. CLISQ was clearing

* SNI on CLK2 at TP12, but the TPG was advancing on CLK1 which occurs after * CLK2, so the TPG state machine was not seeing SNI and was not moving to * the correct state. In this software simulation, everything advances on * the same pulse, so it wasn't a problem to clear SNI on TP12. Added a * switch to enable/disable the scaler. * 1.15 - Reenabled interrupts during stepping (by removing MON::RUN) signals from * CPM-A and CPM-C logic). Interrupts can be prevented by disabling the scaler. * Fixed a problem with INHINT1; it is supposed to prevent an interrupt * between instructions if there's an overflow. It was supposed to be cleared * on TP12 after SNI (after a new instruction), but was being cleared on TP12 * after every subsequence. * 1.16 - Changed CPM-A to load and use EPROM tables for the control pulse matrix. The * EPROM tables are negative logic (0=asserted), but this simulator expects * positive logic, so each word is bit-flipped when the EPROM tables load * during simulator initialization. * SOURCES: * Mostly based on information from "Logical Description for the Apollo Guidance * Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh Blair-Smith, R-393, * MIT Instrumentation Laboratory, 1963. * * PORTABILITY: * Compiled with Microsoft Visual C++ 6.0 standard edition. Should be fairly * portable, except for some Microsoft-specific I/O and timer calls in this file. * * NOTE: set tabs to 4 spaces to keep columns formatted correctly. * ***************************************************************************** */ #include <conio.h> #include #include #include #include #include #include #include #include <iostream.h> <stdio.h> <stdlib.h> <string.h> <conio.h> <stdio.h> <time.h> <ctype.h>

#include "reg.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TPG.h" "MON.h" "SCL.h" "SEQ.h" "INP.h" "OUT.h" "BUS.h" "DSP.h" "ADR.h" "PAR.h" "MBF.h" "MEM.h" "CTR.h" "INT.h" "KBD.h" "CRG.h" "ALU.h" "CPM.h" "ISD.h" "CLK.h"

extern bool dskyChanged; //----------------------------------------------------------------------// CONTROL LOGIC void genAGCStates() { // 1) Decode the current instruction subsequence (glbl_subseq). // SEQ::glbl_subseq = CPM::instructionSubsequenceDecoder(); // 2) Build a list of control pulses for this state. CPM::controlPulseMatrix();

// // // // // // // // //

3) Execute the control pulses for this state. In the real AGC, these occur simultaneously. Since we can't achieve that here, we break it down into the following steps: Most operations involve data transfers--usually reading data from a register onto a bus and then writing that data into another register. To approximate this, we first iterate through all registers to perform the 'read' operation--this transfers data from register to bus. Then we again iterate through the registers to do 'write' operations, which move data from the bus back into the register. = 0; = 0; = 0; // // // // clear bus; necessary because words are logical OR'ed onto the bus. clear data lines: memory bits 15-1 parity line: memory bit 16

BUS::glbl_READ_BUS MEM::MEM_DATA_BUS MEM::MEM_PARITY_BUS

// Now start executing the pulses: // First, read register outputs onto the bus or anywhere else. int i; for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++) { CLK::doexecR(SEQ::glbl_cp[i]); } // Next, execute ALU read pulses. See comments in ALU .C file ALU::glbl_BUS = 0; for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++) { CLK::doexecR_ALU(SEQ::glbl_cp[i]); } BUS::glbl_WRITE_BUS = BUS::glbl_READ_BUS; // in case nothing is logically OR'ed below; for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++) { CLK::doexecR_ALU_OR(SEQ::glbl_cp[i]); } // Now, write the bus and any other signals into the register inputs. for(i=0; i<MAXPULSES && SEQ::glbl_cp[i] != NO_PULSE; i++) { CLK::doexecW(SEQ::glbl_cp[i]); } // Always execute these pulses. SCL::doexecWP_SCL(); SCL::doexecWP_F17(); SCL::doexecWP_F13(); SCL::doexecWP_F10(); TPG::doexecWP_TPG(); } //----------------------------------------------------------------------// SIMULATION LOGIC // contains prefix for source filename; i.e.: the portion // of the filename before .obj or .lst char filename[80]; char* getCommand(char* prompt) { static char s[80]; char* sp = s; cout << prompt; cout.flush(); char key; while((key = _getch()) != 13) { if(isprint(key)) { cout << key; cout.flush(); *sp = key; sp++; }

else if(key == 8 && sp != s) { cout << key << " " << key; cout.flush(); sp--; } } *sp = '\0'; return s; } bool breakpointEnab = false; unsigned breakpoint = 0; void toggleBreakpoint() { if(!breakpointEnab) { char b[80]; strcpy(b, getCommand("Set breakpoint: -- enter 14-bit CADR (octal): ")); cout << endl; breakpoint = strtol(b,0,8); breakpointEnab = true; } else { cout << "Clearing breakpoint." << endl; breakpointEnab = false; } } bool watchEnab = false; unsigned watchAddr = 0; unsigned oldWatchValue = 0; void toggleWatch() { if(!watchEnab) { char b[80]; strcpy(b, getCommand("Set watch: -- enter 14-bit CADR (octal): ")); cout << endl; watchAddr = strtol(b,0,8); watchEnab = true; oldWatchValue = MEM::readMemory(watchAddr); char buf[100]; sprintf(buf, "%06o: %06o", watchAddr, oldWatchValue); cout << buf << endl; } else { cout << "Clearing watch." << endl; watchEnab = false; } } void incrCntr() { char cntrname[80]; strcpy(cntrname, getCommand("Increment counter: -- enter pcell (0-19): ")); cout << endl; int pc = atoi(cntrname); CTR::pcUp[pc] = 1; } void decrCntr() { char cntrname[80]; strcpy(cntrname, getCommand("Decrement counter: -- enter pcell (0-19): ")); cout << endl; int pc = atoi(cntrname); CTR::pcDn[pc] = 1; }

void interrupt() { char iname[80]; strcpy(iname, getCommand("Interrupt: -- enter priority (1-5): ")); cout << endl; int i = atoi(iname) - 1; INT::rupt[i] = 1; }

#ifdef NOTDEF // Load AGC memory from the specified file object file void loadMemory() { strcpy(filename, getCommand("Load Memory -- enter filename: ")); cout << endl; // Add the .obj extension. char fname[80]; strcpy(fname, filename); strcat(fname, ".obj"); FILE* fp = fopen(fname, "r"); if(!fp) { perror("fopen failed:"); cout << "*** ERROR: Can't load memory for file: " << fname << endl; return; } unsigned addr; unsigned data; while(fscanf(fp, "%o %o", &addr, &data) != EOF) { MEM::writeMemory(addr, data); } fclose(fp); cout << "Memory loaded." << endl; } #endif static int loadBuf[0xffff+1]; // tempory buffer for assembling H,L memory data

void loadEPROM(char* fileName, bool highBytes) { cout << "Reading EPROM: " << fileName << endl; // Open the EPROM file. FILE* ifp = fopen(fileName, "r"); if(!ifp) { perror("fopen failed for source file"); exit(-1); } const int addressBytes = 3; // 24-bit address range const int sumCheckBytes = 1; char buf[4096]; // buffer holds a single S-Record while(fgets(buf,4096,ifp)) { // process a record if(buf[0] != 'S') { cout << "Error reading start of EPROM record for: " << fileName << endl; exit(-1); } char tmp[256]; strncpy(tmp, &buf[2], 2); tmp[2] = '\0'; int totalByteCount = strtol(tmp, 0, 16); int mySumCheck = totalByteCount & 0xff;

strncpy(tmp, &buf[4], 6); tmp[addressBytes*2] = '\0'; int address = strtol(tmp, 0, 16); mySumCheck = (mySumCheck + ((address & 0xff0000) >> 16)) % 256; mySumCheck = (mySumCheck + ((address & 0x00ff00) >> 8)) % 256; mySumCheck = (mySumCheck + ((address & 0x0000ff) )) % 256; //cout << hex << totalByteCount << ", " << address << dec << endl; int dataBytes = totalByteCount - addressBytes - sumCheckBytes; int i = (addressBytes+2)*2; // index to 1st databyte char. for(int j=0; j<dataBytes; j++) { // get a data byte strncpy(tmp, &buf[i], 2); tmp[2] = '\0'; int data = strtol(tmp, 0, 16); //cout << hex << data << dec << endl; mySumCheck = (mySumCheck + data) % 256; if(highBytes) { loadBuf[address] = loadBuf[address] | ((data << 8) & 0xff00); } else { loadBuf[address] = loadBuf[address] | (data & 0xff); } address++; i+=2; // bump to next databyte char } strncpy(tmp, &buf[i], 2); tmp[2] = '\0'; int sumCheck = strtol(tmp, 0, 16); if(sumCheck != ((~mySumCheck) & 0xff)) { cout << "sumCheck failed; file: " << fileName << ", address: " << hex << address << ", sumCheck: " << sumCheck << ", mySumCheck: " << mySumCheck << dec << endl; exit(-1); } } fclose(ifp); cout << "Memory loaded." << endl; } // Load AGC memory from the specified EPROM files void loadMemory() { strcpy(filename, getCommand("Load Memory -- enter filename: ")); cout << endl; char fname[80]; // Add the _H.hex extension. strcpy(fname, filename); strcat(fname, "_H.hex"); loadEPROM(fname, true); // Add the _L.hex extension. strcpy(fname, filename); strcat(fname, "_L.hex"); loadEPROM(fname, false); //******************************************************************* // EPROM is now in loadBuf; move it to AGC memory. // AGC fixed memory only uses NUMFBANK banks. for(int address=1024; address < 1024*(NUMFBANK+1); address++) { // Don't load address region 0-1023; that region is allocated

// to eraseable memory. //cout << "loading CADR=" << hex << address << endl; MEM::writeMemory(address, loadBuf[address]); } //******************************************************************* } // Write the entire contents of fixed and // eraseable memory to the specified file. // Does not write the registers void saveMemory(char* filename) { FILE* fp = fopen(filename, "w"); if(!fp) { perror("*** ERROR: fopen failed:"); exit(-1); } char buf[100]; for(unsigned addr=020; addr<=031777; addr++) { sprintf(buf, "%06o %06o\n", addr, MEM::readMemory(addr)); fputs(buf, fp); } fclose(fp); } void examineMemory() { char theAddress[20]; strcpy(theAddress, getCommand("Examine Memory -- enter address (octal): ")); cout << endl; unsigned address = strtol(theAddress, 0, 8); char buf[100]; for(unsigned i=address; i<address+23; i++) { sprintf(buf, "%06o: %06o", i, MEM::readMemory(i)); cout << buf << endl; } } // Returns true if time (s) elapsed since last time it returned true; does not block // search for "Time Management" bool checkElapsedTime(time_t s) { if(!s) return true; static clock_t start = clock(); clock_t finish = clock(); double duration = (double)(finish - start) / CLOCKS_PER_SEC; if(duration >= s) { start = finish; return true; } return false; } // Blocks until time (s) has elapsed. void delay(time_t s) { if(!s) return; clock_t start = clock(); clock_t finish = 0; double duration = 0; do { finish = clock(); } while((duration = (double)(finish - start) / CLOCKS_PER_SEC) < s);

} void updateAGCDisplay() { static bool displayTimeout = false; static int clockCounter = 0; if(checkElapsedTime(2)) displayTimeout = true; if(MON::FCLK) { if(MON::RUN) { // update every 2 seconds at the start of a new instruction if(displayTimeout || dskyChanged) { clockCounter++; if( (TPG::register_SG.read() == TP12 && SEQ::register_SNI.read() == 1) || (TPG::register_SG.read() == STBY) || clockCounter > 500 || dskyChanged) { MON::displayAGC(); displayTimeout = false; clockCounter = 0; dskyChanged = false; } } } else { static bool displayOnce = false; if(TPG::register_SG.read() == WAIT) { if(displayOnce == false) { MON::displayAGC(); displayOnce = true; clockCounter = 0; } } else { displayOnce = false; } } } else MON::displayAGC(); // When the clock is manual or slow, always update. } void showMenu() { cout << "AGC4 EMULATOR MENU:" << endl; cout << " 'r' = RUN: toggle RUN/HALT switch upward to the RUN position." << endl; } const int startCol const int colLen const int maxLines const int noffset = 0; = 5; = 23; = 10; // columns are numbered 0-n // number of chars in column // # of total lines to display // # of lines prior to, and including, selected line

const int maxLineLen = 79; void showSourceCode() { // Add the .lst extension. char fname[80]; strcpy(fname, filename); strcat(fname, ".lst"); // Open the file containing the source code listing. FILE* fp = fopen(fname, "r"); if(!fp)

{ perror("fopen failed:"); cout << "*** ERROR: Can't load source list file: " << fname << endl; return; } cout << endl; // Get the address of the source code line to display. // The address we want is the current effective address is the // S and bank registers. char CADR[colLen+1]; sprintf(CADR, "%05o", ADR::getEffectiveAddress()); int op = 0; // offset index long foffset[noffset]; for(int i=0; i<noffset; i++) foffset[i]=0; bool foundit = false; int lineCount = 0; char s[256]; char valString[20]; char out[256]; while(!feof(fp)) { if(!foundit) { foffset[op] = ftell(fp); op = (op + 1) % noffset; } // Read a line of the source code list file. if(fgets(s, 256, fp)) { // Get the address (CADR) from the line. strncpy(valString, s+startCol, colLen); valString[colLen]='\0'; // 'foundit' is true after we have found the desired line. if(foundit) { if(strcmp(valString,CADR) == 0) cout << ">"; else cout << " "; // truncate line so it fits in 80 col display strncpy(out, s, maxLineLen); out[maxLineLen] = '\0'; cout << out; lineCount++; if(lineCount >= maxLines) break; } else { if(strcmp(valString, CADR) == 0) { // Reposition the file pointer back several lines so // we can see the code that preceeds the desired // line, too. foundit = true; fseek(fp, foffset[op], 0); } } } } fclose(fp); }

void main(int argc, char* argv[]) {

CPM::readEPROM( "CPM1_8.hex", CPM::readEPROM( "CPM9_16.hex", CPM::readEPROM("CPM17_24.hex", CPM::readEPROM("CPM25_32.hex", CPM::readEPROM("CPM33_40.hex", CPM::readEPROM("CPM41_48.hex", CPM::readEPROM("CPM49_56.hex", bool singleClock = false; genAGCStates(); MON::displayAGC();

CPM::EPROM1_8); CPM::EPROM9_16); CPM::EPROM17_24); CPM::EPROM25_32); CPM::EPROM33_40); CPM::EPROM41_48); CPM::EPROM49_56);

while(1) { // NOTE: assumes that the display is always pointing to the start of // a new line at the top of this loop! // Clock the AGC, but between clocks, poll the keyboard // for front-panel input by the user. This uses a Microsoft function; // substitute some other non-blocking function to access the keyboard // if you're porting this to a different platform. cout << "> "; cout.flush(); // display prompt while( !_kbhit() ) { if(MON::FCLK || singleClock) { // This is a performance enhancement. If the AGC is running, // don't check the keyboard or simulator display every // simulation cycle, because that slows the simulator // down too much. int genStateCntr = 100; do { CLK::clkAGC(); singleClock = false; genAGCStates(); genStateCntr--; // Needs more work. It doesn't always stop at the // right location and sometimes stops at the // instruction afterwards, too. if(breakpointEnab && breakpoint == ADR::getEffectiveAddress()) { MON::RUN = 0; } // Halt right after instr that changes a watched // memory location. if(watchEnab) { unsigned newWatchValue = MEM::readMemory(watchAddr); if(newWatchValue != oldWatchValue) { MON::RUN = 0; } oldWatchValue = newWatchValue; } } while (MON::FCLK && MON::RUN && genStateCntr > 0); updateAGCDisplay(); } // for convenience, clear the single step switch on TP1; in the // hardware AGC, this happens when the switch is released if(MON::STEP && TPG::register_SG.read() == TP1) MON::STEP = 0; } char key = _getch(); // Keyboard controls for front-panel: switch(key)

{ // AGC controls // simulator controls case 'q': cout << "QUIT..." << endl; exit(0); case 'm': showMenu(); break; case 'd': genAGCStates(); MON::displayAGC(); break; // update display case 'l': loadMemory(); break; case 'e': examineMemory(); break; case 'f': showSourceCode(); break; case ']': incrCntr(); //genAGCStates(); //displayAGC(EVERY_CYCLE); break; case '[': decrCntr(); //genAGCStates(); //displayAGC(EVERY_CYCLE); break; case 'i': interrupt(); //genAGCStates(); //displayAGC(EVERY_CYCLE); break; case 'z': //SCL::F17 = (SCL::F17 + 1) % 2; genAGCStates(); MON::displayAGC(); break; case 'x': //SCL::F13 = (SCL::F13 + 1) % 2; genAGCStates(); MON::displayAGC(); break; case 'c': MON::SCL_ENAB = (MON::SCL_ENAB + 1) % 2; genAGCStates(); MON::displayAGC(); break; case 'r': MON::RUN = (MON::RUN + 1) % 2; genAGCStates(); if(!MON::FCLK) MON::displayAGC(); break; case 's': MON::STEP = (MON::STEP + 1) % 2; genAGCStates(); if(!MON::FCLK) MON::displayAGC(); break; case 'a': MON::SA = (MON::SA + 1) % 2; genAGCStates(); MON::displayAGC(); break; case 'n': MON::INST = (MON::INST + 1) % 2; genAGCStates();

MON::displayAGC(); break; case 'p': MON::PURST = (MON::PURST + 1) % 2; genAGCStates(); MON::displayAGC(); break; case 'b': toggleBreakpoint(); break; case 'y': toggleWatch(); break; case ';': // Clear ALARM indicators PAR::CLR_PALM(); // Asynchronously clear PARITY FAIL MON::displayAGC(); break; // '0': '1': '2': '3': '4': '5': '6': '7': '8': '9': '+': '-': '.': '/': '*': 'g': 'h': 'j': DSKY: KBD::keypress(KEYIN_0); break; KBD::keypress(KEYIN_1); break; KBD::keypress(KEYIN_2); break; KBD::keypress(KEYIN_3); break; KBD::keypress(KEYIN_4); break; KBD::keypress(KEYIN_5); break; KBD::keypress(KEYIN_6); break; KBD::keypress(KEYIN_7); break; KBD::keypress(KEYIN_8); break; KBD::keypress(KEYIN_9); break; KBD::keypress(KEYIN_PLUS); break; KBD::keypress(KEYIN_MINUS); break; KBD::keypress(KEYIN_CLEAR); break; KBD::keypress(KEYIN_VERB); break; KBD::keypress(KEYIN_NOUN); break; KBD::keypress(KEYIN_KEY_RELEASE); break; KBD::keypress(KEYIN_ERROR_RESET); break; KBD::keypress(KEYIN_ENTER); break;

case case case case case case case case case case case case case case case case case case

case '\0': // must be a function key key = _getch(); switch(key) { case 0x3b: // F1: single clock pulse (when system clock off) singleClock = true; break; case 0x3c: // F2: manual clock (FCLK=0) MON::FCLK = 0; genAGCStates(); MON::displayAGC(); break; case 0x3e: // F4: fast clock (FCLK=1) MON::FCLK = 1; genAGCStates(); MON::displayAGC(); break; default: cout << "function key: " << key << "=" << hex << (int) key << dec << endl; } break; //default: cout << "??" << endl; default: cout << key << "=" << hex << (int) key << dec << endl; } } }

ADR (ADR.h)
/**************************************************************************** * ADR - MEMORY ADDRESS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ADR.h * * VERSIONS: * * DESCRIPTION: * Memory address for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef ADR_H #define ADR_H enum specialRegister { // octal addresses of special registers // Flip-Flop registers A_ADDR =00, Q_ADDR =01, Z_ADDR =02, LP_ADDR =03, IN0_ADDR =04, IN1_ADDR =05, IN2_ADDR =06, IN3_ADDR =07, OUT0_ADDR =010, OUT1_ADDR =011, OUT2_ADDR =012, OUT3_ADDR =013, OUT4_ADDR =014, BANK_ADDR =015, // No bits in these registers RELINT_ADDR =016, INHINT_ADDR =017, // In eraseable memory CYR_ADDR =020, SR_ADDR =021, CYL_ADDR =022, SL_ADDR =023, ZRUPT_ADDR =024, BRUPT_ADDR =025, ARUPT_ADDR =026, QRUPT_ADDR =027, };

class regS : public reg { public: regS() : reg(12, "%04o") { } }; class regBNK : public reg { public: regBNK() : reg(4, "%02o") { } }; class ADR

{ friend class MON; friend class MEM; friend class CLK; friend class CPM; public: static void execWP_WS(); static void execRP_RBK(); static void execWP_WBK(); static static static static static static bool bool bool bool bool bool GTR_17(); GTR_27(); EQU_16(); EQU_17(); EQU_25(); GTR_1777(); // // // // // // for for for for for for MBF, CPM PAR CPM CPM SEQ CPM

static unsigned getEffectiveAddress(); private: static regS register_S; // address register static regBNK register_BNK; // bank register static unsigned bankDecoder(); static unsigned conv_WBK[]; }; #endif

ADR (ADR.cpp)
/**************************************************************************** * ADR - MEMORY ADDRESS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ADR.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "reg.h" #include "ADR.h" #include "SEQ.h" #include "BUS.h" regS ADR::register_S; // address register regBNK ADR::register_BNK; // bank register // transfer bits 14-11 from the bus into the 4-bit bank register unsigned ADR::conv_WBK[] = { BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, B14, B13, B12, B11 };

void ADR::execWP_WS() { register_S.write(BUS::glbl_WRITE_BUS); } void ADR::execRP_RBK() { BUS::glbl_READ_BUS = register_BNK.read() << 10; } void ADR::execWP_WBK() { register_BNK.writeShift(BUS::glbl_WRITE_BUS, ADR::conv_WBK); } bool ADR::GTR_27() { return (register_S.read() > 027); } bool ADR::GTR_17() { // check: address is not a central register return (register_S.read() > 017); } bool ADR::EQU_25() { return (register_S.read() == 025); } bool ADR::EQU_17() { // check: instruction is INHINT (INDEX 017) return (register_S.read() == 017); } bool ADR::EQU_16() { // check: instruction is RELINT (INDEX 016)) return (register_S.read() == 016); } bool ADR::GTR_1777() { // check: address is fixed memory

return (register_S.read() > 01777); } unsigned ADR::bankDecoder() { // Memory is organized into 13 banks of 1K words each. The banks are numbered // 0-12. Bank 0 is erasable memory; banks 1-12 are fixed (rope) memory. The 10 // lower bits in the S register address memory inside a bank. The 2 upper bits // in the S register select the bank. If the 2 upper bits are both 1, the 4-bit // bank register is used to select the bank. // 12 11 Bank // 0 0 0 erasable memory // 0 1 1 fixed-fixed 1 memory // 1 0 2 fixed-fixed 2 memory // 1 1 3-12 fixed-switchable memory (bank register selects bank) unsigned bank = ADR::register_S.readField(12,11); if(bank == 3) { // fixed-switchable if(register_BNK.read() <= 03) // defaults to 6000 - 7777 return 03; else return register_BNK.read(); // 10000 - 31777 } else return bank; // erasable or fixed-fixed } unsigned ADR::getEffectiveAddress() { // Return the 14-bit address selected by lower 10 bits of the S register (1K) // and the bank decoder (which selects the 1K bank) unsigned lowAddress = ADR::register_S.readField(10,1); if(ADR::bankDecoder() == 0) return lowAddress; unsigned highAddress = ADR::bankDecoder() << 10; return highAddress | lowAddress; }

ALU (ALU.h)
/**************************************************************************** * ALU - ARITHMETIC UNIT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ALU.h * * VERSIONS: * * DESCRIPTION: * Arithmetic Unit for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef ALU_H #define ALU_H #include "reg.h" class regB : public reg { public: regB() : reg(16, "%06o") { } }; class regCI : public reg { public: regCI() : reg(1, "%01o") { } }; class regX : public reg { public: regX() : reg(16, "%06o") { } }; class regY : public reg { public: regY() : reg(16, "%06o") { } }; class regU : public reg { public: regU() : reg(16, "%06o") { } virtual unsigned read(); }; class ALU { public: static unsigned glbl_BUS; // // // // // // // // // //

// mixes the RC and RU together for MASK

In the hardware AGC, all read pulses are enabled simultaneously by CLK1. This simulator has to do the pulses one-at-a-time, so they are executed in the following sequence to mimic the hardware: 1) all read pulses involving subsystems other than ALU are executed, These read pulses output to the glbl_READ_BUS. Only 0 or 1 of these pulses should be active at any time (never 2 or more), 2) next, the read pulses for the ALU are executed. The ALU is treated differently because it is the only subsystem where several read

// // // // // // // // // // // // // // // // // 3) finally,

pulses can be active simultaneously. In the original AGC, these pulses 'inclusive OR' their output to the glbl_READ_BUS, so the simulator has be implemented to execute all read pulses other than the ALU reads first, so the ALU will have the bus data it needs in order to do the inclusive OR. In the recreated AGC hardware design, the ALU is also the subsystem that links the glbl_READ_BUS to the glbl_WRITE_BUS. The recreated ALU hardware design checks whether anything is being written to the glbl_READ_BUS by the other subsystems. If not, it outputs zeroes to the glbl_READ_BUS for input to the inclusive OR operation. It then transfers data on the glbl_READ_BUS to the glbl_WRITE_BUS using an inclusive OR with data generated by other ALU read pulses. The AGC sequencer uses this operation to set certain data lines. all write pulses are executed.

static void execRP_ALU_RB(); static void execRP_ALU_RC(); static void execRP_ALU_RU(); static static static static static static static static void void void void void void void void execRP_ALU_OR_RB14(); execRP_ALU_OR_R1(); execRP_ALU_OR_R1C(); execRP_ALU_OR_R2(); execRP_ALU_OR_R22(); execRP_ALU_OR_R24(); execRP_ALU_OR_R2000(); execRP_ALU_OR_RSB();

static void execWP_GENRST(); static void execWP_WB(); static void execWP_CI(); static void execWP_WY(); static void execWP_WX(); static void execWP_WYx();

static static static static static }; #endif

regB register_B; // next instruction regCI register_CI; // ALU carry-in flip flop regX register_X; // ALU X register regY register_Y; // ALU Y register regU register_U; // ALU sum

ALU (ALU.cpp)
/**************************************************************************** * ALU - ARITHMETIC UNIT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ALU.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "ALU.h" #include "SEQ.h" #include "BUS.h" regB ALU::register_B; // next instruction regCI ALU::register_CI; // ALU carry-in flip flop regX ALU::register_X; // ALU X register regY ALU::register_Y; // ALU Y register regU ALU::register_U; // ALU sum unsigned ALU::glbl_BUS = 0;

//************************************************************ void ALU::execRP_ALU_RB() { BUS::glbl_READ_BUS = register_B.read(); } // Performs an inclusive OR or register U and register C; // in the MASK instruction, the RC and RU control pulses // are activated simultaneously. This causes both to be // gated onto the AGC bus which performs the logical OR. void ALU::execRP_ALU_RC() { ALU::glbl_BUS |= register_B.outmask() & (~register_B.read()); BUS::glbl_READ_BUS = ALU::glbl_BUS; } // Performs an inclusive OR or register U and register C; // in the MASK instruction, the RC and RU control pulses // are activated simultaneously. This causes both to be // gated onto the AGC bus which performs the logical OR. void ALU::execRP_ALU_RU() { ALU::glbl_BUS |= register_U.read(); BUS::glbl_READ_BUS = ALU::glbl_BUS; } //************************************************************

//************************************************************ // This is the interface between the read and write busses void ALU::execRP_ALU_OR_RB14() { BUS::glbl_WRITE_BUS |= 0020000 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R1() {

BUS::glbl_WRITE_BUS |= 0000001 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R1C() { BUS::glbl_WRITE_BUS |= 0177776 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R2() { BUS::glbl_WRITE_BUS |= 0000002 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_RSB() { BUS::glbl_WRITE_BUS |= 0100000 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R22() { BUS::glbl_WRITE_BUS |= 0000022 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R24() { BUS::glbl_WRITE_BUS |= 0000024 | BUS::glbl_READ_BUS; } void ALU::execRP_ALU_OR_R2000() { BUS::glbl_WRITE_BUS |= 0002000 | BUS::glbl_READ_BUS; // TC GOPROG instruction } //************************************************************ void ALU::execWP_GENRST() { }

void ALU::execWP_CI() { register_CI.writeField(1,1,1); }

void ALU::execWP_WX() { register_X.write(BUS::glbl_WRITE_BUS); }

void ALU::execWP_WB() { register_B.write(BUS::glbl_WRITE_BUS); }

void ALU::execWP_WYx() { register_Y.write(BUS::glbl_WRITE_BUS); } void ALU::execWP_WY() { if(!SEQ::isAsserted(CI)) register_CI.writeField(1,1,0); register_X.write(0); register_Y.write(BUS::glbl_WRITE_BUS); }

unsigned regU::read() { unsigned carry = (outmask()+1) & (ALU::register_X.read() + ALU::register_Y.read()); // end-around carry if(carry || ALU::register_CI.read()) carry = 1; else carry = 0; return outmask() & (ALU::register_X.read() + ALU::register_Y.read() + carry); }

BUS (BUS.h)
/**************************************************************************** * BUS - READ/WRITE BUS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: BUS.h * * VERSIONS: * * DESCRIPTION: * RW Bus for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef BUS_H #define BUS_H // // // // // // // // BUS LINE DESIGNATIONS Specify the assignment of bus lines to the inputs of a register (for a 'write' operation into a register). Each 'conv_' array specifies the inputs into a single register. The index into the array corresponds to the bit position in the register, where the first parameter (index=0) is bit 16 of the register (msb) and the last parameter (index=15) is register bit 1 (lsb). The value of the parameter identifies the bus line assigned to that register bit. 'BX' means 'don't care'; i.e.: leave that register bit alone.

enum { D0=17, // force bit to zero SGM=15, // sign bit in memory SG=16, // sign (S2; one's compliment) US=15, // uncorrected sign (S1; overflow), except in register G B14=14, B13=13, B12=12, B11=11, B10=10, B9=9, B8=8, B7=7, B6=6, B5=5, B4=4, B3=3, B2=2, B1=1, BX=0 // ignore }; enum ovfState { NO_OVF, POS_OVF, NEG_OVF }; class BUS { public: static unsigned glbl_READ_BUS; // read/write bus for xfer between central regs static unsigned glbl_WRITE_BUS; // read/write bus for xfer between central regs friend class INT; friend class CTR; private: static ovfState testOverflow(unsigned bus); }; #endif

BUS (BUS.cpp)
/**************************************************************************** * BUS - READ/WRITE BUS subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: BUS.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "BUS.h" unsigned BUS::glbl_READ_BUS = 0; unsigned BUS::glbl_WRITE_BUS = 0; ovfState BUS::testOverflow(unsigned bus) { if((bus & 0100000) && !(bus & 0040000)) return NEG_OVF; // negative overflow else if(!(bus & 0100000) && (bus & 0040000)) return POS_OVF; // positive overflow else return NO_OVF; }

CLK (CLK.h)
/**************************************************************************** * CLK - CLOCK subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CLK.h * * VERSIONS: * * DESCRIPTION: * Clock for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef CLK_H #define CLK_H #include "reg.h" // define pointer-to-function type typedef void (*EXECTYPE)();

class CLK { public: static static static static

void void void void

doexecR(int pulse); doexecR_ALU(int pulse); doexecR_ALU_OR(int pulse); doexecW(int pulse);

static void clkAGC(); static reg* registerList[]; }; #endif

CLK (CLK.cpp)
/**************************************************************************** * CLK - CLOCK subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CLK.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "CLK.h" #include "INP.h" #include "OUT.h" #include "MBF.h" #include "ADR.h" #include "SEQ.h" #include "ALU.h" #include "CRG.h" #include "CTR.h" #include "INT.h" #include "PAR.h" #include "TPG.h" #include "SCL.h" #include "MEM.h" // A container for all registers. This is kept so we can iterate through // all registers to execute the control pulses. For simulation purposes // only; this has no counterpart in the hardware AGC. reg* CLK::registerList[] = // registers are in no particular sequence { &INP::register_IN0, &INP::register_IN1, &INP::register_IN2, &INP::register_IN3, &OUT::register_OUT1, &OUT::register_OUT2, &OUT::register_OUT3, &OUT::register_OUT4, &MBF::register_G, &PAR::register_G15, &ADR::register_S, &ADR::register_BNK, &SEQ::register_SQ, &ALU::register_B, &CRG::register_Q, &CRG::register_Z, &CRG::register_LP, &CRG::register_A, &ALU::register_X, &ALU::register_Y, &ALU::register_U, &SEQ::register_STA, &SEQ::register_STB, &SEQ::register_SNI, &SEQ::register_LOOPCTR, &ALU::register_CI, &SEQ::register_BR1, &SEQ::register_BR2, &CTR::register_UpCELL, &CTR::register_DnCELL, &INT::register_RPCELL, &INT::register_INHINT1, &INT::register_INHINT, &PAR::register_P, &PAR::register_P2, &PAR::register_PALM, &TPG::register_SG, &SCL::register_SCL, &SCL::register_F17, &SCL::register_F13, &SCL::register_F10, 0 // zero is end-of-list flag };

void CLK::clkAGC() { // Now that all the inputs are set up, clock the registers so the outputs // can change state in accordance with the inputs. for(int i=0; registerList[i]; i++) { registerList[i]->clk(); } }

void void void void void void void void

execR_NOPULSE() execR_RA0() execR_RA1() execR_RA2() execR_RA3() execR_RA4() execR_RA5() execR_RA6()

{ { { { { { { {

} CRG::execRP_RA0(); CRG::execRP_RA1(); CRG::execRP_RA2(); CRG::execRP_RA3(); INP::execRP_RA4(); INP::execRP_RA5(); INP::execRP_RA6();

} } } } } } }

void void void void void void void void void void void void void void void

execR_RA7() execR_RA11() execR_RA12() execR_RA13() execR_RA14() execR_RA() execR_RBK() execR_RG() execR_RLP() execR_RQ() execR_RRPA() execR_RSCT() execR_RZ() execR_SBWG() execR_WE()

{ { { { { { { { { { { { { { {

INP::execRP_RA7(); OUT::execRP_RA11(); OUT::execRP_RA12(); OUT::execRP_RA13(); OUT::execRP_RA14(); CRG::execRP_RA(); ADR::execRP_RBK(); MBF::execRP_RG(); CRG::execRP_RLP(); CRG::execRP_RQ(); INT::execRP_RRPA(); CTR::execRP_RSCT(); CRG::execRP_RZ(); MEM::execRP_SBWG(); MBF::execRP_WE();

} } } } } } } } } } } } } } PAR::execRP_WE(); } } } } } } } } } } } }

void execR_ALU_RB() void execR_ALU_RC() void execR_ALU_RU() void void void void void void void void execR_ALU_OR_RSB() execR_ALU_OR_R1() execR_ALU_OR_R1C() execR_ALU_OR_R2() execR_ALU_OR_R22() execR_ALU_OR_R24() execR_ALU_OR_R2000() execR_ALU_OR_RB14()

{ ALU::execRP_ALU_RB(); { ALU::execRP_ALU_RC(); { ALU::execRP_ALU_RU(); { { { { { { { { ALU::execRP_ALU_OR_RSB(); ALU::execRP_ALU_OR_R1(); ALU::execRP_ALU_OR_R1C(); ALU::execRP_ALU_OR_R2(); ALU::execRP_ALU_OR_R22(); ALU::execRP_ALU_OR_R24(); ALU::execRP_ALU_OR_R2000(); ALU::execRP_ALU_OR_RB14();

EXECTYPE execR[] = { execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_RA, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_RG, execR_RLP, execR_NOPULSE, execR_RQ, execR_RRPA, execR_NOPULSE, execR_RSCT, execR_NOPULSE, execR_RZ, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE,

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

NO_PULSE, CI, // CLG, // CLCTR, // CTR, // GP, // KRPT, // NISQ, // RA, // RB, // RB14, // RC, // RG, // RLP, // RP2, // RQ, // RRPA, // RSB, // RSCT, // RU, // RZ, // R1, // R1C, // R2, // R22, // R24, // ST1, // ST2, // TMZ, // TOV, // TP, // TRSM, // TSGN, // TSGN2, // WA, // WALP, // WB, // WGx, // WLP, // WOVC, // WOVI, // WOVR, // WP, //

Carry in Clear G Clear loop counter** Loop counter Generate Parity Knock down Rupt priority New instruction to the SQ register Read A Read B Read bit 14 Read C Read G Read LP Read parity 2 Read Q Read RUPT address Read sign bit Read selected counter address Read sum Read Z Read 1 Read 1 complimented Read 2 Read 22 Read 24 Stage 1 Stage 2 Test for minus zero Test for overflow Test parity Test for resume Test sign Test sign 2 Write A Write A and LP Write B Write G (do not reset) Write LP Write overflow counter Write overflow RUPT inhibit Write overflow Write P

execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE,

// // // // // // // //

WPx, WP2, WQ, WS, WX, WY, WYx, WZ, RSC, WSC, WG,

// // // // // // // //

Write Write Write Write Write Write Write Write

P (do not reset) P2 Q S X Y Y (do not reset) Z

execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_RA0, execR_RA1, execR_RA2, execR_RA3, execR_RA4, execR_RA5, execR_RA6, execR_RA7, execR_NOPULSE, execR_RA11, execR_RA12, execR_RA13, execR_RA14, execR_RBK, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_SBWG, execR_NOPULSE, execR_WE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, }; // 99 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

// Read special and central // Write special and central // Write G

SDV1, // Subsequence DV1 is active SMP1, // Subsequence MP1 is active SRSM3, // Subsequence RSM3 is active RA0, RA1, RA2, RA3, RA4, RA5, RA6, RA7, RA10, RA11, RA12, RA13, RA14, RBK, WA0, WA1, WA2, WA3, WA10, WA11, WA12, WA13, WA14, WBK, WGn, W20, W21, W22, W23 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // Read register at address 0 (A) Read register at address 1 (Q) Read register at address 2 (Z) Read register at address 3 (LP) Read register at address 4 Read register at address 5 Read register at address 6 Read register at address 7 Read register at address 10 (octal) Read register at address 11 (octal) Read register at address 12 (octal) Read register at address 13 (octal) Read register at address 14 (octal) Read BNK Write register at address 0 (A) Write register at address 1 (Q) Write register at address 2 (Z) Write register at address 3 (LP) Write register at address 10 (octal) Write register at address 11 (octal) Write register at address 12 (octal) Write register at address 13 (octal) Write register at address 14 (octal) Write BNK Write G (normal gates)** Write into CYR Write into SR Write into CYL Write into SL General Reset** Clear INHINT** Clear INHINT1** Clear state counter A (STA)** Clear state counter B (STB)** Clear SNI** Clear RPCELL** Set INHINT** Read RUPT opcode ** Write G from memory Set the ST1 bit of STB Write E-MEM from G Write PCTR (latch priority counter sequence)** Write SQ Write stage counter B (STB)** Read 2000 **

GENRST,// CLINH, // CLINH1,// CLSTA, // CLSTB, // CLISQ, // CLRP, // INH, // RPT, // SBWG, // SETSTB,// WE, // WPCTR, // WSQ, // WSTB, // R2000, //

void CLK::doexecR(int pulse) { execR[pulse](); }

EXECTYPE execR_ALU[] = { execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, //

NO_PULSE, CI, // Carry in CLG, // Clear G

execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_RB, execR_NOPULSE, execR_ALU_RC, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_RU, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE,

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

CLCTR, CTR, GP, KRPT, NISQ, RA, RB, RB14, RC, RG, RLP, RP2, RQ, RRPA, RSB, RSCT, RU, RZ, R1, R1C, R2, R22, R24, ST1, ST2, TMZ, TOV, TP, TRSM, TSGN, TSGN2, WA, WALP, WB, WGx, WLP, WOVC, WOVI, WOVR, WP, WPx, WP2, WQ, WS, WX, WY, WYx, WZ, RSC, WSC, WG,

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

Clear loop counter** Loop counter Generate Parity Knock down Rupt priority New instruction to the SQ register Read A Read B Read bit 14 Read C Read G Read LP Read parity 2 Read Q Read RUPT address Read sign bit Read selected counter address Read sum Read Z Read 1 Read 1 complimented Read 2 Read 22 Read 24 Stage 1 Stage 2 Test for minus zero Test for overflow Test parity Test for resume Test sign Test sign 2 Write A Write A and LP Write B Write G (do not reset) Write LP Write overflow counter Write overflow RUPT inhibit Write overflow Write P Write P (do not reset) Write P2 Write Q Write S Write X Write Y Write Y (do not reset) Write Z

execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, // // // // // // // // // // // // // // // // // // //

// Read special and central // Write special and central // Write G

SDV1, // Subsequence DV1 is active SMP1, // Subsequence MP1 is active SRSM3, // Subsequence RSM3 is active RA0, RA1, RA2, RA3, RA4, RA5, RA6, RA7, RA10, RA11, RA12, RA13, RA14, RBK, WA0, WA1, WA2, WA3, WA10, // // // // // // // // // // // // // // // // // // // Read register at address 0 (A) Read register at address 1 (Q) Read register at address 2 (Z) Read register at address 3 (LP) Read register at address 4 Read register at address 5 Read register at address 6 Read register at address 7 Read register at address 10 (octal) Read register at address 11 (octal) Read register at address 12 (octal) Read register at address 13 (octal) Read register at address 14 (octal) Read BNK Write register at address 0 (A) Write register at address 1 (Q) Write register at address 2 (Z) Write register at address 3 (LP) Write register at address 10 (octal)

execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, };

// // // // // // // // // // // // // // // // // // // // // // // // // //

WA11, WA12, WA13, WA14, WBK, WGn, W20, W21, W22, W23

// // // // // // // // // //

Write Write Write Write Write Write Write Write Write Write

register at address register at address register at address register at address BNK G (normal gates)** into CYR into SR into CYL into SL

11 12 13 14

(octal) (octal) (octal) (octal)

GENRST,// CLINH, // CLINH1,// CLSTA, // CLSTB, // CLISQ, // CLRP, // INH, // RPT, // SBWG, // SETSTB,// WE, // WPCTR, // WSQ, // WSTB, // R2000, //

General Reset** Clear INHINT** Clear INHINT1** Clear state counter A (STA)** Clear state counter B (STB)** Clear SNI** Clear RPCELL** Set INHINT** Read RUPT opcode ** Write G from memory Set the ST1 bit of STB Write E-MEM from G Write PCTR (latch priority counter sequence)** Write SQ Write stage counter B (STB)** Read 2000 **

void CLK::doexecR_ALU(int pulse) { execR_ALU[pulse](); }

EXECTYPE execR_ALU_OR[] = { execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_OR_RB14, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_OR_RSB, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_OR_R1, execR_ALU_OR_R1C, execR_ALU_OR_R2, execR_ALU_OR_R22, execR_ALU_OR_R24, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE,

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

NO_PULSE, CI, // CLG, // CLCTR, // CTR, // GP, // KRPT, // NISQ, // RA, // RB, // RB14, // RC, // RG, // RLP, // RP2, // RQ, // RRPA, // RSB, // RSCT, // RU, // RZ, // R1, // R1C, // R2, // R22, // R24, // ST1, // ST2, // TMZ, // TOV, // TP, // TRSM, // TSGN, // TSGN2, // WA, // WALP, // WB, // WGx, // WLP, //

Carry in Clear G Clear loop counter** Loop counter Generate Parity Knock down Rupt priority New instruction to the SQ register Read A Read B Read bit 14 Read C Read G Read LP Read parity 2 Read Q Read RUPT address Read sign bit Read selected counter address Read sum Read Z Read 1 Read 1 complimented Read 2 Read 22 Read 24 Stage 1 Stage 2 Test for minus zero Test for overflow Test parity Test for resume Test sign Test sign 2 Write A Write A and LP Write B Write G (do not reset) Write LP

execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_NOPULSE, execR_ALU_OR_R2000, };

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

WOVC, WOVI, WOVR, WP, WPx, WP2, WQ, WS, WX, WY, WYx, WZ, RSC, WSC, WG,

// // // // // // // // // // // //

Write Write Write Write Write Write Write Write Write Write Write Write

overflow counter overflow RUPT inhibit overflow P P (do not reset) P2 Q S X Y Y (do not reset) Z

// Read special and central // Write special and central // Write G

SDV1, // Subsequence DV1 is active SMP1, // Subsequence MP1 is active SRSM3, // Subsequence RSM3 is active RA0, RA1, RA2, RA3, RA4, RA5, RA6, RA7, RA10, RA11, RA12, RA13, RA14, RBK, WA0, WA1, WA2, WA3, WA10, WA11, WA12, WA13, WA14, WBK, WGn, W20, W21, W22, W23 // // // // // // // // // // // // // // // // // // // // // // // // // // // // // Read register at address 0 (A) Read register at address 1 (Q) Read register at address 2 (Z) Read register at address 3 (LP) Read register at address 4 Read register at address 5 Read register at address 6 Read register at address 7 Read register at address 10 (octal) Read register at address 11 (octal) Read register at address 12 (octal) Read register at address 13 (octal) Read register at address 14 (octal) Read BNK Write register at address 0 (A) Write register at address 1 (Q) Write register at address 2 (Z) Write register at address 3 (LP) Write register at address 10 (octal) Write register at address 11 (octal) Write register at address 12 (octal) Write register at address 13 (octal) Write register at address 14 (octal) Write BNK Write G (normal gates)** Write into CYR Write into SR Write into CYL Write into SL General Reset** Clear INHINT** Clear INHINT1** Clear state counter A (STA)** Clear state counter B (STB)** Clear SNI** Clear RPCELL** Set INHINT** Read RUPT opcode ** Write G from memory Set the ST1 bit of STB Write E-MEM from G Write PCTR (latch priority counter sequence)** Write SQ Write stage counter B (STB)** Read 2000 **

GENRST,// CLINH, // CLINH1,// CLSTA, // CLSTB, // CLISQ, // CLRP, // INH, // RPT, // SBWG, // SETSTB,// WE, // WPCTR, // WSQ, // WSTB, // R2000, //

void CLK::doexecR_ALU_OR(int pulse) { execR_ALU_OR[pulse](); }

void void void void void void void void void void void

execW_NOPULSE() execW_CI() execW_CLG() execW_CLINH() execW_CLINH1() execW_CLISQ() execW_CLCTR() execW_CLRP() execW_CLSTA() execW_CLSTB() execW_CTR()

{ { { { { { { { { { { {

} ALU::execWP_CI(); PAR::execWP_CLG(); INT::execWP_CLINH(); INT::execWP_CLINH1(); SEQ::execWP_CLISQ(); SEQ::execWP_CLCTR(); INT::execWP_CLRP(); SEQ::execWP_CLSTA(); SEQ::execWP_CLSTB(); SEQ::execWP_CTR();

} } } } } } } } } }

void execW_GENRST()

SEQ::execWP_GENRST(); MBF::execWP_GENRST(); CRG::execWP_GENRST(); PAR::execWP_GENRST(); ALU::execWP_GENRST(); CTR::execWP_GENRST(); INT::execWP_GENRST(); OUT::execWP_GENRST(); } PAR::execWP_GP(); } INT::execWP_INH(); } INT::execWP_KRPT(); } SEQ::execWP_NISQ(); } INT::execWP_RPT(); } PAR::execWP_RP2(); } MBF::execWP_SBWG(); PAR::execWP_SBWG(); } SEQ::execWP_SETSTB(); } SEQ::execWP_ST1(); } SEQ::execWP_ST2(); } SEQ::execWP_TMZ(); } SEQ::execWP_TOV(); } PAR::execWP_TP(); } SEQ::execWP_TRSM(); } SEQ::execWP_TSGN(); } SEQ::execWP_TSGN2(); } CRG::execWP_WA0(); } CRG::execWP_WA1(); } CRG::execWP_WA2(); } CRG::execWP_WA3(); } OUT::execWP_WA10(); } OUT::execWP_WA11(); } OUT::execWP_WA12(); } OUT::execWP_WA13(); } OUT::execWP_WA14(); } CRG::execWP_WA(); } CRG::execWP_WALP(); } ALU::execWP_WB(); } ADR::execWP_WBK(); } MEM::execWP_WE(); } MBF::execWP_WGn(); } MBF::execWP_WGx(); PAR::execWP_WGx(); } CRG::execWP_WLP(); } CTR::execWP_WOVC(); } INT::execWP_WOVI(); } CTR::execWP_WOVR(); } PAR::execWP_WP(); } PAR::execWP_WPx(); } PAR::execWP_WP2(); } CTR::execWP_WPCTR(); } CRG::execWP_WQ(); } ADR::execWP_WS(); } SEQ::execWP_WSQ(); } SEQ::execWP_WSTB(); } ALU::execWP_WX(); } ALU::execWP_WY(); } ALU::execWP_WYx(); } CRG::execWP_WZ(); } MBF::execWP_W20(); } MBF::execWP_W21(); } MBF::execWP_W22(); } MBF::execWP_W23(); }

void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void

execW_GP() execW_INH() execW_KRPT() execW_NISQ() execW_RPT() execW_RP2() execW_SBWG() execW_SETSTB() execW_ST1() execW_ST2() execW_TMZ() execW_TOV() execW_TP() execW_TRSM() execW_TSGN() execW_TSGN2() execW_WA0() execW_WA1() execW_WA2() execW_WA3() execW_WA10() execW_WA11() execW_WA12() execW_WA13() execW_WA14() execW_WA() execW_WALP() execW_WB() execW_WBK() execW_WE() execW_WGn() execW_WGx() execW_WLP() execW_WOVC() execW_WOVI() execW_WOVR() execW_WP() execW_WPx() execW_WP2() execW_WPCTR() execW_WQ() execW_WS() execW_WSQ() execW_WSTB() execW_WX() execW_WY() execW_WYx() execW_WZ() execW_W20() execW_W21() execW_W22() execW_W23()

{ { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { {

EXECTYPE execW[] = { execW_NOPULSE, execW_CI, execW_CLG, execW_CLCTR, execW_CTR, execW_GP, execW_KRPT, execW_NISQ, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_RP2, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_ST1, execW_ST2, execW_TMZ, execW_TOV, execW_TP, execW_TRSM, execW_TSGN, execW_TSGN2, execW_WA, execW_WALP, execW_WB, execW_WGx, execW_WLP, execW_WOVC, execW_WOVI, execW_WOVR, execW_WP, execW_WPx, execW_WP2, execW_WQ, execW_WS, execW_WX, execW_WY, execW_WYx, execW_WZ,

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

NO_PULSE, CI, // CLG, // CLCTR, // CTR, // GP, // KRPT, // NISQ, // RA, // RB, // RB14, // RC, // RG, // RLP, // RP2, // RQ, // RRPA, // RSB, // RSCT, // RU, // RZ, // R1, // R1C, // R2, // R22, // R24, // ST1, // ST2, // TMZ, // TOV, // TP, // TRSM, // TSGN, // TSGN2, // WA, // WALP, // WB, // WGx, // WLP, // WOVC, // WOVI, // WOVR, // WP, // WPx, // WP2, // WQ, // WS, // WX, // WY, // WYx, // WZ, // RSC, WSC, WG,

Carry in Clear G Clear loop counter** Loop counter Generate Parity Knock down Rupt priority New instruction to the SQ register Read A Read B Read bit 14 Read C Read G Read LP Read parity 2 Read Q Read RUPT address Read sign bit Read selected counter address Read sum Read Z Read 1 Read 1 complimented Read 2 Read 22 Read 24 Stage 1 Stage 2 Test for minus zero Test for overflow Test parity Test for resume Test sign Test sign 2 Write A Write A and LP Write B Write G (do not reset) Write LP Write overflow counter Write overflow RUPT inhibit Write overflow Write P Write P (do not reset) Write P2 Write Q Write S Write X Write Y Write Y (do not reset) Write Z

execW_NOPULSE, // execW_NOPULSE, // execW_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execR_NOPULSE, // execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, execW_NOPULSE, // // // // // // // // // // // // // //

// Read special and central // Write special and central // Write G

SDV1, // Subsequence DV1 is active SMP1, // Subsequence MP1 is active SRSM3, // Subsequence RSM3 is active RA0, RA1, RA2, RA3, RA4, RA5, RA6, RA7, RA10, RA11, RA12, RA13, RA14, RBK, // // // // // // // // // // // // // // Read Read Read Read Read Read Read Read Read Read Read Read Read Read register register register register register register register register register register register register register BNK at at at at at at at at at at at at at address address address address address address address address address address address address address 0 (A) 1 (Q) 2 (Z) 3 (LP) 4 5 6 7 10 (octal) 11 (octal) 12 (octal) 13 (octal) 14 (octal)

execW_WA0, execW_WA1, execW_WA2, execW_WA3, execW_WA10, execW_WA11, execW_WA12, execW_WA13, execW_WA14, execW_WBK, execW_WGn, execW_W20, execW_W21, execW_W22, execW_W23, execW_GENRST, execW_CLINH, execW_CLINH1, execW_CLSTA, execW_CLSTB, execW_CLISQ, execW_CLRP, execW_INH, execW_RPT, execW_SBWG, execW_SETSTB, execW_WE, execW_WPCTR, execW_WSQ, execW_WSTB, execW_NOPULSE, }; // 99

// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //

WA0, WA1, WA2, WA3, WA10, WA11, WA12, WA13, WA14, WBK, WGn, W20, W21, W22, W23

// // // // // // // // // // // // // // //

Write Write Write Write Write Write Write Write Write Write Write Write Write Write Write

register at address register at address register at address register at address register at address register at address register at address register at address register at address BNK G (normal gates)** into CYR into SR into CYL into SL

0 (A) 1 (Q) 2 (Z) 3 (LP) 10 (octal) 11 (octal) 12 (octal) 13 (octal) 14 (octal)

GENRST,// CLINH, // CLINH1,// CLSTA, // CLSTB, // CLISQ, // CLRP, // INH, // RPT, // SBWG, // SETSTB,// WE, // WPCTR, // WSQ, // WSTB, // R2000, //

General Reset** Clear INHINT** Clear INHINT1** Clear state counter A (STA)** Clear state counter B (STB)** Clear SNI** Clear RPCELL** Set INHINT** Read RUPT opcode ** Write G from memory Set the ST1 bit of STB Write E-MEM from G Write PCTR (latch priority counter sequence)** Write SQ Write stage counter B (STB)** Read 2000 **

void CLK::doexecW(int pulse) { execW[pulse](); }

CPM (CPM.h)
/**************************************************************************** * CPM - CONTROL PULSE MATRIX subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CPM.h * * VERSIONS: * * DESCRIPTION: * Control Pulse Matrix for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef CPM_H #define CPM_H #include "TPG.h" #include "SEQ.h"

class CPM { public: static subseq instructionSubsequenceDecoder( int counter_subseq, int SQ_field, int STB_field); static char* subseqString[]; static void controlPulseMatrix(); static void readEPROM(char* fileName, int* eprom); static static static static static static static private: // Clear the list of currently asserted control pulses. static void clearControlPulses(); // Assert the set of control pulses by adding them to the list of currently // active control signals. static void assert(cpType* pulse); // Assert a control pulse by adding it to the list of currently asserted // control pulses. static void assert(cpType pulse); static void get_CPM_A(int CPM_A_address); static void getControlPulses_EPROM(int address); static void checkEPROM(int inval, int lowbit); }; #endif int int int int int int int EPROM1_8 [0x3fff+1]; EPROM9_16 [0x3fff+1]; EPROM17_24[0x3fff+1]; EPROM25_32[0x3fff+1]; EPROM33_40[0x3fff+1]; EPROM41_48[0x3fff+1]; EPROM49_56[0x3fff+1];

CPM (CPM.cpp)
/**************************************************************************** * CPM - CONTROL PULSE MATRIX subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CPM.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "CPM.h" #include "SEQ.h" #include "MON.h" #include "CTR.h" #include "INT.h" #include "ADR.h" #include <stdlib.h> char* CPM::subseqString[] = { "TC0", "CCS0", "CCS1", "NDX0", "NDX1", "RSM3", "XCH0", "CS0", "TS0", "AD0", "MASK0", "MP0", "MP1", "MP3", "DV0", "DV1", "SU0", "RUPT1", "RUPT3", "STD2", "PINC0", "MINC0", "SHINC0", "NO_SEQ" }; subseq CPM::instructionSubsequenceDecoder( int counter_subseq, int SQ_field, int STB_field) { // Combinational logic decodes instruction and the stage count // to get the instruction subsequence. static subseq decode[16][4] = { { TC0, RUPT1, STD2, RUPT3 }, // 00 { CCS0, CCS1, NO_SEQ, NO_SEQ }, // 01 { NDX0, NDX1, NO_SEQ, RSM3 }, // 02 { XCH0, NO_SEQ, STD2, NO_SEQ }, // 03 { { { { { { { { { { { NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, MP0, DV0, SU0, CS0, TS0, AD0, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, MP1, DV1, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, STD2, STD2, STD2, STD2, STD2, NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ }, }, }, }, }, // // // // // 04 05 06 07 10

MP3 }, // 11 NO_SEQ }, // 12 NO_SEQ }, // 13 NO_SEQ }, // 14 NO_SEQ }, // 15 NO_SEQ }, // 16

{ };

MASK0,

NO_SEQ,

STD2,

NO_SEQ }

// 17

if(counter_subseq == PINCSEL) return PINC0; else if(counter_subseq == MINCSEL) return MINC0; else return decode[SQ_field][STB_field]; } void CPM::clearControlPulses() { for(unsigned i=0; i<MAXPULSES; i++) SEQ::glbl_cp[i] = NO_PULSE; } void CPM::assert(cpType* pulse) { int j=0; for(unsigned i=0; i<MAXPULSES && j<MAX_IPULSES && pulse[j] != NO_PULSE; i++) { if(SEQ::glbl_cp[i] == NO_PULSE) { SEQ::glbl_cp[i] = pulse[j]; j++; } } } void CPM::assert(cpType pulse) { for(unsigned i=0; i<MAXPULSES; i++) { if(SEQ::glbl_cp[i] == NO_PULSE) { SEQ::glbl_cp[i] = pulse; break; } } } int int int int int int int CPM::EPROM1_8 []; CPM::EPROM9_16 []; CPM::EPROM17_24[]; CPM::EPROM25_32[]; CPM::EPROM33_40[]; CPM::EPROM41_48[]; CPM::EPROM49_56[];

void CPM::readEPROM(char* fileName, int* eprom) { cout << "Reading EPROM: " << fileName << endl; // Open the EPROM file. FILE* ifp = fopen(fileName, "r"); if(!ifp) { perror("fopen failed for source file"); exit(-1); } const int addressBytes = 3; // 24-bit address range const int sumCheckBytes = 1; char buf[4096]; while(fgets(buf,4096,ifp)) { // process a record if(buf[0] != 'S') { cout << "Error reading start of EPROM record for: " << fileName << endl; exit(-1);

} char tmp[256]; strncpy(tmp, &buf[2], 2); tmp[2] = '\0'; int totalByteCount = strtol(tmp, 0, 16); int mySumCheck = totalByteCount & 0xff; strncpy(tmp, &buf[4], 6); tmp[addressBytes*2] = '\0'; int address = strtol(tmp, 0, 16); mySumCheck = (mySumCheck + ((address & 0xff0000) >> 16)) % 256; mySumCheck = (mySumCheck + ((address & 0x00ff00) >> 8)) % 256; mySumCheck = (mySumCheck + ((address & 0x0000ff) )) % 256; //cout << hex << totalByteCount << ", " << address << dec << endl; int dataBytes = totalByteCount - addressBytes - sumCheckBytes; int i = (addressBytes+2)*2; // index to 1st databyte char. for(int j=0; j<dataBytes; j++) { // get a data byte strncpy(tmp, &buf[i], 2); tmp[2] = '\0'; int data = strtol(tmp, 0, 16); //cout << hex << data << dec << endl; mySumCheck = (mySumCheck + data) % 256; // The H/W AGC needs negative logic in the EPROMS (0=asserted) // but this simulator needs positive logic, so we bit flip the word. //eprom[address] = data; eprom[address] = ((~data) & 0xff); address++; i+=2; // bump to next databyte char } strncpy(tmp, &buf[i], 2); tmp[2] = '\0'; int sumCheck = strtol(tmp, 0, 16); if(sumCheck != ((~mySumCheck) & 0xff)) { cout << "sumCheck failed; file: " << fileName << ", address: " << hex << address << ", sumCheck: " << sumCheck << ", mySumCheck: " << mySumCheck << dec << endl; exit(-1); } } fclose(ifp); } void CPM::checkEPROM(int inval, int lowbit) { for(int mask=0x1; inval && mask !=0x100; mask=mask<<1) { if(inval & mask) assert((cpType) lowbit); lowbit++; } } // perform the CPM-A EPROM function using the EPROM files void CPM::getControlPulses_EPROM(int address) { checkEPROM(EPROM1_8 [address], 1); checkEPROM(EPROM9_16 [address], 9); checkEPROM(EPROM17_24[address], 17); checkEPROM(EPROM25_32[address], 25); checkEPROM(EPROM33_40[address], 33); checkEPROM(EPROM41_48[address], 41); checkEPROM(EPROM49_56[address], 49); } void CPM::get_CPM_A(int address)

{ // Use the EPROM tables to get the CPM-A control pulses documented // in R-393. getControlPulses_EPROM(address); // Now add some additional control pulses implied, but not documented // in R-393. if(SEQ::register_LOOPCTR.read() == 6) { assert(ST2); // STA <- 2 assert(CLCTR); // CTR <- 0 } //***************************************************************** // Now that the EPROM tables are used for CPM-A, this function is only // used to display the instruction subsequence in MON. SEQ::glbl_subseq = CPM::instructionSubsequenceDecoder( CTR::getSubseq(), SEQ::register_SQ.read(), SEQ::register_STB.read()); //***************************************************************** // These were in CPM-C, where the rest of the control signal assertions // related to their use still are, but were moved here because WB and RB // are part of the R-393 sequence tables. Check CPM-C to see how these // assertions fit in (the former use is commented out there). switch(TPG::register_SG.read()) { case PWRON: assert(WB); // break; TC GOPROG copied to B (see CPM-C for related assertions)

case TP12: if(SEQ::register_SNI.read() == 1) { if(!INT::IRQ()) { // Normal instruction assert(RB); // SQ <- B (see CPM-C for related assertions) } } break; default: ; } }

void CPM::controlPulseMatrix() { // Combination logic decodes time pulse, subsequence, branch register, and // "select next instruction" latch to get control pulses associated with // those states. // Get rid of any old control pulses. clearControlPulses(); //******************************************************************************* // SUBSYSTEM A int SB2_field = 0; int SB1_field = 0; switch(CTR::getSubseq()) { case PINCSEL: SB2_field = 0; SB1_field = 1; break; case MINCSEL: SB2_field = 1; SB1_field = 0; break; default:

SB2_field = 0; SB1_field = 0; }; int CPM_A_address = 0; CPM_A_address = (SB2_field << 13) | (SB1_field << 12) | (SEQ::register_SQ.read() (SEQ::register_STB.read() (TPG::register_SG.read() (SEQ::register_BR1.read() SEQ::register_BR2.read();

<< << << <<

8) 6) 2) 1)

| | | |

// Construct address into CPM-A control pulse ROM: // Address bits (bit 1 is LSB) // 1: register BR2 // 2: register BR1 // 3-6: register SG (4) // 7,8: register STB (2) // 9-12: register SQ (4) // 13: STB_01 (from CTR: selects PINC, MINC, or none) // 14: STB_02 (from CTR: selects PINC, MINC, or none) get_CPM_A(CPM_A_address); //*******************************************************************************

//******************************************************************************* // SUBSYSTEM B // NOTE: WG, RSC, WSC are generated by SUBSYSTEM A. Those 3 signals are only used // by SUBSYSTEM B; not anywhere else. // CONSIDER MOVING TO ADR **********************8 if(SEQ::isAsserted(WG)) { switch(ADR::register_S.read()) { case 020: assert(W20); break; case 021: assert(W21); break; case 022: assert(W22); break; case 023: assert(W23); break; default: if(ADR::GTR_17()) assert(WGn); // not a central register } } if(SEQ::isAsserted(RSC)) { switch(ADR::register_S.read()) { case 00: assert(RA0); break; case 01: assert(RA1); break; case 02: assert(RA2); break; case 03: assert(RA3); break; case 04: assert(RA4); break; case 05: assert(RA5); break; case 06: assert(RA6); break; case 07: assert(RA7); break; case 010: assert(RA10); break; case 011: assert(RA11); break; case 012: assert(RA12); break; case 013: assert(RA13); break; case 014: assert(RA14); break; case 015: assert(RBK); break; default: break; // 016, 017 } } if(SEQ::isAsserted(WSC)) switch(ADR::register_S.read()) { case 00: assert(WA0); break;

case 01: assert(WA1); break; case 02: assert(WA2); break; case 03: assert(WA3); break; case 010: assert(WA10); break; case 011: assert(WA11); break; case 012: assert(WA12); break; case 013: assert(WA13); break; case 014: assert(WA14); break; case 015: assert(WBK); break; default: break; // 016, 017 } //*******************************************************************************

//******************************************************************************* // SUBSYSTEM C switch(TPG::register_SG.read()) { case STBY: assert(GENRST); // inhibit all alarms // init "SQ" complex // clear branch registers // stage registers are not cleared; should they be? // zeroes are already gated onto bus when no read pulses are asserted. // to zero synchronous-clocked registers, assert write pulses here. // Level-triggered registers are zeroed by GENRST anded with CLK2. break; case PWRON: assert(R2000); //assert(WB); // break; case TP1: // Moved this from TP12 to TP1 because CLISQ was getting cleared in the // hardware AGC before TPG was clocked; therefore TPG was not seeing the // SNI indication. assert(CLISQ); // SNI <- 0 case TP5: // EMEM must be available in G register by TP6 if( ADR::GTR_17() && // not a central register !ADR::GTR_1777() && // not fixed memory !SEQ::isAsserted(SDV1) && // not a loop counter subseq !SEQ::isAsserted(SMP1)) { assert(SBWG); } if( ADR::EQU_17() ) assert (INH); // INHINT (INDEX 017) if( ADR::EQU_16() ) assert (CLINH); // RELINT (INDEX 016) break; case TP6: // FMEM must be available in G register by TP7 if( ADR::GTR_1777() memory !SEQ::isAsserted(SDV1) !SEQ::isAsserted(SMP1)) { assert(SBWG); } break; case TP11: // G register written to memory beginning at TP11; Memory updates are in // G by TP10 for all normal and extracode instructions, but the PINC, MINC, && // not a loop counter subseq

TC GOPROG copied to B (implemented in CPM-A)

&&

// not eraseable

// and SHINC sequences write to G in TP10 because they need to update the // parity bit. if( ADR::GTR_17() && // not a central register !ADR::GTR_1777() && // not fixed memory !SEQ::isAsserted(SDV1) && // not a loop counter subseq !SEQ::isAsserted(SMP1)) { assert(WE); } // Additional interrupts are inhibited during servicing of an interrupt; // Remove the inhibition when RESUME is executed (INDEX 025) if(SEQ::isAsserted(SRSM3)) assert(CLRP); break; case TP12: // DISABLE INPUT CHANGE TO PRIORITY COUNTER (reenable after TP1) // Check the priority counters; service any waiting inputs on the next // memory cycle. assert(WPCTR); if(SEQ::register_SNI.read() == 1) // if SNI is set, get next instruction { if(INT::IRQ()) // if interrupt requested (see CPM-A for similar assertion) { // Interrupt: SQ <- 0 (the default RW bus state) assert(RPT); // latch interrupt vector assert(SETSTB); // STB <- 1 } else { // Normal instruction //assert(RB); // SQ <- B (implemented in CPM-A) assert(CLSTB); // STB <- 0 } assert(WSQ); assert(CLSTA); // STA <- 0 // Remove inhibition of interrupts (if they were) AFTER the next instruction assert(CLINH1); // INHINT1 <- 0 } else if(CTR::getSubseq() == NOPSEL) // if previous sequence was not a counter { // get next sequence for same instruction. assert(WSTB); // STB <- STA assert(CLSTA); // STA <- 0 } //assert(CLISQ); break; default: ; } //******************************************************************************* } // SNI <- 0 (moved to TP1)

CRG (CRG.h)
/**************************************************************************** * CRG - ADDRESSABLE CENTRAL REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CRG.h * * VERSIONS: * * DESCRIPTION: * Addressable Central Registers for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef CRG_H #define CRG_H #include "reg.h" class regQ : public reg { public: regQ() : reg(16, "%06o") { } }; class regZ : public reg { public: regZ() : reg(16, "%06o") { } }; class regLP : public reg { public: regLP() : reg(16, "%06o") { } }; class regA : public reg { public: regA() : reg(16, "%06o") { } }; class CRG { public: static void execWP_GENRST(); static static static static static static static static static static static static static static static void void void void void void void void void void void void void void void execRP_RQ(); execRP_RA1(); execWP_WQ(); execWP_WA1(); execRP_RZ(); execRP_RA2(); execWP_WZ(); execWP_WA2(); execRP_RLP(); execRP_RA3(); execRP_RA(); execRP_RA0(); execWP_WA(); execWP_WA0(); execWP_WALP();

static void execWP_WLP(); static void execWP_WA3(); static static static static regQ register_Q; // return address regZ register_Z; // program counter regLP register_LP; // lower accumulator regA register_A; // accumulator

static unsigned conv_WALP_LP[]; static unsigned conv_WALP_A[]; static unsigned conv_WLP[]; }; #endif

CRG (CRG.cpp)
/**************************************************************************** * CRG - ADDRESSABLE CENTRAL REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: CRG.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "CRG.h" #include "SEQ.h" #include "BUS.h" regQ CRG::register_Q; // return address regZ CRG::register_Z; // program counter regLP CRG::register_LP; // lower accumulator regA CRG::register_A; // accumulator // // // // // // // // BUS LINE ASSIGNMENTS Specify the assignment of bus lines to the inputs of a register (for a 'write' operation into a register). Each 'conv_' array specifies the inputs into a single register. The index into the array corresponds to the bit position in the register, where the first parameter (index=0) is bit 16 of the register (msb) and the last parameter (index=15) is register bit 1 (lsb). The value of the parameter identifies the bus line assigned to that register bit. 'BX' means 'don't care'; i.e.: leave that register bit alone.

unsigned CRG::conv_WALP_LP[] = { BX, BX, B1, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX, BX }; unsigned CRG::conv_WALP_A[] = { SG, SG, US, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 }; unsigned CRG::conv_WLP[] = { B1, B1, D0, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 };

void CRG::execWP_GENRST() { register_Q.write(0); register_Z.write(0); register_LP.write(0); register_A.write(0); }

void CRG::execRP_RQ() { BUS::glbl_READ_BUS = register_Q.read(); } void CRG::execRP_RA1() { BUS::glbl_READ_BUS = register_Q.read(); }

void CRG::execWP_WQ() { register_Q.write(BUS::glbl_WRITE_BUS); } void CRG::execWP_WA1() { register_Q.write(BUS::glbl_WRITE_BUS);

void CRG::execRP_RZ() { BUS::glbl_READ_BUS = register_Z.read(); } void CRG::execRP_RA2() { BUS::glbl_READ_BUS = register_Z.read(); }

void CRG::execWP_WZ() { register_Z.write(BUS::glbl_WRITE_BUS); } void CRG::execWP_WA2() { register_Z.write(BUS::glbl_WRITE_BUS); } void CRG::execRP_RLP() { BUS::glbl_READ_BUS = register_LP.read(); } void CRG::execRP_RA3() { BUS::glbl_READ_BUS = register_LP.read(); } void CRG::execWP_WALP() { register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WALP_LP); register_A.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WALP_A); } void CRG::execWP_WLP() { register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WLP); } void CRG::execWP_WA3() { register_LP.writeShift(BUS::glbl_WRITE_BUS, CRG::conv_WLP); }

void CRG::execRP_RA() { BUS::glbl_READ_BUS = register_A.read(); } void CRG::execRP_RA0() { BUS::glbl_READ_BUS = register_A.read(); }

void CRG::execWP_WA() { register_A.write(BUS::glbl_WRITE_BUS); } void CRG::execWP_WA0() { register_A.write(BUS::glbl_WRITE_BUS);

CTR (CTR.h)
/**************************************************************************** * CTR - INVOLUNTARY PRIORITY COUNTER subsystem * * AUTHOR: John Pultorak * DATE: 10/25/02 * FILE: CTR.h * * VERSIONS: * * DESCRIPTION: * Involuntary Counters for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef CTR_H #define CTR_H #include "reg.h" enum ctrNumber { // indexes for priority cells OVCTR =0, TIME2 TIME1 TIME3 TIME4 }; enum ctrAddr { // octal addresses of counters // Note: In Block 1, TIME1 preceeds TIME2. In Block II, // this is reversed: TIME2 preceeds TIME1. This reversal // was done so that the most significant time word occurs // at the lower address in the 2 word AGC clock. Therefore, // a common AGC software routine can be used to read the // time. OVCTR_ADDR =0034, TIME2_ADDR TIME1_ADDR TIME3_ADDR TIME4_ADDR SPARE1_ADDR SPARE2_ADDR SPARE3_ADDR }; enum pCntrType { NOPSEL PINCSEL MINCSEL }; =0, =1, =2 // NO COUNTER // PINC // MINC =0035, // Block II puts TIME2 first =0036, =0037, =0040, =0041, =0042, =0043 =1, =2, =3, =4, // Block II puts TIME2 first

class regUpCELL : public reg { public: // Bit synchronize the counter inputs. regUpCELL() : reg(8, "%03o") { } }; class regDnCELL : public reg { public:

// Bit synchronize the counter inputs. regDnCELL() : reg(8, "%03o") { } }; class CTR { public: static static static static static

void void void void void

execWP_GENRST(); execWP_WPCTR(); execRP_RSCT(); execWP_WOVR(); execWP_WOVC();

static unsigned getSubseq(); static unsigned pcUp[]; static unsigned pcDn[]; static regUpCELL register_UpCELL; // latches the selected priority counter cell (0-7) static regDnCELL register_DnCELL; // latches the selected priority counter cell (0-7) private: static void resetAllpc(); }; #endif

CTR (CTR.cpp)
/**************************************************************************** * CTR - INVOLUNTARY PRIORITY COUNTER subsystem * * AUTHOR: John Pultorak * DATE: 10/25/02 * FILE: CTR.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "CTR.h" #include "INT.h" #include "BUS.h" #include "SEQ.h" regUpCELL CTR::register_UpCELL; // latches the selected priority counter cell (0-7 (decimal)) regDnCELL CTR::register_DnCELL; // latches the selected priority counter cell (0-7 (decimal)) unsigned CTR::pcUp[8]; unsigned CTR::pcDn[8];

// PRIORITY COUNTERS // // // // // **************************************************** The interrupt priorities are stored in RPCELL as 1-5, but the priority counter priorities are stored as 0-7; this inconsistency should be fixed, probably. Also, the method of address determination for the priority counters needs work

void CTR::resetAllpc() { for(int i=0; i<8; i++) { pcUp[i]=0; pcDn[i]=0; } } // priority encoder; outputs 0-7; 0=highest priority (OVCTR), 1=TIME2, 2=TIME1, etc static bool newPriority = true; // a simulator performance optimization; not in the hardware AGC unsigned getPriority() { // simulator optimization; don't recompute priority if the priority inputs haven't changed static unsigned priority = 7; // default (lowest priority) if(!newPriority) return priority; priority = 7; // default (lowest priority) for(int i=0; i<8; i++) { if(CTR::register_UpCELL.readField(i+1,i+1) | CTR::register_DnCELL.readField(i+1,i+1)) { priority = i; break; } } newPriority = false; return priority; }

unsigned CTR::getSubseq() { unsigned pc = getPriority(); unsigned upCell = CTR::register_UpCELL.readField(pc+1,pc+1); unsigned dnCell = CTR::register_DnCELL.readField(pc+1,pc+1);

if(upCell == 1 return else if(upCell return else return }

&& dnCell == 0) PINCSEL; == 0 && dnCell == 1) MINCSEL; NOPSEL;

void CTR::execWP_GENRST() { register_UpCELL.write(0); register_DnCELL.write(0); resetAllpc(); }

void CTR::execWP_WPCTR() { // transfer cell data into up and down synch registers for(int i=0; i<8; i++) { register_UpCELL.writeField(i+1,i+1,pcUp[i]); register_DnCELL.writeField(i+1,i+1,pcDn[i]); } newPriority=true; // a simulator performance optimization; not in hardware AGC } // Selected counter address is requested at TP1. // Counter address is latched at TP12 void CTR::execRP_RSCT() { BUS::glbl_READ_BUS = 034 + getPriority(); } void CTR::execWP_WOVR() { unsigned pc = getPriority(); if(register_UpCELL.readField(pc+1,pc+1)) { pcUp[pc]=0; } if(register_DnCELL.readField(pc+1,pc+1)) { pcDn[pc]=0; } // generate various actions in response to counter overflows: switch(BUS::testOverflow(BUS::glbl_WRITE_BUS)) { case POS_OVF: // positive overflow switch(getPriority()) // get the counter { case TIME1: CTR::pcUp[TIME2]=1; break; // overflow from TIME1 increments TIME2 case TIME3: INT::rupt[T3RUPT]=1; break; // overflow from TIME3 triggers T3RUPT case TIME4: INT::rupt[DSRUPT]=1; break; // overflow from TIME4 triggers DSRUPT } break; case NEG_OVF: break; // no actions for negative counter overflow } } void CTR::execWP_WOVC() {

switch(BUS::testOverflow(BUS::glbl_WRITE_BUS)) { case POS_OVF: CTR::pcUp[OVCTR]=1; break; // incr OVCTR (034) case NEG_OVF: CTR::pcDn[OVCTR]=1; break; // decr OVCTR (034) } } // // // // register_PCELL: Overflow from the selected counter appears on the bus when WOVR or WOVC is asserted; it could be used to trigger an interrupt or routed to increment another counter

DSP (DSP.h)
/**************************************************************************** * DSP - DSKY DISPLAY subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: DSP.h * * VERSIONS: * * DESCRIPTION: * DSKY Display for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef DSP_H #define DSP_H class DSP { public: // DSKY display // major mode display static char MD1; static char MD2; // verb display static char VD1; static char VD2; // noun display static char ND1; static char ND2; static static static static static static static static static static static static static static static static static static // R1 char R1S; char R1D1; char R1D2; char R1D3; char R1D4; char R1D5; // R2 char R2S; char R2D1; char R2D2; char R2D3; char R2D4; char R2D5; // R3 char R3S; char R3D1; char R3D2; char R3D3; char R3D4; char R3D5; // These flags control the sign; if both bits are 0 or 1, there is no sign. // Otherwise, the sign is set by the selected bit. unsigned R1SP; unsigned R1SM; unsigned R2SP; unsigned R2SM; unsigned R3SP; unsigned R3SM;

static static static static static static

// verb/noun flash static unsigned flash; static void clearOut0(); static char signConv(unsigned p, unsigned m); static char outConv(unsigned in); static void decodeRelayWord(unsigned in); }; #endif

DSP (DSP.cpp)
/**************************************************************************** * DSP - DSKY DISPLAY subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: DSP.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "DSP.h" #include <string.h> #include <iostream.h> #include <stdio.h> bool dskyChanged = false; // true when DSKY display changes // major mode display char DSP::MD1=0; char DSP::MD2=0; // verb display char DSP::VD1=0; char DSP::VD2=0; // noun display char DSP::ND1=0; char DSP::ND2=0; char char char char char char char char char char char char char char char char char char // R1 DSP::R1S=0; DSP::R1D1=0; DSP::R1D2=0; DSP::R1D3=0; DSP::R1D4=0; DSP::R1D5=0; // R2 DSP::R2S=0; DSP::R2D1=0; DSP::R2D2=0; DSP::R2D3=0; DSP::R2D4=0; DSP::R2D5=0; // R3 DSP::R3S=0; DSP::R3D1=0; DSP::R3D2=0; DSP::R3D3=0; DSP::R3D4=0; DSP::R3D5=0;

// These flags control the sign; if both bits are 0 or 1, there is no sign. // Otherwise, the sign is set by the selected bit. unsigned DSP::R1SP=0; unsigned DSP::R1SM=0; unsigned DSP::R2SP=0; unsigned DSP::R2SM=0; unsigned DSP::R3SP=0; unsigned DSP::R3SM=0; // flag controls 1 Hz flash of verb and noun display unsigned DSP::flash = 0; // 0=flash off, 1=flash on void DSP::clearOut0() { MD1 = MD2 = ' '; VD1 = VD2 = ' ';

// major mode display // verb display

ND1 R1S R2S R3S

= = = =

ND2 = ' '; // noun display R1D1 = R1D2 = R1D3 = R1D4 = R1D5 = ' '; R2D1 = R2D2 = R2D3 = R2D4 = R2D5 = ' '; R3D1 = R3D2 = R3D3 = R3D4 = R3D5 = ' ';

// R1 // R2 // R3

R1SP = R1SM = 0; R2SP = R2SM = 0; R3SP = R3SM = 0; } char DSP::signConv(unsigned p, unsigned m) { if(p && !m) return '+'; else if(m && !p) return '-'; else return ' '; } char DSP::outConv(unsigned in) { switch(in) { case 000: return ' '; case 025: return '0'; case 003: return '1'; case 031: return '2'; case 033: return '3'; case 017: return '4'; case 036: return '5'; case 034: return '6'; case 023: return '7'; case 035: return '8'; case 037: return '9'; } return ' '; // error } void DSP::decodeRelayWord(unsigned in) { unsigned charSelect = (in & 074000) >> 11; // get bits 15-12 unsigned b11 = (in & 02000) >> 10; // get bit 11 unsigned bHigh = (in & 01740) >> 5; // get bits 10-6 unsigned bLow = in & 037; //****************************** #ifdef NOTDEF char buf[80]; sprintf(buf, "bits15-12: %02o, Bit11: %01o, bits10-6: %02o, bits5-1: %02o", charSelect, b11, bHigh, bLow); cout << buf << endl; #endif dskyChanged = true; //****************************** switch(charSelect) { case 013: MD1 = outConv(bHigh); MD2 = outConv(bLow); break; case 012: VD1 = outConv(bHigh); VD2 = outConv(bLow); flash = b11; break; case 011: ND1 = outConv(bHigh); ND2 = outConv(bLow); break; case 010: R1D1 = outConv(bLow); break; // UPACT not implemented case 007: R1SP = b11; R1S = signConv(R1SP, R1SM); R1D2 = outConv(bHigh); R1D3 = outConv(bLow); break; R1SM = b11; R1S = signConv(R1SP, R1SM); R1D4 = outConv(bHigh); R1D5 = outConv(bLow); break; R2SP = b11; R2S = signConv(R2SP, R2SM); R2D1 = outConv(bHigh); R2D2 = outConv(bLow); break;

case 006:

case 005:

case 004:

R2SM = b11; R2S = signConv(R2SP, R2SM); R2D3 = outConv(bHigh); R2D4 = outConv(bLow); break; R2D5 = outConv(bHigh); R3D1 = outConv(bLow); break; R3SP = b11; R3S = signConv(R3SP, R3SM); R3D2 = outConv(bHigh); R3D3 = outConv(bLow); break; R3SM = b11; R3S = signConv(R3SP, R3SM); R3D4 = outConv(bHigh); R3D5 = outConv(bLow); break;

case 003: case 002:

case 001: } }

INP (INP.h)
/**************************************************************************** * INP - INPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INP.h * * VERSIONS: * * DESCRIPTION: * Input Registers for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef INP_H #define INP_H #include "reg.h" class regIn0 : public reg { public: regIn0() : reg(16, "%06o") { } }; class regIn1 : public reg { public: regIn1() : reg(16, "%06o") { } }; class regIn2 : public reg { public: regIn2() : reg(16, "%06o") { } }; class regIn3 : public reg { public: regIn3() : reg(16, "%06o") { } }; class INP { public: static static static static static static static static }; #endif

void execRP_RA4(); void execRP_RA5(); void execRP_RA6(); void execRP_RA7(); regIn0 register_IN0; regIn1 register_IN1; regIn2 register_IN2; regIn3 register_IN3;

// // // //

input input input input

register register register register

0 1 2 3

INP (INP.cpp)
/**************************************************************************** * INP - INPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INP.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "INP.h" #include "SEQ.h" #include "KBD.h" #include "MON.h" #include "BUS.h" regIn0 regIn1 regIn2 regIn3 INP::register_IN0; INP::register_IN1; INP::register_IN2; INP::register_IN3; // // // // input input input input register register register register 0 1 2 3

void INP::execRP_RA4() { // Sample the state of the inputs at the moment the // read pulse is asserted. In the H/W implementation, // register 0 is a buffer, not a latch. register_IN0.writeField(5,1,KBD::kbd); register_IN0.writeField(6,6,0); // actually should be keypressed strobe register_IN0.writeField(14,14,MON::SA); register_IN0.clk(); BUS::glbl_READ_BUS = register_IN0.read(); }

void INP::execRP_RA5() { BUS::glbl_READ_BUS = register_IN1.read(); } void INP::execRP_RA6() { BUS::glbl_READ_BUS = register_IN2.read(); } void INP::execRP_RA7() { BUS::glbl_READ_BUS = register_IN3.read(); }

INT (INT.h)
/**************************************************************************** * INT - PRIORITY INTERRUPT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INT.h * * VERSIONS: * * DESCRIPTION: * Priority Interrupts for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef INT_H #define INT_H #include "reg.h" enum ruptAddress { // Addresses for service routines of vectored interrupts T3RUPT_ADDR =02004, // option 1: overflow of TIME 3 ERRUPT_ADDR =02010, // option 2: error signal DSRUPT_ADDR =02014, // option 3: telemetry end pulse or TIME 4 overflow KEYRUPT_ADDR =02020, // option 4: activity from MARK, keyboard, or tape reader }; enum ruptNumber { // Option number (selects rupt priority cell) // NOTE: the priority cells (rupt[]) are indexed 0-4, but stored in the // RPCELL register as 1-5; (0 in RPCELL means no interrupt) T3RUPT =0, // option 1: overflow of TIME 3 ERRUPT =1, // option 2: error signal DSRUPT =2, // option 3: telemetry end pulse or TIME 4 overflow KEYRUPT =3, // option 4: activity from MARK, keyboard, or tape reader }; class regRPCELL : public reg { public: regRPCELL() : reg(5, "%02o") { } }; // also inhibits additional interrupts while an interrupt is being processed class regINHINT1 : public reg { public: regINHINT1() : reg(1, "%01o") { } }; class regINHINT : public reg { public: regINHINT() : reg(1, "%01o") { } }; class INT { public: friend class CLK; friend class MON; static void execRP_RRPA();

static static static static static static static static

void void void void void void void void

execWP_GENRST(); execWP_RPT(); execWP_KRPT(); execWP_CLRP(); execWP_WOVI(); execWP_CLINH1(); execWP_INH(); execWP_CLINH();

static bool IRQ(); // returns true if an interrupt is requested static unsigned rupt[]; private: static void resetAllRupt(); static unsigned getPriorityRupt(); static regRPCELL register_RPCELL; // latches the selected priority interrupt vector (1-5) static regINHINT1 register_INHINT1; // inhibits interrupts for 1 instruction (on WOVI) static regINHINT register_INHINT; // inhibits interrupts on INHINT, reenables on RELINT }; #endif

INT (INT.cpp)
/**************************************************************************** * INT - PRIORITY INTERRUPT subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: INT.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "INT.h" #include "SEQ.h" #include "BUS.h" regRPCELL INT::register_RPCELL; // latches the selected priority interrupt vector (1-5) regINHINT1 INT::register_INHINT1; // inhibits interrupts for 1 instruction (on WOVI) regINHINT INT::register_INHINT; // inhibits interrupts on INHINT, reenables on RELINT // NOTE: the priority cells (rupt[]) are indexed 0-4, but stored in the // RPCELL register as 1-5; (0 in RPCELL means no interrupt) unsigned INT::rupt[5];

bool INT::IRQ() { if( INT::getPriorityRupt() // if interrupt requested && INT::register_RPCELL.read() == 0 // and interrupt not currently being serviced && INT::register_INHINT1.read() == 0 // and interrupt not inhibited for 1 instruction && INT::register_INHINT.read() == 0) // and interrupts enabled (RELINT) { return true; } return false; } void INT::resetAllRupt() { for(int i=0; i<5; i++) { rupt[i]=0; } } // interrupt vector; outputs 1-5 (decimal) == vector; 0 == no interrupt unsigned INT::getPriorityRupt() { for(int i=0; i<5; i++) { if(rupt[i]) return i+1; } return 0; } void INT::execRP_RRPA() { BUS::glbl_READ_BUS = 02000 + (register_RPCELL.read() << 2); }

// latches the selected priority interrupt vector (1-5) // also inhibits additional interrupts while an interrupt is being processed void INT::execWP_GENRST() { register_RPCELL.write(0); register_INHINT.write(1); resetAllRupt(); } void INT::execWP_RPT() {

register_RPCELL.write(INT::getPriorityRupt()); } void INT::execWP_KRPT() { INT::rupt[register_RPCELL.read()-1] = 0; } void INT::execWP_CLRP() { register_RPCELL.write(0); } // INHINT1: inhibits interrupts for 1 instruction (on WOVI) void INT::execWP_WOVI() { if(BUS::testOverflow(BUS::glbl_WRITE_BUS) != NO_OVF) register_INHINT1.write(1); } void INT::execWP_CLINH1() { register_INHINT1.write(0); } // INHINT: inhibits interrupts on INHINT, reenables on RELINT void INT::execWP_INH() { register_INHINT.write(1); } void INT::execWP_CLINH() { register_INHINT.write(0); }

ISD (ISD.h)
/**************************************************************************** * ISD - INSTRUCTION SUBSEQUENCE DECODER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ISD.h * * VERSIONS: * * DESCRIPTION: * Instruction Subsequence Decoder for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef ISD_H #define ISD_H #include "SEQ.h" #include "CTR.h" // INSTRUCTION SUBSEQUENCE DECODER

#ifdef NOTDEF class ISD { public: static subseq instructionSubsequenceDecoder(); static char* ISD::subseqString[]; }; #endif #endif

ISD (ISD.cpp)
/**************************************************************************** * ISD - INSTRUCTION SUBSEQUENCE DECODER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: ISD.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "ISD.h" #ifdef NOTDEF char* ISD::subseqString[] = { "TC0", "CCS0", "CCS1", "NDX0", "NDX1", "RSM3", "XCH0", "CS0", "TS0", "AD0", "MASK0", "MP0", "MP1", "MP3", "DV0", "DV1", "SU0", "RUPT1", "RUPT3", "STD2", "PINC0", "MINC0", "SHINC0", "NO_SEQ" }; subseq ISD::instructionSubsequenceDecoder() { // Combinational logic decodes instruction and the stage count // to get the instruction subsequence. static subseq decode[16][4] = { { TC0, RUPT1, STD2, RUPT3 }, // 00 { CCS0, CCS1, NO_SEQ, NO_SEQ }, // 01 { NDX0, NDX1, NO_SEQ, RSM3 }, // 02 { XCH0, NO_SEQ, STD2, NO_SEQ }, // 03 { { { { { { { { { { { { }; switch(CTR::getSubseq()) { case PINCSEL: return PINC0; NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, MP0, DV0, SU0, CS0, TS0, AD0, MASK0, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, MP1, DV1, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, NO_SEQ, STD2, STD2, STD2, STD2, STD2, STD2, NO_SEQ NO_SEQ NO_SEQ NO_SEQ NO_SEQ }, }, }, }, }, // // // // // 04 05 06 07 10

MP3 }, // 11 NO_SEQ }, // 12 NO_SEQ }, // 13 NO_SEQ NO_SEQ NO_SEQ NO_SEQ }, }, }, } // // // // 14 15 16 17

case MINCSEL: return MINC0; default: return decode[SEQ::register_SQ.read()][SEQ::register_STB.read()]; } } #endif

KBD (KBD.h)
/**************************************************************************** * KBD - DSKY KEYBOARD subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: KBD.h * * VERSIONS: * * DESCRIPTION: * DSKY Keyboard for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef KBD_H #define KBD_H

enum keyInType { // DSKY keyboard input codes: Taken from E-1574, Appendix 1 // These codes enter the computer through bits 1-5 of IN0. // The MSB is in bit 5; LSB in bit 1. Key entry generates KEYRUPT. KEYIN_NONE =0, // no key depressed** KEYIN_0 =020, KEYIN_1 =001, KEYIN_2 =002, KEYIN_3 =003, KEYIN_4 =004, KEYIN_5 =005, KEYIN_6 =006, KEYIN_7 =007, KEYIN_8 =010, KEYIN_9 =011, KEYIN_VERB =021, KEYIN_ERROR_RESET =022, KEYIN_KEY_RELEASE =031, KEYIN_PLUS =032, KEYIN_MINUS =033, KEYIN_ENTER =034, KEYIN_CLEAR =036, KEYIN_NOUN =037, }; class KBD { public: static keyInType kbd; // latches the last key entry from the DSKY static void keypress(keyInType c); }; #endif

KBD (KBD.cpp)
/**************************************************************************** * KBD - DSKY KEYBOARD subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: KBD.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "KBD.h" #include "INT.h" // DSKY keyboard keyInType KBD::kbd=KEYIN_NONE;

// latches the last key entry from the DSKY

void KBD::keypress(keyInType c) { // latch the keycode kbd = c; // generate KEYRUPT interrupt INT::rupt[KEYRUPT] = 1; }

MBF (MBF.h)
/**************************************************************************** * MBF - MEMORY BUFFER REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MBF.h * * VERSIONS: * * DESCRIPTION: * Memory Buffer Register for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef MBF_H #define MBF_H #include "reg.h" class regG : public reg { public: // all memory bits except bit 15 (parity) // bit 15 is not used, so ignore it. regG() : reg(16, "%06o") { } };

class MBF { public: static void execWP_GENRST(); static void execRP_RG(); static void execRP_WE(); static static static static static static static void void void void void void void execWP_WGn(); execWP_WGx(); execWP_W20(); execWP_W21(); execWP_W22(); execWP_W23(); execWP_SBWG();

// Bit 15 (parity) is kept in a separate register in PAR // because it is independently loaded. static regG register_G; // memory buffer register (except for bit 15) static static static static static static static static }; #endif unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned conv_RG[]; conv_WGn[]; conv_W20[]; conv_W21[]; conv_W22[]; conv_W23[]; conv_SBWG[]; conv_WE[];

MBF (MBF.cpp)
/**************************************************************************** * MBF - MEMORY BUFFER REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MBF.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "MBF.h" #include "SEQ.h" #include "ADR.h" #include "BUS.h" #include "PAR.h" #include "MEM.h" // The actual bit 15 of register_G is not used. regG MBF::register_G; // memory buffer register (except bit 15: parity) unsigned MBF::conv_RG[] = { SG, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 }; unsigned MBF::conv_SBWG[] = { SGM, BX, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 }; unsigned MBF::conv_WE[] = { BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 }; unsigned MBF::conv_W20[] = { B1, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 }; unsigned MBF::conv_W21[] = { SG, BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2 }; unsigned MBF::conv_W22[] = { B14, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG }; unsigned MBF::conv_W23[] = { SG, BX, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1, SG };

void MBF::execWP_GENRST() { register_G.write(0); }

void MBF::execRP_RG() { if(ADR::GTR_17()) { BUS::glbl_READ_BUS = register_G.shiftData(0, register_G.read(), MBF::conv_RG); } } void MBF::execRP_WE() { // Write G into memory; shift the sign to bit 15; parity is written from the // PAR subsystem MEM::MEM_DATA_BUS = (register_G.shiftData(0, MBF::register_G.read(), MBF::conv_WE)); }

void MBF::execWP_WGn() { register_G.write(BUS::glbl_WRITE_BUS); } void MBF::execWP_WGx() { // This is only used in PINC, MINC, and SHINC. Does not clear G // register; writes (ORs) into G from RWBus and writes into parity // from 1-15 generator. The sequence calls CLG in a previous TP to // reset G to zero, so the OR operation can be safely eliminated // from my implementation of the design. register_G.write(BUS::glbl_WRITE_BUS); } void MBF::execWP_W20() { register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W20); } void MBF::execWP_W21() { register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W21); } void MBF::execWP_W22() { register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W22); } void MBF::execWP_W23() { register_G.writeShift(BUS::glbl_WRITE_BUS, MBF::conv_W23); } void MBF::execWP_SBWG() { register_G.writeShift(MEM::MEM_DATA_BUS, MBF::conv_SBWG); }

MEM (MEM.h)
/**************************************************************************** * MEM - ERASEABLE/FIXED MEMORY subsystem * * AUTHOR: John Pultorak * DATE: 9/26/02 * FILE: MEM.h * * VERSIONS: * * DESCRIPTION: * Eraseable & Fixed Memory for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef MEM_H #define MEM_H #include "reg.h" #define NUMFBANK 12 // number of 1024 word fixed memory banks

class regEMEM : public reg { public: regEMEM() : reg(16, "%06o") { } regEMEM& operator= (const unsigned& r) { write(r); return *this; } }; class regFMEM : public reg { public: regFMEM() : reg(16, "%06o") { } regFMEM& operator= (const unsigned& r) { write(r); return *this; } }; class MEM { public: static void execWP_WE(); static void execRP_SBWG(); static regEMEM register_EMEM[]; // erasable memory static regFMEM register_FMEM[]; // fixed memory static unsigned MEM_DATA_BUS; // data lines: memory bits 15-1 static unsigned MEM_PARITY_BUS; // parity line: memory bit 16 static unsigned readMemory(); static void writeMemory(unsigned data); // The following functions are used in the simulator, // but are implemented in the AGC design. static unsigned readMemory(unsigned address); static void writeMemory(unsigned address, unsigned data); }; #endif

MEM (MEM.cpp)
/**************************************************************************** * MEM - ERASEABLE/FIXED MEMORY subsystem * * AUTHOR: John Pultorak * DATE: 9/26/02 * FILE: MEM.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "MEM.h" #include "ADR.h" #include "stdlib.h" regEMEM MEM::register_EMEM[1024]; // erasable memory regFMEM MEM::register_FMEM[1024*(NUMFBANK+1)]; // fixed memory (lowest 1024 words ignored) unsigned MEM::MEM_DATA_BUS = 0; unsigned MEM::MEM_PARITY_BUS = 0; // data lines: memory bits 15-1 // parity line: memory bit 16

void MEM::execWP_WE() { // Write into memory; parity bit in bit 16 writeMemory( (MEM_PARITY_BUS << 15) | MEM_DATA_BUS ); } void MEM::execRP_SBWG() { MEM_DATA_BUS = readMemory() & 0077777; // everything except parity MEM_PARITY_BUS = (readMemory() & 0100000) >> 15; // parity bit only } unsigned MEM::readMemory() { // Return memory value addressed by lower 10 bits of the S register (1K) and the // bank decoder (which selects the 1K bank) unsigned lowAddress = ADR::register_S.readField(10,1); if(ADR::bankDecoder() == 0) return MEM::register_EMEM[lowAddress].read(); unsigned highAddress = ADR::bankDecoder() << 10; return MEM::register_FMEM[highAddress | lowAddress].read(); } void MEM::writeMemory(unsigned data) { // Write into erasable memory addressed by lower 10 bits of the S register (1K) // and the bank decoder (which selects the 1K bank) unsigned lowAddress = ADR::register_S.readField(10,1); if(ADR::bankDecoder() == 0) { MEM::register_EMEM[lowAddress].write(data); MEM::register_EMEM[lowAddress].clk(); // not a synchronous FF, so execute immediately ************* } } unsigned MEM::readMemory(unsigned address) { // Address is 14 bits. This function is used by the simulator for examining // memory; it is not part of the AGC design. unsigned lowAddress = address & 01777; unsigned bank = (address & 036000) >> 10; if(bank == 0) return MEM::register_EMEM[lowAddress].read();

unsigned highAddress = bank << 10; return MEM::register_FMEM[highAddress | lowAddress].read(); } void MEM::writeMemory(unsigned address, unsigned data) { // Address is 14 bits. This function is used by the simulator for depositing into // memory; it is not part of the AGC design. This function is also used to // initialize fixed memory. //************************************************************ // This function could also write the parity into memory //************************************************************ unsigned lowAddress = address & 01777; unsigned bank = (address & 036000) >> 10; if(bank == 0) { if(lowAddress > 1024) { cout << "Error: Eraseable address=" << lowAddress << endl; exit(0); } MEM::register_EMEM[lowAddress].write(data); MEM::register_EMEM[lowAddress].clk(); // execute immediately } else { unsigned highAddress = bank << 10; if((highAddress | lowAddress) >= 1024*(NUMFBANK+1)) { cout << "Error: Fixed address=" << (highAddress | lowAddress) << endl; exit(0); } MEM::register_FMEM[highAddress | lowAddress].write(data); MEM::register_FMEM[highAddress | lowAddress].clk(); // execute immediately } }

MON (MON.h)
/**************************************************************************** * MON - AGC MONITOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MON.h * * VERSIONS: * * DESCRIPTION: * AGC Monitor for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef MON_H #define MON_H class MON { public: static void displayAGC(); static char* MON::clkTypestring[]; static static static static static unsigned unsigned unsigned unsigned unsigned PURST; RUN; STEP; INST; FCLK; SA; // // // // // power up reset run/halt switch single step switch instruction/sequence step select switch clock mode (0=single (manual) clock, 1=continuous clock)

static unsigned static unsigned }; #endif

// "standby allowed" SW; // 0=NO (full power), 1=YES (low power) // "scaler enabled" SW; 0=NO (scaler halted), 1=YES (scaler running)

SCL_ENAB;

MON (MON.cpp)
/**************************************************************************** * MON - AGC MONITOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: MON.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "MON.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned unsigned unsigned unsigned unsigned "TPG.h" "MON.h" "SCL.h" "SEQ.h" "INP.h" "OUT.h" "BUS.h" "DSP.h" "ADR.h" "PAR.h" "MBF.h" "MEM.h" "CTR.h" "INT.h" "KBD.h" "CRG.h" "ALU.h" "CPM.h" "ISD.h" "CLK.h" MON::PURST=1; MON::RUN=0; MON::STEP=0; MON::INST=1; MON::FCLK=0; // // // // // power up reset; initially high at startup run/halt switch single step switch instruction/sequence step select switch clock mode

unsigned MON::SA=0; unsigned MON::SCL_ENAB=1; running)

// "standby allowed" SW; 0=NO (full power), 1=YES (low power) // "scaler enabled" SW; 0=NO (scaler halted), 1=YES (scaler

void MON::displayAGC() { char buf[100]; cout << "AGC4 SIMULATOR 1.16 -------------------------------" << endl; sprintf(buf," TP: %-5s F17:%1d F13:%1d F10:%1d SCL:%06o", TPG::tpTypestring[TPG::register_SG.read()], SCL::register_F17.read(), SCL::register_F13.read(), SCL::register_F10.read(), SCL::register_SCL.read()); cout << buf << endl; sprintf(buf, " STA:%01o STB:%01o BR1:%01o BR2:%01o SNI:%01o CI:%01o LOOPCTR:%01o", SEQ::register_STA.read(), SEQ::register_STB.read(), SEQ::register_BR1.read(), SEQ::register_BR2.read(), SEQ::register_SNI.read(), ALU::register_CI.read(), SEQ::register_LOOPCTR.read()); cout << buf << endl; sprintf(buf, " RPCELL:%05o %-6s", INT::register_RPCELL.read(), INT::register_INHINT1.read(), INT::register_INHINT.read(), CTR::register_UpCELL.read(), CTR::register_DnCELL.read(), SEQ::register_SQ.read(), SEQ::instructionString[SEQ::register_SQ.read()], CPM::subseqString[SEQ::glbl_subseq]); cout << buf << endl; sprintf(buf, " CP:%s", SEQ::getControlPulses()); cout << buf << endl; INH1:%01o INH:%01o UpCELL:%03o DnCELL:%03o SQ:%02o %-6s

// For the G register, bit 15 comes from register G15; the other bits (16, 14-1) come // from register G. sprintf(buf, " S: %04o G:%06o P:%06o (r)RUN :%1d (p)PURST:%1d (F2,F4)FCLK:%1d", ADR::register_S.read(), (MBF::register_G.read() & 0137777) | (PAR::register_G15.read() << 14), PAR::register_P.read(), MON::RUN, MON::PURST, MON::FCLK); cout << buf << endl; sprintf(buf, " RBU:%06o WBU:%06o P2:%01o (s)STEP:%1d", BUS::glbl_READ_BUS & 0177777, BUS::glbl_WRITE_BUS & 0177777, PAR::register_P2.read(), MON::STEP); cout << buf << endl; char parityAlm = ' '; if(PAR::register_PALM.read()) parityAlm = '*'; sprintf(buf, " B:%06o CADR:%06o (n)INST:%1d PALM:[%c]", ALU::register_B.read(), ADR::getEffectiveAddress(), MON::INST, parityAlm); cout << buf << endl; sprintf(buf, " X:%06o Y:%06o U:%06o (a)SA :%1d", ALU::register_X.read(), ALU::register_Y.read(), ALU::register_U.read(), MON::SA); cout << buf << endl; cout << endl; sprintf(buf, "00 A:%06o 15 BANK:%02o 36 TIME1:%06o 53 OPT Y:%06o", CRG::register_A.read(), ADR::register_BNK.read(), MEM::readMemory(036), MEM::readMemory(053)); cout << buf << endl; sprintf(buf, "01 Q:%06o 16 RELINT:%6s 37 TIME3:%06o 54 TRKR X:%06o", CRG::register_Q.read(),"", MEM::readMemory(037), MEM::readMemory(054)); cout << buf << endl; sprintf(buf, "02 Z:%06o 17 INHINT:%6s 40 TIME4:%06o 55 TRKR Y:%06o", CRG::register_Z.read(),"", MEM::readMemory(040), MEM::readMemory(055)); cout << buf << endl; sprintf(buf, "03 LP:%06o 20 CYR:%06o 41 UPLINK:%06o 56 TRKR Z:%06o", CRG::register_LP.read(), MEM::readMemory(020), MEM::readMemory(041), MEM::readMemory(056)); cout << buf << endl; sprintf(buf, "04 IN0:%06o 21 SR:%06o 42 OUTCR1:%06o", INP::register_IN0.read(), MEM::readMemory(021), MEM::readMemory(042)); cout << buf << endl; char progAlm = ' '; if(OUT::register_OUT1.read() & 0400) progAlm = '*'; char compFail = ' '; // also called 'check fail' and 'oper err' if(OUT::register_OUT1.read() & 0100) compFail = '*'; char keyRels = ' '; if(OUT::register_OUT1.read() & 020) keyRels = '*'; char upTl = ' '; if(OUT::register_OUT1.read() & 004) upTl = '*'; char comp = ' '; // also called comp acty if(OUT::register_OUT1.read() & 001) comp = '*'; sprintf(buf, "05 IN1:%06o 22 CYL:%06o 43 OUTCR2:%06o CF:[%c%c]:KR [%c]:PA", INP::register_IN1.read(), MEM::readMemory(022), MEM::readMemory(043), compFail, keyRels, progAlm); cout << buf << endl; sprintf(buf, "06 IN2:%06o 23 SL:%06o 44 PIPA X:%06o", INP::register_IN2.read(), MEM::readMemory(023), MEM::readMemory(044)); cout << buf << endl; sprintf(buf, "07 IN3:%06o 24 ZRUPT:%06o 45 PIPA Y:%06o A:[%c%c] M:[%c%c]", INP::register_IN3.read(), MEM::readMemory(024), MEM::readMemory(045),

upTl, comp, DSP::MD1, DSP::MD2); cout << buf << endl; char fc = ' '; if(DSP::flash) fc = '*'; sprintf(buf, "10 OUT0: 25 BRUPT:%06o 46 PIPA Z:%06o V:[%c%c] N:[%c%c] %c", MEM::readMemory(025), MEM::readMemory(046), DSP::VD1, DSP::VD2, DSP::ND1, DSP::ND2, fc); cout << buf << endl; sprintf(buf, "11 OUT1:%06o 26 ARUPT:%06o 47 CDU X:%06o R1:[ %c%c%c%c%c%c ]", OUT::register_OUT1.read(), MEM::readMemory(026), MEM::readMemory(047), DSP::R1S, DSP::R1D1, DSP::R1D2, DSP::R1D3, DSP::R1D4, DSP::R1D5); cout << buf << endl; sprintf(buf, "12 OUT2:%06o 27 QRUPT:%06o 50 CDU Y:%06o R2:[ %c%c%c%c%c%c ]", OUT::register_OUT2.read(), MEM::readMemory(027), MEM::readMemory(050), DSP::R2S, DSP::R2D1, DSP::R2D2, DSP::R2D3, DSP::R2D4, DSP::R2D5); cout << buf << endl; sprintf(buf, "13 OUT3:%06o 34 OVCTR:%06o 51 CDU Z:%06o R3:[ %c%c%c%c%c%c ]", OUT::register_OUT3.read(), MEM::readMemory(034), MEM::readMemory(051), DSP::R3S, DSP::R3D1, DSP::R3D2, DSP::R3D3, DSP::R3D4, DSP::R3D5); cout << buf << endl; sprintf(buf, "14 OUT4:%06o 35 TIME2:%06o 52 OPT X:%06o", OUT::register_OUT4.read(), MEM::readMemory(035), MEM::readMemory(052)); cout << buf << endl; }

OUT (OUT.h)
/**************************************************************************** * OUT - OUTPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: OUT.h * * VERSIONS: * * DESCRIPTION: * Output Registers for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef OUT_H #define OUT_H #include "reg.h" class regOut1 : public reg { public: regOut1() : reg(16, "%06o") { } }; class regOut2 : public reg { public: regOut2() : reg(16, "%06o") { } }; class regOut3 : public reg { public: regOut3() : reg(16, "%06o") { } }; class regOut4 : public reg { public: regOut4() : reg(16, "%06o") { } }; class OUT { public: static static static static static static static static static static static static static static }; #endif

void void void void void void void void void void

execWP_GENRST(); execWP_WA10(); execRP_RA11(); execWP_WA11(); execRP_RA12(); execWP_WA12(); execRP_RA13(); execWP_WA13(); execRP_RA14(); execWP_WA14(); register_OUT1; register_OUT2; register_OUT3; register_OUT4; // // // // output output output output register register register register 1 2 3 4

regOut1 regOut2 regOut3 regOut4

OUT (OUT.cpp)
/**************************************************************************** * OUT - OUTPUT REGISTER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: OUT.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "OUT.h" #include "SEQ.h" #include "BUS.h" #include "DSP.h" #include "ADR.h" #include "PAR.h" #include <stdlib.h> regOut1 regOut2 regOut3 regOut4 OUT::register_OUT1; OUT::register_OUT2; OUT::register_OUT3; OUT::register_OUT4; // // // // output output output output register register register register 1 2 3 4

// Writing to OUT0 loads the selected DSKY display register.

void OUT::execWP_GENRST() { DSP::clearOut0(); register_OUT1.write(0); register_OUT2.write(0); } void OUT::execWP_WA10() { DSP::decodeRelayWord(BUS::glbl_WRITE_BUS); }

void OUT::execRP_RA11() { BUS::glbl_READ_BUS = register_OUT1.read(); }

void OUT::execWP_WA11() { register_OUT1.write(BUS::glbl_WRITE_BUS); } void OUT::execRP_RA12() { BUS::glbl_READ_BUS = register_OUT2.read(); }

void OUT::execWP_WA12() { register_OUT2.write(BUS::glbl_WRITE_BUS); }

void OUT::execRP_RA13() { BUS::glbl_READ_BUS = register_OUT3.read(); }

void OUT::execWP_WA13() { register_OUT3.write(BUS::glbl_WRITE_BUS); }

void OUT::execRP_RA14() { BUS::glbl_READ_BUS = register_OUT4.read(); }

void OUT::execWP_WA14() { register_OUT4.write(BUS::glbl_WRITE_BUS); }

PAR (PAR.h)
/**************************************************************************** * PAR - PARITY GENERATION AND TEST subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: PAR.h * * VERSIONS: * * DESCRIPTION: * Parity Generation and Test for the Block 1 Apollo Guidance Computer * prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef PAR_H #define PAR_H #include "reg.h" class regG15 : public reg { public: // memory buffer register bit 15 (parity) only regG15() : reg(1, "%01o") { } }; class regP : public reg { public: regP() : reg(16, "%06o") { } }; class regP2 : public reg { public: regP2() : reg(1, "%01o") { } }; class regPALM : public reg { public: // parity alarm FF (set on TP) regPALM() : reg(1, "%01o") { } }; class PAR { public: static void execRP_WE(); static static static static static static static static void void void void void void void void execWP_WP(); execWP_WPx(); execWP_WP2(); execWP_RP2(); execWP_GP(); execWP_SBWG(); execWP_WGx(); execWP_CLG();

static void execWP_GENRST();

static void execWP_TP(); static void CLR_PALM(); // asynchronous clear for PARITY ALARM

// memory buffer register bit 15; the rest of the // memory buffer register is defined in MBF static regG15 register_G15; static regP2 register_P2; static regP register_P; static regPALM register_PALM; static unsigned gen1_15Parity(unsigned r); static unsigned genP_15Parity(unsigned r); static unsigned conv_WP[]; }; #endif

PAR (PAR.cpp)
/**************************************************************************** * PAR - PARITY GENERATION AND TEST subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: PAR.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "PAR.h" #include "SEQ.h" #include "BUS.h" #include "MBF.h" #include "ADR.h" #include "MEM.h" regP PAR::register_P; regP2 PAR::register_P2; regG15 PAR::register_G15; // memory buffer register bit 15 regPALM PAR::register_PALM; // PARITY ALARM FF unsigned PAR::conv_WP[] = { BX, SG, B14, B13, B12, B11, B10, B9, B8, B7, B6, B5, B4, B3, B2, B1 };

void PAR::execRP_WE() { // Write parity into memory. MEM::MEM_PARITY_BUS = PAR::register_G15.read(); }

// IMPLEMENTATION NOTE: It has been empirically determined that the following // control signals are mutually exclusive (there is never more than one of these // generated at any time): // GP, WGX, RP2, SBWG, CLG // // // // NOTE: WP clears register_P before writing into it. Strictly speaking, WPx isn't supposed to clear the register (should OR into the register), but in the counter sequences where WPx is used, register_P is always cleared in the previous TP by asserting WP with default zeroes on the write bus.

void PAR::execWP_WP() { // set all bits except parity bit register_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP); // now set parity bit; in the actual AGC, this is // a single operation. if(SEQ::isAsserted(RG)) register_P.writeField(16, 16, register_G15.read()); else register_P.writeField(16, 16, 0); // clear parity bit } void PAR::execWP_WPx() { // set all bits except parity bit register_P.writeShift(BUS::glbl_WRITE_BUS, PAR::conv_WP); // now set parity bit; in the actual AGC, this is // a single operation. if(SEQ::isAsserted(RG)) register_P.writeField(16, 16, register_G15.read()); else

register_P.writeField(16, 16, 0); // clear parity bit } void PAR::execWP_WP2() { register_P2.write(gen1_15Parity(register_P.read())); } void PAR::execWP_RP2() { register_G15.write(register_P2.read()); } void PAR::execWP_GP() { register_G15.write(gen1_15Parity(register_P.read())); } void PAR::execWP_SBWG() { register_G15.write(MEM::MEM_PARITY_BUS); // load memory bit 16 (parity) into G15 } void PAR::execWP_WGx() { // This is only used in PINC, MINC, and SHINC. Does not clear G // register; writes (ORs) into G from RWBus and writes into parity // from 1-15 generator. All done in one operation, although I show // it in two steps here. The sequence calls CLG in a previous TP. register_G15.write(PAR::gen1_15Parity(register_P.read())); } void PAR::execWP_CLG() { register_G15.write(0); } void PAR::execWP_GENRST() { register_PALM.write(0); } void PAR::execWP_TP() { if(ADR::GTR_27() && genP_15Parity(register_P.read())) register_PALM.write(genP_15Parity(register_P.read())); } void PAR::CLR_PALM() { // asynchronous clear for PARITY ALARM (from MON) register_PALM.clear(); } unsigned PAR::gen1_15Parity(unsigned r) { //check the lower 15 bits of 'r' and return the odd parity; //bit 16 is ignored. unsigned evenParity = (1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^ (1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^ (1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^ (1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14)); return ~evenParity & 1; // odd parity } unsigned PAR::genP_15Parity(unsigned r) { //check all 16 bits of 'r' and return the odd parity unsigned evenParity = (1&(r>>0)) ^ (1&(r>>1)) ^ (1&(r>>2)) ^ (1&(r>>3)) ^ (1&(r>>4)) ^ (1&(r>>5)) ^ (1&(r>>6)) ^ (1&(r>>7)) ^ (1&(r>>8)) ^ (1&(r>>9)) ^ (1&(r>>10)) ^ (1&(r>>11)) ^

(1&(r>>12)) ^ (1&(r>>13)) ^ (1&(r>>14)) ^ (1&(r>>15)); return ~evenParity & 1; // odd parity }

Registers (reg.h)
#ifndef reg_H #define reg_H #include <iostream.h> #include <string.h> #include <stdio.h> class reg { public: virtual unsigned read() { return mask & slaveVal; } virtual void write(unsigned v) { load = true; masterVal = mask & v; } // asynchronous clear void clear() { slaveVal = 0; } // load is set when a register is written into. void clk() { if(load) slaveVal = masterVal; load = false; } unsigned readField(unsigned msb, unsigned lsb); // bitfield numbered n - 1 void writeField(unsigned msb, unsigned lsb, unsigned v); // bitfield numbered n - 1 // Write a 16-bit word (in) into the register. Transpose the bits according to // the specification (ib). void writeShift(unsigned in, unsigned* ib); // Return a shifted 16-bit word. Transpose the 'in' bits according to // the specification 'ib'. 'Or' the result to out and return the value. unsigned shiftData(unsigned out, unsigned in, unsigned* ib); unsigned outmask() { return mask; } protected: reg(unsigned s, char* fs) : size(s), mask(0), masterVal(0), slaveVal(0), fmtString(fs), load(false) { mask = buildMask(size);} static unsigned buildMask(unsigned s); friend ostream& operator << (ostream& os, const reg& r) { char buf[32]; sprintf(buf, r.fmtString, r.slaveVal); os << buf; return os; } private: unsigned unsigned unsigned unsigned char* bool }; #endif

size; // bits masterVal; slaveVal; mask; fmtString; load;

reg(); // prevent instantiation of default constructor

Registers (reg.cpp)
#include "reg.h" #include <math.h> #include "BUS.h" unsigned reg::buildMask(unsigned s) { unsigned msk = 0; for(unsigned i=0; i<s; i++) { msk = (msk << 1) | 1; } return msk; } unsigned reg::readField(unsigned msb, unsigned lsb) { return (slaveVal >> (lsb-1)) & buildMask((msb-lsb)+1); } void reg::writeField(unsigned msb, unsigned lsb, unsigned v) { load = true; unsigned fmask = buildMask((msb-lsb)+1) << (lsb-1); v = (v << (lsb-1)) & fmask; masterVal = (masterVal &(~fmask)) | v; } void reg::writeShift(unsigned in, unsigned* ib) { load = true; unsigned out = masterVal; // iterate through each bit of the output word, copying in bits from the input // word and transposing bit position according to the specification (ib) for(unsigned i=0; i<16; i++) { if(ib[i] == BX) continue; // BX is 'don't care', so leave it alone // zero the output bit at 'ob', where ob specifies a bit // position (numbered 16-1, where 1 is lsb) unsigned ob = 16-i; unsigned obmask = 1 << (ob - 1); // create mask for output bit out &= ~obmask; if(ib[i] == D0) continue; // D0 is 'force the bit to zero' // copy input bit ib[i] to output bit 'ob', where ib and ob // specify bit positions (numbered 16-1, where 1 is lsb) unsigned ibmask = 1 << (ib[i] - 1); // create mask for input bit unsigned inbit = in & ibmask; int shift = ib[i]-ob; if(shift<0) inbit = inbit << abs(shift); else if(shift > 0) inbit = inbit >> shift; out |= inbit; } masterVal = out; } unsigned reg::shiftData(unsigned out, unsigned in, unsigned* ib) { // iterate through each bit of the output word, copying in bits from the input // word and transposing bit position according to the specification (ib) for(unsigned i=0; i<16; i++) { if(ib[i] == BX) continue; // BX is 'don't care', so leave it alone // zero the output bit at 'ob', where ob specifies a bit // position (numbered 16-1, where 1 is lsb) unsigned ob = 16-i;

unsigned obmask = 1 << (ob - 1); // create mask for output bit out &= ~obmask; if(ib[i] == D0) continue; // D0 is 'force the bit to zero' // copy input bit ib[i] to output bit 'ob', where ib and ob // specify bit positions (numbered 16-1, where 1 is lsb) unsigned ibmask = 1 << (ib[i] - 1); // create mask for input bit unsigned inbit = in & ibmask; int shift = ib[i]-ob; if(shift<0) inbit = inbit << abs(shift); else if(shift > 0) inbit = inbit >> shift; out |= inbit; } return out; }

SCL (SCL.h)
/**************************************************************************** * SCL - SCALER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SCL.h * * VERSIONS: * * DESCRIPTION: * Scaler for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef SCL_H #define SCL_H #include "reg.h" class regF17 : public reg { public: regF17() : reg(2, "%01o") { } }; class regF13 : public reg { public: regF13() : reg(2, "%01o") { } }; class regF10 : public reg { public: regF10() : reg(2, "%01o") { } }; class regSCL : public reg { public: regSCL() : reg(17, "%06o") { } }; class SCL { public: static static static static

void void void void

doexecWP_SCL(); doexecWP_F17(); doexecWP_F13(); doexecWP_F10();

static regSCL register_SCL; // Normally outputs '0'; outputs '1' for one // clock pulse at the indicated frequency. static unsigned F17x(); // 0.78125 Hz scaler output static unsigned F13x(); // 12.5 Hz scaler output static unsigned F10x(); // 100 Hz scaler output static regF17 register_F17; static regF13 register_F13; static regF10 register_F10; };

#endif

SCL (SCL.cpp)
/**************************************************************************** * SCL - SCALER subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SCL.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "SCL.h" #include "CTR.h" #include "MON.h" regSCL regF17 regF13 regF10 SCL::register_SCL; SCL::register_F17; SCL::register_F13; SCL::register_F10;

enum oneShotType { // **inferred; not defined in orignal R393 AGC4 spec. WAIT_FOR_TRIGGER=0, OUTPUT_PULSE=1, // LSB (bit 1) is the output bit for the one-shot WAIT_FOR_RESET=2 };

void SCL::doexecWP_F17() { int bit = SCL::register_SCL.readField(17,17); switch(register_F17.read()) { case WAIT_FOR_TRIGGER: if(bit==1) register_F17.write(OUTPUT_PULSE); break; case OUTPUT_PULSE: register_F17.write(WAIT_FOR_RESET); break; case WAIT_FOR_RESET: if(bit==0) register_F17.write(WAIT_FOR_TRIGGER); break; default: ; } } void SCL::doexecWP_F13() { int bit = SCL::register_SCL.readField(13,13); switch(register_F13.read()) { case WAIT_FOR_TRIGGER: if(bit==1) register_F13.write(OUTPUT_PULSE); break; case OUTPUT_PULSE: register_F13.write(WAIT_FOR_RESET); break; case WAIT_FOR_RESET: if(bit==0) register_F13.write(WAIT_FOR_TRIGGER); break; default: ; } } void SCL::doexecWP_F10() { int bit = SCL::register_SCL.readField(10,10); switch(register_F10.read()) { case WAIT_FOR_TRIGGER: if(bit==1) register_F10.write(OUTPUT_PULSE); break; case OUTPUT_PULSE: register_F10.write(WAIT_FOR_RESET); CTR::pcUp[TIME1] = 1; CTR::pcUp[TIME3] = 1; CTR::pcUp[TIME4] = 1; break; case WAIT_FOR_RESET: if(bit==0) register_F10.write(WAIT_FOR_TRIGGER); break; default: ; } } unsigned SCL::F17x() { return register_F17.readField(1,1);

} unsigned SCL::F13x() { return register_F13.readField(1,1); } unsigned SCL::F10x() { return register_F10.readField(1,1); } void SCL::doexecWP_SCL() { if(MON::SCL_ENAB) // if the scaler is enabled { //write((read() + 1) % outmask()); register_SCL.write((register_SCL.read() + 1)); } }

SEQ (SEQ.h)
/**************************************************************************** * SEQ - SEQUENCE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SEQ.h * * VERSIONS: * * DESCRIPTION: * Sequence Generator for the Block 1 Apollo Guidance Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef SEQ_H #define SEQ_H #include "reg.h" #define MAXPULSES 15 #define MAX_IPULSES 5 // no more than 5 instruction-generated pulses active at any time enum cpType { // **inferred; not defined in orignal R393 AGC4 spec. NO_PULSE=0, // OUTPUTS FROM SUBSYSTEM A CI =1, // Carry in CLG =2, // Clear G CLCTR =3, // Clear loop counter CTR =4, // Loop counter GP =5, // Generate Parity KRPT =6, // Knock down Rupt priority NISQ =7, // New instruction to the SQ register RA =8, // Read A RB =9, // Read B RB14 =10, // Read bit 14 RC =11, // Read C RG =12, // Read G RLP =13, // Read LP RP2 =14, // Read parity 2 RQ =15, // Read Q RRPA =16, // Read RUPT address RSB =17, // Read sign bit RSCT =18, // Read selected counter address RU =19, // Read sum RZ =20, // Read Z R1 =21, // Read 1 R1C =22, // Read 1 complimented R2 =23, // Read 2 R22 =24, // Read 22 R24 =25, // Read 24 ST1 =26, // Stage 1 ST2 =27, // Stage 2 TMZ =28, // Test for minus zero TOV =29, // Test for overflow TP =30, // Test parity TRSM =31, // Test for resume TSGN =32, // Test sign TSGN2 =33, // Test sign 2 WA =34, // Write A WALP =35, // Write A and LP WB =36, // Write B WGx =37, // Write G (do not reset)

WLP WOVC WOVI WOVR WP WPx WP2 WQ WS WX WY WYx WZ

=38, =39, =40, =41, =42, =43, =44, =45, =46, =47, =48, =49, =50,

// // // // // // // // // // // // //

Write Write Write Write Write Write Write Write Write Write Write Write Write

LP overflow counter overflow RUPT inhibit overflow P P (do not reset) P2 Q S X Y Y (do not reset) Z

// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY; // NOT USED OUTSIDE CPM RSC =51, // Read special and central (output to B only, not outside CPM) WSC =52, // Write special and central (output to B only, not outside CPM) WG =53, // Write G (output to B only, not outside CPM) // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY; // NOT USED OUTSIDE CPM SDV1 =54, // Subsequence DV1 is currently active SMP1 =55, // Subsequence MP1 is currently active SRSM3 =56, // Subsequence RSM3 is currently active // EXTERNAL OUTPUTS FROM SUBSYSTEM B // RA0 =57, // Read register at address 0 (A) RA1 =58, // Read register at address 1 (Q) RA2 =59, // Read register at address 2 (Z) RA3 =60, // Read register at address 3 (LP) RA4 =61, // Read register at address 4 RA5 =62, // Read register at address 5 RA6 =63, // Read register at address 6 RA7 =64, // Read register at address 7 RA10 =65, // Read register at address 10 (octal) RA11 =66, // Read register at address 11 (octal) RA12 =67, // Read register at address 12 (octal) RA13 =68, // Read register at address 13 (octal) RA14 =69, // Read register at address 14 (octal) RBK =70, // Read BNK WA0 =71, // Write register at address 0 (A) WA1 =72, // Write register at address 1 (Q) WA2 =73, // Write register at address 2 (Z) WA3 =74, // Write register at address 3 (LP) WA10 =75, // Write register at address 10 (octal) WA11 =76, // Write register at address 11 (octal) WA12 =77, // Write register at address 12 (octal) WA13 =78, // Write register at address 13 (octal) WA14 =79, // Write register at address 14 (octal) WBK =80, // Write BNK WGn =81, // Write G (normal gates)** W20 =82, // Write into CYR W21 =83, // Write into SR W22 =84, // Write into CYL W23 =85, // Write into SL // THESE ARE THE LEFTOVERS -- THEY'RE PROBABLY USED IN SUBSYSTEM C // GENRST =86, // General Reset** CLINH =87, // Clear INHINT** CLINH1 =88, // Clear INHINT1** CLSTA =89, // Clear state counter A (STA)** CLSTB =90, // Clear state counter B (STB)** CLISQ =91, // Clear SNI** CLRP =92, // Clear RPCELL** INH =93, // Set INHINT** RPT =94, // Read RUPT opcode ** SBWG =95, // Write G from memory SETSTB =96, // Set the ST1 bit of STB WE =97, // Write E-MEM from G WPCTR =98, // Write PCTR (latch priority counter sequence)** WSQ =99, // Write SQ

WSTB R2000 };

=100, =101,

// Write stage counter B (STB)** // Read 2000 **

// INSTRUCTIONS // Op Codes, as they appear in the SQ register. enum instruction { // The code in the SQ register is the same as the op code for these // four instructions. TC =00, // 00 TC K Transfer Control 1 MCT CCS =01, // 01 CCS K Count, Compare, and Skip 2 MCT INDEX =02, // 02 INDEX K 2 MCT XCH =03, // 03 XCH K Exchange 2 MCT // The SQ register code is the op code + 010 (octal). This happens because all // of these instructions have bit 15 set (the sign (SG) bit) while in memory. When the // instruction is copied from memory to the memory buffer register (G) to register // B, the SG bit moves from bit 15 to bit 16 and the sign is copied back into bit // 15 (US). Therefore, the CS op code (04) becomes (14), and so on. CS =014, // 04 CS K Clear and Subtract 2 MCT TS =015, // 05 TS K Transfer to Storage 2 MCT AD =016, // 06 AD K Add 2 or 3 MCT MASK =017, // 07 MASK K Bitwise AND 2 MCT // // // // // // MP DV SU }; enum subseq { TC0 CCS0 CCS1 NDX0 NDX1 RSM3 XCH0 CS0 TS0 AD0 MASK0 MP0 MP1 MP3 DV0 DV1 SU0 RUPT1 RUPT3 STD2 PINC0 MINC0 SHINC0 NO_SEQ }; =0, =1, =2, =3, =4, =5, =6, =7, =8, =9, =10, =11, =12, =13, =14, =15, =16, =17, =18, =19, =20, =21, =22, =23 These are extended instructions. They are accessed by executing an INDEX 5777 before each instruction. By convention, address 5777 contains 47777. The INDEX instruction adds 47777 to the extended instruction to form the SQ op code. For example, the INDEX adds 4 to the 4 op code for MP to produce the 11 (octal; the addition generates an end-around-carry). SQ register code (the 7777 part is a negative zero). =011, // 04 MP K Multiply 10 MCT =012, // 05 DV K Divide 18 MCT =013, // 06 SU K Subtract 4 or 5 MCT

enum scType { // identifies subsequence for a given instruction SUB0=0, // ST2=0, ST1=0 SUB1=1, // ST2=0, ST1=1 SUB2=2, // ST2=1, ST1=0 SUB3=3 // ST2=1, ST1=1 }; enum brType { BR00 BR01 =0, =1, // BR1=0, BR2=0 // BR1=0, BR2=1

BR10 BR11 NO_BR };

=2, =3, =4

// BR1=1, BR2=0 // BR1=1, BR2=1 // NO BRANCH =02000; // bottom address of fixed memory

const int GOPROG

class regSQ : public reg { public: regSQ() : reg(4, "%02o") { } }; class regSTA : public reg { public: regSTA() : reg(2, "%01o") { } }; class regSTB : public reg { public: regSTB() : reg(2, "%01o") { } }; class regBR1 : public reg { public: regBR1() : reg(1, "%01o") { } }; class regBR2 : public reg { public: regBR2() : reg(1, "%01o") { } }; class regCTR : public reg { public: regCTR() : reg(3, "%01o") { } }; class regSNI : public reg { public: regSNI() : reg(1, "%01o") { } }; class SEQ { public: static static static static static static static static static static static static static static static static static

void void void void void void void void void void void void void void void void void

execWP_GENRST(); execWP_WSQ(); execWP_NISQ(); execWP_CLISQ(); execWP_ST1(); execWP_ST2(); execWP_TRSM(); execWP_CLSTA(); execWP_WSTB(); execWP_CLSTB(); execWP_SETSTB(); execWP_TSGN(); execWP_TOV(); execWP_TMZ(); execWP_TSGN2(); execWP_CTR(); execWP_CLCTR(); // select next intruction flag // current set of asserted control pulses (MAXPULSES)

static regSNI register_SNI; static cpType glbl_cp[MAXPULSES]; static char* cpTypeString[];

// Test the currently asserted control pulses; return true if the specified // control pulse is active. static bool isAsserted(cpType pulse); // Return a string containing the names of all asserted control pulses. static char* getControlPulses(); static subseq glbl_subseq; static static static static static static }; #endif // currently decoded instruction subsequence instruction register stage counter A stage counter B branch register1 branch register2 // loop counter

regSQ register_SQ; // regSTA register_STA; // regSTB register_STB; // regBR1 register_BR1; // regBR2 register_BR2; // regCTR register_LOOPCTR;

static char* instructionString[];

SEQ (SEQ.cpp)
/**************************************************************************** * SEQ - SEQUENCE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: SEQ.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "SEQ.h" #include "ADR.h" #include "BUS.h" regSNI SEQ::register_SNI; cpType SEQ::glbl_cp[]; regSQ SEQ::register_SQ; regSTA SEQ::register_STA; regSTB SEQ::register_STB; regBR1 SEQ::register_BR1; regBR2 SEQ::register_BR2; regCTR SEQ::register_LOOPCTR; subseq SEQ::glbl_subseq; // select next intruction flag // current set of asserted control pulses (MAXPULSES) // // // // // // // instruction register stage counter A stage counter B branch register1 branch register2 loop counter currently decoded instruction subsequence

char* SEQ::instructionString[] = { "TC", "CCS", "INDEX", "XCH", "***", "***", "***", "***", "***", "MP", "DV", "SU", "CS", "TS", "AD", "MASK" };

char* SEQ::cpTypeString[] = { "NO_PULSE", // OUTPUTS FROM SUBSYSTEM A "CI", "CLG", "CLCTR", "CTR", "GP", "KRPT", "NISQ", "RA", "RB", "RB14", "RC", "RG", "RLP", "RP2", "RQ", "RRPA", "RSB", "RSCT", "RU", "RZ", "R1", "R1C", "R2", "R22", "R24", "ST1", "ST2", "TMZ", "TOV", "TP", "TRSM", "TSGN", "TSGN2", "WA", "WALP", "WB", "WGx", "WLP", "WOVC", "WOVI", "WOVR", "WP", "WPx", "WP2", "WQ", "WS", "WX", "WY", "WYx", "WZ", // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY; // NOT USED OUTSIDE CPM // "RSC", "WSC", "WG", // OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY; // NOT USED OUTSIDE CPM // "SDV1", "SMP1", "SRSM3", // EXTERNAL OUTPUTS FROM SUBSYSTEM B

// "RA0", "RA1", "RA2", "RA3", "RA4", "RA5", "RA6", "RA7", "RA10", "RA11", "RA12", "RA13", "RA14", "RBK", "WA0", "WA1", "WA2", "WA3", "WA10", "WA11", "WA12", "WA13", "WA14", "WBK", "WGn", "W20", "W21", "W22", "W23", // THESE ARE THE LEFTOVERS -- THEY'RE PROBABLY USED IN SUBSYSTEM C // "GENRST", "CLINH", "CLINH1", "CLSTA", "CLSTB", "CLISQ", "CLRP", "INH", "RPT", "SBWG", "SETSTB", "WE", "WPCTR", "WSQ", "WSTB", "R2000" };

void SEQ::execWP_GENRST() { register_SQ.write(0); register_BR1.write(0); register_BR2.write(0); register_SNI.write(0); register_LOOPCTR.write(0); register_STA.write(0); register_STB.write(0); } void SEQ::execWP_WSQ() { register_SQ.write(BUS::glbl_WRITE_BUS >> 12); }

void SEQ::execWP_NISQ() { register_SNI.writeField(1,1,1); // change to write(1)?? } void SEQ::execWP_CLISQ() { register_SNI.writeField(1,1,0); }

// change to write(0)??

bool SEQ::isAsserted(cpType pulse) { for(unsigned i=0; i<MAXPULSES; i++) if(glbl_cp[i] == pulse) return true; return false; }

char* SEQ::getControlPulses() { static char buf[MAXPULSES*6]; strcpy(buf,""); for(unsigned i=0; i<MAXPULSES && glbl_cp[i] != NO_PULSE; i++) { strcat(buf, cpTypeString[glbl_cp[i]]); strcat(buf," "); } //if(strcmp(buf,"") == 0) strcat(buf,"NONE"); return buf; } void SEQ::execWP_ST1() { register_STA.writeField(1,1,1); }

void SEQ::execWP_ST2() { register_STA.writeField(2,2,1); } void SEQ::execWP_TRSM() { if(ADR::EQU_25()) register_STA.writeField(2,2,1); } void SEQ::execWP_CLSTA() { register_STA.writeField(2,1,0); }

void SEQ::execWP_WSTB() { register_STB.write(SEQ::register_STA.read()); } void SEQ::execWP_CLSTB() { register_STB.writeField(2,1,0); } void SEQ::execWP_SETSTB() { register_STB.writeField(2,1,1); }

void SEQ::execWP_TSGN() { // Set Branch 1 FF // if sign bit is '1' (negative sign) if(BUS::glbl_WRITE_BUS & 0100000) register_BR1.write(1); else register_BR1.write(0); } void SEQ::execWP_TOV() { // Set Branch 1 FF // if negative overflow (sign==1; overflow==0) if((BUS::glbl_WRITE_BUS & 0140000) == 0100000) register_BR1.write(1); else register_BR1.write(0); // Set Branch 2 FF // if positive overflow (sign==0; oveflow==1) if((BUS::glbl_WRITE_BUS & 0140000) == 0040000) register_BR2.write(1); else register_BR2.write(0); }

void SEQ::execWP_TSGN2() { // Set Branch 2 FF // if sign bit is '1' (negative sign)

if(BUS::glbl_WRITE_BUS & 0100000) register_BR2.write(1); else register_BR2.write(0); } void SEQ::execWP_TMZ() { // Set Branch 2 FF // if minus zero if(BUS::glbl_WRITE_BUS == 0177777) register_BR2.write(1); else register_BR2.write(0); }

void SEQ::execWP_CTR() { register_LOOPCTR.write(register_LOOPCTR.read()+1); } void SEQ::execWP_CLCTR() { register_LOOPCTR.write(0); }

TPG (TPG.h)
/**************************************************************************** * TPG - TIME PULSE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: TPG.h * * VERSIONS: * * DESCRIPTION: * Time Pulse Generator and Start/Stop Logic for the Block 1 Apollo Guidance * Computer prototype (AGC4). * * SOURCES: * Mostly based on information from "Logical Description for the Apollo * Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh * Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963. * * NOTES: * ***************************************************************************** */ #ifndef TPG_H #define TPG_H #include "reg.h" // Start/Stop Logic and Time Pulse Generator Subsystem enum tpType { STBY PWRON TP1 TP2 TP3 TP4 TP5 TP6 TP7 TP8 TP9 TP10 TP11 TP12 SRLSE WAIT }; class regSG : public reg { public: regSG() : reg(4, "%02o") { } }; class TPG { public: static void doexecWP_TPG(); static regSG register_SG; static char* tpTypestring[]; }; #endif =0, =1, =2, =3, =4, =5, =6, =7, =8, =9, =10, =11, =12, =13, =14, =15 // TIME PULSE 1: start of memory cycle time (MCT)

// EMEM is available in G register by TP6 // FMEM is available in G register by TP7 // G register written to memory beginning at TP10 // TIME PULSE 11: end of memory cycle time (MCT) // select new subsequence/select new instruction // step switch release

TPG (TPG.cpp)
/**************************************************************************** * TPG - TIME PULSE GENERATOR subsystem * * AUTHOR: John Pultorak * DATE: 9/22/01 * FILE: TPG.cpp * * NOTES: see header file. * ***************************************************************************** */ #include "TPG.h" #include "MON.h" #include "SCL.h" #include "SEQ.h" #include "OUT.h" char* TPG::tpTypestring[] = // must correspond to tpType enumerated type { "STBY", "PWRON", "TP1", "TP2", "TP3", "TP4", "TP5", "TP6", "TP7", "TP8", "TP9", "TP10", "TP11", "TP12", "SRLSE", "WAIT" }; regSG TPG::register_SG; // static member

void TPG::doexecWP_TPG() { unsigned mystate = register_SG.read(); if(MON::PURST) mystate = STBY; else switch(mystate) { case STBY: if(!MON::PURST && ((!MON::FCLK) || SCL::F17x())) mystate = PWRON; break; case PWRON: if(((!MON::FCLK) || SCL::F13x())) mystate = TP1; break; case case case case case case case case case case case case TP1: mystate = TP2; break; TP2: mystate = TP3; break; TP3: mystate = TP4; break; TP4: mystate = TP5; break; TP5: mystate = TP6; break; TP6: mystate = TP7; break; TP7: mystate = TP8; break; TP8: mystate = TP9; break; TP9: mystate = TP10; break; TP10: mystate = TP11; break; TP11: mystate = TP12; break; TP12: if(SEQ::register_SNI.read() && OUT::register_OUT1.readField(8,8) && MON::SA) mystate = STBY; // the next transition to TP1 is incompletely decoded; it works because // the transition to STBY has already been tested. else if((MON::RUN) || (!SEQ::register_SNI.read() && MON::INST)) mystate = TP1; else mystate = SRLSE; break; case SRLSE: if(!MON::STEP) mystate = WAIT; break; case WAIT: if(MON::STEP || MON::RUN) mystate = TP1; break; default: break; } register_SG.write(mystate); }

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 8: Flight Software
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
I wan ted ge nuin e Block I flight softwa re for my AG C, bu t could nt find an y. I eventu ally woun d up recreating Block I software from Block II code listings that were available. Major portions of Block II were originally coded as Block I anyway, so the conversion back was not too difficult. A bou t 95% of the instru ctions w ere alread y Block I, so I just had to transla te the rem aining 5 % into their Block I equivalen ts. I dow nloa ded a partia l listing of th e CO LOS SU S 24 9 fligh t softwa re for the Blo ck II Apollo Com man d Modu le AGC from a M.I.T website in late 2001. The listing (at that time) com prised first half of the flight software load. The second half was missing. The part that was present contained erase able m em ory declarations, and PINBALL, the AGC user interface. The missing portion contained (among other things) the EXEC and WA ITLIST pieces of the operating system, bank register calling routin es, and ma th libraries. The down loaded doc um ent wa s a .pd f file con tain ing 300 or so fuzzy dig ital im ages of assem bler listing. I printed it, and then retyped the erasable memory and PINBALL portions into a text file, m arkin g off ea ch reentered line in th e orig ina l listin g w ith a hig hlig hter. I coded my own versions of the EXEC, WAITLIST, BANKC ALL, and other missing routines used by PINBALL. The R-393 d ocumen t from M .I.T. provided some guidance. Over a 6 month period, I was able to get all regular verbs and generic normal nouns working. These are listed near the top of my assembler listing. I add ed a dd ition al com m ents to portion s of cod e tak en from CO LOSS US . The pag e nu m bers in my comments refer to pages in the COLOSSUS 249 assembler listing.

Original COLOSSUS 249 Assembler Code


For comparison purposes, heres a page of the original AGC assem bly code, downloaded from th e M.I.T. w ebsite. Th is is a tiny p ortion of th e PINB ALL co de. I m arked each line w ith a yellow highlighter as I reentered it into a text file.

My COLOSSUS Assembler Code


Heres the exact same portion of code, assembled for my Block I AGC. If you compare the two listings, youll see that I defined some different assembler directives for allocating storage (DS % instea d of OC T) an d tha t my code is sittin g in a different ba nk (5 vs. 40) a t a different offset than the original Block II code.

Scenarios
Heres how some AGC verbs and nouns are used to do commonplace operations. The overview (part 1) and simulator (part 7) docum ents contain actual examples of some of these operations in the simu lated and hardw are AGC s. Display elapsed time from the AGC clock: <VERB> <0> <6> <NOUN> <3> <6> <ENTER> Start a monitor program to continuously display the AGC clock: <VERB> <1> <6> <NOUN> <3> <6> <ENTER> Terminate a monitor program: <VERB> <3> <4> <ENTER> Test DSJT display lights: <VERB> <3> <5> <ENTER> All DSKY lamps and display segments illuminate for 5 sec. after 5 sec, the DSKY lamps extinguish. Load component 1 for dataset at octal address 50 with octal 123: <VERB> <2> <1> <NOUN> <0> <1> <ENTER> Verb/no un disp lay flashes: wa iting for address. <5> <0> <ENTER> Verb/noun display flash continues: waiting for data. <1> <2> <3> <ENTER> Octal word from R1 is loaded at address 50. Display component 1 of dataset at octal address 50: <VERB> <0> <1> <NOUN> <0> <1> <ENTER> Verb/no un disp lay flashes: wa iting for address. <5> <0> <ENTER> Octal word from address 50 is displayed in R1. Display component 1 of dataset incrementing from 50: <VERB> <0> <1> <NOUN> <0> <1> <ENTER> Verb/no un disp lay flashes: wa iting for address. <5> <0> <ENTER> Octal word from address 50 is displayed in R1. <NOUN> <1> <5> <ENTER> Octal word from address 51 is displayed in R1, address in R3. <ENTER> Octal word from address 52 is displayed in R1, address in R3.

Load 3 component dataset at octal address 50 with octal values: 123, 456, 701: <VERB> <2> <5> <NOUN> <0> <1> <ENTER> Verb/no un disp lay flashes: wa iting for address. <5> <0> <ENTER> Verb/noun display flash continues: waiting for data. <1> <2> <3> <ENTER> <4> <5> <6> <ENTER> <7> <0> <1> <ENTER>

Octal wo rd from R1 is loaded at add ress 50; Octal w ord from R2 is loaded at add ress 51, Octal word from R3 is loaded at address 52. Display 3 component dataset beginning at address 50: <VERB> <0> <5> <NOUN> <0> <1> <ENTER> Verb/no un disp lay flashes: wa iting for address. <5> <0> <ENTER> Octa l word from a ddres s 50 is d isplay ed in R 1; O ctal w ord from add ress 51 is displayed in R2; Octal word from address 52 is displayed in R3. Change major mode to P00: <VERB> <3> <7> <ENTER> Verb/noun display flashes: waiting for major mode <0> <0> <ENTER>

VERBS and NOUNS


COLOSSUS REGULAR VERBS (00-39 decimal)
This is a dap ted from the A pollo 2 04 a cciden t report po sted on mu ltiple web sites by Richard F. Drushel. The information has been changed as necessary to be consistent with usage in COLOSSUS 249.
Verb | Code | | 01 | | | 02 | | | 03 | | | 04 | | | 05 | | | 06 | | | | | | | | 07 | | | | | | | | | | | | | | | 08 | | 09 | | 10 | | 11 | | | 12 | | | 13 | | | 14 | | | | 15 | | | | Description Display octal comp 1 in R1 Display octal comp 2 in R2 Display octal comp 3 in R3 Display octal comp 1,2 in R1,R2 Display octal comp 1,2,3 in R1,R2,R3 Display decimal in R1 or R1,R2 or R1,R2,R3 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Remarks Performs octal display of data on REGISTER 1. Performs octal display of data on REGISTER 1. Performs octal display of data on REGISTER 1. Performs octal display of data on REGISTER 1 and REGISTER 2 Performs octal display of data on REGISTER 1, REGISTER 2, and REGISTER 3. Performs decimal display of data on appropriate registers. The scale factors, types of scale factor routines, and component information are stored within the machine for each noun which it is required to display in decimal. Performs a double precision decimal display of data on REGISTER 1 and REGISTER 2. It does no scale factoring. It merely performs a 10character, fractional decimal conversion of two consecutive, erasable registers, using REGISTER 1 and REGISTER 2. The sign is placed in the REGISTER 1 sign position with the REGISTER 2 sign position remaining blank. It cannot be used with mixed nouns. Its intended use is primarily with "machine address to be specified" nouns.

Display DP decimal in R1,R2

(Spare) (Spare) (Spare) Monitor octal comp 1 in R1 Monitor octal comp 2 in R2 Monitor octal comp 3 in R3 Monitor octal comp 1,2 in R1,R2 Monitor octal comp 1,2,3 in R1,R2,R3

Performs octal display of updated data every 1/2 second on REGISTER 1. Performs octal display of updated data every 1/2 second on REGISTER 1. Performs octal display of updated data every 1/2 second on REGISTER 1. Performs octal display of updated data every 1/2 second on REGISTER 1 and REGISTER 2. Performs octal display of updated data every 1/2 second on REGISTER 1, REGISTER 2, and REGISTER 3.

16

17

18 19 20 21

22

23

24

25

26 27

28 29 30

31

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Monitor decimal in R1 or R1,R2, or R1,R2,R3 Monitor DP decimal in R1,R2

(Spare) (Spare) (Spare) Load component 1 into R1

Load component 2 into R2

Load component 3 into R3

Load component 1,2 into R1,R2

Load component 1,2,3 into R1,R2,R3

(Spare) Display fixed memory

(Spare) (Spare) Request EXECUTIVE (Used only during ground checkout.)

Request WAITLIST

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Performs decimal display of updated data every 1/2 second on appropriate registers. Performs double precision display of decimal data on REGISTER 1 and REGISTER 2. No scale factoring is performed. Provides 10-character, fractional decimal conversion of two consecutive erasable registers. The sign is placed in the sign-bit position of REGISTER 1. REGISTER 2 sign bit is blank.

Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 1. Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 2. Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 3. Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 1 and REGISTER 2. Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 1, REGISTER 2, and REGISTER 3.

This verb is included to permit displaying the contents of fixed memory in any bank. Its intended use is for checking program ropes and the BANK positions of program ropes.

Enters request to executive routine for any machine address with priority involved. This verb assumes that the desired priority has been loaded into bits 10-14 of the prio/delay register (noun 26). This verb is used with the noun, "machine address to be specified". The complete address of the desired location is then keyed in. (Refer to "Machine address to be specified" in paragraph on Verb/Noun Formats.) Enters request to "waitlist routine"

| (Used only during ground | for any machine address with delay | checkout.) | involved. This verb assumes that the | | desired number of 10-millisecond units | | of delay has been loaded into the low | | order bits of the prio/delay register | | (noun 26). This verb is used with the | | "machine address to be specified" noun. | | The complete address of the desired | | location is then keyed in. (Refer to | | "Machine address to be specified" in | | paragraph on Verb/Noun Formats.) | | 32 | Recycle | | | 33 | Proceed (without data) | Informs routine requesting data that | | the operator chooses not to load | | fresh data, but wishes the routine to | | continue as best it can with old data. | | Final decision for what action should | | be taken is left to the requesting | | routine. | | 34 | Terminate | Informs routine requesting data to be | | loaded that the operator chooses not | | to load fresh data and wishes the | | routine to terminate. Final decision | | for what action should be taken is | | left to the requesting routine. If | | monitor is on, it is turned off. | | 35 | Test lights | | | 36 | Request fresh start | Initializes the program control | | software and the keyboard and display | | system program. | | 37 | Change program (major mode) | Change to new major mode. (Refer to | | "Change major mode" in paragraph on | | Verb/Noun Formats.) | | ;--------------------------------------------------------------------------

COLOSSUS EXTENDED VERBS (40-99 decimal)


Not im plem ented. U se of th ese v erbs trigg ers th e 'check fail ' indic ator.

COLOSSUS NORMAL NOUNS (00-39 decimal)


This is a dap ted from the A pollo 2 04 a cciden t report po sted on mu ltiple web sites by Richard F. Drushel. The information has been changed as necessary to be consistent with usage in COLOSSUS 249.
Noun | Code | | 01 | | | | 02 | | | | 03 | | | Description Specify machine address (frac) | | | | | | | | | | | | | | Scale/Units .XXXXX FRAC .XXXXX FRAC .XXXXX FRAC XXXXX INTEGER XXXXX INTEGER XXXXX INTEGER XXX.XX DEG XXX.XX DEG XXX.XX DEG

Specify machine address (whole)

Specify machine address (degree)

04 05 06 07 08 09

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

27 28 29 30 31 32 33 34 35 36

37

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

(Spare) (Spare) (Spare) (Spare) (Spare) Alarm codes

(Spare) (Spare) (Spare) (Spare) (Spare) Increment address (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) Prio/delay, address

(Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) (Spare) Time of CMC clock: REGISTER 1 REGISTER 2 REGISTER 3 (Spare)

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

OCT OCT OCT

OCT

OCT (prio/delay) OCT (14-bit CADR) (not used)

00XXX. hours 000XX. minutes 0XX.XX seconds

| | | (Spare) | | | 39 | (Spare) | | | ;-------------------------------------------------------------------------38

COLOSSUS MIXED NOUNS (40-99 decimal)


Not implemented.

Flight software assembler listing


B l o c k I A p o l l o Guidance Computer (AGC4) asse mbler version 1.6 for EPROM F i r s t p a s s : g enerate symbol table. S e c o n d p a s s : generate object code. ;================= ========================================================= ; AGC (file:agc.as m) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 6/7/20 02 ; ; PURPOSE: ; AGC Block I demo nstration. Includes most of the AGC operating system: ; WAITLIST, EXEC, PINBALL (DSKY routines), NOUN tables, VERB tables, ; bank intercommun ication routines, the KEY, T3, and T4 interrupt handlers, ; and some dual pr ecision (DP) math routines. ; ; The interpreter is not currently implemented. ; ; Where available, the source is from the Apollo 8 command module computer (CMC ) ; load (called COL OSSUS). In cases where COLOSSUS source is not available, ; functionally equ ivalent code was constructed using COLOSSUS calling and retur n ; parameters and a ccording to specifications in the technical reports given bel o w . ; ; OPERATION: ; TBD. ; ; ERRATA: ; - Adapted for th e AGC4R assembler. The assembler directives and syntax ; differ somewhat from the original AGC assembler. ; - some of the or iginal source was missing from the COLOSSUS listing and ; had to be revers e engineered. Those portions probably differ somewhat ; from the origina l code in implementation, but should be functionally ; identical. ; - because the CO LOSSUS source is for a block II AGC, but the AGC ; implemented here is block I, about 5% of COLOSSUS had to be translated ; to equivalent bl ock I code. ; ; SOURCES: ; Information on t he Block I architecture: instruction set, instruction ; sequences, regis ters, register transfers, control pulses, memory and ; memory addressin g, I/O assignments, interrupts, and involuntary counters ; was obtained fro m: ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393, ; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; ; Supplementary AG C hardware information was obtained from: ; ; R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary ; MOD 3C Programmer's Manual", E-1077, MIT Instrumentation ; Laboratory, Cambridge, MA, Nov. 1961. ; ; B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", ; E-2052, MIT Instrumentation Laboratory, Cambridge, ; MA, Jan. 1967. ; ; E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer ; Subsystem", R-700, MIT Charles Stark Draper Laboratory, ; Cambridge, MA, Aug. 1972. ; ; A. Hopkins, "Guidance Computer Design, Part VI", source unknown. ; ; E, C. Hall, "Journey to the Moon: The History of the Apollo ; Guidance Computer", AIAA, Reston VA, 1996. ; ; AGC software inf ormation was obtained from: ; ; AGC Block II COLOSSUS rev 249 assembly listing, Oct 28, 1968. (A ; listing of the 1st 50% of the build. It encludes the entire ; eraseable memory, restart initialization, T4RUPT, and the ; entire set of DSKY routines. About 5% of instructions ; had to be converted from Block II to Block I). ; ; A. I. Green and J. J. Rocchio, "Keyboard and Display System Program ; for AGC (Program Sunrise)", E-1574, MIT Instrumentation ; Laboratory, Cambridge, MA, Aug. 1964. Contains detailed ; flowcharts and design materials for the DSKY software. ; ; A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description ; for the Apollo Guidance Computer (AGC4)", R-393,

; MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. ; Contains the software interfaces for EXEC and WAITLIST, and ; portions of the dual precision (DP) math library. ; ;================= ========================================================= INC L doc.asm ;================= ========================================================= ; AGC documentatio n (file:doc.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 06/01/ 2002 ; ; PURPOSE: ; Documents AGC op s source code. ;================= =========================================================

;----------------- --------------------------------------------------------; DSKY OPERATION ( examples) ; ; verb/noun (V/N) flash: When the verb and noun indicators flash ; at 1Hz, the DSKY is waiting for keyboard input. ; ; ; Display elapsed time from the AGC clock: ; <VERB> <0> <6> <NOUN> <3> <6> <ENTER> ; ; Test display lig hts ; a) <VERB> <3> <5> <ENTER> ; b) all DSKY lamps and display segments illuminate for 5 sec. ; c) after 5 sec, the DSKY lamps extinguish ; ; Load component 1 for dataset at octal address 50 with octal 123 ; a) <VERB> <2> <1> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) verb/noun display flash continues; waiting for data ; e) <1> <2> <3> <ENTER> ; f) octal word from R1 is loaded at address 50, ; ; Display componen t 1 of dataset at octal address 50: ; a) <VERB> <0> <1> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) octal word from address 50 is displayed in R1 ; ; Load 3 component dataset at octal address 50 with octal values ; 123,456,701 ; a) <VERB> <2> <5> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) verb/noun display flash continues; waiting for data ; e) <1> <2> <3> <ENTER> ; f) <4> <5> <6> <ENTER> ; g) <7> <0> <1> <ENTER> ; h) octal word from R1 is loaded at address 50, ; octal word from R2 is loaded at address 51, ; octal word from R3 is loaded at address 52 ; ; Display 3 compon ent dataset beginning at address 50: ; a) <VERB> <0> <5> <NOUN> <0> <1> <ENTER> ; b) verb/noun display flashes; waiting for address ; c) <5> <0> <ENTER> ; d) octal word from address 50 is displayed in R1, ; octal word from address 51 is displayed in R2, ; octal word from address 52 is displayed in R3 ; ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; COLOSSUS REGULAR VERBS (00-39 decimal) ; ; This is adapted from the Apollo 204 accident report posted on multiple ; web sites by Ric hard F. Drushel. The information has been changed as ; necessary to be consistent with usage in COLOSSUS. ; ; ; Verb | | ; Code | Description | Remarks ; | | ; 01 | Display octal comp 1 in R1 | Performs octal display of data on ; | | REGISTER 1. ; | | ; 02 | Display octal comp 2 in R2 | Performs octal display of data on

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

03

04

05

06

07

08 09 10 11

12

13

14

15

16

17

18 19 20 21

22

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Display octal comp 3 in R3

Display octal comp 1,2 in R1,R2 Display octal comp 1,2,3 in R1,R2 ,R3 Display decimal in R1 or R1,R2 or R1,R2,R3

Display DP decimal in R1,R2

(Spare) (Spare) (Spare) Monitor octal comp 1 in R1

Monitor octal comp 2 in R2

Monitor octal comp 3 in R3

Monitor octal comp 1,2 in R1,R2

Monitor octal comp 1,2,3 in R1,R2 ,R3

Monitor decimal in R1 or R1,R2, o r R1,R2,R3

Monitor DP decimal in R1,R2

(Spare) (Spare) (Spare) Load com ponent 1 into R1

Load com ponent 2 into R2

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

REGISTER 1. Performs octal display of data on REGISTER 1. Performs octal display of data on REGISTER 1 and REGISTER 2 Performs octal display of data on REGISTER 1, REGISTER 2, and REGISTER 3 . Performs decimal display of data on appropriate registers. The scale factors, types of scale factor routines, and component information are stored within the machine for eac h noun which it is required to display in decimal. Performs a double precision decimal display of data on REGISTER 1 and REGISTER 2. It does no scale factoring. It merely performs a 10character, fractional decimal conversion of two consecutive, erasab l e registers, using REGISTER 1 and REGISTER 2. The sign is placed in th e REGISTER 1 sign position with the REGISTER 2 sign position remaining blank. It cannot be used with mixed nouns. Its intended use is primarily with "machine address to be specified " nouns.

Performs octal display of updated dat a every 1/2 second on REGISTER 1. Performs octal display of updated dat a every 1/2 second on REGISTER 1. Performs octal display of updated dat a every 1/2 second on REGISTER 1. Performs octal display of updated dat a every 1/2 second on REGISTER 1 and REGISTER 2. Performs octal display of updated dat a every 1/2 second on REGISTER 1, REGISTER 2, and REGISTER 3. Performs decimal display of updated data every 1/2 second on appropriate registers. Performs double precision display of decimal data on REGISTER 1 and REGISTER 2. No scale factoring is performed. Provides 10-character, fractional decimal conversion of two consecutive erasable registers. The sign is placed in the sign-bit position of REGISTER 1. REGISTER 2 sign bit is blank.

Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER 1. Performs data loading. Octal quantities are unsigned. Decimal quantities are preceded by + or sign. Data is displayed on REGISTER

; | | 2. ; | | ; 23 | Load com ponent 3 into R3 | Performs data loading. Octal ; | | quantities are unsigned. Decimal ; | | quantities are preceded by + or ; | | sign. Data is displayed on REGISTER ; | | 3. ; | | ; 24 | Load com ponent 1,2 into | Performs data loading. Octal ; | R1,R2 | quantities are unsigned. Decimal ; | | quantities are preceded by + or ; | | sign. Data is displayed on REGISTER ; | | 1 and REGISTER 2. ; | | ; 25 | Load com ponent 1,2,3 into | Performs data loading. Octal ; | R1,R2,R3 | quantities are unsigned. Decimal ; | | quantities are preceded by + or ; | | sign. Data is displayed on REGISTER ; | | 1, REGISTER 2, and REGISTER 3. ; | | ; 26 | (Spare) | ; | | ; 27 | Display fixed memory | This verb is included to permit ; | | displaying the contents of fixed ; | | memory in any bank. Its intended use ; | | is for checking program ropes and the ; | | BANK positions of program ropes. ; | | ; 28 | (Spare) | ; | | ; 29 | (Spare) | ; | | ; 30 | Request EXECUTIVE | Enters request to executive routine ; | (Used on ly during ground | for any machine address with priority ; | checkout .) | involved. This verb assumes that the ; | | desired priority has been loaded into ; | | bits 10-14 of the prio/delay register ; | | (noun 26). This verb is used with th e ; | | noun, "machine address to be ; | | specified". The complete address of ; | | the desired location is then keyed in . ; | | (Refer to "Machine address to be ; | | specified" in paragraph on Verb/Noun ; | | Formats.) ; | | ; 31 | Request WAITLIST | Enters request to "waitlist routine" ; | (Used on ly during ground | for any machine address with delay ; | checkout .) | involved. This verb assumes that the ; | | desired number of 10-millisecond unit s ; | | of delay has been loaded into the low ; | | order bits of the prio/delay register ; | | (noun 26). This verb is used with th e ; | | "machine address to be specified" nou n . ; | | The complete address of the desired ; | | location is then keyed in. (Refer to ; | | "Machine address to be specified" in ; | | paragraph on Verb/Noun Formats.) ; | | ; 32 | Recycle | ; | | ; 33 | Proceed (without data) | Informs routine requesting data that ; | | the operator chooses not to load ; | | fresh data, but wishes the routine to ; | | continue as best it can with old data . ; | | Final decision for what action should ; | | be taken is left to the requesting ; | | routine. ; | | ; 34 | Terminat e | Informs routine requesting data to be ; | | loaded that the operator chooses not ; | | to load fresh data and wishes the ; | | routine to terminate. Final decision ; | | for what action should be taken is ; | | left to the requesting routine. If ; | | monitor is on, it is turned off. ; | | ; 35 | Test lig hts | ; | | ; 36 | Request fresh start | Initializes the program control ; | | software and the keyboard and display ; | | system program. ; | | ; 37 | Change p rogram (major mode) | Change to new major mode. (Refer to ; | | "Change major mode" in paragraph on ; | | Verb/Noun Formats.) ; | | ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; COLOSSUS EXTENDE D VERBS (40-99 decimal) ; ; Not implemented. Use of these verbs triggers the 'check fail' indicator. ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; COLOSSUS NORMAL NOUNS (00-39 decimal) ; ; This is adapted from the Apollo 204 accident report posted on multiple ; web sites by Ric hard F. Drushel. The information has been changed as ; necessary to be consistent with usage in COLOSSUS. ; ; ; Noun | | ; Code | Description | Scale/Units ; | | ; 01 | Specify machine address (frac) | .XXXXX FRAC ; | | .XXXXX FRAC ; | | .XXXXX FRAC ; | | ; 02 | Specify machine address (whole) | XXXXX INTEGER ; | | XXXXX INTEGER ; | | XXXXX INTEGER ; | | ; 03 | Specify machine address (degree) | XXX.XX DEG ; | | XXX.XX DEG ; | | XXX.XX DEG ; | | ; 04 | (Spare) | ; | | ; 05 | (Spare) | ; | | ; 06 | (Spare) | ; | | ; 07 | (Spare) | ; | | ; 08 | (Spare) | ; | | ; 09 | Alarm co des | OCT ; | | OCT ; | | OCT ; | | ; 10 | (Spare) | ; | | ; 11 | (Spare) | ; | | ; 12 | (Spare) | ; | | ; 13 | (Spare) | ; | | ; 14 | (Spare) | ; | | ; 15 | Incremen t address | OCT ; | | ; | | ; 16 | (Spare) | ; | | ; 17 | (Spare) | ; | | ; 18 | (Spare) | ; | | ; 19 | (Spare) | ; | | ; 20 | (Spare) | ; | | ; 21 | (Spare) | ; | | ; 22 | (Spare) | ; | | ; 23 | (Spare) | ; | | ; 24 | (Spare) | ; | | ; 25 | (Spare) | ; | | ; 26 | Prio/del ay, address | OCT (prio/delay) ; | | OCT (14-bit CADR) ; | | (not used) ; | | ; 27 | (Spare) | ; | |

; 28 | (Spare) | ; | | ; 29 | (Spare) | ; | | ; 30 | (Spare) | ; | | ; 31 | (Spare) | ; | | ; 32 | (Spare) | ; | | ; 33 | (Spare) | ; | | ; 34 | (Spare) | ; | | ; 35 | (Spare) | ; | | ; 36 | Time of CMC clock: | ; | REGIST ER 1 | 00XXX. hours ; | REGIST ER 2 | 000XX. minutes ; | REGIST ER 3 | 0XX.XX seconds ; | | ; 37 | (Spare) | ; | | ; 38 | (Spare) | ; | | ; 39 | (Spare) | ; | | ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; COLOSSUS MIXED N OUNS (40-99 decimal) ; ; Not implemented. ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; AGC ADDRESS ASSI GNMENTS ; ; Central Register s ; ; 000000 A accumulator ; 000001 Q subroutine return address ; 000002 Z program counter ; 000003 LP lower product register ; ; Input Registers ; ; 000004 IN0 ; 000005 IN1 ; 000006 IN2 ; 000007 IN3 ; ; Output Registers ; ; 000010 OUT0 ; 000011 OUT1 ; 000012 OUT2 ; 000013 OUT3 ; 000014 OUT4 ; ; Memory Bank Sele ct ; ; 000015 BANK ; ; Interrupt Contro l ; ; 000016 RELINT re-enable interrupts ; 000017 INHINT inhibit interrupts ; ; Editing Register s ; ; 000020 CYR cycle right ; 000021 SR shift rRight ; 000022 CYL cycle left ; 000023 SL shift left ; ; Interrupt Storag e Area ; ; 000024 ZRUPT save program counter (Z) ; 000025 BRUPT save B register ; 000026 ARUPT save accumulator (A) ; 000027 QRUPT save Q register ;

; 000030 - 000033 NOT USED ; ; Involuntary Coun ters ; ; 000034 OVCTR arithmetic overflow counter ; 000035 TIME2 AGC clock (high) ; 000036 TIME1 AGC clock (low) ; 000037 TIME3 WAITLIST (T3) timer ; 000040 TIME4 DISPLAY (T4) timer ; ; Involuntary Coun ters -- currently unused ; ; 000041 - 000056 NOT USED ; ; Eraseable Memory ; ; 000057 - 001777 ; ; Start of fixed m emory ; ; 002000 GOPROG AGC (re)start vector ; ; 002004 T3RUPT interrupt vector for TIME3 (T3RUPT) ; 020010 ERRUPT interrupt vector ; 020014 DSRUPT interrupt vector for DSRUPT (T4RUPT) ; 020020 KEYRUPT interrupt vector for keyboard ; 020024 UPRUPT interrupt vector for uplink ;----------------- ---------------------------------------------------------

;----------------- --------------------------------------------------------; AGC TABLES (name , file, description) ; ; Keyboard/display ; CHARIN2 bank40_1.asm keyboard character table ; INRELTAB bank40_1.asm DSKY register/display table map ; DSPTAB dsky_e.asm display table for DSKY ; ; Verbs: ; VERBTAB bank41_1.asm regular verb routines (00-39) ; ; Nouns: ; NNADTAB bank42_3.asm noun address table (00-99) ; NNTYPTAB bank42_3.asm noun type table (00-99) ; SFINTAB bank42_3.asm noun input scale factor select ; SFOUTAB bank42_3.asm nout output scale factor select ; IDADDTAB bank42_3.asm mixed noun address table (40-99) ; RUTMXTAB bank42_3.asm mixed noun scale factor routine (40-9 9 ) ; ; Noun scale facto r routines: ; SFOUTABR bank41_1.asm scale factor output routines ; SFINTABR bank41_2.asm scale factor input routines ; ; Major Modes: ; FCADRMM bank04_1.asm entry points for MM jobs ; EPREMM1 bank04_1,asm priorities for MM jobs ;----------------- ---------------------------------------------------------

; ERASEABLE MEMORY DECLARATIONS ORG BANK0 ; immediately following counters INC L waitlist_e.asm ; WAITLIST variables ;================= ========================================================= ; WAITLIST (file:w aitlist_e.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 11/15/ 2001 ; ; PURPOSE: ; Eraseable memory variables and structures for the WAITLIST. See the ; WAITLIST source code file for more information. ;================= =========================================================

MAXTASK MAXVAL MAXDELAY MAXTIMEOUT

EQU EQU EQU EQU

7 ; max number of tasks %037777 ; largest pos 15-bit int (+16383 dec) 12000 ; 120 seconds (in .01 sec ticks) MAXVAL-MAXDELAY+1 ; TIME3 setting for MAXDELAY

; task delta t: nu mber of 10 mSec ticks until timeout. ; i.e.: 0=timeou t, 1=10mS until timeout, 2=20mS until timeout... ; maximum time d elay is 120 (decimal) seconds. ;

; If a task record is empty (unused), the address is always set to ; zero and the tim e is set to MAXDELAY. ; task record stru cture TSKTIME EQU 0 TSKADDR EQU 1 TRECSZ EQU 2

; offset to task delta time ; offset to 14-bit task address ; size of task record (words)

00057 00060 00061 00062 00063 00064 00065 00066 00067 00070 00071 00072 00073 00074

0057 0060 0061 0062 0063 0064 0065 0066 0067 0070 0071 0072 0073 0074

00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1

; Array of all tas k records WL_taskList EQU * DS 0 DS 0 DS DS DS DS DS DS DS DS DS DS DS DS 0 0 0 0 0 0 0 0 0 0 0 0

; record 0

; record 1

; record 2

; record 3

; record 4

; record 5

; record 6

00075 00076 00077 00100 00101 00102 00103 00104 00105 00106 00107 00110 00111 00112 00113 00114 00115 00116 00117 00120 00121 00122 00123 00124 00125 00126 00127

0075 0076 0077 0100 0101 0102 0103 0104 0105 0106 0107 0110 0111 0112 0113 0114 0115 0116 0117 0120 0121 0122 0123 0124 0125 0126 0127

00000 1 WL_IN_saveQ 00000 1 WL_IN_taskPtr 00000 1 WL_IN_loopCnt 00000 00000 00000 00000 00000 1 1 1 1 1 WL_AT_saveQ WL_AT_taskPtr WL_AT_newTime WL_AT_timeLeft WL_AT_loopCnt

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

; return address ; points to task rec in list ; loop counter ; ; ; ; ; return address points to task rec in list time to be inserted time remaining until timeout loop counter

00000 1 WL_T3_saveQ 00000 1 WL_T3_oldBank 00000 00000 00000 00000 1 1 1 1 WL_ST_saveQ WL_ST_taskPtr WL_ST_newTime WL_ST_loopCnt

; return address ; current bank ; ; ; ; return address points to task rec in list time-out time loop counter

00000 1 WL_RT_saveQ 00000 1 WL_RT_runAddr 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 WL_RM_saveQ WL_RM_taskPtr WL_RM_taskPtr2 WL_RM_loopCnt WL_RM_retval WL_IS_newTime WL_IS_newAddr WL_IS_saveQ WL_IS_taskPtr WL_IS_taskPtr2 WL_IS_loopCnt

; return address ; address of task to run ; ; ; ; ; ; ; ; ; ; ; return address points to task rec in list points to task rec behind taskPtr loop counter tmp store for return value INPUT: time to INPUT: address return address points to task points to task loop counter be inserted to be inserted rec in list rec ahead of taskPtr

INC L exec_e.asm ; EXEC variables ;================= ========================================================= ; EXEC (file:exec_ e.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 04/26/ 2002 ; ; PURPOSE: ; Eraseable memory variables and structures for the EXEX. See the EXEC ; source code file for more information. ; ; The COLOSSUS ver sion of this is on p. 70. ; ; ERRATA: The curr ent version of the EXEC does not set the BANKSET parameter. ; Instead, it stor es the 14-bit CADR in LOC. Also, the JOBPRIOBASE field ; has been added. ;================= =========================================================

MAXJOBS JRECSZ

EQU EQU

7 13

; max number jobs (not incl current job) ; size of job record (words)

; (COLOSSUS, p. 70 ) ; dynamically allo cated core sets for EXEC jobs (8 sets) ; record for curre nt (running) job ; Job priority: 0= no job, 1=lowest priority job, 2=... EX_currentJob EQU *

MPAC 00130 00131 00132 00133 00134 00135 00136 00137 00140 00141 00142 00143 00144 0130 0131 0132 0133 0134 0135 0136 0137 0140 0141 0142 0143 0144 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 1 MODE LOC BANKSET PUSHLOC PRIORITY JOBPRIOBASE

EQU DS DS DS DS DS DS DS DS DS DS DS DS DS

* 0 0 0 0 0 0 0 0 0 0 0 0 0

; multi-purpose accumulator

; ; ; ; ; ;

+1 for TP, +0 for DP, or -1 for vector location associated with job usually contains bank setting word of packed interpretive parameters priority of present job and work area nominal job priority

; records for addi tional jobs waiting to run JREC0 EQU ORG EQU ORG EQU ORG EQU ORG EQU ORG EQU ORG EQU ORG * JREC0+JRECSZ * JREC1+JRECSZ * JREC2+JRECSZ * JREC3+JRECSZ * JREC4+JRECSZ * JREC5+JRECSZ * JREC6+JRECSZ

JREC1

JREC2

JREC3

JREC4

JREC5

JREC6

; ; ; ; ;

sorted list of j obs to run. The list with the highest priority job at the entry on the lis t is a word index to relative to 'EX_ currentJob', but the list. EQU ORG

is sorted by job priority top of the list. Each a job record; the indexes are current job is not on the

EX_jobList

* EX_jobList+MAXJOBS

LOCCTR

EQU

EX_jobList

; index to next job record

00307 00310 00311 00312 00313 00314 00315 00316 00317 00320 00321 00322 00323 00324

0307 0310 0311 0312 0313 0314 0315 0316 0317 0320 0321 0322 0323 0324

CHGJOB KEEPJOB 00000 1 newJob 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 1 EX_JW_saveQ EX_JW_loopCnt EX_JW_CADR EX_JW_foundit EX_JW_jobPtr EX_JW_jobPtr2 EX_JW_fndIndx EX_AJ_saveQ EX_AJ_loopCnt EX_AJ_jobPrio EX_AJ_jobPtr EX_AJ_field EX_AJ_findx

EQU EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

; change jobs at next opportunity ; keep the same job ; change flag (set to CHGJOB or KEEPJOB) ; ; ; ; ; ; ; ; ; ; ; ; ; return address loop counter address of job to wake 0=job not found, 1=found points to job rec in list points to job rec ahead of jobPtr index to awoken record return address loop counter priority of new job initialized to EX_jobList at startup index to field from start of record total index to field

00325 00326 00327 00330 00331 00332 00333 00334 00335 00336 00337 00340 00341 00342 00343 00344 00345 00346 00347 00350 00351 00352 00353 00354

0325 0326 0327 0330 0331 0332 0333 0334 0335 0336 0337 0340 0341 0342 0343 0344 0345 0346 0347 0350 0351 0352 0353 0354

00000 00000 00000 00000 00000 00000

1 1 1 1 1 1

EX_IN_saveQ EX_IN_loopCnt EX_IN_jobPtr EX_IN_recIndex EX_IN_field EX_IN_findx

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

; ; ; ; ; ;

return address loop counter points to job rec in list record index init counter index to field from start of record total index to field

00000 1 EX_MN_runAddr 00000 1 EX_MN_field 00000 1 EX_MN_findx 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 EX_RM_saveQ EX_RM_jobPtr EX_RM_jobPtr2 EX_RM_savePtr EX_RM_loopCnt EX_RM_retval EX_RM_field EX_RM_findx EX_IS_newPrio EX_IS_newPrioB EX_IS_newLoc EX_IS_saveQ EX_IS_jobPtr EX_IS_jobPtr2 EX_IS_loopCnt

; address of job to run ; index to field from start of record ; total index to field ; ; ; ; ; ; ; ; return address points to job rec in list points to job rec behind jobPtr tmp store for index taken off list loop counter tmp store for return value index to field from start of record total index to field

DS 0 ; INPUT: priority to be inserted DS 0 ; INPUT: nominal priority to be inserted DS 0 ; INPUT: address to be inserted DS 0 ; return address DS 0 ; points to job rec in list DS 0 ; points to job rec ahead of jobPtr DS 0 ; loop counter INC L dsky_e.asm ; DSKY variables ;================= ========================================================= ; DSKY (file:dsky_ e.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 12/14/ 2001 ; ; PURPOSE: ; Eraseable memory variables and structures for the DSKY. See the EXEC ; source code file for more information. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;================= ========================================================= DS 0

00355

0355

00000 1 FLAGWRD5

; GENERAL ERASABLE ASSIGNMENTS ; (COLOSSUS, p. 66 )

; interrupt tempor ary storage pool ; (ITEMP1 through RUPTREG4) 00356 0356 00000 1 ITEMP1 WAITEXIT EXECTEM1 00000 1 ITEMP2 WAITBANK EXECTEM2 00000 1 ITEMP3 RUPTSTOR WAITADR NEWPRIO 00000 1 ITEMP4 ;LOCCTR WAITTEMP 00000 1 ITEMP5 NEWLOC 00000 1 ITEMP6 NEWLOCP1 00000 00000 00000 00000 00000 1 1 1 1 1 NEWJOB RUPTREG1 RUPTREG2 RUPTREG3 RUPTREG4 KEYTEMP1 DSRUPTEM DS EQU EQU DS EQU EQU DS EQU EQU EQU DS EQU EQU DS EQU DS EQU DS DS DS DS DS EQU EQU 0 ITEMP1 ITEMP1 0 ITEMP2 ITEMP2 0 ITEMP3 ITEMP3 ITEMP3 0 ITEMP4 ITEMP4 0 ITEMP5 0 ITEMP6 0 0 0 0 0 RUPTREG4 RUPTREG4 ; moved to EXEC

00357

0357

00360

0360

00361

0361

00362

0362

00363

0363

; DP address ; COLOSSUS: must be at loc 68 due to wir i n g

00364 00365 00366 00367 00370

0364 0365 0366 0367 0370

; FLAGWORD reserva tions

STATE 00371 00372 00373 00374 00375 00376 00377 00400 00401 00402 00403 00404 0371 0372 0373 0374 0375 0376 0377 0400 0401 0402 0403 0404 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 FLAGFILL 00405 00406 00407 00410 0405 0406 0407 0410 00000 00000 00000 00000 1 1 1 1

EQU DS DS DS DS DS DS DS DS DS DS DS DS EQU DS DS DS DS

* 0 0 0 0 0 0 0 0 0 0 0 0 * 0 0 0 0

; 12 words

; space for future flags

; pad load for DAP s ; (COLOSSUS, p. 67 ) EMDOT ; exit for VB3 STATEXIT EQU FLAGFILL+2 EQU FLAGFILL

; EXEC temporaries which may be used between CCS NEWJOBS. ; (INTB15P through RUPTMXM) 00411 0411 00000 1 INTB15P DSEXIT EXITEM BLANKRET 00000 1 INTBIT15 WRDRET WDRET DECRET _2122REG DS EQU EQU EQU DS EQU EQU EQU EQU 0 INTB15P INTB15P INTB15P 0 INTBIT15 INTBIT15 INTBIT15 INTBIT15 ; ; ; ; ; ; ; ; ; reflects 15th bit of indexable address e s return for DSPIN return for scale factor routine select return for 2BLANK similar to above return for 5BLANK return for DSPWD return for PUTCOM (dec load) temp for CHARIN

00412

0412

; The registers be tween ADDRWD and PRIORITY must stay in the following order ; for interpretive trace. 00413 00414 0413 0414 00000 1 ADDRWD 00000 1 POLISH UPDATRET CHAR ERCNT DECOUNT 00000 1 FIXLOC 00000 1 OVFIND VBUF 00417 00420 00421 00422 00423 00424 0417 0420 0421 0422 0423 0424 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 SGNON NOUNTEM DISTEM DECTEM DS DS EQU EQU EQU EQU DS DS EQU DS DS DS DS DS DS EQU EQU EQU EQU 0 0 POLISH POLISH POLISH POLISH 0 0 * 0 0 0 0 0 0 VBUF VBUF VBUF VBUF VBUF+1 VBUF+1 VBUF+1 VBUF+1 ; ; ; ; ; ; 12 bit interpretive operand subaddress holds CADR made from POLISH address return for UPDATNN, UPDATVB temp for CHARIN counter for error light reset counter for scaling and display (dec)

00415 00416

0415 0416

; work area address ; set non-zero on overflow ; temporary storage used for vectors

; ; ; ; ; ; ; ;

temp for +,- on counter for MIXNOUN fetch counter for octal display verbs counter for fetch (dec display verbs) temp for +,- off temp for NVSUB storage for SF const hi part(=SFTEMP2- 1 ) temp for load of hrs, min, sec

SGNOFF EQU NVTEMP EQU SFTEMP1 EQU HITEMIN EQU ; must = LOWTEMIN- 1 CODE EQU SFTEMP2 EQU LOWTEMIN EQU ; must = HITEMIN+1 ; (COLOSSUS, p. 68 ) MIXTEMP SIGNRET EQU EQU

VBUF+2 VBUF+2 VBUF+2

; for DSPIN ; storage for SF const low part(=SFTEMP1 + 1 ) ; temp for load of hrs, min, sec

VBUF+3 VBUF+3

; for MIXNOUN data ; return for +,- on

; Also, MIXTEMP+1 = VBUF+4, MIXTEMP+2 = VBUF+5 BUF EQU * ; temporary scalar storage

00425 00426 00427 00430 00431

0425 0426 0427 0430 0431

00000 1 00000 1 00000 1 00000 1 BUF2 00000 1 INDEXLOC SWWORD SWBIT 00000 1 MPTEMP DMPNTEMP 00000 1 DOTINC DVSIGN ESCAPE ENTRET 00000 1 DOTRET DVNORMCT ESCAPE2 WDCNT INREL 00000 1 MATINC MAXDVSW POLYCNT DSPMMTEM MIXBR 00000 1 TEM1 POLYRET DSREL 00000 1 TEM2 DSMAG IDADDTEM 00000 1 TEM3 COUNT 00000 1 TEM4 LSTPTR RELRET FREERET DSPWDRET SEPSCRET SEPMNRET 00000 1 TEM5 NOUNADD

DS DS DS DS DS EQU EQU EQU DS EQU DS EQU EQU EQU DS EQU EQU EQU EQU DS EQU EQU EQU EQU DS EQU EQU DS EQU EQU DS EQU DS EQU EQU EQU EQU EQU EQU DS EQU

0 0 0 0 0 BUF BUF BUF+1 0 MPTEMP 0 DOTINC DOTINC DOTINC 0 DOTRET DOTRET DOTRET DOTRET 0 MATINC MATINC MATINC MATINC 0 TEM1 TEM1 0 TEM2 TEM2 0 TEM3 0 TEM4 TEM4 TEM4 TEM4 TEM4 TEM4 0 TEM5 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; contains address of specified index address of switch word switch bit within switch word temporary used in multiply and shift DMPSUB temporary component increment for DOT subroutine determines sign of DDV result used in arcsin/arccos exit from enter return from DOT subroutine dividend normalization count in DDV alternate arcsin/arccos switch char counter for DSPWD input buffer selector (X,Y,Z REG) vector increment in MXV and VXM +0 if DP quotient is near one - else - 1 polynomial loop counter DSPCOUNT save for DSPMM indicator for mixed or normal noun

00432 00433

0432 0433

00434

0434

00435

0435

00436

0436

; EXEC temp ; rel address for DSPIN ; EXEC temp ; magnitude store for DSPIN ; mixnoun indirect address store ; EXEC temp ; for DSPIN ; ; ; ; ; ; ; EXEC temp list pointer for GRABUSY return for RELDSP return for FREEDSP return for DSPSIGN return for SEPSEC return for SEPMIN

00437

0437

00440

0440

00441

0441

00442

0442

; EXEC temp ; temp storage for noun address

; (COLOSSUS, p. 69 ) 00443 00444 00445 00446 00447 00450 0443 0444 0445 0446 0447 0450 00000 1 NNADTEM DS 0 00000 1 NNTYPTEM DS 0 00000 1 IDAD1TEM DS 0 ; must - IDAD2TEM- 1, = IDAD3TEM-2 00000 1 IDAD2TEM DS 0 ; must - IDAD2TEM+ 1, = IDAD3TEM-1 00000 1 IDAD3TEM DS 0 ; must - IDAD1TEM+ 2, = IDAD2TEM+1 00000 1 RUTMXTEM DS 0 ; AX*SR*T storage DEXDEX DEX1 DEX2 RTNSAVER TERM1TMP EQU EQU EQU EQU EQU TEM2 TEM3 TEM4 TEM5 BUF2 ; ; ; ; ; B(1) B(1) B(1) B(1) B(2) tmp tmp tmp tmp tmp ; temp for noun address table entry ; temp for noun type table entry ; temp for indir address table entry (MI X N N ) ; temp for indir address table entry (MI X N N ) ; temp for indir address table entry (MI X N N ) ; temp for SF rout table entry (MIXNN on l y )

; (COLOSSUS, p. 70 ) Note: the eraseable memory for the EXEC. ; Moved to the EXE C area

; (COLOSSUS, p. 72 ) ; unswitched for d isplay interface routines 00451 00452 00453 00454 00455 00456 0451 0452 0453 0454 0455 0456 00000 00000 00000 00000 RESTREG DS 0 ; B(1) prm for display starts NVWORD DS 0 MARXNV DS 0 NVSAVE DS 0 ; (retain the orde r of CADRFLSH to FAILREG+2 for downlink purposes) 00000 1 CADRFLSH DS 0 ; B(1) tmp 00000 1 CADRMARK DS 0 ; B(1) tmp 1 1 1 1

00457 00460 00461 00462

0457 0460 0461 0462

00000 1 TEMPFLSH 00000 1 FAILREG 00000 1 00000 1

DS DS DS DS

0 0 0 0

; B(1) tmp ; B(3) prm 3 alarm-abort user=S 2CADR

; (COLOSSUS, p. 73 ) ; verb 37 storage 00463 00464 0463 0464 00000 1 MINDEX 00000 1 MMNUMBER DS DS 0 0 ; B(1) tmp index for major mode ; B(1) tmp major mode requested via V37

; pinball interrup t storage 00465 0465 00000 1 DSPCNT DS 0 ; B(1) prm DSPOUT counter

; pinball executiv e action 00466 00467 00470 00471 00472 00473 00474 00475 00476 0466 0467 0470 0471 0472 0473 0474 0475 0476 00000 1 DSPCOUNT DS 0 ; display position indicator 00000 1 DECBRNCH DS 0 ; Bits2,1: octal=0, +dec=1, -dec=2 ; Bit5=R1 (dec), B it4=R2 (dec), Bit3=R3 (dec) 00000 1 VERBREG DS 0 ; verb code 00000 1 NOUNREG DS 0 ; noun code 00000 1 XREG DS 0 ; R1 input buffer 00000 1 YREG DS 0 ; R2 input buffer 00000 1 ZREG DS 0 ; R3 input buffer 00000 1 XREGLP DS 0 ; low part of XREG (for ded conv only) 00000 1 YREGLP DS 0 ; low part of YREG (for ded conv only) HITEMOUT EQU YREGLP ; temp for display of HRS, MIN, SEC ; must equal LOT EMOUT-1 00000 1 ZREGLP DS 0 ; low part of ZREG (for ded conv only) LOTEMOUT EQU ZREGLP ; temp for display of HRS, MIN, SEC ; must equal HIT EMOUT+1 ; (COLOSSUS, p. 74 ) 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 MODREG DSPLOCK REQRET LOADSTAT CLPASS NOUT NOUNCADR MONSAVE MONSAVE1 MONSAVE2 DS DS DS DS DS DS DS DS DS DS 0 0 0 0 0 0 0 0 0 0 ; ; ; ; ; ; ; ; ; ; mode code keyboard/subroutine call interlock return register for load status indicator for LOADTST pass indicator clear activity counter for DSPTAB machine CADR for noun N/V code for monitor (= MONSAVE1 - 1) NOUNCADR for monitor (MATBS) = MONSAVE + 1 NVMONOPT options

00477

0477

00500 00501 00502 00503 00504 00505 00506 00507 00510 00511

0500 0501 0502 0503 0504 0505 0506 0507 0510 0511

; The 11 register table for the display panel (COLOSSUS, p.74, p.306) ; comment key = RELADD: RELAYWD BIT11 BITS10-6 BITS5-1 DSPTAB 00512 00513 00514 00515 00516 00517 00520 00521 00522 00523 00524 00525 00526 00527 00530 00531 00532 00533 00534 00535 00536 00537 00540 00541 0512 0513 0514 0515 0516 0517 0520 0521 0522 0523 0524 0525 0526 0527 0530 0531 0532 0533 0534 0535 0536 0537 0540 0541 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 EQU DS DS DS DS DS DS DS DS DS DS DS DS * 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 DSPTEM2 DSPTEM1

; ; ; ; ; ; ; ; ; ; ; ;

0: 0001 -R3 R3D4( 1) 1: 0010 +R3 R3D2( 3) 2: 0011 --- R2D5( 5) 3: 0100 -R2 R2D3( 7) 4: 0101 +R2 R2D1(11) 5: 0110 -R1 R1D4(13) 6: 0111 +R1 R1D2(15) 7: 1000 --- -------8: 1001 --- ND1 (21) 9: 1010 --- VD1 (23) 10:1011 --- MD1 (25) 11: C/S lights

R3D5( 0) R3D3( 2) R3D1( 4) R2D4( 6) R2D2(10) R1D5(12) R1D3(14) R1D1(16) ND2 (20) VD2 (22) MD1 (24)

00000 1 NVQTEM DS ; must = NVBNKTEM- 1 00000 1 NVBNKTEM DS ; must = NVQTEM+1 00000 1 VERBSAVE DS 00000 1 CADRSTOR DS 00000 1 DSPLIST DS 00000 1 EXTVRACT DS 00000 1 DSPTEM1 00000 1 00000 1 00000 1 DSPTEM2 00000 1 00000 1 DSPTEMX NORMTEM1 DS DS DS DS DS DS EQU EQU

; NVSUB storage for calling address ; NVSUB storage for calling bank ; ; ; ; needed for recycle ENDIDLE storage waiting reg for DSP syst internal use extended verb activity interlock

; buffer storage area 1 (mostly for time )

; buffer storage area 2 (mostly for deg)

; B(2) S-S display buffer for external v e r b s ; B(3) DSP normal display registers

; display for exte nded verbs OPTIONX EQU DSPTEMX ; B(2) extended verb option code N12(VB2 )

; temp store for m ajor mode change 00542 0542 00000 1 MMTEMP DS 0

; T4RUPT Erasable 00543 00544 00545 00546 0543 0544 0545 0546 00000 00000 00000 00000 1 1 1 1 DSRUPTSW T4RET DSPOUTRET DK_IN_saveQ DS DS DS DS 0 0 0 0 ; ; ; ; (COLOSSUS, added, not added, not return for p. 78) part of COLOSSUS part of COLOSSUS T4RUPT init

; Replacement for Block II LXCH instruction (not part of COLOSSUS) 00547 00550 0547 0550 00000 1 LXCH_LPRET 00000 1 LXCH_A DS DS 0 0 ; LP return address ; save A

; vars for KEYPROG 00551 0551 00000 1 KP_MPAC DS 0

; Vars for DPTEST (not part of COLOSSUS) 00552 00553 0552 0553 00000 1 DPTEST_A 00000 1 DPTEST_Q DS DS 0 0

; Vars for REQDATX , REQDATY, REQDATZ (not part of COLOSSUS) 00554 0554 00000 1 REQ_Q DS 0

; Vars for SETNCAD R (not part of COLOSSUS) 00555 0555 00000 1 SETNCADR_Q DS 0

; Vars for ALLDC_O C (not part of COLOSSUS) 00556 0556 00000 1 ALLDC_OC_Q DS 0

; Vars for SFRUTMI X (not part of COLOSSUS) 00557 0557 00000 1 SFRUTMIX_L DS 0

; Vars for SFCONUM (not part of COLOSSUS) 00560 0560 00000 1 SFCONUM_L DS 0

; vars for BLANKSU B (not part of COLOSSUS) 00561 0561 00000 1 BLANKSUB_Q DS 0

; Vars for GTSFOUT , GTSFIN (not part of COLOSSUS) 00562 0562 00000 1 GTSF_RET DS 0

; Vars for FIXRANG E (not part of COLOSSUS) 00563 0563 00000 1 FR_RETQ DS 0

; Vars for NVSUB ( not part of COLOSSUS) 00564 00565 0564 0565 00000 1 NVSUB_L 00000 1 NVSUB_A DS DS 0 0

; Vars for ENDIDLE (not part of COLOSSUS) 00566 0566 00000 1 ENDIDLE_L DS 0

; Vars for NVSUBUS Y (not part of COLOSSUS) 00567 0567 00000 1 NBSUBSY1_L DS 0

; Vars for FLASHON /FLASHOFF (not part of COLOSSUS) 00570 0570 00000 1 FLASHRET DS 0

; vars for PASTEVB (not part of COLOSSUS) 00571 0571 00000 1 PASTE_TMP DS 0

; vars for NEWMODE A (not part of COLOSSUS) 00572 0572 00000 1 NEWMODEA_Q DS 0

; Vars for MATH LI B (not part of COLOSSUS) 00573 00574 00575 00576 00577 00600 0573 0574 0575 0576 0577 0600 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 SHORTMP_A SHORTMP_OVFL SHORTMP_OVFH ADDRWD1 MATH_Q PRSHRTMP_Q DS DS DS DS DS DS 0 0 0 0 0 0

; KEYRUPT Eraseabl e 00601 00602 0601 0602 00000 1 KEYRET 00000 1 SAVEQ DS DS 0 0 ; added, not part of COLOSSUS ; temp for return addr

; Bank intercommun ication 00603 00604 00605 00606 00607 00610 00611 00612 00613 00614 00615 00616 00617 0603 0604 0605 0606 0607 0610 0611 0612 0613 0614 0615 0616 0617 00000 1 BJBANK 00000 1 BJRET 00000 1 PJBANK 00000 1 PJRET 00000 1 PJA 00000 1 BCBANK 00000 1 BCRET 00000 1 BCA 00000 1 MBCBANK 00000 1 MBCRET 00000 1 MBCA 00000 1 DCBANK 00000 1 DCRET DS DS DS DS DS DS DS DS DS DS DS DS DS 0 0 0 0 0 0 0 0 0 0 0 0 0

; FIXED MEMORY DEC LARATIONS ORG DS EXTENDER %47777

05777

5777

47777 0

; needed for EXTEND

;----------------- --------------------------------------------------------; RESTART/INTERRUP T ENTRY POINTS ;----------------- --------------------------------------------------------; Program (re)star t ORG TC ; Interrupt vector s ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC

02000

2000 0

1,2126 0

GOPROG goMAIN

; AGC (re)start begins here!

02004 02005 02006 02007

2004 2005 2006 2007

5 3 5 0

0,0026 0,0001 0,0027 1,2034

0 0 1 1

T3RUPT ARUPT Q QRUPT goT3 ERRUPT ARUPT Q QRUPT goER DSRUPT ARUPT Q QRUPT goDS KEYRUPT ARUPT Q QRUPT goKEY UPRUPT ARUPT Q QRUPT goUP

; TIME3 interrupt vector

02010 02011 02012 02013

2010 2011 2012 2013

5 3 5 0

0,0026 0,0001 0,0027 1,2036

0 0 1 0

; T4RUPT for DSKY display

02014 02015 02016 02017

2014 2015 2016 2017

5 3 5 0

0,0026 0,0001 0,0027 1,2037

0 0 1 1

; DSKY keyboard interrupt vector

02020 02021 02022 02023

2020 2021 2022 2023

5 3 5 0

0,0026 0,0001 0,0027 1,2041

0 0 1 0

02024 02025 02026 02027

2024 2025 2026 2027

5 3 5 0

0,0026 0,0001 0,0027 1,2043

0 0 1 1

; restore Q and A registers and resume endRUPT 02030 02031 02032 02033 2030 2031 2032 2033 3 5 3 2 0,0027 0,0001 0,0026 0,0000 1 0 0 1 EQU XCH TS XCH RES UME * QRUPT Q ARUPT

; restore Q ; restore A ; resume normal program execution

;----------------- --------------------------------------------------------; RUPT (INTERRUPT) SERVICE ROUTINES ; ; Upon entry, regi sters will contain these values: ; - ZRUPT: Prior c ontents of program counter (Z register). ; - BRUPT: Prior c ontents of B register. ; - ARUPT: Prior c ontents of accumulator (A register). ; - QRUPT: Prior c ontents of Q register. ; ; When the service routine is finished, jump to endRUPT to restore the A ; and Q registers. Call RESUME to restore Z and B, which causes a return ; to normal (non-i nterrupt) execution. Interrupts are disabled upon entry ; to the service r outine; they are reenabled following RESUME. ;----------------- --------------------------------------------------------goT3 02034 02035 2034 0 2035 0 1,2347 0 1,2030 0 goER 02036 2036 0 1,2030 0 goDS 02037 02040 2037 0 2040 0 2,4047 0 1,2030 0 goKEY 02041 02042 2041 0 2042 0 2,4132 0 1,2030 0 goUP 02043 2043 0 1,2030 0 EQU TCR TC EQU TC EQU TCR TC EQU TCR TC EQU TC * WL_TIME3task endRUPT * endRUPT * T4PROG endRUPT * KEYPROG endRUPT * endRUPT

; handle T3RUPT for WAITLIST

; handle T4RUPT for DSKY display

; handle keyrupt for keyboard entry

;----------------- --------------------------------------------------------; FIXED MEMORY CON STANTS ;----------------- --------------------------------------------------------02044 02045 02046 02047 02050 02051 02052 02053 02054 02055 02056 02057 02060 02061 2044 2045 2046 2047 2050 2051 2052 2053 2054 2055 2056 2057 2060 2061 00200 0 ofbit 77777 0 NEG0 77776 1 NEG1 77775 1 NEG2 00000 00001 00002 00003 00004 00005 00006 00007 00012 00013 1 0 0 1 0 1 1 0 1 0 ZERO ONE TWO THREE FOUR FIVE SIX SEVEN TEN ELEVEN DS DS DS DS DS DS DS DS DS DS DS DS DS DS %200 -0 -1 -2 0 1 2 3 4 5 6 7 10 11 ; OUT1, bit 8 initiates standby

; must be in rever se order. Pinball treats this as a table ; and indexes thru it. 02062 02063 02064 02065 02066 02067 02070 02071 02072 02073 02074 02075 02076 02077 02100 02101 02102 02103 02104 2062 2063 2064 2065 2066 2067 2070 2071 2072 2073 2074 2075 2076 2077 2100 2101 2102 2103 2104 40000 20000 10000 04000 02000 01000 00400 00200 00100 00040 00020 00010 00004 00002 00001 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 BIT15 BIT14 BIT13 BIT12 BIT11 BIT10 BIT9 BIT8 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS %40000 %20000 %10000 %04000 %02000 %01000 %00400 %00200 %00100 %00040 %00020 %00010 %00004 %00002 %00001 %00177 %6000 %1777 %1400 ; fixed-switchable addr range starts her e ; mask for 10-bit address

00177 0 LOW7 06000 1 bankAddr 01777 1 lowAddr 01400 1 OCT1400

02105 02106

2105 2106

00013 0 NOUTCON 37777 1 POSMAX

DS DS

11 %37777

;----------------- -------------------------------------------------------; CLRMEM - INITIAL IZE ERASEABLE MEMORY ; ; Uses QRUPT and A RUPT as scratchpad. This is OK, because interrupts ; are disabled any way. All eraseable memory above the AGC clock (TIME1, ; TIME2) is cleare d. The AGC clock is not cleared because this might ; be a restart or a startup from standby mode. ;----------------- -------------------------------------------------------CLRMEM 02107 02110 02111 02112 2107 3 2110 5 2111 3 2112 5 0,0001 0 0,0027 1 1,2123 0 0,0026 0 CLRMEM_CHK 02113 02114 02115 2113 1 2114 0 2115 0 0,0026 1 1,2116 0 0,0027 1 CLRMEM_WORD 02116 02117 02120 02121 02122 2116 2117 2120 2121 2122 5 3 2 5 0 0,0026 1,2050 0,0026 0,0037 1,2113 0 0 1 0 0 EQU XCH TS XCH TS EQU CCS TC TC EQU TS CAF IND EX TS TC EQU EQU DS * Q QRUPT CLRMEM_WC ARUPT * ARUPT CLRMEM_WORD QRUPT * ARUPT CLRMEM_VAL ARUPT CLRMEM_BADDR CLRMEM_CHK ZERO TIME3 %1777-TIME3+1

; save return address ; init count of words to clear

; return

; clear a word ; done? ; set memory to this value ; base address to clear ; clear everything >= TIME3

02123

2123

CLRMEM_VAL CLRMEM_BADDR 01741 1 CLRMEM_WC

;----------------- -------------------------------------------------------; FRESH START ; ; AGC starts execu ting here, following power-up, or restart. ;----------------- -------------------------------------------------------02124 02125 2124 2125 10000 0 V37BANK 37600 0 SAMASK DS DS %10000 %37600 ; BANK (4) containg PREMM1, FCADRMM1 ; mask to zero lower 7 bits

goMAIN SLAP1 02126 2126 2 0,0000 0

EQU EQU INH INT

* goMAIN

; entry for V36 (fresh start request)

; First, check for standby operation. Loosely based on the standby ; algorithm in R-3 93. Probably should flash the 'computer activity' ; light as well. 02127 02130 02131 02132 02133 02134 02135 02136 02137 02140 02141 02142 2127 3 2130 6 2131 5 2132 3 2133 6 2134 5 2135 3 2136 7 2137 5 2140 3 2141 5 2142 0 1,2071 0 0,0036 1 0,0036 1 1,2050 0 0,0035 1 0,0035 1 1,2125 0 0,0036 0 0,0036 1 1,2044 0 0,0011 1 1,2107 0 CAF AD TS CAF AD TS CAF MAS K TS XCH TS TC BIT8 TIME1 TIME1 ZERO TIME2 TIME2 SAMASK TIME1 TIME1 ofbit OUT1 CLRMEM ; add 2 to 7th power to AGC clock

; skipped on ovf and C(A) set to 1 ; bump TIME2 with overflow, if any

; zero the LSBs of TIME1

; enable standby operation

; clear everything but the AGC clock

; set fresh start major mode to P00 (AGC CMC idle) 02143 02144 02145 02146 2143 3 2144 5 2145 3 2146 5 1,2124 1 0,0015 0 4,6046 0 0,0463 0 CAF TS CAF TS V37BANK BANK NOV37MM MINDEX

; bank for major mode tables ; assumes BANK is set (above) ; index to P00

goMMchange 02147 2147 2 0,0000 0

EQU INH INT

* ; inhibit interrupts

; Initialize WAITL IST and EXEC eraseable memory. Initialize DSKY eraseable

; memory (but don' t initialize BANK or MINDEX; they are used to start the ; main job for thi s major mode. 02150 02151 02152 2150 0 2151 0 2152 0 1,3252 1 1,2204 0 2,4007 1 ; ; ; ; TCR TCR TCR EX_initEX WL_initWL DK_initDK ; initialize EXEC ; initialize WAITLIST ; initialize DSKY

Start the major mode job. This is modified from COLOSSUS because block I doesn't have E-b ank and my SPVAC interface is a little different from the original. The re ferences to PREMM1 and FCADRMM1 assume that the BANK is set to the one c ontaining those tables. EQU INH INT IND EX CAF TS MAS K TC TC TS IND EX CAF TC * MINDEX PREMM1 MMTEMP HI5 RIGHT5 RIGHT5 NEWPRIO MINDEX FCADRMM1 SPVAC * ZERO MMTEMP LOW7 NEWMODEA RELDSP ; job CADR in C(A), job prio in NEWPRIO ; obtain priority bits 15-11 ; shift right to bits 5-1 ; store PRIO for SPVAC

V37XEQ 02153 02154 02155 02156 02157 02160 02161 02162 02163 02164 02165 2153 2154 2155 2156 2157 2160 2161 2162 2 2 3 5 7 0 0 5 0,0000 0,0463 4,6037 0,0542 2,4666 2,4640 2,4640 0,0360 0 1 0 1 1 1 1 1

2163 2 2164 3 2165 0

0,0463 1 4,6030 1 1,3075 0 V37XEQC

02166 02167 02170 02171 02172

2166 2167 2170 2171

3 6 7 0

1,2050 0,0542 1,2101 2,5036

0 1 1 1

EQU CAF AD MAS K TC TC

; ; ; ;

was CA MMTEMP in Block II upon return from FINDVAC, place the new MM in MODREG (the low 7 bits of PHSERDT1)

2172 0

2,5003 1

; release display

; Start the EXEC. 02173 2173 0 1,2656 0 TC EX_exec ; never returns

;----------------- -------------------------------------------------------; AGC LIBRARIES ; ; System services in fixed-fixed memory. ;----------------- -------------------------------------------------------INC L waitlist_f.asm ; WAITLIST, incl. T3RUPT handler ;================= ========================================================= ; WAITLIST (file:w aitlist_f.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 11/15/ 2001 ; ; PURPOSE: ; Constants and so urce code for WAITLIST. ; ; Non-preemptive i nterrupt timer routines, originally implemented by J. H. ; Laning, Jr. for AGC3 and later adapted for AGC4. Briefly discussed in ; R-393, which giv es some of the software interfaces into the WAITLIST. ; This is my own r ecreation, and the internals may differ from the original. ; ; A task is schedu led for execution by calling 'WAITLIST' and ; furnishing the t ime-out time and starting address. ; L XCH TASK_TIMEOUT ; in 10 mSec ticks ; L+1 TC WAITLIST ; L+2 DS TASK_ADDRESS ; 14-bit address ; L+3 ... execution resumes here ; ; TASK_TIMEOUT = a positive integer from 1 - MAXDELAY that specifies the delay ; in 10 mSec ti cks. Maximum delay is 12000 (2 minutes). ; TASK_ADDRESS = s tarting address of the task (14-bit address) ; ; WAITLIST can be called from from an interrupt, or from normal execution. ; It is the only p ublic function of the waitlist. ; ; **** WARNING *** * If WAITLIST is not called from an interrupt, be sure to ; inhibit interrup ts before calling it to protect the integrity of the list. ; ; Tasks execute wh en TIME3 overflows and generates an interrupt (T3RUPT). ; The task execute s during the interrupt. Tasks terminate themselves by ; jumping to TASKO VER. ; TC TASKOVER ; ; Because tasks ex ecute during an interrupt, they should be fairly short. ; Tasks can initia te longer operations by scheduling a 'job' using EXEC.

;================= =========================================================

02174 02175 02176 02177 02200 02201 02202 02203

2174 2175 2176 2177 2200 2201 2202 2203

00002 00057 00073 00006 00005

0 0 0 1 1

WL_taskRecSize WL_tskLstStart WL_tskLstEnd WL_numTasks WL_numTasks1

DS DS DS DS DS DS DS DS

TRECSZ ; size of a task record (words) WL_taskList ; starting address for task list MAXTASK-1@TRECSZ+WL_taskList MAXTASK-1 ; init loop counter for all tasks MAXTASK-2 ; init loop counter for all tasks - 1 MAXVAL MAXDELAY MAXTIMEOUT

37777 1 WL_maxVal 27340 0 WL_maxDelay 10440 0 WL_maxTimeOut

;----------------- --------------------------------------------------------; WL_initWL - INIT IALIZE WAITLIST ; ; Subroutine initi alizes the eraseable memory segment for WAITLIST. ; Necessary in cas e the AGC is restarted. ; ; Note: the valid range for TIME3 is 10440 to 37777 (which spans ; 12000 (base 10 ) ticks, which corresponds to 120 seconds) ; positive overf low occurs at 40000, which triggers T3RUPT. ; TIME3 values o f 0 to 10437 are illegal; these values occur ; after timeout when the counter overflows. TIME3 values in this ; range indicate that timeout has occurred and that T3RUPT is ; presently occu ring, or is pending. ;----------------- --------------------------------------------------------WL_initWL 02204 02205 02206 02207 2204 3 2205 5 2206 3 2207 5 0,0001 0 0,0075 0 1,2203 1 0,0037 0 EQU XCH TS CAF TS * Q WL_IN_saveQ WL_maxTimeOut TIME3

; save return address

; Iterate through task list and initialize all records to NIL 02210 02211 02212 02213 02214 02215 02216 02217 02220 02221 02222 02223 02224 02225 02226 02227 02230 02231 2210 3 2211 5 2212 3 2213 5 2214 3 2215 2 2216 5 2217 3 2220 2 2221 5 2222 3 2223 6 2224 5 2225 1 2226 0 2227 3 2230 5 2231 0 1,2175 0 0,0076 0 1,2177 1 WL_IN_loop 0,0077 1 1,2202 0 0,0076 1 0,0000 1 1,2050 0 0,0076 1 0,0001 0 0,0076 0 1,2174 1 0,0076 0 0,0077 0 1,2213 0 0,0075 0 0,0001 0 0,0000 0 CAF TS CAF EQU TS CAF IND EX TS CAF IND EX TS XCH AD TS CCS TC XCH TS RET URN WL_tskLstStart ; init pointer to start of list WL_IN_taskPtr WL_numTasks * WL_IN_loopCnt WL_maxDelay WL_IN_taskPtr TSKTIME ZERO WL_IN_taskPtr TSKADDR WL_IN_taskPtr ; bump task pointer back 1 record WL_taskRecSize WL_IN_taskPtr WL_IN_loopCnt WL_IN_loop WL_IN_saveQ Q ; done checking task list? ; not yet ; loop for number of tasks

; restore return address

;----------------- --------------------------------------------------------; WAITLIST - ADD T ASK TO WAITLIST ; ; Subroutine adds a task to WL_taskList. The following conditions are ; true upon entry. ; 1) The task list is sorted so the next task scheduled for execution ; is at the fro nt of the list. ; 2) If no tasks a re currently scheduled, the task record at the front ; of the list w ill be NIL. ; 3) Unused (NIL) records in the task list have their time fields set to ; MAXDELAY and their address fields set to zero. ; 4) If any tasks are on the waitlist, the time field in that task's ; record will c ontain the remaining time AFTER the next timeout. The ; task schedule d for execution at timeout will have a time remaining ; of zero. ; Any other tas ks that will execute at that time will also have a time of ; zero. Tasks t hat will execute some time in the future AFTER timeout ; will have non zero times; these times indicate the additional time ; needed after the next timeout. ; ; This is the only 'public' function. It can be called from a job or from ; a task or other interrupt. It disables interrupts to maintain the integrity ; of the taskList.

;----------------- --------------------------------------------------------WAITLIST 02232 02233 02234 02235 02236 02237 02240 02241 2232 5 2233 3 2234 5 2235 2236 2237 2240 2241 3 2 6 1 0 0,0102 1 0,0001 0 0,0100 0 1,2050 1,2176 0,0001 0,0000 1,2343 0 1 0 0 1 EQU TS XCH TS CAF IND EX AD CCS TC * WL_AT_newTime Q WL_AT_saveQ ZERO WL_tskLstEnd TSKADDR A WL_AT_done

; save task time ; save return address-1

; list full? ; >0 yes, so give up

; Calculate time r emaining until currently scheduled time-out. 02242 02243 02244 2242 3 2243 6 2244 5 1,2050 0 0,0037 0 0,0103 0 CAF AD TS ZERO TIME3 ; get time WL_AT_timeLeft ; save it, temporarily

; Did TIME3 recent ly overflow? If so, we are inside T3RUPT, or T3RUPT ; is pending. TIME 3 values from 0 - 10437 are not legal, so they ; indicate that an overflow has occurred. 02245 02246 02247 02250 02251 02252 02253 2245 2246 2247 2250 2251 2252 2253 4 6 1 0 0 0 0 1,2203 0,0103 0,0000 1,2264 1,2264 1,2254 1,2264 0 0 0 0 0 0 0 CS AD CCS TC TC TC TC WL_maxTimeOut WL_AT_timeLeft A WL_AT_noOvf WL_AT_noOvf *+2 WL_AT_noOvf

; ; ; ; ;

TIME3 recently overflowed? >0 no +0 no <0 yes -0 no

; TIME3 already ti med-out, so we must be inside T3RUPT, or T3RUPT ; is pending. Just add the new task to the list. No time correction ; is necessary; th e epoch is NOW. 02254 02255 02256 02257 02260 02261 02262 02263 2254 3 2255 6 2256 5 2257 2 2260 3 2261 5 2262 0 2263 0 1,2050 0 0,0102 1 0,0122 0 0,0100 1 0,0000 1 0,0123 1 1,2473 0 1,2343 1 CAF AD TS IND EX CAF TS TCR TC ZERO WL_AT_newTime WL_IS_newTime WL_AT_saveQ 0 WL_IS_newAddr WL_insert WL_AT_done

; set time field in new task record ; indirectly address WL_AT_saveQ ; set addr field in new task record ; add new task to task list

; TIME3 has not ti med out yet. Calculate time remaining until timeout ; (timeout occurs when TIME3 overflows) WL_AT_noOvf 02264 02265 02266 02267 2264 2265 2266 2267 4 6 6 5 0,0103 1,2201 1,2051 0,0103 1 0 1 0 EQU CS AD AD TS * WL_AT_timeLeft ; get -TIME3 WL_maxVal ONE WL_AT_timeLeft ; time left = -TIME3 + %37777 + 1

; Compare that tim e against the timeout for the new task. WL_AT_chkOrder EQU CS AD CCS TC TC TC ; ; ; ; 02276 02277 02300 02301 02302 02303 02304 02305 2276 4 2277 6 2300 5 2301 2 2302 3 2303 5 2304 0 2305 0 0,0103 1 0,0102 1 0,0122 0 0,0100 1 0,0000 1 0,0123 1 1,2473 0 1,2343 1 * WL_AT_newTime WL_AT_timeLeft A WL_AT_mkFirst *+2 *+1

02270 02271 02272 02273 02274 02275

2270 2271 2272 2273 2274 2275

4 6 1 0 0 0

0,0102 0,0103 0,0000 1,2306 1,2276 1,2276

0 0 0 0 0 0

; ; ; ;

compare new task to current >0 (make new task 1st) +0 <0

The new task doe s not need to run before the current time-out, so just add it to t he list. Subtract the remaining time interval from the new task's time, so the new task will have the same epoch as the other tasks on the lis t. CS AD TS IND EX CAF TS TCR TC WL_AT_timeLeft WL_AT_newTime ; make epoch correction WL_IS_newTime ; set time field in new task record WL_AT_saveQ 0 WL_IS_newAddr WL_insert WL_AT_done ; indirectly address WL_AT_saveQ ; set addr field in new task record ; add new task to task list

; The new task nee ds to run prior to the current time-out. Add the time ; remaining to all tasks currently on the list to change their epoch ; to NOW. WL_AT_mkFirst 02306 2306 3 1,2175 0 EQU CAF * WL_tskLstStart ; set pointer to front of list

02307 02310 02311 02312 02313 02314 02315 02316 02317 02320 02321 02322 02323 02324 02325 02326 02327 02330 02331 02332

2307 5 2310 3 2311 5 2312 2313 2314 2315 2316 2317 2320 2321 2322 2323 2324 2325 3 2 6 1 0 0 3 2 6 6 2 5

0,0101 1 1,2177 1 WL_AT_loop 0,0104 1 1,2050 0,0101 0,0001 0,0000 1,2320 1,2333 1,2050 0,0101 0,0000 0,0103 0,0101 0,0000 0 0 0 0 1 0 0 0 1 0 0 1

TS CAF EQU TS CAF IND EX AD CCS TC TC CAF IND EX AD AD IND EX TS XCH AD TS CCS TC

WL_AT_taskPtr WL_numTasks * WL_AT_loopCnt ZERO WL_AT_taskPtr TSKADDR A *+2 WL_AT_schTsk ; loop for number of tasks

; end of list? ; >0 no, so keep going ; +0 yes, add the new task

ZERO WL_AT_taskPtr TSKTIME WL_AT_timeLeft ; time-out = time-out + timeLeft WL_AT_taskPtr TSKTIME WL_AT_taskPtr ; bump task pointer back 1 record WL_taskRecSize WL_AT_taskPtr WL_AT_loopCnt WL_AT_loop ; done fixing the times? ; not yet

2326 3 2327 6 2330 5 2331 1 2332 0

0,0101 1 1,2174 1 0,0101 1 0,0104 0 1,2311 0

; Now that the tas ks all share the same epoch, add the new task to the ; list and call th e scheduler to schedule the next task. WL_AT_schTsk 02333 02334 02335 02336 02337 02340 02341 02342 2333 3 2334 6 2335 5 2336 2 2337 3 2340 5 2341 0 2342 0 1,2050 0 0,0102 1 0,0122 0 0,0100 1 0,0000 1 0,0123 1 1,2473 0 1,2417 1 WL_AT_done 02343 02344 02345 02346 2343 2344 2345 2346 3 6 5 0 0,0100 1,2051 0,0001 0,0000 0 1 0 0 EQU CAF AD TS IND EX CAF TS TCR TCR EQU XCH AD TS RET URN * ZERO WL_AT_newTime WL_IS_newTime WL_AT_saveQ 0 WL_IS_newAddr WL_insert WL_schedTask * WL_AT_saveQ ONE Q

; set time field in new task record ; indirectly address WL_AT_saveQ ; set addr field in new task record ; add new task to task list ; schedule the next task

; restore return address

;----------------- --------------------------------------------------------; WL_TIME3task - T 3 TIMEOUT ; ; Perform WAITLIST activities when TIME3 times-out. Called by the ; T3 interrupt han dler. ;----------------- --------------------------------------------------------WL_TIME3task 02347 02350 02351 02352 2347 2350 2351 2352 3 5 3 5 0,0001 0,0105 0,0015 0,0106 0 0 0 0 EQU XCH TS XCH TS * Q WL_T3_saveQ BANK WL_T3_oldBank

; save return address ; save current bank

; Execute all time d-out tasks. 02353 2353 0 1,2362 1 TCR WL_runTasks

; Set up TIME3 to overflow at the next task's time-out. ; Adjust the time- outs for all remaining tasks. 02354 02355 02356 02357 02360 02361 2354 0 2355 2356 2357 2360 2361 3 5 3 5 0 1,2417 1 0,0106 0,0015 0,0105 0,0001 0,0000 0 0 0 0 0 TCR XCH TS XCH TS RET URN WL_schedTask WL_T3_oldBank BANK WL_T3_saveQ Q

; restore previous bank ; restore return address

;----------------- --------------------------------------------------------; WL_runTasks - RU N TIMED-OUT TASK(S) ; ; Runs all tasks t imed-out on WL_taskList. Tasks are removed ; from the list be fore they are run. ;----------------- --------------------------------------------------------WL_runTasks 02362 02363 2362 3 2363 5 0,0001 0 0,0113 1 EQU XCH TS * Q WL_RT_saveQ

; save return address

; loop, checking t he task on the front of the list. If it is ; timed out, remov e it from the list and run it. WL_RT_loop 02364 02365 02366 02367 02370 02371 02372 2364 2365 2366 2367 2370 2371 2372 3 2 6 1 0 0 0 1,2050 1,2175 0,0000 0,0000 1,2414 1,2373 1,2373 0 1 1 0 1 1 1 EQU CAF IND EX AD CCS TC TC TC * ZERO WL_tskLstStart TSKTIME A WL_RT_done *+2 *+1

; ; ; ;

task timed out? >0 no, so we are done +0 <0

; This task has ti med out, so run it. 02373 02374 2373 0 2374 5 1,2565 0 0,0114 0 TCR TS WL_remove WL_RT_runAddr ; remove task from list ; save 14-bit address of task to run

; The task address is always 14-bit, so check whether the address falls ; within erasable or fixed-fixed memory. If so, use it as-is; otherwise, ; set the bank reg ister and change the address to 12-bit. 02375 02376 02377 02400 02401 02402 02403 02404 02405 02406 02407 02410 2375 2376 2377 2400 2401 2402 4 6 1 0 0 0 0,0000 1,2102 0,0000 1,2411 1,2403 1,2403 0 0 0 1 1 1 COM AD CCS TC TC TC CAF AD TS MAS K AD TS WL_RT_runIt 02411 02412 2411 2 2412 0 0,0114 1 0,0000 1 TASKOVER 02413 2413 0 1,2364 1 WL_RT_done 02414 02415 02416 2414 3 2415 5 2416 0 0,0113 1 0,0001 0 0,0000 0 EQU IND EX TC EQU TC EQU XCH TS RET URN ; -(14bitAddr)+%6000 bankAddr A WL_RT_runIt *+2 *+1 ZERO WL_RT_runAddr BANK lowAddr bankAddr WL_RT_runAddr * WL_RT_runAddr 0 * WL_RT_loop * WL_RT_saveQ Q ; ; ; ; task is bank addressed? >0 no, just run it, as is +0 yes <0 yes

2403 3 2404 6 2405 5 2406 7 2407 6 2410 5

1,2050 0 0,0114 0 0,0015 0 1,2103 0 1,2102 0 0,0114 0

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; apply indirect address to next instr. ; run the task ; task returns here ; check next task on list

; restore return address

;----------------- --------------------------------------------------------; WL_schedTask - S CHEDULE NEXT TASK ; ; Schedule task on the front of list for the next time-out. Adjust the ; time-out for all other tasks on the list, so they contain the remaining ; time after the n ext timeout. ;----------------- --------------------------------------------------------WL_schedTask 02417 02420 02421 02422 02423 02424 02425 02426 02427 02430 02431 02432 2417 3 2420 5 2421 2422 2423 2424 2425 2426 2427 2430 2431 2432 3 2 6 1 0 0 3 2 6 5 0,0001 0 0,0107 1 1,2050 1,2175 0,0001 0,0000 1,2427 1,2466 1,2050 1,2175 0,0000 0,0111 0 1 0 0 1 1 0 1 1 0 EQU XCH TS CAF IND EX AD CCS TC TC CAF IND EX AD TS * Q WL_ST_saveQ

; save return address

ZERO WL_tskLstStart TSKADDR A ; task scheduled? *+2 ; >0 yes WL_ST_noTask ; +0 no, so we are done ZERO WL_tskLstStart TSKTIME WL_ST_newTime ; save the new task's time-out

; Iterate through all tasks on the list. Subtract the time-out time ; from each task. (The 1st task on the list will now have a time-out ; of zero) 02433 02434 02435 02436 02437 02440 02441 2433 3 2434 5 2435 3 2436 5 2437 3 2440 2 2441 6 1,2175 0 0,0110 1 1,2177 1 WL_ST_loop 0,0112 0 1,2050 0 0,0110 0 0,0001 0 CAF TS CAF EQU TS CAF IND EX AD WL_tskLstStart ; set pointer to front of list WL_ST_taskPtr WL_numTasks * WL_ST_loopCnt ZERO WL_ST_taskPtr TSKADDR ; loop for number of tasks

02442 02443 02444 02445 02446 02447 02450 02451 02452 02453 02454 02455 02456 02457 02460

2442 1 2443 0 2444 0 2445 2446 2447 2450 2451 2452 2453 3 2 6 2 6 2 5

0,0000 0 1,2445 0 1,2461 0 1,2050 0,0110 0,0000 0,0000 0,0111 0,0110 0,0000 0 0 1 1 0 0 1

CCS TC TC CAF IND EX AD EXT END SU IND EX TS XCH AD TS CCS TC

A *+2 WL_ST_setT3 ZERO WL_ST_taskPtr TSKTIME WL_ST_newTime WL_ST_taskPtr TSKTIME

; end of list? ; >0 no, so keep going ; +0 yes, set TIME3

; time-out = time-out - newtime

2454 3 2455 6 2456 5 2457 1 2460 0

0,0110 1 1,2174 1 0,0110 1 0,0112 1 1,2436 1

WL_ST_taskPtr ; bump task pointer back 1 record WL_taskRecSize WL_ST_taskPtr WL_ST_loopCnt WL_ST_loop ; done fixing the times? ; not yet

; Set TIME3 to ove rflow at the time-out of the task on the front ; of the list: TIM E3 = %37777 - WL_ST_newTime + 1 WL_ST_setT3 02461 02462 02463 02464 02465 2461 2462 2463 2464 2465 4 6 6 5 0 0,0111 1,2201 1,2051 0,0037 1,2470 1 0 1 0 0 WL_ST_noTask 02466 02467 2466 3 2467 5 1,2203 1 0,0037 0 WL_ST_done 02470 02471 02472 2470 3 2471 5 2472 0 0,0107 1 0,0001 0 0,0000 0 EQU CS AD AD TS TC EQU CAF TS EQU XCH TS RET URN * WL_ST_newTime WL_maxVal ONE TIME3 WL_ST_done * WL_maxTimeOut TIME3 * WL_ST_saveQ Q

; overflow at new time-out time

; nothing scheduled, reset the clock

; restore return address

;----------------- --------------------------------------------------------; WL_insert - INSE RT TASK INTO SORTED LIST ; ; Insert a task re cord into the sorted list. Use 'WL_IS_newTime' and ; 'WL_IS_newAddr' to set the fields of record to be inserted. ; Performs an inse rtion sort, with the records sorted by time. ; Lowest times are at the front of the list. If several records ; have the same ti me, the records inserted first will appear first ; in the list. NIL records have a time of NOTASK and a address ; of positive zero . ;----------------- --------------------------------------------------------WL_insert 02473 02474 02475 02476 02477 02500 02501 02502 02503 02504 02505 02506 2473 3 2474 5 2475 3 2476 5 2477 2 2500 6 2501 5 2502 2503 2504 2505 2506 3 2 6 1 0 0,0001 0 0,0124 0 1,2176 0 0,0125 1 0,0000 1 1,2174 1 0,0126 1 1,2050 0,0125 0,0001 0,0000 1,2562 0 0 0 0 1 EQU XCH TS CAF TS EXT END SU TS CAF IND EX AD CCS TC * Q WL_IS_saveQ WL_tskLstEnd WL_IS_taskPtr

; save return address ; set pointer to back of list

WL_taskRecSize ; set pointer to rec in front of it WL_IS_taskPtr2 ZERO WL_IS_taskPtr TSKADDR A WL_IS_done

; list full? ; >0 yes

; Work from the ba ck of the list to the front, pushing each record ; to the back unti l the insertion point is found. 02507 02510 02511 02512 02513 02514 02515 02516 2507 3 2510 5 2511 2512 2513 2514 2515 2516 3 2 6 1 0 0 1,2200 1 WL_IS_loop 0,0127 0 1,2050 0,0126 0,0001 0,0000 1,2517 1,2541 0 0 0 0 0 0 CAF EQU TS CAF IND EX AD CCS TC TC WL_numTasks1 * WL_IS_loopCnt ; loop for number of tasks minus 1

ZERO WL_IS_taskPtr2 TSKADDR A ; previous record is NIL? *+2 ; no, so check it WL_IS_bumpPtr ; yes, so skip to next record

; Is this the inse rtion point? 02517 02520 02521 2517 4 2520 2 2521 6 0,0122 1 0,0126 0 0,0000 1 CS IND EX AD WL_IS_newTime WL_IS_taskPtr2 TSKTIME

02522 02523 02524 02525 02526

2522 2523 2524 2525 2526

1 0 0 0 0

0,0000 1,2527 1,2552 1,2552 1,2552

0 0 1 1 1

CCS TC TC TC TC

A *+4 WL_IS_insRec WL_IS_insRec WL_IS_insRec

; ; ; ; ;

found insertion point? >0 no, keep checking +0 yes <0 yes -0 yes

; No, bump the rec ord toward the back of the list. 02527 02530 02531 02532 02533 02534 02535 02536 02537 02540 2527 2530 2531 2532 2533 2534 2535 2536 2537 2540 3 2 6 2 5 3 2 6 2 5 1,2050 0,0126 0,0000 0,0125 0,0000 1,2050 0,0126 0,0001 0,0125 0,0001 0 0 1 0 1 0 0 0 0 0 WL_IS_bumpPtr 02541 02542 02543 02544 02545 02546 02547 02550 02551 2541 2542 2543 2544 3 2 6 5 0,0125 0,0000 1,2174 0,0125 1 1 1 1 CAF IND EX AD IND EX TS CAF IND EX AD IND EX TS EQU XCH EXT END SU TS EXT END SU TS CCS TC ; Insert new recor d. WL_IS_insRec 02552 02553 02554 02555 02556 02557 02560 02561 2552 2553 2554 2555 2556 2557 2560 2561 3 6 2 5 3 6 2 5 1,2050 0,0122 0,0125 0,0000 1,2050 0,0123 0,0125 0,0001 0 0 0 1 0 1 0 0 WL_IS_done 02562 02563 02564 2562 3 2563 5 2564 0 0,0124 0 0,0001 0 0,0000 0 EQU CAF AD IND EX TS CAF AD IND EX TS EQU XCH TS RET URN * ZERO WL_IS_newTime WL_IS_taskPtr TSKTIME ZERO WL_IS_newAddr WL_IS_taskPtr TSKADDR * WL_IS_saveQ Q ZERO WL_IS_taskPtr2 TSKTIME WL_IS_taskPtr TSKTIME ; copy time field ZERO WL_IS_taskPtr2 TSKADDR WL_IS_taskPtr TSKADDR ; copy address field * WL_IS_taskPtr WL_taskRecSize WL_IS_taskPtr

; bump task pointer forward 1 record

2545 2 2546 6 2547 5 2550 1 2551 0

0,0000 1 1,2174 1 0,0126 1 0,0127 1 1,2510 1

WL_taskRecSize ; set pointer to record in front of it WL_IS_taskPtr2 WL_IS_loopCnt WL_IS_loop ; done bumping tasks backward? ; not yet

; set time field

; set address field

; restore return address

;----------------- --------------------------------------------------------; WL_remove - REMO VE TASK FROM FRONT OF LIST ; ; Returns the addr ess of the task in register A. If the list is ; empty, it return s zero in A. If a task is removed from the list, ; the remaining ta sks are moved up to the front. ;----------------- --------------------------------------------------------WL_remove 02565 02566 02567 02570 02571 02572 2565 3 2566 5 2567 3 2570 5 2571 6 2572 5 0,0001 0 0,0115 1 1,2175 0 0,0116 1 1,2174 1 0,0117 0 EQU XCH TS CAF TS AD TS * Q WL_RM_saveQ

; save return address

WL_tskLstStart ; set pointer to front of list WL_RM_taskPtr WL_taskRecSize ; set pointer to next rec behind it WL_RM_taskPtr2

; Save the address of record at the front of the list. 02573 02574 02575 02576 02577 02600 02601 2573 2574 2575 2576 3 2 6 5 1,2050 0,0116 0,0001 0,0121 0 0 0 0 CAF IND EX AD TS CCS TC TC ZERO WL_RM_taskPtr TSKADDR WL_RM_retval A *+2 WL_RM_done

; get address of 1st task ; list empty? ; >0, no ; +0, yes, so exit

2577 1 2600 0 2601 0

0,0000 0 1,2602 1 1,2636 0

; Loop through the remaining records in the task list and ; bubble them up t o the front. 02602 02603 2602 3 2603 5 1,2200 1 WL_RM_loop 0,0120 1 CAF EQU TS WL_numTasks1 * WL_RM_loopCnt ; loop for number of tasks minus 1

02604 02605 02606 02607 02610 02611 02612 02613 02614 02615 02616 02617 02620 02621 02622 02623 02624 02625 02626 02627

2604 2605 2606 2607 2610 2611 2612 2613 2614 2615

3 2 6 2 5 3 2 6 2 5

1,2050 0,0117 0,0000 0,0116 0,0000 1,2050 0,0117 0,0001 0,0116 0,0001

0 1 1 0 1 0 1 0 0 0

CAF IND EX AD IND EX TS CAF IND EX AD IND EX TS CCS TC TC XCH AD TS AD TS CCS TC

ZERO WL_RM_taskPtr2 TSKTIME WL_RM_taskPtr TSKTIME ; copy time field ZERO WL_RM_taskPtr2 TSKADDR WL_RM_taskPtr TSKADDR ; copy address field A *+2 WL_RM_done ; remainder of list empty? ; >0, no ; +0, yes, so exit

2616 1 2617 0 2620 0 2621 3 2622 6 2623 5 2624 6 2625 5 2626 1 2627 0

0,0000 0 1,2621 0 1,2636 0 0,0116 1 1,2174 1 0,0116 1 1,2174 1 0,0117 0 0,0120 0 1,2603 0

WL_RM_taskPtr ; bump task pointer back 1 record WL_taskRecSize WL_RM_taskPtr WL_taskRecSize ; set pointer to record behind it WL_RM_taskPtr2 WL_RM_loopCnt WL_RM_loop ; done bumping tasks upward? ; not yet

; Since we removed a record, the last record on the list ; should be NIL. 02630 02631 02632 02633 02634 02635 2630 3 2631 2 2632 5 2633 3 2634 2 2635 5 1,2202 0 0,0116 0 0,0000 1 1,2050 0 0,0116 0 0,0001 0 WL_RM_done 02636 02637 02640 02641 2636 2637 2640 2641 3 5 3 0 0,0115 0,0001 0,0121 0,0000 1 0 0 0 CAF IND EX TS CAF IND EX TS WL_maxDelay WL_RM_taskPtr TSKTIME ZERO WL_RM_taskPtr TSKADDR

; set time field to NIL

; set address field to NIL

EQU * XCH WL_RM_saveQ TS Q ; restore return address XCH WL_RM_retval ; return task address in A RET URN INC L exec_f.asm ; EXEC ;================= ========================================================= ; EXEC (file:exec_ f.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 04/26/ 2002 ; ; PURPOSE: ; Constants and so urce code for EXEC. ; ; Non-preemptive m ultitasking routines, originally implemented by J. H. ; Laning, Jr. for AGC3 and later adapted for AGC4. Briefly discussed in ; R-393, which giv es some of the software interfaces into the ; multitasking. Th is is my own recreation, and it only includes the job ; scheduling. The original EXEC also includes memory management for the ; eraseable memory ; this is not reproduced here. ; ; Overview: schedu led elements are called 'jobs'. Up to 7 jobs can be ; concurrently sch eduled. An 8th 'dummy' job is always scheduled. Each ; job has an assig ned priority (1-n, where 1 is the lowest priority). ; The highest prio rity job always executes. When that job terminates, ; the next highest priority job is selected for execution. If several ; jobs have the sa me priority, they are executed round-robin. ; ; A job is schedul ed for execution by calling 'NOVAC' and ; furnishing the j ob priority and starting address. ; L XCH JOB_PRIORITY ; L+1 TC NOVAC ; L+2 DS JOB_ADDRESS ; L+3 ... execution resumes here ; ; JOB_PRIORITY = a positive integer from %3 - %37776 where a higher number ; indicates hig her priority. Priorities below 3 are reserved for ; internal EXEC use: 0=no job, 1=sleeping job, 2=dummy job. ; Priority %377 77 is also reserved for woken jobs. ; JOB_ADDRESS = st arting address of the job. ; ; **** WARNING *** * If NOVAC is not being called from an interrupt, be sure to ; inhibit interrup ts before calling it to protect the integrity of the list. ; ; When a new job i s added, the new job's record (core set) is ; initialized with a copy of the current job's record (MPAC and other ; parameters), exc ept for the new job priority and address, which are ; set by the 'add job' routine. Therefore, data can be stored into

; MPAC prior to st arting a new job as a method of passing data into ; the new job. ; ; Jobs terminate t hemselves by jumping to ENDOFJOB. This removes them ; from the EXEC sc heduler: ; TC ENDOFJOB ; ; Jobs can suspend themselves (yield to a higher priority job) by ; executing the fo llowing sequence. If there is no other job of ; higher priority, executing of the yielded job resumes at L+2 ; L CCS newJob ; L+1 TC CHANG1 ; L+2 ... execution resumes here ; ; If there is no o ther job of equal or higher priority, the branch is ; not taken. ; ; Jobs can put the mselves to sleep by calling JOBSLEEP. The address ; where execution of the sleeping job should resume must be in register ; A before calling JOBSLEEP. The job will remain sleeping until JOBWAKE ; is called: ; ; L CAF WAKECADR ; L+1 TC JOBSLEEP ; (does not return from JOBSLEEP) ; ; Sleeping jobs ar e awakened by calling JOBWAKE. The address where ; execution of the sleeping job should resume must be in register A. ; JOBWAKE returns to the address after the call and execution continues ; for the calling job. The job that was sleeping will now be the next ; job to execute. ; ; L CAF WAKECADR ; L+1 TC JOBWAKE ; L+2 ... execution continues here ; ;================= ========================================================= 02642 02643 02644 02645 02646 02647 02650 02651 02652 02653 2642 2643 2644 2645 2646 2647 2650 2651 2652 2653 37777 1 EX_WAKE_PRIO 00002 0 EX_DUMMY_PRIO 00001 0 EX_SLEEP_PRIO DS DS DS %37777 %00002 %00001 EX_currentJob ; waking job priority (highest) ; dummy job priority (lowest runnable) ; sleeping job; must be < dummy ; starting address for current job

00130 0 EX_jobCurStart DS 00015 00300 00307 00306 00006 00005 0 1 0 1 1 1 EX_jobRecSize EX_jobLstStart EX_jobLstEnd EX_jobLstEnd1 EX_numJobs EX_numJobs1 DS DS DS DS DS DS

JRECSZ ; size of a job record (words) EX_jobList ; starting address for jobList MAXJOBS+EX_jobList MAXJOBS-1+EX_jobList MAXJOBS-1 ; init loop counter for all jobs MAXJOBS-2 ; init loop counter for all jobs - 1

02654 02655

2654 2655

; enumerated types for setting change flag: 00001 0 EX_changeJob DS CHGJOB ; change job 00000 1 EX_keepJob DS KEEPJOB ; keep job

;----------------- --------------------------------------------------------; EX_exec -- EXEC SCHEDULER ; ; Executes the hig hest priority job. Enables interrupts while the job is ; running. Once ca lled, this function never returns. ;----------------- --------------------------------------------------------EX_exec EQU * ; entry point

; Add a dummy job (lowest priority) that never terminates. 02656 02657 02660 02661 2656 3 2657 0 2660 2661 2 1,2643 1,3162 03510 0,0000 1 1 0 0 CAF TC DS INH INT EX_DUMMY_PRIO NOVAC dumJob ; job priority ; 14 bit job address ; inhibit RUPTs enab by addJob

; Get the next job to run. EX_MN_findJob 02662 2662 0 1,3410 1 EQU TCR * EX_remove

; compare priority of current job to priority of next waiting job. ; If next job has same priority as current job, set the newJob ; flag so they wil l be scheduled round-robin. 02663 02664 02665 02666 2663 4 2664 2 2665 2 2666 6 0,0143 0 1,2647 1 0,0000 0 0,0143 1 CS IND EX IND EX AD PRIORITY ; get priority of current job

EX_jobLstStart 0 PRIORITY ; compare with priority of next job

02667 02670 02671 02672 02673 02674 02675 02676

2667 2670 2671 2672 2673

1 0 0 0 0

0,0000 1,2677 1,2677 1,2674 1,2677

0 0 0 0 0

CCS TC TC TC TC CAF TS TC EX_MN_setFlg EQU CAF TS

A EX_MN_setFlg EX_MN_setFlg *+2 EX_MN_setFlg EX_keepJob newJob EX_MN_runJob * EX_changeJob newJob

; ; ; ; ;

next job has equal priority? >0 (error!) +0 yes, set flag <0 no, clear flag -0 yes, set flag

2674 3 2675 5 2676 0

1,2655 0 0,0307 0 1,2701 0

; clear change flag

02677 02700

2677 3 2700 5

1,2654 1 0,0307 0

; set change flag

; Start the job. I nterrupts are reenabled before 'EX_curJobPtr' is ; referenced, but the interrupts can only call 'NOVAC' which does ; not change 'EX_c urJobPtr'. ; The job address is always 14-bit, so check whether the address falls ; within erasable or fixed-fixed memory. If so, use it as-is; otherwise, ; set the bank reg ister and change the address to 12-bit. EX_MN_runJob 02701 02702 02703 02704 02705 02706 02707 02710 02711 02712 02713 02714 02715 02716 02717 2701 3 2702 6 2703 5 2704 2705 2706 2707 2710 2711 4 6 1 0 0 0 1,2050 0 0,0140 1 0,0333 1 0,0000 1,2102 0,0000 1,2720 1,2712 1,2712 0 0 0 0 1 1 EQU CAF AD TS COM AD CCS TC TC TC CAF AD TS MAS K AD TS EX_MN_runIt 02720 02721 02722 2720 2 2721 2 2722 0 0,0000 1 0,0333 0 0,0000 1 EQU REL INT IND EX TC * ZERO LOC EX_MN_runAddr

; save job's 14 bit address

bankAddr A EX_MN_runIt *+2 *+1 ZERO EX_MN_runAddr BANK lowAddr bankAddr EX_MN_runAddr * EX_MN_runAddr 0

; ; ; ; ;

-(14bitAddr)+%6000 job is bank addressed? >0 no, just run it, as is +0 yes <0 yes

2712 3 2713 6 2714 5 2715 7 2716 6 2717 5

1,2050 0 0,0333 1 0,0015 0 1,2103 0 1,2102 0 0,0333 1

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; enable interrupts ; apply indirect address to next instr. ; run the job

; Job is terminate d. Delete the job record. ENDOFJOB 02723 02724 2723 2 2724 0 0,0000 0 1,2662 1 ; ; ; ; EQU INH INT TC * EX_MN_findJob ; inhibit interrupts ; get next job

job is sleeping. Keep the job record, but drop the priority so it is below the pri ority of the dummy job. This will keep the job from running unt il JOBWAKE is called. The address where it should resume running w hen awoken is in register A. EQU INH INT TS CAF TS TS TC * LOC EX_SLEEP_PRIO PRIORITY EX_IS_newPrio EX_MN_mvRec ; inhibit interrupts ; save restart address

JOBSLEEP 02725 02726 02727 02730 02731 02732 2725 2 2726 5 2727 3 2730 5 2731 5 2732 0 0,0000 0 0,0140 1 1,2644 0 0,0143 1 0,0346 0 1,2757 0

; set sleeping priority

; finish up

; Job is suspended . Keep the job record, but update the address, so ; execution will r esume at the point after suspension. CHANG1 02733 02734 02735 02736 02737 02740 02741 02742 02743 02744 02745 2733 2 2734 3 2735 5 2736 2737 2740 2741 2742 2743 4 6 1 0 0 0 0,0000 0 0,0001 0 0,0333 1 0,0000 1,2102 0,0000 1,2750 1,2744 1,2744 0 0 0 1 1 1 EQU INH INT XCH TS COM AD CCS TC TC TC CS AD * ; inhibit interrupts Q EX_MN_runAddr ; save job's 12 bit restart address

bankAddr A EX_MN_notBank *+2 *+1 bankAddr EX_MN_runAddr

; ; ; ; ;

-(12bitAddr)+%6000 job is bank addressed? >0 no, just save it, as is +0 yes <0 yes

2744 4 2745 6

1,2102 1 0,0333 1

; 12bitAddr - %6000

02746 02747

2746 6 2747 0

0,0015 0 1,2752 0 EX_MN_notBank

AD TC EQU CAF AD EQU TS CAF AD TS TS

BANK EX_MN_saveIt * ZERO EX_MN_runAddr * LOC ZERO JOBPRIOBASE PRIORITY EX_IS_newPrio

; make it a 14-bit address

02750 02751

2750 3 2751 6

1,2050 0 0,0333 1 EX_MN_saveIt

; get restart address

02752 02753 02754 02755 02756

2752 5 2753 2754 2755 2756 3 6 5 5

0,0140 1 1,2050 0,0144 0,0143 0,0346 0 0 1 0

; save job's new starting address

; restore job priority to nominal value

; given the priori ty, find the insertion point in the list. Copy ; the current job into the list at the correct insertion point. EX_MN_mvRec 02757 02760 2757 0 2760 5 1,3332 0 0,0352 0 EQU TCR TS * EX_findIns EX_IS_jobPtr

; save address of insertion point

; copy all fields in current record to list 02761 02762 2761 3 2762 5 1,2646 1 0,0334 0 EX_MN_loop3 02763 02764 02765 02766 2763 2764 2765 2766 1 0 0 5 0,0334 1,2766 1,3002 0,0334 1 1 0 0 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_MN_field * EX_MN_field *+2 EX_MN_done3 EX_MN_field

; done? ; not yet ; yes

; copy this field to list 02767 02770 02771 02772 02773 02774 02775 02776 02777 03000 03001 2767 2770 2771 2772 2773 2774 2775 2776 2777 3000 3 2 6 6 5 3 2 6 2 5 1,2050 0,0352 0,0000 0,0334 0,0335 1,2050 0,0334 0,0130 0,0335 0,0130 0 1 1 0 1 0 1 0 0 0 CAF IND EX AD AD TS CAF IND EX AD IND EX TS TC EX_MN_done3 03002 3002 0 1,2662 1 EQU TC ZERO EX_IS_jobPtr 0 EX_MN_field EX_MN_findx ZERO EX_MN_field EX_currentJob EX_MN_findx EX_currentJob EX_MN_loop3 * EX_MN_findJob

; get index to record in list ; add field displacement ; save index to field in list

; get field from current job ; copy field to list

3001 0

1,2763 1

; get next job

;----------------- --------------------------------------------------------; JOBWAKE - wake u p the job identified by address in register A ; ; Search jobList f or a job with address matching the address in A. ; If found, bump t he priority up to the highest level, so the job ; will be the next to run. ; ; This is a 'publi c' function. It assumes that interrupts are already ; disabled before it is called. Disabling interrupts during JOBWAKE ; is necessary to preserve the integrity of the joblist. ;----------------- --------------------------------------------------------JOBWAKE 03003 03004 03005 3003 5 3004 3 3005 5 0,0312 1 0,0001 0 0,0310 0 EQU TS XCH TS * EX_JW_CADR Q EX_JW_saveQ

; save job address ; save return address

; Search the jobli st for the job to wake (job address matches ; EX_JW_CADR). 03006 03007 03010 03011 03012 03013 03014 03015 3006 3 3007 5 3010 3 3011 5 3012 6 3013 5 3014 3 3015 5 1,2050 0 0,0313 0 1,2651 1 0,0314 1 1,2046 1 0,0315 0 1,2653 0 EX_JW_loop 0,0311 1 CAF TS CAF TS AD TS CAF EQU TS ZERO EX_JW_foundit EX_jobLstEnd1 EX_JW_jobPtr NEG1 EX_JW_jobPtr2 EX_numJobs1 * EX_JW_loopCnt

; clear 'found it' flag ; set pointer to back of list

; set pointer to rec in front of it

; loop for number of jobs minus 1

; if foundit=0, jo b has not been found yet. Keep searching toward

; the front of t he list. ; if foundit=1, th e job has been found and removed from the list. ; push all jobs in front of the removed job one step to the back ; to fill in the gap and to make room at the front of the list ; for the awoken job. 03016 03017 3016 1 3017 0 0,0313 1 1,3035 1 CCS TC ; Is this the job? 03020 03021 03022 03023 03024 03025 03026 03027 3020 3021 3022 3023 3024 3025 3026 3027 4 2 2 6 1 0 0 0 0,0312 0,0314 0,0000 0,0140 0,0000 1,3041 1,3030 1,3041 0 0 0 1 0 1 1 1 CS IND EX IND EX AD CCS TC TC TC ; found the job to wake. 03030 03031 3030 3 3031 5 1,2051 1 0,0313 0 CAF TS ONE EX_JW_foundit EX_JW_CADR EX_JW_jobPtr 0 LOC A EX_JW_bumpPtr *+2 EX_JW_bumpPtr EX_JW_foundit EX_JW_moveRec ; already found job to wake? ; >0, yes

; ; ; ;

found job to wake? >0, no +0, yes <0, no

; set 'found it' flag

; save record inde x for awoken job 03032 03033 03034 3032 2 3033 3 3034 5 0,0314 0 0,0000 1 0,0316 0 IND EX XCH TS ; bump prior recor d back EX_JW_moveRec 03035 03036 03037 03040 3035 3036 3037 3040 2 3 2 3 0,0315 0,0000 0,0314 0,0000 1 1 0 1 EX_JW_bumpPtr 03041 03042 03043 03044 03045 03046 03047 03050 03051 03052 03053 03054 03055 3041 3 3042 6 3043 5 3044 6 3045 5 3046 1 3047 0 3050 1 3051 0 3052 0 3053 3 3054 2 3055 5 0,0314 1 1,2046 1 0,0314 1 1,2046 1 0,0315 0 0,0311 0 1,3015 0 0,0313 1 1,3053 1 1,3056 1 0,0316 0 1,2647 1 0,0000 1 EX_JW_done EQU IND EX XCH IND EX XCH EQU XCH AD TS AD TS CCS TC CCS TC TC XCH IND EX TS EQU * EX_JW_jobPtr2 0 EX_JW_jobPtr 0 * EX_JW_jobPtr NEG1 EX_JW_jobPtr NEG1 EX_JW_jobPtr2 EX_JW_loopCnt EX_JW_loop EX_JW_foundit *+2 EX_JW_done EX_JW_jobPtr 0 EX_JW_fndIndx

; index for awoken job

; bump job pointer forward 1 record

; set pointer to record in front of it

; done bumping jobs backward? ; not yet ; found job to wake? ; >0, yes ; no

EX_JW_fndIndx ; put awoken job on front of list EX_jobLstStart 0 *

; Is the awoken jo b at the front of the list? ; (If it was alrea dy there before we started searching, 'foundIt' ; will be false (0 ) so we need to make this test). 03056 03057 03060 03061 03062 03063 03064 03065 3056 3057 3060 3061 3062 3063 3064 3065 4 2 2 6 1 0 0 0 0,0312 1,2647 0,0000 0,0140 0,0000 1,3074 1,3066 1,3074 0 1 0 1 0 1 1 1 CS IND EX IND EX AD CCS TC TC TC EX_JW_CADR EX_jobLstStart 0 LOC A EX_JW_return *+2 EX_JW_return

; ; ; ;

woken job at front of list? >0, no +0, yes <0, no

; set awoken prior ity and change job flag 03066 03067 03070 03071 03072 03073 3066 3067 3070 3071 3 2 2 5 1,2642 1,2647 0,0000 0,0143 0 1 0 1 CAF IND EX IND EX TS CAF TS EX_JW_return 03074 3074 0 0,0310 0 EQU TC EX_WAKE_PRIO EX_jobLstStart 0 PRIORITY ; set waking priority EX_changeJob newJob * EX_JW_saveQ ; set the change flag

3072 3 3073 5

1,2654 1 0,0307 0

; return

;----------------- --------------------------------------------------------; SPVAC - ADD A JO B TO THE JOBLIST ; ; Similar to NOVAC , but used by VERB 37. The job CADR is in register A. ; The job priority is in NEWPRIO. Return to the address in Q. ; ; NOVAC differs fr om SPVAC, because NOVAC has the job CADR at the address ; in Q, and return s to Q+1. Also, in NOVAC the job priority is in A. ; ; This is a 'publi c' function. It can be called from a job ; or from an inter rupt. ;----------------- --------------------------------------------------------SPVAC 03075 03076 03077 3075 5 3076 3 3077 5 0,0350 1 0,0001 0 0,0317 1 EQU TS XCH TS * EX_IS_newLoc Q EX_AJ_saveQ

; store new job address ; save return address

; add new job to e nd of list 03100 03101 03102 03103 03104 03105 3100 3101 3102 3103 3 6 5 5 1,2050 0,0360 0,0346 0,0347 0 1 0 1 CAF AD TS TS TCR TS ZERO NEWPRIO EX_IS_newPrio EX_IS_newPrioB ; store new job priority EX_findIns EX_IS_jobPtr ; find insertion point in list ; save address of insertion point

3104 0 3105 5

1,3332 0 0,0352 0

; Initialize relev ant fields in new job. The remaining fields ; should already b e zeroed.

; Initialize field s for new job record. New job inherits copy of ; MPAC from curren t job, so copy all fields in current job to new ; job in list 03106 03107 3106 3 3107 5 1,2646 1 0,0323 0 EX_SP_loop1 03110 03111 03112 03113 3110 3111 3112 3113 1 0 0 5 0,0323 1,3113 1,3127 0,0323 1 1 0 0 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_AJ_field * EX_AJ_field *+2 EX_SP_done1 EX_AJ_field

; done? ; not yet ; yes

; copy this field to list 03114 03115 03116 03117 03120 03121 03122 03123 03124 03125 03126 3114 3115 3116 3117 3120 3121 3122 3123 3124 3125 3 2 6 6 5 3 2 6 2 5 1,2050 0,0352 0,0000 0,0323 0,0324 1,2050 0,0323 0,0130 0,0324 0,0130 0 1 1 0 1 0 1 0 0 0 CAF IND EX AD AD TS CAF IND EX AD IND EX TS TC ZERO EX_IS_jobPtr 0 EX_AJ_field EX_AJ_findx ZERO EX_AJ_field EX_currentJob EX_AJ_findx EX_currentJob EX_SP_loop1

; get index to record in list ; add field displacement ; save index to field in list

; get field from current job ; copy field to list

3126 0

1,3110 1

; now, overwrite f ields in the record with the priority ; and location uni que to this job. EX_SP_done1 03127 03130 03131 03132 03133 03134 03135 03136 03137 03140 03141 03142 03143 03144 03145 3127 3130 3131 3132 3133 3134 3135 3136 3137 3140 3141 3142 3143 3144 3145 3 6 2 2 5 3 6 2 2 5 3 6 2 2 5 1,2050 0,0346 0,0352 0,0000 0,0143 1,2050 0,0347 0,0352 0,0000 0,0144 1,2050 0,0350 0,0352 0,0000 0,0140 0 0 1 0 1 0 1 1 0 0 0 1 1 0 1 EQU CAF AD IND EX IND EX TS CAF AD IND EX IND EX TS CAF AD IND EX IND EX TS * ZERO EX_IS_newPrio EX_IS_jobPtr 0 PRIORITY

; set priority field

ZERO EX_IS_newPrioB EX_IS_jobPtr 0 JOBPRIOBASE ; set nominal priority field ZERO EX_IS_newLoc EX_IS_jobPtr 0 LOC

; set address field

; Set changeflag i f priority of new job >= priority of current job

EX_SP_testFlg 03146 03147 03150 03151 03152 03153 03154 03155 3146 4 3147 3150 3151 3152 3153 6 1 0 0 0 0,0143 0 0,0321 0,0000 1,3154 1,3154 1,3156 1 0 1 1 0

EQU CS AD CCS TC TC TC CAF TS

* PRIORITY EX_AJ_jobPrio A *+3 *+2 EX_SP_done2 EX_changeJob newJob * EX_AJ_saveQ Q

; get -priority of current job ; ; ; ; ; add new >0, +0, <0, positive priority of new job job is highest priority? yes yes no, current job is higher priority

3154 3 3155 5

1,2654 1 0,0307 0 EX_SP_done2

; set the change flag

03156 03157 03160

3156 3 3157 5 3160 0

0,0317 1 0,0001 0 0,0000 0

EQU XCH TS RET URN

;----------------- --------------------------------------------------------; FINDVAC - not im plemented ; ;----------------- --------------------------------------------------------03161 3161 0 0,0001 0 FINDVAC TC Q ; just return

;----------------- --------------------------------------------------------; NOVAC - ADD A JO B TO THE JOBLIST ; ; Search jobList f or an empty slot. If found, put the new job in the ; empty slot. If t he new job has the same, or higher, priority than the ; current job, set the change flag to 'CHGJOB' (change jobs at the next ; opportunity). ; ; This is a 'publi c' function. It can be called from a job ; or from an inter rupt. ;----------------- --------------------------------------------------------NOVAC 03162 03163 03164 3162 5 3163 3 3164 5 0,0321 1 0,0001 0 0,0317 1 EQU TS XCH TS * EX_AJ_jobPrio Q EX_AJ_saveQ

; save job priority ; save return address-1

; add new job to e nd of list 03165 03166 03167 03170 03171 03172 03173 03174 03175 3165 3166 3167 3170 3 6 5 5 1,2050 0,0321 0,0346 0,0347 0 1 0 1 CAF AD TS TS IND EX CAF TS TCR TS ZERO EX_AJ_jobPrio EX_IS_newPrio EX_IS_newPrioB ; store new job priority EX_AJ_saveQ 0 EX_IS_newLoc EX_findIns EX_IS_jobPtr ; indirectly address addJobQ ; store new job address ; find insertion point in list ; save address of insertion point

3171 2 3172 3 3173 5 3174 0 3175 5

0,0317 0 0,0000 1 0,0350 1 1,3332 0 0,0352 0

; Initialize relev ant fields in new job. The remaining fields ; should already b e zeroed.

; Initialize field s for new job record. New job inherits copy of ; MPAC from curren t job, so copy all fields in current job to new ; job in list 03176 03177 3176 3 3177 5 1,2646 1 0,0323 0 EX_AJ_loop1 03200 03201 03202 03203 3200 3201 3202 3203 1 0 0 5 0,0323 1,3203 1,3217 0,0323 1 0 0 0 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_AJ_field * EX_AJ_field *+2 EX_AJ_done1 EX_AJ_field

; done? ; not yet ; yes

; copy this field to list 03204 03205 03206 03207 03210 03211 03212 03213 03214 3204 3205 3206 3207 3210 3211 3212 3213 3214 3 2 6 6 5 3 2 6 2 1,2050 0,0352 0,0000 0,0323 0,0324 1,2050 0,0323 0,0130 0,0324 0 1 1 0 1 0 1 0 0 CAF IND EX AD AD TS CAF IND EX AD IND EX ZERO EX_IS_jobPtr 0 EX_AJ_field EX_AJ_findx ZERO EX_AJ_field EX_currentJob EX_AJ_findx

; get index to record in list ; add field displacement ; save index to field in list

; get field from current job

03215 03216

3215 5 3216 0

0,0130 0 1,3200 0

TS TC

EX_currentJob EX_AJ_loop1

; copy field to list

; now, overwrite f ields in the record with the priority ; and location uni que to this job. EX_AJ_done1 03217 03220 03221 03222 03223 03224 03225 03226 03227 03230 03231 03232 03233 03234 03235 3217 3220 3221 3222 3223 3224 3225 3226 3227 3230 3231 3232 3233 3234 3235 3 6 2 2 5 3 6 2 2 5 3 6 2 2 5 1,2050 0,0346 0,0352 0,0000 0,0143 1,2050 0,0347 0,0352 0,0000 0,0144 1,2050 0,0350 0,0352 0,0000 0,0140 0 0 1 0 1 0 1 1 0 0 0 1 1 0 1 EQU CAF AD IND EX IND EX TS CAF AD IND EX IND EX TS CAF AD IND EX IND EX TS * ZERO EX_IS_newPrio EX_IS_jobPtr 0 PRIORITY

; set priority field

ZERO EX_IS_newPrioB EX_IS_jobPtr 0 JOBPRIOBASE ; set nominal priority field ZERO EX_IS_newLoc EX_IS_jobPtr 0 LOC

; set address field

; Set changeflag i f priority of new job >= priority of current job EX_AJ_testFlg 03236 03237 03240 03241 03242 03243 03244 03245 3236 4 3237 3240 3241 3242 3243 6 1 0 0 0 0,0143 0 0,0321 0,0000 1,3244 1,3244 1,3246 1 0 0 0 1 EQU CS AD CCS TC TC TC CAF TS EX_AJ_done2 03246 03247 03250 03251 3246 3247 3250 3251 3 6 5 0 0,0317 1,2051 0,0001 0,0000 1 1 0 0 EQU XCH AD TS RET URN * PRIORITY EX_AJ_jobPrio A *+3 *+2 EX_AJ_done2 EX_changeJob newJob * EX_AJ_saveQ ONE Q

; get -priority of current job ; ; ; ; ; add new >0, +0, <0, positive priority of new job job is highest priority? yes yes no, current job is higher priority

3244 3 3245 5

1,2654 1 0,0307 0

; set the change flag

;----------------- --------------------------------------------------------; EX_initEX - INIT IALIZE EXEC ; ; Initialize the e raseable memory segment for EXEC. Necessary in ; case the AGC is restarted. ;----------------- --------------------------------------------------------EX_initEX 03252 03253 03254 03255 03256 03257 3252 3 3253 5 3254 3 3255 5 3256 3 3257 5 0,0001 0 0,0325 0 1,2655 0 0,0307 0 1,2050 0 0,0143 1 EQU XCH TS CAF TS CAF TS * Q EX_IN_saveQ EX_keepJob newJob ZERO PRIORITY

; save return address ; clear change flag

; set current job record to NIL

; Iterate through jobList, initialize each element on the list so it ; points to its ow n job record. 03260 03261 03262 03263 03264 03265 03266 03267 03270 03271 03272 03273 03274 03275 3260 3 3261 5 3262 3 3263 6 3264 5 3265 3 3266 5 3267 3270 3271 3272 3273 3 2 5 6 5 1,2647 0 0,0327 1 1,2050 0 1,2646 1 0,0330 1 1,2652 1 EX_IN_loop1 0,0326 0 0,0330 0,0327 0,0000 1,2646 0,0330 1 0 1 1 1 CAF TS CAF AD TS CAF EQU TS XCH IND EX TS AD TS XCH AD EX_jobLstStart ; init pointer to start of list EX_IN_jobPtr ZERO EX_jobRecSize EX_IN_recIndex EX_numJobs * EX_IN_loopCnt ; loop for number of jobs

EX_IN_recIndex EX_IN_jobPtr 0 ; initialize record index EX_jobRecSize EX_IN_recIndex ; bump index to next record EX_IN_jobPtr ONE ; bump job pointer back 1 record

3274 3 3275 6

0,0327 1 1,2051 1

03276 03277 03300

3276 5 3277 1 3300 0

0,0327 1 0,0326 1 1,3266 0

TS CCS TC

EX_IN_jobPtr EX_IN_loopCnt EX_IN_loop1 ; done clearing jobList? ; not yet

; Iterate through job records, initialize each field to zero. 03301 03302 03303 03304 3301 3 3302 5 3303 3 3304 5 1,2647 0 0,0327 1 1,2652 1 EX_IN_loop2 0,0326 0 CAF TS CAF EQU TS EX_jobLstStart ; init pointer to start of list EX_IN_jobPtr EX_numJobs * EX_IN_loopCnt ; loop for number of jobs

; loop for number of fields in each record 03305 03306 3305 3 3306 5 1,2646 1 0,0331 0 EX_IN_loop3 03307 03310 03311 03312 3307 3310 3311 3312 1 0 0 5 0,0331 1,3312 1,3324 0,0331 1 1 1 0 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_IN_field * EX_IN_field *+2 EX_IN_done EX_IN_field

; done? ; not yet ; yes

; set the field to zero 03313 03314 03315 03316 03317 03320 03321 03322 03323 3313 3314 3315 3316 3317 3320 3321 3322 3 2 6 6 5 3 2 5 1,2050 0,0327 0,0000 0,0331 0,0332 1,2050 0,0332 0,0130 0 0 1 0 0 0 1 0 CAF IND EX AD AD TS CAF IND EX TS TC ZERO EX_IN_jobPtr 0 EX_IN_field EX_IN_findx ZERO EX_IN_findx EX_currentJob EX_IN_loop3

; get index to record ; add field displacement ; save index to field

; clear field

3323 0

1,3307 0

; done clearing al l fields in record, so do next record EX_IN_done 03324 03325 03326 03327 03330 03331 3324 3 3325 6 3326 5 3327 1 3330 0 3331 0 0,0327 1 1,2051 1 0,0327 1 0,0326 1 1,3304 0 0,0325 0 EQU XCH AD TS CCS TC TC * EX_IN_jobPtr ONE EX_IN_jobPtr EX_IN_loopCnt EX_IN_loop2 EX_IN_saveQ

; bump job pointer back 1 record

; done clearing jobList? ; not yet ; return

;----------------- --------------------------------------------------------; EX_findIns - FIN D INSERTION POINT INTO SORTED LIST ; ; Insert a job rec ord into the sorted list. Use 'EX_IS_newPrio', ; EX_IS_newPrioB a nd 'EX_IS_newLoc' to set the fields of record to ; be inserted. ; Performs an inse rtion sort, with the records sorted by priority. ; Highest priority is at the front of the list. If several records ; have the same pr iority, the records inserted first will appear first ; in the list. NIL records have a priority of zero. ;----------------- --------------------------------------------------------EX_findIns 03332 03333 03334 03335 03336 03337 03340 03341 03342 03343 03344 03345 3332 3 3333 5 3334 3 3335 5 3336 6 3337 5 3340 3341 3342 3343 3 2 2 6 0,0001 0 0,0351 0 1,2651 1 0,0352 0 1,2046 1 0,0353 1 1,2050 0,0352 0,0000 0,0143 0 1 0 1 EQU XCH TS CAF TS AD TS CAF IND EX IND EX AD CCS TC * Q EX_IS_saveQ EX_jobLstEnd1 EX_IS_jobPtr NEG1 EX_IS_jobPtr2 ZERO EX_IS_jobPtr 0 PRIORITY A EX_FI_done

; save return address ; set pointer to back of list

; set pointer to rec in front of it

; check last record on list ; list full? ; >0 yes

3344 1 3345 0

0,0000 0 1,3405 0

; Work from the ba ck of the list to the front, pushing each record ; to the back unti l the insertion point is found. 03346 3346 3 1,2653 0 EX_FI_loop CAF EQU EX_numJobs1 * ; loop for number of jobs minus 1

03347 03350 03351 03352 03353 03354 03355 03356

3347 5 3350 3351 3352 3353 3354 3355 3356 3 2 2 6 1 0 0

0,0354 0 1,2050 0,0353 0,0000 0,0143 0,0000 1,3357 1,3376 0 0 0 1 0 0 0

TS CAF IND EX IND EX AD CCS TC TC

EX_IS_loopCnt ZERO EX_IS_jobPtr2 0 PRIORITY A *+2 EX_FI_bumpPtr

; previous record is NIL? ; no, so check it ; yes, so skip to next record

; Is this the inse rtion point? 03357 03360 03361 03362 03363 03364 03365 03366 03367 3357 3360 3361 3362 3363 3364 3365 3366 3367 4 2 2 6 1 0 0 0 0 0,0346 0,0353 0,0000 0,0143 0,0000 1,3405 1,3405 1,3370 1,3405 1 0 0 1 0 0 0 0 0 CS IND EX IND EX AD CCS TC TC TC TC EX_IS_newPrio EX_IS_jobPtr2 0 PRIORITY A EX_FI_insRec EX_FI_insRec *+2 EX_FI_insRec

; ; ; ; ;

found insertion point? >0 yes +0 yes <0 no, keep checking -0 yes

; No, bump the rec ord toward the back of the list. 03370 03371 03372 03373 03374 03375 3370 3371 3372 3373 3374 3375 2 3 2 3 2 3 0,0353 0,0000 0,0352 0,0000 0,0353 0,0000 0 1 1 1 0 1 EX_FI_bumpPtr 03376 03377 03400 03401 03402 03403 03404 3376 3 3377 6 3400 5 3401 6 3402 5 3403 1 3404 0 0,0352 0 1,2046 1 0,0352 0 1,2046 1 0,0353 1 0,0354 1 1,3347 1 IND EX XCH IND EX XCH IND EX XCH EQU XCH AD TS AD TS CCS TC EX_IS_jobPtr2 0 EX_IS_jobPtr 0 EX_IS_jobPtr2 0 * EX_IS_jobPtr NEG1 EX_IS_jobPtr NEG1 EX_IS_jobPtr2 EX_IS_loopCnt EX_FI_loop

; bump job pointer forward 1 record

; set pointer to record in front of it

; done bumping jobs backward? ; not yet

; New record shoul d be inserted at EX_IS_jobPtr. EX_FI_insRec EX_FI_done 03405 03406 03407 3405 3 3406 6 3407 0 1,2050 0 0,0352 0 0,0351 0 EQU EQU CAF AD TC * * ZERO EX_IS_jobPtr EX_IS_saveQ

; get insertion spot in list ; return

;----------------- --------------------------------------------------------; EX_remove - REMO VE JOB FROM FRONT OF LIST ; ; Remove job from front of list and copy it to the current job. Bubble ; any remaining jo bs toward the front of the list. ;----------------- --------------------------------------------------------EX_remove 03410 03411 03412 03413 03414 03415 3410 3 3411 5 3412 3 3413 5 3414 6 3415 5 0,0001 0 0,0336 1 1,2647 0 0,0337 0 1,2051 1 0,0340 0 EQU XCH TS CAF TS AD TS * Q EX_RM_saveQ

; save return address

EX_jobLstStart ; set pointer to front of list EX_RM_jobPtr ONE EX_RM_jobPtr2 ; set pointer to next rec behind it

; Dequeue the reco rd at the top of the list (the next job to run). ; Make it the curr ent job by copying it to the current job record. 03416 03417 3416 3 3417 5 1,2646 1 0,0344 1 EX_RM_loop1 03420 03421 03422 03423 3420 3421 3422 3423 1 0 0 5 0,0344 1,3423 1,3437 0,0344 0 1 1 1 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_RM_field * EX_RM_field *+2 EX_RM_done1 EX_RM_field

; done? ; not yet ; yes

; copy field from list to current job 03424 03425 03426 3424 3 3425 2 3426 6 1,2050 0 0,0337 1 0,0000 1 CAF IND EX AD ZERO EX_RM_jobPtr 0

; get index to record

03427 03430 03431 03432 03433 03434 03435 03436

3427 3430 3431 3432 3433 3434 3435

6 5 3 2 6 2 5

0,0344 0,0345 1,2050 0,0345 0,0130 0,0344 0,0130

1 0 0 1 0 0 0

AD TS CAF IND EX AD IND EX TS TC

EX_RM_field EX_RM_findx ZERO EX_RM_findx EX_currentJob EX_RM_field EX_currentJob EX_RM_loop1

; add field displacement ; save index to field

; get field ; move to current job

3436 0

1,3420 1

; done copying rec ord for current job. Restore the current job to ; its default prio rity, in case it was previously elevated. EX_RM_done1 03437 03440 03441 03442 03443 03444 3437 3 3440 6 3441 5 3442 2 3443 3 3444 5 1,2050 0 0,0144 0 0,0143 1 0,0337 1 0,0000 1 0,0341 1 EQU CAF AD TS IND EX XCH TS * ZERO JOBPRIOBASE PRIORITY EX_RM_jobPtr 0 EX_RM_savePtr

; so we can move it to the end later

; Loop through the remaining records in the job list and ; bubble them up t o the front. 03445 03446 3445 3 3446 5 1,2653 0 EX_RM_loop2 0,0342 1 CAF EQU TS EX_numJobs1 * EX_RM_loopCnt ; loop for number of jobs minus 1

03447 03450 03451 03452 03453 03454 03455 03456 03457 03460 03461 03462 03463 03464

3447 3450 3451 3452

2 3 2 5

0,0340 0,0000 0,0337 0,0000

1 1 1 1

IND EX XCH IND EX TS CCS TC TC XCH AD TS AD TS CCS TC

EX_RM_jobPtr2 0 EX_RM_jobPtr 0 A *+2 EX_RM_done2 EX_RM_jobPtr ONE EX_RM_jobPtr ONE EX_RM_jobPtr2 EX_RM_loopCnt EX_RM_loop2 ; remainder of list empty? ; >0, no ; +0, yes, so exit ; bump job pointer back 1 record

3453 1 3454 0 3455 0 3456 3 3457 6 3460 5 3461 6 3462 5 3463 1 3464 0

0,0000 0 1,3456 0 1,3465 0 0,0337 0 1,2051 1 0,0337 0 1,2051 1 0,0340 0 0,0342 0 1,3446 1

; set pointer to record behind it

; done bumping jobs upward? ; not yet

; Since we removed a record, the last record on the list ; should be NIL. EX_RM_done2 03465 03466 03467 3465 3 3466 2 3467 5 0,0341 1 0,0337 1 0,0000 1 EQU XCH IND EX TS * EX_RM_savePtr EX_RM_jobPtr 0

; move the index for the top record ; to the bottom of the list

; set all fields i n NIL record to zero 03470 03471 3470 3 3471 5 1,2646 1 0,0344 1 EX_RM_loop3 03472 03473 03474 03475 3472 3473 3474 3475 1 0 0 5 0,0344 1,3475 1,3507 0,0344 0 1 0 1 XCH TS EQU CCS TC TC TS EX_jobRecSize EX_RM_field * EX_RM_field *+2 EX_RM_done3 EX_RM_field

; done? ; not yet ; yes

; set this field t o zero 03476 03477 03500 03501 03502 03503 03504 03505 03506 3476 3477 3500 3501 3502 3503 3504 3505 3 2 6 6 5 3 2 5 1,2050 0,0337 0,0000 0,0344 0,0345 1,2050 0,0345 0,0130 0 1 1 1 0 0 1 0 CAF IND EX AD AD TS CAF IND EX TS TC EX_RM_done3 03507 3507 0 0,0336 1 EQU TC ZERO EX_RM_jobPtr 0 EX_RM_field EX_RM_findx ZERO EX_RM_findx EX_currentJob EX_RM_loop3 * EX_RM_saveQ

; get index to record ; add field displacement ; save index to field

; clear field

3506 0

1,3472 0

; return

;----------------- ---------------------------------------------------------

; DUMMY JOB - runs at the lowest priority and never terminates. Ensures ; that there is al ways at least one job executing. Sleeping jobs are ; given a lower pr iority than the dummy job. ; ; The dummy job co ntrols the computer activity light on the DSKY. When ; the dummy job is running, the light is off. When the dummy job is ; preempted by a h igher priority job, the light is on. ; ; I couldn't find good information on the computer activity light ; in COLOSSUS, so this is my best guess concerning its operation. It ; seems consistent witht the MPEG video of the Apollo 11 DSKY. ;----------------- ---------------------------------------------------------

; entering dummy j ob -- turn off computer activity light dumJob 03510 03511 03512 03513 3510 3511 3512 3513 3 6 7 5 1,2050 0,0011 1,3525 0,0011 0 1 1 1 EQU CAF AD MAS K TS * ZERO DSALMOUT NOTACTLT DSALMOUT

; turn bit1 off

; runtime loop for dummy job dumJob1 03514 03515 03516 3514 1 3515 0 3516 0 0,0307 1 1,3517 1 1,3514 1 EQU CCS TC TC * newJob dumJob2 dumJob1

; check for context switch ; yes ; no

; exiting dummy jo b -- turn on computer activity light dumJob2 03517 03520 03521 03522 03523 03524 03525 3517 3520 3521 3522 4 7 4 5 0,0011 1,3525 0,0000 0,0011 0 1 0 1 EQU CS MAS K COM TS TC TC * DSALMOUT NOTACTLT DSALMOUT CHANG1 dumJob ; exit to run higher priority job ; job done, return here, light off again

; inclusive OR bit 1 with 1 using ; Demorgan's theorem

3523 0 3524 0 3525

1,2733 1 1,3510 0 77776 1 NOTACTLT

DS %77776 ; 1's compliment of bit1 (comp activity l i g h t ) INC L bank_f.asm ; bank intercommunication routines ;================= ========================================================= ; BANK INTERCOMMUN ICATION (file:bank_f.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 01/19/ 2002 ; ; PURPOSE: ; Contains bank in tercommunication routines. ; The source is mi ssing from my (incomplete) listing of COLOSSUS. The ; implementation h ere is inferred from the usage in the COLOSSUS pinball ; routines. Some o f these routines could probably be combined or optimized ; away if I unders tood the pinball software architecture a little better. ;================= ========================================================= ;----------------- --------------------------------------------------------; DXCHJUMP ; Do a bank jump t o the CADR in register A. After the bank jump, the return ; CADR is in regis ter A. Contents of register Q are destroyed. ; This is my attem pt to implement the block I equivalent for ; DCA MY2CADR ; DXCH Z ;... which is used in some places in COLOSSUS to implement bank jumps. In that ; implementation, MY2CADR has the lower portion of the address in MYCADR and ; the bank portion in MY2CADR+1. DCA loads the lower address into A and the ; bank address int o L. DXCH loads the lower address into Z and the bank portion ; into BB (both ba nk register), thereby doing a bank call. After the call, ; the lower return address is in A and the return bank is in L. ;----------------- --------------------------------------------------------DXCHJUMP EQU TS XCH TS XCH TS * ADDRWD1 Q DCRET BANK DCBANK

03526 03527 03530 03531 03532

3526 5 3527 3 3530 5 3531 3 3532 5

0,0576 0 0,0001 0 0,0617 1 0,0015 0 0,0616 0

; save 14-bit destination address

; save old return address

; save old bank

; put the 12-bit d estination address in ADDRWD1 03533 03534 03535 03536 3533 3534 3535 3536 4 6 1 0 0,0576 1,2102 0,0000 1,3547 1 0 0 1 CS AD CCS TC ADDRWD1 bankAddr A DODXCHCALL ; -(14bitAddr)+%6000 ; CADR is bank addressed? ; >0 no, just run it, as is

03537 03540 03541 03542 03543 03544 03545 03546

3537 0 3540 0 3541 3 3542 6 3543 5 3544 7 3545 6 3546 5

1,3541 1 1,3541 1 1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0

TC TC CAF AD TS MAS K AD TS

*+2 *+1 ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1

; +0 yes ; <0 yes

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable ; save 12-bit destination address

; put the 14-bit r eturn CADR into A. DODXCHCALL 03547 03550 03551 03552 03553 03554 03555 03556 03557 03560 3547 3550 3551 3552 3553 3554 3555 3556 3557 3560 4 6 1 0 0 0 4 6 6 0 0,0617 1,2102 0,0000 1,3561 1,3555 1,3555 1,2102 0,0617 0,0616 1,3563 0 0 0 0 1 1 1 1 0 1 DC_NOTBANK 03561 03562 03563 03564 3561 3 3562 6 3563 2 3564 0 1,2050 0 0,0617 1 0,0576 1 0,0000 1 EQU CS AD CCS TC TC TC CS AD AD TC EQU CAF AD IND EX TC * DCRET bankAddr A DC_NOTBANK *+2 *+1 bankAddr DCRET DCBANK *+3 * ZERO DCRET ADDRWD1 0

; ; ; ; ; ;

get 12-bit return address -(12bitAddr)+%6000 return address is bank addressed? >0 no, just use it, as is +0 yes <0 yes

; 12bitAddr - %6000 ; put return CADR in A

; put return CADR in A ; apply indirect address to next instr. ; make the jump

;----------------- --------------------------------------------------------; BANKCALL ; Do a bank jump t o the location referenced by the 14-bit address referenced ; in Q. Does not a ffect register A (but assumes A does not contain an ; overflow). Funct ionally identical to POSTJUMP. ; Usage: ; TC BANKCALL ; bank jump to CADR ; DS MYCADR ; the 14-bit address ; returns here if MYCADR calls TC Q. ; ; Inferred from th e AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;----------------- --------------------------------------------------------BANKCALL 03565 03566 03567 03570 03571 03572 03573 03574 03575 03576 03577 03600 03601 03602 03603 03604 03605 03606 03607 03610 3565 5 3566 2 3567 3 3570 5 3571 3 3572 5 3573 3 3574 5 3575 3576 3577 3600 3601 3602 4 6 1 0 0 0 0,0612 1 0,0001 1 0,0000 1 0,0576 0 0,0001 0 0,0611 1 0,0015 0 0,0610 0 0,0576 1,2102 0,0000 1,3611 1,3603 1,3603 1 0 0 1 1 1 EQU TS IND EX CAF TS XCH TS XCH TS CS AD CCS TC TC TC CAF AD TS MAS K AD TS DOBANKCALL 03611 03612 03613 3611 3 3612 2 3613 0 0,0612 1 0,0576 1 0,0000 1 EQU XCH IND EX TC * BCA Q 0 ADDRWD1 Q BCRET BANK BCBANK ADDRWD1 bankAddr A DOBANKCALL *+2 *+1 ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1 * BCA ADDRWD1 0

; save A ; load the CADR into A ; save 14-bit destination address

; save old return address-1

; save old bank ; -(14bitAddr)+%6000 ; ; ; ; CADR is bank addressed? >0 no, just run it, as is +0 yes <0 yes

3603 3 3604 6 3605 5 3606 7 3607 6 3610 5

1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; restore A ; apply indirect address to next instr. ; make the jump

; Jump returns her e; restore the old bank and return 03614 03615 03616 3614 5 3615 3 3616 5 0,0612 1 0,0610 0 0,0015 0 TS XCH TS BCA BCBANK BANK ; save A

03617 03620 03621 03622 03623

3617 3 3620 6 3621 5 3622 3 3623 0

0,0611 1 1,2051 1 0,0001 0 0,0612 1 0,0000 0

XCH AD TS XCH RET URN

BCRET ONE Q BCA

; skip CADR

; restore A

;----------------- --------------------------------------------------------; MYBANKCALL ; Functionally ide ntical to BANKCALL. Used for converting the FLASHON/FLASHOFF ; COLOSSUS block I I code to block I. In Block II, the V/N flash is controlled b y ; setting a bit in an I/O channel. In Block I, a bit in the display table must ; be set using _11 DSPIN. Because _11DSPIN is in fixed/switchable memory, but is ; called from fixe d/fixed, a bank call function is needed. The original BANKCAL L ; could not be use d because it is not reentrant and I dont understand its usage ; in COLOSSUS well enough to be certain that FLASHON/FLASHOFF isn't already ; being called som ewhere through BANKCALL. ;----------------- --------------------------------------------------------MYBANKCALL 03624 03625 03626 03627 03630 03631 03632 03633 03634 03635 03636 03637 03640 03641 03642 03643 03644 03645 3624 5 3625 2 3626 3 3627 5 3630 3 3631 6 3632 5 3633 3 3634 5 3635 3 3636 6 3637 5 3640 7 3641 6 3642 5 3643 3 3644 2 3645 0 0,0615 0 0,0001 1 0,0000 1 0,0576 0 0,0001 0 1,2051 1 0,0614 1 0,0015 0 0,0613 0 1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0 0,0615 0 0,0576 1 0,0000 1 EQU TS IND EX CAF TS XCH AD TS XCH TS CAF AD TS MAS K AD TS XCH IND EX TC * MBCA Q 0 ADDRWD1 Q ONE MBCRET BANK MBCBANK ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1 MBCA ADDRWD1 0

; save A ; load the CADR into A ; save 14-bit destination address

; skip CADR ; save old return address

; save old bank

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; restore A ; apply indirect address to next instr. ; make the jump

; Jump returns her e; restore the old bank and return 03646 03647 03650 03651 03652 3646 5 3647 3 3650 5 3651 3 3652 0 0,0615 0 0,0613 0 0,0015 0 0,0615 0 0,0614 1 TS XCH TS XCH TC MBCA MBCBANK BANK MBCA MBCRET ; save A

; restore A

;----------------- --------------------------------------------------------; POSTJUMP ; Do a bank jump t o the location referenced by the 14-bit address referenced ; in Q. Does not affect register A (but assumes A does not contain an ; overflow). Funct ionally identical to BANKCALL ; Usage: ; TC POSTJUMP ; bank jump to CADR ; DS MYCADR ; the 14-bit address ; returns here if MYCADR calls TC Q. ; ; Inferred from th e AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;----------------- --------------------------------------------------------POSTJUMP 03653 03654 03655 03656 03657 03660 03661 03662 03663 03664 03665 03666 3653 5 3654 2 3655 3 3656 5 3657 3 3660 5 3661 3 3662 5 3663 3664 3665 3666 4 6 1 0 0,0607 0 0,0001 1 0,0000 1 0,0576 0 0,0001 0 0,0606 1 0,0015 0 0,0605 1 0,0576 1,2102 0,0000 1,3677 1 0 0 1 EQU TS IND EX CAF TS XCH TS XCH TS CS AD CCS TC * PJA Q 0 ADDRWD1 Q PJRET BANK PJBANK ADDRWD1 bankAddr A DOPOSTJUMP

; save A ; load the CADR into A ; save 14-bit destination address

; save old return address-1

; save old bank ; -(14bitAddr)+%6000 ; CADR is bank addressed? ; >0 no, just run it, as is

03667 03670 03671 03672 03673 03674 03675 03676

3667 0 3670 0 3671 3 3672 6 3673 5 3674 7 3675 6 3676 5

1,3671 1 1,3671 1 1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0 DOPOSTJUMP

TC TC CAF AD TS MAS K AD TS EQU XCH IND EX TC

*+2 *+1 ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1 * PJA ADDRWD1 0

; +0 yes ; <0 yes

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

03677 03700 03701

3677 3 3700 2 3701 0

0,0607 0 0,0576 1 0,0000 1

; restore A ; apply indirect address to next instr. ; make the jump

; Jump returns her e; restore the old bank and return 03702 03703 03704 03705 03706 03707 03710 03711 3702 5 3703 3 3704 5 3705 3 3706 6 3707 5 3710 3 3711 0 0,0607 0 0,0605 1 0,0015 0 0,0606 1 1,2051 1 0,0001 0 0,0607 0 0,0000 0 TS XCH TS XCH AD TS XCH RET URN PJA PJBANK BANK PJRET ONE Q PJA ; save A

; skip CADR

; restore A

;----------------- --------------------------------------------------------; BANKJUMP ; Do a bank jump t o the location referenced by the 14-bit address in A. ; Usage: ; CADRSTOR DS MYCADR ; ; CAF CADRSTOR ; load the 14-bit address ; TC BANKJUMP ; bank jump to CADR ; returns here if MYCADR calls TC Q ; ; Inferred from th e AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;----------------- --------------------------------------------------------BANKJUMP 03712 03713 03714 03715 03716 03717 03720 03721 03722 03723 03724 03725 03726 03727 03730 03731 03732 3712 5 3713 3 3714 5 3715 3 3716 5 3717 3720 3721 3722 3723 3724 4 6 1 0 0 0 0,0576 0 0,0001 0 0,0604 0 0,0015 0 0,0603 1 0,0576 1,2102 0,0000 1,3733 1,3725 1,3725 1 0 0 0 1 1 EQU TS XCH TS XCH TS CS AD CCS TC TC TC CAF AD TS MAS K AD TS DOBANKJUMP 03733 03734 3733 2 3734 0 0,0576 1 0,0000 1 EQU IND EX TC * ADDRWD1 Q BJRET BANK BJBANK ADDRWD1 bankAddr A DOBANKJUMP *+2 *+1 ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1 * ADDRWD1 0

; save 14-bit destination address

; save old return address

; save old bank ; -(14bitAddr)+%6000 ; ; ; ; CADR is bank addressed? >0 no, just run it, as is +0 yes <0 yes

3725 3 3726 6 3727 5 3730 7 3731 6 3732 5

1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; apply indirect address to next instr. ; make the jump

; Jump returns her e; restore the old bank and return 03735 03736 03737 03740 03741 3735 3 3736 5 3737 3 3740 5 3741 0 0,0603 1 0,0015 0 0,0604 0 0,0001 0 0,0000 0 XCH TS XCH TS RET URN BJBANK BANK BJRET Q

;----------------- --------------------------------------------------------; DATACALL ; Retrieve memory contents at location referenced by the 14-bit address in A. ; Usage:

; CADRSTOR DS MYCADR ; ; CAF CADRSTOR ; load the 14-bit address ; TC DATACALL ; return data in A ; ; Inferred from th e AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968. ;----------------- --------------------------------------------------------DATACALL 03742 03743 03744 03745 03746 03747 03750 03751 03752 03753 03754 03755 03756 03757 03760 03761 03762 3742 5 3743 3 3744 5 3745 3 3746 5 3747 3750 3751 3752 3753 3754 4 6 1 0 0 0 0,0576 0 0,0001 0 0,0604 0 0,0015 0 0,0603 1 0,0576 1,2102 0,0000 1,3763 1,3755 1,3755 1 0 0 0 0 0 EQU TS XCH TS XCH TS CS AD CCS TC TC TC CAF AD TS MAS K AD TS DODATACALL 03763 03764 03765 03766 03767 03770 03771 3763 3 3764 2 3765 6 3766 3 3767 5 3770 3 3771 0 1,2050 0 0,0576 1 0,0000 1 0,0603 1 0,0015 0 0,0603 1 0,0604 0 EQU CAF IND EX AD XCH TS XCH TC * ADDRWD1 Q BJRET BANK BJBANK ADDRWD1 bankAddr A DODATACALL *+2 *+1 ZERO ADDRWD1 BANK lowAddr bankAddr ADDRWD1 * ZERO ADDRWD1 0 BJBANK BANK BJBANK BJRET

; save 14-bit address

; save old return address

; save old bank ; -(14bitAddr)+%6000 ; ; ; ; CADR is bank addressed? >0 no, just use it, as is +0 yes <0 yes

3755 3 3756 6 3757 5 3760 7 3761 6 3762 5

1,2050 0 0,0576 0 0,0015 0 1,2103 0 1,2102 0 0,0576 0

; set the bank ; get lowest 10-bits of address ; set bits 11,12 for fixed-switchable

; apply indirect address to next instr. ; load the word ; restore the old bank

; get the word ; return

INC L T4rupt_f.asm ; T4RUPT handler ;================= ========================================================= ; T4RUPT (file:T4r upt_f.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 01/09/ 2002 ; ; PURPOSE: ; Contains T4RUPT handler and DSPOUT subroutine to update DSKY. ;================= ========================================================= ; RELTAB is a pack ed table. RELAYWORD code in upper 4 bits, RELAY code ; in lower 5 bits. In COLOSSUS, p. 129. RELTAB 1 0 0 0 1 1 1 1 1 0 0 1 RELTAB11 EQU DS DS DS DS DS DS DS DS DS DS DS DS * %04025 %10003 %14031 %20033 %24017 %30036 %34034 %40023 %44035 %50037 %54000 %60000

03772 03773 03774 03775 03776 03777 04000 04001 04002 04003 04004 04005

3772 3773 3774 3775 3776 3777 4000 4001 4002 4003 4004 4005

04025 10003 14031 20033 24017 30036 34034 40023 44035 50037 54000 60000

;----------------- --------------------------------------------------------; DK_initDK - INIT IALIZE DSKY ; ; Subroutine initi alizes the eraseable memory segment for DSKY displays. ; Blank DSKY regis ters program, verb, noun, R1, R2, R3. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, Fr esh Start and Restart, p.187. ;----------------- --------------------------------------------------------04006 4006 05265 0 DKTESTINIT DS %5265 ; init DSKY to all zeroes (TEST ONLY)

DK_initDK 04007 04010 04011 04012 04013 4007 3 4010 5 4011 3 4012 5 4013 4 0,0001 0 0,0546 0 1,2060 0 0,0130 0 DSPOFF 1,2065 1 ; 04014 04015 04016 04017 4014 4015 4016 4017 2 5 1 0 0,0130 0,0512 0,0130 2,4012 1 1 1 0

EQU XCH TS CAF TS CS CS IND EX TS CCS TC

* Q DK_IN_saveQ TEN MPAC BIT12 DKTESTINIT MPAC DSPTAB MPAC DSPOFF

; save return address ; blank DSKY registers

; set display to '0'

; followed by addi tional DSKY initialization p 187, 188) 04020 04021 04022 04023 04024 04025 04026 04027 04030 04031 04032 04033 04034 4020 4021 4022 4023 4024 4025 4026 4027 4030 4031 4032 3 5 5 5 5 5 5 5 5 5 5 1,2050 0,0465 0,0531 0,0502 0,0504 0,0501 0,0507 0,0510 0,0470 0,0471 0,0532 0 0 0 0 0 0 0 0 1 0 0 CAF TS TS TS TS TS TS TS TS TS TS CAF TS ZERO DSPCNT CADRSTOR REQRET CLPASS DSPLOCK MONSAVE MONSAVE1 VERBREG NOUNREG DSPLIST NOUTCON NOUT

; kill monitor

4033 3 4034 5

1,2105 1 0,0505 1

; set DSKY display bit (sign bit). Word must be negative, but ; not minus zero ( find out where they do this in COLOSSUS) 04035 04036 4035 4 4036 5 1,2051 0 0,0355 1 CS TS ONE FLAGWRD5

; initialize DSPCN T (index into DSPTAB). 04037 04040 04041 4037 3 4040 6 4041 5 1,2050 0 2,4072 0 0,0465 0 CAF AD TS ; schedule 1st T4R UPT 04042 04043 04044 04045 04046 4042 3 4043 5 4044 3 4045 5 4046 0 2,4074 0 0,0040 0 0,0546 0 0,0001 0 0,0000 0 CAF TS XCH TS RET URN _120MRUPT TIME4 DK_IN_saveQ Q ; reschedule interrupt for 120 mSec ZERO TABLNTH DSPCNT

; restore return address

;----------------- --------------------------------------------------------; T4PROG -- T4RUPT PROGRAM ; ; Performs T4RUPT (DSRUPT) functions. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 129. ;----------------- --------------------------------------------------------T4PROG 04047 04050 04051 04052 04053 04054 04055 04056 4047 3 4050 5 4051 0 4052 3 4053 5 4054 3 4055 5 4056 0 0,0001 0 0,0544 1 2,4116 0 2,4074 0 0,0040 0 0,0544 1 0,0001 0 0,0000 0 EQU XCH TS TC CAF TS XCH TS RET URN * Q T4RET DSPOUT _120MRUPT TIME4 T4RET Q

; save return address ; update DSKY display ; reschedule interrupt for 120 mSec

; restore return address

;----------------- --------------------------------------------------------; DSPOUT -- PUTS O UT DISPLAYS ; ; Writes changes i n the software display buffer to the AGC DSKY hardware ; display. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 131. ;----------------- --------------------------------------------------------DSPOUTSR EQU *

04057 04060 04061 04062 04063 04064

4057 5 4060 4 4061 5 4062 3 4063 6 4064 5

0,0505 1 1,2050 1 0,0370 0 0,0465 0 1,2045 1 0,0465 0 DSPSCAN

TS CS TS XCH AD TS EQU IND EX CCS CCS TC TC DS CCS DS TS TC TS CAF TC TC

NOUT ZERO DSRUPTEM DSPCNT NEG0 DSPCNT * DSPCNT DSPTAB DSPCNT DSPSCAN-2 DSPLAY %12 DSRUPTEM 16372 NOUT DSPOUTEXIT DSRUPTEM TABLNTH DSPSCAN-1 DSPOUTEXIT

; decrement NOUT

; set to -0 for 1st pass thru DSPTAB

; to prevent +0

04065 04066 04067 04070 04071 04072 04073 04074 04075 04076 04077 04100 04101 04102

4065 2 4066 1 4067 1 4070 0 4071 0 4072 4073 1 4074 4075 5 4076 0 4077 5 4100 3 4101 0 4102 0

0,0465 1 0,0512 0 0,0465 1 2,4063 0 2,4103 1 00012 1 TABLNTH 0,0370 1 37764 0 _120MRUPT 0,0505 1 2,4126 0 0,0370 0 2,4072 0 2,4064 1 2,4126 0

; test sign of DSPTAB + DSPCNT ; >0, already displayed, test DSPCNT ; if DSPCNT +, again ; <0, not yet displayed ; dec 10, length of DSPTAB ; if DSRUPTEM=+0, 2nd pass thru DSPTAB ; (DSPCNT=0), +0 into NOUT ; DSRUPTEM=+0, every table entry was che c k e d ; return ; DSRUPTEM=-0, 1st pass thru DSPTAB ; (DSPCNT=0), +0 into DSRUPTEM, pass aga i n

; return

DSPLAY 04103 04104 04105 04106 04107 04110 04111 04112 04113 04114 04115 4103 4104 4105 4106 4107 4110 4111 4112 4113 4114 6 2 5 7 5 3 2 7 6 5 1,2051 0,0465 0,0512 2,4672 0,0370 2,4666 0,0465 1,3772 0,0370 0,0010 1 1 1 1 0 0 1 1 0 0

EQU AD IND EX TS MAS K TS CAF IND EX MAS K AD TS TC

* ONE DSPCNT DSPTAB LOW11 DSRUPTEM HI5 DSPCNT RELTAB DSRUPTEM OUT0 DSPOUTEXIT

; replace positively ; remove bits 12 to 15

; pick up bits 12 to 15 of RELTAB entry ; was EXTEND/WRITE OUT0 in block II ; return

4115 0

2,4126 0

DSPOUT 04116 04117 04120 04121 04122 04123 04124 04125 4116 3 4117 5 4120 4121 4122 4123 4124 4125 1 3 0 1 0 0 0,0001 0 0,0545 0 0,0355 1,2050 2,4126 0,0505 2,4057 2,4126 0 0 0 0 1 0 NODSPOUT DSPOUTEXIT 04126 04127 04130 4126 3 4127 5 4130 0 0,0545 0 0,0001 0 0,0000 0

EQU XCH TS CCS CAF TC CCS TC TC EQU EQU XCH TS RET URN

* Q DSPOUTRET FLAGWRD5 ZERO NODSPOUT NOUT DSPOUTSR NODSPOUT * * DSPOUTRET Q

; save return address ; ; ; ; ; ; no display unless DSKY flag (sign bit) o n >0, DSKY disabled +0, DSKY disabled <0, DSKY enabled, so test NOUT >0, handle display requests +0, no display requests

; return to calling routine

INC L keyrupt_f.asm ; KEYRUPT handler ;================= ========================================================= ; KEYRUPT (file:ke yrupt_f.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 77. ;================= ========================================================= ;----------------- --------------------------------------------------------; KEYRUPT -- KEYBO ARD INTERRUPT HANDLER ; ; Performs keyRUPT functions. Triggered by a keyboard key entry. N-key ; rollover, implem ented as follows: When an interrupt occurs, the current ; job record is sa ved and then restored when the job resumes after the ; interrupt. The j ob record includes MPAC, a set of general purpose ; registers assign ed to the job. When the keyboard interrupt occurs, the ; interrupt handle r stores the keyboard character in MPAC. A job is then ; started to proce ss the character. The new job copies its MPAC fields from ; the current job, so the character is copied to storage owned by the job. ; When additional keyboard interrupts occur, they start their own jobs. ; Up to 7 jobs can be waiting in a queue for execution, so as many as ; 7 keyboard chara cters can be enqueued for processing. Since all keyboard ; jobs have the sa me priority, they are enqueued in the order received.

; Its OK for the k eyboard handler to modify the MPAC of the interrupted job ; because the inte rrupted job's record is restored at the end of the ; interrupt servic e routine. ; ; Not included in my partial AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, so I had to improvise it from the original flow charts in ; E-1574, p.77. ;----------------- --------------------------------------------------------04131 4131 37776 0 CHRPRIO KEYPROG 04132 04133 4132 3 4133 5 0,0001 0 0,0601 0 DS EQU XCH TS %37776 * Q KEYRET ; priority of CHARIN job (highest)

; save return address

; prepare to EXEC a job to handle the keystroke. 04134 04135 04136 04137 4134 4135 4136 4137 3 7 3 3 0,0004 2,4664 0,0130 0,0551 0 0 0 0 XCH MAS K XCH XCH IN0 LOW5 MPAC KP_MPAC

; save keyboard code ; save previous MPAC

; create the job. It terminates when it finishes processing the key. 04140 04141 04142 04143 04144 04145 04146 04147 4140 3 4141 0 4142 4143 3 4144 3 4145 3 4146 5 4147 0 2,4131 0 1,3162 1 12000 1 0,0551 0 0,0130 0 0,0601 0 0,0001 0 0,0000 0 CAF TC CAD R XCH XCH XCH TS RET URN CHRPRIO NOVAC CHARIN KP_MPAC MPAC KEYRET Q ; CHARIN job priority ; 14 bit CHARIN job address

; restore previous MPAC

; restore return address

INC L math_f.asm ; DP math routines ;================= ========================================================= ; MATH LIBRARY (fi le:math_f.asm) ; ; Version: 1.0 ; Author: John P ultorak ; Date: 03/01/ 2002 ; ; PURPOSE: ; Contains double precision math routines. ;================= ========================================================= ;----------------- --------------------------------------------------------; TPAGREE ; Force the signs in a triple precision (TP) word to agree. The word is ; in MPAC, MPAC+1, MPAC+2 ; ; The sign of the corrected number is always the sign of the most-significant ; non-zero word. ; ; This isn't inclu ded in my partial COLOSSUS listing, so I had to invent ; my own version. ;----------------- ---------------------------------------------------------

TPAGREE 04150 04151 4150 3 4151 5 0,0001 0 0,0577 1

EQU XCH TS

* Q MATH_Q

; return address

; Find the sign to convert to. It will be the sign ; of the most sign ificant non-zero word. TPA_SGN0 04152 04153 04154 04155 04156 4152 4153 4154 4155 4156 1 0 0 0 0 0,0130 2,4157 2,4241 2,4210 2,4241 1 0 1 0 1 EQU CCS TC TC TC TC * MPAC TPA_P0 TPA_SGN1 TPA_M0 TPA_SGN1

; ; ; ;

>0, +0, <0, -0,

sign will be + still don't know sign, check MPAC+ 1 sign will be still don't know sign, check MPAC+ 1

; MPAC is non-zero positive, so reconcile signs to a positive number. TPA_P0 04157 04160 04161 04162 04163 04164 4157 4160 4161 4162 4163 1 0 0 0 0 0,0131 2,4250 2,4167 2,4164 2,4167 0 1 0 0 0 EQU CCS TC TC TC TC CAF * MPAC+1 TPA_P1+2 TPA_PZ0 *+2 TPA_PZ0 TPA_MPAC0

; ; ; ;

>0, MPAC+1 is OK, check MPAC+2 +0, <0, fix MPAC+1 -0,

4164 3

2,4317 0

; borrow from MPAC to correct MPAC+1

04165 04166 MPAC+2

4165 0 4166 0

2,4337 1 2,4250 1

TC TC

TPA_FIXP TPA_P1+2

; MPAC+1 is now non-zero positive; check

; MPAC is non-zero positive, MPAC+1 is zero TPA_PZ0 04167 04170 04171 04172 04173 04174 04175 04176 04177 4167 4170 4171 4172 4173 4174 4175 4176 4177 1 0 0 0 3 5 3 5 0 0,0132 2,4175 2,4173 2,4200 1,2050 0,0132 1,2050 0,0131 0,0577 0 0 0 1 0 1 0 1 1 EQU CCS TC TC TC CAF TS CAF TS TC * MPAC+2 *+5 *+2 TPA_PZ0FIX ZERO MPAC+2 ZERO MPAC+1 MATH_Q

; >0, zero MPAC+1, MPAC+2 is OK ; +0, MPAC+1, +2 both zero ; <0, ; make sure they're both +0

; MPAC is non-zero positive, MPAC+1 is zero, MPAC+2 is non-zero negative. ; Solution: borrow from MPAC, transfer borrowed value to MPAC+1, but also ; borrow from MPAC +1, use borrowed value to correct MPAC+2. TPA_PZ0FIX 04200 04201 04202 04203 04204 04205 04206 04207 4200 3 4201 5 4202 3 4203 0 4204 4205 4206 4207 3 3 5 0 0,0132 1 0,0131 1 2,4317 0 2,4337 1 2,4315 0,0131 0,0132 0,0577 1 1 1 1 EQU XCH TS CAF TC CAF XCH TS TC * MPAC+2 MPAC+1 TPA_MPAC0 TPA_FIXP MAXPOS MPAC+1 MPAC+2 MATH_Q

; move MPAC+2 to MPAC+1 so we can use ; our standard correction function ; borrow from MPAC to correct MPAC+1

; move corrected value from MPAC+1 back ; to MPAC+2. Set MPAC+1 to correct value ; borrowed from MPAC.

; The MPAC is non- zero negative, so reconcile signs to a negative number. TPA_M0 04210 04211 04212 04213 04214 04215 04216 04217 4210 4211 4212 4213 4214 1 0 0 0 0 0,0131 2,4215 2,4220 2,4264 2,4220 0 0 0 0 0 EQU CCS TC TC TC TC CAF TC TC * MPAC+1 *+4 TPA_MZ0 TPA_M1+2 TPA_MZ0 TPA_MPAC0 TPA_FIXM TPA_M1+2

; ; ; ;

>0, fix MPAC+1 +0, <0, MPAC+1 is OK, check MPAC+2 -0,

4215 3 4216 0 4217 0

2,4317 0 2,4321 0 2,4264 0

; borrow from MPAC to correct MPAC+1

; MPAC is non-zero negative, MPAC+1 is zero TPA_MZ0 04220 04221 04222 04223 04224 04225 04226 04227 04230 4220 4221 4222 4223 4224 4225 4226 4227 4230 1 0 0 0 3 5 3 5 0 0,0132 2,4231 2,4224 2,4226 1,2045 0,0132 1,2045 0,0131 0,0577 0 0 1 0 1 1 1 1 1 EQU CCS TC TC TC CAF TS CAF TS TC * MPAC+2 TPA_MZ0FIX *+2 *+3 NEG0 MPAC+2 NEG0 MPAC+1 MATH_Q

; >0, ; +0, MPAC+1, +2 both zero ; <0, zero MPAC+1, MPAC+2 is OK ; make sure they're both -0

; MPAC is non-zero negative, MPAC+1 is zero, MPAC+2 is non-zero positive ; Solution: borrow from MPAC, transfer borrowed value to MPAC+1, but also ; borrow from MPAC +1, use borrowed value to correct MPAC+2. TPA_MZ0FIX 04231 04232 04233 04234 04235 04236 04237 04240 4231 3 4232 5 4233 3 4234 0 4235 4236 4237 4240 3 3 5 0 0,0132 1 0,0131 1 2,4317 0 2,4321 0 2,4316 0,0131 0,0132 0,0577 1 1 1 1 EQU XCH TS CAF TC CAF XCH TS TC * MPAC+2 MPAC+1 TPA_MPAC0 TPA_FIXM MAXNEG MPAC+1 MPAC+2 MATH_Q

; move MPAC+2 to MPAC+1 so we can use ; our standard correction function ; borrow from MPAC to correct MPAC+1

; move corrected value from MPAC+1 back ; to MPAC+2. Set MPAC+1 to correct value ; borrowed from MPAC.

; MPAC was zero, s o we still don't know the sign. Check MPAC+1. TPA_SGN1 04241 04242 04243 04244 04245 4241 4242 4243 4244 4245 1 0 0 0 0 0,0131 2,4246 2,4277 2,4262 2,4277 0 0 1 0 1 EQU CCS TC TC TC TC * MPAC+1 TPA_P1 TPA_SGN2 TPA_M1 TPA_SGN2

; ; ; ;

>0, +0, <0, -0,

sign will be + still don't know sign, check MPAC+ 2 sign will be still don't know sign, check MPAC+ 2

; MPAC+1 is non-ze ro positive, so reconcile signs to a positive number. TPA_P1 04246 04247 04250 04251 04252 04253 04254 04255 04256 04257 04260 04261 4246 3 4247 5 4250 4251 4252 4253 4254 4255 4256 1 0 0 0 3 5 0 1,2050 0 0,0130 0 0,0132 0,0577 0,0577 2,4257 1,2050 0,0132 0,0577 0 1 1 0 0 1 1 EQU CAF TS CCS TC TC TC CAF TS TC CAF TC TC * ZERO MPAC MPAC+2 MATH_Q MATH_Q *+4 ZERO MPAC+2 MATH_Q TPA_MPAC1 TPA_FIXP MATH_Q

; set MPAC to +0

; ; ; ;

>0, +0, <0, -0,

all words all words MPAC+2 is change to

are positive are positive nonzero +0 and we're done

4257 3 4260 0 4261 0

2,4320 1 2,4337 1 0,0577 1

; borrow from MPAC+1 to correct MPAC+2

; MPAC+1 is non-ze ro negative, so reconcile signs to a negative number. TPA_M1 04262 04263 04264 04265 04266 04267 04270 04271 04272 04273 04274 04275 04276 4262 3 4263 5 4264 4265 4266 4267 4270 1 0 0 0 0 1,2045 1 0,0130 0 0,0132 2,4274 2,4271 0,0577 0,0577 0 1 1 1 1 EQU CAF TS CCS TC TC TC TC CAF TS TC CAF TC TC * NEG0 MPAC MPAC+2 *+7 *+3 MATH_Q MATH_Q NEG0 MPAC+2 MATH_Q TPA_MPAC1 TPA_FIXM MATH_Q

; set MPAC to -0

; ; ; ;

>0, +0, <0, -0,

MPAC+2 is change to all words all words

nonzero + -0 and we're done are negative are negative

4271 3 4272 5 4273 0 4274 3 4275 0 4276 0

1,2045 1 0,0132 1 0,0577 1 2,4320 1 2,4321 0 0,0577 1

; +0, change to -0 and we're done

; borrow from MPAC+1 to correct MPAC+2

; MPAC and MPAC+1 were both zero, so we still don't know the sign. ; Check MPAC+2. TPA_SGN2 04277 04300 04301 04302 04303 04304 04305 04306 04307 04310 04311 04312 04313 04314 4277 4300 4301 4302 4303 1 0 0 0 0 0,0132 2,4304 2,4310 2,4306 2,4310 0 1 1 0 1 EQU CCS TC TC TC TC CAF TC CAF TC CAF TS TS TS TC * MPAC+2 TPA_P2 TPA_P3 TPA_M2 TPA_P3 ZERO *+5 NEG0 *+3 ZERO MPAC+2 MPAC+1 MPAC MATH_Q

; ; ; ;

>0, +0, <0, -0,

sign is + number is all zeros sign is number is all zeros

4304 3 4305 0 4306 3 4307 0 4310 3 4311 5 4312 5 4313 5 4314 0

1,2050 0 TPA_P2 2,4312 0 1,2045 1 TPA_M2 2,4312 0 1,2050 0 TPA_P3 0,0132 1 0,0131 1 0,0130 0 0,0577 1

; set MPAC, MPAC+1 to +0 ; set MPAC, MPAC+1 to -0

; set MPAC, MPAC+1, MPAC+2 to +0

04315 04316 04317 04320

4315 4316 4317 4320

37777 1 MAXPOS 40000 0 MAXNEG 00130 0 TPA_MPAC0 00131 1 TPA_MPAC1

DS DS DS DS

%37777 %40000 MPAC MPAC+1

; largest non-overflow pos number ; largest non-overflow neg number

;----------------- --------------------------------------------------------; TPA_FIXM ; Reconcile the si gns in a double precision word. The most significant word ; is in C(A), the lesser word in C(A+1). Reconcilliation occurs by borrowing ; from C(A) and ad ding the borrowed amount to C(A+1). C(A) is assumed to be ; negative non-zer o number and C(A+1) positive non-zero. The reconciliation ; makes both numbe rs negative. ; ; This is part of my implementation of TPAGREE. ;----------------- --------------------------------------------------------TPA_FIXM 04321 04322 04323 4321 5 4322 2 4323 4 0,0576 0 0,0576 1 0,0000 0 EQU TS IND EX CS * ADDRWD1 ADDRWD1 0

; borrow from 1st word

04324 04325 04326 04327 04330 04331 04332 04333 04334 04335 04336

4324 4325 4326 4327 4330 4331 4332 4333 4334 4335 4336

1 4 2 5 3 6 2 6 2 5 0

0,0000 0,0000 0,0576 0,0000 2,4316 1,2046 0,0576 0,0001 0,0576 0,0001 0,0001

0 0 1 1 1 1 1 0 1 0 0

CCS COM IND EX TS CAF AD IND EX AD IND EX TS TC

A ADDRWD1 0 MAXNEG NEG1 ADDRWD1 1 ADDRWD1 1 Q

; create negative overflow ; correct 2nd word, changes sign

;----------------- --------------------------------------------------------; TPA_FIXP ; Reconcile the si gns in a double precision word. The most significant word ; is in C(A), the lesser word in C(A+1). Reconcilliation occurs by borrowing ; from C(A) and ad ding the borrowed amount to C(A+1). C(A) is assumed to be ; positive non-zer o number and C(A+1) negative non-zero. The reconciliation ; makes both numbe rs positive. ; ; This is part of my implementation of TPAGREE. ;----------------- --------------------------------------------------------TPA_FIXP 04337 04340 04341 04342 04343 04344 04345 04346 04347 04350 04351 04352 4337 5 4340 4341 4342 4343 4344 4345 4346 4347 4350 4351 4352 2 1 2 5 3 6 2 6 2 5 0 0,0576 0 0,0576 0,0000 0,0576 0,0000 2,4315 1,2051 0,0576 0,0001 0,0576 0,0001 0,0001 1 0 1 1 1 1 1 0 1 0 0 EQU TS IND EX CCS IND EX TS CAF AD IND EX AD IND EX TS TC * ADDRWD1 ADDRWD1 0 ADDRWD1 0 MAXPOS ONE ADDRWD1 1 ADDRWD1 1 Q

; borrow from 1st word

; create positive overflow ; correct 2nd word, changes sign

;----------------- --------------------------------------------------------; SHORTMP -- MULTI PLY DOUBLE WORD BY A SINGLE WORD ; Multiply C(MPAC, MPAC+1) by the contents of A. Put the product in MPAC, ; MPAC+1, MPAC+2. ;; ; These aren't inc luded in my partial COLOSSUS listing, so I had to invent ; my own version. ;----------------- --------------------------------------------------------SHORTMP 04353 4353 5 0,0573 0 EQU TS * SHORTMP_A

; MPAC+2 = MPAC+1 * A 04354 04355 04356 04357 04360 4354 4355 4356 4357 4360 2 4 5 3 5 0,0000 0,0131 0,0574 0,0003 0,0132 1 0 1 1 1 EXT END MP TS XCH TS

MPAC+1 SHORTMP_OVFL LP MPAC+2

; MPAC+1 = (MPAC * A) + overflow 04361 04362 04363 04364 04365 04366 04367 04370 4361 4362 4363 4364 4365 4366 4367 4370 3 2 4 5 3 6 5 3 0,0573 0,0000 0,0130 0,0575 0,0003 0,0574 0,0131 1,2050 0 1 1 0 1 1 1 0 XCH EXT END MP TS XCH AD TS CAF ; MPAC = overflow 04371 04372 04373 4371 6 4372 5 4373 0 0,0575 0 0,0130 0 0,0001 0 AD TS TC SHORTMP_OVFH MPAC Q ; return SHORTMP_A MPAC SHORTMP_OVFH LP SHORTMP_OVFL MPAC+1 ZERO

; skip on overflow ; otherwise, make interword carry=0

;----------------- --------------------------------------------------------; DMP -- DOUBLE PR ECISION MULTIPLY ; Multiply val, va l+1 with C(MPAC, MPAC+1). 'ADDRWD1' contains the ; address of 'val' . The product appears in MPAC, MPAC+1, MPAC+2 ; ; This isn't inclu ded in my partial COLOSSUS listing, but is taken from

; the double preci sion math examples in R-393. ;----------------- --------------------------------------------------------DMP 04374 04375 04376 04377 04400 04401 04402 04403 04404 04405 04406 04407 04410 04411 04412 04413 04414 04415 04416 04417 04420 04421 04422 04423 04424 04425 04426 04427 04430 04431 04432 04433 04434 4374 4375 4376 4377 4400 4401 4402 4403 4404 4405 4406 4407 4410 4411 4412 4413 4414 4415 4416 4417 4420 4421 4422 4423 4424 4425 4426 4427 4430 4431 4432 4433 4434 2 3 6 5 3 5 2 4 3 2 4 3 6 3 5 2 4 3 3 6 3 2 4 3 6 6 3 3 5 3 6 5 0 0,0001 0,0000 2,5777 0,0576 0,0131 0,0034 0,0576 0,0001 0,0034 0,0576 0,0000 0,0034 0,0003 0,0130 0,0132 0,0576 0,0001 0,0034 0,0130 0,0003 0,0132 0,0576 0,0000 0,0034 0,0130 0,0003 0,0131 0,0034 0,0130 0,0001 1,2051 0,0001 0,0001 1 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 1 0 0 EQU IND EX CAF AD TS XCH TS IND EX MP XCH IND EX MP XCH AD XCH TS IND EX MP XCH XCH AD XCH IND EX MP XCH AD AD XCH XCH TS XCH AD TS TC * Q 0 EXTENDER ADDRWD1 MPAC+1 OVCTR ADDRWD1 1 OVCTR ADDRWD1 0 OVCTR LP MPAC MPAC+2 ADDRWD1 1 OVCTR MPAC LP MPAC+2 ADDRWD1 0 OVCTR MPAC LP MPAC+1 OVCTR MPAC Q ONE Q Q ; skip next word on return

BANKFF_1

EQU

;----------------- -------------------------------------------------------; PINBALL ; ; Now, do the "pin ball game" (DSKY) routines. ; ; Mimic the bank a ssignments in COLOSSUS. Since this is a block I AGC that ; has fewer banks, different bank numbers are used, but the sequence and ; relative allocat ion of routines to various banks is preserved. ;----------------- -------------------------------------------------------; don't change BAN K04_1 without also changing V37BANK BANK04_1 BANK40_1 BANK41_1 BANK42_1 BANK43_1 EQU EQU EQU EQU EQU BANK4 BANK5 BANK6 BANK7 BANK10 ; was BANK 04 in COLOSSUS ; ; ; ; was was was was BANK BANK BANK BANK 40 41 42 43 in in in in COLOSSUS COLOSSUS COLOSSUS COLOSSUS

; start of COLOSSU S routines ORG BANK04_1 ; COLOSSUS pp. 192-204 INC L bank04_1.asm ;================= ========================================================= ; MAJOR MODE CHANG E (file:bank04_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 192-204. ;================= ========================================================= ;----------------- --------------------------------------------------------; VERB 37 ; ; In COLOSSUS, a s uccessful V37 apparently also restarts the AGC. Here, ; we implement a s ubset of COLOSSUS to kick off a job associated with the ; verb. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 192-204. ;----------------- ---------------------------------------------------------

V37 10000 4,0000 5 0,0464 1

EQU TS

* MMNUMBER

; verb 37 ; save major mode

; ** skipped quite a bit of guidance system-related code ** 10001 4,0001 0 4,6005 1 TC CHECKTAB

; ** skipped more guidance system-related code ** V37BAD 10002 10003 10004 4,0002 0 4,0003 0 4,0004 2,5003 1 1,3653 1 05067 0 EQU TC TC CAD R * RELDSP POSTJUMP PINBRNCH

; releases display from astronaut ; bring back last normal display if ther e ; was one, OY

; Search table for entry matching major mode number. Table entries ; are sorted by ma jor mode number, so the search occurs in order from ; lowest number to highest. CHECKTAB 10005 10006 10007 10010 10011 10012 10013 10014 10015 10016 10017 10020 10021 4,0005 3 4,0006 6 4,0007 5 4,0010 4,0011 4,0012 4,0013 4,0014 4,0015 4,0016 3 2 6 7 4 6 1 1,2050 0 4,6046 0 0,0131 1 AGAINMM 1,2050 0,0131 4,6037 1,2101 0,0000 0,0464 0,0000 0 0 0 1 0 1 0 EQU CAF AD TS CAF IND EX AD MAS K COM AD CCS CCS TC TC * ZERO NOV37MM MPAC+1 ZERO MPAC+1 PREMM1 LOW7 MMNUMBER A MPAC+1 AGAINMM V37NONO ; was CA PREMM1 in Block II ; obtain which MM this is for

; was CA NOV37MM in Block II ; the no. of MM in table (minus 1)

; MMNUMBER - current table MM number ; if GR, see if anymore in list ; yes, get next one (was TCF) ; last time or passed MM (was TCF)

4,0017 1 4,0020 0 4,0021 0

0,0131 0 4,6007 0 4,6026 0

; Found the index into the major mode table for entry matching the ; major mode numbe r input by the user. 10022 10023 10024 10025 4,0022 3 4,0023 6 4,0024 5 4,0025 0 1,2050 0 0,0131 1 0,0463 0 1,2147 1 CAF AD TS TC ZERO MPAC+1 MINDEX goMMchange ; was CA MPAC+1 in Block II ; save index for later ; in Block II, jumped to restart AGC

; Requested MM doe sn't exist V37NONO 10026 10027 4,0026 0 4,0027 0 2,4701 0 4,6002 0 EQU TC TC * FALTON V37BAD

; come here if MM requested doesn't exis t

;----------------- --------------------------------------------------------; FCADRMM ; ; For verb 37, two tables are maintained. Each table has an entry for each ; major mode that can be started from the keyboard. The entries are put ; into the table w ith the entry for the highest major mode coming first, ; to the lowest ma jor mode which is the last entry in the table. ; ; The FCADRMM tabl e contains the FCADR of the starting job of the major mode. ; ; The entries in t his table must match the entries in PREMM1 below. ;----------------- --------------------------------------------------------FCADRMM1 10030 10031 10032 10033 10034 10035 10036 4,0030 4,0031 4,0032 4,0033 4,0034 4,0035 4,0036 22147 22142 22127 22066 22036 22022 22000 0 0 0 1 1 1 1 ; etc ********* ;----------------- --------------------------------------------------------; PREMM1 ; ; The PREMM1 table contains the E-bank, major mode, and priority information. ; It is in the fol lowing form: ; ; PPP PPE EEM MMM MMM ; ; Where, ; the 7 'M' bits contain the major mode number EQU CAD R CAD R CAD R CAD R CAD R CAD R CAD R * P79 P78 P04 P03 P02 P01 P00

; the 3 'E' bits contain the E-bank number (ignored in Block I) ; the 5 'P' bits contain the priority at which the job is to be started ; ; The entries in t his table must match the entries in FCADRMM1 above. ;----------------- --------------------------------------------------------PREMM1 10037 10040 10041 10042 10043 10044 10045 4,0037 4,0040 4,0041 4,0042 4,0043 4,0044 4,0045 26117 26116 26004 26003 26002 26001 26000 1 0 1 0 1 1 0 EQU DS DS DS DS DS DS DS * %26117 %26116 %26004 %26003 %26002 %26001 %26000 * EPREMM1-PREMM1-1 ; number of entries in table (minus 1) *

; ; ; ; ; ; ;

MM MM MM MM MM MM MM

79, 78, 04, 03, 02, 01, 00,

PRIO PRIO PRIO PRIO PRIO PRIO PRIO

13 13 13 13 13 13 13

; etc ********* EPREMM1 EQU 10046 4,0046 00006 1 NOV37MM BANK04_2 DS EQU

ORG BANK40_1 ; COLOSSUS pp. 310-317 INC L bank40_1.asm ;================= ========================================================= ; PINBALL GAME (fi le:bank40_1.asm) ; ; AGC Block II COL OSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 310-317. ;================= ========================================================= ;----------------- --------------------------------------------------------; CHARIN -- PROCES S KEYBOARD CHARACTER FROM KEYRUPT ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 310. ;----------------- --------------------------------------------------------CHARIN 12000 12001 12002 12003 12004 12005 12006 12007 5,0000 5,0001 5,0002 5,0003 5,0004 5,0005 5,0006 5,0007 3 3 5 1 0 0 4 6 1,2051 0,0501 0,0412 0,0531 5,6006 5,6016 5,6062 0,0130 1 0 0 1 1 0 1 0 ; VBRELDSP). 12010 12011 12012 12013 12014 12015 5,0010 5,0011 5,0012 5,0013 5,0014 1 0 0 0 0 0,0000 5,6015 5,6014 5,6015 5,6016 0 0 1 0 0 CCS TC TC TC TC TC CHARIN2 12016 12017 12020 12021 12022 12023 12024 12025 12026 12027 12030 12031 12032 12033 12034 12035 12036 12037 12040 12041 12042 12043 12044 12045 12046 12047 12050 12051 12052 12053 5,0016 5,0017 5,0020 5,0021 5,0022 5,0023 5,0024 5,0025 5,0026 5,0027 5,0030 5,0031 5,0032 5,0033 5,0034 5,0035 5,0036 5,0037 5,0040 5,0041 5,0042 5,0043 5,0044 5,0045 5,0046 5,0047 5,0050 5,0051 5,0052 5,0053 3 5 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,0130 0,0414 0,0000 5,6022 5,7307 5,6101 5,6101 5,6101 5,6101 5,6101 5,6101 5,6101 5,6065 5,6065 5,7307 5,7307 5,7307 5,7307 5,7307 5,7307 5,6077 5,6272 5,7462 5,7307 5,7307 5,7307 5,7307 5,7307 5,7307 5,7327 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 EQU XCH TS IND EX TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC A *+4 *+2 *+2 CHARIN2 RELDSPON * MPAC CHAR A *+1 CHARALRM NUM NUM NUM NUM NUM NUM NUM _89TEST _89TEST CHARALRM CHARALRM CHARALRM CHARALRM CHARALRM CHARALRM NUM-2 VERB ERROR CHARALRM CHARALRM CHARALRM CHARALRM CHARALRM CHARALRM VBRELDSP ; ; ; ; ; was BZF CHARIN2 in Block II >0 +0 <0 -0 EQU CAF XCH TS CCS TC TC CS AD * ONE DSPLOCK _2122REG CADRSTOR *+2 CHARIN2 ELRCODE1 MPAC

; ; ; ; ; ; ; ;

block display syst make dsp syst busy, but save old C(DSPLOCK) for error light reset all keys except ER turn on KR lite if CADRSTOR is full. This reminds operato r to re-establish a flashing display which he has obscured with displays of his own (see remarks preceding routine

5,0015 0

2,4713 0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

input_code function 0 1 2 3 4 5 6 7 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27 30 31 9

0 VERB ERROR LIGHT RESET

KEY RELEASE

12054 12055 12056 12057 12060 12061 12062 12063 12064

5,0054 5,0055 5,0056 5,0057 5,0060 5,0061

0 0 0 0 0 0

5,6326 5,6312 5,6063 5,7307 5,6412 5,6306

0 1 1 1 0 1

TC TC TC TC TC TC DS TC DS EQU CCS TC TC TC TC CAF MAS K CCS TC TC

POSGN NEGSGN ENTERJMP CHARALRM CLEAR NOUN %22 POSTJUMP ENTER * DSPCOUNT *+4 *+3 ENDOFJOB ENDOFJOB THREE DECBRNCH A NUM CHARALRM

; ; ; ; ; ;

32 33 34 35 36 37

+ ENTER CLEAR NOUN

5,0062 5,0063 0 5,0064

00022 1 ELRCODE1 1,3653 1 ENTERJMP 14002 0 _89TEST

12065 12066 12067 12070 12071 12072 12073 12074 12075 12076

5,0065 5,0066 5,0067 5,0070 5,0071 5,0072 5,0073 5,0074 5,0075 5,0076

1 0 0 0 0 3 7 1 0 0

0,0466 5,6072 5,6072 1,2723 1,2723 1,2053 0,0467 0,0000 5,6101 5,7307

1 1 1 0 0 0 0 0 1 1

; ; ; ;

>0 +0 <0, block data in if DSPCOUNT is <0 or - 0 -0

; if DECBRNCH is +, 8 or 9 OK ; if DECBRNCH is +0, reject 8 or 9

;----------------- --------------------------------------------------------; NUM -- PROCESS N UMERICAL KEYBOARD CHARACTER ; Assembles octal, 3 bits at a time. For decimal, it converts incoming word ; as a fraction, k eeping results to DP (double precision). ; Octal results ar e left in XREG, YREG, or ZREG. High part of DEC in XREG, ; YREG, ZREG; the low parts in XREGLP, YREGLP, or ZREGLP). ; DECBRNCH is left at +0 for octal, +1 for +DEC, +2 for -DEC. ; If DSPCOUNT was left -, no more data is accepted. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 311. ;----------------- --------------------------------------------------------12077 12100 5,0077 3 5,0100 5 1,2050 0 0,0414 0 NUM 12101 12102 12103 12104 12105 12106 12107 12110 12111 12112 12113 12114 12115 12116 12117 12120 12121 12122 12123 12124 12125 12126 12127 12130 12131 12132 12133 12134 12135 12136 5,0101 5,0102 5,0103 5,0104 5,0105 5,0106 5,0107 5,0110 5,0111 5,0112 5,0113 5,0114 5,0115 5,0116 5,0117 5,0120 5,0121 5,0122 5,0123 5,0124 5,0125 5,0126 5,0127 5,0130 5,0131 5,0132 5,0133 5,0134 5,0135 5,0136 1 0 0 0 0 0 1 3 5 0 2 3 7 5 3 6 5 0 3 7 1 0 2 3 5 4 4 3 6 0 0,0466 5,6106 5,6106 5,6105 1,2723 5,6241 0,0504 1,2050 0,0504 5,6113 0,0414 1,3772 2,4664 0,0421 1,2050 0,0466 0,0440 5,7161 1,2053 0,0467 0,0000 5,6137 0,0434 0,0470 0,0022 0,0022 0,0022 0,0022 0,0414 5,6155 1 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 0 0 1 0 0 DECTOBIN 12137 12140 12141 12142 12143 12144 12145 12146 12147 12150 12151 12152 5,0137 5,0140 5,0141 5,0142 5,0143 5,0144 5,0145 5,0146 5,0147 5,0150 5,0151 2 3 5 3 5 3 0 3 6 5 0 0,0434 0,0470 0,0130 1,2050 0,0131 1,2060 2,4353 0,0131 0,0414 0,0131 5,6155 0 1 0 0 1 0 0 1 0 1 0 CAF TS EQU CCS TC TC TC TC TC CCS CAF TS TC IND EX CAF MAS K TS CAF AD TS TC CAF MAS K CCS TC IND EX XCH TS CS CS XCH AD TC EQU IND EX XCH TS CAF TS CAF TC XCH AD TS TC AD ZERO CHAR * DSPCOUNT *+4 *+3 *+1 ENDOFJOB GETINREL CLPASS ZERO CLPASS *+1 CHAR RELTAB LOW5 CODE ZERO DSPCOUNT COUNT DSPIN THREE DECBRNCH A DECTOBIN INREL VERBREG CYL CYL CYL CYL CHAR ENDNMTST * INREL VERBREG MPAC ZERO MPAC+1 TEN SHORTMP MPAC+1 CHAR MPAC+1 ENDNMTST MPAC

; ; ; ;

>0 +0 <0, block datain if DSPCOUNT is <0 or - 0 -0

; if CLPASS is >0 or +0, make it +0

; was CA DSPCOUNT in Block II

; +0=octal, +1=+dec, +2=-dec ; >0 ; +0 (octal)

; sum x 2EXP-14 in MPAC

; 10 x 3EXP-14 ; 10SUM x 2EXP-28 in MPAC, MPAC+1

; no overflow ; overflow, must be 5th character

5,0152 6

0,0130 0

12153 12154

5,0153 5 5,0154 0

0,0130 0 5,6176 1 ENDNMTST

TS TC EQU IND EX TS CS IND EX AD CCS TC TC TC TC TC ENDNUM EQU CAF MAS K CCS TC EQU CS TC

MPAC DECEND * INREL VERBREG DSPCOUNT INREL CRITCON A *+4 *+2 *+2 ENDNUM MORNUM * THREE DECBRNCH A DECEND * DSPCOUNT MORNUM+1 ; ; ; ; ; was BZF ENDNUM in Block II >0 +0, DSPCOUNT = CRITCON <0 -0

12155 12156 12157 12160 12161 12162 12163 12164 12165 12166 12167

5,0155 5,0156 5,0157 5,0160 5,0161 5,0162 5,0163 5,0164 5,0165 5,0166

2 5 4 2 6 1 0 0 0 0

0,0434 0,0470 0,0466 0,0434 5,6232 0,0000 5,6167 5,6166 5,6167 5,6170

0 1 1 0 1 0 1 0 1 1

5,0167 0

5,6227 0

; - , DSPCOUNT G/ CRITCON

12170 12171 12172 12173

5,0170 5,0171 5,0172 5,0173

3 7 1 0

1,2053 0,0467 0,0000 5,6176

0 0 0 1 ENDALL

12174 12175

5,0174 4 5,0175 0

0,0466 1 5,6230 0

; block NUMIN by placing DSPCOUNT ; negatively

DECEND 12176 12177 12200 12201 12202 12203 12204 12205 12206 12207 12210 12211 12212 12213 12214 12215 12216 12217 5,0176 4 5,0177 6 5,0200 5,0201 5,0202 5,0203 5,0204 1 0 0 0 0 1,2051 0 0,0434 1 0,0000 5,6205 5,6204 5,6204 5,6174 0 0 1 1 0

EQU CS AD CCS TC TC TC TC

* ONE INREL A *+4 *+2 *+1 ENDALL ; ; ; ; ; was >0 +0, <0, -0, BZMF ENDALL in Block II INREL=0,1(VBREG,NNREG), leave whol e INREL=0,1(VBREG,NNREG), leave whol e INREL=0,1(VBREG,NNREG), leave whol e

5,0205 0 5,0206 5,0207 5,0210 5,0211 5,0212 5,0213 5,0214 5,0215 5,0216 5,0217 3 7 2 0 0 4 5 4 5

2,4374 0 06237 1 1,2053 0,0467 0,0000 5,6212 5,6220 0,0131 0,0131 0,0132 0,0132 0 0 0 0 1 0 1 0 1

TC DMP ; if INREL=2,3,4(R1,R2,R3), convert to f r a c ; mult sum x2EXP-2 8 in MPAC, MPAC+1 by ADR ES DECON ; 2EXP14/10EPX5. Gives(sum/10EXP5)x2EXP- 1 4 ; in MPAC, +1, +2 CAF THREE MAS K DECBRNCH IND EX A TC *+0 TC PDECSGN CS TS CS TS PDECSGN EQU XCH IND EX TS XCH IND EX TS TC EQU CCS TS TC EQU DS DS DS DS DS EQU DS DS MPAC+1 MPAC+1 MPAC+2 MPAC+2 * MPAC+2 INREL XREGLP-2 MPAC+1 INREL VERBREG ENDALL * DSPCOUNT DSPCOUNT ENDOFJOB * %22 %20 %12 %5 %0 * %05174 %13261 ; - case (was DCS, DXCH in Block II)

12220 12221 12222 12223 12224 12225 12226

5,0220 5,0221 5,0222 5,0223 5,0224 5,0225 5,0226

3 2 5 3 2 5 0

0,0132 0,0434 0,0473 0,0131 0,0434 0,0470 5,6174

1 0 1 1 0 1 0 MORNUM

12227 12230 12231

5,0227 1 5,0230 5 5,0231 0

0,0466 1 0,0466 0 1,2723 0 CRITCON

; decrement DSPCOUNT

12232 12233 12234 12235 12236

5,0232 5,0233 5,0234 5,0235 5,0236

00022 00020 00012 00005 00000

1 0 1 1 1 DECON

; dec 18 ; dec 16 ; dec 10

12237 12240

5,0237 5,0240

05174 0 13261 0

; 2EXP14/10EXP5 = .16384 DEC

;----------------- --------------------------------------------------------; GETINREL ; Gets proper data register relative address for current C(DSPCOUNT) and ; puts into INREL: +0 VERBREG, 1 NOUNREG, 2 XREG, 3 YREG, 4 ZREG ;

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 313. ;----------------- --------------------------------------------------------GETINREL 12241 12242 12243 12244 5,0241 5,0242 5,0243 5,0244 2 3 5 0 0,0466 5,6245 0,0434 0,0001 1 1 1 0 INRELTAB 12245 12246 12247 12250 12251 12252 12253 12254 12255 12256 12257 12260 12261 12262 12263 12264 12265 12266 12267 12270 5,0245 5,0246 5,0247 5,0250 5,0251 5,0252 5,0253 5,0254 5,0255 5,0256 5,0257 5,0260 5,0261 5,0262 5,0263 5,0264 0 5,0265 5,0266 5,0267 5,0270 00004 00004 00004 00004 00004 00003 00003 00003 00003 00003 00002 00002 00002 00002 00002 5,6271 00001 00001 00000 00000 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 EQU IND EX CAF TS TC EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS TC DS DS DS DS * DSPCOUNT INRELTAB INREL Q * %4 %4 %4 %4 %4 %3 %3 %3 %3 %3 %2 %2 %2 %2 %2 CCSHOLE %1 %1 %0 %0

; (A TEMP, REG)

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

R3D5, 0 = DSPCOUNT R3D4, 1 R3D3, 2 R3D2, 3 R3D1, 4 R2D5, 5 R2D4, 6 R2D3, 7 R2D2, 8D R2D1, 9D R1D5, 10D R1D4, 11D R1D3, 12D R1D2, 13D R1D1, 14D no DSPCOUNT numbers ND2, 16D ND1, 17D VD2, 18D VD1, 19D

12271

5,0271 0

1,2723 0 CCSHOLE

TC

ENDOFJOB

; can't find this anywhere; best guess

;----------------- --------------------------------------------------------; VERB ; Verb key was pre ssed; prepare to enter a 2 decimal digit verb. ; Blank the verb d isplay and call ENDOFJOB. ; ; NOUN ; Noun key was pre ssed; prepare to enter a 2 decimal digit noun. ; Blank the noun d isplay and call ENDOFJOB. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 314. ;----------------- --------------------------------------------------------VERB 12272 12273 12274 5,0272 3 5,0273 5 5,0274 3 1,2050 0 0,0470 1 2,4675 1 NVCOM EQU CAF TS CAF * ZERO VERBREG VD1 * DSPCOUNT _2BLANK ONE DECBRNCH ZERO REQRET ENDINST ENTRET ENDOFJOB * ZERO NOUNREG ND1 NVCOM

12275 12276 12277 12300 12301 12302 12303 12304 12305

5,0275 5,0276 5,0277 5,0300 5,0301 5,0302 5,0303 5,0304

5 0 3 5 3 5 3 5

5,0305 0

EQU TS TC CAF TS CAF TS CAF TS ; to TC ENDOFJOB 1,2723 0 TC 0,0466 5,6540 1,2051 0,0467 1,2050 0,0502 2,4553 0,0433 0 0 1 1 0 0 0 0 NOUN EQU CAF TS CAF TC

; set for dec V/N code ; set for ENTPAS0 ; if DSPALARM occurs before first ENTPAS 0 ; or NVSUB, ENTRET must already be set

12306 12307 12310 12311

5,0306 5,0307 5,0310 5,0311

3 5 3 0

1,2050 0,0471 2,4676 5,6275

0 0 1 1

; ND1, OCT 21 (DEC 17)

;----------------- --------------------------------------------------------; NEGSGN ; Turn the minus s ign on for the register selected by DSPCOUNT. ; Call ENDOFJOB wh en done. ; ; POSGN ; Turn the plus si gn on for the register selected by DSPCOUNT. ; Call ENDOFJOB wh en done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 314. ;----------------- --------------------------------------------------------NEGSGN EQU *

12312 12313 12314

5,0312 0 5,0313 0 5,0314 3

5,6367 0 5,6353 1 1,2052 1 BOTHSGN

TC TC CAF EQU IND EX AD AD TS EQU CCS CAF TS TC TC EQU TC TC CAF TC

SIGNTEST M_ON TWO * INREL BIT7 DECBRNCH DECBRNCH * CLPASS ZERO CLPASS *+1 ENDOFJOB * SIGNTEST P_ON ONE BOTHSGN

12315 12316 12317 12320

5,0315 5,0316 5,0317 5,0320

2 6 6 5

0,0434 1,2072 0,0467 0,0467

0 0 1 1 PIXCLPAS

; set DEC compu bit to 1 (in DECBRNCH) ; Bit 5 for R1, bit 4 for R2, bit 3 for R 3

12321 12322 12323 12324 12325

5,0321 5,0322 5,0323 5,0324 5,0325

1 3 5 0 0

0,0504 1,2050 0,0504 5,6325 1,2723

1 0 0 0 0 POSGN

; if CLPASS is + or +0, make it +0

12326 12327 12330 12331

5,0326 5,0327 5,0330 5,0331

0 0 3 0

5,6367 5,6332 1,2051 5,6315

0 0 1 0

;----------------- --------------------------------------------------------; P_ON ; Turn the plus si gn on for register selected by DSPCOUNT. ; Return when done . ; ; M_ON ; Turn the minus s ign on for register selected by DSPCOUNT. ; Return when done . ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 314. ;----------------- --------------------------------------------------------P_ON 12332 12333 12334 12335 12336 12337 12340 12341 5,0332 3 5,0333 5 5,0334 5,0335 5,0336 5,0337 5,0340 5,0341 0 2 3 5 6 5 0,0001 0 0,0547 1 5,6241 0,0434 5,6362 0,0420 1,2051 0,0417 0 0 0 1 1 0 SGNCOM 12342 12343 12344 12345 12346 12347 12350 12351 12352 5,0342 5,0343 5,0344 5,0345 5,0346 5,0347 5,0350 5,0351 3 5 3 0 3 5 3 0 1,2050 0,0421 0,0420 5,7253 1,2066 0,0421 0,0417 5,7253 0 0 1 1 0 0 0 1 EQU XCH TS TC IND EX CAF TS AD TS EQU CAF TS XCH TC CAF TS XCH TC TC M_ON 12353 12354 12355 12356 12357 12360 12361 12362 12363 5,0353 3 5,0354 5 5,0355 5,0356 5,0357 5,0360 5,0361 5,0362 5,0363 0 2 3 5 6 5 0 0,0001 0 0,0547 1 5,6241 0,0434 5,6362 0,0417 1,2051 0,0420 5,6342 0 0 0 0 1 1 1 SGNTAB 12364 12365 12366 5,0364 5,0365 5,0366 00005 1 00003 1 00000 1 EQU XCH TS TC IND EX CAF TS AD TS TC EQU DS DS DS * Q LXCH_LPRET GETINREL INREL SGNTAB-2 SGNOFF ONE SGNON * ZERO CODE SGNOFF _11DSPIN BIT11 CODE SGNON _11DSPIN LXCH_LPRET * Q LXCH_LPRET GETINREL INREL SGNTAB-2 SGNON ONE SGNOFF SGNCOM * %5 %3 %0 ; return

; was LXCH Q in block II ; save return address in faux LP

5,0352 0

0,0547 1

; was LXCH Q in block II ; save return address in faux LP

; -R1 ; -R2 ; -R3

;----------------- --------------------------------------------------------; SIGNTEST ; Test whether thi s is a valid point for entering a + or - sign character. ; Returns if valid ; calls ENDOFJOB if invalid. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 314. ;----------------- ---------------------------------------------------------

SIGNTEST 12367 12370 5,0367 3 5,0370 5 0,0001 0 0,0547 1

EQU XCH TS

* Q LXCH_LPRET

; was LXCH Q in block II ; save return address in faux LP

12371 12372 12373 12374 12375 12376 12377 12400 12401 12402 12403

5,0371 5,0372 5,0373 5,0374 5,0375 5,0376 5,0377 5,0400 5,0401 5,0402 5,0403

3 7 1 0 4 0 4 0 4 0 0

1,2053 0,0467 0,0000 1,2723 2,4635 5,6404 2,4636 5,6404 2,4637 5,6404 1,2723

0 0 0 0 1 1 1 1 0 1 0

; allows +,- only when DSPCOUNT=R1D1 CAF THREE MAS K DECBRNCH CCS A TC ENDOFJOB CS TC CS TC CS TC TC SGNTST1 EQU AD CCS TC TC TC TC R1D1 SGNTST1 R2D1 SGNTST1 R3D1 SGNTST1 ENDOFJOB * DSPCOUNT A Q LXCH_LPRET Q LXCH_LPRET

; ; ; ;

R2D1, or D3D1. Allows only first of consecutive +/- characters. if low2 bits of DECBRNCH not=0, sign for this word already in, reject.

; DSPCOUNT is R1D1?

; no match found, sign illegal

12404 12405 12406 12407 12410 12411

5,0404 6 5,0405 5,0406 5,0407 5,0410 5,0411 1 0 0 0 0

0,0466 0 0,0000 0,0001 0,0547 0,0001 0,0547 0 0 1 0 1

; ; ; ; ;

was >0, +0, <0, -0,

BZF *+2 in Block II no match, check next match found, sign is no match, check next match found, sign is

register legal register legal

;----------------- --------------------------------------------------------; CLEAR -- PROCESS CLEAR KEY ; Clear blanks whi ch R1, R2, R3 is current or last to be displayed (pertinent ; XREG, YREG, ZREG is cleared). Successive clears take care of each RX L/ ; RC until R1 is d one, then no further action. ; ; The single compo nent load verbs allow only the single RC that is appropriate ; to be cleared. ; ; CLPASS = 0, PASS O, can be backed up ; CLPASS = +NZ, HI PASS, can be backed up ; CLPASS = -NZ, PA SSO, cannot be backed up ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 316. ;----------------- --------------------------------------------------------CLEAR 12412 12413 12414 12415 12416 12417 12420 12421 12422 12423 12424 12425 12426 12427 12430 5,0412 5,0413 5,0414 5,0415 5,0416 5,0417 5,0420 5,0421 5,0422 5,0423 5,0424 5,0425 5,0426 5,0427 5,0430 1 6 0 6 2 3 5 1 0 0 0 3 6 0 0 0,0466 1,2051 5,6416 1,2051 0,0000 5,6245 0,0434 0,0504 5,6431 5,6425 5,6425 1,2050 0,0434 5,6464 5,6454 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 CLPASHI 12431 12432 12433 12434 12435 12436 12437 12440 12441 12442 12443 12444 12445 12446 12447 12450 12451 12452 5,0431 1 5,0432 5 5,0433 0 5,0434 3 5,0435 6 5,0436 5 5,0437 3 5,0440 6 5,0441 5 5,0442 5,0443 5,0444 5,0445 5,0446 1 0 0 0 5 0,0434 0 0,0434 1 5,6464 1 5,6536 1 0,0502 0 0,0502 0 1,2050 0 0,0434 1 0,0422 0 0,0470 5,6446 5,6446 5,6446 0,0470 0 1 1 1 1 EQU CCS AD TC AD IND EX CAF TS CCS TC TC TC CAF AD TC TC EQU CCS TS TC CAF AD TS CAF AD TS CCS TC TC TC TS TC DS CAF AD * DSPCOUNT ONE *+2 ONE A INRELTAB INREL CLPASS CLPASHI *+2 *+1 ZERO INREL LEGALTST CLEAR1 * INREL INREL LEGALTST DOUBLK+2 REQRET REQRET ZERO INREL MIXTEMP VERBREG *+3 *+2 *+1 VERBREG BANKCALL UPDATVB ZERO MIXTEMP ; was CA MIXTEMP in Block II ; +3 to - number, backs data requests ; was ADS REQRET in Block II

; do not change DSPCOUNT because may lat e r ; fail LEGALTST ; must set INREL, even for HIPASS ; ; ; ; + +0, if CCLPASS is +0 or -, it is PASS0 was CA INREL in Block II

; was CA INREL in Block II ; temp storage for INREL ; was DIM VERBREG in Block II

; decrement VERB and redisplay

5,0447 0 5,0450 5,0451 3 5,0452 6

1,3565 1 14327 1 1,2050 0 0,0422 0

12453

5,0453 5

0,0434 1 CLEAR1

TS EQU TC XCH AD TS TC

INREL * CLR5 CLPASS ONE CLPASS ENDOFJOB

; restore INREL

12454 12455 12456 12457 12460

5,0454 0 5,0455 3 5,0456 6 5,0457 5 5,0460 0

5,6461 1 0,0504 0 1,2051 1 0,0504 0 1,2723 0

; was INCR CLPASS in Block II ; only if CLPASS is + or +0 ; set for higher pass

;----------------- --------------------------------------------------------; CLR5 ; blanks 5 char di splay word by calling _5BLANK, but avoids TC GETINREL. ; Returns when don e. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 316. ;----------------- --------------------------------------------------------CLR5 12461 12462 12463 5,0461 3 5,0462 5 5,0463 0 0,0001 0 0,0547 1 5,6476 1 EQU XCH TS TC * Q LXCH_LPRET _5BLANK+3

; was LXCH Q in block II ; save return address in faux LP ; uses _5BLANK, but avoids its TC GETINR E L

;----------------- --------------------------------------------------------; LEGALTST ; Returns if LEGAL , calls ENDOFJOB if illegal. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 316. ;----------------- --------------------------------------------------------LEGALTST 12464 12465 12466 12467 12470 12471 5,0464 5,0465 5,0466 5,0467 5,0470 5,0471 6 1 0 0 0 0 1,2047 0,0000 0,0001 5,6271 1,2723 0,0001 0 0 0 0 0 0 EQU AD CCS TC TC TC TC * NEG2 A Q CCSHOLE ENDOFJOB Q

; LEGAL, INREL G/ 2 ; ILLEGAL, INREL = 0, 1 ; LEGAL, INREL = 2

;----------------- --------------------------------------------------------; _5BLANK ; blanks 5 char di splay word in R1,R2,or R3. It also zeroes XREG, YREG or ; ZREG. Place any + DSPCOUNT number for pertinent RC into DSPCOUNT. ; DSPCOUNT is left set to left most DSP numb for RC just blanked. ; Returns when don e. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 316. ;----------------- --------------------------------------------------------12472 5,0472 5 0,0466 0 _5BLANK 12473 12474 12475 12476 12477 12500 12501 12502 12503 12504 12505 12506 12507 12510 12511 12512 12513 12514 5,0473 3 5,0474 5 5,0475 5,0476 5,0477 5,0500 5,0501 5,0502 5,0503 5,0504 5,0505 5,0506 5,0507 5,0510 5,0511 5,0512 5,0513 5,0514 0 3 2 5 2 5 5 2 4 7 7 5 2 3 5 0 0,0001 0 0,0547 1 5,6241 1,2050 0,0434 0,0470 0,0434 0,0473 0,0421 0,0434 1,2072 0,0467 5,6537 0,0467 0,0434 5,6527 0,0440 5,7161 0 0 0 1 0 1 0 0 1 0 1 1 0 1 1 0 _5BLANK1 12515 12516 12517 12520 12521 12522 12523 5,0515 5,0516 5,0517 5,0520 2 3 5 0 0,0434 5,6532 0,0466 5,6540 0 0 0 0 TS EQU XCH TS TC CAF IND EX TS IND EX TS TS IND EX CS MAS K MAS K TS IND EX CAF TS TC EQU IND EX CAF TS TC CS AD TS DSPCOUNT * Q LXCH_LPRET GETINREL ZERO INREL VERBREG INREL XREGLP-2 CODE INREL BIT7 DECBRNCH BRNCHCON DECBRNCH INREL SINBLANK-2 COUNT DSPIN * INREL DOUBLK-2 DSPCOUNT _2BLANK TWO DSPCOUNT DSPCOUNT ; needed for BLANKSUB

; was LXCH Q in block II ; save return address in faux LP

; zero X, Y, Z reg

; zero pertinent DEC comp bit

; zero low 3 bits

; blank isolated char separately

5,0521 4 5,0522 6 5,0523 5

1,2052 0 0,0466 0 0,0466 0

; was ADS DSPCOUNT in Block II

12524 12525 12526 12527 12530

5,0524 5,0525 5,0526 5,0527 5,0530

0 2 3 5 0

5,6540 0,0434 2,4633 0,0466 0,0547

0 0 0 0 1

TC IND EX CAF TS TC

_2BLANK INREL R1D1-2 DSPCOUNT LXCH_LPRET

; set DSPCOUNT to leftmost DSP number ; of REG, just blanked

SINBLANK 12531 12532 12533 5,0531 5,0532 5,0533 00016 0 00005 1 00004 0 DOUBLK 12534 12535 12536 12537 5,0534 5,0535 5,0536 5,0537 00015 0 00011 1 00003 1 77774 0 BRNCHCON

EQU DS DS DS EQU DS DS DS DS

* %16 %5 %4 * %15 %11 %3 %77774

; DEC 14

; DEC 13 ; DEC 9

;----------------- --------------------------------------------------------; _2BLANK ; blanks 2 char, p lace DSP number of left char of the pair into DSPCOUNT. ; This number is l eft in DSPCOUNT. Returns when done. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 317. ;----------------- ---------------------------------------------------------

_2BLANK 12540 12541 12542 12543 12544 12545 12546 12547 12550 12551 12552 12553 12554 12555 12556 12557 12560 12561 12562 12563 5,0540 3 5,0541 5 5,0542 5,0543 5,0544 5,0545 3 6 5 4 0,0001 0 0,0602 0 1,2050 0,0466 0,0021 5,6563 0 0 1 0

EQU XCH TS CAF AD TS CS INH INT IND EX XCH CCS TC TC TC TC XCH AD TS REL INT TC DS

* Q SAVEQ ZERO DSPCOUNT SR BLANKCON ; was CA DSPCOUNT in Block II

5,0546 2 5,0547 2 5,0550 3 5,0551 5,0552 5,0553 5,0554 5,0555 5,0556 5,0557 5,0560 5,0561 1 0 0 0 0 3 6 5 2

0,0000 0 0,0021 0 0,0512 1 0,0000 5,6556 5,6555 5,6555 5,6557 0,0505 1,2051 0,0505 0,0000 0 1 1 1 0 1 1 1 1

SR DSPTAB A *+4 *+2 *+1 *+2 NOUT ONE NOUT ; ; ; ; ; was >0 +0, <0, -0, BZMF *+2 in Block II if old contents -, NOUT OK if old contents -, NOUT OK if old contents -, NOUT OK

; was INCR NOUT in Block II ; if old contents +, +1 to NOUT

5,0562 0 5,0563

0,0602 0 04000 0 BLANKCON

SAVEQ %4000

BANK40_2

EQU

ORG BANK41_1 ; COLOSSUS pp. 318-329 INC L bank41_1.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 318-329. ;================= ========================================================= ;----------------- --------------------------------------------------------; ENTER -- PROCESS ENTER KEY ; Enter pass 0 is the execute function. Higher order enters are to load ; data. The sign o f REQRET determines the pass, + for pass 0, - for higher ; passes. ; Machine CADR to be specified (MCTBS) nouns desire an ECADR to be loaded ; when used with l oad verbs, monitor verbs, or display verbs (except ; verb = fixed mem ory display, which requires a FCADR). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 318. ;----------------- --------------------------------------------------------14000 14001 6,0000 0 6,0001 0 6,7505 0 NVSUBR 6,6723 1 LOADLV1 TC TC NVSUB1 LOADLV ; standard lead-ins, don't move

ENTER 14002 14003 14004 14005 14006 14007 14010 14011 6,0002 6,0003 6,0004 6,0005 6,0006 6,0007 6,0010 6,0011 3 5 3 5 1 0 0 0 1,2050 0,0504 2,4553 0,0433 0,0502 6,6040 6,6040 6,6012 0 0 0 0 1 0 0 1

EQU CAF TS CAF TS CCS TC TC TC

* ZERO CLPASS ENDINST ENTRET REQRET ENTPAS0 ENTPAS0 *+1

; if +, pass 0 ; if +, pass 0 ; if -, not pass 0

; not first pass t hru ENTER, so enter data word ENTPASHI 14012 14013 14014 14015 14016 14017 14020 14021 14022 14023 14024 14025 14026 14027 14030 14031 6,0012 3 6,0013 6 6,0014 6,0015 6,0016 6,0017 6,0020 6,0021 6,0022 6,0023 6,0024 6,0025 6,0026 6,0027 6,0030 6,0031 1 0 0 0 0 3 7 1 0 0 1 0 0 0 6,6036 1 0,0502 0 0,0000 6,6021 6,6020 6,6021 6,6032 1,2053 0,0467 0,0000 6,6026 6,6032 0,0466 6,6341 6,6341 6,6032 0 1 0 1 0 0 0 0 0 0 1 1 1 0 ACCEPTWD 14032 14033 14034 14035 6,0032 6,0033 6,0034 6,0035 4 5 0 0 0,0502 0,0502 2,4770 0,0502 1 0 0 0 ENTEXIT 14036 14037 6,0036 6,0037 15357 1 MMADREF 00034 0 LOWVERB EQU CAF AD CCS TC TC TC TC CAF MAS K CCS TC TC CCS TC TC TC EQU CS TS TC TC EQU DS DS * MMADREF REQRET A *+4 *+2 *+2 ACCEPTWD THREE DECBRNCH A *+2 ACCEPTWD DSPCOUNT GODSPALM GODSPALM *+1 * REQRET REQRET FLASHOFF REQRET ENTRET MMCHANG+1 28 ; assumes TC REGMM at MMCHANG ; lower verb that avoids nount test.

; if L/2 char in for MM code, alarm ; ; ; ; ; ; ; ; ; ; and recycle (decide at MMCHANG+1) >0 +0 <0 -0, was BZF ACCEPTWD in Block II if DEC, alarm if L/5 char in for data, but leave REQRET - and flash on, so operator can supply missing numerical characters and continue. octal, any number of char OK.

; less than 5 char DEC(DSPCOUNT is +) ; less than 5 char DEC(DSPCOUNT is +) ; 5 char in (DSPCOUNT is -)

; 5 char in (DSPCOUNT is -) ; set REQRET +

; first pass thru ENTER, so execute VERB/NOUN ENTPAS0 14040 14041 14042 14043 6,0040 6,0041 6,0042 6,0043 3 5 4 5 1,2050 0,0467 2,4675 0,0466 0 1 0 0 ; test VERB TESTVB 14044 14045 14046 14047 14050 14051 14052 14053 6,0044 4 6,0045 5 6,0046 6 6,0047 6,0050 6,0051 6,0052 6,0053 1 0 0 0 0 0,0470 0 0,0530 1 6,6037 0 0,0000 6,6054 6,6053 6,6053 6,6151 0 0 1 1 1 ; test NOUN TESTNN ; ; ; ; 14054 14055 14056 14057 14060 14061 6,0054 3 6,0055 0 6,0056 2 6,0057 0 6,0060 0 6,0061 0 6,6124 0 1,3526 0 0,0435 1 6,6057 0 6,6062 0 6,6237 1 EQU * EQU CS TS AD CCS TC TC TC TC * VERBREG VERBSAVE LOWVERB A *+4 *+2 *+1 VERBFAN EQU CAF TS CS TS * ZERO DECBRNCH VD1 DSPCOUNT

; noun verb sub enters here ; block further num char, so that stray ; char do not get into verb or nount lig h t s .

; if verb is G/E LOWVB, skip noun test ; save verb for possible recycle. ; LOWVERB - VB ; ; ; ; ; was >0 +0, <0, -0, BZMF VERBFAN in Block II VERB G/E LOWVERB VERB G/E LOWVERB VERB G/E LOWVERB

set MIXBR and pu t the noun address into NNADTEM MIXBR is an enum erated type: 1 = normal nouns 2 = mixed nouns CAF TC IND EX TC TC TC LODNNLOC DXCHJUMP MIXBR *+0 *+2 MIXNOUN ; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne ; computed GOTO

; returns here for normal noun ; returns here for mixed noun

; normal noun, so test noun address table entry (NNADTEM) 14062 14063 14064 14065 6,0062 6,0063 6,0064 6,0065 1 0 0 0 0,0443 6,6147 6,6341 6,6073 0 0 1 0 CCS TC TC TC NNADTEM VERBFAN-2 GODSPALM REQADD ; ; ; ; normal normal if + not in use if +0 specify machine CADR if -

; NNADTEM was -0, so just increment noun address (in NOUNCADR) and ; set the result i n NOUNADD 14066 14067 14070 14071 14072 6,0066 3 6,0067 6 6,0070 5 6,0071 0 6,0072 0 0,0506 1 1,2051 1 0,0506 1 2,4625 1 6,6132 1 XCH AD TS TC TC NOUNCADR ONE NOUNCADR SETNADD INTMCTBS+3 ; augment machine CADR if -0 ; was INCR NOUNCADR in Block II ; set NOUNADD

; NNADTEM was -, s o noun address needs to be specified (loaded). REQADD 14073 14074 14075 14076 14077 14100 14101 14102 14103 14104 14105 14106 14107 14110 14111 14112 14113 14114 14115 14116 6,0073 6,0074 6,0075 6,0076 6,0077 6,0100 6,0101 6,0102 6,0103 3 5 4 6 1 0 0 0 0 1,2062 0,0504 2,4553 0,0433 0,0000 6,6104 6,6103 6,6104 6,6105 1 0 1 0 0 1 0 1 0 EQU CAF TS CS AD CCS TC TC TC TC TC TC CCS TC CS TS CCS TC TC TC TC * BIT15 CLPASS ENDINST ENTEXIT A *+4 *+2 *+2 *+2 INTMCTBS REQDATZ DECBRNCH ALMCYCLE VD1 DSPCOUNT CADRSTOR *+3 USEADD *+1 FLASHON ; external mach CADR to be specified ; ; ; ; alarm and recycle if decimal used for MCTBS octal used OK block num char in

; set CLPASS for pass0 only ; test if reach here from internal or ; from external ; ; ; ; ; was BZF *+2 in Block II >0 +0 <0 -0, external mach CADR to be specified

6,0104 0 6,0105 0 6,0106 6,0107 6,0110 6,0111 6,0112 6,0113 6,0114 6,0115 6,0116 1 0 4 5 1 0 0 0 0

6,6127 0 6,6274 0 0,0467 2,4474 2,4675 0,0466 0,0531 6,6116 6,6117 6,6116 2,4760 0 1 0 0 1 1 0 1 1

; external MCTBS display will leave flas h ; on if ENDIDLE not = +0

; noun address has now been loaded into the Z register. Copy it into ; NOUNCADR and NOU NADD and then jump to the VERBFAN. USEADD 14117 14120 14121 14122 14123 14124 14125 6,0117 3 6,0120 0 6,0121 3 6,0122 0 6,0123 0 6,0124 6,0125 0,0474 0 2,4616 1 6,6124 0 1,3526 0 6,6151 1 16114 1 LODNNLOC 00000 1 EQU XCH TC CAF TC TC DS DS * ZREG SETNCADR LODNNLOC DXCHJUMP VERBFAN LODNNTAB 0 ; *** uses 2 words in Block II ***

; ECADR into NOUNCADR, set EB, NOUNADD ; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne

14126

6,0126

77772 0 NEG5 ; ; ; ; ;

DS

-5

If external (key board input), noun address is in register A. If internal (S/W input), noun address is in MPAC+2. Store the noun a ddress into NOUNCADR and NOUNADD. If the verb is O5. go direct ly to the VERBFAN; for all other verbs, display the noun address in R3 and then go to the VERBFAN. EQU *

INTMCTBS

; entry point for internal: 14127 14130 6,0127 3 6,0130 6 1,2050 0 0,0132 1 CAF AD ZERO MPAC+2 ; was CA MPAC+2 in Block II ; internal mach CADR to be specified

; entry point for external (keyboard input): 14131 14132 14133 6,0131 0 6,0132 4 6,0133 6 2,4616 1 1,2055 1 0,0470 1 TC CS AD SETNCADR FIVE VERBREG ; store addr (A) into NOUNCADR and NOUNA D D ; NVSUB call left CADR in MAPC+2 for mac h ; CADR to be specified.

14134 14135 14136 14137 14140 14141 14142 14143 14144 14145 14146

6,0134 6,0135 6,0136 6,0137 6,0140

1 0 0 0 0

0,0000 6,6141 6,6140 6,6141 6,6151

0 0 1 0 1

CCS TC TC TC TC CAF TS CAF AD TC TC

A *+4 *+2 *+2 VERBFAN R3D1 DSPCOUNT ZERO NOUNCADR DSPOCTWD VERBFAN

; ; ; ; ;

was BZF VERBFAN in Block II >0 +0 <0 -0, don't display CADR if verb = 05

6,0141 3 6,0142 5 6,0143 6,0144 6,0145 6,0146 3 6 0 0

2,4637 1 0,0466 0 1,2050 0,0506 6,7310 6,6151 0 1 1 1

; verb not = 05, display CADR

; was CA NOUNCADR in Block II

; NNADTEM was + (n ormal), so just use the noun address straight from the ; noun table (curr ently in A). The CCS instruction used to test the ; address also dec remented it, so we add one to restore the correct address. 14147 14150 6,0147 6 6,0150 0 1,2051 1 2,4616 1 AD TC ONE SETNCADR

; store addr (A) into NOUNCADR and NOUNA D D

; noun address is currently in NOUNCADR and NOUNADD. VERBFAN 14151 14152 14153 14154 14155 14156 14157 14160 14161 14162 14163 6,0151 4 6,0152 6 6,0153 6,0154 6,0155 6,0156 6,0157 6,0160 6,0161 6,0162 6,0163 1 6 0 0 5 0 0 6,6163 1 0,0470 1 0,0000 1,2051 6,6157 6,6164 0,0130 2,5003 1,3653 20000 0 1 1 1 0 1 1 0 EQU CS AD CCS AD TC TC TS TC TC DS DS EQU IND EX CAF TC EQU CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R * LST2CON VERBREG A ONE *+2 VBFANDIR MPAC RELDSP POSTJUMP GOEXTVB 40 * VERBREG VERBTAB BANKJUMP * GODSPALM DSPA DSPB DSPC DSPAB DSPABC DECDSP DSPDPDEC GODSPALM GODSPALM GODSPALM MONITOR MONITOR MONITOR MONITOR MONITOR MONITOR MONITOR GODSPALM GODSPALM GODSPALM ALOAD BLOAD CLOAD ABLOAD ABCLOAD GODSPALM DSPFMEM GODSPALM GODSPALM VBRQEXEC VBRQWAIT VBRESEQ VBPROC VBTERM VBTSTLTS SLAP1 MMCHANG GODSPALM GODSPALM

; verb-LST2CON

; ver G/ LST2CON ; verb L/ LST2CON ; release display syst ; go to GOEXTVB with VB-40 in MPAC

00050 1 LST2CON VBFANDIR

; first list2 verb (extended verb)

14164 14165 14166

6,0164 2 6,0165 3 6,0166 0

0,0470 0 6,6167 1 1,3712 0 VERBTAB

14167 14170 14171 14172 14173 14174 14175 14176 14177 14200 14201 14202 14203 14204 14205 14206 14207 14210 14211 14212 14213 14214 14215 14216 14217 14220 14221 14222 14223 14224 14225 14226 14227 14230 14231 14232 14233 14234 14235 14236

6,0167 6,0170 6,0171 6,0172 6,0173 6,0174 6,0175 6,0176 6,0177 6,0200 6,0201 6,0202 6,0203 6,0204 6,0205 6,0206 6,0207 6,0210 6,0211 6,0212 6,0213 6,0214 6,0215 6,0216 6,0217 6,0220 6,0221 6,0222 6,0223 6,0224 6,0225 6,0226 6,0227 6,0230 6,0231 6,0232 6,0233 6,0234 6,0235 6,0236

14341 14355 14363 14370 14350 14343 14510 12704 14341 14341 14341 15146 15146 15146 15146 15146 15146 15146 14341 14341 14341 14663 14673 14707 14635 14600 14341 15301 14341 14341 15420 15446 13325 13315 13323 15572 02126 15356 14341 14341

1 1 1 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 1 1 1 1 1 1 1 0 0 1 1 1 0 0 0 1 1

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

VB00 VB01 VB02 VB03 VB04 VB05 VB06 VB07 VB08 VB09 VB10 VB11 VB12 VB13 VB14 VB15 VB16 VB17 VB18 VB19 VB20 VB21 VB22 VB23 VB24 VB25 VB26 VB27 VB28 VB29 VB30 VB31 VB32 VB33 VB34 VB35 VB36 VB37 VB38 VB39

Illegal display oct comp 1 (R1) display oct comp 2 (R1) display oct comp 3 (R1) display oct comp 1,2 (R1,R2) display oct comp 1,2,3 (R1,R2,R3) decimal display DP decimal display (R1,R2) spare spare spare monitor oct comp 1 (R1) monitor oct comp 2 (R2) monitor oct comp 3 (R3) monitor oct comp 1,2 (R1,R2) monitor oct comp 1,2,3 (R1,R2,R3) monitor decimal monitor DP decimal (R1,R2) spare spare spare load comp 1 (R1) load comp 2 (R2) load comp 3 (R3) load comp 1,2 (R1,R2) load comp 1,2,3 (R1,R2,R3) spare fixed memory display spare spare request executive request waitlist resequence proceed (without data) terminate test lights fresh start change major mode spare spare

;----------------- --------------------------------------------------------; MIXNOUN ; NNADTAB contains a relative address, IDADDREL(in low 10 bits), referring ; to where 3 conse cutive addresses are stored (in IDADDTAB). ; MIXNOUN gets dat a and stores in MIXTEMP, +1, +2. It sets NOUNADD for ; MIXTEMP. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 322. ;----------------- --------------------------------------------------------MIXNOUN 14237 6,0237 0 6,6341 1 EQU TC * GODSPALM

; not currently implemented

; ************ BUN CH OF MISSING STUFF ************

;----------------- --------------------------------------------------------; DPTEST ; enter with SF ro utine code number (SF ROUT) in A. Returns to L+1 if no DP. ; Returns to L+2 i f DP. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 322. Also, see p. 263. ;----------------- --------------------------------------------------------DPTEST 14240 14241 14242 14243 14244 14245 14246 14247 14250 14251 14252 14253 14254 14255 14256 14257 14260 14261 6,0240 5 6,0241 3 6,0242 5 6,0243 6,0244 6,0245 6,0246 6,0247 6,0250 6,0251 6,0252 6,0253 6,0254 6,0255 6,0256 6,0257 6,0260 6,0261 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0,0552 0 0,0001 0 0,0553 1 0,0552 6,6245 0,0553 0,0553 0,0553 0,0553 6,6262 6,6262 0,0553 6,6262 0,0553 0,0553 6,6262 0,0553 0,0553 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 DPTEST1 14262 14263 6,0262 2 6,0263 0 0,0553 0 0,0001 0 EQU TS XCH TS IND EX TC TC TC TC TC TC TC TC TC TC TC TC TC TC EQU IND EX TC * DPTEST_A Q DPTEST_Q DPTEST_A *+1 DPTEST_Q DPTEST_Q DPTEST_Q DPTEST_Q DPTEST1 DPTEST1 DPTEST_Q DPTEST1 DPTEST_Q DPTEST_Q DPTEST1 DPTEST_Q DPTEST_Q * DPTEST_Q 1

; ; ; ; ; ; ; ; ; ; ; ; ;

octal only, no DP straight fractional, no DP CDU degrees (XXX.XX), no DP arithmetic SF, no DP DP1OUT DP2OUT Y OPTICS DEGREES, no DP DP3OUT HMS, no DP MS, no DP DP4OUT arith1, no DP 2INTOUT, no DP to get hi part in MPAC

; return to L+2

;----------------- --------------------------------------------------------; REQDATX, REQDATY , REQDATZ ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 323. ;----------------- --------------------------------------------------------REQDATX 14264 14265 14266 14267 6,0264 3 6,0265 5 6,0266 3 6,0267 0 0,0001 0 0,0554 0 2,4635 0 6,6277 0 REQDATY 14270 14271 14272 14273 6,0270 3 6,0271 5 6,0272 3 6,0273 0 0,0001 0 0,0554 0 2,4636 0 6,6277 0 REQDATZ 14274 14275 14276 14277 14300 14301 14302 14303 14304 6,0274 3 6,0275 5 6,0276 3 6,0277 6,0300 6,0301 6,0302 6,0303 5 4 5 0 0,0001 0 0,0554 0 2,4637 1 0,0466 0,0554 0,0502 1,3565 12473 0 REQCOM 1 0 1 1 EQU XCH TS CAF TC EQU XCH TS CAF TC EQU XCH TS CAF TS CS TS TC DS TC * Q REQ_Q R1D1 REQCOM * Q REQ_Q R2D1 REQCOM * Q REQ_Q R3D1 DSPCOUNT REQ_Q REQRET BANKCALL _5BLANK FLASHON

6,0304 0

2,4760 1

ENDRQDAT 14305 6,0305 0 0,0433 0

EQU TC

* ENTEXIT

;----------------- --------------------------------------------------------; UPDATNN, UPDATVB ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 323. ;----------------- --------------------------------------------------------14306 14307 14310 14311 14312 14313 14314 14315 14316 14317 6,0306 5 6,0307 3 6,0310 5 6,0311 3 6,0312 0 6,0313 6,0314 6,0315 6,0316 6,0317 1 6 0 0 0 0,0471 0 UPDATNN 0,0001 0 0,0414 0 6,6124 0 1,3526 0 0,0443 1,2051 6,6320 6,6321 6,6321 0 1 0 1 1 PUTADD 14320 14321 14322 14323 14324 14325 6,0320 0 6,0321 3 6,0322 5 6,0323 3 6,0324 6 6,0325 0 2,4616 1 2,4676 1 0,0466 0 1,2050 0 0,0471 0 6,6335 1 TS EQU XCH TS CAF TC CCS AD TC TC TC EQU TC CAF TS CAF AD TC NOUNREG * Q UPDATRET LODNNLOC DXCHJUMP NNADTEM ONE PUTADD PUTADD+1 PUTADD+1 * SETNCADR ND1 DSPCOUNT ZERO NOUNREG UPDAT1 ; was CA NOUNREG in Block II ; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne

; ; ; ;

>0, +0, <0, -0,

normal normal MCTBS don't change NOUNADD MCTBI don't change NOUNADD

; ECADR into NOUNCADR, sets NOUNADD

14326 14327 14330 14331 14332 14333 14334

6,0326 5 6,0327 3 6,0330 5 6,0331 3 6,0332 5 6,0333 3 6,0334 6

0,0470 1 UPDATVB 0,0001 0 0,0414 0 2,4675 1 0,0466 0 1,2050 0 0,0470 1 UPDAT1

TS EQU XCH TS CAF TS CAF AD EQU TC DS TC

VERBREG * Q UPDATRET VD1 DSPCOUNT ZERO VERBREG * POSTJUMP GOVNUPDT UPDATRET ; was CA VERBREG in Block II

14335 14336 14337

6,0335 0 6,0336 6,0337 0

1,3653 1 13156 1 0,0414 0

; can't use SWCALL to go to DSPDECVN, si n c e ; UPDATVB can itself be called by SWCALL

;----------------- --------------------------------------------------------; GOALMCYC, GODSPA LM ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 324. ;----------------- --------------------------------------------------------14340 6,0340 0 2,4474 1 GOALMCYC TC ALMCYCLE ; needed because bankjump cant handle F/ F

14341 14342

6,0341 0 6,0342

1,3653 1 GODSPALM 13267 0

TC DS

POSTJUMP DSPALARM

;----------------- --------------------------------------------------------; DISPLAY VERBS ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 326. ;----------------- --------------------------------------------------------DSPABC 14343 14344 14345 14346 14347 6,0343 6,0344 6,0345 6,0346 6,0347 4 0 2 4 3 1,2052 6,6414 0,0442 0,0002 0,0427 0 0 1 1 0 DSPAB 14350 14351 14352 14353 6,0350 6,0351 6,0352 6,0353 4 0 2 4 1,2051 6,6414 0,0442 0,0001 0 0 1 1 EQU CS TC IND EX CS XCH EQU CS TC IND EX CS * TWO COMPTEST NOUNADD 2 BUF+2 * ONE COMPTEST NOUNADD 1

14354

6,0354 3

0,0426 1 DSPA

XCH EQU TC TC IND EX CS EQU XCH TC EQU CS TC IND EX CS TC EQU CS TC IND EX CS TC EQU CS AD CCS TC TC TC EQU TS IND EX CAF TS IND EX CS TC XCH TC

BUF+1 * DECTEST TSTFORDP NOUNADD 0 * BUF DSPCOM2 * ONE DCOMPTST NOUNADD 1 DSPCOM1 * TWO DCOMPTST NOUNADD 2 DSPCOM1 * TWO VERBREG A DSPCOM3 ENTEXIT *+1 * DISTEM A R1D1 DSPCOUNT DISTEM BUF DSPOCTWD DISTEM DSPCOM2+2

14355 14356 14357 14360

6,0355 6,0356 6,0357 6,0360

0 0 2 4

6,6435 6,6462 0,0442 0,0000

0 1 1 0 DSPCOM1

14361 14362

6,0361 3 6,0362 0

0,0425 1 6,6375 0 DSPB

14363 14364 14365 14366 14367

6,0363 6,0364 6,0365 6,0366 6,0367

4 0 2 4 0

1,2051 6,6430 0,0442 0,0001 6,6361

0 0 1 1 0 DSPC

14370 14371 14372 14373 14374

6,0370 6,0371 6,0372 6,0373 6,0374

4 0 2 4 0

1,2052 6,6430 0,0442 0,0002 6,6361

0 0 1 1 0 DSPCOM2

14375 14376 14377 14400 14401 14402

6,0375 6,0376 6,0377 6,0400 6,0401 6,0402

4 6 1 0 0 0

1,2052 0,0470 0,0000 6,6403 0,0433 6,6403

0 1 0 0 0 0 DSPCOM3

; A B C AB ABC ; -1 -0 +1 +2 +3 ; +0 +0 +0 +1 +2

IN A IN A AFTER CCS

14403 14404 14405 14406 14407 14410 14411 14412 14413

6,0403 6,0404 6,0405 6,0406 6,0407 6,0410 6,0411 6,0412 6,0413

5 2 3 5 2 4 0 3 0

0,0417 0,0000 2,4635 0,0466 0,0417 0,0425 6,7310 0,0417 6,6377

0 0 0 0 1 0 1 0 1

; +0, +1, +2 into DISTEM

;----------------- --------------------------------------------------------; COMPTEST ; alarms if compon ent number of verb (load or oct display) is ; greater than the highest component number of noun. ; ; DCOMPTST ; alarms if decima l only bit (bit 4 of comp code number) = 1. ; If not, it perfo rms regular COMPTEST. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 326. ;----------------- --------------------------------------------------------COMPTEST 14414 14415 14416 6,0414 5 6,0415 3 6,0416 5 0,0420 1 0,0001 0 0,0547 1 COMPTST1 14417 14420 14421 14422 14423 14424 14425 14426 6,0417 6,0420 6,0421 6,0422 6,0423 6,0424 6,0425 6,0426 0 0 7 6 1 0 0 0 6,6501 2,4647 1,2053 0,0420 0,0000 0,0547 5,6271 6,6341 0 0 1 1 0 1 0 1 NDOMPTST 14427 6,0427 0 0,0547 1 DCOMPTST 14430 14431 14432 14433 14434 6,0430 5 6,0431 3 6,0432 5 6,0433 0 6,0434 0 0,0420 1 0,0001 0 0,0547 1 6,6435 0 6,6417 0 EQU TS XCH TS EQU TC TC MAS K AD CCS TC TC TC EQU TC EQU TS XCH TS TC TC * SFTEMP1 Q LXCH_LPRET * GETCOMP LEFT5 THREE SFTEMP1 A LXCH_LPRET CCSHOLE GODSPALM * LXCH_LPRET * SFTEMP1 Q LXCH_LPRET DECTEST COMPTST1

; - verb comp ; was LXCH Q in block II ; save return address in faux LP

; noun comp ; noun comp - verb comp ; noun comp G/ verb comp; return ; noun comp L/ verb comp

; noun comp = verb comp; return

; - verb comp ; was LXCH Q in block II ; save return address in faux LP

;----------------- ---------------------------------------------------------

; DECTEST ; alarms if dec on ly bit = 1 (bit 4 of comp code number1). Returns if not. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 327. ;----------------- --------------------------------------------------------DECTEST 14435 14436 14437 14440 14441 14442 14443 6,0435 3 6,0436 5 6,0437 0 6,0440 7 6,0441 1 6,0442 0 6,0443 0 0,0001 0 0,0132 1 6,6501 0 1,2063 1 0,0000 0 6,6341 1 0,0132 1 EQU XCH TS TC MAS K CCS TC TC * Q MPAC+2 GETCOMP BIT14 A GODSPALM MPAC+2

; was QXCH MPAC+2 in block II

;----------------- --------------------------------------------------------; DCTSTCYC ; alarms and recyc les if dec only bit = 1 (bit 4 of comp code number). ; Returns if not. Used by load verbs. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 327. ;----------------- --------------------------------------------------------DCTSTCYC 14444 14445 14446 14447 14450 14451 14452 6,0444 3 6,0445 5 6,0446 0 6,0447 7 6,0450 1 6,0451 0 6,0452 0 0,0001 0 0,0547 1 6,6501 0 1,2063 1 0,0000 0 2,4474 1 0,0547 1 EQU XCH TS TC MAS K CCS TC TC * Q LXCH_LPRET GETCOMP BIT14 A ALMCYCLE LXCH_LPRET

; was LXCH Q in block II ; save return address in faux LP

;----------------- --------------------------------------------------------; NOUNTEST ; alarms if no-loa d bit (bit 5 of comp code number) = 1 ; if not, it retur ns. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 327. ;----------------- --------------------------------------------------------NOUNTEST 14453 14454 14455 14456 14457 14460 14461 6,0453 3 6,0454 5 6,0455 0 6,0456 6,0457 6,0460 6,0461 1 0 0 0 0,0001 0 0,0547 1 6,6501 0 0,0000 0,0547 0,0547 6,6341 0 1 1 1 EQU XCH TS TC CCS TC TC TC * Q LXCH_LPRET GETCOMP A LXCH_LPRET LXCH_LPRET GODSPALM

; was LXCH Q in block II ; save return address in faux LP

;----------------- --------------------------------------------------------; TSTFORDP ; test for DP. If so, get minor part only. ; The Block II ver sion had some code that checked for a -1 in NNADTEM ; which meant use an I/O channel instead of memory. This was removed ; for the Block I. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 327. ;----------------- ---------------------------------------------------------

TSTFORDP 14462 14463 14464 14465 14466 14467 14470 14471 14472 14473 14474 14475 6,0462 3 6,0463 5 6,0464 6,0465 6,0466 6,0467 2 0 0 0 0,0001 0 0,0547 1 0,0435 6,6465 6,6470 0,0547 1 0 1 1

EQU XCH TS IND EX TC TC TC TC TC TC XCH AD TS

* Q LXCH_LPRET MIXBR * *+2 LXCH_LPRET SFRUTNOR DPTEST LXCH_LPRET NOUNADD ONE NOUNADD

; was LXCH Q in block II ; save return address in faux LP

; normal ; mixed case already handled in MIXNOUN

6,0470 0 6,0471 0 6,0472 0 6,0473 3 6,0474 6 6,0475 5

6,6762 1 6,6240 1 0,0547 1 0,0442 0 1,2051 1 0,0442 0

; no DP ; was INCR NOUNADD in Block II ; DP E+1 into NOUNADD for minor part

14476

6,0476 0

0,0547 1

TC

LXCH_LPRET

;----------------- --------------------------------------------------------; GETCOMP ; ; noun address is in NNADTEM ; noun type is in NNTYPTEM ; ; MIXBR is an enum erated type: ; 1 = normal nouns ; 2 = mixed nouns ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 328. ;----------------- --------------------------------------------------------14477 14500 6,0477 6,0500 00444 0 COMPICK 00443 1 GETCOMP 14501 14502 14503 14504 14505 14506 14507 6,0501 2 6,0502 3 6,0503 6,0504 6,0505 6,0506 2 4 4 7 0,0435 1 6,6476 1 0,0000 0,0000 0,0000 2,4666 0 0 0 1 DS DS EQU IND EX CAF IND EX CS COM MAS K TC NNTYPTEM NNADTEM * MIXBR COMPICK-1 A 0 HI5 Q

; normal ; ADRES NNTYPTEM

mixed ADRES NNADTEM

; C(NNTYPTEM) ; was CA 0 in Block II

C(NNADTEM)

6,0507 0

0,0001 0

;----------------- --------------------------------------------------------; DECDSP -- DECIMA L DISPLAY ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 328. ;----------------- --------------------------------------------------------DECDSP 14510 14511 14512 14513 6,0510 6,0511 6,0512 6,0513 0 0 7 5 6,6501 2,4647 1,2053 0,0414 0 0 1 0 DSPDCGET 14514 14515 14516 14517 14520 14521 14522 14523 6,0514 6,0515 6,0516 6,0517 6,0520 6,0521 6,0522 6,0523 5 6 2 4 2 3 1 0 0,0417 0,0442 0,0000 0,0000 0,0417 0,0472 0,0417 6,6514 0 0 0 0 1 0 1 1 DSPDCPUT 14524 14525 14526 14527 14530 14531 14532 14533 14534 14535 14536 14537 14540 14541 14542 14543 14544 14545 6,0524 6,0525 6,0526 6,0527 6,0530 6,0531 6,0532 6,0533 6,0534 6,0535 6,0536 3 5 5 2 3 5 2 4 5 0 5 1,2050 0,0131 0,0132 0,0414 2,4635 0,0466 0,0414 0,0472 0,0130 6,7003 0,0420 0 1 1 1 0 0 1 1 0 0 1 EQU TC TC MAS K TS EQU TS AD IND EX CS IND EX XCH CCS TC EQU CAF TS TS IND EX CAF TS IND EX CS TS TC TS CAF TC IND EX TC TC TC TC EQU TC TC DS EQU TC DS CCS TC TC TS * GETCOMP LEFT5 THREE DECOUNT * DECTEM NOUNADD A 0 DECTEM XREG DECTEM DSPDCGET * ZERO MPAC+1 MPAC+2 DECOUNT R1D1 DSPCOUNT DECOUNT XREG MPAC SFCONUM SFTEMP1 GTSFOUTL DXCHJUMP MIXBR *+0 DSPSFNOR SFRUTMIX DECDSP3 * SFRUTNOR DECDSP3 GTSFOUT * BANKCALL DSPDECWD DECOUNT *+2 ENTEXIT DECOUNT

; comp number into DECOUNT

; picks up data ; DECTEM 1COMP +0, 2COMP +1, 3COMP +2

; cant use BUF since DMP uses it ; more to get

; displays data ; DECOUNT 1COMP +0, 2COMP +1, 3COMP +2

; 2X (SF CON NUMB) in A

6,0537 3 6,0540 0 6,0541 6,0542 6,0543 6,0544 6,0545 2 0 0 0 0

6,6550 1 1,3526 0 0,0435 6,6542 6,6546 6,6770 6,6560 1 1 0 1 1

; was DCA GTSFOUTL, DXCH Z in Block II ; bank jump to SF constant table read rt n e

14546 14547 14550

6,0546 0 6,0547 0 6,0550

DSPSFNOR 6,6762 1 6,6560 1 16162 0 GTSFOUTL DSPDCEND

14551 14552 14553 14554 14555 14556

6,0551 6,0552 6,0553 6,0554 6,0555 6,0556

0 1 0 0 5

1,3565 13064 0,0414 6,6556 0,0433 0,0414

1 1 1 1 0 0

; all SFOUT routines end here

14557

6,0557 0

6,6524 1 DECDSP3

TC EQU IND EX CAF TC EQU CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R

DSPDCPUT * A SFOUTABR BANKJUMP * PREDSPAL DSPDCEND DEGOUTSF ARTOUTSF 0 0 0 0 HMSOUT 0 0 0 0

; more to display

14560 14561 14562

6,0560 2 6,0561 3 6,0562 0

0,0000 0 6,6563 1 1,3712 0 SFOUTABR

14563 14564 14565 14566 14567 14570 14571 14572 14573 14574 14575 14576 14577

6,0563 6,0564 6,0565 6,0566 6,0567 6,0570 6,0571 6,0572 6,0573 6,0574 6,0575 6,0576 6,0577

13265 14551 12564 12644 00000 00000 00000 00000 16000 00000 00000 00000 00000

1 0 0 1 1 1 1 1 0 1 1 1 1

; ; ; ; ; ; ; ; ; ; ; ; ;

0, alarm if dec display with octal onl y n o u n 1 2 3 4 ********** 5 ********** 6 ********** 7 ********** 8 9 ********** 10 ********* 11 ********* 12 *********

BANK41_2

EQU

ORG BANK40_2 ; COLOSSUS pp. 330-332 INC L bank40_2.asm ;================= ========================================================= ; SCALE FACTOR ROU TINES (file:bank40_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 330-332. ;================= ========================================================= DEGOUTSF 12564 12565 12566 12567 12570 12571 5,0564 5,0565 5,0566 5,0567 5,0570 5,0571 3 5 0 0 0 0 1,2050 0,0132 5,6603 5,6571 5,6572 5,6616 0 1 1 1 1 0 SETAUG 12572 12573 12574 12575 12576 12577 12600 12601 12602 5,0572 5,0573 5,0574 5,0575 5,0576 5,0577 5,0600 5,0601 3 2 6 3 3 2 6 3 1,2050 0,0132 5,6640 0,0420 1,2050 0,0132 5,6641 0,0421 0 0 0 1 0 0 1 0 EQU CAF TS TC TC TC TC EQU CAF IND EX AD XCH CAF IND EX AD XCH TC FIXRANGE 12603 12604 12605 12606 12607 12610 12611 12612 12613 12614 12615 5,0603 3 5,0604 5 5,0605 5,0606 5,0607 5,0610 5,0611 5,0612 5,0613 5,0614 5,0615 1 0 0 0 4 7 5 2 0 0,0001 0 0,0563 1 0,0130 0,0563 0,0563 5,6611 1,2062 0,0130 0,0130 0,0563 0,0001 1 1 1 1 0 1 0 0 0 DEGCOM 12616 5,0616 Block II 12617 5,0617 12620 5,0620 12621 5,0621 12622 12623 12624 12625 12626 12627 12630 5,0622 5,0623 5,0624 5,0625 3 2 6 3 3 2 6 3 1,2050 0 0,0132 0 5,6641 1 0,0131 1 1,2050 0,0132 5,6640 0,0130 0 0 0 0 EQU XCH TS CCS TC TC TC CS MAS K TS IND EX TC EQU CAF IND EX AD XCH CAF IND EX AD XCH TC XCH AD * ZERO MPAC+2 FIXRANGE *+2 SETAUG DEGCOM * ZERO MPAC+2 DEGTAB SFTEMP1 ZERO MPAC+2 DEGTAB+1 SFTEMP1+1 Q * Q FR_RETQ MPAC FR_RETQ FR_RETQ *+1 BIT15 MPAC MPAC FR_RETQ 1 * ZERO MPAC+2 DEGTAB+1 MPAC+1 ZERO MPAC+2 DEGTAB MPAC SHORTMP SFTEMP1+1 MPAC+1 ; was DXCH SFTEMP1, DAS MPAC in Block II ; ; ; ; if MPAC if MPAC masking was TCF is +, return is -, return out the sign *+1 in Block to L+1 to L+2 after bit II

; set index for full scale ; no augment needed (SFTEMP1 and 2 are 0 ) ; set augmenter according to C(MPAC+2)

; loads SFTEMP1 and SFTEMP2 with the ; DP augmenter constant ; was DCA DEGTAB, DXCH SFTEMP1 in Block I I

5,0602 0

0,0001 0

; was INDEX MPAC+2, DCA DEGTAB, DXCH MPA C i n ; loads multiplier, does SHORTMP, and ; adds augmenter ; adjusted angle in A

5,0626 0 5,0627 3 5,0630 6

2,4353 0 0,0421 0 0,0131 1

12631 12632 12633 12634 12635 12636

5,0631 5 5,0632 3 5,0633 5,0634 5,0635 5,0636 6 6 5 3

0,0131 1 1,2050 0 0,0420 0,0130 0,0130 1,2050 1 0 0 0

TS CAF AD AD TS CAF

MPAC+1 ZERO SFTEMP1 MPAC MPAC ZERO

; skip on overflow ; otherwise, make interword carry=0

; skip on overflow ; otherwise, make interword carry=0

12637

5,0637 0

5,6651 0 DEGTAB

TC EQU DS DS DS DS

SCOUTEND * %05605 %03656 %16314 %31463

12640 12641 12642 12643

5,0640 5,0641 5,0642 5,0643

05605 03656 16314 31463

1 1 0 1

; ; ; ;

Hi Lo Hi Lo

part part part part

of of of of

.18 .18 .45 .45

ARTOUTSF 12644 12645 12646 12647 12650 12651 12652 5,0644 5,0645 5,0646 5,0647 3 3 3 3 0,0421 0,0131 0,0420 0,0130 0 1 1 0

EQU XCH XCH XCH XCH TC TC CAD R

* SFTEMP1+1 MPAC+1 SFTEMP1 MPAC PRSHRTMP POSTJUMP DSPDCEND

; was DXCH SFTEMP1, DXCH MPAC in Block I I ; assumes point at left of DP SFCON

5,0650 0 5,0651 0 5,0652

2,4740 0 1,3653 1 SCOUTEND 14551 0

; if C(A) = -0, SHORTMP fails to give -0

;----------------- --------------------------------------------------------; READLO ; Picks up fresh d ata for both HI and LO and leaves it in MPAC, MPAC+1. ; This is needed f or time display. It zeroes MPAC+2, but does not force ; TPAGREE. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 332. ;----------------- --------------------------------------------------------READLO 12653 12654 12655 12656 12657 12660 12661 12662 12663 12664 5,0653 3 5,0654 5 5,0655 2 5,0656 0 5,0657 0 5,0660 5,0661 5,0662 5,0663 5,0664 3 2 6 7 0 0,0001 0 0,0441 0 0,0435 1 5,6656 1 5,6701 1 1,2050 0,0414 0,0445 2,4672 2,4633 0 1 1 1 0 EQU XCH TS IND EX TC TC CAF IND EX AD MAS K TC * Q TEM4 MIXBR * RDLONOR ZERO DECOUNT IDAD1TEM LOW11 SETEBANK ; MIXBR=1, so normal noun ; ; ; ; ; MIXBR=2, so mixed noun was INDEX DECOUNT, CA IDAD1TEM in Bloc k I I get IDADDTAB entry for comp K of noun E bank set EB, leave E address in A

; save return address

; ; ; ;

Dereference noun address to move components of noun into MPAC, MPAC+1 mixed normal C(E SUBK) C(E) C((E SUBK)+1) C(E+1) EQU TS CAF IND EX AD TS CAF IND EX AD TS CAF TS TC CAF AD TC EQU ORG INC L * ADDRWD1 ZERO ADDRWD1 0 MPAC ZERO ADDRWD1 1 MPAC+1 ZERO MPAC+2 TEM4 ZERO NOUNADD READLO1 * BANK42_1 bank42_1.asm ; COLOSSUS pp. 333-336 ; return ; was CA NOUNADD in Block II

READLO1 12665 12666 12667 12670 12671 12672 12673 12674 12675 12676 12677 12700 12701 12702 12703 5,0665 5 5,0666 5,0667 5,0670 5,0671 5,0672 5,0673 5,0674 5,0675 3 2 6 5 3 2 6 5 0,0576 0 1,2050 0,0576 0,0000 0,0130 1,2050 0,0576 0,0001 0,0131 0 1 1 0 0 1 0 1

; temp store addr for immediate use belo w ; was INDEX A, DCA Q, DXCH MPAC in Block I I

5,0676 3 5,0677 5 5,0700 0 5,0701 3 5,0702 6 5,0703 0

1,2050 0 0,0132 1 0,0441 0 1,2050 0 RDLONOR 0,0442 0 5,6665 1 ENDRDLO BANK40_3

;================= ========================================================= ; DISPLAY ROUTINES (file:bank42_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 333-336. ;================= ========================================================= ;----------------- --------------------------------------------------------; HMSOUT -- OUTPUT SCALE FACTOR ROUTINE ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 333. ;----------------- --------------------------------------------------------HMSOUT 16000 16001 16002 16003 16004 16005 16006 16007 16010 16011 16012 16013 16014 16015 16016 16017 16020 16021 16022 16023 16024 7,0000 0 7,0001 7,0002 0 7,0003 0 7,0004 0 7,0005 7,0006 3 7,0007 5 7,0010 0 7,0011 7,0012 7,0013 7,0014 7,0015 7,0016 7,0017 7,0020 0 3 3 5 3 3 0 1,3565 1 12653 1 2,4150 1 7,6053 1 EQU TC DS * BANKCALL READLO

; read fresh data for HI and LO into MPA C , ; MPAC+1.

TC TPAGREE ; make DP data agree TC SEPSECNR ; leave frac sec/60 in MPAC, MPAC+1, lea v e ; whole min in bit 13 of LOWTEMOUT and above 2,4374 0 TC DMP ; use only fract sec/60 mod 60 06043 0 ADR ES SECON2 ; mult by .06 2,4637 1 0,0466 0 1,3565 1 13064 1 7,6074 7,6045 0,0130 0,0476 7,6046 0,0131 2,4740 1 0 0 1 0 1 0 ; mult by .0006 CAF TS TC DS TC CAF XCH TS CAF XCH TC CAF TS TC DS R3D1 DSPCOUNT BANKCALL DSPDECWD SEPMIN MINCON2 MPAC HITEMOUT MINCON2+1 MPAC+1 PRSHRTMP R2D1 DSPCOUNT BANKCALL DSPDECWD ; gives CENT1-SEC/10EXP5 mod 60

; display sec mod 60

; ; ; ;

remove rest of seconds leave fract min/60 in MPAC+1, leave whole hours in MPAC save whole hours

; use only fract min/60 mod 60 ; if C(A) = -0, SHORTMP fails to give -0 . ; gives min/10EXP5 mod 60

7,0021 3 7,0022 5 7,0023 0 7,0024

2,4636 0 0,0466 0 1,3565 1 13064 1

; display min mod 60

16025 16026 16027 16030 16031 16032 16033 16034 16035 16036 16037 16040 16041 16042 16043 16044 16045 16046 16047 16050 16051 16052

7,0025 7,0026 7,0027 7,0030

3 5 3 5

7,6051 0,0130 7,6052 0,0131

0 0 0 1

CAF TS CAF TS

HRCON1 MPAC HRCON1+1 MPAC+1 ZERO HITEMOUT PRSHRTMP R1D1 DSPCOUNT BANKCALL DSPDECWD ENTEXIT %25660 %31742 %01727 %01217 %00011 %32445 %02104 %10422 %05174 %13261

; was DCA HRCON1, DXCH MPAC in Block II

; minutes, seconds have been removed ; was CA HITEMOUT in Block II ; use whole hours ; if C(A) = -0, SHORTMP fails to give -0 . ; gives hours/10EXP5

7,0031 3 7,0032 6 7,0033 0 7,0034 3 7,0035 5 7,0036 0 7,0037 7,0040 0 7,0041 7,0042 7,0043 7,0044 7,0045 7,0046 7,0047 7,0050 7,0051 7,0052

1,2050 0 0,0476 1 2,4740 0

CAF AD TC ; mult by .16384 2,4635 0 CAF 0,0466 0 TS 1,3565 1 13064 1 0,0433 0 25660 0 SECON1 31742 1 01727 1 SECON2 01217 1 00011 1 MINCON2 32445 0 02104 0 MINCON1 10422 1 05174 0 HRCON1 13261 0 TC DS TC DS DS DS DS DS DS DS DS DS DS

; use regular DSPDECWD, with round off

; 2EXP12/6000

; .06 for seconds display

; .0006 for minutes display

; .066..66 upped by 2EXP-28

; .16384 decimal

; ************* mi ssing stuff **************** SEPSECNR 16053 16054 16055 16056 7,0053 3 7,0054 5 7,0055 0 7,0056 0,0001 0 0,0441 0 2,4374 0 06041 1 EQU XCH TS TC ADR ES * Q SEPSCRET DMP SECON1

; this entry avoid rounding by .5 secs

; mult by 2EXP12/6000 ; gives fract sec/60 in bit12 of MPAC+1

16057 16060 16061 16062 16063 16064 16065 16066 16067 16070 16071 16072 16073

7,0057 3 7,0060 6 7,0061 3 7,0062 3 7,0063 6 7,0064 3 7,0065 0 7,0066 0 7,0067 7,0070 7,0071 7,0072 3 3 3 3

1,2050 0 0,0130 0 0,0476 1 1,2050 0 0,0131 1 0,0477 0 2,4721 1 2,4721 1 1,2050 0,0132 0,0131 0,0130 0 1 1 0

CAF AD XCH CAF AD XCH TC TC CAF XCH XCH XCH TC

ZERO MPAC HITEMOUT ZERO MPAC+1 HITEMOUT+1 TPSL1 TPSL1 ZERO MPAC+2 MPAC+1 MPAC SEPSCRET

; was DCA MPAC, DXCH HITEMOUT in Block I I ; save minutes and hours

; gives fract sec/60 in MPAC+1, MPAC+2

; leave fract sec/60 in MPAC, MPAC+1

7,0073 0

0,0441 0

SEPMIN 16074 16075 16076 16077 16100 16101 16102 16103 16104 16105 7,0074 3 7,0075 5 7,0076 3 7,0077 6 7,0100 7,0101 7,0102 7,0103 2 4 2 4 0,0001 0 0,0441 0 1,2050 0 0,0477 0 0,0000 1,2076 0,0000 1,2064 1 0 1 0

EQU XCH TS CAF AD EXT END MP EXT END MP

* Q SEPMNRET ZERO LOTEMOUT

; finds whole minutes in bit13 ; of LOWTEMOUT and above.

; removes rest of seconds ; ; ; ; leaves leaves SR 12, SR 2?, fract min/60 in MPAC+1 whole hours in MPAC throw away LP take from LP. = SL 12

BIT3 BIT13

7,0104 3 7,0105 5

0,0003 1 0,0131 1

XCH LP TS MPAC+1 ; forces bits 12-1 to 1 if -. CAF AD TS TC ADR ES TC ZERO HITEMOUT MPAC DMP MINCON1 SEPMNRET

; was LXCH MPAC+1 in Block II ; this forces bits 12-1 to 0 if +,

16106 16107 16110 16111 16112 16113

7,0106 3 7,0107 6 7,0110 5 7,0111 0 7,0112 7,0113 0

1,2050 0 0,0476 1 0,0130 0 2,4374 0 06047 1 0,0441 0 ENDSPMIN

; mult by 1/15 ; gives fract min/60 in MPAC+1 ; gives whole hours in MPAC

BANK42_2

EQU

ORG BANK40_3 ; COLOSSUS pp. 336 INC L bank40_3.asm ;================= ========================================================= ; WORD DISPLAY ROU TINES (file:bank40_3.asm) ; ; AGC Block II COL OSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 336. ;================= ========================================================= ;----------------- --------------------------------------------------------; DSPDPDEC ; This is a specia l purpose verb for displaying a double precision AGC ; word as 10 decim al digits on the AGC display panel. It can be used with ; any noun, except mixed nouns. It displays the contents of the register ; NOUNADD is point ing to. If used with nouns which are inherently not DP ; such as the CDU counters, the display will be garbage. ; Display is in R1 and R2 only with the sign in R1. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 353. ;----------------- --------------------------------------------------------DSPDPDEC 12704 12705 12706 12707 12710 12711 12712 12713 12714 12715 12716 12717 12720 12721 5,0704 5,0705 5,0706 5,0707 5,0710 5,0711 5,0712 5,0713 5,0714 5,0715 5,0716 5,0717 2 0 0 0 3 2 6 5 3 2 6 5 0,0435 5,6705 5,6710 5,7267 1,2050 0,0442 0,0000 0,0130 1,2050 0,0442 0,0001 0,0131 1 0 1 0 0 1 1 0 0 1 0 1 EQU IND EX TC TC TC CAF IND EX AD TS CAF IND EX AD TS CAF TS * MIXBR *+0 *+2 DSPALARM ZERO NOUNADD 0 MPAC ZERO NOUNADD 1 MPAC+1 R1D1 DSPCOUNT

; normal noun

; was DCA 0, DXCH MPAC in Block II

; was DCA 0, DXCH MPAC in Block II

5,0720 3 5,0721 5

2,4635 0 0,0466 0

12722 12723 12724 12725 12726

5,0722 3 5,0723 5 5,0724 0 5,0725 0 5,0726 0

1,2050 0 0,0132 1 2,4150 1 5,7131 0 0,0433 0 ENDDPDEC

CAF TS TC TC TC

ZERO MPAC+2 TPAGREE DSP2DEC ENTEXIT

BANK40_4

EQU

ORG BANK41_2 ; COLOSSUS pp. 337-342 INC L bank41_2.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 337-342. ;================= ========================================================= ;================= ========================================================= ; PINBALL GAME LOA D VERBS (file:bank41_2.asm) ; ; If alarm conditi on is detected during execute, check fail light is ; turned on and EN DOFJOB. If alarm condition is detected during enter ; of data, check f ail is turned on and it recycles to execute of ; original load ve rb. Recycle caused by 1) decimal machine CADR, ; 2) mixture of oc tal/decimal data, 3) octal data into decimal only ; noun, 4) decimal data into octal only noun, 5) data too large for ; scale, 6) fewer than two data words loaded for HRS, MIN, SEC noun. ; For #2-6, alarm and recycle occur at final enter of set; for #1, ; alarm and recycl e occur at enter of CADR. ; ; AGC Block II COL OSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 337-343. ;================= ========================================================= ABCLOAD 14600 14601 14602 14603 14604 14605 14606 14607 14610 14611 14612 14613 6,0600 4 6,0601 0 6,0602 0 6,0603 3 6,0604 0 6,0605 0 6,0606 3 6,0607 0 6,0610 0 6,0611 3 6,0612 0 6,0613 0 1,2052 0 6,6414 0 6,6453 0 6,6733 0 6,6326 0 6,6264 1 6,6734 1 6,6326 0 6,6270 1 6,6735 0 6,6326 0 6,6274 0 PUTXYZ 14614 14615 14616 14617 14620 14621 14622 14623 14624 14625 14626 14627 14630 14631 14632 14633 6,0614 4 6,0615 0 6,0616 3 6,0617 0 6,0620 6,0621 6,0622 6,0623 6,0624 6,0625 6,0626 6,0627 6,0630 6,0631 6,0632 6,0633 3 0 2 5 3 0 2 5 3 0 2 5 1,2056 1 6,6736 0 6,6124 0 1,3526 0 1,2050 6,7031 0,0442 0,0000 1,2051 6,7031 0,0442 0,0001 1,2052 6,7031 0,0442 0,0002 0 1 1 1 1 1 1 0 1 1 1 0 EQU CS TC TC CAF TC TC CAF TC TC CAF TC TC EQU CS TC CAF TC CAF TC IND EX TS CAF TC IND EX TS CAF TC IND EX TS * TWO COMPTEST NOUNTEST VBSP1LD UPDATVB-1 REQDATX VBSP2LD UPDATVB-1 REQDATY VBSP3LD UPDATVB-1 REQDATZ * SIX ALLDC_OC LODNNLOC DXCHJUMP ZERO PUTCOM NOUNADD 0 ONE PUTCOM NOUNADD 1 TWO PUTCOM NOUNADD 2

; test if noun can be loaded

; test that the 3 data words loaded are ; all dec or all oct ; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne ; X comp

; Y comp

; Z comp

; *************** missing stuff ***************** ; Omitted a bunch of code from here that does special stuff if the noun=7. ; (a noun that ope rates on I/O channels and flagbits) 14634 6,0634 0 6,6723 1 TC LOADLV

ABLOAD

EQU

14635 14636 14637 14640 14641 14642 14643 14644 14645

6,0635 4 6,0636 0 6,0637 0 6,0640 3 6,0641 0 6,0642 0 6,0643 3 6,0644 0 6,0645 0

1,2051 0 6,6414 0 6,6453 0 6,6733 0 6,6326 0 6,6264 1 6,6734 1 6,6326 0 6,6270 1 PUTXY

CS TC TC CAF TC TC CAF TC TC EQU CS TC CAF TC CAF TC IND EX TS CAF TC IND EX TS TC ALOAD EQU TC CAF TC CAF TC IND EX TS TC BLOAD EQU CS TC CAF TS TC CAF TC CAF TC IND EX TS TC EQU CS TC CAF TS TC CAF TC CAF TC IND EX TS TC EQU CAF TS CS TS CS TS TC DS DS DS DS EQU TS

ONE COMPTEST NOUNTEST VBSP1LD UPDATVB-1 REQDATX VBSP2LD UPDATVB-1 REQDATY * FIVE ALLDC_OC LODNNLOC DXCHJUMP ZERO PUTCOM NOUNADD 0 ONE PUTCOM NOUNADD 1 LOADLV * REQDATX LODNNLOC DXCHJUMP ZERO PUTCOM NOUNADD 0 LOADLV * ONE COMPTEST BIT15 CLPASS REQDATY LODNNLOC DXCHJUMP ONE PUTCOM NOUNADD 1 LOADLV * TWO COMPTEST BIT15 CLPASS REQDATZ LODNNLOC DXCHJUMP TWO PUTCOM NOUNADD 2 LOADLV * ZERO DECBRNCH ZERO LOADSTAT VD1 DSPCOUNT POSTJUMP RECALTST 21 22 23 * DECOUNT

; test if noun can be loaded

14646 14647 14650 14651 14652 14653 14654 14655 14656 14657 14660 14661 14662

6,0646 4 6,0647 0 6,0650 3 6,0651 0 6,0652 6,0653 6,0654 6,0655 6,0656 6,0657 6,0660 6,0661 3 0 2 5 3 0 2 5

1,2055 1 6,6736 0 6,6124 0 1,3526 0 1,2050 6,7031 0,0442 0,0000 1,2051 6,7031 0,0442 0,0001 0 1 1 1 1 1 1 0

; test that the 2 data words loaded are ; all dec or all oct ; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne ; X comp

; Y comp

6,0662 0

6,6723 1

14663 14664 14665 14666 14667 14670 14671 14672

6,0663 0 6,0664 3 6,0665 0 6,0666 6,0667 6,0670 6,0671 6,0672 3 0 2 5 0

6,6264 1 6,6124 0 1,3526 0 1,2050 6,7031 0,0442 0,0000 6,6723 0 1 1 1 1

; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne ; X comp

14673 14674 14675 14676 14677 14700 14701 14702 14703 14704 14705 14706

6,0673 6,0674 6,0675 6,0676 6,0677 6,0700 6,0701 6,0702 6,0703 6,0704 6,0705 6,0706

4 0 3 5 0 3 0 3 0 2 5 0

1,2051 6,6414 1,2062 0,0504 6,6270 6,6124 1,3526 1,2051 6,7031 0,0442 0,0001 6,6723

0 0 1 0 1 0 0 1 1 1 0 1 CLOAD

; set CLPASS for PASS0 only

; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne

14707 14710 14711 14712 14713 14714 14715 14716 14717 14720 14721 14722

6,0707 6,0710 6,0711 6,0712 6,0713 6,0714 6,0715 6,0716 6,0717 6,0720 6,0721 6,0722

4 0 3 5 0 3 0 3 0 2 5 0

1,2052 6,6414 1,2062 0,0504 6,6274 6,6124 1,3526 1,2052 6,7031 0,0442 0,0002 6,6723

0 0 1 0 0 0 0 1 1 1 0 1 LOADLV

; set CLPASS for PASS0 only

; was DCA LODNNLOC, DXCH Z in Block II ; bank jump to noun table read rtne

; yes, COLOSSUS actually did this

14723 14724 14725 14726 14727 14730 14731 14732 14733 14734 14735

6,0723 6,0724 6,0725 6,0726 6,0727 6,0730 6,0731 6,0732 6,0733 6,0734 6,0735

3 5 4 5 4 5 0

1,2050 0,0467 1,2050 0,0503 2,4675 0,0466 1,3653 13413

0 1 1 1 0 0 1 0

; ; ; ;

to block numerical chars and clears after a completed load after completed load, go to RECALTST to see if there is RECALL from ENDIDLE

00025 0 VBSP1LD 00026 0 VBSP2LD 00027 1 VBSP3LD ALLDC_OC

; VB21 = ALOAD ; VB22 = BLOAD ; VB23 = CLOAD

14736

6,0736 5

0,0414 0

; test that data words loaded are either

14737 14740 14741 14742 14743 14744 14745 14746 14747 14750 14751 14752 14753 14754 14755 14756 14757 14760 14761

6,0737 3 6,0740 5 6,0741 6,0742 6,0743 6,0744 6,0745 6,0746 6,0747 6,0750 6,0751 6,0752 6,0753 6,0754 6,0755 4 5 4 4 1 0 0 6 1 0 0 0 0

0,0001 0 0,0556 1 0,0467 0,0021 0,0021 0,0021 0,0000 6,6750 0,0556 0,0414 0 1 0 0 0 0 1 0

XCH TS

Q ALLDC_OC_Q

; (needed to handle TCF conversion below ) ; save return address ; all dec or all oct; alarms if not

CS DECBRNCH TS SR CS SR CS SR CCS A TC *+2 TC ALLDC_OC_Q AD DECOUNT ; (but it has been decremented by CCS) 0,0000 0 CCS A 6,6756 0 TC *+4 6,6755 0 TC *+2 6,6756 0 TC *+2 6,6757 1 TC *+2 2,4474 1 0,0556 1 0,0001 0 0,0001 0 GOQ TC XCH TS TC ALMCYCLE ALLDC_OC_Q Q Q

; ; ; ; ; ; ; ; ; ;

shifted right 2 dec comp bits in low 3 some ones in low 3 (was TCF in Block I I ) all zeros, all oct, OK so return dec comp = 7 for 3comp, =6 for 2comp must match 6 for 3comp, 5 for 2comp >0 +0 <0 -0, was BZF *+2 in Block II

6,0756 0 6,0757 3 6,0760 5 6,0761 0

; alarm and recycle (does not return) ; restore return address ; all required are dec, OK

;----------------- --------------------------------------------------------; SFRUTNOR ; gets SF routine number for normal case. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 340. ;----------------- --------------------------------------------------------SFRUTNOR 14762 14763 14764 14765 14766 14767 6,0762 6,0763 6,0764 6,0765 6,0766 6,0767 3 5 3 7 0 0 0,0001 0,0411 2,4665 0,0444 2,4640 0,0411 0 0 0 1 1 0 EQU XCH TS CAF MAS K TC TC * Q EXITEM MID5 NNTYPTEM RIGHT5 EXITEM

; can't use L for return. TESTFORDP uses L .

; SF routine number in A

;----------------- --------------------------------------------------------; SFRUTMIX ; gets SF routine number for mixed case. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 340. ;----------------- --------------------------------------------------------SFRUTMIX 14770 14771 14772 14773 14774 14775 14776 14777 15000 15001 6,0770 3 6,0771 5 6,0772 2 6,0773 3 6,0774 5 6,0775 2 6,0776 3 6,0777 7 6,1000 2 6,1001 0 0,0001 0 0,0411 0 0,0414 1 6,7022 0 0,0557 0 0,0414 1 2,4664 1 0,0450 1 0,0557 1 0,0000 1 EQU XCH TS IND EX CAF TS IND EX CAF MAS K IND EX TC * Q EXITEM DECOUNT DISPLACE SFRUTMIX_L DECOUNT LOW5 RUTMXTEM SFRUTMIX_L 0

; gets SF routine number for mixed case

; put TC GOQ, TC RIGHT5, or TC LEFT5 in L

; LOW5, MID5, or HI5 in A ; get HI5, MID5, or LOW5 of RUTMXTAB ent r y

; do TC GOQ (DECOU NT=0), do TC RIGHT5 (DECOUNT=1), do TC LEFT5 (DECOUNT=2) 15002 6,1002 0 0,0411 0 SFRET1 TC EXITEM ; SF routine number in A

SFCONUM 15003 15004 15005 15006 15007 15010 15011 15012 15013 15014 15015 15016 15017 6,1003 6,1004 6,1005 6,1006 6,1007 6,1010 6,1011 6,1012 6,1013 6,1014 6,1015 6,1016 6,1017 3 5 2 0 0 2 3 5 2 3 7 2 0 0,0001 0,0411 0,0435 6,7006 6,7025 0,0414 6,7022 0,0560 0,0414 2,4664 0,0444 0,0560 0,0000 0 0 1 0 1 1 0 1 1 1 1 0 1

EQU XCH TS IND EX TC TC IND EX CAF TS IND EX CAF MAS K IND EX TC

* Q EXITEM MIXBR *+0 CONUMNOR DECOUNT DISPLACE SFCONUM_L DECOUNT LOW5 NNTYPTEM SFCONUM_L 0

; gets 2X (SF constant number)

; normal noun ; mixed noun ; put TC GOQ, TC RIGHT5, or TC LEFT5 in L

; do TC GOQ (DECOU NT=0), do TC RIGHT5 (DECOUNT=1), do TC LEFT5 (DECOUNT=2)

15020 15021

6,1020 6 6,1021 0

0,0000 1 SFRET 0,0411 0

DOU BLE TC

; 2X (SF constant number) in A EXITEM

DISPLACE 15022 15023 15024 6,1022 0 6,1023 0 6,1024 0 6,6761 1 2,4640 1 2,4647 0 CONUMNOR 15025 15026 15027 15030 6,1025 6,1026 6,1027 6,1030 3 7 6 0 2,4664 0,0444 0,0000 0,0411 1 1 1 0 PUTCOM 15031 15032 15033 15034 15035 15036 15037 15040 15041 15042 15043 15044 15045 15046 6,1031 6,1032 6,1033 6,1034 6,1035 6,1036 6,1037 6,1040 6,1041 6,1042 6,1043 6,1044 6,1045 6,1046 5 3 5 3 5 2 3 5 2 3 5 2 0 0 0,0414 0,0001 0,0412 1,2050 0,0136 0,0414 0,0475 0,0131 0,0414 0,0472 0,0130 0,0435 6,7045 6,7077 0 0 0 0 0 1 1 1 1 0 0 1 1 0

EQU TC TC TC EQU CAF MAS K DOU BLE TC EQU TS XCH TS CAF TS IND EX XCH TS IND EX XCH TS IND EX TC TC

* GOQ RIGHT5 LEFT5 * LOW5 NNTYPTEM EXITEM * DECOUNT Q DECRET ZERO MPAC+6 DECOUNT XREGLP MPAC+1 DECOUNT XREG MPAC MIXBR * PUTNORM

; normal noun always gets low 5 of ; NNTYPTAB for SF CONUM ; 2X (SF constant number) in A

; normal noun

; if mixnoun, plac e address for component K into NOUNADD, set EBANK bits. 15047 15050 15051 15052 15053 15054 15055 15056 15057 15060 15061 15062 15063 15064 6,1047 6,1050 6,1051 6,1052 6,1053 6,1054 6,1055 6,1056 6,1057 6,1060 6,1061 6,1062 6,1063 6,1064 2 3 6 7 0 2 6 5 1 0 0 0 0 0 0,0414 1,2050 0,0445 2,4672 2,4616 0,0000 0,0414 0,0442 0,0467 6,7114 6,6444 6,6770 6,6240 6,7111 1 0 1 1 1 1 0 0 0 1 0 1 1 1 IND EX DECOUNT ; CAF ZERO ; AD IDAD1TEM ; MAS K LOW11 ; TC SETNCADR ; EXT END ; SU DECOUNT ; TS NOUNADD CCS DECBRNCH TC PUTDECSF ; TC DCTSTCYC ; TC SFRUTMIX ; TC DPTEST ; TC PUTCOM2 ; ; test for DP scal e for oct load. If so, ; +0 into major pa rt. Set NOUNADD for ; loading octal wo rd into minor part. PUTDPCOM 15065 15066 15067 15070 15071 15072 15073 15074 15075 15076 6,1065 6,1066 6,1067 6,1070 3 6 6 5 1,2050 0,0442 1,2051 0,0442 0 0 1 0 EQU CAF AD AD TS AD TS CAF IND EX TS TC PUTNORM 15077 15100 15101 15102 15103 15104 15105 15106 15107 15110 6,1077 6,1100 6,1101 6,1102 6,1103 6,1104 6,1105 6,1106 6,1107 6,1110 0 1 0 0 0 0 0 3 5 0 2,4625 0,0467 6,7114 6,6444 6,6762 6,6240 6,7111 1,2050 0,0414 6,7065 1 0 1 0 1 1 1 0 0 0 PUTNORM_1 PUTCOM2 15111 15112 15113 6,1111 3 6,1112 0 6,1113 0,0130 0 0,0412 0 16176 0 GTSFINLC EQU TC CCS TC TC TC TC TC CAF TS TC EQU EQU XCH TC DS * ZERO NOUNADD ONE NOUNADD DECOUNT DECOUNT ZERO DECOUNT -1 PUTCOM2 * SETNADD DECBRNCH PUTDECSF DCTSTCYC SFRUTNOR DPTEST PUTNORM_1 ZERO DECOUNT PUTDPCOM * * MPAC DECRET GTSFIN set IDADDTAB entry for component K of noun was CA IDAD1TEM in Block II (ECADR) SUBK for current comp of noun ECADR into NOUNCADR, sets EB, NOUNADD C(NOUNADD) in A upon return place (ESUBK)-K into NOUNADD

+ dec +0 octal test if dec only bit = 1. If so, alarm and recycle. If not, continue. no DP

; was INCR NOUNADD in Block II ; DP (RSUBK)-K+1 or E+1

6,1071 6 6,1072 5 6,1073 6,1074 6,1075 6,1076

0,0414 0 0,0414 0

; (ESUBK)+1 or E+1 into DECOUNT ; was ADS DECOUNT in Block II ; NOUNADD set for minor part ; zero major part (ESUBK or E1)

3 1,2050 0 2 0,0414 1 5 17,7776 0 0 6,7111 1

; ECADR from NOUNCADR, sets EB, NOUNADD ; ; ; ; ; +DEC +0 octal test if dec only bit = 1. If so, alarm and recycle. If not, continue. no DP

; eliminated Block II CHANNEL LOAD code

; *************** missing stuff *****************

; PUTDECSF ; Finds MIXBR and DECOUNT still set from PUTCOM PUTDECSF 15114 15115 15116 15117 15120 15121 15122 15123 15124 15125 15126 15127 15130 15131 15132 15133 15134 15135 15136 15137 15140 15141 15142 15143 15144 15145 6,1114 0 6,1115 5 6,1116 3 6,1117 0 6,1120 6,1121 6,1122 6,1123 6,1124 6,1125 2 0 0 0 0 0 6,7003 0 0,0420 1 6,7113 0 1,3526 0 0,0435 6,7121 6,7125 6,6770 6,7126 6,6762 0,0000 6,7131 1,3712 14340 13011 12727 12776 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 0 1 0 1 EQU TC TS * SFCONUM SFTEMP1

; 2X (SF CON NUM) in A

CAF GTSFINLC TC DXCHJUMP ; loads SFTEMP1, S FTEMP2 IND EX MIXBR TC * TC PUTSFNOR TC SFRUTMIX TC PUTDCSF2 PUTSFNOR TC SFRUTNOR IND EX CAF TC CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R CAD R A SFINTABR BANKJUMP GOALMCYC BINROUND DEGINSF ARTHINSF 0 0 0 0 0 0 0 0 0

; was DCA GTSFINLC, DXCH Z in Block II ; bank jump to SF const table read rtne

6,1126 2 6,1127 3 6,1130 0 6,1131 6,1132 6,1133 6,1134 6,1135 6,1136 6,1137 6,1140 6,1141 6,1142 6,1143 6,1144 6,1145

0 PUTDCSF2 0 0 0 SFINTABR 0 0 1 1 1 1 1 1 1 1 1 1

; ; ; ; ; ; ; ; ; ; ; ; ; ;

switch banks for expansion room 0, alarm and recycle if dec load 1 2 3 4 ********** 5 ********** 6 ********** 7 ********** 8 ********** 9 ********** 10 ********* 11 ********* 12 *********

; BUNCH OF TABLE E NTRIES GO HERE!!!!! ; ************ NEE D TO ADD THE REST *************

BANK41_3

EQU

ORG BANK40_4 ; COLOSSUS pp. 343-346 INC L bank40_4.asm ;================= ========================================================= ; SCALE FACTOR ROU TINES (file:bank40_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 343-346. ;================= ========================================================= DEGINSF 0 0 0 0 0 1 1 1 1 1 DEGINSF2 1 1 1 0 0 0 0 1 SIGNFIX 0 1 1 0 1 1 0 0 0 ENDSCALE 12762 12763 12764 12765 5,0762 0 5,0763 5,0764 4 5,0765 0 1,3653 1 15111 1 1,2106 0 NEG180 5,6761 1 EQU TC ADR ES CCS CAF TC CS AD TC TC TC TC TC CCS TC TC COM TS CCS TC TC CCS TC TC TC XCH MAS K TS EQU TC CAD R CS TC * DMP DEGCON1 MPAC+1 BIT11 *+2 BIT11 MPAC+1 _2ROUND+2 TPSL1 TPSL1 TESTOFUF TPSL1 MPAC SIGNFIX SIGNFIX MPAC MPAC+6 SGNTO1 ENDSCALE MPAC CCSHOLE NEG180 *+1 MPAC POSMAX MPAC * POSTJUMP PUTCOM2 POSMAX ENDSCALE-1

12727 12730 12731 12732 12733 12734 12735 12736 12737 12740 12741 12742 12743 12744 12745 12746 12747 12750 12751 12752 12753 12754 12755 12756 12757 12760 12761

5,0727 5,0730 5,0731 5,0732 5,0733 5,0734 5,0735 5,0736 5,0737 5,0740 5,0741 5,0742 5,0743 5,0744 5,0745 5,0746 5,0747 5,0750 5,0751 5,0752 5,0753 5,0754 5,0755 5,0756 5,0757 5,0760 5,0761

0 1 3 0 4 6 0 0 0 0 0 1 0 0 4 5 1 0 0 1 0 0 0 3 7 5

2,4374 06772 0,0131 1,2066 5,6735 1,2066 0,0131 5,7016 2,4721 2,4721 5,7025 2,4721 0,0130 5,6750 5,6750 0,0000 0,0130 0,0136 5,6766 5,6762 0,0130 5,6271 5,6764 5,6757 0,0130 1,2106 0,0130

; ; ; ; ;

SF routine for dec degrees mult by 5.5 5(10)X2EXP-3 this rounds off MPAC+1 before shift left 3, and causes 360.00 to OF/UF when shifted left and alarm

; left 1 ; left 2 ; returns if no OF/UF (left 3) ; ; ; ; if if if -f +, go to SIGNFIX +0, go to SIGNFIX -, use -MAGNITUDE + 1 -0; use +0

; if overflow ; no overflow/underflow ; if UF, force sign to 0 except -180

SGNTO1 12766 12767 12770 12771 12772 12773 12774 12775 5,0766 5,0767 5,0770 5,0771 5,0772 5,0773 5,0774 5,0775 4 7 4 0 0,0130 1,2106 0,0000 5,6761 1 0 0 1

EQU CS MAS K CS TC DS DS DS DS

* MPAC POSMAX A ENDSCALE-1 %26161 %30707 %21616 %07071

; if OV force sign to 1

26161 0 DEGCON1 30707 1 21616 0 DEGCON2 07071 0

; ************ mis sing stuff *************** ARTHINSF 12776 12777 13000 13001 13002 13003 13004 13005 13006 13007 13010 5,0776 5,0777 5,1000 5,1001 5,1002 5,1003 5,1004 5,1005 5,1006 5,1007 0 3 3 3 1 0 0 0 0 2,4374 00420 0,0132 0,0131 0,0130 0,0000 5,7010 5,7007 5,7010 5,7011 0 1 1 1 0 0 1 1 1 0 EQU TC ADR ES XCH XCH XCH CCS TC TC TC TC TC BINROUND 13011 13012 13013 5,1011 0 5,1012 0 5,1013 0 5,7014 0 5,7025 1 5,6762 1 EQU TC TC TC * DMP SFTEMP1 MPAC+2 MPAC+1 MPAC A *+4 *+2 *+2 BINROUND ALMCYCLE * _2ROUND TESTOFUF ENDSCALE

; ; ; ;

scales MPAC, +1 by SFTEMP1, SFTEMP2 assumes point between HI and LO parts of SFCON, shifts results left by 14. (by taking results from MPAC+1, MPAC+2 )

; ; ; ; ;

was BZF BINROUND in Block II >0 +0 <0 -0

5,1010 0

2,4474 1

; too large a load, alarm and recycle

; ************ mis sing stuff *************** _2ROUND 1 1 1 0 0 0 0 0 0 _2RNDEND TESTOFUF 13025 13026 13027 13030 5,1025 5,1026 5,1027 5,1030 1 0 0 0 0,0136 2,4474 0,0001 2,4474 1 1 0 1 BANK40_5 EQU XCH DOU BLE TS TC AD TS TC TS TC EQU CCS TC TC TC EQU ORG EQU * MPAC+1 MPAC+1 Q MPAC MPAC Q MPAC+6 Q * MPAC+6 ALMCYCLE Q ALMCYCLE * BANK42_2 *

13014 13015 13016 13017 13020 13021 13022 13023 13024

5,1014 5,1015 5,1016 5,1017 5,1020 5,1021 5,1022 5,1023 5,1024

3 6 5 0 6 5 0 5 0

0,0131 0,0000 0,0131 0,0001 0,0130 0,0130 0,0001 0,0136 0,0001

; if MPAC+1 does not OF/UF

; if MPAC does not OF/UF

; returns if no OF/UF ; OF, alarm and recycle ; UF, alarm and recycle

BANK42_3

ORG BANK41_3 INC L bank41_3.asm ; COLOSSUS pp. 349-351 ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_3.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 349-351. ;================= ========================================================= ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; MONITOR allows o ther keyboard activity. It is ended by verb TERMINATE verb PROCEED WIT HOUT DATA, verb RESEQUENCE, another monitor, or any NVSUB call that passes DSPLOCK (provided that the operator has somehow allowed the endi ng of a monitor which he has initiated through the keyboard. MONITOR action i s suspended, but not ended, by any keyboard action, except error lig ht reset. It begins again when KEY RELEASE is performed. MONITOR saves th e noun and appropriate display verb in MONSAVE. It saves NOUNCADR in MONS AVE1, if noun = machine CADR to be specified. Bit 15 of MONSAVE1 is the kill monitor signal (killer bit). Bit 14 of MONSAVE1 indicates the cu rrent monitor was externally initiated (external monitor bit). It is turn ed off by RELDSP and KILMONON. MONSAVE indicate s if MONITOR is on (+=ON, +0=OFF) If MONSAVE is +, monitor enters no request, but turns killer bit off. If MONSAVE is +0 , monitor enters request and turns killer bit off. NVSUB (if extern al monitor bit is off), VB=PROCEED WITHOUT DATA,

; ; ; ; ; ;

VB=RESEQUENCE, a nd VB=TERMINATE turn kill monitor bit on. If killer bit is on, MONREQ enters no further requests, zeroes MONSAVE and MONSAVE1 (tu rning off killer bit and external monitor bit). MONITOR doesn't test for MATBS since NVSUB can handle internal MATBS now.

MONITOR 15146 15147 6,1146 4 6,1147 7 6,7155 0 0,0506 0 MONIT1 15150 15151 15152 15153 15154 15155 15156 15157 15160 15161 15162 15163 6,1150 5 6,1151 6,1152 6,1153 6,1154 4 6 1 0 0,0131 1 0,0433 2,4553 0,0000 6,7164 1 0 0 0

EQU CS MAS K EQU TS CS AD CCS TC DS TC CAF AD TS CAF TS

* BIT15_14 NOUNCADR * MPAC+1 ENTEXIT ENDINST A MONIT2 %60000 MONIT2 BIT14 MPAC+1 MPAC+1 ZERO MONSAVE2 * LOW7 VERBREG LEFT5 CYL CYL CYL NOUNREG MPAC ZERO DSPLOCK CADRSTOR *+2 RELDSP1 MONSAVE *+4 ONE WAITLIST MONREQ MPAC+1 MONSAVE+1 MPAC MONSAVE ; externally initiated monitor ; was ADS MPAC+1 in Block II ; set bit 14 for MONSAVE1

; temp storage

6,1155 6,1156 0 6,1157 3 6,1160 6 6,1161 5 6,1162 3 6,1163 5

60000 1 BIT15_14 6,7164 0 1,2063 0 0,0131 1 0,0131 1 1,2050 0 0,0511 1 MONIT2

; zero NVMONOPT options

15164 15165 15166 15167 15170 15171 15172 15173 15174 15175 15176 15177 15200 15201 15202 15203 15204 15205 15206 15207 15210 15211 15212

6,1164 6,1165 6,1166 6,1167 6,1170 6,1171 6,1172 6,1173 6,1174 6,1175 6,1176 6,1177 6,1200 6,1201 6,1202 6,1203

3 7 0 5 4 3 6 5 3 5 1 0 0 2 1 0

1,2101 0,0470 2,4647 0,0022 0,0022 0,0022 0,0471 0,0130 1,2050 0,0501 0,0531 6,7201 2,5026 0,0000 0,0507 6,7207

0 0 0 1 0 1 0 0 0 0 1 0 0 0 1 0

EQU CAF MAS K TC TS CS XCH AD TS CAF TS CCS TC TC INH INT CCS TC CAF TC CAD R XCH XCH XCH XCH

; temp storage ; ; ; ; +0 into DSPLOCK so monitor can run turn off KR lite if CADRSTOR and DSPLI S T are both empty. (Lite comes on if new monitor is keyed in over old monitor.)

; if MONSAVE was +, no request ; if MONSAVE was 0, request MONREQ

6,1204 3 6,1205 0 6,1206 6,1207 3 6,1210 3 6,1211 3 6,1212 3

1,2051 1 1,2232 0 15215 0 0,0131 1 0,0510 0 0,0130 0 0,0507 0

; was DXCH MPAC, DXCH MONSAVE

; place monitor verb and noun into MONSA V E ; zero the kill monitor bit

15213 15214

6,1213 2 6,1214 0

0,0000 1 0,0433 0 MONREQ

REL INT TC EQU TC CCS TC TC TC TC CAF TC CAD R CAF TC CAD R TC KILLMON EQU CAF TS TS TC DS

; set up external monitor bit ENTRET * LODSAMPT MONSAVE1 *+4 *+3 KILLMON KILLMON MONDEL WAITLIST MONREQ CHRPRIO NOVAC MONDO TASKOVER * ZERO MONSAVE MONSAVE1 TASKOVER %144

15215 15216 15217 15220 15221 15222 15223 15224 15225 15226 15227 15230 15231

6,1215 6,1216 6,1217 6,1220 6,1221 6,1222

0 1 0 0 0 0

6,7300 0,0510 6,7223 6,7223 6,7232 6,7232

0 1 0 0 0 0

; ; ; ; ; ;

called by waitlist (see COLOSSUS p. 37 4 ) time is snatched in RUPT for NOUN 65 if killer bit = 0, enter requests if killer bit = 0, enter requests if killer bit = 1, no requests if killer bit = 1, no requests

6,1223 3 6,1224 0 6,1225 6,1226 3 6,1227 0 6,1230 6,1231 0

6,7236 1 1,2232 0 15215 0 2,4131 0 1,3162 1 15237 0 1,2413 0

; enter waitlist request for MONREQ

; enter EXEC request for MONDO

15232 15233 15234 15235 15236

6,1232 6,1233 6,1234 6,1235 6,1236

3 5 5 0

1,2050 0,0507 0,0510 1,2413

0 0 0 0

; zero MONSAVE and turn killer bit off ; turn off kill monitor bit ; turn off external monitor bit ; for 1 sec monitor intervals

00144 0 MONDEL

MONDO 15237 15240 15241 15242 15243 15244 15245 15246 15247 15250 15251 15252 15253 15254 15255 15256 15257 15260 15261 15262 15263 15264 15265 15266 15267 15270 15271 15272 15273 6,1237 6,1240 6,1241 6,1242 6,1243 6,1244 6,1245 6,1246 6,1247 6,1250 6,1251 6,1252 6,1253 6,1254 6,1255 6,1256 6,1257 6,1260 6,1261 6,1262 6,1263 6,1264 6,1265 6,1266 6,1267 6,1270 6,1271 6,1272 6,1273 1 0 0 0 0 1 0 3 7 0 3 7 6 5 4 4 4 4 4 4 3 7 5 3 5 4 7 5 0 0,0510 6,7244 6,7244 1,2723 1,2723 0,0501 6,7276 1,2101 0,0507 6,6306 2,4473 0,0507 6,7274 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 1,2101 0,0470 6,7275 0,0433 6,7155 0,0510 0,0132 6,6054 1 1 1 0 0 1 0 0 1 1 0 1 1 0 1 1 1 1 1 1 0 1 1 0 0 0 1 1 0 ENDMONDO

EQU CCS TC TC TC TC CCS TC CAF MAS K TC CAF MAS K AD TS CS CS CS CS CS CS XCH MAS K TS CAF TS CS MAS K TS TC

* MONSAVE1 *+4 *+3 ENDOFJOB ENDOFJOB DSPLOCK MONBUSY LOW7 MONSAVE UPDATNN-1 MID7 MONSAVE MONREF CYR CYR CYR CYR CYR CYR CYR CYR LOW7 VERBREG MONBACK ENTRET BIT15_14 MONSAVE1 MPAC+2 TESTNN

; ; ; ; ;

called by EXEC if killer bit = 0, continue if killer bit = 0, continue in case TERMINATE came since last MONR E Q in case TERMINATE came since last MONR E Q

; NVSUB is busy

; place noun into NOUNREG and display it ; change monitor verb to display verb ; -DEC10, starting in bit5 ; shift right 7, was TS EDOP, CA EDOP in B I I

; set return to PASTEVB after data displ a y

; display it and set NOUNCADR, NOUNADD, ; EBANK

; COLOSSUS switche s to fixed/fixed memory and inserts PASTEVB here-; Probably, becaus e their assembler couldn't handle forward references. 15274 15275 15276 15277 6,1274 6,1275 6,1276 0 6,1277 0 75377 0 MONREF 04435 1 MONBACK 2,4713 0 MONBUSY 1,2723 0 DS CAD R TC TC TC EQU %75377 PASTEVB RELDSPON ENDOFJOB Q * ; -dec10, starting in bit8

; turn key release light

15300 6 , 1 3 0 0 0 0,0001 0 LODSAMPT * * * * * * * * * * * * * *************** BANK41_4

; ************************** FIX

ORG BANKFF_1 INC L bankff_1.asm ; COLOSSUS pp. 351 ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 351. ;================= ========================================================= PASTEVB 04435 04436 04437 04440 04441 04442 04443 04444 04445 04446 04447 04450 4435 3 4436 7 4437 5 4440 4441 4442 4443 4444 1 0 0 0 0 2,4473 0 0,0511 0 0,0571 1 0,0000 2,4443 2,4444 2,4445 2,4447 0 0 1 0 1 EQU CAF MAS K TS CCS TC TC TC TC XCH TC CAF AD PASTEOPT 04451 04452 04453 04454 04455 04456 04457 04460 04461 04462 04463 4451 4452 4453 4454 4455 4456 4457 4460 4461 5 4 4 4 4 4 4 3 7 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 1,2101 0 1 1 1 1 1 1 0 1 EQU TS CS CS CS CS CS CS XCH MAS K TC CAD R * MID7 MONSAVE2 PASTE_TMP A *+2 *+2 *+2 *+3 PASTE_TMP PASTEOPT ZERO MONSAVE * CYR CYR CYR CYR CYR CYR CYR CYR LOW7 BANKCALL UPDATVB-1

; NVMONOPT paste option

; ; ; ; ;

was BZF *+2 in Block II >0, +0, <0, -0,

4445 3 4446 0 4447 3 4450 6

0,0571 1 2,4451 0 1,2050 0 0,0507 0

; paste please verb for NVMONOPT ; was CA MONSAVE in BII ; paste monitor verb - paste option is 0

; shift right 7, was TS EDOP, CA EDOP in B I I

; place monitor verb or please verb into ; VERBREG and display it.

4462 0 4463

1,3565 1 14326 0

04464 04465 04466 04467 04470 368) 04471 04472 04473

4464 3 4465 5 4466 3 4467 6 4470 0 4471 0 4472 0 4473

1,2050 0 0,0502 0 1,2050 0 0,0511 1 2,4565 0 2,4472 1 1,2723 0 ENDPASTE 37600 0 MID7 BANKFF_2

CAF TS CAF AD TC TC TC DS EQU

ZERO REQRET ZERO MONSAVE2 BLANKSUB *+1 ENDOFJOB %37600 *

; zero REQRET so that pasted verbs can ; be executed by operator.

; was CA MONSAVE2 in BII ; process NVMONOPT blank option if any ( p .

ORG BANK41_4 INC L bank41_4.asm ; COLOSSUS pp. 352 ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 352. ;================= ========================================================= ;----------------- --------------------------------------------------------; DSPFMEM -- DISPL AY FIXED MEMORY ; Used to display (in octal) any fixed register. It is used with NOUN = ; machine CADR to be specified. The FCADR of the desired location is then ; punched in. It h andles F/F (FCADR 4000-7777) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 352. ;----------------- --------------------------------------------------------DSPFMEM 15301 15302 15303 15304 15305 15306 15307 6,1301 3 6,1302 5 6,1303 3 6,1304 6 6,1305 0 6,1306 0 6,1307 0 2,4635 0 0,0466 0 1,2050 0 0,0506 1 1,3742 0 6,7310 1 1,2723 0 ENDSPF BANK41_5 EQU CAF TS CAF AD TC TC TC EQU * R1D1 DSPCOUNT ZERO NOUNCADR DATACALL DSPOCTWD ENDOFJOB *

; If F/F, DATACALL uses bank 02 or 03

; was CA NOUNCADR, TC SUPDACAL in Block I I ; original FCADR loaded still in NOUNCAD R ; call with FCADR in A

ORG BANK40_5 ; COLOSSUS pp. 353-355 INC L bank40_5.asm ;================= ========================================================= ; WORD DISPLAY ROU TINES (file:bank40_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 353-355. ;================= ========================================================= DSPSIGN 13031 13032 13033 13034 13035 13036 13037 13040 13041 13042 13043 13044 13045 5,1031 3 5,1032 5 5,1033 1 5,1034 0 5,1035 0 5,1036 5,1037 5,1040 5,1041 5,1042 5,1043 6 5 0 4 5 0 0,0001 0 0,0441 0 0,0130 1 5,7044 0 5,7044 0 1,2051 0,0130 5,6353 0,0131 0,0131 0,0441 1 0 1 0 1 0 EQU XCH TS CCS TC TC AD TS TC CS TS TC TC TC * Q DSPWDRET MPAC *+8 *+7 ONE MPAC M_ON MPAC+1 MPAC+1 DSPWDRET P_ON DSPWDRET

; >0, positive sign ; +0, positive sign

; display minus sign

5,1044 0 5,1045 0

5,6332 0 0,0441 0

; display plus sign ; return

;----------------- --------------------------------------------------------; DSPRND ; Round up decimal fraction by 5 EXP -6. This was entirely coded in ; Block II instruc tions, so I translated it to the functional ; equivalent in Bl ock I code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 353. ;----------------- --------------------------------------------------------DSPRND 13046 13047 5,1046 3 5,1047 6 5,7117 1 0,0131 1 EQU CAF AD * DECROUND MPAC+1

13050 13051 13052 13053 13054 13055 13056 13057 13060 13061

5,1050 5,1051 5,1052 5,1053 5,1054 5,1055 5,1056 5,1057 5,1060 5,1061

5 3 6 5 0 3 5 3 5 0

0,0131 1,2050 0,0130 0,0130 0,0001 5,7063 0,0131 5,7062 0,0130 0,0001

1 0 0 0 0 0 1 1 0 0 DPOSMAX

TS CAF AD TS TC CAF TS CAF TS TC EQU DS DS

MPAC+1 ZERO MPAC MPAC Q DPOSMAX+1 MPAC+1 DPOSMAX MPAC Q * %37777 %34000

; skip on overflow ; otherwise, make interword carry=0 ; skip on overflow ; return ; number overflows, so set to max

; return ; max positive decimal fraction

13062 13063

5,1062 5,1063

37777 1 34000 0

;----------------- --------------------------------------------------------; DSPDECTWD -- DIS PLAY DECIMAL WORD ; Converts C(MPAC, MPAC+1) into a sign and 5 char decimal starting in loc ; specified in DSP COUNT. it rounds by 5 exp 6. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 353. ;----------------- --------------------------------------------------------DSPDECWD 13064 13065 13066 13067 13070 5,1064 3 5,1065 5 5,1066 0 5,1067 0 5,1070 3 0,0001 0 0,0412 0 5,7031 1 5,7046 1 1,2054 1 DSPDCWD1 13071 13072 13073 5,1071 5 5,1072 3 5,1073 0 0,0434 1 2,4700 1 2,4353 0 TRACE1 13074 13075 13076 13077 13100 13101 13102 13103 13104 5,1074 5,1075 5,1076 5,1077 5,1100 5,1101 5,1102 5,1103 5,1104 2 3 7 5 3 3 3 5 3 0,0130 1,3772 2,4664 0,0421 1,2050 0,0132 0,0131 0,0130 0,0466 1 0 0 0 0 1 1 0 0 TRACE1S 13105 13106 13107 13110 13111 13112 13113 13114 13115 13116 13117 5,1105 5,1106 5,1107 5,1110 5,1111 5,1112 5 1 5 0 1 0 0,0440 0,0000 0,0466 5,7161 0,0434 5,7071 1 0 0 0 0 0 EQU XCH TS TC TC CAF EQU TS CAF TC EQU IND EX CAF MAS K TS CAF XCH XCH TS XCH EQU TS CCS TS TC CCS TC CS TS TC DS DS * Q WDRET DSPSIGN DSPRND FOUR * WDCNT BINCON SHORTMP * MPAC RELTAB LOW5 CODE ZERO MPAC+2 MPAC+1 MPAC DSPCOUNT * COUNT A DSPCOUNT DSPIN WDCNT DSPDCWD1 VD1 DSPCOUNT WDRET %00000 %02476

; decrement DSPCOUNT except at +0

; >0, not done yet ; +0 ; return

5,1113 4 5,1114 5 5,1115 0 5,1116 5,1117

2,4675 0 0,0466 0 0,0412 0 00000 1 02476 0 DECROUND

;----------------- --------------------------------------------------------; DSPDECNR ; Converts C(MPAC, MPAC+1) into a sign and 5 char decimal starting in loc ; specified in DSP COUNT. It does not round. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 354. ;----------------- --------------------------------------------------------DSPDECNR 13120 13121 13122 13123 5,1120 5,1121 5,1122 5,1123 3 5 0 0 0,0001 0,0412 5,7031 5,7070 0 0 1 1 EQU XCH TS TC TC * Q WDRET DSPSIGN DSPDCWD1-1

;----------------- --------------------------------------------------------; DSPDC2NR ; Converts C(MPAC, MPAC+1) into a sign and 2 char decimal starting in loc ; specified by DSP COUNT. It does not round. ;

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 354. ;----------------- --------------------------------------------------------DSPDC2NR 13124 13125 13126 13127 13130 5,1124 5,1125 5,1126 5,1127 5,1130 3 5 0 3 0 0,0001 0,0412 5,7031 1,2051 5,7071 0 0 1 1 0 EQU XCH TS TC CAF TC * Q WDRET DSPSIGN ONE DSPDCWD1

;----------------- --------------------------------------------------------; DSP2DEC ; Converts C(MPAC) and C(MPAC+1) into a sign and 10 char decimal starting ; in the loc speci fied in DSPCOUNT. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 354. ;----------------- --------------------------------------------------------DSP2DEC 0 0 0 0 0 1 1 1 1 0 0 END2DEC EQU XCH TS CAF TS CAF TC CAF TC TC CAF TC * Q WDRET ZERO CODE THREE _11DSPIN FOUR _11DSPIN DSPSIGN R2D1 DSPDCWD1

13131 13132 13133 13134 13135 13136 13137 13140 13141 13142 13143

5,1131 5,1132 5,1133 5,1134 5,1135 5,1136 5,1137 5,1140 5,1141 5,1142 5,1143

3 5 3 5 3 0 3 0 0 3 0

0,0001 0,0412 1,2050 0,0421 1,2053 5,7253 1,2054 5,7253 5,7031 2,4636 5,7071

; -R2 off ; +R2 off

;----------------- --------------------------------------------------------; DSPDECVN ; Displays C(A) up on entry as a 2 char decimal beginning in the ; loc specified in DSPCOUNT. ; C(A) should be i n form N x 2EXP-14. This is scaled to form N/100 before ; display conversi on. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 353. ;----------------- --------------------------------------------------------DSPDECVN 13144 13145 13146 13147 13150 13151 13152 13153 13154 13155 5,1144 2 5,1145 4 5,1146 3 5,1147 5 5,1150 5,1151 5,1152 5,1153 5,1154 5,1155 3 5 3 5 0 0,0000 1 5,7155 0 0,0003 1 0,0130 0 1,2050 0,0131 0,0001 0,0412 5,7127 0 1 0 0 1 EQU EXT END MP XCH TS CAF TS XCH TS TC DS EQU TC TC DS EQU * VNDSPCON LP MPAC ZERO MPAC+1 Q WDRET DSPDC2NR+3 %00244 * DSPDECVN POSTJUMP UPDAT1+2 * ; mult by .01 ; was LXCH MPAC in Block II ; take results from LP (mult by 2EXP14)

; no sign, no round, 2 char ; .01 rounded up

00244 0 VNDSPCON GOVNUPDT

13156 13157 13160

5,1156 0 5,1157 0 5,1160

5,7144 1 1,3653 1 14337 0 BANK40_6

; this is not for general use. Really pa r t ; of UPDATVB

ORG BANK41_5 ; COLOSSUS pp. 355-356 INC L bank41_5.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 355-356. ;================= ========================================================= ;----------------- --------------------------------------------------------; DSPOCTWD -- DISP LAY OCTAL WORD ; Displays C(A) up on entry as a 5 char octal starting in the DSP char ; specified in DSP COUNT. It stops after 5 char have been displayed. ; ; ; DSP2BIT -- DISPL AY 2 OCTAL CHARS ; Displays C(A) up on entry as a 2 char oct beginning in the DSP ; loc specified in DSPCOUNT by pre-cycling right C(A) and using ; the logic of the 5 char octal display. ;

; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 355/356. ;----------------- --------------------------------------------------------DSPOCTWD 15310 15311 15312 15313 15314 15315 15316 6,1310 5 6,1311 3 6,1312 5 6,1313 3 6,1314 6 6,1315 5 6,1316 3 0,0022 1 0,0001 0 0,0412 0 1,2063 0 0,0466 0 0,0466 0 1,2054 1 WDAGAIN 15317 15320 15321 15322 15323 15324 15325 15326 15327 15330 15331 15332 15333 15334 15335 15336 6,1317 6,1320 6,1321 6,1322 6,1323 6,1324 6,1325 6,1326 6,1327 6,1330 6,1331 6,1332 6,1333 6,1334 6,1335 6,1336 5 4 4 4 4 7 2 3 7 5 3 5 1 5 0 0,0434 0,0022 0,0022 0,0022 0,0000 1,2057 0,0000 1,3772 2,4664 0,0421 0,0466 0,0440 0,0000 0,0466 1,3653 13261 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 OCTBACK 15337 15340 6,1337 1 6,1340 0 0,0434 0 6,7317 0 DSPLW 15341 15342 15343 6,1341 4 6,1342 5 6,1343 0 2,4675 0 0,0466 0 0,0412 0 DSPMSK DSP2BIT 15344 15345 15346 15347 15350 15351 15352 15353 15354 15355 6,1344 6,1345 6,1346 6,1347 6,1350 6,1351 6,1352 6,1353 6,1354 6,1355 5 3 5 3 5 4 4 3 5 0 0,0020 0,0001 0,0412 1,2051 0,0434 0,0020 0,0020 0,0020 0,0022 6,7324 0 0 0 1 1 1 1 0 1 0 EQU TS XCH TS CAF AD TS CAF EQU TS CS CS CS CS MAS K IND EX CAF MAS K TS XCH TS CCS TS TC DS EQU CCS TC EQU CS TS TC EQU EQU TS XCH TS CAF TS CS CS XCH TS TC * CYL Q WDRET BIT14 DSPCOUNT DSPCOUNT FOUR * WDCNT CYL CYL CYL A DSPMSK A RELTAB LOW5 CODE DSPCOUNT COUNT A DSPCOUNT POSTJUMP DSPOCTIN * WDCNT WDAGAIN * VD1 DSPCOUNT WDRET SEVEN * CYR Q WDRET ONE WDCNT CYR CYR CYR CYL WDAGAIN+5

; must use the same return as DSP2BIT ; to blank signs ; was ADS DSPCOUNT in block II

; decrement DSPCOUNT except at +0 ; > 0 ; + 0

; to block numerical characters, clears ; * return

BANK41_6

EQU

ORG BANK40_6 ; COLOSSUS pp. 356-358 INC L bank40_6.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank40_6.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 356-358. ;================= ========================================================= ;----------------- --------------------------------------------------------; DSPIN -- DISPLAY RELAY CODE ; ; For DSPIN, place 0-25 oct into COUNT to select the character (same as DSPCOUN T ) , ; 5 bit relay code into CODE. Both are destroyed. If bit 14 of COUNT is 1, sign i s ; blanked with lef t char. ; For DSPIN11, pla ce 0,1 into CODE, 2 into COUNT, rel address of DSPTAB entry ; into DSREL. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 356. ;----------------- --------------------------------------------------------DSPIN 13161 13162 5,1161 3 5,1162 5 0,0001 0 0,0411 0 EQU XCH TS * Q DSEXIT

; cant use L for RETURN, since many of t h e ; routines calling DSPIN use L as RETURN

; Set DSREL to ind ex into DSPTAB; the index corresponds to the display characte r ; referenced by CO UNT (which is derived from DSPCOUNT) 13163 13164 13165 13166 13167 5,1163 5,1164 5,1165 5,1166 5,1167 3 7 5 3 5 2,4664 0,0440 0,0021 0,0021 0,0436 1 0 1 1 0 CAF MAS K TS XCH TS LOW5 COUNT SR SR DSREL

; divides by 2

; Check COUNT (der ived from DSPCOUNT) to find whether the character to be ; displayed is in the right (Bits 5-1) or left (Bits 10-6) bits of the ; DSPTAB word. 13170 13171 13172 13173 13174 5,1170 5,1171 5,1172 5,1173 5,1174 3 7 1 0 0 1,2100 0,0440 0,0000 5,7175 5,7205 1 0 0 0 1 CAF MAS K CCS TC TC BIT1 COUNT A *+2 DSPIN1-1

; >0, left if COUNT is odd ; +0, right if COUNT is even

; Character to be displayed should be in the left bits (Bit 10-6), so ; shift it left in to bits 10-6. 13175 13176 13177 5,1175 3 5,1176 0 5,1177 5 0,0421 0 2,4656 0 0,0421 0 ; ; ; ; ; 13200 13201 13202 13203 13204 13205 5,1200 5,1201 5,1202 5,1203 5,1204 3 7 1 3 6 1,2063 0,0440 0,0000 1,2052 1,2051 0 0 0 1 1 XCH TC TS CODE SLEFT5 CODE

; does not use CYL

Set COUNT as an enumerated type; tells how to mask the new character into the relay w ord. 0 = mask new cha racter into right side of relayword (bits 5-1) 1 = mask into le ft side (bits 10-6) and leave old sign (bit 11) alone. 2 = mask into le ft side (bits 10-6) and blank sign bit (bit 11) CAF MAS K CCS CAF AD TS BIT14 COUNT A TWO ONE COUNT

; >0, BIT14 = 1, blank sign ; +0, BIT14 = 0, leave sign alone

5,1205 5

0,0440 1

; New display char acter in CODE has been bit-shifted into the correct (left ; or right) bit po sition. All other bits are zeroed. DSPIN1 13206 5,1206 2 0,0000 0 ; ; ; ; 13207 13210 13211 13212 13213 13214 5,1207 5,1210 5,1211 5,1212 5,1213 2 1 0 0 6 0,0436 0,0512 5,7213 5,7245 1,2051 1 0 0 0 1 EQU INH INT *

Get the existing display word from DSPTAB. Words that have already been displayed will b e positive; words yet to be displayed will be negative. Use CCS to load the absolute value of the display word. Since CCS decrements it, we need to a dd 1 to restore the value. IND EX CCS TC TC AD TS DSREL DSPTAB *+2 DSLV ONE DSMAG

; >0, old word already displayed ; +0, illegal DSPCOUNT (was TC CCSHOLE) ; <0, old word not displayed yet ; store the old relay word

5,1214 5

0,0437 1

; Now, mask off th e portion of the old relay word corresponding to the ; new character. S ubtract the new character from the old to see whether ; they are the sam e. 13215 13216 13217 13220 5,1215 5,1216 5,1217 5,1220 2 7 2 6 0,0440 5,7247 0,0000 0,0421 0 0 1 0 IND EX MAS K EXT END SU COUNT DSMSK CODE

; mask with 00037, 01740, 02000, or 0374 0

; Old code same as new code? If so, we don't need to redisplay it. 13221 13222 13223 13224 13225 5,1221 5,1222 5,1223 5,1224 5,1225 1 0 0 0 0 0,0000 5,7226 5,7245 5,7226 5,7245 0 0 0 0 0 CCS TC TC TC TC ; New code is diff erent. DFRNT 13226 13227 13230 13231 5,1226 5,1227 5,1230 5,1231 2 4 7 6 0,0440 5,7247 0,0437 0,0421 0 0 0 0 EQU IND EX CS MAS K AD * COUNT DSMSK DSMAG CODE ; different ; mask with 77740, 76037, 75777, or 7403 7 A DFRNT DSLV DFRNT DSLV ; ; ; ; ; was BZF DSLV in Block II >0 +0, same, so return <0 -0, same, so return

; Store new DSPTAB word and get the old (previous) word. If the old word is ; negative, it had not been displayed yet, so NOUT (the count of undisplayed

; words) has alrea dy been incremented for this DSPTAB word. If the old word ; is positive, it has already been displayed, so we need to increment NOUT ; to tell DSPOUT t o display the new word. 13232 13233 13234 13235 13236 13237 13240 13241 13242 II) 13243 13244 13245 13246 5,1232 4 5,1233 2 5,1234 3 5,1235 5,1236 5,1237 5,1240 5,1241 1 0 0 0 0 0,0000 0 0,0436 1 0,0512 1 0,0000 5,7242 5,7241 5,7241 5,7245 0 1 1 1 0 CS IND EX XCH CCS TC TC TC TC XCH AD TS REL INT TC A DSREL DSPTAB A *+4 *+2 *+1 DSLV NOUT ONE NOUT ; ; ; ; ; was >0 +0, <0, -0, BZMF DSLV in Block II DSPTAB entry was DSPTAB entry was DSPTAB entry was -

5,1242 3 5,1243 6 5,1244 5 5,1245 2 5,1246 0

0,0505 1 1,2051 1 0,0505 1 0,0000 1 DSLV 0,0411 0

; DSPTAB entry was + (was INCR NOUT in B l o c k

DSEXIT

; return

DSMSK 13247 13250 13251 13252 5,1247 5,1250 5,1251 5,1252 00037 01740 02000 03740 0 0 0 1

EQU DS DS DS DS

* %00037 %01740 %02000 %03740

; ; ; ;

COUNT=0 COUNT=1 COUNT=2 COUNT=3

; For 11DSPIN, put rel address of DSPTAB entry into A, 1 in BIT11 or 0 in ; BIT11 of CODE. I changed the name to _11DSPIN because my assembler doesn't ; like labels that start with a digit. _11DSPIN 13253 13254 13255 13256 13257 13260 5,1253 5,1254 5,1255 5,1256 5,1257 5,1260 5 3 5 3 5 0 0,0436 1,2052 0,0440 0,0001 0,0411 5,7206 0 1 1 0 0 1 DSPOCTIN 0 0 0 1 ENDSPOCT EQU TS CAF TS XCH TS TC EQU TC CAF TC DS * DSREL TWO COUNT Q DSEXIT DSPIN1 * DSPIN *+2 BANKJUMP OCTBACK

; must use same return as DSPIN

13261 13262 13263 13264

5,1261 0 5,1262 3 5,1263 0 5,1264

5,7161 5,7264 1,3712 15337

; so DSPOCTWD doesn't use SWCALL

; ; ; ;

DSPALARM finds T C NVSUBEND in ENTRET for NVSUB initiated routines. Abort with 01501 . DSPALARM finds T C ENDOFJOB in ENTRET for keyboard initiated routines. do TC ENTRET. EQU CS TS EQU CS AD CCS TC TC TC TC CS AD CCS TC TC TC TC TC TC * VD1 DSPCOUNT * NVSBENDL ENTEXIT A *+4 *+2 *+2 CHARALRM+2 MONADR ENTEXIT A *+4 *+2 *+2 *+2 *+2 KILMONON * FALTON ENDOFJOB POODOO %01501 PASTEVB NVSUBEND ; ; ; ; ; was BZF CHARALRM+2 in Block II >0 +0 <0 -0

PREDSPAL 13265 13266 5,1265 4 5,1266 5 2,4675 0 0,0466 0 DSPALARM 13267 13270 13271 13272 13273 13274 13275 13276 13277 13300 13301 13302 13303 13304 13305 13306 5,1267 4 5,1270 6 5,1271 5,1272 5,1273 5,1274 5,1275 1 0 0 0 0 5,7314 1 0,0433 0 0,0000 5,7276 5,7275 5,7276 5,7311 0 0 0 0 0

5,1276 4 5,1277 6 5,1300 5,1301 5,1302 5,1303 5,1304 1 0 0 0 0

5,7313 0 0,0433 0 0,0000 5,7305 5,7304 5,7305 5,7306 0 0 1 0 0

; if this is a monitor, kill it

; ; ; ; ;

was BZF *+2 in Block II >0 +0 <0 -0

5,1305 0 5,1306 0

5,7307 1 2,4536 0 CHARALRM

13307 13310 13311 13312 13313 13314

5,1307 0 5,1310 0 5,1311 0 5,1312 5,1313 5,1314 0

2,4701 0 1,2723 0 2,5050 01501 04435 2,4532 1 1 1 MONADR 1 NVSBENDL

EQU TC TC TC DS DS TC

; not NVSUB initiated, turn on OPR error

BANK40_7

EQU

ORG BANKFF_2 ; COLOSSUS pp. 358 INC L bankff_2.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_2.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 358. ;================= ========================================================= ;----------------- --------------------------------------------------------; ALMCYCLE ; Turns on check f ail light, redisplays the original verb that was executed, ; and recycles to execute the original verb/noun combination that was last ; executed. Used f or bad data during load verbs and by MCTBS. Also by MMCHANG ; if 2 numerical c hars were not punched in for MM code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 358. ;----------------- --------------------------------------------------------ALMCYCLE 0 0 0 1 0 1 0 ENDALM BANKFF_3 EQU TC CS TS TC DS TC DS EQU * FALTON VERBSAVE REQRET BANKCALL UPDATVB-1 POSTJUMP ENTER *

04474 04475 04476 04477 04500 04501 04502

4474 4475 4476 4477 4500 4501 4502

0 4 5 0 0

2,4701 0,0530 0,0502 1,3565 14326 1,3653 14002

; ; ; ; ;

turn on check fail light get original verb that was executed set for ENTPAS0 puts original verb into VERBREG and displays it in verb lights

ORG BANK41_6 ; COLOSSUS pp. 359-360 INC L bank41_6.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_6.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 359-360. ;================= ========================================================= ;----------------- --------------------------------------------------------; MMCHANG -- MAJOR MODE CHANGE ; Uses noun displa y until ENTER; then it uses MODE display. It goes to ; MODROUT with the new MM code in A, but not displayed in MM lights. ; It demands 2 num erical characters be punched in for new MM code. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 359. ;----------------- --------------------------------------------------------EQU TC ; if this moves at all, ; MMADREF at ENTPA SHI 1,2074 0 CAF 0,0466 0 AD 6,7404 0 0,0000 6,7366 6,7365 6,7366 6,7367 0 0 0 0 1 CCS TC TC TC TC TC CAF XCH TS CAF TS TC DS CS TS CAF AD TC DS MODROUTR EQU MMCHANG * REQMM must change BIT5 DSPCOUNT A *+4 *+2 *+2 *+2 ALMCYCLE ZERO NOUNREG MPAC ND1 DSPCOUNT BANKCALL _2BLANK VD1 DSPCOUNT ZERO MPAC POSTJUMP MODROUTR V37 ; block num char in

15356

6,1356 0

; ENTPASHI assumes the TC GRQMM at MMCHA N G

15357 15360 15361 15362 15363 15364 15365 15366 15367 15370 15371 15372 15373 15374 15375 15376 15377 15400 15401 15402 15403

6,1357 3 6,1360 6 6,1361 6,1362 6,1363 6,1364 6,1365 1 0 0 0 0

; OCT 20 = ND2 ; DSPCOUNT must = -ND2 ; ; ; ; ; was BZF *+2 in Block II >0 +0 <0 -0

6,1366 0 6,1367 3 6,1370 3 6,1371 5 6,1372 3 6,1373 5 6,1374 0 6,1375 6,1376 4 6,1377 5 6,1400 3 6,1401 6 6,1402 0 6,1403

2,4474 1 1,2050 0 0,0471 0 0,0130 0 2,4676 1 0,0466 0 1,3565 1 12540 0 2,4675 0 0,0466 0 1,2050 0,0130 1,3653 10000 0 0 1 0

; DSPCOUNT not -ND2. Alarm and recycle.

; was CA MPAC in Block II

; go thru standard loc.

REQMM 15404 15405 15406 15407 15410 15411 15412 15413 15414 15415 15416 15417 6,1404 6,1405 6,1406 6,1407 6,1410 6,1411 6,1412 6,1413 6,1414 6,1415 6,1416 6,1417 4 5 3 5 3 5 0 0 3 5 0 0,0001 0,0502 2,4676 0,0466 1,2050 0,0471 1,3565 12540 2,4760 1,2051 0,0467 0,0433 1 0 1 0 0 0 1 0 1 1 1 0

EQU CS TS CAF TS CAF TS TC DS TC CAF TS TC

* Q REQRET ND1 DSPCOUNT ZERO NOUNREG BANKCALL _2BLANK FLASHON ONE DECBRNCH ENTEXIT

; set for dec

;----------------- --------------------------------------------------------; VBRQEXEC -- REQU EST EXECUTIVE ; ; Enters request t o EXEC for any address with any priority. It does ENDOFJOB ; after entering r equest. Display syst is released. It assumes NOUN 26 has been ; preloaded with: ; COMPONENT 1 -- p riority (bits 10-14), bit1=0 for NOVAC, bit1=1 for FINDVAC ; COMPONENT 2 -- j ob CADR (14 bit; was 12 bit in Block II) ; COMPONENT 3 -- n ot used (was BBCON in Block II) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 360. ;----------------- --------------------------------------------------------VBRQEXEC 15420 15421 15422 15423 15424 6,1420 6,1421 6,1422 6,1423 6,1424 3 7 1 0 3 1,2100 0,0534 0,0000 6,7444 2,4667 1 1 0 1 1 ; ; ; ; ; EQU CAF MAS K CCS TC CAF * BIT1 DSPTEM1 A SETVAC TCNOVAC

; if bit1=1, FINDVAC ; if bit1=0, NOVAC

sets up to call NOVAC or FINDVAC thru MPAC as follows: MPAC = TC NOVAC MPAC+1 = job CADR MPAC+2 = TC ENDOFJOB MPAC+3 = temp store for job PRIO EQU TS CS MAS K TS EQU TC CAF AD TS CAF AD TS CAF AD INH INT TC * MPAC BIT1 DSPTEM1 MPAC+3 * RELDSP ZERO ENDINST MPAC+2 ZERO DSPTEM1+1 MPAC+1 ZERO MPAC+3 MPAC * TCFINDVAC REQEX1

REQEX1 15425 15426 15427 15430 6,1425 6,1426 6,1427 6,1430 5 4 7 5 0,0130 1,2100 0,0534 0,0133 0 0 1 0 REQUESTC 15431 15432 15433 15434 15435 15436 15437 15440 15441 15442 15443 6,1431 6,1432 6,1433 6,1434 0 3 6 5 2,5003 1,2050 2,4553 0,0132 1 0 0 1

; TC NOVAC or TC FINDVAC into MPAC

; PRIO into MPAC+3 as a temp (was +4)

; was CA ENDINST in Block II ; TC ENDOFJOB into MPAC+2 (was +3) ; set BBCON for Block II dropped ; job adres into MPAC+1

6,1435 3 6,1436 6 6,1437 5 6,1440 6,1441 6,1442 6,1443 3 6 2 0

1,2050 0 0,0535 1 0,0131 1 1,2050 0,0133 0,0000 0,0130 0 0 0 0 SETVAC

; was CA MPAC+4 in Block II ; PRIO in A

15444 15445

6,1444 3 6,1445 0

2,4671 0 6,7425 0

EQU CAF TC

;----------------- --------------------------------------------------------; VBRQWAIT -- REQU EST WAITLIST ; ; Enters request t o WAITLIST for any address with any delay. It does ENDOFJOB ; after entering r equest. Display syst is released. It assumes NOUN 26 has been ; preloaded with: ; COMPONENT 1 -- d elay (low bits) ; COMPONENT 2 -- t ask CADR (14 bit; was 12 bit in Block II) ; COMPONENT 3 -- n ot used (was BBCON in Block II) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 360. ;----------------- --------------------------------------------------------VBRQWAIT 15446 15447 6,1446 3 6,1447 5 2,4670 1 0,0130 0 EQU CAF TS * TCWAIT MPAC

; TC WAITLIST into MPAC

15450 15451 15452

6,1450 3 6,1451 6 6,1452 0

1,2050 0 0,0534 0 6,7430 1 ENDRQWT

CAF AD TC

ZERO DSPTEM1 REQUESTC-1

; was CA DSPTEM1 in Block II ; time delay

; REQUESTC will pu t task address in MPAC+1, TC ENDOFJOB in MPAC+2. ; It will take the time delay out of MPAC+3 and leave it in A, INHINT ; and TC MPAC. BANK41_7 EQU *

ORG BANK40_7 ; COLOSSUS pp. 360-362 INC L bank40_7.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank40_7.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 360-362. ;================= ========================================================= ;----------------- --------------------------------------------------------; VBPROC -- PROCEE D WITHOUT DATA ; VBTERM -- TERMIN ATE ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 360. ;----------------- --------------------------------------------------------VBPROC 13315 13316 13317 13320 13321 13322 5,1315 5,1316 5,1317 5,1320 5,1321 5,1322 3 5 0 0 0 0 1,2051 0,0503 2,4536 2,5003 2,4770 5,7413 1 1 0 1 0 0 VBTERM 13323 13324 5,1323 4 5,1324 0 1,2051 0 5,7316 1 EQU CAF TS TC TC TC TC EQU CS TC * ONE LOADSTAT KILMONON RELDSP FLASHOFF RECALTST * ONE VBPROC+1

; proceed without data ; turn on kill monitor bit

; see if there is any recall from endidl e

; term verb sets loadstat neg

;----------------- --------------------------------------------------------; VBRESEQ ; Wakes ENDIDLE at same line as final enter of load (L+3). Main use is ; intended as resp onse to internally initiated flashing displays in ENDIDLE. ; Should not be us ed with load verbs, please perform, or please mark verbs ; because they alr eady use L+3 in another context. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 361. ;----------------- --------------------------------------------------------VBRESEQ 13325 13326 5,1325 4 5,1326 0 1,2050 1 5,7316 1 EQU CS TC * ZERO VBPROC+1

; make it look like data in.

; flash is turned off by proceed without data, terminate, ; resequence, end of load.

;----------------- --------------------------------------------------------; VBRELDSP ; This routine alw ays turns off the UPACT light and always clears ; DSPLOCK. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 362. ;----------------- --------------------------------------------------------VBRELDSP EQU *

; some code here t o turn off the UPACT light is omitted 13327 13330 13331 13332 13333 13334 13335 13336 13337 13340 13341 5,1327 5,1330 5,1331 5,1332 5,1333 5,1334 5,1335 5,1336 5,1337 5,1340 5,1341 1 3 7 1 0 0 1 0 0 0 0,0412 1,2063 0,0510 0,0000 5,7342 2,5003 0,0531 5,7340 1,2723 1,3653 05067 1 0 1 0 0 1 TSTLTS4 1 1 0 1 0 UNSUSPEN 13342 13343 5,1342 3 5,1343 5 1,2050 0 0,0501 0 CCS CAF MAS K CCS TC TC CCS TC TC TC CAD R EQU CAF TS _2122REG BIT14 MONSAVE1 A UNSUSPEN RELDSP CADRSTOR *+2 ENDOFJOB POSTJUMP PINBRNCH * ZERO DSPLOCK ; old DSPLOCK ; external monitor bit (EMB) ; old DSPLOCK and EMB both 1, unsuspend ; not unsuspending external monitor, ; release display system and ; do reestablish if CADRSTOR is full

; external monitor is suspended ; just unsuspend it by clearing DSPLOCK

13344 13345 13346 13347

5,1344 5,1345 5,1346 5,1347

1 0 0 0

0,0531 1,2723 2,5026 1,2723

1 0 0 0

CCS TC TC TC

CADRSTOR ENDOFJOB RELDSP1 ENDOFJOB

; turn key release light off if both ; CADRSTOR and DSPLIST are empty

BANK40_8

EQU

ORG BANKFF_3 ; COLOSSUS pp. 363-364 INC L bankff_3.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_3.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 363-364. ;================= ========================================================= ; COLOSSUS p. 364 - comments are taken from the Block I flow charts with some ; additional annot ations by me.

NVSUB 04503 04504 04505 4503 5 4504 3 4505 5 0,0565 1 1,2050 0 0,0564 0

EQU TS CAF TS

* NVSUB_A ZERO NVSUB_L

; more gymnastics for Block II conversio n ; was LXCH 7 in Block II ; zero NVMONOPT options

; save C(A). C(A) should be holding the noun/verb code; C(L) should ; be holding NVMON OPT options. In this Block I version, the NVMONOPT ; options should b e placed in NVSUB_L before calling NVMONOPT. 04506 4506 3 0,0565 1 NVMONOPT 04507 4507 5 0,0420 1 XCH EQU TS NVSUB_A * NVTEMP

; Test DSPLOCK (+N Z=busy; +0=display system available) ; Display is block ed by DSPLOCK=1 or external monitor bit set (bit 14) 04510 04511 04512 04513 04514 4510 4511 4512 4513 4514 3 7 6 1 0 1,2063 0,0510 0,0501 0,0000 0,0001 0 1 0 0 0 CAF MAS K AD CCS TC BIT14 MONSAVE1 DSPLOCK A Q

; external monitor bit

; dsp syst blocked, ret to 1, calling lo c

; Store calling li ne +2 in NVQTEM 04515 04516 04517 4515 3 4516 6 4517 5 1,2051 1 0,0001 0 NVSBCOM 0,0526 0 CAF AD TS ONE Q NVQTEM ; dsp syst available ; 2+calling loc into NVQTEM

; Force bit 15 of MONSAVE to 1, turn off bit 14. 04520 04521 04522 04523 4520 3 4521 3 4522 5 4523 0 0,0564 0 0,0511 1 0,0564 0 2,4536 0 XCH XCH TS TC NVSUB_L MONSAVE2 NVSUB_L KILMONON ; was LXCH MONSAVE2 in Block II ; store NVMONOPT options ; replaces LXCH by working through A ins t e a d ; turn on kill monitor bit

; Store calling ba nk in NVBNKTEM ; ** this was chan ged quite a bit from Block II ** NVSUBCOM 04524 04525 04526 04527 04530 04531 4524 3 4525 6 4526 5 4527 0 4530 4531 1,2050 0 0,0015 0 0,0527 1 1,3624 1 14000 1 15505 0 NVSRRBNK EQU CAF AD TS TC CAD R CAD R * ZERO BANK NVBNKTEM MYBANKCALL NVSUBR NVSUB1 ; go to NVSUB1 thru standard loc

; ****** WHAT'S THIS FOR?? ********

; Restore calling bank and TC NVQTEM ; ** this was chan ged quite a bit from Block II ** NVSUBEND 04532 04533 04534 04535 4532 4533 4534 4535 3 6 5 0 1,2050 0,0527 0,0015 0,0526 0 1 0 0 BANKFF_4 EQU CAF AD TS TC EQU * ZERO NVBNKTEM BANK NVQTEM *

; restore calling bank

ORG BANK41_7 ; COLOSSUS pp. 365-366 INC L bank41_7.asm ;================= =========================================================

; DISPLAY ROUTINES (file:bank41_7.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 365-366. ;================= =========================================================

; BLANKDSP blanks display according to option number in NVTEMP as follows: ; -4 full blank, - 3 leave mode, -2 leave mode and verb, -1 blank R-S only BLANKDSP 15453 15454 15455 15456 15457 15460 15461 15462 15463 15464 15465 15466 15467 15470 15471 15472 15473 15474 15475 15476 15477 15500 6,1453 6,1454 6,1455 6,1456 6,1457 6,1460 6 2 5 4 2 3 1,2057 0,0000 0,0421 1,2065 0,0421 0,0512 1 0 0 1 1 1 EQU AD INH INT TS CS IND EX XCH CCS TC TC CCS TC REL INT IND EX TC TC TS TS TS CS TS TC TC INCR_NOUT 15501 15502 15503 15504 6,1501 6,1502 6,1503 6,1504 3 6 5 0 0,0505 1,2051 0,0505 6,7463 1 1 1 1 NVSUB1 15505 15506 15507 15510 15511 15512 15513 15514 15515 15516 15517 15520 15521 15522 15523 15524 15525 15526 15527 15530 15531 15532 6,1505 3 6,1506 5 6,1507 6,1510 6,1511 6,1512 6,1513 1 0 0 0 0 6,7542 0 0,0433 0 0,0420 6,7514 6,6341 6,7453 6,6341 0 0 1 1 1 EQU XCH AD TS TC EQU CAF TS CCS TC TC TC TC * SEVEN CODE BIT12 CODE DSPTAB A INCR_NOUT *+1 CODE BLANKDSP+2 NVTEMP *+5 *+1 VERBREG NOUNREG CLPASS VD1 DSPCOUNT FLASHOFF ENTSET-2 * NOUT ONE NOUT INCR_NOUT_RET * ENTSET ENTRET NVTEMP *+4 GODSPALM BLANKDSP GODSPALM ; protect against invisible flash ; zeroes REQRET

; 7,8,9,or 10 (A had 0,1,2,or 3) ; blank specified DSPTABS

6,1461 1 6,1462 0 6,1463 0 6,1464 6,1465 6,1466 6,1467 6,1470 6,1471 6,1472 6,1473 6,1474 1 0 2 2 0 0 5 5 5

0,0000 0 6,7501 1 6,7464 0 INCR_NOUT_RET 0,0421 6,7455 0,0000 0,0420 6,7475 6,7472 0,0470 0,0471 0,0504 1 1 1 0 0 1 1 0 0

; was INCR NOUT in Block II

; NVTEMP has -4 (never touch MODREG) ; -3 ; -2 ; -1

6,1475 4 6,1476 5 6,1477 0 6,1500 0

2,4675 0 0,0466 0 2,4770 0 6,7540 1

; ; ; ;

was INCR NOUT in Block II have to make it a separate routine because it was nested inside a CCS.

; in bank ; set return to NVSUBEND ; what now ; normal NVSUB call (execute VN or paste ) ; blank display as specified

6,1514 3 6,1515 7 6,1516 5 6,1517 3 6,1520 6 6,1521 6,1522 6,1523 6,1524 6,1525 6,1526 6,1527 6,1530 6,1531 6,1532 5 4 4 4 4 4 4 3 7 5

1,2101 0 0,0420 0 0,0133 0 ; 1,2050 0 0,0420 1 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 0,0020 1,2101 0,0134 0 1 1 1 1 1 1 0 1 1 ;

CAF LOW7 MAS K NVTEMP TS MPAC+3 u ses MPAC, +1, +2 CAF ZERO AD NVTEMP TS CYR CS CYR CS CYR CS CYR CS CYR CS CYR CS CYR XCH CYR MAS K LOW7 TS MPAC+4 u ses MPAC, +1, +2 CCS TC CAF AD TC CAF TS TC MPAC+3 NVSUB2 ZERO MPAC+4 UPDATVB-1 ZERO REQRET NVSUBEND

; temp for noun (can't use MPAC, DSPDECV N ; was CA NVTEMP

; shift right 7, was TS EDOP, CA EDOP in B I I

; temp for verb (can't use MPAC, DSPDECV N

15533 15534 15535 15536 15537 15540 15541 15542

6,1533 1 6,1534 0 6,1535 3 6,1536 6 6,1537 0 6,1540 3 6,1541 5 6,1542 0

0,0133 1 6,7543 1 1,2050 0 0,0134 1 6,6326 0 1,2050 0 0,0502 0 2,4532 1 ENTSET

; test noun (+NZ or +0) ; if noun not +0, DC on ; was CA MPAC+4 in Block II ; if noun = +0, display verb then return ; zero REQRET so that pasted verbs can ; be executed by operator

15543 15544 15545 15546 15547 15550 15551 15552 15553 15554 15555 15556 15557 15560 15561 15562 15563 15564 15565 15566 15567 15570 15571

6,1543 1 6,1544 0 6,1545 6,1546 6,1547 6,1550 3 6 0 0

0,0134 0 NVSUB2 6,7551 1 1,2050 0,0133 6,6306 2,4532 0 0 1 1

CCS TC CAF AD TC TC CAF AD TS CAF AD TC CAF AD TC CAF TS TS TS CAF AD TS TC

MPAC+4 *+5 ZERO MPAC+3 UPDATNN-1 NVSUBEND ZERO MPAC+2 MPAC+5 ZERO MPAC+4 UPDATVB-1 ZERO MPAC+3 UPDATNN-1 ZERO LOADSTAT CLPASS REQRET ZERO MPAC+5 MPAC+2 ENTPAS0

; test verb (+NZ or +0) ; if verb not +0, go on ; was CA MPAC+3 in Block II ; if verb = +0, display noun, then retur n

6,1551 3 6,1552 6 6,1553 5 6,1554 3 6,1555 6 6,1556 0 6,1557 3 6,1560 6 6,1561 0 6,1562 6,1563 6,1564 6,1565 3 5 5 5

1,2050 0 0,0132 1 0,0135 0 1,2050 0 0,0134 1 6,6326 0 1,2050 0 0,0133 0 6,6306 1 1,2050 0,0503 0,0504 0,0502 0 1 0 0

; was CA MPAC+2 in Block II ; temp for mach CADR to be spec, (DSPDEC V N ; uses MPAC, +1, +2 ; was CA MPAC+4 in Block II ; if both noun and verb not +0, display ; was CA MPAC+3 in Block II ; both and go to ENTPAS0

; set for waiting for data condition ; set request for pass 0 ; was CA MPAC+5 in Block II ; restores mach CADR to be spec to MPAC+ 2 ; for use in INTMCTBS (in ENTPAS0)

6,1566 3 6,1567 6 6,1570 5 6,1571 0

1,2050 0 0,0135 0 0,0132 1 6,6040 0 ENDNVSB1

; if internal mach CADR to be specified, MPAC+2 will be placed into ; NOUNCADR in ENTP AS0 (INTMCTBS)

BANK41_8

EQU

ORG BANKFF_4 ; COLOSSUS pp. 366-368 INC L bankff_4.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_4.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 366-368. ;================= =========================================================

KILMONON 04536 04537 04540 4536 3 4537 5 4540 0 1,2062 1 0,0510 0 0,0001 0

EQU CAF TS TC

* BIT15 MONSAVE1 Q

; ; ; ;

force bit 15 of MONSAVE1 to 1. this is the kill monitor bit. turn off bit 14, the external monitor bit.

; COLOSSUS p. 367 ENDIDLE 04541 04542 04543 04544 04545 04546 04547 04550 04551 04552 04553 4541 3 4542 5 4543 0 4544 0 4545 4546 4547 4550 4551 4552 3 6 7 6 5 0 0,0001 0 0,0566 1 2,4554 1 2,4560 0 1,2050 0,0566 2,4674 0,0015 0,0531 1,2725 0 1 1 0 0 0 EQU XCH TS TC TC CAF AD MAS K AD TS TC TC EQU CCS TC TC TC EQU CCS TC TC TC DS * Q ENDIDLE_L ISCADR_P0 ISLIST_P0 ZERO ENDIDLE_L LOW10 BANK CADRSTOR JOBSLEEP ENDOFJOB * CADRSTOR DSPABORT Q DSPABORT * DSPLIST DSPABORT Q POODOO %1206

; was LXCH Q in Block II ; return address into L ; abort if CADRSTOR not= +0 ; abort if DSPLIST not= +0 ; ; ; ; was CA L in Block II don't set DSPLOCK to 1 so can use ENDIDLE with NVSUB initiated monitor. same strategy for CADR as MAKECADR

4553 0

1,2723 0 ENDINST ISCADR_P0

04554 04555 04556 04557

4554 4555 4556 4557

1 0 0 0

0,0531 2,4563 0,0001 2,4563

1 0 0 0 ISLIST_P0 1 0 0 1 DSPABORT 1

; aborts (code 1206 if CADRSTOR not= +0 ; returns if CADRSTOR = +0

04560 04561 04562 04563 04564

4560 4561 4562 4563 4564

1 0 0 0

0,0532 2,4563 0,0001 2,5050 01206

; aborts (code 1206 if DSPLIST not= +0 ; returns if DSPLIST = +0

; ; ; ; ;

BLANKSUB blanks any combination of R1, R2, R3. Call with blanking code in A. BIT1=1 blanks R1 , BIT2=1 blanks R2, BIT3=1 blanks R3. Any combination of thes e three bits is ac cepted. DSPCOUNT is rest ored to the state it was in before BLANKSUB was executed. EQU MAS K TS CAF MAS K AD CCS TC XCH AD TS CCS TC TC * SEVEN NVTEMP BIT14 MONSAVE1 DSPLOCK A Q Q ONE BLANKSUB_Q NVTEMP *+2 BLANKSUB_Q

BLANKSUB 04565 04566 04567 04570 04571 04572 04573 04574 04575 04576 04577 04600 04601 4565 4566 4567 4570 4571 4572 4573 4574 4575 4576 7 5 3 7 6 1 0 3 6 5 1,2057 0,0420 1,2063 0,0510 0,0501 0,0000 0,0001 0,0001 1,2051 0,0561 0 1 0 1 0 0 0 0 1 0

; store blanking code in NVTEMP ; external monitor bit

; ; ; ;

dsp was set was

syst blocked. Return to 1+calling l o c INCR Q in Block II return for 2+calling location TC Q in Block II

4577 1 4600 0 4601 0

0,0420 0 2,4602 1 0,0561 0

; was TCF in Block II ; nothing to blank, Return to 2+calling l o c

; ; ; ; ; ; ; 04602 04603 04604 04605 04606 04607 04610 04611 04612 4602 3 4603 6 4604 3 4605 3 4606 6 4607 3 4610 3 4611 0 4612 1,2050 0 0,0561 0 0,0426 1 1,2050 0 0,0015 0 0,0425 1

the return addre ss+2 is now in BLANKSUB_Q. We need to call BLNKSUB1 in in "bank 40", so we'll have to save the bank register so that we can return to the ad dress in BLANKSUB_Q. The block II code had a bunch of tricky stuff inv olving the both bank bits and superbit. Block I doesn't need to worry ab out that, so we can substitute this simplified code. As in the Block II code, the return bank gets saved to BUF and the return address+2 gets s aved to BUF+1. CAF AD XCH CAF AD XCH CAF TC CAD R ZERO BLANKSUB_Q BUF+1 ZERO BANK BUF BSUB1ADDR DXCHJUMP BLNKSUB1

; set return for 2+calling loc

; save return bank

2,4612 0 1,3526 0 13350 0 BSUB1ADDR

; bank jump to BLNKSUB1 rtne

; this is my attem pt to implement the return from BLNKSUB1. In BII, it executes ; as part of the B LNKSUB1 routine: ; DXCH BUF ; TC SUPDXCHZ+ 1 ; to jump from the BLNKSUB1 bank to the calling bank. BS_SUPDXCHZ 04613 04614 04615 4613 3 4614 3 4615 0 0,0425 1 0,0015 0 0,0426 1 BANKFF_5 EQU XCH XCH TC EQU * BUF BANK BUF+1 *

; restore the calling bank bits ; return to calling loc+2 (set in BLANKS U B )

ORG BANK04_2 ; COLOSSUS pp. 369 INC L bank04_2.asm ;================= ========================================================= ; DSPMM - DISPLAY MODREG (file: bank04_2.asm) ; ; DSPMM does not d isplay MODREG directly. It puts EXEC request with ; prio=CHARPRIO fo r DSPMMJB and returns to caller. ; ; If MODREG contai ns -0, DSPMMJB blanks the MODE lights. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 369. ;================= =========================================================

10047 10050 10051 10052 10053 10054 10055 10056

4,0047 4,0050 4,0051 4,0052 4,0053 4,0054 4,0055 4,0056

3 5 2 3 0 2 0

0,0001 0,0130 0,0000 2,4131 1,3162 13400 0,0000 0,0130

DSPMM 0 0 0 0 1 1 1 0 ENDSPMM

EQU XCH TS INH INT CAF TC CAD R REL INT TC

* Q MPAC CHRPRIO NOVAC DSPMMJB MPAC

BANK04_3

EQU

ORG BANK40_8 ; COLOSSUS pp. 369-371 INC L bank40_8.asm ;================= =========================================================

; DISPLAY ROUTINES (file:bank40_8.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 369-371. ;================= ========================================================= BLNKSUB1 13350 13351 13352 13353 13354 13355 13356 13357 13360 13361 13362 13363 13364 13365 13366 13367 13370 13371 13372 5,1350 3 5,1351 6 5,1352 5 5,1353 5,1354 5,1355 5,1356 5,1357 5,1360 5,1361 5,1362 5,1363 5,1364 5,1365 5,1366 3 0 3 0 3 0 3 0 3 0 3 0 1,2050 0 0,0466 0 0,0427 0 1,2100 5,7373 2,4635 5,6472 1,2077 5,7373 2,4636 5,6472 1,2076 5,7373 2,4637 5,6472 1 1 0 0 0 1 0 0 1 1 1 0 EQU CAF AD TS CAF TC CAF TC CAF TC CAF TC CAF TC CAF TC CAF AD TS TC * ZERO DSPCOUNT BUF+2 BIT1 TESTBIT R1D1 _5BLANK-1 BIT2 TESTBIT R2D1 _5BLANK-1 BIT3 TESTBIT R3D1 _5BLANK-1 ZERO BUF+2 DSPCOUNT BS_SUPDXCHZ

; was CA DSPCOUNT in Block II ; save old DSPCOUNT for later restoratio n

; test bit 1. See if R1 to be blanked.

; test bit 2. See if R2 to be blanked.

; test bit 3. See if R3 to be blanked.

5,1367 3 5,1370 6 5,1371 5 5,1372 0

1,2050 0 0,0427 0 0,0466 0 2,4613 1

; was CA BUF+2 in Block II ; restore DSPCOUNT to state it had ; before BLANKSUB ; was DXCH BUF, TC SUPDXCHZ+1 in BII

TESTBIT 13373 13374 13375 13376 13377 5,1373 5,1374 5,1375 5,1376 5,1377 7 1 0 2 0 0,0420 0,0000 0,0001 0,0001 0,0002 0 0 0 1 0 DSPMMJB 13400 13401 13402 13403 13404 13405 13406 13407 13410 13411 13412 5,1400 5,1401 5,1402 5,1403 5,1404 5,1405 5,1406 5,1407 5,1410 5,1411 5,1412 3 3 5 1 6 0 0 0 3 5 0 2,4677 0,0466 0,0435 0,0500 1,2051 5,7144 5,7410 5,6540 0,0435 0,0466 1,2723 0 0 0 0 1 1 0 0 0 0 0

EQU MAS K CCS TC IND EX TC EQU CAF XCH TS CCS AD TC TC TC XCH TS TC

* NVTEMP A Q Q 2 * MD1 DSPCOUNT DSPMMTEM MODREG ONE DSPDECVN *+2 _2BLANK DSPMMTEM DSPCOUNT ENDOFJOB

; NVTEMP contains blanking code ; if current bit = 1, return to L+1 ; if current bit = 0, return to L+3

; gets here thru DSPMM ; save DSPCOUNT

; ; ; ;

if MODREG is + or +0, display MODREG if MODREG is -NZ, do nothing if MODREG is -0, blank MM restore DSPCOUNT

;----------------- --------------------------------------------------------; RECALTST ; Entered directly after data is loaded (or resequence verb is executed), ; terminate verb i s executed, or proceed without data verb is executed. ; It wakes up job that did TC ENDIDLE. ; If CADRSTOR not = +0, it puts +0 into DSPLOCK, and turns off KEY RLSE ; light if DSPLIST is empty (leaves KEY RLSE light alone if not empty). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 370. ;----------------- --------------------------------------------------------RECALTST 13413 13414 13415 5,1413 1 5,1414 0 5,1415 0 0,0531 1 5,7416 0 1,2723 0 RECAL1 13416 13417 13420 13421 13422 13423 13424 13425 13426 5,1416 5,1417 5,1420 5,1421 5,1422 5,1423 5,1424 5,1425 5,1426 3 3 2 0 1 0 0 0 3 1,2050 0,0531 0,0000 1,3003 0,0503 5,7450 1,2723 5,7446 1,2052 0 0 0 1 0 1 0 0 1 RECAL2 13427 13430 13431 13432 5,1427 5,1430 5,1431 5,1432 2 6 2 5 0,0300 0,0140 0,0300 0,0140 0 1 0 1 EQU CCS TC TC EQU CAF XCH INH INT TC CCS TC TC TC CAF EQU IND EX AD IND EX TS * CADRSTOR RECAL1 ENDOFJOB * ZERO CADRSTOR JOBWAKE LOADSTAT DOPROC ENDOFJOB DOTERM TWO * LOCCTR LOC LOCCTR LOC

; normal exit if keyboard initiated.

; ; ; ;

+ proceed without data pathological case exit - terminate -0, data in or resequence

; loc is + for basic jobs

13433 13434 13435 13436 13437 13440 13441 13442 13443

5,1433 5,1434 5,1435 5,1436 5,1437 5,1440 5,1441 5,1442

3 6 2 5 3 6 2 5

1,2050 0,0471 0,0300 0,0131 1,2050 0,0470 0,0300 0,0130

0 0 0 1 0 1 0 0

CAF AD IND EX TS CAF AD IND EX TS REL INT RECAL3 EQU TC TC EQU CAF TC EQU CAF TC EQU

ZERO NOUNREG LOCCTR MPAC+1 ZERO VERBREG LOCCTR MPAC

; ; ; ;

save verb in MPAC, noun in MPAC+1 at time of response to ENDIDLE for possible later testing by job that has been waked up

5,1443 2

0,0000 1

13444 13445

5,1444 0 5,1445 0

2,5003 1 1,2723 0 DOTERM

* RELDSP ENDOFJOB * ZERO RECAL2 * ONE RECAL2 *

13446 13447

5,1446 3 5,1447 0

1,2050 0 5,7427 1 DOPROC

13450 13451

5,1450 3 5,1451 0

1,2051 1 5,7427 1 BANK40_8a

ORG BANKFF_5 ; COLOSSUS pp. 372-376 INC L bankff_5.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_5.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 372-376. ;================= ========================================================= ;----------------- --------------------------------------------------------; MISCELLANEOUS SE RVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 372. ;----------------- --------------------------------------------------------; SETNCADR ; Store the erasea ble memory address from A into NOUNCADR and NOUNADD. ; (changed from Bl ock II, because there is no bank addressing for block I) ; ; ; ; ; ; ; SETNADD Get the eraseabl e memory address from NOUNCADR and store it into NOUNADD. (changed from Bl ock II, because there is no bank addressing for block I) SETEBANK E CADR arrives i n A. E ADRES is "derived" and left in A. (changed from Bl ock II, because there is no bank addressing for block I) EQU XCH TS XCH TS MAS K TS TC SETNADD 04625 04626 04627 04630 04631 04632 4625 3 4626 5 4627 3 4630 3 4631 6 4632 0 0,0001 0 0,0555 1 0,0001 0 1,2050 0 0,0506 1 2,4622 0 SETEBANK 04633 04634 4633 7 4634 0 2,4674 1 0,0001 0 EQU XCH TS XCH CAF AD TC EQU MAS K TC * Q SETNCADR_Q Q NOUNCADR LOW10 NOUNADD SETNCADR_Q * Q SETNCADR_Q Q ZERO NOUNCADR SETNCADR+4 * LOW10 Q

SETNCADR 04616 04617 04620 04621 04622 04623 04624 4616 3 4617 5 4620 3 4621 4622 4623 4624 5 7 5 0 0,0001 0 0,0555 1 0,0001 0 0,0506 2,4674 0,0442 0,0555 1 1 0 1

; save return address ; restore A ; store ECADR ; put E ADRES into NOUNADD

; save return address ; restore A

; get NOUNCADR

04635 04636 04637

4635 4636 4637

00016 0 R1D1 00011 1 R2D1 00004 0 R3D1 RIGHT5

DS DS DS EQU TS CS CS

%16 %11 %4 * CYR CYR CYR

; these 3 constants form a packed table ; don't separate ; must stay here

04640 04641 04642

4640 5 4641 4 4642 4

0,0020 0 0,0020 1 0,0020 1

04643 04644 04645 04646

4643 4644 4645 4646

4 4 3 0

0,0020 0,0020 0,0020 0,0001

1 1 0 0 LEFT5

CS CS XCH TC EQU TS CS CS CS CS XCH TC EQU DOU BLE DOU BLE DOU BLE DOU BLE DOU BLE TC DS DS DS TC TC TC TC DS DS EQU DS DS DS DS DS DS

CYR CYR CYR Q * CYL CYL CYL CYL CYL CYL Q *

04647 04650 04651 04652 04653 04654 04655

4647 4650 4651 4652 4653 4654 4655

5 4 4 4 4 3 0

0,0022 0,0022 0,0022 0,0022 0,0022 0,0022 0,0001

1 0 0 0 0 1 0 SLEFT5

04656 04657 04660 04661 04662 04663 04664 04665 04666 04667 04670 04671

4656 4657 4660 4661 4662 4663 4664 4665 4666

6 6 6 6 6 0

0,0000 0,0000 0,0000 0,0000 0,0000 0,0001

1 1 1 1 1 0

Q %00037 %01740 %76000 NOVAC WAITLIST TASKOVER FINDVAC %30000 %3777 LOW11 %377 %01777 %23 %21 %25 10 ; EXEC priority of CHARIN ; these 3 constants form a packed table ; don't separate ; must stay here

00037 0 LOW5 01740 0 MID5 76000 0 HI5 1,3162 1 TCNOVAC 1,2232 0 TCWAIT ;TCTSKOVR 1,3161 1 TCFINDVAC ;CHRPRIO 03777 0 LOW11 B12M1 00377 1 LOW8 01777 1 LOW10 00023 0 VD1 00021 1 ND1 00025 0 MD1 00012 1 BINCON

4667 0 4670 0 4671 0

04672 04673 04674 04675 04676 04677 04700

4672 4673 4674 4675 4676 4677 4700

; these 3 constants form a packed table ; don't separate ; must stay here

;**************** TURN ON/OFF OPERATOR ERROR LIGHT ******* p. 373 DSALMOUT FALTON 04701 04702 04703 04704 04705 4701 4702 4703 4704 4705 4 7 4 5 0 0,0011 2,4712 0,0000 0,0011 0,0001 0 0 0 1 0 FALTOF 04706 04707 04710 04711 04712 4706 4707 4710 4711 4712 4 7 5 0 1,2072 0,0011 0,0011 0,0001 1 0 1 0 EQU EQU CS MAS K COM TS TC EQU CS MAS K TS TC DS OUT1 * DSALMOUT FALTOR DSALMOUT Q * BIT7 DSALMOUT DSALMOUT Q %77677 ; channel 11 in Block II is OUT1 in Bloc k I

; inclusive OR bit 7 with 1 using ; Demorgan's theorem ; was bit 7 of channel 11 in Block II

; was bit 7 of channel 11 in Block II

77677 1 FALTOR

; 1's compliment of bit 7

;**************** TURN ON KEY RELEASE LIGHT ******* p. 373 RELDSPON 04713 04714 04715 04716 04717 04720 4713 4714 4715 4716 4717 4720 4 7 4 5 0 0,0011 2,4720 0,0000 0,0011 0,0001 0 1 0 1 0 EQU CS MAS K COM TS TC DS * DSALMOUT RELDSPOR DSALMOUT Q %77757

; inclusive OR bit 5 with 1 using ; Demorgan's theorem ; was bit 5 of channel 11 in Block II

77757 1 RELDSPOR

; 1's compliment of bit 5

; TPSL1 ; Shift triple wor d MPAC, MPAC+1, MPAC+2 left 1 bit TPSL1 04721 04722 04723 04724 04725 04726 04727 4721 4722 4723 4724 3 6 6 5 1,2050 0,0132 0,0132 0,0132 0 1 1 1 EQU CAF AD AD TS CAF AD AD * ZERO MPAC+2 MPAC+2 MPAC+2 ZERO MPAC+1 MPAC+1

; skip on overflow ; otherwise, make interword carry=0

4725 3 4726 6 4727 6

1,2050 0 0,0131 1 0,0131 1

04730 04731 04732 04733 04734 04735 04736 04737

4730 5 4731 4732 4733 4734 3 6 6 5

0,0131 1 1,2050 0,0130 0,0130 0,0130 0 0 0 0

TS CAF AD AD TS TC TS TC

MPAC+1 ZERO MPAC MPAC MPAC Q MPAC+6 Q

; skip on overflow ; otherwise, make interword carry=0

; skip on overflow ; no net OV/UF ; MPAC+6 set to +/- 1 for OV/UF

4735 0 4736 5 4737 0

0,0001 0 0,0136 0 0,0001 0

; ; ; ; ; ; ;

PRSHRTMP if MPAC, +1 are each +NZ or +0 and C(A)=-0, SHORTMP wrongly gives +0. if MPAC, +1 are each -NZ or -0 and C(A)=+0, SHORTMP wrongly gives +0. PRSHRTMP fixes f irst case only, by merely testing C(A) and if it = -0, setting result t o -0. (Do not use PRSH RTMP unless MPAC, +1 are each +NZ or +0, as they are when they contai n the SF constants). EQU TS XCH TS CCS TC TC TC CS TS TS TS TC * MPTEMP Q PRSHRTMP_Q MPTEMP DOSHRTMP DOSHRTMP DOSHRTMP ZERO MPAC MPAC+1 MPAC+2 PRSHRTMP_Q * ZERO MPTEMP SHORTMP PRSHRTMP_Q

PRSHRTMP 04740 04741 04742 04743 04744 04745 04746 04747 04750 04751 04752 04753 4740 5 4741 3 4742 5 4743 4744 4745 4746 4747 4750 4751 4752 4753 1 0 0 0 4 5 5 5 0 0,0432 1 0,0001 0 0,0600 1 0,0432 2,4754 2,4754 2,4754 1,2050 0,0130 0,0131 0,0132 0,0600 0 0 0 0 1 0 1 1 1 DOSHRTMP 04754 04755 04756 04757 4754 4755 4756 4757 3 6 0 0 1,2050 0,0432 2,4353 0,0600 0 1 0 1

; ; ; ;

C(A) C(A) C(A) C(A)

+, do regular SHORTMP +0, do regular SHORTMP -, do regular SHORTMP -0, force result to -0 and return

EQU CAF AD TC TC

;**************** TURN ON/OFF V/N FLASH ******* p. 374 ; this is handled by setting a bit in channel 11 in Block II. ; In Block I, it h as to be set through the display table, so I ; borrowed this me thod from SGNCOM (the DSKY +/- sign routine) ; Uses MYBANKCALL because BANKCALL is not reentrant and I dont ; understand its u sage in COLOSSUS well enough to be certain ; that FLASHON/FLA SHOFF isn't being called somewhere through ; BANKCALL. FLASHON 04760 04761 04762 04763 04764 04765 04766 04767 4760 3 4761 5 4762 4763 4764 4765 4766 3 5 3 0 0,0001 0 0,0570 0 1,2066 0,0421 2,5000 1,3624 13253 0 0 1 1 1 EQU XCH TS CAF TS CAF TC CAD R TC FLASHOFF 04770 04771 04772 04773 04774 04775 04776 04777 05000 4770 3 4771 5 4772 4773 4774 4775 4776 3 5 3 0 0,0001 0 0,0570 0 1,2050 0,0421 2,5000 1,3624 13253 0 0 1 1 1 EQU XCH TS CAF TS CAF TC CAD R TC DS * Q FLASHRET BIT11 CODE FLSHTAB MYBANKCALL _11DSPIN FLASHRET * Q FLASHRET ZERO CODE FLSHTAB MYBANKCALL _11DSPIN FLASHRET %11 ; V/N flash

4767 0

0,0570 0

4777 0 5000

0,0570 0 00011 1 FLSHTAB

NVSUBUSY 05001 05002 5001 0 5002 1,3653 1 13452 0

EQU TC CAD R

* POSTJUMP NVSUBSY1

BANKFF_5a

EQU

ORG BANK40_8a ; COLOSSUS pp. 376 INC L bank40_8a.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank40_8a.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 376. ;================= ========================================================= ;----------------- --------------------------------------------------------; MISCELLANEOUS SE RVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 376. ;----------------- --------------------------------------------------------NVSUBSY1 0 1 0 0 0 0 0 0 ENDNVBSY BANK40_9 EQU TS TC TC TC CAF AD TS TC EQU * NBSUBSY1_L ISCADR_P0 ISLIST_P0 RELDSPON ZERO NBSUBSY1_L DSPLIST JOBSLEEP *

13452 13453 13454 13455 13456 13457 13460 13461

5,1452 5,1453 5,1454 5,1455 5,1456 5,1457 5,1460 5,1461

5 0 0 0 3 6 5 0

0,0567 2,4554 2,4560 2,4713 1,2050 0,0567 0,0532 1,2725

; save CADR ; abort if CADRSTOR not = +0 ; abort if DSPLIST not = +0 ; was CA L in Block II

ORG BANKFF_5a ; COLOSSUS pp. 376-378 INC L bankff_5a.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bankff_5a.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 376-378. ;================= ========================================================= ;----------------- --------------------------------------------------------; MISCELLANEOUS SE RVICE ROUTINES IN FIXED-FIXED ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 376. ;----------------- --------------------------------------------------------; RELDSP ; used by VBPROC, VBTERM, VBRQEXEC, VBRQWAIT, VBRELDSP, EXTENDED VERB ; DISPATCHER, VBRE SEQ, and RECALTST. ; RELDSP1 ; used by monitor set up, VBRELDSP RELDSP 05003 05004 05005 05006 05007 05010 05011 05012 05013 05014 05015 05016 5003 5004 5005 5006 5007 5010 5011 5012 5013 5014 5015 5016 3 5 4 2 7 5 1 0 0 3 3 0 0,0001 0,0441 1,2063 0,0000 0,0510 0,0510 0,0532 2,5014 2,5017 1,2050 0,0532 1,3003 0 0 1 0 1 0 1 1 1 0 0 1 RELDSP2 05017 05020 05021 05022 05023 05024 05025 5017 5020 5021 5022 2 4 7 5 0,0000 1,2074 0,0011 0,0011 1 1 0 1 EQU XCH TS CS INH INT MAS K TS CCS TC TC CAF XCH TC EQU REL INT CS MAS K TS CAF TS TC RELDSP1 * Q RELRET BIT14 MONSAVE1 MONSAVE1 DSPLIST *+2 RELDSP2 ZERO DSPLIST JOBWAKE * BIT5 DSALMOUT DSALMOUT ZERO DSPLOCK RELRET * Q ; set DSPLOCK to +0, No DSPLIST search RELRET ; turn KEY RLSE light off if DSPLIST is light alone if DSPLIST *+2 RELDSP2 ZERO ; turn off KEY RLSE light ; was WAND DSALMOUT in Block II

; set DSPLOCK to +0, turn RELDSP light ; off, search DSPLIST

; turn off external monitor bit

; list empty

5023 3 5024 5 5025 0

1,2050 0 0,0501 0 0,0441 0

05026 05027

5026 3 5027 5

05030 05031 05032 05033

5030 5031 5032 5033

1 0 0 3

EQU XCH TS ; empty. Leave KEY RLSE ; DSPLIST is not e mpty. 0,0532 1 CCS 2,5033 1 TC 2,5017 1 TC 1,2050 0 CAF 0,0001 0 0,0441 0

; + not empty, leave KEY RLSE light alon e ; +0, list empty, turn off KEY RLSE ligh t ; - not empty, leave KEY RLSE light alon e

05034 05035

5034 5 5035 0

0,0501 0 0,0441 0

TS TC

DSPLOCK RELRET

;----------------- --------------------------------------------------------; NEWMODEA ; ; The new major mo de is in register A. Store the major mode in MODREG and updat e ; the major mode d isplay. ; ; I couldn't find this in my COLOSSUS listing, so I borrowed it from UPDATVB-1 ; (but modified it to work with the major mode instead of the verb). ;----------------- --------------------------------------------------------NEWMODEA 05036 05037 05040 05041 05042 05043 05044 05045 05046 05047 5036 5 5037 3 5040 5 5041 3 5042 5 5043 3 5044 6 5045 0 5046 5047 0 0,0500 1 0,0001 0 0,0572 1 2,4677 0 0,0466 0 1,2050 0 0,0500 1 1,3565 1 13144 1 0,0572 1 EQU TS XCH TS CAF TS CAF AD TC CAD R TC * MODREG Q NEWMODEA_Q MD1 DSPCOUNT ZERO MODREG BANKCALL DSPDECVN NEWMODEA_Q ; return

; store new major mode ; save Q

;----------------- -------------------------------------------------------; POODOO - Program alarm. ; ; Turn on program alarm light and store alarm code in FAILREG. The alarm code ; is retrieved fro m the address pointed to by Q. The most recent code is stored ; in FAILREG. Olde r codes are scrolled to FAILREG+1,+2. Older CADRs are ; scrolled down. ; ; This was missing from my COLOSSUS listing, so I had to guess at the ; implementation, based upon calling references in COLOSSUS, and textual ; descriptions of normal noun 9 which retrieves alarm codes. ;----------------- --------------------------------------------------------

POODOO 05050 05051 05052 05053 05054 05055 05056 05057 05060 05061 05062 05063 05064 05065 05066 5050 5051 5052 5053 5054 5055 5056 5057 5060 5061 5062 5063 5064 5065 5066 3 5 4 7 4 5 3 5 3 5 2 3 5 0 0,0001 0,0130 0,0011 2,5066 0,0000 0,0011 0,0461 0,0462 0,0460 0,0461 0,0130 0,0000 0,0460 1,2723 0 0 0 0 0 1 1 1 0 1 1 1 0 0

EQU XCH TS CS MAS K COM TS XCH TS XCH TS IND EX CAF TS TC DS

* Q MPAC DSALMOUT NOTPALT DSALMOUT FAILREG+1 FAILREG+2 FAILREG FAILREG+1 MPAC 0 FAILREG ENDOFJOB %77377

; inclusive OR bit 9 with 1 using ; Demorgan's theorem ; turn on PROG ALM light ; scroll previous codes down

; indirectly address Q ; (gets alarm code) ; store alarm code

77377 1 NOTPALT

; 1's compliment of bit9 (PROG ALM)

;----------------- -------------------------------------------------------; PINBRNCH ; ; This is supposed to restore the DSKY display to its former state in the ; event of error. According to COLOSSUS, it works if you use "Margaret's" ; code. I don't ha ve that portion of the listing, so I just terminate ; the job, which s eems to be an acceptable work-around, even though the ; old display is n ot restored. ;----------------- -------------------------------------------------------05067 5067 0 1,2723 0 PINBRNCH TC ENDOFJOB

BANKFF_6

EQU

ORG BANK41_8 ; COLOSSUS pp. 379-380 INC L bank41_8.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank41_8.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 379-380. ;================= =========================================================

VBTSTLTS 15572 6,1572 2 0,0000 0

EQU INH INT

; heavily modified from the original Block II code... 15573 15574 15575 15576 15577 15600 15601 15602 15603 15604 15605 15606 15607 15610 15611 15612 15613 15614 15615 15616 15617 15620 6,1573 6,1574 6,1575 6,1576 4 7 4 5 0,0011 6,7623 0,0000 0,0011 0 0 0 1 CS MAS K COM TS CAF TS CS IND EX TS CCS TC CS TS TS TS CAF TS TC CAF TC CAD R DSALMOUT TSTCON1 DSALMOUT TEN ERCNT FULLDSP ERCNT DSPTAB ERCNT TSTLTS1 FULLDSP1 DSPTAB+1 DSPTAB+4 DSPTAB+6 ELEVEN NOUT FLASHON SHOLTS WAITLIST TSTLTS2 ; turn on lights ; inclusive OR light bits with 1's using ; Demorgan's theorem

6,1577 3 6,1600 6,1601 6,1602 6,1603 6,1604 6,1605 6,1606 6,1607 6,1610 6,1611 5 4 2 5 1 0 4 5 5 5

1,2060 0 0,0414 6,7621 0,0414 0,0512 0,0414 6,7600 6,7622 0,0513 0,0516 0,0520 0 TSTLTS1 1 1 1 1 0 1 0 0 0

; turn on 3 plus signs

6,1612 3 6,1613 5 6,1614 0 6,1615 3 6,1616 0 6,1617 6,1620 0

1,2061 1 0,0505 1 2,4760 1 6,7624 0 1,2232 0 15625 1 1,2723 0

TC ENDOFJOB ; DSPLOCK is left busy (from keyboard ; action) until TS TLTS3 to ensure that ; lights test will be seen.

15621 15622

6,1621 6,1622

05675 0 FULLDSP 07675 1 FULLDSP1

DS DS

%05675 %07675

; display all 8's ; display all 8's and +

; 1's Comp of UPTE L=bit3, KEY REL=bit5, oper err=bit7, PROG ALM=bit 9 15623 15624 6,1623 6,1624 77253 0 TSTCON1 00764 1 SHOLTS TSTLTS2 15625 15626 15627 15630 6,1625 3 6,1626 0 6,1627 6,1630 0 2,4131 1,3162 15631 1,2413 0 1 1 0 TSTLTS3 15631 15632 15633 15634 15635 15636 15637 15640 15641 15642 15643 6,1631 6,1632 6,1633 6,1634 2 3 7 5 0,0000 6,7623 0,0011 0,0011 0 1 0 1 DS DS EQU CAF TC CAD R TC EQU INH INT CAF MAS K TS REL INT TC CAD R TC TC TC CAD R EQU BANKCALL DSPMM KILMONON FLASHOFF POSTJUMP TSTLTS4 * ; redisplay C(MODREG) ; ; ; ; turn on kill monitor bit turn off V/N flash does RELDSP and goes to PINBRNCH if ENDIDLE is awaiting operator response %77253 %764 * CHRPRIO NOVAC TSTLTS3 TASKOVER * TSTCON1 DSALMOUT DSALMOUT ; turn off lights ; 5 sec

; called by WAITLIST

6,1635 2 6,1636 6,1637 6,1640 6,1641 6,1642 6,1643 0 0 0 0

0,0000 1 1,3565 10047 2,4536 2,4770 1,3653 13334 1 0 0 0 1 1 BANK41_9

ORG BANK40_9 ; COLOSSUS pp. 381-382 INC L bank40_9.asm ;================= ========================================================= ; DISPLAY ROUTINES (file:bank40_9.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 381-382. ;================= ========================================================= ;----------------- --------------------------------------------------------; ERROR - Error li ght reset. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 381. ;----------------- ---------------------------------------------------------

ERROR 13462 13463 5,1462 3 5,1463 5 0,0412 0 0,0501 0

EQU XCH TS

* _2122REG DSPLOCK

; restore original C(DSPLOCK), thus erro r ; light reset leaves DSPLOCK unchanged

; omitted some stu ff in COLOSSUS here 13464 13465 13466 13467 13470 13471 13472 13473 13474 13475 13476 13477 13500 13501 13502 13503 13504 13505 13506 13507 13510 13511 13512 13513 13514 13515 13516 13517 5,1464 4 5,1465 7 5,1466 5 5,1467 5,1470 5,1471 5,1472 5,1473 5,1474 5,1475 5,1476 3 5 2 2 1 6 0 6 5,7520 0 0,0011 0 0,0011 1 2,4700 0,0414 0,0000 0,0414 0,0512 1,2051 5,7502 1,2051 1 TSTAB 0 0 1 0 1 1 1 CS MAS K TS CAF TS INH INT IND EX CCS AD TC AD CS MAS K TC CS MAS K CS IND EX TS REL INT CCS TC CAF TS TS TS TC DS ERCON DSALMOUT DSALMOUT BINCON ERCNT ERCNT DSPTAB ONE ERPLUS ONE A NOTBIT12 ERCOM A NOTBIT12 A ERCNT DSPTAB ERCNT TSTAB+1 ZERO FAILREG FAILREG+1 FAILREG+2 ENDOFJOB %73777 ; clear the error codes for PROG ALM ; turn off UPTL, OPER ERR, PROG ALM

; dec 10 ; ERCNT = count

5,1477 4 5,1500 7 5,1501 0 5,1502 4 5,1503 7 5,1504 4 5,1505 5,1506 5,1507 5,1510 5,1511 5,1512 5,1513 5,1514 5,1515 2 5 2 1 0 3 5 5 5

0,0000 0 ERMINUS 5,7517 1 5,7505 0 0,0000 0 ERPLUS 5,7517 1 0,0000 0 0,0414 0,0512 0,0000 0,0414 5,7470 1,2050 0,0460 0,0461 0,0462 1 ERCOM 1 1 1 0 0 0 1 1

5,1516 0 5,1517

1,2723 0 73777 1 NOTBIT12

13520

5,1520

00504 0 ERCON BANK40_10

DS EQU

%504 *

; channel 11 bits 3,7,9

; end of PINBALL r outines ; PINBALL NOUN tab les ORG BANK42_3 INC L bank42_3.asm ; COLOSSUS pp. 263-279 ;================= ========================================================= ; PINBALL NOUN TAB LES (file:bank42_3.asm) ; ; The following ro utines are for reading the noun tables and the scale ; factor (SF) tabl es (which are in a separate bank from the rest of ; PINBALL). These reading routines are in the same bank as the tables. ; They are called by DXCH Z (translated to DXCHJUMP for Block I). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 263-279. ;================= ========================================================= ;----------------- --------------------------------------------------------; Noun table info from COLOSSUS, p.325 ; ; noun code < 40 : normal noun case ; noun code >= 40: mixed noun case ;----------------- --------------------------------------------------------; NNADTAB: ; for normal noun case, NNADTAB contains one CADR for each noun. ; +entry = noun CADR ; +0 = noun not used. ; -entry = machine CADR (E or F) to be specified. ; -1 = channel to be specified (not used for Block I); ; -0 = augment of last machine CADR supplied. ; for mixed noun c ase, NNADTAB contains one indirect address (IDADDREL) ; in low 10 bits, and the component code number in the high 5 bits. ; Examples: ; NNADTAB ; NNADTAB ; NNADTAB ; NNADTAB

= = = =

%00042 %00000 %40000 %77777

; ; ; ;

CADR for octal address 42 noun not used specify machine address augment last address

;----------------- --------------------------------------------------------; NNTYPETAB (norma l case): ; a packed table o f the form: MMMMM NNNNN PPPPP ; for the normal c ase: ; MMMMM (bits 15-11): COMPONENT CODE NUMBER (p.263) ; 00000 = 1 component ; 00001 = 2 component ; 00010 = 3 component ; X1XXX = bit4=1, decimal only ; 1XXXX = bit5=1, no load ; ; NNNNN (bits 10-6): SF ROUTINE CODE NUMBER (p.263) ; 00000 = octal only ; 00001 = straight fractional (decimal) ; 00010 = CDU degrees (XXX.XX) ; 00011 = arithmetic SF ; 00100 = arith DP1, OUT(mult by 2EXP14 at end), IN(straight ) ; 00101 = arith DP2, OUT(straight), IN(SL 7 at end) ; 00110 = Y optics degrees (XX.XXX max at 89.999) ; 00111 = arith DP3, OUT(SL 7 at end) IN(straight ) ; 01000 = whole hours in R1, whole minutes (mod 60) in R2, ; seconds (mod 60) 0XX.XX in R3 *** alarms if used wit h octal ; ; ; PPPPP (bits 5-1): SF CONSTANT CODE NUMBER (p.263) 00000 = whole, use arith

; Examples: ; NNTYPTAB ; NNTYPTAB ; NNTYPTAB ; NNTYPTAB ; NNTYPTAB

= = = = =

%00000 %02000 %04000 %00040 %04040

; ; ; ; ;

1 2 3 1 3

comp, octal only comp, octal only comp, octal only comp ,straight fractional comp ,straight fractional

;----------------- --------------------------------------------------------; NNTYPETAB (mixed case): ; a packed table o f the form: MMMMM NNNNN PPPPP ; for the mixed ca se ; MMMMM (bits ; NNNNN (bits ; PPPPP (bits (3 component): 15-11) = SF constant3 code number. 10-6) = SF constant2 code number. 5-1) = SF constant1 code number.

; for the mixed ca se (2 component): ; NNNNN (bits 10-6) = SF constant2 code number. ; PPPPP (bits 5-1) = SF constant1 code number. ; for the mixed ca se (1 component): ; PPPPP (bits 5-1) = SF constant1 code number. ;----------------- --------------------------------------------------------; IDADDTAB (mixed case only): ; there is also an indirect address table for mixed case only. ; Each entry conta ins one ECADR. IDADDREL is the relative address of ; the first of the se entries. ; There is one ent ry in this table for each component of a mixed noun. ; They are listed in order of ascending K. ;----------------- --------------------------------------------------------; RUTMXTAB (mixed case only): ; there is also a scale factor routine number table for mixed case only. ; There is one ent ry per mixed noun. The form is: QQQQQ RRRRR SSSSS ; for the 3 compon ent case ; QQQQQ (bits 15-11) = SF routine3 code number. ; RRRRR (bits 10-6) = SF routine2 code number. ; SSSSS (bits 5-1) = SF routine1 code number. ; for the 2 compon ent case ; RRRRR (bits 10-6) = SF routine2 code number. ; SSSSS (bits 5-1) = SF routine1 code number.

; ; ; ; ;

In octal display and load (oct or dec) verbs, exclude use of verbs whose component number is greater than the number of components in noun. (All machine add ress to be specified nouns are 3 component) In multi-compone nt load verbs, no mixing of octal and decimal data component words is allowed; alarm if violation.

; In decimal loads of data, 5 numerical chars must be keyed in before ; each enter; if n ot, alarm.

;----------------- ---------------------------------------------------------

; LODNNTAB ; loads NNADTEM wi th the NNADTAB entry, NNTYPTEM with the NNTYPTAB ; entry. If the no un is mixed, IDAD1TEM is loaded with the first IDADTAB ; entry, IDAD2TEM the second IDADTAB entry, IDAD3TEM the third IDADTAB ; entry, RUTMXTEM with the RUTMXTAB entry. MIXBR is set for mixed=2 ; or normal=1 noun . ; ; NOTE: in BlockII , NNADTEM = -1 means use an I/O channel instead of a ; memory address ( channel specified in NOUNCADR). Block I does not have ; I/O channels. ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 265. ;----------------- --------------------------------------------------------LODNNTAB 16114 16115 16116 16117 16120 16121 16122 16123 16124 16125 16126 16127 16130 16131 7,0114 5 7,0115 2 7,0116 3 7,0117 5 7,0120 2 7,0121 3 7,0122 5 7,0123 7,0124 7,0125 7,0126 7,0127 7,0130 7,0131 4 6 1 0 0 0 0 0,0562 0 0,0471 1 7,6210 1 0,0443 1 0,0471 1 7,6354 0 0,0444 0 0,0471 7,6161 0,0000 7,6132 7,6131 7,6131 7,6135 1 1 0 1 1 1 0 EQU TS IND EX CAF TS IND EX CAF TS CS AD CCS TC TC TC TC * GTSF_RET NOUNREG NNADTAB NNADTEM NOUNREG NNTYPTAB NNTYPTEM NOUNREG MIXCON A *+4 *+2 *+1 LODMIXNN

; save return CADR

; ; ; ; ;

was >0 +0, <0, -0,

BZMF LODMIXNN in Block II noun number G/E first mixed noun noun number G/E first mixed noun noun number G/E first mixed noun

16132 16133 16134

7,0132 3 7,0133 5 7,0134 0

1,2051 1 0,0435 0 7,6156 0 LODMIXNN

CAF TS TC EQU CAF TS IND EX CAF TS CAF MAS K TS IND EX CAF TS IND EX CAF TS IND EX CAF TS LODNLV EQU CAF AD TC DS

ONE MIXBR LODNLV * TWO MIXBR NOUNREG RUTMXTAB-40 RUTMXTEM LOW10 NNADTEM Q A IDADDTAB IDAD1TEM Q IDADDTAB+1 IDAD2TEM Q IDADDTAB+2 IDAD3TEM * ZERO GTSF_RET DXCHJUMP %50

; noun number L/ first mixed noun ; normal, +1 into MIXBR

16135 16136 16137 16140 16141 16142 16143 16144 16145 16146 16147 16150 16151 16152 16153 16154 16155

7,0135 3 7,0136 5 7,0137 2 7,0140 3 7,0141 5 7,0142 3 7,0143 7 7,0144 5 7,0145 2 7,0146 3 7,0147 5 7,0150 2 7,0151 3 7,0152 5 7,0153 2 7,0154 3 7,0155 5

1,2052 1 0,0435 0 0,0471 1 7,7054 1 0,0450 0 2,4674 0 0,0443 0 0,0001 0 0,0000 0 7,6640 0 0,0445 1 0,0001 1 7,6641 1 0,0446 1 0,0001 1 7,6642 1 0,0447 0

; mixed, +2 into MIXBR

; first mixed noun = 40

; temp

; load IDAD1TEM with first IDADDTAB entr y

; load IDAD2TEM with 2nd IDADDTAB entry

; load IDAD3TEM with 3rd IDADDTAB entry

16156 16157 16160 16161

7,0156 3 7,0157 6 7,0160 0 7,0161

1,2050 0 0,0562 0 1,3526 0 00050 1 MIXCON

; load return CADR ; return ; 1st mixed noun = 40 (DEC 40)

;----------------- --------------------------------------------------------; GTSFOUT ; On entry, SFTEMP 1 contains SFCONUM X 2. ; Loads SFTEMP1, S FTEMP2 with the DP SFOUTAB entries ; ; GTSFIN ; On entry, SFTEMP 1 contains SFCONUM X 2. ; Loads SFTEMP1, S FTEMP2 with the DP SFINTAB entries ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 266. ;----------------- --------------------------------------------------------GTSFOUT 16162 7,0162 5 0,0562 0 EQU TS * GTSF_RET

; save return CADR

16163 16164 16165 16166 16167 16170 16171 16172

7,0163 3 7,0164 5 7,0165 2 7,0166 3 7,0167 5 7,0170 2 7,0171 3 7,0172 5

0,0420 1 0,0001 0 0,0001 1 7,6570 0 0,0420 1 0,0001 1 7,6571 1 0,0421 0 SFCOM

XCH TS IND EX CAF TS IND EX CAF TS EQU CAF AD TC EQU TS XCH TS IND EX CAF TS IND EX CAF TS TC

SFTEMP1 Q Q SFOUTAB SFTEMP1 Q SFOUTAB+1 SFTEMP2 * ZERO GTSF_RET DXCHJUMP * GTSF_RET SFTEMP1 Q Q SFINTAB SFTEMP1 Q SFINTAB+1 SFTEMP2 SFCOM

; temp

16173 16174 16175

7,0173 3 7,0174 6 7,0175 0

1,2050 0 0,0562 0 1,3526 0 GTSFIN

; load return CADR ; return

16176 16177 16200 16201 16202 16203 16204 16205 16206 16207

7,0176 5 7,0177 3 7,0200 5 7,0201 2 7,0202 3 7,0203 5 7,0204 2 7,0205 3 7,0206 5 7,0207 0

0,0562 0 0,0420 1 0,0001 0 0,0001 1 7,6520 0 0,0420 1 0,0001 1 7,6521 1 0,0421 0 7,6173 1

; save return CADR

; temp

;----------------- --------------------------------------------------------; NOUN ADDRESS TAB LE (NNADTAB) ; Indexed by noun number (0-39 decimal for normal nouns). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 266. ;----------------- --------------------------------------------------------NNADTAB 16210 16211 16212 16213 16214 16215 16216 16217 16220 16221 16222 16223 16224 16225 16226 16227 16230 16231 16232 16233 16234 16235 16236 16237 16240 16241 16242 16243 16244 16245 16246 16247 16250 16251 16252 16253 16254 16255 16256 16257 7,0210 7,0211 7,0212 7,0213 7,0214 7,0215 7,0216 7,0217 7,0220 7,0221 7,0222 7,0223 7,0224 7,0225 7,0226 7,0227 7,0230 7,0231 7,0232 7,0233 7,0234 7,0235 7,0236 7,0237 7,0240 7,0241 7,0242 7,0243 7,0244 7,0245 7,0246 7,0247 7,0250 7,0251 7,0252 7,0253 7,0254 7,0255 7,0256 7,0257 00000 40000 40000 40000 00036 00000 00000 00000 00000 00460 00000 00000 00000 00000 00000 77777 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00534 00000 00000 00000 00000 00000 00000 00000 00000 00000 00035 00000 00000 00000 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 EQU DS DS DS DS DS DS DS DS DS ECA DR DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ECA DR DS DS DS DS DS DS DS DS DS ECA DR DS DS DS ; end of normal no uns ; start of mixed n ouns 16260 16261 7,0260 7,0261 00000 1 00000 1 DS DS %0 %0 ; 40 - spare ; 41 - spare * %0 %40000 %40000 %40000 %00036 %0 %0 %0 %0 FAILREG %0 %0 %0 %0 %0 %77777 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 DSPTEM1 %0 %0 %0 %0 %0 %0 %0 %0 %0 TIME2 %0 %0 %0 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; NN 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 NORMAL NOUNS not in use specify machine address (fraction a l ) specify machine address (whole) specify machine address (degrees) spare *********** TEST, CHANGE TO Z E R O spare spare spare spare alarm codes spare spare spare spare spare increment machine address spare spare spare spare spare spare spare spare spare spare prio/delay, adres, BBCON spare spare spare spare spare spare spare spare spare time of AGC clock (hrs, min, sec) spare spare spare

16262 16263 16264 16265 16266 16267 16270 16271 16272 16273 16274 16275 16276 16277 16300 16301 16302 16303 16304 16305 16306 16307 16310 16311 16312 16313 16314 16315 16316 16317 16320 16321 16322 16323 16324 16325 16326 16327 16330 16331 16332 16333 16334 16335 16336 16337 16340 16341 16342 16343 16344 16345 16346 16347 16350 16351 16352 16353

7,0262 7,0263 7,0264 7,0265 7,0266 7,0267 7,0270 7,0271 7,0272 7,0273 7,0274 7,0275 7,0276 7,0277 7,0300 7,0301 7,0302 7,0303 7,0304 7,0305 7,0306 7,0307 7,0310 7,0311 7,0312 7,0313 7,0314 7,0315 7,0316 7,0317 7,0320 7,0321 7,0322 7,0323 7,0324 7,0325 7,0326 7,0327 7,0330 7,0331 7,0332 7,0333 7,0334 7,0335 7,0336 7,0337 7,0340 7,0341 7,0342 7,0343 7,0344 7,0345 7,0346 7,0347 7,0350 7,0351 7,0352 7,0353

00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; end of mixed nou ns

%0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare

;----------------- --------------------------------------------------------; NOUN TYPE TABLE (NNTYPTAB) ; Indexed by noun number (0-39 decimal for normal nouns). ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 269. ;----------------- --------------------------------------------------------NNTYPTAB 16354 16355 16356 16357 16360 16361 16362 16363 16364 16365 16366 16367 16370 16371 16372 16373 16374 16375 7,0354 7,0355 7,0356 7,0357 7,0360 7,0361 7,0362 7,0363 7,0364 7,0365 7,0366 7,0367 7,0370 7,0371 7,0372 7,0373 7,0374 7,0375 00000 04040 04140 04102 00000 00000 00000 00000 00000 04000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 1 EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS * %0 %04040 %04140 %04102 %0 %0 %0 %0 %0 %04000 %0 %0 %0 %0 %0 %0 %0 %0 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; NN 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 NORMAL NOUNS not in use 3 component (fractional) 3 component (whole) 3 component (CDU degrees) spare spare spare spare spare 3 component, octal only spare spare spare spare spare 1 component, octal only spare spare

16376 16377 16400 16401 16402 16403 16404 16405 16406 16407 16410 16411 16412 16413 16414 16415 16416 16417 16420 16421 16422 16423

7,0376 7,0377 7,0400 7,0401 7,0402 7,0403 7,0404 7,0405 7,0406 7,0407 7,0410 7,0411 7,0412 7,0413 7,0414 7,0415 7,0416 7,0417 7,0420 7,0421 7,0422 7,0423

00000 00000 00000 00000 00000 00000 00000 00000 04000 00000 00000 00000 00000 00000 00000 00000 00000 00000 24400 00000 00000 00000

1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 0 1 1 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; end of normal no uns ; start of mixed n ouns

%0 %0 %0 %0 %0 %0 %0 %0 %04000 %0 %0 %0 %0 %0 %0 %0 %0 %0 %24400 %0 %0 %0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

spare spare spare spare spare spare spare spare 3 component, octal only spare spare spare spare spare spare spare spare spare 3 component, HMS, (dec only) spare spare spare

16424 16425 16426 16427 16430 16431 16432 16433 16434 16435 16436 16437 16440 16441 16442 16443 16444 16445 16446 16447 16450 16451 16452 16453 16454 16455 16456 16457 16460 16461 16462 16463 16464 16465 16466 16467 16470 16471 16472 16473 16474 16475 16476 16477 16500 16501 16502 16503 16504 16505 16506 16507 16510 16511 16512 16513 16514 16515 16516 16517

7,0424 7,0425 7,0426 7,0427 7,0430 7,0431 7,0432 7,0433 7,0434 7,0435 7,0436 7,0437 7,0440 7,0441 7,0442 7,0443 7,0444 7,0445 7,0446 7,0447 7,0450 7,0451 7,0452 7,0453 7,0454 7,0455 7,0456 7,0457 7,0460 7,0461 7,0462 7,0463 7,0464 7,0465 7,0466 7,0467 7,0470 7,0471 7,0472 7,0473 7,0474 7,0475 7,0476 7,0477 7,0500 7,0501 7,0502 7,0503 7,0504 7,0505 7,0506 7,0507 7,0510 7,0511 7,0512 7,0513 7,0514 7,0515 7,0516 7,0517

00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; end of mixed nou ns

%0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare

;----------------- --------------------------------------------------------; SCALE FACTOR INP UT TABLE (SFINTAB) ; Indexed by SF co nstant code number x 2 PPPPP (0-19 decimal; 0-23 octal) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 272. ;----------------- --------------------------------------------------------SFINTAB 16520 16521 16522 16523 16524 16525 16526 16527 16530 16531 16532 16533 16534 16535 16536 16537 16540 16541 16542 16543 16544 16545 16546 16547 16550 16551 16552 16553 16554 16555 16556 16557 16560 16561 16562 16563 16564 16565 16566 16567 7,0520 7,0521 7,0522 7,0523 7,0524 7,0525 7,0526 7,0527 7,0530 7,0531 7,0532 7,0533 7,0534 7,0535 7,0536 7,0537 7,0540 7,0541 7,0542 7,0543 7,0544 7,0545 7,0546 7,0547 7,0550 7,0551 7,0552 7,0553 7,0554 7,0555 7,0556 7,0557 7,0560 7,0561 7,0562 7,0563 7,0564 7,0565 7,0566 7,0567 00006 1 03240 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS * %00006 %03240 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000

; 00 - whole, DP time (sec) ; 00 ; 01 - spare ; 01 ; 02 - CDU degrees, Y optics degrees ; 02 (SFCONs in DEGINSF, OPTDEGIN ; 03 ; 03 ; 04 ; 04 ; 05 ; 05 ; 06 ; 06 ; 07 ; 07 ; 10 ; 10 ; 11 ; 11 ; 12 ; 12 ; 13 ; 13 ; 14 ; 14 ; 15 ; 15 ; 16 ; 16 ; 17 ; 17 ; 20 ; 20 ; 21 ; 21 ; 22 ; 22 ; 23 ; 23

;----------------- --------------------------------------------------------; SCALE FACTOR OUT PUT TABLE (SFOUTAB) ; Indexed by SF co nstant code number x 2 PPPPP (0-19 decimal; 0-23 octal) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 273. ;----------------- --------------------------------------------------------SFOUTAB 16570 16571 16572 16573 16574 16575 7,0570 7,0571 7,0572 7,0573 7,0574 7,0575 05174 0 13261 0 00000 1 00000 1 00000 1 00000 1 EQU DS DS DS DS DS DS * %05174 %13261 %00000 %00000 %00000 %00000

; 00 - whole, DP time (sec) ; 00 ; 01 - spare ; 01 ; 02 - CDU degrees, Y optics degrees ; 02 (SFCONs in DEGOURSF, OPTDEGOUT

16576 16577 16600 16601 16602 16603 16604 16605 16606 16607 16610 16611 16612 16613 16614 16615 16616 16617 16620 16621 16622 16623 16624 16625 16626 16627 16630 16631 16632 16633 16634 16635 16636 16637

7,0576 7,0577 7,0600 7,0601 7,0602 7,0603 7,0604 7,0605 7,0606 7,0607 7,0610 7,0611 7,0612 7,0613 7,0614 7,0615 7,0616 7,0617 7,0620 7,0621 7,0622 7,0623 7,0624 7,0625 7,0626 7,0627 7,0630 7,0631 7,0632 7,0633 7,0634 7,0635 7,0636 7,0637

00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

%00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000 %00000

; 03 ; 03 ; 04 ; 04 ; 05 ; 05 ; 06 ; 06 ; 07 ; 07 ; 10 ; 10 ; 11 ; 11 ; 12 ; 12 ; 13 ; 13 ; 14 ; 14 ; 15 ; 15 ; 16 ; 16 ; 17 ; 17 ; 20 ; 20 ; 21 ; 21 ; 22 ; 22 ; 23 ; 23

; SCALE FACTOR INP UT ROUTINE TABLE is on pp. 342, 343 of COLOSSUS ; SCALE FACTOR OUT PUT ROUTINE TABLE is on p. 329 of COLOSSUS ;----------------- --------------------------------------------------------; MIXED NOUN ADDRE SS TABLE (IDADDTAB) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 274. ;----------------- --------------------------------------------------------; ** currently, th e table is not populated ** IDADDTAB 16640 16641 16642 16643 16644 16645 16646 16647 16650 16651 16652 16653 16654 16655 16656 16657 7,0640 7,0641 7,0642 7,0643 7,0644 7,0645 7,0646 7,0647 7,0650 7,0651 7,0652 7,0653 7,0654 7,0655 7,0656 7,0657 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS * %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; 40 - spare component ; 40 - spare component ; 40 - spare component ; 41 - spare component ; 41 - spare component ; 41 - spare component ; 42 - spare component ; 42 - spare component ; 42 - spare component ; 43 - spare component ; 43 - spare component ; 43 - spare component ; 44 - spare component ; 44 - spare component ; 44 - spare component ; 45 - spare component

16660 16661 16662 16663 16664 16665 16666 16667 16670 16671 16672 16673 16674 16675 16676 16677 16700 16701 16702 16703 16704 16705 16706 16707 16710 16711 16712 16713 16714 16715 16716 16717 16720 16721 16722 16723 16724 16725 16726 16727 16730 16731 16732 16733 16734 16735 16736 16737 16740 16741 16742 16743 16744 16745 16746 16747 16750 16751 16752 16753 16754 16755 16756 16757 16760

7,0660 7,0661 7,0662 7,0663 7,0664 7,0665 7,0666 7,0667 7,0670 7,0671 7,0672 7,0673 7,0674 7,0675 7,0676 7,0677 7,0700 7,0701 7,0702 7,0703 7,0704 7,0705 7,0706 7,0707 7,0710 7,0711 7,0712 7,0713 7,0714 7,0715 7,0716 7,0717 7,0720 7,0721 7,0722 7,0723 7,0724 7,0725 7,0726 7,0727 7,0730 7,0731 7,0732 7,0733 7,0734 7,0735 7,0736 7,0737 7,0740 7,0741 7,0742 7,0743 7,0744 7,0745 7,0746 7,0747 7,0750 7,0751 7,0752 7,0753 7,0754 7,0755 7,0756 7,0757 7,0760

00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

%0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; 45 - spare component ; 45 - spare component ; 46 - spare component ; 46 - spare component ; 46 - spare component ; 47 - spare component ; 47 - spare component ; 47 - spare component ; 48 - spare component ; 48 - spare component ; 48 - spare component ; 49 - spare component ; 49 - spare component ; 49 - spare component ; 50 - spare component ; 50 - spare component ; 50 - spare component ; 51 - spare component ; 51 - spare component ; 51 - spare component ; 52 - spare component ; 52 - spare component ; 52 - spare component ; 53 - spare component ; 53 - spare component ; 53 - spare component ; 54 - spare component ; 54 - spare component ; 54 - spare component ; 55 - spare component ; 55 - spare component ; 55 - spare component ; 56 - spare component ; 56 - spare component ; 56 - spare component ; 57 - spare component ; 57 - spare component ; 57 - spare component ; 58 - spare component ; 58 - spare component ; 58 - spare component ; 59 - spare component ; 59 - spare component ; 59 - spare component ; 60 - spare component ; 60 - spare component ; 60 - spare component ; 61 - spare component ; 61 - spare component ; 61 - spare component ; 62 - spare component ; 62 - spare component ; 62 - spare component ; 63 - spare component ; 63 - spare component ; 63 - spare component ; 64 - spare component ; 64 - spare component ; 64 - spare component ; 65 - spare component ; 65 - spare component ; 65 - spare component ; 66 - spare component ; 66 - spare component ; 66 - spare component

16761 16762 16763 16764 16765 16766 16767 16770 16771 16772 16773 16774 16775 16776 16777 17000 17001 17002 17003 17004 17005 17006 17007 17010 17011 17012 17013 17014 17015 17016 17017 17020 17021 17022 17023 17024 17025 17026 17027 17030 17031 17032 17033 17034 17035 17036 17037 17040 17041 17042 17043 17044 17045 17046 17047 17050 17051 17052 17053 17054 17055 17056 17057 17060 17061 17062

7,0761 7,0762 7,0763 7,0764 7,0765 7,0766 7,0767 7,0770 7,0771 7,0772 7,0773 7,0774 7,0775 7,0776 7,0777 7,1000 7,1001 7,1002 7,1003 7,1004 7,1005 7,1006 7,1007 7,1010 7,1011 7,1012 7,1013 7,1014 7,1015 7,1016 7,1017 7,1020 7,1021 7,1022 7,1023 7,1024 7,1025 7,1026 7,1027 7,1030 7,1031 7,1032 7,1033 7,1034 7,1035 7,1036 7,1037 7,1040 7,1041 7,1042 7,1043 7,1044 7,1045 7,1046 7,1047 7,1050 7,1051 7,1052 7,1053 7,1054 7,1055 7,1056 7,1057 7,1060 7,1061 7,1062

00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

%0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; 67 - spare component ; 67 - spare component ; 67 - spare component ; 68 - spare component ; 68 - spare component ; 68 - spare component ; 69 - spare component ; 69 - spare component ; 69 - spare component ; 70 - spare component ; 70 - spare component ; 70 - spare component ; 71 - spare component ; 71 - spare component ; 71 - spare component ; 72 - spare component ; 72 - spare component ; 72 - spare component ; 73 - spare component ; 73 - spare component ; 73 - spare component ; 74 - spare component ; 74 - spare component ; 74 - spare component ; 75 - spare component ; 75 - spare component ; 75 - spare component ; 76 - spare component ; 76 - spare component ; 76 - spare component ; 77 - spare component ; 77 - spare component ; 77 - spare component ; 78 - spare component ; 78 - spare component ; 78 - spare component ; 79 - spare component ; 79 - spare component ; 79 - spare component ; 80 - spare component ; 80 - spare component ; 80 - spare component ; 81 - spare component ; 81 - spare component ; 81 - spare component ; 82 - spare component ; 82 - spare component ; 82 - spare component ; 83 - spare component ; 83 - spare component ; 83 - spare component ; 84 - spare component ; 84 - spare component ; 84 - spare component ; 85 - spare component ; 85 - spare component ; 85 - spare component ; 86 - spare component ; 86 - spare component ; 86 - spare component ; 87 - spare component ; 87 - spare component ; 87 - spare component ; 88 - spare component ; 88 - spare component ; 88 - spare component

17063 17064 17065 17066 17067 17070 17071 17072 17073 17074 17075 17076 17077 17100 17101 17102 17103 17104 17105 17106 17107 17110 17111 17112 17113 17114 17115 17116 17117 17120 17121 17122 17123

7,1063 7,1064 7,1065 7,1066 7,1067 7,1070 7,1071 7,1072 7,1073 7,1074 7,1075 7,1076 7,1077 7,1100 7,1101 7,1102 7,1103 7,1104 7,1105 7,1106 7,1107 7,1110 7,1111 7,1112 7,1113 7,1114 7,1115 7,1116 7,1117 7,1120 7,1121 7,1122 7,1123

00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1 00000 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

%0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; 89 - spare component ; 89 - spare component ; 89 - spare component ; 90 - spare component ; 90 - spare component ; 90 - spare component ; 91 - spare component ; 91 - spare component ; 91 - spare component ; 92 - spare component ; 92 - spare component ; 92 - spare component ; 93 - spare component ; 93 - spare component ; 93 - spare component ; 94 - spare component ; 94 - spare component ; 94 - spare component ; 95 - spare component ; 95 - spare component ; 95 - spare component ; 96 - spare component ; 96 - spare component ; 96 - spare component ; 97 - spare component ; 97 - spare component ; 97 - spare component ; 98 - spare component ; 98 - spare component ; 98 - spare component ; 99 - spare component ; 99 - spare component ; 99 - spare component

DS %0 DS %0 DS %0 ; end of mixed nou n address table

;----------------- --------------------------------------------------------; MIXED NOUN SCALE FACTOR ROUTINE TABLE (RUTMXTAB) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 278. ;----------------- --------------------------------------------------------; ** currently, th e table is not populated ** RUTMXTAB 17124 17125 17126 17127 17130 17131 17132 17133 17134 17135 17136 17137 17140 17141 17142 17143 17144 17145 17146 17147 17150 17151 17152 17153 17154 17155 17156 17157 17160 17161 17162 7,1124 7,1125 7,1126 7,1127 7,1130 7,1131 7,1132 7,1133 7,1134 7,1135 7,1136 7,1137 7,1140 7,1141 7,1142 7,1143 7,1144 7,1145 7,1146 7,1147 7,1150 7,1151 7,1152 7,1153 7,1154 7,1155 7,1156 7,1157 7,1160 7,1161 7,1162 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS * %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0 %0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare

17163 17164 17165 17166 17167 17170 17171 17172 17173 17174 17175 17176 17177 17200 17201 17202 17203 17204 17205 17206 17207 17210 17211 17212 17213 17214 17215 17216 17217

7,1163 7,1164 7,1165 7,1166 7,1167 7,1170 7,1171 7,1172 7,1173 7,1174 7,1175 7,1176 7,1177 7,1200 7,1201 7,1202 7,1203 7,1204 7,1205 7,1206 7,1207 7,1210 7,1211 7,1212 7,1213 7,1214 7,1215 7,1216 7,1217

00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; DS %0 ; ; end of mixed nou n scale factor routine BANK42_4 EQU *

71 - spare 72 - spare 73 - spare 74 - spare 75 - spare 76 - spare 77 - spare 78 - spare 79 - spare 80 - spare 81 - spare 82 - spare 83 - spare 84 - spare 85 - spare 86 - spare 87 - spare 88 - spare 89 - spare 90 - spare 91 - spare 92 - spare 93 - spare 94 - spare 95 - spare 96 - spare 97 - spare 98 - spare 99 - spare table

; extended verb ta bles ORG BANK43_1 INC L bank43_1.asm ; COLOSSUS pp. 230-232 ;================= ========================================================= ; DISPLAY ROUTINES (file:bank43_1.asm) ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, pp . 230. ;================= ========================================================= ;----------------- --------------------------------------------------------; GOEXTVB -- EXTEN DED VERBS ; ; Adapted from the AGC Block II COLOSSUS rev 249 assembly listing, ; Oct 28, 1968, p. 230. ;----------------- --------------------------------------------------------GOEXTVB 2 0 0 0 0 1 0 , 0 0 0 0 2 0,0130 1 2 0 0 0 1 1 0 , 0 0 0 1 0 10,6002 0 LST2FAN 20002 20003 20004 20005 20006 20007 20010 20011 20012 20013 20014 20015 20016 20017 20020 20021 20022 20023 20024 20025 20026 20027 20030 20031 20032 20033 20034 20035 20036 20037 20040 10,0002 10,0003 10,0004 10,0005 10,0006 10,0007 10,0010 10,0011 10,0012 10,0013 10,0014 10,0015 10,0016 10,0017 10,0020 10,0021 10,0022 10,0023 10,0024 10,0025 10,0026 10,0027 10,0030 10,0031 10,0032 10,0033 10,0034 10,0035 10,0036 10,0037 10,0040 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 EQU IND EX TC EQU TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC * MPAC LST2FAN * ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END

; verb-40 is in MPAC ; fan as before

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

VB40 VB41 VB42 VB43 VB44 VB45 VB46 VB47 VB48 VB49 VB50 VB51 VB52 VB53 VB54 VB55 VB56 VB57 VB58 VB59 VB60 VB61 VB62 VB63 VB64 VB65 VB66 VB67 VB68 VB69 VB70

spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare

20041 20042 20043 20044 20045 20046 20047 20050 20051 20052 20053 20054 20055 20056 20057 20060 20061 20062 20063 20064 20065 20066 20067 20070 20071 20072 20073 20074 20075

10,0041 10,0042 10,0043 10,0044 10,0045 10,0046 10,0047 10,0050 10,0051 10,0052 10,0053 10,0054 10,0055 10,0056 10,0057 10,0060 10,0061 10,0062 10,0063 10,0064 10,0065 10,0066 10,0067 10,0070 10,0071 10,0072 10,0073 10,0074 10,0075

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076 10,6076

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC TC

ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END ALM_END

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

VB71 VB72 VB73 VB74 VB75 VB76 VB77 VB78 VB79 VB80 VB81 VB82 VB83 VB84 VB85 VB86 VB87 VB88 VB89 VB90 VB91 VB92 VB93 VB94 VB95 VB96 VB97 VB98 VB99

spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare spare

20076 10,0076 0 20077 10,0077 0 20100 10,0100

ALM_END 2,4701 0 1,3653 1 GOPIN 05067 0

EQU TC TC FCA DR

* FALTON POSTJUMP PINBRNCH

; turn on operator error light

BANK43_2

EQU

;----------------- --------------------------------------------------------; TEST JOBS & TASK S ;----------------- --------------------------------------------------------ORG BANKFF_6

;----------------- --------------------------------------------------------; MAJOR MODES ;----------------- --------------------------------------------------------ORG BANK11

;----------------- --------------------------------------------------------; P00 CMC IDLE PRO GRAM ; ; Does nothing ;----------------- --------------------------------------------------------P00 EQU *

; Start any jobs o r tasks needed at AGC initialization. 22000 22001 22002 22003 1 1 , 0 0 0 0 3 11,6004 0 1 1 , 0 0 0 1 0 1,2232 0 11,0002 22005 1 1 1 , 0 0 0 3 0 1,2723 0 CAF TC CAD R TC time1 WAITLIST task1 ENDOFJOB ; add a test task ; 14-bit task address

; TEST CODE - task started by P00 22004 11,0004 01750 1 time1 task1 2 2 0 0 5 1 1 , 0 0 0 5 3 11,6011 1 2 2 0 0 6 1 1 , 0 0 0 6 0 1,3162 1 22007 11,0007 22012 1 22010 11,0010 0 1,2413 0 DS EQU XCH TC CAD R TC 1000 * prio1 NOVAC job1 TASKOVER ; 10 seconds

; job priority ; 14 bit job address

; TEST CODE - job started by task 22011 11,0011 00003 1 prio1 job1 22012 11,0012 3 1,2050 0 DS EQU CAF %3 * ZERO ; lowest priority

22013 22014 22015 22016

11,0013 11,0014 11,0015 11,0016

6 6 5 0

0,0053 1,2051 0,0053 1,2723

1 1 1 0

AD AD TS TC

%53 ONE %53 ENDOFJOB

; incr data at this address

;----------------- --------------------------------------------------------; P01 DEMO PROGRAM ; ; Calls pinball: v erb 1, noun 4. ;----------------- --------------------------------------------------------22017 11,0017 22020 11,0020 22021 11,0021 00204 1 nvcode1 22024 1 restart1_addr 00042 1 tcadr1 DS DS DS %0204 P01_restart %42 ; verb 01, noun 04

P01 2 2 0 2 2 1 1 , 0 0 2 2 3 11,6021 1 2 2 0 2 3 1 1 , 0 0 2 3 5 0,0132 1

EQU CAF TS

* tcadr1 MPAC+2

; load 'machine address to be specified'

P01_restart 2 2 0 2 4 1 1 , 0 0 2 4 3 11,6017 1 2 2 0 2 5 1 1 , 0 0 2 5 0 2,4503 0 2 2 0 2 6 1 1 , 0 0 2 6 0 11,6030 1 2 2 0 2 7 1 1 , 0 0 2 7 0 1,2723 0 2 2 0 3 0 1 1 , 0 0 3 0 3 11,6020 0 2 2 0 3 1 1 1 , 0 0 3 1 0 2,5001 0 22032 11,0032 0 1,2723 0

EQU CAF TC TC TC CAF TC TC

* nvcode1 NVSUB *+2 ENDOFJOB restart1_addr NVSUBUSY ENDOFJOB ; display busy ; execution of verb/noun succeeded

; go to sleep until display released ; error: another job is already waiting

;----------------- --------------------------------------------------------; P02 DEMO PROGRAM ; ; Calls pinball: v erb 21, noun 2. ; ; Sleeps if DSKY i s busy until KEYREL. Executes verb 21, noun 2 to do ; an external load . Then it sleeps with ENDIDLE until the user loads ; the data or term inatest the load with PROCEED or TERMINATE. ; NOTE: routines t hat call ENDIDLE must be in fixed-switchable memory ;----------------- --------------------------------------------------------22033 11,0033 22034 11,0034 22035 11,0035 05202 1 nvcode2 22040 0 restart2_addr 00042 1 tcadr2 DS DS DS %05202 P02_restart %42 ; verb 21, noun 02

P02 2 2 0 3 6 1 1 , 0 0 3 6 3 11,6035 1 2 2 0 3 7 1 1 , 0 0 3 7 5 0,0132 1 P02_restart 2 2 0 4 0 1 1 , 0 0 4 0 3 11,6033 1 2 2 0 4 1 1 1 , 0 0 4 1 0 2,4503 0 2 2 0 4 2 1 1 , 0 0 4 2 0 11,6044 1 2 2 0 4 3 1 1 , 0 0 4 3 0 11,6047 1 2 2 0 4 4 1 1 , 0 0 4 4 3 11,6034 0 2 2 0 4 5 1 1 , 0 0 4 5 0 2,5001 0 2 2 0 4 6 1 1 , 0 0 4 6 0 1,2723 0 P02_wait 22047 22050 22051 22052 22053 22054 11,0047 11,0050 11,0051 11,0052 11,0053 11,0054 0 2,4541 0 0 11,6060 1 0 11,6055 1 3 1,2051 1 5 0,0043 0 0 1,2723 0 P02_pwd 22055 11,0055 3 22056 11,0056 5 22057 11,0057 0 1,2052 1 0,0043 0 1,2723 0 P02_ter 22060 11,0060 3 22061 11,0061 5 22062 11,0062 0 1,2053 0 0,0043 0 1,2723 0

EQU CAF TS EQU CAF TC TC TC CAF TC TC EQU TC TC TC CAF TS TC EQU CAF TS TC EQU CAF TS TC

* tcadr2 MPAC+2 * nvcode2 NVSUB *+2 P02_wait restart2_addr NVSUBUSY ENDOFJOB * ENDIDLE P02_ter P02_pwd ONE %43 ENDOFJOB * TWO %43 ENDOFJOB * THREE %43 ENDOFJOB ; display busy ; execution of verb/noun succeeded

; go to sleep until display released ; another job is already sleeping

; ; ; ;

terminate proceed without data data in set loc=1

; proceed without data ; set loc=2

; terminate ; set loc=3

;----------------- --------------------------------------------------------; P03 DEMO PROGRAM ;

; Nearly identical to P02, except that the job does not go to sleep ; waiting for the load with ENDIDLE. Instead, it busy-waits on LOADSTAT. ; NOTE: routines t hat call ENDIDLE must be in fixed-switchable memory ;----------------- --------------------------------------------------------22063 11,0063 22064 11,0064 22065 11,0065 05202 1 nvcode3 22070 0 restart3_addr 00042 1 tcadr3 DS DS DS %05202 P03_restart %42 ; verb 21, noun 02

P03 2 2 0 6 6 1 1 , 0 0 6 6 3 11,6065 1 2 2 0 6 7 1 1 , 0 0 6 7 5 0,0132 1 P03_restart 2 2 0 7 0 1 1 , 0 0 7 0 3 11,6063 1 2 2 0 7 1 1 1 , 0 0 7 1 0 2,4503 0 2 2 0 7 2 1 1 , 0 0 7 2 0 11,6074 1 2 2 0 7 3 1 1 , 0 0 7 3 0 11,6077 1 2 2 0 7 4 1 1 , 0 0 7 4 3 11,6064 0 2 2 0 7 5 1 1 , 0 0 7 5 0 2,5001 0 2 2 0 7 6 1 1 , 0 0 7 6 0 1,2723 0 P03_wait 22077 22100 in 22101 22102 22103 1 1 , 0 0 7 7 1 0,0503 0 1 1 , 0 1 0 0 0 11,6115 1 1 1 , 0 1 0 1 0 11,6107 1 1 1 , 0 1 0 2 0 11,6120 1 1 1 , 0 1 0 3 3 0,0000 1 1,2051 1 0,0043 0 1,2723 0 P03_yield 22107 11,0107 3 22110 11,0110 6 22111 11,0111 5 1,2051 1 0,0043 0 0,0043 0

EQU CAF TS EQU CAF TC TC TC CAF TC TC EQU CCS TC TC TC NOO P CAF TS TC EQU CAF AD TS CCS TC TC

* tcadr3 MPAC+2 * nvcode3 NVSUB *+2 P03_wait restart3_addr NVSUBUSY ENDOFJOB * LOADSTAT P03_pwd P03_yield P03_ter ; display busy ; execution of verb/noun succeeded

; go to sleep until display released ; another job is already sleeping

; >0, verb "proceed w/o data" has been k e y e d ; +0, waiting for data ; <0, verb "terminate" has been keyed in ; -0, load has been completed ; data in ; set loc=1

22104 11,0104 3 22105 11,0105 5 22106 11,0106 0

ONE %43 ENDOFJOB * ONE %43 %43 newJob CHANG1 P03_wait * TWO %43 ENDOFJOB * THREE %43 ENDOFJOB

; incr loc while busy-waiting ; yield to higher priority job? ; yes ; no, keep busy-waiting ; proceed without data ; set loc=2

2 2 1 1 2 1 1 , 0 1 1 2 1 0,0307 1 2 2 1 1 3 1 1 , 0 1 1 3 0 1,2733 1 2 2 1 1 4 1 1 , 0 1 1 4 0 11,6077 1 P03_pwd 22115 11,0115 3 22116 11,0116 5 22117 11,0117 0 1,2052 1 0,0043 0 1,2723 0 P03_ter 22120 11,0120 3 22121 11,0121 5 22122 11,0122 0 1,2053 0 0,0043 0 1,2723 0

EQU CAF TS TC EQU CAF TS TC

; terminate ; set loc=3

;----------------- --------------------------------------------------------; P04 DEMO PROGRAM ; ; Calls pinball: m onitor verb 11, noun 04. ;----------------- --------------------------------------------------------22123 11,0123 22124 11,0124 22125 11,0125 22126 11,0126 02604 1 nvcode4 22131 1 restart4_addr 00042 1 tcadr4 ;mon_option 02206 1 mon_option DS DS DS DS DS %02604 P04_restart %42 %6 %2206 ; verb 11, noun 04

P04 2 2 1 2 7 1 1 , 0 1 2 7 3 11,6125 1 2 2 1 3 0 1 1 , 0 1 3 0 5 0,0132 1

EQU CAF TS

* tcadr4 MPAC+2

; load 'machine address to be specified'

P04_restart 2 2 1 3 1 1 1 , 0 1 3 1 3 11,6126 1 2 2 1 3 2 1 1 , 0 1 3 2 5 0,0564 0 2 2 1 3 3 1 1 , 0 1 3 3 3 11,6123 1 2 2 1 3 4 1 1 , 0 1 3 4 0 2,4507 1 2 2 1 3 5 1 1 , 0 1 3 5 0 11,6137 1 2 2 1 3 6 1 1 , 0 1 3 6 0 1,2723 0 2 2 1 3 7 1 1 , 0 1 3 7 3 11,6124 0 2 2 1 4 0 1 1 , 0 1 4 0 0 2,5001 0

EQU CAF TS CAF TC TC TC CAF TC

* mon_option NVSUB_L nvcode4 NVMONOPT *+2 ENDOFJOB restart4_addr NVSUBUSY

; paste verb 09, blank R2, R3

; was NVSUB ; display busy ; execution of verb/noun succeeded

; go to sleep until display released

22141 11,0141 0

1,2723 0

TC

ENDOFJOB

; error: another job is already waiting

;----------------- --------------------------------------------------------; P78 DEMO PROGRAM ; ;----------------- --------------------------------------------------------P78 22142 22143 22144 22145 22146 11,0142 11,0143 11,0144 11,0145 11,0146 3 6 6 5 0 1,2050 0,0051 1,2051 0,0051 1,2723 0 0 1 0 0 EQU CAF AD AD TS TC * ZERO %51 ONE %51 ENDOFJOB

; incr data at this address

;----------------- --------------------------------------------------------; P79 DEMO PROGRAM ; ;----------------- --------------------------------------------------------P79 22147 22150 22151 22152 22153 11,0147 11,0150 11,0151 11,0152 11,0153 3 6 6 5 0 1,2050 0,0052 1,2051 0,0052 1,2723 0 0 1 0 0 EQU CAF AD AD TS TC * ZERO %52 ONE %52 ENDOFJOB

; incr data at this address

A s s e m b l y c o m p lete. Errors = 0 Symbol table: BANK0 MAXDELAY TSKADDR WL_IN_saveQ WL_AT_saveQ WL_AT_timeLeft WL_T3_oldBank WL_ST_newTime WL_RT_runAddr WL_RM_taskPtr2 WL_IS_newTime WL_IS_taskPtr MAXJOBS MPAC BANKSET JOBPRIOBASE JREC2 JREC5 LOCCTR newJob EX_JW_CADR EX_JW_jobPtr2 EX_AJ_loopCnt EX_AJ_field EX_IN_loopCnt EX_IN_field EX_MN_field EX_RM_jobPtr EX_RM_loopCnt EX_RM_findx EX_IS_newLoc EX_IS_jobPtr2 ITEMP1 ITEMP2 ITEMP3 NEWPRIO ITEMP5 NEWLOCP1 RUPTREG2 KEYTEMP1 FLAGFILL INTB15P BLANKRET WDRET ADDRWD CHAR FIXLOC SGNON DECTEM SFTEMP1 SFTEMP2 SIGNRET INDEXLOC MPTEMP

000057 027340 000001 000075 000100 000103 000106 000111 000114 000117 000122 000125 000007 000130 000141 000144 000177 000246 000300 000307 000312 000315 000320 000323 000326 000331 000334 000337 000342 000345 000350 000353 000356 000357 000360 000360 000362 000363 000366 000370 000405 000411 000411 000412 000413 000414 000415 000417 000417 000420 000421 000422 000425 000432

MAXTASK MAXTIMEOUT TRECSZ WL_IN_taskPtr WL_AT_taskPtr WL_AT_loopCnt WL_ST_saveQ WL_ST_loopCnt WL_RM_saveQ WL_RM_loopCnt WL_IS_newAddr WL_IS_taskPtr2 JRECSZ MODE PUSHLOC JREC0 JREC3 JREC6 CHGJOB EX_JW_saveQ EX_JW_foundit EX_JW_fndIndx EX_AJ_jobPrio EX_AJ_findx EX_IN_jobPtr EX_IN_findx EX_MN_findx EX_RM_jobPtr2 EX_RM_retval EX_IS_newPrio EX_IS_saveQ EX_IS_loopCnt WAITEXIT WAITBANK RUPTSTOR ITEMP4 NEWLOC NEWJOB RUPTREG3 DSRUPTEM EMDOT DSEXIT INTBIT15 DECRET POLISH ERCNT OVFIND NOUNTEM SGNOFF HITEMIN LOWTEMIN BUF SWWORD DMPNTEMP

00000 7 01044 0 00000 2 00007 6 00010 1 00010 4 00010 7 00011 2 00011 5 00012 0 00012 3 00012 6 00001 5 00013 7 00014 2 00014 5 00021 4 00026 3 00000 1 00031 0 00031 3 00031 6 00032 1 00032 4 00032 7 00033 2 00033 5 00034 0 00034 3 00034 6 00035 1 00035 4 00035 6 00035 7 00036 0 00036 1 00036 2 00036 4 00036 7 00037 0 00040 5 00041 1 00041 2 00041 2 00041 4 00041 4 00041 6 00041 7 00042 0 00042 0 00042 1 00042 5 00042 5 00043 2

MAXVAL TSKTIME WL_taskList WL_IN_loopCnt WL_AT_newTime WL_T3_saveQ WL_ST_taskPtr WL_RT_saveQ WL_RM_taskPtr WL_RM_retval WL_IS_saveQ WL_IS_loopCnt EX_currentJob LOC PRIORITY JREC1 JREC4 EX_jobList KEEPJOB EX_JW_loopCnt EX_JW_jobPtr EX_AJ_saveQ EX_AJ_jobPtr EX_IN_saveQ EX_IN_recIndex EX_MN_runAddr EX_RM_saveQ EX_RM_savePtr EX_RM_field EX_IS_newPrioB EX_IS_jobPtr FLAGWRD5 EXECTEM1 EXECTEM2 WAITADR WAITTEMP ITEMP6 RUPTREG1 RUPTREG4 STATE STATEXIT EXITEM WRDRET _2122REG UPDATRET DECOUNT VBUF DISTEM NVTEMP CODE MIXTEMP BUF2 SWBIT DOTINC

037777 000000 000057 000077 000102 000105 000110 000113 000116 000121 000124 000127 000130 000140 000143 000162 000231 000300 000000 000311 000314 000317 000322 000325 000330 000333 000336 000341 000344 000347 000352 000355 000356 000357 000360 000361 000363 000365 000370 000371 000407 000411 000412 000412 000414 000414 000417 000417 000420 000421 000422 000430 000426 000433

DVSIGN DOTRET WDCNT MAXDVSW MIXBR DSREL IDADDTEM TEM4 FREERET SEPMNRET NNADTEM IDAD2TEM DEXDEX RTNSAVER NVWORD CADRFLSH FAILREG DSPCNT VERBREG YREG YREGLP LOTEMOUT REQRET NOUT MONSAVE1 NVQTEM CADRSTOR DSPTEM1 NORMTEM1 DSRUPTSW DK_IN_saveQ KP_MPAC REQ_Q SFRUTMIX_L GTSF_RET NVSUB_A FLASHRET SHORTMP_A ADDRWD1 KEYRET BJRET PJA BCA MBCA EXTENDER ERRUPT UPRUPT goER goUP NEG1 ONE FOUR SEVEN BIT15 BIT12 BIT9 BIT6 BIT3 LOW7 OCT1400 CLRMEM CLRMEM_VAL CLRMEM_WC goMAIN V37XEQ WL_tskLstStart WL_numTasks1 WL_maxTimeOut WAITLIST WL_AT_mkFirst WL_AT_done WL_RT_loop WL_RT_done WL_ST_setT3 WL_insert WL_IS_insRec WL_RM_loop EX_DUMMY_PRIO EX_jobRecSize EX_jobLstEnd1 EX_changeJob EX_MN_findJob EX_MN_runIt CHANG1 EX_MN_mvRec JOBWAKE EX_JW_bumpPtr

000433 000434 000434 000435 000435 000436 000437 000441 000441 000441 000443 000446 000437 000442 000452 000455 000460 000465 000470 000473 000476 000477 000502 000505 000510 000526 000531 000534 000534 000543 000546 000551 000554 000557 000562 000565 000570 000573 000576 000601 000604 000607 000612 000615 005777 002010 002024 002036 002043 002046 002051 002054 002057 002062 002065 002070 002073 002076 002101 002104 002107 002050 002123 002126 002153 002175 002200 002203 002232 002306 002343 002364 002414 002461 002473 002552 002603 002643 002646 002651 002654 002662 002720 002733 002757 003003 003041

ESCAPE DVNORMCT INREL POLYCNT TEM1 TEM2 TEM3 LSTPTR DSPWDRET TEM5 NNTYPTEM IDAD3TEM DEX1 TERM1TMP MARXNV CADRMARK MINDEX DSPCOUNT NOUNREG ZREG HITEMOUT MODREG LOADSTAT NOUNCADR MONSAVE2 NVBNKTEM DSPLIST DSPTEM2 OPTIONX T4RET LXCH_LPRET DPTEST_A SETNCADR_Q SFCONUM_L FR_RETQ ENDIDLE_L PASTE_TMP SHORTMP_OVFL MATH_Q SAVEQ PJBANK BCBANK MBCBANK DCBANK GOPROG DSRUPT endRUPT goDS ofbit NEG2 TWO FIVE TEN BIT14 BIT11 BIT8 BIT5 BIT2 bankAddr NOUTCON CLRMEM_CHK TIME3 V37BANK SLAP1 V37XEQC WL_tskLstEnd WL_maxVal WL_initWL WL_AT_noOvf WL_AT_loop WL_TIME3task WL_RT_runIt WL_schedTask WL_ST_noTask WL_IS_loop WL_IS_done WL_RM_done EX_SLEEP_PRIO EX_jobLstStart EX_numJobs EX_keepJob EX_MN_setFlg ENDOFJOB EX_MN_notBank EX_MN_loop3 EX_JW_loop EX_JW_done

00043 3 00043 4 00043 4 00043 5 00043 6 00043 7 00044 0 00044 1 00044 1 00044 2 00044 4 00044 7 00044 0 00043 0 00045 3 00045 6 00046 3 00046 6 00047 1 00047 4 00047 6 00050 0 00050 3 00050 6 00051 1 00052 7 00053 2 00053 7 00053 7 00054 4 00054 7 00055 2 00055 5 00056 0 00056 3 00056 6 00057 1 00057 4 00057 7 00060 2 00060 5 00061 0 00061 3 00061 6 00200 0 00201 4 00203 0 00203 7 00204 4 00204 7 00205 2 00205 5 00206 0 00206 3 00206 6 00207 1 00207 4 00207 7 00210 2 00210 5 00211 3 00003 7 00212 4 00212 6 00216 6 00217 6 00220 1 00220 4 00226 4 00231 1 00234 7 00241 1 00241 7 00246 6 00251 0 00256 2 00263 6 00264 4 00264 7 00265 2 00265 5 00267 7 00272 3 00275 0 00276 3 00301 5 00305 6

ENTRET ESCAPE2 MATINC DSPMMTEM POLYRET DSMAG COUNT RELRET SEPSCRET NOUNADD IDAD1TEM RUTMXTEM DEX2 RESTREG NVSAVE TEMPFLSH MMNUMBER DECBRNCH XREG XREGLP ZREGLP DSPLOCK CLPASS MONSAVE DSPTAB VERBSAVE EXTVRACT DSPTEMX MMTEMP DSPOUTRET LXCH_A DPTEST_Q ALLDC_OC_Q BLANKSUB_Q NVSUB_L NBSUBSY1_L NEWMODEA_Q SHORTMP_OVFH PRSHRTMP_Q BJBANK PJRET BCRET MBCRET DCRET T3RUPT KEYRUPT goT3 goKEY NEG0 ZERO THREE SIX ELEVEN BIT13 BIT10 BIT7 BIT4 BIT1 lowAddr POSMAX CLRMEM_WORD CLRMEM_BADDR SAMASK goMMchange WL_taskRecSize WL_numTasks WL_maxDelay WL_IN_loop WL_AT_chkOrder WL_AT_schTsk WL_runTasks TASKOVER WL_ST_loop WL_ST_done WL_IS_bumpPtr WL_remove EX_WAKE_PRIO EX_jobCurStart EX_jobLstEnd EX_numJobs1 EX_exec EX_MN_runJob JOBSLEEP EX_MN_saveIt EX_MN_done3 EX_JW_moveRec EX_JW_return

000433 000434 000435 000435 000436 000437 000440 000441 000441 000442 000445 000450 000441 000451 000454 000457 000464 000467 000472 000475 000477 000501 000504 000507 000512 000530 000533 000537 000542 000545 000550 000553 000556 000561 000564 000567 000572 000575 000600 000603 000606 000611 000614 000617 002004 002020 002034 002041 002045 002050 002053 002056 002061 002064 002067 002072 002075 002100 002103 002106 002116 000037 002125 002147 002174 002177 002202 002213 002270 002333 002362 002413 002436 002470 002541 002565 002642 002645 002650 002653 002656 002701 002725 002752 003002 003035 003074

SPVAC EX_SP_testFlg NOVAC EX_AJ_testFlg EX_IN_loop1 EX_IN_done EX_FI_bumpPtr EX_remove EX_RM_loop2 EX_RM_done3 dumJob2 DODXCHCALL DOBANKCALL DOPOSTJUMP DATACALL RELTAB11 DSPOFF DSPSCAN DSPLAY DSPOUTEXIT TPAGREE TPA_PZ0 TPA_MZ0 TPA_P1 TPA_P2 MAXPOS TPA_MPAC1 SHORTMP BANK4 BANK40_1 BANK7 BANK43_1 CHECKTAB FCADRMM1 NOV37MM CHARIN2 _89TEST ENDNMTST DECEND CRITCON INRELTAB NVCOM BOTHSGN P_ON SGNTAB CLEAR CLR5 _5BLANK1 BRNCHCON BANK40_2 ENTER ENTEXIT ENTPAS0 REQADD NEG5 LST2CON MIXNOUN REQDATX REQCOM PUTADD GOALMCYC DSPAB DSPB DSPCOM3 NDOMPTST DCTSTCYC COMPICK DSPDCGET GTSFOUTL SFOUTABR SETAUG DEGTAB READLO ENDRDLO SECON1 MINCON1 SEPMIN DSPDPDEC ABCLOAD PUTXY CLOAD VBSP2LD GOQ SFRET1 DISPLACE PUTDPCOM PUTCOM2

003075 003146 003162 003236 003266 003324 003376 003410 003446 003507 003517 003547 003611 003677 003742 004005 004012 004065 004103 004126 004150 004167 004220 004246 004304 004315 004320 004353 010000 012000 016000 020000 010005 010030 010046 012016 012065 012155 012176 012232 012245 012275 012315 012332 012364 012412 012461 012515 012537 012564 014002 000433 014040 014073 014126 014163 014237 014264 014277 014320 014340 014350 014363 014403 014427 014444 014477 014514 014550 014563 012572 012640 012653 012703 016041 016047 016074 012704 014600 014646 014707 014734 014761 015002 015022 015065 015111

EX_SP_loop1 EX_SP_done2 EX_AJ_loop1 EX_AJ_done2 EX_IN_loop2 EX_findIns EX_FI_insRec EX_RM_loop1 EX_RM_done2 dumJob NOTACTLT DC_NOTBANK MYBANKCALL BANKJUMP DODATACALL DKTESTINIT T4PROG TABLNTH DSPOUT CHRPRIO TPA_SGN0 TPA_PZ0FIX TPA_MZ0FIX TPA_M1 TPA_M2 MAXNEG TPA_FIXM DMP BANK04_1 BANK6 BANK42_1 V37 AGAINMM PREMM1 BANK04_2 ELRCODE1 NUM ENDNUM PDECSGN DECON CCSHOLE NOUN PIXCLPAS SGNCOM SIGNTEST CLPASHI LEGALTST SINBLANK _2BLANK NVSUBR ENTPASHI MMADREF TESTVB USEADD INTMCTBS VBFANDIR DPTEST REQDATY ENDRQDAT UPDATVB GODSPALM DSPA DSPC COMPTEST DCOMPTST NOUNTEST GETCOMP DSPDCPUT DSPDCEND BANK41_2 FIXRANGE ARTOUTSF READLO1 BANK40_3 SECON2 HRCON1 ENDSPMIN ENDDPDEC PUTXYZ ALOAD LOADLV VBSP3LD SFRUTNOR SFCONUM CONUMNOR PUTNORM GTSFINLC

00311 0 00315 6 00320 0 00324 6 00330 4 00333 2 00340 5 00342 0 00346 5 00351 0 00352 5 00356 1 00362 4 00371 2 00376 3 00400 6 00404 7 00407 2 00411 6 00413 1 00415 2 00420 0 00423 1 00426 2 00430 6 00431 6 00432 1 00437 4 01000 0 01400 0 01600 0 01000 0 01000 7 01003 7 01004 7 01206 2 01210 1 01217 0 01222 0 01223 7 01227 1 01230 6 01232 1 01234 2 01236 7 01243 1 01246 4 01253 1 01254 0 01400 0 01401 2 01403 6 01404 4 01411 7 01412 7 01416 4 01424 0 01427 0 01430 5 01432 7 01434 1 01435 5 01437 0 01441 4 01443 0 01445 3 01450 1 01452 4 01455 1 01460 0 01260 3 01264 4 01266 5 01270 4 01604 3 01605 1 01611 3 01272 6 01461 4 01466 3 01472 3 01473 5 01476 2 01500 3 01502 5 01507 7 01511 3

EX_SP_done1 FINDVAC EX_AJ_done1 EX_initEX EX_IN_loop3 EX_FI_loop EX_FI_done EX_RM_done1 EX_RM_loop3 dumJob1 DXCHJUMP BANKCALL POSTJUMP DOBANKJUMP RELTAB DK_initDK DSPOUTSR _120MRUPT NODSPOUT KEYPROG TPA_P0 TPA_M0 TPA_SGN1 TPA_SGN2 TPA_P3 TPA_MPAC0 TPA_FIXP BANKFF_1 BANK5 BANK41_1 BANK10 V37BAD V37NONO EPREMM1 CHARIN ENTERJMP DECTOBIN ENDALL MORNUM GETINREL VERB NEGSGN POSGN M_ON SGNTST1 CLEAR1 _5BLANK DOUBLK BLANKCON LOADLV1 ACCEPTWD LOWVERB TESTNN LODNNLOC VERBFAN VERBTAB DPTEST1 REQDATZ UPDATNN UPDAT1 DSPABC DSPCOM1 DSPCOM2 COMPTST1 DECTEST TSTFORDP DECDSP DSPSFNOR DECDSP3 DEGOUTSF DEGCOM SCOUTEND RDLONOR HMSOUT MINCON2 SEPSECNR BANK42_2 BANK40_4 ABLOAD BLOAD VBSP1LD ALLDC_OC SFRUTMIX SFRET PUTCOM PUTNORM_1 PUTDECSF

003127 003161 003217 003252 003307 003347 003405 003437 003472 003514 003526 003565 003653 003733 003772 004007 004057 004074 004126 004132 004157 004210 004241 004277 004310 004317 004337 004435 012000 014000 020000 010002 010026 010046 012000 012063 012137 012174 012227 012241 012272 012312 012326 012353 012404 012454 012473 012534 012563 014001 014032 014037 014054 014124 014151 014167 014262 014274 014307 014335 014343 014361 014375 014417 014435 014462 014510 014546 014560 012564 012616 012651 012701 016000 016045 016053 016114 012727 014635 014673 014733 014736 014770 015020 015031 015111 015114

PUTSFNOR BANK41_3 SIGNFIX SGNTO1 ARTHINSF _2RNDEND BANK42_3 BIT15_14 KILLMON ENDMONDO MONBUSY PASTEVB MID7 ENDSPF DSPRND DSPDCWD1 DECROUND DSP2DEC VNDSPCON DSPOCTWD DSPLW BANK41_6 DFRNT _11DSPIN PREDSPAL MONADR ALMCYCLE MMCHANG VBRQEXEC SETVAC BANK41_7 VBRESEQ UNSUSPEN NVMONOPT NVSRRBNK BLANKDSP NVSUB1 ENDNVSB1 ENDIDLE ISLIST_P0 BSUB1ADDR DSPMM BLNKSUB1 RECALTST RECAL3 BANK40_8a SETEBANK R3D1 SLEFT5 HI5 TCFINDVAC LOW8 ND1 OUT1 FALTOF RELDSPOR DOSHRTMP FLSHTAB NVSUBSY1 RELDSP NEWMODEA PINBRNCH TSTLTS1 TSTCON1 TSTLTS3 TSTAB ERCOM BANK40_10 LODNLV SFCOM NNTYPTAB IDADDTAB GOEXTVB GOPIN P00 prio1 restart1_addr P01_restart tcadr2 P02_wait nvcode3 P03 P03_yield nvcode4 mon_option P78 Q

015125 015146 012750 012766 012776 013024 016114 015155 015232 015273 015276 004435 004473 015307 013046 013071 013117 013131 013155 015310 015341 015356 013226 013253 013265 013313 004474 015356 015420 015444 015453 013325 013342 004507 004531 015453 015505 015571 004541 004560 004612 010047 013350 013413 013444 013452 004633 004637 004656 004666 004671 004673 004676 000011 004706 004720 004754 005000 013452 005003 005036 005067 015600 015623 015631 013467 013505 013521 016156 016173 016354 016640 020000 020077 022000 022011 022020 022024 022035 022047 022063 022066 022107 022123 022126 022142 000001

PUTDCSF2 DEGINSF ENDSCALE DEGCON1 BINROUND TESTOFUF MONITOR MONIT2 MONDEL MONREF LODSAMPT PASTEOPT BANKFF_2 BANK41_5 DPOSMAX TRACE1 DSPDECNR END2DEC GOVNUPDT WDAGAIN DSPMSK DSPIN DSLV DSPOCTIN DSPALARM NVSBENDL ENDALM MODROUTR REQEX1 VBRQWAIT VBPROC VBRELDSP BANK40_8 NVSBCOM NVSUBEND INCR_NOUT_RET ENTSET BANK41_8 ENDINST DSPABORT BS_SUPDXCHZ ENDSPMM TESTBIT RECAL1 DOTERM SETNCADR R1D1 RIGHT5 LOW5 TCNOVAC LOW11 LOW10 MD1 DSALMOUT FALTOR TPSL1 FLASHON NVSUBUSY ENDNVBSY RELDSP2 POODOO BANKFF_6 FULLDSP SHOLTS BANK41_9 ERMINUS NOTBIT12 LODNNTAB MIXCON GTSFIN SFINTAB RUTMXTAB LST2FAN BANK43_2 time1 job1 tcadr1 nvcode2 P02 P02_pwd restart3_addr P03_restart P03_pwd restart4_addr P04 P79 QRUPT

01512 6 01272 7 01276 2 01277 2 01301 1 01302 5 01514 6 01516 4 01523 6 01527 4 01530 0 00445 1 00447 4 01531 0 01306 2 01307 4 01312 0 01314 3 01315 6 01531 7 00205 7 01316 1 01324 5 01326 1 01326 7 01331 4 00450 2 01000 0 01542 5 01544 6 01331 5 01332 7 01335 0 00451 6 00453 2 01546 3 01554 2 01557 2 00455 3 00456 3 00461 3 01005 6 01337 3 01341 6 01344 6 00461 6 00463 5 00464 0 00466 4 00466 7 00467 2 00467 4 00467 7 00001 1 00471 2 00472 1 00476 0 00500 1 01346 1 00501 7 00505 0 00507 0 01562 1 01562 4 01564 4 01347 7 01351 7 01611 4 01616 1 01617 6 01652 0 01712 4 02000 2 02010 1 02200 4 02201 2 02202 1 02203 3 02203 6 02205 5 02206 4 02207 0 02211 5 02212 4 02212 7 02214 7 00002 7

SFINTABR DEGINSF2 NEG180 DEGCON2 _2ROUND BANK40_5 MONIT1 MONREQ MONDO MONBACK BANK41_4 ENDPASTE DSPFMEM DSPSIGN DSPDECWD TRACE1S DSPDC2NR DSPDECVN BANK40_6 OCTBACK DSP2BIT DSPIN1 DSMSK ENDSPOCT CHARALRM BANK40_7 BANKFF_3 REQMM REQUESTC ENDRQWT VBTERM TSTLTS4 NVSUB NVSUBCOM BANKFF_4 INCR_NOUT NVSUB2 KILMONON ISCADR_P0 BLANKSUB BANKFF_5 BANK04_3 DSPMMJB RECAL2 DOPROC SETNADD R2D1 LEFT5 MID5 TCWAIT B12M1 VD1 BINCON FALTON RELDSPON PRSHRTMP FLASHOFF BANKFF_5a BANK40_9 RELDSP1 NOTPALT VBTSTLTS FULLDSP1 TSTLTS2 ERROR ERPLUS ERCON LODMIXNN GTSFOUT NNADTAB SFOUTAB BANK42_4 ALM_END BANK11 task1 nvcode1 P01 restart2_addr P02_restart P02_ter tcadr3 P03_wait P03_ter tcadr4 P04_restart ARUPT TIME1

015131 012740 012764 012774 013014 013031 015150 015215 015237 015275 015301 004472 015301 013031 013064 013105 013124 013144 013161 015337 015344 013206 013247 013264 013307 013315 004503 015404 015431 015452 013323 013334 004503 004524 004536 015501 015543 004536 004554 004565 004616 010057 013400 013427 013450 004625 004636 004647 004665 004670 004672 004675 004700 004701 004713 004740 004770 005003 013462 005026 005066 015572 015622 015625 013462 013502 013520 016135 016162 016210 016570 017220 020076 022000 022005 022017 022022 022034 022040 022060 022065 022077 022120 022125 022131 000026 000036

TIME2 TIME4 LP SR

000035 000040 000003 000021

BANK OUT0 OVCTR CYR

00001 5 00001 0 00003 4 00002 0

A IN0 CYL

000000 000004 000022

Block I Apollo Guidance Computer (AGC)


How to build one in your basement
Part 9: Test and Checkout Software
John Pultorak December, 2004

Abstract
This report describes my successful project to build a working reproduction of the 1964 prototype for the Block I Apollo Guidance Computer. The AGC is the flight computer for the Ap ollo m oon lan din gs, and is the wo rlds first in tegra ted c ircuit com pu ter. I built it in my ba sem ent. It took me 4 yea rs. If you like, you can build one too. It will take you less time, and yours will be better than mine. I docum ented m y project in 9 separate .pdf files: Part 1 Part 2 Part 3 Part 4 Part 5 Part 6 Part 7 Part 8 O v ervie w : Introdu ces the p roject. CTL Module: Design and construction of the control module. PROC M odule: Design and construction of the processing (CPU) modu le. MEM Module: Design and construction of the mem ory module. IO Module: Design and construction of the display/keyboard (DSKY) m odule. Assem bler: A cross-a ssem bler for AG C softw are dev elopm ent. C+ + S imu lator: A low-level simulator that runs assemb led AGC code. Flight Software: My translation of portions of the COLOSSUS 249 flight software. Test & Che ckou t: A suite of test programs in AG C assembly langu age.

Part 9

Overview
A suite of test and checkout programs were coded to verify the operation of the AGC simulators and the hardware AGC.

TECO1
First test and checkout program for the Block 1 AGC. Tests basic instructions: TC, CCS, INDEX, XCH, CS, TS, AD, MA SK. Enters an infinite loop at the end of the test. The A register contains the cod e for the test that failed, or the PAS S code if all tests succeeded. See test codes (in octal) below. Code 01 02 03 04 05 06 07 10 12345 Interpretation TC check failed CCS check failed INDEX check failed XCH check failed CS check failed TS check failed AD check failed MAS K check failed PASSED all checks

TECO2
Second test and checkout program for the Block 1 AGC. Tests extracode instructions: MP, DV, SU. Enters an infinite loop at the end of the test. The A register contains the code for the test that failed, or the PASS code if all tests succeeded. See test codes (in octal) below. Code 01 02 03 12345 Interpretation MP check failed DV check failed SU check failed PASSED all checks

TECO3
Third test and checkout program for the Block 1 AGC. Tests editing registers: CYR, SR, CYL, SL. Enters an infinite loop at the end of the test. The A register contains the code for the test that failed, or the PASS code if all tests succeeded. See test codes (in octal) below. Code 01 02 03 04 12345 Interpretation CYR check failed SR check failed CYL check failed SL check failed PASSED all checks

TECO5
Exercises AGC interrupts by initializing 4 counters, and then entering into a loop that increments the first counter on each iteration. Each of the other 3 counters is assigned to an interrupt and is incremented in the interrupt service routine for that interrupt: KEYRUPT, T3R UPT , and D SR UPT . Interrupts a re inhib ited an d en abled durin g each iteration o f the m ain loop with INHINT and RELINT instructions, and are automatically inhibited during part of each iteration by an overflow condition in register A.

TECO_STBY
An extrem ely sim ple p rogra m for testin g th e ST AN DB Y fun ction . STA ND BY is disabled fo r 2 NOOP instructions and then is enabled. After that, the program infinitely loops (TC TRAP) with STANDBY enabled.

TECO1 assembler listing


Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM First pass: generate symbol table. Second pass: generate object code. ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; TECO1 (file:teco1.asm) Version: 1.0 Author: John Pultorak Date: 9/14/2001 PURPOSE: Test and checkout program for the Block 1 Apollo Guidance Computer. Tests basic instructions: TC, CCS, INDEX, XCH, CS, TS, AD, MASK. OPERATION: Enters an infinite loop at the end of the test. The A register contains the code for the test that failed, or the PASS code if all tests succeeded. See test codes below. ERRATA: - Written for the AGC4R assembler. The assembler directives and syntax differ somewhat from the original AGC assembler. - The tests attempt to check all threads, but are not exhaustive. SOURCES: Information on the Block 1 architecture: instruction set, instruction sequences, registers, register transfers, control pulses, memory and memory addressing, I/O assignments, interrupts, and involuntary counters was obtained from: A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. Supplementary information was obtained from: R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary MOD 3C Programmer's Manual", E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961. B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", E-2052, MIT Instrumentation Laboratory, Cambridge, MA, Jan. 1967. E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer Subsystem", R-700, MIT Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972. A. Hopkins, "Guidance Computer Design, Part VI", source unknown. A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964. E, C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA, Reston VA, 1996. EQU EQU EQU EQU EQU EQU EQU EQU EQU %00 %01 %02 %03 %04 %05 %06 %07 %10 ; ; ; ; ; ; ; ; TC check failed CCS check failed INDEX check failed XCH check failed CS check failed TS check failed AD check failed MASK check failed

START TCtst CCStst INDEXtst XCHtst CStst TStst ADtst MASKtst

PASS EQU %12345 ; PASSED all checks ; ----------------------------------------------

05777

5777

47777 0 OVFCNTR

ORG DS EQU

EXTENDER %47777 %00034

; needed for EXTEND ; overflow counter

; ---------------------------------------------; ERASEABLE MEMORY -- DATA SEGMENT 00100 00101 00102 00103 0100 0101 0102 0103 00000 1 curtest 00000 1 savQ ; CCS test 00000 1 CCSk ; INDEX test 00000 1 INDXval ORG DS DS DS DS %100 START %0 %0 0 ; start of data area ; current test

00104 00105 00106 00107 00110 00111

0104 0105 0106 0107 0110 0111

00000 77777 52525 25252

1 0 1 0

; XCH test ; pre-set in erasable memory because we don't ; want to use XCH to initialize them prior to testing XCH. XCHkP0 DS +0 XCHkM0 DS -0 XCHkalt1 DS %52525 ; alternating bit pattern 1 XCHkalt2 DS %25252 ; alternating bit pattern 2 DS DS -0 -0

; TS test 77777 0 TSk ; AD test 77777 0 ADk

; ---------------------------------------------; ENTRY POINTS ; program (re)start ORG 1,2030 0 TC GOPROG goMAIN

02000

2000 0

02004 02005 02006 02007 02010 02011 02012 02013 02014 02015 02016 02017 02020 02021 02022 02023

2004 2005 2006 2007 2010 2011 2012 2013 2014 2015 2016 2017 2020 2021 2022 2023

5 3 5 0 5 3 5 0 5 3 5 0 5 3 5 0

0,0026 0,0001 0,0027 1,2717 0,0026 0,0001 0,0027 1,2717 0,0026 0,0001 0,0027 1,2717 0,0026 0,0001 0,0027 1,2717

0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

; interrupt service entry points ORG T3RUPT TS ARUPT XCH Q TS QRUPT TC goT3 ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ERRUPT ARUPT Q QRUPT goER DSRUPT ARUPT Q QRUPT goDS KEYRUPT ARUPT Q QRUPT goKEY UPRUPT ARUPT Q QRUPT goUP

02024 02025 02026 02027

2024 2025 2026 2027

5 3 5 0

0,0026 0,0001 0,0027 1,2717

0 0 1 1

; ---------------------------------------------; FIXED MEMORY -- SHARED DATA SEGMENT ; ----------------------------------------------

; MAIN PROGRAM goMAIN 02030 02031 02032 02033 02034 02035 02036 02037 02040 02041 02042 02043 02044 02045 2030 2 2031 0 2032 2033 2034 2035 2036 2037 2040 2041 0 0 0 0 0 0 0 0 0,0000 0 1,2047 0 1,2054 1,2110 1,2244 1,2274 1,2400 1,2446 1,2573 1,2674 1 0 1 1 1 0 1 0 EQU INHINT TCR * ; disable interrupts begin

; Test basic instructions. TCR chkTC TCR chkCCS TCR chkINDEX TCR chkXCH TCR chkCS TCR chkTS TCR chkAD TCR chkMASK ; Passed all tests. TCR fail EQU XCH TS EQU TC finish * curtest curtest * end ; load last passed test into A

2042 0 2043 3 2044 5 2045 0

1,2714 1 0,0100 0 0,0100 0

end 1,2045 1

; finished, TC trap

; ---------------------------------------------; INITIALIZE FOR START OF TESTING 02046 02047 02050 02051 2046 2047 3 2050 5 2051 0 00000 1 STRTcode begin 1,2046 1 0,0100 0 0,0000 0 ; ; ; ; ; ; 02052 02053 02054 02055 02056 02057 02060 02061 02062 02063 02064 02065 02066 02067 02070 02071 02072 2052 2053 2054 3 2055 5 2056 3 2057 5 2060 0 2061 0 2062 2063 2064 2065 2066 2067 4 6 1 0 0 0 DS EQU XCH TS RETURN START * STRTcode curtest

; set current test code to START

---------------------------------------------TEST TC INSTRUCTION SUBROUTINE L: TC K Verifies the following: - Set C(Q) = TC L+1 - Take next instruction from K, and proceed from there. DS DS EQU XCH TS CAF TS TCtst TCret1 * Q savQ TCcode curtest *+2 fail address in Q Q Qtest A fail fail fail ; code for this test ; expected return address

00001 0 TCcode 02061 1 Qtest chkTC 0,0001 0 0,0101 1 1,2052 1 0,0100 0

; save return address ; set test code to this test ; make test jump ; failed to jump

; attempt a jump 1,2062 1 TC 1,2043 1 TCret1 TC 0,0001 1,2053 0,0000 1,2043 1,2043 1,2043 1 0 0 1 1 1 ; verify correct return CS AD CCS TC TC TC

; ; ; ; ;

put (-Q) + val2 in A A = DABS >0 (Q < Qtest) +0 (never happens) <0 (Q > Qtest)

2070 3 2071 5 2072 0

0,0101 1 0,0001 0 0,0000 0

; passed the test XCH savQ TS Q ; restore return address RETURN ; ---------------------------------------------; TEST CCS INSTRUCTION SUBROUTINE ; L: CCS K ; Verifies the following: ; - take next instruction from L+n and proceed from there, where: ; -- n = 1 if C(K) > 0

; ; ; ; ; ; 02073 02074 02075 02076 02077 02100 02101 02102 02103 02104 02105 02106 02107 02110 02111 02112 02113 2073 2074 2075 2076 2077 2100 2101 2102 2103 2104 2105 2106 2107 2110 3 2111 5 2112 3 2113 5

-- n = 2 if C(K) = +0 -- n = 3 if C(K) < 0 -- n = 4 if C(K) = -0 - set C(A) = DABS[C(K)], where DABS (diminished abs value): -- DABS(a) = abs(a) - 1, if abs(a) > 1 -- DABS(a) = +0, if abs(a) <= 1 CCStst -2 -1 -0 +0 +1 +2 1 0 0 0 0 1 * Q savQ CCScode curtest ; ; ; ; ; ; for for for for for for K=-2, K=-1, K=-0, K=+0, K=+1, K=+2, DABS DABS DABS DABS DABS DABS = = = = = = +1 +0 +0 +0 +0 +1 ; code for this test

00002 0 CCScode DS ; test values (K) 77775 1 CCSkM2 DS 77776 1 CCSkM1 DS 77777 0 CCSkM0 DS 00000 1 CCSkP0 DS 00001 0 CCSkP1 DS 00002 0 CCSkP2 DS 00001 00000 00000 00000 00000 00001 0 1 1 1 1 0 ; expected DABS values CCSdM2 DS CCSdM1 DS CCSdM0 DS CCSdP0 DS CCSdP1 DS CCSdP2 DS chkCCS 0,0001 0 0,0101 1 1,2073 1 0,0100 0 EQU XCH TS CAF TS

; save return address ; set test code to this test

02114 02115 02116 02117 02120 02121 02122 02123 02124 02125 02126 02127 02130

2114 2115 2116 2117 2120 2121 2122 2123 2124 2125 2126 2127 2130

3 5 1 0 0 0 0 4 6 1 0 0 0

1,2074 0,0102 0,0102 1,2043 1,2043 1,2123 1,2043 0,0000 1,2102 0,0000 1,2043 1,2043 1,2043

0 1 0 1 1 0 1 0 0 0 1 1 1

; set K to -2 and execute CCS: ; check for correct branch CAF CCSkM2 ; set K = -2 TS CCSk CCS CCSk ; A = DABS[C(K)] TC fail ; K > 0 TC fail ; K= +0 TC *+2 ; K < 0 TC fail ; K= -0 ; check for correct DABS in A (for K=-2, it should be 1) COM ; 1's compliment of A AD CCSdM2 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; set K to -1 and execute CCS: ; check for correct branch CAF CCSkM1 ; set K = -1 TS CCSk CCS CCSk ; A = DABS[C(K)] TC fail ; K > 0 TC fail ; K= +0 TC *+2 ; K < 0 TC fail ; K= -0 ; check for correct DABS in A (for K=-1, it should be +0) COM ; 1's compliment of A AD CCSdM1 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; set K to -0 and execute CCS: ; check for correct branch CAF CCSkM0 ; set K = -0 TS CCSk CCS CCSk ; A = DABS[C(K)] TC fail ; K > 0 TC fail ; K= +0 TC fail ; K < 0 ; check for correct DABS in A (for K=-0, it should be +0) COM ; 1's compliment of A AD CCSdM0 ; put (-A) + expected value in A

02131 02132 02133 02134 02135 02136 02137 02140 02141 02142 02143 02144 02145

2131 2132 2133 2134 2135 2136 2137 2140 2141 2142 2143 2144 2145

3 5 1 0 0 0 0 4 6 1 0 0 0

1,2075 0,0102 0,0102 1,2043 1,2043 1,2140 1,2043 0,0000 1,2103 0,0000 1,2043 1,2043 1,2043

1 1 0 1 1 0 1 0 1 0 1 1 1

02146 02147 02150 02151 02152 02153 02154 02155

2146 2147 2150 2151 2152 2153

3 5 1 0 0 0

1,2076 0,0102 0,0102 1,2043 1,2043 1,2043

1 1 0 1 1 1

2154 4 2155 6

0,0000 0 1,2104 0

02156 02157 02160 02161

2156 2157 2160 2161

1 0 0 0

0,0000 1,2043 1,2043 1,2043

0 1 1 1

CCS TC TC TC

A fail fail fail

; ; ; ;

A = DABS >0 (A < expected value) +0 <0 (A > expected value)

02162 02163 02164 02165 02166 02167 02170 02171 02172 02173 02174 02175 02176

2162 2163 2164 2165 2166 2167 2170 2171 2172 2173 2174 2175 2176

3 5 1 0 0 0 0 4 6 1 0 0 0

1,2077 0,0102 0,0102 1,2043 1,2171 1,2043 1,2043 0,0000 1,2105 0,0000 1,2043 1,2043 1,2043

0 1 0 1 1 1 1 0 1 0 1 1 1

; set K to +0 and execute CCS: ; check for correct branch CAF CCSkP0 ; set K = +0 TS CCSk CCS CCSk ; A = DABS[C(K)] TC fail ; K > 0 TC *+3 ; K= +0 TC fail ; K < 0 TC fail ; K= -0 ; check for correct DABS in A (for K=+0, it should be +0) COM ; 1's compliment of A AD CCSdP0 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; set K to +1 and execute CCS: ; check for correct branch CAF CCSkP1 ; set K = +1 TS CCSk CCS CCSk ; A = DABS[C(K)] TC *+4 ; K > 0 TC fail ; K= +0 TC fail ; K < 0 TC fail ; K= -0 ; check for correct DABS in A (for K=+1, it should be +0) COM ; 1's compliment of A AD CCSdP1 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; set K to +2 and execute CCS: ; check for correct branch CAF CCSkP2 ; set K = +2 TS CCSk CCS CCSk ; A = DABS[C(K)] TC *+4 ; K > 0 TC fail ; K= +0 TC fail ; K < 0 TC fail ; K= -0 ; check for correct DABS in A (for K=+2, it should be +1) COM ; 1's compliment of A AD CCSdP2 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; passed the test XCH savQ TS Q ; restore return address RETURN ; ---------------------------------------------; TEST INDEX INSTRUCTION SUBROUTINE ; L: INDEX K (where K != 0025) ; Verifies the following; ; - Use the sum of C(L+1) + C(K) as the next instruction ; -- just as if that sum had been taken from L+1. DS DS DS DS DS DS DS DS INDEXtst 5 0 1 2 3 4 5 ; code for this test ; somewhere in fixed memory ; base address for indexing

02177 02200 02201 02202 02203 02204 02205 02206 02207 02210 02211 02212 02213

2177 2200 2201 2202 2203 2204 2205 2206 2207 2210 2211 2212 2213

3 5 1 0 0 0 0 4 6 1 0 0 0

1,2100 0,0102 0,0102 1,2206 1,2043 1,2043 1,2043 0,0000 1,2106 0,0000 1,2043 1,2043 1,2043

1 1 0 1 1 1 1 0 1 0 1 1 1

02214 02215 02216 02217 02220 02221 02222 02223 02224 02225 02226 02227 02230 02231 02232 02233

2214 2215 2216 2217 2220 2221 2222 2223 2224 2225 2226 2227 2230

3 5 1 0 0 0 0 4 6 1 0 0 0

1,2101 0,0102 0,0102 1,2223 1,2043 1,2043 1,2043 0,0000 1,2107 0,0000 1,2043 1,2043 1,2043

0 1 0 0 1 1 1 0 0 0 1 1 1

2231 3 2232 5 2233 0

0,0101 1 0,0001 0 0,0000 0

02234 02235 02236 02237 02240 02241 02242 02243

2234 2235 2236 2237 2240 2241 2242 2243

00003 1 INDXcode 00005 1 INDXst 00000 00001 00002 00003 00004 00005 1 INDXbas 0 0 1 0 1

chkINDEX 02244 02245 02246 02247 2244 3 2245 5 2246 3 2247 5 0,0001 0 0,0101 1 1,2234 0 0,0100 0

EQU XCH TS CAF TS

* Q savQ INDXcode curtest

; save return address ; set test code to this test

; Decrementing loop ; - always executes at least once (tests at end of loop) ; - loops 'INDXst+1' times; decrements INDXval 02250 02251 2250 3 2251 5 1,2235 1 INDXlop 0,0103 0 XCH EQU TS INDXst * INDXval ; initialize loop counter

02252 02253 02254 02255 02256 02257 02260 02261 02262 02263 02264 02265 02266

2252 2 2253 3 2254 2255 2256 2257 2260 2261 4 6 1 0 0 0

; perform indexed CAF of values in INDXbas array; ; index values range from 5 to 0 0,0103 1 INDEX INDXval 1,2236 1 CAF INDXbas 0,0000 0,0103 0,0000 1,2043 1,2043 1,2043 0 0 0 1 1 1 ; verify value retrieved using INDEX matches expected value COM ; get -A AD INDXval ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) CCS TC INDXval INDXlop ; done? ; not yet

2262 1 2263 0 2264 3 2265 5 2266 0

0,0103 1 1,2251 0 0,0101 1 0,0001 0 0,0000 0 ; ; ; ; ; ; ;

XCH savQ TS Q ; restore return address RETURN ---------------------------------------------TEST XCH INSTRUCTION SUBROUTINE L: XCH K Verifies the following: - set C(A) = b(K) - set C(K) = b(A) - take next instruction from L+1 XCHtst +0 -0 %52525 %25252 * Q savQ XCHcode curtest ; code for this test

02267 02270 02271 02272 02273 02274 02275 02276 02277

2267 2270 2271 2272 2273 2274 3 2275 5 2276 3 2277 5

00004 0 XCHcode DS ; XCH test values 00000 1 XCHfP0 DS 77777 0 XCHfM0 DS 52525 1 XCHfalt1 DS 25252 0 XCHfalt2 DS chkXCH 0,0001 0 0,0101 1 1,2267 0 0,0100 0 EQU XCH TS CAF TS

; alternating bit pattern 1 ; alternating bit pattern 2

; save return address ; set test code to this test

02300 02301 02302 02303 02304 02305 02306 02307 02310 02311 02312 02313 02314

2300 4 2301 3 2302 2303 2304 2305 2306 2307 2310 2311 2312 2313 2314 4 6 1 0 0 0 4 6 1 0 0

1,2270 1 0,0104 1 0,0000 1,2270 0,0000 1,2043 1,2043 1,2043 0,0104 1,2271 0,0000 1,2043 1,2043 0 0 0 1 1 1 0 1 0 1 1

; test - initial conditions: K=+0, A=-0 ; initialize A CS XCHfP0 ; exchange A and K XCH XCHkP0 ; test contents of A for expected value COM ; AD XCHfP0 ; CCS A ; TC fail ; TC fail ; TC fail ; ; test contents of K for expected value CS XCHkP0 ; AD XCHfM0 ; CCS A ; TC fail ; TC fail ;

get -A put (-A) + expected value in A A = DABS >0 (A < expected value) +0 <0 (A > expected value) get -A put (-A) + expected value in A A = DABS >0 (A < expected value) +0

02315

2315 0

1,2043 1

TC

fail

; <0 (A > expected value)

02316 02317 02320 02321 02322 02323 02324 02325 02326 02327 02330 02331 02332 02333

2316 4 2317 3 2320 2321 2322 2323 2324 2325 2326 2327 2330 2331 2332 2333 4 6 1 0 0 0 4 6 1 0 0 0

1,2271 0 0,0105 0 0,0000 1,2271 0,0000 1,2043 1,2043 1,2043 0,0105 1,2270 0,0000 1,2043 1,2043 1,2043 0 1 0 1 1 1 1 0 0 1 1 1

; test - initial conditions: K=-0, A=+0 ; initialize A CS XCHfM0 ; exchange A and K XCH XCHkM0 ; test contents of A for expected value COM ; AD XCHfM0 ; CCS A ; TC fail ; TC fail ; TC fail ; ; test contents of K for expected value CS XCHkM0 ; AD XCHfP0 ; CCS A ; TC fail ; TC fail ; TC fail ;

get -A put (-A) + expected value in A A = DABS >0 (A < expected value) +0 <0 (A > expected value) get -A put (-A) + expected value in A A = DABS >0 (A < expected value) +0 <0 (A > expected value)

02334 02335 02336 02337 02340 02341 02342 02343 02344 02345 02346 02347 02350 02351

2334 4 2335 3 2336 2337 2340 2341 2342 2343 2344 2345 2346 2347 2350 2351 4 6 1 0 0 0 4 6 1 0 0 0

1,2272 0 0,0106 0 0,0000 1,2272 0,0000 1,2043 1,2043 1,2043 0,0106 1,2273 0,0000 1,2043 1,2043 1,2043 0 1 0 1 1 1 1 0 0 1 1 1

; test - initial conditions: K=52525, A=25252 ; initialize A CS XCHfalt1 ; exchange A and K XCH XCHkalt1 ; test contents of A for expected value COM ; get -A AD XCHfalt1 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; test contents of K for expected value CS XCHkalt1 ; get -A AD XCHfalt2 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; test - initial conditions: K=25252, A=52525 ; initialize A CS XCHfalt2 ; exchange A and K XCH XCHkalt2 ; test contents of A for expected value COM ; get -A AD XCHfalt2 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; test contents of K for expected value CS XCHkalt2 ; get -A AD XCHfalt1 ; put (-A) + expected value in A CCS A ; A = DABS TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; passed the test XCH TS RETURN ; ; ; ; ; ; savQ Q

02352 02353 02354 02355 02356 02357 02360 02361 02362 02363 02364 02365 02366 02367 02370 02371 02372

2352 4 2353 3 2354 2355 2356 2357 2360 2361 2362 2363 2364 2365 2366 2367 4 6 1 0 0 0 4 6 1 0 0 0

1,2273 1 0,0107 1 0,0000 1,2273 0,0000 1,2043 1,2043 1,2043 0,0107 1,2272 0,0000 1,2043 1,2043 1,2043 0 0 0 1 1 1 0 1 0 1 1 1

2370 3 2371 5 2372 0

0,0101 1 0,0001 0 0,0000 0

; restore return address

---------------------------------------------TEST CS INSTRUCTION SUBROUTINE L: CS K Verifies the following: - Set C(A) = -C(K) - Take next instruction from L+1 CStst ; code for this test

02373

2373

00005 1 CScode DS ; test values (K)

02374 02375 02376 02377 02400 02401 02402 02403 02404 02405 02406 02407 02410 02411 02412 02413 02414 02415 02416 02417 02420 02421 02422 02423 02424 02425 02426 02427 02430 02431 02432 02433 02434 02435 02436

2374 2375 2376 2377 2400 3 2401 5 2402 3 2403 5 2404 2405 2406 2407 2410 2411 2412 2413 2414 2415 2416 2417 2420 2421 2422 2423 2424 2425 2426 2427 2430 2431 2432 2433 4 6 1 0 0 0 4 6 1 0 0 0 4 6 1 0 0 0 4 6 1 0 0 0

00000 77777 52525 25252

1 0 1 0

CSkP0 CSkM0 CSkalt1 CSkalt2 chkCS

DS DS DS DS EQU XCH TS CAF TS

+0 -0 %52525 %25252 * Q savQ CScode curtest

; 1's C of CSkalt2 ; 1's C of CSkalt1

0,0001 0 0,0101 1 1,2373 1 0,0100 0 1,2374 1,2374 0,0000 1,2043 1,2043 1,2043 1,2375 1,2375 0,0000 1,2043 1,2043 1,2043 1,2376 1,2376 0,0000 1,2043 1,2043 1,2043 1,2377 1,2377 0,0000 1,2043 1,2043 1,2043 1 0 0 1 1 1 0 1 0 1 1 1 0 1 0 1 1 1 1 0 0 1 1 1

; save return address ; set test code to this test ; ; ; ; ; ; ; ; ; ; ; ; load 1's comp of K into A put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) load 1's comp of K into A put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

; clear and subtract +0 CS CSkP0 AD CSkP0 CCS A TC fail TC fail TC fail ; clear and subtract -0 CS CSkM0 AD CSkM0 CCS A TC fail TC fail TC fail

; clear and subtract alternating bit pattern %52525 CS CSkalt1 ; load 1's comp of K into A AD CSkalt1 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; clear and subtract alternating bit pattern %25252 CS CSkalt2 ; load 1's comp of K into A AD CSkalt2 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; passed the test XCH savQ TS Q ; restore return address RETURN ; ---------------------------------------------; TEST TS INSTRUCTION SUBROUTINE ; L; TS K ; Verifies the following: ; - Set C(K) = b(A) ; - If b(A) contains no overflow, ; -- C(A) = b(A); take next instruction from L+1 ; - If b(A) has positive overflow, C(A) = 000001; ; -- take next instruction from L+2 ; - If b(A) has negative overflow, C(A) = 177776; ; -- take next instruction from L+2 TScode TSone TSzero TSmzero TSmone TSkP1 TSkM1 chkTS DS DS DS DS DS DS DS EQU XCH TS CAF TS ; initialize TSk to -0 TStst +1 +0 -0 -1 %37777 %40000 * Q savQ TScode curtest ; code for this test

2434 3 2435 5 2436 0

0,0101 1 0,0001 0 0,0000 0

02437 02440 02441 02442 02443 02444 02445 02446 02447 02450 02451

2437 2440 2441 2442 2443 2444 2445 2446 3 2447 5 2450 3 2451 5

00006 00001 00000 77777 77776 37777 40000

1 0 1 0 1 1 0

; TEST1: largest + num w/no ovf ; TEST2: largest - num w/no ovf

0,0001 0 0,0101 1 1,2437 0 0,0100 0

; save return address ; set test code to this test

02452 02453 02454 02455 02456 02457 02460 02461 02462 02463 02464 02465 02466 02467 02470 02471 02472 02473 02474 02475 02476 02477 02500 02501 02502 02503 02504 02505 02506 02507 02510 02511 02512 02513 02514 02515 02516 02517 02520 02521 02522 02523 02524 02525 02526 02527 02530 02531 02532 02533 02534 02535 02536 02537 02540 02541 02542 02543 02544 02545

2452 3 2453 3 2454 2455 2456 2457 2460 2461 2462 2463 2464 2465 2466 2467 2470 2471 2472 2473 2474 2475 2476 2477 2500 2501 2502 2503 2504 2505 2506 2507 2510 2511 2512 2513 2514 2515 2516 2517 2520 2521 2522 2523 2524 2525 2526 2527 2530 2531 2532 2533 2534 2535 2536 2537 2540 2541 2542 2543 2544 2545 3 5 0 0 4 6 1 0 0 0 4 6 1 0 0 0 3 5 0 0 4 6 1 0 0 0 4 6 1 0 0 0 3 6 5 0 4 6 1 0 0 0 4 6 1 0 0 0 3 6 5 0 4 6 1 0 0 0

1,2442 1 0,0110 1 1,2444 0,0110 1,2460 1,2043 0,0000 1,2444 0,0000 1,2043 1,2043 1,2043 1,2444 0,0110 0,0000 1,2043 1,2043 1,2043 1,2445 0,0110 1,2500 1,2043 0,0000 1,2445 0,0000 1,2043 1,2043 1,2043 1,2445 0,0110 0,0000 1,2043 1,2043 1,2043 1,2444 1,2440 0,0110 1,2043 0,0000 1,2440 0,0000 1,2043 1,2043 1,2043 1,2441 0,0110 0,0000 1,2043 1,2043 1,2043 1,2445 1,2443 0,0110 1,2043 0,0000 1,2443 0,0000 1,2043 1,2043 1,2043 1 1 1 1 0 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 0 0 1 1 1 1 1 0 1 1 1 1 0 1 1 0 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1 0 0 0 1 1 1

CAF XCH

TSmzero TSk

; TEST 1: store positive number, no overflow CAF TSkP1 TS TSk TC *+2 ; no overflow TC fail ; overflow ; verify C(A) = b(A) COM ; get -A AD TSkP1 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify C(K) = b(A) CS TSkP1 ; get -expected value AD TSk ; put value + C(K) into A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST 2: store negative number, no overflow CAF TSkM1 TS TSk TC *+2 ; no overflow TC fail ; overflow ; verify C(A) = b(A) COM ; get -A AD TSkM1 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify C(K) = b(A) CS TSkM1 ; get -expected value AD TSk ; put value + C(K) into A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST 3: store positive number, overflow CAF TSkP1 ; get largest positive number AD TSone ; make it overflow; A = neg ovf TS TSk ; store the positive overflow TC fail ; no overflow ; verify C(A) = 000001 COM ; get -A AD TSone ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify C(K) = positive overflow CS TSzero ; get -expected value AD TSk ; put value + C(K) into A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST 4: store negative number, overflow CAF TSkM1 ; get largest negative number AD TSmone ; make it overflow; A = neg ovf TS TSk ; store the negative overflow TC fail ; no overflow ; verify C(A) = 177776 COM ; get -A AD TSmone ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify C(K) = negative overflow

02546 02547 02550 02551 02552 02553 02554 02555 02556

2546 2547 2550 2551 2552 2553

4 6 1 0 0 0

1,2442 0,0110 0,0000 1,2043 1,2043 1,2043

0 1 0 1 1 1

CS AD CCS TC TC TC

TSmzero TSk A fail fail fail

; ; ; ; ; ;

get -expected value put value + C(K) into A compare >0 (A < expected value) +0 <0 (A > expected value)

2554 3 2555 5 2556 0

0,0101 1 0,0001 0 0,0000 0 ; ; ; ; ; ; ; ; ; ;

XCH savQ TS Q ; restore return address RETURN ---------------------------------------------TEST AD INSTRUCTION SUBROUTINE L: AD K Verifies the following: - Set C(A) = b(A) + C(K) - Take next instruction from L+1 - if C(A) has positive overflow, -- increment overflow counter by 1 - if C(A) has negative overflow, -- decrement overflow counter by 1 DS DS DS DS DS DS DS DS DS DS DS DS EQU XCH TS CAF TS ADtst +0 1 -1 %25252 %12525 %37777 %12524 %52525 %65252 %40000 %65253 * Q savQ ADcode curtest ; code for this test

02557 02560 02561 02562 02563 02564 02565 02566 02567 02570 02571 02572 02573 02574 02575 02576

2557 2560 2561 2562 2563 2564 2565 2566 2567 2570 2571 2572 2573 3 2574 5 2575 3 2576 5

00007 00000 00001 77776 25252 12525 37777 12524 52525 65252 40000 65253

0 1 0 1 0 0 1 1 1 1 0 0

ADcode ADplus0 ADplus1 ADmin1 AD25252 AD12525 AD37777 AD12524 AD52525 AD65252 AD40000 AD65253 chkAD

; ; ; ; ; ; ; ;

+10922 decimal +5461 decimal largest positive number + overflow of %25252+%25252 -10922 decimal -5461 decimal largest negative number neg overflow of %52525+65252

0,0001 0 0,0101 1 1,2557 1 0,0100 0

; save return address ; set test code to this test

02577 02600 02601 02602 02603 02604 02605 02606

2577 3 2600 6 2601 2602 2603 2604 2605 2606 4 6 1 0 0 0

1,2563 0 1,2564 1 0,0000 1,2565 0,0000 1,2043 1,2043 1,2043 0 0 0 1 1 1

; TEST1: sum positive, no overflow ; add: %25252 + %12525 = %37777 (sign + 14 magnitude) CAF AD25252 AD AD12525 ; verify C(A) = %37777 COM ; get -A AD AD37777 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST2: sum negative, no overflow (sign + 14 magnitude) ; add: %52525 + %65252 = %40000 CAF AD52525 AD AD65252 ; verify C(A) = %40000 COM ; get -A AD AD40000 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST3: sum positive, overflow ; initialize overflow counter and positive overflow storage CAF ADplus0 TS OVFCNTR TS ADk ; add: %25252 + %25252 = %52524 (sign + 14 magnitude) CAF AD25252 AD AD25252 TS ADk ; store positive overflow

02607 02610 02611 02612 02613 02614 02615 02616

2607 3 2610 6 2611 2612 2613 2614 2615 2616 4 6 1 0 0 0

1,2567 1 1,2570 1 0,0000 1,2571 0,0000 1,2043 1,2043 1,2043 0 0 0 1 1 1

02617 02620 02621 02622 02623 02624

2617 3 2620 5 2621 5 2622 3 2623 6 2624 5

1,2560 0 0,0034 0 0,0111 0 1,2563 0 1,2563 0 0,0111 0

02625 02626 02627 02630 02631 02632 02633 02634 02635 02636 02637 02640 02641 02642 02643 02644 02645 02646 02647 02650 02651 02652 02653 02654 02655 02656 02657 02660 02661 02662 02663 02664 02665 02666 02667

2625 0 2626 2627 2630 2631 2632 2633 2634 2635 2636 2637 2640 2641 4 6 1 0 0 0 4 6 1 0 0 0

1,2043 1 0,0111 1,2566 0,0000 1,2043 1,2043 1,2043 0,0034 1,2561 0,0000 1,2043 1,2043 1,2043 1 0 0 1 1 1 1 1 0 1 1 1

TC fail ; verify ADk = %12524 CS ADk AD AD12524 CCS A TC fail TC fail TC fail ; verify overflow counter =%00001 CS OVFCNTR AD ADplus1 CCS A TC fail TC fail TC fail

; ; ; ; ; ; ; ; ; ; ; ;

get -A put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) get -A put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2642 3 2643 5 2644 5 2645 2646 2647 2650 2651 2652 2653 2654 2655 2656 2657 2660 2661 2662 2663 2664 3 6 5 0 4 6 1 0 0 0 4 6 1 0 0 0

1,2560 0 0,0034 0 0,0111 0 1,2567 1,2567 0,0111 1,2043 0,0111 1,2572 0,0000 1,2043 1,2043 1,2043 0,0034 1,2562 0,0000 1,2043 1,2043 1,2043 1 1 0 1 1 0 0 1 1 1 1 1 0 1 1 1

; TEST4: sum negative, overflow CAF ADplus0 TS OVFCNTR TS ADk ; add: %52525 + %52525 = %25253 (sign + 14 magnitude) CAF AD52525 AD AD52525 TS ADk ; store negative overflow TC fail ; verify ADk = %65253 CS ADk ; get -A AD AD65253 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify overflow counter =%77776 CS OVFCNTR ; get -A AD ADmin1 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) XCH savQ TS Q ; restore return address RETURN ---------------------------------------------TEST MASK INSTRUCTION SUBROUTINE L: MASK K Verifies the following: - Set C(A) = b(A) & C(K) DS DS DS DS EQU XCH TS MASKtst %46314 %25252 %04210 * Q savQ ; code for this test ; expected result: MASK1 & MASK2

2665 3 2666 5 2667 0

0,0101 1 0,0001 0 0,0000 0 ; ; ; ; ;

02670 02671 02672 02673 02674 02675 02676 02677 02700 02701 02702 02703 02704 02705 02706 02707 02710 02711 02712

2670 2671 2672 2673 2674 3 2675 5 2676 3 2677 7 2700 2701 2702 2703 2704 2705 4 6 1 0 0 0

00010 46314 25252 04210

0 0 0 0

MASKcode MASK1 MASK2 MASKval chkMASK

0,0001 0 0,0101 1 1,2671 0 1,2672 1 0,0000 1,2673 0,0000 1,2043 1,2043 1,2043 0 1 0 1 1 1

; save return address

; perform logical and of MASK1 and MASK2 CAF MASK1 MASK MASK2 ; verify C(A) = b(A) & C(K) COM ; get -A AD MASKval ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) CAF TS ; passed the test XCH TS RETURN MASKcode curtest savQ Q ; set test code to this test

2706 3 2707 5 2710 3 2711 5 2712 0

1,2670 1 0,0100 0 0,0101 1 0,0001 0 0,0000 0

; restore return address

; ---------------------------------------------; PASSED ALL TESTS! 02713 02714 02715 02716 2713 2714 3 2715 5 2716 0 12345 0 PASScode finish 1,2713 0 0,0100 0 0,0000 0 DS EQU CAF TS RETURN PASS * PASScode curtest

; set current test code to PASS

; ---------------------------------------------; INTERRUPT SERVICE ROUTINE goT3 goER goDS goKEY goUP endRUPT 02717 02720 02721 02722 2717 2720 2721 2722 3 5 3 2 0,0027 0,0001 0,0026 0,0000 1 0 0 1 EQU EQU EQU EQU EQU EQU XCH TS XCH RESUME * * * * * * QRUPT Q ARUPT

; restore Q ; restore A ; finished, go back

Assembly complete. Errors = 0 Symbol table: START INDEXtst TStst PASS curtest INDXval XCHkalt1 ADk ERRUPT UPRUPT end TCcode TCret1 CCSkM1 CCSkP1 CCSdM1 CCSdP1 INDXcode chkINDEX XCHfP0 XCHfalt2 CSkP0 CSkalt2 TSone TSmone chkTS ADplus1 AD12525 AD52525 AD65253 MASK1 chkMASK goT3 goKEY ARUPT A 000000 000003 000006 012345 000100 000103 000106 000111 002010 002024 002045 002052 002061 002075 002100 002103 002106 002234 002244 002270 002273 002374 002377 002440 002443 002446 002561 002564 002567 002572 002671 002674 002717 002717 000026 000000 TCtst XCHtst ADtst EXTENDER savQ XCHkP0 XCHkalt2 GOPROG DSRUPT goMAIN STRTcode Qtest CCScode CCSkM0 CCSkP2 CCSdM0 CCSdP2 INDXst INDXlop XCHfM0 chkXCH CSkM0 chkCS TSzero TSkP1 ADcode ADmin1 AD37777 AD65252 chkAD MASK2 PASScode goER goUP Q 000001 000004 000007 005777 000101 000104 000107 002000 002014 002030 002046 002053 002073 002076 002101 002104 002107 002235 002251 002271 002274 002375 002400 002441 002444 002557 002562 002565 002570 002573 002672 002713 002717 002717 000001 CCStst CStst MASKtst OVFCNTR CCSk XCHkM0 TSk T3RUPT KEYRUPT fail begin chkTC CCSkM2 CCSkP0 CCSdM2 CCSdP0 chkCCS INDXbas XCHcode XCHfalt1 CScode CSkalt1 TScode TSmzero TSkM1 ADplus0 AD25252 AD12524 AD40000 MASKcode MASKval finish goDS endRUPT QRUPT 000002 000005 000010 000034 000102 000105 000110 002004 002020 002043 002047 002054 002074 002077 002102 002105 002110 002236 002267 002272 002373 002376 002437 002442 002445 002560 002563 002566 002571 002670 002673 002714 002717 002717 000027

TECO2 assembler listing


Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM First pass: generate symbol table. Second pass: generate object code. ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; TECO2 (file:teco2.asm) Version: 1.0 Author: John Pultorak Date: 9/14/2001 PURPOSE: Test and checkout program for the Block 1 Apollo Guidance Computer. Tests extracode instructions: MP, DV, SU OPERATION: Enters an infinite loop at the end of the test. The A register contains the code for the test that failed, or the PASS code if all tests succeeded. See test codes below. ERRATA: - Written for the AGC4R assembler. The assembler directives and syntax differ somewhat from the original AGC assembler. - The tests attempt to check all threads, but are not exhaustive. SOURCES: Information on the Block 1 architecture: instruction set, instruction sequences, registers, register transfers, control pulses, memory and memory addressing, I/O assignments, interrupts, and involuntary counters was obtained from: A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. Supplementary information was obtained from: R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary MOD 3C Programmer's Manual", E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961. B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", E-2052, MIT Instrumentation Laboratory, Cambridge, MA, Jan. 1967. E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer Subsystem", R-700, MIT Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972. A. Hopkins, "Guidance Computer Design, Part VI", source unknown. A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964. E, C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA, Reston VA, 1996.

START MPtst DVtst SUtst

EQU EQU EQU EQU

%00 %01 %02 %03 ; MP check failed ; DV check failed ; SU check failed

PASS EQU %12345 ; PASSED all checks ; ---------------------------------------------05777 5777 47777 0 ORG DS EXTENDER %47777 ; needed for EXTEND

OVFCNTR

EQU

%00034

; overflow counter

; ---------------------------------------------; ERASEABLE MEMORY -- DATA SEGMENT 00100 00101 00102 00103 00104 00105 00106 00107 0100 0101 0102 0103 0104 0105 0106 0107 00000 1 curtest 00000 1 savQ ; MP test 00000 1 MPindex 00000 1 MPXTND ; DV test 00000 1 DVsavA 00000 1 DVindex 00000 1 DVXTND ; SU test 77777 0 SUk ORG DS DS DS DS DS DS DS DS %100 START %0 %0 %0 %0 %0 %0 -0 ; start of data area ; current test

; indexed extend

; indexed extend

; ---------------------------------------------; ENTRY POINTS ; program (re)start ORG 1,2030 0 TC GOPROG goMAIN

02000

2000 0

02004 02005 02006 02007 02010 02011 02012 02013 02014 02015 02016 02017 02020 02021 02022 02023

2004 2005 2006 2007 2010 2011 2012 2013 2014 2015 2016 2017 2020 2021 2022 2023

5 3 5 0 5 3 5 0 5 3 5 0 5 3 5 0

0,0026 0,0001 0,0027 1,2742 0,0026 0,0001 0,0027 1,2742 0,0026 0,0001 0,0027 1,2742 0,0026 0,0001 0,0027 1,2742

0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

; interrupt service entry points ORG T3RUPT TS ARUPT XCH Q TS QRUPT TC goT3 ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ERRUPT ARUPT Q QRUPT goER DSRUPT ARUPT Q QRUPT goDS KEYRUPT ARUPT Q QRUPT goKEY UPRUPT ARUPT Q QRUPT goUP

02024 02025 02026 02027

2024 2025 2026 2027

5 3 5 0

0,0026 0,0001 0,0027 1,2742

0 0 1 1

; ---------------------------------------------; FIXED MEMORY -- SHARED DATA SEGMENT ; ---------------------------------------------; MAIN PROGRAM goMAIN 02030 02031 02032 02033 02034 2030 2 2031 0 2032 0 2033 0 2034 0 0,0000 0 1,2042 0 1,2247 1 1,2551 1 1,2635 0 EQU INHINT TCR * ; disable interrupts begin

; Test extracode instructions. TCR chkMP TCR chkDV TCR chkSU

02035 02036 02037 02040

2035 0 2036 3 2037 5 2040 0

1,2737 0 0,0100 0 0,0100 0

; Passed all tests. TCR fail EQU XCH TS EQU TC

finish * curtest curtest * end ; load last passed test into A

end 1,2040 1

; finished, TC trap

; ---------------------------------------------; INITIALIZE FOR START OF TESTING 02041 02042 02043 02044 2041 2042 3 2043 5 2044 0 00000 1 STRTcode begin 1,2041 0 0,0100 0 0,0000 0 ; ; ; ; ; ; 02045 2045 DS EQU XCH TS RETURN START * STRTcode curtest

; set current test code to START

---------------------------------------------TEST MP INSTRUCTION SUBROUTINE L: MP K Verifies the following - Set C(A,LP) = b(A) * C(K) - Take next instruction from L+1 DS MPtst ; code for this test

00001 0 MPcode

02046

2046

; MP test values ; 00037 0 MPstart DS

31

; loop MPstart+1 times

02047 02050 02051 02052 02053 02054 02055 02056 02057 02060 02061 02062 02063 02064 02065 02066 02067 02070 02071 02072 02073 02074 02075 02076 02077 02100 02101 02102 02103 02104 02105 02106

2047 2050 2051 2052 2053 2054 2055 2056 2057 2060 2061 2062 2063 2064 2065 2066 2067 2070 2071 2072 2073 2074 2075 2076 2077 2100 2101 2102 2103 2104 2105 2106

37777 37777 40000 40000 00000 00000 77777 77777 00007 00021 00035 00051 00065 00103 00117 00141 00153 00177 00375 00305 00655 00537 02455 02053 11151 07025 20032 17065 30273 26355 37553 36014

1 1 0 0 1 1 0 0 0 1 1 0 1 0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0 0 1

; C(A) test values mp1 EQU * ; check boundary conditions DS %37777 ; check DS %37777 ; check DS %40000 ; check DS %40000 ; check DS %00000 ; check DS %00000 ; check DS %77777 ; check DS %77777 ; check ; randomly selected checks (one word product) DS %00007 ; check DS %00021 ; check DS %00035 ; check DS %00051 ; check DS %00065 ; check DS %00103 ; check DS %00117 ; check DS %00141 ; check DS %00153 ; check DS %00177 ; check ; randomly selected checks (two word product) DS %00375 ; check DS %00305 ; check DS %00655 ; check DS %00537 ; check DS %02455 ; check DS %02053 ; check DS %11151 ; check DS %07025 ; check DS %20032 ; check DS %17065 ; check DS %30273 ; check DS %26355 ; check DS %37553 ; check DS %36014 ; check

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+16383 * (+16383 * (-16383 * (-16383 * (+0 * +0) (+0 * -0) (-0 * +0) (-0 * -0)

+16383) -16383) +16383) -16383)

(7 * 17) (17 * 7) (29 * 41) (41 * 29) (53 * 67) (67 * 53) (79 * 97) (97 * 79) (107 * 127) (127 * 107) (253 * 197) (197 * 253) (429 * 351) (351 * 429) (1325 * 1067) (1067 * 1325) (4713 * 3605) (3605 * 4713) (8218 * 7733) (7733 * 8218) (12475 * 11501) (11501 * 12475) (16235 * 15372) (15372 * 16235)

02107

2107

; C(K) test values mp2 EQU * ; check boundary conditions 37777 1 DS %37777

; check #00 (+16383 * +16383)

02110 02111 02112 02113 02114 02115 02116 02117 02120 02121 02122 02123 02124 02125 02126 02127 02130 02131 02132 02133 02134 02135 02136 02137 02140 02141 02142 02143 02144 02145 02146

2110 2111 2112 2113 2114 2115 2116 2117 2120 2121 2122 2123 2124 2125 2126 2127 2130 2131 2132 2133 2134 2135 2136 2137 2140 2141 2142 2143 2144 2145 2146

40000 37777 40000 00000 77777 00000 77777

DS %40000 ; check DS %37777 ; check DS %40000 ; check DS %00000 ; check DS %77777 ; check DS %00000 ; check DS %77777 ; check ; randomly selected checks (one word product) 00021 1 DS %00021 ; check 00007 0 DS %00007 ; check 00051 0 DS %00051 ; check 00035 1 DS %00035 ; check 00103 0 DS %00103 ; check 00065 1 DS %00065 ; check 00141 0 DS %00141 ; check 00117 0 DS %00117 ; check 00177 0 DS %00177 ; check 00153 0 DS %00153 ; check ; randomly selected checks (two word product) 00305 1 DS %00305 ; check 00375 0 DS %00375 ; check 00537 0 DS %00537 ; check 00655 1 DS %00655 ; check 02053 0 DS %02053 ; check 02455 1 DS %02455 ; check 07025 1 DS %07025 ; check 11151 1 DS %11151 ; check 17065 1 DS %17065 ; check 20032 1 DS %20032 ; check 26355 0 DS %26355 ; check 30273 1 DS %30273 ; check 36014 1 DS %36014 ; check 37553 0 DS %37553 ; check ; A = upper product MPchkA EQU * ; check boundary conditions DS %37776 ; check DS %40001 ; check DS %40001 ; check DS %37776 ; check DS %00000 ; check DS %77777 ; check DS %77777 ; check DS %00000 ; check ; randomly selected checks DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check ; randomly selected checks (two word product) DS %00003 ; check DS %00003 ; check DS %00011 ; check DS %00011 ; check DS %00126 ; check DS %00126 ; check DS %02015 ; check DS %02015 ; check DS %07446 ; check DS %07446 ; check DS %21065 ; check DS %21065 ; check DS %35600 ; check DS %35600 ; check

0 1 0 1 0 1 0

#01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+16383 * -16383) (-16383 * +16383) (-16383 * -16383) (+0 * +0) (+0 * -0) (-0 * +0) (-0 * -0) (7 * 17) (17 * 7) (29 * 41) (41 * 29) (53 * 67) (67 * 53) (79 * 97) (97 * 79) (107 * 127) (127 * 107) (253 * 197) (197 * 253) (429 * 351) (351 * 429) (1325 * 1067) (1067 * 1325) (4713 * 3605) (3605 * 4713) (8218 * 7733) (7733 * 8218) (12475 * 11501) (11501 * 12475) (16235 * 15372) (15372 * 16235)

02147 02150 02151 02152 02153 02154 02155 02156 02157 02160 02161 02162 02163 02164 02165 02166 02167 02170 02171 02172 02173 02174 02175 02176 02177 02200 02201 02202 02203 02204 02205 02206

2147 2150 2151 2152 2153 2154 2155 2156 2157 2160 2161 2162 2163 2164 2165 2166 2167 2170 2171 2172 2173 2174 2175 2176 2177 2200 2201 2202 2203 2204 2205 2206

37776 40001 40001 37776 00000 77777 77777 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00003 00003 00011 00011 00126 00126 02015 02015 07446 07446 21065 21065 35600 35600

0 1 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31 (7 * 17) (17 * 7) (29 * 41) (41 * 29) (53 * 67) (67 * 53) (79 * 97) (97 * 79) (107 * 127) (127 * 107) (253 * 197) (197 * 253) (429 * 351) (351 * 429) (1325 * 1067) (1067 * 1325) (4713 * 3605) (3605 * 4713) (8218 * 7733) (7733 * 8218) (12475 * 11501) (11501 * 12475) (16235 * 15372) (15372 * 16235)

02207

2207

; LP = lower product MPchkLP EQU * ; check boundary conditions 00001 0 DS %00001

; check #00

02210 02211 02212 02213 02214 02215 02216 02217 02220 02221 02222 02223 02224 02225 02226 02227 02230 02231 02232 02233 02234 02235 02236 02237 02240 02241 02242 02243 02244 02245 02246 02247 02250 02251 02252

2210 2211 2212 2213 2214 2215 2216 2217 2220 2221 2222 2223 2224 2225 2226 2227 2230 2231 2232 2233 2234 2235 2236 2237 2240 2241 2242 2243 2244 2245 2246 2247 3 2250 5 2251 3 2252 5

77776 77776 00001 00000 77777 77777 00000

DS %77776 ; check DS %77776 ; check DS %00001 ; check DS %00000 ; check DS %77777 ; check DS %77777 ; check DS %00000 ; check ; randomly selected checks 00167 1 DS %00167 ; check 00167 1 DS %00167 ; check 02245 0 DS %02245 ; check 02245 0 DS %02245 ; check 06737 1 DS %06737 ; check 06737 1 DS %06737 ; check 16757 0 DS %16757 ; check 16757 0 DS %16757 ; check 32425 0 DS %32425 ; check 32425 0 DS %32425 ; check ; randomly selected checks (two word product) 01261 0 DS %01261 ; check 01261 0 DS %01261 ; check 06063 1 DS %06063 ; check 06063 1 DS %06063 ; check 11217 0 DS %11217 ; check 11217 0 DS %11217 ; check 00235 0 DS %00235 ; check 00235 0 DS %00235 ; check 30542 1 DS %30542 ; check 30542 1 DS %30542 ; check 00437 1 DS %00437 ; check 00437 1 DS %00437 ; check 06404 1 DS %06404 ; check 06404 1 DS %06404 ; check chkMP 0,0001 0 0,0101 1 1,2045 1 0,0100 0 EQU XCH TS CAF TS * Q savQ MPcode curtest

1 1 0 1 0 0 1

#01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #24 #26 #27 #28 #29 #30 #31 (7 * 17) (17 * 7) (29 * 41) (41 * 29) (53 * 67) (67 * 53) (79 * 97) (97 * 79) (107 * 127) (127 * 107) (253 * 197) (197 * 253) (429 * 351) (351 * 429) (1325 * 1067) (1067 * 1325) (4713 * 3605) (3605 * 4713) (8218 * 7733) (7733 * 8218) (12475 * 11501) (11501 * 12475) (16235 * 15372) (15372 * 16235)

; save return address ; set test code to this test

; Decrementing loop ; - always executes at least once (tests at end of loop) ; 02253 2253 3 1,2046 1 - loops 'MPstart+1' times; decrements MPindex XCH MPstart ; initialize loop counter

02254 02255 02256 02257 02260 02261 02262 02263 02264 02265 02266 02267 02270 02271 02272 02273 02274 02275 02276

2254 5 2255 3 2256 6 2257 5 2260 2261 2262 2263 2264 2265 2266 2267 2270 2271 2272 2273 2274 2275 2276 2 3 2 4 4 2 6 1 0 0 0 4 2 6 1

;-----------------------------; MP check starts here ; uses MPindex to access test values MPloop EQU * 0,0102 1 TS MPindex 2,5777 0 0,0102 1 0,0103 0 0,0102 1,2047 0,0103 1,2107 0,0000 0,0102 1,2147 0,0000 1,2036 1,2036 1,2036 0,0003 0,0102 1,2207 0,0000 0 0 1 1 ; verify C(A) 0 0 1 0 0 0 0 ; verify C(LP) 0 0 0 0 CS INDEX AD CCS LP MPindex MPchkLP A COM INDEX AD CCS TC TC TC CAF AD TS INDEX CAF INDEX MP EXTENDER MPindex MPXTND MPindex mp1 MPXTND mp2

; save new index

; EXTEND using MPindex

; get -A MPindex MPchkA A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

; get -A ; put (-A) + expected value in A ; compare

02277 02300 02301

2277 0 2300 0 2301 0

1,2036 0 1,2036 0 1,2036 0

TC TC TC

fail fail fail

; >0 (A < expected value) ; +0 ; <0 (A > expected value)

; end of MP check ;-----------------------------02302 02303 02304 02305 02306 2302 1 2303 0 2304 3 2305 5 2306 0 0,0102 0 1,2254 0 0,0101 1 0,0001 0 0,0000 0 ; ; ; ; ; ; ; ; ; 02307 2307 CCS TC MPindex MPloop ; done? ; not yet, do next check

XCH savQ TS Q ; restore return address RETURN ---------------------------------------------TEST DV INSTRUCTION SUBROUTINE L: DV K Verifies the following: - Set C(A) = b(A) / C(K) - Set C(Q) = - abs(remainder) - Set C(LP) > 0 if quotient is positive - Set C(LP) < 0 if quotient is negative - Take next instruction from L+1 DS DVtst ; code for this test

00002 0 DVcode

02310

2310

; DV test values ; 00037 0 DVstart DS ; C(A) test values div1 EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; C(K) test values div2 EQU DS DS DS DS

31 * %00000 %00000 %77777 %77777 %00000 %00000 %77777 %77777 %00000 %00000 %77777 %77777 %37776 %37776 %40001 %40001 %37777 %37777 %40000 %40000 %00001 %00001 %00001 %00001 %00001 %00001 %00001 %00001 %00002 %00004 %00010 %00020 * %00000 %77777 %00000 %77777

; loop DVstart+1 times

02311 02312 02313 02314 02315 02316 02317 02320 02321 02322 02323 02324 02325 02326 02327 02330 02331 02332 02333 02334 02335 02336 02337 02340 02341 02342 02343 02344 02345 02346 02347 02350

2311 2312 2313 2314 2315 2316 2317 2320 2321 2322 2323 2324 2325 2326 2327 2330 2331 2332 2333 2334 2335 2336 2337 2340 2341 2342 2343 2344 2345 2346 2347 2350

00000 00000 77777 77777 00000 00000 77777 77777 00000 00000 77777 77777 37776 37776 40001 40001 37777 37777 40000 40000 00001 00001 00001 00001 00001 00001 00001 00001 00002 00004 00010 00020

1 1 0 0 1 1 0 0 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+0/+0) (+0/-0) (-0/+0) (-0/-0) (+0/+1) (+0/-1) (-0/+1) (-0/-1) (+0/+16383) (+0/-16383) (-0/+16383) (-0/-16383) (+16382/+16383) (+16382/-16383) (-16382/+16383) (-16382/-16383) (+16383/+16383) (+16383/-16383) (-16383/+16383) (-16383/-16383) (+1/+2) (+1/+3) (+1/+4) (+1/+5) (+1/+6) (+1/+7) (+1/+8) (+1/+6) (+2/+12) (+4/+24) (+8/+48) (+16/+96)

02351 02352 02353 02354

2351 2352 2353 2354

00000 77777 00000 77777

1 0 1 0

; ; ; ;

check check check check

#00 #01 #02 #03

(+0/+0) (+0/-0) (-0/+0) (-0/-0)

02355 02356 02357 02360 02361 02362 02363 02364 02365 02366 02367 02370 02371 02372 02373 02374 02375 02376 02377 02400 02401 02402 02403 02404 02405 02406 02407 02410

2355 2356 2357 2360 2361 2362 2363 2364 2365 2366 2367 2370 2371 2372 2373 2374 2375 2376 2377 2400 2401 2402 2403 2404 2405 2406 2407 2410

00001 77776 00001 77776 37777 40000 37777 40000 37777 40000 37777 40000 37777 40000 37777 40000 00002 00003 00004 00005 00006 00007 00010 00006 00014 00030 00060 00140

0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 0 1 0 1 1 0 0 1 1 1 1 1

DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; A = quotient DVchkA EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

%00001 %77776 %00001 %77776 %37777 %40000 %37777 %40000 %37777 %40000 %37777 %40000 %37777 %40000 %37777 %40000 %00002 %00003 %00004 %00005 %00006 %00007 %00010 %00006 %00014 %00030 %00060 %00140 * %37777 %40000 %40000 %37777 %00000 %77777 %77777 %00000 %00000 %77777 %77777 %00000 %37776 %40001 %40001 %37776 %37777 %40000 %40000 %37777 %20000 %12525 %10000 %06314 %05252 %04444 %04000 %05252 %05252 %05252 %05252 %05252

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check check check check check check check check check check check check check check

#04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+0/+1) (+0/-1) (-0/+1) (-0/-1) (+0/+16383) (+0/-16383) (-0/+16383) (-0/-16383) (+16382/+16383) (+16382/-16383) (-16382/+16383) (-16382/-16383) (+16383/+16383) (+16383/-16383) (-16383/+16383) (-16383/-16383) (+1/+2) (+1/+3) (+1/+4) (+1/+5) (+1/+6) (+1/+7) (+1/+8) (+1/+6) (+2/+12) (+4/+24) (+8/+48) (+16/+96)

02411 02412 02413 02414 02415 02416 02417 02420 02421 02422 02423 02424 02425 02426 02427 02430 02431 02432 02433 02434 02435 02436 02437 02440 02441 02442 02443 02444 02445 02446 02447 02450

2411 2412 2413 2414 2415 2416 2417 2420 2421 2422 2423 2424 2425 2426 2427 2430 2431 2432 2433 2434 2435 2436 2437 2440 2441 2442 2443 2444 2445 2446 2447 2450

37777 40000 40000 37777 00000 77777 77777 00000 00000 77777 77777 00000 37776 40001 40001 37776 37777 40000 40000 37777 20000 12525 10000 06314 05252 04444 04000 05252 05252 05252 05252 05252

1 0 0 1 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+0/+0) (+0/-0) (-0/+0) (-0/-0) (+0/+1) (+0/-1) (-0/+1) (-0/-1) (+0/+16383) (+0/-16383) (-0/+16383) (-0/-16383) (+16382/+16383) (+16382/-16383) (-16382/+16383) (-16382/-16383) (+16383/+16383) (+16383/-16383) (-16383/+16383) (-16383/-16383) (+1/+2) (+1/+3) (+1/+4) (+1/+5) (+1/+6) (+1/+7) (+1/+8) (+1/+6) (+2/+12) (+4/+24) (+8/+48) (+16/+96)

02451 02452 02453 02454 02455 02456 02457 02460 02461 02462 02463 02464 02465 02466 02467 02470 02471 02472 02473 02474 02475 02476 02477 02500 02501 02502 02503 02504 02505 02506 02507 02510

2451 2452 2453 2454 2455 2456 2457 2460 2461 2462 2463 2464 2465 2466 2467 2470 2471 2472 2473 2474 2475 2476 2477 2500 2501 2502 2503 2504 2505 2506 2507 2510

77777 77777 77777 77777 77777 77777 77777 77777 77777 77777 77777 77777 40001 40001 40001 40001 40000 40000 40000 40000 77777 77776 77777 77773 77773 77773 77777 77773 77767 77757 77737 77677

0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 1 1 1 0 1 1 1 1 1

; Q = remainder DVchkQ EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS ; LP = sign DVchkLP EQU DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS DS

* %77777 %77777 %77777 %77777 %77777 %77777 %77777 %77777 %77777 %77777 %77777 %77777 %40001 %40001 %40001 %40001 %40000 %40000 %40000 %40000 %77777 %77776 %77777 %77773 %77773 %77773 %77777 %77773 %77767 %77757 %77737 %77677 * %00001 %40000 %40001 %00001 %00001 %40000 %40001 %00001 %00001 %40000 %40001 %00001 %00001 %40000 %40001 %00001 %00001 %40000 %40001 %00001 %00001 %00001 %00001 %00001 %00001 %00001 %00001

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check check

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26 #27 #28 #29 #30 #31

(+0/+0) (+0/-0) (-0/+0) (-0/-0) (+0/+1) (+0/-1) (-0/+1) (-0/-1) (+0/+16383) (+0/-16383) (-0/+16383) (-0/-16383) (+16382/+16383) (+16382/-16383) (-16382/+16383) (-16382/-16383) (+16383/+16383) (+16383/-16383) (-16383/+16383) (-16383/-16383) (+1/+2) (+1/+3) (+1/+4) (+1/+5) (+1/+6) (+1/+7) (+1/+8) (+1/+6) (+2/+12) (+4/+24) (+8/+48) (+16/+96)

02511 02512 02513 02514 02515 02516 02517 02520 02521 02522 02523 02524 02525 02526 02527 02530 02531 02532 02533 02534 02535 02536 02537 02540 02541 02542 02543

2511 2512 2513 2514 2515 2516 2517 2520 2521 2522 2523 2524 2525 2526 2527 2530 2531 2532 2533 2534 2535 2536 2537 2540 2541 2542 2543

00001 40000 40001 00001 00001 40000 40001 00001 00001 40000 40001 00001 00001 40000 40001 00001 00001 40000 40001 00001 00001 00001 00001 00001 00001 00001 00001

0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0

; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check check check check check check check check check check check check check

#00 #01 #02 #03 #04 #05 #06 #07 #08 #09 #10 #11 #12 #13 #14 #15 #16 #17 #18 #19 #20 #21 #22 #23 #24 #25 #26

(+0/+0) (+0/-0) (-0/+0) (-0/-0) (+0/+1) (+0/-1) (-0/+1) (-0/-1) (+0/+16383) (+0/-16383) (-0/+16383) (-0/-16383) (+16382/+16383) (+16382/-16383) (-16382/+16383) (-16382/-16383) (+16383/+16383) (+16383/-16383) (-16383/+16383) (-16383/-16383) (+1/+2) (+1/+3) (+1/+4) (+1/+5) (+1/+6) (+1/+7) (+1/+8)

02544 02545 02546 02547 02550

2544 2545 2546 2547 2550

00001 00001 00001 00001 00001

0 0 0 0 0 chkDV

DS DS DS DS DS EQU XCH TS CAF TS

%00001 %00001 %00001 %00001 %00001 * Q savQ DVcode curtest

; ; ; ; ;

check check check check check

#27 #28 #29 #30 #31

(+1/+6) (+2/+12) (+4/+24) (+8/+48) (+16/+96)

02551 02552 02553 02554

2551 3 2552 5 2553 3 2554 5

0,0001 0 0,0101 1 1,2307 1 0,0100 0

; save return address ; set code identifying test

; Decrementing loop ; - always executes at least once (tests at end of loop) ; 02555 2555 3 1,2310 1 - loops 'DVstart+1' times; decrements DVindex XCH DVstart ; initialize loop counter

;-----------------------------; DV check starts here ; uses DVindex to access test values DVloop EQU * 0,0105 0 TS DVindex 2,5777 0 0,0105 0 0,0106 0 0,0105 1,2311 0,0106 1,2351 0,0104 0,0001 0,0105 1,2451 0,0000 1,2036 1,2036 1,2036 0,0104 0,0105 1,2411 0,0000 1,2036 1,2036 1,2036 0,0003 0,0105 1,2511 0,0000 1,2036 1,2036 1,2036 1 0 1 1 1 ; verify C(Q) 02567 02570 02571 02572 02573 02574 02575 02576 02577 02600 02601 02602 02603 02604 02605 02606 02607 02610 02611 02612 02613 2567 2570 2571 2572 2573 2574 2575 2576 2577 2600 2601 2602 2603 2604 2605 2606 2607 2610 2611 2612 2613 4 2 6 1 0 0 0 4 2 6 1 0 0 0 4 2 6 1 0 0 0 1 1 0 0 0 0 0 ; verify C(A) 0 1 1 0 0 0 0 ; verify C(LP) 0 1 0 0 0 0 0 CS INDEX AD CCS TC TC TC LP DVindex DVchkLP A fail fail fail ; get -A ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) CS INDEX AD CCS TC TC TC DVsavA DVindex DVchkA A fail fail fail ; get -A ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) CS INDEX AD CCS TC TC TC Q DVindex DVchkQ A fail fail fail ; get -A ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) CAF AD TS INDEX CAF INDEX DV TS EXTENDER DVindex DVXTND DVindex div1 DVXTND div2 DVsavA

02556 02557 02560 02561 02562 02563 02564 02565 02566

2556 5 2557 3 2560 6 2561 5 2562 2563 2564 2565 2566 2 3 2 5 5

; save new index

; EXTEND using DVindex

; end of DV check ;-----------------------------02614 02615 02616 02617 02620 2614 1 2615 0 2616 3 2617 5 2620 0 0,0105 1 1,2556 0 0,0101 1 0,0001 0 0,0000 0 CCS TC DVindex DVloop ; done? ; not yet, do next check

XCH savQ TS Q ; restore return address RETURN ; ---------------------------------------------; TEST SU INSTRUCTION SUBROUTINE

; ; ; ; ; ; ; ; 02621 02622 02623 02624 02625 02626 02627 02630 02631 02632 02633 02634 02635 02636 02637 02640 2621 2622 2623 2624 2625 2626 2627 2630 2631 2632 2633 2634 2635 3 2636 5 2637 3 2640 5

L: SU K Verifies the following: - Set C(A) = b(A) - C(K) - Take next instruction from L+1 - if C(A) has positive overflow, -- increment overflow counter by 1 - if C(A) has negative overflow, -- decrement overflow counter by 1 DS DS DS DS DS DS DS DS DS DS DS DS EQU XCH TS CAF TS SUtst +0 1 -1 %25252 %12525 %37777 %12524 %52525 %65252 %40000 %65253 * Q savQ SUcode curtest ; ; ; ; ; ; ; ; +10922 decimal +5461 decimal largest positive number + overflow of %25252+%25252 -10922 decimal -5461 decimal largest negative number - overflow of %52525+65252 ; code for this test

00003 1 SUcode 00000 1 SUplus0 00001 0 SUplus1 77776 1 SUmin1 25252 12525 37777 12524 52525 65252 40000 65253 0 0 1 1 1 1 0 0 SU25252 SU12525 SU37777 SU12524 SU52525 SU65252 SU40000 SU65253 chkSU 0,0001 0 0,0101 1 1,2621 0 0,0100 0 ; ; ; ;

; save return address ; set test code to this test

NOTE: these test are similar to the checks for AD, but the AD augend value has been changed to negative and AD has been changed to SU. The results produced by this change are identical to AD, and so the checks are the same.

02641 02642 02643 02644 02645 02646 02647 02650 02651

2641 3 2642 2 2643 6 2644 2645 2646 2647 2650 2651 4 6 1 0 0 0

1,2625 1 0,0000 1 1,2632 1 0,0000 1,2627 0,0000 1,2036 1,2036 1,2036 0 0 0 0 0 0

; TEST1: difference positive, no overflow ; sub: %25252 - %65252 = %37777 (sign + 14 magnitude) CAF SU25252 EXTEND SU SU65252 ; verify C(A) = %37777 COM ; get -A AD SU37777 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST2: difference negative, no overflow (sign + 14 magnitude) ; sub: %52525 - %12525 = %40000 CAF SU52525 EXTEND SU SU12525 ; verify C(A) = %40000 COM ; get -A AD SU40000 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; TEST3: difference positive, overflow ; initialize overflow counter and positive overflow storage CAF SUplus0 TS OVFCNTR TS SUk ; sub: %25252 - %52525 = %52524 (sign + 14 magnitude) CAF SU25252 EXTEND SU SU52525 TS SUk ; store positive overflow TC fail ; verify SUk = %12524 CS SUk ; get -A

02652 02653 02654 02655 02656 02657 02660 02661 02662

2652 3 2653 2 2654 6 2655 2656 2657 2660 2661 2662 4 6 1 0 0 0

1,2631 1 0,0000 1 1,2626 1 0,0000 1,2633 0,0000 1,2036 1,2036 1,2036 0 0 0 0 0 0

02663 02664 02665 02666 02667 02670 02671 02672 02673

2663 3 2664 5 2665 5 2666 2667 2670 2671 2672 3 2 6 5 0

1,2622 0 0,0034 0 0,0107 1 1,2625 0,0000 1,2631 0,0107 1,2036 1 1 1 1 0

2673 4

0,0107 0

02674 02675 02676 02677 02700 02701 02702 02703 02704 02705 02706 02707 02710 02711 02712 02713 02714 02715 02716 02717 02720 02721 02722 02723 02724 02725 02726 02727 02730 02731 02732 02733 02734 02735

2674 2675 2676 2677 2700 2701 2702 2703 2704 2705 2706

6 1 0 0 0 4 6 1 0 0 0

1,2630 0,0000 1,2036 1,2036 1,2036

AD SU12524 CCS A TC fail TC fail TC fail ; verify overflow counter =%00001 0,0034 1 CS OVFCNTR 1,2623 1 AD SUplus1 0,0000 0 CCS A 1,2036 0 TC fail 1,2036 0 TC fail 1,2036 0 TC fail 1,2622 0 0,0034 0 0,0107 1 1,2631 0,0000 1,2625 0,0107 1,2036 0,0107 1,2634 0,0000 1,2036 1,2036 1,2036 0,0034 1,2624 0,0000 1,2036 1,2036 1,2036 1 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0

0 0 0 0 0

; ; ; ; ; ; ; ; ; ; ;

put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value) get -A put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2707 3 2710 5 2711 5 2712 2713 2714 2715 2716 2717 2720 2721 2722 2723 2724 2725 2726 2727 2730 2731 2732 3 2 6 5 0 4 6 1 0 0 0 4 6 1 0 0 0

; TEST4: difference negative, overflow CAF SUplus0 TS OVFCNTR TS SUk ; add: %52525 + %25252 = %25253 (sign + 14 magnitude) CAF SU52525 EXTEND SU SU25252 TS SUk ; store negative overflow TC fail ; verify SUk = %65253 CS SUk ; get -A AD SU65253 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) ; verify overflow counter =%77776 CS OVFCNTR ; get -A AD SUmin1 ; put (-A) + expected value in A CCS A ; compare TC fail ; >0 (A < expected value) TC fail ; +0 TC fail ; <0 (A > expected value) XCH savQ TS Q ; restore return address RETURN ; ---------------------------------------------; PASSED ALL TESTS! DS EQU CAF TS RETURN PASS * PASScode curtest

2733 3 2734 5 2735 0

0,0101 1 0,0001 0 0,0000 0

02736 02737 02740 02741

2736 2737 3 2740 5 2741 0

12345 0 PASScode finish 1,2736 1 0,0100 0 0,0000 0

; set current test code to PASS

; ---------------------------------------------; INTERRUPT SERVICE ROUTINE goT3 goER goDS goKEY goUP endRUPT 02742 02743 02744 02745 2742 2743 2744 2745 3 5 3 2 0,0027 0,0001 0,0026 0,0000 1 0 0 1 EQU EQU EQU EQU EQU EQU XCH TS XCH RESUME * * * * * * QRUPT Q ARUPT

; restore Q ; restore A ; finished, go back

Assembly complete. Errors = 0 Symbol table: START SUtst OVFCNTR 000000 000003 000034 MPtst PASS curtest 000001 012345 000100 DVtst EXTENDER savQ 000002 005777 000101

MPindex DVindex GOPROG DSRUPT goMAIN STRTcode MPstart MPchkA MPloop div1 DVchkQ DVloop SUplus1 SU12525 SU52525 SU65253 finish goDS endRUPT QRUPT

000102 000105 002000 002014 002030 002041 002046 002147 002254 002311 002451 002556 002623 002626 002631 002634 002737 002742 002742 000027

MPXTND DVXTND T3RUPT KEYRUPT fail begin mp1 MPchkLP DVcode div2 DVchkLP SUcode SUmin1 SU37777 SU65252 chkSU goT3 goKEY ARUPT A

000103 000106 002004 002020 002036 002042 002047 002207 002307 002351 002511 002621 002624 002627 002632 002635 002742 002742 000026 000000

DVsavA SUk ERRUPT UPRUPT end MPcode mp2 chkMP DVstart DVchkA chkDV SUplus0 SU25252 SU12524 SU40000 PASScode goER goUP Q LP

000104 000107 002010 002024 002040 002045 002107 002247 002310 002411 002551 002622 002625 002630 002633 002736 002742 002742 000001 000003

TECO3 assembler listing


Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM First pass: generate symbol table. Second pass: generate object code. ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; TECO3 (file:teco3.asm) Version: 1.0 Author: John Pultorak Date: 9/14/2001 PURPOSE: Test and checkout program for the Block 1 Apollo Guidance Computer. Tests editing registers: CYR, SR, CYL, SL. OPERATION: Enters an infinite loop at the end of the test. The A register contains the code for the test that failed, or the PASS code if all tests succeeded. See test codes below. ERRATA: - Written for the AGC4R assembler. The assembler directives and syntax differ somewhat from the original AGC assembler. - The tests attempt to check all threads, but are not exhaustive. SOURCES: Information on the Block 1 architecture: instruction set, instruction sequences, registers, register transfers, control pulses, memory and memory addressing, I/O assignments, interrupts, and involuntary counters was obtained from: A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. Supplementary information was obtained from: R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary MOD 3C Programmer's Manual", E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961. B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", E-2052, MIT Instrumentation Laboratory, Cambridge, MA, Jan. 1967. E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer Subsystem", R-700, MIT Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972. A. Hopkins, "Guidance Computer Design, Part VI", source unknown. A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964. E, C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA, Reston VA, 1996. EQU EQU EQU EQU EQU %00 %01 %02 %03 %04 ; ; ; ; CYR check failed SR check failed CYL check failed SL check failed

START CYRtst SRtst CYLtst SLtst

PASS EQU %12345 ; PASSED all checks ; ---------------------------------------------05777 5777 47777 0 ORG DS EXTENDER %47777 ; needed for EXTEND

; ---------------------------------------------; ERASEABLE MEMORY -- DATA SEGMENT 00100 00101 00102 00103 00104 00105 00106 00107 00110 00111 0100 0101 0102 0103 0104 0105 0106 0107 0110 0111 00000 1 curtest 00000 1 savQ ORG DS DS %100 START %0 %0 %0 %0 %0 %0 %0 %0 %0 ; start of data area ; current test

; CYR test values 00000 1 CYRval DS 00000 1 iCYR DS ; SR test values 00000 1 SRval DS 00000 1 iSR DS ; CYL test values 00000 1 CYLval DS 00000 1 iCYL DS ; SL test values 00000 1 SLval DS 00000 1 iSL DS

; current test value ; current index ; current test value ; current index ; current test value ; current index ; current test value ; current index

; ---------------------------------------------; ENTRY POINTS ; program (re)start ORG 1,2030 0 TC GOPROG goMAIN

02000

2000 0

02004 02005 02006 02007 02010 02011 02012 02013 02014 02015 02016 02017 02020 02021 02022 02023

2004 2005 2006 2007 2010 2011 2012 2013 2014 2015 2016 2017 2020 2021 2022 2023

5 3 5 0 5 3 5 0 5 3 5 0 5 3 5 0

0,0026 0,0001 0,0027 1,2424 0,0026 0,0001 0,0027 1,2424 0,0026 0,0001 0,0027 1,2424 0,0026 0,0001 0,0027 1,2424

0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1

; interrupt service entry points ORG T3RUPT TS ARUPT XCH Q TS QRUPT TC goT3 ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ORG TS XCH TS TC ERRUPT ARUPT Q QRUPT goER DSRUPT ARUPT Q QRUPT goDS KEYRUPT ARUPT Q QRUPT goKEY UPRUPT ARUPT Q QRUPT goUP

02024 02025 02026 02027

2024 2025 2026 2027

5 3 5 0

0,0026 0,0001 0,0027 1,2424

0 0 1 1

; ---------------------------------------------; FIXED MEMORY -- SHARED DATA SEGMENT ; ---------------------------------------------; MAIN PROGRAM goMAIN 02030 02031 02032 2030 2 2031 0 2032 0 0,0000 0 1,2043 1 1,2070 1 EQU INHINT TCR * ; disable interrupts begin

; Test extracode instructions. TCR chkCYR

02033 02034 02035 02036 02037 02040 02041

2033 0 2034 0 2035 0 2036 0 2037 3 2040 5 2041 0

1,2162 0 1,2255 1 1,2347 0 1,2421 1 0,0100 0 0,0100 0 end 1,2041 0

TCR TCR TCR ; Passed all tests. TCR fail EQU XCH TS EQU TC

chkSR chkCYL chkSL finish * curtest curtest * end ; load last passed test into A

; finished, TC trap

; ---------------------------------------------; INITIALIZE FOR START OF TESTING 02042 02043 02044 02045 2042 2043 3 2044 5 2045 0 00000 1 STRTcode begin 1,2042 0 0,0100 0 0,0000 0 ; ; ; ; ; ; 02046 02047 02050 2046 2047 2050 DS EQU XCH TS RETURN START * STRTcode curtest

; set current test code to START

---------------------------------------------TEST CYR EDITING FUNCTION SUBROUTINE Rotate a test value right through CYR 15 times. Test the value against an expected value for each time. After 15 rotations, the value should equal the initial value. DS CYRtst %03431 14 ; code for this test ; init test value ; loop CYRindx+1 times

00001 0 CYRcode

; CYR test values 03431 1 CYRinit DS 00016 0 CYRindx DS

02051 02052 02053 02054 02055 02056 02057 02060 02061 02062 02063 02064 02065 02066 02067 02070 02071 02072 02073 02074 02075 02076 02077 02100 02101 02102 02103

2051 2052 2053 2054 2055 2056 2057 2060 2061 2062 2063 2064 2065 2066 2067 2070 3 2071 5 2072 3 2073 5 2074 3 2075 5 2076 3 2077 5 2100 2101 2102 2103 3 5 3 5

03431 07062 16144 34310 70620 61441 43103 06207 14416 31034 62070 44161 10343 20706 41614

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

; check CYR against these values CYRbase EQU * DS %03431 DS %07062 DS %16144 DS %34310 DS %70620 DS %61441 DS %43103 DS %06207 DS %14416 DS %31034 DS %62070 DS %44161 DS %10343 DS %20706 DS %41614 chkCYR EQU XCH TS CAF TS XCH TS XCH CYRloop EQU TS * Q savQ CYRcode curtest CYRinit CYRval CYRindx * iCYR CYRval CYR CYR CYRval

; ; ; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check check check

#0 (back to start) #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14

0,0001 0 0,0101 1 1,2046 1 0,0100 0 1,2047 0 0,0102 1 1,2050 0 0,0103 0 0,0102 0,0020 0,0020 0,0102 1 0 0 1

; save return address ; set test code to this test ; init value to rotate ; load init index ; save index

; rotate A right (CYR) XCH TS XCH TS

; rotate ; put result in A

; verify C(A) 02104 02105 02106 02107 02110 02111 02112 02113 02114 02115 02116 02117 2104 2105 2106 2107 2110 2111 2112 4 2 6 1 0 0 0 0,0000 0,0103 1,2051 0,0000 1,2037 1,2037 1,2037 0 1 1 0 1 1 1 COM INDEX AD CCS TC TC TC ; get -A iCYR CYRbase A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2113 1 2114 0 2115 3 2116 5 2117 0

0,0103 1 1,2077 0 0,0101 1 0,0001 0 0,0000 0

; loop back to test next value CCS iCYR TC CYRloop XCH TS RETURN ; ; ; ; ; savQ Q

; done? ; not yet, do next check ; restore return address

---------------------------------------------TEST SR EDITING FUNCTION SUBROUTINE Shift a test value right through SR 15 times. Test the value against an expected value for each time. After 15 shifts, the value should equal the sign (SG). DS SRtst %03431 %44346 14 ; code for this test ; positive init test value ; negative init test value ; loop SRindx+1 times

02120 02121 02122 02123

2120 2121 2122 2123

00002 0 SRcode

; SR test values 03431 1 SRinitP DS 44346 0 SRinitN DS 00016 0 SRindx DS

02124 02125 02126 02127 02130 02131 02132 02133 02134 02135 02136 02137 02140 02141 02142

2124 2125 2126 2127 2130 2131 2132 2133 2134 2135 2136 2137 2140 2141 2142

00000 00000 00000 00000 00000 00001 00003 00007 00016 00034 00070 00161 00343 00706 01614

1 1 1 1 1 0 1 0 0 0 0 1 0 0 0

; check SR against these values (positive) SRbaseP EQU * DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00000 ; check DS %00001 ; check DS %00003 ; check DS %00007 ; check DS %00016 ; check DS %00034 ; check DS %00070 ; check DS %00161 ; check DS %00343 ; check DS %00706 ; check DS %01614 ; check ; check SR against these values (negative) SRbaseN EQU * DS %77777 ; check DS %77777 ; check DS %77776 ; check DS %77774 ; check DS %77771 ; check DS %77762 ; check DS %77744 ; check DS %77710 ; check DS %77621 ; check DS %77443 ; check DS %77107 ; check DS %76216 ; check DS %74434 ; check DS %71071 ; check DS %62163 ; check chkSR EQU XCH TS CAF TS * Q savQ SRcode curtest

#0 (back to start) #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14

02143 02144 02145 02146 02147 02150 02151 02152 02153 02154 02155 02156 02157 02160 02161 02162 02163 02164 02165 02166 02167

2143 2144 2145 2146 2147 2150 2151 2152 2153 2154 2155 2156 2157 2160 2161 2162 3 2163 5 2164 3 2165 5 2166 3 2167 5

77777 77777 77776 77774 77771 77762 77744 77710 77621 77443 77107 76216 74434 71071 62163

0 0 1 0 0 1 0 1 1 1 1 0 1 1 1

#0 (back to start) #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14

0,0001 0 0,0101 1 1,2120 0 0,0100 0 1,2121 1 0,0104 1

; save return address ; set test code to this test ; init value to shift

; TEST 1: shift a postive value. XCH SRinitP TS SRval

02170

2170 3

1,2123 0 SRloopP

XCH EQU TS

SRindx * iSR SRval SR SR SRval

; load init index

02171 02172 02173 02174 02175 02176 02177 02200 02201 02202 02203 02204 02205 02206 02207 02210 02211

2171 5 2172 2173 2174 2175 2176 2177 2200 2201 2202 2203 2204 3 5 3 5 4 2 6 1 0 0 0

0,0105 0 0,0104 0,0021 0,0021 0,0104 0,0000 0,0105 1,2124 0,0000 1,2037 1,2037 1,2037 1 1 1 1 0 1 1 0 1 1 1

; save index

; shift A right (SR) XCH TS XCH TS ; verify C(A) COM INDEX AD CCS TC TC TC

; shift ; put result in A

; get -A iSR SRbaseP A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2205 1 2206 0 2207 3 2210 5 2211 3

0,0105 1 1,2171 1 1,2122 1 0,0104 1 1,2123 0

; loop back to test next value CCS iSR TC SRloopP ; TEST 2: shift a negative value XCH SRinitN TS SRval XCH SRloopN EQU TS SRindx * iSR SRval SR SR SRval

; done? ; not yet, do next check ; init value to shift ; load init index

02212 02213 02214 02215 02216 02217 02220 02221 02222 02223 02224 02225 02226 02227 02230 02231 02232

2212 5 2213 2214 2215 2216 2217 2220 2221 2222 2223 2224 2225 3 5 3 5 4 2 6 1 0 0 0

0,0105 0 0,0104 0,0021 0,0021 0,0104 0,0000 0,0105 1,2143 0,0000 1,2037 1,2037 1,2037 1 1 1 1 0 1 0 0 1 1 1

; save index

; shift A left (SR) XCH TS XCH TS ; verify C(A) COM INDEX AD CCS TC TC TC

; shift ; put result in A

; get -A iSR SRbaseN A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2226 1 2227 0 2230 3 2231 5 2232 0

0,0105 1 1,2212 1 0,0101 1 0,0001 0 0,0000 0

; loop back to test next value CCS iSR TC SRloopN XCH TS RETURN ; ; ; ; ; ; savQ Q

; done? ; not yet, do next check ; restore return address

---------------------------------------------TEST CYL EDITING FUNCTION SUBROUTINE Rotate a test value left through CYL 15 times. Test the value against an expected value for each time. After 15 rotations, the value should equal the initial value. DS CYLtst %03431 14 ; code for this test ; init test value ; loop CYLindx+1 times

02233 02234 02235

2233 2234 2235

00003 1 CYLcode

; CYL test values 03431 1 CYLinit DS 00016 0 CYLindx DS

02236 02237

2236 2237

; check CYL against these values CYLbase EQU * 03431 1 DS %03431 41614 1 DS %41614

; check #0 (back to start) ; check #1

02240 02241 02242 02243 02244 02245 02246 02247 02250 02251 02252 02253 02254 02255 02256 02257 02260 02261 02262 02263 02264 02265 02266 02267 02270 02271 02272 02273 02274 02275 02276 02277 02300 02301 02302 02303 02304

2240 2241 2242 2243 2244 2245 2246 2247 2250 2251 2252 2253 2254 2255 3 2256 5 2257 3 2260 5 2261 3 2262 5 2263 3 2264 5 2265 2266 2267 2270 2271 2272 2273 2274 2275 2276 2277 3 5 3 5 4 2 6 1 0 0 0

20706 10343 44161 62070 31034 14416 06207 43103 61441 70620 34310 16144 07062

1 1 1 1 1 1 1 1 1 1 1 1 1 chkCYL

DS DS DS DS DS DS DS DS DS DS DS DS DS EQU XCH TS CAF TS XCH TS XCH CYLloop EQU TS

%20706 %10343 %44161 %62070 %31034 %14416 %06207 %43103 %61441 %70620 %34310 %16144 %07062 * Q savQ CYLcode curtest CYLinit CYLval CYLindx * iCYL CYLval CYL CYL CYLval

; ; ; ; ; ; ; ; ; ; ; ; ;

check check check check check check check check check check check check check

#2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14

0,0001 0 0,0101 1 1,2233 1 0,0100 0 1,2234 0 0,0106 0 1,2235 1 0,0107 1 0,0106 0,0022 0,0022 0,0106 0,0000 0,0107 1,2236 0,0000 1,2037 1,2037 1,2037 0 1 1 0 0 0 1 0 1 1 1

; save return address ; set test code to this test ; init value to rotate ; load init index ; save index

; rotate A left (CYL) XCH TS XCH TS ; verify C(A) COM INDEX AD CCS TC TC TC

; rotate ; put result in A

; get -A iCYL CYLbase A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2300 1 2301 0 2302 3 2303 5 2304 0

0,0107 0 1,2264 0 0,0101 1 0,0001 0 0,0000 0

; loop back to test next value CCS iCYL TC CYLloop XCH TS RETURN ; ; ; ; ; savQ Q

; done? ; not yet, do next check ; restore return address

---------------------------------------------TEST SL EDITING FUNCTION SUBROUTINE Shift a test value left through SL 15 times. Test the value against an expected value for each time. After 15 shifts, the value should equal the sign (SG). DS SLtst %03431 %44346 14 ; code for this test ; positive init test value ; negative init test value ; loop SLindx+1 times

02305 02306 02307 02310

2305 2306 2307 2310

00004 0 SLcode

; SL test values 03431 1 SLinitP DS 44346 0 SLinitN DS 00016 0 SLindx DS

02311 02312 02313 02314 02315 02316 02317 02320 02321

2311 2312 2313 2314 2315 2316 2317 2320 2321

00000 00000 20000 10000 04000 22000 31000 14400 06200

1 1 0 0 0 1 0 0 0

; check SL against these values (positive) SLbaseP EQU * DS %00000 ; check DS %00000 ; check DS %20000 ; check DS %10000 ; check DS %04000 ; check DS %22000 ; check DS %31000 ; check DS %14400 ; check DS %06200 ; check

#0 (back to start) #1 #2 #3 #4 #5 #6 #7 #8

02322 02323 02324 02325 02326 02327

2322 2323 2324 2325 2326 2327

03100 21440 30620 34310 16144 07062

0 1 0 1 1 1

DS DS DS DS DS DS

%03100 %21440 %30620 %34310 %16144 %07062

; ; ; ; ; ;

check check check check check check

#9 #10 #11 #12 #13 #14

02330 02331 02332 02333 02334 02335 02336 02337 02340 02341 02342 02343 02344 02345 02346 02347 02350 02351 02352 02353 02354 02355

2330 2331 2332 2333 2334 2335 2336 2337 2340 2341 2342 2343 2344 2345 2346 2347 3 2350 5 2351 3 2352 5 2353 3 2354 5 2355 3

77777 77777 57777 67777 73777 55777 46777 63377 71577 74677 56337 47157 43467 61633 50715

0 0 1 1 1 0 1 1 1 1 0 1 0 0 1

; check SL against these values (negative) SLbaseN EQU * DS %77777 ; check DS %77777 ; check DS %57777 ; check DS %67777 ; check DS %73777 ; check DS %55777 ; check DS %46777 ; check DS %63377 ; check DS %71577 ; check DS %74677 ; check DS %56337 ; check DS %47157 ; check DS %43467 ; check DS %61633 ; check DS %50715 ; check chkSL EQU XCH TS CAF TS * Q savQ SLcode curtest

#0 (back to start) #1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14

0,0001 0 0,0101 1 1,2305 0 0,0100 0 1,2306 0 0,0110 1 1,2310 1 SLloopP

; save return address ; set test code to this test ; init value to shift ; load init index

; TEST 1: shift a postive value. XCH SLinitP TS SLval XCH EQU TS SLindx * iSL SLval SL SL SLval

02356 02357 02360 02361 02362 02363 02364 02365 02366 02367 02370 02371 02372 02373 02374 02375 02376 02377 02400 02401 02402 02403

2356 5 2357 2360 2361 2362 2363 2364 2365 2366 2367 2370 2371 3 5 3 5 4 2 6 1 0 0 0

0,0111 0 0,0110 0,0023 0,0023 0,0110 0,0000 0,0111 1,2311 0,0000 1,2037 1,2037 1,2037 1 0 0 1 0 1 0 0 1 1 1

; save index

; shift A left (SL) XCH TS XCH TS ; verify C(A) COM INDEX AD CCS TC TC TC

; shift ; put result in A

; get -A iSL SLbaseP A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2372 1 2373 0 2374 3 2375 5 2376 3 2377 5 2400 2401 2402 2403 3 5 3 5

0,0111 1 1,2356 0 1,2307 1 0,0110 1 1,2310 1

; loop back to test next value CCS iSL TC SLloopP ; TEST 2: shift a negative value XCH SLinitN TS SLval XCH SLloopN EQU TS SLindx * iSL SLval SL SL SLval

; done? ; not yet, do next check ; init value to shift ; load init index ; save index

0,0111 0 0,0110 0,0023 0,0023 0,0110 1 0 0 1

; shift A left (SL) XCH TS XCH TS

; shift ; put result in A

; verify C(A) 02404 02405 02406 02407 02410 02411 02412 02413 02414 02415 02416 02417 2404 2405 2406 2407 2410 2411 2412 4 2 6 1 0 0 0 0,0000 0,0111 1,2330 0,0000 1,2037 1,2037 1,2037 0 1 0 0 1 1 1 COM INDEX AD CCS TC TC TC ; get -A iSL SLbaseN A fail fail fail ; ; ; ; ; put (-A) + expected value in A compare >0 (A < expected value) +0 <0 (A > expected value)

2413 1 2414 0 2415 3 2416 5 2417 0

0,0111 1 1,2377 0 0,0101 1 0,0001 0 0,0000 0

; loop back to test next value CCS iSL TC SLloopN XCH TS RETURN savQ Q

; done? ; not yet, do next check ; restore return address

; ---------------------------------------------; PASSED ALL TESTS! 02420 02421 02422 02423 2420 2421 3 2422 5 2423 0 12345 0 PASScode finish 1,2420 0 0,0100 0 0,0000 0 DS EQU CAF TS RETURN PASS * PASScode curtest

; set current test code to PASS

; ---------------------------------------------; INTERRUPT SERVICE ROUTINE goT3 goER goDS goKEY goUP endRUPT 02424 02425 02426 02427 2424 2425 2426 2427 3 5 3 2 0,0027 0,0001 0,0026 0,0000 1 0 0 1 EQU EQU EQU EQU EQU EQU XCH TS XCH RESUME * * * * * * QRUPT Q ARUPT

; restore Q ; restore A ; finished, go back

Assembly complete. Errors = 0 Symbol table: START CYLtst EXTENDER CYRval iSR SLval T3RUPT KEYRUPT fail begin CYRindx CYRloop SRinitN SRbaseN SRloopN CYLindx CYLloop SLinitN SLbaseN SLloopN goT3 goKEY ARUPT CYR CYL 000000 000003 005777 000102 000105 000110 002004 002020 002037 002043 002050 002077 002122 002143 002212 002235 002264 002307 002330 002377 002424 002424 000026 000020 000022 CYRtst SLtst curtest iCYR CYLval iSL ERRUPT UPRUPT end CYRcode CYRbase SRcode SRindx chkSR CYLcode CYLbase SLcode SLindx chkSL PASScode goER goUP Q A SL 000001 000004 000100 000103 000106 000111 002010 002024 002041 002046 002051 002120 002123 002162 002233 002236 002305 002310 002347 002420 002424 002424 000001 000000 000023 SRtst PASS savQ SRval iCYL GOPROG DSRUPT goMAIN STRTcode CYRinit chkCYR SRinitP SRbaseP SRloopP CYLinit chkCYL SLinitP SLbaseP SLloopP finish goDS endRUPT QRUPT SR 000002 012345 000101 000104 000107 002000 002014 002030 002042 002047 002070 002121 002124 002171 002234 002255 002306 002311 002356 002421 002424 002424 000027 000021

TECO5 assembler listing


Block I Apollo Guidance Computer (AGC4) assembler version 1.6 for EPROM First pass: generate symbol table. Second pass: generate object code. ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; TECO5 (file:teco5.asm) Version: 1.0 Author: John Pultorak Date: 9/14/2001 PURPOSE: Test and checkout program for the Block 1 Apollo Guidance Computer. Tests interrupts. OPERATION: Tests the interrupts by initializing 4 counters to zero and then entering a loop where the 1st counter (mainCtr) is incremented on each iteration of the loop. Interrupts are disabled and enabled during each iteration by INHINT and RELINT instructions. Interrupts are automatically inhibited during part of each iteration by an overflow condition in register A. Interrupt service routines for T3RUPT, DSRUPT (aka T4RUPT) and KEYRUPT increment their own counters upon each interrupt. ERRATA: - Written for the AGC4R assembler. The assembler directives and syntax differ somewhat from the original AGC assembler. - The tests attempt to check all threads, but are not exhaustive. SOURCES: Information on the Block 1 architecture: instruction set, instruction sequences, registers, register transfers, control pulses, memory and memory addressing, I/O assignments, interrupts, and involuntary counters was obtained from: A. Hopkins, R. Alonso, and H. Blair-Smith, "Logical Description for the Apollo Guidance Computer (AGC4)", R-393, MIT Instrumentation Laboratory, Cambridge, MA, Mar. 1963. Supplementary information was obtained from: R. Alonso, J. H. Laning, Jr. and H. Blair-Smith, "Preliminary MOD 3C Programmer's Manual", E-1077, MIT Instrumentation Laboratory, Cambridge, MA, Nov. 1961. B. I. Savage and A. Drake, "AGC4 Basic Training Manual, Volume I", E-2052, MIT Instrumentation Laboratory, Cambridge, MA, Jan. 1967. E. C. Hall, "MIT's Role in Project Apollo, Volume III, Computer Subsystem", R-700, MIT Charles Stark Draper Laboratory, Cambridge, MA, Aug. 1972. A. Hopkins, "Guidance Computer Design, Part VI", source unknown. A. I. Green and J. J. Rocchio, "Keyboard and Display System Program for AGC (Program Sunrise)", E-1574, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1964. E, C. Hall, "Journey to the Moon: The History of the Apollo Guidance Computer", AIAA, Reston VA, 1996.

; ---------------------------------------------; ---------------------------------------------; ERASEABLE MEMORY -- DATA SEGMENT

00047 00050 00051 00052

0047 0050 0051 0052

00000 1 mainCtr 00000 1 T3Ctr 00000 1 DSCtr 00000 1 KYCtr

ORG DS DS DS DS

%47 %0 %0 %0 %0

; start of data area ; counts T3RUPTs ; counts DSRUPTs (T4RUPT) ; counts KEYRUPT

; ---------------------------------------------; ENTRY POINTS ; program (re)start ORG 1,2030 0 TC GOPROG goMAIN

02000

2000 0

02004 02005 02006 02007 02014 02015 02016 02017 02020 02021 02022 02023

2004 2005 2006 2007 2014 2015 2016 2017 2020 2021 2022 2023

5 3 5 0 5 3 5 0 5 3 5 0

0,0026 0,0001 0,0027 1,2064 0,0026 0,0001 0,0027 1,2071 0,0026 0,0001 0,0027 1,2076

0 0 1 1 0 0 1 0 0 0 1 1

; interrupt service entry points ORG T3RUPT TS ARUPT XCH Q TS QRUPT TC goT3 ORG TS XCH TS TC ORG TS XCH TS TC DSRUPT ARUPT Q QRUPT goDS KEYRUPT ARUPT Q QRUPT goKEY ; aka T4RUPT

; ---------------------------------------------; FIXED MEMORY -- SHARED DATA SEGMENT 02024 02025 02026 02027 2024 2025 2026 2027 00000 00001 25252 52525 1 0 0 1 ZERO ONE AD25252 AD52525 DS DS DS DS %0 %1 %25252 %52525

;+10922 dec, see TECO1 AD test ;-10922 dec, see TECO1 AD test

; ---------------------------------------------; MAIN PROGRAM goMAIN 02030 2030 2 0,0000 0 EQU INHINT * ; disable interrupts

; clear counters for interrupts and for interations ; though main loop. 02031 02032 02033 02034 02035 2031 2032 2033 2034 2035 3 5 5 5 5 1,2024 0,0047 0,0050 0,0051 0,0052 0 1 1 0 0 CAF TS TS TS TS ZERO mainCtr T3Ctr DSCtr KYCtr ; ; ; ; mainCtr T3Ctr = DSCtr = KYCtr = = 0 0 0 0

; keeps bumping mainCtr in an infinite loop. ; interrupts are disabled and enabled on each ; iteration of the loop. infLoop 02036 2036 2 0,0000 0 EQU INHINT * ; disable interrupt

; increment mainCtr while interrupt is inhibited. 02037 02040 02041 02042 02043 2037 3 2040 6 2041 6 2042 2 2043 5 1,2024 0 0,0047 1 1,2025 1 0,0000 1 0,0047 1 CAF AD AD RELINT TS mainCtr ZERO mainCtr ONE ; load mainCtr into A ; incr ; enable interrupts ; store increment value

; ; ; ; 02044 02045 02046 02047 2044 3 2045 6 2046 3 2047 3 1,2026 1 1,2026 1 0,0000 1 0,0000 1

create a positive overflow in A. Interrupts are inhibited while A contains an overflow. The overflow is produced by adding %25252 + %25252 = %52524 (sign + 14 magnitude). This is the overflow test in TECO1 for the AD instruction. CAF AD NOOP NOOP AD25252 AD25252 ; positive overflow ; interrupt should be inhib

; remove the overflow, this reenables the interrupt. 02050 02051 02052 2050 3 2051 3 2052 3 1,2024 0 0,0000 1 0,0000 1 ; ; ; ; 02053 02054 02055 02056 2053 3 2054 6 2055 3 2056 3 1,2027 0 1,2027 0 0,0000 1 0,0000 1 CAF NOOP NOOP ZERO ; clear the overflow in A ; interrupt should be reenab

create a negative overflow in A. Interrupts are inhibited while A contains an overflow. The overflow is produced by adding %52525 + %52525 = %25253 (sign + 14 magnitude). This is the overflow test in TECO1 for the AD instruction. CAF AD NOOP NOOP AD52525 AD52525 ; positive overflow ; interrupt should be inhib

; remove the overflow, this reenables the interrupt. 02057 02060 02061 02062 02063 2057 3 2060 3 2061 3 2062 0 2063 0 1,2024 0 0,0000 1 0,0000 1 1,2036 0 1,2036 0 CAF NOOP NOOP TC TC infLoop infLoop ZERO ; clear the overflow in A ; interrupt should be reenab

; mainCtr no overflow ; mainCtr overflowed

; ---------------------------------------------; INTERRUPT SERVICE ROUTINE goT3 02064 02065 02066 02067 02070 02071 02072 02073 02074 02075 02076 02077 02100 02101 02102 02103 02104 02105 02106 2064 2065 2066 2067 2070 2071 2072 2073 2074 2075 2076 2077 2100 2101 2102 2103 2104 2105 2106 3 6 6 5 0 3 6 6 5 0 3 6 6 5 0 3 5 3 2 1,2024 0,0050 1,2025 0,0050 1,2103 1,2024 0,0051 1,2025 0,0051 1,2103 1,2024 0,0052 1,2025 0,0052 1,2103 0,0027 0,0001 0,0026 0,0000 0 1 1 1 1 goDS 0 0 1 0 1 goKEY 0 0 1 0 1 endRUPT 1 0 0 1 EQU CAF AD AD TS TC EQU CAF AD AD TS TC EQU CAF AD AD TS TC EQU XCH TS XCH RESUME * ZERO T3Ctr ONE T3Ctr endRUPT * ZERO DSCtr ONE DSCtr endRUPT * ZERO KYCtr ONE KYCtr endRUPT * QRUPT Q ARUPT

; load T3Ctr into A ; incr ; store

; load DSCtr into A ; incr ; store

; load KYCtr into A ; incr ; store

; restore Q ; restore A ; finished, go back

Assembly complete. Errors = 0 Symbol table:

mainCtr KYCtr DSRUPT ONE goMAIN goDS ARUPT

000047 000052 002014 002025 002030 002071 000026

T3Ctr GOPROG KEYRUPT AD25252 infLoop goKEY Q

000050 002000 002020 002026 002036 002076 000001

DSCtr T3RUPT ZERO AD52525 goT3 endRUPT QRUPT

000051 002004 002024 002027 002064 002103 000027

TECO_STBY assembler listing


Block I Apollo Guidance Computer (AGC4) assembler version 1.6 First pass: generate symbol table. Second pass: generate object code. ; TECO_STBY (file:stby.asm) ; ; Tests the standby operation. ; program (re)start ORG 1,2002 1 TC 00200 0 ofbit ; MAIN PROGRAM goMAIN 02002 02003 02004 02005 02006 2002 3 2003 3 2004 3 2005 5 2006 0 0,0000 1 0,0000 1 1,2001 1 0,0011 1 1,2006 0 EQU * DS GOPROG goMAIN %200 ; OUT1, bit 8 initiates standby

02000 02001

2000 0 2001

; standby is disabled NOOP NOOP ; enable standby XCH TS infLoop EQU TC ofbit OUT1 * infLoop

Assembly complete. Errors = 0 Symbol table: GOPROG infLoop 002000 002006 ofbit OUT1 002001 000011 goMAIN 002002

You might also like