.IIF	NDF	RSX	RSX	=	1	;Assume RSX	;01+
	.TITLE	AS3F
	.ident	/X01.09/

	.NLIST	BEX
	.ENABL	LC,GBL
	.LIST	MEB						;01-

;
; AS
; SYMBOL TABLES
;
; VERSION X01
;
; DAVID G. CONROY	24-MAY-78
; LAST UPDATED:		11-JUN-79
;
; Edit history
; 01 04-Mar-80 MM	Added RT11 support
; 02 18-May-80 MM	USIZE (symbol table size) is easier to change
; 03 06-Jan-81 RBD	Sorted PST for binary search. Added binary
;			search routine SRCPST.
; 04 26-Feb-81 MM	Added .ident
; 05 10-Feb-82 MM	cmpd source:dst
; 06 26-Feb-82 RBD	Move UST stuff into AS3G for binary tree.
; 07 17-Jul-82 MM	Allow 30. psects 'cause Decus C has psect directive
; 08 22-Jul-82 CCG	Added support for .psect arg's and updated def. names.
; 09 07-Aug-82 MM	Redid symbol tables to eliminate recursion.
;

	.GLOBL	PST
	.GLOBL	SRCPST						;03
	.GLOBL	PSECT
	.GLOBL	PSECT2						;01
	.GLOBL	PSECTO
	.GLOBL	PSECTM
	.GLOBL	PSARGS						;08
	.GLOBL	FB
	.GLOBL	FB2						;01
	.GLOBL	FBF
	.GLOBL	FBB
	.GLOBL	FBORG
	.GLOBL	FBMAX

;
; TABLE SIZES
; CHANGABLE WITH IMPUNITY
;

.IIF	NDF	PSIZE	PSIZE	=	30.	;PSECT TABLE	;07
.IIF	NDF	FSIZE	FSIZE	=	300.	;BRANCH TABLE	;01-

;									;09+
; The following macros are used to build the permanent symbol table.
; Note that the table itself should be ordered so that the most
; frequently used symbols are found LAST in the table (so that
; their nodes are linked closest to the table root.  The pst is
; a linked list rooted in a "bucket".  The bucket size chosen here,
; 64, indicates that there should be about 3 entries in each bucket.
;
; Note: the macros were designed by a process popularly known as
; trial-and-error (or patch until it works).  You should be very
; careful about changing anything.
;
; The first four words of each PST node are identical to symbol-table
; nodes.  However, the PST does not have an S.U field.
;
; The following macros manage a "perfect hash" symbol table.  The
; sum of the letters of the symbol is used to determine an initial
; hash value.  Members of the same hash category are chained together.
;
; For debugging, the number of members of each hash category are
; recorded.
;
; The "bucket" parameter defines the number of hash buckets.
; It must be a power of 2.
;
bucket	=	64.			; Number of pst buckets
bmask	=	<bucket-1>		; Select initial bucket
;
; Set initial values of the link words and counters.
; This sequence sets ps.0, ps.1 etc to zero (the NULL link)
; and initializes counters pn.0, pn.1, etc.  At any point in
; the process, ps.N points to the head of the chain of nodes for
; the symbol whose name hashes to N, while pn.N counts the number
; of nodes in this hash bucket.
;
$	=	0			; '$' is a general counter
.rept	bucket
 .irp	z,<\$>
  ps.'z	=	0
  pn.'z =	0
 .endm
$	=	$+1
.endr

;
; Hash the name by summing all characters in the name.  This code
; obviously must track the run-time code in SRCPST.  The horsing around
; with nested .irp's is needed to generate the value of computed symbols.
;
.macro	hash	s,name			; Link in the name
$	=	0			; This will sum the characters
 .irpc	x,<s>				; For each character in name
  $	=	$ + ''x
 .endm
 $	=	$ & bmask		; '$' now names the hash entry
 .irp	z,<\$>
	.word	ps.'z			; S.L Link to previous
ps.'z	=	name			; Set new link
pn.'z	=	pn.'z+1			; Count links for this hash
 .endm
.endm	hash

;
; This macro writes the asciz text of each symbol to the psttxt
; program section, and a pointer to that string in the symbol table
; node itself.
;
.macro	set	s, n			; Store asciz symbol name
	.psect	psttxt
p'n:	.asciz	"s"
	.psect
	.word	p'n			; S.N -> "s"
.endm	set

;
; The psym macro builds each pst entry with an appropriate name, type,
; and value, calling the set and hash macros to perform necessary
; storage computations.  The pgen macro is needed to prevent uppercasing
; the symbol name on RSX macro.
;

.macro	psym	name, type, value	; Build a symbol.
pst...	=	pst...+1		; Count each symbol
	pgen	<name>, type, value, \pst...
.endm	psym

.macro	pgen	name, type, value, s	; .irp won't work on rsx
psy's:	hash	<name>,psy's		; S.L set link, set new link
	.word	value			; S.V
	.word	type			; S.T
	.word	0			; S.F (flags)
	set	<name>,s		; S.N Output string and pointer
.endm	pgen

;
; This macro is used to build symbol tables for .psects.
; Name must be in correct case.
;
	.macro	sym	name, type, value
	.word	value
	.word	type
	.word	0
	.ascii	"name"
	.nchr	n,name
	.if	gt,8.-n
	.rept	8.-n
	.byte	0
	.endr
	.endc
	.endm

;+
; ** SRCPST - SEARCH PST FOR MATCH. HASHED SEARCH			;09+
;
; INPUTS:
;	IDBUF = SYMBOL TO LOOK UP
;
; OUTPUTS:
;	R5 ==> NODE, CARRY CLEAR IF FOUND
;	CARRY SET IF NOT FOUND (R5 PRESERVED)
;
; R0-R4 PRESERVED
;-

SRCPST::
	jsr	r5,savreg		; Save all registers.
;
; Sum each letter of the symbol to generate the initial hash
;
	mov	#idbuf,r4		; r4 -> argument
.if ne	0				; (debug only)
	mov	r4,r0
	call	note
.iftf
	clr	r5			; r5 gets sum
10$:	movb	(r4)+,r0		; get each byte
	beq	20$			; exit at end
	add	r0,r5			; sum the byte
	br	10$			; and go for another
;
20$:	bic	#^C<bmask>,r5		; Sum .and. mask
	asl	r5			; make it an index
	mov	pst(r5),r5		; r5 -> first node in this chain
	beq	60$			; exit if none in this hash
;
30$:	mov	s.n(r5),r3		; r3 -> pst name
.ift
	mov	r3,r0
	call	note
.iftf
	mov	#idbuf,r4		; r4 -> test name
40$:	cmpb	(r3)+,(r4)		; Does it (still) match?
	bne	50$			; Try another if not
	tstb	(r4)+			; Yes, are we at the end?
	bne	40$			; Try another byte if not
	mov	r5,14(sp)		; Gotcha, set return for caller
	;clc				; (Equality cleared C-bit)
	return				; Restore registers and exit
;
50$:	mov	(r5),r5			; S.L -- Link to the next node
	bne	30$			; and test it if there is one.
60$:	sec				; Failed, set carry and
	return				; Return to caller.
.endc

;									;09+
; PST - Symbols should be ordered so that the most frequent are last
;
	PST... = 0				;03

	PSYM	<.ascii>,	ST.ASC,	000000	;03+
	PSYM	<.asciz>,	ST.ASZ,	000000
	PSYM	<.blkb>,	ST.BKB, 000000
	PSYM	<.blkw>,	ST.BKW, 000000
	PSYM	<.byte>,	ST.BYT, 000000
	PSYM	<.entry>,	ST.ENT, 000000
	PSYM	<.even>,	ST.EVN, 000000
	PSYM	<.flt2>,	ST.FL2, 000000
	PSYM	<.flt4>,	ST.FL4, 000000
	PSYM	<.globl>,	ST.GBL, 000000
	PSYM	<.limit>,	ST.LIM,	000000
	PSYM	<.ident>,	ST.IDN, 000000				;04
	PSYM	<.odd>,		ST.ODD, 000000
	PSYM	<.psect>,	ST.PST,	000000
	PSYM	<.word>,	ST.WRD, 000000
	PSYM	<absd>,		ST.SOP, 170600
	PSYM	<absf>,		ST.SOP, 170600
	PSYM	<adc>,		ST.SOP,	005500
	PSYM	<adcb>,		ST.SOP,	105500
	PSYM	<add>,		ST.DOP,	060000
	PSYM	<addd>,		ST.FLD, 172000
	PSYM	<addf>,		ST.FLD, 172000
	PSYM	<ash>,		ST.MUL, 072000
	PSYM	<ashc>,		ST.MUL, 073000
	PSYM	<asl>,		ST.SOP,	006300
	PSYM	<aslb>,		ST.SOP,	106300
	PSYM	<asr>,		ST.SOP,	006200
	PSYM	<asrb>,		ST.SOP,	106200
	PSYM	<bcc>,		ST.BR,	103000
	PSYM	<bcs>,		ST.BR,	103400
	PSYM	<bec>,		ST.BR,	103000
	PSYM	<beq>,		ST.BR,	001400
	PSYM	<bes>,		ST.BR,	103400
	PSYM	<bge>,		ST.BR,	002000
	PSYM	<bgt>,		ST.BR,	003000
	PSYM	<bhi>,		ST.BR,	101000
	PSYM	<bhis>,		ST.BR,	103000
	PSYM	<bic>,		ST.DOP,	040000
	PSYM	<bicb>,		ST.DOP,	140000
	PSYM	<bis>,		ST.DOP,	050000
	PSYM	<bisb>,		ST.DOP,	150000
	PSYM	<bit>,		ST.DOP,	030000
	PSYM	<bitb>,		ST.DOP,	130000
	PSYM	<ble>,		ST.BR,	003400
	PSYM	<blo>,		ST.BR,	103400
	PSYM	<blos>,		ST.BR,	101400
	PSYM	<blt>,		ST.BR,	002400
	PSYM	<bmi>,		ST.BR,	100400
	PSYM	<bne>,		ST.BR,	001000
	PSYM	<bpl>,		ST.BR,	100000
	PSYM	<bpt>,		ST.INH, 000003
	PSYM	<br>,		ST.BR,	000400
	PSYM	<bvc>,		ST.BR,	102000
	PSYM	<bvs>,		ST.BR,	102400
	PSYM	<call>,		ST.SOP,	004700
	PSYM	<callr>,	ST.SOP, 000100
	PSYM	<cfcc>,		ST.INH, 170000
	PSYM	<clc>,		ST.INH,	000241
	PSYM	<cle>,		ST.INH,	000241
	PSYM	<cln>,		ST.INH, 000250
	PSYM	<clr>,		ST.SOP,	005000
	PSYM	<clrb>,		ST.SOP,	105000
	PSYM	<clrd>,		ST.SOP, 170400
	PSYM	<clrf>,		ST.SOP, 170400
	PSYM	<clv>,		ST.INH,	000242
	PSYM	<clz>,		ST.INH,	000244
	PSYM	<cmp>,		ST.DOP,	020000
	PSYM	<cmpb>,		ST.DOP,	120000
	PSYM	<cmpd>,		ST.FLD, 173400				;05
	PSYM	<cmpf>,		ST.FLD, 173400				;05
	PSYM	<com>,		ST.SOP,	005100
	PSYM	<comb>,		ST.SOP,	105100
	PSYM	<dec>,		ST.SOP,	005300
	PSYM	<decb>,		ST.SOP,	105300
	PSYM	<div>,		ST.MUL,	071000
	PSYM	<divd>,		ST.FLD, 174400
	PSYM	<divf>,		ST.FLD, 174400
	PSYM	<emt>,		ST.EMT,	104000
	PSYM	<fadd>,		ST.RTS, 075000
	PSYM	<fdiv>,		ST.RTS, 075030
	PSYM	<fmul>,		ST.RTS, 075020
	PSYM	<fsub>,		ST.RTS, 075010
	PSYM	<halt>,		ST.INH,	000000
	PSYM	<inc>,		ST.SOP,	005200
	PSYM	<incb>,		ST.SOP,	105200
	PSYM	<iot>,		ST.INH,	000004
	PSYM	<jmp>,		ST.SOP,	000100
	PSYM	<jsr>,		ST.JSR,	004000
	PSYM	<ldcdf>,	ST.FLD, 177400
	PSYM	<ldcfd>,	ST.FLD, 177400
	PSYM	<ldcid>,	ST.FLD, 177000
	PSYM	<ldcif>,	ST.FLD, 177000
	PSYM	<ldcld>,	ST.FLD, 177000
	PSYM	<ldclf>,	ST.FLD, 177000
	PSYM	<ldd>,		ST.FLD, 172400
	PSYM	<ldexp>,	ST.FLD, 176400
	PSYM	<ldf>,		ST.FLD, 172400
	PSYM	<ldfps>,	ST.SOP, 170100
	PSYM	<mark>,		ST.MRK,	006400
	PSYM	<mfpd>,		ST.SOP,	106500
	PSYM	<mfpi>,		ST.SOP,	006500
	PSYM	<mfps>,		ST.SOP, 106700
	PSYM	<modd>,		ST.FLD, 171400
	PSYM	<modf>,		ST.FLD, 171400
	PSYM	<mov>,		ST.DOP,	010000
	PSYM	<movb>,		ST.DOP,	110000
	PSYM	<mtpd>,		ST.SOP,	106600
	PSYM	<mtpi>,		ST.SOP,	006600
	PSYM	<mtps>,		ST.SOP, 106400
	PSYM	<mul>,		ST.MUL,	070000
	PSYM	<muld>,		ST.FLD, 171000
	PSYM	<mulf>,		ST.FLD, 171000
	PSYM	<neg>,		ST.SOP,	005400
	PSYM	<negb>,		ST.SOP,	105400
	PSYM	<negd>,		ST.SOP, 170700
	PSYM	<negf>,		ST.SOP, 170700
	PSYM	<nop>,		ST.INH,	000240
	PSYM	<reset>,	ST.INH, 000005
	PSYM	<return>,	ST.INH,	000207
	PSYM	<rol>,		ST.SOP,	006100
	PSYM	<rolb>,		ST.SOP,	106100
	PSYM	<ror>,		ST.SOP,	006000
	PSYM	<rorb>,		ST.SOP,	106000
	PSYM	<rti>,		ST.INH,	000002
	PSYM	<rts>,		ST.RTS,	000200
	PSYM	<rtt>,		ST.INH, 000006
	PSYM	<sbc>,		ST.SOP,	005600
	PSYM	<sbcb>,		ST.SOP,	105600
	PSYM	<sec>,		ST.INH, 000261
	PSYM	<see>,		ST.INH,	000261
	PSYM	<sen>,		ST.INH, 000270
	PSYM	<setd>,		ST.INH, 170011
	PSYM	<setf>,		ST.INH,	170001
	PSYM	<seti>,		ST.INH, 170002
	PSYM	<setl>,		ST.INH, 170012
	PSYM	<sev>,		ST.INH,	000262
	PSYM	<sez>,		ST.INH, 000264
	PSYM	<sob>,		ST.SOB,	077000
	PSYM	<stcdf>,	ST.FST,	176000
	PSYM	<stcdi>,	ST.FST, 175400
	PSYM	<stcdl>,	ST.FST, 175400
	PSYM	<stcfd>,	ST.FST, 176000
	PSYM	<stcfi>,	ST.FST, 175400
	PSYM	<stcfl>,	ST.FST, 175400
	PSYM	<std>,		ST.FST, 174000
	PSYM	<stexp>,	ST.FST, 175000
	PSYM	<stf>,		ST.FST, 174000
	PSYM	<stfps>,	ST.SOP, 170200
	PSYM	<stst>,		ST.SOP, 170300
	PSYM	<sub>,		ST.DOP,	160000
	PSYM	<subd>,		ST.FLD,	173000
	PSYM	<subf>,		ST.FLD, 173000
	PSYM	<swab>,		ST.SOP,	000300
	PSYM	<sxt>,		ST.SOP,	006700
	PSYM	<sys>,		ST.EMT,	104000
	PSYM	<trap>,		ST.EMT, 104400
	PSYM	<tst>,		ST.SOP,	005700
	PSYM	<tstb>,		ST.SOP,	105700
	PSYM	<tstd>,		ST.SOP, 170500
	PSYM	<tstf>,		ST.SOP, 170500
	PSYM	<wait>,		ST.INH,	000001
	PSYM	<xor>,		ST.JSR,	074000	;03-

;
; The symbol table is built.  Compile the hash bucket so that each
; entry points to the first symbol in each hash chain.
;

$	=	0
link..	=	0			; Summary counter
pst::
.rept	bucket
 .irp	z,<\$>
  .irp	x,<\pn.'z>
	.word	ps.'z			; 'x links for hash value 'z
link..	=	link..+'x
  .endm
 .endm
  $	=	$+1
.endr
;
; And now for a little paranoia
;
.iif ne	<link..-pst...>	.error	; PST messed up, links don't sum	;09-

;
; PROGRAMME SECTION TABLE
; INITIALLY "c$code" ONLY
;

PSECT:	.WORD	PSECTO
PSECT2	=	PSECT + 2					;01
	SYM	<c$code>,	PF.REL+PF.BT3,	000000		;01/08
PSECTO:	.BLKB	PSIZE*14.
PSECTM:

;
; Psect attribute arguments.					;08+
;
PSARGS:	.BYTE	'd,PF.D		; Data space
	.BYTE	'i,0		; Instruction space (default)
	.BYTE	'r,PF.RO	; Read only
	.BYTE	'w,0		; Read-write (default)
	.BYTE	'g,PF.GBL	; Global scope
	.BYTE	'l,0		; Local scope (default)
	.BYTE	'o,PF.OVR	; Overlay
	.BYTE	'c,0		; Concatenate (default)
	.BYTE	0		; End of table
	.EVEN							;08-

;
; FBT
; INITIALISED AT RUNTIME
;

FB:	.WORD	FBORG
FB2	=	FB + 2						;01
FBORG:	.BLKB	FSIZE*4.
FBMAX:

FBF:	.BLKW	10.		;'F' LABEL POINTERS
FBB:	.BLKW	10.		;'B' LABEL POINTERS

	.END
