1 /* ----------------------------------------------------------------------
3 * PACKAGE: as31 - 8031/8051 Assembler.
6 * This file contains the code to generate various
7 * object code formats. Provisions exist to
8 * support many types of output formats within the
12 * Jan. 19, 1990 - Created. (Ken Stauffer)
13 * Jan. 29, 1990 - Added S-records (Theo Deraadt)
17 * All code in this file written by Ken Stauffer (University of Calgary).
26 /* ----------------------------------------------------------------------
27 * DECLARE your own open(), close(), addr(), and byte() routines here.
31 static int open_tdr(const char *file, const char *ftype, const char *arg);
32 static void close_tdr(void);
33 static void addr_tdr(unsigned long a);
34 static void byte_tdr(unsigned char b);
36 static int open_byte(const char *file, const char *ftype, const char *arg);
37 static void close_byte(void);
38 static void addr_byte(unsigned long a);
39 static void byte_byte(unsigned char b);
41 static int open_od(const char *file, const char *ftype, const char *arg);
42 static void close_od(void);
43 static void addr_od(unsigned long a);
44 static void byte_od(unsigned char b);
46 static int open_srec(const char *file, const char *ftype, const char *arg);
47 static void close_srec(void);
48 static void addr_srec(unsigned long a);
49 static void byte_srec(unsigned char b);
51 static int open_hex(const char *file, const char *ftype, const char *arg);
52 static void close_hex(void);
53 static void addr_hex(unsigned long a);
54 static void byte_hex(unsigned char b);
56 static int open_bin(const char *file, const char *ftype, const char *arg);
57 static void close_bin(void);
58 static void addr_bin(unsigned long a);
59 static void byte_bin(unsigned char b);
61 /* ----------------------------------------------------------------------
62 * ADD an entry to this table to register your
63 * output format routines. Give your object format
64 * a name to be specified with the -F option.
74 int (*e_open)(const char *file, const char *ftype, const char *arg);
75 void (*e_close)(void);
76 void (*e_addr)(unsigned long a);
77 void (*e_byte)(unsigned char b);
79 { "hex", "hex", "Intel-Hex (.hex)", open_hex, close_hex, addr_hex, byte_hex },
80 { "bin", "bin", "Binary (.bin)", open_bin, close_bin, addr_bin, byte_bin },
81 { "tdr", "tdr", "TDR Format (.tdr)", open_tdr, close_tdr, addr_tdr, byte_tdr },
82 { "byte", "byte", "BYTE list (.byte)", open_byte, close_byte, addr_byte, byte_byte },
83 { "od", "od", "Octal Dump (.od)", open_od, close_od, addr_od, byte_od },
84 { "srec2", "srec", "S Record, 16 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec },
85 { "srec3", "srec", "S Record, 24 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec },
86 { "srec4", "srec", "S Record, 32 bit Address (.srec)", open_srec, close_srec, addr_srec, byte_srec }
89 #define FORMTABSIZE (sizeof(formtab)/sizeof(formtab[0]))
96 for(i=0; i<FORMTABSIZE; ) {
97 fprintf(stderr, "%s", formtab[i].name);
98 if( ++i < FORMTABSIZE)
101 fprintf(stderr, "]");
104 const char *emit_extension(const char *ftype)
109 for(i=0; i<FORMTABSIZE; i++ ) {
110 if (!strcmp(formtab[i].name, ftype))
111 return formtab[i].extension;
114 return formtab[0].extension;
118 const char *emit_desc_lookup(int num)
120 if (num >= 0 && num < FORMTABSIZE)
121 return formtab[num].description;
125 const char *emit_desc_to_name_lookup(const char *desc)
130 for(i=0; i<FORMTABSIZE; i++ ) {
131 if (!strcmp(formtab[i].description, desc))
132 return formtab[i].name;
139 int emitopen(const char *file, const char *ftype, const char *arg)
143 for(i=0; i<FORMTABSIZE; i++ ) {
144 if( !strcmp(formtab[i].name,ftype) ) {
146 return (*formtab[format].e_open)
150 mesg_f("no format \"%s\", using \"%s\"\n",
151 ftype, formtab[0].name);
154 * 0th entry is the default format type
157 return (*formtab[format].e_open)(file, ftype, arg);
162 (*formtab[format].e_close)();
165 void emitaddr(unsigned long a)
167 (*formtab[format].e_addr)(a);
172 (*formtab[format].e_byte)(b);
175 /* ----------------------------------------------------------------------
176 * Individual file format routines appear here:
177 * Each file format must define the following routines:
178 * open() - Called ONCE before any of the others.
179 * It is passed with a filename and a format
182 * close() - Called ONCE when no more emit_byte()
183 * function calls will be made.
185 * addr() - Called when ever a new address has been set
186 * in the assembler (ie. .org, .skip).
187 * This routine is also called once when the
188 * location counter is set to 0 at the very start of
191 * byte() - Called with each byte to be outputed.
196 static unsigned long addr;
197 static FILE *fout=NULL;
198 static long int offset;
201 static unsigned char bytes[16];
204 /*-----------------------------------------------------------------------
205 * "hex" format. Intel HEX format expected by many EPROM programmers
209 void hexdump(void) /* dumps one line into file */
213 if (fout == NULL) return;
214 fprintf(fout,":%02X%04lX00", pos, addr & 0xFFFF);
215 sum = pos + ((addr>>8)&0xff) + (addr&0xff) ;
216 for (i=0; i < pos; i++) {
217 fprintf(fout,"%02X", bytes[i] & 0xFF );
218 sum += bytes[i]&0xff;
220 fprintf(fout, "%02X\n", (-sum)&0xff);
225 static int open_hex(const char *file, const char *ftype, const char *arg)
227 if (file == NULL) fout = stdout;
228 else fout = fopen(file, "w");
231 mesg_f("Cannot open %s for writing.\n", file);
238 static void close_hex(void)
240 if (fout == NULL) return;
241 if ( pos > 0 ) hexdump();
242 fprintf(fout, ":00000001FF\n"); /* end of file marker */
246 static void addr_hex(unsigned long a)
248 if ( pos > 0 ) hexdump();
252 static void byte_hex(unsigned char b)
256 if ( pos == 16) hexdump();
260 /*-----------------------------------------------------------------------
261 * "bin" format. Raw binary data
264 static int open_bin(const char *file, const char *ftype, const char *arg)
266 if (file == NULL) fout = stdout;
267 else fout = fopen(file, "w");
270 mesg_f("Cannot open %s for writing.\n", file);
277 static void close_bin(void)
279 if (fout == NULL) return;
283 static void addr_bin(unsigned long a)
287 if (fout == NULL) return;
289 for (i=0; i < a - addr; i++) {
290 fprintf(fout, "%c", 0);
296 error("address changed to %lX, from %lX", a, addr);
297 error("binary output format can't write backwards");
303 static void byte_bin(unsigned char b)
305 if (fout == NULL) return;
306 fprintf(fout, "%c", b & 0xFF);
311 /* ----------------------------------------------------------------------
312 * "tdr" format. For tdr's 68008 system. Generates a
313 * script file readable by a debugger.
314 * [addr] : [byte] [byte] ..
316 * arg: This is a number in decimal which specifies
317 * the offset, -Ftdr -A0000
319 * These options specifies the tdr format, with an argument
320 * of 0. This becomes the offset used in generating the
321 * script file. The default if no A is present is 0x10000.
325 static int open_tdr(const char *file, const char *ftype, const char *arg)
327 if (file == NULL) fout = stdout;
328 else fout = fopen(file,"w");
331 mesg_f("Cannot open %s for writing.\n",file);
342 static void close_tdr(void)
344 if (fout == NULL) return;
345 if( pos != 15 ) fprintf(fout,"\n");
349 static void addr_tdr(unsigned long a)
355 static void byte_tdr(unsigned char b)
357 if (fout == NULL) return;
359 if( pos != -666 ) fprintf(fout,"\n");
362 fprintf(fout,"%06lx: ", (addr + offset) & 0xFFFFFF);
363 } else if( pos == 15 ) {
364 fprintf(fout,"%06lx: ", (addr + offset) & 0xFFFFFF);
367 fprintf(fout,"%02x ", b & 0xFF );
377 /* ----------------------------------------------------------------------
379 * Like "tdr" but each byte is on a line by itself.
380 * This is nice for debugging. No -A is used.
383 static int open_byte(const char *file, const char *ftype, const char *arg)
385 if (file == NULL) fout = stdout;
386 else fout = fopen(file,"w");
389 mesg_f("Cannot open %s for writing.\n", file);
395 static void close_byte(void)
397 if (fout == NULL) return;
401 static void addr_byte(unsigned long a)
406 static void byte_byte(unsigned char b)
408 if (fout == NULL) return;
409 fprintf(fout,"%04lX: %02X\n", addr & 0xFFFF, b & 0xFF );
414 /* ----------------------------------------------------------------------
415 * "od", this format shows 16 bytes per line, with address.
416 * It also includes ascii on one side.
418 * The format is similar to the od(1) program under Unix.
423 static unsigned char od_buf[16];
424 static unsigned long saveaddr;
426 void dumpline(unsigned long a, unsigned char *b, int len)
430 if (fout == NULL) return;
431 if(len <= 0 ) return;
433 fprintf(fout,"%04lx: ", a & 0xFFFF);
435 for(i=0; i<8; i++ ) {
437 fprintf(fout,"%02x ",b[i]);
444 for(i=8; i<16; i++ ) {
446 fprintf(fout,"%02x ",b[i]);
452 for(i=0; i<16; i++ ) {
455 (b[i]>=' ' && b[i]<='~') ? b[i] : '.' );
462 static int open_od(const char *file, const char *ftype, const char *arg)
464 if (file == NULL) fout = stdout;
465 else fout = fopen(file,"w");
468 mesg_f("Cannot open %s for writing.\n",file);
474 static void close_od(void)
476 if (fout == NULL) return;
477 dumpline(saveaddr, od_buf, od_pos-1);
481 static void addr_od(unsigned long a)
487 static void byte_od(unsigned char b)
490 dumpline(saveaddr, od_buf, od_pos-1);
494 } else if( od_pos == 16 ) {
495 dumpline(saveaddr, od_buf, od_pos-1);
499 od_buf[od_pos++] = b & 0x00ff;
505 /* ----------------------------------------------------------------------
506 * srecord format. This is called with "-Fsrec2", "-Fsrec3", or
509 * arg: This is a number in decimal which specifies
510 * the offset, -Fsrec3 -A0000
512 * These options specifies the tdr format, with an argument
513 * of 0. This becomes the offset used in generating the
514 * script file. The default if no A is present is 0x0000.
518 #define SREC_BYTESPERLINE 32
520 static int srec_format;
521 static int srec_check, srec_index;
522 static char srec_buf[SREC_BYTESPERLINE];
523 static long srec_address;
525 void srec_finishline(void)
529 if (fout == NULL) return;
530 srec_check = srec_index + (srec_address & 0xff) + ((srec_address>>8) & 0xff) + 4;
532 switch(srec_format) {
534 fprintf(fout, "S1%02X%04lX", srec_index + 4,
535 srec_address & 0xFFFF);
538 fprintf(fout, "S2%02X%06lX", srec_index + 6,
539 srec_address & 0xFFFFFF);
540 srec_check += ((srec_address>>16) & 0xff) + 2;
543 fprintf(fout, "S3%02X%08lX", srec_index + 8, srec_address);
544 srec_check += ((srec_address>>16) & 0xff) +
545 ((srec_address>>24) & 0xff) + 4;
549 for(i=0; i<srec_index; i++) {
550 fprintf(fout, "%02X", srec_buf[i] & 0xff);
551 srec_check += srec_buf[i];
554 fprintf(fout, "%02X\n", (~srec_check & 0xff) );
558 static int open_srec(const char *file, const char *ftype, const char *arg)
561 mesg_f("No S Record Format\n");
565 if (sscanf(ftype, "srec%d", &srec_format) != 1) {
566 mesg_f("Illegal S Record format \"%s\", must be \"srec2\", \"srec3\", or \"srec4\"\n", ftype);
570 if (srec_format < 2 || srec_format > 4) {
571 mesg_f("Illegal S Record format %d %s (must be 2, 3, or 4)\n",
576 if (file == NULL) fout = stdout;
577 else fout = fopen(file,"w");
580 mesg_f("Cannot open %s for writing.\n",file);
584 if(arg) offset = atoi(arg);
587 fprintf(fout, "S0030000%02X\n", (~3 & 0xff) );
591 static void close_srec(void)
593 if (fout == NULL) return;
596 switch(srec_format) {
598 fprintf(fout, "S9030000%02X\n", ~3 & 0xff);
601 fprintf(fout, "S804000000%02X\n", ~4 & 0xff);
604 fprintf(fout, "S70500000000%02X\n", ~5 & 0xff);
610 static void addr_srec(unsigned long a)
614 srec_address = a + offset;
617 static void byte_srec(unsigned char b)
619 srec_buf[srec_index++] = b;
620 if(srec_index==SREC_BYTESPERLINE) {
622 srec_address += SREC_BYTESPERLINE;