*-----------------------------------------------------------
Title[A-Group.mc...July 6, 1980 5:15 PM...Taft];
*-----------------------------------------------------------

* The IFU dispatches to separate entry points for each combination of
* source AC and ALU operation, and provides N = destination AC, and
* provides the low-order instruction byte as 2 nibbles (packed-Alpha).
* Timing (cycles):
*
9
*
+1 if L, R, or S shift
*
+1 if L or R shift and the ALU operation generates a carry
*
+ a value taken from the following table:

*
NL = 0NL = 1
*
Doesn’t skipSkipsDoesn’t skipSkips
* None
1--0--
* SKP
--6--6
* SZC, SNC
1717
* SZR, SNR
1716
* SEZ, SBN
2827

* Worst case is 19, and average for instructions actually used in
* Bcpl programs is about 13.

KnowRBase[AEmRegs];
TopLevel;

COM0:
T← ID, StkP← spAC0, Branch[COMxx];
COM1:
T← ID, StkP← spAC1, Branch[COMxx];
COM2:
T← ID, StkP← spAC2, Branch[COMxx];
COM3:
T← ID, StkP← spAC3, Branch[COMxx];

COMxx:
Q← Stack, Call[SetupA];
ETemp← NOT Q, Branch[AGrpNN];

EmIFUArith[200, COM0, nspAC0];
EmIFUArith[210, COM0, nspAC1];
EmIFUArith[220, COM0, nspAC2];
EmIFUArith[230, COM0, nspAC3];
EmIFUArith[240, COM1, nspAC0];
EmIFUArith[250, COM1, nspAC1];
EmIFUArith[260, COM1, nspAC2];
EmIFUArith[270, COM1, nspAC3];
EmIFUArith[300, COM2, nspAC0];
EmIFUArith[310, COM2, nspAC1];
EmIFUArith[320, COM2, nspAC2];
EmIFUArith[330, COM2, nspAC3];
EmIFUArith[340, COM3, nspAC0];
EmIFUArith[350, COM3, nspAC1];
EmIFUArith[360, COM3, nspAC2];
EmIFUArith[370, COM3, nspAC3];


NEG0:
T← ID, StkP← spAC0, Branch[NEGxx];
NEG1:
T← ID, StkP← spAC1, Branch[NEGxx];
NEG2:
T← ID, StkP← spAC2, Branch[NEGxx];
NEG3:
T← ID, StkP← spAC3, Branch[NEGxx];

NEGxx:
Q← Stack, Call[SetupA];
ETemp← (0S)-Q, Branch[AGrpNN];

EmIFUArith[201, NEG0, nspAC0];
EmIFUArith[211, NEG0, nspAC1];
EmIFUArith[221, NEG0, nspAC2];
EmIFUArith[231, NEG0, nspAC3];
EmIFUArith[241, NEG1, nspAC0];
EmIFUArith[251, NEG1, nspAC1];
EmIFUArith[261, NEG1, nspAC2];
EmIFUArith[271, NEG1, nspAC3];
EmIFUArith[301, NEG2, nspAC0];
EmIFUArith[311, NEG2, nspAC1];
EmIFUArith[321, NEG2, nspAC2];
EmIFUArith[331, NEG2, nspAC3];
EmIFUArith[341, NEG3, nspAC0];
EmIFUArith[351, NEG3, nspAC1];
EmIFUArith[361, NEG3, nspAC2];
EmIFUArith[371, NEG3, nspAC3];

MOV0:
T← ID, StkP← spAC0, Branch[MOVxx];
MOV1:
T← ID, StkP← spAC1, Branch[MOVxx];
MOV2:
T← ID, StkP← spAC2, Branch[MOVxx];
MOV3:
T← ID, StkP← spAC3, Branch[MOVxx];

MOVxx:
Q← Stack, Call[SetupA];
ETemp← Q, Branch[AGrpNN];

EmIFUArith[202, MOV0, nspAC0];
EmIFUArith[212, MOV0, nspAC1];
EmIFUArith[222, MOV0, nspAC2];
EmIFUArith[232, MOV0, nspAC3];
EmIFUArith[242, MOV1, nspAC0];
EmIFUArith[252, MOV1, nspAC1];
EmIFUArith[262, MOV1, nspAC2];
EmIFUArith[272, MOV1, nspAC3];
EmIFUArith[302, MOV2, nspAC0];
EmIFUArith[312, MOV2, nspAC1];
EmIFUArith[322, MOV2, nspAC2];
EmIFUArith[332, MOV2, nspAC3];
EmIFUArith[342, MOV3, nspAC0];
EmIFUArith[352, MOV3, nspAC1];
EmIFUArith[362, MOV3, nspAC2];
EmIFUArith[372, MOV3, nspAC3];


INC0:
T← ID, StkP← spAC0, Branch[INCxx];
INC1:
T← ID, StkP← spAC1, Branch[INCxx];
INC2:
T← ID, StkP← spAC2, Branch[INCxx];
INC3:
T← ID, StkP← spAC3, Branch[INCxx];

INCxx:
Q← Stack, Call[SetupA];
ETemp← Q+1, Branch[AGrpNN];

EmIFUArith[203, INC0, nspAC0];
EmIFUArith[213, INC0, nspAC1];
EmIFUArith[223, INC0, nspAC2];
EmIFUArith[233, INC0, nspAC3];
EmIFUArith[243, INC1, nspAC0];
EmIFUArith[253, INC1, nspAC1];
EmIFUArith[263, INC1, nspAC2];
EmIFUArith[273, INC1, nspAC3];
EmIFUArith[303, INC2, nspAC0];
EmIFUArith[313, INC2, nspAC1];
EmIFUArith[323, INC2, nspAC2];
EmIFUArith[333, INC2, nspAC3];
EmIFUArith[343, INC3, nspAC0];
EmIFUArith[353, INC3, nspAC1];
EmIFUArith[363, INC3, nspAC2];
EmIFUArith[373, INC3, nspAC3];

ADC0:
T← ID, StkP← spAC0, Branch[ADCxx];
ADC1:
T← ID, StkP← spAC1, Branch[ADCxx];
ADC2:
T← ID, StkP← spAC2, Branch[ADCxx];
ADC3:
T← ID, StkP← spAC3, Branch[ADCxx];

ADCxx:
Q← Stack, Call[SetupA];
ETemp← (Stack)-Q-1, Branch[AGrpNN];

EmIFUArith[204, ADC0, nspAC0];
EmIFUArith[214, ADC0, nspAC1];
EmIFUArith[224, ADC0, nspAC2];
EmIFUArith[234, ADC0, nspAC3];
EmIFUArith[244, ADC1, nspAC0];
EmIFUArith[254, ADC1, nspAC1];
EmIFUArith[264, ADC1, nspAC2];
EmIFUArith[274, ADC1, nspAC3];
EmIFUArith[304, ADC2, nspAC0];
EmIFUArith[314, ADC2, nspAC1];
EmIFUArith[324, ADC2, nspAC2];
EmIFUArith[334, ADC2, nspAC3];
EmIFUArith[344, ADC3, nspAC0];
EmIFUArith[354, ADC3, nspAC1];
EmIFUArith[364, ADC3, nspAC2];
EmIFUArith[374, ADC3, nspAC3];


SUB0:
T← ID, StkP← spAC0, Branch[SUBxx];
SUB1:
T← ID, StkP← spAC1, Branch[SUBxx];
SUB2:
T← ID, StkP← spAC2, Branch[SUBxx];
SUB3:
T← ID, StkP← spAC3, Branch[SUBxx];

SUBxx:
Q← Stack, Call[SetupA];
ETemp← (Stack)-Q, Branch[AGrpNN];

EmIFUArith[205, SUB0, nspAC0];
EmIFUArith[215, SUB0, nspAC1];
EmIFUArith[225, SUB0, nspAC2];
EmIFUArith[235, SUB0, nspAC3];
EmIFUArith[245, SUB1, nspAC0];
EmIFUArith[255, SUB1, nspAC1];
EmIFUArith[265, SUB1, nspAC2];
EmIFUArith[275, SUB1, nspAC3];
EmIFUArith[305, SUB2, nspAC0];
EmIFUArith[315, SUB2, nspAC1];
EmIFUArith[325, SUB2, nspAC2];
EmIFUArith[335, SUB2, nspAC3];
EmIFUArith[345, SUB3, nspAC0];
EmIFUArith[355, SUB3, nspAC1];
EmIFUArith[365, SUB3, nspAC2];
EmIFUArith[375, SUB3, nspAC3];

ADD0:
T← ID, StkP← spAC0, Branch[ADDxx];
ADD1:
T← ID, StkP← spAC1, Branch[ADDxx];
ADD2:
T← ID, StkP← spAC2, Branch[ADDxx];
ADD3:
T← ID, StkP← spAC3, Branch[ADDxx];

ADDxx:
Q← Stack, Call[SetupA];
ETemp← (Stack)+Q, Branch[AGrpNN];

EmIFUArith[206, ADD0, nspAC0];
EmIFUArith[216, ADD0, nspAC1];
EmIFUArith[226, ADD0, nspAC2];
EmIFUArith[236, ADD0, nspAC3];
EmIFUArith[246, ADD1, nspAC0];
EmIFUArith[256, ADD1, nspAC1];
EmIFUArith[266, ADD1, nspAC2];
EmIFUArith[276, ADD1, nspAC3];
EmIFUArith[306, ADD2, nspAC0];
EmIFUArith[316, ADD2, nspAC1];
EmIFUArith[326, ADD2, nspAC2];
EmIFUArith[336, ADD2, nspAC3];
EmIFUArith[346, ADD3, nspAC0];
EmIFUArith[356, ADD3, nspAC1];
EmIFUArith[366, ADD3, nspAC2];
EmIFUArith[376, ADD3, nspAC3];


AND0:
T← ID, StkP← spAC0, Branch[ANDxx];
AND1:
T← ID, StkP← spAC1, Branch[ANDxx];
AND2:
T← ID, StkP← spAC2, Branch[ANDxx];
AND3:
T← ID, StkP← spAC3, Branch[ANDxx];

ANDxx:
Q← Stack, Call[SetupA];
ETemp← (Stack) AND Q, Branch[AGrpNN];

EmIFUArith[207, AND0, nspAC0];
EmIFUArith[217, AND0, nspAC1];
EmIFUArith[227, AND0, nspAC2];
EmIFUArith[237, AND0, nspAC3];
EmIFUArith[247, AND1, nspAC0];
EmIFUArith[257, AND1, nspAC1];
EmIFUArith[267, AND1, nspAC2];
EmIFUArith[277, AND1, nspAC3];
EmIFUArith[307, AND2, nspAC0];
EmIFUArith[317, AND2, nspAC1];
EmIFUArith[327, AND2, nspAC2];
EmIFUArith[337, AND2, nspAC3];
EmIFUArith[347, AND3, nspAC0];
EmIFUArith[357, AND3, nspAC1];
EmIFUArith[367, AND3, nspAC2];
EmIFUArith[377, AND3, nspAC3];

* Common code for ALU-class instructions

*-----------------------------------------------------------
SetupA:
* Subroutine called to set up for ALU-class instructions.
* Expects T = destination AC number.
* Returns with a dispatch pending on the high-order 4 bits of alpha
* (Shift and Carry) and with ETemp1 = the low-order 4 bits (NL and Skip).
* Note: BigBDispatch is done peculiarly because assembler doesn’t permit
* BigBDispatch in subroutines--but it’s really OK in conjunction with Return.
*-----------------------------------------------------------
Subroutine;

T← ID, StkP← T, Global;* ID = Shift and Carry fields
ETemp1← ID, B← T, FF64[70], Return; * ID = NL and Skip fields

TopLevel;

*-----------------------------------------------------------
* Dispatch to one of the following immediately after executing the
* ALU operation.
* Note that if a logical operation was executed, the Carry branch condition
* will now be false, because the first instruction of SetupA executed
* ALU← A (arithmetic, thereby resetting Carry) and subsequent instructions
* all executed logical ALU operations which do not affect Carry.
AGrpNN:
T← CRY, DblBranch[DoCryN, NoCryN, Carry], DispTable[20], Global;
AGrpZN:
T← A0, DblBranch[DoCryN, NoCryN, Carry];
AGrpON:
T← T-T-1, DblBranch[DoCryN, NoCryN, Carry];
AGrpCN:
T← NOT(CRY), DblBranch[DoCryN, NoCryN, Carry];
AGrpNL:
T← CRY, DblBranch[DoCryL, NoCryL, Carry];
AGrpZL:
T← A0, DblBranch[DoCryL, NoCryL, Carry];
AGrpOL:
T← T-T-1, DblBranch[DoCryL, NoCryL, Carry];
AGrpCL:
T← NOT(CRY), DblBranch[DoCryL, NoCryL, Carry];
AGrpNR:
T← CRY, DblBranch[DoCryR, NoCryR, Carry];
AGrpZR:
T← A0, DblBranch[DoCryR, NoCryR, Carry];
AGrpOR:
T← T-T-1, DblBranch[DoCryR, NoCryR, Carry];
AGrpCR:
T← NOT(CRY), DblBranch[DoCryR, NoCryR, Carry];
AGrpNS:
T← CRY, DblBranch[DoCryS, NoCryS, Carry];
AGrpZS:
T← A0, DblBranch[DoCryS, NoCryS, Carry];
AGrpOS:
T← T-T-1, DblBranch[DoCryS, NoCryS, Carry];
AGrpCS:
T← NOT(CRY), DblBranch[DoCryS, NoCryS, Carry];
*-----------------------------------------------------------

* Shift the result appropriately, and compute a new carry for L or R shift.
* Put the word result in ETemp and the carry in ETemp1.

* Swap bytes
NoCryS:
ETemp← LCY[ETemp, ETemp, 10], Branch[NoCryN];
DoCryS:
ETemp← LCY[ETemp, ETemp, 10], Branch[DoCryN];

* Left shift
NoCryL:
ETemp← LCY[T, ETemp, 1], DblBranch[NewCy1, NewCy0, R<0];
DoCryL:
T← NOT T, Branch[NoCryL];

* Right shift
NoCryR:
ETemp← RCY[T, ETemp, 1], DblBranch[NewCy1, NewCy0, R odd];
DoCryR:
T← NOT T, Branch[NoCryR];

NewCy0:
ETemp1← A0, BigBDispatch← ETemp1, Branch[LoadX];
NewCy1:
ETemp1← (ETemp1)-(BigBDispatch← ETemp1)-1, Branch[LoadX];

* No shift
NoCryN:
ETemp1← T, BigBDispatch← ETemp1, Branch[LoadX];
DoCryN:
ETemp1← NOT T, BigBDispatch← ETemp1, Branch[LoadX];

* Common code for ALU-class instructions (cont’d)

* ETemp now has the word result, and ETemp1 the carry bit result.
* A 20-way branch is pending on the NL and Skip fields of the instruction.
* Note: the ←MD is to force any memory reference to complete (and possibly
* fault) -- must do this before changing any permanent state.

LoadX:
T← MD, PD← Q← ETemp, Branch[LNSK];

*-----------------------------------------------------------
* Load the results and test the skip condition.
LNSK:
CRY← ETemp1, Branch[LNSK1], DispTable[20], Global;
LSKP:
T← (RR3)-(PCX’), Branch[LSKPX];
LSZC:
CRY← ETemp1, DblBranch[LSKP1C, LNSK1C, R even];
LSNC:
CRY← ETemp1, DblBranch[LSKP1, LNSK1, R odd];
LSZR:
CRY← ETemp1, DblBranch[LSKP1, LNSK1, ALU=0];
LSNR:
CRY← ETemp1, DblBranch[LSKP1C, LNSK1C, ALU#0];
LSEZ:
PD← (ETemp1) AND Q, Branch[LSZR];
LSBN:
PD← (ETemp1) AND Q, Branch[LSNR];

* Don’t load the results, just test the skip condition.
NSK:
IFUJump[0];
SKP:
T← (RR3)-(PCX’), Branch[SKP1];
SZC:
ETemp1, DblBranch[SKPC, NSKC, R even];
SNC:
ETemp1, DblBranch[SKP, NSK, R odd];
SZR:
T← (RR3)-(PCX’), DblBranch[SKP1, NSK1, ALU=0];
SNR:
T← (RR3)-(PCX’), DblBranch[SKP1C, NSK1C, ALU#0];
SEZ:
PD← (ETemp1) AND Q, Branch[SZR];
SBN:
PD← (ETemp1) AND Q, Branch[SNR];
*-----------------------------------------------------------

* Tails of skip tests
LSKPX:
PCF← T, Branch[LNSK];

LNSK1:
Stack← Q, IFUJump[0];
LSKP1:
T← (RR3)-(PCX’), Branch[LSKPX];

LNSK1C:
Stack← Q, IFUJump[0];
LSKP1C:
T← (RR3)-(PCX’), Branch[LSKPX];

NSKC:
IFUJump[0];
SKPC:
T← (RR3)-(PCX’), Branch[SKP1];

NSK1:
IFUJump[0];
SKP1:
PCF← T, Branch[SKPX2];

NSK1C:
IFUJump[0];
SKP1C:
PCF← T;
SKPX2:
Branch[NSK];