/* Reading the EM object file */ /* $Header$ */ #include #include /* for VERSION */ #include #include /* 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 */ 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. In this case only the * * the 4 LSB's are used. These bytes contain the most important * * information, the MSB's are just for precision. * ************************************************************************/ 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); }