* src/pic16/glue.c (pic16_initPointer): avoid assertion, emit better
[fw/sdcc] / src / pic16 / main.c
index 13f3bc47d2fe38050019a543ad4984f59885ca3c..bf96970237f1d17443d441c4f1317ff6a6ee5005 100644 (file)
@@ -31,6 +31,8 @@
 #include "SDCCutil.h"
 #include "glue.h"
 #include "pcode.h"
+#include "SDCCargs.h"
+#include "dbuf_string.h"
 
 
 static char _defaultRules[] =
@@ -335,68 +337,79 @@ do_pragma(int id, const char *name, const char *cp)
         int found = 0;
 
         cp = get_pragma_token(cp, &token);
-        if (TOKEN_EOL == token.type)
-          goto udata_err;
-
-        sectname = Safe_strdup(get_pragma_string(&token));
-
-        cp = get_pragma_token(cp, &token);
-        if (TOKEN_EOL == token.type)
+        if (TOKEN_STR == token.type)
+          sectname = Safe_strdup(get_pragma_string(&token));
+        else
           {
-          udata_err:
-            //fprintf (stderr, "%s:%d: #pragma udata [section-name] [symbol] -- section-name or symbol missing!\n", filename, lineno);
             err = 1;
             break;
           }
-        symname = get_pragma_string(&token);
 
         cp = get_pragma_token(cp, &token);
-        if (TOKEN_EOL != token.type)
+        if (TOKEN_STR == token.type)
+          symname = get_pragma_string(&token);
+        else
           {
+            //fprintf (stderr, "%s:%d: #pragma udata [section-name] [symbol] -- section-name or symbol missing!\n", filename, lineno);
             err = 1;
-            break;
+            symname = NULL;
           }
 
-        while (symname) {
-          ssym = Safe_calloc(1, sizeof(sectSym));
-          ssym->name = Safe_calloc(1, strlen(symname) + 2);
-          sprintf(ssym->name, "%s%s", port->fun_prefix, symname);
-          ssym->reg = NULL;
+        while (symname)
+          {
+            ssym = Safe_calloc(1, sizeof(sectSym));
+            ssym->name = Safe_calloc(1, strlen(symname) + 2);
+            sprintf(ssym->name, "%s%s", port->fun_prefix, symname);
+            ssym->reg = NULL;
 
-          addSet(&sectSyms, ssym);
+            addSet(&sectSyms, ssym);
 
-          nsym = newSymbol((char *)symname, 0);
-          strcpy(nsym->rname, ssym->name);
+            nsym = newSymbol((char *)symname, 0);
+            strcpy(nsym->rname, ssym->name);
 
 #if 0
-          checkAddSym(&publics, nsym);
+            checkAddSym(&publics, nsym);
 #endif
 
-          found = 0;
-          for (snam = setFirstItem(sectNames);snam;snam=setNextItem(sectNames)) {
-            if (!strcmp(sectname, snam->name)){ found=1; break; }
-          }
+            found = 0;
+            for (snam = setFirstItem(sectNames);snam;snam=setNextItem(sectNames))
+              {
+                if (!strcmp(sectname, snam->name))
+                  {
+                    found=1;
+                    break;
+                  }
+              }
 
-          if(!found) {
-            snam = Safe_calloc(1, sizeof(sectName));
-            snam->name = Safe_strdup(sectname);
-            snam->regsSet = NULL;
+            if(!found)
+              {
+                snam = Safe_calloc(1, sizeof(sectName));
+                snam->name = Safe_strdup(sectname);
+                snam->regsSet = NULL;
 
-            addSet(&sectNames, snam);
-          }
+                addSet(&sectNames, snam);
+              }
 
-          ssym->section = snam;
+            ssym->section = snam;
 
 #if 0
-          fprintf(stderr, "%s:%d placing symbol %s at section %s (%p)\n", __FILE__, __LINE__,
-             ssym->name, snam->name, snam);
+            fprintf(stderr, "%s:%d placing symbol %s at section %s (%p)\n", __FILE__, __LINE__,
+               ssym->name, snam->name, snam);
 #endif
 
-          cp = get_pragma_token(cp, &token);
-          symname = (TOKEN_EOL != token.type) ? get_pragma_string(&token) : NULL;
-        }
+            cp = get_pragma_token(cp, &token);
+            if (TOKEN_STR == token.type)
+              symname = get_pragma_string(&token);
+            else if (TOKEN_EOL == token.type)
+              symname = NULL;
+            else
+              {
+                err = 1;
+                symname = NULL;
+              }
+          }
 
-        Safe_free(sectname);
+          Safe_free(sectname);
       }
       break;
 
@@ -417,7 +430,8 @@ do_pragma(int id, const char *name, const char *cp)
              * debug   link the debug libary
              * anything else, will link as-is */
      
-            if(!strcmp(lmodule, "c"))libflags.want_libc = 1;
+            if(!strcmp(lmodule, "c"))
+              libflags.want_libc = 1;
             else if(!strcmp(lmodule, "math"))
               libflags.want_libm = 1;
             else if(!strcmp(lmodule, "io"))
@@ -515,7 +529,6 @@ _process_pragma(const char *s)
 #define NO_DEFLIBS     "--nodefaultlibs"
 #define MPLAB_COMPAT   "--mplab-comp"
 
-#define NL_OPT         "--nl="
 #define USE_CRT                "--use-crt="
 
 #define        OFMSG_LRSUPPORT "--flr-support"
@@ -532,53 +545,47 @@ extern int pic16_debug_verbose;
 extern int pic16_ralloc_debug;
 extern int pic16_pcode_verbose;
 
-int pic16_fstack=0;
 int pic16_enable_peeps=0;
-int pic16_nl=0;                        /* 0 for LF, 1 for CRLF */
 
 OPTION pic16_optionsTable[]= {
-       { 0,    NO_DEFLIBS,             &pic16_options.nodefaultlibs,   "do not link default libraries when linking"},
-       { 0,    "--pno-banksel",        &pic16_options.no_banksel,      "do not generate BANKSEL assembler directives"},
-       { 0,    OPT_BANKSEL,            NULL,                           "set banksel optimization level (default=0 no)"},
-//     { 0,    "--pomit-config-words", &pic16_options.omit_configw,    "omit the generation of configuration words"},
-//     { 0,    "--pomit-ivt",          &pic16_options.omit_ivt,        "omit the generation of the Interrupt Vector Table"},
-//     { 0,    "--pleave-reset-vector",&pic16_options.leave_reset,     "when omitting IVT leave RESET vector"},
+       /* code generation options */
        { 0,    STACK_MODEL,            NULL,                           "use stack model 'small' (default) or 'large'"},
+#if XINST
+       { 'y',  "--extended",   &xinst, "enable Extended Instruction Set/Literal Offset Addressing mode"},
+#endif
+       { 0,    "--pno-banksel",        &pic16_options.no_banksel,      "do not generate BANKSEL assembler directives"},
 
-       { 0,    "--debug-xtra",         &pic16_debug_verbose,   "show more debug info in assembly output"},
-       { 0,    "--debug-ralloc",       &pic16_ralloc_debug,    "dump register allocator debug file *.d"},
-       { 0,    "--pcode-verbose",      &pic16_pcode_verbose,   "dump pcode related info"},
-               
-       { 0,    REP_UDATA,      NULL,   "Place udata variables at another section: udata_acs, udata_ovr, udata_shr"},
+       /* optimization options */
+       { 0,    OPT_BANKSEL,            NULL,                           "set banksel optimization level (default=0 no)"},
+       { 0,    "--denable-peeps",      &pic16_enable_peeps,    "explicit enable of peepholes"},
+       { 0,    OPTIMIZE_GOTO,  NULL,                   "try to use (conditional) BRA instead of GOTO"},
+       { 0,    OPTIMIZE_CMP,   NULL,                   "try to optimize some compares"},
+       { 0,    OPTIMIZE_DF,    NULL,                   "thoroughly analyze data flow (memory and time intensive!)"},
 
+       /* assembling options */
        { 0,    ALT_ASM,        NULL,   "Use alternative assembler"},
-       { 0,    ALT_LINK,       NULL,   "Use alternative linker"},
-
-       { 0,    "--denable-peeps",      &pic16_enable_peeps,    "explicit enable of peepholes"},
-       { 0,    IVT_LOC,        NULL,   "<nnnn> interrupt vector table location"},
-       { 0,    "--calltree",           &pic16_options.dumpcalltree,    "dump call tree in .calltree file"},
        { 0,    MPLAB_COMPAT,           &pic16_mplab_comp,      "enable compatibility mode for MPLAB utilities (MPASM/MPLINK)"},
-       { 0,    "--fstack",             &pic16_fstack,          "enable stack optimizations"},
-       { 0,    NL_OPT,         NULL,                           "new line, \"lf\" or \"crlf\""},
+
+       /* linking options */
+       { 0,    ALT_LINK,       NULL,   "Use alternative linker"},
+       { 0,    REP_UDATA,      NULL,   "Place udata variables at another section: udata_acs, udata_ovr, udata_shr"},
+       { 0,    IVT_LOC,        NULL,   "Set address of interrupt vector table."},
+       { 0,    NO_DEFLIBS,             &pic16_options.nodefaultlibs,   "do not link default libraries when linking"},
        { 0,    USE_CRT,        NULL,   "use <crt-o> run-time initialization module"},
        { 0,    "--no-crt",     &pic16_options.no_crt,  "do not link any default run-time initialization module"},
+
+       /* debugging options */
+       { 0,    "--debug-xtra",         &pic16_debug_verbose,   "show more debug info in assembly output"},
+       { 0,    "--debug-ralloc",       &pic16_ralloc_debug,    "dump register allocator debug file *.d"},
+       { 0,    "--pcode-verbose",      &pic16_pcode_verbose,   "dump pcode related info"},
+       { 0,    "--calltree",           &pic16_options.dumpcalltree,    "dump call tree in .calltree file"},
        { 0,    "--gstack",     &pic16_options.gstack,  "trace stack pointer push/pop to overflow"},
-       { 0,    OPTIMIZE_GOTO,  NULL,                   "try to use (conditional) BRA instead of GOTO"},
-       { 0,    OPTIMIZE_CMP,   NULL,                   "try to optimize some compares"},
-       { 0,    OPTIMIZE_DF,    NULL,                   "thoroughly analyze data flow (memory and time intensive!)"},
-       { 0,    "--num-func-alloc-regs", &pic16_options.CATregs, "dump number of temporary registers allocated for each function"},
-#if XINST
-       { 'y',  "--extended",   &xinst, "enable Extended Instruction Set/Literal Offset Addressing mode"},
-#endif
        { 0,    NULL,           NULL,   NULL}
-       };
+};
 
 
 #define ISOPT(str)     !strncmp(argv[ *i ], str, strlen(str) )
 
-extern char *getStringArg(const char *,  char **, int *, int);
-extern int getIntArg(const char *, char **, int *, int);
-
 static bool
 _pic16_parseOptions (int *pargc, char **argv, int *i)
 {
@@ -635,19 +642,6 @@ _pic16_parseOptions (int *pargc, char **argv, int *i)
       return TRUE;
     }
        
-    if(ISOPT(NL_OPT)) {
-      char *tmp;
-            
-        tmp = Safe_strdup( getStringArg(NL_OPT, argv, i, *pargc) );
-        if(!STRCASECMP(tmp, "lf"))pic16_nl = 0;
-        else if(!STRCASECMP(tmp, "crlf"))pic16_nl = 1;
-        else {
-          fprintf(stderr, "invalid termination character id\n");
-          exit(EXIT_FAILURE);
-        }
-        return TRUE;
-    }
-
     if(ISOPT(USE_CRT)) {
       pic16_options.no_crt = 0;
       pic16_options.crt_name = Safe_strdup( getStringArg(USE_CRT, argv, i, *pargc) );
@@ -685,8 +679,6 @@ extern set *userIncDirsSet;
 
 static void _pic16_initPaths(void)
 {
-  char pic16incDir[512];
-  char pic16libDir[512];
   set *pic16incDirsSet=NULL;
   set *pic16libDirsSet=NULL;
   char devlib[512];
@@ -697,13 +689,15 @@ static void _pic16_initPaths(void)
     setMainValue("mcu1", pic16->name[1] );
     addSet(&preArgvSet, Safe_strdup("-D__{mcu1}"));
 
-    sprintf(pic16incDir, "%s%cpic16", INCLUDE_DIR_SUFFIX, DIR_SEPARATOR_CHAR);
-    sprintf(pic16libDir, "%s%cpic16", LIB_DIR_SUFFIX, DIR_SEPARATOR_CHAR);
+    if(!options.nostdinc) {
+      struct dbuf_s pic16incDir;
 
+      dbuf_init(&pic16incDir, 128);
+      dbuf_makePath(&pic16incDir, INCLUDE_DIR_SUFFIX, "pic16");
 
-    if(!options.nostdinc) {
       /* setup pic16 include directory */
-      pic16incDirsSet = appendStrSet(dataDirsSet, NULL, pic16incDir);
+      pic16incDirsSet = appendStrSet(dataDirsSet, NULL, dbuf_c_str(&pic16incDir));
+      dbuf_destroy(&pic16incDir);
       includeDirsSet = pic16incDirsSet;
 //      mergeSets(&includeDirsSet, pic16incDirsSet);
     }
@@ -712,8 +706,13 @@ static void _pic16_initPaths(void)
     mergeSets(&pic16incDirsSet, userIncDirsSet);
 
     if(!options.nostdlib) {
+      struct dbuf_s pic16libDir;
+
+      dbuf_init(&pic16libDir, 128);
+      dbuf_makePath(&pic16libDir, LIB_DIR_SUFFIX, "pic16");
       /* setup pic16 library directory */
-      pic16libDirsSet = appendStrSet(dataDirsSet, NULL, pic16libDir);
+      pic16libDirsSet = appendStrSet(dataDirsSet, NULL, dbuf_c_str(&pic16libDir));
+      dbuf_destroy(&pic16libDir);
       libDirsSet = pic16libDirsSet;
 //      mergeSets(&libDirsSet, pic16libDirsSet);
     }
@@ -918,7 +917,6 @@ _pic16_setDefaultOptions (void)
   pic16_options.ip_stack = 1;          /* set to 1 to enable ipop/ipush for stack */
   pic16_options.gstack = 0;
   pic16_options.debgen = 0;
-  pic16_options.CATregs = 0;
 }
 
 static const char *
@@ -967,35 +965,35 @@ _pic16_genAssemblerPreamble (FILE * of)
 
 /* Generate interrupt vector table. */
 static int
-_pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+_pic16_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
 {
 #if 1
        /* PIC18F family has only two interrupts, the high and the low
         * priority interrupts, which reside at 0x0008 and 0x0018 respectively - VR */
 
        if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
-               fprintf(of, "; RESET vector\n");
-               fprintf(of, "\tgoto\t__sdcc_gsinit_startup\n");
+               dbuf_printf(oBuf, "; RESET vector\n");
+               dbuf_printf(oBuf, "\tgoto\t__sdcc_gsinit_startup\n");
        }
        
        if(!pic16_options.omit_ivt) {
-               fprintf(of, "\tres 4\n");
+               dbuf_printf(oBuf, "\tres 4\n");
 
 
-               fprintf(of, "; High priority interrupt vector 0x0008\n");
+               dbuf_printf(oBuf, "; High priority interrupt vector 0x0008\n");
                if(interrupts[1]) {
-                       fprintf(of, "\tgoto\t%s\n", interrupts[1]->rname);
-                       fprintf(of, "\tres\t12\n"); 
+                       dbuf_printf(oBuf, "\tgoto\t%s\n", interrupts[1]->rname);
+                       dbuf_printf(oBuf, "\tres\t12\n"); 
                } else {
-                       fprintf(of, "\tretfie\n");
-                       fprintf(of, "\tres\t14\n");
+                       dbuf_printf(oBuf, "\tretfie\n");
+                       dbuf_printf(oBuf, "\tres\t14\n");
                }
 
-               fprintf(of, "; Low priority interrupt vector 0x0018\n");
+               dbuf_printf(oBuf, "; Low priority interrupt vector 0x0018\n");
                if(interrupts[2]) {
-                       fprintf(of, "\tgoto\t%s\n", interrupts[2]->rname);
+                       dbuf_printf(oBuf, "\tgoto\t%s\n", interrupts[2]->rname);
                } else {
-                       fprintf(of, "\tretfie\n");
+                       dbuf_printf(oBuf, "\tretfie\n");
                }
        }
 #endif
@@ -1280,6 +1278,8 @@ PORT pic16_port =
     NULL,                      // xinit
     "CONST   (CODE)",          // const_name - const data (code or not)
     "CABS    (ABS,CODE)",      // cabs_name - const absolute data (code or not)
+    "XABS    (ABS,XDATA)",     // xabs_name - absolute xdata
+    "IABS    (ABS,DATA)",      // iabs_name - absolute data
     NULL,                      // default location for auto vars
     NULL,                      // default location for global vars
     1                          // code is read only 1=yes