* as/z80/z80mch.c: fixed bug #1704376: missing as-z80 errors
[fw/sdcc] / src / pic16 / pcode.c
index 3fbfe25ba81bf1e3cab54d445f7213d5ded119c6..1754eeee407c4f154346b9f3ff3c0bf2b222b319 100644 (file)
@@ -156,8 +156,6 @@ extern void pic16_RemoveUnusedRegisters(void);
 extern void pic16_RegsUnMapLiveRanges(void);
 extern void pic16_BuildFlowTree(pBlock *pb);
 extern void pic16_pCodeRegOptimizeRegUsage(int level);
-extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
-extern int mnem2key(unsigned char const *mnem);
 
 /****************************************************************/
 /*                      Forward declarations                    */
@@ -2882,76 +2880,6 @@ pCodeInstruction pic16_pciBANKSEL = {
 #define MAX_PIC16MNEMONICS 100
 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
 
-//#define USE_VSNPRINTF
-#if OPT_DISABLE_PIC
-
-#ifdef USE_VSNPRINTF
-  // Alas, vsnprintf is not ANSI standard, and does not exist
-  // on Solaris (and probably other non-Gnu flavored Unixes).
-
-/*-----------------------------------------------------------------*/
-/* SAFE_snprintf - like snprintf except the string pointer is      */
-/*                 after the string has been printed to. This is   */
-/*                 useful for printing to string as though if it   */
-/*                 were a stream.                                  */
-/*-----------------------------------------------------------------*/
-void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
-{
-  va_list val;
-  int len;
-
-  if(!str || !*str)
-    return;
-
-  va_start(val, format);
-
-  vsnprintf(*str, *size, format, val);
-
-  va_end (val);
-
-  len = strlen(*str);
-  if(len > *size) {
-    fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
-    fprintf(stderr,"len = %d is > str size %d\n",len,*size);
-  }
-
-  *str += len;
-  *size -= len;
-
-}
-
-#else
-// This version is *not* safe, despite the name.
-
-void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
-{
-  va_list val;
-  int len;
-  static char buffer[1024]; /* grossly conservative, but still not inherently safe */
-
-  if(!str || !*str)
-    return;
-
-  va_start(val, format);
-
-  vsprintf(buffer, format, val);
-  va_end (val);
-
-  len = strlen(buffer);
-  if(len > *size) {
-    fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
-    fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
-  }
-
-  strcpy(*str, buffer);
-  *str += len;
-  *size -= len;
-
-}
-
-#endif    //  USE_VSNPRINTF
-#endif
-
 extern set *externs;
 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
@@ -3097,14 +3025,13 @@ void  pic16_pCodeInitRegisters(void)
 
 }
 
-#if OPT_DISABLE_PIC
 /*-----------------------------------------------------------------*/
 /*  mnem2key - convert a pic mnemonic into a hash key              */
 /*   (BTW - this spreads the mnemonics quite well)                 */
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-int mnem2key(unsigned char const *mnem)
+static int mnem2key(unsigned char const *mnem)
 {
   int key = 0;
 
@@ -3120,7 +3047,6 @@ int mnem2key(unsigned char const *mnem)
   return (key & 0x1f);
 
 }
-#endif
 
 void pic16initMnemonics(void)
 {
@@ -3878,6 +3804,8 @@ static void pCodeLabelDestruct(pCode *pc)
   if(!pc)
     return;
 
+  pic16_unlinkpCode(pc);
+
 //  if((pc->type == PC_LABEL) && PCL(pc)->label)
 //    Safe_free(PCL(pc)->label);
 
@@ -4735,10 +4663,16 @@ void pic16_unlinkpCode(pCode *pc)
     fprintf(stderr,"Unlinking: ");
     printpCode(stderr, pc);
 #endif
-    if(pc->prev)
+    if(pc->prev) {
       pc->prev->next = pc->next;
-    if(pc->next)
+    } else if (pc->pb && (pc->pb->pcHead == pc)) {
+        pc->pb->pcHead = pc->next;
+    }
+    if(pc->next) {
       pc->next->prev = pc->prev;
+    } else if (pc->pb && (pc->pb->pcTail == pc)) {
+        pc->pb->pcTail = pc->prev;
+    }
 
     /* move C source line down (or up) */
     if (isPCI(pc) && PCI(pc)->cline) {
@@ -4798,108 +4732,114 @@ const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
 
 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
 {
-  regs *r;
-  static char b[128];
-  char *s;
-  int use_buffer = 1;    // copy the string to the passed buffer pointer
-
-        if(!buffer) {
-                buffer = b;
-                size = sizeof(b);
-                use_buffer = 0;     // Don't bother copying the string to the buffer.
-        }
+    regs *r;
+    static char b[128];
+    char *s;
+    int use_buffer = 1;    // copy the string to the passed buffer pointer
 
-        if(pcop) {
-
-                switch(pcop->type) {
-                        case PO_W:
-                        case PO_WREG:
-                        case PO_PRODL:
-                        case PO_PRODH:
-                        case PO_INDF0:
-                        case PO_FSR0:
-                                if(use_buffer) {
-                                        SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
-                                        return (buffer);
-                                }
-                                return (PCOR(pcop)->r->name);
-                                break;
-                        case PO_GPR_TEMP:
-                                r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
-                                if(use_buffer) {
-                                        SAFE_snprintf(&buffer,&size,"%s",r->name);
-                                        return (buffer);
-                                }
-                                return (r->name);
-
-                        case PO_IMMEDIATE:
-                                s = buffer;
-                                if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
-                                        if(PCOI(pcop)->index) {
-                                                SAFE_snprintf(&s,&size, "%s(%s + %d)",
-                                                        immdmod[ PCOI(pcop)->offset ],
-                                                        pcop->name,
-                                                        PCOI(pcop)->index);
-                                        } else {
-                                                SAFE_snprintf(&s,&size,"%s(%s)",
-                                                        immdmod[ PCOI(pcop)->offset ],
-                                                        pcop->name);
-                                        }
-                                } else {
-                                        if(PCOI(pcop)->index) {
-                                                SAFE_snprintf(&s,&size, "%s(%s + %d)",
-                                                        immdmod[ 0 ],
-                                                        pcop->name,
-                                                        PCOI(pcop)->index);
-                                        } else {
-                                                SAFE_snprintf(&s,&size, "%s(%s)",
-                                                        immdmod[ 0 ],
-                                                        pcop->name);
-                                        }
-                                }
-                                return (buffer);
-
-                        case PO_GPR_REGISTER:
-                        case PO_DIR:
-                                s = buffer;
-//                              size = sizeof(buffer);
-                                if( PCOR(pcop)->instance) {
-                                        SAFE_snprintf(&s,&size,"(%s + %d)",
-                                                pcop->name,
-                                                PCOR(pcop)->instance );
-                                } else {
-                                        SAFE_snprintf(&s,&size,"%s",pcop->name);
-                                }
-                                return (buffer);
-                        case PO_GPR_BIT:
-                                s = buffer;
-                                if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
-                                        SAFE_snprintf(&s, &size, "%s", pcop->name);
-                                } else {
-                                        if(PCORB(pcop)->pcor.instance)
-                                                SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
-                                        else
-                                                SAFE_snprintf(&s, &size, "%s", pcop->name);
-                                }
+    if(!buffer) {
+        buffer = b;
+        size = sizeof(b);
+        use_buffer = 0;     // Don't bother copying the string to the buffer.
+    }
 
-                                return (buffer);
-                        case PO_TWO_OPS:
-                                return (pic16_get_op( PCOP2(pcop)->pcopL, use_buffer ? buffer : NULL, size ));
+    if(pcop) {
+
+        switch(pcop->type) {
+            case PO_W:
+            case PO_WREG:
+            case PO_PRODL:
+            case PO_PRODH:
+            case PO_INDF0:
+            case PO_FSR0:
+                if(use_buffer) {
+                    SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
+                    return (buffer);
+                }
+                return (PCOR(pcop)->r->name);
+                break;
+            case PO_GPR_TEMP:
+                r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
+                if(use_buffer) {
+                    SNPRINTF(buffer,size,"%s",r->name);
+                    return (buffer);
+                }
+                return (r->name);
+                break;
 
-                        default:
-                                if(pcop->name) {
-                                        if(use_buffer) {
-                                                SAFE_snprintf(&buffer,&size,"%s",pcop->name);
-                                                return (buffer);
-                                        }
-                                return (pcop->name);
-                                }
+            case PO_IMMEDIATE:
+                s = buffer;
+                if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
+                    if(PCOI(pcop)->index) {
+                        SNPRINTF(s,size, "%s(%s + %d)",
+                                immdmod[ PCOI(pcop)->offset ],
+                                pcop->name,
+                                PCOI(pcop)->index);
+                    } else {
+                        SNPRINTF(s,size,"%s(%s)",
+                                immdmod[ PCOI(pcop)->offset ],
+                                pcop->name);
+                    }
+                } else {
+                    if(PCOI(pcop)->index) {
+                        SNPRINTF(s,size, "%s(%s + %d)",
+                                immdmod[ 0 ],
+                                pcop->name,
+                                PCOI(pcop)->index);
+                    } else {
+                        SNPRINTF(s,size, "%s(%s)",
+                                immdmod[ 0 ],
+                                pcop->name);
+                    }
+                }
+                return (buffer);
+                break;
 
+            case PO_GPR_REGISTER:
+            case PO_DIR:
+                s = buffer;
+                //size = sizeof(buffer);
+                if( PCOR(pcop)->instance) {
+                    SNPRINTF(s,size,"(%s + %d)",
+                            pcop->name,
+                            PCOR(pcop)->instance );
+                } else {
+                    SNPRINTF(s,size,"%s",pcop->name);
                 }
-                return ("unhandled type for op1");
+                return (buffer);
+                break;
+
+            case PO_GPR_BIT:
+                s = buffer;
+                if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
+                    SNPRINTF(s, size, "%s", pcop->name);
+                } else {
+                    if(PCORB(pcop)->pcor.instance)
+                        SNPRINTF(s, size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
+                    else
+                        SNPRINTF(s, size, "%s", pcop->name);
+                }
+                return (buffer);
+                break;
+
+            case PO_TWO_OPS:
+                return (pic16_get_op( PCOP2(pcop)->pcopL, use_buffer ? buffer : NULL, size ));
+                break;
+
+            default:
+                if(pcop->name) {
+                    if(use_buffer) {
+                        SNPRINTF(buffer,size,"%s",pcop->name);
+                        return (buffer);
+                    }
+                    return (pcop->name);
+                }
+
         }
+        return ("unhandled type for op1");
+    }
 
-  return ("NO operand1");
+    return ("NO operand1");
 }
 
 /*-----------------------------------------------------------------*/
@@ -4943,147 +4883,147 @@ static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
 /*-----------------------------------------------------------------*/
 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
 {
-  char *s = str;
-  regs *r;
+    char *s = str;
+    regs *r;
 
 #if 0
-        if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
-                fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
-                        __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
-//              exit(EXIT_FAILURE);
-        }
+    if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
+        fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
+                __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
+        //              exit(EXIT_FAILURE);
+    }
 #endif
 
-  switch(pc->type) {
-
-  case PC_OPCODE:
-    SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
+    switch(pc->type) {
 
-    if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
+        case PC_OPCODE:
+            SNPRINTF(s, size, "\t%s\t", PCI(pc)->mnemonic);
+            size -= strlen(s);
+            s += strlen(s);
 
-        //if(PCI(pc)->is2MemOp)
-        if (PCI(pc)->pcop->type == PO_TWO_OPS)
-        {
-                /* split into two phases due to static buffer in pic16_get_op() */
-                SAFE_snprintf(&s,&size, "%s",
-                        pic16_get_op((PCI(pc)->pcop), NULL, 0));
-                SAFE_snprintf(&s, &size, ", %s",
-                        pic16_get_op2((PCI(pc)->pcop), NULL, 0));
-                break;
-        }
+            if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
 
-        if(PCI(pc)->is2LitOp) {
-                SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
-                break;
-        }
-
-      if(PCI(pc)->isBitInst) {
-        if(PCI(pc)->pcop->type != PO_GPR_BIT) {
-          if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
-            SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
-                          PCI(pc)->pcop->name ,
-                          PCI(pc)->pcop->name );
-          else
-            SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
-//                        (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
-                          (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
+                if (PCI(pc)->pcop->type == PO_TWO_OPS)
+                {
+                    /* split into two phases due to static buffer in pic16_get_op() */
+                    SNPRINTF(s, size, "%s",
+                            pic16_get_op((PCI(pc)->pcop), NULL, 0));
+                    size -= strlen(s);
+                    s += strlen(s);
+                    SNPRINTF(s, size, ", %s",
+                            pic16_get_op2((PCI(pc)->pcop), NULL, 0));
+                    break;
+                }
 
-        } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
-          SAFE_snprintf(&s,&size,"%s, %d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
-        } else
-          SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
-        //PCI(pc)->pcop->t.bit );
-      } else {
+                if(PCI(pc)->is2LitOp) {
+                    SNPRINTF(s,size, "%s", PCOP(PCI(pc)->pcop)->name);
+                    break;
+                }
 
-        if(PCI(pc)->pcop->type == PO_GPR_BIT) {
-          if( PCI(pc)->num_ops == 3)
-            SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
-          else
-            SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
+                if(PCI(pc)->isBitInst) {
+                    if(PCI(pc)->pcop->type != PO_GPR_BIT) {
+                        if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
+                            SNPRINTF(s,size,"(%s >> 3), (%s & 7)",
+                                    PCI(pc)->pcop->name ,
+                                    PCI(pc)->pcop->name );
+                        else
+                            SNPRINTF(s,size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
+                                    (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
+
+                    } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+                        SNPRINTF(s,size,"%s, %d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
+                    } else
+                        SNPRINTF(s,size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
+                } else {
 
-        }
-        else
-        {
-          SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
-        }
-      }
-        if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
-          if(PCI(pc)->num_ops == 3 && !PCI(pc)->isBitInst)
-            SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
+                    if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+                        if( PCI(pc)->num_ops == 3)
+                            SNPRINTF(s,size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
+                        else
+                            SNPRINTF(s,size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
+                    } else {
+                        SNPRINTF(s,size,"%s", pic16_get_op_from_instruction(PCI(pc)));
+                    }
+                }
 
-          r = pic16_getRegFromInstruction(pc);
-//              fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
-//                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?isACCESS_BANK(r):-1);
+                if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
+                    size -= strlen(s);
+                    s += strlen(s);
+                    if(PCI(pc)->num_ops == 3 && !PCI(pc)->isBitInst) {
+                        SNPRINTF(s,size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
+                        size -= strlen(s);
+                        s += strlen(s);
+                    }
 
-          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 */
-            };
+                    r = pic16_getRegFromInstruction(pc);
 
-            SAFE_snprintf(&s,&size,"%s", bank_spec[(r && !isACCESS_BANK(r)) ? 1 : 0][pic16_mplab_comp ? 1 : 0]);
-          }
-        }
-//
+                    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 */
+                        };
 
-    }
-    break;
-
-  case PC_COMMENT:
-    /* assuming that comment ends with a \n */
-    SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
-    break;
-
-  case PC_INFO:
-    SAFE_snprintf(&s,&size,"; info ==>");
-    switch( PCINF(pc)->type ) {
-      case INF_OPTIMIZATION:
-          SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
-          break;
-      case INF_LOCALREGS:
-          SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
-          break;
-    }; break;
+                        SNPRINTF(s,size,"%s", bank_spec[(r && !isACCESS_BANK(r)) ? 1 : 0][pic16_mplab_comp ? 1 : 0]);
+                    }
+                }
+            }
+            break;
 
-  case PC_INLINE:
-    /* assuming that inline code ends with a \n */
-    SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
-    break;
+        case PC_COMMENT:
+            /* assuming that comment ends with a \n */
+            SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
+            break;
 
-  case PC_LABEL:
-    SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
-    break;
-  case PC_FUNCTION:
-    SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
-    break;
-  case PC_WILD:
-    SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
-    break;
-  case PC_FLOW:
-    SAFE_snprintf(&s,&size,";\t--FLOW change\n");
-    break;
-  case PC_CSOURCE:
-//    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
-      SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
-        PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
-    break;
-  case PC_ASMDIR:
-        if(PCAD(pc)->directive) {
-                SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
-        } else
-        if(PCAD(pc)->arg) {
-                /* special case to handle inline labels without a tab */
-                SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
-        }
-        break;
+        case PC_INFO:
+            SNPRINTF(s,size,"; info ==>");
+            size -= strlen(s);
+            s += strlen(s);
+            switch( PCINF(pc)->type ) {
+                case INF_OPTIMIZATION:
+                    SNPRINTF(s,size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
+                    break;
+                case INF_LOCALREGS:
+                    SNPRINTF(s,size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
+                    break;
+            }; break;
+
+        case PC_INLINE:
+            /* assuming that inline code ends with a \n */
+            SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
+            break;
 
-  case PC_BAD:
-    SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
-    break;
-  }
+        case PC_LABEL:
+            SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
+            break;
+        case PC_FUNCTION:
+            SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
+            break;
+        case PC_WILD:
+            SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
+            break;
+        case PC_FLOW:
+            SNPRINTF(s,size,";\t--FLOW change\n");
+            break;
+        case PC_CSOURCE:
+            SNPRINTF(s,size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
+                    PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
+            break;
+        case PC_ASMDIR:
+            if(PCAD(pc)->directive) {
+                SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
+            } else
+                if(PCAD(pc)->arg) {
+                    /* special case to handle inline labels without a tab */
+                    SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
+                }
+            break;
 
-  return str;
+        case PC_BAD:
+            SNPRINTF(s,size,";A bad pCode is being used\n");
+            break;
+    }
 
+    return str;
 }
 
 /*-----------------------------------------------------------------*/
@@ -5400,31 +5340,10 @@ void pic16_pCodeUnlink(pCode *pc)
   pBranch *pb1,*pb2;
   pCode *pc1;
 
-  if(!pc->prev || !pc->next) {
-    fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
-    exit(1);
-  }
-
-  /* move C source line down (or up) */
-  if (isPCI(pc) && PCI(pc)->cline) {
-    pc1 = pic16_findNextInstruction (pc->next);
-    if (pc1 && isPCI(pc1) && !PCI(pc1)->cline) {
-      PCI(pc1)->cline = PCI(pc)->cline;
-    } else {
-      pc1 = pic16_findPrevInstruction (pc->prev);
-      if (pc1 && isPCI(pc1) && !PCI(pc1)->cline)
-        PCI(pc1)->cline = PCI(pc)->cline;
-    }
+  if (!pc) {
+    return;
   }
 
-  /* first remove the pCode from the chain */
-  pc->prev->next = pc->next;
-  pc->next->prev = pc->prev;
-
-  pc->prev = pc->next = NULL;
-
-  /* Now for the hard part... */
-
   /* Remove the branches */
 
   pb1 = PCI(pc)->from;
@@ -5447,6 +5366,7 @@ void pic16_pCodeUnlink(pCode *pc)
     pb1 = pb1->next;
   }
 
+  pic16_unlinkpCode (pc);
 
 }
 #endif
@@ -6504,6 +6424,7 @@ static void insertBankSwitch(unsigned char position, pCode *pc)
 }
 
 
+#if 0
 /*-----------------------------------------------------------------*/
 /*int compareBankFlow - compare the banking requirements between   */
 /*  flow objects. */
@@ -6554,6 +6475,7 @@ static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toO
   return 1;
 
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*/
@@ -7826,7 +7748,9 @@ void pic16_AnalyzeBanking(void)
 /*-----------------------------------------------------------------*/
 /* buildCallTree - Look at the flow and extract all of the calls.  */
 /*-----------------------------------------------------------------*/
+#if 0
 static set *register_usage(pBlock *pb);
+#endif
 
 static void buildCallTree(void    )
 {
@@ -8211,6 +8135,7 @@ static pCode *findFunction(char *fname)
   return NULL;
 }
 
+#if 0
 static void MarkUsedRegisters(set *regset)
 {
 
@@ -8224,6 +8149,7 @@ static void MarkUsedRegisters(set *regset)
     r2->wasUsed = 1;
   }
 }
+#endif
 
 static void pBlockStats(FILE *of, pBlock *pb)
 {
@@ -8294,6 +8220,7 @@ static void sequencepCode(void)
 }
 #endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 static set *register_usage(pBlock *pb)
@@ -8403,6 +8330,7 @@ static set *register_usage(pBlock *pb)
 
   return registers;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* pct2 - writes the call tree to a file                           */
@@ -9039,7 +8967,7 @@ unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
 /* bank so that we can make sure the bytes are laid out sequentially in memory)       */
 /* TODO: Symbols with an abslute address must be handled specially!                   */
 /*------------------------------------------------------------------------------------*/
-int assignToSameBank (int bank0, int bank1, int doAbs)
+int assignToSameBank (int bank0, int bank1, int doAbs, int force)
 {
   int eff0, eff1, dummy;
   pseudoBank *pbank0, *pbank1;
@@ -9091,7 +9019,7 @@ int assignToSameBank (int bank0, int bank1, int doAbs)
 #endif
 
   if (pbank1) {
-    if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
+    if (!force && (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE)) {
 #if 0
       fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
                pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
@@ -9234,7 +9162,7 @@ void pic16_OptimizeBanksel ()
     bankNr = reg->address >> 8;
     node = getOrAddGNode (adj, NULL, bankNr);
     bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
-    assignToSameBank (node->hash, bankNr, 1);
+    assignToSameBank (node->hash, bankNr, 1, 1);
 
     assert (bankNr >= 0);
     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
@@ -9247,6 +9175,7 @@ void pic16_OptimizeBanksel ()
     } else {
       assert (pbank->bank == (reg->address >> 8));
       pbank->bank = reg->address >> 8; //FIXED_BANK;
+      pbank->size++;
     }
     //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
   } // for reg
@@ -9265,10 +9194,11 @@ void pic16_OptimizeBanksel ()
       node1next = node1->next;
       base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
       if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
+        int res;
         // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
         //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
-        if (assignToSameBank (node->hash, node1->hash, 0)) {
-          fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
+        if (0 != (res = assignToSameBank (node->hash, node1->hash, 0, 1))) {
+          fprintf (stderr, "%s(%d) == %s(%d), res=%d\n", base_symbol0, len0, base_symbol1, len1, res);
           assert (0 && "Could not assign a symbol to a bank!");
         }
         mergeGraphNodes (node, node1);
@@ -9327,7 +9257,7 @@ void pic16_OptimizeBanksel ()
       node = getGNode (adj, max->src->data, max->src->hash);
       node1 = getGNode (adj, max->node->data, max->node->hash);
 
-      if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
+      if (0 == assignToSameBank (max->src->hash, max->node->hash, 0, 0)) {
         if (max->src->hash < max->node->hash)
           mergeGraphNodes (node, node1);
         else
@@ -11309,6 +11239,10 @@ static void createReachingDefinitions (pBlock *pb) {
   } // for
 
   pc = pic16_findNextInstruction (pb->pcHead);
+  if (!pc) {
+      // empty function, avoid NULL pointer dereference
+      return;
+  } // if
   todo = NULL; blacklist = NULL;
   addSetHead (&todo, PCI(pc)->pcflow);