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
};
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];
};
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:
BOOL ←
TRUE] = {
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
};
};