CSa32/Debug.S
changeset 0 5c129dd80d4f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CSa32/Debug.S	Thu Nov 21 14:55:10 2019 +0100
@@ -0,0 +1,273 @@
+	.include "DS.S"
+#-----------------------------------------------
+#	A B S T R A C T  S T R U C T U R E S
+#-----------------------------------------------
+#-----------------------------------------------
+#	S T A T I C   V A R I A B L E S
+#-----------------------------------------------
+	.data
+D.t0:	.int	0				# initial timestamp in usecs
+D.semP:	.int	0				# -->semaphore for debug output
+	.globl	D.prgNameP
+D.prgNameP:
+	.int	0				# -->prog name
+#-----------------------------------------------
+#	D E B U G   I N I T
+#-----------------------------------------------
+# initialize static debug vars
+	ARGS
+ 	DS	prgP				# -->program name
+# returns:	nothing
+	PROLOC
+	EPILOC
+#-----------------------------------------------
+	.text
+	.global D.init
+D.init:
+	PROLOG
+	push	prgP(bp)
+	call	strlen
+	inc	a
+	push	a
+	call	malloc
+	mov	a, D.prgNameP			# save -->prog name for debugging
+	push	prgP(bp)
+	push	a
+	call	strcpy
+	movl	$0, D.t0
+	call	D.getTs				# get actual time - t0 = actual time
+	mov	a, D.t0				# set t0 to actual time
+
+	jmp	3f
+	push	$0
+	push	$t
+	call	gettimeofday			# get initial timestamp t0
+	cmp	$0, a
+	jz	0f
+	ERR	"gettimeofday"
+0:	lea	t, b				# compute (1000000*secs+usecs)
+	mov	secs(b), c
+	mov	$1000000, a
+	mul	c				# 1000000*secs
+	add	usecs(b), a			# 1000000*secs+usecs
+	movl	a, D.t0				# save low 32 bits of timestamp in t0
+3:
+	push	$0				# allocate semaphore for debug output
+	push	$-1
+	push	$0x21				# PROT_READ | PROT_WRITE
+	push	$0x03				# MAP_SHARED | MAP_ANONYMOUS
+	push	$16				# semaphore size
+	push	$0
+	call	mmap				# get shared storage for semaphore
+	cmp	$-1, a
+	jne	0f
+	ERR	"mmap"
+0:	mov	a, D.semP			# save -->semaphore
+
+	push	$1				# initial semaphore value
+	push	$1				# semaphore shared between processes
+	pushl	D.semP
+	call	sem_init			# initialize semaphore
+	cmp	$0, a
+	jz	0f
+	ERR	"sem_init of debug semaphore"
+0:
+	EPILOG
+#-----------------------------------------------
+#	S E T   D E B U G   I D
+#-----------------------------------------------
+# sets debug ID according to format
+	ARGS
+ 	DS	deP 				# -->Debug instance
+	DS	argc				# # of values to be put into deb ID
+	DS	formP				# -->format
+#	...					# values
+# returns:	nothing
+	PROLOC
+	EPILOC
+#-----------------------------------------------
+	.global D.setId
+D.setId:
+	PROLOG
+# format debug ID
+	mov	argc(bp), c			# no. of values
+0:	mov	formP(bp,c,4), a		# push values and format
+	push	a
+	dec	c
+	jns	0b				# iterate on values
+	pushl	$D.idL				# max deb ID len
+	mov	deP(bp), b			# -->Debug instance
+	lea	D.id(b), a			# -->DebId
+	push	a
+	call	snprintf			# construct DebId
+	cmp	$0, a
+	jnl	0f
+	ERR	"DEBID snprintf"
+0:
+	LOG	6, "debid '%s' set", 1
+	EPILOG
+#-----------------------------------------------
+#	P R I N T   D E B U G   M S G
+#-----------------------------------------------
+# outputs to stderr the synchronized debug msg with time diff from program start
+# 	on appripriate debug level, flushes stderr
+	ARGS
+	ac = 40
+ 	DS	deP 				# -->Debug instance
+ 	DS	level				# msg debug level
+	DS	argc				# # of values to be used in msg
+	DS	form				# -->format
+#	...					# values
+# returns:	nothing
+	PROLOC
+	ac = 0
+	EPILOC
+#-----------------------------------------------
+	.global D.log
+D.log:
+	PROLOG
+
+	mov	C.csP, c
+	mov	level(bp), a			# msg debug level
+	cmp	C.debMaxLev(c), a		# max debug level >= msg debug level ?
+	jg	3f				# nothing to print, leave
+	cmp	$7, C.debMaxLev(c)		# on max debug level = 7 print level 7 only
+	jne	0f
+	cmp	$7, a				# msg debug level = 7 ?
+	jne	3f
+# prepare output string of msg
+0:	mov	argc(bp), c			# no. of values
+0:	mov	form(bp,c,4), a			# copy values and format
+	push	a
+	dec	c
+	jns	0b
+	push	$D.msgL				# msg buffer len
+	mov	deP(bp), b			# -->Debug instance
+	lea	D.msg(b), a			# -->msg buffer
+	push	a
+	call	snprintf			# construct msg in buffer
+	cmp	$0, a
+	jnl	0f
+	ERR	"LOG snprintf"
+# synchronize with other tasks
+0:	pushl	D.semP
+	call	sem_wait			# synchronize
+	cmp	$0, a
+	jz	0f
+	ERR	"LOG sem_wait"
+# get timestamp
+0:	call	D.getTs				# time from beg of program in usecs
+# print debug msg
+	mov	deP(bp), b			# -->Debug instance
+	lea	D.msg(b), c			# -->msg text
+	push	c
+	lea	D.id(b), c			# -->instance debug ID
+	push	c
+	push	a				# tdiff in usecs
+	push	$1f
+	push	stderr
+	call	fprintf
+	jmp	2f
+1:	.ascii	"%09u %s: %s\n\0"
+# flush stderr
+2:	push	stderr
+	call	fflush				# flush stderr
+# free semaphore
+	pushl	D.semP
+	call	sem_post			# free semaphore
+	cmp	$0, a
+	jz	3f
+	ERR	"LOG sem_post"
+3:
+	EPILOG
+#-----------------------------------------------
+#	G E T   T I M E S T A M P   I N   U S E C S
+#-----------------------------------------------
+# returns timestamp in usecs from beg of program
+# returns:	int value
+	PROLOC
+	DL	t, timevalL			# timestamp buffer
+	EPILOC
+#-----------------------------------------------
+	.global D.getTs
+D.getTs:
+	PROLOG
+	push	$0
+	lea	t(bp), b			# -->timeval buffer
+	push	b
+	call	gettimeofday
+# compute time delta from program start = t-t0 in usecs
+# tdiff = (1000000*ts.secs+ts.usecs)-t0
+	lea	t(bp), b			# actual timestamp
+	mov	secs(b), c			# t.secs
+	mov	$1000000, a
+	mul	c				# 1000000*t.secs
+	add	usecs(b), a			# 1000000*t.secs+t.usecs
+	sub	D.t0, a				# 1000000*t.secs+t.usecs-t0
+	EPILOG_R
+#-----------------------------------------------
+#	S U B R O U T I N E S   L I S T
+#-----------------------------------------------
+# print subroutines names and addresses
+# localize address from env ADDR= in subroutine
+	PROLOC
+	DL	wAddr				# wanted addr
+	EPILOC
+#-----------------------------------------------
+	.global	 D.subr
+D.subr:
+	PROLOG
+	movl	$0, wAddr(bp)
+	pushl	$0f
+	call	getenv				# get env ADDR
+	lea	4(sp), sp
+	jmp	1f
+0:	.ascii "ADDR\0"
+1:	cmp	$0, a
+	jz	0f				# no addr wanted
+	pushl	$16
+	pushl	$0
+	push	a
+	call	strtol				# convert str to hex
+	lea	12(sp), sp
+	mov	a, wAddr(bp)			# searched addr
+0:
+	pushl	$0				# end of list
+	SUBRLIST				# print and push list of subroutines
+	cmp	$0, wAddr(bp)			# address wanted ?
+	je	D.subrR
+	mov	wAddr(bp), d
+	mov	sp, b				# -->beg of subr list
+	xor	a, a
+	jmp	1f
+0:	lea	8(b), b
+1:	cmpl	$0, (b)				# end of list ?
+	je	2f				# yes
+	cmp	4(b), d				# -->subr > wanted addr ?
+	jb	0b				# yes, next
+	cmp	4(b), a				# -->subr > last found ?
+	jnb	0b				# no, next
+	mov	(b), c				# get subr name
+	mov	4(b), a				# get subr addr
+	jmp	0b				# next
+2:	test	a, a
+	jnz	1f
+	push	d
+	push	$0f
+	push	stderr
+	call	fprintf
+	jmp	D.subrR
+0:	.ascii	"addr %p not found in subroutines\n\0"
+1:	sub	a, d
+	push	d				# offset in subr
+	push	c				# subroutine name
+	pushl	wAddr(bp)			# wanted addr
+	push	$0f
+	push	stderr
+	call	fprintf
+	jmp	D.subrR
+0:	.ascii	"searched addr %p in subroutine %s at offset %x\n\0"
+D.subrR:
+	EPILOG
+#-----------------------------------------------
+	.end