* src/SDCC.y, src/SDCCast.c, src/SDCCcse.c, src/SDCCglue.c, src/SDCCicode.c,
[fw/sdcc] / src / pic16 / genutils.c
index c79db38540b7adb378ebaa66c4bb64d03fe42dc7..1d25c2c60ca17cbe391a3810a3b015d126b6e742 100644 (file)
@@ -54,6 +54,7 @@
 #include "SDCCpeeph.h"
 #include "ralloc.h"
 #include "pcode.h"
+#include "device.h"
 #include "gen.h"
 
 #include "genutils.h"
 void pic16_genNot (iCode *ic)
 {
   int size;
+//  symbol *tlbl;
 
 /*
  * result[AOP_CRY,AOP_REG]  = ! left[AOP_CRY, AOP_REG]
  */
 
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       /* assign asmOps to operand & result */
-       pic16_aopOp (IC_LEFT(ic),ic,FALSE);
-       pic16_aopOp (IC_RESULT(ic),ic,TRUE);
-       DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
-
-       /* if in bit space then a special case */
-       if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
-               if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
-                       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
-                       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-               } else {
-                       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-                       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
-                       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-               }
-               goto release;
-       }
-
-       size = AOP_SIZE(IC_LEFT(ic));
-       if(size == 1) {
-               pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
-               pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
-               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-               goto release;
-       }
+    FENTRY;
+   
+    /* assign asmOps to operand & result */
+    pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+    pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+    DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
+
+    /* if in bit space then a special case */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
+      if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+        pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+        pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      } else {
+        pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+        pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
+        pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      }
+      goto release;
+    }
+
+    size = AOP_SIZE(IC_LEFT(ic));
+#if 0
+    if(size == 1) {
+      pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
+      pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
+      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
+      goto release;
+    }
+#endif
+
+    pic16_toBoolean( IC_LEFT(ic) );
+    emitSETC;
+    pic16_emitpcode(POC_TSTFSZ, pic16_popCopyReg( &pic16_pc_wreg ));
+    emitCLRC;
+    pic16_outBitC( IC_RESULT(ic) );
 
 release:    
-       /* release the aops */
-       pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-       pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    /* release the aops */
+    pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+    pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
 }
 
 #endif /* defined(GEN_Not) */
@@ -123,37 +134,66 @@ void pic16_genCpl (iCode *ic)
 /*
  * result[CRY,REG] = ~left[CRY,REG]
  */
-
-       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-       /* assign asmOps to operand & result */
-       pic16_aopOp (IC_LEFT(ic),ic,FALSE);
-       pic16_aopOp (IC_RESULT(ic),ic,TRUE);
-       DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
-
-       /* if both are in bit space then 
-          a special case */
-       if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-               AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-
-               /* FIXME */
-               pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
-               pic16_emitcode("cpl","c"); 
-               pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
-               goto release; 
-       } 
-
-       size = AOP_SIZE(IC_RESULT(ic));
-       while (size--) {
-
-               if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-                       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
-               } else {
-                       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
-                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-               }
-               offset++;
-       }
+    FENTRY;
+
+    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    /* assign asmOps to operand & result */
+    pic16_aopOp (IC_LEFT(ic),ic,FALSE);
+    pic16_aopOp (IC_RESULT(ic),ic,TRUE);
+    DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
+
+    /* if both are in bit space then 
+     * a special case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
+      && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+
+        /* FIXME */
+        pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
+        pic16_emitcode("cpl","c"); 
+        pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
+        goto release; 
+    } 
+
+    size = AOP_SIZE(IC_RESULT(ic));
+    if (size >= AOP_SIZE(IC_LEFT(ic))) size = AOP_SIZE(IC_LEFT(ic));
+    
+    while (size--) {
+      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+        pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
+      } else {
+        pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
+        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+      }
+      offset++;
+    }
+
+    /* handle implicit upcast */
+    size = AOP_SIZE(IC_RESULT(ic));
+    if (offset < size)
+    {
+      if (SPEC_USIGN(operandType(IC_LEFT(ic)))) {
+       while (offset < size) {
+         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
+         offset++;
+       } // while
+      } else {
+       if ((offset + 1) == size) {
+         /* just one byte to fix */
+         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
+       } else {
+         /* two or more byte to adjust */
+         pic16_emitpcode(POC_SETF, pic16_popCopyReg( &pic16_pc_wreg ));
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
+         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_wreg ));
+         while (offset < size) {
+           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
+           offset++;
+         } // while
+       } // if
+      }
+    } // if
 
 release:
     /* release the aops */
@@ -162,3 +202,439 @@ release:
 }
 #endif /* defined(GEN_Cpl) */
 
+
+
+/*-----------------------------------------------------------------*/
+/* Helper function to dump operand into comment lines              */
+/*-----------------------------------------------------------------*/
+
+void pic16_DumpValue(char *prefix, value *val)
+{
+//     char s[INITIAL_INLINEASM];  
+       if(!val) return;
+
+       DEBUGpic16_emitcode (";", " %s Dump value",prefix);
+       DEBUGpic16_emitcode (";", " %s name:%s",prefix,val->name);
+}
+
+void pic16_DumpPcodeOp(char *prefix, pCodeOp *pcop)
+{
+//     char s[INITIAL_INLINEASM];  
+       if(!pcop) return;
+
+       DEBUGpic16_emitcode (";", " %s Dump pCodeOp",prefix);
+       DEBUGpic16_emitcode (";", " %s name:%s",prefix,pcop->name);
+       if(pcop->type == PO_NONE) {
+               DEBUGpic16_emitcode (";", " %s type:PO_NONE",prefix);
+       }
+       if(pcop->type == PO_W) {
+               DEBUGpic16_emitcode (";", " %s type:PO_W",prefix);
+       }
+       if(pcop->type == PO_WREG) {
+               DEBUGpic16_emitcode (";", " %s type:PO_WREG",prefix);
+       }
+       if(pcop->type == PO_STATUS) {
+               DEBUGpic16_emitcode (";", " %s type:PO_STATUS",prefix);
+       }
+       if(pcop->type == PO_BSR) {
+               DEBUGpic16_emitcode (";", " %s type:PO_BSR",prefix);
+       }
+       if(pcop->type == PO_FSR0) {
+               DEBUGpic16_emitcode (";", " %s type:PO_FSR0",prefix);
+       }
+       if(pcop->type == PO_INDF0) {
+               DEBUGpic16_emitcode (";", " %s type:PO_INDF0",prefix);
+       }
+       if(pcop->type == PO_INTCON) {
+               DEBUGpic16_emitcode (";", " %s type:PO_INTCON",prefix);
+       }
+       if(pcop->type == PO_GPR_REGISTER) {
+               DEBUGpic16_emitcode (";", " %s type:PO_GPR_REGISTER",prefix);
+       }
+       if(pcop->type == PO_GPR_BIT) {
+               DEBUGpic16_emitcode (";", " %s type:PO_GPR_BIT",prefix);
+       }
+       if(pcop->type == PO_GPR_TEMP) {
+               DEBUGpic16_emitcode (";", " %s type:PO_GPR_TEMP",prefix);
+       }
+       if(pcop->type == PO_SFR_REGISTER) {
+               DEBUGpic16_emitcode (";", " %s type:PO_SFR_REGISTER",prefix);
+       }
+       if(pcop->type == PO_PCL) {
+               DEBUGpic16_emitcode (";", " %s type:PO_PCL",prefix);
+       }
+       if(pcop->type == PO_PCLATH) {
+               DEBUGpic16_emitcode (";", " %s type:PO_PCLATH",prefix);
+       }
+       if(pcop->type == PO_LITERAL) {
+               DEBUGpic16_emitcode (";", " %s type:PO_LITERAL",prefix);
+               DEBUGpic16_emitcode (";", " %s lit:%s",prefix,PCOL(pcop)->lit);
+       }
+       if(pcop->type == PO_REL_ADDR) {
+               DEBUGpic16_emitcode (";", " %s type:PO_REL_ADDR",prefix);
+       }
+       if(pcop->type == PO_IMMEDIATE) {
+               DEBUGpic16_emitcode (";", " %s type:PO_IMMEDIATE",prefix);
+       }
+       if(pcop->type == PO_DIR) {
+               DEBUGpic16_emitcode (";", " %s type:PO_DIR",prefix);
+       }
+       if(pcop->type == PO_CRY) {
+               DEBUGpic16_emitcode (";", " %s type:PO_CRY",prefix);
+       }
+       if(pcop->type == PO_BIT) {
+               DEBUGpic16_emitcode (";", " %s type:PO_BIT",prefix);
+       }
+       if(pcop->type == PO_STR) {
+               DEBUGpic16_emitcode (";", " %s type:PO_STR",prefix);
+       }
+       if(pcop->type == PO_LABEL) {
+               DEBUGpic16_emitcode (";", " %s type:PO_LABEL",prefix);
+       }
+       if(pcop->type == PO_WILD) {
+               DEBUGpic16_emitcode (";", " %s type:PO_WILD",prefix);
+       }
+}
+
+
+
+void pic16_DumpAop(char *prefix, asmop *aop)
+{
+       char s[INITIAL_INLINEASM];  
+       if(!aop) return;
+
+       DEBUGpic16_emitcode (";", " %s Dump asmop",prefix);
+       if (aop->type == AOP_LIT)
+       {
+               DEBUGpic16_emitcode (";", " %s type:AOP_LIT",prefix);
+               sprintf(s,"%s (aopu.aop_lit)",prefix);
+               pic16_DumpValue(s,aop->aopu.aop_lit);
+       }
+       if (aop->type == AOP_REG)
+               DEBUGpic16_emitcode (";", " %s type:AOP_REG",prefix);
+       if (aop->type == AOP_DIR)
+       {
+               DEBUGpic16_emitcode (";", " %s type:AOP_DIR",prefix);
+               DEBUGpic16_emitcode (";", " %s aopu.aop_dir:%s",prefix,aop->aopu.aop_dir);
+       }
+       if (aop->type == AOP_DPTR)
+               DEBUGpic16_emitcode (";", " %s type:AOP_DPTR",prefix);
+       if (aop->type == AOP_DPTR2)
+               DEBUGpic16_emitcode (";", " %s type:AOP_DPTR2",prefix);
+       if (aop->type == AOP_R0)
+               DEBUGpic16_emitcode (";", " %s type:AOP_R0",prefix);
+       if (aop->type == AOP_R1)
+               DEBUGpic16_emitcode (";", " %s type:AOP_R1",prefix);
+       if (aop->type == AOP_STK)
+               DEBUGpic16_emitcode (";", " %s type:AOP_STK",prefix);
+       if (aop->type == AOP_STA)
+               DEBUGpic16_emitcode (";", " %s type:AOP_STA",prefix);
+       if (aop->type == AOP_IMMD)
+       {
+               DEBUGpic16_emitcode (";", " %s type:AOP_IMMD",prefix);
+               DEBUGpic16_emitcode (";", " %s aopu.aop_immd:%s",prefix,aop->aopu.aop_immd);
+       }
+       if (aop->type == AOP_STR)
+       {
+               DEBUGpic16_emitcode (";", " %s type:AOP_STR",prefix);
+               DEBUGpic16_emitcode (";", " %s aopu.aop_str:%s/%s/%s/%s",prefix,aop->aopu.aop_str[0],
+                               aop->aopu.aop_str[1],aop->aopu.aop_str[2],aop->aopu.aop_str[3]);
+       }
+       if (aop->type == AOP_CRY)
+               DEBUGpic16_emitcode (";", " %s type:AOP_CRY",prefix);
+       if (aop->type == AOP_ACC)
+               DEBUGpic16_emitcode (";", " %s type:AOP_ACC",prefix);
+       if (aop->type == AOP_PCODE)
+       {
+               DEBUGpic16_emitcode (";", " %s type:AOP_PCODE",prefix);
+               sprintf(s,"%s (aopu.pcop)",prefix);
+               pic16_DumpPcodeOp(s,aop->aopu.pcop);
+       }
+
+
+       DEBUGpic16_emitcode (";", " %s coff:%d",prefix,aop->coff);
+       DEBUGpic16_emitcode (";", " %s size:%d",prefix,aop->size);
+       DEBUGpic16_emitcode (";", " %s code:%d",prefix,aop->code);
+       DEBUGpic16_emitcode (";", " %s paged:%d",prefix,aop->paged);
+       DEBUGpic16_emitcode (";", " %s freed:%d",prefix,aop->freed);
+
+}
+
+void pic16_DumpSymbol(char *prefix, symbol *sym)
+{
+       char s[INITIAL_INLINEASM];  
+       if(!sym) return;
+
+       DEBUGpic16_emitcode (";", " %s Dump symbol",prefix);
+       DEBUGpic16_emitcode (";", " %s name:%s",prefix,sym->name);
+       DEBUGpic16_emitcode (";", " %s rname:%s",prefix,sym->rname);
+       DEBUGpic16_emitcode (";", " %s level:%d",prefix,sym->level);
+       DEBUGpic16_emitcode (";", " %s block:%d",prefix,sym->block);
+       DEBUGpic16_emitcode (";", " %s key:%d",prefix,sym->key);
+       DEBUGpic16_emitcode (";", " %s implicit:%d",prefix,sym->implicit);
+       DEBUGpic16_emitcode (";", " %s undefined:%d",prefix,sym->undefined);
+       DEBUGpic16_emitcode (";", " %s _isparm:%d",prefix,sym->_isparm);
+       DEBUGpic16_emitcode (";", " %s ismyparm:%d",prefix,sym->ismyparm);
+       DEBUGpic16_emitcode (";", " %s isitmp:%d",prefix,sym->isitmp);
+       DEBUGpic16_emitcode (";", " %s islbl:%d",prefix,sym->islbl);
+       DEBUGpic16_emitcode (";", " %s isref:%d",prefix,sym->isref);
+       DEBUGpic16_emitcode (";", " %s isind:%d",prefix,sym->isind);
+       DEBUGpic16_emitcode (";", " %s isinvariant:%d",prefix,sym->isinvariant);
+       DEBUGpic16_emitcode (";", " %s cdef:%d",prefix,sym->cdef);
+       DEBUGpic16_emitcode (";", " %s addrtaken:%d",prefix,sym->addrtaken);
+       DEBUGpic16_emitcode (";", " %s isreqv:%d",prefix,sym->isreqv);
+       DEBUGpic16_emitcode (";", " %s udChked:%d",prefix,sym->udChked);
+       DEBUGpic16_emitcode (";", " %s isLiveFcall:%d",prefix,sym->isLiveFcall);
+       DEBUGpic16_emitcode (";", " %s isspilt:%d",prefix,sym->isspilt);
+       DEBUGpic16_emitcode (";", " %s spillA:%d",prefix,sym->spillA);
+       DEBUGpic16_emitcode (";", " %s remat:%d",prefix,sym->remat);
+       DEBUGpic16_emitcode (";", " %s isptr:%d",prefix,sym->isptr);
+       DEBUGpic16_emitcode (";", " %s uptr:%d",prefix,sym->uptr);
+       DEBUGpic16_emitcode (";", " %s isFree:%d",prefix,sym->isFree);
+       DEBUGpic16_emitcode (";", " %s islocal:%d",prefix,sym->islocal);
+       DEBUGpic16_emitcode (";", " %s blockSpil:%d",prefix,sym->blockSpil);
+       DEBUGpic16_emitcode (";", " %s remainSpil:%d",prefix,sym->remainSpil);
+       DEBUGpic16_emitcode (";", " %s stackSpil:%d",prefix,sym->stackSpil);
+       DEBUGpic16_emitcode (";", " %s onStack:%d",prefix,sym->onStack);
+       DEBUGpic16_emitcode (";", " %s iaccess:%d",prefix,sym->iaccess);
+       DEBUGpic16_emitcode (";", " %s ruonly:%d",prefix,sym->ruonly);
+       DEBUGpic16_emitcode (";", " %s spildir:%d",prefix,sym->spildir);
+       DEBUGpic16_emitcode (";", " %s ptrreg:%d",prefix,sym->ptrreg);
+       DEBUGpic16_emitcode (";", " %s noSpilLoc:%d",prefix,sym->noSpilLoc);
+       DEBUGpic16_emitcode (";", " %s isstrlit:%d",prefix,sym->isstrlit);
+       DEBUGpic16_emitcode (";", " %s accuse:%d",prefix,sym->accuse);
+       DEBUGpic16_emitcode (";", " %s dptr:%d",prefix,sym->dptr);
+       DEBUGpic16_emitcode (";", " %s allocreq:%d",prefix,sym->allocreq);
+       DEBUGpic16_emitcode (";", " %s stack:%d",prefix,sym->stack);
+       DEBUGpic16_emitcode (";", " %s xstack:%d",prefix,sym->xstack);
+       DEBUGpic16_emitcode (";", " %s nRegs:%d",prefix,sym->nRegs);
+       DEBUGpic16_emitcode (";", " %s regType:%d",prefix,sym->regType);
+
+       // struct regs !!!
+
+       if(sym->aop)
+       {
+               sprintf(s,"%s (aop)",prefix);
+               pic16_DumpAop(s,sym->aop);
+       } else {
+               DEBUGpic16_emitcode (";", " %s aop:NULL",prefix);
+       }
+}
+
+void pic16_DumpOp(char *prefix, operand *op)
+{
+       char s[INITIAL_INLINEASM];  
+       if(!op) return;
+
+       DEBUGpic16_emitcode (";", " %s Dump operand",prefix);
+       if(IS_SYMOP(op))
+               DEBUGpic16_emitcode (";", " %s type: SYMBOL",prefix);
+       if(IS_VALOP(op))
+               DEBUGpic16_emitcode (";", " %s type: VALUE",prefix);
+       if(IS_TYPOP(op))
+               DEBUGpic16_emitcode (";", " %s type: TYPE",prefix);
+       DEBUGpic16_emitcode (";", " %s isaddr:%d",prefix,op->isaddr);
+       DEBUGpic16_emitcode (";", " %s isvolatile:%d",prefix,op->isvolatile);
+       DEBUGpic16_emitcode (";" ," %s isGlobal:%d",prefix,op->isGlobal);
+       DEBUGpic16_emitcode (";", " %s isPtr:%d",prefix,op->isPtr);
+       DEBUGpic16_emitcode (";", " %s isGptr:%d",prefix,op->isGptr);
+       DEBUGpic16_emitcode (";", " %s isParm:%d",prefix,op->isParm);
+       DEBUGpic16_emitcode (";", " %s isLiteral:%d",prefix,op->isLiteral);
+       DEBUGpic16_emitcode (";", " %s key:%d",prefix,op->key);
+       if(IS_SYMOP(op)) {
+               sprintf(s,"%s (symOperand)",prefix);
+               pic16_DumpSymbol(s,op->operand.symOperand);
+       }
+
+}
+
+void pic16_DumpOpX(FILE *fp, char *prefix, operand *op)
+{
+  if(!op)return;
+    
+  fprintf(fp, "%s [", prefix);
+  fprintf(fp, "%s", IS_SYMOP(op)?"S":" ");
+  fprintf(fp, "%s", IS_VALOP(op)?"V":" ");
+  fprintf(fp, "%s", IS_TYPOP(op)?"T":" ");
+  fprintf(fp, "] ");
+
+  fprintf(fp, "isaddr:%d,", op->isaddr);
+  fprintf(fp, "isvolatile:%d,", op->isvolatile);
+  fprintf(fp, "isGlobal:%d,", op->isGlobal);
+  fprintf(fp, "isPtr:%d,", op->isPtr);
+  fprintf(fp, "isParm:%d,", op->isParm);
+  fprintf(fp, "isLit:%d\n", op->isLiteral);
+}  
+    
+
+void _debugf(char *f, int l, char *frm, ...)
+{
+  va_list ap;
+  
+    va_start(ap, frm);
+    fprintf(stderr, "%s:%d ", f, l);
+    vfprintf(stderr, frm, ap);
+    va_end(ap);
+}
+
+
+
+void gpsimio2_pcop(pCodeOp *pcop)
+{
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_gpsimio2)));
+}
+
+void gpsimio2_lit(unsigned char lit)
+{
+  pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit));
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_wreg), pic16_popCopyReg(&pic16_pc_gpsimio2)));
+}
+
+void gpsimio2_str(char *buf)
+{
+  while(*buf) {
+    gpsimio2_lit(*buf);
+    buf++;
+  }
+}
+
+void gpsimDebug_StackDump(char *fname, int line, char *info)
+{
+  pic16_emitpcomment("; gpsim debug stack dump; %s @ %d\tinfo: ", fname, line, info);
+  
+  gpsimio2_str("&c[S:");
+  gpsimio2_str(info);
+  gpsimio2_str("] &h");
+  
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1h),
+                pic16_popCopyReg(&pic16_pc_gpsimio2)));
+  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_fsr1l),
+                pic16_popCopyReg(&pic16_pc_gpsimio2)));
+
+  gpsimio2_lit('\n');
+}
+
+const char *gptr_fns[4][2] = {
+  { "_gptrget1", "_gptrput1" },
+  { "_gptrget2", "_gptrput2" },
+  { "_gptrget3", "_gptrput3" },
+  { "_gptrget4", "_gptrput4" } };
+
+extern set *externs;
+  
+/* generate a call to the generic pointer read/write functions */
+void pic16_callGenericPointerRW(int rw, int size)
+{
+  char buf[32];
+  symbol *sym;
+
+    if(size>4) {
+      werror(W_POSSBUG2, __FILE__, __LINE__);
+      abort();
+    }
+
+    strcpy(buf, port->fun_prefix);
+    strcat(buf, gptr_fns[size-1][rw]);
+    
+    pic16_emitpcode (POC_CALL, pic16_popGetWithString (buf));
+    
+    sym = newSymbol( buf, 0 );
+    sym->used++;
+    strcpy(sym->rname, buf);
+    checkAddSym(&externs, sym);
+}
+
+
+
+/* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
+static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
+        operand *result, int offset, int invert_op)
+{
+  /* add code here */
+  
+  /* check condition, > or < ?? */
+  if(rIfx->condition != 0)invert_op ^= 1;
+  
+  if(ifx && IC_FALSE(ifx))invert_op ^= 1;
+
+  if(!ifx)invert_op ^= 1;
+
+  DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
+      __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
+  
+  /* do selection */
+  if(!invert_op)return POC_CPFSGT;
+  else return POC_CPFSLT;
+}
+
+/* return 1 if function handles compare, 0 otherwise */
+/* this functions handles special cases like:
+ * reg vs. zero
+ * reg vs. one
+ */
+int pic16_genCmp_special(operand *left, operand *right, operand *result,
+                    iCode *ifx, resolvedIfx *rIfx, int sign)
+{
+  int size;
+  int offs=0;
+  symbol *tmplbl;
+  unsigned long lit;
+  int op, cmp_op=0, cond_pre;
+
+    FENTRY;
+    
+    if(!(pic16_options.opt_flags & OF_OPTIMIZE_CMP))return 0;
+
+    size = max(AOP_SIZE(left), AOP_SIZE(right));
+
+    cond_pre = rIfx->condition; // must restore old value on return with 0!!!
+    
+    if(!isAOP_REGlike(left)) {
+      operand *dummy;
+
+        dummy = left;
+        left = right;
+        right = dummy;
+        
+        /* invert comparing operand */
+//        cmp_op ^= 1;
+        rIfx->condition ^= 1;
+    }
+    
+    
+    if(isAOP_REGlike(left) && isAOP_LIT(right)) {
+      /* comparing register vs. literal */
+      lit = ulFromVal(AOP(right)->aopu.aop_lit);
+      
+      
+      if(size == 1) {
+        op = selectCompareOp(rIfx, ifx, result, offs, cmp_op);
+        
+        DEBUGpic16_emitcode("%%", "comparing operand %s, condition: %d", (op==POC_CPFSLT?"POC_CPFSLT":"POC_CPFSGT"), rIfx->condition);
+
+        if(!sign) {
+          /* unsigned compare */
+          switch( lit ) {
+            case 0:
+              if(ifx && IC_FALSE(ifx)) {
+                tmplbl = newiTempLabel( NULL );
+                pic16_emitpcode(POC_TSTFSZ, pic16_popGet(AOP(left), 0));
+                pic16_emitpcode(POC_BRA, pic16_popGetLabel(tmplbl->key));
+                pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx->lbl->key));
+                pic16_emitpLabel(tmplbl->key);
+
+                ifx->generated = 1;
+                return 1;
+              }
+              break;
+          }    /* switch */
+
+        }      /* if(!sign) */
+
+      }                /* if(size==1) */
+
+    }          /* */
+      
+  rIfx->condition = cond_pre;
+  return 0;
+}