Source Code
![]() |
YAYUL: ASSEMBLE REVISION 5 OF PROGRAM BOREALIS BY MSTEWART MAR. 27,2017This is a modern AGC system self-test program, though based on the Apollo-era AURORA 12 program, and was not written by the original AGC developers, but rather by Mike Stewart. All of the original AURORA 12 DAP code added by the DAP Group has been removed, and extensive new system test code has been added in its place. This allows more in-depth testing of CPU behavior, both in AGC software simulations and hardware simulations. |
017450,000002: ## Copyright: Public domain.
017451,000003: ## Filename: AGC_BLOCK_TWO_EXTENDED_TESTS.agc
017452,000004: ## Purpose: This program is designed to extensively test the Apollo Guidance Computer
017453,000005: ## (specifically the LM instantiation of it). It is built on top of a heavily
017454,000006: ## stripped-down Aurora 12, with all code ostensibly added by the DAP Group
017455,000007: ## removed. Instead Borealis expands upon the tests provided by Aurora,
017456,000008: ## including corrected tests from Retread 44 and tests from Ron Burkey's
017457,000009: ## Validation.
017458,000010: ## Assembler: yaYUL
017459,000011: ## Contact: Mike Stewart <mastewar1@gmail.com>.
017460,000012: ## Website: www.ibiblio.org/apollo/index.html
017461,000013: ## Mod history: 2017-01-15 MAS Created to hold new extended tests, starting off with
017462,000014: ## checking out all the timers, EDRUPT, BRUPT substitution,
017463,000015: ## and interrupts following an INDEX.
017464,000016:
017465,000017: 24,2000 BANK 24
017466,000018: # The extended tests check out functionalities not exercised by the Aurora or Retread tests. First up
017467,000019: # is testing of the interrupt priority chain (insofar as it can be deterministically and automatically
017468,000020: # checked) by queuing up all four timer interrupts, and then executing them one at a time using EDRUPT.
017469,000021:
017470,000022: # What we're about to do is sensitive to the phasing of TIME3. Instead of risking it, we simply wait
017471,000023: # for the next TIME3 increment so we can be sure we're safe.
017472,000024: 24,2000 30026 EXTTESTS CA TIME3
017473,000025: 24,2001 55371 TS SKEEP1
017474,000026: 24,2002 40026 WAITT3 CS TIME3 # Wait for the next TIME3 increment.
017475,000027: 24,2003 61371 AD SKEEP1
017476,000028: 24,2004 12005 NOOP # This assembles to TCF +1, and is needed
017477,000029: 24,2005 00006 EXTEND # to keep TC Traps at bay
017478,000030: 24,2006 12002 BZF WAITT3
017479,000031:
017480,000032: # With phasing correct, inhibit interrupts and trigger all the timers.
017481,000033: 24,2007 00004 INHINT
017482,000034:
017483,000035: 24,2010 37673 SCHEDT6 CAF LOW4 # Start with TIME6. It counts the fastest,
017484,000036: 24,2011 54031 TS TIME6 # and will provide a bounds after which we'll
017485,000037: 24,2012 37641 CAF BIT15 # know all the others have fired.
017486,000038: 24,2013 00006 EXTEND
017487,000039: 24,2014 05013 WOR CHAN13 # Start the timer for a bit over 10ms. This
017488,000040: # bit resetting will tell us we're done.
017489,000041:
017490,000042: 24,2015 37637 SCHEDT5 CAF POSMAX # Schedule T5RUPT to happen in <=10ms.
017491,000043: 24,2016 54030 TS TIME5
017492,000044:
017493,000045: 24,2017 37657 SCHEDT3 CAF ONE # Schedule a T3RUPT by waitlisting a task
017494,000046: 24,2020 04517 TC WAITLIST # that does nothing to execute ASAP.
017495,000047: 24,2021 02072 50003 2CADR NOTHING
017496,000048:
017497,000049: # TIME4 needs a bit of special handling. It expects to execute periodically and naively forcing it to
017498,000050: # happen sooner could throw off display handling or other things. Instead, we'll only accelerate it
017499,000051: # if necessary, and if so make sure it doesn't do any actual work in the accelerated interrupt.
017500,000052: 24,2023 30027 SCHEDT4 CA TIME4 # Check to see if we need to force TIME4.
017501,000053: 24,2024 10000 CCS A
017502,000054: 24,2025 12027 TCF +2 # TIME4 positive, we may need to accelerate.
017503,000055: 24,2026 12036 TCF T6CHK # TIME4 is zero, so T4RUPT is already pending
017504,000056: 24,2027 67656 AD TWO # Calculate the new TIME4 value (+10ms from old)
017505,000057: 24,2030 54000 OVSK # ... and if that overflows, TIME4 is already going
017506,000058: 24,2031 12033 TCF +2 # to happen as quickly as is possible, so we can
017507,000059: 24,2032 12036 TCF T6CHK # just leave it alone.
017508,000060: 24,2033 55113 TS T4TEMP # Save the adjusted original TIME4 value so T4RUPT
017509,000061: 24,2034 37637 CA POSMAX # can reschedule, and then set T4RUPT to occur in
017510,000062: 24,2035 54027 TS TIME4 # <= 10ms.
017511,000063:
017512,000064: # All of the balls are now rolling, so we can now wait for TIME6 to expire. While doing so, we can
017513,000065: # verify that TIME6 and the DINC sequence behave as expected.
017514,000066: 24,2036 10031 T6CHK CCS TIME6 # Wait for TIME6 to hit -0
017515,000067: 24,2037 12036 TCF T6CHK
017516,000068: 24,2040 05546 TC ERRORS # (NOT +0, is skipped over)
017517,000069: 24,2041 05546 TC ERRORS
017518,000070: 24,2042 47641 CS BIT15 # TIME6 has reached -0. It is, hover, still active,
017519,000071: 24,2043 00006 EXTEND # because DINC doesn't trigger ZOUT (needed for
017520,000072: 24,2044 04013 ROR CHAN13 # T6RUPT) until it occurs when its counter is already
017521,000073: 24,2045 05563 TC -0CHK # +-0. Thus, T6 should still be enabled.
017522,000074:
017523,000075: # We can now waste a bit of time until the final TIME6 count occurs, and in doing so verify that
017524,000076: # it's counting at roughly the expected rate (1/1600 seconds). That translates to ~53.333 MCT. The
017525,000077: # following loops is timed such that from the "CS BIT15" above to to the "EXTEND" below there
017526,000078: # are exactly 54 MCTs (ignoring any counter increments).
017527,000079: 24,2046 37662 CAF NINE
017528,000080: 24,2047 12050 T6BUSYWT NOOP
017529,000081: 24,2050 10000 CCS A
017530,000082: 24,2051 12047 TCF T6BUSYWT
017531,000083:
017532,000084: 24,2052 37641 CAF BIT15 # T6 should nnow have switched itself off.
017533,000085: 24,2053 00006 EXTEND
017534,000086: 24,2054 02013 RAND CHAN13
017535,000087: 24,2055 05562 TC +0CHK
017536,000088:
017537,000089: # At this point, we can safely expect all four timer interrupts to be pending. We can now
017538,000090: # test each one works, and that each has the correct priority, by executing four EDRUPTs
017539,000091: # and checking to see that the expected timer interrupt was serviced. The expected priority
017540,000092: # order is 6, 5, 3, 4.
017541,000093: 24,2056 36162 PRIOCHK CAF SIX
017542,000094: 24,2057 07731 TC TRIGRUPT
017543,000095: 24,2060 37664 CAF FIVE
017544,000096: 24,2061 07731 TC TRIGRUPT
017545,000097: 24,2062 36165 CAF THREE
017546,000098: 24,2063 07731 TC TRIGRUPT
017547,000099: 24,2064 37655 CAF FOUR
017548,000100: 24,2065 07731 TC TRIGRUPT
017549,000101:
017550,000102: # Timers and their interrupts are healthy. It's finally safe to release interrupts. The
017551,000103: # next test must take place entirely in the 7xxx address range.
017552,000104: 24,2066 00003 RELINT
017553,000105: 24,2067 07701 TC BRUPTCHK
017554,000106:
017555,000107: # Extended tests are complete. Head back to self-check proper.
017556,000108: 24,2070 04104 TC POSTJUMP
017557,000109: 24,2071 40727 CADR EXTTDONE
017558,000110:
017559,000111: # Do-nothing waitlist task, used as a dummy when generating a fast T3RUPT.
017560,000112: 24,2072 04563 NOTHING TC TASKOVER
017561,000113:
017562,000114: 24,2073 ENDEXTST EQUALS
017563,000115:
017564,000116: 7701 SETLOC ENDINTF
017565,000117: # Check EDRUPT's ability to vector to A with no pending interrupts, the correct
017566,000118: # behavior of BRUPT for interrupts following an INDEX, and BRUPT substitution.
017567,000119: 7701 37664 BRUPTCHK CAF FIVE # SKEEP1 = 5. This will be used for indexing.
017568,000120: 7702 55371 TS SKEEP1
017569,000121: 7703 00006 EXTEND # Save our return address.
017570,000122: 7704 23372 QXCH SKEEP2
017571,000123: 7705 37727 CAF ARVECADR # Attempt to use EDRUPT to vector to ARUPTVEC.
017572,000124: 7706 00006 +5 EXTEND # If some other interrupt is taken, continue
017573,000125: 7707 51371 INDEX SKEEP1 # at BRUPTCHK+5 (as calculated by the INDEX).
017574,000126: 7710 07701 EDRPTWRD EDRUPT BRUPTCHK # This instruction should be replaced with
017575,000127: 7711 66045 EDRPT+1 AD NEG4 # "CAF FIVE" upon resume. Make sure it did.
017576,000128: 7712 05570 TC +1CHK
017577,000129: 7713 01372 TC SKEEP2 # EDRUPT-to-A and BRUPT look good. Carry on.
017578,000130:
017579,000131: # Interrupt routine used in BRUPTCHK.
017580,000132: 7714 52011 ARUPTVEC DXCH ARUPT # Although Q is also destroyed, we happen to know
017581,000133: # that the "interrupted" program doesn't need it.
017582,000134:
017583,000135: 7715 40017 CS BRUPT # Check that BRUPT was correctly calculated as
017584,000136: 7716 67710 AD EDRPTWRD # "EDRUPT BRUPTCHK +5".
017585,000137: 7717 67664 AD FIVE
017586,000138: 7720 05563 TC -0CHK
017587,000139:
017588,000140: 7721 40015 CS ZRUPT # ZRUPT should be pointing at the address
017589,000141: 7722 67730 AD EDRP+1AD # immediately following the EDRUPT.
017590,000142: 7723 05563 TC -0CHK
017591,000143:
017592,000144: 7724 37701 CAF BRUPTCHK # Break out of the EDRUPT loop by replacing
017593,000145: 7725 54017 TS BRUPT # BRUPT with "CAF FIVE".
017594,000146: 7726 04573 TC NOQBRSM
017595,000147:
017596,000148: 7727 07714 ARVECADR ADRES ARUPTVEC
017597,000149: 7730 07711 EDRP+1AD ADRES EDRPT+1
017598,000150:
017599,000151: # Routine to trigger a pending timer interrupt and verify that the timer whose number is
017600,000152: # specified in A was the one that got serviced.
017601,000153: 7731 56001 TRIGRUPT XCH L
017602,000154: 7732 00006 EXTEND
017603,000155: 7733 23371 QXCH SKEEP1
017604,000156: 7734 37665 CAF ZERO # Zero LASTIMER so we don't get duped.
017605,000157: 7735 55112 TS LASTIMER
017606,000158: 7736 37747 CA NOPNDADR # EDRUPT will fall back on this vector if
017607,000159: 7737 00006 EXTEND # no interrupts at all are pending.
017608,000160: 7740 07742 EDRUPT TRPTCHK # Trigger an interrupt, then skip over TC ERRORS.
017609,000161: 7741 05546 TC ERRORS
017610,000162: 7742 41112 TRPTCHK CS LASTIMER # Check the timer that just got executed matches
017611,000163: 7743 60001 AD L # what was expected.
017612,000164: 7744 05563 TC -0CHK
017613,000165: 7745 01371 TC SKEEP1
017614,000166:
017615,000167: 7746 05546 NOPNDING TC ERRORS
017616,000168: 7747 07746 NOPNDADR ADRES NOPNDING
017617,000169:
017618,000170: # T5 and T6 interrupt routines. Both currently only set LASTIMER for use with the extended self-tests.
017619,000171: 7750 54016 T5RUPT TS BANKRUPT
017620,000172: 7751 37664 CAF FIVE
017621,000173: 7752 55112 TS LASTIMER
017622,000174: 7753 14571 TCF NOQRSM
017623,000175:
017624,000176: 7754 54016 T6RUPT TS BANKRUPT
017625,000177: 7755 36162 CAF SIX
017626,000178: 7756 55112 TS LASTIMER
017627,000179: 7757 14571 TCF NOQRSM
017628,000180:
017629,000181: 7760 ENDSLFS4 EQUALS
End of include-file AGC_BLOCK_TWO_EXTENDED_TESTS.agc. Parent file is MAIN.agc