* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / hc08 / lkihx.c
1 /* lkihx.c
2
3    Copyright (C) 1989-1995 Alan R. Baldwin
4    721 Berkeley St., Kent, Ohio 44240
5
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.
10
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.
15
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/>. */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include "aslink.h"
22
23 /*)Module       lkihx.c
24  *
25  *      The module lkihx.c contains the function to
26  *      output the relocated object code in the
27  *      Intel Hex format.
28  *
29  *      lkihx.c contains the following functions:
30  *              VOID    hexRecord(addr, rtvalIndex)
31  *              VOID    ihx(i)
32  *              VOID    ihxExtendedLinearAddress(a)
33  *
34  *      local variables: hexPageOverrun, lastHexAddr
35  */
36
37 /*Intel Hex Format
38  *      Record Mark Field    -  This  field  signifies  the  start  of a
39  *                              record, and consists of an  ascii  colon
40  *                              (:).
41  *
42  *      Record Length Field  -  This   field   consists   of  two  ascii
43  *                              characters which indicate the number  of
44  *                              data   bytes   in   this   record.   The
45  *                              characters are the result of  converting
46  *                              the  number  of  bytes  in binary to two
47  *                              ascii characters, high digit first.   An
48  *                              End  of  File  record contains two ascii
49  *                              zeros in this field.
50  *
51  *      Load Address Field   -  This  field  consists  of the four ascii
52  *                              characters which result from  converting
53  *                              the  the  binary value of the address in
54  *                              which to begin loading this record.  The
55  *                              order is as follows:
56  *
57  *                                  High digit of high byte of address.
58  *                                  Low digit of high byte of address.
59  *                                  High digit of low byte of address.
60  *                                  Low digit of low byte of address.
61  *
62  *                              In an End of File record this field con-
63  *                              sists of either four ascii zeros or  the
64  *                              program  entry  address.   Currently the
65  *                              entry address option is not supported.
66  *
67  *      Record Type Field    -  This  field  identifies the record type,
68  *                              which is either 0 for data records or  1
69  *                              for  an End of File record.  It consists
70  *                              of two ascii characters, with  the  high
71  *                              digit of the record type first, followed
72  *                              by the low digit of the record type.
73  *
74  *      Data Field           -  This  field consists of the actual data,
75  *                              converted to two ascii characters,  high
76  *                              digit first.  There are no data bytes in
77  *                              the End of File record.
78  *
79  *      Checksum Field       -  The  checksum  field is the 8 bit binary
80  *                              sum of the record length field, the load
81  *                              address  field,  the  record type field,
82  *                              and the data field.  This  sum  is  then
83  *                              negated  (2's  complement) and converted
84  *                              to  two  ascii  characters,  high  digit
85  *                              first.
86  */
87
88 /* Static variable which holds the count of hex page overruns
89  * (crossings of the 64kB boundary). Cleared at explicit extended
90  * address output.
91  */
92 static int hexPageOverrun = 0;
93
94 /* Global which holds the last (16 bit) address of hex record.
95  * Cleared at begin of new area or when the extended address is output.
96  */
97 unsigned int lastHexAddr = 0;
98
99
100 /*)Function     hexRecord(addr, rtvalIndex)
101  *
102  *              unsigned addr   starting address of hex record
103  *              int rtvalIndex  starting index into the rtval[] array
104  *
105  *      The function hexRecord() outputs the relocated data
106  *      in the standard Intel Hex format (with inserting
107  *      the extended address record if necessary).
108  *
109  *      local variables:
110  *              Addr_T  chksum          byte checksum
111  *              int             i                       index for loops
112  *              int             overrun         temporary storage for hexPageOverrun
113  *              int             bytes           counter for bytes written
114  *
115  *      global variables:
116  *              FILE *  ofp             output file handle
117  *              int     rtcnt           count of data words
118  *              int     rtflg[]         output the data flag
119  *              Addr_T  rtval[]         relocated data
120  *
121  *      functions called:
122  *              int     fprintf()       c_library
123  *              ihxExtendedLinearAddress()      lkihx.c
124  *              hexRecord()             lkihx.c         (recursion)
125  *
126  *      side effects:
127  *              hexPageOverrun is eventually incremented,
128  *              lastHexAddr is updated
129  */
130
131 VOID
132 hexRecord(unsigned addr, int rtvalIndex)
133 {
134         Addr_T chksum;
135         int i, overrun, bytes;
136
137         for (i = rtvalIndex, chksum = 0; i < rtcnt; i++) {
138                 if (rtflg[i]) {
139                         if (addr + ++chksum > 0xffff)
140                                 break;
141                 }
142         }
143         if (chksum == 0)
144                 return;                 // nothing to output
145
146         if (lastHexAddr > addr) {
147                 overrun = hexPageOverrun + 1;
148                 ihxExtendedLinearAddress(lastExtendedAddress + overrun);
149                 hexPageOverrun = overrun;
150                 hexRecord(addr, rtvalIndex);
151                 return;
152         }
153
154         lastHexAddr = addr;
155         fprintf(ofp, ":%02X%04X00", chksum, addr);
156         chksum += (addr >> 8) + (addr & 0xff);
157         for (i = rtvalIndex, bytes = 0; i < rtcnt; i++) {
158                 if (rtflg[i]) {
159                     fprintf(ofp, "%02X", rtval[i]);
160                     chksum += rtval[i];
161 #if 0
162                         if (addr + ++bytes > 0xffff) {
163                                 if (rflag) {
164                                         fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
165                                         overrun = hexPageOverrun + 1;
166                                         ihxExtendedLinearAddress(lastExtendedAddress + overrun);
167                                         hexPageOverrun = overrun;
168                                         hexRecord(0, i + 1);
169                                         return;
170                                 } else {
171                                         fprintf(stderr,
172                                                 "warning: extended linear address encountered; "
173                                                 "you probably want the -r flag.\n");
174                                 }
175                         }
176 #endif
177                 }
178         }
179         fprintf(ofp, "%02X\n", (0-chksum) & 0xff);
180 }
181
182 /*)Function     ihx(i)
183  *
184  *              int     i               0 - process data
185  *                                      1 - end of data
186  *
187  *      The function ihx() calls the hexRecord() function for processing data
188  *      or writes the End of Data record to the file defined by ofp.
189  *
190  *      local variables:
191  *              Addr_T  n               auxiliary variable
192  *
193  *      global variables:
194  *              int     hilo            byte order
195  *              FILE *  ofp             output file handle
196  *              Addr_T  rtval[]         relocated data
197  *
198  *      functions called:
199  *              VOID hexRecord()        lkihx.c
200  *              int     fprintf()               c_library
201  *
202  *      side effects:
203  *              The sequence of rtval[0], rtval[1] is eventually changed.
204  */
205
206 VOID
207 ihx(i)
208 {
209         Addr_T n;
210         if (i) {
211                 if (ap->a_flag & A_NOLOAD)
212                         return;
213                 if (hilo == 0) {
214                         n = rtval[0];
215                         rtval[0] = rtval[1];
216                         rtval[1] = n;
217                 }
218                 hexRecord((rtval[0]<<8) + rtval[1], 2);
219         } else {
220                 fprintf(ofp, ":00000001FF\n");
221         }
222 }
223
224 /*)Function     ihxNewArea(i)
225  * The function ihxNewArea() is called when processing of new area is started.
226  * It resets the value of lastHexAddr.
227  */
228
229 VOID
230 ihxNewArea()
231 {
232         lastHexAddr = 0;
233 }
234
235 /*)Function     ihxExtendedLinearAddress(i)
236  *
237  *              Addr_T  i               16 bit extended linear address.
238  *
239  *      The function ihxExtendedLinearAddress() writes an extended
240  *      linear address record (type 04) to the output file.
241  *
242  *      local variables:
243  *              Addr_T  chksum          byte checksum
244  *
245  *      global variables:
246  *              FILE *  ofp             output file handle
247  *
248  *      functions called:
249  *              int     fprintf()       c_library
250  *
251  *      side effects:
252  *              The data is output to the file defined by ofp.
253  *              hexPageOverrun and lastHexAddr is cleared
254  */
255 VOID
256 ihxExtendedLinearAddress(Addr_T a)
257 {
258     Addr_T      chksum;
259
260     /* The checksum is the complement of the bytes in the
261      * record: the 2 is record length, 4 is the extended linear
262      * address record type, plus the two address bytes.
263      */
264     chksum = 2 + 4 + (a & 0xff) + ((a >> 8) & 0xff);
265
266     fprintf(ofp, ":02000004%04X%02X\n", a & 0xffff, (0-chksum) & 0xff);
267         hexPageOverrun = 0;
268         lastHexAddr = 0;
269 }