comparison old-trunk/lwlink/output.c @ 339:eb230fa7d28e

Prepare for migration to hg
author lost
date Fri, 19 Mar 2010 02:54:14 +0000
parents
children
comparison
equal deleted inserted replaced
338:e7885b3ee266 339:eb230fa7d28e
1 /*
2 output.c
3 Copyright © 2009 William Astle
4
5 This file is part of LWLINK.
6
7 LWLINK is free software: you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation, either version 3 of the License, or (at your option) any later
10 version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21 Actually output the binary
22 */
23
24 #include <config.h>
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "lwlink.h"
31
32 // this prevents warnings about not using the return value of fwrite()
33 // and, theoretically, can be replaced with a function that handles things
34 // better in the future
35 #define writebytes(s, l, c, f) do { int r; r = fwrite((s), (l), (c), (f)); } while (0)
36
37 void do_output_decb(FILE *of);
38 void do_output_raw(FILE *of);
39 void do_output_lwex0(FILE *of);
40
41 void do_output(void)
42 {
43 FILE *of;
44
45 of = fopen(outfile, "wb");
46 if (!of)
47 {
48 fprintf(stderr, "Cannot open output file %s: ", outfile);
49 perror("");
50 exit(1);
51 }
52
53 switch (outformat)
54 {
55 case OUTPUT_DECB:
56 do_output_decb(of);
57 break;
58
59 case OUTPUT_RAW:
60 do_output_raw(of);
61 break;
62
63 case OUTPUT_LWEX0:
64 do_output_lwex0(of);
65 break;
66
67 default:
68 fprintf(stderr, "Unknown output format doing output!\n");
69 exit(111);
70 }
71
72 fclose(of);
73 }
74
75 void do_output_decb(FILE *of)
76 {
77 int sn, sn2;
78 int cloc, olen;
79 unsigned char buf[5];
80
81 for (sn = 0; sn < nsects; sn++)
82 {
83 if (sectlist[sn].ptr -> flags & SECTION_BSS)
84 {
85 // no output for a BSS section
86 continue;
87 }
88 if (sectlist[sn].ptr -> codesize == 0)
89 {
90 // don't generate output for a zero size section
91 continue;
92 }
93
94 // calculate the length of this output block
95 cloc = sectlist[sn].ptr -> loadaddress;
96 olen = 0;
97 for (sn2 = sn; sn2 < nsects; sn2++)
98 {
99 // ignore BSS sections
100 if (sectlist[sn2].ptr -> flags & SECTION_BSS)
101 continue;
102 // ignore zero length sections
103 if (sectlist[sn2].ptr -> codesize == 0)
104 continue;
105 if (cloc != sectlist[sn2].ptr -> loadaddress)
106 break;
107 olen += sectlist[sn2].ptr -> codesize;
108 cloc += sectlist[sn2].ptr -> codesize;
109 }
110
111 // write a preamble
112 buf[0] = 0x00;
113 buf[1] = olen >> 8;
114 buf[2] = olen & 0xff;
115 buf[3] = sectlist[sn].ptr -> loadaddress >> 8;
116 buf[4] = sectlist[sn].ptr -> loadaddress & 0xff;
117 writebytes(buf, 1, 5, of);
118 for (; sn < sn2; sn++)
119 {
120 if (sectlist[sn].ptr -> flags & SECTION_BSS)
121 continue;
122 if (sectlist[sn].ptr -> codesize == 0)
123 continue;
124 writebytes(sectlist[sn].ptr -> code, 1, sectlist[sn].ptr -> codesize, of);
125 }
126 sn--;
127 }
128 // write a postamble
129 buf[0] = 0xff;
130 buf[1] = 0x00;
131 buf[2] = 0x00;
132 buf[3] = linkscript.execaddr >> 8;
133 buf[4] = linkscript.execaddr & 0xff;
134 writebytes(buf, 1, 5, of);
135 }
136
137 void do_output_raw(FILE *of)
138 {
139 int nskips = 0; // used to output blanks for BSS inline
140 int sn;
141
142 for (sn = 0; sn < nsects; sn++)
143 {
144 if (sectlist[sn].ptr -> flags & SECTION_BSS)
145 {
146 // no output for a BSS section
147 nskips += sectlist[sn].ptr -> codesize;
148 continue;
149 }
150 while (nskips > 0)
151 {
152 // the "" is not an error - it turns into a single NUL byte!
153 writebytes("", 1, 1, of);
154 nskips--;
155 }
156 writebytes(sectlist[sn].ptr -> code, 1, sectlist[sn].ptr -> codesize, of);
157 }
158 }
159
160 void do_output_lwex0(FILE *of)
161 {
162 int nskips = 0; // used to output blanks for BSS inline
163 int sn;
164 int codedatasize = 0;
165 unsigned char buf[32];
166
167 // calculate items for the file header
168 for (sn = 0; sn < nsects; sn++)
169 {
170 if (sectlist[sn].ptr -> flags & SECTION_BSS)
171 {
172 // no output for a BSS section
173 nskips += sectlist[sn].ptr -> codesize;
174 continue;
175 }
176 codedatasize += nskips;
177 nskips = 0;
178 codedatasize += sectlist[sn].ptr -> codesize;
179 }
180
181 // output the file header
182 buf[0] = 'L';
183 buf[1] = 'W';
184 buf[2] = 'E';
185 buf[3] = 'X';
186 buf[4] = 0; // version 0
187 buf[5] = 0; // low stack
188 buf[6] = linkscript.stacksize / 256;
189 buf[7] = linkscript.stacksize & 0xff;
190 buf[8] = nskips / 256;
191 buf[9] = nskips & 0xff;
192 buf[10] = codedatasize / 256;
193 buf[11] = codedatasize & 0xff;
194 buf[12] = linkscript.execaddr / 256;
195 buf[13] = linkscript.execaddr & 0xff;
196 memset(buf + 14, 0, 18);
197
198 writebytes(buf, 1, 32, of);
199 // output the data
200 // NOTE: disjoint load addresses will not work correctly!!!!!
201 for (sn = 0; sn < nsects; sn++)
202 {
203 if (sectlist[sn].ptr -> flags & SECTION_BSS)
204 {
205 // no output for a BSS section
206 nskips += sectlist[sn].ptr -> codesize;
207 continue;
208 }
209 while (nskips > 0)
210 {
211 // the "" is not an error - it turns into a single NUL byte!
212 writebytes("", 1, 1, of);
213 nskips--;
214 }
215 writebytes(sectlist[sn].ptr -> code, 1, sectlist[sn].ptr -> codesize, of);
216 }
217 }