summaryrefslogtreecommitdiff
path: root/as/genbin.c
diff options
context:
space:
mode:
Diffstat (limited to 'as/genbin.c')
-rw-r--r--as/genbin.c220
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]);
+ }
+}