GenArith.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Edward Fiala February 10, 1986 6:46:47 pm PST
This diagnostic tests the arithmetic opcodes RVADD, RVSUB, RUADD, RUSUB, RADD, RSUB, ADD, SUB, ADDB, SUBB, ADDDB, and SUBDB. When correctly executed it terminates with a HALT[177777b] at PC = 4034150B on instruction 2876 cycle 6156.
DIRECTORY
DragOpsCross USING [XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Word],
--XopBase, TrapBase, TrapWidthBytes, Inst, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, Word, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, TrapWidthWords, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuXBus, ifuStatus, ifuSLimit, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, IFUStatusRec, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest
DragOpsCrossUtils USING [IntToWord],
--BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, StatusToWord, WordToStatus, BytesToWord, BytesToHalf, WordToBytes, HalfToBytes, HalvesToWord, WordToHalves, HighHalf, LowHalf, LeftHalf, RightHalf, SwapHalves, WordToInt, IntToWord, WordToCard, HalfToCard, ByteToCard, CardToWord, CardToHalf, CardToByte, DragAnd, DragOr, DragXor, DragNot, VanillaAdd, VanillaSub, AddDelta, HalfNot, HalfAnd, HalfOr, HalfXor, HalfShift, DoubleWordShiftLeft, SingleWordShiftLeft, SingleWordShiftRight, TrapIndexToBytePC, XopToBytePC
HandCoding, --Has opcode and register defs.
HandCodingPseudos, --GenLabel, GenLabelHere, SetLabel, Halt, Pause, MakeLabelGlobal, UseLabel8B, UseLabel16, UseLabel32, ProcedureEntry, ProcedureExit, EnableTraps, IndexedJump, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, DisableTraps, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetL, SetL, GetYoungestPC, GetYoungestL, GetEldestPC, GetEldestL, SetYoungestPC, SetYoungestL, SetEldestPC, SetEldestL
HandCodingSupport; --Area, GetCurrentArea, ReserveData, SetOutputPC, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetOutputPC, WordAlign, OutputByte, OutputOneByte, OutputAlphaBeta, OutputAlphaBetaGammaDelta, OutputWord
GenArith: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport;
Word: TYPE = DragOpsCross.Word;
In this diagnostic, the auxiliary registers are called aux0, aux1, ..., aux15; the locals are called reg0, reg1, ..., reg15; and the constants are called const0, const1, ..., const11. Usage of the constants in this diagnostic is as follows:
const2 contains -1.
const3 is used as an "expected" flag by the integer overflow trap subroutine.
const4 is used as a smashable temporary.
const5 is used as a smashable temporary.
const6 contains the constant 4 for the integer overflow trap.
aux0: AuxRegSpec = [aux[0]];
aux1: AuxRegSpec = [aux[1]];
aux2: AuxRegSpec = [aux[2]];
aux3: AuxRegSpec = [aux[3]];
aux4: AuxRegSpec = [aux[4]];
aux5: AuxRegSpec = [aux[5]];
aux6: AuxRegSpec = [aux[6]];
aux14: AuxRegSpec = [aux[14]];
aux15: AuxRegSpec = [aux[15]];
const5: ConstSpec = [const[5]];
const6: ConstSpec = [const[6]];
const7: ConstSpec = [const[7]];
const8: ConstSpec = [const[8]];
const9: ConstSpec = [const[9]];
const10: ConstSpec = [const[10]];
const11: ConstSpec = [const[11]];
All: PROC = {
The Xop trap locations assigned to each opcode are at at opcode*TrapWidthBytes + xopBase*bytesPerWord = 4,000,000B + 20B * opcode, and the trap location assigned to each trap are at TrapIndex*TrapWidthBytes + TrapBase*bytesPerWord = 4,002,000B + 20B * TrapIndex. The TrapIndex definitions are in DragOpsCross.
FillXop: PROC [inst: CARDINAL, dest: Label] = {
SetOutputPC[inst * DragOpsCross.TrapWidthBytes + DragOpsCross.XopBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
FillTrap: PROC [tx: DragOpsCross.TrapIndex, dest: Label] = {
SetOutputPC[LOOPHOLE[tx, CARDINAL] * DragOpsCross.TrapWidthBytes + DragOpsCross.TrapBase * DragOpsCross.bytesPerWord];
drJDB[UseLabel16[dest]];
};
area: Area = GetCurrentArea[];
savePC: LONG CARDINAL;
start: Label = GenLabel[];
dummy: Label = GenLabel[];
ALUOverflow: Label = GenLabel[];
ALUOvfUnexpected: Label = GenLabel[];
enterRUADDTest: Label = GenLabel[];
enterRUSUBTest: Label = GenLabel[];
enterRVADDTest: Label = GenLabel[];
enterRVSUBTest: Label = GenLabel[];
enterRADDTest: Label = GenLabel[];
enterRSUBTest: Label = GenLabel[];
enterADDTest: Label = GenLabel[];
enterSUBTest: Label = GenLabel[];
enterADDBTest: Label = GenLabel[];
enterSUBBTest: Label = GenLabel[];
enterADDDBTest: Label = GenLabel[];
enterSUBDBTest: Label = GenLabel[];
enterQADDTest: Label = GenLabel[];
enterQSUBTest: Label = GenLabel[];
Executes 47x12 + 4x14 + 2 = 622 instructions.
GenRUADD: PROC = {
Test RUADD on a+b+Carry0 and several other cases. Executes 12 or 14 instructions.
RUADDTest: PROC [a, b, apbc: INT] ~ {
okRUADD: Label = GenLabel[];
badRUADD: Label = GenLabel[];
drLIQB[IntToWord[a]]; drLIQB[IntToWord[b]];
drRUADD[pushDst, reg0, reg1]; drLIQB[IntToWord[a + b]];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRUADD]]; SetLabel[badRUADD]; Pause[]; SetLabel[okRUADD];
If RUADD carry-out was wrong, then RUADD below will wind up 1 off.
IF apbc = 1 THEN {
drRUADD[pushDst, reg0, const2]; -- a+(-1)+Carry1 has result = a, Carry ← 1
drRJNEB[popSrc, reg0, UseLabel8B[badRUADD]];
If RUADD carry-out was mistakenly 0, then RUADD below will wind up 1 too small.
drRUADD[pushDst, const2, reg1]; -- -1+b+Carry1 has result = b, Carry ← 1
drRJNEB[popSrc, reg1, UseLabel8B[badRUADD]];
If RUADD carry-out was mistakenly 0, then RUADD below will wind up 1 too small.
drRUADD[belowDst, const0, belowSrcPop]; -- 0+a+Carry1 has result = a+1, Carry ← 0
drLIQB[IntToWord[a+1]]; drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRUADD]];
}
ELSE {
drRUADD[pushDst, reg0, const0]; --a+0+Carry0 has result = a, Carry ← 0
drRJNEB[popSrc, reg0, UseLabel8B[badRUADD]];
If RUADD carry-out was mistakenly 1, then RUADD below will wind up 1 too large.
drRUADD[pushDst, const0, reg1]; -- 0+b+Carry0 has result = b, Carry ← 0
drRJNEB[popSrc, reg1, UseLabel8B[badRUADD]];
If RUADD carry-out was mistakenly 1, then RUADD below will wind up 1 too large.
drRUADD[topDst, const2, reg0]; drLIQB[IntToWord[a - 1]];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRUADD]];
drRUADD[topDst, const0, const0];
drJNEBB[1, UseLabel8B[badRUADD]];
};
If the final RUADD carry-out was mistakenly 1, then the following call to RUADDTest will have a result 1 too large.
};
SetLabel[enterRUADDTest];
drRUADD[const3, const0, const0]; --Eat garbage Carry value and Carry ← 0.
drROR[const3, const0, const0]; --Put 0 in const3, indicating Overflow not expected
The first 32 tests are for carry generation at each bit position.
RUADDTest[ 1B, 1B, 0];
RUADDTest[ 2B, 2B, 0];
RUADDTest[ 4B, 4B, 0];
RUADDTest[ 10B, 10B, 0];
RUADDTest[ 20B, 20B, 0];
RUADDTest[ 40B, 40B, 0];
RUADDTest[ 100B, 100B, 0];
RUADDTest[ 200B, 200B, 0];
RUADDTest[ 400B, 400B, 0];
RUADDTest[ 1000B, 1000B, 0];
RUADDTest[ 2000B, 2000B, 0];
RUADDTest[ 4000B, 4000B, 0];
RUADDTest[ 10000B, 10000B, 0];
RUADDTest[ 20000B, 20000B, 0];
RUADDTest[ 40000B, 40000B, 0];
RUADDTest[ 100000B, 100000B, 0];
RUADDTest[ 200000B, 200000B, 0];
RUADDTest[ 400000B, 400000B, 0];
RUADDTest[ 1000000B, 1000000B, 0];
RUADDTest[ 2000000B, 2000000B, 0];
RUADDTest[ 4000000B, 4000000B, 0];
RUADDTest[ 10000000B, 10000000B, 0];
RUADDTest[ 20000000B, 20000000B, 0];
RUADDTest[ 40000000B, 40000000B, 0];
RUADDTest[ 100000000B, 100000000B, 0];
RUADDTest[ 200000000B, 200000000B, 0];
RUADDTest[ 400000000B, 400000000B, 0];
RUADDTest[ 1000000000B, 1000000000B, 0];
RUADDTest[ 2000000000B, 2000000000B, 0];
RUADDTest[ 4000000000B, 4000000000B, 0];
RUADDTest[10000000000B, 10000000000B, 0];
The compiler rejects -20000000000B, so use FIRST[INT].
RUADDTest[ FIRST[INT], FIRST[INT], 1];
RUADDTest[ 6B, 3B, 0];
RUADDTest[ 30B, 14B, 0];
RUADDTest[ 140B, 60B, 0];
RUADDTest[ 600B, 300B, 0];
RUADDTest[ 3000B, 1400B, 0];
RUADDTest[ 14000B, 6000B, 0];
RUADDTest[ 60000B, 30000B, 0];
RUADDTest[ 300000B, 140000B, 0];
RUADDTest[ 1400000B, 600000B, 0];
RUADDTest[ 6000000B, 3000000B, 0];
RUADDTest[ 30000000B, 14000000B, 0];
RUADDTest[ 140000000B, 60000000B, 0];
RUADDTest[ 1600000000B, 700000000B, 0];
RUADDTest[ 6000000000B, 3000000000B, 0];
RUADDTest[-10000000000B, -4000000000B, 1];
RUADDTest[ -2B, FIRST[INT], 1];
RUADDTest[ 17777777777B, FIRST[INT], 0];
RUADDTest[-17777777777B, 17777777777B, 1];
};
Executes 13 x 15 + 2 = 197 instructions.
Note that RUSUB does c ← a - b - Carry and Carry ← carry-out'. Then when Carry = 0 (normal), RUSUB and RSUB perform c ← a - b. Since the adder has already been tested with RUADD, the primary goal here is to test the b inverter and Carry arithmetic.
GenRUSUB: PROC = {
Test RUSUB on a - b, a - 0 - (carry of a - b), 0 - b - Carry (0), and a - (-1)- Carry (1); a = 0 and b = 0 are illegal for this procedure because they make the carry-out of a - 0 - Carry and 0 - b - Carry uncertain. Executes 15 instructions.
RUSUBTest: PROC [a, b, ambc: INT] ~ {
okRUSUB: Label = GenLabel[];
badRUSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambx: Word ← IntToWord[a - b]; -- a - b
aminusambcarry: Word ← IntToWord[a - ambc];
mbx: Word ← IntToWord[- b]; -- - b
drLIQB[ax]; drLIQB[bx]; drRUSUB[pushDst, reg0, reg1]; drLIQB[ambx];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRUSUB]]; SetLabel[badRUSUB]; Pause[]; SetLabel[okRUSUB];
If RUSUB carry-out was wrong, then RUSUB below will wind up 1 off.
a - 0 - Carry produces carry-out = 1; hence Carry ← 0.
drRUSUB[pushDst, reg0, const0]; drLIQB[aminusambcarry];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRUSUB]];
If RUSUB carry-out was wrong, then RUSUB below will wind up 1 too large.
The result here of 0 - b - Carry (=0) = -b; also carry-out = 0, so Carry ← 1.
drRUSUB[pushDst, const0, reg1]; drLIQB[mbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRUSUB]];
If RUSUB carry-out was wrong, then RUSUB below will wind up 1 too large.
a - (-1) - Carry (=1) = a - 0, so Carry ← 1.
drRUSUB[topDst, reg0, const2];
drRJNEB[popSrc, reg0, UseLabel8B[badRUSUB]];
drRUADD[topDst, const0, const0];
drJNEBB[1, UseLabel8B[badRUSUB]];
};
SetLabel[enterRUSUBTest];
drRUADD[const3, const0, const0]; --Eat garbage Carry value and Carry ← 0.
drROR[const3, const0, const0]; --Put 0 in const3, indicating Overflow not expected
RUSUBTest doesn't work when a = 0 and a-b produces Carry = 1 because then a - 0 - Carry(1) = a + 0' produces carry-out=0 and sets Carry = 1; this screws up the prediction for 0 - b - Carry; nor does it work when b = 0.
RUSUBTest[ 1B, 2B, 1];
RUSUBTest[ 2B, 1B, 0];
RUSUBTest[ 1B, 1B, 0];
RUSUBTest[ -2B, -2B, 0];
RUSUBTest[ FIRST[INT], FIRST[INT], 0];
RUSUBTest[17777777777B, 12525252525B, 0];
RUSUBTest[17777777777B, 5252525252B, 0];
RUSUBTest[12525252525B, 5252525252B, 0];
RUSUBTest[12525252525B, 12525252526B, 1];
RUSUBTest[ 5252525252B, 5252525253B, 1];
RUSUBTest[ 1B, 17777777777B, 1];
RUSUBTest[ -1B, 17777777777B, 0];
RUSUBTest[ -2B, 17777777777B, 0];
};
Executes 20 x 12 + 1 = 241 instructions
GenRVADD: PROC = {
Test RVADD on a+b, a+0, 0+a, and a+(-1). Executes 12 instructions.
RVADDTest: PROC [a, b: INT] ~ {
okRVADD: Label = GenLabel[];
badRVADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbx: Word ← IntToWord[a + b];
aminus1: Word ← IntToWord[a - 1];
drLIQB[ax]; drLIQB[bx];
drRVADD[pushDst, reg0, const0];
drRJEBJ[popSrc, reg0, UseLabel8B[okRVADD]]; SetLabel[badRVADD]; Pause[]; SetLabel[okRVADD];
drRVADD[pushDst, const0, reg1];
drRJNEB[popSrc, reg1, UseLabel8B[badRVADD]];
drRVADD[pushDst, const2, reg0]; drLIQB[aminus1];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVADD]];
drRVADD[belowDst, belowSrc, popSrc]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVADD]];
};
SetLabel[enterRVADDTest];
drROR[const3, const0, const0]; --Put 0 in const3, indicating Overflow not expected
RVADDTest[ 5B, 5B];
RVADDTest[ 12B, 12B];
RVADDTest[ 120B, 120B];
RVADDTest[ 240B, 240B];
RVADDTest[ 2400B, 2400B];
RVADDTest[ 5000B, 5000B];
RVADDTest[ 50000B, 50000B];
RVADDTest[ 120000B, 120000B];
RVADDTest[ 1200000B, 1200000B];
RVADDTest[ 2400000B, 2400000B];
RVADDTest[ 14000000B, 14000000B];
RVADDTest[ 60000000B, 60000000B];
RVADDTest[ 300000000B, 300000000B];
RVADDTest[ 1400000000B, 1400000000B];
RVADDTest[ 6000000000B, 6000000000B];
RVADDTest[-10000000000B, -10000000000B];
RVADDTest[ -2B, FIRST[INT]];
RVADDTest[ -2B, -2B];
RVADDTest[ -1B, -1B];
RVADDTest[ -1B, 1B];
};
Executes 8 x 16 + 1 = 129 instructions
GenRVSUB: PROC = {
Test RVSUB on a - b, a - 0, 0 - b, a - (-1), and -1 - b. Executes 16 instructions.
RVSUBTest: PROC [a, b: INT] ~ {
okRVSUB: Label = GenLabel[];
badRVSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambx: Word ← IntToWord[a - b];
mbx: Word ← IF b = FIRST[INT] THEN IntToWord[FIRST[INT]] ELSE IntToWord[- b];
m1mbx: Word ← IntToWord[- 1 - b];
ap1x: Word ← IntToWord[a - (- 1)];
drLIQB[ax]; drLIQB[bx];
drRVSUB[pushDst, reg0, const0]; -- a - 0
drRJEBJ[popSrc, reg0, UseLabel8B[okRVSUB]]; SetLabel[badRVSUB]; Pause[]; SetLabel[okRVSUB];
drRVSUB[pushDst, const0, reg1]; -- 0 - b
drLIQB[mbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVSUB]];
drRVSUB[pushDst, reg0, const2]; -- a - (-1)
drLIQB[ap1x];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVSUB]];
drRVSUB[pushDst, const2, reg1]; -- (-1) - b
drLIQB[m1mbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVSUB]];
drRVSUB[belowDst, belowSrc, popSrc]; -- a - b
drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVSUB]];
};
SetLabel[enterRVSUBTest];
drROR[const3, const0, const0]; --Put 0 in const3, indicating Overflow not expected
RVSUBTest[ 1B, 2B];
RVSUBTest[ 2B, 1B];
RVSUBTest[ 1B, 1B];
RVSUBTest[ -2B, -2B];
RVSUBTest[ FIRST[INT], FIRST[INT]];
RVSUBTest[ 0B, -1B];
RVSUBTest[ -1B, 0B];
RVSUBTest[ FIRST[INT], 0B];
};
GenRADD: PROC = {
Test RADD on a+b+carry0 and b+a+carry0. Executes 9 instructions.
RADDNoOvfC0: PROC [a, b: INT] ~ {
okRADD: Label = GenLabel[];
badRADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbx: Word ← IntToWord[a + b];
drLIQB[ax]; drLIQB[bx];
drRUADD[pushDst, const0, const0]; --Make Carry = 0
drRADD[topDst, reg0, reg1]; drLIQB[apbx]; --a + b + carry0
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRADD]]; SetLabel[badRADD]; Pause[]; SetLabel[okRADD];
drRADD[belowDst, topSrc, belowSrcPop]; drLIQB[apbx]; --b + a + carry0
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
};
Test RADD on a+b+carry1 and b+a+carry1. Executes 10 instructions.
RADDNoOvfC1: PROC [a, b: INT] ~ {
okRADD: Label = GenLabel[];
badRADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbp1x: Word ← IntToWord[a + b + 1];
drLIQB[ax]; drLIQB[bx];
drRUADD[pushDst, const2, const2];  --Make Carry = 1
drRADD[topDst, reg0, reg1]; drLIQB[apbp1x]; --a + b + carry1
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRADD]]; SetLabel[badRADD]; Pause[]; SetLabel[okRADD];
drRUADD[const5, const2, const2];  --Make Carry = 1
drRADD[belowDst, belowSrc, popSrc]; drLIQB[apbp1x]; --b + a + carry1
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
};
Test RADD on a+b+carry0 which overflows. Executes 10 instructions + overflow trap.
RADDOvfC0: PROC [a, b: INT] ~ {
okRADD: Label = GenLabel[];
badRADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drLIQB[ax]; drLIQB[bx];
This code caused Lizard to fail when carry-in was 1 here; then the 2nd RUADD does [S] ← 0 instead of [S] ← 1.
drRUADD[pushDst, const2, const2]; --Carry ← 1
drRUADD[topDst, const0, const0]; --Carry ← 0, [S] ← 1
drRADD[topDst, reg1, reg0]; --b + a + carry0
Pause[]; --Overflow trap skips this
Ensure that stack wasn't disturbed during the overflow traps.
drJEBBJ[1, UseLabel8B[okRADD]]; SetLabel[badRADD]; Pause[]; SetLabel[okRADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
};
Test RADD on a+b+carry1 which overflows. Executes 11 instructions + overflow trap.
RADDOvfC1: PROC [a, b: INT] ~ {
okRADD: Label = GenLabel[];
badRADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drLIQB[ax]; drLIQB[bx];
drRUADD[pushDst, const0, const0]; --Carry ← 0
drRUADD[topDst, const2, const2]; --Carry ← 1, [S] ← -2
drRADD[topDst, reg0, reg1]; --a + b + carry1
Pause[]; --Overflow trap skips this
Ensure that stack wasn't disturbed during the overflow traps.
drLIQB[IntToWord[-2]];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRADD]]; Pause[]; SetLabel[okRADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRADD]];
};
SetLabel[enterRADDTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note: For this test a+b and a+b+1 must either both overflow or both not overflow.
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
RADDNoOvfC0[ 7777777777B, 7777777777B];
RADDNoOvfC1[ 7777777777B, 7777777777B];
RADDNoOvfC0[10000000000B, 7777777777B];
RADDNoOvfC0[ 5252525252B, 2525252525B];
RADDNoOvfC1[ 5252525252B, 2525252525B];
RADDNoOvfC0[17777777776B, 0B];
RADDNoOvfC1[17777777776B, 0B];
RADDNoOvfC0[-10000000000B, -10000000000B];
RADDNoOvfC1[-10000000000B, -10000000000B];
RADDNoOvfC1[-10000000000B, -10000000001B];
RADDNoOvfC0[-17777777777B, -1B];
RADDNoOvfC1[-17777777777B, -2B];
RADDNoOvfC1[ -2B, -17777777777B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
RADDOvfC0[17777777777B, 1B];
RADDOvfC1[17777777777B, 1B];
RADDOvfC0[10000000000B, 10000000000B];
RADDOvfC1[10000000000B, 10000000000B];
RADDOvfC1[10000000000B, 7777777777B];
RADDOvfC1[12525252525B, 5252525252B];
RADDOvfC0[-17777777777B, -2B];
RADDOvfC0[ -2B, -17777777777B];
RADDOvfC0[-10000000000B, -10000000001B];
};
GenRSUB: PROC = {
Test RSUB on a - b - Carry0; executes 6 instructions.
RSUBNoOvfC0: PROC [a, b: INT] ~ {
okRSUB0: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambx: Word ← IntToWord[a - b];
drLIQB[ax]; drLIQB[bx];
drRUADD[const5, const0, const0]; --Make Carry = 0
drRSUB[belowDst, belowSrc, popSrc]; drLIQB[ambx];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRSUB0]]; Pause[]; SetLabel[okRSUB0];
};
Test RSUB on a - b - Carry1; executes 6 instructions.
RSUBNoOvfC1: PROC [a, b: INT] ~ {
okRSUB0: Label = GenLabel[];
okRSUB1: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambm1x: Word ← IntToWord[a - b - 1];
drLIQB[ax]; drLIQB[bx];
drRUADD[const5, const2, const2]; --Make Carry = 1
drRSUB[belowDst, belowSrc, popSrc]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRSUB0]]; Pause[]; SetLabel[okRSUB0];
};
RSUBOvfC0: PROC [a, b: INT] ~ {
okRSUB: Label = GenLabel[];
badRSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const5, const0, const0]; --Carry ← 0
drLIQB[ax]; drLIQB[bx];
drRSUB[belowDst, belowSrc, popSrc]; --a - b - carry0
Pause[]; --Overflow trap skips this
Ensure stack and Carry not disturbed during overflow trap.
drRUADD[pushDst, const0, const0];
drJEBBJ[0, UseLabel8B[okRSUB]]; SetLabel[badRSUB]; Pause[]; SetLabel[okRSUB];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRSUB]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRSUB]];
};
RSUBOvfC1: PROC [a, b: INT] ~ {
okRSUB: Label = GenLabel[];
badRSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const5, const2, const2];
drLIQB[ax]; drLIQB[bx];
drRSUB[pushDst, reg0, reg1]; --a - b - carry1
Pause[]; --Overflow trap skips this
Ensure stack and Carry not disturbed during overflow trap.
drRUADD[pushDst, const0, const0]; --writes 0 + 0 + carry1
drJEBBJ[1, UseLabel8B[okRSUB]]; SetLabel[badRSUB]; Pause[]; SetLabel[okRSUB];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRSUB]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRSUB]];
};
SetLabel[enterRSUBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note: For this test a-b and a-b-1 must either both overflow or both not overflow.
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
RSUBNoOvfC0[10000000000B, 10000000000B];
RSUBNoOvfC1[10000000000B, 10000000000B];
RSUBNoOvfC1[10000000000B, -10000000000B];
RSUBNoOvfC1[17777777777B, 12525252525B];
RSUBNoOvfC0[17777777777B, 12525252525B];
RSUBNoOvfC1[17777777777B, 5252525252B];
RSUBNoOvfC0[17777777777B, 5252525252B];
RSUBNoOvfC1[ 3333333333B, 2222222222B];
RSUBNoOvfC0[ 3333333333B, 2222222222B];
RSUBNoOvfC1[ 1111111111B, 2222222222B];
RSUBNoOvfC0[ 1111111111B, 3333333333B];
RSUBNoOvfC1[-1111111111B, 12222222222B];
RSUBNoOvfC0[-1111111111B, 13333333333B];
RSUBNoOvfC1[17777777777B, -1B];
RSUBNoOvfC0[-10000000000B, 10000000000B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
RSUBOvfC0[FIRST[INT], 1B];
RSUBOvfC1[FIRST[INT], 1B];
RSUBOvfC0[17777777777B, -1B];
RSUBOvfC0[10000000000B, -10000000000B];
RSUBOvfC1[-10000000000B, 10000000000B];
};
GenADD: PROC = {
Test ADD on a + b + Carry1 and a + b + Carry0; executes 11 instructions (+ overflow trap).
ADDNoOvfTest: PROC [a, b: INT] ~ {
okADD: Label = GenLabel[];
badADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbp1x: Word ← IntToWord[a + b + 1];
apbx: Word ← IntToWord[a + b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drLIQB[bx]; drADD[]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okADD]]; SetLabel[badADD]; Pause[]; SetLabel[okADD];
drLIQB[ax]; drLIQB[bx]; drADD[]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADD]];
};
ADDOvfTest: PROC [a, b: INT] ~ {
okADD: Label = GenLabel[];
badADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drLIQB[bx]; drADD[]; --a + b + carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
drRUADD[const4, const0, const0];
drADD[]; --a + b + carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
Ensure that the stack and Carry bit weren't disturbed during overflow traps.
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okADD]]; SetLabel[badADD]; Pause[]; SetLabel[okADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADD]];
};
SetLabel[enterADDTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
NOTE: a+b+1 and a+b must either both overflow or both not overflow for this test.
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
ADDNoOvfTest[FIRST[INT], 17777777776B];
ADDNoOvfTest[12312323456B, 1231231231B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
ADDOvfTest[10000000000B, 10000000000B];
ADDOvfTest[-10000000001B, -10000000001B];
ADDOvfTest[ 1B, 17777777777B];
};
GenSUB: PROC = {
Test SUB on a - b - Carry1 and a - b - Carry0; executes 11 instructions.
SUBNoOvfTest: PROC [a, b: INT] ~ {
okSUB: Label = GenLabel[];
badSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambm1x: Word ← IntToWord[a - b - 1];
ambx: Word ← IntToWord[a - b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drLIQB[bx]; drSUB[]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okSUB]]; SetLabel[badSUB]; Pause[]; SetLabel[okSUB];
drLIQB[ax]; drLIQB[bx]; drSUB[]; drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUB]];
};
SUBOvfTest: PROC [a, b: INT] ~ {
okSUB: Label = GenLabel[];
badSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drLIQB[bx]; drSUB[]; --a - b - carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const4, const0, const0];
drSUB[]; --a - b - carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okSUB]]; SetLabel[badSUB]; Pause[]; SetLabel[okSUB];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUB]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUB]];
};
SetLabel[enterSUBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
SUBNoOvfTest[10000000000B, 10000000000B];
SUBNoOvfTest[17777777777B, 0B];
SUBNoOvfTest[-17777777777B, 0B];
SUBNoOvfTest[ -1B, 17777777776B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
SUBOvfTest[FIRST[INT], 1B];
SUBOvfTest[17777777777B, -2B];
SUBOvfTest[ -2B, 17777777777B];
};
GenADDB: PROC = {
Test ADDB on a + b + Carry1 and a + b + Carry0; executes 11 instructions.
ADDBNoOvfTest: PROC [a, b: INT] ~ {
okADDB: Label = GenLabel[];
badADDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
apbp1x: Word ← IntToWord[a + b + 1];
apbx: Word ← IntToWord[a + b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drADDB[b]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okADDB]]; SetLabel[badADDB]; Pause[]; SetLabel[okADDB];
drLIQB[ax]; drADDB[b]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDB]];
};
ADDBOvfTest: PROC [a, b: INT] ~ {
okADDB: Label = GenLabel[];
badADDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
drRUADD[const4, const2, const2];
drLIQB[ax]; drADDB[b]; --a + b + carry1
Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const4, const0, const0];
drADDB[b];  --a + b + carry0
Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okADDB]]; SetLabel[badADDB]; Pause[]; SetLabel[okADDB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDB]];
};
SetLabel[enterADDBTest];
Note that a+b+1 and a+b must either both overflow or both not overflow
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
ADDBNoOvfTest[ 10000000000B, 377B];
ADDBNoOvfTest[ 7777777777B, 0B];
ADDBNoOvfTest[ 17777777776B, 0B];
ADDBNoOvfTest[-17777777776B, 377B];
ADDBNoOvfTest[-17777777776B, 0B];
ADDBNoOvfTest[-17777777777B, 0B];
ADDBNoOvfTest[-17777777777B, 1B];
ADDBNoOvfTest[ 13777777777B, 1B];
ADDBNoOvfTest[ 15777777777B, 1B];
ADDBNoOvfTest[ 16777777777B, 1B];
ADDBNoOvfTest[ 17377777777B, 1B];
ADDBNoOvfTest[ 17577777777B, 1B];
ADDBNoOvfTest[ 17677777777B, 1B];
ADDBNoOvfTest[ 17737777777B, 1B];
ADDBNoOvfTest[ 17757777777B, 1B];
ADDBNoOvfTest[ 17767777777B, 1B];
ADDBNoOvfTest[ 17773777777B, 1B];
ADDBNoOvfTest[ 17775777777B, 1B];
ADDBNoOvfTest[ 17776777777B, 1B];
ADDBNoOvfTest[ 17777377777B, 1B];
ADDBNoOvfTest[ 17777577777B, 1B];
ADDBNoOvfTest[ 17777677777B, 1B];
ADDBNoOvfTest[ 17777737777B, 1B];
ADDBNoOvfTest[ 17777757777B, 1B];
ADDBNoOvfTest[ 17777767777B, 1B];
ADDBNoOvfTest[ 17777773777B, 1B];
ADDBNoOvfTest[ 17777775777B, 1B];
ADDBNoOvfTest[ 17777776777B, 1B];
ADDBNoOvfTest[ 17777777377B, 1B];
ADDBNoOvfTest[ 17777777577B, 1B];
ADDBNoOvfTest[ 17777777677B, 1B];
ADDBNoOvfTest[ 17777777737B, 1B];
ADDBNoOvfTest[ 17777777757B, 1B];
ADDBNoOvfTest[ 17777777767B, 1B];
ADDBNoOvfTest[ 17777777773B, 1B];
ADDBNoOvfTest[ 17777777775B, 1B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
ADDBOvfTest[17777777776B, 2B];
ADDBOvfTest[17777777777B, 1B];
ADDBOvfTest[17777777401B, 377B];
};
GenSUBB: PROC = {
Test SUBB on a - b - Carry1 and a - b - Carry0; executes 11 instructions.
SUBBNoOvfTest: PROC [a, b: INT] ~ {
okSUBB: Label = GenLabel[];
badSUBB: Label = GenLabel[];
ax: Word ← IntToWord[a];
ambm1x: Word ← IntToWord[a - b - 1];
ambx: Word ← IntToWord[a - b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drSUBB[b]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okSUBB]]; SetLabel[badSUBB]; Pause[]; SetLabel[okSUBB];
drLIQB[ax]; drSUBB[b]; drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBB]];
};
SUBBOvfTest: PROC [a, b: INT] ~ {
okSUBB: Label = GenLabel[];
badSUBB: Label = GenLabel[];
ax: Word ← IntToWord[a];
drRUADD[const4, const2, const2];
drLIQB[ax]; drSUBB[b]; --a - b - carry1
Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const4, const0, const0];
drSUBB[b];  --a - b - carry0
Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okSUBB]]; SetLabel[badSUBB]; Pause[]; SetLabel[okSUBB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBB]];
};
SetLabel[enterSUBBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note that a-b-1 and a-b must either both overflow or both not overflow
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
SUBBNoOvfTest[17777777777B, 2B];
SUBBNoOvfTest[-17777777777B, 0B];
SUBBNoOvfTest[-17777777400B, 377B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
SUBBOvfTest[FIRST[INT], 1B];
SUBBOvfTest[-17777777402B, 377B];
};
GenADDDB: PROC = {
Test ADDDB on a + b + Carry1 and a + b + Carry0; executes 11 instructions.
ADDDBNoOvfTest: PROC [a, b: INT] ~ {
okADDDB: Label = GenLabel[];
badADDDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
apbp1x: Word ← IntToWord[a + b + 1];
apbx: Word ← IntToWord[a + b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drADDDB[b]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okADDDB]]; SetLabel[badADDDB]; Pause[]; SetLabel[okADDDB];
drLIQB[ax]; drADDDB[b]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDDB]];
};
ADDDBOvfTest: PROC [a, b: INT] ~ {
okADDDB: Label = GenLabel[];
badADDDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
drRUADD[const4, const2, const2];
drLIQB[ax]; drADDDB[b]; --a + b + carry1
Pause[];  --Overflow trap skips these.
drRUADD[const4, const0, const0];
drADDDB[b]; --a + b + carry0
Pause[];  --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okADDDB]]; SetLabel[badADDDB]; Pause[]; SetLabel[okADDDB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDDB]];
};
SetLabel[enterADDDBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note that a+b+1 and a+b must either both overflow or both not overflow
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
ADDDBNoOvfTest[17777600000B, 177776B];
ADDDBNoOvfTest[17777577777B, 177777B];
ADDDBNoOvfTest[17777777776B, 0B];
ADDDBNoOvfTest[17777777775B, 1B];
ADDDBNoOvfTest[12345671234B, 123456B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
ADDDBOvfTest[17777777777B, 1B];
ADDDBOvfTest[17777600001B, 177777B];
};
GenSUBDB: PROC = {
Test SUBDB on a - b - Carry1 and a - b - Carry0; executes 11 instructions.
SUBDBNoOvfTest: PROC [a, b: INT] ~ {
okSUBDB: Label = GenLabel[];
badSUBDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
ambm1x: Word ← IntToWord[a - b - 1];
ambx: Word ← IntToWord[a - b];
drRUADD[const4, const2, const2];
drLIQB[ax]; drSUBDB[b]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okSUBDB]]; SetLabel[badSUBDB]; Pause[]; SetLabel[okSUBDB];
drLIQB[ax]; drSUBDB[b]; drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBDB]];
};
SUBDBOvfTest: PROC [a, b: INT] ~ {
okSUBDB: Label = GenLabel[];
badSUBDB: Label = GenLabel[];
ax: Word ← IntToWord[a];
drRUADD[const4, const2, const2];
drLIQB[ax]; drSUBDB[b]; --a - b - carry1
Pause[];  --Overflow trap skips this.
drRUADD[const4, const0, const0];
drSUBDB[b]; --a - b - carry0
Pause[];  --Overflow trap skips this.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okSUBDB]]; SetLabel[badSUBDB]; Pause[]; SetLabel[okSUBDB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBDB]];
};
SetLabel[enterSUBDBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note that a+b+1 and a+b must either both overflow or both not overflow
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
SUBDBNoOvfTest[ 17777777777B, 177777B];
SUBDBNoOvfTest[ 10000000000B, 177777B];
SUBDBNoOvfTest[ 0B, 177777B];
SUBDBNoOvfTest[ 0B, 0B];
SUBDBNoOvfTest[-17777777777B, 0B];
SUBDBNoOvfTest[-17777600000B, 177777B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
SUBDBOvfTest[-17777777777B, 2B];
SUBDBOvfTest[-17777777777B, 177777B];
SUBDBOvfTest[-17777600002B, 177777B];
};
GenQADD: PROC = {
Test QADD on a + b + Carry1 and a + b + Carry0; executes 10 instructions.
QADDNoOvfTest: PROC [a, b: INT] ~ {
okQADD: Label = GenLabel[];
badQADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbp1x: Word ← IntToWord[a + b + 1];
apbx: Word ← IntToWord[a + b];
drLIQB[ax]; drLIQB[bx];
drRUADD[const4, const2, const2]; --Carry ← 1
drQADD[pushAtop, reg0]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okQADD]]; SetLabel[badQADD]; Pause[]; SetLabel[okQADD];
drRUADD[const4, const0, const0]; --Carry ← 0
drQADD[pushAtop, reg0]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQADD]];
drAS[376B];
};
QADDOvfTest: PROC [a, b: INT] ~ {
okQADD: Label = GenLabel[];
badQADD: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drLIQB[ax]; drLIQB[bx];
drRUADD[const4, const2, const2];
drQADD[pushAtop, reg0]; --a + b + carry1
Pause[]; Pause[]; --Overflow trap skips these
drRUADD[const4, const0, const0];
drQADD[pushAtop, reg0]; --a + b + carry0
Pause[]; Pause[]; --Overflow trap skips these
Ensure that the stack and Carry bit weren't disturbed during overflow traps.
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okQADD]]; SetLabel[badQADD]; Pause[]; SetLabel[okQADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQADD]];
};
SetLabel[enterQADDTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note that a+b+1 and a+b must either both overflow or both not overflow.
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
QADDNoOvfTest[10000000000B, 7777777776B];
QADDNoOvfTest[17777777776B, 0B];
QADDNoOvfTest[-17777777777B, -1B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
QADDOvfTest[10000000000B, 10000000000B];
QADDOvfTest[17777777777B, 1B];
QADDOvfTest[-17777777777B, -3B];
};
GenQSUB: PROC = {
Test QSUB on a - b - Carry1 and a - b - Carry0; executes 10 instructions.
QSUBNoOvfTest: PROC [a, b: INT] ~ {
okQSUB: Label = GenLabel[];
badQSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambm1x: Word ← IntToWord[a - b - 1];
ambx: Word ← IntToWord[a - b];
drLIQB[bx];
drLIQB[ax];
drRUADD[const4, const2, const2]; --Carry ← 1
drQSUB[pushAtop, reg0]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okQSUB]]; SetLabel[badQSUB]; Pause[]; SetLabel[okQSUB];
drRUADD[const4, const0, const0]; --Carry ← 0
drQSUB[pushAtop, reg0]; drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQSUB]];
drAS[376B];
};
QSUBOvfTest: PROC [a, b: INT] ~ {
okQSUB: Label = GenLabel[];
badQSUB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drLIQB[bx]; drLIQB[ax];
drRUADD[const4, const2, const2];
drQSUB[pushAtop, reg0]; --a - b - carry1
Pause[]; Pause[];  --Overflow trap skips these.
drRUADD[const4, const0, const0];
drQSUB[pushAtop, reg0]; --a - b - carry0
Pause[]; Pause[];  --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const4, UseLabel8B[okQSUB]]; SetLabel[badQSUB]; Pause[]; SetLabel[okQSUB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQSUB]];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQSUB]];
};
SetLabel[enterQSUBTest];
drRUADD[const3, const0, const0]; --Eat garbage carry value and Carry ← 0
Note that a-b-1 and a-b must either both overflow or both not overflow.
drROR[const3, const0, const0]; --const3 = 0 means Overflow not expected
QSUBNoOvfTest[10000000000B, 10000000000B];
QSUBNoOvfTest[10000000000B, -7777777777B];
QSUBNoOvfTest[12233445566B, -2134567770B];
drROR[const3, const2, const2]; --const3 = -1 means Overflow expected
QSUBOvfTest[10000000001B, -10000000000B];
QSUBOvfTest[10000000000B, -10000000001B];
QSUBOvfTest[ 7777777777B, -10000000002B];
};
WordAlign[area];
SetLabel[dummy];
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; Halt[123B];
Trap here with the return PC pointing at an opcode which experienced arithmetic overflow; this trap is always enabled, so no special enabling or disabling action is necessary. Unless const3 = -1, Pause[] (overflow not expected); otherwise, increment PC by 4 and return.
WordAlign[area];
SetLabel[ALUOverflow];
drALS[0]; --ALS[1 - nargs], where nargs includes 1 for IFUstatus
drLC3[];
drRJNEB[popSrc, const2, UseLabel8B[ALUOvfUnexpected]];
Advance the PC by 4 without smashing or using Carry (so use RVADD instead of ADDB).
GetYoungestPC[]; --Advance return PC by 4
drRVADD[topDst, topSrc, const6];
SetYoungestPC[];
drRETK[377B]; --RETK[nResults - 1]
SetLabel[ALUOvfUnexpected]; Pause[];
An enableable trap would push IFU status and exit with RETK[nResults - 1].
Opcodes 0 and 377B are intercepted by the simulator, but make them trap to dummy here anyway.
savePC ← GetOutputPC[area];
FillTrap[ResetTrap, start];
FillTrap[ALUCondOver, ALUOverflow];
FillXop[0, dummy];
FillXop[377B, dummy];
SetOutputPC[savePC];
WordAlign[area];
SetLabel[start]; --Simulator execution begins here on a Reset.
const0 is in a ROM, so it requires no initialization; const2 is initialized to -1 here; the other constants require no initialization for this diagnostic.
drASL[255];
When there is nothing on the stack, S should be at L-1
drLIQB[IntToWord[-1]];
drROR[const2, topSrc, popSrc]; --Put -1 in const2.
drLIB[4];
drROR[const6, topSrc, popSrc]; --Put 4 in const6 for overflow trap
GenRUADD[];
GenRUSUB[];
GenRVADD[];
GenRVSUB[];
GenRADD[];
GenRSUB[];
GenADD[];
GenSUB[];
GenADDB[];
GenSUBB[];
GenADDDB[];
GenSUBDB[];
GenQADD[];
GenQSUB[];
Halt[177777B]; --Terminate here at the end of the program
};
END.