blob: 4c3f857e612d31e2169a354a8495855ec1bbd1a6 [file] [log] [blame]
Adrien Destugues1b572422020-12-17 21:53:16 +01001From 64c8f32ebb624c1b58a0ab5683eed7577d38a29d 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
4Subject: Import Kevin Thacker patch for runtime relocation support.
5
6
7diff --git a/sdas/linksrc/Makefile.in b/sdas/linksrc/Makefile.in
Adrien Destugues1b572422020-12-17 21:53:16 +01008index 43e16f5..e37b167 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +02009--- a/sdas/linksrc/Makefile.in
10+++ b/sdas/linksrc/Makefile.in
11@@ -47,7 +47,7 @@ ASXXLIBSRC = strcmpi.c
PulkoMandy2aeca062014-06-28 23:18:25 +020012 SRC = lk_readnl.c lkaomf51.c lkar.c lkarea.c lkdata.c lkelf.c lkeval.c \
13 lkhead.c lklex.c lklib.c lklibr.c lklist.c lkmain.c lkmem.c \
14 lknoice.c lkout.c lkrel.c lkrloc.c lkrloc3.c lks19.c lksdcclib.c \
15- lksym.c sdld.c lksdcdb.c lkbank.c
16+ lksym.c sdld.c lksdcdb.c lkbank.c lkrrel.c
17
18 LKSOURCES = $(SRC) $(ASXXLIBSRC:%.c=$(ASXXLIB)/%.c)
19
Adrien Destugues69a6e722017-06-03 10:17:17 +020020diff --git a/sdas/linksrc/aslink.h b/sdas/linksrc/aslink.h
Adrien Destugues1b572422020-12-17 21:53:16 +010021index ebad061..7dce058 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020022--- a/sdas/linksrc/aslink.h
23+++ b/sdas/linksrc/aslink.h
24@@ -1033,6 +1033,8 @@ extern int yflag; /* -y, enable SDCC Debug output
PulkoMandy2aeca062014-06-28 23:18:25 +020025 */
26 #endif
27
28+extern int hflag; /* Generate relocatable executable
29+ */
30 extern int pflag; /* print linker command file flag
31 */
32 extern int uflag; /* Listing relocation flag
Adrien Destugues69a6e722017-06-03 10:17:17 +020033diff --git a/sdas/linksrc/lkdata.c b/sdas/linksrc/lkdata.c
Adrien Destugues1b572422020-12-17 21:53:16 +010034index e03cd6a..db7c8ff 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020035--- a/sdas/linksrc/lkdata.c
36+++ b/sdas/linksrc/lkdata.c
37@@ -66,6 +66,9 @@ int oflag; /* Output file type flag
PulkoMandy2aeca062014-06-28 23:18:25 +020038 int objflg; /* Linked file/library object output flag
39 */
40
41+int hflag; /* Generate relocatable executable
42+ */
43+
44 #if NOICE
45 int jflag; /* NoICE output flag
46 */
Adrien Destugues69a6e722017-06-03 10:17:17 +020047diff --git a/sdas/linksrc/lkmain.c b/sdas/linksrc/lkmain.c
Adrien Destugues1b572422020-12-17 21:53:16 +010048index fcf7242..5535b95 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020049--- a/sdas/linksrc/lkmain.c
50+++ b/sdas/linksrc/lkmain.c
51@@ -233,6 +233,7 @@ main(int argc, char *argv[])
PulkoMandy2aeca062014-06-28 23:18:25 +020052 startp->f_idp = "";
53
54 pflag = 1;
55+ hflag = 0;
56
57 for(i=1; i<argc; i++) {
58 ip = ib;
Adrien Destugues1b572422020-12-17 21:53:16 +010059@@ -999,6 +1000,11 @@ parse()
PulkoMandy2aeca062014-06-28 23:18:25 +020060 }
61 return(0);
62
63+ case 'h':
64+ case 'H':
65+ hflag = 1;
66+ break;
67+
68 case 'I':
69 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
70 iramsav();
Adrien Destugues69a6e722017-06-03 10:17:17 +020071diff --git a/sdas/linksrc/lkrloc3.c b/sdas/linksrc/lkrloc3.c
Adrien Destugues1b572422020-12-17 21:53:16 +010072index b330184..0a83e0f 100644
Adrien Destugues69a6e722017-06-03 10:17:17 +020073--- a/sdas/linksrc/lkrloc3.c
74+++ b/sdas/linksrc/lkrloc3.c
PulkoMandy2aeca062014-06-28 23:18:25 +020075@@ -31,6 +31,7 @@
76 */
77
78 #include "aslink.h"
79+#include "lkrrel.h"
80
81 /*)Module lkrloc3.c
82 *
Adrien Destugues69a6e722017-06-03 10:17:17 +020083@@ -332,6 +333,9 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +020084 * Do remaining relocations
85 */
86 while (more()) {
87+ int output_relocation_record;
88+ int raddr;
89+
90 error = 0;
91 mode = (int) eval();
92
Adrien Destugues1b572422020-12-17 21:53:16 +010093@@ -390,6 +394,93 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +020094 reli -= paga + pags;
95 }
96
97+ /* KevT 28-05-2005 */
98+
99+ if (hflag)
100+ {
101+ output_relocation_record = 0;
102+ if (mode & R3_SYM)
103+ {
104+ /* If the symbol is defined in a absolute area, then we do not
105+ output a record. This allows us to reference absolute addresses
106+ in our code, but it can still be relocated */
107+
108+ /* If the symbol is relative, it is within our relocatable program */
109+
110+ /* printf("Symbol: %s\n",s[rindex]->s_id); */
111+ if ((s[rindex]->s_axp->a_bap->a_flag & A4_ABS)==0)
112+ {
113+ output_relocation_record=1;
114+ }
115+ }
116+ else
117+ {
118+ /* If the area is absolute then we do not output a record.
119+ This allows us to reference absolute memory, but still the code
120+ can be relocated. */
121+ /* If the area is relative, it refers to data that is part of the
122+ relocatable program */
123+
124+ /* printf("Area: %s\n",a[rindex]->a_bap->a_id); */
125+ if ((a[rindex]->a_bap->a_flag & A4_ABS)==0)
126+ {
127+ output_relocation_record=1;
128+ }
129+ }
130+
131+ if (output_relocation_record)
132+ {
133+ a_uint relocate_address = pc+(rtp-rtofst);
134+ if (hilo)
135+ {
136+ raddr = reli + ((rtval[rtp]&0x0ff)<<8) + (rtval[rtp+1]&0x0ff);
137+ }
138+ else
139+ {
140+ raddr = reli + ((rtval[rtp+1]&0x0ff)<<8) + (rtval[rtp]&0x0ff);
141+ }
142+ /*printf("Relocation modify address: %04x\n",relocate_address); */
143+ /*printf("Relocation address: %04x\n",raddr); */
144+ if (mode & R3_BYTE)
145+ {
146+ if (mode & R3_BYTX)
147+ {
148+ if (mode & R3_MSB)
149+ {
150+
151+relrec8hi(relocate_address,raddr);
152+ }
153+ else
154+ {
155+
156+relrec8lo(relocate_address,raddr);
157+ }
158+ }
159+ else
160+ {
161+ printf("not supported");
162+ }
163+ }
164+ else
165+ {
166+ if (mode & R3_BYTX)
167+ {
168+ if (mode & R3_MSB)
169+ {
170+ printf("not supported");
171+ }
172+ else
173+ {
174+ printf("not supported");
175+ }
176+ }
177+ else
178+ {
179+ relrec16(relocate_address);
180+ }
181+ }
182+ }
183+ }
Adrien Destugues1b572422020-12-17 21:53:16 +0100184
185 /* pdk instruction fusion */
186 if (TARGET_IS_PDK) {
187@@ -856,6 +947,12 @@ rele3()
PulkoMandy2aeca062014-06-28 23:18:25 +0200188 if (uflag != 0) {
189 lkulist(0);
190 }
191+
192+ /* output relocation data */
193+ if (hflag) {
194+ relrecwrite();
195+ }
196+
197 if (oflag != 0) {
198 lkflush();
199 lkfclose();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200200diff --git a/sdas/linksrc/lkrrel.c b/sdas/linksrc/lkrrel.c
201new file mode 100644
202index 0000000..e9e8383
203--- /dev/null
204+++ b/sdas/linksrc/lkrrel.c
PulkoMandy2aeca062014-06-28 23:18:25 +0200205@@ -0,0 +1,251 @@
206+/* (c) Kevin Thacker, May 2005 */
207+#include <stdio.h>
208+#include <string.h>
209+#include <stdlib.h>
210+#include "aslink.h"
211+#include "lkrrel.h"
212+
213+struct relrechead
214+{
215+ int count;
216+ struct relrec *head;
217+};
218+
219+/* 16-bit values, add full 16-bit base address */
220+
221+static struct relrechead head16= {0,NULL};
222+/* 8-bit, but add high byte of 16-bit base address */
223+static struct relrechead head8hi = {0,NULL};
224+/* 8-bit, but add low byte of 16-bit base address */
225+static struct relrechead head8lo = {0,NULL};
226+
227+/* internal; free's list */
228+static void relrecfree(struct relrechead *head)
229+{
230+ struct relrec *cur = head->head;
231+
232+ while (cur!=NULL)
233+ {
234+ struct relrec *next = cur->next;
235+ free(cur);
236+
237+ cur = next;
238+ }
239+}
240+
241+/* free relocation record list; e.g. on exit */
242+void freerelrec()
243+{
244+ relrecfree(&head16);
245+ relrecfree(&head8hi);
246+ relrecfree(&head8lo);
247+}
248+
249+/* internal; allocate a relocation record */
250+static void newrelrec(struct relrechead *head, a_uint addr, a_uint symaddr)
251+{
252+ struct relrec *rec;
253+
254+ rec = (struct relrec *) malloc(sizeof(struct relrec));
255+
256+ /* error if allocation failed */
257+ if (rec==NULL)
258+ return;
259+
260+ rec->addr = addr;
261+ rec->symaddr = symaddr;
262+
263+ /* add to start of list */
264+ rec->next = head->head;
265+ head->head = rec;
266+ head->count++;
267+}
268+
269+/* add item to 16-bit relocation record list */
270+void relrec16(a_uint addr)
271+{
272+ newrelrec(&head16, addr,0);
273+}
274+
275+/* add item to 8-bit (high) relocation record list */
276+void relrec8hi(a_uint addr, a_uint symaddr)
277+{
278+ newrelrec(&head8hi, addr,symaddr);
279+}
280+
281+/* add address to 8-bit (low) relocation list */
282+void relrec8lo(a_uint addr, a_uint symaddr)
283+{
284+ newrelrec(&head8lo, addr,symaddr);
285+}
286+
287+/* internal; compare two addresses within two relocate records */
288+static int relreccompare(const void *a, const void *b)
289+{
290+ const struct relrec *relreca = (const struct relrec *)a;
291+ const struct relrec *relrecb = (const struct relrec *)b;
292+
293+ return (relreca->addr-relrecb->addr);
294+}
295+
296+/* sort a list of relocate records and return an array of the records */
297+static struct relrec *relrecsort(struct relrechead *head)
298+{
299+ int count;
300+ struct relrec *reclist;
301+ struct relrec *cur;
302+
303+ if (head->count==0)
304+ return NULL;
305+
306+ /* allocate list to hold all items */
307+ reclist = (struct relrec *)malloc(sizeof(struct relrec)*head->count);
308+
309+ if (reclist==NULL)
310+ return NULL;
311+
312+ /* fill list */
313+ count = 0;
314+ cur = head->head;
315+ while (cur!=NULL)
316+ {
317+ memcpy(&reclist[count],cur,sizeof(struct relrec));
318+ count++;
319+ cur = cur->next;
320+ }
321+
322+ /* sort into ascending address order */
323+ qsort(reclist, count, sizeof(struct relrec),relreccompare);
324+
325+ return reclist;
326+}
327+
328+int outbyte(int addr, char byte)
329+{
330+ rtval[0] = addr&0x0ff;
331+ rtval[1] = (addr>>8)&0x0ff;
332+ rtval[2] = byte&0x0ff;
333+ addr+=1;
334+ rtflg[0] = 1;
335+ rtflg[1] = 1;
336+ rtflg[2] = 1;
337+ rtcnt = 3;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200338+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200339+ return addr;
340+}
341+
342+void relrecwritelist1(struct relrechead *list,int *addrptr)
343+{
344+ int i;
345+ struct relrec *relreclist;
346+ int addr;
347+
348+ addr = *addrptr;
349+
350+ relreclist = relrecsort(list);
351+
352+ if (relreclist!=NULL)
353+ {
354+ int prevaddr = 0;
355+ for (i=0; i<list->count; i++)
356+ {
357+ struct relrec *cur = &relreclist[i];
358+
359+ int delta = cur->addr-prevaddr;
360+
361+ if (delta>254)
362+ {
363+ int largedelta = delta-1;
364+ addr = outbyte(addr,0x0ff);
365+ addr = outbyte(addr,largedelta&0x0ff);
366+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
367+ delta = 1;
368+ }
369+ prevaddr = cur->addr;
370+ addr = outbyte(addr,delta&0x0ff);
371+ }
372+
373+ free(relreclist);
374+ }
375+
376+ addr = outbyte(addr, 0);
377+
378+ *addrptr = addr;
379+
380+}
381+
382+void relrecwritelist2(struct relrechead *list,int *addrptr)
383+{
384+ int i;
385+ struct relrec *relreclist;
386+ int addr;
387+
388+ addr = *addrptr;
389+
390+ relreclist = relrecsort(list);
391+
392+ if (relreclist!=NULL)
393+ {
394+ int prevaddr = 0;
395+ for (i=0; i<list->count; i++)
396+ {
397+ struct relrec *cur = &relreclist[i];
398+ int delta = cur->addr-prevaddr;
399+ prevaddr = cur->addr;
400+
401+ if (delta>254)
402+ {
403+ int largedelta = delta-1;
404+ addr = outbyte(addr,0x0ff);
405+ addr = outbyte(addr,largedelta&0x0ff);
406+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
407+ delta = 1;
408+ }
409+
410+ addr = outbyte(addr,delta&0x0ff);
411+ addr = outbyte(addr,cur->symaddr&0x0ff);
412+ }
413+
414+ free(relreclist);
415+ }
416+
417+ addr = outbyte(addr,0);
418+
419+ *addrptr = addr;
420+
421+}
422+
423+
424+void relrecwrite()
425+{
426+ int areasize = 0;
427+
428+ struct area *cur = areap;
429+ while (cur!=NULL)
430+ {
431+ areasize+=cur->a_size;
432+ cur=cur->a_ap;
433+ }
434+
Adrien Destugues69a6e722017-06-03 10:17:17 +0200435+ //printf("total length before relocation records: %04x\n",areasize);
PulkoMandy2aeca062014-06-28 23:18:25 +0200436+
437+ /* re-write offset to relocation records */
438+ rtval[0] = 0;
439+ rtval[1] = 0;
440+ rtval[2] = areasize&0x0ff;
441+ rtval[3] = (areasize>>8)&0x0ff;
442+ rtflg[0] = 1;
443+ rtflg[1] = 1;
444+ rtflg[2] = 1;
445+ rtflg[3] = 1;
446+ rtcnt = 4;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200447+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200448+
449+
450+ int addr = areasize;
451+
452+
453+ relrecwritelist1(&head16,&addr);
454+ relrecwritelist1(&head8lo,&addr);
455+ relrecwritelist2(&head8hi,&addr);
456+}
Adrien Destugues69a6e722017-06-03 10:17:17 +0200457diff --git a/sdas/linksrc/lkrrel.h b/sdas/linksrc/lkrrel.h
458new file mode 100644
459index 0000000..ca1cfd4
460--- /dev/null
461+++ b/sdas/linksrc/lkrrel.h
PulkoMandy2aeca062014-06-28 23:18:25 +0200462@@ -0,0 +1,17 @@
463+/* relocation record */
464+struct relrec
465+{
466+ /* next item */
467+ struct relrec *next;
468+
469+ /* address of relocate */
470+ a_uint addr;
471+
472+ a_uint symaddr;
473+};
474+
475+void relrec16(a_uint addr);
476+void relrec8lo(a_uint addr, a_uint symaddr);
477+void relrec8hi(a_uint addr, a_uint symaddr);
478+void freerelrec();
479+void relrecwrite();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200480--
Adrien Destugues1b572422020-12-17 21:53:16 +01004812.28.0
Adrien Destugues69a6e722017-06-03 10:17:17 +0200482
483