changeset 344:55c1f9a321e9

Add S-record output support to lwlink Thanks to a patch from Joachim Ga?ler <achim@diegasslers.de>, lwlink now has output support for S-records. This is output only - it does not add input support for S-record files.
author William Astle <lost@l-w.ca>
date Thu, 09 Apr 2015 12:27:33 -0600
parents 98f3e016cfd8
children e95f07cbce4e
files lwlink/lwlink.h lwlink/main.c lwlink/output.c lwlink/script.c
diffstat 4 files changed, 77 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/lwlink/lwlink.h	Mon Mar 16 09:27:20 2015 -0600
+++ b/lwlink/lwlink.h	Thu Apr 09 12:27:33 2015 -0600
@@ -30,6 +30,7 @@
 #define OUTPUT_RAW		1	// raw sequence of bytes
 #define OUTPUT_LWEX0	2	// LWOS LWEX binary version 0
 #define OUTPUT_OS9		3	// OS9 object code module
+#define OUTPUT_SREC		4	// motorola SREC format
 
 typedef struct symtab_s symtab_t;
 struct symtab_s
--- a/lwlink/main.c	Mon Mar 16 09:27:20 2015 -0600
+++ b/lwlink/main.c	Thu Apr 09 12:27:33 2015 -0600
@@ -81,6 +81,8 @@
 			outformat = OUTPUT_LWEX0;
 		else if (!strcasecmp(arg, "os9"))
 			outformat = OUTPUT_OS9;
+		else if (!strcasecmp(arg, "srec"))
+			outformat = OUTPUT_SREC;
 		else
 		{
 			fprintf(stderr, "Invalid output format: %s\n", arg);
@@ -130,7 +132,7 @@
 	{ "debug",		'd',	0,		0,
 				"Set debug mode"},
 	{ "format",		'f',	"TYPE",	0,
-				"Select output format: decb, raw, lwex, os9"},
+				"Select output format: decb, raw, lwex, os9, srec"},
 	{ "decb",		'b',	0,		0,
 				"Generate DECB .bin format output, equivalent of --format=decb"},
 	{ "raw",		'r',	0,		0,
--- a/lwlink/output.c	Mon Mar 16 09:27:20 2015 -0600
+++ b/lwlink/output.c	Thu Apr 09 12:27:33 2015 -0600
@@ -37,6 +37,7 @@
 void do_output_decb(FILE *of);
 void do_output_raw(FILE *of);
 void do_output_lwex0(FILE *of);
+void do_output_srec(FILE *of);
 
 void do_output(void)
 {
@@ -68,6 +69,10 @@
 		do_output_os9(of);
 		break;
 		
+	case OUTPUT_SREC:
+		do_output_srec(of);
+		break;
+		
 	default:
 		fprintf(stderr, "Unknown output format doing output!\n");
 		exit(111);
@@ -161,6 +166,59 @@
 	}
 }
 
+void do_output_srec(FILE *of)
+{
+	const int SRECLEN = 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 = (SRECLEN>remainingcodebytes)?remainingcodebytes:SRECLEN;
+			recsum = recdlen + 3;
+			codeaddr = recaddr - sectlist[sn].ptr -> loadaddress;			
+			fprintf(of, "S1%02X%04X", recdlen + 3, recaddr);
+			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)(~recsum));
+			reccnt += 1;
+			remainingcodebytes -= recdlen;
+			recaddr += recdlen;
+		}
+	}
+	// S9 record as a footer to inform about start addr
+	recsum = 3;
+	recsum += (linkscript.execaddr >> 8) & 0xFF;
+	recsum += linkscript.execaddr & 0xFF;
+	fprintf(of,"S903%04X%02X\r\n",linkscript.execaddr,(unsigned char)(~recsum));
+}
+
 void do_output_lwex0(FILE *of)
 {
 	int nskips = 0;		// used to output blanks for BSS inline
--- a/lwlink/script.c	Mon Mar 16 09:27:20 2015 -0600
+++ b/lwlink/script.c	Thu Apr 09 12:27:33 2015 -0600
@@ -58,6 +58,17 @@
 	"entry 2000\n"
 	;
 
+// the built-in SREC target linker script
+static char *srec_script =
+	"define basesympat s_%s\n"
+	"define lensympat l_%s\n"
+	"section init load 0400\n"
+	"section code\n"
+	"section *,!bss\n"
+	"section *,bss\n"
+	"entry __start\n"
+	;
+
 // the built-in RAW target linker script
 static char *raw_script = 
 	"define basesympat s_%s\n"
@@ -147,6 +158,10 @@
 			script = decb_script;
 			break;
 		
+		case OUTPUT_SREC:
+			script = srec_script;
+			break;
+		
 		case OUTPUT_LWEX0:
 			script = lwex0_script;
 			break;