GenPuzzle.mesa
Russ Atkinson, March 28, 1984 2:56:53 pm PST
DIRECTORY
DragOpsCross,
DragOpsCrossUtils,
HandCoding,
HandCodingPseudos,
HandCodingSupport;
GenPuzzle: CEDAR PROGRAM
IMPORTS DragOpsCrossUtils, HandCoding, HandCodingPseudos, HandCodingSupport
= BEGIN OPEN DragOpsCross, DragOpsCrossUtils, HandCoding, HandCodingPseudos;
Area: TYPE = HandCodingSupport.Area;
This program takes
3.87 seconds with I/O on a Dorado
3.70 seconds without I/O on a Dorado
Total instructions: 1027, Bytes: 1348
Offsets in the global frame
gOut: NAT = 0; -- we don't use this
gStaticZone: NAT = 1; -- we don't use this either
gPiececount: NAT = 2; -- LONG POINTER TO ARRAY Piececlass OF INT [0..13]
gClass: NAT = 3; -- LONG POINTER TO ARRAY Piecetype OF Piececlass
gPiecemax: NAT = 4; -- LONG POINTER TO ARRAY Piecetype OF Position
gPuzzle: NAT = 5; -- LONG POINTER TO ARRAY Position OF BOOL
gP: NAT = 6; -- LONG POINTER TO ARRAY Piecetype OF ARRAY Position OF BOOL
gM: NAT = 7; -- Position
gN: NAT = 8; -- Position
gI: NAT = 9; -- [0..13]
gJ: NAT = 10; -- [0..13]
gK: NAT = 11; -- [0..13]
gKount: NAT = 12; -- INT
gTrialDepth: NAT = 13; -- INT
gMaxTrialDepth: NAT = 14; -- INT
gSize: NAT = 15; -- size of global frame
Global labels
globalPuzzleCard: LONG CARDINAL; -- global frame base
globalPuzzle: Word; -- global frame base as word
enterFit: Label ← NIL;
enterPlace: Label ← NIL;
enterRemove: Label ← NIL;
enterTrial: Label ← NIL;
enterPuzzleRun: Label ← NIL;
enterHalt: Label ← NIL;
Global constants
D: NAT = 8;
GenInit: PROC = {
This procedure generates the initialzation code for Puzzle.
area: Area = HandCodingSupport.GetCurrentArea[];
startLabel: Label = GenLabelHere[];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Init", startLabel];
reserve data statically
globalPuzzleCard ← HandCodingSupport.ReserveData[32*wordsPerPage];
globalPuzzle ← CardToWord[globalPuzzleCard];
{
Initialialize the global variables.
G: RegSpec = reg0;
top: RegSpec = reg1;
EnableTraps[]; -- to detect stack overflow
ProcedureEntry[NIL, 0];
drLIQB[globalPuzzle];
drLC0[];
FOR i: NAT IN [0..gSize) DO
drWRI[top, G, i];
ENDLOOP;
drROR[c: top, a: const0, b: G];
drADDDB[256];
drWRI[top, G, gPiececount];
drADDB[4];
drWRI[top, G, gClass];
drADDB[13];
drWRI[top, G, gPiecemax];
drADDB[13];
drWRI[top, G, gPuzzle];
drADDDB[512];
drWRI[top, G, gP];
};
PuzzleRun[]
drLFC[UseLabel16[enterPuzzleRun]];
HandCodingPseudos.MakeLabelGlobal["Puzzle.PuzzleRun", enterPuzzleRun];
Just in case we return to this goodie, we loop on the all 1s byte
HandCodingSupport.OutputByte[area, OnesByte];
drJB[255]; -- loop on halting
ProcedureEntry[enterHalt, 1];
To halt, we execute the all 0s byte. The top of stack has the return code (0 for success, non-zero for failure).
HandCodingSupport.OutputByte[area, ZerosByte];
drJB[255]; -- loop on halting
};
All: PROC = {
This procedure generates all of the code for Puzzle.
area: Area = HandCodingSupport.GetCurrentArea[];
enterFit ← GenLabel[];
enterPlace ← GenLabel[];
enterRemove ← GenLabel[];
enterTrial ← GenLabel[];
enterPuzzleRun ← GenLabel[];
enterHalt ← GenLabel[];
GenInit[]; -- must be the first to be generated
GenFit[];
GenPlace[];
GenRemove[];
GenTrial[];
GenPuzzleRun[];
Reserve the static storage
Reserve the global frame (a page is quite sufficient)
HandCodingSupport.SetOutputPC[globalPuzzleCard];
HandCodingSupport.OutputWord[area, ZerosWord];
Reserve the rest of the storage (32 pages is more than enough)
FOR i: NAT IN [1..32] DO
HandCodingSupport.SetOutputPC[globalPuzzleCard+i*LONG[bytesPerPage]+bytesPerPage];
HandCodingSupport.OutputWord[area, ZerosWord];
ENDLOOP;
};
GenFit: PROC = {
[I: Piecetype, J: Position] RETURNS [FitResult: BOOL]
rI: RegSpec = reg0;
rJ: RegSpec = reg1;
rFR: RegSpec = reg2;
G: RegSpec = reg3;
rK: RegSpec = reg4;
rLim: RegSpec = reg5;
labelLabel1: Label = GenLabel[];
ProcedureEntry[enterFit, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Fit", enterFit];
drLC0[];
drLIQB[globalPuzzle];
drLC0[];
drLC0[];
FitResult ← FALSE;
drROR[c: rFR, a: const0, b: const0];
{
FOR K IN [0..Piecemax^[I]] DO
IF P^[I][K] THEN IF Puzzle^[J + K] THEN GO TO Label1;
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
IF P^[I][K] THEN ...
drLRn[rI];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drRVADD[topDst, topSrc, rK];
drLRIn[G, gP];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJNEBB[1, UseLabel8[testLabel]];
IF Puzzle^[J + K] THEN GO TO Label1;
drRADD[c: pushDst, a: rJ, b: rK];
drLIDB[512];
drBNDCK[];
drLRIn[G, gPuzzle];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJEBB[1, UseLabel8[labelLabel1]];
};
drLRIn[G, gPiecemax];
drRRX[c: rLim, a: rI, b: popSrc];
drROR[c: rK, a: const0, b: const0];
GenDynamicLoop[rK, topSrc, body];
};
FitResult ← TRUE
drROR[c: rFR, a: const0, b: const1];
EXITS Label1 => NULL
SetLabel[labelLabel1];
drROR[c: reg0, a: const0, b: rFR];
ProcedureExit[1];
};
GenPlace: PROC = {
[I: Piecetype, J: Position] RETURNS [PlaceResult: BOOL]
rI: RegSpec = reg0;
rJ: RegSpec = reg1;
rPR: RegSpec = reg2;
G: RegSpec = reg3;
rK: RegSpec = reg4;
rLim: RegSpec = reg5;
labelLabel1: Label = GenLabel[];
ProcedureEntry[enterPlace, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Place", enterPlace];
drLC0[]; -- PlaceResult
drLIQB[globalPuzzle]; -- G
drLC0[]; -- K
drLC0[]; -- loop limit
{
FOR K IN [0..Piecemax^[I]] DO
IF P^[I][K] THEN Puzzle^[J + K] ← TRUE;
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
IF P^[I][K] THEN
drLRn[rI];
drLIDB[13];
drBNDCK[];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drLRn[rK];
drLIDB[512];
drBNDCK[];
drADD[];
drLRIn[G, gP];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJNEBB[1, UseLabel8[testLabel]];
Puzzle^[J + K] ← TRUE
drRADD[c: pushDst, a: rJ, b: rK];
drLIDB[512];
drBNDCK[];
drLRIn[G, gPuzzle];
drRVADD[c: belowDst, a: belowSrc, b: popSrc];
drLC1[];
drWSB[0];
};
drLRIn[G, gPiecemax];
drLRn[rI];
drLIDB[13];
drBNDCK[];
drRRX[c: rLim, a: belowSrcPop, b: popSrc];
drROR[c: rK, a: const0, b: const0];
GenDynamicLoop[rK, topSrc, body];
};
Piececount^[Class^[I]] ← Piececount^[Class^[I]] - 1;
drLRn[rI];
drLIB[13];
drBNDCK[];
drLRIn[G, gClass];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drLIB[4];
drBNDCK[];
drLRIn[G, gPiececount];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drSUBB[1];
drLIB[14];
drBNDCK[];
drLRn[rI];
drLIB[13];
drBNDCK[];
drLRIn[G, gClass];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drLIB[4];
drBNDCK[];
drLRIn[G, gPiececount];
drADD[];
drWB[0];
{
FOR K IN [J..Size] DO
IF NOT Puzzle^[K] THEN {PlaceResult ← K; GO TO Label1}
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
drLRn[rK];
drLIDB[512];
drBNDCK[];
drLRIn[G, gPuzzle];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJNEBBJ[0, UseLabel8[testLabel]];
drROR[c: rPR, a: const0, b: rK];
drJB[UseLabel8[labelLabel1]];
};
drROR[c: rK, a: const0, b: rJ];
GenStaticLoop[rK, 511, body];
};
PlaceResult ← 0
drROR[c: rPR, a: const0, b: const0];
EXITS Label1 => NULL
SetLabel[labelLabel1];
drROR[c: reg0, a: const0, b: rPR];
ProcedureExit[1];
};
GenRemove: PROC = {
[I: Piecetype, J: Position]
rI: RegSpec = reg0;
rJ: RegSpec = reg1;
G: RegSpec = reg2;
rK: RegSpec = reg3;
rLim: RegSpec = reg4;
ProcedureEntry[enterRemove, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Remove", enterRemove];
drLIQB[globalPuzzle];
drLC0[]; -- reserve K
drLC0[]; -- reserve loop limit (will be on top of stack to make testing easier)
FOR K IN [0..Piecemax^[I]] DO
{
FOR K IN [0..Piecemax^[I]] DO
IF P^[I][K] THEN Puzzle^[J + K] ← TRUE;
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
IF P^[I][K] THEN
drLRn[rI];
drLIDB[13];
drBNDCK[];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drLRn[rK];
drLIDB[512];
drBNDCK[];
drADD[];
drLRIn[G, gP];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJNEBB[1, UseLabel8[testLabel]];
Puzzle^[J + K] ← FALSE
drRADD[c: pushDst, a: rJ, b: rK];
drLIDB[512];
drBNDCK[];
drLRIn[G, gPuzzle];
drRVADD[c: belowDst, a: belowSrc, b: popSrc];
drLC0[];
drWSB[0];
};
drLRIn[G, gPiecemax];
drLRn[rI];
drLIDB[13];
drBNDCK[];
drRRX[c: rLim, a: belowSrcPop, b: popSrc];
drROR[c: rK, a: const0, b: const0];
GenDynamicLoop[rK, topSrc, body];
};
Piececount^[Class^[I]] ← Piececount^[Class^[I]] + 1;
drLRn[rI];
drLIB[13];
drBNDCK[];
drLRIn[G, gClass];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drLIB[4];
drBNDCK[];
drLRIn[G, gPiececount];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drADDB[1];
drLIB[14];
drBNDCK[];
drLRn[rI];
drLIB[13];
drBNDCK[];
drLRIn[G, gClass];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drLIB[4];
drBNDCK[];
drLRIn[G, gPiececount];
drADD[];
drWB[0];
ProcedureExit[0];
};
GenTrial: PROC = {
[J: Position] RETURNS [TrialResult: BOOL]
rJ: RegSpec = reg0;
rTR: RegSpec = reg1;
G: RegSpec = reg2;
rI: RegSpec = reg3;
rK: RegSpec = reg4;
labelLabel1: Label = GenLabel[];
ProcedureEntry[enterTrial, 1];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Trial", enterTrial];
drLC0[]; -- TrialResult
drLIQB[globalPuzzle]; -- G
drLC0[]; -- I
drLC0[]; -- K
{
for testing against the depth
continueLabel: Label = GenLabel[];
drLRIn[G, gTrialDepth]; drADDB[1]; drDUP[]; drSRIn[G, gTrialDepth];
drLRIn[G, gMaxTrialDepth];
drRJLEB[popLeft: FALSE, right: popSrc, dist: UseLabel8[continueLabel]];
drDUP[]; drSRIn[G, gMaxTrialDepth];
test against known max
drLIB[18];
drRJLEB[popLeft: TRUE, right: popSrc, dist: UseLabel8[continueLabel]];
SetLabel[continueLabel];
};
{
FOR I IN [0..Typemax] DO
IF Piececount^[Class^[I]] # 0 THEN
IF Fit[I, J] THEN {
K ← Place[I, J];
IF Trial[K] OR K = 0
THEN {TrialResult ← TRUE; GO TO Label1}
ELSE Remove[I, J];
};
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
IF Piececount^[Class^[I]] # 0 THEN
drLRn[rI];
drLIB[13];
drBNDCK[];
drLRIn[G, gClass];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drLIB[4];
drBNDCK[];
drLRIn[G, gPiececount];
drRRX[c: belowDst, a: belowSrc, b: popSrc];
drJEBB[0, UseLabel8[testLabel]];
IF Fit[I, J] THEN
drLRn[rI];
drLRn[rJ];
drLFC[UseLabel16[enterFit]];
drJEBB[0, UseLabel8[testLabel]];
{
thenLabel: Label = GenLabel[];
elseLabel: Label = GenLabel[];
K ← Place[I, J];
drLRn[rI];
drLRn[rJ];
drLFC[UseLabel16[enterPlace]];
drSRn[rK];
IF Trial[K] OR K = 0
drLRn[rK];
drLFC[UseLabel16[enterTrial]];
drJEBB[1, UseLabel8[thenLabel]];
drLRn[rK];
drJNEBB[0, UseLabel8[elseLabel]];
THEN {TrialResult ← TRUE; GO TO Label1}
SetLabel[thenLabel];
drROR[c: rTR, a: const0, b: const1];
drJB[UseLabel8[labelLabel1]];
ELSE Remove[I, J]
SetLabel[elseLabel];
drLRn[rI];
drLRn[rJ];
drLFC[UseLabel16[enterRemove]];
};
};
drLRIn[G, gTrialDepth]; drSUBB[1]; drSRIn[G, gTrialDepth];
drROR[c: rI, a: const0, b: const0];
GenStaticLoop[rI, 12, body];
};
TrialResult ← FALSE
drROR[c: rTR, a: const0, b: const0];
EXITS Label1 => NULL
SetLabel[labelLabel1];
Kount ← Kount + 1
drLRIn[G, gKount];
drADDB[1];
drSRIn[G, gKount];
{
test for running too long
continueLabel: Label = GenLabel[];
placeLabel: Label = GenLabelHere[];
HandCodingPseudos.MakeLabelGlobal["Puzzle.testKount", placeLabel];
drLRIn[G, gKount];
drLIDB[2005];
drRJLEBJ[popLeft: TRUE, right: popSrc, dist: UseLabel8[continueLabel]];
Pause[];
SetLabel[continueLabel];
};
drROR[c: reg0, a: const0, b: rTR];
ProcedureExit[1];
};
GenPuzzleRun: PROC = {
G: RegSpec = reg0;
ProcedureEntry[enterPuzzleRun, 0];
drLIQB[globalPuzzle];
drLC0[]; drSRIn[G, gTrialDepth];
drLC0[]; drSRIn[G, gMaxTrialDepth];
{
FOR M IN [0..Size] DO
Puzzle^[M] ← TRUE
ENDLOOP;
body1: LoopBodyProc = {
drLRIn[G, gM];
drLRIn[G, gPuzzle];
drADD[];
drLC1[];
drWSB[0];
};
drLC0[];
GenGlobalStaticLoop[G, gM, 511, body1];
};
{
FOR I IN [1..5] DO
FOR J IN [1..5] DO
FOR K IN [1..5] DO
Puzzle^[I + D * (J + D * K)] ← FALSE
ENDLOOP
ENDLOOP
ENDLOOP;
body1: LoopBodyProc = {
drLC1[];
GenGlobalStaticLoop[G, gJ, 5, body2];
};
body2: LoopBodyProc = {
drLC1[];
GenGlobalStaticLoop[G, gK, 5, body3];
};
body3: LoopBodyProc = {
Puzzle^[I + D * (J + D * K)] ← FALSE
drLRIn[G, gK];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drLRIn[G, gJ];
drADD[];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drLRIn[G, gI];
drADD[];
drLIDB[512];
drBNDCK[];
drLRIn[G, gPuzzle];
drADD[];
drLC0[];
drWSB[0];
};
drLC1[];
GenGlobalStaticLoop[G, gI, 5, body1];
};
{
FOR I IN [0..Typemax] DO
FOR M IN [0..Size] DO
P^[I][M] ← FALSE
ENDLOOP
ENDLOOP;
body1: LoopBodyProc = {
drLC0[];
GenGlobalStaticLoop[G, gM, 511, body2];
};
body2: LoopBodyProc = {
drLRIn[G, gI];
drLIB[13];
drBNDCK[];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drLRIn[G, gM];
drADD[];
drLRIn[G, gP];
drADD[];
drLC0[];
drWSB[0];
};
drLC0[];
GenGlobalStaticLoop[G, gI, 12, body1];
};
FOR I IN [0..3] DO
FOR J IN [0..1] DO
FOR K IN [0..0] DO
P^[0][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[0] ← 0;
Piecemax^[0] ← 3 + D * 1 + D * D * 0;
GenCrap[G, 0, 0, 3, 1, 0];
FOR I IN [0..1] DO
FOR J IN [0..0] DO
FOR K IN [0..3] DO
P^[1][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[1] ← 0;
Piecemax^[1] ← 1 + D * 0 + D * D * 3;
GenCrap[G, 1, 0, 1, 0, 3];
FOR I IN [0..0] DO
FOR J IN [0..3] DO
FOR K IN [0..1] DO
P^[2][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[2] ← 0;
Piecemax^[2] ← 0 + D * 3 + D * D * 1;
GenCrap[G, 2, 0, 0, 3, 1];
FOR I IN [0..1] DO
FOR J IN [0..3] DO
FOR K IN [0..0] DO
P^[3][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[3] ← 0;
Piecemax^[3] ← 1 + D * 3 + D * D * 0;
GenCrap[G, 3, 0, 1, 3, 0];
FOR I IN [0..3] DO
FOR J IN [0..0] DO
FOR K IN [0..1] DO
P^[4][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[4] ← 0;
Piecemax^[4] ← 3 + D * 0 + D * D * 1;
GenCrap[G, 4, 0, 3, 0, 1];
FOR I IN [0..0] DO
FOR J IN [0..1] DO
FOR K IN [0..3] DO
P^[5][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[5] ← 0;
Piecemax^[5] ← 0 + D * 1 + D * D * 3;
GenCrap[G, 5, 0, 0, 1, 3];
FOR I IN [0..2] DO
FOR J IN [0..0] DO
FOR K IN [0..0] DO
P^[6][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[6] ← 1;
Piecemax^[6] ← 2 + D * 0 + D * D * 0;
GenCrap[G, 6, 1, 2, 0, 0];
FOR I IN [0..0] DO
FOR J IN [0..2] DO
FOR K IN [0..0] DO
P^[7][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[7] ← 1;
Piecemax^[7] ← 0 + D * 2 + D * D * 0;
GenCrap[G, 7, 1, 0, 2, 0];
FOR I IN [0..0] DO
FOR J IN [0..0] DO
FOR K IN [0..2] DO
P^[8][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[8] ← 1;
Piecemax^[8] ← 0 + D * 0 + D * D * 2;
GenCrap[G, 8, 1, 0, 0, 2];
FOR I IN [0..1] DO
FOR J IN [0..1] DO
FOR K IN [0..0] DO
P^[9][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[9] ← 2;
Piecemax^[9] ← 1 + D * 1 + D * D * 0;
GenCrap[G, 9, 2, 1, 1, 0];
FOR I IN [0..1] DO
FOR J IN [0..0] DO
FOR K IN [0..1] DO
P^[10][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[10] ← 2;
Piecemax^[10] ← 1 + D * 0 + D * D * 1;
GenCrap[G, 10, 2, 1, 0, 1];
FOR I IN [0..0] DO
FOR J IN [0..1] DO
FOR K IN [0..1] DO
P^[11][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[11] ← 2;
Piecemax^[11] ← 0 + D * 1 + D * D * 1;
GenCrap[G, 11, 2, 0, 1, 1];
FOR I IN [0..1] DO
FOR J IN [0..1] DO
FOR K IN [0..1] DO
P^[12][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
Class^[12] ← 3;
Piecemax^[12] ← 1 + D * 1 + D * D * 1;
GenCrap[G, 12, 3, 1, 1, 1];
Piececount^[0] ← 13;
Piececount^[1] ← 3;
Piececount^[2] ← 1;
Piececount^[3] ← 1;
drLRIn[G, gPiececount]; drLIB[13]; drWSB[0];
drLRIn[G, gPiececount]; drLIB[3]; drWSB[1];
drLRIn[G, gPiececount]; drLIB[1]; drWSB[2];
drLRIn[G, gPiececount]; drLIB[1]; drWSB[3];
M ← 1 + D * (1 + D * 1);
drLIB[1 + D * (1 + D * 1)]; drSRIn[G, gM];
Kount ← 0;
drLC0[]; drSRIn[G, gKount];
{
IF Fit[0, M]
THEN N ← Place[0, M]
ELSE ERROR;
elseLabel: Label = GenLabel[];
fiLabel: Label = GenLabel[];
drLC0[]; drLRIn[G, gM];
drLFC[UseLabel16[enterFit]];
drJNEBB[1, UseLabel8[elseLabel]];
drLC0[]; drLRIn[G, gM];
drLFC[UseLabel16[enterPlace]];
drSRIn[G, gN];
drJB[UseLabel8[fiLabel]];
SetLabel[elseLabel];
Halt[3];
SetLabel[fiLabel];
};
IF Trial[N]
THEN {
IO.PutF[out, "success in %g trials\n", [integer[Kount]]];
}
ELSE {
IO.PutRope[out, "failure\n"];
};
drLRIn[G, gN];
drLFC[UseLabel16[enterTrial]];
drRXOR[c: topDst, a: topSrc, b: const1]; -- code for NOT
Halt[0, TRUE]; -- with either 0 for success, or 1 for failure
};
Little Helpers
LoopBodyProc: TYPE = PROC [loopLabel, testLabel, exitLabel: Label];
Halt: PROC [code: NAT, noPush: BOOLFALSE] = {
loopLabel: Label = GenLabelHere[];
IF NOT noPush THEN drLIB[code];
drLFC[UseLabel16[enterHalt]];
};
GenCrap: PROC
[G: RegSpec, which, class, iLim, jLim, kLim: NAT] = {
body1: LoopBodyProc = {
drLC0[];
GenGlobalStaticLoop[G, gJ, jLim, body2];
};
body2: LoopBodyProc = {
drLC0[];
GenGlobalStaticLoop[G, gK, kLim, body3];
};
body3: LoopBodyProc = {
P^[which][I + D * (J + D * K)] ← TRUE
drLRIn[G, gK];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drLRIn[G, gJ];
drADD[];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drLRIn[G, gI];
drADD[];
drLIDB[512];
drBNDCK[];
drLRIn[G, gP];
drADD[];
IF which # 0 THEN drADDDB[which*512];
drLC1[];
drWSB[0];
};
FOR I IN [0..iLim] DO
FOR J IN [0..jLim] DO
FOR K IN [0..kLim] DO
P^[which][I + D * (J + D * K)] ← TRUE
ENDLOOP
ENDLOOP
ENDLOOP;
drLC0[];
GenGlobalStaticLoop[G, gI, iLim, body1];
Class^[which] ← class;
drLIB[class];
drLRIn[G, gClass];
drWB[which];
Piecemax^[which] ← iLim + D*jLim + D*D*kLim;
drLIB[iLim + D*jLim + D*D*kLim];
drLRIn[G, gPiecemax];
drWB[which];
};
GenStaticLoop: PROC
[var: RegSpec, lim: CARDINAL, body: LoopBodyProc, closed: BOOLTRUE] = {
loopLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
drJB[UseLabel8[entryLabel]];
SetLabel[loopLabel];
body[loopLabel, testLabel, exitLabel];
SetLabel[testLabel];
drRADD[c: var, a: var, b: const1];
SetLabel[entryLabel];
IF lim < 256 THEN drLIB[lim] ELSE drLIDB[lim];
IF closed
THEN drRJGEBJ[popLeft: TRUE, right: var, dist: UseLabel8[loopLabel]]
ELSE drRJGBJ[popLeft: TRUE, right: var, dist: UseLabel8[loopLabel]];
SetLabel[exitLabel];
};
GenGlobalStaticLoop: PROC
[gr: RegSpec, var: NAT, lim: CARDINAL, body: LoopBodyProc, closed: BOOLTRUE] = {
This procedure generates code based on the variable in question being at some small offset from a register base. We assume that at entry the initial value is one the stack and should be stored into the indirect variable.
loopLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
drJB[UseLabel8[entryLabel]];
SetLabel[loopLabel];
body[loopLabel, testLabel, exitLabel];
SetLabel[testLabel];
drLRIn[gr, var];
drADDB[1];
SetLabel[entryLabel];
drDUP[];
drSRIn[gr, var];
IF lim < 256 THEN drLIB[lim] ELSE drLIDB[lim];
IF closed
THEN drRJLEBJ[popLeft: TRUE, right: popSrc, dist: UseLabel8[loopLabel]]
ELSE drRJLBJ[popLeft: TRUE, right: popSrc, dist: UseLabel8[loopLabel]];
SetLabel[exitLabel];
};
GenDynamicLoop: PROC
[var: RegSpec, lim: RegSpec, body: LoopBodyProc, closed: BOOLTRUE] = {
loopLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
limNeedsPush: BOOL = lim # topSrc;
drJB[UseLabel8[entryLabel]];
SetLabel[loopLabel];
body[loopLabel, testLabel, exitLabel];
SetLabel[testLabel];
drRADD[c: var, a: var, b: const1];
SetLabel[entryLabel];
IF limNeedsPush THEN LReg[lim];
IF closed
THEN drRJGEBJ[popLeft: limNeedsPush, right: var, dist: UseLabel8[loopLabel]]
ELSE drRJGBJ[popLeft: limNeedsPush, right: var, dist: UseLabel8[loopLabel]];
SetLabel[exitLabel];
};
END.