0
|
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 }
|