ack/util/int/read.c
1989-11-13 15:36:12 +00:00

322 lines
7 KiB
C

/*
Reading the EM object file
*/
/* $Header$ */
#include <stdio.h>
#include <local.h> /* for VERSION */
#include <em_spec.h>
#include <as_spec.h> /* for as_magic */
#include "logging.h"
#include "nofloat.h"
#include "global.h"
#include "log.h"
#include "warn.h"
#include "mem.h"
#include "shadow.h"
#include "read.h"
#include "text.h"
#ifndef NOFLOAT
extern double str2double();
#endif NOFLOAT
/************************************************************************
* Read object file contents. *
************************************************************************
* *
* rd_open() - open object file. *
* rd_header() - read object file header. *
* rd_text() - read program text. *
* rd_gda() - read global data area. *
* rd_proctab() - read procedure descriptors, *
* rd_close() - close object file. *
* *
************************************************************************/
/* EM header Part 1 variables */
int FLAGS;
/* EM header Part 2 variables */
size NTEXT;
size NDATA;
long NPROC;
long ENTRY;
long NLINE;
size SZDATA;
PRIVATE FILE *load_fp; /* Filepointer of load file */
PRIVATE ptr rd_repeat();
PRIVATE ptr rd_descr();
PRIVATE int rd_byte();
PRIVATE long rd_int();
rd_open(fname)
char *fname;
{ /* Open loadfile */
if ((load_fp = fopen(fname, "r")) == NULL) {
fatal("Cannot open loadfile '%s'", fname);
}
}
rd_header()
{
/* Part 1 */
if (rd_int(2L) != as_magic)
fatal("Bad magic number in loadfile");
FLAGS = rd_int(2L);
if (rd_int(2L) != 0)
fatal("Unresolved references in loadfile");
if (rd_int(2L) != VERSION)
fatal("Incorrect version number in loadfile");
/* We only allow the following wordsize/pointersize combinations: */
/* 2/2, 2/4, 4/4 */
/* A fatal error will be generated if other combinations occur. */
wsize = rd_int(2L);
if (!(wsize == 2 || wsize == 4))
fatal("Bad wordsize in loadfile");
dwsize = 2 * wsize; /* set double wordsize */
wsizem1 = wsize - 1; /* wordsize - 1 used often */
psize = rd_int(2L);
if (!(psize == 2 || psize == 4) || psize < wsize)
fatal("Bad pointersize in loadfile");
if (2 * psize > FRALimit)
fatal("FRA maximum size too small");
rd_int(2L); /* Entry 7 is unused */
rd_int(2L); /* Entry 8 is unused */
/* Part 2 */
NTEXT = rd_int(psize);
NDATA = rd_int(psize);
NPROC = rd_int(psize);
ENTRY = rd_int(psize);
if (ENTRY < 0 || ENTRY >= NPROC)
fatal("Bad entry point");
NLINE = rd_int(psize);
if (NLINE == 0) {
warning(WNLINEZR);
NLINE = I_MAXS4;
}
SZDATA = rd_int(psize);
rd_int(psize); /* entry 7 is unused */
rd_int(psize); /* entry 8 is unused */
}
rd_text()
{
fread(text, 1, (int) DB, load_fp);
}
rd_gda()
{
register int type, prev_type;
register ptr pos, prev_pos; /* prev_pos invalid if prev_type==0 */
register long i;
type = prev_type = 0;
pos = prev_pos = i2p(0);
for (i = 1; i <= NDATA; i++) {
type = btol(rd_byte());
LOG((" r6 rd_gda(), i = %ld, pos = %u", i, pos));
if (type == 0) {
/* repetition descriptor */
register size count = rd_int(psize);
LOG((" r6 rd_gda(), case 0: count = %lu", count));
if (prev_type == 0) {
fatal("Type 0 initialisation on type 0");
}
pos = rd_repeat(pos, count, prev_pos);
prev_type = 0;
}
else {
/* filling descriptor */
register size count = btol(rd_byte());
LOG((" r6 rd_gda(), case %d: count = %lu",
type, count));
prev_pos = pos;
pos = rd_descr(type, count, prev_pos);
prev_type = type;
}
}
/* now protect the LIN and FIL area */
dt_prot(i2p(0), (long)LINSIZE);
dt_prot(i2p(4), psize);
}
rd_proctab()
{
register long p;
init_proctab();
for (p = 0; p < NPROC; p++) {
register long nloc = rd_int(psize);
register ptr ep = i2p(rd_int(psize));
add_proc(nloc, ep);
}
end_init_proctab();
}
rd_close()
{
fclose(load_fp);
load_fp = 0;
}
/************************************************************************
* Read functions for several types. *
************************************************************************
* *
* rd_repeat() - repeat the previous initialisation *
* rd_descr() - read a descriptor *
* rd_byte() - read one byte, return a int. *
* rd_int(n) - read n byte integer, return a long. *
* *
************************************************************************/
/************************************************************************
* Reading a floating point number *
* *
* A double is 8 bytes, so it can contain 4- and 8-byte (EM) *
* floating point numbers. That's why a 4-byte floating point *
* number is also stored in a double. *
************************************************************************/
PRIVATE ptr rd_repeat(pos, count, prev_pos)
ptr pos, prev_pos;
size count;
{
register size diff = pos - prev_pos;
register size j;
for (j = 0; j < count; j++) {
register long i;
for (i = 0; i < diff; i++) {
data_loc(pos) = data_loc(pos - diff);
#ifdef LOGGING
/* copy shadow byte, including protection bit */
dt_sh(pos) = dt_sh(pos - diff);
#endif LOGGING
pos++;
}
}
return pos;
}
PRIVATE ptr rd_descr(type, count, pos)
int type;
size count;
ptr pos;
{
register size j;
char fl_rep[128]; /* fp number representation */
register int fl_cnt;
switch (type) {
case 1: /* m uninitialized words */
j = count;
while (j--) {
dt_stn(pos, 0L, wsize);
pos += wsize;
}
break;
case 2: /* m initialized bytes */
j = count;
while (j--) {
dt_stn(pos++, btol(rd_byte()), 1L);
}
break;
case 3: /* m initialized wordsize integers */
for (j = 0; j < count; j++) {
dt_stn(pos, rd_int(wsize), wsize);
pos += wsize;
}
break;
case 4: /* m initialized data pointers */
for (j = 0; j < count; j++) {
dt_stdp(pos, i2p(rd_int(psize)));
pos += psize;
}
break;
case 5: /* m initialized instruction pointers */
for (j = 0; j < count; j++) {
dt_stip(pos, i2p(rd_int(psize)));
pos += psize;
}
break;
case 6: /* initialized integer of size m */
case 7: /* initialized unsigned int of size m */
if ((j = count) != 1 && j != 2 && j != 4)
fatal("Bad integersize during initialisation");
dt_stn(pos, rd_int(j), j);
pos += j;
break;
case 8: /* initialized float of size m */
if ((j = count) != 4 && j != 8)
fatal("Bad floatsize during initialisation");
/* get fp representation */
fl_cnt = 0;
while (fl_rep[fl_cnt] = rd_byte()) {
fl_cnt++;
if (fl_cnt >= sizeof (fl_rep)) {
fatal("Initialized float longer than %d chars",
sizeof (fl_rep));
}
}
#ifndef NOFLOAT
/* store the float */
dt_stf(pos, str2double(fl_rep), j);
#else NOFLOAT
/* we cannot store the float */
warning(WFLINIT);
#endif NOFLOAT
pos += j;
break;
default:
fatal("Unknown initializer type in global data.");
break;
}
return pos;
}
PRIVATE int rd_byte()
{
register int i;
if ((i = fgetc(load_fp)) == EOF)
fatal("EOF reached during initialization");
return (i);
}
PRIVATE long rd_int(n)
size n;
{
register long l;
register int i;
l = btol(rd_byte());
for (i = 1; i < n; i++) {
l |= (btol(rd_byte()) << (i*8));
}
return (l);
}