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