Here it is in all its g(l)ory ;-)
It wasn´t easy, but the COCONUT CPU has such an extense instruction set that it´s doable. I have to say I´ve spent the unthinkable time trying to get this one shorter - but I did!
098 "X"
019 "Y" Y: number of pages
010 "P" X: first page#
005 "E"
008 "H" Howard Owen
0B8 READ 2(Y) Get the number of pages N
38D ?NC XQ Convert it to hex
008 ->02E3 [BCDBIN]
0E6 B<>C S&X store N in B
0F8 READ 3(X) Get the first page number S
38D ?NC XQ Convert it to hex
008 ->02E3 [BCDBIN]
106 A=C S&X But store the result in A (A=S)
130 LDI S&X comparison with the start page# in A
010 CON: Results in (hex) 010 in C [1:0]
306 ?A<C S&X Valid start page # is: 7< S <16
0B5 ?NC GO Start >= 16, DATA ERROR
0A2 ->282D [ERRDE]
130 LDI S&X Now test the lower bound
007 CON: Load hex 07 in C [1:0]
0A6 A<>C S&X C=Start page
306 ?A<C S&X is 7 less than Start?
3D3 JNC -06 Nope, DATA ERROR
0E6 B<>C S&X B=Start page, S
106 A=C S&X A=# of pages, N
130 LDI S&X Valid #Pgs is 0 < N < 9
009 CON: Load 09 into C [1:0]
306 ?A<C S&X Is N < 9?
3D3 JNC -06 Nope, DATA ERROR
346 ?A#0 S&X Is N not equal to 0?
3C3 JNC -08 Nope, DATA ERROR
0C6 C=B S&X Start page in C[S&X]
070 N=C START page number in N[S&X]
0A6 A<>C S&X
106 A=C S&X copy #pgs N to C[S&X]
126 A=A+B S&X A(X)=start page + number of pages = highest page +1
0A6 A<>C S&X C(X)=hp+1, A(X)=page count
266 C=C-1 S&X C(X)=hp
158 M=C highest page number in M[S&X]
0A6 A<>C S&X A(X)=hp, C(X)=page count
0E6 B<>C S&X B(X)=page count, C(X)=START page
0C6 C=B S&X B(X) is the count down index (page count)
266 C=C-1 S&X Underflow will set the carry bit
067 ?C RTN Done!, end function.
0E6 B<>C S&X place decremented counter back in B(X)
0B0 C=N Calculate the current page from the base pg# & counter
106 A=C S&X base page number in A(X)
126 A=A+B S&X current page in A=(S+N-1)
379 PORT DEP: Initialize the current page
03C XQ pg# expected in A(X)
1ED ->A1ED [INITPG]
3B3 JNC -10d [LOOP] ,and loop
04E C=0 ALL Prepare to load ROM address into C
0A6 A<>C S&X current Page number to C
106 A=C S&X keep it in A
13C RCR 8 Rotate page in C(X) into MSN of address field (C[6:3])
0A6 A<>C S&X Fetch current page again
106 A=C S&X
040 WROM Write X to page base address
0A0 SLCTP C[6:3] is the address field
01C PT= 3 P points to the low nibble
0E0 SLCTQ
15C PT= 6 Q is the high nibble.
112 A=C P-Q A[ADR]=page base address
0B0 C=N START page number in N[S&X]
0B2 A<>C P-Q bring it back to C
112 A=C P-Q Save base address in N
070 N=C N[ADR]=page base address
010 LD@PT- 0 N[S&X]=lowest page number
3D0 LD@PT- F
390 LD@PT- E
1D0 LD@PT- 7 C[ADR]=page relative address of the last page pointer (lpp)
15C PT= 6 Set Q back from the LC3
152 A=A+C P-Q A[ADR]=absolute address of the lpp
092 B=A P-Q save xFE7 in B[ADR] for later
0B0 C=N ALL lowest page number in C[S&X]
31C PT= 1
010 LD@PT- 0
058 G=C @PT+ G= PCALC flag:lowest page number
379 PORT DEP: Set LPP and write it to ROM address
03C XQ Lowest Page Pointer = LPP
25D ->A25D [PCALC]
0D2 C=B P-Q restore previous absolute ADR
23A C=C+1 M adr: xFE8
112 A=C P-Q
198 C=M ALL highest page number in C[S&X]
31C PT= 1
050 LD@PT- 1 This flag says we will subtract from the current page to get the previous page
058 G=C @PT+ G has '1P', where 'P' is the highest page number.
379 PORT DEP: Set NPP and write it to ROM address
03C XQ Next Page Pointer = NPP
25D ->A25D [PCALC]
0D2 C=B P-Q restore previous ADR
010 LD@PT- 0 remove absolute nibble
23A C=C+1 M adr: xFE8
23A C=C+1 M adr: xFE9
3DC PT=PT+1
0F2 B<>C P-Q
130 LDI S&X
091 CON:
106 A=C S&X
379 PORT DEP: Load Character
03C XQ
250 ->A250 [LMLDL]
010 LD@PT- 0
3D0 LD@PT- F
390 LD@PT- E adr: xFED
350 LD@PT- D word: 090
15C PT= 6
0F2 B<>C P-Q
130 LDI S&X
090 CON:
106 A=C S&X
379 PORT DEP: Load Character
03C XQ
250 ->A250 [LMLDL]
0F2 B<>C P-Q
23A C=C+1 M adr: xFEE
23A C=C+1 M adr: xFEF
0F2 B<>C P-Q
130 LDI S&X
091 CON:
106 A=C S&X
379 PORT DEP: Load Character
03C XQ
250 ->A250 [LMLDL]
0F2 B<>C P-Q
23A C=C+1 M adr: xFF0
23A C=C+1 M adr: xFF1
0F2 B<>C P-Q
130 LDI S&X
0E5 CON:
106 A=C S&X
379 PORT DEP: Load Character
03C XQ
250 ->A250 [LMLDL]
0F2 B<>C P-Q
23A C=C+1 M adr: xFF2
0F2 B<>C P-Q
130 LDI S&X
00F CON:
106 A=C S&X
379 PORT DEP: Load Character
03C XQ
250 ->A250 [LMLDL]
0F2 B<>C P-Q
23A C=C+1 M adr: xFF3
0F2 B<>C P-Q
130 LDI S&X
200 CON:
106 A=C S&X
0B0 C=N ALL
09C PT= 5
010 LD@PT- 0
010 LD@PT- 0
010 LD@PT- 0
112 A=C P-Q
15C PT= 6
132 A=A+B P-Q ADR field
0B2 A<>C P-Q ADR field
112 A=C P-Q ADR field
0A6 A<>C S&X get byte value to C[S&X]
040 WROM
3E0 RTN
04E C=0 ALL
39C PT= 0
098 C=G @PT+
31C PT= 1
010 LD@PT- 0 C(X)=passed extreme (highest or lowest) page number
106 A=C S&X Save it in A[S&X]
0B0 C=N Get current address into C[ADR]
07C RCR 4 Rotate the high nibble into C[3]
3C6 RSHFC S&X Mask off the nibbles to the left
3C6 RSHFC S&X What remains is the current page number
246 C=A-C S&X Difference with current page number
2E6 ?C#0 S&X are they different?
03F JC +07 yes, go to [PNEQ]
15C PT= 6 no, go on
010 LD@PT- 0 Otherwise, we are on one of the extreme pages
010 LD@PT- 0 The pointer to the next or previous page is
010 LD@PT- 0 therefore 0.
03C RCR 3
0AB JNC +21d [PCONT]
0B0 C=N We are in a page between the extremes
07C RCR 4 Get current base address into C[ADR])
3C6 RSHFC S&X Rotate the high nibble into C[3]
3C6 RSHFC S&X Mask off the nibbles to the left
106 A=C S&X Store CURRENT page number in A(X)
39C PT= 0 Get the add/subtract flag
098 C=G @PT+
3CE RSHFC ALL
21C PT= 2
010 LD@PT- 0
010 LD@PT- 0
2E6 ?C#0 S&X Add/subtract flag
02F JC +05 ADD
0A6 A<>C S&X
106 A=C S&X Get the page number back in C[S&X]
266 C=C-1 S&X the current page minus 1 is the previous page
023 JNC +04 PCONT
0A6 A<>C S&X
106 A=C S&X C=A S&X
226 C=C+1 S&X the current page plus 1 is the next page
15C PT= 6
0B2 A<>C P-Q Load the previous pointer address
040 WROM and write the computed value
3E0 RTN