* src/pic16/device.h (pic16_options): removed field use_crt,
[fw/sdcc] / src / pic16 / gen.c
index 49dbd23523e7531fc4b57b26b0bbce1cbfdf5e87..1d4021ffa20c56194ec35d41b4f261f46dd6ca9b 100644 (file)
@@ -58,7 +58,7 @@ static asmop *newAsmop (short type);
 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
 static void mov2w (asmop *aop, int offset);
-static int aopIdx (asmop *aop, int offset);
+//static int aopIdx (asmop *aop, int offset);
 
 int pic16_labelOffset=0;
 extern int pic16_debug_verbose;
@@ -132,6 +132,7 @@ static struct {
     short ipushRegs;
     set *sendSet;
     int interruptvector;
+    int usefastretfie;
 } _G;
 
 /* Resolved ifx structure. This structure stores information
@@ -414,6 +415,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
     assert( 0 );
 
+    return NULL;
 #if 0
     /* the logic: if r0 & r1 used in the instruction
     then we are in trouble otherwise */
@@ -871,6 +873,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym)
   return aop;        
 }
 
+#if 0
 static int aopIdx (asmop *aop, int offset)
 {
   if(!aop)
@@ -882,6 +885,8 @@ static int aopIdx (asmop *aop, int offset)
   return aop->aopu.aop_reg[offset]->rIdx;
 
 }
+#endif
+
 /*-----------------------------------------------------------------*/
 /* regsInCommon - two operands have some registers in common       */
 /*-----------------------------------------------------------------*/
@@ -3466,17 +3471,22 @@ static void genFunction (iCode *ic)
         * save acc, b, dpl, dph  */
        if (IFFUNC_ISISR(sym->type)) {
          int i;
+
+               _G.usefastretfie = 1;   /* use shadow registers by default */
                /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
                if(!(_G.interruptvector == 1)) {
 
                        /* do not save WREG,STATUS,BSR for high priority interrupts
                         * because they are stored in the hardware shadow registers already */
-                        
+                       _G.usefastretfie = 0;
                        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
                        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
                        pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
                }
 
+
+                /* these should really be optimized somehow, because not all
+                 * interrupt handlers modify them */
                pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
                pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
                pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
@@ -3712,7 +3722,11 @@ static void genEndFunction (iCode *ic)
                        debugFile->writeEndFunction (currFunc, ic, 1);
                }
        
+               if(_G.usefastretfie)
+                       pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
+               else
                pic16_emitpcodeNULLop(POC_RETFIE);
+               _G.usefastretfie = 0;
        } else {
                if (IFFUNC_ISCRITICAL(sym->type))
                        pic16_emitcode("setb","ea");
@@ -3764,7 +3778,6 @@ static void genEndFunction (iCode *ic)
                        }
                }
 
-               pic16_emitcode ("return","");
                pic16_emitpcodeNULLop(POC_RETURN);
 
                /* Mark the end of a function */
@@ -6591,10 +6604,36 @@ static void genAnd (iCode *ic, iCode *ifx)
     } else {
       symbol *tlbl = newiTempLabel(NULL);
       int sizel = AOP_SIZE(left);
+
       if(size)
-       pic16_emitcode("setb","c");
-      while(sizel--){
-       if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
+        emitSETC;
+
+      while(sizel--) {
+        if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
+
+          /* patch provided by Aaron Colwell */
+          if((posbit = isLiteralBit(bytelit)) != 0) {
+              pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
+                              pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
+                                                (posbit-1),0, PO_GPR_REGISTER));
+
+              pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
+          } else {
+              if (bytelit == 0xff) {
+                  /* Aaron had a MOVF instruction here, changed to MOVFW cause
+                   * a peephole could optimize it out -- VR */
+                  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
+              } else {
+                  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
+                  pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
+              }
+
+              pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
+                            pic16_popGetLabel(tlbl->key));
+          }
+        
+#if 0
+          /* old code, left here for reference -- VR 09/2004 */
          MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
          // byte ==  2^n ?
          if((posbit = isLiteralBit(bytelit)) != 0)
@@ -6604,22 +6643,27 @@ static void genAnd (iCode *ic, iCode *ifx)
              pic16_emitcode("anl","a,%s",
                             pic16_aopGet(AOP(right),offset,FALSE,TRUE));
            pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
-         }
+          }
+#endif
        }
        offset++;
       }
       // bit = left & literal
-      if(size){
-       pic16_emitcode("clr","c");
-       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
+      if(size) {
+        emitCLRC;
+        pic16_emitpLabel(tlbl->key);
       }
       // if(left & literal)
-      else{
-       if(ifx)
-         jmpTrueOrFalse(ifx, tlbl);
-       goto release ;
+      else {
+        if(ifx) {
+          pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
+          pic16_emitpLabel(tlbl->key);
+          ifx->generated = 1;
+        }
+        goto release;
       }
     }
+
     pic16_outBitC(result);
     goto release ;
   }
@@ -9170,10 +9214,16 @@ release:
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
 
+
+void pic16_loadFSR0(operand *op)
+{
+       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
+}
+
 /*-----------------------------------------------------------------*/
 /* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, char *rname, int ptype)
+static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
 {    
     int shCnt ;
     int rlen = 0 ;
@@ -9183,6 +9233,11 @@ static void genUnpackBits (operand *result, char *rname, int ptype)
        DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        etype = getSpec(operandType(result));
 
+        /* the following call to pic16_loadFSR0 is temporary until
+         * optimization to handle single bit assignments is added
+         * to the function. Until then use the old safe way! -- VR */
+        pic16_loadFSR0( left );
        /* read the first byte  */
        switch (ptype) {
                case POINTER:
@@ -9358,10 +9413,6 @@ release:
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
 
-void pic16_loadFSR0(operand *op)
-{
-       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
-}
 
 
 /*-----------------------------------------------------------------*/
@@ -9411,7 +9462,8 @@ static void genNearPointerGet (operand *left,
                        && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
                                || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
                {
-                       pic16_loadFSR0( left );  // patch 10
+                       if(!IS_BITFIELD(retype))
+                               pic16_loadFSR0( left );  // patch 10
                } else {
                        // set up FSR0 with address from left
                        pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
@@ -9425,7 +9477,7 @@ static void genNearPointerGet (operand *left,
     
       /* if bitfield then unpack the bits */
     if (IS_BITFIELD(retype)) 
-       genUnpackBits (result, NULL, POINTER);
+       genUnpackBits (result, left, NULL, POINTER);
     else {
        /* we have can just get the values */
       int size = AOP_SIZE(result);
@@ -9539,7 +9591,7 @@ static void genPagedPointerGet (operand *left,
 
     /* if bitfield then unpack the bits */
     if (IS_BITFIELD(retype)) 
-       genUnpackBits (result,rname,PPOINTER);
+       genUnpackBits (result,left,rname,PPOINTER);
     else {
        /* we have can just get the values */
        int size = AOP_SIZE(result);
@@ -9617,7 +9669,7 @@ static void genFarPointerGet (operand *left,
 
     /* if bit then unpack */
     if (IS_BITFIELD(retype)) 
-        genUnpackBits(result,"dptr",FPOINTER);
+        genUnpackBits(result,left,"dptr",FPOINTER);
     else {
         size = AOP_SIZE(result);
         offset = 0 ;
@@ -9667,7 +9719,7 @@ static void genCodePointerGet (operand *left,
 
     /* if bit then unpack */
     if (IS_BITFIELD(retype)) 
-        genUnpackBits(result,"dptr",CPOINTER);
+        genUnpackBits(result,left,"dptr",CPOINTER);
     else {
         size = AOP_SIZE(result);
         offset = 0 ;
@@ -9740,7 +9792,7 @@ static void genGenPointerGet (operand *left,
 
   /* if bit then unpack */
        if (IS_BITFIELD(retype)) 
-               genUnpackBits(result,"BAD",GPOINTER);
+               genUnpackBits(result,left,"BAD",GPOINTER);
 
        release:
        pic16_freeAsmop(left,NULL,ic,TRUE);
@@ -9919,7 +9971,7 @@ static void genPointerGet (iCode *ic)
 /*-----------------------------------------------------------------*/
 /* genPackBits - generates code for packed bit storage             */
 /*-----------------------------------------------------------------*/
-static void genPackBits (sym_link    *etype ,
+static void genPackBits (sym_link    *etype , operand *result,
                          operand *right ,
                          char *rname, int p_type)
 {
@@ -9942,12 +9994,24 @@ static void genPackBits (sym_link    *etype ,
 
                        lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
 //                     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
-                       if(lit) {
-                               pic16_emitpcode(POC_BSF,
-                                       pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
+                       if((p_type == POINTER) && (result)) {
+                               /* workaround to reduce the extra lfsr instruction */
+                               if(lit) {
+                                       pic16_emitpcode(POC_BSF,
+                                               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
+                               } else {
+                                       pic16_emitpcode(POC_BCF,
+                                               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
+                               }
                        } else {
-                               pic16_emitpcode(POC_BCF,
-                                       pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
+
+                               if(lit) {
+                                       pic16_emitpcode(POC_BSF,
+                                               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
+                               } else {
+                                       pic16_emitpcode(POC_BCF,
+                                               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
+                               }
                        }
        
                  return;
@@ -10182,6 +10246,7 @@ static void genNearPointerSet (operand *right,
                        && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
                                || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
                {
+                 if(!IS_BITFIELD(resetype))
                        pic16_loadFSR0( result );  // patch 10
                } else {
                        // set up FSR0 with address of result
@@ -10197,7 +10262,7 @@ static void genNearPointerSet (operand *right,
 
        /* if bitfield then unpack the bits */
        if (IS_BITFIELD(resetype)) {
-               genPackBits (resetype, right, NULL, POINTER);
+               genPackBits (resetype, result, right, NULL, POINTER);
        } else {
                /* we have can just get the values */
          int size = AOP_SIZE(right);
@@ -10303,7 +10368,7 @@ static void genPagedPointerSet (operand *right,
 
     /* if bitfield then unpack the bits */
     if (IS_BITFIELD(retype)) 
-       genPackBits (retype,right,rname,PPOINTER);
+       genPackBits (retype,result,right,rname,PPOINTER);
     else {
        /* we have can just get the values */
        int size = AOP_SIZE(right);
@@ -10381,7 +10446,7 @@ static void genFarPointerSet (operand *right,
 
     /* if bit then unpack */
     if (IS_BITFIELD(retype)) 
-        genPackBits(retype,right,"dptr",FPOINTER);
+        genPackBits(retype,result,right,"dptr",FPOINTER);
     else {
         size = AOP_SIZE(right);
         offset = 0 ;
@@ -10488,7 +10553,7 @@ static void genGenPointerSet (operand *right,
 
        /* if bit then unpack */
        if (IS_BITFIELD(retype)) 
-               genPackBits(retype,right,"dptr",GPOINTER);
+               genPackBits(retype,result,right,"dptr",GPOINTER);
        else {
                size = AOP_SIZE(right);
                offset = 0 ;
@@ -10827,12 +10892,14 @@ static void genAssign (iCode *ic)
   if(AOP_TYPE(right) != AOP_LIT
        && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype))) {
        DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
+       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
 
        // set up table pointer
        if( (AOP_TYPE(right) == AOP_PCODE)
                && ((AOP(right)->aopu.pcop->type == PO_IMMEDIATE)
                || (AOP(right)->aopu.pcop->type == PO_DIR)))
        {
+               fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
                pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
@@ -10840,6 +10907,7 @@ static void genAssign (iCode *ic)
                pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
                pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
        } else {
+               fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
                                pic16_popCopyReg(&pic16_pc_tblptrl)));
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
@@ -10868,12 +10936,15 @@ static void genAssign (iCode *ic)
 
 
 
+#if 0
 /* VR - What is this?! */
   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
     if(aopIdx(AOP(result),0) == 4) {
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       assert(0);
+
+      /* this is a workaround to save value of right into wreg too,
+       * value of wreg is going to be used later */
+      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
       goto release;
@@ -10881,6 +10952,7 @@ static void genAssign (iCode *ic)
 //     assert(0);
       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
   }
+#endif
 
   know_W=-1;
   while (size--) {