/* genbin.c - binary code generation routines for assembler */ #include "const.h" #include "type.h" #include "address.h" #include "file.h" #include "globvar.h" PRIVATE char *asmbeg; /* beginning of assembler code */ /* for overwrite check */ /* bss-init to zero = NULL and not changed */ PRIVATE offset_t binfbuf; /* binary code buffer for file (counter) */ PRIVATE offset_t binmax; /* maximum value of binmbuf for pass 1 */ PRIVATE offset_t binmin; /* minimum value of binmbuf for pass 1 */ FORWARD void putbinoffset P((offset_t offset, count_t size)); /* write header to binary file */ PUBLIC void binheader() { if ((innum = binfil) != 0x0) { writec(0x0); /* binary header byte */ #ifdef LONG_BINHEADER writeoff(binmax - binmin); /* program length */ writeoff(binfbuf = binmin); /* program start */ #else writew((unsigned) (binmax - binmin)); /* program length */ writew((unsigned) (binfbuf = binmin)); /* program start */ #endif } } /* write trailer to binary file */ PUBLIC void bintrailer() { if ((innum = binfil) != 0x0) { writec(0xFF); /* binary trailer byte */ writew(0x0); /* further trailer bytes */ #ifdef LONG_BINHEADER writeoff(pedata & UNDBIT ? binmin : progent); /* entry point */ #else writew(pedata & UNDBIT ? (unsigned) binmin : (unsigned) progent); #endif } } /* generate binary code for current line */ PUBLIC void genbin() { struct address_s *adrptr; char *bufptr; unsigned char remaining; if (binaryg && mcount != 0x0) { if (popflags) { if (fcflag) { bufptr = databuf.fcbuf; remaining = mcount; do putbin(*bufptr++); while (--remaining != 0x0); } if (fdflag) { adrptr = databuf.fdbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x2); ++adrptr; } while ((remaining -= 0x2) != 0x0); } #if SIZEOF_OFFSET_T > 0x2 if (fqflag) { adrptr = databuf.fqbuf; remaining = mcount; do { putbinoffset(adrptr->offset, 0x4); ++adrptr; } while ((remaining -= 0x4) != 0x0); } #endif } else { remaining = mcount - 0x1; /* count opcode immediately */ #ifdef I80386 if (aprefix != 0x0) { putbin(aprefix); --remaining; } if (oprefix != 0x0) { putbin(oprefix); --remaining; } if (sprefix != 0x0) { putbin(sprefix); --remaining; } #endif if (page != 0x0) { putbin(page); --remaining; } putbin(opcode); if (remaining != 0x0) { if (postb != 0x0) { putbin(postb); --remaining; } #ifdef I80386 if (sib != NO_SIB) { putbin(sib); --remaining; } #endif if (remaining != 0x0) putbinoffset(lastexp.offset, remaining); } #ifdef I80386 if (immcount != 0x0) putbinoffset(immadr.offset, immcount); #endif } /* else no code for this instruction, or already generated */ } } /* initialise private variables */ PUBLIC void initbin() { binmin = -1; /* greater than anything */ } /* write char to binary file or directly to memory */ PUBLIC void putbin(ch) opcode_pt ch; { if (binfil != 0x0) { if (!binaryc) /* pass 1, just record limits */ { if (binmbuf < binmin) binmin = binmbuf; if (++binmbuf > binmax) binmax = binmbuf; } else { if (binfbuf > binmbuf) error(BWRAP); /* file buffer ahead of memory buffer */ else { innum = binfil; while (binfbuf < binmbuf) { writec(0x0);/* pad with nulls if file buffer behind */ ++binfbuf; } writec(ch); binmbuf = ++binfbuf; } } } else if (binaryc && !(lcdata & UNDBIT)) /* memory output, and enabled */ { register char *bufptr; if ((bufptr = (char *) binmbuf) >= asmbeg && bufptr < heapptr) error(OWRITE); else *bufptr = ch; ++binmbuf; } } /* write sized offset to binary file or directly to memory */ PRIVATE void putbinoffset(offset, size) offset_t offset; count_t size; { char buf[sizeof offset]; #if SIZEOF_OFFSET_T > 0x2 u4cn(buf, offset, size); #else u2cn(buf, offset, size); #endif putbin(buf[0]); if (size > 0x1) putbin(buf[1]); if (size > 0x2) { putbin(buf[2]); putbin(buf[3]); } }