* src/pic16/gen.c (genAssign): fixed assignment from longs
[fw/sdcc] / src / pic16 / gen.c
index bc7aed3efeed171bc697901fffdcaa6df83cbcd1..ee85154ddbb2efa13f528619c5b8d7b8692b51cb 100644 (file)
@@ -6,7 +6,7 @@
   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
-             -  Vangelis Rokas vrokas@otenet.gr (2003,2004)
+             -  Vangelis Rokas vrokas@otenet.gr (2003,2004,2005)
   
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
@@ -153,7 +153,6 @@ static struct {
     short ipushRegs;
     set *sendSet;
     set *stackRegSet;
-    int interruptvector;
     int usefastretfie;
     bitVect *fregsUsed;
     int stack_lat;                     /* stack offset latency */
@@ -648,11 +647,29 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
     }
 #endif
 
+
+#if 0
+    if(sym->iaccess) {
+      if(space->paged) {
+        fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
+
+        sym->aop = aop = newAsmop (AOP_PAGED);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+       DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
+       pic16_allocDirReg( IC_LEFT(ic) );
+        return aop;
+      }
+      assert( 0 );
+    }
+#endif
+    
 #if 1
     /* assign depending on the storage class */
     /* if it is on the stack or indirectly addressable */
     /* space we need to assign either r0 or r1 to it   */    
-    if (sym->onStack || sym->iaccess) {
+    if (sym->onStack)  // || sym->iaccess)
+    {
       pCodeOp *pcop[4];
       int i;
       
@@ -857,6 +874,10 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result)
        else if(sym->onStack) {
                aop->size = PTRSIZE;
         } else {
+          if(SPEC_SCLS(sym->etype) == S_PDATA) {
+            fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
+            aop->size = FPTRSIZE;
+          } else
                assert( 0 );
        }
 
@@ -1069,10 +1090,12 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
         aop2->type != AOP_REG )
         return FALSE ;
 
+    /* This is a bit too restrictive if one is a subset of the other...
     if (aop1->size != aop2->size )
         return FALSE ;
+    */
 
-    for (i = 0 ; i < aop1->size ; i++ ) {
+    for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
 
 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
@@ -1170,6 +1193,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
     b) has a spill location */
     if (sym->isspilt || sym->nRegs == 0) {
 
+//      debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs);
       DEBUGpic16_emitcode(";","%d",__LINE__);
         /* rematerialize it NOW */
         if (sym->remat) {
@@ -1230,9 +1254,16 @@ void pic16_aopOp (operand *op, iCode *ic, bool result)
 
        sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
        //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
-       aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
-                                         getSize(sym->type), 
-                                         sym->usl.spillLoc->offset, op);
+       if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
+         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
+                                                 getSize(sym->type), 
+                                                 sym->usl.spillLoc->offset, op);
+       } else {
+         fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__);
+         DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
+         assert (getSize(sym->type) <= 1);
+         aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op);
+       }
         aop->size = getSize(sym->type);
 
         return;
@@ -1543,6 +1574,21 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
       strcpy(rs,s);   
       return rs;
 
+#if 0
+    case AOP_PAGED:
+      DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
+      if (offset) {
+       sprintf(s,"(%s + %d)",
+               aop->aopu.aop_dir,
+               offset);
+      } else
+           sprintf(s,"%s",aop->aopu.aop_dir);
+      DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
+      rs = Safe_calloc(1,strlen(s)+1);
+      strcpy(rs,s);   
+      return rs;
+#endif
+
     case AOP_STA:
         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
         return (rs);
@@ -1941,6 +1987,12 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
        
+#if 0
+    case AOP_PAGED:
+      DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
+      return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
+#endif
+
     case AOP_REG:
       {
        int rIdx;
@@ -1998,16 +2050,14 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
                          __LINE__, 
                          ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
-#if 1
-       switch( aop->aopu.pcop->type ) {
-               case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
-               case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
-               default:
-                       assert( 0 );    /* should never reach here */;
-       }
-#else
-      PCOI(pcop)->offset = offset;
-#endif
+      switch( aop->aopu.pcop->type ) {
+        case PO_DIR: PCOR(pcop)->instance += offset; break;
+        case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
+        case PO_WREG: assert (offset==0); break;
+        default:
+         fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
+          assert( 0 ); /* should never reach here */;
+      }
       return pcop;
     }
 
@@ -2684,6 +2734,8 @@ static void genUminus (iCode *ic)
 {
   int size, i;
   sym_link *optype, *rtype;
+  symbol *label;
+  int needLabel=0;
 
     FENTRY;    
     
@@ -2712,21 +2764,33 @@ static void genUminus (iCode *ic)
 
     /* otherwise subtract from zero by taking the 2's complement */
     size = AOP_SIZE(IC_LEFT(ic));
-
-    for(i=0; i<size; i++) {
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-        pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
-      else {
-        pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
-        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
-      }
-    }
-
-    pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
-    for(i=1; i<size; i++) {
-      emitSKPNZ;
-      pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
+    label = newiTempLabel ( NULL );
+    
+    if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+      for (i=size-1; i > 0; i--) {
+        pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      } // for
+      pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
+      for (i=1; i < size; i++) {
+        if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
+        pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
+      } // for
+    } else {
+      for (i=size-1; i >= 0; i--) {
+        pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
+       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
+      } // for
+      if (size > 1) {
+        for (i=0; i < size-2; i++) {
+          pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
+          pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
+       } // for
+        pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
+      } // if
+      pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
     }
+    if (needLabel)
+      pic16_emitpLabel (label->key);
 
 release:
     /* release the aops */
@@ -3176,7 +3240,7 @@ static void genCall (iCode *ic)
 //     stackParms = psuedoStkPtr;
 //     fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
-    inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name);
+    inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
 
 #if 0
     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
@@ -3380,6 +3444,11 @@ static void genPcall (iCode *ic)
     // push return address
     // push $ on return stack, then replace with retlbl
 
+    /* Thanks to Thorsten Klose for pointing out that the following
+     * snippet should be interrupt safe */
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
+    pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
+
     pic16_emitpcodeNULLop(POC_PUSH);
 
     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
@@ -3389,6 +3458,11 @@ static void genPcall (iCode *ic)
     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
 
+
+    /* restore interrupt control register */
+    pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
+
     /* make the call by writing the pointer into pc */
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
@@ -3507,6 +3581,10 @@ static void genFunction (iCode *ic)
       char asymname[128];
       pBlock *apb;
 
+
+//        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
+
+#if 0
         {
           int i, found=-1;
 
@@ -3522,12 +3600,16 @@ static void genFunction (iCode *ic)
             if(found == -1) {
               fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
                             __FILE__, __LINE__, sym->name);
-              assert( 0 );
+//              assert( 0 );
             }
             _G.interruptvector = found;
         }
+#endif
 
-        sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
+        if(FUNC_INTNO(sym->type) == 256)
+          sprintf(asymname, "ivec_%s", sym->name);
+        else
+          sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
         asym = newSymbol(asymname, 0);
 
         apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
@@ -3546,14 +3628,18 @@ static void genFunction (iCode *ic)
            abSym = Safe_calloc(1, sizeof(absSym));
            strcpy(abSym->name, asymname);
 
-           switch( _G.interruptvector ) {
+           switch( FUNC_INTNO(sym->type) ) {
              case 0: abSym->address = 0x000000; break;
               case 1: abSym->address = 0x000008; break;
               case 2: abSym->address = 0x000018; break;
+              
+              default:
+                abSym->address = -1; break;
             }
 
             /* relocate interrupt vectors if needed */
-            abSym->address += pic16_options.ivt_loc;
+            if(abSym->address != -1)
+              abSym->address += pic16_options.ivt_loc;
 
             addSet(&absSymSet, abSym);
         }
@@ -3598,7 +3684,7 @@ static void genFunction (iCode *ic)
         _G.usefastretfie = 1;  /* use shadow registers by default */
         
         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
-        if(!(_G.interruptvector == 1)) {
+        if(!FUNC_ISSHADOWREGS(sym->type)) {
           /* do not save WREG,STATUS,BSR for high priority interrupts
            * because they are stored in the hardware shadow registers already */
           _G.usefastretfie = 0;
@@ -3646,7 +3732,7 @@ static void genFunction (iCode *ic)
       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));                //&pic16_pc_fsr1h));
     }
           
-    if(inWparamList(sym->name)) {
+    if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
         _G.useWreg = 0;
       else
@@ -3762,14 +3848,14 @@ static void genEndFunction (iCode *ic)
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
 
-      if(!(_G.interruptvector == 1)) {
+      if(!FUNC_ISSHADOWREGS(sym->type)) {
         /* do not restore interrupt vector for WREG,STATUS,BSR
          * for high priority interrupt, see genFunction */
        pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
        pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
        pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
       }
-      _G.interruptvector = 0;          /* sanity check */
+//      _G.interruptvector = 0;                /* sanity check */
 
 
       /* if debug then send end of function */
@@ -4573,6 +4659,33 @@ static void genIfxJump (iCode *ic, char *jval)
     ic->generated = 1;
 }
 
+static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
+{
+  FENTRY;
+  
+    /* if true label then we jump if condition
+    supplied is true */
+    if ( IC_TRUE(ic) ) {
+      DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);    
+      pic16_emitpcode(POC_BTFSC, jop);
+
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
+      pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
+
+    } else {
+      /* false label is present */
+      DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
+      pic16_emitpcode(POC_BTFSS, jop);
+         
+      pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
+      pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
+    }
+
+
+    /* mark the icode as generated */
+    ic->generated = 1;
+}
+
 #if 0
 // not needed ATM
 
@@ -10989,10 +11102,54 @@ static void genNearPointerGet (operand *left,
     }
     
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    pic16_aopOp (result,ic,FALSE);
+    
+    DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
+
+#if 1
+    if(IS_BITFIELD( retype )
+      && (SPEC_BLEN(operandType(result))==1)
+    ) {
+      iCode *nextic;
+      pCodeOp *jop;
+      int bitstrt, bytestrt;
+
+        /* if this is bitfield of size 1, see if we are checking the value
+         * of a single bit in an if-statement,
+         * if yes, then don't generate usual code, but execute the
+         * genIfx directly -- VR */
+
+        nextic = ic->next;
+
+        /* CHECK: if next iCode is IFX
+         * and current result operand is nextic's conditional operand
+         * and current result operand live ranges ends at nextic's key number
+         */
+        if((nextic->op == IFX)
+          && (result == IC_COND(nextic))
+          && (OP_LIVETO(result) == nextic->seq)
+          ) {
+            /* everything is ok then */
+            /* find a way to optimize the genIfx iCode */
+
+            bytestrt = SPEC_BSTR(operandType(result))/8;
+            bitstrt = SPEC_BSTR(operandType(result))%8;
+            
+            jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
+
+            genIfxpCOpJump(nextic, jop);
+            
+            pic16_freeAsmop(left, NULL, ic, TRUE);
+            pic16_freeAsmop(result, NULL, ic, TRUE);
+            return;
+        }
+    }
+#endif
+
 
     /* if the value is already in a pointer register
      * then don't need anything more */
-    if (!AOP_INPREG(AOP(left))) {
+    if (1 || !AOP_INPREG(AOP(left))) {  // AOP_INPREG(AOP(left)) is not always correct...
       /* otherwise get a free pointer register */
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
                
@@ -11009,12 +11166,6 @@ static void genNearPointerGet (operand *left,
         }
       }
     }
-//    else
-//    rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
-    
-    pic16_aopOp (result,ic,FALSE);
-    
-    DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
 
     /* if bitfield then unpack the bits */
     if (IS_BITFIELD(retype)) 
@@ -11220,6 +11371,7 @@ static void genFarPointerGet (operand *left,
 
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* genCodePointerGet - get value from code space                  */
@@ -11272,6 +11424,7 @@ static void genCodePointerGet (operand *left,
     pic16_freeAsmop(result,NULL,ic,TRUE);
 }
 #endif
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* genGenPointerGet - gget value from generic pointer space        */
@@ -11440,29 +11593,11 @@ static void genConstPointerGet (operand *left,
   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
 
   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
-#if 0                                                                  // patch 15
-  pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
-  pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
-  pic16_emitpLabel(albl->key);
-
-  poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
-  
-  /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
-  pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
-  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
-  pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
-  pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
-
-  pic16_emitpLabel(blbl->key);
-
-  pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
-#endif                                                                 // patch 15
-
 
   // set up table pointer
   if( (AOP_TYPE(left) == AOP_PCODE) 
       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
-          || (AOP(left)->aopu.pcop->type == PO_DIR)))                  // patch 15 ......
+          || (AOP(left)->aopu.pcop->type == PO_DIR)))
     {
       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
@@ -11470,25 +11605,20 @@ static void genConstPointerGet (operand *left,
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
-    }
-  else
-    {
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
-    }
-
+  } else {
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
+  }
 
-  while(size--)
-    {
-      pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
-      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
-      offset++;
-    }
+  while(size--) {
+    pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
+    offset++;
+  }
     
   pic16_freeAsmop(left,NULL,ic,TRUE);
   pic16_freeAsmop(result,NULL,ic,TRUE);
-
 }
 
 
@@ -11497,9 +11627,9 @@ static void genConstPointerGet (operand *left,
 /*-----------------------------------------------------------------*/
 static void genPointerGet (iCode *ic)
 {
-    operand *left, *result ;
-    sym_link *type, *etype;
-    int p_type;
+  operand *left, *result ;
+  sym_link *type, *etype;
+  int p_type;
 
     FENTRY;
     
@@ -11520,57 +11650,56 @@ static void genPointerGet (iCode *ic)
 
     /* if left is of type of pointer then it is simple */
     if (IS_PTR(type) && !IS_FUNC(type->next)) 
-        p_type = DCL_TYPE(type);
+      p_type = DCL_TYPE(type);
     else {
-       /* we have to go by the storage class */
-       p_type = PTR_TYPE(SPEC_OCLS(etype));
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE(SPEC_OCLS(etype));
 
-       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
+      DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
 
-       if (SPEC_OCLS(etype)->codesp ) {
-         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
-         //p_type = CPOINTER ; 
-       }
-       else
-           if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
-             DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
-              /*p_type = FPOINTER ;*/ 
-           else
-               if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
-                 DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
-/*                 p_type = PPOINTER; */
-               else
-                   if (SPEC_OCLS(etype) == idata )
-                     DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
-/*                     p_type = IPOINTER; */
-                   else
-                     DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
-/*                     p_type = POINTER ; */
+      if (SPEC_OCLS(etype)->codesp ) {
+        DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
+        //p_type = CPOINTER ;  
+      } else
+      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
+        DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
+        /*p_type = FPOINTER ;*/ 
+      } else
+      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
+        DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
+        /* p_type = PPOINTER; */
+      } else
+      if (SPEC_OCLS(etype) == idata ) {
+        DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
+        /* p_type = IPOINTER; */
+      } else {
+        DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
+        /* p_type = POINTER ; */
+      }
     }
 
     /* now that we have the pointer type we assign
     the pointer values */
     switch (p_type) {
-
-    case POINTER:      
-    case IPOINTER:
+      case POINTER:    
+      case IPOINTER:
        genNearPointerGet (left,result,ic);
        break;
 
-    case PPOINTER:
+      case PPOINTER:
        genPagedPointerGet(left,result,ic);
        break;
 
-    case FPOINTER:
+      case FPOINTER:
        genFarPointerGet (left,result,ic);
        break;
 
-    case CPOINTER:
+      case CPOINTER:
        genConstPointerGet (left,result,ic);
        //pic16_emitcodePointerGet (left,result,ic);
        break;
 
-    case GPOINTER:
+      case GPOINTER:
 #if 0
       if (IS_PTR_CONST(type))
        genConstPointerGet (left,result,ic);
@@ -11584,7 +11713,6 @@ static void genPointerGet (iCode *ic)
              "genPointerGet: illegal pointer type");
     
     }
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -11908,7 +12036,7 @@ static void genNearPointerSet (operand *right,
 
        /* if the value is already in a pointer register
         * then don't need anything more */
-       if (!AOP_INPREG(AOP(result))) {
+       if (1 || !AOP_INPREG(AOP(result))) {  // AOP_INPREG(AOP(result)) is not always correct...
                /* otherwise get a free pointer register */
                DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
@@ -11952,24 +12080,24 @@ static void genNearPointerSet (operand *right,
                                pic16_emitcode("movf","indf0,w ;1");
                        } else {
 
-                               if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
-                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
-                                       if (size) {                                                                     // 
-                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
-                                       } else {                                                                        // 
-                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
-                                       }                                                                               // 
-                               } else { // no literal                                                                  // 
-                                       if(size) {                                                                      // 
-                                               pic16_emitpcode(POC_MOVFF,                                              // 
-                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
-                                                                       pic16_popCopyReg(&pic16_pc_postinc0)));         // 
-                                       } else {                                                                        // 
-                                               pic16_emitpcode(POC_MOVFF,                                              // 
-                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
-                                                                       pic16_popCopyReg(&pic16_pc_indf0)));            //
-                                       }                                                                               //
-                               }                                                                                       // patch 10
+                               if (AOP_TYPE(right) == AOP_LIT) {
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
+                                       if (size) {
+                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
+                                       }
+                               } else { // no literal
+                                       if(size) {
+                                               pic16_emitpcode(POC_MOVFF,
+                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),
+                                                                       pic16_popCopyReg(&pic16_pc_postinc0)));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVFF,
+                                                               pic16_popGet2p(pic16_popGet(AOP(right),offset),
+                                                                       pic16_popCopyReg(&pic16_pc_indf0)));
+                                       }
+                               }
                        }
                        offset++;
                }
@@ -12385,27 +12513,26 @@ static void genPointerSet (iCode *ic)
     /* now that we have the pointer type we assign
     the pointer values */
     switch (p_type) {
+      case POINTER:
+      case IPOINTER:
+        genNearPointerSet (right,result,ic);
+        break;
 
-    case POINTER:
-    case IPOINTER:
-       genNearPointerSet (right,result,ic);
-       break;
-
-    case PPOINTER:
-       genPagedPointerSet (right,result,ic);
-       break;
-
-    case FPOINTER:
-       genFarPointerSet (right,result,ic);
+      case PPOINTER:
+        genPagedPointerSet (right,result,ic);
        break;
 
-    case GPOINTER:
-       genGenPointerSet (right,result,ic);
-       break;
+      case FPOINTER:
+        genFarPointerSet (right,result,ic);
+        break;
+        
+      case GPOINTER:
+        genGenPointerSet (right,result,ic);
+        break;
 
-    default:
-      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
-             "genPointerSet: illegal pointer type");
+      default:
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+          "genPointerSet: illegal pointer type");
     }
 }
 
@@ -12500,10 +12627,6 @@ static void genAddrOf (iCode *ic)
     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
     size = AOP_SIZE(IC_RESULT(ic));
 
-
-    /* Assume that what we want the address of is in data space
-     * since there is no stack on the PIC, yet! -- VR */
-  
     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
@@ -12697,7 +12820,7 @@ static void genAssign (iCode *ic)
                                pic16_popCopyReg(&pic16_pc_tblptru)));
        }
 
-       size = min(AOP_SIZE(right), AOP_SIZE(result));
+       size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result));
        while(size--) {
                pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
                pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
@@ -12705,8 +12828,9 @@ static void genAssign (iCode *ic)
                offset++;
        }
 
-       if(AOP_SIZE(result) > AOP_SIZE(right)) {
-               size = AOP_SIZE(result) - AOP_SIZE(right);
+       size = getSize(OP_SYM_ETYPE(right));
+       if(AOP_SIZE(result) > size) {
+               size = AOP_SIZE(result) - size;
                while(size--) {
                        pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
                        offset++;
@@ -13241,7 +13365,13 @@ static void genCast (iCode *ic)
                break;
 
             case GPOINTER:
-              pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
+               if (GPTRSIZE > AOP_SIZE(right)) {
+                 // assume data pointer... THIS MIGHT BE WRONG!
+                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
+                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
+               } else {
+                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
+               }
               break;
               
            default:
@@ -13437,10 +13567,26 @@ static void genReceive (iCode *ic)
 static void
 genDummyRead (iCode * ic)
 {
-  pic16_emitcode ("; genDummyRead","");
-  pic16_emitcode ("; not implemented","");
+  operand *op;
+  int i;
 
-  ic = ic;
+  op = IC_RIGHT(ic);
+  if (op && IS_SYMOP(op)) {
+    if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
+      fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
+      return;
+    }
+    pic16_aopOp (op, ic, FALSE);
+    for (i=0; i < AOP_SIZE(op); i++) {
+      // may need to protect this from the peepholer -- this is not nice but works...
+      pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
+      pic16_mov2w (AOP(op),i);
+      pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
+    } // for i
+    pic16_freeAsmop (op, NULL, ic, TRUE);
+  } else if (op) {
+    fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
+  } // if
 }
 
 /*-----------------------------------------------------------------*/
@@ -13476,7 +13622,7 @@ void genpic16Code (iCode *lic)
 
     for (ic = lic ; ic ; ic = ic->next ) {
 
-      DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
+      DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
       if ( cln != ic->lineno ) {
         if ( options.debug ) {
           debugFile->writeCLine (ic);