diff --git a/xa/misc/ldo65.c.orig b/xa/misc/ldo65.c.orig deleted file mode 100644 index 9f4b70b..0000000 --- a/xa/misc/ldo65.c.orig +++ /dev/null @@ -1,1078 +0,0 @@ -/* ldo65 -- A part of xa65 - 65xx/65816 cross-assembler and utility suite - * o65 relocatable object file linker - * - * A part of the xa65 - 65xx/65816 cross-assembler and utility suite - * - * Copyright (C) 1997-2023 André Fachat (fachat@web.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#ifndef _MSC_VER -#include -#endif -#include - -#include "version.h" - -#define BUF (9*2+8) /* 16 bit header */ - -#define programname "ldo65" -#define progversion "v0.2.0" -#define author "Written by Andre Fachat" -#define copyright "Copyright (C) 1997-2023 Andre Fachat. Formerly ld65." - -#undef DEBUG - -/* - -The process of linking works as follows: - -1. Every file is loaded in turn via load_file() -2. Calculate new base addresses per segment -3. Merge all globals from all files into a single table, checking for duplicates -4. Resolve undefined labels, and merge remaining into global list -5. relocate all segments, create global relocation tables -6. verify undefined labels -7. write out target file - -*/ - -typedef struct { - char *name; - int len; - int newidx; /* index in new global undef table (for reloc) */ - int resolved; /* index in current global label table after resolve (-1 is not found) */ -} undefs; - -/* file information */ -typedef struct { - char *fname; /* file name */ - size_t fsize; /* length of file */ - unsigned char *buf; /* file content */ - - int tbase; /* header: text base */ - int tlen; /* text length */ - int dbase; /* data base */ - int dlen; /* data length */ - int bbase; /* bss base */ - int blen; /* bss length */ - int zbase; /* zero base */ - int zlen; /* zero length */ - - int tdiff; /* text segment relocation diff */ - int ddiff; /* data segment relocation diff */ - int bdiff; /* bss segment relocation diff */ - int zdiff; /* zero segment relocation diff */ - - int tpos; /* position of text segment in file */ - int dpos; /* position of data segment in file */ - int upos; /* position of undef'd list in file */ - int trpos; /* position of text reloc tab in file */ - int drpos; /* position of data reloc tab in file */ - int gpos; /* position of globals list in file */ - - int nundef; /* number of undefined labels */ - undefs *ud; /* undefined labels list NULL if none */ -} file65; - -/* globally defined lables are stored in this struct */ -typedef struct { - char *name; - int len; /* length of labelname */ - int fl; /* 0=ok, 1=multiply defined */ - int val; /* address value */ - int seg; /* segment */ - file65 *file; /* in which file is it? */ -} glob; - - -file65 *load_file(char *fname); - -int read_options(unsigned char *f); -int read_undef(unsigned char *f, file65 *fp); -int write_undef(FILE *f, file65 *fp); -int check_undef(file65 *fp, char *defined[], int ndefined); -int len_reloc_seg(unsigned char *buf, int ri); -int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, unsigned char *obuf, int *lastaddrp, int *rop, file65 *fp); -unsigned char *reloc_globals(unsigned char *, file65 *fp); -int read_globals(file65 *file); -int write_options(FILE *fp, file65 *file); -int write_reloc(file65 *fp[], int nfp, FILE *f); -int write_globals(FILE *fp); -int write_nglobals(FILE *fp, char **globdef, int nglobal); -int find_global(unsigned char *name); -int resolve_undef(file65 *file, int *remains); - -file65 file; -unsigned char cmp[] = { 1, 0, 'o', '6', '5' }; -unsigned char hdr[26] = { 1, 0, 'o', '6', '5', 0 }; - - -void usage(FILE *fp) -{ - fprintf(fp, - "Usage: %s [OPTION]... [FILE]...\n" - "Linker for o65 object files\n" - "\n" - " -b? addr relocates segment `?' (i.e. `t' for text segment,\n" - " `d' for data, `b' for bss, and `z' for zeropage) to the new\n" - " address `addr'\n" - " -o file uses `file' as output file. Default is `a.o65'\n" - " -G suppress writing of globals\n" - " -U accept any undef'd labels after linking\n" - " -L accept specific given undef'd labels after linking\n" - " -g only export the globals defined with (multiple) -g options\n" - " --version output version information and exit\n" - " --help display this help and exit\n", - programname); -} - -int main(int argc, char *argv[]) { - int noglob=0; - int undefok=0; - int i = 1; - int tbase = 0x0400, dbase = 0x1000, bbase = 0x4000, zbase = 0x0002; - int ttlen, tdlen, tblen, tzlen; - char *outfile = "a.o65"; - int j, jm; - file65 *file, **fp = NULL; - FILE *fd; - int nundef = 0; // counter/index in list of remaining undef'd labels - - char *arg; - - char **defined = NULL; - int ndefined = 0; - int ndefalloc = 0; - - // globals allowed by -g - char **globdef = NULL; - int nglobal = 0; - int ngloballoc = 0; - - if (argc <= 1) { - usage(stderr); - exit(1); - } - - if (strstr(argv[1], "--help") || strstr(argv[1], "-?")) { - usage(stdout); - exit(0); - } - - if (strstr(argv[1], "--version")) { - version(programname, progversion, author, copyright); - exit(0); - } - - /* read options */ - while(i= ngloballoc) { - ngloballoc *= 2; - globdef = realloc(globdef, ngloballoc * sizeof(char*)); - } - globdef[nglobal++] = arg; - break; - case 'L': - if(argv[i][2]) arg=argv[i]+2; - else arg=argv[++i]; - if (ndefalloc == 0) { - ndefalloc = 20; - defined = malloc(ndefalloc * sizeof(char*)); - } else - if (ndefined >= ndefalloc) { - ndefalloc *= 2; - defined = realloc(defined, ndefalloc * sizeof(char*)); - } - defined[ndefined++] = arg; - break; - case 'b': - switch(argv[i][2]) { - case 't': - if(argv[i][3]) tbase = atoi(argv[i]+3); - else tbase = atoi(argv[++i]); - break; - case 'd': - if(argv[i][3]) dbase = atoi(argv[i]+3); - else dbase = atoi(argv[++i]); - break; - case 'b': - if(argv[i][3]) bbase = atoi(argv[i]+3); - else bbase = atoi(argv[++i]); - break; - case 'z': - if(argv[i][3]) zbase = atoi(argv[i]+3); - else zbase = atoi(argv[++i]); - break; - default: - printf("Unknown segment type '%c' - ignored!\n", argv[i][2]); - break; - } - break; - default: - fprintf(stderr,"file65: %s unknown option, use '-?' for help\n",argv[i]); - break; - } - i++; - } - - // ------------------------------------------------------------------------- - // step 1 - load files - - /* each file is loaded first */ - j=0; jm=0; fp=NULL; - while(i=jm) fp=realloc(fp, (jm=(jm?jm*2:10))*sizeof(file65*)); - if(!fp) { fprintf(stderr,"Oops, no more memory\n"); exit(1); } - fp[j++] = f; - } else { - exit(1); - } - i++; - } - - // ------------------------------------------------------------------------- - // step 2 - calculate new segment base addresses per file, by - // concatenating the segments per type - - /* now [tdbz]base holds new segment base address */ - /* set total length to zero */ - ttlen = tdlen = tblen = tzlen = 0; - - /* find new addresses for the files and read globals */ - for(i=0;itdiff = ((tbase + ttlen) - file->tbase); - file->ddiff = ((dbase + tdlen) - file->dbase); - file->bdiff = ((bbase + tblen) - file->bbase); - file->zdiff = ((zbase + tzlen) - file->zbase); -/*printf("tbase=%04x, file->tbase=%04x, ttlen=%04x -> tdiff=%04x\n", - tbase, file->tbase, ttlen, file->tdiff);*/ - - /* update globals (for result file) */ - ttlen += file->tlen; - tdlen += file->dlen; - tblen += file->blen; - tzlen += file->zlen; - } - - // ------------------------------------------------------------------------- - // step 3 - merge globals from all files into single table - // - - for(i=0;idrpos - file->trpos); - routdlen += (file->gpos - file->drpos); - - reloc_globals(file->buf+file->gpos, file); - } - - // prep global reloc tables - unsigned char *treloc = malloc(routtlen); - unsigned char *dreloc = malloc(routdlen); - -#ifdef DEBUG - printf("prep'd text reloc table at %p (%d bytes)\n", treloc, routtlen); - printf("prep'd data reloc table at %p (%d bytes)\n", dreloc, routdlen); -#endif - int tro = 0; - int dro = 0; - - // segment position of last relocation entry to compute offsets across files - int lasttaddr = tbase - 1; - int lastdaddr = dbase - 1; - - for(i=0;ibuf, // input buffer - file->tpos, // position of segment in input buffer - file->tbase, // segment base address - file->tdiff, // reloc difference - file->trpos, // position of reloc table in input - treloc, // output reloc buffer - &lasttaddr, // last relocated target address - &tro, // pointer in output reloc bufer - file); - - reloc_seg(file->buf, - file->dpos, - file->dbase, - file->ddiff, - file->drpos, - dreloc, - &lastdaddr, - &dro, - file); - - // change file information to relocated values - file->tbase += file->tdiff; - file->dbase += file->ddiff; - file->bbase += file->bdiff; - file->zbase += file->zdiff; - } - - // finalize global reloc table - treloc[tro++] = 0; - dreloc[dro++] = 0; - - // ------------------------------------------------------------------------- - // step 6 - validate undefined labels - // - - if (nundef > 0 && !undefok) { - int er = 0; - // we have undefined labels, but it's not ok (no -U) - // check -L defined labels - for(i=0;i>8) & 255; - hdr[10] = ttlen & 255; hdr[11] = (ttlen >>8)& 255; - hdr[12] = dbase & 255; hdr[13] = (dbase>>8) & 255; - hdr[14] = tdlen & 255; hdr[15] = (tdlen >>8)& 255; - hdr[16] = bbase & 255; hdr[17] = (bbase>>8) & 255; - hdr[18] = tblen & 255; hdr[19] = (tblen >>8)& 255; - hdr[20] = zbase & 255; hdr[21] = (zbase>>8) & 255; - hdr[22] = tzlen & 255; hdr[23] = (tzlen >>8)& 255; - hdr[24] = 0; hdr[25] = 0; - - // open file - fd = fopen(outfile, "wb"); - if(!fd) { - fprintf(stderr,"Couldn't open output file %s (%s)\n", - outfile, strerror(errno)); - exit(2); - } - - // write header - fwrite(hdr, 1, 26, fd); - - // write options - this writes _all_ options from _all_files! - for(i=0;ibuf + fp[i]->tpos, 1, fp[i]->tlen, fd); - } - - // write data segment - for(i=0;ibuf + fp[i]->dpos, 1, fp[i]->dlen, fd); - } - - // write list of undefined labels - fputc(nundef & 0xff,fd); - fputc((nundef >> 8) & 0xff,fd); - if (nundef > 0) { - for(i=0;i 0) { - write_nglobals(fd, globdef, nglobal); - } else { - fputc(0,fd); - fputc(0,fd); - } - } - - fclose(fd); - return 0; -} - -/***************************************************************************/ - -int write_options(FILE *fp, file65 *file) { - return fwrite(file->buf+BUF, 1, file->tpos-BUF-1, fp); -} - -int read_options(unsigned char *buf) { - int c, l=0; - - c=buf[0]; - while(c && c!=EOF) { - c&=255; - l+=c; - c=buf[l]; - } - return ++l; -} - -/***************************************************************************/ - -int read_undef(unsigned char *buf, file65 *file) { - int bufp; // pointer in input buffer - int startp; // pointer to start of label name - int nlabels; // number of labels in file - undefs *current = NULL; - int i; - - bufp = 0; - nlabels = buf[bufp] + 256*buf[bufp+1]; - bufp += 2; - - file->nundef = nlabels; - - if (nlabels == 0) { - file->ud = NULL; - } else { - file->ud = malloc(nlabels*sizeof(undefs)); - if(!file->ud) { - fprintf(stderr,"Oops, no more memory\n"); - exit(1); - } - i=0; - while(iud[i]; - current->name = (char*) buf+startp; - current->len = bufp-startp-1; - current->resolved = -1; -/*printf("read undef '%s'(%p), len=%d, ll=%d, l=%d, buf[l]=%d\n", - file->ud[i].name, file->ud[i].name, file->ud[i].len,ll,l,buf[l]);*/ - i++; - } - } - return bufp; -} - -int resolve_undef(file65 *file, int *remains) { - int i; - int nlabels = file->nundef; -#ifdef DEBUG -printf("resolved undef file %s (%d undef'd)\n", file->fname, nlabels); -#endif - if (nlabels == 0) { - return 0; - } - undefs *current = file->ud; - - for (i = 0; i < nlabels; i++) { - // store pointer to global in label info - // if NULL is returned, is not resolved - current->resolved = find_global(current->name); -#ifdef DEBUG -printf("resolved undef label %s to: resolved=%d, newidx=%d\n", current->name, current->resolved, *remains); -#endif - if (current->resolved == -1) { - // keep in global undef list - current->newidx = *remains; - *remains += 1; - } - current++; - } - return 0; -} - - -int write_undef(FILE *f, file65 *fp) { - int i; - for (i = 0; i < fp->nundef; i++) { - undefs *current = &fp->ud[i]; - - if (current->resolved == -1) { - // only write unresolved entries - fprintf(f, "%s%c", current->name, 0); - } - } - return 0; -} - -int check_undef(file65 *fp, char *defined[], int ndefined) { - - int er = 0; - int i, j; - for (i = 0; i < fp->nundef; i++) { - undefs *current = &fp->ud[i]; - - if (current->resolved == -1) { - // only check unresolved entries - int found = 0; - for (j = 0; j < ndefined; j++) { - if (defined && !strcmp(defined[j], current->name)) { - // label is found, so it's ok - found = 1; - break; - } - } - if (!found) { - fprintf(stderr, "Unresolved label '%s' from file '%s'\n", - current->name, fp->fname); - er = -1; - } - } - } - return er; -} - - -/***************************************************************************/ - -/* compute and return the length of the relocation table */ -int len_reloc_seg(unsigned char *buf, int ri) { - int type, seg; - - while(buf[ri]) { - if((buf[ri] & 255) == 255) { - ri++; - } else { - ri++; - type = buf[ri] & 0xe0; - seg = buf[ri] & 0x07; -/*printf("reloc entry @ rtab=%p (offset=%d), adr=%04x, type=%02x, seg=%d\n",buf+ri-1, *(buf+ri-1), adr, type, seg);*/ - ri++; - switch(type) { - case 0x80: - break; - case 0x40: - ri++; - break; - case 0x20: - break; - } - if(seg==0) ri+=2; - } - } - return ++ri; -} - -#define reldiff(s) (((s)==2)?fp->tdiff:(((s)==3)?fp->ddiff:(((s)==4)?fp->bdiff:(((s)==5)?fp->zdiff:0)))) - -unsigned char *reloc_globals(unsigned char *buf, file65 *fp) { - int n, old, new, seg; - - n = buf[0] + 256*buf[1]; - buf +=2; - - while(n) { -/*printf("relocating %s, ", buf);*/ - while(*(buf++)); - seg = *buf; - old = buf[1] + 256*buf[2]; - new = old + reldiff(seg); -/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ - buf[1] = new & 255; - buf[2] = (new>>8) & 255; - buf +=3; - n--; - } - return buf; -} - -/***************************************************************************/ - -file65 *load_file(char *fname) { - file65 *file; - struct stat fs; - FILE *fp; - int mode, hlen; - size_t n; - - file=malloc(sizeof(file65)); - if(!file) { - fprintf(stderr,"Oops, not enough memory!\n"); - exit(1); - } - -/*printf("load_file(%s)\n",fname);*/ - - file->fname=fname; - stat(fname, &fs); - file->fsize=fs.st_size; - file->buf=malloc(file->fsize); - if(!file->buf) { - fprintf(stderr,"Oops, no more memory!\n"); - exit(1); - } - - fp = fopen(fname,"rb"); - if(fp) { - n = fread(file->buf, 1, file->fsize, fp); - fclose(fp); - if((n>=file->fsize) && (!memcmp(file->buf, cmp, 5))) { - mode=file->buf[7]*256+file->buf[6]; - if(mode & 0x2000) { - fprintf(stderr,"file65: %s: 32 bit size not supported\n", fname); - free(file->buf); free(file); file=NULL; - } else - if(mode & 0x4000) { - fprintf(stderr,"file65: %s: pagewise relocation not supported\n", - fname); - free(file->buf); free(file); file=NULL; - } else { - hlen = BUF+read_options(file->buf+BUF); - - file->tbase = file->buf[ 9]*256+file->buf[ 8]; - file->tlen = file->buf[11]*256+file->buf[10]; - file->dbase = file->buf[13]*256+file->buf[12]; - file->dlen = file->buf[15]*256+file->buf[14]; - file->bbase = file->buf[17]*256+file->buf[16]; - file->blen = file->buf[19]*256+file->buf[18]; - file->zbase = file->buf[21]*256+file->buf[20]; - file->zlen = file->buf[23]*256+file->buf[22]; - - file->tpos = hlen; - file->dpos = hlen + file->tlen; - file->upos = file->dpos + file->dlen; - file->trpos= file->upos + read_undef(file->buf+file->upos, file); - file->drpos= len_reloc_seg(file->buf, file->trpos); - file->gpos = len_reloc_seg(file->buf, file->drpos); - } - } else { - fprintf(stderr,"Error: %s: not an o65 file\n", fname); - return NULL; - } - } else { - fprintf(stderr,"file65: %s: %s\n", fname, strerror(errno)); - return NULL; - } - return file; -} - -/***************************************************************************/ - -// global list of all global labels -glob *gp = NULL; -// number of global labels -int g=0; -// number of globals for which memory is already allocated -int gm=0; - - -int write_globals(FILE *fp) { - int i; - - fputc(g&255, fp); - fputc((g>>8)&255, fp); - - for(i=0;i>8)&255); - } - return 0; -} - -int write_nglobals(FILE *fp, char **globdef, int nglobal) { - int i, j; - int newnum = 0; - - // first check which defined globals are allowed to be exported - // and clear out the other ones - for (i = 0; i < g; i++) { - for (j = 0; j < nglobal; j++) { - if (!strcmp(gp[i].name, globdef[j])) { - // found - break; - } - } - if (j >= nglobal) { - // not found - gp[i].name = NULL; - } else { - // found, so we inc the counter - newnum++; - } - } - - // then check which globals from the -g list are actually used, and warn about unused ones - for (j = 0; j < nglobal; j++) { - for (i = 0; i < g; i++) { - if (gp[i].name != NULL && !strcmp(gp[i].name, globdef[j])) { - // found - break; - } - } - if (i >= g) { - // not found - fprintf(stderr,"Warning: command line allowed global '%s' is not defined!\n", globdef[j]); - } - } - - // write out only defined globals - fputc(newnum&255, fp); - fputc((newnum>>8)&255, fp); - - for(i=0;i>8)&255); - } - } - return 0; -} - -int read_globals(file65 *fp) { - int i, l, n, old, new, seg, ll; - char *name; - unsigned char *buf = fp->buf + fp->gpos; - - n = buf[0] + 256*buf[1]; - buf +=2; - - while(n) { -/*printf("reading %s, ", buf);*/ - name = (char*) buf; - l=0; - while(buf[l++]); - buf+=l; - ll=l-1; - seg = *buf; - old = buf[1] + 256*buf[2]; - new = old + reldiff(seg); -/*printf("old=%04x, seg=%d, rel=%04x, new=%04x\n", old, seg, reldiff(seg), new);*/ - - /* multiply defined? */ - for(i=0;ifname, gp[i].file->fname); - gp[i].fl = 1; - break; - } - } - /* not already defined */ - if(i>=g) { - if(g>=gm) { - gp = realloc(gp, (gm=(gm?2*gm:40))*sizeof(glob)); - if(!gp) { - fprintf(stderr,"Oops, no more memory\n"); - exit(1); - } - } - if(g>=0x10000) { - fprintf(stderr,"Outch, maximum number of labels (65536) exceeded!\n"); - exit(3); - } - gp[g].name = name; - gp[g].len = ll; - gp[g].seg = seg; - gp[g].val = new; - gp[g].fl = 0; - gp[g].file = fp; -#ifdef DEBUG -printf("set global label '%s' (l=%d, seg=%d, val=%04x)\n", gp[g].name, - gp[g].len, gp[g].seg, gp[g].val); -#endif - g++; - } - - buf +=3; - n--; - } - return 0; -} - -int find_global(unsigned char *name) { - int i; - for (i = 0; i < g; i++) { - - if (!strcmp(gp[i].name, name)) { - // found - return i; - } - } - return -1; -} - -// searches for a global label in a file by name. -// returns the value of a found global value -int find_file_global(unsigned char *bp, file65 *fp, int *seg) { - int i,l; - char *n; - int nl = bp[0]+256*bp[1]; - - l=fp->ud[nl].len; - n=fp->ud[nl].name; -/*printf("find_global(%s (len=%d))\n",n,l);*/ - - for(i=0;i>8) & 255; -/*printf("return gp[%d]=%s (len=%d), val=%04x\n",i,gp[i].name,gp[i].len,gp[i].val);*/ - return gp[i].val; - } - } - fprintf(stderr,"Warning: undefined label '%s' in file %s\n", - n, fp->fname); - return 0; -} - -/***************************************************************************/ - -#define forwardpos() \ - while(addr-lastaddr>254){obuf[ro++]=255;lastaddr+=254;}obuf[ro++]=addr-lastaddr;lastaddr=addr - -int reloc_seg(unsigned char *buf, int pos, int addr, int rdiff, int ri, - unsigned char *obuf, int *lastaddrp, int *rop, file65 *fp) { - int type, seg, old, new, ro, lastaddr, diff; - int base; - - /* - pos = address of current position - ri = position of relocation table in *buf for reading the reloc entries - ro(p) = position of relocation table entry for writing the modified entries - */ - base = addr; - addr--; - ro = *rop; - lastaddr = *lastaddrp - rdiff; - -#ifdef DEBUG -printf("reloc_seg: %s: addr=%04x, pos=%04x, lastaddr=%04x (%04x - %04x)\n", - fp->fname, addr, pos, lastaddr, *lastaddrp, rdiff); -#endif - - while(buf[ri]) { - // still reloc entry - if((buf[ri] & 255) == 255) { - addr += 254; - ri++; - } else { - addr += buf[ri] & 255; - type = buf[ri+1] & 0xe0; - seg = buf[ri+1] & 0x07; -#ifdef DEBUG -printf("reloc entry @ ri=%04x, pos=%04x, type=%02x, seg=%d, offset=%d, reldiff=%04x\n", - ri, pos, type, seg, addr-lastaddr, reldiff(seg)); -#endif - switch(type) { - case 0x80: - // address (word) relocation - old = buf[addr-base+pos] + 256*buf[addr-base+pos+1]; - if(seg) { - diff = reldiff(seg); - ri++; // skip position byte - forwardpos(); // re-write position offset - obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) - } else { - // undefined - undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; -#ifdef DEBUG -printf("found undef'd label %s, resolved=%d, newidx=%d, (ri=%d, ro=%d)\n", u->name, u->resolved, u->newidx, ri, ro); -#endif - if (u->resolved == -1) { - // not resolved - diff = 0; - ri++; // skip position byte - forwardpos(); // re-write position offset - obuf[ro++] = buf[ri++]; // relocation byte ($8x for segments text, data, bss, zp) - obuf[ro++] = u->newidx & 0xff; // output label number lo/hi - obuf[ro++] = (u->newidx >> 8) & 0xff; - ri += 2; // acount for label number in input - } else { - // resolved from global list - glob *gl = &gp[u->resolved]; - diff = gl->val; - seg = gl->seg; - if (seg != 1) { - // not an absolute value - forwardpos(); // re-write position offset - obuf[ro++] = 0x80 | seg;// relocation byte for new segment - } else { - // absolute value - do not write a new relocation entry - } - ri += 4; // account for position, segment byte, label number in reloc table - } - } - new = old + diff; -/*printf("old=%04x, new=%04x\n",old,new);*/ - buf[addr-base+pos] = new & 255; - buf[addr-base+pos+1] = (new>>8)&255; - break; - case 0x40: - // high byte relocation - if(seg) { - old = buf[addr-base+pos]*256 + buf[ri+2]; - diff = reldiff(seg); - forwardpos(); // re-write position offset - obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) - obuf[ro++] = (old + diff) & 255; - ri += 3; // skip position, segment, and low byte - } else { - old = buf[addr-base+pos]*256 + buf[ri+4]; - // undefined - undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; - if (u->resolved == -1) { - // not resolved - diff = 0; - forwardpos(); // re-write position offset - obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) - obuf[ro++] = u->newidx & 0xff; // output label number lo/hi - obuf[ro++] = (u->newidx >> 8) & 0xff; - obuf[ro++] = buf[ri+4]; // low byte for relocation - } else { - // resolved from global list - glob *gl = &gp[u->resolved]; - diff = gl->val; - seg = gl->seg; - if (seg != 1) { - // not an absolute value - forwardpos(); // re-write position offset - obuf[ro++] = 0x40 | seg; // relocation byte for new segment - obuf[ro++] = (old + diff) & 0xff; // low byte for relocation - } else { - // absolute value - do not write a new relocation entry - } - } - ri += 5; // account for position, segment byte, label number in reloc table, low byte - } - new = old + diff; - buf[addr-base+pos] = (new>>8)&255; - break; - case 0x20: - // low byte relocation - old = buf[addr-base+pos]; - diff = 0; - if(seg) { - diff = reldiff(seg); - forwardpos(); - obuf[ro++] = buf[ri+1]; // relocation byte ($4x for segments text, data, bss, zp) - ri += 2; // account for position & segment - } else { - // undefined - undefs *u = &fp->ud[buf[ri+2]+256*buf[ri+3]]; - if (u->resolved == -1) { - // not resolved - diff = 0; - forwardpos(); // re-write position offset - obuf[ro++] = buf[ri+1]; // relocation byte ($8x for segments text, data, bss, zp) - obuf[ro++] = u->newidx & 0xff; // output label number lo/hi - obuf[ro++] = (u->newidx >> 8) & 0xff; - } else { - // resolved from global list - glob *gl = &gp[u->resolved]; - diff = gl->val; - seg = gl->seg; - if (seg != 1) { - // not an absolute value - forwardpos(); // re-write position offset - obuf[ro++] = 0x20 | seg; // relocation byte for new segment - } else { - // absolute value - do not write a new relocation entry - } - } - ri += 4;// account for position, segment byte, label number in reloc table - } - new = old + diff; - if (((diff & 0xff) + (old & 0xff)) > 0xff) { - fprintf(stderr,"Warning: overflow in byte relocation at %04x in file %s\n", - pos, fp->fname); - } - buf[addr-base+pos] = new & 255; - break; - } - } - } - - *lastaddrp = lastaddr + rdiff; - *rop = ro; -#ifdef DEBUG - printf(" --> lastaddr=%04x (%04x - %04x), rop=%d\n", lastaddr, *lastaddrp, rdiff, ro); -#endif - return ++ri; -} - - -