GenArithTest.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) January 28, 1986 2:23:45 pm PST
DIRECTORY
Basics,
BasicTime,
DragonProcessOffsets,
DragOpsCross,
DragOpsCrossProcess,
DragOpsCrossUtils,
HandCoding,
HandCodingSupport,
HandCodingPseudos,
IO,
LizardHeart,
LizardTweaker,
ViewerIO;
GenArithTest: CEDAR PROGRAM
IMPORTS Basics, BasicTime, DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport, IO, LizardHeart, LizardTweaker, ViewerIO
= BEGIN OPEN DragonProcessOffsets, HandCoding, HandCodingSupport, HandCodingPseudos;
CARD: TYPE = LONG CARDINAL;
STREAM: TYPE = IO.STREAM;
Word: TYPE = DragOpsCross.Word;
LongMult: PROC [x,y: CARD] RETURNS [lo,hi: CARD ← 0] = {
This uses the same algorithm as FatCardMultiply
yLo: CARD ← y;
yHi: CARD ← 0;
IF x # 0 THEN DO
IF Basics.LowHalf[x] MOD 2 = 1 THEN {
Double precision add
lo ← lo + yLo;
IF lo < yLo THEN hi ← hi + 1;
hi ← hi + yHi;
};
x ← Basics.DoubleShiftRight[[lc[x]], 1].lc;
IF x = 0 THEN EXIT;
Double precision add
yHi ← yHi + yHi;
IF LOOPHOLE[yLo, INT] < 0 THEN yHi ← yHi + 1;
yLo ← yLo + yLo;
ENDLOOP;
};
GenMulTest: PROC [enter: Label] = {
intMulLabel: Label = GetGlobalLabel["Basics.IntMultiply"];
fatMulLabel: Label = GetGlobalLabel["Basics.FatCardMultiply"];
innerIntCase: PROC [x, y: INT] = {
okLabel: Label = GenLabel[];
drLIQB[DragOpsCrossUtils.IntToWord[x]];
drLIQB[DragOpsCrossUtils.IntToWord[y]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[0]];
drDFC[UseLabel32[intMulLabel]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[1]];
drLIQB[DragOpsCrossUtils.IntToWord[x*y]];
drRJEBJ[left: popSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[whichHalt ← whichHalt + 1];
SetLabel[okLabel];
};
innerFatCase: PROC [x, y: CARD] = {
okLabel: Label = GenLabel[];
drLIQB[DragOpsCrossUtils.CardToWord[x]];
drLIQB[DragOpsCrossUtils.CardToWord[y]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[0]];
drDFC[UseLabel32[fatMulLabel]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[2]];
drLIQB[DragOpsCrossUtils.CardToWord[LongMult[x, y].hi]];
drRJEBJ[left: popSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[whichHalt ← whichHalt + 1];
drLIQB[DragOpsCrossUtils.CardToWord[LongMult[x, y].lo]];
drRJEBJ[left: popSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[whichHalt ← whichHalt + 1];
SetLabel[okLabel];
};
ProcedureEntry[enter, 0];
MakeLabelGlobal["ArithTest.MulTest", enter];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[-1]];
innerIntCase[37, 401];
innerIntCase[-156, 4];
innerIntCase[123456, 10101];
innerIntCase[LAST[INT] / 78563, 78563];
innerIntCase[LAST[INT] / 78563, -78563];
innerIntCase[LAST[CARDINAL], LAST[INTEGER]];
innerIntCase[FIRST[INT], 0];
innerIntCase[FIRST[INT], 1];
innerIntCase[2, LAST[INT] / 2];
innerIntCase[LAST[INT] / 2, 2];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[-1]];
innerFatCase[37, 401];
innerFatCase[156, 4];
innerFatCase[123456, 10101];
innerFatCase[LAST[CARD] / 78563, 78563];
innerFatCase[LAST[CARD] / 2, 2];
innerFatCase[LAST[CARD], 0];
innerFatCase[LAST[CARD], 1];
innerFatCase[LAST[CARD], LAST[CARD]];
ProcedureExit[0];
};
GenDivTest: PROC [enter: Label] = {
cardDivLabel: Label = GetGlobalLabel["Basics.CardDivide"];
innerCardCase: PROC [x, y: CARD] = {
okLabel: Label = GenLabel[];
drLIQB[DragOpsCrossUtils.CardToWord[x]];
drLIQB[DragOpsCrossUtils.CardToWord[y]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[0]];
drDFC[UseLabel32[cardDivLabel]];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[3]];
drLIQB[DragOpsCrossUtils.CardToWord[x/y]];
drRJEBJ[left: popSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[whichHalt ← whichHalt + 1];
SetLabel[okLabel];
};
ProcedureEntry[enter, 0];
MakeLabelGlobal["ArithTest.DivTest", enter];
HandCodingSupport.OQBcommon[x060B, DragOpsCrossUtils.IntToWord[-1]];
innerCardCase[5, 2];
innerCardCase[37, 401];
innerCardCase[401, 37];
innerCardCase[17*17, 17];
innerCardCase[17*17+3, 17];
innerCardCase[123456, 10101];
innerCardCase[LAST[CARD], 78563];
innerCardCase[LAST[CARD], 1];
innerCardCase[LAST[CARD] / 2, 2];
ProcedureExit[0];
};
All: PROC = {
startLabel: Label = GenLabelHere[];
mulTestLabel: Label = GenLabel[];
divTestLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
MakeLabelGlobal["ArithTest.All", startLabel];
EnableTraps[]; -- to detect stack overflow
drASL[255];
drRUADD[pushDst, constNI, constNI];
drRUADD[pushDst, constN1, constN1];
drRUADD[pushDst, const0, const0];
drASL[255];
drRUADD[pushDst, constN1, constN1];
drRUADD[pushDst, const0, const0];
drASL[255];
drRUADD[pushDst, constNI, constNI];
drRUADD[pushDst, const1, const1];
drRUADD[pushDst, const0, const0];
drASL[255];
drRUADD[pushDst, constNI, constNI];
drRUSUB[pushDst, constN1, constN1];
drRUADD[pushDst, const0, const0];
drASL[255];
drRUADD[pushDst, constNI, constNI];
drRUSUB[pushDst, const1, const0];
drRUADD[pushDst, const0, const0];
drASL[255];
drRUADD[pushDst, constNI, constNI];
drRSUB[pushDst, const1, const0];
drRUADD[pushDst, const0, const0];
drJDB[UseLabel16[testLabel]];
GenMulTest[mulTestLabel];
GenDivTest[divTestLabel];
SetLabel[testLabel];
drLFC[UseLabel16[mulTestLabel]];
drLFC[UseLabel16[divTestLabel]];
Halt[0];
LizardTweaker.Register[x060B, HandleCode];
out ← ViewerIO.CreateViewerStreams[name: "GenArithTest.log"].out;
IO.PutF1[out, "\nOpcode handler registered at %g.\n", [time[BasicTime.Now[]]] ];
};
whichHalt: NAT ← 100;
lastX: Word ← DragOpsCross.ZerosWord;
lastY: Word ← DragOpsCross.ZerosWord;
lastCycle: INT ← 0;
out: STREAMNIL;
HandleCode: LizardTweaker.OpcodeHandler = {
[data: REF ANY, processor: LizardHeart.Processor, inst: DragOpsCross.Inst, rest: DragOpsCross.Word] RETURNS [normal: BOOL ← FALSE]
ri: INT = DragOpsCrossUtils.WordToInt[rest];
SELECT ri FROM
-1 => {
Capture the cycle count and the two registers on top of the stack.
IF out # NIL THEN IO.PutRope[out, "\n"];
};
0 => {
Capture the cycle count and the two registers on top of the stack.
regS: DragOpsCross.ProcessorRegister = LizardHeart.WordToReg[processor.regs[ifuS]];
regSm: DragOpsCross.ProcessorRegister = LizardHeart.StackPlus[regS, 255];
lastCycle ← processor.stats.cycles;
lastX ← processor.regs[regSm];
lastY ← processor.regs[regS];
};
1 => {
Capture the top stack register & the delta of cycles.
regS: DragOpsCross.ProcessorRegister ← LizardHeart.WordToReg[processor.regs[ifuS]];
delta: INT ← processor.stats.cycles - lastCycle;
result: Word ← processor.regs[regS];
lastCycle ← processor.stats.cycles;
IF out # NIL THEN {
IO.PutF1[out, "%g cycles for IntegerMultiply\n", [integer[delta]] ];
IO.PutF1[out, " X: %g", [integer[DragOpsCrossUtils.WordToInt[lastX]]] ];
IO.PutF1[out, ", Y: %g", [integer[DragOpsCrossUtils.WordToInt[lastY]]] ];
IO.PutF1[out, ", Z: %g\n", [integer[DragOpsCrossUtils.WordToInt[result]]] ];
};
};
2 => {
Capture the top stack registers & the delta of cycles.
regS: DragOpsCross.ProcessorRegister ← LizardHeart.WordToReg[processor.regs[ifuS]];
regSm: DragOpsCross.ProcessorRegister = LizardHeart.StackPlus[regS, 255];
delta: INT ← processor.stats.cycles - lastCycle;
lo: Word ← processor.regs[regSm];
hi: Word ← processor.regs[regS];
lastCycle ← processor.stats.cycles;
IF out # NIL THEN {
IO.PutF[out, "%g cycles for FatMultiply\n", [integer[delta]] ];
IO.PutF[out, " X: %bB (%g)", [cardinal[DragOpsCrossUtils.WordToCard[lastX]]], [integer[DragOpsCrossUtils.WordToInt[lastX]]] ];
IO.PutF[out, ", Y: %bB (%g)\n", [cardinal[DragOpsCrossUtils.WordToCard[lastY]]], [integer[DragOpsCrossUtils.WordToInt[lastY]]] ];
IO.PutF[out, " lo: %bB (%g)", [cardinal[DragOpsCrossUtils.WordToCard[lo]]], [integer[DragOpsCrossUtils.WordToInt[lo]]] ];
IO.PutF[out, ", hi: %bB (%g)\n", [cardinal[DragOpsCrossUtils.WordToCard[hi]]], [integer[DragOpsCrossUtils.WordToInt[hi]]] ];
};
};
3 => {
Capture the top stack register & the delta of cycles.
regS: DragOpsCross.ProcessorRegister ← LizardHeart.WordToReg[processor.regs[ifuS]];
delta: INT ← processor.stats.cycles - lastCycle;
result: Word ← processor.regs[regS];
lastCycle ← processor.stats.cycles;
IF out # NIL THEN {
IO.PutF1[out, "%g cycles for Q ← CardDivide[X, Y]\n", [integer[delta]] ];
IO.PutF1[out, " X: %g", [cardinal[DragOpsCrossUtils.WordToCard[lastX]]] ];
IO.PutF1[out, ", Y: %g", [cardinal[DragOpsCrossUtils.WordToCard[lastY]]] ];
IO.PutF1[out, ", Q: %g\n", [cardinal[DragOpsCrossUtils.WordToCard[result]]] ];
};
};
ENDCASE;
};
END.