diff options
Diffstat (limited to 'as/genbin.c')
-rw-r--r-- | as/genbin.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/as/genbin.c b/as/genbin.c new file mode 100644 index 0000000..ce16405 --- /dev/null +++ b/as/genbin.c @@ -0,0 +1,220 @@ +/* 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]); + } +} |