GenArith.mesa
Copyright © 1985, 1986, 1987 by Xerox Corporation. All rights reserved.
Edward Fiala February 10, 1986 6:46:47 pm PST
Curry, September 11, 1986 11:25:08 pm PDT
Curry, September 11, 1986 11:21:02 pm PDT
RETK => RET, const4 => const7 = temporary, const6 => const4 = 4, const3 => const6 = expected, const5 => const8 = temporary, const2 => const5 = -1, LC3 => LC6
Fiala November 5, 1986 3:38:18 pm PST Fix bug in overflow trap ALS[1-nargs] for RETK=>RET; add tests for ADDQB and SUBQB; changed overflow trap to skip 6 bytes instead of 4.
Fiala March 23, 1987 4:53:42 pm PST Eliminate Reset, Halt, and Pause stuff
to run with GenDebugger.
Load with "quad -cx GenDebugger GenArith". This diagnostic tests the arithmetic instructions RVADD, RVSUB, RUADD, RUSUB, RADD, RSUB, ADD, SUB, ADDB, SUBB, ADDDB, SUBDB, ADDQB, and SUBQB. When correctly executed it terminates with a HALT[177777b] at PC = 4064010B on instruction 3147 cycle 6818.
DIRECTORY
DragOpsCross USING [XopBase, TrapBase, TrapWidthBytes, bytesPerWord, TrapIndex, Word],
--Word, wordsPerPage, bytesPerWord, charsPerWord, bitsPerByte, bitsPerCharacter, bitsPerWord, bytesPerPage, logWordsPerPage, logBitsPerByte, logBitsPerChar, logBytesPerWord, logCharsPerWord, logBitsPerWord, logBytesPerPage, PageCount, PageNumber, maxPagesInVM, SixBitIndex, FiveBitIndex, TwoWords, FourBitIndex, Half, ThreeBitIndex, FourHalves, TwoHalves, Byte, ZerosByte, OnesByte, EightBytes, FourBytes, ByteIndex, BytesPerWord, TwoBytes, Comparison, ByteAddress, WordAddress, FieldDescriptor, RegIndex, PadByte, Lit8, Op4, Op8, JDist8, Inst, OIFormat, OQBformat, LRformat, QRformat, ShortRegQR, OBformat, LRBformat, RRformat, ODBformat, LRRBformat, RJBformat, ShortRegRJB, JBBformat, TrapWidthWords, TrapWidthBytes, XopBase, TrapBase, KernalLimit, TrapIndex, StackUnderflowTrap, IFUPageFaultTrap, ResetTrap, IFUStackOverflowTrap, EUStackOverflowTrap, RescheduleTrap, ALUCondFalse, ALUCondEZ, ALUCondLZ, ALUCondLE, ALUCondSpare, ALUCondNE, ALUCondGE, ALUCondGZ, ALUCondOver, ALUCondBC, ALUCondIL, ALUCondDO, ALUCondNotOver, ALUCondNB, ALUCondNI, ModeFault, MemAccessFault, IOAccessFault, EUPageFault, EUWriteFault, AUFault, euStack, euJunk, euToKBus, euMAR, euField, euConstant, euAux, euBogus, euLast, ifuYoungestL, ifuYoungestPC, ifuEldestL, ifuEldestPC, ifuSLimit, ifuBogus, ifuL, ifuS, ifuPC, ifuLast, EURegs, EULegalRegs, IFURegs, IFULegalRegs, StackedStatusWord, IFUStackIndex, IFUStackSize, IFUOverflow, EUStackIndex, EUStackSize, EULocalIndex, EULocals, EUAuxIndex, EUAuxRegs, EUConstIndex, EUConstants, IOLocation, ioRescheduleRequest, ioResetRequest, IOOperand, PCmdFormat, PCmdByteSelect, PCmdClass, PCmdSpace, PCmdDirection
DragOpsCrossUtils USING [IntToWord],
--InstToBytes, InstToFormat, BytePCToWordAddress, WordAddressToBytePC, IOOperandToCard, CardToIOOperand, FieldDescriptorToCard, CardToFieldDescriptor, 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, XopToBytePC, TrapIndexToBytePC, FieldUnit
HandCoding, --Has opcode and register defs.
HandCodingPseudos, --Label, SetLabel, GenLabel, GenLabelHere, UseLabel8A, UseLabel8B, UseLabel16, UseLabel32, LReg, PReg, SReg, AddReg, SubReg, SetRegConst, MoveReg, MoveRegI, LRegI, IndexedJump, ProcedureEntry, ProcedureExit, SetupField, ExtractField, ShiftLeft, LoadProcessorReg, StoreProcessorReg, CauseReschedule, CauseReset, GetSPLimit, SetSPLimit, GetYoungestPC, GetYoungestStatus, GetEldestPC, GetEldestStatus, SetYoungestPC, SetYoungestStatus, SetEldestPC, SetEldestStatus, Pause, Halt
HandCodingSupport; --Area, GetProc, PutProc, ProcList, NewArea, GenWithArea, Gen1WithArea, ForceOut, GetCurrentArea, LoadArea, GetOutputPC, SetOutputPC, WordAlign, ReserveData, 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:
const5 contains -1.
const6 is used as an "expected" flag by the integer overflow trap subroutine.
const7 is used as a smashable temporary.
const8 is used as a smashable temporary.
const4 contains the constant 6 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]];
const4: ConstSpec = [const[4]];
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;
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[];
enterADDQBTest: Label = GenLabel[];
enterSUBQBTest: 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, const5]; -- 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, const5, 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, const5, 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[const6, const0, const0]; --Eat garbage Carry value and Carry ← 0.
drROR[const6, const0, const0]; --Put 0 in const6, 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, const5];
drRJNEB[popSrc, reg0, UseLabel8B[badRUSUB]];
drRUADD[topDst, const0, const0];
drJNEBB[1, UseLabel8B[badRUSUB]];
};
SetLabel[enterRUSUBTest];
drRUADD[const6, const0, const0]; --Eat garbage Carry value and Carry ← 0.
drROR[const6, const0, const0]; --Put 0 in const6, 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, const5, reg0]; drLIQB[aminus1];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVADD]];
drRVADD[belowDst, belowSrc, popSrc]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVADD]];
};
SetLabel[enterRVADDTest];
drROR[const6, const0, const0]; --Put 0 in const6, 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, const5]; -- a - (-1)
drLIQB[ap1x];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badRVSUB]];
drRVSUB[pushDst, const5, 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[const6, const0, const0]; --Put 0 in const6, 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, const5, const5];  --Make Carry = 1
drRADD[topDst, reg0, reg1]; drLIQB[apbp1x]; --a + b + carry1
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okRADD]]; SetLabel[badRADD]; Pause[]; SetLabel[okRADD];
drRUADD[const8, const5, const5];  --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, const5, const5]; --Carry ← 1
drRUADD[topDst, const0, const0]; --Carry ← 0, [S] ← 1
drRADD[topDst, reg1, reg0]; --b + a + carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
Ensure that stack wasn't disturbed during the overflow trap.
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, const5, const5]; --Carry ← 1, [S] ← -2
drRADD[topDst, reg0, reg1]; --a + b + carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
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[const6, 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[const6, const0, const0]; --const6 = 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[const6, const5, const5]; --const6 = -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[const8, 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[const8, const5, const5]; --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[const8, const0, const0]; --Carry ← 0
drLIQB[ax]; drLIQB[bx];
drRSUB[belowDst, belowSrc, popSrc]; --a - b - carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
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[const8, const5, const5];
drLIQB[ax]; drLIQB[bx];
drRSUB[pushDst, reg0, reg1]; --a - b - carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these
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[const6, 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[const6, const0, const0]; --const6 = 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[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drLIQB[bx]; drADD[]; --a + b + carry1
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these
drRUADD[const7, const0, const0];
drADD[]; --a + b + carry0
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these
Ensure that the stack and Carry bit weren't disturbed during overflow traps.
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okADD]]; SetLabel[badADD]; Pause[]; SetLabel[okADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADD]];
};
SetLabel[enterADDTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
ADDNoOvfTest[FIRST[INT], 17777777776B];
ADDNoOvfTest[12312323456B, 1231231231B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drLIQB[bx]; drSUB[]; --a - b - carry1
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drSUB[]; --a - b - carry0
Pause[]; Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okSUB]]; SetLabel[badSUB]; Pause[]; SetLabel[okSUB];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUB]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUB]];
};
SetLabel[enterSUBTest];
drRUADD[const6, const0, const0]; --Eat garbage carry value and Carry ← 0
drROR[const6, const0, const0]; --const6 = 0 means Overflow not expected
SUBNoOvfTest[10000000000B, 10000000000B];
SUBNoOvfTest[17777777777B, 0B];
SUBNoOvfTest[-17777777777B, 0B];
SUBNoOvfTest[ -1B, 17777777776B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drADDB[b]; --a + b + carry1
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drADDB[b];  --a + b + carry0
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, 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[const6, const0, const0]; --const6 = 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[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drSUBB[b]; --a - b - carry1
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drSUBB[b];  --a - b - carry0
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okSUBB]]; SetLabel[badSUBB]; Pause[]; SetLabel[okSUBB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBB]];
};
SetLabel[enterSUBBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
SUBBNoOvfTest[17777777777B, 2B];
SUBBNoOvfTest[-17777777777B, 0B];
SUBBNoOvfTest[-17777777400B, 377B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drADDDB[b]; --a + b + carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drADDDB[b]; --a + b + carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okADDDB]]; SetLabel[badADDDB]; Pause[]; SetLabel[okADDDB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDDB]];
};
SetLabel[enterADDDBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
ADDDBNoOvfTest[17777600000B, 177776B];
ADDDBNoOvfTest[17777577777B, 177777B];
ADDDBNoOvfTest[17777777776B, 0B];
ADDDBNoOvfTest[17777777775B, 1B];
ADDDBNoOvfTest[12345671234B, 123456B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5];
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[const7, const5, const5];
drLIQB[ax]; drSUBDB[b]; --a - b - carry1
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drSUBDB[b]; --a - b - carry0
Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okSUBDB]]; SetLabel[badSUBDB]; Pause[]; SetLabel[okSUBDB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBDB]];
};
SetLabel[enterSUBDBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
SUBDBNoOvfTest[ 17777777777B, 177777B];
SUBDBNoOvfTest[ 10000000000B, 177777B];
SUBDBNoOvfTest[ 0B, 177777B];
SUBDBNoOvfTest[ 0B, 0B];
SUBDBNoOvfTest[-17777777777B, 0B];
SUBDBNoOvfTest[-17777600000B, 177777B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5]; --Carry ← 1
drQADD[pushAtop, reg0]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okQADD]]; SetLabel[badQADD]; Pause[]; SetLabel[okQADD];
drRUADD[const7, 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[const7, const5, const5];
drQADD[pushAtop, reg0]; --a + b + carry1
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these
drRUADD[const7, const0, const0];
drQADD[pushAtop, reg0]; --a + b + carry0
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these
Ensure that the stack and Carry bit weren't disturbed during overflow traps.
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okQADD]]; SetLabel[badQADD]; Pause[]; SetLabel[okQADD];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQADD]];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQADD]];
};
SetLabel[enterQADDTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
QADDNoOvfTest[10000000000B, 7777777776B];
QADDNoOvfTest[17777777776B, 0B];
QADDNoOvfTest[-17777777777B, -1B];
drROR[const6, const5, const5]; --const6 = -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[const7, const5, const5]; --Carry ← 1
drQSUB[pushAtop, reg0]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okQSUB]]; SetLabel[badQSUB]; Pause[]; SetLabel[okQSUB];
drRUADD[const7, 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[const7, const5, const5];
drQSUB[pushAtop, reg0]; --a - b - carry1
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drQSUB[pushAtop, reg0]; --a - b - carry0
Pause[]; Pause[]; Pause[]; Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okQSUB]]; SetLabel[badQSUB]; Pause[]; SetLabel[okQSUB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQSUB]];
drLIQB[bx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badQSUB]];
};
SetLabel[enterQSUBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
QSUBNoOvfTest[10000000000B, 10000000000B];
QSUBNoOvfTest[10000000000B, -7777777777B];
QSUBNoOvfTest[12233445566B, -2134567770B];
drROR[const6, const5, const5]; --const6 = -1 means Overflow expected
QSUBOvfTest[10000000001B, -10000000000B];
QSUBOvfTest[10000000000B, -10000000001B];
QSUBOvfTest[ 7777777777B, -10000000002B];
};
GenADDQB: PROC = {
Test ADDQB on a + b + Carry1 and a + b + Carry0; executes 11 instructions.
ADDQBNoOvfTest: PROC [a, b: INT] ~ {
okADDQB: Label = GenLabel[];
badADDQB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
apbp1x: Word ← IntToWord[a + b + 1];
apbx: Word ← IntToWord[a + b];
drRUADD[const7, const5, const5];
drLIQB[ax]; drADDQB[bx]; drLIQB[apbp1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okADDQB]]; SetLabel[badADDQB]; Pause[]; SetLabel[okADDQB];
drLIQB[ax]; drADDQB[bx]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDQB]];
drRUADD[const7, const5, const5];
drLIQB[bx]; drADDQB[ax]; drLIQB[apbp1x];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDQB]];
drLIQB[bx]; drADDQB[ax]; drLIQB[apbx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDQB]];
};
ADDQBOvfTest: PROC [a, b: INT] ~ {
okADDQB: Label = GenLabel[];
badADDQB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const7, const5, const5];
drLIQB[ax]; drADDQB[bx]; --a + b + carry1
Pause[]; --Overflow trap skips these.
drRUADD[const7, const0, const0];
drADDQB[bx]; --a + b + carry0
Pause[]; --Overflow trap skips these.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okADDQB]]; SetLabel[badADDQB]; Pause[]; SetLabel[okADDQB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badADDQB]];
};
SetLabel[enterADDQBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
ADDQBNoOvfTest[17777600000B, 177776B];
ADDQBNoOvfTest[17777577777B, 177777B];
ADDQBNoOvfTest[17777777776B, 0B];
ADDQBNoOvfTest[17777777775B, 1B];
ADDQBNoOvfTest[12345671234B, 123456B];
drROR[const6, const5, const5]; --const6 = -1 means Overflow expected
ADDQBOvfTest[17777777777B, 1B];
ADDQBOvfTest[17777600001B, 177777B];
};
GenSUBQB: PROC = {
Test SUBQB on a - b - Carry1 and a - b - Carry0; executes 11 instructions.
SUBQBNoOvfTest: PROC [a, b: INT] ~ {
okSUBQB: Label = GenLabel[];
badSUBQB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
ambm1x: Word ← IntToWord[a - b - 1];
ambx: Word ← IntToWord[a - b];
drRUADD[const7, const5, const5];
drLIQB[ax]; drSUBQB[bx]; drLIQB[ambm1x];
drRJEBJ[popSrc, belowSrcPop, UseLabel8B[okSUBQB]]; SetLabel[badSUBQB]; Pause[]; SetLabel[okSUBQB];
drLIQB[ax]; drSUBQB[bx]; drLIQB[ambx];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBQB]];
};
SUBQBOvfTest: PROC [a, b: INT] ~ {
okSUBQB: Label = GenLabel[];
badSUBQB: Label = GenLabel[];
ax: Word ← IntToWord[a];
bx: Word ← IntToWord[b];
drRUADD[const7, const5, const5];
drLIQB[ax]; drSUBQB[bx]; --a - b - carry1
Pause[];  --Overflow trap skips this.
drRUADD[const7, const0, const0];
drSUBQB[bx]; --a - b - carry0
Pause[];  --Overflow trap skips this.
Ensure that registers not smashed by overflow trap
drLIB[1];
drRJEBJ[popSrc, const7, UseLabel8B[okSUBQB]]; SetLabel[badSUBQB]; Pause[]; SetLabel[okSUBQB];
drLIQB[ax];
drRJNEB[popSrc, belowSrcPop, UseLabel8B[badSUBQB]];
};
SetLabel[enterSUBQBTest];
drRUADD[const6, 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[const6, const0, const0]; --const6 = 0 means Overflow not expected
SUBQBNoOvfTest[ 17777777777B, 177777B];
SUBQBNoOvfTest[ 10000000000B, 177777B];
SUBQBNoOvfTest[ 0B, 177777B];
SUBQBNoOvfTest[ 0B, 0B];
SUBQBNoOvfTest[-17777777777B, 0B];
SUBQBNoOvfTest[-17777600000B, 177777B];
drROR[const6, const5, const5]; --const6 = -1 means Overflow expected
SUBQBOvfTest[-17777777777B, 2B];
SUBQBOvfTest[-17777777777B, 177777B];
SUBQBOvfTest[-17777600002B, 177777B];
};
savePC ← GetOutputPC[area];
FillTrap[ALUCondOver, ALUOverflow];
SetOutputPC[savePC];
Begin at PC = userBasePC = 1010000B * 4, L = 1, S = 0 as established in GenDebugger. const0 is in a ROM and require no initialization; const5 is initialized to -1 and const4 to 6 here; the other constants require no initialization for this diagnostic.
drLIQB[IntToWord[-1]];
drROR[const5, topSrc, popSrc]; --Put -1 in const5.
drLIB[6];
drROR[const4, topSrc, popSrc]; --Put 6 in const4 for overflow trap
GenRUADD[];
GenRUSUB[];
GenRVADD[];
GenRVSUB[];
GenRADD[];
GenRSUB[];
GenADD[];
GenSUB[];
GenADDB[];
GenSUBB[];
GenADDDB[];
GenSUBDB[];
GenQADD[];
GenQSUB[];
GenADDQB[];
GenSUBQB[];
Halt[177777B]; --Terminate here at the end of the program
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 const6 = -1, Pause[] (overflow not expected); otherwise, increment PC by 6 and return.
WordAlign[area];
SetLabel[ALUOverflow];
drALS[1]; --ALS[1 - nargs]
drLC6[];
drRJNEB[popSrc, const5, UseLabel8B[ALUOvfUnexpected]];
Advance the PC by 4 without smashing or using Carry (so use RVADD instead of ADDB).
GetYoungestPC[]; --Advance return PC by 6
drRVADD[topDst, topSrc, const4];
SetYoungestPC[];
drRET[377B]; --RET[nResults - 1]
SetLabel[ALUOvfUnexpected]; Pause[];
An enableable trap would push IFU status and exit with RET[nResults - 1].
};
END.