* src/SDCCmain.c (linkEdit): do not test for PIC16 target since, PIC16
[fw/sdcc] / src / pic16 / pcode.c
index 9f77d9d683b73c2a78da9e1a0a68bfe9f191c24b..e20eb83206fbce78c8fc6da68c39329c5f22ccd4 100644 (file)
@@ -161,7 +161,7 @@ extern void pic16_BuildFlowTree(pBlock *pb);
 extern void pic16_pCodeRegOptimizeRegUsage(int level);
 extern int pic16_picIsInitialized(void);
 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
-extern int mnem2key(char const *mnem);
+extern int mnem2key(unsigned char const *mnem);
 
 /****************************************************************/
 /*                      Forward declarations                    */
@@ -3113,7 +3113,7 @@ void  pic16_pCodeInitRegisters(void)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-int mnem2key(char const *mnem)
+int mnem2key(unsigned char const *mnem)
 {
   int key = 0;
 
@@ -3856,7 +3856,7 @@ pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
 
        if(asdir && *asdir) {
                
-               while(isspace(*asdir))asdir++;  // strip any white space from the beginning
+               while(isspace((unsigned char)*asdir))asdir++;   // strip any white space from the beginning
                
                pcad->directive = Safe_strdup( asdir );
        }
@@ -3869,7 +3869,7 @@ pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
        
        va_end(ap);
        
-       while(isspace(*lbp))lbp++;
+       while(isspace((unsigned char)*lbp))lbp++;
        
        if(lbp && *lbp)
                pcad->arg = Safe_strdup( lbp );
@@ -4244,26 +4244,28 @@ pCodeOp *pic16_newpCodeOpBit_simple (struct asmop *op, int offs, int bit)
 pCodeOp *pic16_newpCodeOpReg(int rIdx)
 {
   pCodeOp *pcop;
+  regs *r;
 
   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
 
   pcop->name = NULL;
 
   if(rIdx >= 0) {
-    PCOR(pcop)->rIdx = rIdx;
-    PCOR(pcop)->r = pic16_regWithIdx(rIdx);
+       r = pic16_regWithIdx(rIdx);
+       if(!r)
+               r = pic16_allocWithIdx(rIdx);
   } else {
-    PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
+    r = pic16_findFreeReg(REG_GPR);
 
-    if(PCOR(pcop)->r)
-      PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
-    else {
+    if(!r) {
        fprintf(stderr, "%s:%d Could not find a free GPR register\n",
                __FUNCTION__, __LINE__);
        exit(-1);
     }
   }
 
+  PCOR(pcop)->rIdx = rIdx;
+  PCOR(pcop)->r = r;
   pcop->type = PCOR(pcop)->r->pc_type;
 
   return pcop;
@@ -4385,12 +4387,18 @@ pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
   return pcop;
 }
 
-#define DB_ITEMS_PER_LINE      8
+/* This is a multiple of two as gpasm pads DB directives to even length,
+ * thus the data would be interleaved with \0 bytes...
+ * This is a multiple of three in order to have arrays of 3-byte pointers
+ * continuously in memory (without 0-padding at the lines' end).
+ * This is rather 12 than 6 in order not to split up 4-byte data types
+ * in arrays right in the middle of a 4-byte word. */
+#define DB_ITEMS_PER_LINE      12
 
 typedef struct DBdata
   {
     int count;
-    char buffer[256];
+    char buffer[512];
   } DBdata;
 
 struct DBdata DBd;
@@ -4470,7 +4478,7 @@ void pic16_emitDS(char *s, char ptype, void *p)
 //     fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
 
        DBd.count++;    //=strlen(s);
-       if (DBd.count>=16)
+       if (DBd.count>=DB_ITEMS_PER_LINE)
                pic16_flushDB(ptype, p);
 }
 
@@ -4480,12 +4488,27 @@ void pic16_emitDS(char *s, char ptype, void *p)
 void pic16_pCodeConstString(char *name, char *value)
 {
   pBlock *pb;
-
-  //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
+  char *item;
+  static set *emittedSymbols = NULL;
 
   if(!name || !value)
     return;
 
+  /* keep track of emitted symbols to avoid multiple definition of str_<nr> */
+  if (emittedSymbols) {
+    /* scan set for name */
+    for (item = setFirstItem (emittedSymbols); item; item = setNextItem (emittedSymbols))
+    {
+      if (!strcmp (item,name)) {
+        //fprintf (stderr, "%s already emitted\n", name);
+        return;
+      } // if
+    } // for
+  } // if
+  addSet (&emittedSymbols, Safe_strdup (name));
+
+  //fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
+
   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
 
   pic16_addpBlock(pb);
@@ -5037,7 +5060,14 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc)
 //              fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
 //                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
 
-          if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
+          if(PCI(pc)->isAccess) {
+           static char *bank_spec[2][2] = {
+             { "", ", ACCESS" },  /* gpasm uses access bank by default */
+             { ", B", ", BANKED" }/* MPASM (should) use BANKED by default */
+           };
+            
+           SAFE_snprintf(&s,&size,"%s", bank_spec[(r && !r->accessBank) ? 1 : 0][pic16_mplab_comp ? 1 : 0]);
+         }
         }
 //      
 
@@ -5904,7 +5934,7 @@ static void AnalyzepBlock(pBlock *pb)
       }
       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
        if(PCOR(PCI(pc)->pcop)->r) {
-         pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
+         pic16_allocWithIdx(PCOR(PCI(pc)->pcop)->r->rIdx);                     /* FIXME! - VR */
          DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
        } else {
          if(PCI(pc)->pcop->name)
@@ -9387,6 +9417,9 @@ typedef unsigned int valnum_t;
 #define PTR_TO_INT(x) (((char *)(x)) - ((char *) 0))
 #endif
 
+static int pic16_regIsLocal (regs *r);
+static int pic16_safepCodeRemove (pCode *pc, char *comment);
+
 /* statistics */
 static unsigned int pic16_df_removed_pcodes = 0;
 static unsigned int pic16_df_saved_bytes = 0;
@@ -9417,12 +9450,53 @@ static int pic16_safepCodeUnlink (pCode *pc, char *comment) {
   pcprev = pic16_findPrevInstruction (pc->prev);
   pcnext = pic16_findNextInstruction (pc->next);
   
-  /* if previous instruction is a skip -- do not remove */
-  if (pcprev && isPCI_SKIP(pcprev)) return 0;
-
   /* move labels to next instruction (if possible) */
   if (PCI(pc)->label && !pcnext) return 0;
 
+  /* if this is a SKIP with side-effects -- do not remove */
+  /* XXX: might try to replace this one with the side-effect only version */
+  if (isPCI_SKIP(pc)
+       && ((PCI(pc)->outCond & (PCC_REGISTER | PCC_W)) != 0))
+  {
+    pCode *newpc;
+    switch (PCI(pc)->op)
+    {
+    case POC_INCFSZ:
+    case POC_INFSNZ:
+      newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
+      pic16_pCodeReplace( pc, newpc );
+      return 1;
+      break;
+    case POC_INCFSZW:
+      newpc = pic16_newpCode(POC_INCFW, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
+      pic16_pCodeReplace( pc, newpc );
+      return 1;
+      break;
+    case POC_DECFSZ:
+    case POC_DCFSNZ:
+      newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
+      pic16_pCodeReplace( pc, newpc );
+      return 1;
+      break;
+    case POC_DECFSZW:
+      newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
+      pic16_pCodeReplace( pc, newpc );
+      return 1;
+      break;
+    default:
+      return 0;
+    }
+    return 0;
+  }
+
+  /* if previous instruction is a skip -- do not remove */
+  if (pcprev && isPCI_SKIP(pcprev)) {
+    if (!pic16_safepCodeUnlink (pcprev, "=DF= removed now unused SKIP")) {
+      /* preceeding SKIP could not be removed -- keep this instruction! */
+      return 0;
+    }
+  }
+
   if (PCI(pc)->label) {
     //fprintf (stderr, "%s: moving label(s)\n", __FUNCTION__);
     //pc->print (stderr, pc);
@@ -9603,7 +9677,7 @@ static symbol_t symFromStr (const char *str) {
   /* find symbol in table */
   sym = PTR_TO_INT(hTabFindByKey (map_strToSym, hash, str, &symcmp));
   if (sym) {
-    //fprintf (stderr, "found symbol %u for %s\n", sym, str);
+    //fprintf (stderr, "found symbol %x for %s\n", sym, str);
     return sym;
   }
 
@@ -9614,7 +9688,7 @@ static symbol_t symFromStr (const char *str) {
   hTabAddItemLong (&map_strToSym, hash, res, INT_TO_PTR(sym));
   hTabAddItemLong (&map_symToStr, sym % map_symToStr->size, INT_TO_PTR(sym), res);
 
-  //fprintf (stderr, "created symbol %u for %s\n", sym, res);
+  //fprintf (stderr, "created symbol %x for %s\n", sym, res);
   
   return sym;
 }
@@ -10314,6 +10388,7 @@ static valnum_t valnumFromStr (const char *str) {
   /* create new valnum */
   val = newValnum();
   hTabAddItemLong (&map_symToValnum, sym % map_symToValnum->size, INT_TO_PTR(sym), INT_TO_PTR(val));
+  //fprintf (stderr, "NEW VALNUM %x for symbol %s\n", val, str);
   return val;
 }
 
@@ -10549,6 +10624,8 @@ static int pic16_symIsSpecial (symbol_t sym) {
 static int pic16_regIsLocal (regs *r) {
   symbol_t sym;
   if (r) {
+    if (r->type == REG_TMP) return 1;
+
     sym = symFromStr (r->name);
     switch (sym) {
     case SPO_WREG:
@@ -10661,7 +10738,12 @@ static int pic16_pCodeIsAlive (pCode *pc) {
   while (map && map->pc != pc) map = map->next;
 
   /* no entries found? something is fishy with DF analysis... -- play safe */
-  if (!map) { fprintf (stderr, "%s: defmap not found\n", __FUNCTION__); return 1; }
+  if (!map) {
+    if (pic16_pcode_verbose) {
+      fprintf (stderr, "%s: defmap not found\n", __FUNCTION__);
+    }
+    return 1;
+  }
 
   /* remember first item assigned to pc for later use */
   lastpc = map;
@@ -10883,8 +10965,8 @@ static defmap_t *createDefmap (pCode *pc, defmap_t *list) {
       valnum_t val;
       lit = PCOL(pci->pcop)->lit;
       assert (lit >= 0 && lit < 3);
-      //fprintf (stderr, "LFSR: %s // %s\n", pci->pcop->name, ((pCodeOpLit2 *)(pci->pcop))->arg2->name);
-      val = valnumFromStr (((pCodeOpLit2 *)(pci->pcop))->arg2->name);
+      //fprintf (stderr, "LFSR: %s // %s\n", pci->pcop->name, pic16_get_op(((pCodeOpLit2 *)(pci->pcop))->arg2, NULL, 0));
+      val = valnumFromStr (pic16_get_op(((pCodeOpLit2 *)(pci->pcop))->arg2, NULL, 0));
       //fprintf (stderr, "LFSR lit=%u, symval=%4x\n", lit, val);
       list = newDefmap (pic16_fsrsym_idx[lit][0], 0x00, 0xff, 0, 1, pc, val, list);
       list = newDefmap (pic16_fsrsym_idx[lit][1], 0x00, 0xff, 0, 1, pc, val+1, list); // val+1 is guaranteed not be used as a valnum...
@@ -11546,7 +11628,7 @@ static void assignValnums (pCode *pc) {
       if (val) vallit = litFromValnum (val->in_val);
       if (vallit != -1) {
         /* xxxLW <literal>, WREG contains a known literal */
-       fprintf (stderr, "%s 0x%02x, WREG: 0x%x\n", pci->mnemonic, lit, vallit);
+       //fprintf (stderr, "%s 0x%02x, WREG: 0x%x\n", pci->mnemonic, lit, vallit);
        if (pci->op == POC_ANDLW) {
          lit &= vallit;
        } else if (pci->op == POC_IORLW) {
@@ -11577,7 +11659,7 @@ static void assignValnums (pCode *pc) {
       val = defmapCurr (list, pic16_fsrsym_idx[lit][0], pc);
       
       if (val && (val->in_val != 0) && (val->in_val == val->val)) {
-        fprintf (stderr, "FSR%dL already set up correctly at %p (%x)\n", lit, pc, val->val);
+        //fprintf (stderr, "FSR%dL already set up correctly at %p (%x)\n", lit, pc, val->val);
       } else {
        /* cannot remove this LFSR */
        ok = 0;      
@@ -11585,7 +11667,7 @@ static void assignValnums (pCode *pc) {
       
       val = defmapCurr (list, pic16_fsrsym_idx[lit][1], pc);
       if (val && (val->in_val != 0) && (val->in_val == val->val)) {
-        fprintf (stderr, "FSR%dH already set up correctly at %p (%x)\n", lit, pc, val->val);
+        //fprintf (stderr, "FSR%dH already set up correctly at %p (%x)\n", lit, pc, val->val);
       } else {
        ok = 0;
       } // if
@@ -11912,166 +11994,6 @@ static void pic16_createDF (pBlock *pb) {
 #endif
 }
 
-
-/* ======================================================================= */
-/* === DEPRECATED CONTROL FLOW CREATION ROUTINES ========================= */
-/* ======================================================================= */
-
-#if 0
-
-/* connect pCode f anf t via their to/from pBranches */
-static void pic16_pCodeLink (pCode *f, pCode *t) {
-  pBranch *br;
-  pCodeInstruction *_f, *_t;
-
-  if (!f || !t) return;
-
-#if 0
-  fprintf (stderr, "linking:\n");
-  f->print(stderr, f);
-  f->print(stderr, t);
-#endif
-
-  assert (isPCI(f) || isPCAD(f));
-  assert (isPCI(t) || isPCAD(t));
-  _f = PCI(f);
-  _t = PCI(t);
-  
-  /* define t to be CF successor of f */
-  br = Safe_malloc (sizeof (pBranch));
-  br->pc = t;
-  br->next = NULL;
-  _f->to = pic16_pBranchAppend (_f->to, br);
-
-  /* define f to be CF predecessor of t */
-  br = Safe_malloc (sizeof (pBranch));
-  br->pc = f;
-  br->next = NULL;
-  _t->from = pic16_pBranchAppend (_t->from, br);
-
-  /* also update pcflow information */
-  if (_f->pcflow && _t->pcflow && _f->pcflow != _t->pcflow) {
-    //fprintf (stderr, "creating flow %p --> %p\n", _f->pcflow, _t->pcflow);
-    LinkFlow_pCode (_f, _t);
-  } // if
-}
-
-static void pic16_destructCF (pBlock *pb) {
-  pCode *pc;
-  pBranch *br;
-
-  /* remove old CF information */
-  pc = pb->pcHead;
-  while (pc) {
-    if (isPCI(pc)) {
-      while (PCI(pc)->to) {
-        br = PCI(pc)->to->next;
-        Safe_free (PCI(pc)->to);
-        PCI(pc)->to = br;
-      } // while
-      while (PCI(pc)->from) {
-        br = PCI(pc)->from->next;
-        Safe_free (PCI(pc)->from);
-        PCI(pc)->from = br;
-      }
-    } else if (isPCFL(pc)) {
-      deleteSet (&PCFL(pc)->to);
-      deleteSet (&PCFL(pc)->from);
-    }
-    pc = pc->next;
-  }
-  
-  releaseStack ();
-}
-
-/* Set up pCodeInstruction's to and from pBranches. */
-static void pic16_createCF (pBlock *pb) {
-  pCode *pc;
-  pCode *next, *dest;
-  char *label;
-
-  //fprintf (stderr, "creating CF for %p\n", pb);
-
-  pic16_destructCF (pb);
-
-  /* check pBlock: do not analyze pBlocks with ASMDIRs (for now...) */
-  if (pic16_pBlockHasAsmdirs (pb)) {
-    //fprintf (stderr, "%s: pBlock contains ASMDIRs -- data flow analysis not performed!\n", __FUNCTION__);
-    return;
-  }
-
-  pc = pic16_findNextInstruction(pb->pcHead);
-  while (pc) {
-    next = pic16_findNextInstruction(pc->next);
-    if (isPCI_SKIP(pc)) {
-      pic16_pCodeLink(pc, next);
-      pic16_pCodeLink(pc, pic16_findNextInstruction(next->next));
-    } else if (isPCI_BRANCH(pc)) {
-      // Bcc, BRA, CALL, GOTO
-      if (PCI(pc)->pcop) {
-        switch (PCI(pc)->pcop->type) {
-        case PO_LABEL:
-         label = PCOLAB(PCI(pc)->pcop)->pcop.name;
-         dest = findLabelinpBlock (pc->pb, PCOLAB(PCI(pc)->pcop));
-          break;
-       
-        case PO_STR:
-         /* needed for GOTO ___irq_handler */
-         label = PCI(pc)->pcop->name;
-         dest = NULL;
-         break;
-
-        default:
-         assert (0 && "invalid label format");
-         break;
-        } // switch
-      } else {
-       label = "NO PCOP";
-        dest = NULL;
-      }
-
-      switch (PCI(pc)->op) {
-      case POC_BRA:
-      case POC_GOTO:
-        if (dest != NULL) { 
-          pic16_pCodeLink(pc, dest);
-       } else {
-          //fprintf (stderr, "jump target \"%s\" not found!\n", label);
-       }
-       break;
-      case POC_CALL:
-      case POC_RETURN:
-      case POC_RETFIE:
-        pic16_pCodeLink(pc, next);
-       break;
-      case POC_BC:
-      case POC_BNC:
-      case POC_BZ:
-      case POC_BNZ:
-      case POC_BN:
-      case POC_BNN:
-      case POC_BOV:
-      case POC_BNOV:
-        if (dest != NULL) { 
-          pic16_pCodeLink(pc, dest);
-       } else {
-          //fprintf (stderr, "jump target \"%s\"not found!\n", label);
-       }
-        pic16_pCodeLink(pc, next);
-        break;
-      default:
-       fprintf (stderr, "BRANCH instruction: %s\n", PCI(pc)->mnemonic);
-       assert (0 && "unhandled branch instruction");
-       break;
-      } // switch
-    } else {
-      pic16_pCodeLink (pc, next);
-    }
-    pc = next;
-  } // while
-}
-#endif
-
 /* ======================================================================== */
 /* === VCG DUMPER ROUTINES ================================================ */
 /* ======================================================================== */