struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lkihx.c
blob5a482ab81b4202aec9b875f65afe5abef1499fa8
1 /* lkihx.c
3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <stdio.h>
20 #include <string.h>
21 #include "sdld.h"
22 #include "aslink.h"
24 /*)Module lkihx.c
26 * The module lkihx.c contains the function to
27 * output the relocated object code in the
28 * Intel Hex format.
30 * lkihx.c contains the following functions:
31 * VOID hexRecord(addr, rtvalIndex)
32 * VOID ihx(i)
33 * VOID ihxExtendedLinearAddress(a)
35 * local variables: hexPageOverrun, lastHexAddr
38 /*Intel Format
39 * Record Mark Field - This field signifies the start of a
40 * record, and consists of an ascii colon
41 * (:).
43 * Record Length Field - This field consists of two ascii
44 * characters which indicate the number of
45 * data bytes in this record. The
46 * characters are the result of converting
47 * the number of bytes in binary to two
48 * ascii characters, high digit first. An
49 * End of File record contains two ascii
50 * zeros in this field.
52 * Load Address Field - This field consists of the four ascii
53 * characters which result from converting
54 * the the binary value of the address in
55 * which to begin loading this record. The
56 * order is as follows:
58 * High digit of high byte of address.
59 * Low digit of high byte of address.
60 * High digit of low byte of address.
61 * Low digit of low byte of address.
63 * In an End of File record this field con-
64 * sists of four ascii zeros, in a start
65 * address record this is the program entry
66 * address (low), or in a segment record
67 * this is the high order address.
69 * Record Type Field - This field identifies the record type,
70 * which is either 0 for data records, 1
71 * for an End of File record, 3 for a
72 * start address, or 4 for a
73 * segment record. It consists
74 * of two ascii characters, with the high
75 * digit of the record type first, followed
76 * by the low digit of the record type.
78 * Data Field - This field consists of the actual data,
79 * converted to two ascii characters, high
80 * digit first. There are no data bytes in
81 * the End of File record.
83 * Checksum Field - The checksum field is the 8 bit binary
84 * sum of the record length field, the load
85 * address field, the record type field,
86 * and the data field. This sum is then
87 * negated (2's complement) and converted
88 * to two ascii characters, high digit
89 * first.
92 /* Static variable which holds the count of hex page overruns
93 * (crossings of the 64kB boundary). Cleared at explicit extended
94 * address output.
96 static int hexPageOverrun = 0;
98 /* Global which holds the last (16 bit) address of hex record.
99 * Cleared at begin of new area or when the extended address is output.
101 unsigned int lastHexAddr = 0;
104 /*)Function hexRecord(addr, rtvalIndex)
106 * unsigned addr starting address of hex record
107 * int rtvalIndex starting index into the rtval[] array
109 * The function hexRecord() outputs the relocated data
110 * in the standard Intel Hex format (with inserting
111 * the extended address record if necessary).
113 * local variables:
114 * a_uint chksum byte checksum
115 * int i index for loops
116 * int overrun temporary storage for hexPageOverrun
117 * int bytes counter for bytes written
119 * global variables:
120 * FILE * ofp output file handle
121 * int rtcnt count of data words
122 * int rtflg[] output the data flag
123 * a_uint rtval[] relocated data
125 * functions called:
126 * int fprintf() c_library
127 * ihxExtendedLinearAddress() lkihx.c
128 * hexRecord() lkihx.c (recursion)
130 * side effects:
131 * hexPageOverrun is eventually incremented,
132 * lastHexAddr is updated
135 VOID
136 hexRecord(unsigned addr, int rtvalIndex)
138 a_uint chksum;
139 int i, overrun, bytes;
141 for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) {
142 if (rtflg[i]) {
143 if (addr + ++chksum > 0xffff)
144 break;
147 if (chksum == 0)
148 return; // nothing to output
150 /* Is this record in the same bank as previous? */
151 if ((TARGET_IS_8051 && ((lastHexAddr>>16) != (addr>>16)) && (rflag)) ||
152 (TARGET_IS_6808 && lastHexAddr > addr)) {
153 overrun = hexPageOverrun + 1;
154 ihxExtendedLinearAddress(lastExtendedAddress + overrun);
155 hexPageOverrun = overrun;
156 hexRecord(addr, rtvalIndex);
157 return;
160 lastHexAddr = addr;
161 fprintf(ofp, ":%02X%04X00", chksum, addr);
162 chksum += (addr >> 8) + (addr & 0xff);
163 for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) {
164 if (rtflg[i]) {
165 fprintf(ofp, "%02X", rtval[i]);
166 chksum += rtval[i];
167 if (TARGET_IS_8051) {
168 if (addr + ++bytes > 0xffff) {
169 if (rflag) {
170 fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
171 overrun = hexPageOverrun + 1;
172 ihxExtendedLinearAddress(lastExtendedAddress + overrun);
173 hexPageOverrun = overrun;
174 hexRecord(0, i + 1);
175 return;
176 } else {
177 fprintf(stderr,
178 "warning: extended linear address encountered; "
179 "you probably want the -r flag.\n");
185 fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
188 /*)Function ihx(i)
190 * int i 0 - process data
191 * 1 - end of data
193 * The function ihx() calls the hexRecord() function for processing data
194 * or writes the End of Data record to the file defined by ofp.
196 * local variables:
197 * a_uint n auxiliary variable
199 * global variables:
200 * int hilo byte order
201 * FILE * ofp output file handle
202 * a_uint rtval[] relocated data
204 * functions called:
205 * VOID hexRecord() lkihx.c
206 * int fprintf() c_library
208 * side effects:
209 * The sequence of rtval[0], rtval[1] is eventually changed.
212 VOID
213 ihx(int i)
215 a_uint n;
216 if (i) {
217 if (TARGET_IS_6808 && ap->a_flag & A_NOLOAD)
218 return;
220 if (hilo == 0) {
221 n = rtval[0];
222 rtval[0] = rtval[1];
223 rtval[1] = n;
225 hexRecord((rtval[0]<<8) + rtval[1], 2);
226 } else {
227 if (TARGET_IS_8051 && rflag) /* linear start address, hardcoded as reset vector (0x0000) */
228 fprintf(ofp, ":0400000500000000F7\n");
229 fprintf(ofp, ":00000001FF\n");
233 /*)Function ihxNewArea(i)
234 * The function ihxNewArea() is called when processing of new area is started.
235 * It resets the value of lastHexAddr.
238 VOID
239 ihxNewArea()
241 lastHexAddr = 0;
244 /*)Function ihxExtendedLinearAddress(i)
246 * a_uint i 16 bit extended linear address.
248 * The function ihxExtendedLinearAddress() writes an extended
249 * linear address record (type 04) to the output file.
251 * local variables:
252 * a_uint chksum byte checksum
254 * global variables:
255 * FILE * ofp output file handle
257 * functions called:
258 * int fprintf() c_library
260 * side effects:
261 * The data is output to the file defined by ofp.
262 * hexPageOverrun and lastHexAddr is cleared
264 VOID
265 ihxExtendedLinearAddress(a_uint a)
267 a_uint chksum;
269 /* The checksum is the complement of the bytes in the
270 * record: the 2 is record length, 4 is the extended linear
271 * address record type, plus the two address bytes.
273 chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff);
275 fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff);
276 hexPageOverrun = 0;
277 lastHexAddr = 0;