Add SDCC patch.
diff --git a/sdcc-3.4.1.patch b/sdcc-3.4.1.patch
new file mode 100644
index 0000000..fdfbcf6
--- /dev/null
+++ b/sdcc-3.4.1.patch
@@ -0,0 +1,473 @@
+Index: Makefile.in
+===================================================================
+--- Makefile.in (révision 9037)
++++ Makefile.in (copie de travail)
+@@ -47,7 +47,7 @@
+ SRC = lk_readnl.c lkaomf51.c lkar.c lkarea.c lkdata.c lkelf.c lkeval.c \
+ lkhead.c lklex.c lklib.c lklibr.c lklist.c lkmain.c lkmem.c \
+ lknoice.c lkout.c lkrel.c lkrloc.c lkrloc3.c lks19.c lksdcclib.c \
+- lksym.c sdld.c lksdcdb.c lkbank.c
++ lksym.c sdld.c lksdcdb.c lkbank.c lkrrel.c
+
+ LKSOURCES = $(SRC) $(ASXXLIBSRC:%.c=$(ASXXLIB)/%.c)
+
+Index: aslink.h
+===================================================================
+--- aslink.h (révision 9037)
++++ aslink.h (copie de travail)
+@@ -1019,6 +1019,8 @@
+ */
+ #endif
+
++extern int hflag; /* Generate relocatable executable
++ */
+ extern int pflag; /* print linker command file flag
+ */
+ extern int uflag; /* Listing relocation flag
+Index: lkdata.c
+===================================================================
+--- lkdata.c (révision 9037)
++++ lkdata.c (copie de travail)
+@@ -66,6 +66,9 @@
+ int objflg; /* Linked file/library object output flag
+ */
+
++int hflag; /* Generate relocatable executable
++ */
++
+ #if NOICE
+ int jflag; /* NoICE output flag
+ */
+Index: lkmain.c
+===================================================================
+--- lkmain.c (révision 9037)
++++ lkmain.c (copie de travail)
+@@ -233,6 +233,7 @@
+ startp->f_idp = "";
+
+ pflag = 1;
++ hflag = 0;
+
+ for(i=1; i<argc; i++) {
+ ip = ib;
+@@ -958,6 +959,11 @@
+ }
+ return(0);
+
++ case 'h':
++ case 'H':
++ hflag = 1;
++ break;
++
+ case 'I':
+ if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
+ iramsav();
+Index: lkrloc3.c
+===================================================================
+--- lkrloc3.c (révision 9037)
++++ lkrloc3.c (copie de travail)
+@@ -31,6 +31,7 @@
+ */
+
+ #include "aslink.h"
++#include "lkrrel.h"
+
+ /*)Module lkrloc3.c
+ *
+@@ -332,6 +333,9 @@
+ * Do remaining relocations
+ */
+ while (more()) {
++ int output_relocation_record;
++ int raddr;
++
+ error = 0;
+ mode = (int) eval();
+
+@@ -390,6 +394,95 @@
+ reli -= paga + pags;
+ }
+
++ /* KevT 28-05-2005 */
++
++ if (hflag)
++ {
++ output_relocation_record = 0;
++ if (mode & R3_SYM)
++ {
++ /* If the symbol is defined in a absolute area, then we do not
++ output a record. This allows us to reference absolute addresses
++ in our code, but it can still be relocated */
++
++ /* If the symbol is relative, it is within our relocatable program */
++
++ /* printf("Symbol: %s\n",s[rindex]->s_id); */
++ if ((s[rindex]->s_axp->a_bap->a_flag & A4_ABS)==0)
++ {
++ output_relocation_record=1;
++ }
++ }
++ else
++ {
++ /* If the area is absolute then we do not output a record.
++ This allows us to reference absolute memory, but still the code
++ can be relocated. */
++ /* If the area is relative, it refers to data that is part of the
++ relocatable program */
++
++ /* printf("Area: %s\n",a[rindex]->a_bap->a_id); */
++ if ((a[rindex]->a_bap->a_flag & A4_ABS)==0)
++ {
++ output_relocation_record=1;
++ }
++ }
++
++ if (output_relocation_record)
++ {
++ a_uint relocate_address = pc+(rtp-rtofst);
++ if (hilo)
++ {
++ raddr = reli + ((rtval[rtp]&0x0ff)<<8) + (rtval[rtp+1]&0x0ff);
++ }
++ else
++ {
++ raddr = reli + ((rtval[rtp+1]&0x0ff)<<8) + (rtval[rtp]&0x0ff);
++ }
++ /*printf("Relocation modify address: %04x\n",relocate_address); */
++ /*printf("Relocation address: %04x\n",raddr); */
++ if (mode & R3_BYTE)
++ {
++ if (mode & R3_BYTX)
++ {
++ if (mode & R3_MSB)
++ {
++
++relrec8hi(relocate_address,raddr);
++ }
++ else
++ {
++
++relrec8lo(relocate_address,raddr);
++ }
++ }
++ else
++ {
++ printf("not supported");
++ }
++ }
++ else
++ {
++ if (mode & R3_BYTX)
++ {
++ if (mode & R3_MSB)
++ {
++ printf("not supported");
++ }
++ else
++ {
++ printf("not supported");
++ }
++ }
++ else
++ {
++ relrec16(relocate_address);
++ }
++ }
++ }
++ }
++
++
+ /*
+ * R3_BYTE or R3_WORD operation
+ */
+@@ -755,6 +848,12 @@
+ if (uflag != 0) {
+ lkulist(0);
+ }
++
++ /* output relocation data */
++ if (hflag) {
++ relrecwrite();
++ }
++
+ if (oflag != 0) {
+ lkflush();
+ lkfclose();
+Index: lkrrel.c
+===================================================================
+--- lkrrel.c (révision 0)
++++ lkrrel.c (copie de travail)
+@@ -0,0 +1,251 @@
++/* (c) Kevin Thacker, May 2005 */
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include "aslink.h"
++#include "lkrrel.h"
++
++struct relrechead
++{
++ int count;
++ struct relrec *head;
++};
++
++/* 16-bit values, add full 16-bit base address */
++
++static struct relrechead head16= {0,NULL};
++/* 8-bit, but add high byte of 16-bit base address */
++static struct relrechead head8hi = {0,NULL};
++/* 8-bit, but add low byte of 16-bit base address */
++static struct relrechead head8lo = {0,NULL};
++
++/* internal; free's list */
++static void relrecfree(struct relrechead *head)
++{
++ struct relrec *cur = head->head;
++
++ while (cur!=NULL)
++ {
++ struct relrec *next = cur->next;
++ free(cur);
++
++ cur = next;
++ }
++}
++
++/* free relocation record list; e.g. on exit */
++void freerelrec()
++{
++ relrecfree(&head16);
++ relrecfree(&head8hi);
++ relrecfree(&head8lo);
++}
++
++/* internal; allocate a relocation record */
++static void newrelrec(struct relrechead *head, a_uint addr, a_uint symaddr)
++{
++ struct relrec *rec;
++
++ rec = (struct relrec *) malloc(sizeof(struct relrec));
++
++ /* error if allocation failed */
++ if (rec==NULL)
++ return;
++
++ rec->addr = addr;
++ rec->symaddr = symaddr;
++
++ /* add to start of list */
++ rec->next = head->head;
++ head->head = rec;
++ head->count++;
++}
++
++/* add item to 16-bit relocation record list */
++void relrec16(a_uint addr)
++{
++ newrelrec(&head16, addr,0);
++}
++
++/* add item to 8-bit (high) relocation record list */
++void relrec8hi(a_uint addr, a_uint symaddr)
++{
++ newrelrec(&head8hi, addr,symaddr);
++}
++
++/* add address to 8-bit (low) relocation list */
++void relrec8lo(a_uint addr, a_uint symaddr)
++{
++ newrelrec(&head8lo, addr,symaddr);
++}
++
++/* internal; compare two addresses within two relocate records */
++static int relreccompare(const void *a, const void *b)
++{
++ const struct relrec *relreca = (const struct relrec *)a;
++ const struct relrec *relrecb = (const struct relrec *)b;
++
++ return (relreca->addr-relrecb->addr);
++}
++
++/* sort a list of relocate records and return an array of the records */
++static struct relrec *relrecsort(struct relrechead *head)
++{
++ int count;
++ struct relrec *reclist;
++ struct relrec *cur;
++
++ if (head->count==0)
++ return NULL;
++
++ /* allocate list to hold all items */
++ reclist = (struct relrec *)malloc(sizeof(struct relrec)*head->count);
++
++ if (reclist==NULL)
++ return NULL;
++
++ /* fill list */
++ count = 0;
++ cur = head->head;
++ while (cur!=NULL)
++ {
++ memcpy(&reclist[count],cur,sizeof(struct relrec));
++ count++;
++ cur = cur->next;
++ }
++
++ /* sort into ascending address order */
++ qsort(reclist, count, sizeof(struct relrec),relreccompare);
++
++ return reclist;
++}
++
++int outbyte(int addr, char byte)
++{
++ rtval[0] = addr&0x0ff;
++ rtval[1] = (addr>>8)&0x0ff;
++ rtval[2] = byte&0x0ff;
++ addr+=1;
++ rtflg[0] = 1;
++ rtflg[1] = 1;
++ rtflg[2] = 1;
++ rtcnt = 3;
++ lkout(1);
++ return addr;
++}
++
++void relrecwritelist1(struct relrechead *list,int *addrptr)
++{
++ int i;
++ struct relrec *relreclist;
++ int addr;
++
++ addr = *addrptr;
++
++ relreclist = relrecsort(list);
++
++ if (relreclist!=NULL)
++ {
++ int prevaddr = 0;
++ for (i=0; i<list->count; i++)
++ {
++ struct relrec *cur = &relreclist[i];
++
++ int delta = cur->addr-prevaddr;
++
++ if (delta>254)
++ {
++ int largedelta = delta-1;
++ addr = outbyte(addr,0x0ff);
++ addr = outbyte(addr,largedelta&0x0ff);
++ addr = outbyte(addr,(largedelta>>8)&0x0ff);
++ delta = 1;
++ }
++ prevaddr = cur->addr;
++ addr = outbyte(addr,delta&0x0ff);
++ }
++
++ free(relreclist);
++ }
++
++ addr = outbyte(addr, 0);
++
++ *addrptr = addr;
++
++}
++
++void relrecwritelist2(struct relrechead *list,int *addrptr)
++{
++ int i;
++ struct relrec *relreclist;
++ int addr;
++
++ addr = *addrptr;
++
++ relreclist = relrecsort(list);
++
++ if (relreclist!=NULL)
++ {
++ int prevaddr = 0;
++ for (i=0; i<list->count; i++)
++ {
++ struct relrec *cur = &relreclist[i];
++ int delta = cur->addr-prevaddr;
++ prevaddr = cur->addr;
++
++ if (delta>254)
++ {
++ int largedelta = delta-1;
++ addr = outbyte(addr,0x0ff);
++ addr = outbyte(addr,largedelta&0x0ff);
++ addr = outbyte(addr,(largedelta>>8)&0x0ff);
++ delta = 1;
++ }
++
++ addr = outbyte(addr,delta&0x0ff);
++ addr = outbyte(addr,cur->symaddr&0x0ff);
++ }
++
++ free(relreclist);
++ }
++
++ addr = outbyte(addr,0);
++
++ *addrptr = addr;
++
++}
++
++
++void relrecwrite()
++{
++ int areasize = 0;
++
++ struct area *cur = areap;
++ while (cur!=NULL)
++ {
++ areasize+=cur->a_size;
++ cur=cur->a_ap;
++ }
++
++ printf("total length before relocation records: %04x\n",areasize);
++
++ /* re-write offset to relocation records */
++ rtval[0] = 0;
++ rtval[1] = 0;
++ rtval[2] = areasize&0x0ff;
++ rtval[3] = (areasize>>8)&0x0ff;
++ rtflg[0] = 1;
++ rtflg[1] = 1;
++ rtflg[2] = 1;
++ rtflg[3] = 1;
++ rtcnt = 4;
++ lkout(1);
++
++
++ int addr = areasize;
++
++
++ relrecwritelist1(&head16,&addr);
++ relrecwritelist1(&head8lo,&addr);
++ relrecwritelist2(&head8hi,&addr);
++}
+Index: lkrrel.h
+===================================================================
+--- lkrrel.h (révision 0)
++++ lkrrel.h (copie de travail)
+@@ -0,0 +1,17 @@
++/* relocation record */
++struct relrec
++{
++ /* next item */
++ struct relrec *next;
++
++ /* address of relocate */
++ a_uint addr;
++
++ a_uint symaddr;
++};
++
++void relrec16(a_uint addr);
++void relrec8lo(a_uint addr, a_uint symaddr);
++void relrec8hi(a_uint addr, a_uint symaddr);
++void freerelrec();
++void relrecwrite();