* src/SDCCast.c (gatherAutoInit): allow pic16 to emit static
[fw/sdcc] / src / pic16 / glue.c
index 2dfe5e4b8a5a189c19fc9ffb26c1f34e5a8507e8..573f83c5069c235a8604502cc9435d6ae5dd6f2b 100644 (file)
@@ -57,10 +57,11 @@ extern set *tmpfileSet;
 extern set *tmpfileNameSet;
 extern char *iComments1;
 extern char *iComments2;
-//extern void emitStaticSeg (memmap * map);
 
 extern int initsfpnt;
+extern unsigned long pFile_isize;
 
+extern unsigned long pic16_countInstructions();
 set *rel_idataSymSet=NULL;
 set *fix_idataSymSet=NULL;
 
@@ -68,6 +69,7 @@ extern DEFSETFUNC (closeTmpFiles);
 extern DEFSETFUNC (rmTmpFiles);
 
 extern void pic16_AnalyzeBanking (void);
+extern void pic16_OptimizeJumps ();
 extern void copyFile (FILE * dest, FILE * src);
 extern void pic16_InlinepCode(void);
 extern void pic16_writeUsedRegs(FILE *);
@@ -76,11 +78,10 @@ extern void initialComments (FILE * afile);
 extern void printPublics (FILE * afile);
 
 void  pic16_pCodeInitRegisters(void);
-pCodeOp *pic16_popGetLit(unsigned int lit);
-pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2);
 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
 extern void pic16_pCodeConstString(char *name, char *value);
 
+
 /*-----------------------------------------------------------------*/
 /* aopLiteral - string from a literal value                        */
 /*-----------------------------------------------------------------*/
@@ -135,25 +136,26 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
                        __FUNCTION__,
                        map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
-                       IS_AGGREGATE(sym->type), SPEC_SCLS(sym->etype), IS_FUNC(sym->type));
+                       IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
                printTypeChain( sym->type, stderr );
                fprintf(stderr, "\n");
 #endif
 
                /* if extern then add to externs */
                if (IS_EXTERN (sym->etype)) {
-
                        /* reduce overhead while linking by not declaring
                         * extern unused external functions (usually declared
                         * in header files) */
                        if(IS_FUNC(sym->type) && !sym->used)continue;
                        
-                       checkAddSym(&externs, sym);
+                       /* make sure symbol is not in publics section */
+                       if(!checkSym(publics, sym))
+                               checkAddSym(&externs, sym);
                        continue;
                }
                
                /* if allocation required check is needed
-                *  then check if the symbol really requires
+                * then check if the symbol really requires
                 * allocation only for local variables */
                 if (arFlag && !IS_AGGREGATE (sym->type) &&
                        !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
@@ -173,16 +175,20 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                  
                        checkAddSym(&publics, sym);
                } else
+#if 1
+                        /* new version */
                        if(IS_STATIC(sym->etype)
-                               && !(sym->ival && !sym->level)
-                       ) {
+                               && !sym->ival) /* && !sym->level*/ {
+#else
+                        /* old version */
+                        if(IS_STATIC(sym->etype)
+                                && !(sym->ival && !sym->level)) {
+#endif
                          regs *reg;
-                               /* add it to udata list */
+                          sectSym *ssym;
+                          int found=0;
 
-//                             fprintf(stderr, "%s:%d adding %s (%s) remat=%d\n", __FILE__, __LINE__,
-//                                     sym->name, sym->rname, sym->remat);
-                                       
-                                               //, OP_SYMBOL(operandFromSymbol(sym))->name);
+//                            debugf("adding symbol %s\n", sym->name);
 #define SET_IMPLICIT   1
 
 #if SET_IMPLICIT
@@ -192,18 +198,18 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
 
                                reg = pic16_allocDirReg( operandFromSymbol( sym ));
                                
-                               {
-                                 sectSym *ssym;
-                                 int found=0;
-                                 
-#if 1
-                                       for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
-                                               if(!strcmp(ssym->name, reg->name))found=1;
-                                       }
-#endif
-
-                                       if(!found)checkAddReg(&pic16_rel_udata, reg);
-                               }
+                               if(reg) {
+                                  for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
+                                   if(!strcmp(ssym->name, reg->name))found=1;
+                                  }
+
+                                  if(!found)
+                                    checkAddReg(&pic16_rel_udata, reg);
+                                  else
+                                    debugf("Coudld not find %s in pic16_rel_udata. Check!\n", reg->name);
+//                                 checkAddSym(&publics, sym);
+
+                                }
                        }
 
                /* if extern then do nothing or is a function
@@ -216,28 +222,9 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                        continue;
                }
 
-#if 0
-               /* print extra debug info if required */
-               if (options.debug || sym->level == 0) {
-                       cdbWriteSymbol (sym);   //, cdbFile, FALSE, FALSE);
-
-                       if (!sym->level)        /* global */
-                               if (IS_STATIC (sym->etype))
-                                       fprintf (map->oFile, "F%s_", moduleName);               /* scope is file */
-                               else
-                                       fprintf (map->oFile, "G_");     /* scope is global */
-                       else
-                               /* symbol is local */
-                               fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
-                       fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
-               }
-#endif
-
-
                /* if is has an absolute address then generate
                an equate for this no need to allocate space */
                if (SPEC_ABSA (sym->etype)) {
-//                     if (options.debug || sym->level == 0)
 //                             fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
 //                                     sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
 
@@ -297,19 +284,21 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                                          sectSym *ssym;
                                          int found=0;
                                  
+#if 0
                                                fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
                                                        sym->rname, reg, (reg?reg->name:"<<NULL>>"));
-#if 1
-                                               for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
-                                                       if(!strcmp(ssym->name, reg->name))found=1;
-                                               }
 #endif
 
-                                               if(!found)
-                                                       if(checkAddReg(&pic16_rel_udata, reg)) {
-                                                               addSetHead(&publics, sym);
-                                                       }
+                                                if(reg) {
+                                                 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
+                                                   if(!strcmp(ssym->name, reg->name))found=1;
+                                                  }
 
+                                                  if(!found)
+                                                    if(checkAddReg(&pic16_rel_udata, reg)) {
+                                                      addSetHead(&publics, sym);
+                                                    }
+                                                }
                                        }
 
 
@@ -343,7 +332,9 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                /* if it has an initial value then do it only if
                        it is a global variable */
 
-               if (sym->ival && sym->level == 0) {
+               if (sym->ival
+                 && ((sym->level == 0)
+                     || IS_STATIC(sym->etype)) ) {
                  ast *ival = NULL;
 
 #if 0
@@ -374,7 +365,7 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                                        addSet(&rel_idataSymSet, copySymbol(sym));
 
 //                                     ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
-//                                             decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
+//                                             decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
                        }
 
                        if(ival) {
@@ -556,24 +547,37 @@ void pic16_printPointerType (const char *name, char ptype, void *p)
 /*-----------------------------------------------------------------*/
 /* printGPointerType - generates ival for generic pointer type     */
 /*-----------------------------------------------------------------*/
-void pic16_printGPointerType (const char *iname, const char *oname, const unsigned int itype,
-                   const unsigned int type, char ptype, void *p)
+void pic16_printGPointerType (const char *iname, const unsigned int itype,
+  char ptype, void *p)
 {
-  _pic16_printPointerType (iname, ptype, p);
-
-  if(itype == FPOINTER || itype == CPOINTER) { // || itype == GPOINTER) {
-    char buf[256];
+  char buf[256];
+  
+    _pic16_printPointerType (iname, ptype, p);
 
-       sprintf(buf, "UPPER(%s)", iname);
-       pic16_emitDS(buf, ptype, p);
-  }
+    switch( itype ) {
+      case FPOINTER:
+      case CPOINTER:
+      case FUNCTION:
+        {
+          sprintf(buf, "UPPER(%s)", iname);
+          pic16_emitDS(buf, ptype, p);
+        }; break;
+      case POINTER:
+      case IPOINTER:
+        sprintf(buf, "0x80");
+        pic16_emitDS(buf, ptype, p);
+        break;
+      default:
+        debugf("itype = %d\n", itype );
+        assert( 0 );
+    }
 
-  pic16_flushDB(ptype, p);
+    pic16_flushDB(ptype, p);
 }
 
 
 /* set to 0 to disable debug messages */
-#define DEBUG_PRINTIVAL        1
+#define DEBUG_PRINTIVAL        0
 
 /*-----------------------------------------------------------------*/
 /* pic16_printIvalType - generates ival for int/char               */
@@ -582,7 +586,6 @@ static void
 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
 {
   value *val;
-  unsigned long ulval;
 
 //  fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
 
@@ -608,26 +611,24 @@ pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype,
     val = valCastLiteral(type, floatFromVal(val));
   }
 
-  if(val) 
-    ulval = (unsigned long) floatFromVal (val);
-  else
-    ulval =0;
-
   switch (getSize (type)) {
   case 1:
-    pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
     break;
 
   case 2:
-    pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
-    pic16_emitDB(BYTE_IN_LONG(ulval,1), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
     break;
-
+  case 3:
+    pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
   case 4:
-    pic16_emitDB(BYTE_IN_LONG(ulval,0), ptype, p);
-    pic16_emitDB(BYTE_IN_LONG(ulval,1), ptype, p);
-    pic16_emitDB(BYTE_IN_LONG(ulval,2), ptype, p);
-    pic16_emitDB(BYTE_IN_LONG(ulval,3), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
+    pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
     break;
   }
 }
@@ -639,7 +640,7 @@ static int
 pic16_printIvalChar (sym_link * type, initList * ilist, char *s, char ptype, void *p)
 {
   value *val;
-  int remain;
+  unsigned int remain;
 
   if(!p)
     return 0;
@@ -648,30 +649,24 @@ pic16_printIvalChar (sym_link * type, initList * ilist, char *s, char ptype, voi
   fprintf(stderr, "%s\n",__FUNCTION__);
 #endif
 
-  if (!s)
-    {
-
-      val = list2val (ilist);
-      /* if the value is a character string  */
-      if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
-       {
-         if (!DCL_ELEM (type))
-           DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
-
-           for(remain=0; remain<DCL_ELEM(type); remain++)
-               pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
-                       
-         if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
-             while (remain--) {
-                  pic16_emitDB(0x00, ptype, p);
-              }
-          }
-         return 1;
-       }
-      else
-       return 0;
-    }
-  else {
+  if(!s) {
+    val = list2val (ilist);
+    /* if the value is a character string  */
+    if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
+      if(!DCL_ELEM (type))
+        DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
+
+      for(remain=0; remain<strlen(SPEC_CVAL(val->etype).v_char)+1; remain++)
+        pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
+      
+      if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
+        while(remain--) {
+          pic16_emitDB(0x00, ptype, p);
+        }
+      }
+      return 1;
+    } else return 0;
+  } else {
     for(remain=0; remain<strlen(s); remain++) {
         pic16_emitDB(s[remain], ptype, p);
     }
@@ -896,7 +891,7 @@ int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char pty
             // this is a literal string
             type=CPOINTER;
           }
-          pic16_printGPointerType(val->name, sym->name, type, type, ptype, p);
+          pic16_printGPointerType(val->name, type, ptype, p);
         }
       else
         {
@@ -944,6 +939,11 @@ void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void
   value *val;
   int dLvl = 0;
 
+
+#if DEBUG_PRINTIVAL
+  fprintf(stderr, "%s\n",__FUNCTION__);
+#endif
+
   if (ilist)
     val = list2val (ilist);
   else
@@ -972,9 +972,21 @@ void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void
 
   /* now generate the name */
   if (!val->sym) {
-      pic16_printPointerType (val->name, ptype, p);
+      pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
   } else {
-      pic16_printPointerType (val->sym->rname, ptype, p);
+      pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
+
+      if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
+        
+        if(!checkSym(publics, val->sym))
+         if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
+           /* this has not been declared as extern
+            * so declare it as a 'late extern' just after the symbol */
+           fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
+           fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
+           fprintf((FILE *)p, ";\tcontinue variable declaration\n");
+          }
+      }
   }
 
   return;
@@ -1035,7 +1047,9 @@ void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char p
             pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
             pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
             pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
+            break;
         default:
+               fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
                assert(0);
         }
       return;
@@ -1054,9 +1068,8 @@ void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char p
     }
   else if (size == 3)
     {
-      pic16_printGPointerType (val->name, sym->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
-                         (IS_PTR (val->type) ? DCL_TYPE (val->type) :
-                          PTR_TYPE (SPEC_OCLS (val->etype))), ptype, p);
+      pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
+                          ptype, p);
     } else
        assert(0);
   return;
@@ -1171,6 +1184,7 @@ static void
 pic16emitStaticSeg (memmap * map)
 {
   symbol *sym;
+  static int didcode=0;
 
   //fprintf(stderr, "%s\n",__FUNCTION__);
 
@@ -1243,11 +1257,11 @@ CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
              resolveIvalSym (sym->ival, sym->type);
              asym = newSymbol(sym->rname, 0);
              abSym = Safe_calloc(1, sizeof(absSym));
-             abSym->name = Safe_strdup( sym->rname );
+             strcpy(abSym->name, sym->rname);
              abSym->address = SPEC_ADDR( sym->etype );
              addSet(&absSymSet, abSym);
              
-             pb = pic16_newpCodeChain(NULL, 'A',pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
+             pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
              pic16_addpBlock(pb);
 
              pcf = pic16_newpCodeFunction(moduleName, asym->name);
@@ -1299,8 +1313,12 @@ CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
              pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
              pic16_addpBlock(pb);
 
-              /* make sure that 'code' directive is emitted before */
-              pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
+             if(!didcode) {
+               /* make sure that 'code' directive is emitted before, once */
+               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
+               
+               didcode++;
+             }
                             
 //           fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
 
@@ -1318,7 +1336,7 @@ CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
              if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
                  SPEC_CVAL (sym->etype).v_char) {
                
-//             fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
+//             fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
 
                pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
              } else {
@@ -1413,6 +1431,11 @@ pic16initialComments (FILE * afile)
        if(pic16_mplab_comp)
                fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
        fprintf (afile, iComments2);
+
+       if(options.debug) {
+               fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
+                               SDCC_VERSION_STR, getBuildNumber() );
+       }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1428,6 +1451,8 @@ pic16printPublics (FILE *afile)
        fprintf (afile, "%s", iComments2);
 
        for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
+         /* sanity check */
+         if(!IS_STATIC(sym->etype))
                fprintf(afile, "\tglobal %s\n", sym->rname);
 }
 
@@ -1513,27 +1538,6 @@ pic16emitOverlay (FILE * afile)
          if (IS_FUNC (sym->type))
            continue;
 
-#if 0
-         /* print extra debug info if required */
-         if (options.debug || sym->level == 0)
-           {
-
-             cdbSymbol (sym, cdbFile, FALSE, FALSE);
-
-             if (!sym->level)
-               {               /* global */
-                 if (IS_STATIC (sym->etype))
-                   fprintf (afile, "F%s_", moduleName);        /* scope is file */
-                 else
-                   fprintf (afile, "G_");      /* scope is global */
-               }
-             else
-               /* symbol is local */
-               fprintf (afile, "L%s_",
-                        (sym->localof ? sym->localof->name : "-null-"));
-             fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
-           }
-#endif
 
          /* if is has an absolute address then generate
             an equate for this no need to allocate space */
@@ -1561,6 +1565,23 @@ pic16emitOverlay (FILE * afile)
     }
 }
 
+void emitStatistics(FILE *asmFile)
+{
+  statistics.isize = pic16_countInstructions();
+       
+  fprintf (asmFile, "\n\n; Statistics:\n");
+  fprintf (asmFile, "; code size:\t%ld (0x%lx) bytes\n;\t\t%ld (0x%lx) words\n",
+    statistics.isize, statistics.isize,
+    statistics.isize>>1, statistics.isize>>1);
+  fprintf (asmFile, "; udata size:\t%ld (0x%lx) bytes\n", 
+    statistics.udsize, statistics.udsize);
+  fprintf (asmFile, "; access size:\t%ld (0x%lx) bytes\n",
+    statistics.intsize, statistics.intsize);
+
+  fprintf (asmFile, "\n\n");
+}
+
+
 
 /*-----------------------------------------------------------------*/
 /* glue - the final glue that hold the whole thing together        */
@@ -1568,248 +1589,225 @@ pic16emitOverlay (FILE * afile)
 void
 pic16glue ()
 {
-
   FILE *vFile;
   FILE *asmFile;
   FILE *ovrFile = tempfile();
 
+    mainf = newSymbol ("main", 0);
+    mainf->block = 0;
 
-       mainf = newSymbol ("main", 0);
-       mainf->block = 0;
+    mainf = findSymWithLevel(SymbolTab, mainf);
 
-       mainf = findSymWithLevel(SymbolTab, mainf);
-#if 0
-       /* only if the main function exists */
-       if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
-               if (!options.cc_only)
-                       werror (E_NO_MAIN);
-               return;
-       }
-#endif
-
-//     fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
+    addSetHead(&tmpfileSet,ovrFile);
+    pic16_pCodeInitRegisters();
 
-       addSetHead(&tmpfileSet,ovrFile);
-       pic16_pCodeInitRegisters();
+    if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
+      pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
 
-       if (mainf && IFFUNC_HASBODY(mainf->type)) {
-         pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
+        pic16_addpBlock(pb);
 
-               pic16_addpBlock(pb);
+        /* entry point @ start of CSEG */
+        pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
 
-               /* entry point @ start of CSEG */
-               pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
-
-               if(initsfpnt) {
-                       pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
-                               pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
-                       pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
-                               pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
-               }
+        if(initsfpnt) {
+          pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
+                  pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
+          pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
+                  pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
+        }
 
-               /* put in the call to main */
-               pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
+        /* put in the call to main */
+        pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
 
-               if (options.mainreturn) {
-                       pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
-                       pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
-               } else {
-                       pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
-                       pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
-               }
-       }
+        if (options.mainreturn) {
+          pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
+          pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
+        } else {
+          pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
+          pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
+        }
+    }
 
-       /* At this point we've got all the code in the form of pCode structures */
-       /* Now it needs to be rearranged into the order it should be placed in the */
-       /* code space */
+    /* At this point we've got all the code in the form of pCode structures */
+    /* Now it needs to be rearranged into the order it should be placed in the */
+    /* code space */
 
-       pic16_movepBlock2Head('P');              // Last
-       pic16_movepBlock2Head(code->dbName);
-       pic16_movepBlock2Head('X');
-       pic16_movepBlock2Head(statsg->dbName);   // First
+    pic16_movepBlock2Head('P');              // Last
+    pic16_movepBlock2Head(code->dbName);
+    pic16_movepBlock2Head('X');
+    pic16_movepBlock2Head(statsg->dbName);   // First
 
-       /* print the global struct definitions */
-//     if (options.debug)
-//             cdbStructBlock (0);     //,cdbFile);
+    /* print the global struct definitions */
 
-       vFile = tempfile();
-       /* PENDING: this isnt the best place but it will do */
-       if (port->general.glue_up_main) {
-               /* create the interrupt vector table */
-               pic16createInterruptVect (vFile);
-       }
+    vFile = tempfile();
+    /* PENDING: this isnt the best place but it will do */
+    if (port->general.glue_up_main) {
+      /* create the interrupt vector table */
+      pic16createInterruptVect (vFile);
+    }
 
-       addSetHead(&tmpfileSet,vFile);
+    addSetHead(&tmpfileSet,vFile);
     
-       /* emit code for the all the variables declared */
-       pic16emitMaps ();
-       /* do the overlay segments */
-       pic16emitOverlay(ovrFile);
-       pic16_AnalyzepCode('*');
+    /* emit code for the all the variables declared */
+    pic16emitMaps ();
+
+    /* do the overlay segments */
+    pic16emitOverlay(ovrFile);
+    pic16_AnalyzepCode('*');
 
 #if 1
-       if(pic16_options.dumpcalltree) {
-         FILE *cFile;
-               sprintf(buffer, dstFileName);
-               strcat(buffer, ".calltree");
-               cFile = fopen(buffer, "w");
-               pic16_printCallTree( cFile );
-               fclose(cFile);
-       }
+    if(pic16_options.dumpcalltree) {
+      FILE *cFile;
+        
+        sprintf(buffer, dstFileName);
+        strcat(buffer, ".calltree");
+        cFile = fopen(buffer, "w");
+        pic16_printCallTree( cFile );
+        fclose(cFile);
+    }
 #endif
 
-       pic16_InlinepCode();
-       pic16_AnalyzepCode('*');
+    pic16_InlinepCode();
+    pic16_AnalyzepCode('*');
 
-       if(pic16_debug_verbose)
-               pic16_pcode_test();
 
-       /* now put it all together into the assembler file */
-       /* create the assembler file name */
-       if ((noAssemble || options.c1mode)  && fullDstFileName) {
-               sprintf (buffer, fullDstFileName);
-       } else {
-               sprintf (buffer, dstFileName);
-               strcat (buffer, ".asm");
-       }
+    if(pic16_debug_verbose)
+      pic16_pcode_test();
 
-       if (!(asmFile = fopen (buffer, "w"))) {
-               werror (E_FILE_OPEN_ERR, buffer);
-               exit (1);
-       }
+    /* now put it all together into the assembler file */
+    /* create the assembler file name */
+    if((noAssemble || options.c1mode)  && fullDstFileName) {
+      sprintf (buffer, fullDstFileName);
+    } else {
+      sprintf (buffer, dstFileName);
+      strcat (buffer, ".asm");
+    }
+
+    if(!(asmFile = fopen (buffer, "w"))) {
+      werror (E_FILE_OPEN_ERR, buffer);
+      exit (1);
+    }
     
-       /* initial comments */
-       pic16initialComments (asmFile);
+    /* initial comments */
+    pic16initialComments (asmFile);
 
-       /* print module name */
-       fprintf(asmFile, "#FILE\t\"%s\"\n", fullSrcFileName);
+    /* print module name */
+    if(options.debug)
+      fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
 
-       /* Let the port generate any global directives, etc. */
-       if (port->genAssemblerPreamble) {
-               port->genAssemblerPreamble(asmFile);
-       }
-       
-       /* print the extern variables to this module */
-       pic16_printExterns(asmFile);
+    /* Let the port generate any global directives, etc. */
+    if(port->genAssemblerPreamble) {
+      port->genAssemblerPreamble(asmFile);
+    }
        
-       /* print the global variables in this module */
-       pic16printPublics (asmFile);
+    /* Put all variables into a cblock */
+    pic16_AnalyzeBanking();
 
-#if 0
-       /* copy the sfr segment */
-       fprintf (asmFile, "%s", iComments2);
-       fprintf (asmFile, "; special function registers\n");
-       fprintf (asmFile, "%s", iComments2);
-       copyFile (asmFile, sfr->oFile);
-#endif
+    if(pic16_options.opt_flags & OF_LR_SUPPORT) {
+      pic16_OptimizeLocalRegs();
+    }
 
-       /* Put all variables into a cblock */
-       pic16_AnalyzeBanking();
-       pic16_writeUsedRegs(asmFile);
+    /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
+    if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
+      pic16_OptimizeJumps();
+    }
+
+    /* print the extern variables to this module */
+    pic16_printExterns(asmFile);
+       
+    /* print the global variables in this module */
+    pic16printPublics (asmFile);
+
+    pic16_writeUsedRegs(asmFile);
 
 #if 0
-       /* no xdata in pic */
-       /* if external stack then reserve space of it */
-       if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
-               fprintf (asmFile, "%s", iComments2);
-               fprintf (asmFile, "; external stack \n");
-               fprintf (asmFile, "%s", iComments2);
-               fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
-               fprintf (asmFile,";\t.ds 256\n");
-       }
+    /* no xdata in pic */
+    /* if external stack then reserve space of it */
+    if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
+      fprintf (asmFile, "%s", iComments2);
+      fprintf (asmFile, "; external stack \n");
+      fprintf (asmFile, "%s", iComments2);
+      fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
+      fprintf (asmFile,";\t.ds 256\n");
+    }
 #endif
 
 #if 0  
-       /* no xdata in pic */
-       /* copy xtern ram data */
-       fprintf (asmFile, "%s", iComments2);
-       fprintf (asmFile, "; external ram data\n");
-       fprintf (asmFile, "%s", iComments2);
-       copyFile (asmFile, xdata->oFile);
+    /* no xdata in pic */
+    /* copy xtern ram data */
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; external ram data\n");
+    fprintf (asmFile, "%s", iComments2);
+    copyFile (asmFile, xdata->oFile);
 #endif
 
 #if 0
-       /* copy the bit segment */
-       fprintf (asmFile, "%s", iComments2);
-       fprintf (asmFile, "; bit data\n");
-       fprintf (asmFile, "%s", iComments2);
-       copyFile (asmFile, bit->oFile);
+    /* copy the bit segment */
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; bit data\n");
+    fprintf (asmFile, "%s", iComments2);
+    copyFile (asmFile, bit->oFile);
 #endif
 
-       /* copy the interrupt vector table */
-       if(mainf && IFFUNC_HASBODY(mainf->type)) {
-               fprintf (asmFile, "%s", iComments2);
-               fprintf (asmFile, "; interrupt vector \n");
-               fprintf (asmFile, "%s", iComments2);
-               copyFile (asmFile, vFile);
-       }
+    /* copy the interrupt vector table */
+    if(mainf && IFFUNC_HASBODY(mainf->type)) {
+      fprintf (asmFile, "\n%s", iComments2);
+      fprintf (asmFile, "; interrupt vector \n");
+      fprintf (asmFile, "%s", iComments2);
+      copyFile (asmFile, vFile);
+    }
     
-       /* copy global & static initialisations */
-       fprintf (asmFile, "%s", iComments2);
-       fprintf (asmFile, "; global & static initialisations\n");
-       fprintf (asmFile, "%s", iComments2);
+    /* copy global & static initialisations */
+    fprintf (asmFile, "\n%s", iComments2);
+    fprintf (asmFile, "; global & static initialisations\n");
+    fprintf (asmFile, "%s", iComments2);
     
-#if 0
-       /* copy over code */
-       fprintf (asmFile, "%s", iComments2);
-       fprintf (asmFile, "\tcode\n");
-       fprintf (asmFile, "%s", iComments2);
-#endif
-
-       if(pic16_debug_verbose)
-               fprintf(asmFile, "; A code from now on!\n");
-       pic16_copypCode(asmFile, 'A');
-
-
-       if(mainf && IFFUNC_HASBODY(mainf->type)) {
-               fprintf(asmFile, "\tcode\n");
-               fprintf(asmFile,"__sdcc_gsinit_startup:\n");
-
-#if 0
-               /* FIXME 8051 legacy (?!) - VR 20-Jun-2003 */
-               /* if external stack is specified then the
-                * higher order byte of the xdatalocation is
-                * going into P2 and the lower order going into */
-       
-               if (options.useXstack) {
-                       fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
-                                       (((unsigned int)options.xdata_loc) >> 8) & 0xff);
-                       fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
-                                       (unsigned int)options.xdata_loc & 0xff);
-               }
-#endif
-       }
+    if(pic16_debug_verbose)
+      fprintf(asmFile, "; A code from now on!\n");
+    
+    pic16_copypCode(asmFile, 'A');
 
-//     copyFile (stderr, code->oFile);
+    if(pic16_options.no_crt) {
+      if(mainf && IFFUNC_HASBODY(mainf->type)) {
+        fprintf(asmFile, "\tcode\n");
+        fprintf(asmFile,"__sdcc_gsinit_startup:\n");
+      }
+    }
 
-       fprintf(asmFile, "; I code from now on!\n");
-       pic16_copypCode(asmFile, 'I');
+//    copyFile (stderr, code->oFile);
 
-       if(pic16_debug_verbose)
-               fprintf(asmFile, "; dbName from now on!\n");
-       pic16_copypCode(asmFile, statsg->dbName);
+    fprintf(asmFile, "; I code from now on!\n");
+    pic16_copypCode(asmFile, 'I');
 
+    if(pic16_debug_verbose)
+      fprintf(asmFile, "; dbName from now on!\n");
+    
+    pic16_copypCode(asmFile, statsg->dbName);
 
-       if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
-               fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
-       }
+    if(pic16_options.no_crt) {
+      if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
+        fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
+      }
+    }
        
+    if(pic16_debug_verbose)
+      fprintf(asmFile, "; X code from now on!\n");
 
-       if(pic16_debug_verbose)
-               fprintf(asmFile, "; X code from now on!\n");
-       pic16_copypCode(asmFile, 'X');
-
-       if(pic16_debug_verbose)
-               fprintf(asmFile, "; M code from now on!\n");
-       pic16_copypCode(asmFile, 'M');
+    pic16_copypCode(asmFile, 'X');
 
+    if(pic16_debug_verbose)
+      fprintf(asmFile, "; M code from now on!\n");
 
-       pic16_copypCode(asmFile, code->dbName);
+    pic16_copypCode(asmFile, 'M');
 
-       pic16_copypCode(asmFile, 'P');
+    pic16_copypCode(asmFile, code->dbName);
+    
+    pic16_copypCode(asmFile, 'P');
 
-       fprintf (asmFile,"\tend\n");
-       fclose (asmFile);
+    emitStatistics(asmFile);
 
-       rm_tmpfiles();
+    fprintf (asmFile,"\tend\n");
+    fclose (asmFile);
+    
+    rm_tmpfiles();
 }