blob: fdfbcf6e18af3d9fad70fcb356ef4d42a0b85e39 [file] [log] [blame]
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();