	.equ	a, %eax
	.equ	b, %ebx
	.equ	c, %ecx
	.equ	d, %edx
	.equ	bp, %ebp
	.equ	sp, %esp
	.equ	di, %edi
#-----------------------------------------------
#	M A C R O   D E C L A R A T I O N S
#-----------------------------------------------
# subroutines list
	.macro	SUBRLIST
	SUBR	_start
	SUBR	D.init
	SUBR	D.setId
	SUBR	D.log
	SUBR	D.getTs
	SUBR	D.subr
	SUBR	Node
	SUBR	N.bind
	SUBR	N.conn
	SUBR	N.acc
	SUBR	N.closeSocket
	SUBR	N.read
	SUBR	N.write
	SUBR	N.get
	SUBR	N.put
	SUBR	N.sslErr
	SUBR	Data
	SUBR	Da.load
	SUBR	Da.chk
	SUBR	Da.unl
	SUBR	Da.dttl
	SUBR	Da.ttl
	SUBR	Da.getTs
	.endm
#-----------------------------------------------
# push subroutine addr, prints its name and addr
# leave subr name and addr on stack
	.macro	SUBR	subr:req
	push	$\subr
	push	$9f
	push	$8f
	push	stderr
	call	fprintf
	jmp	7f
9:	.asciz	"\subr"
8:	.asciz	"%-12s\t%p\n"
7:	lea	8(sp), sp
	.endm
#-----------------------------------------------
# prepare to define subroutine args; use macro DS to define args
	.macro	ARGS
	ac = 40
	.endm
#-----------------------------------------------
# prepare to define subroutine args; use macro DS to define args
	.macro	M_ARGS
	ac = 40
	DS	thisP
	.endm
#-----------------------------------------------
# declare storage
	.macro	DS	id:req, len=4
	\id = ac
	ac = ac + \len
	.endm
#-----------------------------------------------
# prepare to define subroutine local vars
	.macro	PROLOC
	ac = 0
	.endm
#-----------------------------------------------
# prepare to define subroutine local vars
	.macro	M_LOCAL
	ac = 0
	DL	deP
	.endm
#-----------------------------------------------
# declare local var
	.macro	DL	id:req, len=4
	ac = ac + \len
	\id = -ac
	.endm
#-----------------------------------------------
# terminate subroutine local vars definition
	.macro	EPILOC
	locL = ac
	.endm
#-----------------------------------------------
# subroutine prolog
# expects length of local storage under the name "locL"
	.macro	PROLOG
	pusha
	enter	$locL, $0
	.endm
#-----------------------------------------------
# subroutine prolog
# expects length of local storage under the name "locL"
	.altmacro
	.macro	M_PROLOG	m_prefix:req, m_name:req
	.global	\m_prefix\().\m_name
\m_prefix\().\m_name:
	pusha
	enter	$ac, $0
	mov	thisP(bp), b
	lea	\m_prefix\().debug(b), a
	mov	a, deP(bp)
	.endm
	.noaltmacro
#-----------------------------------------------
# subroutine epilog without return value
	.macro	EPILOG
	leave
	popa
	ret
	.endm
#-----------------------------------------------
# subroutine epilog with return value in EAX
# expects length of local storage under the name "locL"
	.macro	EPILOG_R
	leave
	mov	a, 28(sp)
	popa
	ret
#	mov	-36(sp), a
	.endm
#-----------------------------------------------
# ABEND at system routine err
	.macro	ERR	causer:req
	pushl	$9f
	call	printf
	pushl	$1
	call	exit
9:	.asciz	"\causer: %m\n"
	.endm
#-----------------------------------------------
# ABEND at system routine err using debug structure
# expects deP(bp)-->Debug inst
	.macro	SYSERR	causer:req
	push	$9f				# -->format
	push	$0				# no. of values
	push	$0				# msg debug level
	pushl	deP(bp)				# -->Debug instance
	call	D.log				# print msg
	call	C.abend
9:	.asciz	"\causer: %m"
	.endm
#-----------------------------------------------
# print SSL err msg queue and then abend
# -->Debug in deP(bp) is expected
	.macro	SSLERR	msg:req
	pushl	$9f
	pushl	deP(bp)
	call	N.sslErr
9:	.asciz	"\msg"
	.endm
#-----------------------------------------------------------
	.macro	SYS	name:req
	call	\name
	cmp	$-1, a
	jne	8f
	SYSERR	"\name"
8:	mov	thisP(bp), b
	test	a, a
	.endm
#-----------------------------------------------
# get integer value from ENV
	.macro	GETINTENV key:req
	pushl	$9f
	call	C.getArg
	lea	4(sp), sp
	cmp	$0, a
	jmp	8f
9:	.asciz	"\key"
8:
	.endm
#-----------------------------------------------
# set local debug ID
# supposed: local deP-->Debug
# expected on the stack:
#	\argc values to be put in debug ID according to format
# \argc may be zero
	.macro	DEBID	format:req, argc=0
	push	$9f				# -->format
	push	$\argc				# no. of values
	pushl	deP(bp)				# -->Debug instance
	call	D.setId				# put debug ID to Debug inst
	jmp	8f
9:	.asciz	"\format"
8:	lea	12(sp), sp
	.endm
#-----------------------------------------------
# debug output
# supposed: local deP-->Debug
# expected on the stack:
#	\argc values to be printed by \format at debug level \level
# \argc may be zero
# all regs are preserved
	.macro LOG	level:req, format:req, argc=7
	push	$9f				# -->format
	push	$\argc				# no. of values
	push	$\level				# msg debug level
	pushl	deP(bp)				# -->Debug instance
	call	D.log		 		# print msg
	jmp	8f
9:	.asciz	"\format"
8:	lea	16(sp), sp
	.endm
#-----------------------------------------------
# flat print
# sp, bp are preserved
	.macro	PR	format:req
	push	$9f
	push	stderr
	call	fprintf
	jmp	8f
9:	.asciz	">>> \format\n"
8:	lea	8(sp), sp
	.endm
#-----------------------------------------------
# print ip, bp, sp before subroutine call
# to be placed directly before a call instruction
# expected deP(bp) as -->Debug
# all regs are preserved
	.macro	B_CALL	level:req, label="BEFORE SUBR CALL "
	push	a
	lea	4(sp), a
	push	a
	push	bp
	pushl	$7f+5
	LOG	\level, "\label: ip: %p, bp: %p, sp: %p", 3
	lea	12(sp), sp
	pop	a
	jmp	7f
7:
	.endm
#-----------------------------------------------
# print ip, bp, sp saved in sburoutine's stack frame
# to be placed anywhere before return seq and after deP(bp) is set
# expected deP(bp) as -->Debug
# all regs are preserved
	.macro	B_RET	level:req, label="BEFORE SUBR RETURN"
	push	a
	lea	8(bp), a
	push	a
	push	(bp)
	push	4(bp)
	LOG	\level, "\label: ip: %p, bp: %p, sp: %p", 3
	lea	12(sp), sp
	pop	a
	jmp	7f
7:
	.endm
#-----------------------------------------------
# print ip, bp, sp retained for return from sburoutine
# all regs are preserved
	.macro	A_CALL	label="AFTER  CALL"
	pusha
	lea	8(bp), a
	push	a
	push	(bp)
	push	4(bp)
	pushl	$9f
	call	printf
	lea	16(sp), sp
	popa
	jmp	8f
9:	.asciz	"\label: ip: %p, bp: %p, sp: %p\n"
8:
	.endm
#-----------------------------------------------
	.macro SLEEPER	time:req, ident=">>>"
	pusha
	LOG	7, "\ident: sleeping \time"
	pushl	$\time
	call	sleep
	lea	4(sp), sp
	LOG	7, "\ident: woken up"
	popa
	.endm
#-----------------------------------------------
#	A B S T R A C T   D A T A   D E C L A R A T I O N S
#-----------------------------------------------
# 	rSA	reg save area
	ac = 0
	DS	retSA
	DS	regSA, 32
	DS	bpSA
	rSAL = ac
#-----------------------------------------------
# 	Timeval
	ac = 0
	DS	secs
	DS	usecs
	timevalL = ac
#-----------------------------------------------
#	AddrInfo		IP family net addr block
	ac = 0
	DS	ai_flags
	DS	ai_family
	DS	ai_socktype
	DS	ai_protocol
	DS	ai_addrlen
	DS	ai_addrP	# -->sockaddr
	DS	ai_canonnameP
	DS	ai_nextP
	AddrInfoL = ac
#-----------------------------------------------
	SIGUSR2 = 12
	SIG_IGN = 1
	SIG_UNBLOCK = 1
#	sigaction		signal handler definition
	ac = 0
	DS	sa_handler
	DS	sa_mask, 128
	DS	sa_flags
	DS	sa_unused
	SigActionL = ac
#-----------------------------------------------
#	SockAddr
	ac = 0
	DS	sa_family, 2
	DS	sa_data, 14
	SockAddrL = ac
#-----------------------------------------------
# 	timeval struct
	ac = 0
	DS	Ti.secs
	DS	Ti.usecs
	timevalL = ac
#-----------------------------------------------
#	Debug		debug info
	ac = 0
	D.idL = 128
	DS	D.id, D.idL			# debug ID of process
	D.msgL = 256
	DS	D.msg, D.msgL			# debug msg workspace
	DebugL = ac

	.macro	DebugA				# returns -->Debug
	push	$DebugL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:	movl	$0, D.id(a)
	.endm
#-----------------------------------------------
#	CS		top level attributes
	ac = 0
	DS	C.debug, DebugL
	DS	C.debMaxLev			# max level of debug msgs to be printed
	DS	C.txtP				# -->text to be sent in messages
	DS	C.ttl				# TTL for circulating msgs
	DS	C.mp0				# TCP port of first mash node
	DS	C.mn				# intended # of nodes in mash
	DS	C.rp0				# TCP port of first ring node
	DS	C.rn				# intended # of nodes in ring
	DS	C.pace.tv_sec			# timespec.tv_sec
	DS	C.pace.tv_nsec			# timespec.tv_nsec
	DS	C.pacing			# pacing indicator
#	DS	C.rs				# random() seed
	DS	C.ssl				# ssl mask: 01B=noSSL, 10B=SSL, 11B=both
	DS	C.connTh			# connection retry threshhold
	DS	C.shP				# -->shared counters
	DS	C.pathP				# -->pathname to application home dir
	DS	C.cePathP			# -->pathname to SSL dir
	DS	C.caPathP			# -->pathname to SSL CA CERT dir
	CSL = ac

	.macro	CSA				# returns -->CS
	push	$CSL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:
	.endm
#-----------------------------------------------
# 	Share		counters shared between procs or threads
	ac = 0
	DS	S.counter_sem, 16		# semaphore for counters
	DS	S.conns				# overall connections counter both in ring and mash
	DS	S.msgs				# overall forewards# both in ring and mash
	DS	S.act				# active node processes counter
	DS	S.mash_open_client_count	# no. of opened clients in mash
	DS	S.mash_open_SSL_client_count	# no. of opened SSL clients in mash
	ShareL = ac

	.macro ShareA				# returns -->Share
	push	$0
	push	$-1
	push	$0x21				# PROT_READ | PROT_WRITE
	push	$0x03				# MAP_SHARED | MAP_ANONYMOUS
	push	$ShareL
	push	$0
	call	mmap
	cmp	$-1, a
	jne	8f
	SYSERR	"mmap"
8:
	.endm
#-----------------------------------------------
# Data - container for data sent through connection topology
#	Container Header
	ac = 0
	DS	H.ttl				# msg TTL
	DS	H.ts				# timestamp
	DS	H.lport				# listening TCP port
	HeaderL = ac
#	Container Payload
	ac = 0
#	Pa.loadL = 256
	DS	Pa.ts				# timestamp
	DS	Pa.text, 0			# load sent in msg
	PayloadL = ac
#	Container to be send
	ac = 0
	DS	Co.hdr, HeaderL			# Header
	DS	Co.payl, PayloadL		# Payload
#	ContainerL = ac
# 	Data instantion
	ac = 0
	DS	Da.debug, DebugL		# Debug
	DS	Da.contP			# -->Container
	DS	Da.datalen			# container length
	DataL = ac

	.macro	DataA				# returns -->Data
	push	$DataL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:
	.endm
#-----------------------------------------------
#	Node		general attributes of node
	ac = 0
	DS	N.debug, DebugL			# debug info
	DS	N.cnstlnP			# -->Constellation block
	DS	N.topo				# constellation topology
	DS 	N.locPort			# TCP port node binds to
	DS	N.first				# port # of first node in constellation
	DS	N.last				# port # of last node in constellation
	DS	N.nodes				# number of nodes
	DS	N.div				# random node choise divisor (MAX_INT / nodes)
	DS	N.kicker			# kicker indicator
	DS	N.forwP				# -->shared forward indicator
	DS	N.closing			# closing in progress indicator
	DS	N.ssc				# server side socket
	DS	N.data, DataL			# data block
	DS	N.dataP				# -->data block
	DS	N.srvSideP			# -->array of server side Sockets
	DS	N.cliSideP			# -->array of client side Sockets
	DS	N.sockArrLen			# socket array length
	DS	N.next				# next node's port#
	DS	N.nfds				# highest FD# in FD sets
	DS	N.rs, 128			# read FD set
	DS	N.es, 128			# exceptional FD set
	DS	N.t, timevalL			# timeval for select
	DS	N.ssl				# SSL switch: 0=noSSL, 1=SSL
	DS	N.ctxP				# -->SSL context
	DS	N.pid				# process ID
	DS	N.ptid				# closing thread ID
	NodeL = ac

	.macro	NodeA				# returns -->Node
	push	$NodeL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:
	.endm
#-----------------------------------------------
#	SocketInfo	comm socket info
	ac = 0
	DS	So.remPort			# TCP port on remote site
	DS	So.sc				# comm socket#
	DS	So.sslP				# -->SSL structure
	SocketInfoL = ac

	.macro	SocketA				# returns -->Socket
	push	$SocketL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:
	.endm
#-----------------------------------------------
#	Constellation	attributes of constellation of nodes (mash or ring)
	ac = 0
	DS	Cn.debug, DebugL		# debug info
	DS	Cn.topo				# Constellation topology
		Cn.ring = 0
		Cn.mash = 1
	DS	Cn.first
	DS	Cn.nodes
	DS	Cn.div				# random node choise divisor (MAX_INT / nodes)
	DS	Cn.ssl
	DS	Cn.forwP
	ConstellationL = ac

	.macro	ConstellationA			# returns -->Constellation
	push	$ConstellationL
	call	malloc
	cmp	$0, a
	ja	8f
	SYSERR	"malloc"
8:
	.endm
