* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / pic16 / pcode.c
index 34ecf9517fbdb537842330b0b06f14a246ffd475..9cb878feae768e03fe634fe363563249122bfa45 100644 (file)
 extern char *pic16_aopGet (struct asmop *aop, int offset, bool bit16, bool dname);
 
 #if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
 #define inline
-#else
-#define STRCASECMP strcasecmp
 #endif
 
 #define DUMP_DF_GRAPHS 0
@@ -3245,7 +3242,7 @@ void pic16initMnemonics(void)
 
   for(i=0; i<MAX_PIC16MNEMONICS; i++)
     if(pic16Mnemonics[i])
-      hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
+      hTabAddItem(&pic16MnemonicsHash, mnem2key((const unsigned char *)pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
   pci = hTabFirstItem(pic16MnemonicsHash, &key);
 
   while(pci) {
@@ -3262,7 +3259,7 @@ int pic16_getpCode(char *mnem,unsigned dest)
 {
 
   pCodeInstruction *pci;
-  int key = mnem2key(mnem);
+  int key = mnem2key((unsigned char *)mnem);
 
   if(!mnemonics_initialized)
     pic16initMnemonics();
@@ -3302,7 +3299,7 @@ void pic16initpCodePeepCommands(void)
   i = 0;
   do {
     hTabAddItem(&pic16pCodePeepCommandsHash, 
-               mnem2key(peepCommands[i].cmd), &peepCommands[i]);
+               mnem2key((const unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
     i++;
   } while (peepCommands[i].cmd);
 
@@ -3324,7 +3321,7 @@ int pic16_getpCodePeepCommand(char *cmd)
 {
 
   peepCommand *pcmd;
-  int key = mnem2key(cmd);
+  int key = mnem2key((unsigned char *)cmd);
 
 
   pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
@@ -3525,6 +3522,7 @@ static int RegCond(pCodeOp *pcop)
   return 0;
 }
 
+
 /*-----------------------------------------------------------------*/
 /* pic16_newpCode - create and return a newly initialized pCode          */
 /*                                                                 */
@@ -4069,6 +4067,30 @@ pCodeOp *pic16_newpCodeOpLit(int lit)
   return pcop;
 }
 
+/* Allow for 12 bit literals, required for LFSR */
+pCodeOp *pic16_newpCodeOpLit12(int lit)
+{
+  char *s = buffer;
+  pCodeOp *pcop;
+
+
+  pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
+  pcop->type = PO_LITERAL;
+
+  pcop->name = NULL;
+  //if(lit>=0)
+    sprintf(s,"0x%03x", ((unsigned int)lit) & 0x0fff);
+  //else
+  //  sprintf(s, "%i", lit);
+  
+  if(s)
+    pcop->name = Safe_strdup(s);
+
+  ((pCodeOpLit *)pcop)->lit = lit;
+
+  return pcop;
+}
+
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
@@ -4117,6 +4139,7 @@ pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
 //                     fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
        } else {
                pcop->name = NULL;
+               PCOI(pcop)->rIdx = -1;
        }
 
        PCOI(pcop)->index = index;
@@ -4244,26 +4267,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);
+       exit(EXIT_FAILURE);
     }
   }
 
+  PCOR(pcop)->rIdx = rIdx;
+  PCOR(pcop)->r = r;
   pcop->type = PCOR(pcop)->r->pc_type;
 
   return pcop;
@@ -4372,6 +4397,11 @@ pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
     else
       pcop = pic16_newpCodeOpReg(-1);
     break;
+    
+  case PO_TWO_OPS:
+    assert( !"Cannot create PO_TWO_OPS from string!" );
+    pcop = NULL;
+    break;
 
   default:
     pcop = Safe_calloc(1,sizeof(pCodeOp) );
@@ -4385,6 +4415,15 @@ pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
   return pcop;
 }
 
+pCodeOp *pic16_newpCodeOp2(pCodeOp *src, pCodeOp *dst)
+{
+  pCodeOp2 *pcop2 = Safe_calloc(1, sizeof(pCodeOp2));
+  pcop2->pcop.type = PO_TWO_OPS;
+  pcop2->pcopL = src;
+  pcop2->pcopR = dst;
+  return PCOP(pcop2);
+}
+
 /* 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
@@ -4438,7 +4477,7 @@ void pic16_flushDB(char ptype, void *p)
 /*-----------------------------------------------------------------*/
 /*    Add "DB" directives to a pBlock                              */
 /*-----------------------------------------------------------------*/
-void pic16_emitDB(char c, char ptype, void *p)
+void pic16_emitDB(int c, char ptype, void *p)
 {
   int l;
 
@@ -4777,6 +4816,7 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
        } 
 
        if(pcop) {
+
                switch(pcop->type) {
                        case PO_W:
                        case PO_WREG:
@@ -4786,17 +4826,17 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
                        case PO_FSR0:
                                if(use_buffer) {
                                        SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
-                                       return buffer;
+                                       return (buffer);
                                }
-                               return PCOR(pcop)->r->name;
+                               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 (buffer);
                                }
-                               return r->name;
+                               return (r->name);
 
                        case PO_IMMEDIATE:
                                s = buffer;
@@ -4823,7 +4863,7 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
                                                        pcop->name);
                                        }
                                }
-                               return buffer;
+                               return (buffer);
 
                        case PO_GPR_REGISTER:
                        case PO_DIR:
@@ -4836,7 +4876,7 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
                                } else {
                                        SAFE_snprintf(&s,&size,"%s",pcop->name);
                                }
-                               return buffer;
+                               return (buffer);
                        case PO_GPR_BIT:
                                s = buffer;
                                if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
@@ -4849,19 +4889,23 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
                                }
 
                                return (buffer);
+                       case PO_TWO_OPS:
+                               return (pic16_get_op( PCOP2(pcop)->pcopL, use_buffer ? buffer : NULL, size ));
+                               
                        default:
                                if(pcop->name) {
                                        if(use_buffer) {
                                                SAFE_snprintf(&buffer,&size,"%s",pcop->name);
-                                               return buffer;
+                                               return (buffer);
                                        }
-                               return pcop->name;
+                               return (pcop->name);
                                }
 
                }
+               return ("unhandled type for op1");
        }
 
-  return "NO operand1";
+  return ("NO operand1");
 }
 
 /*-----------------------------------------------------------------*/
@@ -4869,95 +4913,10 @@ char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
 /*-----------------------------------------------------------------*/
 char *pic16_get_op2(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.
-       } 
-
-#if 0
-       fprintf(stderr, "%s:%d second operand %s is %d\tPO_DIR(%d) PO_GPR_TEMP(%d) PO_IMMEDIATE(%d) PO_INDF0(%d) PO_FSR0(%d)\n",
-               __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
-               PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
-#endif
-
-       if(pcop) {
-               switch(PCOR2(pcop)->pcop2->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(PCOR2(pcop)->pcop2)->r->name);
-                                       return buffer;
-                               }
-                               return PCOR(PCOR2(pcop)->pcop2)->r->name;
-                               break;
-                       case PO_GPR_TEMP:
-                               r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
-
-                               if(use_buffer) {
-                                       SAFE_snprintf(&buffer,&size,"%s",r->name);
-                                       return buffer;
-                               }
-                               return r->name;
-
-                       case PO_IMMEDIATE:
-                                       assert( 0 );
-                               break;
-#if 0
-                               s = buffer;
-
-                               if(PCOI(pcop)->_const) {
-                                       if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
-                                               SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
-                                                       pcop->name,
-                                                       PCOI(pcop)->index,
-                                                       8 * PCOI(pcop)->offset );
-                                       } else
-                                               SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
-                               } else {
-                                       if( PCOI(pcop)->index) {
-                                               SAFE_snprintf(&s,&size,"(%s + %d)",
-                                                       pcop->name,
-                                                       PCOI(pcop)->index );
-                                       } else {
-                                               if(PCOI(pcop)->offset)
-                                                       SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
-                                               else
-                                                       SAFE_snprintf(&s,&size,"%s",pcop->name);
-                                       }
-                               }
-                               return buffer;
-#endif
-                       case PO_DIR:
-                               s = buffer;
-                               if( PCOR(PCOR2(pcop)->pcop2)->instance) {
-                                       SAFE_snprintf(&s,&size,"(%s + %d)",
-                                               PCOR(PCOR2(pcop)->pcop2)->r->name,
-                                               PCOR(PCOR2(pcop)->pcop2)->instance );
-                               } else {
-                                       SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
-                               }
-                               return buffer;
-
-                       default:
-                               if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
-                                       if(use_buffer) {
-                                               SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
-                                               return buffer;
-                                       }
-                                       return PCOR(PCOR2(pcop)->pcop2)->r->name;
-                               }
-               }
-       }
+  if(pcop && pcop->type == PO_TWO_OPS) {
+    return pic16_get_op( PCOP2(pcop)->pcopR, buffer, size );
+  }
 
   return "NO operand2";
 }
@@ -4997,7 +4956,7 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc)
        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(-1);
+//             exit(EXIT_FAILURE);
        }
 #endif
 
@@ -5008,10 +4967,14 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc)
 
     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
 
-       if(PCI(pc)->is2MemOp) {
-               SAFE_snprintf(&s,&size, "%s, %s", 
-               pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
-               pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
+       //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;
        }
 
@@ -5056,7 +5019,7 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc)
 
           r = pic16_getRegFromInstruction(pc);
 //              fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
-//                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
+//                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?isACCESS_BANK(r):-1);
 
           if(PCI(pc)->isAccess) {
            static char *bank_spec[2][2] = {
@@ -5064,7 +5027,7 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc)
              { ", 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]);
+           SAFE_snprintf(&s,&size,"%s", bank_spec[(r && !isACCESS_BANK(r)) ? 1 : 0][pic16_mplab_comp ? 1 : 0]);
          }
         }
 //      
@@ -5832,9 +5795,13 @@ regs * pic16_getRegFrompCodeOp (pCodeOp *pcop) {
     
   case PO_WILD:
     break;
+
+  case PO_TWO_OPS:
+    return pic16_getRegFrompCodeOp( PCOP2(pcop)->pcopL );
+    break;
     
   default:
-       fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d (%s)\n",pcop->type, dumpPicOptype (pcop->type));
+       fprintf(stderr, "pic16_getRegFrompCodeOp - unknown reg type %d (%s)\n",pcop->type, dumpPicOptype (pcop->type));
 //     assert( 0 );
        break;
   }
@@ -5846,7 +5813,6 @@ regs * pic16_getRegFrompCodeOp (pCodeOp *pcop) {
 /*-----------------------------------------------------------------*/
 regs * pic16_getRegFromInstruction(pCode *pc)
 {
-
   if(!pc                   || 
      !isPCI(pc)            ||
      !PCI(pc)->pcop        ||
@@ -5859,7 +5825,7 @@ regs * pic16_getRegFromInstruction(pCode *pc)
        dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
 #endif
 
-  return pic16_getRegFrompCodeOp (PCI(pc)->pcop);
+  return( pic16_getRegFrompCodeOp (PCI(pc)->pcop) );
 }
 
 /*-------------------------------------------------------------------------------*/
@@ -5875,13 +5841,15 @@ regs * pic16_getRegFromInstruction2(pCode *pc)
      (PCI(pc)->num_ops == 1))          // accept only 2 operand commands
     return NULL;
 
+  if (PCI(pc)->pcop->type != PO_TWO_OPS)
+    return NULL;
 
 #if 0
   fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
        dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
 #endif
 
-  return pic16_getRegFrompCodeOp (PCOR2(PCI(pc)->pcop)->pcop2);
+  return pic16_getRegFrompCodeOp (PCOP2(PCI(pc)->pcop)->pcopR);
 }
 
 /*-----------------------------------------------------------------*/
@@ -5932,7 +5900,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)
@@ -8730,12 +8698,14 @@ char *pic_optype_names[]={
        "PO_BIT",            // bit operand.
        "PO_STR",            //  (8051 legacy)
        "PO_LABEL",
-       "PO_WILD"            // Wild card operand in peep optimizer
+       "PO_WILD",           // Wild card operand in peep optimizer
+       "PO_TWO_OPS"         // combine two operands
 };
 
 
 char *dumpPicOptype(PIC_OPTYPE type)
 {
+       assert( type >= 0 && type < sizeof(pic_optype_names)/sizeof( char *) );
        return (pic_optype_names[ type ]);
 }
 
@@ -8799,7 +8769,7 @@ int comparePtr (const void *p1, const void *p2)
 /* getSymbolFromOperand - return a pointer to the symbol in */
 /*                        the given operand and its length  */
 /*----------------------------------------------------------*/
-char *getSymbolFromOperand (char *op, unsigned int *len)
+char *getSymbolFromOperand (char *op, int *len)
 {
   char *sym, *curr;
   *len = 0;
@@ -11742,9 +11712,9 @@ static void assignValnums (pCode *pc) {
     if (!isSpecial1 && pic16_regIsLocal (reg1) && val && oldval && !pic16_isAlive (SPO_STATUS, pc)) {
       //pc->print (stderr, pc); fprintf (stderr, "lit: %d (%x, %x)\n", lit, lit, val->in_val);
       if (lit == 0) {
-        newpc = pic16_newpCode (POC_CLRF, PCOR2(pci->pcop)->pcop2);
+        newpc = pic16_newpCode (POC_CLRF, PCOP2(pci->pcop)->pcopR);
       } else if (lit == 0x00ff) {
-       newpc = pic16_newpCode (POC_SETF, PCOR2(pci->pcop)->pcop2);
+       newpc = pic16_newpCode (POC_SETF, PCOP2(pci->pcop)->pcopR);
       } else {
         newpc = NULL;
       }
@@ -11757,8 +11727,10 @@ static void assignValnums (pCode *pc) {
         pc = newpc;
         break; // do not process instruction as MOVFF...
       }
-    } else if (!isSpecial1 && !isSpecial2 && pic16_regIsLocal (reg1) && pic16_regIsLocal (reg2)) {
-      if (val && oldval && (val->in_val != 0) && (val->in_val == oldval->in_val)) {
+    } else if (!isSpecial1 && !isSpecial2
+               && pic16_regIsLocal (reg1) && pic16_regIsLocal (reg2)
+               && val && oldval && (val->in_val != 0)) {
+      if (val->in_val == oldval->in_val) {
        //fprintf (stderr, "MOVFF: F2 (%s) already set up correctly (%x) at %p\n", strFromSym (sym2), oldval->in_val, pc);
         pic16_safepCodeRemove (pc, "=DF= redundant MOVFF removed");
       } else {
@@ -11782,12 +11754,36 @@ static void assignValnums (pCode *pc) {
            if (copy->val && copy->val == val->in_val) {
              //fprintf (stderr, "found replacement symbol for %s (val %x) <-- %s (assigned %x @ %p)\n", strFromSym(sym1), val->in_val, strFromSym(copy->sym), copy->val, copy->pc);
              if (copy->sym == SPO_WREG) {
-               newpc = pic16_newpCode (POC_MOVWF, pic16_pCodeOpCopy (PCOR2(pci->pcop)->pcop2));
+               newpc = pic16_newpCode (POC_MOVWF, pic16_pCodeOpCopy (PCOP2(pci->pcop)->pcopR));
              } else {
+               pCodeOp *pcop = NULL;
+               /* the code below fails if we try to replace
+                *   MOVFF PRODL, r0x03
+                *   MOVFF r0x03, PCLATU
+                * with
+                *   MOVFF PRODL, PCLATU
+                * as copy(PRODL) contains has pc==NULL, by name fails...
+                */
+               if (!copy->pc || !PCI(copy->pc)->pcop) break;
+               
+               if (copy->pc && PCI(copy->pc)->pcop)
+                 pcop = PCI(copy->pc)->pcop;
+#if 0
+               /* This code is broken--see above. */
+               else
+               {
+                 const char *symname = strFromSym(copy->sym);
+                 
+                 assert( symname );
+                 pic16_InsertCommentAfter (pc->prev, "BUG-ME");
+                 pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: newpCodeOpregFromStr(%s)", (char *)symname);
+                 //pcop = pic16_newpCodeOpRegFromStr((char *)symname);
+               }
+#endif
+               assert( pcop );
                 newpc = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
-//                     /*TODO: change to copy->pc's out symbol*/pic16_pCodeOpCopy (pci->pcop),
-                       pic16_pCodeOpCopy (PCI(copy->pc)->pcop),
-                       pic16_pCodeOpCopy (PCOR2(pci->pcop)->pcop2)));
+                       pcop,
+                       pic16_pCodeOpCopy (PCOP2(pci->pcop)->pcopR)));
              }
              pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: SRC op %s replaced by %s", strFromSym(sym1), strFromSym(copy->sym));
              pic16_df_saved_bytes += PCI(pc)->isize - PCI(newpc)->isize;