<> <> <> 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] = { <> yLo: CARD _ y; yHi: CARD _ 0; IF x # 0 THEN DO IF Basics.LowHalf[x] MOD 2 = 1 THEN { <> 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; <> 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: STREAM _ NIL; 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 => { <> IF out # NIL THEN IO.PutRope[out, "\n"]; }; 0 => { <> 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 => { <> 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 => { <> 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 => { <> 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.