* fixed GCC 4.4.0 mingw compilation:
[fw/sdcc] / as / xa51 / xa_link.c
index 6eb90101b0f801635980904d17bae7322d58c0d0..a6823d246765f8272f394fb5266747832df3bc99 100644 (file)
@@ -1,20 +1,27 @@
+/* xa_link.c
+
+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 3, 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, see <http://www.gnu.org/licenses/>. */
+
 /* WORK IN PROGRESS: do not watch this if you don't have the legal
    age in your country to watch this.
 */
 
-/* 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
 /* 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.
 
@@ -50,13 +57,17 @@ enum {
   GSINIT=1,
   CSEG,
   XINIT,
-  GSFINAL, // here goes the final output
+
+  // 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
 };
 
@@ -212,7 +223,7 @@ void addToModules (char *name, int isLib) {
   module=calloc(1, sizeof(struct MODULE));
   module->name=strdup(name);
   for (s=0; s<MAX_SEGMENTS; s++) {
-    module->offset[s]=segments[s]._size;
+    module->offset[s]=(segments[s]._size+1)&0xfffffe;
   }
   module->isLib=isLib;
   if (!modules) {
@@ -455,7 +466,6 @@ void readModule(char *module, int isLib) {
       }
     currentLine++;
   }
-  // that's all for now, thanks for watching */
   fclose (relModule);
 }
 
@@ -466,11 +476,6 @@ void writeModule(char *outFileName) {
   unsigned int len;
   unsigned int checksum;
 
-  fprintf (stderr, "writeModule: %s from 0x%04x to 0x%04x\n",
-          outFileName, 
-          address,
-          address+size);
-
   if ((fOut=fopen(outFileName, "w"))==NULL) {
     perror (outFileName);
   }
@@ -522,6 +527,11 @@ int relocate() {
   }
 
   // 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);
 
@@ -531,6 +541,9 @@ int relocate() {
   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;
@@ -538,6 +551,9 @@ int relocate() {
   memcpy(to, from, 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;
@@ -545,8 +561,19 @@ int relocate() {
   memcpy(to, from, 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;  
 
@@ -578,8 +605,9 @@ int relocate() {
          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\n",
-                    reference->name, reference->module->name);
+                    "rel8 target for %s is out of range in module %s:%d\n",
+                    reference->name, reference->module->name, 
+                    reference->lineno);
            fatalErrors++;
          }
          gsfinalImage[reference->address]=rel8/2;
@@ -589,8 +617,9 @@ int relocate() {
          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\n",
-                    reference->name, reference->module->name);
+                    "rel16 target for %s is out of range in module %s:%d\n",
+                    reference->name, reference->module->name,
+                    reference->lineno);
            fatalErrors++;
          }
          gsfinalImage[reference->address]=(rel16/2)>>8;
@@ -598,7 +627,9 @@ int relocate() {
          break;
        }
        case DIR_70FF:
-         gsfinalImage[reference->address] = (symbol->address<<4)&0x70;
+         gsfinalImage[reference->address] = 
+           (gsfinalImage[reference->address]&~0x70) + 
+           ((symbol->address>>4)&0x70);
          gsfinalImage[reference->address+1] = symbol->address;
          break;
        case ABS_FFFF:
@@ -648,7 +679,6 @@ int scanLibraries(int unresolved) {
   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;
       }
@@ -656,15 +686,13 @@ int scanLibraries(int unresolved) {
        // 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
@@ -773,7 +801,6 @@ int main(int argc, char **argv) {
   addToDefs("s_XISEG", 0, 0);
   addToDefs("l_XISEG", segments[XISEG]._size, 1);
 
-#if 1
   // mark the resolved references
   resolve();
 
@@ -797,7 +824,6 @@ int main(int argc, char **argv) {
   if (unresolved==0) {
     writeModule(outFileName);
   }
-#endif
 
   // the modules
   fprintf (mapOut, "Modules:\n");