comparison src/output.c @ 0:57495da01900

Initial checking of LWASM
author lost
date Fri, 03 Oct 2008 02:44:20 +0000
parents
children 34568fab6058
comparison
equal deleted inserted replaced
-1:000000000000 0:57495da01900
1 /*
2 * output.c
3 *
4 * code for actually outputting the assembled code
5 */
6
7 //#include <ctype.h>
8 #include <errno.h>
9 #include <stdio.h>
10 //#include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #define __output_c_seen__
14 //#include "instab.h"
15 #include "lwasm.h"
16
17 void write_code_raw(asmstate_t *as, FILE *of);
18 void write_code_decb(asmstate_t *as, FILE *of);
19 void write_code_rawrel(asmstate_t *as, FILE *of);
20
21 void write_code(asmstate_t *as)
22 {
23 FILE *of;
24
25 if (as -> errorcount > 0)
26 {
27 fprintf(stderr, "Not doing output due to assembly errors.\n");
28 return;
29 }
30
31 of = fopen(as -> outfile, "wb");
32 if (!of)
33 {
34 fprintf(stderr, "Cannot open '%s' for output", as -> outfile);
35 perror("");
36 return;
37 }
38
39 switch (as -> outformat)
40 {
41 case OUTPUT_RAW:
42 write_code_raw(as, of);
43 break;
44
45 case OUTPUT_DECB:
46 write_code_decb(as, of);
47 break;
48
49 case OUTPUT_RAWREL:
50 write_code_rawrel(as, of);
51 break;
52
53 default:
54 fprintf(stderr, "BUG: unrecognized output format when generating output file\n");
55 fclose(of);
56 unlink(as -> outfile);
57 return;
58 }
59
60 fclose(of);
61 }
62
63 /*
64 rawrel output treats an ORG directive as an offset from the start of the
65 file. Undefined results will occur if an ORG directive moves the output
66 pointer backward. This particular implementation uses "fseek" to handle
67 ORG requests and to skip over RMBs.
68
69 This simple brain damanged method simply does an fseek before outputting
70 each instruction.
71 */
72 void write_code_rawrel(asmstate_t *as, FILE *of)
73 {
74 sourceline_t *cl;
75
76 for (cl = as -> source_head; cl; cl = cl -> next)
77 {
78 if (cl -> nocode)
79 continue;
80
81 fseek(of, cl -> addr, SEEK_SET);
82 fwrite(cl -> codebytes, cl -> numcodebytes, 1, of);
83 }
84 }
85
86 /*
87 raw merely writes all the bytes directly to the file as is. ORG is just a
88 reference for the assembler to handle absolute references. Multiple ORG
89 statements will produce mostly useless results
90 */
91 void write_code_raw(asmstate_t *as, FILE *of)
92 {
93 sourceline_t *cl;
94
95 for (cl = as -> source_head; cl; cl = cl -> next)
96 {
97 if (cl -> nocode && cl -> len > 0)
98 {
99 int i;
100 for (i = 0; i < cl -> len; i++)
101 fwrite("\0", 1, 1, of);
102 continue;
103 }
104 if (cl -> nocode)
105 continue;
106
107 fwrite(cl -> codebytes, cl -> numcodebytes, 1, of);
108 }
109 }
110
111 void write_code_decb(asmstate_t *as, FILE *of)
112 {
113 long preambloc;
114 sourceline_t *cl;
115 int blocklen = -1;
116 int nextcalc = -1;
117 unsigned char outbuf[5];
118
119 for (cl = as -> source_head; cl; cl = cl -> next)
120 {
121 if (cl -> nocode)
122 continue;
123 if (cl -> addr != nextcalc && cl -> numcodebytes > 0)
124 {
125 // need preamble here
126 if (blocklen > 0)
127 {
128 fseek(of, preambloc, SEEK_SET);
129 outbuf[0] = (blocklen >> 8) & 0xFF;
130 outbuf[1] = blocklen & 0xFF;
131 fwrite(outbuf, 2, 1, of);
132 fseek(of, 0, SEEK_END);
133 }
134 blocklen = 0;
135 nextcalc = cl -> addr;
136 outbuf[0] = 0x00;
137 outbuf[1] = 0x00;
138 outbuf[2] = 0x00;
139 outbuf[3] = (nextcalc >> 8) & 0xFF;
140 outbuf[4] = nextcalc & 0xFF;
141 preambloc = ftell(of) + 1;
142 fwrite(outbuf, 5, 1, of);
143 }
144 nextcalc += cl -> numcodebytes;
145 fwrite(cl -> codebytes, cl -> numcodebytes, 1, of);
146 blocklen += cl -> numcodebytes;
147 }
148 if (blocklen > 0)
149 {
150 fseek(of, preambloc, SEEK_SET);
151 outbuf[0] = (blocklen >> 8) & 0xFF;
152 outbuf[1] = blocklen & 0xFF;
153 fwrite(outbuf, 2, 1, of);
154 fseek(of, 0, SEEK_END);
155 }
156
157 // now write postamble
158 outbuf[0] = 0xFF;
159 outbuf[1] = 0x00;
160 outbuf[2] = 0x00;
161 outbuf[3] = (as -> execaddr >> 8) & 0xFF;
162 outbuf[4] = (as -> execaddr) & 0xFF;
163 fwrite(outbuf, 5, 1, of);
164 }