GenStackTest.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) February 27, 1986 0:07:05 am PST
DIRECTORY
DragonProcessOffsets,
DragOpsCross,
DragOpsCrossProcess,
DragOpsCrossUtils,
HandCoding,
HandCodingSupport,
HandCodingPseudos;
GenStackTest: CEDAR PROGRAM
IMPORTS HandCoding, HandCodingPseudos
= BEGIN OPEN DragonProcessOffsets, HandCoding, HandCodingSupport, HandCodingPseudos;
CARD: TYPE = LONG CARDINAL;
Word: TYPE = DragOpsCross.Word;
depthReg: RegSpec = HandCoding.aux10;
An unused aux register that keeps track of the frame depth.
GenRecurse: PROC [entry: Label] = {
times: RegSpec = reg0; -- this value is also returned
size: RegSpec = reg1;
current: RegSpec = reg2;
ProcedureEntry[entry, 2];
MakeLabelGlobal["StackTest.Recurse", entry];
drLC3[]; -- init current to 3 (words initially on stack)
{
loop to put extra words on the stack
loopLabel: Label = GenLabelHere[];
drRADD[current, current, const1];
drLRn[current];
drRJLBJ[left: topSrc, right: size, dist: UseLabel8B[loopLabel]];
};
{
if times > 1, then recurse on times-1
fiLabel: Label = GenLabel[];
drRJGEB[left: const1, right: times, dist: UseLabel8B[fiLabel]];
drRSUB[pushDst, times, const1];
drLRn[size];
drLFC[UseLabel16[entry]];
{okLabel: Label = GenLabel[];
drRSUB[pushDst, times, const1];
drRJEBJ[left: topSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[1];
At this point the returned value of times is not what was passed in. This is an indication that the stack management was blown.
SetLabel[okLabel];
drDIS[];
};
SetLabel[fiLabel];
};
ProcedureExit[1];
};
GenEmptyRecurse: PROC [entry: Label] = {
exitLabel: Label = GenLabel[];
ProcedureEntry[entry, 0];
MakeLabelGlobal["StackTest.EmptyRecurse", entry];
drRJGEB[left: const0, right: depthReg, dist: UseLabel8B[exitLabel]];
drRVSUB[depthReg, depthReg, const1];
drLFC[UseLabel16[entry]];
drRVADD[depthReg, depthReg, const1];
SetLabel[exitLabel];
ProcedureExit[0];
};
All: PROC = {
startLabel: Label = GenLabelHere[];
enterRecurse: Label = GenLabel[];
emptyRecurse: Label = GenLabel[];
testLabel: Label = GenLabel[];
maxDepth: NAT ← 32;
MakeLabelGlobal["StackTest.Start", startLabel];
EnableTraps[]; -- to detect stack overflow
drJDB[UseLabel16[testLabel]];
GenEmptyRecurse[emptyRecurse];
GenRecurse[enterRecurse];
SetLabel[testLabel];
{
Test for empty stack frames being properly handled. This will cause various IFU overflow and underflow traps. The depthReg register governs how deep we go.
okLabel: Label = GenLabel[];
drLIB[maxDepth];
SReg[depthReg];
drLFC[UseLabel16[emptyRecurse]];
drLIB[maxDepth];
drRJEBJ[left: topSrc, right: depthReg, dist: UseLabel8B[okLabel]];
Halt[1];
SetLabel[okLabel];
};
{
Test for small frames being properly handled. This will exercise the IFU stack overflow handler.
okLabel: Label = GenLabel[];
drLIB[maxDepth];
drLIB[5];
drLFC[UseLabel16[enterRecurse]];
drLIB[maxDepth];
drRJEBJ[left: topSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[2];
SetLabel[okLabel];
drDIS[];
};
{
Test for large frames being properly handled. This will exercise the EU stack overflow handler.
okLabel: Label = GenLabel[];
drLIB[maxDepth];
drLIB[33];
drLFC[UseLabel16[enterRecurse]];
drLIB[maxDepth];
drRJEBJ[left: topSrc, right: popSrc, dist: UseLabel8B[okLabel]];
Halt[3];
SetLabel[okLabel];
drDIS[];
};
Halt[0];
};
END.