123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685 |
- /* genobj.c - object code generation routines for assembler */
- #include "syshead.h"
- #include "const.h"
- #include "type.h"
- #include "address.h"
- #include "file.h"
- #include "globvar.h"
- #define OBJBUFSIZE 512 /* size of object code output buffer */
- #define isge2byteoffset(offset) ((offset) >= 0x100)
- #define isge4byteoffset(offset) ((offset) >= 0x10000L)
- PRIVATE char hid_absbuf[OBJ_MAX_ABS_LEN]; /* absolute object code buf */
- PRIVATE char *absbuf; /* start */
- PRIVATE char *absbufend; /* last location + 1 */
- PRIVATE char *absbufptr; /* current location */
- PRIVATE struct sym_s **arrext; /* array of external symbol ptrs */
- PRIVATE char hid_objbuf[OBJBUFSIZE]; /* object code buffer */
- PRIVATE unsigned numext; /* number of external symbols */
- PRIVATE char *objbuf; /* start */
- PRIVATE char *objbufend; /* last location + 1 */
- PRIVATE char *objbufptr; /* current location */
- PRIVATE unsigned char relsize; /* current relocation size, 0 init */
- /* local to genobjadr, but here */
- /* because of static re-init bug */
- PRIVATE offset_t rmbcount; /* accumulator for repeated RMB's */
- FORWARD void flushabs P((void));
- FORWARD void flushrmb P((void));
- FORWARD void genobjadr P((struct address_s *adrptr, int size));
- FORWARD void putobj1 P((opcode_pt ch));
- FORWARD void putobj4 P((u32_T offset));
- FORWARD void putobjoffset P((offset_t offset, count_t size));
- FORWARD void putobjword P((unsigned word));
- FORWARD void writeobj P((char *buf, unsigned count));
- /* accumulate RMB requests into 1 (so + and - requests cancel) */
- PUBLIC void accumulate_rmb(offset)
- offset_t offset;
- {
- if (objectc)
- {
- flushabs();
- rmbcount += offset;
- }
- }
- /* flush absolute object code buffer to object code buffer if necessary */
- PRIVATE void flushabs()
- {
- if (absbufptr > absbuf)
- {
- putobj1((absbufptr - absbuf) | OBJ_ABS);
- {
- register char *bufptr;
- bufptr = absbuf;
- do
- putobj1(*bufptr);
- while (++bufptr < absbufptr);
- absbufptr = absbuf;
- }
- }
- }
- /* flush object code buffer if necessary */
- PUBLIC void flushobj()
- {
- int ntowrite;
- if ((ntowrite = objbufptr - objbuf) > 0)
- {
- if (write(objfil, objbuf, (unsigned) ntowrite) != ntowrite)
- {
- error(OBJOUT);
- listline();
- finishup();
- }
- objbufptr = objbuf;
- }
- }
- /* flush RMB count if necessary */
- PRIVATE void flushrmb()
- {
- count_t size;
- if (rmbcount != 0)
- {
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(rmbcount))
- {
- putobj1(OBJ_SKIP_4);
- size = 4;
- }
- else
- #endif
- if (isge2byteoffset(rmbcount))
- {
- putobj1(OBJ_SKIP_2);
- size = 2;
- }
- else
- {
- putobj1(OBJ_SKIP_1);
- size = 1;
- }
- putobjoffset(rmbcount, size);
- rmbcount = 0;
- }
- }
- /* generate object code for current line */
- /*
- any address parameter is (regrettably) in lastexp
- any immediate parameter is (corectly) in immadr
- */
- PUBLIC void genobj()
- {
- struct address_s *adrptr;
- char *bufptr;
- unsigned char remaining;
- if (objectc && mcount != 0)
- {
- if (popflags)
- {
- if (fcflag)
- {
- bufptr = databuf.fcbuf;
- remaining = mcount;
- do
- putabs(*bufptr++);
- while (--remaining != 0);
- }
- if (fdflag)
- {
- adrptr = databuf.fdbuf;
- remaining = mcount;
- do
- genobjadr(adrptr++, 2);
- while ((remaining -= 2) != 0);
- }
- #if SIZEOF_OFFSET_T > 2
- if (fqflag)
- {
- adrptr = databuf.fqbuf;
- remaining = mcount;
- do
- genobjadr(adrptr++, 4);
- while ((remaining -= 4) != 0);
- }
- #endif
- }
- else
- {
- remaining = mcount - 1; /* count opcode immediately */
- #ifdef I80386
- if (aprefix != 0)
- {
- putabs(aprefix);
- --remaining;
- }
- if (oprefix != 0)
- {
- putabs(oprefix);
- --remaining;
- }
- if (sprefix != 0)
- {
- putabs(sprefix);
- --remaining;
- }
- #endif
- if (page != 0)
- {
- putabs(page);
- --remaining;
- }
- putabs(opcode);
- if (remaining != 0)
- {
- if (postb != 0)
- {
- putabs(postb);
- --remaining;
- }
- #ifdef I80386
- if (sib != NO_SIB)
- {
- putabs(sib);
- --remaining;
- }
- #endif
- if (remaining != 0)
- genobjadr(&lastexp, remaining);
- }
- }
- #ifdef I80386
- if (immcount != 0)
- genobjadr(&immadr, immcount);
- #endif
- }
- }
- /* generate object code for current address */
- PRIVATE void genobjadr(adrptr, size)
- struct address_s *adrptr;
- smallcount_t size;
- {
- unsigned char byte;
- unsigned symnum;
- if (!(adrptr->data & RELBIT))
- {
- /* absolute address */
- char buf[sizeof(offset_t)];
- #if SIZEOF_OFFSET_T > 2
- u4cn(buf, adrptr->offset, size);
- #else
- u2cn(buf, adrptr->offset, size);
- #endif
- putabs(buf[0]);
- if (size > 1)
- putabs(buf[1]);
- if (size > 2)
- {
- putabs(buf[2]);
- putabs(buf[3]);
- }
- }
- else
- {
- /* relocatable address */
- if (size != relsize)
- /* set reloc size index |00|0000xx| */
- putobj((relsize = size) == 4 ? 0x03 : relsize);
- if (!(adrptr->data & IMPBIT))
- {
- /* offset relocation (known offset) */
- putobj((adrptr->data & SEGM) | OBJ_OFFSET_REL | pcrflag);
- putobjoffset(adrptr->offset, size);
- }
- else
- {
- /* symbol relocation (imported symbol + offset) */
- {
- register struct sym_s **copyptr;
- for (copyptr = arrext, symnum = 0;
- symnum < numext && *copyptr++ != adrptr->sym; ++symnum)
- ;
- }
- byte = OBJ_SYMBOL_REL;
- if (isge2byteoffset(symnum))
- byte = OBJ_SYMBOL_REL | OBJ_S_MASK;
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(adrptr->offset))
- {
- byte |= 0x03; /* 4 byte offset */
- size = 4;
- }
- else
- #endif
- if (isge2byteoffset(adrptr->offset))
- {
- byte |= 0x02; /* 2 byte offset */
- size = 2;
- }
- else if (adrptr->offset != 0)
- {
- byte |= 0x01; /* 1 byte offset */
- size = 1;
- }
- else
- size = 0;
- putobj(byte | pcrflag);
- if (isge2byteoffset(symnum))
- putobjword(symnum);
- else
- putobj1((opcode_pt) symnum);
- if (adrptr->offset != 0)
- putobjoffset(adrptr->offset, size);
- }
- }
- }
- /* initialise private variables */
- PUBLIC void initobj()
- {
- absbufend = (absbufptr = absbuf = hid_absbuf) + sizeof hid_absbuf;
- objbufend = (objbufptr = objbuf = hid_objbuf) + sizeof hid_objbuf;
- }
- /*
- write header to object file
- also build array of imported/exported symbols
- */
- PUBLIC void objheader()
- {
- static char module_header[] =
- {
- #ifdef I80386
- 0xA3, 0x86,
- 1, 0,
- (char) (0xA3 + 0x86 + 1 + 0),
- #endif
- #ifdef MC6809
- 'S', '1', /* 2 byte magic number */
- 0, 1, /* 2 byte number of modules in file */
- 'S' + '1' + 0 + 1, /* 1 byte checksum */
- #endif
- };
- static char seg_max_sizes[] =
- {
- 0x55, /* all segments have maximum size 2^16 */
- 0x55, /* this is encoded by 0b01 4 times per byte */
- 0x55, /* other codes are 0b00 = max size 2^8 */
- 0x55, /* 0b10 = max size 2^24, 0b11 = max 2^32 */
- };
- unsigned char byte;
- register struct sym_s **copyptr;
- struct sym_s **copytop;
- struct sym_s **hashptr;
- struct lc_s *lcp;
- char module_name[FILNAMLEN + 1];
- char *nameptr;
- unsigned offset;
- unsigned segsizebytes;
- unsigned size;
- unsigned char sizebits;
- unsigned strsiz; /* size of object string table */
- unsigned symosiz; /* size of object symbol table */
- register struct sym_s *symptr;
- u32_T textlength;
- int symcount = 0;
- if ((objectc = objectg) == 0)
- return;
- writeobj(module_header, sizeof module_header);
- /* calculate number of imported/exported symbols */
- /* and lengths of symbol and string tables */
- /* build array of imported/exported symbols */
- symosiz = 0;
- if (truefilename == NUL_PTR)
- truefilename = filnamptr;
- nameptr = strrchr(truefilename, DIRCHAR);
- strcpy(module_name, nameptr != NUL_PTR ? nameptr + 1 : truefilename);
- if ((nameptr = strrchr(module_name, '.')) != NUL_PTR)
- *nameptr = 0;
- strsiz = strlen(module_name) + 1;
-
- for (hashptr = spt; hashptr < spt_top;)
- if ((symptr = *hashptr++) != NUL_PTR)
- do
- {
- if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
- (!globals_only_in_obj && symptr->name[0] != '.' &&
- !(symptr->type & (MNREGBIT | MACBIT | VARBIT))))
- {
- symcount ++;
- }
- }
- while ((symptr = symptr->next) != NUL_PTR);
- arrext = copyptr = asalloc( sizeof(struct sym_s *) * symcount);
- for (hashptr = spt; hashptr < spt_top;)
- if ((symptr = *hashptr++) != NUL_PTR)
- do
- {
- if ((symptr->type & EXPBIT || symptr->data & IMPBIT) ||
- (!globals_only_in_obj && symptr->name[0] != '.' &&
- !(symptr->type & (MNREGBIT | MACBIT | VARBIT))))
- {
- *copyptr++ = symptr;
- strsiz += symptr->length + 1;
- if (textseg>=0 && (symptr->data & SEGM) == textseg)
- strsiz+=2;
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(symptr->value_reg_or_op.value))
- size = 4 + 4;
- /* 4 is size of offset into string table and flags */
- /* 2nd 4 is for 4 byte offset */
- else
- #endif
- if (isge2byteoffset(symptr->value_reg_or_op.value))
- size = 4 + 2;
- else if (symptr->value_reg_or_op.value != 0)
- size = 4 + 1;
- else
- size = 4;
- symosiz += size;
- ++numext;
- }
- }
- while ((symptr = symptr->next) != NUL_PTR);
- copytop = copyptr;
- /* calculate length of text, and number of seg size bytes in header */
- textlength = segsizebytes = 0;
- lcp = lctab;
- do
- if (lcp->lc != 0)
- {
- textlength += lcp->lc; /* assuming text starts at 0 */
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(lcp->lc))
- segsizebytes += 4;
- else
- #endif
- segsizebytes += 2; /* use 2 byte size if possible */
- }
- while (++lcp < lctabtop);
- /*
- offset to text = length of header since only 1 module
- header consists of:
- module header sizeof module_header
- offset to start of text 4
- length of text 4
- length of string area 2
- class 1
- revision 1
- seg max sizes sizeof seg_max_sizes
- seg size descriptors 4
- seg sizes segsizebytes
- symbol count 2
- symbol offsets and types symosiz
- strings strsiz
- */
- /* offset to start of text */
- putobj4((u32_T) (sizeof module_header + 4 + 4 + 2 + 1 + 1 +
- sizeof seg_max_sizes + 4 + segsizebytes + 2 +
- symosiz) + strsiz);
- /* length of text */
- putobj4((u32_T) textlength);
- /* length of string area */
- putobjword(strsiz);
- /* class and revision */
- putobj1(0);
- putobj1(0);
- /* segment max sizes (constant) */
- writeobj(seg_max_sizes, sizeof seg_max_sizes);
- /* segment size descriptors */
- /* produce only 0 and 2 byte sizes */
- lcp = lctabtop;
- byte = 0;
- sizebits = OBJ_SEGSZ_TWO << 6;
- do
- {
- --lcp;
- if (lcp->lc != 0)
- {
- byte |= sizebits;
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(lcp->lc))
- byte |= sizebits >> 1; /* XXX - convert size 2 to size 4 */
- #endif
- }
- if ((sizebits >>= 2) == 0)
- {
- putobj1(byte);
- byte = 0;
- sizebits = OBJ_SEGSZ_TWO << 6;
- }
- }
- while (lcp > lctab);
- /* segment sizes */
- do /* lcp starts at lctab */
- if (lcp->lc != 0)
- {
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(lcp->lc))
- putobj4(lcp->lc);
- else
- #endif
- putobjword((unsigned) lcp->lc);
- }
- while (++lcp < lctabtop);
- /* symbol count */
- putobjword(numext);
- /* symbol offsets and types */
- offset = strlen(module_name) + 1; /* 1st symbol begins after name */
- for (copyptr = arrext; copyptr < copytop;)
- {
- putobjword(offset);
- symptr = *copyptr++;
- byte = symptr->type & OBJ_N_MASK;
- #if SIZEOF_OFFSET_T > 2
- if (isge4byteoffset(symptr->value_reg_or_op.value))
- {
- byte |= OBJ_SZ_FOUR;
- size = 4;
- }
- else
- #endif
- if (isge2byteoffset(symptr->value_reg_or_op.value))
- {
- byte |= OBJ_SZ_TWO;
- size = 2;
- }
- else if (symptr->value_reg_or_op.value != 0)
- {
- byte |= OBJ_SZ_ONE;
- size = 1;
- }
- else
- size = 0;
- if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
- {
- byte |= OBJ_SA_MASK;
- symptr->data &= ~OBJ_I_MASK;
- }
- putobjword((unsigned)
- (byte << 0x8) |
- (symptr->type & OBJ_E_MASK) | /* |E|0000000| */
- ((symptr->data & (OBJ_I_MASK | OBJ_A_MASK | OBJ_SEGM_MASK)) ^
- /* |0|I|0|A|SEGM| */
- RELBIT)); /* RELBIT by negative logic */
- if ((symptr->type & (COMMBIT | REDBIT)) == (COMMBIT | REDBIT))
- symptr->data |= OBJ_I_MASK;
- if (size != 0)
- putobjoffset(symptr->value_reg_or_op.value, size);
- offset += symptr->length + 1;
- if (textseg>=0 && (symptr->data & SEGM) == textseg)
- offset+=2;
- }
- /* strings */
- writeobj(module_name, strlen(module_name));
- putobj1(0);
- for (copyptr = arrext; copyptr < copytop;)
- {
- symptr = *copyptr++;
- writeobj(symptr->name, symptr->length);
- if (textseg>=0 && (symptr->data & SEGM) == textseg)
- {
- putobj1('.');
- putobj1(hexdigit[textseg]);
- }
- putobj1(0);
- }
- putobj1(OBJ_SET_SEG | 0); /* default segment 0, |0010|SEGM| */
- }
- /* write trailer to object file */
- PUBLIC void objtrailer()
- {
- if (objectc)
- {
- putobj(0); /* end of object file */
- flushobj();
- }
- }
- /* write char to absolute object code buffer, flush if necessary */
- PUBLIC void putabs(ch)
- opcode_pt ch;
- {
- if (objectc)
- {
- if (rmbcount != 0)
- flushrmb();
- if (absbufptr >= absbufend)
- flushabs();
- *absbufptr++ = ch;
- }
- }
- /* write char to object code buffer, flush if necessary */
- PUBLIC void putobj(ch)
- opcode_pt ch;
- {
- if (objectc)
- {
- flushabs();
- flushrmb();
- putobj1(ch);
- }
- }
- /* write char to object code buffer assuming nothing in absolute & rmb bufs */
- PRIVATE void putobj1(ch)
- opcode_pt ch;
- {
- if (objbufptr >= objbufend)
- flushobj();
- *objbufptr++ = ch;
- }
- /* write 32 bit offset to object code buffer assuming ... */
- PRIVATE void putobj4(offset)
- u32_T offset;
- {
- char buf[sizeof offset];
- u4c4(buf, offset);
- writeobj(buf, 4);
- }
- /* write sized offset to object code buffer assuming ... */
- PRIVATE void putobjoffset(offset, size)
- offset_t offset;
- count_t size;
- {
- char buf[sizeof offset];
- #if SIZEOF_OFFSET_T > 2
- u4cn(buf, offset, size);
- #else
- u2cn(buf, offset, size);
- #endif
- putobj1(buf[0]);
- if (size > 1)
- putobj1(buf[1]);
- if (size > 2)
- {
- putobj1(buf[2]);
- putobj1(buf[3]);
- }
- }
- /* write word to object code buffer assuming ... */
- PRIVATE void putobjword(word)
- unsigned word;
- {
- char buf[sizeof word];
- u2c2(buf, word);
- putobj1(buf[0]);
- putobj1(buf[1]);
- }
- /* write several bytes to object code buffer assuming ... */
- PRIVATE void writeobj(buf, count)
- char *buf;
- unsigned count;
- {
- do
- putobj1(*buf++);
- while (--count);
- }
|