blob: 3244d0602092f62236ffcfd7a645e3eb444099b5 [file] [log] [blame]
PulkoMandy3783e422023-05-02 17:40:17 +02001From dd799e32d1e14eaebba8c6c6a91615f24695f8aa Mon Sep 17 00:00:00 2001
Adrien Destugues69a6e722017-06-03 10:17:17 +02002From: Adrien Destugues <pulkomandy@pulkomandy.tk>
3Date: Fri, 22 Jan 2016 21:01:19 +0100
PulkoMandy3783e422023-05-02 17:40:17 +02004Subject: Kevin Thacker's patch for runtime relocation support.
Adrien Destugues69a6e722017-06-03 10:17:17 +02005
PulkoMandy3783e422023-05-02 17:40:17 +02006This patch is used to build the Contiki operating system for Z80
7machines.
8
9This version is modified for SDCC 4.2, the addresses are now internally
10stored on 24 bits instead of 16 bits (to help support banked code), and
11the code in the patch was adjusted for that.
Adrien Destugues69a6e722017-06-03 10:17:17 +020012
13diff --git a/sdas/linksrc/Makefile.in b/sdas/linksrc/Makefile.in
Adrien Destugues1b572422020-12-17 21:53:16 +010014index 43e16f5..e37b167 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020015--- a/sdas/linksrc/Makefile.in
16+++ b/sdas/linksrc/Makefile.in
17@@ -47,7 +47,7 @@ ASXXLIBSRC = strcmpi.c
PulkoMandy2aeca062014-06-28 23:18:25 +020018 SRC = lk_readnl.c lkaomf51.c lkar.c lkarea.c lkdata.c lkelf.c lkeval.c \
19 lkhead.c lklex.c lklib.c lklibr.c lklist.c lkmain.c lkmem.c \
20 lknoice.c lkout.c lkrel.c lkrloc.c lkrloc3.c lks19.c lksdcclib.c \
21- lksym.c sdld.c lksdcdb.c lkbank.c
22+ lksym.c sdld.c lksdcdb.c lkbank.c lkrrel.c
23
24 LKSOURCES = $(SRC) $(ASXXLIBSRC:%.c=$(ASXXLIB)/%.c)
25
Adrien Destugues69a6e722017-06-03 10:17:17 +020026diff --git a/sdas/linksrc/aslink.h b/sdas/linksrc/aslink.h
PulkoMandy3783e422023-05-02 17:40:17 +020027index 94c2b7b..f898a19 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020028--- a/sdas/linksrc/aslink.h
29+++ b/sdas/linksrc/aslink.h
30@@ -1033,6 +1033,8 @@ extern int yflag; /* -y, enable SDCC Debug output
PulkoMandy2aeca062014-06-28 23:18:25 +020031 */
32 #endif
33
34+extern int hflag; /* Generate relocatable executable
35+ */
36 extern int pflag; /* print linker command file flag
37 */
38 extern int uflag; /* Listing relocation flag
Adrien Destugues69a6e722017-06-03 10:17:17 +020039diff --git a/sdas/linksrc/lkdata.c b/sdas/linksrc/lkdata.c
PulkoMandy3783e422023-05-02 17:40:17 +020040index 169e8c1..8686631 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020041--- a/sdas/linksrc/lkdata.c
42+++ b/sdas/linksrc/lkdata.c
43@@ -66,6 +66,9 @@ int oflag; /* Output file type flag
PulkoMandy2aeca062014-06-28 23:18:25 +020044 int objflg; /* Linked file/library object output flag
45 */
46
47+int hflag; /* Generate relocatable executable
48+ */
49+
50 #if NOICE
51 int jflag; /* NoICE output flag
52 */
Adrien Destugues69a6e722017-06-03 10:17:17 +020053diff --git a/sdas/linksrc/lkmain.c b/sdas/linksrc/lkmain.c
PulkoMandy3783e422023-05-02 17:40:17 +020054index daf5515..d690d46 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020055--- a/sdas/linksrc/lkmain.c
56+++ b/sdas/linksrc/lkmain.c
PulkoMandy3783e422023-05-02 17:40:17 +020057@@ -212,6 +212,7 @@ main(int argc, char *argv[])
PulkoMandy2aeca062014-06-28 23:18:25 +020058 startp->f_idp = "";
59
60 pflag = 1;
61+ hflag = 0;
62
63 for(i=1; i<argc; i++) {
64 ip = ib;
PulkoMandy3783e422023-05-02 17:40:17 +020065@@ -979,6 +980,11 @@ parse()
PulkoMandy2aeca062014-06-28 23:18:25 +020066 }
67 return(0);
68
69+ case 'h':
70+ case 'H':
71+ hflag = 1;
72+ break;
73+
74 case 'I':
75 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
76 iramsav();
Adrien Destugues69a6e722017-06-03 10:17:17 +020077diff --git a/sdas/linksrc/lkrloc3.c b/sdas/linksrc/lkrloc3.c
Adrien Destugues1b572422020-12-17 21:53:16 +010078index b330184..0a83e0f 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020079--- a/sdas/linksrc/lkrloc3.c
80+++ b/sdas/linksrc/lkrloc3.c
PulkoMandy2aeca062014-06-28 23:18:25 +020081@@ -31,6 +31,7 @@
82 */
83
84 #include "aslink.h"
85+#include "lkrrel.h"
86
87 /*)Module lkrloc3.c
88 *
Adrien Destugues69a6e722017-06-03 10:17:17 +020089@@ -332,6 +333,9 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +020090 * Do remaining relocations
91 */
92 while (more()) {
93+ int output_relocation_record;
94+ int raddr;
95+
96 error = 0;
97 mode = (int) eval();
98
Adrien Destugues1b572422020-12-17 21:53:16 +010099@@ -390,6 +394,93 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +0200100 reli -= paga + pags;
101 }
102
103+ /* KevT 28-05-2005 */
104+
105+ if (hflag)
106+ {
107+ output_relocation_record = 0;
108+ if (mode & R3_SYM)
109+ {
110+ /* If the symbol is defined in a absolute area, then we do not
111+ output a record. This allows us to reference absolute addresses
112+ in our code, but it can still be relocated */
113+
114+ /* If the symbol is relative, it is within our relocatable program */
115+
116+ /* printf("Symbol: %s\n",s[rindex]->s_id); */
117+ if ((s[rindex]->s_axp->a_bap->a_flag & A4_ABS)==0)
118+ {
119+ output_relocation_record=1;
120+ }
121+ }
122+ else
123+ {
124+ /* If the area is absolute then we do not output a record.
125+ This allows us to reference absolute memory, but still the code
126+ can be relocated. */
127+ /* If the area is relative, it refers to data that is part of the
128+ relocatable program */
129+
130+ /* printf("Area: %s\n",a[rindex]->a_bap->a_id); */
131+ if ((a[rindex]->a_bap->a_flag & A4_ABS)==0)
132+ {
133+ output_relocation_record=1;
134+ }
135+ }
136+
137+ if (output_relocation_record)
138+ {
139+ a_uint relocate_address = pc+(rtp-rtofst);
140+ if (hilo)
141+ {
142+ raddr = reli + ((rtval[rtp]&0x0ff)<<8) + (rtval[rtp+1]&0x0ff);
143+ }
144+ else
145+ {
146+ raddr = reli + ((rtval[rtp+1]&0x0ff)<<8) + (rtval[rtp]&0x0ff);
147+ }
148+ /*printf("Relocation modify address: %04x\n",relocate_address); */
149+ /*printf("Relocation address: %04x\n",raddr); */
150+ if (mode & R3_BYTE)
151+ {
152+ if (mode & R3_BYTX)
153+ {
154+ if (mode & R3_MSB)
155+ {
156+
157+relrec8hi(relocate_address,raddr);
158+ }
159+ else
160+ {
161+
162+relrec8lo(relocate_address,raddr);
163+ }
164+ }
165+ else
166+ {
167+ printf("not supported");
168+ }
169+ }
170+ else
171+ {
172+ if (mode & R3_BYTX)
173+ {
174+ if (mode & R3_MSB)
175+ {
176+ printf("not supported");
177+ }
178+ else
179+ {
180+ printf("not supported");
181+ }
182+ }
183+ else
184+ {
185+ relrec16(relocate_address);
186+ }
187+ }
188+ }
189+ }
Adrien Destugues1b572422020-12-17 21:53:16 +0100190
191 /* pdk instruction fusion */
192 if (TARGET_IS_PDK) {
193@@ -856,6 +947,12 @@ rele3()
PulkoMandy2aeca062014-06-28 23:18:25 +0200194 if (uflag != 0) {
195 lkulist(0);
196 }
197+
198+ /* output relocation data */
199+ if (hflag) {
200+ relrecwrite();
201+ }
202+
203 if (oflag != 0) {
204 lkflush();
205 lkfclose();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200206diff --git a/sdas/linksrc/lkrrel.c b/sdas/linksrc/lkrrel.c
207new file mode 100644
PulkoMandy3783e422023-05-02 17:40:17 +0200208index 0000000..0d9f943
Adrien Destugues69a6e722017-06-03 10:17:17 +0200209--- /dev/null
210+++ b/sdas/linksrc/lkrrel.c
PulkoMandy3783e422023-05-02 17:40:17 +0200211@@ -0,0 +1,256 @@
PulkoMandy2aeca062014-06-28 23:18:25 +0200212+/* (c) Kevin Thacker, May 2005 */
213+#include <stdio.h>
214+#include <string.h>
215+#include <stdlib.h>
216+#include "aslink.h"
217+#include "lkrrel.h"
218+
219+struct relrechead
220+{
221+ int count;
222+ struct relrec *head;
223+};
224+
225+/* 16-bit values, add full 16-bit base address */
226+
227+static struct relrechead head16= {0,NULL};
228+/* 8-bit, but add high byte of 16-bit base address */
229+static struct relrechead head8hi = {0,NULL};
230+/* 8-bit, but add low byte of 16-bit base address */
231+static struct relrechead head8lo = {0,NULL};
232+
233+/* internal; free's list */
234+static void relrecfree(struct relrechead *head)
235+{
236+ struct relrec *cur = head->head;
237+
238+ while (cur!=NULL)
239+ {
240+ struct relrec *next = cur->next;
241+ free(cur);
242+
243+ cur = next;
244+ }
245+}
246+
247+/* free relocation record list; e.g. on exit */
248+void freerelrec()
249+{
250+ relrecfree(&head16);
251+ relrecfree(&head8hi);
252+ relrecfree(&head8lo);
253+}
254+
255+/* internal; allocate a relocation record */
256+static void newrelrec(struct relrechead *head, a_uint addr, a_uint symaddr)
257+{
258+ struct relrec *rec;
259+
260+ rec = (struct relrec *) malloc(sizeof(struct relrec));
261+
262+ /* error if allocation failed */
263+ if (rec==NULL)
264+ return;
265+
266+ rec->addr = addr;
267+ rec->symaddr = symaddr;
268+
269+ /* add to start of list */
270+ rec->next = head->head;
271+ head->head = rec;
272+ head->count++;
273+}
274+
275+/* add item to 16-bit relocation record list */
276+void relrec16(a_uint addr)
277+{
278+ newrelrec(&head16, addr,0);
279+}
280+
281+/* add item to 8-bit (high) relocation record list */
282+void relrec8hi(a_uint addr, a_uint symaddr)
283+{
284+ newrelrec(&head8hi, addr,symaddr);
285+}
286+
287+/* add address to 8-bit (low) relocation list */
288+void relrec8lo(a_uint addr, a_uint symaddr)
289+{
290+ newrelrec(&head8lo, addr,symaddr);
291+}
292+
293+/* internal; compare two addresses within two relocate records */
294+static int relreccompare(const void *a, const void *b)
295+{
296+ const struct relrec *relreca = (const struct relrec *)a;
297+ const struct relrec *relrecb = (const struct relrec *)b;
298+
299+ return (relreca->addr-relrecb->addr);
300+}
301+
302+/* sort a list of relocate records and return an array of the records */
303+static struct relrec *relrecsort(struct relrechead *head)
304+{
305+ int count;
306+ struct relrec *reclist;
307+ struct relrec *cur;
308+
309+ if (head->count==0)
310+ return NULL;
311+
312+ /* allocate list to hold all items */
313+ reclist = (struct relrec *)malloc(sizeof(struct relrec)*head->count);
314+
315+ if (reclist==NULL)
316+ return NULL;
317+
318+ /* fill list */
319+ count = 0;
320+ cur = head->head;
321+ while (cur!=NULL)
322+ {
323+ memcpy(&reclist[count],cur,sizeof(struct relrec));
324+ count++;
325+ cur = cur->next;
326+ }
327+
328+ /* sort into ascending address order */
329+ qsort(reclist, count, sizeof(struct relrec),relreccompare);
330+
331+ return reclist;
332+}
333+
334+int outbyte(int addr, char byte)
335+{
336+ rtval[0] = addr&0x0ff;
337+ rtval[1] = (addr>>8)&0x0ff;
PulkoMandy3783e422023-05-02 17:40:17 +0200338+ rtval[2] = (addr>>16)&0x0ff;
339+
340+ rtval[3] = byte&0x0ff;
341+ addr+=1;
PulkoMandy2aeca062014-06-28 23:18:25 +0200342+ rtflg[0] = 1;
343+ rtflg[1] = 1;
344+ rtflg[2] = 1;
PulkoMandy3783e422023-05-02 17:40:17 +0200345+ rtflg[3] = 1;
346+ rtcnt = 4;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200347+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200348+ return addr;
349+}
350+
351+void relrecwritelist1(struct relrechead *list,int *addrptr)
352+{
353+ int i;
354+ struct relrec *relreclist;
355+ int addr;
356+
357+ addr = *addrptr;
358+
359+ relreclist = relrecsort(list);
360+
361+ if (relreclist!=NULL)
362+ {
363+ int prevaddr = 0;
364+ for (i=0; i<list->count; i++)
365+ {
366+ struct relrec *cur = &relreclist[i];
367+
368+ int delta = cur->addr-prevaddr;
369+
370+ if (delta>254)
371+ {
372+ int largedelta = delta-1;
373+ addr = outbyte(addr,0x0ff);
374+ addr = outbyte(addr,largedelta&0x0ff);
375+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
376+ delta = 1;
377+ }
378+ prevaddr = cur->addr;
379+ addr = outbyte(addr,delta&0x0ff);
380+ }
381+
382+ free(relreclist);
383+ }
384+
385+ addr = outbyte(addr, 0);
386+
387+ *addrptr = addr;
388+
389+}
390+
391+void relrecwritelist2(struct relrechead *list,int *addrptr)
392+{
393+ int i;
394+ struct relrec *relreclist;
395+ int addr;
396+
397+ addr = *addrptr;
398+
399+ relreclist = relrecsort(list);
400+
401+ if (relreclist!=NULL)
402+ {
403+ int prevaddr = 0;
404+ for (i=0; i<list->count; i++)
405+ {
406+ struct relrec *cur = &relreclist[i];
407+ int delta = cur->addr-prevaddr;
408+ prevaddr = cur->addr;
409+
410+ if (delta>254)
411+ {
412+ int largedelta = delta-1;
413+ addr = outbyte(addr,0x0ff);
414+ addr = outbyte(addr,largedelta&0x0ff);
415+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
416+ delta = 1;
417+ }
418+
419+ addr = outbyte(addr,delta&0x0ff);
420+ addr = outbyte(addr,cur->symaddr&0x0ff);
421+ }
422+
423+ free(relreclist);
424+ }
425+
426+ addr = outbyte(addr,0);
427+
428+ *addrptr = addr;
429+
430+}
431+
432+
433+void relrecwrite()
434+{
435+ int areasize = 0;
436+
437+ struct area *cur = areap;
438+ while (cur!=NULL)
439+ {
440+ areasize+=cur->a_size;
441+ cur=cur->a_ap;
442+ }
443+
Adrien Destugues69a6e722017-06-03 10:17:17 +0200444+ //printf("total length before relocation records: %04x\n",areasize);
PulkoMandy2aeca062014-06-28 23:18:25 +0200445+
446+ /* re-write offset to relocation records */
447+ rtval[0] = 0;
448+ rtval[1] = 0;
PulkoMandy3783e422023-05-02 17:40:17 +0200449+ rtval[2] = 0;
450+ rtval[3] = areasize&0x0ff;
451+ rtval[4] = (areasize>>8)&0x0ff;
PulkoMandy2aeca062014-06-28 23:18:25 +0200452+ rtflg[0] = 1;
453+ rtflg[1] = 1;
454+ rtflg[2] = 1;
455+ rtflg[3] = 1;
PulkoMandy3783e422023-05-02 17:40:17 +0200456+ rtflg[4] = 1;
457+ rtcnt = 5;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200458+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200459+
460+
461+ int addr = areasize;
462+
463+
464+ relrecwritelist1(&head16,&addr);
465+ relrecwritelist1(&head8lo,&addr);
466+ relrecwritelist2(&head8hi,&addr);
467+}
Adrien Destugues69a6e722017-06-03 10:17:17 +0200468diff --git a/sdas/linksrc/lkrrel.h b/sdas/linksrc/lkrrel.h
469new file mode 100644
470index 0000000..ca1cfd4
471--- /dev/null
472+++ b/sdas/linksrc/lkrrel.h
PulkoMandy2aeca062014-06-28 23:18:25 +0200473@@ -0,0 +1,17 @@
474+/* relocation record */
475+struct relrec
476+{
477+ /* next item */
478+ struct relrec *next;
479+
480+ /* address of relocate */
481+ a_uint addr;
482+
483+ a_uint symaddr;
484+};
485+
486+void relrec16(a_uint addr);
487+void relrec8lo(a_uint addr, a_uint symaddr);
488+void relrec8hi(a_uint addr, a_uint symaddr);
489+void freerelrec();
490+void relrecwrite();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200491--
PulkoMandy3783e422023-05-02 17:40:17 +02004922.37.3
Adrien Destugues69a6e722017-06-03 10:17:17 +0200493
494