| C startup 		-- Steve Ward 1/80
|			-- modified for Now Machine Larry Allen 10/6/83
|
| Defined globals:
|
|	START()			startup entry point
|	long lmul(a,b)		long multiply
|				 to return val.

| Undefined globals:
|	main()			main C entry point


	.insrt	"maclib.a68"
	.insrt	"iotech.a68"
	.insrt	"system.a68"

	.text
	.globl	START$, main, exit


| Main entry point; entered at prio 7 from boot.  Stack is underneath
| code; must save enough room at ld68 time.

START$:
stack	=	.
	movl	#stack,sp	| initialize stack pointer
	io_init$		| reinit io system
	movl	a0,sp@-
	movl	a0,sp@-
	jsr	main		| call user program
	jra	exit		| ... which should never return.

| long multiply routine: c = a*b (unsigned, for now...)

	.globl	lmul
lmul:	movl	d1,sp@-		| save d1.
	clrl	d0
	movw	sp@(10),d0	| alo, unsigned.
	mulu	sp@(14),d0	| alo*blo, unsigned.

	clrl	d1
	movw	sp@(8),d1	| ahi, unsigned
	mulu	sp@(14),d1	| ahi*blo, unsigned
	swap	d1		| use just the low portion...
	clrw	d1		| clear the unused half.
	addl	d1,d0

	clrl	d1		| similar, for bhi*alo
	movw	sp@(12),d1
	mulu	sp@(10),d1
	swap	d1
	clrw	d1
	addl	d1,d0

	movl	sp@+,d1		| restore & return.
	rts

| Integer divide routine: c=a/b. short = long/short, signed

	.globl	ldiv
ldiv:	movl	d1,sp@-		| save d1.
	clrl	d0
	movl	sp@(8),d0	| a, long.
	divs	sp@(14),d0	| divide by blo
	extl	d0		| sign-extend quotient
	movl	sp@+,d1		| restore & return.
	rts

| similar, but returns signed remainder.

	.globl	lrem
lrem:	movl	d1,sp@-		| save d1.
	clrl	d0
	movl	sp@(8),d0	| a, long.
	divs	sp@(14),d0	| divide by blo
	asrl	#8,d0
	asrl	#8,d0		| access remainder.
	movl	sp@+,d1		| restore & return.
	rts

| Return to ROM debugger:

exit:	movl	#10000,d1	| loop for a while
ex1:	subql	#1,d1
	jgt	ex1
	movl	#USER_ENTRY,a0
	jmp	a0@		| enter ROM bootstrap

	.globl	rte
rte:	rte

| set priority level to 0:

	.globl	spl0
spl0:	movw	sr,d0		| get program status register
	andw	#~PS_PR$M,d0	| set priority to zero
	movw	d0,sr		| put it back.
	rts

| set priority level to 7:

	.globl	spl7
spl7:	movw	sr,d0
	orw	#PS_PR$M,d0
	movw	d0,sr
	rts

| Output character (on stack) to both serial ports.
| Calling sequence:
|	putchar(c)
|	char c;

	.globl	putchar

c	=	4		| character
LF	=	0x0a

putchar:
	movl	sp@(c),d0	| pick it up
	cmpb	#LF,d0
	jne	nocr
	putchar$	#CR
nocr:
	putchar$	d0	| put it out
	rts


| getchar gets a character from either serial port, echos it, strips it
| to seven bits, and returns it.
| Calling sequence:
|	int	getchar()

	.globl	getchar

getchar:
	getchar$
	andl	#0x7F,d0
	putchar$	d0
	rts


| getchar_image is like getchar but returns the raw character without echoing
| it.  Calling sequence:
|	int	getchar_image()

	.globl	getchar_image

getchar_image:
	getchar$
	andl	#0xFF,d0	| make sure it's > 0
	rts


| pendchar checks to see whether a character is available on either port;
| it returns TRUE if so.  Calling sequence:
|	int	pendchar()

	.globl	pendchar

pendchar:
	clrl	d0		| sne only sets low byte...
	pendchar$
	sne	d0
	rts

	.globl	inittm0
inittm0:
	inittm0$
	rts

arg1	=	4

	.globl	settm0
settm0:
	movw	sp@(arg1),d0
	settm0$	d0
	rts

	.globl	gettm0
gettm0:
	gettm0$
	rts

	.globl	tm0tst
tm0tst:
	movl	#IOTECH+TIMER+TMR0,d0
	rts

	.globl	lswap
lswap:
	movb	#0,d0
 	movb	sp@(arg1+3),d0
	roll	#8,d0
	movb	sp@(arg1+2),d0
	roll	#8,d0
	movb	sp@(arg1+1),d0
	roll	#8,d0
	movb	sp@(arg1),d0
	rts

	.end	START$
