SEQ.h
/****************************************************************************
* SEQ - SEQUENCE GENERATOR subsystem
*
* AUTHOR: John Pultorak
* DATE: 9/22/01
* FILE: SEQ.h
*
* VERSIONS:
*
* DESCRIPTION:
* Sequence Generator for the Block 1 Apollo Guidance Computer prototype (AGC4).
*
* SOURCES:
* Mostly based on information from "Logical Description for the Apollo
* Guidance Computer (AGC4)", Albert Hopkins, Ramon Alonso, and Hugh
* Blair-Smith, R-393, MIT Instrumentation Laboratory, 1963.
*
* NOTES:
*
*****************************************************************************
*/
#ifndef SEQ_H
#define SEQ_H
#include "reg.h"
#define MAXPULSES 15
#define MAX_IPULSES 5 // no more than 5 instruction-generated pulses active at any time
enum cpType
{ // **inferred; not defined in orignal R393 AGC4 spec.
NO_PULSE = 0,
// OUTPUTS FROM SUBSYSTEM A
CI = 1, // Carry in
CLG = 2, // Clear G
CLCTR = 3, // Clear loop counter
CTR = 4, // Loop counter
GP = 5, // Generate Parity
KRPT = 6, // Knock down Rupt priority
NISQ = 7, // New instruction to the SQ register
RA = 8, // Read A
RB = 9, // Read B
RB14 = 10, // Read bit 14
RC = 11, // Read C
RG = 12, // Read G
RLP = 13, // Read LP
RP2 = 14, // Read parity 2
RQ = 15, // Read Q
RRPA = 16, // Read RUPT address
RSB = 17, // Read sign bit
RSCT = 18, // Read selected counter address
RU = 19, // Read sum
RZ = 20, // Read Z
R1 = 21, // Read 1
R1C = 22, // Read 1 complimented
R2 = 23, // Read 2
R22 = 24, // Read 22
R24 = 25, // Read 24
ST1 = 26, // Stage 1
ST2 = 27, // Stage 2
TMZ = 28, // Test for minus zero
TOV = 29, // Test for overflow
TP = 30, // Test parity
TRSM = 31, // Test for resume
TSGN = 32, // Test sign
TSGN2 = 33, // Test sign 2
WA = 34, // Write A
WALP = 35, // Write A and LP
WB = 36, // Write B
WGx = 37, // Write G (do not reset)
WLP = 38, // Write LP
WOVC = 39, // Write overflow counter
WOVI = 40, // Write overflow RUPT inhibit
WOVR = 41, // Write overflow
WP = 42, // Write P
WPx = 43, // Write P (do not reset)
WP2 = 44, // Write P2
WQ = 45, // Write Q
WS = 46, // Write S
WX = 47, // Write X
WY = 48, // Write Y
WYx = 49, // Write Y (do not reset)
WZ = 50, // Write Z
// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM B ONLY;
// NOT USED OUTSIDE CPM
RSC = 51, // Read special and central (output to B only, not outside CPM)
WSC = 52, // Write special and central (output to B only, not outside CPM)
WG = 53, // Write G (output to B only, not outside CPM)
// OUTPUTS FROM SUBSYSTEM A; USED AS INPUTS TO SUBSYSTEM C ONLY;
// NOT USED OUTSIDE CPM
SDV1 = 54, // Subsequence DV1 is currently active
SMP1 = 55, // Subsequence MP1 is currently active
SRSM3 = 56, // Subsequence RSM3 is currently active
// EXTERNAL OUTPUTS FROM SUBSYSTEM B
//
RA0 = 57, // Read register at address 0 (A)
RA1 = 58, // Read register at address 1 (Q)
RA2 = 59, // Read register at address 2 (Z)
RA3 = 60, // Read register at address 3 (LP)
RA4 = 61, // Read register at address 4
RA5 = 62, // Read register at address 5
RA6 = 63, // Read register at address 6
RA7 = 64, // Read register at address 7
RA10 = 65, // Read register at address 10 (octal)
RA11 = 66, // Read register at address 11 (octal)
RA12 = 67, // Read register at address 12 (octal)
RA13 = 68, // Read register at address 13 (octal)
RA14 = 69, // Read register at address 14 (octal)
RBK = 70, // Read BNK
WA0 = 71, // Write register at address 0 (A)
WA1 = 72, // Write register at address 1 (Q)
WA2 = 73, // Write register at address 2 (Z)
WA3 = 74, // Write register at address 3 (LP)
WA10 = 75, // Write register at address 10 (octal)
WA11 = 76, // Write register at address 11 (octal)
WA12 = 77, // Write register at address 12 (octal)
WA13 = 78, // Write register at address 13 (octal)
WA14 = 79, // Write register at address 14 (octal)
WBK = 80, // Write BNK
WGn = 81, // Write G (normal gates)**
W20 = 82, // Write into CYR
W21 = 83, // Write into SR
W22 = 84, // Write into CYL
W23 = 85, // Write into SL
// THESE ARE THE LEFTOVERS -- THEY'RE PROBABLY USED IN SUBSYSTEM C
//
GENRST = 86, // General Reset**
CLINH = 87, // Clear INHINT**
CLINH1 = 88, // Clear INHINT1**
CLSTA = 89, // Clear state counter A (STA)**
CLSTB = 90, // Clear state counter B (STB)**
CLISQ = 91, // Clear SNI**
CLRP = 92, // Clear RPCELL**
INH = 93, // Set INHINT**
RPT = 94, // Read RUPT opcode **
SBWG = 95, // Write G from memory
SETSTB = 96, // Set the ST1 bit of STB
WE = 97, // Write E-MEM from G
WPCTR = 98, // Write PCTR (latch priority counter sequence)**
WSQ = 99, // Write SQ
WSTB = 100, // Write stage counter B (STB)**
R2000 = 101, // Read 2000 **
};
// INSTRUCTIONS
// Op Codes, as they appear in the SQ register.
enum instruction
{
// The code in the SQ register is the same as the op code for these
// four instructions.
TC = 00, // 00 TC K Transfer Control 1 MCT
CCS = 01, // 01 CCS K Count, Compare, and Skip 2 MCT
INDEX = 02, // 02 INDEX K 2 MCT
XCH = 03, // 03 XCH K Exchange 2 MCT
// The SQ register code is the op code + 010 (octal). This happens because all
// of these instructions have bit 15 set (the sign (SG) bit) while in memory. When the
// instruction is copied from memory to the memory buffer register (G) to register
// B, the SG bit moves from bit 15 to bit 16 and the sign is copied back into bit
// 15 (US). Therefore, the CS op code (04) becomes (14), and so on.
CS = 014, // 04 CS K Clear and Subtract 2 MCT
TS = 015, // 05 TS K Transfer to Storage 2 MCT
AD = 016, // 06 AD K Add 2 or 3 MCT
MASK = 017, // 07 MASK K Bitwise AND 2 MCT
// These are extended instructions. They are accessed by executing an INDEX 5777
// before each instruction. By convention, address 5777 contains 47777. The INDEX
// instruction adds 47777 to the extended instruction to form the SQ op code. For
// example, the INDEX adds 4 to the 4 op code for MP to produce the 11 (octal; the
// addition generates an end-around-carry). SQ register code (the 7777 part is a
// negative zero).
MP = 011, // 04 MP K Multiply 10 MCT
DV = 012, // 05 DV K Divide 18 MCT
SU = 013, // 06 SU K Subtract 4 or 5 MCT
};
enum subseq
{
TC0 = 0,
CCS0 = 1,
CCS1 = 2,
NDX0 = 3,
NDX1 = 4,
RSM3 = 5,
XCH0 = 6,
CS0 = 7,
TS0 = 8,
AD0 = 9,
MASK0 = 10,
MP0 = 11,
MP1 = 12,
MP3 = 13,
DV0 = 14,
DV1 = 15,
SU0 = 16,
RUPT1 = 17,
RUPT3 = 18,
STD2 = 19,
PINC0 = 20,
MINC0 = 21,
SHINC0 = 22,
NO_SEQ = 23
};
enum scType
{ // identifies subsequence for a given instruction
SUB0 = 0, // ST2=0, ST1=0
SUB1 = 1, // ST2=0, ST1=1
SUB2 = 2, // ST2=1, ST1=0
SUB3 = 3 // ST2=1, ST1=1
};
enum brType
{
BR00 = 0, // BR1=0, BR2=0
BR01 = 1, // BR1=0, BR2=1
BR10 = 2, // BR1=1, BR2=0
BR11 = 3, // BR1=1, BR2=1
NO_BR = 4 // NO BRANCH
};
const int GOPROG = 02000; // bottom address of fixed memory
class regSQ : public reg
{
public:
regSQ() :
reg(4, "%02o")
{
}
};
class regSTA : public reg
{
public:
regSTA() :
reg(2, "%01o")
{
}
};
class regSTB : public reg
{
public:
regSTB() :
reg(2, "%01o")
{
}
};
class regBR1 : public reg
{
public:
regBR1() :
reg(1, "%01o")
{
}
};
class regBR2 : public reg
{
public:
regBR2() :
reg(1, "%01o")
{
}
};
class regCTR : public reg
{
public:
regCTR() :
reg(3, "%01o")
{
}
};
class regSNI : public reg
{
public:
regSNI() :
reg(1, "%01o")
{
}
};
class SEQ
{
public:
static void
execWP_GENRST();
static void
execWP_WSQ();
static void
execWP_NISQ();
static void
execWP_CLISQ();
static void
execWP_ST1();
static void
execWP_ST2();
static void
execWP_TRSM();
static void
execWP_CLSTA();
static void
execWP_WSTB();
static void
execWP_CLSTB();
static void
execWP_SETSTB();
static void
execWP_TSGN();
static void
execWP_TOV();
static void
execWP_TMZ();
static void
execWP_TSGN2();
static void
execWP_CTR();
static void
execWP_CLCTR();
static regSNI register_SNI; // select next intruction flag
static cpType glbl_cp[MAXPULSES]; // current set of asserted control pulses (MAXPULSES)
static char* cpTypeString[];
// Test the currently asserted control pulses; return true if the specified
// control pulse is active.
static bool
isAsserted(cpType pulse);
// Return a string containing the names of all asserted control pulses.
static char*
getControlPulses();
static subseq glbl_subseq; // currently decoded instruction subsequence
static regSQ register_SQ; // instruction register
static regSTA register_STA; // stage counter A
static regSTB register_STB; // stage counter B
static regBR1 register_BR1; // branch register1
static regBR2 register_BR2; // branch register2
static regCTR register_LOOPCTR; // loop counter
static char* instructionString[];
};
#endif