Mercurial > hg-old > index.cgi
diff src/output.c @ 0:57495da01900
Initial checking of LWASM
author | lost |
---|---|
date | Fri, 03 Oct 2008 02:44:20 +0000 |
parents | |
children | 34568fab6058 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/output.c Fri Oct 03 02:44:20 2008 +0000 @@ -0,0 +1,164 @@ +/* + * output.c + * + * code for actually outputting the assembled code + */ + +//#include <ctype.h> +#include <errno.h> +#include <stdio.h> +//#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#define __output_c_seen__ +//#include "instab.h" +#include "lwasm.h" + +void write_code_raw(asmstate_t *as, FILE *of); +void write_code_decb(asmstate_t *as, FILE *of); +void write_code_rawrel(asmstate_t *as, FILE *of); + +void write_code(asmstate_t *as) +{ + FILE *of; + + if (as -> errorcount > 0) + { + fprintf(stderr, "Not doing output due to assembly errors.\n"); + return; + } + + of = fopen(as -> outfile, "wb"); + if (!of) + { + fprintf(stderr, "Cannot open '%s' for output", as -> outfile); + perror(""); + return; + } + + switch (as -> outformat) + { + case OUTPUT_RAW: + write_code_raw(as, of); + break; + + case OUTPUT_DECB: + write_code_decb(as, of); + break; + + case OUTPUT_RAWREL: + write_code_rawrel(as, of); + break; + + default: + fprintf(stderr, "BUG: unrecognized output format when generating output file\n"); + fclose(of); + unlink(as -> outfile); + return; + } + + fclose(of); +} + +/* +rawrel output treats an ORG directive as an offset from the start of the +file. Undefined results will occur if an ORG directive moves the output +pointer backward. This particular implementation uses "fseek" to handle +ORG requests and to skip over RMBs. + +This simple brain damanged method simply does an fseek before outputting +each instruction. +*/ +void write_code_rawrel(asmstate_t *as, FILE *of) +{ + sourceline_t *cl; + + for (cl = as -> source_head; cl; cl = cl -> next) + { + if (cl -> nocode) + continue; + + fseek(of, cl -> addr, SEEK_SET); + fwrite(cl -> codebytes, cl -> numcodebytes, 1, of); + } +} + +/* +raw merely writes all the bytes directly to the file as is. ORG is just a +reference for the assembler to handle absolute references. Multiple ORG +statements will produce mostly useless results +*/ +void write_code_raw(asmstate_t *as, FILE *of) +{ + sourceline_t *cl; + + for (cl = as -> source_head; cl; cl = cl -> next) + { + if (cl -> nocode && cl -> len > 0) + { + int i; + for (i = 0; i < cl -> len; i++) + fwrite("\0", 1, 1, of); + continue; + } + if (cl -> nocode) + continue; + + fwrite(cl -> codebytes, cl -> numcodebytes, 1, of); + } +} + +void write_code_decb(asmstate_t *as, FILE *of) +{ + long preambloc; + sourceline_t *cl; + int blocklen = -1; + int nextcalc = -1; + unsigned char outbuf[5]; + + for (cl = as -> source_head; cl; cl = cl -> next) + { + if (cl -> nocode) + continue; + if (cl -> addr != nextcalc && cl -> numcodebytes > 0) + { + // need preamble here + if (blocklen > 0) + { + fseek(of, preambloc, SEEK_SET); + outbuf[0] = (blocklen >> 8) & 0xFF; + outbuf[1] = blocklen & 0xFF; + fwrite(outbuf, 2, 1, of); + fseek(of, 0, SEEK_END); + } + blocklen = 0; + nextcalc = cl -> addr; + outbuf[0] = 0x00; + outbuf[1] = 0x00; + outbuf[2] = 0x00; + outbuf[3] = (nextcalc >> 8) & 0xFF; + outbuf[4] = nextcalc & 0xFF; + preambloc = ftell(of) + 1; + fwrite(outbuf, 5, 1, of); + } + nextcalc += cl -> numcodebytes; + fwrite(cl -> codebytes, cl -> numcodebytes, 1, of); + blocklen += cl -> numcodebytes; + } + if (blocklen > 0) + { + fseek(of, preambloc, SEEK_SET); + outbuf[0] = (blocklen >> 8) & 0xFF; + outbuf[1] = blocklen & 0xFF; + fwrite(outbuf, 2, 1, of); + fseek(of, 0, SEEK_END); + } + + // now write postamble + outbuf[0] = 0xFF; + outbuf[1] = 0x00; + outbuf[2] = 0x00; + outbuf[3] = (as -> execaddr >> 8) & 0xFF; + outbuf[4] = (as -> execaddr) & 0xFF; + fwrite(outbuf, 5, 1, of); +}