
/* monstart.c  --  start-up routine for XHM960 NINDY monitor environment */

#pragma option -ng

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

FILE _iob[FOPEN_MAX];			/* define the streams */
char **_environ = NULL;			/* the environment vector */
char _com_line[512] = {0};		/* the command line */

#define MAX_ARGC 32
static unsigned argc;			/* the argument count */
static char *argv[MAX_ARGC];		/* the argument vector */

int _stack_start = 0;			/* address of lowest byte of stack */

extern unsigned _sizeof_zerovars;
extern char *_startof_zerovars;
extern unsigned _sizeof_INITDATA;
extern char *_startof_INITDATA;

#pragma asm
	.sect	code,text,align 4
	.globl	mri_start
mri_start:
/*	mov	1,g13 */
/*	modpc	g13,g13,g13	*/	/* enable tracing */
/*	mov	g13,g13 */
	lda	__end,sp		/* highest address */
	lda	heapsize(sp),sp		/* allocate heap */
	call	init_frame		/* do a call to set up first frame */
	fmark				/* return to XRAY */

init_frame:
	mov	0,g14			/* initialize g14 */
	lda	0x3b001000,g13		/* initialize ac */
	lda	0xffffffff,g12
	modac	g12,g13,g13
	st	sp,__stack_start	/* for sbrk() error checking */
	mov	0,pfp			/* final frame for debugger */
	b	__mri_start
#pragma endasm

_mri_start(void)
	{
	memset(_startof_zerovars, 0, _sizeof_zerovars);
	initcopy();
	build_argv();
	initialize_stdio();
	main(argc, argv, _environ);
	exit(0);
	}

static initialize_stdio(void)
	{
	stdin->_file = 0;
	stdin->_flag = _IOREAD | _IONBF | _IOSTRG;  
	stdout->_file = 1;
	stdout->_flag = _IOWRT | _IONBF | _IOSTRG;  
	stderr->_file = 2;
	stderr->_flag = _IOWRT | _IONBF | _IOSTRG;
	}

static build_argv(void)
	{
	/* Constructs the argv array from the command line (_com_line). */

	char *line = _com_line;

	if (!*line)
		{
		argc = 1;
		argv[0] = "";
		return;
		}

	for (argc = 0; argc < MAX_ARGC; )
		{
		/* strip white space */
		while (*line == ' ' || (*line >= '\t' && *line <= '\r')) line++;
		if (*line == '\0') break;

		/* point to next token */
		argv[argc++] = line;

		/* skip over and terminate this token */
		while (    *line != '\0'
			&& *line != ' '
			&& !(*line >= '\t' && *line <= '\r')
		      ) line++; 
		if (*line == '\0') break;
		*line++ = '\0';
		}
	}

static initcopy(void)
	{
	/*
	Initialization routine to copy the initialized data to RAM  
	space based on organized information stored in the special
	section assigned through linker command INITDATA. 

	This routine will scan thorugh the section __INITDATA and copy
	data based on the special bytes indicated.  The content of
	this section consists the content of each individual input
	section specified in INITDATA command (i.e. even sections
	are specified as output section).  Special bytes are:
		Byte 'S' means the starting of a section;
		Byte 'C' means operation COPY;
		Byte 'E' means end of section;
		Four bytes after byte 'C' indicates the size of section;
		Subsequent four bytes that follows indicates the address 
		of copy destination.
	Returns:
		0 - Normal return
		1 - __INITDATA not initialized - No starting point
		2 - __INITDATA not initialized correctly - Unknown operation
	*/

	char *local;
	unsigned long size, dest;

	if (_sizeof_INITDATA <= 2)
		return(0);
	local = _startof_INITDATA;
	if (*local != 'S')
		return(1);
	local++;
	while (*local != 'E')
		switch (*local)
		{
		case 'C':
			local++;
			size = (unsigned long)(((unsigned char)*local) |
					((unsigned char)*(local+1) << 8) |
					((unsigned char)*(local+2) << 16) |
					(unsigned char)*(local+3) << 24);
			local += 4;
			dest = (unsigned long)(((unsigned char)*local) |
					((unsigned char)*(local+1) << 8) |
					((unsigned char)*(local+2) << 16) |
					(unsigned char)*(local+3) << 24);
			local += 4;
			memcpy ((void *)dest, (void *)local, (size_t)size);
			local += size;
			break;
		default:
			return(2);
		}
	return(0);
	}
;
#pragma asm
			.sect	__INITDATA,data,align 4
			.sect	zerovars,data,align 4
			.sect	code,text,align 4
__sizeof_zerovars:	.word	sizeof zerovars
__startof_zerovars:	.word	startof zerovars
__sizeof_INITDATA:	.word	sizeof __INITDATA
__startof_INITDATA:	.word	startof __INITDATA

			/*
			The heap section must be the last new section name
			encountered by the linker.  This ensures that it
			will be given the highest address in the program.
			*/
			.sect	heap,data,align 4
			.globl	__end
__end:
			.space	4

			.end	mri_start	/* mri_start is entry point */
#pragma endasm

