changeset 548:cde1a5a48636

Add IHEX output format to lwlink At the request of Craig Iannello who provided a small bribe, IHEX output format is now available in lwlink. At least a first pass version of it.
author William Astle <lost@l-w.ca>
date Thu, 16 Mar 2023 16:59:50 -0600
parents 33e37b3d98cf
children ee3e52ab2288
files lwlink/lwlink.h lwlink/main.c lwlink/output.c
diffstat 3 files changed, 61 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/lwlink/lwlink.h	Thu Mar 16 16:18:13 2023 -0600
+++ b/lwlink/lwlink.h	Thu Mar 16 16:59:50 2023 -0600
@@ -32,6 +32,7 @@
 #define OUTPUT_OS9		3	// OS9 object code module
 #define OUTPUT_SREC		4	// motorola SREC format
 #define OUTPUT_RAW2     5   // raw sequence of bytes, BSS converted to NULs
+#define OUTPUT_IHEX     6   // IHEX output format
 
 typedef struct symtab_s symtab_t;
 struct symtab_s
--- a/lwlink/main.c	Thu Mar 16 16:18:13 2023 -0600
+++ b/lwlink/main.c	Thu Mar 16 16:59:50 2023 -0600
@@ -92,6 +92,8 @@
 			outformat = OUTPUT_OS9;
 		else if (!strcasecmp(arg, "srec"))
 			outformat = OUTPUT_SREC;
+		else if (!strcasecmp(arg, "ihex"))
+			outformat = OUTPUT_IHEX;
 		else
 		{
 			fprintf(stderr, "Invalid output format: %s\n", arg);
@@ -141,7 +143,7 @@
 	{ "debug",		'd',	0,		0,
 				"Set debug mode"},
 	{ "format",		'f',	"TYPE",	0,
-				"Select output format: decb, raw, lwex, os9, srec"},
+				"Select output format: decb, raw, lwex, os9, srec, ihex"},
 	{ "decb",		'b',	0,		0,
 				"Generate DECB .bin format output, equivalent of --format=decb"},
 	{ "raw",		'r',	0,		0,
--- a/lwlink/output.c	Thu Mar 16 16:18:13 2023 -0600
+++ b/lwlink/output.c	Thu Mar 16 16:59:50 2023 -0600
@@ -39,6 +39,7 @@
 void do_output_raw2(FILE *of);
 void do_output_lwex0(FILE *of);
 void do_output_srec(FILE *of);
+void do_output_ihex(FILE *of);
 
 void do_output(void)
 {
@@ -77,6 +78,10 @@
 	case OUTPUT_SREC:
 		do_output_srec(of);
 		break;
+
+	case OUTPUT_IHEX:
+		do_output_ihex(of);
+		break;
 		
 	default:
 		fprintf(stderr, "Unknown output format doing output!\n");
@@ -241,6 +246,58 @@
 	fprintf(of,"S903%04X%02X\r\n",linkscript.execaddr,(unsigned char)(~recsum));
 }
 
+void do_output_ihex(FILE *of)
+{
+	const int IRECLEN = 16;
+
+	int sn;	
+	int remainingcodebytes;
+	
+	int codeaddr;
+	int i;
+	int recaddr = 0;
+	int recdlen = 0;
+	int recsum;
+	int reccnt = -1;
+	unsigned char* sectcode;
+	// no header yet; unnecessary
+
+	for (sn = 0; sn < nsects; sn++)				// check all sections
+	{
+		if (sectlist[sn].ptr -> flags & SECTION_BSS)	// ignore BSS sections
+			continue;
+		if (sectlist[sn].ptr -> codesize == 0)		// ignore empty sections
+			continue;
+
+		recaddr = sectlist[sn].ptr -> loadaddress;
+		remainingcodebytes = sectlist[sn].ptr -> codesize;
+		sectcode = sectlist[sn].ptr -> code;
+		
+		while (remainingcodebytes) 
+		{
+			recdlen = (IRECLEN>remainingcodebytes)?remainingcodebytes:IRECLEN;
+			recsum = recdlen;
+			codeaddr = recaddr - sectlist[sn].ptr -> loadaddress;			
+			fprintf(of, ":%02X%04X00", recdlen, recaddr & 0xffff);
+			for (i = 0; i < recdlen; i++)
+			{
+				fprintf(of, "%02X", sectcode[codeaddr+i]);
+				recsum += sectcode[codeaddr+i];
+			}
+			recsum += (recaddr >> 8) & 0xFF;
+			recsum += recaddr & 0xFF;
+			fprintf(of, "%02X\r\n", (unsigned char)(256 - recsum));
+			reccnt += 1;
+			remainingcodebytes -= recdlen;
+			recaddr += recdlen;
+		}
+	}
+	if (reccnt > 0)
+	{
+		fprintf(of, ":00%04X01FF\r\n", linkscript.execaddr);
+	}
+}
+
 void do_output_lwex0(FILE *of)
 {
 	int nskips = 0;		// used to output blanks for BSS inline