185 lines
4.8 KiB
C
185 lines
4.8 KiB
C
/** @file
|
|
Startup routines.
|
|
*/
|
|
|
|
/* $Id$ */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "em_abs.h"
|
|
#include "logging.h"
|
|
#include "global.h"
|
|
#include "segment.h"
|
|
#include "log.h"
|
|
#include "rsb.h"
|
|
#include "fra.h"
|
|
#include "read.h"
|
|
#include "stack.h"
|
|
#include "text.h"
|
|
#include "data.h"
|
|
#include "alloc.h"
|
|
#include "warn.h"
|
|
#include "mem.h"
|
|
#include "io.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;
|
|
|
|
void init(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 */
|
|
|
|
wpush((long) ac); /* push argc */
|
|
}
|
|
|
|
PRIVATE size alignedstrlen(char *s)
|
|
{
|
|
register size len = strlen(s) + 1;
|
|
|
|
return (len + wsize - 1) / wsize * wsize;
|
|
}
|
|
|
|
PRIVATE ptr storestring(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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|