202 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
	Startup routines
 | 
						|
*/
 | 
						|
 | 
						|
/* $Header$ */
 | 
						|
 | 
						|
#include	<stdio.h>
 | 
						|
 | 
						|
#include	<em_abs.h>
 | 
						|
#include	"logging.h"
 | 
						|
#include	"global.h"
 | 
						|
#include	"log.h"
 | 
						|
#include	"alloc.h"
 | 
						|
#include	"warn.h"
 | 
						|
#include	"mem.h"
 | 
						|
#include	"shadow.h"
 | 
						|
#include	"trap.h"
 | 
						|
#include	"read.h"
 | 
						|
 | 
						|
 | 
						|
/****************************************************************
 | 
						|
 *	The EM-machine is not implemented as a contiguous	*
 | 
						|
 *	piece of memory. Instead there are a number of		*
 | 
						|
 *	"floating" pieces of memory, each representing a	*
 | 
						|
 *	specific part of the machine. There are separate	*
 | 
						|
 *	allocations for:					*
 | 
						|
 *		- stack and local area (stack),			*
 | 
						|
 *		- heap area & global data area (data),		*
 | 
						|
 *		- program text & procedure descriptors (text).	*
 | 
						|
 *	The names in parenthesis are the names of the global	*
 | 
						|
 *	variables used within our program, pointing to		*
 | 
						|
 *	the beginning of such an area. The sizes of the global	*
 | 
						|
 *	data area and the program text can be determined	*
 | 
						|
 *	once and for all in the "rd_header" routine.		*
 | 
						|
 ****************************************************************/
 | 
						|
 | 
						|
extern char **environ;
 | 
						|
 | 
						|
PRIVATE ptr storestring();
 | 
						|
PRIVATE size alignedstrlen();
 | 
						|
 | 
						|
char *load_name;
 | 
						|
 | 
						|
init(ac, av)
 | 
						|
	int ac;
 | 
						|
	char **av;
 | 
						|
{
 | 
						|
	register char **p;
 | 
						|
	register size env_vec_size;	/* size of environ vector */
 | 
						|
	register size arg_vec_size;	/* size of argument vector */
 | 
						|
	register size string_size = 0;	/* total size arg, env, strings */
 | 
						|
	register ptr ARGB, vecp, strp;
 | 
						|
	
 | 
						|
	init_ofiles(1);			/* Initialize all output files */
 | 
						|
	init_signals();
 | 
						|
 | 
						|
	/* Read the load file header, to obtain wsize and psize */
 | 
						|
	load_name = av[0];
 | 
						|
	rd_open(load_name);		/* Open object file */
 | 
						|
 | 
						|
	rd_header();			/* Read in load file header */
 | 
						|
 | 
						|
	/* Initialize wsize- and psize-dependent variables */
 | 
						|
 | 
						|
	init_rsb();
 | 
						|
	i_minsw = (wsize == 2) ? I_MINS2 : I_MINS4;
 | 
						|
	i_maxsw = (wsize == 2) ? I_MAXS2 : I_MAXS4;
 | 
						|
	i_maxuw = (wsize == 2) ? I_MAXU2 : I_MAXU4;
 | 
						|
	max_addr = i2p(((psize == 2) ? I_MAXU2 : I_MAXS4) / wsize * wsize) - 1;
 | 
						|
	min_off = (psize == 2) ? (-MAX_OFF2-1) : (-MAX_OFF4-1);
 | 
						|
	max_off = (psize == 2) ? MAX_OFF2 : MAX_OFF4;
 | 
						|
 | 
						|
	/* Determine nr of bytes, needed to store arguments/environment */
 | 
						|
 | 
						|
	env_vec_size = 0;		/* length of environ vector copy */
 | 
						|
	for (p = environ; *p != (char *) 0; p++) {
 | 
						|
		string_size += alignedstrlen(*p);
 | 
						|
		env_vec_size += psize;
 | 
						|
	}
 | 
						|
	env_vec_size += psize;		/* terminating zero */
 | 
						|
 | 
						|
	arg_vec_size = 0;		/* length of argument vector copy */
 | 
						|
	for (p = av; *p != (char *) 0; p++) {
 | 
						|
		string_size += alignedstrlen(*p);
 | 
						|
		arg_vec_size += psize;
 | 
						|
	}
 | 
						|
	arg_vec_size += psize;		/* terminating zero */
 | 
						|
 | 
						|
	/* One pseudo-register */
 | 
						|
	ARGB = i2p(SZDATA);		/* command arguments base */
 | 
						|
 | 
						|
	/* Initialize segments */
 | 
						|
	init_text();
 | 
						|
	init_data(ARGB + arg_vec_size + env_vec_size + string_size);
 | 
						|
	init_stack();
 | 
						|
	init_FRA();
 | 
						|
	init_AB_list();
 | 
						|
 | 
						|
	/* Initialize trap registers */
 | 
						|
	TrapPI = 0;			/* set Trap Procedure Identifier */
 | 
						|
	OnTrap = TR_ABORT;		/* there cannot be a trap handler yet*/
 | 
						|
	IgnMask = PreIgnMask;		/* copy Ignore Mask from preset */
 | 
						|
 | 
						|
	/* Initialize Exit Status */
 | 
						|
	ES_def = UNDEFINED;		/* set Exit Status illegal */
 | 
						|
 | 
						|
	/* Read partitions */
 | 
						|
 | 
						|
	rd_text();
 | 
						|
	rd_gda();
 | 
						|
	rd_proctab();
 | 
						|
 | 
						|
	rd_close();
 | 
						|
 | 
						|
	/* Set up the arguments and environment */
 | 
						|
 | 
						|
	vecp = ARGB;			/* start of environ vector copy */
 | 
						|
	dppush(vecp);			/* push address of env pointer */
 | 
						|
	strp = vecp + env_vec_size;	/* start of environ strings */
 | 
						|
	for (p = environ; *p != (char *) 0; p++) {
 | 
						|
		dt_stdp(vecp, strp);
 | 
						|
		strp = storestring(strp, *p);
 | 
						|
		vecp += psize;
 | 
						|
	}
 | 
						|
	dt_stdp(vecp, i2p(0));		/* terminating zero */
 | 
						|
 | 
						|
	vecp = strp;			/* start of argument vector copy */
 | 
						|
	dppush(vecp);			/* push address of argv pointer */
 | 
						|
	strp = vecp + arg_vec_size;	/* start of argument strings */
 | 
						|
	for (p = av; *p != (char *) 0; p++) {
 | 
						|
		dt_stdp(vecp, strp);
 | 
						|
		strp = storestring(strp, *p);
 | 
						|
		vecp += psize;
 | 
						|
	}
 | 
						|
	dt_stdp(vecp, i2p(0));		/* terminating zero */
 | 
						|
 | 
						|
	npush((long) ac, wsize);	/* push argc */
 | 
						|
}
 | 
						|
 | 
						|
PRIVATE size alignedstrlen(s)
 | 
						|
	char *s;
 | 
						|
{
 | 
						|
	register size len = strlen(s) + 1;
 | 
						|
 | 
						|
	return (len + wsize - 1) / wsize * wsize;
 | 
						|
}
 | 
						|
 | 
						|
PRIVATE ptr storestring(addr, s)
 | 
						|
	ptr addr;
 | 
						|
	char *s;
 | 
						|
{
 | 
						|
	/*	Store string, aligned to a fit multiple of wsize bytes.
 | 
						|
		Return first address on a wordsize boundary after string.
 | 
						|
	*/
 | 
						|
	register size oldlen = strlen(s) + 1;
 | 
						|
	register size newlen = ((oldlen + wsize - 1) / wsize) * wsize;
 | 
						|
	register long i;
 | 
						|
 | 
						|
	LOG(("@g6 storestring(%lu, %s), oldlen = %ld, newlen = %ld",
 | 
						|
			addr, s, oldlen, newlen));
 | 
						|
	ch_in_data(addr, newlen);
 | 
						|
	ch_aligned(addr, newlen);
 | 
						|
 | 
						|
	/* copy data of source string */
 | 
						|
	for (i = 0; i < oldlen; i++) {
 | 
						|
		data_loc(addr + i) = *s++;
 | 
						|
		dt_int(addr + i);
 | 
						|
	}
 | 
						|
	/* pad until newlen */
 | 
						|
	for (; i < newlen; i++) {
 | 
						|
		data_loc(addr + i) = (char) 0;
 | 
						|
		dt_int(addr + i);
 | 
						|
	}
 | 
						|
	return (addr + i);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef	LOGGING
 | 
						|
dt_clear_area(from, to)
 | 
						|
	ptr from;
 | 
						|
	ptr to;
 | 
						|
{
 | 
						|
	/* includes *from but excludes *to */
 | 
						|
	register ptr a;
 | 
						|
 | 
						|
	for (a = from; a < to; a++) {
 | 
						|
		dt_undef(a);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
st_clear_area(from, to)
 | 
						|
	ptr from;
 | 
						|
	ptr to;
 | 
						|
{
 | 
						|
	/* includes both *from and *to (since ML+1 is unexpressible) */
 | 
						|
	register ptr a;
 | 
						|
 | 
						|
	for (a = from; a >= to; a--) {
 | 
						|
		st_undef(a);
 | 
						|
	}
 | 
						|
}
 | 
						|
#endif	LOGGING
 | 
						|
 |