/* This is a cheap hack. The xa51 has a couple of ways to scramble
relocation info into it's opcode that the standard linker can't
- handle. No hash or qsort yet.
+ handle, not to mention word allignment.
+
+ No hash or qsort yet.
The relocatable format looks like the known one, BUT ISN'T.
"T xxxx <how> <symbol> 0"
"R xxxx <how> <symbol> <pc+>" the relocation info. xxxx is the address
within relative code space. How is something like REL_FF, REL_FFFF,
- ABS_F0FF. Symbol is the referenced symbol and pc+ is the program
+ ABS_70FF. Symbol is the referenced symbol and pc+ is the program
counter that will be used to calculate the relative address (that is
the address of the following instruction).
GSINIT=1,
CSEG,
XINIT,
- //GSFINAL, // do we need this?
+
+ // here goes the final output and should be used by the assembler
+ GSFINAL,
// these are only for storage
BSEG,
DSEG,
XSEG,
XISEG,
+
+ // that's all
MAX_SEGMENTS
};
enum {
REL_FF=1,
REL_FFFF,
+ BIT_03FF,
+ DIR_07FF,
+ DIR_70FF,
+ DIR_0700FF,
ABS_0F,
ABS_FF,
- ABS_03FF,
- ABS_07FF,
- ABS_F0FF,
ABS_FFFF,
- ABS_0F00FF,
+ ABS_PC,
MAX_REFS
};
"???",
"REL_FF",
"REL_FFFF",
+ "BIT_03FF",
+ "DIR_07FF",
+ "DIR_70FF",
+ "DIR_0700FF",
"ABS_0F",
"ABS_FF",
- "ABS_03FF",
- "ABS_07FF",
- "ABS_F0FF",
"ABS_FFFF",
- "ABS_0F00FF",
+ "ABS_PC"
};
#define CODESIZE 0x10000
int fatalErrors=0;
-char gsinitImage[CODESIZE];
-char csegImage[CODESIZE];
-char xinitImage[CODESIZE];
-//char gsfinalImage[CODESIZE];
+unsigned char gsinitImage[CODESIZE];
+unsigned char csegImage[CODESIZE];
+unsigned char xinitImage[CODESIZE];
+unsigned char gsfinalImage[CODESIZE];
struct SEGMENT {
short id;
{GSINIT, "GSINIT", 0, 0, 0, 0, gsinitImage},
{CSEG, "CSEG", 0, 0, 0, 0, csegImage},
{XINIT, "XINIT", 0, 0, 0, 0, xinitImage},
- //{GSFINAL, "GSFINAL", 0, 0, 0, 0, NULL},
+ {GSFINAL, "GSFINAL", 0, 0, 0, 0, gsfinalImage},
{BSEG, "BSEG", 0, 0, 0, 0, NULL},
{DSEG, "DSEG", 0, 0, 0, 0, NULL},
struct REFERENCE {
char *name;
struct MODULE *module;
+ struct SEGMENT *segment;
int lineno;
unsigned address, pc;
short how;
module=calloc(1, sizeof(struct MODULE));
module->name=strdup(name);
for (s=0; s<MAX_SEGMENTS; s++) {
- module->offset[s]=segments[s].current;
+ module->offset[s]=(segments[s]._size+1)&0xfffffe;
}
module->isLib=isLib;
if (!modules) {
reference=calloc(1, sizeof(struct REFERENCE));
reference->name=strdup(ref);
reference->module=currentModule;
+ reference->segment=currentSegment;
reference->lineno=currentLine;
reference->address=address;
reference->how=howToReference(how);
+ if (reference->how==ABS_PC) {
+ reference->resolved=1;
+ }
reference->pc=pc;
if (!references) {
references=reference;
void resolve() {
struct REFERENCE *reference;
for (reference=references; reference; reference=reference->next) {
- if (findSymbolByName(reference->name)) {
+ if ((reference->how==ABS_PC) || findSymbolByName(reference->name)) {
reference->resolved=1;
}
}
}
// double check repeated 'A' records
if (currentModule->size[currentSegment->id]) {
+ // pleased to meet you again, I hope ...
if (currentModule->size[currentSegment->id] != size) {
fprintf (stderr, "*** %s:%d error %s size %d != %d\n",
module, currentLine,
currentModule->size[currentSegment->id],
size);
fatalErrors++;
- } else {
- // pleased to meet you again
}
} else {
- currentModule->size[currentSegment->id]=size;
- currentModule->offset[currentSegment->id]+=currentSegment->_size;
currentSegment->_size += size;
+ currentModule->size[currentSegment->id] = size;
}
// never mind about the flags for now
break;
char *tline=NULL;
if (currentSegment->id!=CSEG &&
currentSegment->id!=GSINIT &&
- //currentSegment->id!=GSFINAL &&
currentSegment->id!=XINIT) {
fprintf (stderr, "%s:%d cannot emit bytes in %s\n",
module, currentLine, currentSegment->name);
fprintf (stderr, "%s:%d error in T record\n", module, currentLine);
fatalErrors++;
}
- address+=currentSegment->current;
+
+ address+=currentModule->offset[currentSegment->id];
+ //address+=currentSegment->current;
for ( ;
(tline=strtok(NULL, " \t\n")) &&
(sscanf(tline, "%02x", &byte)==1);
break;
}
case 'R': {
- unsigned address, from;
+ unsigned address, pc;
char symbol[132];
char how[32];
- sscanf (line, "R %x %[^ ] %[^ ] %x", &address, how, symbol, &from);
- addToRefs (symbol, address, how, from);
+ sscanf (line, "R %x %[^ ] %[^ ] %x", &address, how, symbol, &pc);
+ addToRefs (symbol, address, how, pc);
break;
}
default:
}
currentLine++;
}
- // that's all for now, thanks for watching */
fclose (relModule);
}
void writeModule(char *outFileName) {
FILE *fOut;
+ unsigned int address=segments[GSFINAL].start;
+ unsigned int size=segments[GSFINAL]._size;
+ unsigned int len;
+ unsigned int checksum;
if ((fOut=fopen(outFileName, "w"))==NULL) {
perror (outFileName);
}
- // oops, forgot something :) */
+
+ while (size) {
+ len = size>16 ? 16 : size;
+ size-=len;
+ fprintf (fOut, ":%02X%04X%02X", len, address, 0);
+ checksum = len + (address>>8) + (address&0xff);
+ while (len--) {
+ checksum += gsfinalImage[address];
+ fprintf (fOut, "%02X", gsfinalImage[address++]);
+ }
+ checksum &= 0xff;
+ if (checksum) {
+ checksum = 0x100 - checksum;
+ }
+ fprintf (fOut, "%02X\n", checksum);
+ }
+ fprintf (fOut, ":00000001FF\n");
+
fclose (fOut);
}
struct SYMBOL *symbol;
struct REFERENCE *reference;
char *from, *to;
- int length=segments[GSINIT].current +
- segments[CSEG].current +
- segments[XINIT].current;
+ int length=segments[GSINIT]._size +
+ segments[CSEG]._size +
+ segments[XINIT]._size;
int unresolved=0;
// first check if it will fit
return unresolved;
}
- // GSINIT gets the --code-loc
- segments[GSINIT].start=segments[CSEG].start;
- segments[CSEG].start=segments[GSINIT].start+segments[GSINIT]._size;
- // concat cseg and gsinit
+ // GSFINAL starts at --code-loc ( -b CSEG = 0x1234 )
+ if (segments[CSEG].start & 1) {
+ fprintf (stderr, "*** error: code doesn't start at "
+ "an even address: %04x\n", segments[CSEG].start);
+ exit (1);
+ }
+ segments[GSFINAL].start=segments[CSEG].start;
+ memset(gsfinalImage, 0xff, CODESIZE);
+
+ // copy gsinit to gsfinal
+ from = gsinitImage;
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
+ memcpy(to, from, segments[GSINIT]._size);
+ segments[GSINIT].start=segments[GSFINAL].start;
+ segments[GSFINAL]._size += segments[GSINIT]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // append cseg to gsfinal
from=csegImage;
- to=&gsinitImage[segments[GSINIT].start+segments[GSINIT]._size];
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
memcpy(to, from, segments[CSEG]._size);
- segments[XINIT].start=segments[CSEG].start+segments[CSEG]._size;
+ segments[CSEG].start=segments[GSFINAL].start+segments[GSFINAL]._size;
+ segments[GSFINAL]._size += segments[CSEG]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // append xinit to gsfinal
from=xinitImage;
- to+=segments[CSEG]._size;
+ to = gsfinalImage + segments[GSFINAL].start + segments[GSFINAL]._size;
memcpy(to, from, segments[XINIT]._size);
-#if 0
- from=gsfinalImage;
- to+=segments[XINIT]._size;
- memcpy(to, from, segments[GSFINAL]._size);
-#endif
- segments[XISEG].start=segments[XSEG].start+segments[XINIT]._size;
+ segments[XINIT].start=segments[GSFINAL].start+segments[GSFINAL]._size;
+ segments[GSFINAL]._size += segments[XINIT]._size;
+ if (segments[GSFINAL]._size & 1) {
+ segments[GSFINAL]._size++;
+ }
+
+ // XISEG is located after XSEG
+ if (segments[XSEG].start & 1) {
+ fprintf (stderr, "*** warning: xdata doesn't start at "
+ "an even address: %04x\n", segments[XSEG].start);
+ }
+ if (segments[XSEG]._size & 1) {
+ segments[XSEG]._size++;
+ }
+
+ segments[XISEG].start=segments[XSEG].start +
+ segments[XSEG]._size;
+
// now relocate the defined symbols
for (symbol=symbols; symbol; symbol=symbol->next) {
if (!symbol->absolute) {
}
// and the references
for (reference=references; reference; reference=reference->next) {
- if (!(symbol=findSymbolByName(reference->name))) {
- // this reference isn't defined after all
+ symbol=findSymbolByName(reference->name);
+ if (!reference->resolved && !symbol && reference->how!=ABS_PC) {
+ // this reference isn't resolved after all
fprintf (stderr, "*** %s:%d undefined symbol %s\n",
reference->module->name, reference->lineno,
reference->name);
fatalErrors++;
} else {
- reference->address += symbol->segment->start;
+ reference->address +=
+ reference->module->offset[reference->segment->id]+
+ reference->segment->start;
+ reference->pc +=
+ reference->module->offset[reference->segment->id]+
+ reference->segment->start;
switch (reference->how)
{
- case REL_FFFF: {
- int rel16 = symbol->address-reference->pc;
- if (rel16<-65536 || rel16>65534) {
- fprintf (stderr,
- "rel16 target for %s is out of range in module %s\n",
- reference->name, reference->module->name);
+ case REL_FF: {
+ int rel8 = symbol->address-(reference->pc & ~1);
+ if (rel8<-256 || rel8>256) {
+ fprintf (stderr,
+ "rel8 target for %s is out of range in module %s:%d\n",
+ reference->name, reference->module->name,
+ reference->lineno);
fatalErrors++;
}
- gsinitImage[reference->address+1]=(rel16/2)>>8;
- gsinitImage[reference->address]=rel16/2;
+ gsfinalImage[reference->address]=rel8/2;
break;
}
- case REL_FF: {
- int rel8 = symbol->address-reference->pc;
- if (rel8<-256 || rel8>256) {
- fprintf (stderr,
- "rel8 target for %s is out of range in module %s\n",
- reference->name, reference->module->name);
+ case REL_FFFF: {
+ int rel16 = symbol->address-(reference->pc & ~1);
+ if (rel16<-65536 || rel16>65534) {
+ fprintf (stderr,
+ "rel16 target for %s is out of range in module %s:%d\n",
+ reference->name, reference->module->name,
+ reference->lineno);
fatalErrors++;
}
- gsinitImage[reference->address]=rel8/2;
+ gsfinalImage[reference->address]=(rel16/2)>>8;
+ gsfinalImage[reference->address+1]=rel16/2;
break;
}
+ case DIR_70FF:
+ gsfinalImage[reference->address] =
+ (gsfinalImage[reference->address]&~0x70) +
+ ((symbol->address>>4)&0x70);
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
case ABS_FFFF:
- gsinitImage[reference->address+1] = symbol->address>>8;
- // fall through
+ gsfinalImage[reference->address] = symbol->address>>8;
+ gsfinalImage[reference->address+1] = symbol->address;
+ break;
case ABS_FF:
- gsinitImage[reference->address] = symbol->address;
+ gsfinalImage[reference->address] = symbol->address;
+ break;
+ case ABS_PC:
+ {
+ unsigned int address=
+ (gsfinalImage[reference->address]<<8) +
+ gsfinalImage[reference->address+1];
+ address += reference->module->offset[reference->segment->id];
+ address += segments[reference->segment->id].start;
+ gsfinalImage[reference->address] = address>>8;
+ gsfinalImage[reference->address+1] = address;
+ };
break;
default:
fprintf (stderr, "unsupported reference mode %d.\n",
for (nlp=0; nlp<nlibPaths; nlp++) {
for (nlf=0; nlf<nlibFiles; nlf++) {
sprintf (libFiles, "%s/%s.lib", libraryPaths[nlp], libraryFiles[nlf]);
- //fprintf (stderr, " %s\n", libFiles);
if ((lfs=fopen(libFiles,"r"))==NULL) {
continue;
}
// remove trailing \n
line[strlen(line)-1]='\0';
sprintf (libFile, "%s/%s", libraryPaths[nlp], line);
- //fprintf (stderr, " %s\n", libFile);
- if ((lf=fopen(libFile,"r"))==0) {
+ if ((lf=fopen(libFile,"r"))==NULL) {
continue;
}
while (fgets(line, 132, lf)) {
int dummy; // we need this to get the right count of the next sscanf
if (sscanf(line, "S %[^ ] Def%04x", symName, &dummy)==2) {
if (isUnresolved(symName, 1)) {
- //fprintf (stderr, "%s:%s\n", libFile, symName);
readModule(libFile,1);
if (resolved++ == unresolved) {
// we are done
// add the segment symbols
currentSegment=findSegmentByName("XINIT");
- addToDefs("s_XINIT", segments[XINIT].start, 0);
- addToDefs("l_XINIT", segments[XINIT]._size, 0);
+ addToDefs("s_XINIT", 0, 0);
+ addToDefs("l_XINIT", segments[XINIT]._size, 1);
currentSegment=findSegmentByName("XISEG");
- addToDefs("s_XISEG", segments[XISEG].start, 0);
- addToDefs("l_XISEG", segments[XISEG]._size, 0);
+ addToDefs("s_XISEG", 0, 0);
+ addToDefs("l_XISEG", segments[XISEG]._size, 1);
// mark the resolved references
resolve();
for (s=0; s<MAX_SEGMENTS; s++) {
if (module->size[s]) {
fprintf (mapOut, "\t\t%s:0x%04x-0x%04x\n", segments[s].name,
- module->offset[s], module->offset[s]+module->size[s]);
+ module->offset[s]+segments[s].start,
+ module->offset[s]+segments[s].start+module->size[s]);
}
}
}
symbol->address, symbol->module->name);
}
- writeModule(outFileName);
fclose(mapOut);
return fatalErrors? 1 : 0;
}