GenPuzzle.mesa
Copyright © 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) March 18, 1986 2:08:50 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.66 seconds on a Dorado (March 18, 1986)
Total instructions: 985, Bytes: 1282 (no I/O code)
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
gKount: NAT = 7; -- INT
gTrialDepth: NAT = 8; -- INT
gMaxDepth: NAT = 9; -- INT
gSize: NAT = 10; -- 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] / bytesPerWord;
globalPuzzle ← CardToWord[globalPuzzleCard];
{
Initialialize the global variables.
G: RegSpec = reg0;
top: RegSpec = reg1;
EnableTraps[]; -- to detect stack overflow
drASL[255]; -- ensure that stack is empty, regardless of where it was
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
Halt[301B]; -- 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).
Halt[302B]; -- 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;
c512: RegSpec = reg5;
rLim: RegSpec = reg6;
labelLabel1: Label = GenLabel[];
ProcedureEntry[enterFit, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Fit", enterFit];
drLC0[]; -- FitResult
drLIQB[globalPuzzle]; -- global frame
drLC0[]; -- K: Position
drLIDB[512]; -- constant 512
drLC0[]; -- loop limit
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
drQADD[topAtop, rK];
drLRIn[G, gP];
drRX[];
drJNEBBJ[1, UseLabel8B[testLabel]];
IF Puzzle^[J + K] THEN GO TO Label1;
drRADD[c: pushDst, a: rJ, b: rK];
drQBC[topAtop, c512];
drLRIn[G, gPuzzle];
drRX[];
drJEBB[1, UseLabel8B[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;
c512: RegSpec = reg5;
rLim: RegSpec = reg6;
labelLabel1: Label = GenLabel[];
ProcedureEntry[enterPlace, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Place", enterPlace];
drLC0[]; -- PlaceResult
drLIQB[globalPuzzle]; -- global frame
drLC0[]; -- K
drLIDB[512]; -- constant 512
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];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drQADD[topAtop, rK];
drLRIn[G, gP];
drRX[];
drJNEBBJ[1, UseLabel8B[testLabel]];
Puzzle^[J + K] ← TRUE
drRADD[c: pushDst, a: rJ, b: rK];
drQBC[topAtop, c512];
drLRIn[G, gPuzzle];
drADD[];
drLC1[];
drWSB[0];
};
drLRIn[G, gPiecemax];
drRRX[c: rLim, a: rI, b: popSrc];
drROR[c: rK, a: const0, b: const0];
GenDynamicLoop[rK, topSrc, body];
};
Piececount^[Class^[I]] ← Piececount^[Class^[I]] - 1;
drLRIn[G, gClass];
drQRX[topAtop, rI];
drLRIn[G, gPiececount];
drADD[];
drRSB[0];
drSUBB[1];
drLIB[14];
drBC[];
drWSB[0];
{
FOR K IN [J..Size] DO
IF NOT Puzzle^[K] THEN {PlaceResult ← K; GO TO Label1}
ENDLOOP;
body: LoopBodyProc = {
[loopLabel, testLabel, exitLabel: Label]
drLRIn[G, gPuzzle];
drQRX[topAtop, rK];
drJNEBBJ[0, UseLabel8B[testLabel]];
drROR[c: rPR, a: const0, b: rK];
drJB[UseLabel8A[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;
c512: RegSpec = reg4;
rLim: RegSpec = reg5;
ProcedureEntry[enterRemove, 2];
HandCodingPseudos.MakeLabelGlobal["Puzzle.Remove", enterRemove];
drLIQB[globalPuzzle];
drLC0[]; -- reserve K
drLIDB[512]; -- constant 512
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];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drQADD[topAtop, rK];
drLRIn[G, gP];
drRX[];
drJNEBBJ[1, UseLabel8B[testLabel]];
Puzzle^[J + K] ← FALSE
drRADD[c: pushDst, a: rJ, b: rK];
drQBC[topAtop, c512];
drLRIn[G, gPuzzle];
drADD[];
drLC0[];
drWSB[0];
};
drLRIn[G, gPiecemax];
drRRX[c: rLim, a: rI, b: popSrc];
drROR[c: rK, a: const0, b: const0];
GenDynamicLoop[rK, topSrc, body];
};
Piececount^[Class^[I]] ← Piececount^[Class^[I]] + 1;
drLRIn[G, gClass];
drQRX[topAtop, rI];
drLRIn[G, gPiececount];
drADD[];
drRSB[0];
drADDB[1];
drLIB[14];
drBC[];
drWSB[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[];
placeLabel: Label = GenLabelHere[];
newMaxLabel: Label = GenLabel[];
HandCodingPseudos.MakeLabelGlobal["Puzzle.testDepth", placeLabel];
drLRIn[G, gTrialDepth]; drADDB[1]; drDUP[]; drSRIn[G, gTrialDepth];
drLRIn[G, gMaxDepth];
drRJLEBJ[left: topSrc, right: popSrc, dist: UseLabel8B[continueLabel]];
SetLabel[newMaxLabel];
HandCodingPseudos.MakeLabelGlobal["Puzzle.newMaxDepth", newMaxLabel];
drDUP[]; drSRIn[G, gMaxDepth];
test against known max
drLIB[18];
drRJGEBJ[left: topSrc, right: belowSrc, dist: UseLabel8B[continueLabel]];
Pause[];
SetLabel[continueLabel];
drDIS[];
};
{
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
drLRIn[G, gClass];
drQRX[topAtop, rI];
drLRIn[G, gPiececount];
drRX[];
drJEBBJ[0, UseLabel8B[testLabel]];
IF Fit[I, J] THEN
drLRn[rI];
drLRn[rJ];
drLFC[UseLabel16[enterFit]];
drJEBBJ[0, UseLabel8B[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, UseLabel8B[thenLabel]];
drLRn[rK];
drJNEBBJ[0, UseLabel8B[elseLabel]];
THEN {TrialResult ← TRUE; GO TO Label1}
SetLabel[thenLabel];
drROR[c: rTR, a: const0, b: const1];
drJB[UseLabel8A[labelLabel1]];
ELSE Remove[I, J]
SetLabel[elseLabel];
drLRn[rI];
drLRn[rJ];
drLFC[UseLabel16[enterRemove]];
};
};
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];
TrialDepth ← TrialDepth - 1;
drLRIn[G, gTrialDepth]; drSUBB[1]; drSRIn[G, gTrialDepth];
{
test for running too long
continueLabel: Label = GenLabel[];
placeLabel: Label = GenLabelHere[];
HandCodingPseudos.MakeLabelGlobal["Puzzle.testKount", placeLabel];
drLRIn[G, gKount];
drLIDB[2005];
drRJGEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[continueLabel]];
Pause[];
SetLabel[continueLabel];
};
drROR[c: reg0, a: const0, b: rTR];
ProcedureExit[1];
};
GenPuzzleRun: PROC = {
G: RegSpec = reg0;
rM: RegSpec = reg1;
rN: RegSpec = reg2;
rI: RegSpec = reg3;
rJ: RegSpec = reg4;
rK: RegSpec = reg5;
c512: RegSpec = reg6;
c13: RegSpec = reg7;
GenSetupStaticLoop: PROC [var: RegSpec, lim: CARDINAL, body: LoopBodyProc, closed: BOOLTRUE] = {
This procedure generates code based on var being in a register. We assume that at entry the initial value is on the stack and should be stored into var.
loopLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
drJB[UseLabel8A[entryLabel]];
HandCodingSupport.WordAlign[];
SetLabel[loopLabel];
body[loopLabel, testLabel, exitLabel];
SetLabel[testLabel];
drRADD[pushDst, var, const1];
SetLabel[entryLabel];
drROR[var, topSrc, const0];
IF lim < 256 THEN drLIB[lim] ELSE drLIDB[lim];
IF closed
THEN drRJGEBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[loopLabel]]
ELSE drRJGBJ[left: popSrc, right: belowSrcPop, dist: UseLabel8B[loopLabel]];
SetLabel[exitLabel];
};
GenCrap: PROC [G: RegSpec, which, class, iLim, jLim, kLim: NAT] = {
body1: LoopBodyProc = {
drLC0[];
GenSetupStaticLoop[rJ, jLim, body2];
};
body2: LoopBodyProc = {
drLC0[];
GenSetupStaticLoop[rK, kLim, body3];
};
body3: LoopBodyProc = {
P^[which][I + D * (J + D * K)] ← TRUE
drLRn[rK];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drQADD[topAtop, rJ];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drQADD[topAtop, rI];
drQBC[topAtop, c512];
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[];
GenSetupStaticLoop[rI, 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];
};
ProcedureEntry[enterPuzzleRun, 0];
drLIQB[globalPuzzle];
drLC0[]; -- rM
drLC0[]; -- rN
drLC0[]; -- rI
drLC0[]; -- rJ
drLC0[]; -- rK
drLIDB[512]; -- constant 512
drLIDB[13]; -- constant 13
TrialDepth ← 0;
MaxTrialDepth ← 0;
drLC0[]; drSRIn[G, gTrialDepth];
drLC0[]; drSRIn[G, gMaxDepth];
{
FOR M IN [0..Size] DO
Puzzle^[M] ← TRUE
ENDLOOP;
body1: LoopBodyProc = {
drLRIn[G, gPuzzle];
drQADD[topAtop, rM];
drLC1[];
drWSB[0];
};
drLC0[];
GenSetupStaticLoop[rM, 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[];
GenSetupStaticLoop[rJ, 5, body2];
};
body2: LoopBodyProc = {
drLC1[];
GenSetupStaticLoop[rK, 5, body3];
};
body3: LoopBodyProc = {
Puzzle^[I + D * (J + D * K)] ← FALSE
drLRn[rK];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drQADD[topAtop, rJ];
drSHL[FieldDescriptorToCard[[shift: 3]]]; -- to mult by 8
drQADD[topAtop, rI];
drQBC[topAtop, c512];
drLRIn[G, gPuzzle];
drADD[];
drLC0[];
drWSB[0];
};
drLC1[];
GenSetupStaticLoop[rI, 5, body1];
};
{
FOR I IN [0..Typemax] DO
FOR M IN [0..Size] DO
P^[I][M] ← FALSE
ENDLOOP
ENDLOOP;
body1: LoopBodyProc = {
drLC0[];
GenSetupStaticLoop[rM, 511, body2];
};
body2: LoopBodyProc = {
drLRn[rI];
drQBC[topAtop, c13];
drSHL[FieldDescriptorToCard[[shift: 9]]]; -- to mult by 512
drQADD[topAtop, rM];
drLRIn[G, gP];
drADD[];
drLC0[];
drWSB[0];
};
drLC0[];
GenSetupStaticLoop[rI, 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]; drLRn[c13]; drWSB[0];
drLRIn[G, gPiececount]; drLC3[]; drWSB[1];
drLRIn[G, gPiececount]; drLC1[]; drWSB[2];
drLRIn[G, gPiececount]; drLC1[]; drWSB[3];
M ← 1 + D * (1 + D * 1);
drLIB[1 + D * (1 + D * 1)]; drSRn[rM];
Kount ← 0;
drLC0[]; drSRIn[G, gKount];
{
IF Fit[0, M]
THEN N ← Place[0, M]
ELSE ERROR;
elseLabel: Label = GenLabel[];
fiLabel: Label = GenLabel[];
drLC0[]; drLRn[rM];
drLFC[UseLabel16[enterFit]];
drJNEBB[1, UseLabel8B[elseLabel]];
drLC0[]; drLRn[rM];
drLFC[UseLabel16[enterPlace]];
drSRn[rN];
drJB[UseLabel8A[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"];
};
drLRn[rN];
drLFC[UseLabel16[enterTrial]];
Leaves a boolean on the stack, 1 for success, 0 for failure
drLRIn[G, gKount]; drROR[temp, const0, popSrc]; -- leave the Kount in temp for later
drLRn[G]; drROR[nregs, const0, popSrc]; -- leave the global data addr in nregs for later
{oopsLabel: Label = GenLabel[];
drJNEBB[1, UseLabel8B[oopsLabel]];
Halt[0]; -- success
SetLabel[oopsLabel];
Halt[101B]; -- failure
};
};
Little Helpers
LoopBodyProc: TYPE = PROC [loopLabel, testLabel, exitLabel: Label];
GenStaticLoop: PROC [var: RegSpec, lim: CARDINAL, body: LoopBodyProc, closed: BOOLTRUE] = {
This procedure generates a loop where the variable in question goes from its initial value (not generated by this routine) to some static limit (inclusive). The variable must be in a local register.
loopLabel: Label = GenLabel[];
testLabel: Label = GenLabel[];
entryLabel: Label = GenLabel[];
exitLabel: Label = GenLabel[];
drJB[UseLabel8A[entryLabel]];
HandCodingSupport.WordAlign[];
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[left: popSrc, right: var, dist: UseLabel8B[loopLabel]]
ELSE drRJGBJ[left: popSrc, right: var, dist: UseLabel8B[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[UseLabel8A[entryLabel]];
HandCodingSupport.WordAlign[];
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[left: IF limNeedsPush THEN popSrc ELSE topSrc, right: var, dist: UseLabel8B[loopLabel]]
ELSE drRJGBJ[left: IF limNeedsPush THEN popSrc ELSE topSrc, right: var, dist: UseLabel8B[loopLabel]];
SetLabel[exitLabel];
};
END.