* Added z80 blurb.
[fw/sdcc] / src / SDCCglue.c
index eb574a35426c6a83b68d47887097cb1766109b0c..8b4629595e1f10acff04feda0076f854c1c3eded 100644 (file)
 #include <time.h>
 
 symbol *interrupts[256];
-extern char *aopLiteral (value *, int);
+/*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
 void printIval (symbol *, link *, initList *, FILE *);
 extern int noAlloc;
 set *publics = NULL;           /* public variables */
+
+/* TODO: this should be configurable (DS803C90 uses more than 6) */
 int maxInterrupts = 6;
 extern int maxRegBank ;
 symbol *mainf;
 extern char *VersionString;
 extern FILE *codeOutFile;
 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
+set *tmpfileNameSet = NULL; /* All are unlinked at close. */
 /*-----------------------------------------------------------------*/
 /* closeTmpFiles - closes all tmp files created by the compiler    */
 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
@@ -50,6 +53,21 @@ DEFSETFUNC(closeTmpFiles)
     return 0;
 }
 
+/*-----------------------------------------------------------------*/
+/* rmTmpFiles - closes all tmp files created by the compiler    */
+/*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(rmTmpFiles)
+{
+    char *name = item;
+
+    if (name) {
+       unlink(name);
+       free(name);
+    }
+    return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* copyFile - copies source file to destination file               */
 /*-----------------------------------------------------------------*/
@@ -63,6 +81,39 @@ void copyFile (FILE * dest, FILE * src)
            fputc (ch, dest);
 }
 
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value                        */
+/*-----------------------------------------------------------------*/
+char *aopLiteral (value *val, int offset)
+{
+    char *rs;
+    union {
+        float f;
+        unsigned char c[4];
+    } fl;
+
+    /* if it is a float then it gets tricky */
+    /* otherwise it is fairly simple */
+    if (!IS_FLOAT(val->type)) {
+        unsigned long v = floatFromVal(val);
+
+        v >>= (offset * 8);
+        sprintf(buffer,"#0x%02x",((char) v) & 0xff);
+        ALLOC_ATOMIC(rs,strlen(buffer)+1);
+        return strcpy (rs,buffer);
+    }
+
+    /* it is type float */
+    fl.f = (float) floatFromVal(val);
+#ifdef _BIG_ENDIAN    
+    sprintf(buffer,"#0x%02x",fl.c[3-offset]);
+#else
+    sprintf(buffer,"#0x%02x",fl.c[offset]);
+#endif
+    ALLOC_ATOMIC(rs,strlen(buffer)+1);
+    return strcpy (rs,buffer);
+}
+
 /*-----------------------------------------------------------------*/
 /* emitRegularMap - emit code for maps with no special cases       */
 /*-----------------------------------------------------------------*/
@@ -179,7 +230,7 @@ value *initPointer (initList *ilist)
            val->type = newLink();
            if (SPEC_SCLS(expr->left->etype) == S_CODE) {
                DCL_TYPE(val->type) = CPOINTER ;
-               DCL_PTR_CONST(val->type) = 1;
+               DCL_PTR_CONST(val->type) = port->mem.code_ro;
            }
            else
                if (SPEC_SCLS(expr->left->etype) == S_XDATA)
@@ -191,7 +242,10 @@ value *initPointer (initList *ilist)
                        if (SPEC_SCLS(expr->left->etype) == S_IDATA)
                            DCL_TYPE(val->type) = IPOINTER ;
                        else
-                           DCL_TYPE(val->type) = POINTER ;
+                           if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
+                               DCL_TYPE(val->type) = EEPPOINTER ;
+                           else
+                               DCL_TYPE(val->type) = POINTER ;
            val->type->next = expr->left->ftype;
            val->etype = getSpec(val->type);
            return val;
@@ -684,18 +738,27 @@ void createInterruptVect (FILE * vFile)
        return;
     }
     
-    fprintf (vFile, "\t.area\tCODE (CODE)\n");
+    fprintf (vFile, "\t.area\t%s\n", CODE_NAME);
     fprintf (vFile, "__interrupt_vect:\n");
+
     
-    fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
+    if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
+    {
+        /* "generic" interrupt table header (if port doesn't specify one).
+         *
+         * Look suspiciously like 8051 code to me...
+         */
     
+       fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
     
-    /* now for the other interrupts */
-    for (; i < maxInterrupts; i++) {
-       if (interrupts[i])
-           fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
-       else
-           fprintf (vFile, "\treti\n\t.ds\t7\n");
+    
+       /* now for the other interrupts */
+       for (; i < maxInterrupts; i++) {
+               if (interrupts[i])
+                       fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
+               else
+                       fprintf (vFile, "\treti\n\t.ds\t7\n");
+       }
     }
 }
 
@@ -745,7 +808,7 @@ static void emitOverlay(FILE *afile)
     set *ovrset;
     
     if (!elementsInSet(ovrSetSets))
-       fprintf(afile,"\t.area\tOSEG\t(OVR,DATA)\n");
+       fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name);
 
     /* for each of the sets in the overlay segment do */
     for (ovrset = setFirstItem(ovrSetSets); ovrset;
@@ -760,7 +823,7 @@ static void emitOverlay(FILE *afile)
               sad but true */
            fprintf(afile,"\t.area _DUMMY\n");
            /* output the area informtion */
-           fprintf(afile,"\t.area\tOSEG\t(OVR,DATA)\n"); /* MOF */
+           fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name); /* MOF */
        }
        
        for (sym = setFirstItem(ovrset); sym;
@@ -838,15 +901,20 @@ void glue ()
 {
     FILE *vFile;
     FILE *asmFile;
-    FILE *ovrFile = tmpfile();
+    FILE *ovrFile = tempfile();
     
     addSetHead(&tmpfileSet,ovrFile);
     /* print the global struct definitions */
     if (options.debug)
        cdbStructBlock (0,cdbFile);
 
-    /* create the interrupt vector table */
-    createInterruptVect ((vFile = tmpfile ()));
+    vFile = tempfile();
+    /* PENDING: this isnt the best place but it will do */
+    if (port->general.glue_up_main) {
+       /* create the interrupt vector table */
+       createInterruptVect (vFile);
+    }
+
     addSetHead(&tmpfileSet,vFile);
     
     /* emit code for the all the variables declared */
@@ -856,8 +924,15 @@ void glue ()
 
     /* now put it all together into the assembler file */
     /* create the assembler file name */
-    sprintf (buffer, srcFileName);
-    strcat (buffer, ".asm");
+    
+    if (!options.c1mode) {
+       sprintf (buffer, srcFileName);
+       strcat (buffer, ".asm");
+    }
+    else {
+       strcpy(buffer, options.out_name);
+    }
+
     if (!(asmFile = fopen (buffer, "w"))) {
        werror (E_FILE_OPEN_ERR, buffer);
        exit (1);
@@ -869,9 +944,14 @@ void glue ()
     /* print module name */
     fprintf (asmFile, "\t.module %s\n", moduleName);
     
+    /* Let the port generate any global directives, etc. */
+    if (port->genAssemblerPreamble)
+    {
+       port->genAssemblerPreamble(asmFile);
+    }
+    
     /* print the global variables in this module */
     printPublics (asmFile);
-
     
     /* copy the sfr segment */
     fprintf (asmFile, "%s", iComments2);
@@ -947,7 +1027,17 @@ void glue ()
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; global & static initialisations\n");
     fprintf (asmFile, "%s", iComments2);
-    fprintf (asmFile, "\t.area GSINIT (CODE)\n"); /* MOF */
+    
+    /* Everywhere we generate a reference to the static_name area, 
+     * (which is currently only here), we immediately follow it with a 
+     * definition of the post_static_name area. This guarantees that
+     * the post_static_name area will immediately follow the static_name
+     * area.
+     */
+    fprintf (asmFile, "\t.area %s\n", port->mem.static_name); /* MOF */
+    fprintf (asmFile, "\t.area %s\n", port->mem.post_static_name);
+    fprintf (asmFile, "\t.area %s\n", port->mem.static_name);
+    
     if (mainf && mainf->fbody) {
        fprintf (asmFile,"__sdcc_gsinit_startup:\n");
        /* if external stack is specified then the
@@ -980,12 +1070,22 @@ void glue ()
        
     }
     copyFile (asmFile, statsg->oFile);
-    
+
+    if (port->general.glue_up_main && mainf && mainf->fbody)
+    {
+        /* This code is generated in the post-static area.
+         * This area is guaranteed to follow the static area
+         * by the ugly shucking and jiving about 20 lines ago.
+         */
+       fprintf(asmFile, "\t.area %s\n", port->mem.post_static_name);
+       fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
+    }
+       
     /* copy over code */
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; code\n");
     fprintf (asmFile, "%s", iComments2);
-    fprintf (asmFile, "\t.area CSEG (CODE)\n");
+    fprintf (asmFile, "\t.area %s\n", port->mem.code_name);
     if (mainf && mainf->fbody) {
        
        /* entry point @ start of CSEG */
@@ -1008,4 +1108,31 @@ void glue ()
     
     fclose (asmFile);
     applyToSet(tmpfileSet,closeTmpFiles);
+    applyToSet(tmpfileNameSet, rmTmpFiles);
+}
+
+/** Creates a temporary file a'la tmpfile which avoids the bugs
+    in cygwin wrt c:\tmp.
+    Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
+*/
+FILE *tempfile(void)
+{
+    const char *tmpdir = NULL;
+    if (getenv("TMP"))
+       tmpdir = getenv("TMP");
+    else if (getenv("TEMP"))
+       tmpdir = getenv("TEMP");
+    else if (getenv("TMPDIR"))
+       tmpdir = getenv("TMPDIR");
+    if (tmpdir) {
+       char *name = tempnam(tmpdir, "sdcc");
+       if (name) {
+           FILE *fp = fopen(name, "w+b");
+           if (fp)
+               addSetHead(&tmpfileNameSet, name);
+           return fp;
+       }
+       return NULL;
+    }
+    return tmpfile();
 }