[net.sources] Re-post

lwt1@aplvax (06/13/84)

   Here is a re-post (part 1 of 2) of the SYS:ASM file for PDP-11 
unix-FORTH.  The network mangled the original.  Remove this header
to the ------ cut here ------ line.  Since the SYS:ASM file has been
broken into two pieces, you will need to concatenate them:
	cat SYS:ASM.1 SYS:ASM.2   >SYS:ASM

--------------------------- cut here ------------------------------------
( Copyright 1984 by The Johns Hopkins University/Applied Physics Lab.   )
( Free non-commercial distribution is *encouraged*, provided that:      )
(									)
( 	1.  This copyright notice is included in any distribution, and  )
( 	2.  You let us know that you're using it. 			)
(  									)
( Please notify: 							)
(  									)
( 	Lloyd W. Taylor 						)
( 	JHU/Applied Physics Lab 					)
( 	Johns Hopkins Road 						)
( 	Laurel, MD 20707 						)
( 	[301] 953-5000 							)
(  									)
( 	Usenet:  ... seismo!umcp-cs!aplvax!lwt1 			)
(  									)
(  									)
( Unix-FORTH was developed under NASA contract NAS5-27000 for the 	)
( Hopkins Ultraviolet Telescope, a March 1986 Space Shuttle mission.    )
( {We hope to take a peek at Halley's comet!}				)
(  									)
( Written entirely by Wizard-In-Residence John R. Hayes. 		)
(  									)	
( * Unix is a trademark of Bell Labs. 					)

( FORTH ASSEMBLY LANGUAGE SOUCE CODE ) OCTAL

( THIS IS SOURCE CODE TO BE RUN THROUGH THE METACOMPILER - METAASSEMBLER. )
( THEREFORE, THERE ARE DIFFERENCES BETWEEN THIS SOURCE CODE AND SOURCE    )
( CODE TO BE ASSEMBLED IN THE ORDINARY WAY. IN PARTICULAR, THERE IS NO    )
( IMPLICIT OR EXPLICIT SMUDGING.                                          )

 JMP 0 *$                       ( JUMP TO STARTUP; WILL BE BACKPATCHED )

LABEL vector
 MOV 0 $   IAR REG    		( MOVE ABORT TO IAR; WILL BE BACKPATCHED )
 60 TRAP   2 , vector ,
 NEXT

( VARIABLES AND DATA BUFFERS )
LABEL	rsp0 0 ,		( INITIAL VALUE OF RETURN STACK POINTER ) 
LABEL	in 0 ,			( >IN: INPUT PARSER )
LABEL	initvocab 0 ,		( INITIAL FORTH VOCABULARY )
LABEL	dp 0 ,			( END OF DICTIONARY POINTER )

	400 RAMALLOT		( 256 BYTE PARAMETER STACK )
LABEL inbuf
	DECIMAL 120 RAMALLOT 	( 120 BYTES OF INPUT BUFFER )
	OCTAL

( INNER INTERPRETER AND LOW-LEVEL RUN TIME WORDS )

CODE (:)			( CODE FOR NEXT )
 JMP IAR *)+

(    THE CODE FOR CALL IS COMPILED IN-LINE FOR COLON DEFINITIONS. )
(								  )
(    JSR IAR,*$NEXT
(								  )

CODE (;)
 MOV SP )+   IAR REG
 NEXT

(     THIS IS TRICKY CODE. ALL WORDS DEFINED BY VARIABLE, CONSTANT, OR )
( <BUILDS .. DOES> WORDS WILL HAVE SIMILAR CODE FIELDS. THEREFORE, THE )
( CODE FOR [VARIABLE], [CONSTANT], AND [DOES>] IS SHOW BELOW.          )
( EXAMPLE: CODE COMPILED FOR VARIABLE WILL BE:			       )
(     JSR IAR,*$[VARIABLE]					       )

CODE (VARIABLE)
 MOV IAR REG   PSP -(
 MOV SP )+   IAR REG
 NEXT

CODE (CONSTANT)
 MOV IAR )   PSP -(
 MOV SP )+   IAR REG
 NEXT

CODE (DOES>)
 MOV IAR )+   0 REG
 MOV IAR REG   PSP -(
 MOV 0 REG   IAR REG
 NEXT

(     BRANCHING PRIMITIVES )

CODE (LITERAL)
 MOV IAR )+   PSP -(
 NEXT

CODE BRANCH
 MOV IAR )   IAR REG
 NEXT

CODE ?BRANCH
 MOV PSP )+   0 REG
 BNE 1 FWD
 MOV IAR )   IAR REG
 JMP IAR *)+			( NEXT )
1 L: ADD 2 $   IAR REG
 NEXT

CODE EXECUTE
 JMP PSP *)+

(     FORTH-83 DO LOOPS )

CODE (DO)
 MOV PSP )+   1 REG
 MOV PSP )+   0 REG
 ADD 100000 $   0 REG		( LIMIT' := LIMIT + 8000 )
 MOV 0 REG   SP -(
 SUB 0 REG   1 REG		( IINIT' := INIT - LIMIT' )
 MOV 1 REG   SP -(
 NEXT

CODE (LOOP)
 INC SP )
 BVS 1 FWD
 MOV IAR )   IAR REG  		( LOOP BACK )
 JMP IAR *)+			( NEXT )
1 L: ADD 4 $   SP REG		( POP RETURN STACK )
 ADD 2 $   IAR REG		( SKIP LOOP ADDRESS )
 NEXT

CODE (+LOOP)
 ADD PSP )+   SP )
 BVS 1 FWD
 MOV IAR )   IAR REG  		( LOOP BACK )
 JMP IAR *)+ 			( NEXT )
1 L: ADD 4 $   SP REG		( POP RETURN STACK )
 ADD 2 $   IAR REG 		( SKIP LOOP ADDRESS )
 NEXT

CODE I
 MOV SP )   0 REG
 ADD 2 SP X(   0 REG		( I := I' + LIMIT' )
 MOV 0 REG   PSP -(
 NEXT

CODE J
 MOV 4 SP X(   0 REG
 ADD 6 SP X(   0 REG		( J := J' + LIMIT' )
 MOV 0 REG   PSP -(
 NEXT

CODE (LEAVE)
 ADD 4 $   SP REG		( POP RETURN STACK )
 MOV IAR )   IAR REG		( BRANCH PAST LOOP )
 NEXT

(	BASIC UNIX SYSTEM INTERFACE ROUTINES )

( BUFFER FOR HOLDING INDIRECT SYSTEM CALLS )
LABEL SYSBUF    0 ,		( TRAP INSTRUCTION )
		0 ,		( ARGUMENT 1 )
		0 ,		( ARGUMENT 2 )
		0 ,		( ARGUMENT 3 )

(	DATA AND CODE FOR SPAWNING OFF SUBPROCESSES )
HEX
LABEL STATUS	0 ,		( WORD FOR RECEIVING RETURN STATUS OF CHILD )
LABEL NAME	622F , 6E69 , 732F , 68 ,	( "/bin/sh" )
LABEL 0ARG	6873 , 0 ,			( "sh" )
LABEL 1ARG	632D , 0 ,			( "-c" )
LABEL ARGV	0ARG , 1ARG , 0 , 0 ,		( ARGUMENT LIST )
OCTAL

CODE SHELL			( --- )   ( SPAWN OFF INTERACTIVE SUB-SHELL )
 CLR ARGV 2+ *$			( sh WITH NO ARGUMENTS )
0 L: ( SPAWN SUB-PROCESS.  SYSTEM BELOW SHARES THIS CODE )
 2 TRAP				( FORK SYSTEM CALL )
 BR 2 FWD			( BRANCH TO CHILD PROCESS CODE )
 60 TRAP  2 , 1 ,		( IGNORE INTERRUPTS )
 MOV 0 REG   2 REG		( SAVE OLD VECTOR )
 7 TRAP				( WAIT SYSTEM CALL )
 ROR 2 REG
 BCS 1 FWD			( SKIP IF INTERRUPTS WERE IGNORED )
 60 TRAP  2 , vector ,		( ELSE, CATCH INTERRUPTS )
1 L: NEXT			( DONE )
2 L: ( CHILD )			( CHILD PROCESS CODE )
 MOV 104473 $   SYSBUF *$	( EXECE TRAP INSTRUCTION )
 MOV NAME $   SYSBUF 2+ *$	( MOVE NAME POINTER )
 MOV ARGV $   SYSBUF 4 + *$	( MOVE ARGUMENT POINTER )
 MOV rsp0 *$   SYSBUF 6 + *$	( MOVE ENVIRONMENT POINTER )
 0 TRAP	SYSBUF ,		( INDIRECT EXECE SYSTEM CALL )
 1 TRAP				( RETURN TO PARENT )

CODE SYSTEM			( ADDR[STRING] --- )
 MOV 1ARG $   ARGV 2+ *$	( MOVE POINTER TO "-c" TO ARGUMENT LIST )
 MOV PSP )+   ARGV 4 + *$	( MOVE POINTER TO COMMAND STRING TO LIST )
 BR 0 BACK			( BRANCH TO CODE TO SPAWN SUB-SHELL )

(	I/O BUFFER AND CONTROL VARIABLES
LABEL BLOCK	1000 RAMALLOT	( 512 BYTE DISK BUFFER )
LABEL SIZE	0 ,		( SIZE IN BYTES )
LABEL INDEX	0 ,		( CURRENT OFFSET INTO BLOCK )
LABEL FILED	0 ,		( FILE DESCRIPTOR OF FILE THAT OWNS BLOCK )

(	FILE POSITION TABLE: EACH SLOT HAS A 32 BIT FILE OFFSET. FILE )
(	DESCRIPTOR IS OFFSET INTO TABLE. THERE ARE 15 SLOTS.          )
LABEL FILEPOS	0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,
		0 , 0 ,

( SUBROUTINE GETC: HANDLES ALL INPUT AND DOES BUFFERING )
(	INPUT: FILE DESCRIPTOR IN R0                    )
(	OUTPUT: CHARACTER OF EOF IN R0			)
(	SIDE EFFECTS: R0 AND R1 DESTROYED		)
LABEL GETC
 CMP 0 REG   FILED *$		( IS THIS FILE CURRENTLY BUFFERED? )
 BEQ 0 FWD			( IS SO, DO NOT NEED TO TO SEEK )
 MOV 0 REG   FILED *$		( SAVE NEW FD IN BUFFER DESCRIPTOR )
 MOV SIZE *$   INDEX *$		( INDICATE THAT BUFFER IS EMPTY )
 MOV 104423 $   SYSBUF *$	( MOVE LSEEK TRAP INSTRUCTION TO SYSBUF )
 ASL 0 REG   ASL 0 REG		( MULTIPLY BY 4 TO INDEX INTO POSITION TABLE )
 MOV FILEPOS 0 X(   SYSBUF 2+ *$	( HIGH OFFSET WORD )
 MOV FILEPOS 2+ 0 X(   SYSBUF 4 + *$	( LOW OFFSET WORD )
 CLR SYSBUF 6 + *$		( OFFSET FROM BEGINNING OF FILE )
 MOV FILED *$   0 REG		( FILE DESCRIPTOR IN R0 )
 0 TRAP   SYSBUF ,		( LSEEK SYSTEM CALL )
 MOV FILED *$   0 REG		( RESTORE FD SINCE CALL DESTROYED R0, R1 )
0 L: MOV 2 REG   SP -(		( SAVE R2 )
 MOV INDEX *$   2 REG		( R2 IS INDEX )
 CMP 2 REG   SIZE *$
 BLT 1 FWD			( IF THERE IS STILL DATA IN BUFFER, USE IT )
 3 TRAP   BLOCK ,  1000 ,       ( READ UP TO 512 BYTES )
 BCS 2 FWD			( BRANCH IF ERROR )
 MOV 0 REG   SIZE *$		( SAVE SIZE OF BLOCK )
 BEQ 3 FWD			( BRANCH IF EOF )
 CLR 2 REG			( RESET INDEX )
1 L: MOV BLOCK 2 X(   0 REG BYTE
				( GET NEXT CHARACTER )
 BIC 17400 $   0 REG		( MASK OFF HIGH BYTE )
 INC 2 REG
 MOV 2 REG   INDEX *$		( UPDATE INDEX )
 MOV FILED *$   2 REG		( REUSE R2 TO HOLD FILE DESCRIPTOR )
 ASL 2 REG   ASL 2 REG		( MULTIPLY BY 4 TO INDEX INTO POSITION TABLE )
 ADD 1 $   FILEPOS 2+ 2 X(	( ADD ONE TO CURRENT FILE POSITION )
 ADC FILEPOS 2 X(
 BR 4 FWD
2 L: 3 L:
 MOV -1 $   0 REG		( RETURN EOF ON ERROR )
4 L: MOV SP )+   2 REG		( RESTORE R2 )
 RTS PC REG-ONLY 

CODE OPEN			( ADDR[STRING] MODE --- FD )
 MOV 104405 $   SYSBUF *$	( MOVE TRAP 5 INSTRUCTION TO INDIR AREA )
 MOV PSP )+   SYSBUF 4 + *$	( MOVE MODE )
 MOV PSP )   SYSBUF 2+ *$	( MOVE ADDR[STRING] )
 0 TRAP   SYSBUF ,		( OPEN SYSTEM CALL )
 BCC 1 FWD
 MOV -1 $   PSP )		( ERROR, NEGATIVE FILE DESCRIPTOR RETURNED )
 BR 2 FWD
1 L: MOV 0 REG   PSP )		( RETURN FILE DESCRIPTOR )
 ASL 0 REG   ASL 0 REG		( MULTIPLY BY 4 IN INDEX INTO POSITION TABLE )
 CLR FILEPOS 0 X(		( INITIALIZE FILE POSITION TO ZERO )
 CLR FILEPOS 2+ 0 X(
2 L: NEXT

CODE CREAT			( ADDR[STRING] PMODE --- FD )
 MOV 104410 $   SYSBUF *$	( MOVE TRAP 8 INSTRUCTION TO INDIR AREA )
 MOV PSP )+   SYSBUF 4 + *$	( MOVE PMODE )
 MOV PSP )   SYSBUF 2+ *$	( MOVE ADDRESS OF FILE NAME )
 0 TRAP SYSBUF ,		( CREAT SYSTEM CALL )
 BCC 1 FWD
 MOV -1 $   PSP )		( ERROR, NEGATIVE FILE DESCRIPTOR RETURNED )
 BR 2 FWD
1 L: MOV 0 REG   PSP )		( RETURN FILE DESCRIPTOR )
 ASL 0 REG   ASL 0 REG		( MULTIPLY BY 4 TO INDEX INTO POSITION TABLE )
 CLR FILEPOS 0 X(		( INITIALIZE FILE POSITION TO ZERO )
 CLR FILEPOS 2+ 0 X(
2 L: NEXT

CODE CLOSE			( FD --- )
 MOV 104406 $   SYSBUF *$	( MOVE TRAP 6 INSTRUCTION TO INDIR AREA )
 MOV PSP )+   0 REG		( FILE DESCRIPTOR )
 0 TRAP   SYSBUF ,		( CLOSE SYSTEM CALL )
 NEXT

CODE FEXPECT			( FD ADDR COUNT --- ACTCOUNT )
 MOV 2 PSP X(   2 REG		( BUFFER ADDRESS )
 MOV PSP )+   3 REG		( COUNT )
 BEQ 3 FWD			( DO NOTHING IF COUNT IS ZERO )
1 L: MOV 2 PSP X(   0 REG	( FILE DESCRIPTOR )
 JSR PC REG-ONLY   GETC *$	( GET NEXT CHARACTER )
 CMP 0 REG   -1 $		( EOF? )
 BEQ 4 FWD			( LEAVE LOOP ON EOF )
 CMP 0 REG   011 $ BYTE		( TAB ? )
 BNE 2 FWD
 MOV 040 $   0 REG BYTE		( CHANGE TABS TO BLANKS )
2 L: MOV 0 REG   2 )+ BYTE	( SAVE CHARACTER )
 CMP 0 REG   012 $ BYTE		( NEWLINE? )
 BEQ 5 FWD
 1 3 SOB 			( DECREMENT COUNT AND CONTINUE IF NON-ZERO )
3 L: 4 L: 5 L:
 SUB PSP )+   2 REG		( COMPUTE ACTUAL NUMBER OF CHARACTERS READ )
 MOV 2 REG   PSP )		( RETURN ACTUAL NUMBER )
 NEXT

CODE READ			( FD ADDR COUNT --- ACTCOUNT )
 MOV 2 PSP X(   2 REG		( BUFFER ADDRESS )
 MOV PSP )+   3 REG		( COUNT )
 BEQ 2 FWD			( DO NOTHING IF COUNT IS ZERO )
1 L: MOV 2 PSP X(   0 REG	( FILE DESCRIPTOR )
 JSR PC REG-ONLY   GETC *$	( GET NEXT CHARACTER )
 CMP 0 REG   -1 $		( EOF? )
 BEQ 3 FWD			( LEAVE LOOP ON EOF )
 MOV 0 REG   2 )+ BYTE		( SAVE CHARACTER )
 1 3 SOB 			( DECREMENT COUNT AND CONTINUE IF NON-ZERO )
2 L: 3 L:
 SUB PSP )+   2 REG		( COMPUTE ACTUAL NUMBER OF CHARACTERS READ )
 MOV 2 REG   PSP )		( RETURN ACTUAL NUMBER )
 NEXT

CODE WRITE			( ADDR COUNT FD --- ACTCOUNT )
 MOV 104404 $   SYSBUF *$	( MOVE TRAP INSTRUCTION TO INDIR AREA )
 MOV PSP )+   0 REG		( FILE DESCRIPTOR )
 MOV PSP )+   SYSBUF 4 + *$	( COUNT )
 MOV PSP )   SYSBUF 2+ *$	( ADDRESS )
 0 TRAP   SYSBUF ,		( WRITE SYSTEM CALL )
 BCC 1 FWD
 MOV -1 $   0 REG		( ERROR FLAG )
1 L: MOV 0 REG   PSP ) 		( RETURN ACTUAL COUNT )
 NEXT

CODE SEEK			( FD OFFSETL OFFSETH --- )
 MOV 4 PSP X(   0 REG		( FILE DESCRIPTOR )
 CMP 0 REG   FILED *$		( IF SEEK ON CURRENTLY BUFFERED FILE )
 BNE 1 FWD
 MOV -1 $   FILED *$		( FLAG BUFFER AS INVALID )
1 L: ASL 0 REG   ASL 0 REG	( MULTIPLY BY 4 TO INDEX INTO POSITION TABLE )
 MOV PSP )   FILEPOS 0 X(	( HIGH OFFSET INTO FILE POSITION TABLE )
 MOV 2 PSP X(   FILEPOS 2+ 0 X( ( LOW OFFSET INTO FILE POSITION TABLE )
 MOV 104423 $   SYSBUF *$	( MOVE SEEK TRAP INSTRUCTION TO SYSBUF )
 MOV PSP )+   SYSBUF 2+ *$	( MOVE HIGH OFFSET )
 MOV PSP )+   SYSBUF 4 + *$	( MOVE LOW OFFSET )
 CLR SYSBUF 6 + *$		( OFFSET FROM BEGINNING OF FILE )
 MOV PSP )+ 0 REG		( FILE DESCRIPTOR IN R0 )
 0 TRAP   SYSBUF ,		( SEEK SYSTEM CALL )
 NEXT

CODE TERMINATE 			( --- )
 CLR 0 REG			( RETURN GOOD STATUS )
 1 TRAP				( EXIT SYSTEM CALL )
				( SHOULD NOT EXECUTE BEYOND TRAP )

lwt1@aplvax (06/13/84)

   Here is a re-post (part 2 of 2) of the SYS:ASM file for PDP-11 
unix-FORTH.  The network mangled the original.  Remove this header
to the ------ cut here ------ line.  Since the SYS:ASM file has been
broken into two pieces, you will need to concatenate them:
	cat SYS:ASM.1 SYS:ASM.2   >SYS:ASM
 

------------------------ cut here -----------------------------------
CODE (FIND)			( ADDR[NAME] ADDR[VOCAB] --- 0 <OR> NFA ) 
MOV PSP )+   0 REG
 BEQ 3 FWD			( EMPTY VOCABULARY? )
 MOV PSP )   3 REG		( POINTER TO NAME )
 MOV 3 )+   2 REG		( NAME LS )
 MOV 3 )   3 REG		( NAME MS )
1 L: MOV 0 )   1 REG
 BIC 200 $   1 REG		( CLEAR IMMEDIATE BIT )
 CMP 1 REG   2 REG		( COMPARE LS )
 BNE 2 FWD
 CMP 2 0 X( 3 REG		( COMPARE MS )
 BEQ 4 FWD
2 L: MOV 4 0 X(   0 REG		( NEXT LINK )
 BNE 1 BACK			( ZERO LINK? )
3 L: 4 L:
 MOV 0 REG   PSP )
 NEXT

CODE WORD			( DEL --- ADDR )
 MOV PSP )   0 REG		( DELIMITER )
 MOV in *$   1 REG		( >IN )
 ADD inbuf $   1 REG            ( R1 HAS ADDRESS OF NEXT BYTE IN STREAM )
 MOV dp *$   2 REG		( HERE )
 MOV 2 REG   PSP )		( RETURN HERE, ADDRESS OF STRING )
1 L: CMP 0 REG   1 )+ BYTE	( SKIP DELIMITERS )
 BEQ 1 BACK
 DEC 1 REG			( BACK UP ONE )
 MOV 1 REG   3 REG
2 L: CMP 0 REG   3 ) BYTE	( DELIMITER? )
 BEQ 3 FWD
 CMP 012 $   3 ) BYTE		( NEWLINE? )
 BEQ 4 FWD
 INC 3 REG			( SKIP UNTIL END OF WORD )
 BR 2 BACK
3 L: 4 L:
 SUB 1 REG   3 REG		( R3 HAS LENGTH )
 MOV 3 REG 2 )+ BYTE 		( SAVE COUNT )
 BEQ 6 FWD			( SKIP IF EOL, I.E. ZERO LENGTH )
5 L: MOV 1 )+   2 )+ BYTE	( MOVE CHARACTERS TO HERE )
 5 3 SOB
6 L: CMP 012 $   1 ) BYTE	( IF NOT NEWLINE )
 BEQ 7 FWD
 INC 1 REG			( SKIP DELIMITER )
7 L: SUB inbuf $   1 REG        ( >IN IS OFFSET FROM START OF TIB )
 MOV 1 REG   in *$		( UPDATE >IN SCANNER )
 MOV 040 $   2 )+ BYTE		( ADD BLANK TO END OF WORD
 NEXT 
 
(     STACK PRIMITIVES )
 
CODE !				( DATA ADDR --- )
 MOV PSP )+   0 REG
 MOV PSP )+   0 )
 NEXT

CODE !SP			( ADDR --- )   ( SET ADDRESS OF STACK TOP. )
 MOV PSP )   PSP REG
 NEXT

CODE +				( N1 N2 --- N1+N2 )
 ADD PSP )+   PSP )
 NEXT

CODE +!				( DATA ADDR --- )
 MOV PSP )+   0 REG
 ADD PSP )+   0 )
 NEXT

CODE -				( N1 N2 --- N1-N2 )
 SUB PSP )+   PSP )
 NEXT

CODE -1				( --- -1 )
 MOV -1 $   PSP -(
 NEXT

CODE 0				( --- 0 )
 CLR PSP -(
 NEXT

CODE 0<				( N --- T/F )
 CLR 0 REG
 TST PSP )
 BPL 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE 0=				( N --- T/F )
 CLR 0 REG
 TST PSP )
 BNE 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE 1				( --- 1 )
 MOV 1 $   PSP -(
 NEXT

CODE 1+				( N --- N+1 )
 INC PSP )
 NEXT

CODE 1-				( N --- N-1 )
 DEC PSP )
 NEXT

CODE 2				( --- 2 )
 MOV 2 $   PSP -(
 NEXT

CODE 2+				( N --- N+2 )
 ADD 2 $   PSP )
 NEXT

CODE 2-				( N --- N-2 )
 SUB 2 $   PSP )
 NEXT

CODE 2*				( N --- 2*N )
 ASL PSP )
 NEXT

CODE 2/				( N --- N/2 )
 ASR PSP )
 NEXT

CODE <				( N1 N2 --- T/F )
 CLR 0 REG
 CMP PSP )+   PSP )
 BLE 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE =				( N1 N2 --- T/F )
 CLR 0 REG
 CMP PSP )+ PSP )
 BNE 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE >				( N1 N2 --- T/F )
 CLR 0 REG
 CMP PSP )+ PSP )
 BGE 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE >R				( N1 --- )
 MOV PSP )+ SP -(
 NEXT

CODE @				( ADDR --- DATA )
 MOV 0 PSP *X(   PSP )
 NEXT

CODE @SP			( --- ADDR )   ( RETURN STACK POINTER )
 MOV PSP REG   0 REG
 MOV 0 REG   PSP -(
 NEXT

CODE AND			( N1 N2 --- N1 & N2 )
 MOV PSP )+   0 REG
 COM 0 REG
 BIC 0 REG   PSP )
 NEXT

CODE C!				( BYTE ADDR --- )
 MOV PSP )+   0 REG
 MOV PSP )+   1 REG
 MOV 1 REG   0 )   BYTE
 NEXT

CODE C@				( ADDR --- BYTE )
 MOV 0 PSP *X(   0 REG   BYTE
 BIC 177400 $   0 REG
 MOV 0 REG   PSP )
 NEXT

CODE CMOVE			( SRC DEST UCOUNT --- )
 MOV PSP )+   2 REG
 BEQ 2 FWD			( DO NOTHING IF LENGTH ZERO )
 MOV PSP )+   0 REG		( DESTINATION )
 MOV PSP )+   1 REG		( SOURCE )
1 L: MOV 1 )+   0 )+ BYTE	( MOVE BYTE )
 1 2 SOB
 BR 3 FWD
2 L: ADD 4 $ PSP REG		( POP TWO STACK ARGS )
3 L: NEXT

CODE D+				( D1L D1H D2L D2H --- [D1+D2]L [D1+D2]H )
 MOV PSP )+   0 REG
 ADD PSP )+   2 PSP X(
 ADC PSP )
 ADD 0 REG   PSP )
 NEXT

CODE D<				( D1L D1H D2L D2H --- T/F )
 CLR 0 REG
 CMP PSP )+   2 PSP X(
 BLT 2 FWD
 BNE 1 FWD
 CMP PSP )   4 PSP X(
 BLE 3 FWD
1 L: MOV -1 $   0 REG
2 L: 3 L:
 ADD 4 $   PSP REG
 MOV 0 REG   PSP )
 NEXT

CODE DNEGATE			( D1L D1H --- [-D1]L [-D1]H )
 COM PSP )
 COM 2 PSP X(
 ADD 1 $   2 PSP X(
 ADC PSP )
 NEXT

CODE DROP			( N --- )
 ADD 2 $   PSP REG
 NEXT

CODE DUP			( N --- N N )
 MOV PSP )   PSP -(
 NEXT

CODE M* 			( S1 S2 --- [S1*S2]L [S1*S2]H )
 MOV PSP )   0 REG
 MUL 0 REG-ONLY   2 PSP X(
 MOV 1 REG   2 PSP X(		( LOW RESULT )
 MOV 0 REG   PSP )		( HIGH RESULT )
 NEXT

CODE M/ 			( SDL SDH DIVISOR --- SREM SQUOT )
 MOV PSP )+   2 REG		( R2 HAS DIVISOR )
 MOV PSP )   0 REG		( R0 HAS HIGH DIVIDEND )
 MOV 2 PSP X(   1 REG		( R1 HAS LOW DIVIDEND )
 MOV 2 REG   3 REG
 EXOR 0 REG-ONLY   3 REG	( R3 HAS SIGN )
 DIV 0 REG-ONLY   2 REG		( DIVIDE BY R2 )
 TST 3 REG
 BPL 1 FWD			( BRANCH IF SIGN IS NOT NEGATIVE )
 TST 1 REG
 BEQ 2 FWD			( BRANCH IF REMAINDER IS ZERO )
 DEC 0 REG			( SUBTRACT ONE FROM QUOTIENT )
 ADD 2 REG   1 REG		( ADD DIVISOR TO REMAINDER )
1 L: 2 L:
 MOV 1 REG   2 PSP X(		( REMAINDER )
 MOV 0 REG   PSP )		( QUOTIENT )
 NEXT

CODE NEGATE			( N --- -N )
 NEG PSP )
 NEXT

CODE NOT			( N --- ONE'S_COMPLEMENT_N )
 COM PSP )
 NEXT

CODE OR				( N1 N2 --- N1 V N2 )
 BIS PSP )+   PSP )
 NEXT

CODE OVER			( N1 N2 --- N1 N2 N1 )
 MOV 2 PSP X(   PSP -(
 NEXT

CODE R>				( --- N )
 MOV SP )+   PSP -(
 NEXT

CODE R@				( --- N )
 MOV SP )   PSP -(
 NEXT

CODE RESET			( --- )   ( RESET RETURN STACK POINTER )
 MOV rsp0 *$   SP REG
 NEXT

CODE ROT			( N1 N2 N3 --- N2 N3 N1 )
 MOV 4 PSP X(   0 REG
 MOV 2 PSP X(   4 PSP X(
 MOV PSP )   2 PSP X(
 MOV 0 REG   PSP )
 NEXT

CODE ROTATE			( WORD NBITS --- WORD' )
 MOV PSP )+    1 REG		( LOOP COUNTER )
 BIC 177760 $   1 REG		( MASK OFF ALL BUT LOWER FOUR BITS )
 BEQ 3 FWD			( SKIP IF ZERO LENGTH ROTATE )
 MOV PSP )   0 REG
1 L: TST 0 REG			( TEST SIGN BIT; CLEAR CARRY )
 BPL 2 FWD
 SEC				( SET CARRY )
2 L: ROL 0 REG			( ROTATE )
 1 1 SOB
 MOV 0 REG   PSP )
3 L: NEXT

CODE SWAP 			( N1 N2 --- N2 N1 )
 MOV 2 PSP X(   0 REG
 MOV PSP )   2 PSP X(
 MOV 0 REG   PSP )
 NEXT

CODE UM*			( N1 N2 --- UL UH )
 CLR 0 REG
 MOV 20 $   1 REG		( R1 := 16 )
 MOV PSP )   2 REG
 MOV 2 PSP X(   3 REG		( MULTIPLIER )
 ROR 3 REG			( GET LS BIT )
1 L: BCC 2 FWD
 ADD 2 REG   0 REG		( ACCUMULATE )
2 L: ROR 0 REG			( SHIFT CARRY INTO R0 )
 ROR 3 REG			( SHIFT INTO R3; GET CARRY BIT )
 1 1 SOB
 MOV 3 REG   2 PSP X(		( SAVE LS WORD )
 MOV 0 REG   PSP )		( SAVE MS WORD )
 NEXT

CODE UM/			( DL DH DIVISOR --- REM QUOT )
 MOV 20 $   0 REG		( 16 BITS )
 MOV PSP )+   1 REG		( DIVISOR )
 MOV PSP )   2 REG		( MS WORD )
 MOV 2 PSP X(   3 REG		( LS WORD )
1 L: ASL 3 REG
 ROL 2 REG
 CMP 1 REG   2 REG
 BHI 2 FWD
 SUB 1 REG   2 REG
 INC 3 REG
2 L: 1 0 SOB
 MOV 2 REG   2 PSP X(		( REMAINDER )
 MOV 3 REG   PSP )		( QUOTIENT )
 NEXT
 
CODE U<				( U1 U2 --- T/F )
 CLR 0 REG
 CMP PSP )+   PSP )
 BLOS 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

 CODE U>			( U1 U2 --- T/F )
 CLR 0 REG
 CMP PSP )+   PSP )
 BHIS 1 FWD
 MOV -1 $   0 REG
1 L: MOV 0 REG   PSP )
 NEXT

CODE XOR			( N1 N2 --- N1xorN2 )
 MOV PSP )+   0 REG
 EXOR 0 REG-ONLY   PSP )
 NEXT