The design of the AGC went through several stages, which for the
sake of this discussion we'll call "blocks". However, the
different block designs, while similar in many ways, were quite
different in others. Rather than try to cover all of them on
this one page, the different blocks are covered in separate pages:
However, this page confines itself just to the Block 2
design.
An example of some kinds of things supported by Yul or GAP
but not supported by yaYUL are provisions for formatting
the output assembly listing. (By the way, notice that I said
Yul rather than YUL in the preceding
sentence. That's because "Yul" is an abbreviation—of
"Yuletide—and not an acronym like "GAP", and so it really isn't
appropriate to put it in all-caps, and I don't think the original
developers did so. But I've only thought of this belatedly,
and am too lazy to go back and change it everywhere. So
that's the one and only time I won't call the original assembler
"YUL".)
I personally didn't think that formatting commands were
appropriate in the modern age, when computer-program listings are
views on a computer screen, rather than as printed out on
fixed-length paper pages. Plus, I didn't have any
information about them when I wrote yaYUL anyway, and they
seemed pretty mysterious.
But not everyone agrees with me about the significance of such
formatting, and there's room for more than one opinion, even
though I end up winning since I wrote yaYUL. ☺
Here's what YUL's author actually has to say, from a
personal communication, regarding the formatting conventions of
the source code and the formatting commands available in YUL,
and the question of whether multiple consecutive blank lines are
of any importance in AGC source code. This may be
interesting to you if you try to read our online page images of
AGC assembly listings. (Note that the reference below to
"##Page" refers to the AGC source code we've created from those
page images, and not to the original assembly listings.)
"One question is whether a manual page break falls into your definition of 'blank lines' in which case there could be any number of consecutive 'blank lines' up to fifty-something for a very short page. I believe the only way such page breaks were put in the code was to begin a remarks card with P instead of R in column 1, thereby forcing it to be the first line on a new page. That certainly implied a fairly major change of topic. On the other hand, it appears this info isn't entirely lost because somebody has put in what looks like a full set of page number indicators in the form ## Page 1234. They look as if they appear at the original automatic page breaks in most cases (as they should do because the symbol table and other indexy things are keyed to page numbers), but for manual page breaks they seem to appear after the page-top remarks cards and just ahead of the first non-remark code on that page. A (small) pity, that, since it would have expressed the purpose of the manual page breaks better if it had preceded the page-top remarks. But not a big thing.
"Within the code on a page, the blank lines were put in under control of an unprinted digit in card column 8, between the card number field and the location field. A 2 there forced a double-space (1 blank line) after its card, a 3 there forced a triple-space (2 blank lines), and I'm pretty sure the values 4 through 8 were never used, though they were defined and supported. Double-spacing separated groups of assembler control commands from actual code-generating lines, or within code generally meant that the line above it (often a branch instruction) was not always followed at run time by the line below it, and triple-spacing was generally a small change of topic, not big enough to induce a manual page break. So yes, triple-spacing did mark differences in sections of code, but I don't see that much was lost by reducing them to double spacing. If your friends would like to restore the triple-spacings, they could (aside from peeking at sites with scanned hard-copy pages) limit their attention to blank lines that are preceded by a non-remark and followed by a remark line. Within that set, an educated guess as to where topic breaks occur will get pretty close.
"Having said all that, if you think there were any non-page-break cases with more than two consecutive blank lines, I like to hear about them.
"And yes, I am indeed the right fellow to ask. These minutiae were part of my determination to make the code easy to read. I can't think of any reasons for blank lines beyond those stated above, and I'd be pretty surprised if anybody else could.
"The reason for providing double-spacing and triple-spacing logic was to make it unnecessary to have physical blank cards in the decks, which were frequently pulled out, carried to and from keypunches, and put back. A Steelcase file drawer of 3000 punched cards was a heavy mutha.
"You can see evidence of the above in the fact that in the normal flow of card numbers, the one after such a spacing is generally 1 more than that of the card before—no missing numbers due to spacing. But having said that, I have to explain why the card number following a remark over 72 columns wide is generally 2 more than the one you can see on the remark line. That's because the only way to make such a remark was to have a second card, with a 9 in column 8, whose columns 9-48 were printed in print positions 81-120 of the previous line. That feature was called 'right print'."
— Hugh Blair-Smith
Address
(octal) |
Name |
Description |
00 |
A |
The "accumulator".
Almost every AGC instruction uses or modifies the
accumulator in some way. The accumulator differs from
all other memory or i/o locations addressed by the CPU, in
that it is a 16-bit
register rather than a 15-bit register. In
most cases this is transparent to the programmer, because
the 16th bit is not directly observable or modifiable, and
because data within the accumulator is automatically
adjusted to 15 bits before most uses of it. The 16th
bit is present in order to allow detection of arithmetical
overflow or underflow. Internally, when there is no overflow, the 16th bit of the accumulator is a duplicate of the 15th (sign) bit. When a value is loaded into the accumulator from memory, the value is sign-extended from the 15th bit to the 16th bit. In other words, for positive values the 15th and 16th bits are both 0, while for negative values they are both 1. When overflow occurs, however, the 15th and 16th bits differ: After an operation that causes positive overflow, the 16th bit is 0 and the 15th bit is 1. After an operation that causes negative overflow, the 16th bit is 1 and the 15th bit is 0. Various CPU instructions can detect overflow and alter their actions somewhat upon finding it. The TS (transfer to storage) instruction is notable in this regard, because it can actually be used to provide a branch upon detection of overflow. In most cases, when data is transferred out of the accumulator to a true 15-bit register, it is overflow-corrected. Overflow-correction implies:
|
01 |
L |
This is the "lower product register". This is a general-purpose register, but many instructions pair it with the accumulator in cases where double precision (DP) operations are performed. In these cases, the A register holds the more-significant word, and the L register holds the less-significant word. Note that erasable-memory location 01 is automatically duplicated as i/o channel 01, and vice-versa. |
02 |
Q |
Like the accumulator, this is
a 16-bit register
rather than a 15-bit register. This means, for
example, that like the accumulator you can generate overflow
conditions with instructions like ADS Q; also, the overflow can be
transferred between the accumulator and Q with instructions
like XCH Q or
QXCH A. This register is intended to store return addresses of called procedures. Note that the AGC CPU has no hardware stack, and provides only a single memory location (the Q register) for storing return addresses. Therefore, it is not possible to have nested procedure calls unless the contents of the Q register are stored prior to calling a procedure and then restored after the procedure returns. The CPU's instruction TC is used to call a procedure, and the instruction automatically updates the Q register; similarly, the RETURN instruction returns from a called procedure by placing the contents of the Q register into the program-counter register (technically it does an indirect jump through Q, but the net effect is the same). Note that erasable-memory location 02 is automatically duplicated as i/o channel 02, and vice-versa. |
03 |
EB |
The "erasable bank
register". This register contains a 3-bit field that
determines which of the 8 banks of erasable memory (see
"Memory Map" below) is mapped into the address range
1400-1777 (octal). The 15 bits of the EB register are
arranged as follows: 000 0EE E00 000 000
where EEE are the bank-selector bits.Note that the EEE field of the EB register is duplicated into the BB register (see below). Internally, the two point to the same set of flip-flops, and simply provide different means of accessing them. |
04 |
FB |
The "fixed bank
register". This register contains a 5-bit field that
determines which of the 36 banks of fixed memory (see
"Memory Map" below) is mapped into the address range
2000-3777 (octal). 5 bits are not, of course, adequate
for selecting among 36 banks, so these 5 bits are
supplemented by a 7th bit (the "super bank" bit) from i/o
channel 7. In most cases, the superbank bit is 0, and
so the 5-bit field in the FB register simply selects from
among banks 0-37 (octal). When the superbank bit is 1,
on the other hand, the 5 bits of the FB register actually
select from among banks 0, 1, ..., 27, 40, 41, ..., 47;
i.e., bank-selection is the same as when the superbank bit
is 0, except that banks 40-47 are used instead of
30-37. Banks 44-47, however, do not exist. Though the
AGC can internally calculate addresses in this range, the
rope selection circuitry gives up and decides to select no
rope at all when given such an address. The appropriate strands are still cycled,
and a read is still attempted, but we can only guess as to
what sort of data would be returned with no ropes
selected. Presumably they would read all 0 or all 1, and
trip the parity fail alarm, causing a reset. The 15 bits of the FB register are arranged as follows: FFF FF0 000 000 000
where FFFFF are the bank-selector bits.Note that the FFFFF field of the FB register is duplicated into the BB register (see below). Internally, the two point to the same set of flip-flops, and simply provide different means of accessing them. Refer also to i/o channel 07. |
05 |
Z |
The program-counter
register. This 12-bit register always indicates the
next instruction to be executed. It is always updated
prior to executing
the instruction, so that an instruction which saved the
value of the Z register would actually be the address of the
next instruction in memory. Obviously, a 12-bit register cannot address all of memory. Full addresses are formed by combining the 12-bits of the Z register with the 3 bits of the EB register, the 5 bits of the FB register, and the superbank bit of i/o channel 7. (Refer to "Memory Map" below, and to the descriptions of the EB and FB registers above.) 12 bits can represent values from 0-7777 (octal), and these are interpreted as follows:
|
06 |
BB |
The "both banks
register". This register contains a 3-bit field
duplicating the EEE field of the EB register, and a 5-bit
field duplicating the FFFFF field of the FB register.
Internally, it points to the same flip-flops as the EB and
FB registers, so changing it directly changes the other
two. The bits are arranged within the register as
follows: FFF FF0 000 000 EEE
Refer also to i/o
channel 07. |
07 |
(no name) |
This location is not
associated with core memory, but is hardwired to 0. In
other words, it always contains the value 00000. It is
very useful as a source of zeroes, because most AGC
instructions have no "immediate" addressing
mode. (In other words, you can't use a specific
numerical value as an operand, but can only use the address
of a memory location as an operand.) |
10 |
ARUPT |
This register is provided as
a convenient location for storing the value of the A
register during an interrupt service routine. However,
vectoring to the interrupt does not automatically load this
register, nor does returning from the interrupt-service
routine restore the A register from ARUPT. These
actions must be done under program control by the interrupt
service routine. Interrupts are automatically disabled
while overflow is present in the accumulator, so the fact
that overflow would be lost by writing A to ARUPT is not a
concern. |
11 |
LRUPT |
This register is provided as a convenient location for storing the value of the L register during an interrupt service routine. However, vectoring to the interrupt does not automatically load this register, nor does returning from the interrupt-service routine restore the L register from LRUPT. These actions must be done under program control by the interrupt service routine. |
12 |
QRUPT |
This register is provided as a convenient location for storing the value of the Q register during an interrupt service routine. However, vectoring to the interrupt does not automatically load this register, nor does returning from the interrupt-service routine restore the Q register from QRUPT. These actions must be done under program control by the interrupt service routine. |
13-14 |
SAMPTIME |
These registers store copies
of TIME1 and TIME2, respectively, as sampled in the waitlist
interrupt service routine. They are used for Noun 65
displays. |
15 |
ZRUPT |
This register stores the
return address, plus one, of an interrupt service
routine. When the CPU vectors to an interrupt service
routine, it automatically transfers the value of the Z
register (the program counter) into the ZRUPT
register. When the interrupt-service routine returns,
using the RESUME instruction, the value of ZRUPT is
automatically transferred back into the Z register. |
16 |
BBRUPT |
This register is provided as a convenient location for storing the value of the BB register during an interrupt service routine. However, vectoring to the interrupt does not automatically load this register, nor does returning from the interrupt-service routine restore the BB register from BBRUPT. These actions must be done under program control by the interrupt service routine. |
17 |
BRUPT |
(Note: As of 20050820, I no
longer perform the instruction substitution described
below. The internal mechanics of yaAGC are
sufficiently different from the true AGC CPU that it should
not been needed. I may restore it later.) This register stores the value stored at the return address of an interrupt service routine. In other words, it is the instruction (not the address of the instruction) which will be executed when the interrupt-service routine returns. When the CPU vectors to an interrupt service routine, it automatically loads this register. When the interrupt-service routine returns, using the RESUME instruction, the value found in the BRUPT register will be used as the next instruction. It may seem from this description that an interrupt service routine can return to a position in memory from which the interrupt vector occurred, but can arrange to execute an entirely different instruction than what is found at that address. I believe that this statement is true, and obviously such a feature would need to be used with great care. (However, I don't believe that the BRUPT register was really provided for this purpose; I believe that the BRUPT register exists for the purpose of holding instruction which have been altered by a preceding INDEX instruction, as described below under the discussion of the instruction set. The true AGC allowed interrupts to occur between an INDEX instruction and the instruction affected by the INDEX instruction, and so this provision was necessary. However, yaAGC does not allow such interrupts, and conflicts between INDEX and the interrupt system do not arise in yaAGC.) |
20 |
CYR |
The "cycle right register",
which is one of the four so-called "editing"
registers. When a value is written to this register,
the value is automatically cycled right (with the least
significant bit, bit 1, wrapping into bit 15).
For example, if the software attempted to write the
following bits to the CYR register, abc def ghi jkl mno
then the value actually stored in the CYR register would be oab cde fgh ijk lmn
|
21 |
SR |
The "shift right register",
which is one of the four so-called "editing"
registers. When a value is written to this register,
the value is automatically shifted right (with the most
significant bit, bit 15, being duplicated into bit 14,and
the least significant bit, bit 1, being
discarded). For example, if the software
attempted to write the following bits into the SR register, abc def ghi jkl mno
then the value actually stored in the SR register would be: aab cde fgh ijk lmn
This operation corresponds arithmetically to division of a
single-precision (SP) value by 2, as it automatically
sign-extends the result. |
22 |
CYL |
The "cycle left register",
which is one of the four so-called "editing"
registers. When a value is read back from this
register, the value is automatically cycled left (with the
most significant bit, bit 15, wrapping into bit
1). For example, if before readback the CYL
register contained the bits abc def ghi jkl mno
then the value actually stored in the CYL register would be: bcd efg hij klm noa
|
23 |
EDOP |
The "edit polish opcode
register", which is one of the four so-called "editing"
registers. This register is used mainly by the
interpreter for decoding interpreted instructions (which are
packed two to a word), and has little value for other
purposes. When a value is written to this register, it
is automatically shifted right 7 positions, and the upper 8
bits are zeroed. Though the zeroing of these bits is
undefined in the reference documentation, it nevertheless
was the behavior of the hardware. For example, if the software attempts to write the following bits into the EDOP register, abc def ghi jkl mno
then the value actually stored in the EDOP register would
be: 000
000 00b cde fgh
|
24 |
TIME2 |
TIME1 is a
15-bit 1's-complement counter which is incremented every 10
ms. TIME1 by itself overflows every 214*10 ms.,
or 163.84 seconds. Upon overflow of TIME1, the 14-bit
counter TIME2 is automatically incremented. Thus, the
two counters together form a 28-bit value which can keep
track of time for up to 228*10 ms., or just over
31 days. The TIME1/TIME2 register pair acts as a
master clock for the AGC. yaAGC internally clocks
this counter. |
25 |
TIME1 |
|
26 |
TIME3 |
TIME3 is a 15-bit
1's-complement counter which is incremented every 10
ms. It is incremented synchronously with TIME1.
Upon overflow, it requests an interrupt (T3RUPT), which
results in vectoring to the interrupt service routine at
address 4014 (octal). This interrupt is used by the
"wait-list" for scheduling multi-tasking. Incrementing TIME3 is 7.5 ms. out of phase with incrementing TIME4 (i.e., TIME4 increments 7.5ms after TIME3). Thus, if the TIME3 interrupt service routine doesn't take any longer than 6ms. or so, the interrupts for the two will not conflict. Software typically uses this counter by having the interrupt service routine reload the counter with a value chosen to insure that the interrupts occur at a desired rate. For example, to make an interrupt occur once per second, at every interrupt the counter would be reloaded with 214-100=16284 (decimal). Because 10 ms. is usually much longer than the amount of time needed to vector to the interrupt service routine, it is unnecessary in such calculations to account for the time taken by the interrupt vectoring. yaAGC internally clocks this counter. |
27 |
TIME4 |
TIME4 is a 15-bit
1's-complement counter which is incremented every 10
ms. Upon overflow, it requests an interrupt (T4RUPT),
which results in vectoring to the interrupt service routine
at address 4020 (octal). The T4RUPT program
services the DSKY's display. (It does not service DSKY
keypad.) Incrementing TIME3 is 7.5 ms. out of phase with incrementing TIME4 (i.e., TIME4 increments 7.5ms after TIME3). Thus, the TIME4 interrupt service routine doesn't take any longer than 2 ms. or so, the interrupts for the two will not conflict. Software typically uses this counter by having the interrupt service routine reload the counter with a value chosen to insure that the interrupts occur at a desired rate. For example, to make an interrupt occur once per second, at every interrupt the counter would be reloaded with 214-100=16284 (decimal). Because 10 ms. is usually much longer than the amount of time needed to vector to the interrupt service routine, it is unnecessary in such calculations to account for the time taken by the interrupt vectoring. yaAGC internally clocks this counter. |
30 |
TIME5 |
TIME5 is a 15-bit
1's-complement counter which is incremented every 10 ms. It
is incremented 5 ms. out of ph ase with TIME1 and
TIME3. Upon overflow, it requests an interrupt
(T5RUPT), which results in vectoring to the interrupt
service routine at address 4010 (octal). This is
used by the digital autopilot (DAP) Software typically uses this counter by having the interrupt service routine reload the counter with a value chosen to insure that the interrupts occur at a desired rate. For example, to make an interrupt occur once per second, at every interrupt the counter would be reloaded with 214-100=16284 (decimal). Because 10 ms. is usually much longer than the amount of time needed to vector to the interrupt service routine, it is unnecessary in such calculations to account for the time taken by the interrupt vectoring. yaAGC internally clocks this counter. |
31 |
TIME6 |
TIME6 is a 15-bit
1's-complement counter which is updated every 1/1600 second
by means of a DINCunprogrammed sequence.
There
is a CPU flag which can mask counting of TIME6 on or
off. By writing 1 to bit 15 of i/o channel 13
(octal), TIME6 counting is enabled; conversely, by writing 0
to that bit, the TIME6 counting is disabled. Upon
reaching ±0, the counter requests an interrupt (T6RUPT),
which results in vectoring to the interrupt service routine
at address 4004 (octal), and then turns off the T6RUPT
counter-enable bit. The T6RUPT is used by the digital autopilot (DAP) of the LM to control the jets of the reaction control system (RCS). Thus a typical use might be:
|
32 |
CDUX |
These counters
are used to monitor the orientation of the spacecraft.
Three Control Data Units (CDUs) are dedicated to measuring
the 3 gimbal angles in the Inertial Measurement Unit
(IMU). CDUX refers to the "inner" gimbal angle, CDUY
refers to the "middle" gimbal angle, and CDUZ refers to the
"outer" gimbal angle. The CDUs are like analog-to-digital converters, and convert the analog angles to digital data comprehended by the CPU. The IMU provides a measurement platform which is stable with respect to the fixed stars, and maintains its orientation with respect to the stars even while the spacecraft itself rotates. The platform is physically mounted on gimbals, and by measuring the gimbal angles, the orientation of the spacecraft with respect to the IMU's stable platform can be deduced by calculation. (Because only 3 gimbals were used, it was possible for the spacecraft to rotate into positions beyond which the stable platform could no longer maintain its stability with respect to the fixed stars, and would thus begin to rotate with the spacecraft. This condition, "gimbal lock", resulted in an inability to continue monitoring spacecraft orientation and acceleration, and required re-entry of all orientation, position, and velocity data into the computer system. A 4th gimbal would have prevented gimbal lock, but was not provided for some reason.) These counters contain 15-bit 2's-complement unsigned values, and therefore can take values ranging from 0 to 32767 (decimal). The counters are processed with the PCDU unprogrammed sequence (see below) in order to increase the angles by one unit, and are processed with the MCDU unprogrammed sequence to decrease the angles by one unit. The units of measurement are quoted as 40" of arc in Savage&Drake, but actually they were 39.55078125" of arc, making the full range come out to exactly 360 degrees. |
33 |
CDUY |
|
34 |
CDUZ |
|
35 |
OPTY |
These counters
are used to monitor the orientation of the optics subsystem
(i.e., the line of sight) or LM rendezvous radar with
respect to the spacecraft. Two Control Data Units
(CDUs) are dedicated to measuring these relative
angles. OPTY refers to the trunnion angle, whereas
OPTX refers to the shaft angle. The CDUs are like
analog-to-digital converters, and convert the analog angles
to digital data comprehended by the CPU. These counters contain 15-bit 2's-complement unsigned values, and therefore can take values ranging from 0 to 32767 (decimal). The counters are processed with the PCDU unprogrammed sequence (see below) in order to increase the angles by one unit, and are processed with the MCDU unprogrammed sequence to decrease the angles by one unit. The units of measurement are quoted in Savage&Drake as 10" of arc for the optical trunnion angle, or 40" of arc for the radar trunnion angle or optical or radar shaft angles; but they were actually 9.887695312" and 39.55078125" of arc, respectively, making the full range come out to exactly 90 or 360 degrees. |
36 |
OPTX |
|
37 |
PIPAX |
"PIPA" stands
for "Pulsed Integrating Pendulous Accelerometer".
There are 3 PIPAs mounted on the stable platform of the
Inertial Management Unit (IMU). Since the PIPAs are
"integrating", they measure changes in velocity (i.e.,
"delta-V") rather than acceleration, and the counters PIPAX,
PIPAY, PIPAZ thus monitor the velocity of the spacecraft (as
long as gimbal lock has not occurred).
Savage&Drake quote the units as 5.85 cm./sec or 1
cm./sec., but do not state the conditions under which the
two different units are used. These counters are incremented or decremented with PINC or MINC unprogrammed sequences. |
40 |
PIPAY |
|
41 |
PIPAZ |
|
42 |
Q-RHCCTR (RHCP) "Pitch" |
LM only.
Each of these registers holds a count in 1's-complement
format, indicating the displacement of the rotational hand
controller (RHC) in the pitch, yaw, or roll axes. The
way this is supposed to work is as follows: There is a
deadband near the detent, where the count is supposed to be
zero. When outside of the deadband, the counter is
supposed to continually update to correspond to the angular
displacement. The count begins to be non-zero after
the angle has reached about 2°, is calibrated to a count of
42 at 10° (which is the nominal full-scale position), and
increases until reaching a mechanical stop at 13°. The
counts are supposed to update only if the RHC counts are
enabled (bit 8 of output channel 013 set) and when the count
is requested (bit 9 of output channel 013 set). In
other words, the flight software must enable the counters
and then request new data whenever it wants new data.
Furthermore, the fact that the RHC is out of detent is
reported to the CPU by clearing bit 15 of channel 031 to
zero. In practice, of course, people will be using 3D joysticks intended for games, rather than the actual LM RHC, so there's no way the yaACA program that manages all this can enforce these angles. So the way it actually works is this: yaACA assumes that the usable range in each axis, as reported by the joystick driver, is -127 to +127. (Any values outside this range are simply forced to be -127 or +127.) A raw value of 13 or less appears in the counter register as 0, a raw value of 97 appears in the counter register as 42, and all other values are scaled linearly from these reference points. The formula is Counter = (Raw - 13)/2. The maximum possible count is thus 57. For negative deflections, of course, the same formula applies but is simply negative. This formula is based partially on the characteristics of the LM RHC, but is also partially based on being able to translate from raw joystick values to RHCCTR registers relatively elegantly. It is, of course, possible to use MINC and PINC commands to alter the value of these register, but in the interest of reliablity, yaACA reports the count to yaAGC via fictitious input channels, 0170 (roll) or 0167 (yaw) or 0166 (pitch). The value in the input channel is a 1's-complement value in the range -57 to +57, and is placed directly in the counter by yaAGC. |
43 |
P-RHCCTR (RHCY) "Yaw" |
|
44 |
R-RHCCTR (RHCR) "Roll" |
|
45 |
INLINK |
This register is used to
receive digital uplink data from a ground station.
After the incoming data word is deposited in the register,
the UPRUPT interrupt-request is set. Correct data is
in one of two forms: the value 0 (which the ground
station may uplink for error-recovery purposes) or the
triply-redundant bit pattern cccccCCCCCccccc, where CCCCC is meant to
be the logical complement of ccccc , which is always a DSKY-type
keycode. Other patterns will be interpreted by the
flight software as corrupted data. |
46 |
RNRAD |
|
47 |
GYROCTR (GYROCMD) |
These registers are used
during IMU fine alignment to torque the gyro to the the
precise alignment expected by the AGS. (The tolerance
of fine alignment is approximately ±80" of arc.)
This register is written by the flight software with counts
(in AGC 1's-complement format) that represent the desired
drive on the currently selected axis. Only one axis
can be selected at any given time—namely, +X, -X, +Y, -Y,
+Z, or -Z—using bits 7-9 of output channel 014. Each
count represents ±0.617981" of arc. Actual torquing of
the gyro does not begin until bit 10 of output channel 014
is set. (For completeness, note also that bit 6 of
channel 014 is supposed to be set at least 20 ms. prior to
any of the other stuff just mentioned.) If the torque is supposed to be 1-16383 counts, it should be achieved in a single burst. However, if it is greater than that, it should be achieved by bursts of 8192 counts each, with bursts separated by 30 ms. If you examine the Luminary131 software, you'll see that it does exactly this. Upon detecting a non-zero value in the GYROCTR register while the gyro activity bit (10) in channel 014 is set, the true AGC would emit a stream of electronic pulses at a rate of 3200 pulses per second, with a pulse-count equal to the register value. yaAGC behaves simularly, except that it emits fictitious output channels 0174-0176, each one of which can contain multiple pulses, scheduled to roughly correspond to the 3200 pps. timing. As soon as yaAGC has read the GYROCTR register, it resets it to zero. I have no idea if the actual AGC did this or not. |
50 |
CDUXCMD |
These registers
are used during IMU coarse alignment to drive the IMU stable
platform to approximately the orientation expected by the
AGC. (The tolerance of coarse alignment is
approximately ±1.5°.) These registers are written by
the flight software with counts (in AGC 1's-complement
format) that represent the desired drive in each axis.
Each count represents ±0.04375°. (192 counts represent
±8.4 degrees.) The drive sequence does not actually
commence until the corresponding drive-enable bit is set in
output channel 14 (octal). Bit 15 (the most
significant bit) of channel 14 must be set to drive in the X
axis, bit 14 in the Y axis, and bit 13 in the Z axis.
yaAGC does not
perform this operation instantly, but instead simulates the
true AGC timing (which emits a burst of 192 count-pulses
every 600 ms. when active), using the fictitious
output channel 0177. Notice that all three
axes can be slewed simultaneously if multiple drive bits are
set in channel 014. yaAGCzeroes the CDUxCMD registers as soon as it has read them while the corresponding drive-bit in channel 014 is set. I have no idea if the actual AGC behaved this way or not. |
51 |
CDUYCMD |
|
52 |
CDUZCMD |
|
53 |
OPTYCMD |
|
54 |
OPTXCMD |
|
55 |
THRUST |
LM only. |
56 |
LEMONM |
LM only. |
57 |
OUTLINK |
One might suppose that since
the INLINK register is used for digital uplinks, then the
OUTLINK register is used for digital downlinks.
Actually, output channels 013, 034, and 034 are used for
digital downlinks, and OUTLINK apparently was not used at
all, at least according to the description of it in the
symbolic information listing document (p. 33).
That document saysNot used. Originally intended for use to provide "crosslink" capability for serial binary data to cell 00458 of another computer ....and then proceeds with a lengthy explanation of exactly how to use the "unused" register that I won't bother to cover here. |
60 |
ALTM |
LM only. |
Vector Address (octal) |
Interrupt Name |
Trigger Condition |
Description |
4000 |
(boot) |
Power-up or GOJ signal. |
This is
where the program begins executing at power-up, and where
hardware resets cause execution to go. |
4004 |
T6RUPT | Counter-register TIME6 decremented to 0. | The digital autopilot (DAP) for controlling thrust times of the jets of the reaction control system (RCS). |
4010 |
T5RUPT |
Overflow of counter-timer TIME5. |
Used by the autopilot. |
4014 |
T3RUPT | Overflow of counter-timer TIME3. | Used by the task scheduler (WAITLIST). |
4020 |
T4RUPT | Overflow of counter-timer TIME4. | Used for various DSKY-related activities such as monitoring the PRO key and updating display data. |
4024 |
KEYRUPT1 |
Keystroke received from DSKY. |
The DSKY
transmits codes representing keystrokes to the AGC.
Reception of these codes by the AGC hardware triggers an
interrupt. |
4030 |
KEYRUPT2 | Keystroke
received from secondary DSKY. |
In the CM, there was a second
DSKY at the navigator's station, used for star-sighting
data, in conjunction with the Alignment Optical Telescope
(AOT). There was no 2nd DSKY in the LM, but the
interrupt was not re-purposed. |
4034 |
UPRUPT |
Uplink word available in the INLINK register. |
Data
transmitted from ground-control for the purpose of
controlling or monitoring the AGC is in the form of a serial
data stream which is assembled in AGC INLINK
counter-register. When a word has been assembled in
this fashion, an interrupt is triggered. |
4040 |
DOWNRUPT | The
downlink shift register is ready for new data (output
channels 34 & 35). |
Used for
telemetry-downlink. |
4044 |
RADAR RUPT |
Automatically generated inside the AGC after a set pulse
sequence has been sent to the radars. |
Data
from the rendezvous radar is assembled similarly to the
uplink data described above. When a data word is
complete, an interrupt is triggered. |
4050 |
RUPT10, aka HANDRUPT |
Selectable from three possible sources: Trap 31A, Trap 31B, and Trap 32. |
Used for the hand controller. Only trap 31A is
ever used. Trap 31-A (enabled by resetting CH13 bit 12): Causes a RUPT10 when any of CH31 bits 1-6 are set. Trap 31-B (enabled by resetting CH13 bit 13): Causes a RUPT10 when any of CH31 bits 7-12 are set. Trap 32 (enabled by resetting CH13 bit 14): Causes a RUPT10 when any of CH32 bits 1-10 are set. |
Description: |
The "Add" instruction adds
the contents of a memory location into the accumulator. |
Syntax: |
AD K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow depends on the
result of the operation, and can be positive, negative, or
none. The Extracode flag remains clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
60000 + K |
Notes: |
The accumulator is not
overflow-corrected prior to the addition. The contents
of K are added
to the accumulator, which retains any overflow that resulted
from the addition. A side-effect of this instruction is that K is rewritten after its value is written to the accumulator; this means that if K is CYR, SR, CYL, or EDOP, then it is re-edited. Note that the normal result of AGC arithmetic such as (+1)+(-1) is -0. For the special case "AD A", refer instead to the DOUBLE instruction. |
Description: |
The "Add to Storage"
instruction adds the accumulator to an erasable-memory
location (and vice-versa). |
Syntax: |
ADS K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the addition. The Extracode flag
remains clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
26000 + K |
Notes: |
The contents of the
accumulator and K
are added together, and the result is stored both in the
accumulator and in K.
The
accumulator is neither overflow-corrected prior to the
addition nor after it. However, the sum is
overflow-corrected prior to being saved at K if K is a 15-bit
register. If K
is a 16-bit register like L or Q, then the sum is not
overflow corrected before storage. Note that the normal result of AGC arithmetic such as (+1)+(-1) is -0. If the destination register is 16-bits (L or Q register), then the non-overflow-corrected values added. |
Description: |
The "Augment" instruction
increments a positive value in an erasable-memory location
in-place by +1, or a negative value by -1. |
Syntax: |
AUG K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
24000 + K |
Notes: |
If K is
a 16-bit register like A, L, or Q, then arithmetic is
performed on the full 15-bit value (plus sign).
Otherwise, only the available 14-bit value (plus sign) is
used. If the contents of K before the operation is greater than or equal to +0, it is incremented by +1. On the other hand, if it is less than or equal to -0, it is decremented. If K is one of the counter registers which triggers an interrupt upon overflow, then an oveflow caused by AUG will trigger the interrupt also. These registers include TIME3-TIME6. Furthermore, if K is the TIME1 counter and the AUG causes an overflow, the TIME2 counter will be incremented. Some of the counter registers such as CDUX-CDUZ are formatted in 2's-complement format, but the AUG instruction is insensitive to this distinction and always uses normal 1's-complement arithmetic. |
Description: |
The "Branch Zero to Fixed"
instruction jumps to a memory location in fixed (as opposed
to erasable) memory if the accumulator is zero. |
Syntax: |
BZF K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address
in fixed memory. (In other words, the two most
significant bits of address K cannot be 00.) |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) if the accumulator is plus zero or minus zero, or 2 MCT (about 23.4 µs) if the accumulator is non-zero. |
Flags: |
The Overflow is not
affected. The Extracode flag is cleared. The Q
register is unaffected. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not affected. |
Octal: |
10000 + K |
Notes: |
If the accumulator is
non-zero, then control proceeds to the next
instruction. Only if the accumulator is plus zero or
minus zero does the branch to address K occur. The
accumulator (and its stored overflow) are not actually
modified. Note that if the accumulator contains overflow, then the accumulator is not treated as being zero, even if the sign-corrected value would be +0 or -0. This instruction does not set up a later return. Use the TC instruction instead for that. Indirect conditional branch: For an indirect conditional branch, it is necessary to combine an INDEX instruction with a BZF instruction. Refer to the entry for the INDEX instruction. |
Description: |
The "Branch Zero or Minus to
Fixed" instruction jumps to a memory location in fixed (as
opposed to erasable) memory if the accumulator is zero or
negative. |
Syntax: |
BZMF K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address
in fixed memory. (In other words, the two most
significant bits of address K cannot be 00.) |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) if the accumulator is zero or negative, or 2 MCT (about 23.4 µs) if the accumulator is positive non-zero. |
Flags: |
The Overflow is not
affected. The Extracode flag is cleared. The Q
register is unaffected. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not affected. |
Octal: |
60000 + K |
Notes: |
If the accumulator is
positive non-zero, then control proceeds to the next
instruction. Only if the accumulator is plus zero or
negative does the branch to address K occur. The
accumulator and its stored oveflow are not actually
modified. Note that if the accumulator contains +overflow, then the accumulator is not treated as being zero, even if the sign-corrected value would be +0. If the accumulator contains negative overflow, then the value is treated as being negative non-zero, so the jump is taken. This instruction does not set up a later return. Use the TC instruction instead for that. Indirect conditional branch: For an indirect conditional branch, it is necessary to combine an INDEX instruction with a BZMF instruction. Refer to the entry for the INDEX instruction. |
Description: |
The "Clear and Add" (or
"Clear and Add Erasable" or "Clear and Add Fixed")
instruction moves the contents of a memory location into the
accumulator. |
Syntax: |
CA K or CAE K or CAF K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory
address. The CAE
or CAF
variants differ from the generic CA, only in that the assembler is
supposed to display error messages if K is not in
erasable or fixed memory, respectively. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is cleared,
unless K is
the accumulator or the Q register. The Extracode flag
remains clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
30000 + K |
Notes: |
A side-effect of this
instruction is that K
is rewritten after its value is written to the accumulator;
this means that if K
is CYR, SR, CYL, or EDOP, then it is re-edited. Note that if the source register contains 16-bits (like the L or Q register), then all 16 bits will be transferred to the accumulator, and thus the overflow will be transferred into A. On the other hand, if the source register is 15 bits, then it will be sign-extended to 16 bits when placed in A. For the special case "CA A", refer instead to the NOOP instruction. |
Description: |
The "Count, Compare, and
Skip" instruction stores a variable from erasable memory
into the accumulator (which is decremented), and then
performs one of several jumps based on the original value of
the variable. This is the only "compare" instruction
in the AGC instruction set. |
Syntax: |
CCS K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag
remains cleared. |
Editing: |
The contents of K is edited if K is one of the special registers CYR, SR, CYL, or EDOP. |
Octal: |
10000 + K |
Notes: |
The operation of this
instruction is rather complex:
Note that the net effect of the way overflow is treated when K is A, L, or Q is to allow 16-bit loop counters rather than mere 15-bit loop counters. For example, if A contains +1 with +overflow, then CCS A will place +0 with +overflow into A, and another CCS A will place 037777 without overflow into A, and thus no anomaly is seen when decrementing from +overflow to no overflow. If K has negative overflow going into CCS, the absolute value operation will change it into positive overflow. All overflow conditions are taken into account before this operation; thus, if a given K has negative overflow, the negative branch of CCS is taken. |
Description: |
The "Complement the Contents
of A" bitwise complements the accumulator |
Syntax: |
COM |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs). |
Flags: |
The Overflow is unaffected.
The Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
40000 |
Notes: |
All 16 bits of the
accumulator are complemented. Therefore, in addition
to negating the contents of the register (i.e., converting
plus to minus and minus to plus), the overflow is preserved,
but swtiches type (i.e., negative overflow will become
positive overflow). This instruction assembles as "CS A". |
Description: |
The "Clear and Subtract"
instruction moves the 1's-complement (i.e., the negative) of
a memory location into the accumulator. |
Syntax: |
CS K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is cleared,
unless K is
the accumulator. The Extracode flag remains
clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
40000 + K |
Notes: |
A side-effect of this
instruction is that K
is rewritten with its original value after the accumulator
is written; this means that if K is CYR, SR, CYL, or EDOP, then it is
re-edited. Note that if the source register contains 16 bits (the A or Q register), then all 16 bits will be complemented and transferred to the accumulator, and thus the overflow in the source register will be inverted and transferred into A. (For example, +overflow in Q will turn into -overflow in A.) On the other hand, if the source register is 15 bits, then it will be complemented and sign-extended to 16 bits when placed in A. For the special case "CS A", refer instead to the COM instruction. |
Description: |
The "Double Add to Storage"
instruction does a double-precision (DP) add of the A,L
register pair to a pair of variables in erasable memory. |
Syntax: |
DAS K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. The location K contains the
more-significant word of a pair of variables containing a DP
value, while K+1
contains the less-significant word. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Overflow is
cleared. The Extracode flag remains clear. |
Editing: |
Editing is done if the K,K+1 variable pair overlaps the CYR, SR, CYL, and EDOP registers. |
Octal: |
20001 + K |
Notes: |
A variant on this instruction
is the case "DAS A"
Refer
to the DDOUBL
instruction for an explanation of this case. Prior to the instruction, the A,L register pair and the K,K+1 pair each contain a double precision (DP) value, with the more-significant word first and the less-significant word second. The signs of the contents of A and L need not agree, nor need the signs of K and K+1. (See above.) 16-bit values (the A, L, and Q registers) are not overflow-corrected prior to the addition. The words of the sum are overflow-corrected when saved to 15-bit registers but not when saved to 16-bit registers. The two DP values are added together, and the result is stored back in the K,K+1 pair. The signs of the resulting words need not agree; the sign of the less significant word is the same as the sign from an SP addition of the less-significant words. Any overflow or underflow from addition of the less-significant words rolls over into the addition of the more-significant words. If either of K or K+1 are editing registers (CYR, SR, CYL, or EDOP), then the appropriate editing occurs when K,K+1 are written. Note that the normal result of AGC arithmetic such as (+1)+(-1) is -0. After the addition, the L register is set to +0, and the A register is set to +1, -1, or +0, depending on whether there had been positive overflow, negative overflow, or no overflow during the addition. |
Description: |
The "Double Clear and Add"
instruction moves the contents of a pair of memory locations
into the A,L register pair. |
Syntax: |
DCA K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory
address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Overflow is
cleared. The Extracode flag is cleared. |
Editing: |
Editing is done after the operation, if K,K+1 coincides with CYR, SR, CYL, or EDOP. |
Octal: |
30001 + K |
Notes: |
The value from K is transferred
into the accumulator, while the value from K+1 is transferred
into the L register. A side-effect of this instruction is that K,K+1 are rewritten after their values are written to the A,L register pair; this means that if K or K+1 is CYR, SR, CYL, or EDOP, then they are re-edited. The instruction "DCA L" is an unusual case. Since the less-significant word is processed first and then the more-significant word, the effect will be to first load the L register with the contents of the Q register, and then to load the A register with the contents of L. In other words, A and L will both be loaded with the contents of the 16-bit register Q. On the other hand, the instruction "DCA Q" will cause the full 16-bit contents (including overflow) of Q to be loaded into A, and the 15-bit contents of EB to be loaded into L. |
Description: |
The "Double Complement"
bitwise complements the register pair A,L |
Syntax: |
DCOM |
Operand: |
This instruction has no
operand. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs). |
Flags: |
The Overflow is unaffected.
The Extracode flag is cleared. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
40001 |
Notes: |
All 16 bits of the
accumulator and all 15 bits of the L register are
complemented. Therefore, in addition to negating the
DP value (i.e., converting plus to minus and minus to plus),
the overflow in the accumulator is preserved. This instruction assembles as "DCS A". |
Description: |
The "Double Clear and
Subtract" instruction moves the 1's-complement (i.e., the
negative) of the contents of a pair of memory locations into
the A,L register pair. |
Syntax: |
DCS K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory
address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Overflow is
cleared. The Extracode flag is cleared. |
Editing: |
Editing is done after the operation, if K,K+1 coincides with CYR, SR, CYL, or EDOP. |
Octal: |
40001 + K |
Notes: |
The negative of the value
from K is
transferred into the accumulator, while the negative of the
value from K+1
is transferred into the L register. A side-effect of this instruction is that K,K+1 are rewritten after their values are written to the A,L register pair; this means that if K or K+1 is CYR, SR, CYL, or EDOP, then they are re-edited. For the special case "DCS A", refer to the DCOM instruction. The instruction "DCS L" is an unusual case. Since the less-significant word is processed first and then the more-significant word, the effect will be to first load the L register with the negative of the contents of the 16-bit Q register, and then to load the A register with the negative of the contents of L. In other words, A will be loaded with the contents of Q, and L will be loaded with the negative of the contents of Q. On the other hand, the instruction "DCS Q" will load A with the full 16-bit complement of Q, and will load L with the 15-bit complement of EB. |
Description: |
The "Double Precision Double"
instruction — and yes, that's really what it's called — adds
the double-precision (DP) value in the A,L register pair to
itself. |
Syntax: |
DDOUBL |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs). |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag remains
clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
20001 |
Notes: |
The A,L register pair is
treated as a DP value, and is added to itself, returning a
DP value in the A,L register. Note that if the accumulator contains overflow prior the addition, the accumulator will not be overflow-corrected prior to the addition, and thus the sign of the resulting sum will not be correct. As Blair-Smith and Savage&Drake state, the results will be "messy". Refer to the DAS instruction for a discussion of mismatched signs in the less-significant and more-significant words. |
Description: |
The "Diminish" instruction
decrements a positive non-zero value in an erasable-memory
location in-place, or increments a negative non-zero value. |
Syntax: |
DIM K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set as a
result of the operation. The Extracode flag is
cleared. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
26000 + K |
Notes: |
If K is a 16-bit
register like A or Q, then arithmetic is performed on
the full 15-bit value (plus sign). Otherwise, only
the available 14-bit value (plus sign) is used. If the contents of K before the operation is greater than +0, it is decremented by +1. On the other hand, if it is less than -0, it is incremented by +1. (For example, 6 would become 5, or -6 would become -5.) A value of +0 or -0 would be unchanged by the operation. Note, by the way, that +1 decrements to -0, as is normal for AGC additions. A sharp-eyed reader may notice that the DIM instruction behaves simularly to the DINC unprogrammed sequence, and wonder if it likewise emits POUT, MOUT, and ZOUT output pulses; it does not do so. Because ZOUT is one of the conditions for T6RUPT to occur, DIM TIME6 cannot trigger the interrupt. Some of the counter registers such as CDUX-CDUZ are formatted in 2's-complement format, but the DIM instruction is insensitive to this distinction and always uses normal 1's-complement arithmetic. |
Description: |
The "Double the Contents of
A" instruction adds the accumulator to itself. |
Syntax: |
DOUBLE |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 35.4 µs). |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag remains
clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
60000 |
Notes: |
The value in the accumulator
is added to itself, and then placed back into the
accumulator. This instruction assembles as " AD A ".Note that if the accumulator contains overflow prior the addition, the accumulator will not be overflow-corrected prior to the addition, and thus the sign of the resulting sum will not be correct. |
Description: |
The "Double Transfer Control,
Switching Both Banks" instruction performs a jump and
switching both fixed and erasable banks, by simultaneously
loading the BB and Z registers. |
Syntax: |
DTCB |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs). |
Flags: |
The Overflow is cleared. The
Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
52006 |
Notes: |
This instruction exchanges
the contents of A with Z, and the contents of L with
B. Thus by preloading the A,L register pair, we can
effectively perform a jump to a different memory bank, and
switching both fixed and erasable banks, whilst preserving
the current address and erasable- and fixed-memory banks for
a later return. The assembler, yaYUL, provides a pseudo-op 2BCADR for the purpose of creating data suitable for preloading into A,L. This assembles as a DXCH to address 5. Recall that registers 5 and 6 are the Z and BB registers. |
Description: |
The "Double Transfer Control,
Switching F Bank" instruction performs a jump to a different
fixed memory bank, by simultaneously loading the FB and Z
registers. |
Syntax: |
DTCF |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs). |
Flags: |
The Overflow is cleared. The
Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
52005 |
Notes: |
This instruction exchanges
the contents of A with FB, and the contents of L with
Z. Thus by preloading the A,L register pair, we can
effectively perform a jump to a different fixed-memory bank,
whilst preserving the current address and fixed-memory bank
for a later return. The assembler, yaYUL, provides a pseudo-op 2FCADR for the purpose of creating data suitable for preloading into A,L. This assembles as a DXCH to address 4. Recall that registers 4 and 5 are the FB and Z registers. |
Description: |
The "Divide" instruction
performs a division, giving a remainder and a quotient. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Syntax: |
DV K |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address,
and must therefore be in a subrange of erasable memory. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Timing: |
6 MCT (about 70.2 µs) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Flags: |
The Overflow is
cleared. The Extracode flag is cleared. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Octal: |
10000 + K |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Notes: |
The accumulator (and the Q
register if K
is Q) is considered as overflow-corrected during this
operation. There are two alternate but equally valid ways of looking at this operation.
The sign of the quotient (A register) is (as usual, according to the rules of arithmetic) positive if the signs of the dividend and divisor agree, and is negative if the signs of the dividend and divisor differ. The sign of the remainder (L register) is the sign of the dividend. Note that the sign of the dividend is the sign of the A register prior to the division, unless A is ±0; in that case, the sign of the dividend is the sign of the L register. For example, suppose that A contains +0 and L contains -0; then the overall sign of the dividend is -0. If the dividend is ±0 but the divisor is non-zero, the L register remains unchanged and the A register is assigned 0 with a sign according to the rules above. If the divisor is equal to the dividend in magnitude and they are nonzero, then the A register will be stored with ±37777, while the L register will be stored with the dividend. If both the dividend and the divisor are ±0, the A register will be stored with ±37777, and the L register will remain unchanged. If the divisor is less than the dividend in magnitude, according to Savage&Drake, "we get total nonsense", and there is no warning or indication of the problem; the advice given by Savage&Drake is simply to make sure (by pre-scaling) that this situation doesn't occur. I assume that "getting total nonsense" was accepted for pragmatic reasons, and was not seriously intended by the designers of the AGC hardware. However, on the grounds that Luminary or Colossus code may have relied on this "total nonsense" (as programmers tend to do), yaAGC returns random numbers in A and L in this case. Several numerical examples are given in Smally:
|
Description: |
The "Double Exchange"
instruction exchanges the double-precision (DP) value in the
register-pair A,L with a value stored in the erasable memory
variable pair K,K+1. |
Syntax: |
DXCH K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag
remains clear. |
Editing: |
Editing is done upon writing to K,K+1 if either is CYR, SR, CYL, or EDOP. |
Octal: |
52001 + K |
Notes: |
The accumulator is stored at
address K,
while the value in K
is stored into the accumulator. The value from the L
register is stored into K+1, and vice-versa. If K or K+1 is an editing
register (CYR, SR, CYL, EDOP), then the value from the A or
L register is edited whilst being stored into K or K+1. If K is Q, then the full 16-bit values of A and Q are exchanged. Otherwise, A is overflow-corrected before being stored in K, and K is sign-extended when placed in A. In the case of the "DXCH L" instruction (in which the source and destination ranges overlap, Q (full 16 bits, including overflow) goes into A, A goes into L, and L goes into Q. Note: The final contents of the L register will be overflow-corrected. |
Description: |
For machine checkout only. |
Syntax: |
EDRUPT K |
Operand: |
K is the address of an
instruction. In assembly, only the lower 9 bits are
retained, and the upper 3 bits are cleared.
However, the actual value is irrelevant and is ignored
during execution. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Extracode flag is
cleared. |
Editing: |
I presume there is no effect on CYR, SR, CYL, and
EDOP. |
Octal: |
07000 + KC |
Notes: |
This instruction is not listed by
Savage&Drake. It is listed
by Blair-Smith, but not explained, other than to say it
is for "machine checkout only". Note that software
versions prior to 20050820 incorporated a very different
conception of the operation of this instruction than
described below. Fortunately, I have been able to obtain an explanation directly from Hugh Blair-Smith: The EDRUPT instruction is so-called because it was requested by programmer Ed Smally, and was used only by him. From discussing it with Hugh and from examining the instruction's "control pulses", it appears to me that it does this:
|
Description: |
Set the Extracode flag, so
that the next
instruction encountered is taken from the "extracode"
instruction set rather than from the "basic" instruction
set. |
Syntax: |
EXTEND |
Operand: |
This instruction has no
operand. |
Extracode: |
This is not an extracode, and
therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is set. |
Editing: |
The CYR, SR, CYL, and EDOP
registers are not edited. |
Octal: |
00006 |
Notes: |
Sets the Extracode flag, so
that the next instruction countered will be decoded as an
"extracode" instruction rather than as a "basic"
instruction. Since only 3 bits are provided within
instruction words to indicate the instruction type, and yet
there are more than 8 instruction types, the "extracode"
method was provided as a means to have 4 bits available to
indicate instruction types, and thus to extend the number of
instruction types which can be represented. The Extracode flag is automatically reset as soon as the next instruction after EXTEND is executed, unless the next instruction is an INDEX instruction, in which case the next instruction after the INDEX is also treated as extracode. Interrupts are automatically disabled while the Extracode flag is set. Thus, there is no need to fear that an interrupt will occur between an EXTEND and the instruction following it, and hence that the wrong instruction will be affected by the EXTEND. The encoding of this instruction is a special case of TC K, in which K is the address 00006, however the action is completely unlike other TC instructions. Note that a normal TC instruction to address 00006 can be manufactured by means of indexing. For example, suppose that some location K contains the numerical value 6. The following sequence of instructions INDEX K
ends up executing an instruction numerically encoded as
00006 octal, just is the EXTEND instruction; however, that
instruction is treated literally as a TC instruction
addressing location 00006 rather than as an EXTEND instruction.TC A |
Description: |
The "Increment" instruction
increments an erasable-memory location in-place by +1. |
Syntax: |
INCR K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not affected
unless K is
the accumulator. The Extracode flag remains
clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
24000 + K |
Notes: |
If K is
a 16-bit register like A, L, or Q, then
non-overflow-corrected value is incremented. In
other words, in A, L, or Q, one can increment 0, 1, ...,
037777, 040000 (with + overflow), 040001 (with +
overflow), .... 077777 (with + overflow). For 15-bit
registers, one can only increment as high as 037777. If K is one of the counter registers which triggers an interrupt upon overflow, then an oveflow caused by INCR will trigger the interrupt also. These registers include TIME3-TIME6. Furthermore, if K is the TIME1 counter and the INCR causes an overflow, the TIME2 counter will be incremented. Some of the counter registers such as CDUX-CDUZ are formatted in 2's-complement format, but the INCR instruction is insensitive to this distinction and always uses normal 1's-complement arithmetic. |
Description: |
The "Index Next Instruction"
or "Index Extracode Instruction" instruction causes the next
instruction to be executed in a modified way from its actual
representation in memory. |
Syntax: |
INDEX K or NDX K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit address in
erasable memory when INDEX
is used as a basic instruction, but cannot be equal to
17octal. It can assemble to a 12-bit memory address
when INDEX is
used as an extracode instruction. |
Extracode: | This can be used with as a basic instruction (without a preceding EXTEND instruction), or as an extracode instruction (with a preceding EXTEND instruction). |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is not affected. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
50000 + K |
Notes: |
The idea behind this
instruction is that it simulates an indexed addressing
mode. The effect is to:
#
BEFORE EXECUTING THE FOLLOWING CODE,
# LOAD 1 INTO A TO JUMP TO LOC1, LOAD 2 # INTO A TO JUMP TO LOC2, AND SO ON. # SIMILARLY, LOAD -1 INTO A TO JUMP TO LOC-1. # (RECALL ALSO THAT "LOC-1" IS A LEGAL # SYMBOL NAME, AND DOES *NOT* MEAN # "LOC MINUS 1".) INDEX A TC JMPTAB ... TCF LOC-2 TCF LOC-1 JMPTAB TCF LOC0 TCF LOC1 TCF LOC2 TCF LOC3 ... For example, if we loaded the value 3 into the accumulator, then the "INDEX A" instruction would effectively turn the "TC JMPTAB" instruction into "TC JMPTAB +3", which would cause a jump to the "TCF LOC3" instruction. But the modification to the "TC JMPTAB" instruction caused by INDEX takes place only within the musty recesses of the CPU, and not in memory. So the code listed above could be in fixed memory, and is not self-modifying code. Note that the usefulness of INDEX is not limited to TC instructions, and applies to every instruction type. Indeed, there are cases where the indexing operation is used to change the instruction type itself rather than just the operand. If K is the A, L, or Q register (i.e., 16-bit registers), the value is overflow-corrected before use (though the register itself is not modified). The INDEX instruction is the only instruction which does not reset the extracode flag. The extracode flag, if set by the EXTEND instruction, will persist through any number of INDEX instructions. This is useful, of course, for indexing multi-dimensional objects such as matrices. A side-effect of this instruction is that K is rewritten after its value is interrogated; this means that if K is CYR, SR, CYL, or EDOP, then it is re-edited. It is worth noting that the INDEX instruction is the only case where yaAGC intentionally implements functionality significantly differently from the true AGC. The true AGC reacts to the INDEX instruction by computing the modified following instruction, storing it in the hidden CPU register B, advancing the program counter past the following instruction, and then executing the instruction it finds in the B register; it also allows interrupts to occur prior to executing the code in the B register. yaAGC, on the other hand, stores the index value itself in a hidden CPU register, advances the program counter only to the following instruction, and then adds the hidden index value to the following instruction when it actually reaches it; but it does not allow an interrupt between the INDEX and the following instruction. (Anyone who objects to this difference is free to send me a patch.) When the basic form of INDEX is used (i.e., without a preceding EXTEND), the special case of K being address 017 octal is not an INDEX instruction, refer instead to the RESUME instruction. The extracode version of INDEX, on the other hand, is never treated as RESUME. |
Description: |
Disable Interrupts. |
Syntax: |
INHINT |
Operand: |
This instruction has no
operand. |
Extracode: |
This is not an extracode, and
therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag remains clear. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00004 |
Notes: |
Globally disables
interrupts. Note that interrupts can be re-enabled
with the RELINT
instruction. Interrupts are automatically disabled during various conditions which prove troublesome, so it is not always necessary to explicitly use RELINT. This automatically disabling of interrupts is completely different from the flag manipulated by the INHINT and RELINT instructions. These additional interrupt-inhibiting conditions are described above. The encoding of this instruction is a special case of TC K, in which K is the address 00004, but the action is completely unlike other TC instructions. Note that a normal TC instruction to address 00004 can be manufactured by means of indexing. For example, suppose that some location K contains the numerical value 4. The following sequence of instructions INDEX K
ends up executing an instruction numerically encoded as
00004 octal, just is the INHINT instruction; however, that
instruction is treated literally as a TC instruction
addressing location 00004 rather than as an INHINT instruction.
TC A |
Description: |
The "Exchange L and K" instruction
exchanges the value in the L register with a value stored in
erasable memory. |
Syntax: |
LXCH K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not affected
unless K is
the accumulator, in which case it is cleared. The
Extracode flag remains clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
22000 + K |
Notes: |
If K is the accumulator or the Q register,
then the values will be the full 16 bits of the
sources. Otherwise, source data from 15-bit locations
will be sign-extended to 16 bits prior to storage in L, and
the data from L will be overflow-corrected to 15 bits prior
to storage in K. |
Description: |
The "Mask A by K" instruction
logically ANDs the contents of a memory location bitwise
into the accumulator. |
Syntax: |
MASK K or MSK K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag remains
clear. |
Editing: |
CYR, SR, CYL, or EDOP are
unchanged. |
Octal: |
70000 + K |
Notes: |
If K is a 16-bit register (L or Q), then
the full 16 bits of K
and A are logically anded and stored in the
accumulator. Otherwise, the source register is 15
bits, and the accumulator is overflow-adjusted prior to the
operation. The contents of K (which remains unchanged) are then
logically ANDed bitwise to the accumulator, and
sign-extended to 16 bits for storage in the accumulator. |
Description: |
The "Multiply" instruction
multiplies two single-precision (SP) values to give a
double-precision (DP) value. |
Syntax: |
MP K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs) |
Flags: |
The Overflow is
cleared. The Extracode flag is cleared. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
70000 + K |
Notes: |
The accumulator is overflow-adjusted prior to
the operation. The single-precision (SP)
contents of K
are then multiplied by the SP contents of the accumulator,
resulting in a double-precision (DP) value whose
more-significant word is stored into the accumulator and
whose less-significant word is stored into the L register. The sign of the resulting DP value is just what would be expected (i.e., positive when multiplying two factors with the same sign, and negative when multiplying two factors of opposite signs). If one of the factors is 0, determining the sign of the result (i.e., +0 or -0) is a little trickier, and is done according to the following rules:
It is important to remember that the AGC's SP and DP values represent numbers between (but not including) -1 and +1. Therefore, the result of a multiplication is always less than either of the factors which are multiplied together. While you can work with numbers larger than 1, such as calculating 2×2, the scaling of the the factors and the result must be carefully considered. For example, if you wanted to use the MP instruction with A and K each containing the octal value 2 (which would really be the SP value 2×2-14), then you would indeed find a result of 4, but it would be in L register because it would be part of the DP value 4×2-28 rather than just the integer 4. For the special case "MP A", refer instead to the SQUARE instruction. |
Description: |
The "Modular Subtract"
instruction forms a normal signed 1's-complement difference
from two unsigned 2's-complement values. |
Syntax: |
MSU K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit address in
erasable memory. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is cleared. The
Extracode flag is cleared. |
Editing: |
Editing is done upon output, if K is CYR, SR, CYL, or EDOP. |
Octal: |
20000 + K |
Notes: |
The contents of K are subtracted
from the accumulator. Both A and K are assumed to
contain 2's-complement unsigned values prior to the
calculation. The result of the subtraction (in the
accumulator) is converted to a 1's-complement value.
If K is the
16-bit Q register, then 16-bit values are used in the
calculation; otherwise, the overflow-corrected value from A
is used, and the result is sign-extended to 16 bit before
storing it back into A. The point of this instruction is that the CDU counters (see above) monitor gimbal angles in 2's-complement form, yet the CPU can only perform general calculations in 1's-complement form. This instruction thus provides a way to convert differences of gimbal angles to a form in which further calculation can be done. A side-effect of this instruction is that K is rewritten (with its original value) after the calculation; this means that if K is CYR, SR, CYL, or EDOP, then it is re-edited. |
Description: |
No-operation |
Syntax: |
NOOP |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) if executed from erasable memory, 1 MCT (about 11.7 µs) if executed from fixed memory. |
Flags: |
The Overflow is
unaffected. The Extracode flag is cleared. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
30000
(in erasable memory) or 10000 + next instruction address (in fixed memory) |
Notes: |
This instruction takes time
to execute, but has no other effect. The instruction
is assembled differently, depending on whether it is found
in erasable memory or in fixed memory. In erasable
memory, it assembles as "CA A" (i.e, as "load the accumulator
with itself"), while in fixed memory it assembles as a jump
(TCF) to the
next instruction. The latter method is apparently
considered preferable, because it requires less CPU cycles,
but cannot be used in erasable memory because the TCF instruction can
only target locations in fixed memory. Of course, "CA A" could still
be used in fixed memory by coding it directly rather than
using the generic NOOP
instruction. (Of course, these issues really relate to
the assembler, yaYUL,
rather than the CPU, since the CPU will execute whatever
instructions you throw at it.) |
Description: |
The "Overflow Skip"
instruction skips the next instruction if the accumulator
contains overflow. |
Syntax: |
OVSK |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs). |
Flags: |
The Overflow is not changed.
The Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
54000 |
Notes: |
This instruction simply
proceeds as normal to the next instruction if the
accumulator contains no overflow, but skips the next
instruction and goes to the instruction after that if the
accumulator does contain overflow. The accumulator
itself is unchanged. This instruction is encoded as "TS A". |
Description: |
The "Exchange Q and K" instruction
exchanges the value in the Q register with a value stored in
erasable memory. |
Syntax: |
QXCH K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit address in
erasable memory. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not affected
unless K is
the accumulator. The Extracode flag is cleared. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
22000 + K |
Notes: |
If K is the accumulator or L register,
then the full 16-bit values of A and Q are swapped.
Otherwise, the overflow-corrected value of Q is stored into
K, and the
contents of K
are sign-extended to 16 bits before storage in Q. |
Description: |
The "Read and Mask"
instruction logically bitwise ANDs the contents of an i/o
channel into the accumulator. |
Syntax: |
RAND KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
02000 + KC |
Notes: |
Refer to the list of
available i/o
channels. If the source is the 16-bit L or Q register, then the full 16-bit value is logically ANDed with A. Otherwise, the 15-bit source is logically ANDed with the overflow-corrected accumulator, and the result is sign-extended to 16 bits before storage in A. |
Description: |
The "Read Channel KC" instruction
moves the contents of an i/o channel into the accumulator. |
Syntax: |
READ KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
00000 + KC |
Notes: |
Refer to the list of
available i/o channels. If
the source is the 16-bit Q register, then the full 16-bit
value is moved into A. Otherwise, the 15-bit source is
sign-extended to 16 bits before storage in A. |
Description: |
Enable Interrupts. |
Syntax: |
RELINT |
Operand: |
This instruction has no
operand. |
Extracode: |
This is not an extracode, and
therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag remains clear. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00003 |
Notes: |
Enables interrupts.
Note that interrupts can be disabled with the INHINT instruction. The encoding of this instruction is a special case of TC K, in which K is the address 00003, but the action is completely unlike other TC instructions. Note that a normal TC instruction to address 00003 can be manufactured by means of indexing. For example, suppose that some location K contains the numerical value 3. The following sequence of instructions INDEX K
ends up executing an instruction numerically encoded as
00003 octal, just is the RELINT instruction; however, that
instruction is treated literally as a TC instruction
addressing location 00003 rather than as an RELINT instruction.
TC A |
Description: |
Resume Interrupted Program. |
Syntax: |
RESUME |
Operand: |
This instruction has no
operand. |
Extracode: |
This is a basic instruction,
and therefore cannot be preceded by EXTEND. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is cleared. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
50017 |
Notes: |
This instruction is used to
return from an interrupt-service routine. Interrupt
vectoring automatically copies the contents of the current
instruction pointer (Z register) into the ZRUPT register and
copies the contents of the memory location pointed to by the
Z register (in other words, the value of the current
instruction) into the BRUPT register. Thus, in order
to resume after interrupt, the RESUME instruction copies the ZRUPT
register back to the Z register and then causes the
instruction stored in the BRUPT register to be executed as if it were stored in
memory at the location pointed to by Z. This oddity of executing the instruction stored in the BRUPT allows the programmer to execute an arbitrary instruction upon return from interrupt, rather than executing the instruction originally appearing in the program flow. Obviously, you never want to do this. While theoretically providing this capability, the BRUPT register actually exists for the purpose of holding instructions which have been altered by a preceding INDEX instruction, but which have not yet been executed when the interrupt vectoring occurs. This was necessary in the true AGC, because the AGC allowed interrupts to occur between an INDEX instruction and the instruction affected by the INDEX instruction, and thus it was necessary to stored the indexed instruction somehow, so that it could be executed when normal operation resumed after the interrupt. yaAGC does not allow interrupts following an INDEX instruction, and conflicts between INDEX and the interrupt system do not arise in yaAGC. However, the BRUPT register continues to be supported by yaAGC. The RESUME instruction is a special case of INDEX, in which K is the address 00017, but the action is completely unlike other INDEX instructions. (The logic of using address 00017, by the way, is that address 00017 is the BRUPT register; see above.) Note that a normal INDEX instruction to address 00017 can itself be manufactured by means of indexing. For example, suppose that some location K1 contains the numerical value 00000 and K2 is the address 00017 octal. The instruction sequence INDEX K2
would not index the final instruction as shown, because "INDEX K2" would be
interpreted as RESUME
rather than as an INDEX
instruction. However, the sequence of instructionsSome instruction INDEX K1
converts "INDEX K2"
into a literal INDEX
instruction rather than allowing it to be reinterpreted as RESUME, and thus
does index the final instruction. On the other hand,
and probably more logically, the first code sequence shown
would have worked to index the instruction if preceded by an
EXTEND
instruction, since RESUME
is a basic instruction and not an extracode instruction.INDEX K2 Some instruction Note that any useful interrupt service routine would modify the A register (and probably the L, Q, and BB registers). Registers called ARUPT, LRUPT, QRUPT, and BBRUPT are dedicated to holding register values during the interrupt service routine, yet the act of vectoring to the interrupt does not automatically A, L, Q, and BB to ARUPT, LRUPT, QRUPT, and BBRUPT. Nor does the RESUME instruction restore A, L, Q, and BB from ARUPT, LRUPT, QRUPT, and BBRUPT. Consequently, most useful interrupt service routines will need to begin by saving A, L, Q, and BB, and will need to end by restoring them prior to the RESUME instruction. Interrupts are disabled during execution of an interrupt service routine, independently of the use of the INHINT and RELINT instructions. Interrupts are re-enabled (if not previously disabled by INHINT) when the RESUME instruction is executed. |
Description: |
The "Return from Subroutine"
instruction. |
Syntax: |
RETURN or TC Q |
Operand: |
None |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is not affected (but is
clear). The Q register is loaded with 00003 (octal). |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00002 |
Notes: |
This instruction is the same
as all other TC
instructions. It makes use of an indirect jump through
register Q. (see below). This works because the TC
instruction reads the instruction at its target address before
updating Q. |
Description: |
The "Read and Superimpose"
instruction logically bitwise ORs the contents of an i/o
channel into the accumulator. |
Syntax: |
ROR KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
04000 + KC |
Notes: |
Refer to the list of
available i/o
channels. One unobvious use of this instruction
is to overcome the lack of a logical-OR instruction with a
memory operand, by recalling that the L and Q registers are
duplicated into i/o-channel space. If the source is the 16-bit Q register, then the full 16-bit value is logically ORed with A. Otherwise, the 15-bit source is logically ORed with the overflow-corrected accumulator, and the result is sign-extended to 16 bits before storage in A. |
Description: |
The "Read and Invert"
instruction logically bitwise exclusive-ORs the contents of
an i/o channel into the accumulator. |
Syntax: |
RXOR KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
06000 + KC |
Notes: |
Refer to the list of
available i/o
channels. One unobvious use of this instruction
is to overcome the lack of a logical-XOR instruction with a
memory operand, by recalling that the L and Q registers are
duplicated into i/o-channel space. If the source is the 16-bit Q register, then the full 16-bit value is logically exclusive-ORed with A. Otherwise, the 15-bit source is logically exclusive-ORed with the overflow-corrected accumulator, and the result is sign-extended to 16 bits before storage in A. |
Description: |
"Square the Contents of A" |
Syntax: |
SQUARE |
Operand: |
This instruction has no
operand. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
3 MCT (about 35.1 µs). |
Flags: |
The Overflow is cleared (but
see notes). The Extracode flag is cleared. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
70000 |
Notes: |
The accumulator is multiplied
by itself, and the result stored back into the accumulator
(more-significant word) and the L register (less-significant
word). Both Blair-Smith and Savage&Drake state that the results are "messy" if the accumulator contains positive or negative overflow prior to the operation. This instruction assembles as "MP A". |
Description: |
The "Subtract" instruction
subtracts a memory value from the accumulator. |
Syntax: |
SU K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit address in
erasable memory. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set on the
basis of the output of the calculation. The Extracode
flag is cleared. |
Editing: |
Editing is done upon output, if K is CYR, SR, CYL, or EDOP. |
Octal: |
60000 + K |
Notes: |
The contents of K are subtracted
from the accumulator, which is not overflow-corrected in advance of the
calculation. If K
is the 16-bit L or Q register, then the full 16-bit
non-overflow-corrected value of K is used in the calculation.
Otherwise, K
is sign-extended to 16 bits before the calculation. Note that the normal result of AGC arithmetic such as 1-1 is -0. A side-effect of this instruction is that K is rewritten (with its original value) after the calculation; this means that if K is CYR, SR, CYL, or EDOP, then it is re-edited. |
Description: |
The "Transfer Control" (or
"Transfer Control setting up a Return") instruction calls a
subroutine, first preparing for a later return to the
instruction following the TC instruction. |
Syntax: |
TC K or TCR K |
Operand: |
K is the label of the start of the
subroutine. It must assemble to a 12-bit memory
address, other than 2, 3, 4, or 6. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is clear after the
instruction. The Q register is set up with the address
following the instruction. |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00000 + K |
Notes: |
Nesting of subroutine calls: The
AGC is not stack-based, and does not automatically support
nesting of subroutines. Only one level of
subroutine-calls is supported directly by the CPU.
Thus, each use of a TC
instruction destroys the subroutine-return which has been
set up by prior TC
instructions. If additional levels are required, the
program must specifically allocate storage and save/restore
the subroutine-return information (from/to the Q register). Indirect jumps: The TC instruction may also be used to accomplish an indirect jump (i.e., a jump to a computed rather than a hard-coded address) by first loading the A register with the desired 12-bit address, and then using the instruction TC A. Note, though, that this will be an indirect jump to the address, rather than an indirect call to the address. The reason the latter trick works is a side-effect of the fact that the instruction TC K assembles to the octal value K. When an instruction like TC A is executed, the CPU does not actually load the program counter with the contents of the A register, as we might suppose. Instead, it literally calls the subroutine at memory location 0 (since the A register has address 0), and what it finds at address 0 is coincidentally another TC instruction. A return from the subroutine is not correctly set up in this case because the return which is set up is for the TC instruction at address 0, rather than for the TC A instruction that started the chain of events. Thus, the Q register will contain a value of 1. Incidentally, it should also be obvious that TC A will require 2 MCT of CPU time instead of the 1 MCT quoted earlier, since it actually results in two TC instructions being executed. A similar but subtly different effect occurs when using the "TC Q" instruction to return from a subroutine. Refer to the RETURN instruction for full details. Indirect calls: For an indirect call, it is necessary to combine an INDEX instruction with a TC instruction. Refer to the entry for the INDEX instruction. The XXALQ, XLQ, RETURN, INHINT, RELINT, and EXTEND instructions are encoded as TC, for K=0, 1, 2, 3, 4, or 6, respectively. The XXALQ and XLQ instructions really behave exactly as you'd expect from the descriptions I've given of the TC instruction, whereas RETURN has slightly different functionality than other TC instructions, and INHINT, RELINT, and EXTEND are completely different from other TC instructions. |
Description: |
"Transfer Control to Address
in A" |
Syntax: |
TCAA |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs). |
Flags: |
The Overflow is cleared. The
Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
54005 |
Notes: |
The low-order 12 bits of the
accumulator are placed into the Z register (causing a
jump). If positive overflow existed, then the
accumulator is loaded with the value +1, and if there had
been negative overflow, the accumulator is loaded with the
value -1. The accumulator is unchanged if there had
been no overflow. This instruction is encoded as "TS Z". |
Description: |
The "Transfer Control to
Fixed" instruction jumps to a memory location in fixed (as
opposed to erasable) memory. |
Syntax: |
TCF K |
Operand: |
K is the label of a memory
location. It must assemble to a 12-bit memory address
in fixed memory. (In other words, the two most
significant bits of address K cannot be 00.) |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag remains clear. The
Q register is unaffected |
Editing: |
The CYR, SR, CYL, and EDOP registers are not affected. |
Octal: |
10000 + K |
Notes: |
This instruction does not set up a later
return. Use the TC
instruction instead for that. Indirect jumps: For an indirect jump, it is necessary to combine an INDEX instruction with a TCF instruction. Refer to the entry for the INDEX instruction. |
Description: |
The "Transfer to Storage"
instruction copies the accumulator into memory ... and so
much more. |
Syntax: |
TS K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory, but not 0 (the accumulator). |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is
cleared. The Extracode flag remains clear. |
Editing: |
Editing is done upon writing to K if K is CYR, SR, CYL, or EDOP. |
Octal: |
54000 + K |
Notes: |
The special case "TS A" acts somewhat
differently; refer to the OVSK instruction instead. The value of the accumulator (overflow-corrected if K is not the 16-bit L or Q register) is copied into K, at the same time being edited if K is CYR, SR, CYL, or EDOP. The action of the TS instruction differs, depending on whether or not the accumulator had originally contained overflow:
|
Description: |
The "Write and Mask"
instruction bitwise logically-ANDs the contents of the
accumulator into an i/o channel, and vice-versa. |
Syntax: |
WAND KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
03000 + KC |
Notes: |
Refer to the list of
available i/o
channels. The bitwise logical-AND of the
accumulator and the i/o channel is copied into both the
accumulator and the i/o channel. If the destination is the 16-bit Q register, then the full 16-bit value is logically ANDed with A and stored at both A and K. Otherwise, the 15-bit destination is logically ANDed with the overflow-corrected accumulator and stored to K, and the result is sign-extended to 16 bits before storage in A. |
Description: |
The "Write and Superimpose"
instruction bitwise logically-ORs the contents of the
accumulator into an i/o channel, and vice-versa. |
Syntax: |
WOR KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
05000 + KC |
Notes: |
Refer to the list of
available i/o
channels. The bitwise logical-OR of the
accumulator and the i/o channel is copied into both the
accumulator and the i/o channel. One unobvious use of
this instruction is to overcome the lack of a logical-OR
instruction with a memory operand, by recalling that the L
and Q registers are duplicated into i/o-channel space. If the destination is the 16-bit Q register, then the full 16-bit value is logically ORed with A and stored at both A and K. Otherwise, the 15-bit destination is logically ORed with the overflow-corrected accumulator and stored to K, and the result is sign-extended to 16 bits before storage in A. |
Description: |
The "Write Channel KC" instruction
moves the contents of the accumulator into an i/o channel. |
Syntax: |
WRITE KC |
Operand: |
KC is an i/o-channel location. It
must assemble to a 9-bit address. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag is
cleared |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unchanged. |
Octal: |
01000 + KC |
Notes: |
Refer to the list of
available i/o
channels. If the destination is the 16-bit Q register, then the full 16-bit value of A is stored into K. Otherwise, the value is overflow-corrected before storage. |
Description: |
The "Exchange A and K" instruction
exchanges the value in the A register with a value stored in
erasable memory. |
Syntax: |
XCH K |
Operand: |
K is the label of a memory
location. It must assemble to a 10-bit memory address
in erasable memory. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs) |
Flags: |
The Overflow is set according
to the result of the operation. The Extracode flag
remains clear. |
Editing: |
Editing is done upon writing to K, if K is CYR, SR, CYL, or EDOP. |
Octal: |
56000 + K |
Notes: |
The accumulator is stored at
address K,
while the value in K
is stored into the accumulator. If K is the 16-bit L
or Q register (or the 16-bit A register), then the full
contents of the registers (including overflow) are
exchanged; otherwise, the value of A is overflow-corrected
before being stored in K, and the value of K is sign-extended
to 16 bits before being stored in A. If K is an editing
register (CYR, SR, CYL, EDOP), then the value from the
accumulator is edited whilst being stored into K. |
Description: |
The "Execute Using L and Q"
instruction is another name for "TC L". |
Syntax: |
XLQ |
Operand: |
None |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is not affected (but is
clear). The Q register is set up with the address
following the instruction (but see the notes). |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00001 |
Notes: |
This instruction is
identical to "TC L"
(see above), but has been given a different name on the
suppostition that the programmer might like to use it to
execute a single basic (i.e., non-extracode) instruction
chosen at runtime, without otherwise interrupting program
flow. The way this would be done is to:
Blair-Smith implies that the following sequence is preferred to XLQ in most cases: INDEX L
OCT 0 |
Description: |
The "Execute Extracode Using
A, L, and Q" instruction is another name for "TC A". |
Syntax: |
XXALQ |
Operand: |
None |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
1 MCT (about 11.7 µs) |
Flags: |
The Overflow is not
affected. The Extracode flag is not affected (but is
clear). The Q register is set up with the address
following the instruction (but see the notes). |
Editing: |
The CYR, SR, CYL, and EDOP registers are not edited. |
Octal: |
00000 |
Notes: |
This instruction is
identical to "TC A"
(see above), but has been given a different name on the
suppostition that the programmer might like to use it to
execute a single extracode instruction chosen at runtime,
without otherwise interrupting program flow. The way
this would be done is to:
Blair-Smith recommends that this functionality is usually provided better by the sequence: EXTEND
INDEX L OCT 0 |
Description: |
The "Zero L" instruction
writes a value of 0 to the L register. |
Syntax: |
ZL |
Operand: |
This instruction has no
operand. |
Extracode: | This is not an extracode, and therefore cannot be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs). |
Flags: |
The Overflow is unaffected.
The Extracode flag remains clear. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
22007 |
Notes: |
This assembles as an LXCH to address
7. Recall that register 7 is hardwired to 0 rather
than to a memory location, and hence always contains the
value 0. |
Description: |
The "Zero Q" instruction
writes a value of 0 to the Q register. |
Syntax: |
ZQ |
Operand: |
This instruction has no
operand. |
Extracode: | This is an extracode, and therefore must be preceded by an EXTEND instruction. |
Timing: |
2 MCT (about 23.4 µs). |
Flags: |
The Overflow is unaffected.
The Extracode flag is cleared. |
Editing: |
The editing registers CYR,
SR, CYL, or EDOP are unaffected. |
Octal: |
22007 |
Notes: |
This assembles as a QXCH to address
7. Recall that register 7 is hardwired to 0 rather
than to a memory location, and hence always contains the
value 0. |
(Versions 2016-09-29 and later.) This is an experimental
concept for a new pseudo-op not present in the original AGC code,
but which could be possibly be of value in the process of
transcribing hard-copies or scanned AGC assembly listings to ASCII
source code that can be assembled later with yaYUL.
It provides a way to instruct the assembler, after SETLOC,
BANK, or BLOCK pseudo-ops have been used, how
many words that section of memory will contain before the nextSETLOC,
BANK, or BLOCK pseudo-op is encountered.
What this does is to allow the assembler to potentially assemble
AGC source code which has only been partially transcribed, but to
still locate all symbols and code at their proper locations in
memory in spite of that (though not necessarily with their proper
numerical values, since not all operands may be resolvable).
After the code has been entered completely, the SECSIZ
pseudo-ops can be either retained or discarded without affecting
the assembly process.
If a BANK pseudo-op is used together with a SETLOC,
then SECSIZ must follow the BANK rather than
the SETLOC. Here is an example of usage, with
alternating uses of block 2 and block 3. Arbitrary SECSIZ
pseudo-ops have been added, but you can see that whenever a switch
is made back to block 2 or 3 from block 3 or 2, an amount of space
equivalent to the SECSIZ has been allocated, rather than
just the space needed for the instructions explicitly present:
000005,000005: ??????? A EQUALS 0
000006,000006:
000007,000007: 4000 BLOCK 2
000008,000008: 4000 SECSIZ 25
000009,000009: 4000 60000 FIRST AD A
000010,000010: 4001 60000 AD A
000011,000011:
000012,000012: 6000 BLOCK 3
000013,000013: 6000 SECSIZ 64
000014,000014: 6000 56000 SECOND XCH A
000015,000015: 6001 BANK
000016,000016: 6064 SECSIZ 6
000017,000017: 6064 60000 SECONDB AD A
000018,000018:
000019,000019: 4000 SETLOC FIRST
000020,000020: 4000 BANK
000021,000021: 4025 SECSIZ 12
000022,000022: 4025 60000 THIRD AD A
000023,000023:
000024,000024: 6072 BLOCK 3
000025,000025: 6072 SECSIZ 14
000026,000026: 6072 60000 FOURTH AD A
000027,000027:
000028,000028: 6106 BLOCK 3
000029,000029: 6106 SECSIZ 31
000030,000030: 6106 60000 FIFTH AD A
000031,000031:
000032,000032: 02,2037 BANK 2
000033,000033: 02,2037 SECSIZ 17
000034,000034: 02,2037 60000 SIXTH AD A
000035,000035: 02,2040 BANK
000036,000036: 02,2056 SECSIZ 18
000037,000037: 02,2056 60000 SEVENTH AD A
Description: |
|
Syntax: |
STCALL X Y |
Operand(s): |
X is in unswitched erasable or in the
current erasable bank. |
Timing: |
|
Octal: |
34001 + e(X) |
Notes: |
Description: |
|
Syntax: |
STODL X [Y] |
Operand(s): |
X is in unswitched erasable or in the
current erasable bank. |
Timing: |
|
Octal: |
14001 + e(X) |
Notes: |
Description: |
|
Syntax: |
STORE X |
Operand(s): |
X is in unswitched erasable or in the
current erasable bank. |
Timing: |
|
Octal: |
00001 + e(X) |
Notes: |
Description: |
|
Syntax: |
STOVL X [Y] |
Operand(s): |
X is in unswitched erasable or in the
current erasable bank. |
Timing: |
|
Octal: |
24001 + e(X) |
Notes: |
Actually — confession time! — the truth is that I (Ron Burkey)
have spent very little time figuring out what the various
interpreter instructions do, so I can't really say much more about
them than I've said above. Fortunately, Mark Schulman
(thanks, Mark!) has stepped in to fill in the gaps and provide a
pretty comprehensive explanation of how it all works. This
entire section, which I've turned brown
to make it stand out, has been written by Mark with only minimal
editing (for format) by me. I'm sure there's some overlap
with what I said about the interpreter above, but I've made no
attempt to edit Mark's content. At any rate, I'll turn it
over to Mark here:
Because the AGC used a 3-bit opcode, the number of instructions was limited. The hardware designers used various tricks (such as the EXTEND instruction) to increase the number of opcodes — there were 40 — but the AGC's instruction set was still limited. Additionally, important operations (such as trig functions and vector manipulation) are not supported by the hardware, which meant that performing navigation calculations required an enormous number of subroutine calls.
To solve these problems, as well as get around the general unwieldiness of writing large programs for the AGC, the developers implemented an interpreter that simulated a computer that was an easier and more natural fit for navigation calculations. The machine simulated by the Interpreter is quite different from the AGC, with its own set of registers, more powerful instructions, and a different memory model.
The result is that some software in the AGC is written using the AGC's native instructions, and some of the software is written using the instructions that are understood by the Interpreter. YUL (the assembler) understands both sets of instructions, but it is up to the programmer to use the proper instructions at the proper place in the code, as described below.
The Interpreter includes these features:
The software that implements the Interpreter occupies most of fixed bank 00, some of 01, and some fixed-fixed memory.
A machine-code program starts a block of interpreted code by calling the INTPRET subroutine with this assembler instruction:
The Interpreter expects the TC INTPRET instruction to be immediately followed by a block of Interpeter code. The Interpreter reads and executes this code until it encounters an EXIT Interpreter instruction. The Interpreter assumes that the memory word following the EXIT instruction is an AGC machine instruction, and execution continues immediately after the EXIT.
The typical structure of a program containing Interpreter code looks like this:
It is vitally important that a programmer use the appropriate instructions in the appropriate context. If a programmer uses an Interpreter instruction in the middle of AGC code without starting the Interpreter, the AGC will misinterpret the instruction. Similarly, if a programmer uses a native AGC instruction inside a block of Interpreter code, a similar misinterpretation will occur.
An interpreted program can call a machine code subroutine by executing an RTB instruction (which branches to a machine code location). The RTB instruction stores a return address in the Interpreter. When the machine code subroutine has finished executing, it returns to the interpreted code by executing this instruction:
"Outside my bailiwick, you say? Nay sir, I'm fairly sure I personally coined the term in that context. The interpretive language, in both Block I and Block II, was formatted in 'Polish notation,' where one word was occupied by two operation codes and the next few words held as many addresses as those op codes needed. The additional gimmick was that the logic in the interpreter that picked up addresses could tell when it was looking at an op code word instead, in which case it understood that the address it was thinking of wasn't necessary, and it should pop an operand off the stack instead. That's how it implemented Lukasiewicz's parenthesis-free notation, spending a little logic to save words of memory.So there you have it.
"So .......... the dispatcher is the 'gateway to Poland' and as any student of World War II history knows, the bogus Polish provocation, and the Wehrmacht's all-too-ready charge across the border, occurred in Danzig. It was many years before I understood that 'Danzig' was a German respelling of the city known to any proper Pole as 'Gdansk.'
"But it was 'Danzig' on the maps and globes of my childhood, so established by the Treaty of Versailles to give Poland a corridor to the Baltic Sea, and that's why!"
The Interpreter simulates these registers:
MPAC | Multi-purpose accumulator. The MPAC can contain single-, double-, and triple-precision values, and double-precision vectors. The Interpreter keeps track of the type of value currently stored in the MPAC. |
OVFIND | An overflow indicator register. |
ADRLOC | A program counter. |
QPRET | Return address register. |
X1, X2 | Two index registers |
S1, S2 | Two step registers, primarily used as loop counters |
There are five sets of registers, so the Interpreter can support up to five simultaneous programs.
The Interpreter simulates a push-down stack, which can contain up to 38 values.
The Interpreter supports 120 binary (on/off) switches, number 0 - 119 (decimal).
The AGC hardware uses a complex and cumbersome memory model which divides both erasable and fixed memory into a series of banks. Banking registers are required to specify which banks of memory are being accessed. The Interpreter relieves the programmer of dealing with most of this complexity within interpreted code. An interpreted program can access roughly half of erasable memory and half of fixed memory.
The Interpreter organizes memory into these three areas:
These rules apply:
The memory organization presented to a program differs, depending on whether a program is located in low fixed memory or high fixed memory:
Address (oct) | Size (dec) | Program in Low Fixed Memory | Program in High Fixed Memory |
---|---|---|---|
00000 - 01377 | 768 | Unswitched erasable memory (i.e. erasable banks 0 - 2) | |
01400 - 01777 | 256 | Currently-selected erasable bank* | |
02000 - 07777 | 3K | Not usable | Fixed banks 21 - 23 |
10000 - 37777 | 13K | Fixed banks 04 - 17 | Fixed banks 24 - 37 |
*This is the erasable memory bank that is selected by the AGC's EBANK register.
Since a 15-bit address can't access enough memory locations the include all the fixed banks, the designers who wrote the Interpreter came up with this scheme: When an interpreted program runs, an internal register called INTBIT15 is set to 1 if the program is in high fixed memory; 0 otherwise. The Interpreter prepends this bit onto data addresses if the address is 2000 (octal) or above. The net effect is that a 15-bit address enables any program in low fixed memory to reach any address in low fixed memory, and any program in high fixed memory to reach any address in high fixed memory.
The Interpreter doesn't support indexing on branch instructions, but it does support a method of indirection. The Interpreter requires that all executable code reside in fixed memory, and that erasable memory is used only for data. If the argument for a branch instruction works out to an address in erasable memory, then the assumption is that the location in erasable memory contains an address — the value in the erasable memory location is read and the Interpreter branches to that address. This continues any number of times, until the address resolves to an address in fixed memory.
Interpreter instructions pack two 7-bit opcodes into a single word, like so:
1 | opcode 1 | opcode 2 | ||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
This word is then followed by whatever arguments are required by the first opcode, and then by whatever arguments are required for the second opcode.
The 127 possible opcodes are divided into four categories, specified by the two low-order bits in each opcode. Roughly, the lowest bit — bit 1 — specifies whether the opcode requires an argument, and bit 2 determines whether the argument may be indexed. Specifically, the four categories work like this:
Bit 2 & 1 | Description |
---|---|
00 | Instruction does not take an argument and are not indexed. |
01 | Instructions that take an argument and are not indexed. The argument is always an address (never a value), and can be taken either from the word following the instruction, or from the stack. The Interpreter determines where to get its argument by looking at the word following the instruction. It counts on the fact that instruction words always have bit 15 set to 1, and arguments that don't involve indexing (and instructions in this class never involve indexing) always have their bit 15 set to zero. So if the word following the instruction has its 15 bit set to 0, it's the argument for this instruction; if it's set to 1, it's the next instruction and the argument should be pulled off the stack. [What's not clear to me is how to handle the case in which opcode 1 is in class 01, and opcode 2 is in class 11. It seems that there could be a problem if the intention is to get opcode 1's argument from the stack, but opcode 2's argument follows the instruction.] |
10 | Branch and index instructions. This class is handled as a special case, and the individual bits do not have their usual meaning. |
11 | Instruction requires an address and may be indexed. Bit 15 of the argument determines which index register is used (0=X1, 1=X2). |
Store instructions break the usual pattern of packing two 7-bit opcodes into a word. They consist of a single opcode with a 10-bit address in erasable memory.
The following table describes each Interpreter opcode. The "Args" column indicates whether the instruction requires 0, 1, or 2 arguments, and whether the arguments are addresses or constants.
The documentations didn't provide the numeric opcodes for any of the instructions, so it's hard to tell which of the four classes each opcode falls into.
Opcode | Args X, Y | Description |
---|---|---|
ABS | Absolute Value. Replaces the scalar value in the MPAC with its absolute value. | |
ABVAL | Vector Absolute Value. Replaces the vector value in the MPAC with its absolute value as a scalar. [Documentation goes into detail.] | |
ACOS | Arc-cosine. Multiplies the MPAC by 2, takes the arcsine, divides by 2p, and leaves the result in the MPAC. | |
ASIN | Arc-sine. Multiplies the MPAC by 2, takes the arcsine, multiplies by 2p, and leaves the result in the MPAC. | |
AXC | C | Loads the complement of a constant into one of the index registers. [See Note 1 below] |
AXT | C | Loads a constant into one of the index registers. [See Note 1 below] |
BDDV | A | Backwards Double Divide. Divide the double-precision value in X by the MPAC and leave the result in the MPAC. |
BDSU | A | Backwards Double Subtract. Subtracts the MPAC from the double-precision value at X and leaves the result in the MPAC. |
BHIZ | A | Branch High Order Zero. Branch to X if the single-precision value in the MPAC is zero. |
BMN | A | Branch Minus. Branch to X if the triple-precision number in the MPAC is negative. |
BOF | A, A | Branch to Y if switch X is off. |
BOFCLR | A, A | Clear switch X and branch to Y if the switch was initially off. |
BOFINV | A, A | Invert switch X and branch to Y if the switch was originally off. |
BOFSET | A, A | Set switch X and branch to Y if the switch was initially off. |
BON | A, A | Branch to Y if switch X is on. |
BONCLR | A, A | Clear switch X and branch to Y if the switch was initially on. |
BONINV | A, A | Invert switch X and branch to Y if the switch was originally on. |
BONSET | A, A | Set switch X and branch to Y if the switch was initially on. |
BOV | A | Branch on Overflow. If the OVFIND register is not zero, then reset it to zero and branch to X. |
BOVB | A | Brand on Overflow to Basic. If the OVFIND register is not zero, then reset it to zero and call a regular machine language subroutine (as if an RTB had been executed). |
BPL | A | Branch Plus. Branch to X if the triple-precision number in the MPAC is greater than or equal to zero. |
BVSU | A | Backwards Vector Subtract. Subtracts the MPAC from the vector at X and leaves the result in the MPAC. |
BZE | A | Branch Zero. Branch to X if the triple-precision number in the MPAC is zero. |
CALL | A | Calls a subroutine. Transfers to location X, and loads the return address into the QPRET register. |
CCALL | A, A | Computed CALL. Works like CGOTO, but also puts the return address in the QPRET register, like CALL. |
CGOTO | A, A | Computed GOTO. X must point to erasable memory. The value at X is added to Y (which must be in fixed memory), and control transfers there. Like GOTO, if CGOTO occurs as the first opcode in an instruction word, then the second opcode must be blank. |
CLEAR | A | Clear switch X. |
CLRGO | A, A | Clear switch X and branch to location Y. Essentially a CLEAR and GOTO in one instruction. |
COS | Cosine. Multiplies 2p by the value of the MPAC, takes the cosine, multiplies that by 0.5, and leaves the result in the MPAC. | |
DAD | A | Double Add. Adds the double-precision value at X to the MPAC. |
DCOMP | Complement. Replaces the scalar value in the MPAC with its complement. | |
DDV | A | Double Divide. Divide the MPAC by the double-precision value in X. |
DLOAD | A | Load a double-precision value into the MPAC |
DMP | A | Double Multiply. Multiplies the MPAC by the double-precision value at X and leaves the product in the MPAC. |
DMPR | A | Double Multiply and Round. Multiplies the MPAC by the double-precision value at X and leaves the product in the MPAC, rounded to double precision. |
DOT | A | Vector Dot Product. [tl;dr] |
DSQ | Double Square. Squares the value in the MPAC. | |
DSU | A | Double Subtract. Subtracts the double-precision value at X from the MPAC. |
EXIT | Exit the Interpreter and resume executing normal machine code at the next instruction. | |
GOTO | A | Transfer control to a new location. If GOTO occurs in the first opcode of a word, then the 2nd opcode must be blank. Note that a subroutine can return using GOTO if it previously saved the contents of the QPRET register in a memory location. |
INCR | C | Adds a constant Y to one of the index registers. [See Note 1.] |
INVERT | A | Invert (flip) switch X. |
INVGO | A, A | Invert (flip) switch X and branch to location Y. |
LXC | A | Loads one of the index registers with the complement of the contents of erasable location Y. [See Note 1.] |
LXA | A | Loads one of the index registers with the contents of erasable location Y. [See Note 1.] |
MXV | A | Matrix Post-Multiplication by Vector. |
NORM | A | Normalize. The value of the MPAC is shifted left until the value is greater than or equal to 0.5. Memory location X is set to the complement of the number of places the value was shifted left. If the starting value of the MPAC is 0, then -0 is stored in X and the MPAC remains unchanged. |
PDDL | A | Push Down and Double Load. Push the value of the MPAC register onto the stack, and load the MPAC with double-precision value at X. |
PDVL | A | Push Down and Vector Load. Push the value of the MPAC register onto the stack, and load the MPAC with the vector at X. |
PUSH | Push. Pushes the contents of the MPAC onto the stack. | |
ROUND | Rounds the triple-precision value in the MPAC to a double-precision value. | |
RTB | A | Return to Basic. Essentially this instruction allows the interpreted program to call a subroutine outside the Interpreter (i.e. written in normal machine code). X is the address of the subroutine. The subroutine returns to the Interpreter by executing a TC Q. Alternatively, the subroutine can exit by executing TC DANZIG. [I assume DANZIG is some predefined entry point into the Interpreter.] |
RVQ | Return via QPRET. Returns to the location specified in the QPRET register. This is the normal way to return from a subroutine, although if the QPRET register had previously been saved to a memory location, then GOTO can be used instead. | |
SET | A | Set Switch. Sets a switch to 1. |
SETGO | A, A | Sets a switch to 1 and then jumps to address Y. (Essentially a SET and GOTO in one instruction.) |
SETPD | C | Set Push Loc. |
SIGN | A | Sign Test. If the double-precision value at X is negative, then the value in the MPAC is replaced with the MPAC's complement. |
SIN | Sine. Multiplies 2p by the value of the MPAC, takes the sine, multiplies that by 0.5, and leaves the result in the MPAC. | |
SL | C | Shift Left. Shift the MPAC left by the number of places in X. The documentation contains a lengthy discussion of the valid values for X. |
SL1 ... SL4 | Shift Left. Shifts the contents of the MPAC 1 to 4 places left. (There are four separate opcodes here that differ only in how many places the value is shifted.) | |
SL1R ... SL4R | Shift Left and Round. Shifts the contents of the MPAC 1 to 4 places left and rounds. [Not sure what it means to round a number that's shifted left.] (There are four separate opcodes here that differ only in how many places the value is shifted.) | |
SLOAD | A | Load a single-precision value into the MPAC, but sets the MPAC's type to double precision. |
SLR | C | Shift Left and Round. Shift the MPAC left by the number of places in X and rounded. The documentation contains a lengthy discussion of the valid values for X. |
SQRT | Square Root. The contents of the MPAC are replaced by the square root of the MPAC. | |
SR | C | Shift Right. Shift the MPAC right by the number of places in X. The documentation contains a lengthy discussion of the valid values for X. |
SR1 ... SR4 | Shift Right. Shifts the contents of the MPAC 1 to 4 places right. (There are four separate opcodes here that differ only in how many places the value is shifted.) | |
SR1R ... SR4R | Shift Right and Round. Shifts the contents of the MPAC 1 to 4 places right and rounds. (There are four separate opcodes here that differ only in how many places the value is shifted.) | |
SRR | C | Shift Right and Round. Shift the MPAC right by the number of places in X, and rounded. The documentation contains a lengthy discussion of the valid values for X. |
SSP | A | Set Single Precision. Stores a constant Y in single-precision location X. |
STCALL | A, A | Store the MPAC into a memory location X and then call subroutine at location Y. |
STODL | A, A | Store the MPAC to a memory location, and then reload MPAC with a new double-precision value. |
STORE | A | Stores the contents of the MPAC into erasable memory, according to the current type. |
STOVL | A, A | Store the MPAC to a memory location, and then reload MPAC with a new vector value. |
STQ | A | Store the QPRET register in the word at location X. This instruction is used when one subroutine calls another — it gives the subroutine the ability to save the current return address before it gets replaced. |
SXA | A | Stores one of the index registers at location Y. [See Note 1.] |
TAD | A | Triple Add. Adds the trip;e-precision value at X to the MPAC. |
TIX | A | Count and Branch on Index. If subtracting step register X from index register X would yield a positive (non-zero) number, then the subtraction takes place, leaving the result in the index register, and a branch takes place to Y. This instruction enables the creation of a loop counter. [See Note 1.] |
TLOAD | A | Load a triple-precision value into the MPAC |
UNIT | Causes the vector in the MPAC to be replaced by the quotient of the MPAC vector divided by twice the absolute value of the MPAC vector. | |
VAD | A | Vector Add. Adds the vector at X to the MPAC. |
VCOMP | Complement Vector. Replaces the vector value in the MPAC with its complement. | |
VDEF | Vector Define. Somehow takes the double-precision value in the MPAC and converts it into a vector. | |
VDSC | A | Vector Divide by Scalar. |
VLOAD | A | Load a vector into the MPAC |
VPROJ | A | Vector Projection. |
VSL | C | Vector Shift Left. [tl;dr] |
VSL1 ... VSL8 | Vector Shift Left by 1 - 8 places. (There are eight separate opcodes here that differ only in how many places the value is shifted.) | |
VSQ | Vector Square. Squares the vector quantity in the MPAC, replacing it with a double-precision number. [Don't understand what it means to square a vector.] | |
VSR | C | Vector Shift Right. [tl;dr] |
VSR1 ... VSR8 | Vector Shift Right by 1 - 8 places. (There are eight separate opcodes here that differ only in how many places the value is shifted.) | |
VSU | A | Vector Subtract. Subtracts the vector at X from the MPAC and leaves the result in the MPAC. |
VXM | A | Matrix Pre-Multiplication by Vector. |
VXSC | A | Vector Times Scalar. [tl;dr] |
VXV | A | Vector Cross Product. |
XAD | A | Adds the contents of Y to one of the index registers. [See Note 1.] |
XCHX | A | Exchanges one of the index registers with the contents of an erasable memory location. [See Note 1.] |
XSU | A | Subtracts the contents of Y from one of the index registers. [See Note 1.] |
Address |
Luminary |
Colossus |
0 |
Not used. |
Same as Luminary |
1 |
Duplicate of the L register
(unswitched-erasable address 1). |
Same as Luminary |
2 |
Duplicate of the Q register
(unswitched-erasable address 2). |
Same as Luminary |
3 |
A 15-bit 1's-complement
counter called HISCALAR, which is incremented every time
SCALER1 overflows (i.e., every 5.12 seconds). It will
thus overflow and return to 0 after about 23.3 hours. |
|
4 |
A 15-bit 1's-complement
counter called LOSCALAR, which is incremented every 1/3200
second. It will thus overflow every 5.12
seconds. Upon overflow counter SCALER2 is incremented. |
|
5 |
PYJETS: An output
channel used by the reaction control system (RCS) for pitch
control. Only bits 1-8 are used. |
|
6 |
ROLLJETS: An output channel used by the reaction control system (RCS) for roll control. Only bits 1-8 are used. | |
7 |
SUPERBNK: Bit 7 is the
superbank bit (for memory-bank control). Only bits 5-7
are used, and they are used as additional memory-bank
selection bits. However, the only combinations of bits
5-7 which are actually meaningful are 0XX ('X' meaning
"don't care") and 100. In the former case, only memory
banks 00-37 (octal) are accessible, by means of the FB
register. In the latter case, however, banks 30-33 are
replaced by banks 40-43. Banks 34-37 also become
inaccessible. Other bit combinations would have been
meaningful in the SUPERBNK channel if more core-ropes had
been added to the AGC; however, with the available ropes,
setting them simply causes the AGC to not select any rope at
all (see the discussion in the FB register description). |
Same as Luminary. |
Mnemonic |
Octal |
Extracode? |
Address Constraint |
Brief
Description |
---|---|---|---|---|
TC K or TCR K |
00000 + K |
No |
K is 12-bit
address. |
Call
subroutine K. |
XXALQ |
00000 |
No |
Special case of TC K
with K=00000 |
|
XLQ |
00001 |
No |
Special case of TC K with K=00001 | |
RETURN |
00002 |
No |
Special case of TC K with K=00002 | |
RELINT |
00003 |
No |
Special case of TC K with K=00003 | Enable
interrupts. |
INHINT |
00004 |
No |
Special case of TC K with K=00004 | Disable
interrupts. |
EXTEND |
00006 |
No |
Special case of TC K with K=00006 |
Interpret the next
instruction as Extracode. |
CCS K |
10000 + K |
No |
K is 10-bit address. | Count,
compare, and skip. |
TCF K |
10000 + K |
No |
K is 12-bit
address. Two most-significant bits of K not 00. |
Jump to
address K. |
NOOP |
10001 + Current address |
No |
Special case of TCF
K. Used only in fixed memory. |
No-op. |
DAS K |
20001 + K |
No |
K is 10-bit address. |
Double-precision integer addition. |
DDOUBL |
20001 |
No |
Special case of DAS K with K=00000 | Double
the (A,L)
register pair. |
LXCH K |
22000 + K |
No |
K is 10-bit address. |
Exchange contents of L
and K. |
ZL |
22007 |
No |
Special case of LXCH K with K=00006 | |
INCR K |
24000 + K |
No |
K is 10-bit address. | Increment value stored at address K. |
ADS K |
26000 + K |
No |
K is 10-bit address. | Add
contents of A
to value at address K. |
CA K or CAF K (fixed memory) or CAE K (erasable memory) |
30000 + K |
No |
K is 12-bit address. | Copy K to A. |
NOOP |
30000 |
No |
Special case of CA K
with K=00000. Used only in erasable memory. |
No-op. |
CS K |
40000 + K |
No |
K is 12-bit address. | Copy -K to A. |
COM |
40000 |
No |
Special case of CS K with K=00000 | |
INDEX K |
50000 + K |
No |
K is 10-bit address. | Indexes
the next
instruction. (I.e., adds the contents of K to the next
instruction before executing it, but without altering the
memory location at which the next instruction is stored.) |
RESUME |
50017 |
No |
Special case of INDEX K with K=00017 | Resume
interrupted program. (The contents of ZRUPT are loaded
into the program counter, and the contents of BRUPT are executed
as if they were the instruction actually stored at the new
program counter.) |
DXCH K |
52001 + K |
No |
K is 10-bit address. |
Double-precision exchange of the contents of K,K+1 with A,L. |
DTCF |
52005 |
No |
Special case of DXCH K with K=00004 | |
DTCB |
52006 |
No |
Special case of DXCH K with K=00005 | |
TS K |
54000 + K |
No |
K is 10-bit address. | Copy the
contents of A
to location K. |
OVSK |
54000 |
No |
Special case of TS K with K=00000 | |
TCAA |
54005 |
No |
Special case of TS K with K=00005 | |
XCH K |
56000 + K |
No |
K is 10-bit address. |
Exchange the contents of A and location K. |
AD K |
60000 + K |
No |
K is 12-bit address. | Add the
contents of location K
to A. |
DOUBLE |
60000 |
No |
Special case of AD K with K=00000 | Doubles
the A
register. |
MASK K |
70000 + K |
No |
K is 12-bit address. | Bitwise
boolean AND the contents of K to A. |
READ KC |
00000 + KC |
Yes |
KC is 9-bit i/o channel. | Read i/o
channel KC to
A. |
WRITE KC |
01000 + KC |
Yes | KC is 9-bit i/o channel. | Write A to i/o channel KC. |
RAND KC |
02000 + KC |
Yes | KC is 9-bit i/o channel. | Read i/o channel KC and bitwise boolean AND it to A. |
WAND KC |
03000 + KC |
Yes | KC is 9-bit i/o channel. | Read i/o
channel KC and
bitwise boolean AND it to A, then write it to i/o channel KC. |
ROR KC |
04000 + KC |
Yes | KC is 9-bit i/o channel. | Read i/o channel KC and bitwise boolean OR it to A. |
WOR KC |
05000 + KC |
Yes | KC is 9-bit i/o channel. | Read i/o
channel KC and
bitwise boolean OR it to A, then write it to i/o channel KC. |
RXOR KC |
06000 + KC |
Yes | KC is 9-bit i/o channel. | Read i/o channel KC and bitwise boolean exclusive-OR it to A. |
EDRUPT KC |
07000 + KC |
Yes | KC is 9-bit i/o channel. | (For
machine checkout only. I'm not sure what it's supposed
to do.) |
DV K |
10000 + K |
Yes | K is 10-bit address. | Divide
the double-precision integer value in (A,L) by the
contents of K,
putting the quotient in A and the remainder in L. |
BZF K |
10000 + K |
Yes | K is 12-bit
address. Two most-significant bits of K not 00. |
|
MSU K |
20000 + K |
Yes | K is 10-bit address. | |
QXCH K |
22000 + K |
Yes | K is 10-bit address. | |
ZQ |
22007 |
Yes |
Special case of QXCH K with K=00007 | |
AUG K |
24000 + K |
Yes | K is 10-bit address. | |
DIM K |
26000 + K |
Yes | K is 10-bit address. | |
DCA K |
30001 + K |
Yes | K is 12-bit
address. |
|
DCS K |
40001 + K |
Yes | K is 12-bit address. | |
DCOM |
40001 |
Yes |
Special case of DCS K with K=00000 | |
INDEX K |
50000 + K |
Yes | K is 12-bit address. | |
SU K |
60000 + K |
Yes | K is 10-bit address. | |
BZMF K |
60000 + K |
Yes | K is 12-bit
address. Two most-significant bits of K not 00. |
|
MP K |
70000 + K |
Yes | K is 12-bit address. | |
SQUARE |
70000 |
Yes |
Special case of MP K with K=00000 | |
|
Code=0 |
Code=1 |
Code=2 |
Code=3 |
Code=4 |
Code=5 |
Code=6 |
Code=7 |
||
Basic Instructions |
QC=0 |
TC |
CCS |
DAS |
CA |
CS |
INDEX |
AD |
MASK |
|
QC=1 |
TCF |
LXCH |
DXCH |
|||||||
QC=2 |
INCR |
TS |
||||||||
QC=3 |
ADS |
XCH |
||||||||
Extracodes |
QC=0 |
PC=0 |
READ |
DV |
MSU |
DCA |
DCS |
INDEX |
SU |
MP |
PC=1 |
WRITE |
|||||||||
QC=1 |
PC=2 |
RAND |
BZF |
QXCH |
BZMF |
|||||
PC=3 |
WAND |
|||||||||
QC=2 |
PC=4 |
ROR |
AUG |
|||||||
PC=5 |
WOR |
|||||||||
QC=3 |
PC=6 |
RXOR |
DIM |
|||||||
PC=7 |
EDRUPT |
Name |
Timing |
I/O |
Applicable Counters |
Description |
PINC |
1 MCT (about 11.7 µs) | Input to CPU |
TIME1-TIME5 |
Add +1 in 1's-complement
fashion to a counter. If there is overflow, then the
counter is reset to +0. Note that PINCs for
TIME1-TIME5 are triggered by oscillators (or in the case of
TIME2, from overflow of TIME1) and need no external signal. |
PCDU |
1 MCT (about 11.7 µs) | Input to CPU | CDUX, CDUY, CDUZ, OPTX, OPTY |
Add +1 in 2's-complement fashion to a counter. |
MINC |
1 MCT (about 11.7 µs) | Input to CPU | Add -1 in 1's-complement fashion to a counter. If there is overflow, then the counter is reset to -0. | |
MCDU |
1 MCT (about 11.7 µs) | Input to CPU | CDUX, CDUY, CDUZ, OPTX, OPTY | Add -1 in 2's-complement fashion to a counter. |
DINC |
1 MCT (about 11.7 µs) | Input to CPU | TIME6 |
This sequence not only
counts, but also emits a signal to peripheral hardware, as
follows:
|
SHINC |
1 MCT (about 11.7 µs) | Input to CPU | INLINK, RNRAD, OUTLINK |
Shift the counter left.
If there is overflow, then set an
interrupt request, presumably for the UPRUPT,
RADAR RUPT, or DOWNRUPT interrupt (whichever is
appropriate). This is used for accumulating a
0-bit from a serial-data stream into a parallel word of
data. |
SHANC |
1 MCT (about 11.7 µs) | Input to CPU | INLINK, RNRAD, OUTLINK | Shift the counter left and increment by +1. If there is overflow, then set an interrupt request, presumably for the UPRUPT, RADAR RUPT, or DOWNRUPT interrupt (whichever is appropriate). This is used for accumulating a 1-bit from a serial-data stream into a parallel word of data. |
INOTRD |
1 MCT (about 11.7 µs) | Input to CPU | None |
|
INOTLD |
1 MCT (about 11.7 µs) | Input to CPU | None |
|
FETCH |
2 MCT (about 23.4 µs) | Input to CPU | None |
|
STORE |
2 MCT (about 23.4 µs) | Input to CPU | None |
|
GOJ |
2 MCT (about 23.4 µs) | Input to CPU | None |
Jump to location 04000 octal. This sequence is used to force a reset of the AGC. Additionally, the CPU's internal flip-flop indicating that an ISR is in progress is reset (as if a RESUME instruction had been executed), since otherwise interrupts would be permanently inhibited if the GOJ had occurred during an ISR. |
TCSAJ |
2 MCT (about 23.4 µs) | Input to CPU | None |
|
POUT |
n/a |
Output from CPU |
TIME6 |
Indicates that the result of
a DINC
unprogrammed sequence is positive. |
MOUT |
n/a |
Output from CPU |
TIME6 |
Indicates that the result of a DINC unprogrammed sequence is negative. |
ZOUT |
n/a |
Output from CPU |
TIME6 |
Indicates that the result of
a DINC
unprogrammed sequence is plus zero or minus zero. |