Update dependencies
[nasm/avx512.git] / rdoff / rdf2ihx.c
blob43e5c720b1005586f2bfc7b4389f16c04cf40660
1 /*
2 * rdf2ihx.c - convert an RDOFF object file to Intel Hex format.
3 * This is based on rdf2bin.
4 * Note that this program only writes 16-bit HEX.
5 */
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
11 #include "rdfload.h"
12 #include "nasmlib.h"
13 #include "symtab.h"
15 long origin = 0;
16 int align = 16;
18 /* This function writes a single n-byte data record to of. Maximum value
19 for n is 255. */
20 static int write_data_record(FILE *of, int ofs, int nbytes,
21 unsigned char *data)
23 int i, iofs;
24 unsigned int checksum;
26 iofs = ofs;
27 fprintf(of, ":%02X%04X00", nbytes, ofs);
28 checksum = 0;
29 for (i=0; i<nbytes; i++) {
30 fprintf(of, "%02X", data[i]);
31 ofs++;
32 checksum += data[i];
34 checksum = checksum + /* current checksum */
35 nbytes + /* RECLEN (one byte) */
36 ((iofs >> 8) & 0xff) + /* high byte of load offset */
37 (iofs & 0xff); /* low byte of load offset */
38 checksum = ~checksum + 1;
39 fprintf(of, "%02X\n", checksum&0xff);
40 return(ofs);
43 int main(int argc, char **argv)
45 rdfmodule *m;
46 int tmp;
47 FILE *of;
48 char *padding;
49 unsigned char *segbin[2];
50 int pad[2], segn, ofs, i;
51 long segaddr;
52 unsigned int checksum;
53 symtabEnt *s;
55 if (argc < 2) {
56 puts("Usage: rdf2ihx [-o relocation-origin] [-p segment-alignment] "
57 "input-file output-file");
58 return(1);
61 argv++, argc--;
63 while (argc > 2) {
64 if (strcmp(*argv,"-o") == 0) {
65 argv++, argc--;
66 origin = readnum(*argv, &tmp);
67 if (tmp) {
68 fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
69 return 1;
71 } else if (strcmp(*argv,"-p") == 0) {
72 argv++, argc--;
73 align = readnum(*argv, &tmp);
74 if (tmp) {
75 fprintf(stderr,"rdf2ihx: invalid parameter: %s\n",*argv);
76 return 1;
78 } else
79 break;
80 argv++, argc--;
82 if (argc < 2) {
83 puts("rdf2ihx: required parameter missing");
84 return -1;
86 m = rdfload(*argv);
88 if (!m) {
89 rdfperror("rdf2ihx",*argv);
90 return 1;
92 printf("relocating %s: origin=%lx, align=%d\n",*argv, origin, align);
94 m->textrel = origin;
95 m->datarel = origin + m->f.seg[0].length;
96 if (m->datarel % align != 0) {
97 pad[0] = align - (m->datarel % align);
98 m->datarel += pad[0];
99 } else {
100 pad[0] = 0;
103 m->bssrel = m->datarel + m->f.seg[1].length;
104 if (m->bssrel % align != 0) {
105 pad[1] = align - (m->bssrel % align);
106 m->bssrel += pad[1];
107 } else {
108 pad[1] = 0;
111 printf("code: %08lx\ndata: %08lx\nbss: %08lx\n",
112 m->textrel, m->datarel, m->bssrel);
114 rdf_relocate(m);
116 argv++;
118 of = fopen(*argv,"w");
119 if (!of) {
120 fprintf(stderr,"rdf2ihx: could not open output file %s\n",*argv);
121 return(1);
124 padding = malloc(align);
125 if (!padding) {
126 fprintf(stderr,"rdf2ihx: out of memory\n");
127 return(1);
130 /* write extended segment address record */
131 fprintf(of, ":02000002"); /* Record mark, reclen, load offset & rectyp
132 fields for ext. seg. address record */
133 segaddr = ((origin >> 16) & 0xffff); /* segment address */
134 fprintf(of, "%04X", (unsigned int)(segaddr & 0xffff));
135 checksum = 0x02 + /* reclen */
136 0x0000 + /* Load Offset */
137 0x02 + /* Rectyp */
138 (segaddr & 0xff) + /* USBA low */
139 ((segaddr >> 8) & 0xff); /* USBA high */
140 checksum = ~checksum + 1; /* two's-complement the checksum */
141 fprintf(of, "%02X\n", checksum & 0xff);
143 /* See if there's a '_main' symbol in the symbol table */
144 if ((s=symtabFind(m->symtab, "_main")) == NULL) {
145 printf("No _main symbol found, no start segment address record added\n");
146 } else {
147 printf("_main symbol found at %04x:%04x\n", s->segment,
148 (unsigned int)(s->offset & 0xffff));
149 /* Create a start segment address record for the _main symbol. */
150 segaddr = ((s->segment & 0xffff) << 16) + ((s->offset) & 0xffff);
151 fprintf(of, ":04000003"); /* Record mark, reclen, load offset & rectyp
152 fields for start seg. addr. record */
153 fprintf(of, "%08lX", segaddr); /* CS/IP field */
154 checksum = 0x04 + /* reclen */
155 0x0000 + /* load offset */
156 0x03 + /* Rectyp */
157 (segaddr & 0xff) + /* low-low byte of segaddr */
158 ((segaddr >> 8) & 0xff) + /* low-high byte of segaddr */
159 ((segaddr >> 16) & 0xff) + /* high-low byte of segaddr */
160 ((segaddr >> 24) & 0xff); /* high-high byte of segaddr */
161 checksum = ~checksum + 1; /* two's complement */
162 fprintf(of, "%02X\n", checksum & 0xff);
165 /* Now it's time to write data records from the code and data segments in.
166 This current version doesn't check for segment overflow; proper behavior
167 should be to output a segment address record for the code and data
168 segments. Something to do. */
169 ofs = 0;
170 segbin[0] = m->t;
171 segbin[1] = m->d;
172 for (segn=0; segn<2; segn++) {
173 int mod, adr;
175 if (m->f.seg[segn].length == 0)
176 continue;
177 for (i=0; i+15<m->f.seg[segn].length; i+=16) {
178 ofs = write_data_record(of, ofs, 16, &segbin[segn][i]);
180 if ((mod=m->f.seg[segn].length & 0x000f) != 0) {
181 adr = m->f.seg[segn].length & 0xfff0;
182 ofs = write_data_record(of, ofs, mod, &segbin[segn][adr]);
185 /* output an end of file record */
186 fprintf(of, ":00000001FF\n");
188 fclose(of);
189 return 0;