* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / pic16 / main.c
index 7c9bb8312dd3207da693b26b233d667e5fe984d6..ee7b4b4f4fd8848b66367b86cb07602fffaf97fd 100644 (file)
@@ -31,7 +31,7 @@
 #include "SDCCutil.h"
 #include "glue.h"
 #include "pcode.h"
-//#include "gen.h"
+#include "dbuf_string.h"
 
 
 static char _defaultRules[] =
@@ -161,258 +161,359 @@ struct {
 } libflags = { 0, 0, 0, 0, 0 };
   
 
+enum {
+  P_MAXRAM = 1,
+  P_STACK,
+  P_CODE,
+  P_UDATA,
+  P_LIBRARY
+};
+
 static int
-_process_pragma(const char *sz)
+do_pragma(int id, const char *name, const char *cp)
 {
-  static const char *WHITE = " \t\n";
-  static const char *WHITECOMMA = " \t\n,";
-  char *ptr = strtok((char *)sz, WHITE);
+  struct pragma_token_s token;
+  int err = 0;
+  int processed = 1;
 
-    /* #pragma maxram [maxram] */
-    if (startsWith (ptr, "maxram")) {
-      char *maxRAM = strtok((char *)NULL, WHITE);
+  init_pragma_token(&token);
 
-        if (maxRAM != (char *)NULL) {
-          int maxRAMaddress;
-          value *maxRAMVal;
+  switch (id)
+    {
+    /* #pragma maxram [maxram] */
+    case P_MAXRAM:
+      {
+        int max_ram;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_INT == token.type)
+          max_ram = token.val.int_val;
+        else
+          {
+            err = 1;
+            break;
+          }
 
-            maxRAMVal = constVal(maxRAM);
-            maxRAMaddress = (int)floatFromVal(maxRAMVal);
-            pic16_setMaxRAM(maxRAMaddress);
-        }
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
 
-        return 0;
-    }
-  
-  /* #pragma stack [stack-position] [stack-len] */
-  if(startsWith(ptr, "stack")) {
-    char *stackPosS = strtok((char *)NULL, WHITE);
-    char *stackLenS = strtok((char *)NULL, WHITE);
-    value *stackPosVal;
-    value *stackLenVal;
-    regs *reg;
-    symbol *sym;
-
-      if (!stackPosS) {
-        fprintf (stderr, "%s:%d: #pragma stack [stack-pos] [stack-length] -- stack-position missing\n", filename, lineno-1);
-
-        return 0; /* considered an error */
+        pic16_setMaxRAM(max_ram);
       }
+      break;
 
-      stackPosVal = constVal( stackPosS );
-      stackPos = (unsigned int)floatFromVal( stackPosVal );
-
-      if(stackLenS) {
-        stackLenVal = constVal( stackLenS );
-        stackLen = (unsigned int)floatFromVal( stackLenVal );
-      }
+    /* #pragma stack [stack-position] [stack-len] */
+    case  P_STACK:
+      {
+        unsigned int stackPos, stackLen;
+        regs *reg;
+        symbol *sym;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_INT != token.type)
+          {
+            err = 1;
+            break;
+          }
+        stackPos = token.val.int_val;
 
-      if(stackLen < 1) {
-        stackLen = 64;
-        fprintf(stderr, "%s:%d: warning: setting stack to default size %d (0x%04x)\n",
-                filename, lineno-1, stackLen, stackLen);
-      }
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_INT != token.type)
+          {
+            err = 1;
+            break;
+          }
+        stackLen = token.val.int_val;
 
-      /* check sanity of stack */
-      if ((stackPos >> 8) != ((stackPos+stackLen-1) >> 8)) {
-        fprintf (stderr, "%s:%u: warning: stack [0x%03X,0x%03X] crosses memory bank boundaries (not fully tested)\n",
-               filename,lineno-1, stackPos, stackPos+stackLen-1);
-      }
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
 
-      if (pic16) {
-        if (stackPos < pic16->acsSplitOfs) {
-          fprintf (stderr, "%s:%u: warning: stack [0x%03X, 0x%03X] intersects with the access bank [0x000,0x%03x] -- this is highly discouraged!\n",
-               filename, lineno-1, stackPos, stackPos+stackLen-1, pic16->acsSplitOfs);
+        if (stackLen < 1) {
+          stackLen = 64;
+          fprintf(stderr, "%s:%d: warning: setting stack to default size %d (0x%04x)\n",
+                  filename, lineno, stackLen, stackLen);
         }
 
-        if (stackPos+stackLen > 0xF00 + pic16->acsSplitOfs) {
-          fprintf (stderr, "%s:%u: warning: stack [0x%03X,0x%03X] intersects with special function registers [0x%03X,0xFFF]-- this is highly discouraged!\n",
-               filename, lineno-1, stackPos, stackPos+stackLen-1, 0xF00 + pic16->acsSplitOfs);
+        /* check sanity of stack */
+        if ((stackPos >> 8) != ((stackPos + stackLen - 1) >> 8)) {
+          fprintf (stderr, "%s:%u: warning: stack [0x%03X,0x%03X] crosses memory bank boundaries (not fully tested)\n",
+                  filename, lineno, stackPos, stackPos + stackLen - 1);
         }
 
-        if (stackPos+stackLen > pic16->RAMsize) {
-          fprintf (stderr, "%s:%u: error: stack [0x%03X,0x%03X] is placed outside available memory [0x000,0x%03X]!\n",
-               filename, lineno-1, stackPos, stackPos+stackLen-1, pic16->RAMsize-1);
-          exit(EXIT_FAILURE);
-          return 1;    /* considered an error, but this reports "invalid pragma stack"... */
+        if (pic16) {
+          if (stackPos < pic16->acsSplitOfs) {
+            fprintf (stderr, "%s:%u: warning: stack [0x%03X, 0x%03X] intersects with the access bank [0x000,0x%03x] -- this is highly discouraged!\n",
+                  filename, lineno, stackPos, stackPos + stackLen - 1, pic16->acsSplitOfs);
+          }
+
+          if (stackPos+stackLen > 0xF00 + pic16->acsSplitOfs) {
+            fprintf (stderr, "%s:%u: warning: stack [0x%03X,0x%03X] intersects with special function registers [0x%03X,0xFFF]-- this is highly discouraged!\n",
+                   filename, lineno, stackPos, stackPos + stackLen - 1, 0xF00 + pic16->acsSplitOfs);
+          }
+
+          if (stackPos+stackLen > pic16->RAMsize) {
+            fprintf (stderr, "%s:%u: error: stack [0x%03X,0x%03X] is placed outside available memory [0x000,0x%03X]!\n",
+                  filename, lineno, stackPos, stackPos + stackLen - 1, pic16->RAMsize-1);
+            err = 1;
+            break;
+          }
         }
-      }
 
-      reg=newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "_stack", stackLen-1, 0, NULL);
-      addSet(&pic16_fix_udata, reg);
-    
-      reg = newReg(REG_SFR, PO_SFR_REGISTER, stackPos + stackLen-1, "_stack_end", 1, 0, NULL);
-      addSet(&pic16_fix_udata, reg);
-    
-      sym = newSymbol("stack", 0);
-      sprintf(sym->rname, "_%s", sym->name);
-      addSet(&publics, sym);
+        reg = newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "_stack", stackLen-1, 0, NULL);
+        addSet(&pic16_fix_udata, reg);
 
-      sym = newSymbol("stack_end", 0);
-      sprintf(sym->rname, "_%s", sym->name);
-      addSet(&publics, sym);
-    
-      initsfpnt = 1;    // force glue() to initialize stack/frame pointers */
+        reg = newReg(REG_SFR, PO_SFR_REGISTER, stackPos + stackLen-1, "_stack_end", 1, 0, NULL);
+        addSet(&pic16_fix_udata, reg);
 
-    return 0;
-  }
-  
-  /* #pragma code [symbol] [location] */
-  if(startsWith(ptr, "code")) {
-    char *symname = strtok((char *)NULL, WHITE);
-    char *location = strtok((char *)NULL, WHITE);
-    absSym *absS;
-    value *addr;
-
-      if (!symname || !location) {
-        fprintf (stderr, "%s:%d: #pragma code [symbol] [location] -- symbol or location missing\n", filename, lineno-1);
-       exit (EXIT_FAILURE);
-        return 1; /* considered an error, but this reports "invalid pragma code"... */
-      }
+        sym = newSymbol("stack", 0);
+        sprintf(sym->rname, "_%s", sym->name);
+        addSet(&publics, sym);
 
-      absS = Safe_calloc(1, sizeof(absSym));
-      sprintf(absS->name, "_%s", symname);
+        sym = newSymbol("stack_end", 0);
+        sprintf(sym->rname, "_%s", sym->name);
+        addSet(&publics, sym);
     
-      addr = constVal( location );
-      absS->address = (unsigned int)floatFromVal( addr );
-
-      if((absS->address % 2) != 0) {
-        absS->address--;
-        fprintf(stderr, "%s:%d: warning: code memory locations should be word aligned, will locate to 0x%06x instead\n",
-                filename, lineno-1, absS->address);
+        initsfpnt = 1;    // force glue() to initialize stack/frame pointers */
       }
+      break;
 
-      addSet(&absSymSet, absS);
-//    fprintf(stderr, "%s:%d symbol %s will be placed in location 0x%06x in code memory\n",
-//      __FILE__, __LINE__, symname, absS->address);
+    /* #pragma code [symbol] [location] */
+    case P_CODE:
+      {
+        absSym *absS;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_STR != token.type)
+          goto code_err;
+
+        absS = Safe_calloc(1, sizeof(absSym));
+        sprintf(absS->name, "_%s", get_pragma_string(&token));
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_INT != token.type)
+          {
+          code_err:
+            //fprintf (stderr, "%s:%d: #pragma code [symbol] [location] -- symbol or location missing\n", filename, lineno);
+            err = 1;
+            break;
+          }
+        absS->address = token.val.int_val;
 
-    return 0;
-  }
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
 
-  /* #pragma udata [section-name] [symbol] */
-  if(startsWith(ptr, "udata")) {
-    char *sectname = strtok((char *)NULL, WHITE);
-    char *symname = strtok((char *)NULL, WHITE);
-    symbol *nsym;
-    sectSym *ssym;
-    sectName *snam;
-    int found=0;
-    
-      if (!symname || !sectname) {
-        fprintf (stderr, "%s:%d: #pragma udata [section-name] [symbol] -- section-name or symbol missing!\n", filename, lineno-1);
-       exit (EXIT_FAILURE);
-        return 1; /* considered an error, but this reports "invalid pragma code"... */
+        if ((absS->address % 2) != 0) {
+          absS->address--;
+          fprintf(stderr, "%s:%d: warning: code memory locations should be word aligned, will locate to 0x%06x instead\n",
+                  filename, lineno, absS->address);
+        }
+
+        addSet(&absSymSet, absS);
+//      fprintf(stderr, "%s:%d symbol %s will be placed in location 0x%06x in code memory\n",
+//        __FILE__, __LINE__, symname, absS->address);
       }
-    
-      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;
+      break;
+
+    /* #pragma udata [section-name] [symbol] */
+    case P_UDATA:
+      {
+        char *sectname;
+        const char *symname;
+        symbol *nsym;
+        sectSym *ssym;
+        sectName *snam;
+        int found = 0;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_STR == token.type)
+          sectname = Safe_strdup(get_pragma_string(&token));
+        else
+          {
+            err = 1;
+            break;
+          }
+
+        cp = get_pragma_token(cp, &token);
+        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;
+            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;
 
-        addSet(&sectSyms, ssym);
+            addSet(&sectSyms, ssym);
 
-        nsym = newSymbol(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; }
-        }
-      
-        if(!found) {
-          snam = Safe_calloc(1, sizeof(sectName));
-          snam->name = Safe_strdup( sectname );
-          snam->regsSet = NULL;
-        
-          addSet(&sectNames, snam);
-        }
-      
-        ssym->section = snam;
-        
+            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;
+
+                addSet(&sectNames, 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
 
-        symname = strtok((char *)NULL, WHITE);
-    }
+            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;
+              }
+          }
 
-    return 0;
-  }
-  
-  /* #pragma wparam function1[, function2[,...]] */
-  if(startsWith(ptr, "wparam")) {
-    char *fname = strtok((char *)NULL, WHITECOMMA);
-
-      
-      while(fname) {
-        fprintf(stderr, "PIC16 Warning: `%s' wparam pragma is obsolete. use function attribute `wparam' instead.\n", fname);
-        addSet(&wparamList, Safe_strdup(fname));
-              
-//        debugf("passing with WREG to %s\n", fname);
-        fname = strtok((char *)NULL, WHITECOMMA);
+          Safe_free(sectname);
       }
-            
-      return 0;
-  }
-        
-  /* #pragma library library_module */
-  if(startsWith(ptr, "library")) {
-  char *lmodule = strtok((char *)NULL, WHITE);
-        
-    if(lmodule) {
-      /* lmodule can be:
-       * c     link the C library
-       * math  link the math library
-       * io    link the IO library
-       * debug link the debug libary
-       * anything else, will link as-is */
-       
-      if(!strcmp(lmodule, "c"))libflags.want_libc = 1;
-      else if(!strcmp(lmodule, "math"))libflags.want_libm = 1;
-      else if(!strcmp(lmodule, "io"))libflags.want_libio = 1;
-      else if(!strcmp(lmodule, "debug"))libflags.want_libdebug = 1;
-      else if(!strcmp(lmodule, "ignore"))libflags.ignore = 1;
-      else {
-        if(!libflags.ignore) {
-          fprintf(stderr, "link library %s\n", lmodule);
-          addSetHead(&libFilesSet, lmodule);
-        }
+      break;
+
+    /* #pragma library library_module */
+    case P_LIBRARY:
+      {
+        const char *lmodule;
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            lmodule = get_pragma_string(&token);
+
+            /* lmodule can be:
+             * c       link the C library
+             * math    link the math library
+             * io      link the IO library
+             * debug   link the debug libary
+             * anything else, will link as-is */
+     
+            if(!strcmp(lmodule, "c"))
+              libflags.want_libc = 1;
+            else if(!strcmp(lmodule, "math"))
+              libflags.want_libm = 1;
+            else if(!strcmp(lmodule, "io"))
+              libflags.want_libio = 1;
+            else if(!strcmp(lmodule, "debug"))
+              libflags.want_libdebug = 1;
+            else if(!strcmp(lmodule, "ignore"))
+              libflags.ignore = 1;
+            else
+              {
+                if(!libflags.ignore)
+                  {
+                    fprintf(stderr, "link library %s\n", lmodule);
+                    addSetHead(&libFilesSet, (char *)lmodule);
+                  }
+              }
+          }
+        else
+          {
+            err = 1;
+            break;
+          }
+
+        cp = get_pragma_token(cp, &token);
+        if (TOKEN_EOL != token.type)
+          {
+            err = 1;
+            break;
+          }
       }
-    }
-    
-    return 0;
-  }
-   
+      break;
+
 #if 0
   /* This is an experimental code for #pragma inline
      and is temporarily disabled for 2.5.0 release */
-  if(startsWith(ptr, "inline")) {
-    char *tmp = strtok((char *)NULL, WHITECOMMA);
+    case P_INLINE:
+      {
+        char *tmp = strtok((char *)NULL, WHITECOMMA);
 
-      while(tmp) {
-        addSet(&asmInlineMap, Safe_strdup( tmp ));
-        tmp = strtok((char *)NULL, WHITECOMMA);
-      }
+        while(tmp) {
+          addSet(&asmInlineMap, Safe_strdup( tmp ));
+          tmp = strtok((char *)NULL, WHITECOMMA);
+        }
 
-      {
-        char *s;
+        {
+          char *s;
           
           for(s = setFirstItem(asmInlineMap); s ; s = setNextItem(asmInlineMap)) {
             debugf("inline asm: `%s'\n", s);
           }
+        }
       }
-      
-      return 0;
-  }
+      break;
 #endif  /* 0 */
 
-  return 1;
+    default:
+      processed = 0;
+      break;
+  }
+
+  get_pragma_token(cp, &token);
+
+  if (1 == err)
+    werror(W_BAD_PRAGMA_ARGUMENTS, name);
+
+  free_pragma_token(&token);
+  return processed;
+}
+
+static struct pragma_s pragma_tbl[] = {
+  { "maxram",  P_MAXRAM,  0, do_pragma },
+  { "stack",   P_STACK,   0, do_pragma },
+  { "code",    P_CODE,    0, do_pragma },
+  { "udata",   P_UDATA,   0, do_pragma },
+  { "library", P_LIBRARY, 0, do_pragma },
+/*{ "inline",  P_INLINE,  0, do_pragma }, */
+  { NULL,      0,         0, NULL },
+  };
+
+static int
+_process_pragma(const char *s)
+{
+  return process_pragma_tbl(pragma_tbl, s);
 }
 
 #define REP_UDATA      "--preplace-udata-with="
@@ -597,8 +698,6 @@ extern set *userIncDirsSet;
 
 static void _pic16_initPaths(void)
 {
-  char pic16incDir[512];
-  char pic16libDir[512];
   set *pic16incDirsSet=NULL;
   set *pic16libDirsSet=NULL;
   char devlib[512];
@@ -609,13 +708,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);
     }
@@ -624,8 +725,13 @@ static void _pic16_initPaths(void)
     mergeSets(&pic16incDirsSet, userIncDirsSet);
 
     if(!options.nostdlib) {
+      struct dbuf_s pic16libDir;
+
+      dbuf_init(&pic16libDir, 128);
+      dbuf_makePath(&pic16libDir, INCLUDE_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);
     }
@@ -879,35 +985,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
@@ -1192,6 +1298,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